| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737 |
- /*
- ** 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: ParachuteContain.cpp //////////////////////////////////////////////////////////////////////
- // Author: Steven Johnson, March 2002
- // Desc: Contain module for transport units.
- ///////////////////////////////////////////////////////////////////////////////////////////////////
- // USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
- #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
- #include "Common/CRCDebug.h"
- #include "Common/Player.h"
- #include "Common/RandomValue.h"
- #include "Common/ThingTemplate.h"
- #include "Common/Xfer.h"
- #include "GameLogic/Locomotor.h"
- #include "GameLogic/Module/AIUpdate.h"
- #include "GameLogic/Module/ParachuteContain.h"
- #include "GameLogic/Module/PhysicsUpdate.h"
- #include "GameLogic/Object.h"
- #include "GameLogic/PartitionManager.h"
- #include "GameClient/Drawable.h"
- const Real NO_START_Z = 1e10;
- #ifdef _INTERNAL
- // for occasional debugging...
- //#pragma optimize("", off)
- //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
- #endif
- // PRIVATE ////////////////////////////////////////////////////////////////////////////////////////
- //-------------------------------------------------------------------------------------------------
- ParachuteContainModuleData::ParachuteContainModuleData() :
- m_pitchRateMax(0),
- m_rollRateMax(0),
- m_lowAltitudeDamping(0.2f),
- m_paraOpenDist(0.0f),
- m_freeFallDamagePercent(0.5f),
- m_killWhenLandingInWaterSlop(10.0f)
- {
- }
- //-------------------------------------------------------------------------------------------------
- void ParachuteContainModuleData::buildFieldParse(MultiIniFieldParse& p)
- {
- OpenContainModuleData::buildFieldParse(p);
- static const FieldParse dataFieldParse[] =
- {
- { "PitchRateMax", INI::parseAngularVelocityReal, NULL, offsetof( ParachuteContainModuleData, m_pitchRateMax ) },
- { "RollRateMax", INI::parseAngularVelocityReal, NULL, offsetof( ParachuteContainModuleData, m_rollRateMax ) },
- { "LowAltitudeDamping", INI::parseReal, NULL, offsetof( ParachuteContainModuleData, m_lowAltitudeDamping ) },
- { "ParachuteOpenDist", INI::parseReal, NULL, offsetof( ParachuteContainModuleData, m_paraOpenDist ) },
- { "KillWhenLandingInWaterSlop", INI::parseReal, NULL, offsetof( ParachuteContainModuleData, m_killWhenLandingInWaterSlop ) },
- { "FreeFallDamagePercent", INI::parsePercentToReal, NULL, offsetof( ParachuteContainModuleData, m_freeFallDamagePercent ) },
- { "ParachuteOpenSound", INI::parseAudioEventRTS, NULL, offsetof( ParachuteContainModuleData, m_parachuteOpenSound ) },
- { 0, 0, 0, 0 }
- };
- p.add(dataFieldParse);
- }
- // PUBLIC /////////////////////////////////////////////////////////////////////////////////////////
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- ParachuteContain::ParachuteContain( Thing *thing, const ModuleData *moduleData ) :
- OpenContain( thing, moduleData )
- {
- m_opened = false;
- m_needToUpdateParaBones = true;
- m_needToUpdateRiderBones = true;
- m_pitch = 0;
- m_roll = 0;
- m_pitchRate = 0;
- m_rollRate = 0;
- m_isLandingOverrideSet = FALSE;
- m_startZ = NO_START_Z;
-
- //Added By Sadullah Nader
- //Initializations
- m_landingOverride.zero();
- m_paraAttachBone.zero();
- m_paraAttachOffset.zero();
- m_paraSwayBone.zero();
- m_paraSwayOffset.zero();
- m_riderAttachBone.zero();
- m_riderAttachOffset.zero();
- m_riderSwayBone.zero();
- m_riderSwayOffset.zero();
- //
- const ParachuteContainModuleData* d = getParachuteContainModuleData();
- if (d)
- {
- m_pitchRate = GameLogicRandomValueReal(-d->m_pitchRateMax, d->m_pitchRateMax);
- m_rollRate = GameLogicRandomValueReal(-d->m_rollRateMax, d->m_rollRateMax);
- }
- getObject()->setStatus(OBJECT_STATUS_PARACHUTING);
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- ParachuteContain::~ParachuteContain( void )
- {
- }
- //-------------------------------------------------------------------------------------------------
- /**
- this is called whenever a drawable is bound to the object.
- drawable is NOT guaranteed to be non-null.
- */
- void ParachuteContain::onDrawableBoundToObject()
- {
- Drawable* draw = getObject()->getDrawable();
- if (draw)
- draw->setDrawableHidden(!m_opened);
- }
- //-------------------------------------------------------------------------------------------------
- void ParachuteContain::calcSwayMtx(const Coord3D* offset, Matrix3D* mtx)
- {
- mtx->Make_Identity();
- mtx->Translate(offset->x, offset->y, offset->z);
- mtx->In_Place_Pre_Rotate_X(m_roll);
- mtx->In_Place_Pre_Rotate_Y(m_pitch);
- mtx->Translate(-offset->x, -offset->y, -offset->z);
- }
- //-------------------------------------------------------------------------------------------------
- void ParachuteContain::updateBonePositions()
- {
- if (m_needToUpdateParaBones)
- {
- m_needToUpdateParaBones = false; // yeah, even if not found.
-
- Drawable* parachuteDraw = getObject()->getDrawable();
- if (parachuteDraw)
- {
- if (parachuteDraw->getPristineBonePositions( "PARA_COG", 0, &m_paraSwayBone, NULL, 1) != 1)
- {
- DEBUG_CRASH(("PARA_COG not found\n"));
- m_paraSwayBone.zero();
- }
- if (parachuteDraw->getPristineBonePositions( "PARA_ATTCH", 0, &m_paraAttachBone, NULL, 1 ) != 1)
- {
- DEBUG_CRASH(("PARA_ATTCH not found\n"));
- m_paraAttachBone.zero();
- }
- }
- //DEBUG_LOG(("updating para bone positions %d...\n",TheGameLogic->getFrame()));
- }
- if (m_needToUpdateRiderBones)
- {
- m_needToUpdateRiderBones = false; // yeah, even if not found.
- Object* rider = (getContainCount() > 0) ? getContainList().front() : NULL;
- Drawable* riderDraw = rider ? rider->getDrawable() : NULL;
- if (riderDraw)
- {
- if (riderDraw->getPristineBonePositions( "PARA_MAN", 0, &m_riderAttachBone, NULL, 1) != 1)
- {
- //DEBUG_LOG(("*** No parachute-attach bone... using object height!\n"));
- m_riderAttachBone.zero();
- m_riderAttachBone.z += riderDraw->getDrawableGeometryInfo().getMaxHeightAbovePosition();
- }
- }
- //DEBUG_LOG(("updating rider bone positions %d...\n",TheGameLogic->getFrame()));
- }
- }
- //-------------------------------------------------------------------------------------------------
- void ParachuteContain::updateOffsetsFromBones()
- {
- const Coord3D* objPos = getObject()->getPosition();
- getObject()->convertBonePosToWorldPos(&m_paraSwayBone, NULL, &m_paraSwayOffset, NULL);
- m_paraSwayOffset.x -= objPos->x;
- m_paraSwayOffset.y -= objPos->y;
- m_paraSwayOffset.z -= objPos->z;
- getObject()->convertBonePosToWorldPos(&m_paraAttachBone, NULL, &m_paraAttachOffset, NULL);
- m_paraAttachOffset.x -= objPos->x;
- m_paraAttachOffset.y -= objPos->y;
- m_paraAttachOffset.z -= objPos->z;
- Object* rider = (getContainCount() > 0) ? getContainList().front() : NULL;
- if (rider)
- {
- const Coord3D* riderPos = rider->getPosition();
- rider->convertBonePosToWorldPos(&m_riderAttachBone, NULL, &m_riderAttachOffset, NULL);
- m_riderAttachOffset.x -= riderPos->x;
- m_riderAttachOffset.y -= riderPos->y;
- m_riderAttachOffset.z -= riderPos->z;
- m_riderAttachOffset.x = m_paraAttachOffset.x - m_riderAttachOffset.x;
- m_riderAttachOffset.y = m_paraAttachOffset.y - m_riderAttachOffset.y;
- m_riderAttachOffset.z = m_paraAttachOffset.z - m_riderAttachOffset.z;
- m_riderSwayOffset.x = m_paraSwayOffset.x - m_riderAttachOffset.x;
- m_riderSwayOffset.y = m_paraSwayOffset.y - m_riderAttachOffset.y;
- m_riderSwayOffset.z = m_paraSwayOffset.z - m_riderAttachOffset.z;
- }
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- /**
- can this container contain this kind of object?
- and, if checkCapacity is TRUE, does this container have enough space left to hold the given unit?
- */
- Bool ParachuteContain::isValidContainerFor(const Object* rider, Bool checkCapacity) const
- {
- if (!rider)
- return false;
- // extend functionality
- if( OpenContain::isValidContainerFor( rider, checkCapacity ) == false )
- return false;
- Int transportSlotCount = rider->getTransportSlotCount();
- // if 0, this object isn't transportable.
- // (exception: infantry are always transportable by parachutes, regardless
- // of this.... this allows us to paradrop pilots, but not transport them
- // by other means)
- if (transportSlotCount == 0 && !rider->isKindOf(KINDOF_INFANTRY) && !rider->isKindOf(KINDOF_PARACHUTABLE))
- return false;
- // we can only "hold" one item at a time.
- if (getContainCount() > 0)
- return false;
- return true;
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- void ParachuteContain::containReactToTransformChange()
- {
- // a bit of a cheese festival here... hidden is a flag, not a counter, so when we are dumped
- // from a plane, we might get drawn for a frame before our update is called, meaning we
- // should be briefly visible. put this here to ensure we stay hidden appropriately.
- Drawable* draw = getObject()->getDrawable();
- if (draw)
- draw->setDrawableHidden(!m_opened);
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- UpdateSleepTime ParachuteContain::update( void )
- {
- OpenContain::update();
- Object* parachute = getObject();
- if( parachute->isDisabledByType( DISABLED_HELD ) )
- {
- return UPDATE_SLEEP_NONE; // my, that was easy
- }
- AIUpdateInterface *parachuteAI = parachute->getAI();
- Drawable* draw = parachute->getDrawable();
- const ParachuteContainModuleData* d = getParachuteContainModuleData();
- Object* rider = (getContainCount() > 0) ? getContainList().front() : NULL;
- if (m_startZ == NO_START_Z) {
- m_startZ = parachute->getPosition()->z;
- Real groundHeight = TheTerrainLogic->getGroundHeight(parachute->getPosition()->x, parachute->getPosition()->y);
- if (m_startZ-groundHeight < 2*d->m_paraOpenDist) {
- // Oh dear - we ejected too close to the ground, and there isn't enough
- // room to open the chute. Well, since it's only a game, we'll fudge
- // a little so that the pilot doesn't slam into the ground & stick.
- m_startZ = groundHeight+2*d->m_paraOpenDist;
- }
- }
- if (!m_opened)
- {
- // see if we need to open.
- if (fabs(m_startZ - parachute->getPosition()->z) >= d->m_paraOpenDist)
- {
- m_opened = true;
- parachute->clearAndSetModelConditionState(MODELCONDITION_FREEFALL, MODELCONDITION_PARACHUTING);
- m_needToUpdateParaBones = true;
- if (rider)
- {
- rider->clearAndSetModelConditionState(MODELCONDITION_FREEFALL, MODELCONDITION_PARACHUTING);
- m_needToUpdateRiderBones = true;
- AudioEventRTS soundToPlay = d->m_parachuteOpenSound;
- soundToPlay.setObjectID( rider->getID() );
- TheAudio->addAudioEvent( &soundToPlay );
- }
-
- // When a parachute opens, it should look for a good place to land. This could be explicitly set
- // by a DeliverPayload, otherwise any place clear is good.
- if( parachuteAI )
- {
- Coord3D target = *parachute->getPosition();
- if( m_isLandingOverrideSet )
- {
- target = m_landingOverride;
- if( parachuteAI->getCurLocomotor() )
- parachuteAI->getCurLocomotor()->setUltraAccurate( TRUE );
- }
- else
- {
- FindPositionOptions fpOptions;
- fpOptions.minRadius = 0.0f;
- fpOptions.maxRadius = 100.0f;
- fpOptions.relationshipObject = NULL;
- fpOptions.flags = FPF_NONE;
- ThePartitionManager->findPositionAround( &target, &fpOptions, &target );
- }
- parachuteAI->aiMoveToPosition( &target, CMD_FROM_AI );
- }
- }
- }
- draw->setDrawableHidden(!m_opened);
- if (!m_opened || getContainCount() == 0)
- {
- // unopened, or empty, chutes, don't collide with anything, to simplify
- // ejections, paradrops, landings, etc...
- parachute->setStatus(OBJECT_STATUS_NO_COLLISIONS);
- if (rider)
- rider->setStatus(OBJECT_STATUS_NO_COLLISIONS);
- }
- else
- {
- // opened/nonempty chutes DO collide...
- parachute->clearStatus(OBJECT_STATUS_NO_COLLISIONS);
- if (rider)
- rider->clearStatus(OBJECT_STATUS_NO_COLLISIONS);
- }
- AIUpdateInterface* ai = parachute->getAIUpdateInterface();
- if (ai && !parachute->isEffectivelyDead())
- {
- ai->chooseLocomotorSet(m_opened ? LOCOMOTORSET_NORMAL : LOCOMOTORSET_FREEFALL);
- Locomotor* locomotor = ai->getCurLocomotor();
- if (locomotor)
- {
- // damp the swaying a bunch when we get close, so that things land vertically (or nearly so)
- Real altitudeDamping = 0;
- if (getContainCount() > 0)
- {
- Object* rider = getContainList().front();
- const Real ALTITUDE_DAMP_START = 20.0f;
- if (rider->getHeightAboveTerrain() <= ALTITUDE_DAMP_START)
- altitudeDamping = d->m_lowAltitudeDamping;
- }
- if (m_opened)
- {
- const Real PITCH_STIFFNESS = locomotor->getPitchStiffness();
- const Real ROLL_STIFFNESS = locomotor->getRollStiffness();
- const Real PITCH_DAMPING = locomotor->getPitchDamping() + altitudeDamping;
- const Real ROLL_DAMPING = locomotor->getRollDamping() + altitudeDamping;
- m_pitchRate += ((-PITCH_STIFFNESS * m_pitch) + (-PITCH_DAMPING * m_pitchRate)); // spring/damper
- m_rollRate += ((-ROLL_STIFFNESS * m_roll) + (-ROLL_DAMPING * m_rollRate)); // spring/damper
- m_pitch += m_pitchRate;
- m_roll += m_rollRate;
- if( m_isLandingOverrideSet )
- {
- // Need to wait until after opening to do this, or else we are sending the message to the Freefall locomotor.
- locomotor->setCloseEnoughDist( 10.0 );
- locomotor->setCloseEnoughDist3D( FALSE );
- }
- }
- if (draw)
- {
- updateBonePositions();
- updateOffsetsFromBones();
- Matrix3D tmp;
- calcSwayMtx(&m_paraSwayOffset, &tmp);
- draw->setInstanceMatrix(&tmp);
- }
- positionContainedObjectsRelativeToContainer();
- }
- }
- // allow us to land on bridges!
- const Coord3D* paraPos = getObject()->getPosition();
- PathfindLayerEnum newLayer = TheTerrainLogic->getHighestLayerForDestination(paraPos);
- getObject()->setLayer(newLayer);
- if (rider)
- rider->setLayer(newLayer);
- // If we have lost our passenger for whatever reason, die early. Otherwise we just sit around forever.
- if( getContainCount() == 0 )
- getObject()->kill();
- // the collide system doesn't always collide us with the ground if we fall into water.
- // so force the issue.
- Real waterZ;
- if (!getObject()->isEffectivelyDead()
- && getObject()->getLayer() == LAYER_GROUND
- && TheTerrainLogic->isUnderwater(paraPos->x, paraPos->y, &waterZ)
- && (paraPos->z - waterZ) < d->m_killWhenLandingInWaterSlop)
- {
- getObject()->kill();
- }
- return UPDATE_SLEEP_NONE;
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- void ParachuteContain::onContaining( Object *rider )
- {
- OpenContain::onContaining(rider);
- // objects inside a transport are held
- rider->setDisabled( DISABLED_HELD );
- rider->setStatus(OBJECT_STATUS_PARACHUTING);
- rider->clearAndSetModelConditionState(MODELCONDITION_PARACHUTING, MODELCONDITION_FREEFALL);
- m_needToUpdateRiderBones = true;
- // position him correctly.
- positionRider(rider);
- }
- //-------------------------------------------------------------------------------------------------
- //-------------------------------------------------------------------------------------------------
- void ParachuteContain::onRemoving( Object *rider )
- {
- OpenContain::onRemoving(rider);
- const ParachuteContainModuleData* d = getParachuteContainModuleData();
- // object is no longer held inside a transport
- rider->clearDisabled( DISABLED_HELD );
- rider->clearStatus(OBJECT_STATUS_PARACHUTING);
- // mark parachute as "no-collisions"... it is just ephemeral at this point,
- // and having the chute collide with the soldier (and both bounce apart) is
- // just dumb-lookin'...
- getObject()->setStatus(OBJECT_STATUS_NO_COLLISIONS);
- // position him correctly.
- positionRider(rider);
- rider->clearModelConditionFlags(MAKE_MODELCONDITION_MASK2(MODELCONDITION_FREEFALL, MODELCONDITION_PARACHUTING));
- m_needToUpdateRiderBones = true;
- // temporarily mark the guy as being allowed to fall
- // (overriding his locomotor's stick-to-ground attribute).
- // this will be reset (by PhysicsBehavior) when he touches the ground.
- PhysicsBehavior* physics = rider->getPhysics();
- if (physics)
- {
- physics->setAllowToFall(true);
- Coord3D force;
- force.zero();
- physics->applyForce(&force); // force its physics to wake up... should be done when DISABLED_HELD is cleared, but it not, and scared to do it now.
- }
- AIUpdateInterface* riderAI = rider->getAIUpdateInterface();
- if (riderAI)
- {
- Player* controller = rider->getControllingPlayer();
- if (controller && controller->isSkirmishAIPlayer())
- riderAI->aiHunt(CMD_FROM_AI); // hunt, as per Dustin's request.
- else
- riderAI->aiIdle(CMD_FROM_AI); // become idle.
- }
-
- // if we land in the water, we die. alas.
- const Coord3D* riderPos = rider->getPosition();
- Real waterZ, terrainZ;
- if (TheTerrainLogic->isUnderwater(riderPos->x, riderPos->y, &waterZ, &terrainZ)
- && riderPos->z <= waterZ + d->m_killWhenLandingInWaterSlop
- && rider->getLayer() == LAYER_GROUND)
- {
- // don't call kill(); do it manually, so we can specify DEATH_FLOODED
- DamageInfo damageInfo;
- damageInfo.in.m_damageType = DAMAGE_WATER; // use this instead of UNRESISTABLE so we don't get a dusty damage effect
- damageInfo.in.m_deathType = DEATH_FLOODED;
- damageInfo.in.m_sourceID = INVALID_ID;
- damageInfo.in.m_amount = HUGE_DAMAGE_AMOUNT;
- rider->attemptDamage( &damageInfo );
- }
- }
- //-------------------------------------------------------------------------------------------------
- void ParachuteContain::positionRider(Object* rider)
- {
- updateBonePositions();
- updateOffsetsFromBones();
- Coord3D pos = *getObject()->getPosition();
- ///DUMPCOORD3D(&pos);
- pos.x += m_riderAttachOffset.x;
- pos.y += m_riderAttachOffset.y;
- pos.z += m_riderAttachOffset.z;
- //DUMPCOORD3D(&pos);
- rider->setPosition(&pos);
- Real alt = rider->getHeightAboveTerrain();
- if (alt < 0.0f)
- {
- // don't let him go below ground.
- pos.z -= alt;
- rider->setPosition(&pos);
- }
- rider->setOrientation(getObject()->getOrientation());
- Drawable* draw = rider->getDrawable();
- if (draw)
- {
- if( rider->isDisabledByType( DISABLED_HELD ) )
- {
- Matrix3D tmp;
- calcSwayMtx(&m_riderSwayOffset, &tmp);
- draw->setInstanceMatrix(&tmp);
- }
- else
- {
- draw->setInstanceMatrix(NULL);
- }
- }
- }
- //-------------------------------------------------------------------------------------------------
- void ParachuteContain::positionContainedObjectsRelativeToContainer()
- {
- for(ContainedItemsList::const_iterator it = getContainList().begin(); it != getContainList().end(); ++it)
- {
- positionRider(*it);
- }
- }
- //-------------------------------------------------------------------------------------------------
- void ParachuteContain::setOverrideDestination( const Coord3D *override )
- {
- // Instead of trying to float straight down, I am going to nail this spot.
- m_landingOverride = *override;
- m_isLandingOverrideSet = TRUE;
- }
- //-------------------------------------------------------------------------------------------------
- void ParachuteContain::onDie( const DamageInfo * damageInfo )
- {
- // if we are airborne when killed, the guy falls screaming to his death...
- if (getObject()->isSignificantlyAboveTerrain())
- {
- Object* rider = (getContainCount() > 0) ? getContainList().front() : NULL;
- if (rider)
- {
- removeAllContained();
- const ParachuteContainModuleData* d = getParachuteContainModuleData();
- if (d->m_freeFallDamagePercent > 0.0f)
- {
- // do some damage just for losing your parachute.
- // not very realistic, but practical to help ensure that
- // you really do die from going "splat" on the ground.
- DamageInfo extraDamageInfo;
- extraDamageInfo.in.m_damageType = DAMAGE_FALLING;
- extraDamageInfo.in.m_deathType = DEATH_SPLATTED;
- extraDamageInfo.in.m_sourceID = damageInfo->in.m_sourceID;
- extraDamageInfo.in.m_amount = rider->getBodyModule()->getMaxHealth() * d->m_freeFallDamagePercent;
- rider->attemptDamage(&extraDamageInfo);
- }
- PhysicsBehavior* physics = rider->getPhysics();
- if (physics)
- {
- physics->setAllowToFall(true);
- physics->setIsInFreeFall(true); // bwah ha ha
- Coord3D force;
- force.zero();
- physics->applyForce(&force); // force its physics to wake up... should be done when DISABLED_HELD is cleared, but it not, and scared to do it now.
- }
- }
- }
- OpenContain::onDie(damageInfo);
- }
- //-------------------------------------------------------------------------------------------------
- void ParachuteContain::onCollide( Object *other, const Coord3D *loc, const Coord3D *normal )
- {
- // Note that other == null means "collide with ground"
- if( other == NULL )
- {
- // if we're in a container (eg, a transport plane), just ignore this...
- if( getObject()->getContainedBy() != NULL )
- return;
- removeAllContained();
- // TheGameLogic->destroyObject(obj);
- // kill it, so that the chute's SlowDeath will trigger!
- getObject()->kill();
- }
- }
- // ------------------------------------------------------------------------------------------------
- /** CRC */
- // ------------------------------------------------------------------------------------------------
- void ParachuteContain::crc( Xfer *xfer )
- {
- // extend base class
- OpenContain::crc( xfer );
- } // end crc
- // ------------------------------------------------------------------------------------------------
- /** Xfer method
- * Version Info:
- * 1: Initial version */
- // ------------------------------------------------------------------------------------------------
- void ParachuteContain::xfer( Xfer *xfer )
- {
- // version
- XferVersion currentVersion = 1;
- XferVersion version = currentVersion;
- xfer->xferVersion( &version, currentVersion );
- // extend base class
- OpenContain::xfer( xfer );
- // pitch
- xfer->xferReal( &m_pitch );
- // roll
- xfer->xferReal( &m_roll );
- // pitch rage
- xfer->xferReal( &m_pitchRate );
- // roll rate
- xfer->xferReal( &m_rollRate );
- // start Z
- xfer->xferReal( &m_startZ );
- // is landing override set
- xfer->xferBool( &m_isLandingOverrideSet );
-
- // landing override
- xfer->xferCoord3D( &m_landingOverride );
- // rider attach bone
- xfer->xferCoord3D( &m_riderAttachBone );
- // rider sway bone
- xfer->xferCoord3D( &m_riderSwayBone );
- // para attach bone
- xfer->xferCoord3D( &m_paraAttachBone );
- // para sway bone
- xfer->xferCoord3D( &m_paraSwayBone );
- // rider attach offset
- xfer->xferCoord3D( &m_riderAttachOffset );
- // rider sway offset
- xfer->xferCoord3D( &m_riderSwayOffset );
- // para attach offset
- xfer->xferCoord3D( &m_paraAttachOffset );
- // para sway offset
- xfer->xferCoord3D( &m_paraSwayOffset );
- // need to update rider bones
- xfer->xferBool( &m_needToUpdateRiderBones );
- // need to update para bones
- xfer->xferBool( &m_needToUpdateParaBones );
- // opened
- xfer->xferBool( &m_opened );
- } // end xfer
- // ------------------------------------------------------------------------------------------------
- /** Load post process */
- // ------------------------------------------------------------------------------------------------
- void ParachuteContain::loadPostProcess( void )
- {
- // extend base class
- OpenContain::loadPostProcess();
- } // end loadPostProcess
|