@@ -98,6 +98,20 @@ anchor_t target_to_anchor(int target)
9898 return anchor_t (target);
9999}
100100
101+ void update_custom_wing_indexes ()
102+ {
103+ int i;
104+
105+ for (i = 0 ; i < MAX_STARTING_WINGS ; i++)
106+ Starting_wings[i] = wing_name_lookup (Starting_wing_names[i], 1 );
107+
108+ for (i = 0 ; i < MAX_SQUADRON_WINGS ; i++)
109+ Squadron_wings[i] = wing_name_lookup (Squadron_wing_names[i], 1 );
110+
111+ for (i = 0 ; i < MAX_TVT_WINGS ; i++)
112+ TVT_wings[i] = wing_name_lookup (TVT_wing_names[i], 1 );
113+ }
114+
101115void generate_weaponry_usage_list_team (int team, int * arr)
102116{
103117 int i;
@@ -214,14 +228,14 @@ void reassign_ship_slot(int from, int to, const FredShipSlotConfig& cfg)
214228 // Wing membership: scan every wing and re-point any reference to the old slot.
215229 // (wing.special_ship is wing-relative, NOT a Ships[] index, so it is intentionally
216230 // not touched here.)
217- for (int w = 0 ; w < MAX_WINGS ; ++w )
231+ for (auto & w : Wings )
218232 {
219- if (Wings[w] .wave_count == 0 )
233+ if (w .wave_count == 0 )
220234 continue ;
221- for (int k = 0 ; k < Wings[w] .wave_count ; ++k)
235+ for (int k = 0 ; k < w .wave_count ; ++k)
222236 {
223- if (Wings[w] .ship_index [k] == from)
224- Wings[w] .ship_index [k] = to;
237+ if (w .ship_index [k] == from)
238+ w .ship_index [k] = to;
225239 }
226240 }
227241
@@ -268,6 +282,74 @@ void swap_ship_slots(int a, int b, const FredShipSlotConfig& cfg)
268282 reassign_ship_slot (tmp, b, cfg);
269283}
270284
285+ void reassign_wing_slot (int from, int to, const FredWingSlotConfig& cfg)
286+ {
287+ Assertion (from != to, " reassign_wing_slot: from == to (%d)" , from);
288+ Assertion (from >= 0 && from < MAX_WINGS , " reassign_wing_slot: 'from' slot %d out of range" , from);
289+ Assertion (to >= 0 && to < MAX_WINGS , " reassign_wing_slot: 'to' slot %d out of range" , to);
290+ Assertion (Wings[from].wave_count > 0 , " reassign_wing_slot: source slot %d is empty" , from);
291+ Assertion (Wings[to].wave_count == 0 , " reassign_wing_slot: destination slot %d is occupied" , to);
292+
293+ // Move the wing struct itself. wing::clear() is the engine's canonical
294+ // empty-slot state (matches ship_level_init); wave_count == 0 is the sentinel.
295+ Wings[to] = Wings[from];
296+ Wings[from].clear ();
297+
298+ // Move FRED-side parallel array if the caller supplied it.
299+ if (cfg.wing_objects != nullptr )
300+ {
301+ for (int k = 0 ; k < MAX_SHIPS_PER_WING ; ++k)
302+ {
303+ cfg.wing_objects [to][k] = cfg.wing_objects [from][k];
304+ cfg.wing_objects [from][k] = -1 ;
305+ }
306+ }
307+
308+ // Per-ship parent-wing back-reference.
309+ for (auto & sh : Ships)
310+ {
311+ if (sh.objnum < 0 )
312+ continue ;
313+ if (sh.wingnum == from)
314+ sh.wingnum = to;
315+ }
316+
317+ // FRED's current-wing pointer, if the caller is tracking one.
318+ if (cfg.cur_wing != nullptr && *cfg.cur_wing == from)
319+ *cfg.cur_wing = to;
320+
321+ // Rebuild Starting/Squadron/TVT_wings caches from the parallel name arrays.
322+ update_custom_wing_indexes ();
323+ }
324+
325+ void swap_wing_slots (int a, int b, const FredWingSlotConfig& cfg)
326+ {
327+ if (a == b)
328+ return ;
329+
330+ Assertion (a >= 0 && a < MAX_WINGS , " swap_wing_slots: slot 'a' %d out of range" , a);
331+ Assertion (b >= 0 && b < MAX_WINGS , " swap_wing_slots: slot 'b' %d out of range" , b);
332+ Assertion (Wings[a].wave_count > 0 && Wings[b].wave_count > 0 ,
333+ " swap_wing_slots: both slots must be valid (a=%d, b=%d)" , a, b);
334+
335+ // Find a free temporary slot.
336+ int tmp = -1 ;
337+ for (int i = 0 ; i < MAX_WINGS ; ++i)
338+ {
339+ if (Wings[i].wave_count == 0 )
340+ {
341+ tmp = i;
342+ break ;
343+ }
344+ }
345+ Assertion (tmp >= 0 , " swap_wing_slots: no free Wings[] slot available for the temporary leg" );
346+
347+ // Three-leg swap; each call's preconditions hold by construction.
348+ reassign_wing_slot (a, tmp, cfg);
349+ reassign_wing_slot (b, a, cfg);
350+ reassign_wing_slot (tmp, b, cfg);
351+ }
352+
271353// Bulk-re-sort one type's subset of obj_used_list while keeping non-matching
272354// entries in their original relative positions. Each callsite supplies a
273355// type matcher and a key function; the i-th matching slot (in original list
0 commit comments