Add UIScript support.

This commit is contained in:
momo5502 2015-12-28 14:08:46 +01:00
parent 601d4d063e
commit 03fac2e637
19 changed files with 570 additions and 360 deletions

View File

@ -1,285 +0,0 @@
#include "..\STDInclude.hpp"
namespace Components
{
Feeder::Container Feeder::Current;
std::map<float, Feeder::Callbacks> Feeder::Feeders;
void Feeder::Add(float feeder, Feeder::GetItemCount_t itemCountCb, Feeder::GetItemText_t itemTextCb, Feeder::Select_t selectCb)
{
Feeder::Feeders[feeder] = { itemCountCb, itemTextCb, selectCb };
}
const char* Feeder::GetItemText()
{
if (Feeder::Feeders.find(Feeder::Current.Num) != Feeder::Feeders.end())
{
return Feeder::Feeders[Feeder::Current.Num].GetItemText(Feeder::Current.Index, Feeder::Current.Column);
}
return nullptr;
}
int Feeder::GetItemCount()
{
if (Feeder::Feeders.find(Feeder::Current.Num) != Feeder::Feeders.end())
{
return Feeder::Feeders[Feeder::Current.Num].GetItemCount();
}
return 0;
}
bool Feeder::SetItemSelection()
{
if (Feeder::Feeders.find(Feeder::Current.Num) != Feeder::Feeders.end())
{
Feeder::Feeders[Feeder::Current.Num].Select(Feeder::Current.Index);
return true;
}
return false;
}
bool Feeder::CheckFeeder()
{
if (Feeder::Current.Num == 15.0f) return false;
return (Feeder::Feeders.find(Feeder::Current.Num) != Feeder::Feeders.end());
}
void __declspec(naked) Feeder::SetItemSelectionStub()
{
__asm
{
mov eax, [esp + 08h]
mov Feeder::Current.Num, eax
mov eax, [esp + 0Ch]
mov Feeder::Current.Index, eax
call Feeder::SetItemSelection
test eax, eax
jz continue
retn
continue:
fld ds : 739FD0h
mov eax, 4C25D6h
jmp eax
}
}
void __declspec(naked) Feeder::GetItemTextStub()
{
__asm
{
mov eax, [esp + 0Ch]
mov Feeder::Current.Num, eax
mov eax, [esp + 10h]
mov Feeder::Current.Index, eax
mov eax, [esp + 14h]
mov Feeder::Current.Column, eax
call Feeder::GetItemText
test eax, eax
jz continue
push ebx
mov ebx, [esp + 4 + 28h]
mov dword ptr[ebx], 0
pop ebx
retn
continue:
push ecx
fld ds:739FD0h
mov eax, 4CE9E7h
jmp eax
}
}
void __declspec(naked) Feeder::GetItemCountStub()
{
__asm
{
mov eax, [esp + 8h]
mov Feeder::Current.Num, eax
call Feeder::GetItemCount
test eax, eax
jz continue
retn
continue:
push ecx
fld ds:739FD0h
mov eax, 41A0D7h
jmp eax;
}
}
void __declspec(naked) Feeder::HandleKeyStub()
{
static int NextClickTime = 0;
__asm
{
mov ebx, ebp
mov eax, [ebp + 12Ch]
mov Feeder::Current.Num, eax
push ebx
call Feeder::CheckFeeder
pop ebx
test eax, eax
jz continueOriginal
// Get current milliseconds
call Game::Com_Milliseconds
// Check if allowed to click
cmp eax, NextClickTime
jl continueOriginal
// Set next allowed click time to current time + 300ms
add eax, 300
mov NextClickTime, eax
// Get item cursor position ptr
mov ecx, ebx
add ecx, Game::itemDef_t::cursorPos
// Get item listbox ptr
mov edx, ebx
add edx, Game::itemDef_t::typeData
// Get listbox cursor pos
mov edx, [edx]
add edx, Game::listBoxDef_s::startPos
mov edx, [edx]
// Resolve item cursor pos pointer
mov ebx, [ecx]
// Check if item cursor pos equals listbox cursor pos
cmp ebx, edx
je returnSafe
// Update indices if not
mov [ecx], edx
mov Feeder::Current.Index, edx
call Feeder::SetItemSelection
returnSafe:
retn
continueOriginal:
mov eax, 635570h
jmp eax
}
}
void __declspec(naked) Feeder::MouseEnterStub()
{
__asm
{
mov eax, [edi + 12Ch]
mov Feeder::Current.Num, eax
call Feeder::CheckFeeder
test eax, eax
jnz continue
mov[edi + 130h], esi
continue:
mov eax, 639D75h
jmp eax
}
}
void __declspec(naked) Feeder::MouseSelectStub()
{
__asm
{
mov eax, [esp + 08h]
mov Feeder::Current.Num, eax
call Feeder::CheckFeeder
test eax, eax
jnz continue
mov eax, 4C25D0h
jmp eax
continue:
retn
}
}
void __declspec(naked) Feeder::PlaySoundStub()
{
__asm
{
mov eax, [edi + 12Ch]
mov Feeder::Current.Num, eax
call Feeder::CheckFeeder
test eax, eax
jnz continue
mov eax, 685E10h
jmp eax
continue:
retn
}
}
Feeder::Feeder()
{
// Get feeder item count
Utils::Hook(0x41A0D0, Feeder::GetItemCountStub, HOOK_JUMP).Install()->Quick();
// Get feeder item text
Utils::Hook(0x4CE9E0, Feeder::GetItemTextStub, HOOK_JUMP).Install()->Quick();
// Select feeder item
Utils::Hook(0x4C25D0, Feeder::SetItemSelectionStub, HOOK_JUMP).Install()->Quick();
// Mouse enter check
Utils::Hook(0x639D6E, Feeder::MouseEnterStub, HOOK_JUMP).Install()->Quick();
// Handle key event
Utils::Hook(0x63C5BC, Feeder::HandleKeyStub, HOOK_CALL).Install()->Quick();
// Mouse select check
Utils::Hook(0x639D31, Feeder::MouseSelectStub, HOOK_CALL).Install()->Quick();
// Play mouse over sound check
Utils::Hook(0x639D66, Feeder::PlaySoundStub, HOOK_CALL).Install()->Quick();
// some thing overwriting feeder 2's data
Utils::Hook::Set<BYTE>(0x4A06A9, 0xEB);
}
Feeder::~Feeder()
{
Feeder::Feeders.clear();
}
}

