Add more commands + fixes

This commit is contained in:
Federico Cecchetto 2022-03-13 21:01:29 +01:00
parent 66b2a82ab3
commit 2a5e9721c3
12 changed files with 814 additions and 162 deletions

View File

@ -5,10 +5,13 @@
#include "console.hpp" #include "console.hpp"
#include "game_console.hpp" #include "game_console.hpp"
#include "fastfiles.hpp" #include "fastfiles.hpp"
#include "scheduler.hpp"
#include "game/game.hpp" #include "game/game.hpp"
#include "game/dvars.hpp" #include "game/dvars.hpp"
#include "game/scripting/execution.hpp"
#include <utils/hook.hpp> #include <utils/hook.hpp>
#include <utils/string.hpp> #include <utils/string.hpp>
#include <utils/memory.hpp> #include <utils/memory.hpp>
@ -134,6 +137,202 @@ namespace command
return 0; 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<std::string>& 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<scripting::entity>();
auto ps = game::SV_GetPlayerstateForClientNum(client_num);
if (arg == "ammo")
{
const auto weapon = player.call("getcurrentweapon").as<std::string>();
player.call("givemaxammo", {weapon});
}
else if (arg == "allammo")
{
const auto weapons = player.call("getweaponslistall").as<scripting::array>();
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<int>();
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<scripting::entity>();
const auto weapon = player.call("getcurrentweapon");
player.call("dropitem", {weapon});
}
catch (...)
{
}
}
void cmd_take_weapon(int client_num, const std::vector<std::string>& 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<scripting::entity>();
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<scripting::entity>();
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) void read_startup_variable(const std::string& dvar)
@ -141,8 +340,8 @@ namespace command
// parse the commandline if it's not parsed // parse the commandline if it's not parsed
parse_command_line(); parse_command_line();
auto& com_num_console_lines = *reinterpret_cast<int*>(0x142623FB4); //H1(1.4) auto& com_num_console_lines = *reinterpret_cast<int*>(0x142623FB4);
auto* com_console_lines = reinterpret_cast<char**>(0x142623FC0); //H1(1.4) auto* com_console_lines = reinterpret_cast<char**>(0x142623FC0);
for (int i = 0; i < com_num_console_lines; i++) for (int i = 0; i < com_num_console_lines; i++)
{ {
@ -190,6 +389,16 @@ namespace command
return result; return result;
} }
std::vector<std::string> params::get_all() const
{
std::vector<std::string> params_;
for (auto i = 0; i < this->size(); i++)
{
params_.push_back(this->get(i));
}
return params_;
}
params_sv::params_sv() params_sv::params_sv()
: nesting_(game::sv_cmd_args->nesting) : nesting_(game::sv_cmd_args->nesting)
{ {
@ -222,6 +431,16 @@ namespace command
return result; return result;
} }
std::vector<std::string> params_sv::get_all() const
{
std::vector<std::string> 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)()) void add_raw(const char* name, void (*callback)())
{ {
game::Cmd_AddCommandInternal(name, callback, utils::memory::get_allocator()->allocate<game::cmd_function_s>()); game::Cmd_AddCommandInternal(name, callback, utils::memory::get_allocator()->allocate<game::cmd_function_s>());
@ -418,11 +637,7 @@ namespace command
return; return;
} }
game::sp::g_entities[0].flags ^= 1; toggle_entity_flag(1, "godmode");
game::CG_GameMessage(0, utils::string::va("godmode %s",
game::sp::g_entities[0].flags & 1
? "^2on"
: "^1off"));
}); });
add("demigod", []() add("demigod", []()
@ -432,11 +647,7 @@ namespace command
return; return;
} }
game::sp::g_entities[0].flags ^= 2; toggle_entity_flag(2, "demigod mode");
game::CG_GameMessage(0, utils::string::va("demigod mode %s",
game::sp::g_entities[0].flags & 2
? "^2on"
: "^1off"));
}); });
add("notarget", []() add("notarget", []()
@ -446,11 +657,7 @@ namespace command
return; return;
} }
game::sp::g_entities[0].flags ^= 4; toggle_entity_flag(4, "notarget");
game::CG_GameMessage(0, utils::string::va("notarget %s",
game::sp::g_entities[0].flags & 4
? "^2on"
: "^1off"));
}); });
add("noclip", []() add("noclip", []()
@ -460,11 +667,7 @@ namespace command
return; return;
} }
game::sp::g_entities[0].client->flags ^= 1; toggle_client_flag(1, "noclip");
game::CG_GameMessage(0, utils::string::va("noclip %s",
game::sp::g_entities[0].client->flags & 1
? "^2on"
: "^1off"));
}); });
add("ufo", []() add("ufo", []()
@ -474,11 +677,47 @@ namespace command
return; return;
} }
game::sp::g_entities[0].client->flags ^= 2; toggle_client_flag(2, "ufo");
game::CG_GameMessage(0, utils::string::va("ufo %s", });
game::sp::g_entities[0].client->flags & 2
? "^2on" add("give", [](const params& params)
: "^1off")); {
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&) 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; return;
} }
game::mp::g_entities[client_num].flags ^= 1; toggle_entity_flag(client_num, 1, "godmode");
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"));
}); });
add_sv("demigod", [](const int client_num, const params_sv&) 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; return;
} }
game::mp::g_entities[client_num].flags ^= 2; toggle_entity_flag(client_num, 2, "demigod mode");
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"));
}); });
add_sv("notarget", [](const int client_num, const params_sv&) 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; return;
} }
game::mp::g_entities[client_num].flags ^= 4; toggle_entity_flag(client_num, 4, "notarget");
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"));
}); });
add_sv("noclip", [](const int client_num, const params_sv&) 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; return;
} }
game::mp::g_entities[client_num].client->flags ^= 1; toggle_client_flag(client_num, 1, "noclip");
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"));
}); });
add_sv("ufo", [](const int client_num, const params_sv&) 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; return;
} }
game::mp::g_entities[client_num].client->flags ^= 2; toggle_client_flag(client_num, 2, "noclip");
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"));
}); });
add_sv("give", [](const int client_num, const params_sv& params) 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; 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; return;
} }
auto ps = game::SV_GetPlayerstateForClientNum(client_num); cmd_drop_weapon(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);
}
}
}); });
add_sv("take", [](const int client_num, const params_sv& params) 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; 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; return;
} }
auto ps = game::SV_GetPlayerstateForClientNum(client_num); cmd_kill(client_num);
const auto wp = game::G_GetWeaponForName(params.get(1));
if (wp)
{
game::G_TakePlayerWeapon(ps, wp);
}
}); });
} }
}; };

