Skip to content

Commit

Permalink
WIP TF2 Stuff
Browse files Browse the repository at this point in the history
[ci skip]
  • Loading branch information
caxanga334 committed Jun 11, 2024
1 parent f421e9b commit 8a459d1
Show file tree
Hide file tree
Showing 14 changed files with 128 additions and 58 deletions.
5 changes: 5 additions & 0 deletions extension/bot/interfaces/behavior.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,8 @@ Vector IBehavior::GetTargetAimPos(CBaseBot* me, edict_t* entity, CBaseExtPlayer*
{
return GetDecisionQueryResponder()->GetTargetAimPos(me, entity, player);
}

QueryAnswerType IBehavior::IsReady(CBaseBot* me)
{
return GetDecisionQueryResponder()->IsReady(me);
}
21 changes: 11 additions & 10 deletions extension/bot/interfaces/behavior.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,17 @@ class IBehavior : public IBotInterface, public IDecisionQuery
// Returns who will answer to decision queries
virtual IDecisionQuery* GetDecisionQueryResponder() = 0;

virtual QueryAnswerType ShouldAttack(CBaseBot* me, const CKnownEntity* them) override;
virtual QueryAnswerType ShouldSeekAndDestroy(CBaseBot* me, const CKnownEntity* them) override;
virtual QueryAnswerType ShouldPickup(CBaseBot* me, edict_t* item) override;
virtual QueryAnswerType ShouldHurry(CBaseBot* me) override;
virtual QueryAnswerType ShouldRetreat(CBaseBot* me) override;
virtual QueryAnswerType ShouldUse(CBaseBot* me, edict_t* object) override;
virtual QueryAnswerType ShouldFreeRoam(CBaseBot* me) override;
virtual QueryAnswerType IsBlocker(CBaseBot* me, edict_t* blocker, const bool any = false) override;
virtual const CKnownEntity* SelectTargetThreat(CBaseBot* me, const CKnownEntity* threat1, const CKnownEntity* threat2) override;
virtual Vector GetTargetAimPos(CBaseBot* me, edict_t* entity, CBaseExtPlayer* player = nullptr) override;
QueryAnswerType ShouldAttack(CBaseBot* me, const CKnownEntity* them) override;
QueryAnswerType ShouldSeekAndDestroy(CBaseBot* me, const CKnownEntity* them) override;
QueryAnswerType ShouldPickup(CBaseBot* me, edict_t* item) override;
QueryAnswerType ShouldHurry(CBaseBot* me) override;
QueryAnswerType ShouldRetreat(CBaseBot* me) override;
QueryAnswerType ShouldUse(CBaseBot* me, edict_t* object) override;
QueryAnswerType ShouldFreeRoam(CBaseBot* me) override;
QueryAnswerType IsBlocker(CBaseBot* me, edict_t* blocker, const bool any = false) override;
const CKnownEntity* SelectTargetThreat(CBaseBot* me, const CKnownEntity* threat1, const CKnownEntity* threat2) override;
Vector GetTargetAimPos(CBaseBot* me, edict_t* entity, CBaseExtPlayer* player = nullptr) override;
QueryAnswerType IsReady(CBaseBot* me) override;

private:

Expand Down
7 changes: 7 additions & 0 deletions extension/bot/interfaces/decisionquery.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ class IDecisionQuery
virtual const CKnownEntity* SelectTargetThreat(CBaseBot* me, const CKnownEntity* threat1, const CKnownEntity* threat2);
// Given a entity, returns a vector of where the bot should aim at. The player parameter may be NULL.
virtual Vector GetTargetAimPos(CBaseBot* me, edict_t* entity, CBaseExtPlayer* player = nullptr);
// If a game mode has a toggle ready feature, this asks if the bot is ready
virtual QueryAnswerType IsReady(CBaseBot* me);
private:

};
Expand Down Expand Up @@ -109,5 +111,10 @@ inline Vector IDecisionQuery::GetTargetAimPos(CBaseBot* me, edict_t* entity, CBa
return vec3_origin;
}

inline QueryAnswerType IDecisionQuery::IsReady(CBaseBot* me)
{
return ANSWER_UNDEFINED;
}

#endif // !SMNAV_BOT_DECISION_QUERY_H_

27 changes: 16 additions & 11 deletions extension/bot/interfaces/tasks.h
Original file line number Diff line number Diff line change
Expand Up @@ -289,47 +289,47 @@ class AITaskManager : public IEventListener, public IDecisionQuery
return __result; \
\

virtual QueryAnswerType ShouldAttack(CBaseBot* me, const CKnownEntity* them) override
QueryAnswerType ShouldAttack(CBaseBot* me, const CKnownEntity* them) override
{
PROPAGATE_DECISION_WITH_2ARGS(ShouldAttack, me, them);
}

