diff --git a/gamedata/srccoop.games.txt b/gamedata/srccoop.games.txt index a09d1f1a..d1965f6f 100644 --- a/gamedata/srccoop.games.txt +++ b/gamedata/srccoop.games.txt @@ -427,6 +427,20 @@ } } } + "CServerGameDLL::GameFrame" + { + "offset" "CServerGameDLL::GameFrame" + "hooktype" "raw" + "return" "void" + "this" "ignore" + "arguments" + { + "simulating" + { + "type" "bool" + } + } + } "CEngineSoundServer::SetPlayerDSP" { "offset" "CEngineSoundServer::SetPlayerDSP" @@ -690,19 +704,6 @@ } } } - "Physics_RunThinkFunctions" - { - "signature" "Physics_RunThinkFunctions" - "callconv" "cdecl" - "return" "void" - "arguments" - { - "simulating" - { - "type" "bool" - } - } - } "CBoneSetup::AccumulatePose" { "signature" "CBoneSetup::AccumulatePose" @@ -872,6 +873,7 @@ "signature" "UTIL_FindClientInPVSGuts" "callconv" "cdecl" "return" "edict" + "this" "ignore" "arguments" { "pEdict" @@ -1062,12 +1064,6 @@ "windows" "\x55\x8B\xEC\x83\xEC\x5C\x56\x57\x8B\xF9\x2A\x2A\x2A\x2A\x2A\x8B\xF0\x85\xF6\x2A\x2A\x2A\x2A\x2A\x2A" "linux" "@_ZN11CWeapon_Tau8FireBeamERKfb" } - "Physics_RunThinkFunctions" - { - // str: "sv_teststepsimulation" (referenced convar) - "windows" "\x55\x8B\xEC\x83\xEC\x08\xA1\x2A\x2A\x2A\x2A\x33\xC5\x89\x45\xFC\xA1\x2A\x2A\x2A\x2A" - "linux" "@_Z25Physics_RunThinkFunctionsb" - } "CAI_ExpresserHost_NPC_DoModifyOrAppendCriteria" { "windows" "\x55\x8B\xEC\x83\xEC\x0C\x53\x56\x8B\x75\x08\x57\xFF\xB6\xA0\x09\x00\x00\x2A\x2A\x2A\x2A\x2A\x8B\x7D\x0C\x83\xC4" @@ -1206,6 +1202,11 @@ "windows" "8" "linux" "8" } + "CServerGameDLL::GameFrame" // CServerGameDLL::GameFrame(bool) + { + "windows" "5" + "linux" "5" + } "CMultiplayRules::FAllowFlashlight" // CMultiplayRules::FAllowFlashlight() { "windows" "56" @@ -1609,12 +1610,6 @@ "windows" "\x55\x8B\xEC\x83\xEC\x0C\x53\x56\x57\xFF\x75\x08" "linux" "@_Z16GlobalEntity_AddPKcS0_12GLOBALESTATE" } - "Physics_RunThinkFunctions" - { - // str: "Trace: %d, contents %d, enumerate %d" (in caller) - "windows" "\x55\x8B\xEC\x51\xA1\x2A\x2A\x2A\x2A\xB9\x2A\x2A\x2A\x2A\x53\x56\x57\x83\x78\x30\x00\xA1" - "linux" "@_Z25Physics_RunThinkFunctionsb" - } "CAI_ExpresserHost_NPC_DoModifyOrAppendCriteria" { "windows" "\x55\x8B\xEC\x83\xEC\x0C\x53\x56\x8B\x75\x08\x57\xFF\xB6\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x8B\x2A\x2A\x83\xC4\x04" // str: "timesincecombat" @@ -1707,6 +1702,11 @@ "windows" "8" "linux" "8" } + "CServerGameDLL::GameFrame" // CServerGameDLL::GameFrame(bool) + { + "windows" "5" + "linux" "5" + } "CMultiplayRules::IsMultiplayer" // CMultiplayRules::IsMultiplayer() { "windows" "34" diff --git a/scripting/include/srccoop/entitypatch.inc b/scripting/include/srccoop/entitypatch.inc index 1c42adbb..177bfd73 100644 --- a/scripting/include/srccoop/entitypatch.inc +++ b/scripting/include/srccoop/entitypatch.inc @@ -223,11 +223,11 @@ public MRESReturn Hook_BaseNPCThinkPost(int _this) } //------------------------------------------------------ -// Physics_RunThinkFunctions - The main physics simulation loop against all entities +// CServerGameDLL::GameFrame // This hook is only active when there are no real players on the server! // Its main purpose is to ensure NPCs can always find a valid player pointer when thinking. //------------------------------------------------------ -public MRESReturn Hook_Physics_RunThinkFunctions(DHookParam hParams) +public MRESReturn Hook_GameFrame(DHookParam hParams) { return MRES_Supercede; } diff --git a/scripting/include/srccoop/globals.inc b/scripting/include/srccoop/globals.inc index 37958ee7..aa6ddfdd 100644 --- a/scripting/include/srccoop/globals.inc +++ b/scripting/include/srccoop/globals.inc @@ -155,7 +155,8 @@ DynamicDetour hkBaseNpcUpdateSleepState; #endif #if defined ENTPATCH_NPC_THINK_LOCALPLAYER -DynamicDetour hkPhysics_RunThinkFunctions; +int g_iGameFrameHookId = INVALID_HOOK_ID; +DynamicHook hkGameFrame; #endif #if defined ENTPATCH_BM_DISSOLVE diff --git a/scripting/srccoop.sp b/scripting/srccoop.sp index ba4be9f0..aa258bcf 100644 --- a/scripting/srccoop.sp +++ b/scripting/srccoop.sp @@ -44,6 +44,12 @@ void LoadGameData() if (hkLevelInit.HookRaw(Hook_Pre, IServerGameDLL.Get().GetAddress(), Hook_OnLevelInit) == INVALID_HOOK_ID) SetFailState("Could not hook CServerGameDLL::LevelInit"); + #if defined ENTPATCH_NPC_THINK_LOCALPLAYER + LoadDHookVirtual(pGameConfig, hkGameFrame, "CServerGameDLL::GameFrame"); + if ((g_iGameFrameHookId = hkGameFrame.HookRaw(Hook_Pre, IServerGameDLL.Get().GetAddress(), Hook_GameFrame)) == INVALID_HOOK_ID) + SetFailState("Could not hook CServerGameDLL::GameFrame"); + #endif + LoadDHookVirtual(pGameConfig, hkChangeTeam, "CBasePlayer::ChangeTeam"); LoadDHookVirtual(pGameConfig, hkShouldCollide, "CBaseEntity::ShouldCollide"); LoadDHookVirtual(pGameConfig, hkPlayerSpawn, "CBasePlayer::Spawn"); @@ -164,10 +170,6 @@ void LoadGameData() LoadDHookDetour(pGameConfig, hkPickup_ForcePlayerToDropThisObject, "Pickup_ForcePlayerToDropThisObject", Hook_ForcePlayerToDropThisObject); #endif - #if defined ENTPATCH_NPC_THINK_LOCALPLAYER - LoadDHookDetour(pGameConfig, hkPhysics_RunThinkFunctions, "Physics_RunThinkFunctions", Hook_Physics_RunThinkFunctions); - #endif - #if defined ENTPATCH_BM_DISSOLVE LoadDHookDetour(pGameConfig, hkDissolve, "CBaseAnimating::Dissolve", Hook_Dissolve); #endif @@ -467,8 +469,9 @@ public void OnClientPutInServer(int client) if (!g_iPlayerCount++) { #if defined ENTPATCH_NPC_THINK_LOCALPLAYER - // resume entity thinking - hkPhysics_RunThinkFunctions.Disable(Hook_Pre, Hook_Physics_RunThinkFunctions); + // resume running frames + DynamicHook.RemoveHook(g_iGameFrameHookId); + g_iGameFrameHookId = INVALID_HOOK_ID; #endif } @@ -538,8 +541,8 @@ public void OnClientDisconnect_Post(int client) #if defined ENTPATCH_NPC_THINK_LOCALPLAYER if (!g_iPlayerCount) { - // pause entity thinking - hkPhysics_RunThinkFunctions.Enable(Hook_Pre, Hook_Physics_RunThinkFunctions); + // pause running frames + g_iGameFrameHookId = hkGameFrame.HookRaw(Hook_Pre, IServerGameDLL.Get().GetAddress(), Hook_GameFrame); } #endif }