ship.patch (45,760 bytes)
2014-12-23 14:32
Index: code/ship/ship.cpp
===================================================================
--- code/ship/ship.cpp (revision 11204)
+++ code/ship/ship.cpp (working copy)
@@ -162,6 +162,7 @@
ship_info Ship_info[MAX_SHIP_CLASSES];
reinforcements Reinforcements[MAX_REINFORCEMENTS];
+SCP_vector<ship_info> Ship_templates;
static char **tspecies_names = NULL;
@@ -655,7 +656,325 @@
#define SHIP_MULTITEXT_LENGTH 4096
#define DEFAULT_DELTA_BANK_CONST 0.5f
+#define CHECK_THEN_COPY(attribute) \
+do {\
+ if (other.attribute != NULL)\
+ attribute = vm_strdup( other.attribute );\
+} while(false)
+void ship_info::clone(const ship_info& other)
+{
+ strcpy_s(name, other.name);
+ strcpy_s(alt_name, other.alt_name);
+ strcpy_s(short_name, other.short_name);
+ species = other.species;
+ class_type = other.class_type;
+
+ CHECK_THEN_COPY(type_str);
+ CHECK_THEN_COPY(maneuverability_str);
+ CHECK_THEN_COPY(armor_str);
+ CHECK_THEN_COPY(manufacturer_str);
+ CHECK_THEN_COPY(desc);
+ CHECK_THEN_COPY(tech_desc);
+
+ strcpy_s(tech_title, other.tech_title);
+
+ CHECK_THEN_COPY(ship_length);
+ CHECK_THEN_COPY(gun_mounts);
+ CHECK_THEN_COPY(missile_banks);
+
+ strcpy_s(cockpit_pof_file, other.cockpit_pof_file);
+ cockpit_offset = other.cockpit_offset;
+ strcpy_s(pof_file, other.pof_file);
+ strcpy_s(pof_file_hud, other.pof_file_hud);
+ num_detail_levels = other.num_detail_levels;
+ memcpy(detail_distance, other.detail_distance, sizeof(int) * MAX_SHIP_DETAIL_LEVELS);
+
+ // I'm not sure if these three are A) a good idea or B) relevant at all. -MageKing17
+ cockpit_model_num = other.cockpit_model_num;
+ model_num = other.model_num;
+ model_num_hud = other.model_num_hud;
+
+ hud_target_lod = other.hud_target_lod;
+ density = other.density;
+ damp = other.damp;
+ rotdamp = other.rotdamp;
+ delta_bank_const = other.delta_bank_const;
+ max_vel = other.max_vel;
+ max_rotvel = other.max_rotvel;
+ rotation_time = other.rotation_time;
+ srotation_time = other.srotation_time;
+ max_rear_vel = other.max_rear_vel;
+ forward_accel = other.forward_accel;
+ forward_decel = other.forward_decel;
+ slide_accel = other.slide_accel;
+ slide_decel = other.slide_decel;
+
+ strcpy_s(warpin_anim, other.warpin_anim);
+ warpin_radius = other.warpin_radius;
+ warpin_snd_start = other.warpin_snd_start;
+ warpin_snd_end = other.warpin_snd_end;
+ warpin_speed = other.warpin_speed;
+ warpin_time = other.warpin_time;
+ warpin_decel_exp = other.warpin_decel_exp;
+ warpin_type = other.warpin_type;
+
+ strcpy_s(warpout_anim, other.warpout_anim);
+ warpout_radius = other.warpout_radius;
+ warpout_snd_start = other.warpout_snd_start;
+ warpout_snd_end = other.warpout_snd_end;
+ warpout_engage_time = other.warpout_engage_time;
+ warpout_speed = other.warpout_speed;
+ warpout_time = other.warpout_time;
+ warpout_accel_exp = other.warpout_accel_exp;
+ warpout_type = other.warpout_type;
+
+ warpout_player_speed = other.warpout_player_speed;
+
+ flags = other.flags;
+ flags2 = other.flags2;
+ ai_class = other.ai_class;
+ max_speed = other.max_speed;
+ min_speed = other.min_speed;
+ max_accel = other.max_accel;
+
+ collision_damage_type_idx = other.collision_damage_type_idx;
+ collision_physics = other.collision_physics;
+
+ memcpy(&shockwave, &other.shockwave, sizeof(shockwave_create_info));
+ explosion_propagates = other.explosion_propagates;
+ big_exp_visual_rad = other.big_exp_visual_rad;
+ prop_exp_rad_mult = other.prop_exp_rad_mult;
+ death_roll_r_mult = other.death_roll_r_mult;
+ death_fx_r_mult = other.death_fx_r_mult;
+ death_roll_time_mult = other.death_roll_time_mult;
+ death_roll_base_time = other.death_roll_base_time;
+ death_fx_count = other.death_fx_count;
+ shockwave_count = other.shockwave_count;
+ explosion_bitmap_anims = other.explosion_bitmap_anims;
+ vaporize_chance = other.vaporize_chance;
+
+ impact_spew = other.impact_spew;
+ damage_spew = other.damage_spew;
+ split_particles = other.split_particles;
+ knossos_end_particles = other.knossos_end_particles;
+ regular_end_particles = other.regular_end_particles;
+
+ debris_min_lifetime = other.debris_min_lifetime;
+ debris_max_lifetime = other.debris_max_lifetime;
+ debris_min_speed = other.debris_min_speed;
+ debris_max_speed = other.debris_max_speed;
+ debris_min_rotspeed = other.debris_min_rotspeed;
+ debris_max_rotspeed = other.debris_max_rotspeed;
+ debris_damage_type_idx = other.debris_damage_type_idx;
+ debris_min_hitpoints = other.debris_min_hitpoints;
+ debris_max_hitpoints = other.debris_max_hitpoints;
+ debris_damage_mult = other.debris_damage_mult;
+ debris_arc_percent = other.debris_arc_percent;
+
+ if ( other.n_subsystems > 0 ) {
+ if( n_subsystems < 1 ) {
+ subsystems = (model_subsystem *)vm_malloc(sizeof(model_subsystem) * other.n_subsystems );
+ } else {
+ subsystems = (model_subsystem *)vm_realloc(subsystems, sizeof(model_subsystem) * other.n_subsystems);
+ }
+ Assert( subsystems != NULL );
+
+ for ( int i = 0; i < other.n_subsystems; i++ ){
+ memcpy(&(subsystems[i]), &(other.subsystems[i]), sizeof(model_subsystem));
+ }
+ }
+ n_subsystems = other.n_subsystems;
+
+ power_output = other.power_output;
+ max_overclocked_speed = other.max_overclocked_speed;
+ max_weapon_reserve = other.max_weapon_reserve;
+ max_shield_regen_per_second = other.max_shield_regen_per_second;
+ max_weapon_regen_per_second = other.max_weapon_regen_per_second;
+
+ afterburner_max_vel = other.afterburner_max_vel;
+ afterburner_forward_accel = other.afterburner_forward_accel;
+ afterburner_fuel_capacity = other.afterburner_fuel_capacity;
+ afterburner_burn_rate = other.afterburner_burn_rate;
+ afterburner_recover_rate = other.afterburner_recover_rate;
+ afterburner_max_reverse_vel = other.afterburner_max_reverse_vel;
+ afterburner_reverse_accel = other.afterburner_reverse_accel;
+
+ cmeasure_type = other.cmeasure_type;
+ cmeasure_max = other.cmeasure_max;
+
+ num_primary_banks = other.num_primary_banks;
+ memcpy(primary_bank_weapons, other.primary_bank_weapons, sizeof(int) * MAX_SHIP_PRIMARY_BANKS);
+ memcpy(primary_bank_ammo_capacity, other.primary_bank_ammo_capacity, sizeof(int) * MAX_SHIP_PRIMARY_BANKS);
+
+ num_secondary_banks = other.num_secondary_banks;
+ memcpy(secondary_bank_weapons, other.secondary_bank_weapons, sizeof(int) * MAX_SHIP_SECONDARY_BANKS);
+ memcpy(secondary_bank_ammo_capacity, other.secondary_bank_ammo_capacity, sizeof(int) * MAX_SHIP_SECONDARY_BANKS);
+
+ memcpy(draw_primary_models, other.draw_primary_models, sizeof(bool) * MAX_SHIP_PRIMARY_BANKS);
+ memcpy(draw_secondary_models, other.draw_secondary_models, sizeof(bool) * MAX_SHIP_SECONDARY_BANKS);
+ weapon_model_draw_distance = other.weapon_model_draw_distance;
+
+ max_hull_strength = other.max_hull_strength;
+ max_shield_strength = other.max_shield_strength;
+ auto_shield_spread = other.auto_shield_spread;
+ auto_shield_spread_bypass = other.auto_shield_spread_bypass;
+ auto_shield_spread_from_lod = other.auto_shield_spread_from_lod;
+
+ // ...Hmm. A memcpy() seems slightly overkill here, but I've settled into the pattern of "array gets memcpy'd", so... -MageKing17
+ memcpy(shield_point_augment_ctrls, other.shield_point_augment_ctrls, sizeof(int) * 4);
+
+ hull_repair_rate = other.hull_repair_rate;
+ subsys_repair_rate = other.subsys_repair_rate;
+
+ sup_hull_repair_rate = other.sup_hull_repair_rate;
+ sup_shield_repair_rate = other.sup_shield_repair_rate;
+ sup_subsys_repair_rate = other.sup_subsys_repair_rate;
+
+ closeup_pos = other.closeup_pos;
+ closeup_zoom = other.closeup_zoom;
+
+ memcpy(allowed_weapons, other.allowed_weapons, sizeof(int) * MAX_WEAPON_TYPES);
+
+ memcpy(restricted_loadout_flag, other.restricted_loadout_flag, sizeof(int) * MAX_SHIP_WEAPONS);
+ memcpy(allowed_bank_restricted_weapons, other.allowed_bank_restricted_weapons, sizeof(int) * MAX_SHIP_WEAPONS * MAX_WEAPON_TYPES);
+
+ shield_icon_index = other.shield_icon_index;
+ strcpy_s(icon_filename, other.icon_filename);
+ strcpy_s(anim_filename, other.anim_filename);
+ strcpy_s(overhead_filename, other.overhead_filename);
+ selection_effect = other.selection_effect;
+
+ bii_index_ship = other.bii_index_ship;
+ bii_index_ship_with_cargo = other.bii_index_ship_with_cargo;
+ bii_index_wing = other.bii_index_wing;
+ bii_index_wing_with_cargo = other.bii_index_wing_with_cargo;
+
+ score = other.score;
+
+ scan_time = other.scan_time;
+
+ memcpy(ct_info, other.ct_info, sizeof(trail_info) * MAX_SHIP_CONTRAILS);
+ ct_count = other.ct_count;
+
+ num_nondark_colors = other.num_nondark_colors;
+ memcpy(nondark_colors, other.nondark_colors, sizeof(ubyte) * 3);
+
+ memcpy(shield_color, other.shield_color, sizeof(ubyte) * 3);
+
+ uses_team_colors = other.uses_team_colors;
+ default_team_name = other.default_team_name;
+
+ afterburner_trail = other.afterburner_trail;
+ afterburner_trail_width_factor = other.afterburner_trail_width_factor;
+ afterburner_trail_alpha_factor = other.afterburner_trail_alpha_factor;
+ afterburner_trail_life = other.afterburner_trail_life;
+ afterburner_trail_faded_out_sections = other.afterburner_trail_faded_out_sections;
+
+ normal_thruster_particles = other.normal_thruster_particles;
+ afterburner_thruster_particles = other.afterburner_thruster_particles;
+
+ memcpy(&thruster_flame_info, &other.thruster_flame_info, sizeof(thrust_pair));
+ memcpy(&thruster_glow_info, &other.thruster_glow_info, sizeof(thrust_pair));
+ memcpy(&thruster_secondary_glow_info, &other.thruster_secondary_glow_info, sizeof(thrust_pair_bitmap));
+ memcpy(&thruster_tertiary_glow_info, &other.thruster_tertiary_glow_info, sizeof(thrust_pair_bitmap));
+ memcpy(&thruster_distortion_info, &other.thruster_distortion_info, sizeof(thrust_pair_bitmap));
+
+ thruster01_glow_rad_factor = other.thruster01_glow_rad_factor;
+ thruster02_glow_rad_factor = other.thruster02_glow_rad_factor;
+ thruster03_glow_rad_factor = other.thruster03_glow_rad_factor;
+ thruster02_glow_len_factor = other.thruster02_glow_len_factor;
+ thruster_dist_rad_factor = other.thruster_dist_rad_factor;
+ thruster_dist_len_factor = other.thruster_dist_len_factor;
+
+ draw_distortion = other.draw_distortion;
+
+ splodeing_texture = other.splodeing_texture;
+ strcpy_s(splodeing_texture_name, other.splodeing_texture_name);
+
+ replacement_textures = other.replacement_textures;
+
+ armor_type_idx = other.armor_type_idx;
+ shield_armor_type_idx = other.shield_armor_type_idx;
+
+ can_glide = other.can_glide;
+ glide_cap = other.glide_cap;
+ glide_dynamic_cap = other.glide_dynamic_cap;
+ glide_accel_mult = other.glide_accel_mult;
+ use_newtonian_damp = other.use_newtonian_damp;
+ newtonian_damp_override = other.newtonian_damp_override;
+
+ autoaim_fov = other.autoaim_fov;
+
+ topdown_offset_def = other.topdown_offset_def;
+ topdown_offset = other.topdown_offset;
+
+ engine_snd = other.engine_snd;
+ glide_start_snd = other.glide_start_snd;
+ glide_end_snd = other.glide_end_snd;
+
+ ship_sounds = other.ship_sounds;
+
+ num_maneuvering = other.num_maneuvering;
+ memcpy(maneuvering, other.maneuvering, sizeof(man_thruster) * MAX_MAN_THRUSTERS);
+
+ radar_image_2d_idx = other.radar_image_2d_idx;
+ radar_color_image_2d_idx = other.radar_color_image_2d_idx;
+ radar_image_size = other.radar_image_size;
+ radar_projection_size_mult = other.radar_projection_size_mult;
+
+ memcpy(ship_iff_info, other.ship_iff_info, sizeof(int) * MAX_IFFS * MAX_IFFS);
+
+ aiming_flags = other.aiming_flags;
+ minimum_convergence_distance = other.minimum_convergence_distance;
+ convergence_distance = other.convergence_distance;
+ convergence_offset = other.convergence_offset;
+
+ emp_resistance_mod = other.emp_resistance_mod;
+
+ piercing_damage_draw_limit = other.piercing_damage_draw_limit;
+
+ damage_lightning_type = other.damage_lightning_type;
+
+ hud_gauges = other.hud_gauges;
+ hud_enabled = other.hud_enabled;
+ hud_retail = other.hud_retail;
+
+ displays = other.displays;
+
+ pathMetadata = other.pathMetadata;
+}
+
+#define CHECK_THEN_FREE(attribute) \
+do {\
+ if (attribute != NULL) {\
+ vm_free(attribute);\
+ attribute = NULL;\
+ }\
+} while(false)
+
+void ship_info::free_strings()
+{
+ CHECK_THEN_FREE(type_str);
+ CHECK_THEN_FREE(maneuverability_str);
+ CHECK_THEN_FREE(armor_str);
+ CHECK_THEN_FREE(manufacturer_str);
+ CHECK_THEN_FREE(desc);
+ CHECK_THEN_FREE(tech_desc);
+ CHECK_THEN_FREE(ship_length);
+ CHECK_THEN_FREE(gun_mounts);
+ CHECK_THEN_FREE(missile_banks);
+}
+
+const ship_info &ship_info::operator= (const ship_info& other)
+{
+ if (this != &other) {
+ free_strings();
+ clone(other);
+ }
+ return *this;
+}
+
/**
* Writes default info to a ship entry
*
@@ -1101,14 +1420,90 @@
// Use a template for this ship.
if( optional_string( "+Use Template:" ) ) {
- Warning(LOCATION, "Ignoring '+Use Template' field for '%s'. Ship templates have been broken since they were added, and are not currently supported.", sip->name);
+ if ( !create_if_not_found ) {
+ Warning(LOCATION, "Both '+nocreate' and '+Use Template:' were specified for ship class '%s', ignoring '+Use Template:'\n", buf);
+ }
+ else {
+ char template_name[SHIP_MULTITEXT_LENGTH];
+ stuff_string(template_name, F_NAME, SHIP_MULTITEXT_LENGTH);
+ int template_id = ship_template_lookup(template_name);
+ if ( template_id != -1 ) {
+ first_time = false;
+ *sip = Ship_templates[template_id];
+ strcpy_s(sip->name, buf);
+ }
+ else {
+ Warning(LOCATION, "Unable to find ship template '%s' requested by ship class '%s', ignoring template request...", template_name, buf);
+ }
+ }
}
- rtn = parse_ship_values(sip, first_time, replace);
+ rtn = parse_ship_values(sip, false, first_time, replace);
return rtn; //0 for success
}
+/**
+ * Parse the information for a specific ship type template.
+ */
+int parse_ship_template()
+{
+ char buf[SHIP_MULTITEXT_LENGTH];
+ ship_info *sip;
+ int rtn = 0;
+ bool first_time = false;
+
+ required_string("$Template:");
+ stuff_string(buf, F_NAME, SHIP_MULTITEXT_LENGTH);
+
+ if( optional_string("+nocreate") ) {
+ Warning(LOCATION, "+nocreate flag used on ship template. Ship templates can not be modified. Ignoring +nocreate.");
+ }
+
+ diag_printf ("Ship template name -- %s\n", buf);
+ //Check if the template exists already
+ int template_id;
+ template_id = ship_template_lookup( buf );
+
+ if( template_id != -1 ) {
+ sip = &Ship_templates[template_id];
+ Warning(LOCATION, "WARNING: Ship template %s already exists. All ship template names must be unique.", sip->name);
+ if ( !skip_to_start_of_string_either("$Template:", "#End")) {
+ error_display(1, "Missing [#End] or [$Template] after duplicate entry for %s", sip->name);
+ }
+ return -1;
+ }
+ else {
+
+ Ship_templates.push_back(ship_info());
+ sip = &Ship_templates.back();
+
+ init_ship_entry(sip);
+ strcpy_s(sip->name, buf);
+ //Use another template for this template. This allows for template hierarchies. - Turey
+ if( optional_string("+Use Template:") ) {
+ char template_name[SHIP_MULTITEXT_LENGTH];
+ stuff_string(template_name, F_NAME, SHIP_MULTITEXT_LENGTH);
+ template_id = ship_template_lookup( template_name);
+
+ if ( template_id != -1 ) {
+ first_time = false;
+ *sip = Ship_templates[template_id];
+ strcpy_s(sip->name, buf);
+ }
+ else {
+ Warning(LOCATION, "Unable to find ship template '%s' requested by ship template '%s', ignoring template request...", template_name, buf);
+ }
+ }
+ }
+
+ rtn = parse_ship_values( sip, true, first_time, false );
+
+ Assertion(ship_template_lookup(sip->name) == -1, "Somehow, despite checking for duplicate templates before parsing, we wound up with one (%s) anyway. Get a coder!\n", sip->name);
+
+ return rtn;
+}
+
void parse_ship_sound(char *name, GameSoundsIndex id, ship_info *sip)
{
Assert( name != NULL );
@@ -1349,13 +1744,24 @@
/**
* Puts values into a ship_info.
*/
-int parse_ship_values(ship_info* sip, bool first_time, bool replace)
+int parse_ship_values(ship_info* sip, const bool is_template, const bool first_time, const bool replace)
{
char buf[SHIP_MULTITEXT_LENGTH];
+ char* info_type_name;
+ char* type_name;
int i, j, num_allowed;
int allowed_weapons[MAX_WEAPON_TYPES];
int rtn = 0;
char name_tmp[NAME_LENGTH];
+
+ if ( ! is_template ) {
+ info_type_name = "Ship Class";
+ type_name = "$Name";
+ }
+ else {
+ info_type_name = "Ship Template";
+ type_name = "$Template";
+ }
if(optional_string("$Alt name:"))
stuff_string(sip->alt_name, F_NAME, NAME_LENGTH);
@@ -1362,14 +1768,13 @@
if(optional_string("$Short name:"))
stuff_string(sip->short_name, F_NAME, NAME_LENGTH);
- else if(first_time)
+ else if (first_time)
{
- char *srcpos, *srcend, *destpos, *destend;
+ char *srcpos, *srcend, *destpos;
srcpos = sip->name;
destpos = sip->short_name;
srcend = srcpos + strlen(sip->name);
- destend = destpos + sizeof(sip->short_name) - 1;
- while(srcpos < srcend)
+ while(srcpos <= srcend)
{
if(*srcpos != ' ')
*destpos++ = *srcpos++;
@@ -1769,32 +2174,32 @@
if(optional_string("+Min Lifetime:")) {
stuff_float(&sip->debris_min_lifetime);
if(sip->debris_min_lifetime < 0.0f)
- Warning(LOCATION, "Debris min lifetime on ship class '%s' is below 0 and will be ignored", sip->name);
+ Warning(LOCATION, "Debris min lifetime on %s '%s' is below 0 and will be ignored", info_type_name, sip->name);
}
if(optional_string("+Max Lifetime:")) {
stuff_float(&sip->debris_max_lifetime);
if(sip->debris_max_lifetime < 0.0f)
- Warning(LOCATION, "Debris max lifetime on ship class '%s' is below 0 and will be ignored", sip->name);
+ Warning(LOCATION, "Debris max lifetime on %s '%s' is below 0 and will be ignored", info_type_name, sip->name);
}
if(optional_string("+Min Speed:")) {
stuff_float(&sip->debris_min_speed);
if(sip->debris_min_speed < 0.0f)
- Warning(LOCATION, "Debris min speed on ship class '%s' is below 0 and will be ignored", sip->name);
+ Warning(LOCATION, "Debris min speed on %s '%s' is below 0 and will be ignored", info_type_name, sip->name);
}
if(optional_string("+Max Speed:")) {
stuff_float(&sip->debris_max_speed);
if(sip->debris_max_speed < 0.0f)
- Warning(LOCATION, "Debris max speed on ship class '%s' is below 0 and will be ignored", sip->name);
+ Warning(LOCATION, "Debris max speed on %s '%s' is below 0 and will be ignored", info_type_name, sip->name);
}
if(optional_string("+Min Rotation speed:")) {
stuff_float(&sip->debris_min_rotspeed);
if(sip->debris_min_rotspeed < 0.0f)
- Warning(LOCATION, "Debris min speed on ship class '%s' is below 0 and will be ignored", sip->name);
+ Warning(LOCATION, "Debris min speed on %s '%s' is below 0 and will be ignored", info_type_name, sip->name);
}
if(optional_string("+Max Rotation speed:")) {
stuff_float(&sip->debris_max_rotspeed);
if(sip->debris_max_rotspeed < 0.0f)
- Warning(LOCATION, "Debris max speed on ship class '%s' is below 0 and will be ignored", sip->name);
+ Warning(LOCATION, "Debris max speed on %s '%s' is below 0 and will be ignored", info_type_name, sip->name);
}
if(optional_string("+Damage Type:")) {
stuff_string(buf, F_NAME, NAME_LENGTH);
@@ -1803,22 +2208,22 @@
if(optional_string("+Min Hitpoints:")) {
stuff_float(&sip->debris_min_hitpoints);
if(sip->debris_min_hitpoints < 0.0f)
- Warning(LOCATION, "Debris min hitpoints on ship class '%s' is below 0 and will be ignored", sip->name);
+ Warning(LOCATION, "Debris min hitpoints on %s '%s' is below 0 and will be ignored", info_type_name, sip->name);
}
if(optional_string("+Max Hitpoints:")) {
stuff_float(&sip->debris_max_hitpoints);
if(sip->debris_max_hitpoints < 0.0f)
- Warning(LOCATION, "Debris max hitpoints on ship class '%s' is below 0 and will be ignored", sip->name);
+ Warning(LOCATION, "Debris max hitpoints on %s '%s' is below 0 and will be ignored", info_type_name, sip->name);
}
if(optional_string("+Damage Multiplier:")) {
stuff_float(&sip->debris_damage_mult);
if(sip->debris_damage_mult < 0.0f)
- Warning(LOCATION, "Debris damage multiplier on ship class '%s' is below 0 and will be ignored", sip->name);
+ Warning(LOCATION, "Debris damage multiplier on %s '%s' is below 0 and will be ignored", info_type_name, sip->name);
}
if(optional_string("+Lightning Arc Percent:")) {
stuff_float(&sip->debris_arc_percent);
if(sip->debris_arc_percent < 0.0f || sip->debris_arc_percent > 100.0f) {
- Warning(LOCATION, "Lightning Arc Percent on ship class '%s' should be between 0 and 100.0 (read %f). Entry will be ignored.", sip->name, sip->debris_arc_percent);
+ Warning(LOCATION, "Lightning Arc Percent on %s '%s' should be between 0 and 100.0 (read %f). Entry will be ignored.", info_type_name, sip->name, sip->debris_arc_percent);
sip->debris_arc_percent = 50.0;
}
//Percent is nice for modders, but here in the code we want it betwwen 0 and 1.0
@@ -1828,19 +2233,19 @@
}
//WMC - sanity checking
if(sip->debris_min_speed > sip->debris_max_speed && sip->debris_max_speed >= 0.0f) {
- Warning(LOCATION, "Debris min speed (%f) on ship class '%s' is greater than debris max speed (%f), and will be set to debris max speed.", sip->debris_min_speed, sip->name, sip->debris_max_speed);
+ Warning(LOCATION, "Debris min speed (%f) on %s '%s' is greater than debris max speed (%f), and will be set to debris max speed.", sip->debris_min_speed, info_type_name, sip->name, sip->debris_max_speed);
sip->debris_min_speed = sip->debris_max_speed;
}
if(sip->debris_min_rotspeed > sip->debris_max_rotspeed && sip->debris_max_rotspeed >= 0.0f) {
- Warning(LOCATION, "Debris min rotation speed (%f) on ship class '%s' is greater than debris max rotation speed (%f), and will be set to debris max rotation speed.", sip->debris_min_rotspeed, sip->name, sip->debris_max_rotspeed);
+ Warning(LOCATION, "Debris min rotation speed (%f) on %s '%s' is greater than debris max rotation speed (%f), and will be set to debris max rotation speed.", sip->debris_min_rotspeed, info_type_name, sip->name, sip->debris_max_rotspeed);
sip->debris_min_rotspeed = sip->debris_max_rotspeed;
}
if(sip->debris_min_lifetime > sip->debris_max_lifetime && sip->debris_max_lifetime >= 0.0f) {
- Warning(LOCATION, "Debris min lifetime (%f) on ship class '%s' is greater than debris max lifetime (%f), and will be set to debris max lifetime.", sip->debris_min_lifetime, sip->name, sip->debris_max_lifetime);
+ Warning(LOCATION, "Debris min lifetime (%f) on %s '%s' is greater than debris max lifetime (%f), and will be set to debris max lifetime.", sip->debris_min_lifetime, info_type_name, sip->name, sip->debris_max_lifetime);
sip->debris_min_lifetime = sip->debris_max_lifetime;
}
if(sip->debris_min_hitpoints > sip->debris_max_hitpoints && sip->debris_max_hitpoints >= 0.0f) {
- Warning(LOCATION, "Debris min hitpoints (%f) on ship class '%s' is greater than debris max hitpoints (%f), and will be set to debris max hitpoints.", sip->debris_min_hitpoints, sip->name, sip->debris_max_hitpoints);
+ Warning(LOCATION, "Debris min hitpoints (%f) on %s '%s' is greater than debris max hitpoints (%f), and will be set to debris max hitpoints.", sip->debris_min_hitpoints, info_type_name, sip->name, sip->debris_max_hitpoints);
sip->debris_min_hitpoints = sip->debris_max_hitpoints;
}
@@ -1858,7 +2263,7 @@
if(optional_string("$Banking Constant:"))
stuff_float( &(sip->delta_bank_const) );
- diag_printf ("Ship class '%s' delta_bank_const -- %7.3f\n", sip->name, sip->delta_bank_const);
+ diag_printf ("%s '%s' delta_bank_const -- %7.3f\n", info_type_name, sip->name, sip->delta_bank_const);
if(optional_string("$Max Velocity:"))
{
@@ -1875,7 +2280,7 @@
// div/0 safety check.
if ((sip->rotation_time.xyz.x == 0) || (sip->rotation_time.xyz.y == 0) || (sip->rotation_time.xyz.z == 0))
- Warning(LOCATION, "Rotation time must have non-zero values in each of the three variables.\nFix this in ship %s\n", sip->name);
+ Warning(LOCATION, "Rotation time must have non-zero values in each of the three variables.\nFix this in %s %s\n", info_type_name, sip->name);
sip->srotation_time = (sip->rotation_time.xyz.x + sip->rotation_time.xyz.y)/2.0f;
@@ -1982,7 +2387,7 @@
if(j >= 0) {
sip->warpin_type = j;
} else {
- Warning(LOCATION, "Invalid warpin type '%s' specified for ship '%s'", buf, sip->name);
+ Warning(LOCATION, "Invalid warpin type '%s' specified for %s '%s'", buf, info_type_name, sip->name);
sip->warpin_type = WT_DEFAULT;
}
}
@@ -2001,7 +2406,7 @@
stuff_float(&t_time);
sip->warpin_time = fl2i(t_time*1000.0f);
if(sip->warpin_time <= 0) {
- Warning(LOCATION, "Warp-in time specified as 0 or less on ship '%s'; value ignored", sip->name);
+ Warning(LOCATION, "Warp-in time specified as 0 or less on %s '%s'; value ignored", info_type_name, sip->name);
}
}
@@ -2009,7 +2414,7 @@
{
stuff_float(&sip->warpin_decel_exp);
if (sip->warpin_decel_exp < 0.0f) {
- Warning(LOCATION, "Warp-in deceleration exponent specified as less than 0 on ship '%s'; value ignored", sip->name);
+ Warning(LOCATION, "Warp-in deceleration exponent specified as less than 0 on %s '%s'; value ignored", info_type_name, sip->name);
sip->warpin_decel_exp = 1.0f;
}
}
@@ -2018,7 +2423,7 @@
{
stuff_float(&sip->warpin_radius);
if(sip->warpin_radius <= 0.0f) {
- Warning(LOCATION, "Warp-in radius specified as 0 or less on ship '%s'; value ignored", sip->name);
+ Warning(LOCATION, "Warp-in radius specified as 0 or less on %s '%s'; value ignored", info_type_name, sip->name);
}
}
@@ -2034,7 +2439,7 @@
if(j >= 0) {
sip->warpout_type = j;
} else {
- Warning(LOCATION, "Invalid warpout type '%s' specified for ship '%s'", buf, sip->name);
+ Warning(LOCATION, "Invalid warpout type '%s' specified for %s '%s'", buf, info_type_name, sip->name);
sip->warpout_type = WT_DEFAULT;
}
}
@@ -2049,7 +2454,7 @@
if (t_time >= 0)
sip->warpout_engage_time = fl2i(t_time*1000.0f);
else
- Warning(LOCATION, "Warp-out engage time specified as 0 or less on ship '%s'; value ignored", sip->name);
+ Warning(LOCATION, "Warp-out engage time specified as 0 or less on %s '%s'; value ignored", info_type_name, sip->name);
} else {
sip->warpout_engage_time = -1;
}
@@ -2065,7 +2470,7 @@
stuff_float(&t_time);
sip->warpout_time = fl2i(t_time*1000.0f);
if(sip->warpout_time <= 0) {
- Warning(LOCATION, "Warp-out time specified as 0 or less on ship '%s'; value ignored", sip->name);
+ Warning(LOCATION, "Warp-out time specified as 0 or less on %s '%s'; value ignored", info_type_name, sip->name);
}
}
@@ -2073,7 +2478,7 @@
{
stuff_float(&sip->warpout_accel_exp);
if (sip->warpout_accel_exp < 0.0f) {
- Warning(LOCATION, "Warp-out acceleration exponent specified as less than 0 on ship '%s'; value ignored", sip->name);
+ Warning(LOCATION, "Warp-out acceleration exponent specified as less than 0 on %s '%s'; value ignored", info_type_name, sip->name);
sip->warpout_accel_exp = 1.0f;
}
}
@@ -2082,7 +2487,7 @@
{
stuff_float(&sip->warpout_radius);
if(sip->warpout_radius <= 0.0f) {
- Warning(LOCATION, "Warp-out radius specified as 0 or less on ship '%s'; value ignored", sip->name);
+ Warning(LOCATION, "Warp-out radius specified as 0 or less on %s '%s'; value ignored", info_type_name, sip->name);
}
}
@@ -2126,7 +2531,7 @@
stuff_float(&sip->prop_exp_rad_mult);
if(sip->prop_exp_rad_mult <= 0) {
// on invalid value return to default setting
- Warning(LOCATION, "Propagating explosion radius multiplier was set to non-positive value.\nDefaulting multiplier to 1.0 on ship '%s'.\n", sip->name);
+ Warning(LOCATION, "Propagating explosion radius multiplier was set to non-positive value.\nDefaulting multiplier to 1.0 on %s '%s'.\n", info_type_name, sip->name);
sip->prop_exp_rad_mult = 1.0f;
}
}
@@ -2492,7 +2897,7 @@
stuff_float(&sip->max_hull_strength);
if (sip->max_hull_strength < 0.0f)
{
- Warning(LOCATION, "Max hull strength on ship %s cannot be less than 0. Defaulting to 100.\n", sip->name, sip->max_hull_strength);
+ Warning(LOCATION, "Max hull strength on %s '%s' cannot be less than 0. Defaulting to 100.\n", info_type_name, sip->name, sip->max_hull_strength);
sip->max_hull_strength = 100.0f;
}
}
@@ -2546,7 +2951,7 @@
sip->armor_type_idx = armor_type_get_idx(buf);
if(sip->armor_type_idx == -1)
- Warning(LOCATION,"Invalid armor name %s specified for hull in ship class %s", buf, sip->name);
+ Warning(LOCATION,"Invalid armor name %s specified for hull in %s '%s'", buf, info_type_name, sip->name);
}
if(optional_string("$Shield Armor Type:"))
@@ -2555,7 +2960,7 @@
sip->shield_armor_type_idx = armor_type_get_idx(buf);
if(sip->shield_armor_type_idx == -1)
- Warning(LOCATION,"Invalid armor name %s specified for shield in ship class %s", buf, sip->name);
+ Warning(LOCATION,"Invalid armor name %s specified for shield in %s '%s'", buf, info_type_name, sip->name);
}
if (optional_string("$Flags:"))
@@ -2606,7 +3011,7 @@
flag_found = true;
if (Ship_flags[idx].var == 255)
- Warning(LOCATION, "Use of '%s' flag for ship '%s' - this flag is no longer needed.", Ship_flags[idx].name, sip->name);
+ Warning(LOCATION, "Use of '%s' flag for %s '%s' - this flag is no longer needed.", Ship_flags[idx].name, info_type_name, sip->name);
else if (Ship_flags[idx].var == 0)
sip->flags |= Ship_flags[idx].def;
else if (Ship_flags[idx].var == 1)
@@ -2628,7 +3033,7 @@
// Goober5000 - ensure number of banks checks out
if (sip->num_primary_banks > MAX_SHIP_PRIMARY_BANKS)
{
- Error(LOCATION, "Ship Class %s has too many primary banks (%d). Maximum for ships is currently %d.\n", sip->name, sip->num_primary_banks, MAX_SHIP_PRIMARY_BANKS);
+ Error(LOCATION, "%s '%s' has too many primary banks (%d). Maximum for ships is currently %d.\n", info_type_name, sip->name, sip->num_primary_banks, MAX_SHIP_PRIMARY_BANKS);
}
// copy to regular allowed_weapons array
@@ -2699,7 +3104,7 @@
}
if (!(sip->afterburner_fuel_capacity) ) {
- Warning(LOCATION, "Ship class %s has an afterburner but has no afterburner fuel. Setting fuel to 1", sip->name);
+ Warning(LOCATION, "%s '%s' has an afterburner but has no afterburner fuel. Setting fuel to 1", info_type_name, sip->name);
sip->afterburner_fuel_capacity = 1.0f;
}
}
@@ -2734,7 +3139,7 @@
}
if (trails_warning)
- Warning(LOCATION, "Ship %s entry has $Trails field specified, but no properties given.", sip->name);
+ Warning(LOCATION, "%s %s entry has $Trails field specified, but no properties given.", info_type_name, sip->name);
}
if (optional_string("$Countermeasure type:")) {
@@ -2741,9 +3146,9 @@
stuff_string(buf, F_NAME, SHIP_MULTITEXT_LENGTH);
int res = weapon_info_lookup(buf);
if (res < 0) {
- Warning(LOCATION, "Could not find weapon type '%s' to use as countermeasure on ship class '%s'", buf, sip->name);
+ Warning(LOCATION, "Could not find weapon type '%s' to use as countermeasure on %s '%s'", buf, info_type_name, sip->name);
} else if (Weapon_info[res].wi_flags & WIF_BEAM) {
- Warning(LOCATION, "Attempt made to set a beam weapon as a countermeasure on ship class '%s'", sip->name);
+ Warning(LOCATION, "Attempt made to set a beam weapon as a countermeasure on %s '%s'", info_type_name, sip->name);
} else {
sip->cmeasure_type = res;
}
@@ -2838,9 +3243,9 @@
// check for inconsistencies
if ((sip->bii_index_wing_with_cargo >= 0) && (sip->bii_index_wing < 0 || sip->bii_index_ship_with_cargo < 0))
- Warning(LOCATION, "Ship '%s' has a wing-with-cargo briefing icon but is missing a wing briefing icon or a ship-with-cargo briefing icon!", sip->name);
+ Warning(LOCATION, "%s '%s' has a wing-with-cargo briefing icon but is missing a wing briefing icon or a ship-with-cargo briefing icon!", info_type_name, sip->name);
if ((sip->bii_index_wing_with_cargo < 0) && (sip->bii_index_wing >= 0) && (sip->bii_index_ship_with_cargo >= 0))
- Warning(LOCATION, "Ship '%s' has both a wing briefing icon and a ship-with-cargo briefing icon but does not have a wing-with-cargo briefing icon!", sip->name);
+ Warning(LOCATION, "%s '%s' has both a wing briefing icon and a ship-with-cargo briefing icon but does not have a wing-with-cargo briefing icon!", info_type_name, sip->name);
if ( optional_string("$Score:") ){
stuff_int( &sip->score );
@@ -2974,7 +3379,7 @@
else if ( optional_string("$Afterburner Particle Bitmap:") )
afterburner = true;
else
- Error( LOCATION, "formatting error in the thruster's particle section for ship %s\n", sip->name );
+ Error( LOCATION, "formatting error in the thruster's particle section for %s '%s'\n", info_type_name, sip->name );
generic_anim_init(&tpart.thruster_bitmap, NULL);
stuff_string(tpart.thruster_bitmap.filename, F_NAME, MAX_FILENAME_LEN);
@@ -3007,7 +3412,7 @@
}
else if ( optional_string("$Stealth") ) {
- Warning(LOCATION, "Ship %s is missing the colon after \"$Stealth\". Note that you may also use the ship flag \"stealth\".", sip->name);
+ Warning(LOCATION, "%s '%s' is missing the colon after \"$Stealth\". Note that you may also use the ship flag \"stealth\".", info_type_name, sip->name);
sip->flags |= SIF_STEALTH;
}
@@ -3029,7 +3434,7 @@
// this means you've reached the max # of contrails for a ship
if (sip->ct_count >= MAX_SHIP_CONTRAILS) {
- Warning(LOCATION, "%s has more contrails than the max of %d", sip->name, MAX_SHIP_CONTRAILS);
+ Warning(LOCATION, "%s '%s' has more contrails than the max of %d", info_type_name, sip->name, MAX_SHIP_CONTRAILS);
break;
}
@@ -3081,11 +3486,11 @@
if(sip->num_maneuvering < MAX_MAN_THRUSTERS) {
mtp = &sip->maneuvering[sip->num_maneuvering++];
} else {
- Warning(LOCATION, "Too many maneuvering thrusters on ship '%s'; maximum is %d", sip->name, MAX_MAN_THRUSTERS);
+ Warning(LOCATION, "Too many maneuvering thrusters on %s '%s'; maximum is %d", info_type_name, sip->name, MAX_MAN_THRUSTERS);
}
} else {
mtp = &manwich;
- Warning(LOCATION, "Invalid index (%d) specified for maneuvering thruster on ship %s", idx, sip->name);
+ Warning(LOCATION, "Invalid index (%d) specified for maneuvering thruster on %s '%s'", idx, info_type_name, sip->name);
}
if(optional_string("+Used for:")) {
@@ -3167,10 +3572,10 @@
iff_data[1] = iff_lookup(iff_2);
if (iff_data[0] == -1)
- WarningEx(LOCATION, "Ship %s\nIFF colour seen by \"%s\" invalid!", sip->name, iff_1);
+ WarningEx(LOCATION, "%s '%s'\nIFF colour seen by \"%s\" invalid!", info_type_name, sip->name, iff_1);
if (iff_data[1] == -1)
- WarningEx(LOCATION, "Ship %s\nIFF colour when IFF is \"%s\" invalid!", sip->name, iff_2);
+ WarningEx(LOCATION, "%s '%s'\nIFF colour when IFF is \"%s\" invalid!", info_type_name, sip->name, iff_2);
// Set the color
required_string("+As Color:");
@@ -3210,7 +3615,7 @@
}
}
if (i == num_groups) {
- Warning(LOCATION,"Unidentified priority group '%s' set for ship class '%s'\n", target_group_strings[j].c_str(), sip->name);
+ Warning(LOCATION,"Unidentified priority group '%s' set for %s '%s'\n", target_group_strings[j].c_str(), info_type_name, sip->name);
}
}
}
@@ -3259,7 +3664,7 @@
}
while (cont_flag) {
- int r = required_string_3("#End", "$Subsystem:", "$Name" );
+ int r = required_string_one_of(3, "#End", "$Subsystem:", type_name);
switch (r) {
case 0:
cont_flag = 0;
@@ -3285,7 +3690,7 @@
{
if( sip->n_subsystems + n_subsystems >= MAX_MODEL_SUBSYSTEMS )
{
- Warning(LOCATION, "Number of subsystems for ship entry '%s' (%d) exceeds max of %d; only the first %d will be used", sip->name, sip->n_subsystems, n_subsystems, MAX_MODEL_SUBSYSTEMS);
+ Warning(LOCATION, "Number of subsystems for %s '%s' (%d) exceeds max of %d; only the first %d will be used", info_type_name, sip->name, sip->n_subsystems, n_subsystems, MAX_MODEL_SUBSYSTEMS);
break;
}
sp = &subsystems[n_subsystems++]; // subsystems a local -- when done, we will malloc and copy
@@ -3364,9 +3769,9 @@
}
else
{
- Error(LOCATION, "Malformed $Subsystem entry '%s' %s.\n\n"
+ Error(LOCATION, "Malformed $Subsystem entry '%s' in %s '%s'.\n\n"
"Specify a turning rate or remove the trailing comma.",
- sp->subobj_name, sip->name);
+ sp->subobj_name, info_type_name, sip->name);
}
}
@@ -3385,7 +3790,7 @@
sp->armor_type_idx = armor_type_get_idx(buf);
if (sp->armor_type_idx == -1)
- WarningEx(LOCATION, "Ship %s, subsystem %s\nInvalid armor type %s!", sip->name, sp->subobj_name, buf);
+ WarningEx(LOCATION, "%s '%s', subsystem %s\nInvalid armor type %s!", info_type_name, sip->name, sp->subobj_name, buf);
}
// Get primary bank weapons
@@ -3401,7 +3806,7 @@
sp->engine_wash_pointer = get_engine_wash_pointer(name_tmp);
if(sp->engine_wash_pointer == NULL)
- WarningEx(LOCATION,"Invalid engine wash name %s specified for subsystem %s in ship class %s", name_tmp, sp->subobj_name, sip->name);
+ WarningEx(LOCATION,"Invalid engine wash name %s specified for subsystem %s in %s '%s'", name_tmp, sp->subobj_name, info_type_name, sip->name);
}
parse_sound("$AliveSnd:", &sp->alive_snd, sp->subobj_name);
@@ -3478,7 +3883,7 @@
}
}
if (j == num_groups) {
- Warning(LOCATION, "Unidentified target priority '%s' set for\nsubsystem '%s' in ship class '%s'.", tgt_priorities[i].c_str(), sp->subobj_name, sip->name);
+ Warning(LOCATION, "Unidentified target priority '%s' set for\nsubsystem '%s' in %s '%s'.", tgt_priorities[i].c_str(), sp->subobj_name, info_type_name, sip->name);
}
}
}
@@ -3501,13 +3906,13 @@
stuff_float(&tempf);
if (tempf < 0) {
- mprintf(("RoF multiplier clamped to 0 for subsystem '%s' in ship class '%s'.\n", sp->subobj_name, sip->name));
+ mprintf(("RoF multiplier clamped to 0 for subsystem '%s' in %s '%s'.\n", sp->subobj_name, info_type_name, sip->name));
sp->turret_rof_scaler = 0;
} else {
sp->turret_rof_scaler = tempf;
}
} else {
- Warning(LOCATION, "RoF multiplier not set for subsystem\n'%s' in ship class '%s'.", sp->subobj_name, sip->name);
+ Warning(LOCATION, "RoF multiplier not set for subsystem\n'%s' in %s '%s'.", sp->subobj_name, info_type_name, sip->name);
}
}
}
@@ -3578,17 +3983,17 @@
}
if ((sp->flags & MSS_FLAG_TURRET_FIXED_FP) && !(sp->flags & MSS_FLAG_USE_MULTIPLE_GUNS)) {
- Warning(LOCATION, "\"fixed firingpoints\" flag used without \"use multiple guns\" flag on a subsystem on ship %s.\n\"use multiple guns\" flags added by default\n", sip->name);
+ Warning(LOCATION, "\"fixed firingpoints\" flag used without \"use multiple guns\" flag on a subsystem on %s '%s'.\n\"use multiple guns\" flags added by default\n", info_type_name, sip->name);
sp->flags |= MSS_FLAG_USE_MULTIPLE_GUNS;
}
if (old_flags) {
mprintf(("Use of deprecated subsystem syntax. Please use the $Flags: field for subsystem flags.\n\n" \
- "At least one of the following tags was used on ship %s, subsystem %s:\n" \
+ "At least one of the following tags was used on %s '%s', subsystem %s:\n" \
"\t+untargetable\n" \
"\t+carry-no-damage\n" \
"\t+use-multiple-guns\n" \
- "\t+fire-down-normals\n", sip->name, sp->subobj_name));
+ "\t+fire-down-normals\n", info_type_name, sip->name, sp->subobj_name));
}
while(optional_string("$animation:"))
@@ -3757,8 +4162,11 @@
case 2:
cont_flag = 0;
break;
+ case -1:
+ // Possible if -noparseerrors is used.
+ break;
default:
- Int3(); // Impossible return value from required_string_3.
+ Assertion(false, "This should never happen.\n"); // Impossible return value from required_string_one_of().
}
}
@@ -4158,6 +4566,17 @@
required_string("#End");
}
+ if ( optional_string("#Ship Templates") ) {
+
+ while ( required_string_either("#End", "$Template:") ) {
+ if ( parse_ship_template() ) {
+ continue;
+ }
+ }
+
+ required_string("#End");
+ }
+
//Add ship classes
if(optional_string("#Ship Classes"))
{
@@ -4276,6 +4695,25 @@
}
}
}
+
+ // Clear out ship templates, since they're no longer needed. -MageKing17
+ for ( SCP_vector<ship_info>::iterator it = Ship_templates.begin(); it != Ship_templates.end(); ++it ) {
+ // free memory alloced for subsystem storage
+ if ( it->subsystems != NULL ) {
+ for(int n = 0; n < it->n_subsystems; n++) {
+ if (it->subsystems[n].triggers != NULL) {
+ vm_free(it->subsystems[n].triggers);
+ it->subsystems[n].triggers = NULL;
+ }
+ }
+
+ vm_free(it->subsystems);
+ it->subsystems = NULL;
+ }
+
+ it->free_strings();
+ }
+ Ship_templates.clear();
}
/**
@@ -11886,6 +12324,21 @@
return -1;
}
+/**
+ * Return the index of Ship_templates[].name that is *token.
+ */
+int ship_template_lookup(const char *token)
+{
+ int i;
+
+ for ( i = 0; i < (int)Ship_templates.size(); i++ ) {
+ if ( !stricmp(token, Ship_templates[i].name) ) {
+ return i;
+ }
+ }
+ return -1;
+}
+
// Goober5000
int ship_info_lookup(const char *token)
{
@@ -13285,8 +13738,9 @@
// free this too! -- Goober5000
ship_clear_subsystems();
- // free memory alloced for subsystem storage
+ // free info from parsed table data
for ( i = 0; i < Num_ship_classes; i++ ) {
+ // free memory alloced for subsystem storage
if ( Ship_info[i].subsystems != NULL ) {
for(n = 0; n < Ship_info[i].n_subsystems; n++) {
if (Ship_info[i].subsystems[n].triggers != NULL) {
@@ -13299,105 +13753,9 @@
Ship_info[i].subsystems = NULL;
}
- // free info from parsed table data
- if (Ship_info[i].type_str != NULL) {
- vm_free(Ship_info[i].type_str);
- Ship_info[i].type_str = NULL;
- }
-
- if (Ship_info[i].maneuverability_str != NULL) {
- vm_free(Ship_info[i].maneuverability_str);
- Ship_info[i].maneuverability_str = NULL;
- }
-
- if (Ship_info[i].armor_str != NULL) {
- vm_free(Ship_info[i].armor_str);
- Ship_info[i].armor_str = NULL;
- }
-
- if (Ship_info[i].manufacturer_str != NULL) {
- vm_free(Ship_info[i].manufacturer_str);
- Ship_info[i].manufacturer_str = NULL;
- }
-
- if (Ship_info[i].desc != NULL) {
- vm_free(Ship_info[i].desc);
- Ship_info[i].desc = NULL;
- }
-
- if (Ship_info[i].tech_desc != NULL) {
- vm_free(Ship_info[i].tech_desc);
- Ship_info[i].tech_desc = NULL;
- }
-
- if (Ship_info[i].ship_length != NULL) {
- vm_free(Ship_info[i].ship_length);
- Ship_info[i].ship_length = NULL;
- }
-
- if (Ship_info[i].gun_mounts != NULL) {
- vm_free(Ship_info[i].gun_mounts);
- Ship_info[i].gun_mounts = NULL;
- }
-
- if (Ship_info[i].missile_banks != NULL) {
- vm_free(Ship_info[i].missile_banks);
- Ship_info[i].missile_banks = NULL;
- }
+ Ship_info[i].free_strings();
}
- // free info from parsed table data
- for (i=0; i<MAX_SHIP_CLASSES; i++) {
- if ( Ship_info[i].subsystems != NULL ) {
- for(n = 0; n < Ship_info[i].n_subsystems; n++) {
- if (Ship_info[i].subsystems[n].triggers != NULL) {
- vm_free(Ship_info[i].subsystems[n].triggers);
- Ship_info[i].subsystems[n].triggers = NULL;
- }
- }
-
- vm_free(Ship_info[i].subsystems);
- Ship_info[i].subsystems = NULL;
- }
-
- if(Ship_info[i].type_str != NULL){
- vm_free(Ship_info[i].type_str);
- Ship_info[i].type_str = NULL;
- }
- if(Ship_info[i].maneuverability_str != NULL){
- vm_free(Ship_info[i].maneuverability_str);
- Ship_info[i].maneuverability_str = NULL;
- }
- if(Ship_info[i].armor_str != NULL){
- vm_free(Ship_info[i].armor_str);
- Ship_info[i].armor_str = NULL;
- }
- if(Ship_info[i].manufacturer_str != NULL){
- vm_free(Ship_info[i].manufacturer_str);
- Ship_info[i].manufacturer_str = NULL;
- }
- if(Ship_info[i].desc != NULL){
- vm_free(Ship_info[i].desc);
- Ship_info[i].desc = NULL;
- }
- if(Ship_info[i].tech_desc != NULL){
- vm_free(Ship_info[i].tech_desc);
- Ship_info[i].tech_desc = NULL;
- }
- if(Ship_info[i].ship_length != NULL){
- vm_free(Ship_info[i].ship_length);
- Ship_info[i].ship_length = NULL;
- }
- if(Ship_info[i].gun_mounts != NULL){
- vm_free(Ship_info[i].gun_mounts);
- Ship_info[i].gun_mounts = NULL;
- }
- if(Ship_info[i].missile_banks != NULL){
- vm_free(Ship_info[i].missile_banks);
- Ship_info[i].missile_banks = NULL;
- }
- }
-
for (i = 0; i < (int)Ship_types.size(); i++) {
Ship_types[i].ai_actively_pursues.clear();
Ship_types[i].ai_actively_pursues_temp.clear();
Index: code/ship/ship.h
===================================================================
--- code/ship/ship.h (revision 11204)
+++ code/ship/ship.h (working copy)
@@ -1431,6 +1431,11 @@
SCP_vector<cockpit_display_info> displays;
SCP_map<SCP_string, path_metadata> pathMetadata;
+
+ const ship_info &operator=(const ship_info& other);
+ void free_strings();
+private:
+ void clone(const ship_info& other);
};
extern int Num_wings;
@@ -1620,7 +1625,8 @@
// Stuff vector *pos with absolute position.
extern int get_subsystem_pos(vec3d *pos, object *objp, ship_subsys *subsysp);
-int parse_ship_values(ship_info* sip, bool first_time, bool replace);
+int parse_ship_values(ship_info* sip, const bool is_template, const bool first_time, const bool replace);
+int ship_template_lookup(const char *name = NULL);
void parse_ship_particle_effect(ship_info* sip, particle_effect* pe, char *id_string);
extern int ship_info_lookup(const char *name = NULL);