SecurityCamera.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200
  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. /*
  21. SecurityCamera.cpp
  22. Security camera that triggers targets when player is in view
  23. */
  24. #include "../idlib/precompiled.h"
  25. #pragma hdrstop
  26. #include "Game_local.h"
  27. #define CAMERAGHOST_LIFETIME 20 //how long ghost sits there.
  28. /***********************************************************************
  29. idSecurityCamera
  30. ***********************************************************************/
  31. const idEventDef EV_SecurityCam_ReverseSweep( "<reverseSweep>" );
  32. const idEventDef EV_SecurityCam_ContinueSweep( "<continueSweep>" );
  33. const idEventDef EV_SecurityCam_Pause( "<pause>" );
  34. const idEventDef EV_SecurityCam_Alert( "<alert>" );
  35. const idEventDef EV_SecurityCam_AddLight( "<addLight>" );
  36. const idEventDef EV_SecurityCam_camOff( "camOff" );
  37. const idEventDef EV_SecurityCam_camOn( "camOn" );
  38. const idEventDef EV_SecurityCam_KillGhost( "<killghost>" );
  39. const idEventDef EV_SecurityCam_reset( "camreset" );
  40. CLASS_DECLARATION( idEntity, idSecurityCamera )
  41. EVENT( EV_SecurityCam_ReverseSweep, idSecurityCamera::Event_ReverseSweep )
  42. EVENT( EV_SecurityCam_ContinueSweep, idSecurityCamera::Event_ContinueSweep )
  43. EVENT( EV_SecurityCam_Pause, idSecurityCamera::Event_Pause )
  44. EVENT( EV_SecurityCam_Alert, idSecurityCamera::Event_Alert )
  45. EVENT( EV_SecurityCam_AddLight, idSecurityCamera::Event_AddLight )
  46. EVENT( EV_SecurityCam_camOff, idSecurityCamera::Event_camOff)
  47. EVENT( EV_SecurityCam_camOn, idSecurityCamera::Event_camOn)
  48. EVENT( EV_SecurityCam_KillGhost, idSecurityCamera::Event_KillGhost)
  49. EVENT( EV_SecurityCam_reset, idSecurityCamera::reset)
  50. END_CLASS
  51. /*
  52. ================
  53. idSecurityCamera::Save
  54. ================
  55. */
  56. void idSecurityCamera::Save( idSaveGame *savefile ) const {
  57. savefile->WriteFloat( angle );
  58. savefile->WriteFloat( sweepAngle );
  59. savefile->WriteInt( modelAxis );
  60. savefile->WriteBool( flipAxis );
  61. savefile->WriteFloat( scanDist );
  62. savefile->WriteFloat( scanFov );
  63. savefile->WriteFloat( sweepStart );
  64. savefile->WriteFloat( sweepEnd );
  65. savefile->WriteBool( negativeSweep );
  66. savefile->WriteBool( sweeping );
  67. savefile->WriteInt( alertMode );
  68. savefile->WriteFloat( stopSweeping );
  69. savefile->WriteFloat( scanFovCos );
  70. savefile->WriteVec3( viewOffset );
  71. savefile->WriteInt( pvsArea );
  72. savefile->WriteStaticObject( physicsObj );
  73. savefile->WriteTraceModel( trm );
  74. savefile->WriteBool(camActive);
  75. savefile->WriteFloat(softAlarmTimer);
  76. savefile->WriteBool(softAlarmActivated);
  77. savefile->WriteFloat(targetDist);
  78. savefile->WriteFloat(closeTolerance);
  79. lastSpottedEnt.Save(savefile);
  80. savefile->WriteObject(beam);
  81. savefile->WriteObject(beamTarget);
  82. savefile->WriteObject(ghostImage);
  83. int i;
  84. for (i = 0; i < VIEWCONE_SPOKES; i++)
  85. {
  86. savefile->WriteObject(boundBeam[i]);
  87. savefile->WriteObject(boundBeamTarget[i]);
  88. }
  89. }
  90. /*
  91. ================
  92. idSecurityCamera::Restore
  93. ================
  94. */
  95. void idSecurityCamera::Restore( idRestoreGame *savefile ) {
  96. savefile->ReadFloat( angle );
  97. savefile->ReadFloat( sweepAngle );
  98. savefile->ReadInt( modelAxis );
  99. savefile->ReadBool( flipAxis );
  100. savefile->ReadFloat( scanDist );
  101. savefile->ReadFloat( scanFov );
  102. savefile->ReadFloat( sweepStart );
  103. savefile->ReadFloat( sweepEnd );
  104. savefile->ReadBool( negativeSweep );
  105. savefile->ReadBool( sweeping );
  106. savefile->ReadInt( alertMode );
  107. savefile->ReadFloat( stopSweeping );
  108. savefile->ReadFloat( scanFovCos );
  109. savefile->ReadVec3( viewOffset );
  110. savefile->ReadInt( pvsArea );
  111. savefile->ReadStaticObject( physicsObj );
  112. savefile->ReadTraceModel( trm );
  113. savefile->ReadBool(camActive);
  114. savefile->ReadFloat(softAlarmTimer);
  115. savefile->ReadBool(softAlarmActivated);
  116. savefile->ReadFloat(targetDist);
  117. savefile->ReadFloat(closeTolerance);
  118. lastSpottedEnt.Restore(savefile);
  119. savefile->ReadObject(reinterpret_cast<idClass *&>(beam));
  120. savefile->ReadObject(reinterpret_cast<idClass *&>(beamTarget));
  121. savefile->ReadObject(reinterpret_cast<idClass *&>(ghostImage));
  122. int i;
  123. for (i = 0; i < VIEWCONE_SPOKES; i++)
  124. {
  125. savefile->ReadObject(reinterpret_cast<idClass *&>(boundBeam[i]));
  126. savefile->ReadObject(reinterpret_cast<idClass *&>(boundBeamTarget[i]));
  127. }
  128. }
  129. /*
  130. ================
  131. idSecurityCamera::Spawn
  132. ================
  133. */
  134. void idSecurityCamera::Spawn( void ) {
  135. idStr str;
  136. int pitch;
  137. int i;
  138. sweepAngle = spawnArgs.GetFloat( "sweepAngle", "90" );
  139. health = spawnArgs.GetInt( "health", "100" );
  140. scanFov = spawnArgs.GetFloat( "scanFov", "90" );
  141. scanDist = spawnArgs.GetFloat( "scanDist", "200" );
  142. flipAxis = spawnArgs.GetBool( "flipAxis" );
  143. modelAxis = spawnArgs.GetInt( "modelAxis" );
  144. if ( modelAxis < 0 || modelAxis > 2 ) {
  145. modelAxis = 0;
  146. }
  147. //bc tilt the camera down.
  148. pitch = spawnArgs.GetInt("pitch", "35");
  149. idAngles curAng = GetPhysics()->GetAxis().ToAngles();
  150. curAng.pitch = pitch;
  151. SetAxis( curAng.ToMat3() );
  152. this->closeTolerance = spawnArgs.GetInt("closeTolerance", "130");
  153. this->camActive = true;
  154. spawnArgs.GetVector( "viewOffset", "0 0 0", viewOffset );
  155. if ( spawnArgs.GetBool( "spotLight" ) ) {
  156. PostEventMS( &EV_SecurityCam_AddLight, 0 );
  157. }
  158. negativeSweep = ( sweepAngle < 0 ) ? true : false;
  159. sweepAngle = abs( sweepAngle );
  160. scanFovCos = cos( scanFov * idMath::PI / 360.0f );
  161. angle = GetPhysics()->GetAxis().ToAngles().yaw;
  162. this->baseAngle = this->angle;
  163. if (this->baseAngle < 0)
  164. this->baseAngle += 360.0f;
  165. StartSweep();
  166. SetAlertMode( SCANNING );
  167. BecomeActive( TH_THINK );
  168. if ( health ) {
  169. fl.takedamage = true;
  170. }
  171. pvsArea = gameLocal.pvs.GetPVSArea( GetPhysics()->GetOrigin() );
  172. // if no target specified use ourself
  173. str = spawnArgs.GetString( "cameraTarget" );
  174. if ( str.Length() == 0 ) {
  175. spawnArgs.Set( "cameraTarget", spawnArgs.GetString( "name" ) );
  176. }
  177. // check if a clip model is set
  178. spawnArgs.GetString( "clipmodel", "", str );
  179. if ( !str[0] ) {
  180. str = spawnArgs.GetString( "model" ); // use the visual model
  181. }
  182. if ( !collisionModelManager->TrmFromModel( str, trm ) ) {
  183. gameLocal.Error( "idSecurityCamera '%s': cannot load collision model %s", name.c_str(), str.c_str() );
  184. return;
  185. }
  186. GetPhysics()->SetContents( CONTENTS_SOLID );
  187. GetPhysics()->SetClipMask( MASK_SOLID | CONTENTS_BODY | CONTENTS_CORPSE | CONTENTS_MOVEABLECLIP );
  188. // setup the physics
  189. UpdateChangeableSpawnArgs( NULL );
  190. //Beam stuff.
  191. idDict args;
  192. args.SetVector( "origin", vec3_origin );
  193. args.SetBool( "start_off", true );
  194. this->beamTarget = ( idBeam * )gameLocal.SpawnEntityType( idBeam::Type, &args );
  195. args.Clear();
  196. args.Set( "target", beamTarget->name.c_str() );
  197. args.SetVector( "origin", vec3_origin );
  198. args.SetBool( "start_off", false );
  199. args.Set( "width", "2" );
  200. args.Set( "skin", "skins/beam_cameraline" );
  201. this->beam = ( idBeam * )gameLocal.SpawnEntityType( idBeam::Type, &args );
  202. for ( i = 0; i < VIEWCONE_SPOKES; i++ )
  203. {
  204. args.Clear();
  205. args.SetVector( "origin", vec3_origin );
  206. args.SetBool( "start_off", false );
  207. this->boundBeamTarget[ i ] = ( idBeam * )gameLocal.SpawnEntityType( idBeam::Type, &args );
  208. args.Clear();
  209. args.Set( "target", this->boundBeamTarget[ i ]->name.c_str() );
  210. args.SetVector( "origin", vec3_origin );
  211. args.SetBool( "start_off", false );
  212. args.Set( "width", "12" );
  213. args.Set( "skin", "skins/beam_camera" );
  214. this->boundBeam[ i ] = ( idBeam * )gameLocal.SpawnEntityType( idBeam::Type, &args );
  215. this->boundBeam[ i ]->GetRenderEntity()->shaderParms[ SHADERPARM_RED ] = 0;
  216. this->boundBeam[ i ]->GetRenderEntity()->shaderParms[ SHADERPARM_GREEN ] = 1.0f;
  217. this->boundBeam[ i ]->GetRenderEntity()->shaderParms[ SHADERPARM_BLUE ] = 0;
  218. this->boundBeam[ i ]->GetRenderEntity()->shaderParms[ SHADERPARM_TIMESCALE ] = 0.3f;
  219. }
  220. args.Clear();
  221. //args.SetInt( "solid", 0 );
  222. args.SetVector( "origin", vec3_origin );
  223. //args.Set( "model", "models/monster_npc/tris.md5mesh" );
  224. //this->ghostImage = ( idAnimated * )gameLocal.SpawnEntityType( idAnimated::Type, &args );
  225. args.Set( "classname", "env_cameradummy" );
  226. gameLocal.SpawnEntityDef( args, &this->ghostImage );
  227. this->beam->Hide();
  228. this->ghostImage->Hide();
  229. renderEntity.shaderParms[ SHADERPARM_RED ] = 0;
  230. renderEntity.shaderParms[ SHADERPARM_GREEN ] = 1.0f;
  231. renderEntity.shaderParms[ SHADERPARM_BLUE ] = 0;
  232. StartSound( "snd_hum", SND_CHANNEL_DEMONIC, 0, false, NULL );
  233. }
  234. /*
  235. ================
  236. idSecurityCamera::Event_AddLight
  237. ================
  238. */
  239. void idSecurityCamera::Event_AddLight( void ) {
  240. idDict args;
  241. idVec3 right, up, target, temp;
  242. idVec3 dir;
  243. float radius;
  244. idVec3 lightOffset;
  245. idLight *spotLight;
  246. dir = GetAxis();
  247. dir.NormalVectors( right, up );
  248. target = GetPhysics()->GetOrigin() + dir * scanDist;
  249. radius = tan( scanFov * idMath::PI / 360.0f );
  250. up = dir + up * radius;
  251. up.Normalize();
  252. up = GetPhysics()->GetOrigin() + up * scanDist;
  253. up -= target;
  254. right = dir + right * radius;
  255. right.Normalize();
  256. right = GetPhysics()->GetOrigin() + right * scanDist;
  257. right -= target;
  258. spawnArgs.GetVector( "lightOffset", "0 0 0", lightOffset );
  259. args.Set( "origin", ( GetPhysics()->GetOrigin() + lightOffset ).ToString() );
  260. args.Set( "light_target", target.ToString() );
  261. args.Set( "light_right", right.ToString() );
  262. args.Set( "light_up", up.ToString() );
  263. args.SetFloat( "angle", GetPhysics()->GetAxis()[0].ToYaw() );
  264. args.SetInt("alarmlight", 0);
  265. spotLight = static_cast<idLight *>( gameLocal.SpawnEntityType( idLight::Type, &args ) );
  266. spotLight->Bind( this, true );
  267. spotLight->UpdateVisuals();
  268. }
  269. /*
  270. ================
  271. idSecurityCamera::DrawFov
  272. ================
  273. */
  274. void idSecurityCamera::DrawFov( void ) {
  275. int i;
  276. float radius, a, s, c, halfRadius;
  277. idVec3 right, up;
  278. idVec4 color(1, 0, 0, 1), color2(0, 0, 1, 1);
  279. idVec3 lastPoint, point, lastHalfPoint, halfPoint, center;
  280. idVec3 dir = GetAxis();
  281. dir.NormalVectors( right, up );
  282. radius = tan( scanFov * idMath::PI / 360.0f );
  283. halfRadius = radius * 0.5f;
  284. lastPoint = dir + up * radius;
  285. lastPoint.Normalize();
  286. lastPoint = GetPhysics()->GetOrigin() + lastPoint * scanDist;
  287. lastHalfPoint = dir + up * halfRadius;
  288. lastHalfPoint.Normalize();
  289. lastHalfPoint = GetPhysics()->GetOrigin() + lastHalfPoint * scanDist;
  290. center = GetPhysics()->GetOrigin() + dir * scanDist;
  291. for ( i = 1; i < 12; i++ ) {
  292. a = idMath::TWO_PI * i / 12.0f;
  293. idMath::SinCos( a, s, c );
  294. point = dir + right * s * radius + up * c * radius;
  295. point.Normalize();
  296. point = GetPhysics()->GetOrigin() + point * scanDist;
  297. gameRenderWorld->DebugLine( color, lastPoint, point );
  298. gameRenderWorld->DebugLine( color, GetPhysics()->GetOrigin(), point );
  299. lastPoint = point;
  300. halfPoint = dir + right * s * halfRadius + up * c * halfRadius;
  301. halfPoint.Normalize();
  302. halfPoint = GetPhysics()->GetOrigin() + halfPoint * scanDist;
  303. gameRenderWorld->DebugLine( color2, point, halfPoint );
  304. gameRenderWorld->DebugLine( color2, lastHalfPoint, halfPoint );
  305. lastHalfPoint = halfPoint;
  306. gameRenderWorld->DebugLine( color2, halfPoint, center );
  307. }
  308. }
  309. idVec3 idSecurityCamera::GetLensPos()
  310. {
  311. idVec3 forward, right, up;
  312. GetPhysics()->GetAxis().ToAngles().ToVectors( &forward, &right, &up );
  313. return GetPhysics()->GetOrigin() + (forward * viewOffset.x) + (right * viewOffset.y) + (up * viewOffset.z);
  314. }
  315. /*
  316. ================
  317. idSecurityCamera::GetRenderView
  318. ================
  319. */
  320. renderView_t *idSecurityCamera::GetRenderView()
  321. {
  322. idVec3 forward, right, up;
  323. GetPhysics()->GetAxis().ToAngles().ToVectors( &forward, &right, &up );
  324. renderView_t *rv = idEntity::GetRenderView();
  325. rv->fov_x = scanFov;
  326. rv->fov_y = scanFov;
  327. rv->viewaxis = GetAxis().ToAngles().ToMat3();
  328. rv->vieworg = GetLensPos();
  329. return rv;
  330. }
  331. /*
  332. ================
  333. idSecurityCamera::CanSeePlayer
  334. ================
  335. */
  336. bool idSecurityCamera::CanSeePlayer( void ) {
  337. int i;
  338. float dist;
  339. idPlayer *ent;
  340. trace_t tr;
  341. idVec3 dir;
  342. pvsHandle_t handle;
  343. idEntity *projector = NULL; //bc
  344. if (this->IsHidden())
  345. return false;
  346. if (g_skill.GetInteger() <= 0)
  347. return false;
  348. handle = gameLocal.pvs.SetupCurrentPVS( pvsArea );
  349. for ( i = 0; i < gameLocal.num_entities; i++ )
  350. {
  351. if ( !gameLocal.entities[ i ] )
  352. continue;
  353. //check if the classname matches.
  354. if (idStr::Icmp( "env_projector", gameLocal.entities[ i ]->spawnArgs.GetString( "classname" )) == 0)
  355. {
  356. projector = gameLocal.entities[i];
  357. break;
  358. }
  359. }
  360. /*
  361. if (projector)
  362. {
  363. float leftLength = projector->spawnArgs.GetFloat("leftlength", "");
  364. float ceilingLength = projector->spawnArgs.GetFloat("ceilinglength", "");
  365. float rightLength = projector->spawnArgs.GetFloat("rightlength", "");
  366. idBounds bounds = idBounds( idVec3( -4, -rightLength, 0 ), idVec3( 4, leftLength, ceilingLength ) );
  367. bounds.RotateSelf( projector->GetPhysics()->GetAxis().ToAngles().ToMat3() );
  368. gameRenderWorld->DebugBounds( colorMagenta, bounds, projector->GetPhysics()->GetOrigin(), gameLocal.msec );
  369. }
  370. */
  371. for ( i = 0; i < gameLocal.numClients; i++ )
  372. {
  373. ent = static_cast<idPlayer*>(gameLocal.entities[ i ]);
  374. //if ( !ent || ( ent->fl.notarget ) )
  375. if ( !ent || ( ent->fl.notarget ) || ent->noclip)
  376. {
  377. continue;
  378. }
  379. // if there is no way we can see this player
  380. if ( !gameLocal.pvs.InCurrentPVS( handle, ent->GetPVSAreas(), ent->GetNumPVSAreas() ) ) {
  381. continue;
  382. }
  383. dir = ent->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin();
  384. dist = dir.Normalize();
  385. if ( dist > scanDist ) {
  386. continue;
  387. }
  388. if ( dir * GetAxis() < scanFovCos ) {
  389. continue;
  390. }
  391. idVec3 eye;
  392. eye = ent->EyeOffset();
  393. //gameRenderWorld->DebugLine( colorWhite, GetPhysics()->GetOrigin(), ent->GetPhysics()->GetOrigin() + eye + idVec3(0,0,-1), 1000 );
  394. //gameRenderWorld->DebugCircle( colorWhite, GetPhysics()->GetOrigin() + idVec3(0,0,-3.5f) /*close to where lens is*/, idVec3(0,0,1), 2, 5, 200);
  395. //gameRenderWorld->DebugCircle( colorWhite, GetPhysics()->GetOrigin() + (GetPhysics()->GetAxis().ToAngles().ToForward() * 6), idVec3(0,0,1), 2, 5, 200);
  396. gameLocal.clip.TracePoint( tr, GetLensPos()/*close to where lens is*/,
  397. ent->GetPhysics()->GetOrigin() + eye, /*MASK_OPAQUE*/MASK_SOLID, this );
  398. if (projector)
  399. {
  400. if (gameLocal.GetTraceEntity( tr ) == projector)
  401. {
  402. float projectorDot = DotProduct( this->GetPhysics()->GetAxis().ToAngles().ToForward(), projector->GetPhysics()->GetAxis().ToAngles().ToForward() );
  403. //if blocked by the projector screen...
  404. if (projectorDot > 0)
  405. {
  406. continue;
  407. }
  408. else
  409. {
  410. //projector is facing away from camera. Therefore we need the trace to now IGNORE the projector screen.
  411. gameLocal.clip.TracePoint( tr, GetPhysics()->GetOrigin() + idVec3(0,0,-3), ent->GetPhysics()->GetOrigin() + eye,
  412. MASK_SOLID, projector );
  413. }
  414. }
  415. }
  416. if ( tr.fraction >= 1.0 || ( gameLocal.GetTraceEntity( tr ) == ent ) )
  417. {
  418. gameLocal.pvs.FreeCurrentPVS( handle );
  419. this->targetDist = dist;
  420. this->lastSpottedEnt = ent;
  421. return true;
  422. }
  423. }
  424. gameLocal.pvs.FreeCurrentPVS( handle );
  425. this->lastSpottedEnt = NULL;
  426. return false;
  427. }
  428. /*
  429. ================
  430. idSecurityCamera::SetAlertMode
  431. ================
  432. */
  433. void idSecurityCamera::SetAlertMode( int alert ) {
  434. if (alert >= SCANNING && alert <= ACTIVATED) {
  435. alertMode = alert;
  436. }
  437. renderEntity.shaderParms[ SHADERPARM_MODE ] = alertMode;
  438. UpdateVisuals();
  439. }
  440. void idSecurityCamera::DrawBounds( void ) {
  441. int i;
  442. float radius, a, s, c, halfRadius;
  443. idVec3 right, up;
  444. idVec4 color(1, 1, 1, 0.1f), color2(1, 0.5f, 0, 1);
  445. idVec3 lastPoint, point, lastHalfPoint, halfPoint, center;
  446. idVec3 last3dPoint, first3dPoint;
  447. idVec3 dir = GetAxis();
  448. dir.NormalVectors( right, up );
  449. radius = tan( scanFov * idMath::PI / 360.0f );
  450. halfRadius = radius * 0.5f;
  451. lastPoint = dir + up * radius;
  452. lastPoint.Normalize();
  453. lastPoint = GetPhysics()->GetOrigin() + lastPoint * scanDist;
  454. lastHalfPoint = dir + up * halfRadius;
  455. lastHalfPoint.Normalize();
  456. lastHalfPoint = GetPhysics()->GetOrigin() + lastHalfPoint * scanDist;
  457. center = GetPhysics()->GetOrigin() + dir * scanDist;
  458. first3dPoint.Set( 0,0,0 );
  459. for ( i = 1; i < VIEWCONE_SPOKES; i++ )
  460. {
  461. trace_t tr;
  462. a = idMath::TWO_PI * i / (VIEWCONE_SPOKES * 1.0f);
  463. idMath::SinCos( a, s, c );
  464. point = dir + right * s * radius + up * c * radius;
  465. point.Normalize();
  466. point = GetPhysics()->GetOrigin() + point * scanDist;
  467. //gameRenderWorld->DebugLine( color, lastPoint, point ); //draw circle.
  468. //gameRenderWorld->DebugLine( color, GetPhysics()->GetOrigin(), point ); //draw spokes.
  469. gameLocal.clip.TracePoint( tr, GetPhysics()->GetOrigin(), point, MASK_SOLID, this );
  470. if (i >= 2)
  471. {
  472. //gameRenderWorld->DebugLine( color, last3dPoint, tr.endpos );
  473. this->boundBeam[ i - 1 ]->SetOrigin( last3dPoint + dir * -4 );
  474. this->boundBeamTarget[ i - 1 ]->SetOrigin( tr.endpos + dir * -4 );
  475. }
  476. if ( first3dPoint.x == 0 && first3dPoint.y == 0 && first3dPoint.z == 0 )
  477. {
  478. first3dPoint.Set( tr.endpos.x, tr.endpos.y, tr.endpos.z );
  479. }
  480. last3dPoint = tr.endpos;
  481. lastPoint = point;
  482. halfPoint = dir + right * s * halfRadius + up * c * halfRadius;
  483. halfPoint.Normalize();
  484. halfPoint = GetPhysics()->GetOrigin() + halfPoint * scanDist;
  485. //gameRenderWorld->DebugLine( color2, point, halfPoint );
  486. //gameRenderWorld->DebugLine( color2, lastHalfPoint, halfPoint );
  487. lastHalfPoint = halfPoint;
  488. //gameRenderWorld->DebugLine( color2, halfPoint, center );
  489. }
  490. this->boundBeam[ VIEWCONE_SPOKES - 1 ]->SetOrigin( last3dPoint + dir * -4 );
  491. this->boundBeamTarget[ VIEWCONE_SPOKES - 1 ]->SetOrigin( first3dPoint + dir * -4 );
  492. //gameRenderWorld->DebugLine( color, first3dPoint, last3dPoint );
  493. }
  494. /*
  495. ================
  496. idSecurityCamera::Think
  497. ================
  498. */
  499. void idSecurityCamera::Think( void ) {
  500. float pct;
  501. float travel;
  502. if ( thinkFlags & TH_THINK ) {
  503. if ( g_showEntityInfo.GetBool() ) {
  504. DrawFov();
  505. }
  506. DrawBounds();
  507. if (health <= 0) {
  508. BecomeInactive( TH_THINK );
  509. return;
  510. }
  511. }
  512. // run physics
  513. RunPhysics();
  514. if ( thinkFlags & TH_THINK )
  515. {
  516. if (!this->camActive)
  517. {
  518. //do nothing.
  519. if (gameLocal.time > this->softAlarmTimer && !this->softAlarmActivated)
  520. {
  521. uiAlarmTimer = gameLocal.time + UIALARMTIME;
  522. //trigger soft alarm.
  523. this->softAlarmActivated = true;
  524. gameLocal.GetLocalPlayer()->Event_hudMessage( va( common->GetLanguageDict()->GetString( "#str_01203" ), this->GetName() ) );
  525. idStr funcname = spawnArgs.GetString( "softalarmtarget", "" );
  526. if ( funcname.Length() )
  527. {
  528. idEntity *softAlarmEnt;
  529. softAlarmEnt = gameLocal.FindEntity( funcname );
  530. if ( softAlarmEnt->RespondsTo( EV_Activate ) || softAlarmEnt->HasSignal( SIG_TRIGGER ) )
  531. {
  532. softAlarmEnt->Signal( SIG_TRIGGER );
  533. softAlarmEnt->ProcessEvent( &EV_Activate, this );
  534. }
  535. }
  536. }
  537. Present();
  538. return;
  539. }
  540. if (CanSeePlayer())
  541. {
  542. if (alertMode == SCANNING)
  543. {
  544. float sightTime;
  545. int i;
  546. SetAlertMode(ALERT);
  547. stopSweeping = gameLocal.time;
  548. if (sweeping)
  549. {
  550. CancelEvents( &EV_SecurityCam_Pause );
  551. }
  552. else
  553. {
  554. CancelEvents( &EV_SecurityCam_ReverseSweep );
  555. }
  556. sweeping = false;
  557. StopSound( SND_CHANNEL_ANY, false );
  558. StartSound( "snd_sight", SND_CHANNEL_BODY, 0, false, NULL );
  559. renderEntity.shaderParms[ SHADERPARM_RED ] = 1;
  560. renderEntity.shaderParms[ SHADERPARM_GREEN ] = .9f;
  561. renderEntity.shaderParms[ SHADERPARM_BLUE ] = 0;
  562. for ( i = 0; i < VIEWCONE_SPOKES; i++ )
  563. {
  564. //re-enable the boundbeam. Suspicious.
  565. // set skin.
  566. this->boundBeam[ i ]->SetSkin( declManager->FindSkin( "skins/beam_camera" ) );
  567. this->boundBeam[ i ]->GetRenderEntity()->shaderParms[ SHADERPARM_RED ] = 1;
  568. this->boundBeam[ i ]->GetRenderEntity()->shaderParms[ SHADERPARM_GREEN ] = 0.8f;
  569. this->boundBeam[ i ]->GetRenderEntity()->shaderParms[ SHADERPARM_BLUE ] = 0;
  570. }
  571. //bc if player is very close, then player is spotted immediately.
  572. if (this->targetDist < this->closeTolerance)
  573. {
  574. sightTime = spawnArgs.GetFloat( "closeSightTime", "0.3" );
  575. }
  576. else
  577. {
  578. sightTime = spawnArgs.GetFloat( "sightTime", "0.6" );
  579. }
  580. PostEventSec(&EV_SecurityCam_Alert, sightTime);
  581. }
  582. }
  583. else
  584. {
  585. if (alertMode == ALERT)
  586. {
  587. float sightResume;
  588. SetAlertMode(LOSINGINTEREST);
  589. CancelEvents( &EV_SecurityCam_Alert );
  590. sightResume = spawnArgs.GetFloat( "sightResume", "3" );
  591. PostEventSec( &EV_SecurityCam_ContinueSweep, sightResume );
  592. }
  593. if ( sweeping && sweepAngle > 0)
  594. {
  595. idAngles a = GetPhysics()->GetAxis().ToAngles();
  596. pct = ( gameLocal.time - sweepStart ) / ( sweepEnd - sweepStart );
  597. travel = pct * sweepAngle;
  598. if ( negativeSweep )
  599. {
  600. a.yaw = angle + travel;
  601. }
  602. else
  603. {
  604. a.yaw = angle - travel;
  605. }
  606. /*
  607. //verify the camera isn't using some wacky angle.
  608. if (idMath::Fabs(a.yaw) > this->baseAngle + 2)
  609. {
  610. a.yaw = this->baseAngle + 2;
  611. }
  612. if (idMath::Fabs(a.yaw) < this->baseAngle - this->sweepAngle - 2)
  613. {
  614. a.yaw = this->baseAngle - this->sweepAngle - 2;
  615. }
  616. */
  617. SetAngles( a );
  618. }
  619. }
  620. }
  621. Present();
  622. }
  623. /*
  624. ================
  625. idSecurityCamera::GetAxis
  626. ================
  627. */
  628. const idVec3 idSecurityCamera::GetAxis( void ) const {
  629. return (flipAxis) ? -GetPhysics()->GetAxis()[modelAxis] : GetPhysics()->GetAxis()[modelAxis];
  630. };
  631. /*
  632. ================
  633. idSecurityCamera::SweepSpeed
  634. ================
  635. */
  636. float idSecurityCamera::SweepSpeed( void ) const {
  637. return spawnArgs.GetFloat( "sweepSpeed", "5" );
  638. }
  639. /*
  640. ================
  641. idSecurityCamera::StartSweep
  642. ================
  643. */
  644. void idSecurityCamera::StartSweep( void ) {
  645. int speed;
  646. sweeping = true;
  647. sweepStart = gameLocal.time;
  648. speed = SEC2MS( SweepSpeed() );
  649. sweepEnd = sweepStart + speed;
  650. PostEventMS( &EV_SecurityCam_Pause, speed );
  651. if ( this->sweepAngle != 0 )
  652. StartSound( "snd_moving", SND_CHANNEL_BODY, 0, false, NULL );
  653. }
  654. void idSecurityCamera::Event_KillGhost( void )
  655. {
  656. this->beam->Hide();
  657. this->ghostImage->Hide();
  658. }
  659. /*
  660. ================
  661. idSecurityCamera::Event_ContinueSweep
  662. ================
  663. */
  664. void idSecurityCamera::Event_ContinueSweep( void ) {
  665. int i;
  666. float pct = (stopSweeping - sweepStart) / (sweepEnd - sweepStart);
  667. float f = gameLocal.time - (sweepEnd - sweepStart) * pct;
  668. int speed;
  669. sweepStart = f;
  670. //speed = MS2SEC( SweepSpeed() );
  671. speed = SEC2MS( SweepSpeed() ); //bc fixed bug.
  672. sweepEnd = sweepStart + speed;
  673. PostEventMS( &EV_SecurityCam_Pause, speed * (1.0 - pct));
  674. if ( this->sweepAngle != 0 )
  675. StartSound( "snd_moving", SND_CHANNEL_BODY, 0, false, NULL );
  676. SetAlertMode(SCANNING);
  677. sweeping = true;
  678. renderEntity.shaderParms[ SHADERPARM_RED ] = 0;
  679. renderEntity.shaderParms[ SHADERPARM_GREEN ] = 1.0f;
  680. renderEntity.shaderParms[ SHADERPARM_BLUE ] = 0;
  681. for ( i = 0; i < VIEWCONE_SPOKES; i++ )
  682. {
  683. //re-enable the boundbeam.
  684. // set skin.
  685. this->boundBeam[ i ]->SetSkin( declManager->FindSkin( "skins/beam_camera" ) );
  686. this->boundBeam[ i ]->GetRenderEntity()->shaderParms[ SHADERPARM_RED ] = 0;
  687. this->boundBeam[ i ]->GetRenderEntity()->shaderParms[ SHADERPARM_GREEN ] = 1.0f;
  688. this->boundBeam[ i ]->GetRenderEntity()->shaderParms[ SHADERPARM_BLUE ] = 0;
  689. }
  690. StartSound( "snd_hum", SND_CHANNEL_DEMONIC, 0, false, NULL );
  691. }
  692. /*
  693. ================
  694. idSecurityCamera::Event_Alert
  695. ================
  696. */
  697. void idSecurityCamera::Event_Alert( void ) {
  698. float wait;
  699. int i;
  700. //the camera has confirmed the suspicious thingamajig. Go red.
  701. if ( this->lastSpottedEnt.IsValid() )
  702. {
  703. CancelEvents( &EV_SecurityCam_KillGhost );
  704. this->beam->Show();
  705. this->ghostImage->Show();
  706. //draw the beam to the entity.
  707. this->beam->SetOrigin( GetLensPos() );
  708. this->beamTarget->SetOrigin( this->lastSpottedEnt.GetEntity()->GetPhysics()->GetAbsBounds().GetCenter() );
  709. this->ghostImage->SetOrigin( this->lastSpottedEnt.GetEntity()->GetPhysics()->GetOrigin() );
  710. //set the ghost angle.
  711. idAngles playerAng;
  712. playerAng.yaw = static_cast<idPlayer *>( this->lastSpottedEnt.GetEntity() )->viewAngles.yaw;
  713. playerAng.pitch = 0;
  714. playerAng.roll = 0;
  715. this->ghostImage->SetAxis( playerAng.ToMat3() );
  716. PostEventSec( &EV_SecurityCam_KillGhost, CAMERAGHOST_LIFETIME );
  717. //common->Printf("Event: CAUGHT BY CAMERA: %s\n", this->GetName() );
  718. gameLocal.GetLocalPlayer()->Event_hudMessage( va( common->GetLanguageDict()->GetString( "#str_01202" ), this->GetName() ) );
  719. }
  720. renderEntity.shaderParms[ SHADERPARM_RED ] = 1;
  721. renderEntity.shaderParms[ SHADERPARM_GREEN ] = 0;
  722. renderEntity.shaderParms[ SHADERPARM_BLUE ] = 0;
  723. for ( i = 0; i < VIEWCONE_SPOKES; i++ )
  724. {
  725. //re-enable the boundbeam. Caught player.
  726. // set skin.
  727. this->boundBeam[ i ]->SetSkin( declManager->FindSkin( "skins/beam_camera" ) );
  728. this->boundBeam[ i ]->GetRenderEntity()->shaderParms[ SHADERPARM_RED ] = 1;
  729. this->boundBeam[ i ]->GetRenderEntity()->shaderParms[ SHADERPARM_GREEN ] = 0;
  730. this->boundBeam[ i ]->GetRenderEntity()->shaderParms[ SHADERPARM_BLUE ] = 0;
  731. }
  732. SetAlertMode(ACTIVATED);
  733. StopSound( SND_CHANNEL_ANY, false );
  734. StartSound( "snd_activate", SND_CHANNEL_BODY, 0, false, NULL ); //"You've been spotted!" sound.
  735. ActivateTargets(this);
  736. CancelEvents( &EV_SecurityCam_ContinueSweep );
  737. wait = spawnArgs.GetFloat( "wait", "2" );
  738. PostEventSec( &EV_SecurityCam_ContinueSweep, wait );
  739. }
  740. /*
  741. ================
  742. idSecurityCamera::Event_ReverseSweep
  743. ================
  744. */
  745. void idSecurityCamera::Event_ReverseSweep( void ) {
  746. if (spawnArgs.GetBool("hidebeam"))
  747. {
  748. int i;
  749. for ( i = 0; i < VIEWCONE_SPOKES; i++ )
  750. {
  751. this->boundBeam[i]->Hide();
  752. }
  753. }
  754. angle = GetPhysics()->GetAxis().ToAngles().yaw;
  755. negativeSweep = !negativeSweep;
  756. StartSweep();
  757. }
  758. /*
  759. ================
  760. idSecurityCamera::Event_Pause
  761. ================
  762. */
  763. void idSecurityCamera::Event_Pause( void ) {
  764. float sweepWait;
  765. sweepWait = spawnArgs.GetFloat( "sweepWait", "0.5" );
  766. sweeping = false;
  767. StopSound( SND_CHANNEL_BODY, false );
  768. StartSound( "snd_stop", SND_CHANNEL_BODY, 0, false, NULL );
  769. PostEventSec( &EV_SecurityCam_ReverseSweep, sweepWait );
  770. }
  771. void idSecurityCamera::Event_camOff( void )
  772. {
  773. int i;
  774. idDict args;
  775. if (!this->camActive)
  776. return;
  777. this->camActive = false;
  778. StopSound( SND_CHANNEL_ANY, false );
  779. CancelEvents( &EV_SecurityCam_ContinueSweep );
  780. CancelEvents( &EV_SecurityCam_Pause );
  781. CancelEvents( &EV_SecurityCam_ReverseSweep );
  782. CancelEvents( &EV_SecurityCam_Alert );
  783. this->stopSweeping = gameLocal.time;
  784. this->softAlarmTimer = gameLocal.time + 100 /*leeway time*/ + (spawnArgs.GetFloat( "softalarmtime", "3" ) * 1000.0f);
  785. for ( i = 0; i < VIEWCONE_SPOKES; i++ )
  786. {
  787. //this->boundBeamTarget[ i ]->Hide();
  788. //this->boundBeam[ i ]->Hide();
  789. //cam has been disabled.
  790. //this->boundBeam[ i ]->GetRenderEntity()->shaderParms[ SHADERPARM_RED ] = 0.1f;
  791. //this->boundBeam[ i ]->GetRenderEntity()->shaderParms[ SHADERPARM_GREEN ] = 0.1f;
  792. //this->boundBeam[ i ]->GetRenderEntity()->shaderParms[ SHADERPARM_BLUE ] = 0.1f;
  793. // set skin.
  794. this->boundBeam[ i ]->SetSkin( declManager->FindSkin( "skins/beam_camera_noscroll" ) );
  795. }
  796. //StopSound( SND_CHANNEL_ANY, false );
  797. StartSound( "snd_off", SND_CHANNEL_BODY2, 0, false, NULL );
  798. args.Clear();
  799. args.SetVector( "origin", this->GetPhysics()->GetOrigin() +idVec3(0,0,-4) );
  800. args.Set( "model", "sparkburst3.prt" );
  801. args.SetBool( "start_off", false );
  802. gameLocal.SpawnEntityType( idExplodable::Type, &args );
  803. renderEntity.shaderParms[ SHADERPARM_RED ] = 0;
  804. renderEntity.shaderParms[ SHADERPARM_GREEN ] = 0;
  805. renderEntity.shaderParms[ SHADERPARM_BLUE ] = 0;
  806. UpdateVisuals();
  807. uiHackTimer = gameLocal.time + UIHACKTIME;
  808. }
  809. void idSecurityCamera::Event_camOn( void )
  810. {
  811. int i;
  812. if (this->camActive)
  813. return;
  814. StopSound( SND_CHANNEL_ANY, false );
  815. renderEntity.shaderParms[ SHADERPARM_RED ] = 0;
  816. renderEntity.shaderParms[ SHADERPARM_GREEN ] = 1.0f;
  817. renderEntity.shaderParms[ SHADERPARM_BLUE ] = 0;
  818. for ( i = 0; i < VIEWCONE_SPOKES; i++ )
  819. {
  820. //re-enable the boundbeam. Normal idle.
  821. // set skin.
  822. this->boundBeam[ i ]->SetSkin( declManager->FindSkin( "skins/beam_camera" ) );
  823. this->boundBeam[ i ]->GetRenderEntity()->shaderParms[ SHADERPARM_RED ] = 0;
  824. this->boundBeam[ i ]->GetRenderEntity()->shaderParms[ SHADERPARM_GREEN ] = 1.0f;
  825. this->boundBeam[ i ]->GetRenderEntity()->shaderParms[ SHADERPARM_BLUE ] = 0;
  826. }
  827. this->camActive = true;
  828. this->softAlarmActivated = false;
  829. Event_ContinueSweep();
  830. StartSound( "snd_on", SND_CHANNEL_BODY2, 0, false, NULL );
  831. StartSound( "snd_hum", SND_CHANNEL_DEMONIC, 0, false, NULL );
  832. }
  833. /*
  834. ============
  835. idSecurityCamera::Killed
  836. ============
  837. */
  838. void idSecurityCamera::Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location ) {
  839. sweeping = false;
  840. StopSound( SND_CHANNEL_ANY, false );
  841. const char *fx = spawnArgs.GetString( "fx_destroyed" );
  842. if ( fx[0] != '\0' ) {
  843. idEntityFx::StartFx( fx, NULL, NULL, this, true );
  844. }
  845. physicsObj.SetSelf( this );
  846. physicsObj.SetClipModel( new idClipModel( trm ), 0.02f );
  847. physicsObj.SetOrigin( GetPhysics()->GetOrigin() );
  848. physicsObj.SetAxis( GetPhysics()->GetAxis() );
  849. physicsObj.SetBouncyness( 0.2f );
  850. physicsObj.SetFriction( 0.6f, 0.6f, 0.2f );
  851. physicsObj.SetGravity( gameLocal.GetGravity() );
  852. physicsObj.SetContents( CONTENTS_SOLID );
  853. physicsObj.SetClipMask( MASK_SOLID | CONTENTS_BODY | CONTENTS_CORPSE | CONTENTS_MOVEABLECLIP );
  854. SetPhysics( &physicsObj );
  855. physicsObj.DropToFloor();
  856. }
  857. /*
  858. ============
  859. idSecurityCamera::Pain
  860. ============
  861. */
  862. bool idSecurityCamera::Pain( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location ) {
  863. const char *fx = spawnArgs.GetString( "fx_damage" );
  864. if ( fx[0] != '\0' ) {
  865. idEntityFx::StartFx( fx, NULL, NULL, this, true );
  866. }
  867. return true;
  868. }
  869. void idSecurityCamera::reset( void )
  870. {
  871. int i;
  872. CancelEvents( &EV_SecurityCam_Alert );
  873. this->beam->Hide();
  874. this->ghostImage->Hide();
  875. this->camActive = false;
  876. StopSound( SND_CHANNEL_ANY, false );
  877. renderEntity.shaderParms[ SHADERPARM_RED ] = 0;
  878. renderEntity.shaderParms[ SHADERPARM_GREEN ] = 1.0f;
  879. renderEntity.shaderParms[ SHADERPARM_BLUE ] = 0;
  880. for ( i = 0; i < VIEWCONE_SPOKES; i++ )
  881. {
  882. //re-enable the boundbeam. Normal idle.
  883. // set skin.
  884. this->boundBeam[ i ]->SetSkin( declManager->FindSkin( "skins/beam_camera" ) );
  885. this->boundBeam[ i ]->GetRenderEntity()->shaderParms[ SHADERPARM_RED ] = 0;
  886. this->boundBeam[ i ]->GetRenderEntity()->shaderParms[ SHADERPARM_GREEN ] = 1.0f;
  887. this->boundBeam[ i ]->GetRenderEntity()->shaderParms[ SHADERPARM_BLUE ] = 0;
  888. }
  889. this->camActive = true;
  890. this->softAlarmActivated = false;
  891. alertMode = SCANNING;
  892. StartSound( "snd_hum", SND_CHANNEL_DEMONIC, 0, false, NULL );
  893. }
  894. /*
  895. ================
  896. idSecurityCamera::Present
  897. Present is called to allow entities to generate refEntities, lights, etc for the renderer.
  898. ================
  899. */
  900. void idSecurityCamera::Present( void ) {
  901. // don't present to the renderer if the entity hasn't changed
  902. if ( !( thinkFlags & TH_UPDATEVISUALS ) ) {
  903. return;
  904. }
  905. BecomeInactive( TH_UPDATEVISUALS );
  906. // camera target for remote render views
  907. if ( cameraTarget ) {
  908. renderEntity.remoteRenderView = cameraTarget->GetRenderView();
  909. }
  910. // if set to invisible, skip
  911. if ( !renderEntity.hModel || IsHidden() ) {
  912. return;
  913. }
  914. // add to refresh list
  915. if ( modelDefHandle == -1 ) {
  916. modelDefHandle = gameRenderWorld->AddEntityDef( &renderEntity );
  917. } else {
  918. gameRenderWorld->UpdateEntityDef( modelDefHandle, &renderEntity );
  919. }
  920. }