AIZOMBF.CPP 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include "aizombf.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 kFatZombieMeleeDist M2X(2.0) //M2X(1.6)
  20. #define kFatZombiePukeDist1 M2X(3)
  21. #define kFatZombiePukeDist2 M2X(5)
  22. #define kFatZombieThrowDist1 M2X(10)
  23. #define kFatZombieThrowDist2 M2X(6)
  24. /****************************************************************************
  25. ** LOCAL callback prototypes
  26. ****************************************************************************/
  27. static void HackCallback( int /* type */, int nXIndex );
  28. static void PukeCallback( int /* type */, int nXIndex );
  29. static void ThrowCallback( int /* type */, int nXIndex );
  30. /****************************************************************************
  31. ** LOCAL think/move function prototypes
  32. ****************************************************************************/
  33. static void thinkSearch( SPRITE *pSprite, XSPRITE *pXSprite );
  34. static void thinkGoto( SPRITE *pSprite, XSPRITE *pXSprite );
  35. static void thinkChase( SPRITE *pSprite, XSPRITE *pXSprite );
  36. /****************************************************************************
  37. ** GLOBAL CONSTANTS
  38. ****************************************************************************/
  39. AISTATE zombieFIdle = { kSeqDudeIdle, NULL, 0, NULL, NULL, aiThinkTarget, NULL };
  40. AISTATE zombieFChase = { kSeqFatZombieWalk, NULL, 0, NULL, aiMoveForward, thinkChase, NULL };
  41. AISTATE zombieFGoto = { kSeqFatZombieWalk, NULL, 3600, NULL, aiMoveForward, thinkGoto, &zombieFIdle };
  42. AISTATE zombieFHack = { kSeqFatZombieAttack,HackCallback, 120, NULL, NULL, NULL, &zombieFChase };
  43. AISTATE zombieFPuke = { kSeqFatZombieAttack,PukeCallback, 120, NULL, NULL, NULL, &zombieFChase };
  44. AISTATE zombieFThrow = { kSeqFatZombieAttack,ThrowCallback, 120, NULL, NULL, NULL, &zombieFChase };
  45. AISTATE zombieFSearch = { kSeqFatZombieWalk, NULL, 3600, NULL, aiMoveForward, thinkSearch, &zombieFIdle };
  46. AISTATE zombieFRecoil = { kSeqDudeRecoil, NULL, 0, NULL, NULL, NULL, &zombieFChase };
  47. /****************************************************************************
  48. ** LOCAL FUNCTIONS
  49. ****************************************************************************/
  50. /****************************************************************************
  51. ** HackCallback()
  52. **
  53. **
  54. ****************************************************************************/
  55. static void HackCallback( int /* type */, int nXIndex )
  56. {
  57. XSPRITE *pXSprite = &xsprite[nXIndex];
  58. int nSprite = pXSprite->reference;
  59. SPRITE *pSprite = &sprite[nSprite];
  60. int dx = Cos(pSprite->ang) >> 16;
  61. int dy = Sin(pSprite->ang) >> 16;
  62. int dz = 0;
  63. actFireVector(nSprite, pSprite->z, dx, dy, dz, kVectorCleaver);
  64. }
  65. /****************************************************************************
  66. ** HackCallback()
  67. **
  68. **
  69. ****************************************************************************/
  70. static void PukeCallback( int /* type */, int nXIndex )
  71. {
  72. XSPRITE *pXSprite = &xsprite[nXIndex];
  73. int nSprite = pXSprite->reference;
  74. SPRITE *pSprite = &sprite[nSprite];
  75. int dx = Cos(pSprite->ang) >> 16;
  76. int dy = Sin(pSprite->ang) >> 16;
  77. int dz = 0;
  78. int nThing = actFireThing(nSprite, pSprite->z, 0, kThingTNTStick, (M2X(4.0) << 4) / kTimerRate);
  79. evPost(nThing, SS_SPRITE, 2 * kTimerRate); // 2 second burn off
  80. }
  81. /****************************************************************************
  82. ** ThrowCallback()
  83. **
  84. **
  85. ****************************************************************************/
  86. static void ThrowCallback( int /* type */, int nXIndex )
  87. {
  88. XSPRITE *pXSprite = &xsprite[nXIndex];
  89. int nSprite = pXSprite->reference;
  90. SPRITE *pSprite = &sprite[nSprite];
  91. int dx = Cos(pSprite->ang) >> 16;
  92. int dy = Sin(pSprite->ang) >> 16;
  93. int dz = 0;
  94. int nZOffset = dudeInfo[pSprite->type - kDudeBase].eyeHeight;
  95. actFireMissile( nSprite, pSprite->z - nZOffset, dx, dy, dz, kMissileButcherKnife );
  96. }
  97. /****************************************************************************
  98. ** thinkSearch()
  99. **
  100. **
  101. ****************************************************************************/
  102. static void thinkSearch( SPRITE *pSprite, XSPRITE *pXSprite )
  103. {
  104. aiChooseDirection(pSprite, pXSprite, pXSprite->goalAng);
  105. aiThinkTarget(pSprite, pXSprite);
  106. }
  107. /****************************************************************************
  108. ** thinkGoto()
  109. **
  110. **
  111. ****************************************************************************/
  112. static void thinkGoto( SPRITE *pSprite, XSPRITE *pXSprite )
  113. {
  114. int dx, dy, dist;
  115. dassert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
  116. DUDEINFO *pDudeInfo = &dudeInfo[pSprite->type - kDudeBase];
  117. SPRITE *pTarget = &sprite[pXSprite->target];
  118. XSPRITE *pXTarget = &xsprite[pTarget->extra];
  119. dx = pXSprite->targetX - pSprite->x;
  120. dy = pXSprite->targetY - pSprite->y;
  121. int nAngle = getangle(dx, dy);
  122. dist = qdist(dx, dy);
  123. aiChooseDirection(pSprite, pXSprite, nAngle);
  124. // if reached target, change to search mode
  125. if ( dist < M2X(1.0) && qabs(pSprite->ang - nAngle) < pDudeInfo->periphery )
  126. aiNewState(pSprite, pXSprite, &zombieFSearch);
  127. aiThinkTarget(pSprite, pXSprite);
  128. }
  129. /****************************************************************************
  130. ** thinkChase()
  131. **
  132. **
  133. ****************************************************************************/
  134. static void thinkChase( SPRITE *pSprite, XSPRITE *pXSprite )
  135. {
  136. if ( pXSprite->target == -1)
  137. {
  138. aiNewState(pSprite, pXSprite, &zombieFGoto);
  139. return;
  140. }
  141. int dx, dy, dist;
  142. dassert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
  143. DUDEINFO *pDudeInfo = &dudeInfo[pSprite->type - kDudeBase];
  144. dassert(pXSprite->target >= 0 && pXSprite->target < kMaxSprites);
  145. SPRITE *pTarget = &sprite[pXSprite->target];
  146. XSPRITE *pXTarget = &xsprite[pTarget->extra];
  147. // check target
  148. dx = pTarget->x - pSprite->x;
  149. dy = pTarget->y - pSprite->y;
  150. aiChooseDirection(pSprite, pXSprite, getangle(dx, dy));
  151. if ( pXTarget->health == 0 )
  152. {
  153. // target is dead
  154. aiNewState(pSprite, pXSprite, &zombieFSearch);
  155. return;
  156. }
  157. if ( IsPlayerSprite( pTarget ) )
  158. {
  159. PLAYER *pPlayer = &gPlayer[ pTarget->type - kDudePlayer1 ];
  160. if ( powerupCheck( pPlayer, kItemLtdInvisibility - kItemBase ) > 0
  161. || powerupCheck( pPlayer, kItemDeathMask - kItemBase ) > 0 )
  162. {
  163. aiNewState(pSprite, pXSprite, &zombieFSearch);
  164. return;
  165. }
  166. }
  167. dist = qdist(dx, dy);
  168. if ( dist <= pDudeInfo->seeDist )
  169. {
  170. int nAngle = getangle(dx, dy);
  171. int losAngle = ((kAngle180 + nAngle - pSprite->ang) & kAngleMask) - kAngle180;
  172. int eyeAboveZ = pDudeInfo->eyeHeight * pSprite->yrepeat << 2;
  173. // is there a line of sight to the target?
  174. if ( cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum,
  175. pSprite->x, pSprite->y, pSprite->z - eyeAboveZ, pSprite->sectnum) )
  176. {
  177. // is the target visible?
  178. if ( dist < pDudeInfo->seeDist && qabs(losAngle) <= pDudeInfo->periphery )
  179. {
  180. aiSetTarget(pXSprite, pXSprite->target);
  181. // check to see if we can attack
  182. if ( dist < kFatZombieThrowDist1 && dist > kFatZombieThrowDist2 && qabs(losAngle) < kAngle15 )
  183. aiNewState(pSprite, pXSprite, &zombieFThrow);
  184. else
  185. if ( dist < kFatZombiePukeDist1 && dist > kFatZombiePukeDist2 && qabs(losAngle) < kAngle15 )
  186. aiNewState(pSprite, pXSprite, &zombieFPuke);
  187. else
  188. if ( dist < kFatZombieMeleeDist && qabs(losAngle) < kAngle15 )
  189. aiNewState(pSprite, pXSprite, &zombieFHack);
  190. return;
  191. }
  192. }
  193. }
  194. dprintf("Fat zombie %d lost sight of target %d\n", pXSprite->reference, pXSprite->target);
  195. aiNewState(pSprite, pXSprite, &zombieFSearch);
  196. pXSprite->target = -1;
  197. }