//-----------------------------------------------------------------------------
// Torque Game Engine
// 
// Copyright (c) 2001 GarageGames.Com
// Portions Copyright (c) 2001 by Sierra Online, Inc.
//-----------------------------------------------------------------------------

//
// This is the default AIPlayer class file, when the aiAddPlayer function
// is executed, if an initalization function is provided it will
//

//-----------------------------------------------------------------------------
// Callback Handlers
//-----------------------------------------------------------------------------
function AIPlayer::onStuck() {
   echo( "I'm stuck" );
   commandToServer('MoveBotsToPlayer');
}

function AIPlayer::onUnStuck() {
   echo( "onUnStuck" );
}

function AIPlayer::onStop() {
   echo( "onStop" );
}

function AIPlayer::onMove(%this) {
   echo( "onMove" SPC %this);
}

function AIPlayer::onReachDestination(%this) {
    echo( "onReachDestination" );
    // the first time the bot reaches any destination, he is programmed to
    // follow the waypoint path, if any, and hunt the player after finishing it:
    aiPlayer::handleWaypointsAndChase(%this);
}

function AIPlayer::onTargetEnterLOS() {
   echo( "onTargetEnterLOS" );
}

function AIPlayer::onTargetExitLOS() {
   echo( "onTargetExitLOS" );
}

function AIPlayer::onAdd() {
   echo( "I've been added." );
}


//-----------------------------------------------------------------------------
// AI Helpers
//-----------------------------------------------------------------------------
function AIPlayer::handleWaypointsAndChase(%this)
{
   //%nextClient = ClientGroup.getObject(AIConnection::findClosestEntity(%this.getId()));
   %nextClient = ClientGroup.getObject(AIPlayer::getClosestHuman(%this));
   $daPlaya = %nextClient.player;
   if(!isObject($daPlaya))
   {
      return;
   }
   error("daPlaya is" SPC $daPlaya);
   %playPos = $daPlaya.getPosition();
   // if there are some waypoints to follow
   if(isObject(BotMarkers))
   {
      %num = getNumberBotMarkers();
      if(%this.countMyMoves $= "")
      {
      echo(%num @ " BotMarkers found!");
      }
      error("Player Position: " @ %playPos);
      // as long as this bot hasn't completed the waypoint path:
      if(%this.countMyMoves < BotMarkers.getCount())
      {
         %dest = BotMarkers.getObject(%this.countMyMoves).position;
         echo("Next destination: " @ %dest);
         echo("The distance is: " @ getMarkerDistance(%this.countMyMoves, %this));
         echo("myMoves along the waypoint path:" SPC %this.countMyMoves);
         %this.setMoveDestination(%dest);
         %this.move();
         %this.countMyMoves++;
      }
      // okay, finished path, time for hunting the player...
      else
      {
         AIPlayer::shootHimIfYouSeeHim(%this, %playPos);
      }
   }
   // else: No waypoints, so chase the player!
   else
   {
      AIPlayer::shootHimIfYouSeeHim(%this, %playPos);
   }
}

