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

@ -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
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
#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();
}

View File

@ -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

View File

@ -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);
}

View File

@ -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
**************************************************************/

View File

@ -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_{};
};
}