/* only works for vehicles atm */
//#define TELEPORT_DETACHABLES


#define MSEC_TO_TIME(v)    ((uint32_t)(v) * 10)
#define TIME_TO_FLOAT(v)   ((float)((double)(v) / (double)MSEC_TO_TIME(1000)))

#define ACTOR_POOL_POINTER    0x00B74490
#define ACTOR_POINTER_SELF    0x00B7CD98
#define ACTOR_SELF            -1
#define VEHICLE_POOL_POINTER  0x00B74494
#define VEHICLE_POINTER_SELF  0x00B6F980
#define VEHICLE_SELF          -1

#define ACTOR_STATE_DRIVING   50
#define ACTOR_STATE_DYING     54
#define ACTOR_STATE_DEAD      55

#define ACTOR_MSTATE_STILL    1
#define ACTOR_MSTATE_RUN      6
#define ACTOR_MSTATE_RUN_FAST 7

#define VEHICLE_FLAGS_INDESTRUCTIBLE   (4 | 8 | 16 | 128)
#define ACTOR_FLAGS_INVULNERABLE       (4 | 8 | 64 | 128)

#define VEHICLE_TYPE_CAR   0  /* + helicopters and planes */
#define VEHICLE_TYPE_BOAT  5
#define VEHICLE_TYPE_TRAIN 6
#define VEHICLE_TYPE_BIKE  9

#define CHEAT_STATE_NONE      0
#define CHEAT_STATE_ACTOR     1
#define CHEAT_STATE_VEHICLE   2

#define TELEPORT_MAX          10
#define STATIC_TELEPORT_MAX   200



struct cheat_state_actor
{
   float coords[3];
   int   air_break;
   int   air_break_slowmo;
   int   stick;
   int   autoaim;
};

struct cheat_state_vehicle
{
   float coords[3];
   int   air_break;
   int   air_break_slowmo;
   int   stick;
   int   protection;
};

struct cheat_state_teleport
{
   int   set;
   float matrix[16];
   int   interior_id;
};

struct cheat_state_generic
{
   int   hp_cheat;
   int   hp_safe_haven;
   int   force_weather;
   int   force_time;
   int   money;
   int   weapon;
   int   map;
   int   menu;
   int   spoof_weapon;        /* set to the weapon type id */
   int   vehicles_unlock;
   int   vehicles_warp_invert;
};

#define DEBUG_DATA_SIZE 320
#define DEBUG_HIST_LEN  100

struct debug_info
{
   int      data_type;  /* 0 byte, 1 word, 2 dword, 3 float */

   int      hist_pos;
   uint8_t  *ptr[DEBUG_HIST_LEN];
   int      offset[DEBUG_HIST_LEN];

   uint8_t  data[DEBUG_DATA_SIZE];
   uint8_t  data_prev[DEBUG_DATA_SIZE];
   uint32_t modify_time[DEBUG_DATA_SIZE];

   int      data_prev_clear;

   uint8_t  cursor_data[sizeof(void *)];
   char     ptr_hist_str[64];
};

struct cheat_state
{
   int   state;         /* CHEAT_STATE_* */

   struct cheat_state_actor   actor;
   struct cheat_state_vehicle vehicle;
   struct cheat_state_generic generic;

   struct cheat_state_teleport teleport[TELEPORT_MAX];

   int   debug_enabled;
   struct debug_info debug;

   int   in_chat;

   int   text_time;
   char  text[128];
};



struct pool
{
   #pragma pack(1)
   void     *start;     /* pointer to start of pool */
   void     *__end;     /* end of this structure? (not the pool) */
   int32_t  size;       /* max number of items in the pool */
   /* there's some more junk after this */
};

struct detachable
{
   #pragma pack(1)
   float    position[3];
   uint8_t  __unknown_12[4];
   float    vector[3];
   uint8_t  __unknown_28[16];
};

struct animation_aim
{
   #pragma pack(1)
   uint8_t  __unknown_0[8];
   float    *matrix;
};

struct animation
{
   #pragma pack(1)
   uint8_t              __unknown_0[44];
   struct animation_aim *animation_aim;
};

struct weapon
{
   #pragma pack(1)
   uint32_t id;
   uint32_t state;
   int32_t  ammo_clip;
   int32_t  ammo;
   uint32_t __unknown_count;
   uint32_t __goggle;  /* 0 off, 256 on */
   uint32_t __unknown;
};

