iw5-mod/src/game/scripting/parameters.cpp
2022-03-24 10:44:20 +00:00

151 lines
4.7 KiB
C++

#include <std_include.hpp>
#include "context.hpp"
namespace game::scripting
{
parameters::parameters(context* context) : context_(context)
{
}
chaiscript::Boxed_Value parameters::load(const native::VariableValue value) const
{
if (value.type == native::SCRIPT_STRING)
{
const std::string string = native::SL_ConvertToString(value.u.stringValue);
return chaiscript::var(string);
}
else if (value.type == native::SCRIPT_FLOAT)
{
return chaiscript::var(value.u.floatValue);
}
else if (value.type == native::SCRIPT_INTEGER)
{
return chaiscript::var(value.u.intValue);
}
else if (value.type == native::SCRIPT_OBJECT)
{
return chaiscript::var(entity(this->context_, value.u.entityId));
}
else if (value.type == native::SCRIPT_VECTOR)
{
std::vector<chaiscript::Boxed_Value> values;
values.push_back(chaiscript::var(value.u.vectorValue[0]));
values.push_back(chaiscript::var(value.u.vectorValue[1]));
values.push_back(chaiscript::var(value.u.vectorValue[2]));
return chaiscript::var(values);
}
return {};
}
void parameters::push(const chaiscript::Boxed_Value& value) const
{
if (native::scr_VmPub->outparamcount)
{
native::Scr_ClearOutParams();
}
if (native::scr_VmPub->top == native::scr_VmPub->maxstack)
{
throw std::runtime_error("Internal script stack overflow");
}
native::VariableValue* value_ptr = ++native::scr_VmPub->top;
++native::scr_VmPub->inparamcount;
value_ptr->type = native::SCRIPT_NONE;
value_ptr->u.intValue = 0;
if (value.get_type_info() == typeid(float))
{
const auto real_value = this->context_->get_chai()->boxed_cast<float>(value);
value_ptr->type = native::SCRIPT_FLOAT;
value_ptr->u.floatValue = real_value;
}
else if (value.get_type_info() == typeid(double))
{
const auto real_value = this->context_->get_chai()->boxed_cast<double>(value);
value_ptr->type = native::SCRIPT_FLOAT;
value_ptr->u.floatValue = static_cast<float>(real_value);
}
else if (value.get_type_info() == typeid(int))
{
const auto real_value = this->context_->get_chai()->boxed_cast<int>(value);
value_ptr->type = native::SCRIPT_INTEGER;
value_ptr->u.intValue = real_value;
}
else if (value.get_type_info() == typeid(bool))
{
const auto real_value = this->context_->get_chai()->boxed_cast<bool>(value);
value_ptr->type = native::SCRIPT_INTEGER;
value_ptr->u.intValue = real_value;
}
else if (value.get_type_info() == typeid(entity))
{
const auto real_value = this->context_->get_chai()->boxed_cast<entity>(value);
value_ptr->type = native::SCRIPT_OBJECT;
value_ptr->u.entityId = real_value.get_entity_id();
game::native::AddRefToValue(value_ptr);
}
else if (value.get_type_info() == typeid(std::string))
{
const auto real_value = this->context_->get_chai()->boxed_cast<std::string>(value);
value_ptr->type = native::SCRIPT_STRING;
value_ptr->u.stringValue = game::native::SL_GetString(real_value.data(), 0);
}
else if (value.get_type_info() == typeid(std::vector<chaiscript::Boxed_Value>))
{
float values[3];
const auto real_value = this->context_->get_chai()->boxed_cast<std::vector<chaiscript::Boxed_Value>
>(value);
if (real_value.size() != 3)
{
throw std::runtime_error("Invalid vector length. Size must be exactly 3");
}
const auto unbox_float = [&real_value, this](const size_t index) -> float
{
const auto value = real_value[index];
if (value.get_type_info() == typeid(float))
{
return this->context_->get_chai()->boxed_cast<float>(value);
}
if (value.get_type_info() == typeid(double))
{
return float(this->context_->get_chai()->boxed_cast<double>(value));
}
if (value.get_type_info() == typeid(int))
{
return float(this->context_->get_chai()->boxed_cast<int>(value));
}
throw std::runtime_error("Vector element at index " + std::to_string(index) + " is not a number");
};
values[0] = unbox_float(0);
values[1] = unbox_float(1);
values[2] = unbox_float(2);
value_ptr->type = native::SCRIPT_VECTOR;
value_ptr->u.vectorValue = native::Scr_AllocVector(values);
}
else
{
throw std::runtime_error("Unable to unbox value of type '"s + value.get_type_info().bare_name() + "'");
}
}
chaiscript::Boxed_Value parameters::get_return_value() const
{
if (native::scr_VmPub->inparamcount == 0) return {};
native::Scr_ClearOutParams();
native::scr_VmPub->outparamcount = native::scr_VmPub->inparamcount;
native::scr_VmPub->inparamcount = 0;
return this->load(native::scr_VmPub->top[1 - native::scr_VmPub->outparamcount]);
}
}