-
Notifications
You must be signed in to change notification settings - Fork 172
/
shipTemplate.cpp
815 lines (743 loc) · 38.7 KB
/
shipTemplate.cpp
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
#include <i18n.h>
#include <optional>
#include "shipTemplate.h"
#include "spaceObjects/spaceObject.h"
#include "mesh.h"
#include "multiplayer_server.h"
#include "scriptInterface.h"
/// A ShipTemplate defines the base functionality, stats, models, and other details for the ShipTemplateBasedObjects created from it.
/// ShipTemplateBasedObjects belong to either the SpaceStation or SpaceShip subclasses. SpaceShips in turn belong to the CpuShip or PlayerSpaceship classes.
/// ShipTemplates appear in ship and space station creation lists, such as the ship selection screen on scenarios that allow player ship creation, or the GM console's object creation tool.
/// They also appear as default entries in the science database.
/// EmptyEpsilon loads scripts/shipTemplates.lua at launch, which requires files containing ShipTemplates located in scripts/shiptemplates/.
/// New ShipTemplates can't be defined while a scenario is running.
/// Use Lua variables to apply several ShipTemplate functions to the same template.
/// Example:
/// -- Create a ShipTemplate for a Cruiser Frigate-class CpuShip designated Phobos T3
/// template = ShipTemplate():setName("Phobos T3"):setLocaleName(_("ship","Phobos T3")):setClass(_("class","Frigate"),_("subclass","Cruiser"))
/// -- Set the Phobos T3's appearance to the ModelData named "AtlasHeavyFighterYellow"
/// template:setModel("AtlasHeavyFighterYellow")
REGISTER_SCRIPT_CLASS(ShipTemplate)
{
/// Sets this ShipTemplate's unique reference name.
/// Use this value for referencing this ShipTemplate in scripts.
/// If this value begins with "Player ", including the trailing space, EmptyEpsilon uses only what follows as the name.
/// If this ShipTemplate lacks a localized name (ShipTemplate:setLocaleName()), it defaults to this reference name.
/// Example: template:setName("Phobos T3")
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setName);
/// Sets the displayed vessel model designation for ShipTemplateBasedObjects created from this ShipTemplate.
/// Use with the _ function to expose the localized name to translation.
/// Examples:
/// template:setLocaleName("Phobos T3")
/// template:setLocaleName(_("ship","Phobos T3")) -- with a translation-exposed name
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setLocaleName);
/// Sets the vessel class and subclass for ShipTemplateBasedObjects created from this ShipTemplate.
/// Vessel classes are used to define certain traits across similar ships, such as dockability.
/// See also ShipTemplate:setExternalDockClasses() and ShipTemplate:setInternalDockClasses().
/// For consistent class usage across translations, wrap class name strings in the _ function.
/// Defaults to the equivalent value of (_("No class"),_("No sub-class")).
/// Examples:
/// template:setClass(_("class","Frigate"),_("subclass","Cruiser"))
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setClass);
/// Sets the description shown in the science database for ShipTemplateBasedObjects created from this ShipTemplate.
/// Example: template:setDescription(_("The Phobos T3 is most any navy's workhorse frigate."))
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setDescription);
/// Sets the object-oriented subclass of ShipTemplateBasedObject to create from this ShipTemplate.
/// Defaults to "ship" (CpuShip).
/// Valid values are "ship", "playership" (PlayerSpaceship), and "station" (SpaceStation).
/// Using setType("station") is equivalent to also using ShipTemplate:setRepairDocked(true) and ShipTemplate:setRadarTrace("blip.png").
/// Example: template:setType("playership")
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setType);
/// If declared, this function hides this ShipTemplate from creation features and the science database.
/// Hidden templates provide backward compatibility to older scenario scripts.
/// Example: template:hidden() -- hides this template
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, hidden);
/// Sets the default combat AI state for CpuShips created from this ShipTemplate.
/// Combat AI states determine the AI's combat tactics and responses.
/// They're distinct from orders, which determine the ship's active objectives and are defined by CpuShip:order...() functions.
/// Valid combat AI states are:
/// - "default" directly pursues enemies at beam range while making opportunistic missile attacks
/// - "evasion" maintains distance from enemy weapons and evades attacks
/// - "fighter" prefers strafing maneuvers and attacks briefly at close range while passing
/// - "missilevolley" prefers lining up missile attacks from long range
/// Example: template:setAI("fighter") -- default to the "fighter" combat AI state
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setDefaultAI);
/// Sets the 3D appearance, by ModelData name, of ShipTemplateBasedObjects created from this ShipTemplate.
/// ModelData objects define a 3D mesh, textures, adjustments, and collision box, and are loaded from scripts/model_data.lua when EmptyEpsilon is launched.
/// Example: template:setModel("AtlasHeavyFighterYellow") -- uses the ModelData named "AtlasHeavyFighterYellow"
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setModel);
/// As ShipTemplate:setExternalDockClasses().
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setDockClasses);
/// Defines a list of vessel classes that can be externally docked to ShipTemplateBasedObjects created from this ShipTemplate.
/// External docking keeps the docked ship attached to the outside of the carrier.
/// By default, SpaceStations allow all classes of SpaceShips to dock externally.
/// For consistent class usage across translations, wrap class name strings in the _ function.
/// Example: template:setExternalDockClasses(_("class","Frigate"),_("class","Corvette")) -- all Frigate and Corvette ships can dock to the outside of this ShipTemplateBasedObject
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setExternalDockClasses);
/// Defines a list of ship classes that can be docked inside of ShipTemplateBasedObjects created from this ShipTemplate.
/// Internal docking stores the docked ship inside of this derived ShipTemplateBasedObject.
/// For consistent class usage across translations, wrap class name strings in the _ function.
/// Example: template:setInternalDockClasses(_("class","Starfighter")) -- all Starfighter ships can dock inside of this ShipTemplateBasedObject
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setInternalDockClasses);
/// Sets the amount of energy available for PlayerSpaceships created from this ShipTemplate.
/// Only PlayerSpaceships consume energy. Setting this for other ShipTemplateBasedObject types has no effect.
/// Defaults to 1000.
/// Example: template:setEnergyStorage(500)
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setEnergyStorage);
/// Sets the default number of repair crew for PlayerSpaceships created from this ShipTemplate.
/// Defaults to 3.
/// Only PlayerSpaceships use repair crews. Setting this for other ShipTemplateBasedObject types has no effect.
/// Example: template:setRepairCrewCount(5)
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setRepairCrewCount);
/// As ShipTemplate:setBeamWeapon().
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setBeam);
/// Defines the traits of a BeamWeapon for ShipTemplateBasedObjects created from this ShipTemplate.
/// - index: Each beam weapon in this ShipTemplate must have a unique index.
/// - arc: Sets the arc of its firing capability, in degrees.
/// - direction: Sets the default center angle of the arc, in degrees relative to the ship's forward bearing. Value can be negative.
/// - range: Sets how far away the beam can fire.
/// - cycle_time: Sets the base firing delay, in seconds. System effectiveness modifies the cycle time.
/// - damage: Sets the base damage done by the beam to the target. System effectiveness modifies the damage.
/// To add multiple beam weapons to a ship, invoke this function multiple times, assigning each weapon a unique index value.
/// To create a turreted beam, also add ShipTemplate:setBeamWeaponTurret(), and set the beam weapon's arc to be smaller than the turret's arc.
/// Example: setBeamWeapon(0,90,-15,1200,3,1) -- index 0, 90-degree arc centered -15 degrees from forward, extending 1.2U, firing every 3 seconds and dealing 1 damage
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setBeamWeapon);
/// Converts a BeamWeapon into a turret and defines its traits for SpaceShips created from this ShipTemplate.
/// A turreted beam weapon rotates within its turret arc toward the weapons target at the given rotation rate.
/// - index: Must match the index of an existing beam weapon.
/// - arc: Sets the turret's maximum targeting angles, in degrees. The turret arc must be larger than the associated beam weapon's arc.
/// - direction: Sets the default center angle of the turret arc, in degrees relative to the ship's forward bearing. Value can be negative.
/// - rotation_rate: Sets how many degrees per tick that the associated beam weapon's direction can rotate toward the target within the turret arc. System effectiveness modifies the rotation rate.
/// To create a turreted beam, also add ShipTemplate:setBeamWeapon(), and set the beam weapon's arc to be smaller than the turret's arc.
/// Example:
/// -- Makes beam weapon 0 a turret with a 200-degree turret arc centered on 90 degrees from forward, rotating at 5 degrees per tick (unit?)
/// template:setBeamWeaponTurret(0,200,90,5)
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setBeamWeaponTurret);
/// Sets the BeamEffect texture, by filename, for the BeamWeapon with the given index on SpaceShips created from this ShipTemplate.
/// See BeamEffect:setTexture().
/// Example: template:setBeamWeaponTexture("texture/beam_blue.png")
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setBeamTexture);
/// Sets how much energy is drained each time the BeamWeapon with the given index is fired.
/// Only PlayerSpaceships consume energy. Setting this for other ShipTemplateBasedObject types has no effect.
/// Defaults to 3.0, as defined in src/spaceObjects/spaceshipParts/beamWeapon.cpp.
/// Example: template:setBeamWeaponEnergyPerFire(0,1) -- sets beam 0 to use 1 energy per firing
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setBeamWeaponEnergyPerFire);
/// Sets how much "beamweapon" system heat is generated, in percentage of total system heat capacity, each time the BeamWeapon with the given index is fired.
/// Only PlayerSpaceships generate and manage heat. Setting this for other ShipTemplateBasedObject types has no effect.
/// Defaults to 0.02, as defined in src/spaceObjects/spaceshipParts/beamWeapon.cpp.
/// Example: template:setBeamWeaponHeatPerFire(0,0.5) -- sets beam 0 to generate 0.5 (50%) system heat per firing
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setBeamWeaponHeatPerFire);
/// Sets the number of WeaponTubes for ShipTemplateBasedObjects created from this ShipTemplate, and the default delay for loading and unloading each tube, in seconds.
/// Weapon tubes are 0-indexed. For example, 3 tubes would be indexed 0, 1, and 2.
/// Ships are limited to a maximum of 16 weapon tubes.
/// The default ShipTemplate adds 0 tubes and an 8-second loading time.
/// Example: template:setTubes(6,15.0) -- creates 6 weapon tubes with 15-second loading times
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setTubes);
/// Sets the delay, in seconds, for loading and unloading the WeaponTube with the given index.
/// Defaults to 8.0.
/// Example: template:setTubeLoadTime(0,12) -- sets the loading time for tube 0 to 12 seconds
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setTubeLoadTime);
/// Sets which weapon types the WeaponTube with the given index can load.
/// Note the spelling of "missle".
/// Example: template:weaponTubeAllowMissle(0,"Homing") -- allows Homing missiles to be loaded in tube 0
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, weaponTubeAllowMissle);
/// Sets which weapon types the WeaponTube with the given index can't load.
/// Note the spelling of "missle".
/// Example: template:weaponTubeDisallowMissle(0,"Homing") -- prevents Homing missiles from being loaded in tube 0
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, weaponTubeDisallowMissle);
/// Sets a WeaponTube with the given index to allow loading only the given weapon type.
/// Example: template:setWeaponTubeExclusiveFor(0,"Homing") -- allows only Homing missiles to be loaded in tube 0
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setWeaponTubeExclusiveFor);
/// Sets the angle, relative to the ShipTemplateBasedObject's forward bearing, toward which the WeaponTube with the given index points.
/// Defaults to 0. Accepts negative and positive values.
/// Example:
/// -- Sets tube 0 to point 90 degrees right of forward, and tube 1 to point 90 degrees left of forward
/// template:setTubeDirection(0,90):setTubeDirection(1,-90)
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setTubeDirection);
/// Sets the weapon size launched from the WeaponTube with the given index.
/// Defaults to "medium".
/// Example: template:setTubeSize(0,"large") -- sets tube 0 to fire large weapons
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setTubeSize);
/// Sets the number of default hull points for ShipTemplateBasedObjects created from this ShipTemplate.
/// Defaults to 70.
/// Example: template:setHull(100)
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setHull);
/// Sets the maximum points per shield segment for ShipTemplateBasedObjects created from this ShipTemplate.
/// Each argument segments the shield clockwise by dividing the arc equally for each segment, up to a maximum of 8 segments.
/// The center of the first segment's arc always faces forward.
/// A ShipTemplateBasedObject with one shield segment has only a front shield generator system, and one with two or more segments has only front and rear generator systems.
/// If not defined, the ShipTemplateBasedObject defaults to having no shield capabilities.
/// Examples:
/// template:setShields(400) -- one shield segment; hits from all angles damage the same shield
/// template:setShields(100,80) -- two shield segments; the front 180-degree shield has 100 points, the rear 80
/// template:setShields(100,50,40,30) -- four shield segments; the front 90-degree shield has 100, right 50, rear 40, and left 30
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setShields);
/// Sets the impulse speed, rotational speed, and impulse acceleration for SpaceShips created from this ShipTemplate.
/// (unit?)
/// The optional fourth and fifth arguments set the reverse speed and reverse acceleration.
/// If the reverse speed and acceleration aren't explicitly set, the defaults are equal to the forward speed and acceleration.
/// See also SpaceShip:setImpulseMaxSpeed(), SpaceShip:setRotationMaxSpeed(), SpaceShip:setAcceleration().
/// Defaults to the equivalent value of (500,10,20).
/// Example:
/// -- Sets the forward impulse speed to 80, rotational speed to 15, forward acceleration to 25, reverse speed to 20, and reverse acceleration to the same as the forward acceleration
/// template:setSpeed(80,15,25,20)
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setSpeed);
/// Sets the combat maneuver capacity for SpaceShips created from this ShipTemplate.
/// The boost value sets the forward maneuver capacity, and the strafe value sets the lateral maneuver capacity.
/// Defaults to (0,0).
/// Example: template:setCombatManeuver(400,250)
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setCombatManeuver);
/// Sets the warp speed factor for SpaceShips created from this ShipTemplate.
/// Defaults to 0. The typical warp speed value for a warp-capable ship is 1000, which is equivalent to 60U/minute at warp 1.
/// Setting any value also enables the "warp" system and controls.
/// Example: template:setWarpSpeed(1000)
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setWarpSpeed);
/// Defines whether ShipTemplateBasedObjects created from this ShipTemplate supply energy to docked PlayerSpaceships.
/// Defaults to true.
/// Example: template:setSharesEnergyWithDocked(false)
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setSharesEnergyWithDocked);
/// Defines whether ShipTemplateBasedObjects created from this template repair docked SpaceShips.
/// Defaults to false. ShipTemplate:setType("station") sets this to true.
/// Example: template:setRepairDocked(true)
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setRepairDocked);
/// Defines whether ShipTemplateBasedObjects created from this ShipTemplate restock scan probes on docked PlayerSpaceships.
/// Defaults to false.
/// Example: template:setRestocksScanProbes(true)
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setRestocksScanProbes);
/// Defines whether ShipTemplateBasedObjects created from this ShipTemplate restock missiles on docked CpuShips.
/// To restock docked PlayerSpaceships' weapons, use a comms script. See ShipTemplateBasedObject:setCommsScript() and :setCommsFunction().
/// Defaults to false.
/// Example template:setRestocksMissilesDocked(true)
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setRestocksMissilesDocked);
/// Defines whether SpaceShips created from this ShipTemplate have a jump drive.
/// Defaults to false.
/// Example: template:setJumpDrive(true)
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setJumpDrive);
/// Sets the minimum and maximum jump distances for SpaceShips created from this ShipTemplate.
/// Defaults to (5000,50000).
/// Example: template:setJumpDriveRange(2500,25000) -- sets the minimum jump distance to 2.5U and maximum to 25U
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setJumpDriveRange);
/// Not implemented.
/// Defaults to false.
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setCloaking);
/// Sets the storage capacity of the given weapon type for ShipTemplateBasedObjects created from this ShipTemplate.
/// Example: template:setWeaponStorage("HVLI", 6):setWeaponStorage("Homing",4) -- sets HVLI capacity to 6 and Homing capacity to 4
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setWeaponStorage);
/// Adds an empty room to a ShipTemplate.
/// Rooms are displayed on the engineering and damcon screens.
/// If a system room isn't accessible via other rooms connected by doors, repair crews on PlayerSpaceships might not be able to repair that system.
/// Rooms are placed on a 0-indexed integer x/y grid, with the given values representing the room's upper-left corner, and are sized by damage crew capacity (minimum 1x1).
/// To place multiple rooms, declare addRoom() multiple times.
/// Example: template::addRoom(0,0,3,2) -- adds a 3x2 room with its upper-left coordinate at position 0,0
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, addRoom);
/// Adds a room containing a ship system to a ShipTemplate.
/// Rooms are displayed on the engineering and damcon screens.
/// If a system room doesn't exist or isn't accessible via other rooms connected by doors, repair crews on PlayerSpaceships won't be able to repair that system.
/// Rooms are placed on a 0-indexed integer x/y grid, with the given values representing the room's upper-left corner, and are sized by damage crew capacity (minimum 1x1).
/// To place multiple rooms, declare addRoomSystem() multiple times.
/// Example: template:addRoomSystem(1,2,3,4,"reactor") -- adds a 3x4 room with its upper-left coordinate at position 1,2 that contains the Reactor system
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, addRoomSystem);
/// Adds a door between rooms in a ShipTemplate.
/// Doors connect rooms as displayed on the engineering and damcon screens. All doors are 1 damage crew wide.
/// If a system room isn't accessible via other rooms connected by doors, repair crews on PlayerSpaceships might not be able to repair that system.
/// The horizontal value defines whether the door is oriented horizontally (true) or vertically (false).
/// Doors are placed on a 0-indexed integer x/y grid, with the given values representing the door's left-most point (horizontal) or top-most point (vertical) point.
/// To place multiple doors, declare addDoor() multiple times.
/// Example: template:addDoor(2,1,true) -- places a horizontal door with its left-most point at 2,1
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, addDoor);
/// Sets the default radar trace image for ShipTemplateBasedObjects created from this ShipTemplate.
/// Valid values are filenames of PNG images relative to the resources/radar/ directory.
/// Radar trace images should be white with a transparent background.
/// Defaults to ship.png. ShipTemplate:setType("station") sets this to blip.png.
/// Example: template:setRadarTrace("cruiser.png")
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setRadarTrace);
/// Sets the long-range radar range of SpaceShips created from this ShipTemplate.
/// PlayerSpaceships use this range on the science and operations screens' radar.
/// AI orders of CpuShips use this range to detect potential targets.
/// Defaults to 30000.0 (30U).
/// Example: template:setLongRangeRadarRange(20000) -- sets the long-range radar range to 20U
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setLongRangeRadarRange);
/// Sets the short-range radar range of SpaceShips created from this ShipTemplate.
/// PlayerSpaceships use this range on the helms, weapons, and single pilot screens' radar.
/// AI orders of CpuShips use this range to decide when to disengage pursuit of fleeing targets.
/// This also defines the shared radar radius on the relay screen for friendly ships and stations, and how far into nebulae that this SpaceShip can detect objects.
/// Defaults to 5000.0 (5U).
/// Example: template:setShortRangeRadarRange(4000) -- sets the short-range radar range to 4U
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setShortRangeRadarRange);
/// Sets the sound file used for the impulse drive sounds on SpaceShips created from this ShipTemplate.
/// Valid values are filenames to WAV files relative to the resources directory.
/// Use a looping sound file that tolerates being pitched up and down as the ship's impulse speed changes.
/// Defaults to sfx/engine.wav.
/// Example: template:setImpulseSoundFile("sfx/engine_fighter.wav")
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setImpulseSoundFile);
/// Defines whether scanning features appear on related crew screens in PlayerSpaceships created from this ShipTemplate.
/// Defaults to true.
/// Example: template:setCanScan(false)
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setCanScan);
/// Defines whether hacking features appear on related crew screens in PlayerSpaceships created from this ShipTemplate.
/// Defaults to true.
/// Example: template:setCanHack(false)
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setCanHack);
/// Defines whether the "Request Docking" button appears on related crew screens in PlayerSpaceships created from this ShipTemplate.
/// Defaults to true.
/// Example: template:setCanDock(false)
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setCanDock);
/// Defines whether combat maneuver controls appear on related crew screens in PlayerSpaceships created from this ShipTemplate.
/// Defaults to true.
/// Example: template:setCanCombatManeuver(false)
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setCanCombatManeuver);
/// Defines whether self-destruct controls appear on related crew screens in PlayerSpaceships created from this ShipTemplate.
/// Defaults to true.
/// Example: template:setCanSelfDestruct(false)
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setCanSelfDestruct);
/// Defines whether ScanProbe-launching controls appear on related crew screens in PlayerSpaceships created from this ShipTemplate.
/// Defaults to true.
/// Example: template:setCanLaunchProbe(false)
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setCanLaunchProbe);
/// Returns an exact copy of this ShipTemplate and sets the new copy's reference name to the given name, as ShipTemplate:setName().
/// The copy retains all other traits of the copied ShipTemplate.
/// Use this function to create variations of an existing ShipTemplate.
/// Example:
/// -- Create two ShipTemplates: one with 50 hull points and one 50-point shield segment,
/// -- and a second with 50 hull points and two 25-point shield segments.
/// template = ShipTemplate():setName("Stalker Q7"):setHull(50):setShields(50)
/// variation = template:copy("Stalker Q5"):setShields(25,25)
REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, copy);
}
std::unordered_map<string, P<ShipTemplate> > ShipTemplate::templateMap;
ShipTemplate::ShipTemplate()
{
if (game_server) { LOG(ERROR) << "ShipTemplate objects can not be created during a scenario."; destroy(); return; }
type = Ship;
class_name = tr("No class");
sub_class_name = tr("No sub-class");
shares_energy_with_docked = true;
repair_docked = false;
restocks_scan_probes = false;
restocks_missiles_docked = false;
energy_storage_amount = 1000;
repair_crew_count = 3;
weapon_tube_count = 0;
for(int n=0; n<max_weapon_tubes; n++)
{
weapon_tube[n].load_time = 8.0;
weapon_tube[n].type_allowed_mask = (1 << MW_Count) - 1;
weapon_tube[n].direction = 0;
weapon_tube[n].size = MS_Medium;
}
hull = 70;
shield_count = 0;
for(int n=0; n<max_shield_count; n++)
shield_level[n] = 0.0;
impulse_speed = 500.0;
impulse_reverse_speed = 500.0;
impulse_acceleration = 20.0;
impulse_reverse_acceleration = 20.0;
turn_speed = 10.0;
combat_maneuver_boost_speed = 0.0f;
combat_maneuver_strafe_speed = 0.0f;
warp_speed = 0.0;
has_jump_drive = false;
jump_drive_min_distance = 5000.0;
jump_drive_max_distance = 50000.0;
has_cloaking = false;
for(int n=0; n<MW_Count; n++)
weapon_storage[n] = 0;
long_range_radar_range = 30000.0f;
short_range_radar_range = 5000.0f;
radar_trace = "radar/ship.png";
impulse_sound_file = "sfx/engine.wav";
default_ai_name = "default";
}
void ShipTemplate::setBeamTexture(int index, string texture)
{
if (index >= 0 && index < max_beam_weapons)
{
beams[index].setBeamTexture(texture);
}
}
void ShipTemplate::setTubes(int amount, float load_time)
{
weapon_tube_count = std::min(max_weapon_tubes, amount);
for(int n=0; n<max_weapon_tubes; n++)
weapon_tube[n].load_time = load_time;
}
void ShipTemplate::setTubeLoadTime(int index, float load_time)
{
if (index < 0 || index >= max_weapon_tubes)
return;
weapon_tube[index].load_time = load_time;
}
void ShipTemplate::weaponTubeAllowMissle(int index, EMissileWeapons type)
{
if (index < 0 || index >= max_weapon_tubes)
return;
weapon_tube[index].type_allowed_mask |= (1 << type);
}
void ShipTemplate::weaponTubeDisallowMissle(int index, EMissileWeapons type)
{
if (index < 0 || index >= max_weapon_tubes)
return;
weapon_tube[index].type_allowed_mask &=~(1 << type);
}
void ShipTemplate::setWeaponTubeExclusiveFor(int index, EMissileWeapons type)
{
if (index < 0 || index >= max_weapon_tubes)
return;
weapon_tube[index].type_allowed_mask = (1 << type);
}
void ShipTemplate::setTubeDirection(int index, float direction)
{
if (index < 0 || index >= max_weapon_tubes)
return;
weapon_tube[index].direction = direction;
}
void ShipTemplate::setTubeSize(int index, EMissileSizes size)
{
if (index < 0 || index >= max_weapon_tubes)
return;
weapon_tube[index].size = size;
}
void ShipTemplate::setType(TemplateType type)
{
if (radar_trace == "radar/ship.png" && type == Station)
{
radar_trace = "radar/blip.png";
}
if (type == Station)
repair_docked = true;
this->type = type;
}
void ShipTemplate::setName(string name)
{
if (templateMap.find(name) != templateMap.end())
{
LOG(ERROR) << "Duplicate ship template definition: " << name;
}
templateMap[name] = this;
if (name.startswith("Player "))
name = name.substr(7);
this->name = name;
if (this->locale_name == "")
this->locale_name = name;
}
void ShipTemplate::setLocaleName(string name)
{
this->locale_name = name;
}
void ShipTemplate::setClass(string class_name, string sub_class_name)
{
this->class_name = class_name;
this->sub_class_name = sub_class_name;
}
void ShipTemplate::setBeam(int index, float arc, float direction, float range, float cycle_time, float damage)
{
setBeamWeapon(index, arc, direction, range, cycle_time, damage);
}
void ShipTemplate::setBeamWeapon(int index, float arc, float direction, float range, float cycle_time, float damage)
{
if (index < 0 || index > max_beam_weapons)
return;
beams[index].setDirection(direction);
beams[index].setArc(arc);
beams[index].setRange(range);
beams[index].setCycleTime(cycle_time);
beams[index].setDamage(damage);
}
void ShipTemplate::setBeamWeaponTurret(int index, float arc, float direction, float rotation_rate)
{
if (index < 0 || index > max_beam_weapons)
return;
beams[index].setTurretArc(arc);
beams[index].setTurretDirection(direction);
beams[index].setTurretRotationRate(rotation_rate);
}
glm::ivec2 ShipTemplate::interiorSize()
{
glm::ivec2 min_pos(1000, 1000);
glm::ivec2 max_pos(0, 0);
for(unsigned int n=0; n<rooms.size(); n++)
{
min_pos.x = std::min(min_pos.x, rooms[n].position.x);
min_pos.y = std::min(min_pos.y, rooms[n].position.y);
max_pos.x = std::max(max_pos.x, rooms[n].position.x + rooms[n].size.x);
max_pos.y = std::max(max_pos.y, rooms[n].position.y + rooms[n].size.y);
}
if (min_pos != glm::ivec2(1, 1))
{
glm::ivec2 offset = glm::ivec2(1, 1) - min_pos;
for(unsigned int n=0; n<rooms.size(); n++)
rooms[n].position += offset;
for(unsigned int n=0; n<doors.size(); n++)
doors[n].position += offset;
max_pos += offset;
}
max_pos += glm::ivec2(1, 1);
return max_pos;
}
ESystem ShipTemplate::getSystemAtRoom(glm::ivec2 position)
{
for(unsigned int n=0; n<rooms.size(); n++)
{
if (rooms[n].position.x <= position.x && rooms[n].position.x + rooms[n].size.x > position.x && rooms[n].position.y <= position.y && rooms[n].position.y + rooms[n].size.y > position.y)
return rooms[n].system;
}
return SYS_None;
}
void ShipTemplate::setCollisionData(P<SpaceObject> object)
{
model_data->setCollisionData(object);
}
void ShipTemplate::setShields(const std::vector<float>& values)
{
shield_count = std::min(max_shield_count, int(values.size()));
for(int n=0; n<shield_count; n++)
{
shield_level[n] = values[n];
}
}
P<ShipTemplate> ShipTemplate::getTemplate(string name)
{
if (templateMap.find(name) == templateMap.end())
{
LOG(ERROR) << "Failed to find ship template: " << name;
return nullptr;
}
return templateMap[name];
}
std::vector<string> ShipTemplate::getAllTemplateNames()
{
std::vector<string> ret;
for(std::unordered_map<string, P<ShipTemplate> >::iterator i = templateMap.begin(); i != templateMap.end(); i++)
ret.push_back(i->first);
return ret;
}
std::vector<string> ShipTemplate::getTemplateNameList(TemplateType type)
{
std::vector<string> ret;
for(std::unordered_map<string, P<ShipTemplate> >::iterator i = templateMap.begin(); i != templateMap.end(); i++)
if (i->second->getType() == type)
ret.push_back(i->first);
return ret;
}
string getSystemName(ESystem system)
{
switch(system)
{
case SYS_Reactor: return "reactor";
case SYS_BeamWeapons: return "beamweapons";
case SYS_MissileSystem: return "missilesystem";
case SYS_Maneuver: return "maneuvering";
case SYS_Impulse: return "impulse";
case SYS_Warp: return "warp";
case SYS_JumpDrive: return "jumpdrive";
case SYS_FrontShield: return "frontshield";
case SYS_RearShield: return "rearshield";
default:
return "UNKNOWN";
}
}
string getLocaleSystemName(ESystem system)
{
switch(system)
{
case SYS_Reactor: return tr("system", "Reactor");
case SYS_BeamWeapons: return tr("system", "Beam Weapons");
case SYS_MissileSystem: return tr("system", "Missile System");
case SYS_Maneuver: return tr("system", "Maneuvering");
case SYS_Impulse: return tr("system", "Impulse Engines");
case SYS_Warp: return tr("system", "Warp Drive");
case SYS_JumpDrive: return tr("system", "Jump Drive");
case SYS_FrontShield: return tr("system", "Front Shield Generator");
case SYS_RearShield: return tr("system", "Rear Shield Generator");
default:
return "UNKNOWN";
}
}
void ShipTemplate::setDescription(string description)
{
this->description = description;
}
void ShipTemplate::setModel(string model_name)
{
this->model_data = ModelData::getModel(model_name);
}
void ShipTemplate::setDefaultAI(string default_ai_name)
{
this->default_ai_name = default_ai_name;
}
void ShipTemplate::setDockClasses(const std::vector<string>& classes)
{
external_dock_classes = std::unordered_set<string>(classes.begin(), classes.end());
}
void ShipTemplate::setExternalDockClasses(const std::vector<string>& classes)
{
external_dock_classes = std::unordered_set<string>(classes.begin(), classes.end());
}
void ShipTemplate::setInternalDockClasses(const std::vector<string>& classes)
{
internal_dock_classes = std::unordered_set<string>(classes.begin(), classes.end());
}
void ShipTemplate::setSpeed(float impulse, float turn, float acceleration, std::optional<float> reverse_speed, std::optional<float> reverse_acceleration)
{
impulse_speed = impulse;
turn_speed = turn;
impulse_acceleration = acceleration;
impulse_reverse_speed = reverse_speed.value_or(impulse);
impulse_reverse_acceleration = reverse_acceleration.value_or(acceleration);
}
void ShipTemplate::setCombatManeuver(float boost, float strafe)
{
combat_maneuver_boost_speed = boost;
combat_maneuver_strafe_speed = strafe;
}
void ShipTemplate::setWarpSpeed(float warp)
{
warp_speed = warp;
}
void ShipTemplate::setSharesEnergyWithDocked(bool enabled)
{
shares_energy_with_docked = enabled;
}
void ShipTemplate::setRepairDocked(bool enabled)
{
repair_docked = enabled;
}
void ShipTemplate::setRestocksScanProbes(bool enabled)
{
restocks_scan_probes = enabled;
}
void ShipTemplate::setRestocksMissilesDocked(bool enabled)
{
restocks_missiles_docked = enabled;
}
void ShipTemplate::setJumpDrive(bool enabled)
{
has_jump_drive = enabled;
}
void ShipTemplate::setCloaking(bool enabled)
{
has_cloaking = enabled;
}
void ShipTemplate::setWeaponStorage(EMissileWeapons weapon, int amount)
{
if (weapon != MW_None)
{
weapon_storage[weapon] = amount;
}
}
void ShipTemplate::addRoom(glm::ivec2 position, glm::ivec2 size)
{
rooms.push_back(ShipRoomTemplate(position, size, SYS_None));
}
void ShipTemplate::addRoomSystem(glm::ivec2 position, glm::ivec2 size, ESystem system)
{
rooms.push_back(ShipRoomTemplate(position, size, system));
}
void ShipTemplate::addDoor(glm::ivec2 position, bool horizontal)
{
doors.push_back(ShipDoorTemplate(position, horizontal));
}
void ShipTemplate::setRadarTrace(string trace)
{
radar_trace = "radar/" + trace;
}
void ShipTemplate::setLongRangeRadarRange(float range)
{
range = std::max(range, 100.0f);
long_range_radar_range = range;
short_range_radar_range = std::min(short_range_radar_range, range);
}
void ShipTemplate::setShortRangeRadarRange(float range)
{
range = std::max(range, 100.0f);
short_range_radar_range = range;
long_range_radar_range = std::max(long_range_radar_range, range);
}
void ShipTemplate::setImpulseSoundFile(string sound)
{
impulse_sound_file = sound;
}
P<ShipTemplate> ShipTemplate::copy(string new_name)
{
P<ShipTemplate> result = new ShipTemplate();
result->setName(new_name);
result->description = description;
result->class_name = class_name;
result->sub_class_name = sub_class_name;
result->type = type;
result->model_data = model_data;
result->external_dock_classes = external_dock_classes;
result->internal_dock_classes = internal_dock_classes;
result->energy_storage_amount = energy_storage_amount;
result->repair_crew_count = repair_crew_count;
result->can_scan = can_scan;
result->can_hack = can_hack;
result->can_dock = can_dock;
result->can_combat_maneuver = can_combat_maneuver;
result->can_self_destruct = can_self_destruct;
result->can_launch_probe = can_launch_probe;
result->default_ai_name = default_ai_name;
for(int n=0; n<max_beam_weapons; n++)
result->beams[n] = beams[n];
result->weapon_tube_count = weapon_tube_count;
for(int n=0; n<max_weapon_tubes; n++)
result->weapon_tube[n] = weapon_tube[n];
result->hull = hull;
result->shield_count = shield_count;
for(int n=0; n<max_shield_count; n++)
result->shield_level[n] = shield_level[n];
result->impulse_speed = impulse_speed;
result->impulse_reverse_speed = impulse_reverse_speed;
result->turn_speed = turn_speed;
result->warp_speed = warp_speed;
result->impulse_acceleration = impulse_acceleration;
result->impulse_reverse_acceleration = impulse_reverse_acceleration;
result->combat_maneuver_boost_speed = combat_maneuver_boost_speed;
result->combat_maneuver_strafe_speed = combat_maneuver_strafe_speed;
result->shares_energy_with_docked = shares_energy_with_docked;
result->repair_docked = repair_docked;
result->restocks_scan_probes = restocks_scan_probes;
result->restocks_missiles_docked = restocks_missiles_docked;
result->has_jump_drive = has_jump_drive;
result->has_cloaking = has_cloaking;
for(int n=0; n<MW_Count; n++)
result->weapon_storage[n] = weapon_storage[n];
result->radar_trace = radar_trace;
result->rooms = rooms;
result->doors = doors;
return result;
}
void ShipTemplate::setEnergyStorage(float energy_amount)
{
this->energy_storage_amount = energy_amount;
}
void ShipTemplate::setRepairCrewCount(int amount)
{
this->repair_crew_count = amount;
}
string ShipTemplate::getName()
{
return this->name;
}
string ShipTemplate::getLocaleName()
{
return this->locale_name;
}
string ShipTemplate::getDescription()
{
return this->description;
}
string ShipTemplate::getClass()
{
return this->class_name;
}
string ShipTemplate::getSubClass()
{
return this->sub_class_name;
}
ShipTemplate::TemplateType ShipTemplate::getType()
{
return type;
}
#include "shipTemplate.hpp"