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.
234 lines
6.0 KiB
234 lines
6.0 KiB
//========= 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 ) |
|
{ |
|
}
|
|
|