Standardize isValid across the Lua API by making the types auto-generate it (#7761)

* Automatically generate the isValid() Lua API function for handle types

If an ADE object's stored type has an isValid() member, ade_obj now registers an isValid function for it automatically.  An explicit ADE_FUNC(isValid, ...) declared after the ADE_OBJ replaces the generated one, so types with special semantics (e.g. sound) keep their own.  The 67 hand-written functions that merely delegated to the member are removed, and 26 types that previously exposed no isValid() gain one.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

* Add ADE_OBJ_VALIDATOR for index-based Lua handles

Int-index handles (shipclass, weaponclass, team, etc.) can now declare their validity predicate with a single ADE_OBJ_VALIDATOR or ADE_OBJ_VALIDATOR_RANGE line after the ADE_OBJ.  The registered validator drives the generated isValid() function and is also honored by ade_set_args when the mod table asks for nil instead of invalid objects, which previously never applied to these handles.  The 19 hand-written range-check functions are replaced, and loadout_ship, default_primary, default_secondary, and support_rearm_pool_team gain isValid().  Add a validator to HudGauge while we're at it.

Also fully qualify the scripting namespace in LuaConvert.h so its templates can be instantiated from the unit tests.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

---------

Co-authored-by: Claude Fable 5.1 <[email protected]>
This commit is contained in:
Goober5000andClaude Fable 5.1 authored and GitHub committed 2026-09-08 10:50:53 -04:00
1 parent a168f5a9c0
commit 37b0b6ea82
68 files changed
+294 -982

No files matched your search

+17 -2
View File
@@ -316,7 +316,8 @@ int ade_table_entry::SetTable(lua_State* L, int p_amt_ldx, int p_mtb_ldx)
// when using va_args for some reason.
lua_pushstring(L, "<UNNAMED FUNCTION>");
lua_pushboolean(L, 0);
lua_pushcclosure(L, Function, 2);
lua_pushlightuserdata(L, Obj_upvalue); // upvalue(3) = Reference to ade_obj, if this is a generated function
lua_pushcclosure(L, Function, 3);
}
nset++;
break;
@@ -430,7 +431,7 @@ int ade_table_entry::SetTable(lua_State* L, int p_amt_ldx, int p_mtb_ldx)
lua_pushstring(L, "__gc");
lua_pushfstring(L, "%s Destructor", GetName()); // upvalue(1) = function name
lua_pushboolean(L, 0); // upvalue(2) = setting true/false
lua_pushlightuserdata(L, Destructor_upvalue); // upvalue(3) = Reference to ade_obj
lua_pushlightuserdata(L, Obj_upvalue); // upvalue(3) = Reference to ade_obj
lua_pushcclosure(L, Destructor, 3);
lua_rawset(L, mtb_ldx);
}
@@ -488,6 +489,20 @@ int ade_table_entry::SetTable(lua_State* L, int p_amt_ldx, int p_mtb_ldx)
size_t ade_table_entry::AddSubentry(ade_table_entry& n_ate) {
ade_table_entry ate = n_ate;
ate.ParentIdx = Idx;
// If a subentry with this name already exists (e.g. an explicitly declared function overriding one that was
// automatically generated), replace it in place so that both Lua and the documentation see only the latest one
if (ate.Name != nullptr) {
for (size_t i = 0; i < Num_subentries; i++) {
auto& existing = ade_manager::getInstance()->getEntry(Subentries[i]);
if (existing.Name != nullptr && strcmp(existing.Name, ate.Name) == 0) {
ate.Idx = existing.Idx;
existing = ate;
return ate.Idx;
}
}
}
size_t new_idx = ade_manager::getInstance()->addTableEntry(ate);
//WMC - Oi. Moving the Ade_table_entries vector
+31 -2
View File
@@ -60,7 +60,7 @@ const size_t ODATA_PTR_SIZE = (size_t) -1;
const int ADE_FUNCNAME_UPVALUE_INDEX = 1;
const int ADE_SETTING_UPVALUE_INDEX = 2;
const int ADE_DESTRUCTOR_OBJ_UPVALUE_INDEX = 3; // Upvalue which stores the reference to the ade_obj of a destructor
const int ADE_OBJ_UPVALUE_INDEX = 3; // Upvalue which stores the reference to the ade_obj for destructors and generated functions
#define ADE_SETTING_VAR lua_toboolean(L,lua_upvalueindex(ADE_SETTING_UPVALUE_INDEX))
template <typename T>
@@ -130,8 +130,14 @@ class ade_table_entry {
//Functions/virtfuncs
lua_CFunction Function = nullptr;
// Reference to the ade_obj, passed as an upvalue to Function (for generated functions) and Destructor
void* Obj_upvalue = nullptr;
// For Objects, an optional validity predicate taking a pointer to the stored value. Set via ADE_OBJ_VALIDATOR;
// takes precedence over the stored type's isValid() member.
bool (*Validator)(const void*) = nullptr;
// For Objects, the destructor of the object
void* Destructor_upvalue = nullptr;
lua_CFunction Destructor = nullptr;
size_t Size = 0;
@@ -245,6 +251,29 @@ struct ade_is_valid <T, decltype((void)(std::declval<T>().isValid()), 0)> : std:
}
};
/**
* @brief Determines whether a value stored in an API object is valid
*
* A validator registered (via ADE_OBJ_VALIDATOR) on the object's table entry, or on that of any object it derives
* from, takes precedence; otherwise the stored type's isValid() member is used, and types without one are always
* considered valid.
*
* @param idx The table entry index of the API object
* @param value The stored value
*/
template <typename T>
bool ade_object_is_valid(size_t idx, const T& value)
{
for (size_t i = idx; i != UINT_MAX; i = ade_manager::getInstance()->getEntry(i).DerivatorIdx)
{
const auto& entry = ade_manager::getInstance()->getEntry(i);
if (entry.Validator != nullptr)
return entry.Validator(&value);
}
return ade_is_valid<T>::get(value);
}
/**
* @brief Converts an object index to something that can be used with ade_set_args.
*
+105 -7
View File
@@ -98,21 +98,52 @@ class ade_obj : public ade_lib_handle {
static int lua_destructor(lua_State* L)
{
auto* obj =
static_cast<ade_obj<StoreType>*>(lua_touserdata(L, lua_upvalueindex(ADE_DESTRUCTOR_OBJ_UPVALUE_INDEX)));
static_cast<ade_obj<StoreType>*>(lua_touserdata(L, lua_upvalueindex(ADE_OBJ_UPVALUE_INDEX)));
StoreType* value = nullptr;
if (!ade_get_args(L, "o", obj->GetPtr(&value))) {
return 0;
}
if (value == nullptr) {
return 0;
}
value->~StoreType();
return 0;
}
// Automatically generated isValid() API function for types whose StoreType has an isValid() member or which have
// a validator registered via ADE_OBJ_VALIDATOR. An explicit ADE_FUNC(isValid, ...) declared after the ADE_OBJ
// replaces this one.
static int lua_isValid(lua_State* L)
{
auto* obj =
static_cast<ade_obj<StoreType>*>(lua_touserdata(L, lua_upvalueindex(ADE_OBJ_UPVALUE_INDEX)));
StoreType* value = nullptr;
if (!ade_get_args(L, "o", obj->GetPtr(&value))) {
return 0; // nil
}
return ade_set_args(L, "b", ade_object_is_valid(obj->GetIdx(), *value));
}
// Registers the generated isValid() function as a member of this object. Safe to call more than once.
void registerIsValid() const
{
ade_table_entry func;
func.Name = "isValid";
func.Instanced = true;
func.Type = 'u';
func.Function = lua_isValid;
func.Obj_upvalue = const_cast<void*>(static_cast<const void*>(this));
func.Arguments = nullptr;
func.Description = "Detects whether handle is valid";
func.ReturnType = "boolean";
func.ReturnDescription = "true if valid, false if handle is invalid, nil if a syntax/type error occurs";
ade_manager::getInstance()->getEntry(LibIdx).AddSubentry(func);
}
public:
using value_type = StoreType;
ade_obj(const char* in_name, const char* in_desc, const ade_lib_handle* in_deriv = nullptr, size_t size = 0, ade_serialize_func serializer = nullptr, ade_deserialize_func deserializer = nullptr)
{
ade_table_entry ate;
@@ -132,11 +163,25 @@ class ade_obj : public ade_lib_handle {
// If this type is not trivial then we need to have a destructor
// This is mildly dangerous since "this" will only remain valid if it was constructed statically. Since this
// value is only used once at program startup it should be relatively safe
ate.Destructor_upvalue = static_cast<void*>(this);
ate.Destructor = lua_destructor;
ate.Obj_upvalue = static_cast<void*>(this);
ate.Destructor = lua_destructor;
}
LibIdx = ade_manager::getInstance()->addTableEntry(ate);
// If the stored type can report its validity, expose that to Lua automatically. Derived types inherit
// this from their base object (which in all current cases stores the same type), so skip it for those.
if (ade_is_valid<StoreType>::value && in_deriv == nullptr) {
registerIsValid();
}
}
// Registers a validity predicate for this object, used by the generated isValid() function and by ade_set_args
// when returning nil instead of invalid objects. Use the ADE_OBJ_VALIDATOR macro rather than calling this directly.
void setValidator(bool (*fn)(const void*)) const
{
ade_manager::getInstance()->getEntry(LibIdx).Validator = fn;
registerIsValid();
}
// WMC - Use this to store object data for return, or for setting as a global
@@ -219,8 +264,61 @@ class ade_obj : public ade_lib_handle {
* @ingroup ade_api
*/
#define ADE_OBJ_DERIV(field, type, name, desc, deriv) \
static_assert(std::is_same<type, \
std::remove_cv_t<std::remove_reference_t<decltype(SCP_TOKEN_CONCAT(get_, deriv)())>>::value_type>::value, \
"A derived API object must store the same type as the object it derives from"); \
ADE_OBJ_DERIV_IMPL(field, type, name, desc, &SCP_TOKEN_CONCAT(get_, deriv)(), ade_multi_serializer<type>)
/**
* Validator registration class. Use the ADE_OBJ_VALIDATOR macro rather than declaring one of these directly.
*
* @ingroup ade_api
*/
class ade_validator {
public:
template <class StoreType>
ade_validator(const ade_obj<StoreType>& obj, bool (*fn)(const void*))
{
obj.setValidator(fn);
}
};
/**
* @brief Declare a validity predicate for an API object
*
* This generates an isValid() function for the object, and also lets the engine return nil instead of an invalid
* handle when the mod table option for that is set. Use this for objects whose stored type cannot report its own
* validity (e.g. an int index into a table); objects whose stored type has an isValid() member get this automatically.
*
* @param field The name of the object field (e.g. l_Shipclass)
* @param var The name by which the stored value is referred to in the expression
* @param expr An expression yielding true when the value is valid; evaluated each time validity is checked
*
* @ingroup ade_api
*/
#define ADE_OBJ_VALIDATOR(field, var, expr) \
static bool SCP_TOKEN_CONCAT(field, _validator)(const void* ade_validator_value) \
{ \
const auto& var = \
*static_cast<const std::remove_reference_t<decltype(field)>::value_type*>(ade_validator_value); \
return (expr); \
} \
static ::scripting::ade_validator SCP_TOKEN_CONCAT(field, _validator_registrar)(SCP_TOKEN_CONCAT(get_, field)(), \
SCP_TOKEN_CONCAT(field, _validator))
/**
* @brief Declare an index-based API object as valid for the range [0, upper)
*
* Shorthand for ADE_OBJ_VALIDATOR for the common case of an int index. The upper bound is evaluated each time
* validity is checked, so it can (and usually should) be a function call or a container size.
*
* @param field The name of the object field (e.g. l_Shipclass)
* @param upper The exclusive upper bound of the valid range
*
* @ingroup ade_api
*/
#define ADE_OBJ_VALIDATOR_RANGE(field, upper) ADE_OBJ_VALIDATOR(field, idx, idx >= 0 && idx < (upper))
/**
* @brief Declare an API object but don't define it
*
+3 -2
View File
@@ -307,8 +307,9 @@ void set_single_arg(lua_State* L, char fmt, ade_odata_setter<T>&& od)
Assertion(fmt == 'o', "Invalid format character '%c' for object type!", fmt);
if (Lua_API_returns_nil_instead_of_invalid_object) {
// If the underlying type has an isValid, it'll be evaluated; otherwise it'll be always true.
bool isValid = ade_is_valid<T>::get(od.value);
// A registered validator wins; otherwise, if the underlying type has an isValid, it'll be evaluated;
// otherwise it'll be always true.
bool isValid = ade_object_is_valid(od.idx, od.value);
if (!isValid) {
lua_pushnil(L);
-9
View File
@@ -128,14 +128,5 @@ ADE_FUNC(removeEnumItem,
return ADE_RETURN_FALSE;
}
ADE_FUNC(isValid, l_LuaEnum, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
lua_enum_h lua_enum;
if (!ade_get_args(L, "o", l_LuaEnum.Get(&lua_enum)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", lua_enum.isValid());
}
} // namespace api
} // namespace scripting
+1 -15
View File
@@ -8,6 +8,7 @@ namespace api {
//**********HANDLE: Asteroid
ADE_OBJ_NO_MULTI(l_AudioStream, int, "audio_stream", "An audio stream handle");
ADE_OBJ_VALIDATOR(l_AudioStream, idx, idx >= 0);
ADE_FUNC(play,
l_AudioStream,
@@ -161,20 +162,5 @@ ADE_FUNC(getDuration, l_AudioStream, nullptr, "Gets the duration of the stream",
return ade_set_args(L, "f", (float)audiostream_get_duration(streamHandle));
}
ADE_FUNC(isValid,
l_AudioStream,
nullptr,
"Determines if the handle is valid",
"boolean",
"true if valid, false otherwise")
{
int streamHandle = -1;
if (!ade_get_args(L, "o", l_AudioStream.Get(&streamHandle))) {
return ADE_RETURN_FALSE;
}
return ade_set_args(L, "b", streamHandle >= 0);
}
} // namespace api
} // namespace scripting
@@ -26,16 +26,6 @@ bool background_el_h::isValid() const
}
}
ADE_FUNC(isValid, l_BackgroundElement, nullptr, "Determines if this handle is valid", "boolean",
"true if valid, false if not.")
{
background_el_h* el = nullptr;
if (!ade_get_args(L, "o", l_BackgroundElement.GetPtr(&el)))
return ADE_RETURN_FALSE;
return ade_set_args(L, "b", el->isValid());
}
ADE_VIRTVAR(Orientation, l_BackgroundElement, "orientation", "Backround element orientation (treating the angles as correctly calculated)", "orientation", "Orientation, or null orientation if handle is invalid")
{
background_el_h* el = nullptr;
-12
View File
@@ -25,18 +25,6 @@ ADE_FUNC(__tostring, l_Camera, NULL, "Camera name", "string", "Camera name, or a
return ade_set_args(L, "s", cid.getCamera()->get_name());
}
ADE_FUNC(isValid, l_Camera, NULL, "True if valid, false or nil if not", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
camid cid;
if(!ade_get_args(L, "o", l_Camera.Get(&cid)))
return ADE_RETURN_NIL;
if(!cid.isValid())
return ADE_RETURN_FALSE;
return ADE_RETURN_TRUE;
}
ADE_VIRTVAR(Name, l_Camera, "string", "New camera name", "string", "Camera name")
{
camid cid;
@@ -168,16 +168,6 @@ ADE_FUNC(getOffset,
return ade_set_args(L, "ii", cdi->offset[0], cdi->offset[1]);
}
ADE_FUNC(isValid, l_DisplayInfo, NULL, "Detects whether this handle is valid", "boolean", "true if valid false otherwise")
{
cockpit_disp_info_h *cdh = NULL;
if (!ade_get_args(L, "o", l_DisplayInfo.GetPtr(&cdh)))
return ADE_RETURN_FALSE;
return ade_set_args(L, "b", cdh->isValid());
}
cockpit_display_h::cockpit_display_h()
: m_obj_num( -1 ), m_display_num( INVALID_ID ) {}
@@ -354,16 +344,6 @@ ADE_FUNC(getOffset,
return ade_set_args(L, "ii", cd->offset[0], cd->offset[1]);
}
ADE_FUNC(isValid, l_CockpitDisplay, NULL, "Detects whether this handle is valid or not", "boolean", "true if valid, false otherwise")
{
cockpit_display_h *cdh = NULL;
if (!ade_get_args(L, "o", l_CockpitDisplay.GetPtr(&cdh)))
return ADE_RETURN_FALSE;
return ade_set_args(L, "b", cdh->isValid());
}
cockpit_displays_info_h::cockpit_displays_info_h() : m_ship_info_idx( -1 ) {}
cockpit_displays_info_h::cockpit_displays_info_h(int ship_info_idx) {
@@ -485,15 +465,6 @@ ADE_INDEXER(l_CockpitDisplayInfos, "number/string",
}
}
ADE_FUNC(isValid, l_CockpitDisplayInfos, NULL, "Detects whether this handle is valid", "boolean", "true if valid, false otehrwise")
{
cockpit_displays_info_h *cdih = NULL;
if (!ade_get_args(L, "o", l_CockpitDisplayInfos.GetPtr(&cdih)))
return ADE_RETURN_FALSE;
return ade_set_args(L, "b", cdih->isValid());
}
cockpit_displays_h::cockpit_displays_h() : m_obj_num( -1 ) {}
cockpit_displays_h::cockpit_displays_h(int obj_num) : m_obj_num( obj_num ) {}
@@ -600,15 +571,6 @@ ADE_INDEXER(l_CockpitDisplays, "number/string", "Gets a cockpit display from the
}
}
ADE_FUNC(isValid, l_CockpitDisplays, NULL, "Detects whether this handle is valid or not", "boolean", "true if valid, false otherwise")
{
cockpit_displays_h *cdh = NULL;
if(!ade_get_args(L, "o", l_CockpitDisplays.GetPtr(&cdh)))
return ADE_RETURN_FALSE;
return ade_set_args(L, "b", cdh->isValid());
}
}
}
+1 -10
View File
@@ -6,6 +6,7 @@ namespace scripting::api {
//**********HANDLE: mission goals
ADE_OBJ_NO_MULTI(l_Comm_Item, int, "comm_item", "Comm Item handle");
ADE_OBJ_VALIDATOR(l_Comm_Item, idx, MsgItems.in_bounds(idx));
ADE_VIRTVAR(Name, l_Comm_Item, nullptr, "The name of the comm item", "string", "The comm item name")
{
@@ -73,14 +74,4 @@ ADE_FUNC(selectItem, l_Comm_Item, nullptr, "Selects the item and either proceeds
return ADE_RETURN_TRUE;
}
ADE_FUNC(isValid, l_Comm_Item, nullptr, "Detect if the handle is valid", "boolean", "true if valid, false otherwise")
{
int current = -1;
if (!ade_get_args(L, "o", l_Comm_Item.Get(&current)))
return ADE_RETURN_FALSE;
return ade_set_args(L, "b", MsgItems.in_bounds(current));
}
} // namespace scripting::api
-9
View File
@@ -130,15 +130,6 @@ ADE_FUNC(getDebrisRadius, l_Debris, NULL, "The radius of this debris piece", "nu
return ade_set_error(L, "f", pm->submodel[db->submodel_num].rad);
}
ADE_FUNC(isValid, l_Debris, NULL, "Return if this debris handle is valid", "boolean", "true if valid false otherwise")
{
object_h *oh;
if(!ade_get_args(L, "o", l_Debris.GetPtr(&oh)))
return ADE_RETURN_FALSE;
return ade_set_args(L, "b", oh != NULL && oh->isValid());
}
ADE_FUNC(isGeneric, l_Debris, nullptr, "Return if this debris is the generic debris model, not a model subobject", "boolean", "true if Debris_model")
{
object_h *oh;
+1 -12
View File
@@ -13,6 +13,7 @@ namespace api {
//**********HANDLE: DecalDefinitionclass
ADE_OBJ(l_DecalDefinitionclass, int, "decaldefinition", "Decal definition handle");
ADE_OBJ_VALIDATOR(l_DecalDefinitionclass, idx, decals::DecalDefinitions.in_bounds(idx));
ADE_FUNC(__tostring, l_DecalDefinitionclass, nullptr, "Decal definition name", "string", "Decal definition unique id, or an empty string if handle is invalid")
{
@@ -42,18 +43,6 @@ ADE_FUNC(__eq, l_DecalDefinitionclass, "decaldefinition, decaldefinition", "Chec
return ade_set_args(L, "b", idx1 == idx2);
}
ADE_FUNC(isValid, l_DecalDefinitionclass, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if invalid, nil if a syntax/type error occurs")
{
int idx;
if (!ade_get_args(L, "o", l_DecalDefinitionclass.Get(&idx)))
return ADE_RETURN_NIL;
if (idx < 0 || idx >= static_cast<int>(decals::DecalDefinitions.size()))
return ADE_RETURN_FALSE;
return ADE_RETURN_TRUE;
}
ADE_VIRTVAR(Name, l_DecalDefinitionclass, "string", "Decal definition name", "string", "Decal definition name, or empty string if handle is invalid")
{
int idx;
+1 -12
View File
@@ -8,6 +8,7 @@ namespace scripting::api
{
//**********HANDLE: mission event
ADE_OBJ(l_Event, int, "mission_event", "Mission event handle");
ADE_OBJ_VALIDATOR(l_Event, idx, Mission_events.in_bounds(idx));
ADE_VIRTVAR(Name, l_Event, "string", "Mission event name", "string", nullptr)
{
@@ -142,16 +143,4 @@ ADE_VIRTVAR(Score, l_Event, "number", "Event score", "number", "Event score, or
return ade_set_args(L, "i", mep->score);
}
ADE_FUNC(isValid, l_Event, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
int idx;
if (!ade_get_args(L, "o", l_Event.Get(&idx)))
return ADE_RETURN_NIL;
if (idx < 0 || idx >= (int)Mission_events.size())
return ADE_RETURN_FALSE;
return ADE_RETURN_TRUE;
}
}
@@ -48,20 +48,5 @@ ADE_FUNC(determineState,
}
}
ADE_FUNC(isValid,
l_ExecutionContext,
nullptr,
"Determines if the handle is valid",
"boolean",
"true if valid, false otherwise")
{
execution_context_h* context = nullptr;
if (!ade_get_args(L, "o", l_ExecutionContext.GetPtr(&context))) {
return ADE_RETURN_FALSE;
}
return ade_set_args(L, "b", context != nullptr && context->isValid());
}
} // namespace api
} // namespace scripting
-18
View File
@@ -60,23 +60,5 @@ ADE_FUNC(schedule,
return ADE_RETURN_TRUE;
}
ADE_FUNC(isValid,
l_Executor,
nullptr,
"Determined if this handle is valid",
"boolean",
"true if valid, false otherwise.")
{
executor_h* executor = nullptr;
if (!ade_get_args(L, "o", l_Executor.GetPtr(&executor))) {
return ADE_RETURN_FALSE;
}
if (executor == nullptr || !executor->isValid()) {
return ADE_RETURN_FALSE;
}
return ADE_RETURN_TRUE;
}
} // namespace api
} // namespace scripting
-10
View File
@@ -68,16 +68,6 @@ ADE_VIRTVAR(Position, l_Eyepoint, "vector", "Eyepoint location (Local vector)",
return ade_set_args(L, "o", l_Vector.Set(pm->view_positions[eh->eye_idx].pnt));
}
ADE_FUNC(isValid, l_Eyepoint, nullptr, "Detect whether this handle is valid", "boolean", "true if valid false otherwise")
{
eye_h* eh = nullptr;
if (!ade_get_args(L, "o", l_Eyepoint.GetPtr(&eh))) {
return ADE_RETURN_FALSE;
}
return ade_set_args(L, "b", eh->isValid());
}
ADE_FUNC_DEPRECATED(IsValid,
l_Eyepoint,
nullptr,
-12
View File
@@ -26,18 +26,6 @@ void cfile_h::close()
//**********HANDLE: File
ADE_OBJ(l_File, cfile_h, "file", "File handle");
ADE_FUNC(isValid, l_File, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
cfile_h* cfp = nullptr;
if (!ade_get_args(L, "o", l_File.GetPtr(&cfp)))
return ADE_RETURN_NIL;
if (cfp == nullptr || !cfp->isValid())
return ADE_RETURN_FALSE;
return ADE_RETURN_TRUE;
}
ADE_FUNC(close, l_File, NULL, "Instantly closes file and invalidates all file handles", NULL, NULL)
{
cfile_h* cfp = nullptr;
+1 -12
View File
@@ -11,6 +11,7 @@ namespace api {
//**********HANDLE: Fireballclass
ADE_OBJ(l_Fireballclass, int, "fireballclass", "Fireball class handle");
ADE_OBJ_VALIDATOR(l_Fireballclass, idx, Fireball_info.in_bounds(idx));
ADE_FUNC(__tostring, l_Fireballclass, NULL, "Fireball class name", "string", "Fireball class unique id, or an empty string if handle is invalid")
{
@@ -100,18 +101,6 @@ ADE_VIRTVAR(FPS, l_Fireballclass, NULL, "The FPS with which this fireball's anim
return ade_set_args(L, "i", Fireball_info[idx].lod[0].fps);
}
ADE_FUNC(isValid, l_Fireballclass, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
int idx;
if(!ade_get_args(L, "o", l_Fireballclass.Get(&idx)))
return ADE_RETURN_NIL;
if (!SCP_vector_inbounds(Fireball_info, idx))
return ADE_RETURN_FALSE;
return ADE_RETURN_TRUE;
}
ADE_FUNC(getTableIndex, l_Fireballclass, NULL, "Gets the index value of the fireball class", "number", "index value of the fireball class")
{
int idx;
-9
View File
@@ -186,14 +186,5 @@ ADE_FUNC(hasCanScale, l_Font, nullptr, "True if this font is allowed to scale ba
return ade_set_args(L, "b", fh != nullptr && fh->Get()->getScaleBehavior());
}
ADE_FUNC(isValid, l_Font, nullptr, "True if valid, false or nil if not", "boolean", "Detects whether handle is valid")
{
font_h *fh = nullptr;
if (!ade_get_args(L, "o", l_Font.GetPtr(&fh)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", fh != nullptr && fh->isValid());
}
}
} // namespace scripting
-9
View File
@@ -24,15 +24,6 @@ bool help_section_h::isValid() const
//**********HANDLE: help section
ADE_OBJ(l_Help_Section, help_section_h, "help_section", "Help Section handle");
ADE_FUNC(isValid, l_Help_Section, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
help_section_h current;
if (!ade_get_args(L, "o", l_Help_Section.Get(&current)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", current.isValid());
}
ADE_VIRTVAR(Title, l_Help_Section, nullptr, "The title of the help section", "string", "The title")
{
help_section_h current;
+1 -10
View File
@@ -9,6 +9,7 @@ namespace scripting::api
{
//**********HANDLE: mission goal
ADE_OBJ(l_Goal, int, "mission_goal", "Mission goal handle");
ADE_OBJ_VALIDATOR(l_Goal, idx, Mission_goals.in_bounds(idx));
ADE_VIRTVAR(Name, l_Goal, nullptr, "The name of the goal", "string", "The goal name")
{
@@ -129,14 +130,4 @@ ADE_VIRTVAR(isGoalValid, l_Goal, nullptr, "The goal validity", "boolean", "true
return ade_set_args(L, "b", !(Mission_goals[current].type & INVALID_GOAL));
}
ADE_FUNC(isValid, l_Goal, nullptr, "Detect if the handle is valid", "boolean", "true if valid, false otherwise")
{
int current = -1;
if (!ade_get_args(L, "o", l_Goal.Get(&current)))
return ADE_RETURN_FALSE;
return ade_set_args(L, "b", (current >= 0) && (current < (int)Mission_goals.size()));
}
}
-32
View File
@@ -118,20 +118,6 @@ ADE_VIRTVAR(Color, l_HUD_Color_Preset, nullptr, "The name of this preset", "colo
return ade_set_args(L, "o", l_Color.Set(c));
}
ADE_FUNC(isValid,
l_HUD_Color_Preset,
nullptr,
"Detects whether handle is valid",
"boolean",
"true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
hud_color_preset_h current;
if (!ade_get_args(L, "o", l_HUD_Color_Preset.Get(&current)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", current.isValid());
}
//**********HANDLE: hud preset
ADE_OBJ(l_HUD_Preset, hud_preset_h, "hud_preset", "Hud preset handle");
@@ -169,15 +155,6 @@ ADE_FUNC(deletePreset, l_HUD_Preset, nullptr, "Deletes the preset file", nullptr
return ADE_RETURN_NIL;
}
ADE_FUNC(isValid, l_HUD_Preset, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
hud_preset_h current;
if (!ade_get_args(L, "o", l_HUD_Preset.Get(&current)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", current.isValid());
}
//**********HANDLE: gauge config
ADE_OBJ(l_Gauge_Config, gauge_config_h, "gauge_config", "Gauge config handle");
@@ -407,14 +384,5 @@ ADE_FUNC(setSelected, l_Gauge_Config, "boolean", "Sets if the gauge is the curre
return ADE_RETURN_NIL;
}
ADE_FUNC(isValid, l_Gauge_Config, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
gauge_config_h current;
if (!ade_get_args(L, "o", l_Gauge_Config.Get(&current)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", current.isValid());
}
} // namespace api
} // namespace scripting
+1
View File
@@ -11,6 +11,7 @@ namespace scripting {
namespace api {
ADE_OBJ(l_HudGauge, HudGauge*, "HudGauge", "HUD Gauge handle");
ADE_OBJ_VALIDATOR(l_HudGauge, gauge, gauge != nullptr);
ADE_FUNC(isCustom, l_HudGauge, nullptr, "Custom HUD Gauge status", "boolean", "Returns true if this is a custom HUD gauge, or false if it is a non-custom (default) HUD gauge")
{
+1 -12
View File
@@ -10,6 +10,7 @@ namespace api {
//**********HANDLE: Intelentry
ADE_OBJ(l_Intelentry, int, "intel_entry", "Intel entry handle");
ADE_OBJ_VALIDATOR_RANGE(l_Intelentry, intel_info_size());
ADE_FUNC(__tostring, l_Intelentry, nullptr, "Intel entry name", "string", "Intel entry name, or an empty string if handle is invalid")
{
@@ -174,18 +175,6 @@ ADE_FUNC(hasCustomData,
return ade_set_args(L, "b", result);
}
ADE_FUNC(isValid, l_Intelentry, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
int idx;
if(!ade_get_args(L, "o", l_Intelentry.Get(&idx)))
return ADE_RETURN_NIL;
if(idx < 0 || idx >= intel_info_size())
return ADE_RETURN_FALSE;
return ADE_RETURN_TRUE;
}
ADE_FUNC(getIntelEntryIndex, l_Intelentry, nullptr, "Gets the index value of the intel entry", "number", "index value of the intel entry")
{
int idx;
-13
View File
@@ -147,18 +147,5 @@ ADE_FUNC(getCollisionNormal, l_ColInfo, "[boolean local]", "The collision normal
}
}
ADE_FUNC(isValid, l_ColInfo, NULL, "Detects if this handle is valid", "boolean", "true if valid false otherwise")
{
mc_info_h* info;
if(!ade_get_args(L, "o", l_ColInfo.GetPtr(&info)))
return ADE_RETURN_FALSE;
if (info->isValid())
return ADE_RETURN_TRUE;
else
return ADE_RETURN_FALSE;
}
}
}
-9
View File
@@ -29,15 +29,6 @@ bool medal_h::isRank() const
//**********HANDLE: medal
ADE_OBJ(l_Medal, medal_h, "medal", "Medal handle");
ADE_FUNC(isValid, l_Medal, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
medal_h current;
if (!ade_get_args(L, "o", l_Medal.Get(&current)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", current.isValid());
}
ADE_VIRTVAR(Name, l_Medal, nullptr, "The name of the medal", "string", "The name")
{
medal_h current;
+2 -19
View File
@@ -15,6 +15,7 @@ namespace api {
//**********HANDLE: Persona
ADE_OBJ(l_Persona, int, "persona", "Persona handle");
ADE_OBJ_VALIDATOR(l_Persona, idx, Personas.in_bounds(idx));
ADE_VIRTVAR(Name, l_Persona, "string", "The name of the persona", "string", "The name or empty string on error")
{
@@ -83,18 +84,9 @@ ADE_FUNC(hasCustomData, l_Persona, nullptr, "Detects whether the persona has any
return ade_set_args(L, "b", result);
}
ADE_FUNC(isValid, l_Persona, nullptr, "Detect if the handle is valid", "boolean", "true if valid, false otherwise")
{
int idx = -1;
if (!ade_get_args(L, "o", l_Persona.Get(&idx)))
return ADE_RETURN_FALSE;
return ade_set_args(L, "b", SCP_vector_inbounds(Personas, idx));
}
//**********HANDLE: Message
ADE_OBJ(l_Message, int, "message", "Handle to a mission message");
ADE_OBJ_VALIDATOR(l_Message, idx, Messages.in_bounds(idx));
ADE_VIRTVAR(Name, l_Message, "string", "The name of the message as specified in the mission file", "string", "The name or an empty string if handle is invalid")
{
@@ -216,15 +208,6 @@ ADE_FUNC(getMessage, l_Message, "[boolean replaceStuff = true]", "Gets the text
}
}
ADE_FUNC(isValid, l_Message, nullptr, "Checks if the message handle is valid", "boolean", "true if valid, false otherwise")
{
int idx = -1;
if (!ade_get_args(L, "o", l_Message.Get(&idx)))
return ADE_RETURN_FALSE;
return ade_set_args(L, "b", SCP_vector_inbounds(Messages, idx));
}
}
}
@@ -31,15 +31,6 @@ bool hotkey_h::isValid() const
//**********HANDLE: help section
ADE_OBJ(l_Hotkey, hotkey_h, "hotkey_ship", "Hotkey handle");
ADE_FUNC(isValid, l_Hotkey, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
hotkey_h current;
if (!ade_get_args(L, "o", l_Hotkey.Get(&current)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", current.isValid());
}
ADE_VIRTVAR(Text, l_Hotkey, nullptr, "The text of this hotkey line", "string", "The text")
{
hotkey_h current;
-18
View File
@@ -46,15 +46,6 @@ bool message_entry_h::isValid() const
//**********HANDLE: log entry
ADE_OBJ(l_Log_Entry, log_entry_h, "log_entry", "Log Entry handle");
ADE_FUNC(isValid, l_Log_Entry, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
log_entry_h current;
if (!ade_get_args(L, "o", l_Log_Entry.Get(&current)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", current.isValid());
}
ADE_VIRTVAR(Timestamp, l_Log_Entry, nullptr, "The timestamp of the log entry", "string", "The timestamp")
{
log_entry_h current;
@@ -215,15 +206,6 @@ ADE_VIRTVAR(SegmentColors,
//**********HANDLE: message entry
ADE_OBJ(l_Message_Entry, message_entry_h, "message_entry", "Message Entry handle");
ADE_FUNC(isValid, l_Message_Entry, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
message_entry_h current;
if (!ade_get_args(L, "o", l_Message_Entry.Get(&current)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", current.isValid());
}
ADE_VIRTVAR(Timestamp, l_Message_Entry, nullptr, "The timestamp of the message entry", "string", "The timestamp")
{
message_entry_h current;
-111
View File
@@ -327,15 +327,6 @@ ADE_FUNC(getDetailRoot, l_Model, "[number detailLevel]", "Returns the root submo
return ade_set_args(L, "o", l_Submodel.Set(submodel_h(pm, pm->detail[detail])));
}
ADE_FUNC(isValid, l_Model, nullptr, "True if valid, false or nil if not", "boolean", "Detects whether handle is valid")
{
model_h *mdl;
if (!ade_get_args(L, "o", l_Model.GetPtr(&mdl)))
return ADE_RETURN_FALSE;
return ade_set_args(L, "b", mdl->isValid());
}
ADE_VIRTVAR(Name, l_Submodel, nullptr, "Gets the submodel's name", "string", "The name or an empty string if invalid")
{
submodel_h *smh = nullptr;
@@ -508,15 +499,6 @@ ADE_FUNC(getParent, l_Submodel, nullptr, "Gets the parent submodel of this submo
return ade_set_args(L, "o", l_Submodel.Set(submodel_h(smh->GetModel(), sm->parent)));
}
ADE_FUNC(isValid, l_Submodel, nullptr, "True if valid, false or nil if not", "boolean", "Detects whether handle is valid")
{
submodel_h *smh;
if (!ade_get_args(L, "o", l_Submodel.GetPtr(&smh)))
return ADE_RETURN_FALSE;
return ade_set_args(L, "b", smh->isValid());
}
ADE_VIRTVAR(NoCollide, l_Submodel, nullptr, "Whether the submodel and its children ignore collisions", "boolean", "The flag, or error-false if invalid")
{
submodel_h* smh = nullptr;
@@ -606,15 +588,6 @@ ADE_INDEXER(l_ModelSubmodels, "submodel", "number|string IndexOrName", "submodel
return ade_set_args(L, "o", l_Submodel.Set(submodel_h(pm, index)));
}
ADE_FUNC(isValid, l_ModelSubmodels, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if invalid, nil if a syntax/type error occurs")
{
model_h *msh;
if (!ade_get_args(L, "o", l_ModelSubmodels.GetPtr(&msh)))
return ADE_RETURN_FALSE;
return ade_set_args(L, "b", msh->isValid());
}
//**********HANDLE: modeltextures
ADE_OBJ(l_ModelTextures, model_h, "textures", "Array of textures");
@@ -682,15 +655,6 @@ ADE_INDEXER(l_ModelTextures, "texture", "number Index/string TextureName", "text
return ade_set_args(L, "o", l_Texture.Set(texture_h(tinfo->GetTexture())));
}
ADE_FUNC(isValid, l_ModelTextures, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
model_h *mth;
if(!ade_get_args(L, "o", l_ModelTextures.GetPtr(&mth)))
return ADE_RETURN_FALSE;
return ade_set_args(L, "b", mth->isValid());
}
//**********HANDLE: eyepoints
ADE_OBJ(l_ModelEyepoints, model_h, "eyepoints", "Array of model eye points");
@@ -730,15 +694,6 @@ ADE_INDEXER(l_ModelEyepoints, "eyepoint", "Gets an eyepoint handle", "eyepoint",
return ade_set_args(L, "o", l_Eyepoint.Set(eye_h(pm->id, index)));
}
ADE_FUNC(isValid, l_ModelEyepoints, NULL, "Detects whether handle is valid or not", "boolean", "true if valid false otherwise")
{
model_h *eph;
if(!ade_get_args(L, "o", l_ModelEyepoints.GetPtr(&eph)))
return ADE_RETURN_FALSE;
return ade_set_args(L, "b", eph->isValid());
}
//**********HANDLE: thrusters
ADE_OBJ(l_ModelThrusters, model_h, "thrusters", "The thrusters of a model");
@@ -777,15 +732,6 @@ ADE_INDEXER(l_ModelThrusters, "number Index", "Array of all thrusterbanks on thi
return ade_set_args(L, "o", l_Thrusterbank.Set(thrusterbank_h(pm->id, idx)));
}
ADE_FUNC(isValid, l_ModelThrusters, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
model_h *trh;
if(!ade_get_args(L, "o", l_ModelThrusters.GetPtr(&trh)))
return ADE_RETURN_FALSE;
return ade_set_args(L, "b", trh->isValid());
}
//**********HANDLE: thrusterbank
ADE_OBJ(l_Thrusterbank, thrusterbank_h, "thrusterbank", "A model thrusterbank");
@@ -849,18 +795,6 @@ ADE_INDEXER(l_Thrusterbank, "number Index", "Array of glowpoint", "glowpoint", "
return ade_set_args(L, "o", l_Glowpoint.Set(glowpoint_h(tbh->modelh.GetID(), -1, tbh->thrusterbank_index, idx)));
}
ADE_FUNC(isValid, l_Thrusterbank, nullptr, "Detects if this handle is valid", "boolean", "true if this handle is valid, false otherwise")
{
thrusterbank_h* trh;
if(!ade_get_args(L, "o", l_Thrusterbank.GetPtr(&trh)))
return ADE_RETURN_FALSE;
if (!trh->isValid())
return ADE_RETURN_FALSE;
return ade_set_args(L, "b", trh->isValid());
}
//**********HANDLE: glow point banks
ADE_OBJ(l_ModelGlowpointbanks, model_h, "glowpointbanks", "Array of model glow point banks");
@@ -899,15 +833,6 @@ ADE_INDEXER(l_ModelGlowpointbanks, "glowpointbank", "Gets a glow point bank hand
return ade_set_args(L, "o", l_Glowpointbank.Set(glowpointbank_h(pm->id, index)));
}
ADE_FUNC(isValid, l_ModelGlowpointbanks, nullptr, "Detects whether handle is valid or not", "boolean", "true if valid false otherwise")
{
model_h *modelh;
if(!ade_get_args(L, "o", l_ModelGlowpointbanks.GetPtr(&modelh)))
return ADE_RETURN_FALSE;
return ade_set_args(L, "b", modelh->isValid());
}
//**********HANDLE: glow point bank
ADE_OBJ(l_Glowpointbank, glowpointbank_h, "glowpointbank", "A model glow point bank");
@@ -974,15 +899,6 @@ ADE_INDEXER(l_Glowpointbank, "glowpoint", "Gets a glow point handle", "glowpoint
// NOTE: Any fields or functions of glowpointbank will need to take glowpoint_bank_overrides into account
// **********
ADE_FUNC(isValid, l_Glowpointbank, nullptr, "Detects whether handle is valid or not", "boolean", "true if valid false otherwise")
{
glowpointbank_h* gpbh = nullptr;
if (!ade_get_args(L, "o", l_Glowpointbank.GetPtr(&gpbh)))
return ADE_RETURN_FALSE;
return ade_set_args(L, "b", gpbh->isValid());
}
//**********HANDLE: glowpoint
ADE_OBJ(l_Glowpoint, glowpoint_h, "glowpoint", "A model glowpoint");
@@ -1083,16 +999,6 @@ ADE_VIRTVAR(Radius, l_Glowpoint, nullptr, "The radius of the glowpoint", "number
return ade_set_args(L, "f", point->radius);
}
ADE_FUNC(isValid, l_Glowpoint, NULL, "Returns whether this handle is valid or not", "boolean", "True if handle is valid, false otherwise")
{
glowpoint_h glh;
if(!ade_get_args(L, "o", l_Glowpoint.Get(&glh)))
return ADE_RETURN_FALSE;
return ade_set_args(L, "b", glh.isValid());
}
//**********HANDLE: dockingbays
ADE_OBJ(l_ModelDockingbays, model_h, "dockingbays", "The docking bays of a model");
@@ -1312,22 +1218,5 @@ ADE_FUNC(computeDocker, l_Dockingbay, "dockingbay",
return ade_set_args(L, "oo", l_Vector.Set(final_pos),l_Matrix.Set(matrix_h(&final_orient)));
}
ADE_FUNC(isValid, l_Dockingbay, nullptr, "Detects whether is valid or not", "boolean", "true if valid, false otherwise")
{
dockingbay_h* dbh = nullptr;
if (!ade_get_args(L, "o", l_Dockingbay.GetPtr(&dbh)))
{
return ADE_RETURN_FALSE;
}
if (dbh == nullptr)
{
return ADE_RETURN_FALSE;
}
return ade_set_args(L, "b", dbh->isValid());
}
}
}
-23
View File
@@ -25,16 +25,6 @@ struct model_path_point_h {
ADE_OBJ(l_ModelPathPoint, model_path_point_h, "modelpathpoint", "Point in a model path");
ADE_FUNC(isValid, l_ModelPathPoint, nullptr, "Determines if the handle is valid", "boolean",
"True if valid, false otherwise")
{
model_path_point_h* p = nullptr;
if (!ade_get_args(L, "o", l_ModelPathPoint.GetPtr(&p)))
return ADE_RETURN_FALSE;
return ade_set_args(L, "b", p->isValid());
}
ADE_VIRTVAR(Position, l_ModelPathPoint, "vector", "The current, global position of this path point.", "vector",
"The current position of the point.")
{
@@ -102,19 +92,6 @@ ADE_FUNC(__len, l_ModelPath, nullptr, "Gets the number of points in this path",
return ade_set_args(L, "i", static_cast<int>(p->verts.size()));
}
ADE_FUNC(isValid, l_ModelPath, nullptr, "Determines if the handle is valid", "boolean",
"True if valid, false otherwise")
{
model_path_h* p = nullptr;
if (!ade_get_args(L, "o", l_ModelPath.GetPtr(&p)))
return ADE_RETURN_FALSE;
if (p == nullptr)
return ADE_RETURN_FALSE;
return ade_set_args(L, "b", p->isValid());
}
ADE_INDEXER(l_ModelPath, "number", "Returns the point in the path with the specified index", "modelpathpoint",
"The point or invalid handle if index is invalid")
{
-36
View File
@@ -97,15 +97,6 @@ ADE_INDEXER(l_ModelInstanceTextures, "number/string IndexOrTextureFilename", "Ar
return ade_set_args(L, "o", l_Texture.Set(texture_h(pm->maps[final_index / TM_NUM_TYPES].textures[final_index % TM_NUM_TYPES].GetTexture())));
}
ADE_FUNC(isValid, l_ModelInstanceTextures, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
modelinstance_h *mih;
if(!ade_get_args(L, "o", l_ModelInstanceTextures.GetPtr(&mih)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", mih->isValid());
}
ADE_OBJ(l_ModelInstance, modelinstance_h, "model_instance", "Model instance handle");
@@ -278,15 +269,6 @@ ADE_VIRTVAR(SubmodelInstances, l_ModelInstance, nullptr, "Submodel instances", "
return ade_set_args(L, "o", l_ModelSubmodelInstances.Set(modelsubmodelinstances_h(pmi)));
}
ADE_FUNC(isValid, l_ModelInstance, nullptr, "True if valid, false or nil if not", "boolean", "Detects whether handle is valid")
{
modelinstance_h *mih;
if (!ade_get_args(L, "o", l_ModelInstance.GetPtr(&mih)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", mih->isValid());
}
ADE_FUNC(getModelInstance, l_SubmodelInstance, nullptr, "Gets the model instance of this submodel", "model_instance", "A model instancve")
{
submodelinstance_h* smih;
@@ -473,15 +455,6 @@ ADE_FUNC(findLocalPointAndOrientation, l_SubmodelInstance, "vector, orientation,
return ade_set_args(L, "oo", l_Vector.Set(local_pnt), l_Matrix.Set(matrix_h(&local_orient)));
}
ADE_FUNC(isValid, l_SubmodelInstance, nullptr, "True if valid, false or nil if not", "boolean", "Detects whether handle is valid")
{
submodelinstance_h *smih;
if (!ade_get_args(L, "o", l_SubmodelInstance.GetPtr(&smih)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", smih->isValid());
}
ADE_OBJ(l_ModelSubmodelInstances, modelsubmodelinstances_h, "submodel_instances", "Array of submodel instances");
@@ -556,14 +529,5 @@ ADE_INDEXER(l_ModelSubmodelInstances, "submodel_instance", "number|string IndexO
return ade_set_args(L, "o", l_SubmodelInstance.Set(submodelinstance_h(pmi, index)));
}
ADE_FUNC(isValid, l_ModelSubmodelInstances, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if invalid, nil if a syntax/type error occurs")
{
modelsubmodelinstances_h *msih;
if (!ade_get_args(L, "o", l_ModelSubmodelInstances.GetPtr(&msih)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", msih->isValid());
}
}
}
-18
View File
@@ -171,23 +171,5 @@ ADE_FUNC(stop, l_MoviePlayer, nullptr,
return ADE_RETURN_NIL;
}
ADE_FUNC(isValid, l_MoviePlayer, nullptr, "Determines if this handle is valid", "boolean",
"true if valid, false otherwise")
{
movie_player_h* ph = nullptr;
if (!ade_get_args(L, "o", l_MoviePlayer.GetPtr(&ph)))
return ADE_RETURN_FALSE;
if (ph == nullptr) {
return ADE_RETURN_FALSE;
}
if (!ph->isValid()) {
return ADE_RETURN_FALSE;
}
return ADE_RETURN_TRUE;
}
} // namespace api
} // namespace scripting
-112
View File
@@ -196,20 +196,6 @@ bool join_ship_choices_h::isValid() const
//**********HANDLE: channel section
ADE_OBJ(l_Channel, channel_h, "pxo_channel", "Channel Section handle");
ADE_FUNC(isValid,
l_Channel,
nullptr,
"Detects whether handle is valid",
"boolean",
"true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
channel_h current;
if (!ade_get_args(L, "o", l_Channel.Get(&current)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", current.isValid());
}
ADE_VIRTVAR(Name, l_Channel, nullptr, "The name of the channel", "string", "The name")
{
channel_h current;
@@ -301,20 +287,6 @@ ADE_FUNC(joinChannel, l_Channel, nullptr, "Joins the specified channel", nullptr
//**********HANDLE: net player section
ADE_OBJ(l_NetPlayer, net_player_h, "net_player", "Net Player handle");
ADE_FUNC(isValid,
l_NetPlayer,
nullptr,
"Detects whether handle is valid",
"boolean",
"true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
net_player_h current;
if (!ade_get_args(L, "o", l_NetPlayer.Get(&current)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", current.isValid());
}
ADE_VIRTVAR(Name, l_NetPlayer, nullptr, "The player's callsign", "string", "The player callsign")
{
net_player_h current;
@@ -507,20 +479,6 @@ ADE_FUNC(kickPlayer, l_NetPlayer, nullptr, "Kicks the player from the game", nul
//**********HANDLE: mission section
ADE_OBJ(l_NetMission, net_mission_h, "net_mission", "Net Mission handle");
ADE_FUNC(isValid,
l_NetMission,
nullptr,
"Detects whether handle is valid",
"boolean",
"true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
net_mission_h current;
if (!ade_get_args(L, "o", l_NetMission.Get(&current)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", current.isValid());
}
ADE_VIRTVAR(Name, l_NetMission, nullptr, "The name of the mission", "string", "The name")
{
net_mission_h current;
@@ -683,20 +641,6 @@ ADE_VIRTVAR(Builtin,
//**********HANDLE: campaign section
ADE_OBJ(l_NetCampaign, net_campaign_h, "net_campaign", "Net Campaign handle");
ADE_FUNC(isValid,
l_NetCampaign,
nullptr,
"Detects whether handle is valid",
"boolean",
"true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
net_campaign_h current;
if (!ade_get_args(L, "o", l_NetCampaign.Get(&current)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", current.isValid());
}
ADE_VIRTVAR(Name, l_NetCampaign, nullptr, "The name of the mission", "string", "The name")
{
net_campaign_h current;
@@ -859,20 +803,6 @@ ADE_VIRTVAR(Builtin,
//**********HANDLE: netgame section
ADE_OBJ(l_NetGame, net_game_h, "netgame", "Netgame handle");
ADE_FUNC(isValid,
l_NetGame,
nullptr,
"Detects whether handle is valid",
"boolean",
"true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
net_game_h current;
if (!ade_get_args(L, "o", l_NetGame.Get(&current)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", current.isValid());
}
ADE_VIRTVAR(Name,
l_NetGame,
nullptr,
@@ -1294,20 +1224,6 @@ ADE_FUNC(setMission,
//**********HANDLE: channel section
ADE_OBJ(l_Active_Game, active_game_h, "active_game", "Active Game handle");
ADE_FUNC(isValid,
l_Active_Game,
nullptr,
"Detects whether handle is valid",
"boolean",
"true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
active_game_h current;
if (!ade_get_args(L, "o", l_Active_Game.Get(&current)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", current.isValid());
}
ADE_VIRTVAR(Status, l_Active_Game, nullptr, "The status of the game", "string", "The status")
{
active_game_h current;
@@ -1508,20 +1424,6 @@ ADE_FUNC(setSelected, l_Active_Game, nullptr, "Sets the specified game as the se
//**********HANDLE: channel section
ADE_OBJ(l_Dogfight_Scores, dogfight_scores_h, "dogfight_scores", "Dogfight scores handle");
ADE_FUNC(isValid,
l_Dogfight_Scores,
nullptr,
"Detects whether handle is valid",
"boolean",
"true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
dogfight_scores_h current;
if (!ade_get_args(L, "o", l_Dogfight_Scores.Get(&current)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", current.isValid());
}
ADE_VIRTVAR(Callsign,
l_Dogfight_Scores,
nullptr,
@@ -1558,20 +1460,6 @@ ADE_FUNC(getKillsOnPlayer,
//**********HANDLE: join choice section
ADE_OBJ(l_Join_Ship_Choice, join_ship_choices_h, "net_join_choice", "Join Choice handle");
ADE_FUNC(isValid,
l_Join_Ship_Choice,
nullptr,
"Detects whether handle is valid",
"boolean",
"true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
join_ship_choices_h current;
if (!ade_get_args(L, "o", l_Join_Ship_Choice.Get(&current)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", current.isValid());
}
ADE_VIRTVAR(Name, l_Join_Ship_Choice,
nullptr,
"Gets the name of the ship",
-9
View File
@@ -353,15 +353,6 @@ ADE_FUNC(getSignature, l_Object, NULL, "Gets the object's unique signature", "nu
return ade_set_args(L, "i", oh->sig);
}
ADE_FUNC(isValid, l_Object, NULL, "Detects whether handle is valid", "boolean", "true if handle is valid, false if handle is invalid, nil if a syntax/type error occurs")
{
object_h *oh;
if(!ade_get_args(L, "o", l_Object.GetPtr(&oh)))
return ADE_RETURN_FALSE;
return ade_set_args(L, "b", oh->isValid());
}
ADE_FUNC(isExpiring, l_Object, nullptr, "Checks whether the object has the should-be-dead flag set, which will cause it to be deleted within one frame", "boolean", "true or false according to the flag, or nil if a syntax/type error occurs")
{
object_h* oh;
-18
View File
@@ -559,15 +559,6 @@ ADE_VIRTVAR(PurgeWhenNewGoalAdded, l_Order, "boolean", "Whether this goal should
return goal_flag_helper(L, AI::Goal_Flags::Purge_when_new_goal_added);
}
ADE_FUNC(isValid, l_Order, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
order_h *ohp = NULL;
if(!ade_get_args(L, "o", l_Order.GetPtr(&ohp)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", ohp->isValid());
}
//**********HANDLE: shiporders
ADE_OBJ(l_ShipOrders, object_h, "shiporders", "Ship orders");
@@ -604,15 +595,6 @@ ADE_INDEXER(l_ShipOrders, "number Index", "Array of ship orders", "order", "Orde
return ade_set_args(L, "o", l_Order.Set(order_h()));
}
ADE_FUNC(isValid, l_ShipOrders, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
object_h *oh;
if(!ade_get_args(L, "o", l_ShipOrders.GetPtr(&oh)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", oh->isValid());
}
}
}
-9
View File
@@ -90,15 +90,6 @@ ADE_VIRTVAR(
return ade_set_args(L, "s", poh->getObject()->get_display_name());
}
ADE_FUNC(isValid, l_ParseObject, nullptr, "Detect whether the parsed ship handle is valid", "boolean", "true if valid false otherwise")
{
parse_object_h* poh = nullptr;
if (!ade_get_args(L, "o", l_ParseObject.GetPtr(&poh)))
return ADE_RETURN_FALSE;
return ade_set_args(L, "b", poh->isValid());
}
ADE_FUNC(getBreedName, l_ParseObject, nullptr, "Gets the FreeSpace type name", "string", "'Parse Object', or empty string if handle is invalid")
{
parse_object_h* poh = nullptr;
-12
View File
@@ -214,18 +214,6 @@ ADE_VIRTVAR(AttachedObject, l_Particle, "object", "The object this particle is a
return ade_set_object_with_breed(L, -1);
}
ADE_FUNC(isValid, l_Particle, NULL, "Detects whether this handle is valid", "boolean", "true if valid false if not")
{
particle_h *ph = NULL;
if (!ade_get_args(L, "o", l_Particle.GetPtr(&ph)))
return ADE_RETURN_FALSE;
if (ph == NULL)
return ADE_RETURN_FALSE;
return ade_set_args(L, "b", ph->isValid());
}
ADE_FUNC_DEPRECATED(setColor, l_Particle, "number r, number g, number b", "Sets the color for a particle. If the particle does not support color, the function does nothing. (Currently only debug particles support color.)", nullptr, nullptr, gameversion::version(25,0,0), "Debug particles are deprecated as of FSO 25.0.0! Use particles with a solid-color bitmap instead!")
{
LuaError(L, "Debug particles are deprecated as of FSO 25.0.0!");
-9
View File
@@ -413,15 +413,6 @@ ADE_VIRTVAR(GravityConst, l_Physics, "number", "Multiplier for the effect of gra
return ade_set_args(L, "f", pih->pi->gravity_const);
}
ADE_FUNC(isValid, l_Physics, NULL, "True if valid, false or nil if not", "boolean", "Detects whether handle is valid")
{
physics_info_h *pih;
if(!ade_get_args(L, "o", l_Physics.GetPtr(&pih)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", pih->isValid());
}
ADE_FUNC(getSpeed, l_Physics, NULL, "Gets total speed as of last frame", "number", "Total speed, or 0 if handle is invalid")
{
physics_info_h *pih;
-12
View File
@@ -205,18 +205,6 @@ ADE_VIRTVAR(ShowSkipPopup,
return ade_set_args(L, "b", plr->get()->show_skip_popup != 0);
}
ADE_FUNC(isValid, l_Player, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
player_h* plr;
if (!ade_get_args(L, "o", l_Player.GetPtr(&plr)))
return ADE_RETURN_NIL;
if (!plr->isValid())
return ADE_RETURN_FALSE;
return ADE_RETURN_TRUE;
}
ADE_FUNC(getName, l_Player, NULL, "Gets current player name", "string", "Player name, or empty string if handle is invalid")
{
player_h* plr;
+1 -17
View File
@@ -7,6 +7,7 @@ namespace scripting::api {
//**********HANDLE: Propclass
ADE_OBJ(l_Propclass, int, "propclass", "Prop class handle");
ADE_OBJ_VALIDATOR_RANGE(l_Propclass, prop_info_size());
ADE_FUNC(__tostring,
l_Propclass,
@@ -197,23 +198,6 @@ ADE_FUNC(hasCustomStrings,
return ade_set_args(L, "b", result);
}
ADE_FUNC(isValid,
l_Propclass,
nullptr,
"Detects whether handle is valid",
"boolean",
"true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
int idx;
if (!ade_get_args(L, "o", l_Propclass.Get(&idx)))
return ADE_RETURN_NIL;
if (idx < 0 || idx >= prop_info_size())
return ADE_RETURN_FALSE;
return ADE_RETURN_TRUE;
}
ADE_FUNC(renderTechModel,
l_Propclass,
"number X1, number Y1, number X2, number Y2, [number RotationPercent =0, number PitchPercent =0, number "
-9
View File
@@ -24,15 +24,6 @@ bool rank_h::isValid() const
//**********HANDLE: rank
ADE_OBJ(l_Rank, rank_h, "rank", "Rank handle");
ADE_FUNC(isValid, l_Rank, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
rank_h current;
if (!ade_get_args(L, "o", l_Rank.Get(&current)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", current.isValid());
}
ADE_VIRTVAR(Name, l_Rank, nullptr, "The name of the rank", "string", "The name")
{
rank_h current;
-12
View File
@@ -156,18 +156,6 @@ ADE_FUNC(__tostring, l_SEXPVariable, NULL, "Returns SEXP name", "string", "SEXP
return ade_set_args(L, "s", Sexp_variables[svh->idx].variable_name);
}
ADE_FUNC(isValid, l_SEXPVariable, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
sexpvar_h *svh = NULL;
if(!ade_get_args(L, "o", l_SEXPVariable.GetPtr(&svh)))
return ADE_RETURN_NIL;
if(!svh->isValid())
return ADE_RETURN_FALSE;
return ADE_RETURN_TRUE;
}
ADE_FUNC(delete, l_SEXPVariable, NULL, "Deletes a SEXP Variable", "boolean", "True if successful, false if the handle is invalid")
{
sexpvar_h *svh = NULL;
-9
View File
@@ -134,14 +134,5 @@ ADE_VIRTVAR(CombinedMax, l_Shields, "number", "Maximum shield hitpoints (for all
return ade_set_args(L, "f", shield_get_max_strength(objh->objp()));
}
ADE_FUNC(isValid, l_Shields, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
object_h *oh;
if(!ade_get_args(L, "o", l_Shields.GetPtr(&oh)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", oh->isValid());
}
}
}
-18
View File
@@ -139,15 +139,6 @@ ADE_VIRTVAR(DualFire, l_WeaponBankType, "boolean", "Whether bank is in dual fire
return ade_set_error(L, "b", false);
}
ADE_FUNC(isValid, l_WeaponBankType, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
ship_banktype_h *sb;
if(!ade_get_args(L, "o", l_WeaponBankType.GetPtr(&sb)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", sb->isValid());
}
ADE_FUNC(__len, l_WeaponBankType, NULL, "Number of weapons in the mounted bank", "number", "Number of bank weapons, or 0 if handle is invalid")
{
ship_banktype_h *sb=NULL;
@@ -476,15 +467,6 @@ ADE_VIRTVAR(BurstSeed, l_WeaponBank, "number", "A random seed associated to the
return ade_set_error(L, "i", -1);
}
ADE_FUNC(isValid, l_WeaponBank, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
ship_bank_h *bh;
if(!ade_get_args(L, "o", l_WeaponBank.GetPtr(&bh)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", bh->isValid());
}
}
}
@@ -13,6 +13,7 @@ namespace api {
//**********HANDLE: ShipRegistryEntry
ADE_OBJ(l_ShipRegistryEntry, int, "ship_registry_entry", "Ship entry handle");
ADE_OBJ_VALIDATOR(l_ShipRegistryEntry, idx, Ship_registry.in_bounds(idx));
ADE_VIRTVAR(Name, l_ShipRegistryEntry, nullptr, "Name of ship", "string", "Ship name, or empty string if handle is invalid")
{
@@ -29,18 +30,6 @@ ADE_VIRTVAR(Name, l_ShipRegistryEntry, nullptr, "Name of ship", "string", "Ship
return ade_set_args(L, "s", Ship_registry[idx].name);
}
ADE_FUNC(isValid, l_ShipRegistryEntry, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if invalid, nil if a syntax/type error occurs")
{
int idx;
if (!ade_get_args(L, "o", l_ShipRegistryEntry.Get(&idx)))
return ADE_RETURN_NIL;
if (idx < 0 || (size_t)idx >= Ship_registry.size())
return ADE_RETURN_FALSE;
return ADE_RETURN_TRUE;
}
ADE_VIRTVAR(Status, l_ShipRegistryEntry, nullptr, "Status of ship", "enumeration", "A SHIP_STATUS_* enumeration, or nil if handle is invalid")
{
int idx;
+3 -12
View File
@@ -28,6 +28,7 @@ namespace api {
//**********HANDLE: default primary
ADE_OBJ(l_Default_Primary, int, "default_primary", "weapon index");
ADE_OBJ_VALIDATOR_RANGE(l_Default_Primary, ship_info_size());
ADE_INDEXER(l_Default_Primary,
"number idx",
@@ -70,6 +71,7 @@ ADE_FUNC(__len,
//**********HANDLE: default secondary
ADE_OBJ(l_Default_Secondary, int, "default_secondary", "weapon index");
ADE_OBJ_VALIDATOR_RANGE(l_Default_Secondary, ship_info_size());
ADE_INDEXER(l_Default_Secondary,
"number idx",
@@ -112,6 +114,7 @@ ADE_FUNC(__len,
//**********HANDLE: Shipclass
ADE_OBJ(l_Shipclass, int, "shipclass", "Ship class handle");
ADE_OBJ_VALIDATOR_RANGE(l_Shipclass, ship_info_size());
ADE_FUNC(__tostring, l_Shipclass, NULL, "Ship class name", "string", "Ship class name, or an empty string if handle is invalid")
{
@@ -1117,18 +1120,6 @@ ADE_FUNC(hasCustomStrings,
return ade_set_args(L, "b", result);
}
ADE_FUNC(isValid, l_Shipclass, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
int idx;
if(!ade_get_args(L, "o", l_Shipclass.Get(&idx)))
return ADE_RETURN_NIL;
if(idx < 0 || idx >= ship_info_size())
return ADE_RETURN_FALSE;
return ADE_RETURN_TRUE;
}
ADE_FUNC(isInTechroom, l_Shipclass, NULL, "Gets whether or not the ship class is available in the techroom", "boolean", "Whether ship has been revealed in the techroom, false if handle is invalid")
{
int idx;
+1 -12
View File
@@ -11,6 +11,7 @@ namespace api {
//**********HANDLE: Shiptype
ADE_OBJ(l_Shiptype, int, "shiptype", "Ship type handle");
ADE_OBJ_VALIDATOR(l_Shiptype, idx, Ship_types.in_bounds(idx));
ADE_VIRTVAR(Name, l_Shiptype, "string", "Ship type name", "string", "Ship type name, or empty string if handle is invalid")
{
@@ -34,17 +35,5 @@ ADE_VIRTVAR(Name, l_Shiptype, "string", "Ship type name", "string", "Ship type n
return ade_set_args(L, "s", Ship_types[idx].name);
}
ADE_FUNC(isValid, l_Shiptype, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
int idx;
if(!ade_get_args(L, "o", l_Shiptype.Get(&idx)))
return ADE_RETURN_NIL;
if(idx < 0 || idx >= (int)Ship_types.size())
return ADE_RETURN_FALSE;
return ADE_RETURN_TRUE;
}
}
}
@@ -379,6 +379,7 @@ ADE_FUNC(__len, l_Loadout_Weapon, nullptr, "The number of weapon banks in the sl
//**********HANDLE: loadout ship
ADE_OBJ_NO_MULTI(l_Loadout_Ship, int, "loadout_ship", "Loadout handle");
ADE_OBJ_VALIDATOR_RANGE(l_Loadout_Ship, MAX_WSS_SLOTS);
ADE_VIRTVAR(ShipClassIndex,
l_Loadout_Ship,
+5 -23
View File
@@ -111,15 +111,6 @@ ADE_FUNC(get3DValues,
}
}
ADE_FUNC(isValid, l_SoundEntry, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
sound_entry_h *seh;
if(!ade_get_args(L, "o", l_SoundEntry.GetPtr(&seh)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", seh->isValid());
}
ADE_FUNC(tryLoad, l_SoundEntry, nullptr, "Detects whether handle references a sound that can be loaded", "boolean", "true if a load succeeded, false if not, nil if a syntax/type error occurs")
{
sound_entry_h *seh;
@@ -407,6 +398,11 @@ ADE_FUNC(updatePosition, l_Sound3D,
//**********HANDLE: Soundfile
soundfile_h::soundfile_h(sound_load_id id) : idx(id) {}
bool soundfile_h::isValid() const
{
return idx.isValid();
}
ADE_OBJ(l_Soundfile, soundfile_h, "soundfile", "Handle to a sound file");
ADE_VIRTVAR(Duration, l_Soundfile, "number", "The duration of the sound file, in seconds", "number", "The duration or -1 on error")
@@ -491,20 +487,6 @@ ADE_FUNC(unload, l_Soundfile, nullptr,
return ade_set_args(L, "b", result != 0);
}
ADE_FUNC(isValid, l_Soundfile, NULL, "Checks if the soundfile handle is valid", "boolean", "true if valid, false otherwise")
{
soundfile_h* handle = nullptr;
if (!ade_get_args(L, "o", l_Soundfile.GetPtr(&handle)))
return ADE_RETURN_FALSE;
if (handle == nullptr) {
return ADE_RETURN_FALSE;
}
return ade_set_args(L, "b", handle->idx.isValid());
}
}
}
+2
View File
@@ -53,6 +53,8 @@ struct soundfile_h {
sound_load_id idx;
explicit soundfile_h(sound_load_id id = sound_load_id::invalid());
bool isValid() const;
};
DECLARE_ADE_OBJ(l_Soundfile, soundfile_h);
+1 -12
View File
@@ -11,6 +11,7 @@ namespace api {
//**********HANDLE: Species
ADE_OBJ(l_Species, int, "species", "Species handle");
ADE_OBJ_VALIDATOR(l_Species, idx, Species_info.in_bounds(idx));
ADE_VIRTVAR(Name, l_Species, "string", "Species name", "string", "Species name, or empty string if handle is invalid")
{
@@ -34,18 +35,6 @@ ADE_VIRTVAR(Name, l_Species, "string", "Species name", "string", "Species name,
return ade_set_args(L, "s", Species_info[idx].species_name);
}
ADE_FUNC(isValid, l_Species, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
int idx;
if(!ade_get_args(L, "o", l_Species.Get(&idx)))
return ADE_RETURN_NIL;
if(idx < 0 || idx >= (int)Species_info.size())
return ADE_RETURN_FALSE;
return ADE_RETURN_TRUE;
}
}
}
@@ -209,15 +209,6 @@ ADE_FUNC(getWidth, l_streaminganim, nullptr, "Get the width of the animation in
return ade_set_args(L, "i", sah->ga.width);
}
ADE_FUNC(isValid, l_streaminganim, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
streaminganim_h* sah;
if(!ade_get_args(L, "o", l_streaminganim.GetPtr(&sah)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", sah->isValid());
}
ADE_FUNC(preload, l_streaminganim, NULL, "Load all apng animations into memory, enabling apng frame cache if not already enabled", "boolean", "true if preload was successful, nil if a syntax/type error occurs")
{
streaminganim_h* sah;
-9
View File
@@ -1099,15 +1099,6 @@ ADE_FUNC(isInViewFrom, l_Subsystem, "vector from",
return ade_set_args(L, "b", in_sight);
}
ADE_FUNC(isValid, l_Subsystem, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
ship_subsys_h *sso;
if(!ade_get_args(L, "o", l_Subsystem.GetPtr(&sso)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", sso->isValid());
}
}
}
@@ -11,6 +11,7 @@ namespace scripting::api {
//****HANDLE: support_rearm_pool_team
ADE_OBJ(l_SupportRearmPoolTeam, int, "support_rearm_pool_team", "Support rearm pool team handle");
ADE_OBJ_VALIDATOR(l_SupportRearmPoolTeam, idx, idx >= 0 && idx < Num_teams && idx < MAX_TVT_TEAMS);
ADE_INDEXER(l_SupportRearmPoolTeam,
"number/weaponclass IndexOrClass, number amount",
+1 -12
View File
@@ -11,6 +11,7 @@ namespace api {
//**********HANDLE: Team
ADE_OBJ(l_Team, int, "team", "Team handle");
ADE_OBJ_VALIDATOR(l_Team, idx, Iff_info.in_bounds(idx));
ADE_FUNC(__eq, l_Team, "team, team", "Checks whether two teams are the same team", "boolean", "true if equal, false otherwise")
{
@@ -64,18 +65,6 @@ ADE_FUNC(getColor,
}
}
ADE_FUNC(isValid, l_Team, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
int idx;
if(!ade_get_args(L, "o", l_Team.Get(&idx)))
return ADE_RETURN_NIL;
if(!SCP_vector_inbounds(Iff_info, idx))
return ADE_RETURN_FALSE;
return ADE_RETURN_TRUE;
}
ADE_FUNC(getBreedName, l_Team, nullptr, "Gets the FreeSpace type name", "string", "'Team', or empty string if handle is invalid")
{
int idx;
+1 -17
View File
@@ -9,6 +9,7 @@ namespace scripting::api {
//**********HANDLE: TeamColor
ADE_OBJ(l_TeamColor, int, "teamcolor", "Team color handle");
ADE_OBJ_VALIDATOR(l_TeamColor, idx, Team_Names.in_bounds(idx) && Team_Colors.find(Team_Names[idx]) != Team_Colors.end());
ADE_FUNC(__tostring, l_TeamColor, nullptr, "Team color name", "string", "Team color name, or an empty string if handle is invalid")
{
@@ -112,21 +113,4 @@ ADE_VIRTVAR(StripeColor, l_TeamColor, nullptr, "Team color stripe color", "color
return ade_set_args(L, "o", l_Color.Set(cur));
}
ADE_FUNC(isValid, l_TeamColor, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
int idx;
if (!ade_get_args(L, "o", l_TeamColor.Get(&idx)))
return ADE_RETURN_NIL;
if (!SCP_vector_inbounds(Team_Names, idx))
return ADE_RETURN_FALSE;
const auto& it = Team_Colors.find(Team_Names[idx]);
if (it == Team_Colors.end()) {
return ADE_RETURN_FALSE;
}
return ADE_RETURN_TRUE;
}
}
-10
View File
@@ -225,15 +225,5 @@ ADE_FUNC(hasCustomData, l_TechRoomCutscene, nullptr, "Detects whether the cutsce
return ade_set_args(L, "b", result);
}
ADE_FUNC(isValid, l_TechRoomCutscene, NULL, "Detects whether cutscene is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
cutscene_info_h current;
if (!ade_get_args(L, "o", l_TechRoomCutscene.Get(&current))) {
return ADE_RETURN_NIL;
}
return ade_set_args(L, "b", current.isValid());
}
} // namespace api
} // namespace scripting
-9
View File
@@ -101,15 +101,6 @@ ADE_INDEXER(l_Texture, "number",
return ade_set_args(L, "o", l_Texture.Set(texture_h(frame, true, first)));
}
ADE_FUNC(isValid, l_Texture, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
texture_h* th;
if (!ade_get_args(L, "o", l_Texture.GetPtr(&th)))
return ADE_RETURN_NIL;
return ade_set_args(L, "b", th->isValid());
}
ADE_FUNC(unload, l_Texture, NULL, "Unloads a texture from memory", NULL, NULL)
{
texture_h* th;
-15
View File
@@ -38,21 +38,6 @@ void volumetric_h::deserialize(lua_State* /*L*/, const scripting::ade_table_entr
new(data_ptr) volumetric_h(index);
}
ADE_FUNC(isValid,
l_Volumetric,
nullptr,
"Determines if this handle is valid",
"boolean",
"true if valid, false otherwise")
{
volumetric_h* vh = nullptr;
if (!ade_get_args(L, "o", l_Volumetric.GetPtr(&vh))) {
return ADE_RETURN_FALSE;
}
return ade_set_args(L, "b", vh != nullptr && vh->isValid());
}
ADE_VIRTVAR(POF,
l_Volumetric,
nullptr,
-9
View File
@@ -136,14 +136,5 @@ ADE_VIRTVAR(Name, l_WaypointList, "string", "Name of WaypointList", "string", "W
return ade_set_args( L, "s", wlh->getList()->get_name());
}
ADE_FUNC(isValid, l_WaypointList, NULL, "Return if this waypointlist handle is valid", "boolean", "true if valid false otherwise")
{
waypointlist_h* wlh = NULL;
if ( !ade_get_args(L, "o", l_WaypointList.GetPtr(&wlh)) ) {
return ADE_RETURN_FALSE;
}
return ade_set_args(L, "b", wlh != NULL && wlh->isValid());
}
}
}
+1 -12
View File
@@ -17,6 +17,7 @@ namespace api {
//**********HANDLE: Weaponclass
ADE_OBJ(l_Weaponclass, int, "weaponclass", "Weapon class handle");
ADE_OBJ_VALIDATOR_RANGE(l_Weaponclass, weapon_info_size());
ADE_FUNC(__tostring, l_Weaponclass, NULL, "Weapon class name", "string", "Weapon class name, or an empty string if handle is invalid")
{
@@ -1083,18 +1084,6 @@ ADE_VIRTVAR(BeamWarmdown, l_Weaponclass, "number", "The time in seconds that a b
return ade_set_args(L, "f", 0.0f);
}
ADE_FUNC(isValid, l_Weaponclass, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
int idx;
if(!ade_get_args(L, "o", l_Weaponclass.Get(&idx)))
return ADE_RETURN_NIL;
if(idx < 0 || idx >= weapon_info_size())
return ADE_RETURN_FALSE;
return ADE_RETURN_TRUE;
}
ADE_FUNC(renderTechModel,
l_Weaponclass,
"number X1, number Y1, number X2, number Y2, [number RotationPercent =0, number PitchPercent =0, number "
+1 -12
View File
@@ -15,6 +15,7 @@ namespace api {
//**********HANDLE: Wing
ADE_OBJ(l_Wing, int, "wing", "Wing handle");
ADE_OBJ_VALIDATOR_RANGE(l_Wing, Num_wings);
ADE_INDEXER(l_Wing, "number Index", "Array of ships in the wing", "ship", "Ship handle, or invalid ship handle if index is invalid or wing handle is invalid")
{
@@ -86,18 +87,6 @@ ADE_VIRTVAR(DisplayName, l_Wing, "string", "Wing display name", "string", "The d
return ade_set_args(L, "s", wingp->display_name.c_str());
}
ADE_FUNC(isValid, l_Wing, NULL, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
int idx;
if(!ade_get_args(L, "o", l_Wing.Get(&idx)))
return ADE_RETURN_NIL;
if (idx < 0 || idx >= Num_wings)
return ADE_RETURN_FALSE;
return ADE_RETURN_TRUE;
}
ADE_FUNC(getBreedName, l_Wing, nullptr, "Gets the FreeSpace type name", "string", "'Wing', or empty string if handle is invalid")
{
int idx;
+1 -12
View File
@@ -13,6 +13,7 @@ namespace api {
//**********HANDLE: WingFormation
ADE_OBJ(l_WingFormation, int, "wingformation", "Wing formation handle");
ADE_OBJ_VALIDATOR_RANGE(l_WingFormation, sz2i(Wing_formations.size()) + 1); // + 1 admits the default formation
ADE_FUNC(__tostring, l_WingFormation, nullptr, "Wing formation name", "string", "Wing formation name, or an empty string if handle is invalid")
{
@@ -66,17 +67,5 @@ ADE_VIRTVAR(Name, l_WingFormation, "string", "Wing formation name", "string", "W
return ade_set_args(L, "s", Wing_formations[formation_id].name);
}
ADE_FUNC(isValid, l_WingFormation, nullptr, "Detects whether handle is valid", "boolean", "true if valid, false if handle is invalid, nil if a syntax/type error occurs")
{
int formation_id;
if (!ade_get_args(L, "o", l_WingFormation.Get(&formation_id)))
return ADE_RETURN_NIL;
if (formation_id < 0 || formation_id >= (int)Wing_formations.size() + 1)
return ADE_RETURN_FALSE;
return ADE_RETURN_TRUE;
}
}
}
+4 -4
View File
@@ -59,8 +59,8 @@ void pushValue(lua_State* luaState, const bool& value);
void pushValue(lua_State* luaState, const lua_CFunction& value);
template<typename T>
void pushValue(lua_State* L, scripting::ade_odata_setter<T>&& value) {
using namespace scripting;
void pushValue(lua_State* L, ::scripting::ade_odata_setter<T>&& value) {
using namespace ::scripting;
//WMC - char must be 1 byte, foo.
static_assert(sizeof(char) == 1, "char must be 1 byte!");
@@ -105,7 +105,7 @@ bool popValue(lua_State* luaState, bool& target, int stackposition = -1, bool re
bool popValue(lua_State* luaState, lua_CFunction& target, int stackposition = -1, bool remove = true);
template <typename T>
bool popValue(lua_State* L, scripting::ade_odata_getter<T>&& od, int stackposition = -1, bool remove = true)
bool popValue(lua_State* L, ::scripting::ade_odata_getter<T>&& od, int stackposition = -1, bool remove = true)
{
// Use the helper to reduce the amount of code here
if (!internal::ade_odata_helper(L, stackposition, od.idx)) {
@@ -124,7 +124,7 @@ bool popValue(lua_State* L, scripting::ade_odata_getter<T>&& od, int stackpositi
}
template <typename T>
bool popValue(lua_State* L, scripting::ade_odata_ptr_getter<T>&& od, int stackposition = -1, bool remove = true)
bool popValue(lua_State* L, ::scripting::ade_odata_ptr_getter<T>&& od, int stackposition = -1, bool remove = true)
{
// Use the helper to reduce the amount of code here
if (!internal::ade_odata_helper(L, stackposition, od.idx)) {
+80
View File
@@ -1,4 +1,9 @@
#include "mod_table/mod_table.h"
#include "scripting/ade_args.h"
#include "scripting/api/objs/shipclass.h"
#include "scripting/scripting_doc.h"
#include "scripting/ScriptingTestFixture.h"
class ScriptingBaseTest : public test::scripting::ScriptingTestFixture {
@@ -12,6 +17,81 @@ TEST_F(ScriptingBaseTest, print) {
this->EvalTestScript();
}
TEST_F(ScriptingBaseTest, autoIsValid) {
this->EvalTestScript();
}
// Verifies that automatically generated isValid() functions and explicitly declared ones coexist correctly in the
// documentation: no class lists isValid more than once, and an explicit declaration replaces the generated one.
TEST_F(ScriptingBaseTest, isValidDocumentation) {
const auto doc = _state->OutputDocumentation([](const SCP_string& error) {
ADD_FAILURE() << "Documentation error: " << error;
});
SCP_unordered_map<SCP_string, const ::scripting::DocumentationElement*> isValidByClass;
for (const auto& element : doc.elements) {
if (element->type != ::scripting::ElementType::Class)
continue;
int count = 0;
for (const auto& child : element->children) {
if (child->name == "isValid") {
count++;
isValidByClass[element->name] = child.get();
}
}
ASSERT_LE(count, 1) << "Class '" << element->name << "' lists isValid more than once";
}
// Generated from the isValid() member of the stored type
ASSERT_NE(isValidByClass.end(), isValidByClass.find("object"));
ASSERT_NE(isValidByClass.end(), isValidByClass.find("gamestate"));
ASSERT_NE(isValidByClass.end(), isValidByClass.find("parse_subsystem"));
ASSERT_NE(isValidByClass.end(), isValidByClass.find("soundfile"));
ASSERT_EQ("Detects whether handle is valid", isValidByClass["object"]->description);
// Generated from a validator registered with ADE_OBJ_VALIDATOR
ASSERT_NE(isValidByClass.end(), isValidByClass.find("shipclass"));
ASSERT_NE(isValidByClass.end(), isValidByClass.find("weaponclass"));
ASSERT_NE(isValidByClass.end(), isValidByClass.find("team"));
ASSERT_NE(isValidByClass.end(), isValidByClass.find("loadout_ship"));
ASSERT_NE(isValidByClass.end(), isValidByClass.find("HudGauge"));
ASSERT_EQ("Detects whether handle is valid", isValidByClass["shipclass"]->description);
// Derived classes inherit it rather than listing their own
ASSERT_EQ(isValidByClass.end(), isValidByClass.find("ship"));
ASSERT_EQ(isValidByClass.end(), isValidByClass.find("sound3D"));
// An explicit declaration replaces the generated one
ASSERT_NE(isValidByClass.end(), isValidByClass.find("sound"));
ASSERT_NE(SCP_string::npos, isValidByClass["sound"]->description.find("sound entry"));
}
// Exercises the generated isValid() of an int-index handle from Lua
TEST_F(ScriptingBaseTest, intValidator) {
this->EvalTestScript();
}
// A registered validator must also drive the "return nil instead of an invalid object" option in ade_set_args
TEST_F(ScriptingBaseTest, intValidatorNilReturn) {
auto L = _state->GetLuaSession();
const bool previous = Lua_API_returns_nil_instead_of_invalid_object;
// Headless there are no ship classes, so index 0 is invalid
Lua_API_returns_nil_instead_of_invalid_object = false;
::scripting::ade_set_args(L, "o", ::scripting::api::l_Shipclass.Set(0));
ASSERT_TRUE(lua_isuserdata(L, -1));
lua_pop(L, 1);
Lua_API_returns_nil_instead_of_invalid_object = true;
::scripting::ade_set_args(L, "o", ::scripting::api::l_Shipclass.Set(0));
ASSERT_TRUE(lua_isnil(L, -1));
lua_pop(L, 1);
Lua_API_returns_nil_instead_of_invalid_object = previous;
}
class ScriptingSerializationTest : public ScriptingBaseTest {
public:
ScriptingSerializationTest() = default;
@@ -0,0 +1,16 @@
-- gamestate and gameevent handles have an isValid() C++ member but never had an explicit
-- ADE_FUNC(isValid, ...), so these exercise the automatically generated function.
local state = ba.GameStates["GS_STATE_MAIN_MENU"]
assert(type(state.isValid) == "function", "gamestate should expose isValid()")
assert(state:isValid() == true, "a real game state should be valid")
local badState = ba.GameStates[100000]
assert(badState:isValid() == false, "an out-of-range game state should be invalid")
local event = ba.GameEvents["GS_EVENT_MAIN_MENU"]
assert(type(event.isValid) == "function", "gameevent should expose isValid()")
assert(event:isValid() == true, "a real game event should be valid")
local badEvent = ba.GameEvents[100000]
assert(badEvent:isValid() == false, "an out-of-range game event should be invalid")
@@ -0,0 +1,7 @@
-- shipclass is an int-index handle whose validity comes from ADE_OBJ_VALIDATOR. Headless there are no
-- ship classes, so any index yields an invalid handle.
local sc = tb.ShipClasses[1]
assert(sc ~= nil, "an invalid handle should still be returned when the nil-instead-of-invalid option is off")
assert(type(sc.isValid) == "function", "shipclass should expose isValid()")
assert(sc:isValid() == false, "an out-of-range ship class should be invalid")