From 7061de4fcbc238865a9092ec05e762688ad580d5 Mon Sep 17 00:00:00 2001 From: rcnoob Date: Sun, 3 Aug 2025 18:44:48 -0400 Subject: [PATCH 01/16] update submodules --- hl2sdk-manifests | 2 +- sdk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/hl2sdk-manifests b/hl2sdk-manifests index 20b1d6e2..f9558bcc 160000 --- a/hl2sdk-manifests +++ b/hl2sdk-manifests @@ -1 +1 @@ -Subproject commit 20b1d6e20ecc615a44b63543555408a355093de7 +Subproject commit f9558bcc764598cb94c676ea0d0d3870a9b40353 diff --git a/sdk b/sdk index 74ea9343..774d82f5 160000 --- a/sdk +++ b/sdk @@ -1 +1 @@ -Subproject commit 74ea9343746475b148f5f53679516dc9cd2b336b +Subproject commit 774d82f5989211cd0ddbd230ec64b939361efb1d From 3e8df12233fa5c50d325881e016a23db13241c86 Mon Sep 17 00:00:00 2001 From: rcnoob Date: Wed, 6 Aug 2025 14:01:11 -0400 Subject: [PATCH 02/16] attempted fix - fix after 7-28 update - update submodules --- gamedata/cs2fixes.games.txt | 127 ++++++++++++++++-------------------- sdk | 2 +- src/addresses.cpp | 2 - src/addresses.h | 2 - src/detours.cpp | 23 +++---- src/detours.h | 2 +- 6 files changed, 68 insertions(+), 90 deletions(-) diff --git a/gamedata/cs2fixes.games.txt b/gamedata/cs2fixes.games.txt index d8e7d44d..049578dd 100644 --- a/gamedata/cs2fixes.games.txt +++ b/gamedata/cs2fixes.games.txt @@ -9,22 +9,8 @@ "TryPlayerMove" { "library" "server" - "windows" "\x48\x8B\xC4\x4C\x89\x48\x20\x4C\x89\x40\x18\x48\x89\x50\x10\x48\x89\x48\x08\x55\x53\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x8D\xA8\xE8\xFD\xFF\xFF\x48\x81\xEC\xD8\x02\x00\x00\x0F\x29\x70\xA8\x45\x33\xE4" - "linux" "\x48\xB8\x00\x00\x00\x00\xFF\xFF\xFF\xFF\x55\x66\x0F\xEF\xC0" - } - //https://github.com/KZGlobalTeam/cs2kz-metamod/blob/743d50e1622d5354b1848f63b8b69ffe90ee744e/gamedata/cs2kz-core.games.txt#L43C4-L48C5 - "InitPlayerMovementTraceFilter" - { - "library" "server" - "windows" "\x48\x89\x5C\x24\x08\x48\x89\x74\x24\x10\x57\x48\x83\xEC\x20\x0F\xB6\x41\x37\x48" - "linux" "\x55\xB8\x2A\x2A\x2A\x2A\x48\x89\xE5\x41\x55\x41\x54\x49\x89\xF4\x53\x48\x89\xFB\x48\x83\xEC\x2A\x66\x89\x47\x2A\x48\x8D\x05\x2A\x2A\x2A\x2A\x88\x4F\x2A\x48\x89\x07\x0F\xB7\x47\x2A\x48\x89\x57\x2A\x48\xC7\x47\x2A\x2A\x2A\x2A\x2A\x48\xC7\x47\x2A\x2A\x2A\x2A\x2A\x66\x25\x2A\x2A\x48\xC7\x47\x2A\x2A\x2A\x2A\x2A\x83\xC8\x2A\x48\xC7\x47\x2A\x2A\x2A\x2A\x2A\xC7\x47\x2A\x2A\x2A\x2A\x2A\x66\x89\x47\x2A\x48\x89\xF7\xE8\x2A\x2A\x2A\x2A\x31" - } - // search for "CCSBot::BendLineOfSight". should find 1 function, CGameTrace::Init is called in there right after this string is referenced with an 80 byte parameter. - "InitGameTrace" - { - "library" "server" - "windows" "\x48\x89\x5C\x24\x08\x57\x48\x83\xEC\x20\x48\x8B\xD9\x33\xFF\x48\x8B\x0D\x2A\x2A\x2A\x2A\x48\x85\xC9" - "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x41\x54\x53\x48\x89\xFB\x48\x81\xEC\xA8\x00\x00\x00\x4C\x8B\x25\x2A\x2A\x2A\x2A\x4D\x85\xE4" + "windows" "\x48\x8B\xC4\x4C\x89\x48\x20\x4C\x89\x40\x18\x48\x89\x50\x10\x48\x89\x48\x08\x55\x53\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x8D\xA8\x98\xFC\xFF\xFF" + "linux" "\x55\x66\x0F\xEF\xC0\x48\x89\xE5\x41\x57\x49\x89\xF7\x41\x56\x41\x55\x49\x89\xD5" } //https://github.com/KZGlobalTeam/cs2kz-metamod/blob/f4ba43bd44dc3300bb78ca20006174935ba7964f/gamedata/cs2kz-core.games.txt#L217C4-L224C5 // sub_18061AF90(a1, a2, ((a1 + 48) + 864i64) & 1); <- this one @@ -32,8 +18,8 @@ "CategorizePosition" { "library" "server" - "windows" "\x40\x55\x56\x57\x41\x54\x48\x8D\xAC\x24\x28\xFE\xFF\xFF" - "linux" "\x48\xB8\x00\x00\x00\x00\xFF\xFF\xFF\xFF\x55\x48\x89\xE5\x41\x57\x41\x89\xD7\x41\x56\x4C\x8D\xB5\x50" + "windows" "\x40\x55\x56\x57\x41\x55\x48\x8D\xAC\x24\x18\xFE\xFF\xFF" + "linux" "\x55\x66\x0F\xEF\xC0\x48\x89\xE5\x41\x57\x41\x56\x48\x8D\x85\x2A\x2A\x2A\x2A\x41\x55" } // Function with 5 arguments next to sv_walkable_normal references "TracePlayerBBox" @@ -53,8 +39,8 @@ "CCSPlayerController_SwitchTeam" { "library" "server" - "windows" "\x40\x56\x57\x48\x81\xEC\x2A\x2A\x2A\x2A\x48\x8B\xF9\x8B\xF2\x8B\xCA" - "linux" "\x55\x48\x89\xE5\x41\x55\x49\x89\xFD\x89\xF7" + "windows" "\x40\x53\x57\x48\x81\xEC\x2A\x2A\x2A\x2A\x48\x8B\xD9\x8B\xFA" + "linux" "\x55\x48\x89\xE5\x41\x54\x49\x89\xFC\x89\xF7" } // Called right after "Removed %s(%s)\n" "UTIL_Remove" @@ -67,8 +53,8 @@ "CEntitySystem_AddEntityIOEvent" { "library" "server" - "windows" "\x48\x89\x5C\x24\x08\x48\x89\x74\x24\x18\x57\x48\x83\xEC\x40\x49\x8B\xF1" - "linux" "\x55\x41\xBA\xFF\xFF\xFF\xFF" + "windows" "\x48\x89\x5C\x24\x2A\x4C\x89\x4C\x24\x2A\x48\x89\x4C\x24\x2A\x55\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x83\xEC\x2A\x49\x8B\xF9" + "linux" "\x55\x48\x89\xE5\x41\x55\x49\x89\xCD\x41\x54\x49\x89\xFC" } // "Explode" is passed to this "CEntityInstance_AcceptInput" @@ -80,8 +66,8 @@ "CEntityIdentity_AcceptInput" { "library" "server" - "windows" "\x48\x89\x54\x24\x10\x48\x89\x4C\x24\x08\x55\x53\x56\x57\x41\x55\x41\x56" - "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x4C\x8D\xBD\xD0\xFE\xFF\xFF\x49\x89\xD6\x41\x55\x49\x89\xF5\x41\x54\x49\x89\xCC" + "windows" "\xE8\x2A\x2A\x2A\x2A\xF6\x44\x24\x2A\x2A\x74\x2A\x48\x8B\x05\x2A\x2A\x2A\x2A\x48\x8B\x54\x24\x2A\x48\x8B\x08\x48\x8B\x01\xFF\x50\x2A\x48\x83\xC4\x2A\x5B\xC3\xCC\xCC\xCC\x48\x89\x5C\x24" + "linux" "\x55\x48\x89\xF0\x48\x89\xE5\x41\x57\x49\x89\xFF\x41\x56\x48\x8D\x7D\xC0" } // Literally has "CGameRules::CGameRules constructed" in it "CGameRules_Constructor" @@ -95,56 +81,56 @@ { "library" "server" "windows" "\x48\x83\xEC\x68\x45\x33\xC9" - "linux" "\x55\x45\x31\xC0\x31\xC9\x48\x89\xE5\x41\x54" + "linux" "\x55\x45\x31\xC0\x31\xC9\x48\x89\xE5\x53" } // "commentary_semaphore" is passed to this "CGameEntitySystem_FindEntityByName" { "library" "server" "windows" "\x48\x81\xEC\x88\x2A\x2A\x2A\x4D\x85\xC0" - "linux" "\x48\x85\xD2\x74\x2A\x55\x48\x89\xE5\x41\x54" + "linux" "\x55\x48\x89\xE5\x41\x54\x53\x48\x83\xEC\x2A\x48\x85\xD2" } // "CBaseEntity::TakeDamageOld" "CBaseEntity_TakeDamageOld" { "library" "server" "windows" "\x48\x89\x74\x24\x2A\x57\x48\x81\xEC\x2A\x2A\x2A\x2A\x48\x8B\x41\x2A\x48\x8B\xFA" - "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x41\x54\x49\x89\xFC\x53\x48\x83\xEC\x2A\x4C\x8D\x3D\x2A\x2A\x2A\x2A\x49\x8B\x3F" + "linux" "\x55\x48\x89\xE5\x41\x57\x49\x89\xF7\x41\x56\x41\x55\x41\x54\x53\x48\x89\xFB\x48\x81\xEC\x2A\x2A\x2A\x2A\xF6\x46" } // "Game System %s is defined twice!\n" // Note that this signature points to the instruction with sm_pFirst which is the first qword referenced in the function. "IGameSystem_InitAllSystems_pFirst" { "library" "server" - "windows" "\x48\x8B\x3D\x2A\x2A\x2A\x2A\x48\x85\xFF\x0F\x84\x2A\x2A\x2A\x2A\xBE" + "windows" "\x48\x8B\x1D\x2A\x2A\x2A\x2A\x48\x85\xDB\x0F\x84\x2A\x2A\x2A\x2A\xBD" "linux" "\x4C\x8B\x35\x2A\x2A\x2A\x2A\x4D\x85\xF6\x75\x2A\xE9" } "CBasePlayerController_SetPawn" { "library" "server" - "windows" "\x48\x89\x74\x24\x2A\x55\x41\x54\x41\x55\x41\x56\x41\x57\x48\x8D\x6C\x24\x2A\x48\x81\xEC\x2A\x2A\x2A\x2A\x4C\x8B\xF9" - "linux" "\x55\x48\x89\xE5\x41\x57\x49\x89\xFF\x41\x56\x48\x8D\x3D\x2A\x2A\x2A\x2A\x41\x89\xCE" + "windows" "\x48\x89\x5C\x24\x2A\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x83\xEC\x2A\x4C\x8B\x15" + "linux" "\x55\x48\x8D\x87\x2A\x2A\x2A\x2A\x48\x89\xE5\x41\x57\x45\x89\xC7" } // String: "CNavMesh::GetNearestNavArea" "CNavMesh_GetNearestNavArea" { "library" "server" - "windows" "\x48\x89\x5C\x24\x2A\x48\x89\x54\x24\x2A\x48\x89\x4C\x24\x2A\x55\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x8D\xAC\x24\x2A\x2A\x2A\x2A" - "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x89\xCE\x41\x55\x49\x89\xFD\x41\x54\x48\x8D\x3D\x2A\x2A\x2A\x2A" + "windows" "\x48\x89\x5C\x24\x2A\x44\x89\x4C\x24\x2A\x48\x89\x54\x24\x2A\x48\x89\x4C\x24\x2A\x55\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x8D\xAC\x24" + "linux" "\x55\x48\x8D\x05\x2A\x2A\x2A\x2A\x48\x89\xE5\x41\x57\x4D\x89\xC7" } // Search "Changes's player's model", look for a function containing 'models/%s.vmdl'. Below V_snprintf is the one // This matches 2 functions on linux, however they're literally identical "CBaseModelEntity_SetModel" { "library" "server" - "windows" "\x48\x89\x5C\x24\x2A\x48\x89\x7C\x24\x2A\x55\x48\x8B\xEC\x48\x83\xEC\x50\x48\x8B\xF9\x4C\x8B\xC2" - "linux" "\x55\x48\x89\xF2\x48\x89\xE5\x41\x54\x49\x89\xFC\x48\x8D\x7D\xE0\x48\x83\xEC\x18\x48\x8D\x05\x2A\x2A\x2A\x2A\x48\x8B\x30\x48\x8B\x06" + "windows" "\x40\x53\x48\x83\xEC\x2A\x48\x8B\xD9\x4C\x8B\xC2\x48\x8B\x0D\x2A\x2A\x2A\x2A\x48\x8D\x54\x24\x2A\x48\x8B\x01\xFF\x50\x2A\x48\x8B\x44\x24" + "linux" "\x55\x48\x89\xF2\x48\x89\xE5\x53\x48\x89\xFB\x48\x8D\x7D\x2A\x48\x83\xEC\x2A\x48\x8D\x05\x2A\x2A\x2A\x2A\x48\x8B\x30\x48\x8B\x06" } "CCSPlayer_WeaponServices_CanUse" { "library" "server" "windows" "\x48\x89\x5C\x24\x2A\x48\x89\x6C\x24\x2A\x56\x57\x41\x56\x48\x83\xEC\x2A\x48\x8B\x01\x48\x8B\xFA" - "linux" "\x55\x48\x8D\x15\x2A\x2A\x2A\x2A\x48\x89\xE5\x41\x55\x49\x89\xFD\x41\x54\x49\x89\xF4" + "linux" "\x55\x48\x8D\x15\x2A\x2A\x2A\x2A\x48\x89\xE5\x41\x55\x49\x89\xFD" } "CreateEntityByName" { @@ -159,14 +145,14 @@ { "library" "server" "windows" "\x48\x89\x5C\x24\x10\x57\x48\x83\xEC\x20\x48\x8B\xD9\x4C\x8B\xC2" - "linux" "\x55\x48\x89\xF2\x48\x89\xE5\x41\x54\x49\x89\xFC\x48\x8D\x7D\xE0\x48\x83\xEC\x18\x48\x8D\x05\x2A\x2A\x2A\x2A\x48\x8B\x30\xE8\x2A\x2A\x2A\x2A\x48\x8B\x45\xE0" + "linux" "\x55\x48\x89\xF2\x48\x89\xE5\x41\x55\x41\x54\x53" } // "Error - cannot add bots after game is over." "BotNavIgnore" { "library" "server" "windows" "\x0F\x84\x2A\x2A\x2A\x2A\x80\xB8\x2A\x2A\x2A\x2A\x00\x0F\x84\x2A\x2A\x2A\x2A\x80\x3D\x2A\x2A\x2A\x2A\x00\x74\x15" - "linux" "\x48\x85\xC0\x74\x2E\x80\xB8\x2A\x2A\x2A\x2A\x00\x74\x25" + "linux" "\x0F\x84\x2A\x2A\x2A\x2A\x44\x0F\xB6\xB0\x2A\x2A\x2A\x2A\x45\x84\xF6\x0F\x84" } // Called right after this in windows "Entity %s(%s) is ambiguously parented to..." "CBaseEntity_SetParent" @@ -188,32 +174,32 @@ "CBaseEntity_EmitSoundFilter" { "library" "server" - "windows" "\x48\x89\x5C\x24\x08\x48\x89\x6C\x24\x10\x48\x89\x74\x24\x18\x48\x89\x7C\x24\x20\x41\x56\x48\x83\xEC\x30\x48\x8B\xEA" - "linux" "\x55\x48\x89\xE5\x41\x56\x49\x89\xD6\x41\x55\x41\x89\xF5\x41\x54\x48\x8D\x35\x2A\x2A\x2A\x2A" + "windows" "\x48\x89\x5C\x24\x2A\x48\x89\x74\x24\x2A\x48\x89\x7C\x24\x2A\x4C\x89\x74\x24\x2A\x55\x48\x8D\x6C\x24\x2A\x48\x81\xEC\x2A\x2A\x2A\x2A\x45\x33\xF6\x48\xC7\x45" + "linux" "\x48\xB8\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x55\x0F\x28\xD0" } // the longer function containing "___clientsideitemsplaceholder0___" "CNetworkStringTable_DeleteAllStrings" { "library" "engine" - "windows" "\x40\x53\x57\x41\x57\x48\x83\xEC\x2A\x45\x33\xFF" - "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x41\x54\x53\x48\x89\xFB\x48\x83\xEC\x28\x48\x8B\x87\x2A\x2A\x2A\x2A" + "windows" "\x48\x89\x5C\x24\x2A\x48\x89\x7C\x24\x2A\x41\x56\x48\x83\xEC\x2A\x45\x33\xF6" + "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x41\x54\x45\x31\xE4\x53\x48\x89\xFB\x48\x83\xEC\x2A\x48\x83\x7F" } // "PlayerMovementTraces" "ProcessMovement" { "library" "server" - "windows" "\x40\x56\x57\x48\x81\xEC\x2A\x2A\x2A\x2A\x4C\x8B\x49" - "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x41\x54\x49\x89\xFC\x53\x48\x83\xEC\x38\x48\x8B\x7F\x30" + "windows" "\x40\x57\x41\x57\x48\x81\xEC\x2A\x2A\x2A\x2A\x48\x83\x79" + "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x41\x54\x49\x89\xF4\x53\x48\x89\xFB\x48\x83\xEC\x2A\x48\x8B\x7F\x2A\x48\x85\xFF\x0F\x84" } // "env_shake %s with...", in either xref there will be a call to SetMoveType(a1, 0, 0) at the top "CBaseEntity_SetMoveType" { "library" "server" - "windows" "\x48\x89\x5C\x24\x2A\x48\x89\x6C\x24\x2A\x48\x89\x74\x24\x2A\x57\x48\x83\xEC\x2A\x41\x0F\xB6\xF0" - "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x41\x89\xD5\x41\x54\x49\x89\xFC\x53\x48\x83\xEC" + "windows" "\x48\x89\x5C\x24\x2A\x48\x89\x6C\x24\x2A\x48\x89\x74\x24\x2A\x48\x89\x7C\x24\x2A\x41\x56\x48\x83\xEC\x2A\x41\x0F\xB6\xF0" + "linux" "\x55\x48\x89\xE5\x41\x57\x41\x56\x41\x55\x41\x89\xD5\x41\x54\x53\x48\x89\xFB\x48\x83\xEC\x2A\x40\x38\xB7" } "CTakeDamageInfo" { @@ -224,6 +210,7 @@ } "Offsets" { + //MAYBE BROKEN "GameEventManager" { "linux" "93" @@ -236,68 +223,68 @@ } "CBaseEntity::Use" { - "windows" "133" - "linux" "132" + "windows" "148" + "linux" "147" } "Teleport" { - "windows" "157" - "linux" "156" + "windows" "166" + "linux" "165" } "CollisionRulesChanged" { - "windows" "179" - "linux" "178" + "windows" "190" + "linux" "189" } "IsEntityPawn" { - "windows" "165" - "linux" "164" + "windows" "172" + "linux" "171" } "IsEntityController" { - "windows" "161" - "linux" "160" + "windows" "173" + "linux" "172" } // String: "%s<%i><%s><%s>" ChangeTeam() CTMDBG..." "CCSPlayerController_ChangeTeam" { - "windows" "100" - "linux" "99" + "windows" "107" + "linux" "106" } // Look for the kill command, go through its callback and you should a find call like this, with v9 being a pawn pointer: // return (*(*v9 + 2872LL))(v9, v27, 0LL); // 2872 (359 * 8) is the offset "CBasePlayerPawn_CommitSuicide" { - "windows" "377" - "linux" "377" + "windows" "404" + "linux" "404" } // In the function with "[%03d] Found: %s, firing\n", you'll find a call into a pointer offset just a bit higher, that's the offset * 8 "CGameRules_FindPickerEntity" { - "windows" "27" - "linux" "28" + "windows" "25" + "linux" "26" } "PassesTriggerFilters" { - "windows" "260" - "linux" "261" + "windows" "269" + "linux" "270" } "CCSPlayerController_Respawn" { - "windows" "257" - "linux" "259" + "windows" "276" + "linux" "278" } "GetHammerUniqueId" { - "windows" "102" - "linux" "101" + "windows" "116" + "linux" "115" } "CheckTransmitPlayerSlot" { - "windows" "584" - "linux" "584" + "windows" "576" + "linux" "576" } // engine // "tried to sprint to a non-client", there will be a check above like this: if ( a2 >= *(v5 + 632) ), note that this is a CUtlVector @@ -319,7 +306,7 @@ "BotNavIgnore" { "windows" "\xE9\x2C\x00\x00\x00\x90" - "linux" "\xE9\x15\x00\x00\x00" + "linux" "\xE9\x25\x00\x00\x00\x90" } } } diff --git a/sdk b/sdk index 774d82f5..83070f7d 160000 --- a/sdk +++ b/sdk @@ -1 +1 @@ -Subproject commit 774d82f5989211cd0ddbd230ec64b939361efb1d +Subproject commit 83070f7dae067a2193e46d9006048bfc2743f18d diff --git a/src/addresses.cpp b/src/addresses.cpp index 996ab734..d7768b85 100644 --- a/src/addresses.cpp +++ b/src/addresses.cpp @@ -51,9 +51,7 @@ bool addresses::Initialize(CGameConfig *g_GameConfig) #endif RESOLVE_SIG(g_GameConfig, "CBasePlayerController_SetPawn", addresses::CBasePlayerController_SetPawn); - RESOLVE_SIG(g_GameConfig, "InitPlayerMovementTraceFilter", addresses::InitPlayerMovementTraceFilter); RESOLVE_SIG(g_GameConfig, "TracePlayerBBox", addresses::TracePlayerBBox); - RESOLVE_SIG(g_GameConfig, "InitGameTrace", addresses::InitGameTrace); return true; } diff --git a/src/addresses.h b/src/addresses.h index 39b7194e..3acf20c6 100644 --- a/src/addresses.h +++ b/src/addresses.h @@ -65,9 +65,7 @@ namespace addresses inline void(FASTCALL *CBasePlayerController_SetPawn)(CBasePlayerController *pController, CCSPlayerPawn *pPawn, bool a3, bool a4); // typedef void InitPlayerMovementTraceFilter_t(CTraceFilterPlayerMovementCS &pFilter, CEntityInstance *pHandleEntity, uint64_t interactWith, int collisionGroup); - inline void(FASTCALL *InitPlayerMovementTraceFilter)(CTraceFilterPlayerMovementCS &pFilter, CEntityInstance *pHandleEntity, uint64_t interactWith, int collisionGroup); // typedef void TracePlayerBBox_t(const Vector &start, const Vector &end, const bbox_t &bounds, CTraceFilterPlayerMovementCS *filter, trace_t_s2 &pm); inline void(FASTCALL *TracePlayerBBox)(const Vector &start, const Vector &end, const bbox_t &bounds, CTraceFilter *filter, trace_t &pm); - inline void(FASTCALL*InitGameTrace)(trace_t *trace); } diff --git a/src/detours.cpp b/src/detours.cpp index 5cb8c911..142ca50a 100644 --- a/src/detours.cpp +++ b/src/detours.cpp @@ -34,6 +34,7 @@ #include "igameevents.h" #include "gameconfig.h" #include "serversideclient.h" +#include "sdk/tracefilter.h" #define VPROF_ENABLED #include "tier0/vprof.h" @@ -142,7 +143,7 @@ bool IsValidMovementTrace(trace_t &tr, bbox_t bounds, CTraceFilterPlayerMovement #define RAMP_BUG_THRESHOLD 0.99f #define RAMP_BUG_VELOCITY_THRESHOLD 0.95f #define NEW_RAMP_THRESHOLD 0.95f -void TryPlayerMovePre(CCSPlayer_MovementServices *ms, Vector *pFirstDest, trace_t *pFirstTrace) +void TryPlayerMovePre(CCSPlayer_MovementServices *ms, Vector *pFirstDest, trace_t *pFirstTrace, bool *bIsSurfing) { CCSPlayerPawn *pawn = ms->GetPawn(); ZEPlayer *player = g_playerManager->GetPlayer(pawn->m_hController()->GetPlayerSlot()); @@ -179,9 +180,7 @@ void TryPlayerMovePre(CCSPlayer_MovementServices *ms, Vector *pFirstDest, trace_ bounds.maxs.z = 54; } - CTraceFilterPlayerMovementCS filter; - addresses::InitPlayerMovementTraceFilter(filter, pawn, pawn->m_Collision().m_collisionAttribute().m_nInteractsWith(), - COLLISION_GROUP_PLAYER_MOVEMENT); + CTraceFilterPlayerMovementCS filter(pawn); bool potentiallyStuck {}; @@ -371,7 +370,7 @@ void TryPlayerMovePre(CCSPlayer_MovementServices *ms, Vector *pFirstDest, trace_ player->tpmVelocity = velocity; } -void TryPlayerMovePost(CCSPlayer_MovementServices *ms) +void TryPlayerMovePost(CCSPlayer_MovementServices *ms, bool *bIsSurfing) { ZEPlayer *player = g_playerManager->GetPlayer(ms->GetPawn()->m_hController()->GetPlayerSlot()); if(!player) @@ -388,11 +387,11 @@ void TryPlayerMovePost(CCSPlayer_MovementServices *ms) } } -void FASTCALL Detour_TryPlayerMove(CCSPlayer_MovementServices *ms, CMoveData *mv, Vector *pFirstDest, trace_t *pFirstTrace) +void FASTCALL Detour_TryPlayerMove(CCSPlayer_MovementServices *ms, CMoveData *mv, Vector *pFirstDest, trace_t *pFirstTrace, bool *bIsSurfing) { - TryPlayerMovePre(ms, pFirstDest, pFirstTrace); - TryPlayerMove(ms, mv, pFirstDest, pFirstTrace); - TryPlayerMovePost(ms); + TryPlayerMovePre(ms, pFirstDest, pFirstTrace, bIsSurfing); + TryPlayerMove(ms, mv, pFirstDest, pFirstTrace, bIsSurfing); + TryPlayerMovePost(ms, bIsSurfing); } void CategorizePositionPre(CCSPlayer_MovementServices *ms,bool bStayOnGround) @@ -421,13 +420,9 @@ void CategorizePositionPre(CCSPlayer_MovementServices *ms,bool bStayOnGround) bounds.maxs.z = 54; } - CTraceFilterPlayerMovementCS filter; - addresses::InitPlayerMovementTraceFilter(filter, pawn, - pawn->m_Collision().m_collisionAttribute().m_nInteractsWith(), - COLLISION_GROUP_PLAYER_MOVEMENT); + CTraceFilterPlayerMovementCS filter(pawn); trace_t trace; - addresses::InitGameTrace(&trace); Vector origin, groundOrigin; player->GetOrigin(&origin); diff --git a/src/detours.h b/src/detours.h index 90842c5b..d118c174 100644 --- a/src/detours.h +++ b/src/detours.h @@ -30,5 +30,5 @@ bool InitDetours(CGameConfig *gameConfig); void FlushAllDetours(); void FASTCALL Detour_ProcessMovement(CCSPlayer_MovementServices *pThis, void *pMove); -void FASTCALL Detour_TryPlayerMove(CCSPlayer_MovementServices *ms, CMoveData *mv, Vector *pFirstDest, trace_t *pFirstTrace); +void FASTCALL Detour_TryPlayerMove(CCSPlayer_MovementServices *ms, CMoveData *mv, Vector *pFirstDest, trace_t *pFirstTrace, bool *bIsSurfing); void FASTCALL Detour_CategorizePosition(CCSPlayer_MovementServices *ms, CMoveData *mv, bool bStayOnGround); \ No newline at end of file From 06f7f2efd0ce33a983887157285ef04d9659fb93 Mon Sep 17 00:00:00 2001 From: rcnoob Date: Wed, 6 Aug 2025 14:07:40 -0400 Subject: [PATCH 03/16] Update recipientfilters.h --- src/recipientfilters.h | 82 +++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 50 deletions(-) diff --git a/src/recipientfilters.h b/src/recipientfilters.h index b3ba9b85..7630b399 100644 --- a/src/recipientfilters.h +++ b/src/recipientfilters.h @@ -1,7 +1,7 @@ /** * ============================================================================= * CS2Fixes - * Copyright (C) 2023-2024 Source2ZE + * Copyright (C) 2023-2025 Source2ZE * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under @@ -20,67 +20,33 @@ #pragma once #include "irecipientfilter.h" #include "playermanager.h" - -// Simple filter for when only 1 recipient is needed -class CSingleRecipientFilter : public IRecipientFilter -{ -public: - CSingleRecipientFilter(CPlayerSlot iRecipient, NetChannelBufType_t nBufType = BUF_RELIABLE, bool bInitMessage = false) : - m_iRecipient(iRecipient), m_nBufType(nBufType), m_bInitMessage(bInitMessage) {} - - ~CSingleRecipientFilter() override {} - - NetChannelBufType_t GetNetworkBufType(void) const override { return m_nBufType; } - bool IsInitMessage(void) const override { return m_bInitMessage; } - int GetRecipientCount(void) const override { return 1; } - CPlayerSlot GetRecipientIndex(int slot) const override { return m_iRecipient; } - -private: - CPlayerSlot m_iRecipient; - NetChannelBufType_t m_nBufType; - bool m_bInitMessage; -}; - +#include class CRecipientFilter : public IRecipientFilter { public: - CRecipientFilter() - { - m_nBufType = BUF_RELIABLE; - m_bInitMessage = false; - } + CRecipientFilter(NetChannelBufType_t nBufType = BUF_RELIABLE, bool bInitMessage = false) : + m_nBufType(nBufType), m_bInitMessage(bInitMessage) {} - CRecipientFilter(IRecipientFilter *source, int iExcept = -1) + CRecipientFilter(IRecipientFilter* source, CPlayerSlot exceptSlot = -1) { + m_Recipients = source->GetRecipients(); m_nBufType = source->GetNetworkBufType(); m_bInitMessage = source->IsInitMessage(); - m_Recipients.RemoveAll(); - for (int i = 0; i < source->GetRecipientCount(); i++) - { - if (source->GetRecipientIndex(i).Get() != iExcept) - m_Recipients.AddToTail(source->GetRecipientIndex(i)); - } + if (exceptSlot != -1) + m_Recipients.Clear(exceptSlot.Get()); } ~CRecipientFilter() override {} NetChannelBufType_t GetNetworkBufType(void) const override { return m_nBufType; } bool IsInitMessage(void) const override { return m_bInitMessage; } - int GetRecipientCount(void) const override { return m_Recipients.Count(); } - - CPlayerSlot GetRecipientIndex(int slot) const override - { - if (slot < 0 || slot >= GetRecipientCount()) - return CPlayerSlot(-1); - - return m_Recipients[slot]; - } + const CPlayerBitVec& GetRecipients(void) const override { return m_Recipients; } void AddAllPlayers(void) { - m_Recipients.RemoveAll(); + m_Recipients.ClearAll(); for (int i = 0; i < MAXPLAYERS; i++) { @@ -93,15 +59,31 @@ class CRecipientFilter : public IRecipientFilter void AddRecipient(CPlayerSlot slot) { - // Don't add if it already exists - if (m_Recipients.Find(slot) != m_Recipients.InvalidIndex()) - return; + if (slot.Get() >= 0 && slot.Get() < ABSOLUTE_PLAYER_LIMIT) + m_Recipients.Set(slot.Get()); + } + + int GetRecipientCount() + { + const uint64 bits = *reinterpret_cast(&GetRecipients()); - m_Recipients.AddToTail(slot); + return std::popcount(bits); } -private: +protected: NetChannelBufType_t m_nBufType; bool m_bInitMessage; - CUtlVectorFixed m_Recipients; + CPlayerBitVec m_Recipients; +}; + +// Simple filter for when only 1 recipient is needed +class CSingleRecipientFilter : public CRecipientFilter +{ +public: + CSingleRecipientFilter(CPlayerSlot nRecipientSlot, NetChannelBufType_t nBufType = BUF_RELIABLE, bool bInitMessage = false) : + CRecipientFilter(nBufType, bInitMessage) + { + if (nRecipientSlot.Get() >= 0 && nRecipientSlot.Get() < ABSOLUTE_PLAYER_LIMIT) + m_Recipients.Set(nRecipientSlot.Get()); + } }; \ No newline at end of file From 45b595e7634e4be91be52b8050b7cbd2eccaeaf7 Mon Sep 17 00:00:00 2001 From: rcnoob Date: Wed, 6 Aug 2025 14:20:15 -0400 Subject: [PATCH 04/16] Update build.yml install clang16 --- .github/workflows/build.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a3bf947b..b7502ea3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -62,6 +62,12 @@ jobs: run: | cd ambuild && python setup.py install && cd .. + - name: Install Clang 16 + if: matrix.os == 'ubuntu-latest' + run: | + apt update && apt install -y clang-16 + ln -sf /usr/bin/clang-16 /usr/bin/clang && ln -sf /usr/bin/clang++-16 /usr/bin/clang++ + - name: Build working-directory: CS2Fixes-RampbugFix shell: bash From 226d96c789274d3734893f5d0bc94b5bf714cd52 Mon Sep 17 00:00:00 2001 From: rcnoob Date: Wed, 6 Aug 2025 14:35:09 -0400 Subject: [PATCH 05/16] update clang --- AMBuildScript | 3 ++- src/detours.cpp | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/AMBuildScript b/AMBuildScript index d84cacd2..0e1a908c 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -157,7 +157,7 @@ class MMSPluginConfig(object): '-fPIC', ] - cxx.cxxflags += ['-std=c++17'] + cxx.cxxflags += ['-std=c++20'] if (cxx.version >= 'gcc-4.0') or cxx.family == 'clang': cxx.cflags += ['-fvisibility=hidden'] cxx.cxxflags += ['-fvisibility-inlines-hidden'] @@ -167,6 +167,7 @@ class MMSPluginConfig(object): '-Wno-non-virtual-dtor', '-Wno-overloaded-virtual', '-Wno-register', + '-Wno-invalid-offsetof', ] if (cxx.version >= 'gcc-4.7' or cxx.family == 'clang'): cxx.cxxflags += ['-Wno-delete-non-virtual-dtor'] diff --git a/src/detours.cpp b/src/detours.cpp index 142ca50a..b85acf2f 100644 --- a/src/detours.cpp +++ b/src/detours.cpp @@ -189,6 +189,10 @@ void TryPlayerMovePre(CCSPlayer_MovementServices *ms, Vector *pFirstDest, trace_ // Assume we can move all the way from the current origin to the end point. VectorMA(start, timeLeft, velocity, end); // See if we can make it from origin to end point. + if (numPlanes == 1) + { + VectorMA(end, 0.03125f, planes[0], end) + } // If their velocity Z is 0, then we can avoid an extra trace here during WalkMove. if (pFirstDest && end == *pFirstDest) { From 412e5897ffa4db4430dbb50ce19276a672d7e734 Mon Sep 17 00:00:00 2001 From: rcnoob Date: Wed, 6 Aug 2025 14:43:35 -0400 Subject: [PATCH 06/16] fix tracefilter --- src/detours.cpp | 2 +- src/tracefilter.h | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 src/tracefilter.h diff --git a/src/detours.cpp b/src/detours.cpp index b85acf2f..0f6ba7fb 100644 --- a/src/detours.cpp +++ b/src/detours.cpp @@ -34,7 +34,7 @@ #include "igameevents.h" #include "gameconfig.h" #include "serversideclient.h" -#include "sdk/tracefilter.h" +#include "tracefilter.h" #define VPROF_ENABLED #include "tier0/vprof.h" diff --git a/src/tracefilter.h b/src/tracefilter.h new file mode 100644 index 00000000..be56c7a5 --- /dev/null +++ b/src/tracefilter.h @@ -0,0 +1,21 @@ +#pragma once +#include "gametrace.h" +#include "cs2_sdk/entity/cbaseplayerpawn.h" + +struct CTraceFilterPlayerMovementCS : public CTraceFilter +{ + CTraceFilterPlayerMovementCS(CBasePlayerPawn *pawn) + : CTraceFilter((CEntityInstance *)pawn, pawn->m_hOwnerEntity.Get(), pawn->m_Collision().m_collisionAttribute().m_nHierarchyId(), + pawn->m_pCollision()->m_collisionAttribute().m_nInteractsWith, COLLISION_GROUP_PLAYER, true) + { + EnableInteractsAsLayer(LAYER_INDEX_CONTENTS_PLAYER); + m_nObjectSetMask = RNQUERY_OBJECTS_ALL; + m_bHitSolid = true; + m_bHitSolidRequiresGenerateContacts = true; + m_bHitTrigger = false; + m_bShouldIgnoreDisabledPairs = true; + m_bIgnoreIfBothInteractWithHitboxes = false; + m_bForceHitEverything = false; + m_bUnknown = true; + } +}; \ No newline at end of file From e6cb0c4d871033b22b1064113d74532d4d64b4d5 Mon Sep 17 00:00:00 2001 From: rcnoob Date: Wed, 6 Aug 2025 14:56:10 -0400 Subject: [PATCH 07/16] Update sdk --- sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk b/sdk index 83070f7d..d03fadc6 160000 --- a/sdk +++ b/sdk @@ -1 +1 @@ -Subproject commit 83070f7dae067a2193e46d9006048bfc2743f18d +Subproject commit d03fadc6df7582da1eb55f3d7f5a5405b2d82df9 From 89dfb4e809abccf40766d10d6b2bd2710e4c4a05 Mon Sep 17 00:00:00 2001 From: rcnoob Date: Wed, 6 Aug 2025 15:08:06 -0400 Subject: [PATCH 08/16] update schema --- src/cs2_sdk/schema.cpp | 191 +++++++++++++++----------------- src/cs2_sdk/schema.h | 240 +++++++++++++++++++++++++---------------- 2 files changed, 235 insertions(+), 196 deletions(-) diff --git a/src/cs2_sdk/schema.cpp b/src/cs2_sdk/schema.cpp index 0c2f91bb..9238ac9a 100644 --- a/src/cs2_sdk/schema.cpp +++ b/src/cs2_sdk/schema.cpp @@ -1,7 +1,7 @@ /** * ============================================================================= * CS2Fixes - * Copyright (C) 2023-2024 Source2ZE + * Copyright (C) 2023-2025 Source2ZE * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under @@ -20,145 +20,130 @@ #include "schema.h" #include "../common.h" -#include "schemasystem/schemasystem.h" -#include "tier1/utlmap.h" -#include "tier0/memdbgon.h" -#include "plat.h" #include "entity/cbaseentity.h" +#include "plat.h" +#include "schemasystem/schemasystem.h" -extern CGlobalVars *gpGlobals; +#include "tier0/memdbgon.h" -using SchemaKeyValueMap_t = CUtlMap; -using SchemaTableMap_t = CUtlMap; +extern CGlobalVars* GetGlobals(); +using SchemaKeyValueMap_t = std::map; +using SchemaTableMap_t = std::map; static bool IsFieldNetworked(SchemaClassFieldData_t& field) { - for (int i = 0; i < field.m_nStaticMetadataCount; i++) - { - static auto networkEnabled = hash_32_fnv1a_const("MNetworkEnable"); - if (networkEnabled == hash_32_fnv1a_const(field.m_pStaticMetadata[i].m_pszName)) - return true; - } - - return false; -} + for (int i = 0; i < field.m_nStaticMetadataCount; i++) + { + static auto networkEnabled = hash_32_fnv1a_const("MNetworkEnable"); + if (networkEnabled == hash_32_fnv1a_const(field.m_pStaticMetadata[i].m_pszName)) + return true; + } + + return false; +} -static bool InitSchemaFieldsForClass(SchemaTableMap_t *tableMap, const char* className, uint32_t classKey) +static bool InitSchemaFieldsForClass(SchemaTableMap_t& tableMap, const char* className, uint32_t classKey) { - CSchemaSystemTypeScope* pType = g_pSchemaSystem->FindTypeScopeForModule(MODULE_PREFIX "server" MODULE_EXT); + CSchemaSystemTypeScope* pType = g_pSchemaSystem->FindTypeScopeForModule(MODULE_PREFIX "server" MODULE_EXT); - if (!pType) - return false; + if (!pType) + return false; - SchemaClassInfoData_t *pClassInfo = pType->FindDeclaredClass(className).Get(); + SchemaClassInfoData_t* pClassInfo = pType->FindDeclaredClass(className).Get(); - if (!pClassInfo) - { - SchemaKeyValueMap_t *map = new SchemaKeyValueMap_t(0, 0, DefLessFunc(uint32_t)); - tableMap->Insert(classKey, map); + if (!pClassInfo) + { + SchemaKeyValueMap_t map; + tableMap.insert(std::make_pair(classKey, map)); - Warning("InitSchemaFieldsForClass(): '%s' was not found!\n", className); - return false; - } + Warning("InitSchemaFieldsForClass(): '%s' was not found!\n", className); + return false; + } - short fieldsSize = pClassInfo->m_nFieldCount; - short dataNumFields = pClassInfo->m_pDataDescMap ? pClassInfo->m_pDataDescMap->dataNumFields : 0; - SchemaClassFieldData_t* pFields = pClassInfo->m_pFields; + short fieldsSize = pClassInfo->m_nFieldCount; + SchemaClassFieldData_t* pFields = pClassInfo->m_pFields; - SchemaKeyValueMap_t *keyValueMap = new SchemaKeyValueMap_t(0, 0, DefLessFunc(uint32_t)); - keyValueMap->EnsureCapacity(fieldsSize + dataNumFields); - tableMap->Insert(classKey, keyValueMap); + SchemaKeyValueMap_t& keyValueMap = tableMap.insert(std::make_pair(classKey, SchemaKeyValueMap_t())).first->second; - for (int i = 0; i < fieldsSize; ++i) - { - SchemaClassFieldData_t& field = pFields[i]; + for (int i = 0; i < fieldsSize; ++i) + { + SchemaClassFieldData_t& field = pFields[i]; #ifdef _DEBUG Message("%s::%s found at -> 0x%X - %llx\n", className, field.m_pszName, field.m_nSingleInheritanceOffset, &field); #endif - keyValueMap->Insert(hash_32_fnv1a_const(field.m_pszName), {field.m_nSingleInheritanceOffset, IsFieldNetworked(field)}); - } - - for (int i = 0; i < dataNumFields; ++i) - { - auto &field = pClassInfo->m_pDataDescMap->dataDesc[i]; - - if (!field.fieldName || !field.fieldName[0] || field.fieldOffset < 0) - { - continue; - } - if (keyValueMap->Find(hash_32_fnv1a_const(field.fieldName)) != keyValueMap->InvalidIndex()) - { - continue; - } - keyValueMap->Insert(hash_32_fnv1a_const(field.fieldName), {field.fieldOffset, false}); - } - - return true; + std::pair keyValuePair; + keyValuePair.first = hash_32_fnv1a_const(field.m_pszName); + keyValuePair.second.offset = field.m_nSingleInheritanceOffset; + keyValuePair.second.networked = IsFieldNetworked(field); + + keyValueMap.insert(keyValuePair); + } + + return true; } int16_t schema::FindChainOffset(const char* className) { - CSchemaSystemTypeScope* pType = g_pSchemaSystem->FindTypeScopeForModule(MODULE_PREFIX "server" MODULE_EXT); + CSchemaSystemTypeScope* pType = g_pSchemaSystem->FindTypeScopeForModule(MODULE_PREFIX "server" MODULE_EXT); - if (!pType) - return false; + if (!pType) + return false; - SchemaClassInfoData_t* pClassInfo = pType->FindDeclaredClass(className).Get(); + SchemaClassInfoData_t* pClassInfo = pType->FindDeclaredClass(className).Get(); - do - { - SchemaClassFieldData_t* pFields = pClassInfo->m_pFields; - short fieldsSize = pClassInfo->m_nFieldCount; - for (int i = 0; i < fieldsSize; ++i) - { - SchemaClassFieldData_t& field = pFields[i]; + do + { + SchemaClassFieldData_t* pFields = pClassInfo->m_pFields; + short fieldsSize = pClassInfo->m_nFieldCount; + for (int i = 0; i < fieldsSize; ++i) + { + SchemaClassFieldData_t& field = pFields[i]; - if (V_strcmp(field.m_pszName, "__m_pChainEntity") == 0) - { - return field.m_nSingleInheritanceOffset; - } - } - } while ((pClassInfo = pClassInfo->m_pBaseClasses ? pClassInfo->m_pBaseClasses->m_pClass : nullptr) != nullptr); + if (V_strcmp(field.m_pszName, "__m_pChainEntity") == 0) + return field.m_nSingleInheritanceOffset; + } + } while ((pClassInfo = pClassInfo->m_pBaseClasses ? pClassInfo->m_pBaseClasses->m_pClass : nullptr) != nullptr); - return 0; + return 0; } SchemaKey schema::GetOffset(const char* className, uint32_t classKey, const char* memberName, uint32_t memberKey) { - static SchemaTableMap_t schemaTableMap(0, 0, DefLessFunc(uint32_t)); - int16_t tableMapIndex = schemaTableMap.Find(classKey); - if (!schemaTableMap.IsValidIndex(tableMapIndex)) - { - if (InitSchemaFieldsForClass(&schemaTableMap, className, classKey)) - return GetOffset(className, classKey, memberName, memberKey); - - return { 0, 0 }; - } - - SchemaKeyValueMap_t *tableMap = schemaTableMap[tableMapIndex]; - int16_t memberIndex = tableMap->Find(memberKey); - if (!tableMap->IsValidIndex(memberIndex)) - { - Warning("schema::GetOffset(): '%s' was not found in '%s'!\n", memberName, className); - return { 0, 0 }; - } - - return tableMap->Element(memberIndex); + static SchemaTableMap_t schemaTableMap; + + if (!schemaTableMap.contains(classKey)) + { + if (InitSchemaFieldsForClass(schemaTableMap, className, classKey)) + return GetOffset(className, classKey, memberName, memberKey); + + return {0, 0}; + } + + SchemaKeyValueMap_t tableMap = schemaTableMap[classKey]; + + if (!tableMap.contains(memberKey)) + { + Warning("schema::GetOffset(): '%s' was not found in '%s'!\n", memberName, className); + return {0, 0}; + } + + return tableMap[memberKey]; } -void EntityNetworkStateChanged(uintptr_t entityInstance, uint nOffset) +void NetworkStateChanged(uintptr_t chainEntity, uint32_t offset, uint32_t nArrayIndex, uint32_t nPathIndex) { - reinterpret_cast(entityInstance)->NetworkStateChanged(nOffset); + CNetworkStateChangedInfo info(offset, nArrayIndex, nPathIndex); + + addresses::NetworkStateChanged(reinterpret_cast(chainEntity), info); } -void ChainNetworkStateChanged(uintptr_t networkVarChainer, uint nLocalOffset) +void SetStateChanged(uintptr_t pEntity, uint32_t offset, uint32_t nArrayIndex, uint32_t nPathIndex) { - CEntityInstance* pEntity = *reinterpret_cast(networkVarChainer); - if (pEntity && (pEntity->m_pEntity->m_flags & EF_IS_CONSTRUCTION_IN_PROGRESS) == 0) - { - pEntity->NetworkStateChanged(nLocalOffset, -1, *reinterpret_cast(networkVarChainer + 32)); - } -} \ No newline at end of file + CNetworkStateChangedInfo info(offset, nArrayIndex, nPathIndex); + + static auto fnOffset = g_GameConfig->GetOffset("CBaseEntity::StateChanged"); + CALL_VIRTUAL(void, fnOffset, (void*)pEntity, &info); +} diff --git a/src/cs2_sdk/schema.h b/src/cs2_sdk/schema.h index 8e72c009..128d4e1c 100644 --- a/src/cs2_sdk/schema.h +++ b/src/cs2_sdk/schema.h @@ -1,7 +1,7 @@ /** * ============================================================================= * CS2Fixes - * Copyright (C) 2023-2024 Source2ZE + * Copyright (C) 2023-2025 Source2ZE * ============================================================================= * * This program is free software; you can redistribute it and/or modify it under @@ -20,124 +20,178 @@ #pragma once #ifdef _WIN32 -#pragma warning(push) -#pragma warning(disable : 4005) + #pragma warning(push) + #pragma warning(disable : 4005) #endif #include #ifdef _WIN32 -#pragma warning(pop) + #pragma warning(pop) #endif #include "../addresses.h" -#include "tier0/dbg.h" #include "const.h" -#include "virtual.h" #include "stdint.h" +#include "tier0/dbg.h" +#include "virtual.h" #undef schema +class CBaseEntity; + struct SchemaKey { int32 offset; bool networked; }; -void EntityNetworkStateChanged(uintptr_t entityInstance, uint nOffset); -void ChainNetworkStateChanged(uintptr_t networkVarChainer, uint nLocalOffset); +struct CNetworkStateChangedInfo +{ + CNetworkStateChangedInfo() = delete; + + CNetworkStateChangedInfo(uint32_t nOffset, uint32_t nArrayIndex, uint32_t nPathIndex) + { + m_vecOffsetData.EnsureCount(1); + m_vecOffsetData[0] = nOffset; + + unk_30 = -1; + + unk_3c = 0; + + m_nArrayIndex = nArrayIndex; + m_nPathIndex = nPathIndex; + } + +private: + int m_nSize; // 0x0 + CUtlVector m_vecOffsetData; // 0x8 + char* m_pszFieldName{}; // 0x20 + char* m_pszFileName{}; // 0x28 + uint32_t unk_30 = -1; // 0x30 + uint32_t m_nArrayIndex{}; // 0x34 + uint32_t m_nPathIndex{}; // 0x38 + uint16_t unk_3c{}; // 0x3c +}; // Size: 0x3e + +void NetworkStateChanged(uintptr_t chainEntity, uint32_t offset, uint32_t nArrayIndex = -1, uint32_t nPathIndex = -1); +void SetStateChanged(uintptr_t pEntity, uint32_t offset, uint32_t nArrayIndex = -1, uint32_t nPathIndex = -1); constexpr uint32_t val_32_const = 0x811c9dc5; constexpr uint32_t prime_32_const = 0x1000193; constexpr uint64_t val_64_const = 0xcbf29ce484222325; constexpr uint64_t prime_64_const = 0x100000001b3; -inline constexpr uint32_t hash_32_fnv1a_const(const char *const str, const uint32_t value = val_32_const) noexcept +inline constexpr uint32_t hash_32_fnv1a_const(const char* const str, const uint32_t value = val_32_const) noexcept { return (str[0] == '\0') ? value : hash_32_fnv1a_const(&str[1], (value ^ uint32_t(str[0])) * prime_32_const); } -inline constexpr uint64_t hash_64_fnv1a_const(const char *const str, const uint64_t value = val_64_const) noexcept +inline constexpr uint64_t hash_64_fnv1a_const(const char* const str, const uint64_t value = val_64_const) noexcept { return (str[0] == '\0') ? value : hash_64_fnv1a_const(&str[1], (value ^ uint64_t(str[0])) * prime_64_const); } -#define SCHEMA_FIELD_OFFSET(type, varName, extra_offset) \ - class varName##_prop \ - { \ - public: \ - std::add_lvalue_reference_t Get() \ - { \ - static constexpr auto datatable_hash = hash_32_fnv1a_const(ThisClassName); \ - static constexpr auto prop_hash = hash_32_fnv1a_const(#varName); \ - \ - static const auto m_key = \ - schema::GetOffset(ThisClassName, datatable_hash, #varName, prop_hash); \ - \ - static const size_t offset = offsetof(ThisClass, varName); \ - ThisClass *pThisClass = (ThisClass *)((byte *)this - offset); \ - \ - return *reinterpret_cast>( \ - (uintptr_t)(pThisClass) + m_key.offset + extra_offset); \ - } \ - void Set(type val) \ - { \ - static constexpr auto datatable_hash = hash_32_fnv1a_const(ThisClassName); \ - static constexpr auto prop_hash = hash_32_fnv1a_const(#varName); \ - \ - static const auto m_key = \ - schema::GetOffset(ThisClassName, datatable_hash, #varName, prop_hash); \ - \ - static const auto m_chain = \ - schema::FindChainOffset(ThisClassName); \ - \ - static const size_t offset = offsetof(ThisClass, varName); \ - ThisClass *pThisClass = (ThisClass *)((byte *)this - offset); \ - \ - if (m_chain != 0 && m_key.networked) \ - { \ - DevMsg("Found chain offset %d for %s::%s\n", m_chain, ThisClassName, #varName); \ - ChainNetworkStateChanged((uintptr_t)(pThisClass) + m_chain, m_key.offset + extra_offset); \ - } \ - else if(m_key.networked) \ - { \ - /* WIP: Works fine for most props, but inlined classes in the middle of a class will - need to have their this pointer corrected by the offset .*/ \ - DevMsg("Attempting to call SetStateChanged on on %s::%s\n", ThisClassName, #varName); \ - if (!IsStruct) \ - EntityNetworkStateChanged((uintptr_t)pThisClass, m_key.offset + extra_offset); \ - else \ - CALL_VIRTUAL(void, 1, pThisClass, m_key.offset + extra_offset, 0xFFFFFFFF, 0xFFFF); \ - } \ - *reinterpret_cast>((uintptr_t)(pThisClass) + m_key.offset + extra_offset) = val; \ - } \ - operator std::add_lvalue_reference_t() { return Get(); } \ - std::add_lvalue_reference_t operator ()() { return Get(); } \ - std::add_lvalue_reference_t operator->() { return Get(); } \ - void operator()(type val) { Set(val); } \ - void operator=(type val) { Set(val); } \ +#define SCHEMA_FIELD_OFFSET(type, varName, extra_offset) \ + class varName##_prop \ + { \ + public: \ + std::add_lvalue_reference_t Get() \ + { \ + static constexpr auto datatable_hash = hash_32_fnv1a_const(ThisClassName); \ + static constexpr auto prop_hash = hash_32_fnv1a_const(#varName); \ + \ + static const auto m_key = \ + schema::GetOffset(ThisClassName, datatable_hash, #varName, prop_hash); \ + \ + static const size_t offset = offsetof(ThisClass, varName); \ + ThisClass* pThisClass = (ThisClass*)((byte*)this - offset); \ + \ + return *reinterpret_cast>( \ + (uintptr_t)(pThisClass) + m_key.offset + extra_offset); \ + } \ + void Set(type val) \ + { \ + static constexpr auto datatable_hash = hash_32_fnv1a_const(ThisClassName); \ + static constexpr auto prop_hash = hash_32_fnv1a_const(#varName); \ + \ + static const auto m_key = \ + schema::GetOffset(ThisClassName, datatable_hash, #varName, prop_hash); \ + \ + static const auto m_chain = \ + schema::FindChainOffset(ThisClassName); \ + \ + static const size_t offset = offsetof(ThisClass, varName); \ + ThisClass* pThisClass = (ThisClass*)((byte*)this - offset); \ + \ + if (m_chain != 0 && m_key.networked) \ + { \ + DevMsg("Found chain offset %d for %s::%s\n", m_chain, ThisClassName, #varName); \ + ::NetworkStateChanged((uintptr_t)(pThisClass) + m_chain, m_key.offset + extra_offset); \ + } \ + else if (m_key.networked) \ + { \ + /* WIP: Works fine for most props, but inlined classes in the middle of a class will \ + need to have their this pointer corrected by the offset .*/ \ + if (!IsStruct) \ + ::SetStateChanged((uintptr_t)pThisClass, m_key.offset + extra_offset); \ + /* Crash here if no VTable */ \ + /*else \ + CALL_VIRTUAL(void, 1, pThisClass, m_key.offset + extra_offset, 0xFFFFFFFF, 0xFFFFFFFF);*/ \ + } \ + *reinterpret_cast>((uintptr_t)(pThisClass) + m_key.offset + extra_offset) = val; \ + } \ + operator std::add_lvalue_reference_t() \ + { \ + return Get(); \ + } \ + std::add_lvalue_reference_t operator()() \ + { \ + return Get(); \ + } \ + std::add_lvalue_reference_t operator->() \ + { \ + return Get(); \ + } \ + void operator()(type val) \ + { \ + Set(val); \ + } \ + void operator=(type val) \ + { \ + Set(val); \ + } \ } varName; -#define SCHEMA_FIELD_POINTER_OFFSET(type, varName, extra_offset) \ - class varName##_prop \ - { \ - public: \ - type *Get() \ - { \ - static constexpr auto datatable_hash = hash_32_fnv1a_const(ThisClassName); \ - static constexpr auto prop_hash = hash_32_fnv1a_const(#varName); \ - \ - static const auto m_key = \ - schema::GetOffset(ThisClassName, datatable_hash, #varName, prop_hash); \ - \ - static const size_t offset = offsetof(ThisClass, varName); \ - ThisClass *pThisClass = (ThisClass *)((byte *)this - offset); \ - \ - return reinterpret_cast>( \ - (uintptr_t)(pThisClass) + m_key.offset + extra_offset); \ - } \ - operator type*() { return Get(); } \ - type* operator ()() { return Get(); } \ - type* operator->() { return Get(); } \ +#define SCHEMA_FIELD_POINTER_OFFSET(type, varName, extra_offset) \ + class varName##_prop \ + { \ + public: \ + type* Get() \ + { \ + static constexpr auto datatable_hash = hash_32_fnv1a_const(ThisClassName); \ + static constexpr auto prop_hash = hash_32_fnv1a_const(#varName); \ + \ + static const auto m_key = \ + schema::GetOffset(ThisClassName, datatable_hash, #varName, prop_hash); \ + \ + static const size_t offset = offsetof(ThisClass, varName); \ + ThisClass* pThisClass = (ThisClass*)((byte*)this - offset); \ + \ + return reinterpret_cast>( \ + (uintptr_t)(pThisClass) + m_key.offset + extra_offset); \ + } \ + operator type*() \ + { \ + return Get(); \ + } \ + type* operator()() \ + { \ + return Get(); \ + } \ + type* operator->() \ + { \ + return Get(); \ + } \ } varName; // Use this when you want the member's value itself @@ -150,14 +204,14 @@ inline constexpr uint64_t hash_64_fnv1a_const(const char *const str, const uint6 namespace schema { - int16_t FindChainOffset(const char *className); - SchemaKey GetOffset(const char *className, uint32_t classKey, const char *memberName, uint32_t memberKey); -} - -#define DECLARE_SCHEMA_CLASS_BASE(className, isStruct) \ - typedef className ThisClass; \ - static constexpr const char *ThisClassName = #className; \ - static constexpr bool IsStruct = isStruct; + int16_t FindChainOffset(const char* className); + SchemaKey GetOffset(const char* className, uint32_t classKey, const char* memberName, uint32_t memberKey); +} // namespace schema + +#define DECLARE_SCHEMA_CLASS_BASE(className, isStruct) \ + typedef className ThisClass; \ + static constexpr const char* ThisClassName = #className; \ + static constexpr bool IsStruct = isStruct; #define DECLARE_SCHEMA_CLASS(className) DECLARE_SCHEMA_CLASS_BASE(className, false) From 57919cb2eb7205844ec4e2bfc5ae29935abc6208 Mon Sep 17 00:00:00 2001 From: rcnoob Date: Wed, 6 Aug 2025 15:12:39 -0400 Subject: [PATCH 09/16] update addresses --- gamedata/cs2fixes.games.txt | 11 +++++++++++ src/addresses.cpp | 1 + src/addresses.h | 3 ++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/gamedata/cs2fixes.games.txt b/gamedata/cs2fixes.games.txt index 049578dd..a602d970 100644 --- a/gamedata/cs2fixes.games.txt +++ b/gamedata/cs2fixes.games.txt @@ -207,6 +207,12 @@ "windows" "\x40\x53\x48\x83\xEC\x60\x48\xC7\x41\x38\xFF\xFF\xFF\xFF" "linux" "\x55\x48\x89\xE5\x48\x83\xEC\x10\x4C\x8D\x15\x2A\x2A\x2A\x2A" } + "NetworkStateChanged" + { + "library" "server" + "windows" "\x4C\x8B\xC2\x48\x8B\xD1\x48\x8B\x09" + "linux" "\x48\x8B\x07\x48\x85\xC0\x74\x2A\x48\x8B\x50\x10" + } } "Offsets" { @@ -299,6 +305,11 @@ "windows" "37" "linux" "38" } + "CBaseEntity::StateChanged" + { + "windows" "25" + "linux" "26" + } } "Patches" { diff --git a/src/addresses.cpp b/src/addresses.cpp index d7768b85..9df1ab56 100644 --- a/src/addresses.cpp +++ b/src/addresses.cpp @@ -52,6 +52,7 @@ bool addresses::Initialize(CGameConfig *g_GameConfig) RESOLVE_SIG(g_GameConfig, "CBasePlayerController_SetPawn", addresses::CBasePlayerController_SetPawn); RESOLVE_SIG(g_GameConfig, "TracePlayerBBox", addresses::TracePlayerBBox); + RESOLVE_SIG(g_GameConfig, "NetworkStateChanged", addresses::NetworkStateChanged); return true; } diff --git a/src/addresses.h b/src/addresses.h index 3acf20c6..161051af 100644 --- a/src/addresses.h +++ b/src/addresses.h @@ -54,6 +54,7 @@ class CEntityKeyValues; class IRecipientFilter; class CTraceFilterPlayerMovementCS; class CTraceFilter; +class CNetworkStateChangedInfo; struct bbox_t; struct SndOpEventGuid_t; @@ -63,7 +64,7 @@ namespace addresses bool Initialize(CGameConfig *g_GameConfig); inline void(FASTCALL *CBasePlayerController_SetPawn)(CBasePlayerController *pController, CCSPlayerPawn *pPawn, bool a3, bool a4); - + inline void(FASTCALL* NetworkStateChanged)(void* chainEntity, CNetworkStateChangedInfo& info); // typedef void InitPlayerMovementTraceFilter_t(CTraceFilterPlayerMovementCS &pFilter, CEntityInstance *pHandleEntity, uint64_t interactWith, int collisionGroup); // typedef void TracePlayerBBox_t(const Vector &start, const Vector &end, const bbox_t &bounds, CTraceFilterPlayerMovementCS *filter, trace_t_s2 &pm); inline void(FASTCALL *TracePlayerBBox)(const Vector &start, const Vector &end, const bbox_t &bounds, CTraceFilter *filter, trace_t &pm); From dc5802b0ad7cbb73ac671282842c6cadf690bf2b Mon Sep 17 00:00:00 2001 From: rcnoob Date: Wed, 6 Aug 2025 15:21:04 -0400 Subject: [PATCH 10/16] fix detour and remove old tracefilter --- src/cs2_sdk/entity/services.h | 4 ---- src/detours.cpp | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/cs2_sdk/entity/services.h b/src/cs2_sdk/entity/services.h index f47e374c..9e56e68c 100644 --- a/src/cs2_sdk/entity/services.h +++ b/src/cs2_sdk/entity/services.h @@ -221,10 +221,6 @@ struct touchlist_t { trace_t trace; }; -class CTraceFilterPlayerMovementCS : public CTraceFilter -{ -}; - class CTraceFilterHitAllTriggers: public CTraceFilter { public: diff --git a/src/detours.cpp b/src/detours.cpp index 0f6ba7fb..206bf91f 100644 --- a/src/detours.cpp +++ b/src/detours.cpp @@ -191,7 +191,7 @@ void TryPlayerMovePre(CCSPlayer_MovementServices *ms, Vector *pFirstDest, trace_ // See if we can make it from origin to end point. if (numPlanes == 1) { - VectorMA(end, 0.03125f, planes[0], end) + VectorMA(end, 0.03125f, planes[0], end); } // If their velocity Z is 0, then we can avoid an extra trace here during WalkMove. if (pFirstDest && end == *pFirstDest) From fb06c2ffcbccdb80c78f1179df91469329dee03f Mon Sep 17 00:00:00 2001 From: rcnoob Date: Wed, 6 Aug 2025 15:30:14 -0400 Subject: [PATCH 11/16] update sdk --- src/cs2_sdk/entity/cbaseentity.h | 1 + src/cs2_sdk/entity/ccollisionproperty.h | 1 + 2 files changed, 2 insertions(+) diff --git a/src/cs2_sdk/entity/cbaseentity.h b/src/cs2_sdk/entity/cbaseentity.h index c01f124b..df2703db 100644 --- a/src/cs2_sdk/entity/cbaseentity.h +++ b/src/cs2_sdk/entity/cbaseentity.h @@ -40,6 +40,7 @@ class CGameSceneNode SCHEMA_FIELD(CGameSceneNode *, m_pChild) SCHEMA_FIELD(CNetworkOriginCellCoordQuantizedVector, m_vecOrigin) SCHEMA_FIELD(QAngle, m_angRotation) + SCHEMA_FIELD(CHandle, m_hOwnerEntity) SCHEMA_FIELD(float, m_flScale) SCHEMA_FIELD(float, m_flAbsScale) SCHEMA_FIELD(Vector, m_vecAbsOrigin) diff --git a/src/cs2_sdk/entity/ccollisionproperty.h b/src/cs2_sdk/entity/ccollisionproperty.h index a21f5d6c..fde768ec 100644 --- a/src/cs2_sdk/entity/ccollisionproperty.h +++ b/src/cs2_sdk/entity/ccollisionproperty.h @@ -29,6 +29,7 @@ struct VPhysicsCollisionAttribute_t SCHEMA_FIELD(uint64_t, m_nInteractsAs) SCHEMA_FIELD(uint64_t, m_nInteractsWith) SCHEMA_FIELD(uint64_t, m_nInteractsExclude) + SCHEMA_FIELD(uint16, m_nHierarchyId) }; class CCollisionProperty From 0135cf0988a61847e787f7e3cea8b22f441c4a4d Mon Sep 17 00:00:00 2001 From: rcnoob Date: Wed, 6 Aug 2025 15:53:30 -0400 Subject: [PATCH 12/16] Update cbaseentity.h --- src/cs2_sdk/entity/cbaseentity.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cs2_sdk/entity/cbaseentity.h b/src/cs2_sdk/entity/cbaseentity.h index df2703db..628a7b27 100644 --- a/src/cs2_sdk/entity/cbaseentity.h +++ b/src/cs2_sdk/entity/cbaseentity.h @@ -40,7 +40,6 @@ class CGameSceneNode SCHEMA_FIELD(CGameSceneNode *, m_pChild) SCHEMA_FIELD(CNetworkOriginCellCoordQuantizedVector, m_vecOrigin) SCHEMA_FIELD(QAngle, m_angRotation) - SCHEMA_FIELD(CHandle, m_hOwnerEntity) SCHEMA_FIELD(float, m_flScale) SCHEMA_FIELD(float, m_flAbsScale) SCHEMA_FIELD(Vector, m_vecAbsOrigin) @@ -144,6 +143,7 @@ class Z_CBaseEntity : public CEntityInstance SCHEMA_FIELD(bool, m_bTakesDamage) SCHEMA_FIELD_POINTER(CUtlStringToken, m_nSubclassID) SCHEMA_FIELD(CHandle, m_hGroundEntity) + SCHEMA_FIELD(CHandle, m_hOwnerEntity) SCHEMA_FIELD(float, m_flFriction) SCHEMA_FIELD(float, m_flGravityScale) SCHEMA_FIELD(float, m_flTimeScale) From 484f2cbce8eadbf906ebd573cec8e02742688bfb Mon Sep 17 00:00:00 2001 From: rcnoob Date: Wed, 6 Aug 2025 15:59:25 -0400 Subject: [PATCH 13/16] Update addresses.h remove old tracefilter references --- src/addresses.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/addresses.h b/src/addresses.h index 161051af..207b7ce7 100644 --- a/src/addresses.h +++ b/src/addresses.h @@ -52,8 +52,6 @@ class IEntityFindFilter; class CGameRules; class CEntityKeyValues; class IRecipientFilter; -class CTraceFilterPlayerMovementCS; -class CTraceFilter; class CNetworkStateChangedInfo; struct bbox_t; From b22539719ed2aaab8b945ab5cfc53a1e9ff6709d Mon Sep 17 00:00:00 2001 From: rcnoob Date: Wed, 6 Aug 2025 16:27:42 -0400 Subject: [PATCH 14/16] Update cbaseentity.h --- src/cs2_sdk/entity/cbaseentity.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cs2_sdk/entity/cbaseentity.h b/src/cs2_sdk/entity/cbaseentity.h index 628a7b27..94a92d53 100644 --- a/src/cs2_sdk/entity/cbaseentity.h +++ b/src/cs2_sdk/entity/cbaseentity.h @@ -143,7 +143,7 @@ class Z_CBaseEntity : public CEntityInstance SCHEMA_FIELD(bool, m_bTakesDamage) SCHEMA_FIELD_POINTER(CUtlStringToken, m_nSubclassID) SCHEMA_FIELD(CHandle, m_hGroundEntity) - SCHEMA_FIELD(CHandle, m_hOwnerEntity) + SCHEMA_FIELD(CHandle, m_hOwnerEntity) SCHEMA_FIELD(float, m_flFriction) SCHEMA_FIELD(float, m_flGravityScale) SCHEMA_FIELD(float, m_flTimeScale) From 775c651f5ee999c138d1231ced1c1d47dd6244fd Mon Sep 17 00:00:00 2001 From: rcnoob Date: Wed, 6 Aug 2025 16:35:46 -0400 Subject: [PATCH 15/16] Update AMBuildScript fix windows compile --- AMBuildScript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AMBuildScript b/AMBuildScript index 0e1a908c..c9ca9123 100644 --- a/AMBuildScript +++ b/AMBuildScript @@ -205,7 +205,7 @@ class MMSPluginConfig(object): cxx.cflags += [ '/W3', '/Zi', - '/std:c++17', + '/std:c++20', ] cxx.cxxflags += ['/TP'] From 88e4d10b7fb05c6772ad2f6535e33b5eb8de6dc6 Mon Sep 17 00:00:00 2001 From: rcnoob Date: Wed, 6 Aug 2025 16:42:57 -0400 Subject: [PATCH 16/16] Update AMBuilder update version --- AMBuilder | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AMBuilder b/AMBuilder index e9645537..dfdb5606 100644 --- a/AMBuilder +++ b/AMBuilder @@ -14,7 +14,7 @@ for sdk_target in MMSPlugin.sdk_targets: try: version = subprocess.check_output(['git', 'describe', '--tags', '--long']).decode('ascii').strip() except subprocess.SubprocessError as e: - version = "1.7-dev" + version = "1.8-dev" print("git describe failed as there are no tags") print(f'Setting version to "{version}"')