diff --git a/src/game/server/neo/bot/behavior/neo_bot_behavior.cpp b/src/game/server/neo/bot/behavior/neo_bot_behavior.cpp index 40336fdbd..6c6f47ee6 100644 --- a/src/game/server/neo/bot/behavior/neo_bot_behavior.cpp +++ b/src/game/server/neo/bot/behavior/neo_bot_behavior.cpp @@ -6,6 +6,8 @@ #include "neo_gamerules.h" #include "bot/neo_bot.h" #include "bot/neo_bot_manager.h" +#include "bot/neo_bot_path_compute.h" +#include "bot/neo_bot_path_cost.h" #include "bot/behavior/neo_bot_behavior.h" #include "bot/behavior/neo_bot_dead.h" #include "NextBot/NavMeshEntities/func_nav_prerequisite.h" @@ -238,6 +240,38 @@ EventDesiredResult< CNEOBot > CNEOBotMainAction::OnStuck( CNEOBot *me ) me->PressRightButton(); } + // NEO Jank: For the current match, all bots share where they get stuck + // The reasoning is that bots on either team will get stuck in their respective half of the map + // so the overall fairness may balance out for both teams sharing common sticking points. + if ( const CNavArea *navArea = me->GetLastKnownArea() ) + { + CNEOBotPathReservations()->IncrementAreaStuckPenalty( navArea->GetID() ); + } + else + { + // Fallback if GetLastKnownArea is null, try finding nearest nav area + CNavArea *nearestArea = TheNavMesh->GetNearestNavArea( me->GetAbsOrigin() ); + if ( nearestArea ) + { + CNEOBotPathReservations()->IncrementAreaStuckPenalty( nearestArea->GetID() ); + } + } + + // Also penalize the immediate next nav area bot was trying to get to + if ( const PathFollower *path = me->GetCurrentPath() ) + { + if ( const Path::Segment *currentGoal = path->GetCurrentGoal() ) + { + if ( const Path::Segment *nextSegment = path->NextSegment( currentGoal ) ) + { + if ( nextSegment->area ) + { + CNEOBotPathReservations()->IncrementAreaStuckPenalty( nextSegment->area->GetID() ); + } + } + } + } + return TryContinue(); } diff --git a/src/game/server/neo/bot/neo_bot_path_cost.cpp b/src/game/server/neo/bot/neo_bot_path_cost.cpp index d31a24911..758b1c8fc 100644 --- a/src/game/server/neo/bot/neo_bot_path_cost.cpp +++ b/src/game/server/neo/bot/neo_bot_path_cost.cpp @@ -114,6 +114,7 @@ float CNEOBotPathCost::operator()(CNavArea* baseArea, CNavArea* fromArea, const && (m_routeType != FASTEST_ROUTE) ) { cost += CNEOBotPathReservations()->GetPredictedFriendlyPathCount(area->GetID(), m_me->GetTeamNumber()) * neo_bot_path_reservation_penalty.GetFloat(); + cost += CNEOBotPathReservations()->GetAreaStuckPenalty(area->GetID()); } // ------------------------------------------------------------------------------------------------ diff --git a/src/game/server/neo/bot/neo_bot_path_reservation.cpp b/src/game/server/neo/bot/neo_bot_path_reservation.cpp index 7ce7086c4..a6b229067 100644 --- a/src/game/server/neo/bot/neo_bot_path_reservation.cpp +++ b/src/game/server/neo/bot/neo_bot_path_reservation.cpp @@ -11,6 +11,8 @@ ConVar neo_bot_path_reservation_enabled("neo_bot_path_reservation_enabled", "1", ConVar neo_bot_path_reservation_penalty("neo_bot_path_reservation_penalty", "100", FCVAR_NONE, "Pathing cost penalty for a reserved area."); ConVar neo_bot_path_reservation_duration("neo_bot_path_reservation_duration", "30.0", FCVAR_NONE, "How long a path reservation lasts, in seconds."); ConVar neo_bot_path_reservation_distance("neo_bot_path_reservation_distance", "10000", FCVAR_NONE, "How far along the path to reserve, in Hammer units."); +ConVar neo_bot_path_reservation_onstuck_penalty_enabled("neo_bot_path_reservation_onstuck_penalty_enabled", "1", FCVAR_NONE, "Whether to update or retrieve the area onstuck penalty."); +ConVar neo_bot_path_reservation_onstuck_penalty("neo_bot_path_reservation_onstuck_penalty", "10000", FCVAR_NONE, "Path selection penalty added to a nav area each time a bot gets stuck moving through that area."); CNEOBotPathReservationSystem* CNEOBotPathReservations() @@ -230,6 +232,7 @@ void CNEOBotPathReservationSystem::Clear() m_AreaPathCounts[team].RemoveAll(); } m_BotReservedAreas.RemoveAll(); + m_AreaOnStuckPenalties.RemoveAll(); } //------------------------------------------------------------------------------------------------- @@ -286,3 +289,36 @@ int CNEOBotPathReservationSystem::GetPredictedFriendlyPathCount( int areaID, int return 0; } + +//------------------------------------------------------------------------------------------------- +void CNEOBotPathReservationSystem::IncrementAreaStuckPenalty(unsigned int navAreaID) +{ + if ( !neo_bot_path_reservation_onstuck_penalty_enabled.GetBool() ) + { + return; + } + + unsigned short index = m_AreaOnStuckPenalties.Find(navAreaID); + if (index == m_AreaOnStuckPenalties.InvalidIndex()) + { + index = m_AreaOnStuckPenalties.Insert(navAreaID, 0.0f); + } + + m_AreaOnStuckPenalties[index] += neo_bot_path_reservation_onstuck_penalty.GetFloat(); +} + +//------------------------------------------------------------------------------------------------- +float CNEOBotPathReservationSystem::GetAreaStuckPenalty(unsigned int navAreaID) const +{ + if ( !neo_bot_path_reservation_onstuck_penalty_enabled.GetBool() ) + { + return 0.0f; + } + + unsigned short index = m_AreaOnStuckPenalties.Find(navAreaID); + if (index != m_AreaOnStuckPenalties.InvalidIndex()) + { + return m_AreaOnStuckPenalties[index]; + } + return 0.0f; +} diff --git a/src/game/server/neo/bot/neo_bot_path_reservation.h b/src/game/server/neo/bot/neo_bot_path_reservation.h index 709763a88..c24c32a79 100644 --- a/src/game/server/neo/bot/neo_bot_path_reservation.h +++ b/src/game/server/neo/bot/neo_bot_path_reservation.h @@ -42,7 +42,7 @@ class CNEOBotPathReservationSystem return lhs.GetSerialNumber() < rhs.GetSerialNumber(); } - CNEOBotPathReservationSystem() : m_BotReservedAreas(EHandleLessFunc) + CNEOBotPathReservationSystem() : m_BotReservedAreas(EHandleLessFunc), m_AreaOnStuckPenalties(DefLessFunc(unsigned int)) { for (int i = 0; i < MAX_TEAMS; ++i) { @@ -61,6 +61,9 @@ class CNEOBotPathReservationSystem void DecrementPredictedFriendlyPathCount( int areaID, int teamID ); int GetPredictedFriendlyPathCount( int areaID, int teamID ) const; + void IncrementAreaStuckPenalty(unsigned int navAreaID); + float GetAreaStuckPenalty(unsigned int navAreaID) const; + // Allow the global accessor to access private members if needed, though constructor handles init now. friend CNEOBotPathReservationSystem* CNEOBotPathReservations(); @@ -68,6 +71,7 @@ class CNEOBotPathReservationSystem CUtlMap m_Reservations[MAX_TEAMS]; CUtlMap m_BotReservedAreas; CUtlMap m_AreaPathCounts[MAX_TEAMS]; + CUtlMap m_AreaOnStuckPenalties; };