Scripting progress
This commit is contained in:
parent
26d9ab5abd
commit
e5149fe721
@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -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
@ -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());
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user