"Games" { "left4dead2" { "Addresses" { "ZombieManager" { "windows" { "signature" "StartChangeLevel" "read" "293" } "linux" { "signature" "TheZombieManager" "read" "0" } } "WeaponInfoDatabase" { "windows" { "signature" "ReadWeaponDataFromFileForSlot" "read" "75" } "linux" { "signature" "WeaponInfoDatabase" } } "MeleeWeaponInfoStore" { "windows" { "signature" "CTerrorPlayer_GiveNamedItem" "read" "340" } "linux" { "signature" "CMeleeWeaponInfoStore" } } "CDirector" { "windows" { "signature" "DirectorMusicBanks_OnRoundStart" "read" "12" } "linux" { "signature" "TheDirector" } } } "Offsets" { /* Offset into CDirector::AreWanderersAllowed */ "CDirectorScavengeMode" { "windows" "11" /* mov ecx, [esi+offs] */ "linux" "13" /* mov eax, [ebx+offs] */ } /* Offset from ConnectClientLobbyCheck to cmp with max players check string #Valve_Reject_Server_Full */ "ValveRejectServerFullFirst" { "windows" "30" /* cmp eax, [esi+180h] -> cmp eax, imm32 */ "linux" "0" /* cmp esi, [ebx+17Ch] -> cmp esi, imm32 */ } /* Member variable offset into CTerrorGameRules * * - Look for CTerrorGameRules::GetVersusMaxCompletionScore, which is ref'd * - by CL4DGameStats::AddSurvivorStats--unique string "CharacterId" */ "VersusMaxCompletionScore" { "windows" "3568" "linux" "3560" } /* Offset into CTerrorPlayer * Is this right? How do we find it? */ "SpawnTimer" { "windows" "11308" "linux" "11288" } } "Signatures" { /* * CTerrorGameRules::GetTeamScore(int,bool) * Find "Staying on original map %s\n" * -> CDirector::Restart(void) * -> showed up near "info_window" * -> called twice along with another function called twice (CterrorGameRules::UpdateChapterScores) */ "GetTeamScore" { "library" "server" "linux" "@_ZN16CTerrorGameRules12GetTeamScoreEib" "windows" "\x55\x8B\xEC\x8B\x2A\x2A\x85\xC0\x2A\x2A\x33\xC0\x5D\xC2" /* 55 8B EC 8B ? ? 85 C0 ? ? 33 C0 5D C2 */ } /* * CTerrorGameRules::SetCampaignScores(int,int) * Search for unique string "singlechapter" * -> has two xref from same function, CTerrorGameRules::IsSingleChapterMode() * -> has two xref, one is CRestartGameIssue::ExecuteCommand() (exclude the other, CServerGameDLL::ServerHibernationUpdate(), which has string "FCVAR_NEVER_AS_STRING") * -> CRestartGameIssue::ExecuteCommand() calls CDirectorVersusMode::VoteRestartVersusLevel() (fourth call..?) * -> first call is CTerrorGameRules::SetCampaignScores() * make sure to double check uniqueness when done */ "SetCampaignScores" { "library" "server" "linux" "@_ZN16CTerrorGameRules17SetCampaignScoresEii" "windows" "\x55\x8B\xEC\x56\x57\x8B\x7D\x08\x8B\xF1\x39\xBE\x2A\x2A\x2A\x2A\x74\x2A\xE8\x2A\x2A\x2A\x2A\x89\xBE\x2A\x2A\x2A\x2A\x8B" /* 55 8B EC 56 57 8B 7D 08 8B F1 39 BE ? ? ? ? 74 ? E8 ? ? ? ? 89 BE ? ? ? ? 8B */ } /* * CTerrorGameRules::ClearTeamScores(bool) */ "ClearTeamScores" { "library" "server" "linux" "@_ZN16CTerrorGameRules15ClearTeamScoresEb" "windows" "\x55\x8B\xEC\x51\x0F\x57\xC0\x53\x56\x57\x33\xDB\x8B" /* 55 8B EC 51 0F 57 C0 53 56 57 33 DB 8B */ } /* * CBaseServer::SetReservationCookie(uint64_t, char*, va_list) * - clear the reservation by setting a cookie of 0 */ "SetReservationCookie" { "library" "engine" "linux" "@_ZN11CBaseServer20SetReservationCookieEyPKcz" "windows" "\x55\x8B\xEC\x81\xEC\x2A\x2A\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x33\xC5\x89\x45\xFC\x53\x8B\x5D\x10\x56\x8B\x75\x08\x57\x8B\x7D\x0C\x3B" /* 55 8B EC 81 EC ? ? ? ? A1 ? ? ? ? 33 C5 89 45 FC 53 8B 5D 10 56 8B 75 08 57 8B 7D 0C 3B */ } /* * CTerrorPlayer::TakeOverBot * unique string "[TAKEOVER]: %s (%d) possessed %s" */ "TakeOverBot" { "library" "server" "linux" "@_ZN13CTerrorPlayer11TakeOverBotEb" "windows" "\x55\x8B\xEC\x81\xEC\x2A\x2A\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x33\xC5\x89\x45\xFC\x53\x56\x8D\x85" /* 55 8B EC 81 EC ? ? ? ? A1 ? ? ? ? 33 C5 89 45 FC 53 56 8D 85 */ } /* * SurvivorBot::SetHumanSpectator(CTerrorPlayer*) * Very similar to BossZombiePlayerBot::SetHumanSpectator() * SurvivorBot version has 5 xref (one of them is CTerrorPlayer::TakeOverBot), BossZombie has just 1 (CTerrorPlayer::TakeOverBot) */ "SetHumanSpec" { "library" "server" "linux" "@_ZN11SurvivorBot17SetHumanSpectatorEP13CTerrorPlayer" "windows" "\x55\x8B\xEC\x56\x8B\xF1\x83\xBE\x2A\x2A\x2A\x2A\x00\x7E\x07\x32\xC0\x5E\x5D\xC2\x04\x00\x8B\x0D" /* 55 8B EC 56 8B F1 83 BE ? ? ? ? 00 7E 07 32 C0 5E 5D C2 04 00 8B 0D */ } /* * CDirectorScavengeMode::OnBeginRoundSetupTime * used to reset the setup timer during scavenge mode * has one of five references to string "ready_countdown" */ "CDirectorScavengeMode_OnBeginRoundSetupTime" { "library" "server" "linux" "@_ZN21CDirectorScavengeMode21OnBeginRoundSetupTimeEv" "windows" "\x55\x8B\xEC\x83\xEC\x10\x56\x8B\xF1\xE8\x2A\x2A\x2A\x2A\x84\xC0\x74\x2A\xF3" /* 55 8B EC 83 EC 10 56 8B F1 E8 ? ? ? ? 84 C0 74 ? F3 */ } /* CTerrorGameRules::ResetRoundNumber * used to reset the round number during scavenge mode * Search for unique string "singlechapter" * -> has two xref from same function, CTerrorGameRules::IsSingleChapterMode() * -> has two xref, one is CRestartGameIssue::ExecuteCommand() (exclude the other, CServerGameDLL::ServerHibernationUpdate(), which has string "FCVAR_NEVER_AS_STRING") * -> calls CTerrorGameRules::GetMissionFirstMap (TODO more detail on where this is) * -> xref from CDirector::Rematch * -> CTerrorGameRules::ResetRoundNumber is called right before CTerrorGameRules::IsVersusMode */ "CTerrorGameRules_ResetRoundNumber" { "library" "server" "linux" "@_ZN16CTerrorGameRules16ResetRoundNumberEv" "windows" "\x56\x8B\xF1\x83\xBE\x2A\x2A\x2A\x2A\x00\x74\x2A\xE8\x2A\x2A\x2A\x2A\xC7\x86\x2A\x2A\x2A\x2A\x00\x00\x00\x00\x5E\xC3" /* 56 8B F1 83 BE ? ? ? ? 00 74 ? E8 ? ? ? ? C7 86 ? ? ? ? 00 00 00 00 5E C3 */ } /* CTerrorGameRules::SetRoundEndTime(float) * used to freeze the scavenge game clock * start with unique string "scavenge_round_halftime" in function CDirectorScavengeMode::EndScavengeRound * -> first call in CDirectorScavengeMode::EndScavengeRound */ "CTerrorGameRules_SetRoundEndTime" { "library" "server" "linux" "@_ZN16CTerrorGameRules15SetRoundEndTimeEf" "windows" "\x55\x8B\xEC\x56\x8B\xF1\xF3\x0F\x10\x86\x2A\x2A\x2A\x2A\x0F\x2E\x45\x08\x9F\x57" /* 55 8B EC 56 8B F1 F3 0F 10 86 ? ? ? ? 0F 2E 45 08 9F 57 */ } /* CDirector::AreWanderersAllowed(void) * Used to get offset for CDirectorScavengeMode * *(director + offset) == ptr to CDirectorScavengeMode * has unique string "AlwaysAllowWanderers" */ "CDirector_AreWanderersAllowed" { "library" "server" "linux" "@_ZNK9CDirector19AreWanderersAllowedEv" "windows" "\x55\x8B\xEC\x83\xEC\x2A\x56\x8B\xF1\x8B\x8E\x2A\x2A\x2A\x2A\x8D\x45\xFF" /* 55 8B EC 83 EC ? 56 8B F1 8B 8E ? ? ? ? 8D 45 FF */ } /* Used solely to get the offset for TheDirector * CDirectorMusicBanks::OnRoundStart * Has unique string "Event.Reveal" */ "DirectorMusicBanks_OnRoundStart" { "library" "server" "windows" "\x55\x8B\xEC\x83\xEC\x2A\x56\x57\x8B\xF9\x8B\x0D\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x84" /* 55 8B EC 83 EC ? 56 57 8B F9 8B 0D ? ? ? ? E8 ? ? ? ? 84 */ } /* Find the Director/ZombieManager singleton classes */ "TheDirector" { "library" "server" "linux" "@TheDirector" } "TheZombieManager" { "library" "server" "linux" "@TheZombieManager" } /* Find the WeaponInfo Database dictionary */ "WeaponInfoDatabase" { "library" "server" "linux" "@_ZL20m_WeaponInfoDatabase" } /* We can find the WeaponInfoDatabase location in this sub on windows * * - Look for "scripts/%s", should be the ref that's furthest into a func. * OR * Look for unique string "scripts/weapon_manifest.txt", then look in same func for almost unique string "Expecting 'file', got %s\n", should be two calls before that string */ "ReadWeaponDataFromFileForSlot" { "library" "server" "windows" "\x55\x8B\xEC\x81\xEC\x2A\x2A\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x33\xC5\x89\x45\xFC\x8B\x45\x14\x53\x8B\x5D\x10" /* 55 8B EC 81 EC ? ? ? ? A1 ? ? ? ? 33 C5 89 45 FC 8B 45 14 53 8B 5D 10 */ } /* Find the Melee Weapon Info dictionary */ "CMeleeWeaponInfoStore" { "library" "server" "linux" "@g_MeleeWeaponInfoStore" } /* We can find the CMeleeWeaponInfo location in this sub on windows * * - "NULL Ent '%s' in GiveNamedItem!\n" is unique in thie function * - There are at least 3 calls using the g_MeleeWeaponInfoStore here--use some brain for offset. */ "CTerrorPlayer_GiveNamedItem" { "library" "server" "windows" "\x55\x8B\xEC\x81\xEC\x2A\x2A\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x33\xC5\x89\x45\xFC\x8B\x45\x14\x53\x8B\x5D\x08" /* 55 8B EC 81 EC ? ? ? ? A1 ? ? ? ? 33 C5 89 45 FC 8B 45 14 53 8B 5D 08 */ } /* * CDirector::RestartScenarioFromVote(const char*) * Search for unique string "singlechapter" * -> has two xref from same function, CTerrorGameRules::IsSingleChapterMode() * -> has two xref, one is CRestartGameIssue::ExecuteCommand() (exclude the other, CServerGameDLL::ServerHibernationUpdate(), which has string "FCVAR_NEVER_AS_STRING") * -> Last call in CRestartGameIssue::ExecuteCommand */ "RestartScenarioFromVote" { "library" "server" "linux" "@_ZN9CDirector23RestartScenarioFromVoteEPKc" "windows" "\x55\x8B\xEC\x56\x8B\xF1\x8B\x0D\x2A\x2A\x2A\x2A\x57\x85" /* 55 8B EC 56 8B F1 8B 0D ? ? ? ? 57 85 */ } /* * ZombieManager::SpawnSpecial(ZombieClassType, Vector const&, QAngle const&) * Be careful, there are a few overrides for SpawnSpecial * Make sure the one you have has like 11 xrefs, 6 from CCommentaryZombieSpawner::InputSpawnZombie * To find, look for non-unique string "common_", has three refs, one ref will have strings for all classes, that's CCommentaryZombieSpawner::InputSpawnZombie */ "SpawnSpecial" { "library" "server" "linux" "@_ZN13ZombieManager12SpawnSpecialE15ZombieClassTypeRK6VectorRK6QAngle" "windows" "\x55\x8B\xEC\x53\x8B\x5D\x08\x8D\x43\xFF\x56" /* 55 8B EC 53 8B 5D 08 8D 43 FF 56 */ } /* * ZombieManager::SpawnTank(Vector const&, QAngle const&) * * find by Navarea variant method and "Failed to find a tank spawn position i" * OR * To find, look for non-unique string "common_", has three refs, one ref will have strings for all classes, that's CCommentaryZombieSpawner::InputSpawnZombie * SpawnTank will be called after string "tank" */ "SpawnTank" { "library" "server" "linux" "@_ZN13ZombieManager9SpawnTankERK6VectorRK6QAngle" "windows" "\x55\x8B\xEC\x57\x8B\xF9\x8B\x0D\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x85\xC0\x78\x2A\x8B\x0D\x2A\x2A\x2A\x2A\x39" /* 55 8B EC 57 8B F9 8B 0D ? ? ? ? E8 ? ? ? ? 85 C0 78 ? 8B 0D ? ? ? ? 39 */ } /* * ZombieManager::SpawnWitch(Vector const&, QAngle const&) * * find by Navarea variant method and "Failed to find a witch spawn position i" * OR * To find, look for non-unique string "common_", has three refs, one ref will have strings for all classes, that's CCommentaryZombieSpawner::InputSpawnZombie * SpawnWitch will be called after string "witch" */ "SpawnWitch" { "library" "server" "linux" "@_ZN13ZombieManager10SpawnWitchERK6VectorRK6QAngle" "windows" "\x55\x8B\xEC\x8B\x0D\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x85\xC0\x78\x2A\x8B\x0D\x2A\x2A\x2A\x2A\x39\x81" /* 55 8B EC 8B 0D ? ? ? ? E8 ? ? ? ? 85 C0 78 */ } /* * ZombieManager::SpawnWitchBride(Vector const&, QAngle const&) * Has three xref, one is CInfoZombieSpawn::SpawnZombie (shared with SpawnWitch above) * where SpawnWitch is the third call after string "bride", and SpawnWitchBride is the second call after "bride" */ "SpawnWitchBride" { "library" "server" "linux" "@_ZN13ZombieManager15SpawnWitchBrideERK6VectorRK6QAngle" "windows" "\x55\x8B\xEC\x8B\x0D\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x85\xC0\x75" /* 55 8B EC 8B 0D ? ? ? ? E8 ? ? ? ? 85 C0 75 */ } /* * CDirectorVersusMode::OnVersusRoundStarted() * Unused? Nothing in source accesses this signature * Last call in CDirector::OnFirstSurvivorLeftSafeArea() * Also has string "versus_round_start" */ "OnVersusRoundStarted" { "library" "server" "linux" "@_ZN19CDirectorVersusMode20OnVersusRoundStartedEv" "windows" "\x8B\x0D\x2A\x2A\x2A\x2A\x85\xC9\x74\x2A\xA1\x2A\x2A\x2A\x2A\xF3\x0F\x2A\x2A\x2A\x51\xF3\x0F\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x8B" /* 8B 0D ? ? ? ? 85 C9 74 ? A1 ? ? ? ? F3 0F ? ? ? 51 F3 0F ? ? ? E8 ? ? ? ? 8B */ } /* * CDirector::OnFirstSurvivorLeftSafeArea(CTerrorPlayer *) * * string "Allowing spawning - %s left safe area\n" */ "OnFirstSurvivorLeftSafeArea" { "library" "server" "linux" "@_ZN9CDirector27OnFirstSurvivorLeftSafeAreaEP13CTerrorPlayer" "windows" "\x55\x8B\xEC\x83\xEC\x2A\x56\x57\x8B\x7D\x2A\x8B\xF1\x8B\x8E\x2A\x2A\x2A\x2A\x57\xE8" /* 55 8B EC 83 EC ? 56 57 8B 7D ? 8B F1 8B 8E ? ? ? ? 57 E8 */ } /* * CDirector::GetScriptValue(const char*, int) * Find CTerrorPlayer::OnRevived(), then look for string SurvivorMaxIncapacitatedCount * If you look for string "No conversion from %s to int now\n" you will be one call too deep */ "CDirector_GetScriptValueInt" { "library" "server" "linux" "@_ZN9CDirector14GetScriptValueEPKci" "windows" "\x55\x8B\xEC\x8B\x81\x2A\x2A\x2A\x2A\x83\xEC\x10\x83\xF8\xFF\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x8B\x45\x2A\x8B" /* 55 8B EC 8B 81 ? ? ? ? 83 EC 10 83 F8 FF ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 8B 45 ? 8B */ } /* * CDirector::GetScriptValue(const char*, float) * Called in CDirector::OnMobRushStart */ "CDirector_GetScriptValueFloat" { "library" "server" "linux" "@_ZN9CDirector14GetScriptValueEPKcf" "windows" "\x55\x8B\xEC\x8B\x81\x2A\x2A\x2A\x2A\x83\xEC\x10\x83\xF8\xFF\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\xD9" /* 55 8B EC 8B 81 ? ? ? ? 83 EC 10 83 F8 FF ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? D9 */ } /* * CDirector::GetScriptValue(const char*, const char*, char*, int) * unique string "OnChangeFinaleMusic", call right after it */ "CDirector_GetScriptValueString" { "library" "server" "linux" "@_ZN9CDirector14GetScriptValueEPKcS1_Pci" "windows" "\x55\x8B\xEC\x8B\x81\x2A\x2A\x2A\x2A\x83\xEC\x2A\x56\x8B" /* 55 8B EC 8B 81 ? ? ? ? 83 EC ? 56 8B */ } /* * CDirector::IsFinaleEscapeInProgress(void) * unique string "#L4D_idle_spectator" in CTerrorPlayer::PreThink() * CDirector::IsFinaleEscapeInProgress is a couple calls before the string, and a couple calls after CountdownTimer::Now */ "CDirector_IsFinaleEscapeInProgress" { "library" "server" "linux" "@_ZNK9CDirector24IsFinaleEscapeInProgressEv" "windows" "\x8B\x81\x2A\x2A\x2A\x2A\x83\x38\x2A\x75\x03\x32\xC0\xC3\x33\xC0\x83\xB9\x2A\x2A\x2A\x2A\x02\x0F\x94\xC0\xC3" /* 8B 81 ? ? ? ? 83 38 ? 75 03 32 C0 C3 33 C0 83 B9 ? ? ? ? 02 0F 94 C0 C3 */ } /* * CTerrorPlayer::CanBecomeGhost(bool areSpawnsDisabled) * unique string "ghost_spawn_time" */ "CTerrorPlayer_CanBecomeGhost" { "library" "server" "linux" "@_ZN13CTerrorPlayer14CanBecomeGhostEb" "windows" "\x53\x8B\xDC\x83\xEC\x2A\x83\xE4\xF0\x83\xC4\x2A\x55\x8B\x6B\x04\x89\x6C\x24\x04\x8B\xEC\x83\xEC\x2A\x56\x57\x8B\xF1\xE8\x0E" /* 53 8B DC 83 EC ? 83 E4 F0 83 C4 ? 55 8B 6B 04 89 6C 24 04 8B EC 83 EC ? 56 57 8B F1 E8 0E */ } /* * CTerrorPlayer::OnEnterGhostState() * almost unique string spawnmode_bar has three refs, one ref has strings "zombieClass" and "data" */ "CTerrorPlayer_OnEnterGhostState" { "library" "server" "linux" "@_ZN13CTerrorPlayer17OnEnterGhostStateEv" "windows" "\x55\x8B\xEC\x83\xEC\x08\x53\x56\x8B\xF1\x8B\x86\x2A\x2A\x2A\x2A\x8B" /* 55 8B EC 83 EC 08 53 56 8B F1 8B 86 ? ? ? ? 8B */ } /* * CDirector::IsFinale(void)const */ "CDirector_IsFinale" { "library" "server" "linux" "@_ZNK9CDirector8IsFinaleEv" "windows" "\x8B\x81\x2A\x2A\x2A\x2A\x33\xC9\x83\x38\x2A\x0F\x95\xC0\xC3" /* 8B 81 ? ? ? ? 33 C9 83 38 ? 0F 95 C0 C3 */ } /* * CDirector::TryOfferingTankBot(void) * unique string "Tank offer: Starting the lottery\n" */ "TryOfferingTankBot" { "library" "server" "linux" "@_ZN9CDirector18TryOfferingTankBotEP11CBaseEntityb" "windows" "\x55\x8B\xEC\x51\x83\x7D\x08\x00\x56\x8B\xF1\x89" /* 55 8B EC 51 83 7D 08 00 56 8B F1 89 */ } /* * CDirector::OnMobRushStart(void) - used by boomer and natural horde functions. Resets natural horde timer. * * find by String: "MobMinSize", its inlined in Windows */ "OnMobRushStart" { "library" "server" "linux" "@_ZN9CDirector14OnMobRushStartEv" "windows" "\x55\x8B\xEC\x83\xEC\x08\xA1\x2A\x2A\x2A\x2A\xF3\x0F\x10\x40\x2A\x56\x57\x51" /* 55 8B EC 83 EC 08 A1 ? ? ? ? F3 0F 10 40 ? 56 57 51 */ } /* * ZombieManager::SpawnITMob(int) - used for bile hordes, increases spawn count * * search for unique strings with "SpawnITMob" */ "Zombiemanager_SpawnITMob" { "library" "server" "linux" "@_ZN13ZombieManager10SpawnITMobEi" "windows" "\x55\x8B\xEC\xA1\x2A\x2A\x2A\x2A\xF3\x0F\x10\x40\x2A\x56\x57" /* 55 8B EC A1 ? ? ? ? F3 0F 10 40 ? 56 57 */ } /* * ZombieManager::SpawnMob(int) - used for natural/z_spawn * hordes, increases spawn count and calls horde music, etc * * search for unique strings with "SpawnMob" */ "Zombiemanager_SpawnMob" { "library" "server" "linux" "@_ZN13ZombieManager8SpawnMobEi" "windows" "\x55\x8B\xEC\xA1\x2A\x2A\x2A\x2A\xF3\x0F\x10\x40\x2A\x83\xEC\x2A\x53\x56\x57" /* 55 8B EC A1 ? ? ? ? F3 0F 10 40 ? 83 EC ? 53 56 57 */ } /* * CTerrorPlayer::OnStaggered(CBaseEntity *, Vector const*) - used by L4D2 on Survivors, causes staggering (e.g. Charger Impact nearby) * * - string "PlayerShoved" has 3 refs, the one furthest into a function should be this one. */ "CTerrorPlayer_OnStaggered" { "library" "server" "linux" "@_ZN13CTerrorPlayer11OnStaggeredEP11CBaseEntityPK6Vector" "windows" "\x53\x8B\xDC\x83\xEC\x2A\x83\xE4\xF0\x83\xC4\x04\x55\x8B\x6B\x04\x89\x6C\x24\x04\x8B\xEC\x83\xEC\x2A\x56\x57\x8B\xF1\xE8\x2A\x2A\x2A\x2A\x84\xC0\x0F\x85\x73\x08" /* 53 8B DC 83 EC ? 83 E4 F0 83 C4 04 55 8B 6B 04 89 6C 24 04 8B EC 83 EC ? 56 57 8B F1 E8 ? ? ? ? 84 C0 0F 85 73 08 * Using a long local jump as the unique portion (last few bytes of sig) */ } /* * CTerrorPlayer::OnShovedBySurvivor(CTerrorPlayer*, Vector const&) - used by L4D2 on Special Infected (got melee'd) * unique string "jockey_ride" in CTerrorPlayer::OnLeptOnSurvivor(), look up for "JockeyZombie.Ride", look up for var_14, CTerrorPlayer::OnShovedBySurvivor is call after that */ "CTerrorPlayer_OnShovedBySurvivor" { "library" "server" "linux" "@_ZN13CTerrorPlayer18OnShovedBySurvivorEPS_RK6Vector" "windows" "\x55\x8B\xEC\x81\xEC\x2A\x2A\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x33\xC5\x89\x45\xFC\x53\x8B\x5D\x0C\x56\x57\x8B\x7D\x08\x8B\xF1" /* 55 8B EC 81 EC ? ? ? ? A1 ? ? ? ? 33 C5 89 45 FC 53 8B 5D 0C 56 57 8B 7D 08 8B F1 */ } /* * CTerrorPlayer::GetWalkTopSpeed(void)const * an xref from GetRunTopSpeed */ "CTerrorPlayer_GetWalkTopSpeed" { "library" "server" "linux" "@_ZNK13CTerrorPlayer15GetWalkTopSpeedEv" "windows" "\x56\x8B\xF1\x80\x2A\x2A\x2A\x2A\x2A\x2A\x74\x2A\x5E\xE9\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x50\xE8" /* 56 8B F1 80 ? ? ? ? ? ? 74 ? 5E E9 ? ? ? ? E8 ? ? ? ? 50 E8 */ } /* * CTerrorPlayer::GetRunTopSpeed(void)const * * - Only references to float value 115.0 (00 00 E6 42) are in this func. */ "CTerrorPlayer_GetRunTopSpeed" { "library" "server" "linux" "@_ZNK13CTerrorPlayer14GetRunTopSpeedEv" "windows" "\x55\x8B\xEC\x83\xEC\x2A\x56\x8B\xF1\x8B\x06\x8B\x90\x2A\x2A\x2A\x2A\xFF\xD2\x84\xC0\x74\x0D\xA1\x2A\x2A\x2A\x2A\xD9\x40\x2A\x5E" /* 55 8B EC 83 EC ? 56 8B F1 8B 06 8B 90 ? ? ? ? FF D2 84 C0 74 0D A1 ? ? ? ? D9 40 ? 5E */ } /* * CTerrorPlayer::GetCrouchTopSpeed(void)const * an xref from GetRunTopSpeed */ "CTerrorPlayer_GetCrouchTopSpeed" { "library" "server" "linux" "@_ZNK13CTerrorPlayer17GetCrouchTopSpeedEv" "windows" "\x56\x8B\xF1\x80\x2A\x2A\x2A\x2A\x2A\x2A\x74\x2A\x5E\xE9\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x83\xF8" /* 56 8B F1 80 ? ? ? ? ? ? 74 ? 5E E9 ? ? ? ? E8 ? ? ? ? 83 F8 */ } /* * CTerrorPlayer::OnRevived(void) * * ->Search for string "revive_success", then open vtables window. Should be the 5th member. * Left4Downtown2 patches this function, which will prevent Sourcemod from finding it * That is why the first six bytes are wild cards (five bytes for detour + nop fill the remaining bytes of the instructions) */ "CTerrorPlayer_OnRevived" { "library" "server" "linux" "@_ZN13CTerrorPlayer9OnRevivedEv" "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x53\x56\x8B\xF1\x8B\x06\x8B\x90\x2A\x2A\x2A\x2A\x57\xff\xd2\x84\xc0\x0f\x84\x2A\x2A\x2A\x2A\x8B\xCE" /* ? ? ? ? ? ? 53 56 8B F1 8B 06 8B 90 ? ? ? ? 57 ff d2 84 c0 0f 84 ? ? ? ? 8B CE */ } /* * GetDifficulty(void) */ "GetDifficulty" { "library" "server" "linux" "@_Z13GetDifficultyv" "windows" "\xA1\x2A\x48\x7A\x10\xC3" /* A1 ? 48 7A 10 C3 */ } /* * CTerrorGameRules::HasConfigurableDifficultySetting(void) * * - Look for string "hasdifficulty" */ "HasConfigurableDifficulty" { "library" "server" "linux" "@_ZN16CTerrorGameRules32HasConfigurableDifficultySettingEv" "windows" "\x8B\x0D\x2A\x2A\x2A\x2A\x85\xC9\x75\x1B\xE8\x2A\x2A\x2A\x2A\x84" /* 8B 0D ? ? ? ? 85 C9 75 1B E8 ? ? ? ? 84 */ } /* * CTerrorGameRules::GetSurvivorSet(void) * * - string "survivor_set" */ "GetSurvivorSet" { "library" "server" "linux" "@_ZN16CTerrorGameRules14GetSurvivorSetEv" "windows" "\x55\x8B\xEC\x51\x8B\x0D\x2A\x2A\x2A\x2A\x8B\x01\x8B\x50\x2A\x53" /* 55 8B EC 51 8B 0D ? ? ? ? 8B 01 8B 50 ? 53 */ } /* * CTerrorGameRules::FastGetSurvivorSet(void) * * - Should be 2 calls after "DistToMechanic" in CTerrorPlayer::ModifyOrAppendCriteria */ "FastGetSurvivorSet" { "library" "server" "linux" "@_ZN16CTerrorGameRules18FastGetSurvivorSetEv" "windows" "\xA1\x2A\x2A\x2A\x2A\x85\xC0\x75\x0A\xE8" /* A1 ? ? ? ? 85 C0 75 0A E8 */ } /* * CDirectorVersusMode::GetMissionVersusBossSpawning(float&, float&, float&, float&) * * - string "versus_boss_spawning" hits in 2 functions: This short func and the much longer InitVersusBossSpawning */ "GetMissionVersusBossSpawning" { "library" "server" "linux" "@_ZN19CDirectorVersusMode28GetMissionVersusBossSpawningERfS0_S0_S0_" "windows" "\x55\x8B\xEC\x6A\x00\xE8\x2A\x2A\x2A\x2A\x83\xC4\x04\x85" /* 55 8B EC 6A 00 E8 ? ? ? ? 83 C4 04 85 */ } /* * CTerrorGameRules::GetMissionCurrentMap(KeyValues **) * * - Look for string "chapter" (unique on windows only) in CDirector:OnMapLoaded. * - Function called right before that with 0 as arg. * NOTE/WARNING: This function is incredibly non-unique!!!! Replace with a native implementation!! */ "GetMissionCurrentMap" { "library" "server" "linux" "@_ZN16CTerrorGameRules20GetMissionCurrentMapEPP9KeyValues" "windows" "\x55\x8B\xEC\x56\x57\x8B\x7D\x08\x85\xFF\x74\x06\xC7\x07\x00\x00\x00\x00\x8B\x0D\x2A\x2A\x2A\x2A\x8B\x01\x8B\x50\x28\xFF\xD2\x8B\x10\x8B\xC8\x8B\x42\x04\x6A\x00\xFF\xD0\x8B\xF0\x85\xF6\x75\x04\x5F\x5E\x5D\xC3\x8B\x0D\x2A\x2A\x2A\x2A\x8B\x11\x8B\x42\x08\x57\x56\xFF\xD0\x8B" /* * 68 byte signature. Fuck me. * 55 8B EC 56 57 8B 7D 08 85 FF 74 06 C7 07 00 00 00 00 8B 0D ? ? ? ? 8B 01 8B 50 28 FF D2 8B 10 8B C8 8B 42 04 6A 00 FF D0 8B F0 85 F6 75 04 5F 5E 5D C3 8B 0D ? ? ? ? 8B 11 8B 42 08 57 56 FF D0 8B */ } /* * CThrow::ActivateAbililty() * Start a tank rock throw * * - "HulkZombie.Throw.Fail" has 2 refs in this function. Should be easy to find. */ "CThrowActivate" { "library" "server" "linux" "@_ZN6CThrow15ActivateAbilityEv" "windows" "\x55\x8B\xEC\x51\x53\x8B\xD9\x8B\x83\x2A\x2A\x2A\x2A\x83" /* 55 8B EC 51 53 8B D9 8B 83 ? ? ? ? 83 */ } /* * CTerrorMeleeWeapon::StartMeleeSwing(CTerrorPlayer *, bool) * * find "melee attack failed - !IsWeaponVisible" in CTerrorWeapon::PrimaryAttack and look for a call (being passed ptr and float) followed by some sse xmm0 calls. */ "StartMeleeSwing" { "library" "server" "linux" "@_ZN18CTerrorMeleeWeapon15StartMeleeSwingEP13CTerrorPlayerb" "windows" "\x55\x8B\xEC\x53\x56\x8B\xF1\x8B\x86\x2A\x2A\x2A\x2A\x50\xB9" /* 55 8B EC 53 56 8B F1 8B 86 ? ? ? ? 50 B9 */ } /* * CDirectorScriptedEventManager::SendInRescueVehicle(void) * * find by String "FinaleEscapeStarted" */ "SendInRescueVehicle" { "library" "server" "linux" "@_ZN29CDirectorScriptedEventManager19SendInRescueVehicleEv" "windows" "\x55\x8B\xEC\x83\xEC\x18\x56\x68\x2A\x2A\x2A\x2A\x8B\xF1" /* 55 8B EC 83 EC 18 56 68 ? ? ? ? 8B F1 */ } /* * CDirectorScriptedEventManager__ChangeFinaleStage(int, char arg, int) * or CDirectorScriptedEventManager::ChangeFinaleStage(CDirectorScriptedEventManager::FinaleStageType,char const*) * * find by String "CHANGEFINALESTAGEOVERRIDE: %s\n" */ "ChangeFinaleStage" { "library" "server" "linux" "@_ZN29CDirectorScriptedEventManager17ChangeFinaleStageENS_18ScriptedEventStageEPKc" "windows" "\x55\x8B\xEC\x81\xEC\x2A\x2A\x00\x00\xA1\x2A\x2A\x2A\x2A\x33\xC5\x89\x45\xFC\x53\x8B\x5D\x08\x56\x8B\x75\x0C\x57\x53" /* 55 8B EC 81 EC ? ? 00 00 A1 ? ? ? ? 33 C5 89 45 FC 53 8B 5D 08 56 8B 75 0C 57 53 */ } /* * CDirectorVersusMode::EndVersusModeRound(bool) * Updates scores using a bunch of CTerrorGameRules calls and triggers the fullscreen_vs_scoreboard viewport panel * * find by String "fullscreen_vs_scoreboard", and look for a func which also creates a "scores" kv and sets values for "t1", "t2", "c1", "c2", and "tiebreak" */ "EndVersusModeRound" { "library" "server" "linux" "@_ZN19CDirectorVersusMode18EndVersusModeRoundEb" "windows" "\x55\x8B\xEC\x83\xEC\x2A\x57\x8B\xF9\xE8\x2A\x2A\x2A\x2A\x84\xC0\x0F\x84" /* 55 8B EC 83 EC ? 57 8B F9 E8 ? ? ? ? 84 C0 0F 84 */ } /* * int CBaseAnimating::SelectWeightedSequence(int Activity) * * - Called at the end of CTerrorPlayer::SelectWeightedSequence() (found via string "Hulk_RunAttack1_Gesture") * NOTE - WARNING - This function should probably be hooked using vtable methods!!!!!!!! DEPRECATE */ "SelectWeightedSequence" { "library" "server" "linux" "@_ZN14CBaseAnimating22SelectWeightedSequenceE8Activity" "windows" "\x55\x8B\xEC\x56\x8B\xF1\x83\xBE\x2A\x2A\x2A\x2A\x00\x57\x8B\xBE" /* 55 8B EC 56 8B F1 83 BE ? ? ? ? 00 57 8B BE */ } /* * InfoChangelevel::StartChangeLevel(Checkpoint const*) * * Used for finding ZombieManager on Windows * - String "Would change level, but not going to!\n" is unique to this function */ "StartChangeLevel" { "library" "server" "linux" "@_ZN15InfoChangelevel16StartChangeLevelEPK10Checkpoint" "windows" "\x55\x8B\xEC\xA1\x2A\x2A\x2A\x2A\x83\x78\x30\x00\x56\x8B\xF1\x74" /* 55 8B EC A1 ? ? ? ? 83 78 30 00 56 8B F1 74 */ } /* * SurvivorBot::UseHealingItems(Action *) * Called by the game when deciding whether the bots should use any healing items * unique string "Trying to heal a friend" */ "UseHealingItems" { "library" "server" "linux" "@_ZN11SurvivorBot15UseHealingItemsEP6ActionIS_E" "windows" "\x55\x8B\xEC\x83\xEC\x20\x53\x56\x8B\xD9\x57\x8D\x8B" /* 55 8B EC 83 EC 20 53 56 8B D9 57 8D 8B */ } /* * SurvivorBot::FindScavengeItem(float) * Called by the game when deciding what items a bot should attempt to pick up * Despite name, has nothing to do with scavenge game mode * SurvivorBot::ScavengeNearbyItems(Action*) has almost unique string "Scavenging something" * FindScavengeItem(float) is called with 420.0 (0x43D20000) as its argument */ "FindScavengeItem" { "library" "server" "linux" "@_ZNK11SurvivorBot16FindScavengeItemEf" "windows" "\x55\x8B\xEC\x81\xEC\x2A\x2A\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x33\xC5\x89\x45\xFC\x53\x56\x57\x8B\xF9\x8B\x97\x2A\x2A\x2A\x2A\x8D\x85" /* 55 8B EC 81 EC ? ? ? ? A1 ? ? ? ? 33 C5 89 45 FC 53 56 57 8B F9 8B 97 ? ? ? ? 8D 85 */ } /* * CTerrorWeapon::OnHit(CGameTrace &, Vector const&, bool) */ "CTerrorWeapon__OnHit" { "library" "server" "linux" "@_ZN13CTerrorWeapon5OnHitER10CGameTraceRK6Vectorb" "windows" "" } /* * CBasePlayer::WaterMove(void) */ "WaterMove" { "library" "server" "linux" "@_ZN11CBasePlayer9WaterMoveEv" "windows" "" } /* * KeyValues *CTerrorGameRules::GetMissionInfo(void) */ "CTerrorGameRules__GetMissionInfo" { "library" "server" "linux" "@_ZN16CTerrorGameRules14GetMissionInfoEv" "windows" "" } /********************************************************************* ********************* ADDONS DISABLER ******************************** *********************************************************************/ /* * CBaseServer::FillServerInfo(SVC_ServerInfo *) */ "CBaseServer__FillServerInfo" { "library" "engine" "linux" "@_ZN11CBaseServer14FillServerInfoER14SVC_ServerInfo" "windows" "" } /* * mov esi+[19h] */ "VanillaModeOffset" { "library" "engine" "linux" "\xC6\x46\x1B\x4C\x88\x46\x19" "windows" "" } /********************************************************************* ****************** PLAYER SLOTS PATCHING ***************************** *********************************************************************/ /* * CTerrorGameRules::GetMaxHumanPlayers(void) * We just override the return value to our own * * This method is called for max players when viewing server info * Overriding this on Linux changes the server browser maxplayers * * On Windows overriding it doesn't fix the server browser, * but it does break scavenge mode (like the map doesn't support scavenge) * * Find via string "playercontrolledzombies", unique in Linux, inlined a few times in Windows * look for an inline that is very short and returns either 8 or 4 as a result * Commented out since the note above suggests it breaks scavenge? * Since it is inlined, its signature will look a LOT like CTerrorGameRules::HasPlayerControlledZombies() * this sig is probably also excessively wild carded (lots of very short local jumps that are probably safe) */ "GetMaxHumanPlayers" { "library" "server" "linux" "@_ZNK16CTerrorGameRules18GetMaxHumanPlayersEv" // "windows" "\xF7\x05\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x74\x2A\xB8\x2A\x2A\x2A\x2A\xEB\x2A\xA1\x2A\x2A\x2A\x2A\x8B\x40\x2A\x85\xC0\x75\x2A\xB8\x2A\x2A\x2A\x2A\x8B\x2A\x2A\x2A\x2A\x2A\x8B\x11\x50\x8B\x2A\x2A\xFF\xD0\x85\xC0\x74\x2A\x6A\x00\x68\x2A\x2A\x2A\x2A\x8B\xC8\xE8\x2A\x2A\x2A\x2A\x85\xC0\xB8" /* F7 05 ? ? ? ? ? ? ? ? 74 ? B8 ? ? ? ? EB ? A1 ? ? ? ? 8B 40 ? 85 C0 75 ? B8 ? ? ? ? 8B ? ? ? ? ? 8B 11 50 8B ? ? FF D0 85 C0 74 ? 6A 00 68 ? ? ? ? 8B C8 E8 ? ? ? ? 85 C0 B8 */ } /* * Total Number of Players Supported (Steam Group/Lobby) * Currently disabled - SourceMod unable to look up other libraries. * "GetTotalNumPlayersSupported" { "library" "matchmaking_ds" "linux" "@_ZN11CMatchTitle27GetTotalNumPlayersSupportedEv" } */ /* CServerGameClients::GetPlayerLimits(int& , int&, int&) * Sig is still broken, cannot find in Windows */ "GetPlayerLimits" { "library" "server" "linux" "@_ZNK18CServerGameClients15GetPlayerLimitsERiS0_S0_" // "windows" "\x8B\x44\x24\x04\x8B\x4C\x24\x08\xC7\x00\x2A\x2A\x2A\x2A\xC7\x01\x2A\x2A\x2A\x2A\x8B\x10" /* 8B 44 24 04 8B 4C 24 08 C7 00 ? ? ? ? C7 01 ? ? ? ? 8B 10 */ } /* * int CBaseServer::GetMasterServerPlayerCounts(int &, int &, int &) * * Used to override server browser maxplayers reporting (Windows) * Search for string: "increased_maxplayers", call is just before the string */ "GetMasterServerPlayerCounts" { "library" "engine" "linux" "@_ZN11CBaseServer27GetMasterServerPlayerCountsERiS0_S0_" "windows" "\x55\x8B\xEC\x56\x8B\xF1\xE8\x2A\x2A\x2A\x2A\x8B\x4D\x2A\x89\x01\x8B\x0D\x2A\x2A\x2A\x2A\x85\xC9\x74" /* windows: 55 8B EC 56 8B F1 E8 ? ? ? ? 8B 4D ? 89 01 8B 0D ? ? ? ? 85 C9 74 */ } /* Not an actual function, this is inside CBaseServer::ConnectClient (a jz instruction) use it to remove skippable code when sv_allow_lobby_connect 0 */ "ConnectClientLobbyCheck" { /* look for jz between "#Valve_Reject_Server_Full" and "#Valve_Reject_Bad_Password" in Windows * On Linux, this points directy at the cmp for "#Valve_Reject_Server_Full" instead of the jz for the lobby * For 2.1.2.5 this offset was ebx+17Ch on Linux and esi+180h on Windows */ "library" "engine" "linux" "\x3B\xB3\x2A\x2A\x2A\x2A\x0F\x8E\x2A\x2A\x2A\x2A\x8B\x03\xC7\x44\x24\x08\x2A\x2A\x2A\x2A\x89" /* 3B B3 ? ? ? ? 0F 8E ? ? ? ? 8B 03 C7 44 24 08 ? ? ? ? 89 */ "windows" "\x74\x2A\x8B\x55\x2A\x8B\x06\x8B\x7A\x2A\x8B\x50" /* windows: 74 ? 8B 55 ? 8B 06 8B 7A ? 8B 50 */ } /* Not an actual function, This rejects players when there are all full human players jl just before string "Human player limit reached (%d/%d)" deprecated on linux: This function checks GetMaxHumanPlayers on linux, so patching this to an unconditional jump removes a check on maxplayers. */ "HumanPlayerLimitReached" { "library" "server" // "linux" "\x7E\x2A\x8B\x2A\x2A\x89\x2A\x2A\x2A\x8B\x2A\x2A\x89\x2A\x2A\x2A\x8B\x2A\x2A\x89\x2A\x2A\x2A\x8B\x2A\x2A\x89\x2A\x2A\x2A\x8B\x2A\x2A\x89\x2A\x2A\x2A\x8B\x2A\x2A" /* linux: 7E ? 8B ? ? 89 ? ? ? 8B ? ? 89 ? ? ? 8B ? ? 89 ? ? ? 8B ? ? 89 ? ? ? 8B ? ? 89 ? ? ? 8B ? ? */ "windows" "\x7C\x2A\x8B\x4D\x2A\x8B\x55\x2A\x50\x57\x68" /* windows: 7C ? 8B 4D ? 8B 55 ? 50 57 68 */ } /********************************************************************* ****************** MISC USEFUL NATIVES ******************************* *********************************************************************/ /* CTerrorGameRules::IsMissionFinalMap() Uses campaign mission file to determine if the current map is a Final(e) map. Called from CDirectorVersusMode::EndVersusModeRound(), look near string "versus_match_finished" */ "IsMissionFinalMap" { "library" "server" "linux" "@_ZN16CTerrorGameRules17IsMissionFinalMapEv" "windows" "\x8B\x0D\x2A\x2A\x2A\x2A\x8B\x01\x8B\x50\x28\x56\xFF\xD2\x8B\x10\x8B\xC8\x8B\x42\x04\x6A\x00\xFF\xD0\x8B\xF0\x85\xF6\x75\x04\xB0" /* 8B 0D ? ? ? ? 8B 01 8B 50 28 56 FF D2 8B 10 8B C8 8B 42 04 6A 00 FF D0 8B F0 85 F6 75 04 B0 */ } /* CDirector::ResetMobTimer() Resets the Director's natural horde timer. Normally this is called when a horde is spawned naturally or by boomer. Small function, nearly hits another segment in the file. - Find it through only xref, which is setting up ScriptDesc structures: string "Trigger a mob as soon as possible when" - If you go past the first call, you should hit unique bytes in sig making */ "ResetMobTimer" { "library" "server" "linux" "@_ZN9CDirector13ResetMobTimerEv" "windows" "\x55\x8B\xEC\x51\x56\x57\x8D\xB9\x2A\x2A\x2A\x2A\x8B\xCF\xE8\x2A\x2A\x2A\x2A\xD9" /* 55 8B EC 51 56 57 8D B9 ? ? ? ? 8B CF E8 ? ? ? ? D9 */ } /* CGameRulesProxy::NotifyNetworkStateChanged() This function is called before changing a variety of pieces of networked data (data which is reflected in network game states). - Find "Going to intermission...\n" in CGameRules::GoToIntermission - Last call in the func */ "NotifyNetworkStateChanged" { "library" "server" "linux" "@_ZN15CGameRulesProxy25NotifyNetworkStateChangedEv" "windows" "\xA1\x2A\x2A\x2A\x2A\x85\xC0\x74\x2A\x80\x78" /* A1 ? ? ? ? 85 C0 74 ? 80 78 */ } } } }