struct object_base
{
   #pragma pack(1)
   UINT_PTR    *vmt;             /* 0 */
   float       coords[3];        /* 4 */
   uint32_t    __unknown_16;     /* 16 */
   float       *matrix;          /* 20 */
   uint8_t     __unknown_24[6];  /* 24 */
   uint16_t    model_id;         /* 30 */
   uint16_t    __unknown_32;     /* 32 */
   uint16_t    model_alt_id;     /* 34 */
   uint8_t     __unknown_36[8];  /* 36 */
   uint16_t    timer;            /* 44 */
   uint8_t     __unknown_46;     /* 46 */
   uint8_t     interior_id;      /* 47 */
   uint8_t     __unknown[4];     /* 48 */
};

struct actor_info
{
   #pragma pack(1)
   struct object_base base;
   uint8_t           __unknown_52[14];    /* 52 */
   uint8_t           flags;               /* 66 */
   uint8_t           __unknown_67[1];     /* 67 */
   float             speed[3];            /* 68 */
   float             spin[3];             /* 80 */
   uint8_t           __unknown_92[264];   /* 92 */
   float             step_pos[3];         /* 356 - coordinates, last foot step */
   uint8_t           __unknown_368[780];  /* 368 */
   struct animation  *animation;          /* 1148 */
   uint8_t           __unknown_1152[92];  /* 1152 */
   float             runspeed;            /* 1244 */
   uint8_t           __unknown_1248[52];  /* 1248 */
   float             x_angle;             /* 1300 - x_angle / z_angle */
   uint8_t           __unknown_1304[24];  /* 1304 */
   uint32_t          state;               /* 1328 - ACTOR_STATE_* */
   uint32_t          mstate;              /* 1332 - ACTOR_MSTATE_* */
   uint8_t           __unknown_1336[8];   /* 1336 */
   float             hitpoints;           /* 1344 */
   float             hitpoints_max;       /* 1348 - hmm, does not seem to be right.. it's set to "100.1318519" or something like that */
   float             armor;               /* 1352 */
   uint8_t           __unknown_1356[12];  /* 1356 */
   float             z_angle;             /* 1368 */
   float             z_angle2;            /* 1372 - same value as z_angle */
   uint8_t           __unknown_1376[8];   /* 1376 */
   struct vehicle_info *vehicle_contact;  /* 1384 */
   uint8_t           __unknown_1388[24];  /* 1388 */
   void              *building_contact;   /* 1412 */
   uint8_t           __unknown_1392[4];   /* 1416 */
   struct vehicle_info *vehicle;          /* 1420 */
   uint8_t           __unknown_1424[16];  /* 1424 */
   struct weapon     weapon[13];          /* 1440 */
   uint8_t           __unknown_1804[12];  /* 1804 */
   uint8_t           weapon_slot;         /* 1816 */
   uint8_t           __unknown_1817[3];   /* 1817 */
   void              *ptr;                /* 1820 */
   uint8_t           __unknown_1824[32];  /* 1824 */
   uint32_t          weapon_model;        /* 1856 */
   uint8_t           __unknown_1860[28];  /* 1860 */
   uint32_t          weapon_hit_type;     /* 1888 - last hit by this weapon */
   struct actor_info *weapon_hit_by;      /* 1892 - last hit by this object (usually an actor) */
   uint8_t           __unknown_1889[92];  /* 1896 */
};                                        /* 1988 */


