| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483 |
- /*
- ** Command & Conquer Generals(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: BridgeBehavior.cpp ///////////////////////////////////////////////////////////////////////
- // Author: Colin Day, July 2002
- // Desc: Behavior module for bridges
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // INCLUDES ///////////////////////////////////////////////////////////////////////////////////////
- #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
- #include "Common/Radar.h"
- #include "Common/ThingFactory.h"
- #include "Common/ThingTemplate.h"
- #include "Common/Xfer.h"
- #include "GameClient/InGameUI.h"
- #include "GameClient/FXList.h"
- #include "GameClient/Line2D.h"
- #include "GameClient/TerrainRoads.h"
- #include "GameLogic/AI.h"
- #include "GameLogic/AIPathfind.h"
- #include "GameLogic/Object.h"
- #include "GameLogic/GameLogic.h"
- #include "GameLogic/ObjectCreationList.h"
- #include "GameLogic/Module/BodyModule.h"
- #include "GameLogic/Module/BridgeBehavior.h"
- #include "GameLogic/Module/BridgeScaffoldBehavior.h"
- #include "GameLogic/Module/PhysicsUpdate.h"
- #include "GameLogic/PartitionManager.h"
- #include "GameLogic/TerrainLogic.h"
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- BridgeBehaviorModuleData::BridgeBehaviorModuleData( void )
- {
- m_lateralScaffoldSpeed = 1.0f;
- m_verticalScaffoldSpeed = 1.0f;
- } // end BridgeBehaviorModuleData
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- BridgeBehaviorModuleData::~BridgeBehaviorModuleData( void )
- {
- // clear the fx list
- m_fx.clear();
- // clear the ocl list
- m_ocl.clear();
- } // end ~BridgeBehaviorModuleData
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- /*static*/ void BridgeBehaviorModuleData::buildFieldParse( MultiIniFieldParse &p )
- {
- BehaviorModuleData::buildFieldParse( p );
- static const FieldParse dataFieldParse[] =
- {
- { "LateralScaffoldSpeed", INI::parseVelocityReal, NULL, offsetof( BridgeBehaviorModuleData, m_lateralScaffoldSpeed ) },
- { "VerticalScaffoldSpeed", INI::parseVelocityReal, NULL, offsetof( BridgeBehaviorModuleData, m_verticalScaffoldSpeed ) },
- { "BridgeDieFX", parseFX, NULL, offsetof( BridgeBehaviorModuleData, m_fx ) },
- { "BridgeDieOCL", parseOCL, NULL, offsetof( BridgeBehaviorModuleData, m_ocl ) },
- { 0, 0, 0, 0 }
- };
- p.add( dataFieldParse );
- } // end buildFieldParse
- // ------------------------------------------------------------------------------------------------
- /** Parse time and location info in the form of:
- * Delay:#### <Bone:BoneName> */
- // ------------------------------------------------------------------------------------------------
- static void parseTimeAndLocationInfo( INI *ini, void *instance,
- TimeAndLocationInfo *timeAndLocationInfo )
- {
- // delay label
- const char *token = ini->getNextToken( ini->getSepsColon() );
- if( stricmp( token, "Delay" ) != 0 )
- {
- DEBUG_CRASH(( "Expected 'Delay' token, found '%s'\n", token ));
- throw INI_INVALID_DATA;
- } // end if
- // delay value
- ini->parseDurationUnsignedInt( ini, instance, &timeAndLocationInfo->delay, NULL );
- // get optional bone label
- token = ini->getNextTokenOrNull( ini->getSepsColon() );
- if( token )
- {
- // token must be a label for bone location
- if( stricmp( token, "Bone" ) != 0 )
- {
- DEBUG_CRASH(( "Expected 'Bone' token, found '%s'\n", token ));
- throw INI_INVALID_DATA;
- } // end if
- // read bone name and store
- timeAndLocationInfo->boneName = ini->getNextAsciiString();
- } // end if
- } // end parseTimeAndLocationInfo
- //-------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- /*static*/ void BridgeBehaviorModuleData::parseFX( INI *ini,
- void *instance,
- void *store,
- const void *userData )
- {
- const char *token;
- // create item we will read into and push on list
- BridgeFXInfo item;
- item.fx = NULL;
- // get list to store at
- BridgeFXList *bridgeFXList = (BridgeFXList *)store;
- // fx list label
- token = ini->getNextToken( ini->getSepsColon() );
- if( stricmp( token, "FX" ) != 0 )
- {
- DEBUG_CRASH(( "Expected 'FX' token, found '%s'\n", token ));
- throw INI_INVALID_DATA;
- } // end if
- // fx list name and store as pointer
- FXList *fx;
- ini->parseFXList( ini, instance, &fx, NULL );
- // store fx list to item
- item.fx = fx;
- // parse the timing and location info
- parseTimeAndLocationInfo( ini, instance, &item.timeAndLocationInfo );
- // put on list
- bridgeFXList->push_back( item );
- } // end parseFX
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- /*static*/ void BridgeBehaviorModuleData::parseOCL( INI *ini,
- void *instance,
- void *store,
- const void *userData )
- {
- const char *token;
- // create item we will read into and push on list
- BridgeOCLInfo item;
- item.ocl = NULL;
- // get list to store at
- BridgeOCLList *bridgeOCLList = (BridgeOCLList *)store;
- // fx list label
- token = ini->getNextToken( ini->getSepsColon() );
- if( stricmp( token, "OCL" ) != 0 )
- {
- DEBUG_CRASH(( "Expected 'OCL' token, found '%s'\n", token ));
- throw INI_INVALID_DATA;
- } // end if
- // fx list name and store as pointer
- ObjectCreationList *ocl;
- ini->parseObjectCreationList( ini, instance, &ocl, NULL );
- // store ocl list to item
- item.ocl = ocl;
- // parse the timing and location info
- parseTimeAndLocationInfo( ini, instance, &item.timeAndLocationInfo );
- // put on list
- bridgeOCLList->push_back( item );
- } // end parseOCL
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- BridgeBehavior::BridgeBehavior( Thing *thing, const ModuleData *moduleData )
- : UpdateModule( thing, moduleData )
- {
- Int i;
- m_scaffoldObjectIDList.clear();
- m_scaffoldPresent = FALSE;
- for( i = 0; i < BRIDGE_MAX_TOWERS; ++i )
- m_towerID[ i ] = INVALID_ID;
- m_fxResolved = FALSE;
- for( Int bodyState = BODY_PRISTINE; bodyState < BODYDAMAGETYPE_COUNT; ++bodyState )
- {
- // initialize the fx and ocl lists
- for( i = 0; i < MAX_BRIDGE_BODY_FX; ++i )
- {
- m_damageToOCL[ bodyState ][ i ] = NULL;
- m_damageToFX[ bodyState ][ i ] = NULL;
- m_repairToOCL[ bodyState ][ i ] = NULL;
- m_repairToFX[ bodyState ][ i ] = NULL;
- } // end for i
- // these don't need initialization, they have constructors
- // m_damageToSound[ bodyState ] = ???
- // m_repairToSound[ bodyState ] = ???
- } // end for, bodyState
- m_deathFrame = 0;
- } // end BridgeBehavior
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- BridgeBehavior::~BridgeBehavior( void )
- {
- //
- // destroy our four towers if they are still present in the world (they wouldn't be if we
- // are resetting the engine, and those towers were earlier in the destruction list than
- // we were)
- //
- for( Int i = 0; i < BRIDGE_MAX_TOWERS; ++i )
- {
- Object *tower;
- // get the tower and destroy
- tower = TheGameLogic->findObjectByID( getTowerID( (BridgeTowerType)i ) );
- if( tower )
- TheGameLogic->destroyObject( tower );
- } // end for i
- } // end ~BridgeBehavior
- // ------------------------------------------------------------------------------------------------
- /** Get bridge behavior interface */
- // ------------------------------------------------------------------------------------------------
- /*static */BridgeBehaviorInterface *BridgeBehavior::getBridgeBehaviorInterfaceFromObject( Object *obj )
- {
-
- // sanity
- if( obj == NULL )
- return NULL;
- BehaviorModule **bmi;
- BridgeBehaviorInterface *bbi = NULL;
- for( bmi = obj->getBehaviorModules(); *bmi; ++bmi )
- {
- bbi = (*bmi)->getBridgeBehaviorInterface();
- if( bbi )
- return bbi;
- } // end for, bmi
- // interface not found
- return NULL;
- } // end getBridgeBehaviorInterfaceFromObject
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void BridgeBehavior::onDelete( void )
- {
- // clear the list of scaffold objects
- m_scaffoldObjectIDList.clear();
- } // end onDelete
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void BridgeBehavior::resolveFX( void )
- {
- Object *us = getObject();
- Bridge *bridge = TheTerrainLogic->findBridgeAt( us->getPosition() );
- // sanity
- if( bridge == NULL )
- return;
- // get the bridge template name
- AsciiString bridgeTemplateName = bridge->getBridgeTemplateName();
- // find the bridge template
- TerrainRoadType *bridgeTemplate = TheTerrainRoads->findBridge( bridgeTemplateName );
- // sanity
- if( bridgeTemplate == NULL )
- return;
- AsciiString name;
- for( Int bodyState = BODY_PRISTINE; bodyState < BODYDAMAGETYPE_COUNT; ++bodyState )
- {
- // initialize the fx and ocl lists
- for( Int i = 0; i < MAX_BRIDGE_BODY_FX; ++i )
- {
- name = bridgeTemplate->getDamageToOCLString( (BodyDamageType)bodyState, i );
- m_damageToOCL[ bodyState ][ i ] = TheObjectCreationListStore->findObjectCreationList( name.str() );
- if( name.isEmpty() == FALSE && m_damageToOCL[ bodyState ][ i ] == NULL )
- DEBUG_CRASH(( "OCL list '%s' not found\n", name.str() ));
- name = bridgeTemplate->getDamageToFXString( (BodyDamageType)bodyState, i );
- m_damageToFX[ bodyState ][ i ] = TheFXListStore->findFXList( name.str() );
- if( name.isEmpty() == FALSE && m_damageToFX[ bodyState ][ i ] == NULL )
- DEBUG_CRASH(( "FX list '%s' not found\n", name.str() ));
- name = bridgeTemplate->getRepairedToOCLString( (BodyDamageType)bodyState, i );
- m_repairToOCL[ bodyState ][ i ] = TheObjectCreationListStore->findObjectCreationList( name.str() );
- if( name.isEmpty() == FALSE && m_repairToOCL[ bodyState ][ i ] == NULL )
- DEBUG_CRASH(( "OCL list '%s' not found\n", name.str() ));
- name = bridgeTemplate->getRepairedToFXString( (BodyDamageType)bodyState, i );
- m_repairToFX[ bodyState ][ i ] = TheFXListStore->findFXList( name.str() );;
- if( name.isEmpty() == FALSE && m_repairToFX[ bodyState ][ i ] == NULL )
- DEBUG_CRASH(( "FX list '%s' not found\n", name.str() ));
- } // end for i
- // audio sounds
- name = bridgeTemplate->getDamageToSoundString( (BodyDamageType)bodyState );
- m_damageToSound[ bodyState ].setEventName( name );
- m_damageToSound[ bodyState ].setObjectID( us->getID() );
- name = bridgeTemplate->getRepairedToSoundString( (BodyDamageType)bodyState );
- m_repairToSound[ bodyState ].setEventName( name );
- m_repairToSound[ bodyState ].setObjectID( us->getID() );
- } // end for, bodyState
- // fx are now "resolved"
- m_fxResolved = TRUE;
- } // end resolveFX
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void BridgeBehavior::setTower( BridgeTowerType towerType, Object *tower )
- {
- // sanity
- if( towerType < 0 || towerType >= BRIDGE_MAX_TOWERS )
- {
- DEBUG_CRASH(( "BridgeBehavior::setTower - Invalid tower type index '%d'\n", towerType ));
- return;
- } // end if
- // store it
- if( tower )
- m_towerID[ towerType ] = tower->getID();
- else
- m_towerID[ towerType ] = INVALID_ID;
- } // end setTower
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- ObjectID BridgeBehavior::getTowerID( BridgeTowerType towerType )
- {
- // sanity
- if( towerType < 0 || towerType >= BRIDGE_MAX_TOWERS )
- {
- DEBUG_CRASH(( "BridgeBehavior::setTower - Invalid tower type index '%d'\n", towerType ));
- return INVALID_ID;
- } // end if
- // return the stored ID
- return m_towerID[ towerType ];
- } // end getTowerID
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void BridgeBehavior::onDamage( DamageInfo *damageInfo )
- {
- //
- // get our body info so we now how much damage percent is being done to us ... we need this
- // so that we can propagate the same damage percentage amont the towers and the bridge
- //
- BodyModuleInterface *body = getObject()->getBodyModule();
- Real damagePercentage = damageInfo->in.m_amount / body->getMaxHealth();
- //
- // if the damage didn't come from a bridge tower, then we must propagate this damage
- // to all our towers
- //
- Object *source = TheGameLogic->findObjectByID( damageInfo->in.m_sourceID );
- if( source == NULL || source->isKindOf( KINDOF_BRIDGE_TOWER ) == FALSE )
- {
- Object *tower;
- for( Int i = 0; i < BRIDGE_MAX_TOWERS; i++ )
- {
- tower = TheGameLogic->findObjectByID( getTowerID( (BridgeTowerType)i ) );
- if( tower )
- {
- BodyModuleInterface *towerBody = tower->getBodyModule();
- DamageInfo towerDamage;
- towerDamage.in.m_amount = damagePercentage * towerBody->getMaxHealth();
- towerDamage.in.m_sourceID = getObject()->getID(); // we're now the source
- towerDamage.in.m_damageType = damageInfo->in.m_damageType;
- towerDamage.in.m_deathType = damageInfo->in.m_deathType;
- tower->attemptDamage( &towerDamage );
- } // end if
- } // end for i
- } // end if
- } // end onDamage
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void BridgeBehavior::onHealing( DamageInfo *damageInfo )
- {
- //
- // get our body info so we now how much healing percent is being done to us ... we need this
- // so that we can propagate the same healing percentage amont the towers and the bridge
- //
- BodyModuleInterface *body = getObject()->getBodyModule();
- Real healingPercentage = damageInfo->in.m_amount / body->getMaxHealth();
- //
- // if the healing didn't come from a bridge tower, then we must propagate this healing
- // to all our towers
- //
- Object *source = TheGameLogic->findObjectByID( damageInfo->in.m_sourceID );
- if( source == NULL || source->isKindOf( KINDOF_BRIDGE_TOWER ) == FALSE )
- {
- Object *tower;
- for( Int i = 0; i < BRIDGE_MAX_TOWERS; i++ )
- {
- tower = TheGameLogic->findObjectByID( getTowerID( (BridgeTowerType)i ) );
- if( tower )
- {
- BodyModuleInterface *towerBody = tower->getBodyModule();
- tower->attemptHealing(healingPercentage * towerBody->getMaxHealth(), getObject());
- } // end if
- } // end for i
- } // end if
- } // end onHealing
- // ------------------------------------------------------------------------------------------------
- /** Pick a random surface spot on the bridge surface */
- // ------------------------------------------------------------------------------------------------
- void BridgeBehavior::getRandomSurfacePosition( TerrainRoadType *bridgeTemplate,
- const BridgeInfo *bridgeInfo,
- Coord3D *pos )
- {
- // sanity
- if( bridgeInfo == NULL || pos == NULL )
- return;
- //
- // pick the spot by finding vectors along the edge of the bridge region, scaling
- // them and then adding them together
- //
- Real scale;
- Coord3D v1;
- v1.x = bridgeInfo->toLeft.x - bridgeInfo->fromLeft.x;
- v1.y = bridgeInfo->toLeft.y - bridgeInfo->fromLeft.y;
- v1.z = bridgeInfo->toLeft.z - bridgeInfo->fromLeft.z;
- scale = GameLogicRandomValueReal( 0.0f, 1.0f );
- v1.x *= scale;
- v1.y *= scale;
- v1.z *= scale;
- Coord3D v2;
- v2.x = bridgeInfo->fromRight.x - bridgeInfo->fromLeft.x;
- v2.y = bridgeInfo->fromRight.y - bridgeInfo->fromLeft.y;
- v2.z = bridgeInfo->fromRight.z - bridgeInfo->fromLeft.z;
- scale = GameLogicRandomValueReal( 0.0f, 1.0f );
- v2.x *= scale;
- v2.y *= scale;
- v2.z *= scale;
- // set the position
- pos->x = v1.x + v2.x + bridgeInfo->fromLeft.x;
- pos->y = v1.y + v2.y + bridgeInfo->fromLeft.y;
- pos->z = v1.z + v2.z + bridgeInfo->fromLeft.z;
- //
- // we now have a position picked, the last thing to do is add in an additional
- // Z component so that effects can be created in a "cube" area on and above the bridge
- //
- pos->z += GameLogicRandomValueReal( 0.0f, bridgeTemplate->getTransitionEffectsHeight() );
- } // end getRandomSurfacePosition
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void BridgeBehavior::doAreaEffects( TerrainRoadType *bridgeTemplate,
- Bridge *bridge,
- const ObjectCreationList *ocl,
- const FXList *fx )
- {
-
- // sanity
- if( bridge == NULL )
- return;
- // if no effects, don't bother
- if( ocl == NULL && fx == NULL )
- return;
- // get bridge info
- const BridgeInfo *bridgeInfo = bridge->peekBridgeInfo();
- // play effects in the bridge area
- const Int maxEffects = bridgeTemplate->getNumFXPerType();
- Coord3D pos;
- for( Int i = 0; i < maxEffects; ++i )
- {
- // pick spot in the bridge area and do FX
- if( fx )
- {
- getRandomSurfacePosition( bridgeTemplate, bridgeInfo, &pos );
- FXList::doFXPos( fx, &pos );
- } // end if
- // pick spot in the bridge area and do OCL
- if( ocl )
- {
- getRandomSurfacePosition( bridgeTemplate, bridgeInfo, &pos );
- ObjectCreationList::create( ocl, getObject(), &pos, NULL );
- } // end if
- } // end for i
- } // end doAreaEffects
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void BridgeBehavior::onBodyDamageStateChange( const DamageInfo* damageInfo,
- BodyDamageType oldState,
- BodyDamageType newState )
- {
- //
- // check for coming back from the dead, if our new state is not the rubble state, we can't
- // possibly be dead
- //
- if( newState != BODY_RUBBLE )
- m_deathFrame = 0;
- // first resolve any fx stuff if we need to
- if( m_fxResolved == FALSE )
- resolveFX();
- // sanity
- if( m_fxResolved == FALSE )
- return;
- // sanity
- DEBUG_ASSERTCRASH( oldState != newState, ("BridgeBehavior::onBodyDamageStateChange - oldState and newState should be different if this is getting called\n") );
- Object *us = getObject();
- Bridge *bridge = TheTerrainLogic->findBridgeAt( us->getPosition() );
- // sanity
- if( bridge == NULL )
- {
- DEBUG_CRASH(( "BridgeBehavior - Unable to find bridge\n" ));
- return;
- } // end if
- // get the bridge template name
- AsciiString bridgeTemplateName = bridge->getBridgeTemplateName();
- // find the bridge template
- TerrainRoadType *bridgeTemplate = TheTerrainRoads->findBridge( bridgeTemplateName );
- // sanity
- DEBUG_ASSERTCRASH( bridgeTemplate, ("BridgeBehavior: Unable to find bridge template '%s' in bridge object '%s'\n",
- bridgeTemplateName,
- us->getTemplate()->getName().str()) );
- //
- // given the old state and the new state, did we get worse (damaged) or did
- // we get better (repaired)?
- //
- Bool gotRepaired = IS_CONDITION_WORSE( oldState, newState );
- // get the effect data
- AsciiString soundString;
- AsciiString oclString[ MAX_BRIDGE_BODY_FX ];
- AsciiString fxString[ MAX_BRIDGE_BODY_FX ];
- if( gotRepaired )
- {
- // play the sound
- TheAudio->addAudioEvent( &m_repairToSound[ newState ] );
- for( Int i = 0; i < MAX_BRIDGE_BODY_FX; i++ )
- doAreaEffects( bridgeTemplate, bridge, m_repairToOCL[ newState ][ i ], m_repairToFX[ newState ][ i ] );
- } // end if
- else
- {
- // play the sound
- TheAudio->addAudioEvent( &m_damageToSound[ newState ] );
- for( Int i = 0; i < MAX_BRIDGE_BODY_FX; i++ )
- doAreaEffects( bridgeTemplate, bridge, m_damageToOCL[ newState ][ i ], m_damageToFX[ newState ][ i ] );
- } // end else
- // update bridge damage states
- ///@todo this should be re-written, there no need for this looping bridge examination
- TheTerrainLogic->updateBridgeDamageStates();
- //
- // for the local player, if this bridge has switched from rubble, to usable, or from
- // usable to rubble, we should reflect the change on the radar. note that we
- // request that the radar queue a refresh sometime in the future because it keeps
- // track of how often we makes requests to do a refresh and doesn't do them too
- // often because it's expensive to refresh the terrain
- //
- if( oldState == BODY_RUBBLE || newState == BODY_RUBBLE )
- TheRadar->queueTerrainRefresh();
- } // end onBodyDamageStateChange
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- UpdateSleepTime BridgeBehavior::update( void )
- {
- // if we're dead, we need to possibly throw off some effects
- if( m_deathFrame != 0 )
- {
- AsciiString boneName;
- // get object
- Object *us = getObject();
- // get module data
- const BridgeBehaviorModuleData *modData = getBridgeBehaviorModuleData();
- // get bridge information
- Bridge *bridge = TheTerrainLogic->findBridgeAt( us->getPosition() );
- const BridgeInfo *bridgeInfo = NULL;
- TerrainRoadType *bridgeTemplate = NULL;
- if ( bridge )
- {
- DEBUG_ASSERTCRASH( bridge, ("BridgeBehavior::update - Unable to find bridge\n") );
- // get bridge info
- bridgeInfo = bridge->peekBridgeInfo();
- // get the bridge template info
- AsciiString bridgeTemplateName = bridge->getBridgeTemplateName();
- bridgeTemplate = TheTerrainRoads->findBridge( bridgeTemplateName );
- DEBUG_ASSERTCRASH( bridgeTemplate, ("BridgeBeahvior::getRandomSurfacePosition - Encountered a bridge with no template!\n") );
- }
- // how much time has passed between now and our destruction frame
- UnsignedInt deathTime = TheGameLogic->getFrame() - m_deathFrame;
- // see if there are any fx visuals we need to execute
- BridgeFXList::const_iterator fxIt;
- for( fxIt = modData->m_fx.begin(); fxIt != modData->m_fx.end(); ++fxIt )
- {
- //
- // we'll launch an fx list if our death time is equal to exactly the delay
- // we're waiting for to launch the list
- //
- if( deathTime == (*fxIt).timeAndLocationInfo.delay )
- {
- Coord3D pos;
- //
- // if a bone name is present, we'll use the bone position, otherwise we'll pick a
- // spot somewhere on the bridge surface
- //
- boneName = (*fxIt).timeAndLocationInfo.boneName;
- if( boneName.isEmpty() == FALSE )
- us->getSingleLogicalBonePosition( boneName.str(), &pos, NULL );
- else if ( bridge && bridgeTemplate && bridgeInfo)//we have valid Terrain data for the bridge
- getRandomSurfacePosition( bridgeTemplate, bridgeInfo, &pos );
- else
- pos.set( getObject()->getPosition() );
-
- // launch the fx list
- FXList::doFXPos( (*fxIt).fx, &pos );
- } // end if
- } // end for, fxIt
- // see if there are any ocl visuals we need to execute
- BridgeOCLList::const_iterator oclIt;
- for( oclIt = modData->m_ocl.begin(); oclIt != modData->m_ocl.end(); ++oclIt )
- {
- //
- // we'll launch an ocl list if our death time is equal to exactly the delay
- // we're waiting for to launch the list
- //
- if( deathTime == (*oclIt).timeAndLocationInfo.delay )
- {
- Coord3D pos;
- //
- // if a bone name is present, we'll use the bone position, otherwise we'll pick a
- // spot somewhere on the bridge surface
- //
- boneName = (*oclIt).timeAndLocationInfo.boneName;
- if( boneName.isEmpty() == FALSE )
- {
- //
- // special case for creating an OCL for using the bridge object parent center location
- // why do we have this ... well, apparently the OCL ignores the obj parameter
- // passed in if you give it a position parameter, and we need it to pay attention
- // to that object parameteter so the OCL stuff can inherit the LIKE_EXISTING
- // properties from its parent
- //
- if( boneName.compare( "ParentObject" ) == 0 )
- {
-
- // launch the effects just using the parent object for location info
- ObjectCreationList::create( (*oclIt).ocl, us, NULL );
- } // endif
- else
- {
- // get bone position
- us->getSingleLogicalBonePosition( boneName.str(), &pos, NULL );
- // launch the fx list
- ObjectCreationList::create( (*oclIt).ocl, us, &pos, NULL );
-
- } // end else
- } // end if, bone name not empty
- else
- {
- // get random place on bridge
- if ( bridge && bridgeTemplate && bridgeInfo )//we have valid Terrain data for the bridge
- getRandomSurfacePosition( bridgeTemplate, bridgeInfo, &pos );
- else
- pos.set( getObject()->getPosition() );
- // launch the fx list
- ObjectCreationList::create( (*oclIt).ocl, us, &pos, NULL );
- } // end else
- } // end if
- } // end for, oclIt
- } // end if
- return UPDATE_SLEEP_NONE;
- } // end update
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void BridgeBehavior::onDie( const DamageInfo *damageInfo )
- {
- // kill the towers associated with us
- Object *tower;
- for( Int i = 0; i < BRIDGE_MAX_TOWERS; ++i )
- {
- tower = TheGameLogic->findObjectByID( getTowerID( (BridgeTowerType)i ) );
- if( tower )
- tower->kill();
- } // end for, i
- // we need to handle anything that was on top of us now that we've been destroyed
- handleObjectsOnBridgeOnDie();
- // we have now died, record the death frame
- m_deathFrame = TheGameLogic->getFrame();
-
- } // end onDie
- // ------------------------------------------------------------------------------------------------
- // ------------------------------------------------------------------------------------------------
- void BridgeBehavior::handleObjectsOnBridgeOnDie( void )
- {
- const Object *bridge = getObject();
- const Coord3D *bridgePos = bridge->getPosition();
- Bridge *terrainBridge = TheTerrainLogic->findBridgeAt( getObject()->getPosition() );
- if( terrainBridge )
- {
- PathfindLayerEnum bridgeLayer = terrainBridge->getLayer();
- BridgeInfo bridgeInfo;
- // get the bridge info
- terrainBridge->getBridgeInfo( &bridgeInfo );
- // setup a polygon area using the bridge extents
- Coord3D bridgePolygon[ 4 ];
- bridgePolygon[ 0 ] = bridgeInfo.fromLeft;
- bridgePolygon[ 1 ] = bridgeInfo.fromRight;
- bridgePolygon[ 2 ] = bridgeInfo.toRight;
- bridgePolygon[ 3 ] = bridgeInfo.toLeft;
- //
- // find the lowest Z point of the bridge area ... we will use this to figure out of
- // objects in the bridge area are "on top" of the bridge
- //
- Real lowBridgeZ = bridgePolygon[ 0 ].z;
- for( Int i = 0; i < 4; ++i )
- if( bridgePolygon[ i ].z < lowBridgeZ )
- lowBridgeZ = bridgePolygon[ i ].z;
-
- //
- // given the polygon area, how big is the radius that we need to scan in the world
- // to cover from the center of the bridge (the bridge object position) to the edge
- // of the bridge
- //
- Coord2D v;
- v.x = bridgeInfo.toLeft.x - bridgePos->x;
- v.y = bridgeInfo.toLeft.y - bridgePos->y;
- Real radius = v.length();
- // scan the objects in the radius
- ObjectIterator *iter = ThePartitionManager->iterateObjectsInRange( bridgePos,
- radius,
- FROM_CENTER_2D );
- MemoryPoolObjectHolder hold( iter );
- Object *other;
- for( other = iter->first(); other; other = iter->next() )
- {
- // ingnore some kind of objects
- if( other->isKindOf( KINDOF_BRIDGE ) || other->isKindOf( KINDOF_BRIDGE_TOWER ) )
- continue;
- // ignore airborne objects
- if( other->isAboveTerrain() )
- continue;
- // ignore objects that were not actually on the bridge
- if( other->getPosition()->z < lowBridgeZ )
- continue;
- // ignore objects that are not inside the bridge polygon
- if( PointInsideArea2D( other->getPosition(), bridgePolygon, 4 ) == FALSE )
- continue;
- // if object not on same layer as bridge do nothing
- if( bridgeLayer != other->getLayer() )
- continue;
- if (other->getLayer() == bridgeLayer)
- other->setLayer(LAYER_GROUND);
- // if they have physics, let 'em fall, otherwise just kill 'em
- PhysicsBehavior* physics = other->getPhysics();
- if (physics)
- physics->setAllowToFall(true);
- else
- other->kill();
- } // end for, other
- } // end if, terrainBridge
- } // end handleObjectsOnBridgeDie
- // ------------------------------------------------------------------------------------------------
- /** Set all the position, angle, and speed data we need to for a single scaffold object */
- // ------------------------------------------------------------------------------------------------
- void BridgeBehavior::setScaffoldData( Object *obj,
- Real *angle,
- Real *sunkenHeight,
- const Coord3D *riseToPos,
- const Coord3D *buildPos,
- const Coord3D *bridgeCenter )
- {
- // sanity
- if( obj == NULL || angle == NULL || riseToPos == NULL || buildPos == NULL )
- return;
- const BridgeBehaviorModuleData *modData = getBridgeBehaviorModuleData();
- // get the scaffold behavior interface
- BridgeScaffoldBehaviorInterface *scaffoldBehavior;
- scaffoldBehavior = BridgeScaffoldBehavior::getBridgeScaffoldBehaviorInterfaceFromObject( obj );
- DEBUG_ASSERTCRASH( scaffoldBehavior, ("Unable to find bridge scaffold behavior interface\n") );
- // compute the sunken position that the object will initially start at
- Real fudge = 8.0f;
- Coord3D sunkenPos = *riseToPos;
- sunkenPos.z = sunkenPos.z - *sunkenHeight - fudge;
- // set object initial position
- obj->setPosition( &sunkenPos );
- // set all the destination points for all scaffold motion
- scaffoldBehavior->setPositions( &sunkenPos, riseToPos, buildPos );
-
- // set the scaffold object in motion rising up out of the ground
- scaffoldBehavior->setMotion( STM_RISE );
- // set object angle
- obj->setOrientation( *angle );
- //
- // set the speed of the scaffold "animation" which is based on how big of a distance
- // all the scaffold objects have to traverse in order to meet up and be complete in
- // the center of the bridge in an interesting way
- //
- Real lateralSpeed = modData->m_lateralScaffoldSpeed;
- Coord3D buildUpPosToBridgeCenter, riseToPosToBridgeCenter;
- buildUpPosToBridgeCenter.x = buildPos->x - riseToPos->x;
- buildUpPosToBridgeCenter.y = buildPos->y - riseToPos->y;
- buildUpPosToBridgeCenter.z = buildPos->z - riseToPos->z;
- riseToPosToBridgeCenter.x = bridgeCenter->x - riseToPos->x;
- riseToPosToBridgeCenter.y = bridgeCenter->y - riseToPos->y;
- riseToPosToBridgeCenter.z = bridgeCenter->z - riseToPos->z;
- Real distBuildUpPosToBridgeCenter = buildUpPosToBridgeCenter.length();
- Real distRiseToPosToBridgeCenter = riseToPosToBridgeCenter.length();
- scaffoldBehavior->setLateralSpeed( lateralSpeed * (distBuildUpPosToBridgeCenter / distRiseToPosToBridgeCenter) );
- // rising speed is always the same for all objects
- Real verticalSpeed = modData->m_verticalScaffoldSpeed;
- scaffoldBehavior->setVerticalSpeed( verticalSpeed );
- } // end setScaffoldData
- // ------------------------------------------------------------------------------------------------
- /** Start the bridge repair scaffolding. If we already have scaffolding this call
- * is ignored */
- // ------------------------------------------------------------------------------------------------
- void BridgeBehavior::createScaffolding( void )
- {
- // if we have scaffolding up already do nothing
- if( m_scaffoldPresent == TRUE )
- return;
- // get the bridge world object
- Object *us = getObject();
- const Coord3D *center = us->getPosition();
- // get our bridge object
- Bridge *bridge = TheTerrainLogic->findBridgeAt( us->getPosition() );
- // get the bridge template
- AsciiString bridgeTemplateName = bridge->getBridgeTemplateName();
- TerrainRoadType *bridgeTemplate = TheTerrainRoads->findBridge( bridgeTemplateName );
- DEBUG_ASSERTCRASH( bridgeTemplate, ("Unable to find bridge template to create scaffolding\n") );
- // get the thing template for the scaffold object we're going to use
- AsciiString scaffoldObjectName = bridgeTemplate->getScaffoldObjectName();
- const ThingTemplate *scaffoldTemplate = TheThingFactory->findTemplate( scaffoldObjectName );
- if( scaffoldTemplate == NULL )
- {
- DEBUG_CRASH(( "Unable to find bridge scaffold template\n" ));
- return;
- } // end if
- // get thing template for scaffold support object
- AsciiString scaffoldSupportObjectName = bridgeTemplate->getScaffoldSupportObjectName();
- const ThingTemplate *scaffoldSupportTemplate = TheThingFactory->findTemplate( scaffoldSupportObjectName );
- if( scaffoldSupportTemplate == NULL )
- {
- DEBUG_CRASH(( "Unable to find bridge support scaffold template\n" ));
- return;
- } // end if
- // how much space is going to be between each of the scaffold objects at their final positions
- Real spacing = scaffoldTemplate->getTemplateGeometryInfo().getMajorRadius() * 2.0f;
- // how tall are the scaffold objects
- Real scaffoldHeight = scaffoldTemplate->getTemplateGeometryInfo().getMaxHeightAbovePosition() +
- scaffoldTemplate->getTemplateGeometryInfo().getMaxHeightBelowPosition();
- Real scaffoldSupportHeight = scaffoldSupportTemplate->getTemplateGeometryInfo().getMaxHeightAbovePosition() +
- scaffoldSupportTemplate->getTemplateGeometryInfo().getMaxHeightBelowPosition();
- // get the bridge info
- BridgeInfo bridgeInfo;
- bridge->getBridgeInfo( &bridgeInfo );
- //
- // given the area of the bridge, figure out what the start and end points are to create
- // all the scaffold objects at (just in the 2D bridge plane, not thinking about
- // rising the objects up through the ground yet)
- //
- Coord3D leftStart;
- leftStart.x = ((bridgeInfo.fromLeft.x - bridgeInfo.fromRight.x) / 2.0f) + bridgeInfo.fromRight.x;
- leftStart.y = ((bridgeInfo.fromLeft.y - bridgeInfo.fromRight.y) / 2.0f) + bridgeInfo.fromRight.y;
- leftStart.z = ((bridgeInfo.fromLeft.z - bridgeInfo.fromRight.z) / 2.0f) + bridgeInfo.fromRight.z;
- Coord3D rightStart;
- rightStart.x = ((bridgeInfo.toLeft.x - bridgeInfo.toRight.x) / 2.0f) + bridgeInfo.toRight.x;
- rightStart.y = ((bridgeInfo.toLeft.y - bridgeInfo.toRight.y) / 2.0f) + bridgeInfo.toRight.y;
- rightStart.z = ((bridgeInfo.toLeft.z - bridgeInfo.toRight.z) / 2.0f) + bridgeInfo.toRight.z;
- //
- // now that we have the left and right start points, we will compute two angles to
- // use for all the objects that we will create ... objects on the left side of the
- // bridge will be given a 'leftAngle' pointing from 'leftStart' to 'rightStart' and
- // the opposite will be given to objects on the right side of the bridge
- //
- Coord2D angleV;
- angleV.x = rightStart.x - leftStart.x;
- angleV.y = rightStart.y - leftStart.y;
- Real leftAngle = angleV.toAngle();
- Real rightAngle = leftAngle + TWO_PI;
- // compute vector from left to right across bridge and the reverse
- Coord3D leftVector;
- leftVector.x = rightStart.x - leftStart.x;
- leftVector.y = rightStart.y - leftStart.y;
- leftVector.z = rightStart.z - leftStart.z;
- Coord3D rightVector;
- rightVector.x = leftStart.x - rightStart.x;
- rightVector.y = leftStart.y - rightStart.y;
- rightVector.z = leftStart.z - rightStart.z;
- //
- // how many of these scaffold objects will take to tile from each of the endpoints
- // to the center area of the bridge
- //
- Real tileDistance = leftVector.length();
- Int numObjects = REAL_TO_INT_CEIL( tileDistance / spacing ) + 1;
- //
- // given the number of objects that we need to tile across the whole bridge, we will
- // go through the creation loop ceil( numObjects / 2.0f ) times, and each
- // time through the loop we'll create an object to move from each side of the
- // bridge, except the last object if the number of objects is odd is dead in the
- // center
- //
- Int numIterations = REAL_TO_INT_CEIL( INT_TO_REAL( numObjects ) / 2.0f );
- //
- // normalize left and right vectors as it is a vector that goes from our left start
- // position to the destination right start position ... we will multiply this vector by a
- // spacing amount and add to the left start position to find a destination position
- // for a particular scaffold object along the bridge surface
- //
- leftVector.normalize();
- rightVector.normalize();
- // create the scaffold objects for now
- Int scaffoldObjectsCreated = 0;
- Coord3D destinationPos, *riseToPos;
- Real *angle;
- Object *obj;
- for( Int i = 0; i < numIterations; ++i )
- {
- // sanity
- DEBUG_ASSERTCRASH( scaffoldObjectsCreated < numObjects,
- ("Creating too many scaffold objects\n") );
- // create object
- obj = TheThingFactory->newObject( scaffoldTemplate, us->getTeam() );
- // this object is from the "left" side of the bridge
- riseToPos = &leftStart;
- angle = &leftAngle;
- //
- // compute position for object moving from the left side, we're adding 0.1 here
- // so that all scaffold objects *have* to move some distance ... that way we
- // can just assign the speeds so they line up perfectly and not have to worry
- // about any object reaching a destination before any other object
- //
- destinationPos.x = leftVector.x * (spacing * i) + riseToPos->x + 0.1f;
- destinationPos.y = leftVector.y * (spacing * i) + riseToPos->y;
- destinationPos.z = leftVector.z * (spacing * i) + riseToPos->z;
- //
- // now that they key positions are calculated, set the rest of the position data
- // and movement speeds for the object
- //
- setScaffoldData( obj, angle, &scaffoldHeight, riseToPos, &destinationPos, center );
- // keeping track of objects created
- scaffoldObjectsCreated++;
- m_scaffoldObjectIDList.push_back( obj->getID() );
- //
- // create support object layers under the scaffold object, this object mirrors the scaffold
- // object except is on a lower layer
- //
- Real offset = riseToPos->z;
- Coord3D supportRiseToPos = *riseToPos;
- Coord3D supportDestinationPos = destinationPos;
- Coord3D supportBridgeCenter = *center;
- while( offset >= 0.0f )
- {
- supportRiseToPos.z -= scaffoldSupportHeight;
- supportDestinationPos.z -= scaffoldSupportHeight;
- supportBridgeCenter.z -= scaffoldSupportHeight;
- obj = TheThingFactory->newObject( scaffoldSupportTemplate, us->getTeam() );
- setScaffoldData( obj,
- angle,
- &scaffoldSupportHeight,
- &supportRiseToPos,
- &supportDestinationPos,
- &supportBridgeCenter );
- m_scaffoldObjectIDList.push_back( obj->getID() );
- // off to the next layer
- offset -= scaffoldSupportHeight;
- } // end while
- //
- // now create the object from the "right" side of the bridge ... but note that
- // we don't do this on the last iteration through this loop when we have an odd
- // number of objects we're tiling because all the space is already perfectly used up)
- //
- if( scaffoldObjectsCreated < numObjects )
- {
- // sanity
- DEBUG_ASSERTCRASH( scaffoldObjectsCreated < numObjects,
- ("Creating too many scaffold objects\n") );
- // create new object
- obj = TheThingFactory->newObject( scaffoldTemplate, us->getTeam() );
- // this object is on the "right" side of the bridge
- riseToPos = &rightStart;
- angle = &rightAngle;
- //
- // compute position for object moving from the left side, we're adding 0.1 here
- // so that all scaffold objects *have* to move some distance ... that way we
- // can just assign the speeds so they line up perfectly and not have to worry
- // about any object reaching a destination before any other object
- //
- destinationPos.x = rightVector.x * (spacing * i) + riseToPos->x + 0.1f;
- destinationPos.y = rightVector.y * (spacing * i) + riseToPos->y;
- destinationPos.z = rightVector.z * (spacing * i) + riseToPos->z;
- // set the rest scaffold data again
- setScaffoldData( obj, angle, &scaffoldHeight, riseToPos, &destinationPos, center );
- // keeping track of objects created
- scaffoldObjectsCreated++;
- m_scaffoldObjectIDList.push_back( obj->getID() );
- //
- // create support object layers under the scaffold object, this object mirrors the scaffold
- // object except is on a lower layer
- //
- Real offset = riseToPos->z;
- Coord3D supportRiseToPos = *riseToPos;
- Coord3D supportDestinationPos = destinationPos;
- Coord3D supportBridgeCenter = *center;
- while( offset >= 0.0f )
- {
- supportRiseToPos.z -= scaffoldSupportHeight;
- supportDestinationPos.z -= scaffoldSupportHeight;
- supportBridgeCenter.z -= scaffoldSupportHeight;
- obj = TheThingFactory->newObject( scaffoldSupportTemplate, us->getTeam() );
- setScaffoldData( obj,
- angle,
- &scaffoldSupportHeight,
- &supportRiseToPos,
- &supportDestinationPos,
- &supportBridgeCenter );
- m_scaffoldObjectIDList.push_back( obj->getID() );
- // off to the next layer
- offset -= scaffoldSupportHeight;
- } // end while
- } // end if
- } // end for i
- // scaffolding is now present
- m_scaffoldPresent = TRUE;
- // when scaffolding is present, a bridge cannot be used
- TheAI->pathfinder()->changeBridgeState( bridge->getLayer(), FALSE );
- } // end createScaffolding
- // ------------------------------------------------------------------------------------------------
- /** Remove the bridge scaffolding. If we don't have any then this call is ignored */
- // ------------------------------------------------------------------------------------------------
- void BridgeBehavior::removeScaffolding( void )
- {
- // if we have no scaffolding, do nothing
- if( m_scaffoldPresent == FALSE )
- return;
- // go through each object and tell them to reverse course
- Object *obj;
- ObjectIDListIterator it;
- BridgeScaffoldBehaviorInterface *scaffoldBehavior;
- for( it = m_scaffoldObjectIDList.begin(); it != m_scaffoldObjectIDList.end(); ++it )
- {
- // get the object
- obj = TheGameLogic->findObjectByID( (*it) );
- if( obj == NULL )
- continue;
- // get the scaffold behavior
- scaffoldBehavior = BridgeScaffoldBehavior::getBridgeScaffoldBehaviorInterfaceFromObject( obj );
- DEBUG_ASSERTCRASH( scaffoldBehavior, ("Unable to find bridge scaffold behavior interface\n") );
-
- // reverse the motion
- scaffoldBehavior->reverseMotion();
- } // end for, it
- // clear our scaffold object list
- m_scaffoldObjectIDList.clear();
- // scaffolding is no longer present
- m_scaffoldPresent = FALSE;
- // when scaffolding is gone, a bridge can be used again if we're not in a rubble state
- Object *us = getObject();
- BodyModuleInterface *body = us->getBodyModule();
- if( body->getDamageState() != BODY_RUBBLE )
- {
- Bridge *bridge = TheTerrainLogic->findBridgeAt( us->getPosition() );
- if( bridge )
- TheAI->pathfinder()->changeBridgeState( bridge->getLayer(), TRUE );
- } // end if
- } // end removeScaffolding
- // ------------------------------------------------------------------------------------------------
- /** Is any of the scaffolding in motion */
- // ------------------------------------------------------------------------------------------------
- Bool BridgeBehavior::isScaffoldInMotion( void )
- {
- Object *obj;
- // go through the scaffold objects, if any of them are in motion the scaffold is in motion
- ObjectIDListIterator it;
- for( it = m_scaffoldObjectIDList.begin(); it != m_scaffoldObjectIDList.end(); ++it )
- {
- // get object
- obj = TheGameLogic->findObjectByID( (*it) );
- if( obj == NULL )
- continue;
- // get scaffold interface
- BridgeScaffoldBehaviorInterface *bsbi = BridgeScaffoldBehavior::getBridgeScaffoldBehaviorInterfaceFromObject( obj );
- if( bsbi == NULL )
- continue;
- // check in motion
- if( bsbi->getCurrentMotion() != STM_STILL )
- return TRUE;
- } // end for
- // not in motion
- return FALSE;
- } // end isScaffoldInMotion
- // ------------------------------------------------------------------------------------------------
- /** CRC */
- // ------------------------------------------------------------------------------------------------
- void BridgeBehavior::crc( Xfer *xfer )
- {
- // extend base class
- UpdateModule::crc( xfer );
- } // end crc
- // ------------------------------------------------------------------------------------------------
- /** Xfer method
- * Version Info:
- * 1: Initial version */
- // ------------------------------------------------------------------------------------------------
- void BridgeBehavior::xfer( Xfer *xfer )
- {
- Object *us = getObject();
- // version
- XferVersion currentVersion = 1;
- XferVersion version = currentVersion;
- xfer->xferVersion( &version, currentVersion );
- // extend base class
- UpdateModule::xfer( xfer );
- // set us as the bridge object in the bridge info
- if( xfer->getXferMode() == XFER_LOAD )
- {
- Bridge *bridge = TheTerrainLogic->findBridgeAt( us->getPosition() );
- // sanity
- DEBUG_ASSERTCRASH( bridge, ("BridgeBehavior::xfer - Unable to find bridge\n" ));
- // set new object ID in bridge info to us
- bridge->setBridgeObjectID( us->getID() );
- } // end if
- // xfer the tower object ids
- for( Int i = 0; i < BRIDGE_MAX_TOWERS; ++i )
- xfer->xferObjectID( &m_towerID[ i ] );
- // set the tower object ids in the bridge info
- if( xfer->getXferMode() == XFER_LOAD )
- {
- Object *us = getObject();
- Bridge *bridge = TheTerrainLogic->findBridgeAt( us->getPosition() );
- // sanity
- DEBUG_ASSERTCRASH( bridge, ("BridgeBehavior::xfer - Unable to find bridge\n" ));
- // set new object ID in bridge info to us
- for( Int i = 0; i < BRIDGE_MAX_TOWERS; ++i )
- bridge->setTowerObjectID( m_towerID[ i ], (BridgeTowerType)i );
- } // end if
- // scaffold present flag
- xfer->xferBool( &m_scaffoldPresent );
- // scaffold object id list
- UnsignedShort scaffoldObjectCount = 0;
- scaffoldObjectCount = m_scaffoldObjectIDList.size();
- xfer->xferUnsignedShort( &scaffoldObjectCount );
- ObjectID scaffoldObjectID;
- if( xfer->getXferMode() == XFER_SAVE )
- {
-
- // write out all object IDs
- ObjectIDListIterator it;
- for( it = m_scaffoldObjectIDList.begin(); it != m_scaffoldObjectIDList.end(); ++it )
- {
- scaffoldObjectID = *it;
- xfer->xferObjectID( &scaffoldObjectID );
- } // end for
- } // end if, save
- else
- {
- // read all object IDs
- DEBUG_ASSERTCRASH( m_scaffoldObjectIDList.size() == 0,
- ("BridgeBehavior::xfer - scaffold object list should be empty\n") );
- for( Int i = 0; i < scaffoldObjectCount; ++i )
- {
- // read id
- xfer->xferObjectID( &scaffoldObjectID );
- // put on list
- m_scaffoldObjectIDList.push_back( scaffoldObjectID );
- } // end for i
- } // end load
- // death frame
- xfer->xferUnsignedInt( &m_deathFrame );
-
- } // end xfer
- // ------------------------------------------------------------------------------------------------
- /** Load post process */
- // ------------------------------------------------------------------------------------------------
- void BridgeBehavior::loadPostProcess( void )
- {
- // extend base class
- UpdateModule::loadPostProcess();
- } // end loadPostProcess
|