You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
235 lines
6.0 KiB
235 lines
6.0 KiB
5 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
// $NoKeywords: $
|
||
|
//=============================================================================//
|
||
|
|
||
|
// Author: Michael S. Booth (mike@turtlerockstudios.com), 2003
|
||
|
|
||
|
#include "cbase.h"
|
||
|
#include "cs_simple_hostage.h"
|
||
|
#include "cs_bot.h"
|
||
|
|
||
|
// memdbgon must be the last include file in a .cpp file!!!
|
||
|
#include "tier0/memdbgon.h"
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------------------------
|
||
|
/**
|
||
|
* Begin the hunt
|
||
|
*/
|
||
|
void HuntState::OnEnter( CCSBot *me )
|
||
|
{
|
||
|
// lurking death
|
||
|
if (me->IsUsingKnife() && me->IsWellPastSafe() && !me->IsHurrying())
|
||
|
me->Walk();
|
||
|
else
|
||
|
me->Run();
|
||
|
|
||
|
|
||
|
me->StandUp();
|
||
|
me->SetDisposition( CCSBot::ENGAGE_AND_INVESTIGATE );
|
||
|
me->SetTask( CCSBot::SEEK_AND_DESTROY );
|
||
|
|
||
|
me->DestroyPath();
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------------------------
|
||
|
/**
|
||
|
* Hunt down our enemies
|
||
|
*/
|
||
|
void HuntState::OnUpdate( CCSBot *me )
|
||
|
{
|
||
|
// if we've been hunting for a long time, drop into Idle for a moment to
|
||
|
// select something else to do
|
||
|
const float huntingTooLongTime = 30.0f;
|
||
|
if (gpGlobals->curtime - me->GetStateTimestamp() > huntingTooLongTime)
|
||
|
{
|
||
|
// stop being a rogue and do the scenario, since there must not be many enemies left to hunt
|
||
|
me->PrintIfWatched( "Giving up hunting.\n" );
|
||
|
me->SetRogue( false );
|
||
|
me->Idle();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// scenario logic
|
||
|
if (TheCSBots()->GetScenario() == CCSBotManager::SCENARIO_DEFUSE_BOMB)
|
||
|
{
|
||
|
if (me->GetTeamNumber() == TEAM_TERRORIST)
|
||
|
{
|
||
|
// if we have the bomb and it's time to plant, or we happen to be in a bombsite and it seems safe, do it
|
||
|
if (me->HasC4())
|
||
|
{
|
||
|
const float safeTime = 3.0f;
|
||
|
|
||
|
if (TheCSBots()->IsTimeToPlantBomb() ||
|
||
|
(me->IsAtBombsite() && gpGlobals->curtime - me->GetLastSawEnemyTimestamp() > safeTime))
|
||
|
{
|
||
|
me->Idle();
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// if we notice the bomb lying on the ground, go get it
|
||
|
if (me->NoticeLooseBomb())
|
||
|
{
|
||
|
me->FetchBomb();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// if bomb has been planted, and we hear it, move to a hiding spot near the bomb and watch it
|
||
|
const Vector *bombPos = me->GetGameState()->GetBombPosition();
|
||
|
if (!me->IsRogue() && me->GetGameState()->IsBombPlanted() && bombPos)
|
||
|
{
|
||
|
me->SetTask( CCSBot::GUARD_TICKING_BOMB );
|
||
|
me->Hide( TheNavMesh->GetNavArea( *bombPos ) );
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
else // CT
|
||
|
{
|
||
|
if (!me->IsRogue() && me->CanSeeLooseBomb())
|
||
|
{
|
||
|
// if we are near the loose bomb and can see it, hide nearby and guard it
|
||
|
me->SetTask( CCSBot::GUARD_LOOSE_BOMB );
|
||
|
me->Hide( TheCSBots()->GetLooseBombArea() );
|
||
|
me->GetChatter()->GuardingLooseBomb( TheCSBots()->GetLooseBomb() );
|
||
|
return;
|
||
|
}
|
||
|
else if (TheCSBots()->IsBombPlanted())
|
||
|
{
|
||
|
// rogues will defuse a bomb, but not guard the defuser
|
||
|
if (!me->IsRogue() || !TheCSBots()->GetBombDefuser())
|
||
|
{
|
||
|
// search for the planted bomb to defuse
|
||
|
me->Idle();
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (TheCSBots()->GetScenario() == CCSBotManager::SCENARIO_RESCUE_HOSTAGES)
|
||
|
{
|
||
|
if (me->GetTeamNumber() == TEAM_TERRORIST)
|
||
|
{
|
||
|
if (me->GetGameState()->AreAllHostagesBeingRescued())
|
||
|
{
|
||
|
// all hostages are being rescued, head them off at the escape zones
|
||
|
if (me->GuardRandomZone())
|
||
|
{
|
||
|
me->SetTask( CCSBot::GUARD_HOSTAGE_RESCUE_ZONE );
|
||
|
me->PrintIfWatched( "Trying to beat them to an escape zone!\n" );
|
||
|
me->SetDisposition( CCSBot::OPPORTUNITY_FIRE );
|
||
|
me->GetChatter()->GuardingHostageEscapeZone( IS_PLAN );
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// if safe time is up, and we stumble across a hostage, guard it
|
||
|
if (!me->IsRogue() && !me->IsSafe())
|
||
|
{
|
||
|
CHostage *hostage = me->GetGameState()->GetNearestVisibleFreeHostage();
|
||
|
if (hostage)
|
||
|
{
|
||
|
CNavArea *area = TheNavMesh->GetNearestNavArea( GetCentroid( hostage ) );
|
||
|
if (area)
|
||
|
{
|
||
|
// we see a free hostage, guard it
|
||
|
me->SetTask( CCSBot::GUARD_HOSTAGES );
|
||
|
me->Hide( area );
|
||
|
me->PrintIfWatched( "I'm guarding hostages\n" );
|
||
|
me->GetChatter()->GuardingHostages( area->GetPlace(), IS_PLAN );
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// listen for enemy noises
|
||
|
if (me->HeardInterestingNoise())
|
||
|
{
|
||
|
me->InvestigateNoise();
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
// look around
|
||
|
me->UpdateLookAround();
|
||
|
|
||
|
// if we have reached our destination area, pick a new one
|
||
|
// if our path fails, pick a new one
|
||
|
if (me->GetLastKnownArea() == m_huntArea || me->UpdatePathMovement() != CCSBot::PROGRESSING)
|
||
|
{
|
||
|
// pick a new hunt area
|
||
|
const float earlyGameTime = 45.0f;
|
||
|
if (TheCSBots()->GetElapsedRoundTime() < earlyGameTime && !me->HasVisitedEnemySpawn())
|
||
|
{
|
||
|
// in the early game, rush the enemy spawn
|
||
|
CBaseEntity *enemySpawn = TheCSBots()->GetRandomSpawn( OtherTeam( me->GetTeamNumber() ) );
|
||
|
|
||
|
//ADRIAN: REVISIT
|
||
|
if ( enemySpawn )
|
||
|
{
|
||
|
m_huntArea = TheNavMesh->GetNavArea( enemySpawn->WorldSpaceCenter() );
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_huntArea = NULL;
|
||
|
float oldest = 0.0f;
|
||
|
|
||
|
int areaCount = 0;
|
||
|
const float minSize = 150.0f;
|
||
|
|
||
|
FOR_EACH_VEC( TheNavAreas, it )
|
||
|
{
|
||
|
CNavArea *area = TheNavAreas[ it ];
|
||
|
|
||
|
++areaCount;
|
||
|
|
||
|
// skip the small areas
|
||
|
Extent extent;
|
||
|
area->GetExtent(&extent);
|
||
|
if (extent.hi.x - extent.lo.x < minSize || extent.hi.y - extent.lo.y < minSize)
|
||
|
continue;
|
||
|
|
||
|
// keep track of the least recently cleared area
|
||
|
float age = gpGlobals->curtime - area->GetClearedTimestamp( me->GetTeamNumber()-1 );
|
||
|
if (age > oldest)
|
||
|
{
|
||
|
oldest = age;
|
||
|
m_huntArea = area;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// if all the areas were too small, pick one at random
|
||
|
int which = RandomInt( 0, areaCount-1 );
|
||
|
|
||
|
areaCount = 0;
|
||
|
FOR_EACH_VEC( TheNavAreas, hit )
|
||
|
{
|
||
|
m_huntArea = TheNavAreas[ hit ];
|
||
|
|
||
|
if (which == areaCount)
|
||
|
break;
|
||
|
|
||
|
--which;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (m_huntArea)
|
||
|
{
|
||
|
// create a new path to a far away area of the map
|
||
|
me->ComputePath( m_huntArea->GetCenter() );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//--------------------------------------------------------------------------------------------------------------
|
||
|
/**
|
||
|
* Done hunting
|
||
|
*/
|
||
|
void HuntState::OnExit( CCSBot *me )
|
||
|
{
|
||
|
}
|