mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-07 17:52:15 -10:00
1658 lines
46 KiB
C++
1658 lines
46 KiB
C++
//
|
|
//
|
|
|
|
#include "freespace.h" //For frametime
|
|
|
|
#include "shipclass.h"
|
|
#include "model.h"
|
|
#include "cockpit_display.h"
|
|
#include "species.h"
|
|
#include "shiptype.h"
|
|
#include "vecmath.h"
|
|
#include "ship/ship.h"
|
|
#include "playerman/player.h"
|
|
#include "weapon/weapon.h"
|
|
#include "mission/missioncampaign.h"
|
|
#include "missionui/missionweaponchoice.h"
|
|
#include "graphics/matrix.h"
|
|
#include "missionui/missionscreencommon.h"
|
|
#include "scripting/api/objs/weaponclass.h"
|
|
#include "model/modelrender.h"
|
|
|
|
namespace scripting {
|
|
namespace api {
|
|
|
|
|
|
//**********HANDLE: default primary
|
|
ADE_OBJ(l_Default_Primary, int, "default_primary", "weapon index");
|
|
|
|
ADE_INDEXER(l_Default_Primary,
|
|
"number idx",
|
|
"Array of ship default primaries for each bank. Returns the Weapon Class or "
|
|
"nil if the bank is invalid for the ship class.",
|
|
"weaponclass",
|
|
"The weapon index")
|
|
{
|
|
int current;
|
|
int idx = -1;
|
|
if (!ade_get_args(L, "oi", l_Default_Primary.Get(¤t), &idx))
|
|
return ADE_RETURN_NIL;
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "This property is read only.");
|
|
}
|
|
|
|
ship_info* sip = &Ship_info[current];
|
|
|
|
if (idx < 1 || idx > sip->num_primary_banks) {
|
|
return ADE_RETURN_NIL;
|
|
};
|
|
idx--; // Convert to Lua's 1 based index system
|
|
|
|
return ade_set_args(L, "o", l_Weaponclass.Set(sip->primary_bank_weapons[idx]));
|
|
}
|
|
|
|
ADE_FUNC(__len,
|
|
l_Default_Primary,
|
|
nullptr,
|
|
"The number of primary banks with defaults",
|
|
"number",
|
|
"The number of primary banks.")
|
|
{
|
|
int current;
|
|
ade_get_args(L, "o", l_Default_Primary.Get(¤t));
|
|
ship_info* sip = &Ship_info[current];
|
|
return ade_set_args(L, "i", sip->num_primary_banks);
|
|
}
|
|
|
|
//**********HANDLE: default secondary
|
|
ADE_OBJ(l_Default_Secondary, int, "default_secondary", "weapon index");
|
|
|
|
ADE_INDEXER(l_Default_Secondary,
|
|
"number idx",
|
|
"Array of ship default secondaries for each bank. Returns the Weapon Class or "
|
|
"nil if the bank is invalid for the ship class.",
|
|
"weaponclass",
|
|
"The weapon index")
|
|
{
|
|
int current;
|
|
int idx = -1;
|
|
if (!ade_get_args(L, "oi", l_Default_Secondary.Get(¤t), &idx))
|
|
return ADE_RETURN_NIL;
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "This property is read only.");
|
|
}
|
|
|
|
ship_info* sip = &Ship_info[current];
|
|
|
|
if (idx < 1 || idx > sip->num_secondary_banks) {
|
|
return ADE_RETURN_NIL;
|
|
};
|
|
idx--; // Convert to Lua's 1 based index system
|
|
|
|
return ade_set_args(L, "o", l_Weaponclass.Set(sip->secondary_bank_weapons[idx]));
|
|
}
|
|
|
|
ADE_FUNC(__len,
|
|
l_Default_Secondary,
|
|
nullptr,
|
|
"The number of secondary banks with defaults",
|
|
"number",
|
|
"The number of secondary banks.")
|
|
{
|
|
int current;
|
|
ade_get_args(L, "o", l_Default_Secondary.Get(¤t));
|
|
ship_info* sip = &Ship_info[current];
|
|
return ade_set_args(L, "i", sip->num_secondary_banks);
|
|
}
|
|
|
|
//**********HANDLE: Shipclass
|
|
ADE_OBJ(l_Shipclass, int, "shipclass", "Ship class handle");
|
|
|
|
ADE_FUNC(__tostring, l_Shipclass, NULL, "Ship class name", "string", "Ship class name, or an empty string if handle is invalid")
|
|
{
|
|
int idx;
|
|
const char* s = nullptr;
|
|
if(!ade_get_args(L, "o|s", l_Shipclass.Get(&idx), &s))
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if(idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "s", "");
|
|
|
|
return ade_set_args(L, "s", Ship_info[idx].name);
|
|
}
|
|
|
|
ADE_FUNC(__eq, l_Shipclass, "shipclass, shipclass", "Checks if the two classes are equal", "boolean", "true if equal, false otherwise")
|
|
{
|
|
int idx1,idx2;
|
|
if(!ade_get_args(L, "oo", l_Shipclass.Get(&idx1), l_Shipclass.Get(&idx2)))
|
|
return ade_set_error(L, "b", false);
|
|
|
|
if(idx1 < 0 || idx1 >= ship_info_size())
|
|
return ade_set_error(L, "b", false);
|
|
|
|
if(idx2 < 0 || idx2 >= ship_info_size())
|
|
return ade_set_error(L, "b", false);
|
|
|
|
return ade_set_args(L, "b", idx1 == idx2);
|
|
}
|
|
|
|
|
|
ADE_VIRTVAR(Name, l_Shipclass, "string", "Ship class name", "string", "Ship class name, or an empty string if handle is invalid")
|
|
{
|
|
int idx;
|
|
const char* s = nullptr;
|
|
if(!ade_get_args(L, "o|s", l_Shipclass.Get(&idx), &s))
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if(idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if(ADE_SETTING_VAR && s != NULL) {
|
|
auto len = sizeof(Ship_info[idx].name);
|
|
strncpy(Ship_info[idx].name, s, len);
|
|
Ship_info[idx].name[len - 1] = 0;
|
|
}
|
|
|
|
return ade_set_args(L, "s", Ship_info[idx].name);
|
|
}
|
|
|
|
ADE_VIRTVAR(ShortName, l_Shipclass, "string", "Ship class short name", "string", "Ship short name, or empty string if handle is invalid")
|
|
{
|
|
int idx;
|
|
const char* s = nullptr;
|
|
if(!ade_get_args(L, "o|s", l_Shipclass.Get(&idx), &s))
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if(idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if(ADE_SETTING_VAR && s != NULL) {
|
|
auto len = sizeof(Ship_info[idx].short_name);
|
|
strncpy(Ship_info[idx].short_name, s, len);
|
|
Ship_info[idx].short_name[len - 1] = 0;
|
|
}
|
|
|
|
return ade_set_args(L, "s", Ship_info[idx].short_name);
|
|
}
|
|
|
|
ADE_VIRTVAR(TypeString, l_Shipclass, "string", "Ship class type string", "string", "Type string, or empty string if handle is invalid")
|
|
{
|
|
int idx;
|
|
const char* s = nullptr;
|
|
if(!ade_get_args(L, "o|s", l_Shipclass.Get(&idx), &s))
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if(idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "s", "");
|
|
|
|
ship_info *sip = &Ship_info[idx];
|
|
|
|
if(ADE_SETTING_VAR) {
|
|
vm_free(sip->type_str);
|
|
if(s != NULL) {
|
|
sip->type_str = (char*)vm_malloc(strlen(s)+1);
|
|
strcpy(sip->type_str, s);
|
|
} else {
|
|
sip->type_str = NULL;
|
|
}
|
|
}
|
|
|
|
if(sip->type_str != NULL)
|
|
return ade_set_args(L, "s", sip->type_str);
|
|
else
|
|
return ade_set_args(L, "s", "");
|
|
}
|
|
|
|
ADE_VIRTVAR(ManeuverabilityString, l_Shipclass, "string", "Ship class maneuverability string", "string", "Maneuverability string, or empty string if handle is invalid")
|
|
{
|
|
int idx;
|
|
const char* s = nullptr;
|
|
if(!ade_get_args(L, "o|s", l_Shipclass.Get(&idx), &s))
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if(idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "s", "");
|
|
|
|
ship_info *sip = &Ship_info[idx];
|
|
|
|
if(ADE_SETTING_VAR) {
|
|
vm_free(sip->maneuverability_str);
|
|
if(s != NULL) {
|
|
sip->maneuverability_str = (char*)vm_malloc(strlen(s)+1);
|
|
strcpy(sip->maneuverability_str, s);
|
|
} else {
|
|
sip->maneuverability_str = NULL;
|
|
}
|
|
}
|
|
|
|
if(sip->maneuverability_str != NULL)
|
|
return ade_set_args(L, "s", sip->maneuverability_str);
|
|
else
|
|
return ade_set_args(L, "s", "");
|
|
}
|
|
|
|
ADE_VIRTVAR(ArmorString, l_Shipclass, "string", "Ship class armor string", "string", "Armor string, or empty string if handle is invalid")
|
|
{
|
|
int idx;
|
|
const char* s = nullptr;
|
|
if(!ade_get_args(L, "o|s", l_Shipclass.Get(&idx), &s))
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if(idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "s", "");
|
|
|
|
ship_info *sip = &Ship_info[idx];
|
|
|
|
if(ADE_SETTING_VAR) {
|
|
vm_free(sip->armor_str);
|
|
if(s != NULL) {
|
|
sip->armor_str = (char*)vm_malloc(strlen(s)+1);
|
|
strcpy(sip->armor_str, s);
|
|
} else {
|
|
sip->armor_str = NULL;
|
|
}
|
|
}
|
|
|
|
if(sip->armor_str != NULL)
|
|
return ade_set_args(L, "s", sip->armor_str);
|
|
else
|
|
return ade_set_args(L, "s", "");
|
|
}
|
|
|
|
ADE_VIRTVAR(ManufacturerString, l_Shipclass, "string", "Ship class manufacturer", "string", "Manufacturer, or empty string if handle is invalid")
|
|
{
|
|
int idx;
|
|
const char* s = nullptr;
|
|
if(!ade_get_args(L, "o|s", l_Shipclass.Get(&idx), &s))
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if(idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "s", "");
|
|
|
|
ship_info *sip = &Ship_info[idx];
|
|
|
|
if(ADE_SETTING_VAR) {
|
|
vm_free(sip->manufacturer_str);
|
|
if(s != NULL) {
|
|
sip->manufacturer_str = (char*)vm_malloc(strlen(s)+1);
|
|
strcpy(sip->manufacturer_str, s);
|
|
} else {
|
|
sip->manufacturer_str = NULL;
|
|
}
|
|
}
|
|
|
|
if(sip->manufacturer_str != NULL)
|
|
return ade_set_args(L, "s", sip->manufacturer_str);
|
|
else
|
|
return ade_set_args(L, "s", "");
|
|
}
|
|
|
|
ADE_VIRTVAR(LengthString, l_Shipclass, "string", "Ship class length", "string", "Length, or empty string if handle is invalid")
|
|
{
|
|
int idx;
|
|
const char* s = nullptr;
|
|
if(!ade_get_args(L, "o|s", l_Shipclass.Get(&idx), &s))
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if(idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "s", "");
|
|
|
|
ship_info *sip = &Ship_info[idx];
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "Setting Length is not supported");
|
|
}
|
|
|
|
if (sip->ship_length != nullptr)
|
|
return ade_set_args(L, "s", sip->ship_length);
|
|
else
|
|
return ade_set_args(L, "s", "");
|
|
}
|
|
|
|
ADE_VIRTVAR(GunMountsString, l_Shipclass, "string", "Ship class gun mounts", "string", "Gun mounts, or empty string if handle is invalid")
|
|
{
|
|
int idx;
|
|
const char* s = nullptr;
|
|
if(!ade_get_args(L, "o|s", l_Shipclass.Get(&idx), &s))
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if(idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "s", "");
|
|
|
|
ship_info *sip = &Ship_info[idx];
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "Setting Gun mounts is not supported");
|
|
}
|
|
|
|
if (sip->gun_mounts != nullptr)
|
|
return ade_set_args(L, "s", sip->gun_mounts);
|
|
else
|
|
return ade_set_args(L, "s", "");
|
|
}
|
|
|
|
ADE_VIRTVAR(MissileBanksString, l_Shipclass, "string", "Ship class missile banks", "string", "Missile banks, or empty string if handle is invalid")
|
|
{
|
|
int idx;
|
|
const char* s = nullptr;
|
|
if(!ade_get_args(L, "o|s", l_Shipclass.Get(&idx), &s))
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if(idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "s", "");
|
|
|
|
ship_info *sip = &Ship_info[idx];
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "Setting Missile banks is not supported");
|
|
}
|
|
|
|
if (sip->missile_banks != nullptr)
|
|
return ade_set_args(L, "s", sip->missile_banks);
|
|
else
|
|
return ade_set_args(L, "s", "");
|
|
}
|
|
|
|
ADE_VIRTVAR(VelocityString, l_Shipclass, "string", "Ship class velocity", "string", "velocity, or empty string if handle is invalid")
|
|
{
|
|
int idx;
|
|
const char* s = nullptr;
|
|
if(!ade_get_args(L, "o|s", l_Shipclass.Get(&idx), &s))
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if(idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "s", "");
|
|
|
|
ship_info *sip = &Ship_info[idx];
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "Setting Missile banks is not supported");
|
|
}
|
|
|
|
char str[100];
|
|
sprintf(str, XSTR("%d m/s", 743), fl2i((float)sip->max_vel.xyz.z * Hud_speed_multiplier));
|
|
|
|
return ade_set_args(L, "s", str);
|
|
}
|
|
|
|
|
|
ADE_VIRTVAR(Description, l_Shipclass, "string", "Ship class description", "string", "Description, or empty string if handle is invalid")
|
|
{
|
|
int idx;
|
|
const char* s = nullptr;
|
|
if(!ade_get_args(L, "o|s", l_Shipclass.Get(&idx), &s))
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if(idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "s", "");
|
|
|
|
ship_info *sip = &Ship_info[idx];
|
|
|
|
if(ADE_SETTING_VAR) {
|
|
vm_free(sip->desc);
|
|
if(s != NULL) {
|
|
sip->desc = (char*)vm_malloc(strlen(s)+1);
|
|
strcpy(sip->desc, s);
|
|
} else {
|
|
sip->desc = NULL;
|
|
}
|
|
}
|
|
|
|
if(sip->desc != NULL)
|
|
return ade_set_args(L, "s", sip->desc);
|
|
else
|
|
return ade_set_args(L, "s", "");
|
|
}
|
|
|
|
ADE_VIRTVAR(SelectIconFilename, l_Shipclass, "string", "Ship class select icon filename", "string", "Filename, or empty string if handle is invalid")
|
|
{
|
|
int idx;
|
|
const char* s = nullptr;
|
|
if (!ade_get_args(L, "o|s", l_Shipclass.Get(&idx), &s))
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if (idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if(ADE_SETTING_VAR) {
|
|
LuaError(L, "Setting Select Icon is not supported");
|
|
}
|
|
|
|
return ade_set_args(L, "s", Ship_info[idx].icon_filename);
|
|
}
|
|
|
|
ADE_VIRTVAR(SelectAnimFilename, l_Shipclass, "string", "Ship class select animation filename", "string", "Filename, or empty string if handle is invalid")
|
|
{
|
|
int idx;
|
|
const char* s = nullptr;
|
|
if (!ade_get_args(L, "o|s", l_Shipclass.Get(&idx), &s))
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if (idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if(ADE_SETTING_VAR) {
|
|
LuaError(L, "Setting Select Anim is not supported");
|
|
}
|
|
|
|
return ade_set_args(L, "s", Ship_info[idx].anim_filename);
|
|
}
|
|
|
|
ADE_VIRTVAR(SelectOverheadFilename, l_Shipclass, "string", "Ship class select overhead filename", "string", "Filename, or empty string if handle is invalid")
|
|
{
|
|
int idx;
|
|
const char* s = nullptr;
|
|
if (!ade_get_args(L, "o|s", l_Shipclass.Get(&idx), &s))
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if (idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if(ADE_SETTING_VAR) {
|
|
LuaError(L, "Setting Select Overhead Image is not supported");
|
|
}
|
|
|
|
return ade_set_args(L, "s", Ship_info[idx].overhead_filename);
|
|
}
|
|
|
|
ADE_VIRTVAR(TechDescription, l_Shipclass, "string", "Ship class tech description", "string", "Tech description, or empty string if handle is invalid")
|
|
{
|
|
int idx;
|
|
const char* s = nullptr;
|
|
if(!ade_get_args(L, "o|s", l_Shipclass.Get(&idx), &s))
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if(idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "s", "");
|
|
|
|
ship_info *sip = &Ship_info[idx];
|
|
|
|
if(ADE_SETTING_VAR) {
|
|
vm_free(sip->tech_desc);
|
|
if(s != NULL) {
|
|
sip->tech_desc = (char*)vm_malloc(strlen(s)+1);
|
|
strcpy(sip->tech_desc, s);
|
|
} else {
|
|
sip->tech_desc = NULL;
|
|
}
|
|
}
|
|
|
|
if(sip->tech_desc != NULL)
|
|
return ade_set_args(L, "s", sip->tech_desc);
|
|
else
|
|
return ade_set_args(L, "s", "");
|
|
}
|
|
|
|
ADE_VIRTVAR(numPrimaryBanks,
|
|
l_Shipclass,
|
|
nullptr,
|
|
"Number of primary banks on this ship class",
|
|
"number",
|
|
"number of banks or nil is ship handle is invalid")
|
|
{
|
|
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_NIL;
|
|
|
|
ship_info* sip = &Ship_info[idx];
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "Setting number of banks is not supported");
|
|
}
|
|
|
|
return ade_set_args(L, "i", sip->num_primary_banks);
|
|
}
|
|
|
|
ADE_FUNC(getPrimaryBankCapacity,
|
|
l_Shipclass,
|
|
"number index",
|
|
"Returns the capacity of the specified primary bank",
|
|
"number",
|
|
"The bank capacity or nil if the index is invalid")
|
|
{
|
|
int shipIdx;
|
|
int idx;
|
|
if (!ade_get_args(L, "oi", l_Shipclass.Get(&shipIdx), &idx))
|
|
return ADE_RETURN_NIL;
|
|
|
|
ship_info* sip = &Ship_info[shipIdx];
|
|
|
|
if (idx < 1 || idx > sip->num_primary_banks) {
|
|
return ADE_RETURN_NIL;
|
|
};
|
|
|
|
idx--; // Convert from Lua's 1 based index system
|
|
|
|
return ade_set_args(L, "i", sip->primary_bank_ammo_capacity[idx]);
|
|
}
|
|
|
|
ADE_VIRTVAR(numSecondaryBanks,
|
|
l_Shipclass,
|
|
nullptr,
|
|
"Number of secondary banks on this ship class",
|
|
"number",
|
|
"number of banks or nil is ship handle is invalid")
|
|
{
|
|
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_NIL;
|
|
|
|
ship_info* sip = &Ship_info[idx];
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "Setting number of banks is not supported");
|
|
}
|
|
|
|
return ade_set_args(L, "i", sip->num_secondary_banks);
|
|
}
|
|
|
|
ADE_FUNC(getSecondaryBankCapacity,
|
|
l_Shipclass,
|
|
"number index",
|
|
"Returns the capacity of the specified secondary bank",
|
|
"number",
|
|
"The bank capacity or nil if the index is invalid")
|
|
{
|
|
int shipIdx;
|
|
int idx;
|
|
if (!ade_get_args(L, "oi", l_Shipclass.Get(&shipIdx), &idx))
|
|
return ADE_RETURN_NIL;
|
|
|
|
ship_info* sip = &Ship_info[shipIdx];
|
|
|
|
if (idx < 1 || idx > sip->num_secondary_banks) {
|
|
return ADE_RETURN_NIL;
|
|
};
|
|
|
|
idx--; // Convert from Lua's 1 based index system
|
|
|
|
return ade_set_args(L, "i", sip->secondary_bank_ammo_capacity[idx]);
|
|
}
|
|
|
|
ADE_VIRTVAR(defaultPrimaries,
|
|
l_Shipclass,
|
|
"number",
|
|
"Array of default primary weapons",
|
|
"default_primary",
|
|
"The weapons array or nil if handle is invalid")
|
|
{
|
|
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_NIL;
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "This property is read only.");
|
|
}
|
|
|
|
return ade_set_args(L, "o", l_Default_Primary.Set(idx));
|
|
}
|
|
|
|
ADE_VIRTVAR(defaultSecondaries,
|
|
l_Shipclass,
|
|
"number",
|
|
"Array of default secondary weapons",
|
|
"default_secondary",
|
|
"The weapons array or nil if handle is invalid")
|
|
{
|
|
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_NIL;
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "This property is read only.");
|
|
}
|
|
|
|
return ade_set_args(L, "o", l_Default_Secondary.Set(idx));
|
|
}
|
|
|
|
ADE_FUNC(isWeaponAllowedOnShip,
|
|
l_Shipclass,
|
|
"number index, [number bank]",
|
|
"Gets whether or not a weapon is allowed on a ship class. "
|
|
"Optionally check a specific bank. Banks are 1 to a maximum of 7 where the first banks are Primaries and rest are "
|
|
"Secondaries. "
|
|
"Exact numbering depends on the ship class being checked. Note also that this will consider dogfight weapons only "
|
|
"if "
|
|
"a dogfight mission has been loaded. Index is index into Weapon Classes.",
|
|
"boolean",
|
|
"True if allowed, false if not.")
|
|
{
|
|
int idx;
|
|
int wepidx;
|
|
int bank = 0;
|
|
if (!ade_get_args(L, "oi|i", l_Shipclass.Get(&idx), &wepidx, &bank))
|
|
return ade_set_error(L, "b", false);
|
|
|
|
if (idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "b", false);
|
|
wepidx--; // Convert from Lua
|
|
if (wepidx < 0 || wepidx >= weapon_info_size())
|
|
return ade_set_error(L, "b", false);
|
|
if (bank != 0) {
|
|
if (bank < 0 || bank > (Ship_info[idx].num_primary_banks + Ship_info[idx].num_secondary_banks))
|
|
return ade_set_error(L, "b", false);
|
|
};
|
|
bank--; // Convert from Lua
|
|
|
|
bool retv = false;
|
|
if ((bank >= 0) && (eval_weapon_flag_for_game_type(Ship_info[idx].restricted_loadout_flag[bank]))) {
|
|
if (eval_weapon_flag_for_game_type(Ship_info[idx].allowed_bank_restricted_weapons[bank][wepidx]))
|
|
retv = true;
|
|
} else if (eval_weapon_flag_for_game_type(Ship_info[idx].allowed_weapons[wepidx])) {
|
|
retv = true;
|
|
}
|
|
|
|
return ade_set_args(L, "b", retv);
|
|
}
|
|
|
|
ADE_VIRTVAR(AfterburnerFuelMax, l_Shipclass, "number", "Afterburner fuel capacity", "number", "Afterburner capacity, or 0 if handle is invalid")
|
|
{
|
|
int idx;
|
|
float fuel = -1.0f;
|
|
if(!ade_get_args(L, "o|f", l_Shipclass.Get(&idx), &fuel))
|
|
return ade_set_error(L, "f", 0.0f);
|
|
|
|
if(idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "f", 0.0f);
|
|
|
|
if(ADE_SETTING_VAR && fuel >= 0.0f)
|
|
Ship_info[idx].afterburner_fuel_capacity = fuel;
|
|
|
|
return ade_set_args(L, "f", Ship_info[idx].afterburner_fuel_capacity);
|
|
}
|
|
|
|
ADE_VIRTVAR(ScanTime, l_Shipclass, nullptr, "Ship scan time", "number", "Time required to scan, or 0 if handle is invalid. This property is read-only")
|
|
{
|
|
int idx;
|
|
if (!ade_get_args(L, "o", l_Shipclass.Get(&idx)))
|
|
return ade_set_error(L, "i", 0);
|
|
|
|
if (idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "i", 0);
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "Setting ScanTime is not supported");
|
|
}
|
|
|
|
return ade_set_args(L, "i", Ship_info[idx].scan_time);
|
|
}
|
|
|
|
ADE_VIRTVAR(CountermeasureClass, l_Shipclass, "weaponclass", "The default countermeasure class assigned to this ship class", "weaponclass", "Countermeasure hardpoint weapon class, or invalid weaponclass handle if no countermeasure class or ship handle is invalid")
|
|
{
|
|
int idx;
|
|
if (!ade_get_args(L, "o", l_Shipclass.Get(&idx)))
|
|
return ade_set_error(L, "o", l_Weaponclass.Set(-1));
|
|
|
|
if (idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "o", l_Weaponclass.Set(-1));
|
|
|
|
ship_info* sip = &Ship_info[idx];
|
|
|
|
if(ADE_SETTING_VAR) {
|
|
LuaError(L, "Setting CountermeasureClass is not supported");
|
|
}
|
|
|
|
if (sip->cmeasure_type > -1) {
|
|
return ade_set_args(L, "o", l_Weaponclass.Set(sip->cmeasure_type));
|
|
} else {
|
|
return ade_set_error(L, "o", l_Weaponclass.Set(-1));
|
|
}
|
|
}
|
|
|
|
ADE_VIRTVAR(CountermeasuresMax, l_Shipclass, "number", "Maximum number of countermeasures the ship can carry", "number", "Countermeasure capacity, or 0 if handle is invalid")
|
|
{
|
|
int idx;
|
|
int i = -1;
|
|
if(!ade_get_args(L, "o|i", l_Shipclass.Get(&idx), &i))
|
|
return ade_set_error(L, "i", 0);
|
|
|
|
if(idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "i", 0);
|
|
|
|
if(ADE_SETTING_VAR && i > -1) {
|
|
Ship_info[idx].cmeasure_max = i;
|
|
}
|
|
|
|
return ade_set_args(L, "i", Ship_info[idx].cmeasure_max);
|
|
}
|
|
|
|
ADE_VIRTVAR(Model, l_Shipclass, "model", "Model", "model", "Ship class model, or invalid model handle if shipclass handle is invalid")
|
|
{
|
|
int ship_info_idx=-1;
|
|
model_h *mdl = NULL;
|
|
if(!ade_get_args(L, "o|o", l_Shipclass.Get(&ship_info_idx), l_Model.GetPtr(&mdl)))
|
|
return ade_set_error(L, "o", l_Model.Set(model_h(-1)));
|
|
|
|
if(ship_info_idx < 0 || ship_info_idx >= ship_info_size())
|
|
return ade_set_error(L, "o", l_Model.Set(model_h(-1)));
|
|
|
|
ship_info *sip = &Ship_info[ship_info_idx];
|
|
|
|
int mid = (mdl ? mdl->GetID() : -1);
|
|
|
|
if(ADE_SETTING_VAR && mid > -1) {
|
|
sip->model_num = mid;
|
|
}
|
|
|
|
return ade_set_args(L, "o", l_Model.Set(model_h(sip->model_num)));
|
|
}
|
|
|
|
ADE_VIRTVAR(CockpitModel, l_Shipclass, "model", "Model used for first-person cockpit", "model", "Cockpit model")
|
|
{
|
|
int ship_info_idx=-1;
|
|
model_h *mdl = NULL;
|
|
if(!ade_get_args(L, "o|o", l_Shipclass.Get(&ship_info_idx), l_Model.GetPtr(&mdl)))
|
|
return ade_set_error(L, "o", l_Model.Set(model_h()));
|
|
|
|
if(ship_info_idx < 0 || ship_info_idx >= ship_info_size())
|
|
return ade_set_error(L, "o", l_Model.Set(model_h()));
|
|
|
|
ship_info *sip = &Ship_info[ship_info_idx];
|
|
|
|
int mid = (mdl ? mdl->GetID() : -1);
|
|
|
|
if(ADE_SETTING_VAR) {
|
|
sip->cockpit_model_num = mid;
|
|
}
|
|
|
|
return ade_set_args(L, "o", l_Model.Set(model_h(sip->cockpit_model_num)));
|
|
}
|
|
|
|
ADE_VIRTVAR(CockpitDisplays, l_Shipclass, "cockpitdisplays", "Gets the cockpit display information array of this ship class", "cockpitdisplays", "Array handle containing the information or invalid handle on error")
|
|
{
|
|
int ship_info_idx=-1;
|
|
cockpit_displays_info_h *cdih = NULL;
|
|
if(!ade_get_args(L, "o|o", l_Shipclass.Get(&ship_info_idx), l_CockpitDisplayInfos.GetPtr(&cdih)))
|
|
return ade_set_error(L, "o", l_CockpitDisplayInfos.Set(cockpit_displays_info_h()));
|
|
|
|
if(ship_info_idx < 0 || ship_info_idx >= ship_info_size())
|
|
return ade_set_error(L, "o", l_CockpitDisplayInfos.Set(cockpit_displays_info_h()));
|
|
|
|
if(ADE_SETTING_VAR) {
|
|
LuaError(L, "Attempted to use incomplete feature: Cockpit display information copy");
|
|
}
|
|
|
|
return ade_set_args(L, "o", l_CockpitDisplayInfos.Set(cockpit_displays_info_h(ship_info_idx)));
|
|
}
|
|
|
|
ADE_VIRTVAR(HitpointsMax, l_Shipclass, "number", "Ship class hitpoints", "number", "Hitpoints, or 0 if handle is invalid")
|
|
{
|
|
int idx;
|
|
float f = -1.0f;
|
|
if(!ade_get_args(L, "o|f", l_Shipclass.Get(&idx), &f))
|
|
return ade_set_error(L, "f", 0.0f);
|
|
|
|
if(idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "f", 0.0f);
|
|
|
|
if(ADE_SETTING_VAR && f >= 0.0f) {
|
|
Ship_info[idx].max_hull_strength = f;
|
|
}
|
|
|
|
return ade_set_args(L, "f", Ship_info[idx].max_hull_strength);
|
|
}
|
|
|
|
ADE_VIRTVAR(Species, l_Shipclass, "species", "Ship class species", "species", "Ship class species, or invalid species handle if shipclass handle is invalid")
|
|
{
|
|
int idx;
|
|
int sidx = -1;
|
|
if(!ade_get_args(L, "o|o", l_Shipclass.Get(&idx), l_Species.Get(&sidx)))
|
|
return ade_set_error(L, "o", l_Species.Set(-1));
|
|
|
|
if(idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "o", l_Species.Set(-1));
|
|
|
|
if(ADE_SETTING_VAR && sidx > -1 && sidx < (int)Species_info.size()) {
|
|
Ship_info[idx].species = sidx;
|
|
}
|
|
|
|
return ade_set_args(L, "o", l_Species.Set(Ship_info[idx].species));
|
|
}
|
|
|
|
ADE_VIRTVAR(Type, l_Shipclass, "shiptype", "Ship class type", "shiptype", "Ship type, or invalid handle if shipclass handle is invalid")
|
|
{
|
|
int idx;
|
|
int sidx = -1;
|
|
if(!ade_get_args(L, "o|o", l_Shipclass.Get(&idx), l_Shiptype.Get(&sidx)))
|
|
return ade_set_error(L, "o", l_Shiptype.Set(-1));
|
|
|
|
if(idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "o", l_Shiptype.Set(-1));
|
|
|
|
if(ADE_SETTING_VAR && sidx > -1 && sidx < (int)Ship_types.size()) {
|
|
Ship_info[idx].class_type = sidx;
|
|
}
|
|
|
|
return ade_set_args(L, "o", l_Shiptype.Set(Ship_info[idx].class_type));
|
|
}
|
|
|
|
ADE_VIRTVAR(AltName, l_Shipclass, "string", "Alternate name for ship class", "string", "Alternate string or empty string if handle is invalid")
|
|
{
|
|
const char* newName = nullptr;
|
|
int idx;
|
|
if(!ade_get_args(L, "o|s", l_Shipclass.Get(&idx), &newName))
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if(idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "s", "");
|
|
|
|
if(ADE_SETTING_VAR && newName != NULL) {
|
|
if (strlen(newName) >= NAME_LENGTH)
|
|
{
|
|
LuaError(L, "Cannot set alternate name value to '%s' because it is too long, maximum length is %d!", newName, NAME_LENGTH - 1);
|
|
return ade_set_error(L, "s", "");
|
|
}
|
|
|
|
strcpy_s(Ship_info[idx].display_name, newName);
|
|
}
|
|
|
|
return ade_set_args(L, "s", Ship_info[idx].display_name);
|
|
}
|
|
|
|
ADE_VIRTVAR(VelocityMax, l_Shipclass, "vector", "Ship's lateral and forward speeds", "vector", "Maximum velocity, or null vector if handle is invalid")
|
|
{
|
|
int idx;
|
|
vec3d* vec = NULL;
|
|
if (!ade_get_args(L, "o|o", l_Shipclass.Get(&idx), l_Vector.GetPtr(&vec)))
|
|
return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
|
|
|
|
if (idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "Setting VelocityMax is not supported");
|
|
}
|
|
|
|
return ade_set_args(L, "o", l_Vector.Set(Ship_info[idx].max_vel));
|
|
}
|
|
|
|
ADE_VIRTVAR(VelocityDamping, l_Shipclass, "number", "Damping, the natural period (1 / omega) of the dampening effects on top of the acceleration model. ", "number", "Damping, or 0 if handle is invalid")
|
|
{
|
|
int idx;
|
|
float f = 0.0f;
|
|
if (!ade_get_args(L, "o|f", l_Shipclass.Get(&idx), &f))
|
|
return ade_set_error(L, "f", 0.0f);
|
|
|
|
if (idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "f", 0.0f);
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "Setting VelocityDamping is not supported");
|
|
}
|
|
|
|
return ade_set_args(L, "f", Ship_info[idx].damp);
|
|
}
|
|
|
|
ADE_VIRTVAR(RearVelocityMax, l_Shipclass, "number", "The maximum rear velocity of the ship", "number", "Speed, or 0 if handle is invalid")
|
|
{
|
|
int idx;
|
|
float f = 0.0f;
|
|
if (!ade_get_args(L, "o|f", l_Shipclass.Get(&idx), &f))
|
|
return ade_set_error(L, "f", 0.0f);
|
|
|
|
if (idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "f", 0.0f);
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "Setting RearVelocityMax is not supported");
|
|
}
|
|
|
|
return ade_set_args(L, "f", Ship_info[idx].max_rear_vel);
|
|
}
|
|
|
|
ADE_VIRTVAR(ForwardAccelerationTime, l_Shipclass, "number", "Forward acceleration time", "number", "Forward acceleration time, or 0 if handle is invalid")
|
|
{
|
|
int idx;
|
|
float f = 0.0f;
|
|
if (!ade_get_args(L, "o|f", l_Shipclass.Get(&idx), &f))
|
|
return ade_set_error(L, "f", 0.0f);
|
|
|
|
if (idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "f", 0.0f);
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "Setting ForwardAccelerationTime is not supported");
|
|
}
|
|
|
|
return ade_set_args(L, "f", Ship_info[idx].forward_accel);
|
|
}
|
|
|
|
ADE_VIRTVAR(ForwardDecelerationTime, l_Shipclass, "number", "Forward deceleration time", "number", "Forward deceleration time, or 0 if handle is invalid")
|
|
{
|
|
int idx;
|
|
float f = 0.0f;
|
|
if (!ade_get_args(L, "o|f", l_Shipclass.Get(&idx), &f))
|
|
return ade_set_error(L, "f", 0.0f);
|
|
|
|
if (idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "f", 0.0f);
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "Setting ForwardDecelerationTime is not supported");
|
|
}
|
|
|
|
return ade_set_args(L, "f", Ship_info[idx].forward_decel);
|
|
}
|
|
|
|
ADE_VIRTVAR(RotationTime, l_Shipclass, "vector", "Maximum rotation time on each axis", "vector", "Full rotation time for each axis, or null vector if handle is invalid")
|
|
{
|
|
int idx;
|
|
vec3d* vec = NULL;
|
|
if (!ade_get_args(L, "o|o", l_Shipclass.Get(&idx), l_Vector.GetPtr(&vec)))
|
|
return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
|
|
|
|
if (idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "Setting RotationTime is not supported");
|
|
}
|
|
|
|
return ade_set_args(L, "o", l_Vector.Set(Ship_info[idx].rotation_time));
|
|
}
|
|
|
|
ADE_VIRTVAR(RotationalVelocityDamping, l_Shipclass, "number", "Rotational damping, ie derivative of rotational speed", "number", "Rotational damping, or 0 if handle is invalid")
|
|
{
|
|
int idx;
|
|
float f = 0.0f;
|
|
if (!ade_get_args(L, "o|f", l_Shipclass.Get(&idx), &f))
|
|
return ade_set_error(L, "f", 0.0f);
|
|
|
|
if (idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "f", 0.0f);
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "Setting RotationalVelocityDamping is not supported");
|
|
}
|
|
|
|
return ade_set_args(L, "f", Ship_info[idx].rotdamp);
|
|
}
|
|
|
|
ADE_VIRTVAR(AfterburnerAccelerationTime, l_Shipclass, "number", "Afterburner acceleration time", "number", "Afterburner acceleration time, or 0 if handle is invalid")
|
|
{
|
|
int idx;
|
|
float f = 0.0f;
|
|
if (!ade_get_args(L, "o|f", l_Shipclass.Get(&idx), &f))
|
|
return ade_set_error(L, "f", 0.0f);
|
|
|
|
if (idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "f", 0.0f);
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "Setting AfterburnerAccelerationTime is not supported");
|
|
}
|
|
|
|
return ade_set_args(L, "f", Ship_info[idx].afterburner_forward_accel);
|
|
}
|
|
|
|
ADE_VIRTVAR(AfterburnerVelocityMax, l_Shipclass, "vector", "Afterburner max velocity", "vector", "Afterburner max velocity, or null vector if handle is invalid")
|
|
{
|
|
int idx;
|
|
vec3d* vec = NULL;
|
|
if (!ade_get_args(L, "o|o", l_Shipclass.Get(&idx), l_Vector.GetPtr(&vec)))
|
|
return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
|
|
|
|
if (idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "o", l_Vector.Set(vmd_zero_vector));
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "Setting AfterburnerVelocityMax is not supported");
|
|
}
|
|
|
|
return ade_set_args(L, "o", l_Vector.Set(Ship_info[idx].afterburner_max_vel));
|
|
}
|
|
|
|
ADE_VIRTVAR(AfterburnerRearVelocityMax, l_Shipclass, "number", "Afterburner maximum rear velocity", "number", "Rear velocity, or 0 if handle is invalid")
|
|
{
|
|
int idx;
|
|
float f = 0.0f;
|
|
if (!ade_get_args(L, "o|f", l_Shipclass.Get(&idx), &f))
|
|
return ade_set_error(L, "f", 0.0f);
|
|
|
|
if (idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "f", 0.0f);
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "Setting AfterburnerRearVelocityMax is not supported");
|
|
}
|
|
|
|
return ade_set_args(L, "f", Ship_info[idx].afterburner_max_reverse_vel);
|
|
}
|
|
|
|
ADE_VIRTVAR(Score, l_Shipclass, "string", "The score of this ship class", "number", "The score or -1 on invalid ship class")
|
|
{
|
|
int idx;
|
|
int new_score;
|
|
if(!ade_get_args(L, "o|i", l_Shipclass.Get(&idx), &new_score))
|
|
return ade_set_error(L, "i", -1);
|
|
|
|
if(idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "i", -1);
|
|
|
|
if(ADE_SETTING_VAR) {
|
|
Ship_info[idx].score = new_score;
|
|
}
|
|
|
|
return ade_set_args(L, "i", Ship_info[idx].score);
|
|
}
|
|
|
|
ADE_VIRTVAR(InTechDatabase, l_Shipclass, "boolean", "Gets or sets whether this ship class is visible in the tech room", "boolean", "True or false")
|
|
{
|
|
int idx;
|
|
bool new_value;
|
|
if (!ade_get_args(L, "o|b", l_Shipclass.Get(&idx), &new_value))
|
|
return ade_set_error(L, "b", false);
|
|
|
|
if (idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "b", false);
|
|
|
|
auto flag = (Player && (Player->flags & PLAYER_FLAGS_IS_MULTI))
|
|
? Ship::Info_Flags::In_tech_database_m
|
|
: Ship::Info_Flags::In_tech_database;
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
Ship_info[idx].flags.set(flag, new_value);
|
|
}
|
|
|
|
return ade_set_args(L, "b", Ship_info[idx].flags[flag]);
|
|
}
|
|
|
|
ADE_VIRTVAR(AllowedInCampaign, l_Shipclass, "boolean", "Gets or sets whether this ship class is allowed in loadouts in campaign mode", "boolean", "True or false")
|
|
{
|
|
int idx;
|
|
bool new_value;
|
|
if (!ade_get_args(L, "o|b", l_Shipclass.Get(&idx), &new_value))
|
|
return ade_set_error(L, "b", false);
|
|
|
|
if (idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "b", false);
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
Campaign.ships_allowed[idx] = new_value;
|
|
}
|
|
|
|
return Campaign.ships_allowed[idx] ? ADE_RETURN_TRUE : ADE_RETURN_FALSE;
|
|
}
|
|
|
|
ADE_VIRTVAR(PowerOutput, l_Shipclass, "number", "Gets or sets a ship class' power output", "number", "The ship class' current power output")
|
|
{
|
|
int idx;
|
|
float new_power;
|
|
if (!ade_get_args(L, "o|f", l_Shipclass.Get(&idx), &new_power))
|
|
return ade_set_error(L, "f", -1.0f);
|
|
|
|
if (idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "f", -1.0f);
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
Ship_info[idx].power_output = new_power;
|
|
}
|
|
|
|
return ade_set_args(L, "f", Ship_info[idx].power_output);
|
|
}
|
|
|
|
ADE_VIRTVAR(ScanningTimeMultiplier, l_Shipclass, nullptr, "Time multiplier for scans performed by this ship class", "number", "Scanning time multiplier, or 0 if handle is invalid")
|
|
{
|
|
int idx;
|
|
if(!ade_get_args(L, "o", l_Shipclass.Get(&idx)))
|
|
return ade_set_error(L, "f", 0.0f);
|
|
|
|
if(idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "f", 0.0f);
|
|
|
|
if(ADE_SETTING_VAR) {
|
|
LuaError(L, "Setting ScanningTimeMultiplier is not supported");
|
|
}
|
|
|
|
return ade_set_args(L, "f", Ship_info[idx].scanning_time_multiplier);
|
|
}
|
|
|
|
ADE_VIRTVAR(ScanningRangeMultiplier, l_Shipclass, nullptr, "Range multiplier for scans performed by this ship class", "number", "Scanning range multiplier, or 0 if handle is invalid")
|
|
{
|
|
int idx;
|
|
if(!ade_get_args(L, "o", l_Shipclass.Get(&idx)))
|
|
return ade_set_error(L, "f", 0.0f);
|
|
|
|
if(idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "f", 0.0f);
|
|
|
|
if(ADE_SETTING_VAR) {
|
|
LuaError(L, "Setting ScanningRangeMultiplier is not supported");
|
|
}
|
|
|
|
return ade_set_args(L, "f", Ship_info[idx].scanning_range_multiplier);
|
|
}
|
|
|
|
ADE_VIRTVAR(CustomData, l_Shipclass, nullptr, "Gets the custom data table for this ship class", "table", "The ship class's custom data table")
|
|
{
|
|
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_NIL;
|
|
|
|
auto table = luacpp::LuaTable::create(L);
|
|
|
|
ship_info *sip = &Ship_info[idx];
|
|
|
|
for (const auto& pair : sip->custom_data)
|
|
{
|
|
table.addValue(pair.first, pair.second);
|
|
}
|
|
|
|
return ade_set_args(L, "t", &table);
|
|
}
|
|
|
|
ADE_FUNC(hasCustomData, l_Shipclass, nullptr, "Detects whether the ship class has any custom data", "boolean", "true if the shipclass's custom_data is not empty, false otherwise")
|
|
{
|
|
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_NIL;
|
|
|
|
ship_info *sip = &Ship_info[idx];
|
|
|
|
bool result = !sip->custom_data.empty();
|
|
return ade_set_args(L, "b", result);
|
|
}
|
|
|
|
ADE_VIRTVAR(CustomStrings,
|
|
l_Shipclass,
|
|
nullptr,
|
|
"Gets the indexed custom string table for this ship. Each item in the table is a table with the following values: "
|
|
"Name - the name of the custom string, Value - the value associated with the custom string, String - the custom "
|
|
"string itself.",
|
|
"table",
|
|
"The ship's custom data table")
|
|
{
|
|
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_NIL;
|
|
|
|
ship_info* sip = &Ship_info[idx];
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "Setting Custom Data is not supported");
|
|
}
|
|
|
|
auto table = luacpp::LuaTable::create(L);
|
|
|
|
int cnt = 0;
|
|
|
|
for (const auto& cs : sip->custom_strings) {
|
|
cnt++;
|
|
auto item = luacpp::LuaTable::create(L);
|
|
|
|
item.addValue("Name", luacpp::LuaValue::createValue(Script_system.GetLuaSession(), cs.name));
|
|
item.addValue("Value", luacpp::LuaValue::createValue(Script_system.GetLuaSession(), cs.value));
|
|
item.addValue("String", luacpp::LuaValue::createValue(Script_system.GetLuaSession(), cs.text));
|
|
|
|
table.addValue(cnt, item);
|
|
}
|
|
|
|
return ade_set_args(L, "t", &table);
|
|
}
|
|
|
|
ADE_FUNC(hasCustomStrings,
|
|
l_Shipclass,
|
|
nullptr,
|
|
"Detects whether the ship has any custom strings",
|
|
"boolean",
|
|
"true if the ship's custom_strings is not empty, false otherwise")
|
|
{
|
|
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_NIL;
|
|
|
|
ship_info* sip = &Ship_info[idx];
|
|
|
|
bool result = !sip->custom_strings.empty();
|
|
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;
|
|
if(!ade_get_args(L, "o", l_Shipclass.Get(&idx)))
|
|
return ade_set_error(L, "b", false);
|
|
|
|
if(idx < 0 || idx >= ship_info_size())
|
|
return ade_set_error(L, "b", false);
|
|
|
|
bool b = false;
|
|
if(Player != NULL && (Player->flags & PLAYER_FLAGS_IS_MULTI) && (Ship_info[idx].flags[Ship::Info_Flags::In_tech_database_m])) {
|
|
b = true;
|
|
} else if(Ship_info[idx].flags[Ship::Info_Flags::In_tech_database]) {
|
|
b = true;
|
|
}
|
|
|
|
return ade_set_args(L, "b", b);
|
|
}
|
|
|
|
ADE_FUNC(renderTechModel,
|
|
l_Shipclass,
|
|
"number X1, number Y1, number X2, number Y2, [number RotationPercent =0, number PitchPercent =0, number "
|
|
"BankPercent=40, number Zoom=1.3, boolean Lighting=true]",
|
|
"Draws ship model as if in techroom. True for regular lighting, false for flat lighting.",
|
|
"boolean",
|
|
"Whether ship was rendered")
|
|
{
|
|
int x1,y1,x2,y2;
|
|
angles rot_angles = {0.0f, 0.0f, 40.0f};
|
|
int idx;
|
|
float zoom = 1.3f;
|
|
bool lighting = true;
|
|
if(!ade_get_args(L, "oiiii|ffffb", l_Shipclass.Get(&idx), &x1, &y1, &x2, &y2, &rot_angles.h, &rot_angles.p, &rot_angles.b, &zoom, &lighting))
|
|
return ade_set_error(L, "b", false);
|
|
|
|
if(idx < 0 || idx >= ship_info_size())
|
|
return ade_set_args(L, "b", false);
|
|
|
|
if(x2 < x1 || y2 < y1)
|
|
return ade_set_args(L, "b", false);
|
|
|
|
CLAMP(rot_angles.p, 0.0f, 100.0f);
|
|
CLAMP(rot_angles.b, 0.0f, 100.0f);
|
|
CLAMP(rot_angles.h, 0.0f, 100.0f);
|
|
|
|
//Handle angles
|
|
matrix orient = vmd_identity_matrix;
|
|
angles view_angles = {-0.6f, 0.0f, 0.0f};
|
|
vm_angles_2_matrix(&orient, &view_angles);
|
|
|
|
rot_angles.p = (rot_angles.p*0.01f) * PI2;
|
|
rot_angles.b = (rot_angles.b*0.01f) * PI2;
|
|
rot_angles.h = (rot_angles.h*0.01f) * PI2;
|
|
vm_rotate_matrix_by_angles(&orient, &rot_angles);
|
|
|
|
return ade_set_args(L, "b", render_tech_model(TECH_SHIP, x1, y1, x2, y2, zoom, lighting, idx, &orient));
|
|
}
|
|
|
|
// Nuke's alternate tech model rendering function
|
|
ADE_FUNC(renderTechModel2, l_Shipclass, "number X1, number Y1, number X2, number Y2, [orientation Orientation=nil, number Zoom=1.3]", "Draws ship model as if in techroom", "boolean", "Whether ship was rendered")
|
|
{
|
|
int x1,y1,x2,y2;
|
|
int idx;
|
|
float zoom = 1.3f;
|
|
matrix_h *mh = NULL;
|
|
if(!ade_get_args(L, "oiiiio|f", l_Shipclass.Get(&idx), &x1, &y1, &x2, &y2, l_Matrix.GetPtr(&mh), &zoom))
|
|
return ade_set_error(L, "b", false);
|
|
|
|
if(idx < 0 || idx >= ship_info_size())
|
|
return ade_set_args(L, "b", false);
|
|
|
|
if(x2 < x1 || y2 < y1)
|
|
return ade_set_args(L, "b", false);
|
|
|
|
//Handle angles
|
|
matrix *orient = mh->GetMatrix();
|
|
|
|
return ade_set_args(L, "b", render_tech_model(TECH_SHIP, x1, y1, x2, y2, zoom, true, idx, orient));
|
|
}
|
|
|
|
ADE_FUNC(renderSelectModel,
|
|
l_Shipclass,
|
|
"boolean restart, number x, number y, [number width = 629, number height = 355, number currentEffectSetting = default, number zoom = 1.3]",
|
|
"Draws the 3D select ship model with the chosen effect at the specified coordinates. Restart should "
|
|
"be true on the first frame this is called and false on subsequent frames. Valid selection effects are 1 (fs1) or 2 (fs2), "
|
|
"defaults to the mod setting or the model's setting. Zoom is a multiplier to the model's closeup_zoom value.",
|
|
"boolean",
|
|
"true if rendered, false if error")
|
|
{
|
|
int idx;
|
|
bool restart;
|
|
int x1;
|
|
int y1;
|
|
int x2 = 629;
|
|
int y2 = 355;
|
|
int effect = -1;
|
|
float zoom = 1.3f;
|
|
if (!ade_get_args(L, "obii|iiif", l_Shipclass.Get(&idx), &restart, &x1, &y1, &x2, &y2, &effect, &zoom))
|
|
return ADE_RETURN_NIL;
|
|
|
|
if (idx < 0 || idx >= ship_info_size())
|
|
return ade_set_args(L, "b", false);
|
|
|
|
if (effect == 0 || effect > 2) {
|
|
LuaError(L, "Valid effect values are 1 or 2, got %i", effect);
|
|
return ade_set_args(L, "b", false);
|
|
}
|
|
|
|
if (restart) {
|
|
anim_timer_start = timer_get_milliseconds();
|
|
}
|
|
|
|
ship_info* sip = &Ship_info[idx];
|
|
|
|
if (effect == -1) {
|
|
effect = sip->selection_effect;
|
|
}
|
|
|
|
float rev_rate = REVOLUTION_RATE;
|
|
if (sip->is_big_ship()) {
|
|
rev_rate *= 1.7f;
|
|
}
|
|
if (sip->is_huge_ship()) {
|
|
rev_rate *= 3.0f;
|
|
}
|
|
|
|
int modelNum = model_load(sip->pof_file, sip->n_subsystems, &sip->subsystems[0]);
|
|
static float ShipRot = 0.0f;
|
|
|
|
model_render_params render_info;
|
|
|
|
if (sip->uses_team_colors) {
|
|
render_info.set_team_color(sip->default_team_name, "none", 0, 0);
|
|
}
|
|
|
|
if (sip->replacement_textures.size() > 0) {
|
|
render_info.set_replacement_textures(modelNum, sip->replacement_textures);
|
|
}
|
|
|
|
draw_model_rotating(&render_info,
|
|
modelNum,
|
|
x1,
|
|
y1,
|
|
x2,
|
|
y2,
|
|
&ShipRot,
|
|
&sip->closeup_pos,
|
|
sip->closeup_zoom * zoom,
|
|
rev_rate,
|
|
MR_AUTOCENTER | MR_NO_FOGGING,
|
|
GR_RESIZE_NONE,
|
|
effect);
|
|
|
|
return ade_set_args(L, "b", true);
|
|
}
|
|
|
|
ADE_FUNC(renderOverheadModel,
|
|
l_Shipclass,
|
|
"number x, number y, [number width = 467, number height = 362, number|table /* selectedSlot = -1 or empty table */, number selectedWeapon = -1, number hoverSlot = -1, "
|
|
"number bank1_x = 170, number bank1_y = 203, number bank2_x = 170, number bank2_y = 246, number bank3_x = 170, number bank3_y = 290, "
|
|
"number bank4_x = 552, number bank4_y = 203, number bank5_x = 552, number bank5_y = 246, number bank6_x = 552, number bank6_y = 290, "
|
|
"number bank7_x = 552, number bank7_y = 333, number style = 0]",
|
|
"Draws the 3D overhead ship model with the lines pointing from bank weapon selections to bank firepoints. SelectedSlot refers to loadout "
|
|
"ship slots 1-12 where wing 1 is 1-4, wing 2 is 5-8, and wing 3 is 9-12. SelectedWeapon is the index into weapon classes. HoverSlot refers "
|
|
"to the bank slots 1-7 where 1-3 are primaries and 4-6 are secondaries. Lines will be drawn from any bank containing the SelectedWeapon to "
|
|
"the firepoints on the model of that bank. Similarly, lines will be drawn from the bank defined by HoverSlot to the firepoints on the model "
|
|
"of that slot. Line drawing for HoverSlot takes precedence over line drawing for SelectedWeapon. Set either or both to -1 to stop line drawing. "
|
|
"The bank coordinates are the coordinates from which the lines for that bank will be drawn. It is expected that primary slots will be on the "
|
|
"left of the ship model and secondaries will be on the right. The lines have a hard-coded curve expecing to be drawn from those directions. "
|
|
"Style can be 0 or 1. 0 for the ship to be drawn stationary from top down, 1 for the ship to be rotating.",
|
|
"boolean",
|
|
"true if rendered, false if error")
|
|
{
|
|
int idx;
|
|
int x1;
|
|
int y1;
|
|
int x2 = 467;
|
|
int y2 = 362;
|
|
int selectedSlot = -1;
|
|
auto weapon_table = luacpp::LuaTable::create(L);
|
|
int selectedWeapon = -1;
|
|
int hoverSlot = -1;
|
|
|
|
//Bank coords
|
|
int bank1_x = 170;
|
|
int bank1_y = 203;
|
|
int bank2_x = 170;
|
|
int bank2_y = 246;
|
|
int bank3_x = 170;
|
|
int bank3_y = 290;
|
|
int bank4_x = 552;
|
|
int bank4_y = 203;
|
|
int bank5_x = 552;
|
|
int bank5_y = 246;
|
|
int bank6_x = 552;
|
|
int bank6_y = 290;
|
|
int bank7_x = 552;
|
|
int bank7_y = 333;
|
|
int style = 0;
|
|
|
|
int weapon_list[MAX_SHIP_WEAPONS] = {-1, -1, -1, -1, -1, -1, -1};
|
|
|
|
if (lua_isnumber(L, 6)) {
|
|
|
|
if (!ade_get_args(L,
|
|
"oii|iiiiiiiiiiiiiiiiiiii",
|
|
l_Shipclass.Get(&idx),
|
|
&x1,
|
|
&y1,
|
|
&x2,
|
|
&y2,
|
|
&selectedSlot,
|
|
&selectedWeapon,
|
|
&hoverSlot,
|
|
&bank1_x,
|
|
&bank1_y,
|
|
&bank2_x,
|
|
&bank2_y,
|
|
&bank3_x,
|
|
&bank3_y,
|
|
&bank4_x,
|
|
&bank4_y,
|
|
&bank5_x,
|
|
&bank5_y,
|
|
&bank6_x,
|
|
&bank6_y,
|
|
&bank7_x,
|
|
&bank7_y,
|
|
&style))
|
|
return ADE_RETURN_NIL;
|
|
|
|
// Convert this from the Lua index
|
|
selectedSlot--;
|
|
|
|
if (selectedSlot < 0)
|
|
return ADE_RETURN_FALSE;
|
|
|
|
for (int i = 0; i < (MAX_SHIP_WEAPONS); i++) {
|
|
weapon_list[i] = Wss_slots[selectedSlot].wep[i];
|
|
}
|
|
} else {
|
|
if (!ade_get_args(L,
|
|
"oii|iitiiiiiiiiiiiiiiiii",
|
|
l_Shipclass.Get(&idx),
|
|
&x1,
|
|
&y1,
|
|
&x2,
|
|
&y2,
|
|
&weapon_table,
|
|
&selectedWeapon,
|
|
&hoverSlot,
|
|
&bank1_x,
|
|
&bank1_y,
|
|
&bank2_x,
|
|
&bank2_y,
|
|
&bank3_x,
|
|
&bank3_y,
|
|
&bank4_x,
|
|
&bank4_y,
|
|
&bank5_x,
|
|
&bank5_y,
|
|
&bank6_x,
|
|
&bank6_y,
|
|
&bank7_x,
|
|
&bank7_y,
|
|
&style))
|
|
return ADE_RETURN_NIL;
|
|
|
|
int count = 0;
|
|
if (weapon_table.isValid()) {
|
|
for (const auto& item : weapon_table) {
|
|
if (item.second.is(luacpp::ValueType::NUMBER)) {
|
|
// This'll lua-error internally if it's not fed only numbers. Additionally, catch the lua exception
|
|
// and then carry on
|
|
try {
|
|
int wep = item.second.getValue<int>();
|
|
wep--; // convert from the lua index
|
|
weapon_list[count++] = wep;
|
|
} catch (const luacpp::LuaException& /*e*/) {
|
|
// We were likely fed a userdata that was not a number.
|
|
// Since we can't actually tell whether that's the case before we try to get the value, and the
|
|
// attempt to get the value is printing a LuaError itself, just eat the exception here and
|
|
// return
|
|
return ADE_RETURN_FALSE;
|
|
}
|
|
} else {
|
|
// This happens on a non-userdata value, i.e. a string
|
|
LuaError(L, "Weapon index table contained non-number values! Aborting...");
|
|
return ADE_RETURN_FALSE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (idx < 0 || idx >= ship_info_size())
|
|
return ade_set_args(L, "b", false);
|
|
|
|
//Convert these from Lua indecies
|
|
selectedWeapon--;
|
|
hoverSlot--;
|
|
|
|
if ((style < 0) || (style > 1))
|
|
LuaError(L, "Overhead style can only be 0 or 1!");
|
|
|
|
if (selectedWeapon < 0 || selectedWeapon >= weapon_info_size())
|
|
selectedWeapon = -1;
|
|
|
|
if (hoverSlot < 0 || hoverSlot >= (MAX_SHIP_PRIMARY_BANKS + MAX_SHIP_SECONDARY_BANKS))
|
|
hoverSlot = -1;
|
|
|
|
ship_info* sip = &Ship_info[idx];
|
|
|
|
int modelNum = model_load(sip->pof_file, sip->n_subsystems, &sip->subsystems[0]);
|
|
model_page_in_textures(modelNum, idx);
|
|
static float ShipRot = 0.0f;
|
|
|
|
draw_3d_overhead_view(modelNum,
|
|
idx,
|
|
&ShipRot,
|
|
flFrametime,
|
|
weapon_list,
|
|
selectedWeapon,
|
|
hoverSlot,
|
|
x1,
|
|
y1,
|
|
x2,
|
|
y2,
|
|
GR_RESIZE_NONE,
|
|
bank1_x,
|
|
bank1_y,
|
|
bank2_x,
|
|
bank2_y,
|
|
bank3_x,
|
|
bank3_y,
|
|
bank4_x,
|
|
bank4_y,
|
|
bank5_x,
|
|
bank5_y,
|
|
bank6_x,
|
|
bank6_y,
|
|
bank7_x,
|
|
bank7_y,
|
|
0,
|
|
0,
|
|
0,
|
|
(overhead_style)style);
|
|
|
|
return ade_set_args(L, "b", true);
|
|
}
|
|
|
|
ADE_FUNC(isModelLoaded, l_Shipclass, "[boolean Load = false]", "Checks if the model used for this shipclass is loaded or not and optionally loads the model, which might be a slow operation.", "boolean", "If the model is loaded or not")
|
|
{
|
|
int idx;
|
|
bool load_check = false;
|
|
if(!ade_get_args(L, "o|b", l_Shipclass.Get(&idx), &load_check))
|
|
return ADE_RETURN_FALSE;
|
|
|
|
ship_info *sip = &Ship_info[idx];
|
|
|
|
if (sip == NULL)
|
|
return ADE_RETURN_FALSE;
|
|
|
|
if(load_check){
|
|
sip->model_num = model_load(sip->pof_file, sip->n_subsystems, &sip->subsystems[0]);
|
|
}
|
|
|
|
if (sip->model_num > -1)
|
|
return ADE_RETURN_TRUE;
|
|
else
|
|
return ADE_RETURN_FALSE;
|
|
}
|
|
|
|
ADE_FUNC(isPlayerAllowed,
|
|
l_Shipclass,
|
|
nullptr,
|
|
"Detects whether the ship has the player allowed flag",
|
|
"boolean",
|
|
"true if player allowed, false otherwise, 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;
|
|
|
|
ship_info* sip = &Ship_info[idx];
|
|
|
|
if (sip->flags[Ship::Info_Flags::Player_ship]) {
|
|
return ADE_RETURN_TRUE;
|
|
}
|
|
|
|
return ADE_RETURN_FALSE;
|
|
}
|
|
|
|
ADE_FUNC(getShipClassIndex, l_Shipclass, nullptr, "Gets the index value of the ship class", "number", "index value of the ship class")
|
|
{
|
|
int idx;
|
|
if(!ade_get_args(L, "o", l_Shipclass.Get(&idx)))
|
|
return ade_set_args(L, "i", -1);
|
|
|
|
if(idx < 0 || idx >= ship_info_size())
|
|
return ade_set_args(L, "i", -1);
|
|
|
|
return ade_set_args(L, "i", idx + 1); // Lua is 1-based
|
|
}
|
|
|
|
|
|
}
|
|
}
|