AIRAT.CPP 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include "airat.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 kRatBiteDist 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 ratIdle = { kSeqDudeIdle, NULL, 0, NULL, NULL, aiThinkTarget, NULL };
  34. AISTATE ratSearch = { kSeqRatWalk, NULL, 3600, NULL, aiMoveForward, thinkSearch, &ratIdle };
  35. AISTATE ratChase = { kSeqRatWalk, NULL, 0, NULL, aiMoveForward, thinkChase, NULL };
  36. AISTATE ratDodge = { kSeqRatWalk, NULL, 0, NULL, NULL, NULL, &ratChase };
  37. AISTATE ratRecoil = { kSeqRatWalk, NULL, 0, NULL, NULL, NULL, &ratDodge };
  38. AISTATE ratGoto = { kSeqRatWalk, NULL, 3600, NULL, aiMoveForward, thinkGoto, &ratIdle };
  39. AISTATE ratBite = { kSeqDudeIdle, BiteCallback, 120, NULL, NULL, NULL, &ratChase };
  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. actFireVector(nSprite, pSprite->z, dx, dy, dz, kVectorRatBite);
  57. }
  58. /****************************************************************************
  59. ** thinkSearch()
  60. **
  61. **
  62. ****************************************************************************/
  63. static void thinkSearch( SPRITE *pSprite, XSPRITE *pXSprite )
  64. {
  65. aiChooseDirection(pSprite, pXSprite, pXSprite->goalAng);
  66. aiThinkTarget(pSprite, pXSprite);
  67. }
  68. /****************************************************************************
  69. ** thinkGoto()
  70. **
  71. **
  72. ****************************************************************************/
  73. static void thinkGoto( SPRITE *pSprite, XSPRITE *pXSprite )
  74. {
  75. int dx, dy, dist;
  76. dassert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
  77. DUDEINFO *pDudeInfo = &dudeInfo[pSprite->type - kDudeBase];
  78. SPRITE *pTarget = &sprite[pXSprite->target];
  79. XSPRITE *pXTarget = &xsprite[pTarget->extra];
  80. dx = pXSprite->targetX - pSprite->x;
  81. dy = pXSprite->targetY - pSprite->y;
  82. int nAngle = getangle(dx, dy);
  83. dist = qdist(dx, dy);
  84. aiChooseDirection(pSprite, pXSprite, nAngle);
  85. // if reached target, change to search mode
  86. if ( dist < M2X(1.0) && qabs(pSprite->ang - nAngle) < pDudeInfo->periphery )
  87. aiNewState(pSprite, pXSprite, &ratSearch);
  88. aiThinkTarget(pSprite, pXSprite);
  89. }
  90. /****************************************************************************
  91. ** thinkChase()
  92. **
  93. **
  94. ****************************************************************************/
  95. static void thinkChase( SPRITE *pSprite, XSPRITE *pXSprite )
  96. {
  97. if ( pXSprite->target == -1)
  98. {
  99. aiNewState(pSprite, pXSprite, &ratGoto);
  100. return;
  101. }
  102. int dx, dy, dist;
  103. dassert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
  104. DUDEINFO *pDudeInfo = &dudeInfo[pSprite->type - kDudeBase];
  105. dassert(pXSprite->target >= 0 && pXSprite->target < kMaxSprites);
  106. SPRITE *pTarget = &sprite[pXSprite->target];
  107. XSPRITE *pXTarget = &xsprite[pTarget->extra];
  108. // check target
  109. dx = pTarget->x - pSprite->x;
  110. dy = pTarget->y - pSprite->y;
  111. aiChooseDirection(pSprite, pXSprite, getangle(dx, dy));
  112. if ( pXTarget->health == 0 )
  113. {
  114. // target is dead
  115. aiNewState(pSprite, pXSprite, &ratSearch);
  116. return;
  117. }
  118. if ( IsPlayerSprite( pTarget ) )
  119. {
  120. PLAYER *pPlayer = &gPlayer[ pTarget->type - kDudePlayer1 ];
  121. if ( powerupCheck( pPlayer, kItemLtdInvisibility - kItemBase ) > 0 )
  122. {
  123. aiNewState(pSprite, pXSprite, &ratSearch);
  124. return;
  125. }
  126. }
  127. dist = qdist(dx, dy);
  128. if ( dist <= pDudeInfo->seeDist )
  129. {
  130. int nAngle = getangle(dx, dy);
  131. int losAngle = ((kAngle180 + nAngle - pSprite->ang) & kAngleMask) - kAngle180;
  132. int eyeAboveZ = pDudeInfo->eyeHeight * pSprite->yrepeat << 2;
  133. // is there a line of sight to the target?
  134. if ( cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum,
  135. pSprite->x, pSprite->y, pSprite->z - eyeAboveZ, pSprite->sectnum) )
  136. {
  137. // is the target visible?
  138. if ( dist < pDudeInfo->seeDist && qabs(losAngle) <= pDudeInfo->periphery )
  139. {
  140. aiSetTarget(pXSprite, pXSprite->target);
  141. if ( dist < kRatBiteDist && qabs(losAngle) < kAngle15 )
  142. aiNewState(pSprite, pXSprite, &ratBite);
  143. return;
  144. }
  145. }
  146. }
  147. dprintf("Rat %d lost sight of target %d\n", pXSprite->reference, pXSprite->target);
  148. aiNewState(pSprite, pXSprite, &ratGoto);
  149. pXSprite->target = -1;
  150. }