BunkerBusterBehavior.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  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: BunkerBusterBehavior.cpp ////////////////////////////////////////////////////////////////
  24. // Author: Mark Lorenzen, June 2003
  25. // Desc: Behavior module for Bunker Buster... it kills garrisoned objects
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. // INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
  28. #include "PreRTS.h"
  29. #include "Common/Upgrade.h"
  30. #include "Common/Player.h"
  31. #include "Common/Xfer.h"
  32. #include "GameLogic/Module/BunkerBusterBehavior.h"
  33. #include "GameLogic/Module/ContainModule.h"
  34. #include "GameLogic/Module/AIUpdate.h"
  35. #include "GameLogic/GameLogic.h"
  36. #include "GameLogic/Object.h"
  37. #include "GameLogic/Weapon.h"
  38. #include "GameClient/TerrainVisual.h"//Seismic simulations!
  39. #ifdef _INTERNAL
  40. // for occasional debugging...
  41. //#pragma optimize("", off)
  42. //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
  43. #endif
  44. static DomeStyleSeismicFilter bunkerBusterHeavingEarthSeismicFilter;
  45. // ------------------------------------------------------------------------------------------------
  46. // ------------------------------------------------------------------------------------------------
  47. BunkerBusterBehaviorModuleData::BunkerBusterBehaviorModuleData( void )
  48. {
  49. m_upgradeRequired = NULL;
  50. m_detonationFX = NULL;
  51. m_crashThroughBunkerFX = NULL;
  52. m_crashThroughBunkerFXFrequency = 4;
  53. m_seismicEffectRadius = 140.0f;
  54. m_seismicEffectMagnitude = 6.0f;
  55. m_shockwaveWeaponTemplate = NULL;
  56. m_occupantDamageWeaponTemplate = NULL;
  57. } // end BunkerBusterBehaviorModuleData
  58. // ------------------------------------------------------------------------------------------------
  59. // ------------------------------------------------------------------------------------------------
  60. /*static*/ void BunkerBusterBehaviorModuleData::buildFieldParse( MultiIniFieldParse &p )
  61. {
  62. UpdateModuleData::buildFieldParse( p );
  63. static const FieldParse dataFieldParse[] =
  64. {
  65. { "UpgradeRequired", INI::parseAsciiString, NULL, offsetof( BunkerBusterBehaviorModuleData, m_upgradeRequired ) },
  66. { "DetonationFX", INI::parseFXList, NULL, offsetof( BunkerBusterBehaviorModuleData, m_detonationFX ) },
  67. { "CrashThroughBunkerFX", INI::parseFXList, NULL, offsetof( BunkerBusterBehaviorModuleData, m_crashThroughBunkerFX ) },
  68. { "CrashThroughBunkerFXFrequency", INI::parseDurationUnsignedInt, NULL, offsetof( BunkerBusterBehaviorModuleData, m_crashThroughBunkerFXFrequency ) },
  69. { "SeismicEffectRadius", INI::parseReal, NULL, offsetof( BunkerBusterBehaviorModuleData, m_seismicEffectRadius ) },
  70. { "SeismicEffectMagnitude", INI::parseReal, NULL, offsetof( BunkerBusterBehaviorModuleData, m_seismicEffectMagnitude ) },
  71. { "ShockwaveWeaponTemplate", INI::parseWeaponTemplate, NULL, offsetof( BunkerBusterBehaviorModuleData, m_shockwaveWeaponTemplate ) },
  72. { "OccupantDamageWeaponTemplate", INI::parseWeaponTemplate, NULL, offsetof( BunkerBusterBehaviorModuleData, m_occupantDamageWeaponTemplate ) },
  73. { 0, 0, 0, 0 }
  74. };
  75. p.add( dataFieldParse );
  76. } // end buildFieldParse
  77. ///////////////////////////////////////////////////////////////////////////////////////////////////
  78. ///////////////////////////////////////////////////////////////////////////////////////////////////
  79. ///////////////////////////////////////////////////////////////////////////////////////////////////
  80. // ------------------------------------------------------------------------------------------------
  81. // ------------------------------------------------------------------------------------------------
  82. BunkerBusterBehavior::BunkerBusterBehavior( Thing *thing, const ModuleData *modData )
  83. : UpdateModule( thing, modData )
  84. {
  85. // THIS HAS AN UPDATE... BECAUSE I FORSEE THE NEED FOR ONE, BUT RIGHT NOW IT DOES NOTHING
  86. setWakeFrame( getObject(), UPDATE_SLEEP_NONE );
  87. m_victimID = INVALID_ID;
  88. m_upgradeRequired = NULL;
  89. } // end BunkerBusterBehavior
  90. // ------------------------------------------------------------------------------------------------
  91. // ------------------------------------------------------------------------------------------------
  92. BunkerBusterBehavior::~BunkerBusterBehavior( void )
  93. {
  94. } // end ~BunkerBusterBehavior
  95. void BunkerBusterBehavior::onObjectCreated( void )
  96. {
  97. const BunkerBusterBehaviorModuleData *modData = getBunkerBusterBehaviorModuleData();
  98. // convert module upgrade name to a pointer
  99. m_upgradeRequired = TheUpgradeCenter->findUpgrade( modData->m_upgradeRequired );
  100. } // end onObjectCreated
  101. // ------------------------------------------------------------------------------------------------
  102. /** The update callback */
  103. // ------------------------------------------------------------------------------------------------
  104. UpdateSleepTime BunkerBusterBehavior::update( void )
  105. {
  106. const BunkerBusterBehaviorModuleData *modData = getBunkerBusterBehaviorModuleData();
  107. AIUpdateInterface *ai = getObject()->getAI();
  108. if ( ai )// is this a SMART bomb?
  109. {
  110. if ( m_victimID == INVALID_ID )
  111. {
  112. Object *victim = ai->getCurrentVictim();
  113. if ( victim )
  114. m_victimID = victim->getID();
  115. DEBUG_ASSERTCRASH( victim, ("BunkerBusterBehavior::update... AIUpdateInterface reports no victim." ) );
  116. }
  117. DEBUG_ASSERTCRASH( ai, ("BunkerBusterBehavior::update could not find an AIUpdateInterface." ) );
  118. if ( TheGameLogic->getFrame()%modData->m_crashThroughBunkerFXFrequency == 1 )// not too much
  119. {
  120. const FXList *crashFX = modData->m_crashThroughBunkerFX;
  121. if ( getObject()->testStatus( OBJECT_STATUS_MISSILE_KILLING_SELF ) && crashFX )
  122. FXList::doFXObj( crashFX, getObject() );// CrashFX done on the missile/bomb
  123. }
  124. }
  125. return UPDATE_SLEEP_NONE;
  126. } // end update
  127. // ------------------------------------------------------------------------------------------------
  128. /** The death callback */
  129. // ------------------------------------------------------------------------------------------------
  130. void BunkerBusterBehavior::onDie( const DamageInfo *damageInfo )
  131. {
  132. // do what we came here to do!
  133. bustTheBunker();
  134. }
  135. // ------------------------------------------------------------------------------------------------
  136. /** The bunker-busting effect callback */
  137. // ------------------------------------------------------------------------------------------------
  138. void BunkerBusterBehavior::bustTheBunker( void )
  139. {
  140. const BunkerBusterBehaviorModuleData *modData = getBunkerBusterBehaviorModuleData();
  141. if ( m_upgradeRequired != NULL )
  142. {
  143. Bool weaponUpgraded = getObject()->getControllingPlayer()->hasUpgradeComplete( m_upgradeRequired );
  144. if ( ! weaponUpgraded )
  145. return;
  146. }
  147. // here is where we kill everyone inside any targeted garrisoned buildings
  148. // AIUpdateInterface *ai = getObject()->getAI();
  149. Object *target = TheGameLogic->findObjectByID( m_victimID );
  150. Object *objectForFX = getObject();
  151. if ( target ) // Was the pilot aiming at an object?
  152. {
  153. objectForFX = target;
  154. ContainModuleInterface *contain = target->getContain();
  155. if ( contain && contain->isBustable() ) // Was that object something that bunkerbusters bust?
  156. {
  157. if ( modData->m_occupantDamageWeaponTemplate )
  158. {
  159. DamageInfo damageInfo;
  160. damageInfo.in.m_damageType = modData->m_occupantDamageWeaponTemplate->getDamageType();
  161. damageInfo.in.m_deathType = modData->m_occupantDamageWeaponTemplate->getDeathType();
  162. damageInfo.in.m_sourceID = getObject()->getID();
  163. damageInfo.in.m_sourcePlayerMask = getObject()->getControllingPlayer()->getPlayerMask();
  164. damageInfo.in.m_amount = 100.0f;
  165. contain->harmAndForceExitAllContained( &damageInfo ); // Ouch!
  166. }
  167. else
  168. contain->killAllContained();
  169. }
  170. }
  171. const FXList *detonationFX = modData->m_detonationFX;
  172. if ( detonationFX )
  173. FXList::doFXObj( detonationFX, objectForFX );//DetonationFX done on the building
  174. #ifdef DO_SEISMIC_SIMULATIONS
  175. // Okay, the right proper way to do this is to add SeismicSim support to FXList...
  176. // But until that day, I'm just gonna do it here, sorry, M Lorenzen 6/26/03
  177. SeismicSimulationNode sim(
  178. objectForFX->getPosition(),
  179. modData->m_seismicEffectRadius,
  180. modData->m_seismicEffectMagnitude,
  181. &bunkerBusterHeavingEarthSeismicFilter );
  182. TheTerrainVisual->addSeismicSimulation( sim );
  183. #endif
  184. if ( modData->m_shockwaveWeaponTemplate )
  185. TheWeaponStore->createAndFireTempWeapon(modData->m_shockwaveWeaponTemplate, objectForFX, objectForFX->getPosition());
  186. } // end onDie
  187. // ------------------------------------------------------------------------------------------------
  188. // ------------------------------------------------------------------------------------------------
  189. /** CRC */
  190. // ------------------------------------------------------------------------------------------------
  191. void BunkerBusterBehavior::crc( Xfer *xfer )
  192. {
  193. // extend base class
  194. UpdateModule::crc( xfer );
  195. } // end crc
  196. // ------------------------------------------------------------------------------------------------
  197. /** Xfer method
  198. * Version Info:
  199. * 1: Initial version */
  200. // ------------------------------------------------------------------------------------------------
  201. void BunkerBusterBehavior::xfer( Xfer *xfer )
  202. {
  203. // version
  204. XferVersion currentVersion = 1;
  205. XferVersion version = currentVersion;
  206. xfer->xferVersion( &version, currentVersion );
  207. // extend base class
  208. UpdateModule::xfer( xfer );
  209. } // end xfer
  210. // ------------------------------------------------------------------------------------------------
  211. /** Load post process */
  212. // ------------------------------------------------------------------------------------------------
  213. void BunkerBusterBehavior::loadPostProcess( void )
  214. {
  215. // extend base class
  216. UpdateModule::loadPostProcess();
  217. } // end loadPostProcess