diff --git a/code/mission/missionparse.cpp b/code/mission/missionparse.cpp index 7461bb211d2..8cbe4730cc5 100644 --- a/code/mission/missionparse.cpp +++ b/code/mission/missionparse.cpp @@ -4595,10 +4595,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. @@ -4622,6 +4623,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 @@ -4792,6 +4806,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 33a5b29152b..6ec0ec3aef4 100644 --- a/code/missioneditor/missionsave.cpp +++ b/code/missioneditor/missionsave.cpp @@ -4867,6 +4867,15 @@ int Fred_mission_save::save_wings() parse_comments(2); 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()); + } + // squad logo - Goober5000 if (save_config.save_format != MissionFormat::RETAIL) { if (strlen(w.wing_squad_filename) > 0) //-V805 diff --git a/code/ship/ship.cpp b/code/ship/ship.cpp index fbea96329c3..05c698a1a21 100644 --- a/code/ship/ship.cpp +++ b/code/ship/ship.cpp @@ -7495,6 +7495,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 65aa7f9b665..3a13bdcc8cc 100644 --- a/code/ship/ship.h +++ b/code/ship/ship.h @@ -1566,6 +1566,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; diff --git a/fred2/fred.rc b/fred2/fred.rc index 676ea0c46db..d0a27b2ca03 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 d172fe29a69..4f7b10258cd 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; diff --git a/qtfred/src/mission/dialogs/WingEditorDialogModel.cpp b/qtfred/src/mission/dialogs/WingEditorDialogModel.cpp index 475e5f8574c..ebef417c8a0 100644 --- a/qtfred/src/mission/dialogs/WingEditorDialogModel.cpp +++ b/qtfred/src/mission/dialogs/WingEditorDialogModel.cpp @@ -420,6 +420,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 7360df82d40..d5723f01557 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 efbd704f37b..59836046113 100644 --- a/qtfred/src/ui/dialogs/WingEditorDialog.cpp +++ b/qtfred/src/ui/dialogs/WingEditorDialog.cpp @@ -45,6 +45,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 74ef6d39890..ebea3e881cf 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