virtual QueryAnswerType ShouldSeekAndDestroy(CBaseBot* me, const CKnownEntity* them) override
QueryAnswerType ShouldSeekAndDestroy(CBaseBot* me, const CKnownEntity* them) override
{
PROPAGATE_DECISION_WITH_2ARGS(ShouldSeekAndDestroy, me, them);
}

virtual QueryAnswerType ShouldPickup(CBaseBot* me, edict_t* item) override
QueryAnswerType ShouldPickup(CBaseBot* me, edict_t* item) override
{
PROPAGATE_DECISION_WITH_2ARGS(ShouldPickup, me, item);
}

virtual QueryAnswerType ShouldHurry(CBaseBot* me) override
QueryAnswerType ShouldHurry(CBaseBot* me) override
{
PROPAGATE_DECISION_WITH_1ARG(ShouldHurry, me);
}

virtual QueryAnswerType ShouldRetreat(CBaseBot* me) override
QueryAnswerType ShouldRetreat(CBaseBot* me) override
{
PROPAGATE_DECISION_WITH_1ARG(ShouldRetreat, me);
}

virtual QueryAnswerType ShouldUse(CBaseBot* me, edict_t* object) override
QueryAnswerType ShouldUse(CBaseBot* me, edict_t* object) override
{
PROPAGATE_DECISION_WITH_2ARGS(ShouldUse, me, object);
}

virtual QueryAnswerType ShouldFreeRoam(CBaseBot* me) override
QueryAnswerType ShouldFreeRoam(CBaseBot* me) override
{
PROPAGATE_DECISION_WITH_1ARG(ShouldFreeRoam, me);
}

virtual QueryAnswerType IsBlocker(CBaseBot* me, edict_t* blocker, const bool any = false) override
QueryAnswerType IsBlocker(CBaseBot* me, edict_t* blocker, const bool any = false) override
{
PROPAGATE_DECISION_WITH_3ARGS(IsBlocker, me, blocker, any);
}

virtual const CKnownEntity* SelectTargetThreat(CBaseBot* me, const CKnownEntity* threat1, const CKnownEntity* threat2) override
const CKnownEntity* SelectTargetThreat(CBaseBot* me, const CKnownEntity* threat1, const CKnownEntity* threat2) override
{
const CKnownEntity* result = nullptr;

Expand All @@ -354,7 +354,7 @@ class AITaskManager : public IEventListener, public IDecisionQuery
return result;
}

virtual Vector GetTargetAimPos(CBaseBot* me, edict_t* entity, CBaseExtPlayer* player = nullptr) override
Vector GetTargetAimPos(CBaseBot* me, edict_t* entity, CBaseExtPlayer* player = nullptr) override
{
Vector result = vec3_origin;

Expand All @@ -379,6 +379,11 @@ class AITaskManager : public IEventListener, public IDecisionQuery
return result;
}

QueryAnswerType IsReady(CBaseBot* me) override
{
PROPAGATE_DECISION_WITH_1ARG(IsReady, me);
}

private:
friend class AITask<BotClass>;

Expand Down Expand Up @@ -563,7 +568,7 @@ class AITask : public IEventListener, public IDecisionQuery
* @brief The task that comes after this
* @return NULL for none or pointer to a task that will be added after this task
*/
virtual AITask<BotClass>* InitialNextTask() { return nullptr; }
virtual AITask<BotClass>* InitialNextTask(AITask<BotClass>* bot) { return nullptr; }

AITask<BotClass>* GetPreviousTask() const { return m_prevTask; }
AITask<BotClass>* GetNextTask() const { return m_nextTask; }
Expand Down
9 changes: 9 additions & 0 deletions extension/bot/tf2/tasks/engineer/tf2bot_engineer_main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include <extension.h>
#include <bot/tf2/tf2bot.h>
#include <bot/tf2/tasks/tf2bot_scenario.h>
#include "tf2bot_engineer_main.h"

TaskResult<CTF2Bot> CTF2BotEngineerMainTask::OnTaskUpdate(CTF2Bot* bot)
{
return Continue();
}
15 changes: 15 additions & 0 deletions extension/bot/tf2/tasks/engineer/tf2bot_engineer_main.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#ifndef NAVBOT_TF2BOT_TASKS_ENGINEER_MAIN_H_
#define NAVBOT_TF2BOT_TASKS_ENGINEER_MAIN_H_

class CTF2Bot;

