sqwarmed/sdk_src/game/server/swarm/asw_mission_manager.cpp

315 lines
7.9 KiB
C++

#include "cbase.h"
#include "asw_objective.h"
#include "asw_game_resource.h"
#include "asw_mission_manager.h"
#include "asw_gamerules.h"
#include "asw_marine_resource.h"
#include "asw_marine_speech.h"
#include "asw_marine.h"
#include "asw_objective_escape.h"
#include "game_timescale_shared.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
LINK_ENTITY_TO_CLASS( asw_mission_manager, CASW_Mission_Manager );
BEGIN_DATADESC( CASW_Mission_Manager )
END_DATADESC()
ConVar asw_last_marine_dead_delay( "asw_last_marine_dead_delay", "0.6f", FCVAR_CHEAT, "How long to wait after the last marine has died before failing the mission" );
CASW_Mission_Manager::CASW_Mission_Manager()
{
m_bDoneLeavingChatter = false;
m_flLastMarineDeathTime = 0.0f;
m_bAllMarinesDead = false;
}
CASW_Mission_Manager::~CASW_Mission_Manager()
{
}
void CASW_Mission_Manager::Spawn()
{
BaseClass::Spawn();
SetThink( &CASW_Mission_Manager::ManagerThink );
SetNextThink( gpGlobals->curtime + 1.0f );
}
void CASW_Mission_Manager::ManagerThink()
{
if ( m_bAllMarinesDead ) // once all marines are dead, we need to check for mission complete periodically to see if the marine_dead_delay time has passed
{
CheckMissionComplete();
}
SetNextThink( gpGlobals->curtime + 1.0f );
}
bool CASW_Mission_Manager::CheckMissionComplete()
{
bool bFailed = false;
bool bSuccess = true;
bool bAtLeastOneObjective = false;
// notify all objectives about this event
if ( !ASWGameResource() )
return false;
int iIncomplete = 0;
int iNumObjectives = 0;
bool bEscapeIncomplete = false;
for (int i=0;i<ASW_MAX_OBJECTIVES;i++)
{
CASW_Objective* pObjective = ASWGameResource()->GetObjective(i);
if (pObjective)
{
bAtLeastOneObjective = true;
iNumObjectives++;
if (!pObjective->IsObjectiveComplete() && !pObjective->IsObjectiveOptional())
{
bSuccess = false;
iIncomplete++;
if (iIncomplete == 1 && !m_bDoneLeavingChatter)
{
CASW_Objective_Escape *pEscape = dynamic_cast<CASW_Objective_Escape*>(pObjective);
if (pEscape)
bEscapeIncomplete = true;
}
}
if (pObjective->IsObjectiveFailed())
{
bFailed = true;
}
}
}
m_bAllMarinesDead = AllMarinesDead();
if ( m_bAllMarinesDead && ( gpGlobals->curtime > m_flLastMarineDeathTime + asw_last_marine_dead_delay.GetFloat() || GameTimescale()->GetCurrentTimescale() < 1.0f ) )
{
bFailed = true;
}
if (bSuccess && bAtLeastOneObjective)
{
MissionSuccess();
return true;
}
else if (bFailed)
{
MissionFail();
return true;
}
else
{
if (bEscapeIncomplete && iIncomplete)
{
// make a marine do the 'time to leave' speech
if ( ASWGameResource() )
{
CASW_Game_Resource *pGameResource = ASWGameResource();
// count how many live marines we have
int iNearby = 0;
for (int i=0;i<pGameResource->GetMaxMarineResources();i++)
{
CASW_Marine_Resource *pMR = pGameResource->GetMarineResource(i);
CASW_Marine *pMarine = pMR ? pMR->GetMarineEntity() : NULL;
if (pMarine && pMarine->GetHealth() > 0)
iNearby++;
}
int iChatter = random->RandomInt(0, iNearby-1);
for (int i=0;i<pGameResource->GetMaxMarineResources();i++)
{
CASW_Marine_Resource *pMR = pGameResource->GetMarineResource(i);
CASW_Marine *pMarine = pMR ? pMR->GetMarineEntity() : NULL;
if (pMarine && pMarine->GetHealth() > 0)
{
if (iChatter <= 0)
{
pMarine->GetMarineSpeech()->QueueChatter(CHATTER_TIME_TO_LEAVE, gpGlobals->curtime + 3.0f, gpGlobals->curtime + 6.0f);
break;
}
iChatter--;
}
}
}
m_bDoneLeavingChatter = true;
}
}
return false;
}
void CASW_Mission_Manager::AlienKilled(CBaseEntity* pAlien)
{
// notify all objectives about this event
if ( !ASWGameResource() )
return;
for (int i=0;i<ASW_MAX_OBJECTIVES;i++)
{
CASW_Objective* pObjective = ASWGameResource()->GetObjective(i);
if (pObjective)
pObjective->AlienKilled(pAlien);
}
}
void CASW_Mission_Manager::MarineKilled(CASW_Marine* pMarine)
{
m_flLastMarineDeathTime = gpGlobals->curtime;
// notify all objectives about this event
if ( !ASWGameResource() )
return;
for (int i=0;i<ASW_MAX_OBJECTIVES;i++)
{
CASW_Objective* pObjective = ASWGameResource()->GetObjective(i);
if (pObjective)
pObjective->MarineKilled(pMarine);
}
// check if our mission is over (from all the marines dying)
CheckMissionComplete();
}
void CASW_Mission_Manager::EggKilled(CASW_Egg* pEgg)
{
// notify all objectives about this event
if ( !ASWGameResource() )
return;
for (int i=0;i<ASW_MAX_OBJECTIVES;i++)
{
CASW_Objective* pObjective = ASWGameResource()->GetObjective(i);
if (pObjective)
pObjective->EggKilled(pEgg);
}
}
void CASW_Mission_Manager::GooKilled(CASW_Alien_Goo* pGoo)
{
// notify all objectives about this event
if ( !ASWGameResource() )
return;
//Msg("Mission manager sees Alien Goo killed!\n");
for (int i=0;i<ASW_MAX_OBJECTIVES;i++)
{
CASW_Objective* pObjective = ASWGameResource()->GetObjective(i);
if (pObjective)
pObjective->GooKilled(pGoo);
}
}
void CASW_Mission_Manager::MissionStarted(void)
{
// notify all objectives about this event
if ( !ASWGameResource() )
return;
for (int i=0;i<ASW_MAX_OBJECTIVES;i++)
{
CASW_Objective* pObjective = ASWGameResource()->GetObjective(i);
if (pObjective)
pObjective->MissionStarted();
}
}
// marines screwed up
void CASW_Mission_Manager::MissionFail(void)
{
// notify all objectives about this event
if (!ASWGameRules() || !ASWGameResource()
|| ASWGameRules()->GetGameState() == ASW_GS_DEBRIEF)
return;
for (int i=0;i<ASW_MAX_OBJECTIVES;i++)
{
CASW_Objective* pObjective = ASWGameResource()->GetObjective(i);
if (pObjective)
pObjective->MissionFail();
}
// tell the game rules the mission is over
ASWGameRules()->MissionComplete(false);
}
// marines have succeeded in finishing the mission! yay
void CASW_Mission_Manager::MissionSuccess(void)
{
// notify all objectives about this event
if (!ASWGameRules() || !ASWGameResource()
|| ASWGameRules()->GetGameState() == ASW_GS_DEBRIEF)
return;
for (int i=0;i<ASW_MAX_OBJECTIVES;i++)
{
CASW_Objective* pObjective = ASWGameResource()->GetObjective(i);
if (pObjective)
pObjective->MissionSuccess();
}
// tell the game rules the mission is over
ASWGameRules()->MissionComplete(true);
}
bool CASW_Mission_Manager::AllMarinesDead()
{
if (!ASWGameRules() || !ASWGameResource())
return false;
// can't be all dead if we haven't left briefing yet!
if (ASWGameRules()->GetGameState() < ASW_GS_INGAME)
return false;
int iMax = ASWGameResource()->GetMaxMarineResources();
for (int i=0;i<iMax;i++)
{
CASW_Marine_Resource *pMarineResource = ASWGameResource()->GetMarineResource(i);
if (pMarineResource && pMarineResource->GetHealthPercent() > 0)
{
return false; // we have a live marine, so they're not all dead
}
}
return true; // arg all dead!
}
void CASW_Mission_Manager::CheatCompleteMission()
{
Msg("CheatCompleteMission\n");
// notify all objectives about this event
if ( !ASWGameResource() )
return;
for (int i=0;i<ASW_MAX_OBJECTIVES;i++)
{
CASW_Objective* pObjective = ASWGameResource()->GetObjective(i);
if (pObjective)
{
pObjective->SetComplete(true);
}
}
CheckMissionComplete();
}
CASW_Objective_Escape* CASW_Mission_Manager::GetEscapeObjective()
{
if ( m_hEscapeObjective.Get() )
return m_hEscapeObjective.Get();
for ( int i=0; i < ASW_MAX_OBJECTIVES; i++ ) // 12 is max number of objectives
{
CASW_Objective_Escape *pEscape = dynamic_cast<CASW_Objective_Escape*>( ASWGameResource()->GetObjective( i ) );
if ( pEscape )
{
m_hEscapeObjective = pEscape;
return pEscape;
}
}
return NULL;
}