stuff
Console improvement & printing s1 command system"needs work"
This commit is contained in:
parent
a326a70a7f
commit
1b91a2deac
@ -1,13 +1,10 @@
|
|||||||
#include <std_include.hpp>
|
#include <std_include.hpp>
|
||||||
#include "loader/component_loader.hpp"
|
#include "loader/component_loader.hpp"
|
||||||
|
|
||||||
#include "game/game.hpp"
|
|
||||||
#include "game/dvars.hpp"
|
|
||||||
|
|
||||||
#include "command.hpp"
|
#include "command.hpp"
|
||||||
#include "console.hpp"
|
#include "console.hpp"
|
||||||
#include "game_console.hpp"
|
#include "game_console.hpp"
|
||||||
|
|
||||||
|
#include "game/game.hpp"
|
||||||
|
|
||||||
#include <utils/hook.hpp>
|
#include <utils/hook.hpp>
|
||||||
#include <utils/string.hpp>
|
#include <utils/string.hpp>
|
||||||
@ -18,10 +15,9 @@ namespace command
|
|||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
utils::hook::detour dvar_command_hook;
|
utils::hook::detour client_command_hook;
|
||||||
|
|
||||||
std::unordered_map<std::string, std::function<void(params&)>> handlers;
|
std::unordered_map<std::string, std::function<void(params&)>> handlers;
|
||||||
|
|
||||||
std::unordered_map<std::string, std::function<void(int, params_sv&)>> handlers_sv;
|
std::unordered_map<std::string, std::function<void(int, params_sv&)>> handlers_sv;
|
||||||
|
|
||||||
void main_handler()
|
void main_handler()
|
||||||
@ -45,53 +41,78 @@ namespace command
|
|||||||
handlers_sv[command](client_num, params);
|
handlers_sv[command](client_num, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
dvar_command_hook.invoke<void>(client_num, a2);
|
client_command_hook.invoke<void>(client_num, a2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void enum_assets(const game::XAssetType type, const std::function<void(game::XAssetHeader)>& callback, const bool includeOverride)
|
// Shamelessly stolen from Quake3
|
||||||
|
// https://github.com/id-Software/Quake-III-Arena/blob/dbe4ddb10315479fc00086f08e25d968b4b43c49/code/qcommon/common.c#L364
|
||||||
|
void parse_command_line()
|
||||||
{
|
{
|
||||||
game::DB_EnumXAssets_Internal(type, static_cast<void(*)(game::XAssetHeader, void*)>([](game::XAssetHeader header, void* data)
|
static auto parsed = false;
|
||||||
{
|
if (parsed)
|
||||||
const auto& cb = *static_cast<const std::function<void(game::XAssetHeader)>*>(data);
|
|
||||||
cb(header);
|
|
||||||
}), &callback, includeOverride);
|
|
||||||
}
|
|
||||||
|
|
||||||
game::dvar_t* dvar_command_stub()
|
|
||||||
{
|
|
||||||
const params args;
|
|
||||||
|
|
||||||
if (args.size() <= 0)
|
|
||||||
{
|
{
|
||||||
return 0;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto dvar = game::Dvar_FindVar(args[0]);
|
static std::string comand_line_buffer = GetCommandLineA();
|
||||||
|
auto* command_line = comand_line_buffer.data();
|
||||||
|
|
||||||
if (dvar)
|
auto& com_num_console_lines = *reinterpret_cast<int*>(0x142623FB4); //H1(1.4)
|
||||||
|
auto* com_console_lines = reinterpret_cast<char**>(0x142623FC0); //H1(1.4)
|
||||||
|
|
||||||
|
auto inq = false;
|
||||||
|
com_console_lines[0] = command_line;
|
||||||
|
com_num_console_lines = 0;
|
||||||
|
|
||||||
|
while (*command_line)
|
||||||
{
|
{
|
||||||
if (args.size() == 1)
|
if (*command_line == '"')
|
||||||
{
|
{
|
||||||
const auto current = game::Dvar_ValueToString(dvar, dvar->current, 0);
|
inq = !inq;
|
||||||
const auto reset = game::Dvar_ValueToString(dvar, dvar->reset, 0);
|
|
||||||
|
|
||||||
game_console::print(game_console::con_type_info, "\"%s\" is: \"%s\" default: \"%s\" hash: %i",
|
|
||||||
args[0], current, reset, dvar->hash);
|
|
||||||
|
|
||||||
game_console::print(game_console::con_type_info, " %s\n",
|
|
||||||
dvars::dvar_get_domain(dvar->type, dvar->domain).data());
|
|
||||||
}
|
}
|
||||||
//else
|
// look for a + separating character
|
||||||
//{
|
// if commandLine came from a file, we might have real line seperators
|
||||||
// char command[0x1000] = { 0 };
|
if ((*command_line == '+' && !inq) || *command_line == '\n' || *command_line == '\r')
|
||||||
// game::Dvar_GetCombinedString(command, 1);
|
{
|
||||||
// game::Dvar_SetCommand(dvar->name, command);
|
if (com_num_console_lines == 0x20) // MAX_CONSOLE_LINES
|
||||||
//}
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
com_console_lines[com_num_console_lines] = command_line + 1;
|
||||||
|
com_num_console_lines++;
|
||||||
|
*command_line = '\0';
|
||||||
|
}
|
||||||
|
command_line++;
|
||||||
|
}
|
||||||
|
parsed = true;
|
||||||
|
}
|
||||||
|
|
||||||
return dvar;
|
void parse_commandline_stub()
|
||||||
|
{
|
||||||
|
parse_command_line();
|
||||||
|
reinterpret_cast<void(*)()>(0x1400D8210)(); // mwr: test
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_startup_variable(const std::string& dvar)
|
||||||
|
{
|
||||||
|
// parse the commandline if it's not parsed
|
||||||
|
parse_command_line();
|
||||||
|
|
||||||
|
auto& com_num_console_lines = *reinterpret_cast<int*>(0x142623FB4); //H1(1.4)
|
||||||
|
auto* com_console_lines = reinterpret_cast<char**>(0x142623FC0); //H1(1.4)
|
||||||
|
|
||||||
|
for (int i = 0; i < com_num_console_lines; i++)
|
||||||
|
{
|
||||||
|
game::Cmd_TokenizeString(com_console_lines[i]);
|
||||||
|
|
||||||
|
// only +set dvar value
|
||||||
|
if (game::Cmd_Argc() >= 3 && game::Cmd_Argv(0) == "set"s && game::Cmd_Argv(1) == dvar)
|
||||||
|
{
|
||||||
|
game::Dvar_SetCommand(game::Cmd_Argv(1), game::Cmd_Argv(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
game::Cmd_EndTokenizeString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,8 +185,16 @@ namespace command
|
|||||||
game::Cmd_AddCommandInternal(name, callback, utils::memory::get_allocator()->allocate<game::cmd_function_s>());
|
game::Cmd_AddCommandInternal(name, callback, utils::memory::get_allocator()->allocate<game::cmd_function_s>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void add_test(const char* name, void (*callback)())
|
||||||
|
{
|
||||||
|
static game::cmd_function_s cmd_test;
|
||||||
|
return game::Cmd_AddCommandInternal(name, callback, &cmd_test);
|
||||||
|
}
|
||||||
|
|
||||||
void add(const char* name, const std::function<void(const params&)>& callback)
|
void add(const char* name, const std::function<void(const params&)>& callback)
|
||||||
{
|
{
|
||||||
|
static game::cmd_function_s cmd_test;
|
||||||
|
|
||||||
const auto command = utils::string::to_lower(name);
|
const auto command = utils::string::to_lower(name);
|
||||||
|
|
||||||
if (handlers.find(command) == handlers.end())
|
if (handlers.find(command) == handlers.end())
|
||||||
@ -207,73 +236,13 @@ namespace command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_command_line()
|
void enum_assets(const game::XAssetType type, const std::function<void(game::XAssetHeader)>& callback, const bool includeOverride)
|
||||||
{
|
{
|
||||||
static auto parsed = false;
|
game::DB_EnumXAssets_Internal(type, static_cast<void(*)(game::XAssetHeader, void*)>([](game::XAssetHeader header, void* data)
|
||||||
if (parsed)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string comand_line_buffer = GetCommandLineA();
|
|
||||||
auto* command_line = comand_line_buffer.data();
|
|
||||||
|
|
||||||
auto& com_num_console_lines = *reinterpret_cast<int*>(0x142623FB4);
|
|
||||||
auto* com_console_lines = reinterpret_cast<char**>(0x142623FC0);
|
|
||||||
|
|
||||||
auto inq = false;
|
|
||||||
com_console_lines[0] = command_line;
|
|
||||||
com_num_console_lines = 0;
|
|
||||||
|
|
||||||
while (*command_line)
|
|
||||||
{
|
|
||||||
if (*command_line == '"')
|
|
||||||
{
|
{
|
||||||
inq = !inq;
|
const auto& cb = *static_cast<const std::function<void(game::XAssetHeader)>*>(data);
|
||||||
}
|
cb(header);
|
||||||
// look for a + separating character
|
}), &callback, includeOverride);
|
||||||
// if commandLine came from a file, we might have real line seperators
|
|
||||||
if ((*command_line == '+' && !inq) || *command_line == '\n' || *command_line == '\r')
|
|
||||||
{
|
|
||||||
if (com_num_console_lines == 0x20) // MAX_CONSOLE_LINES
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
com_console_lines[com_num_console_lines] = command_line + 1;
|
|
||||||
com_num_console_lines++;
|
|
||||||
*command_line = '\0';
|
|
||||||
}
|
|
||||||
command_line++;
|
|
||||||
}
|
|
||||||
parsed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void parse_commandline_stub()
|
|
||||||
{
|
|
||||||
parse_command_line();
|
|
||||||
reinterpret_cast<void(*)()>(0x1400D8210)(); // mwr: test
|
|
||||||
}
|
|
||||||
|
|
||||||
void read_startup_variable(const std::string& dvar)
|
|
||||||
{
|
|
||||||
// parse the commandline if it's not parsed
|
|
||||||
parse_command_line();
|
|
||||||
|
|
||||||
auto& com_num_console_lines = *reinterpret_cast<int*>(0x142623FB4);
|
|
||||||
auto* com_console_lines = reinterpret_cast<char**>(0x142623FC0);
|
|
||||||
|
|
||||||
for (int i = 0; i < com_num_console_lines; i++)
|
|
||||||
{
|
|
||||||
game::Cmd_TokenizeString(com_console_lines[i]);
|
|
||||||
|
|
||||||
// only +set dvar value
|
|
||||||
if (game::Cmd_Argc() >= 3 && game::Cmd_Argv(0) == "set"s && game::Cmd_Argv(1) == dvar)
|
|
||||||
{
|
|
||||||
game::Dvar_SetCommand(game::Cmd_Argv(1), game::Cmd_Argv(2));
|
|
||||||
}
|
|
||||||
|
|
||||||
game::Cmd_EndTokenizeString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class component final : public component_interface
|
class component final : public component_interface
|
||||||
@ -281,138 +250,447 @@ namespace command
|
|||||||
public:
|
public:
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
//utils::hook::jump(game::base_address + 0x000000, dvar_command_stub, true); // H1
|
if (game::environment::is_sp())
|
||||||
|
|
||||||
static game::cmd_function_s cmd_test;
|
|
||||||
|
|
||||||
game::Cmd_AddCommandInternal("quit", game::Com_Quit_f, &cmd_test);
|
|
||||||
/*game::Cmd_AddCommandInternal("connect", []() {
|
|
||||||
|
|
||||||
}, game::cmd_function_s);*/
|
|
||||||
//add_raw("quit", main_handler);
|
|
||||||
|
|
||||||
//add("quit", game::Com_Quit_f);
|
|
||||||
|
|
||||||
//add("startmap", [](const params& params)
|
|
||||||
//{
|
|
||||||
// const auto map = params.get(1);
|
|
||||||
|
|
||||||
// const auto exists = utils::hook::invoke<bool>(game::base_address + 0x412B50, map, 0);
|
|
||||||
|
|
||||||
// if (!exists)
|
|
||||||
// {
|
|
||||||
// game_console::print(game_console::con_type_error, "map '%s' not found\n", map);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // SV_SpawnServer
|
|
||||||
// utils::hook::invoke<void>(game::base_address + 0x6B3AA0, map, 0, 0, 0, 0);
|
|
||||||
//});
|
|
||||||
|
|
||||||
/*add("say", [](const params& params)
|
|
||||||
{
|
{
|
||||||
chat::print(params.join(1));
|
add_commands_sp();
|
||||||
});*/
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
utils::hook::call(0x1400D728F, &parse_commandline_stub); // MWR TEST
|
||||||
|
|
||||||
//add("listassetpool", [](const params& params)
|
add_commands_mp();
|
||||||
//{
|
}
|
||||||
// if (params.size() < 2)
|
add_commands_generic();
|
||||||
// {
|
}
|
||||||
// game_console::print(game_console::con_type_info, "listassetpool <poolnumber>: list all the assets in the specified pool\n");
|
|
||||||
|
|
||||||
// for (auto i = 0; i < game::XAssetType::ASSET_TYPE_COUNT; i++)
|
private:
|
||||||
// {
|
static void add_commands_generic()
|
||||||
// game_console::print(game_console::con_type_info, "%d %s\n", i, game::g_assetNames[i]);
|
{
|
||||||
// }
|
add_test("quit", game::Com_Quit_f);
|
||||||
// }
|
add("quit_hard", utils::nt::raise_hard_exception);
|
||||||
// else
|
add("crash", []()
|
||||||
// {
|
{
|
||||||
// const auto type = static_cast<game::XAssetType>(atoi(params.get(1)));
|
*reinterpret_cast<int*>(1) = 0;
|
||||||
|
});
|
||||||
|
|
||||||
// if (type < 0 || type >= game::XAssetType::ASSET_TYPE_COUNT)
|
/*add("consoleList", [](const params& params)
|
||||||
// {
|
{
|
||||||
// game_console::print(game_console::con_type_info, "Invalid pool passed must be between [%d, %d]\n", 0, game::XAssetType::ASSET_TYPE_COUNT - 1);
|
const std::string input = params.get(1);
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// game_console::print(game_console::con_type_info, "Listing assets in pool %s\n", game::g_assetNames[type]);
|
std::vector<std::string> matches;
|
||||||
|
game_console::find_matches(input, matches, false);
|
||||||
|
|
||||||
// enum_assets(type, [type](const game::XAssetHeader header)
|
for (auto& match : matches)
|
||||||
// {
|
{
|
||||||
// const auto asset = game::XAsset{type, header};
|
auto* dvar = game::Dvar_FindVar(match.c_str());
|
||||||
// const auto* const asset_name = game::DB_GetXAssetName(&asset);
|
if (!dvar)
|
||||||
// //const auto entry = game::DB_FindXAssetEntry(type, asset_name);
|
{
|
||||||
// //TODO: display which zone the asset is from
|
console::info("[CMD]\t %s\n", match.c_str());
|
||||||
// game_console::print(game_console::con_type_info, "%s\n", asset_name);
|
}
|
||||||
// }, true);
|
else
|
||||||
// }
|
{
|
||||||
//});
|
console::info("[DVAR]\t%s \"%s\"\n", match.c_str(), game::Dvar_ValueToString(dvar, dvar->current, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//add("commandDump", []()
|
console::info("Total %i matches\n", matches.size());
|
||||||
//{
|
});
|
||||||
// printf("======== Start command dump =========\n");
|
|
||||||
|
|
||||||
// game::cmd_function_s* cmd = (*game::cmd_functions);
|
add("dvarDump", [](const params& argument)
|
||||||
|
{
|
||||||
|
console::info("================================ DVAR DUMP ========================================\n");
|
||||||
|
std::string filename;
|
||||||
|
if (argument.size() == 2)
|
||||||
|
{
|
||||||
|
filename = "s1x/";
|
||||||
|
filename.append(argument[1]);
|
||||||
|
if (!filename.ends_with(".txt"))
|
||||||
|
{
|
||||||
|
filename.append(".txt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto i = 0; i < *game::dvarCount; i++)
|
||||||
|
{
|
||||||
|
const auto dvar = game::sortedDvars[i];
|
||||||
|
if (dvar)
|
||||||
|
{
|
||||||
|
if (!filename.empty())
|
||||||
|
{
|
||||||
|
const auto line = std::format("{} \"{}\"\r\n", dvar->hash,
|
||||||
|
game::Dvar_ValueToString(dvar, dvar->current, 0));
|
||||||
|
utils::io::write_file(filename, line, i != 0);
|
||||||
|
}
|
||||||
|
console::info("%s \"%s\"\n", dvar->hash,
|
||||||
|
game::Dvar_ValueToString(dvar, dvar->current, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console::info("\n%i dvars\n", *game::dvarCount);
|
||||||
|
console::info("================================ END DVAR DUMP ====================================\n");
|
||||||
|
});
|
||||||
|
|
||||||
// while (cmd)
|
add("commandDump", [](const params& argument)
|
||||||
// {
|
{
|
||||||
// if (cmd->name)
|
console::info("================================ COMMAND DUMP =====================================\n");
|
||||||
// {
|
game::cmd_function_s* cmd = (*game::cmd_functions);
|
||||||
// game_console::print(game_console::con_type_info, "%s\n", cmd->name);
|
std::string filename;
|
||||||
// }
|
if (argument.size() == 2)
|
||||||
|
{
|
||||||
|
filename = "s1x/";
|
||||||
|
filename.append(argument[1]);
|
||||||
|
if (!filename.ends_with(".txt"))
|
||||||
|
{
|
||||||
|
filename.append(".txt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int i = 0;
|
||||||
|
while (cmd)
|
||||||
|
{
|
||||||
|
if (cmd->name)
|
||||||
|
{
|
||||||
|
if (!filename.empty())
|
||||||
|
{
|
||||||
|
const auto line = std::format("{}\r\n", cmd->name);
|
||||||
|
utils::io::write_file(filename, line, i != 0);
|
||||||
|
}
|
||||||
|
console::info("%s\n", cmd->name);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
cmd = cmd->next;
|
||||||
|
}
|
||||||
|
console::info("\n%i commands\n", i);
|
||||||
|
console::info("================================ END COMMAND DUMP =================================\n");
|
||||||
|
});
|
||||||
|
|
||||||
// cmd = cmd->next;
|
add("listassetpool", [](const params& params)
|
||||||
// }
|
{
|
||||||
|
if (params.size() < 2)
|
||||||
|
{
|
||||||
|
console::info("listassetpool <poolnumber> [filter]: list all the assets in the specified pool\n");
|
||||||
|
|
||||||
// printf("======== End command dump =========\n");
|
for (auto i = 0; i < game::XAssetType::ASSET_TYPE_COUNT; i++)
|
||||||
//});
|
{
|
||||||
|
console::info("%d %s\n", i, game::g_assetNames[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto type = static_cast<game::XAssetType>(atoi(params.get(1)));
|
||||||
|
|
||||||
|
if (type < 0 || type >= game::XAssetType::ASSET_TYPE_COUNT)
|
||||||
|
{
|
||||||
|
console::error("Invalid pool passed must be between [%d, %d]\n", 0, game::XAssetType::ASSET_TYPE_COUNT - 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*add("god", []()
|
console::info("Listing assets in pool %s\n", game::g_assetNames[type]);
|
||||||
|
|
||||||
|
const std::string filter = params.get(2);
|
||||||
|
enum_assets(type, [type, filter](const game::XAssetHeader header)
|
||||||
|
{
|
||||||
|
const auto asset = game::XAsset{ type, header };
|
||||||
|
const auto* const asset_name = game::DB_GetXAssetName(&asset);
|
||||||
|
//const auto entry = game::DB_FindXAssetEntry(type, asset_name);
|
||||||
|
//TODO: display which zone the asset is from
|
||||||
|
|
||||||
|
if (!filter.empty() && !game_console::match_compare(filter, asset_name, false))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
console::info("%s\n", asset_name);
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
add("vstr", [](const params& params)
|
||||||
|
{
|
||||||
|
if (params.size() < 2)
|
||||||
|
{
|
||||||
|
console::info("vstr <variablename> : execute a variable command\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto* dvarName = params.get(1);
|
||||||
|
const auto* dvar = game::Dvar_FindVar(dvarName);
|
||||||
|
|
||||||
|
if (dvar == nullptr)
|
||||||
|
{
|
||||||
|
console::info("%s doesn't exist\n", dvarName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dvar->type != game::dvar_type::string
|
||||||
|
&& dvar->type != game::dvar_type::enumeration)
|
||||||
|
{
|
||||||
|
console::info("%s is not a string-based dvar\n", dvar->hash);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
execute(dvar->current.string);
|
||||||
|
});*/
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_commands_sp()
|
||||||
|
{
|
||||||
|
add("god", []()
|
||||||
{
|
{
|
||||||
if (!game::SV_Loaded())
|
if (!game::SV_Loaded())
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
game::mp::g_entities[0].flags ^= game::FL_GODMODE;
|
game::sp::g_entities[0].flags ^= 1;
|
||||||
game::CG_GameMessage(0, utils::string::va("godmode %s",
|
game::CG_GameMessage(0, utils::string::va("godmode %s",
|
||||||
game::g_entities[0].flags & game::FL_GODMODE
|
game::sp::g_entities[0].flags & 1
|
||||||
? "^2on"
|
? "^2on"
|
||||||
: "^1off"));
|
: "^1off"));
|
||||||
|
});
|
||||||
|
|
||||||
|
/*add("demigod", []()
|
||||||
|
{
|
||||||
|
if (!game::SV_Loaded())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
game::sp::g_entities[0].flags ^= 2;
|
||||||
|
game::CG_GameMessage(0, utils::string::va("demigod mode %s",
|
||||||
|
game::sp::g_entities[0].flags & 2
|
||||||
|
? "^2on"
|
||||||
|
: "^1off"));
|
||||||
|
});
|
||||||
|
|
||||||
|
add("notarget", []()
|
||||||
|
{
|
||||||
|
if (!game::SV_Loaded())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
game::sp::g_entities[0].flags ^= 4;
|
||||||
|
game::CG_GameMessage(0, utils::string::va("notarget %s",
|
||||||
|
game::sp::g_entities[0].flags & 4
|
||||||
|
? "^2on"
|
||||||
|
: "^1off"));
|
||||||
|
});
|
||||||
|
|
||||||
|
add("noclip", []()
|
||||||
|
{
|
||||||
|
if (!game::SV_Loaded())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
game::sp::g_entities[0].client->flags ^= 1;
|
||||||
|
game::CG_GameMessage(0, utils::string::va("noclip %s",
|
||||||
|
game::sp::g_entities[0].client->flags & 1
|
||||||
|
? "^2on"
|
||||||
|
: "^1off"));
|
||||||
|
});
|
||||||
|
|
||||||
|
add("ufo", []()
|
||||||
|
{
|
||||||
|
if (!game::SV_Loaded())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
game::sp::g_entities[0].client->flags ^= 2;
|
||||||
|
game::CG_GameMessage(0, utils::string::va("ufo %s",
|
||||||
|
game::sp::g_entities[0].client->flags & 2
|
||||||
|
? "^2on"
|
||||||
|
: "^1off"));
|
||||||
|
});
|
||||||
|
|
||||||
|
add("give", [](const params& params)
|
||||||
|
{
|
||||||
|
if (!game::SV_Loaded())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.size() < 2)
|
||||||
|
{
|
||||||
|
game::CG_GameMessage(0, "You did not specify a weapon name");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ps = game::SV_GetPlayerstateForClientNum(0);
|
||||||
|
const auto wp = game::G_GetWeaponForName(params.get(1));
|
||||||
|
if (wp)
|
||||||
|
{
|
||||||
|
if (game::G_GivePlayerWeapon(ps, wp, 0, 0, 0, 0, 0, 0))
|
||||||
|
{
|
||||||
|
game::G_InitializeAmmo(ps, wp, 0);
|
||||||
|
game::G_SelectWeapon(0, wp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
add("take", [](const params& params)
|
||||||
|
{
|
||||||
|
if (!game::SV_Loaded())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.size() < 2)
|
||||||
|
{
|
||||||
|
game::CG_GameMessage(0, "You did not specify a weapon name");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ps = game::SV_GetPlayerstateForClientNum(0);
|
||||||
|
const auto wp = game::G_GetWeaponForName(params.get(1));
|
||||||
|
if (wp)
|
||||||
|
{
|
||||||
|
game::G_TakePlayerWeapon(ps, wp);
|
||||||
|
}
|
||||||
});*/
|
});*/
|
||||||
|
}
|
||||||
|
|
||||||
|
static void add_commands_mp()
|
||||||
|
{
|
||||||
|
//client_command_hook.create(0x1402E98F0, &client_command);
|
||||||
|
|
||||||
|
/*add_sv("god", [](const int client_num, const params_sv&)
|
||||||
|
{
|
||||||
|
if (!game::Dvar_FindVar("sv_cheats")->current.enabled)
|
||||||
|
{
|
||||||
|
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
||||||
|
"f \"Cheats are not enabled on this server\"");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//add("notarget", []()
|
game::mp::g_entities[client_num].flags ^= 1;
|
||||||
//{
|
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
||||||
// if (!game::SV_Loaded())
|
utils::string::va("f \"godmode %s\"",
|
||||||
// {
|
game::mp::g_entities[client_num].flags & 1
|
||||||
// return;
|
? "^2on"
|
||||||
// }
|
: "^1off"));
|
||||||
|
});
|
||||||
|
|
||||||
// game::g_entities[0].flags ^= game::FL_NOTARGET;
|
add_sv("demigod", [](const int client_num, const params_sv&)
|
||||||
// game::CG_GameMessage(0, utils::string::va("notarget %s",
|
{
|
||||||
// game::g_entities[0].flags & game::FL_NOTARGET
|
if (!game::Dvar_FindVar("sv_cheats")->current.enabled)
|
||||||
// ? "^2on"
|
{
|
||||||
// : "^1off"));
|
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
||||||
//});
|
"f \"Cheats are not enabled on this server\"");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//add("noclip", []()
|
game::mp::g_entities[client_num].flags ^= 2;
|
||||||
//{
|
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
||||||
// if (!game::SV_Loaded())
|
utils::string::va("f \"demigod mode %s\"",
|
||||||
// {
|
game::mp::g_entities[client_num].flags & 2
|
||||||
// return;
|
? "^2on"
|
||||||
// }
|
: "^1off"));
|
||||||
|
});
|
||||||
|
|
||||||
// game::g_entities[0].client->flags ^= 1;
|
add_sv("notarget", [](const int client_num, const params_sv&)
|
||||||
// game::CG_GameMessage(0, utils::string::va("noclip %s",
|
{
|
||||||
// game::g_entities[0].client->flags & 1
|
if (!game::Dvar_FindVar("sv_cheats")->current.enabled)
|
||||||
// ? "^2on"
|
{
|
||||||
// : "^1off"));
|
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
||||||
//});
|
"f \"Cheats are not enabled on this server\"");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
game::mp::g_entities[client_num].flags ^= 4;
|
||||||
|
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
||||||
|
utils::string::va("f \"notarget %s\"",
|
||||||
|
game::mp::g_entities[client_num].flags & 4
|
||||||
|
? "^2on"
|
||||||
|
: "^1off"));
|
||||||
|
});
|
||||||
|
|
||||||
|
add_sv("noclip", [](const int client_num, const params_sv&)
|
||||||
|
{
|
||||||
|
if (!game::Dvar_FindVar("sv_cheats")->current.enabled)
|
||||||
|
{
|
||||||
|
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
||||||
|
"f \"Cheats are not enabled on this server\"");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
game::mp::g_entities[client_num].client->flags ^= 1;
|
||||||
|
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
||||||
|
utils::string::va("f \"noclip %s\"",
|
||||||
|
game::mp::g_entities[client_num].client->flags & 1
|
||||||
|
? "^2on"
|
||||||
|
: "^1off"));
|
||||||
|
});
|
||||||
|
|
||||||
|
add_sv("ufo", [](const int client_num, const params_sv&)
|
||||||
|
{
|
||||||
|
if (!game::Dvar_FindVar("sv_cheats")->current.enabled)
|
||||||
|
{
|
||||||
|
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
||||||
|
"f \"Cheats are not enabled on this server\"");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
game::mp::g_entities[client_num].client->flags ^= 2;
|
||||||
|
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
||||||
|
utils::string::va("f \"ufo %s\"",
|
||||||
|
game::mp::g_entities[client_num].client->flags & 2
|
||||||
|
? "^2on"
|
||||||
|
: "^1off"));
|
||||||
|
});
|
||||||
|
|
||||||
|
add_sv("give", [](const int client_num, const params_sv& params)
|
||||||
|
{
|
||||||
|
if (!game::Dvar_FindVar("sv_cheats")->current.enabled)
|
||||||
|
{
|
||||||
|
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
||||||
|
"f \"Cheats are not enabled on this server\"");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.size() < 2)
|
||||||
|
{
|
||||||
|
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
||||||
|
"f \"You did not specify a weapon name\"");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ps = game::SV_GetPlayerstateForClientNum(client_num);
|
||||||
|
const auto wp = game::G_GetWeaponForName(params.get(1));
|
||||||
|
if (wp)
|
||||||
|
{
|
||||||
|
if (game::G_GivePlayerWeapon(ps, wp, 0, 0, 0, 0, 0, 0))
|
||||||
|
{
|
||||||
|
game::G_InitializeAmmo(ps, wp, 0);
|
||||||
|
game::G_SelectWeapon(client_num, wp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
add_sv("take", [](const int client_num, const params_sv& params)
|
||||||
|
{
|
||||||
|
if (!game::Dvar_FindVar("sv_cheats")->current.enabled)
|
||||||
|
{
|
||||||
|
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
||||||
|
"f \"Cheats are not enabled on this server\"");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.size() < 2)
|
||||||
|
{
|
||||||
|
game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE,
|
||||||
|
"f \"You did not specify a weapon name\"");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ps = game::SV_GetPlayerstateForClientNum(client_num);
|
||||||
|
const auto wp = game::G_GetWeaponForName(params.get(1));
|
||||||
|
if (wp)
|
||||||
|
{
|
||||||
|
game::G_TakePlayerWeapon(ps, wp);
|
||||||
|
}
|
||||||
|
}); */
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
REGISTER_COMPONENT(command::component)
|
REGISTER_COMPONENT(command::component)
|
@ -46,11 +46,11 @@ namespace console
|
|||||||
|
|
||||||
void dispatch_message(const int type, const std::string& message)
|
void dispatch_message(const int type, const std::string& message)
|
||||||
{
|
{
|
||||||
/*if (rcon::message_redirect(message))
|
game_console::print(type, message);
|
||||||
{
|
messages.access([&message](message_queue& msgs)
|
||||||
return;
|
{
|
||||||
}*/
|
msgs.emplace(message);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void append_text(const char* text)
|
void append_text(const char* text)
|
||||||
@ -172,7 +172,6 @@ namespace console
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void log_messages()
|
void log_messages()
|
||||||
{
|
{
|
||||||
/*while*/
|
/*while*/
|
||||||
@ -203,10 +202,6 @@ namespace console
|
|||||||
{
|
{
|
||||||
OutputDebugStringA(message.data());
|
OutputDebugStringA(message.data());
|
||||||
game::Conbuf_AppendText(message.data());
|
game::Conbuf_AppendText(message.data());
|
||||||
FILE* pFile = fopen("debug.log", "a");
|
|
||||||
fprintf(pFile, "%s\n", message.data());
|
|
||||||
fclose(pFile);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void runner()
|
void runner()
|
||||||
|
@ -416,9 +416,13 @@ namespace demonware
|
|||||||
|
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
mwr has upgraded some networking methods and the gethostbyname import from winsock library is no longer used
|
||||||
|
gethostbyname has been replaced with getaddrinfo
|
||||||
|
btw, still you can't get online..
|
||||||
|
*/
|
||||||
utils::hook::jump(SELECT_VALUE(0x140610320, 0x1407400B0), bd_logger_stub); // H1MP64(1.4)
|
utils::hook::jump(SELECT_VALUE(0x140610320, 0x1407400B0), bd_logger_stub); // H1MP64(1.4)
|
||||||
|
|
||||||
//singleplayer not supported so far.
|
|
||||||
if (game::environment::is_sp())
|
if (game::environment::is_sp())
|
||||||
{
|
{
|
||||||
utils::hook::set<uint8_t>(0x1405FCA00, 0xC3); // bdAuthSteam H1(1.4)
|
utils::hook::set<uint8_t>(0x1405FCA00, 0xC3); // bdAuthSteam H1(1.4)
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
#include <std_include.hpp>
|
#include <std_include.hpp>
|
||||||
#include "loader/component_loader.hpp"
|
#include "loader/component_loader.hpp"
|
||||||
|
#include "game_console.hpp"
|
||||||
|
#include "command.hpp"
|
||||||
|
#include "console.hpp"
|
||||||
|
#include "scheduler.hpp"
|
||||||
|
|
||||||
#include "game/game.hpp"
|
#include "game/game.hpp"
|
||||||
#include "game/dvars.hpp"
|
#include "game/dvars.hpp"
|
||||||
|
|
||||||
#include "game_console.hpp"
|
|
||||||
#include "command.hpp"
|
|
||||||
#include "scheduler.hpp"
|
|
||||||
|
|
||||||
#include <utils/string.hpp>
|
#include <utils/string.hpp>
|
||||||
#include <utils/hook.hpp>
|
#include <utils/hook.hpp>
|
||||||
|
#include <utils/concurrency.hpp>
|
||||||
|
|
||||||
|
#include "version.hpp"
|
||||||
|
|
||||||
#define console_font game::R_RegisterFont("fonts/fira_mono_regular.ttf", 18)
|
#define console_font game::R_RegisterFont("fonts/fira_mono_regular.ttf", 18)
|
||||||
#define material_white game::Material_RegisterHandle("white")
|
#define material_white game::Material_RegisterHandle("white")
|
||||||
@ -20,66 +23,68 @@ namespace game_console
|
|||||||
{
|
{
|
||||||
struct console_globals
|
struct console_globals
|
||||||
{
|
{
|
||||||
float x;
|
float x{};
|
||||||
float y;
|
float y{};
|
||||||
float left_x;
|
float left_x{};
|
||||||
float font_height;
|
float font_height{};
|
||||||
bool may_auto_complete;
|
bool may_auto_complete{};
|
||||||
char auto_complete_choice[64];
|
char auto_complete_choice[64]{};
|
||||||
int info_line_count;
|
int info_line_count{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using output_queue = std::deque<std::string>;
|
||||||
|
|
||||||
struct ingame_console
|
struct ingame_console
|
||||||
{
|
{
|
||||||
char buffer[256];
|
char buffer[256]{};
|
||||||
int cursor;
|
int cursor{};
|
||||||
int font_height;
|
int font_height{};
|
||||||
int visible_line_count;
|
int visible_line_count{};
|
||||||
int visible_pixel_width;
|
int visible_pixel_width{};
|
||||||
float screen_min[2]; //left & top
|
float screen_min[2]{}; //left & top
|
||||||
float screen_max[2]; //right & bottom
|
float screen_max[2]{}; //right & bottom
|
||||||
console_globals globals;
|
console_globals globals{};
|
||||||
bool output_visible;
|
bool output_visible{};
|
||||||
int display_line_offset;
|
int display_line_offset{};
|
||||||
int line_count;
|
int line_count{};
|
||||||
std::deque<std::string> output;
|
utils::concurrency::container<output_queue, std::recursive_mutex> output{};
|
||||||
};
|
};
|
||||||
|
|
||||||
ingame_console con;
|
ingame_console con{};
|
||||||
|
|
||||||
std::int32_t history_index = -1;
|
std::int32_t history_index = -1;
|
||||||
std::deque<std::string> history;
|
std::deque<std::string> history{};
|
||||||
|
|
||||||
std::string fixed_input;
|
std::string fixed_input{};
|
||||||
std::vector<std::string> matches;
|
std::vector<std::string> matches{};
|
||||||
|
|
||||||
float color_white[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
float color_white[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||||
float color_title[4] = { 0.9f, 0.9f, 0.5f, 1.0f };
|
float color_title[4] = { 0.9f, 0.9f, 0.5f, 1.0f };
|
||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
strncpy_s(con.buffer, "", 256);
|
strncpy_s(con.buffer, "", sizeof(con.buffer));
|
||||||
con.cursor = 0;
|
con.cursor = 0;
|
||||||
|
|
||||||
fixed_input = "";
|
fixed_input = "";
|
||||||
matches.clear();
|
matches.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void print(const std::string& data)
|
void print_internal(const std::string& data)
|
||||||
{
|
{
|
||||||
if (con.visible_line_count > 0 && con.display_line_offset == (con.output.size() - con.visible_line_count))
|
con.output.access([&](output_queue& output)
|
||||||
{
|
{
|
||||||
con.display_line_offset++;
|
if (con.visible_line_count > 0
|
||||||
}
|
&& con.display_line_offset == (output.size() - con.visible_line_count))
|
||||||
|
{
|
||||||
con.output.push_back(data);
|
con.display_line_offset++;
|
||||||
|
}
|
||||||
printf("%s\n", data.data());
|
output.push_back(data);
|
||||||
|
if (output.size() > 512)
|
||||||
if (con.output.size() > 1024)
|
{
|
||||||
{
|
output.pop_front();
|
||||||
con.output.pop_front();
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void toggle_console()
|
void toggle_console()
|
||||||
@ -146,6 +151,8 @@ namespace game_console
|
|||||||
color);
|
color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void draw_input_text_and_over(const char* str, float* color)
|
void draw_input_text_and_over(const char* str, float* color)
|
||||||
{
|
{
|
||||||
game::R_AddCmdDrawText(str, 0x7FFFFFFF, console_font, con.globals.x,
|
game::R_AddCmdDrawText(str, 0x7FFFFFFF, console_font, con.globals.x,
|
||||||
@ -171,6 +178,7 @@ namespace game_console
|
|||||||
game::R_AddCmdDrawText(text, 0x7FFFFFFF, console_font, con.globals.x + offset, _y, 1.0f, 1.0f, 0.0f, color, 0);
|
game::R_AddCmdDrawText(text, 0x7FFFFFFF, console_font, con.globals.x + offset, _y, 1.0f, 1.0f, 0.0f, color, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool match_compare(const std::string& input, const std::string& text, const bool exact)
|
bool match_compare(const std::string& input, const std::string& text, const bool exact)
|
||||||
{
|
{
|
||||||
if (exact && text == input) return true;
|
if (exact && text == input) return true;
|
||||||
@ -230,7 +238,7 @@ namespace game_console
|
|||||||
con.globals.left_x = con.screen_min[0] + 6.0f;
|
con.globals.left_x = con.screen_min[0] + 6.0f;
|
||||||
|
|
||||||
draw_input_box(1, dvars::con_inputBoxColor->current.vector);
|
draw_input_box(1, dvars::con_inputBoxColor->current.vector);
|
||||||
draw_input_text_and_over("H1-Mod >", color_title);
|
draw_input_text_and_over("H1-Mod: " VERSION ">", color_title);
|
||||||
|
|
||||||
con.globals.left_x = con.globals.x;
|
con.globals.left_x = con.globals.x;
|
||||||
con.globals.auto_complete_choice[0] = 0;
|
con.globals.auto_complete_choice[0] = 0;
|
||||||
@ -240,8 +248,8 @@ namespace game_console
|
|||||||
con.globals.y + con.globals.font_height, 1.0f, 1.0f, 0, color_white, 0,
|
con.globals.y + con.globals.font_height, 1.0f, 1.0f, 0, color_white, 0,
|
||||||
con.cursor, '|');
|
con.cursor, '|');
|
||||||
|
|
||||||
//game::R_AddCmdDrawText(con.buffer, 0x7FFF, console_font, con.globals.x,
|
game::R_AddCmdDrawText(con.buffer, 0x7FFF, console_font, con.globals.x,
|
||||||
// con.globals.y + con.globals.font_height, 1.0f, 1.0f, 0.0f, color_white, 0);
|
con.globals.y + con.globals.font_height, 1.0f, 1.0f, 0.0f, color_white, 0);
|
||||||
|
|
||||||
|
|
||||||
// check if using a prefixed '/' or not
|
// check if using a prefixed '/' or not
|
||||||
@ -328,19 +336,19 @@ namespace game_console
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_output_scrollbar(const float x, float y, const float width, const float height)
|
void draw_output_scrollbar(const float x, float y, const float width, const float height, output_queue& output)
|
||||||
{
|
{
|
||||||
const auto _x = (x + width) - 10.0f;
|
const auto _x = (x + width) - 10.0f;
|
||||||
draw_box(_x, y, 10.0f, height, dvars::con_outputBarColor->current.vector);
|
draw_box(_x, y, 10.0f, height, dvars::con_outputBarColor->current.vector);
|
||||||
|
|
||||||
auto _height = height;
|
auto _height = height;
|
||||||
if (con.output.size() > con.visible_line_count)
|
if (output.size() > con.visible_line_count)
|
||||||
{
|
{
|
||||||
const auto percentage = static_cast<float>(con.visible_line_count) / con.output.size();
|
const auto percentage = static_cast<float>(con.visible_line_count) / output.size();
|
||||||
_height *= percentage;
|
_height *= percentage;
|
||||||
|
|
||||||
const auto remainingSpace = height - _height;
|
const auto remainingSpace = height - _height;
|
||||||
const auto percentageAbove = static_cast<float>(con.display_line_offset) / (con.output.size() - con.
|
const auto percentageAbove = static_cast<float>(con.display_line_offset) / (output.size() - con.
|
||||||
visible_line_count);
|
visible_line_count);
|
||||||
|
|
||||||
y = y + (remainingSpace * percentageAbove);
|
y = y + (remainingSpace * percentageAbove);
|
||||||
@ -349,42 +357,45 @@ namespace game_console
|
|||||||
draw_box(_x, y, 10.0f, _height, dvars::con_outputSliderColor->current.vector);
|
draw_box(_x, y, 10.0f, _height, dvars::con_outputSliderColor->current.vector);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_output_text(const float x, float y)
|
void draw_output_text(const float x, float y, output_queue& output)
|
||||||
{
|
{
|
||||||
const auto offset = con.output.size() >= con.visible_line_count
|
const auto offset = output.size() >= con.visible_line_count
|
||||||
? 0.0f
|
? 0.0f
|
||||||
: (con.font_height * (con.visible_line_count - con.output.size()));
|
: (con.font_height * (con.visible_line_count - output.size()));
|
||||||
|
|
||||||
for (auto i = 0; i < con.visible_line_count; i++)
|
for (auto i = 0; i < con.visible_line_count; i++)
|
||||||
{
|
{
|
||||||
y = console_font->pixelHeight + y;
|
y = console_font->pixelHeight + y;
|
||||||
|
|
||||||
const auto index = i + con.display_line_offset;
|
const auto index = i + con.display_line_offset;
|
||||||
if (index >= con.output.size())
|
if (index >= output.size())
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
game::R_AddCmdDrawText(con.output.at(index).data(), 0x7FFF, console_font, x, y + offset, 1.0f, 1.0f,
|
game::R_AddCmdDrawText(output.at(index).data(), 0x7FFF, console_font, x, y + offset, 1.0f, 1.0f,
|
||||||
0.0f, color_white, 0);
|
0.0f, color_white, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_output_window()
|
void draw_output_window()
|
||||||
{
|
{
|
||||||
draw_box(con.screen_min[0], con.screen_min[1] + 32.0f, con.screen_max[0] - con.screen_min[0],
|
con.output.access([](output_queue& output)
|
||||||
(con.screen_max[1] - con.screen_min[1]) - 32.0f, dvars::con_outputWindowColor->current.vector);
|
{
|
||||||
|
draw_box(con.screen_min[0], con.screen_min[1] + 32.0f, con.screen_max[0] - con.screen_min[0],
|
||||||
|
(con.screen_max[1] - con.screen_min[1]) - 32.0f, dvars::con_outputWindowColor->current.vector);
|
||||||
|
|
||||||
const auto x = con.screen_min[0] + 6.0f;
|
const auto x = con.screen_min[0] + 6.0f;
|
||||||
const auto y = (con.screen_min[1] + 32.0f) + 6.0f;
|
const auto y = (con.screen_min[1] + 32.0f) + 6.0f;
|
||||||
const auto width = (con.screen_max[0] - con.screen_min[0]) - 12.0f;
|
const auto width = (con.screen_max[0] - con.screen_min[0]) - 12.0f;
|
||||||
const auto height = ((con.screen_max[1] - con.screen_min[1]) - 32.0f) - 12.0f;
|
const auto height = ((con.screen_max[1] - con.screen_min[1]) - 32.0f) - 12.0f;
|
||||||
|
|
||||||
game::R_AddCmdDrawText("H1-Mod 1.4", 0x7FFFFFFF, console_font, x,
|
game::R_AddCmdDrawText("H1-Mod 1.4", 0x7FFFFFFF, console_font, x,
|
||||||
((height - 16.0f) + y) + console_font->pixelHeight, 1.0f, 1.0f, 0.0f, color_title, 0);
|
((height - 16.0f) + y) + console_font->pixelHeight, 1.0f, 1.0f, 0.0f, color_title, 0);
|
||||||
|
|
||||||
draw_output_scrollbar(x, y, width, height);
|
draw_output_scrollbar(x, y, width, height, output);
|
||||||
draw_output_text(x, y);
|
draw_output_text(x, y, output);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_console()
|
void draw_console()
|
||||||
@ -408,7 +419,7 @@ namespace game_console
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void print(const int type, const char* fmt, ...)
|
void print_internal(const char* fmt, ...)
|
||||||
{
|
{
|
||||||
char va_buffer[0x200] = { 0 };
|
char va_buffer[0x200] = { 0 };
|
||||||
|
|
||||||
@ -420,22 +431,38 @@ namespace game_console
|
|||||||
const auto formatted = std::string(va_buffer);
|
const auto formatted = std::string(va_buffer);
|
||||||
const auto lines = utils::string::split(formatted, '\n');
|
const auto lines = utils::string::split(formatted, '\n');
|
||||||
|
|
||||||
for (auto& line : lines)
|
for (const auto& line : lines)
|
||||||
{
|
{
|
||||||
print(type == con_type_info ? line : "^"s.append(std::to_string(type)).append(line));
|
print_internal(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool console_char_event(const int localClientNum, const int key)
|
void print(const int type, const std::string& data)
|
||||||
{
|
{
|
||||||
if (key == '`' || key == '~' || key == '|' || key == '\\')
|
try
|
||||||
{
|
{
|
||||||
return false;
|
if (game::environment::is_dedi())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (std::exception&)
|
||||||
|
{
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key > 127)
|
const auto lines = utils::string::split(data, '\n');
|
||||||
|
for (const auto& line : lines)
|
||||||
{
|
{
|
||||||
return true;
|
print_internal(type == console::con_type_info ? line : "^"s.append(std::to_string(type)).append(line));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool console_char_event(const int local_client_num, const int key)
|
||||||
|
{
|
||||||
|
if (key == game::keyNum_t::K_GRAVE || key == game::keyNum_t::K_TILDE)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*game::keyCatchers & 1)
|
if (*game::keyCatchers & 1)
|
||||||
@ -444,13 +471,13 @@ namespace game_console
|
|||||||
{
|
{
|
||||||
if (con.globals.may_auto_complete)
|
if (con.globals.may_auto_complete)
|
||||||
{
|
{
|
||||||
const auto firstChar = con.buffer[0];
|
const auto first_char = con.buffer[0];
|
||||||
|
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
if (firstChar == '\\' || firstChar == '/')
|
if (first_char == '\\' || first_char == '/')
|
||||||
{
|
{
|
||||||
con.buffer[0] = firstChar;
|
con.buffer[0] = first_char;
|
||||||
con.buffer[1] = '\0';
|
con.buffer[1] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -473,9 +500,9 @@ namespace game_console
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto i = 0; i < clipboard.length(); i++)
|
for (size_t i = 0; i < clipboard.length(); i++)
|
||||||
{
|
{
|
||||||
console_char_event(localClientNum, clipboard[i]);
|
console_char_event(local_client_num, clipboard[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@ -485,7 +512,11 @@ namespace game_console
|
|||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
con.line_count = 0;
|
con.line_count = 0;
|
||||||
con.output.clear();
|
con.display_line_offset = 0;
|
||||||
|
con.output.access([](output_queue& output)
|
||||||
|
{
|
||||||
|
output.clear();
|
||||||
|
});
|
||||||
history_index = -1;
|
history_index = -1;
|
||||||
history.clear();
|
history.clear();
|
||||||
|
|
||||||
@ -527,13 +558,18 @@ namespace game_console
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute(const char* cmd)
|
bool console_key_event(const int local_client_num, const int key, const int down)
|
||||||
{
|
{
|
||||||
game::Cbuf_AddText(0, utils::string::va("%s \n", cmd));
|
if (key == game::keyNum_t::K_F10)
|
||||||
}
|
{
|
||||||
|
if (game::mp::svs_clients[local_client_num].header.state >= 1)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
game::Cmd_ExecuteSingleCommand(local_client_num, 0, "lui_open menu_systemlink_join\n");
|
||||||
|
}
|
||||||
|
|
||||||
bool console_key_event(const int localClientNum, const int key, const int down)
|
|
||||||
{
|
|
||||||
if (key == game::keyNum_t::K_GRAVE || key == game::keyNum_t::K_TILDE)
|
if (key == game::keyNum_t::K_GRAVE || key == game::keyNum_t::K_TILDE)
|
||||||
{
|
{
|
||||||
if (!down)
|
if (!down)
|
||||||
@ -541,7 +577,7 @@ namespace game_console
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (game::playerKeys[localClientNum].keys[game::keyNum_t::K_SHIFT].down)
|
if (game::playerKeys[local_client_num].keys[game::keyNum_t::K_SHIFT].down)
|
||||||
{
|
{
|
||||||
if (!(*game::keyCatchers & 1))
|
if (!(*game::keyCatchers & 1))
|
||||||
toggle_console();
|
toggle_console();
|
||||||
@ -613,24 +649,29 @@ namespace game_console
|
|||||||
//scroll through output
|
//scroll through output
|
||||||
if (key == game::keyNum_t::K_MWHEELUP || key == game::keyNum_t::K_PGUP)
|
if (key == game::keyNum_t::K_MWHEELUP || key == game::keyNum_t::K_PGUP)
|
||||||
{
|
{
|
||||||
if (con.output.size() > con.visible_line_count && con.display_line_offset > 0)
|
con.output.access([](output_queue& output)
|
||||||
{
|
{
|
||||||
con.display_line_offset--;
|
if (output.size() > con.visible_line_count && con.display_line_offset > 0)
|
||||||
}
|
{
|
||||||
|
con.display_line_offset--;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else if (key == game::keyNum_t::K_MWHEELDOWN || key == game::keyNum_t::K_PGDN)
|
else if (key == game::keyNum_t::K_MWHEELDOWN || key == game::keyNum_t::K_PGDN)
|
||||||
{
|
{
|
||||||
if (con.output.size() > con.visible_line_count && con.display_line_offset < (con.output.size() -
|
con.output.access([](output_queue& output)
|
||||||
con.
|
{
|
||||||
visible_line_count))
|
if (output.size() > con.visible_line_count
|
||||||
{
|
&& con.display_line_offset < (output.size() - con.visible_line_count))
|
||||||
con.display_line_offset++;
|
{
|
||||||
}
|
con.display_line_offset++;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key == game::keyNum_t::K_ENTER)
|
if (key == game::keyNum_t::K_ENTER)
|
||||||
{
|
{
|
||||||
execute(fixed_input.data());
|
game::Cbuf_AddText(0, utils::string::va("%s \n", fixed_input.data()));
|
||||||
|
|
||||||
if (history_index != -1)
|
if (history_index != -1)
|
||||||
{
|
{
|
||||||
@ -644,7 +685,7 @@ namespace game_console
|
|||||||
|
|
||||||
history.push_front(con.buffer);
|
history.push_front(con.buffer);
|
||||||
|
|
||||||
print(""s.append(con.buffer));
|
console::info("]%s\n", con.buffer);
|
||||||
|
|
||||||
if (history.size() > 10)
|
if (history.size() > 10)
|
||||||
{
|
{
|
||||||
@ -661,13 +702,31 @@ namespace game_console
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class component final : public component_interface
|
class component final : public component_interface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
void post_load() override
|
||||||
|
{
|
||||||
|
if (game::environment::is_dedi())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//scheduler::loop(draw_console, scheduler::pipeline::renderer);
|
||||||
|
}
|
||||||
|
|
||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
scheduler::loop(draw_console, scheduler::pipeline::renderer);
|
scheduler::loop(draw_console, scheduler::pipeline::renderer);
|
||||||
|
|
||||||
|
|
||||||
|
if (game::environment::is_dedi())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// initialize our structs
|
||||||
con.cursor = 0;
|
con.cursor = 0;
|
||||||
con.visible_line_count = 0;
|
con.visible_line_count = 0;
|
||||||
con.output_visible = false;
|
con.output_visible = false;
|
||||||
@ -683,70 +742,49 @@ namespace game_console
|
|||||||
con.globals.info_line_count = 0;
|
con.globals.info_line_count = 0;
|
||||||
strncpy_s(con.globals.auto_complete_choice, "", 64);
|
strncpy_s(con.globals.auto_complete_choice, "", 64);
|
||||||
|
|
||||||
// //add clear command
|
// add clear command
|
||||||
//command::add("clear", [&]()
|
command::add("clear", [&]()
|
||||||
//{
|
{
|
||||||
//clear();
|
clear();
|
||||||
//con.line_count = 0;
|
con.line_count = 0;
|
||||||
//con.output.clear();
|
con.display_line_offset = 0;
|
||||||
//history_index = -1;
|
con.output.access([](output_queue& output)
|
||||||
//history.clear();
|
{
|
||||||
//});
|
output.clear();
|
||||||
|
});
|
||||||
|
history_index = -1;
|
||||||
|
history.clear();
|
||||||
|
});
|
||||||
|
|
||||||
// add our dvars
|
// add our dvars
|
||||||
dvars::con_inputBoxColor = dvars::register_vec4(
|
dvars::con_inputBoxColor = dvars::register_vec4("con_inputBoxColor", 0.2f, 0.2f, 0.2f, 0.9f, 0.0f, 1.0f,
|
||||||
"con_inputBoxColor",
|
game::DVAR_FLAG_SAVED,
|
||||||
0.2f, 0.2f, 0.2f, 0.9f,
|
"color of console input box");
|
||||||
|
dvars::con_inputHintBoxColor = dvars::register_vec4("con_inputHintBoxColor", 0.3f, 0.3f, 0.3f, 1.0f,
|
||||||
0.0f, 1.0f,
|
0.0f, 1.0f,
|
||||||
game::DVAR_FLAG_SAVED);
|
game::DVAR_FLAG_SAVED, "color of console input hint box");
|
||||||
|
dvars::con_outputBarColor = dvars::register_vec4("con_outputBarColor", 0.5f, 0.5f, 0.5f, 0.6f, 0.0f,
|
||||||
dvars::con_inputHintBoxColor = dvars::register_vec4(
|
1.0f, game::DVAR_FLAG_SAVED,
|
||||||
"con_inputHintBoxColor",
|
"color of console output bar");
|
||||||
0.3f, 0.3f, 0.3f, 1.0f,
|
dvars::con_outputSliderColor = dvars::register_vec4("con_outputSliderColor", 1.0f, 0.8f, 0.0f, 1.0f,
|
||||||
0.0f, 1.0f,
|
0.0f, 1.0f,
|
||||||
game::DVAR_FLAG_SAVED);
|
game::DVAR_FLAG_SAVED, "color of console output slider");
|
||||||
|
dvars::con_outputWindowColor = dvars::register_vec4("con_outputWindowColor", 0.25f, 0.25f, 0.25f, 0.85f,
|
||||||
dvars::con_outputBarColor = dvars::register_vec4(
|
0.0f,
|
||||||
"con_outputBarColor",
|
1.0f, game::DVAR_FLAG_SAVED, "color of console output window");
|
||||||
0.5f, 0.5f, 0.5f, 0.6f,
|
dvars::con_inputDvarMatchColor = dvars::register_vec4("con_inputDvarMatchColor", 1.0f, 1.0f, 0.8f, 1.0f,
|
||||||
0.0f, 1.0f,
|
0.0f,
|
||||||
game::DVAR_FLAG_SAVED);
|
1.0f, game::DVAR_FLAG_SAVED, "color of console matched dvar");
|
||||||
|
dvars::con_inputDvarValueColor = dvars::register_vec4("con_inputDvarValueColor", 1.0f, 1.0f, 0.8f, 1.0f,
|
||||||
dvars::con_outputSliderColor = dvars::register_vec4(
|
0.0f,
|
||||||
"con_outputSliderColor",
|
1.0f, game::DVAR_FLAG_SAVED, "color of console matched dvar value");
|
||||||
0.9f, 0.9f, 0.5f, 1.00f,
|
|
||||||
0.0f, 1.0f,
|
|
||||||
game::DVAR_FLAG_SAVED);
|
|
||||||
|
|
||||||
dvars::con_outputWindowColor = dvars::register_vec4(
|
|
||||||
"con_outputWindowColor",
|
|
||||||
0.25f, 0.25f, 0.25f, 0.85f,
|
|
||||||
0.0f, 1.0f,
|
|
||||||
game::DVAR_FLAG_SAVED);
|
|
||||||
|
|
||||||
dvars::con_inputDvarMatchColor = dvars::register_vec4(
|
|
||||||
"con_inputDvarMatchColor",
|
|
||||||
1.0f, 1.0f, 0.8f, 1.0f,
|
|
||||||
0.0f, 1.0f,
|
|
||||||
game::DVAR_FLAG_SAVED);
|
|
||||||
|
|
||||||
dvars::con_inputDvarValueColor = dvars::register_vec4(
|
|
||||||
"con_inputDvarValueColor",
|
|
||||||
1.0f, 1.0f, 0.8f, 1.0f,
|
|
||||||
0.0f, 1.0f,
|
|
||||||
game::DVAR_FLAG_SAVED);
|
|
||||||
|
|
||||||
dvars::con_inputDvarInactiveValueColor = dvars::register_vec4(
|
dvars::con_inputDvarInactiveValueColor = dvars::register_vec4(
|
||||||
"con_inputDvarInactiveValueColor",
|
"con_inputDvarInactiveValueColor", 0.8f, 0.8f,
|
||||||
0.8f, 0.8f, 0.8f, 1.0f,
|
0.8f, 1.0f, 0.0f, 1.0f, game::DVAR_FLAG_SAVED,
|
||||||
0.0f, 1.0f,
|
"color of console inactive dvar value");
|
||||||
game::DVAR_FLAG_SAVED);
|
dvars::con_inputCmdMatchColor = dvars::register_vec4("con_inputCmdMatchColor", 0.80f, 0.80f, 1.0f, 1.0f,
|
||||||
|
0.0f,
|
||||||
dvars::con_inputCmdMatchColor = dvars::register_vec4(
|
1.0f, game::DVAR_FLAG_SAVED, "color of console matched command");
|
||||||
"con_inputCmdMatchColor",
|
|
||||||
0.80f, 0.80f, 1.0f, 1.0f,
|
|
||||||
0.0f, 1.0f,
|
|
||||||
game::DVAR_FLAG_SAVED);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,12 @@ namespace game_console
|
|||||||
con_type_info = 7
|
con_type_info = 7
|
||||||
};
|
};
|
||||||
|
|
||||||
void print(int type, const char* fmt, ...);
|
//void print(int type, const char* fmt, ...);
|
||||||
|
|
||||||
bool console_char_event(int local_client_num, int key);
|
bool console_char_event(int local_client_num, int key);
|
||||||
bool console_key_event(int local_client_num, int key, int down);
|
bool console_key_event(int local_client_num, int key, int down);
|
||||||
|
bool match_compare(const std::string& input, const std::string& text, const bool exact);
|
||||||
|
void find_matches(std::string input, std::vector<std::string>& suggestions, const bool exact);
|
||||||
|
|
||||||
void execute(const char* cmd);
|
void execute(const char* cmd);
|
||||||
}
|
}
|
@ -9,6 +9,7 @@
|
|||||||
#include <utils/hook.hpp>
|
#include <utils/hook.hpp>
|
||||||
#include <utils/string.hpp>
|
#include <utils/string.hpp>
|
||||||
#include <game/dvars.hpp>
|
#include <game/dvars.hpp>
|
||||||
|
#include <component/console.hpp>
|
||||||
|
|
||||||
namespace network
|
namespace network
|
||||||
{
|
{
|
||||||
@ -268,7 +269,7 @@ namespace network
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
game_console::print(game_console::con_type_info, "%s\n", message.data());
|
console::info("%s\n", message.data()); //test
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,26 @@ namespace dvars
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
template <typename T>
|
||||||
|
T* find_dvar(std::unordered_map<std::string, T>& map, const std::string& name)
|
||||||
|
{
|
||||||
|
auto i = map.find(name);
|
||||||
|
if (i != map.end())
|
||||||
|
{
|
||||||
|
return &i->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool find_dvar(std::unordered_set<std::string>& set, const std::string& name)
|
||||||
|
{
|
||||||
|
return set.find(name) != set.end();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string dvar_get_domain(const game::dvar_type type, const game::dvar_limits& domain)
|
std::string dvar_get_domain(const game::dvar_type type, const game::dvar_limits& domain)
|
||||||
{
|
{
|
||||||
std::string str;
|
std::string str;
|
||||||
|
@ -932,7 +932,7 @@ namespace game
|
|||||||
|
|
||||||
struct dvar_t
|
struct dvar_t
|
||||||
{
|
{
|
||||||
int hash;
|
const char* hash;
|
||||||
unsigned int flags;
|
unsigned int flags;
|
||||||
dvar_type type;
|
dvar_type type;
|
||||||
bool modified;
|
bool modified;
|
||||||
|
@ -46,7 +46,7 @@ namespace game
|
|||||||
WEAK symbol<bool()> CL_IsCgameInitialized{ 0x14017EE30, 0x140245650 }; // H1(1.4)
|
WEAK symbol<bool()> CL_IsCgameInitialized{ 0x14017EE30, 0x140245650 }; // H1(1.4)
|
||||||
WEAK symbol<unsigned int(int)> Live_SyncOnlineDataFlags{ 0, 0x14059A700 }; // H1(1.4)
|
WEAK symbol<unsigned int(int)> Live_SyncOnlineDataFlags{ 0, 0x14059A700 }; // H1(1.4)
|
||||||
|
|
||||||
WEAK symbol<void()> Sys_Milliseconds{ 0x1403E2B10, 0x140513710 }; // H1(1.4)
|
WEAK symbol<int()> Sys_Milliseconds{ 0x1403E2B10, 0x140513710 }; // H1(1.4)
|
||||||
WEAK symbol<bool()> Sys_IsDatabaseReady2{ 0, 0x14042B090 }; // H1(1.4)
|
WEAK symbol<bool()> Sys_IsDatabaseReady2{ 0, 0x14042B090 }; // H1(1.4)
|
||||||
|
|
||||||
WEAK symbol<void(netadr_s* from)> SV_DirectConnect{ 0, 0x140480860 }; // H1(1.4)
|
WEAK symbol<void(netadr_s* from)> SV_DirectConnect{ 0, 0x140480860 }; // H1(1.4)
|
||||||
@ -151,6 +151,11 @@ namespace game
|
|||||||
|
|
||||||
WEAK symbol<void()> Sys_ShowConsole{ 0x1403E3B90, 0x140514910 }; // H1(1.4)
|
WEAK symbol<void()> Sys_ShowConsole{ 0x1403E3B90, 0x140514910 }; // H1(1.4)
|
||||||
|
|
||||||
|
WEAK symbol<const char* (const char*)> UI_GetMapDisplayName{ 0, 0x140408CC0 }; // H1(1.4)
|
||||||
|
|
||||||
|
WEAK symbol<const char* (const char*)> UI_GetGameTypeDisplayName{ 0, 0x1404086A0 }; // H1(1.4)
|
||||||
|
|
||||||
|
|
||||||
WEAK symbol<const char* (const char* string)> UI_SafeTranslateString{ 0x140350430, 0x1405A2930 }; // H1(1.4)
|
WEAK symbol<const char* (const char* string)> UI_SafeTranslateString{ 0x140350430, 0x1405A2930 }; // H1(1.4)
|
||||||
|
|
||||||
WEAK symbol<void* (jmp_buf* Buf, int Value)> longjmp{ 0x140648FD4, 0x14089EED0 }; // H1(1.4)
|
WEAK symbol<void* (jmp_buf* Buf, int Value)> longjmp{ 0x140648FD4, 0x14089EED0 }; // H1(1.4)
|
||||||
|
Loading…
Reference in New Issue
Block a user