Add more commands + fixes
This commit is contained in:
335
src/client/game/scripting/array.cpp
Normal file
335
src/client/game/scripting/array.cpp
Normal 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_);
|
||||
}
|
||||
}
|
87
src/client/game/scripting/array.hpp
Normal file
87
src/client/game/scripting/array.hpp
Normal 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_;
|
||||
};
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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<script_value>& arguments);
|
||||
|
||||
unsigned int make_array();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -21,7 +21,7 @@ namespace scripting::lua
|
||||
|
||||
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 idx = 1;
|
||||
@ -294,7 +294,7 @@ namespace scripting::lua
|
||||
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);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include <std_include.hpp>
|
||||
#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<std::vector<script_value>>() const
|
||||
bool script_value::is<array>() 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
|
||||
**************************************************************/
|
||||
|
@ -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 <typename T>
|
||||
T get() const;
|
||||
|
||||
variable_value value_{};
|
||||
};
|
||||
}
|
||||
|
Reference in New Issue
Block a user