Drawable.h 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797
  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. // FILE: Drawable.h ///////////////////////////////////////////////////////////////////////////////
  24. // Simple base drawable
  25. // Author: Michael S. Booth, March 2001
  26. #pragma once
  27. #ifndef _DRAWABLE_H_
  28. #define _DRAWABLE_H_
  29. #include "Common/AudioEventRTS.h"
  30. #include "Common/GameType.h"
  31. #include "Common/ModelState.h"
  32. #include "Common/ModuleFactory.h"
  33. #include "Common/Thing.h"
  34. #include "Common/Geometry.h"
  35. #include "GameClient/Color.h"
  36. #include "WWMath/Matrix3D.h"
  37. #include "GameClient/DrawableInfo.h"
  38. // FORWARD REFERENCES /////////////////////////////////////////////////////////////////////////////
  39. class PositionalSound;
  40. class ThingTemplate;
  41. class Particle;
  42. class DisplayString;
  43. class FXList;
  44. class DrawModule;
  45. class ClientUpdateModule;
  46. class View;
  47. class Locomotor;
  48. class Anim2D;
  49. class Shadow;
  50. class ModuleInfo;
  51. class Anim2DTemplate;
  52. class Image;
  53. class DynamicAudioEventInfo;
  54. enum BodyDamageType;
  55. // this is a very worthwhile performance win. left conditionally defined for now, just
  56. // in case, but probably should be made permanent soon. (srj)
  57. #define DIRTY_CONDITION_FLAGS
  58. #define DEFAULT_TINT_COLOR_FADE_RATE (0.6f) // fast fade
  59. #define DEF_ATTACK_FRAMES (1)
  60. #define DEF_SUSTAIN_FRAMES (1)
  61. #define DEF_DECAY_FRAMES (4)
  62. #define SUSTAIN_INDEFINITELY (0xfffffffe) // forever and ever, amen.
  63. //-----------------------------------------------------------------------------
  64. //@TODO -- The drawable icon system needs to be implemented in a proper manner -- KM
  65. // Fact 1: Every drawable in the world shouldn't have to have a pointer
  66. // and frame counter for every possible icon type. It should be a dynamic vector.
  67. // Fact 2: It's polling every frame for every object on screen for every possible icon condition...
  68. // KM : I moved this into Drawable.cpp so I don't have to recompile the entire project
  69. // each time I add a new icon, and made the arrays dynamic...
  70. // CD: No so good, core engine components should not be made dynamic in this way
  71. enum DrawableIconType
  72. {
  73. /** NOTE: This enum MUST appear in the same order as TheDrawableIconNames array to be
  74. * indexed correctly using that array */
  75. ICON_INVALID = -1,
  76. ICON_FIRST = 0,
  77. ICON_DEFAULT_HEAL = ICON_FIRST,
  78. ICON_STRUCTURE_HEAL,
  79. ICON_VEHICLE_HEAL,
  80. #ifdef ALLOW_DEMORALIZE
  81. ICON_DEMORALIZED,
  82. #else
  83. ICON_DEMORALIZED_OBSOLETE,
  84. #endif
  85. ICON_BOMB_TIMED,
  86. ICON_BOMB_REMOTE,
  87. ICON_DISABLED,
  88. ICON_BATTLEPLAN_BOMBARD,
  89. ICON_BATTLEPLAN_HOLDTHELINE,
  90. ICON_BATTLEPLAN_SEARCHANDDESTROY,
  91. ICON_EMOTICON,
  92. ICON_ENTHUSIASTIC,
  93. ICON_ENTHUSIASTIC_SUBLIMINAL,
  94. ICON_CARBOMB,
  95. MAX_ICONS ///< keep this last
  96. };
  97. //-----------------------------------------------------------------------------
  98. class DrawableIconInfo : public MemoryPoolObject
  99. {
  100. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(DrawableIconInfo, "DrawableIconInfo" )
  101. public:
  102. Anim2D* m_icon[MAX_ICONS];
  103. UnsignedInt m_keepTillFrame[MAX_ICONS];
  104. DrawableIconInfo();
  105. //~DrawableIconInfo();
  106. void clear();
  107. void killIcon(DrawableIconType t);
  108. };
  109. //-----------------------------------------------------------------------------
  110. struct TWheelInfo
  111. {
  112. Real m_frontLeftHeightOffset; ///< Height offsets for tires due to suspension sway
  113. Real m_frontRightHeightOffset;
  114. Real m_rearLeftHeightOffset;
  115. Real m_rearRightHeightOffset;
  116. Real m_wheelAngle; ///< Wheel angle. 0 = straight, >0 left, <0 right.
  117. Int m_framesAirborneCounter; ///< Counter.
  118. Int m_framesAirborne; ///< How many frames it was in the air.
  119. };
  120. //-----------------------------------------------------------------------------
  121. class DrawableLocoInfo : public MemoryPoolObject
  122. {
  123. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(DrawableLocoInfo, "DrawableLocoInfo" )
  124. public:
  125. Real m_pitch; ///< pitch of the entire drawable
  126. Real m_pitchRate; ///< rate of change of pitch
  127. Real m_roll; ///< roll of the entire drawable
  128. Real m_rollRate; ///< rate of change of roll
  129. Real m_yaw; ///< yaw for entire drawable
  130. Real m_accelerationPitch; ///< pitch of the drawable due to impact/acceleration
  131. Real m_accelerationPitchRate; ///< rate of change of pitch
  132. Real m_accelerationRoll; ///< roll of the entire drawable
  133. Real m_accelerationRollRate; ///< rate of change of roll
  134. Real m_overlapZVel; ///< fake Z velocity
  135. Real m_overlapZ; ///< current height (additional)
  136. Real m_wobble; ///< for wobbling
  137. Real m_yawModulator; ///< for the swimmy soft hover of a helicopter
  138. Real m_pitchModulator; ///< for the swimmy soft hover of a helicopter
  139. TWheelInfo m_wheelInfo; ///< Wheel offset & angle info for a wheeled type locomotor.
  140. DrawableLocoInfo();
  141. };
  142. //-----------------------------------------------------------------------------
  143. //* TintEnvelope handles the fading of the tint color up, down stable etc...
  144. //* assumes that 0,0,0, is the color for the AT REST state, used as decay target
  145. //* works like an ADSR envelope,
  146. //* except that SUSTAIN and RELEASE are randomly (or never) triggered, externally
  147. class TintEnvelope : public MemoryPoolObject, public Snapshot
  148. {
  149. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(TintEnvelope, "TintEnvelope" )
  150. public:
  151. TintEnvelope(void);
  152. void update(void); ///< does all the work
  153. void play(const RGBColor *peak,
  154. UnsignedInt atackFrames = DEF_ATTACK_FRAMES,
  155. UnsignedInt decayFrames = DEF_DECAY_FRAMES,
  156. UnsignedInt sustainAtPeak = DEF_SUSTAIN_FRAMES ); // ask MLorenzen
  157. void sustain(void) { m_envState = ENVELOPE_STATE_SUSTAIN; }
  158. void release(void) { m_envState = ENVELOPE_STATE_DECAY; }
  159. void rest(void) { m_envState = ENVELOPE_STATE_REST; } // goes away now!
  160. Bool isEffective() const { return m_affect; }
  161. const Vector3* getColor() const { return &m_currentColor; }
  162. protected:
  163. // snapshot methods
  164. virtual void crc( Xfer *xfer );
  165. virtual void xfer( Xfer *xfer );
  166. virtual void loadPostProcess( void );
  167. private:
  168. void setAttackFrames(UnsignedInt frames);
  169. void setDecayFrames( UnsignedInt frames);
  170. void setPeakColor( const RGBColor *peak) {m_peakColor = Vector3( peak->red, peak->green, peak->blue );};
  171. void setPeakColor( Real r, Real g, Real b ) {m_peakColor.Set( r, g, b );};
  172. enum EnvelopeStatesEnum
  173. {
  174. ENVELOPE_STATE_REST,
  175. ENVELOPE_STATE_ATTACK,
  176. ENVELOPE_STATE_DECAY,
  177. ENVELOPE_STATE_SUSTAIN ///< RELEASE IS THE LOGICAL COMPLIMENT TO SUSTAIN
  178. };
  179. Vector3 m_attackRate; ///< step amount to make tint turn on slow or fast
  180. Vector3 m_decayRate; ///< step amount to make tint turn off slow or fast
  181. Vector3 m_peakColor; ///< um, the peak color, what color we are headed toward during attack
  182. Vector3 m_currentColor; ///< um, the current color, how we are colored, now
  183. UnsignedInt m_sustainCounter;
  184. Byte m_envState; ///< a randomly switchable SUSTAIN state, release is compliment
  185. Bool m_affect; ///< set TRUE if this has any effect (has a non 0,0,0 color).
  186. };
  187. EMPTY_DTOR(TintEnvelope)
  188. //-----------------------------------------------------------------------------
  189. enum StealthLookType
  190. {
  191. STEALTHLOOK_NONE, ///< unit is not stealthed at all
  192. STEALTHLOOK_VISIBLE_FRIENDLY, ///< unit is stealthed-but-visible due to friendly status
  193. STEALTHLOOK_DISGUISED_ENEMY, ///< we can have units that are disguised (instead of invisible)
  194. STEALTHLOOK_VISIBLE_DETECTED, ///< unit is stealthed and invisible, but a second material pass
  195. ///< is added to reveal the invisible unit as with heat vision
  196. STEALTHLOOK_VISIBLE_FRIENDLY_DETECTED, ///< unit is stealthed-but-visible due to being detected,
  197. ///< and rendered in heatvision effect second material pass
  198. STEALTHLOOK_INVISIBLE ///< unit is stealthed-and-invisible
  199. };
  200. // ------------------------------------------------------------------------------------------------
  201. /** Drawable status bits */
  202. // ------------------------------------------------------------------------------------------------
  203. enum DrawableStatus
  204. {
  205. DRAWABLE_STATUS_NONE = 0x00000000, ///< no status
  206. DRAWABLE_STATUS_DRAWS_IN_MIRROR = 0x00000001, ///< drawable can reflect
  207. DRAWABLE_STATUS_SHADOWS = 0x00000002, ///< use setShadowsEnabled() access method
  208. DRAWABLE_STATUS_TINT_COLOR_LOCKED = 0x00000004, ///< drawable tint color is "locked" and won't fade to normal
  209. DRAWABLE_STATUS_NO_STATE_PARTICLES = 0x00000008, ///< do *not* auto-create particle systems based on model condition
  210. DRAWABLE_STATUS_NO_SAVE = 0x00000010, ///< do *not* save this drawable (UI fluff only). ignored (error, actually) if attached to an object
  211. };
  212. enum TintStatus
  213. {
  214. TINT_STATUS_DISABLED = 0x00000001,///< drawable tint color is deathly dark grey
  215. TINT_STATUS_IRRADIATED = 0x00000002,///< drawable tint color is sickly green
  216. TINT_STATUS_POISONED = 0x00000004,///< drawable tint color is open-sore red
  217. TINT_STATUS_GAINING_SUBDUAL_DAMAGE = 0x00000008,///< When gaining subdual damage, we tint SUBDUAL_DAMAGE_COLOR
  218. TINT_STATUS_FRENZY = 0x00000010,///< When frenzied, we tint FRENZY_COLOR
  219. };
  220. //-----------------------------------------------------------------------------
  221. //Keep this enum in sync with the TerrainDecalTextureName array in drawable.cpp
  222. //
  223. // Note: these values are saved in save files, so you MUST NOT REMOVE OR CHANGE
  224. // existing values!
  225. //
  226. enum TerrainDecalType
  227. {
  228. #ifdef ALLOW_DEMORALIZE
  229. TERRAIN_DECAL_DEMORALIZED = 0,
  230. #else
  231. TERRAIN_DECAL_DEMORALIZED_OBSOLETE = 0,
  232. #endif
  233. TERRAIN_DECAL_HORDE,
  234. TERRAIN_DECAL_HORDE_WITH_NATIONALISM_UPGRADE,
  235. TERRAIN_DECAL_HORDE_VEHICLE,
  236. TERRAIN_DECAL_HORDE_WITH_NATIONALISM_UPGRADE_VEHICLE,
  237. TERRAIN_DECAL_CRATE,
  238. TERRAIN_DECAL_HORDE_WITH_FANATICISM_UPGRADE,
  239. TERRAIN_DECAL_CHEMSUIT,
  240. TERRAIN_DECAL_NONE,
  241. TERRAIN_DECAL_SHADOW_TEXTURE, //use the shadow texture as the terrain decal.
  242. TERRAIN_DECAL_MAX ///< keep this last
  243. };
  244. //-----------------------------------------------------------------------------
  245. const Int DRAWABLE_FRAMES_PER_FLASH = LOGICFRAMES_PER_SECOND / 2;
  246. //-----------------------------------------------------------------------------
  247. /**
  248. * A Drawable is a graphical entity which is generally associated
  249. * with a GameLogic object. Drawables are managed by TheGameClient.
  250. */
  251. class Drawable : public Thing,
  252. public Snapshot
  253. {
  254. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE(Drawable, "Drawable" )
  255. public:
  256. Drawable( const ThingTemplate *thing, DrawableStatus statusBits = DRAWABLE_STATUS_NONE );
  257. void onDestroy( void ); ///< run from GameClient::destroyDrawable
  258. void onLevelStart(); ///< run from GameLogic::startNewGame
  259. Drawable *getNextDrawable( void ) const { return m_nextDrawable; } ///< return the next drawable in the global list
  260. Drawable *getPrevDrawable( void ) const { return m_prevDrawable; } ///< return the prev drawable in the global list
  261. DrawableID getID( void ) const; ///< return this drawable's unique ID
  262. void friend_bindToObject( Object *obj ); ///< bind this drawable to an object ID. for use ONLY by GameLogic!
  263. void setIndicatorColor(Color color);
  264. void setTintStatus( TintStatus statusBits ) { BitSet( m_tintStatus, statusBits ); };
  265. void clearTintStatus( TintStatus statusBits ) { BitClear( m_tintStatus, statusBits ); };
  266. Bool testTintStatus( TintStatus statusBits ) const { return BitTest( m_tintStatus, statusBits ); };
  267. TintEnvelope *getColorTintEnvelope( void ) { return m_colorTintEnvelope; }
  268. void setColorTintEnvelope( TintEnvelope &source ) { if (m_colorTintEnvelope) *m_colorTintEnvelope = source; }
  269. void imitateStealthLook( Drawable& otherDraw );
  270. void setTerrainDecal(TerrainDecalType type); ///<decal that is to appear under the drawable
  271. void setTerrainDecalSize(Real x, Real y);
  272. void setTerrainDecalFadeTarget(Real target, Real rate = 0.1f);
  273. inline Object *getObject( void ) { return m_object; } ///< return object ID bound to this drawble
  274. inline const Object *getObject( void ) const { return m_object; } ///< return object ID bound to this drawble
  275. inline DrawableInfo *getDrawableInfo(void) {return &m_drawableInfo;}
  276. void setDrawableHidden( Bool hidden ); ///< hide or unhide drawable
  277. //
  278. // note that this is not necessarily the 'get' reflection of setDrawableHidden, since drawables
  279. // can spontaneously hide via stealth. (srj)
  280. //
  281. inline Bool isDrawableEffectivelyHidden() const { return m_hidden || m_hiddenByStealth; }
  282. void setSelectable( Bool selectable ); ///< Changes the drawables selectability
  283. Bool isSelectable( void ) const;
  284. Bool isMassSelectable( void ) const;
  285. void setStealthLook(StealthLookType look);
  286. StealthLookType getStealthLook() const { return m_stealthLook; }
  287. void updateDrawableClipStatus( UnsignedInt shotsRemaining, UnsignedInt maxShots, WeaponSlotType slot ); ///< This will do the show/hide work if ProjectileBoneFeedbackEnabled is set.
  288. void updateDrawableSupplyStatus( Int maxSupply, Int currentSupply ); ///< This will do visual feedback on Supplies carried
  289. void notifyDrawableDependencyCleared();///< If any of your draw modules were waiting for something, it's ready now.
  290. // Override.
  291. void setPosition( const Coord3D *pos );
  292. void reactToGeometryChange();
  293. const GeometryInfo& getDrawableGeometryInfo() const;
  294. void reactToBodyDamageStateChange(BodyDamageType newState);
  295. const Real getScale (void) const ;
  296. // access to modules
  297. //---------------------------------------------------------------------------
  298. // since most things don't have CU modules, we allow this to be null!
  299. ClientUpdateModule** getClientUpdateModules() { return (ClientUpdateModule**)getModuleList(MODULETYPE_CLIENT_UPDATE); }
  300. ClientUpdateModule const** getClientUpdateModules() const { return (ClientUpdateModule const**)getModuleList(MODULETYPE_CLIENT_UPDATE); }
  301. ClientUpdateModule* findClientUpdateModule( NameKeyType key );
  302. DrawModule** getDrawModulesNonDirty();
  303. DrawModule** getDrawModules();
  304. DrawModule const** getDrawModules() const;
  305. //---------------------------------------------------------------------------
  306. void setDrawableStatus( DrawableStatus bit ) { BitSet( m_status, bit ); }
  307. void clearDrawableStatus( DrawableStatus bit ) { BitClear( m_status, bit ); }
  308. inline Bool testDrawableStatus( DrawableStatus bit ) const { return (m_status & bit) != 0; }
  309. void setShroudClearFrame( UnsignedInt frame ) { m_shroudClearFrame = frame; }
  310. UnsignedInt getShroudClearFrame( void ) { return m_shroudClearFrame; }
  311. void setShadowsEnabled(Bool enable);
  312. Bool getShadowsEnabled() const { return BitTest(m_status, DRAWABLE_STATUS_SHADOWS); }
  313. void releaseShadows(void); ///< frees all shadow resources used by this module - used by Options screen.
  314. void allocateShadows(void); ///< create shadow resources if not already present. Used by Options screen.
  315. void setFullyObscuredByShroud(Bool fullyObscured);
  316. inline Bool getFullyObscuredByShroud(void) {return m_drawableFullyObscuredByShroud;}
  317. // Put on ice until later... M Lorenzen
  318. // inline UnsignedByte getFullyObscuredByShroudWithCheatSpy(void) {return (UnsignedByte)m_drawableFullyObscuredByShroud | 128;}//8 looks like a zero in most fonts
  319. Bool getDrawsInMirror() const { return BitTest(m_status, DRAWABLE_STATUS_DRAWS_IN_MIRROR) || isKindOf(KINDOF_CAN_CAST_REFLECTIONS); }
  320. void colorFlash( const RGBColor *color, UnsignedInt decayFrames = DEF_DECAY_FRAMES, UnsignedInt attackFrames = 0, UnsignedInt sustainAtPeak = FALSE ); ///< flash a drawable in the color specified for a short time
  321. void colorTint( const RGBColor *color ); ///< tint this drawable the color specified
  322. void setTintEnvelope( const RGBColor *color, Real attack, Real decay ); ///< how to transition color
  323. void flashAsSelected( const RGBColor *color = NULL ); ///< drawable takes care of the details if you spec no color
  324. /// Return true if drawable has been marked as "selected"
  325. Bool isSelected( void ) const { return m_selected; }
  326. void onSelected(); ///< Work unrelated to selection that must happen at time of selection
  327. void onUnselected(); ///< Work unrelated to selection that must happen at time of unselection
  328. //---------------------------------------------------------------------------
  329. // an "instance" matrix defines the local transform of the Drawable, and is concatenated with the global transform
  330. void setInstanceMatrix( const Matrix3D *instance ); ///< set the Drawable's instance transform
  331. const Matrix3D *getInstanceMatrix( void ) const { return &m_instance; } ///< get drawable instance transform
  332. inline Bool isInstanceIdentity() const { return m_instanceIsIdentity; }
  333. inline Real getInstanceScale( void ) const { return m_instanceScale; } ///< get scale that will be applied to instance matrix
  334. void setInstanceScale(Real value) { m_instanceScale = value;} ///< set scale that will be applied to instance matrix before rendering.
  335. const Matrix3D *getTransformMatrix( void ) const; ///< return the world transform
  336. void draw( View *view ); ///< render the drawable to the given view
  337. void updateDrawable(); ///< update the drawable
  338. void drawIconUI( void ); ///< draw "icon"(s) needed on drawable (health bars, veterency, etc)
  339. void startAmbientSound( Bool onlyIfPermanent = false );
  340. void stopAmbientSound( void );
  341. void enableAmbientSound( Bool enable );
  342. void setTimeOfDay( TimeOfDay tod );
  343. Bool getAmbientSoundEnabledFromScript( void ) const { return m_ambientSoundEnabledFromScript; }
  344. void prependToList(Drawable **pListHead);
  345. void removeFromList(Drawable **pListHead);
  346. void setID( DrawableID id ); ///< set this drawable's unique ID
  347. inline const ModelConditionFlags& getModelConditionFlags( void ) const { return m_conditionState; }
  348. //
  349. // NOTE: avoid repeated calls to the set and clear for the condition state as they
  350. // reconstruct and load models which is expensive ... wrap up all our bit flags to
  351. // set and clear into one function call
  352. //
  353. void clearModelConditionState( ModelConditionFlagType a ) { clearAndSetModelConditionState(a, MODELCONDITION_INVALID); }
  354. void setModelConditionState( ModelConditionFlagType a ) { clearAndSetModelConditionState(MODELCONDITION_INVALID, a); }
  355. void clearAndSetModelConditionState( ModelConditionFlagType clr, ModelConditionFlagType set );
  356. void clearModelConditionFlags( const ModelConditionFlags& clr ) { ModelConditionFlags empty; clearAndSetModelConditionFlags(clr, empty); }
  357. void setModelConditionFlags( const ModelConditionFlags& set ) { ModelConditionFlags empty; clearAndSetModelConditionFlags(empty, set); }
  358. void clearAndSetModelConditionFlags( const ModelConditionFlags& clr, const ModelConditionFlags& set );
  359. void replaceModelConditionFlags( const ModelConditionFlags &flags, Bool forceReplace = FALSE );
  360. Bool handleWeaponFireFX(
  361. WeaponSlotType wslot,
  362. Int specificBarrelToUse,
  363. const FXList* fxl,
  364. Real weaponSpeed,
  365. Real recoilAmount,
  366. Real recoilAngle,
  367. const Coord3D* victimPos,
  368. Real damageRadius
  369. );
  370. Int getBarrelCount(WeaponSlotType wslot) const;
  371. // when our Object changes teams, it calls us to let us know, so
  372. // we can update our model, etc., if necessary. NOTE, we don't guarantee
  373. // that the new team is different from the old team, nor do we guarantee
  374. // that the team is nonnull.
  375. void changedTeam();
  376. const TWheelInfo *getWheelInfo(void) const { return m_locoInfo ? &m_locoInfo->m_wheelInfo : NULL; }
  377. const DrawableLocoInfo *getLocoInfo() const { return m_locoInfo; }
  378. // this method must ONLY be called from the client, NEVER From the logic, not even indirectly.
  379. Bool clientOnly_getFirstRenderObjInfo(Coord3D* pos, Real* boundingSphereRadius, Matrix3D* transform);
  380. /**
  381. Find the bone(s) with the given name and return their positions and/or transforms in the given arrays.
  382. We look for a bone named "boneNamePrefixQQ", where QQ is 01, 02, 03, etc, starting at the
  383. value of "startIndex". Want to look for just a specific boneName with no numeric suffix?
  384. just pass zero (0) for startIndex. (no, we never look for "boneNamePrefix00".)
  385. We copy up to 'maxBones' into the array(s), and return the total count found.
  386. NOTE: this returns the positions and transform for the "ideal" model... that is,
  387. at its default rotation and scale, located at (0,0,0). You'll have to concatenate
  388. an Object's position and transform onto these in order to move 'em into "world space"!
  389. NOTE: this isn't very fast. Please call it sparingly and cache the result.
  390. */
  391. Int getPristineBonePositions(const char* boneNamePrefix, Int startIndex, Coord3D* positions, Matrix3D* transforms, Int maxBones) const;
  392. Int getCurrentClientBonePositions(const char* boneNamePrefix, Int startIndex, Coord3D* positions, Matrix3D* transforms, Int maxBones) const;
  393. // this is a special-purpose call for W3DModelDraw. (srj)
  394. Bool getCurrentWorldspaceClientBonePositions(const char* boneName, Matrix3D& transform) const;
  395. Bool getProjectileLaunchOffset(WeaponSlotType wslot, Int specificBarrelToUse, Matrix3D* launchPos, WhichTurretType tur, Coord3D* turretRotPos, Coord3D* turretPitchPos = NULL) const;
  396. /**
  397. This call says, "I want the current animation (if any) to take n frames to complete a single cycle".
  398. If it's a looping anim, each loop will take n frames. someday, we may want to add the option to insert
  399. "pad" frames at the start and/or end, but for now, we always just "stretch" the animation to fit.
  400. Note that you must call this AFTER setting the condition codes.
  401. */
  402. void setAnimationLoopDuration(UnsignedInt numFrames);
  403. /**
  404. similar to the above, but assumes that the current state is a "ONCE",
  405. and is smart about transition states... if there is a transition state
  406. "inbetween", it is included in the completion time.
  407. */
  408. void setAnimationCompletionTime(UnsignedInt numFrames);
  409. //Kris: Manually set a drawable's current animation to specific frame.
  410. virtual void setAnimationFrame( int frame );
  411. void updateSubObjects();
  412. void showSubObject( const AsciiString& name, Bool show );
  413. #ifdef ALLOW_ANIM_INQUIRIES
  414. // srj sez: not sure if this is a good idea, for net sync reasons...
  415. Real getAnimationScrubScalar( void ) const; // lorenzen // returns 0 to 1... where are we between start and finish?
  416. #endif
  417. UnsignedInt getExpirationDate() const { return m_expirationDate; }
  418. void setExpirationDate(UnsignedInt frame) { m_expirationDate = frame; }
  419. //
  420. // *ONLY* the InGameUI should do the actual drawable selection and de-selection
  421. //
  422. void friend_setSelected( void ); ///< mark drawable as "selected"
  423. void friend_clearSelected( void ); ///< clear drawable's "selected"
  424. Vector3 * getAmbientLight( void ); ///< get color value to add to ambient light when drawing
  425. void setAmbientLight( Vector3 *ambient ); ///< set color value to add to ambient light when drawing
  426. const Vector3 * getTintColor( void ) const; ///< get FX color value to add to ALL LIGHTS when drawing
  427. const Vector3 * getSelectionColor( void ) const; ///< get FX color value to add to ALL LIGHTS when drawing
  428. inline TerrainDecalType getTerrainDecalType( void ) const { return m_terrainDecalType; }
  429. inline void setDrawableOpacity( Real value ) { m_explicitOpacity = value; } ///< set alpha/opacity value used to override defaults when drawing.
  430. // note that this is not the 'get' inverse of setDrawableOpacity, since stealthing can also affect the effective opacity!
  431. inline Real getEffectiveOpacity() const { return m_explicitOpacity * m_effectiveStealthOpacity; } ///< get alpha/opacity value used to override defaults when drawing.
  432. void setEffectiveOpacity( Real pulseFactor, Real explicitOpacity = -1.0f );
  433. // this is for the add'l pass fx which operates completely independently of the stealth opacity effects. Draw() does the fading every frame.
  434. inline Real getSecondMaterialPassOpacity() const { return m_secondMaterialPassOpacity; } ///< get alpha/opacity value used to render add'l rendering pass.
  435. void setSecondMaterialPassOpacity( Real op ) { m_secondMaterialPassOpacity = op; }; ///< set alpha/opacity value used to render add'l rendering pass.
  436. // both of these assume that you are starting at one extreme 100% or 0% opacity and are trying to go to the other!! -- amit
  437. void fadeOut( UnsignedInt frames ); ///< fade object out...how gradually this is done is determined by frames
  438. void fadeIn( UnsignedInt frames ); ///< fade object in...how gradually this is done is determined by frames
  439. void preloadAssets( TimeOfDay timeOfDay ); ///< preload the assets
  440. Bool isVisible(); ///< for limiting tree sway, etc to visible objects
  441. Bool getShouldAnimate( Bool considerPower ) const;
  442. // flash drawable methods ---------------------------------------------------------
  443. Int getFlashCount( void ) { return m_flashCount; }
  444. void setFlashCount( Int count ) { m_flashCount = count; }
  445. void setFlashColor( Color color ) { m_flashColor = color; }
  446. void saturateRGB(RGBColor& color, Real factor);// not strictly for flash color, but it is the only practical use for this
  447. //---------------------------------------------------------------------------------
  448. // caption text methods -----------------------------------------------------------
  449. void setCaptionText( const UnicodeString& captionText );
  450. void clearCaptionText( void );
  451. UnicodeString getCaptionText( void );
  452. //---------------------------------------------------------------------------------
  453. DrawableIconInfo* getIconInfo(); ///< lazily allocates, if necessary
  454. void killIcon(DrawableIconType t) { if (m_iconInfo) m_iconInfo->killIcon(t); }
  455. Bool hasIconInfo() const { return m_iconInfo != NULL; }
  456. Bool getReceivesDynamicLights( void ) { return m_receivesDynamicLights; };
  457. void setReceivesDynamicLights( Bool set ) { m_receivesDynamicLights = set; };
  458. //---------------------------------------------------------------------------------
  459. // Stuff for overriding ambient sound
  460. const AudioEventInfo * getBaseSoundAmbientInfo() const; //< Possible starting point if only some parameters are customized
  461. void enableAmbientSoundFromScript( Bool enable );
  462. const AudioEventRTS * getAmbientSound() const { return m_ambientSound == NULL ? NULL : &m_ambientSound->m_event; }
  463. void setCustomSoundAmbientOff(); //< Kill the ambient sound
  464. void setCustomSoundAmbientInfo( DynamicAudioEventInfo * customAmbientInfo ); //< Set ambient sound.
  465. void clearCustomSoundAmbient( ) { clearCustomSoundAmbient( true ); } //< Return to using defaults
  466. Bool getAmbientSoundEnabled( void ) const { return m_ambientSoundEnabled; }
  467. void mangleCustomAudioName( DynamicAudioEventInfo * audioToMangle ) const;
  468. Real friend_getStealthOpacity( void ) { return m_stealthOpacity; }
  469. Real friend_getExplicitOpacity( void ) { return m_explicitOpacity; }
  470. Real friend_getEffectiveStealthOpacity( void ) { return m_effectiveStealthOpacity; }
  471. protected:
  472. // snapshot methods
  473. virtual void crc( Xfer *xfer );
  474. virtual void xfer( Xfer *xfer );
  475. virtual void loadPostProcess( void );
  476. void xferDrawableModules( Xfer *xfer );
  477. void startAmbientSound( BodyDamageType dt, TimeOfDay tod, Bool onlyIfPermanent = false );
  478. Drawable *asDrawableMeth() { return this; }
  479. const Drawable *asDrawableMeth() const { return this; }
  480. inline Module** getModuleList(ModuleType i)
  481. {
  482. Module** m = m_modules[i - FIRST_DRAWABLE_MODULE_TYPE];
  483. return m;
  484. }
  485. inline Module* const* getModuleList(ModuleType i) const
  486. {
  487. Module** m = m_modules[i - FIRST_DRAWABLE_MODULE_TYPE];
  488. return m;
  489. }
  490. void applyPhysicsXform(Matrix3D* mtx);
  491. struct PhysicsXformInfo
  492. {
  493. Real m_totalPitch; ///< Current total pitch for this frame.
  494. Real m_totalRoll; ///< Current total roll for this frame.
  495. Real m_totalYaw; ///< Current total yaw for this frame
  496. Real m_totalZ;
  497. PhysicsXformInfo() : m_totalPitch(0), m_totalRoll(0), m_totalYaw(0), m_totalZ(0) { }
  498. };
  499. Bool calcPhysicsXform(PhysicsXformInfo& info);
  500. void calcPhysicsXformThrust(const Locomotor *locomotor, PhysicsXformInfo& info);
  501. void calcPhysicsXformHoverOrWings(const Locomotor *locomotor, PhysicsXformInfo& info);
  502. void calcPhysicsXformTreads(const Locomotor *locomotor, PhysicsXformInfo& info);
  503. void calcPhysicsXformWheels(const Locomotor *locomotor, PhysicsXformInfo& info);
  504. void calcPhysicsXformMotorcycle( const Locomotor *locomotor, PhysicsXformInfo& info );
  505. const AudioEventRTS& getAmbientSoundByDamage(BodyDamageType dt);
  506. void clearCustomSoundAmbient( bool restartSound ); //< Return to using defaults
  507. #ifdef _DEBUG
  508. void validatePos() const;
  509. #endif
  510. virtual void reactToTransformChange(const Matrix3D* oldMtx, const Coord3D* oldPos, Real oldAngle);
  511. void updateHiddenStatus();
  512. private:
  513. // note, these are lazily allocated!
  514. TintEnvelope* m_selectionFlashEnvelope; ///< used for selection flash, works WITH m_colorTintEnvelope
  515. TintEnvelope* m_colorTintEnvelope; ///< house color flashing, etc... works WITH m_selectionFlashEnvelope
  516. // this used to use m_ambientLight... but this replaces it
  517. // int most places. It works harder to change the drawable's
  518. // color, by tinting all four scene lights, not just ambient
  519. // zero = no effect
  520. // 1 = full effect
  521. TerrainDecalType m_terrainDecalType; ///<current decal in use by m_terrainDecal
  522. Real m_explicitOpacity; ///< opacity level. 1.0f == Solid/Opaque.
  523. Real m_stealthOpacity; ///< <<minimum>> opacity due to stealth. pulse is between opaque and this
  524. Real m_effectiveStealthOpacity; ///< opacity actually used to render with, after the pulse and stuff.
  525. Real m_decalOpacityFadeTarget;
  526. Real m_decalOpacityFadeRate;
  527. Real m_decalOpacity;
  528. Object *m_object; ///< object (if any) that this drawable represents
  529. DrawableID m_id; ///< this drawable's unique ID
  530. Drawable *m_nextDrawable;
  531. Drawable *m_prevDrawable; ///< list links
  532. DynamicAudioEventInfo *m_customSoundAmbientInfo; ///< If not NULL, info about the ambient sound to attach to this object
  533. UnsignedInt m_status; ///< status bits (see DrawableStatus enum)
  534. UnsignedInt m_tintStatus; ///< tint color status bits (see TintStatus enum)
  535. UnsignedInt m_prevTintStatus;///< for edge testing with m_tintStatus
  536. enum FadingMode
  537. {
  538. FADING_NONE,
  539. FADING_IN,
  540. FADING_OUT
  541. };
  542. FadingMode m_fadeMode;
  543. UnsignedInt m_timeElapsedFade; ///< for how many frames have i been fading
  544. UnsignedInt m_timeToFade; ///< how slowly am I fading
  545. UnsignedInt m_shroudClearFrame; ///< Last frame the local player saw this drawable "OBJECTSHROUD_CLEAR"
  546. DrawableLocoInfo* m_locoInfo; // lazily allocated
  547. DynamicAudioEventRTS* m_ambientSound; ///< sound module for ambient sound (lazily allocated)
  548. Module** m_modules[NUM_DRAWABLE_MODULE_TYPES];
  549. StealthLookType m_stealthLook;
  550. Int m_flashCount; ///< number of times to flash the drawable
  551. Color m_flashColor; ///< color to flash the drawable
  552. Matrix3D m_instance; ///< The instance matrix that holds the initial/default position & orientation
  553. Real m_instanceScale; ///< the uniform scale factor applied to the instance matrix before it is sent to W3D.
  554. DrawableInfo m_drawableInfo; ///< structure pointed to by W3D render objects so they know which drawable they belong to.
  555. ModelConditionFlags m_conditionState; ///< The Drawables current behavior state
  556. Real m_lastConstructDisplayed; ///< last construct percent used to make the string
  557. DisplayString* m_constructDisplayString; ///< string to display construction % complete
  558. DisplayString* m_captionDisplayString; ///< string to display caption
  559. DisplayString* m_groupNumber; ///< string to display the group number of this drawable
  560. UnsignedInt m_expirationDate; ///< if nonzero, Drawable should destroy itself at this frame
  561. DrawableIconInfo* m_iconInfo; ///< lazily allocated!
  562. Real m_secondMaterialPassOpacity; ///< drawable gets rendered again in hardware with an extra material layer
  563. // --------- BYTE-SIZED THINGS GO HERE
  564. Byte m_selected; ///< drawable is selected or not
  565. Bool m_hidden; ///< drawable is "hidden" or not (overrides stealth effects)
  566. Bool m_hiddenByStealth; ///< drawable is hidden due to stealth
  567. Bool m_instanceIsIdentity; ///< If true, instance matrix can be skipped
  568. Bool m_drawableFullyObscuredByShroud; ///<drawable is hidden by shroud/fog
  569. Bool m_ambientSoundEnabled;
  570. Bool m_ambientSoundEnabledFromScript;
  571. Bool m_receivesDynamicLights;
  572. #ifdef DIRTY_CONDITION_FLAGS
  573. mutable Bool m_isModelDirty; ///< if true, must call replaceModelConditionState() before drawing or accessing drawmodule info
  574. #endif
  575. //*******************************************
  576. //Perhaps we can move this out of Drawable???
  577. public:
  578. static void killStaticImages();
  579. #ifdef DIRTY_CONDITION_FLAGS
  580. // only for StDrawableDirtyStuffLocker!
  581. static void friend_lockDirtyStuffForIteration();
  582. static void friend_unlockDirtyStuffForIteration();
  583. #endif
  584. //For now, you can only have one emoticon at a time. Changing it will clear the previous one.
  585. void clearEmoticon();
  586. void setEmoticon( const AsciiString &name, Int duration );
  587. void drawUIText( void ); ///< draw the group number of this unit // public so gameclient can call
  588. private:
  589. // "icon" drawing methods **************
  590. void drawConstructPercent( const IRegion2D *healthBarRegion ); ///< display % construction complete
  591. void drawCaption( const IRegion2D *healthBarRegion ); ///< draw caption
  592. void drawAmmo( const IRegion2D *healthBarRegion ); ///< draw icons
  593. void drawContained( const IRegion2D *healthBarRegion ); ///< draw icons
  594. void drawVeterancy( const IRegion2D *healthBarRegion ); ///< draw veterency information
  595. void drawEmoticon( const IRegion2D* healthBarRegion );
  596. void drawHealthBar( const IRegion2D* healthBarRegion ); ///< draw heath bar
  597. void drawHealing( const IRegion2D* healthBarRegion ); ///< draw icons
  598. void drawEnthusiastic( const IRegion2D* healthBarRegin ); ///< draw icons
  599. #ifdef ALLOW_DEMORALIZE
  600. void drawDemoralized( const IRegion2D* healthBarRegion ); ///< draw icons
  601. #endif
  602. void drawBombed( const IRegion2D* healthBarRegion ); ///< draw icons
  603. void drawDisabled( const IRegion2D* healthBarRegion ); ///< draw icons
  604. void drawBattlePlans( const IRegion2D* healthBarRegion ); ///< Icons rendering for active battle plan statii
  605. Bool drawsAnyUIText( void );
  606. static Bool s_staticImagesInited;
  607. static const Image* s_veterancyImage[LEVEL_COUNT];
  608. static const Image* s_fullAmmo;
  609. static const Image* s_emptyAmmo;
  610. static const Image* s_fullContainer;
  611. static const Image* s_emptyContainer;
  612. static Anim2DTemplate** s_animationTemplates;
  613. #ifdef DIRTY_CONDITION_FLAGS
  614. static Int s_modelLockCount;
  615. #endif
  616. static void initStaticImages();
  617. //*******************************************
  618. };
  619. #ifdef DIRTY_CONDITION_FLAGS
  620. class StDrawableDirtyStuffLocker
  621. {
  622. public:
  623. StDrawableDirtyStuffLocker()
  624. {
  625. Drawable::friend_lockDirtyStuffForIteration();
  626. }
  627. ~StDrawableDirtyStuffLocker()
  628. {
  629. Drawable::friend_unlockDirtyStuffForIteration();
  630. }
  631. };
  632. #endif
  633. #endif // _DRAWABLE_H_