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

  1. // RAVEN BEGIN
  2. // bdube: note that this file is no longer merged with Doom3 updates
  3. //
  4. // MERGE_DATE 09/30/2004
  5.  
  6. #include "../idlib/precompiled.h"
  7. #pragma hdrstop
  8.  
  9. #include "Game_local.h"
  10.  
  11.  
  12. /*
  13. ===============================================================================
  14.  
  15.   idItem
  16.  
  17. ===============================================================================
  18. */
  19.  
  20. const idEventDef EV_DropToFloor( "<dropToFloor>" );
  21. const idEventDef EV_RespawnItem( "respawn" );
  22. const idEventDef EV_RespawnFx( "<respawnFx>" );
  23. const idEventDef EV_GetPlayerPos( "<getplayerpos>" );
  24. const idEventDef EV_HideObjective( "<hideobjective>", "e" );
  25. const idEventDef EV_CamShot( "<camshot>" );
  26.  
  27. // RAVEN BEGIN
  28. // abahr:
  29. const idEventDef EV_SetGravity( "<setGravity>" );
  30. // RAVEN END
  31.  
  32. CLASS_DECLARATION( idEntity, idItem )
  33.     EVENT( EV_DropToFloor,        idItem::Event_DropToFloor )
  34.     EVENT( EV_Touch,            idItem::Event_Touch )
  35.     EVENT( EV_Activate,            idItem::Event_Trigger )
  36.     EVENT( EV_RespawnItem,        idItem::Event_Respawn )
  37.     EVENT( EV_RespawnFx,        idItem::Event_RespawnFx )
  38. // RAVEN BEGIN
  39. // abahr
  40.     EVENT( EV_SetGravity,        idItem::Event_SetGravity )
  41. // RAVEN END
  42.  
  43. END_CLASS
  44.  
  45.  
  46. /*
  47. ================
  48. idItem::idItem
  49. ================
  50. */
  51. idItem::idItem() {
  52.     spin = false;
  53.     inView = false;
  54.     skin = NULL;
  55.     pickupSkin = NULL;
  56.     inViewTime = 0;
  57.     lastCycle = 0;
  58.     lastRenderViewTime = -1;
  59.     itemShellHandle = -1;
  60.     shellMaterial = NULL;
  61.     orgOrigin.Zero();
  62.     canPickUp = true;
  63.     fl.networkSync = true;
  64.     trigger = NULL;
  65.     syncPhysics = false;
  66.     srvReady = -1;
  67.     clReady = -1;
  68.     effectIdle = NULL;
  69.     itemPVSArea = 0;
  70. }
  71.  
  72. /*
  73. ================
  74. idItem::~idItem
  75. ================
  76. */
  77. idItem::~idItem() {
  78.     // remove the highlight shell
  79.     if ( itemShellHandle != -1 ) {
  80.         gameRenderWorld->FreeEntityDef( itemShellHandle );
  81.     }
  82.     if ( trigger ) {
  83.         delete trigger;
  84.     }
  85.     
  86.     SetPhysics( NULL );
  87. }
  88.  
  89. /*
  90. ================
  91. idItem::Save
  92. ================
  93. */
  94. void idItem::Save( idSaveGame *savefile ) const {
  95.        savefile->WriteClipModel( trigger );
  96.     savefile->WriteBool( spin );
  97.  
  98.     savefile->WriteSkin( skin );
  99.     savefile->WriteSkin( pickupSkin );
  100.  
  101.     savefile->WriteVec3( orgOrigin );
  102.  
  103.     savefile->WriteBool( pulse );
  104.     savefile->WriteBool( canPickUp );
  105.  
  106.     savefile->WriteStaticObject( physicsObj );
  107.  
  108. //    savefile->WriteInt(itemShellHandle);    // cnicholson: Set at end of Restore, do not save
  109.     savefile->WriteMaterial( shellMaterial );
  110.  
  111.     savefile->WriteBool( inView );
  112.     savefile->WriteInt( inViewTime );
  113.     savefile->WriteInt( lastCycle );
  114.     savefile->WriteInt( lastRenderViewTime );
  115. }
  116.  
  117. /*
  118. ================
  119. idItem::Restore
  120. ================
  121. */
  122. void idItem::Restore( idRestoreGame *savefile ) {
  123.     savefile->ReadClipModel( trigger );
  124.     savefile->ReadBool( spin );
  125.  
  126.     savefile->ReadSkin( skin );
  127.     savefile->ReadSkin( pickupSkin );
  128.  
  129.     savefile->ReadVec3( orgOrigin );
  130.  
  131.     savefile->ReadBool( pulse );
  132.     savefile->ReadBool( canPickUp );
  133.  
  134.     savefile->ReadStaticObject ( physicsObj );
  135.  
  136. //    savefile->ReadInt(itemShellHandle);    // cnicholson: Set at end of function, do not restore
  137.     savefile->ReadMaterial( shellMaterial );
  138.  
  139.     savefile->ReadBool( inView );
  140.     savefile->ReadInt( inViewTime );
  141.     savefile->ReadInt( lastCycle );
  142.     savefile->ReadInt( lastRenderViewTime );
  143.  
  144.     RestorePhysics( &physicsObj );
  145.     
  146.     physicsObj.SetSelf( this );
  147.     
  148.     itemShellHandle = -1;
  149. }
  150.  
  151. /*
  152. ================
  153. idItem::UpdateRenderEntity
  154. ================
  155. */
  156. bool idItem::UpdateRenderEntity( renderEntity_s *renderEntity, const renderView_t *renderView ) const {
  157.  
  158.     if ( lastRenderViewTime == renderView->time ) {
  159.         return false;
  160.     }
  161.  
  162.     lastRenderViewTime = renderView->time;
  163.  
  164.     // check for glow highlighting if near the center of the view
  165.     idVec3 dir = renderEntity->origin - renderView->vieworg;
  166.     dir.Normalize();
  167.     float d = dir * renderView->viewaxis[0];
  168.  
  169.     // two second pulse cycle
  170.     float cycle = ( renderView->time - inViewTime ) / 2000.0f;
  171.  
  172.     if ( d > 0.94f ) {
  173.         if ( !inView ) {
  174.             inView = true;
  175.             if ( cycle > lastCycle ) {
  176.                 // restart at the beginning
  177.                 inViewTime = renderView->time;
  178.                 cycle = 0.0f;
  179.             }
  180.         }
  181.     } else {
  182.         if ( inView ) {
  183.             inView = false;
  184.             lastCycle = ceil( cycle );
  185.         }
  186.     }
  187.  
  188.     // fade down after the last pulse finishes 
  189.     if ( !inView && cycle > lastCycle ) {
  190.         renderEntity->shaderParms[4] = 0.0f;
  191.     } else {
  192.         // pulse up in 1/4 second
  193.         cycle -= (int)cycle;
  194.         if ( cycle < 0.1f ) {
  195.             renderEntity->shaderParms[4] = cycle * 10.0f;
  196.         } else if ( cycle < 0.2f ) {
  197.             renderEntity->shaderParms[4] = 1.0f;
  198.         } else if ( cycle < 0.3f ) {
  199.             renderEntity->shaderParms[4] = 1.0f - ( cycle - 0.2f ) * 10.0f;
  200.         } else {
  201.             // stay off between pulses
  202.             renderEntity->shaderParms[4] = 0.0f;
  203.         }
  204.     }
  205.  
  206.     // update every single time this is in view
  207.     return true;
  208. }
  209.  
  210. /*
  211. ================
  212. idItem::UpdateTrigger
  213. ================
  214. */
  215. void idItem::UpdateTrigger ( void ) {
  216.     // update trigger position
  217. // RAVEN BEGIN
  218. // ddynerman: multiple clip worlds
  219.     trigger->Link( this, 0, GetPhysics()->GetOrigin(), mat3_identity );
  220. // RAVEN END
  221. }
  222.  
  223. /*
  224. ================
  225. idItem::ModelCallback
  226. ================
  227. */
  228. bool idItem::ModelCallback( renderEntity_t *renderEntity, const renderView_t *renderView ) {
  229.     const idItem *ent;
  230.  
  231.     // this may be triggered by a model trace or other non-view related source
  232.     if ( !renderView ) {
  233.         return false;
  234.     }
  235.  
  236.     ent = static_cast<idItem *>(gameLocal.entities[ renderEntity->entityNum ]);
  237.     if ( !ent ) {
  238.         gameLocal.Error( "idItem::ModelCallback: callback with NULL game entity" );
  239.     }
  240.  
  241.     return ent->UpdateRenderEntity( renderEntity, renderView );
  242. }
  243.  
  244.  
  245. /*
  246. ================
  247. idItem::GetPhysicsToVisualTransform
  248. ================
  249. */
  250. bool idItem::GetPhysicsToVisualTransform( idVec3 &origin, idMat3 &axis ) {
  251.     if( !spin || (gameLocal.isServer && !gameLocal.isListenServer) ) {
  252.         return false;
  253.     }
  254.     
  255.     idAngles ang;
  256.     ang.pitch = ang.roll = 0.0f;
  257.     ang.yaw = ( gameLocal.time & 4095 ) * 360.0f / -4096.0f;
  258.     axis = ang.ToMat3() * GetPhysics()->GetAxis();
  259.  
  260.     float scale = 0.005f + entityNumber * 0.00001f;
  261.     origin.Zero();
  262.  
  263.     origin += GetPhysics()->GetAxis()[2] * (4.0f + idMath::Cos( ( gameLocal.time + 1000 ) * scale ) * 4.0f);
  264.  
  265.     return true;
  266. }
  267.  
  268. // RAVEN BEGIN
  269. // mekberg: added
  270. /*
  271. ================
  272. idItem::Collide
  273. ================
  274. */
  275. bool idItem::Collide( const trace_t &collision, const idVec3 &velocity ) {
  276.     if ( gameLocal.isMultiplayer && collision.c.contents & CONTENTS_ITEMCLIP ) {
  277.         PostEventMS( &EV_Remove, 0 );
  278.     }
  279.     return false;
  280. }
  281. // RAVEN END
  282.  
  283. /*
  284. ================
  285. idItem::Think
  286. ================
  287. */
  288. void idItem::Think( void ) {
  289.     if ( thinkFlags & TH_PHYSICS ) {
  290.         RunPhysics();        
  291.         UpdateTrigger();
  292.     }
  293.  
  294.     if ( gameLocal.IsMultiplayer() && g_skipItemShadowsMP.GetBool() ) {
  295.         renderEntity.suppressShadowInViewID = gameLocal.localClientNum + 1;
  296.     } else {
  297.         renderEntity.suppressShadowInViewID = 0;
  298.     }
  299.  
  300.     UpdateVisuals();
  301.     Present();
  302. }
  303.  
  304. /*
  305. ================
  306. idItem::Present
  307. ================
  308. */
  309. void idItem::Present( void ) {
  310.     idEntity::Present();
  311.  
  312.     if ( !fl.hidden && pulse ) {
  313.         // also add a highlight shell model
  314.         renderEntity_t    shell;
  315.  
  316.         shell = renderEntity;
  317.  
  318.         // we will mess with shader parms when the item is in view
  319.         // to give the "item pulse" effect
  320.         shell.callback = idItem::ModelCallback;
  321.         shell.entityNum = entityNumber;
  322.         shell.customShader = shellMaterial;
  323.         if ( itemShellHandle == -1 ) {
  324.             itemShellHandle = gameRenderWorld->AddEntityDef( &shell );
  325.         } else {
  326.             gameRenderWorld->UpdateEntityDef( itemShellHandle, &shell );
  327.         }
  328.     }
  329. }
  330.  
  331. /*
  332. ================
  333. idItem::InstanceJoin
  334. ================
  335. */
  336. void idItem::InstanceJoin( void ) {
  337.     idEntity::InstanceJoin();
  338.  
  339.     UpdateModelTransform();
  340.     if ( spawnArgs.GetString( "fx_idle" ) ) {
  341.         PlayEffect( "fx_idle", GetPhysics()->GetOrigin(), GetPhysics()->GetAxis(), true );
  342.     }
  343. }
  344.  
  345. /*
  346. ================
  347. idItem::InstanceLeave
  348. ================
  349. */
  350. void idItem::InstanceLeave( void ) {
  351.     idEntity::InstanceLeave();
  352.  
  353.     StopEffect( "fx_idle", true );
  354. }
  355.  
  356. /*
  357. ================
  358. idItem::Spawn
  359. ================
  360. */
  361. void idItem::Spawn( void ) {
  362.     idStr        giveTo;
  363.     idEntity *    ent;
  364.     idVec3        vSize;
  365.     idBounds    bounds(vec3_origin);
  366.  
  367.     // check for triggerbounds, which allows for non-square triggers (useful for, say, a CTF flag)
  368.     if ( spawnArgs.GetVector( "triggerbounds", "16 16 16", vSize )) {
  369.         bounds.AddPoint(idVec3( vSize.x*0.5f,  vSize.y*0.5f, 0.0f));
  370.         bounds.AddPoint(idVec3(-vSize.x*0.5f, -vSize.y*0.5f, vSize.z));
  371.     }
  372.     else {
  373.         // create a square trigger for item pickup
  374.         float tsize;
  375.         spawnArgs.GetFloat( "triggersize", "16.0", tsize );
  376.         bounds.ExpandSelf( tsize );
  377.     }
  378.  
  379. // RAVEN BEGIN
  380. // mwhitlock: Dynamic memory consolidation
  381.     RV_PUSH_HEAP_MEM(this);
  382. // RAVEN END
  383.     trigger = new idClipModel( idTraceModel( bounds ));
  384. // RAVEN BEGIN
  385. // mwhitlock: Dynamic memory consolidation
  386.     RV_POP_HEAP();
  387. // RAVEN END
  388. // RAVEN BEGIN
  389. // ddynerman: multiple clip worlds
  390.     trigger->Link( this, 0, GetPhysics()->GetOrigin(), GetPhysics()->GetAxis() );
  391. // RAVEN END
  392.  
  393.     physicsObj.SetSelf ( this );
  394. // RAVEN BEGIN
  395. // mwhitlock: Dynamic memory consolidation
  396.     RV_PUSH_HEAP_MEM(this);
  397. // RAVEN END
  398.  
  399.     physicsObj.SetClipModel( new idClipModel( GetPhysics()->GetClipModel() ), 1.0f );
  400.  
  401. // RAVEN BEGIN
  402. // mwhitlock: Dynamic memory consolidation
  403.     RV_POP_HEAP();
  404. // RAVEN END
  405.     physicsObj.SetOrigin( GetPhysics()->GetOrigin() );
  406.     physicsObj.SetAxis( GetPhysics()->GetAxis() );
  407.     physicsObj.SetGravity( gameLocal.GetGravity() );
  408.     physicsObj.SetContents( 0 );
  409.     physicsObj.SetClipMask( MASK_SOLID );
  410.     physicsObj.SetFriction( 0.0f, 0.0f, 6.0f );
  411.     SetPhysics( &physicsObj );
  412.  
  413.     if ( spawnArgs.GetBool( "start_off" ) ) {
  414.         trigger->SetContents( 0 );
  415.         Hide();
  416.     } else {
  417.         trigger->SetContents( CONTENTS_TRIGGER );
  418.     }
  419.  
  420.     giveTo = spawnArgs.GetString( "owner" );
  421.     if ( giveTo.Length() ) {
  422.         ent = gameLocal.FindEntity( giveTo );
  423.         if ( !ent ) {
  424.             gameLocal.Error( "Item couldn't find owner '%s'", giveTo.c_str() );
  425.         }
  426.         PostEventMS( &EV_Touch, 0, ent, NULL );
  427.     }
  428.  
  429.     if ( spawnArgs.GetBool( "spin" ) || gameLocal.isMultiplayer ) {
  430.         spin = true;
  431.         BecomeActive( TH_THINK );
  432.     }
  433.  
  434.     if ( spawnArgs.GetString( "fx_idle" ) ) {
  435.         effectIdle = PlayEffect( "fx_idle", GetPhysics()->GetOrigin(), GetPhysics()->GetAxis(), true );
  436.     }
  437.  
  438.     // pulse ( and therefore itemShellHandle ) was taken out and shot. do not sync
  439.     //pulse = !spawnArgs.GetBool( "nopulse" );
  440.     pulse = false;
  441.     orgOrigin = GetPhysics()->GetOrigin();
  442.  
  443.     canPickUp = !( spawnArgs.GetBool( "triggerFirst" ) || spawnArgs.GetBool( "no_touch" ) );
  444.  
  445.     inViewTime = -1000;
  446.     lastCycle = -1;
  447.     itemShellHandle = -1;
  448. // RAVEN BEGIN
  449. // abahr: move texture to def file for precaching
  450.     shellMaterial = declManager->FindMaterial( spawnArgs.GetString("mtr_highlight", "_default") );
  451.     PostEventMS( &EV_SetGravity, 0 );
  452. // RAVEN END
  453.     if ( spawnArgs.GetString( "skin", NULL ) ) {
  454.         skin = declManager->FindSkin( spawnArgs.GetString( "skin" ), false );
  455.         if( skin ) {
  456.             SetSkin( skin );
  457.             srvReady = 1;
  458.         }
  459.     } else {
  460.         skin = NULL;
  461.     }
  462.  
  463.     if ( spawnArgs.GetString( "skin_pickup", NULL ) ) {
  464.         pickupSkin = declManager->FindSkin( spawnArgs.GetString( "skin_pickup" ), false );
  465.     } else {
  466.         pickupSkin = NULL;
  467.     }
  468.  
  469.     syncPhysics = spawnArgs.GetBool( "net_syncPhysics", "0" );
  470.  
  471.     if ( srvReady == -1 ) {
  472.         srvReady = IsHidden() ? 0 : 1;
  473.     }
  474.  
  475. // RAVEN BEGIN
  476. // mekberg: added for removing pickups in mp in pits
  477.     if ( gameLocal.isMultiplayer ) {
  478.         GetPhysics( )->SetClipMask( GetPhysics( )->GetClipMask( ) | CONTENTS_ITEMCLIP );
  479.     }
  480. // RAVEN END
  481.  
  482.     if( gameLocal.isMultiplayer ) {
  483.         itemPVSArea = gameLocal.pvs.GetPVSArea( GetPhysics()->GetOrigin() );
  484.     } else {
  485.         itemPVSArea = 0;
  486.     }
  487. }
  488.  
  489. /*
  490. ================
  491. idItem::Event_SetGravity
  492. ================
  493. */
  494. void idItem::Event_SetGravity() {
  495.     // If the item isnt a dropped item then see if it should settle itself
  496.     // to the floor or not
  497.     if ( !spawnArgs.GetBool( "dropped" ) ) {
  498.         if ( spawnArgs.GetBool( "nodrop" ) ) {
  499.             physicsObj.PutToRest();
  500.         } else {
  501.              PostEventMS( &EV_DropToFloor, 0 );
  502.         }
  503.     }
  504. }
  505. // RAVEN END
  506.  
  507. /*
  508. ================
  509. idItem::GetAttributes
  510. ================
  511. */
  512. void idItem::GetAttributes( idDict &attributes ) {
  513.     int                    i;
  514.     const idKeyValue    *arg;
  515.  
  516.     for( i = 0; i < spawnArgs.GetNumKeyVals(); i++ ) {
  517.         arg = spawnArgs.GetKeyVal( i );
  518.         if ( arg->GetKey().Left( 4 ) == "inv_" ) {
  519.             attributes.Set( arg->GetKey().Right( arg->GetKey().Length() - 4 ), arg->GetValue() );
  520.         }
  521.     }
  522. }
  523.  
  524. /*
  525. ================
  526. idItem::GiveToPlayer
  527. ================
  528. */
  529. bool idItem::GiveToPlayer( idPlayer *player ) {
  530.     if ( player == NULL ) {
  531.         return false;
  532.     }
  533.  
  534.     // no pickups during warmup
  535.     /*if ( gameLocal.isMultiplayer && ( (gameLocal.mpGame.GetGameState() != idMultiplayerGame::GAMEON) ||  
  536.         (gameLocal.gameType == GAME_TOURNEY && tourneyManager->GetArena( player->GetInstance() ).GetState() != AS_ROUND ) ) ) {
  537.         return false;
  538.     }*/
  539.  
  540.     if ( spawnArgs.GetBool( "inv_carry" ) ) {
  541.         return player->GiveInventoryItem( &spawnArgs );
  542.     } 
  543.     
  544.     return player->GiveItem( this );
  545. }
  546.  
  547. /*
  548. ===============
  549. idItem::SendPickupMsg
  550. ===============
  551. */
  552. void idItem::SendPickupMsg( int clientNum ) {
  553.     idBitMsg    msg;
  554.     byte        msgBuf[MAX_GAME_MESSAGE_SIZE];
  555.  
  556.     msg.Init( msgBuf, sizeof( msgBuf ) );
  557.     msg.WriteByte( GAME_UNRELIABLE_MESSAGE_EVENT );
  558.     msg.WriteBits( gameLocal.GetSpawnId( this ), 32 );
  559.     msg.WriteByte( EVENT_PICKUP );
  560.     msg.WriteByte( clientNum );
  561.  
  562.     // send as unreliable to client picking up the item, so it can play HUD things
  563.     for( int i = 0; i < MAX_CLIENTS; i++ ) {
  564.         if( gameLocal.entities[ i ] ) {
  565.             gameLocal.SendUnreliableMessagePVS( msg, this, itemPVSArea );    
  566.         }
  567.     }
  568. }
  569.  
  570. /*
  571. ================
  572. idItem::Pickup
  573. ================
  574. */
  575. bool idItem::Pickup( idPlayer *player ) {
  576.     assert( !gameLocal.isClient );
  577.     
  578.     if ( !GiveToPlayer( player ) ) {
  579.         return false;
  580.     }
  581.  
  582.     if ( gameLocal.isServer ) {
  583.         SendPickupMsg( player->entityNumber );
  584.     }
  585.  
  586.     // Check for global acquire sounds in multiplayer
  587.      if ( gameLocal.isMultiplayer && spawnArgs.GetBool( "globalAcquireSound" ) ) {
  588.         gameLocal.mpGame.PlayGlobalItemAcquireSound( entityDefNumber );
  589.     } else {
  590.         StartSound( "snd_acquire", SND_CHANNEL_ITEM, 0, false, NULL );
  591.     }
  592.         
  593.     // trigger our targets
  594.     ActivateTargets( player );
  595.  
  596.     //dropped weapon?
  597.     bool dropped = spawnArgs.GetBool( "dropped" );
  598.  
  599.     //if a placed item and si_weaponStay is on and we're a weapon, don't remove and respawn
  600.     if ( gameLocal.IsMultiplayer() ) {
  601.         if ( !dropped )    {
  602.             if ( spawnArgs.FindKey( "weaponclass" ) ) { 
  603.                 if ( gameLocal.serverInfo.GetBool( "si_weaponStay" ) ) {
  604.                     return true;
  605.                 }
  606.             }
  607.         }
  608.     }
  609.  
  610.     // clear our contents so the object isn't picked up twice
  611.     GetPhysics()->SetContents( 0 );
  612.  
  613.     // hide the model, or switch to the pickup skin
  614.     if ( pickupSkin ) {
  615.         SetSkin( pickupSkin );
  616.         srvReady = 0;
  617.     } else {
  618.         Hide();
  619.         BecomeInactive( TH_THINK );
  620.     }
  621.  
  622.     // remove the highlight shell
  623.     if ( itemShellHandle != -1 ) {
  624.         gameRenderWorld->FreeEntityDef( itemShellHandle );
  625.         itemShellHandle = -1;
  626.     }
  627.  
  628.     // asalmon: Added option for a differnt respawn rate based on gametype.
  629.     float respawn = spawnArgs.GetFloat(va("respawn_%s",gameLocal.serverInfo.GetString( "si_gameType" )), "-1.0");
  630.     if( respawn == -1.0f ) {
  631.         respawn = spawnArgs.GetFloat( "respawn", "5.0" );
  632.     }
  633.  
  634.     bool no_respawn = spawnArgs.GetBool( "no_respawn" );
  635.  
  636.     if ( !gameLocal.isMultiplayer ) {
  637.         respawn = 0.0f;
  638.     }
  639.  
  640.     if ( respawn && !dropped && !no_respawn ) {
  641.         const char *sfx = spawnArgs.GetString( "fx_Respawn" );
  642.         if ( sfx && *sfx ) {
  643.             PostEventSec( &EV_RespawnFx, respawn - 0.5f );
  644.         }
  645.         PostEventSec( &EV_RespawnItem, respawn );
  646.     } else if ( !spawnArgs.GetBool( "inv_objective" ) && !no_respawn ) {
  647.         // give some time for the pickup sound to play
  648.         // FIXME: Play on the owner
  649.         if ( !spawnArgs.GetBool( "inv_carry" ) ) {
  650.             PostEventMS( &EV_Remove, 5000 );
  651.         }
  652.     }
  653.     
  654.     trigger->SetContents( 0 );    
  655.     
  656.     StopEffect( "fx_idle" );
  657.  
  658.     return true;
  659. }
  660.  
  661. /*
  662. ================
  663. idItem::Hide
  664. ================
  665. */
  666. void idItem::Hide( void ) {
  667.     srvReady = 0;
  668.     idEntity::Hide( );    
  669.     trigger->SetContents ( 0 );
  670. }
  671.  
  672. /*
  673. ================
  674. idItem::Show
  675. ================
  676. */
  677. void idItem::Show( void ) {
  678.     srvReady = 1;
  679.     idEntity::Show( );
  680.     trigger->SetContents( CONTENTS_TRIGGER );
  681. }
  682.  
  683. /*
  684. ================
  685. idItem::ClientStale
  686. ================
  687. */
  688. bool idItem::ClientStale( void ) {
  689.     idEntity::ClientStale();
  690.  
  691.     StopEffect( "fx_idle" );
  692.     return false;
  693. }
  694.  
  695. /*
  696. ================
  697. idItem::ClientUnstale
  698. ================
  699. */
  700. void idItem::ClientUnstale( void ) {
  701.     idEntity::ClientUnstale();
  702.  
  703.     UpdateModelTransform();
  704.     if ( spawnArgs.GetString( "fx_idle" ) ) {
  705.         PlayEffect( "fx_idle", GetPhysics()->GetOrigin(), GetPhysics()->GetAxis(), true );
  706.     }
  707. }
  708.  
  709. /*
  710. ================
  711. idItem::ClientPredictionThink
  712. ================
  713. */
  714. void idItem::ClientPredictionThink( void ) {
  715.     // only think forward because the state is not synced through snapshots
  716.     if ( !gameLocal.isNewFrame ) {
  717.         return;
  718.     }
  719.     Think();
  720. }
  721.  
  722. /*
  723. ================
  724. idItem::WriteFromSnapshot
  725. ================
  726. */
  727. void idItem::WriteToSnapshot( idBitMsgDelta &msg ) const {
  728.     if ( syncPhysics ) {
  729.         physicsObj.WriteToSnapshot( msg );
  730.     }
  731.     assert( srvReady != -1 );
  732.     msg.WriteBits( ( srvReady == 1 ), 1 );
  733. }
  734.  
  735. /*
  736. ================
  737. idItem::ReadFromSnapshot
  738. ================
  739. */
  740. void idItem::ReadFromSnapshot( const idBitMsgDelta &msg ) {
  741.     if ( syncPhysics ) {
  742.         physicsObj.ReadFromSnapshot( msg );
  743.     }
  744.     int newReady = ( msg.ReadBits( 1 ) != 0 );
  745.     idVec3 resetOrigin( 0, 0, 0 );
  746.     // client spawns the ent with ready == -1 so the state set happens at least once
  747.     if ( newReady != clReady ) {
  748.         if ( newReady ) {
  749.             if ( pickupSkin ) {
  750.                 SetSkin( skin );
  751.             } else {
  752.                 Show();
  753.             }
  754.  
  755.             if ( effectIdle.GetEntity( ) ) {
  756.                 UpdateModelTransform();
  757.                 effectIdle->SetOrigin( resetOrigin );
  758.             } else if ( spawnArgs.GetString( "fx_idle" ) ) {
  759.                 UpdateModelTransform();
  760.                 effectIdle = PlayEffect( "fx_idle", GetPhysics()->GetOrigin(), GetPhysics()->GetAxis(), true );
  761.             }
  762.         } else {
  763.             if ( pickupSkin ) {
  764.                 SetSkin( pickupSkin );
  765.             } else {
  766.                 Hide();
  767.             }
  768.             StopEffect( "fx_idle" );
  769.             effectIdle = NULL;
  770.         }
  771.     }
  772.     clReady = newReady;
  773. }
  774.  
  775. /*
  776. ================
  777. idItem::Event_Pickup
  778. ================
  779. */
  780. void idItem::Event_Pickup( int clientNum ) {
  781.     idPlayer *player;
  782.  
  783.     assert( gameLocal.isClient );
  784.     
  785.     // play pickup sound
  786.     if ( !spawnArgs.GetBool( "globalAcquireSound" ) ) {
  787.         StartSound( "snd_acquire", SND_CHANNEL_ITEM, 0, false, NULL );
  788.     }
  789.  
  790.     if( clientNum == gameLocal.localClientNum ) {
  791.         player = (idPlayer*)gameLocal.entities[ clientNum ];
  792.         if ( player ) {
  793.             player->GiveItem( this );
  794.         }
  795.     }
  796. }
  797.  
  798. /*
  799. ================
  800. idItem::ClientReceiveEvent
  801. ================
  802. */
  803. bool idItem::ClientReceiveEvent( int event, int time, const idBitMsg &msg ) {
  804.     switch( event ) {
  805.         case EVENT_PICKUP: {
  806.             int clientNum = msg.ReadByte();
  807.             if( clientNum >= 0 && clientNum < MAX_CLIENTS ) {
  808.                 Event_Pickup( clientNum );
  809.             }
  810.             return true;
  811.         }
  812.         case EVENT_RESPAWNFX: {
  813.             Event_RespawnFx();
  814.             return true;
  815.         }
  816.         default: {
  817.             return idEntity::ClientReceiveEvent( event, time, msg );
  818.         }
  819.     }
  820. //unreachable
  821. //    return false;
  822. }
  823.  
  824. /*
  825. ================
  826. idItem::Event_DropToFloor
  827. ================
  828. */
  829. void idItem::Event_DropToFloor( void ) {
  830.      // don't drop the floor if bound to another entity
  831.      if ( GetBindMaster() != NULL && GetBindMaster() != this ) {
  832.          return;
  833.      }
  834.      
  835.      physicsObj.DropToFloor( );
  836. }
  837.  
  838. /*
  839. ================
  840. idItem::Event_Touch
  841. ================
  842. */
  843. void idItem::Event_Touch( idEntity *other, trace_t *trace ) {
  844. // RAVEN BEGIN
  845. // jnewquist: Use accessor for static class type 
  846.     if ( !other->IsType( idPlayer::GetClassType() ) ) {
  847. // RAVEN END
  848.         return;
  849.     }
  850.  
  851.     if ( !canPickUp ) {
  852.         return;
  853.     }
  854.  
  855.     Pickup( static_cast<idPlayer *>(other) );
  856. }
  857.  
  858. /*
  859. ================
  860. idItem::Event_Trigger
  861. ================
  862. */
  863. void idItem::Event_Trigger( idEntity *activator ) {
  864.     if ( !canPickUp && spawnArgs.GetBool( "triggerFirst" ) ) {
  865.         canPickUp = true;
  866.         return;
  867.     }
  868.  
  869. // RAVEN BEGIN
  870. // jnewquist: Use accessor for static class type 
  871.     if ( activator && activator->IsType( idPlayer::GetClassType() ) ) {
  872. // RAVEN END
  873.         Pickup( static_cast<idPlayer *>( activator ) );
  874.     }
  875. }
  876.  
  877. /*
  878. ================
  879. idItem::Event_Respawn
  880. ================
  881. */
  882. void idItem::Event_Respawn( void ) {
  883.  
  884.     if ( pickupSkin ) {
  885.         SetSkin( skin );
  886.         srvReady = true;
  887.     } else {
  888.         BecomeActive( TH_THINK );    
  889.         Show();
  890.     }
  891.  
  892.     inViewTime = -1000;
  893.     lastCycle = -1;
  894.     trigger->SetContents ( CONTENTS_TRIGGER );
  895.     SetOrigin( orgOrigin );
  896.     StartSound( "snd_respawn", SND_CHANNEL_ITEM, 0, false, NULL );
  897.     PostEventMS( &EV_SetGravity, 0 );
  898.     CancelEvents( &EV_RespawnItem ); // don't double respawn
  899.  
  900.     if ( spawnArgs.GetString( "fx_idle" ) ) {
  901.         PlayEffect( "fx_idle", GetPhysics()->GetOrigin(), GetPhysics()->GetAxis(), true );
  902.     }
  903. }
  904.  
  905. /*
  906. ================
  907. idItem::Event_RespawnFx
  908. ================
  909. */
  910. void idItem::Event_RespawnFx( void ) {
  911.     idBitMsg    msg;
  912.     byte        msgBuf[MAX_GAME_MESSAGE_SIZE];
  913.  
  914.     if ( gameLocal.isServer ) {
  915.         msg.Init( msgBuf, sizeof( msgBuf ) );
  916.         msg.WriteByte( GAME_UNRELIABLE_MESSAGE_EVENT );
  917.         msg.WriteBits( gameLocal.GetSpawnId( this ), 32 );
  918.         msg.WriteByte( EVENT_RESPAWNFX );
  919.         // send unreliable PVS-sensitive
  920.         gameLocal.SendUnreliableMessagePVS( msg, this, gameLocal.pvs.GetPVSArea( GetPhysics()->GetOrigin() ) );
  921.     }
  922.  
  923.     gameLocal.PlayEffect( spawnArgs, "fx_respawn", GetPhysics()->GetOrigin(), idVec3(0,0,1).ToMat3(), false, vec3_origin );
  924. }
  925.  
  926. /*
  927. ===============================================================================
  928.  
  929.   idItemPowerup
  930.  
  931. ===============================================================================
  932. */
  933.  
  934. /*
  935. ===============
  936. idItemPowerup
  937. ===============
  938. */
  939.  
  940. CLASS_DECLARATION( idItem, idItemPowerup )
  941. END_CLASS
  942.  
  943. /*
  944. ================
  945. idItemPowerup::idItemPowerup
  946. ================
  947. */
  948. idItemPowerup::idItemPowerup() {
  949.     time = 0;
  950.     type = 0;
  951.     droppedTime = 0;
  952.     unique = false;
  953. }
  954.  
  955. /*
  956. ================
  957. idItemPowerup::Save
  958. ================
  959. */
  960. void idItemPowerup::Save( idSaveGame *savefile ) const {
  961.     savefile->WriteInt( time );
  962.     savefile->WriteInt( type );
  963.     savefile->WriteInt( droppedTime );    // cnicholson: Added unsaved var
  964. }
  965.  
  966. /*
  967. ================
  968. idItemPowerup::Restore
  969. ================
  970. */
  971. void idItemPowerup::Restore( idRestoreGame *savefile ) {
  972.     savefile->ReadInt( time );
  973.     savefile->ReadInt( type );
  974.     savefile->ReadInt( droppedTime );    // cnicholson: Added unrestored var
  975. }
  976.  
  977. /*
  978. ================
  979. idItemPowerup::Spawn
  980. ================
  981. */
  982. void idItemPowerup::Spawn( void ) {
  983.     time = SEC2MS( spawnArgs.GetInt( "time", "30" ) );
  984.     // SEC2MS screws up when we want -1 time (no expiration)
  985.     if( spawnArgs.GetInt( "time" ) == -1 ) {
  986.         time = -1;
  987.     }
  988.  
  989.     type = spawnArgs.GetInt( "type", "0" );
  990.     
  991.     // If the powerup was dropped then make it dissapear using its remaining time.
  992.     if ( spawnArgs.GetBool( "dropped" ) ) {
  993.         droppedTime = gameLocal.time + time;
  994.         PostEventMS( &EV_Remove, time );
  995.     }
  996.  
  997.     // unique powerpus won't respawn while a player has them
  998.     unique = spawnArgs.GetBool( "unique", "0" );
  999.     if( unique ) {
  1000.         spawnArgs.SetBool( "no_respawn", true );
  1001.     }
  1002.  
  1003.     if ( !idStr::Icmp( spawnArgs.GetString( "team" ), "strogg" ) ) {
  1004.         team = TEAM_STROGG;
  1005.     } else if( !idStr::Icmp( spawnArgs.GetString( "team" ), "marine" ) ) {
  1006.         team = TEAM_MARINE;
  1007.     } else {
  1008.         team = -1;
  1009.     }
  1010. }
  1011.  
  1012. /*
  1013. ================
  1014. idItemPowerup::GiveToPlayer
  1015. ================
  1016. */
  1017. bool idItemPowerup::GiveToPlayer( idPlayer *player ) {
  1018.     if ( !player || player->spectating ) {
  1019.         return false;
  1020.     }
  1021.     
  1022.     // only one arena CTF powerup at a time
  1023.     if( type >= POWERUP_AMMOREGEN && type <= POWERUP_SCOUT ) {
  1024.         if( (player->inventory.powerups & ARENA_POWERUP_MASK) != 0 ) {
  1025.             return false;
  1026.         } 
  1027.     }
  1028.  
  1029.     // in flavours of arena CTF (or are idItemPowerups only used in Arena? or even, are idItemPowerups MP only?), 
  1030.     //    ensure that items with a team can only be picked up by members of that team
  1031.     if ( gameLocal.IsMultiplayer() && gameLocal.IsTeamGame() && team >= 0 ) {
  1032.         if( team != player->team ) {
  1033.             return false;
  1034.         }
  1035.     }
  1036.  
  1037.     if ( droppedTime > 0 ) {
  1038.         player->GivePowerUp( type, droppedTime - gameLocal.time );
  1039.     } else {
  1040.         player->GivePowerUp( type, time );
  1041.     }
  1042.  
  1043.     // also call idItem::GiveToPlayer so any inv_* keywords get applied
  1044.     idItem::GiveToPlayer( player );
  1045.  
  1046.     return true;
  1047. }
  1048.  
  1049. /*
  1050. ================
  1051. idItemPowerup::Think
  1052. ================
  1053. */
  1054. void idItemPowerup::Think( void ) {
  1055.     int i;
  1056.  
  1057.     // idItem::Think() only needs to be called if we're spawned in
  1058.     if( !IsHidden() || (pickupSkin && GetSkin() != pickupSkin ) ) {
  1059.         // only get here if spawned in
  1060.         idItem::Think();
  1061.         return;
  1062.     }
  1063.  
  1064.     if( !unique ) {
  1065.         // non-unique despawned powerups don't need to think
  1066.         return;
  1067.     }
  1068.  
  1069.     for( i = 0; i < gameLocal.numClients; i++ ) {
  1070.         idPlayer* p = (idPlayer*)gameLocal.entities[ i ];
  1071.         if( p == NULL ) {
  1072.             continue;
  1073.         }
  1074.  
  1075.         // only spawn back in if noone on your team has the powerup
  1076.         if( p->PowerUpActive( type ) && p->team == team ) {
  1077.             break;
  1078.         }
  1079.     }
  1080.  
  1081.     if( i >= gameLocal.numClients ) {
  1082.         PostEventMS( &EV_RespawnItem, 0 );
  1083.     }
  1084. }
  1085.  
  1086. /*
  1087. ================
  1088. idItemPowerup::Pickup
  1089. ================
  1090. */
  1091. bool idItemPowerup::Pickup( idPlayer* player ) {
  1092.     // regular pickup routine, but unique items need to think to know when to respawn
  1093.     bool pickup;
  1094.     
  1095.     pickup = idItem::Pickup( player );
  1096.     if( unique ) {
  1097.         BecomeActive( TH_THINK );
  1098.     }
  1099.  
  1100.     return pickup;
  1101. }
  1102.  
  1103. /*
  1104. ===============================================================================
  1105.  
  1106.   idObjective
  1107.  
  1108. ===============================================================================
  1109. */
  1110.  
  1111. CLASS_DECLARATION( idItem, idObjective )
  1112.     EVENT( EV_Activate,            idObjective::Event_Trigger )
  1113.     EVENT( EV_HideObjective,    idObjective::Event_HideObjective )
  1114.     EVENT( EV_GetPlayerPos,        idObjective::Event_GetPlayerPos )
  1115.      EVENT( EV_CamShot,            idObjective::Event_CamShot )
  1116. END_CLASS
  1117.  
  1118. /*
  1119. ================
  1120. idObjective::idObjective
  1121. ================
  1122. */
  1123. idObjective::idObjective() {
  1124.     playerPos.Zero();
  1125.  
  1126. // RAVEN BEGIN
  1127. // mekberg: store triggered time for timed removal.
  1128.     triggerTime = 0;
  1129. // RAVEN END
  1130. }
  1131.  
  1132. /*
  1133. ================
  1134. idObjective::Save
  1135. ================
  1136. */
  1137. void idObjective::Save( idSaveGame *savefile ) const {
  1138.     savefile->WriteVec3( playerPos );
  1139. }
  1140.  
  1141. /*
  1142. ================
  1143. idObjective::Restore
  1144. ================
  1145. */
  1146. void idObjective::Restore( idRestoreGame *savefile ) {
  1147.     savefile->ReadVec3( playerPos );
  1148. // RAVEN BEGIN
  1149. // jnewquist: Don't do this on Xenon, we want prebuilt textures
  1150. #ifndef _XENON
  1151.      PostEventMS( &EV_CamShot, 250 );
  1152. #endif
  1153. // RAVEN END
  1154. }
  1155.  
  1156. /*
  1157. ================
  1158. idObjective::Spawn
  1159. ================
  1160. */
  1161. void idObjective::Spawn( void ) {
  1162.     Hide();
  1163. // RAVEN BEGIN
  1164. // jnewquist: Only post a camshot event if the spawn args request it
  1165. #ifndef _XENON
  1166.     const char *camName;
  1167.     if ( spawnArgs.GetString( "camShot", "", &camName ) ) {
  1168.         common->Warning( "SpawnArg camShot on %s is not recommended.", spawnArgs.GetString( "name" ) );
  1169.          PostEventMS( &EV_CamShot, 250 );
  1170.     }
  1171. #endif
  1172. // RAVEN END
  1173. }
  1174.  
  1175. /*
  1176. ================
  1177. idObjective::Event_Screenshot
  1178. ================
  1179. */
  1180. void idObjective::Event_CamShot( ) {
  1181.     const char *camName;
  1182. // RAVEN BEGIN
  1183. // bdube: changed screenshot location
  1184.      idStr shotName = "gfx/objectives/";
  1185.      shotName += spawnArgs.GetString( "screenshot" );
  1186.      shotName.SetFileExtension( ".tga" );
  1187.  // RAVEN END
  1188.     if ( spawnArgs.GetString( "camShot", "", &camName ) ) {
  1189.         idEntity *ent = gameLocal.FindEntity( camName );
  1190.         if ( ent && ent->cameraTarget ) {
  1191.             const renderView_t *view = ent->cameraTarget->GetRenderView();
  1192.             renderView_t fullView = *view;
  1193.             fullView.width = SCREEN_WIDTH;
  1194.             fullView.height = SCREEN_HEIGHT;
  1195.  
  1196.             // draw a view to a texture
  1197.             renderSystem->CropRenderSize( 256, 256, true );
  1198.             gameRenderWorld->RenderScene( &fullView );
  1199.              renderSystem->CaptureRenderToFile( shotName );
  1200.             renderSystem->UnCrop();
  1201.         }
  1202.     }
  1203. }  
  1204.  
  1205. /*
  1206. ================
  1207. idObjective::Event_Trigger
  1208. ================
  1209. */
  1210. void idObjective::Event_Trigger( idEntity *activator ) {
  1211.     idPlayer *player = gameLocal.GetLocalPlayer();
  1212.     if ( player ) {
  1213.         if ( spawnArgs.GetString( "inv_objective", NULL ) ) {
  1214. // RAVEN BEGIN
  1215. // abahr: changed player->hud to player->GetHud so when in a vehicle we update the vehicle hud
  1216. // twhitaker: changed player->hud to player->GetObjectiveHud(), to resolve all issues
  1217.              if ( player && player->GetObjectiveHud() ) {
  1218. // bdube: changed screenshot location
  1219.                 idStr shotName = spawnArgs.GetString( "screenshot" );
  1220.  
  1221.                 player->GetObjectiveHud()->SetStateString( "screenshot", shotName );
  1222.                 player->GetObjectiveHud()->SetStateString( "objective", "1" );
  1223.                 player->GetObjectiveHud()->SetStateString( "objectivetext", common->GetLocalizedString( spawnArgs.GetString( "objectivetext" ) ) );
  1224.                 player->GetObjectiveHud()->SetStateString( "objectivetitle", common->GetLocalizedString( spawnArgs.GetString( "objectivetitle" ) ) );
  1225. // RAVEN END
  1226.                  player->GiveObjective( spawnArgs.GetString( "objectivetitle" ), spawnArgs.GetString( "objectivetext" ), shotName );
  1227.  
  1228.                 // a tad slow but keeps from having to update all objectives in all maps with a name ptr
  1229.                 for( int i = 0; i < gameLocal.num_entities; i++ ) {
  1230. // RAVEN BEGIN
  1231. // jnewquist: Use accessor for static class type 
  1232.                     if ( gameLocal.entities[ i ] && gameLocal.entities[ i ]->IsType( idObjectiveComplete::GetClassType() ) ) {
  1233. // RAVEN END
  1234.                         if ( idStr::Icmp( spawnArgs.GetString( "objectivetitle" ), gameLocal.entities[ i ]->spawnArgs.GetString( "objectivetitle" ) ) == 0 ){
  1235.                             gameLocal.entities[ i ]->spawnArgs.SetBool( "objEnabled", true );
  1236.                             break;
  1237.                         }
  1238.                     }
  1239.                 }
  1240.  
  1241.                 PostEventMS( &EV_GetPlayerPos, 2000 );
  1242. // RAVEN BEGIN
  1243. // mekberg: store triggered time for timed removal.
  1244.                 triggerTime = gameLocal.time;
  1245. // RAVEN END
  1246.             }
  1247.         }
  1248.     }
  1249. }
  1250.  
  1251. /*
  1252. ================
  1253. idObjective::Event_GetPlayerPos
  1254. ================
  1255. */
  1256. void idObjective::Event_GetPlayerPos() {
  1257.     idPlayer *player = gameLocal.GetLocalPlayer();
  1258.     if ( player ) {
  1259.         playerPos = player->GetPhysics()->GetOrigin();
  1260.         PostEventMS( &EV_HideObjective, 100, player );
  1261.     }
  1262. }
  1263.  
  1264. /*
  1265. ================
  1266. idObjective::Event_HideObjective
  1267. ================
  1268. */
  1269. void idObjective::Event_HideObjective(idEntity *e) {
  1270.     idPlayer *player = gameLocal.GetLocalPlayer();
  1271.     if ( player ) {
  1272.         idVec3 v = player->GetPhysics()->GetOrigin() - playerPos;
  1273. // RAVEN BEGIN
  1274. // mekberg: hide time done internally now
  1275.         if ( v.Length() > 64.0f || gameLocal.time > triggerTime + 5000 ) {
  1276. // RAVEN END
  1277.             player->HideObjective ( );
  1278.             PostEventMS( &EV_Remove, 0 );
  1279.         } else {
  1280.             PostEventMS( &EV_HideObjective, 100, player );
  1281.         }
  1282.     }
  1283. }
  1284.  
  1285. /*
  1286. ===============================================================================
  1287.  
  1288.   idMoveableItem
  1289.     
  1290. ===============================================================================
  1291. */
  1292.  
  1293. CLASS_DECLARATION( idItem, idMoveableItem )
  1294.      EVENT( EV_Gib,            idMoveableItem::Event_Gib )
  1295. END_CLASS
  1296.  
  1297. /*
  1298. ================
  1299. idMoveableItem::idMoveableItem
  1300. ================
  1301. */
  1302. idMoveableItem::idMoveableItem() {
  1303. }
  1304.  
  1305. /*
  1306. ================
  1307. idMoveableItem::~idMoveableItem
  1308. ================
  1309. */
  1310. idMoveableItem::~idMoveableItem() {
  1311.     // If this entity has been allocated, but not spawned, the physics object will
  1312.     // not have a self pointer, and will not unregister itself from the entity.
  1313.     SetPhysics( NULL );
  1314. }
  1315.  
  1316. /*
  1317. ================
  1318. idMoveableItem::Save
  1319. ================
  1320. */
  1321. void idMoveableItem::Save( idSaveGame *savefile ) const {
  1322.        savefile->WriteStaticObject( physicsObj );
  1323. }
  1324.  
  1325. /*
  1326. ================
  1327. idMoveableItem::Restore
  1328. ================
  1329. */
  1330. void idMoveableItem::Restore( idRestoreGame *savefile ) {
  1331.     savefile->ReadStaticObject ( physicsObj );
  1332.     RestorePhysics ( &physicsObj );
  1333. }
  1334.  
  1335. /*
  1336. ================
  1337. idMoveableItem::Spawn
  1338. ================
  1339. */
  1340. void idMoveableItem::Spawn( void ) {
  1341.     idTraceModel trm;
  1342.     float density, friction, bouncyness;
  1343.     idStr clipModelName;
  1344.     idBounds bounds;
  1345.  
  1346.     // if the model should be shrinked
  1347.     if ( spawnArgs.GetBool( "clipshrink" ) ) {
  1348.         trm.Shrink( CM_CLIP_EPSILON );
  1349.     }
  1350.  
  1351.     // get rigid body properties
  1352.     spawnArgs.GetFloat( "density", "0.5", density );
  1353.     density = idMath::ClampFloat( 0.001f, 1000.0f, density );
  1354.     spawnArgs.GetFloat( "friction", "0.05", friction );
  1355.     friction = idMath::ClampFloat( 0.0f, 1.0f, friction );
  1356.     spawnArgs.GetFloat( "bouncyness", "0.6", bouncyness );
  1357.     bouncyness = idMath::ClampFloat( 0.0f, 1.0f, bouncyness );
  1358.  
  1359.     // setup the physics
  1360.     physicsObj.SetSelf( this );
  1361.  
  1362. // RAVEN BEGIN
  1363. // mwhitlock: Dynamic memory consolidation
  1364.     RV_PUSH_HEAP_MEM(this);
  1365.     // check if a clip model is set
  1366.     spawnArgs.GetString( "itemclipmodel", "", clipModelName );
  1367.     if ( clipModelName[0] ) {
  1368.         if ( collisionModelManager->TrmFromModel( gameLocal.GetMapName(), clipModelName, trm ) ) {
  1369.             physicsObj.SetClipModel( new idClipModel( trm ), density );
  1370.         } else {
  1371.             // fallback
  1372.             physicsObj.SetClipModel( new idClipModel( GetPhysics()->GetClipModel() ), density );
  1373.         }
  1374.     } else {
  1375.         // fallback
  1376.         physicsObj.SetClipModel( new idClipModel( GetPhysics()->GetClipModel() ), density );
  1377.     }
  1378.  
  1379. // mwhitlock: Dynamic memory consolidation
  1380.     RV_POP_HEAP();
  1381. // RAVEN END
  1382.     physicsObj.SetOrigin( GetPhysics()->GetOrigin() );
  1383.     physicsObj.SetAxis( GetPhysics()->GetAxis() );
  1384.     physicsObj.SetBouncyness( bouncyness );
  1385.     physicsObj.SetFriction( 0.6f, 0.6f, friction );
  1386.     physicsObj.SetGravity( gameLocal.GetGravity() );
  1387.     physicsObj.SetContents( CONTENTS_RENDERMODEL );
  1388.     physicsObj.SetClipMask( MASK_SOLID | CONTENTS_MOVEABLECLIP );
  1389.     SetPhysics( &physicsObj );
  1390.  
  1391. // RAVEN BEGIN
  1392. // mekberg: added
  1393.     if ( spawnArgs.GetBool( "noimpact" ) || spawnArgs.GetBool( "notPushable" ) ) {
  1394.         physicsObj.DisableImpact();
  1395.     }
  1396. // RAVEN END
  1397. }
  1398.  
  1399. /*
  1400. ================
  1401. idMoveableItem::Think
  1402. ================
  1403. */
  1404. void idMoveableItem::Think( void ) {
  1405.     RunPhysics();
  1406.     UpdateTrigger( );
  1407.     Present();
  1408. }
  1409.  
  1410. /*
  1411. ================
  1412. idMoveableItem::DropItem
  1413. ================
  1414. */
  1415. idEntity *idMoveableItem::DropItem( const char *classname, const idVec3 &origin, const idMat3 &axis, const idVec3 &velocity, int activateDelay, int removeDelay ) {
  1416.     idDict args;
  1417.     idEntity *item;
  1418.  
  1419.     args.Set( "classname", classname );
  1420.     args.Set( "dropped", "1" );
  1421.  
  1422.      // we sometimes drop idMoveables here, so set 'nodrop' to 1 so that it doesn't get put on the floor
  1423.      args.Set( "nodrop", "1" ); 
  1424.  
  1425.     if ( activateDelay ) {
  1426.         args.SetBool( "triggerFirst", true );
  1427.     }
  1428.  
  1429.     gameLocal.SpawnEntityDef( args, &item );
  1430.     if ( item ) {
  1431.         // set item position
  1432.         item->GetPhysics()->SetOrigin( origin );
  1433.         item->GetPhysics()->SetAxis( axis );
  1434.         item->GetPhysics()->SetLinearVelocity( velocity );
  1435.          item->UpdateVisuals();
  1436.         if ( activateDelay ) {
  1437.             item->PostEventMS( &EV_Activate, activateDelay, item );
  1438.         }
  1439.         if ( !removeDelay ) {
  1440.             removeDelay = 5 * 60 * 1000;
  1441.         }
  1442.         // always remove a dropped item after 5 minutes in case it dropped to an unreachable location
  1443.         item->PostEventMS( &EV_Remove, removeDelay );
  1444.     }
  1445.  
  1446.      return item;
  1447. }
  1448.  
  1449. /*
  1450. ================
  1451. idMoveableItem::DropItems
  1452.  
  1453.   The entity should have the following key/value pairs set:
  1454.      "def_drop<type>Item"            "item def"
  1455.      "drop<type>ItemJoint"            "joint name"
  1456.      "drop<type>ItemRotation"        "pitch yaw roll"
  1457.      "drop<type>ItemOffset"            "x y z"
  1458.      "skin_drop<type>"                "skin name"
  1459.   To drop multiple items the following key/value pairs can be used:
  1460.      "def_drop<type>Item<X>"            "item def"
  1461.      "drop<type>Item<X>Joint"        "joint name"
  1462.      "drop<type>Item<X>Rotation"        "pitch yaw roll"
  1463.      "drop<type>Item<X>Offset"        "x y z"
  1464.   where <X> is an aribtrary string.
  1465. ================
  1466. */
  1467. void idMoveableItem::DropItems( idAnimatedEntity  *ent, const char *type, idList<idEntity *> *list ) {
  1468.     const idKeyValue *kv;
  1469.     const char *skinName, *c, *jointName;
  1470.     idStr key, key2;
  1471.     idVec3 origin;
  1472.     idMat3 axis;
  1473.     idAngles angles;
  1474.     const idDeclSkin *skin;
  1475.     jointHandle_t joint;
  1476.     idEntity *item;
  1477.  
  1478.     // drop all items
  1479.     kv = ent->spawnArgs.MatchPrefix( va( "def_drop%sItem", type ), NULL );
  1480.     while ( kv ) {
  1481.  
  1482.         c = kv->GetKey().c_str() + kv->GetKey().Length();
  1483.         if ( idStr::Icmp( c - 5, "Joint" ) != 0 && idStr::Icmp( c - 8, "Rotation" ) != 0 ) {
  1484.  
  1485.             key = kv->GetKey().c_str() + 4;
  1486.             key2 = key;
  1487.             key += "Joint";
  1488.             key2 += "Offset";
  1489.             jointName = ent->spawnArgs.GetString( key );
  1490.             joint = ent->GetAnimator()->GetJointHandle( jointName );
  1491.             if ( !ent->GetJointWorldTransform( joint, gameLocal.time, origin, axis ) ) {
  1492.                 gameLocal.Warning( "%s refers to invalid joint '%s' on entity '%s'\n", key.c_str(), jointName, ent->name.c_str() );
  1493.                 origin = ent->GetPhysics()->GetOrigin();
  1494.                 axis = ent->GetPhysics()->GetAxis();
  1495.             }
  1496.             if ( g_dropItemRotation.GetString()[0] ) {
  1497.                 angles.Zero();
  1498.                 sscanf( g_dropItemRotation.GetString(), "%f %f %f", &angles.pitch, &angles.yaw, &angles.roll );
  1499.             } else {
  1500.                 key = kv->GetKey().c_str() + 4;
  1501.                 key += "Rotation";
  1502.                 ent->spawnArgs.GetAngles( key, "0 0 0", angles );
  1503.             }
  1504.             axis *= angles.ToMat3() * axis;
  1505.  
  1506.             origin += ent->spawnArgs.GetVector( key2, "0 0 0" );
  1507.  
  1508.             item = DropItem( kv->GetValue(), origin, axis, vec3_origin, 0, 0 );
  1509.             if ( list && item ) {
  1510.                 list->Append( item );
  1511.             }
  1512.         }
  1513.  
  1514.         kv = ent->spawnArgs.MatchPrefix( va( "def_drop%sItem", type ), kv );
  1515.     }
  1516.  
  1517.     // change the skin to hide all items
  1518.      skinName = ent->spawnArgs.GetString( va( "skin_drop%s", type ) );
  1519.     if ( skinName[0] ) {
  1520.         skin = declManager->FindSkin( skinName );
  1521.         ent->SetSkin( skin );
  1522.     }
  1523. }
  1524.  
  1525. /*
  1526. ======================
  1527. idMoveableItem::WriteToSnapshot
  1528. ======================
  1529. */
  1530. void idMoveableItem::WriteToSnapshot( idBitMsgDelta &msg ) const {
  1531.     physicsObj.WriteToSnapshot( msg );
  1532. }
  1533.  
  1534. /*
  1535. ======================
  1536. idMoveableItem::ReadFromSnapshot
  1537. ======================
  1538. */
  1539. void idMoveableItem::ReadFromSnapshot( const idBitMsgDelta &msg ) {
  1540.     physicsObj.ReadFromSnapshot( msg );
  1541.      if ( msg.HasChanged() ) {
  1542.         UpdateVisuals();
  1543.      }
  1544. }
  1545.  
  1546. /*
  1547. ============
  1548. idMoveableItem::Gib
  1549. ============
  1550. */
  1551. void idMoveableItem::Gib( const idVec3 &dir, const char *damageDefName ) {
  1552.     // remove the entity
  1553.     PostEventMS( &EV_Remove, 0 );
  1554. }
  1555.  
  1556. /*
  1557. ============
  1558. idMoveableItem::Event_Gib
  1559. ============
  1560. */
  1561. void idMoveableItem::Event_Gib( const char *damageDefName ) {
  1562.     Gib( idVec3( 0, 0, 1 ), damageDefName );
  1563. }
  1564.  
  1565. /*
  1566. ===============================================================================
  1567.  
  1568.   idItemRemover
  1569.  
  1570. ===============================================================================
  1571. */
  1572.  
  1573. CLASS_DECLARATION( idEntity, idItemRemover )
  1574.     EVENT( EV_Activate,        idItemRemover::Event_Trigger )
  1575. END_CLASS
  1576.  
  1577. /*
  1578. ================
  1579. idItemRemover::Spawn
  1580. ================
  1581. */
  1582. void idItemRemover::Spawn( void ) {
  1583. }
  1584.  
  1585. /*
  1586. ================
  1587. idItemRemover::RemoveItem
  1588. ================
  1589. */
  1590. void idItemRemover::RemoveItem( idPlayer *player ) {
  1591.     const char *remove;
  1592.     
  1593.     remove = spawnArgs.GetString( "remove" );
  1594.     player->RemoveInventoryItem( remove );
  1595. }
  1596.  
  1597. /*
  1598. ================
  1599. idItemRemover::Event_Trigger
  1600. ================
  1601. */
  1602. void idItemRemover::Event_Trigger( idEntity *activator ) {
  1603. // RAVEN BEGIN
  1604. // jnewquist: Use accessor for static class type 
  1605.     if ( activator->IsType( idPlayer::GetClassType() ) ) {
  1606. // RAVEN END
  1607.         RemoveItem( static_cast<idPlayer *>(activator) );
  1608.     }
  1609. }
  1610.  
  1611. /*
  1612. ===============================================================================
  1613.  
  1614.   idObjectiveComplete
  1615.  
  1616. ===============================================================================
  1617. */
  1618.  
  1619. CLASS_DECLARATION( idItemRemover, idObjectiveComplete )
  1620.     EVENT( EV_Activate,            idObjectiveComplete::Event_Trigger )
  1621.     EVENT( EV_HideObjective,    idObjectiveComplete::Event_HideObjective )
  1622.     EVENT( EV_GetPlayerPos,        idObjectiveComplete::Event_GetPlayerPos )
  1623. END_CLASS
  1624.  
  1625. /*
  1626. ================
  1627. idObjectiveComplete::idObjectiveComplete
  1628. ================
  1629. */
  1630. idObjectiveComplete::idObjectiveComplete() {
  1631.     playerPos.Zero();
  1632.  
  1633. // RAVEN BEGIN
  1634. // mekberg: store triggered time for timed removal.
  1635.     triggerTime = 0;
  1636. // RAVEN END
  1637. }
  1638.  
  1639. /*
  1640. ================
  1641. idObjectiveComplete::Save
  1642. ================
  1643. */
  1644. void idObjectiveComplete::Save( idSaveGame *savefile ) const {
  1645.     savefile->WriteVec3( playerPos );
  1646. }
  1647.  
  1648. /*
  1649. ================
  1650. idObjectiveComplete::Restore
  1651. ================
  1652. */
  1653. void idObjectiveComplete::Restore( idRestoreGame *savefile ) {
  1654.     savefile->ReadVec3( playerPos );
  1655. }
  1656.  
  1657. /*
  1658. ================
  1659. idObjectiveComplete::Spawn
  1660. ================
  1661. */
  1662. void idObjectiveComplete::Spawn( void ) {
  1663.      spawnArgs.SetBool( "objEnabled", false );
  1664.     Hide();
  1665. }
  1666.  
  1667. /*
  1668. ================
  1669. idObjectiveComplete::Event_Trigger
  1670. ================
  1671. */
  1672. void idObjectiveComplete::Event_Trigger( idEntity *activator ) {
  1673.      if ( !spawnArgs.GetBool( "objEnabled" ) ) {
  1674.          return;
  1675.      }
  1676.     idPlayer *player = gameLocal.GetLocalPlayer();
  1677.     if ( player ) {
  1678.         RemoveItem( player );
  1679.  
  1680.         if ( spawnArgs.GetString( "inv_objective", NULL ) ) {
  1681. // RAVEN BEGIN
  1682. // abahr: changed player->hud to player->GetHud so if in a vehicle we update that hud
  1683. // twhitaker: moved objective system to it's own hud, to solve vehicle hud issues.
  1684.              if ( player->GetObjectiveHud() ) {
  1685.                 player->GetObjectiveHud()->SetStateString( "objective", "2" );
  1686.                 player->GetObjectiveHud()->SetStateString( "objectivetext", common->GetLocalizedString( spawnArgs.GetString( "objectivetext" ) ) );
  1687.                 player->GetObjectiveHud()->SetStateString( "objectivetitle", common->GetLocalizedString( spawnArgs.GetString( "objectivetitle" ) ) );
  1688. // RAVEN END
  1689.                 player->CompleteObjective( spawnArgs.GetString( "objectivetitle" ) );
  1690.                 PostEventMS( &EV_GetPlayerPos, 2000 );
  1691. // RAVEN BEGIN
  1692. // mekberg: store triggered time for timed removal.
  1693.                 triggerTime = gameLocal.time;
  1694. // RAVEN END
  1695.             }
  1696.         }
  1697.     }
  1698. }
  1699.  
  1700. /*
  1701. ================
  1702. idObjectiveComplete::Event_GetPlayerPos
  1703. ================
  1704. */
  1705. void idObjectiveComplete::Event_GetPlayerPos() {
  1706.     idPlayer *player = gameLocal.GetLocalPlayer();
  1707.     if ( player ) {
  1708.         playerPos = player->GetPhysics()->GetOrigin();
  1709.         PostEventMS( &EV_HideObjective, 100, player );
  1710.     }
  1711. }
  1712.  
  1713. /*
  1714. ================
  1715. idObjectiveComplete::Event_HideObjective
  1716. ================
  1717. */
  1718. void idObjectiveComplete::Event_HideObjective( idEntity *e ) {
  1719.     idPlayer *player = gameLocal.GetLocalPlayer();
  1720.     if ( player && player->GetObjectiveHud() ) {
  1721.         idVec3 v = player->GetPhysics()->GetOrigin();
  1722.         v -= playerPos;
  1723. // RAVEN BEGIN
  1724. // mekberg: hide time done internally now
  1725.         if ( v.Length() > 64.0f || gameLocal.time > triggerTime + 5000 ) {
  1726. // RAVEN END
  1727.             player->HideObjective ( );
  1728.             PostEventMS( &EV_Remove, 0 );
  1729.         } else {
  1730.             PostEventMS( &EV_HideObjective, 100, player );
  1731.         }
  1732.     }
  1733. }
  1734.  
  1735. /*
  1736. ===============================================================================
  1737.  
  1738.   rvObjectiveFailed
  1739.  
  1740. ===============================================================================
  1741. */
  1742. CLASS_DECLARATION( idItemRemover, rvObjectiveFailed )
  1743.     EVENT( EV_Activate,            rvObjectiveFailed::Event_Trigger )
  1744. END_CLASS
  1745.  
  1746. rvObjectiveFailed::rvObjectiveFailed ( void ) {
  1747. }
  1748.  
  1749. /*
  1750. ================
  1751. rvObjectiveFailed::Event_Trigger
  1752. ================
  1753. */
  1754. void rvObjectiveFailed::Event_Trigger( idEntity *activator ) {
  1755.     idPlayer *player = gameLocal.GetLocalPlayer();
  1756.     if ( !player || !player->GetObjectiveHud() ) {
  1757.         return;
  1758.     }
  1759.     if ( !spawnArgs.GetString( "inv_objective", NULL ) ) {
  1760.         return;
  1761.     }    
  1762.  
  1763.     player->GetObjectiveHud()->SetStateString( "objective", "2" );
  1764.     player->GetObjectiveHud()->SetStateString( "objectivetext", common->GetLocalizedString( spawnArgs.GetString( "objectivetext" ) ) );
  1765.     player->GetObjectiveHud()->SetStateString( "objectivetitle", common->GetLocalizedString( spawnArgs.GetString( "objectivetitle" ) ) );
  1766.     player->FailObjective( spawnArgs.GetString( "objectivetitle" ) );
  1767. }
  1768.  
  1769. /*
  1770. ===============================================================================
  1771.  
  1772.   rvItemCTFFlag
  1773.  
  1774. ===============================================================================
  1775. */
  1776.  
  1777. const idEventDef EV_ResetFlag ( "<resetflag>" );
  1778. const idEventDef EV_LinkTrigger( "<linktrigger>" );
  1779. CLASS_DECLARATION( idItem, rvItemCTFFlag )
  1780.     EVENT( EV_ResetFlag,        rvItemCTFFlag::Event_ResetFlag )
  1781.     EVENT( EV_LinkTrigger,        rvItemCTFFlag::Event_LinkTrigger )
  1782. END_CLASS
  1783.  
  1784. /*
  1785. ================
  1786. rvItemCTFFlag::rvItemCTFFlag
  1787. ================
  1788. */
  1789. rvItemCTFFlag::rvItemCTFFlag() {
  1790. }
  1791.  
  1792.  
  1793. /*
  1794. ================
  1795. rvItemCTFFlag::Spawn
  1796. ================
  1797. */
  1798. void rvItemCTFFlag::Spawn () {
  1799. /* rjohnson: I fixed the crash so we don't need to remove them...
  1800.     //don't spawn outside of CTF games
  1801.     if( (gameLocal.gameType != GAME_CTF) && (gameLocal.gameType != GAME_1F_CTF) &&
  1802.         (gameLocal.gameType != GAME_ARENA_CTF) && (gameLocal.gameType != GAME_ARENA_1F_CTF) ){
  1803.         //don't spawn!
  1804.         gameLocal.Error("Flag spawn on in non-CTF gametype.");
  1805.         PostEventMS ( &EV_Remove, 0 );
  1806.         return;
  1807.     }
  1808. */
  1809.     spawnArgs.GetBool ( "dropped", "0", dropped );
  1810.     spawnArgs.GetInt ( "team", "0", team );
  1811.  
  1812.     bool reset = false;
  1813.     spawnArgs.GetBool ( "reset", "0", reset );
  1814.  
  1815.     switch ( team ) {
  1816.         case TEAM_MARINE: {
  1817.             powerup = POWERUP_CTF_MARINEFLAG;    
  1818.             break;
  1819.         }
  1820.         case TEAM_STROGG: {
  1821.             powerup = POWERUP_CTF_STROGGFLAG;    
  1822.             break;
  1823.         }
  1824.         case TEAM_MAX: {
  1825.             powerup = POWERUP_CTF_ONEFLAG;
  1826.             break;
  1827.         }
  1828.         default:
  1829.             gameLocal.Warning ( "Unknown ctf flag team '%d' on entity '%s'", team, name.c_str() );
  1830.             PostEventMS ( &EV_Remove, 0 );
  1831.             return;
  1832.     }
  1833.     
  1834.     if ( dropped ) {
  1835.         if ( !gameLocal.isClient ) {
  1836.             ((rvCTFGameState*)gameLocal.mpGame.GetGameState())->SetFlagState( team, FS_DROPPED );
  1837.         }    
  1838.         if ( reset ) {
  1839.             PostEventSec( &EV_ResetFlag, 1 );
  1840.         } else {
  1841.             PostEventSec( &EV_ResetFlag, 30 );
  1842.         }
  1843.  
  1844.         // Let powerups settle for a frame before allowing them to be picked up - we need to
  1845.         // make sure we hit the dropped state for VO, etc to work properly
  1846.         trigger->SetContents( 0 );
  1847.         PostEventSec( &EV_LinkTrigger, 0 );
  1848.     } else {
  1849.         if ( !gameLocal.isClient ) {
  1850.             ((rvCTFGameState*)gameLocal.mpGame.GetGameState())->SetFlagState( team, FS_AT_BASE );
  1851.         }    
  1852.     }
  1853.  
  1854.     GetPhysics( )->SetClipMask( GetPhysics( )->GetClipMask( ) | CONTENTS_ITEMCLIP );
  1855.  
  1856.     spin = false;
  1857. }
  1858.  
  1859. /*
  1860. ================
  1861. rvItemCTFFlag::Event_LinkTrigger
  1862. ================
  1863. */
  1864. void rvItemCTFFlag::Event_LinkTrigger( void ) {
  1865.     trigger->SetContents( CONTENTS_TRIGGER );
  1866. }
  1867.  
  1868. /*
  1869. ================
  1870. rvItemCTFFlag::GiveToPlayer
  1871. ================
  1872. */
  1873. bool rvItemCTFFlag::GiveToPlayer( idPlayer* player ) {
  1874.     if ( !gameLocal.IsMultiplayer() ) {
  1875.         return false;
  1876.     }
  1877.  
  1878.     if ( player->spectating || ((gameLocal.mpGame.GetGameState())->GetMPGameState() != GAMEON && (gameLocal.mpGame.GetGameState())->GetMPGameState() != SUDDENDEATH && !cvarSystem->GetCVarBool( "g_testCTF" )) ) {
  1879.         return false;
  1880.     }
  1881.  
  1882.     int teamPowerup;
  1883.     int enemyPowerup;
  1884.  
  1885.     bool canPickup = ( team == player->team );
  1886.     
  1887.     switch ( player->team ) {
  1888.         default:
  1889.         case TEAM_MARINE:
  1890.             teamPowerup  = POWERUP_CTF_MARINEFLAG;
  1891.             enemyPowerup = POWERUP_CTF_STROGGFLAG;
  1892.             break;
  1893.             
  1894.         case TEAM_STROGG:
  1895.             teamPowerup  = POWERUP_CTF_STROGGFLAG;
  1896.             enemyPowerup = POWERUP_CTF_MARINEFLAG;
  1897.             break;
  1898.     }
  1899.  
  1900.     if( gameLocal.gameType == GAME_1F_CTF || gameLocal.gameType == GAME_ARENA_1F_CTF ) {
  1901.         // in one flag CTF, we score touching the enemy's flag
  1902.         canPickup = ( team == gameLocal.mpGame.OpposingTeam( player->team ) );
  1903.         enemyPowerup = POWERUP_CTF_ONEFLAG;
  1904.     }
  1905.     
  1906.     // If the player runs over their own flag the only thing they
  1907.     // can do is score or return it.
  1908.  
  1909.     // when the player touches the one flag, he always gets it
  1910.     if ( canPickup ) {
  1911.         // If the flag was dropped, return it        
  1912.         if ( dropped ) {
  1913.             gameLocal.mpGame.AddPlayerTeamScore( player, 2 );
  1914.             statManager->FlagReturned( player );
  1915.             ResetFlag ( teamPowerup );
  1916.         } else if ( player->PowerUpActive ( enemyPowerup ) ) {
  1917.             // If they have the enemy flag then they score
  1918.             if ( !gameLocal.mpGame.CanCapture ( player->team ) ) {
  1919.                 return false;
  1920.             }
  1921.             
  1922.             ResetFlag( enemyPowerup );
  1923.             
  1924.             gameLocal.mpGame.FlagCaptured( player );
  1925.         }
  1926.         return false;
  1927.     } 
  1928.  
  1929.     // only pickup one flag in arena CTF
  1930.     if( ( gameLocal.gameType == GAME_1F_CTF || gameLocal.gameType == GAME_ARENA_1F_CTF ) && team != TEAM_MAX ) {
  1931.         return false;
  1932.     }
  1933.  
  1934.     player->GivePowerUp( enemyPowerup, -1 );
  1935.     return true;
  1936. }
  1937.  
  1938. /*
  1939. ================
  1940. rvItemCTFFlag::Pickup
  1941. ================
  1942. */
  1943. bool rvItemCTFFlag::Pickup( idPlayer *player ) {
  1944.     
  1945.     if ( !GiveToPlayer( player ) ) {
  1946.         return false;
  1947.     }
  1948.  
  1949.     //    ServerSendEvent( EVENT_PICKUP, NULL, false, -1 );
  1950.     if ( gameLocal.isServer ) {
  1951.         SendPickupMsg( player->entityNumber );
  1952.     }
  1953.  
  1954.     // Check for global acquire sounds in multiplayer
  1955.     if ( gameLocal.isMultiplayer && spawnArgs.GetBool( "globalAcquireSound" ) ) {
  1956.         gameLocal.mpGame.PlayGlobalItemAcquireSound( entityDefNumber );
  1957.     } else {
  1958.         StartSound( "snd_acquire", SND_CHANNEL_ITEM, 0, false, NULL );
  1959.     }
  1960.  
  1961.     // trigger our targets
  1962.     ActivateTargets( player );
  1963.  
  1964.     // clear our contents so the object isn't picked up twice
  1965.     GetPhysics()->SetContents( 0 );
  1966.  
  1967.     // hide the model
  1968.     Hide();
  1969.  
  1970.     gameLocal.mpGame.AddPlayerTeamScore( player, 1 );
  1971.  
  1972.     if( gameLocal.gameType == GAME_CTF || gameLocal.gameType == GAME_ARENA_CTF ) { 
  1973.         ((rvCTFGameState*)gameLocal.mpGame.GetGameState())->SetFlagState( team, FS_TAKEN );
  1974.     } else if( gameLocal.gameType == GAME_1F_CTF || gameLocal.gameType == GAME_ARENA_1F_CTF ) {
  1975.         ((rvCTFGameState*)gameLocal.mpGame.GetGameState())->SetFlagState( team, (player->team == TEAM_MARINE ? FS_TAKEN_MARINE : FS_TAKEN_STROGG) );
  1976.     }
  1977.     
  1978.     ((rvCTFGameState*)gameLocal.mpGame.GetGameState())->SetFlagCarrier( team, player->entityNumber );
  1979.  
  1980.     if ( spawnArgs.GetBool( "dropped" ) ) {
  1981.         PostEventMS( &EV_Remove, 0 );
  1982.     }
  1983.  
  1984.     BecomeInactive( TH_THINK );
  1985.     
  1986.     return true;
  1987. }
  1988.  
  1989. /*
  1990. ================
  1991. rvItemCTFFlag::ResetFlag
  1992. ================
  1993. */
  1994. void rvItemCTFFlag::ResetFlag( int powerup ) {
  1995.     idEntity* ent;
  1996.     for ( ent = gameLocal.spawnedEntities.Next(); ent != NULL; ent = ent->spawnNode.Next() ) {
  1997.         // Make sure no players have the flag anymore
  1998. // RAVEN BEGIN
  1999. // jnewquist: Use accessor for static class type 
  2000.         if ( ent->IsType ( idPlayer::GetClassType() ) ) {
  2001. // RAVEN END
  2002.             static_cast<idPlayer*>(ent)->ClearPowerup ( powerup );
  2003.             continue;
  2004.         }
  2005.     
  2006.         // If its not a CTF flag item then skip it
  2007.         if ( !ent->IsType( rvItemCTFFlag::Type ) ) {
  2008.             continue;            
  2009.         }
  2010.         
  2011.         // Make sure its the right type first
  2012.         rvItemCTFFlag* flag;
  2013.         flag = static_cast<rvItemCTFFlag*>(ent);
  2014.         if ( flag->powerup != powerup ) {
  2015.             continue;
  2016.         }
  2017.         
  2018.         if ( flag->dropped ) {            
  2019.             flag->PostEventMS( &EV_Remove, 0 );
  2020.         } else {
  2021.             flag->PostEventMS( &EV_RespawnItem, 0 );            
  2022.         }
  2023.     }
  2024.  
  2025.     if ( !gameLocal.isClient ) {
  2026.         int team = -1;
  2027.         if ( powerup == POWERUP_CTF_MARINEFLAG ) {
  2028.             team = TEAM_MARINE;
  2029.         } else if ( powerup == POWERUP_CTF_STROGGFLAG ) {
  2030.             team = TEAM_STROGG;
  2031.         } else if ( powerup == POWERUP_CTF_ONEFLAG ) {
  2032.             team = TEAM_MAX;
  2033.         }
  2034.         
  2035.         ((rvCTFGameState*)gameLocal.mpGame.GetGameState())->SetFlagState( team, FS_AT_BASE );
  2036.     }    
  2037.  
  2038. }
  2039.   
  2040. /*
  2041. ================
  2042. rvItemCTFFlag::Event_ResetFlag
  2043. ================
  2044. */
  2045. void rvItemCTFFlag::Event_ResetFlag( void ) {
  2046.     ResetFlag( powerup );
  2047. }
  2048.  
  2049. void rvItemCTFFlag::Think( void ) {
  2050.     idItem::Think();
  2051. }
  2052.  
  2053. /*
  2054. ================
  2055. rvItemCTFFlag::Collide
  2056. ================
  2057. */
  2058. bool rvItemCTFFlag::Collide( const trace_t &collision, const idVec3 &velocity ) {
  2059.     if ( collision.c.contents & CONTENTS_ITEMCLIP ) {
  2060.         ResetFlag( powerup );
  2061.     }
  2062.     return false;
  2063. }
  2064. // RAVEN END
  2065.