new stuff and other stuff
This commit is contained in:
parent
745486e18c
commit
58dc53850b
150
src/client/component/binding.cpp
Normal file
150
src/client/component/binding.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
#include <utils/string.hpp>
|
||||
|
||||
namespace binding
|
||||
{
|
||||
namespace
|
||||
{
|
||||
std::vector<std::string> custom_binds = {};
|
||||
|
||||
utils::hook::detour cl_execute_key_hook;
|
||||
|
||||
int get_num_keys()
|
||||
{
|
||||
return 118;
|
||||
}
|
||||
|
||||
int key_write_bindings_to_buffer_stub(int, char* buffer, const int buffer_size)
|
||||
{
|
||||
auto bytes_used = 0;
|
||||
const auto buffer_size_align = static_cast<std::int32_t>(buffer_size) - 4;
|
||||
|
||||
for (auto key_index = 0; key_index < 256; ++key_index)
|
||||
{
|
||||
const auto* const key_button = game::Key_KeynumToString(key_index, 0, 1);
|
||||
auto value = game::playerKeys->keys[key_index].binding;
|
||||
|
||||
if (value && value < get_num_keys())
|
||||
{
|
||||
const auto len = sprintf_s(&buffer[bytes_used], (buffer_size_align - bytes_used),
|
||||
"bind %s \"%s\"\n", key_button, game::command_whitelist[value]);
|
||||
|
||||
if (len < 0)
|
||||
{
|
||||
return bytes_used;
|
||||
}
|
||||
|
||||
bytes_used += len;
|
||||
}
|
||||
else if (value >= get_num_keys())
|
||||
{
|
||||
value -= get_num_keys();
|
||||
if (static_cast<size_t>(value) < custom_binds.size() && !custom_binds[value].empty())
|
||||
{
|
||||
const auto len = sprintf_s(&buffer[bytes_used], (buffer_size_align - bytes_used),
|
||||
"bind %s \"%s\"\n", key_button, custom_binds[value].data());
|
||||
|
||||
if (len < 0)
|
||||
{
|
||||
return bytes_used;
|
||||
}
|
||||
|
||||
bytes_used += len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buffer[bytes_used] = 0;
|
||||
return bytes_used;
|
||||
}
|
||||
|
||||
int get_binding_for_custom_command(const char* command)
|
||||
{
|
||||
auto index = 0;
|
||||
for (auto& bind : custom_binds)
|
||||
{
|
||||
if (bind == command)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
custom_binds.emplace_back(command);
|
||||
index = static_cast<unsigned int>(custom_binds.size()) - 1;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
int key_get_binding_for_cmd_stub(const char* command)
|
||||
{
|
||||
// original binds
|
||||
for (auto i = 0; i < get_num_keys(); i++)
|
||||
{
|
||||
if (game::command_whitelist[i] && !strcmp(command, game::command_whitelist[i]))
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
// custom binds
|
||||
return get_num_keys() + get_binding_for_custom_command(command);
|
||||
}
|
||||
|
||||
|
||||
std::optional<std::string> get_custom_binding_for_key(int key)
|
||||
{
|
||||
key -= get_num_keys();
|
||||
|
||||
if (static_cast<size_t>(key) < custom_binds.size() && !custom_binds[key].empty())
|
||||
{
|
||||
return { custom_binds[key] };
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void cl_execute_key_stub(const int local_client_num, int key, const int down, const unsigned int time)
|
||||
{
|
||||
if (key >= get_num_keys())
|
||||
{
|
||||
const auto bind = get_custom_binding_for_key(key);
|
||||
if (!bind.has_value())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
return game::Cbuf_AddText(local_client_num, utils::string::va("%s\n", bind.value().data()));
|
||||
}
|
||||
|
||||
cl_execute_key_hook.invoke<void>(local_client_num, key, down, time);
|
||||
}
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
if (game::environment::is_dedi())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// write all bindings to config file
|
||||
utils::hook::jump(0x9A9F70_b, key_write_bindings_to_buffer_stub);
|
||||
|
||||
// links a custom command to an index
|
||||
utils::hook::jump(0x9A8EA0_b, key_get_binding_for_cmd_stub);
|
||||
|
||||
// execute custom binds
|
||||
cl_execute_key_hook.create(0x32A3B0_b, &cl_execute_key_stub);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(binding::component)
|
@ -6,6 +6,7 @@
|
||||
#include "version.hpp"
|
||||
|
||||
#include "game/game.hpp"
|
||||
#include "game/dvars.hpp"
|
||||
|
||||
// Fonts used in game:
|
||||
// fonts/blender_pro_bold.ttf, fonts/blender_pro_book.ttf, fonts/blender_pro_heavy.ttf, fonts/blender_pro_medium.ttf
|
||||
@ -16,8 +17,6 @@ namespace branding
|
||||
namespace
|
||||
{
|
||||
float color[4] = { 0.666f, 0.666f, 0.666f, 0.666f };
|
||||
|
||||
game::dvar_t* branding;
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
@ -38,12 +37,12 @@ namespace branding
|
||||
|
||||
scheduler::once([]()
|
||||
{
|
||||
branding = game::Dvar_RegisterBool("branding", true, game::DvarFlags::DVAR_FLAG_SAVED, "Show branding in the top left corner");
|
||||
dvars::branding = game::Dvar_RegisterBool("branding", true, game::DvarFlags::DVAR_FLAG_SAVED, "Show branding in the top left corner");
|
||||
}, scheduler::pipeline::renderer);
|
||||
|
||||
scheduler::loop([]()
|
||||
{
|
||||
if (branding && branding->current.enabled)
|
||||
if (dvars::branding && dvars::branding->current.enabled)
|
||||
{
|
||||
const auto font = game::R_RegisterFont("fonts/fira_mono_bold.ttf", 20);
|
||||
if (font)
|
||||
|
@ -18,7 +18,8 @@ namespace command
|
||||
{
|
||||
namespace
|
||||
{
|
||||
utils::hook::detour client_command_hook;
|
||||
utils::hook::detour client_command_mp_hook;
|
||||
utils::hook::detour client_command_sp_hook;
|
||||
utils::hook::detour parse_commandline_hook;
|
||||
|
||||
std::unordered_map<std::string, std::function<void(params&)>> handlers;
|
||||
@ -35,7 +36,7 @@ namespace command
|
||||
}
|
||||
}
|
||||
|
||||
void client_command(const int client_num)
|
||||
void client_command_mp(const int client_num)
|
||||
{
|
||||
params_sv params = {};
|
||||
|
||||
@ -45,7 +46,22 @@ namespace command
|
||||
handlers_sv[command](client_num, params);
|
||||
}
|
||||
|
||||
client_command_hook.invoke<void>(client_num);
|
||||
client_command_mp_hook.invoke<void>(client_num);
|
||||
}
|
||||
|
||||
void client_command_sp(const int client_num, const char* s)
|
||||
{
|
||||
game::SV_Cmd_TokenizeString(s);
|
||||
params_sv params = {};
|
||||
|
||||
const auto command = utils::string::to_lower(s);
|
||||
if (handlers_sv.find(command) != handlers_sv.end())
|
||||
{
|
||||
handlers_sv[command](client_num, params);
|
||||
}
|
||||
game::SV_Cmd_EndTokenizedString();
|
||||
|
||||
client_command_sp_hook.invoke<void>(client_num, s);
|
||||
}
|
||||
|
||||
// Shamelessly stolen from Quake3
|
||||
@ -109,8 +125,8 @@ namespace command
|
||||
const auto current = game::Dvar_ValueToString(dvar, dvar->current);
|
||||
const auto reset = game::Dvar_ValueToString(dvar, dvar->reset);
|
||||
|
||||
console::info("\"%s\" is: \"%s\" default: \"%s\" hash: 0x%08lX type: %i\n",
|
||||
args[0], current, reset, dvar->hash, dvar->type);
|
||||
console::info("\"%s\" is: \"%s\" default: \"%s\" checksum: 0x%08lX type: %i\n",
|
||||
args[0], current, reset, dvar->checksum, dvar->type);
|
||||
|
||||
const auto dvar_info = dvars::dvar_get_description(dvar);
|
||||
|
||||
@ -134,16 +150,23 @@ namespace command
|
||||
|
||||
void client_println(int client_num, const std::string& text)
|
||||
{
|
||||
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
||||
utils::string::va("f \"%s\"", text.data()));
|
||||
if (game::Com_GameMode_GetActiveGameMode() == game::GAME_TYPE_SP)
|
||||
{
|
||||
game::CG_Utils_GameMessage(client_num, text.data(), 0); // why is nothing printed?
|
||||
}
|
||||
else
|
||||
{
|
||||
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
||||
utils::string::va("f \"%s\"", text.data()));
|
||||
}
|
||||
}
|
||||
|
||||
bool check_cheats(int client_num)
|
||||
bool cheats_ok(int client_num)
|
||||
{
|
||||
const auto sv_cheats = game::Dvar_FindVar("sv_cheats");
|
||||
if (!sv_cheats || !sv_cheats->current.enabled)
|
||||
{
|
||||
client_println(client_num, "Cheats are not enabled on this server");
|
||||
client_println(client_num, "GAME_CHEATSNOTENABLED");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -289,7 +312,8 @@ namespace command
|
||||
void post_unpack() override
|
||||
{
|
||||
utils::hook::jump(0xBB1DC0_b, dvar_command_stub, true);
|
||||
client_command_hook.create(0xB105D0_b, &client_command);
|
||||
//client_command_mp_hook.create(0xB105D0_b, &client_command_mp);
|
||||
//client_command_sp_hook.create(0x483130_b, &client_command_sp);
|
||||
|
||||
add_commands();
|
||||
}
|
||||
@ -302,6 +326,76 @@ namespace command
|
||||
{
|
||||
*reinterpret_cast<int*>(1) = 0;
|
||||
});
|
||||
|
||||
add("god", []()
|
||||
{
|
||||
if (!game::SV_Loaded())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
game::g_entities[0].flags ^= 1;
|
||||
client_println(0,
|
||||
game::g_entities[0].flags & 1
|
||||
? "GAME_GODMODE_ON"
|
||||
: "GAME_GODMODE_OFF");
|
||||
});
|
||||
|
||||
add("demigod", []()
|
||||
{
|
||||
if (!game::SV_Loaded())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
game::g_entities[0].flags ^= 2;
|
||||
client_println(0,
|
||||
game::g_entities[0].flags & 2
|
||||
? "GAME_DEMI_GODMODE_ON"
|
||||
: "GAME_DEMI_GODMODE_OFF");
|
||||
});
|
||||
|
||||
add("notarget", []()
|
||||
{
|
||||
if (!game::SV_Loaded())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
game::g_entities[0].flags ^= 4;
|
||||
client_println(0,
|
||||
game::g_entities[0].flags & 4
|
||||
? "GAME_NOTARGETON"
|
||||
: "GAME_NOTARGETOFF");
|
||||
});
|
||||
|
||||
add("noclip", []()
|
||||
{
|
||||
if (!game::SV_Loaded())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
game::g_entities[0].client->flags ^= 1;
|
||||
client_println(0,
|
||||
game::g_entities[0].client->flags & 1
|
||||
? "GAME_NOCLIPON"
|
||||
: "GAME_NOCLIPOFF");
|
||||
});
|
||||
|
||||
add("ufo", []()
|
||||
{
|
||||
if (!game::SV_Loaded())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
game::g_entities[0].client->flags ^= 1;
|
||||
client_println(0,
|
||||
game::g_entities[0].client->flags & 1
|
||||
? "GAME_UFOON"
|
||||
: "GAME_UFOOFF");
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -36,7 +36,6 @@ namespace dvars
|
||||
|
||||
struct dvar_vector3 : dvar_base
|
||||
{
|
||||
|
||||
float x{};
|
||||
float y{};
|
||||
float z{};
|
||||
@ -93,22 +92,10 @@ namespace dvars
|
||||
}
|
||||
|
||||
utils::hook::detour dvar_register_new_hook;
|
||||
game::dvar_t* dvar_register_new_internal(const char* name, int hash, game::dvar_type type, unsigned int flags,
|
||||
game::dvar_value* value, game::dvar_limits* domain, bool level, const char* description)
|
||||
game::dvar_t* dvar_register_new(const char* name, unsigned int checksum, game::DvarType type, unsigned int flags,
|
||||
game::DvarValue* value, game::DvarLimits* domain, char level, const char* description)
|
||||
{
|
||||
auto* dvar = dvar_register_new_hook.invoke<game::dvar_t*>(name, hash, type, flags, value, domain, level, description);
|
||||
|
||||
if (dvar)
|
||||
{
|
||||
if (name)
|
||||
{
|
||||
dvars::dvar_set_name(dvar, name);
|
||||
}
|
||||
if (description)
|
||||
{
|
||||
dvars::dvar_set_description(dvar, description);
|
||||
}
|
||||
}
|
||||
auto* dvar = dvar_register_new_hook.invoke<game::dvar_t*>(name, checksum, type, flags, value, domain, level, description);
|
||||
|
||||
if (dvar && name && dvar_on_register_function_map.find(name) != dvar_on_register_function_map.end())
|
||||
{
|
||||
@ -119,11 +106,13 @@ namespace dvars
|
||||
return dvar;
|
||||
}
|
||||
|
||||
utils::hook::detour dvar_reregister_hook;
|
||||
void dvar_reregister(game::dvar_t* dvar, const char* name, game::dvar_type type, unsigned int flags,
|
||||
game::dvar_value* value, game::dvar_limits* domain, bool level, const char* description)
|
||||
std::recursive_mutex register_var_lock;
|
||||
utils::hook::detour dvar_register_variant_hook;
|
||||
game::dvar_t* dvar_register_variant(const char* name, unsigned int checksum, game::DvarType type, unsigned int flags,
|
||||
game::DvarValue* value, game::DvarLimits* domain, const char* description)
|
||||
{
|
||||
dvar_reregister_hook.invoke<game::dvar_t*>(dvar, name, type, flags, value, domain, level, description);
|
||||
std::lock_guard<std::recursive_mutex> $(register_var_lock);
|
||||
auto* dvar = dvar_register_variant_hook.invoke<game::dvar_t*>(name, checksum, type, flags, value, domain, description);
|
||||
|
||||
if (dvar)
|
||||
{
|
||||
@ -136,6 +125,8 @@ namespace dvars
|
||||
dvars::dvar_set_description(dvar, description);
|
||||
}
|
||||
}
|
||||
|
||||
return dvar;
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
@ -143,9 +134,13 @@ namespace dvars
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
// the post_unpack happens too late for some dvars...
|
||||
dvar_register_new_hook.create(0xCEBA60_b, dvar_register_new_internal);
|
||||
dvar_reregister_hook.create(0xCEC210_b, dvar_reregister);
|
||||
dvar_register_new_hook.create(0xCEBA60_b, dvar_register_new);
|
||||
dvar_register_variant_hook.create(0xCEBDD0_b, dvar_register_variant);
|
||||
}
|
||||
|
||||
int priority() override
|
||||
{
|
||||
return COMPONENT_MAX_PRIORITY - 1;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -159,4 +159,4 @@ namespace exception
|
||||
};
|
||||
}
|
||||
|
||||
//REGISTER_COMPONENT(exception::component)
|
||||
REGISTER_COMPONENT(exception::component)
|
@ -75,7 +75,7 @@ namespace fastfiles
|
||||
void post_unpack() override
|
||||
{
|
||||
db_try_load_x_file_internal_hook.create(0x3BBC40_b, db_try_load_x_file_internal_stub);
|
||||
#if defined(DEBUG) and defined (XFILE_DEBUG)
|
||||
#if defined(DEBUG) and defined(XFILE_DEBUG)
|
||||
db_init_load_x_file_hook.create(0x9E8D10_b, db_init_load_x_file_stub);
|
||||
#else
|
||||
db_load_x_zone_hook.create(0x3BA920_b, db_load_x_zone_stub);
|
||||
|
@ -278,8 +278,17 @@ namespace game_console
|
||||
if (matches.size() > 24)
|
||||
{
|
||||
draw_hint_box(1, dvars::con_inputHintBoxColor->current.vector);
|
||||
draw_hint_text(0, utils::string::va("%i matches (too many to show here)", matches.size()),
|
||||
draw_hint_text(0, utils::string::va("%i matches (too many to show here). Press SHIFT + TAB to show more", matches.size()),
|
||||
dvars::con_inputDvarMatchColor->current.vector);
|
||||
|
||||
if (game::playerKeys[0].keys[game::keyNum_t::K_SHIFT].down && game::playerKeys[0].keys[game::keyNum_t::K_TAB].down)
|
||||
{
|
||||
console::info("]%s\n", con.buffer);
|
||||
for (size_t i = 0; i < matches.size(); i++)
|
||||
{
|
||||
console::info("\t%s\n", matches[i].data());
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (matches.size() == 1)
|
||||
{
|
||||
@ -304,7 +313,7 @@ namespace game_console
|
||||
color_white, 0);
|
||||
|
||||
const auto offset_y = height + 3.f;
|
||||
const auto line_count_ = dvar->type == game::dvar_type::enumeration
|
||||
const auto line_count_ = dvar->type == game::DvarType::enumeration
|
||||
? dvar->domain.enumeration.stringCount + 1
|
||||
: 1;
|
||||
|
||||
@ -334,11 +343,15 @@ namespace game_console
|
||||
|
||||
if (dvar)
|
||||
{
|
||||
draw_hint_text(static_cast<int>(i), game::Dvar_ValueToString(dvar, dvar->current),
|
||||
const auto value = game::Dvar_ValueToString(dvar, dvar->current);
|
||||
draw_hint_text(static_cast<int>(i), value,
|
||||
dvars::con_inputDvarValueColor->current.vector, offset_value);
|
||||
|
||||
draw_hint_text(static_cast<int>(i), dvars::dvar_get_description(dvar).data(),
|
||||
dvars::con_inputDvarValueColor->current.vector, offset_description);
|
||||
if (strlen(value) < 0x18)
|
||||
{
|
||||
draw_hint_text(static_cast<int>(i), dvars::dvar_get_description(dvar).data(),
|
||||
dvars::con_inputDvarValueColor->current.vector, offset_description);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -554,7 +567,7 @@ namespace game_console
|
||||
return false;
|
||||
}
|
||||
|
||||
if (key < 32)
|
||||
if (key < ' ')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
74
src/client/component/renderer.cpp
Normal file
74
src/client/component/renderer.cpp
Normal file
@ -0,0 +1,74 @@
|
||||
#include <std_include.hpp>
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
#include "dvars.hpp"
|
||||
|
||||
#include "game/game.hpp"
|
||||
#include "game/dvars.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
namespace renderer
|
||||
{
|
||||
namespace
|
||||
{
|
||||
utils::hook::detour r_init_draw_method_hook;
|
||||
utils::hook::detour r_update_front_end_dvar_options_hook;
|
||||
|
||||
int get_fullbright_technique()
|
||||
{
|
||||
switch (dvars::r_fullbright->current.integer)
|
||||
{
|
||||
case 2:
|
||||
return game::TECHNIQUE_LIT;
|
||||
default:
|
||||
return game::TECHNIQUE_UNLIT;
|
||||
}
|
||||
}
|
||||
|
||||
void gfxdrawmethod()
|
||||
{
|
||||
game::gfxDrawMethod->drawScene = game::GFX_DRAW_SCENE_STANDARD;
|
||||
game::gfxDrawMethod->baseTechType = dvars::r_fullbright->current.integer ? get_fullbright_technique() : game::TECHNIQUE_LIT;
|
||||
game::gfxDrawMethod->emissiveTechType = dvars::r_fullbright->current.integer ? get_fullbright_technique() : game::TECHNIQUE_EMISSIVE;
|
||||
game::gfxDrawMethod->forceTechType = dvars::r_fullbright->current.integer ? get_fullbright_technique() : game::TECHNIQUE_LIT;
|
||||
}
|
||||
|
||||
void r_init_draw_method_stub()
|
||||
{
|
||||
gfxdrawmethod();
|
||||
}
|
||||
|
||||
bool r_update_front_end_dvar_options_stub()
|
||||
{
|
||||
if (dvars::r_fullbright->modified)
|
||||
{
|
||||
game::Dvar_ClearModified(dvars::r_fullbright);
|
||||
game::R_SyncRenderThread();
|
||||
|
||||
gfxdrawmethod();
|
||||
}
|
||||
|
||||
return r_update_front_end_dvar_options_hook.invoke<bool>();
|
||||
}
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
{
|
||||
public:
|
||||
void post_unpack() override
|
||||
{
|
||||
if (game::environment::is_dedi())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
dvars::r_fullbright = game::Dvar_RegisterInt("r_fullbright", 0, 0, 2, game::DVAR_FLAG_SAVED, "Toggles rendering without lighting");
|
||||
|
||||
r_init_draw_method_hook.create(0xDE9260_b, &r_init_draw_method_stub);
|
||||
r_update_front_end_dvar_options_hook.create(0xE28B60_b, &r_update_front_end_dvar_options_stub);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
REGISTER_COMPONENT(renderer::component)
|
@ -56,7 +56,6 @@ namespace system_check
|
||||
|
||||
static std::unordered_map<std::string, std::string> sp_zone_hashes =
|
||||
{
|
||||
// Steam doesn't necessarily deliver this file :(
|
||||
{"patch_common.ff", "A427FDFBFCF16B0BA662459383C48AE15C884B9B44C61C12B98E062FBC4C6DB3"},
|
||||
};
|
||||
|
||||
|
@ -19,7 +19,11 @@ namespace dvars
|
||||
game::dvar_t* con_inputDvarInactiveValueColor = nullptr;
|
||||
game::dvar_t* con_inputCmdMatchColor = nullptr;
|
||||
|
||||
std::string dvar_get_vector_domain(const int components, const game::dvar_limits& domain)
|
||||
game::dvar_t* branding = nullptr;
|
||||
|
||||
game::dvar_t* r_fullbright = nullptr;
|
||||
|
||||
std::string dvar_get_vector_domain(const int components, const game::DvarLimits& domain)
|
||||
{
|
||||
if (domain.vector.min == -FLT_MAX)
|
||||
{
|
||||
@ -45,16 +49,16 @@ namespace dvars
|
||||
}
|
||||
}
|
||||
|
||||
std::string dvar_get_domain(const game::dvar_type type, const game::dvar_limits& domain)
|
||||
std::string dvar_get_domain(const game::DvarType type, const game::DvarLimits& domain)
|
||||
{
|
||||
std::string str;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case game::dvar_type::boolean:
|
||||
case game::DvarType::boolean:
|
||||
return "Domain is 0 or 1"s;
|
||||
|
||||
case game::dvar_type::value:
|
||||
case game::DvarType::value:
|
||||
if (domain.value.min == -FLT_MAX)
|
||||
{
|
||||
if (domain.value.max == FLT_MAX)
|
||||
@ -75,17 +79,17 @@ namespace dvars
|
||||
return utils::string::va("Domain is any number from %g to %g", domain.value.min, domain.value.max);
|
||||
}
|
||||
|
||||
case game::dvar_type::vec2:
|
||||
case game::DvarType::vec2:
|
||||
return dvar_get_vector_domain(2, domain);
|
||||
|
||||
case game::dvar_type::rgb:
|
||||
case game::dvar_type::vec3:
|
||||
case game::DvarType::rgb:
|
||||
case game::DvarType::vec3:
|
||||
return dvar_get_vector_domain(3, domain);
|
||||
|
||||
case game::dvar_type::vec4:
|
||||
case game::DvarType::vec4:
|
||||
return dvar_get_vector_domain(4, domain);
|
||||
|
||||
case game::dvar_type::integer:
|
||||
case game::DvarType::integer:
|
||||
if (domain.enumeration.stringCount == INT_MIN)
|
||||
{
|
||||
if (domain.integer.max == INT_MAX)
|
||||
@ -106,10 +110,10 @@ namespace dvars
|
||||
return utils::string::va("Domain is any integer from %i to %i", domain.integer.min, domain.integer.max);
|
||||
}
|
||||
|
||||
case game::dvar_type::color:
|
||||
case game::DvarType::color:
|
||||
return "Domain is any 4-component color, in RGBA format"s;
|
||||
|
||||
case game::dvar_type::enumeration:
|
||||
case game::DvarType::enumeration:
|
||||
str = "Domain is one of the following:"s;
|
||||
|
||||
for (auto string_index = 0; string_index < domain.enumeration.stringCount; ++string_index)
|
||||
@ -119,7 +123,7 @@ namespace dvars
|
||||
|
||||
return str;
|
||||
|
||||
case game::dvar_type::string:
|
||||
case game::DvarType::string:
|
||||
return "Domain is any text"s;
|
||||
|
||||
default:
|
||||
|
@ -15,8 +15,12 @@ namespace dvars
|
||||
extern game::dvar_t* con_inputDvarInactiveValueColor;
|
||||
extern game::dvar_t* con_inputCmdMatchColor;
|
||||
|
||||
std::string dvar_get_vector_domain(const int components, const game::dvar_limits& domain);
|
||||
std::string dvar_get_domain(const game::dvar_type type, const game::dvar_limits& domain);
|
||||
extern game::dvar_t* branding;
|
||||
|
||||
extern game::dvar_t* r_fullbright;
|
||||
|
||||
std::string dvar_get_vector_domain(const int components, const game::DvarLimits& domain);
|
||||
std::string dvar_get_domain(const game::DvarType type, const game::DvarLimits& domain);
|
||||
std::string dvar_get_name(const game::dvar_t* dvar);
|
||||
std::string dvar_get_description(const game::dvar_t* dvar);
|
||||
void dvar_set_name(const game::dvar_t* dvar, const std::string& name);
|
||||
|
@ -33,11 +33,6 @@ namespace game
|
||||
return sv_cmd_args->argv[sv_cmd_args->nesting][index];
|
||||
}
|
||||
|
||||
bool VirtualLobby_Loaded()
|
||||
{
|
||||
return 0; //return *mp::virtualLobby_loaded == 1;
|
||||
}
|
||||
|
||||
const char* g_assetNames[ASSET_TYPE_COUNT] =
|
||||
{
|
||||
"physicslibrary",
|
||||
@ -81,13 +76,13 @@ namespace game
|
||||
"attachment",
|
||||
"weapon",
|
||||
"vfx",
|
||||
"impactfx", // not confirmed
|
||||
"surfacefx", // not confirmed
|
||||
"aitype", // not confirmed
|
||||
"mptype", // not confirmed
|
||||
"character", // not confirmed
|
||||
"xmodelalias", // not confirmed
|
||||
"ASSET_TYPE_UNKNOWN", // not confirmed
|
||||
"impactfx",
|
||||
"surfacefx",
|
||||
"aitype",
|
||||
"mptype",
|
||||
"character",
|
||||
"xmodelalias",
|
||||
"ASSET_TYPE_UNKNOWN",
|
||||
"rawfile",
|
||||
"scriptfile",
|
||||
"stringtable",
|
||||
|
@ -48,8 +48,6 @@ namespace game
|
||||
int SV_Cmd_Argc();
|
||||
const char* SV_Cmd_Argv(int index);
|
||||
|
||||
bool VirtualLobby_Loaded();
|
||||
|
||||
extern const char* g_assetNames[ASSET_TYPE_COUNT];
|
||||
const char* DB_GetXAssetName(const XAsset* asset);
|
||||
void DB_EnumXAssets(const std::int32_t type, const std::function<void(XAssetHeader)>& callback);
|
||||
|
@ -14,6 +14,14 @@ namespace game
|
||||
{
|
||||
};
|
||||
|
||||
enum GameModeType : std::uint32_t
|
||||
{
|
||||
GAME_TYPE_NONE = 0x0,
|
||||
GAME_TYPE_SP = 0x1,
|
||||
GAME_TYPE_MP = 0x2,
|
||||
GAME_TYPE_CP = 0x3,
|
||||
};
|
||||
|
||||
struct CmdArgs
|
||||
{
|
||||
int nesting;
|
||||
@ -51,8 +59,20 @@ namespace game
|
||||
DVAR_FLAG_READ = 0x2000,
|
||||
};
|
||||
|
||||
enum dvar_type : std::int8_t
|
||||
enum DvarType : std::uint8_t
|
||||
{
|
||||
DVAR_TYPE_BOOL = 0x0,
|
||||
DVAR_TYPE_FLOAT = 0x1,
|
||||
DVAR_TYPE_FLOAT_2 = 0x2,
|
||||
DVAR_TYPE_FLOAT_3 = 0x3,
|
||||
DVAR_TYPE_FLOAT_4 = 0x4,
|
||||
DVAR_TYPE_INT = 0x5,
|
||||
DVAR_TYPE_ENUM = 0x6,
|
||||
DVAR_TYPE_STRING = 0x7,
|
||||
DVAR_TYPE_COLOR = 0x8,
|
||||
DVAR_TYPE_FLOAT_3_COLOR = 0x9,
|
||||
DVAR_TYPE_COUNT = 0xA,
|
||||
|
||||
boolean = 0,
|
||||
value = 1,
|
||||
vec2 = 2,
|
||||
@ -62,10 +82,10 @@ namespace game
|
||||
enumeration = 6,
|
||||
string = 7,
|
||||
color = 8,
|
||||
rgb = 9 // Color without alpha
|
||||
rgb = 9, // Color without alpha
|
||||
};
|
||||
|
||||
union dvar_value
|
||||
union DvarValue
|
||||
{
|
||||
bool enabled;
|
||||
int integer;
|
||||
@ -94,7 +114,7 @@ namespace game
|
||||
float max;
|
||||
};
|
||||
|
||||
union dvar_limits
|
||||
union DvarLimits
|
||||
{
|
||||
$A37BA207B3DDD6345C554D4661813EDD enumeration;
|
||||
$9CA192F9DB66A3CB7E01DE78A0DEA53D integer;
|
||||
@ -104,17 +124,17 @@ namespace game
|
||||
|
||||
struct dvar_t
|
||||
{
|
||||
int hash; // 0
|
||||
unsigned int flags; // 4
|
||||
bool unk; // 8 tls value?
|
||||
dvar_type type; // 9
|
||||
bool modified; // 10
|
||||
dvar_value current; // 16
|
||||
dvar_value latched; // 32
|
||||
dvar_value reset; // 48
|
||||
dvar_limits domain; // 64
|
||||
char unk2; // 80 always 0?
|
||||
void* unk3; // 88 some pointer related to hash?
|
||||
unsigned int checksum;
|
||||
unsigned int flags;
|
||||
char level;
|
||||
DvarType type;
|
||||
bool modified;
|
||||
DvarValue current;
|
||||
DvarValue latched;
|
||||
DvarValue reset;
|
||||
DvarLimits domain;
|
||||
bool(__fastcall* domainFunc)(dvar_t*, DvarValue);
|
||||
dvar_t* hashNext;
|
||||
}; static_assert(sizeof(dvar_t) == 96);
|
||||
|
||||
enum svscmd_type
|
||||
@ -271,7 +291,7 @@ namespace game
|
||||
int down;
|
||||
int unk;
|
||||
int repeats;
|
||||
int unk2;
|
||||
int binding;
|
||||
};
|
||||
|
||||
struct field_t
|
||||
@ -438,13 +458,13 @@ namespace game
|
||||
ASSET_TYPE_ATTACHMENT = 38,
|
||||
ASSET_TYPE_WEAPON = 39,
|
||||
ASSET_TYPE_VFX = 40,
|
||||
ASSET_TYPE_IMPACT_FX = 41, // not confirmed
|
||||
ASSET_TYPE_SURFACE_FX = 42, // not confirmed
|
||||
ASSET_TYPE_AITYPE = 43, // not confirmed + unused
|
||||
ASSET_TYPE_MPTYPE = 44, // not confirmed + unused
|
||||
ASSET_TYPE_CHARACTER = 45, // not confirmed + unused
|
||||
ASSET_TYPE_XMODELALIAS = 46, // not confirmed + unused
|
||||
ASSET_TYPE_UNKNOWN = 47, // not confirmed + unused
|
||||
ASSET_TYPE_IMPACT_FX = 41,
|
||||
ASSET_TYPE_SURFACE_FX = 42,
|
||||
ASSET_TYPE_AITYPE = 43, // unused
|
||||
ASSET_TYPE_MPTYPE = 44, // unused
|
||||
ASSET_TYPE_CHARACTER = 45, // unused
|
||||
ASSET_TYPE_XMODELALIAS = 46, // unused
|
||||
ASSET_TYPE_UNKNOWN = 47, // unused
|
||||
ASSET_TYPE_RAWFILE = 48,
|
||||
ASSET_TYPE_SCRIPTFILE = 49,
|
||||
ASSET_TYPE_STRINGTABLE = 50,
|
||||
@ -1468,6 +1488,26 @@ namespace game
|
||||
TTFDef* ttfDef;
|
||||
};
|
||||
|
||||
enum MaterialTechniqueType
|
||||
{
|
||||
TECHNIQUE_UNLIT = 8,
|
||||
TECHNIQUE_EMISSIVE = 10,
|
||||
TECHNIQUE_LIT = 13,
|
||||
};
|
||||
|
||||
enum GfxDrawSceneMethod
|
||||
{
|
||||
GFX_DRAW_SCENE_STANDARD = 0x1,
|
||||
};
|
||||
|
||||
struct GfxDrawMethod
|
||||
{
|
||||
int drawScene;
|
||||
int baseTechType;
|
||||
int emissiveTechType;
|
||||
int forceTechType;
|
||||
};
|
||||
|
||||
namespace demonware
|
||||
{
|
||||
enum DWOnlineStatus
|
||||
|
@ -10,9 +10,15 @@ namespace game
|
||||
|
||||
WEAK symbol<void()> Com_Quit_f{ 0xBADC90 };
|
||||
|
||||
WEAK symbol<bool()> Com_FrontEndScene_IsActive{ 0x5AEBA0 };
|
||||
|
||||
WEAK symbol<GameModeType()> Com_GameMode_GetActiveGameMode{ 0x5AFD50 };
|
||||
|
||||
WEAK symbol<void(int localClientNum, const char* text)> Cbuf_AddText{ 0xB7C290 };
|
||||
WEAK symbol<void(int localClientNum, void(*))> Cbuf_AddCall{ 0xB7C220 };
|
||||
|
||||
WEAK symbol<void(int localClientNum, const char* msg, int flags)> CG_Utils_GameMessage{ 0x1D7FC0 };
|
||||
|
||||
WEAK symbol<void(int localClientNum, int controllerIndex, const char* text)> Cmd_ExecuteSingleCommand{ 0xB7D040 };
|
||||
WEAK symbol<void(const char* cmdName, void(), cmd_function_s* allocedCmd)> Cmd_AddCommandInternal{ 0xB7C8F0 };
|
||||
WEAK symbol<void(const char* cmdName)> Cmd_RemoveCommand{ 0xB7D630 };
|
||||
@ -41,12 +47,17 @@ namespace game
|
||||
|
||||
WEAK symbol<void(const char* name, const char* string)> Dvar_SetCommand{ 0xCECB30 };
|
||||
WEAK symbol<dvar_t* (const char* name)> Dvar_FindVar{ 0xCEA460 };
|
||||
WEAK symbol<void(const dvar_t* dvar)> Dvar_ClearModified{ 0xCE9E90 };
|
||||
WEAK symbol<void(char* buffer, int index)> Dvar_GetCombinedString{ 0xBB1F30 };
|
||||
WEAK symbol<const char* (dvar_t* dvar, dvar_value value)> Dvar_ValueToString{ 0xCEED00 };
|
||||
WEAK symbol<const char* (dvar_t* dvar, DvarValue value)> Dvar_ValueToString{ 0xCEED00 };
|
||||
WEAK symbol<int(const char* name)> Dvar_GenerateChecksum{ 0xCEA520 };
|
||||
#define Dvar_GenerateHash(name) \
|
||||
Dvar_GenerateChecksum(name);
|
||||
|
||||
WEAK symbol<const char* (int, int, int)> Key_KeynumToString{ 0x9A95E0 };
|
||||
|
||||
WEAK symbol<bool()> LUI_CoD_InFrontEnd{ 0x615080 };
|
||||
|
||||
WEAK symbol<unsigned int(int controllerIndex)> Live_SyncOnlineDataFlags{ 0xDC5CE0 };
|
||||
|
||||
WEAK symbol<Material* (const char* material)> Material_RegisterHandle{ 0xE11CE0 };
|
||||
@ -82,6 +93,9 @@ namespace game
|
||||
WEAK symbol<CmdArgs> sv_cmd_args{ 0x5D65C20 };
|
||||
WEAK symbol<CmdArgs> cmd_args{ 0x5D65B70 };
|
||||
WEAK symbol<cmd_function_s*> cmd_functions{ 0x5D65CC8 };
|
||||
WEAK symbol<const char*> command_whitelist{ 0x14D1B70 };
|
||||
|
||||
WEAK symbol<GfxDrawMethod> gfxDrawMethod{ 0x83E86A8 };
|
||||
|
||||
WEAK symbol<int> keyCatchers{ 0x2246C34 };
|
||||
WEAK symbol<PlayerKeyState> playerKeys{ 0x523BA0C };
|
||||
|
@ -32,4 +32,9 @@ public:
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual int priority()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
@ -1,8 +1,12 @@
|
||||
#include <std_include.hpp>
|
||||
#include "component_loader.hpp"
|
||||
|
||||
void component_loader::register_component(std::unique_ptr<component_interface>&& component_)
|
||||
void component_loader::register_component(std::unique_ptr<component_interface>&& component_, [[maybe_unused]] const std::string& name)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("registering component: %s\n", name.data());
|
||||
#endif
|
||||
|
||||
get_components().push_back(std::move(component_));
|
||||
}
|
||||
|
||||
@ -33,8 +37,6 @@ bool component_loader::post_load()
|
||||
if (handled) return true;
|
||||
handled = true;
|
||||
|
||||
clean();
|
||||
|
||||
try
|
||||
{
|
||||
for (const auto& component_ : get_components())
|
||||
@ -65,7 +67,7 @@ void component_loader::post_unpack()
|
||||
catch (std::exception& e)
|
||||
{
|
||||
MessageBoxA(nullptr, e.what(), "ERROR", MB_ICONERROR);
|
||||
quick_exit(-1);
|
||||
quick_exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -78,7 +80,15 @@ void component_loader::pre_destroy()
|
||||
|
||||
for (const auto& component_ : get_components())
|
||||
{
|
||||
component_->pre_destroy();
|
||||
try
|
||||
{
|
||||
component_->pre_destroy();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
MessageBoxA(nullptr, e.what(), "ERROR", MB_ICONERROR);
|
||||
quick_exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,6 +109,17 @@ void component_loader::clean()
|
||||
}
|
||||
}
|
||||
|
||||
void component_loader::sort()
|
||||
{
|
||||
auto& components = get_components();
|
||||
|
||||
std::ranges::stable_sort(components, [](const std::unique_ptr<component_interface>& a,
|
||||
const std::unique_ptr<component_interface>& b)
|
||||
{
|
||||
return a->priority() > b->priority();
|
||||
});
|
||||
}
|
||||
|
||||
void* component_loader::load_import(const std::string& library, const std::string& function)
|
||||
{
|
||||
void* function_ptr = nullptr;
|
||||
|
@ -1,6 +1,8 @@
|
||||
#pragma once
|
||||
#include "component_interface.hpp"
|
||||
|
||||
#define COMPONENT_MAX_PRIORITY 999
|
||||
|
||||
class component_loader final
|
||||
{
|
||||
public:
|
||||
@ -22,6 +24,17 @@ public:
|
||||
{
|
||||
register_component(std::make_unique<T>());
|
||||
}
|
||||
|
||||
installer(const std::string& component_name)
|
||||
{
|
||||
register_component(
|
||||
std::make_unique<T>(),
|
||||
std::string(
|
||||
component_name.begin(),
|
||||
component_name.begin() + component_name.find("::")
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@ -38,13 +51,14 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void register_component(std::unique_ptr<component_interface>&& component);
|
||||
static void register_component(std::unique_ptr<component_interface>&& component, const std::string& name = "(unnamed)");
|
||||
|
||||
static bool post_start();
|
||||
static bool post_load();
|
||||
static void post_unpack();
|
||||
static void pre_destroy();
|
||||
static void clean();
|
||||
static void sort();
|
||||
|
||||
static void* load_import(const std::string& library, const std::string& function);
|
||||
|
||||
@ -54,8 +68,9 @@ private:
|
||||
static std::vector<std::unique_ptr<component_interface>>& get_components();
|
||||
};
|
||||
|
||||
#define REGISTER_COMPONENT(name) \
|
||||
namespace \
|
||||
{ \
|
||||
static component_loader::installer<name> __component; \
|
||||
#define REGISTER_COMPONENT(name) \
|
||||
namespace \
|
||||
{ \
|
||||
static component_loader::installer<name> __component = component_loader::installer<name>(#name); \
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,8 @@ FARPROC load_binary(uint64_t* base_address)
|
||||
}
|
||||
else if (function == "SystemParametersInfoA")
|
||||
{
|
||||
return system_parameters_info_a;
|
||||
// post_unpack called from SteamAPI_Init
|
||||
//return system_parameters_info_a;
|
||||
}
|
||||
|
||||
return component_loader::load_import(library, function);
|
||||
@ -118,6 +119,9 @@ int main()
|
||||
remove_crash_file();
|
||||
|
||||
{
|
||||
component_loader::sort();
|
||||
component_loader::clean();
|
||||
|
||||
auto premature_shutdown = true;
|
||||
const auto _ = gsl::finally([&premature_shutdown]()
|
||||
{
|
||||
@ -129,7 +133,7 @@ int main()
|
||||
|
||||
try
|
||||
{
|
||||
if (!component_loader::post_start()) return 0;
|
||||
if (!component_loader::post_start()) return EXIT_FAILURE;
|
||||
|
||||
uint64_t base_address{};
|
||||
entry_point = load_binary(&base_address);
|
||||
@ -146,14 +150,14 @@ int main()
|
||||
}
|
||||
game::base_address = base_address;
|
||||
|
||||
if (!component_loader::post_load()) return 0;
|
||||
if (!component_loader::post_load()) return EXIT_FAILURE;
|
||||
|
||||
premature_shutdown = false;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
MessageBoxA(nullptr, e.what(), "ERROR", MB_ICONERROR);
|
||||
return 1;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,3 +101,5 @@
|
||||
#include "resource.hpp"
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
#define __FILENAME__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
#include <utils/nt.hpp>
|
||||
|
||||
#include "loader/component_loader.hpp"
|
||||
|
||||
namespace steam
|
||||
{
|
||||
uint64_t callbacks::call_id_ = 0;
|
||||
@ -111,12 +113,14 @@ namespace steam
|
||||
bool SteamAPI_Init()
|
||||
{
|
||||
const std::filesystem::path steam_path = steam::SteamAPI_GetSteamInstallPath();
|
||||
if (steam_path.empty()) return true;
|
||||
if (steam_path.empty()) return false;
|
||||
|
||||
::utils::nt::library::load(steam_path / "tier0_s64.dll");
|
||||
::utils::nt::library::load(steam_path / "vstdlib_s64.dll");
|
||||
::utils::nt::library::load(steam_path / "gameoverlayrenderer64.dll");
|
||||
::utils::nt::library::load(steam_path / "steamclient64.dll");
|
||||
|
||||
component_loader::post_unpack();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user