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.
198 lines
4.8 KiB
198 lines
4.8 KiB
#include "bot_common.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->time - 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, and being a rogue\n"); |
|
me->SetRogue(false); |
|
me->Idle(); |
|
return; |
|
} |
|
|
|
CCSBotManager *ctrl = TheCSBots(); |
|
#if 0 |
|
// scenario logic |
|
if (ctrl->GetScenario() == CCSBotManager::SCENARIO_DEFUSE_BOMB) |
|
{ |
|
if (me->m_iTeam == 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->IsCarryingBomb()) |
|
{ |
|
const float safeTime = 3.0f; |
|
if (ctrl->IsTimeToPlantBomb() || (me->IsAtBombsite() && gpGlobals->time - 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 != NULL) |
|
{ |
|
me->SetTask(CCSBot::GUARD_TICKING_BOMB); |
|
me->Hide(TheNavAreaGrid.GetNavArea(bombPos)); |
|
return; |
|
} |
|
} |
|
// CT |
|
else |
|
{ |
|
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(ctrl->GetLooseBombArea()); |
|
me->GetChatter()->AnnouncePlan("GoingToGuardLooseBomb", ctrl->GetLooseBombArea()->GetPlace()); |
|
return; |
|
} |
|
else if (ctrl->IsBombPlanted()) |
|
{ |
|
// rogues will defuse a bomb, but not guard the defuser |
|
if (!me->IsRogue() || !ctrl->GetBombDefuser()) |
|
{ |
|
// search for the planted bomb to defuse |
|
me->Idle(); |
|
return; |
|
} |
|
} |
|
} |
|
} |
|
else if (ctrl->GetScenario() == CCSBotManager::SCENARIO_RESCUE_HOSTAGES) |
|
{ |
|
if (me->m_iTeam == 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 != NULL) |
|
{ |
|
CNavArea *area = TheNavAreaGrid.GetNearestNavArea(&hostage->pev->origin); |
|
if (area != NULL) |
|
{ |
|
// 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; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
#endif |
|
|
|
// listen for enemy noises |
|
if (me->ShouldInvestigateNoise()) |
|
{ |
|
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) |
|
{ |
|
m_huntArea = NULL; |
|
float oldest = 0.0f; |
|
|
|
int areaCount = 0; |
|
const float minSize = 150.0f; |
|
|
|
FOR_EACH_LL (TheNavAreaList, it) |
|
{ |
|
CNavArea *area = TheNavAreaList[it]; |
|
|
|
++areaCount; |
|
|
|
// skip the small areas |
|
const Extent *extent = area->GetExtent(); |
|
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->time - area->GetClearedTimestamp(me->m_iTeam - 1); |
|
if (age > oldest) |
|
{ |
|
oldest = age; |
|
m_huntArea = area; |
|
} |
|
} |
|
|
|
// if all the areas were too small, pick one at random |
|
int which = RANDOM_LONG(0, areaCount - 1); |
|
|
|
areaCount = 0; |
|
FOR_EACH_LL (TheNavAreaList, it2) |
|
{ |
|
m_huntArea = TheNavAreaList[it2]; |
|
|
|
if (which == areaCount) |
|
break; |
|
|
|
--which; |
|
} |
|
|
|
if (m_huntArea != NULL) |
|
{ |
|
// create a new path to a far away area of the map |
|
me->ComputePath(m_huntArea, NULL, SAFEST_ROUTE); |
|
} |
|
} |
|
} |
|
|
|
// Done hunting |
|
|
|
void HuntState::OnExit(CCSBot *me) |
|
{ |
|
; |
|
}
|
|
|