ParachuteContain.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  1. /*
  2. ** Command & Conquer Generals(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. ////////////////////////////////////////////////////////////////////////////////
  19. // //
  20. // (c) 2001-2003 Electronic Arts Inc. //
  21. // //
  22. ////////////////////////////////////////////////////////////////////////////////
  23. // FILE: ParachuteContain.cpp //////////////////////////////////////////////////////////////////////
  24. // Author: Steven Johnson, March 2002
  25. // Desc: Contain module for transport units.
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. // USER INCLUDES //////////////////////////////////////////////////////////////////////////////////
  28. #include "PreRTS.h" // This must go first in EVERY cpp file int the GameEngine
  29. #include "Common/CRCDebug.h"
  30. #include "Common/Player.h"
  31. #include "Common/RandomValue.h"
  32. #include "Common/ThingTemplate.h"
  33. #include "Common/Xfer.h"
  34. #include "GameLogic/Locomotor.h"
  35. #include "GameLogic/Module/AIUpdate.h"
  36. #include "GameLogic/Module/ParachuteContain.h"
  37. #include "GameLogic/Module/PhysicsUpdate.h"
  38. #include "GameLogic/Object.h"
  39. #include "GameLogic/PartitionManager.h"
  40. #include "GameClient/Drawable.h"
  41. const Real NO_START_Z = 1e10;
  42. #ifdef _INTERNAL
  43. // for occasional debugging...
  44. //#pragma optimize("", off)
  45. //#pragma MESSAGE("************************************** WARNING, optimization disabled for debugging purposes")
  46. #endif
  47. // PRIVATE ////////////////////////////////////////////////////////////////////////////////////////
  48. //-------------------------------------------------------------------------------------------------
  49. ParachuteContainModuleData::ParachuteContainModuleData() :
  50. m_pitchRateMax(0),
  51. m_rollRateMax(0),
  52. m_lowAltitudeDamping(0.2f),
  53. m_paraOpenDist(0.0f),
  54. m_freeFallDamagePercent(0.5f),
  55. m_killWhenLandingInWaterSlop(10.0f)
  56. {
  57. }
  58. //-------------------------------------------------------------------------------------------------
  59. void ParachuteContainModuleData::buildFieldParse(MultiIniFieldParse& p)
  60. {
  61. OpenContainModuleData::buildFieldParse(p);
  62. static const FieldParse dataFieldParse[] =
  63. {
  64. { "PitchRateMax", INI::parseAngularVelocityReal, NULL, offsetof( ParachuteContainModuleData, m_pitchRateMax ) },
  65. { "RollRateMax", INI::parseAngularVelocityReal, NULL, offsetof( ParachuteContainModuleData, m_rollRateMax ) },
  66. { "LowAltitudeDamping", INI::parseReal, NULL, offsetof( ParachuteContainModuleData, m_lowAltitudeDamping ) },
  67. { "ParachuteOpenDist", INI::parseReal, NULL, offsetof( ParachuteContainModuleData, m_paraOpenDist ) },
  68. { "KillWhenLandingInWaterSlop", INI::parseReal, NULL, offsetof( ParachuteContainModuleData, m_killWhenLandingInWaterSlop ) },
  69. { "FreeFallDamagePercent", INI::parsePercentToReal, NULL, offsetof( ParachuteContainModuleData, m_freeFallDamagePercent ) },
  70. { "ParachuteOpenSound", INI::parseAudioEventRTS, NULL, offsetof( ParachuteContainModuleData, m_parachuteOpenSound ) },
  71. { 0, 0, 0, 0 }
  72. };
  73. p.add(dataFieldParse);
  74. }
  75. // PUBLIC /////////////////////////////////////////////////////////////////////////////////////////
  76. //-------------------------------------------------------------------------------------------------
  77. //-------------------------------------------------------------------------------------------------
  78. ParachuteContain::ParachuteContain( Thing *thing, const ModuleData *moduleData ) :
  79. OpenContain( thing, moduleData )
  80. {
  81. m_opened = false;
  82. m_needToUpdateParaBones = true;
  83. m_needToUpdateRiderBones = true;
  84. m_pitch = 0;
  85. m_roll = 0;
  86. m_pitchRate = 0;
  87. m_rollRate = 0;
  88. m_isLandingOverrideSet = FALSE;
  89. m_startZ = NO_START_Z;
  90. //Added By Sadullah Nader
  91. //Initializations
  92. m_landingOverride.zero();
  93. m_paraAttachBone.zero();
  94. m_paraAttachOffset.zero();
  95. m_paraSwayBone.zero();
  96. m_paraSwayOffset.zero();
  97. m_riderAttachBone.zero();
  98. m_riderAttachOffset.zero();
  99. m_riderSwayBone.zero();
  100. m_riderSwayOffset.zero();
  101. //
  102. const ParachuteContainModuleData* d = getParachuteContainModuleData();
  103. if (d)
  104. {
  105. m_pitchRate = GameLogicRandomValueReal(-d->m_pitchRateMax, d->m_pitchRateMax);
  106. m_rollRate = GameLogicRandomValueReal(-d->m_rollRateMax, d->m_rollRateMax);
  107. }
  108. getObject()->setStatus(OBJECT_STATUS_PARACHUTING);
  109. }
  110. //-------------------------------------------------------------------------------------------------
  111. //-------------------------------------------------------------------------------------------------
  112. ParachuteContain::~ParachuteContain( void )
  113. {
  114. }
  115. //-------------------------------------------------------------------------------------------------
  116. /**
  117. this is called whenever a drawable is bound to the object.
  118. drawable is NOT guaranteed to be non-null.
  119. */
  120. void ParachuteContain::onDrawableBoundToObject()
  121. {
  122. Drawable* draw = getObject()->getDrawable();
  123. if (draw)
  124. draw->setDrawableHidden(!m_opened);
  125. }
  126. //-------------------------------------------------------------------------------------------------
  127. void ParachuteContain::calcSwayMtx(const Coord3D* offset, Matrix3D* mtx)
  128. {
  129. mtx->Make_Identity();
  130. mtx->Translate(offset->x, offset->y, offset->z);
  131. mtx->In_Place_Pre_Rotate_X(m_roll);
  132. mtx->In_Place_Pre_Rotate_Y(m_pitch);
  133. mtx->Translate(-offset->x, -offset->y, -offset->z);
  134. }
  135. //-------------------------------------------------------------------------------------------------
  136. void ParachuteContain::updateBonePositions()
  137. {
  138. if (m_needToUpdateParaBones)
  139. {
  140. m_needToUpdateParaBones = false; // yeah, even if not found.
  141. Drawable* parachuteDraw = getObject()->getDrawable();
  142. if (parachuteDraw)
  143. {
  144. if (parachuteDraw->getPristineBonePositions( "PARA_COG", 0, &m_paraSwayBone, NULL, 1) != 1)
  145. {
  146. DEBUG_CRASH(("PARA_COG not found\n"));
  147. m_paraSwayBone.zero();
  148. }
  149. if (parachuteDraw->getPristineBonePositions( "PARA_ATTCH", 0, &m_paraAttachBone, NULL, 1 ) != 1)
  150. {
  151. DEBUG_CRASH(("PARA_ATTCH not found\n"));
  152. m_paraAttachBone.zero();
  153. }
  154. }
  155. //DEBUG_LOG(("updating para bone positions %d...\n",TheGameLogic->getFrame()));
  156. }
  157. if (m_needToUpdateRiderBones)
  158. {
  159. m_needToUpdateRiderBones = false; // yeah, even if not found.
  160. Object* rider = (getContainCount() > 0) ? getContainList().front() : NULL;
  161. Drawable* riderDraw = rider ? rider->getDrawable() : NULL;
  162. if (riderDraw)
  163. {
  164. if (riderDraw->getPristineBonePositions( "PARA_MAN", 0, &m_riderAttachBone, NULL, 1) != 1)
  165. {
  166. //DEBUG_LOG(("*** No parachute-attach bone... using object height!\n"));
  167. m_riderAttachBone.zero();
  168. m_riderAttachBone.z += riderDraw->getDrawableGeometryInfo().getMaxHeightAbovePosition();
  169. }
  170. }
  171. //DEBUG_LOG(("updating rider bone positions %d...\n",TheGameLogic->getFrame()));
  172. }
  173. }
  174. //-------------------------------------------------------------------------------------------------
  175. void ParachuteContain::updateOffsetsFromBones()
  176. {
  177. const Coord3D* objPos = getObject()->getPosition();
  178. getObject()->convertBonePosToWorldPos(&m_paraSwayBone, NULL, &m_paraSwayOffset, NULL);
  179. m_paraSwayOffset.x -= objPos->x;
  180. m_paraSwayOffset.y -= objPos->y;
  181. m_paraSwayOffset.z -= objPos->z;
  182. getObject()->convertBonePosToWorldPos(&m_paraAttachBone, NULL, &m_paraAttachOffset, NULL);
  183. m_paraAttachOffset.x -= objPos->x;
  184. m_paraAttachOffset.y -= objPos->y;
  185. m_paraAttachOffset.z -= objPos->z;
  186. Object* rider = (getContainCount() > 0) ? getContainList().front() : NULL;
  187. if (rider)
  188. {
  189. const Coord3D* riderPos = rider->getPosition();
  190. rider->convertBonePosToWorldPos(&m_riderAttachBone, NULL, &m_riderAttachOffset, NULL);
  191. m_riderAttachOffset.x -= riderPos->x;
  192. m_riderAttachOffset.y -= riderPos->y;
  193. m_riderAttachOffset.z -= riderPos->z;
  194. m_riderAttachOffset.x = m_paraAttachOffset.x - m_riderAttachOffset.x;
  195. m_riderAttachOffset.y = m_paraAttachOffset.y - m_riderAttachOffset.y;
  196. m_riderAttachOffset.z = m_paraAttachOffset.z - m_riderAttachOffset.z;
  197. m_riderSwayOffset.x = m_paraSwayOffset.x - m_riderAttachOffset.x;
  198. m_riderSwayOffset.y = m_paraSwayOffset.y - m_riderAttachOffset.y;
  199. m_riderSwayOffset.z = m_paraSwayOffset.z - m_riderAttachOffset.z;
  200. }
  201. }
  202. //-------------------------------------------------------------------------------------------------
  203. //-------------------------------------------------------------------------------------------------
  204. /**
  205. can this container contain this kind of object?
  206. and, if checkCapacity is TRUE, does this container have enough space left to hold the given unit?
  207. */
  208. Bool ParachuteContain::isValidContainerFor(const Object* rider, Bool checkCapacity) const
  209. {
  210. if (!rider)
  211. return false;
  212. // extend functionality
  213. if( OpenContain::isValidContainerFor( rider, checkCapacity ) == false )
  214. return false;
  215. Int transportSlotCount = rider->getTransportSlotCount();
  216. // if 0, this object isn't transportable.
  217. // (exception: infantry are always transportable by parachutes, regardless
  218. // of this.... this allows us to paradrop pilots, but not transport them
  219. // by other means)
  220. if (transportSlotCount == 0 && !rider->isKindOf(KINDOF_INFANTRY) && !rider->isKindOf(KINDOF_PARACHUTABLE))
  221. return false;
  222. // we can only "hold" one item at a time.
  223. if (getContainCount() > 0)
  224. return false;
  225. return true;
  226. }
  227. //-------------------------------------------------------------------------------------------------
  228. //-------------------------------------------------------------------------------------------------
  229. void ParachuteContain::containReactToTransformChange()
  230. {
  231. // a bit of a cheese festival here... hidden is a flag, not a counter, so when we are dumped
  232. // from a plane, we might get drawn for a frame before our update is called, meaning we
  233. // should be briefly visible. put this here to ensure we stay hidden appropriately.
  234. Drawable* draw = getObject()->getDrawable();
  235. if (draw)
  236. draw->setDrawableHidden(!m_opened);
  237. }
  238. //-------------------------------------------------------------------------------------------------
  239. //-------------------------------------------------------------------------------------------------
  240. UpdateSleepTime ParachuteContain::update( void )
  241. {
  242. OpenContain::update();
  243. Object* parachute = getObject();
  244. if( parachute->isDisabledByType( DISABLED_HELD ) )
  245. {
  246. return UPDATE_SLEEP_NONE; // my, that was easy
  247. }
  248. AIUpdateInterface *parachuteAI = parachute->getAI();
  249. Drawable* draw = parachute->getDrawable();
  250. const ParachuteContainModuleData* d = getParachuteContainModuleData();
  251. Object* rider = (getContainCount() > 0) ? getContainList().front() : NULL;
  252. if (m_startZ == NO_START_Z) {
  253. m_startZ = parachute->getPosition()->z;
  254. Real groundHeight = TheTerrainLogic->getGroundHeight(parachute->getPosition()->x, parachute->getPosition()->y);
  255. if (m_startZ-groundHeight < 2*d->m_paraOpenDist) {
  256. // Oh dear - we ejected too close to the ground, and there isn't enough
  257. // room to open the chute. Well, since it's only a game, we'll fudge
  258. // a little so that the pilot doesn't slam into the ground & stick.
  259. m_startZ = groundHeight+2*d->m_paraOpenDist;
  260. }
  261. }
  262. if (!m_opened)
  263. {
  264. // see if we need to open.
  265. if (fabs(m_startZ - parachute->getPosition()->z) >= d->m_paraOpenDist)
  266. {
  267. m_opened = true;
  268. parachute->clearAndSetModelConditionState(MODELCONDITION_FREEFALL, MODELCONDITION_PARACHUTING);
  269. m_needToUpdateParaBones = true;
  270. if (rider)
  271. {
  272. rider->clearAndSetModelConditionState(MODELCONDITION_FREEFALL, MODELCONDITION_PARACHUTING);
  273. m_needToUpdateRiderBones = true;
  274. AudioEventRTS soundToPlay = d->m_parachuteOpenSound;
  275. soundToPlay.setObjectID( rider->getID() );
  276. TheAudio->addAudioEvent( &soundToPlay );
  277. }
  278. // When a parachute opens, it should look for a good place to land. This could be explicitly set
  279. // by a DeliverPayload, otherwise any place clear is good.
  280. if( parachuteAI )
  281. {
  282. Coord3D target = *parachute->getPosition();
  283. if( m_isLandingOverrideSet )
  284. {
  285. target = m_landingOverride;
  286. if( parachuteAI->getCurLocomotor() )
  287. parachuteAI->getCurLocomotor()->setUltraAccurate( TRUE );
  288. }
  289. else
  290. {
  291. FindPositionOptions fpOptions;
  292. fpOptions.minRadius = 0.0f;
  293. fpOptions.maxRadius = 100.0f;
  294. fpOptions.relationshipObject = NULL;
  295. fpOptions.flags = FPF_NONE;
  296. ThePartitionManager->findPositionAround( &target, &fpOptions, &target );
  297. }
  298. parachuteAI->aiMoveToPosition( &target, CMD_FROM_AI );
  299. }
  300. }
  301. }
  302. draw->setDrawableHidden(!m_opened);
  303. if (!m_opened || getContainCount() == 0)
  304. {
  305. // unopened, or empty, chutes, don't collide with anything, to simplify
  306. // ejections, paradrops, landings, etc...
  307. parachute->setStatus(OBJECT_STATUS_NO_COLLISIONS);
  308. if (rider)
  309. rider->setStatus(OBJECT_STATUS_NO_COLLISIONS);
  310. }
  311. else
  312. {
  313. // opened/nonempty chutes DO collide...
  314. parachute->clearStatus(OBJECT_STATUS_NO_COLLISIONS);
  315. if (rider)
  316. rider->clearStatus(OBJECT_STATUS_NO_COLLISIONS);
  317. }
  318. AIUpdateInterface* ai = parachute->getAIUpdateInterface();
  319. if (ai && !parachute->isEffectivelyDead())
  320. {
  321. ai->chooseLocomotorSet(m_opened ? LOCOMOTORSET_NORMAL : LOCOMOTORSET_FREEFALL);
  322. Locomotor* locomotor = ai->getCurLocomotor();
  323. if (locomotor)
  324. {
  325. // damp the swaying a bunch when we get close, so that things land vertically (or nearly so)
  326. Real altitudeDamping = 0;
  327. if (getContainCount() > 0)
  328. {
  329. Object* rider = getContainList().front();
  330. const Real ALTITUDE_DAMP_START = 20.0f;
  331. if (rider->getHeightAboveTerrain() <= ALTITUDE_DAMP_START)
  332. altitudeDamping = d->m_lowAltitudeDamping;
  333. }
  334. if (m_opened)
  335. {
  336. const Real PITCH_STIFFNESS = locomotor->getPitchStiffness();
  337. const Real ROLL_STIFFNESS = locomotor->getRollStiffness();
  338. const Real PITCH_DAMPING = locomotor->getPitchDamping() + altitudeDamping;
  339. const Real ROLL_DAMPING = locomotor->getRollDamping() + altitudeDamping;
  340. m_pitchRate += ((-PITCH_STIFFNESS * m_pitch) + (-PITCH_DAMPING * m_pitchRate)); // spring/damper
  341. m_rollRate += ((-ROLL_STIFFNESS * m_roll) + (-ROLL_DAMPING * m_rollRate)); // spring/damper
  342. m_pitch += m_pitchRate;
  343. m_roll += m_rollRate;
  344. if( m_isLandingOverrideSet )
  345. {
  346. // Need to wait until after opening to do this, or else we are sending the message to the Freefall locomotor.
  347. locomotor->setCloseEnoughDist( 10.0 );
  348. locomotor->setCloseEnoughDist3D( FALSE );
  349. }
  350. }
  351. if (draw)
  352. {
  353. updateBonePositions();
  354. updateOffsetsFromBones();
  355. Matrix3D tmp;
  356. calcSwayMtx(&m_paraSwayOffset, &tmp);
  357. draw->setInstanceMatrix(&tmp);
  358. }
  359. positionContainedObjectsRelativeToContainer();
  360. }
  361. }
  362. // allow us to land on bridges!
  363. const Coord3D* paraPos = getObject()->getPosition();
  364. PathfindLayerEnum newLayer = TheTerrainLogic->getHighestLayerForDestination(paraPos);
  365. getObject()->setLayer(newLayer);
  366. if (rider)
  367. rider->setLayer(newLayer);
  368. // If we have lost our passenger for whatever reason, die early. Otherwise we just sit around forever.
  369. if( getContainCount() == 0 )
  370. getObject()->kill();
  371. // the collide system doesn't always collide us with the ground if we fall into water.
  372. // so force the issue.
  373. Real waterZ;
  374. if (!getObject()->isEffectivelyDead()
  375. && getObject()->getLayer() == LAYER_GROUND
  376. && TheTerrainLogic->isUnderwater(paraPos->x, paraPos->y, &waterZ)
  377. && (paraPos->z - waterZ) < d->m_killWhenLandingInWaterSlop)
  378. {
  379. getObject()->kill();
  380. }
  381. return UPDATE_SLEEP_NONE;
  382. }
  383. //-------------------------------------------------------------------------------------------------
  384. //-------------------------------------------------------------------------------------------------
  385. void ParachuteContain::onContaining( Object *rider )
  386. {
  387. OpenContain::onContaining(rider);
  388. // objects inside a transport are held
  389. rider->setDisabled( DISABLED_HELD );
  390. rider->setStatus(OBJECT_STATUS_PARACHUTING);
  391. rider->clearAndSetModelConditionState(MODELCONDITION_PARACHUTING, MODELCONDITION_FREEFALL);
  392. m_needToUpdateRiderBones = true;
  393. // position him correctly.
  394. positionRider(rider);
  395. }
  396. //-------------------------------------------------------------------------------------------------
  397. //-------------------------------------------------------------------------------------------------
  398. void ParachuteContain::onRemoving( Object *rider )
  399. {
  400. OpenContain::onRemoving(rider);
  401. const ParachuteContainModuleData* d = getParachuteContainModuleData();
  402. // object is no longer held inside a transport
  403. rider->clearDisabled( DISABLED_HELD );
  404. rider->clearStatus(OBJECT_STATUS_PARACHUTING);
  405. // mark parachute as "no-collisions"... it is just ephemeral at this point,
  406. // and having the chute collide with the soldier (and both bounce apart) is
  407. // just dumb-lookin'...
  408. getObject()->setStatus(OBJECT_STATUS_NO_COLLISIONS);
  409. // position him correctly.
  410. positionRider(rider);
  411. rider->clearModelConditionFlags(MAKE_MODELCONDITION_MASK2(MODELCONDITION_FREEFALL, MODELCONDITION_PARACHUTING));
  412. m_needToUpdateRiderBones = true;
  413. // temporarily mark the guy as being allowed to fall
  414. // (overriding his locomotor's stick-to-ground attribute).
  415. // this will be reset (by PhysicsBehavior) when he touches the ground.
  416. PhysicsBehavior* physics = rider->getPhysics();
  417. if (physics)
  418. {
  419. physics->setAllowToFall(true);
  420. Coord3D force;
  421. force.zero();
  422. 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.
  423. }
  424. AIUpdateInterface* riderAI = rider->getAIUpdateInterface();
  425. if (riderAI)
  426. {
  427. Player* controller = rider->getControllingPlayer();
  428. if (controller && controller->isSkirmishAIPlayer())
  429. riderAI->aiHunt(CMD_FROM_AI); // hunt, as per Dustin's request.
  430. else
  431. riderAI->aiIdle(CMD_FROM_AI); // become idle.
  432. }
  433. // if we land in the water, we die. alas.
  434. const Coord3D* riderPos = rider->getPosition();
  435. Real waterZ, terrainZ;
  436. if (TheTerrainLogic->isUnderwater(riderPos->x, riderPos->y, &waterZ, &terrainZ)
  437. && riderPos->z <= waterZ + d->m_killWhenLandingInWaterSlop
  438. && rider->getLayer() == LAYER_GROUND)
  439. {
  440. // don't call kill(); do it manually, so we can specify DEATH_FLOODED
  441. DamageInfo damageInfo;
  442. damageInfo.in.m_damageType = DAMAGE_WATER; // use this instead of UNRESISTABLE so we don't get a dusty damage effect
  443. damageInfo.in.m_deathType = DEATH_FLOODED;
  444. damageInfo.in.m_sourceID = INVALID_ID;
  445. damageInfo.in.m_amount = HUGE_DAMAGE_AMOUNT;
  446. rider->attemptDamage( &damageInfo );
  447. }
  448. }
  449. //-------------------------------------------------------------------------------------------------
  450. void ParachuteContain::positionRider(Object* rider)
  451. {
  452. updateBonePositions();
  453. updateOffsetsFromBones();
  454. Coord3D pos = *getObject()->getPosition();
  455. ///DUMPCOORD3D(&pos);
  456. pos.x += m_riderAttachOffset.x;
  457. pos.y += m_riderAttachOffset.y;
  458. pos.z += m_riderAttachOffset.z;
  459. //DUMPCOORD3D(&pos);
  460. rider->setPosition(&pos);
  461. Real alt = rider->getHeightAboveTerrain();
  462. if (alt < 0.0f)
  463. {
  464. // don't let him go below ground.
  465. pos.z -= alt;
  466. rider->setPosition(&pos);
  467. }
  468. rider->setOrientation(getObject()->getOrientation());
  469. Drawable* draw = rider->getDrawable();
  470. if (draw)
  471. {
  472. if( rider->isDisabledByType( DISABLED_HELD ) )
  473. {
  474. Matrix3D tmp;
  475. calcSwayMtx(&m_riderSwayOffset, &tmp);
  476. draw->setInstanceMatrix(&tmp);
  477. }
  478. else
  479. {
  480. draw->setInstanceMatrix(NULL);
  481. }
  482. }
  483. }
  484. //-------------------------------------------------------------------------------------------------
  485. void ParachuteContain::positionContainedObjectsRelativeToContainer()
  486. {
  487. for(ContainedItemsList::const_iterator it = getContainList().begin(); it != getContainList().end(); ++it)
  488. {
  489. positionRider(*it);
  490. }
  491. }
  492. //-------------------------------------------------------------------------------------------------
  493. void ParachuteContain::setOverrideDestination( const Coord3D *override )
  494. {
  495. // Instead of trying to float straight down, I am going to nail this spot.
  496. m_landingOverride = *override;
  497. m_isLandingOverrideSet = TRUE;
  498. }
  499. //-------------------------------------------------------------------------------------------------
  500. void ParachuteContain::onDie( const DamageInfo * damageInfo )
  501. {
  502. // if we are airborne when killed, the guy falls screaming to his death...
  503. if (getObject()->isSignificantlyAboveTerrain())
  504. {
  505. Object* rider = (getContainCount() > 0) ? getContainList().front() : NULL;
  506. if (rider)
  507. {
  508. removeAllContained();
  509. const ParachuteContainModuleData* d = getParachuteContainModuleData();
  510. if (d->m_freeFallDamagePercent > 0.0f)
  511. {
  512. // do some damage just for losing your parachute.
  513. // not very realistic, but practical to help ensure that
  514. // you really do die from going "splat" on the ground.
  515. DamageInfo extraDamageInfo;
  516. extraDamageInfo.in.m_damageType = DAMAGE_FALLING;
  517. extraDamageInfo.in.m_deathType = DEATH_SPLATTED;
  518. extraDamageInfo.in.m_sourceID = damageInfo->in.m_sourceID;
  519. extraDamageInfo.in.m_amount = rider->getBodyModule()->getMaxHealth() * d->m_freeFallDamagePercent;
  520. rider->attemptDamage(&extraDamageInfo);
  521. }
  522. PhysicsBehavior* physics = rider->getPhysics();
  523. if (physics)
  524. {
  525. physics->setAllowToFall(true);
  526. physics->setIsInFreeFall(true); // bwah ha ha
  527. Coord3D force;
  528. force.zero();
  529. 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.
  530. }
  531. }
  532. }
  533. OpenContain::onDie(damageInfo);
  534. }
  535. //-------------------------------------------------------------------------------------------------
  536. void ParachuteContain::onCollide( Object *other, const Coord3D *loc, const Coord3D *normal )
  537. {
  538. // Note that other == null means "collide with ground"
  539. if( other == NULL )
  540. {
  541. // if we're in a container (eg, a transport plane), just ignore this...
  542. if( getObject()->getContainedBy() != NULL )
  543. return;
  544. removeAllContained();
  545. // TheGameLogic->destroyObject(obj);
  546. // kill it, so that the chute's SlowDeath will trigger!
  547. getObject()->kill();
  548. }
  549. }
  550. // ------------------------------------------------------------------------------------------------
  551. /** CRC */
  552. // ------------------------------------------------------------------------------------------------
  553. void ParachuteContain::crc( Xfer *xfer )
  554. {
  555. // extend base class
  556. OpenContain::crc( xfer );
  557. } // end crc
  558. // ------------------------------------------------------------------------------------------------
  559. /** Xfer method
  560. * Version Info:
  561. * 1: Initial version */
  562. // ------------------------------------------------------------------------------------------------
  563. void ParachuteContain::xfer( Xfer *xfer )
  564. {
  565. // version
  566. XferVersion currentVersion = 1;
  567. XferVersion version = currentVersion;
  568. xfer->xferVersion( &version, currentVersion );
  569. // extend base class
  570. OpenContain::xfer( xfer );
  571. // pitch
  572. xfer->xferReal( &m_pitch );
  573. // roll
  574. xfer->xferReal( &m_roll );
  575. // pitch rage
  576. xfer->xferReal( &m_pitchRate );
  577. // roll rate
  578. xfer->xferReal( &m_rollRate );
  579. // start Z
  580. xfer->xferReal( &m_startZ );
  581. // is landing override set
  582. xfer->xferBool( &m_isLandingOverrideSet );
  583. // landing override
  584. xfer->xferCoord3D( &m_landingOverride );
  585. // rider attach bone
  586. xfer->xferCoord3D( &m_riderAttachBone );
  587. // rider sway bone
  588. xfer->xferCoord3D( &m_riderSwayBone );
  589. // para attach bone
  590. xfer->xferCoord3D( &m_paraAttachBone );
  591. // para sway bone
  592. xfer->xferCoord3D( &m_paraSwayBone );
  593. // rider attach offset
  594. xfer->xferCoord3D( &m_riderAttachOffset );
  595. // rider sway offset
  596. xfer->xferCoord3D( &m_riderSwayOffset );
  597. // para attach offset
  598. xfer->xferCoord3D( &m_paraAttachOffset );
  599. // para sway offset
  600. xfer->xferCoord3D( &m_paraSwayOffset );
  601. // need to update rider bones
  602. xfer->xferBool( &m_needToUpdateRiderBones );
  603. // need to update para bones
  604. xfer->xferBool( &m_needToUpdateParaBones );
  605. // opened
  606. xfer->xferBool( &m_opened );
  607. } // end xfer
  608. // ------------------------------------------------------------------------------------------------
  609. /** Load post process */
  610. // ------------------------------------------------------------------------------------------------
  611. void ParachuteContain::loadPostProcess( void )
  612. {
  613. // extend base class
  614. OpenContain::loadPostProcess();
  615. } // end loadPostProcess