View File

@ -13,7 +13,6 @@ namespace Components
Loader::Register(new Menus());
Loader::Register(new Party());
Loader::Register(new Colors());
Loader::Register(new Feeder());
Loader::Register(new Logger());
Loader::Register(new Window());
Loader::Register(new Command());
@ -21,6 +20,8 @@ namespace Components
Loader::Register(new Network());
Loader::Register(new RawFiles());
Loader::Register(new Renderer());
Loader::Register(new UIFeeder());
Loader::Register(new UIScript());
Loader::Register(new FastFiles());
Loader::Register(new Materials());
Loader::Register(new Singleton());

View File

@ -24,7 +24,6 @@ namespace Components
#include "Maps.hpp"
#include "Menus.hpp"
#include "Colors.hpp"
#include "Feeder.hpp"
#include "Logger.hpp"
#include "Window.hpp"
#include "Command.hpp"
@ -33,6 +32,8 @@ namespace Components
#include "Party.hpp" // Destroys the order, but requires network classes :D
#include "RawFiles.hpp"
#include "Renderer.hpp"
#include "UIFeeder.hpp"
#include "UIScript.hpp"
#include "Dedicated.hpp"
#include "FastFiles.hpp"
#include "Materials.hpp"

View File

@ -24,11 +24,11 @@ namespace Components
return i;
}
Game::script_t* Menus::LoadMenuScript(const char* name, std::string buffer)
Game::script_t* Menus::LoadMenuScript(std::string name, std::string buffer)
{
Game::script_t* script = Game::Script_Alloc(sizeof(Game::script_t) + 1 + buffer.length());
strcpy_s(script->filename, sizeof(script->filename), name);
strcpy_s(script->filename, sizeof(script->filename), name.data());
script->buffer = (char*)(script + 1);
*((char*)(script + 1) + buffer.length()) = '\0';
@ -51,7 +51,7 @@ namespace Components
return script;
}
int Menus::LoadMenuSource(const char* name, std::string buffer)
int Menus::LoadMenuSource(std::string name, std::string buffer)
{
int handle = Menus::ReserveSourceHandle();
if (!Menus::IsValidSourceHandle(handle)) return 0; // No free source slot!
@ -156,55 +156,56 @@ namespace Components
return menu;
}
std::vector<Game::menuDef_t*> Menus::LoadMenu(Game::menuDef_t* menudef)
std::vector<Game::menuDef_t*> Menus::LoadMenu(std::string menu)
{
std::vector<Game::menuDef_t*> menus;
FileSystem::File menuFile(Utils::VA("ui_mp\\%s.menu", menudef->window.name));
FileSystem::File menuFile(menu);
if (menuFile.Exists())
{
Game::pc_token_t token;
int handle = Menus::LoadMenuSource(menudef->window.name, menuFile.GetBuffer());
if (!Menus::IsValidSourceHandle(handle))
int handle = Menus::LoadMenuSource(menu, menuFile.GetBuffer());
if (Menus::IsValidSourceHandle(handle))
{
menus.push_back(menudef);
return menus;
}
while (true)
{
ZeroMemory(&token, sizeof(token));
if (!Game::PC_ReadTokenHandle(handle, &token) || token.string[0] == '}')
while (true)
{
break;
}
ZeroMemory(&token, sizeof(token));
if (!_stricmp(token.string, "loadmenu"))
{
Game::PC_ReadTokenHandle(handle, &token);
// Ugly, but does the job ;)
Game::menuDef_t _temp;
_temp.window.name = token.string;
std::vector<Game::menuDef_t*> newMenus = Menus::LoadMenu(&_temp);
for (auto newMenu : newMenus)
if (!Game::PC_ReadTokenHandle(handle, &token) || token.string[0] == '}')
{
menus.push_back(newMenu);
break;
}
if (!_stricmp(token.string, "loadmenu"))
{
Game::PC_ReadTokenHandle(handle, &token);
std::vector<Game::menuDef_t*> newMenus = Menus::LoadMenu(Utils::VA("ui_mp\\%s.menu", token.string));
for (auto newMenu : newMenus)
{
menus.push_back(newMenu);
}
}
if (!_stricmp(token.string, "menudef"))
{
menus.push_back(Menus::ParseMenu(handle));
}
}
if (!_stricmp(token.string, "menudef"))
{
menus.push_back(Menus::ParseMenu(handle));
}
Menus::FreeMenuSource(handle);
}
Menus::FreeMenuSource(handle);
}
return menus;
}
std::vector<Game::menuDef_t*> Menus::LoadMenu(Game::menuDef_t* menudef)
{
std::vector<Game::menuDef_t*> menus = Menus::LoadMenu(Utils::VA("ui_mp\\%s.menu", menudef->window.name));
if (!menus.size())
{
menus.push_back(menudef);
@ -213,6 +214,25 @@ namespace Components
return menus;
}
Game::MenuList* Menus::LoadScriptMenu(const char* menu)
{
std::vector<Game::menuDef_t*> menus = Menus::LoadMenu(menu);
if (!menus.size()) return nullptr;
// Allocate new menu list
Game::MenuList* newList = (Game::MenuList*)calloc(1, sizeof(Game::MenuList));
newList->name = _strdup(menu);
newList->menus = (Game::menuDef_t **)calloc(menus.size(), sizeof(Game::menuDef_t *));
newList->menuCount = menus.size();
// Copy new menus
memcpy(newList->menus, menus.data(), menus.size() * sizeof(Game::menuDef_t *));
Menus::MenuListList.push_back(newList);
return newList;
}
Game::MenuList* Menus::LoadMenuList(Game::MenuList* menuList)
{
std::vector<Game::menuDef_t*> menus;
@ -401,8 +421,21 @@ namespace Components
if (menuList)
{
// Don't parse scriptmenus for now!
if (strcmp(menuList->menus[0]->window.name, "default_menu") && !Utils::EndsWith(filename, ".menu"))
// Parse scriptmenus!
if (!strcmp(menuList->menus[0]->window.name, "default_menu") || Utils::EndsWith(filename, ".menu"))
{
if (FileSystem::File(filename).Exists())
{
header.menuList = Menus::LoadScriptMenu(filename);
// Reset, if we didn't find scriptmenus
if (!header.menuList)
{
header.menuList = menuList;
}
}
}
else
{
header.menuList = Menus::LoadMenuList(menuList);
}

View File

@ -17,10 +17,12 @@ namespace Components
static Game::XAssetHeader MenuFileLoad(Game::XAssetType type, const char* filename);
static Game::MenuList* LoadMenuList(Game::MenuList* menuList);
static Game::MenuList* LoadScriptMenu(const char* menu);
static std::vector<Game::menuDef_t*> LoadMenu(Game::menuDef_t* menudef);
static std::vector<Game::menuDef_t*> LoadMenu(std::string file);
static Game::script_t* LoadMenuScript(const char* name, std::string buffer);
static int LoadMenuSource(const char* name, std::string buffer);
static Game::script_t* LoadMenuScript(std::string name, std::string buffer);
static int LoadMenuSource(std::string name, std::string buffer);
static int ReserveSourceHandle();
static bool IsValidSourceHandle(int handle);

View File

@ -182,7 +182,6 @@ namespace Components
Network::Handle("infoResponse", [] (Network::Address address, std::string data)
{
OutputDebugStringA(data.data());
Utils::InfoString info(data);
// Handle connection
@ -199,10 +198,6 @@ namespace Components
{
Party::ConnectError("Invalid join response: Challenge mismatch.");
}
else if (matchType < 0 || 2 < matchType)
{
Party::ConnectError("Invalid join response: Unknown matchtype");
}
else if (!matchType)
{
Party::ConnectError("Server is not hosting a match.");
@ -242,8 +237,7 @@ namespace Components
}
else
{
// WAT?
OutputDebugStringA("WAT?");
Party::ConnectError("Invalid join response: Unknown matchtype");
}
}
}

View File

@ -2,7 +2,7 @@
namespace Components
{
int ServerList::CurrentServer = 0;
unsigned int ServerList::CurrentServer = 0;
ServerList::Container ServerList::RefreshContainer;
std::vector<ServerList::ServerInfo> ServerList::OnlineList;
@ -13,7 +13,7 @@ namespace Components
const char* ServerList::GetServerText(int index, int column)
{
if (index >= (int)ServerList::OnlineList.size()) return "";
if ((unsigned int)index >= ServerList::OnlineList.size()) return "";
ServerList::ServerInfo* Server = &ServerList::OnlineList[index];
@ -60,7 +60,7 @@ namespace Components
void ServerList::SelectServer(int index)
{
ServerList::CurrentServer = index;
ServerList::CurrentServer = (unsigned int)index;
}
void ServerList::Refresh()
@ -113,6 +113,7 @@ namespace Components
server.MaxClients = atoi(info.Get("sv_maxclients").data());
server.Password = 0; // No info yet
server.Ping = (Game::Com_Milliseconds() - i->SendTime);
server.Addr = address;
ServerList::OnlineList.push_back(server);
@ -129,9 +130,6 @@ namespace Components
{
ServerList::OnlineList.clear();
// Add server list feeder
Feeder::Add(2.0f, ServerList::GetServerCount, ServerList::GetServerText, ServerList::SelectServer);
Network::Handle("getServersResponse", [] (Network::Address address, std::string data)
{
if (!ServerList::RefreshContainer.AwaitingList) return; // Only parse if we are awaiting a list
@ -179,13 +177,27 @@ namespace Components
ServerList::RefreshContainer.Mutex.unlock();
});
Command::Add("refreshList", [] (Command::Params params)
{
ServerList::Refresh();
});
// Set default masterServerName + port and save it
Utils::Hook::Set<const char*>(0x60AD92, "localhost");
Utils::Hook::Set<BYTE>(0x60AD90, Game::dvar_flag::DVAR_FLAG_SAVED); // masterServerName
Utils::Hook::Set<BYTE>(0x60ADC6, Game::dvar_flag::DVAR_FLAG_SAVED); // masterPort
// Temporary overwriting
strcpy((char*)0x6D9CBC, "localhost");
// Add server list feeder
UIFeeder::Add(2.0f, ServerList::GetServerCount, ServerList::GetServerText, ServerList::SelectServer);
// Add required UIScripts
UIScript::Add("RefreshServers", ServerList::Refresh);
UIScript::Add("JoinServer", [] ()
{
if (ServerList::OnlineList.size() > ServerList::CurrentServer)
{
Party::Connect(ServerList::OnlineList[ServerList::CurrentServer].Addr);
}
});
UIScript::Add("ServerSort", [] (UIScript::Token token)
{
Logger::Print("Server list sorting by token: %d\n", token.Get<int>());
});
}
ServerList::~ServerList()

View File

@ -57,7 +57,7 @@ namespace Components
static const char* GetServerText(int index, int column);
static void SelectServer(int index);
static int CurrentServer;
static unsigned int CurrentServer;
static Container RefreshContainer;
static std::vector<ServerInfo> OnlineList;
};

285
iw4/Components/UIFeeder.cpp Normal file
View File

@ -0,0 +1,285 @@
#include "..\STDInclude.hpp"
namespace Components
{
UIFeeder::Container UIFeeder::Current;
std::map<float, UIFeeder::Callbacks> UIFeeder::Feeders;
void UIFeeder::Add(float feeder, UIFeeder::GetItemCount_t itemCountCb, UIFeeder::GetItemText_t itemTextCb, UIFeeder::Select_t selectCb)
{
UIFeeder::Feeders[feeder] = { itemCountCb, itemTextCb, selectCb };
}
const char* UIFeeder::GetItemText()
{
if (UIFeeder::Feeders.find(UIFeeder::Current.Feeder) != UIFeeder::Feeders.end())
{
return UIFeeder::Feeders[UIFeeder::Current.Feeder].GetItemText(UIFeeder::Current.Index, UIFeeder::Current.Column);
}
return nullptr;
}
int UIFeeder::GetItemCount()
{
if (UIFeeder::Feeders.find(UIFeeder::Current.Feeder) != UIFeeder::Feeders.end())
{
return UIFeeder::Feeders[UIFeeder::Current.Feeder].GetItemCount();
}
return 0;
}
bool UIFeeder::SetItemSelection()
{
if (UIFeeder::Feeders.find(UIFeeder::Current.Feeder) != UIFeeder::Feeders.end())
{
UIFeeder::Feeders[UIFeeder::Current.Feeder].Select(UIFeeder::Current.Index);
return true;
}
return false;
}
bool UIFeeder::CheckFeeder()
{
if (UIFeeder::Current.Feeder == 15.0f) return false;
return (UIFeeder::Feeders.find(UIFeeder::Current.Feeder) != UIFeeder::Feeders.end());
}
void __declspec(naked) UIFeeder::SetItemSelectionStub()
{
__asm
{
mov eax, [esp + 08h]
mov UIFeeder::Current.Feeder, eax
mov eax, [esp + 0Ch]
mov UIFeeder::Current.Index, eax
call UIFeeder::SetItemSelection
test eax, eax
jz continue
retn
continue:
fld ds : 739FD0h
mov eax, 4C25D6h
jmp eax
}
}
void __declspec(naked) UIFeeder::GetItemTextStub()
{
__asm
{
mov eax, [esp + 0Ch]
mov UIFeeder::Current.Feeder, eax
mov eax, [esp + 10h]
mov UIFeeder::Current.Index, eax
mov eax, [esp + 14h]
mov UIFeeder::Current.Column, eax
call UIFeeder::GetItemText
test eax, eax
jz continue
push ebx
mov ebx, [esp + 4 + 28h]
mov dword ptr[ebx], 0
pop ebx
retn
continue:
push ecx
fld ds:739FD0h
mov eax, 4CE9E7h
jmp eax
}
}
void __declspec(naked) UIFeeder::GetItemCountStub()
{
__asm
{
mov eax, [esp + 8h]
mov UIFeeder::Current.Feeder, eax
call UIFeeder::GetItemCount
test eax, eax
jz continue
retn
continue:
push ecx
fld ds:739FD0h
mov eax, 41A0D7h
jmp eax;
}
}
void __declspec(naked) UIFeeder::HandleKeyStub()
{
static int NextClickTime = 0;
__asm
{
mov ebx, ebp
mov eax, [ebp + 12Ch]
mov UIFeeder::Current.Feeder, eax
push ebx
call UIFeeder::CheckFeeder
pop ebx
test eax, eax
jz continueOriginal
// Get current milliseconds
call Game::Com_Milliseconds
// Check if allowed to click
cmp eax, NextClickTime
jl continueOriginal
// Set next allowed click time to current time + 300ms
add eax, 300
mov NextClickTime, eax
// Get item cursor position ptr
mov ecx, ebx
add ecx, Game::itemDef_t::cursorPos
// Get item listbox ptr
mov edx, ebx
add edx, Game::itemDef_t::typeData
// Get listbox cursor pos
mov edx, [edx]
add edx, Game::listBoxDef_s::startPos
mov edx, [edx]
// Resolve item cursor pos pointer
mov ebx, [ecx]
// Check if item cursor pos equals listbox cursor pos
cmp ebx, edx
je returnSafe
// Update indices if not
mov [ecx], edx
mov UIFeeder::Current.Index, edx
call UIFeeder::SetItemSelection
returnSafe:
retn
continueOriginal:
mov eax, 635570h
jmp eax
}
}
void __declspec(naked) UIFeeder::MouseEnterStub()
{
__asm
{
mov eax, [edi + 12Ch]
mov UIFeeder::Current.Feeder, eax
call UIFeeder::CheckFeeder
test eax, eax
jnz continue
mov[edi + 130h], esi
continue:
mov eax, 639D75h
jmp eax
}
}
void __declspec(naked) UIFeeder::MouseSelectStub()
{
__asm
{
mov eax, [esp + 08h]
mov UIFeeder::Current.Feeder, eax
call UIFeeder::CheckFeeder
test eax, eax
jnz continue
mov eax, 4C25D0h
jmp eax
continue:
retn
}
}
void __declspec(naked) UIFeeder::PlaySoundStub()
{
__asm
{
mov eax, [edi + 12Ch]
mov UIFeeder::Current.Feeder, eax
call UIFeeder::CheckFeeder
test eax, eax
jnz continue
mov eax, 685E10h
jmp eax
continue:
retn
}
}
UIFeeder::UIFeeder()
{
// Get feeder item count
Utils::Hook(0x41A0D0, UIFeeder::GetItemCountStub, HOOK_JUMP).Install()->Quick();
// Get feeder item text
Utils::Hook(0x4CE9E0, UIFeeder::GetItemTextStub, HOOK_JUMP).Install()->Quick();
// Select feeder item
Utils::Hook(0x4C25D0, UIFeeder::SetItemSelectionStub, HOOK_JUMP).Install()->Quick();
// Mouse enter check
Utils::Hook(0x639D6E, UIFeeder::MouseEnterStub, HOOK_JUMP).Install()->Quick();
// Handle key event
Utils::Hook(0x63C5BC, UIFeeder::HandleKeyStub, HOOK_CALL).Install()->Quick();
// Mouse select check
Utils::Hook(0x639D31, UIFeeder::MouseSelectStub, HOOK_CALL).Install()->Quick();
// Play mouse over sound check
Utils::Hook(0x639D66, UIFeeder::PlaySoundStub, HOOK_CALL).Install()->Quick();
// some thing overwriting feeder 2's data
Utils::Hook::Set<BYTE>(0x4A06A9, 0xEB);
}
UIFeeder::~UIFeeder()
{
UIFeeder::Feeders.clear();
}
}

View File

@ -1,6 +1,6 @@
namespace Components
{
class Feeder : public Component
class UIFeeder : public Component
{
public:
typedef int(__cdecl * GetItemCount_t)();
@ -14,16 +14,16 @@ namespace Components
Select_t Select;
};
Feeder();
~Feeder();
const char* GetName() { return "Feeder"; };
UIFeeder();
~UIFeeder();
const char* GetName() { return "UIFeeder"; };
static void Add(float feeder, GetItemCount_t itemCountCb, GetItemText_t itemTextCb, Select_t selectCb);
private:
struct Container
{
float Num;
float Feeder;
int Index;
int Column;
};

110
iw4/Components/UIScript.cpp Normal file
View File

@ -0,0 +1,110 @@
#include "..\STDInclude.hpp"
namespace Components
{
std::map<std::string, UIScript::Callback> UIScript::UIScripts;
template<> int UIScript::Token::Get()
{
if (this->IsValid())
{
return atoi(this->token);
}
return 0;
}
template<> char* UIScript::Token::Get()
{
if (this->IsValid())
{
return this->token;
}
return "";
}
template<> const char* UIScript::Token::Get()
{
return this->Get<char*>();
}
template<> std::string UIScript::Token::Get()
{
return this->Get<const char*>();
}
bool UIScript::Token::IsValid()
{
return (token && token[0]);
}
void UIScript::Token::Parse(const char** args)
{
if (args)
{
this->token = Game::Com_ParseExt(args);
}
}
void UIScript::Add(std::string name, UIScript::Callback callback)
{
UIScript::UIScripts[name] = callback;
}
void UIScript::Add(std::string name, UIScript::CallbackRaw callback)
{
UIScript::Add(name, reinterpret_cast<UIScript::Callback>(callback));
}
bool UIScript::RunMenuScript(const char* name, const char** args)
{
if (UIScript::UIScripts.find(name) != UIScript::UIScripts.end())
{
UIScript::UIScripts[name](UIScript::Token(args));
return true;
}
return false;
}
void __declspec(naked) UIScript::RunMenuScriptStub()
{
__asm
{
mov eax, esp
add eax, 8h
mov edx, eax // UIScript name
mov eax, [esp + 0C10h] // UIScript args
push eax
push edx
call UIScript::RunMenuScript
add esp, 8h
test eax, eax
jz continue
// if returned
pop edi
pop esi
add esp, 0C00h
retn
continue:
mov eax, 45ED00h
jmp eax
}
}
UIScript::UIScript()
{
// Install handler
Utils::Hook::Set<int>(0x45EC5B, (DWORD)UIScript::RunMenuScriptStub - 0x45EC59 - 6);
}
UIScript::~UIScript()
{
UIScript::UIScripts.clear();
}
}

View File

@ -0,0 +1,39 @@
namespace Components
{
class UIScript : public Component
{
public:
UIScript();
~UIScript();
const char* GetName() { return "UIScript"; };
class Token
{
public:
Token(const char** args) : token(0) { this->Parse(args); };
Token(const Token &obj) { this->token = obj.token; };
template<typename T> T Get();
bool IsValid();
private:
char* token;
void Parse(const char** args);
};
typedef void(*Callback)(Token token);
typedef void(*CallbackRaw)();
static void Add(std::string name, Callback callback);
static void Add(std::string name, CallbackRaw callback);
private:
static bool RunMenuScript(const char* name, const char** args);
static void RunMenuScriptStub();
static std::map<std::string, Callback> UIScripts;
};
}

View File

@ -13,6 +13,7 @@ namespace Game
Com_Error_t Com_Error = (Com_Error_t)0x4B22D0;
Com_Printf_t Com_Printf = (Com_Printf_t)0x402500;
Com_Milliseconds_t Com_Milliseconds = (Com_Milliseconds_t)0x42A660;
Com_ParseExt_t Com_ParseExt = (Com_ParseExt_t)0x474D60;
DB_FindXAssetHeader_t DB_FindXAssetHeader = (DB_FindXAssetHeader_t)0x407930;
DB_GetXAssetNameHandler_t* DB_GetXAssetNameHandlers = (DB_GetXAssetNameHandler_t*)0x799328;

View File

@ -24,6 +24,9 @@ namespace Game
typedef int(__cdecl * Com_Milliseconds_t)(void);
extern Com_Milliseconds_t Com_Milliseconds;
typedef char* (__cdecl * Com_ParseExt_t)(const char**);
extern Com_ParseExt_t Com_ParseExt;
typedef XAssetHeader (__cdecl * DB_FindXAssetHeader_t)(XAssetType type, const char* filename);
extern DB_FindXAssetHeader_t DB_FindXAssetHeader;

View File

@ -12,13 +12,13 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReser
DWORD oldProtect;
VirtualProtect(GetModuleHandle(NULL), 0x6C73000, PAGE_EXECUTE_READWRITE, &oldProtect);
EntryPointHook.Initialize(0x6BAC0F, static_cast<void __declspec(naked)(*)()>([] ()
EntryPointHook.Initialize(0x6BAC0F, [] ()
{
EntryPointHook.Uninstall();
Components::Loader::Initialize();
__asm jmp EntryPointHook.Place
}))->Install();
})->Install();
}
else if (ul_reason_for_call == DLL_PROCESS_DETACH)
{

View File

@ -10,6 +10,11 @@ namespace Utils
}
}
Hook* Hook::Initialize(DWORD place, void(*stub)(), bool useJump)
{
return Hook::Initialize(place, (void*)stub, useJump);
}
Hook* Hook::Initialize(DWORD place, void* stub, bool useJump)
{
return Hook::Initialize((void*)place, stub, useJump);

View File

@ -16,6 +16,7 @@ namespace Utils
Hook* Initialize(void* place, void* stub, bool useJump = true);
Hook* Initialize(DWORD place, void* stub, bool useJump = true);
Hook* Initialize(DWORD place, void(*stub)(), bool useJump = true); // For lambdas
Hook* Install();
Hook* Uninstall();

View File

@ -61,7 +61,6 @@
<ClInclude Include="Components\Dedicated.hpp" />
<ClInclude Include="Components\Dvar.hpp" />
<ClInclude Include="Components\FastFiles.hpp" />
<ClInclude Include="Components\Feeder.hpp" />
<ClInclude Include="Components\FileSystem.hpp" />
<ClInclude Include="Components\Loader.hpp" />
<ClInclude Include="Components\Localization.hpp" />
@ -77,6 +76,8 @@
<ClInclude Include="Components\Renderer.hpp" />
<ClInclude Include="Components\ServerList.hpp" />
<ClInclude Include="Components\Singleton.hpp" />
<ClInclude Include="Components\UIFeeder.hpp" />
<ClInclude Include="Components\UIScript.hpp" />
<ClInclude Include="Components\Window.hpp" />
<ClInclude Include="Game\Functions.hpp" />
<ClInclude Include="Game\Structs.hpp" />
@ -101,7 +102,6 @@
<ClCompile Include="Components\Dedicated.cpp" />
<ClCompile Include="Components\Dvar.cpp" />
<ClCompile Include="Components\FastFiles.cpp" />
<ClCompile Include="Components\Feeder.cpp" />
<ClCompile Include="Components\FileSystem.cpp" />
<ClCompile Include="Components\Loader.cpp" />
<ClCompile Include="Components\Localization.cpp" />
@ -117,6 +117,8 @@
<ClCompile Include="Components\Renderer.cpp" />
<ClCompile Include="Components\ServerList.cpp" />
<ClCompile Include="Components\Singleton.cpp" />
<ClCompile Include="Components\UIFeeder.cpp" />
<ClCompile Include="Components\UIScript.cpp" />
<ClCompile Include="Components\Window.cpp" />
<ClCompile Include="Game\Functions.cpp" />
<ClCompile Include="Steam\Interfaces\SteamFriends.cpp" />

View File

@ -134,10 +134,13 @@
<ClCompile Include="Components\Singleton.cpp">
<Filter>Source\Components\Modules</Filter>
</ClCompile>
<ClCompile Include="Components\Feeder.cpp">
<ClCompile Include="Components\ServerList.cpp">
<Filter>Source\Components\Modules</Filter>
</ClCompile>
<ClCompile Include="Components\ServerList.cpp">
<ClCompile Include="Components\UIFeeder.cpp">
<Filter>Source\Components\Modules</Filter>
</ClCompile>
<ClCompile Include="Components\UIScript.cpp">
<Filter>Source\Components\Modules</Filter>
</ClCompile>
</ItemGroup>
@ -250,10 +253,13 @@
<ClInclude Include="Components\Singleton.hpp">
<Filter>Source\Components\Modules</Filter>
</ClInclude>
<ClInclude Include="Components\Feeder.hpp">
<ClInclude Include="Components\ServerList.hpp">
<Filter>Source\Components\Modules</Filter>
</ClInclude>
<ClInclude Include="Components\ServerList.hpp">
<ClInclude Include="Components\UIFeeder.hpp">
<Filter>Source\Components\Modules</Filter>
</ClInclude>
<ClInclude Include="Components\UIScript.hpp">
<Filter>Source\Components\Modules</Filter>
</ClInclude>
</ItemGroup>