Initial commit

This commit is contained in:
Federico Cecchetto
2022-06-09 23:40:58 +02:00
parent 768b1358c0
commit cdd2c51568
77 changed files with 6418 additions and 0 deletions

82
src/game/game.cpp Normal file
View File

@ -0,0 +1,82 @@
#include <stdinc.hpp>
#include "game.hpp"
#include <utils/hook.hpp>
namespace game
{
gamemode current = *reinterpret_cast<int*>(0x401337) == 0x281488C0
? gamemode::multiplayer
: gamemode::singleplayer;
namespace environment
{
bool is_mp()
{
return current == gamemode::multiplayer;
}
bool is_sp()
{
return current == gamemode::singleplayer;
}
}
void AddRefToValue(scriptInstance_t inst, const VariableValue* value)
{
AddRefToValue_(inst, value->type, value->u);
}
unsigned int AllocVariable(scriptInstance_t inst)
{
static const auto func = utils::hook::assemble([](utils::hook::assembler& a)
{
a.mov(eax, 0);
a.call(SELECT_VALUE(0, 0x8E49A0));
a.ret();
});
return utils::hook::invoke<unsigned int>(func, inst);
}
VariableValue Scr_GetArrayIndexValue(scriptInstance_t inst, unsigned int name)
{
VariableValue value{};
if (name >= 0x10000)
{
if (name >= 0x17FFE)
{
value.type = 6;
value.u.intValue = name - 0x800000;
}
else
{
value.type = 1;
value.u.intValue = name - 0x10000;
}
}
else
{
value.type = 2;
value.u.intValue = name;
}
return value;
}
unsigned int Scr_GetSelf(scriptInstance_t inst, unsigned int threadId)
{
return game::scr_VarGlob->variableList[threadId + 1].u.o.u.self;
}
namespace plutonium
{
bool is_up_to_date()
{
//const auto value = *reinterpret_cast<DWORD*>(0);
//return value == 0;
return false;
}
}
}

85
src/game/game.hpp Normal file
View File

@ -0,0 +1,85 @@
#pragma once
#include "structs.hpp"
#define SELECT_VALUE(sp, mp) (game::environment::is_sp() ? (sp) : (mp))
namespace game
{
enum gamemode
{
none,
multiplayer,
singleplayer
};
extern gamemode current;
namespace environment
{
bool is_mp();
bool is_sp();
}
template <typename T>
class symbol
{
public:
symbol(const size_t sp_address, const size_t mp_address)
: sp_object_(reinterpret_cast<T*>(sp_address))
, mp_object_(reinterpret_cast<T*>(mp_address))
{
}
T* get() const
{
if (environment::is_mp())
{
#ifdef DEBUG
if (mp_object_ == nullptr)
{
MessageBoxA(nullptr, "nullptr symbol", "", 0);
}
#endif
return mp_object_;
}
#ifdef DEBUG
if (sp_object_ == nullptr)
{
MessageBoxA(nullptr, "nullptr symbol", "", 0);
}
#endif
return sp_object_;
}
operator T* () const
{
return this->get();
}
T* operator->() const
{
return this->get();
}
private:
T* sp_object_;
T* mp_object_;
};
void AddRefToValue(scriptInstance_t inst, const VariableValue* value);
unsigned int AllocVariable(scriptInstance_t inst);
VariableValue Scr_GetArrayIndexValue(scriptInstance_t inst, unsigned int name);
unsigned int Scr_GetSelf(scriptInstance_t inst, unsigned int threadId);
namespace plutonium
{
bool is_up_to_date();
}
}
#include "symbols.hpp"

View 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_);
}
}

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

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

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

View 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;
};
}

View 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;
}
}

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

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

View 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_;
};
}

View 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_);
}
}

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

View 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;
}
}

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

View 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)
{
}
}

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

View 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_;
}
}

View 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_;
};
}

View 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
{
}
}

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

View 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;
}
}
}

View 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};
};
}

View 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;
}
}

View 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 };
};
}

742
src/game/structs.hpp Normal file
View File

