Add UIScript support.
This commit is contained in:
parent
601d4d063e
commit
03fac2e637
@ -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();
|
||||
}
|
||||
}
|
@ -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());
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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
285
iw4/Components/UIFeeder.cpp
Normal 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();
|
||||
}
|
||||
}
|
@ -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
110
iw4/Components/UIScript.cpp
Normal 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();
|
||||
}
|
||||
}
|
39
iw4/Components/UIScript.hpp
Normal file
39
iw4/Components/UIScript.hpp
Normal 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;
|
||||
};
|
||||
}
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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" />
|
||||
|
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user