From c5b5a9336062303ba1cf8d9a582d4bac44d58107 Mon Sep 17 00:00:00 2001 From: Federico Cecchetto Date: Sun, 13 Mar 2022 21:01:29 +0100 Subject: [PATCH] Add more commands + fixes --- src/client/component/command.cpp | 392 +++++++++++++----- src/client/component/command.hpp | 2 + src/client/game/scripting/array.cpp | 335 +++++++++++++++ src/client/game/scripting/array.hpp | 87 ++++ src/client/game/scripting/execution.cpp | 11 + src/client/game/scripting/execution.hpp | 3 + src/client/game/scripting/function_tables.cpp | 28 +- .../game/scripting/lua/value_conversion.cpp | 4 +- src/client/game/scripting/script_value.cpp | 19 +- src/client/game/scripting/script_value.hpp | 5 +- src/client/game/structs.hpp | 72 ++-- src/client/game/symbols.hpp | 18 +- 12 files changed, 814 insertions(+), 162 deletions(-) create mode 100644 src/client/game/scripting/array.cpp create mode 100644 src/client/game/scripting/array.hpp diff --git a/src/client/component/command.cpp b/src/client/component/command.cpp index 63b66724..32e7fa0a 100644 --- a/src/client/component/command.cpp +++ b/src/client/component/command.cpp @@ -5,10 +5,13 @@ #include "console.hpp" #include "game_console.hpp" #include "fastfiles.hpp" +#include "scheduler.hpp" #include "game/game.hpp" #include "game/dvars.hpp" +#include "game/scripting/execution.hpp" + #include #include #include @@ -134,6 +137,202 @@ namespace command return 0; } + + void client_println(int client_num, const std::string& text) + { + if (game::environment::is_sp()) + { + game::CG_GameMessage(0, text.data()); + } + else + { + game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, + utils::string::va("f \"%s\"", text.data())); + } + } + + bool check_cheats(int client_num) + { + if (!game::Dvar_FindVar("sv_cheats")->current.enabled) + { + client_println(client_num, "Cheats are not enabled on this server"); + return false; + } + + return true; + } + + void cmd_give_weapon(const int client_num, const std::vector& params) + { + if (params.size() < 2) + { + client_println(client_num, "You did not specify a weapon name"); + return; + } + + try + { + const auto arg = params[1]; + const scripting::entity player = scripting::call("getentbynum", {client_num}).as(); + auto ps = game::SV_GetPlayerstateForClientNum(client_num); + + if (arg == "ammo") + { + const auto weapon = player.call("getcurrentweapon").as(); + player.call("givemaxammo", {weapon}); + } + else if (arg == "allammo") + { + const auto weapons = player.call("getweaponslistall").as(); + for (auto i = 0; i < weapons.size(); i++) + { + player.call("givemaxammo", {weapons[i]}); + } + } + else if (arg == "health") + { + if (params.size() > 2) + { + const auto amount = atoi(params[2].data()); + const auto health = player.get("health").as(); + player.set("health", {health + amount}); + } + else + { + const auto amount = SELECT_VALUE( + game::Dvar_FindVar("g_player_maxhealth")->current.integer, + atoi(game::Dvar_FindVar("scr_player_maxhealth")->current.string) + ); + player.set("health", {amount}); + } + } + else if (arg == "all") + { + const auto type = game::XAssetType::ASSET_TYPE_WEAPON; + fastfiles::enum_assets(type, [&player, type](const game::XAssetHeader header) + { + const auto asset = game::XAsset{type, header}; + const auto asset_name = game::DB_GetXAssetName(&asset); + + player.call("giveweapon", {asset_name}); + }, true); + } + else + { + const auto wp = game::G_GetWeaponForName(arg.data()); + if (wp) + { + if (game::G_GivePlayerWeapon(ps, wp, 0, 0, 0, 0, 0, 0)) + { + game::G_InitializeAmmo(ps, wp, 0); + game::G_SelectWeapon(0, wp); + } + } + else + { + client_println(client_num, "Weapon does not exist"); + } + } + } + catch (...) + { + } + } + + void cmd_drop_weapon(int client_num) + { + try + { + const scripting::entity player = scripting::call("getentbynum", {client_num}).as(); + const auto weapon = player.call("getcurrentweapon"); + player.call("dropitem", {weapon}); + } + catch (...) + { + } + } + + void cmd_take_weapon(int client_num, const std::vector& params) + { + if (params.size() < 2) + { + client_println(client_num, "You did not specify a weapon name"); + return; + } + + const auto& weapon = params[1]; + + try + { + const scripting::entity player = scripting::call("getentbynum", {client_num}).as(); + if (weapon == "all"s) + { + player.call("takeallweapons"); + } + else + { + player.call("takeweapon", {weapon}); + } + } + catch (...) + { + } + } + + void cmd_kill(int client_num) + { + scheduler::once([client_num]() + { + try + { + const scripting::entity player = scripting::call("getentbynum", {client_num}).as(); + player.call(SELECT_VALUE("kill", "suicide")); + } + catch (...) + { + } + }, scheduler::pipeline::server); + } + + void toggle_entity_flag(int client_num, int value, const std::string& name) + { + game::mp::g_entities[client_num].flags ^= value; + client_println(client_num, utils::string::va("%s %s", + name.data(), + game::mp::g_entities[client_num].flags & value + ? "^2on" + : "^1off")); + } + + void toggle_entity_flag(int value, const std::string& name) + { + game::sp::g_entities[0].flags ^= value; + client_println(0, utils::string::va("%s %s", + name.data(), + game::sp::g_entities[0].flags & value + ? "^2on" + : "^1off")); + } + + void toggle_client_flag(int client_num, int value, const std::string& name) + { + game::mp::g_entities[client_num].client->flags ^= value; + client_println(client_num, utils::string::va("%s %s", + name.data(), + game::mp::g_entities[client_num].client->flags & value + ? "^2on" + : "^1off")); + } + + void toggle_client_flag(int value, const std::string& name) + { + game::sp::g_entities[0].client->flags ^= value; + client_println(0, utils::string::va("%s %s", + name.data(), + game::sp::g_entities[0].client->flags & value + ? "^2on" + : "^1off")); + } } void read_startup_variable(const std::string& dvar) @@ -141,8 +340,8 @@ namespace command // parse the commandline if it's not parsed parse_command_line(); - auto& com_num_console_lines = *reinterpret_cast(0x142623FB4); //H1(1.4) - auto* com_console_lines = reinterpret_cast(0x142623FC0); //H1(1.4) + auto& com_num_console_lines = *reinterpret_cast(0x142623FB4); + auto* com_console_lines = reinterpret_cast(0x142623FC0); for (int i = 0; i < com_num_console_lines; i++) { @@ -190,6 +389,16 @@ namespace command return result; } + std::vector params::get_all() const + { + std::vector params_; + for (auto i = 0; i < this->size(); i++) + { + params_.push_back(this->get(i)); + } + return params_; + } + params_sv::params_sv() : nesting_(game::sv_cmd_args->nesting) { @@ -222,6 +431,16 @@ namespace command return result; } + std::vector params_sv::get_all() const + { + std::vector params_; + for (auto i = 0; i < this->size(); i++) + { + params_.push_back(this->get(i)); + } + return params_; + } + void add_raw(const char* name, void (*callback)()) { game::Cmd_AddCommandInternal(name, callback, utils::memory::get_allocator()->allocate()); @@ -418,11 +637,7 @@ namespace command return; } - game::sp::g_entities[0].flags ^= 1; - game::CG_GameMessage(0, utils::string::va("godmode %s", - game::sp::g_entities[0].flags & 1 - ? "^2on" - : "^1off")); + toggle_entity_flag(1, "godmode"); }); add("demigod", []() @@ -432,11 +647,7 @@ namespace command return; } - game::sp::g_entities[0].flags ^= 2; - game::CG_GameMessage(0, utils::string::va("demigod mode %s", - game::sp::g_entities[0].flags & 2 - ? "^2on" - : "^1off")); + toggle_entity_flag(2, "demigod mode"); }); add("notarget", []() @@ -446,11 +657,7 @@ namespace command return; } - game::sp::g_entities[0].flags ^= 4; - game::CG_GameMessage(0, utils::string::va("notarget %s", - game::sp::g_entities[0].flags & 4 - ? "^2on" - : "^1off")); + toggle_entity_flag(4, "notarget"); }); add("noclip", []() @@ -460,11 +667,7 @@ namespace command return; } - game::sp::g_entities[0].client->flags ^= 1; - game::CG_GameMessage(0, utils::string::va("noclip %s", - game::sp::g_entities[0].client->flags & 1 - ? "^2on" - : "^1off")); + toggle_client_flag(1, "noclip"); }); add("ufo", []() @@ -474,11 +677,47 @@ namespace command return; } - game::sp::g_entities[0].client->flags ^= 2; - game::CG_GameMessage(0, utils::string::va("ufo %s", - game::sp::g_entities[0].client->flags & 2 - ? "^2on" - : "^1off")); + toggle_client_flag(2, "ufo"); + }); + + add("give", [](const params& params) + { + if (!game::SV_Loaded()) + { + return; + } + + cmd_give_weapon(0, params.get_all()); + }); + + add("dropweapon", [](const params& params) + { + if (!game::SV_Loaded()) + { + return; + } + + cmd_drop_weapon(0); + }); + + add("take", [](const params& params) + { + if (!game::SV_Loaded()) + { + return; + } + + cmd_take_weapon(0, params.get_all()); + }); + + add("kill", [](const params& params) + { + if (!game::SV_Loaded()) + { + return; + } + + cmd_kill(0); }); } @@ -488,139 +727,92 @@ namespace command add_sv("god", [](const int client_num, const params_sv&) { - if (!game::Dvar_FindVar("sv_cheats")->current.enabled) + if (!check_cheats(client_num)) { - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - "f \"Cheats are not enabled on this server\""); return; } - game::mp::g_entities[client_num].flags ^= 1; - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - utils::string::va("f \"godmode %s\"", - game::mp::g_entities[client_num].flags & 1 - ? "^2on" - : "^1off")); + toggle_entity_flag(client_num, 1, "godmode"); }); add_sv("demigod", [](const int client_num, const params_sv&) { - if (!game::Dvar_FindVar("sv_cheats")->current.enabled) + if (!check_cheats(client_num)) { - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - "f \"Cheats are not enabled on this server\""); return; } - game::mp::g_entities[client_num].flags ^= 2; - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - utils::string::va("f \"demigod mode %s\"", - game::mp::g_entities[client_num].flags & 2 - ? "^2on" - : "^1off")); + toggle_entity_flag(client_num, 2, "demigod mode"); }); add_sv("notarget", [](const int client_num, const params_sv&) { - if (!game::Dvar_FindVar("sv_cheats")->current.enabled) + if (!check_cheats(client_num)) { - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - "f \"Cheats are not enabled on this server\""); return; } - game::mp::g_entities[client_num].flags ^= 4; - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - utils::string::va("f \"notarget %s\"", - game::mp::g_entities[client_num].flags & 4 - ? "^2on" - : "^1off")); + toggle_entity_flag(client_num, 4, "notarget"); }); add_sv("noclip", [](const int client_num, const params_sv&) { - if (!game::Dvar_FindVar("sv_cheats")->current.enabled) + if (!check_cheats(client_num)) { - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - "f \"Cheats are not enabled on this server\""); return; } - game::mp::g_entities[client_num].client->flags ^= 1; - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - utils::string::va("f \"noclip %s\"", - game::mp::g_entities[client_num].client->flags & 1 - ? "^2on" - : "^1off")); + toggle_client_flag(client_num, 1, "noclip"); }); add_sv("ufo", [](const int client_num, const params_sv&) { - if (!game::Dvar_FindVar("sv_cheats")->current.enabled) + if (!check_cheats(client_num)) { - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - "f \"Cheats are not enabled on this server\""); return; } - game::mp::g_entities[client_num].client->flags ^= 2; - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - utils::string::va("f \"ufo %s\"", - game::mp::g_entities[client_num].client->flags & 2 - ? "^2on" - : "^1off")); + toggle_client_flag(client_num, 2, "noclip"); }); add_sv("give", [](const int client_num, const params_sv& params) { - if (!game::Dvar_FindVar("sv_cheats")->current.enabled) + if (!check_cheats(client_num)) { - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - "f \"Cheats are not enabled on this server\""); return; } - if (params.size() < 2) + cmd_give_weapon(client_num, params.get_all()); + }); + + add_sv("dropweapon", [](const int client_num, const params_sv& params) + { + if (!check_cheats(client_num)) { - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - "f \"You did not specify a weapon name\""); return; } - auto ps = game::SV_GetPlayerstateForClientNum(client_num); - const auto wp = game::G_GetWeaponForName(params.get(1)); - if (wp) - { - if (game::G_GivePlayerWeapon(ps, wp, 0, 0, 0, 0, 0, 0)) - { - game::G_InitializeAmmo(ps, wp, 0); - game::G_SelectWeapon(client_num, wp); - } - } + cmd_drop_weapon(client_num); }); add_sv("take", [](const int client_num, const params_sv& params) { - if (!game::Dvar_FindVar("sv_cheats")->current.enabled) + if (!check_cheats(client_num)) { - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - "f \"Cheats are not enabled on this server\""); return; } - if (params.size() < 2) + cmd_take_weapon(client_num, params.get_all()); + }); + + add_sv("kill", [](const int client_num, const params_sv& params) + { + if (!check_cheats(client_num)) { - game::SV_GameSendServerCommand(client_num, game::SV_CMD_RELIABLE, - "f \"You did not specify a weapon name\""); return; } - auto ps = game::SV_GetPlayerstateForClientNum(client_num); - const auto wp = game::G_GetWeaponForName(params.get(1)); - if (wp) - { - game::G_TakePlayerWeapon(ps, wp); - } + cmd_kill(client_num); }); } }; diff --git a/src/client/component/command.hpp b/src/client/component/command.hpp index bd70d0c6..06228c9d 100644 --- a/src/client/component/command.hpp +++ b/src/client/component/command.hpp @@ -10,6 +10,7 @@ namespace command int size() const; const char* get(int index) const; std::string join(int index) const; + std::vector get_all() const; const char* operator[](const int index) const { @@ -28,6 +29,7 @@ namespace command int size() const; const char* get(int index) const; std::string join(int index) const; + std::vector get_all() const; const char* operator[](const int index) const { diff --git a/src/client/game/scripting/array.cpp b/src/client/game/scripting/array.cpp new file mode 100644 index 00000000..33164bd9 --- /dev/null +++ b/src/client/game/scripting/array.cpp @@ -0,0 +1,335 @@ +#include +#include "array.hpp" +#include "script_value.hpp" +#include "execution.hpp" + +namespace scripting +{ + array_value::array_value(unsigned int parent_id, unsigned int id) + : id_(id) + , parent_id_(parent_id) + { + if (!this->id_) + { + return; + } + + const auto value = game::scr_VarGlob->childVariableValue[this->id_ + 0xFA00 * (this->parent_id_ & 3)]; + 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) + { + if (!this->id_) + { + return; + } + + const auto value = _value.get_raw(); + + const auto variable = &game::scr_VarGlob->childVariableValue[this->id_ + 0xFA00 * (this->parent_id_ & 3)]; + game::AddRefToValue(value.type, value.u); + game::RemoveRefToValue(variable->type, variable->u.u); + + variable->type = (char)value.type; + variable->u.u = value.u; + + this->value_ = value; + } + + array::array(const unsigned int id) + : id_(id) + { + this->add(); + } + + array::array(const array& other) : array(other.id_) + { + } + + array::array(array&& other) noexcept + { + this->id_ = other.id_; + other.id_ = 0; + } + + array::array() + { + this->id_ = make_array(); + } + + array::array(std::vector values) + { + this->id_ = make_array(); + + for (const auto& value : values) + { + this->push(value); + } + } + + array::array(std::unordered_map values) + { + this->id_ = make_array(); + + for (const auto& value : values) + { + this->set(value.first, value.second); + } + } + + array::~array() + { + this->release(); + } + + array& array::operator=(const array& other) + { + if (&other != this) + { + this->release(); + this->id_ = other.id_; + this->add(); + } + + return *this; + } + + array& array::operator=(array&& other) noexcept + { + if (&other != this) + { + this->release(); + this->id_ = other.id_; + other.id_ = 0; + } + + return *this; + } + + void array::add() const + { + if (this->id_) + { + game::AddRefToValue(game::SCRIPT_OBJECT, {static_cast(this->id_)}); + } + } + + void array::release() const + { + if (this->id_) + { + game::RemoveRefToValue(game::SCRIPT_OBJECT, {static_cast(this->id_)}); + } + } + + std::vector array::get_keys() const + { + std::vector result; + + const auto offset = 0xFA00 * (this->id_ & 3); + auto current = game::scr_VarGlob->objectVariableChildren[this->id_].firstChild; + + for (auto i = offset + current; current; i = offset + current) + { + const auto var = game::scr_VarGlob->childVariableValue[i]; + + if (var.type == game::SCRIPT_NONE) + { + current = var.nextSibling; + continue; + } + + const auto string_value = (game::scr_string_t)((unsigned __int8)var.name_lo + (var.k.keys.name_hi << 8)); + const auto* str = game::SL_ConvertToString(string_value); + + script_value key; + if (string_value < 0x40000 && str) + { + key = str; + } + else + { + key = (string_value - 0x800000) & 0xFFFFFF; + } + + result.push_back(key); + + current = var.nextSibling; + } + + return result; + } + + int array::size() const + { + return static_cast(game::scr_VarGlob->objectVariableValue[this->id_].u.f.next); + } + + unsigned int array::push(script_value value) const + { + this->set(this->size(), value); + return this->size(); + } + + void array::erase(const unsigned int index) const + { + const auto variable_id = game::FindVariable(this->id_, (index - 0x800000) & 0xFFFFFF); + if (variable_id) + { + game::RemoveVariableValue(this->id_, variable_id); + } + } + + void array::erase(const std::string& key) const + { + const auto string_value = game::SL_GetString(key.data(), 0); + const auto variable_id = game::FindVariable(this->id_, string_value); + if (variable_id) + { + game::RemoveVariableValue(this->id_, variable_id); + } + } + + script_value array::pop() const + { + const auto value = this->get(this->size() - 1); + this->erase(this->size() - 1); + return value; + } + + script_value array::get(const script_value& key) const + { + if (key.is()) + { + return this->get(key.as()); + } + else + { + return this->get(key.as()); + } + } + + script_value array::get(const std::string& key) const + { + const auto string_value = game::SL_GetString(key.data(), 0); + const auto variable_id = game::FindVariable(this->id_, string_value); + + if (!variable_id) + { + return {}; + } + + const auto value = game::scr_VarGlob->childVariableValue[variable_id + 0xFA00 * (this->id_ & 3)]; + game::VariableValue variable; + variable.u = value.u.u; + variable.type = (game::scriptType_e)value.type; + + return variable; + } + + script_value array::get(const unsigned int index) const + { + const auto variable_id = game::FindVariable(this->id_, (index - 0x800000) & 0xFFFFFF); + + if (!variable_id) + { + return {}; + } + + const auto value = game::scr_VarGlob->childVariableValue[variable_id + 0xFA00 * (this->id_ & 3)]; + game::VariableValue variable; + variable.u = value.u.u; + variable.type = (game::scriptType_e)value.type; + + return variable; + } + + void array::set(const script_value& key, const script_value& value) const + { + if (key.is()) + { + this->set(key.as(), value); + } + else + { + this->set(key.as(), value); + } + } + + void array::set(const std::string& key, const script_value& _value) const + { + const auto value = _value.get_raw(); + const auto variable_id = this->get_value_id(key); + + if (!variable_id) + { + return; + } + + const auto variable = &game::scr_VarGlob->childVariableValue[variable_id + 0xFA00 * (this->id_ & 3)]; + + game::AddRefToValue(value.type, value.u); + game::RemoveRefToValue(variable->type, variable->u.u); + + variable->type = (char)value.type; + variable->u.u = value.u; + } + + void array::set(const unsigned int index, const script_value& _value) const + { + const auto value = _value.get_raw(); + const auto variable_id = this->get_value_id(index); + + if (!variable_id) + { + return; + } + + const auto variable = &game::scr_VarGlob->childVariableValue[variable_id + 0xFA00 * (this->id_ & 3)]; + + game::AddRefToValue(value.type, value.u); + game::RemoveRefToValue(variable->type, variable->u.u); + + variable->type = (char)value.type; + variable->u.u = value.u; + } + + unsigned int array::get_entity_id() const + { + return this->id_; + } + + unsigned int array::get_value_id(const std::string& key) const + { + const auto string_value = game::SL_GetString(key.data(), 0); + const auto variable_id = game::FindVariable(this->id_, string_value); + + if (!variable_id) + { + return game::GetNewVariable(this->id_, string_value); + } + + return variable_id; + } + + 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); + } + + return variable_id; + } + + entity array::get_raw() const + { + return entity(this->id_); + } +} diff --git a/src/client/game/scripting/array.hpp b/src/client/game/scripting/array.hpp new file mode 100644 index 00000000..e78ace3b --- /dev/null +++ b/src/client/game/scripting/array.hpp @@ -0,0 +1,87 @@ +#pragma once +#include "game/game.hpp" +#include "script_value.hpp" + +namespace scripting +{ + class array_value : public script_value + { + public: + array_value(unsigned int, unsigned int); + void operator=(const script_value&); + private: + unsigned int id_; + unsigned int parent_id_; + }; + + class array final + { + public: + array(); + array(const unsigned int); + + array(std::vector); + array(std::unordered_map); + + array(const array& other); + array(array&& other) noexcept; + + ~array(); + + array& operator=(const array& other); + array& operator=(array&& other) noexcept; + + std::vector get_keys() const; + int size() const; + + unsigned int push(script_value) const; + void erase(const unsigned int) const; + void erase(const std::string&) const; + script_value pop() const; + + script_value get(const script_value&) const; + script_value get(const std::string&) const; + script_value get(const unsigned int) const; + + void set(const script_value&, const script_value&) const; + void set(const std::string&, const script_value&) const; + void set(const unsigned int, const script_value&) const; + + unsigned int get_entity_id() const; + + unsigned int get_value_id(const std::string&) const; + unsigned int get_value_id(const unsigned int) const; + + entity get_raw() const; + + array_value operator[](const int index) const + { + return {this->id_, this->get_value_id(index)}; + } + + array_value operator[](const std::string& key) const + { + return {this->id_, this->get_value_id(key)}; + } + + template + array_value operator[](const script_value& key) const + { + if (key.is()) + { + return { this->id_, this->get_value_id(key.as()) }; + } + + if (key.is()) + { + return { this->id_, this->get_value_id(key.as()) }; + } + } + + private: + void add() const; + void release() const; + + unsigned int id_; + }; +} diff --git a/src/client/game/scripting/execution.cpp b/src/client/game/scripting/execution.cpp index 29faaad4..273b4f7a 100644 --- a/src/client/game/scripting/execution.cpp +++ b/src/client/game/scripting/execution.cpp @@ -237,4 +237,15 @@ namespace scripting // Add custom fields return get_custom_field(entity, field); } + + unsigned int make_array() + { + unsigned int index = 0; + const auto variable = game::AllocVariable(&index); + variable->w.type = game::SCRIPT_ARRAY; + variable->u.f.prev = 0; + variable->u.f.next = 0; + + return index; + } } diff --git a/src/client/game/scripting/execution.hpp b/src/client/game/scripting/execution.hpp index 7fff1840..94a2678d 100644 --- a/src/client/game/scripting/execution.hpp +++ b/src/client/game/scripting/execution.hpp @@ -1,6 +1,7 @@ #pragma once #include "game/game.hpp" #include "entity.hpp" +#include "array.hpp" #include "script_value.hpp" namespace scripting @@ -33,4 +34,6 @@ namespace scripting script_value get_entity_field(const entity& entity, const std::string& field); void notify(const entity& entity, const std::string& event, const std::vector& arguments); + + unsigned int make_array(); } diff --git a/src/client/game/scripting/function_tables.cpp b/src/client/game/scripting/function_tables.cpp index f429aad0..300c7352 100644 --- a/src/client/game/scripting/function_tables.cpp +++ b/src/client/game/scripting/function_tables.cpp @@ -1494,12 +1494,12 @@ namespace scripting {"setspectatedefaults", 0x82C5}, // SP 0x000000000 MP 0x140331EE0 {"getthirdpersoncrosshairoffset", 0x82C6}, // SP 0x000000000 MP 0x140332250 {"disableweaponpickup", 0x82C7}, // SP 0x140262950 MP 0x14032EF00 - {"_meth_82c8", 0x82C8}, // SP 0x140262A60 MP 0x14032EFF0 - {"_meth_82c9", 0x82C9}, // SP 0x140262AB0 MP 0x14032F0D0 - {"_meth_82ca", 0x82CA}, // SP 0x000000000 MP 0x1403322C0 - {"getweaponslistexclusives", 0x82CB}, // SP 0x1402623D0 MP 0x14032E3A0 - {"_meth_82cc", 0x82CC}, // SP 0x1402624C0 MP 0x14032E4B0 - {"_meth_82cd", 0x82CD}, // SP 0x1402625B0 MP 0x14032E650 + {"enableweaponpickup", 0x82C8}, // SP 0x140262A60 MP 0x14032EFF0 + {"issplitscreenplayer", 0x82C9}, // SP 0x140262AB0 MP 0x14032F0D0 + {"issplitscreenplayerprimary", 0x82CA}, // SP 0x000000000 MP 0x1403322C0 + {"getweaponslistoffhands", 0x82CB}, // SP 0x1402623D0 MP 0x14032E3A0 + {"getweaponslistitems", 0x82CC}, // SP 0x1402624C0 MP 0x14032E4B0 + {"getweaponslistexclusives", 0x82CD}, // SP 0x1402625B0 MP 0x14032E650 {"getweaponslist", 0x82CE}, // SP 0x140262720 MP 0x14032E790 {"canplayerplacesentry", 0x82CF}, // SP 0x140264D00 MP 0x140331530 {"canplayerplacetank", 0x82D0}, // SP 0x1402651B0 MP 0x1403292E0 @@ -1559,8 +1559,8 @@ namespace scripting {"setviewkickscale", 0x8306}, // SP 0x1402608B0 MP 0x14032CB90 {"getviewkickscale", 0x8307}, // SP 0x140260A80 MP 0x14032CCC0 {"getweaponslistall", 0x8308}, // SP 0x1402621A0 MP 0x14032E120 - getweaponslistoffhands - {"getweaponslistitems", 0x8309}, // SP 0x1402622E0 MP 0x14032E230 - {"_meth_830a", 0x830A}, // SP 0x140261090 MP 0x14032C720 + {"getweaponslistprimaries", 0x8309}, // SP 0x1402622E0 MP 0x14032E230 + {"getnormalizedcameramovement", 0x830A}, // SP 0x140261090 MP 0x14032C720 {"giveweapon", 0x830B}, // SP 0x140262F00 MP 0x14032EA90f {"takeweapon", 0x830C}, // SP 0x140263380 MP 0x14032F210 {"takeallweapons", 0x830D}, // SP 0x1402635B0 MP 0x14032F310 @@ -1596,13 +1596,13 @@ namespace scripting {"setreverb", 0x832B}, // SP 0x140266EA0 MP 0x14032B9C0 {"_meth_832c", 0x832C}, // SP 0x140267180 MP 0x14032B9E0 {"deactivatechannelvolumes", 0x832D}, // SP 0x140267410 MP 0x14032BB00 - {"_meth_832e", 0x832E}, // SP 0x140265FA0 MP 0x140329C00 - {"_meth_832f", 0x832F}, // SP 0x140266200 MP 0x140329F00 - {"_meth_8330", 0x8330}, // SP 0x140266560 MP 0x14032A240 - {"_meth_8331", 0x8331}, // SP 0x140266820 MP 0x14032A6F0 + {"givestartammo", 0x832E}, // SP 0x140265FA0 MP 0x140329C00 + {"givemaxammo", 0x832F}, // SP 0x140266200 MP 0x140329F00 + {"getfractionstartammo", 0x8330}, // SP 0x140266560 MP 0x14032A240 + {"getfractionmaxammo", 0x8331}, // SP 0x140266820 MP 0x14032A6F0 {"isdualwielding", 0x8332}, // SP 0x140266E10 MP 0x14032ABC0 - {"_meth_8333", 0x8333}, // SP 0x140267030 MP 0x14032AD00 - {"isreloading", 0x8334}, // SP 0x140267100 MP 0x14032AEE0 + {"isreloading", 0x8333}, // SP 0x140267030 MP 0x14032AD00 + {"isswitchingweapon", 0x8334}, // SP 0x140267100 MP 0x14032AEE0 {"setorigin", 0x8335}, // SP 0x1402677C0 MP 0x14032B8D0 {"getvelocity", 0x8336}, // SP 0x1402604D0 MP 0x14032BC80 {"_meth_8337", 0x8337}, // SP 0x140260930 MP 0x14032BE70 diff --git a/src/client/game/scripting/lua/value_conversion.cpp b/src/client/game/scripting/lua/value_conversion.cpp index 3cc37e20..a838c787 100644 --- a/src/client/game/scripting/lua/value_conversion.cpp +++ b/src/client/game/scripting/lua/value_conversion.cpp @@ -21,7 +21,7 @@ namespace scripting::lua std::unordered_map values; - const auto offset = 0xA000 * (id & 3); + const auto offset = 0xFA00 * (id & 3); auto current = game::scr_VarGlob->objectVariableChildren[id].firstChild; auto idx = 1; @@ -294,7 +294,7 @@ namespace scripting::lua return entity_to_struct(state, value.get_raw().u.uintValue); } - if (value.is>()) + if (value.is()) { return entity_to_array(state, value.get_raw().u.uintValue); } diff --git a/src/client/game/scripting/script_value.cpp b/src/client/game/scripting/script_value.cpp index 7d334f17..b99d831f 100644 --- a/src/client/game/scripting/script_value.cpp +++ b/src/client/game/scripting/script_value.cpp @@ -1,7 +1,7 @@ #include #include "script_value.hpp" #include "entity.hpp" - +#include "array.hpp" namespace scripting { @@ -79,6 +79,15 @@ namespace scripting this->value_ = variable; } + script_value::script_value(const array& value) + { + game::VariableValue variable{}; + variable.type = game::SCRIPT_OBJECT; + variable.u.pointerValue = value.get_entity_id(); + + this->value_ = variable; + } + script_value::script_value(const vector& value) { game::VariableValue variable{}; @@ -194,7 +203,7 @@ namespace scripting **************************************************************/ template <> - bool script_value::is>() const + bool script_value::is() const { if (this->get_raw().type != game::SCRIPT_OBJECT) { @@ -207,6 +216,12 @@ namespace scripting return type == game::SCRIPT_ARRAY; } + template <> + array script_value::get() const + { + return array(this->get_raw().u.uintValue); + } + /*************************************************************** * Struct **************************************************************/ diff --git a/src/client/game/scripting/script_value.hpp b/src/client/game/scripting/script_value.hpp index df8a95b6..27cae79f 100644 --- a/src/client/game/scripting/script_value.hpp +++ b/src/client/game/scripting/script_value.hpp @@ -6,6 +6,7 @@ namespace scripting { class entity; + class array; class script_value { @@ -24,6 +25,7 @@ namespace scripting script_value(const std::string& value); script_value(const entity& value); + script_value(const array& value); script_value(const vector& value); @@ -43,10 +45,11 @@ namespace scripting const game::VariableValue& get_raw() const; + variable_value value_{}; + private: template T get() const; - variable_value value_{}; }; } diff --git a/src/client/game/structs.hpp b/src/client/game/structs.hpp index 60c368a1..bf618a5d 100644 --- a/src/client/game/structs.hpp +++ b/src/client/game/structs.hpp @@ -186,12 +186,11 @@ namespace game struct scrVarGlob_t { - ObjectVariableValue objectVariableValue[56320]; - ObjectVariableChildren objectVariableChildren[56320]; + ObjectVariableValue objectVariableValue[40960]; + ObjectVariableChildren objectVariableChildren[40960]; unsigned __int16 childVariableBucket[65536]; ChildVariableValue childVariableValue[384000]; }; - // * enum Sys_Folder { @@ -1009,11 +1008,11 @@ namespace game enum XAssetType { ASSET_TYPE_PHYSPRESET, - ASSET_TYPE_PHYSCOLLMAP, + ASSET_TYPE_PHYS_COLLMAP, ASSET_TYPE_PHYSWATERPRESET, - ASSET_TYPE_PHYSWORLDMAP, + ASSET_TYPE_PHYS_WORLDMAP, ASSET_TYPE_PHYSCONSTRAINT, - ASSET_TYPE_XANIMPARTS, + ASSET_TYPE_XANIM, ASSET_TYPE_XMODELSURFS, ASSET_TYPE_XMODEL, ASSET_TYPE_MATERIAL, @@ -1023,36 +1022,35 @@ namespace game ASSET_TYPE_DOMAINSHADER, ASSET_TYPE_PIXELSHADER, ASSET_TYPE_VERTEXDECL, - ASSET_TYPE_TECHNIQUE_SET, + ASSET_TYPE_TECHSET, ASSET_TYPE_IMAGE, ASSET_TYPE_SOUND, - ASSET_TYPE_SOUND_SUBMIX, - ASSET_TYPE_SOUND_CURVE, - ASSET_TYPE_LPF_CURVE, - ASSET_TYPE_REVERB_CURVE, - ASSET_TYPE_SOUND_CONTEXT, + ASSET_TYPE_SOUNDSUBMIX, + ASSET_TYPE_SNDCURVE, + ASSET_TYPE_LPFCURVE, + ASSET_TYPE_REVERBSENDCURVE, + ASSET_TYPE_SNDCONTEXT, ASSET_TYPE_LOADED_SOUND, - ASSET_TYPE_CLIPMAP, - ASSET_TYPE_COMWORLD, - ASSET_TYPE_GLASSWORLD, - ASSET_TYPE_PATHDATA, + ASSET_TYPE_COL_MAP_MP, + ASSET_TYPE_COM_MAP, + ASSET_TYPE_GLASS_MAP, + ASSET_TYPE_AIPATHS, ASSET_TYPE_VEHICLE_TRACK, ASSET_TYPE_MAP_ENTS, - ASSET_TYPE_FXWORLD, - ASSET_TYPE_GFXWORLD, - ASSET_TYPE_LIGHT_DEF, + ASSET_TYPE_FX_MAP, + ASSET_TYPE_GFX_MAP, + ASSET_TYPE_LIGHTDEF, ASSET_TYPE_UI_MAP, - ASSET_TYPE_FONT, - ASSET_TYPE_MENULIST, + ASSET_TYPE_MENUFILE, ASSET_TYPE_MENU, ASSET_TYPE_ANIMCLASS, - ASSET_TYPE_LOCALIZE_ENTRY, + ASSET_TYPE_LOCALIZE, ASSET_TYPE_ATTACHMENT, ASSET_TYPE_WEAPON, - ASSET_TYPE_SNDDRIVER_GLOBALS, + ASSET_TYPE_SNDDRIVERGLOBALS, ASSET_TYPE_FX, - ASSET_TYPE_IMPACT_FX, - ASSET_TYPE_SURFACE_FX, + ASSET_TYPE_IMPACTFX, + ASSET_TYPE_SURFACEFX, ASSET_TYPE_AITYPE, ASSET_TYPE_MPTYPE, ASSET_TYPE_CHARACTER, @@ -1060,23 +1058,27 @@ namespace game ASSET_TYPE_RAWFILE, ASSET_TYPE_SCRIPTFILE, ASSET_TYPE_STRINGTABLE, - ASSET_TYPE_LEADERBOARD, - ASSET_TYPE_STRUCTURED_DATA_DEF, + ASSET_TYPE_LEADERBOARDDEF, + ASSET_TYPE_VIRTUALLEADERBOARDDEF, + ASSET_TYPE_STRUCTUREDDATADEF, + ASSET_TYPE_DDL, + ASSET_TYPE_PROTO, ASSET_TYPE_TRACER, ASSET_TYPE_VEHICLE, ASSET_TYPE_ADDON_MAP_ENTS, - ASSET_TYPE_NET_CONST_STRINGS, - ASSET_TYPE_REVERB_PRESET, - ASSET_TYPE_LUA_FILE, + ASSET_TYPE_NETCONSTSTRINGS, + ASSET_TYPE_REVERBPRESET, + ASSET_TYPE_LUAFILE, ASSET_TYPE_SCRIPTABLE, - ASSET_TYPE_EQUIPMENT_SND_TABLE, + ASSET_TYPE_EQUIPSNDTABLE, ASSET_TYPE_VECTORFIELD, - ASSET_TYPE_DOPPLER_PRESET, - ASSET_TYPE_PARTICLE_SIM_ANIMATION, + ASSET_TYPE_DOPPLERPRESET, + ASSET_TYPE_PARTICLESIMANIMATION, ASSET_TYPE_LASER, - ASSET_TYPE_SKELETON_SCRIPT, + ASSET_TYPE_SKELETONSCRIPT, ASSET_TYPE_CLUT, - ASSET_TYPE_COUNT, + ASSET_TYPE_TTF, + ASSET_TYPE_COUNT }; enum GfxDrawSceneMethod diff --git a/src/client/game/symbols.hpp b/src/client/game/symbols.hpp index bfabfd0d..257bbf15 100644 --- a/src/client/game/symbols.hpp +++ b/src/client/game/symbols.hpp @@ -13,6 +13,7 @@ namespace game WEAK symbol AddRefToObject{0x14036E5F0, 0x14043C570}; WEAK symbol RemoveRefToObject{0x14036FFE0, 0x14043DF80}; WEAK symbol AllocThread{0x14036E960, 0x14043C8E0}; + WEAK symbol AllocVariable{0x14036E9C0, 0x14043C940}; WEAK symbol Cbuf_AddText{0x140342EB0, 0x1404033B0}; WEAK symbol FS_AddLocalizedGameDirectory{0x1403B6030, 0x1404EBE20}; WEAK symbol GetVariable{0x14036FDD0, 0x1403F3730}; - + WEAK symbol GetNewVariable{0x14036FA00, 0x14043D990}; + WEAK symbol GetNewArrayVariable{0x14036F880, 0x14043D810}; WEAK symbol GScr_LoadConsts{0x1402D13E0, 0x140393810}; WEAK symbol FindVariable{0x14036F4B0, 0x14043D430}; WEAK symbol FindEntityId{0x14036F3B0, 0x14043D330}; @@ -197,21 +199,21 @@ namespace game WEAK symbol sv_cmd_args{0x14AD99A10, 0x14946BA20}; - WEAK symbol g_script_error_level{0x14A1917A8, 0x14A33C824}; - WEAK symbol g_script_error{0x14A1917B0, 0x14A33C940}; + WEAK symbol g_script_error_level{0x14BCFA4A4, 0x14A33C824}; + WEAK symbol g_script_error{0x14BCFA5C0, 0x14A33C940}; - WEAK symbol levelEntityId{0x149AF55B0, 0x149CA0730}; - WEAK symbol gameEntityId{0x149CA0734, 0x14B65E3B4}; + WEAK symbol levelEntityId{0x14B65E3B0, 0x149CA0730}; + WEAK symbol gameEntityId{0x14B65E3B4, 0x149CA0734}; WEAK symbol command_whitelist{0x141079A60, 0x14120C360}; WEAK symbol cmd_functions{0x14AD99AB8, 0x14946BAC8}; WEAK symbol cmd_args{0x14AD99960, 0x14946B970}; - WEAK symbol g_poolSize{0, 0x140FEADF0}; - WEAK symbol g_classMap{0x14080A840, 0x1412106B0}; + WEAK symbol g_poolSize{0x140DE84A0, 0x140FEADF0}; + WEAK symbol g_classMap{0x14107AAF0, 0x1412106B0}; WEAK symbol scr_VarGlob{0x14B686480, 0x149CC8800}; - WEAK symbol scr_VmPub{0x14A1938C0, 0x14A33EA40}; + WEAK symbol scr_VmPub{0x14BCFC6C0, 0x14A33EA40}; WEAK symbol scr_function_stack{0x14BD06C40, 0x14A348FC0}; WEAK symbol gfxDrawMethod{0x14F05CE50, 0x14FD21180};