Skip to content

Commit 09cc11f

Browse files
committed
Add support for Arena mode in TF bots
1 parent c049aab commit 09cc11f

11 files changed

Lines changed: 180 additions & 2 deletions

src/game/server/tf/bot/behavior/engineer/tf_bot_engineer_build.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,19 @@
2222
// this was useful when engineers build at their normal (slow) rate to make sure initial sentries get built in time
2323
ConVar tf_raid_engineer_infinte_metal( "tf_raid_engineer_infinte_metal", "1", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY );
2424

25+
#ifdef MAPBASE
26+
ConVar tf_bot_arena_build_teleporter( "tf_bot_arena_build_teleporter", "0" );
27+
#endif
28+
2529

2630
//---------------------------------------------------------------------------------------------
2731
Action< CTFBot > *CTFBotEngineerBuild::InitialContainedAction( CTFBot *me )
2832
{
33+
#ifdef MAPBASE
34+
if ( TFGameRules()->IsPVEModeActive() || ( TFGameRules()->IsInArenaMode() && !tf_bot_arena_build_teleporter.GetBool() ) )
35+
#else
2936
if ( TFGameRules()->IsPVEModeActive() )
37+
#endif
3038
{
3139
return new CTFBotEngineerMoveToBuild;
3240
}

src/game/server/tf/bot/behavior/engineer/tf_bot_engineer_building.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
#include "bot/behavior/engineer/tf_bot_engineer_build_teleport_exit.h"
1919
#include "bot/behavior/engineer/tf_bot_engineer_build_sentrygun.h"
2020
#include "bot/behavior/engineer/tf_bot_engineer_build_dispenser.h"
21+
#ifdef MAPBASE
22+
#include "bot/behavior/scenario/capture_point/tf_bot_capture_point.h"
23+
#include "bot/behavior/tf_bot_seek_and_destroy.h"
24+
#endif
2125
#include "bot/behavior/tf_bot_attack.h"
2226
#include "bot/behavior/tf_bot_get_ammo.h"
2327
#include "bot/map_entities/tf_bot_hint_teleporter_exit.h"
@@ -464,6 +468,30 @@ ActionResult< CTFBot > CTFBotEngineerBuilding::Update( CTFBot *me, float interva
464468
}
465469
}
466470

471+
#ifdef MAPBASE
472+
if ( TFGameRules()->IsInArenaMode() )
473+
{
474+
// If we are the only player left on our team, don't get caught in a loop in case there's
475+
// another engineer on the other team maintaining their buildings like we are
476+
// Defer to default capture AI
477+
CUtlVector< CTFPlayer * > livePlayerVector;
478+
CollectPlayers( &livePlayerVector, me->GetTeamNumber(), COLLECT_ONLY_LIVING_PLAYERS );
479+
480+
if ( livePlayerVector.Count() <= 1 )
481+
{
482+
CUtlVector< CTeamControlPoint * > captureVector;
483+
TFGameRules()->CollectCapturePoints( me, &captureVector );
484+
485+
if ( captureVector.Count() > 0 )
486+
{
487+
return ChangeTo( new CTFBotCapturePoint, "Everyone is gone! Going for the point" );
488+
}
489+
490+
return ChangeTo( new CTFBotSeekAndDestroy, "Everyone is gone! Seeking and destroying" );
491+
}
492+
}
493+
#endif
494+
467495
// everything is built - maintain them
468496
UpgradeAndMaintainBuildings( me );
469497

src/game/server/tf/bot/behavior/engineer/tf_bot_engineer_move_to_build.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ void CTFBotEngineerMoveToBuild::CollectBuildAreas( CTFBot *me )
5858
m_sentryAreaVector.RemoveAll();
5959

6060
CUtlVector< CTFNavArea * > pointAreaVector;
61+
#ifdef MAPBASE
62+
// Gamemodes such as arena may use control points outside of the actual CP mode
63+
// This is used to check if there's a valid control point, as GetControlPointCenterArea is used elsewhere in engineer AI
64+
CTFNavArea *pointCenterArea = NULL;
65+
#endif
6166
Vector pointCentroid = vec3_origin;
6267
float pointEnemyIncursion = 0.0f;
6368
int i;
@@ -110,6 +115,10 @@ void CTFBotEngineerMoveToBuild::CollectBuildAreas( CTFBot *me )
110115
if ( !ctrlPoint )
111116
return;
112117

118+
#ifdef MAPBASE
119+
pointCenterArea = TheTFNavMesh()->GetControlPointCenterArea( ctrlPoint->GetPointIndex() );
120+
#endif
121+
113122
const CUtlVector< CTFNavArea * > *ctrlPointAreaVector = TheTFNavMesh()->GetControlPointAreas( ctrlPoint->GetPointIndex() );
114123

115124
if ( ctrlPointAreaVector )
@@ -161,7 +170,12 @@ void CTFBotEngineerMoveToBuild::CollectBuildAreas( CTFBot *me )
161170
// continue;
162171
// }
163172

