WeaponSet.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /*
  2. ** Command & Conquer Generals Zero Hour(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. // WeaponSet.h
  24. #pragma once
  25. #ifndef _WeaponSet_H_
  26. #define _WeaponSet_H_
  27. #include "Lib/BaseType.h"
  28. #include "Common/GameType.h"
  29. #include "Common/KindOf.h"
  30. #include "Common/ModelState.h"
  31. #include "Common/SparseMatchFinder.h"
  32. #include "Common/Snapshot.h"
  33. #include "GameLogic/Damage.h"
  34. //-------------------------------------------------------------------------------------------------
  35. class INI;
  36. class Object;
  37. class Weapon;
  38. class WeaponTemplate;
  39. enum CommandSourceType;
  40. enum DamageType;
  41. // for WeaponSetType. Part of detangling.
  42. #include "GameLogic/WeaponSetType.h"
  43. //-------------------------------------------------------------------------------------------------
  44. // for WeaponSetFlags. Part of detangling.
  45. #include "GameLogic/WeaponSetFlags.h"
  46. #ifdef DEFINE_WEAPONSLOTTYPE_NAMES
  47. static char *TheWeaponSlotTypeNames[] =
  48. {
  49. "PRIMARY",
  50. "SECONDARY",
  51. "TERTIARY",
  52. NULL
  53. };
  54. static const LookupListRec TheWeaponSlotTypeNamesLookupList[] =
  55. {
  56. { "PRIMARY", PRIMARY_WEAPON },
  57. { "SECONDARY", SECONDARY_WEAPON },
  58. { "TERTIARY", TERTIARY_WEAPON },
  59. { NULL, 0 }// keep this last!
  60. };
  61. #endif
  62. //-------------------------------------------------------------------------------------------------
  63. #ifdef DEFINE_WEAPONCONDITIONMAP
  64. //Kris: I did not write this code, but I am adding comments to clarify it.
  65. //When I ran into this, I discovered that it was grossly out of date. It wasn't
  66. //clearly identified as a "lookup table", but hopefully now it makes sense. I've
  67. //updated it as of May 2003 when I added RIDER1-8 conditions.
  68. //Purpose: Whenever you change a weaponset, the model condition state associated with it
  69. //will be properly set exclusively.
  70. static const ModelConditionFlagType TheWeaponSetTypeToModelConditionTypeMap[WEAPONSET_COUNT] =
  71. {
  72. /*WEAPONSET_VETERAN*/ MODELCONDITION_WEAPONSET_VETERAN,
  73. /*WEAPONSET_ELITE*/ MODELCONDITION_WEAPONSET_ELITE,
  74. /*WEAPONSET_HERO*/ MODELCONDITION_WEAPONSET_HERO,
  75. /*WEAPONSET_PLAYER_UPGRADE*/ MODELCONDITION_WEAPONSET_PLAYER_UPGRADE,
  76. /*WEAPONSET_CRATEUPGRADE_ONE*/ MODELCONDITION_WEAPONSET_CRATEUPGRADE_ONE,
  77. /*WEAPONSET_CRATEUPGRADE_TWO*/ MODELCONDITION_WEAPONSET_CRATEUPGRADE_TWO,
  78. /*WEAPONSET_VEHICLE_HIJACK*/ MODELCONDITION_INVALID,
  79. /*WEAPONSET_CARBOMB*/ MODELCONDITION_INVALID,
  80. /*WEAPONSET_MINE_CLEARING_DETAIL*/ MODELCONDITION_INVALID,
  81. /*WEAPONSET_RIDER1*/ MODELCONDITION_RIDER1, //Added these for different riders, but feel free to use these for anything.
  82. /*WEAPONSET_RIDER2*/ MODELCONDITION_RIDER2,
  83. /*WEAPONSET_RIDER3*/ MODELCONDITION_RIDER3,
  84. /*WEAPONSET_RIDER4*/ MODELCONDITION_RIDER4,
  85. /*WEAPONSET_RIDER5*/ MODELCONDITION_RIDER5,
  86. /*WEAPONSET_RIDER6*/ MODELCONDITION_RIDER6,
  87. /*WEAPONSET_RIDER7*/ MODELCONDITION_RIDER7,
  88. /*WEAPONSET_RIDER8*/ MODELCONDITION_RIDER8,
  89. };
  90. #endif
  91. //-------------------------------------------------------------------------------------------------
  92. enum WeaponSetConditionType
  93. {
  94. WSF_INVALID = -1,
  95. WSF_NONE = 0,
  96. WSF_FIRING,
  97. WSF_BETWEEN,
  98. WSF_RELOADING,
  99. WSF_PREATTACK,
  100. WSF_COUNT
  101. };
  102. //-------------------------------------------------------------------------------------------------
  103. class WeaponTemplateSet
  104. {
  105. private:
  106. const ThingTemplate* m_thingTemplate; // needed for save/load
  107. WeaponSetFlags m_types;
  108. const WeaponTemplate* m_template[WEAPONSLOT_COUNT];
  109. UnsignedInt m_autoChooseMask[WEAPONSLOT_COUNT];
  110. KindOfMaskType m_preferredAgainst[WEAPONSLOT_COUNT];
  111. Bool m_isReloadTimeShared;
  112. Bool m_isWeaponLockSharedAcrossSets; ///< A weapon set so similar that it is safe to hold locks across
  113. static void parseWeapon(INI* ini, void *instance, void *store, const void* userData);
  114. static void parseAutoChoose(INI* ini, void *instance, void *store, const void* userData);
  115. static void parsePreferredAgainst(INI* ini, void *instance, void *store, const void* userData);
  116. public:
  117. inline WeaponTemplateSet()
  118. {
  119. clear();
  120. }
  121. const ThingTemplate* friend_getThingTemplate() const { return m_thingTemplate; } // only for WeaponSet::xfer
  122. const WeaponSetFlags& friend_getWeaponSetFlags() const { return m_types; } // only for WeaponSet::xfer
  123. void clear();
  124. void parseWeaponTemplateSet( INI* ini, const ThingTemplate* tt );
  125. Bool testWeaponSetFlag( WeaponSetType wst ) const;
  126. Bool isSharedReloadTime( void ) const { return m_isReloadTimeShared; }
  127. Bool isWeaponLockSharedAcrossSets() const {return m_isWeaponLockSharedAcrossSets; }
  128. Bool hasAnyWeapons() const;
  129. inline const WeaponTemplate* getNth(WeaponSlotType n) const { return m_template[n]; }
  130. inline UnsignedInt getNthCommandSourceMask(WeaponSlotType n) const { return m_autoChooseMask[n]; }
  131. inline const KindOfMaskType& getNthPreferredAgainstMask(WeaponSlotType n) const { return m_preferredAgainst[n]; }
  132. inline Int getConditionsYesCount() const { return 1; }
  133. inline const WeaponSetFlags& getNthConditionsYes(Int i) const { return m_types; }
  134. #if defined(_DEBUG) || defined(_INTERNAL)
  135. inline AsciiString getDescription() const { return AsciiString("ArmorTemplateSet"); }
  136. #endif
  137. };
  138. //-------------------------------------------------------------------------------------------------
  139. typedef std::vector<WeaponTemplateSet> WeaponTemplateSetVector;
  140. //-------------------------------------------------------------------------------------------------
  141. typedef SparseMatchFinder<WeaponTemplateSet, WeaponSetFlags> WeaponTemplateSetFinder;
  142. //-------------------------------------------------------------------------------------------------
  143. enum WeaponChoiceCriteria
  144. {
  145. PREFER_MOST_DAMAGE, ///< choose the weapon that will do the most damage
  146. PREFER_LONGEST_RANGE ///< choose the weapon with the longest range (that will do nonzero damage)
  147. };
  148. //-------------------------------------------------------------------------------------------------
  149. enum WeaponLockType
  150. {
  151. NOT_LOCKED, ///< Weapon is not locked
  152. LOCKED_TEMPORARILY, ///< Weapon is locked until clip is empty, or current "attack" state exits
  153. LOCKED_PERMANENTLY ///< Weapon is locked until explicitly unlocked or lock is changed to another weapon
  154. };
  155. //-------------------------------------------------------------------------------------------------
  156. enum CanAttackResult
  157. {
  158. //Worst scenario to best scenario -- These must be done this way now!
  159. ATTACKRESULT_NOT_POSSIBLE, //Can't possibly attack target.
  160. ATTACKRESULT_INVALID_SHOT, //Not a clear shot
  161. ATTACKRESULT_POSSIBLE_AFTER_MOVING, //I can attack, but after moving closer.
  162. ATTACKRESULT_POSSIBLE, //I can attack now.
  163. };
  164. //-------------------------------------------------------------------------------------------------
  165. class WeaponSet : public Snapshot
  166. {
  167. private:
  168. const WeaponTemplateSet* m_curWeaponTemplateSet;
  169. Weapon* m_weapons[WEAPONSLOT_COUNT];
  170. WeaponSlotType m_curWeapon;
  171. WeaponLockType m_curWeaponLockedStatus;
  172. UnsignedInt m_filledWeaponSlotMask;
  173. Int m_totalAntiMask; ///< anti mask of all current weapons
  174. DamageTypeFlags m_totalDamageTypeMask; ///< damagetype mask of all current weapons
  175. Bool m_hasPitchLimit;
  176. Bool m_hasDamageWeapon;
  177. Bool isAnyWithinTargetPitch(const Object* obj, const Object* victim) const;
  178. protected:
  179. // snapshot methods
  180. virtual void crc( Xfer *xfer );
  181. virtual void xfer( Xfer *xfer );
  182. virtual void loadPostProcess( void );
  183. public:
  184. WeaponSet();
  185. ~WeaponSet();
  186. void updateWeaponSet(const Object* obj);
  187. void reloadAllAmmo(const Object *obj, Bool now);
  188. Bool isOutOfAmmo() const;
  189. Bool hasAnyWeapon() const { return m_filledWeaponSlotMask != 0; }
  190. Bool hasAnyDamageWeapon() const { return m_hasDamageWeapon; }
  191. Bool hasWeaponToDealDamageType(DamageType typeToDeal) const { return m_totalDamageTypeMask.test(typeToDeal); }
  192. Bool hasSingleDamageType(DamageType typeToDeal) const { return (m_totalDamageTypeMask.test(typeToDeal) && (m_totalDamageTypeMask.count() == 1) ); }
  193. Bool isCurWeaponLocked() const { return m_curWeaponLockedStatus != NOT_LOCKED; }
  194. Weapon* getCurWeapon() { return m_weapons[m_curWeapon]; }
  195. const Weapon* getCurWeapon() const { return m_weapons[m_curWeapon]; }
  196. WeaponSlotType getCurWeaponSlot() const { return m_curWeapon; }
  197. Weapon* findWaypointFollowingCapableWeapon();
  198. const Weapon* findAmmoPipShowingWeapon() const;
  199. void weaponSetOnWeaponBonusChange(const Object *source);
  200. UnsignedInt getMostPercentReadyToFireAnyWeapon() const;
  201. inline UnsignedInt getNthCommandSourceMask( WeaponSlotType n ) const { return m_curWeaponTemplateSet ? m_curWeaponTemplateSet->getNthCommandSourceMask( n ) : NULL; }
  202. Bool setWeaponLock( WeaponSlotType weaponSlot, WeaponLockType lockType );
  203. void releaseWeaponLock(WeaponLockType lockType);
  204. Bool isSharedReloadTime() const;
  205. //When an AIAttackState is over, it needs to clean up any weapons that might be in leech range mode
  206. //or else those weapons will have unlimited range!
  207. void clearLeechRangeModeForAllWeapons();
  208. /**
  209. Determines if the unit has any weapon that could conceivably
  210. harm the victim. this does not take range, ammo, etc. into
  211. account, but immutable weapon properties, such as "can you
  212. target airborne victims".
  213. */
  214. CanAttackResult getAbleToAttackSpecificObject( AbleToAttackType t, const Object* obj, const Object* victim, CommandSourceType commandSource, WeaponSlotType specificSlot = (WeaponSlotType)-1 ) const;
  215. //When calling this function, all conditions must be validated to the point where we have decided that we wish to attack the object (faction checks, etc).
  216. //Now, we are determining if the attack itself is able to be performed!
  217. CanAttackResult getAbleToUseWeaponAgainstTarget( AbleToAttackType attackType, const Object *source, const Object *victim, const Coord3D *pos, CommandSourceType commandSource, WeaponSlotType specificSlot = (WeaponSlotType)-1 ) const;
  218. /**
  219. Selects the best weapon for the given target, and sets it as the current weapon.
  220. If there is no weapon that can damage the target, false is returned (and the current-weapon is unchanged).
  221. Note that this DOES take weapon attack range into account.
  222. */
  223. Bool chooseBestWeaponForTarget(const Object* obj, const Object* victim, WeaponChoiceCriteria criteria, CommandSourceType cmdSource);
  224. Weapon* getWeaponInWeaponSlot(WeaponSlotType wslot) const;
  225. static ModelConditionFlags getModelConditionForWeaponSlot(WeaponSlotType wslot, WeaponSetConditionType a);
  226. };
  227. #endif // _WeaponSet_H_