AIBURN.CPP 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include "aiburn.h"
  4. #include "actor.h"
  5. #include "db.h"
  6. #include "debug4g.h"
  7. #include "dude.h"
  8. #include "engine.h"
  9. #include "eventq.h"
  10. #include "gameutil.h"
  11. #include "globals.h"
  12. #include "misc.h"
  13. #include "multi.h"
  14. #include "player.h"
  15. #include "trig.h"
  16. /****************************************************************************
  17. ** LOCAL CONSTANTS
  18. ****************************************************************************/
  19. #define kBurnDist M2X(1.6)
  20. /****************************************************************************
  21. ** LOCAL callback prototypes
  22. ****************************************************************************/
  23. //static void ExplodeCallback( int /* type */, int nXIndex );
  24. static void BurnCallback( int /* type */, int nXIndex );
  25. /****************************************************************************
  26. ** LOCAL think/move/entry function prototypes
  27. ****************************************************************************/
  28. static void entryTorchy( SPRITE *pSprite, XSPRITE *pXSprite );
  29. static void thinkSearch( SPRITE *pSprite, XSPRITE *pXSprite );
  30. static void thinkGoto( SPRITE *pSprite, XSPRITE *pXSprite );
  31. static void thinkChase( SPRITE *pSprite, XSPRITE *pXSprite );
  32. /****************************************************************************
  33. ** GLOBAL CONSTANTS
  34. ****************************************************************************/
  35. AISTATE cultistBurnChase = { kSeqCultistWalk, NULL, 0, NULL, aiMoveForward, thinkChase, NULL };
  36. AISTATE cultistBurnGoto = { kSeqCultistWalk, NULL, 3600, NULL, aiMoveForward, thinkGoto, &cultistBurnSearch };
  37. AISTATE cultistBurnSearch = { kSeqCultistWalk, NULL, 3600, NULL, aiMoveForward, thinkSearch, &cultistBurnSearch };
  38. AISTATE cultistBurnAttack = { kSeqCultistWalk, BurnCallback, 120, NULL, NULL, NULL, &cultistBurnChase };
  39. AISTATE playerBurnChase = { kSeqCultistWalk, NULL, 0, NULL, aiMoveForward, thinkChase, NULL };
  40. AISTATE playerBurnGoto = { kSeqCultistWalk, NULL, 3600, NULL, aiMoveForward, thinkGoto, &playerBurnSearch };
  41. AISTATE playerBurnSearch = { kSeqCultistWalk, NULL, 3600, NULL, aiMoveForward, thinkSearch, &playerBurnSearch };
  42. AISTATE playerBurnAttack = { kSeqCultistWalk, BurnCallback, 120, NULL, NULL, NULL, &playerBurnChase };
  43. AISTATE zombieABurnChase = { kSeqAxeZombieWalk, NULL, 0, NULL, aiMoveForward, thinkChase, NULL };
  44. AISTATE zombieABurnGoto = { kSeqAxeZombieWalk, NULL, 3600, NULL, aiMoveForward, thinkGoto, &zombieABurnSearch };
  45. AISTATE zombieABurnSearch = { kSeqAxeZombieWalk, NULL, 3600, NULL, aiMoveForward, thinkSearch, &zombieABurnSearch };
  46. AISTATE zombieABurnAttack = { kSeqAxeZombieWalk, BurnCallback, 120, NULL, NULL, NULL, &zombieABurnChase };
  47. AISTATE zombieFBurnChase = { kSeqFatZombieWalk, NULL, 0, NULL, aiMoveForward, thinkChase, NULL };
  48. AISTATE zombieFBurnGoto = { kSeqFatZombieWalk, NULL, 3600, NULL, aiMoveForward, thinkGoto, &zombieFBurnSearch };
  49. AISTATE zombieFBurnSearch = { kSeqFatZombieWalk, NULL, 3600, NULL, aiMoveForward, thinkSearch, &zombieFBurnSearch };
  50. AISTATE zombieFBurnAttack = { kSeqFatZombieWalk, BurnCallback, 120, NULL, NULL, NULL, &zombieFBurnChase };
  51. /****************************************************************************
  52. ** LOCAL FUNCTIONS
  53. ****************************************************************************/
  54. /****************************************************************************
  55. ** entryTorchy()
  56. **
  57. **
  58. ****************************************************************************/
  59. static void entryCultist( SPRITE *pSprite, XSPRITE */*pXSprite*/ )
  60. {
  61. pSprite->type =
  62. switch( pSprite->type )
  63. {
  64. case kDudePlayerBurning:
  65. aiNewState(pSprite, pXSprite, &playerBurnSearch);
  66. break;
  67. case kDudeCultistBurning:
  68. aiNewState(pSprite, pXSprite, &cultistBurnSearch);
  69. break;
  70. case kDudeAxeZombieBurning:
  71. aiNewState(pSprite, pXSprite, &zombieABurnSearch);
  72. break;
  73. case kDudeFatZombieBurning:
  74. aiNewState(pSprite, pXSprite, &zombieFBurnSearch);
  75. break;
  76. }
  77. }
  78. /****************************************************************************
  79. ** ExplodeCallback()
  80. **
  81. ** This should be called when a burning cultist or burning player with
  82. ** dynamite randomly explodes.
  83. ****************************************************************************/
  84. //static void ExplodeCallback( int /* type */, int nXIndex )
  85. //{
  86. // XSPRITE *pXSprite = &xsprite[nXIndex];
  87. // int nSprite = pXSprite->reference;
  88. // SPRITE *pSprite = &sprite[nSprite];
  89. //
  90. // (void)pSprite;
  91. //}
  92. /****************************************************************************
  93. ** BurnCallback()
  94. **
  95. ** This should be called when a burning cultist or burning player touches
  96. ** any other dudes or explodable objects, like barrels. Basically, a close
  97. ** hitscan that further immolates whatever it hits with burn damage.
  98. ****************************************************************************/
  99. static void BurnCallback( int /* type */, int nXIndex )
  100. {
  101. XSPRITE *pXSprite = &xsprite[nXIndex];
  102. int nSprite = pXSprite->reference;
  103. SPRITE *pSprite = &sprite[nSprite];
  104. (void)pSprite;
  105. }
  106. /****************************************************************************
  107. ** CheckNearBarrel()
  108. **
  109. **
  110. ****************************************************************************/
  111. //static int CheckNearBarrel( SPRITE *pTarget )
  112. //{
  113. // for (short nSprite = headspritesect[pTarget->sectnum]; nSprite >= 0; nSprite = nextspritesect[nSprite])
  114. // {
  115. // // check for TNT sticks or explosions in the same sector as the target
  116. // if (sprite[nSprite].type == kThingTNTBarrel || sprite[nSprite].statnum == kStatExplosion)
  117. // return nSprite; // indicate new target
  118. // }
  119. // return -1;
  120. //}
  121. /****************************************************************************
  122. ** thinkSearch()
  123. **
  124. **
  125. ****************************************************************************/
  126. static void thinkSearch( SPRITE *pSprite, XSPRITE *pXSprite )
  127. {
  128. aiChooseDirection(pSprite, pXSprite, pXSprite->goalAng);
  129. aiThinkTarget(pSprite, pXSprite);
  130. }
  131. /****************************************************************************
  132. ** thinkGoto()
  133. **
  134. **
  135. ****************************************************************************/
  136. static void thinkGoto( SPRITE *pSprite, XSPRITE *pXSprite )
  137. {
  138. int dx, dy, dist;
  139. dassert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
  140. DUDEINFO *pDudeInfo = &dudeInfo[pSprite->type - kDudeBase];
  141. SPRITE *pTarget = &sprite[pXSprite->target];
  142. XSPRITE *pXTarget = &xsprite[pTarget->extra];
  143. dx = pXSprite->targetX - pSprite->x;
  144. dy = pXSprite->targetY - pSprite->y;
  145. int nAngle = getangle(dx, dy);
  146. dist = qdist(dx, dy);
  147. aiChooseDirection(pSprite, pXSprite, nAngle);
  148. // if reached target, change to search mode
  149. if ( dist < M2X(1.0) && qabs(pSprite->ang - nAngle) < pDudeInfo->periphery )
  150. {
  151. switch( pSprite->type )
  152. {
  153. case kDudePlayerBurning:
  154. aiNewState(pSprite, pXSprite, &playerBurnSearch);
  155. break;
  156. case kDudeCultistBurning:
  157. aiNewState(pSprite, pXSprite, &cultistBurnSearch);
  158. break;
  159. case kDudeAxeZombieBurning:
  160. aiNewState(pSprite, pXSprite, &zombieABurnSearch);
  161. break;
  162. case kDudeFatZombieBurning:
  163. aiNewState(pSprite, pXSprite, &zombieFBurnSearch);
  164. break;
  165. }
  166. }
  167. aiThinkTarget(pSprite, pXSprite);
  168. }
  169. /****************************************************************************
  170. ** thinkChase()
  171. **
  172. **
  173. ****************************************************************************/
  174. static void thinkChase( SPRITE *pSprite, XSPRITE *pXSprite )
  175. {
  176. if ( pXSprite->target == -1)
  177. {
  178. switch( pSprite->type )
  179. {
  180. case kDudePlayerBurning:
  181. aiNewState(pSprite, pXSprite, &playerBurnGoto);
  182. break;
  183. case kDudeCultistBurning:
  184. aiNewState(pSprite, pXSprite, &cultistBurnGoto);
  185. break;
  186. case kDudeAxeZombieBurning:
  187. aiNewState(pSprite, pXSprite, &zombieABurnGoto);
  188. break;
  189. case kDudeFatZombieBurning:
  190. aiNewState(pSprite, pXSprite, &zombieFBurnGoto);
  191. break;
  192. }
  193. return;
  194. }
  195. int dx, dy, dist;
  196. dassert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
  197. DUDEINFO *pDudeInfo = &dudeInfo[pSprite->type - kDudeBase];
  198. dassert(pXSprite->target >= 0 && pXSprite->target < kMaxSprites);
  199. SPRITE *pTarget = &sprite[pXSprite->target];
  200. XSPRITE *pXTarget = &xsprite[pTarget->extra];
  201. // check target
  202. dx = pTarget->x - pSprite->x;
  203. dy = pTarget->y - pSprite->y;
  204. aiChooseDirection(pSprite, pXSprite, getangle(dx, dy));
  205. if ( pXTarget->health == 0 )
  206. {
  207. switch( pSprite->type )
  208. {
  209. case kDudePlayerBurning:
  210. aiNewState(pSprite, pXSprite, &playerBurnSearch);
  211. break;
  212. case kDudeCultistBurning:
  213. aiNewState(pSprite, pXSprite, &cultistBurnSearch);
  214. break;
  215. case kDudeAxeZombieBurning:
  216. aiNewState(pSprite, pXSprite, &zombieABurnSearch);
  217. break;
  218. case kDudeFatZombieBurning:
  219. aiNewState(pSprite, pXSprite, &zombieFBurnSearch);
  220. break;
  221. }
  222. return;
  223. }
  224. dist = qdist(dx, dy);
  225. if ( dist <= pDudeInfo->seeDist )
  226. {
  227. int nAngle = getangle(dx, dy);
  228. int losAngle = ((kAngle180 + nAngle - pSprite->ang) & kAngleMask) - kAngle180;
  229. int eyeAboveZ = pDudeInfo->eyeHeight * pSprite->yrepeat << 2;
  230. // is there a line of sight to the target?
  231. if ( cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum,
  232. pSprite->x, pSprite->y, pSprite->z - eyeAboveZ, pSprite->sectnum) )
  233. {
  234. // is the target visible?
  235. if ( dist < pDudeInfo->seeDist && qabs(losAngle) <= pDudeInfo->periphery )
  236. {
  237. aiSetTarget(pXSprite, pXSprite->target);
  238. // check to see if we can attack
  239. if ( dist < kBurnDist && qabs(losAngle) < kAngle15 )
  240. {
  241. switch ( pSprite->type )
  242. {
  243. case kDudePlayerBurning:
  244. aiNewState(pSprite, pXSprite, &playerBurnAttack);
  245. break;
  246. case kDudeCultistBurning:
  247. aiNewState(pSprite, pXSprite, &cultistBurnAttack);
  248. break;
  249. case kDudeAxeZombieBurning:
  250. aiNewState(pSprite, pXSprite, &zombieABurnAttack);
  251. break;
  252. case kDudeFatZombieBurning:
  253. aiNewState(pSprite, pXSprite, &zombieFBurnAttack);
  254. break;
  255. }
  256. }
  257. return;
  258. }
  259. }
  260. }
  261. dprintf("Torchy %d lost sight of target %d\n", pXSprite->reference, pXSprite->target);
  262. switch ( pSprite->type )
  263. {
  264. case kDudePlayerBurning:
  265. aiNewState(pSprite, pXSprite, &playerBurnGoto);
  266. break;
  267. case kDudeCultistBurning:
  268. aiNewState(pSprite, pXSprite, &cultistBurnGoto);
  269. break;
  270. case kDudeAxeZombieBurning:
  271. aiNewState(pSprite, pXSprite, &zombieABurnGoto);
  272. break;
  273. case kDudeFatZombieBurning:
  274. aiNewState(pSprite, pXSprite, &zombieFBurnGoto);
  275. break;
  276. }
  277. pXSprite->target = -1;
  278. }