#include "defs.h"
#include "engine.h"
#include "ai.h"
#include "ai_waypt.h"
#include "math.h"
#include "maths.h"
#include "rules.h"

#include "console.h"

void ai_process_st_enemy(worm *tmpWorm)
{
   worm *enemy = NULL;
   char keyz[7] = {0, 0, 0, 0, 0, 0, 0};
   unsigned char tmp;
   double px, py, dist;
   long tl, tm, vx, vy, tvx, tvy, affect, pLoop;
   int sx, sy, angle, i;
   int bestWeap, chLeft=0, chRight=0;
   waypoint *tmpWay;

   if (tmpWorm->enemy)
   {
      traceLine(tmpWorm->coords.x, tmpWorm->coords.y + Engine.wormFireOffs, tmpWorm->enemy->coords.x, tmpWorm->enemy->coords.y + Engine.wormFireOffs, 0);
   }
   else
   {
      tmpWorm->aiState = AI_STATE_NONE;
   }
   
   if (!trace)
   if (aiNeedReload(tmpWorm))
   {
      sx = findSafePt(tmpWorm, tmpWorm->coords.x, tmpWorm->coords.y);
      if (sx != -1)
      {
         tmpWorm->enemy = NULL;
         tmpWorm->aiState = AI_STATE_RUN;
         tmpWorm->dest = &waypts[sx];
      }
   }

   if ((tmpWorm->enemy) && (tmpWorm->enemy->health > 0) && ((trace) || (!useWayPts)))
   {
      enemy = tmpWorm->enemy;

      if (tmpWorm->health <= 0)
      if ((tmpWorm->lives > 0) || (gameType != GAME_KTA))
      if (tmpWorm->next_spawn + 90 - GP_WORM_RESPAWN < gameTime)
      {
         keyz[GK_CHANGE] = 1;
      }

      vx = (weapons[tmpWorm->weaps[tmpWorm->curWeap]].initSpeed * cosinus[tmpWorm->aim])/1000;
      vy = (weapons[tmpWorm->weaps[tmpWorm->curWeap]].initSpeed * sinus[tmpWorm->aim])/1000;

      if (weapons[tmpWorm->weaps[tmpWorm->curWeap]].affectedByWorm)
      {
#ifdef OLD_AIM

         tvx = (tmpWorm->vel.x * weapons[tmpWorm->weaps[tmpWorm->curWeap]].affectedByWorm) / (weapons[tmpWorm->weaps[tmpWorm->curWeap]].physicsLoop * 1000);
         tvy = (tmpWorm->vel.y * weapons[tmpWorm->weaps[tmpWorm->curWeap]].affectedByWorm) / (weapons[tmpWorm->weaps[tmpWorm->curWeap]].physicsLoop * 1000);

#else
         tl = (vx * tmpWorm->VelX + vy * tmpWorm->VelY)/1000;
         tm = (vx*vx + vy*vy)/1000;
         if (tm == 0) tm = 1;

         tvx = (vx * tl)/tm;
         tvy = (vy * tl)/tm;
//         tvx = owner->VelX / weap->physicsLoop;
//         tvy = owner->VelY / weap->physicsLoop;
         if ((tvx * vx<0) || (tvy * vy<0))
         {
            tvx /= 2;
            tvy /= 2;
         }
#endif
         vx+=tvx;
         vy+=tvy;
      }

      pLoop = weapons[tmpWorm->weaps[tmpWorm->curWeap]].physicsLoop;
      affect = weapons[tmpWorm->weaps[tmpWorm->curWeap]].gravity;

      dist = (hypot(vx, vy) * pLoop);
      if (dist == 0) dist = 1;
      dist = hypot(enemy->pos.x - tmpWorm->pos.x, enemy->pos.y - tmpWorm->pos.y)/dist;

      px = fabs(enemy->pos.x + (enemy->vel.x * dist) - tmpWorm->pos.x);
      py = enemy->pos.y + (enemy->vel.y * dist) - tmpWorm->pos.y;
      sx = INT((enemy->pos.x + (enemy->vel.x * dist))/1000.0);
      sy = INT((enemy->pos.y + (enemy->vel.y * dist))/1000.0);

      angle = 16-(INT((atan2(py, px)*32.0)/(3.1415)));

      if (angle > tmpWorm->aim)
      {
         keyz[GK_UP] = 1;
      }
      else
      if (angle < tmpWorm->aim)
      {
         keyz[GK_DOWN] = 1;
      }

      traceLine(tmpWorm->coords.x, tmpWorm->coords.y + Engine.wormFireOffs, sx, sy + Engine.wormFireOffs, weapons[tmpWorm->weaps[tmpWorm->curWeap]].expOnGround);

      if (trace) // we can shoot at the enemy
      {
         tmpWorm->aiPath = -1;
         tmpWorm->enemyTime = gameTime + 90 + (600 * useWayPts);
      }
 
      if ((angle == tmpWorm->aim) || (tmpWorm->flashEnd > gameTime + GP_FLASH_DIM))
      if (trace)
      if (hypot(tmpWorm->pos.x - enemy->pos.x, tmpWorm->pos.y - enemy->pos.y) < weapons[tmpWorm->weaps[tmpWorm->curWeap]].botRange)
         keyz[GK_FIRE] = 1;
   
      if ((tmpWorm->coords.x - 10 > enemy->coords.x) || ((enemy->coords.x < tmpWorm->coords.x) && (tmpWorm->dir != DIR_LEFT)))
      {
         keyz[GK_LEFT] = 1;
//         keyz[GK_RIGHT] = (tmpWorm->dir == DIR_LEFT ? 1 : 0);
      }
      else
      if ((tmpWorm->coords.x + 10 < enemy->coords.x) || ((enemy->coords.x > tmpWorm->coords.x) && (tmpWorm->dir != DIR_RIGHT)))
      {
//         keyz[GK_LEFT] = (tmpWorm->dir == DIR_RIGHT ? 1 : 0);
         keyz[GK_RIGHT] = 1;
      }
      if (enemy->next_fire[enemy->curWeap] <= gameTime)
      if (enemy->ammo[enemy->curWeap] > 0)
      if (tmpWorm->flags[FL_CAN_JUMP])
      {
         keyz[GK_JUMP] = 1;
      }

      if (!tactics)
      if (!tmpWorm->flags[FL_ROPE_OUT])
      {

         if (tmpWorm->coords.y - 5 > enemy->coords.y)
         if (tmpWorm->flags[FL_CAN_JUMP])
         {
            keyz[GK_JUMP] = 1;
         }
         if ((angle >= 28) && (tmpWorm->aim >= 28))
         {
            keyz[GK_CHANGE] = (keyz[GK_JUMP] = 1);
         }
      }
      else
      {
         if ((tmpWorm->flags[FL_GOT_ENEMY]) && (tmpWorm->lineCatch != tmpWorm->enemy))
         {
            keyz[GK_JUMP] = 1;
         }
         
         if (tmpWorm->coords.y - 5 < enemy->coords.y)
         {
            keyz[GK_JUMP] = 1;
         }
         if (tmpWorm->coords.y > tmpWorm->ropecoords.y)
         if (fabs(tmpWorm->vel.y)<2000)
         {
            keyz[GK_JUMP] = 1;
         }
         if (angle <= 16)
         {
            keyz[GK_JUMP] = 1;
         }
      }

      bestWeap = getBestWeap(tmpWorm, !trace);
      chLeft = tmpWorm->curWeap - bestWeap;
      if (chLeft < 0)
         chLeft += 5;
      chRight = bestWeap - tmpWorm->curWeap;
      if (chRight < 0)
         chRight += 5;   

      if (tmpWorm->curWeap != bestWeap)
      if (tmpWorm->flags[FL_CAN_CHANGE])
      if (!keyz[GK_JUMP])
      {
         keyz[GK_CHANGE] = 1;
         keyz[GK_LEFT] = (chLeft < chRight ? 1 : 0);
         keyz[GK_RIGHT] = (chLeft > chRight ? 1 : 0);
      }
      
   }
   else if ((tmpWorm->enemy) && (useWayPts))
   {
//      if (tmpWorm->aiPath == -1)
//         findBotPath(tmpWorm, tmpWorm->enemy->x, tmpWorm->enemy->y);
   }
   if (tmpWorm->enemy)
   if ((tmpWorm->enemy->health <= 0) || (!tmpWorm->enemy->active) || (tmpWorm->enemyTime < gameTime))
   {
      tmpWorm->enemy = NULL;
      tmpWorm->aiState = AI_STATE_NONE;
   }

   if (useWayPts)
   if (tmpWorm->aiPath != -1)
   {
      tmpWay = &waypts[tmpWorm->aiPath];

      bestWeap = getBestWeap(tmpWorm, 1);
      chLeft = tmpWorm->curWeap - bestWeap;
      if (chLeft < 0)
         chLeft += 5;
      chRight = bestWeap - tmpWorm->curWeap;
      if (chRight < 0)
         chRight += 5;   

      if (tmpWorm->curWeap != bestWeap)
      if (tmpWorm->flags[FL_CAN_CHANGE])
      if (!keyz[GK_JUMP])
      {
         keyz[GK_CHANGE] = 1;
         keyz[GK_LEFT] = (chLeft < chRight ? 1 : 0);
         keyz[GK_RIGHT] = (chLeft > chRight ? 1 : 0);
      }

      px = abs(tmpWay->x - tmpWorm->coords.x);
      py = tmpWay->y - tmpWorm->coords.y;
      dist = hypot(px, py);

      if (tmpWorm->aiFlags & AI_FLAG_ROPE)
         angle = 32;
      else
         angle = 16;

      if (!keyz[GK_CHANGE])
      if (angle > tmpWorm->aim)
      {
         keyz[GK_UP] = 1;
      }
      else
      if (angle < tmpWorm->aim)
      {
         keyz[GK_DOWN] = 1;
      }

      if (!keyz[GK_CHANGE])
      if (tmpWay->x > tmpWorm->coords.x + 3)
         keyz[GK_RIGHT] = 1;
      else if (tmpWay->x < tmpWorm->coords.x - 3)
         keyz[GK_LEFT] = 1;
      else
      {
         if (tmpWorm->aiFlags & AI_FLAG_ROPE)
         if (!tmpWorm->flags[FL_ROPE_OUT])
         if (tmpWorm->coords.y > tmpWay->y)
         if (tmpWorm->aim == angle)
         {
            keyz[GK_JUMP] = 1;
            keyz[GK_CHANGE] = 1;
         }
         keyz[GK_LEFT] = (tmpWorm->vel.x > 500);
         keyz[GK_RIGHT] = (tmpWorm->vel.y < -500);
      }

      if (tmpWorm->flags[FL_ROPE_OUT])
      if (tmpWorm->flags[FL_CAN_JUMP])
      if (
          (tmpWorm->coords.y <= tmpWay->y) ||
          (tmpWorm->coords.y <= tmpWorm->ropecoords.y) ||
          (!tmpWorm->aiFlags & AI_FLAG_ROPE) ||
          (tmpWorm->flags[FL_GOT_ENEMY])
         )
      {
         keyz[GK_CHANGE] = 0;
         keyz[GK_JUMP] = 1;
      }

      if (!keyz[GK_CHANGE])
      if (tmpWorm->aiFlags & AI_FLAG_JUMP)
      if (tmpWorm->flags[FL_CAN_JUMP])
      {
         keyz[GK_JUMP] = 1;
      }
      if (dist < 10)
      {
         tmpWorm->aiPath = -1;
      }
      traceLine(tmpWorm->coords.x, tmpWorm->coords.y + Engine.wormFireOffs, tmpWay->x, tmpWay->y, 0);

      if (trace)
         tmpWorm->chaseTime = gameTime + 90;
      if (tmpWorm->chaseTime < gameTime)
         tmpWorm->aiPath = -1;
      
   }
   else
   {
      if (tmpWorm->flags[FL_ROPE_OUT])
      if (tmpWorm->flags[FL_CAN_JUMP])
      {
         keyz[GK_JUMP] = 1;
      }
   }

   tmp = 0;

   if (keyz[GK_JUMP]) tmp += KP_JUMP;
   if (keyz[GK_FIRE]) tmp += KP_FIRE;
   if (keyz[GK_CHANGE]) tmp += KP_CHANGE;
   if (keyz[GK_LEFT]) tmp += KP_LEFT;
   if (keyz[GK_RIGHT]) tmp += KP_RIGHT;
   if (keyz[GK_UP]) tmp += KP_UP;
   if (keyz[GK_DOWN]) tmp += KP_DOWN;

   bufor[tmpWorm->num] = tmp;
   worms[tmpWorm->num].sentKeys = 1;
}