View File

@ -10,6 +10,7 @@ namespace command
int size() const; int size() const;
const char* get(int index) const; const char* get(int index) const;
std::string join(int index) const; std::string join(int index) const;
std::vector<std::string> get_all() const;
const char* operator[](const int index) const const char* operator[](const int index) const
{ {
@ -28,6 +29,7 @@ namespace command
int size() const; int size() const;
const char* get(int index) const; const char* get(int index) const;
std::string join(int index) const; std::string join(int index) const;
std::vector<std::string> get_all() const;
const char* operator[](const int index) const const char* operator[](const int index) const
{ {

View File

@ -0,0 +1,335 @@
#include <std_include.hpp>
#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<script_value> values)
{
this->id_ = make_array();
for (const auto& value : values)
{
this->push(value);
}
}
array::array(std::unordered_map<std::string, script_value> 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<int>(this->id_)});
}
}
void array::release() const
{
if (this->id_)
{
game::RemoveRefToValue(game::SCRIPT_OBJECT, {static_cast<int>(this->id_)});
}
}
std::vector<script_value> array::get_keys() const
{
std::vector<script_value> 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<int>(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<int>())
{
return this->get(key.as<int>());
}
else
{
return this->get(key.as<std::string>());
}
}
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<int>())
{
this->set(key.as<int>(), value);
}
else
{
this->set(key.as<std::string>(), 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_);
}
}

