//---------------------------------------------------------------- // CTF.cpp // // Copyright 2002-2004 Raven Software //---------------------------------------------------------------- #include "../../idlib/precompiled.h" #pragma hdrstop #include "CTF.h" /* =============================================================================== rvCTF_AssaultPoint =============================================================================== */ CLASS_DECLARATION( idEntity, rvCTF_AssaultPoint ) EVENT( EV_PostSpawn, rvCTF_AssaultPoint::Event_InitializeLinks ) EVENT( EV_Touch, rvCTF_AssaultPoint::Event_Touch ) END_CLASS rvCTF_AssaultPoint::rvCTF_AssaultPoint() { trigger = NULL; linked = false; owner = AS_NEUTRAL; } rvCTF_AssaultPoint::~rvCTF_AssaultPoint() { delete trigger; trigger = NULL; } /* ================ rvCTF_AssaultPoint::Spawn ================ */ void rvCTF_AssaultPoint::Spawn( void ) { PostEventMS( &EV_PostSpawn, 0 ); } /* ================ rvCTF_AssaultPoint::InitializeLinks ================ */ void rvCTF_AssaultPoint::Event_InitializeLinks( void ) { if( linked ) { return; } // pull in our targets toStrogg = gameLocal.FindEntity( spawnArgs.GetString( "targetStroggAP" ) ); toMarine = gameLocal.FindEntity( spawnArgs.GetString( "targetMarineAP" ) ); ResetIndices(); trigger = new idClipModel( idTraceModel( idBounds( vec3_origin ).Expand( 16.0f ) ) ); // RAVEN BEGIN // ddynerman: multiple clip worlds trigger->Link( this, 0, GetPhysics()->GetOrigin(), GetPhysics()->GetAxis() ); // RAVEN END trigger->SetContents ( CONTENTS_TRIGGER ); GetPhysics()->SetClipModel( NULL, 1.0f ); linked = true; } /* ================ rvCTF_AssaultPoint::ResetIndices ================ */ void rvCTF_AssaultPoint::ResetIndices( void ) { // find the closest AP to the marine flag, which is index 0, then work towards strogg flag if ( !toMarine || !toMarine->IsType ( rvItemCTFFlag::GetClassType() ) ) { return; } idEntityPtr ptr; ptr = this; gameLocal.mpGame.assaultPoints.Append( ptr ); int assignIndices = 0; index = assignIndices++; rvCTF_AssaultPoint* ap = this; while( !ap->toStrogg->IsType ( rvItemCTFFlag::GetClassType() ) ) { if( !ap->toStrogg->IsType ( rvCTF_AssaultPoint::GetClassType() ) ) { gameLocal.Error( "rvCTF_AssaultPoint::ResetIndices() - non assault point targeted in assault point chain" ); } ap = static_cast(ap->toStrogg.GetEntity()); ap->index = assignIndices++; ptr = ap; gameLocal.mpGame.assaultPoints.Append( ptr ); if ( !ap->linked ) { ap->Event_InitializeLinks(); } if( !ap->toStrogg ) { gameLocal.Error( "rvCTF_AssaultPoint::ResetIndices() - break in assault point chain" ); } } } /* ================ rvCTF_AssaultPoint::Event_Activate ================ */ void rvCTF_AssaultPoint::Event_Touch( idEntity *activator, trace_t *trace ) { if( !activator->IsType( idPlayer::GetClassType() ) || ((gameLocal.mpGame.GetGameState())->GetMPGameState() != GAMEON && !cvarSystem->GetCVarBool( "g_testCTF" )) ) { return; } idPlayer* player = static_cast(activator); int oldOwner = owner; if ( owner == player->team ) return; int enemyPowerup = -1; int friendlyPowerup = -1; if ( owner == TEAM_MARINE ) { friendlyPowerup = POWERUP_CTF_STROGGFLAG; enemyPowerup = POWERUP_CTF_MARINEFLAG; } else if ( owner == TEAM_STROGG ) { friendlyPowerup = POWERUP_CTF_MARINEFLAG; enemyPowerup = POWERUP_CTF_STROGGFLAG; } else { // neutral assault point if ( player->team == TEAM_MARINE ) { friendlyPowerup = POWERUP_CTF_MARINEFLAG; enemyPowerup = POWERUP_CTF_STROGGFLAG; } else { friendlyPowerup = POWERUP_CTF_STROGGFLAG; enemyPowerup = POWERUP_CTF_MARINEFLAG; } } if ( !player->PowerUpActive ( enemyPowerup ) ) { return; } switch( player->team ) { case TEAM_MARINE: { if( !toMarine || owner == TEAM_MARINE ) { break; } if( toMarine->IsType( rvItemCTFFlag::GetClassType() ) ) { owner = TEAM_MARINE; gameLocal.Printf("Assault point %s captured by marines!\n", name.c_str()); } else if( toMarine->IsType( rvCTF_AssaultPoint::GetClassType() ) ) { if( static_cast(toMarine.GetEntity())->owner == TEAM_MARINE ) { owner = TEAM_MARINE; gameLocal.Printf("Assault point %s captured by marines!\n", name.c_str()); } } break; } case TEAM_STROGG: { if( !toStrogg || owner == TEAM_STROGG ) { break; } if( toStrogg->IsType( rvItemCTFFlag::GetClassType() ) ) { owner = TEAM_STROGG; gameLocal.Printf("Assault point %s captured by strogg!\n", name.c_str()); } else if( toStrogg->IsType( rvCTF_AssaultPoint::GetClassType() ) ) { if( static_cast(toStrogg.GetEntity())->owner == TEAM_STROGG ) { owner = TEAM_STROGG; gameLocal.Printf("Assault point %s captured by strogg!\n", name.c_str()); } } break; } } if( oldOwner != owner ) { // we switched hands, reset forward spawns gameLocal.ClearForwardSpawns(); if( oldOwner == TEAM_MARINE ) { if( static_cast(toMarine.GetEntity())->IsType( rvCTF_AssaultPoint::Type ) ) { static_cast(toMarine.GetEntity())->ResetSpawns( oldOwner ); } } else if( oldOwner == TEAM_STROGG ) { if( static_cast(toStrogg.GetEntity())->IsType( rvCTF_AssaultPoint::Type ) ) { static_cast(toStrogg.GetEntity())->ResetSpawns( oldOwner ); } } rvItemCTFFlag::ResetFlag ( enemyPowerup ); gameLocal.mpGame.AddPlayerTeamScore( player, 2 ); ((rvCTFGameState*)gameLocal.mpGame.GetGameState())->SetAPOwner( index, owner ); ActivateTargets( this ); SetOwnerColor (); } } /* ================ rvCTF_AssaultPoint::ResetSpawns ================ */ void rvCTF_AssaultPoint::ResetSpawns( int team ) { // check to see if team can spawn at me, if not pass down if( owner == team ) { ActivateTargets( this ); } else { if( team == TEAM_MARINE ) { if( static_cast(toMarine.GetEntity())->IsType( rvCTF_AssaultPoint::Type ) ) { static_cast(toMarine.GetEntity())->ResetSpawns( team ); } } else if( team == TEAM_STROGG ) { if( static_cast(toStrogg.GetEntity())->IsType( rvCTF_AssaultPoint::Type ) ) { static_cast(toStrogg.GetEntity())->ResetSpawns( team ); } } } } void rvCTF_AssaultPoint::SetOwner ( int newOwner ) { if ( !gameLocal.isClient ) { // server should set owner via EVENT_ACTIVATE, not here return; } owner = newOwner; SetOwnerColor (); } void rvCTF_AssaultPoint::Reset ( void ) { owner = AS_NEUTRAL; SetOwnerColor(); } /* ================ rvCTF_AssaultPoint::ChangeColor ================ */ void rvCTF_AssaultPoint::SetOwnerColor ( void ) { const idDeclSkin* skin = NULL; if( owner == TEAM_MARINE ) { skin = declManager->FindSkin( "skins/ddynerman/green_glow", false ); } else if ( owner == TEAM_STROGG ) { skin = declManager->FindSkin( "skins/ddynerman/orange_glow", false ); } else { skin = declManager->FindSkin( "skins/ddynerman/white", false ); } if ( skin ) { SetSkin( skin ); } } /* =============================================================================== rvCTFAssaultPlayerStart =============================================================================== */ CLASS_DECLARATION( idPlayerStart, rvCTFAssaultPlayerStart ) EVENT( EV_Activate, rvCTFAssaultPlayerStart::Event_Activate ) END_CLASS /* ================ rvCTFAssaultPlayerStart::Spawn ================ */ void rvCTFAssaultPlayerStart::Spawn(void) { if( !idStr::Icmp( spawnArgs.GetString( "team" ), "marine" ) ) { team = TEAM_MARINE; } else if( !idStr::Icmp( spawnArgs.GetString( "team" ), "strogg" ) ) { team = TEAM_STROGG; } else { gameLocal.Error("rvCTFAssaultPlayerStart::Spawn() - unknown team\n"); team = -1; } } void rvCTFAssaultPlayerStart::Event_Activate( idEntity *activator ) { if ( !activator->IsType( rvCTF_AssaultPoint::GetClassType() ) ) { gameLocal.Warning( "rvCTFAssaultPlayerStart::Event_Activate() - was activated by something other than an assault point\n" ); return; } rvCTF_AssaultPoint* ap = static_cast(activator); if( ap->GetOwner() == team ) { gameLocal.UpdateForwardSpawns( this, team ); } }