mirror of
https://github.com/fedddddd/iw5-gsc-utils.git
synced 2026-08-01 04:40:34 +00:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
befebc4b6e | ||
|
|
933192724a |
+119
-145
@@ -6,7 +6,6 @@
|
||||
|
||||
#include "game/scripting/event.hpp"
|
||||
#include "game/scripting/execution.hpp"
|
||||
#include "game/scripting/functions.hpp"
|
||||
#include "game/scripting/array.hpp"
|
||||
#include "game/scripting/function.hpp"
|
||||
|
||||
@@ -16,19 +15,6 @@ namespace gsc
|
||||
{
|
||||
namespace
|
||||
{
|
||||
function_args get_arguments()
|
||||
{
|
||||
std::vector<scripting::script_value> args;
|
||||
|
||||
for (auto i = 0; i < game::scr_VmPub->outparamcount; i++)
|
||||
{
|
||||
const auto value = game::scr_VmPub->top[-i];
|
||||
args.push_back(value);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
void return_value(const scripting::script_value& value)
|
||||
{
|
||||
if (game::scr_VmPub->outparamcount)
|
||||
@@ -39,200 +25,182 @@ namespace gsc
|
||||
scripting::push_value(value);
|
||||
}
|
||||
|
||||
auto field_offset_start = 0xA000;
|
||||
auto field_offset_start = 0xA000u;
|
||||
|
||||
struct entity_field
|
||||
{
|
||||
std::string name;
|
||||
std::function<scripting::script_value(unsigned int entnum)> getter;
|
||||
std::function<void(unsigned int entnum, scripting::script_value)> setter;
|
||||
};
|
||||
|
||||
std::vector<std::function<void()>> post_load_callbacks;
|
||||
std::unordered_map<unsigned int, std::unordered_map<unsigned int, entity_field>> custom_fields;
|
||||
|
||||
void call_function(const script_function* function, const char* name)
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto result = function->operator()(get_arguments());
|
||||
const auto type = result.get_raw().type;
|
||||
|
||||
if (type)
|
||||
{
|
||||
return_value(result);
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
printf("************** Script execution error **************");
|
||||
printf("Error executing function %s:", name);
|
||||
printf(" %s", e.what());
|
||||
printf("****************************************************");
|
||||
}
|
||||
}
|
||||
|
||||
void call_method(const script_method* method, const char* name, game::scr_entref_t ent)
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto result = method->operator()(ent, get_arguments());
|
||||
const auto type = result.get_raw().type;
|
||||
|
||||
if (type)
|
||||
{
|
||||
return_value(result);
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
printf("************** Script execution error **************");
|
||||
printf("Error executing method %s:", name);
|
||||
printf(" %s", e.what());
|
||||
printf("****************************************************");
|
||||
}
|
||||
}
|
||||
std::unordered_map<unsigned int, entity_field_t> custom_fields[class_id_t::class_count];
|
||||
|
||||
utils::hook::detour scr_get_object_field_hook;
|
||||
utils::hook::detour scr_set_object_field_hook;
|
||||
utils::hook::detour scr_post_load_scripts_hook;
|
||||
|
||||
const char* get_script_loc()
|
||||
{
|
||||
return "unknown location";
|
||||
}
|
||||
|
||||
void print_error(const char* fmt, ...)
|
||||
{
|
||||
static char buffer[0x1000];
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
_vsnprintf_s(buffer, sizeof(buffer), sizeof(buffer), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
printf("\n"
|
||||
"******* script runtime error *******\n"
|
||||
"%s\n"
|
||||
"\tat %s\n"
|
||||
"************************************",
|
||||
buffer, get_script_loc());
|
||||
}
|
||||
|
||||
const gsc::entity_field_t* find_field(unsigned int classnum, unsigned int offset)
|
||||
{
|
||||
const auto& class_map = custom_fields[classnum];
|
||||
const auto field_iter = class_map.find(offset);
|
||||
if (field_iter == class_map.end())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return &field_iter->second;
|
||||
}
|
||||
|
||||
void scr_get_object_field_stub(unsigned int classnum, int entnum, unsigned int offset)
|
||||
{
|
||||
if (custom_fields[classnum].find(offset) == custom_fields[classnum].end())
|
||||
const auto field = find_field(classnum, offset);
|
||||
if (field == nullptr)
|
||||
{
|
||||
return scr_get_object_field_hook.invoke<void>(classnum, entnum, offset);
|
||||
}
|
||||
|
||||
const auto& field = custom_fields[classnum][offset];
|
||||
|
||||
try
|
||||
{
|
||||
const auto result = field.getter(entnum);
|
||||
const auto result = field->getter(entnum);
|
||||
return_value(result);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
printf("************** Script execution error **************");
|
||||
printf("Error getting field %s:", field.name.data());
|
||||
printf(" %s", e.what());
|
||||
printf("****************************************************");
|
||||
print_error("while getting builtin field \"%s\"\n%s", field->name.data(), e.what());
|
||||
}
|
||||
}
|
||||
|
||||
utils::hook::detour scr_set_object_field_hook;
|
||||
void scr_set_object_field_stub(unsigned int classnum, int entnum, unsigned int offset)
|
||||
{
|
||||
if (custom_fields[classnum].find(offset) == custom_fields[classnum].end())
|
||||
const auto field = find_field(classnum, offset);
|
||||
if (field == nullptr)
|
||||
{
|
||||
return scr_set_object_field_hook.invoke<void>(classnum, entnum, offset);
|
||||
}
|
||||
|
||||
const auto args = get_arguments();
|
||||
const auto& field = custom_fields[classnum][offset];
|
||||
function_args args;
|
||||
|
||||
try
|
||||
{
|
||||
field.setter(entnum, args[0]);
|
||||
field->setter(entnum, args[0]);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
printf("************** Script execution error **************");
|
||||
printf("Error setting field %s:", field.name.data());
|
||||
printf(" %s", e.what());
|
||||
printf("****************************************************");
|
||||
print_error("while setting builtin field \"%s\"\n%s", field->name.data(), e.what());
|
||||
}
|
||||
}
|
||||
|
||||
utils::hook::detour scr_post_load_scripts_hook;
|
||||
void scr_post_load_scripts_stub()
|
||||
{
|
||||
for (const auto& callback : post_load_callbacks)
|
||||
for (auto i = 0; i < class_id_t::class_count; i++)
|
||||
{
|
||||
callback();
|
||||
const auto& class_map = custom_fields[i];
|
||||
for (const auto& [offset, field] : class_map)
|
||||
{
|
||||
const auto str_id = game::SL_GetString(field.name.data(), 0);
|
||||
const auto canon_str = game::SL_GetCanonicalString(field.name.data());
|
||||
game::Scr_AddClassField(i, str_id, canon_str, offset);
|
||||
}
|
||||
}
|
||||
|
||||
return scr_post_load_scripts_hook.invoke<void>();
|
||||
}
|
||||
}
|
||||
|
||||
void* make_function_thunk(const char* name, const script_function* func)
|
||||
void call_function(const script_function& function, const std::string& name)
|
||||
{
|
||||
static std::uint8_t bytes[] =
|
||||
try
|
||||
{
|
||||
0x68, 0x44, 0x33, 0x22, 0x11, // push
|
||||
0x68, 0x44, 0x33, 0x22, 0x11, // push
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, // call
|
||||
0x83, 0xC4, 0x08, // add esp, 8
|
||||
0xC3 // ret
|
||||
};
|
||||
function_args args;
|
||||
const auto result = function.operator()(args);
|
||||
const auto type = result.get_raw().type;
|
||||
|
||||
const auto stub = utils::memory::allocate_array<std::uint8_t>(sizeof(bytes));
|
||||
std::memcpy(stub, bytes, sizeof(bytes));
|
||||
|
||||
utils::hook::unprotect(stub, sizeof(bytes));
|
||||
|
||||
*reinterpret_cast<std::size_t*>(stub + 1) = reinterpret_cast<size_t>(name);
|
||||
*reinterpret_cast<std::size_t*>(stub + 6) = reinterpret_cast<size_t>(func);
|
||||
utils::hook::call(stub + 10, call_function);
|
||||
|
||||
return stub;
|
||||
if (type)
|
||||
{
|
||||
return_value(result);
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
print_error("in call to builtin function \"%s\"\n%s", name.data(), e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void* make_method_thunk(const char* name, const script_method* func)
|
||||
void call_method(const script_method& method, const std::string& name, game::scr_entref_t ent)
|
||||
{
|
||||
static std::uint8_t bytes[] =
|
||||
try
|
||||
{
|
||||
0xFF, 0x74, 0x24, 0x04, // push [esp+4]
|
||||
0x68, 0x44, 0x33, 0x22, 0x11, // push
|
||||
0x68, 0x44, 0x33, 0x22, 0x11, // push
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, // call
|
||||
0x83, 0xC4, 0x0C, // add esp, 8
|
||||
0xC3 // ret
|
||||
};
|
||||
function_args args;
|
||||
const auto result = method.operator()(ent, args);
|
||||
const auto type = result.get_raw().type;
|
||||
|
||||
const auto stub = utils::memory::allocate_array<std::uint8_t>(sizeof(bytes));
|
||||
std::memcpy(stub, bytes, sizeof(bytes));
|
||||
|
||||
utils::hook::unprotect(stub, sizeof(bytes));
|
||||
|
||||
*reinterpret_cast<std::size_t*>(stub + 5) = reinterpret_cast<size_t>(name);
|
||||
*reinterpret_cast<std::size_t*>(stub + 10) = reinterpret_cast<size_t>(func);
|
||||
utils::hook::call(stub + 14, call_method);
|
||||
|
||||
return stub;
|
||||
if (type)
|
||||
{
|
||||
return_value(result);
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
print_error("in call to builtin method \"%s\"\n%s", name.data(), e.what());
|
||||
}
|
||||
}
|
||||
|
||||
namespace field
|
||||
{
|
||||
void add(const classid classnum, const std::string& name,
|
||||
const std::function<scripting::script_value(unsigned int entnum)>& getter,
|
||||
const std::function<void(unsigned int entnum, const scripting::script_value&)>& setter)
|
||||
void add(const class_id_t classnum, const std::string& name, const field_getter_t getter, const field_setter_t& setter)
|
||||
{
|
||||
const auto offset = field_offset_start++;
|
||||
custom_fields[classnum][offset] = {name, getter, setter};
|
||||
auto& class_map = custom_fields[classnum];
|
||||
|
||||
post_load_callbacks.push_back([=]()
|
||||
{
|
||||
const auto name_str = game::SL_GetString(name.data(), 0);
|
||||
game::Scr_AddClassField(classnum, name_str, game::SL_GetCanonicalString(name.data()), offset);
|
||||
});
|
||||
entity_field_t field{};
|
||||
field.name = name;
|
||||
field.getter = getter;
|
||||
field.setter = setter;
|
||||
class_map.insert(std::make_pair(offset, field));
|
||||
}
|
||||
}
|
||||
|
||||
function_args::function_args(std::vector<scripting::script_value> values)
|
||||
function_args::function_args()
|
||||
{
|
||||
for (auto i = 0u; i < game::scr_VmPub->outparamcount; i++)
|
||||
{
|
||||
const auto value = game::scr_VmPub->top[-i];
|
||||
this->values_.emplace_back(value);
|
||||
}
|
||||
}
|
||||
|
||||
function_args::function_args(const std::vector<scripting::script_value>& values)
|
||||
: values_(values)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int function_args::size() const
|
||||
std::uint32_t function_args::size() const
|
||||
{
|
||||
return this->values_.size();
|
||||
}
|
||||
|
||||
std::vector<scripting::script_value> function_args::get_raw() const
|
||||
const std::vector<scripting::script_value>& function_args::get_raw() const
|
||||
{
|
||||
return this->values_;
|
||||
}
|
||||
|
||||
scripting::value_wrap function_args::get(const int index) const
|
||||
scripting::value_wrap function_args::get(const std::uint32_t index) const
|
||||
{
|
||||
if (index >= this->values_.size())
|
||||
{
|
||||
@@ -251,7 +219,7 @@ namespace gsc
|
||||
scr_set_object_field_hook.create(0x52BCC0, scr_set_object_field_stub);
|
||||
scr_post_load_scripts_hook.create(0x628B50, scr_post_load_scripts_stub);
|
||||
|
||||
field::add(classid::entity, "entityflags",
|
||||
field::add(class_id_t::class_entity, "entityflags",
|
||||
[](unsigned int entnum) -> scripting::script_value
|
||||
{
|
||||
const auto entity = &game::g_entities[entnum];
|
||||
@@ -264,7 +232,7 @@ namespace gsc
|
||||
}
|
||||
);
|
||||
|
||||
field::add(classid::entity, "clientflags",
|
||||
field::add(class_id_t::class_entity, "clientflags",
|
||||
[](unsigned int entnum) -> scripting::script_value
|
||||
{
|
||||
const auto entity = &game::g_entities[entnum];
|
||||
@@ -277,13 +245,15 @@ namespace gsc
|
||||
}
|
||||
);
|
||||
|
||||
function::add("executecommand", [](const function_args& args) -> scripting::script_value
|
||||
function::add("executecommand", [](const function_args& args)
|
||||
-> scripting::script_value
|
||||
{
|
||||
game::Cbuf_AddText(0, args[0].as<const char*>());
|
||||
return {};
|
||||
});
|
||||
|
||||
function::add("addcommand", [](const function_args& args) -> scripting::script_value
|
||||
function::add("addcommand", [](const function_args& args)
|
||||
-> scripting::script_value
|
||||
{
|
||||
const auto name = args[0].as<std::string>();
|
||||
const auto function = args[1].as<scripting::function>();
|
||||
@@ -301,7 +271,8 @@ namespace gsc
|
||||
return {};
|
||||
});
|
||||
|
||||
function::add("dropallbots", [](const function_args&) -> scripting::script_value
|
||||
function::add("dropallbots", [](const function_args&)
|
||||
-> scripting::script_value
|
||||
{
|
||||
for (auto i = 0; i < *game::svs_clientCount; i++)
|
||||
{
|
||||
@@ -315,7 +286,8 @@ namespace gsc
|
||||
return {};
|
||||
});
|
||||
|
||||
method::add("specialtymarathon", [](const game::scr_entref_t ent, const function_args& args) -> scripting::script_value
|
||||
method::add("specialtymarathon", [](const game::scr_entref_t ent, const function_args& args)
|
||||
-> scripting::script_value
|
||||
{
|
||||
if (ent.classnum != 0)
|
||||
{
|
||||
@@ -339,7 +311,8 @@ namespace gsc
|
||||
return {};
|
||||
});
|
||||
|
||||
method::add("isbot", [](const game::scr_entref_t ent, const function_args&) -> scripting::script_value
|
||||
method::add("isbot", [](const game::scr_entref_t ent, const function_args&)
|
||||
-> scripting::script_value
|
||||
{
|
||||
if (ent.classnum != 0)
|
||||
{
|
||||
@@ -356,7 +329,8 @@ namespace gsc
|
||||
return game::svs_clients[client].bIsTestClient;
|
||||
});
|
||||
|
||||
method::add("arecontrolsfrozen", [](const game::scr_entref_t ent, const function_args&) -> scripting::script_value
|
||||
method::add("arecontrolsfrozen", [](const game::scr_entref_t ent, const function_args&)
|
||||
-> scripting::script_value
|
||||
{
|
||||
if (ent.classnum != 0)
|
||||
{
|
||||
@@ -370,7 +344,7 @@ namespace gsc
|
||||
throw std::runtime_error("not a player entity");
|
||||
}
|
||||
|
||||
return {(game::g_entities[client].client->flags & 4) != 0};
|
||||
return (game::g_entities[client].client->flags & 4) != 0;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
+55
-28
@@ -4,25 +4,36 @@
|
||||
|
||||
namespace gsc
|
||||
{
|
||||
enum classid
|
||||
enum class_id_t
|
||||
{
|
||||
entity,
|
||||
hudelem,
|
||||
pathnode,
|
||||
node,
|
||||
count
|
||||
class_entity,
|
||||
class_hudelem,
|
||||
class_pathnode,
|
||||
class_node,
|
||||
class_count
|
||||
};
|
||||
|
||||
using field_getter_t = std::function<scripting::script_value(unsigned int entnum)>;
|
||||
using field_setter_t = std::function<void(unsigned int entnum, const scripting::script_value&)>;
|
||||
|
||||
struct entity_field_t
|
||||
{
|
||||
std::string name;
|
||||
field_getter_t getter;
|
||||
field_setter_t setter;
|
||||
};
|
||||
|
||||
class function_args
|
||||
{
|
||||
public:
|
||||
function_args(std::vector<scripting::script_value>);
|
||||
function_args();
|
||||
function_args(const std::vector<scripting::script_value>&);
|
||||
|
||||
unsigned int size() const;
|
||||
std::vector<scripting::script_value> get_raw() const;
|
||||
scripting::value_wrap get(const int index) const;
|
||||
std::uint32_t size() const;
|
||||
const std::vector<scripting::script_value>& get_raw() const;
|
||||
scripting::value_wrap get(const std::uint32_t index) const;
|
||||
|
||||
scripting::value_wrap operator[](const int index) const
|
||||
scripting::value_wrap operator[](const std::uint32_t index) const
|
||||
{
|
||||
return this->get(index);
|
||||
}
|
||||
@@ -36,39 +47,55 @@ namespace gsc
|
||||
using script_function = std::function<scripting::script_value(const function_args&)>;
|
||||
using script_method = std::function<scripting::script_value(const game::scr_entref_t, const function_args&)>;
|
||||
|
||||
void* make_function_thunk(const char* name, const script_function* func);
|
||||
void* make_method_thunk(const char* name, const script_method* meth);
|
||||
void call_function(const script_function& function, const std::string& name);
|
||||
void call_method(const script_method& method, const std::string& name, game::scr_entref_t ent);
|
||||
|
||||
namespace function
|
||||
{
|
||||
template <typename F>
|
||||
void add(const std::string& name, F&& f)
|
||||
void add(const std::string& n, F&& f)
|
||||
{
|
||||
const auto name_str = utils::memory::duplicate_string(name);
|
||||
const auto func = new script_function(std::forward<F>(f));
|
||||
const auto thunk = reinterpret_cast<
|
||||
plutonium::sdk::interfaces::gsc::function_callback>(make_function_thunk(name_str, func));
|
||||
plugin::get()->get_interface()->gsc()->register_function(name, thunk);
|
||||
static auto done = false;
|
||||
assert(!done);
|
||||
done = true;
|
||||
|
||||
static struct
|
||||
{
|
||||
std::string name;
|
||||
script_function function;
|
||||
} ctx{n, f};
|
||||
|
||||
plugin::get()->get_interface()->gsc()->register_function(n, []()
|
||||
{
|
||||
call_function(ctx.function, ctx.name);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
namespace method
|
||||
{
|
||||
template <typename F>
|
||||
void add(const std::string& name, F&& f)
|
||||
void add(const std::string& n, F&& f)
|
||||
{
|
||||
const auto name_str = utils::memory::duplicate_string(name);
|
||||
const auto func = new script_method(std::forward<F>(f));
|
||||
const auto thunk = reinterpret_cast<
|
||||
plutonium::sdk::interfaces::gsc::method_callback>(make_method_thunk(name_str, func));
|
||||
plugin::get()->get_interface()->gsc()->register_method(name, thunk);
|
||||
static auto done = false;
|
||||
assert(!done);
|
||||
done = true;
|
||||
|
||||
static struct
|
||||
{
|
||||
std::string name;
|
||||
script_method function;
|
||||
} ctx{n, f};
|
||||
|
||||
plugin::get()->get_interface()->gsc()->register_method(n, [](plutonium::sdk::types::entref entref)
|
||||
{
|
||||
call_method(ctx.function, ctx.name, *reinterpret_cast<game::scr_entref_t*>(&entref));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
namespace field
|
||||
{
|
||||
void add(const classid classnum, const std::string& name,
|
||||
const std::function<scripting::script_value(unsigned int entnum)>& getter,
|
||||
const std::function<void(unsigned int entnum, const scripting::script_value&)>& setter);
|
||||
void add(const class_id_t classnum, const std::string& name, const field_getter_t getter, const field_setter_t& setter);
|
||||
}
|
||||
}
|
||||
@@ -102,7 +102,8 @@ namespace io
|
||||
});
|
||||
});
|
||||
|
||||
gsc::function::add("jsonprint", [](const gsc::function_args& args) -> scripting::script_value
|
||||
gsc::function::add("jsonprint", [](const gsc::function_args& args)
|
||||
-> scripting::script_value
|
||||
{
|
||||
std::string buffer;
|
||||
|
||||
@@ -189,7 +190,8 @@ namespace io
|
||||
return scripting::script_value{};
|
||||
});
|
||||
|
||||
gsc::function::add("httpget", [](const gsc::function_args& args) -> scripting::script_value
|
||||
gsc::function::add("httpget", [](const gsc::function_args& args)
|
||||
-> scripting::script_value
|
||||
{
|
||||
const auto url = args[0].as<std::string>();
|
||||
const auto object = scripting::entity(scripting::make_object());
|
||||
|
||||
@@ -20,7 +20,8 @@ namespace json
|
||||
|
||||
auto string_indexed = -1;
|
||||
const auto keys = array.get_keys();
|
||||
for (auto i = 0; i < keys.size(); i++)
|
||||
|
||||
for (auto i = 0u; i < keys.size(); i++)
|
||||
{
|
||||
const auto is_int = keys[i].is<int>();
|
||||
const auto is_string = keys[i].is<std::string>();
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
#include "game/scripting/event.hpp"
|
||||
#include "game/scripting/execution.hpp"
|
||||
#include "game/scripting/functions.hpp"
|
||||
|
||||
#include "gsc.hpp"
|
||||
|
||||
|
||||
+19
-15
@@ -7,23 +7,23 @@
|
||||
namespace userinfo
|
||||
{
|
||||
using userinfo_map = std::unordered_map<std::string, std::string>;
|
||||
std::unordered_map<int, userinfo_map> userinfo_overrides;
|
||||
std::array<userinfo_map, 18> userinfo_overrides;
|
||||
|
||||
namespace
|
||||
{
|
||||
utils::hook::detour sv_getuserinfo_hook;
|
||||
|
||||
userinfo_map userinfo_to_map(std::string userinfo)
|
||||
userinfo_map userinfo_to_map(const char* userinfo)
|
||||
{
|
||||
userinfo_map map{};
|
||||
|
||||
if (userinfo[0] == '\\')
|
||||
{
|
||||
userinfo = userinfo.substr(1);
|
||||
++userinfo;
|
||||
}
|
||||
|
||||
const auto args = utils::string::split(userinfo, '\\');
|
||||
for (size_t i = 0; !args.empty() && i < (args.size() - 1); i += 2)
|
||||
for (auto i = 0u; !args.empty() && i < (args.size() - 1); i += 2)
|
||||
{
|
||||
map[args[i]] = args[i + 1];
|
||||
}
|
||||
@@ -49,12 +49,8 @@ namespace userinfo
|
||||
void sv_getuserinfo_stub(int index, char* buffer, int bufferSize)
|
||||
{
|
||||
sv_getuserinfo_hook.invoke<void>(index, buffer, bufferSize);
|
||||
auto map = userinfo_to_map(buffer);
|
||||
|
||||
if (userinfo_overrides.find(index) == userinfo_overrides.end())
|
||||
{
|
||||
userinfo_overrides[index] = {};
|
||||
}
|
||||
auto map = userinfo_to_map(buffer);
|
||||
|
||||
for (const auto& values : userinfo_overrides[index])
|
||||
{
|
||||
@@ -80,7 +76,10 @@ namespace userinfo
|
||||
|
||||
void clear_overrides()
|
||||
{
|
||||
userinfo_overrides.clear();
|
||||
for (auto& entry : userinfo_overrides)
|
||||
{
|
||||
entry.clear();
|
||||
}
|
||||
}
|
||||
|
||||
class component final : public component_interface
|
||||
@@ -93,7 +92,8 @@ namespace userinfo
|
||||
plugin->get_interface()->callbacks()->on_player_connect(clear_client_overrides);
|
||||
plugin->get_interface()->callbacks()->on_player_disconnect(clear_client_overrides);
|
||||
|
||||
gsc::method::add("setname", [](const game::scr_entref_t ent, const gsc::function_args& args) -> scripting::script_value
|
||||
gsc::method::add("setname", [](const game::scr_entref_t ent, const gsc::function_args& args)
|
||||
-> scripting::script_value
|
||||
{
|
||||
if (ent.classnum != 0)
|
||||
{
|
||||
@@ -113,7 +113,8 @@ namespace userinfo
|
||||
return {};
|
||||
});
|
||||
|
||||
gsc::method::add("resetname", [](const game::scr_entref_t ent, const gsc::function_args&) -> scripting::script_value
|
||||
gsc::method::add("resetname", [](const game::scr_entref_t ent, const gsc::function_args&)
|
||||
-> scripting::script_value
|
||||
{
|
||||
if (ent.classnum != 0)
|
||||
{
|
||||
@@ -131,7 +132,8 @@ namespace userinfo
|
||||
return {};
|
||||
});
|
||||
|
||||
gsc::method::add("setclantag", [](const game::scr_entref_t ent, const gsc::function_args& args) -> scripting::script_value
|
||||
gsc::method::add("setclantag", [](const game::scr_entref_t ent, const gsc::function_args& args)
|
||||
-> scripting::script_value
|
||||
{
|
||||
if (ent.classnum != 0)
|
||||
{
|
||||
@@ -153,7 +155,8 @@ namespace userinfo
|
||||
return {};
|
||||
});
|
||||
|
||||
gsc::method::add("resetclantag", [](const game::scr_entref_t ent, const gsc::function_args&) -> scripting::script_value
|
||||
gsc::method::add("resetclantag", [](const game::scr_entref_t ent, const gsc::function_args&)
|
||||
-> scripting::script_value
|
||||
{
|
||||
if (ent.classnum != 0)
|
||||
{
|
||||
@@ -173,7 +176,8 @@ namespace userinfo
|
||||
return {};
|
||||
});
|
||||
|
||||
gsc::method::add("removeclantag", [](const game::scr_entref_t ent, const gsc::function_args&) -> scripting::script_value
|
||||
gsc::method::add("removeclantag", [](const game::scr_entref_t ent, const gsc::function_args&)
|
||||
-> scripting::script_value
|
||||
{
|
||||
if (ent.classnum != 0)
|
||||
{
|
||||
|
||||
@@ -2,6 +2,5 @@
|
||||
|
||||
namespace userinfo
|
||||
{
|
||||
void clear_client_overrides(int client);
|
||||
void clear_overrides();
|
||||
}
|
||||
@@ -15,30 +15,30 @@ namespace scripting
|
||||
}
|
||||
|
||||
const auto value = game::scr_VarGlob->childVariableValue[this->id_ + 0xC800 * (this->parent_id_ & 1)];
|
||||
game::VariableValue variable;
|
||||
game::VariableValue variable{};
|
||||
variable.u = value.u.u;
|
||||
variable.type = (game::scriptType_e)value.type;
|
||||
|
||||
this->value_ = variable;
|
||||
}
|
||||
|
||||
void array_value::operator=(const script_value& _value)
|
||||
void array_value::operator=(const script_value& value)
|
||||
{
|
||||
if (!this->id_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto value = _value.get_raw();
|
||||
const auto& value_raw = value.get_raw();
|
||||
|
||||
const auto variable = &game::scr_VarGlob->childVariableValue[this->id_ + 0xC800 * (this->parent_id_ & 1)];
|
||||
game::AddRefToValue(value.type, value.u);
|
||||
game::AddRefToValue(value_raw.type, value_raw.u);
|
||||
game::RemoveRefToValue(variable->type, variable->u.u);
|
||||
|
||||
variable->type = value.type;
|
||||
variable->u.u = value.u;
|
||||
variable->type = value_raw.type;
|
||||
variable->u.u = value_raw.u;
|
||||
|
||||
this->value_ = value;
|
||||
this->value_ = value_raw;
|
||||
}
|
||||
|
||||
array::array(const unsigned int id)
|
||||
@@ -170,7 +170,7 @@ namespace scripting
|
||||
return game::Scr_GetSelf(this->id_);
|
||||
}
|
||||
|
||||
unsigned int array::push(script_value value) const
|
||||
unsigned int array::push(const script_value& value) const
|
||||
{
|
||||
this->set(this->size(), value);
|
||||
return this->size();
|
||||
@@ -225,7 +225,7 @@ namespace scripting
|
||||
}
|
||||
|
||||
const auto value = game::scr_VarGlob->childVariableValue[variable_id + 0xC800 * (this->id_ & 1)];
|
||||
game::VariableValue variable;
|
||||
game::VariableValue variable{};
|
||||
variable.u = value.u.u;
|
||||
variable.type = (game::scriptType_e)value.type;
|
||||
|
||||
@@ -242,7 +242,7 @@ namespace scripting
|
||||
}
|
||||
|
||||
const auto value = game::scr_VarGlob->childVariableValue[variable_id + 0xC800 * (this->id_ & 1)];
|
||||
game::VariableValue variable;
|
||||
game::VariableValue variable{};
|
||||
variable.u = value.u.u;
|
||||
variable.type = (game::scriptType_e)value.type;
|
||||
|
||||
@@ -261,9 +261,9 @@ namespace scripting
|
||||
}
|
||||
}
|
||||
|
||||
void array::set(const std::string& key, const script_value& value_) const
|
||||
void array::set(const std::string& key, const script_value& value) const
|
||||
{
|
||||
const auto value = value_.get_raw();
|
||||
const auto& value_raw = value.get_raw();
|
||||
const auto variable_id = this->get_value_id(key);
|
||||
|
||||
if (!variable_id)
|
||||
@@ -273,16 +273,16 @@ namespace scripting
|
||||
|
||||
const auto variable = &game::scr_VarGlob->childVariableValue[variable_id + 0xC800 * (this->id_ & 1)];
|
||||
|
||||
game::AddRefToValue(value.type, value.u);
|
||||
game::AddRefToValue(value_raw.type, value_raw.u);
|
||||
game::RemoveRefToValue(variable->type, variable->u.u);
|
||||
|
||||
variable->type = value.type;
|
||||
variable->u.u = value.u;
|
||||
variable->type = value_raw.type;
|
||||
variable->u.u = value_raw.u;
|
||||
}
|
||||
|
||||
void array::set(const unsigned int index, const script_value& value_) const
|
||||
void array::set(const unsigned int index, const script_value& value) const
|
||||
{
|
||||
const auto value = value_.get_raw();
|
||||
const auto& value_raw = value.get_raw();
|
||||
const auto variable_id = this->get_value_id(index);
|
||||
|
||||
if (!variable_id)
|
||||
@@ -292,11 +292,11 @@ namespace scripting
|
||||
|
||||
const auto variable = &game::scr_VarGlob->childVariableValue[variable_id + 0xC800 * (this->id_ & 1)];
|
||||
|
||||
game::AddRefToValue(value.type, value.u);
|
||||
game::AddRefToValue(value_raw.type, value_raw.u);
|
||||
game::RemoveRefToValue(variable->type, variable->u.u);
|
||||
|
||||
variable->type = value.type;
|
||||
variable->u.u = value.u;
|
||||
variable->type = value_raw.type;
|
||||
variable->u.u = value_raw.u;
|
||||
}
|
||||
|
||||
unsigned int array::get_entity_id() const
|
||||
@@ -320,6 +320,7 @@ namespace scripting
|
||||
unsigned int array::get_value_id(const unsigned int index) const
|
||||
{
|
||||
const auto variable_id = game::FindVariable(this->id_, (index - 0x800000) & 0xFFFFFF);
|
||||
|
||||
if (!variable_id)
|
||||
{
|
||||
return game::GetNewArrayVariable(this->id_, index);
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace scripting
|
||||
std::vector<script_value> get_keys() const;
|
||||
unsigned int size() const;
|
||||
|
||||
unsigned int push(script_value) const;
|
||||
unsigned int push(const script_value&) const;
|
||||
void erase(const unsigned int) const;
|
||||
void erase(const std::string&) const;
|
||||
script_value pop() const;
|
||||
@@ -69,12 +69,12 @@ namespace scripting
|
||||
{
|
||||
if (key.is<I>())
|
||||
{
|
||||
return { this->id_, this->get_value_id(key.as<I>()) };
|
||||
return {this->id_, this->get_value_id(key.as<I>())};
|
||||
}
|
||||
|
||||
if (key.is<S>())
|
||||
{
|
||||
return { this->id_, this->get_value_id(key.as<S>()) };
|
||||
return {this->id_, this->get_value_id(key.as<S>())};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,10 +11,9 @@ namespace scripting
|
||||
|
||||
script_value function::get_raw() const
|
||||
{
|
||||
game::VariableValue value;
|
||||
game::VariableValue value{};
|
||||
value.type = game::SCRIPT_FUNCTION;
|
||||
value.u.codePosValue = this->pos_;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -23,7 +22,7 @@ namespace scripting
|
||||
return this->pos_;
|
||||
}
|
||||
|
||||
script_value function::call(const entity& self, std::vector<script_value> arguments) const
|
||||
script_value function::call(const entity& self, const std::vector<script_value>& arguments) const
|
||||
{
|
||||
return exec_ent_thread(self, this->pos_, arguments);
|
||||
}
|
||||
|
||||
@@ -12,14 +12,14 @@ namespace scripting
|
||||
script_value get_raw() const;
|
||||
const char* get_pos() const;
|
||||
|
||||
script_value call(const entity& self, std::vector<script_value> arguments) const;
|
||||
script_value call(const entity& self, const std::vector<script_value>& arguments) const;
|
||||
|
||||
script_value operator()(const entity& self, std::vector<script_value> arguments) const
|
||||
script_value operator()(const entity& self, const std::vector<script_value>& arguments) const
|
||||
{
|
||||
return this->call(self, arguments);
|
||||
}
|
||||
|
||||
script_value operator()(std::vector<script_value> arguments) const
|
||||
script_value operator()(const std::vector<script_value>& arguments) const
|
||||
{
|
||||
return this->call(*game::levelEntityId, arguments);
|
||||
}
|
||||
@@ -28,7 +28,9 @@ namespace scripting
|
||||
{
|
||||
return this->call(*game::levelEntityId, {});
|
||||
}
|
||||
|
||||
private:
|
||||
const char* pos_;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
#include <stdinc.hpp>
|
||||
#include "functions.hpp"
|
||||
|
||||
#include <utils/string.hpp>
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#pragma once
|
||||
#include "game/game.hpp"
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
using script_function = void(*)(game::scr_entref_t);
|
||||
}
|
||||
@@ -321,7 +321,7 @@ namespace scripting
|
||||
return this->value_.get();
|
||||
}
|
||||
|
||||
value_wrap::value_wrap(const scripting::script_value& value, int argument_index)
|
||||
value_wrap::value_wrap(const scripting::script_value& value, const std::uint32_t argument_index)
|
||||
: value_(value)
|
||||
, argument_index_(argument_index)
|
||||
{
|
||||
|
||||
@@ -164,7 +164,7 @@ namespace scripting
|
||||
class value_wrap
|
||||
{
|
||||
public:
|
||||
value_wrap(const scripting::script_value& value, int argument_index);
|
||||
value_wrap(const scripting::script_value& value, const std::uint32_t);
|
||||
|
||||
template <typename T>
|
||||
T as() const
|
||||
@@ -179,7 +179,7 @@ namespace scripting
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename I = int>
|
||||
template <typename T>
|
||||
T* as_ptr()
|
||||
{
|
||||
try
|
||||
@@ -203,7 +203,7 @@ namespace scripting
|
||||
return this->value_.get_raw();
|
||||
}
|
||||
|
||||
int argument_index_{};
|
||||
std::uint32_t argument_index_{};
|
||||
scripting::script_value value_;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -26,6 +26,6 @@ namespace scripting
|
||||
void set_z(float value);
|
||||
|
||||
private:
|
||||
game::vec3_t value_{ 0 };
|
||||
game::vec3_t value_{};
|
||||
};
|
||||
}
|
||||
@@ -48,6 +48,7 @@ namespace game
|
||||
WEAK symbol<void()> Scr_MakeArray{0x56ADE0};
|
||||
WEAK symbol<void(unsigned int stringValue)> Scr_AddArrayStringIndexed{0x56AE70};
|
||||
WEAK symbol<void(unsigned int classnum, unsigned int name, unsigned int canonicalString, unsigned int offset)> Scr_AddClassField{0x567CD0};
|
||||
WEAK symbol<void()> Scr_ErrorInternal{0x568FD0};
|
||||
|
||||
WEAK symbol<unsigned int(const char* str, unsigned int user)> SL_GetString{0x5649E0};
|
||||
WEAK symbol<unsigned int(const char* str)> SL_GetCanonicalString{0x5619A0};
|
||||
|
||||
Reference in New Issue
Block a user