#include "main.h"


void cheat_actor_teleport(struct actor_info *info, const float pos[3], int interior_id)
{
   if(info == NULL)
      return;
   vect3_copy(pos, &info->base.matrix[4*3]);
   gta_interior_id_set(interior_id);
}


void cheat_handle_actor_autoaim(struct actor_info *info, float time_diff)
{
   static int prev_id;


   if(KEY_PRESSED(set.key_autoaim))
   {
      cheat_state->actor.autoaim ^= 1;
      prev_id = -1;
   }

   if(cheat_state->actor.autoaim)
   {
      static float adj_rx, adj_rz, prev_rx, prev_rz;
      float rx = *(float *)0x00B6F248;
      float rz = *(float *)0x00B6F258;

      int nearest_id = actor_find_nearest(ACTOR_ALIVE);
      struct actor_info *nearest;
      float vect[3], ax, az;


      if(nearest_id == -1)
      {
         cheat_state_text("No players found; auto aim disabled.");
         cheat_state->actor.autoaim = 0;
         return;
      }

      if(nearest_id == prev_id)
      {
         adj_rx += rx - prev_rx;
         adj_rz += rz - prev_rz;
      }
      prev_id = nearest_id;

      if((nearest = actor_info_get(nearest_id, ACTOR_ALIVE)) == NULL)
         return;  /* won't happen */

      /*cheat_state_text("%.3f %.3f %d %d", adj_rx, adj_rz, nearest->state, nearest->state_running);*/

      /* calculate distance vector */
      vect3_vect3_sub(&nearest->base.matrix[4*3], &info->base.matrix[4*3], vect);

      /* z angle */
      az = atan2f(vect[0], vect[1]);
      /* rotate around z axis */
      vect[1] = sinf(az) * vect[0] + cosf(az) * vect[1];
      /* x angle */
      ax = atan2f(vect[1], vect[2]);

      ax = -ax + M_PI / 2.0f + adj_rx;
      az = -az - M_PI / 2.0f + adj_rz;

      if(ax < -M_PI)
         ax = -M_PI;
      else if(ax > M_PI)
         ax = M_PI;

      /* XXX make function */
      prev_rx = *(float *)0x00B6F248 = ax;
      prev_rz = *(float *)0x00B6F258 = az;
   }
}


void cheat_handle_actor_air_break(struct actor_info *info, float time_diff)
{
   static float orig_pos[3];


   if(KEY_PRESSED(set.key_air_break_foot_mod))
   {
      vect3_copy(&info->base.matrix[4*3], orig_pos);
      cheat_state->actor.air_break = set.air_break_toggle ?
            cheat_state->actor.air_break^1
          : 0;
   }

   if(cheat_state->actor.air_break && KEY_PRESSED(set.key_air_break_mod2))
      cheat_state->actor.air_break_slowmo = set.air_break_toggle ?
            cheat_state->actor.air_break_slowmo^1
          : 0;

   if(KEY_DOWN(set.key_air_break_foot_mod) || cheat_state->actor.air_break)
   {
      /* prevent all kinds of movement */
      vect3_copy(orig_pos, &info->base.matrix[4*3]);
      vect3_mult(info->speed, 0.0f, info->speed);
      //info->state_running = 1;
   }
   else
   {
      cheat_state->actor.air_break = 0;
      cheat_state->actor.air_break_slowmo = 0;
   }

   if(KEY_DOWN(set.key_air_break_foot_mod) || cheat_state->actor.air_break)
   {
      static uint32_t time_start;
      float *matrix = info->base.matrix;
      float d[4] = { 0.0f, 0.0f, 0.0f, time_diff * set.air_break_speed };


      if(KEY_DOWN(set.key_air_break_mod2) || cheat_state->actor.air_break_slowmo)
         d[3] /= 10.0f;

      if(KEY_DOWN(set.key_air_break_forward))   d[0] += 1.0f;
      if(KEY_DOWN(set.key_air_break_backward))  d[0] -= 1.0f;
      if(KEY_DOWN(set.key_air_break_left))      d[1] += 1.0f;
      if(KEY_DOWN(set.key_air_break_right))     d[1] -= 1.0f;
      if(KEY_DOWN(set.key_air_break_up))        d[2] += 1.0f;
      if(KEY_DOWN(set.key_air_break_down))      d[2] -= 1.0f;

      if(!near_zero(set.air_break_accel_time))
      {
         if(!vect3_near_zero(d))
            time_start = (time_start == 0) ? time_get() : time_start;
         else
            time_start = 0;   /* no keys pressed */

         /* acceleration */
         if(time_start != 0)
         {
            float t = TIME_TO_FLOAT(time_get() - time_start);
            if(t < set.air_break_accel_time)
               d[3] *= t / set.air_break_accel_time;
         }
      }

      if(!vect3_near_zero(d))
      {
         float vect[4] = { -d[1], d[0], d[2], 0.0f };
         float out[4];

         /*info->z_angle += d[1] * time_diff;
         info->z_angle2 = info->z_angle;*/

         /* out = matrix * norm(d) */
         vect3_normalize(vect, vect);
         matrix_vect4_mult(matrix, vect, out);

         matrix[4*3+0] += out[0] * d[3];
         matrix[4*3+1] += out[1] * d[3];
         matrix[4*3+2] += out[2] * d[3];
      }

      vect3_copy(&matrix[4*3], orig_pos);
   }
}

