AIHOUND.CPP 6.7 KB

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