diff --git a/src/Features/ConfigPlus.cpp b/src/Features/ConfigPlus.cpp index 87e702fe..f6c81fd7 100644 --- a/src/Features/ConfigPlus.cpp +++ b/src/Features/ConfigPlus.cpp @@ -395,6 +395,7 @@ static const char *gameName() { case SourceGame_ThinkingWithTimeMachine: return "twtm"; case SourceGame_PortalReloaded: return "reloaded"; case SourceGame_Portal2: return Game::IsSpeedrunMod() ? "srm" : "portal2"; + case SourceGame_Portal2_2011: return "portal2"; case SourceGame_INFRA: return "infra"; case SourceGame_BeginnersGuide: return "guide"; case SourceGame_StanleyParable: return "stanley"; diff --git a/src/Features/Hud/CheatWarn.cpp b/src/Features/Hud/CheatWarn.cpp index fef81af8..f7ca202d 100644 --- a/src/Features/Hud/CheatWarn.cpp +++ b/src/Features/Hud/CheatWarn.cpp @@ -58,7 +58,7 @@ static Cheat g_cheats[] = { { +[]() { auto map = engine->GetCurrentMapName(); - if (!sar.game->Is(SourceGame_Portal2)) return false; + if (!sar.game->Is(SourceGame_Portal2 | SourceGame_Portal2_2011)) return false; if (map == "sp_a2_bts5") return false; if (engine->GetMapIndex(map) == -1) return false; return sv_allow_mobile_portals.GetBool(); diff --git a/src/Features/Hud/LPHud.cpp b/src/Features/Hud/LPHud.cpp index 6799cbf2..268354c2 100644 --- a/src/Features/Hud/LPHud.cpp +++ b/src/Features/Hud/LPHud.cpp @@ -39,16 +39,20 @@ static int getCurrentCount() { // Get the current total portal count as reported by the the players' // m_StatsThisLevel values static int getStatsCount() { - int total = 0; + if (!sar.game->Is(SourceGame_Portal2_2011)) { + int total = 0; + + int slots = engine->GetMaxClients() >= 2 ? 2 : 1; + for (int slot = 0; slot < slots; ++slot) { + ClientEnt *player = client->GetPlayer(slot + 1); + if (!player) continue; + total += player->field("iNumPortalsPlaced"); + } - int slots = engine->GetMaxClients() >= 2 ? 2 : 1; - for (int slot = 0; slot < slots; ++slot) { - ClientEnt *player = client->GetPlayer(slot + 1); - if (!player) continue; - total += player->field("iNumPortalsPlaced"); + return total; + } else { + return 0; } - - return total; } // Calculate an up-to-date total portal count using the player stats and diff --git a/src/Features/Speedrun/SpeedrunTimer.cpp b/src/Features/Speedrun/SpeedrunTimer.cpp index 2d8a8b55..4ac47b7d 100644 --- a/src/Features/Speedrun/SpeedrunTimer.cpp +++ b/src/Features/Speedrun/SpeedrunTimer.cpp @@ -214,6 +214,7 @@ ON_EVENT(SESSION_START) { if (!sar_speedrun_skip_cutscenes.GetBool()) return; if (engine->IsOrange()) return; switch (sar.game->GetVersion()) { + case SourceGame_Portal2_2011: case SourceGame_Portal2: if (Game::IsSpeedrunMod()) return; @@ -335,7 +336,7 @@ int SpeedrunTimer::GetSegmentTicks() { int ticks = 0; ticks += g_speedrun.saved; if (!g_speedrun.isPaused && !g_speedrun.inCoopPause && (!engine->demoplayer->IsPlaying() || engine->demoplayer->IsPlaybackFixReady())) { - if (sar_speedrun_skip_cutscenes.GetBool() && sar.game->GetVersion() == SourceGame_Portal2 && !Game::IsSpeedrunMod()) { + if (sar_speedrun_skip_cutscenes.GetBool() && sar.game->Is(SourceGame_Portal2 | SourceGame_Portal2_2011) && !Game::IsSpeedrunMod()) { if (g_speedrun.lastMap == "sp_a2_bts6") return 3112; else if (g_speedrun.lastMap == "sp_a3_00") return 4666; } diff --git a/src/Game.cpp b/src/Game.cpp index d9339aef..429f3288 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -3,11 +3,13 @@ #include "Command.hpp" #include "Modules/Engine.hpp" #include "Utils.hpp" +#include "Interface.hpp" #include #include #include "Games/Portal2.hpp" +#include "Games/Portal2_2011.hpp" #include "Games/ApertureTag.hpp" #include "Games/PortalStoriesMel.hpp" #include "Games/PortalReloaded.hpp" @@ -76,7 +78,13 @@ Game *Game::CreateNew() { modDir = GetModDir(TARGET_MOD); if (Utils::ICompare(modDir, Portal2::ModDir())) { - return new Portal2(); + + void *engineClient = Interface::GetPtr(MODULE("engine"), "VEngineClient015", false); + if (engineClient) { + return new Portal2(); + } else { + return new Portal2_2011(); + } } if (Utils::ICompare(modDir, PortalStoriesMel::ModDir())) { @@ -105,6 +113,7 @@ std::string Game::VersionToString(int version) { auto games = std::string(""); while (version > 0) { HAS_GAME_FLAG(SourceGame_Portal2, "Portal 2") + HAS_GAME_FLAG(SourceGame_Portal2_2011, "Portal 2") HAS_GAME_FLAG(SourceGame_ApertureTag, "Aperture Tag") HAS_GAME_FLAG(SourceGame_PortalStoriesMel, "Portal Stories: Mel") HAS_GAME_FLAG(SourceGame_ThinkingWithTimeMachine, "Thinking with Time Machine") diff --git a/src/Game.hpp b/src/Game.hpp index 6050f67a..8eeec84b 100644 --- a/src/Game.hpp +++ b/src/Game.hpp @@ -6,6 +6,7 @@ enum SourceGameVersion { SourceGame_Unknown = 0, SourceGame_Portal2 = (1 << 0), + SourceGame_Portal2_2011 = (1 << 1), SourceGame_ApertureTag = (1 << 5), SourceGame_PortalStoriesMel = (1 << 6), SourceGame_ThinkingWithTimeMachine = (1 << 7), diff --git a/src/Games/Portal2_2011.cpp b/src/Games/Portal2_2011.cpp new file mode 100644 index 00000000..93c5483e --- /dev/null +++ b/src/Games/Portal2_2011.cpp @@ -0,0 +1,185 @@ +#include "Portal2_2011.hpp" + +#include "Game.hpp" +#include "Offsets.hpp" + +Portal2_2011::Portal2_2011() { + this->version = SourceGame_Portal2_2011; + Game::maps = { + {"sp_a1_intro1", "Container Ride", "62761"}, + {"sp_a1_intro2", "Portal Carousel", "62758"}, + {"sp_a1_intro3", "Portal Gun", "47458"}, + {"sp_a1_intro4", "Smooth Jazz", "47455"}, + {"sp_a1_intro5", "Cube Momentum", "47452"}, + {"sp_a1_intro6", "Future Starter", "47106"}, + {"sp_a1_intro7", "Secret Panel", "62763"}, + {"sp_a1_wakeup", "Wakeup", "62759"}, + {"sp_a2_intro", "Incinerator", "47735"}, + {"sp_a2_laser_intro", "Laser Intro", "62765"}, + {"sp_a2_laser_stairs", "Laser Stairs", "47736"}, + {"sp_a2_dual_lasers", "Dual Lasers", "47738"}, + {"sp_a2_laser_over_goo", "Laser Over Goo", "47742"}, + {"sp_a2_catapult_intro", "Catapult Intro", "62767"}, + {"sp_a2_trust_fling", "Trust Fling", "47744"}, + {"sp_a2_pit_flings", "Pit Flings", "47465"}, + {"sp_a2_fizzler_intro", "Fizzler Intro", "47746"}, + {"sp_a2_sphere_peek", "Ceiling Catapult", "47748"}, + {"sp_a2_ricochet", "Ricochet", "47751"}, + {"sp_a2_bridge_intro", "Bridge Intro", "47752"}, + {"sp_a2_bridge_the_gap", "Bridge The Gap", "47755"}, + {"sp_a2_turret_intro", "Turret Intro", "47756"}, + {"sp_a2_laser_relays", "Laser Relays", "47759"}, + {"sp_a2_turret_blocker", "Turret Blocker", "47760"}, + {"sp_a2_laser_vs_turret", "Laser vs Turret", "47763"}, + {"sp_a2_pull_the_rug", "Pull the Rug", "47764"}, + {"sp_a2_column_blocker", "Column Blocker", "47766"}, + {"sp_a2_laser_chaining", "Laser Chaining", "47768"}, + {"sp_a2_triple_laser", "Triple Laser", "47770"}, + {"sp_a2_bts1", "Jailbreak", "47773"}, + {"sp_a2_bts2", "Escape", "47774"}, + {"sp_a2_bts3", "Turret Factory", "47776"}, + {"sp_a2_bts4", "Turret Sabotage", "47779"}, + {"sp_a2_bts5", "Neurotoxin Sabotage", "47780"}, + {"sp_a2_bts6", "Tube Ride", ""}, + {"sp_a2_core", "Core", "62771"}, + {"sp_a3_00", "Long Fall", ""}, + {"sp_a3_01", "Underground", "47783"}, + {"sp_a3_03", "Cave Johnson", "47784"}, + {"sp_a3_jump_intro", "Repulsion Intro", "47787"}, + {"sp_a3_bomb_flings", "Bomb Flings", "47468"}, + {"sp_a3_crazy_box", "Crazy Box", "47469"}, + {"sp_a3_transition01", "PotatOS", "47472"}, + {"sp_a3_speed_ramp", "Propulsion Intro", "47791"}, + {"sp_a3_speed_flings", "Propulsion Flings", "47793"}, + {"sp_a3_portal_intro", "Conversion Intro", "47795"}, + {"sp_a3_end", "Three Gels", "47798"}, + {"sp_a4_intro", "Test", "88350"}, + {"sp_a4_tb_intro", "Funnel Intro", "47800"}, + {"sp_a4_tb_trust_drop", "Ceiling Button", "47802"}, + {"sp_a4_tb_wall_button", "Wall Button", "47804"}, + {"sp_a4_tb_polarity", "Polarity", "47806"}, + {"sp_a4_tb_catch", "Funnel Catch", "47808"}, + {"sp_a4_stop_the_box", "Stop the Box", "47811"}, + {"sp_a4_laser_catapult", "Laser Catapult", "47813"}, + {"sp_a4_laser_platform", "Laser Platform", "47815"}, + {"sp_a4_speed_tb_catch", "Propulsion Catch", "47817"}, + {"sp_a4_jump_polarity", "Repulsion Polarity", "47819"}, + {"sp_a4_finale1", "Finale 1", "62776"}, + {"sp_a4_finale2", "Finale 2", "47821"}, + {"sp_a4_finale3", "Finale 3", "47824"}, + {"sp_a4_finale4", "Finale 4", "47456"}, + {"mp_coop_start", "Calibration", ""}, + {"mp_coop_lobby_2", "Lobby (pre-DLC)", ""}, + {"mp_coop_doors", "Doors", "47741"}, + {"mp_coop_race_2", "Buttons", "47825"}, + {"mp_coop_laser_2", "Lasers", "47828"}, + {"mp_coop_rat_maze", "Rat Maze", "47829"}, + {"mp_coop_laser_crusher", "Laser Crusher", "45467"}, + {"mp_coop_teambts", "Behind the Scenes", "46362"}, + {"mp_coop_fling_3", "Flings", "47831"}, + {"mp_coop_infinifling_train", "Infinifling", "47833"}, + {"mp_coop_come_along", "Team Retrieval", "47835"}, + {"mp_coop_fling_1", "Vertical Flings", "47837"}, + {"mp_coop_catapult_1", "Catapults", "47840"}, + {"mp_coop_multifling_1", "Multifling", "47841"}, + {"mp_coop_fling_crushers", "Fling Crushers", "47844"}, + {"mp_coop_fan", "Industrial Fan", "47845"}, + {"mp_coop_wall_intro", "Cooperative Bridges", "47848"}, + {"mp_coop_wall_2", "Bridge Swap", "47849"}, + {"mp_coop_catapult_wall_intro", "Fling Block", "47854"}, + {"mp_coop_wall_block", "Catapult Block", "47856"}, + {"mp_coop_catapult_2", "Bridge Fling", "47858"}, + {"mp_coop_turret_walls", "Turret Walls", "47861"}, + {"mp_coop_turret_ball", "Turret Assassin", "52642"}, + {"mp_coop_wall_5", "Bridge Testing", "52660"}, + {"mp_coop_tbeam_redirect", "Cooperative Funnels", "52662"}, + {"mp_coop_tbeam_drill", "Funnel Drill", "52663"}, + {"mp_coop_tbeam_catch_grind_1", "Funnel Catch Coop", "52665"}, + {"mp_coop_tbeam_laser_1", "Funnel Laser", "52667"}, + {"mp_coop_tbeam_polarity", "Cooperative Polarity", "52671"}, + {"mp_coop_tbeam_polarity2", "Funnel Hop", "52687"}, + {"mp_coop_tbeam_polarity3", "Advanced Polarity", "52689"}, + {"mp_coop_tbeam_maze", "Funnel Maze", "52691"}, + {"mp_coop_tbeam_end", "Turret Warehouse", "52777"}, + {"mp_coop_paint_come_along", "Repulsion Jumps", "52694"}, + {"mp_coop_paint_redirect", "Double Bounce", "52711"}, + {"mp_coop_paint_bridge", "Bridge Repulsion", "52714"}, + {"mp_coop_paint_walljumps", "Wall Repulsion", "52715"}, + {"mp_coop_paint_speed_fling", "Propulsion Crushers", "52717"}, + {"mp_coop_paint_red_racer", "Turret Ninja", "52735"}, + {"mp_coop_paint_speed_catch", "Propulsion Retrieval", "52738"}, + {"mp_coop_paint_longjump_intro", "Vault Entrance", "52740"}, + }; + + Game::mapNames = {}; + for (const auto &map : Game::maps) { + Game::mapNames.push_back(map.fileName); + } + + Game::achievements = { + {"ACH.SURVIVE_CONTAINER_RIDE", "Wake Up Call", false}, + {"ACH.WAKE_UP", "You Monster", false}, + {"ACH.LASER", "Undiscouraged", false}, + {"ACH.BRIDGE", "Bridge Over Troubling Water", false}, + {"ACH.BREAK_OUT", "SaBOTour", false}, + {"ACH.STALEMATE_ASSOCIATE", "Stalemate Associate", false}, + {"ACH.ADDICTED_TO_SPUDS", "Tater Tote", false}, + {"ACH.BLUE_GEL", "Vertically Unchallenged", false}, + {"ACH.ORANGE_GEL", "Stranger Than Friction", false}, + {"ACH.WHITE_GEL", "White Out", false}, + {"ACH.TRACTOR_BEAM", "Tunnel of Funnel", false}, + {"ACH.TRIVIAL_TEST", "Dual Pit Experiment", false}, + {"ACH.WHEATLEY_TRIES_TO", "The Part Where He Kills You", false}, + {"ACH.SHOOT_THE_MOON", "Lunacy", false}, + {"ACH.BOX_HOLE_IN_ONE", "Drop Box", false}, + {"ACH.SPEED_RUN_LEVEL", "Overclocker", false}, + {"ACH.COMPLIANT", "Pit Boss", false}, + {"ACH.SAVE_CUBE", "Preservation of Mass", false}, + {"ACH.LAUNCH_TURRET", "Pturretdactyl", false}, + {"ACH.CLEAN_UP", "Final Transmission", false}, + {"ACH.REENTER_TEST_CHAMBERS", "Good Listener", false}, + {"ACH.NOT_THE_DROID", "Scanned Alone", false}, + {"ACH.SAVE_REDEMPTION_TURRET", "No Hard Feelings", false}, + {"ACH.CATCH_CRAZY_BOX", "Schrodinger's Catch", false}, + {"ACH.NO_BOAT", "Ship Overboard", false}, + {"ACH.A3_DOORS", "Door Prize", false}, + {"ACH.PORTRAIT", "Portrait of a Lady", false}, + {"ACH.DEFIANT", "You Made Your Point", false}, + {"ACH.BREAK_MONITORS", "Smash TV", false}, + {"ACH.HI_FIVE_YOUR_PARTNER", "High Five", true}, + {"ACH.TEAM_BUILDING", "Team Building", true}, + {"ACH.MASS_AND_VELOCITY", "Confidence Building", true}, + {"ACH.HUG_NAME", "Bridge Building", true}, + {"ACH.EXCURSION_FUNNELS", "Obstacle Building", true}, + {"ACH.NEW_BLOOD", "You Saved Science", true}, + {"ACH.NICE_CATCH", "Iron Grip", true}, + {"ACH.TAUNTS", "Gesticul-8", true}, + {"ACH.YOU_MONSTER", "Can't Touch This", true}, + {"ACH.PARTNER_DROP", "Empty Gesture", true}, + {"ACH.PARTY_OF_THREE", "Party of Three", true}, + {"ACH.PORTAL_TAUNT", "Narbacular Drop", true}, + {"ACH.TEACHER", "Professor Portal", true}, + {"ACH.WITH_STYLE", "Air Show", true}, + {"ACH.LIMITED_PORTALS", "Portal Conservation Society", true}, + {"ACH.FOUR_PORTALS", "Four Ring Circus", true}, + {"ACH.SPEED_RUN_COOP", "Triple Crown", true}, + {"ACH.STAYING_ALIVE", "Still Alive", true}, + {"ACH.TAUNT_CAMERA", "Asking for Trouble", true}, + {"ACH.ROCK_CRUSHES_ROBOT", "Rock Portal Scissors", true}, + {"ACH.SPREAD_THE_LOVE", "Friends List With Benefits", true} + }; +} +void Portal2_2011::LoadOffsets() { + using namespace Offsets; + + #include "Offsets/Portal 2 4554.hpp" +} +const char *Portal2_2011::Version() { + return "Portal 2 4554"; +} +const float Portal2_2011::Tickrate() { + return 60; +} +const char *Portal2_2011::ModDir() { + return "portal2"; +} diff --git a/src/Games/Portal2_2011.hpp b/src/Games/Portal2_2011.hpp new file mode 100644 index 00000000..62658d85 --- /dev/null +++ b/src/Games/Portal2_2011.hpp @@ -0,0 +1,12 @@ +#pragma once +#include "Game.hpp" + +class Portal2_2011 : public Game { +public: + Portal2_2011(); + void LoadOffsets() override; + const char *Version() override; + const float Tickrate() override; + + static const char *ModDir(); +}; diff --git a/src/Interface.cpp b/src/Interface.cpp index f289f493..61508079 100644 --- a/src/Interface.cpp +++ b/src/Interface.cpp @@ -73,7 +73,7 @@ void Interface::Delete(Interface *ptr) { ptr = nullptr; } } -void *Interface::GetPtr(const char *filename, const char *interfaceSymbol) { +void *Interface::GetPtr(const char *filename, const char *interfaceSymbol, bool shouldTryLowerVersion) { auto handle = Memory::GetModuleHandleByName(filename); if (!handle) { console->DevWarning("SAR: Failed to open module %s!\n", filename); @@ -92,8 +92,17 @@ void *Interface::GetPtr(const char *filename, const char *interfaceSymbol) { void *fn = CreateInterface(interfaceSymbol, &ret); if (ret) { - auto CreateInterfaceInternal = Memory::Read((uintptr_t)CreateInterface + Offsets::CreateInterfaceInternal); - auto s_pInterfaceRegs = Memory::DerefDeref(CreateInterfaceInternal + Offsets::s_pInterfaceRegs); + uintptr_t CreateInterfaceInternal; + InterfaceReg *s_pInterfaceRegs; + // hacky: if offsets aren't initialized then just hardcode the offsets + // (this is currently only for differentiating 2011/latest p2) + if (Offsets::CreateInterfaceInternal && Offsets::s_pInterfaceRegs) { + CreateInterfaceInternal = Memory::Read((uintptr_t)CreateInterface + Offsets::CreateInterfaceInternal); + s_pInterfaceRegs = Memory::DerefDeref(CreateInterfaceInternal + Offsets::s_pInterfaceRegs); + } else { + CreateInterfaceInternal = Memory::Read((uintptr_t)CreateInterface + 5); + s_pInterfaceRegs = Memory::DerefDeref(CreateInterfaceInternal + 6); + } if (!CreateInterfaceInternal || !s_pInterfaceRegs) { console->DevWarning("SAR: Failed to find interface with symbol %s in %s! (old method failed)\n", interfaceSymbol, filename); @@ -108,7 +117,7 @@ void *Interface::GetPtr(const char *filename, const char *interfaceSymbol) { } } - if (!fn) { + if (!fn && shouldTryLowerVersion) { // Interface012 -> Interface0 // Try to get any version of the interface if (interfaceSymbol[std::strlen(interfaceSymbol) - 3] >= '0' && interfaceSymbol[std::strlen(interfaceSymbol) - 3] <= '9') { diff --git a/src/Interface.hpp b/src/Interface.hpp index ec99f31c..dca5eea5 100644 --- a/src/Interface.hpp +++ b/src/Interface.hpp @@ -61,7 +61,7 @@ class Interface { static Interface *Create(void *ptr, bool copyVtable = true, bool autoHook = true); static Interface *Create(const char *filename, const char *interfaceSymbol, bool copyVtable = true, bool autoHook = true); static void Delete(Interface *ptr); - static void *GetPtr(const char *filename, const char *interfaceSymbol); + static void *GetPtr(const char *filename, const char *interfaceSymbol, bool shouldTryLowerVersion = true); template static T Get(const char *filename, const char *interfaceSymbol) { diff --git a/src/Modules/Client.cpp b/src/Modules/Client.cpp index e626c6c4..df49146a 100644 --- a/src/Modules/Client.cpp +++ b/src/Modules/Client.cpp @@ -499,7 +499,7 @@ DETOUR(Client::MsgFunc_SayText2, bf_read &msg) { char c = (char)(uint8_t)msg.ReadUnsigned(8); if (!c) break; } - } else if (sar.game->Is(SourceGame_PortalReloaded)) { + } else if (sar.game->Is(SourceGame_PortalReloaded | SourceGame_Portal2_2011)) { // Reloaded uses the legacy format where it's just one string while (true) { char c = (char)(uint8_t)msg.ReadUnsigned(8); @@ -1008,7 +1008,7 @@ bool Client::Init() { if (sar.game->Is(SourceGame_Portal2)) { this->g_HudChat->Hook(Client::MsgFunc_SayText2_Hook, Client::MsgFunc_SayText2, Offsets::MsgFunc_SayText2); this->g_HudChat->Hook(Client::GetTextColorForClient_Hook, Client::GetTextColorForClient, Offsets::GetTextColorForClient); - } else if (sar.game->Is(SourceGame_PortalReloaded)) { + } else if (sar.game->Is(SourceGame_PortalReloaded | SourceGame_Portal2_2011)) { this->g_HudChat->Hook(Client::MsgFunc_SayText2_Hook, Client::MsgFunc_SayText2, Offsets::MsgFunc_SayTextReloaded); } } else { @@ -1163,6 +1163,9 @@ bool Client::Init() { if (readJmp) { cbk = Memory::Read(cbk + 1); } + if (sar.game->Is(SourceGame_Portal2_2011)) { + cbk = Memory::Read(cbk + 3); + } // OpenRadialMenuCommand is inlined on Windows #ifndef _WIN32 cbk = Memory::Read(cbk + Offsets::OpenRadialMenuCommand); diff --git a/src/Modules/EngineDemoRecorder.cpp b/src/Modules/EngineDemoRecorder.cpp index c89d1867..95ba0189 100644 --- a/src/Modules/EngineDemoRecorder.cpp +++ b/src/Modules/EngineDemoRecorder.cpp @@ -354,7 +354,7 @@ bool EngineDemoRecorder::Init() { this->s_ClientDemoRecorder->Hook(EngineDemoRecorder::SetSignonState_Hook, EngineDemoRecorder::SetSignonState, Offsets::SetSignonState); this->s_ClientDemoRecorder->Hook(EngineDemoRecorder::StartRecording_Hook, EngineDemoRecorder::StartRecording, Offsets::StartRecording); this->s_ClientDemoRecorder->Hook(EngineDemoRecorder::StopRecording_Hook, EngineDemoRecorder::StopRecording, Offsets::StopRecording); - if (!sar.game->Is(SourceGame_INFRA)) { + if (!sar.game->Is(SourceGame_INFRA | SourceGame_Portal2_2011)) { this->s_ClientDemoRecorder->Hook(EngineDemoRecorder::RecordCustomData_Hook, EngineDemoRecorder::RecordCustomData, Offsets::RecordCustomData); } diff --git a/src/Modules/Matchmaking.cpp b/src/Modules/Matchmaking.cpp index de637348..d8a45ee3 100644 --- a/src/Modules/Matchmaking.cpp +++ b/src/Modules/Matchmaking.cpp @@ -12,7 +12,7 @@ DETOUR(Matchmaking::UpdateLeaderboardData, KeyValues *a2) { Hook g_UpdateLeaderboardDataHook(&Matchmaking::UpdateLeaderboardData_Hook); bool Matchmaking::Init() { - if (!sar.game->Is(SourceGame_Portal2)) { + if (!sar.game->Is(SourceGame_Portal2 | SourceGame_Portal2_2011)) { Matchmaking::UpdateLeaderboardData = (decltype(Matchmaking::UpdateLeaderboardData))Memory::Scan(this->Name(), Offsets::UpdateLeaderboardData); g_UpdateLeaderboardDataHook.SetFunc(Matchmaking::UpdateLeaderboardData); diff --git a/src/Modules/MaterialSystem.cpp b/src/Modules/MaterialSystem.cpp index bbd7fca9..5511b225 100644 --- a/src/Modules/MaterialSystem.cpp +++ b/src/Modules/MaterialSystem.cpp @@ -57,7 +57,7 @@ DETOUR(MaterialSystem::UncacheUnusedMaterials, bool bRecomputeStateSnapshots) { } DETOUR_T(IMaterial *, MaterialSystem::CreateMaterial, const char *pMaterialName, void *pVMTKeyValues) { - if (sar.game->Is(SourceGame_Portal2 | SourceGame_PortalReloaded | SourceGame_PortalStoriesMel)) { + if (sar.game->Is(SourceGame_Portal2 | SourceGame_Portal2_2011 | SourceGame_PortalReloaded | SourceGame_PortalStoriesMel)) { // Patched by Valve, no need for us to do it again return MaterialSystem::CreateMaterial(thisptr, pMaterialName, pVMTKeyValues); } diff --git a/src/Modules/Server.cpp b/src/Modules/Server.cpp index a30835c6..58d4d119 100644 --- a/src/Modules/Server.cpp +++ b/src/Modules/Server.cpp @@ -945,7 +945,7 @@ bool Server::Init() { g_check_stuck_code = (void *)code; } - if (sar.game->Is(SourceGame_Portal2)) { + if (sar.game->Is(SourceGame_Portal2 | SourceGame_Portal2_2011)) { Server::IsInPVS = (Server::_IsInPVS)Memory::Scan(this->Name(), Offsets::IsInPVS); g_IsInPVS_Hook.SetFunc(IsInPVS); } @@ -960,7 +960,7 @@ bool Server::Init() { } } - if (sar.game->Is(SourceGame_Portal2)) { + if (sar.game->Is(SourceGame_Portal2 | SourceGame_Portal2_2011)) { CreateViewModel = Memory::Read(Memory::Scan(this->Name(), Offsets::CreateViewModel, 1)); } diff --git a/src/Offsets/Portal 2 4554.hpp b/src/Offsets/Portal 2 4554.hpp new file mode 100644 index 00000000..6ef9d7d4 --- /dev/null +++ b/src/Offsets/Portal 2 4554.hpp @@ -0,0 +1,129 @@ +#include "Offsets/Portal 2 5723.hpp" + +/* anything not mentioned in this file could be wrong/most likely was not checked */ + +// Client +// stolen from Beginner's Guide +SIGSCAN_WINDOWS(MatrixBuildRotationAboutAxis, "55 8B EC 51 F3 0F 10 45 ? 0F 5A C0 F2 0F 59 05 ? ? ? ? 66 0F 5A C0 F3 0F 11 45 ? F3 0F 5A C0 E8 ? ? ? ? F2 0F 5A C0 F3 0F 11 45 ? F3 0F 10 45 ? 0F 5A C0 E8 ? ? ? ? 8B 45 ? F3 0F 10 60") + +// stolen from Infra +SIGSCAN_WINDOWS(DrawTranslucentRenderables, "55 8B EC 81 EC 80 00 00 00 53 56 8B F1") + +// same as something else but I found myself +OFFSET_WINDOWS(HostState_OnClientConnected, 695) + +OFFSET_WINDOWS(gamerules, 5) + +//stolen +OFFSET_WINDOWS(tickcount, 103) +OFFSET_WINDOWS(interval_per_tick, 73) + +OFFSET_WINDOWS(GetLocalClient, 138) + +// CEngineAPI +// all good + +// CEngineClient +// this game version doesn't have GetDemoHeaderInfo at index 36, so everything past 35 is -1 compared to latest +OFFSET_WINDOWS(GetLevelNameShort, 52) +OFFSET_WINDOWS(DebugDrawPhysCollide, 74) +OFFSET_WINDOWS(IsPaused, 85) +OFFSET_WINDOWS(ExecuteClientCmd, 103) +OFFSET_WINDOWS(GetSaveDirName, 123) +OFFSET_WINDOWS(GetActiveSplitScreenPlayerSlot, 126) +OFFSET_WINDOWS(GetSteamAPIContext, 176) + +// CHLClient +//OFFSET_DEFAULT(GetAllClasses, 8, 8) // verified +//OFFSET_DEFAULT(HudProcessInput, 10, 10) // verified +//OFFSET_WINDOWS(HudUpdate, 11) // found, if needed +//OFFSET_DEFAULT(IN_ActivateMouse, 15, 15) // verified +//OFFSET_DEFAULT(IN_DeactivateMouse, 16, 16) // verified +OFFSET_WINDOWS(ApplyMouse, 53) // found myself +OFFSET_EMPTY(SteamControllerMove) // THIS DOES NOT EXIST IN 2011!!!! (because the Steam Controller didn't exist in 2011) +//OFFSET_WINDOWS(JoyStickApplyMovement, 60) // found, if needed +//OFFSET_DEFAULT(LevelInitPreEntity, 5, 5) // verified + +// CVEngineServer +// all good + +// vgui stuff, pretty sure I just stole these from another version, no idea if they are correct, +// but the game doesn't crash. +OFFSET_WINDOWS(DrawColoredCircle, 158) +OFFSET_WINDOWS(DrawColoredText, 159) +OFFSET_WINDOWS(DrawTextLen, 162) + +// CMaterialSystem - more stuff could be wrong, dunno, don't care to check +OFFSET_WINDOWS(UncacheUnusedMaterials, 76) // confirmed +OFFSET_WINDOWS(CreateMaterial, 80) // confirmed +OFFSET_WINDOWS(FindMaterial, 81) // confirmed +OFFSET_WINDOWS(CreateProceduralTexture, 89) // confirmed +OFFSET_WINDOWS(GetRenderContext, 111) // found myself +OFFSET_WINDOWS(RemoveMaterial, 153) // found myself + +// CEngineTool +//OFFSET_DEFAULT(GetCurrentMap, 25, 26) // good +//OFFSET_DEFAULT(HostFrameTime, 39, 40) // good +//OFFSET_DEFAULT(HostTick, 41, 42) // good +//OFFSET_DEFAULT(ServerTick, 45, 46) // seems good +//OFFSET_DEFAULT(ClientTime, 47, 48) // seems good +//OFFSET_DEFAULT(ClientTick, 49, 50) // seems good +OFFSET_WINDOWS(PrecacheModel, 62) + +// CServerGameDLL +// didn't check the ShouldDraw offset, but the vtable offsets defined in 9568 are good + +// Server +SIGSCAN_WINDOWS(ViewPunch, "55 8B EC A1 ? ? ? ? 83 EC 0C 83 78 ? 00 56 8B F1") // this works for 9568 too, maybe shorten that pattern/adjust to match this? + +// CBasePlayer +OFFSET_WINDOWS(m_pShadowStand, 3156) // found myself +OFFSET_WINDOWS(m_pShadowCrouch, 3160) // found myself + +OFFSET_WINDOWS(viewangles, 19112) // found myself + +// CBaseEntity +OFFSET_WINDOWS(AcceptInput, 39) // found myself +OFFSET_WINDOWS(IsPlayer, 84) // found myself + +// CPortal_Player +//OFFSET_WINDOWS(GetPaintPower, 2) // this seems to be fine as is +OFFSET_WINDOWS(PlayerRunCommand, 452) // found myself +OFFSET_WINDOWS(UseSpeedPower, 508) // found myself + +// CSteam3Client +OFFSET_WINDOWS(OnGameOverlayActivated, 92) + +// IPhysicsObject +// everything (should) be fine. + +// Steam API +SIGSCAN_EMPTY(interfaceMgrSig) +OFFSET_EMPTY(interfaceMgrOff) + +// CDemoRecorder +// all same as current P2 + +// CDemoPlayer +OFFSET_WINDOWS(SkipToTick, 14) // found myself +// rest are good + +// stolen +SIGSCAN_WINDOWS(GetHudSig, "55 8B EC 8B 45 ? 83 F8 FF 75 ? 8B 0D ? ? ? ? 8B 01 8B 90 ? ? ? ? FF D2 C1 E0 07") +SIGSCAN_WINDOWS(FindElementSig, "55 8B EC 53 8B 5D ? 56 57 8B F1 33 FF") + +OFFSET_WINDOWS(m_szLevelName, 36) +OFFSET_WINDOWS(m_bLoadGame, 440) + +SIGSCAN_WINDOWS(readConsoleCommandInjectSig, "8B 45 F4 50 68 ? 04 00 00 68 ? ? ? ? 8D 4D 90 E8 ? ? ? ? 8D 4F 04 E8") // needed to mask one byte + +OFFSET_WINDOWS(net_time, 21) // found myself + +OFFSET_WINDOWS(PerUserInput_tSize, 212) // found myself +OFFSET_WINDOWS(m_pCommands, 224) // found myself +// multiplayer_backup is good + +// check/refind these +OFFSET_WINDOWS(m_pSurfaceData, 4088) // found myself but unsure +OFFSET_WINDOWS(S_m_surfaceFriction, 4092) // found myself +OFFSET_WINDOWS(C_m_surfaceFriction, 5532) // found myself \ No newline at end of file