mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-10 12:41:35 -10:00
438 lines
13 KiB
C++
438 lines
13 KiB
C++
//
|
|
//
|
|
|
|
#include "ship_bank.h"
|
|
#include "weaponclass.h"
|
|
#include "weapon/weapon.h"
|
|
|
|
|
|
namespace scripting {
|
|
namespace api {
|
|
|
|
ship_banktype_h::ship_banktype_h() : object_h () {
|
|
sw = NULL;
|
|
type = SWH_NONE;
|
|
}
|
|
ship_banktype_h::ship_banktype_h(object* objp_in, ship_weapon* wpn, int in_type) : object_h(objp_in) {
|
|
sw = wpn;
|
|
type = in_type;
|
|
}
|
|
bool ship_banktype_h::IsValid() {
|
|
return object_h::IsValid() && sw != NULL && (type == SWH_PRIMARY || type == SWH_SECONDARY || type == SWH_TERTIARY);
|
|
}
|
|
|
|
//**********HANDLE: Weaponbanktype
|
|
ADE_OBJ(l_WeaponBankType, ship_banktype_h, "weaponbanktype", "Ship/subsystem weapons bank type handle");
|
|
|
|
ADE_INDEXER(l_WeaponBankType, "number Index", "Array of weapon banks", "weaponbank", "Weapon bank, or invalid handle on failure")
|
|
{
|
|
ship_banktype_h *sb=NULL;
|
|
int idx = -1;
|
|
ship_bank_h *newbank = nullptr;
|
|
if(!ade_get_args(L, "oi|o", l_WeaponBankType.GetPtr(&sb), &idx, l_WeaponBank.GetPtr(&newbank)))
|
|
return ade_set_error(L, "o", l_WeaponBank.Set(ship_bank_h()));
|
|
|
|
if(!sb->IsValid())
|
|
return ade_set_error(L, "o", l_WeaponBank.Set(ship_bank_h()));
|
|
|
|
switch(sb->type)
|
|
{
|
|
case SWH_PRIMARY:
|
|
if(idx < 1 || idx > sb->sw->num_primary_banks)
|
|
return ade_set_error(L, "o", l_WeaponBank.Set(ship_bank_h()));
|
|
|
|
idx--; //Lua->FS2
|
|
|
|
if(ADE_SETTING_VAR && newbank && newbank->IsValid()) {
|
|
sb->sw->primary_bank_weapons[idx] = newbank->sw->primary_bank_weapons[idx];
|
|
sb->sw->next_primary_fire_stamp[idx] = timestamp(0);
|
|
sb->sw->primary_bank_ammo[idx] = newbank->sw->primary_bank_ammo[idx];
|
|
sb->sw->primary_bank_start_ammo[idx] = newbank->sw->primary_bank_start_ammo[idx];
|
|
sb->sw->primary_bank_capacity[idx] = newbank->sw->primary_bank_capacity[idx];
|
|
sb->sw->primary_bank_rearm_time[idx] = timestamp(0);
|
|
}
|
|
break;
|
|
case SWH_SECONDARY:
|
|
if(idx < 1 || idx > sb->sw->num_secondary_banks)
|
|
return ade_set_error(L, "o", l_WeaponBank.Set(ship_bank_h()));
|
|
|
|
idx--; //Lua->FS2
|
|
|
|
if(ADE_SETTING_VAR && newbank && newbank->IsValid()) {
|
|
sb->sw->primary_bank_weapons[idx] = newbank->sw->primary_bank_weapons[idx];
|
|
sb->sw->next_primary_fire_stamp[idx] = timestamp(0);
|
|
sb->sw->primary_bank_ammo[idx] = newbank->sw->primary_bank_ammo[idx];
|
|
sb->sw->primary_bank_start_ammo[idx] = newbank->sw->primary_bank_start_ammo[idx];
|
|
sb->sw->primary_bank_capacity[idx] = newbank->sw->primary_bank_capacity[idx];
|
|
}
|
|
break;
|
|
case SWH_TERTIARY:
|
|
if(idx < 1 || idx > sb->sw->num_tertiary_banks)
|
|
return ade_set_error(L, "o", l_WeaponBank.Set(ship_bank_h()));
|
|
|
|
idx--; //Lua->FS2
|
|
|
|
if(ADE_SETTING_VAR && newbank && newbank->IsValid()) {
|
|
Error(LOCATION, "Tertiary bank support is still in progress");
|
|
//WMC: TODO
|
|
}
|
|
break;
|
|
default:
|
|
return ade_set_error(L, "o", l_WeaponBank.Set(ship_bank_h())); //Invalid type
|
|
}
|
|
|
|
return ade_set_args(L, "o", l_WeaponBank.Set(ship_bank_h(sb->objp, sb->sw, sb->type, idx)));
|
|
}
|
|
|
|
ADE_VIRTVAR(Linked, l_WeaponBankType, "boolean", "Whether bank is in linked or unlinked fire mode (Primary-only)", "boolean", "Link status, or false if handle is invalid")
|
|
{
|
|
ship_banktype_h *bh;
|
|
bool newlink = false;
|
|
int numargs = ade_get_args(L, "o|b", l_WeaponBankType.GetPtr(&bh), &newlink);
|
|
|
|
if(!numargs)
|
|
return ade_set_error(L, "b", false);
|
|
|
|
if(!bh->IsValid())
|
|
return ade_set_error(L, "b", false);
|
|
|
|
switch(bh->type)
|
|
{
|
|
case SWH_PRIMARY:
|
|
if(ADE_SETTING_VAR && numargs > 1) {
|
|
Ships[bh->objp->instance].flags.set(Ship::Ship_Flags::Primary_linked, newlink);
|
|
}
|
|
|
|
return ade_set_args(L, "b", (Ships[bh->objp->instance].flags[Ship::Ship_Flags::Primary_linked]));
|
|
|
|
case SWH_SECONDARY:
|
|
case SWH_TERTIARY:
|
|
return ADE_RETURN_FALSE;
|
|
}
|
|
|
|
return ade_set_error(L, "b", false);
|
|
}
|
|
|
|
ADE_VIRTVAR(DualFire, l_WeaponBankType, "boolean", "Whether bank is in dual fire mode (Secondary-only)", "boolean", "Dual fire status, or false if handle is invalid")
|
|
{
|
|
ship_banktype_h *bh;
|
|
bool newfire = false;
|
|
int numargs = ade_get_args(L, "o|b", l_WeaponBankType.GetPtr(&bh), &newfire);
|
|
|
|
if(!numargs)
|
|
return ade_set_error(L, "b", false);
|
|
|
|
if(!bh->IsValid())
|
|
return ade_set_error(L, "b", false);
|
|
|
|
switch(bh->type)
|
|
{
|
|
case SWH_SECONDARY:
|
|
if(ADE_SETTING_VAR && numargs > 1) {
|
|
Ships[bh->objp->instance].flags.set(Ship::Ship_Flags::Secondary_dual_fire, newfire);
|
|
}
|
|
|
|
return ade_set_args(L, "b", (Ships[bh->objp->instance].flags[Ship::Ship_Flags::Secondary_dual_fire]));
|
|
|
|
case SWH_PRIMARY:
|
|
case SWH_TERTIARY:
|
|
return ADE_RETURN_FALSE;
|
|
}
|
|
|
|
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;
|
|
if(!ade_get_args(L, "o", l_WeaponBankType.GetPtr(&sb)))
|
|
return ade_set_error(L, "i", 0);
|
|
|
|
if(!sb->IsValid())
|
|
return ade_set_error(L, "i", 0);
|
|
|
|
switch(sb->type)
|
|
{
|
|
case SWH_PRIMARY:
|
|
return ade_set_args(L, "i", sb->sw->num_primary_banks);
|
|
case SWH_SECONDARY:
|
|
return ade_set_args(L, "i", sb->sw->num_secondary_banks);
|
|
case SWH_TERTIARY:
|
|
return ade_set_args(L, "i", sb->sw->num_tertiary_banks);
|
|
default:
|
|
return ade_set_error(L, "i", 0); //Invalid type
|
|
}
|
|
}
|
|
|
|
|
|
//**********HANDLE: Weaponbank
|
|
ADE_OBJ(l_WeaponBank, ship_bank_h, "weaponbank", "Ship/subystem weapons bank handle");
|
|
|
|
ship_bank_h::ship_bank_h() : ship_banktype_h() {
|
|
bank = -1;
|
|
}
|
|
ship_bank_h::ship_bank_h(object* objp_in, ship_weapon* wpn, int in_type, int in_bank) : ship_banktype_h(objp_in, wpn, in_type) {
|
|
bank = in_bank;
|
|
}
|
|
bool ship_bank_h::IsValid() {
|
|
if(!ship_banktype_h::IsValid())
|
|
return false;
|
|
|
|
if(bank < 0)
|
|
return false;
|
|
|
|
if(type == SWH_PRIMARY && bank >= sw->num_primary_banks)
|
|
return false;
|
|
if(type == SWH_SECONDARY && bank >= sw->num_secondary_banks)
|
|
return false;
|
|
if(type == SWH_TERTIARY && bank >= sw->num_tertiary_banks)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
ADE_VIRTVAR(WeaponClass, l_WeaponBank, "weaponclass", "Class of weapon mounted in the bank", "weaponclass", "Weapon class, or an invalid weaponclass handle if bank handle is invalid")
|
|
{
|
|
ship_bank_h *bh = NULL;
|
|
int weaponclass=-1;
|
|
if(!ade_get_args(L, "o|o", l_WeaponBank.GetPtr(&bh), l_Weaponclass.Get(&weaponclass)))
|
|
return ade_set_error(L, "o", l_Weaponclass.Set(-1));
|
|
|
|
if(!bh->IsValid())
|
|
return ade_set_error(L, "o", l_Weaponclass.Set(-1));
|
|
|
|
switch(bh->type)
|
|
{
|
|
case SWH_PRIMARY:
|
|
if(ADE_SETTING_VAR && weaponclass > -1) {
|
|
bh->sw->primary_bank_weapons[bh->bank] = weaponclass;
|
|
}
|
|
|
|
return ade_set_args(L, "o", l_Weaponclass.Set(bh->sw->primary_bank_weapons[bh->bank]));
|
|
case SWH_SECONDARY:
|
|
if(ADE_SETTING_VAR && weaponclass > -1) {
|
|
bh->sw->secondary_bank_weapons[bh->bank] = weaponclass;
|
|
}
|
|
|
|
return ade_set_args(L, "o", l_Weaponclass.Set(bh->sw->secondary_bank_weapons[bh->bank]));
|
|
case SWH_TERTIARY:
|
|
if(ADE_SETTING_VAR && weaponclass > -1) {
|
|
//bh->sw->tertiary_bank_weapons[bh->bank] = weaponclass;
|
|
}
|
|
|
|
// return ade_set_args(L, "o", l_Weaponclass.Set(bh->sw->tertiary_bank_weapons[bh->bank]));
|
|
// Error(LOCATION, "Tertiary bank support is still in progress");
|
|
// WMC: TODO
|
|
return ADE_RETURN_FALSE;
|
|
}
|
|
|
|
return ade_set_error(L, "o", l_Weaponclass.Set(-1));
|
|
}
|
|
|
|
ADE_VIRTVAR(AmmoLeft, l_WeaponBank, "number", "Ammo left for the current bank", "number", "Ammo left, or 0 if handle is invalid")
|
|
{
|
|
ship_bank_h *bh = NULL;
|
|
int ammo;
|
|
if(!ade_get_args(L, "o|i", l_WeaponBank.GetPtr(&bh), &ammo))
|
|
return ade_set_error(L, "i", 0);
|
|
|
|
if(!bh->IsValid())
|
|
return ade_set_error(L, "i", 0);
|
|
|
|
switch(bh->type)
|
|
{
|
|
case SWH_PRIMARY:
|
|
if(ADE_SETTING_VAR && ammo > -1) {
|
|
bh->sw->primary_bank_ammo[bh->bank] = ammo;
|
|
}
|
|
|
|
return ade_set_args(L, "i", bh->sw->primary_bank_ammo[bh->bank]);
|
|
case SWH_SECONDARY:
|
|
if(ADE_SETTING_VAR && ammo > -1) {
|
|
bh->sw->secondary_bank_ammo[bh->bank] = ammo;
|
|
}
|
|
|
|
return ade_set_args(L, "i", bh->sw->secondary_bank_ammo[bh->bank]);
|
|
case SWH_TERTIARY:
|
|
if(ADE_SETTING_VAR && ammo > -1) {
|
|
bh->sw->tertiary_bank_ammo = ammo;
|
|
}
|
|
return ade_set_args(L, "i", bh->sw->tertiary_bank_ammo);
|
|
}
|
|
|
|
return ade_set_error(L, "i", 0);
|
|
}
|
|
|
|
ADE_VIRTVAR(AmmoMax, l_WeaponBank, "number", "Maximum ammo for the current bank<br>"
|
|
"<b>Note:</b> Setting this value actually sets the <i>capacity</i> of the weapon bank. To set the actual maximum ammunition use <tt>AmmoMax = <amount> * class.CargoSize</tt>", "number", "Ammo capacity, or 0 if handle is invalid")
|
|
{
|
|
ship_bank_h *bh = NULL;
|
|
int ammomax;
|
|
if(!ade_get_args(L, "o|i", l_WeaponBank.GetPtr(&bh), &ammomax))
|
|
return ade_set_error(L, "i", 0);
|
|
|
|
if(!bh->IsValid())
|
|
return ade_set_error(L, "i", 0);
|
|
|
|
switch(bh->type)
|
|
{
|
|
case SWH_PRIMARY:
|
|
{
|
|
if(ADE_SETTING_VAR && ammomax > -1) {
|
|
bh->sw->primary_bank_capacity[bh->bank] = ammomax;
|
|
}
|
|
|
|
int weapon_class = bh->sw->primary_bank_weapons[bh->bank];
|
|
|
|
Assert(bh->objp->type == OBJ_SHIP);
|
|
|
|
return ade_set_args(L, "i", get_max_ammo_count_for_primary_bank(Ships[bh->objp->instance].ship_info_index, bh->bank, weapon_class));
|
|
}
|
|
case SWH_SECONDARY:
|
|
{
|
|
if(ADE_SETTING_VAR && ammomax > -1) {
|
|
bh->sw->secondary_bank_capacity[bh->bank] = ammomax;
|
|
}
|
|
|
|
int weapon_class = bh->sw->secondary_bank_weapons[bh->bank];
|
|
|
|
Assert(bh->objp->type == OBJ_SHIP);
|
|
|
|
return ade_set_args(L, "i", get_max_ammo_count_for_bank(Ships[bh->objp->instance].ship_info_index, bh->bank, weapon_class));
|
|
}
|
|
case SWH_TERTIARY:
|
|
if(ADE_SETTING_VAR && ammomax > -1) {
|
|
bh->sw->tertiary_bank_capacity = ammomax;
|
|
}
|
|
|
|
return ade_set_args(L, "i", bh->sw->tertiary_bank_capacity);
|
|
}
|
|
|
|
return ade_set_error(L, "i", 0);
|
|
}
|
|
|
|
ADE_VIRTVAR(Armed, l_WeaponBank, "boolean", "Weapon armed status. Does not take linking into account.", "boolean", "True if armed, false if unarmed or handle is invalid")
|
|
{
|
|
ship_bank_h *bh = NULL;
|
|
bool armthis=false;
|
|
if(!ade_get_args(L, "o|b", l_WeaponBank.GetPtr(&bh), &armthis))
|
|
return ade_set_error(L, "b", false);
|
|
|
|
if(!bh->IsValid())
|
|
return ade_set_error(L, "b", false);
|
|
|
|
int new_armed_bank = -1;
|
|
if(armthis)
|
|
new_armed_bank = bh->bank;
|
|
|
|
switch(bh->type)
|
|
{
|
|
case SWH_PRIMARY:
|
|
if(ADE_SETTING_VAR) {
|
|
bh->sw->current_primary_bank = new_armed_bank;
|
|
}
|
|
return ade_set_args(L, "b", bh->sw->current_primary_bank == bh->bank);
|
|
case SWH_SECONDARY:
|
|
if(ADE_SETTING_VAR) {
|
|
bh->sw->current_secondary_bank = new_armed_bank;
|
|
}
|
|
return ade_set_args(L, "b", bh->sw->current_secondary_bank == bh->bank);
|
|
case SWH_TERTIARY:
|
|
if(ADE_SETTING_VAR) {
|
|
bh->sw->current_tertiary_bank = new_armed_bank;
|
|
}
|
|
return ade_set_args(L, "b", bh->sw->current_tertiary_bank == bh->bank);
|
|
}
|
|
|
|
return ade_set_error(L, "b", false);
|
|
}
|
|
|
|
ADE_VIRTVAR(Capacity, l_WeaponBank, "number", "The actual capacity of a weapon bank as specified in the table", "number", "The capacity or -1 if handle is invalid")
|
|
{
|
|
ship_bank_h *bh = NULL;
|
|
int newCapacity = -1;
|
|
if(!ade_get_args(L, "o|i", l_WeaponBank.GetPtr(&bh), &newCapacity))
|
|
return ade_set_error(L, "i", -1);
|
|
|
|
if(!bh->IsValid())
|
|
return ade_set_error(L, "i", -1);
|
|
|
|
switch(bh->type)
|
|
{
|
|
case SWH_PRIMARY:
|
|
if(ADE_SETTING_VAR && newCapacity > 0) {
|
|
bh->sw->primary_bank_capacity[bh->bank] = newCapacity;
|
|
}
|
|
return ade_set_args(L, "i", bh->sw->primary_bank_capacity[bh->bank]);
|
|
case SWH_SECONDARY:
|
|
if(ADE_SETTING_VAR && newCapacity > 0) {
|
|
bh->sw->secondary_bank_capacity[bh->bank] = newCapacity;
|
|
}
|
|
return ade_set_args(L, "i", bh->sw->secondary_bank_capacity[bh->bank]);
|
|
case SWH_TERTIARY:
|
|
if(ADE_SETTING_VAR && newCapacity > 0) {
|
|
bh->sw->tertiary_bank_capacity = newCapacity;
|
|
}
|
|
return ade_set_args(L, "i", bh->sw->tertiary_bank_capacity);
|
|
}
|
|
|
|
return ade_set_error(L, "i", -1);
|
|
}
|
|
|
|
ADE_VIRTVAR(FOFCooldown, l_WeaponBank, "number", "The FOF cooldown value. A value of 0 means the default weapon FOF is used. A value of 1 means that the max FOF will be used", "number", "The cooldown value or -1 if invalid")
|
|
{
|
|
ship_bank_h *bh = NULL;
|
|
float newValue = -1.f;
|
|
if(!ade_get_args(L, "o|i", l_WeaponBank.GetPtr(&bh), &newValue))
|
|
return ade_set_error(L, "f", -1.f);
|
|
|
|
if(!bh->IsValid())
|
|
return ade_set_error(L, "f", -1.f);
|
|
|
|
if (ADE_SETTING_VAR) {
|
|
LuaError(L, "This function does not support setting values yet!");
|
|
return ade_set_error(L, "f", -1.f);
|
|
}
|
|
|
|
switch(bh->type)
|
|
{
|
|
case SWH_PRIMARY:
|
|
{
|
|
auto wif = &Weapon_info[bh->sw->primary_bank_weapons[bh->bank]];
|
|
float reset_amount = (timestamp_until(bh->sw->last_primary_fire_stamp[bh->bank]) / 1000.0f) * wif->fof_reset_rate;
|
|
auto val = bh->sw->primary_bank_fof_cooldown[bh->bank] + reset_amount;
|
|
CLAMP(val, 0.0f, 1.0f);
|
|
return ade_set_args(L, "f", val);
|
|
}
|
|
case SWH_SECONDARY:
|
|
case SWH_TERTIARY:
|
|
LuaError(L, "FOF cooldown is not valid for secondary or tertiary banks!");
|
|
return ade_set_args(L, "f", -1.f);
|
|
}
|
|
|
|
return ade_set_error(L, "f", -1.f);
|
|
}
|
|
|
|
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());
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
|