diff --git a/regamedll/dlls/bot/cs_bot_manager.cpp b/regamedll/dlls/bot/cs_bot_manager.cpp index 5656667bf..730805bbf 100644 --- a/regamedll/dlls/bot/cs_bot_manager.cpp +++ b/regamedll/dlls/bot/cs_bot_manager.cpp @@ -1213,6 +1213,13 @@ void CCSBotManager::ValidateMapData() found = true; isLegacy = false; } + else if (FClassnameIs(pEntity->pev, "func_escapezone")) + { + m_gameScenario = SCENARIO_ESCAPE; + found = true; + isLegacy = false; + } + if (found) { diff --git a/regamedll/dlls/bot/cs_bot_manager.h b/regamedll/dlls/bot/cs_bot_manager.h index 1faea5461..9552c6978 100644 --- a/regamedll/dlls/bot/cs_bot_manager.h +++ b/regamedll/dlls/bot/cs_bot_manager.h @@ -85,7 +85,8 @@ class CCSBotManager: public CBotManager SCENARIO_DEATHMATCH, SCENARIO_DEFUSE_BOMB, SCENARIO_RESCUE_HOSTAGES, - SCENARIO_ESCORT_VIP + SCENARIO_ESCORT_VIP, + SCENARIO_ESCAPE }; GameScenarioType GetScenario() const diff --git a/regamedll/dlls/bot/states/cs_bot_idle.cpp b/regamedll/dlls/bot/states/cs_bot_idle.cpp index e38bde885..4bfcd7cc0 100644 --- a/regamedll/dlls/bot/states/cs_bot_idle.cpp +++ b/regamedll/dlls/bot/states/cs_bot_idle.cpp @@ -773,6 +773,93 @@ void IdleState::OnUpdate(CCSBot *me) } break; } + case CCSBotManager::SCENARIO_ESCAPE: + { + if (me->m_iTeam == TERRORIST) + { + // if early in round, pick a random zone, otherwise pick closest zone + const float earlyTime = 20.0f; + const CCSBotManager::Zone *zone = nullptr; + + if (TheCSBots()->GetElapsedRoundTime() < earlyTime) + { + // pick random zone + zone = TheCSBots()->GetRandomZone(); + } + else + { + // pick closest zone + zone = TheCSBots()->GetClosestZone(me->GetLastKnownArea(), PathCost(me)); + } + + if (zone) + { + // pick a random spot within the escape zone + const Vector *pos = TheCSBots()->GetRandomPositionInZone(zone); + if (pos) + { + // move to escape zone + // me->SetTask(CCSBot::VIP_ESCAPE); + me->Run(); + me->MoveTo(pos); + return; + } + } + } + // CT + else + { + if (me->IsSniper()) + { + if (RANDOM_FLOAT(0, 100) <= defenseSniperCampChance) + { + // snipe escape zone(s) + const CCSBotManager::Zone *zone = TheCSBots()->GetRandomZone(); + if (zone) + { + CNavArea *area = TheCSBots()->GetRandomAreaInZone(zone); + if (area) + { + me->SetTask(CCSBot::MOVE_TO_SNIPER_SPOT); + me->Hide(area, -1.0, sniperHideRange); + me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); + me->PrintIfWatched("Sniping near escape zone\n"); + return; + } + } + } + } + + // rogues just hunt, unless they want to snipe + // if the whole team has decided to rush, hunt + if (me->IsRogue() || TheCSBots()->IsDefenseRushing()) + break; + + // the lower our morale gets, the more we want to camp the escape zone(s) + float guardEscapeZoneChance = -34.0f * me->GetMorale(); + + if (RANDOM_FLOAT(0.0f, 100.0f) < guardEscapeZoneChance) + { + // guard escape zone(s) + const CCSBotManager::Zone *zone = TheCSBots()->GetRandomZone(); + if (zone) + { + CNavArea *area = TheCSBots()->GetRandomAreaInZone(zone); + if (area) + { + // guard the escape zone - stay closer if our morale is low + //me->SetTask(CCSBot::GUARD_VIP_ESCAPE_ZONE); + me->PrintIfWatched("I'm guarding an escape zone\n"); + + float escapeGuardRange = 750.0f + 250.0f * (me->GetMorale() + 3); + me->Hide(area, -1.0, escapeGuardRange); + me->SetDisposition(CCSBot::OPPORTUNITY_FIRE); + return; + } + } + } + } + } // deathmatch default: {