AISPID.CPP 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include "aispid.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 kSpiderBiteDist M2X(1.8)
  20. /****************************************************************************
  21. ** LOCAL callback prototypes
  22. ****************************************************************************/
  23. static void BiteCallback( int /* type */, int nXIndex );
  24. /****************************************************************************
  25. ** LOCAL think/move function prototypes
  26. ****************************************************************************/
  27. static void thinkSearch( SPRITE *pSprite, XSPRITE *pXSprite );
  28. static void thinkGoto( SPRITE *pSprite, XSPRITE *pXSprite );
  29. static void thinkChase( SPRITE *pSprite, XSPRITE *pXSprite );
  30. /****************************************************************************
  31. ** GLOBAL CONSTANTS
  32. ****************************************************************************/
  33. AISTATE spidIdle = { kSeqDudeIdle, NULL, 0, NULL, NULL, aiThinkTarget, NULL };
  34. AISTATE spidChase = { kSeqSpiderWalk, NULL, 0, NULL, aiMoveForward, thinkChase, NULL };
  35. AISTATE spidDodge = { kSeqSpiderWalk, NULL, 90, NULL, aiMoveDodge, NULL, &spidChase };
  36. AISTATE spidGoto = { kSeqSpiderWalk, NULL, 3600, NULL, aiMoveForward, thinkGoto, &spidIdle };
  37. AISTATE spidSearch = { kSeqSpiderWalk, NULL, 3600, NULL, aiMoveForward, thinkSearch, &spidIdle };
  38. AISTATE spidBite = { kSeqSpiderBite, BiteCallback, 60, NULL, NULL, NULL, &spidChase };
  39. AISTATE spidJump = { kSeqSpiderJump, BiteCallback, 60, NULL, NULL, NULL, &spidChase };
  40. /****************************************************************************
  41. ** LOCAL FUNCTIONS
  42. ****************************************************************************/
  43. /****************************************************************************
  44. ** BiteCallback()
  45. **
  46. **
  47. ****************************************************************************/
  48. static void BiteCallback( int /* type */, int nXIndex )
  49. {
  50. XSPRITE *pXSprite = &xsprite[nXIndex];
  51. int nSprite = pXSprite->reference;
  52. SPRITE *pSprite = &sprite[nSprite];
  53. int dx = Cos(pSprite->ang) >> 16;
  54. int dy = Sin(pSprite->ang) >> 16;
  55. int dz = 0;
  56. // dispersal modifiers here
  57. dx += BiRandom(2000);
  58. dy += BiRandom(2000);
  59. dz += BiRandom(2000);
  60. actFireVector(nSprite, pSprite->z, dx, dy, dz, kVectorSpiderBite);
  61. }
  62. /****************************************************************************
  63. ** thinkSearch()
  64. **
  65. **
  66. ****************************************************************************/
  67. static void thinkSearch( SPRITE *pSprite, XSPRITE *pXSprite )
  68. {
  69. aiChooseDirection(pSprite, pXSprite, pXSprite->goalAng);
  70. aiThinkTarget(pSprite, pXSprite);
  71. }
  72. /****************************************************************************
  73. ** thinkGoto()
  74. **
  75. **
  76. ****************************************************************************/
  77. static void thinkGoto( SPRITE *pSprite, XSPRITE *pXSprite )
  78. {
  79. int dx, dy, dist;
  80. dassert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
  81. DUDEINFO *pDudeInfo = &dudeInfo[pSprite->type - kDudeBase];
  82. SPRITE *pTarget = &sprite[pXSprite->target];
  83. XSPRITE *pXTarget = &xsprite[pTarget->extra];
  84. dx = pXSprite->targetX - pSprite->x;
  85. dy = pXSprite->targetY - pSprite->y;
  86. int nAngle = getangle(dx, dy);
  87. dist = qdist(dx, dy);
  88. aiChooseDirection(pSprite, pXSprite, nAngle);
  89. // if reached target, change to search mode
  90. if ( dist < M2X(1.0) && qabs(pSprite->ang - nAngle) < pDudeInfo->periphery )
  91. aiNewState(pSprite, pXSprite, &spidSearch);
  92. aiThinkTarget(pSprite, pXSprite);
  93. }
  94. /****************************************************************************
  95. ** thinkChase()
  96. **
  97. **
  98. ****************************************************************************/
  99. static void thinkChase( SPRITE *pSprite, XSPRITE *pXSprite )
  100. {
  101. if ( pXSprite->target == -1)
  102. {
  103. aiNewState(pSprite, pXSprite, &spidGoto);
  104. return;
  105. }
  106. int dx, dy, dist;
  107. dassert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
  108. DUDEINFO *pDudeInfo = &dudeInfo[pSprite->type - kDudeBase];
  109. dassert(pXSprite->target >= 0 && pXSprite->target < kMaxSprites);
  110. SPRITE *pTarget = &sprite[pXSprite->target];
  111. XSPRITE *pXTarget = &xsprite[pTarget->extra];
  112. // check target
  113. dx = pTarget->x - pSprite->x;
  114. dy = pTarget->y - pSprite->y;
  115. aiChooseDirection(pSprite, pXSprite, getangle(dx, dy));
  116. if ( pXTarget->health == 0 )
  117. {
  118. // target is dead
  119. aiNewState(pSprite, pXSprite, &spidSearch);
  120. return;
  121. }
  122. if ( IsPlayerSprite( pTarget ) )
  123. {
  124. PLAYER *pPlayer = &gPlayer[ pTarget->type - kDudePlayer1 ];
  125. if ( powerupCheck( pPlayer, kItemLtdInvisibility - kItemBase ) > 0 )
  126. {
  127. aiNewState(pSprite, pXSprite, &spidSearch);
  128. return;
  129. }
  130. }
  131. dist = qdist(dx, dy);
  132. if ( dist <= pDudeInfo->seeDist )
  133. {
  134. int nAngle = getangle(dx, dy);
  135. int losAngle = ((kAngle180 + nAngle - pSprite->ang) & kAngleMask) - kAngle180;
  136. int eyeAboveZ = pDudeInfo->eyeHeight * pSprite->yrepeat << 2;
  137. // is there a line of sight to the target?
  138. if ( cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum,
  139. pSprite->x, pSprite->y, pSprite->z - eyeAboveZ, pSprite->sectnum) )
  140. {
  141. // is the target visible?
  142. if ( dist < pDudeInfo->seeDist && qabs(losAngle) <= pDudeInfo->periphery )
  143. {
  144. aiSetTarget(pXSprite, pXSprite->target);
  145. // check to see if we can attack
  146. switch ( pSprite->type )
  147. {
  148. case kDudeBrownSpider:
  149. case kDudeRedSpider:
  150. case kDudeBlackSpider:
  151. case kDudeMotherSpider:
  152. if ( dist < kSpiderBiteDist && qabs(losAngle) < kAngle15 )
  153. aiNewState(pSprite, pXSprite, &spidBite);
  154. break;
  155. }
  156. return;
  157. }
  158. }
  159. }
  160. dprintf("Spider %d lost sight of target %d\n", pXSprite->reference, pXSprite->target);
  161. aiNewState(pSprite, pXSprite, &spidGoto);
  162. pXSprite->target = -1;
  163. }