AIGARG.CPP 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include "aigarg.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 "sfx.h"
  16. #include "trig.h"
  17. /****************************************************************************
  18. ** LOCAL CONSTANTS
  19. ****************************************************************************/
  20. #define kFGargoyleMeleeDist M2X(2.0)
  21. #define kFGargoyleThrowDist1 M2X(12) // thrown bone
  22. #define kFGargoyleThrowDist2 M2X(6)
  23. #define kSGargoyleMeleeDist M2X(2.0)
  24. #define kSGargoyleBlastDist1 M2X(20) // thrown paralyzing blast
  25. #define kSGargoyleBlastDist2 M2X(14)
  26. #define kSlopeThrow -7168
  27. /****************************************************************************
  28. ** LOCAL callback prototypes
  29. ****************************************************************************/
  30. // flesh gargoyle callbacks
  31. static void SlashFCallback( int /* type */, int nXIndex );
  32. static void ThrowFCallback( int /* type */, int nXIndex );
  33. // stone gargoyle callbacks
  34. //static void SlashSCallback( int /* type */, int nXIndex );
  35. //static void ThrowSCallback( int /* type */, int nXIndex );
  36. /****************************************************************************
  37. ** LOCAL think/move/entry function prototypes
  38. ****************************************************************************/
  39. static void thinkSearch( SPRITE *pSprite, XSPRITE *pXSprite );
  40. static void thinkGoto( SPRITE *pSprite, XSPRITE *pXSprite );
  41. static void thinkChase( SPRITE *pSprite, XSPRITE *pXSprite );
  42. static void entryFStatue( SPRITE *pSprite, XSPRITE */*pXSprite*/ );
  43. /****************************************************************************
  44. ** GLOBAL CONSTANTS
  45. ****************************************************************************/
  46. AISTATE gargoyleFIdle = { kSeqDudeIdle, NULL, 0, NULL, NULL, aiThinkTarget, NULL };
  47. AISTATE gargoyleFChase = { kSeqDudeIdle, NULL, 0, NULL, aiMoveForward, thinkChase, NULL };
  48. AISTATE gargoyleFGoto = { kSeqDudeIdle, NULL, 3600, NULL, aiMoveForward, thinkGoto, &gargoyleFIdle };
  49. AISTATE gargoyleFSlash = { kSeqGargoyleAttack, SlashFCallback, 120, NULL, NULL, NULL, &gargoyleFChase };
  50. AISTATE gargoyleFThrow = { kSeqGargoyleAttack, ThrowFCallback, 120, NULL, NULL, NULL, &gargoyleFChase };
  51. AISTATE gargoyleFRecoil = { kSeqDudeRecoil, NULL, 0, NULL, NULL, NULL, &gargoyleFChase };
  52. AISTATE gargoyleFSearch = { kSeqDudeIdle, NULL, 3600, NULL, aiMoveForward, thinkSearch, &gargoyleFIdle };
  53. AISTATE gargoyleFMorph2 = { -1, NULL, 0, entryFStatue, NULL, NULL, &gargoyleFSearch };
  54. AISTATE gargoyleFMorph = { kSeqFleshStatueTurn,NULL, 0, NULL, NULL, NULL, &gargoyleFMorph2 };
  55. //AISTATE fleshGargoyleDodge = { kSeqDudeIdle, NULL, 90, NULL, aiMoveDodge, NULL, &gargoyleFChase };
  56. //AISTATE fleshGargoyleSwoop = { kSeqGargoyleFly, NULL, 0, NULL, aiMoveForward, thinkChase, NULL };
  57. /****************************************************************************
  58. ** LOCAL FUNCTIONS
  59. ****************************************************************************/
  60. /****************************************************************************
  61. ** SlashFCallback()
  62. **
  63. **
  64. ****************************************************************************/
  65. static void SlashFCallback( int /* type */, int nXIndex )
  66. {
  67. XSPRITE *pXSprite = &xsprite[nXIndex];
  68. int nSprite = pXSprite->reference;
  69. SPRITE *pSprite = &sprite[nSprite];
  70. int dx = Cos(pSprite->ang) >> 16;
  71. int dy = Sin(pSprite->ang) >> 16;
  72. int dz = 0;
  73. actFireVector(nSprite, pSprite->z, dx, dy, dz, kVectorClaw);
  74. }
  75. /****************************************************************************
  76. ** ThrowFCallback()
  77. **
  78. **
  79. ****************************************************************************/
  80. static void ThrowFCallback( int /* type */, int nXIndex )
  81. {
  82. XSPRITE *pXSprite = &xsprite[nXIndex];
  83. int nSprite = pXSprite->reference;
  84. SPRITE *pSprite = &sprite[nSprite];
  85. int nThing = actFireThing(
  86. nSprite, pSprite->z, gDudeSlope[nXIndex] + kSlopeThrow, kThingBoneClub, (M2X(14.0) << 4) / kTimerRate);
  87. }
  88. /****************************************************************************
  89. ** thinkSearch()
  90. **
  91. **
  92. ****************************************************************************/
  93. static void thinkSearch( SPRITE *pSprite, XSPRITE *pXSprite )
  94. {
  95. aiChooseDirection(pSprite, pXSprite, pXSprite->goalAng);
  96. aiThinkTarget(pSprite, pXSprite);
  97. }
  98. /****************************************************************************
  99. ** thinkGoto()
  100. **
  101. **
  102. ****************************************************************************/
  103. static void thinkGoto( SPRITE *pSprite, XSPRITE *pXSprite )
  104. {
  105. int dx, dy, dist;
  106. dassert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
  107. DUDEINFO *pDudeInfo = &dudeInfo[pSprite->type - kDudeBase];
  108. SPRITE *pTarget = &sprite[pXSprite->target];
  109. XSPRITE *pXTarget = &xsprite[pTarget->extra];
  110. dx = pXSprite->targetX - pSprite->x;
  111. dy = pXSprite->targetY - pSprite->y;
  112. int nAngle = getangle(dx, dy);
  113. dist = qdist(dx, dy);
  114. aiChooseDirection(pSprite, pXSprite, nAngle);
  115. // if reached target, change to search mode
  116. if ( dist < M2X(1.0) && qabs(pSprite->ang - nAngle) < pDudeInfo->periphery )
  117. aiNewState(pSprite, pXSprite, &gargoyleFSearch);
  118. aiThinkTarget(pSprite, pXSprite);
  119. }
  120. /****************************************************************************
  121. ** thinkChase()
  122. **
  123. **
  124. ****************************************************************************/
  125. static void thinkChase( SPRITE *pSprite, XSPRITE *pXSprite )
  126. {
  127. if ( pXSprite->target == -1)
  128. {
  129. aiNewState(pSprite, pXSprite, &gargoyleFGoto);
  130. return;
  131. }
  132. int dx, dy, dist;
  133. dassert(pSprite->type >= kDudeBase && pSprite->type < kDudeMax);
  134. DUDEINFO *pDudeInfo = &dudeInfo[pSprite->type - kDudeBase];
  135. dassert(pXSprite->target >= 0 && pXSprite->target < kMaxSprites);
  136. SPRITE *pTarget = &sprite[pXSprite->target];
  137. XSPRITE *pXTarget = &xsprite[pTarget->extra];
  138. // check target
  139. dx = pTarget->x - pSprite->x;
  140. dy = pTarget->y - pSprite->y;
  141. aiChooseDirection(pSprite, pXSprite, getangle(dx, dy));
  142. if ( pXTarget->health == 0 )
  143. {
  144. // target is dead
  145. aiNewState(pSprite, pXSprite, &gargoyleFSearch);
  146. return;
  147. }
  148. if ( IsPlayerSprite( pTarget ) )
  149. {
  150. PLAYER *pPlayer = &gPlayer[ pTarget->type - kDudePlayer1 ];
  151. if ( powerupCheck( pPlayer, kItemLtdInvisibility - kItemBase ) > 0 )
  152. {
  153. aiNewState(pSprite, pXSprite, &gargoyleFSearch);
  154. return;
  155. }
  156. }
  157. dist = qdist(dx, dy);
  158. if ( dist <= pDudeInfo->seeDist )
  159. {
  160. int nAngle = getangle(dx, dy);
  161. int losAngle = ((kAngle180 + nAngle - pSprite->ang) & kAngleMask) - kAngle180;
  162. int eyeAboveZ = pDudeInfo->eyeHeight * pSprite->yrepeat << 2;
  163. // is there a line of sight to the target?
  164. if ( cansee(pTarget->x, pTarget->y, pTarget->z, pTarget->sectnum,
  165. pSprite->x, pSprite->y, pSprite->z - eyeAboveZ, pSprite->sectnum) )
  166. {
  167. // is the target visible?
  168. if ( dist < pDudeInfo->seeDist && qabs(losAngle) <= pDudeInfo->periphery )
  169. {
  170. aiSetTarget(pXSprite, pXSprite->target);
  171. // check to see if we can attack
  172. switch ( pSprite->type )
  173. {
  174. case kDudeFleshGargoyle:
  175. if ( dist < kFGargoyleThrowDist1 && dist > kFGargoyleThrowDist2 && qabs(losAngle) < kAngle15 )
  176. aiNewState(pSprite, pXSprite, &gargoyleFThrow);
  177. else if ( dist < kFGargoyleMeleeDist && qabs(losAngle) < kAngle15 )
  178. {
  179. aiNewState(pSprite, pXSprite, &gargoyleFSlash);
  180. sfxStart3DSound(pSprite->extra, kSfxGargAttack);
  181. }
  182. break;
  183. }
  184. return;
  185. }
  186. }
  187. }
  188. dprintf("Gargoyle %d lost sight of target %d\n", pXSprite->reference, pXSprite->target);
  189. aiNewState(pSprite, pXSprite, &gargoyleFGoto);
  190. pXSprite->target = -1;
  191. }
  192. static void entryFStatue( SPRITE *pSprite, XSPRITE */*pXSprite*/ )
  193. {
  194. pSprite->type = kDudeFleshGargoyle;
  195. }