mirror of
https://github.com/alicealys/t5-gsc-utils.git
synced 2025-04-19 12:32:53 +00:00
Finish scripting::object + add some functions
This commit is contained in:
parent
7f553cba0e
commit
6165f07275
@ -305,6 +305,35 @@ namespace gsc
|
|||||||
|
|
||||||
return count;
|
return count;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
gsc::function::add("toint", [](const std::string& str, const scripting::variadic_args& va)
|
||||||
|
{
|
||||||
|
auto radix = 10;
|
||||||
|
if (va.size() > 0)
|
||||||
|
{
|
||||||
|
radix = va[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast<int>(std::strtoull(str.data(), nullptr, radix));
|
||||||
|
});
|
||||||
|
|
||||||
|
gsc::function::add("os::date", [](const scripting::variadic_args& va)
|
||||||
|
{
|
||||||
|
std::string format = "%Y-%m-%dT%H:%M:%S%z";
|
||||||
|
if (va.size() > 0)
|
||||||
|
{
|
||||||
|
format = va[0].as<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
tm ltime{};
|
||||||
|
char timestamp[MAX_PATH] = {0};
|
||||||
|
const auto time = _time64(nullptr);
|
||||||
|
|
||||||
|
_localtime64_s(<ime, &time);
|
||||||
|
std::strftime(timestamp, sizeof(timestamp) - 1, format.data(), <ime);
|
||||||
|
|
||||||
|
return std::string(timestamp);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,7 @@ namespace json
|
|||||||
|
|
||||||
nlohmann::json gsc_to_json(scripting::script_value value, bool print_id)
|
nlohmann::json gsc_to_json(scripting::script_value value, bool print_id)
|
||||||
{
|
{
|
||||||
const auto variable = value.get_raw();
|
const auto& variable = value.get_raw();
|
||||||
|
|
||||||
if (value.is<int>())
|
if (value.is<int>())
|
||||||
{
|
{
|
||||||
@ -131,28 +131,24 @@ namespace json
|
|||||||
return object_to_json(variable.u.uintValue, print_id);
|
return object_to_json(variable.u.uintValue, print_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value.is<scripting::function>())
|
|
||||||
{
|
|
||||||
const auto function = value.as<scripting::function>();
|
|
||||||
return utils::string::va("[[ %s ]]", function.get_name().data());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (variable.type == game::SCRIPT_NONE)
|
if (variable.type == game::SCRIPT_NONE)
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: scripting component, gsc is way different in BO1 than BO2 :/
|
if (value.is<scripting::function>())
|
||||||
|
{
|
||||||
|
return "[function]";
|
||||||
|
}
|
||||||
|
|
||||||
if (variable.type == game::SCRIPT_CODEPOS)
|
if (variable.type == game::SCRIPT_CODEPOS)
|
||||||
{
|
{
|
||||||
// const auto function = scripting::find_function(variable.u.codePosValue);
|
return "[codepos]";
|
||||||
return utils::string::va("[codepos]");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (variable.type == game::SCRIPT_END)
|
if (variable.type == game::SCRIPT_END)
|
||||||
{
|
{
|
||||||
// const auto function = scripting::find_function(variable.u.codePosValue);
|
return "[precodepos]";
|
||||||
return utils::string::va("[precodepos]");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return utils::string::va("[%s]", value.type_name().data());
|
return utils::string::va("[%s]", value.type_name().data());
|
||||||
|
@ -23,13 +23,21 @@ namespace scripting
|
|||||||
std::unordered_map<std::string, std::vector<std::pair<std::string, const char*>>> script_function_table_sort;
|
std::unordered_map<std::string, std::vector<std::pair<std::string, const char*>>> script_function_table_sort;
|
||||||
std::unordered_map<const char*, std::pair<std::string, std::string>> script_function_table_rev;
|
std::unordered_map<const char*, std::pair<std::string, std::string>> script_function_table_rev;
|
||||||
|
|
||||||
|
std::unordered_map<unsigned int, std::string> canonical_string_table;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
utils::hook::detour g_shutdown_game_hook;
|
utils::hook::detour g_shutdown_game_hook;
|
||||||
|
utils::hook::detour sl_get_canonical_string_hook;
|
||||||
|
|
||||||
std::vector<std::function<void()>> shutdown_callbacks;
|
std::vector<std::function<void()>> shutdown_callbacks;
|
||||||
void g_shutdown_game_stub(const int free_scripts)
|
void g_shutdown_game_stub(const int free_scripts)
|
||||||
{
|
{
|
||||||
|
if (free_scripts)
|
||||||
|
{
|
||||||
|
canonical_string_table.clear();
|
||||||
|
}
|
||||||
|
|
||||||
for (const auto& callback : shutdown_callbacks)
|
for (const auto& callback : shutdown_callbacks)
|
||||||
{
|
{
|
||||||
callback();
|
callback();
|
||||||
@ -37,6 +45,18 @@ namespace scripting
|
|||||||
|
|
||||||
return g_shutdown_game_hook.invoke<void>(free_scripts);
|
return g_shutdown_game_hook.invoke<void>(free_scripts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int sl_transfer_canonical_string_stub(game::scriptInstance_t inst, unsigned int string_value)
|
||||||
|
{
|
||||||
|
const auto result = sl_get_canonical_string_hook.invoke<unsigned int>(inst, string_value);
|
||||||
|
const auto str = game::SL_ConvertToString(string_value, inst);
|
||||||
|
if (str)
|
||||||
|
{
|
||||||
|
canonical_string_table[result] = game::SL_ConvertToString(string_value, inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_shutdown(const std::function<void()>& callback)
|
void on_shutdown(const std::function<void()>& callback)
|
||||||
@ -50,6 +70,7 @@ namespace scripting
|
|||||||
void post_unpack() override
|
void post_unpack() override
|
||||||
{
|
{
|
||||||
g_shutdown_game_hook.create(SELECT_VALUE(0x607700, 0x540950), g_shutdown_game_stub);
|
g_shutdown_game_hook.create(SELECT_VALUE(0x607700, 0x540950), g_shutdown_game_stub);
|
||||||
|
sl_get_canonical_string_hook.create(SELECT_VALUE(0x5F3F40, 0x622530), sl_transfer_canonical_string_stub);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,8 @@ namespace scripting
|
|||||||
extern std::unordered_map<std::string, game::BuiltinMethodDef> method_map;
|
extern std::unordered_map<std::string, game::BuiltinMethodDef> method_map;
|
||||||
extern std::unordered_map<std::string, game::BuiltinFunctionDef> function_map;
|
extern std::unordered_map<std::string, game::BuiltinFunctionDef> function_map;
|
||||||
|
|
||||||
|
extern std::unordered_map<unsigned int, std::string> canonical_string_table;
|
||||||
|
|
||||||
using script_function = void(*)(game::scr_entref_t);
|
using script_function = void(*)(game::scr_entref_t);
|
||||||
|
|
||||||
void on_shutdown(const std::function<void()>& callback);
|
void on_shutdown(const std::function<void()>& callback);
|
||||||
|
@ -2,46 +2,145 @@
|
|||||||
#include "object.hpp"
|
#include "object.hpp"
|
||||||
#include "execution.hpp"
|
#include "execution.hpp"
|
||||||
|
|
||||||
|
#include "../../component/scripting.hpp"
|
||||||
|
|
||||||
namespace scripting
|
namespace scripting
|
||||||
{
|
{
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
std::string get_string(unsigned int canonical_string)
|
||||||
|
{
|
||||||
|
if (canonical_string_table.find(canonical_string) != canonical_string_table.end())
|
||||||
|
{
|
||||||
|
return canonical_string_table[canonical_string];
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int get_canonical_string(const std::string& str)
|
||||||
|
{
|
||||||
|
for (const auto& value : canonical_string_table)
|
||||||
|
{
|
||||||
|
if (value.second == str)
|
||||||
|
{
|
||||||
|
return value.first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return game::SL_GetCanonicalString(game::SCRIPTINSTANCE_SERVER, str.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> get_keys_sp(unsigned int id)
|
||||||
|
{
|
||||||
|
std::vector<std::string> result;
|
||||||
|
|
||||||
|
auto current = game::scr_VarGlob->variableList_sp[id + 1].nextSibling;
|
||||||
|
|
||||||
|
while (current)
|
||||||
|
{
|
||||||
|
const auto var = &game::scr_VarGlob->variableList_sp[current + 0x6000];
|
||||||
|
const auto key_value = get_string(var->w.status >> 8);
|
||||||
|
result.push_back(key_value);
|
||||||
|
|
||||||
|
const auto next_sibling = game::scr_VarGlob->variableList_sp[current + 0x6000].nextSibling;
|
||||||
|
if (!next_sibling)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = static_cast<unsigned __int16>(game::scr_VarGlob->variableList_sp[next_sibling + 0x6000].id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> get_keys_mp(unsigned int id)
|
||||||
|
{
|
||||||
|
std::vector<std::string> result;
|
||||||
|
|
||||||
|
auto current = game::scr_VarGlob->variableList_mp[id + 1].nextSibling;
|
||||||
|
|
||||||
|
while (current)
|
||||||
|
{
|
||||||
|
const auto var = &game::scr_VarGlob->variableList_mp[current + 0x8000];
|
||||||
|
const auto key_value = get_string(var->w.status >> 8);
|
||||||
|
result.push_back(key_value);
|
||||||
|
|
||||||
|
const auto next_sibling = game::scr_VarGlob->variableList_mp[current + 0x8000].nextSibling;
|
||||||
|
if (!next_sibling)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = game::scr_VarGlob->variableList_mp[next_sibling + 0x8000].hash.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
object_value::object_value(unsigned int parent_id, unsigned int id)
|
object_value::object_value(unsigned int parent_id, unsigned int id)
|
||||||
: id_(id)
|
: id_(id)
|
||||||
, parent_id_(parent_id)
|
, parent_id_(parent_id)
|
||||||
{
|
{
|
||||||
/*if (!this->id_)
|
if (!this->id_)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto value = game::scr_VarGlob->childVariableValue[this->id_];
|
game::VariableValue variable_{};
|
||||||
game::VariableValue variable;
|
|
||||||
variable.u = value.u.u;
|
|
||||||
variable.type = (game::scriptType_e)value.type;
|
|
||||||
|
|
||||||
this->value_ = variable;*/
|
if (game::environment::is_sp())
|
||||||
|
{
|
||||||
|
const auto variable = &game::scr_VarGlob->variableList_sp[this->id_ + 0x6000];
|
||||||
|
variable_.type = variable->w.type & 0x1F;
|
||||||
|
variable_.u = variable->u.u;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto variable = &game::scr_VarGlob->variableList_mp[this->id_ + 0x8000];
|
||||||
|
variable_.type = variable->w.type & 0x1F;
|
||||||
|
variable_.u = variable->u.u;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->value_ = variable_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void object_value::operator=(const script_value& /*value*/)
|
void object_value::operator=(const script_value& value)
|
||||||
{
|
{
|
||||||
/*if (!this->id_)
|
if (!this->id_)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto value = _value.get_raw();
|
const auto& value_0 = value.get_raw();
|
||||||
|
|
||||||
const auto variable = &game::scr_VarGlob->childVariableValue[this->id_];
|
game::VariableValue previous{};
|
||||||
game::VariableValue variable_{};
|
|
||||||
variable_.type = variable->type;
|
|
||||||
variable_.u = variable->u.u;
|
|
||||||
|
|
||||||
game::AddRefToValue(game::SCRIPTINSTANCE_SERVER, &value);
|
if (game::environment::is_sp())
|
||||||
game::RemoveRefToValue(game::SCRIPTINSTANCE_SERVER, variable->type, variable->u.u);
|
{
|
||||||
|
const auto variable = &game::scr_VarGlob->variableList_sp[this->id_ + 0x6000];
|
||||||
|
previous.type = variable->w.type & 0x1F;
|
||||||
|
previous.u = variable->u.u;
|
||||||
|
|
||||||
variable->type = gsl::narrow_cast<char>(value.type);
|
variable->w.type |= value_0.type;
|
||||||
variable->u.u = value.u;
|
variable->u.u = value_0.u;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto variable = &game::scr_VarGlob->variableList_mp[this->id_ + 0x8000];
|
||||||
|
previous.type = variable->w.type & 0x1F;
|
||||||
|
previous.u = variable->u.u;
|
||||||
|
|
||||||
this->value_ = value;*/
|
variable->w.type |= value_0.type;
|
||||||
|
variable->u.u = value_0.u;
|
||||||
|
}
|
||||||
|
|
||||||
|
game::AddRefToValue(game::SCRIPTINSTANCE_SERVER, &value_0);
|
||||||
|
game::RemoveRefToValue(game::SCRIPTINSTANCE_SERVER, previous.type, previous.u);
|
||||||
|
|
||||||
|
this->value_ = value_0;
|
||||||
}
|
}
|
||||||
|
|
||||||
object::object(const unsigned int id)
|
object::object(const unsigned int id)
|
||||||
@ -121,25 +220,7 @@ namespace scripting
|
|||||||
|
|
||||||
std::vector<std::string> object::get_keys() const
|
std::vector<std::string> object::get_keys() const
|
||||||
{
|
{
|
||||||
std::vector<std::string> result;
|
return SELECT_VALUE(get_keys_sp, get_keys_mp)(this->id_);
|
||||||
|
|
||||||
/*auto current = game::scr_VarGlob->objectVariableChildren[this->id_].firstChild;
|
|
||||||
|
|
||||||
while (current)
|
|
||||||
{
|
|
||||||
const auto var = game::scr_VarGlob->childVariableValue[current];
|
|
||||||
const auto string_id = (unsigned __int8)var.name_lo + (var.k.keys.name_hi << 8);
|
|
||||||
|
|
||||||
if (string_id < 0x34BC)
|
|
||||||
{
|
|
||||||
const auto string = reinterpret_cast<const char**>(SELECT_VALUE(0x2DACC28, 0x2D7CF28))[string_id];
|
|
||||||
result.push_back(string);
|
|
||||||
}
|
|
||||||
|
|
||||||
current = var.nextSibling;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int object::size() const
|
unsigned int object::size() const
|
||||||
@ -157,9 +238,9 @@ namespace scripting
|
|||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
script_value object::get(const std::string& /*key*/) const
|
script_value object::get(const std::string& key) const
|
||||||
{
|
{
|
||||||
/*const auto string_value = game::SL_GetCanonicalString(key.data(), 0);
|
const auto string_value = get_canonical_string(key);
|
||||||
const auto variable_id = game::FindVariable(game::SCRIPTINSTANCE_SERVER, this->id_, string_value);
|
const auto variable_id = game::FindVariable(game::SCRIPTINSTANCE_SERVER, this->id_, string_value);
|
||||||
|
|
||||||
if (!variable_id)
|
if (!variable_id)
|
||||||
@ -167,18 +248,27 @@ namespace scripting
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto value = game::scr_VarGlob->childVariableValue[variable_id];
|
game::VariableValue variable_{};
|
||||||
game::VariableValue variable;
|
|
||||||
variable.u = value.u.u;
|
|
||||||
variable.type = (game::scriptType_e)value.type;
|
|
||||||
|
|
||||||
return variable;*/
|
if (game::environment::is_sp())
|
||||||
return {};
|
{
|
||||||
|
const auto variable = &game::scr_VarGlob->variableList_sp[variable_id + 0x6000];
|
||||||
|
variable_.type = variable->w.type & 0x1F;
|
||||||
|
variable_.u = variable->u.u;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto variable = &game::scr_VarGlob->variableList_mp[variable_id + 0x8000];
|
||||||
|
variable_.type = variable->w.type & 0x1F;
|
||||||
|
variable_.u = variable->u.u;
|
||||||
|
}
|
||||||
|
|
||||||
|
return variable_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void object::set(const std::string& /*key*/, const script_value& /*value*/) const
|
void object::set(const std::string& key, const script_value& value) const
|
||||||
{
|
{
|
||||||
/*const auto value = value_.get_raw();
|
const auto& value_ = value.get_raw();
|
||||||
const auto variable_id = this->get_value_id(key);
|
const auto variable_id = this->get_value_id(key);
|
||||||
|
|
||||||
if (!variable_id)
|
if (!variable_id)
|
||||||
@ -186,16 +276,29 @@ namespace scripting
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto variable = &game::scr_VarGlob->childVariableValue[variable_id];
|
game::VariableValue previous{};
|
||||||
game::VariableValue variable_{};
|
|
||||||
variable_.type = variable->type;
|
|
||||||
variable_.u = variable->u.u;
|
|
||||||
|
|
||||||
game::AddRefToValue(game::SCRIPTINSTANCE_SERVER, &value);
|
if (game::environment::is_sp())
|
||||||
game::RemoveRefToValue(game::SCRIPTINSTANCE_SERVER, variable_.type, variable_.u);
|
{
|
||||||
|
const auto variable = &game::scr_VarGlob->variableList_sp[variable_id + 0x6000];
|
||||||
|
previous.type = variable->w.type & 0x1F;
|
||||||
|
previous.u = variable->u.u;
|
||||||
|
|
||||||
variable->type = gsl::narrow_cast<char>(value.type);
|
variable->w.type |= value_.type;
|
||||||
variable->u.u = value.u;*/
|
variable->u.u = value_.u;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const auto variable = &game::scr_VarGlob->variableList_mp[variable_id + 0x8000];
|
||||||
|
previous.type = variable->w.type & 0x1F;
|
||||||
|
previous.u = variable->u.u;
|
||||||
|
|
||||||
|
variable->w.type |= value_.type;
|
||||||
|
variable->u.u = value_.u;
|
||||||
|
}
|
||||||
|
|
||||||
|
game::AddRefToValue(game::SCRIPTINSTANCE_SERVER, &value_);
|
||||||
|
game::RemoveRefToValue(game::SCRIPTINSTANCE_SERVER, previous.type, previous.u);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int object::get_entity_id() const
|
unsigned int object::get_entity_id() const
|
||||||
@ -205,7 +308,7 @@ namespace scripting
|
|||||||
|
|
||||||
unsigned int object::get_value_id(const std::string& key) const
|
unsigned int object::get_value_id(const std::string& key) const
|
||||||
{
|
{
|
||||||
const auto string_value = game::SL_GetCanonicalString(key.data(), 0);
|
const auto string_value = get_canonical_string(key);
|
||||||
const auto variable_id = game::FindVariable(game::SCRIPTINSTANCE_SERVER, this->id_, string_value);
|
const auto variable_id = game::FindVariable(game::SCRIPTINSTANCE_SERVER, this->id_, string_value);
|
||||||
|
|
||||||
if (!variable_id)
|
if (!variable_id)
|
||||||
|
@ -75,7 +75,7 @@ namespace game
|
|||||||
|
|
||||||
WEAK symbol<unsigned int(const char* str, unsigned int user, scriptInstance_t inst)> SL_GetString{0x463130, 0x4B1770};
|
WEAK symbol<unsigned int(const char* str, unsigned int user, scriptInstance_t inst)> SL_GetString{0x463130, 0x4B1770};
|
||||||
WEAK symbol<const char*(unsigned int stringValue, scriptInstance_t inst)> SL_ConvertToString{0x687530, 0x624C70};
|
WEAK symbol<const char*(unsigned int stringValue, scriptInstance_t inst)> SL_ConvertToString{0x687530, 0x624C70};
|
||||||
WEAK symbol<unsigned int(const char* str, bool is_static)> SL_GetCanonicalString{0x0, 0x0};
|
WEAK symbol<unsigned int(scriptInstance_t inst, const char* str)> SL_GetCanonicalString{0x4FB120, 0x68D860};
|
||||||
|
|
||||||
WEAK symbol<int(scriptInstance_t inst)> Scr_GetNumParam{0x0, 0x0};
|
WEAK symbol<int(scriptInstance_t inst)> Scr_GetNumParam{0x0, 0x0};
|
||||||
WEAK symbol<gentity_s*(scriptInstance_t inst, int index)> Scr_GetEntity{0x0, 0x0};
|
WEAK symbol<gentity_s*(scriptInstance_t inst, int index)> Scr_GetEntity{0x0, 0x0};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user