#40 Experiments.

This commit is contained in:
momo5502 2016-01-16 13:11:00 +01:00
parent 32088789ef
commit 6fa0a743d8
6 changed files with 119 additions and 22 deletions

View File

@ -167,6 +167,7 @@ namespace Components
} }
} }
Menus::OverrideMenu(menu);
Menus::RemoveMenu(menu->window.name); Menus::RemoveMenu(menu->window.name);
Menus::MenuList[menu->window.name] = menu; Menus::MenuList[menu->window.name] = menu;
@ -224,7 +225,17 @@ namespace Components
if (!menus.size()) 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; return menus;
@ -285,7 +296,8 @@ namespace Components
Game::MenuList* newList = Utils::Memory::AllocateArray<Game::MenuList>(1); Game::MenuList* newList = Utils::Memory::AllocateArray<Game::MenuList>(1);
if (!newList) return menuList; if (!newList) return menuList;
newList->menus = Utils::Memory::AllocateArray<Game::menuDef_t*>(menus.size()); size_t size = menus.size();
newList->menus = Utils::Memory::AllocateArray<Game::menuDef_t*>(size);
if (!newList->menus) if (!newList->menus)
{ {
Utils::Memory::Free(newList); Utils::Memory::Free(newList);
@ -293,10 +305,10 @@ namespace Components
} }
newList->name = Utils::Memory::DuplicateString(menuList->name); newList->name = Utils::Memory::DuplicateString(menuList->name);
newList->menuCount = menus.size(); newList->menuCount = size;
// Copy new menus // 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::RemoveMenuList(newList->name);
Menus::MenuListList[newList->name] = newList; 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) void Menus::RemoveMenuList(Game::MenuList* menuList)
{ {
if (!menuList || !menuList->name) return; 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; return header;
} }
@ -570,6 +635,29 @@ namespace Components
AssetHandler::OnFind(Game::XAssetType::ASSET_TYPE_MENU, Menus::MenuLoad); AssetHandler::OnFind(Game::XAssetType::ASSET_TYPE_MENU, Menus::MenuLoad);
AssetHandler::OnFind(Game::XAssetType::ASSET_TYPE_MENUFILE, Menus::MenuFileLoad); AssetHandler::OnFind(Game::XAssetType::ASSET_TYPE_MENUFILE, Menus::MenuFileLoad);
// Reinitialize ui
Utils::Hook(0x4BA5C8, static_cast<void(*)(Game::UiContext*, Game::menuDef_t*)>([] (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<void(Game::UiContext*, Game::menuDef_t*)>(0x430D50)(context, menu);
}), HOOK_CALL).Install()->Quick();
// Don't open connect menu // Don't open connect menu
Utils::Hook::Nop(0x428E48, 5); Utils::Hook::Nop(0x428E48, 5);
@ -612,7 +700,7 @@ namespace Components
else else
{ {
// Reinitialize ui context // Reinitialize ui context
((void(*)())0x401700)(); Utils::Hook::Call<void()>(0x401700)();
// Reopen main menu // Reopen main menu
Game::Menus_OpenByName(Game::uiContext, "main_text"); Game::Menus_OpenByName(Game::uiContext, "main_text");

View File

@ -20,7 +20,7 @@ namespace Components
static std::vector<std::string> CustomMenus; static std::vector<std::string> CustomMenus;
static Game::XAssetHeader MenuLoad(Game::XAssetType type, const char* filename); 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* LoadMenuList(Game::MenuList* menuList);
static Game::MenuList* LoadScriptMenu(const char* menu); static Game::MenuList* LoadScriptMenu(const char* menu);
@ -45,6 +45,8 @@ namespace Components
static void RemoveMenuList(std::string menuList); static void RemoveMenuList(std::string menuList);
static void RemoveMenuList(Game::MenuList* 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 bool IsMenuVisible(Game::UiContext *dc, Game::menuDef_t *menu);
static void RemoveMenuFromContext(Game::UiContext *dc, Game::menuDef_t *menu); static void RemoveMenuFromContext(Game::UiContext *dc, Game::menuDef_t *menu);

View File

@ -27,9 +27,9 @@ namespace Game
Dvar_RegisterBool_t Dvar_RegisterBool = (Dvar_RegisterBool_t)0x4CE1A0; Dvar_RegisterBool_t Dvar_RegisterBool = (Dvar_RegisterBool_t)0x4CE1A0;
Dvar_RegisterFloat_t Dvar_RegisterFloat = (Dvar_RegisterFloat_t)0x648440; Dvar_RegisterFloat_t Dvar_RegisterFloat = (Dvar_RegisterFloat_t)0x648440;
Dvar_RegisterFloat2_t Dvar_RegisterFloat2 = (Dvar_RegisterFloat2_t)0x4F6070; Dvar_RegisterVec2_t Dvar_RegisterVec2 = (Dvar_RegisterVec2_t)0x4F6070;
Dvar_RegisterFloat3_t Dvar_RegisterFloat3 = (Dvar_RegisterFloat3_t)0x4EF8E0; Dvar_RegisterVec3_t Dvar_RegisterVec3 = (Dvar_RegisterVec3_t)0x4EF8E0;
Dvar_RegisterFloat4_t Dvar_RegisterFloat4 = (Dvar_RegisterFloat4_t)0x4F28E0; Dvar_RegisterVec4_t Dvar_RegisterVec4 = (Dvar_RegisterVec4_t)0x4F28E0;
Dvar_RegisterInt_t Dvar_RegisterInt = (Dvar_RegisterInt_t)0x479830; Dvar_RegisterInt_t Dvar_RegisterInt = (Dvar_RegisterInt_t)0x479830;
Dvar_RegisterEnum_t Dvar_RegisterEnum = (Dvar_RegisterEnum_t)0x412E40; Dvar_RegisterEnum_t Dvar_RegisterEnum = (Dvar_RegisterEnum_t)0x412E40;
Dvar_RegisterString_t Dvar_RegisterString = (Dvar_RegisterString_t)0x4FC7E0; Dvar_RegisterString_t Dvar_RegisterString = (Dvar_RegisterString_t)0x4FC7E0;

View File

@ -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); 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; 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); 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_RegisterFloat2_t Dvar_RegisterFloat2; 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); 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_RegisterFloat3_t Dvar_RegisterFloat3; 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); 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_RegisterFloat4_t Dvar_RegisterFloat4; 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); 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; extern Dvar_RegisterInt_t Dvar_RegisterInt;

