aiPlayer.cs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. //-----------------------------------------------------------------------------
  23. // AIPlayer callbacks
  24. // The AIPlayer class implements the following callbacks:
  25. //
  26. // PlayerData::onStop(%this,%obj)
  27. // PlayerData::onMove(%this,%obj)
  28. // PlayerData::onReachDestination(%this,%obj)
  29. // PlayerData::onMoveStuck(%this,%obj)
  30. // PlayerData::onTargetEnterLOS(%this,%obj)
  31. // PlayerData::onTargetExitLOS(%this,%obj)
  32. // PlayerData::onAdd(%this,%obj)
  33. //
  34. // Since the AIPlayer doesn't implement it's own datablock, these callbacks
  35. // all take place in the PlayerData namespace.
  36. //-----------------------------------------------------------------------------
  37. //-----------------------------------------------------------------------------
  38. // Demo Pathed AIPlayer.
  39. //-----------------------------------------------------------------------------
  40. function DemoPlayer::onReachDestination(%this,%obj)
  41. {
  42. //echo( %obj @ " onReachDestination" );
  43. // Moves to the next node on the path.
  44. // Override for all player. Normally we'd override this for only
  45. // a specific player datablock or class of players.
  46. if (%obj.path !$= "")
  47. {
  48. if (%obj.currentNode == %obj.targetNode)
  49. %this.onEndOfPath(%obj,%obj.path);
  50. else
  51. %obj.moveToNextNode();
  52. }
  53. }
  54. function DemoPlayer::onMoveStuck(%this,%obj)
  55. {
  56. //echo( %obj @ " onMoveStuck" );
  57. }
  58. function DemoPlayer::onTargetExitLOS(%this,%obj)
  59. {
  60. //echo( %obj @ " onTargetExitLOS" );
  61. }
  62. function DemoPlayer::onTargetEnterLOS(%this,%obj)
  63. {
  64. //echo( %obj @ " onTargetEnterLOS" );
  65. }
  66. function DemoPlayer::onEndOfPath(%this,%obj,%path)
  67. {
  68. %obj.nextTask();
  69. }
  70. function DemoPlayer::onEndSequence(%this,%obj,%slot)
  71. {
  72. echo("Sequence Done!");
  73. %obj.stopThread(%slot);
  74. %obj.nextTask();
  75. }
  76. //-----------------------------------------------------------------------------
  77. // AIPlayer static functions
  78. //-----------------------------------------------------------------------------
  79. function AIPlayer::spawnAtLocation(%name, %spawnPoint)
  80. {
  81. // Create the demo player object
  82. %player = new AiPlayer()
  83. {
  84. dataBlock = DemoPlayer;
  85. path = "";
  86. };
  87. MissionCleanup.add(%player);
  88. %player.setShapeName(%name);
  89. %player.setTransform(%spawnPoint);
  90. return %player;
  91. }
  92. function AIPlayer::spawnOnPath(%name, %path)
  93. {
  94. // Spawn a player and place him on the first node of the path
  95. if (!isObject(%path))
  96. return 0;
  97. %node = %path.getObject(0);
  98. %player = AIPlayer::spawnAtLocation(%name, %node.getTransform());
  99. return %player;
  100. }
  101. //-----------------------------------------------------------------------------
  102. // AIPlayer methods
  103. //-----------------------------------------------------------------------------
  104. function AIPlayer::followPath(%this,%path,%node)
  105. {
  106. // Start the player following a path
  107. if (!isObject(%path))
  108. {
  109. %this.path = "";
  110. return;
  111. }
  112. if (%node > %path.getCount() - 1)
  113. %this.targetNode = %path.getCount() - 1;
  114. else
  115. %this.targetNode = %node;
  116. if (%this.path $= %path)
  117. %this.moveToNode(%this.currentNode);
  118. else
  119. {
  120. %this.path = %path;
  121. %this.moveToNode(0);
  122. }
  123. }
  124. function AIPlayer::moveToNextNode(%this)
  125. {
  126. %pathNodeCount=%this.path.getCount();
  127. %slowdown=0;
  128. %targetNode=%this.currentNode + 1;
  129. if (%this.path.isLooping) {
  130. %targetNode %= %pathNodeCount;
  131. } else {
  132. if (%targetNode >= %pathNodeCount-1) {
  133. %targetNode=%pathNodeCount-1;
  134. if (%currentNode < %targetNode)
  135. %slowdown=1;
  136. }
  137. }
  138. %this.moveToNode(%targetNode, %slowdown);
  139. }
  140. function AIPlayer::moveToNode(%this,%index,%slowdown)
  141. {
  142. // Move to the given path node index
  143. %this.currentNode = %index;
  144. %node = %this.path.getObject(%index);
  145. %this.setMoveDestination(%node.getTransform(),%slowdown);
  146. }
  147. //-----------------------------------------------------------------------------
  148. //
  149. //-----------------------------------------------------------------------------
  150. function AIPlayer::pushTask(%this,%method)
  151. {
  152. if (%this.taskIndex $= "")
  153. {
  154. %this.taskIndex = 0;
  155. %this.taskCurrent = -1;
  156. }
  157. %this.task[%this.taskIndex] = %method;
  158. %this.taskIndex++;
  159. if (%this.taskCurrent == -1)
  160. %this.executeTask(%this.taskIndex - 1);
  161. }
  162. function AIPlayer::clearTasks(%this)
  163. {
  164. %this.taskIndex = 0;
  165. %this.taskCurrent = -1;
  166. }
  167. function AIPlayer::nextTask(%this)
  168. {
  169. if (%this.taskCurrent != -1)
  170. if (%this.taskCurrent < %this.taskIndex - 1)
  171. %this.executeTask(%this.taskCurrent++);
  172. else
  173. %this.taskCurrent = -1;
  174. }
  175. function AIPlayer::executeTask(%this,%index)
  176. {
  177. %this.taskCurrent = %index;
  178. eval(%this.getId() @"."@ %this.task[%index] @";");
  179. }
  180. //-----------------------------------------------------------------------------
  181. function AIPlayer::singleShot(%this)
  182. {
  183. // The shooting delay is used to pulse the trigger
  184. %this.setImageTrigger(0, true);
  185. %this.setImageTrigger(0, false);
  186. %delay = %this.getDataBlock().shootingDelay;
  187. if (%delay $= "")
  188. %delay = 1000;
  189. %this.trigger = %this.schedule(%delay, singleShot);
  190. }
  191. //-----------------------------------------------------------------------------
  192. function AIPlayer::wait(%this, %time)
  193. {
  194. %this.schedule(%time * 1000, "nextTask");
  195. }
  196. function AIPlayer::done(%this,%time)
  197. {
  198. %this.schedule(0, "delete");
  199. }
  200. function AIPlayer::fire(%this,%bool)
  201. {
  202. if (%bool)
  203. {
  204. cancel(%this.trigger);
  205. %this.singleShot();
  206. }
  207. else
  208. cancel(%this.trigger);
  209. %this.nextTask();
  210. }
  211. function AIPlayer::aimAt(%this,%object)
  212. {
  213. echo("Aim: "@ %object);
  214. %this.setAimObject(%object);
  215. %this.nextTask();
  216. }
  217. function AIPlayer::animate(%this,%seq)
  218. {
  219. //%this.stopThread(0);
  220. //%this.playThread(0,%seq);
  221. %this.setActionThread(%seq);
  222. }
  223. // ----------------------------------------------------------------------------
  224. // Some handy getDistance/nearestTarget functions for the AI to use
  225. // ----------------------------------------------------------------------------
  226. function AIPlayer::getTargetDistance(%this, %target)
  227. {
  228. echo("\c4AIPlayer::getTargetDistance("@ %this @", "@ %target @")");
  229. $tgt = %target;
  230. %tgtPos = %target.getPosition();
  231. %eyePoint = %this.getWorldBoxCenter();
  232. %distance = VectorDist(%tgtPos, %eyePoint);
  233. echo("Distance to target = "@ %distance);
  234. return %distance;
  235. }
  236. function AIPlayer::getNearestPlayerTarget(%this)
  237. {
  238. echo("\c4AIPlayer::getNearestPlayerTarget("@ %this @")");
  239. %index = -1;
  240. %botPos = %this.getPosition();
  241. %count = ClientGroup.getCount();
  242. for(%i = 0; %i < %count; %i++)
  243. {
  244. %client = ClientGroup.getObject(%i);
  245. if (%client.player $= "" || %client.player == 0)
  246. return -1;
  247. %playerPos = %client.player.getPosition();
  248. %tempDist = VectorDist(%playerPos, %botPos);
  249. if (%i == 0)
  250. {
  251. %dist = %tempDist;
  252. %index = %i;
  253. }
  254. else
  255. {
  256. if (%dist > %tempDist)
  257. {
  258. %dist = %tempDist;
  259. %index = %i;
  260. }
  261. }
  262. }
  263. return %index;
  264. }
  265. //-----------------------------------------------------------------------------
  266. function AIPlayer::think(%player)
  267. {
  268. // Thinking allows us to consider other things...
  269. %player.schedule(500, think);
  270. }
  271. function AIPlayer::spawn(%path)
  272. {
  273. %player = AIPlayer::spawnOnPath("Shootme", %path);
  274. if (isObject(%player))
  275. {
  276. %player.followPath(%path, -1);
  277. // slow this sucker down, I'm tired of chasing him!
  278. %player.setMoveSpeed(0.5);
  279. //%player.mountImage(xxxImage, 0);
  280. //%player.setInventory(xxxAmmo, 1000);
  281. //%player.think();
  282. return %player;
  283. }
  284. else
  285. return 0;
  286. }