Skip to content

Commit 55d7995

Browse files
Vauffxen-000
authored andcommitted
Change GoToIntermission detour to a virtual hook
For whatever reason, the signature is extremely unstable, and has been breaking nearly every CS2 update
1 parent e098b5a commit 55d7995

File tree

6 files changed

+40
-19
lines changed

6 files changed

+40
-19
lines changed

gamedata/cs2fixes.games.txt

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -316,14 +316,6 @@
316316
"linux" "\x55\x48\x89\xE5\x41\x55\x41\x54\x48\x83\xEC\x10\x4C\x8B\x26\x4D\x85\xE4\x74\x2A"
317317
}
318318

319-
// "Going to intermission...\n"
320-
"CCSGameRules_GoToIntermission"
321-
{
322-
"library" "server"
323-
"windows" "\x48\x8B\xC4\x55\x53\x56\x57\x41\x56\x48\x8D\xA8\x2A\x2A\x2A\x2A\x48\x81\xEC\x2A\x2A\x2A\x2A\x0F\x29\x78"
324-
"linux" "\x55\x31\xC0\x48\x89\xE5\x41\x57\x41\x56\x41\x89\xF6\x41\x55\x41\x54\x49\x89\xFC\x53"
325-
}
326-
327319
// Return value of this function is used to determine whether "NETWORK_DISCONNECT_REJECT_SERVERFULL to %s: Cannot get free client\n" gets printed
328320
"GetFreeClient"
329321
{
@@ -444,6 +436,11 @@
444436
"windows" "20"
445437
"linux" "21"
446438
}
439+
"CCSGameRules_GoToIntermission"
440+
{
441+
"windows" "128"
442+
"linux" "129"
443+
}
447444
}
448445
"Patches"
449446
{

src/cs2fixes.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ SH_DECL_MANUALHOOK2_void(CreateWorkshopMapGroup, 0, 0, 0, const char*, const CUt
116116
SH_DECL_MANUALHOOK1(OnTakeDamage_Alive, 0, 0, 0, bool, CTakeDamageInfoContainer *);
117117
SH_DECL_MANUALHOOK1_void(CheckMovingGround, 0, 0, 0, double);
118118
SH_DECL_HOOK2(IGameEventManager2, LoadEventsFromFile, SH_NOATTRIB, 0, int, const char *, bool);
119+
SH_DECL_MANUALHOOK2(GoToIntermission, 0, 0, 0, int64_t*, int64_t, char);
119120

120121
CS2Fixes g_CS2Fixes;
121122

@@ -137,6 +138,7 @@ int g_iCreateWorkshopMapGroupId = -1;
137138
int g_iOnTakeDamageAliveId = -1;
138139
int g_iCheckMovingGroundId = -1;
139140
int g_iLoadEventsFromFileId = -1;
141+
int g_iGoToIntermissionId = -1;
140142

141143
CGameEntitySystem *GameEntitySystem()
142144
{
@@ -189,7 +191,10 @@ bool CS2Fixes::Load(PluginId id, ISmmAPI *ismm, char *error, size_t maxlen, bool
189191
int offset = g_GameConfig->GetOffset("IGameTypes_CreateWorkshopMapGroup");
190192
SH_MANUALHOOK_RECONFIGURE(CreateWorkshopMapGroup, offset, 0, 0);
191193

192-
SH_ADD_HOOK(IServerGameDLL, GameFrame, g_pSource2Server, SH_MEMBER(this, &CS2Fixes::Hook_GameFramePost), true);
194+
offset = g_GameConfig->GetOffset("CCSGameRules_GoToIntermission");
195+
SH_MANUALHOOK_RECONFIGURE(GoToIntermission, offset, 0, 0);
196+
197+
SH_ADD_HOOK(IServerGameDLL, GameFrame, g_pSource2Server, SH_MEMBER(this, &CS2Fixes::Hook_GameFramePost), true);
193198
SH_ADD_HOOK(IServerGameDLL, GameServerSteamAPIActivated, g_pSource2Server, SH_MEMBER(this, &CS2Fixes::Hook_GameServerSteamAPIActivated), false);
194199
SH_ADD_HOOK(IServerGameDLL, GameServerSteamAPIDeactivated, g_pSource2Server, SH_MEMBER(this, &CS2Fixes::Hook_GameServerSteamAPIDeactivated), false);
195200
SH_ADD_HOOK(IServerGameDLL, ApplyGameSettings, g_pSource2Server, SH_MEMBER(this, &CS2Fixes::Hook_ApplyGameSettings), false);
@@ -356,6 +361,9 @@ bool CS2Fixes::Unload(char *error, size_t maxlen)
356361
SH_REMOVE_HOOK_ID(g_iOnTakeDamageAliveId);
357362
SH_REMOVE_HOOK_ID(g_iCheckMovingGroundId);
358363

364+
if (g_iGoToIntermissionId != -1)
365+
SH_REMOVE_HOOK_ID(g_iGoToIntermissionId);
366+
359367
ConVar_Unregister();
360368

361369
g_CommandList.Purge();
@@ -868,6 +876,24 @@ void CS2Fixes::Hook_CreateWorkshopMapGroup(const char* name, const CUtlStringLis
868876
RETURN_META(MRES_IGNORED);
869877
}
870878

879+
void CS2Fixes::CreateGoToIntermissionHook()
880+
{
881+
g_iGoToIntermissionId = SH_ADD_MANUALVPHOOK(GoToIntermission, g_pGameRules, SH_MEMBER(this, &CS2Fixes::Hook_GoToIntermission), false);
882+
}
883+
884+
void CS2Fixes::RemoveGoToIntermissionHook()
885+
{
886+
SH_REMOVE_HOOK_ID(g_iGoToIntermissionId);
887+
}
888+
889+
int64_t* CS2Fixes::Hook_GoToIntermission(int64_t unk1, char unk2)
890+
{
891+
if (!g_pMapVoteSystem->IsIntermissionAllowed())
892+
RETURN_META_VALUE(MRES_SUPERCEDE, nullptr);
893+
894+
RETURN_META_NOREF(MRES_IGNORED, int64_t*);
895+
}
896+
871897
bool g_bDropMapWeapons = false;
872898

873899
FAKE_BOOL_CVAR(cs2f_drop_map_weapons, "Whether to force drop map-spawned weapons on death", g_bDropMapWeapons, false, false)

src/cs2fixes.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ class CS2Fixes : public ISmmPlugin, public IMetamodListener
6464
void Hook_StartupServer(const GameSessionConfiguration_t& config, ISource2WorldSession*, const char*);
6565
void Hook_ApplyGameSettings(KeyValues* pKV);
6666
void Hook_CreateWorkshopMapGroup(const char* name, const CUtlStringList& mapList);
67+
void CreateGoToIntermissionHook();
68+
void RemoveGoToIntermissionHook();
69+
int64_t* Hook_GoToIntermission(int64_t unk1, char unk2);
6770
bool Hook_OnTakeDamage_Alive(CTakeDamageInfoContainer *pInfoContainer);
6871
void Hook_CheckMovingGround(double frametime);
6972
int Hook_LoadEventsFromFile(const char *filename, bool bSearchAll);

src/detours.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ DECLARE_DETOUR(ProcessMovement, Detour_ProcessMovement);
7272
DECLARE_DETOUR(ProcessUsercmds, Detour_ProcessUsercmds);
7373
DECLARE_DETOUR(CGamePlayerEquip_InputTriggerForAllPlayers, Detour_CGamePlayerEquip_InputTriggerForAllPlayers);
7474
DECLARE_DETOUR(CGamePlayerEquip_InputTriggerForActivatedPlayer, Detour_CGamePlayerEquip_InputTriggerForActivatedPlayer);
75-
DECLARE_DETOUR(CCSGameRules_GoToIntermission, Detour_CCSGameRules_GoToIntermission);
7675
DECLARE_DETOUR(GetFreeClient, Detour_GetFreeClient);
7776
DECLARE_DETOUR(CCSPlayerPawn_GetMaxSpeed, Detour_CCSPlayerPawn_GetMaxSpeed);
7877

@@ -508,14 +507,6 @@ void FASTCALL Detour_CGamePlayerEquip_InputTriggerForActivatedPlayer(CGamePlayer
508507
CGamePlayerEquip_InputTriggerForActivatedPlayer(pEntity, pInput);
509508
}
510509

511-
int64_t* FASTCALL Detour_CCSGameRules_GoToIntermission(int64_t unk1, char unk2)
512-
{
513-
if (!g_pMapVoteSystem->IsIntermissionAllowed())
514-
return nullptr;
515-
516-
return CCSGameRules_GoToIntermission(unk1, unk2);
517-
}
518-
519510
CServerSideClient* FASTCALL Detour_GetFreeClient(int64_t unk1, const __m128i* unk2, unsigned int unk3, int64_t unk4, char unk5, void* unk6)
520511
{
521512
// Check if there is still unused slots, this should never break so just fall back to original behaviour for ease (we don't have a CServerSideClient constructor)

src/detours.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,5 @@ void FASTCALL Detour_ProcessMovement(CCSPlayer_MovementServices *pThis, void *pM
6262
void *FASTCALL Detour_ProcessUsercmds(CCSPlayerController *pController, CUserCmd *cmds, int numcmds, bool paused, float margin);
6363
void FASTCALL Detour_CGamePlayerEquip_InputTriggerForAllPlayers(CGamePlayerEquip*, InputData_t*);
6464
void FASTCALL Detour_CGamePlayerEquip_InputTriggerForActivatedPlayer(CGamePlayerEquip*, InputData_t*);
65-
int64_t* FASTCALL Detour_CCSGameRules_GoToIntermission(int64_t unk1, char unk2);
6665
CServerSideClient* FASTCALL Detour_GetFreeClient(int64_t unk1, const __m128i* unk2, unsigned int unk3, int64_t unk4, char unk5, void* unk6);
6766
float FASTCALL Detour_CCSPlayerPawn_GetMaxSpeed(CCSPlayerPawn*);

src/entitylistener.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,16 @@ void CEntityListener::OnEntityCreated(CEntityInstance* pEntity)
5151
ExecuteOnce(Patch_GetHammerUniqueId(pEntity));
5252

5353
if (!V_strcmp("cs_gamerules", pEntity->GetClassname()))
54+
{
5455
g_pGameRules = ((CCSGameRulesProxy*)pEntity)->m_pGameRules;
56+
g_CS2Fixes.CreateGoToIntermissionHook();
57+
}
5558
}
5659

5760
void CEntityListener::OnEntityDeleted(CEntityInstance* pEntity)
5861
{
62+
if (!V_strcmp("cs_gamerules", pEntity->GetClassname()))
63+
g_CS2Fixes.RemoveGoToIntermissionHook();
5964
}
6065

6166
void CEntityListener::OnEntityParentChanged(CEntityInstance* pEntity, CEntityInstance* pNewParent)

0 commit comments

Comments
 (0)