View File

@ -1,7 +1,11 @@
#define PROTOCOL 0x92 #define PROTOCOL 0x92
// This allows us to compile our structures in IDA, for easier reversing :3
#ifdef __cplusplus
namespace Game namespace Game
{ {
#endif
typedef enum typedef enum
{ {
ASSET_TYPE_PHYSPRESET = 0, ASSET_TYPE_PHYSPRESET = 0,
@ -115,7 +119,7 @@ namespace Game
char pad2[3]; //13:15 char pad2[3]; //13:15
dvar_value_t current; //16:31 dvar_value_t current; //16:31
dvar_value_t latched; //32:47 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 min; //65:67
dvar_maxmin_t max; //68:72 woooo dvar_maxmin_t max; //68:72 woooo
} dvar_t; } dvar_t;
@ -270,7 +274,7 @@ namespace Game
union entryInternalData union entryInternalData
{ {
operationEnum op; //operationEnum op;
Operand operand; Operand operand;
}; };
@ -1079,7 +1083,7 @@ namespace Game
unsigned __int16 usageFrame; unsigned __int16 usageFrame;
}; };
enum XFileLanguage : uint8_t enum XFileLanguage : unsigned char
{ {
XLANG_NONE = 0x00, XLANG_NONE = 0x00,
XLANG_ENGLISH = 0x01, XLANG_ENGLISH = 0x01,
@ -1102,8 +1106,8 @@ namespace Game
#pragma pack(push, 1) #pragma pack(push, 1)
struct XFileHeader struct XFileHeader
{ {
uint64_t magic; unsigned __int64 magic;
uint32_t version; unsigned int version;
XFileLanguage language; XFileLanguage language;
DWORD highDateTime; DWORD highDateTime;
DWORD lowDateTime; DWORD lowDateTime;
@ -1145,7 +1149,7 @@ namespace Game
{ {
ScriptStringList stringList; ScriptStringList stringList;
int assetCount; int assetCount;
Game::XAsset *assets; XAsset *assets;
}; };
struct ZoneHeader struct ZoneHeader
@ -1204,4 +1208,7 @@ namespace Game
{ {
DWORD unk; DWORD unk;
} PartyData_t; } PartyData_t;
#ifdef __cplusplus
} }
#endif

View File

@ -32,7 +32,7 @@
#define ZLIB_CONST #define ZLIB_CONST
#define ASIO_STANDALONE #define ASIO_STANDALONE
#include <zlib.h> #include <zlib.h>
#include <asio.hpp> //#include <asio.hpp>
#include <json11.hpp> #include <json11.hpp>
// Version number // Version number