diff --git a/code/asteroid/asteroid.cpp b/code/asteroid/asteroid.cpp index 05caf2105d4..9cf86ad2360 100644 --- a/code/asteroid/asteroid.cpp +++ b/code/asteroid/asteroid.cpp @@ -702,7 +702,7 @@ void remove_all_asteroids() } // will replace any existing asteroid or debris field with an asteroid field -void asteroid_create_asteroid_field(int num_asteroids, int field_type, int asteroid_speed, bool brown, bool blue, bool orange, vec3d o_min, vec3d o_max, bool inner_box, vec3d i_min, vec3d i_max, SCP_vector targets) +void asteroid_create_asteroid_field(int num_asteroids, int field_type, int asteroid_speed, vec3d o_min, vec3d o_max, bool inner_box, vec3d i_min, vec3d i_max, SCP_vector asteroid_types) { remove_all_asteroids(); @@ -740,15 +740,7 @@ void asteroid_create_asteroid_field(int num_asteroids, int field_type, int aster Asteroid_field.field_asteroid_type.clear(); - if (brown) { - Asteroid_field.field_asteroid_type.push_back("Brown"); - } - if (blue) { - Asteroid_field.field_asteroid_type.push_back("Blue"); - } - if (orange) { - Asteroid_field.field_asteroid_type.push_back("Orange"); - } + Asteroid_field.field_asteroid_type = std::move(asteroid_types); Asteroid_field.min_bound = o_min; Asteroid_field.max_bound = o_max; @@ -766,8 +758,6 @@ void asteroid_create_asteroid_field(int num_asteroids, int field_type, int aster Asteroid_field.inner_max_bound = i_max; } - Asteroid_field.target_names = std::move(targets); - // Only create asteroids if we have some to create if ((!Asteroid_field.field_asteroid_type.empty()) && (num_asteroids > 0)) { asteroid_create_all(); diff --git a/code/asteroid/asteroid.h b/code/asteroid/asteroid.h index 14b12ac2175..a30c855ec43 100644 --- a/code/asteroid/asteroid.h +++ b/code/asteroid/asteroid.h @@ -163,7 +163,7 @@ bool asteroid_is_within_view(vec3d *pos, float range, bool range_override = f void asteroid_level_init(); void asteroid_level_close(); void asteroid_create_all(); -void asteroid_create_asteroid_field(int num_asteroids, int field_type, int asteroid_speed, bool brown, bool blue, bool orange, vec3d o_min, vec3d o_max, bool inner_box, vec3d i_min, vec3d i_max, SCP_vector targets); +void asteroid_create_asteroid_field(int num_asteroids, int field_type, int asteroid_speed, vec3d o_min, vec3d o_max, bool inner_box, vec3d i_min, vec3d i_max, SCP_vector asteroid_types); void asteroid_create_debris_field(int num_asteroids, int asteroid_speed, SCP_vector debris_types, vec3d o_min, vec3d o_max, bool enhanced); void asteroid_render(object* obj, model_draw_list* scene); void asteroid_delete( object *asteroid_objp ); diff --git a/code/parse/sexp.cpp b/code/parse/sexp.cpp index d5cafc29cf7..d4e5f300779 100644 --- a/code/parse/sexp.cpp +++ b/code/parse/sexp.cpp @@ -765,8 +765,11 @@ SCP_vector Operators = { { "set-skybox-alpha", OP_SET_SKYBOX_ALPHA, 1, 1, SEXP_ACTION_OPERATOR, }, // Goober5000 { "set-ambient-light", OP_SET_AMBIENT_LIGHT, 3, 3, SEXP_ACTION_OPERATOR, }, // Karajorma { "toggle-asteroid-field", OP_TOGGLE_ASTEROID_FIELD, 1, 1, SEXP_ACTION_OPERATOR, }, // MjnMixael - { "set-asteroid-field", OP_SET_ASTEROID_FIELD, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // MjnMixael - { "set-debris-field", OP_SET_DEBRIS_FIELD, 1, 12, SEXP_ACTION_OPERATOR, }, // MjnMixael + { "set-asteroid-field", OP_SET_ASTEROID_FIELD, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // MjnMixael - Deprecated + { "set-debris-field", OP_SET_DEBRIS_FIELD, 1, 12, SEXP_ACTION_OPERATOR, }, // MjnMixael - Deprecated + { "config-asteroid-field", OP_CONFIG_ASTEROID_FIELD, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // MjnMixael + { "config-debris-field", OP_CONFIG_DEBRIS_FIELD, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // MjnMixael + { "config-field-targets", OP_CONFIG_FIELD_TARGETS, 1, INT_MAX, SEXP_ACTION_OPERATOR, }, // MjnMixael { "set-motion-debris", OP_SET_MOTION_DEBRIS, 1, 1, SEXP_ACTION_OPERATOR, }, // MjnMixael //Jump Node Sub-Category @@ -4047,7 +4050,26 @@ int check_sexp_syntax(int node, int return_type, int recursive, int *bad_node, s break; } - case OPF_ASTEROID_DEBRIS: + case OPF_ASTEROID_TYPES: + if (type2 != SEXP_ATOM_STRING) { + return SEXP_CHECK_TYPE_MISMATCH; + } else { + auto list = get_list_valid_asteroid_subtypes(); + bool valid = false; + for (const auto& item : list) { + if (!stricmp(CTEXT(node), item.c_str())) { + valid = true; + break; + } + } + + if (stricmp(CTEXT(node), SEXP_NONE_STRING) && !valid) { + return SEXP_CHECK_INVALID_ASTEROID; + } + } + break; + + case OPF_DEBRIS_TYPES: if (type2 != SEXP_ATOM_STRING) { return SEXP_CHECK_TYPE_MISMATCH; } @@ -16359,7 +16381,7 @@ void sexp_toggle_asteroid_field(int n) Asteroids_enabled = is_sexp_true(n); } -void sexp_set_asteroid_field(int n) +void sexp_set_asteroid_field(int n, bool new_sexp) { bool is_nan, is_nan_forever; @@ -16381,22 +16403,29 @@ void sexp_set_asteroid_field(int n) } } - bool brown = true; - if (n >= 0) { - brown = is_sexp_true(n); - n = CDR(n); - } + SCP_vector asteroid_types; - bool blue = false; - if (n >= 0) { - blue = is_sexp_true(n); - n = CDR(n); - } + if (!new_sexp) { + if (n >= 0) { + if (is_sexp_true(n)) { + asteroid_types.push_back("Brown"); + } + n = CDR(n); + } - bool orange = false; - if (n >= 0) { - orange = is_sexp_true(n); - n = CDR(n); + if (n >= 0) { + if (is_sexp_true(n)) { + asteroid_types.push_back("Blue"); + } + n = CDR(n); + } + + if (n >= 0) { + if (is_sexp_true(n)) { + asteroid_types.push_back("Orange"); + } + n = CDR(n); + } } int o_minx = -1000, o_miny = -1000, o_minz = -1000; @@ -16458,13 +16487,30 @@ void sexp_set_asteroid_field(int n) } SCP_vector targets; - if (n >= 0) { - for (; n >= 0; true ? n = CDR(n) : n = -1) { - auto ship_entry = eval_ship(n); - if (!ship_entry) - continue; + if (!new_sexp) { + if (n >= 0) { + for (; n >= 0;n = CDR(n)) { + auto ship_entry = eval_ship(n); + if (!ship_entry) + continue; - targets.push_back(ship_entry->name); + targets.push_back(ship_entry->name); + } + } + } else { + if (n >= 0) { + auto list = get_list_valid_asteroid_subtypes(); + for (; n >= 0;n = CDR(n)) { + + // Verify that it's a valid asteroid type + for (const auto& item : list) { + if (stricmp(CTEXT(n), item.c_str())) { + continue; + } + } + + asteroid_types.emplace_back(CTEXT(n)); + } } } @@ -16482,19 +16528,20 @@ void sexp_set_asteroid_field(int n) num_asteroids, field_type, asteroid_speed, - brown, - blue, - orange, o_min, o_max, inner_box, i_min, i_max, - std::move(targets)); + std::move(asteroid_types)); + + if (!new_sexp) { + Asteroid_field.target_names = std::move(targets); + } } -void sexp_set_debris_field(int n) +void sexp_set_debris_field(int n, bool new_sexp) { bool is_nan, is_nan_forever; @@ -16514,22 +16561,31 @@ void sexp_set_debris_field(int n) } } - int debris1 = -1; - if (n >= 0) { - debris1 = get_asteroid_index(CTEXT(n)); - n = CDR(n); - } + SCP_vector debris_types; + if (!new_sexp) { + if (n >= 0) { + int debris1 = get_asteroid_index(CTEXT(n)); + if (debris1 >= 0) { + debris_types.push_back(debris1); + } + n = CDR(n); + } - int debris2 = -1; - if (n >= 0) { - debris2 = get_asteroid_index(CTEXT(n)); - n = CDR(n); - } + if (n >= 0) { + int debris2 = get_asteroid_index(CTEXT(n)); + if (debris2 >= 0) { + debris_types.push_back(debris2); + } + n = CDR(n); + } - int debris3 = -1; - if (n >= 0) { - debris3 = get_asteroid_index(CTEXT(n)); - n = CDR(n); + if (n >= 0) { + int debris3 = get_asteroid_index(CTEXT(n)); + if (debris3 >= 0) { + debris_types.push_back(debris3); + } + n = CDR(n); + } } int o_minx = -1000, o_miny = -1000, o_minz = -1000; @@ -16570,15 +16626,18 @@ void sexp_set_debris_field(int n) vec3d o_min = vm_vec_new((float)o_minx, (float)o_miny, (float)o_minz); vec3d o_max = vm_vec_new((float)o_maxx, (float)o_maxy, (float)o_maxz); - SCP_vector debris_types; - if (debris1 > 0) { - debris_types.push_back(debris1); - } - if (debris2 > 0) { - debris_types.push_back(debris2); - } - if (debris3 > 0) { - debris_types.push_back(debris3); + if (new_sexp) { + if (n >= 0) { + for (; n >= 0; n = CDR(n)) { + + // Verify that it's a valid debris type + auto idx = get_asteroid_index(CTEXT(n)); + if (idx < 0) + continue; + + debris_types.push_back(idx); + } + } } asteroid_create_debris_field( @@ -16590,6 +16649,61 @@ void sexp_set_debris_field(int n) enhanced); } +void sexp_config_field_targets(int n) +{ + // Do nothing for disabled fields + if (Asteroid_field.num_initial_asteroids == 0) { + return; + } + + // Do nothing for passive fields + if (Asteroid_field.field_type == FT_PASSIVE) { + return; + } + + bool toggle = false; + if (n >= 0) { + toggle = is_sexp_true(n); + n = CDR(n); + } + + SCP_vector targets; + if (n >= 0) { + for (; n >= 0; n = CDR(n)) { + auto ship_entry = eval_ship(n); + if (!ship_entry) + continue; + + targets.push_back(ship_entry->name); + } + } + + if (targets.size() == 0) { + if (toggle) { + // No ships provided to add so abort + return; + } else { + Asteroid_field.target_names.clear(); + return; + } + } else { + if (toggle) { + // Add the targets + for (const auto& ship : targets) { + // Check if the ship is already in the target_names + if (std::find(Asteroid_field.target_names.begin(), Asteroid_field.target_names.end(), ship) == Asteroid_field.target_names.end()) { + Asteroid_field.target_names.push_back(ship); + } + } + } else { + // Remove the targets + for (const auto& ship : targets) { + Asteroid_field.target_names.erase(std::remove(Asteroid_field.target_names.begin(), Asteroid_field.target_names.end(), ship), Asteroid_field.target_names.end()); + } + } + } +} + void sexp_set_motion_debris_type(int n) { SCP_string name = CTEXT(n); @@ -28574,12 +28688,27 @@ int eval_sexp(int cur_node, int referenced_node) break; case OP_SET_ASTEROID_FIELD: - sexp_set_asteroid_field(node); + sexp_set_asteroid_field(node, false); sexp_val = SEXP_TRUE; break; case OP_SET_DEBRIS_FIELD: - sexp_set_debris_field(node); + sexp_set_debris_field(node, false); + sexp_val = SEXP_TRUE; + break; + + case OP_CONFIG_ASTEROID_FIELD: + sexp_set_asteroid_field(node, true); + sexp_val = SEXP_TRUE; + break; + + case OP_CONFIG_DEBRIS_FIELD: + sexp_set_debris_field(node, true); + sexp_val = SEXP_TRUE; + break; + + case OP_CONFIG_FIELD_TARGETS: + sexp_config_field_targets(node); sexp_val = SEXP_TRUE; break; @@ -30943,6 +31072,9 @@ int query_operator_return_type(int op) case OP_TOGGLE_ASTEROID_FIELD: case OP_SET_ASTEROID_FIELD: case OP_SET_DEBRIS_FIELD: + case OP_CONFIG_ASTEROID_FIELD: + case OP_CONFIG_DEBRIS_FIELD: + case OP_CONFIG_FIELD_TARGETS: case OP_SET_MOTION_DEBRIS: case OP_SET_PRIMARY_AMMO: case OP_SET_SECONDARY_AMMO: @@ -33659,12 +33791,40 @@ int query_operator_argument_type(int op, int argnum) if (argnum <= 1) return OPF_POSITIVE; else if (argnum <= 4) - return OPF_ASTEROID_DEBRIS; + return OPF_DEBRIS_TYPES; else if (argnum <= 10) return OPF_NUMBER; else return OPF_BOOL; + case OP_CONFIG_ASTEROID_FIELD: + if (argnum <= 2) + return OPF_POSITIVE; + else if (argnum <= 8) + return OPF_NUMBER; + else if (argnum == 9) + return OPF_BOOL; + else if (argnum <= 15) + return OPF_NUMBER; + else + return OPF_ASTEROID_TYPES; + + case OP_CONFIG_DEBRIS_FIELD: + if (argnum <= 1) + return OPF_POSITIVE; + else if (argnum <= 7) + return OPF_NUMBER; + else if (argnum <= 8) + return OPF_BOOL; + else + return OPF_DEBRIS_TYPES; + + case OP_CONFIG_FIELD_TARGETS: + if (argnum == 0) + return OPF_BOOL; + else + return OPF_SHIP; + case OP_SET_MOTION_DEBRIS: return OPF_MOTION_DEBRIS; @@ -36120,6 +36280,9 @@ int get_category(int op_id) case OP_VALIDATE_GENERAL_ORDERS: case OP_SET_ASTEROID_FIELD: case OP_SET_DEBRIS_FIELD: + case OP_CONFIG_ASTEROID_FIELD: + case OP_CONFIG_DEBRIS_FIELD: + case OP_CONFIG_FIELD_TARGETS: case OP_SET_WING_FORMATION: case OP_SET_MOTION_DEBRIS: return OP_CATEGORY_CHANGE; @@ -36561,6 +36724,9 @@ int get_subcategory(int op_id) case OP_TOGGLE_ASTEROID_FIELD: case OP_SET_ASTEROID_FIELD: case OP_SET_DEBRIS_FIELD: + case OP_CONFIG_ASTEROID_FIELD: + case OP_CONFIG_DEBRIS_FIELD: + case OP_CONFIG_FIELD_TARGETS: case OP_SET_MOTION_DEBRIS: return CHANGE_SUBCATEGORY_BACKGROUND_AND_NEBULA; @@ -41570,7 +41736,7 @@ SCP_vector Sexp_help = { "\t1:\ttrue for field on, false for field off\r\n" }, - { OP_SET_ASTEROID_FIELD, "set-asteroid-field\r\n" + { OP_SET_ASTEROID_FIELD, "set-asteroid-field (deprecated in favor of config-asteroid-field)\r\n" "\tCreates or overwrites the asteroid or debris field with an asteroid field. \r\n" "\tTakes 1 or more arguments...\r\n" "\t1:\tNumber of asteroids in the field, or 0 to remove an existing field\r\n" @@ -41595,7 +41761,7 @@ SCP_vector Sexp_help = { "\tRest:\tThe ships the asteroid field will target if it's an active field\r\n" }, - { OP_SET_DEBRIS_FIELD, "set-debris-field\r\n" + { OP_SET_DEBRIS_FIELD, "set-debris-field (deprecated in favor of config-debris-field)\r\n" "\tCreates or overwrites the asteroid or debris field with a debris field. \r\n" "\tTakes 1 or more arguments...\r\n" "\t1:\tNumber of debris in the field, or 0 to remove an existing field\r\n" @@ -41612,6 +41778,54 @@ SCP_vector Sexp_help = { "\t12:\tIf the field uses enhanced spawning checks, defaults to false\r\n" }, + { OP_CONFIG_ASTEROID_FIELD, "config-asteroid-field\r\n" + "\tCreates or overwrites the asteroid or debris field with an asteroid field. \r\n" + "\tNote that setting targets for an active field must be done with config-asteroid-targets. \r\n" + "\tTakes 1 or more arguments...\r\n" + "\t1:\tNumber of asteroids in the field, or 0 to remove an existing field\r\n" + "\t2:\t0 for passive field, 1 for active field, 2 for enhanced passive, 3 for enhanced active, defaults to 0\r\n" + "\t3:\tThe speed of the asteroids, defaults to 0\r\n" + "\t4:\tOuterbox Min X, defaults to -1000\r\n" + "\t5:\tOuterbox Max X, defaults to 1000\r\n" + "\t6:\tOuterbox Min Y, defaults to -1000\r\n" + "\t7:\tOuterbox Max Y, defaults to 1000\r\n" + "\t8:\tOuterbox Min Z, defaults to -1000\r\n" + "\t9:\tOuterbox Max Z, defaults to 1000\r\n" + "\t10:\tTrue to activate the inner box where no asteroids will be spawned, defaults to false\r\n" + "\t11:\tInnerbox Min X, defaults to -500\r\n" + "\t12:\tInnerbox Max X, defaults to 500\r\n" + "\t13:\tInnerbox Min Y, defaults to -500\r\n" + "\t14:\tInnerbox Max Y, defaults to 500\r\n" + "\t15:\tInnerbox Min Z, defaults to -500\r\n" + "\t16:\tInnerbox Max Z, defaults to 500\r\n" + "\tRest:\tThe asteroid types to enable\r\n" + }, + + { OP_CONFIG_DEBRIS_FIELD, "config-debris-field\r\n" + "\tCreates or overwrites the asteroid or debris field with a debris field. \r\n" + "\tTakes 1 or more arguments...\r\n" + "\t1:\tNumber of debris in the field, or 0 to remove an existing field\r\n" + "\t2:\tThe speed of the asteroids, defaults to 0\r\n" + "\t3:\tOuterbox Min X, defaults to -1000\r\n" + "\t4:\tOuterbox Max X, defaults to 1000\r\n" + "\t5:\tOuterbox Min Y, defaults to -1000\r\n" + "\t6:\tOuterbox Max Y, defaults to 1000\r\n" + "\t7:\tOuterbox Min Z, defaults to -1000\r\n" + "\t8:\tOuterbox Max Z, defaults to 1000\r\n" + "\t9:\tIf the field uses enhanced spawning checks, defaults to false\r\n" + "\tRest:\tThe asteroid types to enable\r\n" + }, + + { OP_CONFIG_FIELD_TARGETS, "config-field-targets\r\n" + "\tAdds or removes ships from the Asteroid Field targets list. Only works on Active fields. \r\n" + "\tYou can remove all targets at once by supplying 0 ship arguments. \r\n" + "\tRemoving all targets will force the field to use default behavior and target the first ship on the escort list. \r\n" + "\tThe inverse is not true. Ship arguments must be provided to add targets. \r\n" + "\tTakes 1 or more arguments...\r\n" + "\t1:\tTrue to add to the list, false to remove\r\n" + "\tRest:\tThe names of ships to add or remove\r\n" + }, + { OP_SET_MOTION_DEBRIS, "set-motion-debris\r\n" "\tSets the bitmap used for motion debris. If set-motion-debris-override is set then this will unset it.\r\n" "\tTakes 1 argument...\r\n" diff --git a/code/parse/sexp.h b/code/parse/sexp.h index 9504342aea6..f6e2c4ec450 100644 --- a/code/parse/sexp.h +++ b/code/parse/sexp.h @@ -134,7 +134,8 @@ enum sexp_opf_t : int { OPF_TRANSLATING_SUBSYSTEM, // Goober5000 - a translating subsystem OPF_ANY_HUD_GAUGE, // Goober5000 - both custom and builtin OPF_WING_FLAG, // Goober5000 - The name of a wing flag - OPF_ASTEROID_DEBRIS, // MjnMixael - Debris types as defined in asteroids.tbl + OPF_ASTEROID_TYPES, // MjnMixael - Asteroids from asteroids.tbl, asteroid types only + OPF_DEBRIS_TYPES, // MjnMixael - Asteroids from asteroids.tbl, debris types only OPF_WING_FORMATION, // Goober5000 - as defined in ships.tbl OPF_MOTION_DEBRIS, // MjnMixael - Motion debris types as defined in stars.tbl OPF_TURRET_TYPE, // MjnMixael - Turret types as defined in aiturret.cpp @@ -910,8 +911,10 @@ enum : int { OP_VALIDATE_GENERAL_ORDERS, // MjnMixael OP_USED_CHEAT, // Kiloku OP_SET_ASTEROID_FIELD, // MjnMixael - OP_SET_DEBRIS_FIELD, // MjnMixael + OP_CONFIG_ASTEROID_FIELD, // MjnMixael + OP_CONFIG_DEBRIS_FIELD, // MjnMixael + OP_CONFIG_FIELD_TARGETS, // MjnMixael OP_SET_MOTION_DEBRIS, // MjnMixael OP_GOOD_PRIMARY_TIME, // plieblang OP_SET_SKYBOX_ALPHA, // Goober5000 diff --git a/fred2/sexp_tree.cpp b/fred2/sexp_tree.cpp index da8152622c9..6e5ee4ab804 100644 --- a/fred2/sexp_tree.cpp +++ b/fred2/sexp_tree.cpp @@ -1015,6 +1015,8 @@ void sexp_tree::right_clicked(int mode) case OP_ADD_SUN_BITMAP: case OP_JUMP_NODE_SET_JUMPNODE_NAME: case OP_KEY_RESET: + case OP_SET_ASTEROID_FIELD: + case OP_SET_DEBRIS_FIELD: j = (int)op_menu.size(); // don't allow these operators to be visible break; } @@ -1071,6 +1073,8 @@ void sexp_tree::right_clicked(int mode) case OP_ADD_SUN_BITMAP: case OP_JUMP_NODE_SET_JUMPNODE_NAME: case OP_KEY_RESET: + case OP_SET_ASTEROID_FIELD: + case OP_SET_DEBRIS_FIELD: j = (int)op_submenu.size(); // don't allow these operators to be visible break; } @@ -3661,12 +3665,20 @@ int sexp_tree::query_default_argument_available(int op, int i) } return 0; - case OPF_ASTEROID_DEBRIS: - if ((Asteroid_info.size() - NUM_ASTEROID_SIZES) > 0) { + case OPF_ASTEROID_TYPES: + if (!get_list_valid_asteroid_subtypes().empty()) { return 1; } return 0; + case OPF_DEBRIS_TYPES: + for (const auto& this_asteroid : Asteroid_info) { + if (this_asteroid.type == ASTEROID_TYPE_DEBRIS) { + return 1; + } + } + return 0; + case OPF_MOTION_DEBRIS: if (Motion_debris_info.size() > 0) { return 1; @@ -5745,8 +5757,12 @@ sexp_list_item *sexp_tree::get_listing_opf(int opf, int parent_node, int arg_ind list = nullptr; break; - case OPF_ASTEROID_DEBRIS: - list = get_listing_opf_asteroid_debris(); + case OPF_ASTEROID_TYPES: + list = get_listing_opf_asteroid_types(); + break; + + case OPF_DEBRIS_TYPES: + list = get_listing_opf_debris_types(); break; case OPF_WING_FORMATION: @@ -7523,16 +7539,30 @@ sexp_list_item *sexp_tree::get_listing_opf_nebula_patterns() return head.next; } -sexp_list_item* sexp_tree::get_listing_opf_asteroid_debris() +sexp_list_item *sexp_tree::get_listing_opf_asteroid_types() +{ + sexp_list_item head; + + head.add_data(SEXP_NONE_STRING); + + auto list = get_list_valid_asteroid_subtypes(); + + for (const auto& this_asteroid : list) { + head.add_data(this_asteroid.c_str()); + } + + return head.next; +} + +sexp_list_item *sexp_tree::get_listing_opf_debris_types() { sexp_list_item head; head.add_data(SEXP_NONE_STRING); - for (int i = 0; i < (int)Asteroid_info.size(); i++) { - //first three asteroids are not debris-Mjn - if (i > (NUM_ASTEROID_SIZES - 1)) { - head.add_data(Asteroid_info[i].name); + for (const auto& this_asteroid : Asteroid_info) { + if (this_asteroid.type == ASTEROID_TYPE_DEBRIS) { + head.add_data(this_asteroid.name); } } diff --git a/fred2/sexp_tree.h b/fred2/sexp_tree.h index 599797251f8..965f6430b08 100644 --- a/fred2/sexp_tree.h +++ b/fred2/sexp_tree.h @@ -298,7 +298,8 @@ class sexp_tree : public CTreeCtrl sexp_list_item *get_listing_opf_wing_flags(); sexp_list_item *get_listing_opf_team_colors(); sexp_list_item *get_listing_opf_nebula_patterns(); - sexp_list_item *get_listing_opf_asteroid_debris(); + sexp_list_item *get_listing_opf_asteroid_types(); + sexp_list_item *get_listing_opf_debris_types(); sexp_list_item *get_listing_opf_motion_debris(); sexp_list_item *get_listing_opf_game_snds(); sexp_list_item *get_listing_opf_fireball(); diff --git a/qtfred/src/ui/widgets/sexp_tree.cpp b/qtfred/src/ui/widgets/sexp_tree.cpp index 1709426c077..f8a5d62a9f0 100644 --- a/qtfred/src/ui/widgets/sexp_tree.cpp +++ b/qtfred/src/ui/widgets/sexp_tree.cpp @@ -1671,12 +1671,20 @@ int sexp_tree::query_default_argument_available(int op, int i) { } return 0; - case OPF_ASTEROID_DEBRIS: - if ((Asteroid_info.size() - NUM_ASTEROID_SIZES) > 0) { + case OPF_ASTEROID_TYPES: + if (!get_list_valid_asteroid_subtypes().empty()) { return 1; } return 0; + case OPF_DEBRIS_TYPES: + for (const auto& this_asteroid : Asteroid_info) { + if (this_asteroid.type == ASTEROID_TYPE_DEBRIS) { + return 1; + } + } + return 0; + case OPF_TRAITOR_OVERRIDE: return Traitor_overrides.empty() ? 0 : 1; @@ -3449,8 +3457,12 @@ sexp_list_item* sexp_tree::get_listing_opf(int opf, int parent_node, int arg_ind list = nullptr; break; - case OPF_ASTEROID_DEBRIS: - list = get_listing_opf_asteroid_debris(); + case OPF_ASTEROID_TYPES: + list = get_listing_opf_asteroid_types(); + break; + + case OPF_DEBRIS_TYPES: + list = get_listing_opf_debris_types(); break; case OPF_WING_FORMATION: @@ -5197,16 +5209,30 @@ sexp_list_item* sexp_tree::get_listing_opf_message_types() return head.next; } -sexp_list_item* sexp_tree::get_listing_opf_asteroid_debris() +sexp_list_item *sexp_tree::get_listing_opf_asteroid_types() +{ + sexp_list_item head; + + head.add_data(SEXP_NONE_STRING); + + auto list = get_list_valid_asteroid_subtypes(); + + for (const auto& this_asteroid : list) { + head.add_data(this_asteroid.c_str()); + } + + return head.next; +} + +sexp_list_item *sexp_tree::get_listing_opf_debris_types() { sexp_list_item head; head.add_data(SEXP_NONE_STRING); - for (int i = 0; i < (int)Asteroid_info.size(); i++) { - // first three asteroids are not debris-Mjn - if (i > (NUM_ASTEROID_SIZES - 1)) { - head.add_data(Asteroid_info[i].name); + for (const auto& this_asteroid : Asteroid_info) { + if (this_asteroid.type == ASTEROID_TYPE_DEBRIS) { + head.add_data(this_asteroid.name); } } @@ -6095,6 +6121,8 @@ std::unique_ptr sexp_tree::buildContextMenu(QTreeWidgetItem* h) { case OP_ADD_SUN_BITMAP: case OP_JUMP_NODE_SET_JUMPNODE_NAME: case OP_KEY_RESET: + case OP_SET_ASTEROID_FIELD: + case OP_SET_DEBRIS_FIELD: j = (int) op_menu.size(); // don't allow these operators to be visible break; } @@ -6168,6 +6196,8 @@ std::unique_ptr sexp_tree::buildContextMenu(QTreeWidgetItem* h) { case OP_ADD_SUN_BITMAP: case OP_JUMP_NODE_SET_JUMPNODE_NAME: case OP_KEY_RESET: + case OP_SET_ASTEROID_FIELD: + case OP_SET_DEBRIS_FIELD: j = (int) op_submenu.size(); // don't allow these operators to be visible break; } diff --git a/qtfred/src/ui/widgets/sexp_tree.h b/qtfred/src/ui/widgets/sexp_tree.h index 2e206e9e2a3..04f4503b1b3 100644 --- a/qtfred/src/ui/widgets/sexp_tree.h +++ b/qtfred/src/ui/widgets/sexp_tree.h @@ -347,7 +347,8 @@ class sexp_tree: public QTreeWidget { sexp_list_item* get_listing_opf_team_colors(); sexp_list_item* get_listing_opf_nebula_patterns(); sexp_list_item* get_listing_opf_motion_debris(); - sexp_list_item* get_listing_opf_asteroid_debris(); + static sexp_list_item* get_listing_opf_asteroid_types(); + static sexp_list_item* get_listing_opf_debris_types(); sexp_list_item* get_listing_opf_game_snds(); sexp_list_item* get_listing_opf_fireball(); sexp_list_item *get_listing_opf_species();