Object.h 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829
  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. // Object.h ///////////////////////////////////////////////////////////////////
  24. // Simple base object
  25. // Author: Michael S. Booth, October 2000
  26. #pragma once
  27. #ifndef _OBJECT_H_
  28. #define _OBJECT_H_
  29. #include "Lib/BaseType.h"
  30. #include "Common/Geometry.h"
  31. #include "Common/Snapshot.h"
  32. #include "Common/SpecialPowerMaskType.h"
  33. #include "Common/DisabledTypes.h"
  34. #include "Common/Thing.h"
  35. #include "Common/ObjectStatusTypes.h"
  36. #include "Common/Upgrade.h"
  37. #include "GameClient/Color.h"
  38. #include "GameLogic/Damage.h" //for kill()
  39. #include "GameLogic/WeaponBonusConditionFlags.h"
  40. #include "GameLogic/WeaponSet.h"
  41. #include "GameLogic/WeaponSetFlags.h"
  42. #include "GameLogic/Module/StealthUpdate.h"
  43. //-----------------------------------------------------------------------------
  44. // Forward References
  45. //-----------------------------------------------------------------------------
  46. class AIGroup;
  47. class AIUpdateInterface;
  48. class Anim2DTemplate;
  49. class BehaviorModule;
  50. class BehaviorModuleInterface;
  51. class BodyModuleInterface;
  52. class CollideModule;
  53. class CollideModuleInterface;
  54. class CommandButton;
  55. class ContainModuleInterface;
  56. class CountermeasuresBehaviorInterface;
  57. class CreateModuleInterface;
  58. class DamageInfo;
  59. class DamageInfoInput;
  60. class DamageModule;
  61. class DamageModuleInterface;
  62. class DestroyModuleInterface;
  63. class DockUpdateInterface;
  64. class Dict;
  65. class DieModule;
  66. class DieModuleInterface;
  67. class ExitInterface;
  68. class ExperienceTracker;
  69. class FiringTracker;
  70. class Module;
  71. class PartitionData;
  72. class PhysicsBehavior;
  73. class PhysicsUpdate;
  74. class Player;
  75. class PolygonTrigger;
  76. class ProductionUpdateInterface;
  77. class ProjectileUpdateInterface;
  78. class RadarObject;
  79. class SightingInfo;
  80. class SpawnBehaviorInterface;
  81. class SpecialAbilityUpdate;
  82. class SpecialPowerCompletionDie;
  83. class SpecialPowerModuleInterface;
  84. class SpecialPowerTemplate;
  85. class SpecialPowerUpdateInterface;
  86. class Team;
  87. class UpdateModule;
  88. class UpdateModuleInterface;
  89. class UpgradeModule;
  90. class UpgradeModuleInterface;
  91. class UpgradeTemplate;
  92. class ObjectHeldHelper;
  93. class ObjectDisabledHelper;
  94. class ObjectSMCHelper;
  95. class ObjectRepulsorHelper;
  96. class StatusDamageHelper;
  97. class SubdualDamageHelper;
  98. class TempWeaponBonusHelper;
  99. class ObjectWeaponStatusHelper;
  100. class ObjectDefectionHelper;
  101. enum CommandSourceType;
  102. enum HackerAttackMode;
  103. enum NameKeyType;
  104. enum SpecialPowerType;
  105. enum WeaponBonusConditionType;
  106. enum WeaponChoiceCriteria;
  107. enum WeaponSetConditionType;
  108. enum WeaponSetType;
  109. enum ArmorSetType;
  110. enum WeaponStatus;
  111. enum RadarPriorityType;
  112. enum CanAttackResult;
  113. // For ObjectStatusTypes
  114. #include "Common/ObjectStatusTypes.h"
  115. // For ObjectScriptStatusBit
  116. #include "GameLogic/ObjectScriptStatusBits.h"
  117. //-----------------------------------------------------------------------------
  118. // Type Defines
  119. //-----------------------------------------------------------------------------
  120. struct TTriggerInfo
  121. {
  122. const PolygonTrigger* pTrigger; ///< The trigger area that the object is inside.
  123. Byte entered; ///< True if the object entered this trigger area this frame.
  124. Byte exited; ///< True if the object entered this trigger area this frame.
  125. Byte isInside; ///< True if the object is inside this trigger area this frame.
  126. Byte padding; ///< unused.
  127. TTriggerInfo() : entered(false), exited(false), isInside(false), padding(false), pTrigger(NULL) { }
  128. };
  129. //----------------------------------------------------
  130. enum CrushSquishTestType
  131. {
  132. TEST_CRUSH_ONLY,
  133. TEST_SQUISH_ONLY,
  134. TEST_CRUSH_OR_SQUISH
  135. };
  136. // ---------------------------------------------------
  137. /**
  138. * Object definition. Objects are manipulated via TheGameLogic singleton.
  139. * @todo Create an ObjectInterface class.
  140. */
  141. class Object : public Thing, public Snapshot
  142. {
  143. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(Object, "ObjectPool" )
  144. /// destructor is non-public in order to require the use of TheGameLogic->destroyObject()
  145. MEMORY_POOL_DELETEINSTANCE_VISIBILITY(protected)
  146. public:
  147. /// Object constructor automatically attaches all objects to "TheGameLogic"
  148. Object(const ThingTemplate *thing, const ObjectStatusMaskType &objectStatusMask, Team *team);
  149. void initObject();
  150. void onDestroy(); ///< run during TheGameLogic::destroyObject
  151. Object* getNextObject() { return m_next; }
  152. const Object* getNextObject() const { return m_next; }
  153. void updateObjValuesFromMapProperties(Dict* properties); ///< Brings in properties set in the editor.
  154. // ids and binding
  155. ObjectID getID() const { return m_id; } ///< this object's unique ID
  156. void friend_bindToDrawable( Drawable *draw ); ///< set drawable association. for use ONLY by GameLogic!
  157. Drawable* getDrawable() const { return m_drawable; } ///< drawable (if any) bound to obj
  158. ObjectID getProducerID() const { return m_producerID; }
  159. void setProducer(const Object* obj);
  160. ObjectID getBuilderID() const { return m_builderID; }
  161. void setBuilder( const Object *obj );
  162. void enterGroup( AIGroup *group ); ///< become a member of the AIGroup
  163. void leaveGroup( void ); ///< leave our current AIGroup
  164. AIGroup *getGroup(void);
  165. // physical properties
  166. Bool isMobile() const; ///< returns true if object is currently able to move
  167. Bool isAbleToAttack() const; ///< returns true if object currently has some kind of attack capability
  168. void maskObject( Bool mask ); ///< mask/unmask object
  169. /**
  170. Booby traps are set off by many random actions, so those actions are responsible for calling this.
  171. Return value is if a booby trap was set off, so caller can react.
  172. Those actions are: planting any type of bomb, entering, starting to capture, dying.
  173. */
  174. Bool checkAndDetonateBoobyTrap(const Object *victim);
  175. // cannot set velocity, since this is calculated from position every frame
  176. Bool isDestroyed() const { return m_status.test( OBJECT_STATUS_DESTROYED ); } ///< Returns TRUE if object has been destroyed
  177. Bool isAirborneTarget() const { return m_status.test( OBJECT_STATUS_AIRBORNE_TARGET ); } ///< Our locomotor will control marking us as a valid target for anti air weapons or not
  178. Bool isUsingAirborneLocomotor( void ) const; ///< returns true if the current locomotor is an airborne one
  179. /// central place for us to put any additional capture logic
  180. void onCapture( Player *oldOwner, Player *newOwner );
  181. /// And game death logic. Destroy is deletion of object as code
  182. void onDie( DamageInfo *damageInfo );
  183. // health and damage
  184. void attemptDamage( DamageInfo *damageInfo ); ///< damage object as specified by the info
  185. void attemptHealing(Real amount, const Object* source); ///< heal object as specified by the info
  186. Bool attemptHealingFromSoleBenefactor ( Real amount, const Object* source, UnsignedInt duration );///< for the non-stacking healers like ambulance and propaganda
  187. ObjectID getSoleHealingBenefactor( void ) const;
  188. Real estimateDamage( DamageInfoInput& damageInfo ) const;
  189. void kill( DamageType damageType = DAMAGE_UNRESISTABLE, DeathType deathType = DEATH_NORMAL ); ///< kill the object with an optional type of damage and death.
  190. void healCompletely(); ///< Restore max health to this Object
  191. void notifySubdualDamage( Real amount );///< At this level, we just pass this on to our helper and do a special tint
  192. void doStatusDamage( ObjectStatusTypes status, Real duration );///< At this level, we just pass this on to our helper
  193. void doTempWeaponBonus( WeaponBonusConditionType status, UnsignedInt duration );///< At this level, we just pass this on to our helper
  194. void scoreTheKill( const Object *victim ); ///< I just killed this object.
  195. void onVeterancyLevelChanged( VeterancyLevel oldLevel, VeterancyLevel newLevel, Bool provideFeedback = TRUE ); ///< I just achieved this level right this moment
  196. ExperienceTracker* getExperienceTracker() {return m_experienceTracker;}
  197. const ExperienceTracker* getExperienceTracker() const {return m_experienceTracker;}
  198. VeterancyLevel getVeterancyLevel() const;
  199. inline const AsciiString& getName() const { return m_name; }
  200. inline void setName( const AsciiString& newName ) { m_name = newName; }
  201. inline Team* getTeam() { return m_team; }
  202. inline const Team *getTeam() const { return m_team; }
  203. void restoreOriginalTeam();
  204. void setTeam( Team* team ); ///< sets the unit's team AND original team
  205. void setTemporaryTeam( Team* team ); ///< sets the unit's team BUT NOT its original team
  206. Player* getControllingPlayer() const;
  207. Relationship getRelationship(const Object *that) const;
  208. Color getIndicatorColor() const;
  209. Color getNightIndicatorColor() const;
  210. Bool hasCustomIndicatorColor() const { return m_indicatorColor != 0; }
  211. void setCustomIndicatorColor(Color c);
  212. void removeCustomIndicatorColor();
  213. Bool isLocallyControlled() const;
  214. Bool isNeutralControlled() const;
  215. Bool getIsUndetectedDefector(void) const { return BitTest(m_privateStatus, UNDETECTED_DEFECTOR); }
  216. void friend_setUndetectedDefector(Bool status);
  217. inline Bool isOffMap() const { return BitTest(m_privateStatus, OFF_MAP); }
  218. inline Bool isCaptured() const { return BitTest(m_privateStatus, CAPTURED); }
  219. void setCaptured(Bool isCaptured);
  220. inline const GeometryInfo& getGeometryInfo() const { return m_geometryInfo; }
  221. void setGeometryInfo(const GeometryInfo& geom);
  222. void setGeometryInfoZ( Real newZ );
  223. void onCollide( Object *other, const Coord3D *loc, const Coord3D *normal );
  224. Real getCarrierDeckHeight() const;
  225. // access to modules
  226. //-----------------------------------------------------------------------------
  227. //This is a good creation inspector. There's been multitudes of issues with conflicts of
  228. //Objects getting constructed causing crashes either because the modules aren't created
  229. //yet, and there's stuff being done inside of setTeam() that cares.
  230. Bool areModulesReady() const { return m_modulesReady; }
  231. BehaviorModule** getBehaviorModules() const { return m_behaviors; }
  232. BodyModuleInterface* getBodyModule() const { return m_body; }
  233. ContainModuleInterface* getContain() const { return m_contain; }
  234. StealthUpdate* getStealth() const { return m_stealth; }
  235. SpawnBehaviorInterface* getSpawnBehaviorInterface() const;
  236. ProjectileUpdateInterface* getProjectileUpdateInterface() const;
  237. // special case for the AIUpdateInterface, since it will be referred to a great deal
  238. inline AIUpdateInterface *getAIUpdateInterface() { return m_ai; }
  239. inline const AIUpdateInterface* getAIUpdateInterface() const { return m_ai; }
  240. inline AIUpdateInterface *getAI() { return m_ai; }
  241. inline const AIUpdateInterface* getAI() const { return m_ai; }
  242. inline PhysicsBehavior* getPhysics() { return m_physics; }
  243. inline const PhysicsBehavior* getPhysics() const { return m_physics; }
  244. void topple( const Coord3D *toppleDirection, Real toppleSpeed, UnsignedInt options );
  245. UpdateModule* findUpdateModule(NameKeyType key) const { return (UpdateModule*)findModule(key); }
  246. DamageModule* findDamageModule(NameKeyType key) const { return (DamageModule*)findModule(key); }
  247. Bool isSalvageCrate() const;
  248. //
  249. // Find us our production update interface if we have one. This method exists simply
  250. // because we do this in a lot of places in the code and I want a convenient way to get thsi (CBD)
  251. //
  252. ProductionUpdateInterface* getProductionUpdateInterface( void );
  253. //
  254. // Find us our dock update interface if we have one. Again, this method exists simple
  255. // because we want to do this in a lot of places throughout the code
  256. //
  257. DockUpdateInterface *getDockUpdateInterface( void );
  258. // Ditto for special powers -- Kris
  259. SpecialPowerModuleInterface* findSpecialPowerModuleInterface( SpecialPowerType type ) const;
  260. SpecialPowerModuleInterface* findAnyShortcutSpecialPowerModuleInterface() const;
  261. SpecialAbilityUpdate* findSpecialAbilityUpdate( SpecialPowerType type ) const;
  262. SpecialPowerCompletionDie* findSpecialPowerCompletionDie() const;
  263. SpecialPowerUpdateInterface* findSpecialPowerWithOverridableDestinationActive( SpecialPowerType type = SPECIAL_INVALID ) const;
  264. SpecialPowerUpdateInterface* findSpecialPowerWithOverridableDestination( SpecialPowerType type = SPECIAL_INVALID ) const;
  265. CountermeasuresBehaviorInterface* Object::getCountermeasuresBehaviorInterface();
  266. const CountermeasuresBehaviorInterface* Object::getCountermeasuresBehaviorInterface() const;
  267. inline ObjectStatusMaskType getStatusBits() const { return m_status; }
  268. inline Bool testStatus( ObjectStatusTypes bit ) const { return m_status.test( bit ); }
  269. void setStatus( ObjectStatusMaskType objectStatus, Bool set = true );
  270. inline void clearStatus( ObjectStatusMaskType objectStatus ) { setStatus( objectStatus, false ); }
  271. void updateUpgradeModules(); ///< We need to go through our Upgrade Modules and see which should be activated
  272. UpgradeMaskType getObjectCompletedUpgradeMask() const { return m_objectUpgradesCompleted; } ///< Upgrades I complete locally
  273. //This function sucks.
  274. //It was added for objects that can disguise as other objects and contain upgraded subobject overrides.
  275. //A concrete example is the bomb truck. Different payloads are displayed based on which upgrades have been
  276. //made. When the bomb truck disguises as something else, these subobjects are lost because the vector is
  277. //stored in W3DDrawModule. When we revert back to the original bomb truck, we call this function to
  278. //recalculate those upgraded subobjects.
  279. void forceRefreshSubObjectUpgradeStatus();
  280. // Useful for status bits that can be set by the scripting system
  281. inline Bool testScriptStatusBit(ObjectScriptStatusBit b) const { return BitTest(m_scriptStatus, b); }
  282. void setScriptStatus( ObjectScriptStatusBit bit, Bool set = true );
  283. inline void clearScriptStatus( ObjectScriptStatusBit bit ) { setScriptStatus(bit, false); }
  284. // Selectable is individually controlled on an object by object basis for design now.
  285. // It defaults to the thingTemplate->isKindof(KINDOF_SELECTABLE), however, it can be overridden on an
  286. // object by object basis. Finally, it can be temporarily overriden by the OBJECT_STATUS_UNSELECTABLE.
  287. // jba.
  288. void setSelectable(Bool selectable);
  289. Bool isSelectable() const;
  290. Bool isMassSelectable() const;
  291. // User specified formation.
  292. void setFormationID(enum FormationID id) {m_formationID = id;}
  293. enum FormationID getFormationID(void) const {return m_formationID;}
  294. void setFormationOffset(const Coord2D& offset) {m_formationOffset = offset;}
  295. void getFormationOffset(Coord2D* offset) const {*offset = m_formationOffset;}
  296. //THIS FUNCTION BELONGS AT THE OBJECT LEVEL BECAUSE THERE IS AT LEAST ONE SPECIAL UNIT
  297. //(ANGRY MOB) WHICH NEEDS LOGIC-SIDE POSITION CALC'S...
  298. //IT WOULD PROBABLY BE WISE TO MOVE ALL THE HARD-CODED DEFAULTS BELOW
  299. //INTO A new Drawable::getHealthBox..() WHICH USES GEOM0INFO, MODEL DATA, INI DATA, ETC.
  300. void getHealthBoxPosition(Coord3D& pos) const;
  301. Bool getHealthBoxDimensions(Real &healthBoxHeight, Real &healthBoxWidth) const;
  302. inline Bool isEffectivelyDead() const { return (m_privateStatus & EFFECTIVELY_DEAD) != 0; }
  303. void setEffectivelyDead(Bool dead);
  304. void markSingleUseCommandUsed() { m_singleUseCommandUsed = true; }
  305. Bool hasSingleUseCommandBeenUsed() const { return m_singleUseCommandUsed; }
  306. /// returns true iff the object can run over the other object.
  307. Bool canCrushOrSquish(Object *otherObj, CrushSquishTestType testType = TEST_CRUSH_OR_SQUISH) const;
  308. UnsignedByte getCrusherLevel() const;
  309. UnsignedByte getCrushableLevel() const;
  310. Bool hasUpgrade( const UpgradeTemplate *upgradeT ) const ; ///< does this object already have this upgrade
  311. Bool affectedByUpgrade( const UpgradeTemplate *upgradeT ) const ; ///< can the object even "have" this upgrade, will it do something?
  312. void giveUpgrade( const UpgradeTemplate *upgradeT ); ///< give upgrade to this object
  313. void removeUpgrade( const UpgradeTemplate *upgradeT ); ///< remove upgrade from this object
  314. Bool hasCountermeasures() const;
  315. void reportMissileForCountermeasures( Object *missile );
  316. ObjectID calculateCountermeasureToDivertTo( const Object& victim );
  317. void calcNaturalRallyPoint(Coord2D *pt); ///< calc the "natural" starting rally point
  318. void setConstructionPercent( Real percent ) { m_constructionPercent = percent; }
  319. Real getConstructionPercent() const { return m_constructionPercent; }
  320. void setLayer( PathfindLayerEnum layer );
  321. PathfindLayerEnum getLayer() const { return m_layer; }
  322. void setDestinationLayer( PathfindLayerEnum layer );
  323. PathfindLayerEnum getDestinationLayer() const { return m_destinationLayer; }
  324. void prependToList(Object **pListHead);
  325. void removeFromList(Object **pListHead);
  326. Bool isInList(Object **pListHead) const;
  327. // this is intended for use ONLY by GameLogic.
  328. void friend_deleteInstance() { deleteInstance(); }
  329. /// cache the partition module (should be called only by PartitionData)
  330. void friend_setPartitionData(PartitionData *pd) { m_partitionData = pd; }
  331. PartitionData *friend_getPartitionData() const { return m_partitionData; }
  332. const PartitionData *friend_getConstPartitionData() const { return m_partitionData; }
  333. void onPartitionCellChange();///< We have moved a 'significant' amount, so do maintenence that can be considered 'cell-based'
  334. void handlePartitionCellMaintenance(); ///< Undo and redo all shroud actions. Call when something has changed, like position or ownership or Death
  335. Real getVisionRange() const; ///< How far can you see? This is dynamic so it is in Object.
  336. void setVisionRange( Real newVisionRange ); ///< Access to setting someone's Vision distance
  337. Real getShroudRange() const; ///< How far can you shroud? Even more dynamic since it'll start at zero for everyone.
  338. void setShroudRange( Real newShroudRange ); ///< Access to setting someone's shrouding distance
  339. Real getShroudClearingRange() const; ///< How far do you clear shroud?
  340. void setShroudClearingRange( Real newShroudClearingRange ); ///< Access to setting someone's clear shroud distance
  341. void setVisionSpied(Bool setting, Int byWhom);///< Change who is looking through our eyes
  342. // Both of these calls are intended to only be used by TerrainLogic, specifically setActiveBoundary()
  343. void friend_prepareForMapBoundaryAdjust(void);
  344. void friend_notifyOfNewMapBoundary(void);
  345. // data for the radar
  346. void friend_setRadarData( RadarObject *rd ) { m_radarData = rd; }
  347. RadarObject *friend_getRadarData() { return m_radarData; }
  348. RadarPriorityType getRadarPriority() const;
  349. // contained-by
  350. inline Object *getContainedBy() { return m_containedBy; }
  351. inline const Object *getContainedBy() const { return m_containedBy; }
  352. inline UnsignedInt getContainedByFrame() const { return m_containedByFrame; }
  353. inline Bool isContained() const { return m_containedBy != NULL; }
  354. void onContainedBy( Object *containedBy );
  355. void onRemovedFrom( Object *removedFrom );
  356. Int getTransportSlotCount() const;
  357. void friend_setContainedBy( Object *containedBy ) { m_containedBy = containedBy; }
  358. // Special Powers -------------------------------------------------------------------------------
  359. SpecialPowerModuleInterface *getSpecialPowerModule( const SpecialPowerTemplate *specialPowerTemplate ) const;
  360. void doSpecialPower( const SpecialPowerTemplate *specialPowerTemplate, UnsignedInt commandOptions, Bool forced = false ); ///< execute power
  361. void doSpecialPowerAtObject( const SpecialPowerTemplate *specialPowerTemplate, Object *obj, UnsignedInt commandOptions, Bool forced = false ); ///< execute power
  362. void doSpecialPowerAtLocation( const SpecialPowerTemplate *specialPowerTemplate, const Coord3D *loc, Real angle, UnsignedInt commandOptions, Bool forced = false ); ///< execute power
  363. void doSpecialPowerUsingWaypoints( const SpecialPowerTemplate *specialPowerTemplate, const Waypoint *way, UnsignedInt commandOptions, Bool forced = false ); ///< execute power
  364. void doCommandButton( const CommandButton *commandButton, CommandSourceType cmdSource );
  365. void doCommandButtonAtObject( const CommandButton *commandButton, Object *obj, CommandSourceType cmdSource );
  366. void doCommandButtonAtPosition( const CommandButton *commandButton, const Coord3D *pos, CommandSourceType cmdSource );
  367. void doCommandButtonUsingWaypoints( const CommandButton *commandButton, const Waypoint *way, CommandSourceType cmdSource );
  368. /**
  369. For Object specific dynamic command sets. Different from the Science specific ones handled in ThingTemplate
  370. */
  371. const AsciiString& getCommandSetString() const;
  372. void setCommandSetStringOverride( AsciiString newCommandSetString ) { m_commandSetStringOverride = newCommandSetString; }
  373. /// People are faking their commandsets, and, Surprise!, they are authoritative. Challenge everything.
  374. Bool Object::canProduceUpgrade( const UpgradeTemplate *upgrade );
  375. // Weapons & Damage -------------------------------------------------------------------------------------------------
  376. void reloadAllAmmo(Bool now);
  377. Bool isOutOfAmmo() const;
  378. Bool hasAnyWeapon() const;
  379. Bool hasAnyDamageWeapon() const; //Kris: a should be used for real weapons that directly inflict damage... not deploy, hack, etc.
  380. Bool hasWeaponToDealDamageType(DamageType typeToDeal) const;
  381. Real getLargestWeaponRange() const;
  382. UnsignedInt getMostPercentReadyToFireAnyWeapon() const;
  383. Weapon* getWeaponInWeaponSlot(WeaponSlotType wslot) const { return m_weaponSet.getWeaponInWeaponSlot(wslot); }
  384. UnsignedInt getWeaponInWeaponSlotCommandSourceMask( WeaponSlotType wSlot ) const { return m_weaponSet.getNthCommandSourceMask( wSlot ); }
  385. // see if this current weapon set's weapons has shared reload times
  386. const Bool isReloadTimeShared() const { return m_weaponSet.isSharedReloadTime(); }
  387. Weapon* getCurrentWeapon(WeaponSlotType* wslot = NULL);
  388. const Weapon* getCurrentWeapon(WeaponSlotType* wslot = NULL) const;
  389. void setFiringConditionForCurrentWeapon() const;
  390. void adjustModelConditionForWeaponStatus(); ///< Check to see if I should change my model condition.
  391. void fireCurrentWeapon(Object *target);
  392. void fireCurrentWeapon(const Coord3D* pos);
  393. void preFireCurrentWeapon( const Object *victim );
  394. UnsignedInt getLastShotFiredFrame() const; ///< Get the frame a shot was last fired on
  395. ObjectID getLastVictimID() const; ///< Get the last victim we shot at
  396. Weapon* findWaypointFollowingCapableWeapon();
  397. Bool getAmmoPipShowingInfo(Int& numTotal, Int& numFull) const;
  398. void notifyFiringTrackerShotFired( const Weapon* weaponFired, ObjectID victimID ) ;
  399. /**
  400. Determines if the unit has any weapon that could conceivably
  401. harm the victim. this does not take range, ammo, etc. into
  402. account, but immutable weapon properties, such as "can you
  403. target airborne victims".
  404. */
  405. /*
  406. NOTE: getAbleToAttackSpecificObject NO LONGER internally calls isAbleToAttack(),
  407. since that isn't an incredibly fast call, and this is called repeatedly in some inner loops
  408. where we already know that isAbleToAttack() == true. so you should always
  409. call isAbleToAttack prior to calling this! (srj)
  410. */
  411. CanAttackResult getAbleToAttackSpecificObject( AbleToAttackType t, const Object* target, CommandSourceType commandSource, WeaponSlotType specificSlot = (WeaponSlotType)-1 ) const;
  412. //Used for base defenses and otherwise stationary units to see if you can attack a position potentially out of range.
  413. CanAttackResult getAbleToUseWeaponAgainstTarget( AbleToAttackType attackType, const Object *victim, const Coord3D *pos, CommandSourceType commandSource, WeaponSlotType specificSlot = (WeaponSlotType)-1 ) const;
  414. /**
  415. Selects the best weapon for the given target, and sets it as the current weapon.
  416. If there is no weapon that can damage the target, false is returned (and the current-weapon is unchanged).
  417. Note that this DOES take weapon attack range into account.
  418. */
  419. Bool chooseBestWeaponForTarget(const Object* target, WeaponChoiceCriteria criteria, CommandSourceType cmdSource);
  420. // set and/or clear a single modelcondition flag
  421. void setModelConditionState( ModelConditionFlagType a );
  422. void clearModelConditionState( ModelConditionFlagType a );
  423. void clearAndSetModelConditionState( ModelConditionFlagType clr, ModelConditionFlagType set );
  424. //Special model states are states that are turned on for a period of time, and turned off
  425. //automatically -- used for cheer, and scripted special moment animations. Setting a special
  426. //state will automatically clear any other special states that may be turned on so you can only
  427. //have one at a time.
  428. void setSpecialModelConditionState( ModelConditionFlagType set, UnsignedInt frames = 0 );
  429. void clearSpecialModelConditionStates();
  430. // set and/or clear multiple modelcondition flags
  431. void clearModelConditionFlags( const ModelConditionFlags& clr );
  432. void setModelConditionFlags( const ModelConditionFlags& set );
  433. void clearAndSetModelConditionFlags( const ModelConditionFlags& clr, const ModelConditionFlags& set );
  434. void setWeaponSetFlag(WeaponSetType wst);
  435. void clearWeaponSetFlag(WeaponSetType wst);
  436. inline Bool testWeaponSetFlag(WeaponSetType wst) const { return m_curWeaponSetFlags.test(wst); }
  437. inline const WeaponSetFlags& getWeaponSetFlags() const { return m_curWeaponSetFlags; }
  438. Bool setWeaponLock( WeaponSlotType weaponSlot, WeaponLockType lockType ){ return m_weaponSet.setWeaponLock( weaponSlot, lockType ); }
  439. void releaseWeaponLock(WeaponLockType lockType){ m_weaponSet.releaseWeaponLock(lockType); }
  440. Bool isCurWeaponLocked() const { return m_weaponSet.isCurWeaponLocked(); }
  441. void setArmorSetFlag(ArmorSetType ast);
  442. void clearArmorSetFlag(ArmorSetType ast);
  443. Bool testArmorSetFlag(ArmorSetType ast) const;
  444. /// return true if the template has the specified special power flag set
  445. // @todo: inline
  446. Bool hasSpecialPower( SpecialPowerType type ) const;
  447. Bool hasAnySpecialPower() const;
  448. void setWeaponBonusCondition(WeaponBonusConditionType wst);
  449. void clearWeaponBonusCondition(WeaponBonusConditionType wst);
  450. // note, the !=0 at the end is important, to convert this into a boolean type! (srj)
  451. Bool testWeaponBonusCondition(WeaponBonusConditionType wst) const { return (m_weaponBonusCondition & (1 << wst)) != 0; }
  452. inline WeaponBonusConditionFlags getWeaponBonusCondition() const { return m_weaponBonusCondition; }
  453. Bool getSingleLogicalBonePosition(const char* boneName, Coord3D* position, Matrix3D* transform) const;
  454. Bool getSingleLogicalBonePositionOnTurret(WhichTurretType whichTurret, const char* boneName, Coord3D* position, Matrix3D* transform) const;
  455. Int getMultiLogicalBonePosition(const char* boneNamePrefix, Int maxBones, Coord3D* positions, Matrix3D* transforms, Bool convertToWorld = TRUE ) const;
  456. // Entered & exited.
  457. Bool didEnter(const PolygonTrigger *pTrigger) const;
  458. Bool didExit(const PolygonTrigger *pTrigger) const;
  459. Bool isInside(const PolygonTrigger *pTrigger) const;
  460. // exiting of any kind
  461. ExitInterface *getObjectExitInterface() const; ///< get exit interface is present
  462. Bool hasExitInterface() const { return getObjectExitInterface() != 0; }
  463. ObjectShroudStatus getShroudedStatus(Int playerIndex) const;
  464. DisabledMaskType getDisabledFlags() const { return m_disabledMask; }
  465. Bool isDisabled() const { return m_disabledMask.any(); }
  466. Bool clearDisabled( DisabledType type );
  467. void setDisabled( DisabledType type );
  468. void setDisabledUntil( DisabledType type, UnsignedInt frame );
  469. Bool isDisabledByType( DisabledType type ) const { return TEST_DISABLEDMASK( m_disabledMask, type ); }
  470. UnsignedInt getDisabledUntil( DisabledType type = DISABLED_ANY ) const;
  471. void pauseAllSpecialPowers( const Bool disabling ) const;
  472. //Checks any timers and clears disabled statii that have expired.
  473. void checkDisabledStatus();
  474. //When an AIAttackState is over, it needs to clean up any weapons that might be in leech range mode
  475. //or else those weapons will have unlimited range!
  476. void clearLeechRangeModeForAllWeapons();
  477. Int getNumConsecutiveShotsFiredAtTarget( const Object *victim) const;
  478. void setHealthBoxOffset( const Coord3D& offset ) { m_healthBoxOffset = offset; } ///< for special amorphous like angry mob
  479. void defect( Team *newTeam, UnsignedInt detectionTime );
  480. void goInvulnerable( UnsignedInt time );
  481. // This is public, since there is no Thing level master setting of Turret stuff. It is all done in a sleepy hamlet
  482. // of a module called TurretAI.
  483. virtual void reactToTurretChange( WhichTurretType turret, Real oldRotation, Real oldPitch );
  484. // Convenience function for checking certain kindof bits
  485. Bool isStructure(void) const;
  486. // Convenience function for checking certain kindof bits
  487. Bool isFactionStructure(void) const;
  488. // Convenience function for checking certain kindof bits
  489. Bool isNonFactionStructure(void) const;
  490. Bool isHero(void) const;
  491. Bool getReceivingDifficultyBonus() const { return m_isReceivingDifficultyBonus; }
  492. void setReceivingDifficultyBonus(Bool receive);
  493. inline UnsignedInt getSafeOcclusionFrame(void) { return m_safeOcclusionFrame; } //< this is an object specific frame at which it's safe to enable building occlusion.
  494. inline void setSafeOcclusionFrame(UnsignedInt frame) { m_safeOcclusionFrame = frame;}
  495. // All of our cheating for radars and power go here.
  496. // This is the function that we now call in becomingTeamMember to adjust our power.
  497. // If incoming is true, we're working on the incoming player, if its false, we're on the outgoing
  498. // player. These are friend_s for player.
  499. void friend_adjustPowerForPlayer( Bool incoming );
  500. protected:
  501. void setOrRestoreTeam( Team* team, Bool restoring );
  502. void onDisabledEdge(Bool becomingDisabled);
  503. // All of our cheating for radars and power go here.
  504. // snapshot methods
  505. void crc( Xfer *xfer );
  506. void xfer( Xfer *xfer );
  507. void loadPostProcess();
  508. void handleShroud();
  509. void handleValueMap();
  510. void handleThreatMap();
  511. // NOTE NOTE NOTE -- this is a private method. Do Not Ever Make It Public.
  512. // If you think you need to make it public, you are wrong. Don't do it.
  513. // It will go away someday. Yeah, right. Just like GlobalData.
  514. Module* findModule(NameKeyType key) const;
  515. Bool didEnterOrExit() const;
  516. void setID( ObjectID id );
  517. virtual Object *asObjectMeth() { return this; }
  518. virtual const Object *asObjectMeth() const { return this; }
  519. virtual Real calculateHeightAboveTerrain(void) const; // Calculates the actual height above terrain. Doesn't use cache.
  520. void updateTriggerAreaFlags(void);
  521. void setTriggerAreaFlagsForChangeInPosition(void);
  522. /// Look and unlook are protected. They should be called from Object::reasonToLook. Like Capture, or death.
  523. void look();
  524. void unlook();
  525. void shroud();
  526. void unshroud();
  527. /// value and threat functions are protected, and should only be called from handleValueMap
  528. void addValue();
  529. void removeValue();
  530. void addThreat();
  531. void removeThreat();
  532. virtual void reactToTransformChange(const Matrix3D* oldMtx, const Coord3D* oldPos, Real oldAngle);
  533. private:
  534. // yes, private. No, really. Private. Don't expose.
  535. enum ObjectPrivateStatusBits
  536. {
  537. EFFECTIVELY_DEAD = (1 << 0), ///< Object is effectively dead
  538. UNDETECTED_DEFECTOR = (1 << 1), ///< set to true when I defect from my team; set to false when I attack anything or when time runs out
  539. CAPTURED = (1 << 2), ///< set to true if I've been captured, otherwise, its false. (Note: Never becomes false once it's true)
  540. OFF_MAP = (1 << 3) ///< set to true if I am known to be OFF the current map.
  541. // NOTE: Object currently only uses a Byte for this, so if you add status bits, you may need to enlarge that field.
  542. };
  543. ObjectID m_id; ///< this object's unique ID
  544. ObjectID m_producerID; ///< object that produced us, if any
  545. ObjectID m_builderID; ///< object that is building or has built us (dozers or workers are builders)
  546. Drawable* m_drawable; ///< drawable (if any) for this object
  547. AsciiString m_name; ///< internal name
  548. Object * m_next;
  549. Object * m_prev;
  550. ObjectStatusMaskType m_status; ///< status bits (see ObjectStatusMaskType)
  551. GeometryInfo m_geometryInfo;
  552. AIGroup* m_group; ///< if non-NULL, we are part of this group of agents
  553. // These will last for my lifetime. I will reuse them and reset them. The truly dynamic ones are in PartitionManager
  554. SightingInfo *m_partitionLastLook; ///< Where and for whom I last looked, so I can undo its effects when I stop
  555. SightingInfo *m_partitionRevealAllLastLook; ///< And a seperate look to reveal at a different range if so marked
  556. Int m_visionSpiedBy[MAX_PLAYER_COUNT]; ///< Reference count of having units spied on by players.
  557. PlayerMaskType m_visionSpiedMask; ///< For quick lookup and edge triggered maintenance
  558. SightingInfo *m_partitionLastShroud; ///< Where and for whom I last shrouded, so I can undo its effects when I stop
  559. SightingInfo *m_partitionLastThreat; ///< Where and for whom I last delt with threat, so I can undo its effects when I stop
  560. SightingInfo *m_partitionLastValue; ///< Where and for whom I last delt with value, so I can undo its effects when I stop
  561. Real m_visionRange; ///< looking range
  562. Real m_shroudClearingRange; ///< looking range for shroud ONLY
  563. Real m_shroudRange; ///< like looking range, this is how far I shroud others' looks
  564. DisabledMaskType m_disabledMask;
  565. UnsignedInt m_disabledTillFrame[ DISABLED_COUNT ];
  566. UnsignedInt m_smcUntil;
  567. enum { NUM_SLEEP_HELPERS = 8 };
  568. ObjectRepulsorHelper* m_repulsorHelper;
  569. ObjectSMCHelper* m_smcHelper;
  570. ObjectWeaponStatusHelper* m_wsHelper;
  571. ObjectDefectionHelper* m_defectionHelper;
  572. StatusDamageHelper* m_statusDamageHelper;
  573. SubdualDamageHelper* m_subdualDamageHelper;
  574. TempWeaponBonusHelper* m_tempWeaponBonusHelper;
  575. FiringTracker* m_firingTracker; ///< Tracker is really a "helper" and is included NUM_SLEEP_HELPERS
  576. // modules
  577. BehaviorModule** m_behaviors; // BehaviorModule, not BehaviorModuleInterface
  578. // cache these, for convenience
  579. ContainModuleInterface* m_contain;
  580. BodyModuleInterface* m_body;
  581. StealthUpdate* m_stealth;
  582. AIUpdateInterface* m_ai; ///< ai interface (if any), cached for handy access. (duplicate of entry in the module array!)
  583. PhysicsBehavior* m_physics; ///< physics interface (if any), cached for handy access. (duplicate of entry in the module array!)
  584. PartitionData* m_partitionData; ///< our PartitionData
  585. RadarObject* m_radarData; ///< radar data
  586. ExperienceTracker* m_experienceTracker; ///< Manages experience, gaining levels, and value when killed
  587. Object* m_containedBy; /**< an object can only be contained by at most one
  588. other object, this is that object (if present) */
  589. ObjectID m_xferContainedByID; ///< xfer uses IDs to store pointers and looks them up after
  590. UnsignedInt m_containedByFrame; ///< frame we were contained by m_containedBy
  591. Real m_constructionPercent; ///< for objects being built ... this is the amount completed (0.0 to 100.0)
  592. UpgradeMaskType m_objectUpgradesCompleted; ///< Bit field of upgrades locally completed.
  593. Team* m_team; ///< team that is current owner of this guy
  594. AsciiString m_originalTeamName; ///< team that was the original ("birth") team of this guy
  595. Color m_indicatorColor; ///< if nonzero, use this instead of controlling player's color
  596. Coord3D m_healthBoxOffset; ///< generally zero, except for special amorphous ones like angry mob
  597. /// @todo srj -- convert to non-DLINK list, after it is once again possible to test the change
  598. MAKE_DLINK(Object, TeamMemberList) ///< other Things that are members of the same team
  599. // Weapons & Damage -------------------------------------------------------------------------------------------------
  600. WeaponSet m_weaponSet;
  601. WeaponSetFlags m_curWeaponSetFlags;
  602. WeaponBonusConditionFlags m_weaponBonusCondition;
  603. Byte m_lastWeaponCondition[WEAPONSLOT_COUNT];
  604. SpecialPowerMaskType m_specialPowerBits; ///< bits determining what kind of special abilities this object has access to.
  605. //////////////////////////////////////< for the non-stacking healers like ambulance and propaganda
  606. ObjectID m_soleHealingBenefactorID; ///< who is the only other object that can give me this non-stacking heal benefit?
  607. UnsignedInt m_soleHealingBenefactorExpirationFrame; ///< on what frame can I accept healing (thus to switch) from a new benefactor
  608. ///////////////////////////////////
  609. // Entered & exited housekeeping.
  610. enum { MAX_TRIGGER_AREA_INFOS = 5 };
  611. TTriggerInfo m_triggerInfo[MAX_TRIGGER_AREA_INFOS];
  612. UnsignedInt m_enteredOrExitedFrame;
  613. ICoord3D m_iPos;
  614. PathfindLayerEnum m_layer; // Layer object is pathing on.
  615. PathfindLayerEnum m_destinationLayer; // Layer of current path goal.
  616. // User formations.
  617. FormationID m_formationID;
  618. Coord2D m_formationOffset;
  619. AsciiString m_commandSetStringOverride;///< To allow specific object to switch command sets
  620. UnsignedInt m_safeOcclusionFrame; ///<flag used by occlusion renderer so it knows when objects have exited their production building.
  621. // --------- BYTE-SIZED THINGS GO HERE
  622. Bool m_isSelectable;
  623. Bool m_modulesReady;
  624. #if defined(_DEBUG) || defined(_INTERNAL)
  625. Bool m_hasDiedAlready;
  626. #endif
  627. UnsignedByte m_scriptStatus; ///< status as set by scripting, corresponds to ORed ObjectScriptStatusBits
  628. UnsignedByte m_privateStatus; ///< status bits that are never directly accessible to outside world
  629. Byte m_numTriggerAreasActive;
  630. Bool m_singleUseCommandUsed;
  631. Bool m_isReceivingDifficultyBonus;
  632. }; // end class Object
  633. #ifdef DEBUG_LOGGING
  634. // describe an object as an AsciiString: e.g. "Object 102 (KillerBuggy) [GLARocketBuggy, owned by player 2 (GLAIntroPlayer)]"
  635. AsciiString DescribeObject(const Object *obj);
  636. #endif // DEBUG_LOGGING
  637. #if defined(_DEBUG) || defined(_INTERNAL)
  638. #define DEBUG_OBJECT_ID_EXISTS
  639. #else
  640. #undef DEBUG_OBJECT_ID_EXISTS
  641. #endif
  642. #ifdef DEBUG_OBJECT_ID_EXISTS
  643. extern ObjectID TheObjectIDToDebug;
  644. #endif
  645. #endif // _OBJECT_H_