small clean up [skip ci]
also no compiler err's
This commit is contained in:
@ -1,103 +0,0 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "command.hpp"
|
||||
#include "scheduler.hpp"
|
||||
#include "network.hpp"
|
||||
#include "party.hpp"
|
||||
|
||||
#include "game/game.hpp"
|
||||
#include "game/scripting/execution.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/string.hpp>
|
||||
#include <utils/cryptography.hpp>
|
||||
|
||||
namespace bots
|
||||
{
|
||||
namespace
|
||||
{
|
||||
bool can_add()
|
||||
{
|
||||
if (party::get_client_count() < *game::mp::svs_numclients)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: when scripting comes, fix this to use better notifies
|
||||
void bot_team_join(const int entity_num)
|
||||
{
|
||||
const game::scr_entref_t entref{static_cast<uint16_t>(entity_num), 0};
|
||||
scheduler::once([entref]()
|
||||
{
|
||||
scripting::notify(entref, "luinotifyserver", {"team_select", 2});
|
||||
scheduler::once([entref]()
|
||||
{
|
||||
auto* _class = utils::string::va("class%d", utils::cryptography::random::get_integer() % 5);
|
||||
scripting::notify(entref, "luinotifyserver", {"class_select", _class});
|
||||
}, scheduler::pipeline::server, 2s);
|
||||
}, scheduler::pipeline::server, 2s);
|
||||
}
|
||||
|
||||
void spawn_bot(const int entity_num)
|
||||
{
|
||||
game::SV_SpawnTestClient(&game::mp::g_entities[entity_num]);
|
||||
if (game::Com_GetCurrentCoDPlayMode() == game::CODPLAYMODE_CORE)
|
||||
{
|
||||
bot_team_join(entity_num);
|
||||
}
|
||||
}
|
||||
|
||||
void add_bot()
|
||||
{
|
||||
if (!can_add())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// SV_BotGetRandomName
|
||||
const auto* const bot_name = game::SV_BotGetRandomName();
|
||||
auto* bot_ent = game::SV_AddBot(bot_name);
|
||||
if (bot_ent)
|
||||
{
|
||||
spawn_bot(bot_ent->s.entityNum);
|
||||
}
|
||||
else if (can_add()) // workaround since first bot won't ever spawn
|
||||
{
|
||||
add_bot();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
if (game::environment::is_sp())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
command::add("spawnBot", [](const command::params& params)
|
||||
{
|
||||
if (!game::SV_Loaded() || game::VirtualLobby_Loaded()) return;
|
||||
|
||||
auto num_bots = 1;
|
||||
if (params.size() == 2)
|
||||
{
|
||||
num_bots = atoi(params.get(1));
|
||||
}
|
||||
|
||||
for (auto i = 0; i < (num_bots > *game::mp::svs_numclients ? *game::mp::svs_numclients : num_bots); i++)
|
||||
{
|
||||
scheduler::once(add_bot, scheduler::pipeline::server, 100ms * i);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(bots::component)
|
@ -1,317 +0,0 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
#include "scheduler.hpp"
|
||||
|
||||
#include "game/scripting/entity.hpp"
|
||||
#include "game/scripting/execution.hpp"
|
||||
#include "game/scripting/lua/value_conversion.hpp"
|
||||
#include "game/scripting/lua/error.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
#include "logfile.hpp"
|
||||
|
||||
namespace logfile
|
||||
{
|
||||
std::unordered_map<const char*, sol::protected_function> vm_execute_hooks;
|
||||
|
||||
namespace
|
||||
{
|
||||
utils::hook::detour scr_player_killed_hook;
|
||||
utils::hook::detour scr_player_damage_hook;
|
||||
|
||||
std::vector<sol::protected_function> player_killed_callbacks;
|
||||
std::vector<sol::protected_function> player_damage_callbacks;
|
||||
|
||||
utils::hook::detour vm_execute_hook;
|
||||
char empty_function[2] = {0x32, 0x34}; // CHECK_CLEAR_PARAMS, END
|
||||
bool hook_enabled = true;
|
||||
|
||||
sol::lua_value convert_entity(lua_State* state, const game::mp::gentity_s* ent)
|
||||
{
|
||||
if (!ent)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
const scripting::entity player{game::Scr_GetEntityId(ent->s.entityNum, 0)};
|
||||
return scripting::lua::convert(state, player);
|
||||
}
|
||||
|
||||
std::string get_weapon_name(unsigned int weapon, bool isAlternate)
|
||||
{
|
||||
char output[1024] = {0};
|
||||
game::BG_GetWeaponNameComplete(weapon, isAlternate, output, 1024);
|
||||
return output;
|
||||
}
|
||||
|
||||
sol::lua_value convert_vector(lua_State* state, const float* vec)
|
||||
{
|
||||
if (!vec)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto vec_ = scripting::vector(vec);
|
||||
return scripting::lua::convert(state, vec_);
|
||||
}
|
||||
|
||||
std::string convert_mod(const int meansOfDeath)
|
||||
{
|
||||
const auto value = reinterpret_cast<game::scr_string_t**>(0x140FEC3F0)[meansOfDeath];
|
||||
const auto string = game::SL_ConvertToString(*value);
|
||||
return string;
|
||||
}
|
||||
|
||||
void scr_player_killed_stub(game::mp::gentity_s* self, const game::mp::gentity_s* inflictor,
|
||||
game::mp::gentity_s* attacker, int damage, const int meansOfDeath, const unsigned int weapon,
|
||||
const bool isAlternate, const float* vDir, const unsigned int hitLoc, int psTimeOffset, int deathAnimDuration)
|
||||
{
|
||||
{
|
||||
const std::string hitloc = reinterpret_cast<const char**>(0x140FEC4D0)[hitLoc];
|
||||
const auto mod_ = convert_mod(meansOfDeath);
|
||||
|
||||
const auto weapon_ = get_weapon_name(weapon, isAlternate);
|
||||
|
||||
for (const auto& callback : player_killed_callbacks)
|
||||
{
|
||||
const auto state = callback.lua_state();
|
||||
|
||||
const auto self_ = convert_entity(state, self);
|
||||
const auto inflictor_ = convert_entity(state, inflictor);
|
||||
const auto attacker_ = convert_entity(state, attacker);
|
||||
|
||||
const auto dir = convert_vector(state, vDir);
|
||||
|
||||
const auto result = callback(self_, inflictor_, attacker_, damage,
|
||||
mod_, weapon_, dir, hitloc, psTimeOffset, deathAnimDuration);
|
||||
|
||||
scripting::lua::handle_error(result);
|
||||
|
||||
if (result.valid() && result.get_type() == sol::type::number)
|
||||
{
|
||||
damage = result.get<int>();
|
||||
}
|
||||
}
|
||||
|
||||
if (damage == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
scr_player_killed_hook.invoke<void>(self, inflictor, attacker, damage, meansOfDeath,
|
||||
weapon, isAlternate, vDir, hitLoc, psTimeOffset, deathAnimDuration);
|
||||
}
|
||||
|
||||
void scr_player_damage_stub(game::mp::gentity_s* self, const game::mp::gentity_s* inflictor,
|
||||
game::mp::gentity_s* attacker, int damage, int dflags, const int meansOfDeath,
|
||||
const unsigned int weapon, const bool isAlternate, const float* vPoint,
|
||||
const float* vDir, const unsigned int hitLoc, const int timeOffset)
|
||||
{
|
||||
{
|
||||
const std::string hitloc = reinterpret_cast<const char**>(0x140FEC4D0)[hitLoc];
|
||||
const auto mod_ = convert_mod(meansOfDeath);
|
||||
|
||||
const auto weapon_ = get_weapon_name(weapon, isAlternate);
|
||||
|
||||
for (const auto& callback : player_damage_callbacks)
|
||||
{
|
||||
const auto state = callback.lua_state();
|
||||
|
||||
const auto self_ = convert_entity(state, self);
|
||||
const auto inflictor_ = convert_entity(state, inflictor);
|
||||
const auto attacker_ = convert_entity(state, attacker);
|
||||
|
||||
const auto point = convert_vector(state, vPoint);
|
||||
const auto dir = convert_vector(state, vDir);
|
||||
|
||||
const auto result = callback(self_, inflictor_, attacker_,
|
||||
damage, dflags, mod_, weapon_, point, dir, hitloc);
|
||||
|
||||
scripting::lua::handle_error(result);
|
||||
|
||||
if (result.valid() && result.get_type() == sol::type::number)
|
||||
{
|
||||
damage = result.get<int>();
|
||||
}
|
||||
}
|
||||
|
||||
if (damage == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
scr_player_damage_hook.invoke<void>(self, inflictor, attacker, damage, dflags,
|
||||
meansOfDeath, weapon, isAlternate, vPoint, vDir, hitLoc, timeOffset);
|
||||
}
|
||||
|
||||
void client_command_stub(const int clientNum)
|
||||
{
|
||||
auto self = &game::mp::g_entities[clientNum];
|
||||
char cmd[1024] = {0};
|
||||
|
||||
game::SV_Cmd_ArgvBuffer(0, cmd, 1024);
|
||||
|
||||
if (cmd == "say"s || cmd == "say_team"s)
|
||||
{
|
||||
auto hidden = false;
|
||||
std::string message(game::ConcatArgs(1));
|
||||
|
||||
hidden = message[1] == '/';
|
||||
message.erase(0, hidden ? 2 : 1);
|
||||
|
||||
scheduler::once([cmd, message, self]()
|
||||
{
|
||||
const scripting::entity level{*game::levelEntityId};
|
||||
const scripting::entity player{game::Scr_GetEntityId(self->s.entityNum, 0)};
|
||||
|
||||
scripting::notify(level, cmd, {player, message});
|
||||
scripting::notify(player, cmd, {message});
|
||||
}, scheduler::pipeline::server);
|
||||
|
||||
if (hidden)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// ClientCommand
|
||||
return utils::hook::invoke<void>(0x140336000, clientNum);
|
||||
}
|
||||
|
||||
void g_shutdown_game_stub(const int freeScripts)
|
||||
{
|
||||
{
|
||||
const scripting::entity level{*game::levelEntityId};
|
||||
scripting::notify(level, "shutdownGame_called", {1});
|
||||
}
|
||||
|
||||
// G_ShutdownGame
|
||||
return utils::hook::invoke<void>(0x140345A60, freeScripts);
|
||||
}
|
||||
|
||||
unsigned int local_id_to_entity(unsigned int local_id)
|
||||
{
|
||||
const auto variable = game::scr_VarGlob->objectVariableValue[local_id];
|
||||
return variable.u.f.next;
|
||||
}
|
||||
|
||||
bool execute_vm_hook(const char* pos)
|
||||
{
|
||||
if (vm_execute_hooks.find(pos) == vm_execute_hooks.end())
|
||||
{
|
||||
hook_enabled = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!hook_enabled && pos > reinterpret_cast<char*>(vm_execute_hooks.size()))
|
||||
{
|
||||
hook_enabled = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto hook = vm_execute_hooks[pos];
|
||||
const auto state = hook.lua_state();
|
||||
|
||||
const scripting::entity self = local_id_to_entity(game::scr_VmPub->function_frame->fs.localId);
|
||||
|
||||
std::vector<sol::lua_value> args;
|
||||
|
||||
const auto top = game::scr_function_stack->top;
|
||||
|
||||
for (auto* value = top; value->type != game::SCRIPT_END; --value)
|
||||
{
|
||||
args.push_back(scripting::lua::convert(state, *value));
|
||||
}
|
||||
|
||||
const auto result = hook(self, sol::as_args(args));
|
||||
scripting::lua::handle_error(result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void vm_execute_stub(utils::hook::assembler& a)
|
||||
{
|
||||
const auto replace = a.newLabel();
|
||||
const auto end = a.newLabel();
|
||||
|
||||
a.pushad64();
|
||||
|
||||
a.mov(rcx, r14);
|
||||
a.call_aligned(execute_vm_hook);
|
||||
|
||||
a.cmp(al, 0);
|
||||
a.jne(replace);
|
||||
|
||||
a.popad64();
|
||||
a.jmp(end);
|
||||
|
||||
a.bind(end);
|
||||
|
||||
a.movzx(r15d, byte_ptr(r14));
|
||||
a.inc(r14);
|
||||
a.mov(dword_ptr(rbp, 0xA4), r15d);
|
||||
|
||||
a.jmp(SELECT_VALUE(0x140376663, 0x140444653));
|
||||
|
||||
a.bind(replace);
|
||||
|
||||
a.popad64();
|
||||
a.mov(r14, reinterpret_cast<char*>(empty_function));
|
||||
a.jmp(end);
|
||||
}
|
||||
}
|
||||
|
||||
void add_player_damage_callback(const sol::protected_function& callback)
|
||||
{
|
||||
player_damage_callbacks.push_back(callback);
|
||||
}
|
||||
|
||||
void add_player_killed_callback(const sol::protected_function& callback)
|
||||
{
|
||||
player_killed_callbacks.push_back(callback);
|
||||
}
|
||||
|
||||
void clear_callbacks()
|
||||
{
|
||||
player_damage_callbacks.clear();
|
||||
player_killed_callbacks.clear();
|
||||
vm_execute_hooks.clear();
|
||||
}
|
||||
|
||||
void enable_vm_execute_hook()
|
||||
{
|
||||
hook_enabled = true;
|
||||
}
|
||||
|
||||
void disable_vm_execute_hook()
|
||||
{
|
||||
hook_enabled = false;
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
if (game::environment::is_sp())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
utils::hook::call(0x14048191D, client_command_stub);
|
||||
|
||||
scr_player_damage_hook.create(0x14037DC50, scr_player_damage_stub);
|
||||
scr_player_killed_hook.create(0x14037DF30, scr_player_killed_stub);
|
||||
|
||||
utils::hook::call(0x140484EC0, g_shutdown_game_stub);
|
||||
utils::hook::call(0x1404853C1, g_shutdown_game_stub);
|
||||
|
||||
utils::hook::jump(SELECT_VALUE(0x140376655, 0x140444645), utils::hook::assemble(vm_execute_stub), true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(logfile::component)
|
@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
namespace logfile
|
||||
{
|
||||
extern std::unordered_map<const char*, sol::protected_function> vm_execute_hooks;
|
||||
|
||||
void add_player_damage_callback(const sol::protected_function& callback);
|
||||
void add_player_killed_callback(const sol::protected_function& callback);
|
||||
void clear_callbacks();
|
||||
|
||||
void enable_vm_execute_hook();
|
||||
void disable_vm_execute_hook();
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include "command.hpp"
|
||||
#include "console.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
namespace lui
|
||||
{
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
// Don't show create cod account popup
|
||||
//utils::hook::set<uint32_t>(0x14017C957, 0); // H1(1.4)
|
||||
|
||||
//#ifdef _DEBUG
|
||||
// Enable development menus (causes issues in sp)
|
||||
//utils::hook::set<uint32_t>(SELECT_VALUE(0x1400B4ABC, 0x1401AB779), 1);
|
||||
//#endif
|
||||
|
||||
command::add("lui_open", [](const command::params& params)
|
||||
{
|
||||
if (params.size() <= 1)
|
||||
{
|
||||
console::info("usage: lui_open <name>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
game::LUI_OpenMenu(0, params[1], 0, 0, 0);
|
||||
});
|
||||
|
||||
command::add("lui_open_popup", [](const command::params& params)
|
||||
{
|
||||
if (params.size() <= 1)
|
||||
{
|
||||
console::info("usage: lui_open_popup <name>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
game::LUI_OpenMenu(0, params[1], 1, 0, 0);
|
||||
});
|
||||
|
||||
command::add("runMenuScript", [](const command::params& params)
|
||||
{
|
||||
const auto args_str = params.join(1);
|
||||
const auto* args = args_str.data();
|
||||
game::UI_RunMenuScript(0, &args);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(lui::component)
|
@ -1,141 +0,0 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "game/game.hpp"
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
#include "game/scripting/entity.hpp"
|
||||
#include "game/scripting/functions.hpp"
|
||||
#include "game/scripting/event.hpp"
|
||||
#include "game/scripting/lua/engine.hpp"
|
||||
#include "game/scripting/execution.hpp"
|
||||
|
||||
#include "scheduler.hpp"
|
||||
#include "scripting.hpp"
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
std::unordered_map<int, std::unordered_map<std::string, int>> fields_table;
|
||||
std::unordered_map<std::string, std::unordered_map<std::string, const char*>> script_function_table;
|
||||
|
||||
namespace
|
||||
{
|
||||
utils::hook::detour vm_notify_hook;
|
||||
utils::hook::detour scr_load_level_hook;
|
||||
utils::hook::detour g_shutdown_game_hook;
|
||||
|
||||
utils::hook::detour scr_add_class_field_hook;
|
||||
|
||||
utils::hook::detour scr_set_thread_position_hook;
|
||||
utils::hook::detour process_script_hook;
|
||||
|
||||
std::string current_file;
|
||||
|
||||
void vm_notify_stub(const unsigned int notify_list_owner_id, const game::scr_string_t string_value,
|
||||
game::VariableValue* top)
|
||||
{
|
||||
if (!game::VirtualLobby_Loaded())
|
||||
{
|
||||
const auto* string = game::SL_ConvertToString(string_value);
|
||||
if (string)
|
||||
{
|
||||
event e;
|
||||
e.name = string;
|
||||
e.entity = notify_list_owner_id;
|
||||
|
||||
for (auto* value = top; value->type != game::SCRIPT_END; --value)
|
||||
{
|
||||
e.arguments.emplace_back(*value);
|
||||
}
|
||||
|
||||
if (e.name == "entitydeleted")
|
||||
{
|
||||
scripting::clear_entity_fields(e.entity);
|
||||
}
|
||||
|
||||
lua::engine::notify(e);
|
||||
}
|
||||
}
|
||||
|
||||
vm_notify_hook.invoke<void>(notify_list_owner_id, string_value, top);
|
||||
}
|
||||
|
||||
void scr_load_level_stub()
|
||||
{
|
||||
scr_load_level_hook.invoke<void>();
|
||||
if (!game::VirtualLobby_Loaded())
|
||||
{
|
||||
lua::engine::start();
|
||||
}
|
||||
}
|
||||
|
||||
void g_shutdown_game_stub(const int free_scripts)
|
||||
{
|
||||
lua::engine::stop();
|
||||
return g_shutdown_game_hook.invoke<void>(free_scripts);
|
||||
}
|
||||
|
||||
void scr_add_class_field_stub(unsigned int classnum, game::scr_string_t _name, unsigned int canonicalString, unsigned int offset)
|
||||
{
|
||||
const auto name = game::SL_ConvertToString(_name);
|
||||
|
||||
if (fields_table[classnum].find(name) == fields_table[classnum].end())
|
||||
{
|
||||
fields_table[classnum][name] = offset;
|
||||
}
|
||||
|
||||
scr_add_class_field_hook.invoke<void>(classnum, _name, canonicalString, offset);
|
||||
}
|
||||
|
||||
void process_script_stub(const char* filename)
|
||||
{
|
||||
const auto file_id = atoi(filename);
|
||||
if (file_id)
|
||||
{
|
||||
current_file = scripting::find_token(file_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
current_file = filename;
|
||||
}
|
||||
|
||||
process_script_hook.invoke<void>(filename);
|
||||
}
|
||||
|
||||
void scr_set_thread_position_stub(unsigned int threadName, const char* codePos)
|
||||
{
|
||||
const auto function_name = scripting::find_token(threadName);
|
||||
script_function_table[current_file][function_name] = codePos;
|
||||
scr_set_thread_position_hook.invoke<void>(threadName, codePos);
|
||||
}
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
if (game::environment::is_sp())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
vm_notify_hook.create(SELECT_VALUE(0x140379A00, 0x1404479F0), vm_notify_stub);
|
||||
|
||||
scr_add_class_field_hook.create(SELECT_VALUE(0x140370370, 0x14043E2C0), scr_add_class_field_stub);
|
||||
|
||||
scr_set_thread_position_hook.create(SELECT_VALUE(0x14036A180, 0x140437D10), scr_set_thread_position_stub);
|
||||
process_script_hook.create(SELECT_VALUE(0x1403737E0, 0x1404417E0), process_script_stub);
|
||||
|
||||
scr_load_level_hook.create(SELECT_VALUE(0x1402A5BE0, 0x1403727C0), scr_load_level_stub);
|
||||
g_shutdown_game_hook.create(SELECT_VALUE(0x140277D40, 0x140345A60), g_shutdown_game_stub);
|
||||
|
||||
scheduler::loop([]()
|
||||
{
|
||||
lua::engine::run_frame();
|
||||
}, scheduler::pipeline::server);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(scripting::component)
|
@ -1,8 +0,0 @@
|
||||
#pragma once
|
||||
#include <utils/concurrency.hpp>
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
extern std::unordered_map<int, std::unordered_map<std::string, int>> fields_table;
|
||||
extern std::unordered_map<std::string, std::unordered_map<std::string, const char*>> script_function_table;
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "scheduler.hpp"
|
||||
#include "dvars.hpp"
|
||||
|
||||
#include "game/game.hpp"
|
||||
#include "game/dvars.hpp"
|
||||
|
||||
#include <utils/nt.hpp>
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/flags.hpp>
|
||||
|
||||
namespace shaders
|
||||
{
|
||||
namespace
|
||||
{
|
||||
game::dvar_t* disable_shader_caching = nullptr;
|
||||
|
||||
bool shader_should_show_dialog_stub()
|
||||
{
|
||||
return !disable_shader_caching->current.enabled;
|
||||
}
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
if (!game::environment::is_mp())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto has_flag = utils::flags::has_flag("noshadercaching");
|
||||
|
||||
disable_shader_caching = dvars::register_bool("disable_shader_caching", has_flag, game::DVAR_FLAG_SAVED, true);
|
||||
if (has_flag)
|
||||
{
|
||||
dvars::override::set_bool("disable_shader_caching", 1);
|
||||
dvars::override::set_from_string("disable_shader_caching", "1");
|
||||
}
|
||||
|
||||
utils::hook::jump(0x14007E710, shader_should_show_dialog_stub);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(shaders::component)
|
@ -1,53 +0,0 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/string.hpp>
|
||||
|
||||
namespace slowmotion
|
||||
{
|
||||
namespace
|
||||
{
|
||||
void scr_cmd_set_slow_motion()
|
||||
{
|
||||
if (game::Scr_GetNumParam() < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int duration = 1000;
|
||||
float end = 1.0f;
|
||||
const float start = game::Scr_GetFloat(0);
|
||||
|
||||
if (game::Scr_GetNumParam() >= 2)
|
||||
{
|
||||
end = game::Scr_GetFloat(1u);
|
||||
}
|
||||
|
||||
if (game::Scr_GetNumParam() >= 3)
|
||||
{
|
||||
duration = static_cast<int>(game::Scr_GetFloat(2u) * 1000.0f);
|
||||
}
|
||||
|
||||
game::SV_SetConfigstring(10, utils::string::va("%i %i %g %g", *game::mp::gameTime, duration, start, end));
|
||||
game::Com_SetSlowMotion(start, end, duration);
|
||||
}
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
if (!game::environment::is_dedi())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
utils::hook::jump(0x140365480, scr_cmd_set_slow_motion); // H1(1.4)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(slowmotion::component)
|
@ -1,60 +0,0 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "scheduler.hpp"
|
||||
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include <utils/thread.hpp>
|
||||
|
||||
namespace thread_names
|
||||
{
|
||||
namespace
|
||||
{
|
||||
void set_thread_names()
|
||||
{
|
||||
static std::unordered_map<int, std::string> thread_names =
|
||||
{
|
||||
{game::THREAD_CONTEXT_MAIN, "Main"},
|
||||
{game::THREAD_CONTEXT_BACKEND, "Backend"}, // Renderer
|
||||
{game::THREAD_CONTEXT_WORKER0, "Worker0"},
|
||||
{game::THREAD_CONTEXT_WORKER1, "Worker1"},
|
||||
{game::THREAD_CONTEXT_WORKER2, "Worker2"},
|
||||
{game::THREAD_CONTEXT_WORKER3, "Worker3"},
|
||||
{game::THREAD_CONTEXT_WORKER4, "Worker4"},
|
||||
{game::THREAD_CONTEXT_WORKER5, "Worker5"},
|
||||
{game::THREAD_CONTEXT_WORKER6, "Worker6"},
|
||||
{game::THREAD_CONTEXT_WORKER7, "Worker7"},
|
||||
{game::THREAD_CONTEXT_SERVER, "Server"},
|
||||
{game::THREAD_CONTEXT_CINEMATIC, "Cinematic"},
|
||||
{game::THREAD_CONTEXT_DATABASE, "Database"},
|
||||
{game::THREAD_CONTEXT_STREAM, "Stream"},
|
||||
{game::THREAD_CONTEXT_SNDSTREAMPACKETCALLBACK, "Snd stream packet callback"},
|
||||
{game::THREAD_CONTEXT_STATS_WRITE, "Stats write"},
|
||||
};
|
||||
|
||||
for (const auto& thread_name : thread_names)
|
||||
{
|
||||
const auto id = game::threadIds[thread_name.first];
|
||||
if (id)
|
||||
{
|
||||
utils::thread::set_name(id, thread_name.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
set_thread_names();
|
||||
scheduler::once(set_thread_names, scheduler::pipeline::main);
|
||||
scheduler::once(set_thread_names, scheduler::pipeline::renderer);
|
||||
scheduler::once(set_thread_names, scheduler::pipeline::server);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(thread_names::component)
|
@ -1,180 +0,0 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "game/game.hpp"
|
||||
#include "game/dvars.hpp"
|
||||
|
||||
#include "scheduler.hpp"
|
||||
#include "command.hpp"
|
||||
|
||||
#include "ui_scripting.hpp"
|
||||
|
||||
#include "game/ui_scripting/lua/engine.hpp"
|
||||
#include "game/ui_scripting/execution.hpp"
|
||||
#include "game/ui_scripting/lua/error.hpp"
|
||||
|
||||
#include <utils/string.hpp>
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
namespace ui_scripting
|
||||
{
|
||||
namespace
|
||||
{
|
||||
std::unordered_map<game::hks::cclosure*, sol::protected_function> converted_functions;
|
||||
|
||||
utils::hook::detour hksi_lual_error_hook;
|
||||
utils::hook::detour hksi_lual_error_hook2;
|
||||
utils::hook::detour hks_start_hook;
|
||||
utils::hook::detour hks_shutdown_hook;
|
||||
utils::hook::detour hks_allocator_hook;
|
||||
utils::hook::detour hks_frame_hook;
|
||||
|
||||
bool error_hook_enabled = false;
|
||||
|
||||
void hksi_lual_error_stub(game::hks::lua_State* s, const char* fmt, ...)
|
||||
{
|
||||
char va_buffer[2048] = {0};
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vsprintf_s(va_buffer, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
const auto formatted = std::string(va_buffer);
|
||||
|
||||
if (!error_hook_enabled)
|
||||
{
|
||||
return hksi_lual_error_hook.invoke<void>(s, formatted.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error(formatted);
|
||||
}
|
||||
}
|
||||
|
||||
void* hks_start_stub(char a1)
|
||||
{
|
||||
const auto _1 = gsl::finally([]()
|
||||
{
|
||||
ui_scripting::lua::engine::start();
|
||||
});
|
||||
|
||||
return hks_start_hook.invoke<void*>(a1);
|
||||
}
|
||||
|
||||
void hks_shutdown_stub()
|
||||
{
|
||||
ui_scripting::lua::engine::stop();
|
||||
hks_shutdown_hook.invoke<void*>();
|
||||
}
|
||||
|
||||
void* hks_allocator_stub(void* userData, void* oldMemory, unsigned __int64 oldSize, unsigned __int64 newSize)
|
||||
{
|
||||
const auto closure = reinterpret_cast<game::hks::cclosure*>(oldMemory);
|
||||
if (converted_functions.find(closure) != converted_functions.end())
|
||||
{
|
||||
converted_functions.erase(closure);
|
||||
}
|
||||
|
||||
return hks_allocator_hook.invoke<void*>(userData, oldMemory, oldSize, newSize);
|
||||
}
|
||||
|
||||
void hks_frame_stub()
|
||||
{
|
||||
const auto state = *game::hks::lua_state;
|
||||
if (state)
|
||||
{
|
||||
ui_scripting::lua::engine::run_frame();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main_function_handler(game::hks::lua_State* state)
|
||||
{
|
||||
const auto value = state->m_apistack.base[-1];
|
||||
if (value.t != game::hks::TCFUNCTION)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const auto closure = reinterpret_cast<game::hks::cclosure*>(value.v.cClosure);
|
||||
if (converted_functions.find(closure) == converted_functions.end())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const auto function = converted_functions[closure];
|
||||
const auto count = static_cast<int>(state->m_apistack.top - state->m_apistack.base);
|
||||
const auto arguments = get_return_values(count);
|
||||
const auto s = function.lua_state();
|
||||
|
||||
std::vector<sol::lua_value> converted_args;
|
||||
|
||||
for (const auto& argument : arguments)
|
||||
{
|
||||
converted_args.push_back(lua::convert(s, argument));
|
||||
}
|
||||
|
||||
const auto results = function(sol::as_args(converted_args));
|
||||
lua::handle_error(results);
|
||||
|
||||
for (const auto& result : results)
|
||||
{
|
||||
push_value(lua::convert({s, result}));
|
||||
}
|
||||
|
||||
return results.return_count();
|
||||
}
|
||||
|
||||
void add_converted_function(game::hks::cclosure* closure, const sol::protected_function& function)
|
||||
{
|
||||
converted_functions[closure] = function;
|
||||
}
|
||||
|
||||
void clear_converted_functions()
|
||||
{
|
||||
converted_functions.clear();
|
||||
}
|
||||
|
||||
void enable_error_hook()
|
||||
{
|
||||
error_hook_enabled = true;
|
||||
}
|
||||
|
||||
void disable_error_hook()
|
||||
{
|
||||
error_hook_enabled = false;
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
|
||||
void post_unpack() override
|
||||
{
|
||||
if (game::environment::is_dedi())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
hks_start_hook.create(SELECT_VALUE(0x1400E4B40, 0x140176A40), hks_start_stub);
|
||||
hks_shutdown_hook.create(SELECT_VALUE(0x1400DD3D0, 0x14016CA80), hks_shutdown_stub);
|
||||
hksi_lual_error_hook.create(SELECT_VALUE(0x1400A5EA0, 0x14012F300), hksi_lual_error_stub);
|
||||
hks_allocator_hook.create(SELECT_VALUE(0x14009B570, 0x14012BAC0), hks_allocator_stub);
|
||||
hks_frame_hook.create(SELECT_VALUE(0x1400E37F0, 0x1401755B0), hks_frame_stub);
|
||||
|
||||
if (game::environment::is_mp())
|
||||
{
|
||||
hksi_lual_error_hook2.create(0x1401366B0, hksi_lual_error_stub);
|
||||
}
|
||||
|
||||
command::add("lui_restart", []()
|
||||
{
|
||||
utils::hook::invoke<void>(SELECT_VALUE(0x1400DD3D0, 0x14016CA80));
|
||||
utils::hook::invoke<void>(SELECT_VALUE(0x1400E6170, 0x1401780D0));
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(ui_scripting::component)
|
@ -1,12 +0,0 @@
|
||||
#pragma once
|
||||
#include "game/ui_scripting/lua/value_conversion.hpp"
|
||||
|
||||
namespace ui_scripting
|
||||
{
|
||||
int main_function_handler(game::hks::lua_State* state);
|
||||
void add_converted_function(game::hks::cclosure* closure, const sol::protected_function& function);
|
||||
void clear_converted_functions();
|
||||
|
||||
void enable_error_hook();
|
||||
void disable_error_hook();
|
||||
}
|
@ -1,474 +0,0 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "scheduler.hpp"
|
||||
#include "dvars.hpp"
|
||||
#include "updater.hpp"
|
||||
|
||||
#include "version.h"
|
||||
|
||||
#include "game/game.hpp"
|
||||
#include "game/dvars.hpp"
|
||||
|
||||
#include <utils/nt.hpp>
|
||||
#include <utils/concurrency.hpp>
|
||||
#include <utils/http.hpp>
|
||||
#include <utils/cryptography.hpp>
|
||||
#include <utils/io.hpp>
|
||||
#include <utils/string.hpp>
|
||||
|
||||
#define MASTER "https://master.fed0001.xyz/h1-mod/"
|
||||
|
||||
#define FILES_PATH "files.json"
|
||||
#define FILES_PATH_DEV "files-dev.json"
|
||||
|
||||
#define DATA_PATH "data/"
|
||||
#define DATA_PATH_DEV "data-dev/"
|
||||
|
||||
#define ERR_UPDATE_CHECK_FAIL "Failed to check for updates"
|
||||
#define ERR_DOWNLOAD_FAIL "Failed to download file "
|
||||
#define ERR_WRITE_FAIL "Failed to write file "
|
||||
|
||||
#define BINARY_NAME "h1-mod.exe"
|
||||
|
||||
namespace updater
|
||||
{
|
||||
namespace
|
||||
{
|
||||
game::dvar_t* cl_auto_update;
|
||||
bool has_tried_update = false;
|
||||
|
||||
struct status
|
||||
{
|
||||
bool done;
|
||||
bool success;
|
||||
};
|
||||
|
||||
struct file_data
|
||||
{
|
||||
std::string name;
|
||||
std::string data;
|
||||
};
|
||||
|
||||
struct update_data_t
|
||||
{
|
||||
bool restart_required{};
|
||||
bool cancelled{};
|
||||
status check{};
|
||||
status download{};
|
||||
std::string error{};
|
||||
std::string current_file{};
|
||||
std::vector<std::string> required_files{};
|
||||
};
|
||||
|
||||
utils::concurrency::container<update_data_t> update_data;
|
||||
|
||||
std::string get_branch()
|
||||
{
|
||||
return GIT_BRANCH;
|
||||
}
|
||||
|
||||
std::string select(const std::string& main, const std::string& develop)
|
||||
{
|
||||
if (get_branch() == "develop")
|
||||
{
|
||||
return develop;
|
||||
}
|
||||
|
||||
return main;
|
||||
}
|
||||
|
||||
std::string get_data_path()
|
||||
{
|
||||
if (get_branch() == "develop")
|
||||
{
|
||||
return DATA_PATH_DEV;
|
||||
}
|
||||
|
||||
return DATA_PATH;
|
||||
}
|
||||
|
||||
void set_update_check_status(bool done, bool success, const std::string& error = {})
|
||||
{
|
||||
update_data.access([done, success, error](update_data_t& data_)
|
||||
{
|
||||
data_.check.done = done;
|
||||
data_.check.success = success;
|
||||
data_.error = error;
|
||||
});
|
||||
}
|
||||
|
||||
void set_update_download_status(bool done, bool success, const std::string& error = {})
|
||||
{
|
||||
update_data.access([done, success, error](update_data_t& data_)
|
||||
{
|
||||
data_.download.done = done;
|
||||
data_.download.success = success;
|
||||
data_.error = error;
|
||||
});
|
||||
}
|
||||
|
||||
bool check_file(const std::string& name, const std::string& sha)
|
||||
{
|
||||
std::string data;
|
||||
if (!utils::io::read_file(name, &data))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (utils::cryptography::sha1::compute(data, true) != sha)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string load_binary_name()
|
||||
{
|
||||
// utils::nt::library self;
|
||||
// return self.get_name();
|
||||
// returns the game's name and not the client's
|
||||
|
||||
return BINARY_NAME;
|
||||
}
|
||||
|
||||
std::string get_binary_name()
|
||||
{
|
||||
static const auto name = load_binary_name();
|
||||
return name;
|
||||
}
|
||||
|
||||
std::string get_time_str()
|
||||
{
|
||||
return utils::string::va("%i", uint32_t(time(nullptr)));
|
||||
}
|
||||
|
||||
std::optional<std::string> download_file(const std::string& name)
|
||||
{
|
||||
return utils::http::get_data(MASTER + select(DATA_PATH, DATA_PATH_DEV) + name + "?" + get_time_str());
|
||||
}
|
||||
|
||||
bool is_update_cancelled()
|
||||
{
|
||||
return update_data.access<bool>([](update_data_t& data_)
|
||||
{
|
||||
return data_.cancelled;
|
||||
});
|
||||
}
|
||||
|
||||
bool write_file(const std::string& name, const std::string& data)
|
||||
{
|
||||
if (get_binary_name() == name &&
|
||||
utils::io::file_exists(name) &&
|
||||
!utils::io::move_file(name, name + ".old"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
return utils::io::write_file("update_test/" + name, data);
|
||||
#else
|
||||
return utils::io::write_file(name, data);
|
||||
#endif
|
||||
}
|
||||
|
||||
void delete_old_file()
|
||||
{
|
||||
utils::io::remove_file(get_binary_name() + ".old");
|
||||
}
|
||||
|
||||
void reset_data()
|
||||
{
|
||||
update_data.access([](update_data_t& data_)
|
||||
{
|
||||
data_ = {};
|
||||
});
|
||||
}
|
||||
|
||||
std::string get_mode_flag()
|
||||
{
|
||||
if (game::environment::is_mp())
|
||||
{
|
||||
return "-multiplayer";
|
||||
}
|
||||
|
||||
if (game::environment::is_sp())
|
||||
{
|
||||
return "-singleplayer";
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
// workaround
|
||||
void relaunch()
|
||||
{
|
||||
if (!utils::io::file_exists(BINARY_NAME))
|
||||
{
|
||||
utils::nt::terminate(0);
|
||||
return;
|
||||
}
|
||||
|
||||
STARTUPINFOA startup_info;
|
||||
PROCESS_INFORMATION process_info;
|
||||
|
||||
ZeroMemory(&startup_info, sizeof(startup_info));
|
||||
ZeroMemory(&process_info, sizeof(process_info));
|
||||
startup_info.cb = sizeof(startup_info);
|
||||
|
||||
char current_dir[MAX_PATH];
|
||||
GetCurrentDirectoryA(sizeof(current_dir), current_dir);
|
||||
|
||||
char buf[1024] = {0};
|
||||
const auto command_line = utils::string::va("%s %s", GetCommandLineA(), get_mode_flag().data());
|
||||
strcpy_s(buf, 1024, command_line);
|
||||
|
||||
CreateProcess(BINARY_NAME, buf, nullptr, nullptr, false, NULL, nullptr, current_dir,
|
||||
&startup_info, &process_info);
|
||||
|
||||
if (process_info.hThread && process_info.hThread != INVALID_HANDLE_VALUE) CloseHandle(process_info.hThread);
|
||||
if (process_info.hProcess && process_info.hProcess != INVALID_HANDLE_VALUE) CloseHandle(process_info.hProcess);
|
||||
|
||||
utils::nt::terminate(0);
|
||||
}
|
||||
|
||||
void set_has_tried_update(bool tried)
|
||||
{
|
||||
has_tried_update = tried;
|
||||
}
|
||||
|
||||
bool get_has_tried_update()
|
||||
{
|
||||
return has_tried_update;
|
||||
}
|
||||
|
||||
bool auto_updates_enabled()
|
||||
{
|
||||
return cl_auto_update->current.enabled;
|
||||
}
|
||||
|
||||
bool is_update_check_done()
|
||||
{
|
||||
return update_data.access<bool>([](update_data_t& data_)
|
||||
{
|
||||
return data_.check.done;
|
||||
});
|
||||
}
|
||||
|
||||
bool is_update_download_done()
|
||||
{
|
||||
return update_data.access<bool>([](update_data_t& data_)
|
||||
{
|
||||
return data_.download.done;
|
||||
});
|
||||
}
|
||||
|
||||
bool get_update_check_status()
|
||||
{
|
||||
return update_data.access<bool>([](update_data_t& data_)
|
||||
{
|
||||
return data_.check.success;
|
||||
});
|
||||
}
|
||||
|
||||
bool get_update_download_status()
|
||||
{
|
||||
return update_data.access<bool>([](update_data_t& data_)
|
||||
{
|
||||
return data_.download.success;
|
||||
});
|
||||
}
|
||||
|
||||
bool is_update_available()
|
||||
{
|
||||
return update_data.access<bool>([](update_data_t& data_)
|
||||
{
|
||||
return data_.required_files.size() > 0;
|
||||
});
|
||||
}
|
||||
|
||||
bool is_restart_required()
|
||||
{
|
||||
return update_data.access<bool>([](update_data_t& data_)
|
||||
{
|
||||
return data_.restart_required;
|
||||
});
|
||||
}
|
||||
|
||||
std::string get_last_error()
|
||||
{
|
||||
return update_data.access<std::string>([](update_data_t& data_)
|
||||
{
|
||||
return data_.error;
|
||||
});
|
||||
}
|
||||
|
||||
std::string get_current_file()
|
||||
{
|
||||
return update_data.access<std::string>([](update_data_t& data_)
|
||||
{
|
||||
return data_.current_file;
|
||||
});
|
||||
}
|
||||
|
||||
void cancel_update()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("[Updater] Cancelling update\n");
|
||||
#endif
|
||||
|
||||
return update_data.access([](update_data_t& data_)
|
||||
{
|
||||
data_.cancelled = true;
|
||||
});
|
||||
}
|
||||
|
||||
void start_update_check()
|
||||
{
|
||||
cancel_update();
|
||||
reset_data();
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("[Updater] starting update check\n");
|
||||
#endif
|
||||
|
||||
scheduler::once([]()
|
||||
{
|
||||
const auto files_data = utils::http::get_data(MASTER + select(FILES_PATH, FILES_PATH_DEV) + "?" + get_time_str());
|
||||
|
||||
if (is_update_cancelled())
|
||||
{
|
||||
reset_data();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!files_data.has_value())
|
||||
{
|
||||
set_update_check_status(true, false, ERR_UPDATE_CHECK_FAIL);
|
||||
return;
|
||||
}
|
||||
|
||||
rapidjson::Document j;
|
||||
j.Parse(files_data.value().data());
|
||||
|
||||
if (!j.IsArray())
|
||||
{
|
||||
set_update_check_status(true, false, ERR_UPDATE_CHECK_FAIL);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::string> required_files;
|
||||
|
||||
const auto files = j.GetArray();
|
||||
for (const auto& file : files)
|
||||
{
|
||||
if (!file.IsArray() || file.Size() != 3 || !file[0].IsString() || !file[2].IsString())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto name = file[0].GetString();
|
||||
const auto sha = file[2].GetString();
|
||||
|
||||
if (!check_file(name, sha))
|
||||
{
|
||||
if (get_binary_name() == name)
|
||||
{
|
||||
update_data.access([](update_data_t& data_)
|
||||
{
|
||||
data_.restart_required = true;
|
||||
});
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("[Updater] need file %s\n", name);
|
||||
#endif
|
||||
|
||||
required_files.push_back(name);
|
||||
}
|
||||
}
|
||||
|
||||
update_data.access([&required_files](update_data_t& data_)
|
||||
{
|
||||
data_.check.done = true;
|
||||
data_.check.success = true;
|
||||
data_.required_files = required_files;
|
||||
});
|
||||
}, scheduler::pipeline::async);
|
||||
}
|
||||
|
||||
void start_update_download()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("[Updater] starting update download\n");
|
||||
#endif
|
||||
|
||||
if (!is_update_check_done() || !get_update_check_status() || is_update_cancelled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
scheduler::once([]()
|
||||
{
|
||||
const auto required_files = update_data.access<std::vector<std::string>>([](update_data_t& data_)
|
||||
{
|
||||
return data_.required_files;
|
||||
});
|
||||
|
||||
std::vector<file_data> downloads;
|
||||
|
||||
for (const auto& file : required_files)
|
||||
{
|
||||
update_data.access([file](update_data_t& data_)
|
||||
{
|
||||
data_.current_file = file;
|
||||
});
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("[Updater] downloading file %s\n", file.data());
|
||||
#endif
|
||||
|
||||
const auto data = download_file(file);
|
||||
|
||||
if (is_update_cancelled())
|
||||
{
|
||||
reset_data();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data.has_value())
|
||||
{
|
||||
set_update_download_status(true, false, ERR_DOWNLOAD_FAIL + file);
|
||||
return;
|
||||
}
|
||||
|
||||
downloads.push_back({file, data.value()});
|
||||
}
|
||||
|
||||
for (const auto& download : downloads)
|
||||
{
|
||||
if (!write_file(download.name, download.data))
|
||||
{
|
||||
set_update_download_status(true, false, ERR_WRITE_FAIL + download.name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
set_update_download_status(true, true);
|
||||
}, scheduler::pipeline::async);
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
delete_old_file();
|
||||
cl_auto_update = dvars::register_bool("cg_auto_update", true, game::DVAR_FLAG_SAVED, true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(updater::component)
|
@ -1,26 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
namespace updater
|
||||
{
|
||||
void relaunch();
|
||||
|
||||
void set_has_tried_update(bool tried);
|
||||
bool get_has_tried_update();
|
||||
bool auto_updates_enabled();
|
||||
|
||||
bool is_update_available();
|
||||
bool is_update_check_done();
|
||||
bool get_update_check_status();
|
||||
|
||||
bool is_update_download_done();
|
||||
bool get_update_download_status();
|
||||
|
||||
bool is_restart_required();
|
||||
|
||||
std::string get_last_error();
|
||||
std::string get_current_file();
|
||||
|
||||
void start_update_check();
|
||||
void start_update_download();
|
||||
void cancel_update();
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
namespace videos
|
||||
{
|
||||
namespace
|
||||
{
|
||||
utils::hook::detour playvid_hook;
|
||||
std::unordered_map<std::string, std::string> video_replaces;
|
||||
|
||||
void playvid(const char* name, const int a2, const int a3)
|
||||
{
|
||||
const auto vid = video_replaces.find(name);
|
||||
if (vid != video_replaces.end())
|
||||
{
|
||||
char path[256];
|
||||
game::Sys_BuildAbsPath(path, sizeof(path), game::SF_VIDEO, vid->second.data(), ".bik");
|
||||
|
||||
if (game::Sys_FileExists(path))
|
||||
{
|
||||
name = vid->second.data();
|
||||
}
|
||||
}
|
||||
|
||||
return playvid_hook.invoke<void>(name, a2, a3);
|
||||
}
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
playvid_hook.create(SELECT_VALUE(0x1404A9D00, 0x1405B0AF0), &playvid); // H1(1.4)
|
||||
|
||||
if (game::environment::is_mp())
|
||||
{
|
||||
video_replaces["menus_bg_comp2"] = "menus_bg_h1mod";
|
||||
video_replaces["mp_menus_bg_options"] = "menus_bg_h1mod_blur";
|
||||
}
|
||||
else if (game::environment::is_sp())
|
||||
{
|
||||
video_replaces["sp_menus_bg_main_menu"] = "menus_bg_h1mod_sp";
|
||||
video_replaces["sp_menus_bg_campaign"] = "menus_bg_h1mod_sp";
|
||||
video_replaces["sp_menus_bg_options"] = "menus_bg_h1mod_sp";
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(videos::component)
|
@ -1,63 +0,0 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "game/game.hpp"
|
||||
#include "game/dvars.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
namespace virtuallobby
|
||||
{
|
||||
namespace
|
||||
{
|
||||
game::dvar_t* virtualLobby_fovscale;
|
||||
|
||||
const auto get_fovscale_stub = utils::hook::assemble([](utils::hook::assembler& a)
|
||||
{
|
||||
const auto ret = a.newLabel();
|
||||
const auto original = a.newLabel();
|
||||
|
||||
a.pushad64();
|
||||
a.mov(rax, qword_ptr(0x1425F7210)); // virtualLobbyInFiringRange
|
||||
a.cmp(byte_ptr(rax, 0x10), 1);
|
||||
a.je(original);
|
||||
a.call_aligned(game::VirtualLobby_Loaded);
|
||||
a.cmp(al, 0);
|
||||
a.je(original);
|
||||
|
||||
// virtuallobby
|
||||
a.popad64();
|
||||
a.mov(rax, ptr(reinterpret_cast<int64_t>(&virtualLobby_fovscale)));
|
||||
a.jmp(ret);
|
||||
|
||||
// original
|
||||
a.bind(original);
|
||||
a.popad64();
|
||||
a.mov(rax, qword_ptr(0x1413A8580));
|
||||
a.jmp(ret);
|
||||
|
||||
a.bind(ret);
|
||||
a.mov(rcx, 0x142935000);
|
||||
a.jmp(0x1400B556A);
|
||||
});
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
if (!game::environment::is_mp())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
virtualLobby_fovscale = dvars::register_float("virtualLobby_fovScale", 0.7f, 0.0f, 2.0f, game::DVAR_FLAG_SAVED);
|
||||
|
||||
utils::hook::nop(0x1400B555C, 14);
|
||||
utils::hook::jump(0x1400B555C, get_fovscale_stub, true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(virtuallobby::component)
|
Reference in New Issue
Block a user