Scripting progress

This commit is contained in:
Federico Cecchetto 2022-03-03 02:09:13 +01:00
parent 26d9ab5abd
commit e5149fe721
9 changed files with 3737 additions and 1719 deletions

View File

@ -24,7 +24,7 @@ namespace logfile
std::vector<sol::protected_function> player_damage_callbacks;
utils::hook::detour vm_execute_hook;
char empty_function[2] = { 0x32, 0x34 }; // CHECK_CLEAR_PARAMS, END
char empty_function[2] = {0x32, 0x34}; // CHECK_CLEAR_PARAMS, END
bool hook_enabled = true;
sol::lua_value convert_entity(lua_State* state, const game::mp::gentity_s* ent)
@ -34,16 +34,14 @@ namespace logfile
return {};
}
const auto player = scripting::call("getEntByNum", { ent->s.entityNum });
const scripting::entity player{game::Scr_GetEntityId(ent->s.entityNum, 0)};
return scripting::lua::convert(state, player);
}
std::string get_weapon_name(unsigned int weapon, bool isAlternate)
{
char output[1024] = { 0 };
char output[1024] = {0};
game::BG_GetWeaponNameComplete(weapon, isAlternate, output, 1024);
return output;
}
@ -54,39 +52,39 @@ namespace logfile
return {};
}
const auto _vec = scripting::vector(vec);
return scripting::lua::convert(state, _vec);
const auto vec_ = scripting::vector(vec);
return scripting::lua::convert(state, vec_);
}
std::string convert_mod(const int meansOfDeath)
{
const auto value = reinterpret_cast<game::scr_string_t**>(0x140FEC3F0)[meansOfDeath];
const auto string = game::SL_ConvertToString(*value);
return string;
}
void scr_player_killed_stub(game::mp::gentity_s* self, const game::mp::gentity_s* inflictor, game::mp::gentity_s* attacker, int damage,
const int meansOfDeath, const unsigned int weapon, const bool isAlternate, const float* vDir, const unsigned int hitLoc, int psTimeOffset, int deathAnimDuration)
void scr_player_killed_stub(game::mp::gentity_s* self, const game::mp::gentity_s* inflictor,
game::mp::gentity_s* attacker, int damage, const int meansOfDeath, const unsigned int weapon,
const bool isAlternate, const float* vDir, const unsigned int hitLoc, int psTimeOffset, int deathAnimDuration)
{
{
const std::string _hitLoc = reinterpret_cast<const char**>(0x140FEC4D0)[hitLoc]; // or 12162B0
const auto _mod = convert_mod(meansOfDeath);
const std::string hitloc = reinterpret_cast<const char**>(0x140FEC4D0)[hitLoc];
const auto mod_ = convert_mod(meansOfDeath);
const auto _weapon = get_weapon_name(weapon, isAlternate);
const auto weapon_ = get_weapon_name(weapon, isAlternate);
for (const auto& callback : player_killed_callbacks)
{
const auto state = callback.lua_state();
const auto _self = convert_entity(state, self);
const auto _inflictor = convert_entity(state, inflictor);
const auto _attacker = convert_entity(state, attacker);
const auto self_ = convert_entity(state, self);
const auto inflictor_ = convert_entity(state, inflictor);
const auto attacker_ = convert_entity(state, attacker);
const auto _vDir = convert_vector(state, vDir);
const auto dir = convert_vector(state, vDir);
const auto result = callback(_self, _inflictor, _attacker, damage, _mod, _weapon, _vDir, _hitLoc, psTimeOffset, deathAnimDuration);
const auto result = callback(self_, inflictor_, attacker_, damage,
mod_, weapon_, dir, hitloc, psTimeOffset, deathAnimDuration);
scripting::lua::handle_error(result);
@ -102,30 +100,34 @@ namespace logfile
}
}
scr_player_killed_hook.invoke<void>(self, inflictor, attacker, damage, meansOfDeath, weapon, isAlternate, vDir, hitLoc, psTimeOffset, deathAnimDuration);
scr_player_killed_hook.invoke<void>(self, inflictor, attacker, damage, meansOfDeath,
weapon, isAlternate, vDir, hitLoc, psTimeOffset, deathAnimDuration);
}
void scr_player_damage_stub(game::mp::gentity_s* self, const game::mp::gentity_s* inflictor, game::mp::gentity_s* attacker, int damage, int dflags,
const int meansOfDeath, const unsigned int weapon, const bool isAlternate, const float* vPoint, const float* vDir, const unsigned int hitLoc, const int timeOffset)
void scr_player_damage_stub(game::mp::gentity_s* self, const game::mp::gentity_s* inflictor,
game::mp::gentity_s* attacker, int damage, int dflags, const int meansOfDeath,
const unsigned int weapon, const bool isAlternate, const float* vPoint,
const float* vDir, const unsigned int hitLoc, const int timeOffset)
{
{
const std::string _hitLoc = reinterpret_cast<const char**>(0x140FEC4D0)[hitLoc]; // or 12162B0
const auto _mod = convert_mod(meansOfDeath);
const std::string hitloc = reinterpret_cast<const char**>(0x140FEC4D0)[hitLoc];
const auto mod_ = convert_mod(meansOfDeath);
const auto _weapon = get_weapon_name(weapon, isAlternate);
const auto weapon_ = get_weapon_name(weapon, isAlternate);
for (const auto& callback : player_damage_callbacks)
{
const auto state = callback.lua_state();
const auto _self = convert_entity(state, self);
const auto _inflictor = convert_entity(state, inflictor);
const auto _attacker = convert_entity(state, attacker);
const auto self_ = convert_entity(state, self);
const auto inflictor_ = convert_entity(state, inflictor);
const auto attacker_ = convert_entity(state, attacker);
const auto _vPoint = convert_vector(state, vPoint);
const auto _vDir = convert_vector(state, vDir);
const auto point = convert_vector(state, vPoint);
const auto dir = convert_vector(state, vDir);
const auto result = callback(_self, _inflictor, _attacker, damage, dflags, _mod, _weapon, _vPoint, _vDir, _hitLoc);
const auto result = callback(self_, inflictor_, attacker_,
damage, dflags, mod_, weapon_, point, dir, hitloc);
scripting::lua::handle_error(result);
@ -141,13 +143,14 @@ namespace logfile
}
}
scr_player_damage_hook.invoke<void>(self, inflictor, attacker, damage, dflags, meansOfDeath, weapon, isAlternate, vPoint, vDir, hitLoc, timeOffset);
scr_player_damage_hook.invoke<void>(self, inflictor, attacker, damage, dflags,
meansOfDeath, weapon, isAlternate, vPoint, vDir, hitLoc, timeOffset);
}
void client_command_stub(const int clientNum)
{
auto self = &game::mp::g_entities[clientNum];
char cmd[1024]{};
char cmd[1024] = {0};
game::SV_Cmd_ArgvBuffer(0, cmd, 1024);
@ -160,13 +163,13 @@ namespace logfile
message.erase(0, hidden ? 2 : 1);
scheduler::once([cmd, message, self]()
{
const scripting::entity level{ *game::levelEntityId };
const auto player = scripting::call("getEntByNum", { self->s.entityNum }).as<scripting::entity>();
{
const scripting::entity level{*game::levelEntityId};
const scripting::entity player{game::Scr_GetEntityId(self->s.entityNum, 0)};
scripting::notify(level, cmd, { player, message });
scripting::notify(player, cmd, { message });
}, scheduler::pipeline::server);
scripting::notify(level, cmd, {player, message});
scripting::notify(player, cmd, {message});
}, scheduler::pipeline::server);
if (hidden)
{
@ -175,18 +178,18 @@ namespace logfile
}
// ClientCommand
return reinterpret_cast<void(*)(int)>(0x140336000)(clientNum);
return utils::hook::invoke<void>(0x140336000, clientNum);
}
void g_shutdown_game_stub(const int freeScripts)
{
{
const scripting::entity level{ *game::levelEntityId };
scripting::notify(level, "shutdownGame_called", { 1 });
const scripting::entity level{*game::levelEntityId};
scripting::notify(level, "shutdownGame_called", {1});
}
// G_ShutdownGame
return reinterpret_cast<void(*)(int)>(0x140345A60)(freeScripts);
return utils::hook::invoke<void>(0x140345A60, freeScripts);
}
unsigned int local_id_to_entity(unsigned int local_id)
@ -249,10 +252,9 @@ namespace logfile
a.movzx(r15d, byte_ptr(r14));
a.inc(r14);
a.lea(eax, dword_ptr(r15, -0x17));
a.mov(dword_ptr(rbp, 0x68), r15d);
a.mov(dword_ptr(rbp, 0xA4), r15d);
a.jmp(0x140444653);
a.jmp(SELECT_VALUE(0x140376663, 0x140444653));
a.bind(replace);
@ -294,20 +296,18 @@ namespace logfile
public:
void post_unpack() override
{
if (game::environment::is_sp())
if (!game::environment::is_sp())
{
return;
utils::hook::call(0x14048191D, client_command_stub);
scr_player_damage_hook.create(0x14037DC50, scr_player_damage_stub);
scr_player_killed_hook.create(0x14037DF30, scr_player_killed_stub);
utils::hook::call(0x140484EC0, g_shutdown_game_stub);
utils::hook::call(0x1404853C1, g_shutdown_game_stub);
}
utils::hook::call(0x14048191D, client_command_stub);
scr_player_damage_hook.create(0x14037DC50, scr_player_damage_stub);
scr_player_killed_hook.create(0x14037DF30, scr_player_killed_stub);
utils::hook::call(0x140484EC0, g_shutdown_game_stub);
utils::hook::call(0x1404853C1, g_shutdown_game_stub);
utils::hook::jump(0x140444645, utils::hook::assemble(vm_execute_stub), true);
utils::hook::jump(SELECT_VALUE(0x140376655, 0x140444645), utils::hook::assemble(vm_execute_stub), true);
}
};
}

