| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- /*
- ** Command & Conquer Generals Zero Hour(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program is free software: you can redistribute it and/or modify
- ** it under the terms of the GNU General Public License as published by
- ** the Free Software Foundation, either version 3 of the License, or
- ** (at your option) any later version.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- ////////////////////////////////////////////////////////////////////////////////
- // //
- // (c) 2001-2003 Electronic Arts Inc. //
- // //
- ////////////////////////////////////////////////////////////////////////////////
- // FILE: BunkerBusterBehavior.cpp ////////////////////////////////////////////////////////////////
- // Author: Mark Lorenzen, June 2003
- // Desc: Behavior module for Bunker Buster... it kills garrisoned objects
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
- #include "PreRTS.h"
- #include "Common/Upgrade.h"
- #include "Common/Player.h"
- #include "Common/Xfer.h"
- #include "GameLogic/Module/BunkerBusterBehavior.h"
- #include "GameLogic/Module/ContainModule.h"
- #include "GameLogic/Module/AIUpdate.h"
- #include "GameLogic/GameLogic.h"
- #include "GameLogic/Object.h"
- #include "GameLogic/Weapon.h"
- #include "GameClient/TerrainVisual.h"//Seismic simulations!
- #ifdef _INTERNAL
- // for occasional debugging...
- //#pragma optimize("", off)
- //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
- #endif
- static DomeStyleSeismicFilter bunkerBusterHeavingEarthSeismicFilter;
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- BunkerBusterBehaviorModuleData::BunkerBusterBehaviorModuleData( void )
- {
- m_upgradeRequired = NULL;
- m_detonationFX = NULL;
- m_crashThroughBunkerFX = NULL;
- m_crashThroughBunkerFXFrequency = 4;
-
- m_seismicEffectRadius = 140.0f;
- m_seismicEffectMagnitude = 6.0f;
- m_shockwaveWeaponTemplate = NULL;
- m_occupantDamageWeaponTemplate = NULL;
- } // end BunkerBusterBehaviorModuleData
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- /*static*/ void BunkerBusterBehaviorModuleData::buildFieldParse( MultiIniFieldParse &p )
- {
- UpdateModuleData::buildFieldParse( p );
- static const FieldParse dataFieldParse[] =
- {
- { "UpgradeRequired", INI::parseAsciiString, NULL, offsetof( BunkerBusterBehaviorModuleData, m_upgradeRequired ) },
- { "DetonationFX", INI::parseFXList, NULL, offsetof( BunkerBusterBehaviorModuleData, m_detonationFX ) },
- { "CrashThroughBunkerFX", INI::parseFXList, NULL, offsetof( BunkerBusterBehaviorModuleData, m_crashThroughBunkerFX ) },
- { "CrashThroughBunkerFXFrequency", INI::parseDurationUnsignedInt, NULL, offsetof( BunkerBusterBehaviorModuleData, m_crashThroughBunkerFXFrequency ) },
- { "SeismicEffectRadius", INI::parseReal, NULL, offsetof( BunkerBusterBehaviorModuleData, m_seismicEffectRadius ) },
- { "SeismicEffectMagnitude", INI::parseReal, NULL, offsetof( BunkerBusterBehaviorModuleData, m_seismicEffectMagnitude ) },
- { "ShockwaveWeaponTemplate", INI::parseWeaponTemplate, NULL, offsetof( BunkerBusterBehaviorModuleData, m_shockwaveWeaponTemplate ) },
- { "OccupantDamageWeaponTemplate", INI::parseWeaponTemplate, NULL, offsetof( BunkerBusterBehaviorModuleData, m_occupantDamageWeaponTemplate ) },
- { 0, 0, 0, 0 }
- };
- p.add( dataFieldParse );
- } // end buildFieldParse
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- BunkerBusterBehavior::BunkerBusterBehavior( Thing *thing, const ModuleData *modData )
- : UpdateModule( thing, modData )
- {
- // THIS HAS AN UPDATE... BECAUSE I FORSEE THE NEED FOR ONE, BUT RIGHT NOW IT DOES NOTHING
- setWakeFrame( getObject(), UPDATE_SLEEP_NONE );
- m_victimID = INVALID_ID;
- m_upgradeRequired = NULL;
- } // end BunkerBusterBehavior
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- BunkerBusterBehavior::~BunkerBusterBehavior( void )
- {
- } // end ~BunkerBusterBehavior
- void BunkerBusterBehavior::onObjectCreated( void )
- {
- const BunkerBusterBehaviorModuleData *modData = getBunkerBusterBehaviorModuleData();
- // convert module upgrade name to a pointer
- m_upgradeRequired = TheUpgradeCenter->findUpgrade( modData->m_upgradeRequired );
- } // end onObjectCreated
- // ------------------------------------------------------------------------------------------------
- /** The update callback */
- // ------------------------------------------------------------------------------------------------
- UpdateSleepTime BunkerBusterBehavior::update( void )
- {
- const BunkerBusterBehaviorModuleData *modData = getBunkerBusterBehaviorModuleData();
- AIUpdateInterface *ai = getObject()->getAI();
- if ( ai )// is this a SMART bomb?
- {
- if ( m_victimID == INVALID_ID )
- {
- Object *victim = ai->getCurrentVictim();
- if ( victim )
- m_victimID = victim->getID();
- DEBUG_ASSERTCRASH( victim, ("BunkerBusterBehavior::update... AIUpdateInterface reports no victim." ) );
- }
- DEBUG_ASSERTCRASH( ai, ("BunkerBusterBehavior::update could not find an AIUpdateInterface." ) );
- if ( TheGameLogic->getFrame()%modData->m_crashThroughBunkerFXFrequency == 1 )// not too much
- {
- const FXList *crashFX = modData->m_crashThroughBunkerFX;
- if ( getObject()->testStatus( OBJECT_STATUS_MISSILE_KILLING_SELF ) && crashFX )
- FXList::doFXObj( crashFX, getObject() );// CrashFX done on the missile/bomb
- }
-
- }
-
- return UPDATE_SLEEP_NONE;
- } // end update
- // ------------------------------------------------------------------------------------------------
- /** The death callback */
- // ------------------------------------------------------------------------------------------------
- void BunkerBusterBehavior::onDie( const DamageInfo *damageInfo )
- {
- // do what we came here to do!
- bustTheBunker();
- }
- // ------------------------------------------------------------------------------------------------
- /** The bunker-busting effect callback */
- // ------------------------------------------------------------------------------------------------
- void BunkerBusterBehavior::bustTheBunker( void )
- {
- const BunkerBusterBehaviorModuleData *modData = getBunkerBusterBehaviorModuleData();
- if ( m_upgradeRequired != NULL )
- {
- Bool weaponUpgraded = getObject()->getControllingPlayer()->hasUpgradeComplete( m_upgradeRequired );
- if ( ! weaponUpgraded )
- return;
- }
-
- // here is where we kill everyone inside any targeted garrisoned buildings
- // AIUpdateInterface *ai = getObject()->getAI();
- Object *target = TheGameLogic->findObjectByID( m_victimID );
- Object *objectForFX = getObject();
- if ( target ) // Was the pilot aiming at an object?
- {
- objectForFX = target;
- ContainModuleInterface *contain = target->getContain();
- if ( contain && contain->isBustable() ) // Was that object something that bunkerbusters bust?
- {
- if ( modData->m_occupantDamageWeaponTemplate )
- {
- DamageInfo damageInfo;
- damageInfo.in.m_damageType = modData->m_occupantDamageWeaponTemplate->getDamageType();
- damageInfo.in.m_deathType = modData->m_occupantDamageWeaponTemplate->getDeathType();
- damageInfo.in.m_sourceID = getObject()->getID();
- damageInfo.in.m_sourcePlayerMask = getObject()->getControllingPlayer()->getPlayerMask();
- damageInfo.in.m_amount = 100.0f;
- contain->harmAndForceExitAllContained( &damageInfo ); // Ouch!
- }
- else
- contain->killAllContained();
- }
- }
- const FXList *detonationFX = modData->m_detonationFX;
- if ( detonationFX )
- FXList::doFXObj( detonationFX, objectForFX );//DetonationFX done on the building
- #ifdef DO_SEISMIC_SIMULATIONS
- // Okay, the right proper way to do this is to add SeismicSim support to FXList...
- // But until that day, I'm just gonna do it here, sorry, M Lorenzen 6/26/03
- SeismicSimulationNode sim(
- objectForFX->getPosition(),
- modData->m_seismicEffectRadius,
- modData->m_seismicEffectMagnitude,
- &bunkerBusterHeavingEarthSeismicFilter );
- TheTerrainVisual->addSeismicSimulation( sim );
- #endif
- if ( modData->m_shockwaveWeaponTemplate )
- TheWeaponStore->createAndFireTempWeapon(modData->m_shockwaveWeaponTemplate, objectForFX, objectForFX->getPosition());
- } // end onDie
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- /** CRC */
- // ------------------------------------------------------------------------------------------------
- void BunkerBusterBehavior::crc( Xfer *xfer )
- {
- // extend base class
- UpdateModule::crc( xfer );
- } // end crc
- // ------------------------------------------------------------------------------------------------
- /** Xfer method
- * Version Info:
- * 1: Initial version */
- // ------------------------------------------------------------------------------------------------
- void BunkerBusterBehavior::xfer( Xfer *xfer )
- {
- // version
- XferVersion currentVersion = 1;
- XferVersion version = currentVersion;
- xfer->xferVersion( &version, currentVersion );
- // extend base class
- UpdateModule::xfer( xfer );
- } // end xfer
- // ------------------------------------------------------------------------------------------------
- /** Load post process */
- // ------------------------------------------------------------------------------------------------
- void BunkerBusterBehavior::loadPostProcess( void )
- {
- // extend base class
- UpdateModule::loadPostProcess();
- } // end loadPostProcess
|