mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-07 08:15:59 -10:00
P3: Add weapon_info::clone (#7847)
* Add weapon_info::clone Copies every member of a weapon class, following ship_info::clone, so a weapon can be created from another as ship templates do. The CLONE_UNIQUE_PTR macro moves from ship.cpp to utils/string_utils.h so both clone functions share it. * Group weapon_info::clone fields as the struct declares them --------- Co-authored-by: Dustinspace217 <[email protected]>
This commit is contained in:
1 parent
c47a8bf351
commit
12bddb8366
5 files changed
+371
-2
No files matched your search
@@ -1083,8 +1083,6 @@ const float DEFAULT_ASK_HELP_HULL_PERCENT = 0.3f; // percent hull at which shi
|
||||
const float AWACS_HELP_HULL_HI = 0.75f; // percent hull at which ship will ask for help
|
||||
const float AWACS_HELP_HULL_LOW = 0.25f; // percent hull at which ship will ask for help
|
||||
|
||||
#define CLONE_UNIQUE_PTR(attribute) attribute = util::unique_copy(other.attribute.get(), true)
|
||||
|
||||
void ship_info::clone(const ship_info& other)
|
||||
{
|
||||
strcpy_s(name, other.name);
|
||||
|
||||
@@ -39,3 +39,5 @@ std::unique_ptr<char[]> unique_copy(const char *str, bool null_if_empty);
|
||||
SCP_vm_unique_ptr<char> vm_unique_copy(const char *str, bool null_if_empty);
|
||||
|
||||
} // namespace util
|
||||
|
||||
#define CLONE_UNIQUE_PTR(attribute) attribute = util::unique_copy(other.attribute.get(), true)
|
||||
@@ -961,6 +961,7 @@ struct weapon_info
|
||||
bool has_display_name() const;
|
||||
|
||||
void reset();
|
||||
void clone(const weapon_info& other);
|
||||
};
|
||||
|
||||
extern special_flag_def_list_new<Weapon::Info_Flags, weapon_info*, flagset<Weapon::Info_Flags>&> Weapon_Info_Flags[];
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
#include "particle/volumes/PointVolume.h"
|
||||
#include "tracing/Monitor.h"
|
||||
#include "tracing/tracing.h"
|
||||
#include "utils/string_utils.h"
|
||||
#include "weapon.h"
|
||||
#include "model/modelrender.h"
|
||||
|
||||
@@ -10158,6 +10159,336 @@ void weapon_info::reset()
|
||||
this->on_create_program = actions::ProgramSet();
|
||||
}
|
||||
|
||||
void weapon_info::clone(const weapon_info& other)
|
||||
{
|
||||
strcpy_s(name, other.name);
|
||||
display_name = other.display_name;
|
||||
strcpy_s(title, other.title);
|
||||
CLONE_UNIQUE_PTR(desc);
|
||||
strcpy_s(altSubsysName, other.altSubsysName);
|
||||
|
||||
strcpy_s(pofbitmap_name, other.pofbitmap_name);
|
||||
model_num = other.model_num;
|
||||
strcpy_s(external_model_name, other.external_model_name);
|
||||
external_model_num = other.external_model_num;
|
||||
|
||||
CLONE_UNIQUE_PTR(tech_desc);
|
||||
strcpy_s(tech_anim_filename, other.tech_anim_filename);
|
||||
strcpy_s(tech_title, other.tech_title);
|
||||
strcpy_s(tech_model, other.tech_model);
|
||||
|
||||
hud_target_lod = other.hud_target_lod;
|
||||
num_detail_levels = other.num_detail_levels;
|
||||
memcpy(detail_distance, other.detail_distance, sizeof(detail_distance));
|
||||
subtype = other.subtype;
|
||||
render_type = other.render_type;
|
||||
|
||||
closeup_pos = other.closeup_pos;
|
||||
closeup_zoom = other.closeup_zoom;
|
||||
icon_closeup_pos = other.icon_closeup_pos;
|
||||
icon_closeup_zoom = other.icon_closeup_zoom;
|
||||
|
||||
strcpy_s(hud_filename, other.hud_filename);
|
||||
hud_image_index = other.hud_image_index;
|
||||
|
||||
laser_bitmap = other.laser_bitmap;
|
||||
laser_headon_bitmap = other.laser_headon_bitmap;
|
||||
laser_glow_bitmap = other.laser_glow_bitmap;
|
||||
laser_glow_headon_bitmap = other.laser_glow_headon_bitmap;
|
||||
laser_headon_switch_rate = other.laser_headon_switch_rate;
|
||||
laser_headon_switch_ang = other.laser_headon_switch_ang;
|
||||
|
||||
laser_length = other.laser_length;
|
||||
laser_length_by_frametime = other.laser_length_by_frametime;
|
||||
bitmap_color = other.bitmap_color;
|
||||
laser_color_1 = other.laser_color_1;
|
||||
laser_color_2 = other.laser_color_2;
|
||||
laser_head_radius = other.laser_head_radius;
|
||||
laser_tail_radius = other.laser_tail_radius;
|
||||
laser_glow_length_scale = other.laser_glow_length_scale;
|
||||
laser_glow_head_scale = other.laser_glow_head_scale;
|
||||
laser_glow_tail_scale = other.laser_glow_tail_scale;
|
||||
laser_min_pixel_size = other.laser_min_pixel_size;
|
||||
laser_pos_offset = other.laser_pos_offset;
|
||||
|
||||
collision_radius_override = other.collision_radius_override;
|
||||
|
||||
light_color_set = other.light_color_set;
|
||||
light_color = other.light_color;
|
||||
light_radius = other.light_radius;
|
||||
|
||||
max_speed = other.max_speed;
|
||||
acceleration_time = other.acceleration_time;
|
||||
vel_inherit_amount = other.vel_inherit_amount;
|
||||
free_flight_time = other.free_flight_time;
|
||||
free_flight_speed_factor = other.free_flight_speed_factor;
|
||||
gravity_const = other.gravity_const;
|
||||
mass = other.mass;
|
||||
fire_wait = other.fire_wait;
|
||||
max_delay = other.max_delay;
|
||||
min_delay = other.min_delay;
|
||||
|
||||
damage = other.damage;
|
||||
damage_time = other.damage_time;
|
||||
atten_damage = other.atten_damage;
|
||||
damage_incidence_max = other.damage_incidence_max;
|
||||
damage_incidence_min = other.damage_incidence_min;
|
||||
|
||||
shockwave = other.shockwave;
|
||||
dinky_shockwave = other.dinky_shockwave;
|
||||
|
||||
arm_time = other.arm_time;
|
||||
arm_dist = other.arm_dist;
|
||||
arm_radius = other.arm_radius;
|
||||
det_range = other.det_range;
|
||||
det_radius = other.det_radius;
|
||||
proximity_radius = other.proximity_radius;
|
||||
proximity_iff = other.proximity_iff;
|
||||
proximity_species = other.proximity_species;
|
||||
proximity_type = other.proximity_type;
|
||||
proximity_class = other.proximity_class;
|
||||
proximity_relation_mask = other.proximity_relation_mask;
|
||||
proximity_detonate_chance = other.proximity_detonate_chance;
|
||||
proximity_stealth_multiplier = other.proximity_stealth_multiplier;
|
||||
mine_sensors_range = other.mine_sensors_range;
|
||||
mine_targetable_range = other.mine_targetable_range;
|
||||
mine_chase_duration = other.mine_chase_duration;
|
||||
mine_detonates_on_chase_timeout = other.mine_detonates_on_chase_timeout;
|
||||
mine_chase_cooldown = other.mine_chase_cooldown;
|
||||
flak_detonation_accuracy = other.flak_detonation_accuracy;
|
||||
flak_targeting_accuracy = other.flak_targeting_accuracy;
|
||||
untargeted_flak_range_penalty = other.untargeted_flak_range_penalty;
|
||||
|
||||
armor_factor = other.armor_factor;
|
||||
shield_factor = other.shield_factor;
|
||||
subsystem_factor = other.subsystem_factor;
|
||||
|
||||
life_min = other.life_min;
|
||||
life_max = other.life_max;
|
||||
lifetime = other.lifetime;
|
||||
|
||||
energy_consumed = other.energy_consumed;
|
||||
|
||||
wi_flags = other.wi_flags;
|
||||
|
||||
turn_time = other.turn_time;
|
||||
turn_accel_time = other.turn_accel_time;
|
||||
cargo_size = other.cargo_size;
|
||||
autoaim_fov = other.autoaim_fov;
|
||||
rearm_rate = other.rearm_rate;
|
||||
disallow_rearm = other.disallow_rearm;
|
||||
reloaded_per_batch = other.reloaded_per_batch;
|
||||
weapon_range = other.weapon_range;
|
||||
optimum_range = other.optimum_range;
|
||||
weapon_min_range = other.weapon_min_range;
|
||||
|
||||
aiming_flags = other.aiming_flags;
|
||||
minimum_convergence_distance = other.minimum_convergence_distance;
|
||||
convergence_distance = other.convergence_distance;
|
||||
|
||||
pierce_objects = other.pierce_objects;
|
||||
spawn_children_on_pierce = other.spawn_children_on_pierce;
|
||||
|
||||
num_spawn_weapons_defined = other.num_spawn_weapons_defined;
|
||||
maximum_children_spawned = other.maximum_children_spawned;
|
||||
memcpy(spawn_info, other.spawn_info, sizeof(spawn_info));
|
||||
|
||||
lifetime_variation_factor_when_child = other.lifetime_variation_factor_when_child;
|
||||
|
||||
swarm_count = other.swarm_count;
|
||||
SwarmWait = other.SwarmWait;
|
||||
|
||||
target_restrict = other.target_restrict;
|
||||
target_restrict_objecttypes = other.target_restrict_objecttypes;
|
||||
multi_lock = other.multi_lock;
|
||||
max_seeking = other.max_seeking;
|
||||
max_seekers_per_target = other.max_seekers_per_target;
|
||||
|
||||
ship_restrict = other.ship_restrict;
|
||||
ship_restrict_strings = other.ship_restrict_strings;
|
||||
|
||||
trigger_lock = other.trigger_lock;
|
||||
launch_reset_locks = other.launch_reset_locks;
|
||||
|
||||
auto_target_method = other.auto_target_method;
|
||||
|
||||
acquire_method = other.acquire_method;
|
||||
min_lock_time = other.min_lock_time;
|
||||
lock_pixels_per_sec = other.lock_pixels_per_sec;
|
||||
catchup_pixels_per_sec = other.catchup_pixels_per_sec;
|
||||
catchup_pixel_penalty = other.catchup_pixel_penalty;
|
||||
lock_fov = other.lock_fov;
|
||||
|
||||
fov = other.fov;
|
||||
|
||||
seeker_strength = other.seeker_strength;
|
||||
|
||||
pre_launch_snd = other.pre_launch_snd;
|
||||
pre_launch_snd_min_interval = other.pre_launch_snd_min_interval;
|
||||
launch_snd = other.launch_snd;
|
||||
cockpit_launch_snd = other.cockpit_launch_snd;
|
||||
impact_snd = other.impact_snd;
|
||||
disarmed_impact_snd = other.disarmed_impact_snd;
|
||||
shield_impact_snd = other.shield_impact_snd;
|
||||
flyby_snd = other.flyby_snd;
|
||||
ambient_snd = other.ambient_snd;
|
||||
start_firing_snd = other.start_firing_snd;
|
||||
loop_firing_snd = other.loop_firing_snd;
|
||||
linked_loop_firing_snd = other.linked_loop_firing_snd;
|
||||
end_firing_snd = other.end_firing_snd;
|
||||
|
||||
hud_tracking_snd = other.hud_tracking_snd;
|
||||
hud_locked_snd = other.hud_locked_snd;
|
||||
hud_in_flight_snd = other.hud_in_flight_snd;
|
||||
in_flight_play_type = other.in_flight_play_type;
|
||||
|
||||
tr_info = other.tr_info;
|
||||
|
||||
strcpy_s(icon_filename, other.icon_filename);
|
||||
strcpy_s(anim_filename, other.anim_filename);
|
||||
selection_effect = other.selection_effect;
|
||||
fs2_effect_grid_color = other.fs2_effect_grid_color;
|
||||
fs2_effect_scanline_color = other.fs2_effect_scanline_color;
|
||||
fs2_effect_grid_density = other.fs2_effect_grid_density;
|
||||
fs2_effect_wireframe_color = other.fs2_effect_wireframe_color;
|
||||
|
||||
shield_impact_effect_radius = other.shield_impact_effect_radius;
|
||||
shield_impact_explosion_radius = other.shield_impact_explosion_radius;
|
||||
|
||||
impact_weapon_expl_effect = other.impact_weapon_expl_effect;
|
||||
dinky_impact_weapon_expl_effect = other.dinky_impact_weapon_expl_effect;
|
||||
flash_impact_weapon_expl_effect = other.flash_impact_weapon_expl_effect;
|
||||
|
||||
piercing_impact_effect = other.piercing_impact_effect;
|
||||
piercing_impact_secondary_effect = other.piercing_impact_secondary_effect;
|
||||
|
||||
conditional_impacts = other.conditional_impacts;
|
||||
|
||||
muzzle_effect = other.muzzle_effect;
|
||||
|
||||
state_effects = other.state_effects;
|
||||
|
||||
emp_intensity = other.emp_intensity;
|
||||
emp_time = other.emp_time;
|
||||
|
||||
recoil_modifier = other.recoil_modifier;
|
||||
|
||||
shudder_modifier = other.shudder_modifier;
|
||||
|
||||
weapon_reduce = other.weapon_reduce;
|
||||
afterburner_reduce = other.afterburner_reduce;
|
||||
|
||||
vamp_regen = other.vamp_regen;
|
||||
|
||||
tag_time = other.tag_time;
|
||||
tag_level = other.tag_level;
|
||||
|
||||
field_of_fire = other.field_of_fire;
|
||||
fof_spread_rate = other.fof_spread_rate;
|
||||
fof_reset_rate = other.fof_reset_rate;
|
||||
max_fof_spread = other.max_fof_spread;
|
||||
firing_pattern = other.firing_pattern;
|
||||
shots = other.shots;
|
||||
cycle_multishot = other.cycle_multishot;
|
||||
|
||||
cs_num_fired = other.cs_num_fired;
|
||||
cs_radius = other.cs_radius;
|
||||
cs_twist = other.cs_twist;
|
||||
cs_crotate = other.cs_crotate;
|
||||
cs_delay = other.cs_delay;
|
||||
cs_random_angle = other.cs_random_angle;
|
||||
cs_angle = other.cs_angle;
|
||||
|
||||
elec_time = other.elec_time;
|
||||
elec_eng_mult = other.elec_eng_mult;
|
||||
elec_weap_mult = other.elec_weap_mult;
|
||||
elec_beam_mult = other.elec_beam_mult;
|
||||
elec_sensors_mult = other.elec_sensors_mult;
|
||||
elec_randomness = other.elec_randomness;
|
||||
elec_use_new_style = other.elec_use_new_style;
|
||||
|
||||
SSM_index = other.SSM_index;
|
||||
|
||||
lssm_warpout_delay = other.lssm_warpout_delay;
|
||||
lssm_warpin_delay = other.lssm_warpin_delay;
|
||||
lssm_stage5_vel = other.lssm_stage5_vel;
|
||||
lssm_warpin_radius = other.lssm_warpin_radius;
|
||||
lssm_lock_range = other.lssm_lock_range;
|
||||
lssm_warpeffect = other.lssm_warpeffect;
|
||||
|
||||
b_info = other.b_info;
|
||||
|
||||
particle_spewers = other.particle_spewers;
|
||||
|
||||
cm_aspect_effectiveness = other.cm_aspect_effectiveness;
|
||||
cm_heat_effectiveness = other.cm_heat_effectiveness;
|
||||
cm_effective_rad = other.cm_effective_rad;
|
||||
cm_detonation_rad = other.cm_detonation_rad;
|
||||
cm_launch_vec = other.cm_launch_vec;
|
||||
cm_launch_speed = other.cm_launch_speed;
|
||||
cm_launch_variance = other.cm_launch_variance;
|
||||
cm_kill_single = other.cm_kill_single;
|
||||
cmeasure_timer_interval = other.cmeasure_timer_interval;
|
||||
cmeasure_firewait = other.cmeasure_firewait;
|
||||
cmeasure_use_firewait = other.cmeasure_use_firewait;
|
||||
cmeasure_failure_delay_multiplier_ai = other.cmeasure_failure_delay_multiplier_ai;
|
||||
cmeasure_success_delay_multiplier_ai = other.cmeasure_success_delay_multiplier_ai;
|
||||
|
||||
weapon_submodel_rotate_accell = other.weapon_submodel_rotate_accell;
|
||||
weapon_submodel_rotate_vel = other.weapon_submodel_rotate_vel;
|
||||
|
||||
damage_type_idx = other.damage_type_idx;
|
||||
damage_type_idx_sav = other.damage_type_idx_sav;
|
||||
|
||||
armor_type_idx = other.armor_type_idx;
|
||||
|
||||
alpha_max = other.alpha_max;
|
||||
alpha_min = other.alpha_min;
|
||||
alpha_cycle = other.alpha_cycle;
|
||||
|
||||
weapon_hitpoints = other.weapon_hitpoints;
|
||||
|
||||
burst_shots = other.burst_shots;
|
||||
burst_delay = other.burst_delay;
|
||||
burst_flags = other.burst_flags;
|
||||
|
||||
thruster_flame = other.thruster_flame;
|
||||
thruster_glow = other.thruster_glow;
|
||||
thruster_glow_factor = other.thruster_glow_factor;
|
||||
|
||||
target_lead_scaler = other.target_lead_scaler;
|
||||
num_targeting_priorities = other.num_targeting_priorities;
|
||||
memcpy(targeting_priorities, other.targeting_priorities, sizeof(targeting_priorities));
|
||||
|
||||
failure_rate = other.failure_rate;
|
||||
CLONE_UNIQUE_PTR(failure_sub_name);
|
||||
failure_sub = other.failure_sub;
|
||||
|
||||
num_substitution_patterns = other.num_substitution_patterns;
|
||||
memcpy(weapon_substitution_pattern, other.weapon_substitution_pattern, sizeof(weapon_substitution_pattern));
|
||||
memcpy(weapon_substitution_pattern_names,
|
||||
other.weapon_substitution_pattern_names,
|
||||
sizeof(weapon_substitution_pattern_names));
|
||||
|
||||
score = other.score;
|
||||
|
||||
custom_data = other.custom_data;
|
||||
|
||||
custom_strings = other.custom_strings;
|
||||
|
||||
impact_decal = other.impact_decal;
|
||||
|
||||
on_create_program = other.on_create_program;
|
||||
|
||||
animations = other.animations;
|
||||
|
||||
weapon_launch_curves = other.weapon_launch_curves;
|
||||
weapon_curves = other.weapon_curves;
|
||||
weapon_hit_curves = other.weapon_hit_curves;
|
||||
beam_curves = other.beam_curves;
|
||||
beam_hit_curves = other.beam_hit_curves;
|
||||
}
|
||||
|
||||
const char* weapon_info::get_display_name() const
|
||||
{
|
||||
if (has_display_name())
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "util/FSTestFixture.h"
|
||||
#include "util/test_util.h"
|
||||
|
||||
#include "utils/string_utils.h"
|
||||
#include "weapon/weapon.h"
|
||||
|
||||
class WeaponsParseTest : public test::FSTestFixture {
|
||||
@@ -34,3 +35,39 @@ TEST_F(WeaponsParseTest, description_too_many_lines) {
|
||||
|
||||
ASSERT_THROW(weapon_init(), os::dialogs::WarningException);
|
||||
}
|
||||
|
||||
TEST(WeaponInfoCloneTest, copies_members) {
|
||||
weapon_info src;
|
||||
strcpy_s(src.name, "Template Laser");
|
||||
src.display_name = "Shown Name";
|
||||
src.desc = util::unique_copy("a description", true);
|
||||
src.failure_sub_name = util::unique_copy("Sub Weapon", true);
|
||||
src.detail_distance[2] = 1234;
|
||||
strcpy_s(src.weapon_substitution_pattern_names[1], "Other Laser");
|
||||
src.spawn_info[1].spawn_count = 7;
|
||||
src.damage = 42.5f;
|
||||
src.wi_flags.set(Weapon::Info_Flags::Homing_heat);
|
||||
src.proximity_iff = {1, 3};
|
||||
src.b_info.beam_iff_miss_factor[2] = {{0.1f, 0.2f, 0.3f, 0.4f, 0.5f}};
|
||||
src.b_info.t5info.burst_rot_pattern = {0.25f};
|
||||
src.custom_data["key"] = "value";
|
||||
|
||||
weapon_info dest;
|
||||
dest.clone(src);
|
||||
|
||||
EXPECT_STREQ(dest.name, "Template Laser");
|
||||
EXPECT_EQ(dest.display_name, "Shown Name");
|
||||
ASSERT_NE(dest.desc, nullptr);
|
||||
EXPECT_STREQ(dest.desc.get(), "a description");
|
||||
ASSERT_NE(dest.failure_sub_name, nullptr);
|
||||
EXPECT_STREQ(dest.failure_sub_name.get(), "Sub Weapon");
|
||||
EXPECT_EQ(dest.detail_distance[2], 1234);
|
||||
EXPECT_STREQ(dest.weapon_substitution_pattern_names[1], "Other Laser");
|
||||
EXPECT_EQ(dest.spawn_info[1].spawn_count, 7);
|
||||
EXPECT_EQ(dest.damage, 42.5f);
|
||||
EXPECT_TRUE(dest.wi_flags[Weapon::Info_Flags::Homing_heat]);
|
||||
EXPECT_EQ(dest.proximity_iff, src.proximity_iff);
|
||||
EXPECT_EQ(dest.b_info.beam_iff_miss_factor, src.b_info.beam_iff_miss_factor);
|
||||
EXPECT_EQ(dest.b_info.t5info.burst_rot_pattern, src.b_info.t5info.burst_rot_pattern);
|
||||
EXPECT_EQ(dest.custom_data, src.custom_data);
|
||||
}
|
||||
Reference in new issue
Block a user