diff --git a/src/core/init.cpp b/src/core/init.cpp index 5d106a71..9cb497b8 100644 --- a/src/core/init.cpp +++ b/src/core/init.cpp @@ -138,6 +138,7 @@ #include "game/server/movehelper_server.h" #include "game/server/player.h" #include "game/server/player_command.h" +#include "game/server/ai_basenpc.h" #include "game/server/physics_main.h" #include "game/server/vscript_server.h" #endif // !CLIENT_DLL @@ -668,6 +669,7 @@ void DetourRegister() // Register detour classes to be searched and hooked. REGISTER(VBaseEntity); REGISTER(VBaseAnimating); REGISTER(VPlayer); + REGISTER(VAI_BaseNPC); REGISTER(VPlayerMove); #endif // !CLIENT_DLL diff --git a/src/game/CMakeLists.txt b/src/game/CMakeLists.txt index 00f6bcef..b74f82d9 100644 --- a/src/game/CMakeLists.txt +++ b/src/game/CMakeLists.txt @@ -82,6 +82,7 @@ add_sources( SOURCE_GROUP "AI" "server/ai_node.h" "server/ai_utility.cpp" "server/ai_utility.h" + "server/ai_task.cpp" "server/ai_task.h" "server/ai_schedule.cpp" "server/ai_schedule.h" diff --git a/src/game/server/ai_basenpc.cpp b/src/game/server/ai_basenpc.cpp index b35a2c79..8362f468 100644 --- a/src/game/server/ai_basenpc.cpp +++ b/src/game/server/ai_basenpc.cpp @@ -4,4 +4,25 @@ // //=============================================================================// #include "ai_basenpc.h" +#include "game/shared/util_shared.h" + +static ConVar ai_debug_tasks("ai_debug_tasks", "0", FCVAR_DEVELOPMENTONLY, "Debug the attempted tasks"); + +void CAI_BaseNPC::_TaskFail(CAI_BaseNPC* thisptr, const AI_TaskFailureCode_t code) +{ + if (ai_debug_tasks.GetBool()) + { + thisptr->m_failText = TaskFailureToString(code); + thisptr->m_failedSchedule = thisptr->GetCurSchedule(); + + Msg(eDLL_T::SERVER, "TaskFail -> %s (%s)\n", thisptr->m_failText, UTIL_GetEntityScriptInfo(thisptr)); + } + + CAI_BaseNPC__TaskFail(thisptr, code); +} + +void VAI_BaseNPC::Detour(const bool bAttach) const +{ + DetourSetup(&CAI_BaseNPC__TaskFail, &CAI_BaseNPC::_TaskFail, bAttach); +} diff --git a/src/game/server/ai_basenpc.h b/src/game/server/ai_basenpc.h index 79c2c097..e309bf9c 100644 --- a/src/game/server/ai_basenpc.h +++ b/src/game/server/ai_basenpc.h @@ -91,6 +91,17 @@ class CAI_BaseNPC : public CBaseCombatCharacter, public IAI_BehaviorBridge { public: + // Hook statics + static void _TaskFail(CAI_BaseNPC* thisptr, const AI_TaskFailureCode_t code); + +public: + //----------------------------------------------------- + // + // Schedules & tasks + // + //----------------------------------------------------- + inline CAI_Schedule* GetCurSchedule() const { return m_pSchedule; } + float GetTimeScheduleStarted() const { return m_ScheduleState.timeStarted; } private: int m_threadedPostProcessJob; @@ -431,4 +442,24 @@ private: static_assert(sizeof(CAI_BaseNPC) == 0x6648); +inline void(*CAI_BaseNPC__TaskFail)(CAI_BaseNPC* thisptr, const AI_TaskFailureCode_t code); + +/////////////////////////////////////////////////////////////////////////////// +class VAI_BaseNPC : public IDetour +{ + virtual void GetAdr(void) const + { + LogFunAdr("CAI_BaseNPC::TaskFail", CAI_BaseNPC__TaskFail); + } + virtual void GetFun(void) const + { + g_GameDll.FindPatternSIMD("48 89 5C 24 ?? 57 48 83 EC ?? 48 8B D9 48 8B FA 48 81 C1 ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 83 FF").GetPtr(CAI_BaseNPC__TaskFail); + } + virtual void GetVar(void) const { } + virtual void GetCon(void) const { } + virtual void Detour(const bool bAttach) const; +}; +/////////////////////////////////////////////////////////////////////////////// + + #endif // AI_BASENPC_H diff --git a/src/game/server/ai_task.cpp b/src/game/server/ai_task.cpp new file mode 100644 index 00000000..2f7cfc1e --- /dev/null +++ b/src/game/server/ai_task.cpp @@ -0,0 +1,59 @@ +//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. =======// +// +// Purpose: Sets up the tasks for default AI. +// +// $NoKeywords: $ +//=============================================================================// +//#include "ai_basenpc.h" +#include "ai_task.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +static const char* const s_ppszTaskFailureText[NUM_FAIL_CODES] = +{ + "No failure", // NO_TASK_FAILURE + "No target", // FAIL_NO_TARGET + "Weapon owned by someone else", // FAIL_WEAPON_OWNED + "Item doesn't exist", // FAIL_ITEM_NO_FIND + "No hint node", // FAIL_NO_HINT_NODE + "Schedule not found", // FAIL_SCHEDULE_NOT_FOUND + "Don't have an enemy", // FAIL_NO_ENEMY + "Found no near node", // FAIL_NO_NEAR_NODE + "Found no back away node", // FAIL_NO_BACKAWAY_NODE + "Couldn't find cover", // FAIL_NO_COVER + "Couldn't find flank", // FAIL_NO_FLANK + "Couldn't find shoot position", // FAIL_NO_SHOOT + "Don't have a route", // FAIL_NO_ROUTE + "Don't have a route: no goal", // FAIL_NO_ROUTE_GOAL + "Don't have a route: blocked", // FAIL_NO_ROUTE_BLOCKED + "Don't have a route: illegal move", // FAIL_NO_ROUTE_ILLEGAL + "Couldn't walk to target", // FAIL_NO_WALK + "Don't have LOS", // FAIL_NO_LOS + "Node already locked", // FAIL_ALREADY_LOCKED + "No sound present", // FAIL_NO_SOUND + "Bad activity", // FAIL_BAD_ACTIVITY + "No goal entity", // FAIL_NO_GOAL + "No player", // FAIL_NO_PLAYER + "Can't reach any nodes", // FAIL_NO_REACHABLE_NODE + "No AI Network to use", // FAIL_NO_AI_NETWORK + "No start position", // FAIL_NO_START_POSITION + "Bad position to target", // FAIL_BAD_POSITION + "Route destination no longer valid", // FAIL_BAD_PATH_GOAL + "Stuck on top of something", // FAIL_STUCK_ONTOP + "Item has been taken", // FAIL_ITEM_TAKEN + "Too frozen", // FAIL_FROZEN + "Animation blocked", // FAIL_ANIMATION_BLOCKED + "Timeout", // FAIL_TIMEOUT + "Detour specific", // FAIL_DETOUR_SPECIFIC +}; + +const char* TaskFailureToString(const AI_TaskFailureCode_t code) +{ + const char* pszResult; + if (code < 0 || code >= NUM_FAIL_CODES) + pszResult = (const char*)code; + else + pszResult = s_ppszTaskFailureText[code]; + return pszResult; +} diff --git a/src/game/server/ai_task.h b/src/game/server/ai_task.h index ec173969..76d15fde 100644 --- a/src/game/server/ai_task.h +++ b/src/game/server/ai_task.h @@ -14,7 +14,7 @@ typedef intp AI_TaskFailureCode_t; //========================================================= -// These are th efailure codes +// These are the failure codes //========================================================= enum AI_BaseTaskFailureCodes_t {