@ -0,0 +1,742 @@
#pragma once
namespace game
{
typedef float vec_t;
typedef vec_t vec2_t[2];
typedef vec_t vec3_t[3];
typedef vec_t vec4_t[4];
enum scriptInstance_t
{
SCRIPTINSTANCE_SERVER,
SCRIPTINSTANCE_CLIENT,
};
struct scr_entref_t
{
unsigned short entnum;
unsigned short classnum;
int client;
};
struct BuiltinMethodDef
{
const char* actionString;
unsigned int constId;
int min_args;
int max_args;
void(__cdecl* actionFunc)(scr_entref_t);
int type;
};
struct BuiltinFunctionDef
{
const char* actionString;
unsigned int constId;
int min_args;
int max_args;
void(__cdecl* actionFunc)();
int type;
};
enum scriptType_e
{
SCRIPT_NONE = 0,
SCRIPT_OBJECT = 1,
SCRIPT_STRING = 2,
SCRIPT_ISTRING = 3,
SCRIPT_VECTOR = 4,
SCRIPT_FLOAT = 5,
SCRIPT_INTEGER = 6,
SCRIPT_CODEPOS = 7,
SCRIPT_END = 8,
SCRIPT_FUNCTION = 9,
SCRIPT_THREAD = 13,
SCRIPT_NOTIFY_THREAD = 14,
SCRIPT_TIME_THREAD = 15,
SCRIPT_STRUCT = 17,
SCRIPT_ENTITY = 19,
SCRIPT_ARRAY = 20,
SCRIPT_FREE = 0x17,
};
struct VariableStackBuffer
{
const char* pos;
unsigned __int16 size;
unsigned __int16 bufLen;
unsigned __int16 localId;
char time;
char buf[1];
};
union VariableUnion
{
int intValue;
unsigned int uintValue;
float floatValue;
unsigned int stringValue;
const float* vectorValue;
const char* codePosValue;
unsigned int pointerValue;
VariableStackBuffer* stackValue;
unsigned int entityOffset;
};
struct VariableValue
{
VariableUnion u;
int type;
};
struct function_stack_t
{
char* pos;
VariableValue* top;
unsigned int localId;
unsigned int localVarCount;
VariableValue* startTop;
};
struct function_frame_t
{
function_stack_t fs;
};
struct scrVmPub_t
{
unsigned int* localVars;
VariableValue* maxstack;
int function_count;
function_frame_t* function_frame;
VariableValue* top;
bool abort_on_error;
bool terminal_error;
bool block_execution;
unsigned int inparamcount;
unsigned int outparamcount;
function_frame_t function_frame_start[32];
VariableValue stack[2048];
void(__cdecl* notifyListeners[1])(unsigned int, unsigned int);
};
static_assert(offsetof(scrVmPub_t, top) == 16);
static_assert(offsetof(scrVmPub_t, inparamcount) == 24);
struct scrVarPub_t
{
const char* fieldBuffer;
unsigned __int16 canonicalStrCount;
bool developer;
bool developer_script;
bool evaluate;
const char* error_message;
int error_index;
unsigned int time;
unsigned int timeArrayId;
unsigned int pauseArrayId;
unsigned int levelId;
unsigned int gameId;
unsigned int animId;
unsigned int freeEntList;
unsigned int tempVariable;
bool bInited;
unsigned __int16 savecount;
unsigned int checksum;
unsigned int entId;
unsigned int entFieldName;
void* programHunkUser;
const char* programBuffer;
const char* endScriptBuffer;
unsigned __int16* saveIdMap;
unsigned __int16* saveIdMapRev;
unsigned int numScriptThreads;
unsigned int numScriptValues;
unsigned int numScriptObjects;
const char* varUsagePos;
int ext_threadcount;
int totalObjectRefCount;
volatile int totalVectorRefCount;
};
union Variable_u
{
unsigned int prev;
unsigned int prevSibling;
};
struct Variable
{
unsigned int id;
Variable_u u;
};
union ObjectInfo_u
{
unsigned __int16 entnum;
unsigned __int16 size;
unsigned int nextEntId;
unsigned int self;
};
struct ObjectInfo
{
unsigned __int16 refCount;
ObjectInfo_u u;
};
union VariableValueInternal_u
{
unsigned int next;
VariableUnion u;
ObjectInfo o;
};
union VariableValueInternal_w
{
unsigned int status;
unsigned int type;
unsigned int name;
unsigned int classnum;
unsigned int notifyName;
unsigned int waitTime;
unsigned int parentLocalId;
};
union VariableValueInternal_v
{
unsigned int next;
unsigned int index;
};
struct VariableValueInternal
{
Variable hash;
VariableValueInternal_u u;
VariableValueInternal_w w;
VariableValueInternal_v v;
unsigned int nextSibling;
};
static_assert(sizeof(VariableValueInternal) == 28);
static_assert(offsetof(VariableValueInternal, hash) == 0);
static_assert(offsetof(VariableValueInternal, u) == 8);
static_assert(offsetof(VariableValueInternal, w) == 16);
struct scrVarGlob_t
{
VariableValueInternal* variableList;
};
struct scr_classStruct_t
{
unsigned __int16 id;
unsigned __int16 entArrayId;
char charId;
const char* name;
};
enum gclientFlag
{
NOCLIP = 1 << 0,
UFO = 1 << 1,
};
enum entityFlag
{
FL_GODMODE = 1 << 0,
FL_DEMI_GODMODE = 1 << 1,
FL_NOTARGET = 1 << 2,
FL_SUPPORTS_LINKTO = 1 << 12,
}; // TODO: Finish
struct gclient_s
{
char __pad0[0x18];
int eflags;
char __pad1[0x5668];
int flags;
};
struct gentity_s
{
int number;
char __pad0[0x150];
gclient_s* client; // 340
char __pad1[0x30];
int flags; // 392
char __pad2[0x190];
};
static_assert(sizeof(gentity_s) == 0x31C);
enum clientState_t
{
CS_FREE,
CS_ZOMBIE,
CS_RECONNECTING,
CS_CONNECTED,
CS_CLIENTLOADING,
CS_ACTIVE,
};
enum netsrc_t
{
NS_CLIENT1 = 0x0,
NS_CLIENT2 = 0x1,
NS_CLIENT3 = 0x2,
NS_CLIENT4 = 0x3,
NS_SERVER = 0x4,
NS_PACKET = 0x5,
NS_NULL = -1,
};
enum netadrtype_t
{
NA_BOT = 0x0,
NA_BAD = 0x1,
NA_LOOPBACK = 0x2,
NA_BROADCAST = 0x3,
NA_IP = 0x4,
};
struct netadr_t
{
union
{
unsigned char ip[4];
unsigned int inaddr;
};
unsigned __int16 port;
netadrtype_t type;
netsrc_t localNetID;
unsigned __int16 serverID;
};
static_assert(sizeof(netadr_t) == 0x14);
struct netProfileInfo_t
{
unsigned char __pad0[0x5E0];
};
struct netchan_t
{
int outgoingSequence;
netsrc_t sock;
int dropped;
int incomingSequence;
netadr_t remoteAddress;
int qport;
int fragmentSequence;
int fragmentLength;
unsigned char* fragmentBuffer;
int fragmentBufferSize;
int unsentFragments;
int unsentOnLoan;
int unsentFragmentStart;
int unsentLength;
unsigned char* unsentBuffer;
int unsentBufferSize;
int reliable_fragments;
unsigned char fragment_send_count[128];
unsigned int fragment_ack[4];
int lowest_send_count;
netProfileInfo_t prof;
};
static_assert(sizeof(netchan_t) == 0x6C8);
struct PredictedVehicleDef
{
bool fullPhysics;
vec3_t origin;
vec3_t angles;
vec3_t tVel;
vec3_t aVel;
int serverTime;
};
static_assert(sizeof(PredictedVehicleDef) == 0x38);
struct clientHeader_t
{
clientState_t state;
int sendAsActive;
int deltaMessage;
int rateDelayed;
int hasAckedBaselineData;
int hugeSnapshotSent;
netchan_t netchan;
vec3_t predictedOrigin;
int predictedOriginServerTime;
int migrationState;
PredictedVehicleDef predictedVehicle;
};
static_assert(sizeof(clientHeader_t) == 0x72C);
struct client_s
{
clientHeader_t header;
const char* dropReason;
char userinfo[1024];
unsigned char __pad0[0x3F75C];
int bIsTestClient;
unsigned char __pad1[0xDEF0];
};
static_assert(sizeof(client_s) == 0x4E180);
struct cmd_function_t
{
cmd_function_t* next;
const char* name;
const char* autoCompleteDir;
const char* autoCompleteExt;
void(__cdecl* function)();
int flags;
};
struct CmdArgs
{
int nesting;
int localClientNum[8];
int controllerIndex[8];
void* itemDef[8];
int argshift[8];
int argc[8];
const char** argv[8];
char textPool[8192];
const char* argvPool[512];
int usedTextPool[8];
int totalUsedArgvPool;
int totalUsedTextPool;
};
enum dvarType_t
{
DVAR_TYPE_INVALID = 0x0,
DVAR_TYPE_BOOL = 0x1,
DVAR_TYPE_FLOAT = 0x2,
DVAR_TYPE_FLOAT_2 = 0x3,
DVAR_TYPE_FLOAT_3 = 0x4,
DVAR_TYPE_FLOAT_4 = 0x5,
DVAR_TYPE_INT = 0x6,
DVAR_TYPE_ENUM = 0x7,
DVAR_TYPE_STRING = 0x8,
DVAR_TYPE_COLOR = 0x9,
DVAR_TYPE_INT64 = 0xA,
DVAR_TYPE_LINEAR_COLOR_RGB = 0xB,
DVAR_TYPE_COLOR_XYZ = 0xC,
DVAR_TYPE_COUNT = 0xD,
};
union DvarValue
{
bool enabled;
int integer;
unsigned int unsignedInt;
__int64 integer64;
unsigned __int64 unsignedInt64;
float value;
vec4_t vector;
const char* string;
char color[4];
};
struct $A37BA207B3DDD6345C554D4661813EDD
{
int stringCount;
const char* const* strings;
};
struct $9CA192F9DB66A3CB7E01DE78A0DEA53D
{
int min;
int max;
};
struct $251C2428A496074035CACA7AAF3D55BD
{
float min;
float max;
};
union DvarLimits
{
$A37BA207B3DDD6345C554D4661813EDD enumeration;
$9CA192F9DB66A3CB7E01DE78A0DEA53D integer;
$251C2428A496074035CACA7AAF3D55BD value;
$251C2428A496074035CACA7AAF3D55BD vector;
};
struct dvar_t
{
const char* name;
const char* description;
int hash;
unsigned int flags;
dvarType_t type;
bool modified;
DvarValue current;
DvarValue latched;
DvarValue reset;
DvarLimits domain;
dvar_t* hashNext;
};
struct GSC_OBJ
{
char magic[8];
unsigned int source_crc;
unsigned int include_offset;
unsigned int animtree_offset;
unsigned int cseg_offset;
unsigned int stringtablefixup_offset;
unsigned int exports_offset;
unsigned int imports_offset;
unsigned int fixup_offset;
unsigned int profile_offset;
unsigned int cseg_size;
unsigned __int16 name;
unsigned __int16 stringtablefixup_count;
unsigned __int16 exports_count;
unsigned __int16 imports_count;
unsigned __int16 fixup_count;
unsigned __int16 profile_count;
char include_count;
char animtree_count;
char flags;
};
struct GSC_EXPORT_ITEM
{
unsigned int checksum;
unsigned int address;
unsigned __int16 name;
char param_count;
char flags;
};
// gsc-tool
enum class opcode : std::uint8_t
{
OP_End = 0x0,
OP_Return = 0x1,
OP_GetUndefined = 0x2,
OP_GetZero = 0x3,
OP_GetByte = 0x4,
OP_GetNegByte = 0x5,
OP_GetUnsignedShort = 0x6,
OP_GetNegUnsignedShort = 0x7,
OP_GetInteger = 0x8,
OP_GetFloat = 0x9,
OP_GetString = 0xA,
OP_GetIString = 0xB,
OP_GetVector = 0xC,
OP_GetLevelObject = 0xD,
OP_GetAnimObject = 0xE,
OP_GetSelf = 0xF,
OP_GetLevel = 0x10,
OP_GetGame = 0x11,
OP_GetAnim = 0x12,
OP_GetAnimation = 0x13,
OP_GetGameRef = 0x14,
OP_GetFunction = 0x15,
OP_CreateLocalVariable = 0x16,
OP_SafeCreateLocalVariables = 0x17,
OP_RemoveLocalVariables = 0x18,
OP_EvalLocalVariableCached = 0x19,
OP_EvalArray = 0x1A,
OP_EvalLocalArrayRefCached = 0x1B,
OP_EvalArrayRef = 0x1C,
OP_ClearArray = 0x1D,
OP_EmptyArray = 0x1E,
OP_GetSelfObject = 0x1F,
OP_EvalFieldVariable = 0x20,
OP_EvalFieldVariableRef = 0x21,
OP_ClearFieldVariable = 0x22,
OP_SafeSetVariableFieldCached = 0x23,
OP_SafeSetWaittillVariableFieldCached = 0x24,
OP_ClearParams = 0x25,
OP_CheckClearParams = 0x26,
OP_EvalLocalVariableRefCached = 0x27,
OP_SetVariableField = 0x28,
OP_CallBuiltin = 0x29,
OP_CallBuiltinMethod = 0x2A,
OP_Wait = 0x2B,
OP_WaitTillFrameEnd = 0x2C,
OP_PreScriptCall = 0x2D,
OP_ScriptFunctionCall = 0x2E,
OP_ScriptFunctionCallPointer = 0x2F,
OP_ScriptMethodCall = 0x30,
OP_ScriptMethodCallPointer = 0x31,
OP_ScriptThreadCall = 0x32,
OP_ScriptThreadCallPointer = 0x33,
OP_ScriptMethodThreadCall = 0x34,
OP_ScriptMethodThreadCallPointer = 0x35,
OP_DecTop = 0x36,
OP_CastFieldObject = 0x37,
OP_CastBool = 0x38,
OP_BoolNot = 0x39,
OP_BoolComplement = 0x3A,
OP_JumpOnFalse = 0x3B,
OP_JumpOnTrue = 0x3C,
OP_JumpOnFalseExpr = 0x3D,
OP_JumpOnTrueExpr = 0x3E,
OP_Jump = 0x3F,
OP_JumpBack = 0x40,
OP_Inc = 0x41,
OP_Dec = 0x42,
OP_Bit_Or = 0x43,
OP_Bit_Xor = 0x44,
OP_Bit_And = 0x45,
OP_Equal = 0x46,
OP_NotEqual = 0x47,
OP_LessThan = 0x48,
OP_GreaterThan = 0x49,
OP_LessThanOrEqualTo = 0x4A,
OP_GreaterThanOrEqualTo = 0x4B,
OP_ShiftLeft = 0x4C,
OP_ShiftRight = 0x4D,
OP_Plus = 0x4E,
OP_Minus = 0x4F,
OP_Multiply = 0x50,
OP_Divide = 0x51,
OP_Modulus = 0x52,
OP_SizeOf = 0x53,
OP_WaitTillMatch = 0x54,
OP_WaitTill = 0x55,
OP_Notify = 0x56,
OP_EndOn = 0x57,
OP_VoidCodePos = 0x58,
OP_Switch = 0x59,
OP_EndSwitch = 0x5A,
OP_Vector = 0x5B,
OP_GetHash = 0x5C,
OP_RealWait = 0x5D,
OP_VectorConstant = 0x5E,
OP_IsDefined = 0x5F,
OP_VectorScale = 0x60,
OP_AnglesToUp = 0x61,
OP_AnglesToRight = 0x62,
OP_AnglesToForward = 0x63,
OP_AngleClamp180 = 0x64,
OP_VectorToAngles = 0x65,
OP_Abs = 0x66,
OP_GetTime = 0x67,
OP_GetDvar = 0x68,
OP_GetDvarInt = 0x69,
OP_GetDvarFloat = 0x6A,
OP_GetDvarVector = 0x6B,
OP_GetDvarColorRed = 0x6C,
OP_GetDvarColorGreen = 0x6D,
OP_GetDvarColorBlue = 0x6E,
OP_GetDvarColorAlpha = 0x6F,
OP_FirstArrayKey = 0x70,
OP_NextArrayKey = 0x71,
OP_ProfileStart = 0x72,
OP_ProfileStop = 0x73,
OP_SafeDecTop = 0x74,
OP_Nop = 0x75,
OP_Abort = 0x76,
OP_Object = 0x77,
OP_ThreadObject = 0x78,
OP_EvalLocalVariable = 0x79,
OP_EvalLocalVariableRef = 0x7A,
OP_DevblockBegin = 0x7B,
OP_DevblockEnd = 0x7C,
OP_Breakpoint = 0x7D,
OP_Count = 0x7E,
};
enum XAssetType
{
ASSET_TYPE_XMODELPIECES = 0x0,
ASSET_TYPE_PHYSPRESET = 0x1,
ASSET_TYPE_PHYSCONSTRAINTS = 0x2,
ASSET_TYPE_DESTRUCTIBLEDEF = 0x3,
ASSET_TYPE_XANIMPARTS = 0x4,
ASSET_TYPE_XMODEL = 0x5,
ASSET_TYPE_MATERIAL = 0x6,
ASSET_TYPE_TECHNIQUE_SET = 0x7,
ASSET_TYPE_IMAGE = 0x8,
ASSET_TYPE_SOUND = 0x9,
ASSET_TYPE_SOUND_PATCH = 0xA,
ASSET_TYPE_CLIPMAP = 0xB,
ASSET_TYPE_CLIPMAP_PVS = 0xC,
ASSET_TYPE_COMWORLD = 0xD,
ASSET_TYPE_GAMEWORLD_SP = 0xE,
ASSET_TYPE_GAMEWORLD_MP = 0xF,
ASSET_TYPE_MAP_ENTS = 0x10,
ASSET_TYPE_GFXWORLD = 0x11,
ASSET_TYPE_LIGHT_DEF = 0x12,
ASSET_TYPE_UI_MAP = 0x13,
ASSET_TYPE_FONT = 0x14,
ASSET_TYPE_FONTICON = 0x15,
ASSET_TYPE_MENULIST = 0x16,
ASSET_TYPE_MENU = 0x17,
ASSET_TYPE_LOCALIZE_ENTRY = 0x18,
ASSET_TYPE_WEAPON = 0x19,
ASSET_TYPE_WEAPONDEF = 0x1A,
ASSET_TYPE_WEAPON_VARIANT = 0x1B,
ASSET_TYPE_WEAPON_FULL = 0x1C,
ASSET_TYPE_ATTACHMENT = 0x1D,
ASSET_TYPE_ATTACHMENT_UNIQUE = 0x1E,
ASSET_TYPE_WEAPON_CAMO = 0x1F,
ASSET_TYPE_SNDDRIVER_GLOBALS = 0x20,
ASSET_TYPE_FX = 0x21,
ASSET_TYPE_IMPACT_FX = 0x22,
ASSET_TYPE_AITYPE = 0x23,
ASSET_TYPE_MPTYPE = 0x24,
ASSET_TYPE_MPBODY = 0x25,
ASSET_TYPE_MPHEAD = 0x26,
ASSET_TYPE_CHARACTER = 0x27,
ASSET_TYPE_XMODELALIAS = 0x28,
ASSET_TYPE_RAWFILE = 0x29,
ASSET_TYPE_STRINGTABLE = 0x2A,
ASSET_TYPE_LEADERBOARD = 0x2B,
ASSET_TYPE_XGLOBALS = 0x2C,
ASSET_TYPE_DDL = 0x2D,
ASSET_TYPE_GLASSES = 0x2E,
ASSET_TYPE_EMBLEMSET = 0x2F,
ASSET_TYPE_SCRIPTPARSETREE = 0x30,
ASSET_TYPE_KEYVALUEPAIRS = 0x31,
ASSET_TYPE_VEHICLEDEF = 0x32,
ASSET_TYPE_MEMORYBLOCK = 0x33,
ASSET_TYPE_ADDON_MAP_ENTS = 0x34,
ASSET_TYPE_TRACER = 0x35,
ASSET_TYPE_SKINNEDVERTS = 0x36,
ASSET_TYPE_QDB = 0x37,
ASSET_TYPE_SLUG = 0x38,
ASSET_TYPE_FOOTSTEP_TABLE = 0x39,
ASSET_TYPE_FOOTSTEPFX_TABLE = 0x3A,
ASSET_TYPE_ZBARRIER = 0x3B,
ASSET_TYPE_COUNT = 0x3C,
ASSET_TYPE_STRING = 0x3C,
ASSET_TYPE_ASSETLIST = 0x3D,
ASSET_TYPE_REPORT = 0x3E,
ASSET_TYPE_DEPEND = 0x3F,
ASSET_TYPE_FULL_COUNT = 0x40,
};
struct ScriptParseTree
{
const char* name;
int len;
GSC_OBJ* obj;
};
struct objFileInfo_t
{
GSC_OBJ* activeVersion;
char __pad[0x24];
};
union XAssetHeader
{
ScriptParseTree* scriptParseTree;
};
}