View File

@ -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<script_value>);
array(std::unordered_map<std::string, script_value>);
array(const array& other);
array(array&& other) noexcept;
~array();
array& operator=(const array& other);
array& operator=(array&& other) noexcept;
std::vector<script_value> 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 <typename I = int, typename S = std::string>
array_value operator[](const script_value& key) const
{
if (key.is<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>()) };
}
}
private:
void add() const;
void release() const;
unsigned int id_;
};
}

View File

@ -237,4 +237,15 @@ namespace scripting
// Add custom fields // Add custom fields
return get_custom_field(entity, field); 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;
}
} }

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "game/game.hpp" #include "game/game.hpp"
#include "entity.hpp" #include "entity.hpp"
#include "array.hpp"
#include "script_value.hpp" #include "script_value.hpp"
namespace scripting namespace scripting
@ -33,4 +34,6 @@ namespace scripting
script_value get_entity_field(const entity& entity, const std::string& field); script_value get_entity_field(const entity& entity, const std::string& field);
void notify(const entity& entity, const std::string& event, const std::vector<script_value>& arguments); void notify(const entity& entity, const std::string& event, const std::vector<script_value>& arguments);
unsigned int make_array();
} }

View File

@ -1494,12 +1494,12 @@ namespace scripting
{"setspectatedefaults", 0x82C5}, // SP 0x000000000 MP 0x140331EE0 {"setspectatedefaults", 0x82C5}, // SP 0x000000000 MP 0x140331EE0
{"getthirdpersoncrosshairoffset", 0x82C6}, // SP 0x000000000 MP 0x140332250 {"getthirdpersoncrosshairoffset", 0x82C6}, // SP 0x000000000 MP 0x140332250
{"disableweaponpickup", 0x82C7}, // SP 0x140262950 MP 0x14032EF00 {"disableweaponpickup", 0x82C7}, // SP 0x140262950 MP 0x14032EF00
{"_meth_82c8", 0x82C8}, // SP 0x140262A60 MP 0x14032EFF0 {"enableweaponpickup", 0x82C8}, // SP 0x140262A60 MP 0x14032EFF0
{"_meth_82c9", 0x82C9}, // SP 0x140262AB0 MP 0x14032F0D0 {"issplitscreenplayer", 0x82C9}, // SP 0x140262AB0 MP 0x14032F0D0
{"_meth_82ca", 0x82CA}, // SP 0x000000000 MP 0x1403322C0 {"issplitscreenplayerprimary", 0x82CA}, // SP 0x000000000 MP 0x1403322C0
{"getweaponslistexclusives", 0x82CB}, // SP 0x1402623D0 MP 0x14032E3A0 {"getweaponslistoffhands", 0x82CB}, // SP 0x1402623D0 MP 0x14032E3A0
{"_meth_82cc", 0x82CC}, // SP 0x1402624C0 MP 0x14032E4B0 {"getweaponslistitems", 0x82CC}, // SP 0x1402624C0 MP 0x14032E4B0
{"_meth_82cd", 0x82CD}, // SP 0x1402625B0 MP 0x14032E650 {"getweaponslistexclusives", 0x82CD}, // SP 0x1402625B0 MP 0x14032E650
{"getweaponslist", 0x82CE}, // SP 0x140262720 MP 0x14032E790 {"getweaponslist", 0x82CE}, // SP 0x140262720 MP 0x14032E790
{"canplayerplacesentry", 0x82CF}, // SP 0x140264D00 MP 0x140331530 {"canplayerplacesentry", 0x82CF}, // SP 0x140264D00 MP 0x140331530
{"canplayerplacetank", 0x82D0}, // SP 0x1402651B0 MP 0x1403292E0 {"canplayerplacetank", 0x82D0}, // SP 0x1402651B0 MP 0x1403292E0
@ -1559,8 +1559,8 @@ namespace scripting
{"setviewkickscale", 0x8306}, // SP 0x1402608B0 MP 0x14032CB90 {"setviewkickscale", 0x8306}, // SP 0x1402608B0 MP 0x14032CB90
{"getviewkickscale", 0x8307}, // SP 0x140260A80 MP 0x14032CCC0 {"getviewkickscale", 0x8307}, // SP 0x140260A80 MP 0x14032CCC0
{"getweaponslistall", 0x8308}, // SP 0x1402621A0 MP 0x14032E120 - getweaponslistoffhands {"getweaponslistall", 0x8308}, // SP 0x1402621A0 MP 0x14032E120 - getweaponslistoffhands
{"getweaponslistitems", 0x8309}, // SP 0x1402622E0 MP 0x14032E230 {"getweaponslistprimaries", 0x8309}, // SP 0x1402622E0 MP 0x14032E230
{"_meth_830a", 0x830A}, // SP 0x140261090 MP 0x14032C720 {"getnormalizedcameramovement", 0x830A}, // SP 0x140261090 MP 0x14032C720
{"giveweapon", 0x830B}, // SP 0x140262F00 MP 0x14032EA90f {"giveweapon", 0x830B}, // SP 0x140262F00 MP 0x14032EA90f
{"takeweapon", 0x830C}, // SP 0x140263380 MP 0x14032F210 {"takeweapon", 0x830C}, // SP 0x140263380 MP 0x14032F210
{"takeallweapons", 0x830D}, // SP 0x1402635B0 MP 0x14032F310 {"takeallweapons", 0x830D}, // SP 0x1402635B0 MP 0x14032F310
@ -1596,13 +1596,13 @@ namespace scripting
{"setreverb", 0x832B}, // SP 0x140266EA0 MP 0x14032B9C0 {"setreverb", 0x832B}, // SP 0x140266EA0 MP 0x14032B9C0
{"_meth_832c", 0x832C}, // SP 0x140267180 MP 0x14032B9E0 {"_meth_832c", 0x832C}, // SP 0x140267180 MP 0x14032B9E0
{"deactivatechannelvolumes", 0x832D}, // SP 0x140267410 MP 0x14032BB00 {"deactivatechannelvolumes", 0x832D}, // SP 0x140267410 MP 0x14032BB00
{"_meth_832e", 0x832E}, // SP 0x140265FA0 MP 0x140329C00 {"givestartammo", 0x832E}, // SP 0x140265FA0 MP 0x140329C00
{"_meth_832f", 0x832F}, // SP 0x140266200 MP 0x140329F00 {"givemaxammo", 0x832F}, // SP 0x140266200 MP 0x140329F00
{"_meth_8330", 0x8330}, // SP 0x140266560 MP 0x14032A240 {"getfractionstartammo", 0x8330}, // SP 0x140266560 MP 0x14032A240
{"_meth_8331", 0x8331}, // SP 0x140266820 MP 0x14032A6F0 {"getfractionmaxammo", 0x8331}, // SP 0x140266820 MP 0x14032A6F0
{"isdualwielding", 0x8332}, // SP 0x140266E10 MP 0x14032ABC0 {"isdualwielding", 0x8332}, // SP 0x140266E10 MP 0x14032ABC0
{"_meth_8333", 0x8333}, // SP 0x140267030 MP 0x14032AD00 {"isreloading", 0x8333}, // SP 0x140267030 MP 0x14032AD00
{"isreloading", 0x8334}, // SP 0x140267100 MP 0x14032AEE0 {"isswitchingweapon", 0x8334}, // SP 0x140267100 MP 0x14032AEE0
{"setorigin", 0x8335}, // SP 0x1402677C0 MP 0x14032B8D0 {"setorigin", 0x8335}, // SP 0x1402677C0 MP 0x14032B8D0
{"getvelocity", 0x8336}, // SP 0x1402604D0 MP 0x14032BC80 {"getvelocity", 0x8336}, // SP 0x1402604D0 MP 0x14032BC80
{"_meth_8337", 0x8337}, // SP 0x140260930 MP 0x14032BE70 {"_meth_8337", 0x8337}, // SP 0x140260930 MP 0x14032BE70