View File

@ -15,6 +15,7 @@
namespace scripting
{
std::unordered_map<int, std::unordered_map<std::string, int>> fields_table;
std::unordered_map<std::string, std::unordered_map<std::string, const char*>> script_function_table;
namespace
@ -23,6 +24,8 @@ namespace scripting
utils::hook::detour scr_load_level_hook;
utils::hook::detour g_shutdown_game_hook;
utils::hook::detour scr_add_class_field_hook;
utils::hook::detour scr_set_thread_position_hook;
utils::hook::detour process_script_hook;
@ -45,7 +48,7 @@ namespace scripting
e.arguments.emplace_back(*value);
}
if (e.name == "connected")
if (e.name == "entitydeleted")
{
scripting::clear_entity_fields(e.entity);
}
@ -72,6 +75,18 @@ namespace scripting
return g_shutdown_game_hook.invoke<void>(free_scripts);
}
void scr_add_class_field_stub(unsigned int classnum, game::scr_string_t _name, unsigned int canonicalString, unsigned int offset)
{
const auto name = game::SL_ConvertToString(_name);
if (fields_table[classnum].find(name) == fields_table[classnum].end())
{
fields_table[classnum][name] = offset;
}
scr_add_class_field_hook.invoke<void>(classnum, _name, canonicalString, offset);
}
void process_script_stub(const char* filename)
{
const auto file_id = atoi(filename);
@ -100,18 +115,25 @@ namespace scripting
public:
void post_unpack() override
{
vm_notify_hook.create(SELECT_VALUE(0x140320E50, 0x1404479F0 ), vm_notify_stub); // H1MP
// SP address is wrong, but should be ok
scr_load_level_hook.create(SELECT_VALUE(0x140005260, 0x1403727C0), scr_load_level_stub); // H1MP
g_shutdown_game_hook.create(SELECT_VALUE(0x140228BA0, 0x140345A60), g_shutdown_game_stub); // H1MP
if (game::environment::is_sp())
{
return;
}
scr_set_thread_position_hook.create(SELECT_VALUE(0x1403115E0, 0x140437D10), scr_set_thread_position_stub); // H1MP
process_script_hook.create(SELECT_VALUE(0x14031AB30, 0x1404417E0), process_script_stub); // H1MP
vm_notify_hook.create(SELECT_VALUE(0x140379A00, 0x1404479F0), vm_notify_stub);
scr_add_class_field_hook.create(SELECT_VALUE(0x140370370, 0x14043E2C0), scr_add_class_field_stub);
scr_set_thread_position_hook.create(SELECT_VALUE(0x14036A180, 0x140437D10), scr_set_thread_position_stub);
process_script_hook.create(SELECT_VALUE(0x1403737E0, 0x1404417E0), process_script_stub);
scr_load_level_hook.create(0x1403727C0, scr_load_level_stub);
g_shutdown_game_hook.create(0x140345A60, g_shutdown_game_stub);
scheduler::loop([]()
{
lua::engine::run_frame();
}, scheduler::pipeline::server);
{
lua::engine::run_frame();
}, scheduler::pipeline::server);
}
};
}