126
src/game/symbols.hpp Normal file
View File

@ -0,0 +1,126 @@
#pragma once
#define WEAK __declspec(selectany)
namespace game
{
// Functions
WEAK symbol<int(const char* str)> BG_StringHashValue{0x0, 0x0};
WEAK symbol<void(int localClientNum, const char* text)> Cbuf_InsertText{0x0, 0x0};
WEAK symbol<void(int localClientNum, const char* text)> Cbuf_AddText{0x0, 0x0};
WEAK symbol<void(int localClientNum, int controllerIndex, const char* text)> Cmd_ExecuteSingleCommand{0x0, 0x0};
WEAK symbol<void(const char* cmdName, void(), cmd_function_t* allocedCmd)> Cmd_AddCommandInternal{0x0, 0x0};
WEAK symbol<const char*(int index)> Cmd_Argv{0x0, 0x0};
WEAK symbol<void(const char* cmdName)> Cmd_RemoveCommand{0x0, 0x0};
WEAK symbol<void(int clientNum)> ClientUserInfoChanged{0x0, 0x0};
WEAK symbol<const dvar_t*(const char*)> Dvar_FindVar{0x0, 0x0};
WEAK symbol<int(const dvar_t*)> Dvar_GetInt{0x0, 0x0};
WEAK symbol<dvar_t*(const char* dvarName, int value, int min, int max,
unsigned int flags, const char* description)> Dvar_RegisterInt{0x0, 0x0};
WEAK symbol<XAssetHeader(XAssetType type, const char* name, bool errorIfMissing, int waitTime)> DB_FindXAssetHeader{0x0, 0x0};
WEAK symbol<char*(const char*)> I_CleanStr{0x0, 0x0};
WEAK symbol<void*(const char** pName, int* min_args, int* max_args)> Player_GetMethod{0x0, 0x0};
WEAK symbol<void*(const char** pName, int* type, int* min_args, int* max_args)> Scr_GetCommonFunction{0x0, 0x0};
WEAK symbol<void*(const char** pName, int* type, int* min_args, int* max_args)> Scr_GetMethod{0x0, 0x0};
WEAK symbol<void(scriptInstance_t inst, gentity_s* ent)> Scr_AddEntity{0x0, 0x0};
WEAK symbol<void(scriptInstance_t inst, float value)> Scr_AddFloat{0x0, 0x0};
WEAK symbol<void(scriptInstance_t inst, int value)> Scr_AddInt{0x0, 0x0};
WEAK symbol<void(scriptInstance_t inst, const char* value)> Scr_AddString{0x0, 0x0};
WEAK symbol<void(scriptInstance_t inst, float* value)> Scr_AddVector{0x0, 0x0};
WEAK symbol<void(scriptInstance_t inst, unsigned int id)> Scr_AddObject{0x0, 0x0};
WEAK symbol<void(scriptInstance_t inst)> Scr_ClearOutParams{0x0, 0x588680};
WEAK symbol<unsigned int(scriptInstance_t inst)> AllocObject{0x0, 0x0};
WEAK symbol<unsigned int(scriptInstance_t inst, unsigned int id)> AllocThread{0x0, 0x0};
WEAK symbol<void(scriptInstance_t inst, unsigned int id)> RemoveRefToObject{0x0, 0x0};
WEAK symbol<void(scriptInstance_t inst, const float* vectorValue)> RemoveRefToVector{0x0, 0x0};
WEAK symbol<void(scriptInstance_t inst, const int type, VariableUnion value)> AddRefToValue_{0x0, 0x6706B0};
WEAK symbol<void(scriptInstance_t inst, const int type, VariableUnion value)> RemoveRefToValue{0x0, 0x4249C0};
WEAK symbol<void(scriptInstance_t inst, unsigned int parentId, unsigned int index)> RemoveVariableValue{0x0, 0x0};
WEAK symbol<unsigned int(scriptInstance_t inst, unsigned int parentId, unsigned int id)> FindVariable{0x0, 0x5DF7E0};
WEAK symbol<unsigned int(scriptInstance_t inst, unsigned int parentId, unsigned int id)> FindArrayVariable{0x0, 0x509230};
WEAK symbol<unsigned int(scriptInstance_t inst, unsigned int parentId, unsigned int id)> GetVariable{0x0, 0x0};
WEAK symbol<unsigned int(scriptInstance_t inst, unsigned int parentId, unsigned int name)> GetNewVariable{0x0, 0x5B3750};
WEAK symbol<unsigned int(scriptInstance_t inst, unsigned int parentId, unsigned int unsignedValue)> GetNewArrayVariable{0x0, 0x468BC0};
WEAK symbol<VariableValueInternal_u*(scriptInstance_t inst, unsigned int id)> GetVariableValueAddress{0x0, 0x651390};
WEAK symbol<void(scriptInstance_t inst, unsigned int id, const VariableValue* value)> SetNewVariableValue{0x0, 0x4DCA30};
WEAK symbol<void(unsigned int classnum, int entnum, int offset)> Scr_SetObjectField{0x0, 0x0};
WEAK symbol<VariableValue(scriptInstance_t inst, unsigned int classnum, int entnum, int clientNum, int offset)> GetEntityFieldValue{0x0, 0x0};
WEAK symbol<void(gentity_s* ent, unsigned int stringValue, unsigned int paramcount)> Scr_Notify{0x0, 0x0};
WEAK symbol<void(scriptInstance_t inst, int clientNum, unsigned int id, unsigned int stringValue, unsigned int paramcount)> Scr_NotifyId{0x0, 0x0};
WEAK symbol<void(int entnum, unsigned int classnum, unsigned int stringValue, unsigned int paramcount)> Scr_NotifyNum{0x0, 0x0};
WEAK symbol<unsigned int(const char* str, unsigned int user, scriptInstance_t inst)> SL_GetString{0x0, 0x4B1770};
WEAK symbol<const char*(unsigned int stringValue, scriptInstance_t inst)> SL_ConvertToString{0x0, 0x624C70};
WEAK symbol<unsigned int(const char* str, bool is_static)> SL_GetCanonicalString{0x0, 0x0};
WEAK symbol<int(scriptInstance_t inst)> Scr_GetNumParam{0x0, 0x0};
WEAK symbol<gentity_s*(scriptInstance_t inst, int index)> Scr_GetEntity{0x0, 0x0};
WEAK symbol<float(scriptInstance_t inst, int index)> Scr_GetFloat{0x0, 0x0};
WEAK symbol<int(scriptInstance_t inst, int index)> Scr_GetInt{0x0, 0x0};
WEAK symbol<const char*(scriptInstance_t inst, int index)> Scr_GetString{0x0, 0x0};
WEAK symbol<void(scriptInstance_t inst, int index, float* out)> Scr_GetVector{0x0, 0x0};
WEAK symbol<const float*(scriptInstance_t inst, const float* v)> Scr_AllocVector{0x0, 0x4C4440};
WEAK symbol<int(scriptInstance_t inst, const char* filename,
const char* name, unsigned int* checksum, bool errorIfMissing)> Scr_GetFunctionHandle{0x0, 0x0};
WEAK symbol<void(scriptInstance_t inst, unsigned int classnum, char const* name, unsigned int offset)> Scr_AddClassField{0x0, 0x0};
WEAK symbol<unsigned int(scriptInstance_t inst, int entnum, unsigned int classnum, int clientNum)> Scr_GetEntityId{0x0, 0x6A07D0};
WEAK symbol<unsigned int(scriptInstance_t inst, unsigned int localId)> GetStartLocalId{0x0, 0x0};
WEAK symbol<unsigned int(scriptInstance_t inst, unsigned int localId)> Scr_TerminateRunningThread{0x0, 0x0};
WEAK symbol<void(scriptInstance_t inst, const char* error, bool force_terminal)> Scr_Error{0x0, 0x6245E0};
WEAK symbol<void(scriptInstance_t inst, unsigned int paramIndex, const char* error)> Scr_ParamError{0x0, 0x0};
WEAK symbol<void(scriptInstance_t inst, const char* error)> Scr_ObjectError{0x0, 0x0};
WEAK symbol<scr_entref_t*(scr_entref_t* refref, scriptInstance_t inst, unsigned int entId)> Scr_GetEntityIdRef{0x0, 0x6A53C0};
WEAK symbol<unsigned int(scriptInstance_t inst)> Scr_AllocArray{0x0, 0x5B8400};
WEAK symbol<gentity_s*(scr_entref_t entref)> GetPlayerEntity{0x0, 0x0};
WEAK symbol<unsigned int(scriptInstance_t inst, unsigned int localId, const char* pos, unsigned int paramcount)> VM_Execute{0x0, 0x0};
WEAK symbol<void(int clientNum, const char* reason)> SV_GameDropClient{0x0, 0x0};
WEAK symbol<bool(int clientNum)> SV_IsTestClient{0x0, 0x0};
WEAK symbol<void(int clientNum, int type, const char* command)> SV_GameSendServerCommand{0x0, 0x0};
WEAK symbol<void*(int valueIndex)> Sys_GetValue{0x0, 0x0};
WEAK symbol<int()> Sys_Milliseconds{0x0, 0x0};
WEAK symbol<void*(jmp_buf* Buf, int Value)> longjmp{0x0, 0x9D05C4};
WEAK symbol<int(jmp_buf* Buf, int a2)> _setjmp{0x0, 0x9CED5C};
// Variables
WEAK symbol<int> g_script_error_level{0x0, 0x3DD4A18};
WEAK symbol<jmp_buf> g_script_error{0x0, 0x3DD3998};
WEAK symbol<scrVmPub_t> scr_VmPub{0x0, 0x3DCB338};
WEAK symbol<scrVarGlob_t> scr_VarGlob{0x0, 0x3DCB180};
WEAK symbol<scrVarPub_t> scr_VarPub{0x0, 0x3DCB280};
WEAK symbol<int> scr_starttime{0x0, 0x0};
WEAK symbol<function_stack_t> fs{0x0, 0x0};
WEAK symbol<unsigned short> sv_configstrings{0x0, 0x0};
WEAK symbol<scr_classStruct_t*> g_classMap{0x0, 0x0};
WEAK symbol<gentity_s> g_entities{0x0, 0x0};
WEAK symbol<unsigned int> levelEntityId{0x0, 0x0};
WEAK symbol<client_s> svs_clients{0x0, 0x0};
namespace plutonium
{
WEAK symbol<int(const char* fmt, ...)> printf{0x0, 0x0};
}
}