View File

@ -21,7 +21,7 @@ namespace scripting::lua
std::unordered_map<std::string, array_value> values; std::unordered_map<std::string, array_value> values;
const auto offset = 0xA000 * (id & 3); const auto offset = 0xFA00 * (id & 3);
auto current = game::scr_VarGlob->objectVariableChildren[id].firstChild; auto current = game::scr_VarGlob->objectVariableChildren[id].firstChild;
auto idx = 1; auto idx = 1;
@ -294,7 +294,7 @@ namespace scripting::lua
return entity_to_struct(state, value.get_raw().u.uintValue); return entity_to_struct(state, value.get_raw().u.uintValue);
} }
if (value.is<std::vector<script_value>>()) if (value.is<scripting::array>())
{ {
return entity_to_array(state, value.get_raw().u.uintValue); return entity_to_array(state, value.get_raw().u.uintValue);
} }

View File

@ -1,7 +1,7 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "script_value.hpp" #include "script_value.hpp"
#include "entity.hpp" #include "entity.hpp"
#include "array.hpp"
namespace scripting namespace scripting
{ {
@ -79,6 +79,15 @@ namespace scripting
this->value_ = variable; 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) script_value::script_value(const vector& value)
{ {
game::VariableValue variable{}; game::VariableValue variable{};
@ -194,7 +203,7 @@ namespace scripting
**************************************************************/ **************************************************************/
template <> template <>
bool script_value::is<std::vector<script_value>>() const bool script_value::is<array>() const
{ {
if (this->get_raw().type != game::SCRIPT_OBJECT) if (this->get_raw().type != game::SCRIPT_OBJECT)
{ {
@ -207,6 +216,12 @@ namespace scripting
return type == game::SCRIPT_ARRAY; return type == game::SCRIPT_ARRAY;
} }
template <>
array script_value::get() const
{
return array(this->get_raw().u.uintValue);
}
/*************************************************************** /***************************************************************
* Struct * Struct
**************************************************************/ **************************************************************/

View File

@ -6,6 +6,7 @@
namespace scripting namespace scripting
{ {
class entity; class entity;
class array;
class script_value class script_value
{ {
@ -24,6 +25,7 @@ namespace scripting
script_value(const std::string& value); script_value(const std::string& value);
script_value(const entity& value); script_value(const entity& value);
script_value(const array& value);
script_value(const vector& value); script_value(const vector& value);
@ -43,10 +45,11 @@ namespace scripting
const game::VariableValue& get_raw() const; const game::VariableValue& get_raw() const;
variable_value value_{};
private: private:
template <typename T> template <typename T>
T get() const; T get() const;
variable_value value_{};
}; };
} }

View File

@ -186,12 +186,11 @@ namespace game
struct scrVarGlob_t struct scrVarGlob_t
{ {
ObjectVariableValue objectVariableValue[56320]; ObjectVariableValue objectVariableValue[40960];
ObjectVariableChildren objectVariableChildren[56320]; ObjectVariableChildren objectVariableChildren[40960];
unsigned __int16 childVariableBucket[65536]; unsigned __int16 childVariableBucket[65536];
ChildVariableValue childVariableValue[384000]; ChildVariableValue childVariableValue[384000];
}; };
// *
enum Sys_Folder enum Sys_Folder
{ {
@ -1009,11 +1008,11 @@ namespace game
enum XAssetType enum XAssetType
{ {
ASSET_TYPE_PHYSPRESET, ASSET_TYPE_PHYSPRESET,
ASSET_TYPE_PHYSCOLLMAP, ASSET_TYPE_PHYS_COLLMAP,
ASSET_TYPE_PHYSWATERPRESET, ASSET_TYPE_PHYSWATERPRESET,
ASSET_TYPE_PHYSWORLDMAP, ASSET_TYPE_PHYS_WORLDMAP,
ASSET_TYPE_PHYSCONSTRAINT, ASSET_TYPE_PHYSCONSTRAINT,
ASSET_TYPE_XANIMPARTS, ASSET_TYPE_XANIM,
ASSET_TYPE_XMODELSURFS, ASSET_TYPE_XMODELSURFS,
ASSET_TYPE_XMODEL, ASSET_TYPE_XMODEL,
ASSET_TYPE_MATERIAL, ASSET_TYPE_MATERIAL,
@ -1023,36 +1022,35 @@ namespace game
ASSET_TYPE_DOMAINSHADER, ASSET_TYPE_DOMAINSHADER,
ASSET_TYPE_PIXELSHADER, ASSET_TYPE_PIXELSHADER,
ASSET_TYPE_VERTEXDECL, ASSET_TYPE_VERTEXDECL,
ASSET_TYPE_TECHNIQUE_SET, ASSET_TYPE_TECHSET,
ASSET_TYPE_IMAGE, ASSET_TYPE_IMAGE,
ASSET_TYPE_SOUND, ASSET_TYPE_SOUND,
ASSET_TYPE_SOUND_SUBMIX, ASSET_TYPE_SOUNDSUBMIX,
ASSET_TYPE_SOUND_CURVE, ASSET_TYPE_SNDCURVE,
ASSET_TYPE_LPF_CURVE, ASSET_TYPE_LPFCURVE,
ASSET_TYPE_REVERB_CURVE, ASSET_TYPE_REVERBSENDCURVE,
ASSET_TYPE_SOUND_CONTEXT, ASSET_TYPE_SNDCONTEXT,
ASSET_TYPE_LOADED_SOUND, ASSET_TYPE_LOADED_SOUND,
ASSET_TYPE_CLIPMAP, ASSET_TYPE_COL_MAP_MP,
ASSET_TYPE_COMWORLD, ASSET_TYPE_COM_MAP,
ASSET_TYPE_GLASSWORLD, ASSET_TYPE_GLASS_MAP,
ASSET_TYPE_PATHDATA, ASSET_TYPE_AIPATHS,
ASSET_TYPE_VEHICLE_TRACK, ASSET_TYPE_VEHICLE_TRACK,
ASSET_TYPE_MAP_ENTS, ASSET_TYPE_MAP_ENTS,
ASSET_TYPE_FXWORLD, ASSET_TYPE_FX_MAP,
ASSET_TYPE_GFXWORLD, ASSET_TYPE_GFX_MAP,
ASSET_TYPE_LIGHT_DEF, ASSET_TYPE_LIGHTDEF,
ASSET_TYPE_UI_MAP, ASSET_TYPE_UI_MAP,
ASSET_TYPE_FONT, ASSET_TYPE_MENUFILE,
ASSET_TYPE_MENULIST,
ASSET_TYPE_MENU, ASSET_TYPE_MENU,
ASSET_TYPE_ANIMCLASS, ASSET_TYPE_ANIMCLASS,
ASSET_TYPE_LOCALIZE_ENTRY, ASSET_TYPE_LOCALIZE,
ASSET_TYPE_ATTACHMENT, ASSET_TYPE_ATTACHMENT,
ASSET_TYPE_WEAPON, ASSET_TYPE_WEAPON,
ASSET_TYPE_SNDDRIVER_GLOBALS, ASSET_TYPE_SNDDRIVERGLOBALS,
ASSET_TYPE_FX, ASSET_TYPE_FX,
ASSET_TYPE_IMPACT_FX, ASSET_TYPE_IMPACTFX,
ASSET_TYPE_SURFACE_FX, ASSET_TYPE_SURFACEFX,
ASSET_TYPE_AITYPE, ASSET_TYPE_AITYPE,
ASSET_TYPE_MPTYPE, ASSET_TYPE_MPTYPE,
ASSET_TYPE_CHARACTER, ASSET_TYPE_CHARACTER,
@ -1060,23 +1058,27 @@ namespace game
ASSET_TYPE_RAWFILE, ASSET_TYPE_RAWFILE,
ASSET_TYPE_SCRIPTFILE, ASSET_TYPE_SCRIPTFILE,
ASSET_TYPE_STRINGTABLE, ASSET_TYPE_STRINGTABLE,
ASSET_TYPE_LEADERBOARD, ASSET_TYPE_LEADERBOARDDEF,
ASSET_TYPE_STRUCTURED_DATA_DEF, ASSET_TYPE_VIRTUALLEADERBOARDDEF,
ASSET_TYPE_STRUCTUREDDATADEF,
ASSET_TYPE_DDL,
ASSET_TYPE_PROTO,
ASSET_TYPE_TRACER, ASSET_TYPE_TRACER,
ASSET_TYPE_VEHICLE, ASSET_TYPE_VEHICLE,
ASSET_TYPE_ADDON_MAP_ENTS, ASSET_TYPE_ADDON_MAP_ENTS,
ASSET_TYPE_NET_CONST_STRINGS, ASSET_TYPE_NETCONSTSTRINGS,
ASSET_TYPE_REVERB_PRESET, ASSET_TYPE_REVERBPRESET,
ASSET_TYPE_LUA_FILE, ASSET_TYPE_LUAFILE,
ASSET_TYPE_SCRIPTABLE, ASSET_TYPE_SCRIPTABLE,
ASSET_TYPE_EQUIPMENT_SND_TABLE, ASSET_TYPE_EQUIPSNDTABLE,
ASSET_TYPE_VECTORFIELD, ASSET_TYPE_VECTORFIELD,
ASSET_TYPE_DOPPLER_PRESET, ASSET_TYPE_DOPPLERPRESET,
ASSET_TYPE_PARTICLE_SIM_ANIMATION, ASSET_TYPE_PARTICLESIMANIMATION,
ASSET_TYPE_LASER, ASSET_TYPE_LASER,
ASSET_TYPE_SKELETON_SCRIPT, ASSET_TYPE_SKELETONSCRIPT,
ASSET_TYPE_CLUT, ASSET_TYPE_CLUT,
ASSET_TYPE_COUNT, ASSET_TYPE_TTF,
ASSET_TYPE_COUNT
}; };
enum GfxDrawSceneMethod enum GfxDrawSceneMethod

View File

@ -13,6 +13,7 @@ namespace game
WEAK symbol<void(unsigned int id)> AddRefToObject{0x14036E5F0, 0x14043C570}; WEAK symbol<void(unsigned int id)> AddRefToObject{0x14036E5F0, 0x14043C570};
WEAK symbol<void(unsigned int id)> RemoveRefToObject{0x14036FFE0, 0x14043DF80}; WEAK symbol<void(unsigned int id)> RemoveRefToObject{0x14036FFE0, 0x14043DF80};
WEAK symbol<unsigned int(unsigned int id)> AllocThread{0x14036E960, 0x14043C8E0}; WEAK symbol<unsigned int(unsigned int id)> AllocThread{0x14036E960, 0x14043C8E0};
WEAK symbol<ObjectVariableValue*(unsigned int* id)> AllocVariable{0x14036E9C0, 0x14043C940};
WEAK symbol<void(int localClientNum, const char* text)> Cbuf_AddText{0x140342EB0, 0x1404033B0}; WEAK symbol<void(int localClientNum, const char* text)> Cbuf_AddText{0x140342EB0, 0x1404033B0};
WEAK symbol<void(int localClientNum, int controllerIndex, const char* buffer, WEAK symbol<void(int localClientNum, int controllerIndex, const char* buffer,
@ -70,7 +71,8 @@ namespace game
WEAK symbol<void(const char* path, const char* dir)> FS_AddLocalizedGameDirectory{0x1403B6030, 0x1404EBE20}; WEAK symbol<void(const char* path, const char* dir)> FS_AddLocalizedGameDirectory{0x1403B6030, 0x1404EBE20};
WEAK symbol<unsigned int(unsigned int, unsigned int)> GetVariable{0x14036FDD0, 0x1403F3730}; WEAK symbol<unsigned int(unsigned int, unsigned int)> GetVariable{0x14036FDD0, 0x1403F3730};
WEAK symbol<unsigned int(unsigned int parentId, unsigned int unsignedValue)> GetNewVariable{0x14036FA00, 0x14043D990};
WEAK symbol<unsigned int(unsigned int parentId, unsigned int unsignedValue)> GetNewArrayVariable{0x14036F880, 0x14043D810};
WEAK symbol<void()> GScr_LoadConsts{0x1402D13E0, 0x140393810}; WEAK symbol<void()> GScr_LoadConsts{0x1402D13E0, 0x140393810};
WEAK symbol<unsigned int(unsigned int parentId, unsigned int name)> FindVariable{0x14036F4B0, 0x14043D430}; WEAK symbol<unsigned int(unsigned int parentId, unsigned int name)> FindVariable{0x14036F4B0, 0x14043D430};
WEAK symbol<unsigned int(int entnum, unsigned int classnum)> FindEntityId{0x14036F3B0, 0x14043D330}; WEAK symbol<unsigned int(int entnum, unsigned int classnum)> FindEntityId{0x14036F3B0, 0x14043D330};
@ -197,21 +199,21 @@ namespace game
WEAK symbol<CmdArgs> sv_cmd_args{0x14AD99A10, 0x14946BA20}; WEAK symbol<CmdArgs> sv_cmd_args{0x14AD99A10, 0x14946BA20};
WEAK symbol<int> g_script_error_level{0x14A1917A8, 0x14A33C824}; WEAK symbol<int> g_script_error_level{0x14BCFA4A4, 0x14A33C824};
WEAK symbol<jmp_buf> g_script_error{0x14A1917B0, 0x14A33C940}; WEAK symbol<jmp_buf> g_script_error{0x14BCFA5C0, 0x14A33C940};
WEAK symbol<unsigned int> levelEntityId{0x149AF55B0, 0x149CA0730}; WEAK symbol<unsigned int> levelEntityId{0x14B65E3B0, 0x149CA0730};
WEAK symbol<unsigned int> gameEntityId{0x149CA0734, 0x14B65E3B4}; WEAK symbol<unsigned int> gameEntityId{0x14B65E3B4, 0x149CA0734};
WEAK symbol<const char*> command_whitelist{0x141079A60, 0x14120C360}; WEAK symbol<const char*> command_whitelist{0x141079A60, 0x14120C360};
WEAK symbol<cmd_function_s*> cmd_functions{0x14AD99AB8, 0x14946BAC8}; WEAK symbol<cmd_function_s*> cmd_functions{0x14AD99AB8, 0x14946BAC8};
WEAK symbol<CmdArgs> cmd_args{0x14AD99960, 0x14946B970}; WEAK symbol<CmdArgs> cmd_args{0x14AD99960, 0x14946B970};
WEAK symbol<int> g_poolSize{0, 0x140FEADF0}; WEAK symbol<int> g_poolSize{0x140DE84A0, 0x140FEADF0};
WEAK symbol<scr_classStruct_t> g_classMap{0x14080A840, 0x1412106B0}; WEAK symbol<scr_classStruct_t> g_classMap{0x14107AAF0, 0x1412106B0};
WEAK symbol<scrVarGlob_t> scr_VarGlob{0x14B686480, 0x149CC8800}; WEAK symbol<scrVarGlob_t> scr_VarGlob{0x14B686480, 0x149CC8800};
WEAK symbol<scrVmPub_t> scr_VmPub{0x14A1938C0, 0x14A33EA40}; WEAK symbol<scrVmPub_t> scr_VmPub{0x14BCFC6C0, 0x14A33EA40};
WEAK symbol<function_stack_t> scr_function_stack{0x14BD06C40, 0x14A348FC0}; WEAK symbol<function_stack_t> scr_function_stack{0x14BD06C40, 0x14A348FC0};
WEAK symbol<GfxDrawMethod_s> gfxDrawMethod{0x14F05CE50, 0x14FD21180}; WEAK symbol<GfxDrawMethod_s> gfxDrawMethod{0x14F05CE50, 0x14FD21180};