Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,19 @@
// this was useful when engineers build at their normal (slow) rate to make sure initial sentries get built in time
ConVar tf_raid_engineer_infinte_metal( "tf_raid_engineer_infinte_metal", "1", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY );

#ifdef MAPBASE
ConVar tf_bot_arena_build_teleporter( "tf_bot_arena_build_teleporter", "0" );
#endif


//---------------------------------------------------------------------------------------------
Action< CTFBot > *CTFBotEngineerBuild::InitialContainedAction( CTFBot *me )
{
#ifdef MAPBASE
if ( TFGameRules()->IsPVEModeActive() || ( TFGameRules()->IsInArenaMode() && !tf_bot_arena_build_teleporter.GetBool() ) )
#else
if ( TFGameRules()->IsPVEModeActive() )
#endif
{
return new CTFBotEngineerMoveToBuild;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@
#include "bot/behavior/engineer/tf_bot_engineer_build_teleport_exit.h"
#include "bot/behavior/engineer/tf_bot_engineer_build_sentrygun.h"
#include "bot/behavior/engineer/tf_bot_engineer_build_dispenser.h"
#ifdef MAPBASE
#include "bot/behavior/scenario/capture_point/tf_bot_capture_point.h"
#include "bot/behavior/tf_bot_seek_and_destroy.h"
#endif
#include "bot/behavior/tf_bot_attack.h"
#include "bot/behavior/tf_bot_get_ammo.h"
#include "bot/map_entities/tf_bot_hint_teleporter_exit.h"
Expand Down Expand Up @@ -464,6 +468,30 @@ ActionResult< CTFBot > CTFBotEngineerBuilding::Update( CTFBot *me, float interva
}
}

#ifdef MAPBASE
if ( TFGameRules()->IsInArenaMode() )
{
// If we are the only player left on our team, don't get caught in a loop in case there's
// another engineer on the other team maintaining their buildings like we are
// Defer to default capture AI
CUtlVector< CTFPlayer * > livePlayerVector;
CollectPlayers( &livePlayerVector, me->GetTeamNumber(), COLLECT_ONLY_LIVING_PLAYERS );

if ( livePlayerVector.Count() <= 1 )
{
CUtlVector< CTeamControlPoint * > captureVector;
TFGameRules()->CollectCapturePoints( me, &captureVector );

if ( captureVector.Count() > 0 )
{
return ChangeTo( new CTFBotCapturePoint, "Everyone is gone! Going for the point" );
}

return ChangeTo( new CTFBotSeekAndDestroy, "Everyone is gone! Seeking and destroying" );
}
}
#endif

// everything is built - maintain them
UpgradeAndMaintainBuildings( me );

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ void CTFBotEngineerMoveToBuild::CollectBuildAreas( CTFBot *me )
m_sentryAreaVector.RemoveAll();

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

#ifdef MAPBASE
pointCenterArea = TheTFNavMesh()->GetControlPointCenterArea( ctrlPoint->GetPointIndex() );
#endif

const CUtlVector< CTFNavArea * > *ctrlPointAreaVector = TheTFNavMesh()->GetControlPointAreas( ctrlPoint->GetPointIndex() );

if ( ctrlPointAreaVector )
Expand Down Expand Up @@ -161,7 +170,12 @@ void CTFBotEngineerMoveToBuild::CollectBuildAreas( CTFBot *me )
// continue;
// }

#ifdef MAPBASE
// Control points may exist outside of CP mode
if ( pointCenterArea )
#else
if ( TFGameRules()->GetGameType() == TF_GAMETYPE_CP )
#endif
{
// don't build directly on the point
if ( visibleArea->HasAttributeTF( TF_NAV_CONTROL_POINT ) )
Expand Down
25 changes: 25 additions & 0 deletions src/game/server/tf/bot/behavior/medic/tf_bot_medic_heal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
#include "bot/behavior/medic/tf_bot_medic_retreat.h"
#include "bot/behavior/tf_bot_use_teleporter.h"
#include "bot/behavior/scenario/capture_the_flag/tf_bot_fetch_flag.h"
#ifdef MAPBASE
#include "bot/behavior/scenario/capture_point/tf_bot_capture_point.h"
#include "bot/behavior/tf_bot_seek_and_destroy.h"
#endif
#include "nav_mesh.h"
#include "tier0/vprof.h"

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

CSelectPrimaryPatient choose( me, current );

#ifdef MAPBASE
if ( TFGameRules()->IsPVEModeActive() || TFGameRules()->IsInArenaMode() )
#else
if ( TFGameRules()->IsPVEModeActive() )
#endif
{
// assume perfect knowledge
CUtlVector< CTFPlayer * > livePlayerVector;
Expand Down Expand Up @@ -518,6 +526,23 @@ ActionResult< CTFBot > CTFBotMedicHeal::Update( CTFBot *me, float interval )
return Continue();
}

#ifdef MAPBASE
if ( TFGameRules()->IsInArenaMode() )
{
// If we can't find a patient in arena mode, we probably won't for the rest of the round
// Defer to default capture AI
CUtlVector< CTeamControlPoint * > captureVector;
TFGameRules()->CollectCapturePoints( me, &captureVector );

if ( captureVector.Count() > 0 )
{
return ChangeTo( new CTFBotCapturePoint, "Everyone is gone! Going for the point" );
}

return ChangeTo( new CTFBotSeekAndDestroy, "Everyone is gone! Seeking and destroying" );
}
#endif

// no patients - retreat to spawn to find another one
return SuspendFor( new CTFBotMedicRetreat, "Retreating to find another patient to heal" );
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,15 @@ ActionResult< CTFBot > CTFBotCapturePoint::Update( CTFBot *me, float interval )
return SuspendFor( new CTFBotSeekAndDestroy( roamTime ), "Seek and destroy until a point becomes available" );
}

#ifdef MAPBASE
if ( TFGameRules()->IsInArenaMode() )
{
// CollectCapturePoints() can still count a locked point in arena mode. Wait until it's open before zeroing in
if ( !TeamplayGameRules()->TeamMayCapturePoint( me->GetTeamNumber(), point->GetPointIndex() ) )
return SuspendFor( new CTFBotSeekAndDestroy, "Seek and destroy until a point becomes available" );
}
#endif

if ( point->GetTeamNumber() == me->GetTeamNumber() )
{
return ChangeTo( new CTFBotDefendPoint, "We need to defend our point(s)" );
Expand Down
15 changes: 15 additions & 0 deletions src/game/server/tf/bot/behavior/tf_bot_scenario_monitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,21 @@ Action< CTFBot > *CTFBotScenarioMonitor::DesiredScenarioAndClassAction( CTFBot *
DevMsg( "%3.2f: %s: Gametype is CP, but I can't find a point to capture or defend!\n", gpGlobals->curtime, me->GetDebugIdentifier() );
return new CTFBotCapturePoint;
}
#ifdef MAPBASE
else if ( TFGameRules()->GetGameType() == TF_GAMETYPE_ARENA )
{
// if we have a point we can capture - do it
CUtlVector< CTeamControlPoint * > captureVector;
TFGameRules()->CollectCapturePoints( me, &captureVector );

if ( captureVector.Count() > 0 )
{
return new CTFBotCapturePoint;
}

return new CTFBotSeekAndDestroy;
}
#endif
else
{
// scenario not implemented yet - just fight
Expand Down
35 changes: 31 additions & 4 deletions src/game/server/tf/bot/behavior/tf_bot_seek_and_destroy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ ActionResult< CTFBot > CTFBotSeekAndDestroy::OnStart( CTFBot *me, Action< CTFBot
RecomputeSeekPath( me );

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

// restart the timer if we have one
if ( m_giveUpTimer.HasStarted() )
Expand Down Expand Up @@ -77,15 +77,20 @@ ActionResult< CTFBot > CTFBotSeekAndDestroy::Update( CTFBot *me, float interval
{
CTeamControlPoint *point = me->GetMyControlPoint();

if ( point && !point->IsLocked() )
if ( !IsPointLocked( me, point ) )
{
return Done( "The point just unlocked" );
}
}

if ( !TFGameRules()->RoundHasBeenWon() && me->GetTimeLeftToCapture() < tf_bot_offense_must_push_time.GetFloat() )
// Added proper fix to the bot offense push time bug that causes seek and destroy to never happen
// Basically just check for these gamemodes and otherwise allow seek and destroy at all times
if (TFGameRules()->GetGameType() == TF_GAMETYPE_ESCORT || TFGameRules()->GetGameType() == TF_GAMETYPE_CP)
{
return Done( "Time to push for the objective" );
if (!TFGameRules()->RoundHasBeenWon() && me->GetTimeLeftToCapture() < tf_bot_offense_must_push_time.GetFloat())
{
return Done("Time to push for the objective");
}
}
}

Expand Down Expand Up @@ -248,3 +253,25 @@ EventDesiredResult< CTFBot > CTFBotSeekAndDestroy::OnTerritoryLost( CTFBot *me,
return TryDone( RESULT_IMPORTANT, "Giving up due to point lost" );
}


//---------------------------------------------------------------------------------------------
bool CTFBotSeekAndDestroy::IsPointLocked( CTFBot *me, CTeamControlPoint *point )
{
if ( !point )
return false;

if ( point->IsLocked() )
return true;

#ifdef MAPBASE
if ( TFGameRules()->IsInArenaMode() )
{
// Arena mode has special lock conditions in CTFGameRules::TeamMayCapturePoint
if ( !TFGameRules()->TeamMayCapturePoint( me->GetTeamNumber(), point->GetPointIndex() ) )
return true;
}
#endif

return false;
}

2 changes: 2 additions & 0 deletions src/game/server/tf/bot/behavior/tf_bot_seek_and_destroy.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ class CTFBotSeekAndDestroy : public Action< CTFBot >

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

bool IsPointLocked( CTFBot *me, CTeamControlPoint *point );

private:
CTFNavArea *m_goalArea;
CTFNavArea *ChooseGoalArea( CTFBot *me );
Expand Down
9 changes: 8 additions & 1 deletion src/game/server/tf/bot/tf_bot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1381,6 +1381,12 @@ void CTFBot::SetMission( MissionType mission, bool resetBehaviorSystem )
//-----------------------------------------------------------------------------------------------------
bool CTFBot::ShouldReEvaluateCurrentClass( void ) const
{
#ifdef MAPBASE
// Don't change class mid-round in arena mode
if ( TFGameRules() && TFGameRules()->IsInArenaMode() && TFGameRules()->GetRoundState() >= GR_STATE_RND_RUNNING )
return false;
#endif

ETFClass iCurrentClass = ( ETFClass )GetPlayerClass()->GetClassIndex();
Assert( iCurrentClass != TF_CLASS_UNDEFINED );
TFPlayerClassData_t *classData = GetPlayerClassData( iCurrentClass );
Expand Down Expand Up @@ -2286,7 +2292,8 @@ float CTFBot::GetTimeLeftToCapture( void ) const
return TFGameRules()->GetActiveRoundTimer()->GetTimeRemaining();
}

return 0.0f;
// Instead of returning 0.0, return FLT_MAX to prevent any other bugs related to this check.
return FLT_MAX;
}


Expand Down
18 changes: 18 additions & 0 deletions src/game/server/tf/bot/tf_bot_manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,13 @@ void CTFBotManager::MaintainBotQuota()
{
nTFBotsOnGameTeams++;
}
#ifdef MAPBASE
else if ( TFGameRules()->IsInArenaMode() && tf_arena_use_queue.GetBool() && pPlayer->GetTeamNumber() == TEAM_SPECTATOR )
{
// Spectators waiting in queue
nTFBotsOnGameTeams++;
}
#endif
}
else
{
Expand Down Expand Up @@ -471,6 +478,12 @@ void CTFBotManager::MaintainBotQuota()
if ( pBot )
{
pBot->SetAttribute( CTFBot::QUOTA_MANANGED );

#ifdef MAPBASE
// Don't try to change teams on anyone in arena mode queue
if ( pBot->GetTeamNumber() != TEAM_UNASSIGNED && TFGameRules()->IsInArenaMode() && tf_arena_use_queue.GetBool() )
return;
#endif

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

#ifdef MAPBASE
// Spectators stay quota-managed in arena mode queue
if ( ( pBot->GetTeamNumber() == TEAM_SPECTATOR && ( !TFGameRules()->IsInArenaMode() || !tf_arena_use_queue.GetBool() ) ) || pBot->GetTeamNumber() == TEAM_UNASSIGNED )
#else
if ( pBot->GetTeamNumber() == TEAM_SPECTATOR || pBot->GetTeamNumber() == TEAM_UNASSIGNED )
#endif
{
pBot->ClearAttribute( CTFBot::QUOTA_MANANGED );
return pBot;
Expand Down
Loading
Loading