1 #include <i18n.h>
2 #include <optional>
3 #include "shipTemplate.h"
4 #include "spaceObjects/spaceObject.h"
5 #include "mesh.h"
6 
7 #include "scriptInterface.h"
8 
9 /// ShipTemplates are created when EmptyEpsilon is started.
10 /// And used to fill the ship starting statistics, and other information.
REGISTER_SCRIPT_CLASS(ShipTemplate)11 REGISTER_SCRIPT_CLASS(ShipTemplate)
12 {
13     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setName);
14     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setLocaleName);
15     /// Set the class name, and subclass name for the ship. Used to divide ships into different classes.
16     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setClass);
17     /// Set the description shown for this ship in the science database.
18     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setDescription);
19     /// Sets the type of template. Defaults to normal ships, so then it does not need to be set.
20     /// Example: template:setType("ship"), template:setType("playership"), template:setType("station")
21     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setType);
22     /// Set the default AI behaviour. EE has 3 types of AI coded into the game right now: "default", "fighter", "missilevolley"
23     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setDefaultAI);
24     /// Set the 3D model to be used for this template. The model referers to data set in the model_data.lua file.
25     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setModel);
26     /// Supply a list of ship classes that can be docked to this ship. setDockClasses("Starfighter") will allow all small starfighter type ships to dock with this ship.
27     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setDockClasses);
28     /// Set the amount of energy available for this ship. Note that only player ships use energy. So setting this for anything else is useless.
29     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setEnergyStorage);
30     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setRepairCrewCount);
31     /// Setup a beam weapon.
32     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setBeam);
33     /// Setup a beam weapon.
34     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setBeamWeapon);
35     /// Setup a beam's turret.
36     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setBeamWeaponTurret);
37     /// Setup a beam weapon texture
38     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setBeamTexture);
39     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setBeamWeaponEnergyPerFire);
40     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setBeamWeaponHeatPerFire);
41 
42     /// Set the amount of missile tubes, limited to a maximum of 16.
43     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setTubes);
44     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setTubeLoadTime);
45     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, weaponTubeAllowMissle);
46     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, weaponTubeDisallowMissle);
47     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setWeaponTubeExclusiveFor);
48     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setTubeDirection);
49     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setTubeSize);
50 
51     /// Set the amount of starting hull
52     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setHull);
53     /// Set the shield levels, amount of parameters defines the amount of shields. (Up to a maximum of 8 shields)
54     /// Example: setShieldData(400) setShieldData(100, 80) setShieldData(100, 50, 50)
55     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setShields);
56     /// Set the impulse speed, rotation speed and impulse acceleration for this ship.
57     /// Optional fourth and fifth arguments are reverse speed and reverse acceeleration.
58     /// If not explicitely set, reverse speed and reverse acceleration are set to forward speed and acceleration
59     /// Compare SpaceShip:setImpulseMaxSpeed, :setRotationMaxSpeed, :setAcceleration.
60     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setSpeed);
61     /// Sets the combat maneuver power of this ship.
62     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setCombatManeuver);
63     /// Set the warp speed for warp level 1 for this ship. Setting this will indicate that this ship has a warpdrive. (normal value is 1000)
64     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setWarpSpeed);
65     /// Set if this ship shares energy with docked ships. Example: template:setSharesEnergyWithDocked(false)
66     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setSharesEnergyWithDocked);
67     /// Set if this ship repairs docked ships. Example: template:setRepairDocked(false)
68     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setRepairDocked);
69     /// Set if this ship restocks scan probes on docked ships. Example: template:setRestocksScanProbes(false)
70     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setRestocksScanProbes);
71     /// Set if this ship restores missiles on docked cpuships. Example template:setRestocksMissilesDocked(false)
72     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setRestocksMissilesDocked);
73     /// Set if this ship has a jump drive. Example: template:setJumpDrive(true)
74     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setJumpDrive);
75     /// Set this ship's minimum and maximum jump drive distances.
76     /// Example: template:setJumpDrive(5000.0, 50000.0)
77     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setJumpDriveRange);
78     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setCloaking);
79     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setWeaponStorage);
80     /// Add an empty room to a ship template.
81     /// Rooms are shown on the engineering and damcon screens.
82     /// If a system room isn't accessible via other rooms connected by doors, that system
83     /// might not be repairable.
84     /// Rooms are placed on an integer x/y grid. The minimum size for a room is 1x1.
85     /// Accepts four parameters: the room's x coordinate, y coordinate, width, and height.
86     /// Example: template:addRoom(1, 2, 3, 4)
87     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, addRoom);
88     /// Add a room containing a ship system to a ship template.
89     /// Rooms are shown on the engineering and damcon screens.
90     /// If a system doesn't have a room, or repair crews can't reach a system's room, it
91     /// might not be repairable.
92     /// Accepts five parameters: the room's x coordinate, y coordinate, width, height, and
93     /// the ship system as the string equivalent of an ESystem value.
94     /// Example: template:addRoomSystem(1, 2, 3, 4, "Reactor")
95     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, addRoomSystem);
96     /// Add a door between rooms in a ship template.
97     /// Rooms are shown on the engineering and damcon screens.
98     /// If a system room doesn't have a door connecting it to other rooms, repair crews
99     /// might not be able to reach it for repairs.
100     /// Accepts three parameters: the door's x coordinate, y coordinate, and a Boolean
101     /// value for whether it's horizontal (true) or vertical (false).
102     /// Example: template:addDoor(2, 2, false)
103     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, addDoor);
104     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setRadarTrace);
105     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setLongRangeRadarRange);
106     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setShortRangeRadarRange);
107     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setImpulseSoundFile);
108     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setCanScan);
109     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setCanHack);
110     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setCanDock);
111     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setCanCombatManeuver);
112     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setCanSelfDestruct);
113     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, setCanLaunchProbe);
114     /// Return a new template with the given name, which is an exact copy of this template.
115     /// Used to make easy variations of templates.
116     REGISTER_SCRIPT_CLASS_FUNCTION(ShipTemplate, copy);
117 }
118 
119 std::unordered_map<string, P<ShipTemplate> > ShipTemplate::templateMap;
120 
ShipTemplate()121 ShipTemplate::ShipTemplate()
122 {
123     if (game_server) { LOG(ERROR) << "ShipTemplate objects can not be created during a scenario."; destroy(); return; }
124 
125     type = Ship;
126     class_name = tr("No class");
127     sub_class_name = tr("No sub-class");
128     shares_energy_with_docked = true;
129     repair_docked = false;
130     restocks_scan_probes = false;
131     restocks_missiles_docked = false;
132     energy_storage_amount = 1000;
133     repair_crew_count = 3;
134     weapon_tube_count = 0;
135     for(int n=0; n<max_weapon_tubes; n++)
136     {
137         weapon_tube[n].load_time = 8.0;
138         weapon_tube[n].type_allowed_mask = (1 << MW_Count) - 1;
139         weapon_tube[n].direction = 0;
140         weapon_tube[n].size = MS_Medium;
141     }
142     hull = 70;
143     shield_count = 0;
144     for(int n=0; n<max_shield_count; n++)
145         shield_level[n] = 0.0;
146     impulse_speed = 500.0;
147     impulse_reverse_speed = 500.0;
148     impulse_acceleration = 20.0;
149     impulse_reverse_acceleration = 20.0;
150     turn_speed = 10.0;
151     combat_maneuver_boost_speed = 0.0f;
152     combat_maneuver_strafe_speed = 0.0f;
153     warp_speed = 0.0;
154     has_jump_drive = false;
155     jump_drive_min_distance = 5000.0;
156     jump_drive_max_distance = 50000.0;
157     has_cloaking = false;
158     for(int n=0; n<MW_Count; n++)
159         weapon_storage[n] = 0;
160     long_range_radar_range = 30000.0f;
161     short_range_radar_range = 5000.0f;
162     radar_trace = "RadarArrow.png";
163     impulse_sound_file = "sfx/engine.wav";
164     default_ai_name = "default";
165 }
166 
setBeamTexture(int index,string texture)167 void ShipTemplate::setBeamTexture(int index, string texture)
168 
169 {
170     if (index >= 0 && index < max_beam_weapons)
171     {
172         beams[index].setBeamTexture(texture);
173     }
174 }
175 
setTubes(int amount,float load_time)176 void ShipTemplate::setTubes(int amount, float load_time)
177 {
178     weapon_tube_count = std::min(max_weapon_tubes, amount);
179     for(int n=0; n<max_weapon_tubes; n++)
180         weapon_tube[n].load_time = load_time;
181 }
182 
setTubeLoadTime(int index,float load_time)183 void ShipTemplate::setTubeLoadTime(int index, float load_time)
184 {
185     if (index < 0 || index >= max_weapon_tubes)
186         return;
187     weapon_tube[index].load_time = load_time;
188 }
189 
weaponTubeAllowMissle(int index,EMissileWeapons type)190 void ShipTemplate::weaponTubeAllowMissle(int index, EMissileWeapons type)
191 {
192     if (index < 0 || index >= max_weapon_tubes)
193         return;
194     weapon_tube[index].type_allowed_mask |= (1 << type);
195 }
196 
weaponTubeDisallowMissle(int index,EMissileWeapons type)197 void ShipTemplate::weaponTubeDisallowMissle(int index, EMissileWeapons type)
198 {
199     if (index < 0 || index >= max_weapon_tubes)
200         return;
201     weapon_tube[index].type_allowed_mask &=~(1 << type);
202 }
203 
setWeaponTubeExclusiveFor(int index,EMissileWeapons type)204 void ShipTemplate::setWeaponTubeExclusiveFor(int index, EMissileWeapons type)
205 {
206     if (index < 0 || index >= max_weapon_tubes)
207         return;
208     weapon_tube[index].type_allowed_mask = (1 << type);
209 }
210 
setTubeDirection(int index,float direction)211 void ShipTemplate::setTubeDirection(int index, float direction)
212 {
213     if (index < 0 || index >= max_weapon_tubes)
214         return;
215     weapon_tube[index].direction = direction;
216 }
217 
setTubeSize(int index,EMissileSizes size)218 void ShipTemplate::setTubeSize(int index, EMissileSizes size)
219 {
220     if (index < 0 || index >= max_weapon_tubes)
221         return;
222     weapon_tube[index].size = size;
223 }
224 
setType(TemplateType type)225 void ShipTemplate::setType(TemplateType type)
226 {
227     if (radar_trace == "RadarArrow.png" && type == Station)
228     {
229         radar_trace = "RadarBlip.png";
230     }
231     if (type == Station)
232         repair_docked = true;
233     this->type = type;
234 }
235 
setName(string name)236 void ShipTemplate::setName(string name)
237 {
238     if (templateMap.find(name) != templateMap.end())
239     {
240         LOG(ERROR) << "Duplicate ship template definition: " << name;
241     }
242 
243     templateMap[name] = this;
244     if (name.startswith("Player "))
245         name = name.substr(7);
246     this->name = name;
247     if (this->locale_name == "")
248         this->locale_name = name;
249 }
250 
setLocaleName(string name)251 void ShipTemplate::setLocaleName(string name)
252 {
253     this->locale_name = name;
254 }
255 
setClass(string class_name,string sub_class_name)256 void ShipTemplate::setClass(string class_name, string sub_class_name)
257 {
258     this->class_name = class_name;
259     this->sub_class_name = sub_class_name;
260 }
261 
setBeam(int index,float arc,float direction,float range,float cycle_time,float damage)262 void ShipTemplate::setBeam(int index, float arc, float direction, float range, float cycle_time, float damage)
263 {
264     setBeamWeapon(index, arc, direction, range, cycle_time, damage);
265 }
266 
setBeamWeapon(int index,float arc,float direction,float range,float cycle_time,float damage)267 void ShipTemplate::setBeamWeapon(int index, float arc, float direction, float range, float cycle_time, float damage)
268 {
269     if (index < 0 || index > max_beam_weapons)
270         return;
271     beams[index].setDirection(direction);
272     beams[index].setArc(arc);
273     beams[index].setRange(range);
274     beams[index].setCycleTime(cycle_time);
275     beams[index].setDamage(damage);
276 }
277 
setBeamWeaponTurret(int index,float arc,float direction,float rotation_rate)278 void ShipTemplate::setBeamWeaponTurret(int index, float arc, float direction, float rotation_rate)
279 {
280     if (index < 0 || index > max_beam_weapons)
281         return;
282     beams[index].setTurretArc(arc);
283     beams[index].setTurretDirection(direction);
284     beams[index].setTurretRotationRate(rotation_rate);
285 }
286 
interiorSize()287 sf::Vector2i ShipTemplate::interiorSize()
288 {
289     sf::Vector2i min_pos(1000, 1000);
290     sf::Vector2i max_pos(0, 0);
291     for(unsigned int n=0; n<rooms.size(); n++)
292     {
293         min_pos.x = std::min(min_pos.x, rooms[n].position.x);
294         min_pos.y = std::min(min_pos.y, rooms[n].position.y);
295         max_pos.x = std::max(max_pos.x, rooms[n].position.x + rooms[n].size.x);
296         max_pos.y = std::max(max_pos.y, rooms[n].position.y + rooms[n].size.y);
297     }
298     if (min_pos != sf::Vector2i(1, 1))
299     {
300         sf::Vector2i offset = sf::Vector2i(1, 1) - min_pos;
301         for(unsigned int n=0; n<rooms.size(); n++)
302             rooms[n].position += offset;
303         for(unsigned int n=0; n<doors.size(); n++)
304             doors[n].position += offset;
305         max_pos += offset;
306     }
307     max_pos += sf::Vector2i(1, 1);
308     return max_pos;
309 }
310 
getSystemAtRoom(sf::Vector2i position)311 ESystem ShipTemplate::getSystemAtRoom(sf::Vector2i position)
312 {
313     for(unsigned int n=0; n<rooms.size(); n++)
314     {
315         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)
316             return rooms[n].system;
317     }
318     return SYS_None;
319 }
320 
setCollisionData(P<SpaceObject> object)321 void ShipTemplate::setCollisionData(P<SpaceObject> object)
322 {
323     model_data->setCollisionData(object);
324 }
325 
setShields(std::vector<float> values)326 void ShipTemplate::setShields(std::vector<float> values)
327 {
328     shield_count = std::min(max_shield_count, int(values.size()));
329     for(int n=0; n<shield_count; n++)
330     {
331         shield_level[n] = values[n];
332     }
333 }
334 
335 
getTemplate(string name)336 P<ShipTemplate> ShipTemplate::getTemplate(string name)
337 {
338     if (templateMap.find(name) == templateMap.end())
339     {
340         LOG(ERROR) << "Failed to find ship template: " << name;
341         return nullptr;
342     }
343     return templateMap[name];
344 }
345 
getAllTemplateNames()346 std::vector<string> ShipTemplate::getAllTemplateNames()
347 {
348     std::vector<string> ret;
349     for(std::unordered_map<string, P<ShipTemplate> >::iterator i = templateMap.begin(); i != templateMap.end(); i++)
350         ret.push_back(i->first);
351     return ret;
352 }
353 
getTemplateNameList(TemplateType type)354 std::vector<string> ShipTemplate::getTemplateNameList(TemplateType type)
355 {
356     std::vector<string> ret;
357     for(std::unordered_map<string, P<ShipTemplate> >::iterator i = templateMap.begin(); i != templateMap.end(); i++)
358         if (i->second->getType() == type)
359             ret.push_back(i->first);
360     return ret;
361 }
362 
getSystemName(ESystem system)363 string getSystemName(ESystem system)
364 {
365     switch(system)
366     {
367     case SYS_Reactor: return "Reactor";
368     case SYS_BeamWeapons: return "Beam Weapons";
369     case SYS_MissileSystem: return "Missile System";
370     case SYS_Maneuver: return "Maneuvering";
371     case SYS_Impulse: return "Impulse Engines";
372     case SYS_Warp: return "Warp Drive";
373     case SYS_JumpDrive: return "Jump Drive";
374     case SYS_FrontShield: return "Front Shield Generator";
375     case SYS_RearShield: return "Rear Shield Generator";
376     default:
377         return "UNKNOWN";
378     }
379 }
380 
getLocaleSystemName(ESystem system)381 string getLocaleSystemName(ESystem system)
382 {
383     switch(system)
384     {
385     case SYS_Reactor: return tr("system", "Reactor");
386     case SYS_BeamWeapons: return tr("system", "Beam Weapons");
387     case SYS_MissileSystem: return tr("system", "Missile System");
388     case SYS_Maneuver: return tr("system", "Maneuvering");
389     case SYS_Impulse: return tr("system", "Impulse Engines");
390     case SYS_Warp: return tr("system", "Warp Drive");
391     case SYS_JumpDrive: return tr("system", "Jump Drive");
392     case SYS_FrontShield: return tr("system", "Front Shield Generator");
393     case SYS_RearShield: return tr("system", "Rear Shield Generator");
394     default:
395         return "UNKNOWN";
396     }
397 }
398 
setDescription(string description)399 void ShipTemplate::setDescription(string description)
400 {
401     this->description = description;
402 }
403 
setModel(string model_name)404 void ShipTemplate::setModel(string model_name)
405 {
406     this->model_data = ModelData::getModel(model_name);
407 }
408 
setDefaultAI(string default_ai_name)409 void ShipTemplate::setDefaultAI(string default_ai_name)
410 {
411     this->default_ai_name = default_ai_name;
412 }
413 
setDockClasses(std::vector<string> classes)414 void ShipTemplate::setDockClasses(std::vector<string> classes)
415 {
416     can_be_docked_by_class = std::unordered_set<string>(classes.begin(), classes.end());
417 }
418 
setSpeed(float impulse,float turn,float acceleration,std::optional<float> reverse_speed,std::optional<float> reverse_acceleration)419 void ShipTemplate::setSpeed(float impulse, float turn, float acceleration, std::optional<float> reverse_speed, std::optional<float> reverse_acceleration)
420 {
421     impulse_speed = impulse;
422     turn_speed = turn;
423     impulse_acceleration = acceleration;
424 
425     impulse_reverse_speed = reverse_speed.value_or(impulse);
426     impulse_reverse_acceleration = reverse_acceleration.value_or(acceleration);
427 }
428 
setCombatManeuver(float boost,float strafe)429 void ShipTemplate::setCombatManeuver(float boost, float strafe)
430 {
431     combat_maneuver_boost_speed = boost;
432     combat_maneuver_strafe_speed = strafe;
433 }
434 
setWarpSpeed(float warp)435 void ShipTemplate::setWarpSpeed(float warp)
436 {
437     warp_speed = warp;
438 }
439 
setSharesEnergyWithDocked(bool enabled)440 void ShipTemplate::setSharesEnergyWithDocked(bool enabled)
441 {
442     shares_energy_with_docked = enabled;
443 }
444 
setRepairDocked(bool enabled)445 void ShipTemplate::setRepairDocked(bool enabled)
446 {
447     repair_docked = enabled;
448 }
449 
setRestocksScanProbes(bool enabled)450 void ShipTemplate::setRestocksScanProbes(bool enabled)
451 {
452     restocks_scan_probes = enabled;
453 }
454 
setRestocksMissilesDocked(bool enabled)455 void ShipTemplate::setRestocksMissilesDocked(bool enabled)
456 {
457     restocks_missiles_docked = enabled;
458 }
459 
setJumpDrive(bool enabled)460 void ShipTemplate::setJumpDrive(bool enabled)
461 {
462     has_jump_drive = enabled;
463 }
464 
setCloaking(bool enabled)465 void ShipTemplate::setCloaking(bool enabled)
466 {
467     has_cloaking = enabled;
468 }
469 
setWeaponStorage(EMissileWeapons weapon,int amount)470 void ShipTemplate::setWeaponStorage(EMissileWeapons weapon, int amount)
471 {
472     if (weapon != MW_None)
473     {
474         weapon_storage[weapon] = amount;
475     }
476 }
477 
addRoom(sf::Vector2i position,sf::Vector2i size)478 void ShipTemplate::addRoom(sf::Vector2i position, sf::Vector2i size)
479 {
480     rooms.push_back(ShipRoomTemplate(position, size, SYS_None));
481 }
482 
addRoomSystem(sf::Vector2i position,sf::Vector2i size,ESystem system)483 void ShipTemplate::addRoomSystem(sf::Vector2i position, sf::Vector2i size, ESystem system)
484 {
485     rooms.push_back(ShipRoomTemplate(position, size, system));
486 }
487 
addDoor(sf::Vector2i position,bool horizontal)488 void ShipTemplate::addDoor(sf::Vector2i position, bool horizontal)
489 {
490     doors.push_back(ShipDoorTemplate(position, horizontal));
491 }
492 
setRadarTrace(string trace)493 void ShipTemplate::setRadarTrace(string trace)
494 {
495     radar_trace = trace;
496 }
497 
setLongRangeRadarRange(float range)498 void ShipTemplate::setLongRangeRadarRange(float range)
499 {
500     range = std::max(range, 100.0f);
501     long_range_radar_range = range;
502     short_range_radar_range = std::min(short_range_radar_range, range);
503 }
504 
setShortRangeRadarRange(float range)505 void ShipTemplate::setShortRangeRadarRange(float range)
506 {
507     range = std::max(range, 100.0f);
508     short_range_radar_range = range;
509     long_range_radar_range = std::max(long_range_radar_range, range);
510 }
511 
setImpulseSoundFile(string sound)512 void ShipTemplate::setImpulseSoundFile(string sound)
513 {
514     impulse_sound_file = sound;
515 }
516 
copy(string new_name)517 P<ShipTemplate> ShipTemplate::copy(string new_name)
518 {
519     P<ShipTemplate> result = new ShipTemplate();
520     result->setName(new_name);
521 
522     result->description = description;
523     result->class_name = class_name;
524     result->sub_class_name = sub_class_name;
525     result->type = type;
526     result->model_data = model_data;
527 
528     result->can_be_docked_by_class = can_be_docked_by_class;
529     result->energy_storage_amount = energy_storage_amount;
530     result->repair_crew_count = repair_crew_count;
531 
532     result->can_scan = can_scan;
533     result->can_hack = can_hack;
534     result->can_dock = can_dock;
535     result->can_combat_maneuver = can_combat_maneuver;
536     result->can_self_destruct = can_self_destruct;
537     result->can_launch_probe = can_launch_probe;
538 
539     result->default_ai_name = default_ai_name;
540     for(int n=0; n<max_beam_weapons; n++)
541         result->beams[n] = beams[n];
542     result->weapon_tube_count = weapon_tube_count;
543     for(int n=0; n<max_beam_weapons; n++)
544         result->weapon_tube[n] = weapon_tube[n];
545     result->hull = hull;
546     result->shield_count = shield_count;
547     for(int n=0; n<max_shield_count; n++)
548         result->shield_level[n] = shield_level[n];
549     result->impulse_speed = impulse_speed;
550     result->impulse_reverse_speed = impulse_reverse_speed;
551     result->turn_speed = turn_speed;
552     result->warp_speed = warp_speed;
553     result->impulse_acceleration = impulse_acceleration;
554     result->impulse_reverse_acceleration = impulse_reverse_acceleration;
555     result->combat_maneuver_boost_speed = combat_maneuver_boost_speed;
556     result->combat_maneuver_strafe_speed = combat_maneuver_strafe_speed;
557     result->shares_energy_with_docked = shares_energy_with_docked;
558     result->repair_docked = repair_docked;
559     result->restocks_scan_probes = restocks_scan_probes;
560     result->restocks_missiles_docked = restocks_missiles_docked;
561     result->has_jump_drive = has_jump_drive;
562     result->has_cloaking = has_cloaking;
563     for(int n=0; n<MW_Count; n++)
564         result->weapon_storage[n] = weapon_storage[n];
565     result->radar_trace = radar_trace;
566 
567     result->rooms = rooms;
568     result->doors = doors;
569 
570     return result;
571 }
572 
setEnergyStorage(float energy_amount)573 void ShipTemplate::setEnergyStorage(float energy_amount)
574 {
575     this->energy_storage_amount = energy_amount;
576 }
577 
setRepairCrewCount(int amount)578 void ShipTemplate::setRepairCrewCount(int amount)
579 {
580     this->repair_crew_count = amount;
581 }
582 
getName()583 string ShipTemplate::getName()
584 {
585     return this->name;
586 }
587 
getLocaleName()588 string ShipTemplate::getLocaleName()
589 {
590     return this->locale_name;
591 }
592 
getDescription()593 string ShipTemplate::getDescription()
594 {
595     return this->description;
596 }
597 
getClass()598 string ShipTemplate::getClass()
599 {
600     return this->class_name;
601 }
602 
getSubClass()603 string ShipTemplate::getSubClass()
604 {
605     return this->sub_class_name;
606 }
607 
getType()608 ShipTemplate::TemplateType ShipTemplate::getType()
609 {
610     return type;
611 }
612 
613 #include "shipTemplate.hpp"
614