| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584 |
- /*
- ** 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: SlowDeathBehavior.cpp ///////////////////////////////////////////////////////////////////////
- // Author:
- // Desc:
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
- #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
- #define DEFINE_SLOWDEATHPHASE_NAMES
- #include "Common/GameLOD.h"
- #include "Common/INI.h"
- #include "Common/RandomValue.h"
- #include "Common/Thing.h"
- #include "Common/ThingTemplate.h"
- #include "Common/Xfer.h"
- #include "GameClient/Drawable.h"
- #include "GameClient/FXList.h"
- #include "GameClient/InGameUI.h"
- #include "GameLogic/GameLogic.h"
- #include "GameLogic/Module/BodyModule.h"
- #include "GameLogic/Module/PhysicsUpdate.h"
- #include "GameLogic/Module/SlowDeathBehavior.h"
- #include "GameLogic/Module/AIUpdate.h"
- #include "GameLogic/Module/SlavedUpdate.h"
- #include "GameLogic/Object.h"
- #include "GameLogic/ObjectCreationList.h"
- #include "GameLogic/Weapon.h"
- #include "GameClient/Drawable.h"
- #ifdef _INTERNAL
- // for occasional debugging...
- //#pragma optimize("", off)
- //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
- #endif
- const Real BEGIN_MIDPOINT_RATIO = 0.35f;
- const Real END_MIDPOINT_RATIO = 0.65f;
- //-------------------------------------------------------------------------------------------------
- SlowDeathBehaviorModuleData::SlowDeathBehaviorModuleData()
- {
- m_sinkRate = 0;
- m_probabilityModifier = 10;
- m_modifierBonusPerOverkillPercent = 0;
- m_sinkDelay = 0;
- m_sinkDelayVariance = 0;
- m_destructionDelay = 0;
- m_destructionDelayVariance = 0;
- m_destructionAltitude = -10;
- m_maskOfLoadedEffects = 0; //assume no ocl, fx, or weapons.
- m_flingForce = 0;
- m_flingForceVariance = 0;
- m_flingPitch = 0;
- m_flingPitchVariance = 0;
- // redundant.
- //m_fx.clear();
- //m_ocls.clear();
- //m_weapons.clear();
- }
- //-------------------------------------------------------------------------------------------------
- static void parseFX( INI* ini, void *instance, void * /*store*/, const void* /*userData*/ )
- {
- SlowDeathBehaviorModuleData* self = (SlowDeathBehaviorModuleData*)instance;
- SlowDeathPhaseType sdphase = (SlowDeathPhaseType)INI::scanIndexList(ini->getNextToken(), TheSlowDeathPhaseNames);
- for (const char* token = ini->getNextToken(); token != NULL; token = ini->getNextTokenOrNull())
- {
- const FXList *fxl = TheFXListStore->findFXList((token)); // could be null! this is OK!
- self->m_fx[sdphase].push_back(fxl);
- if (fxl)
- self->m_maskOfLoadedEffects |= SlowDeathBehaviorModuleData::HAS_FX;
- }
- }
- //-------------------------------------------------------------------------------------------------
- static void parseOCL( INI* ini, void *instance, void * /*store*/, const void* /*userData*/ )
- {
- SlowDeathBehaviorModuleData* self = (SlowDeathBehaviorModuleData*)instance;
- SlowDeathPhaseType sdphase = (SlowDeathPhaseType)INI::scanIndexList(ini->getNextToken(), TheSlowDeathPhaseNames);
- for (const char* token = ini->getNextToken(); token != NULL; token = ini->getNextTokenOrNull())
- {
- const ObjectCreationList *ocl = TheObjectCreationListStore->findObjectCreationList(token); // could be null! this is OK!
- self->m_ocls[sdphase].push_back(ocl);
- if (ocl)
- self->m_maskOfLoadedEffects |= SlowDeathBehaviorModuleData::HAS_OCL;
- }
- }
- //-------------------------------------------------------------------------------------------------
- static void parseWeapon( INI* ini, void *instance, void * /*store*/, const void* /*userData*/ )
- {
- SlowDeathBehaviorModuleData* self = (SlowDeathBehaviorModuleData*)instance;
- SlowDeathPhaseType sdphase = (SlowDeathPhaseType)INI::scanIndexList(ini->getNextToken(), TheSlowDeathPhaseNames);
- for (const char* token = ini->getNextToken(); token != NULL; token = ini->getNextTokenOrNull())
- {
- const WeaponTemplate *wt = TheWeaponStore->findWeaponTemplate(token); // could be null! this is OK!
- self->m_weapons[sdphase].push_back(wt);
- if (wt)
- self->m_maskOfLoadedEffects |= SlowDeathBehaviorModuleData::HAS_WEAPON;
- }
- }
- //-------------------------------------------------------------------------------------------------
- /*static*/ void SlowDeathBehaviorModuleData::buildFieldParse(MultiIniFieldParse& p)
- {
- UpdateModuleData::buildFieldParse(p);
- static const FieldParse dataFieldParse[] =
- {
- { "SinkRate", INI::parseVelocityReal, NULL, offsetof( SlowDeathBehaviorModuleData, m_sinkRate ) },
- { "ProbabilityModifier", INI::parseInt, NULL, offsetof( SlowDeathBehaviorModuleData, m_probabilityModifier ) },
- { "ModifierBonusPerOverkillPercent", INI::parsePercentToReal, NULL, offsetof( SlowDeathBehaviorModuleData, m_modifierBonusPerOverkillPercent ) },
- { "SinkDelay", INI::parseDurationUnsignedInt, NULL, offsetof( SlowDeathBehaviorModuleData, m_sinkDelay ) },
- { "SinkDelayVariance", INI::parseDurationUnsignedInt, NULL, offsetof( SlowDeathBehaviorModuleData, m_sinkDelayVariance ) },
- { "DestructionDelay", INI::parseDurationUnsignedInt, NULL, offsetof( SlowDeathBehaviorModuleData, m_destructionDelay ) },
- { "DestructionDelayVariance", INI::parseDurationUnsignedInt, NULL, offsetof( SlowDeathBehaviorModuleData, m_destructionDelayVariance ) },
- { "DestructionAltitude", INI::parseReal, NULL, offsetof( SlowDeathBehaviorModuleData, m_destructionAltitude ) },
- { "FX", parseFX, NULL, 0 },
- { "OCL", parseOCL, NULL, 0 },
- { "Weapon", parseWeapon, NULL, 0 },
- { "FlingForce", INI::parseReal, NULL, offsetof( SlowDeathBehaviorModuleData, m_flingForce) },
- { "FlingForceVariance", INI::parseReal, NULL, offsetof( SlowDeathBehaviorModuleData, m_flingForceVariance) },
- { "FlingPitch", INI::parseAngleReal, NULL, offsetof( SlowDeathBehaviorModuleData, m_flingPitch) },
- { "FlingPitchVariance", INI::parseAngleReal, NULL, offsetof( SlowDeathBehaviorModuleData, m_flingPitchVariance) },
- { 0, 0, 0, 0 }
- };
- p.add(dataFieldParse);
- p.add(DieMuxData::getFieldParse(), offsetof( SlowDeathBehaviorModuleData, m_dieMuxData ));
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- SlowDeathBehavior::SlowDeathBehavior( Thing *thing, const ModuleData* moduleData ) : UpdateModule( thing, moduleData )
- {
- m_flags = 0;
- m_sinkFrame = 0;
- m_midpointFrame = 0;
- m_destructionFrame = 0;
- m_acceleratedTimeScale = 1.0f;
- if (getSlowDeathBehaviorModuleData()->m_probabilityModifier < 1)
- {
- DEBUG_CRASH(("ProbabilityModifer must be >= 1.\n"));
- throw INI_INVALID_DATA;
- }
- setWakeFrame(getObject(), UPDATE_SLEEP_FOREVER);
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- SlowDeathBehavior::~SlowDeathBehavior( void )
- {
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- Int SlowDeathBehavior::getProbabilityModifier( const DamageInfo *damageInfo ) const
- {
- // Calculating how far past dead we were allows us to pick more spectacular deaths when
- // severly killed, and more sedate ones when only slightly killed.
- // eg ( 200 hp max, had 10 left, took 50 damage, 40 overkill, (40/200) * 100 = 20 overkill %)
- Int overkillDamage = damageInfo->out.m_actualDamageDealt - damageInfo->out.m_actualDamageClipped;
- Real overkillPercent = (float)overkillDamage / (float)getObject()->getBodyModule()->getMaxHealth();
- Int overkillModifier = overkillPercent * getSlowDeathBehaviorModuleData()->m_modifierBonusPerOverkillPercent;
- return max( getSlowDeathBehaviorModuleData()->m_probabilityModifier + overkillModifier, 1 );
- }
- //-------------------------------------------------------------------------------------------------
- static void calcRandomForce(Real minMag, Real maxMag, Real minPitch, Real maxPitch, Coord3D& force)
- {
- Real angle = GameLogicRandomValueReal(-PI, PI);
- Real pitch = GameLogicRandomValueReal(minPitch, maxPitch);
- Real mag = GameLogicRandomValueReal(minMag, maxMag);
- Matrix3D mtx(1);
- mtx.Scale(mag);
- mtx.Rotate_Z(angle);
- mtx.Rotate_Y(-pitch);
- Vector3 v = mtx.Get_X_Vector();
- force.x = v.X;
- force.y = v.Y;
- force.z = v.Z;
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- void SlowDeathBehavior::beginSlowDeath(const DamageInfo *damageInfo)
- {
- if (!isSlowDeathActivated())
- {
- const SlowDeathBehaviorModuleData* d = getSlowDeathBehaviorModuleData();
- Object* obj = getObject();
- if (d->m_sinkRate && obj->isKindOf(KINDOF_INFANTRY))
- {
- Drawable *draw = getObject()->getDrawable();
- if ( draw )
- {
- // this object sinks slowly after it dies so don't draw a
- // floating shadow decal on the ground above it.
- obj->getDrawable()->setShadowsEnabled(false);
- draw->setTerrainDecalFadeTarget( 0.0f, -0.2f );
- }
- }
-
- // Ask game detail manager if we need to speedup all deaths to improve performance
- Real timeScale = TheGameLODManager->getSlowDeathScale();
- m_acceleratedTimeScale = 1.0f; // assume normal death speed.
- if (timeScale == 0.0f && !d->hasNonLodEffects())
- {
- // Deaths happen instantly so just delete the object and return
- TheGameLogic->destroyObject(obj);
- return;
- }
- else
- {
- // timescale is some non-zero value so we may need to speed up death
- if( getObject()->isKindOf( KINDOF_HULK ) && TheGameLogic->getHulkMaxLifetimeOverride() != -1 )
- {
- //Scripts don't want hulks around, so start sinking immediately!
- m_sinkFrame = 1;
- m_midpointFrame = (LOGICFRAMES_PER_SECOND/2) + 1;
- m_destructionFrame = LOGICFRAMES_PER_SECOND + 1;
- m_acceleratedTimeScale = 1.0f;
- }
- else
- {
- m_sinkFrame = timeScale * (d->m_sinkDelay + GameLogicRandomValue(0, d->m_sinkDelayVariance));
- m_destructionFrame = timeScale * (d->m_destructionDelay + GameLogicRandomValue(0, d->m_destructionDelayVariance));
- m_midpointFrame = GameLogicRandomValue( BEGIN_MIDPOINT_RATIO * m_destructionFrame, END_MIDPOINT_RATIO * m_destructionFrame );
- m_acceleratedTimeScale = timeScale;
- }
- }
- UnsignedInt now = TheGameLogic->getFrame();
- if (d->m_flingForce > 0)
- {
-
- //Just in case this is a stingersoldier or other HELD object, lets set them free so they will fly
- // with their own physics during slow death
- if( obj->isDisabledByType( DISABLED_HELD ) )
- {
- static NameKeyType key_SlavedUpdate = NAMEKEY( "SlavedUpdate" );
- SlavedUpdate* slave = (SlavedUpdate*)obj->findUpdateModule( key_SlavedUpdate );
- if( slave )
- {
- slave->onSlaverDie( NULL );
- }
- }
- PhysicsBehavior* physics = obj->getPhysics();
- if (physics)
- {
- // make sure we are at least a bit above the ground
- const Real MIN_ALTITUDE = 1.0f;
- Real altitude = obj->getHeightAboveTerrain();
- if (altitude < MIN_ALTITUDE)
- {
- Coord3D pos = *obj->getPosition();
- pos.z += MIN_ALTITUDE;
- obj->setPosition(&pos);
- }
- Coord3D force;
- calcRandomForce(d->m_flingForce, d->m_flingForce + d->m_flingForceVariance,
- d->m_flingPitch, d->m_flingPitch + d->m_flingPitchVariance, force);
- physics->setAllowToFall(true);
- physics->applyForce(&force);
- physics->setExtraBounciness(-1.0); // we don't want this guy to bounce at all
- physics->setExtraFriction(-3 * SECONDS_PER_LOGICFRAME_REAL); // reduce his ground friction a bit
- physics->setAllowBouncing(true);
- Real orientation = atan2(force.y, force.x);
- physics->setAngles(orientation, 0, 0);
- obj->getDrawable()->setModelConditionState(MODELCONDITION_EXPLODED_FLAILING);
- m_flags |= (1<<FLUNG_INTO_AIR);
- }
- setWakeFrame(obj, UPDATE_SLEEP_NONE);
- }
- else
- {
- // we don't need to wake up immediately, but only when the first of these
- // counters wants to trigger....
- Int whenToWakeTime = m_sinkFrame;
- if (whenToWakeTime > m_destructionFrame)
- whenToWakeTime = m_destructionFrame;
- if (whenToWakeTime > m_midpointFrame)
- whenToWakeTime = m_midpointFrame;
- setWakeFrame(obj, UPDATE_SLEEP(whenToWakeTime));
- }
- m_sinkFrame += now;
- m_destructionFrame += now;
- m_midpointFrame += now;
- m_flags |= (1<<SLOW_DEATH_ACTIVATED);
- doPhaseStuff(SDPHASE_INITIAL);
- }
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- void SlowDeathBehavior::doPhaseStuff(SlowDeathPhaseType sdphase)
- {
- const SlowDeathBehaviorModuleData* d = getSlowDeathBehaviorModuleData();
- Int idx, listSize;
- if (!d->m_maskOfLoadedEffects)
- return; //has no ocl, fx, or weapons.
- listSize = d->m_fx[sdphase].size();
- if (listSize > 0)
- {
- idx = GameLogicRandomValue(0, listSize-1);
- const FXListVec& v = d->m_fx[sdphase];
- DEBUG_ASSERTCRASH(idx>=0&&idx<v.size(),("bad idx"));
- const FXList* fxl = v[idx];
- FXList::doFXObj(fxl, getObject(), NULL);
- }
- listSize = d->m_ocls[sdphase].size();
- if (listSize > 0)
- {
- idx = GameLogicRandomValue(0, listSize-1);
- const OCLVec& v = d->m_ocls[sdphase];
- DEBUG_ASSERTCRASH(idx>=0&&idx<v.size(),("bad idx"));
- const ObjectCreationList* ocl = v[idx];
- ObjectCreationList::create(ocl, getObject(), NULL);
- }
- listSize = d->m_weapons[sdphase].size();
- if (listSize > 0)
- {
- idx = GameLogicRandomValue(0, listSize-1);
- const WeaponTemplateVec& v = d->m_weapons[sdphase];
- DEBUG_ASSERTCRASH(idx>=0&&idx<v.size(),("bad idx"));
- const WeaponTemplate* wt = v[idx];
- if (wt)
- {
- TheWeaponStore->createAndFireTempWeapon(wt, getObject(), getObject()->getPosition());
- }
- }
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- UpdateSleepTime SlowDeathBehavior::update()
- {
- //DEBUG_LOG(("updating SlowDeathBehavior %08lx\n",this));
- DEBUG_ASSERTCRASH(isSlowDeathActivated(), ("hmm, this should not be possible"));
- const SlowDeathBehaviorModuleData* d = getSlowDeathBehaviorModuleData();
- Object* obj = getObject();
- Real timeScale = TheGameLODManager->getSlowDeathScale();
- // Check if we have normal time scale but LODManager is requeseting acceleration
- if (timeScale != 1.0f && m_acceleratedTimeScale == 1.0f && !d->hasNonLodEffects())
- {
- // speed of deaths has been increased since beginning of death
- // so adjust it to current levels.
- if (timeScale == 0)
- {
- // instant death
- TheGameLogic->destroyObject(obj);
- return UPDATE_SLEEP_NONE;
- }
- m_sinkFrame = (Real)m_sinkFrame * timeScale;
- m_midpointFrame = (Real)m_midpointFrame * timeScale;
- m_destructionFrame = (Real)m_destructionFrame * timeScale;
- m_acceleratedTimeScale = timeScale;
- };
- UnsignedInt now = TheGameLogic->getFrame();
-
- if ((m_flags & (1<<FLUNG_INTO_AIR)) != 0)
- {
- if ((m_flags & (1<<BOUNCED)) == 0)
- {
- ++m_sinkFrame;
- ++m_midpointFrame;
- ++m_destructionFrame;
- if (!obj->isAboveTerrain())
- {
- obj->clearAndSetModelConditionFlags(MAKE_MODELCONDITION_MASK(MODELCONDITION_EXPLODED_FLAILING),
- MAKE_MODELCONDITION_MASK(MODELCONDITION_EXPLODED_BOUNCING));
- m_flags |= (1<<BOUNCED);
- }
-
- // Here we want to make sure we die if we collide with a tree on the way down
- PhysicsBehavior *phys = obj->getPhysics();
- if ( phys )
- {
- ObjectID treeID = phys->getLastCollidee();
- Object *tree = TheGameLogic->findObjectByID( treeID );
- if ( tree )
- {
- if (tree->isKindOf( KINDOF_SHRUBBERY ) )
- {
- obj->setDisabled( DISABLED_HELD );
- obj->clearModelConditionFlags( MAKE_MODELCONDITION_MASK(MODELCONDITION_EXPLODED_FLAILING) );
- obj->clearModelConditionFlags( MAKE_MODELCONDITION_MASK(MODELCONDITION_EXPLODED_BOUNCING) );
- obj->setModelConditionFlags( MAKE_MODELCONDITION_MASK(MODELCONDITION_PARACHUTING) ); //looks like he is snagged in a tree
- obj->setPositionZ( obj->getPosition()->z - (d->m_sinkRate * 50.0f) );// make him sink faster
- if ( !obj->isAboveTerrain() )
- TheGameLogic->destroyObject(obj);
- }
- }
- }
- }
- }
- if ( (now >= m_sinkFrame && d->m_sinkRate > 0.0f) )
- {
- // disable Physics (if any) so that we can control the sink...
- obj->setDisabled( DISABLED_HELD );
- Coord3D pos = *obj->getPosition();
- pos.z -= d->m_sinkRate / m_acceleratedTimeScale;
- obj->setPosition( &pos );
- }
- if( now >= m_midpointFrame && (m_flags & (1<<MIDPOINT_EXECUTED)) == 0 )
- {
- doPhaseStuff(SDPHASE_MIDPOINT);
- m_flags |= (1<<MIDPOINT_EXECUTED);
- }
- if (now >= m_destructionFrame)
- {
- doPhaseStuff(SDPHASE_FINAL);
- TheGameLogic->destroyObject(obj);
- }
- return UPDATE_SLEEP_NONE;
- }
- //-------------------------------------------------------------------------------------------------
- void SlowDeathBehavior::onDie( const DamageInfo *damageInfo )
- {
- Object *obj = getObject();
- if (!isDieApplicable(damageInfo))
- return;
- AIUpdateInterface *ai = obj->getAIUpdateInterface();
- if (ai)
- {
- // has another AI already handled us. (hopefully another SlowDeathBehavior)
- if (ai->isAiInDeadState())
- return;
- ai->markAsDead();
- }
- // deselect this unit for all players.
- TheGameLogic->deselectObject(obj, PLAYERMASK_ALL, TRUE);
- Int total = 0;
- for (BehaviorModule** update = obj->getBehaviorModules(); *update; ++update)
- {
- SlowDeathBehaviorInterface* sdu = (*update)->getSlowDeathBehaviorInterface();
- if (sdu != NULL && sdu->isDieApplicable(damageInfo))
- {
- total += sdu->getProbabilityModifier( damageInfo );
- }
- }
- DEBUG_ASSERTCRASH(total > 0, ("Hmm, this is wrong"));
- // this returns a value from 1...total, inclusive
- Int roll = GameLogicRandomValue(1, total);
- for (/* UpdateModuleInterface** */ update = obj->getBehaviorModules(); *update; ++update)
- {
- SlowDeathBehaviorInterface* sdu = (*update)->getSlowDeathBehaviorInterface();
- if (sdu != NULL && sdu->isDieApplicable(damageInfo))
- {
- roll -= sdu->getProbabilityModifier( damageInfo );
- if (roll <= 0)
- {
- sdu->beginSlowDeath(damageInfo);
- return;
- }
- }
- }
- DEBUG_CRASH(("We should never get here"));
- }
- // ------------------------------------------------------------------------------------------------
- /** CRC */
- // ------------------------------------------------------------------------------------------------
- void SlowDeathBehavior::crc( Xfer *xfer )
- {
- // extend base class
- UpdateModule::crc( xfer );
- } // end crc
- // ------------------------------------------------------------------------------------------------
- /** Xfer method
- * Version Info:
- * 1: Initial version */
- // ------------------------------------------------------------------------------------------------
- void SlowDeathBehavior::xfer( Xfer *xfer )
- {
- // version
- XferVersion currentVersion = 1;
- XferVersion version = currentVersion;
- xfer->xferVersion( &version, currentVersion );
- // extend base class
- UpdateModule::xfer( xfer );
- // sink frame
- xfer->xferUnsignedInt( &m_sinkFrame );
- // midpoint frame
- xfer->xferUnsignedInt( &m_midpointFrame );
- // destruction frame
- xfer->xferUnsignedInt( &m_destructionFrame );
- // accelerated time scale
- xfer->xferReal( &m_acceleratedTimeScale );
- // flags
- xfer->xferUnsignedInt( &m_flags );
- } // end xfer
- // ------------------------------------------------------------------------------------------------
- /** Load post process */
- // ------------------------------------------------------------------------------------------------
- void SlowDeathBehavior::loadPostProcess( void )
- {
- // extend base class
- UpdateModule::loadPostProcess();
- } // end loadPostProcess
|