diff --git a/src/component/command.cpp b/src/component/command.cpp index 30b5bde..c01196f 100644 --- a/src/component/command.cpp +++ b/src/component/command.cpp @@ -130,12 +130,12 @@ namespace command { scripting::on_shutdown(clear_script_commands); - gsc::function::add("executecommand", [](const std::string& command) + const auto execute_command = [](const std::string& command) { execute(command, false); - }); + }; - gsc::function::add("addcommand", [](const std::string& name, const scripting::function& function) + const auto add_command = [](const std::string& name, const scripting::function& function) { command::add_script_command(name, [function](const command::params& params) { @@ -148,7 +148,28 @@ namespace command function({array}); }); - }); + }; + + gsc::function::add_multiple([](const std::string& command) + { + execute(command, false); + }, "executecommand", "command::execute"); + + + gsc::function::add_multiple([](const std::string& name, const scripting::function& function) + { + command::add_script_command(name, [function](const command::params& params) + { + scripting::array array; + + for (auto i = 0; i < params.size(); i++) + { + array.push(params[i]); + } + + function({array}); + }); + }, "addcommand", "command::add"); } }; } diff --git a/src/component/gsc.cpp b/src/component/gsc.cpp index a3cae8f..5444a09 100644 --- a/src/component/gsc.cpp +++ b/src/component/gsc.cpp @@ -171,6 +171,42 @@ namespace gsc { scr_settings_hook.invoke(developer_script, developer_script, 0, inst); } + + utils::hook::detour scr_get_builtin_hook; + unsigned int scr_get_builtin_stub(int inst, game::sval_u func_name) + { + const auto type = *reinterpret_cast(func_name.block); + if (type != 28) + { + return scr_get_builtin_hook.invoke(inst, func_name); + } + + const auto func_namea = *reinterpret_cast(reinterpret_cast(func_name.block) + 4); + const auto typea = *reinterpret_cast(func_namea); + if (typea != 20) + { + return scr_get_builtin_hook.invoke(inst, func_name); + } + + const auto func_nameb = *reinterpret_cast(reinterpret_cast(func_namea) + 4); + const auto typeb = *reinterpret_cast(func_nameb); + + if (typeb == 23) // script::function type call + { + const auto namespace_ = game::SL_ConvertToString( + *reinterpret_cast(reinterpret_cast(func_nameb) + 4), game::SCRIPTINSTANCE_SERVER); + const auto name = game::SL_ConvertToString( + *reinterpret_cast(reinterpret_cast(func_nameb) + 8), game::SCRIPTINSTANCE_SERVER); + + const auto full_name = utils::string::va("%s::%s", namespace_, name); + if (functions.find(full_name) != functions.end()) + { + return game::SL_GetString(full_name, 0, game::SCRIPTINSTANCE_SERVER); + } + } + + return scr_get_builtin_hook.invoke(inst, func_name); + } } namespace function @@ -209,6 +245,8 @@ namespace gsc get_function_hook.create(utils::hook::extract(SELECT_VALUE(0x8A02FB, 0x8DE11B) + 1), get_function_stub); get_method_hook.create(utils::hook::extract(SELECT_VALUE(0x8A052E, 0x8DE34E) + 1), get_method_stub); + scr_get_builtin_hook.create(SELECT_VALUE(0x4ACAC0, 0x411490), scr_get_builtin_stub); + // \n******* script runtime error *******\n%s\n utils::hook::set(SELECT_VALUE(0x9FC5C0 + 40, 0xAABA68 + 40), '\n'); utils::hook::set(SELECT_VALUE(0x9FC5C0 + 41, 0xAABA68 + 41), '\0'); @@ -225,13 +263,10 @@ namespace gsc return array; }); - const auto typeof = [](const scripting::script_value& value) + gsc::function::add_multiple([](const scripting::script_value& value) { return value.type_name(); - }; - - gsc::function::add("typeof", typeof); - gsc::function::add("type", typeof); + }, "typeof", "type"); } }; } diff --git a/src/component/gsc.hpp b/src/component/gsc.hpp index 67cfc24..6ebf3ca 100644 --- a/src/component/gsc.hpp +++ b/src/component/gsc.hpp @@ -56,6 +56,13 @@ namespace gsc { add_internal(name, wrap_function(f)); } + + template + void add_multiple(F f, Args&& ...names) + { + const auto wrap = wrap_function(f); + (add_internal(names, wrap), ...); + } } namespace method @@ -67,5 +74,12 @@ namespace gsc { add_internal(name, wrap_function(f)); } + + template + void add_multiple(F f, Args&& ...names) + { + const auto wrap = wrap_function(f); + (add_internal(names, wrap), ...); + } } } diff --git a/src/component/string.cpp b/src/component/string.cpp index b0830aa..ecf99cd 100644 --- a/src/component/string.cpp +++ b/src/component/string.cpp @@ -24,7 +24,7 @@ namespace string // lua/lstrlib.c const char* getformat(const char* strfrmt, char* form) { - const auto len = strspn(strfrmt, L_FMTFLAGSF "123456789.") + 1; + const auto len = std::strspn(strfrmt, L_FMTFLAGSF "123456789.") + 1; if (len >= MAX_FORMAT - 10) { throw std::runtime_error("invalid format (too long)"); @@ -162,9 +162,8 @@ namespace string public: void post_unpack() override { - gsc::function::add("va", format_string); - gsc::function::add("formatstring", format_string); - gsc::function::add("sprintf", format_string); + gsc::function::add_multiple(format_string, "va", "string::va", + "formatstring", "string::format", "sprintf"); gsc::function::add("printf", [](const std::string& fmt, const scripting::variadic_args& va) { @@ -179,6 +178,14 @@ namespace string } printf("\n"); }); + + gsc::function::add_multiple(utils::string::to_upper, "toupper", "string::toupper"); + gsc::function::add_multiple(utils::string::to_lower, "tolower", "string::tolower"); + + gsc::function::add("string::isnumeric", utils::string::is_numeric); + gsc::function::add("string::startswith", utils::string::starts_with); + gsc::function::add("string::endswith", utils::string::ends_with); + gsc::function::add("string::replace", utils::string::replace); } }; } diff --git a/src/game/structs.hpp b/src/game/structs.hpp index fc04743..488fd77 100644 --- a/src/game/structs.hpp +++ b/src/game/structs.hpp @@ -767,4 +767,19 @@ namespace game { ScriptParseTree* scriptParseTree; }; + + union sval_u + { + unsigned __int8 type; + unsigned int stringValue; + unsigned int idValue; + float floatValue; + int intValue; + sval_u* node; + unsigned int sourcePosValue; + const char* codePosValue; + const char* debugString; + void* block; + }; + } \ No newline at end of file