class CTF2BotEngineerMainTask : public AITask<CTF2Bot>
{
public:

TaskResult<CTF2Bot> OnTaskUpdate(CTF2Bot* bot) override;

const char* GetName() const override { return "EngineerMain"; }
};

#endif // !NAVBOT_TF2BOT_TASKS_ENGINEER_MAIN_H_
52 changes: 33 additions & 19 deletions extension/bot/tf2/tasks/scenario/mvm/tf2bot_mvm_idle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,24 +33,13 @@ TaskResult<CTF2Bot> CTF2BotMvMIdleTask::OnTaskUpdate(CTF2Bot* bot)
return PauseFor(new CTF2BotMvMUpgradeTask, "Going to use an upgrade station!");
}

if (m_isready)
if (!bot->GetBehaviorInterface()->IsReady(bot) == ANSWER_YES)
{
// Bot is not ready yet, toggle ready mode
if (!bot->TournamentIsReady() && tf2lib::MVM_ShouldBotsReadyUp())
{
bot->ToggleTournamentReadyStatus(true);
}
}
else
{
CTFNavArea* area = static_cast<CTFNavArea*>(bot->GetLastKnownNavArea());

if (area && area->HasMVMAttributes(CTFNavArea::MVMNAV_FRONTLINES))
{
// bot is at a frontline area
m_isready = true;
}
}
}

// TO-DO: Move to defensive positions near the robot spawn
Expand All @@ -62,13 +51,6 @@ TaskResult<CTF2Bot> CTF2BotMvMIdleTask::OnTaskUpdate(CTF2Bot* bot)

TaskResult<CTF2Bot> CTF2BotMvMIdleTask::OnTaskResume(CTF2Bot* bot, AITask<CTF2Bot>* pastTask)
{
CTF2BotMvMUpgradeTask* upgradetask = dynamic_cast<CTF2BotMvMUpgradeTask*>(pastTask);

if (upgradetask != nullptr)
{
m_isready = false; // we just used an upgrade station, go back to the frontlines
}

return Continue();
}

Expand All @@ -81,3 +63,35 @@ TaskEventResponseResult<CTF2Bot> CTF2BotMvMIdleTask::OnMoveToSuccess(CTF2Bot* bo
{
return TryContinue();
}

QueryAnswerType CTF2BotMvMIdleTask::IsReady(CBaseBot* me)
{
CTF2Bot* tf2bot = static_cast<CTF2Bot*>(me);
auto& manager = tf2bot->GetUpgradeManager();

if (!manager.IsManagerReady() || manager.ShouldGoToAnUpgradeStation())
{
return ANSWER_NO;
}

auto myclass = tf2bot->GetMyClassType();

if (myclass == TeamFortress2::TFClass_Medic)
{
// medic logic here
// check uber%
}
else if (myclass == TeamFortress2::TFClass_Engineer)
{
// all buildings must be level 3 and health, also check their position
}

CTFNavArea* area = static_cast<CTFNavArea*>(me->GetLastKnownNavArea());

if (area && !area->HasMVMAttributes(CTFNavArea::MVMNAV_FRONTLINES))
{
return ANSWER_NO;
}

return ANSWER_YES;
}
4 changes: 2 additions & 2 deletions extension/bot/tf2/tasks/scenario/mvm/tf2bot_mvm_idle.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ class CTF2BotMvMIdleTask : public AITask<CTF2Bot>
CTF2BotMvMIdleTask()
{
m_goal.Init();
m_isready = false;
}

TaskResult<CTF2Bot> OnTaskStart(CTF2Bot* bot, AITask<CTF2Bot>* pastTask) override;
Expand All @@ -24,11 +23,12 @@ class CTF2BotMvMIdleTask : public AITask<CTF2Bot>
TaskEventResponseResult<CTF2Bot> OnMoveToSuccess(CTF2Bot* bot, CPath* path) override;

const char* GetName() const override { return "MvMIdle"; }

QueryAnswerType IsReady(CBaseBot* me) override;
private:
CMeshNavigator m_nav;
Vector m_goal;
CountdownTimer m_repathtimer;
bool m_isready; // true if the bot is ready and should ready up when possible
};

#endif // !NAVBOT_TF2BOT_TASK_MVM_IDLE_H_
2 changes: 1 addition & 1 deletion extension/bot/tf2/tasks/tf2bot_maintask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
#undef min
#undef clamp

