diff --git a/code/asteroid/asteroid.cpp b/code/asteroid/asteroid.cpp index 51619e061fc..2b3e56d2637 100644 --- a/code/asteroid/asteroid.cpp +++ b/code/asteroid/asteroid.cpp @@ -1593,9 +1593,8 @@ static float asteroid_create_explosion(object *objp) fireball_type = FIREBALL_ASTEROID; } - if (fireball_type >= Num_fireball_types) { - Warning(LOCATION, "Invalid fireball type %i specified for an asteroid, only %i fireball types are defined.", fireball_type, Num_fireball_types); - + if (fireball_type >= static_cast(Fireball_info.size())) { + Warning(LOCATION, "Invalid fireball type %i specified for an asteroid; only " SIZE_T_ARG " fireball types are defined.", fireball_type, Fireball_info.size()); return 0; } @@ -2251,10 +2250,7 @@ static void asteroid_parse_section() } if(optional_string("$Explosion Animations:")){ - int temp[MAX_FIREBALL_TYPES]; - auto parsed_ints = stuff_int_list(temp, MAX_FIREBALL_TYPES, RAW_INTEGER_TYPE); - asteroid_p->explosion_bitmap_anims.clear(); - asteroid_p->explosion_bitmap_anims.insert(asteroid_p->explosion_bitmap_anims.begin(), temp, temp + parsed_ints); + stuff_fireball_index_list(asteroid_p->explosion_bitmap_anims, asteroid_p->name); } if (optional_string("$Explosion Radius Mult:")) { diff --git a/code/fireball/fireballs.cpp b/code/fireball/fireballs.cpp index a5ea43f86c9..1b2783799f8 100644 --- a/code/fireball/fireballs.cpp +++ b/code/fireball/fireballs.cpp @@ -37,11 +37,7 @@ constexpr int INTITIAL_FIREBALL_CONTAINTER_SIZE = 256; SCP_vector Fireballs; SCP_vector Unused_fireball_indices; -fireball_info Fireball_info[MAX_FIREBALL_TYPES]; - -int fireball_used[MAX_FIREBALL_TYPES]; - -int Num_fireball_types = 0; +SCP_vector Fireball_info; bool fireballs_inited = false; bool fireballs_parsed = false; @@ -120,7 +116,7 @@ void fireball_play_warphole_close_sound(fireball *fb) static void fireball_generate_unique_id(char *unique_id, int buffer_len, int fireball_index) { - Assert((fireball_index >= 0) && (fireball_index < MAX_FIREBALL_TYPES)); + Assertion(SCP_vector_inbounds(Fireball_info, fireball_index), "fireball_index is out of bounds!"); switch (fireball_index) { @@ -164,7 +160,7 @@ static void fireball_generate_unique_id(char *unique_id, int buffer_len, int fir */ static void fireball_set_default_color(int idx) { - Assert((idx >= 0) && (idx < MAX_FIREBALL_TYPES)); + Assertion(SCP_vector_inbounds(Fireball_info, idx), "idx is out of bounds!"); switch (idx) { @@ -200,7 +196,7 @@ static void fireball_set_default_color(int idx) static void fireball_set_default_warp_attributes(int idx) { - Assert((idx >= 0) && (idx < MAX_FIREBALL_TYPES)); + Assertion(SCP_vector_inbounds(Fireball_info, idx), "idx is out of bounds!"); switch (idx) { @@ -232,9 +228,9 @@ void fireball_info_clear(fireball_info *fb) int fireball_info_lookup(const char *unique_id) { - for (int i = 0; i < Num_fireball_types; ++i) + for (size_t i = 0; i < Fireball_info.size(); ++i) if (!stricmp(Fireball_info[i].unique_id, unique_id)) - return i; + return static_cast(i); return -1; } @@ -308,25 +304,19 @@ static void parse_fireball_tbl(const char *table_filename) // we are creating a new entry, so set some defaults else { - // make sure we don't exceed the max - if (Num_fireball_types >= MAX_FIREBALL_TYPES) - { - error_display(0, "Too many fireball entries! Max is %d", MAX_FIREBALL_TYPES); - return; - } - - fi = &Fireball_info[Num_fireball_types]; + int new_fireball_index = static_cast(Fireball_info.size()); + Fireball_info.emplace_back(); + fi = &Fireball_info.back(); fireball_info_clear(fi); // If the table didn't specify a unique ID, generate one. This will be assigned a few lines later. if (strlen(unique_id) == 0) - fireball_generate_unique_id(unique_id, NAME_LENGTH, Num_fireball_types); + fireball_generate_unique_id(unique_id, NAME_LENGTH, new_fireball_index); // Set remaining fireball defaults - fireball_set_default_color(Num_fireball_types); - fireball_set_default_warp_attributes(Num_fireball_types); + fireball_set_default_color(new_fireball_index); + fireball_set_default_warp_attributes(new_fireball_index); - Num_fireball_types++; first_time = true; } @@ -399,9 +389,9 @@ void fireball_parse_tbl() if (fireballs_parsed) return; - // every newly parsed fireball_info will get cleared before being added - // must do this outside of parse_fireball_tbl because it's called twice - Num_fireball_types = 0; + // every newly parsed fireball_info will get cleared before being added; + // must clear the vector outside of parse_fireball_tbl because it's called more than once + Fireball_info.clear(); parse_fireball_tbl("fireball.tbl"); @@ -436,10 +426,11 @@ void fireball_parse_tbl() void fireball_load_data() { - int i, idx; + int i, n, idx; fireball_info *fd; - for ( i = 0; i < Num_fireball_types; i++ ) { + n = static_cast(Fireball_info.size()); + for ( i = 0; i < n; i++ ) { fd = &Fireball_info[i]; for(idx=0; idxlod_count; idx++){ @@ -798,8 +789,7 @@ int fireball_create(vec3d *pos, int fireball_type, int render_type, int parent_o object *obj; fireball_info *fd; fireball_lod *fl; - Assert( fireball_type > -1 ); - Assert( fireball_type < Num_fireball_types ); + Assertion(SCP_vector_inbounds(Fireball_info, fireball_type), "fireball_type is out of bounds!"); fd = &Fireball_info[fireball_type]; @@ -946,13 +936,14 @@ void fireball_close() void fireballs_page_in() { - int i, idx; + int i, n, idx; fireball_info *fd; - for ( i = 0; i < Num_fireball_types; i++ ) { + n = static_cast(Fireball_info.size()); + for ( i = 0; i < n; i++ ) { fd = &Fireball_info[i]; - if((i < NUM_DEFAULT_FIREBALLS) || fireball_used[i]) { + if ((i < NUM_DEFAULT_FIREBALLS) || fd->fireball_used) { // if this is a Knossos ani, only load if Knossos_warp_ani_used is true if ( (i == FIREBALL_KNOSSOS) && !Knossos_warp_ani_used) continue; @@ -984,8 +975,8 @@ void fireball_get_color(int idx, float *red, float *green, float *blue) { Assert( red && blue && green ); - if ( (idx < 0) || (idx >= Num_fireball_types) ) { - Int3(); + if (!SCP_vector_inbounds(Fireball_info, idx)) { + UNREACHABLE("idx is out of bounds!"); *red = 1.0f; *green = 1.0f; @@ -1120,3 +1111,16 @@ int fireball_get_count() return count; } + +void stuff_fireball_index_list(SCP_vector &list, const char *name) +{ + stuff_int_list(list, RAW_INTEGER_TYPE); + + list.erase(std::remove_if(list.begin(), list.end(), [&](int index) { + if (!SCP_vector_inbounds(Fireball_info, index)) { + Warning(LOCATION, "Fireball index %d for %s was out of bounds. Removing this index.", index, name); + return true; + } + return false; + }), list.end()); +} diff --git a/code/fireball/fireballs.h b/code/fireball/fireballs.h index 3f4aeda6463..388282071db 100644 --- a/code/fireball/fireballs.h +++ b/code/fireball/fireballs.h @@ -33,15 +33,12 @@ class asteroid_info; #define FIREBALL_EXPLOSION_LARGE1 4 // Used for the big explosion when a ship breaks into pieces #define FIREBALL_EXPLOSION_LARGE2 5 // Used for the big explosion when a ship breaks into pieces -#define MAX_FIREBALL_TYPES 32 // The maximum number of fireballs that can be defined #define NUM_DEFAULT_FIREBALLS 6 #define MAX_FIREBALL_LOD 4 #define FIREBALL_NUM_LARGE_EXPLOSIONS 2 -extern int fireball_used[MAX_FIREBALL_TYPES]; - // all this moved here by Goober5000 because it makes more sense in the H file typedef struct fireball_lod { char filename[MAX_FILENAME_LEN]; @@ -57,6 +54,7 @@ typedef struct fireball_info { float exp_color[3]; // red, green, blue bool use_3d_warp; + bool fireball_used; char warp_glow[NAME_LENGTH]; int warp_glow_bitmap; @@ -66,8 +64,7 @@ typedef struct fireball_info { int warp_model_id; } fireball_info; -extern fireball_info Fireball_info[MAX_FIREBALL_TYPES]; -extern int Num_fireball_types; +extern SCP_vector Fireball_info; // flag values for fireball struct flags member #define FBF_WARP_CLOSE_SOUND_PLAYED (1<<0) @@ -153,4 +150,7 @@ extern bool Fireball_warp_flash; // Cyborg - get a count of how many valid fireballs are in the mission. int fireball_get_count(); +// Goober5000 - stuffs fireballs and checks that indexes are in bounds +void stuff_fireball_index_list(SCP_vector &list, const char *name); + #endif /* _FIREBALLS_H */ diff --git a/code/hud/hudartillery.cpp b/code/hud/hudartillery.cpp index e34a2014f23..47d702048f1 100644 --- a/code/hud/hudartillery.cpp +++ b/code/hud/hudartillery.cpp @@ -132,8 +132,8 @@ void parse_ssm(const char *filename) { int temp = atoi(unique_id); - if ((temp < 0) || (temp >= Num_fireball_types)) - error_display(0, "Fireball index [%d] out of range (should be 0-%d) for SSM strike [%s]", temp, Num_fireball_types - 1, s->name); + if (!SCP_vector_inbounds(Fireball_info, temp)) + error_display(0, "Fireball index [%d] out of range (should be 0-%d) for SSM strike [%s]", temp, static_cast(Fireball_info.size()) - 1, s->name); else s->fireball_type = temp; } diff --git a/code/parse/parselo.cpp b/code/parse/parselo.cpp index ffea15054e8..3b5053c24e1 100644 --- a/code/parse/parselo.cpp +++ b/code/parse/parselo.cpp @@ -3064,13 +3064,16 @@ const char* get_lookup_type_name(int lookup_type) return "Unknown lookup type, tell a coder!"; } -// Stuffs an integer list. -// This is of the form ( i* ) -// where i is an integer. -// For example, (1) () (1 2 3) ( 1 ) are legal integer lists. -size_t stuff_int_list(int *ilp, size_t max_ints, int lookup_type) +// use a functor here so that we don't need to re-roll the parsing function for both variants of stuff_int_lists +struct StuffIntListParser { - return stuff_token_list(ilp, max_ints, [&](int *buf)->bool { + int lookup_type; + + StuffIntListParser(int _lookup_type) + : lookup_type(_lookup_type) + {} + + bool operator()(int* buf) { if (*Mp == '"') { int num = 0; bool valid_negative = false; @@ -3123,7 +3126,25 @@ size_t stuff_int_list(int *ilp, size_t max_ints, int lookup_type) } return true; - }, get_lookup_type_name(lookup_type)); + } +}; + +// Stuffs an integer list. +// This is of the form ( i* ) +// where i is an integer. +// For example, (1) () (1 2 3) ( 1 ) are legal integer lists. +size_t stuff_int_list(int *ilp, size_t max_ints, int lookup_type) +{ + return stuff_token_list(ilp, max_ints, StuffIntListParser(lookup_type), get_lookup_type_name(lookup_type)); +} + +// Stuffs an integer list. +// This is of the form ( i* ) +// where i is an integer. +// For example, (1) () (1 2 3) ( 1 ) are legal integer lists. +void stuff_int_list(SCP_vector &ilp, int lookup_type) +{ + stuff_token_list(ilp, StuffIntListParser(lookup_type), get_lookup_type_name(lookup_type)); } // Karajorma/Goober5000 - Stuffs a loadout list by parsing a list of ship or weapon choices. diff --git a/code/parse/parselo.h b/code/parse/parselo.h index 6e4a5937e84..86477d3cf3a 100644 --- a/code/parse/parselo.h +++ b/code/parse/parselo.h @@ -234,6 +234,7 @@ void stuff_flagset(T *dest) { } extern size_t stuff_int_list(int *ilp, size_t max_ints, int lookup_type = RAW_INTEGER_TYPE); +extern void stuff_int_list(SCP_vector &ilp, int lookup_type = RAW_INTEGER_TYPE); extern size_t stuff_float_list(float* flp, size_t max_floats); extern void stuff_float_list(SCP_vector& flp); extern size_t stuff_vec3d_list(vec3d *vlp, size_t max_vecs); diff --git a/code/parse/sexp.cpp b/code/parse/sexp.cpp index ecc1a21c5c6..a2bb27f5d21 100644 --- a/code/parse/sexp.cpp +++ b/code/parse/sexp.cpp @@ -3995,7 +3995,7 @@ int check_sexp_syntax(int node, int return_type, int recursive, int *bad_node, s if (type2 == SEXP_ATOM_NUMBER || can_construe_as_integer(CTEXT(node))) { int num = atoi(CTEXT(node)); - if (num < 0 || num >= Num_fireball_types) + if (!SCP_vector_inbounds(Fireball_info, num)) { return SEXP_CHECK_NUM_RANGE_INVALID; } @@ -14234,7 +14234,7 @@ void sexp_explosion_effect(int n) { fireball_type = FIREBALL_EXPLOSION_LARGE2; } - else if (num >= Num_fireball_types) + else if (!SCP_vector_inbounds(Fireball_info, num)) { Warning(LOCATION, "explosion-effect fireball type is out of range; quitting the explosion...\n"); return; @@ -14431,7 +14431,7 @@ void sexp_warp_effect(int n) { fireball_type = FIREBALL_KNOSSOS; } - else if (num >= Num_fireball_types) + else if (!SCP_vector_inbounds(Fireball_info, num)) { Warning(LOCATION, "warp-effect fireball type is out of range; quitting the warp...\n"); return; diff --git a/code/scripting/api/libs/tables.cpp b/code/scripting/api/libs/tables.cpp index 14952c7085b..d6f150b65e4 100644 --- a/code/scripting/api/libs/tables.cpp +++ b/code/scripting/api/libs/tables.cpp @@ -220,7 +220,7 @@ ADE_FUNC(__len, l_Tables_FireballClasses, NULL, "Number of fireball classes", "n if (!fireballs_inited) return ade_set_args(L, "i", 0); - return ade_set_args(L, "i", Num_fireball_types); + return ade_set_args(L, "i", static_cast(Fireball_info.size())); } //*****SUBLIBRARY: Tables/SimulatedSpeechOverrides diff --git a/code/scripting/api/objs/fireballclass.cpp b/code/scripting/api/objs/fireballclass.cpp index 05d5229dc79..dacbe8e8055 100644 --- a/code/scripting/api/objs/fireballclass.cpp +++ b/code/scripting/api/objs/fireballclass.cpp @@ -18,7 +18,7 @@ ADE_FUNC(__tostring, l_Fireballclass, NULL, "Fireball class name", "string", "Fi if(!ade_get_args(L, "o", l_Fireballclass.Get(&idx))) return ade_set_error(L, "s", ""); - if(idx < 0 || idx >= Num_fireball_types) + if (!SCP_vector_inbounds(Fireball_info, idx)) return ade_set_error(L, "s", ""); return ade_set_args(L, "s", Fireball_info[idx].unique_id); @@ -30,10 +30,10 @@ ADE_FUNC(__eq, l_Fireballclass, "fireballclass, fireballclass", "Checks if the t if(!ade_get_args(L, "oo", l_Fireballclass.Get(&idx1), l_Fireballclass.Get(&idx2))) return ade_set_error(L, "b", false); - if(idx1 < 0 || idx1 >= Num_fireball_types) + if (!SCP_vector_inbounds(Fireball_info, idx1)) return ade_set_error(L, "b", false); - if(idx2 < 0 || idx2 >= Num_fireball_types) + if (!SCP_vector_inbounds(Fireball_info, idx2)) return ade_set_error(L, "b", false); return ade_set_args(L, "b", idx1 == idx2); @@ -45,7 +45,7 @@ ADE_VIRTVAR(UniqueID, l_Fireballclass, "string", "Fireball class name", "string" if(!ade_get_args(L, "o", l_Fireballclass.Get(&idx))) return ade_set_error(L, "s", ""); - if(idx < 0 || idx >= Num_fireball_types) + if (!SCP_vector_inbounds(Fireball_info, idx)) return ade_set_error(L, "s", ""); if (ADE_SETTING_VAR) @@ -60,7 +60,7 @@ ADE_VIRTVAR(Filename, l_Fireballclass, NULL, "Fireball class animation filename if(!ade_get_args(L, "o", l_Fireballclass.Get(&idx))) return ade_set_error(L, "s", ""); - if(idx < 0 || idx >= Num_fireball_types) + if (!SCP_vector_inbounds(Fireball_info, idx)) return ade_set_error(L, "s", ""); //Currently not settable as the bitmaps are only loaded once at level start @@ -76,7 +76,7 @@ ADE_VIRTVAR(NumberFrames, l_Fireballclass, NULL, "Amount of frames the animation if(!ade_get_args(L, "o", l_Fireballclass.Get(&idx))) return ade_set_error(L, "i", -1); - if(idx < 0 || idx >= Num_fireball_types) + if (!SCP_vector_inbounds(Fireball_info, idx)) return ade_set_error(L, "i", -1); if (ADE_SETTING_VAR) @@ -91,7 +91,7 @@ ADE_VIRTVAR(FPS, l_Fireballclass, NULL, "The FPS with which this fireball's anim if (!ade_get_args(L, "o", l_Fireballclass.Get(&idx))) return ade_set_error(L, "i", -1); - if (idx < 0 || idx >= Num_fireball_types) + if (!SCP_vector_inbounds(Fireball_info, idx)) return ade_set_error(L, "i", -1); if (ADE_SETTING_VAR) @@ -106,7 +106,7 @@ ADE_FUNC(isValid, l_Fireballclass, NULL, "Detects whether handle is valid", "boo if(!ade_get_args(L, "o", l_Fireballclass.Get(&idx))) return ADE_RETURN_NIL; - if(idx < 0 || idx >= Num_fireball_types) + if (!SCP_vector_inbounds(Fireball_info, idx)) return ADE_RETURN_FALSE; return ADE_RETURN_TRUE; @@ -118,7 +118,7 @@ ADE_FUNC(getTableIndex, l_Fireballclass, NULL, "Gets the index value of the fire if(!ade_get_args(L, "o", l_Fireballclass.Get(&idx))) return ade_set_args(L, "i", -1); - if(idx < 0 || idx >= Num_fireball_types) + if (!SCP_vector_inbounds(Fireball_info, idx)) return ade_set_args(L, "i", -1); return ade_set_args(L, "i", idx + 1); diff --git a/code/ship/ship.cpp b/code/ship/ship.cpp index b47ae4872d7..ed7fbd19ff0 100644 --- a/code/ship/ship.cpp +++ b/code/ship/ship.cpp @@ -3778,10 +3778,7 @@ static void parse_ship_values(ship_info* sip, const bool is_template, const bool parse_game_sound("$Shockwave Sound:", &sci->blast_sound_id); if(optional_string("$Explosion Animations:")){ - int temp[MAX_FIREBALL_TYPES]; - auto parsed_ints = stuff_int_list(temp, MAX_FIREBALL_TYPES, RAW_INTEGER_TYPE); - sip->explosion_bitmap_anims.clear(); - sip->explosion_bitmap_anims.insert(sip->explosion_bitmap_anims.begin(), temp, temp+parsed_ints); + stuff_fireball_index_list(sip->explosion_bitmap_anims, sci->name); } if (optional_string("$Weapon Model Draw Distance:")) { @@ -5810,10 +5807,7 @@ static void parse_ship_type(const char *filename, const bool replace) if(optional_string("$Explosion Animations:")) { - int temp[MAX_FIREBALL_TYPES]; - auto parsed_ints = stuff_int_list(temp, MAX_FIREBALL_TYPES, RAW_INTEGER_TYPE); - stp->explosion_bitmap_anims.clear(); - stp->explosion_bitmap_anims.insert(stp->explosion_bitmap_anims.begin(), temp, temp+parsed_ints); + stuff_fireball_index_list(stp->explosion_bitmap_anims, stp->name); } auto skip_str = "$Skip Death Roll Percent Chance:"; @@ -18144,7 +18138,8 @@ void ship_page_in() int num_ship_types_used = 0; int test_id __UNUSED = -1; - memset( fireball_used, 0, sizeof(int) * MAX_FIREBALL_TYPES ); + for (auto& fi : Fireball_info) + fi.fireball_used = false; i = 0; for (auto sip = Ship_info.begin(); sip != Ship_info.end(); i++, ++sip) { @@ -18258,15 +18253,13 @@ void ship_page_in() // Page in the shockwave stuff. -C shockwave_create_info_load(&sip->shockwave); - if(!sip->explosion_bitmap_anims.empty()) { - int num_fireballs = (int)sip->explosion_bitmap_anims.size(); - for(j = 0; j < num_fireballs; j++){ - fireball_used[sip->explosion_bitmap_anims[j]] = 1; - } - } else if(sip->class_type >= 0 && !Ship_types[sip->class_type].explosion_bitmap_anims.empty()) { - int num_fireballs = (int)Ship_types[sip->class_type].explosion_bitmap_anims.size(); - for(j = 0; j < num_fireballs; j++){ - fireball_used[Ship_types[sip->class_type].explosion_bitmap_anims[j]] = 1; + if (!sip->explosion_bitmap_anims.empty()) { + for (int explosion_bitmap_anim: sip->explosion_bitmap_anims) { + Fireball_info[explosion_bitmap_anim].fireball_used = true; + } + } else if (sip->class_type >= 0 && !Ship_types[sip->class_type].explosion_bitmap_anims.empty()) { + for (int explosion_bitmap_anim: Ship_types[sip->class_type].explosion_bitmap_anims) { + Fireball_info[explosion_bitmap_anim].fireball_used = true; } } } diff --git a/code/weapon/weapons.cpp b/code/weapon/weapons.cpp index c7512c3dfb2..d2ac7e39052 100644 --- a/code/weapon/weapons.cpp +++ b/code/weapon/weapons.cpp @@ -2634,8 +2634,8 @@ int parse_weapon(int subtype, bool replace, const char *filename) } } else { - if ((temp < 0) || (temp >= Num_fireball_types)) { - error_display(0, "Fireball index [%d] out of range (should be 0-%d) for LSSM weapon [%s].", temp, Num_fireball_types - 1, wip->name); + if (!SCP_vector_inbounds(Fireball_info, temp)) { + error_display(0, "Fireball index [%d] out of range (should be 0-%d) for LSSM weapon [%s].", temp, static_cast(Fireball_info.size()) - 1, wip->name); wip->lssm_warpeffect = FIREBALL_WARP; } else { diff --git a/fred2/sexp_tree.cpp b/fred2/sexp_tree.cpp index 216e9637859..0f67407fc1c 100644 --- a/fred2/sexp_tree.cpp +++ b/fred2/sexp_tree.cpp @@ -7656,9 +7656,9 @@ sexp_list_item *sexp_tree::get_listing_opf_fireball() { sexp_list_item head; - for (int i = 0; i < Num_fireball_types; ++i) + for (const auto &fi: Fireball_info) { - char *unique_id = Fireball_info[i].unique_id; + auto unique_id = fi.unique_id; if (strlen(unique_id) > 0) head.add_data(unique_id); diff --git a/fred2/warpparamsdlg.cpp b/fred2/warpparamsdlg.cpp index 0a853fe5eeb..b6cfb8d30c5 100644 --- a/fred2/warpparamsdlg.cpp +++ b/fred2/warpparamsdlg.cpp @@ -73,8 +73,8 @@ BOOL warp_params_dlg::OnInitDialog() ptr->ResetContent(); for (int i = 0; i < Num_warp_types; ++i) ptr->AddString(Warp_types[i]); - for (int i = 0; i < Num_fireball_types; ++i) - ptr->AddString(Fireball_info[i].unique_id); + for (const auto &fi: Fireball_info) + ptr->AddString(fi.unique_id); // find the params of the first marked ship WarpParams *params = nullptr; diff --git a/qtfred/src/ui/widgets/sexp_tree.cpp b/qtfred/src/ui/widgets/sexp_tree.cpp index dd278aef4ef..d1c6c092253 100644 --- a/qtfred/src/ui/widgets/sexp_tree.cpp +++ b/qtfred/src/ui/widgets/sexp_tree.cpp @@ -5264,9 +5264,9 @@ sexp_list_item *sexp_tree::get_listing_opf_fireball() { sexp_list_item head; - for (int i = 0; i < Num_fireball_types; ++i) + for (const auto &fi: Fireball_info) { - char *unique_id = Fireball_info[i].unique_id; + auto unique_id = fi.unique_id; if (strlen(unique_id) > 0) head.add_data(unique_id);