diff --git a/src/Components/Modules/Menus.cpp b/src/Components/Modules/Menus.cpp index ad660add..dd64f48d 100644 --- a/src/Components/Modules/Menus.cpp +++ b/src/Components/Modules/Menus.cpp @@ -167,6 +167,7 @@ namespace Components } } + Menus::OverrideMenu(menu); Menus::RemoveMenu(menu->window.name); Menus::MenuList[menu->window.name] = menu; @@ -224,7 +225,17 @@ namespace Components if (!menus.size()) { - menus.push_back(menudef); + // Try loading the original menu, if we can't load our custom one + Game::menuDef_t* originalMenu = AssetHandler::FindOriginalAsset(Game::XAssetType::ASSET_TYPE_MENU, menudef->window.name).menu; + + if (originalMenu) + { + menus.push_back(originalMenu); + } + else + { + menus.push_back(menudef); + } } return menus; @@ -285,7 +296,8 @@ namespace Components Game::MenuList* newList = Utils::Memory::AllocateArray(1); if (!newList) return menuList; - newList->menus = Utils::Memory::AllocateArray(menus.size()); + size_t size = menus.size(); + newList->menus = Utils::Memory::AllocateArray(size); if (!newList->menus) { Utils::Memory::Free(newList); @@ -293,10 +305,10 @@ namespace Components } newList->name = Utils::Memory::DuplicateString(menuList->name); - newList->menuCount = menus.size(); + newList->menuCount = size; // Copy new menus - memcpy(newList->menus, menus.data(), menus.size() * sizeof(Game::menuDef_t *)); + memcpy(newList->menus, menus.data(), size * sizeof(Game::menuDef_t *)); Menus::RemoveMenuList(newList->name); Menus::MenuListList[newList->name] = newList; @@ -433,6 +445,52 @@ namespace Components } } + // This is actually a really important function + // It checks if we have already loaded the menu we passed and replaces its instances in memory + // Due to deallocating the old menu, the game might crash on not being able to handle its old instance + // So we need to override it in our menu lists and the game's ui context + // EDIT: We might also remove the old instances inside RemoveMenu + // EDIT2: Removing old instances without having a menu to replace them with might leave a nullptr + void Menus::OverrideMenu(Game::menuDef_t *menu) + { + if (!menu || !menu->window.name) return; + std::string name = menu->window.name; + + // Find the old menu + auto i = Menus::MenuList.find(name); + if (i != Menus::MenuList.end()) + { + // We have found it, *yay* + Game::menuDef_t* oldMenu = i->second; + + // Replace every old instance with our new one in the ui context + for (int i = 0; i < Game::uiContext->menuCount; i++) + { + if (Game::uiContext->menus[i] == oldMenu) + { + Game::uiContext->menus[i] = menu; + } + } + + // Replace every old instance with our new one in our menu lists + for (auto i = Menus::MenuListList.begin(); i != Menus::MenuListList.end(); i++) + { + Game::MenuList* list = i->second; + + if (list && list->menus) + { + for (int i = 0; i < list->menuCount; i++) + { + if (list->menus[i] == oldMenu) + { + list->menus[i] = menu; + } + } + } + } + } + } + void Menus::RemoveMenuList(Game::MenuList* menuList) { if (!menuList || !menuList->name) return; @@ -503,6 +561,13 @@ namespace Components } } + for (int i = 0; i < header.menuList->menuCount; i++) + { + OutputDebugString(Utils::VA("Menu: %d\t%X\t%s",i + Game::uiContext->menuCount, header.menuList->menus[i], header.menuList->menus[i]->window.name)); + } + + OutputDebugString(Utils::VA("Loaded menus: %d", header.menuList->menuCount)); + return header; } @@ -570,6 +635,29 @@ namespace Components AssetHandler::OnFind(Game::XAssetType::ASSET_TYPE_MENU, Menus::MenuLoad); AssetHandler::OnFind(Game::XAssetType::ASSET_TYPE_MENUFILE, Menus::MenuFileLoad); + // Reinitialize ui + Utils::Hook(0x4BA5C8, static_cast([] (Game::UiContext* context, Game::menuDef_t* menu) + { + if (menu->window.name == (char*)0xDDDDDDDD) + { + OutputDebugString("Going to crash!"); + for (int i = 0; i < context->menuCount; i++) + { + if(menu == context->menus[i]) OutputDebugString(Utils::VA("Menu crash: %d %X", i, menu)); + } + + //return; + } + static bool displayed = false; + if (!displayed) + { + displayed = true; + OutputDebugString(Utils::VA("Current menus: %d", context->menuCount)); + } + + Utils::Hook::Call(0x430D50)(context, menu); + }), HOOK_CALL).Install()->Quick(); + // Don't open connect menu Utils::Hook::Nop(0x428E48, 5); @@ -612,7 +700,7 @@ namespace Components else { // Reinitialize ui context - ((void(*)())0x401700)(); + Utils::Hook::Call(0x401700)(); // Reopen main menu Game::Menus_OpenByName(Game::uiContext, "main_text"); diff --git a/src/Components/Modules/Menus.hpp b/src/Components/Modules/Menus.hpp index 81a0f35b..686e13e8 100644 --- a/src/Components/Modules/Menus.hpp +++ b/src/Components/Modules/Menus.hpp @@ -20,7 +20,7 @@ namespace Components static std::vector CustomMenus; static Game::XAssetHeader MenuLoad(Game::XAssetType type, const char* filename); - static Game::XAssetHeader Menus::MenuFileLoad(Game::XAssetType type, const char* filename); + static Game::XAssetHeader MenuFileLoad(Game::XAssetType type, const char* filename); static Game::MenuList* LoadMenuList(Game::MenuList* menuList); static Game::MenuList* LoadScriptMenu(const char* menu); @@ -45,6 +45,8 @@ namespace Components static void RemoveMenuList(std::string menuList); static void RemoveMenuList(Game::MenuList* menuList); + static void OverrideMenu(Game::menuDef_t *menu); + static bool IsMenuVisible(Game::UiContext *dc, Game::menuDef_t *menu); static void RemoveMenuFromContext(Game::UiContext *dc, Game::menuDef_t *menu); diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index 4a69107a..b1fbc314 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -27,9 +27,9 @@ namespace Game Dvar_RegisterBool_t Dvar_RegisterBool = (Dvar_RegisterBool_t)0x4CE1A0; Dvar_RegisterFloat_t Dvar_RegisterFloat = (Dvar_RegisterFloat_t)0x648440; - Dvar_RegisterFloat2_t Dvar_RegisterFloat2 = (Dvar_RegisterFloat2_t)0x4F6070; - Dvar_RegisterFloat3_t Dvar_RegisterFloat3 = (Dvar_RegisterFloat3_t)0x4EF8E0; - Dvar_RegisterFloat4_t Dvar_RegisterFloat4 = (Dvar_RegisterFloat4_t)0x4F28E0; + Dvar_RegisterVec2_t Dvar_RegisterVec2 = (Dvar_RegisterVec2_t)0x4F6070; + Dvar_RegisterVec3_t Dvar_RegisterVec3 = (Dvar_RegisterVec3_t)0x4EF8E0; + Dvar_RegisterVec4_t Dvar_RegisterVec4 = (Dvar_RegisterVec4_t)0x4F28E0; Dvar_RegisterInt_t Dvar_RegisterInt = (Dvar_RegisterInt_t)0x479830; Dvar_RegisterEnum_t Dvar_RegisterEnum = (Dvar_RegisterEnum_t)0x412E40; Dvar_RegisterString_t Dvar_RegisterString = (Dvar_RegisterString_t)0x4FC7E0; diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index 6eae865b..18c6bfd8 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -57,14 +57,14 @@ namespace Game typedef dvar_t* (__cdecl * Dvar_RegisterFloat_t)(const char* name, float default, float min, float max, int flags, const char* description); extern Dvar_RegisterFloat_t Dvar_RegisterFloat; - typedef dvar_t* (__cdecl * Dvar_RegisterFloat2_t)(const char* name, float defx, float defy, float min, float max, int flags, const char* description); - extern Dvar_RegisterFloat2_t Dvar_RegisterFloat2; + typedef dvar_t* (__cdecl * Dvar_RegisterVec2_t)(const char* name, float defx, float defy, float min, float max, int flags, const char* description); + extern Dvar_RegisterVec2_t Dvar_RegisterVec2; - typedef dvar_t* (__cdecl * Dvar_RegisterFloat3_t)(const char* name, float defx, float defy, float defz, float min, float max, int flags, const char* description); - extern Dvar_RegisterFloat3_t Dvar_RegisterFloat3; + typedef dvar_t* (__cdecl * Dvar_RegisterVec3_t)(const char* name, float defx, float defy, float defz, float min, float max, int flags, const char* description); + extern Dvar_RegisterVec3_t Dvar_RegisterVec3; - typedef dvar_t* (__cdecl * Dvar_RegisterFloat4_t)(const char* name, float defx, float defy, float defz, float defw, float min, float max, int flags, const char* description); - extern Dvar_RegisterFloat4_t Dvar_RegisterFloat4; + typedef dvar_t* (__cdecl * Dvar_RegisterVec4_t)(const char* name, float defx, float defy, float defz, float defw, float min, float max, int flags, const char* description); + extern Dvar_RegisterVec4_t Dvar_RegisterVec4; typedef dvar_t* (__cdecl * Dvar_RegisterInt_t)(const char* name, int default, int min, int max, int flags, const char* description); extern Dvar_RegisterInt_t Dvar_RegisterInt; diff --git a/src/Game/Structs.hpp b/src/Game/Structs.hpp index 546c4f0a..dc8f3ed9 100644 --- a/src/Game/Structs.hpp +++ b/src/Game/Structs.hpp @@ -1,7 +1,11 @@ #define PROTOCOL 0x92 +// This allows us to compile our structures in IDA, for easier reversing :3 +#ifdef __cplusplus namespace Game { +#endif + typedef enum { ASSET_TYPE_PHYSPRESET = 0, @@ -115,7 +119,7 @@ namespace Game char pad2[3]; //13:15 dvar_value_t current; //16:31 dvar_value_t latched; //32:47 - dvar_value_t default; //48:64 + dvar_value_t _default; //48:64 dvar_maxmin_t min; //65:67 dvar_maxmin_t max; //68:72 woooo } dvar_t; @@ -270,7 +274,7 @@ namespace Game union entryInternalData { - operationEnum op; + //operationEnum op; Operand operand; }; @@ -1079,7 +1083,7 @@ namespace Game unsigned __int16 usageFrame; }; - enum XFileLanguage : uint8_t + enum XFileLanguage : unsigned char { XLANG_NONE = 0x00, XLANG_ENGLISH = 0x01, @@ -1102,8 +1106,8 @@ namespace Game #pragma pack(push, 1) struct XFileHeader { - uint64_t magic; - uint32_t version; + unsigned __int64 magic; + unsigned int version; XFileLanguage language; DWORD highDateTime; DWORD lowDateTime; @@ -1145,7 +1149,7 @@ namespace Game { ScriptStringList stringList; int assetCount; - Game::XAsset *assets; + XAsset *assets; }; struct ZoneHeader @@ -1204,4 +1208,7 @@ namespace Game { DWORD unk; } PartyData_t; + +#ifdef __cplusplus } +#endif \ No newline at end of file diff --git a/src/STDInclude.hpp b/src/STDInclude.hpp index 4766d6fd..5809378e 100644 --- a/src/STDInclude.hpp +++ b/src/STDInclude.hpp @@ -32,7 +32,7 @@ #define ZLIB_CONST #define ASIO_STANDALONE #include -#include +//#include #include // Version number