mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-09 04:49:39 -10:00
Several things going on here: 1) refactor `get_display_string()` to `get_display_name()` to be more precise 2) likewise, refactor `alt_name` to `display_name` 3) automatically generate display names when parsing the ship, ship class, and weapon class for the first time 4) remove the on-the-fly truncation of names with hash symbols Basically this subsumes the `end_string_at_first_hash_symbol` logic into the display name. Rather than truncate the name every time it's displayed, truncate it once when it's parsed. This takes advantage of the previous display name infrastructure, since display names are a superset of the case of truncating the hash symbol. This also has the benefit of now allowing hash symbols within display names. When updating Destiny of Peace, I noticed that "Lockheed Shuttle #4" would no longer display properly; and it was not previously possible to fix this even with display names. I could pull out the `get_display_string()` and `alt_name` renaming into a separate PR if desired.
451 lines
13 KiB
C++
451 lines
13 KiB
C++
|
|
#include "parse_object.h"
|
|
|
|
#include "shipclass.h"
|
|
#include "vecmath.h"
|
|
#include "weaponclass.h"
|
|
|
|
namespace scripting {
|
|
namespace api {
|
|
|
|
parse_object_h::parse_object_h(p_object* obj) : _obj(obj) {}
|
|
p_object* parse_object_h::getObject() const { return _obj; }
|
|
bool parse_object_h::isValid() const { return _obj != nullptr; }
|
|
|
|
//**********HANDLE: parse_object
|
|
ADE_OBJ(l_ParseObject, parse_object_h, "parse_object", "Handle to a parse object");
|
|
|
|
ADE_VIRTVAR(Name, l_ParseObject, "string",
|
|
"The name of the object. If possible, don't set the name but set the display name instead.", "string",
|
|
"The name or empty string on error")
|
|
{
|
|
parse_object_h* poh = nullptr;
|
|
const char* newName = nullptr;
|
|
if (!ade_get_args(L, "o|s", l_ParseObject.GetPtr(&poh), &newName))
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if (poh == nullptr)
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if (!poh->isValid())
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
strcpy_s(poh->getObject()->name, newName);
|
|
}
|
|
|
|
return ade_set_args(L, "s", poh->getObject()->name);
|
|
}
|
|
|
|
ADE_VIRTVAR(
|
|
DisplayName, l_ParseObject, "string",
|
|
"The display name of the object. If the name should be shown to the user, use this since it can be translated.",
|
|
"string", "The display name or empty string on error")
|
|
{
|
|
parse_object_h* poh = nullptr;
|
|
const char* newName = nullptr;
|
|
if (!ade_get_args(L, "o|s", l_ParseObject.GetPtr(&poh), &newName))
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if (poh == nullptr)
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if (!poh->isValid())
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
poh->getObject()->display_name = newName;
|
|
}
|
|
|
|
return ade_set_args(L, "s", poh->getObject()->get_display_name());
|
|
}
|
|
|
|
ADE_VIRTVAR(Position, l_ParseObject, "vector", "The position at which the object will arrive.", "vector",
|
|
"The position of the object.")
|
|
{
|
|
parse_object_h* poh = nullptr;
|
|
vec3d* newPos = nullptr;
|
|
if (!ade_get_args(L, "o|o", l_ParseObject.GetPtr(&poh), l_Vector.GetPtr(&newPos)))
|
|
return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
|
|
|
|
if (poh == nullptr)
|
|
return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
|
|
|
|
if (!poh->isValid())
|
|
return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
poh->getObject()->pos = *newPos;
|
|
}
|
|
|
|
return ade_set_args(L, "o", l_Vector.Set(poh->getObject()->pos));
|
|
}
|
|
|
|
ADE_VIRTVAR(Orientation, l_ParseObject, "orientation", "The orientation of the object.", "orientation", "The orientation")
|
|
{
|
|
parse_object_h* poh = nullptr;
|
|
matrix_h* newMat = nullptr;
|
|
if (!ade_get_args(L, "o|o", l_ParseObject.GetPtr(&poh), l_Matrix.GetPtr(&newMat)))
|
|
return ade_set_error(L, "o", l_Matrix.Set(matrix_h()));
|
|
|
|
if (poh == nullptr)
|
|
return ade_set_error(L, "o", l_Matrix.Set(matrix_h()));
|
|
|
|
if (!poh->isValid())
|
|
return ade_set_error(L, "o", l_Matrix.Set(matrix_h()));
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
poh->getObject()->orient = *newMat->GetMatrix();
|
|
}
|
|
|
|
return ade_set_args(L, "o", l_Matrix.Set(matrix_h(&poh->getObject()->orient)));
|
|
}
|
|
|
|
ADE_VIRTVAR(ShipClass, l_ParseObject, "shipclass", "The ship class of the object.", "shipclass", "The ship class")
|
|
{
|
|
parse_object_h* poh = nullptr;
|
|
int newClass = -1;
|
|
if (!ade_get_args(L, "o|o", l_ParseObject.GetPtr(&poh), l_Shipclass.Get(&newClass)))
|
|
return ade_set_error(L, "o", l_Shipclass.Set(-1));
|
|
|
|
if (poh == nullptr)
|
|
return ade_set_error(L, "o", l_Shipclass.Set(-1));
|
|
|
|
if (!poh->isValid())
|
|
return ade_set_error(L, "o", l_Shipclass.Set(-1));
|
|
|
|
if (ADE_SETTING_VAR && newClass >= 0) {
|
|
poh->getObject()->ship_class = newClass;
|
|
}
|
|
|
|
return ade_set_args(L, "o", l_Shipclass.Set(poh->getObject()->ship_class));
|
|
}
|
|
|
|
ADE_VIRTVAR(InitialHull, l_ParseObject, "number", "The initial hull percentage of this object.", "number",
|
|
"The initial hull")
|
|
{
|
|
parse_object_h* poh = nullptr;
|
|
int newInitialHull = -1;
|
|
if (!ade_get_args(L, "o|i", l_ParseObject.GetPtr(&poh), &newInitialHull))
|
|
return ade_set_error(L, "i", -1);
|
|
|
|
if (poh == nullptr)
|
|
return ade_set_error(L, "i", -1);
|
|
|
|
if (!poh->isValid())
|
|
return ade_set_error(L, "i", -1);
|
|
|
|
if (ADE_SETTING_VAR && newInitialHull >= 0 && newInitialHull <= 100) {
|
|
poh->getObject()->initial_hull = newInitialHull;
|
|
}
|
|
|
|
return ade_set_args(L, "i", poh->getObject()->initial_hull);
|
|
}
|
|
|
|
ADE_VIRTVAR(InitialShields, l_ParseObject, "number", "The initial shields percentage of this object.", "number",
|
|
"The initial shields")
|
|
{
|
|
parse_object_h* poh = nullptr;
|
|
int newInitialShields = -1;
|
|
if (!ade_get_args(L, "o|i", l_ParseObject.GetPtr(&poh), &newInitialShields))
|
|
return ade_set_error(L, "i", -1);
|
|
|
|
if (poh == nullptr)
|
|
return ade_set_error(L, "i", -1);
|
|
|
|
if (!poh->isValid())
|
|
return ade_set_error(L, "i", -1);
|
|
|
|
if (ADE_SETTING_VAR && newInitialShields >= 0 && newInitialShields <= 100) {
|
|
poh->getObject()->initial_shields = newInitialShields;
|
|
}
|
|
|
|
return ade_set_args(L, "i", poh->getObject()->initial_shields);
|
|
}
|
|
|
|
ADE_VIRTVAR(MainStatus, l_ParseObject, nullptr,
|
|
"Gets the \"subsystem\" status of the ship itself. This is a special subsystem that represents the primary "
|
|
"and secondary weapons and the AI class.",
|
|
"parse_subsystem", "The subsystem handle or invalid handle if there were no changes to the main status")
|
|
{
|
|
parse_object_h* poh = nullptr;
|
|
if (!ade_get_args(L, "o", l_ParseObject.GetPtr(&poh)))
|
|
return ade_set_error(L, "o", l_ParseSubsystem.Set(parse_subsys_h()));
|
|
|
|
if (poh == nullptr)
|
|
return ade_set_error(L, "o", l_ParseSubsystem.Set(parse_subsys_h()));
|
|
|
|
if (!poh->isValid())
|
|
return ade_set_error(L, "o", l_ParseSubsystem.Set(parse_subsys_h()));
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "This property is read only.");
|
|
}
|
|
|
|
auto po = poh->getObject();
|
|
for (int i = 0; i < po->subsys_count; ++i) {
|
|
if (!stricmp(Subsys_status[po->subsys_index + i].name, "Pilot")) {
|
|
return ade_set_args(L, "o", l_ParseSubsystem.Set(parse_subsys_h(po, i)));
|
|
}
|
|
}
|
|
|
|
return ade_set_args(L, "o", l_ParseSubsystem.Set(parse_subsys_h()));
|
|
}
|
|
|
|
ADE_VIRTVAR(Subsystems, l_ParseObject, nullptr, "Get the list of subsystems of this parse object",
|
|
ade_type_array("parse_subsystem"), "An array of the parse subsystems of this object")
|
|
{
|
|
parse_object_h* poh = nullptr;
|
|
if (!ade_get_args(L, "o", l_ParseObject.GetPtr(&poh)))
|
|
return ADE_RETURN_NIL;
|
|
|
|
if (poh == nullptr)
|
|
return ADE_RETURN_NIL;
|
|
|
|
if (!poh->isValid())
|
|
return ADE_RETURN_NIL;
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "This property is read only.");
|
|
}
|
|
|
|
luacpp::LuaTable tbl = luacpp::LuaTable::create(L);
|
|
auto po = poh->getObject();
|
|
int luaIdx = 1;
|
|
for (int i = 0; i < po->subsys_count; ++i) {
|
|
// Only include the "non-main" subsystems
|
|
if (stricmp(Subsys_status[po->subsys_index + i].name, "Pilot")) {
|
|
tbl.addValue(luaIdx, l_ParseSubsystem.Set(parse_subsys_h(poh->getObject(), i)));
|
|
++luaIdx;
|
|
}
|
|
}
|
|
|
|
return ade_set_args(L, "t", tbl);
|
|
}
|
|
|
|
ADE_FUNC(isPlayerStart, l_ParseObject, nullptr, "Determines if this parse object is a player start.", "boolean",
|
|
"true if player start, false if not or if invalid")
|
|
{
|
|
parse_object_h* poh = nullptr;
|
|
if (!ade_get_args(L, "o", l_ParseObject.GetPtr(&poh)))
|
|
return ade_set_error(L, "b", false);
|
|
|
|
if (poh == nullptr)
|
|
return ade_set_error(L, "b", false);
|
|
|
|
if (!poh->isValid())
|
|
return ade_set_error(L, "b", false);
|
|
|
|
return ade_set_args(L, "b", poh->getObject()->flags[Mission::Parse_Object_Flags::OF_Player_start]);
|
|
}
|
|
|
|
parse_subsys_h::parse_subsys_h() = default;
|
|
parse_subsys_h::parse_subsys_h(p_object* obj, int subsys_offset) : _obj(obj), _subsys_offset(subsys_offset) {}
|
|
subsys_status* parse_subsys_h::getSubsys() const { return &Subsys_status[_obj->subsys_index + _subsys_offset]; }
|
|
bool parse_subsys_h::isValid() const { return _obj != nullptr && _subsys_offset < _obj->subsys_count; }
|
|
|
|
//**********HANDLE: parse_object
|
|
ADE_OBJ(l_ParseSubsystem, parse_subsys_h, "parse_subsystem", "Handle to a parse subsystem");
|
|
|
|
ADE_VIRTVAR(Name, l_ParseSubsystem, "string",
|
|
"The name of the subsystem. If possible, don't set the name but set the display name instead.", "string",
|
|
"The name or empty string on error")
|
|
{
|
|
parse_subsys_h* poh = nullptr;
|
|
const char* newName = nullptr;
|
|
if (!ade_get_args(L, "o|s", l_ParseSubsystem.GetPtr(&poh), &newName)) {
|
|
return ade_set_error(L, "s", "");
|
|
}
|
|
|
|
if (poh == nullptr) {
|
|
return ade_set_error(L, "s", "");
|
|
}
|
|
|
|
if (!poh->isValid()) {
|
|
return ade_set_error(L, "s", "");
|
|
}
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
strcpy_s(poh->getSubsys()->name, newName);
|
|
}
|
|
|
|
return ade_set_args(L, "s", poh->getSubsys()->name);
|
|
}
|
|
|
|
ADE_VIRTVAR(Damage, l_ParseSubsystem, "number", "The percentage to what the subsystem is damage", "number",
|
|
"The percentage or negative on error")
|
|
{
|
|
parse_subsys_h* poh = nullptr;
|
|
float newPercentage = -1.0f;
|
|
if (!ade_get_args(L, "o|f", l_ParseSubsystem.GetPtr(&poh), &newPercentage)) {
|
|
return ade_set_error(L, "f", -1.0f);
|
|
}
|
|
|
|
if (poh == nullptr) {
|
|
return ade_set_error(L, "f", -1.0f);
|
|
}
|
|
|
|
if (!poh->isValid()) {
|
|
return ade_set_error(L, "f", -1.0f);
|
|
}
|
|
|
|
if (ADE_SETTING_VAR && newPercentage >= 0.0f && newPercentage <= 100.0f) {
|
|
poh->getSubsys()->percent = newPercentage;
|
|
}
|
|
|
|
return ade_set_args(L, "f", poh->getSubsys()->percent);
|
|
}
|
|
|
|
ADE_VIRTVAR(PrimaryBanks, l_ParseSubsystem, nullptr, "The overridden primary banks", ade_type_array("weaponclass"),
|
|
"The primary bank weapons or nil if not changed from default")
|
|
{
|
|
parse_subsys_h* poh = nullptr;
|
|
float newPercentage = -1.0f;
|
|
if (!ade_get_args(L, "o|f", l_ParseSubsystem.GetPtr(&poh), &newPercentage)) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
|
|
if (poh == nullptr) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
|
|
if (!poh->isValid()) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "This property is read only.");
|
|
}
|
|
|
|
if (poh->getSubsys()->primary_banks[0] == SUBSYS_STATUS_NO_CHANGE) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
|
|
luacpp::LuaTable tbl = luacpp::LuaTable::create(L);
|
|
auto po = poh->getSubsys();
|
|
for (int i = 0; i < MAX_SHIP_PRIMARY_BANKS; ++i) {
|
|
if (po->primary_banks[i] == -1) {
|
|
break;
|
|
}
|
|
tbl.addValue(i + 1, l_Weaponclass.Set(po->primary_banks[i]));
|
|
}
|
|
|
|
return ade_set_args(L, "t", tbl);
|
|
}
|
|
|
|
ADE_VIRTVAR(PrimaryAmmo, l_ParseSubsystem, nullptr, "The overridden primary ammunition, as a percentage of the default",
|
|
ade_type_array("weaponclass"), "The primary bank ammunition percantage or nil if not changed from default")
|
|
{
|
|
parse_subsys_h* poh = nullptr;
|
|
float newPercentage = -1.0f;
|
|
if (!ade_get_args(L, "o|f", l_ParseSubsystem.GetPtr(&poh), &newPercentage)) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
|
|
if (poh == nullptr) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
|
|
if (!poh->isValid()) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "This property is read only.");
|
|
}
|
|
|
|
// Check the primary banks to see if changes were applied
|
|
if (poh->getSubsys()->primary_banks[0] == SUBSYS_STATUS_NO_CHANGE) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
|
|
luacpp::LuaTable tbl = luacpp::LuaTable::create(L);
|
|
auto po = poh->getSubsys();
|
|
for (int i = 0; i < MAX_SHIP_PRIMARY_BANKS; ++i) {
|
|
if (po->primary_banks[i] == -1) {
|
|
break;
|
|
}
|
|
tbl.addValue(i + 1, po->primary_ammo[i]);
|
|
}
|
|
|
|
return ade_set_args(L, "t", tbl);
|
|
}
|
|
|
|
ADE_VIRTVAR(SecondaryBanks, l_ParseSubsystem, nullptr, "The overridden secondary banks", ade_type_array("weaponclass"),
|
|
"The secondary bank weapons or nil if not changed from default")
|
|
{
|
|
parse_subsys_h* poh = nullptr;
|
|
float newPercentage = -1.0f;
|
|
if (!ade_get_args(L, "o|f", l_ParseSubsystem.GetPtr(&poh), &newPercentage)) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
|
|
if (poh == nullptr) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
|
|
if (!poh->isValid()) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "This property is read only.");
|
|
}
|
|
|
|
if (poh->getSubsys()->secondary_banks[0] == SUBSYS_STATUS_NO_CHANGE) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
|
|
luacpp::LuaTable tbl = luacpp::LuaTable::create(L);
|
|
auto po = poh->getSubsys();
|
|
for (int i = 0; i < MAX_SHIP_PRIMARY_BANKS; ++i) {
|
|
if (po->secondary_banks[i] == -1) {
|
|
break;
|
|
}
|
|
tbl.addValue(i + 1, l_Weaponclass.Set(po->secondary_banks[i]));
|
|
}
|
|
|
|
return ade_set_args(L, "t", tbl);
|
|
}
|
|
|
|
ADE_VIRTVAR(SecondaryAmmo, l_ParseSubsystem, nullptr, "The overridden secondary ammunition, as a percentage of the default",
|
|
ade_type_array("weaponclass"), "The secondary bank ammunition percantage or nil if not changed from default")
|
|
{
|
|
parse_subsys_h* poh = nullptr;
|
|
float newPercentage = -1.0f;
|
|
if (!ade_get_args(L, "o|f", l_ParseSubsystem.GetPtr(&poh), &newPercentage)) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
|
|
if (poh == nullptr) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
|
|
if (!poh->isValid()) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "This property is read only.");
|
|
}
|
|
|
|
// Check the secondary banks to see if changes were applied
|
|
if (poh->getSubsys()->secondary_banks[0] == SUBSYS_STATUS_NO_CHANGE) {
|
|
return ADE_RETURN_NIL;
|
|
}
|
|
|
|
luacpp::LuaTable tbl = luacpp::LuaTable::create(L);
|
|
auto po = poh->getSubsys();
|
|
for (int i = 0; i < MAX_SHIP_PRIMARY_BANKS; ++i) {
|
|
if (po->secondary_banks[i] == -1) {
|
|
break;
|
|
}
|
|
tbl.addValue(i + 1, po->secondary_ammo[i]);
|
|
}
|
|
|
|
return ade_set_args(L, "t", tbl);
|
|
}
|
|
|
|
} // namespace api
|
|
} // namespace scripting
|