mirror of
https://github.com/alicealys/t5-gsc-utils.git
synced 2025-04-19 04:22:54 +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;
|
||||
});
|
||||
|
||||
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)
|
||||
{
|
||||
const auto variable = value.get_raw();
|
||||
const auto& variable = value.get_raw();
|
||||
|
||||
if (value.is<int>())
|
||||
{
|
||||
@ -131,28 +131,24 @@ namespace json
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
// const auto function = scripting::find_function(variable.u.codePosValue);
|
||||
return utils::string::va("[codepos]");
|
||||
return "[codepos]";
|
||||
}
|
||||
|
||||
if (variable.type == game::SCRIPT_END)
|
||||
{
|
||||
// const auto function = scripting::find_function(variable.u.codePosValue);
|
||||
return utils::string::va("[precodepos]");
|
||||
return "[precodepos]";
|
||||
}
|
||||
|
||||
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<const char*, std::pair<std::string, std::string>> script_function_table_rev;
|
||||
|
||||
std::unordered_map<unsigned int, std::string> canonical_string_table;
|
||||
|
||||
namespace
|
||||
{
|
||||
utils::hook::detour g_shutdown_game_hook;
|
||||
utils::hook::detour sl_get_canonical_string_hook;
|
||||
|
||||
std::vector<std::function<void()>> shutdown_callbacks;
|
||||
void g_shutdown_game_stub(const int free_scripts)
|
||||
{
|
||||
if (free_scripts)
|
||||
{
|
||||
canonical_string_table.clear();
|
||||
}
|
||||
|
||||
for (const auto& callback : shutdown_callbacks)
|
||||
{
|
||||
callback();
|
||||
@ -37,6 +45,18 @@ namespace scripting
|
||||
|
||||
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)
|
||||
@ -50,6 +70,7 @@ namespace scripting
|
||||
void post_unpack() override
|
||||
{
|
||||
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::BuiltinFunctionDef> function_map;
|
||||
|
||||
extern std::unordered_map<unsigned int, std::string> canonical_string_table;
|
||||
|
||||
using script_function = void(*)(game::scr_entref_t);
|
||||
|
||||
void on_shutdown(const std::function<void()>& callback);
|
||||
|
@ -2,46 +2,145 @@
|
||||
#include "object.hpp"
|
||||
#include "execution.hpp"
|
||||
|
||||
#include "../../component/scripting.hpp"
|
||||
|
||||
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)
|
||||
: id_(id)
|
||||
, parent_id_(parent_id)
|
||||
{
|
||||
/*if (!this->id_)
|
||||
if (!this->id_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto value = game::scr_VarGlob->childVariableValue[this->id_];
|
||||
game::VariableValue variable;
|
||||
variable.u = value.u.u;
|
||||
variable.type = (game::scriptType_e)value.type;
|
||||
game::VariableValue variable_{};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
const auto value = _value.get_raw();
|
||||
const auto& value_0 = value.get_raw();
|
||||
|
||||
const auto variable = &game::scr_VarGlob->childVariableValue[this->id_];
|
||||
game::VariableValue variable_{};
|
||||
variable_.type = variable->type;
|
||||
variable_.u = variable->u.u;
|
||||
game::VariableValue previous{};
|
||||
|
||||
game::AddRefToValue(game::SCRIPTINSTANCE_SERVER, &value);
|
||||
game::RemoveRefToValue(game::SCRIPTINSTANCE_SERVER, variable->type, variable->u.u);
|
||||
if (game::environment::is_sp())
|
||||
{
|
||||
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->u.u = value.u;
|
||||
variable->w.type |= value_0.type;
|
||||
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)
|
||||
@ -121,25 +220,7 @@ namespace scripting
|
||||
|
||||
std::vector<std::string> object::get_keys() const
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
|
||||
/*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;
|
||||
return SELECT_VALUE(get_keys_sp, get_keys_mp)(this->id_);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if (!variable_id)
|
||||
@ -167,18 +248,27 @@ namespace scripting
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto value = game::scr_VarGlob->childVariableValue[variable_id];
|
||||
game::VariableValue variable;
|
||||
variable.u = value.u.u;
|
||||
variable.type = (game::scriptType_e)value.type;
|
||||
game::VariableValue variable_{};
|
||||
|
||||
return variable;*/
|
||||
return {};
|
||||
if (game::environment::is_sp())
|
||||
{
|
||||
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);
|
||||
|
||||
if (!variable_id)
|
||||
@ -186,16 +276,29 @@ namespace scripting
|
||||
return;
|
||||
}
|
||||
|
||||
const auto variable = &game::scr_VarGlob->childVariableValue[variable_id];
|
||||
game::VariableValue variable_{};
|
||||
variable_.type = variable->type;
|
||||
variable_.u = variable->u.u;
|
||||
game::VariableValue previous{};
|
||||
|
||||
game::AddRefToValue(game::SCRIPTINSTANCE_SERVER, &value);
|
||||
game::RemoveRefToValue(game::SCRIPTINSTANCE_SERVER, variable_.type, variable_.u);
|
||||
if (game::environment::is_sp())
|
||||
{
|
||||
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->u.u = value.u;*/
|
||||
variable->w.type |= value_.type;
|
||||
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
|
||||
@ -205,7 +308,7 @@ namespace scripting
|
||||
|
||||
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);
|
||||
|
||||
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<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<gentity_s*(scriptInstance_t inst, int index)> Scr_GetEntity{0x0, 0x0};
|
||||
|
Loading…
x
Reference in New Issue
Block a user