173+
#ifdef MAPBASE
174+
// Control points may exist outside of CP mode
175+
if ( pointCenterArea )
176+
#else
164177
if ( TFGameRules()->GetGameType() == TF_GAMETYPE_CP )
178+
#endif
165179
{
166180
// don't build directly on the point
167181
if ( visibleArea->HasAttributeTF( TF_NAV_CONTROL_POINT ) )

src/game/server/tf/bot/behavior/medic/tf_bot_medic_heal.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
#include "bot/behavior/medic/tf_bot_medic_retreat.h"
1414
#include "bot/behavior/tf_bot_use_teleporter.h"
1515
#include "bot/behavior/scenario/capture_the_flag/tf_bot_fetch_flag.h"
16+
#ifdef MAPBASE
17+
#include "bot/behavior/scenario/capture_point/tf_bot_capture_point.h"
18+
#include "bot/behavior/tf_bot_seek_and_destroy.h"
19+
#endif
1620
#include "nav_mesh.h"
1721
#include "tier0/vprof.h"
1822

@@ -272,7 +276,11 @@ CTFPlayer *CTFBotMedicHeal::SelectPatient( CTFBot *me, CTFPlayer *current )
272276

273277
CSelectPrimaryPatient choose( me, current );
274278

279+
#ifdef MAPBASE
280+
if ( TFGameRules()->IsPVEModeActive() || TFGameRules()->IsInArenaMode() )
281+
#else
275282
if ( TFGameRules()->IsPVEModeActive() )
283+
#endif
276284
{
277285
// assume perfect knowledge
278286
CUtlVector< CTFPlayer * > livePlayerVector;
@@ -518,6 +526,23 @@ ActionResult< CTFBot > CTFBotMedicHeal::Update( CTFBot *me, float interval )
518526
return Continue();
519527
}
520528

529+
#ifdef MAPBASE
530+
if ( TFGameRules()->IsInArenaMode() )
531+
{
532+
// If we can't find a patient in arena mode, we probably won't for the rest of the round
533+
// Defer to default capture AI
534+
CUtlVector< CTeamControlPoint * > captureVector;
535+
TFGameRules()->CollectCapturePoints( me, &captureVector );
536+
537+
if ( captureVector.Count() > 0 )
538+
{
539+
return ChangeTo( new CTFBotCapturePoint, "Everyone is gone! Going for the point" );
540+
}
541+
542+
return ChangeTo( new CTFBotSeekAndDestroy, "Everyone is gone! Seeking and destroying" );
543+
}
544+
#endif
545+
521546
// no patients - retreat to spawn to find another one
522547
return SuspendFor( new CTFBotMedicRetreat, "Retreating to find another patient to heal" );
523548
}

src/game/server/tf/bot/behavior/scenario/capture_point/tf_bot_capture_point.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,15 @@ ActionResult< CTFBot > CTFBotCapturePoint::Update( CTFBot *me, float interval )
5555
return SuspendFor( new CTFBotSeekAndDestroy( roamTime ), "Seek and destroy until a point becomes available" );
5656
}
5757

