home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2006 March / Gamestar_82_2006-03_dvd.iso / DVDStar / Editace / quake4_sdkv10.exe / source / game / SecurityCamera.cpp < prev    next >
C/C++ Source or Header  |  2005-11-14  |  15KB  |  579 lines

  1. /*
  2.  
  3.   SecurityCamera.cpp
  4.  
  5.   Security camera that triggers targets when player is in view
  6.  
  7. */
  8.  
  9. #include "../idlib/precompiled.h"
  10. #pragma hdrstop
  11.  
  12. #include "Game_local.h"
  13.  
  14.  
  15. /***********************************************************************
  16.  
  17.   idSecurityCamera
  18.     
  19. ***********************************************************************/
  20.  
  21. const idEventDef EV_SecurityCam_ReverseSweep( "<reverseSweep>" );
  22. const idEventDef EV_SecurityCam_ContinueSweep( "<continueSweep>" );
  23. const idEventDef EV_SecurityCam_Pause( "<pause>" );
  24. const idEventDef EV_SecurityCam_Alert( "<alert>" );
  25. const idEventDef EV_SecurityCam_AddLight( "<addLight>" );
  26.  
  27. CLASS_DECLARATION( idEntity, idSecurityCamera )
  28.     EVENT( EV_SecurityCam_ReverseSweep,        idSecurityCamera::Event_ReverseSweep )
  29.     EVENT( EV_SecurityCam_ContinueSweep,    idSecurityCamera::Event_ContinueSweep )
  30.     EVENT( EV_SecurityCam_Pause,            idSecurityCamera::Event_Pause )
  31.     EVENT( EV_SecurityCam_Alert,            idSecurityCamera::Event_Alert )
  32.     EVENT( EV_SecurityCam_AddLight,            idSecurityCamera::Event_AddLight )
  33. END_CLASS
  34.  
  35.  
  36. idSecurityCamera::~idSecurityCamera() {
  37.     SetPhysics( NULL );
  38. }
  39.  
  40. /*
  41. ================
  42. idSecurityCamera::Save
  43. ================
  44. */
  45. void idSecurityCamera::Save( idSaveGame *savefile ) const {
  46.     savefile->WriteFloat( angle );
  47.     savefile->WriteFloat( sweepAngle );
  48.     savefile->WriteInt( modelAxis );
  49.     savefile->WriteBool( flipAxis );
  50.     savefile->WriteFloat( scanDist );
  51.     savefile->WriteFloat( scanFov );
  52.                             
  53.     savefile->WriteFloat( sweepStart );
  54.     savefile->WriteFloat( sweepEnd );
  55.     savefile->WriteBool( negativeSweep );
  56.     savefile->WriteBool( sweeping );
  57.     savefile->WriteInt( alertMode );
  58.     savefile->WriteFloat( stopSweeping );
  59.     savefile->WriteFloat( scanFovCos );
  60.  
  61.     savefile->WriteVec3( viewOffset );
  62.                             
  63.     savefile->WriteInt( pvsArea );
  64.     savefile->WriteStaticObject( physicsObj );
  65.     savefile->Write( &trm, sizeof( trm ) );
  66. }
  67.  
  68. /*
  69. ================
  70. idSecurityCamera::Restore
  71. ================
  72. */
  73. void idSecurityCamera::Restore( idRestoreGame *savefile ) {
  74.     savefile->ReadFloat( angle );
  75.     savefile->ReadFloat( sweepAngle );
  76.     savefile->ReadInt( modelAxis );
  77.     savefile->ReadBool( flipAxis );
  78.     savefile->ReadFloat( scanDist );
  79.     savefile->ReadFloat( scanFov );
  80.                             
  81.     savefile->ReadFloat( sweepStart );
  82.     savefile->ReadFloat( sweepEnd );
  83.     savefile->ReadBool( negativeSweep );
  84.     savefile->ReadBool( sweeping );
  85.     savefile->ReadInt( alertMode );
  86.     savefile->ReadFloat( stopSweeping );
  87.     savefile->ReadFloat( scanFovCos );
  88.  
  89.     savefile->ReadVec3( viewOffset );
  90.                             
  91.     savefile->ReadInt( pvsArea );
  92.     savefile->ReadStaticObject( physicsObj );
  93.     savefile->Read( &trm, sizeof( trm ) );
  94. }
  95.  
  96. /*
  97. ================
  98. idSecurityCamera::Spawn
  99. ================
  100. */
  101. void idSecurityCamera::Spawn( void ) {
  102.     idStr    str;
  103.  
  104.     sweepAngle    = spawnArgs.GetFloat( "sweepAngle", "90" );
  105.     health        = spawnArgs.GetInt( "health", "100" );
  106.     scanFov        = spawnArgs.GetFloat( "scanFov", "90" );
  107.     scanDist    = spawnArgs.GetFloat( "scanDist", "200" );
  108.     flipAxis    = spawnArgs.GetBool( "flipAxis" );
  109.  
  110.     modelAxis    = spawnArgs.GetInt( "modelAxis" );
  111.     if ( modelAxis < 0 || modelAxis > 2 ) {
  112.         modelAxis = 0;
  113.     }
  114.  
  115.     spawnArgs.GetVector( "viewOffset", "0 0 0", viewOffset );
  116.  
  117.     if ( spawnArgs.GetBool( "spotLight" ) ) {
  118.         PostEventMS( &EV_SecurityCam_AddLight, 0 );
  119.     }
  120.  
  121.     negativeSweep = ( sweepAngle < 0 ) ? true : false;
  122.     sweepAngle = abs( sweepAngle );
  123.  
  124.     scanFovCos = idMath::Cos( scanFov * idMath::PI / 360.0f );
  125.  
  126.     angle = GetPhysics()->GetAxis().ToAngles().yaw;
  127.     StartSweep();
  128.     SetAlertMode( SCANNING );
  129.     BecomeActive( TH_THINK );
  130.  
  131.     if ( health ) {
  132.         fl.takedamage = true;
  133.     }
  134.  
  135.     pvsArea = gameLocal.pvs.GetPVSArea( GetPhysics()->GetOrigin() );
  136.     // if no target specified use ourself
  137.     str = spawnArgs.GetString( "cameraTarget" );
  138.     if ( str.Length() == 0 ) {
  139.         spawnArgs.Set( "cameraTarget", spawnArgs.GetString( "name" ) );
  140.     }
  141.  
  142.     // check if a clip model is set
  143.     spawnArgs.GetString( "clipmodel", "", str );
  144.     if ( !str[0] ) {
  145.         str = spawnArgs.GetString( "model" );        // use the visual model
  146.     }
  147.  
  148.     if ( !collisionModelManager->TrmFromModel( gameLocal.GetMapName(), str, trm ) ) {
  149.         gameLocal.Error( "idSecurityCamera '%s': cannot load collision model %s", name.c_str(), str.c_str() );
  150.         return;
  151.     }
  152.  
  153.     GetPhysics()->SetContents( CONTENTS_SOLID );
  154.     GetPhysics()->SetClipMask( MASK_SOLID | CONTENTS_BODY | CONTENTS_CORPSE | CONTENTS_MOVEABLECLIP );
  155.     // setup the physics
  156.     UpdateChangeableSpawnArgs( NULL );
  157. }
  158.  
  159. /*
  160. ================
  161. idSecurityCamera::Event_AddLight
  162. ================
  163. */
  164. void idSecurityCamera::Event_AddLight( void ) {
  165.     idDict    args;
  166.     idVec3    right, up, target, temp;
  167.     idVec3    dir;
  168.     float    radius;
  169.     idVec3    lightOffset;
  170.     idLight    *spotLight;
  171.     
  172.     dir = GetAxis();
  173.     dir.NormalVectors( right, up );
  174.     target = GetPhysics()->GetOrigin() + dir * scanDist;
  175.         
  176.     radius = idMath::Tan( scanFov * idMath::PI / 360.0f );
  177.     up = dir + up * radius;
  178.     up.Normalize();
  179.     up = GetPhysics()->GetOrigin() + up * scanDist;
  180.     up -= target;
  181.     
  182.     right = dir + right * radius;
  183.     right.Normalize();
  184.     right = GetPhysics()->GetOrigin() + right * scanDist;
  185.     right -= target;
  186.  
  187.     spawnArgs.GetVector( "lightOffset", "0 0 0", lightOffset );
  188.     
  189.     args.Set( "origin", ( GetPhysics()->GetOrigin() + lightOffset ).ToString() );
  190.     args.Set( "light_target", target.ToString() );
  191.     args.Set( "light_right", right.ToString() );
  192.     args.Set( "light_up", up.ToString() );
  193.     args.SetFloat( "angle", GetPhysics()->GetAxis()[0].ToYaw() );
  194.  
  195. // RAVEN BEGIN
  196. // jnewquist: Use accessor for static class type 
  197.     spotLight = static_cast<idLight *>( gameLocal.SpawnEntityType( idLight::GetClassType(), &args ) );
  198. // RAVEN END
  199.     spotLight->Bind( this, true );
  200.     spotLight->UpdateVisuals();
  201. }
  202.  
  203. /*
  204. ================
  205. idSecurityCamera::DrawFov
  206. ================
  207. */
  208. void idSecurityCamera::DrawFov( void ) {
  209.     int i;
  210.     float radius, a, s, c, halfRadius;
  211.     idVec3 right, up;
  212.     idVec4 color(1, 0, 0, 1), color2(0, 0, 1, 1);
  213.     idVec3 lastPoint, point, lastHalfPoint, halfPoint, center;
  214.  
  215.     idVec3 dir = GetAxis();
  216.     dir.NormalVectors( right, up );
  217.  
  218.     radius = idMath::Tan( scanFov * idMath::PI / 360.0f );
  219.     halfRadius = radius * 0.5f;
  220.     lastPoint = dir + up * radius;
  221.     lastPoint.Normalize();
  222.     lastPoint = GetPhysics()->GetOrigin() + lastPoint * scanDist;
  223.     lastHalfPoint = dir + up * halfRadius;
  224.     lastHalfPoint.Normalize();
  225.     lastHalfPoint = GetPhysics()->GetOrigin() + lastHalfPoint * scanDist;
  226.     center = GetPhysics()->GetOrigin() + dir * scanDist;
  227.     for ( i = 1; i < 12; i++ ) {
  228.         a = idMath::TWO_PI * i / 12.0f;
  229.         idMath::SinCos( a, s, c );
  230.         point = dir + right * s * radius + up * c * radius;
  231.         point.Normalize();
  232.         point = GetPhysics()->GetOrigin() + point * scanDist;
  233.         gameRenderWorld->DebugLine( color, lastPoint, point );
  234.         gameRenderWorld->DebugLine( color, GetPhysics()->GetOrigin(), point );
  235.         lastPoint = point;
  236.  
  237.         halfPoint = dir + right * s * halfRadius + up * c * halfRadius;
  238.         halfPoint.Normalize();
  239.         halfPoint = GetPhysics()->GetOrigin() + halfPoint * scanDist;
  240.         gameRenderWorld->DebugLine( color2, point, halfPoint );
  241.         gameRenderWorld->DebugLine( color2, lastHalfPoint, halfPoint );
  242.         lastHalfPoint = halfPoint;
  243.  
  244.         gameRenderWorld->DebugLine( color2, halfPoint, center );
  245.     }
  246. }
  247.  
  248. /*
  249. ================
  250. idSecurityCamera::GetRenderView
  251. ================
  252. */
  253. renderView_t *idSecurityCamera::GetRenderView() {
  254.     renderView_t *rv = idEntity::GetRenderView();
  255.     rv->fov_x = scanFov;
  256.     rv->fov_y = scanFov;
  257.     rv->viewaxis = GetAxis().ToAngles().ToMat3();
  258.     rv->vieworg = GetPhysics()->GetOrigin() + viewOffset;
  259.     return rv;
  260. }
  261.  
  262. /*
  263. ================
  264. idSecurityCamera::CanSeePlayer
  265. ================
  266. */
  267. bool idSecurityCamera::CanSeePlayer( void ) {
  268.     int i;
  269.     float dist;
  270.     idPlayer *ent;
  271.     trace_t tr;
  272.     idVec3 dir;
  273.     pvsHandle_t handle;
  274.  
  275.     handle = gameLocal.pvs.SetupCurrentPVS( pvsArea );
  276.  
  277.     for ( i = 0; i < gameLocal.numClients; i++ ) {
  278.         ent = static_cast<idPlayer*>(gameLocal.entities[ i ]);
  279.  
  280.         if ( !ent || ( ent->fl.notarget ) ) {
  281.             continue;
  282.         }
  283.  
  284.         // if there is no way we can see this player
  285.         if ( !gameLocal.pvs.InCurrentPVS( handle, ent->GetPVSAreas(), ent->GetNumPVSAreas() ) ) {
  286.             continue;
  287.         }
  288.  
  289.         dir = ent->GetPhysics()->GetOrigin() - GetPhysics()->GetOrigin();
  290.         dist = dir.Normalize();
  291.  
  292.         if ( dist > scanDist ) {
  293.             continue;
  294.         }
  295.  
  296.         if ( dir * GetAxis() < scanFovCos ) {
  297.             continue;
  298.         }
  299.  
  300. // RAVEN BEGIN
  301. // ddynerman: multiple clip worlds
  302.         gameLocal.TracePoint( this, tr, GetPhysics()->GetOrigin(), ent->GetEyePosition(), MASK_OPAQUE, this );
  303. // RAVEN END
  304.         if ( tr.fraction == 1.0 || ( gameLocal.GetTraceEntity( tr ) == ent ) ) {
  305.             gameLocal.pvs.FreeCurrentPVS( handle );
  306.             return true;
  307.         }
  308.     }
  309.  
  310.     gameLocal.pvs.FreeCurrentPVS( handle );
  311.  
  312.     return false;
  313. }
  314.  
  315. /*
  316. ================
  317. idSecurityCamera::SetAlertMode
  318. ================
  319. */
  320. void idSecurityCamera::SetAlertMode( int alert ) {
  321.     if (alert >= SCANNING && alert <= ACTIVATED) {
  322.         alertMode = alert;
  323.     }
  324.     renderEntity.shaderParms[ SHADERPARM_MODE ] = alertMode;
  325.     UpdateVisuals();
  326. }
  327.  
  328. /*
  329. ================
  330. idSecurityCamera::Think
  331. ================
  332. */
  333. void idSecurityCamera::Think( void ) {
  334.     float pct;
  335.     float travel;
  336.  
  337.     if ( thinkFlags & TH_THINK ) {
  338.         if ( g_showEntityInfo.GetBool() ) {
  339.             DrawFov();
  340.         }
  341.  
  342.         if (health <= 0) {
  343.             BecomeInactive( TH_THINK );
  344.             return;
  345.         }
  346.     }
  347.  
  348.     // run physics
  349.     RunPhysics();
  350.  
  351.     if ( thinkFlags & TH_THINK ) {
  352.         if (CanSeePlayer()) {
  353.             if (alertMode == SCANNING) {
  354.                 float    sightTime;
  355.  
  356.                 SetAlertMode(ALERT);
  357.                 stopSweeping = gameLocal.time;
  358.                 if (sweeping) {
  359.                     CancelEvents( &EV_SecurityCam_Pause );
  360.                 } else {
  361.                     CancelEvents( &EV_SecurityCam_ReverseSweep );
  362.                 }
  363.                 sweeping = false;
  364.                 StopSound( SND_CHANNEL_ANY, false );
  365.                 StartSound( "snd_sight", SND_CHANNEL_BODY, 0, false, NULL );
  366.  
  367.                 sightTime = spawnArgs.GetFloat( "sightTime", "5" );
  368.                 PostEventSec(&EV_SecurityCam_Alert, sightTime);
  369.             }
  370.         } else {
  371.             if (alertMode == ALERT) {
  372.                 float    sightResume;
  373.  
  374.                 SetAlertMode(LOSINGINTEREST);
  375.                 CancelEvents( &EV_SecurityCam_Alert );
  376.                 
  377.                 sightResume = spawnArgs.GetFloat( "sightResume", "1.5" );
  378.                 PostEventSec( &EV_SecurityCam_ContinueSweep, sightResume );
  379.             }
  380.  
  381.             if ( sweeping ) {
  382.                 idAngles a = GetPhysics()->GetAxis().ToAngles();
  383.  
  384.                 pct = ( gameLocal.time - sweepStart ) / ( sweepEnd - sweepStart );
  385.                 travel = pct * sweepAngle;
  386.                 if ( negativeSweep ) {
  387.                     a.yaw = angle + travel;
  388.                 } else {
  389.                     a.yaw = angle - travel;
  390.                 }
  391.  
  392.                 SetAngles( a );
  393.             }
  394.         }
  395.     }
  396.     Present();
  397. }
  398.  
  399. /*
  400. ================
  401. idSecurityCamera::GetAxis
  402. ================
  403. */
  404. const idVec3 idSecurityCamera::GetAxis( void ) const {
  405.     return (flipAxis) ? -GetPhysics()->GetAxis()[modelAxis] : GetPhysics()->GetAxis()[modelAxis];
  406. };
  407.  
  408. /*
  409. ================
  410. idSecurityCamera::SweepSpeed
  411. ================
  412. */
  413. float idSecurityCamera::SweepSpeed( void ) const {
  414.     return spawnArgs.GetFloat( "sweepSpeed", "5" );
  415. }
  416.  
  417. /*
  418. ================
  419. idSecurityCamera::StartSweep
  420. ================
  421. */
  422. void idSecurityCamera::StartSweep( void ) {
  423.     int speed;
  424.  
  425.     sweeping = true;
  426.     sweepStart = gameLocal.time;
  427.     speed = SEC2MS( SweepSpeed() );
  428.     sweepEnd = sweepStart + speed;
  429.        PostEventMS( &EV_SecurityCam_Pause, speed );
  430.     StartSound( "snd_moving", SND_CHANNEL_BODY, 0, false, NULL );
  431. }
  432.  
  433. /*
  434. ================
  435. idSecurityCamera::Event_ContinueSweep
  436. ================
  437. */
  438. void idSecurityCamera::Event_ContinueSweep( void ) {
  439.     float pct = (stopSweeping - sweepStart) / (sweepEnd - sweepStart);
  440.     float f = gameLocal.time - (sweepEnd - sweepStart) * pct;
  441.     int speed;
  442.  
  443.     sweepStart = f;
  444.     speed = MS2SEC( SweepSpeed() );
  445.     sweepEnd = sweepStart + speed;
  446.        PostEventMS( &EV_SecurityCam_Pause, speed * (1.0 - pct));
  447.     StartSound( "snd_moving", SND_CHANNEL_BODY, 0, false, NULL );
  448.     SetAlertMode(SCANNING);
  449.     sweeping = true;
  450. }
  451.  
  452. /*
  453. ================
  454. idSecurityCamera::Event_Alert
  455. ================
  456. */
  457. void idSecurityCamera::Event_Alert( void ) {
  458.     float    wait;
  459.  
  460.     SetAlertMode(ACTIVATED);
  461.     StopSound( SND_CHANNEL_ANY, false );
  462.     StartSound( "snd_activate", SND_CHANNEL_BODY, 0, false, NULL );
  463.     ActivateTargets(this);
  464.     CancelEvents( &EV_SecurityCam_ContinueSweep );
  465.  
  466.     wait = spawnArgs.GetFloat( "wait", "20" );
  467.     PostEventSec( &EV_SecurityCam_ContinueSweep, wait );
  468. }
  469.  
  470. /*
  471. ================
  472. idSecurityCamera::Event_ReverseSweep
  473. ================
  474. */
  475. void idSecurityCamera::Event_ReverseSweep( void ) {
  476.     angle = GetPhysics()->GetAxis().ToAngles().yaw;
  477.     negativeSweep = !negativeSweep;
  478.     StartSweep();
  479. }
  480.  
  481. /*
  482. ================
  483. idSecurityCamera::Event_Pause
  484. ================
  485. */
  486. void idSecurityCamera::Event_Pause( void ) {
  487.     float    sweepWait;
  488.  
  489.     sweepWait = spawnArgs.GetFloat( "sweepWait", "0.5" );
  490.     sweeping = false;
  491.     StopSound( SND_CHANNEL_ANY, false );
  492.     StartSound( "snd_stop", SND_CHANNEL_BODY, 0, false, NULL );
  493.        PostEventSec( &EV_SecurityCam_ReverseSweep, sweepWait );
  494. }
  495.  
  496. /*
  497. ============
  498. idSecurityCamera::Killed
  499. ============
  500. */
  501. void idSecurityCamera::Killed( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location ) {
  502.     sweeping = false;
  503.     StopSound( SND_CHANNEL_ANY, false );
  504. // RAVEN BEGIN
  505. // bdube: replaced fx call with raven call
  506.     gameLocal.PlayEffect ( spawnArgs, "fx_destroyed", GetPhysics()->GetOrigin(), GetPhysics()->GetAxis() );
  507. /*
  508.     const char *fx = spawnArgs.GetString( "fx_destroyed" );
  509.     if ( fx[0] != '\0' ) {
  510.         idEntityFx::StartFx( fx, NULL, NULL, this, true );
  511.     }
  512. */
  513. // RAVEN END
  514.     physicsObj.SetSelf( this );
  515.     physicsObj.SetClipModel( new idClipModel( trm ), 0.02f );
  516.     physicsObj.SetOrigin( GetPhysics()->GetOrigin() );
  517.     physicsObj.SetAxis( GetPhysics()->GetAxis() );
  518.     physicsObj.SetBouncyness( 0.2f );
  519.     physicsObj.SetFriction( 0.6f, 0.6f, 0.2f );
  520.     physicsObj.SetGravity( gameLocal.GetGravity() );
  521.     physicsObj.SetContents( CONTENTS_SOLID );
  522.     physicsObj.SetClipMask( MASK_SOLID | CONTENTS_BODY | CONTENTS_CORPSE | CONTENTS_MOVEABLECLIP );
  523.     SetPhysics( &physicsObj );
  524.     physicsObj.DropToFloor();
  525. }
  526.  
  527.  
  528. /*
  529. ============
  530. idSecurityCamera::Pain
  531. ============
  532. */
  533. bool idSecurityCamera::Pain( idEntity *inflictor, idEntity *attacker, int damage, const idVec3 &dir, int location ) {
  534. // RAVEN BEGIN
  535. // bdube: replaced fx call with raven call
  536.     PlayEffect ( "fx_damage", renderEntity.origin, renderEntity.axis );
  537. /*
  538.     const char *fx = spawnArgs.GetString( "fx_damage" );
  539.     if ( fx[0] != '\0' ) {
  540.         idEntityFx::StartFx( fx, NULL, NULL, this, true );
  541.     }
  542. */
  543. // RAVEN END
  544.     return true;
  545. }
  546.  
  547.  
  548. /*
  549. ================
  550. idSecurityCamera::Present
  551.  
  552. Present is called to allow entities to generate refEntities, lights, etc for the renderer.
  553. ================
  554. */
  555. void idSecurityCamera::Present( void ) {
  556.     // don't present to the renderer if the entity hasn't changed
  557.     if ( !( thinkFlags & TH_UPDATEVISUALS ) ) {
  558.         return;
  559.     }
  560.     BecomeInactive( TH_UPDATEVISUALS );
  561.  
  562.     // camera target for remote render views
  563.     if ( cameraTarget ) {
  564.         renderEntity.remoteRenderView = cameraTarget->GetRenderView();
  565.     }
  566.  
  567.     // if set to invisible, skip
  568.     if ( !renderEntity.hModel || IsHidden() ) {
  569.         return;
  570.     }
  571.  
  572.     // add to refresh list
  573.     if ( modelDefHandle == -1 ) {
  574.         modelDefHandle = gameRenderWorld->AddEntityDef( &renderEntity );
  575.     } else {
  576.         gameRenderWorld->UpdateEntityDef( modelDefHandle, &renderEntity );
  577.     }
  578. }
  579.