function AIPlayer::shootHimIfYouSeeHim(%this, %playPos)
{
   %this.setTargetObject($daPlaya);
   %iSeeHim = aiPlayer::isObjectInView(%this, $daPlaya);
   error(%this.player SPC "isObjectInView:" SPC %iSeeHim);
   if(%iSeeHim)
   {
      error(%this.player @ ": I see him!!!");
      %this.setAimLocation($daPlaya.getWorldBoxCenter());
      // do we have a weapon?
      error(%this.player SPC "has Weapon:" SPC %this.player.hasInventory("Crossbow"));
      error(%this.player SPC "has Ammo:" SPC %this.player.hasInventory("CrossbowAmmo"));
      if ( (%this.player.hasInventory("Crossbow") && %this.player.hasInventory("CrossbowAmmo"))
            || (%this.player.hasInventory("Rifle") && %this.player.hasInventory("RifleAmmo")) )
      {
         // shoooooot
         %this.setTrigger(0,true);
      }
      else
      {
         error(%this.player SPC "has no weapon/ammo!");
      }
      %this.setMoveDestination(%playPos);
      %this.move();
   }
   // no player in sight?
   else
   {
      // juuuump
      //%this.setTrigger(2,true);
      // move randomly
      //setRandomSeed();
      //%myPos = %this.player.getPosition();
      //%x = getWord(%myPos, 0);
      //%y = getWord(%myPos, 1);
      //%z = getWord(%myPos, 2);
      //%dest = %x - getRandom(512)-256 SPC %y - getRandom(512)-256 SPC %z - getRandom(512)-256;
      //%dest = getRandom(512)-256 SPC getRandom(512)-256 SPC getRandom(512)-256;
      %this.clearAim();
      // check for next nearest player
      %nextClient = ClientGroup.getObject(AIPlayer::getClosestHuman(%this));
      $daPlaya = %nextClient.player;
      if(!isObject($daPlaya))
      {
         return;
      }
      %playPos = $daPlaya.getPosition();
      %this.setMoveDestination(%playPos);
      %this.setAimLocation($daPlaya.getWorldBoxCenter());
      %this.move();
   }
}


function aiPlayer::isObjectInView(%this, %object)
{
   %player = %this.player;
   // default sight range of AI:
   %this.sightRange = 70.0;
   if (!(isObject(%player) && isObject(%object))) return;

   %objPos = %object.getWorldBoxCenter();
   %eyePoint = %player.getWorldBoxCenter();
   %distance = VectorDist(%objPos, %eyePoint);
   
   error("DISTANCE:" SPC %distance);

   if (%distance <= %this.sightRange)
   {
      // if the object is within 1.5 meters sometimes it can
      // fall out of the field of view due to the eye height
      if (%distance > 2)
      {
      	%eyeTransform = %player.getEyeTransform();
      	%eyePoint = firstWord(%eyeTransform)
      	   SPC getWord(%eyeTransform, 1)
      	   SPC getWord(%eyeTransform, 2);
      }
      %eyeVector = VectorNormalize(%player.getEyeVector());
      //error("EYE_VECTOR:" SPC %eyeVector);
      
    //make sure we're not looking through walls...
    %mask = $TypeMasks::TerrainObjectType |
           $TypeMasks::InteriorObjectType |
           $TypeMasks::StaticShapeObjectType;
    %losResult = containerRayCast(%objPos, %eyePoint, %mask);
    %losObject = GetWord(%losResult, 0);
    if (!isObject(%losObject))
    {
         //create the vector from this client to the client
         %objVector = VectorNormalize(VectorSub(%objPos, %eyePoint));

         // dot product to determine field of view
         %dot = VectorDot(%objVector, %eyeVector);

         // within field of view
   	    return (%dot > 0.6);
    }
   }
   return false;
}
function AIPlayer::getClosestHuman(%this) {
   %botPos = %this.getLocation();
   %count = ClientGroup.getCount();
   for(%i = 0; %i < %count; %i++)
   {
      %client = ClientGroup.getObject(%i);
      %playPos = %client.player.getPosition();
      %tempDist = VectorDist(%playPos, %botPos);
      if(%i == 0) {
         %dist = %tempDist;
         %index = %i;
      }
      else {
         if(%dist > %tempDist) {
            %dist = %tempDist;
            %index = %i;
         }
      }
   }
   return %index;
}

function getNumberBotMarkers()
{
	%count = BotMarkers.getCount();
	return %count;
}
function getMarkerDistance(%markernumber, %bot)
{
	%botPosition = %bot.getLocation();
	%markerObject = BotMarkers.getObject(%markernumber);
	%dist = vectorDist( %botPosition, %markerObject.position );
	return %dist;
}


//
// Test Fxn
//
function AITest::onAdd() {
   echo( "Multi-namespace worked!" );
}

//-----------------------------------------------------------------------------
// 