58+
#ifdef MAPBASE
59+
if ( TFGameRules()->IsInArenaMode() )
60+
{
61+
// CollectCapturePoints() can still count a locked point in arena mode. Wait until it's open before zeroing in
62+
if ( !TeamplayGameRules()->TeamMayCapturePoint( me->GetTeamNumber(), point->GetPointIndex() ) )
63+
return SuspendFor( new CTFBotSeekAndDestroy, "Seek and destroy until a point becomes available" );
64+
}
65+
#endif
66+
5867
if ( point->GetTeamNumber() == me->GetTeamNumber() )
5968
{
6069
return ChangeTo( new CTFBotDefendPoint, "We need to defend our point(s)" );

src/game/server/tf/bot/behavior/tf_bot_scenario_monitor.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,21 @@ Action< CTFBot > *CTFBotScenarioMonitor::DesiredScenarioAndClassAction( CTFBot *
287287
DevMsg( "%3.2f: %s: Gametype is CP, but I can't find a point to capture or defend!\n", gpGlobals->curtime, me->GetDebugIdentifier() );
288288
return new CTFBotCapturePoint;
289289
}
290+
#ifdef MAPBASE
291+
else if ( TFGameRules()->GetGameType() == TF_GAMETYPE_ARENA )
292+
{
293+
// if we have a point we can capture - do it
294+
CUtlVector< CTeamControlPoint * > captureVector;
295+
TFGameRules()->CollectCapturePoints( me, &captureVector );
296+
297+
if ( captureVector.Count() > 0 )
298+
{
299+
return new CTFBotCapturePoint;
300+
}
301+
302+
return new CTFBotSeekAndDestroy;
303+
}
304+
#endif
290305
else
291306
{
292307
// scenario not implemented yet - just fight

src/game/server/tf/bot/behavior/tf_bot_seek_and_destroy.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ ActionResult< CTFBot > CTFBotSeekAndDestroy::OnStart( CTFBot *me, Action< CTFBot
3838
RecomputeSeekPath( me );
3939

4040
CTeamControlPoint *point = me->GetMyControlPoint();
41-
m_isPointLocked = ( point && point->IsLocked() );
41+
m_isPointLocked = IsPointLocked( me, point );
4242

4343
// restart the timer if we have one
4444
if ( m_giveUpTimer.HasStarted() )
@@ -77,7 +77,7 @@ ActionResult< CTFBot > CTFBotSeekAndDestroy::Update( CTFBot *me, float interval
7777
{
7878
CTeamControlPoint *point = me->GetMyControlPoint();
7979

80-
if ( point && !point->IsLocked() )
80+
if ( !IsPointLocked( me, point ) )
8181
{
8282
return Done( "The point just unlocked" );
8383
}
@@ -253,3 +253,25 @@ EventDesiredResult< CTFBot > CTFBotSeekAndDestroy::OnTerritoryLost( CTFBot *me,
253253
return TryDone( RESULT_IMPORTANT, "Giving up due to point lost" );
254254
}
255255

256+
257+
//---------------------------------------------------------------------------------------------
258+
bool CTFBotSeekAndDestroy::IsPointLocked( CTFBot *me, CTeamControlPoint *point )
259+
{
260+
if ( !point )
261+
return false;
262+
263+
if ( point->IsLocked() )
264+
return true;
265+
266+
#ifdef MAPBASE
267+
if ( TFGameRules()->IsInArenaMode() )
268+
{
269+
// Arena mode has special lock conditions in CTFGameRules::TeamMayCapturePoint
270+
if ( !TFGameRules()->TeamMayCapturePoint( me->GetTeamNumber(), point->GetPointIndex() ) )
271+
return true;
272+
}
273+
#endif
274+
275+
return false;
276+
}
277+

src/game/server/tf/bot/behavior/tf_bot_seek_and_destroy.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ class CTFBotSeekAndDestroy : public Action< CTFBot >
3535

3636
virtual const char *GetName( void ) const { return "SeekAndDestroy"; };
3737

38+
bool IsPointLocked( CTFBot *me, CTeamControlPoint *point );
39+
3840
private:
3941
CTFNavArea *m_goalArea;
4042
CTFNavArea *ChooseGoalArea( CTFBot *me );

src/game/server/tf/bot/tf_bot.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1381,6 +1381,12 @@ void CTFBot::SetMission( MissionType mission, bool resetBehaviorSystem )
13811381
//-----------------------------------------------------------------------------------------------------
13821382
bool CTFBot::ShouldReEvaluateCurrentClass( void ) const
13831383
{
1384+
#ifdef MAPBASE
1385+
// Don't change class mid-round in arena mode
1386+
if ( TFGameRules() && TFGameRules()->IsInArenaMode() && TFGameRules()->GetRoundState() >= GR_STATE_RND_RUNNING )
1387+
return false;
1388+
#endif
1389+
13841390
ETFClass iCurrentClass = ( ETFClass )GetPlayerClass()->GetClassIndex();
13851391
Assert( iCurrentClass != TF_CLASS_UNDEFINED );
13861392
TFPlayerClassData_t *classData = GetPlayerClassData( iCurrentClass );

src/game/server/tf/bot/tf_bot_manager.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,13 @@ void CTFBotManager::MaintainBotQuota()
408408
{
409409
nTFBotsOnGameTeams++;
410410
}
411+
#ifdef MAPBASE
412+
else if ( TFGameRules()->IsInArenaMode() && tf_arena_use_queue.GetBool() && pPlayer->GetTeamNumber() == TEAM_SPECTATOR )
413+
{
414+
// Spectators waiting in queue
415+
nTFBotsOnGameTeams++;
416+
}
417+
#endif
411418
}
412419
else
413420
{
@@ -471,6 +478,12 @@ void CTFBotManager::MaintainBotQuota()
471478
if ( pBot )
472479
{
473480
pBot->SetAttribute( CTFBot::QUOTA_MANANGED );
481+
482+
#ifdef MAPBASE
483+
// Don't try to change teams on anyone in arena mode queue
484+
if ( pBot->GetTeamNumber() != TEAM_UNASSIGNED && TFGameRules()->IsInArenaMode() && tf_arena_use_queue.GetBool() )
485+
return;
486+
#endif
474487

475488
// join a team before we pick our class, since we use our teammates to decide what class to be
476489
pBot->HandleCommand_JoinTeam( "auto" );
@@ -632,7 +645,12 @@ CTFBot* CTFBotManager::GetAvailableBotFromPool()
632645
if ( ( pBot->GetFlags() & FL_FAKECLIENT ) == 0 )
633646
continue;
634647

648+
#ifdef MAPBASE
649+
// Spectators stay quota-managed in arena mode queue
650+
if ( ( pBot->GetTeamNumber() == TEAM_SPECTATOR && ( !TFGameRules()->IsInArenaMode() || !tf_arena_use_queue.GetBool() ) ) || pBot->GetTeamNumber() == TEAM_UNASSIGNED )
651+
#else
635652
if ( pBot->GetTeamNumber() == TEAM_SPECTATOR || pBot->GetTeamNumber() == TEAM_UNASSIGNED )
653+
#endif
636654
{
637655
pBot->ClearAttribute( CTFBot::QUOTA_MANANGED );
638656
return pBot;

0 commit comments

Comments
 (0)