mirror of
https://github.com/alicealys/t5-gsc-utils.git
synced 2025-07-07 11:41:52 +00:00
Initial commit
This commit is contained in:
324
src/game/scripting/array.cpp
Normal file
324
src/game/scripting/array.cpp
Normal file
@ -0,0 +1,324 @@
|
||||
#include <stdinc.hpp>
|
||||
#include "array.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->variableList[this->id_];
|
||||
game::VariableValue variable{};
|
||||
variable.u = value.u.u;
|
||||
variable.type = value.w.type & 0x1F;
|
||||
|
||||
this->value_ = variable;
|
||||
}
|
||||
|
||||
void array_value::operator=(const script_value& value)
|
||||
{
|
||||
if (!this->id_)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto& value_0 = value.get_raw();
|
||||
|
||||
const auto variable = &game::scr_VarGlob->variableList[this->id_];
|
||||
game::VariableValue variable_{};
|
||||
variable_.type = variable->w.type & 0x1F;
|
||||
variable_.u = variable->u.u;
|
||||
|
||||
game::AddRefToValue(game::SCRIPTINSTANCE_SERVER, &value_0);
|
||||
game::RemoveRefToValue(game::SCRIPTINSTANCE_SERVER, variable_.type, variable_.u);
|
||||
|
||||
variable->w.type = value_0.type & 0x1F;
|
||||
variable->u.u = value_0.u;
|
||||
|
||||
this->value_ = value_0;
|
||||
}
|
||||
|
||||
array::array(const unsigned int id)
|
||||
: id_(id)
|
||||
{
|
||||
this->add();
|
||||
}
|
||||
|
||||
array::array(const array& other)
|
||||
{
|
||||
this->operator=(other);
|
||||
}
|
||||
|
||||
array::array(array&& other) noexcept
|
||||
{
|
||||
this->id_ = other.id_;
|
||||
other.id_ = 0;
|
||||
}
|
||||
|
||||
array::array()
|
||||
{
|
||||
this->id_ = game::Scr_AllocArray(game::SCRIPTINSTANCE_SERVER);
|
||||
}
|
||||
|
||||
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::VariableValue value{};
|
||||
value.u.uintValue = this->id_;
|
||||
value.type = game::SCRIPT_OBJECT;
|
||||
|
||||
game::AddRefToValue(game::SCRIPTINSTANCE_SERVER, &value);
|
||||
}
|
||||
}
|
||||
|
||||
void array::release() const
|
||||
{
|
||||
if (this->id_)
|
||||
{
|
||||
game::VariableValue value{};
|
||||
value.u.uintValue = this->id_;
|
||||
value.type = game::SCRIPT_OBJECT;
|
||||
|
||||
game::RemoveRefToValue(game::SCRIPTINSTANCE_SERVER, value.type, value.u);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<script_value> array::get_keys() const
|
||||
{
|
||||
std::vector<script_value> result;
|
||||
|
||||
auto current = game::scr_VarGlob->variableList[this->id_ + 1].nextSibling;
|
||||
|
||||
while (current)
|
||||
{
|
||||
const auto var = &game::scr_VarGlob->variableList[current + 0x8000];
|
||||
const auto key_value = game::Scr_GetArrayIndexValue(game::SCRIPTINSTANCE_SERVER, var->w.status >> 8);
|
||||
result.push_back(key_value);
|
||||
|
||||
const auto next_sibling = game::scr_VarGlob->variableList[current + 0x8000].nextSibling;
|
||||
if (!next_sibling)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
current = game::scr_VarGlob->variableList[next_sibling + 0x8000].hash.id;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned int array::size() const
|
||||
{
|
||||
return game::Scr_GetSelf(game::SCRIPTINSTANCE_SERVER, this->id_);
|
||||
}
|
||||
|
||||
unsigned int array::push(const 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::FindArrayVariable(game::SCRIPTINSTANCE_SERVER, this->id_, index);
|
||||
if (variable_id)
|
||||
{
|
||||
game::RemoveVariableValue(game::SCRIPTINSTANCE_SERVER, this->id_, variable_id);
|
||||
}
|
||||
}
|
||||
|
||||
void array::erase(const std::string& key) const
|
||||
{
|
||||
const auto string_value = game::SL_GetString(key.data(), 0, game::SCRIPTINSTANCE_SERVER);
|
||||
const auto variable_id = game::FindVariable(game::SCRIPTINSTANCE_SERVER, this->id_, string_value);
|
||||
if (variable_id)
|
||||
{
|
||||
game::RemoveVariableValue(game::SCRIPTINSTANCE_SERVER, 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 std::string& key) const
|
||||
{
|
||||
const auto string_value = game::SL_GetString(key.data(), 0, game::SCRIPTINSTANCE_SERVER);
|
||||
const auto variable_id = game::FindVariable(game::SCRIPTINSTANCE_SERVER, this->id_, string_value);
|
||||
|
||||
if (!variable_id)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto value = game::scr_VarGlob->variableList[variable_id + 0x8000];
|
||||
game::VariableValue variable{};
|
||||
variable.u = value.u.u;
|
||||
variable.type = value.w.type & 0x1F;
|
||||
|
||||
return variable;
|
||||
}
|
||||
|
||||
script_value array::get(const unsigned int index) const
|
||||
{
|
||||
const auto variable_id = game::FindArrayVariable(game::SCRIPTINSTANCE_SERVER, this->id_, index);
|
||||
|
||||
if (!variable_id)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto value = game::scr_VarGlob->variableList[variable_id + 0x8000];
|
||||
game::VariableValue variable{};
|
||||
variable.u = value.u.u;
|
||||
variable.type = value.w.type & 0x1F;
|
||||
|
||||
return variable;
|
||||
}
|
||||
|
||||
script_value array::get(const script_value& key) const
|
||||
{
|
||||
if (key.is<int>())
|
||||
{
|
||||
this->get(key.as<int>());
|
||||
}
|
||||
|
||||
if (key.is<std::string>())
|
||||
{
|
||||
this->get(key.as<std::string>());
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
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->variableList[variable_id + 0x8000];
|
||||
game::VariableValue variable_{};
|
||||
variable_.type = variable->w.type & 0x1F;
|
||||
variable_.u = variable->u.u;
|
||||
|
||||
game::AddRefToValue(game::SCRIPTINSTANCE_SERVER, &value_);
|
||||
game::RemoveRefToValue(game::SCRIPTINSTANCE_SERVER, variable_.type, variable_.u);
|
||||
|
||||
variable->w.type |= 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;
|
||||
}
|
||||
|
||||
auto variable_list = *game::scr_VarGlob;
|
||||
const auto variable = &game::scr_VarGlob->variableList[variable_id + 0x8000];
|
||||
game::VariableValue variable_{};
|
||||
variable_.type = variable->w.type & 0x1F;
|
||||
variable_.u = variable->u.u;
|
||||
|
||||
game::AddRefToValue(game::SCRIPTINSTANCE_SERVER, &value_);
|
||||
game::RemoveRefToValue(game::SCRIPTINSTANCE_SERVER, variable_.type, variable_.u);
|
||||
|
||||
variable->w.type |= value_.type;
|
||||
variable->u.u = value_.u;
|
||||
}
|
||||
|
||||
void array::set(const script_value& key, const script_value& _value) const
|
||||
{
|
||||
if (key.is<int>())
|
||||
{
|
||||
this->set(key.as<int>(), _value);
|
||||
}
|
||||
|
||||
if (key.is<std::string>())
|
||||
{
|
||||
this->set(key.as<std::string>(), _value);
|
||||
}
|
||||
}
|
||||
|
||||
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, game::SCRIPTINSTANCE_SERVER);
|
||||
const auto variable_id = game::FindVariable(game::SCRIPTINSTANCE_SERVER, this->id_, string_value);
|
||||
|
||||
if (!variable_id)
|
||||
{
|
||||
return game::GetNewVariable(game::SCRIPTINSTANCE_SERVER, this->id_, string_value);
|
||||
}
|
||||
|
||||
return variable_id;
|
||||
}
|
||||
|
||||
unsigned int array::get_value_id(const unsigned int index) const
|
||||
{
|
||||
const auto variable_id = game::FindArrayVariable(game::SCRIPTINSTANCE_SERVER, this->id_, index);
|
||||
if (!variable_id)
|
||||
{
|
||||
return game::GetNewArrayVariable(game::SCRIPTINSTANCE_SERVER, this->id_, index);
|
||||
}
|
||||
|
||||
return variable_id;
|
||||
}
|
||||
|
||||
entity array::get_raw() const
|
||||
{
|
||||
return entity(this->id_);
|
||||
}
|
||||
}
|
83
src/game/scripting/array.hpp
Normal file
83
src/game/scripting/array.hpp
Normal file
@ -0,0 +1,83 @@
|
||||
#pragma once
|
||||
#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(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;
|
||||
unsigned int size() const;
|
||||
|
||||
unsigned int push(const 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_{};
|
||||
};
|
||||
}
|
120
src/game/scripting/entity.cpp
Normal file
120
src/game/scripting/entity.cpp
Normal file
@ -0,0 +1,120 @@
|
||||
#include <stdinc.hpp>
|
||||
#include "entity.hpp"
|
||||
#include "script_value.hpp"
|
||||
#include "execution.hpp"
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
entity::entity()
|
||||
: entity(0)
|
||||
{
|
||||
}
|
||||
|
||||
entity::entity(const entity& other) : entity(other.entity_id_)
|
||||
{
|
||||
}
|
||||
|
||||
entity::entity(entity&& other) noexcept
|
||||
{
|
||||
this->entity_id_ = other.entity_id_;
|
||||
other.entity_id_ = 0;
|
||||
}
|
||||
|
||||
entity::entity(const unsigned int entity_id)
|
||||
: entity_id_(entity_id)
|
||||
{
|
||||
this->add();
|
||||
}
|
||||
|
||||
entity::~entity()
|
||||
{
|
||||
this->release();
|
||||
}
|
||||
|
||||
entity& entity::operator=(const entity& other)
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
this->release();
|
||||
this->entity_id_ = other.entity_id_;
|
||||
this->add();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
entity& entity::operator=(entity&& other) noexcept
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
this->release();
|
||||
this->entity_id_ = other.entity_id_;
|
||||
other.entity_id_ = 0;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
unsigned int entity::get_entity_id() const
|
||||
{
|
||||
return this->entity_id_;
|
||||
}
|
||||
|
||||
game::scr_entref_t entity::get_entity_reference() const
|
||||
{
|
||||
if (!this->entity_id_)
|
||||
{
|
||||
const auto not_null = static_cast<uint16_t>(~0ui16);
|
||||
return game::scr_entref_t{not_null, not_null};
|
||||
}
|
||||
|
||||
game::scr_entref_t entref{};
|
||||
game::Scr_GetEntityIdRef(&entref, game::SCRIPTINSTANCE_SERVER, this->get_entity_id());
|
||||
return entref;
|
||||
}
|
||||
|
||||
bool entity::operator==(const entity& other) const noexcept
|
||||
{
|
||||
return this->get_entity_id() == other.get_entity_id();
|
||||
}
|
||||
|
||||
bool entity::operator!=(const entity& other) const noexcept
|
||||
{
|
||||
return !this->operator==(other);
|
||||
}
|
||||
|
||||
void entity::add() const
|
||||
{
|
||||
if (this->entity_id_)
|
||||
{
|
||||
game::VariableValue value;
|
||||
value.type = game::SCRIPT_OBJECT;
|
||||
value.u.uintValue = this->entity_id_;
|
||||
|
||||
game::AddRefToValue(game::SCRIPTINSTANCE_SERVER, &value);
|
||||
}
|
||||
}
|
||||
|
||||
void entity::release() const
|
||||
{
|
||||
if (this->entity_id_)
|
||||
{
|
||||
game::VariableValue value;
|
||||
value.type = game::SCRIPT_OBJECT;
|
||||
value.u.uintValue = this->entity_id_;
|
||||
|
||||
game::RemoveRefToValue(game::SCRIPTINSTANCE_SERVER, value.type, value.u);
|
||||
}
|
||||
}
|
||||
|
||||
void entity::set(const std::string& field, const script_value& value) const
|
||||
{
|
||||
set_entity_field(*this, field, value);
|
||||
}
|
||||
|
||||
template <>
|
||||
script_value entity::get<script_value>(const std::string& field) const
|
||||
{
|
||||
return get_entity_field(*this, field);
|
||||
}
|
||||
}
|
47
src/game/scripting/entity.hpp
Normal file
47
src/game/scripting/entity.hpp
Normal file
@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
#include "game/game.hpp"
|
||||
#include "script_value.hpp"
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
class entity final
|
||||
{
|
||||
public:
|
||||
entity();
|
||||
entity(unsigned int entity_id);
|
||||
|
||||
entity(const entity& other);
|
||||
entity(entity&& other) noexcept;
|
||||
|
||||
~entity();
|
||||
|
||||
entity& operator=(const entity& other);
|
||||
entity& operator=(entity&& other) noexcept;
|
||||
|
||||
void set(const std::string& field, const script_value& value) const;
|
||||
|
||||
template <typename T = script_value>
|
||||
T get(const std::string& field) const;
|
||||
|
||||
unsigned int get_entity_id() const;
|
||||
game::scr_entref_t get_entity_reference() const;
|
||||
|
||||
bool operator ==(const entity& other) const noexcept;
|
||||
bool operator !=(const entity& other) const noexcept;
|
||||
|
||||
private:
|
||||
unsigned int entity_id_;
|
||||
|
||||
void add() const;
|
||||
void release() const;
|
||||
};
|
||||
|
||||
template <>
|
||||
script_value entity::get(const std::string& field) const;
|
||||
|
||||
template <typename T>
|
||||
T entity::get(const std::string& field) const
|
||||
{
|
||||
return this->get<script_value>(field).as<T>();
|
||||
}
|
||||
}
|
13
src/game/scripting/event.hpp
Normal file
13
src/game/scripting/event.hpp
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
#include "script_value.hpp"
|
||||
#include "entity.hpp"
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
struct event
|
||||
{
|
||||
std::string name;
|
||||
entity entity{};
|
||||
std::vector<script_value> arguments;
|
||||
};
|
||||
}
|
160
src/game/scripting/execution.cpp
Normal file
160
src/game/scripting/execution.cpp
Normal file
@ -0,0 +1,160 @@
|
||||
#include <stdinc.hpp>
|
||||
#include "execution.hpp"
|
||||
#include "safe_execution.hpp"
|
||||
#include "stack_isolation.hpp"
|
||||
|
||||
#include "component/scripting.hpp"
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
namespace
|
||||
{
|
||||
game::VariableValue* allocate_argument()
|
||||
{
|
||||
game::VariableValue* value_ptr = ++game::scr_VmPub->top;
|
||||
++game::scr_VmPub->inparamcount;
|
||||
return value_ptr;
|
||||
}
|
||||
|
||||
script_value get_return_value()
|
||||
{
|
||||
if (game::scr_VmPub->inparamcount == 0)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
game::Scr_ClearOutParams(game::SCRIPTINSTANCE_SERVER);
|
||||
game::scr_VmPub->outparamcount = game::scr_VmPub->inparamcount;
|
||||
game::scr_VmPub->inparamcount = 0;
|
||||
|
||||
return script_value(game::scr_VmPub->top[1 - game::scr_VmPub->outparamcount]);
|
||||
}
|
||||
|
||||
int get_field_id(const int classnum, const std::string& field)
|
||||
{
|
||||
if (scripting::fields_table[classnum].find(field) != scripting::fields_table[classnum].end())
|
||||
{
|
||||
return scripting::fields_table[classnum][field];
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void push_value(const script_value& value)
|
||||
{
|
||||
auto* value_ptr = allocate_argument();
|
||||
*value_ptr = value.get_raw();
|
||||
|
||||
game::AddRefToValue(game::SCRIPTINSTANCE_SERVER, value_ptr);
|
||||
}
|
||||
|
||||
void notify(const entity& entity, const std::string& event, const std::vector<script_value>& arguments)
|
||||
{
|
||||
stack_isolation _;
|
||||
for (auto i = arguments.rbegin(); i != arguments.rend(); ++i)
|
||||
{
|
||||
push_value(*i);
|
||||
}
|
||||
|
||||
const auto event_id = game::SL_GetString(event.data(), 0, game::SCRIPTINSTANCE_SERVER);
|
||||
game::Scr_NotifyId(game::SCRIPTINSTANCE_SERVER, 0, entity.get_entity_id(), event_id, game::scr_VmPub->inparamcount);
|
||||
}
|
||||
|
||||
script_value exec_ent_thread(const entity& entity, const char* pos, const std::vector<script_value>& arguments)
|
||||
{
|
||||
const auto id = entity.get_entity_id();
|
||||
|
||||
stack_isolation _;
|
||||
for (auto i = arguments.rbegin(); i != arguments.rend(); ++i)
|
||||
{
|
||||
push_value(*i);
|
||||
}
|
||||
|
||||
game::VariableValue value{};
|
||||
value.type = game::SCRIPT_OBJECT;
|
||||
value.u.uintValue = id;
|
||||
game::AddRefToValue(game::SCRIPTINSTANCE_SERVER, &value);
|
||||
|
||||
const auto local_id = game::AllocThread(game::SCRIPTINSTANCE_SERVER, id);
|
||||
const auto result = game::VM_Execute(game::SCRIPTINSTANCE_SERVER, local_id, pos, arguments.size());
|
||||
game::RemoveRefToObject(game::SCRIPTINSTANCE_SERVER, result);
|
||||
|
||||
return get_return_value();
|
||||
}
|
||||
|
||||
script_value get_custom_field(const entity& entity, const std::string& field)
|
||||
{
|
||||
const object object = entity.get_entity_id();
|
||||
return object.get(field);
|
||||
}
|
||||
|
||||
void set_custom_field(const entity& entity, const std::string& field, const script_value& value)
|
||||
{
|
||||
const object object = entity.get_entity_id();
|
||||
object.set(field, value);
|
||||
}
|
||||
|
||||
void set_entity_field(const entity& entity, const std::string& field, const script_value& value)
|
||||
{
|
||||
const auto entref = entity.get_entity_reference();
|
||||
const int id = get_field_id(entref.classnum, field);
|
||||
|
||||
if (id != -1)
|
||||
{
|
||||
stack_isolation _;
|
||||
push_value(value);
|
||||
|
||||
game::scr_VmPub->outparamcount = game::scr_VmPub->inparamcount;
|
||||
game::scr_VmPub->inparamcount = 0;
|
||||
|
||||
if (!safe_execution::set_entity_field(entref, id))
|
||||
{
|
||||
throw std::runtime_error("Failed to set value for field '" + field + "'");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
set_custom_field(entity, field, value);
|
||||
}
|
||||
}
|
||||
|
||||
script_value get_entity_field(const entity& entity, const std::string& field)
|
||||
{
|
||||
const auto entref = entity.get_entity_reference();
|
||||
const auto id = get_field_id(entref.classnum, field);
|
||||
|
||||
if (id != -1)
|
||||
{
|
||||
stack_isolation _;
|
||||
|
||||
game::VariableValue value{};
|
||||
if (!safe_execution::get_entity_field(entref, id, &value))
|
||||
{
|
||||
throw std::runtime_error("Failed to get value for field '" + field + "'");
|
||||
}
|
||||
|
||||
const auto __ = gsl::finally([&value]()
|
||||
{
|
||||
game::RemoveRefToValue(game::SCRIPTINSTANCE_SERVER, value.type, value.u);
|
||||
});
|
||||
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return get_custom_field(entity, field);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int make_object()
|
||||
{
|
||||
unsigned int index = 0;
|
||||
const auto id = game::AllocVariable(game::SCRIPTINSTANCE_SERVER);
|
||||
const auto variable = &game::scr_VarGlob->variableList[id + 1];
|
||||
variable->w.type = game::SCRIPT_STRUCT;
|
||||
variable->u.o.refCount = 0;
|
||||
|
||||
return index;
|
||||
}
|
||||
}
|
22
src/game/scripting/execution.hpp
Normal file
22
src/game/scripting/execution.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "game/game.hpp"
|
||||
#include "entity.hpp"
|
||||
#include "array.hpp"
|
||||
#include "object.hpp"
|
||||
#include "function.hpp"
|
||||
#include "thread.hpp"
|
||||
#include "script_value.hpp"
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
void push_value(const script_value& value);
|
||||
|
||||
script_value exec_ent_thread(const entity& entity, const char* pos, const std::vector<script_value>& arguments);
|
||||
|
||||
void set_entity_field(const entity& entity, const std::string& field, const script_value& value);
|
||||
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_object();
|
||||
}
|
42
src/game/scripting/function.cpp
Normal file
42
src/game/scripting/function.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
#include <stdinc.hpp>
|
||||
#include "function.hpp"
|
||||
#include "execution.hpp"
|
||||
#include "../../component/scripting.hpp"
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
function::function(const char* pos)
|
||||
: pos_(pos)
|
||||
{
|
||||
}
|
||||
|
||||
script_value function::get_raw() const
|
||||
{
|
||||
game::VariableValue value;
|
||||
value.type = game::SCRIPT_FUNCTION;
|
||||
value.u.codePosValue = this->pos_;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
const char* function::get_pos() const
|
||||
{
|
||||
return this->pos_;
|
||||
}
|
||||
|
||||
std::string function::get_name() const
|
||||
{
|
||||
if (scripting::script_function_table_rev.find(this->pos_) != scripting::script_function_table_rev.end())
|
||||
{
|
||||
const auto& func = scripting::script_function_table_rev[this->pos_];
|
||||
return utils::string::va("%s::%s", func.first.data(), func.second.data());
|
||||
}
|
||||
|
||||
return "unknown function";
|
||||
}
|
||||
|
||||
script_value function::call(const entity& self, const arguments& arguments) const
|
||||
{
|
||||
return exec_ent_thread(self, this->pos_, arguments);
|
||||
}
|
||||
}
|
48
src/game/scripting/function.hpp
Normal file
48
src/game/scripting/function.hpp
Normal file
@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
#include "entity.hpp"
|
||||
#include "script_value.hpp"
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
class function
|
||||
{
|
||||
public:
|
||||
function(const char*);
|
||||
|
||||
script_value get_raw() const;
|
||||
const char* get_pos() const;
|
||||
std::string get_name() const;
|
||||
|
||||
script_value call(const entity& self, const arguments& arguments) const;
|
||||
|
||||
script_value operator()(const entity& self, const arguments& arguments) const
|
||||
{
|
||||
return this->call(self, arguments);
|
||||
}
|
||||
|
||||
script_value operator()(const arguments& arguments) const
|
||||
{
|
||||
return this->call(*game::levelEntityId, arguments);
|
||||
}
|
||||
|
||||
script_value operator()() const
|
||||
{
|
||||
return this->call(*game::levelEntityId, {});
|
||||
}
|
||||
|
||||
template<class ...T>
|
||||
arguments operator()(T... arguments) const
|
||||
{
|
||||
return this->call(*game::levelEntityId, {arguments...});
|
||||
}
|
||||
|
||||
template<class ...T>
|
||||
arguments operator()(const entity& self, T... arguments) const
|
||||
{
|
||||
return this->call(self, {arguments...});
|
||||
}
|
||||
|
||||
private:
|
||||
const char* pos_;
|
||||
};
|
||||
}
|
233
src/game/scripting/object.cpp
Normal file
233
src/game/scripting/object.cpp
Normal file
@ -0,0 +1,233 @@
|
||||
#include <stdinc.hpp>
|
||||
#include "object.hpp"
|
||||
#include "execution.hpp"
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
object_value::object_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_];
|
||||
game::VariableValue variable;
|
||||
variable.u = value.u.u;
|
||||
variable.type = (game::scriptType_e)value.type;
|
||||
|
||||
this->value_ = variable;*/
|
||||
}
|
||||
|
||||
void object_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_];
|
||||
game::VariableValue variable_{};
|
||||
variable_.type = variable->type;
|
||||
variable_.u = variable->u.u;
|
||||
|
||||
game::AddRefToValue(game::SCRIPTINSTANCE_SERVER, &value);
|
||||
game::RemoveRefToValue(game::SCRIPTINSTANCE_SERVER, variable->type, variable->u.u);
|
||||
|
||||
variable->type = gsl::narrow_cast<char>(value.type);
|
||||
variable->u.u = value.u;
|
||||
|
||||
this->value_ = value;*/
|
||||
}
|
||||
|
||||
object::object(const unsigned int id)
|
||||
: id_(id)
|
||||
{
|
||||
this->add();
|
||||
}
|
||||
|
||||
object::object(const object& other)
|
||||
{
|
||||
this->operator=(other);
|
||||
}
|
||||
|
||||
object::object(object&& other) noexcept
|
||||
{
|
||||
this->id_ = other.id_;
|
||||
other.id_ = 0;
|
||||
}
|
||||
|
||||
object::object()
|
||||
{
|
||||
this->id_ = make_object();
|
||||
}
|
||||
|
||||
object::object(std::unordered_map<std::string, script_value> values)
|
||||
{
|
||||
this->id_ = make_object();
|
||||
|
||||
for (const auto& value : values)
|
||||
{
|
||||
this->set(value.first, value.second);
|
||||
}
|
||||
}
|
||||
|
||||
object::~object()
|
||||
{
|
||||
this->release();
|
||||
}
|
||||
|
||||
object& object::operator=(const object& other)
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
this->release();
|
||||
this->id_ = other.id_;
|
||||
this->add();
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
object& object::operator=(object&& other) noexcept
|
||||
{
|
||||
if (&other != this)
|
||||
{
|
||||
this->release();
|
||||
this->id_ = other.id_;
|
||||
other.id_ = 0;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void object::add() const
|
||||
{
|
||||
if (this->id_)
|
||||
{
|
||||
game::VariableValue value{};
|
||||
value.u.uintValue = this->id_;
|
||||
value.type = game::SCRIPT_OBJECT;
|
||||
|
||||
game::AddRefToValue(game::SCRIPTINSTANCE_SERVER, &value);
|
||||
}
|
||||
}
|
||||
|
||||
void object::release() const
|
||||
{
|
||||
if (this->id_)
|
||||
{
|
||||
game::VariableValue value{};
|
||||
value.u.uintValue = this->id_;
|
||||
value.type = game::SCRIPT_OBJECT;
|
||||
|
||||
game::RemoveRefToValue(game::SCRIPTINSTANCE_SERVER, value.type, value.u);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> object::get_keys() const
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
|
||||
/*auto current = game::scr_VarGlob->objectVariableChildren[this->id_].firstChild;
|
||||
|
||||
while (current)
|
||||
{
|
||||
const auto var = game::scr_VarGlob->childVariableValue[current];
|
||||
const auto string_id = (unsigned __int8)var.name_lo + (var.k.keys.name_hi << 8);
|
||||
|
||||
if (string_id < 0x34BC)
|
||||
{
|
||||
const auto string = reinterpret_cast<const char**>(SELECT_VALUE(0x2DACC28, 0x2D7CF28))[string_id];
|
||||
result.push_back(string);
|
||||
}
|
||||
|
||||
current = var.nextSibling;
|
||||
}*/
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned int object::size() const
|
||||
{
|
||||
return game::Scr_GetSelf(game::SCRIPTINSTANCE_SERVER, this->id_);
|
||||
}
|
||||
|
||||
void object::erase(const std::string& key) const
|
||||
{
|
||||
const auto string_value = game::SL_GetCanonicalString(key.data(), 0);
|
||||
const auto variable_id = game::FindVariable(game::SCRIPTINSTANCE_SERVER, this->id_, string_value);
|
||||
if (variable_id)
|
||||
{
|
||||
game::RemoveVariableValue(game::SCRIPTINSTANCE_SERVER, this->id_, variable_id);
|
||||
}
|
||||
}
|
||||
|
||||
script_value object::get(const std::string& /*key*/) const
|
||||
{
|
||||
/*const auto string_value = game::SL_GetCanonicalString(key.data(), 0);
|
||||
const auto variable_id = game::FindVariable(game::SCRIPTINSTANCE_SERVER, this->id_, string_value);
|
||||
|
||||
if (!variable_id)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto value = game::scr_VarGlob->childVariableValue[variable_id];
|
||||
game::VariableValue variable;
|
||||
variable.u = value.u.u;
|
||||
variable.type = (game::scriptType_e)value.type;
|
||||
|
||||
return variable;*/
|
||||
return {};
|
||||
}
|
||||
|
||||
void object::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];
|
||||
game::VariableValue variable_{};
|
||||
variable_.type = variable->type;
|
||||
variable_.u = variable->u.u;
|
||||
|
||||
game::AddRefToValue(game::SCRIPTINSTANCE_SERVER, &value);
|
||||
game::RemoveRefToValue(game::SCRIPTINSTANCE_SERVER, variable_.type, variable_.u);
|
||||
|
||||
variable->type = gsl::narrow_cast<char>(value.type);
|
||||
variable->u.u = value.u;*/
|
||||
}
|
||||
|
||||
unsigned int object::get_entity_id() const
|
||||
{
|
||||
return this->id_;
|
||||
}
|
||||
|
||||
unsigned int object::get_value_id(const std::string& key) const
|
||||
{
|
||||
const auto string_value = game::SL_GetCanonicalString(key.data(), 0);
|
||||
const auto variable_id = game::FindVariable(game::SCRIPTINSTANCE_SERVER, this->id_, string_value);
|
||||
|
||||
if (!variable_id)
|
||||
{
|
||||
return game::GetNewVariable(game::SCRIPTINSTANCE_SERVER, this->id_, string_value);
|
||||
}
|
||||
|
||||
return variable_id;
|
||||
}
|
||||
|
||||
entity object::get_raw() const
|
||||
{
|
||||
return entity(this->id_);
|
||||
}
|
||||
}
|
55
src/game/scripting/object.hpp
Normal file
55
src/game/scripting/object.hpp
Normal file
@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
#include "script_value.hpp"
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
class object_value : public script_value
|
||||
{
|
||||
public:
|
||||
object_value(unsigned int, unsigned int);
|
||||
void operator=(const script_value&);
|
||||
private:
|
||||
unsigned int id_;
|
||||
unsigned int parent_id_;
|
||||
};
|
||||
|
||||
class object final
|
||||
{
|
||||
public:
|
||||
object();
|
||||
object(const unsigned int);
|
||||
|
||||
object(std::unordered_map<std::string, script_value>);
|
||||
|
||||
object(const object& other);
|
||||
object(object&& other) noexcept;
|
||||
|
||||
~object();
|
||||
|
||||
object& operator=(const object& other);
|
||||
object& operator=(object&& other) noexcept;
|
||||
|
||||
std::vector<std::string> get_keys() const;
|
||||
unsigned int size() const;
|
||||
void erase(const std::string&) const;
|
||||
|
||||
script_value get(const std::string&) const;
|
||||
void set(const std::string&, const script_value&) const;
|
||||
|
||||
unsigned int get_entity_id() const;
|
||||
unsigned int get_value_id(const std::string&) const;
|
||||
|
||||
entity get_raw() const;
|
||||
|
||||
object_value operator[](const std::string& key) const
|
||||
{
|
||||
return {this->id_, this->get_value_id(key)};
|
||||
}
|
||||
|
||||
private:
|
||||
void add() const;
|
||||
void release() const;
|
||||
|
||||
unsigned int id_{};
|
||||
};
|
||||
}
|
67
src/game/scripting/safe_execution.cpp
Normal file
67
src/game/scripting/safe_execution.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
#include <stdinc.hpp>
|
||||
#include "safe_execution.hpp"
|
||||
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4611)
|
||||
|
||||
namespace scripting::safe_execution
|
||||
{
|
||||
bool execute_with_seh(const script_function function, const game::scr_entref_t& entref)
|
||||
{
|
||||
__try
|
||||
{
|
||||
function(entref);
|
||||
return true;
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool call(const script_function function, const game::scr_entref_t& entref)
|
||||
{
|
||||
*game::g_script_error_level += 1;
|
||||
if (game::_setjmp(&game::g_script_error[*game::g_script_error_level], 0))
|
||||
{
|
||||
*game::g_script_error_level -= 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto result = execute_with_seh(function, entref);
|
||||
*game::g_script_error_level -= 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool set_entity_field(const game::scr_entref_t& entref, const int offset)
|
||||
{
|
||||
*game::g_script_error_level += 1;
|
||||
if (game::_setjmp(&game::g_script_error[*game::g_script_error_level], 0))
|
||||
{
|
||||
*game::g_script_error_level -= 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
game::Scr_SetObjectField(entref.classnum, entref.entnum, offset);
|
||||
|
||||
*game::g_script_error_level -= 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get_entity_field(const game::scr_entref_t& entref, const int offset, game::VariableValue* value)
|
||||
{
|
||||
*game::g_script_error_level += 1;
|
||||
if (game::_setjmp(&game::g_script_error[*game::g_script_error_level], 0))
|
||||
{
|
||||
value->type = game::SCRIPT_NONE;
|
||||
value->u.intValue = 0;
|
||||
*game::g_script_error_level -= 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
*value = game::GetEntityFieldValue(game::SCRIPTINSTANCE_SERVER, entref.classnum, entref.entnum, 0, offset);
|
||||
|
||||
*game::g_script_error_level -= 1;
|
||||
return true;
|
||||
}
|
||||
}
|
14
src/game/scripting/safe_execution.hpp
Normal file
14
src/game/scripting/safe_execution.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
#include "game/game.hpp"
|
||||
|
||||
namespace scripting::safe_execution
|
||||
{
|
||||
using script_function = void(*)(game::scr_entref_t);
|
||||
|
||||
bool execute_with_seh(const script_function function, const game::scr_entref_t& entref);
|
||||
|
||||
bool call(script_function function, const game::scr_entref_t& entref);
|
||||
|
||||
bool set_entity_field(const game::scr_entref_t& entref, int offset);
|
||||
bool get_entity_field(const game::scr_entref_t& entref, int offset, game::VariableValue* value);
|
||||
}
|
386
src/game/scripting/script_value.cpp
Normal file
386
src/game/scripting/script_value.cpp
Normal file
@ -0,0 +1,386 @@
|
||||
#include <stdinc.hpp>
|
||||
#include "script_value.hpp"
|
||||
#include "entity.hpp"
|
||||
#include "array.hpp"
|
||||
#include "function.hpp"
|
||||
#include "object.hpp"
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
/***********************************************
|
||||
* Constructors
|
||||
**********************************************/
|
||||
|
||||
script_value::script_value(const game::VariableValue& value)
|
||||
: value_(value)
|
||||
{
|
||||
}
|
||||
|
||||
script_value::script_value(void* value)
|
||||
{
|
||||
game::VariableValue variable{};
|
||||
variable.type = game::SCRIPT_INTEGER;
|
||||
variable.u.intValue = reinterpret_cast<uintptr_t>(value);
|
||||
|
||||
this->value_ = variable;
|
||||
}
|
||||
|
||||
script_value::script_value(const int value)
|
||||
{
|
||||
game::VariableValue variable{};
|
||||
variable.type = game::SCRIPT_INTEGER;
|
||||
variable.u.intValue = value;
|
||||
|
||||
this->value_ = variable;
|
||||
}
|
||||
|
||||
script_value::script_value(const unsigned int value)
|
||||
{
|
||||
game::VariableValue variable{};
|
||||
variable.type = game::SCRIPT_INTEGER;
|
||||
variable.u.uintValue = value;
|
||||
|
||||
this->value_ = variable;
|
||||
}
|
||||
|
||||
script_value::script_value(const bool value)
|
||||
: script_value(static_cast<unsigned>(value))
|
||||
{
|
||||
}
|
||||
|
||||
script_value::script_value(const float value)
|
||||
{
|
||||
game::VariableValue variable{};
|
||||
variable.type = game::SCRIPT_FLOAT;
|
||||
variable.u.floatValue = value;
|
||||
|
||||
this->value_ = variable;
|
||||
}
|
||||
|
||||
script_value::script_value(const double value)
|
||||
: script_value(static_cast<float>(value))
|
||||
{
|
||||
}
|
||||
|
||||
script_value::script_value(const char* value)
|
||||
{
|
||||
game::VariableValue variable{};
|
||||
variable.type = game::SCRIPT_STRING;
|
||||
variable.u.stringValue = game::SL_GetString(value, 0, game::SCRIPTINSTANCE_SERVER);
|
||||
|
||||
const auto _ = gsl::finally([&variable]()
|
||||
{
|
||||
game::RemoveRefToValue(game::SCRIPTINSTANCE_SERVER, variable.type, variable.u);
|
||||
});
|
||||
|
||||
this->value_ = variable;
|
||||
}
|
||||
|
||||
script_value::script_value(const std::string& value)
|
||||
: script_value(value.data())
|
||||
{
|
||||
}
|
||||
|
||||
script_value::script_value(const entity& value)
|
||||
{
|
||||
game::VariableValue variable{};
|
||||
variable.type = game::SCRIPT_OBJECT;
|
||||
variable.u.pointerValue = value.get_entity_id();
|
||||
|
||||
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 object& value)
|
||||
{
|
||||
game::VariableValue variable{};
|
||||
variable.type = game::SCRIPT_OBJECT;
|
||||
variable.u.pointerValue = value.get_entity_id();
|
||||
|
||||
this->value_ = variable;
|
||||
}
|
||||
|
||||
script_value::script_value(const function& value)
|
||||
{
|
||||
game::VariableValue variable{};
|
||||
variable.type = game::SCRIPT_FUNCTION;
|
||||
variable.u.codePosValue = value.get_pos();
|
||||
|
||||
this->value_ = variable;
|
||||
}
|
||||
|
||||
script_value::script_value(const vector& value)
|
||||
{
|
||||
game::VariableValue variable{};
|
||||
variable.type = game::SCRIPT_VECTOR;
|
||||
variable.u.vectorValue = game::Scr_AllocVector(game::SCRIPTINSTANCE_SERVER, value);
|
||||
|
||||
const auto _ = gsl::finally([&variable]()
|
||||
{
|
||||
game::RemoveRefToValue(game::SCRIPTINSTANCE_SERVER, variable.type, variable.u);
|
||||
});
|
||||
|
||||
this->value_ = variable;
|
||||
}
|
||||
|
||||
/***********************************************
|
||||
* Integer
|
||||
**********************************************/
|
||||
|
||||
template <>
|
||||
bool script_value::is<int>() const
|
||||
{
|
||||
return this->get_raw().type == game::SCRIPT_INTEGER;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool script_value::is<unsigned int>() const
|
||||
{
|
||||
return this->is<int>();
|
||||
}
|
||||
|
||||
template <>
|
||||
bool script_value::is<bool>() const
|
||||
{
|
||||
return this->is<int>();
|
||||
}
|
||||
|
||||
template <>
|
||||
int script_value::get() const
|
||||
{
|
||||
return this->get_raw().u.intValue;
|
||||
}
|
||||
|
||||
template <>
|
||||
unsigned int script_value::get() const
|
||||
{
|
||||
return this->get_raw().u.uintValue;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool script_value::get() const
|
||||
{
|
||||
return this->get_raw().u.uintValue != 0;
|
||||
}
|
||||
|
||||
/***********************************************
|
||||
* Float
|
||||
**********************************************/
|
||||
|
||||
template <>
|
||||
bool script_value::is<float>() const
|
||||
{
|
||||
return this->get_raw().type == game::SCRIPT_FLOAT;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool script_value::is<double>() const
|
||||
{
|
||||
return this->is<float>();
|
||||
}
|
||||
|
||||
template <>
|
||||
float script_value::get() const
|
||||
{
|
||||
return this->get_raw().u.floatValue;
|
||||
}
|
||||
|
||||
template <>
|
||||
double script_value::get() const
|
||||
{
|
||||
return static_cast<double>(this->get_raw().u.floatValue);
|
||||
}
|
||||
|
||||
/***********************************************
|
||||
* String
|
||||
**********************************************/
|
||||
|
||||
template <>
|
||||
bool script_value::is<const char*>() const
|
||||
{
|
||||
return this->get_raw().type == game::SCRIPT_STRING
|
||||
|| this->get_raw().type == game::SCRIPT_ISTRING;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool script_value::is<std::string>() const
|
||||
{
|
||||
return this->is<const char*>();
|
||||
}
|
||||
|
||||
template <>
|
||||
const char* script_value::get() const
|
||||
{
|
||||
return game::SL_ConvertToString(static_cast<unsigned int>(this->get_raw().u.stringValue),
|
||||
game::SCRIPTINSTANCE_SERVER);
|
||||
}
|
||||
|
||||
template <>
|
||||
std::string script_value::get() const
|
||||
{
|
||||
return this->get<const char*>();
|
||||
}
|
||||
|
||||
/***********************************************
|
||||
* Entity
|
||||
**********************************************/
|
||||
|
||||
template <>
|
||||
bool script_value::is<entity>() const
|
||||
{
|
||||
return this->get_raw().type == game::SCRIPT_OBJECT;
|
||||
}
|
||||
|
||||
template <>
|
||||
entity script_value::get() const
|
||||
{
|
||||
return entity(this->get_raw().u.pointerValue);
|
||||
}
|
||||
|
||||
/***********************************************
|
||||
* Array
|
||||
**********************************************/
|
||||
|
||||
template <>
|
||||
bool script_value::is<array>() const
|
||||
{
|
||||
if (this->get_raw().type != game::SCRIPT_OBJECT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto id = this->get_raw().u.uintValue;
|
||||
const auto type = game::scr_VarGlob->variableList[id + 1].w.type & 0x1F;
|
||||
|
||||
return type == game::SCRIPT_ARRAY;
|
||||
}
|
||||
|
||||
template <>
|
||||
array script_value::get() const
|
||||
{
|
||||
return array(this->get_raw().u.uintValue);
|
||||
}
|
||||
|
||||
/***********************************************
|
||||
* Struct
|
||||
**********************************************/
|
||||
|
||||
template <>
|
||||
bool script_value::is<object>() const
|
||||
{
|
||||
if (this->get_raw().type != game::SCRIPT_OBJECT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto id = this->get_raw().u.uintValue;
|
||||
const auto type = game::scr_VarGlob->variableList[id + 1].w.type & 0x1F;
|
||||
|
||||
return type == game::SCRIPT_STRUCT || type == game::SCRIPT_ENTITY;
|
||||
}
|
||||
|
||||
template <>
|
||||
object script_value::get() const
|
||||
{
|
||||
return object(this->get_raw().u.uintValue);
|
||||
}
|
||||
|
||||
/***********************************************
|
||||
* Function
|
||||
**********************************************/
|
||||
|
||||
template <>
|
||||
bool script_value::is<function>() const
|
||||
{
|
||||
return this->get_raw().type == game::SCRIPT_FUNCTION;
|
||||
}
|
||||
|
||||
template <>
|
||||
function script_value::get() const
|
||||
{
|
||||
return function(this->get_raw().u.codePosValue);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************
|
||||
* Vector
|
||||
**********************************************/
|
||||
|
||||
template <>
|
||||
bool script_value::is<vector>() const
|
||||
{
|
||||
return this->get_raw().type == game::SCRIPT_VECTOR;
|
||||
}
|
||||
|
||||
template <>
|
||||
vector script_value::get() const
|
||||
{
|
||||
return this->get_raw().u.vectorValue;
|
||||
}
|
||||
|
||||
/***********************************************
|
||||
*
|
||||
**********************************************/
|
||||
|
||||
const game::VariableValue& script_value::get_raw() const
|
||||
{
|
||||
return this->value_.get();
|
||||
}
|
||||
|
||||
std::string script_value::to_string() const
|
||||
{
|
||||
if (this->is<int>())
|
||||
{
|
||||
return utils::string::va("%i", this->as<int>());
|
||||
}
|
||||
|
||||
if (this->is<float>())
|
||||
{
|
||||
return utils::string::va("%f", this->as<float>());
|
||||
}
|
||||
|
||||
if (this->is<std::string>())
|
||||
{
|
||||
return this->as<std::string>();
|
||||
}
|
||||
|
||||
if (this->is<vector>())
|
||||
{
|
||||
const auto vec = this->as<vector>();
|
||||
return utils::string::va("(%g, %g, %g)",
|
||||
vec.get_x(),
|
||||
vec.get_y(),
|
||||
vec.get_z()
|
||||
);
|
||||
}
|
||||
|
||||
if (this->is<function>())
|
||||
{
|
||||
const auto func = this->as<function>();
|
||||
const auto& name = func.get_name();
|
||||
return utils::string::va("[[ %s ]]", name.data());
|
||||
}
|
||||
|
||||
return this->type_name();
|
||||
}
|
||||
|
||||
function_argument::function_argument(const arguments& args, const script_value& value, const int index)
|
||||
: values_(args)
|
||||
, value_(value)
|
||||
, index_(index)
|
||||
{
|
||||
}
|
||||
|
||||
function_arguments::function_arguments(const arguments& values)
|
||||
: values_(values)
|
||||
{
|
||||
}
|
||||
}
|
262
src/game/scripting/script_value.hpp
Normal file
262
src/game/scripting/script_value.hpp
Normal file
@ -0,0 +1,262 @@
|
||||
#pragma once
|
||||
#include "game/game.hpp"
|
||||
#include "variable_value.hpp"
|
||||
#include "vector.hpp"
|
||||
|
||||
#include <utils/string.hpp>
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
class entity;
|
||||
class array;
|
||||
class object;
|
||||
class function;
|
||||
class script_value;
|
||||
|
||||
namespace
|
||||
{
|
||||
std::unordered_map<int, std::string> typenames =
|
||||
{
|
||||
{0, "undefined"},
|
||||
{1, "object"},
|
||||
{2, "string"},
|
||||
{3, "localized string"},
|
||||
{4, "vector"},
|
||||
{5, "float"},
|
||||
{6, "int"},
|
||||
{7, "codepos"},
|
||||
{8, "precodepos"},
|
||||
{9, "function"},
|
||||
{10, "stack"},
|
||||
{11, "animation"},
|
||||
{12, "developer codepos"},
|
||||
{13, "thread"},
|
||||
{14, "thread"},
|
||||
{15, "thread"},
|
||||
{16, "thread"},
|
||||
{17, "struct"},
|
||||
{18, "removed entity"},
|
||||
{19, "entity"},
|
||||
{20, "array"},
|
||||
{21, "removed thread"},
|
||||
};
|
||||
|
||||
std::string get_typename(const game::VariableValue& value)
|
||||
{
|
||||
auto type_ = 0;
|
||||
if (value.type == game::SCRIPT_OBJECT)
|
||||
{
|
||||
type_ = game::scr_VarGlob->variableList[value.u.uintValue].w.type & 0x1F;
|
||||
}
|
||||
else
|
||||
{
|
||||
type_ = value.type;
|
||||
}
|
||||
|
||||
if (typenames.find(type_) != typenames.end())
|
||||
{
|
||||
return typenames[type_];
|
||||
}
|
||||
|
||||
printf("UNKNOWN TYPE %i\n", type_);
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::string get_c_typename()
|
||||
{
|
||||
auto& info = typeid(T);
|
||||
|
||||
if (info == typeid(std::string))
|
||||
{
|
||||
return "string";
|
||||
}
|
||||
|
||||
if (info == typeid(const char*))
|
||||
{
|
||||
return "string";
|
||||
}
|
||||
|
||||
if (info == typeid(entity))
|
||||
{
|
||||
return "entity";
|
||||
}
|
||||
|
||||
if (info == typeid(array))
|
||||
{
|
||||
return "array";
|
||||
}
|
||||
|
||||
if (info == typeid(object))
|
||||
{
|
||||
return "struct";
|
||||
}
|
||||
|
||||
if (info == typeid(function))
|
||||
{
|
||||
return "function";
|
||||
}
|
||||
|
||||
if (info == typeid(vector))
|
||||
{
|
||||
return "vector";
|
||||
}
|
||||
|
||||
return info.name();
|
||||
}
|
||||
}
|
||||
|
||||
using arguments = std::vector<script_value>;
|
||||
|
||||
class script_value
|
||||
{
|
||||
public:
|
||||
script_value() = default;
|
||||
script_value(const game::VariableValue& value);
|
||||
|
||||
script_value(void* value);
|
||||
|
||||
script_value(int value);
|
||||
script_value(unsigned int value);
|
||||
script_value(bool value);
|
||||
|
||||
script_value(float value);
|
||||
script_value(double value);
|
||||
|
||||
script_value(const char* value);
|
||||
script_value(const std::string& value);
|
||||
|
||||
script_value(const entity& value);
|
||||
script_value(const array& value);
|
||||
script_value(const object& value);
|
||||
|
||||
script_value(const function& value);
|
||||
|
||||
script_value(const vector& value);
|
||||
|
||||
template <typename T>
|
||||
bool is() const;
|
||||
|
||||
template <typename T>
|
||||
T as() const
|
||||
{
|
||||
if (!this->is<T>())
|
||||
{
|
||||
const auto type = get_typename(this->get_raw());
|
||||
const auto c_type = get_c_typename<T>();
|
||||
throw std::runtime_error(std::string("has type '" + type + "' but should be '" + c_type + "'"));
|
||||
}
|
||||
|
||||
return get<T>();
|
||||
}
|
||||
|
||||
std::string type_name() const
|
||||
{
|
||||
return get_typename(this->get_raw());
|
||||
}
|
||||
|
||||
template <template<class, class> class C, class T, typename ArrayType = array>
|
||||
script_value(const C<T, std::allocator<T>>& container)
|
||||
{
|
||||
ArrayType array_{};
|
||||
|
||||
for (const auto& value : container)
|
||||
{
|
||||
array_.push(value);
|
||||
}
|
||||
|
||||
game::VariableValue value{};
|
||||
value.type = game::SCRIPT_OBJECT;
|
||||
value.u.pointerValue = array_.get_entity_id();
|
||||
|
||||
this->value_ = value;
|
||||
}
|
||||
|
||||
template<class ...T>
|
||||
arguments operator()(T... arguments) const
|
||||
{
|
||||
return this->as<function>().call({arguments...});
|
||||
}
|
||||
|
||||
std::string to_string() const;
|
||||
|
||||
const game::VariableValue& get_raw() const;
|
||||
|
||||
variable_value value_{};
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
T get() const;
|
||||
|
||||
};
|
||||
|
||||
class variadic_args : public arguments
|
||||
{
|
||||
};
|
||||
|
||||
class function_argument
|
||||
{
|
||||
public:
|
||||
function_argument(const arguments& args, const script_value& value, const int index);
|
||||
|
||||
template <typename T>
|
||||
T as() const
|
||||
{
|
||||
try
|
||||
{
|
||||
return this->value_.as<T>();
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
throw std::runtime_error(utils::string::va("parameter %d %s",
|
||||
this->index_ + 1, e.what()));
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
variadic_args as() const
|
||||
{
|
||||
variadic_args args{};
|
||||
for (auto i = this->index_; i < static_cast<int>(this->values_.size()); i++)
|
||||
{
|
||||
args.push_back(this->values_[i]);
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
template <>
|
||||
script_value as() const
|
||||
{
|
||||
return this->value_;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
operator T() const
|
||||
{
|
||||
return this->as<T>();
|
||||
}
|
||||
|
||||
private:
|
||||
arguments values_{};
|
||||
script_value value_{};
|
||||
int index_{};
|
||||
};
|
||||
|
||||
class function_arguments
|
||||
{
|
||||
public:
|
||||
function_arguments(const arguments& values);
|
||||
|
||||
function_argument operator[](const int index) const
|
||||
{
|
||||
if (index >= static_cast<int>(values_.size()))
|
||||
{
|
||||
throw std::runtime_error(utils::string::va("parameter %d does not exist", index));
|
||||
}
|
||||
|
||||
return {values_, values_[index], index};
|
||||
}
|
||||
private:
|
||||
arguments values_{};
|
||||
};
|
||||
}
|
27
src/game/scripting/stack_isolation.cpp
Normal file
27
src/game/scripting/stack_isolation.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
#include <stdinc.hpp>
|
||||
#include "stack_isolation.hpp"
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
stack_isolation::stack_isolation()
|
||||
{
|
||||
this->in_param_count_ = game::scr_VmPub->inparamcount;
|
||||
this->out_param_count_ = game::scr_VmPub->outparamcount;
|
||||
this->top_ = game::scr_VmPub->top;
|
||||
this->max_stack_ = game::scr_VmPub->maxstack;
|
||||
|
||||
game::scr_VmPub->top = this->stack_;
|
||||
game::scr_VmPub->maxstack = &this->stack_[ARRAYSIZE(this->stack_) - 1];
|
||||
game::scr_VmPub->inparamcount = 0;
|
||||
game::scr_VmPub->outparamcount = 0;
|
||||
}
|
||||
|
||||
stack_isolation::~stack_isolation()
|
||||
{
|
||||
game::Scr_ClearOutParams(game::SCRIPTINSTANCE_SERVER);
|
||||
game::scr_VmPub->inparamcount = this->in_param_count_;
|
||||
game::scr_VmPub->outparamcount = this->out_param_count_;
|
||||
game::scr_VmPub->top = this->top_;
|
||||
game::scr_VmPub->maxstack = this->max_stack_;
|
||||
}
|
||||
}
|
25
src/game/scripting/stack_isolation.hpp
Normal file
25
src/game/scripting/stack_isolation.hpp
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#include "game/game.hpp"
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
class stack_isolation final
|
||||
{
|
||||
public:
|
||||
stack_isolation();
|
||||
~stack_isolation();
|
||||
|
||||
stack_isolation(stack_isolation&&) = delete;
|
||||
stack_isolation(const stack_isolation&) = delete;
|
||||
stack_isolation& operator=(stack_isolation&&) = delete;
|
||||
stack_isolation& operator=(const stack_isolation&) = delete;
|
||||
|
||||
private:
|
||||
game::VariableValue stack_[512]{};
|
||||
|
||||
game::VariableValue* max_stack_;
|
||||
game::VariableValue* top_;
|
||||
unsigned int in_param_count_;
|
||||
unsigned int out_param_count_;
|
||||
};
|
||||
}
|
67
src/game/scripting/thread.cpp
Normal file
67
src/game/scripting/thread.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
#include <stdinc.hpp>
|
||||
#include "thread.hpp"
|
||||
#include "execution.hpp"
|
||||
#include "../../component/scripting.hpp"
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
thread::thread(unsigned int id)
|
||||
: id_(id)
|
||||
, type_(game::scr_VarGlob->variableList[id].w.type & 0x7F)
|
||||
{
|
||||
}
|
||||
|
||||
script_value thread::get_raw() const
|
||||
{
|
||||
game::VariableValue value;
|
||||
value.type = game::SCRIPT_OBJECT;
|
||||
value.u.uintValue = this->id_;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
unsigned int thread::get_entity_id() const
|
||||
{
|
||||
return this->id_;
|
||||
}
|
||||
|
||||
unsigned int thread::get_type() const
|
||||
{
|
||||
return this->type_;
|
||||
}
|
||||
|
||||
unsigned int thread::get_wait_time() const
|
||||
{
|
||||
return game::scr_VarGlob->variableList[this->id_].w.waitTime >> 8;
|
||||
}
|
||||
|
||||
unsigned int thread::get_notify_name_id() const
|
||||
{
|
||||
return game::scr_VarGlob->variableList[this->id_].w.notifyName >> 8;
|
||||
}
|
||||
|
||||
unsigned int thread::get_self() const
|
||||
{
|
||||
return game::Scr_GetSelf(game::SCRIPTINSTANCE_SERVER, this->id_);
|
||||
}
|
||||
|
||||
std::string thread::get_notify_name() const
|
||||
{
|
||||
return game::SL_ConvertToString(this->get_notify_name_id(), game::SCRIPTINSTANCE_SERVER);
|
||||
}
|
||||
|
||||
const char* thread::get_pos() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* thread::get_start_pos() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void thread::kill() const
|
||||
{
|
||||
|
||||
}
|
||||
}
|
32
src/game/scripting/thread.hpp
Normal file
32
src/game/scripting/thread.hpp
Normal file
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
#include "entity.hpp"
|
||||
#include "script_value.hpp"
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
class thread
|
||||
{
|
||||
public:
|
||||
thread(unsigned int);
|
||||
|
||||
script_value get_raw() const;
|
||||
|
||||
unsigned int get_entity_id() const;
|
||||
unsigned int get_type() const;
|
||||
|
||||
unsigned int get_self() const;
|
||||
unsigned int get_wait_time() const;
|
||||
unsigned int get_notify_name_id() const;
|
||||
std::string get_notify_name() const;
|
||||
|
||||
const char* get_pos() const;
|
||||
const char* get_start_pos() const;
|
||||
|
||||
void kill() const;
|
||||
|
||||
private:
|
||||
unsigned int id_{};
|
||||
unsigned int type_{};
|
||||
|
||||
};
|
||||
}
|
68
src/game/scripting/variable_value.cpp
Normal file
68
src/game/scripting/variable_value.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
#include <stdinc.hpp>
|
||||
#include "variable_value.hpp"
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
variable_value::variable_value(const game::VariableValue& value)
|
||||
{
|
||||
this->assign(value);
|
||||
}
|
||||
|
||||
variable_value::variable_value(const variable_value& other) noexcept
|
||||
{
|
||||
this->operator=(other);
|
||||
}
|
||||
|
||||
variable_value::variable_value(variable_value&& other) noexcept
|
||||
{
|
||||
this->operator=(std::move(other));
|
||||
}
|
||||
|
||||
variable_value& variable_value::operator=(const variable_value& other) noexcept
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
this->release();
|
||||
this->assign(other.value_);
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
variable_value& variable_value::operator=(variable_value&& other) noexcept
|
||||
{
|
||||
if (this != &other)
|
||||
{
|
||||
this->release();
|
||||
this->value_ = other.value_;
|
||||
other.value_.type = game::SCRIPT_NONE;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
variable_value::~variable_value()
|
||||
{
|
||||
this->release();
|
||||
}
|
||||
|
||||
const game::VariableValue& variable_value::get() const
|
||||
{
|
||||
return this->value_;
|
||||
}
|
||||
|
||||
void variable_value::assign(const game::VariableValue& value)
|
||||
{
|
||||
this->value_ = value;
|
||||
game::AddRefToValue(game::SCRIPTINSTANCE_SERVER, &this->value_);
|
||||
}
|
||||
|
||||
void variable_value::release()
|
||||
{
|
||||
if (this->value_.type != game::SCRIPT_NONE)
|
||||
{
|
||||
game::RemoveRefToValue(game::SCRIPTINSTANCE_SERVER, this->value_.type, this->value_.u);
|
||||
this->value_.type = game::SCRIPT_NONE;
|
||||
}
|
||||
}
|
||||
}
|
27
src/game/scripting/variable_value.hpp
Normal file
27
src/game/scripting/variable_value.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
#include "game/game.hpp"
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
class variable_value
|
||||
{
|
||||
public:
|
||||
variable_value() = default;
|
||||
variable_value(const game::VariableValue& value);
|
||||
variable_value(const variable_value& other) noexcept;
|
||||
variable_value(variable_value&& other) noexcept;
|
||||
|
||||
variable_value& operator=(const variable_value& other) noexcept;
|
||||
variable_value& operator=(variable_value&& other) noexcept;
|
||||
|
||||
~variable_value();
|
||||
|
||||
const game::VariableValue& get() const;
|
||||
|
||||
private:
|
||||
void assign(const game::VariableValue& value);
|
||||
void release();
|
||||
|
||||
game::VariableValue value_{{0}, game::SCRIPT_NONE};
|
||||
};
|
||||
}
|
85
src/game/scripting/vector.cpp
Normal file
85
src/game/scripting/vector.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
#include <stdinc.hpp>
|
||||
#include "vector.hpp"
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
vector::vector(const float* value)
|
||||
{
|
||||
for (auto i = 0; i < 3; ++i)
|
||||
{
|
||||
this->value_[i] = value[i];
|
||||
}
|
||||
}
|
||||
|
||||
vector::vector(const game::vec3_t& value)
|
||||
: vector(&value[0])
|
||||
{
|
||||
}
|
||||
|
||||
vector::vector(const float x, const float y, const float z)
|
||||
{
|
||||
this->value_[0] = x;
|
||||
this->value_[1] = y;
|
||||
this->value_[2] = z;
|
||||
}
|
||||
|
||||
vector::operator game::vec3_t& ()
|
||||
{
|
||||
return this->value_;
|
||||
}
|
||||
|
||||
vector::operator const game::vec3_t& () const
|
||||
{
|
||||
return this->value_;
|
||||
}
|
||||
|
||||
game::vec_t& vector::operator[](const size_t i)
|
||||
{
|
||||
if (i >= 3)
|
||||
{
|
||||
throw std::runtime_error("Out of bounds.");
|
||||
}
|
||||
|
||||
return this->value_[i];
|
||||
}
|
||||
|
||||
const game::vec_t& vector::operator[](const size_t i) const
|
||||
{
|
||||
if (i >= 3)
|
||||
{
|
||||
throw std::runtime_error("Out of bounds.");
|
||||
}
|
||||
|
||||
return this->value_[i];
|
||||
}
|
||||
|
||||
float vector::get_x() const
|
||||
{
|
||||
return this->operator[](0);
|
||||
}
|
||||
|
||||
float vector::get_y() const
|
||||
{
|
||||
return this->operator[](1);
|
||||
}
|
||||
|
||||
float vector::get_z() const
|
||||
{
|
||||
return this->operator[](2);
|
||||
}
|
||||
|
||||
void vector::set_x(const float value)
|
||||
{
|
||||
this->operator[](0) = value;
|
||||
}
|
||||
|
||||
void vector::set_y(const float value)
|
||||
{
|
||||
this->operator[](1) = value;
|
||||
}
|
||||
|
||||
void vector::set_z(const float value)
|
||||
{
|
||||
this->operator[](2) = value;
|
||||
}
|
||||
}
|
31
src/game/scripting/vector.hpp
Normal file
31
src/game/scripting/vector.hpp
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#include "game/game.hpp"
|
||||
|
||||
namespace scripting
|
||||
{
|
||||
class vector final
|
||||
{
|
||||
public:
|
||||
vector() = default;
|
||||
vector(const float* value);
|
||||
vector(const game::vec3_t& value);
|
||||
vector(float x, float y, float z);
|
||||
|
||||
operator game::vec3_t& ();
|
||||
operator const game::vec3_t& () const;
|
||||
|
||||
game::vec_t& operator[](size_t i);
|
||||
const game::vec_t& operator[](size_t i) const;
|
||||
|
||||
float get_x() const;
|
||||
float get_y() const;
|
||||
float get_z() const;
|
||||
|
||||
void set_x(float value);
|
||||
void set_y(float value);
|
||||
void set_z(float value);
|
||||
|
||||
private:
|
||||
game::vec3_t value_{ 0 };
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user