View File

@ -3,9 +3,6 @@
namespace scripting
{
using shared_table_t = std::unordered_map<std::string, std::string>;
extern std::unordered_map<int, std::unordered_map<std::string, int>> fields_table;
extern std::unordered_map<std::string, std::unordered_map<std::string, const char*>> script_function_table;
extern utils::concurrency::container<shared_table_t> shared_table;
}

View File

@ -26,19 +26,9 @@ namespace scripting
int get_field_id(const int classnum, const std::string& field)
{
const auto class_id = game::g_classMap[classnum].id;
const auto field_str = game::SL_GetString(field.data(), 0);
const auto _ = gsl::finally([field_str]()
if (scripting::fields_table[classnum].find(field) != scripting::fields_table[classnum].end())
{
game::RemoveRefToValue(game::SCRIPT_STRING, {static_cast<int>(field_str)});
});
const auto offset = game::FindVariable(class_id, field_str);
if (offset)
{
const auto index = 3 * (offset + 0xFA00 * (class_id & 3));
const auto id = reinterpret_cast<PINT64>(SELECT_VALUE(0x149BB5680, 0x14821DF80))[index];
return static_cast<int>(id);
return scripting::fields_table[classnum][field];
}
return -1;

File diff suppressed because it is too large Load Diff

View File

@ -11,82 +11,44 @@
#include "../../../component/scripting.hpp"
#include <utils/string.hpp>
#include <utils/io.hpp>
namespace scripting::lua
{
namespace
{
std::vector<std::string> load_game_constants()
vector normalize_vector(const vector& vec)
{
std::vector<std::string> result{};
const auto length = sqrt(
(vec.get_x() * vec.get_x()) +
(vec.get_y() * vec.get_y()) +
(vec.get_z() * vec.get_z())
);
const auto constants = game::GScr_LoadConsts.get();
ud_t ud;
ud_init(&ud);
ud_set_mode(&ud, 64);
ud_set_pc(&ud, uint64_t(constants));
ud_set_input_buffer(&ud, reinterpret_cast<const uint8_t*>(constants), INT32_MAX);
while (true)
{
ud_disassemble(&ud);
if (ud_insn_mnemonic(&ud) == UD_Iret)
{
break;
}
if (ud_insn_mnemonic(&ud) == UD_Imov)
{
const auto* operand = ud_insn_opr(&ud, 0);
if (operand && operand->type == UD_OP_REG && operand->base == UD_R_ECX)
{
operand = ud_insn_opr(&ud, 1);
if (operand && operand->type == UD_OP_IMM && (operand->base == UD_R_RAX || operand->base == UD_R_EAX))
{
result.emplace_back(reinterpret_cast<const char**>(0x1409C1CE0)[operand->lval.udword]);
}
}
}
if (ud_insn_mnemonic(&ud) == UD_Ilea)
{
const auto* operand = ud_insn_opr(&ud, 0);
if (!operand || operand->type != UD_OP_REG || operand->base != UD_R_RCX)
{
continue;
}
operand = ud_insn_opr(&ud, 1);
if (operand && operand->type == UD_OP_MEM && operand->base == UD_R_RIP)
{
auto* operand_ptr = reinterpret_cast<char*>(ud_insn_len(&ud) + ud_insn_off(&ud) + operand->lval.
sdword);
if (!utils::memory::is_bad_read_ptr(operand_ptr) && utils::memory::is_rdata_ptr(operand_ptr) &&
strlen(operand_ptr) > 0)
{
result.emplace_back(operand_ptr);
}
}
}
if (*reinterpret_cast<unsigned char*>(ud.pc) == 0xCC) break; // int 3
}
return result;
return vector(
vec.get_x() / length,
vec.get_y() / length,
vec.get_z() / length
);
}
const std::vector<std::string>& get_game_constants()
void setup_io(sol::state& state)
{
static auto constants = load_game_constants();
return constants;
state["io"]["fileexists"] = utils::io::file_exists;
state["io"]["writefile"] = utils::io::write_file;
state["io"]["remove_file"] = utils::io::remove_file;
state["io"]["filesize"] = utils::io::file_size;
state["io"]["createdirectory"] = utils::io::create_directory;
state["io"]["directoryexists"] = utils::io::directory_exists;
state["io"]["directoryisempty"] = utils::io::directory_is_empty;
state["io"]["listfiles"] = utils::io::list_files;
state["io"]["copyfolder"] = utils::io::copy_folder;
state["io"]["readfile"] = static_cast<std::string(*)(const std::string&)>(utils::io::read_file);
}
void setup_entity_type(sol::state& state, event_handler& handler, scheduler& scheduler)
void setup_vector_type(sol::state& state)
{
state["level"] = entity{*game::levelEntityId};
auto vector_type = state.new_usertype<vector>("vector", sol::constructors<vector(float, float, float)>());
vector_type["x"] = sol::property(&vector::get_x, &vector::set_x);
vector_type["y"] = sol::property(&vector::get_y, &vector::set_y);
@ -96,6 +58,109 @@ namespace scripting::lua
vector_type["g"] = sol::property(&vector::get_y, &vector::set_y);
vector_type["b"] = sol::property(&vector::get_z, &vector::set_z);
vector_type[sol::meta_function::addition] = sol::overload(
[](const vector& a, const vector& b)
{
return vector(
a.get_x() + b.get_x(),
a.get_y() + b.get_y(),
a.get_z() + b.get_z()
);
},
[](const vector& a, const int value)
{
return vector(
a.get_x() + value,
a.get_y() + value,
a.get_z() + value
);
}
);
vector_type[sol::meta_function::subtraction] = sol::overload(
[](const vector& a, const vector& b)
{
return vector(
a.get_x() - b.get_x(),
a.get_y() - b.get_y(),
a.get_z() - b.get_z()
);
},
[](const vector& a, const int value)
{
return vector(
a.get_x() - value,
a.get_y() - value,
a.get_z() - value
);
}
);
vector_type[sol::meta_function::multiplication] = sol::overload(
[](const vector& a, const vector& b)
{
return vector(
a.get_x() * b.get_x(),
a.get_y() * b.get_y(),
a.get_z() * b.get_z()
);
},
[](const vector& a, const int value)
{
return vector(
a.get_x() * value,
a.get_y() * value,
a.get_z() * value
);
}
);
vector_type[sol::meta_function::division] = sol::overload(
[](const vector& a, const vector& b)
{
return vector(
a.get_x() / b.get_x(),
a.get_y() / b.get_y(),
a.get_z() / b.get_z()
);
},
[](const vector& a, const int value)
{
return vector(
a.get_x() / value,
a.get_y() / value,
a.get_z() / value
);
}
);
vector_type[sol::meta_function::equal_to] = [](const vector& a, const vector& b)
{
return a.get_x() == b.get_x() &&
a.get_y() == b.get_y() &&
a.get_z() == b.get_z();
};
vector_type[sol::meta_function::length] = [](const vector& a)
{
return sqrt((a.get_x() * a.get_x()) + (a.get_y() * a.get_y()) + (a.get_z() * a.get_z()));
};
vector_type[sol::meta_function::to_string] = [](const vector& a)
{
return utils::string::va("{x: %f, y: %f, z: %f}", a.get_x(), a.get_y(), a.get_z());
};
vector_type["normalize"] = [](const vector& a)
{
return normalize_vector(a);
};
}
void setup_entity_type(sol::state& state, event_handler& handler, scheduler& scheduler)
{
state["level"] = entity{*game::levelEntityId};
auto entity_type = state.new_usertype<entity>("entity");
for (const auto& func : method_map)
@ -114,19 +179,6 @@ namespace scripting::lua
};
}
for (const auto& constant : get_game_constants())
{
entity_type[constant] = sol::property(
[constant](const entity& entity, const sol::this_state s)
{
return convert(s, entity.get(constant));
},
[constant](const entity& entity, const sol::this_state s, const sol::lua_value& value)
{
entity.set(constant, convert({s, value}));
});
}
entity_type["set"] = [](const entity& entity, const std::string& field,
const sol::lua_value& value)
{
@ -288,8 +340,7 @@ namespace scripting::lua
game_type["getgamevar"] = [](const sol::this_state s)
{
const auto id = *reinterpret_cast<unsigned int*>(0x14815DEB4);
const auto value = ::game::scr_VarGlob->childVariableValue[id];
const auto value = ::game::scr_VarGlob->childVariableValue[*::game::gameEntityId];
::game::VariableValue variable{};
variable.type = value.type;
@ -445,6 +496,8 @@ namespace scripting::lua
return this->folder_;
};
setup_io(this->state_);
setup_vector_type(this->state_);
setup_entity_type(this->state_, this->event_handler_, this->scheduler_);
printf("Loading script '%s'\n", this->folder_.data());

View File

@ -21,7 +21,7 @@ namespace scripting::lua
std::unordered_map<std::string, array_value> values;
const auto offset = 64000 * (id & 3);
const auto offset = 0xA000 * (id & 3);
auto current = game::scr_VarGlob->objectVariableChildren[id].firstChild;
auto idx = 1;

View File

@ -186,8 +186,8 @@ namespace game
struct scrVarGlob_t
{
ObjectVariableValue objectVariableValue[40960];
ObjectVariableChildren objectVariableChildren[40960];
ObjectVariableValue objectVariableValue[56320];
ObjectVariableChildren objectVariableChildren[56320];
unsigned __int16 childVariableBucket[65536];
ChildVariableValue childVariableValue[384000];
};
@ -1358,18 +1358,22 @@ namespace game
struct EntityState
{
char entityNum;
uint16_t entityNum;
}; // size = ?
#pragma pack(push, 1)
struct gentity_s
{
EntityState s;
char __pad0[343];
char __pad0[342];
gclient_s* client;
char __pad1[80];
int flags;
char __pad2[300];
}; // size = 736
#pragma pack(pop)
static_assert(sizeof(gentity_s) == 736);
struct playerState_s
{

View File

@ -8,17 +8,17 @@ namespace game
* Functions
**************************************************************/
WEAK symbol<void(int type, VariableUnion u)> AddRefToValue{0x140315830, 0x14043C580}; // H1MP
WEAK symbol<void(int type, VariableUnion u)> RemoveRefToValue{0x140317340, 0x14043E090}; // H1MP
WEAK symbol<void(unsigned int id)> AddRefToObject{0, 0x14043C570 }; // H1MP
WEAK symbol<void(unsigned int id)> RemoveRefToObject{0, 0x14043DF80 }; // H1MP
WEAK symbol<unsigned int(unsigned int id)> AllocThread{0, 0x14043C8E0 }; // H1MP
WEAK symbol<void(int type, VariableUnion u)> AddRefToValue{0x14036E600, 0x14043C580};
WEAK symbol<void(int type, VariableUnion u)> RemoveRefToValue{0x1403700F0, 0x14043E090};
WEAK symbol<void(unsigned int id)> AddRefToObject{0x14036E5F0, 0x14043C570};
WEAK symbol<void(unsigned int id)> RemoveRefToObject{0x14036FFE0, 0x14043DF80};
WEAK symbol<unsigned int(unsigned int id)> AllocThread{0x14036E960, 0x14043C8E0};
WEAK symbol<void(int localClientNum, const char* text)> Cbuf_AddText{0x140342EB0, 0x1404033B0};
WEAK symbol<void(int localClientNum, int controllerIndex, const char* buffer,
void (int, int, const char*))> Cbuf_ExecuteBufferInternal{0, 0x1404034C0};
void (int, int, const char*))> Cbuf_ExecuteBufferInternal{0x140342FC0, 0x1404034C0};
WEAK symbol<void(const char* message)> Conbuf_AppendText{0x1403E3300, 0x140513FF0};
WEAK symbol<char* (int start)> ConcatArgs{0x14021A7E0, 0x140335D70}; // h1mp
WEAK symbol<char*(int start)> ConcatArgs{0x1402697F0, 0x140335D70};
WEAK symbol<void(int localClientNum, int controllerIndex, const char* text)> Cmd_ExecuteSingleCommand{0x140343980, 0x140403F60};
WEAK symbol<void(const char* cmdName, void(), cmd_function_s* allocedCmd)> Cmd_AddCommandInternal{0x1403433E0, 0x140403950};
WEAK symbol<void(const char*)> Cmd_RemoveCommand{0x140343FF0, 0x1404045D0};
@ -27,7 +27,8 @@ namespace game
WEAK symbol<void(void*, void*)> AimAssist_AddToTargetList{0, 0x14009D0F0};
WEAK symbol<void(unsigned int weapon, bool isAlternate, char* output, unsigned int maxStringLen)> BG_GetWeaponNameComplete{0x0, 0x140165580}; // H1MP
WEAK symbol<void(unsigned int weapon, bool isAlternate,
char* output, unsigned int maxStringLen)> BG_GetWeaponNameComplete{0x140430550, 0x1401F9670};
WEAK symbol<void()> Com_Frame_Try_Block_Function{0x1401CE8D0, 0x1400D8310};
WEAK symbol<CodPlayMode()> Com_GetCurrentCoDPlayMode{0, 0x1405039A0};
@ -44,7 +45,6 @@ namespace game
WEAK symbol<void(int hash, const char* name, const char* buffer)> Dvar_SetCommand{0x1403C72B0, 0x1404FD0A0};
WEAK symbol<dvar_t*(const char* name)> Dvar_FindVar{0x1403C5D50, 0x1404FBB00};
WEAK symbol<void(const dvar_t* dvar)> Dvar_ClearModified{0x0, 0x1404FB930};
WEAK symbol<void(char* buffer, int index)> Dvar_GetCombinedString{0x140354DF0, 0x14041D830};
WEAK symbol<const char*(dvar_t* dvar, dvar_value value)> Dvar_ValueToString{0x1403C8560, 0x1404FE660};
WEAK symbol<dvar_t*(int hash, const char* name, bool value,
@ -63,16 +63,18 @@ namespace game
WEAK symbol<void(const char* gameName)> FS_Startup{0x1403B85D0, 0x1404EDD30};
WEAK symbol<void(const char* path, const char* dir)> FS_AddLocalizedGameDirectory{0x1403B6030, 0x1404EBE20};
WEAK symbol<unsigned int(unsigned int, unsigned int)> GetVariable{0x0, 0x1403F3730}; // H1MP
WEAK symbol<unsigned int(unsigned int, unsigned int)> GetVariable{0x14036FDD0, 0x1403F3730};
WEAK symbol<void()> GScr_LoadConsts{0x1402D13E0, 0x140393810};
WEAK symbol<unsigned int(unsigned int parentId, unsigned int name)> FindVariable{0x1403165D0, 0x14043D430}; // H1MP
WEAK symbol<unsigned int(int entnum, unsigned int classnum)> FindEntityId{0x1403166D0, 0x14043D330}; // H1MP
WEAK symbol<void(unsigned int parentId, unsigned int index)> RemoveVariableValue{0, 0x14043E130}; // H1MP
WEAK symbol<void(VariableValue* result, unsigned int classnum, int entnum, int offset)> GetEntityFieldValue{0x14031AAD0, 0x140441780}; // H1MP
WEAK symbol<unsigned int(unsigned int parentId, unsigned int name)> FindVariable{0x14036F4B0, 0x14043D430};
WEAK symbol<unsigned int(int entnum, unsigned int classnum)> FindEntityId{0x14036F3B0, 0x14043D330};
WEAK symbol<void(unsigned int parentId, unsigned int index)> RemoveVariableValue{0x140370190, 0x14043E130};
WEAK symbol<void(VariableValue* result, unsigned int classnum,
int entnum, int offset)> GetEntityFieldValue{0x140373780, 0x140441780};
WEAK symbol<int(const char* fname)> generateHashValue{0x1400FE8A0, 0x1401B1010};
WEAK symbol<void()> G_Glass_Update{0, 0x14033A640};
WEAK symbol<void()> G_Glass_Update{0x14026C570, 0x14033A640};
WEAK symbol<int(int clientNum)> G_GetClientScore{0, 0x140342F90};
WEAK symbol<char*(char* string)> I_CleanStr{0x1403CD230, 0x140503D00};
@ -94,7 +96,7 @@ namespace game
WEAK symbol<int(const char* text, int maxChars, Font_s* font)> R_TextWidth{0x1404D43B0, 0x1405D94A0};
WEAK symbol<int(void* font)> R_GetFontHeight{0x1405EA360, 0x1405D92C0};
WEAK symbol<void* (int a1)> R_DrawSomething{0x1404D37B0, 0x1405D8890};
WEAK symbol<void()> R_SyncRenderThread{0, 0x1405FF3A0};
WEAK symbol<void()> R_SyncRenderThread{0x1404F8240, 0x1405FF3A0};
WEAK symbol<void* (const char* text, int maxChars, void* font, int fontHeight, float x,
float y, float xScale, float yScale, float rotation, float* color,
int style, int cursor_pos, char cursor_char,
@ -105,32 +107,36 @@ namespace game
#define R_AddCmdDrawTextWithCursor(TXT, MC, F, UNK, X, Y, XS, YS, R, C, S, CP, CC) \
H1_AddBaseDrawTextCmd(TXT, MC, F, game::R_GetFontHeight(F), X, Y, XS, YS, R, C, S, CP, CC, game::R_DrawSomething(S))
WEAK symbol<unsigned int(unsigned int localId, const char* pos, unsigned int paramcount)> VM_Execute{0x0, 0x140444350};
WEAK symbol<unsigned int(unsigned int localId, const char* pos,
unsigned int paramcount)> VM_Execute{0x140376360, 0x140444350};
WEAK symbol<void(unsigned int id, scr_string_t stringValue, unsigned int paramcount)> Scr_NotifyId{0x14031CB80, 0x1404437E0};
WEAK symbol<const float* (const float* v)> Scr_AllocVector{0x140317D10, 0x14043E7D0}; // H1MP
WEAK symbol<void(unsigned int id, scr_string_t stringValue,
unsigned int paramcount)> Scr_NotifyId{0x140375800, 0x1404437E0};
WEAK symbol<const float*(const float* v)> Scr_AllocVector{0x140370930, 0x14043E7D0};
WEAK symbol<float(int index)> Scr_GetFloat{0x140374D20, 0x140442D10};
WEAK symbol<const char*(int index)> Scr_GetString{0, 0x14032F0A0};
WEAK symbol<const char*(int index)> Scr_GetString{0x140375210, 0x140443150};
WEAK symbol<int()> Scr_GetNumParam{0x140374F30, 0x140442E70};
WEAK symbol<void()> Scr_ClearOutParams{0x14031B7C0, 0x140442510}; // H1MP
WEAK symbol<scr_entref_t(unsigned int entId)> Scr_GetEntityIdRef{0x14031A0D0, 0x1403F68A0}; // H1MP
WEAK symbol<void()> Scr_ClearOutParams{0x140374460, 0x140442510};
WEAK symbol<scr_entref_t(unsigned int entId)> Scr_GetEntityIdRef{0x140372D50, 0x140440D80};
WEAK symbol<unsigned int(int classnum, unsigned int entnum)> Scr_GetEntityId{0x140372CA0, 0x140440CD0};
WEAK symbol<ScreenPlacement* ()> ScrPlace_GetViewPlacement{0x1401981F0, 0x140288550};
WEAK symbol<int(XAssetType type)> DB_GetXAssetTypeSize{0x14019A3B0, 0x14028BE70};
WEAK symbol<void(int clientNum, const char* menu, int a3, int a4, unsigned int a5)> LUI_OpenMenu{0x14039D5F0, 0x1404CD210};
WEAK symbol<void(int clientNum, const char* menu,
int a3, int a4, unsigned int a5)> LUI_OpenMenu{0x14039D5F0, 0x1404CD210};
WEAK symbol<bool(int clientNum, const char* menu)> Menu_IsMenuOpenAndVisible{0x1404709C0, 0x1404C7320};
WEAK symbol<scr_string_t(const char* str)> SL_FindString{0x140314AF0, 0x14043B470};
WEAK symbol<scr_string_t(const char* str, unsigned int user)> SL_GetString{0x140314D90, 0x14043B840}; // H1MP
WEAK symbol<scr_string_t(const char* str)> SL_FindString{0x14036D700, 0x14043B470};
WEAK symbol<scr_string_t(const char* str, unsigned int user)> SL_GetString{0x14036D9A0, 0x14043B840};
WEAK symbol<const char* (scr_string_t stringValue)> SL_ConvertToString{0x14036D420, 0x14043B170};
WEAK symbol<int(unsigned int classnum, int entnum, int offset)> Scr_SetObjectField{ 0x14026B620, 0x140385330 }; // H1MP
WEAK symbol<int(unsigned int classnum, int entnum, int offset)> Scr_SetObjectField{0x1402B9F60, 0x140385330};
WEAK symbol<void(netadr_s* from)> SV_DirectConnect{0, 0x140480860};
WEAK symbol<void(int arg, char* buffer, int bufferLength)> SV_Cmd_ArgvBuffer{0x1402EEFD0, 0x1403B05C0}; // H1MP
WEAK symbol<void(const char* text_in)> SV_Cmd_TokenizeString{0x1402EF050, 0x140404D20};
WEAK symbol<void(int arg, char* buffer, int bufferLength)> SV_Cmd_ArgvBuffer{0x1403446C0, 0x140404CA0};
WEAK symbol<void(const char* text_in)> SV_Cmd_TokenizeString{0x140344740, 0x140404D20};
WEAK symbol<void()> SV_Cmd_EndTokenizedString{0x140344700, 0x140404CE0};
WEAK symbol<mp::gentity_s*(const char* name)> SV_AddBot{0, 0x140480190};
@ -176,26 +182,27 @@ namespace game
WEAK symbol<CmdArgs> sv_cmd_args{0, 0x14946BA20};
WEAK symbol<int> g_script_error_level{0x14A1917A8, 0x14A33C824}; // H1MP
WEAK symbol<jmp_buf> g_script_error{0x14A1917B0, 0x14A33C940}; // H1MP
WEAK symbol<int> g_script_error_level{0x14A1917A8, 0x14A33C824};
WEAK symbol<jmp_buf> g_script_error{0x14A1917B0, 0x14A33C940};
WEAK symbol<unsigned int> levelEntityId{0x149AF55B0, 0x149CA0730}; // H1MP
WEAK symbol<unsigned int> levelEntityId{0x149AF55B0, 0x149CA0730};
WEAK symbol<unsigned int> gameEntityId{0x149CA0734, 0x14B65E3B4};
WEAK symbol<const char*> command_whitelist{0x141079A60, 0x14120C360};
WEAK symbol<cmd_function_s*> cmd_functions{0x14AD99AB8, 0x14946BAC8};
WEAK symbol<CmdArgs> cmd_args{0x14AD99960, 0x14946B970};
WEAK symbol<int> g_poolSize{0, 0x140FEADF0};
WEAK symbol<scr_classStruct_t> g_classMap{0x14080A840, 0x1412106B0}; // H1MP
WEAK symbol<scr_classStruct_t> g_classMap{0x14080A840, 0x1412106B0};
WEAK symbol<scrVarGlob_t> scr_VarGlob{0x149B1D680, 0x149CC8800}; // H1MP
WEAK symbol<scrVmPub_t> scr_VmPub{0x14A1938C0, 0x14A33EA40}; // H1MP
WEAK symbol<function_stack_t> scr_function_stack{0x14A19DE40, 0x14A348FC0}; // H1MP
WEAK symbol<scrVarGlob_t> scr_VarGlob{0x14B686480, 0x149CC8800};
WEAK symbol<scrVmPub_t> scr_VmPub{0x14A1938C0, 0x14A33EA40};
WEAK symbol<function_stack_t> scr_function_stack{0x14BD06C40, 0x14A348FC0};
WEAK symbol<GfxDrawMethod_s> gfxDrawMethod{0, 0x14FD21180};
WEAK symbol<GfxDrawMethod_s> gfxDrawMethod{0x14F05CE50, 0x14FD21180};
WEAK symbol<int> dvarCount{0, 0x14D064CF4};
WEAK symbol<dvar_t*> sortedDvars{0, 0x14D064D00};
WEAK symbol<int> dvarCount{0x14C217D10, 0x14D064CF4};
WEAK symbol<dvar_t*> dvarPool{0x14C217D20, 0x14D064D00};
WEAK symbol<void*> DB_XAssetPool{0x140DE8C80, 0x140FEB5D0};