Physics_Monster.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807
  1. /*
  2. ===========================================================================
  3. Doom 3 GPL Source Code
  4. Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
  6. Doom 3 Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 Source Code 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. You should have received a copy of the GNU General Public License
  15. along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
  17. If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
  18. ===========================================================================
  19. */
  20. #include "../../idlib/precompiled.h"
  21. #pragma hdrstop
  22. #include "../Game_local.h"
  23. CLASS_DECLARATION( idPhysics_Actor, idPhysics_Monster )
  24. END_CLASS
  25. const float OVERCLIP = 1.001f;
  26. /*
  27. =====================
  28. idPhysics_Monster::CheckGround
  29. =====================
  30. */
  31. void idPhysics_Monster::CheckGround( monsterPState_t &state ) {
  32. trace_t groundTrace;
  33. idVec3 down;
  34. if ( gravityNormal == vec3_zero ) {
  35. state.onGround = false;
  36. groundEntityPtr = NULL;
  37. return;
  38. }
  39. down = state.origin + gravityNormal * CONTACT_EPSILON;
  40. gameLocal.clip.Translation( groundTrace, state.origin, down, clipModel, clipModel->GetAxis(), clipMask, self );
  41. if ( groundTrace.fraction == 1.0f ) {
  42. state.onGround = false;
  43. groundEntityPtr = NULL;
  44. return;
  45. }
  46. groundEntityPtr = gameLocal.entities[ groundTrace.c.entityNum ];
  47. if ( ( groundTrace.c.normal * -gravityNormal ) < minFloorCosine ) {
  48. state.onGround = false;
  49. return;
  50. }
  51. state.onGround = true;
  52. // let the entity know about the collision
  53. self->Collide( groundTrace, state.velocity );
  54. // apply impact to a non world floor entity
  55. if ( groundTrace.c.entityNum != ENTITYNUM_WORLD && groundEntityPtr.GetEntity() ) {
  56. impactInfo_t info;
  57. groundEntityPtr.GetEntity()->GetImpactInfo( self, groundTrace.c.id, groundTrace.c.point, &info );
  58. if ( info.invMass != 0.0f ) {
  59. groundEntityPtr.GetEntity()->ApplyImpulse( self, 0, groundTrace.c.point, state.velocity / ( info.invMass * 10.0f ) );
  60. }
  61. }
  62. }
  63. /*
  64. =====================
  65. idPhysics_Monster::SlideMove
  66. =====================
  67. */
  68. monsterMoveResult_t idPhysics_Monster::SlideMove( idVec3 &start, idVec3 &velocity, const idVec3 &delta ) {
  69. int i;
  70. trace_t tr;
  71. idVec3 move;
  72. blockingEntity = NULL;
  73. move = delta;
  74. for( i = 0; i < 3; i++ ) {
  75. gameLocal.clip.Translation( tr, start, start + move, clipModel, clipModel->GetAxis(), clipMask, self );
  76. start = tr.endpos;
  77. if ( tr.fraction == 1.0f ) {
  78. if ( i > 0 ) {
  79. return MM_SLIDING;
  80. }
  81. return MM_OK;
  82. }
  83. if ( tr.c.entityNum != ENTITYNUM_NONE ) {
  84. blockingEntity = gameLocal.entities[ tr.c.entityNum ];
  85. }
  86. // clip the movement delta and velocity
  87. move.ProjectOntoPlane( tr.c.normal, OVERCLIP );
  88. velocity.ProjectOntoPlane( tr.c.normal, OVERCLIP );
  89. }
  90. return MM_BLOCKED;
  91. }
  92. /*
  93. =====================
  94. idPhysics_Monster::StepMove
  95. move start into the delta direction
  96. the velocity is clipped conform any collisions
  97. =====================
  98. */
  99. monsterMoveResult_t idPhysics_Monster::StepMove( idVec3 &start, idVec3 &velocity, const idVec3 &delta ) {
  100. trace_t tr;
  101. idVec3 up, down, noStepPos, noStepVel, stepPos, stepVel;
  102. monsterMoveResult_t result1, result2;
  103. float stepdist;
  104. float nostepdist;
  105. if ( delta == vec3_origin ) {
  106. return MM_OK;
  107. }
  108. // try to move without stepping up
  109. noStepPos = start;
  110. noStepVel = velocity;
  111. result1 = SlideMove( noStepPos, noStepVel, delta );
  112. if ( result1 == MM_OK ) {
  113. velocity = noStepVel;
  114. if ( gravityNormal == vec3_zero ) {
  115. start = noStepPos;
  116. return MM_OK;
  117. }
  118. // try to step down so that we walk down slopes and stairs at a normal rate
  119. down = noStepPos + gravityNormal * maxStepHeight;
  120. gameLocal.clip.Translation( tr, noStepPos, down, clipModel, clipModel->GetAxis(), clipMask, self );
  121. if ( tr.fraction < 1.0f ) {
  122. start = tr.endpos;
  123. return MM_STEPPED;
  124. } else {
  125. start = noStepPos;
  126. return MM_OK;
  127. }
  128. }
  129. if ( blockingEntity && blockingEntity->IsType( idActor::Type ) ) {
  130. // try to step down in case walking into an actor while going down steps
  131. down = noStepPos + gravityNormal * maxStepHeight;
  132. gameLocal.clip.Translation( tr, noStepPos, down, clipModel, clipModel->GetAxis(), clipMask, self );
  133. start = tr.endpos;
  134. velocity = noStepVel;
  135. return MM_BLOCKED;
  136. }
  137. if ( gravityNormal == vec3_zero ) {
  138. return result1;
  139. }
  140. // try to step up
  141. up = start - gravityNormal * maxStepHeight;
  142. gameLocal.clip.Translation( tr, start, up, clipModel, clipModel->GetAxis(), clipMask, self );
  143. if ( tr.fraction == 0.0f ) {
  144. start = noStepPos;
  145. velocity = noStepVel;
  146. return result1;
  147. }
  148. // try to move at the stepped up position
  149. stepPos = tr.endpos;
  150. stepVel = velocity;
  151. result2 = SlideMove( stepPos, stepVel, delta );
  152. if ( result2 == MM_BLOCKED ) {
  153. start = noStepPos;
  154. velocity = noStepVel;
  155. return result1;
  156. }
  157. // step down again
  158. down = stepPos + gravityNormal * maxStepHeight;
  159. gameLocal.clip.Translation( tr, stepPos, down, clipModel, clipModel->GetAxis(), clipMask, self );
  160. stepPos = tr.endpos;
  161. // if the move is further without stepping up, or the slope is too steap, don't step up
  162. nostepdist = ( noStepPos - start ).LengthSqr();
  163. stepdist = ( stepPos - start ).LengthSqr();
  164. if ( ( nostepdist >= stepdist ) || ( ( tr.c.normal * -gravityNormal ) < minFloorCosine ) ) {
  165. start = noStepPos;
  166. velocity = noStepVel;
  167. return MM_SLIDING;
  168. }
  169. start = stepPos;
  170. velocity = stepVel;
  171. return MM_STEPPED;
  172. }
  173. /*
  174. ================
  175. idPhysics_Monster::Activate
  176. ================
  177. */
  178. void idPhysics_Monster::Activate( void ) {
  179. current.atRest = -1;
  180. self->BecomeActive( TH_PHYSICS );
  181. }
  182. /*
  183. ================
  184. idPhysics_Monster::Rest
  185. ================
  186. */
  187. void idPhysics_Monster::Rest( void ) {
  188. current.atRest = gameLocal.time;
  189. current.velocity.Zero();
  190. self->BecomeInactive( TH_PHYSICS );
  191. }
  192. /*
  193. ================
  194. idPhysics_Monster::PutToRest
  195. ================
  196. */
  197. void idPhysics_Monster::PutToRest( void ) {
  198. Rest();
  199. }
  200. /*
  201. ================
  202. idPhysics_Monster::idPhysics_Monster
  203. ================
  204. */
  205. idPhysics_Monster::idPhysics_Monster( void ) {
  206. memset( &current, 0, sizeof( current ) );
  207. current.atRest = -1;
  208. saved = current;
  209. delta.Zero();
  210. maxStepHeight = 18.0f;
  211. minFloorCosine = 0.7f;
  212. moveResult = MM_OK;
  213. forceDeltaMove = false;
  214. fly = false;
  215. useVelocityMove = false;
  216. noImpact = false;
  217. blockingEntity = NULL;
  218. }
  219. /*
  220. ================
  221. idPhysics_Monster_SavePState
  222. ================
  223. */
  224. void idPhysics_Monster_SavePState( idSaveGame *savefile, const monsterPState_t &state ) {
  225. savefile->WriteVec3( state.origin );
  226. savefile->WriteVec3( state.velocity );
  227. savefile->WriteVec3( state.localOrigin );
  228. savefile->WriteVec3( state.pushVelocity );
  229. savefile->WriteBool( state.onGround );
  230. savefile->WriteInt( state.atRest );
  231. }
  232. /*
  233. ================
  234. idPhysics_Monster_RestorePState
  235. ================
  236. */
  237. void idPhysics_Monster_RestorePState( idRestoreGame *savefile, monsterPState_t &state ) {
  238. savefile->ReadVec3( state.origin );
  239. savefile->ReadVec3( state.velocity );
  240. savefile->ReadVec3( state.localOrigin );
  241. savefile->ReadVec3( state.pushVelocity );
  242. savefile->ReadBool( state.onGround );
  243. savefile->ReadInt( state.atRest );
  244. }
  245. /*
  246. ================
  247. idPhysics_Monster::Save
  248. ================
  249. */
  250. void idPhysics_Monster::Save( idSaveGame *savefile ) const {
  251. idPhysics_Monster_SavePState( savefile, current );
  252. idPhysics_Monster_SavePState( savefile, saved );
  253. savefile->WriteFloat( maxStepHeight );
  254. savefile->WriteFloat( minFloorCosine );
  255. savefile->WriteVec3( delta );
  256. savefile->WriteBool( forceDeltaMove );
  257. savefile->WriteBool( fly );
  258. savefile->WriteBool( useVelocityMove );
  259. savefile->WriteBool( noImpact );
  260. savefile->WriteInt( (int)moveResult );
  261. savefile->WriteObject( blockingEntity );
  262. }
  263. /*
  264. ================
  265. idPhysics_Monster::Restore
  266. ================
  267. */
  268. void idPhysics_Monster::Restore( idRestoreGame *savefile ) {
  269. idPhysics_Monster_RestorePState( savefile, current );
  270. idPhysics_Monster_RestorePState( savefile, saved );
  271. savefile->ReadFloat( maxStepHeight );
  272. savefile->ReadFloat( minFloorCosine );
  273. savefile->ReadVec3( delta );
  274. savefile->ReadBool( forceDeltaMove );
  275. savefile->ReadBool( fly );
  276. savefile->ReadBool( useVelocityMove );
  277. savefile->ReadBool( noImpact );
  278. savefile->ReadInt( (int &)moveResult );
  279. savefile->ReadObject( reinterpret_cast<idClass *&>( blockingEntity ) );
  280. }
  281. /*
  282. ================
  283. idPhysics_Monster::SetDelta
  284. ================
  285. */
  286. void idPhysics_Monster::SetDelta( const idVec3 &d ) {
  287. delta = d;
  288. if ( delta != vec3_origin ) {
  289. Activate();
  290. }
  291. }
  292. /*
  293. ================
  294. idPhysics_Monster::SetMaxStepHeight
  295. ================
  296. */
  297. void idPhysics_Monster::SetMaxStepHeight( const float newMaxStepHeight ) {
  298. maxStepHeight = newMaxStepHeight;
  299. }
  300. /*
  301. ================
  302. idPhysics_Monster::GetMaxStepHeight
  303. ================
  304. */
  305. float idPhysics_Monster::GetMaxStepHeight( void ) const {
  306. return maxStepHeight;
  307. }
  308. /*
  309. ================
  310. idPhysics_Monster::OnGround
  311. ================
  312. */
  313. bool idPhysics_Monster::OnGround( void ) const {
  314. return current.onGround;
  315. }
  316. /*
  317. ================
  318. idPhysics_Monster::GetSlideMoveEntity
  319. ================
  320. */
  321. idEntity *idPhysics_Monster::GetSlideMoveEntity( void ) const {
  322. return blockingEntity;
  323. }
  324. /*
  325. ================
  326. idPhysics_Monster::GetMoveResult
  327. ================
  328. */
  329. monsterMoveResult_t idPhysics_Monster::GetMoveResult( void ) const {
  330. return moveResult;
  331. }
  332. /*
  333. ================
  334. idPhysics_Monster::ForceDeltaMove
  335. ================
  336. */
  337. void idPhysics_Monster::ForceDeltaMove( bool force ) {
  338. forceDeltaMove = force;
  339. }
  340. /*
  341. ================
  342. idPhysics_Monster::UseFlyMove
  343. ================
  344. */
  345. void idPhysics_Monster::UseFlyMove( bool force ) {
  346. fly = force;
  347. }
  348. /*
  349. ================
  350. idPhysics_Monster::UseVelocityMove
  351. ================
  352. */
  353. void idPhysics_Monster::UseVelocityMove( bool force ) {
  354. useVelocityMove = force;
  355. }
  356. /*
  357. ================
  358. idPhysics_Monster::EnableImpact
  359. ================
  360. */
  361. void idPhysics_Monster::EnableImpact( void ) {
  362. noImpact = false;
  363. }
  364. /*
  365. ================
  366. idPhysics_Monster::DisableImpact
  367. ================
  368. */
  369. void idPhysics_Monster::DisableImpact( void ) {
  370. noImpact = true;
  371. }
  372. /*
  373. ================
  374. idPhysics_Monster::Evaluate
  375. ================
  376. */
  377. bool idPhysics_Monster::Evaluate( int timeStepMSec, int endTimeMSec ) {
  378. idVec3 masterOrigin, oldOrigin;
  379. idMat3 masterAxis;
  380. float timeStep;
  381. timeStep = MS2SEC( timeStepMSec );
  382. moveResult = MM_OK;
  383. blockingEntity = NULL;
  384. oldOrigin = current.origin;
  385. // if bound to a master
  386. if ( masterEntity ) {
  387. self->GetMasterPosition( masterOrigin, masterAxis );
  388. current.origin = masterOrigin + current.localOrigin * masterAxis;
  389. clipModel->Link( gameLocal.clip, self, 0, current.origin, clipModel->GetAxis() );
  390. current.velocity = ( current.origin - oldOrigin ) / timeStep;
  391. masterDeltaYaw = masterYaw;
  392. masterYaw = masterAxis[0].ToYaw();
  393. masterDeltaYaw = masterYaw - masterDeltaYaw;
  394. return true;
  395. }
  396. // if the monster is at rest
  397. if ( current.atRest >= 0 ) {
  398. return false;
  399. }
  400. ActivateContactEntities();
  401. // move the monster velocity into the frame of a pusher
  402. current.velocity -= current.pushVelocity;
  403. clipModel->Unlink();
  404. // check if on the ground
  405. idPhysics_Monster::CheckGround( current );
  406. // if not on the ground or moving upwards
  407. float upspeed;
  408. if ( gravityNormal != vec3_zero ) {
  409. upspeed = -( current.velocity * gravityNormal );
  410. } else {
  411. upspeed = current.velocity.z;
  412. }
  413. if ( fly || ( !forceDeltaMove && ( !current.onGround || upspeed > 1.0f ) ) ) {
  414. if ( upspeed < 0.0f ) {
  415. moveResult = MM_FALLING;
  416. }
  417. else {
  418. current.onGround = false;
  419. moveResult = MM_OK;
  420. }
  421. delta = current.velocity * timeStep;
  422. if ( delta != vec3_origin ) {
  423. moveResult = idPhysics_Monster::SlideMove( current.origin, current.velocity, delta );
  424. delta.Zero();
  425. }
  426. if ( !fly ) {
  427. current.velocity += gravityVector * timeStep;
  428. }
  429. } else {
  430. if ( useVelocityMove ) {
  431. delta = current.velocity * timeStep;
  432. } else {
  433. current.velocity = delta / timeStep;
  434. }
  435. current.velocity -= ( current.velocity * gravityNormal ) * gravityNormal;
  436. if ( delta == vec3_origin ) {
  437. Rest();
  438. } else {
  439. // try moving into the desired direction
  440. moveResult = idPhysics_Monster::StepMove( current.origin, current.velocity, delta );
  441. delta.Zero();
  442. }
  443. }
  444. clipModel->Link( gameLocal.clip, self, 0, current.origin, clipModel->GetAxis() );
  445. // get all the ground contacts
  446. EvaluateContacts();
  447. // move the monster velocity back into the world frame
  448. current.velocity += current.pushVelocity;
  449. current.pushVelocity.Zero();
  450. if ( IsOutsideWorld() ) {
  451. gameLocal.Warning( "clip model outside world bounds for entity '%s' at (%s)", self->name.c_str(), current.origin.ToString(0) );
  452. Rest();
  453. }
  454. return ( current.origin != oldOrigin );
  455. }
  456. /*
  457. ================
  458. idPhysics_Monster::UpdateTime
  459. ================
  460. */
  461. void idPhysics_Monster::UpdateTime( int endTimeMSec ) {
  462. }
  463. /*
  464. ================
  465. idPhysics_Monster::GetTime
  466. ================
  467. */
  468. int idPhysics_Monster::GetTime( void ) const {
  469. return gameLocal.time;
  470. }
  471. /*
  472. ================
  473. idPhysics_Monster::GetImpactInfo
  474. ================
  475. */
  476. void idPhysics_Monster::GetImpactInfo( const int id, const idVec3 &point, impactInfo_t *info ) const {
  477. info->invMass = invMass;
  478. info->invInertiaTensor.Zero();
  479. info->position.Zero();
  480. info->velocity = current.velocity;
  481. }
  482. /*
  483. ================
  484. idPhysics_Monster::ApplyImpulse
  485. ================
  486. */
  487. void idPhysics_Monster::ApplyImpulse( const int id, const idVec3 &point, const idVec3 &impulse ) {
  488. if ( noImpact ) {
  489. return;
  490. }
  491. current.velocity += impulse * invMass;
  492. Activate();
  493. }
  494. /*
  495. ================
  496. idPhysics_Monster::IsAtRest
  497. ================
  498. */
  499. bool idPhysics_Monster::IsAtRest( void ) const {
  500. return current.atRest >= 0;
  501. }
  502. /*
  503. ================
  504. idPhysics_Monster::GetRestStartTime
  505. ================
  506. */
  507. int idPhysics_Monster::GetRestStartTime( void ) const {
  508. return current.atRest;
  509. }
  510. /*
  511. ================
  512. idPhysics_Monster::SaveState
  513. ================
  514. */
  515. void idPhysics_Monster::SaveState( void ) {
  516. saved = current;
  517. }
  518. /*
  519. ================
  520. idPhysics_Monster::RestoreState
  521. ================
  522. */
  523. void idPhysics_Monster::RestoreState( void ) {
  524. current = saved;
  525. clipModel->Link( gameLocal.clip, self, 0, current.origin, clipModel->GetAxis() );
  526. EvaluateContacts();
  527. }
  528. /*
  529. ================
  530. idPhysics_Player::SetOrigin
  531. ================
  532. */
  533. void idPhysics_Monster::SetOrigin( const idVec3 &newOrigin, int id ) {
  534. idVec3 masterOrigin;
  535. idMat3 masterAxis;
  536. current.localOrigin = newOrigin;
  537. if ( masterEntity ) {
  538. self->GetMasterPosition( masterOrigin, masterAxis );
  539. current.origin = masterOrigin + newOrigin * masterAxis;
  540. }
  541. else {
  542. current.origin = newOrigin;
  543. }
  544. clipModel->Link( gameLocal.clip, self, 0, newOrigin, clipModel->GetAxis() );
  545. Activate();
  546. }
  547. /*
  548. ================
  549. idPhysics_Player::SetAxis
  550. ================
  551. */
  552. void idPhysics_Monster::SetAxis( const idMat3 &newAxis, int id ) {
  553. clipModel->Link( gameLocal.clip, self, 0, clipModel->GetOrigin(), newAxis );
  554. Activate();
  555. }
  556. /*
  557. ================
  558. idPhysics_Monster::Translate
  559. ================
  560. */
  561. void idPhysics_Monster::Translate( const idVec3 &translation, int id ) {
  562. current.localOrigin += translation;
  563. current.origin += translation;
  564. clipModel->Link( gameLocal.clip, self, 0, current.origin, clipModel->GetAxis() );
  565. Activate();
  566. }
  567. /*
  568. ================
  569. idPhysics_Monster::Rotate
  570. ================
  571. */
  572. void idPhysics_Monster::Rotate( const idRotation &rotation, int id ) {
  573. idVec3 masterOrigin;
  574. idMat3 masterAxis;
  575. current.origin *= rotation;
  576. if ( masterEntity ) {
  577. self->GetMasterPosition( masterOrigin, masterAxis );
  578. current.localOrigin = ( current.origin - masterOrigin ) * masterAxis.Transpose();
  579. }
  580. else {
  581. current.localOrigin = current.origin;
  582. }
  583. clipModel->Link( gameLocal.clip, self, 0, current.origin, clipModel->GetAxis() * rotation.ToMat3() );
  584. Activate();
  585. }
  586. /*
  587. ================
  588. idPhysics_Monster::SetLinearVelocity
  589. ================
  590. */
  591. void idPhysics_Monster::SetLinearVelocity( const idVec3 &newLinearVelocity, int id ) {
  592. current.velocity = newLinearVelocity;
  593. Activate();
  594. }
  595. /*
  596. ================
  597. idPhysics_Monster::GetLinearVelocity
  598. ================
  599. */
  600. const idVec3 &idPhysics_Monster::GetLinearVelocity( int id ) const {
  601. return current.velocity;
  602. }
  603. /*
  604. ================
  605. idPhysics_Monster::SetPushed
  606. ================
  607. */
  608. void idPhysics_Monster::SetPushed( int deltaTime ) {
  609. // velocity with which the monster is pushed
  610. current.pushVelocity += ( current.origin - saved.origin ) / ( deltaTime * idMath::M_MS2SEC );
  611. }
  612. /*
  613. ================
  614. idPhysics_Monster::GetPushedLinearVelocity
  615. ================
  616. */
  617. const idVec3 &idPhysics_Monster::GetPushedLinearVelocity( const int id ) const {
  618. return current.pushVelocity;
  619. }
  620. /*
  621. ================
  622. idPhysics_Monster::SetMaster
  623. the binding is never orientated
  624. ================
  625. */
  626. void idPhysics_Monster::SetMaster( idEntity *master, const bool orientated ) {
  627. idVec3 masterOrigin;
  628. idMat3 masterAxis;
  629. if ( master ) {
  630. if ( !masterEntity ) {
  631. // transform from world space to master space
  632. self->GetMasterPosition( masterOrigin, masterAxis );
  633. current.localOrigin = ( current.origin - masterOrigin ) * masterAxis.Transpose();
  634. masterEntity = master;
  635. masterYaw = masterAxis[0].ToYaw();
  636. }
  637. ClearContacts();
  638. }
  639. else {
  640. if ( masterEntity ) {
  641. masterEntity = NULL;
  642. Activate();
  643. }
  644. }
  645. }
  646. const float MONSTER_VELOCITY_MAX = 4000;
  647. const int MONSTER_VELOCITY_TOTAL_BITS = 16;
  648. const int MONSTER_VELOCITY_EXPONENT_BITS = idMath::BitsForInteger( idMath::BitsForFloat( MONSTER_VELOCITY_MAX ) ) + 1;
  649. const int MONSTER_VELOCITY_MANTISSA_BITS = MONSTER_VELOCITY_TOTAL_BITS - 1 - MONSTER_VELOCITY_EXPONENT_BITS;
  650. /*
  651. ================
  652. idPhysics_Monster::WriteToSnapshot
  653. ================
  654. */
  655. void idPhysics_Monster::WriteToSnapshot( idBitMsgDelta &msg ) const {
  656. msg.WriteFloat( current.origin[0] );
  657. msg.WriteFloat( current.origin[1] );
  658. msg.WriteFloat( current.origin[2] );
  659. msg.WriteFloat( current.velocity[0], MONSTER_VELOCITY_EXPONENT_BITS, MONSTER_VELOCITY_MANTISSA_BITS );
  660. msg.WriteFloat( current.velocity[1], MONSTER_VELOCITY_EXPONENT_BITS, MONSTER_VELOCITY_MANTISSA_BITS );
  661. msg.WriteFloat( current.velocity[2], MONSTER_VELOCITY_EXPONENT_BITS, MONSTER_VELOCITY_MANTISSA_BITS );
  662. msg.WriteDeltaFloat( current.origin[0], current.localOrigin[0] );
  663. msg.WriteDeltaFloat( current.origin[1], current.localOrigin[1] );
  664. msg.WriteDeltaFloat( current.origin[2], current.localOrigin[2] );
  665. msg.WriteDeltaFloat( 0.0f, current.pushVelocity[0], MONSTER_VELOCITY_EXPONENT_BITS, MONSTER_VELOCITY_MANTISSA_BITS );
  666. msg.WriteDeltaFloat( 0.0f, current.pushVelocity[1], MONSTER_VELOCITY_EXPONENT_BITS, MONSTER_VELOCITY_MANTISSA_BITS );
  667. msg.WriteDeltaFloat( 0.0f, current.pushVelocity[2], MONSTER_VELOCITY_EXPONENT_BITS, MONSTER_VELOCITY_MANTISSA_BITS );
  668. msg.WriteLong( current.atRest );
  669. msg.WriteBits( current.onGround, 1 );
  670. }
  671. /*
  672. ================
  673. idPhysics_Monster::ReadFromSnapshot
  674. ================
  675. */
  676. void idPhysics_Monster::ReadFromSnapshot( const idBitMsgDelta &msg ) {
  677. current.origin[0] = msg.ReadFloat();
  678. current.origin[1] = msg.ReadFloat();
  679. current.origin[2] = msg.ReadFloat();
  680. current.velocity[0] = msg.ReadFloat( MONSTER_VELOCITY_EXPONENT_BITS, MONSTER_VELOCITY_MANTISSA_BITS );
  681. current.velocity[1] = msg.ReadFloat( MONSTER_VELOCITY_EXPONENT_BITS, MONSTER_VELOCITY_MANTISSA_BITS );
  682. current.velocity[2] = msg.ReadFloat( MONSTER_VELOCITY_EXPONENT_BITS, MONSTER_VELOCITY_MANTISSA_BITS );
  683. current.localOrigin[0] = msg.ReadDeltaFloat( current.origin[0] );
  684. current.localOrigin[1] = msg.ReadDeltaFloat( current.origin[1] );
  685. current.localOrigin[2] = msg.ReadDeltaFloat( current.origin[2] );
  686. current.pushVelocity[0] = msg.ReadDeltaFloat( 0.0f, MONSTER_VELOCITY_EXPONENT_BITS, MONSTER_VELOCITY_MANTISSA_BITS );
  687. current.pushVelocity[1] = msg.ReadDeltaFloat( 0.0f, MONSTER_VELOCITY_EXPONENT_BITS, MONSTER_VELOCITY_MANTISSA_BITS );
  688. current.pushVelocity[2] = msg.ReadDeltaFloat( 0.0f, MONSTER_VELOCITY_EXPONENT_BITS, MONSTER_VELOCITY_MANTISSA_BITS );
  689. current.atRest = msg.ReadLong();
  690. current.onGround = msg.ReadBits( 1 ) != 0;
  691. }