Skip to content

Commit

Permalink
electrical arc upgrade, stage 4: add a new ModifyElectricArcPoints fu…
Browse files Browse the repository at this point in the history
…nction with a handy valueToVec3d utility function
  • Loading branch information
Goober5000 committed Sep 21, 2024
1 parent 8548e7f commit 2606d31
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 0 deletions.
66 changes: 66 additions & 0 deletions code/scripting/api/objs/ship.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
#include "ship/shipfx.h"
#include "ship/shiphit.h"

#include "scripting/lua/LuaException.h"
#include "scripting/lua/LuaUtil.h"

extern void ship_reset_disabled_physics(object *objp, int ship_class);
extern bool sexp_check_flag_arrays(const char *flag_name, Object::Object_Flags &object_flag, Ship::Ship_Flags &ship_flags, Mission::Parse_Object_Flags &parse_obj_flag, AI::AI_Flags &ai_flag);
extern void sexp_alter_ship_flag_helper(object_ship_wing_point_team &oswpt, bool future_ships, Object::Object_Flags object_flag, Ship::Ship_Flags ship_flag, Mission::Parse_Object_Flags parse_obj_flag, AI::AI_Flags ai_flag, bool set_flag);
Expand Down Expand Up @@ -2824,5 +2827,68 @@ ADE_FUNC(ModifyElectricArc, l_Ship, "number index, vector firstPoint, vector sec
return ADE_RETURN_NIL;
}

ADE_FUNC(ModifyElectricArcPoints, l_Ship, "number index, table points, [number width]",
"Sets the collection of persistent points to be used by this arc, as well as optionally the arc's width. "
"The table of points should consist of Vectors (e.g. created with ba.createVector()), arrays with three elements each, or tables with 'x'/'X', 'y'/'Y', and 'z'/'Z' pairs. There must be at least two points.",
nullptr,
nullptr)
{
object_h* objh = nullptr;
int index;
luacpp::LuaTable luaPoints;
float width = 0.0f;

int args = ade_get_args(L, "oit|f", l_Ship.GetPtr(&objh), &index, &luaPoints, &width);
if (args < 3)
return ADE_RETURN_NIL;

if (!objh->isValid())
return ADE_RETURN_NIL;

auto shipp = &Ships[objh->objp()->instance];

index--; // Lua -> FS2
if (SCP_vector_inbounds(shipp->electrical_arcs, index) && luaPoints.isValid())
{
SCP_vector<vec3d> fsoPoints;

// convert Lua points to FSO points
for (const auto &entry : luaPoints)
{
try
{
fsoPoints.push_back(luacpp::util::valueToVec3d(entry.second));
}
catch (const luacpp::LuaException &e)
{
LuaError(L, "%s", e.what());
return ADE_RETURN_NIL;
}
}

if (fsoPoints.size() < 2)
{
LuaError(L, "Points table passed to ship:ModifyElectricArcPoints() has fewer than two points!");
return ADE_RETURN_NIL;
}

auto &arc = shipp->electrical_arcs[index];
arc.endpoint_1 = fsoPoints.front();
arc.endpoint_2 = fsoPoints.back();

// need to create the persistent point storage if it isn't set up yet
if (!arc.persistent_arc_points)
arc.persistent_arc_points.reset(new SCP_vector<vec3d>());

// assign all of our new points to the persistent point storage
arc.persistent_arc_points->operator=(std::move(fsoPoints));

if (args >= 4)
arc.width = width;
}

return ADE_RETURN_NIL;
}

}
}
78 changes: 78 additions & 0 deletions code/scripting/lua/LuaUtil.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@

#include "LuaUtil.h"

#include "scripting/api/objs/vecmath.h"

namespace {
const char* mainStateRefName = "_lua_mainthread";
}
Expand Down Expand Up @@ -62,5 +64,81 @@ lua_State* getMainThread(lua_State* L)
return state;
}

vec3d valueToVec3d(const LuaValue &luaValue)
{
if (luaValue.is(luacpp::ValueType::TABLE))
{
vec3d tablePoint = vmd_zero_vector;
int index = 0;
bool is_array = false;
bool is_table = false;

// we have to go deeper
luacpp::LuaTable childTable;
childTable.setReference(luaValue.getReference());
for (const auto &childEntry : childTable)
{
// note: this is pre-increment
if (index >= 3)
throw LuaException("Vec3d table has more than three entries!");

if (!childEntry.second.is(luacpp::ValueType::NUMBER))
throw LuaException("Value in vec3d table is not a number!");

auto number = static_cast<float>(childEntry.second.getValue<double>());

if (childEntry.first.is(luacpp::ValueType::STRING))
{
is_table = true;
if (is_array)
throw LuaException("Vec3d table has an unexpected format!");

const auto &str = childEntry.first.getValue<SCP_string>();
if (lcase_equal(str, "x"))
tablePoint.xyz.x = number;
else if (lcase_equal(str, "y"))
tablePoint.xyz.y = number;
else if (lcase_equal(str, "z"))
tablePoint.xyz.z = number;
else
throw LuaException("Vec3d table has an entry other than x/X, y/Y, or z/Z!");
}
else
{
is_array = true;
if (is_table)
throw LuaException("Vec3d table has an unexpected format!");

tablePoint.a1d[index] = number;
}

index++;
}

// note: this is post-increment
if (index < 3)
throw LuaException("Vec3d table has fewer than three entries!");

return tablePoint;
}
else if (luaValue.is(luacpp::ValueType::USERDATA))
{
try
{
vec3d v;
luaValue.getValue(scripting::api::l_Vector.Get(&v));
return v;
}
catch (const luacpp::LuaException& /*e*/)
{
throw LuaException("Userdata in vec3d table is not a vector!");
}
}
else
{
throw LuaException("Vec3d value is of an unhandled type!");
}
}

} // namespace util
} // namespace luacpp
8 changes: 8 additions & 0 deletions code/scripting/lua/LuaUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,14 @@ void tableToList(LuaTable& table, Container& list) {
}

const char* getValueName(ValueType type);

/**
* Processes a LuaValue and returns a vec3d. The LuaValue could be a Vector, an array with three elements, or a table with x/X, y/Y, and z/Z entries.
*
* Throws a LuaException if the conversion was not successful.
*/
vec3d valueToVec3d(const LuaValue &luaValue);

}
}

Expand Down

0 comments on commit 2606d31

Please sign in to comment.