struct vehicle_info
{
   #pragma pack(1)
   struct object_base base;
   uint8_t           __unknown_52[14];          /* 52 */
   uint8_t           flags;                     /* 66 - flags */
   uint8_t           __unknown_67;              /* 67 */
   float             speed[3];                  /* 68 */
   float             spin[3];                   /* 80 */
   uint8_t           __unknown_92[48];          /* 92 */
   float             mass;                      /* 140 - vehicle mass from handling.cfg */
   float             turn_mass;                 /* 144 - turn mass */
   float             grip_div;                  /* 148 - grip divider */
   float             mass_to_grip_mult;         /* 152 - mass to grip multiplier */
   float             __unknown_156;             /* 156 - 0.05 or 0.1 */
   float             grip_level_norm;           /* 160 - normalized grip level */
   float             center_of_mass[3];         /* 164 - center of mass */
   void              *__unknown_176;            /* 176 - pointer to a "entry node info" pool item */
   void              *__unknown_180;            /* 180 - pointer to a "ptr node Double" pool item */
   uint8_t           __unknown_184[4];          /* 184 */
   void              *__unknown_188;            /* 188 - pointer to a "building" pool item */
   void              *__unknown_192;            /* 192 - pointer to a "building" pool item */
   uint8_t           __unknown_196[20];         /* 196 */
   float             collision_something;       /* 216 */
   uint8_t           __unknown_220[16];         /* 220 - probably collision stuff */
   float             collision_position[3];     /* 236 - last collision coordinates */
   uint8_t           __unknown_248[68];         /* 248 */
   void              *__unknown_316;            /* 316 - pointer to this something in this structure */
   uint8_t           __unknown_320[157];        /* 320 */
   uint8_t           in_vehicle;                /* 477 */
   uint8_t           __unknown_478[586];        /* 478 */
   uint8_t           engine_state;              /* 1064 0 = stalled, 16 = ok */
   uint8_t           __unknown_1065[11];        /* 1065 */
   uint8_t           color[4];                  /* 1076 - as in carcolors.dat - body, stripe, body2, stripe2 */
   uint32_t          modding[8];                /* 1080 - modding data */
   float             wheel_size;                /* 1112 */
   uint32_t          timer_alarm;               /* 1116 - time left for car alarm to sound in ms */
   struct actor_info *driver;                   /* 1120 (pointer to a player struct) */
   struct actor_info *passenger;                /* 1124 */
   uint8_t           __unknown_1128[44];        /* 1128 */
   float             steer_angles[2];           /* 1172 - steer angles */
   float             gas_pedal;                 /* 1180 - gas pedal */
   float             break_pedal;               /* 1184 - break pedal */
   uint8_t           __unknown_1188[28];        /* 1188 */
   float             hitpoints;                 /* 1216 */
   float             armor;                     /* 1220 */
   uint8_t           __unknown_1224[48];        /* 1224 */
   uint32_t          door_status;               /* 1272 - car door status (1:Opened 2:Locked) */
   uint8_t           __unknown_1276[148];       /* 1276 */
   uint8_t           vehicle_type;              /* 1424 - VEHICLE_TYPE_* */
   uint8_t           __unknown_1425[20];        /* 1425 */
   uint8_t          car_tire_status[4];         /* 1445 - LF, LR, RF, RR, 0 = ok, 1 = flat, 2 = landing gear up */
   uint8_t           __unknown_1449[83];        /* 1449 */
   struct detachable detachable_bike1[1];       /* 1532 - bike/motorcycle part */
   uint8_t           __unknown_1576[52];        /* 1576 */
   uint8_t           bike_tire_status[2];       /* 1628 Front, Rear, 0 = ok, 1 = flat */
   uint8_t           __unknown_1630[2];         /* 1630 */
   struct detachable detachable_bike2[4];       /* 1632 - bike/motorcycle and boat parts */
   uint8_t           __unknown_1808[20];        /* 1808 */
   struct detachable detachable_car[4];         /* 1828 - car/helicopter/airplane parts */
   uint8_t           __unknown_2004[12];        /* 2004 */
   float             suspension[4];             /* 2016 - FL, RL, FR, RR suspension height */
   uint8_t           __unknown_2032[552];       /* 2032 */
};   /* 2584 */


struct checkpoint
{
   #pragma pack(1)
   uint32_t __unknown1;       /* Dunno, but I'm guessing the type of checkpoint is stored here */
   uint32_t counter;          /* Some sort of counter. */
   uint32_t color;            /* RGBA color value */
   uint32_t __unknown2;       /* 1024 most of the time */
   float    position[3];
   float    rotation[3];      /* direction from this checkpoint to the next */
   float    zero_point_two;
   float    radius;           /* radius? */
   uint32_t __unknown3;       /* always zero */
   uint32_t __unknown4;       /* always zero */
};

struct vehicle_state
{
   float matrix[16];
   float speed[3];
   float spin[3];
};


/* __time_current is set in cheat_hook(). the time is "cached".
   by doing this we save some CPU time, and we get a constant time */
#define time_get() __time_current

extern uint32_t            __time_current;

extern struct pool         *pool_actor;
extern struct pool         *pool_vehicle;

extern struct cheat_state  *cheat_state;
extern float               *cam_matrix;

void cheat_hook(HWND wnd);
