| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- //-----------------------------------------------------------------------------
- // 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::spawnAtLocation(%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::spawnAtLocation(%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)
- {
- %pathNodeCount=%this.path.getCount();
- %slowdown=0;
- %targetNode=%this.currentNode + 1;
- if (%this.path.isLooping) {
- %targetNode %= %pathNodeCount;
- } else {
- if (%targetNode >= %pathNodeCount-1) {
- %targetNode=%pathNodeCount-1;
- if (%currentNode < %targetNode)
- %slowdown=1;
- }
- }
- %this.moveToNode(%targetNode, %slowdown);
- }
- function AIPlayer::moveToNode(%this,%index,%slowdown)
- {
- // Move to the given path node index
- %this.currentNode = %index;
- %node = %this.path.getObject(%index);
- %this.setMoveDestination(%node.getTransform(),%slowdown);
- }
- //-----------------------------------------------------------------------------
- //
- //-----------------------------------------------------------------------------
- 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);
- %delay = %this.getDataBlock().shootingDelay;
- if (%delay $= "")
- %delay = 1000;
- %this.trigger = %this.schedule(%delay, 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;
- }
|