TurretAI.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. /*
  2. ** Command & Conquer Generals(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. ////////////////////////////////////////////////////////////////////////////////
  19. // //
  20. // (c) 2001-2003 Electronic Arts Inc. //
  21. // //
  22. ////////////////////////////////////////////////////////////////////////////////
  23. // TurretAI.h
  24. // Author: Steven Johnson, April 2002
  25. // Simple turret behavior
  26. #pragma once
  27. #ifndef _TURRETAI_H_
  28. #define _TURRETAI_H_
  29. #include "Common/StateMachine.h"
  30. #include "Common/GameMemory.h"
  31. const Real DEFAULT_TURN_RATE = 0.01f;
  32. const Real DEFAULT_PITCH_RATE = 0.01f;
  33. /**
  34. * The TurretAI state IDs.
  35. * Each of these constants will be associated with an instance of a State class
  36. * in a given StateMachine.
  37. */
  38. enum TurretStateType
  39. {
  40. TURRETAI_IDLE,
  41. TURRETAI_IDLESCAN,
  42. TURRETAI_AIM, ///< aim turret at GoalObject
  43. TURRETAI_FIRE, ///< fire turret at GoalObject
  44. TURRETAI_RECENTER, ///< rotate turret back to default position
  45. TURRETAI_HOLD, ///< hold turret position for a bit before recenter
  46. NUM_TURRETAI_STATES
  47. };
  48. // FORWARD DECLARATIONS ///////////////////////////////////////////////////////////////////////////
  49. class Weapon;
  50. class TurretAI;
  51. //-----------------------------------------------------------------------------------------------------------
  52. /**
  53. * The AI state machine. This is used by AIUpdate to implement all of the
  54. * commands in the AICommandInterface.
  55. */
  56. class TurretStateMachine : public StateMachine
  57. {
  58. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( TurretStateMachine, "TurretStateMachine" );
  59. public:
  60. /**
  61. * The implementation of this constructor defines the states
  62. * used by this machine.
  63. */
  64. TurretStateMachine( TurretAI* tai, Object* owner, AsciiString name );
  65. TurretAI* getTurretAI() const { return m_turretAI; }
  66. virtual void clear();
  67. virtual StateReturnType resetToDefaultState();
  68. virtual StateReturnType setState( StateID newStateID );
  69. private:
  70. TurretAI* m_turretAI;
  71. protected:
  72. // snapshot interface
  73. virtual void crc( Xfer *xfer );
  74. virtual void xfer( Xfer *xfer );
  75. virtual void loadPostProcess();
  76. };
  77. //-----------------------------------------------------------------------------------------------------------
  78. class TurretState : public State
  79. {
  80. MEMORY_POOL_GLUE_ABC(TurretState)
  81. protected:
  82. TurretState( TurretStateMachine* machine, AsciiString name ) : State( machine, name) { }
  83. TurretAI* getTurretAI() { return ((TurretStateMachine*)getMachine())->getTurretAI(); }
  84. };
  85. EMPTY_DTOR(TurretState)
  86. //-----------------------------------------------------------------------------------------------------------
  87. class TurretAIIdleState : public TurretState
  88. {
  89. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(TurretAIIdleState, "TurretAIIdleState")
  90. public:
  91. TurretAIIdleState( TurretStateMachine* machine ) : TurretState( machine, "TurretAIIdleState"), m_nextIdleScan(0) { }
  92. virtual StateReturnType onEnter();
  93. virtual StateReturnType update();
  94. protected:
  95. // snapshot interface
  96. virtual void crc( Xfer *xfer );
  97. virtual void xfer( Xfer *xfer );
  98. virtual void loadPostProcess();
  99. private:
  100. void resetIdleScan();
  101. UnsignedInt m_nextIdleScan;
  102. };
  103. EMPTY_DTOR(TurretAIIdleState)
  104. //-----------------------------------------------------------------------------------------------------------
  105. class TurretAIIdleScanState : public TurretState
  106. {
  107. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(TurretAIIdleScanState, "TurretAIIdleScanState")
  108. public:
  109. TurretAIIdleScanState( TurretStateMachine* machine ) : TurretState( machine, "TurretAIIdleScanState"), m_desiredAngle(0) { }
  110. virtual StateReturnType onEnter();
  111. virtual void onExit( StateExitType status );
  112. virtual StateReturnType update();
  113. protected:
  114. // snapshot interface
  115. virtual void crc( Xfer *xfer );
  116. virtual void xfer( Xfer *xfer );
  117. virtual void loadPostProcess();
  118. private:
  119. Real m_desiredAngle;
  120. };
  121. EMPTY_DTOR(TurretAIIdleScanState)
  122. //-----------------------------------------------------------------------------------------------------------
  123. /**
  124. * Aim a turret at GoalObject
  125. */
  126. class TurretAIAimTurretState : public TurretState
  127. {
  128. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(TurretAIAimTurretState, "TurretAIAimTurretState")
  129. private:
  130. #ifdef INTER_TURRET_DELAY
  131. UnsignedInt m_extraDelay;
  132. #endif
  133. public:
  134. TurretAIAimTurretState( TurretStateMachine* machine ) : TurretState( machine, "TurretAIAimTurretState" )
  135. {
  136. }
  137. virtual StateReturnType onEnter();
  138. virtual void onExit( StateExitType status );
  139. virtual StateReturnType update();
  140. protected:
  141. // snapshot interface STUBBED - no member vars to save. jba.
  142. virtual void crc( Xfer *xfer ){};
  143. virtual void xfer( Xfer *xfer ){XferVersion cv = 1; XferVersion v = cv; xfer->xferVersion( &v, cv );}
  144. virtual void loadPostProcess(){};
  145. };
  146. EMPTY_DTOR(TurretAIAimTurretState)
  147. //-----------------------------------------------------------------------------------------------------------
  148. /**
  149. * Rotate a turret back to its default position
  150. */
  151. class TurretAIRecenterTurretState : public TurretState
  152. {
  153. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(TurretAIRecenterTurretState, "TurretAIRecenterTurretState")
  154. public:
  155. TurretAIRecenterTurretState( TurretStateMachine* machine ) : TurretState( machine, "TurretAIRecenterTurretState" ) { }
  156. virtual StateReturnType onEnter();
  157. virtual void onExit( StateExitType status );
  158. virtual StateReturnType update();
  159. protected:
  160. // snapshot interface STUBBED - no member vars to save. jba.
  161. virtual void crc( Xfer *xfer ){};
  162. virtual void xfer( Xfer *xfer ){XferVersion cv = 1; XferVersion v = cv; xfer->xferVersion( &v, cv );}
  163. virtual void loadPostProcess(){};
  164. };
  165. EMPTY_DTOR(TurretAIRecenterTurretState)
  166. //-----------------------------------------------------------------------------------------------------------
  167. /**
  168. * Hold turret position for a bit before recenter
  169. */
  170. class TurretAIHoldTurretState : public TurretState
  171. {
  172. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(TurretAIHoldTurretState, "TurretAIHoldTurretState")
  173. private:
  174. UnsignedInt m_timestamp; ///< frame this state was last entered
  175. public:
  176. TurretAIHoldTurretState( TurretStateMachine* machine ) : TurretState( machine , "AIHoldTurretState")
  177. {
  178. m_timestamp = 0;
  179. }
  180. virtual StateReturnType onEnter();
  181. virtual void onExit( StateExitType status );
  182. virtual StateReturnType update();
  183. protected:
  184. // snapshot interface
  185. virtual void crc( Xfer *xfer );
  186. virtual void xfer( Xfer *xfer );
  187. virtual void loadPostProcess();
  188. };
  189. EMPTY_DTOR(TurretAIHoldTurretState)
  190. //-------------------------------------------------------------------------------------------------
  191. class TurretAIData : public MemoryPoolObject
  192. {
  193. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(TurretAIData, "TurretAIData")
  194. public:
  195. Real m_turnRate;
  196. Real m_pitchRate;
  197. Real m_naturalTurretAngle;
  198. Real m_naturalTurretPitch;
  199. Real m_turretFireAngleSweep[WEAPONSLOT_COUNT]; ///< if nonzero, sweep within +/- this angle range while firing
  200. Real m_turretSweepSpeedModifier[WEAPONSLOT_COUNT]; ///< While sweeping, change your speed by this
  201. Real m_firePitch; ///< if nonzero, I am on target at this fixed pitch, not when pointing at target
  202. Real m_minPitch; ///< dependent on allowspitch. defaults to 0 (horizontal). The lowest pitch allowed (negative to allow pointing down of a high turret)
  203. Real m_groundUnitPitch; ///< dependent on allowspitch. defaults to 0 (horizontal). The lowest pitch allowed when firing at ground units to give the weapon an arc. jba
  204. UnsignedInt m_turretWeaponSlots; ///< which WeaponSlots are controlled by this turret
  205. #ifdef INTER_TURRET_DELAY
  206. UnsignedInt m_interTurretDelay; ///< special-case for multiturret battleships
  207. #endif
  208. Real m_minIdleScanAngle; ///< max angle the turret can turn while idling
  209. Real m_maxIdleScanAngle; ///< max angle the turret can turn while idling
  210. UnsignedInt m_minIdleScanInterval; ///< min interval between idle scans
  211. UnsignedInt m_maxIdleScanInterval; ///< max interval between idle scans
  212. UnsignedInt m_recenterTime; ///< time to wait before recentering turret
  213. Bool m_initiallyDisabled; ///< manually controlled and disabled.
  214. Bool m_firesWhileTurning; ///< so the firing state does not instantly expire the turning state
  215. Bool m_isAllowsPitch; ///< This type of turret can pitch up and down as well as spin
  216. TurretAIData();
  217. static void buildFieldParse(MultiIniFieldParse& p);
  218. static void parseTurretSweep(INI* ini, void *instance, void *store, const void* userData);
  219. static void parseTurretSweepSpeed(INI* ini, void *instance, void *store, const void* userData);
  220. };
  221. EMPTY_DTOR(TurretAIData)
  222. //-----------------------------------------------------------------------------------------------------
  223. enum TurretTargetType
  224. {
  225. TARGET_NONE,
  226. TARGET_OBJECT,
  227. TARGET_POSITION
  228. };
  229. //-----------------------------------------------------------------------------------------------------
  230. /**
  231. * Turret behavior implementation.
  232. */
  233. class TurretAI : public MemoryPoolObject, public Snapshot, public NotifyWeaponFiredInterface
  234. {
  235. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( TurretAI, "TurretAI" )
  236. public:
  237. TurretAI(Object* owner, const TurretAIData* data, WhichTurretType tur);
  238. // virtual destructor prototype provided by memory pool declaration
  239. Real getTurretAngle() const { return m_angle; }
  240. Real getTurretPitch() const { return m_pitch; }
  241. Real getMinPitch() const { return m_data->m_minPitch; }
  242. Bool isAllowsPitch() const { return m_data->m_isAllowsPitch; }
  243. Real getTurnRate() const { return m_data->m_turnRate; }
  244. Real getNaturalTurretAngle() const { return m_data->m_naturalTurretAngle; }
  245. Real getPitchRate() const { return m_data->m_pitchRate; }
  246. Real getFirePitch() const { return m_data->m_firePitch; }
  247. Real getGroundUnitPitch() const { return m_data->m_groundUnitPitch; }
  248. Real getNaturalTurretPitch() const { return m_data->m_naturalTurretPitch; }
  249. Real getTurretFireAngleSweepForWeaponSlot( WeaponSlotType slot ) const;
  250. Real getTurretSweepSpeedModifierForWeaponSlot( WeaponSlotType slot ) const;
  251. Real getMinIdleScanAngle() const { return m_data->m_minIdleScanAngle; }
  252. Real getMaxIdleScanAngle() const { return m_data->m_maxIdleScanAngle; }
  253. UnsignedInt getMinIdleScanInterval() const { return m_data->m_minIdleScanInterval; }
  254. UnsignedInt getMaxIdleScanInterval() const { return m_data->m_maxIdleScanInterval; }
  255. UnsignedInt getRecenterTime() const { return m_data->m_recenterTime; }
  256. Object* getOwner() { return m_owner; }
  257. const Object* getOwner() const { return m_owner; }
  258. Bool isOwnersCurWeaponOnTurret() const;
  259. Bool isWeaponSlotOnTurret(WeaponSlotType wslot) const;
  260. Bool isAttackingObject() const { return m_target == TARGET_OBJECT; }
  261. Bool isForceAttacking() const { return m_isForceAttacking; }
  262. // this will cause the turret to continuously track the given victim.
  263. // passing null will allow the turret to revert back to "normal" position.
  264. void setTurretTargetObject(Object* o, Bool forceAttacking);
  265. void setTurretTargetPosition(const Coord3D* pos);
  266. void recenterTurret();
  267. Bool isTurretInNaturalPosition() const;
  268. void setTurretEnabled( Bool enabled );
  269. Bool isTurretEnabled() const { return m_enabled; }
  270. /**
  271. return true iff the turret is trying to aim at the victim, BUT not yet pointing in
  272. the right dir.
  273. */
  274. Bool isTryingToAimAtTarget(const Object* victim) const;
  275. UpdateSleepTime updateTurretAI(); ///< implement this module's behavior
  276. virtual void notifyFired();
  277. virtual void notifyNewVictimChosen(Object* victim);
  278. virtual const Coord3D* getOriginalVictimPos() const { return NULL; } // yes, we return NULL here
  279. virtual Bool isWeaponSlotOkToFire(WeaponSlotType wslot) const;
  280. // these are only for use by the state machines... don't call them otherwise, please
  281. Bool friend_turnTowardsAngle(Real desiredAngle, Real rateModifier, Real relThresh);
  282. Bool friend_turnTowardsPitch(Real pitch, Real rateModifier);
  283. Bool friend_getPositiveSweep() const { return m_positiveSweep; }
  284. void friend_setPositiveSweep(Bool b) { m_positiveSweep = b; }
  285. Bool friend_isSweepEnabled() const;
  286. WhichTurretType friend_getWhichTurret() const { return m_whichTurret; }
  287. #ifdef INTER_TURRET_DELAY
  288. UnsignedInt friend_getInterTurretDelay();
  289. #endif
  290. Bool friend_isAnyWeaponInRangeOf(const Object* o) const;
  291. TurretTargetType friend_getTurretTarget(Object*& obj, Coord3D& pos) const;
  292. Bool friend_getTargetWasSetByIdleMood() const { return m_targetWasSetByIdleMood; }
  293. const Team* friend_getVictimInitialTeam() const { return m_victimInitialTeam; }
  294. void friend_checkForIdleMoodTarget();
  295. UnsignedInt friend_getNextIdleMoodTargetFrame() const;
  296. void friend_notifyStateMachineChanged();
  297. protected:
  298. // snapshot interface
  299. virtual void crc( Xfer *xfer );
  300. virtual void xfer( Xfer *xfer );
  301. virtual void loadPostProcess();
  302. private:
  303. void startRotOrPitchSound(); ///< start turret rotation sound
  304. void stopRotOrPitchSound(); ///< stop turret rotation sound
  305. void removeSelfAsTargeter();
  306. #ifdef INTER_TURRET_DELAY
  307. void getOtherTurretWeaponInfo(Int& numSelf, Int& numSelfReloading, Int& numSelfReady, Int& numOther, Int& numOtherReloading, Int& numOtherReady) const;
  308. #endif
  309. const TurretAIData* m_data;
  310. const WhichTurretType m_whichTurret;
  311. Object* m_owner;
  312. TurretStateMachine* m_turretStateMachine; ///< the state machine
  313. Real m_angle; ///< angle of the turret
  314. Real m_pitch; ///< pitch angle, if this supports it
  315. AudioEventRTS m_turretRotOrPitchSound; ///< Sound of turret rotation
  316. UnsignedInt m_enableSweepUntil;
  317. Team* m_victimInitialTeam; // The team of the victim at the BEGINNING of the attack. If it changes, we may need to stop the attack.
  318. mutable TurretTargetType m_target;
  319. UnsignedInt m_continuousFireExpirationFrame;
  320. UnsignedInt m_sleepUntil;
  321. Bool m_playRotSound : 1;
  322. Bool m_playPitchSound : 1;
  323. Bool m_positiveSweep : 1;
  324. Bool m_didFire : 1;
  325. Bool m_enabled : 1;
  326. Bool m_firesWhileTurning : 1;
  327. Bool m_isForceAttacking : 1;
  328. mutable Bool m_targetWasSetByIdleMood : 1;
  329. };
  330. #endif // end _TURRETAI_H_