mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-09 04:49:39 -10:00
* Measure afterburner cooldowns on the mission clock afterburners_start()/afterburners_stop() timed the +Aburn Cooldown Time delay and the player's 1.3 s re-engage delay with timer_get_milliseconds(), the real clock. Under time compression a cooldown therefore lasted longer in mission time than the table says, and it kept running while the game was paused. The cooldown was added in 2020 and reused the retail re-engage check's real-clock "now"; the rest of the file (ABURN_DECAY_TIME, the sound timers) already uses mission timestamps. Both delays now use the mission clock. The mission clock does not run outside missions, so it can still be near zero when the first mission of a session starts; the "last stopped" and "last started" times therefore start out invalid instead of 0, so that no delay is in effect before the afterburner has been used. Without time compression or pausing, the delays behave as before. * Drop stale afterburner comment and use fl2i for the cooldown cast The comment described an earlier startup state rather than the current behavior. fl2i is the project's float-to-int macro and truncates the same way the old C-style cast did. * Remove the remaining afterburner cooldown comment Timestamps running on mission time is the common case, so it doesn't need a comment.
2282 lines
93 KiB
C++
2282 lines
93 KiB
C++
/*
|
|
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
|
*
|
|
* All source code herein is the property of Volition, Inc. You may not sell
|
|
* or otherwise commercially exploit the source or things you created based on the
|
|
* source.
|
|
*
|
|
*/
|
|
|
|
#ifndef _SHIP_H
|
|
#define _SHIP_H
|
|
|
|
#include "ai/ai.h"
|
|
#include "fireball/fireballs.h"
|
|
#include "globalincs/globals.h" // for defintions of token lengths -- maybe move this elsewhere later (Goober5000 - moved to globals.h)
|
|
#include "globalincs/pstypes.h"
|
|
#include "graphics/2d.h" // for color def
|
|
#include "hud/hud.h"
|
|
#include "hud/hudparse.h"
|
|
#include "model/model.h"
|
|
#include "model/animation/modelanimation.h"
|
|
#include "network/multi_obj.h"
|
|
#include "radar/radarsetup.h"
|
|
#include "render/3d.h"
|
|
#include "species_defs/species_defs.h"
|
|
#include "weapon/shockwave.h"
|
|
#include "weapon/trails.h"
|
|
#include "ship/anchor_t.h"
|
|
#include "ship/ship_flags.h"
|
|
#include "utils/reset_on_move.h"
|
|
#include "weapon/weapon_flags.h"
|
|
#include "weapon/weapon.h"
|
|
#include "ai/ai.h"
|
|
|
|
#include <string>
|
|
#include <set>
|
|
#include <optional>
|
|
#include <particle/ParticleManager.h>
|
|
|
|
class object;
|
|
class WarpEffect;
|
|
|
|
// Part of the player died system.
|
|
extern vec3d Original_vec_to_deader;
|
|
|
|
// States for player death sequence, stuffed in Player_died_state.
|
|
#define PDS_NONE 1
|
|
#define PDS_DIED 2
|
|
#define PDS_EJECTED 3
|
|
|
|
#define SHIP_GUARDIAN_THRESHOLD_DEFAULT 1 // Goober5000
|
|
|
|
#define HULL_DAMAGE_THRESHOLD_PERCENT 0.25f // Apply damage to hull, not shield if shield < this
|
|
|
|
// the #defines below are to avoid round-off errors
|
|
#define WEAPON_RESERVE_THRESHOLD 0.01f // energy threshold where ship is considered to have no weapon energy system
|
|
#define SUBSYS_MAX_HITS_THRESHOLD 0.01f // max_hits threshold where subsys is considered to take damage
|
|
|
|
#define MAX_SHIP_SPARKS 8 // maximum number of spark emitters on a ship
|
|
#define MAX_SHIP_DETAIL_LEVELS 5 // maximum detail levels that a ship can render at
|
|
|
|
|
|
// defines for 'direction' parameter of ship_select_next_primary()
|
|
enum class CycleDirection { NEXT, PREV };
|
|
|
|
#define BANK_1 0
|
|
#define BANK_2 1
|
|
#define BANK_3 2
|
|
#define BANK_4 3
|
|
#define BANK_5 4
|
|
#define BANK_6 5
|
|
#define BANK_7 6
|
|
#define BANK_8 7
|
|
#define BANK_9 8
|
|
|
|
#define TYPE_ATTACK_PROTECT 0
|
|
#define TYPE_REPAIR_REARM 1
|
|
|
|
#define MAX_REINFORCEMENT_MESSAGES 5
|
|
|
|
#define RF_IS_AVAILABLE (1<<0) // reinforcement is now available
|
|
|
|
struct reinforcements {
|
|
char name[NAME_LENGTH]; // ship or wing name (ship and wing names don't collide)
|
|
int type; // what operations this reinforcement unit can perform
|
|
int uses; // number of times reinforcemnt unit can be used
|
|
int num_uses; // number of times this reinforcement was actually used
|
|
int arrival_delay; // how long after called does this reinforcement appear
|
|
int flags;
|
|
char no_messages[MAX_REINFORCEMENT_MESSAGES][NAME_LENGTH]; // list of messages to possibly send when calling for reinforcement not available
|
|
char yes_messages[MAX_REINFORCEMENT_MESSAGES][NAME_LENGTH]; // list of messages to acknowledge reinforcement on the way
|
|
|
|
reinforcements(const char *reinforcement_name = nullptr);
|
|
};
|
|
|
|
// Per-bank state for a weapon's external model - the model rendered at the bank's firing
|
|
// points when the ship enables $Show Primary Models: / $Show Secondary Models:.
|
|
struct external_weapon_state
|
|
{
|
|
int model_instance = -1; // model instance used to spin Gun_rotation submodels, or -1 if the weapon doesn't need one
|
|
int model_instance_weapon = -1; // the weapon the model instance state was created for, or -1 if not yet checked
|
|
int fp_counter = 0; // cycles through the model's firing points, for "chain external model fps" weapons
|
|
float rotate_rate = 0.0f; // current spin rate of the model's Gun_rotation submodels (primaries only)
|
|
float rotate_ang = 0.0f; // current spin angle of the model's Gun_rotation submodels (primaries only)
|
|
bool spin_up_requested = false; // set each frame the bank tries to fire; consumed by update_external_weapon_spin()
|
|
};
|
|
|
|
class ship_weapon {
|
|
public:
|
|
int num_primary_banks; // Number of primary banks (same as model)
|
|
int num_secondary_banks; // Number of secondary banks (same as model)
|
|
int num_tertiary_banks;
|
|
|
|
int primary_bank_weapons[MAX_SHIP_PRIMARY_BANKS]; // Weapon_info[] index for the weapon in the bank
|
|
int secondary_bank_weapons[MAX_SHIP_SECONDARY_BANKS]; // Weapon_info[] index for the weapon in the bank
|
|
|
|
external_weapon_state primary_bank_external_weapon[MAX_SHIP_PRIMARY_BANKS];
|
|
external_weapon_state secondary_bank_external_weapon[MAX_SHIP_SECONDARY_BANKS];
|
|
|
|
int current_primary_bank; // currently selected primary bank
|
|
int current_secondary_bank; // currently selected secondary bank
|
|
int current_tertiary_bank;
|
|
|
|
int previous_primary_bank;
|
|
int previous_secondary_bank; // currently selected secondary bank
|
|
|
|
int next_primary_fire_stamp[MAX_SHIP_PRIMARY_BANKS]; // next time this primary bank can fire
|
|
int last_primary_fire_stamp[MAX_SHIP_PRIMARY_BANKS]; // last time this primary bank fired (mostly used by SEXPs)
|
|
int next_secondary_fire_stamp[MAX_SHIP_SECONDARY_BANKS]; // next time this secondary bank can fire
|
|
int last_secondary_fire_stamp[MAX_SHIP_SECONDARY_BANKS]; // last time this secondary bank fired (mostly used by SEXPs)
|
|
int next_tertiary_fire_stamp;
|
|
int last_primary_fire_sound_stamp[MAX_SHIP_PRIMARY_BANKS]; // trailing end of the last time this primary bank was fired, for purposes of timing the pre-launch sound
|
|
|
|
// ballistic primary support - by Goober5000
|
|
int primary_bank_ammo[MAX_SHIP_PRIMARY_BANKS]; // Number of missiles left in primary bank
|
|
int primary_bank_start_ammo[MAX_SHIP_PRIMARY_BANKS]; // Number of missiles starting in primary bank
|
|
int primary_bank_capacity[MAX_SHIP_PRIMARY_BANKS]; // Max number of projectiles in bank
|
|
int primary_next_slot[MAX_SHIP_PRIMARY_BANKS]; // Next slot to fire in the bank
|
|
int primary_bank_rearm_time[MAX_SHIP_PRIMARY_BANKS]; // timestamp which indicates when bank can get new projectile
|
|
// end ballistic primary support
|
|
|
|
float primary_bank_fof_cooldown[MAX_SHIP_PRIMARY_BANKS]; // SUSHI: Current FOF cooldown level for the primary weapon
|
|
|
|
// dynamic weapon linking - by RSAXVC
|
|
int primary_bank_slot_count[MAX_SHIP_PRIMARY_BANKS]; // Fire this many slots at a time
|
|
int dynamic_firing_pattern[MAX_SHIP_PRIMARY_BANKS]; // Index into ship_info's dyn_firing_patterns_allowed
|
|
// end dynamic weapon linking
|
|
|
|
int secondary_bank_ammo[MAX_SHIP_SECONDARY_BANKS]; // Number of missiles left in secondary bank
|
|
int secondary_bank_start_ammo[MAX_SHIP_SECONDARY_BANKS]; // Number of missiles starting in secondary bank -- Every time the secondary bank changes, this must change too!
|
|
int secondary_bank_capacity[MAX_SHIP_SECONDARY_BANKS]; // Max number of missiles in bank
|
|
int secondary_next_slot[MAX_SHIP_SECONDARY_BANKS]; // Next slot to fire in the bank
|
|
int secondary_bank_rearm_time[MAX_SHIP_SECONDARY_BANKS]; // timestamp which indicates when bank can get new missile
|
|
|
|
int tertiary_bank_ammo; // Number of shots left tertiary bank
|
|
int tertiary_bank_start_ammo; // Number of shots starting in tertiary bank
|
|
int tertiary_bank_capacity; // Max number of shots in bank
|
|
int tertiary_bank_rearm_time; // timestamp which indicates when bank can get new something (used for ammopod or boostpod)
|
|
|
|
int remote_detonaters_active;
|
|
int detonate_weapon_time; // time at which last fired weapon can be detonated
|
|
int ai_class;
|
|
|
|
int firing_loop_sounds[MAX_SHIP_PRIMARY_BANKS]; // objsnd indices,
|
|
// -2 is a special value used to mean 'a loop WOULD be going on right now'
|
|
// but the modder did not actually specify a loop sound
|
|
|
|
flagset<Ship::Weapon_Flags> flags;
|
|
|
|
EModelAnimationPosition primary_animation_position[MAX_SHIP_PRIMARY_BANKS];
|
|
EModelAnimationPosition secondary_animation_position[MAX_SHIP_SECONDARY_BANKS];
|
|
int primary_animation_done_time[MAX_SHIP_PRIMARY_BANKS];
|
|
int secondary_animation_done_time[MAX_SHIP_SECONDARY_BANKS];
|
|
|
|
int burst_counter[MAX_SHIP_PRIMARY_BANKS + MAX_SHIP_SECONDARY_BANKS];
|
|
int burst_seed[MAX_SHIP_PRIMARY_BANKS + MAX_SHIP_SECONDARY_BANKS]; // A random seed, recalculated only when the weapon's burst resets
|
|
|
|
SCP_vector<int> primary_firepoint_indices[MAX_SHIP_PRIMARY_BANKS]; // A list of firepoint indices which is shuffled for random fire ordering
|
|
int primary_firepoint_next_to_fire_index[MAX_SHIP_PRIMARY_BANKS]; // For cycle firing modes, keeps track of which firepoint we're on
|
|
// For randomized ones, keeps track of where we are in primary_firepoint_indices
|
|
|
|
size_t primary_bank_substitution_pattern_index[MAX_SHIP_PRIMARY_BANKS];
|
|
size_t secondary_bank_substitution_pattern_index[MAX_SHIP_SECONDARY_BANKS];
|
|
|
|
// for type5 beams, keeps track of accumulated per burst rotation, added to with each shot (or burst)
|
|
float per_burst_rot;
|
|
|
|
/**
|
|
* @brief Constructor. Calls clear()
|
|
*/
|
|
ship_weapon();
|
|
|
|
/**
|
|
* @brief Inits ship_weapon
|
|
*/
|
|
void clear();
|
|
};
|
|
|
|
//**************************************************************
|
|
//WMC - Damage type handling code
|
|
|
|
int damage_type_add(const char *name);
|
|
|
|
//**************************************************************
|
|
//WMC - Armor stuff
|
|
|
|
// Nuke: some defines for difficulty scaling type
|
|
#define ADT_DIFF_SCALE_BAD_VAL -1 // error mode
|
|
#define ADT_DIFF_SCALE_FIRST 0
|
|
#define ADT_DIFF_SCALE_LAST 1
|
|
#define ADT_DIFF_SCALE_MANUAL 2 // this is the user defined mode where the modder has to handle difficulty scaling in their calculations
|
|
|
|
// Nuke: +value: replacing constants
|
|
// these are stored as altArguments, positive values mean storage idxes and -1 means not used, anything below that is fair game
|
|
#define AT_CONSTANT_NOT_USED -1 // will probibly never get used
|
|
#define AT_CONSTANT_BAD_VAL -2 // this conveys table error to the user
|
|
#define AT_CONSTANT_BASE_DMG -3 // what the damage was at start of calculations
|
|
#define AT_CONSTANT_CURRENT_DMG -4 // what the damage currently is
|
|
#define AT_CONSTANT_DIFF_FACTOR -5 // difficulty factor (by default 0.2 (easy) to 1.0 (insane))
|
|
#define AT_CONSTANT_RANDOM -6 // number between 0 and 1 (redundant but saves a calculation)
|
|
#define AT_CONSTANT_PI -7 // because everyone likes pi
|
|
|
|
struct ArmorDamageType
|
|
{
|
|
friend class ArmorType;
|
|
private:
|
|
//Rather than make an extra struct,
|
|
//I just made two arrays
|
|
int DamageTypeIndex;
|
|
SCP_vector<int> Calculations;
|
|
SCP_vector<float> Arguments;
|
|
SCP_vector<int> altArguments; // Nuke: to facilitate optional importation of data in place of +value: tag -nuke
|
|
float shieldpierce_pct;
|
|
|
|
// piercing effect data
|
|
float piercing_start_pct;
|
|
int piercing_type;
|
|
// Nuke: difficulty scale type
|
|
int difficulty_scale_type;
|
|
|
|
public:
|
|
void clear();
|
|
};
|
|
|
|
class ArmorType
|
|
{
|
|
private:
|
|
char Name[NAME_LENGTH];
|
|
|
|
SCP_vector<ArmorDamageType> DamageTypes;
|
|
public:
|
|
ArmorType(const char* in_name);
|
|
int flags;
|
|
|
|
//Get
|
|
char *GetNamePtr(){return Name;}
|
|
bool IsName(const char* in_name) { return (stricmp(in_name, Name) == 0); }
|
|
float GetDamage(float damage_applied, int in_damage_type_idx, float diff_dmg_scale, bool is_beam);
|
|
float GetShieldPiercePCT(int damage_type_idx);
|
|
int GetPiercingType(int damage_type_idx);
|
|
float GetPiercingLimit(int damage_type_idx);
|
|
|
|
//Set
|
|
void ParseData();
|
|
};
|
|
|
|
extern SCP_vector<ArmorType> Armor_types;
|
|
|
|
// Caps how far the guarder will stray from the guarded ship while guarding it; range <= 0 removes the cap
|
|
void set_guard_range_ship(float range, int guarded_shipnum, ship* guarder_shipp);
|
|
// Returns the guarder's cap for the guarded ship, or -1 if there is none
|
|
float get_guard_range_ship(int guarded_shipnum, const ship* guarder_shipp);
|
|
// Removes the caps that all ships have for the guarded ship
|
|
void clear_guard_ranges_for_ship(int guarded_shipnum);
|
|
|
|
//**************************************************************
|
|
//WMC - Damage type handling code
|
|
|
|
typedef struct DamageTypeStruct
|
|
{
|
|
char name[NAME_LENGTH];
|
|
} DamageTypeStruct;
|
|
|
|
extern SCP_vector<DamageTypeStruct> Damage_types;
|
|
|
|
#define SAF_IGNORE_SS_ARMOR (1 << 0) // hull armor is applied regardless of the subsystem armor for hull damage
|
|
|
|
#define SADTF_PIERCING_NONE 0 // no piercing effects, no beam tooling
|
|
#define SADTF_PIERCING_DEFAULT 1 // piercing effects, beam tooling
|
|
#define SADTF_PIERCING_RETAIL 2 // no piercing effects, beam tooling
|
|
|
|
//SUSHI: Damage lightning types. SLT = Ship Lighting Type.
|
|
#define SLT_NONE 0
|
|
#define SLT_DEFAULT 1
|
|
|
|
#define NUM_TURRET_ORDER_TYPES 3
|
|
extern const char *Turret_target_order_names[NUM_TURRET_ORDER_TYPES]; //aiturret.cpp
|
|
|
|
#define NUM_TURRET_TYPES 4
|
|
extern const char* Turret_valid_types[NUM_TURRET_TYPES];
|
|
|
|
// Swifty: Cockpit displays
|
|
typedef struct cockpit_display {
|
|
int target;
|
|
int source;
|
|
int foreground;
|
|
int background;
|
|
int offset[2];
|
|
int size[2];
|
|
char name[MAX_FILENAME_LEN];
|
|
} cockpit_display;
|
|
|
|
extern bool Disable_cockpits;
|
|
extern bool Disable_cockpit_sway;
|
|
|
|
extern SCP_vector<cockpit_display> Player_displays;
|
|
|
|
typedef struct cockpit_display_info {
|
|
char name[MAX_FILENAME_LEN];
|
|
char filename[MAX_FILENAME_LEN];
|
|
char fg_filename[MAX_FILENAME_LEN];
|
|
char bg_filename[MAX_FILENAME_LEN];
|
|
int offset[2];
|
|
int size[2];
|
|
} cockpit_display_info;
|
|
|
|
// structure to keep track of ship locks
|
|
typedef struct lock_info {
|
|
object *obj;
|
|
ship_subsys *subsys;
|
|
|
|
vec3d world_pos;
|
|
|
|
int current_target_sx;
|
|
int current_target_sy;
|
|
|
|
bool locked;
|
|
int maintain_lock_count;
|
|
int indicator_x;
|
|
int indicator_y;
|
|
int indicator_start_x;
|
|
int indicator_start_y;
|
|
bool indicator_visible;
|
|
float time_to_lock;
|
|
float dist_to_lock;
|
|
int catching_up;
|
|
float catch_up_distance;
|
|
float last_dist_to_target;
|
|
double accumulated_x_pixels;
|
|
double accumulated_y_pixels;
|
|
bool need_new_start_pos;
|
|
bool target_in_lock_cone;
|
|
|
|
float lock_gauge_time_elapsed;
|
|
float lock_anim_time_elapsed;
|
|
} lock_info;
|
|
|
|
struct guard_range_entry {
|
|
float range;
|
|
int shipnum;
|
|
guard_range_entry(float _range, int _shipnum) : range(_range), shipnum(_shipnum) {}
|
|
};
|
|
|
|
// structure definition for a linked list of subsystems for a ship. Each subsystem has a pointer
|
|
// to the static data for the subsystem. The obj_subsystem data is defined and read in the model
|
|
// code. Other dynamic data (such as current_hits) should remain in this structure.
|
|
class ship_subsys
|
|
{
|
|
public:
|
|
class ship_subsys *next, *prev; // Index of next and previous objects in list.
|
|
model_subsystem *system_info; // pointer to static data for this subsystem -- see model.h for definition
|
|
|
|
int parent_objnum; // objnum of the parent ship
|
|
int parent_subsys_index; // index of this subsystem in the parent ship's linked list -- Do not access manually, use parent_subsys_index() as this may not yet be cached.
|
|
|
|
char sub_name[NAME_LENGTH]; //WMC - Name that overrides name of original
|
|
float current_hits; // current number of hits this subsystem has left.
|
|
float max_hits;
|
|
|
|
flagset<Ship::Subsystem_Flags> flags; // Goober5000
|
|
|
|
int subsys_guardian_threshold; // Goober5000
|
|
int armor_type_idx; // FUBAR
|
|
|
|
// turret info
|
|
//Important -WMC
|
|
//With the new turret code, indexes run from 0 to MAX_SHIP_WEAPONS; a value of MAX_SHIP_PRIMARY_WEAPONS
|
|
//or higher, an index into the turret weapons is considered to be an index into the secondary weapons
|
|
//for much of the code. See turret_next_weap_fire_stamp.
|
|
|
|
vec3d turret_last_fire_direction; // direction pointing last time this turret fired
|
|
int turret_next_enemy_check_stamp; // time at which to next look for a new enemy.
|
|
int turret_next_fire_stamp; // next time this turret can fire
|
|
TIMESTAMP turret_last_fired; // time when the turret last fired any weapon
|
|
int turret_enemy_objnum; // object index of ship this turret is firing upon
|
|
int turret_enemy_sig; // signature of object ship this turret is firing upon
|
|
int turret_next_fire_pos; // counter which tells us which gun position to fire from next
|
|
float turret_time_enemy_in_range; // Number of seconds enemy in view cone, accuracy improves over time.
|
|
int turret_targeting_order[NUM_TURRET_ORDER_TYPES]; //Order that turrets target different types of things.
|
|
float optimum_range;
|
|
float favor_current_facing;
|
|
ship_subsys *targeted_subsys; // subsystem this turret is attacking
|
|
bool scripting_target_override;
|
|
int last_fired_weapon_info_index; // which weapon class was last fired
|
|
int shared_fire_direction_beam_objnum; // reference beam for shared fire direction
|
|
|
|
int turret_pick_big_attack_point_timestamp; // Next time to pick an attack point for this turret
|
|
vec3d turret_big_attack_point; // local coordinate of point for this turret to attack on enemy
|
|
|
|
float turret_inaccuracy; // additional SEXP inaccuracy, field of fire degrees
|
|
|
|
EModelAnimationPosition turret_animation_position;
|
|
int turret_animation_done_time;
|
|
|
|
// swarm (rapid fire) info
|
|
int turret_swarm_info_index[MAX_TFP];
|
|
int turret_swarm_num;
|
|
|
|
// awacs info
|
|
float awacs_intensity;
|
|
float awacs_radius;
|
|
|
|
ship_weapon weapons;
|
|
|
|
// Data the renderer needs for ship instance specific data, like
|
|
// angles and if it is blown off or not.
|
|
// There are 2 of these because turrets need one for the turret and one for the barrel.
|
|
// Things like radar dishes would only use one.
|
|
submodel_instance *submodel_instance_1; // Instance data for main turret or main object
|
|
submodel_instance *submodel_instance_2; // Instance data for turret guns, if there is one
|
|
|
|
int disruption_timestamp; // time at which subsystem isn't disrupted
|
|
|
|
int subsys_cargo_name; // cap ship cargo on subsys
|
|
char subsys_cargo_title[NAME_LENGTH]; // cap ship cargo title (IE: Cargo: or Passengers:)
|
|
fix time_subsys_cargo_revealed; // added by Goober5000
|
|
|
|
int triggered_rotation_index; //the actual currently running animation and assosiated states
|
|
|
|
float points_to_target;
|
|
float base_rotation_rate_pct;
|
|
float gun_rotation_rate_pct;
|
|
|
|
// still going through these...
|
|
flagset<Ship::Subsys_Sound_Flags> subsys_snd_flags;
|
|
|
|
int rotation_timestamp;
|
|
|
|
// target priority setting for turrets
|
|
int target_priority[32];
|
|
int num_target_priorities;
|
|
|
|
//SUSHI: Fields for max_turret_aim_update_delay
|
|
//Only used when targeting small ships
|
|
fix next_aim_pos_time;
|
|
vec3d last_aim_enemy_pos;
|
|
vec3d last_aim_enemy_vel;
|
|
|
|
//scaler for setting adjusted turret rof
|
|
float rof_scaler;
|
|
|
|
//Per-turret ownage settings - SUSHI
|
|
int turret_max_bomb_ownage;
|
|
int turret_max_target_ownage;
|
|
|
|
// multiplayer
|
|
TIMESTAMP info_from_server_stamp;
|
|
|
|
ship_subsys()
|
|
: next(NULL), prev(NULL)
|
|
{}
|
|
|
|
void clear();
|
|
};
|
|
|
|
// The head sentinel of a ship's intrusive subsystem list. The sentinel's
|
|
// address is meaningful: the first node's prev and the last node's next point
|
|
// back at it, and an empty list is self-referential (after list_init) or
|
|
// null-linked (after construction or ship::clear). Moving a ship would
|
|
// otherwise leave the bookend nodes pointing at the old sentinel address, so
|
|
// the move operations re-link them. Copying is deleted: a copied sentinel
|
|
// would alias another list's nodes.
|
|
struct ship_subsys_sentinel : public ship_subsys
|
|
{
|
|
ship_subsys_sentinel() = default;
|
|
|
|
ship_subsys_sentinel(const ship_subsys_sentinel &) = delete;
|
|
ship_subsys_sentinel &operator=(const ship_subsys_sentinel &) = delete;
|
|
|
|
ship_subsys_sentinel(ship_subsys_sentinel &&other) noexcept
|
|
{
|
|
take_links_from(other);
|
|
}
|
|
|
|
ship_subsys_sentinel &operator=(ship_subsys_sentinel &&other) noexcept
|
|
{
|
|
if (this != &other)
|
|
{
|
|
Assertion(next == nullptr || next == this, "Move-assigning over a sentinel whose subsystem list is not empty! The destination's subsystems would be orphaned.");
|
|
take_links_from(other);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
private:
|
|
void take_links_from(ship_subsys_sentinel &other) noexcept
|
|
{
|
|
if (other.next == nullptr)
|
|
{
|
|
// other was never list_init'd; match that state
|
|
next = nullptr;
|
|
prev = nullptr;
|
|
}
|
|
else if (other.next == &other)
|
|
{
|
|
// other is an initialized empty list
|
|
next = this;
|
|
prev = this;
|
|
}
|
|
else
|
|
{
|
|
// take ownership of the chain and re-point the bookends
|
|
next = other.next;
|
|
prev = other.prev;
|
|
next->prev = this;
|
|
prev->next = this;
|
|
}
|
|
// leave other as an initialized empty list, which is safe to iterate
|
|
other.next = &other;
|
|
other.prev = &other;
|
|
}
|
|
};
|
|
|
|
// structure for subsystems which tells us the total count of a particular type of subsystem (i.e.
|
|
// we might have 3 engines), and the relative strength of the subsystem. The #defines in model.h
|
|
// for SUBSYSTEM_xxx will be used as indices into this array.
|
|
typedef struct ship_subsys_info {
|
|
int type_count; // number of subsystems of type on this ship;
|
|
float aggregate_max_hits; // maximum number of hits for all subsystems of this type.
|
|
float aggregate_current_hits; // current count of hits for all subsystems of this type.
|
|
} ship_subsys_info;
|
|
|
|
// Karajorma - Used by the alter-ship-flag SEXP as an alternative to having lots of ship flag SEXPs
|
|
typedef struct ship_flag_name {
|
|
Ship::Ship_Flags flag; // the actual ship flag constant as given by the define below
|
|
char flag_name[TOKEN_LENGTH]; // the name written to the mission file for its corresponding parse_object flag
|
|
} ship_flag_name;
|
|
|
|
typedef struct ship_flag_description {
|
|
Ship::Ship_Flags flag;
|
|
const char *flag_desc;
|
|
} ship_flag_description;
|
|
|
|
extern ship_flag_name Ship_flag_names[];
|
|
extern ship_flag_description Ship_flag_descriptions[];
|
|
extern const size_t Num_ship_flag_names;
|
|
extern const size_t Num_ship_flag_descriptions;
|
|
|
|
typedef struct wing_flag_name {
|
|
Ship::Wing_Flags flag;
|
|
char flag_name[TOKEN_LENGTH];
|
|
} wing_flag_name;
|
|
|
|
typedef struct wing_flag_description {
|
|
Ship::Wing_Flags flag;
|
|
const char *flag_desc;
|
|
} wing_flag_description;
|
|
|
|
extern wing_flag_name Wing_flag_names[];
|
|
extern wing_flag_description Wing_flag_descriptions[];
|
|
extern const size_t Num_wing_flag_names;
|
|
extern const size_t Num_wing_flag_descriptions;
|
|
|
|
#define DEFAULT_SHIP_PRIMITIVE_SENSOR_RANGE 10000 // Goober5000
|
|
|
|
#define MAX_DAMAGE_SLOTS 32
|
|
#define MAX_SHIP_DAMAGE_ARCS 5 // How many damage or emp "arcs" can be active at once
|
|
#define NUM_SUB_EXPL_HANDLES 2 // How many different big ship sub explosion sounds can be played.
|
|
|
|
#define MAX_SHIP_CONTRAILS 24
|
|
|
|
typedef struct ship_spark {
|
|
vec3d pos; // position of spark in the submodel's RF
|
|
int submodel_num; // which submodel is making the spark
|
|
int end_time;
|
|
} ship_spark;
|
|
|
|
template <class T>
|
|
struct reload_pct
|
|
{
|
|
void init(int num_banks, int points_per_bank, T value)
|
|
{
|
|
_points_per_bank = points_per_bank;
|
|
_buffer.clear();
|
|
_buffer.resize(num_banks * points_per_bank, value);
|
|
_value = value;
|
|
}
|
|
|
|
T& get(int bank, int point)
|
|
{
|
|
int pos = bank * _points_per_bank + point;
|
|
|
|
// this can happen with mismatched ships.tbl and models
|
|
if (pos >= (int)_buffer.size())
|
|
return _value;
|
|
|
|
return _buffer[pos];
|
|
}
|
|
|
|
void set(int bank, int point, T value)
|
|
{
|
|
int pos = bank * _points_per_bank + point;
|
|
|
|
// this can happen with mismatched ships.tbl and models
|
|
if (pos >= (int)_buffer.size())
|
|
return;
|
|
|
|
_buffer[pos] = value;
|
|
}
|
|
|
|
private:
|
|
int _points_per_bank = 0;
|
|
T _value;
|
|
SCP_vector<T> _buffer;
|
|
};
|
|
|
|
struct ship_electrical_arc : electrical_arc
|
|
{
|
|
TIMESTAMP timestamp; // When this times out, the spark goes away. Invalid is not used
|
|
|
|
// if this vector exists, these points will be used instead of the ones generated on each frame by interp_generate_arc_segment()
|
|
std::unique_ptr<SCP_vector<vec3d>> persistent_arc_points;
|
|
};
|
|
|
|
// NOTE: Can't be treated as a struct anymore, since it has STL data structures in its object tree!
|
|
class ship
|
|
{
|
|
public:
|
|
int objnum;
|
|
int ai_index; // Index in Ai_info of ai_info associated with this ship.
|
|
int ship_info_index; // Index in ship_info for this ship
|
|
int hotkey;
|
|
int escort_priority;
|
|
int score;
|
|
float assist_score_pct;
|
|
int respawn_priority;
|
|
|
|
// BEGIN PACK ubytes and chars
|
|
ubyte pre_death_explosion_happened; // If set, it means the 4 or 5 smaller explosions
|
|
ubyte wash_killed;
|
|
char cargo1;
|
|
char cargo_title[NAME_LENGTH];
|
|
|
|
// ship wing status info
|
|
char wing_status_wing_index; // wing index (0-4) in wingman status gauge
|
|
char wing_status_wing_pos; // wing position (0-5) in wingman status gauge
|
|
|
|
// alternate indexes
|
|
int alt_type_index; // only used for display purposes (read : safe)
|
|
int callsign_index; // ditto
|
|
|
|
// targeting laser info
|
|
char targeting_laser_bank; // -1 if not firing, index into polymodel gun points if it _is_ firing
|
|
int targeting_laser_objnum; // -1 if invalid, beam object # otherwise
|
|
|
|
// corkscrew missile stuff
|
|
ubyte num_corkscrew_to_fire; // # of corkscrew missiles lef to fire
|
|
int corkscrew_missile_bank;
|
|
int next_corkscrew_fire; // next time to fire a corkscrew missile
|
|
// END PACK
|
|
|
|
int final_death_time; // Time until big fireball starts
|
|
int really_final_death_time; // Time until ship breaks up and disappears
|
|
vec3d deathroll_rotvel; // Desired death rotational velocity
|
|
|
|
std::unique_ptr<WarpEffect> warpin_effect;
|
|
std::unique_ptr<WarpEffect> warpout_effect;
|
|
|
|
int warpin_params_index;
|
|
int warpout_params_index;
|
|
|
|
int next_fireball;
|
|
|
|
int next_hit_spark;
|
|
int num_sparks; // Note, this is the number of spark emitter positions!
|
|
ship_spark sparks[MAX_SHIP_SPARKS];
|
|
|
|
bool use_special_explosion;
|
|
int special_exp_damage; // new special explosion/hitpoints system
|
|
int special_exp_blast;
|
|
int special_exp_inner;
|
|
int special_exp_outer;
|
|
bool use_shockwave;
|
|
int special_exp_shockwave_speed;
|
|
int special_exp_deathroll_time;
|
|
|
|
int special_hitpoints;
|
|
int special_shield;
|
|
|
|
float ship_max_shield_strength;
|
|
float ship_max_hull_strength;
|
|
|
|
float max_shield_recharge;
|
|
float max_shield_regen_per_second; // wookieejedi - make this a ship object variable
|
|
float max_weapon_regen_per_second; // wookieejedi - make this a ship object variable
|
|
|
|
int ship_guardian_threshold; // Goober5000 - now also determines whether ship is guardian'd
|
|
SCP_vector<guard_range_entry> max_guard_ranges; // per-guarded-ship caps on this ship's guard engagement/resume range
|
|
float max_guard_radius; // cap for every ship guarding this one, used when the guarder has no cap of its own; <= 0 means unused
|
|
|
|
|
|
char ship_name[NAME_LENGTH];
|
|
SCP_string display_name;
|
|
|
|
int team; // Which team it's on, HOSTILE, FRIENDLY, UNKNOWN, NEUTRAL
|
|
|
|
fix time_cargo_revealed; // time at which the cargo was revealed
|
|
|
|
ArrivalLocation arrival_location;
|
|
int arrival_distance; // how far away this ship should arrive
|
|
anchor_t arrival_anchor; // ship registry index of object this ship arrives near (or in front of)
|
|
int arrival_path_mask; // Goober5000 - possible restrictions on which bay paths to use
|
|
int arrival_cue;
|
|
int arrival_delay;
|
|
|
|
DepartureLocation departure_location; // depart to hyperspace or someplace else (like docking bay)
|
|
anchor_t departure_anchor; // when docking bay -- ship registry index of ship to use
|
|
int departure_path_mask; // Goober5000 - possible restrictions on which bay paths to use
|
|
int departure_cue; // sexpression to eval when departing
|
|
int departure_delay; // time in seconds after sexp is true that we delay.
|
|
|
|
int wingnum; // wing number this ship is in. -1 if in no wing, Wing array index otherwise
|
|
SCP_set<size_t> orders_accepted; // set of orders this ship will accept from the player.
|
|
SCP_set<size_t> orders_allowed_against; // set of orders for which this ship cannot be a target.
|
|
|
|
// Subsystem fields. The subsys_list is a list of all subsystems (which might include multiple types
|
|
// of a particular subsystem, like engines). The subsys_info struct is information for particular
|
|
// types of subsystems. (i.e. the list might contain 3 engines. There will be one subsys_info entry
|
|
// describing the state of all engines combined) -- MWA 4/1/97
|
|
ship_subsys_sentinel subsys_list; // linked list of subsystems for this ship.
|
|
std::unique_ptr<ship_subsys*[]> subsys_list_indexer; // provides random-access lookup to the linked list
|
|
ship_subsys *last_targeted_subobject[MAX_PLAYERS]; // Last subobject that has been targeted. NULL if none;(player specific)
|
|
ship_subsys_info subsys_info[SUBSYSTEM_MAX]; // info on particular generic types of subsystems
|
|
|
|
// ETS fields
|
|
int shield_recharge_index; // index into array holding the shield recharge rate
|
|
int weapon_recharge_index; // index into array holding the weapon recharge rate
|
|
int engine_recharge_index; // index into array holding the engine recharge rate
|
|
float weapon_energy; // Number of EUs in energy reserves
|
|
int next_manage_ets; // timestamp for when ai can next modify ets ( -1 means never )
|
|
float prev_engine_strength; // used only in update_ets() to allow for minimizing overrides to max speed --Asteroth and wookieejedi
|
|
|
|
flagset<Ship::Ship_Flags> flags; // flag variable to contain ship state
|
|
int reinforcement_index; // index into reinforcement struct or -1
|
|
|
|
float afterburner_fuel; // amount of afterburner fuel remaining (capacity is stored
|
|
// as afterburner_fuel_capacity in ship_info).
|
|
float afterburner_last_engage_fuel; // the fuel level when the afterburners were last engaged
|
|
TIMESTAMP afterburner_last_end_time; // when the ship last stopped its afterburner
|
|
|
|
int cmeasure_count; // Number of charges of countermeasures this ship can hold.
|
|
int current_cmeasure; // Currently selected countermeasure.
|
|
|
|
int cmeasure_fire_stamp; // Time at which can fire countermeasure.
|
|
|
|
float target_shields_delta; // Target for shield recharge system.
|
|
float target_weapon_energy_delta; // Target for recharge system.
|
|
ship_weapon weapons;
|
|
|
|
int shield_hits; // Number of hits on shield this frame.
|
|
|
|
SCP_vector<vec3d> shield_points;
|
|
|
|
float wash_intensity;
|
|
vec3d wash_rot_axis;
|
|
int wash_timestamp;
|
|
|
|
SCP_vector<lock_info> missile_locks;
|
|
SCP_vector<lock_info> missile_locks_firing;
|
|
|
|
int num_swarm_missiles_to_fire; // number of swarm missiles that need to be launched
|
|
int next_swarm_fire; // timestamp of next swarm missile to fire
|
|
int num_turret_swarm_info; // number of turrets in process of launching swarm
|
|
int swarm_missile_bank; // The missilebank the swarm was originally launched from
|
|
|
|
int group; // group ship is in, or -1 if none. Fred thing
|
|
SCP_string fred_layer = "Default"; // FRED view layer assignment
|
|
sound_handle death_roll_snd; // id of death roll sound, may need to be stopped early
|
|
int ship_list_index; // index of ship in Ship_objs[] array
|
|
|
|
int thruster_bitmap; // What frame the current thruster bitmap is at for this ship
|
|
float thruster_frame; // Used to keep track of which frame the animation should be on.
|
|
|
|
int thruster_glow_bitmap; // What frame the current thruster engine glow bitmap is at for this ship
|
|
float thruster_glow_frame; // Used to keep track of which frame the engine glow animation should be on.
|
|
float thruster_glow_noise; // Noise for current frame
|
|
|
|
int thruster_secondary_glow_bitmap; // Bobboau
|
|
int thruster_tertiary_glow_bitmap; // Bobboau
|
|
int thruster_distortion_bitmap; // Valathil
|
|
|
|
int next_engine_stutter; // timestamp to time the engine stuttering when a ship dies
|
|
|
|
TIMESTAMP base_texture_anim_timestamp; // Goober5000 - zero mark for texture animations
|
|
|
|
float total_damage_received; // total damage received (for scoring purposes)
|
|
float damage_ship[MAX_DAMAGE_SLOTS]; // damage applied from each player
|
|
int damage_ship_id[MAX_DAMAGE_SLOTS]; // signature of the damager (corresponds to each entry in damage_ship)
|
|
int persona_index; // which persona is this guy.
|
|
|
|
int subsys_disrupted_flags; // bitflags used to check if SUBYSTEM_* is disrupted or not
|
|
int subsys_disrupted_check_timestamp; // timer to control how oftern flags are set/cleared in subsys_disrupted_flags
|
|
|
|
uint create_time; // time ship was created, set by gettime()
|
|
|
|
// keep multiplayer specific stuff below this point
|
|
int ts_index; // index into the team select and Wss_slots array (or -1 if not in one of those arrays)
|
|
|
|
int large_ship_blowup_index; // -1 if not a large ship exploding, else this is an index used by the shipfx large ship exploding code.
|
|
std::array<sound_handle, NUM_SUB_EXPL_HANDLES> sub_expl_sound_handle;
|
|
|
|
// Stuff for showing electrical arcs on damaged ships
|
|
SCP_vector<ship_electrical_arc> electrical_arcs;
|
|
TIMESTAMP arc_next_time; // When the next damage/emp arc will be created.
|
|
SCP_vector<TIMESTAMP> passive_arc_next_times; // When the next passive ship arc will be created.
|
|
|
|
// emp missile stuff
|
|
float emp_intensity; // <= 0.0f if no emp effect present
|
|
float emp_decr; // how much to decrement EMP effect per second for this ship
|
|
|
|
// contrail stuff
|
|
trail *trail_ptr[MAX_SHIP_CONTRAILS];
|
|
|
|
// tag stuff
|
|
float tag_total; // total tag time
|
|
float tag_left; // total tag remaining
|
|
fix time_first_tagged;
|
|
float level2_tag_total; // total tag time
|
|
float level2_tag_left; // total tag remaining
|
|
|
|
// lightning timestamp
|
|
int lightning_stamp;
|
|
|
|
// AWACS warning flag
|
|
flagset<Ship::Awacs_Warning_Flags> awacs_warning_flag;
|
|
|
|
// Special warp objnum (warping at knossos)
|
|
int special_warpin_objnum;
|
|
int special_warpout_objnum;
|
|
|
|
ship_subsys fighter_beam_turret_data; //a fake subsystem that pretends to be a turret for fighter beams
|
|
model_subsystem beam_sys_info;
|
|
int was_firing_last_frame[MAX_SHIP_PRIMARY_BANKS];
|
|
|
|
// Goober5000 - range of primitive sensors
|
|
int primitive_sensor_range;
|
|
|
|
// Goober5000 - index into pm->view_positions[]
|
|
// apparently, early in FS1 development, there was a field called current_eye_index
|
|
// that had this same functionality
|
|
int current_viewpoint;
|
|
|
|
trail *ABtrail_ptr[MAX_SHIP_CONTRAILS]; //after burner trails -Bobboau
|
|
trail_info ab_info[MAX_SHIP_CONTRAILS];
|
|
int ab_count;
|
|
|
|
// glow points
|
|
std::deque<bool> glow_point_bank_active;
|
|
|
|
//Animated Shader effects
|
|
int shader_effect_num;
|
|
int shader_effect_duration;
|
|
TIMESTAMP shader_effect_timestamp;
|
|
|
|
float alpha_mult;
|
|
|
|
ship_subsys *last_fired_turret; // which turret has fired last
|
|
|
|
// fighter bay door stuff, parent side
|
|
int bay_doors_anim_done_time; // ammount of time to transition from one animation state to another
|
|
EModelAnimationPosition bay_doors_status; // anim status of the bay doors (closed/not-animating, opening, open/not-animating)
|
|
int bay_doors_wanting_open; // how many ships want/need the bay door open
|
|
|
|
// figther bay door stuff, client side
|
|
ubyte bay_doors_launched_from; // the bay door that I launched from
|
|
bool bay_doors_need_open; // keep track of whether I need the door open or not
|
|
int bay_doors_parent_shipnum; // our parent ship, what we are entering/leaving
|
|
|
|
reload_pct<float> secondary_point_reload_pct; //after fireing a secondary it takes some time for that secondary weapon to reload, this is how far along in that proces it is (from 0 to 1)
|
|
|
|
SCP_vector<std::tuple<TIMESTAMP, int, float>> rcs_activity; //Timestamp of when thrusters started
|
|
//Sound index for thrusters
|
|
//Thruster status
|
|
|
|
SCP_vector<alt_class> s_alt_classes;
|
|
|
|
SCP_map<std::pair<int, int>, int> ship_iff_color;
|
|
|
|
int ammo_low_complaint_count; // number of times this ship has complained about low ammo
|
|
int armor_type_idx;
|
|
int shield_armor_type_idx;
|
|
int collision_damage_type_idx;
|
|
int debris_damage_type_idx;
|
|
ushort debris_net_sig; // net signiture of the first piece of debris this ship has
|
|
|
|
int model_instance_num;
|
|
|
|
fix time_created;
|
|
|
|
fix radar_visible_since; // The first time this ship was visible on the radar. Gets reset when ship is not visible anymore
|
|
fix radar_last_contact; // The last time this ship appeared on the radar. When it is currently visible this has the value if Missiontime
|
|
|
|
RadarVisibility radar_last_status; // Last radar status
|
|
RadarVisibility radar_current_status; // Current radar status
|
|
|
|
SCP_string team_name;
|
|
SCP_string secondary_team_name; //If the change-team-color sexp is used, these fields control the fading behaviour
|
|
fix team_change_timestamp;
|
|
int team_change_time;
|
|
|
|
float autoaim_fov;
|
|
float bank_autoaim_fov[MAX_SHIP_PRIMARY_BANKS];
|
|
|
|
int cockpit_model_instance;
|
|
|
|
TIMESTAMP multi_client_collision_timestamp;
|
|
|
|
enum warpstage {
|
|
STAGE1 = 0,
|
|
STAGE2,
|
|
BOTH,
|
|
};
|
|
|
|
// Ships support moving but not copying. The defaulted moves are correct
|
|
// because the members carry the smarts: the subsys_list sentinel re-links
|
|
// its bookend nodes, and the owning pointers are unique_ptrs. Callers must
|
|
// still fix up external back-references (Objects[].instance,
|
|
// Ai_info[].shipnum, etc.) -- see reassign_ship_slot in
|
|
// missioneditor/common.cpp.
|
|
// All the defaulted special member functions are defaulted in ship.cpp
|
|
// rather than here because they need the complete WarpEffect type.
|
|
// The moves are not declared noexcept because the implicit exception
|
|
// specification differs by standard library: MSVC and clang compute
|
|
// nothrow, but libstdc++ computes potentially-throwing for some members,
|
|
// making an explicit noexcept ill-formed there (a defaulted redeclaration
|
|
// may not strengthen the implicit specification). The NOLINTs suppress
|
|
// clang-tidy's performance-noexcept-move-constructor, which only sees
|
|
// clang's computation.
|
|
ship();
|
|
~ship();
|
|
ship(const ship &) = delete;
|
|
ship &operator=(const ship &) = delete;
|
|
ship(ship &&); // NOLINT(performance-noexcept-move-constructor)
|
|
ship &operator=(ship &&); // NOLINT(performance-noexcept-move-constructor)
|
|
|
|
// reset to a completely blank ship
|
|
void clear();
|
|
|
|
//Helper functions
|
|
bool is_arriving(ship::warpstage stage = ship::warpstage::BOTH, bool dock_leader_or_single = false) const;
|
|
inline bool is_departing() const { return flags.any_of(Ship::Ship_Flags::Depart_warp,Ship::Ship_Flags::Depart_dockbay); }
|
|
inline bool cannot_warp_flags() const { return flags.any_of(Ship::Ship_Flags::Warp_broken,Ship::Ship_Flags::Warp_never,Ship::Ship_Flags::Disabled,Ship::Ship_Flags::No_subspace_drive); }
|
|
inline bool is_dying_or_departing() const { return is_departing() || flags[Ship::Ship_Flags::Dying]; }
|
|
|
|
const char* get_display_name() const;
|
|
bool has_display_name() const;
|
|
|
|
void apply_replacement_textures(const SCP_vector<texture_replace> &replacements);
|
|
};
|
|
|
|
struct ai_target_priority {
|
|
char name[NAME_LENGTH];
|
|
|
|
int obj_type;
|
|
SCP_vector <int> ship_type;
|
|
SCP_vector <int> ship_class;
|
|
SCP_vector <int> weapon_class;
|
|
|
|
flagset<Object::Object_Flags> obj_flags;
|
|
flagset<Ship::Info_Flags> sif_flags;
|
|
flagset<Weapon::Info_Flags> wif_flags;
|
|
};
|
|
|
|
extern SCP_vector <ai_target_priority> Ai_tp_list;
|
|
|
|
void parse_ai_target_priorities();
|
|
void parse_weapon_targeting_priorities();
|
|
ai_target_priority init_ai_target_priorities();
|
|
|
|
// structure and array def for ships that have exited the game. Keeps track of certain useful
|
|
// information.
|
|
|
|
typedef struct exited_ship {
|
|
char ship_name[NAME_LENGTH];
|
|
SCP_string display_name;
|
|
int obj_signature;
|
|
int ship_class;
|
|
int team;
|
|
int wingnum;
|
|
flagset<Ship::Exit_Flags> flags;
|
|
fix time;
|
|
int hull_strength;
|
|
fix time_cargo_revealed;
|
|
char cargo1;
|
|
float damage_ship[MAX_DAMAGE_SLOTS]; // A copy of the arrays from the ship so that we can figure out what damaged it
|
|
int damage_ship_id[MAX_DAMAGE_SLOTS];
|
|
} exited_ship;
|
|
|
|
extern SCP_vector<exited_ship> Ships_exited;
|
|
|
|
// a couple of functions to get at the data
|
|
extern void ship_add_exited_ship( ship *shipp, Ship::Exit_Flags reason );
|
|
extern int ship_find_exited_ship_by_name( const char *name );
|
|
extern int ship_find_exited_ship_by_signature( int signature);
|
|
|
|
// Stuff for overall ship status, useful for reference by sexps and scripts. Status changes occur in the same frame as mission log entries.
|
|
enum class ShipStatus
|
|
{
|
|
// The ship_registry_entry hasn't been initialized yet
|
|
INVALID = 0,
|
|
|
|
// A ship is on the arrival list as a parse object
|
|
NOT_YET_PRESENT,
|
|
|
|
// A ship is currently in-mission, and its objp and shipp pointers are valid
|
|
PRESENT,
|
|
|
|
// A ship has been destroyed but is still doing its death roll (not yet "exited");
|
|
// the objp and shipp pointers are still valid
|
|
DEATH_ROLL,
|
|
|
|
// A ship is destroyed, departed, or vanished; the objp and shipp pointers are nullptr.
|
|
// Note that for destroyed ships, ship_cleanup is not called until the death roll is complete,
|
|
// so the ship will spend a period of time in DEATH_ROLL before moving to EXITED.
|
|
EXITED
|
|
};
|
|
|
|
struct ship_registry_entry
|
|
{
|
|
ShipStatus status = ShipStatus::INVALID;
|
|
char name[NAME_LENGTH] = { 0 };
|
|
|
|
int pobj_num = -1;
|
|
int objnum = -1;
|
|
int shipnum = -1;
|
|
|
|
int cleanup_mode = 0;
|
|
int exited_index = -1;
|
|
|
|
ship_registry_entry(const char* _name);
|
|
|
|
inline bool has_p_objp() const { return pobj_num >= 0; }
|
|
inline bool has_objp() const { return objnum >= 0; }
|
|
inline bool has_shipp() const { return shipnum >= 0; }
|
|
|
|
p_object* p_objp() const;
|
|
object* objp() const;
|
|
ship* shipp() const;
|
|
|
|
p_object* p_objp_or_null() const;
|
|
object* objp_or_null() const;
|
|
ship* shipp_or_null() const;
|
|
|
|
ship_info* sip() const;
|
|
int ship_class_index() const;
|
|
};
|
|
|
|
extern SCP_vector<ship_registry_entry> Ship_registry;
|
|
extern SCP_unordered_map<SCP_string, int, SCP_string_lcase_hash, SCP_string_lcase_equal_to> Ship_registry_map;
|
|
|
|
extern int ship_registry_get_index(const char *name);
|
|
extern int ship_registry_get_index(const SCP_string &name);
|
|
extern bool ship_registry_exists(const char *name);
|
|
extern bool ship_registry_exists(const SCP_string &name);
|
|
extern bool ship_registry_exists(int index);
|
|
extern const ship_registry_entry *ship_registry_get(const char *name);
|
|
extern const ship_registry_entry *ship_registry_get(const SCP_string &name);
|
|
extern const ship_registry_entry *ship_registry_get(int index);
|
|
extern const ship_registry_entry *ship_registry_get(anchor_t anchor);
|
|
extern void ship_registry_rename(int entry_index, const char *new_name, bool erase_old_key);
|
|
|
|
#define REGULAR_WEAPON (1<<0)
|
|
#define DOGFIGHT_WEAPON (1<<1)
|
|
|
|
typedef struct ship_passive_arc_info {
|
|
std::pair<int, int> submodels;
|
|
std::pair<SCP_string, SCP_string> submodel_strings; // the string names from parsing, to be looked up and used to fill the above later when the model is ready
|
|
std::pair<vec3d, vec3d> pos;
|
|
float duration;
|
|
float frequency;
|
|
float width;
|
|
color primary_color_1;
|
|
color primary_color_2;
|
|
color secondary_color;
|
|
} ship_lightning_data;
|
|
|
|
typedef struct thruster_particles {
|
|
generic_anim thruster_bitmap;
|
|
particle::ParticleEffectHandle particle_handle;
|
|
} thruster_particles;
|
|
|
|
typedef struct ship_type_info {
|
|
char name[NAME_LENGTH];
|
|
|
|
flagset<Ship::Type_Info_Flags> flags;
|
|
|
|
float debris_max_speed;
|
|
|
|
// Damage multiplier for friendly fire, but only for purposes of scoring and traitor check, not actually damaging ships in-mission
|
|
float ff_multiplier;
|
|
|
|
// Not currently implemented. Originally used for "electronics" weapons. Deactivated in commit 941faf9ab9ed05a1b0efebf7de32c6e3c724baf7
|
|
// as it broke retail compatibility.
|
|
float emp_multiplier;
|
|
|
|
// Modifies the audible range used for warp fireball 3d sound effects
|
|
float warp_sound_range_multiplier;
|
|
|
|
//Fog
|
|
float fog_start_dist;
|
|
float fog_complete_dist;
|
|
|
|
//AI
|
|
SCP_set<ai_goal_mode> ai_valid_goals;
|
|
SCP_set<size_t> ai_player_orders;
|
|
int ai_active_dock;
|
|
int ai_passive_dock;
|
|
SCP_vector<int> ai_actively_pursues;
|
|
SCP_vector<int> ai_cripple_ignores;
|
|
|
|
//Explosions
|
|
float skip_deathroll_chance;
|
|
|
|
//Resources
|
|
SCP_vector<int> explosion_bitmap_anims;
|
|
|
|
//Regen values - need to be converted after all types have loaded
|
|
SCP_vector<SCP_string> ai_actively_pursues_temp;
|
|
SCP_vector<SCP_string> ai_cripple_ignores_temp;
|
|
|
|
ship_type_info( )
|
|
: debris_max_speed( 0.f ),
|
|
ff_multiplier( 0.f ), emp_multiplier( 0.f ), warp_sound_range_multiplier( 1.f ),
|
|
fog_start_dist( 0.f ), fog_complete_dist( 0.f ),
|
|
ai_active_dock( 0 ), ai_passive_dock( 0 ),
|
|
skip_deathroll_chance( 0.f )
|
|
|
|
{
|
|
flags.reset();
|
|
name[ 0 ] = '\0';
|
|
}
|
|
} ship_type_info;
|
|
|
|
extern SCP_vector<ship_type_info> Ship_types;
|
|
extern bool Fighter_bomber_valid; // Whether "fighter/bomber" can be used as a union of "fighter" and "bomber"
|
|
extern const char *Fighter_bomber_type_name;
|
|
extern int Ship_type_fighter, Ship_type_bomber, Ship_type_fighter_bomber;
|
|
|
|
class rcs_thruster_info {
|
|
public:
|
|
flagset<Ship::Thruster_Flags> use_flags;
|
|
|
|
gamesnd_id start_snd;
|
|
gamesnd_id loop_snd;
|
|
gamesnd_id stop_snd;
|
|
|
|
int tex_id;
|
|
int tex_nframes;
|
|
int tex_fps;
|
|
float length;
|
|
float radius;
|
|
|
|
vec3d pos, norm;
|
|
|
|
rcs_thruster_info() : tex_id(-1), tex_nframes(0), tex_fps(0), length(0), radius (0.0f) {
|
|
norm.xyz.x = norm.xyz.y = norm.xyz.z = 0.0f; // I wanted to do norm = ZERO_VECTOR here, but apparently that breaks the MSVC 2015 compiler....
|
|
pos.xyz.x = pos.xyz.y = pos.xyz.z = 0.0f;
|
|
use_flags.reset();
|
|
|
|
start_snd = gamesnd_id();
|
|
loop_snd = gamesnd_id();
|
|
stop_snd = gamesnd_id();
|
|
}
|
|
};
|
|
|
|
// Holds variables for collision physics (Gets its own struct purely for clarity purposes)
|
|
// Most of this only really applies properly to small ships
|
|
typedef struct ship_collision_physics {
|
|
// Collision physics definitions: how a ship responds to collisions
|
|
float both_small_bounce{}; // Bounce factor when both ships are small
|
|
// This currently only comes into play if one ship is the player...
|
|
// blame retail for that.
|
|
float bounce{}; // Bounce factor for all other cases
|
|
float friction{}; // Controls lateral velocity lost when colliding with a large ship
|
|
float rotation_factor{}; // Affects the rotational energy of collisions... TBH not sure how.
|
|
float rotation_mag_max{}; // Maximum value of the final rotational velocity resulting from a collision --wookieejedi
|
|
|
|
// Speed & angle constraints for a smooth landing
|
|
// Note that all angles are stored as a dotproduct between normalized vectors instead. This saves us from having
|
|
// to do a lot of dot product calculations later.
|
|
float landing_max_z{};
|
|
float landing_min_z{};
|
|
float landing_min_y{};
|
|
float landing_max_x{};
|
|
float landing_max_angle{};
|
|
float landing_min_angle{};
|
|
float landing_max_rot_angle{};
|
|
|
|
// Speed & angle constraints for a "rough" landing (one with normal collision consequences, but where
|
|
// the ship is still reoriented towards its resting orientation)
|
|
float reorient_max_z{};
|
|
float reorient_min_z{};
|
|
float reorient_min_y{};
|
|
float reorient_max_x{};
|
|
float reorient_max_angle{};
|
|
float reorient_min_angle{};
|
|
float reorient_max_rot_angle{};
|
|
|
|
// Landing response parameters
|
|
float reorient_mult{}; // How quickly the ship will reorient towards it's resting position
|
|
float landing_rest_angle{}; // The vertical angle where the ship's orientation comes to rest
|
|
gamesnd_id landing_sound_idx; //Sound to play on successful landing collisions
|
|
|
|
// Collision sounds
|
|
gamesnd_id collision_sound_light_idx;
|
|
gamesnd_id collision_sound_heavy_idx;
|
|
gamesnd_id collision_sound_shielded_idx;
|
|
|
|
} ship_collision_physics;
|
|
|
|
typedef struct path_metadata {
|
|
vec3d departure_rvec;
|
|
vec3d arrival_rvec;
|
|
float arrive_speed_mult;
|
|
float depart_speed_mult;
|
|
} path_metadata;
|
|
|
|
class allowed_weapon_bank
|
|
{
|
|
public:
|
|
SCP_vector<std::pair<int, ubyte>> weapon_and_flags;
|
|
|
|
ubyte find_flags(int weapon_info_index) const;
|
|
void set_flag(int weapon_info_index, ubyte flag);
|
|
void clear_flag(int weapon_info_index, ubyte flag);
|
|
void clear_flag(ubyte flag);
|
|
|
|
void clear();
|
|
|
|
ubyte operator[](int index) const;
|
|
ubyte operator[](size_t index) const;
|
|
};
|
|
|
|
// The real FreeSpace ship_info struct.
|
|
// NOTE: Can't be treated as a struct anymore, since it has STL data structures in its object tree!
|
|
class ship_info
|
|
{
|
|
public:
|
|
char name[NAME_LENGTH]; // name for the ship
|
|
SCP_string display_name; // display another name for the ship
|
|
char short_name[NAME_LENGTH]; // short name, for use in the editor?
|
|
int species; // which species this craft belongs to
|
|
int class_type; //For type table
|
|
|
|
std::unique_ptr<char[]> type_str; // type string used by tooltips
|
|
std::unique_ptr<char[]> maneuverability_str; // string used by tooltips
|
|
std::unique_ptr<char[]> armor_str; // string used by tooltips
|
|
std::unique_ptr<char[]> manufacturer_str; // string used by tooltips
|
|
std::unique_ptr<char[]> desc; // string used by tooltips
|
|
std::unique_ptr<char[]> tech_desc; // string used by tech database
|
|
char tech_title[NAME_LENGTH]; // ship's name (in tech database)
|
|
|
|
std::unique_ptr<char[]> ship_length; // string used by multiplayer ship desc
|
|
std::unique_ptr<char[]> gun_mounts; // string used by multiplayer ship desc
|
|
std::unique_ptr<char[]> missile_banks; // string used by multiplayer ship desc
|
|
|
|
char cockpit_pof_file[MAX_FILENAME_LEN]; // POF file for cockpit view
|
|
vec3d cockpit_offset;
|
|
float cockpit_sway_val; // multiplier for cockpit 'swaying'
|
|
char pof_file[MAX_FILENAME_LEN]; // POF file to load/associate with ship
|
|
char pof_file_hud[MAX_FILENAME_LEN]; // POF file to load for the HUD target box
|
|
char pof_file_tech[MAX_FILENAME_LEN]; // POF file to load for the techroom
|
|
int num_detail_levels; // number of detail levels for this ship
|
|
int detail_distance[MAX_SHIP_DETAIL_LEVELS]; // distance to change detail levels at
|
|
int collision_lod; // check for collisions using a LOD
|
|
int cockpit_model_num; // cockpit model
|
|
int model_num; // ship model
|
|
int model_num_hud; // model to use when rendering to the HUD (eg, mini supercap)
|
|
int hud_target_lod; // LOD to use for rendering to the HUD targetbox (if not already using special HUD model)
|
|
float density; // density of the ship in g/cm^3 (water = 1)
|
|
float damp; // drag
|
|
float rotdamp; // rotational drag
|
|
float delta_bank_const;
|
|
vec3d max_vel; // max velocity of the ship in the linear directions -- read from ships.tbl
|
|
vec3d min_vel; // min velocity of the ship in the linear directions -- read from ships.tbl
|
|
vec3d max_rotvel; // maximum rotational velocity
|
|
vec3d rotation_time; // time to rotate in x/y/z dimension traveling at max rotvel
|
|
float srotation_time; // scalar, computed at runtime as (rotation_time.x + rotation_time.y)/2
|
|
float max_rear_vel; // max speed ship can go backwards.
|
|
float forward_accel;
|
|
float forward_decel;
|
|
float slide_accel;
|
|
float slide_decel;
|
|
float gravity_const; // multiplies the affect of gravity, if any
|
|
float dying_gravity_const; // as above, when death rolling
|
|
|
|
int warpin_params_index;
|
|
int warpout_params_index;
|
|
|
|
flagset<Ship::Info_Flags> flags; // See SIF_xxxx - changed to uint by Goober5000, changed back by Zacam, and changed to something entirely different by The E!
|
|
int ai_class; // Index into Ai_classes[]. Defined in ai.tbl
|
|
float max_speed, min_speed, max_accel;
|
|
|
|
//Collision
|
|
int collision_damage_type_idx;
|
|
ship_collision_physics collision_physics;
|
|
|
|
// ship explosion info
|
|
shockwave_create_info shockwave;
|
|
int explosion_propagates; // If true, then the explosion propagates
|
|
bool explosion_splits_ship; // If true, then the ship 'splits in two' when it blows up
|
|
float big_exp_visual_rad; //SUSHI: The visual size of the main explosion
|
|
float prop_exp_rad_mult; // propagating explosions radius multiplier
|
|
float death_roll_r_mult;
|
|
float death_fx_r_mult;
|
|
float death_roll_time_mult;
|
|
float death_roll_rotation_mult;
|
|
float death_roll_xrotation_cap; // max rotation around x-axis in radians-per-sec (aka pitch)
|
|
float death_roll_yrotation_cap; // max rotation around y-axis in radians-per-sec (aka yaw)
|
|
float death_roll_zrotation_cap; // max rotation around z-axis in radians-per-sec (aka roll)
|
|
int death_roll_base_time;
|
|
int death_fx_count;
|
|
int shockwave_count; // the # of total shockwaves
|
|
SCP_vector<int> explosion_bitmap_anims;
|
|
bool disable_main_fireball;
|
|
float skip_deathroll_chance;
|
|
|
|
particle::ParticleEffectHandle impact_spew;
|
|
particle::ParticleEffectHandle damage_spew;
|
|
particle::ParticleEffectHandle death_roll_exp_particles;
|
|
particle::ParticleEffectHandle pre_death_exp_particles;
|
|
particle::ParticleEffectHandle propagating_exp_particles;
|
|
particle::ParticleEffectHandle split_particles;
|
|
particle::ParticleEffectHandle knossos_end_particles;
|
|
particle::ParticleEffectHandle regular_end_particles;
|
|
particle::ParticleEffectHandle debris_flame_particles;
|
|
particle::ParticleEffectHandle shrapnel_flame_particles;
|
|
particle::ParticleEffectHandle debris_end_particles;
|
|
particle::ParticleEffectHandle shrapnel_end_particles;
|
|
particle::ParticleEffectHandle default_subsys_debris_flame_particles;
|
|
particle::ParticleEffectHandle default_subsys_shrapnel_flame_particles;
|
|
|
|
//Debris stuff
|
|
float debris_min_lifetime;
|
|
float debris_max_lifetime;
|
|
float debris_min_speed;
|
|
float debris_max_speed;
|
|
float debris_min_rotspeed;
|
|
float debris_max_rotspeed;
|
|
int debris_damage_type_idx;
|
|
float debris_min_hitpoints;
|
|
float debris_max_hitpoints;
|
|
float debris_hitpoints_radius_multi;
|
|
float debris_damage_mult;
|
|
float debris_arc_percent;
|
|
float debris_gravity_const; // see gravity_const above
|
|
float debris_density;
|
|
gamesnd_id debris_ambient_sound;
|
|
gamesnd_id debris_collision_sound_light;
|
|
gamesnd_id debris_collision_sound_heavy;
|
|
gamesnd_id debris_explosion_sound;
|
|
char generic_debris_pof_file[MAX_FILENAME_LEN]; // smaller debris bits thrown around willy-nilly on death
|
|
int generic_debris_model_num;
|
|
int generic_debris_num_submodels;
|
|
int generic_debris_spew_num;
|
|
|
|
// subsystem information
|
|
// (n_subsystems describes the subsystems array; the wrapper keeps it
|
|
// consistent with the array by resetting it to 0 in a moved-from ship_info)
|
|
util::reset_on_move<int> n_subsystems; // this number comes from ships.tbl
|
|
std::unique_ptr<model_subsystem[]> subsystems; // see model.h for structure definition
|
|
particle::ParticleEffectHandle default_subsys_death_effect;
|
|
|
|
// Energy Transfer System fields
|
|
float power_output; // power output of ships reactor (EU/s)
|
|
float max_overclocked_speed; // max speed when 100% power output sent to engines
|
|
float max_weapon_reserve; // maximum energy that can be stored for primary weapon usage
|
|
float max_shield_regen_per_second; // Goober5000 - max percent/100 of shield energy regenerated per second
|
|
float shield_regen_hit_delay; // Asteroth - delay after being hit before shield will start recharging again
|
|
float max_weapon_regen_per_second; // Goober5000 - max percent/100 of weapon energy regenerated per second
|
|
|
|
// Fields for tuning the ETS' direct shield<->weapon transfer feature
|
|
float shield_weap_amount; // fraction of shield capacity to transfer
|
|
float shield_weap_efficiency; // efficiency multiplier for output into weapons capacitor
|
|
float shield_weap_speed; // rate that energy will be added to the weap capacitor
|
|
float weap_shield_amount; // ...
|
|
float weap_shield_efficiency; // ditto, but reverse the direction
|
|
float weap_shield_speed; // ...
|
|
|
|
// Afterburner fields
|
|
vec3d afterburner_max_vel; // max velocity of the ship in the linear directions when afterburners are engaged -- read from ships.tbl
|
|
float afterburner_forward_accel; // forward acceleration with afterburner engaged
|
|
float afterburner_fuel_capacity; // maximum afterburner fuel that can be stored
|
|
float afterburner_burn_rate; // rate in fuel/second that afterburner consumes fuel
|
|
float afterburner_recover_rate; // rate in fuel/second that afterburner recovers fuel
|
|
float afterburner_min_start_fuel; // must have at least this much fuel to start
|
|
float afterburner_min_fuel_to_burn; // consumes at least this much fuel before allowing to stop
|
|
float afterburner_cooldown_time; // minimum time between last afterburner finish and next start
|
|
//SparK: reverse afterburner
|
|
float afterburner_max_reverse_vel;
|
|
float afterburner_reverse_accel;
|
|
|
|
int cmeasure_type; // Type of countermeasures this ship carries
|
|
int cmeasure_max; // Number of charges of countermeasures this ship can hold.
|
|
|
|
int num_primary_banks; // Actual number of primary banks (property of model)
|
|
int primary_bank_weapons[MAX_SHIP_PRIMARY_BANKS]; // Weapon_info[] index for the weapon in the bank
|
|
// Goober5000's ballistic conversion
|
|
int primary_bank_ammo_capacity[MAX_SHIP_PRIMARY_BANKS]; // Capacity of primary ballistic bank
|
|
|
|
int num_secondary_banks; // Actual number of secondary banks (property of model)
|
|
int secondary_bank_weapons[MAX_SHIP_SECONDARY_BANKS]; // Weapon_info[] index for the weapon in the bank
|
|
int secondary_bank_ammo_capacity[MAX_SHIP_SECONDARY_BANKS]; // Capacity of bank (not number of missiles)
|
|
|
|
bool draw_primary_models[MAX_SHIP_PRIMARY_BANKS];
|
|
bool draw_secondary_models[MAX_SHIP_SECONDARY_BANKS];
|
|
float weapon_model_draw_distance;
|
|
|
|
// Recoil modifier for the ship
|
|
float ship_recoil_modifier;
|
|
|
|
// Shudder modifier for the ship
|
|
float ship_shudder_modifier;
|
|
|
|
SCP_vector<FiringPattern> dyn_firing_patterns_allowed[MAX_SHIP_PRIMARY_BANKS];
|
|
|
|
float max_hull_strength; // Max hull strength of this class of ship.
|
|
float max_shield_strength;
|
|
float auto_shield_spread; // Thickness of the shield
|
|
bool auto_shield_spread_bypass; // Whether weapons fired up close can bypass shields
|
|
int auto_shield_spread_from_lod; // Which LOD to project the shield from
|
|
float auto_shield_spread_min_span; // Minimum distance weapons must travel until allowed to collide with the shield
|
|
float max_shield_impact_effect_radius;
|
|
|
|
int shield_point_augment_ctrls[4]; // Re-mapping of shield augmentation controls for model point shields
|
|
|
|
float max_shield_recharge;
|
|
|
|
float hull_repair_rate; // How much of the hull is repaired every second
|
|
float subsys_repair_rate; // How much of the subsystem is repaired every second
|
|
float hull_repair_max; // Maximum percent that hull can self repair --wookieejedi
|
|
float subsys_repair_max; // Maximum percent that subsystems can self repair --wookieejedi
|
|
|
|
float sup_hull_repair_rate;
|
|
float sup_shield_repair_rate;
|
|
float sup_subsys_repair_rate;
|
|
|
|
vec3d closeup_pos; // position for camera when using ship in closeup view (eg briefing and techroom)
|
|
float closeup_zoom; // zoom when using ship in closeup view (eg briefing and techroom)
|
|
std::optional<vec3d> icon_closeup_pos; // icon-specific position for camera when using ship in closeup view
|
|
std::optional<float> icon_closeup_zoom; // icon-specific zoom when using ship in closeup view
|
|
|
|
vec3d closeup_pos_targetbox; // position for camera when using ship in closeup view for hud target monitor
|
|
float closeup_zoom_targetbox; // zoom when using ship in closeup view for hud target monitor
|
|
|
|
vec3d chase_view_offset; // special offset for chase view
|
|
float chase_view_rigidity; // how 'floaty' this ship is when viewed in chase view
|
|
|
|
allowed_weapon_bank allowed_weapons; // specifies which weapons can be loaded out by the
|
|
// player during weapons loadout.
|
|
|
|
// Goober5000 - fix for restricted banks mod
|
|
SCP_vector<ubyte> restricted_loadout_flag;
|
|
SCP_vector<allowed_weapon_bank> allowed_bank_restricted_weapons;
|
|
|
|
ubyte shield_icon_index; // index to locate ship-specific animation frames for the shield on HUD
|
|
char icon_filename[MAX_FILENAME_LEN]; // filename for icon that is displayed in ship selection
|
|
angles model_icon_angles; // angle from which the model icon should be rendered (if not 0,0,0)
|
|
char anim_filename[MAX_FILENAME_LEN]; // filename for animation that plays in ship selection
|
|
char overhead_filename[MAX_FILENAME_LEN]; // filename for animation that plays weapons loadout
|
|
int selection_effect;
|
|
color fs2_effect_grid_color; // color of the grid effect in the ship selection screen
|
|
color fs2_effect_scanline_color; // color of the scanline effect in the ship selection screen
|
|
int fs2_effect_grid_density; // density of the grid effect in the ship selection screen
|
|
color fs2_effect_wireframe_color; // color of the wireframe effect in the ship selection screen
|
|
|
|
int wingmen_status_dot_override; // optional wingmen dot status animation to use instead of default --wookieejedi
|
|
|
|
int bii_index_ship; // if this ship has a briefing icon that overrides the normal icon set
|
|
int bii_index_ship_with_cargo;
|
|
int bii_index_wing;
|
|
int bii_index_wing_with_cargo;
|
|
|
|
int score; // default score for this ship
|
|
|
|
int scan_time; // time to scan this ship (in ms)
|
|
float scan_range_normal; // this ship can scan other normal/small ships at this range
|
|
float scan_range_capital; // this ship can scan other capital/large ships at this range
|
|
float scanning_time_multiplier; // when this ship is doing the scanning, the factor to apply to scan time
|
|
float scanning_range_multiplier; // ditto for scan range
|
|
|
|
float ask_help_shield_percent;
|
|
float ask_help_hull_percent;
|
|
|
|
// contrail info
|
|
trail_info ct_info[MAX_SHIP_CONTRAILS];
|
|
int ct_count;
|
|
|
|
// rgb shield color
|
|
ubyte shield_color[3];
|
|
|
|
// HW2-style team coloring
|
|
bool uses_team_colors;
|
|
SCP_string default_team_name;
|
|
|
|
// optional afterburner trail values
|
|
generic_bitmap afterburner_trail;
|
|
float afterburner_trail_tex_stretch;
|
|
float afterburner_trail_width_factor;
|
|
float afterburner_trail_alpha_factor;
|
|
float afterburner_trail_alpha_end_factor;
|
|
float afterburner_trail_alpha_decay_exponent;
|
|
float afterburner_trail_life;
|
|
float afterburner_trail_spread;
|
|
int afterburner_trail_faded_out_sections;
|
|
|
|
// thruster particles
|
|
SCP_vector<thruster_particles> normal_thruster_particles;
|
|
SCP_vector<thruster_particles> afterburner_thruster_particles;
|
|
|
|
// Bobboau's extra thruster stuff
|
|
thrust_pair thruster_flame_info;
|
|
thrust_pair thruster_glow_info;
|
|
thrust_pair_bitmap thruster_secondary_glow_info;
|
|
thrust_pair_bitmap thruster_tertiary_glow_info;
|
|
thrust_pair_bitmap thruster_distortion_info;
|
|
|
|
float thruster01_glow_rad_factor;
|
|
float thruster02_glow_rad_factor;
|
|
float thruster03_glow_rad_factor;
|
|
float thruster02_glow_len_factor;
|
|
float thruster_dist_rad_factor;
|
|
float thruster_dist_len_factor;
|
|
float thruster_glow_noise_mult;
|
|
|
|
bool draw_distortion;
|
|
|
|
// Goober5000
|
|
SCP_vector<texture_replace> replacement_textures;
|
|
|
|
|
|
int armor_type_idx;
|
|
int shield_armor_type_idx;
|
|
|
|
bool can_glide;
|
|
float glide_cap; //Backslash - for 'newtonian'-style gliding, the cap on velocity
|
|
bool glide_dynamic_cap; //SUSHI: Whether or not we are using a dynamic glide cap
|
|
float glide_accel_mult; //SUSHI: acceleration multiplier for glide mode
|
|
bool use_newtonian_damp; //SUSHI: Whether or not to use newtonian dampening for this ship
|
|
bool newtonian_damp_override;
|
|
|
|
float autoaim_fov;
|
|
float bank_autoaim_fov[MAX_SHIP_PRIMARY_BANKS];
|
|
|
|
bool aims_at_flight_cursor;
|
|
bool aims_at_flight_cursor_secondary;
|
|
float flight_cursor_aim_extent;
|
|
|
|
bool topdown_offset_def;
|
|
vec3d topdown_offset;
|
|
|
|
gamesnd_id engine_snd; // handle to engine sound for ship (-1 if no engine sound)
|
|
float min_engine_vol; // minimum volume modifier for engine sound when ship is stationary
|
|
gamesnd_id glide_start_snd; // handle to sound to play at the beginning of a glide maneuver (default is 0 for regular throttle down sound)
|
|
gamesnd_id glide_end_snd; // handle to sound to play at the end of a glide maneuver (default is 0 for regular throttle up sound)
|
|
gamesnd_id flyby_snd; // handle to sound to play with ship flyby
|
|
|
|
SCP_map<GameSounds, gamesnd_id> ship_sounds; // specifies ship-specific sound indexes
|
|
|
|
SCP_map<SCP_string, SCP_string> custom_data;
|
|
|
|
SCP_vector<custom_string> custom_strings;
|
|
|
|
SCP_vector<rcs_thruster_info> rcs_thrusters;
|
|
|
|
int radar_image_2d_idx;
|
|
int radar_color_image_2d_idx;
|
|
int radar_image_size;
|
|
float radar_projection_size_mult;
|
|
|
|
SCP_map<std::pair<int, int>, int> ship_iff_info;
|
|
|
|
flagset<Object::Aiming_Flags> aiming_flags;
|
|
float minimum_convergence_distance;
|
|
float convergence_distance;
|
|
vec3d convergence_offset;
|
|
gamesnd_id autoaim_lock_snd;
|
|
gamesnd_id autoaim_lost_snd;
|
|
|
|
float emp_resistance_mod;
|
|
|
|
float piercing_damage_draw_limit;
|
|
particle::ParticleEffectHandle shield_impact_explosion_anim;
|
|
|
|
int damage_lightning_type;
|
|
|
|
SCP_vector<std::unique_ptr<HudGauge>> hud_gauges;
|
|
bool hud_enabled;
|
|
bool hud_retail;
|
|
|
|
SCP_vector<cockpit_display_info> displays;
|
|
|
|
SCP_map<SCP_string, path_metadata> pathMetadata;
|
|
|
|
SCP_unordered_map<int, int> glowpoint_bank_override_map; // key: glowpoint bank (-1 = all banks); value: index into the growable global glowpoint_bank_overrides vector
|
|
|
|
animation::ModelAnimationSet animations;
|
|
animation::ModelAnimationSet cockpit_animations;
|
|
|
|
SCP_vector<ship_passive_arc_info> ship_passive_arcs;
|
|
|
|
ship_info();
|
|
~ship_info() = default;
|
|
void clone(const ship_info& other);
|
|
|
|
ship_info(ship_info&& other) = default; // NOLINT(performance-noexcept-move-constructor) - not declared noexcept because the implicit exception specification differs by standard library
|
|
ship_info &operator=(ship_info&& other) = default; // NOLINT(performance-noexcept-move-constructor) - ditto
|
|
|
|
// Deleted so nobody copies a ship class by accident; use clone() for a deliberate deep copy.
|
|
ship_info(const ship_info& other) = delete;
|
|
ship_info &operator=(const ship_info& other) = delete;
|
|
|
|
//Helper functions
|
|
|
|
inline bool is_small_ship() const { return flags.any_of(Ship::Info_Flags::Fighter,Ship::Info_Flags::Bomber,Ship::Info_Flags::Support,Ship::Info_Flags::Escapepod); }
|
|
inline bool is_big_ship() const { return flags.any_of(Ship::Info_Flags::Cruiser,Ship::Info_Flags::Freighter,Ship::Info_Flags::Transport,Ship::Info_Flags::Corvette,Ship::Info_Flags::Gas_miner,Ship::Info_Flags::Awacs); }
|
|
inline bool is_huge_ship() const { return flags.any_of(Ship::Info_Flags::Capital,Ship::Info_Flags::Supercap,Ship::Info_Flags::Drydock,Ship::Info_Flags::Knossos_device); }
|
|
inline bool is_flyable() const { return flags.none_of(Ship::Info_Flags::Cargo,Ship::Info_Flags::Navbuoy,Ship::Info_Flags::Sentrygun); } // AL 11-24-97: this useful to know for targeting reasons
|
|
// note: code that previously used is_harmless() / SIF_HARMLESS now uses several flags defined in objecttypes.tbl
|
|
// inline bool is_harmless() const { return flags[Ship::Info_Flags::Cargo, Ship::Info_Flags::Navbuoy, Ship::Info_Flags::Escapepod]; } // AL 12-3-97: ships that are not a threat
|
|
inline bool is_fighter_bomber() const { return flags.any_of(Ship::Info_Flags::Fighter,Ship::Info_Flags::Bomber); }
|
|
inline bool is_big_or_huge() const { return is_big_ship() || is_huge_ship(); }
|
|
inline bool avoids_shockwaves() const { return is_small_ship(); }
|
|
|
|
const char* get_display_name() const;
|
|
bool has_display_name() const;
|
|
|
|
};
|
|
|
|
extern flag_def_list_new<Ship::Info_Flags> Ship_flags[];
|
|
extern const size_t Num_ship_flags;
|
|
|
|
extern flag_def_list_new<Model::Subsystem_Flags> Subsystem_flags[];
|
|
extern const size_t Num_subsystem_flags;
|
|
|
|
extern int Num_wings;
|
|
extern ship Ships[MAX_SHIPS];
|
|
extern ship *Player_ship;
|
|
extern std::shared_ptr<model_texture_replace> Player_cockpit_textures;
|
|
|
|
// Data structure to track the active missiles
|
|
typedef struct ship_obj {
|
|
ship_obj *next, *prev;
|
|
int flags, objnum;
|
|
} ship_obj;
|
|
extern ship_obj Ship_obj_list;
|
|
|
|
typedef struct engine_wash_info
|
|
{
|
|
char name[NAME_LENGTH];
|
|
float angle; // half angle of cone around engine thruster
|
|
float radius_mult; // multiplier for radius
|
|
float length; // length of engine wash, measured from thruster
|
|
float intensity; // intensity of engine wash
|
|
|
|
} engine_wash_info;
|
|
|
|
extern SCP_vector<engine_wash_info> Engine_wash_info;
|
|
|
|
|
|
// Defines a wing of ships.
|
|
typedef struct wing {
|
|
char name[NAME_LENGTH];
|
|
SCP_string display_name;
|
|
|
|
char wing_squad_filename[MAX_FILENAME_LEN]; // Goober5000
|
|
int reinforcement_index; // index in reinforcement struct or -1
|
|
int hotkey;
|
|
|
|
// members for dealing with waves
|
|
int num_waves;
|
|
int current_wave; // NOTE: this is 1-based! As each wave arrives, this will reflect the counting number: Wave 1, Wave 2, etc.
|
|
int threshold; // when number of ships in the wing reaches this number -- new wave
|
|
|
|
fix time_gone; // time into the mission when this wing is officially gone.
|
|
|
|
int wave_count; // max ships per wave (as defined by the number of ships in the ships list)
|
|
int total_arrived_count; // count of number of ships that we have created, regardless of wave
|
|
int red_alert_skipped_ships; // Goober5000 - if we skipped over any indexes while creating red-alert ships
|
|
int current_count; // count of number of ships actually in this wing -- used for limit in next array
|
|
int ship_index[MAX_SHIPS_PER_WING]; // index into ships array of all ships currently in the wing
|
|
|
|
int total_destroyed; // total number of ships destroyed in the wing (including all waves)
|
|
int total_departed; // total number of ships departed in this wing (including all waves)
|
|
int total_vanished; // total number of ships vanished in this wing (including all waves)
|
|
|
|
int special_ship; // the leader of the wing. An index into ship_index[].
|
|
int special_ship_ship_info_index; // the ship info index of the special ship
|
|
|
|
ArrivalLocation arrival_location; // arrival and departure information for wings -- similar to info for ships
|
|
int arrival_distance; // distance from some ship where this ship arrives
|
|
anchor_t arrival_anchor; // ship registry index of object this wing arrives near (or in front of)
|
|
int arrival_path_mask; // Goober5000 - possible restrictions on which bay paths to use
|
|
int arrival_cue;
|
|
int arrival_delay;
|
|
|
|
DepartureLocation departure_location;
|
|
anchor_t departure_anchor; // ship registry index of object that we depart to (in case of dock bays)
|
|
int departure_path_mask; // Goober5000 - possible restrictions on which bay paths to use
|
|
int departure_cue;
|
|
int departure_delay;
|
|
|
|
int wave_delay_min; // minimum number of seconds before new wave can arrive
|
|
int wave_delay_max; // maximum number of seconds before new wave can arrive
|
|
TIMESTAMP wave_delay_timestamp; // timestamp used for delaying arrival of next wave
|
|
|
|
flagset<Ship::Wing_Flags> flags;
|
|
|
|
ai_goal ai_goals[MAX_AI_GOALS]; // goals for the wing -- converted to ai_goal struct
|
|
|
|
ushort net_signature; // starting net signature for ships in this wing. assiged at mission load time
|
|
|
|
// Goober5000 - if this wing has a unique squad logo
|
|
// it's specified for the wing rather than each individual ship to cut down on the amount
|
|
// of stuff that needs to be sitting in memory at once - each ship uses the wing texture;
|
|
// and it also makes practical sense: no wing has two different squadrons in it :)
|
|
int wing_insignia_texture;
|
|
|
|
// if -1, retail formation, else a custom one defined in ships.tbl
|
|
int formation;
|
|
float formation_scale;
|
|
|
|
// reset to a completely blank wing
|
|
void clear();
|
|
|
|
const char *get_display_name() const;
|
|
bool has_display_name() const;
|
|
} wing;
|
|
|
|
extern wing Wings[MAX_WINGS];
|
|
|
|
extern int Starting_wings[MAX_STARTING_WINGS];
|
|
extern int Squadron_wings[MAX_SQUADRON_WINGS];
|
|
extern int TVT_wings[MAX_TVT_WINGS];
|
|
|
|
extern char Starting_wing_names[MAX_STARTING_WINGS][NAME_LENGTH];
|
|
extern char Squadron_wing_names[MAX_SQUADRON_WINGS][NAME_LENGTH];
|
|
extern char TVT_wing_names[MAX_TVT_WINGS][NAME_LENGTH];
|
|
|
|
extern int ai_paused;
|
|
|
|
extern SCP_vector<ship_info> Ship_info;
|
|
extern SCP_vector<const char *> Ship_class_names;
|
|
|
|
extern SCP_vector<reinforcements> Reinforcements;
|
|
|
|
// structure definition for ship type counts. Used to give a count of the number of ships
|
|
// of a particular type, and the number of times that a ship of that particular type has been
|
|
// killed. When changing any info here, be sure to update the ship_type_names array in Ship.cpp
|
|
// the order of the types here MUST match the order of the types in the array
|
|
typedef struct ship_counts {
|
|
int total;
|
|
int killed;
|
|
ship_counts(){total=0;killed=0;}
|
|
} ship_counts;
|
|
|
|
extern SCP_vector<ship_counts> Ship_type_counts;
|
|
|
|
|
|
// Formations
|
|
typedef struct wing_formation {
|
|
char name[NAME_LENGTH];
|
|
std::array<vec3d, MAX_SHIPS_PER_WING - 1> positions; // does NOT include wing leader, so index 0 for each formation is the second in the wing, 1 is third, etc
|
|
} wing_formation;
|
|
|
|
extern SCP_vector<wing_formation> Wing_formations;
|
|
|
|
|
|
// Use the below macros when you want to find the index of an array element in the
|
|
// Wings[] or Ships[] arrays.
|
|
#define WING_INDEX(wingp) (static_cast<int>((wingp)-Wings))
|
|
#define SHIP_INDEX(shipp) (static_cast<int>((shipp)-Ships))
|
|
#define SHIP_REGISTRY_INDEX(ship_entry) (static_cast<int>((ship_entry)-Ship_registry.data()))
|
|
|
|
|
|
extern void ship_init(); // called once at game start
|
|
extern void ship_level_init(); // called before the start of each level
|
|
extern void ship_level_close(); // called after the end of each level
|
|
|
|
//returns -1 if failed
|
|
extern int ship_create(matrix* orient, vec3d* pos, int ship_type, const char* ship_name = nullptr, bool standalone_ship = false);
|
|
extern void change_ship_type(int n, int ship_type, int by_sexp = 0);
|
|
extern void ship_process_pre( object * objp, float frametime );
|
|
extern void ship_process_post( object * objp, float frametime );
|
|
extern void ship_render( object * obj, model_draw_list * scene );
|
|
// whether this ship class shows a cockpit at all: it has a cockpit model and the player hasn't turned cockpits off
|
|
extern bool ship_cockpit_enabled(const ship_info* sip);
|
|
// whether the cockpit model is rendered for this ship class when it is the viewer
|
|
extern bool ship_render_player_cockpit(const ship_info* sip);
|
|
// whether the viewer's cockpit is being rendered this frame
|
|
extern bool ship_render_player_cockpit_active();
|
|
extern bool ship_render_player_ship_casts_shadow_on_cockpit();
|
|
extern bool ship_render_player_has_closeup_visuals();
|
|
// The cockpit model's render offset: sip->cockpit_offset rotated into world orientation,
|
|
// plus acceleration-driven sway (unless Disable_cockpit_sway). This is the camera-relative
|
|
// offset used to draw the cockpit model, NOT combined with objp->pos -- callers that need
|
|
// a world-space position must add objp->pos themselves. Shared by every path that draws or
|
|
// otherwise anchors the cockpit model: ship_render_player_ship(), render_viewer_shadow()
|
|
// (shadows.cpp), and gatherCockpitShadowCasterInstance() (VulkanRaytracingTlas.cpp).
|
|
extern vec3d ship_cockpit_render_offset(const ship_info* sip, const object* objp);
|
|
extern void ship_render_player_ship( object * objp, const vec3d* offset = nullptr, const matrix* rot_offset = nullptr, const fov_t* fov_override = nullptr);
|
|
extern void ship_delete( object * objp );
|
|
extern int ship_check_collision_fast( object * obj, object * other_obj, vec3d * hitpos );
|
|
extern int ship_get_num_ships();
|
|
|
|
#define SHIP_VANISHED (1<<0)
|
|
#define SHIP_DESTROYED (1<<1)
|
|
#define SHIP_DEPARTED_WARP (1<<2)
|
|
#define SHIP_DEPARTED_BAY (1<<3)
|
|
#define SHIP_DEPARTED ( SHIP_DEPARTED_BAY | SHIP_DEPARTED_WARP )
|
|
#define SHIP_DESTROYED_REDALERT (1<<4)
|
|
#define SHIP_DEPARTED_REDALERT (1<<5)
|
|
#define SHIP_PRESENT_AT_MISSION_END (1<<6)
|
|
|
|
/**
|
|
* @brief Deletes and de-inits a ship.
|
|
*
|
|
* @param[in] shipnum Index of this ship in Ships[]
|
|
* @param[in] cleanup_mode Flags describing how this ship is to be removed. See SHIP_VANISHED, SHIP_DESTROYED, etc.
|
|
*
|
|
* @details This is the deconstructor of a ship, it does all the necassary processes to remove the ship from the Ships
|
|
* array, and frees the slot for use by others. De-init of its Objects[] slot is handled by obj_delete_all_that_should_be_dead().
|
|
*
|
|
* @author Goober5000
|
|
* @sa obj_delete_all_that_should_be_dead()
|
|
*/
|
|
extern void ship_cleanup(int shipnum, int cleanup_mode);
|
|
|
|
// Goober5000
|
|
extern void ship_destroy_instantly(object *ship_obj, bool with_debris = false);
|
|
extern void ship_actually_depart(int shipnum, int method = SHIP_DEPARTED_WARP);
|
|
|
|
extern bool in_autoaim_fov(ship *shipp, int bank_to_fire, object *obj);
|
|
extern int ship_stop_fire_primary(object * obj);
|
|
extern int ship_fire_primary(object * objp, int force = 0, bool rollback_shot = false);
|
|
extern vec3d ship_get_external_model_fp_offset(external_weapon_state *ext, const weapon_info *wip, const polymodel *weapon_model, const w_bank *ship_bank, int slot, bool advance_counter, int sub_shot = 0);
|
|
extern void ship_get_weapon_model_slot_transform(const w_bank *bank, int slot, float reload_slide_back, vec3d *outpnt, matrix *outorient);
|
|
extern int ship_get_external_weapon_model_instance(ship_weapon *swp, int bank, int display_model_num);
|
|
extern int ship_fire_secondary(object * objp, int allow_swarm = 0, bool rollback_shot = false );
|
|
extern bool ship_secondary_bank_can_dual_fire(const ship *shipp, int bank);
|
|
bool ship_start_secondary_fire(object* objp);
|
|
bool ship_stop_secondary_fire(object* objp);
|
|
extern int ship_launch_countermeasure(object *objp, int rand_val = -1);
|
|
|
|
// for special targeting lasers
|
|
extern void ship_process_targeting_lasers();
|
|
|
|
extern bool ship_select_next_primary(object *objp, CycleDirection direction);
|
|
extern int ship_select_next_secondary(object *objp);
|
|
|
|
// Goober5000
|
|
extern int get_available_primary_weapons(object *objp, int *outlist, int *outbanklist);
|
|
|
|
extern int get_available_secondary_weapons(object *objp, int *outlist, int *outbanklist);
|
|
extern void ship_recalc_subsys_strength( ship *shipp );
|
|
|
|
// switch a subsystem's looping sounds between its alive and dead sets, according to its hitpoints
|
|
extern void ship_update_subsys_sounds(const ship *shipp, ship_subsys *ss);
|
|
extern void physics_ship_init(object *objp);
|
|
|
|
// Note: This is not a general purpose routine.
|
|
// It is specifically used for targeting.
|
|
// Return true/false for subsystem found/not found.
|
|
// Stuff vector *pos with absolute position.
|
|
extern int get_subsystem_pos(vec3d *pos, const object *objp, const ship_subsys *subsysp);
|
|
|
|
extern int ship_info_lookup(const char *name);
|
|
extern int ship_name_lookup(const char *name, int inc_players = 0); // returns the index into Ship array of name
|
|
extern int ship_type_name_lookup(const char *name);
|
|
|
|
inline int ship_info_size()
|
|
{
|
|
return static_cast<int>(Ship_info.size());
|
|
}
|
|
|
|
extern int wing_lookup(const char *name);
|
|
extern int wing_formation_lookup(const char *formation_name);
|
|
|
|
// returns 0 if no conflict, 1 if conflict, -1 on some kind of error with wing struct
|
|
extern int wing_has_conflicting_teams(int wing_index);
|
|
|
|
// next function takes optional second parameter which says to ignore the current count of ships
|
|
// in the wing -- used to tell is the wing exists or not, not whether it exists and has ships currently
|
|
// present.
|
|
extern int wing_name_lookup(const char *name, int ignore_count = 0);
|
|
|
|
extern bool wing_has_yet_to_arrive(const wing *wingp);
|
|
|
|
// for generating a ship name for arbitrary waves/indexes of that wing
|
|
extern void wing_bash_ship_name(SCP_string &ship_name, const char *wing_name, int ordinal);
|
|
extern void wing_bash_ship_name(char *ship_name, const char *wing_name, int ordinal);
|
|
extern void wing_bash_ship_name(p_object *p_objp, const wing *wingp, int ordinal, bool reset_display_name_if_normal = false);
|
|
extern void wing_bash_ship_name(ship *shipp, const wing *wingp, int ordinal, bool reset_display_name_if_normal = false);
|
|
extern bool wing_bash_legacy_hashed_ship_name(SCP_string &dest, const char *src);
|
|
|
|
extern int Player_ship_class;
|
|
|
|
// Do the special effect for energy dissipating into the shield for a hit.
|
|
// model_num = index in Polygon_models[]
|
|
// centerp = pos of object, sort of the center of the shield
|
|
// tcp = hit point, probably the global hit_point set in polygon_check_face
|
|
// tr0 = index of polygon in shield pointer in polymodel.
|
|
extern void create_shield_explosion(int objnum, int model_num, matrix *orient, vec3d *centerp, vec3d *tcp, int tr0);
|
|
|
|
// Initialize shield hit system.
|
|
extern void shield_hit_init();
|
|
extern void create_shield_explosion_all(object *objp);
|
|
extern void shield_frame_init();
|
|
extern void add_shield_point(int objnum, int tri_num, const vec3d *hit_pos, float radius_override);
|
|
extern void add_shield_point_multi(int objnum, int tri_num, vec3d *hit_pos);
|
|
extern void shield_point_multi_setup();
|
|
extern void shield_hit_close();
|
|
|
|
float ship_shield_hitpoint_threshold(const object* obj, bool all_quadrants = false);
|
|
bool ship_is_shield_up(const object *obj, int quadrant);
|
|
|
|
//=================================================
|
|
void ship_model_replicate_submodels(object *objp);
|
|
|
|
//============================================
|
|
extern int ship_find_num_crewpoints(object *objp);
|
|
extern int ship_find_num_turrets(object *objp);
|
|
|
|
extern void compute_slew_matrix(matrix *orient, angles *a);
|
|
extern void object_get_eye(vec3d *eye_pos, matrix *eye_orient, const object *obj, bool do_slew = true, bool local_pos = false, bool local_orient = false);
|
|
|
|
extern ship_subsys *ship_find_first_subsys(ship *sp, int subsys_type, const vec3d *attacker_pos = nullptr);
|
|
extern ship_subsys *ship_get_indexed_subsys(ship *sp, int index); // returns index'th subsystem of this ship
|
|
extern int ship_find_subsys(const ship *sp, const char *ss_name); // returns numerical index in linked list of subsystems
|
|
extern int ship_get_subsys_index(const ship_subsys *subsys);
|
|
|
|
extern bool ship_subsystems_blown(const ship *shipp, int type, bool skip_dying_check = false);
|
|
extern float ship_get_subsystem_strength(const ship *shipp, int type, bool skip_dying_check = false, bool no_minimum_engine_str = false);
|
|
extern ship_subsys *ship_get_subsys(const ship *shipp, const char *subsys_name);
|
|
extern int ship_get_num_subsys(const ship *shipp);
|
|
extern ship_subsys *ship_get_closest_subsys_in_sight(const ship *sp, int subsys_type, const vec3d *attacker_pos);
|
|
|
|
//WMC
|
|
const char *ship_subsys_get_name(const ship_subsys *ss);
|
|
bool ship_subsys_has_instance_name(const ship_subsys *ss);
|
|
void ship_subsys_set_name(ship_subsys* ss, const char* n_name);
|
|
|
|
const char *ship_subsys_get_name_on_hud(const ship_subsys *ss);
|
|
const char *ship_subsys_get_canonical_name(const ship_subsys *ss);
|
|
|
|
// subsys disruption
|
|
extern int ship_subsys_disrupted(const ship_subsys *ss);
|
|
extern int ship_subsys_disrupted(const ship *sp, int type);
|
|
extern void ship_subsys_set_disrupted(ship_subsys *ss, int time);
|
|
|
|
extern int ship_do_rearm_frame( object *objp, float frametime );
|
|
extern float ship_calculate_rearm_duration( object *objp );
|
|
extern void ship_wing_cleanup( int shipnum, wing *wingp );
|
|
extern void wing_maybe_cleanup( wing *wingp, int team = -1 );
|
|
|
|
extern int ship_find_repair_ship( object *requester_obj, object **ship_we_found = NULL );
|
|
extern void ship_close(); // called in game_shutdown() to free malloced memory
|
|
|
|
|
|
extern void ship_assign_sound_all();
|
|
extern void ship_assign_sound(ship *sp);
|
|
|
|
extern void ship_clear_ship_type_counts();
|
|
extern void ship_add_ship_type_count( int ship_info_index, int num );
|
|
|
|
extern const char *ship_get_type(const ship_info *sip);
|
|
extern const SCP_set<size_t>& ship_get_default_orders_accepted( ship_info *sip );
|
|
extern SCP_set<size_t> ship_get_default_orders_against();
|
|
extern int ship_query_general_type(int ship);
|
|
extern int ship_class_query_general_type(int ship_class);
|
|
extern int ship_query_general_type(ship *shipp);
|
|
extern int ship_docking_valid(int docker, int dockee);
|
|
extern int get_quadrant(const vec3d *hit_pnt, const object *shipobjp = nullptr); // Return quadrant num of given hit point.
|
|
|
|
int ship_secondary_bank_has_ammo(int shipnum); // check if current secondary bank has ammo
|
|
|
|
int ship_engine_ok_to_warp(ship *sp); // check if ship has engine power to warp
|
|
int ship_navigation_ok_to_warp(ship *sp); // check if ship has navigation power to warp
|
|
bool ship_can_warp_full_check(ship *sp); // checks both the warp flags and ship_engine_ok_to_warp() and ship_navigation_ok_to_warp() --wookieejedi
|
|
bool ship_can_bay_depart(ship *sp); // checks to see if a ship has a departure location as a bay and if the mothership is present
|
|
|
|
int ship_return_subsys_path_normal(const ship *sp, const ship_subsys *ss, const vec3d *gsubpos, vec3d *norm);
|
|
bool ship_subsystem_in_sight(const object *objp, const ship_subsys *subsys, const vec3d *eye_pos, const vec3d *subsys_pos, bool do_facing_check = true, float *dot_out = nullptr, vec3d *vec_out = nullptr);
|
|
ship_subsys *ship_return_next_subsys(ship *shipp, int type, vec3d *attacker_pos);
|
|
|
|
// defines and definition for function to get a random ship of a particular team (any ship,
|
|
// any ship but player ships, or only players)
|
|
#define SHIP_GET_ANY_SHIP 0
|
|
#define SHIP_GET_NO_PLAYERS 1
|
|
#define SHIP_GET_ONLY_PLAYERS 2
|
|
#define SHIP_GET_UNSILENCED 3 // Karajorma - Returns no_players that can send builtin messages.
|
|
|
|
|
|
extern int ship_get_random_team_ship(int team_mask, int flags = SHIP_GET_ANY_SHIP, float max_dist = 0.0f);
|
|
extern int ship_get_random_player_wing_ship(int flags = SHIP_GET_ANY_SHIP, float max_dist = 0.0f, int persona_index = -1, int get_first = 0, int multi_team = -1);
|
|
extern int ship_get_random_ship_in_wing(int wingnum, int flags = SHIP_GET_ANY_SHIP, float max_dist = 0.0f, int get_first = 0, int order_id = -1);
|
|
|
|
// return ship index
|
|
int ship_get_random_targetable_ship();
|
|
|
|
extern int ship_get_by_signature(int signature);
|
|
|
|
#ifndef NDEBUG
|
|
extern int Ai_render_debug_flag;
|
|
extern int Show_shield_mesh;
|
|
extern int Ship_auto_repair; // flag to indicate auto-repair of subsystem should occur
|
|
#endif
|
|
|
|
int ship_dumbfire_threat(ship *sp);
|
|
int ship_lock_threat(ship *sp);
|
|
|
|
int bitmask_2_bitnum(int num);
|
|
SCP_string ship_return_orders(ship *sp);
|
|
char *ship_return_time_to_goal(char *outbuf, ship *sp);
|
|
int ship_return_seconds_to_goal(ship *sp);
|
|
|
|
void ship_maybe_warn_player(ship *enemy_sp, float dist);
|
|
void ship_maybe_praise_player(ship *deader_sp);
|
|
void ship_maybe_praise_self(ship *deader_sp, ship *killer_sp);
|
|
void ship_maybe_ask_for_help(ship *sp, ship *attacker);
|
|
void ship_scream(ship *sp);
|
|
void ship_maybe_scream(ship *sp);
|
|
void ship_maybe_tell_about_rearm(ship *sp);
|
|
void ship_maybe_tell_about_low_ammo(ship *sp);
|
|
void ship_maybe_lament();
|
|
|
|
void ship_primary_changed(ship *sp);
|
|
void ship_secondary_changed(ship *sp);
|
|
|
|
// get the Ship_info flags for a given ship
|
|
flagset<Ship::Info_Flags> ship_get_SIF(ship *shipp);
|
|
flagset<Ship::Info_Flags> ship_get_SIF(int sh);
|
|
|
|
// get the ship type info (objecttypes.tbl)
|
|
ship_type_info *ship_get_type_info(object *objp);
|
|
|
|
extern void ship_do_cargo_revealed( ship *shipp, int from_network = 0 );
|
|
extern void ship_do_cargo_hidden( ship *shipp, int from_network = 0 );
|
|
extern void ship_do_cap_subsys_cargo_revealed( ship *shipp, ship_subsys *subsys, int from_network = 0);
|
|
extern void ship_do_cap_subsys_cargo_hidden( ship *shipp, ship_subsys *subsys, int from_network = 0);
|
|
|
|
float ship_get_secondary_weapon_range(ship *shipp);
|
|
|
|
// Goober5000
|
|
int get_max_ammo_count_for_primary_bank(int ship_class, int bank, int ammo_type);
|
|
int get_max_ammo_count_for_primary_turret_bank(ship_weapon* swp, int bank, int ammo_type);
|
|
|
|
|
|
int get_max_ammo_count_for_bank(int ship_class, int bank, int ammo_type);
|
|
int get_max_ammo_count_for_turret_bank(ship_weapon *swp, int bank, int ammo_type);
|
|
|
|
int is_support_allowed(object *objp, bool do_simple_check = false);
|
|
|
|
// Given an object and a turret on that object, return the actual firing point of the gun
|
|
// and its normal. This uses the current turret angles. We are keeping track of which
|
|
// gun to fire next in the ship specific info for this turret subobject. Use this info
|
|
// to determine which position to fire from next.
|
|
// Stuffs:
|
|
// *gpos: absolute position of gun firing point
|
|
// *gvec: vector fro *gpos to *targetp
|
|
void ship_get_global_turret_gun_info(const object *objp, const ship_subsys *ssp, vec3d *gpos, bool avg_origin, vec3d *gvec, bool use_angles, const vec3d *targetp);
|
|
|
|
// Given an object and a turret on that object, return the global position and forward vector
|
|
// of the turret. The gun normal is the unrotated gun normal, (the center of the FOV cone), not
|
|
// the actual gun normal given using the current turret heading. But it _is_ rotated into the model's orientation
|
|
// in global space.
|
|
void ship_get_global_turret_info(const object *objp, const model_subsystem *tp, vec3d *gpos, vec3d *gvec);
|
|
|
|
// return 1 if objp is in fov of the specified turret, tp. Otherwise return 0.
|
|
// dist = distance from turret to center point of object
|
|
bool object_in_turret_fov(const object *objp, const ship_subsys *ss, const vec3d *tvec, const vec3d *tpos, float dist);
|
|
|
|
// functions for testing fov.. returns true if fov test is passed.
|
|
bool turret_std_fov_test(const ship_subsys *ss, const vec3d *gvec, const vec3d *v2e, float size_mod = 0);
|
|
bool turret_adv_fov_test(const ship_subsys *ss, const vec3d *gvec, const vec3d *v2e, float size_mod = 0);
|
|
bool turret_fov_test(const ship_subsys *ss, const vec3d *gvec, const vec3d *v2e, float size_mod = 0);
|
|
|
|
// function for checking adjusted turret rof
|
|
float get_adjusted_turret_rof(ship_subsys *ss);
|
|
|
|
// forcible jettison cargo from a ship
|
|
void object_jettison_cargo(object *objp, object *cargo_objp, float jettison_speed, bool jettison_new);
|
|
|
|
// get damage done by exploding ship, takes into account mods for individual ship
|
|
float ship_get_exp_damage(object* objp);
|
|
|
|
// get outer radius of damage, takes into account mods for individual ship
|
|
float ship_get_exp_outer_rad(object *ship_objp);
|
|
|
|
// externed by Goober5000
|
|
extern int ship_explode_area_calc_damage( vec3d *pos1, vec3d *pos2, float inner_rad, float outer_rad, float max_damage, float max_blast, float *damage, float *blast );
|
|
|
|
// determine turret status of a given subsystem, returns 0 for no turret, 1 for "fixed turret", 2 for "rotating" turret
|
|
int ship_get_turret_type(ship_subsys *subsys);
|
|
|
|
// get ship by object signature, returns OBJECT INDEX
|
|
int ship_get_by_signature(int sig);
|
|
|
|
// get the team of a reinforcement item
|
|
int ship_get_reinforcement_team(const reinforcements &reinforcement);
|
|
|
|
// page in bitmaps for all ships on a given level
|
|
void ship_page_in();
|
|
|
|
// Goober5000 - helper for above
|
|
void ship_page_in_textures(int ship_index = -1);
|
|
|
|
// fixer for above - taylor
|
|
void ship_page_out_textures(int ship_index, bool release = false);
|
|
|
|
// replaces a texture on a ship with a different texture
|
|
void ship_replace_active_texture(int ship_index, const char* old_name, const char* new_name);
|
|
|
|
// update artillery lock info
|
|
void ship_update_artillery_lock();
|
|
|
|
// checks if a world point is inside the extended bounding box of a ship
|
|
int check_world_pt_in_expanded_ship_bbox(const vec3d *world_pt, const object *objp, float delta_box);
|
|
|
|
// returns true if objp is ship and is tagged
|
|
int ship_is_tagged(object *objp);
|
|
|
|
// returns max normal speed of ship (overclocked / afterburned)
|
|
float ship_get_max_speed(ship *shipp);
|
|
|
|
// returns warpout speed of ship
|
|
float ship_get_warpout_speed(object *objp, ship_info *sip = nullptr, float half_length = 0.0f, float warping_dist = 0.0f);
|
|
|
|
// returns true if ship is beginning to speed up in warpout
|
|
int ship_is_beginning_warpout_speedup(object *objp);
|
|
|
|
// return the length of the ship class
|
|
float ship_class_get_length(const ship_info *sip);
|
|
|
|
// return the actual center of the ship class
|
|
void ship_class_get_actual_center(const ship_info *sip, vec3d *center_pos);
|
|
|
|
// Goober5000 - used by change-ai-class
|
|
extern void ship_set_new_ai_class(ship *shipp, int new_ai_class);
|
|
extern void ship_subsystem_set_new_ai_class(ship_subsys *ss, int new_ai_class);
|
|
|
|
// wing squad logos - Goober5000
|
|
extern void wing_load_squad_bitmap(wing *w);
|
|
|
|
// Goober5000 - needed by new hangar depart code
|
|
extern bool ship_has_hangar_bay(int shipnum);
|
|
extern bool ship_useful_for_departure(int shipnum, int path_mask = 0);
|
|
extern int ship_get_ship_for_departure(int team);
|
|
|
|
// Goober5000
|
|
extern bool ship_fighterbays_all_destroyed(ship *shipp);
|
|
|
|
// Goober5000
|
|
extern bool ship_subsys_takes_damage(ship_subsys *ss);
|
|
|
|
// Goober5000 - handles submodel rotation for subsystems, excluding turrets
|
|
extern void ship_move_subsystems(object *objp);
|
|
|
|
// Goober5000 - shortcut hud stuff
|
|
extern int ship_has_energy_weapons(ship *shipp);
|
|
extern int ship_has_engine_power(ship *shipp);
|
|
|
|
// Swifty - Cockpit displays
|
|
void ship_init_cockpit_displays(ship *shipp);
|
|
void ship_close_cockpit_displays(ship* shipp);
|
|
int ship_start_render_cockpit_display(size_t cockpit_display_num);
|
|
void ship_end_render_cockpit_display(size_t cockpit_display_num);
|
|
|
|
// Goober5000
|
|
int ship_starting_wing_lookup(const char *wing_name);
|
|
int ship_squadron_wing_lookup(const char *wing_name);
|
|
int ship_tvt_wing_lookup(const char *wing_name);
|
|
|
|
// Goober5000
|
|
int ship_class_compare(int ship_class_1, int ship_class_2);
|
|
|
|
int armor_type_get_idx(const char* name);
|
|
|
|
void armor_init();
|
|
|
|
// Sushi - Path metadata
|
|
void init_path_metadata(path_metadata& metadata);
|
|
|
|
|
|
typedef struct ship_effect {
|
|
char name[NAME_LENGTH];
|
|
bool disables_rendering;
|
|
bool invert_timer;
|
|
int shader_effect;
|
|
} ship_effect;
|
|
|
|
extern SCP_vector<ship_effect> Ship_effects;
|
|
|
|
/**
|
|
* @brief Returns a ship-specific sound index
|
|
*
|
|
* @param objp An object pointer. Has to be of type OBJ_SHIP
|
|
* @param id A sound id as defined in gamsesnd.h. If the given id is unknown then the game_snd with the id as index is returned.
|
|
*
|
|
* @return An index into the Snds vector, if the specified index could not be found then the id itself will be returned
|
|
*/
|
|
gamesnd_id ship_get_sound(object *objp, GameSounds id);
|
|
|
|
/**
|
|
* @brief Specifies if a ship has a custom sound for the specified id
|
|
*
|
|
* @param objp An object pointer. Has to be of type OBJ_SHIP
|
|
* @param id A sound id as defined in gamsesnd.h
|
|
*
|
|
* @return True if this object has the specified sound, false otherwise
|
|
*/
|
|
bool ship_has_sound(object *objp, GameSounds id);
|
|
|
|
/**
|
|
* @brief Returns the index of the default player ship
|
|
*
|
|
* @return An index into Ship_info[], location of the default player ship.
|
|
*/
|
|
int get_default_player_ship_index();
|
|
|
|
/**
|
|
* Given a ship with bounding box and a point, find the closest point on the bbox
|
|
*
|
|
* @param ship_obj Object that has the bounding box (should be a ship)
|
|
* @param start World position of the point being compared
|
|
* @param box_pt OUTPUT PARAMETER: closest point on the bbox to start
|
|
*
|
|
* @return point is inside bbox, TRUE/1
|
|
* @return point is outside bbox, FALSE/0
|
|
*/
|
|
int get_nearest_bbox_point(const object *ship_obj, const vec3d *start, vec3d *box_pt);
|
|
|
|
extern flagset<Ship::Ship_Flags> Ignore_List;
|
|
inline bool should_be_ignored(ship* shipp) {
|
|
return (shipp->flags & Ignore_List).any_set();
|
|
}
|
|
|
|
extern void set_default_ignore_list();
|
|
|
|
extern void toggle_ignore_list_flag(Ship::Ship_Flags flag);
|
|
|
|
ship_subsys* ship_get_subsys_for_submodel(ship* shipp, int submodel);
|
|
|
|
// Clears a lock_info struct with defaults
|
|
void ship_clear_lock(lock_info *slot);
|
|
|
|
// queues up locks
|
|
void ship_queue_missile_locks(ship *shipp);
|
|
|
|
// snoops missile locks to see if any are ready to fire.
|
|
bool ship_lock_present(ship *shipp);
|
|
|
|
bool ship_secondary_has_ammo(ship_weapon* swp, int bank_index);
|
|
|
|
// Used to check if one ship can see the other on radar
|
|
int ship_check_visibility(const ship* viewed, ship* viewer);
|
|
|
|
// Find the first available arc slot. If none is available, and no_create is false, add one.
|
|
ship_electrical_arc *ship_find_or_create_electrical_arc_slot(ship *shipp, bool no_create);
|
|
|
|
#endif
|