-
Notifications
You must be signed in to change notification settings - Fork 180
Expand file tree
/
Copy pathship.h
More file actions
2132 lines (1650 loc) · 84.6 KB
/
ship.h
File metadata and controls
2132 lines (1650 loc) · 84.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* 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/ship_flags.h"
#include "weapon/weapon_flags.h"
#include "weapon/weapon.h"
#include "ai/ai.h"
#include <string>
#include <set>
#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
#define MAX_REINFORCEMENTS 32
// 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
typedef struct {
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;
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
int primary_bank_external_model_instance[MAX_SHIP_PRIMARY_BANKS];
bool primary_bank_model_instance_check[MAX_SHIP_PRIMARY_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
int external_model_fp_counter[MAX_SHIP_PRIMARY_BANKS + MAX_SHIP_SECONDARY_BANKS];
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;
//**************************************************************
//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 bool Cockpit_active;
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;
// 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();
};
// 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;
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;
#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
WarpEffect *warpin_effect;
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
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
int arrival_anchor; // name 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)
int departure_anchor; // when docking bay -- 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 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
int afterburner_last_end_time; // timestamp 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
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)
float primary_rotate_rate[MAX_SHIP_PRIMARY_BANKS];
float primary_rotate_ang[MAX_SHIP_PRIMARY_BANKS];
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,
};
// 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[Ship::Ship_Flags::Depart_warp, Ship::Ship_Flags::Depart_dockbay]; }
inline bool cannot_warp_flags() const { return flags[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;
};
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 const ship_registry_entry *ship_registry_get(const char *name);
extern const ship_registry_entry *ship_registry_get(const SCP_string &name);
#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.