From ff7ab49aea1c8fe96c4ce7bbfb9cde5e5e40ccdc Mon Sep 17 00:00:00 2001 From: Mike Nelson Date: Mon, 16 Feb 2026 16:06:45 -0600 Subject: [PATCH 1/8] wing display name support --- code/mission/missionparse.cpp | 19 ++++++++++++++++++- code/missioneditor/missionsave.cpp | 9 +++++++++ code/ship/ship.cpp | 1 + code/ship/ship.h | 1 + 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/code/mission/missionparse.cpp b/code/mission/missionparse.cpp index 057a62afe4f..dd4953b6c45 100644 --- a/code/mission/missionparse.cpp +++ b/code/mission/missionparse.cpp @@ -4641,10 +4641,11 @@ int parse_wing_create_ships( wing *wingp, int num_to_create, bool force_create, // bash the ship name to be the name of the wing + some number if there is > 1 wave in this wing wingp->total_arrived_count++; + auto wing_ship_index = wingp->total_arrived_count + wingp->red_alert_skipped_ships; if (wingp->num_waves > 1) { bool needs_display_name; - wing_bash_ship_name(p_objp->name, wingp->name, wingp->total_arrived_count + wingp->red_alert_skipped_ships, &needs_display_name); + wing_bash_ship_name(p_objp->name, wingp->name, wing_ship_index, &needs_display_name); // set up display name if we need to // (In the unlikely edge case where the ship already has a display name for some reason, it will be overwritten. @@ -4668,6 +4669,18 @@ int parse_wing_create_ships( wing *wingp, int num_to_create, bool force_create, } } + if (!wingp->display_name.empty()) + { + char ship_display_name[NAME_LENGTH]; + bool wing_display_name_has_hash; + wing_bash_ship_name(ship_display_name, wingp->display_name.c_str(), wing_ship_index, &wing_display_name_has_hash); + + p_objp->display_name = ship_display_name; + if (wing_display_name_has_hash) + end_string_at_first_hash_symbol(p_objp->display_name); + p_objp->flags.set(Mission::Parse_Object_Flags::SF_Has_display_name); + } + // also, if multiplayer, set the parse object's net signature to be wing's net signature // base + total_arrived_count (before adding 1) // Cyborg -- The original ships in the wave have their net_signature set at mission parse @@ -4838,6 +4851,10 @@ void parse_wing(mission *pm) error_display(0, NOX("Redundant wing name: %s\n"), wingp->name); wingnum = Num_wings; + if (optional_string("+Display Name:")) { + stuff_string(wingp->display_name, F_NAME); + } + // squad logo - Goober5000 if (optional_string("+Squad Logo:")) { diff --git a/code/missioneditor/missionsave.cpp b/code/missioneditor/missionsave.cpp index e46fb6b590c..139e21fbdc8 100644 --- a/code/missioneditor/missionsave.cpp +++ b/code/missioneditor/missionsave.cpp @@ -4955,6 +4955,15 @@ int Fred_mission_save::save_wings() parse_comments(count ? 2 : 1); fout(" %s", w.name); + if (!w.display_name.empty()) { + if (optional_string_fred("+Display Name:", "$Name:")) + parse_comments(); + else + fout("\n+Display Name:"); + + fout_ext(" ", "%s", w.display_name.c_str()); + } + count++; // squad logo - Goober5000 diff --git a/code/ship/ship.cpp b/code/ship/ship.cpp index 32454b762b0..060f1b3e591 100644 --- a/code/ship/ship.cpp +++ b/code/ship/ship.cpp @@ -7547,6 +7547,7 @@ ship_weapon::ship_weapon() { void wing::clear() { name[0] = '\0'; + display_name.clear(); wing_squad_filename[0] = '\0'; reinforcement_index = -1; hotkey = -1; diff --git a/code/ship/ship.h b/code/ship/ship.h index fc25427a6bc..0f30d1da8c8 100644 --- a/code/ship/ship.h +++ b/code/ship/ship.h @@ -1571,6 +1571,7 @@ extern SCP_vector Engine_wash_info; // Defines a wing of ships. typedef struct wing { char name[NAME_LENGTH]; + SCP_string display_name; char wing_squad_filename[MAX_FILENAME_LEN]; // Goober5000 int reinforcement_index; // index in reinforcement struct or -1 int hotkey; From 118ef81310b3b39be630316a6b7da4eb27e109ca Mon Sep 17 00:00:00 2001 From: Mike Nelson Date: Mon, 16 Feb 2026 16:29:12 -0600 Subject: [PATCH 2/8] clarify priority --- code/mission/missionparse.cpp | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/code/mission/missionparse.cpp b/code/mission/missionparse.cpp index dd4953b6c45..bc76291acac 100644 --- a/code/mission/missionparse.cpp +++ b/code/mission/missionparse.cpp @@ -4642,24 +4642,33 @@ int parse_wing_create_ships( wing *wingp, int num_to_create, bool force_create, // bash the ship name to be the name of the wing + some number if there is > 1 wave in this wing wingp->total_arrived_count++; auto wing_ship_index = wingp->total_arrived_count + wingp->red_alert_skipped_ships; - if (wingp->num_waves > 1) + + if (!wingp->display_name.empty()) { + char ship_display_name[NAME_LENGTH]; + bool wing_display_name_has_hash; + wing_bash_ship_name(ship_display_name, wingp->display_name.c_str(), wing_ship_index, &wing_display_name_has_hash); + + p_objp->display_name = ship_display_name; + if (wing_display_name_has_hash) + end_string_at_first_hash_symbol(p_objp->display_name); + p_objp->flags.set(Mission::Parse_Object_Flags::SF_Has_display_name); + } else if (wingp->num_waves > 1) { bool needs_display_name; wing_bash_ship_name(p_objp->name, wingp->name, wing_ship_index, &needs_display_name); // set up display name if we need to - // (In the unlikely edge case where the ship already has a display name for some reason, it will be overwritten. - // This is unavoidable, because if we didn't overwrite display names, all waves would have the display name from the first wave.) - if (needs_display_name) - { + // (In the unlikely edge case where the ship already has a display name for some reason, it will be + // overwritten. This is unavoidable, because if we didn't overwrite display names, all waves would have the + // display name from the first wave.) + if (needs_display_name) { p_objp->display_name = p_objp->name; end_string_at_first_hash_symbol(p_objp->display_name); p_objp->flags.set(Mission::Parse_Object_Flags::SF_Has_display_name); } // subsequent waves of ships will not be in the ship registry, so add them - if (!ship_registry_exists(p_objp->name)) - { + if (!ship_registry_exists(p_objp->name)) { ship_registry_entry entry(p_objp->name); entry.status = ShipStatus::NOT_YET_PRESENT; entry.pobj_num = POBJ_INDEX(p_objp); @@ -4669,18 +4678,6 @@ int parse_wing_create_ships( wing *wingp, int num_to_create, bool force_create, } } - if (!wingp->display_name.empty()) - { - char ship_display_name[NAME_LENGTH]; - bool wing_display_name_has_hash; - wing_bash_ship_name(ship_display_name, wingp->display_name.c_str(), wing_ship_index, &wing_display_name_has_hash); - - p_objp->display_name = ship_display_name; - if (wing_display_name_has_hash) - end_string_at_first_hash_symbol(p_objp->display_name); - p_objp->flags.set(Mission::Parse_Object_Flags::SF_Has_display_name); - } - // also, if multiplayer, set the parse object's net signature to be wing's net signature // base + total_arrived_count (before adding 1) // Cyborg -- The original ships in the wave have their net_signature set at mission parse From b309271fb42d9b961cd885ad1ca4dab3bfe7f0b9 Mon Sep 17 00:00:00 2001 From: Mike Nelson Date: Mon, 16 Feb 2026 16:52:13 -0600 Subject: [PATCH 3/8] This is better --- code/mission/missionparse.cpp | 36 +++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/code/mission/missionparse.cpp b/code/mission/missionparse.cpp index bc76291acac..3e460083419 100644 --- a/code/mission/missionparse.cpp +++ b/code/mission/missionparse.cpp @@ -4642,33 +4642,24 @@ int parse_wing_create_ships( wing *wingp, int num_to_create, bool force_create, // bash the ship name to be the name of the wing + some number if there is > 1 wave in this wing wingp->total_arrived_count++; auto wing_ship_index = wingp->total_arrived_count + wingp->red_alert_skipped_ships; - - if (!wingp->display_name.empty()) + if (wingp->num_waves > 1) { - char ship_display_name[NAME_LENGTH]; - bool wing_display_name_has_hash; - wing_bash_ship_name(ship_display_name, wingp->display_name.c_str(), wing_ship_index, &wing_display_name_has_hash); - - p_objp->display_name = ship_display_name; - if (wing_display_name_has_hash) - end_string_at_first_hash_symbol(p_objp->display_name); - p_objp->flags.set(Mission::Parse_Object_Flags::SF_Has_display_name); - } else if (wingp->num_waves > 1) { bool needs_display_name; wing_bash_ship_name(p_objp->name, wingp->name, wing_ship_index, &needs_display_name); // set up display name if we need to - // (In the unlikely edge case where the ship already has a display name for some reason, it will be - // overwritten. This is unavoidable, because if we didn't overwrite display names, all waves would have the - // display name from the first wave.) - if (needs_display_name) { + // (In the unlikely edge case where the ship already has a display name for some reason, it will be overwritten. + // This is unavoidable, because if we didn't overwrite display names, all waves would have the display name from the first wave.) + if (needs_display_name) + { p_objp->display_name = p_objp->name; end_string_at_first_hash_symbol(p_objp->display_name); p_objp->flags.set(Mission::Parse_Object_Flags::SF_Has_display_name); } // subsequent waves of ships will not be in the ship registry, so add them - if (!ship_registry_exists(p_objp->name)) { + if (!ship_registry_exists(p_objp->name)) + { ship_registry_entry entry(p_objp->name); entry.status = ShipStatus::NOT_YET_PRESENT; entry.pobj_num = POBJ_INDEX(p_objp); @@ -4678,6 +4669,19 @@ int parse_wing_create_ships( wing *wingp, int num_to_create, bool force_create, } } + // Wing display names take priority over all display names because they are newer and cooler + if (!wingp->display_name.empty()) + { + char ship_display_name[NAME_LENGTH]; + bool wing_display_name_has_hash; + wing_bash_ship_name(ship_display_name, wingp->display_name.c_str(), wing_ship_index, &wing_display_name_has_hash); + + p_objp->display_name = ship_display_name; + if (wing_display_name_has_hash) + end_string_at_first_hash_symbol(p_objp->display_name); + p_objp->flags.set(Mission::Parse_Object_Flags::SF_Has_display_name); + } + // also, if multiplayer, set the parse object's net signature to be wing's net signature // base + total_arrived_count (before adding 1) // Cyborg -- The original ships in the wave have their net_signature set at mission parse From 6236d3b3ab74c6e180704454fef68b065090ffb3 Mon Sep 17 00:00:00 2001 From: Mike Nelson Date: Mon, 16 Feb 2026 19:01:15 -0600 Subject: [PATCH 4/8] qtfred support --- .../mission/dialogs/WingEditorDialogModel.cpp | 18 +++++++++++ .../mission/dialogs/WingEditorDialogModel.h | 2 ++ qtfred/src/ui/dialogs/WingEditorDialog.cpp | 1 + qtfred/ui/WingEditorDialog.ui | 31 ++++++++++++++----- 4 files changed, 45 insertions(+), 7 deletions(-) diff --git a/qtfred/src/mission/dialogs/WingEditorDialogModel.cpp b/qtfred/src/mission/dialogs/WingEditorDialogModel.cpp index 459c9d46134..5558ed627b6 100644 --- a/qtfred/src/mission/dialogs/WingEditorDialogModel.cpp +++ b/qtfred/src/mission/dialogs/WingEditorDialogModel.cpp @@ -425,6 +425,24 @@ void WingEditorDialogModel::setWingName(const SCP_string& name) } } +SCP_string WingEditorDialogModel::getWingDisplayName() const +{ + if (!wingIsValid()) + return ""; + + const auto w = getCurrentWing(); + return w->display_name; +} + +void WingEditorDialogModel::setWingDisplayName(const SCP_string& name) +{ + if (!wingIsValid()) + return; + + auto* w = getCurrentWing(); + modify(w->display_name, name); +} + int WingEditorDialogModel::getWingLeaderIndex() const { if (!wingIsValid()) diff --git a/qtfred/src/mission/dialogs/WingEditorDialogModel.h b/qtfred/src/mission/dialogs/WingEditorDialogModel.h index b25195be769..a45767229ff 100644 --- a/qtfred/src/mission/dialogs/WingEditorDialogModel.h +++ b/qtfred/src/mission/dialogs/WingEditorDialogModel.h @@ -58,6 +58,8 @@ class WingEditorDialogModel : public AbstractDialogModel { // Top section, first column SCP_string getWingName() const; void setWingName(const SCP_string& name); + SCP_string getWingDisplayName() const; + void setWingDisplayName(const SCP_string& name); int getWingLeaderIndex() const; void setWingLeaderIndex(int newLeaderIndex); int getNumberOfWaves() const; diff --git a/qtfred/src/ui/dialogs/WingEditorDialog.cpp b/qtfred/src/ui/dialogs/WingEditorDialog.cpp index 060bd86def1..91b8de5da82 100644 --- a/qtfred/src/ui/dialogs/WingEditorDialog.cpp +++ b/qtfred/src/ui/dialogs/WingEditorDialog.cpp @@ -58,6 +58,7 @@ void WingEditorDialog::updateUi() // Top section, first column ui->wingNameEdit->setText(_model->getWingName().c_str()); + ui->wingDisplayNameEdit->setText(_model->getWingDisplayName().c_str()); ui->wingLeaderCombo->setCurrentIndex(_model->getWingLeaderIndex()); ui->numWavesSpinBox->setValue(_model->getNumberOfWaves()); ui->waveThresholdSpinBox->setValue(_model->getWaveThreshold()); diff --git a/qtfred/ui/WingEditorDialog.ui b/qtfred/ui/WingEditorDialog.ui index a73c7f3ae9e..f61b479f585 100644 --- a/qtfred/ui/WingEditorDialog.ui +++ b/qtfred/ui/WingEditorDialog.ui @@ -43,7 +43,7 @@ - + Hotkey @@ -53,7 +53,7 @@ - + # of Waves @@ -70,7 +70,7 @@ - + Wave Threshold @@ -80,7 +80,7 @@ - + 1 @@ -90,10 +90,10 @@ - + - + @@ -107,6 +107,23 @@ + + + Display Name + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Optional display name for ships in this wing. + + + + Wing Leader @@ -116,7 +133,7 @@ - + true From ef5c00d2cd0b678829f56f2527b7f768de371987 Mon Sep 17 00:00:00 2001 From: Mike Nelson Date: Mon, 16 Feb 2026 19:11:28 -0600 Subject: [PATCH 5/8] old fred support --- fred2/fred.rc | 26 ++++++++++++++------------ fred2/resource.h | 3 ++- fred2/wing_editor.cpp | 13 +++++++++++-- fred2/wing_editor.h | 1 + 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/fred2/fred.rc b/fred2/fred.rc index bbfefe7442b..f57659dee75 100644 --- a/fred2/fred.rc +++ b/fred2/fred.rc @@ -1241,14 +1241,15 @@ BEGIN PUSHBUTTON "Prev",IDC_PREV,240,7,24,14,0,WS_EX_STATICEDGE PUSHBUTTON "Next",IDC_NEXT,267,7,24,14,0,WS_EX_STATICEDGE EDITTEXT IDC_WING_NAME,65,7,73,14,ES_AUTOHSCROLL - COMBOBOX IDC_WING_SPECIAL_SHIP,65,23,73,161,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - EDITTEXT IDC_WING_WAVES,65,37,61,14,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "Spin2",IDC_SPIN_WAVES,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,127,37,11,15 - EDITTEXT IDC_WING_WAVE_THRESHOLD,65,53,61,15,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "Spin2",IDC_SPIN_WAVE_THRESHOLD,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,127,53,11,15 - COMBOBOX IDC_HOTKEY,65,70,73,115,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - PUSHBUTTON "Squad Logo",IDC_WING_SQUAD_LOGO_BUTTON,7,89,55,14 - EDITTEXT IDC_WING_SQUAD_LOGO,65,90,80,14,ES_AUTOHSCROLL | ES_READONLY + EDITTEXT IDC_WING_DISPLAY_NAME,65,22,73,14,ES_AUTOHSCROLL + COMBOBOX IDC_WING_SPECIAL_SHIP,65,38,73,161,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + EDITTEXT IDC_WING_WAVES,65,52,61,14,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "Spin2",IDC_SPIN_WAVES,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,127,52,11,15 + EDITTEXT IDC_WING_WAVE_THRESHOLD,65,68,61,15,ES_AUTOHSCROLL | ES_NUMBER + CONTROL "Spin2",IDC_SPIN_WAVE_THRESHOLD,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,127,68,11,15 + COMBOBOX IDC_HOTKEY,65,84,73,115,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + PUSHBUTTON "Squad Logo",IDC_WING_SQUAD_LOGO_BUTTON,7,98,55,14 + EDITTEXT IDC_WING_SQUAD_LOGO,65,99,80,14,ES_AUTOHSCROLL | ES_READONLY CONTROL "Reinforcement Unit",IDC_REINFORCEMENT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,143,10,77,10 CONTROL "Ignore for Counting Goals",IDC_IGNORE_COUNT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,143,21,96,10 CONTROL "No Arrival Music",IDC_NO_ARRIVAL_MUSIC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,143,32,67,10 @@ -1282,9 +1283,10 @@ BEGIN CONTROL "Hide Cues",IDC_HIDE_CUES,"Button",BS_AUTOCHECKBOX | BS_PUSHLIKE | WS_TABSTOP,241,71,49,12 GROUPBOX "Departure",IDC_STATIC,153,110,138,270 RTEXT "Wing Name",IDC_STATIC,19,10,42,8 - RTEXT "Wave Threshold",IDC_STATIC,7,56,54,8 - RTEXT "# of Waves",IDC_STATIC,16,40,45,8 - RTEXT "Leader",IDC_STATIC,38,25,23,8,NOT WS_GROUP + RTEXT "Display Name",IDC_STATIC,10,25,51,8 + RTEXT "Wave Threshold",IDC_STATIC,7,71,54,8 + RTEXT "# of Waves",IDC_STATIC,16,55,45,8 + RTEXT "Leader",IDC_STATIC,38,40,23,8,NOT WS_GROUP LTEXT "Location",IDC_STATIC,15,124,28,8 LTEXT "Cue:",IDC_STATIC,15,259,16,8 GROUPBOX "Arrival",IDC_CUE_FRAME,7,110,138,270 @@ -1293,7 +1295,7 @@ BEGIN LTEXT "Delay",IDC_STATIC,160,140,19,8 LTEXT "Delay",IDC_STATIC,15,140,19,8 LTEXT "Seconds",IDC_STATIC,102,141,45,8 - RTEXT "Hotkey",IDC_STATIC,37,72,24,8 + RTEXT "Hotkey",IDC_STATIC,37,86,24,8 GROUPBOX "Delay Between Waves",IDC_STATIC,15,154,119,30 LTEXT "Min",IDC_STATIC,21,167,12,8 LTEXT "Max",IDC_STATIC,80,167,14,8 diff --git a/fred2/resource.h b/fred2/resource.h index 0ba948f0bd9..998e7a7511d 100644 --- a/fred2/resource.h +++ b/fred2/resource.h @@ -1271,6 +1271,7 @@ #define IDC_PROP_PREV 1710 #define IDC_PROP_NEXT 1711 #define IDC_PROP_FLAGS 1712 +#define IDC_WING_DISPLAY_NAME 1713 #define IDC_SEXP_POPUP_LIST 32770 #define ID_FILE_MISSIONNOTES 32771 #define ID_DUPLICATE 32774 @@ -1581,7 +1582,7 @@ #define _APS_3D_CONTROLS 1 #define _APS_NEXT_RESOURCE_VALUE 335 #define _APS_NEXT_COMMAND_VALUE 33104 -#define _APS_NEXT_CONTROL_VALUE 1705 +#define _APS_NEXT_CONTROL_VALUE 1714 #define _APS_NEXT_SYMED_VALUE 105 #endif #endif diff --git a/fred2/wing_editor.cpp b/fred2/wing_editor.cpp index e9df5847710..e0f06231403 100644 --- a/fred2/wing_editor.cpp +++ b/fred2/wing_editor.cpp @@ -45,6 +45,7 @@ wing_editor::wing_editor(CWnd* pParent /*=NULL*/) { //{{AFX_DATA_INIT(wing_editor) m_wing_name = _T(""); + m_wing_display_name = _T(""); m_wing_squad_filename = _T(""); m_special_ship = -1; m_waves = 0; @@ -90,6 +91,7 @@ void wing_editor::DoDataExchange(CDataExchange* pDX) DDX_Control(pDX, IDC_SPIN_WAVE_THRESHOLD, m_threshold_spin); DDX_Control(pDX, IDC_SPIN_WAVES, m_waves_spin); DDX_Text(pDX, IDC_WING_NAME, m_wing_name); + DDX_Text(pDX, IDC_WING_DISPLAY_NAME, m_wing_display_name); DDX_Text(pDX, IDC_WING_SQUAD_LOGO, m_wing_squad_filename); DDX_CBIndex(pDX, IDC_WING_SPECIAL_SHIP, m_special_ship); DDX_CBIndex(pDX, IDC_WING_FORMATION, m_formation); @@ -286,6 +288,7 @@ void wing_editor::initialize_data_safe(int full_update) m_ignore_count = 0; if (cur_wing < 0) { + m_wing_display_name = _T(""); m_wing_squad_filename = _T(""); m_special_ship = -1; m_formation = 0; @@ -348,6 +351,7 @@ void wing_editor::initialize_data_safe(int full_update) if (Ships[Player_start_shipnum].wingnum == cur_wing) player_wing = 1; + m_wing_display_name = _T(Wings[cur_wing].display_name.c_str()); m_wing_squad_filename = _T(Wings[cur_wing].wing_squad_filename); m_special_ship = Wings[cur_wing].special_ship; m_waves = Wings[cur_wing].num_waves; @@ -451,6 +455,7 @@ void wing_editor::initialize_data_safe(int full_update) UpdateData(FALSE); GetDlgItem(IDC_WING_NAME)->EnableWindow(enable); + GetDlgItem(IDC_WING_DISPLAY_NAME)->EnableWindow(enable); GetDlgItem(IDC_WING_SQUAD_LOGO_BUTTON)->EnableWindow(enable); GetDlgItem(IDC_WING_SPECIAL_SHIP)->EnableWindow(enable); GetDlgItem(IDC_WING_WAVES)->EnableWindow(player_enabled); @@ -544,10 +549,13 @@ void wing_editor::initialize_data(int full_update) m_arrival_tree.select_sexp_node = m_departure_tree.select_sexp_node = select_sexp_node; select_sexp_node = -1; - if (cur_wing == -1) + if (cur_wing == -1) { m_wing_name = _T(""); - else + m_wing_display_name = _T(""); + } else { m_wing_name = _T(Wings[cur_wing].name); + m_wing_display_name = _T(Wings[cur_wing].display_name.c_str()); + } initialize_data_safe(full_update); modified = 0; @@ -800,6 +808,7 @@ void wing_editor::update_data_safe() MODIFY(Wings[cur_wing].threshold, m_threshold); MODIFY(Wings[cur_wing].formation, m_formation - 1); MODIFY(Wings[cur_wing].formation_scale, (float)atof(m_formation_scale)); + MODIFY(Wings[cur_wing].display_name, (LPCSTR)m_wing_display_name); MODIFY(Wings[cur_wing].arrival_location, static_cast(m_arrival_location)); MODIFY(Wings[cur_wing].departure_location, static_cast(m_departure_location)); diff --git a/fred2/wing_editor.h b/fred2/wing_editor.h index 71a231abdc2..f7bab81b055 100644 --- a/fred2/wing_editor.h +++ b/fred2/wing_editor.h @@ -47,6 +47,7 @@ class wing_editor : public CDialog CSpinButtonCtrl m_threshold_spin; CSpinButtonCtrl m_waves_spin; CString m_wing_name; + CString m_wing_display_name; int m_special_ship; int m_waves; int m_threshold; From 30f23cc0fc6793b15cb8d50dad5aa27e0253c1a5 Mon Sep 17 00:00:00 2001 From: Mike Nelson Date: Tue, 3 Mar 2026 06:58:00 -0600 Subject: [PATCH 6/8] versioning --- code/mission/missionparse.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code/mission/missionparse.cpp b/code/mission/missionparse.cpp index 3e460083419..300113f7916 100644 --- a/code/mission/missionparse.cpp +++ b/code/mission/missionparse.cpp @@ -9578,6 +9578,12 @@ bool check_for_25_1_data() if (count_items_with_value(Props) > 0) return true; + for (int i = 0; i < Num_wings; i++) { + if (!Wings[i].display_name.empty()) { + return true; + } + } + constexpr auto defaultLayer = "Default"; for (const auto& so : list_range(&Ship_obj_list)) From e713a1a46e2875274da5e324dede1182d0f9d771 Mon Sep 17 00:00:00 2001 From: Mike Nelson Date: Wed, 8 Apr 2026 11:49:33 -0500 Subject: [PATCH 7/8] editor name length limit --- fred2/wing_editor.cpp | 2 ++ qtfred/src/ui/dialogs/WingEditorDialog.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/fred2/wing_editor.cpp b/fred2/wing_editor.cpp index e0f06231403..6bff0092390 100644 --- a/fred2/wing_editor.cpp +++ b/fred2/wing_editor.cpp @@ -223,6 +223,8 @@ BOOL wing_editor::Create() m_arrival_delay_spin.SetRange(0, 999); m_departure_delay_spin.SetRange(0, 999); + ((CEdit *)GetDlgItem(IDC_WING_DISPLAY_NAME))->SetLimitText(NAME_LENGTH - 1); + initialize_data(1); return r; } diff --git a/qtfred/src/ui/dialogs/WingEditorDialog.cpp b/qtfred/src/ui/dialogs/WingEditorDialog.cpp index 91b8de5da82..8ec1b80e496 100644 --- a/qtfred/src/ui/dialogs/WingEditorDialog.cpp +++ b/qtfred/src/ui/dialogs/WingEditorDialog.cpp @@ -25,6 +25,8 @@ WingEditorDialog::WingEditorDialog(FredView* parent, EditorViewport* viewport) ui->wingNameEdit->setMaxLength(NAME_LENGTH - 1); + ui->wingDisplayNameEdit->setMaxLength(NAME_LENGTH - 1); + setWindowTitle(tr("Wing Editor")); // Whenever the model reports changes, refresh the UI From e4c1e918549778e775e04dfb2c863a34f426559c Mon Sep 17 00:00:00 2001 From: Mike Nelson Date: Mon, 4 May 2026 08:48:28 -0500 Subject: [PATCH 8/8] qtfred help doc update --- qtfred/help-src/doc/dialogs/WingEditorDialog.html | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/qtfred/help-src/doc/dialogs/WingEditorDialog.html b/qtfred/help-src/doc/dialogs/WingEditorDialog.html index 29108ca0336..56ff20ad73c 100644 --- a/qtfred/help-src/doc/dialogs/WingEditorDialog.html +++ b/qtfred/help-src/doc/dialogs/WingEditorDialog.html @@ -18,6 +18,10 @@

General fields

FieldDescription NameWing name shown on the HUD and used in SEXPs (e.g. Alpha, Gamma). + Display NameOptional name shown to the player in place of the + internal name. Useful for localisation — the display name can be translated + while the internal name stays stable for SEXPs and scripting. Leave blank to + use the internal name. Wing leaderWhich ship in the wing acts as leader. Other members form up on the leader. Number of wavesHow many waves of this wing will arrive over the