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

View File

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

View File

@ -24,11 +24,11 @@ namespace Components
return i; 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()); 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); script->buffer = (char*)(script + 1);
*((char*)(script + 1) + buffer.length()) = '\0'; *((char*)(script + 1) + buffer.length()) = '\0';
@ -51,7 +51,7 @@ namespace Components
return script; return script;
} }
int Menus::LoadMenuSource(const char* name, std::string buffer) int Menus::LoadMenuSource(std::string name, std::string buffer)
{ {
int handle = Menus::ReserveSourceHandle(); int handle = Menus::ReserveSourceHandle();
if (!Menus::IsValidSourceHandle(handle)) return 0; // No free source slot! if (!Menus::IsValidSourceHandle(handle)) return 0; // No free source slot!
@ -156,55 +156,56 @@ namespace Components
return menu; 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; 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()) if (menuFile.Exists())
{ {
Game::pc_token_t token; Game::pc_token_t token;
int handle = Menus::LoadMenuSource(menudef->window.name, menuFile.GetBuffer()); int handle = Menus::LoadMenuSource(menu, menuFile.GetBuffer());
if (!Menus::IsValidSourceHandle(handle))
if (Menus::IsValidSourceHandle(handle))
{ {
menus.push_back(menudef); while (true)
return menus;
}
while (true)
{
ZeroMemory(&token, sizeof(token));
if (!Game::PC_ReadTokenHandle(handle, &token) || token.string[0] == '}')
{ {
break; ZeroMemory(&token, sizeof(token));
}
if (!_stricmp(token.string, "loadmenu")) if (!Game::PC_ReadTokenHandle(handle, &token) || token.string[0] == '}')
{
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)
{ {
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::FreeMenuSource(handle);
{
menus.push_back(Menus::ParseMenu(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()) if (!menus.size())
{ {
menus.push_back(menudef); menus.push_back(menudef);
@ -213,6 +214,25 @@ namespace Components
return menus; 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) Game::MenuList* Menus::LoadMenuList(Game::MenuList* menuList)
{ {
std::vector<Game::menuDef_t*> menus; std::vector<Game::menuDef_t*> menus;
@ -401,8 +421,21 @@ namespace Components
if (menuList) if (menuList)
{ {
// Don't parse scriptmenus for now! // Parse scriptmenus!
if (strcmp(menuList->menus[0]->window.name, "default_menu") && !Utils::EndsWith(filename, ".menu")) 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); 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::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 std::vector<Game::menuDef_t*> LoadMenu(Game::menuDef_t* menudef); 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 Game::script_t* LoadMenuScript(std::string name, std::string buffer);
static int LoadMenuSource(const char* name, std::string buffer); static int LoadMenuSource(std::string name, std::string buffer);
static int ReserveSourceHandle(); static int ReserveSourceHandle();
static bool IsValidSourceHandle(int handle); static bool IsValidSourceHandle(int handle);

View File

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

View File

@ -2,7 +2,7 @@
namespace Components namespace Components
{ {
int ServerList::CurrentServer = 0; unsigned int ServerList::CurrentServer = 0;
ServerList::Container ServerList::RefreshContainer; ServerList::Container ServerList::RefreshContainer;
std::vector<ServerList::ServerInfo> ServerList::OnlineList; std::vector<ServerList::ServerInfo> ServerList::OnlineList;
@ -13,7 +13,7 @@ namespace Components
const char* ServerList::GetServerText(int index, int column) 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]; ServerList::ServerInfo* Server = &ServerList::OnlineList[index];
@ -60,7 +60,7 @@ namespace Components
void ServerList::SelectServer(int index) void ServerList::SelectServer(int index)
{ {
ServerList::CurrentServer = index; ServerList::CurrentServer = (unsigned int)index;
} }
void ServerList::Refresh() void ServerList::Refresh()
@ -113,6 +113,7 @@ namespace Components
server.MaxClients = atoi(info.Get("sv_maxclients").data()); server.MaxClients = atoi(info.Get("sv_maxclients").data());
server.Password = 0; // No info yet server.Password = 0; // No info yet
server.Ping = (Game::Com_Milliseconds() - i->SendTime); server.Ping = (Game::Com_Milliseconds() - i->SendTime);
server.Addr = address;
ServerList::OnlineList.push_back(server); ServerList::OnlineList.push_back(server);
@ -129,9 +130,6 @@ namespace Components
{ {
ServerList::OnlineList.clear(); 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) Network::Handle("getServersResponse", [] (Network::Address address, std::string data)
{ {
if (!ServerList::RefreshContainer.AwaitingList) return; // Only parse if we are awaiting a list if (!ServerList::RefreshContainer.AwaitingList) return; // Only parse if we are awaiting a list
@ -179,13 +177,27 @@ namespace Components
ServerList::RefreshContainer.Mutex.unlock(); ServerList::RefreshContainer.Mutex.unlock();
}); });
Command::Add("refreshList", [] (Command::Params params) // Set default masterServerName + port and save it
{ Utils::Hook::Set<const char*>(0x60AD92, "localhost");
ServerList::Refresh(); 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 // Add server list feeder
strcpy((char*)0x6D9CBC, "localhost"); 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() ServerList::~ServerList()

View File

@ -57,7 +57,7 @@ namespace Components
static const char* GetServerText(int index, int column); static const char* GetServerText(int index, int column);
static void SelectServer(int index); static void SelectServer(int index);
static int CurrentServer; static unsigned int CurrentServer;
static Container RefreshContainer; static Container RefreshContainer;
static std::vector<ServerInfo> OnlineList; 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 namespace Components
{ {
class Feeder : public Component class UIFeeder : public Component
{ {
public: public:
typedef int(__cdecl * GetItemCount_t)(); typedef int(__cdecl * GetItemCount_t)();
@ -14,16 +14,16 @@ namespace Components
Select_t Select; Select_t Select;
}; };
Feeder(); UIFeeder();
~Feeder(); ~UIFeeder();
const char* GetName() { return "Feeder"; }; const char* GetName() { return "UIFeeder"; };
static void Add(float feeder, GetItemCount_t itemCountCb, GetItemText_t itemTextCb, Select_t selectCb); static void Add(float feeder, GetItemCount_t itemCountCb, GetItemText_t itemTextCb, Select_t selectCb);
private: private:
struct Container struct Container
{ {
float Num; float Feeder;
int Index; int Index;
int Column; 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_Error_t Com_Error = (Com_Error_t)0x4B22D0;
Com_Printf_t Com_Printf = (Com_Printf_t)0x402500; Com_Printf_t Com_Printf = (Com_Printf_t)0x402500;
Com_Milliseconds_t Com_Milliseconds = (Com_Milliseconds_t)0x42A660; 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_FindXAssetHeader_t DB_FindXAssetHeader = (DB_FindXAssetHeader_t)0x407930;
DB_GetXAssetNameHandler_t* DB_GetXAssetNameHandlers = (DB_GetXAssetNameHandler_t*)0x799328; DB_GetXAssetNameHandler_t* DB_GetXAssetNameHandlers = (DB_GetXAssetNameHandler_t*)0x799328;

View File

@ -24,6 +24,9 @@ namespace Game
typedef int(__cdecl * Com_Milliseconds_t)(void); typedef int(__cdecl * Com_Milliseconds_t)(void);
extern Com_Milliseconds_t Com_Milliseconds; 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); typedef XAssetHeader (__cdecl * DB_FindXAssetHeader_t)(XAssetType type, const char* filename);
extern DB_FindXAssetHeader_t DB_FindXAssetHeader; 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; DWORD oldProtect;
VirtualProtect(GetModuleHandle(NULL), 0x6C73000, PAGE_EXECUTE_READWRITE, &oldProtect); VirtualProtect(GetModuleHandle(NULL), 0x6C73000, PAGE_EXECUTE_READWRITE, &oldProtect);
EntryPointHook.Initialize(0x6BAC0F, static_cast<void __declspec(naked)(*)()>([] () EntryPointHook.Initialize(0x6BAC0F, [] ()
{ {
EntryPointHook.Uninstall(); EntryPointHook.Uninstall();
Components::Loader::Initialize(); Components::Loader::Initialize();
__asm jmp EntryPointHook.Place __asm jmp EntryPointHook.Place
}))->Install(); })->Install();
} }
else if (ul_reason_for_call == DLL_PROCESS_DETACH) 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) Hook* Hook::Initialize(DWORD place, void* stub, bool useJump)
{ {
return Hook::Initialize((void*)place, stub, 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(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);
Hook* Initialize(DWORD place, void(*stub)(), bool useJump = true); // For lambdas
Hook* Install(); Hook* Install();
Hook* Uninstall(); Hook* Uninstall();

View File

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

View File

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