Torque3D/Templates/Full PhysX/game/scripts/server/aiPlayer.cs
2012-10-04 02:27:55 -05:00

326 lines
8.6 KiB
C#

//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// AIPlayer callbacks
// The AIPlayer class implements the following callbacks:
//
// PlayerData::onStop(%this,%obj)
// PlayerData::onMove(%this,%obj)
// PlayerData::onReachDestination(%this,%obj)
// PlayerData::onMoveStuck(%this,%obj)
// PlayerData::onTargetEnterLOS(%this,%obj)
// PlayerData::onTargetExitLOS(%this,%obj)
// PlayerData::onAdd(%this,%obj)
//
// Since the AIPlayer doesn't implement it's own datablock, these callbacks
// all take place in the PlayerData namespace.
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Demo Pathed AIPlayer.
//-----------------------------------------------------------------------------
function DemoPlayer::onReachDestination(%this,%obj)
{
//echo( %obj @ " onReachDestination" );
// Moves to the next node on the path.
// Override for all player. Normally we'd override this for only
// a specific player datablock or class of players.
if (%obj.path !$= "")
{
if (%obj.currentNode == %obj.targetNode)
%this.onEndOfPath(%obj,%obj.path);
else
%obj.moveToNextNode();
}
}
function DemoPlayer::onMoveStuck(%this,%obj)
{
//echo( %obj @ " onMoveStuck" );
}
function DemoPlayer::onTargetExitLOS(%this,%obj)
{
//echo( %obj @ " onTargetExitLOS" );
}
function DemoPlayer::onTargetEnterLOS(%this,%obj)
{
//echo( %obj @ " onTargetEnterLOS" );
}
function DemoPlayer::onEndOfPath(%this,%obj,%path)
{
%obj.nextTask();
}
function DemoPlayer::onEndSequence(%this,%obj,%slot)
{
echo("Sequence Done!");
%obj.stopThread(%slot);
%obj.nextTask();
}
//-----------------------------------------------------------------------------
// AIPlayer static functions
//-----------------------------------------------------------------------------
function AIPlayer::produce(%name,%spawnPoint)
{
// Create the demo player object
%player = new AiPlayer()
{
dataBlock = DemoPlayer;
path = "";
};
MissionCleanup.add(%player);
%player.setShapeName(%name);
%player.setTransform(%spawnPoint);
return %player;
}
function AIPlayer::spawnOnPath(%name,%path)
{
// Spawn a player and place him on the first node of the path
if (!isObject(%path))
return 0;
%node = %path.getObject(0);
%player = AIPlayer::produce(%name, %node.getTransform());
return %player;
}
//-----------------------------------------------------------------------------
// AIPlayer methods
//-----------------------------------------------------------------------------
function AIPlayer::followPath(%this,%path,%node)
{
// Start the player following a path
if (!isObject(%path))
{
%this.path = "";
return;
}
if (%node > %path.getCount() - 1)
%this.targetNode = %path.getCount() - 1;
else
%this.targetNode = %node;
if (%this.path $= %path)
%this.moveToNode(%this.currentNode);
else
{
%this.path = %path;
%this.moveToNode(0);
}
}
function AIPlayer::moveToNextNode(%this)
{
if (%this.targetNode < 0 || %this.currentNode < %this.targetNode)
{
if (%this.currentNode < %this.path.getCount() - 1)
%this.moveToNode(%this.currentNode + 1);
else
%this.moveToNode(0);
}
else
if (%this.currentNode == 0)
%this.moveToNode(%this.path.getCount() - 1);
else
%this.moveToNode(%this.currentNode - 1);
}
function AIPlayer::moveToNode(%this,%index)
{
// Move to the given path node index
%this.currentNode = %index;
%node = %this.path.getObject(%index);
%this.setMoveDestination(%node.getTransform());
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
function AIPlayer::pushTask(%this,%method)
{
if (%this.taskIndex $= "")
{
%this.taskIndex = 0;
%this.taskCurrent = -1;
}
%this.task[%this.taskIndex] = %method;
%this.taskIndex++;
if (%this.taskCurrent == -1)
%this.executeTask(%this.taskIndex - 1);
}
function AIPlayer::clearTasks(%this)
{
%this.taskIndex = 0;
%this.taskCurrent = -1;
}
function AIPlayer::nextTask(%this)
{
if (%this.taskCurrent != -1)
if (%this.taskCurrent < %this.taskIndex - 1)
%this.executeTask(%this.taskCurrent++);
else
%this.taskCurrent = -1;
}
function AIPlayer::executeTask(%this,%index)
{
%this.taskCurrent = %index;
eval(%this.getId() @"."@ %this.task[%index] @";");
}
//-----------------------------------------------------------------------------
function AIPlayer::singleShot(%this)
{
// The shooting delay is used to pulse the trigger
%this.setImageTrigger(0, true);
%this.setImageTrigger(0, false);
%this.trigger = %this.schedule(%this.shootingDelay, singleShot);
}
//-----------------------------------------------------------------------------
function AIPlayer::wait(%this, %time)
{
%this.schedule(%time * 1000, "nextTask");
}
function AIPlayer::done(%this,%time)
{
%this.schedule(0, "delete");
}
function AIPlayer::fire(%this,%bool)
{
if (%bool)
{
cancel(%this.trigger);
%this.singleShot();
}
else
cancel(%this.trigger);
%this.nextTask();
}
function AIPlayer::aimAt(%this,%object)
{
echo("Aim: "@ %object);
%this.setAimObject(%object);
%this.nextTask();
}
function AIPlayer::animate(%this,%seq)
{
//%this.stopThread(0);
//%this.playThread(0,%seq);
%this.setActionThread(%seq);
}
// ----------------------------------------------------------------------------
// Some handy getDistance/nearestTarget functions for the AI to use
// ----------------------------------------------------------------------------
function AIPlayer::getTargetDistance(%this, %target)
{
echo("\c4AIPlayer::getTargetDistance("@ %this @", "@ %target @")");
$tgt = %target;
%tgtPos = %target.getPosition();
%eyePoint = %this.getWorldBoxCenter();
%distance = VectorDist(%tgtPos, %eyePoint);
echo("Distance to target = "@ %distance);
return %distance;
}
function AIPlayer::getNearestPlayerTarget(%this)
{
echo("\c4AIPlayer::getNearestPlayerTarget("@ %this @")");
%index = -1;
%botPos = %this.getPosition();
%count = ClientGroup.getCount();
for(%i = 0; %i < %count; %i++)
{
%client = ClientGroup.getObject(%i);
if (%client.player $= "" || %client.player == 0)
return -1;
%playerPos = %client.player.getPosition();
%tempDist = VectorDist(%playerPos, %botPos);
if (%i == 0)
{
%dist = %tempDist;
%index = %i;
}
else
{
if (%dist > %tempDist)
{
%dist = %tempDist;
%index = %i;
}
}
}
return %index;
}
//-----------------------------------------------------------------------------
function AIPlayer::think(%player)
{
// Thinking allows us to consider other things...
%player.schedule(500, think);
}
function AIPlayer::spawn(%path)
{
%player = AIPlayer::spawnOnPath("Shootme", %path);
if (isObject(%player))
{
%player.followPath(%path, -1);
// slow this sucker down, I'm tired of chasing him!
%player.setMoveSpeed(0.5);
//%player.mountImage(xxxImage, 0);
//%player.setInventory(xxxAmmo, 1000);
//%player.think();
return %player;
}
else
return 0;
}