AITask<CTF2Bot>* CTF2BotMainTask::InitialNextTask()
AITask<CTF2Bot>* CTF2BotMainTask::InitialNextTask(CTF2Bot* bot)
{
return new CTF2BotTacticalTask;
}
Expand Down
2 changes: 1 addition & 1 deletion extension/bot/tf2/tasks/tf2bot_maintask.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class CTF2BotSensor;
class CTF2BotMainTask : public AITask<CTF2Bot>
{
public:
AITask<CTF2Bot>* InitialNextTask() override;
AITask<CTF2Bot>* InitialNextTask(CTF2Bot* bot) override;
TaskResult<CTF2Bot> OnTaskUpdate(CTF2Bot* bot) override;

TaskEventResponseResult<CTF2Bot> OnTestEventPropagation(CTF2Bot* bot) override;
Expand Down
37 changes: 25 additions & 12 deletions extension/bot/tf2/tasks/tf2bot_scenario.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,47 @@
#include "bot/tf2/tf2bot.h"
#include <bot/tf2/tasks/scenario/tf2bot_map_ctf.h>
#include <bot/tf2/tasks/medic/tf2bot_medic_main_task.h>
#include <bot/tf2/tasks/engineer/tf2bot_engineer_main.h>
#include "scenario/mvm/tf2bot_mvm_idle.h"
#include "tf2bot_scenario.h"

TaskResult<CTF2Bot> CTF2BotScenarioTask::OnTaskUpdate(CTF2Bot* bot)
AITask<CTF2Bot>* CTF2BotScenarioTask::InitialNextTask(CTF2Bot* bot)
{
auto tf2mod = CTeamFortress2Mod::GetTF2Mod();
auto gm = tf2mod->GetCurrentGameMode();
auto myclass = bot->GetMyClassType();

if (myclass == TeamFortress2::TFClass_Medic)
if (gm == TeamFortress2::GameModeType::GM_MVM)
{
return SwitchTo(new CTF2BotMedicMainTask, "Starting Medic Behavior");
return new CTF2BotMvMIdleTask; // In MvM, all bots start with this
}

switch (gm)
{
case TeamFortress2::GameModeType::GM_CTF:

switch (myclass)
{
auto newtask = new CTF2BotCTFMonitorTask;
return SwitchTo(newtask, "Starting CTF Behavior");
case TeamFortress2::TFClass_Sniper:
break; // TODO
case TeamFortress2::TFClass_Medic:
return new CTF2BotMedicMainTask;
case TeamFortress2::TFClass_Spy:
break; // TODO
case TeamFortress2::TFClass_Engineer:
return new CTF2BotEngineerMainTask;
default:
break;
}
case TeamFortress2::GameModeType::GM_MVM:

switch (gm)
{
return SwitchTo(new CTF2BotMvMIdleTask, "Starting MvM Behavior");
}
case TeamFortress2::GameModeType::GM_CTF:
return new CTF2BotCTFMonitorTask;
default:
break;
}

return nullptr;
}

TaskResult<CTF2Bot> CTF2BotScenarioTask::OnTaskUpdate(CTF2Bot* bot)
{
return Continue();
}
1 change: 1 addition & 0 deletions extension/bot/tf2/tasks/tf2bot_scenario.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class CTF2Bot;
class CTF2BotScenarioTask : public AITask<CTF2Bot>
{
public:
AITask<CTF2Bot>* InitialNextTask(CTF2Bot* bot) override;
TaskResult<CTF2Bot> OnTaskUpdate(CTF2Bot* bot) override;

const char* GetName() const override { return "Scenario"; }
Expand Down
2 changes: 1 addition & 1 deletion extension/bot/tf2/tasks/tf2bot_tactical.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

static ConVar sm_navbot_tf_ai_low_health_percent("sm_navbot_tf_ai_low_health_percent", "0.5", FCVAR_GAMEDLL, "If the bot health is below this percentage, the bot should retreat for health", true, 0.0f, true, 1.0f);

AITask<CTF2Bot>* CTF2BotTacticalTask::InitialNextTask()
AITask<CTF2Bot>* CTF2BotTacticalTask::InitialNextTask(CTF2Bot* bot)
{
return new CTF2BotScenarioTask;
}
Expand Down
2 changes: 1 addition & 1 deletion extension/bot/tf2/tasks/tf2bot_tactical.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class CTF2Bot;
class CTF2BotTacticalTask : public AITask<CTF2Bot>
{
public:
AITask<CTF2Bot>* InitialNextTask() override;
AITask<CTF2Bot>* InitialNextTask(CTF2Bot* bot) override;
TaskResult<CTF2Bot> OnTaskStart(CTF2Bot* bot, AITask<CTF2Bot>* pastTask) override;
TaskResult<CTF2Bot> OnTaskUpdate(CTF2Bot* bot) override;
TaskResult<CTF2Bot> OnTaskResume(CTF2Bot* bot, AITask<CTF2Bot>* pastTask) override;
Expand Down

0 comments on commit 8a459d1

Please sign in to comment.