//------------------------------------------------------------------------------
// File: svr_tools.cs
// This file contains the server methods for the tools
// Author: Matthew Rudge
//------------------------------------------------------------------------------

////////////////////////////////////////////////////////////////////////////////
//! Creates a tool object for dynamite (and others if needed)
//! \param %tool Tool object to create
//! \retval int Id of tool object created or zero
////////////////////////////////////////////////////////////////////////////////
function toolsCreateTool(%tool)
{
   switch(%tool) {
         // Create dynamite
      case $INV_DYNAMITE:
         %dynamite = CreateSaveObject(Dynamite, "", $OST_PLAYER);
         %dynamite.dmgStartRadius = Dynamite.dmgStartRadius;
         %dynamite.dmgStartPower = Dynamite.dmgStartPower;
         %dynamite.dmgEndRadius = Dynamite.dmgEndRadius;
         %dynamite.dmgEndPower = Dynamite.dmgEndPower;
         return %dynamite;
         
      case $INV_TOMBSTONE:
      case $INV_PLANTING:
      
      // Default is zero (no item)
      default:
         return 0;
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Returns the maximum stack for a tool (This will later be used as part of
//! an item database)
//! \param %tool Tool to retrieve max stack
//! \retval int Maximum stack count for tool. A return of zero indicates maximum
//! amount possible
////////////////////////////////////////////////////////////////////////////////
function toolsGetMaxStack(%tool)
{
   // Get stack count for tool
   switch(%tool) {
      case $INV_DYNAMITE:
         return 10;
      case $INV_HEALING:
         return 10;
      case $INV_TOMBSTONE:
         return 5;
      case $INV_PLANTING:
         return 5;
      
      // Default is zero...maximum amount possible
      default: 
         return 0;
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Transaction center for any tool that is executed
//! \param %tool Tool being executed
//! \param %target Target of tool
//! \param %selObjs Selected objects
//! \retval bool True if the tool was successfully executed
////////////////////////////////////////////////////////////////////////////////
function toolsOnExecute(%tool, %target, %selObjs)
{
   switch(%tool) {
         // Place dynamite
      case $INV_DYNAMITE:
         return toolsOnDynamiteExecute(%selObjs, %target);
         
         // Heal target for a specified amount
      case $INV_HEALING:
         return toolsOnHealExecute(%target, %selObjs);
         
      case $INV_TOMBSTONE:
         return true;
         
      case $INV_PLANTING:
         return true;
      
         // Defaulting to true in case tool is undefined and we can revert back
         // to the select state
      default:
         return true;
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Attempts to place the dynamite at the target location
//! \param %selObjs Object that is placing the dynamite
//! \param %target Dynamite location
//! \retval bool True if the dynamite is placed
////////////////////////////////////////////////////////////////////////////////
function toolsOnDynamiteExecute(%selObjs, %target)
{
   if (isObject(%selObjs) == false)
   {
      return false;
   }
   
   // check if the dynamite can be placed
   if (CanPlaceObject($ObjectToPlace) == false)
   {
      // send an error message
      %client = ClientGroup.getObject(0);
      commandToClient(%client, 'SendHudMessage', "The dynamite cannot be placed there.");
      return false;
   }

   // check if the object can path there   
   %object = %selObjs.getID(0);
   if (IsSameRegion(%object, getWord(%target, 0), getWord(%target, 1)) == true)
   {
      return true;
   }
   
   // send an error message
   %client = ClientGroup.getObject(0);
   commandToClient(%client, 'SendHudMessage', %object.name @ " cannot place dynamite there.");
   return false;
}

////////////////////////////////////////////////////////////////////////////////
//! Attempts to heal the target by a specified amount
//! \param %target Recipient of heal
//! \param %selObjs Selected objects
//! \retval bool True if the target was successfully healed
////////////////////////////////////////////////////////////////////////////////
function toolsOnHealExecute(%target, %selObjs)
{
   // Target and selection will need to be objects
   if(!isObject(%target) || !isObject(%selObjs)) {
      return false;
   }
   // Target will need to be on player's team
   if(!%target.isOnTeam($OST_PLAYER)) {
      return false;
   }
   
   // start the heal effect
   startEffect(%target, "heal");
   
   %timer = new SLTimer()
   {
      time = 3;
   };
   %timer.notifyOnFire(onStopHeal, %target);
   
   // Heal target
   %target.health += 50;
   slgSendToolUseMsgLocal($INV_HEALING, %selObjs.getID(0), true);
   
   // Notify clients of use
   for(%i = 0; %i < ClientGroup.getCount(); %i++) {
      %client = ClientGroup.getObject(%i);
      commandToClient(%client, 'OnHealUse');
   }
   
   return true;
}

function SLGameObj::onStopHeal(%this)
{
   stopEffect(%this, "heal");
}

////////////////////////////////////////////////////////////////////////////////
//! Called when a dynamite stick is to be placed down on the ground by the AI
//! \param %dynamite Id of dynamite stick object
//! \param %location Location to place dynamite stick object
//! \param %user Object that placed dynamite
////////////////////////////////////////////////////////////////////////////////
function toolsOnDynamitePlace(%dynamite, %location, %user)
{
   // Set explosion timer for dynamite
   if(!isObject(%dynamite) || !isObject(%user)) {
      return;
   }
   
   // Set position for dynamite
   %x = getWord(%location, 0);
   %y = getWord(%location, 1);
   %z = getWord(%location, 2);
   %dynamite.setPosition(%x, %y, %z);
   
   // Set explosion timer for dynamite
   %datablock = %dynamite.getDataBlock();
   %timer = new SLTimer()
   {
      time = %datablock.dmgTime;
   };
   %timer.notifyOnFire(onExplode, %dynamite);
   %dynamite.explodeTimer = %timer;
   slgSendToolUseMsgLocal($INV_DYNAMITE, %user, true, %dynamite);
   
   // Notify clients of placement
   for(%i = 0; %i < ClientGroup.getCount(); %i++) {
      %client = ClientGroup.getObject(%i);
      commandToClient(%client, 'OnDynamitePlace', %location);
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Used for exploding the dynamite stick after the explosion timer has elapsed
////////////////////////////////////////////////////////////////////////////////
function SLGameObj::onExplode(%this)
{
   // Apply damage radially
   %objs = new SLGameObjList();
   GetObjects(%this.getPosition(), %this.dmgEndRadius, %objs);
   %xPos = getWord(%this.position, 0);
   %yPos = getWord(%this.position, 1);
   for (%i = 0; %i < %objs.getSize(); %i++)
   {
      %idObj = %objs.getID(%i);
      if (isObject(%idObj) == false)
      {
         continue;
      }
      
      // Apply damage to object if damagable
      if (%idObj.canDamage())
      {
         %xDiff = getWord(%idObj.position, 0) - %xPos;
         %yDiff = getWord(%idObj.position, 1) - %yPos;
         %distanceSqrd = %xDiff * %xDiff + %yDiff * %yDiff;
         
         // inside the start area, takes full damage
         if (%distanceSqrd <= %this.dmgStartRadius * %this.dmgStartRadius)
         {
            %idObj.health -= %this.dmgStartPower;
            continue;
         }
         
         // outside of area, takes no damage
         if (%distanceSqrd > %this.dmgEndRadius * %this.dmgEndRadius)
         {
            continue;
         }
         
         // in between start and end areas, takes partial damage
         %distance = mSqrt(%distanceSqrd);
         %fraction = 1 - (%distance - %this.dmgStartRadius) /
            (%this.dmgEndRadius - %this.dmgStartRadius);
         %damage = %fraction * (%this.dmgStartPower -
            %this.dmgEndPower) + %this.dmgEndPower;
         
         %idObj.health -= %damage;
      }
   }
   %objs.delete();
   
   // Notify clients of explosion
   for(%i = 0; %i < ClientGroup.getCount(); %i++) {
      %client = ClientGroup.getObject(%i);
      commandToClient(%client, 'OnDynamiteExplode', %this.getPosition());
   }
   
   // start the dynamite explosion effect
   startEffect(%this, "dynamite");
   %this.showMesh(false);
   
   // set up the destruction timer for the object
   %timer = new SLTimer()
   {
      time = Dynamite.dmgTime;
   };
   %timer.notifyOnFire(onDynamiteDestroy, %this);
}

function SLGameObj::onDynamiteDestroy(%this)
{
   // stop the dynamite explosion effect
   stopEffect(%this, "dynamite");
   
   // Delete dynamite
   RemoveObject(%this);
   %this.DeleteObject();
}

////////////////////////////////////////////////////////////////////////////////
//! Notifies the client once the dynamite stick has a ghost id for that client
//! \param %client Client to ghost to
//! \param %dynamite Server id of dynamite stick object
////////////////////////////////////////////////////////////////////////////////
function notifyClientOnDynamiteCreate(%client, %dynamite)
{
   %ghost = %client.getGhostID(%dynamite);
   
   // Reschedule if dynamite does not have ghost id yet
   if(%ghost == -1) {
      schedule(100, 0, notifyClientOnDynamiteCreate, %client, %dynamite);
   }
   
   // Otherwise notify client
   else {
      commandToClient(%client, 'OnDynamiteSelect', %ghost);
   }
}

//-Server Command Methods-------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
//! Called by a client when they have successfully selected a dynamite stick 
//! from their inventory
//! \param %client Client that selected dynamite stick
////////////////////////////////////////////////////////////////////////////////
function serverCmdOnDynamiteSelect(%client)
{
   // Create dynamite
   %dynamite = toolsCreateTool($INV_DYNAMITE);
   
   // Notify client once object is ghosted to client
   schedule(100, 0, notifyClientOnDynamiteCreate, %client, %dynamite);
}

////////////////////////////////////////////////////////////////////////////////
//! Called by a client when they have decided to cancel placement of the 
//! dynamite
//! \param %client Client that canceled
//! \param %ghDynamite Ghost id of dynamite stick that is being canceled
////////////////////////////////////////////////////////////////////////////////
function serverCmdOnDynamiteCancel(%client, %ghDynamite)
{
   // Destroy dynamite
   %dynamite = %client.resolveObjectFromGhostIndex(%ghDynamite);
   if(isObject(%dynamite)) {
      %dynamite.delete();
   }
}

////////////////////////////////////////////////////////////////////////////////
//! Short-circuits the AI so that a dynamite stick can immediately be placed
//! \param %client Client that placed dynamite stick
//! \param %ghDynamite Ghost id of dynamite stick
//! \param %location Location to place dynamite stick
//! \param %ghUser Ghost id of dynamite placer
////////////////////////////////////////////////////////////////////////////////
function serverCmdOnDynamitePlace(%client, %ghDynamite, %location, %ghUser)
{
   %dynamite = %client.resolveObjectFromGhostIndex(%ghDynamite);
   %dynamite.delete();
   %user = %client.resolveObjectFromGhostIndex(%ghUser);
   //toolsOnDynamitePlace(%dynamite, %location, %user);
   AICmd_Dynamite(%user,getWord(%location, 0),getWord(%location, 1));
}
//------------------------------------------------------------------------------

// End svr_tools.cs