]> icculus.org git repositories - taylor/freespace2.git/blob - src/fred2/missionnotesdlg.cpp
The Great Newline Fix
[taylor/freespace2.git] / src / fred2 / missionnotesdlg.cpp
1 /*
2  * $Logfile: /Freespace2/code/Fred2/MissionNotesDlg.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * Mission notes editor dialog box handling code
8  *
9  * $Log$
10  * Revision 1.2  2002/05/07 03:16:44  theoddone33
11  * The Great Newline Fix
12  *
13  * Revision 1.1.1.1  2002/05/03 03:28:08  root
14  * Initial import.
15  *
16  * 
17  * 6     8/23/99 6:21p Jefff
18  * added "no traitor" option to missions (and fred)
19  * 
20  * 5     8/23/99 5:04p Jefff
21  * Added new mission flag to disable built-in messages from playing.
22  * Added fred support as well.
23  * 
24  * 4     3/24/99 4:05p Dave
25  * Put in support for assigning the player to a specific squadron with a
26  * specific logo. Preliminary work for doing pos/orient checksumming in
27  * multiplayer to reduce bandwidth.
28  * 
29  * 3     2/23/99 2:32p Dave
30  * First run of oldschool dogfight mode.
31  * 
32  * 2     10/07/98 6:28p Dave
33  * Initial checkin. Renamed all relevant stuff to be Fred2 instead of
34  * Fred. Globalized mission and campaign file extensions. Removed Silent
35  * Threat specific code.
36  * 
37  * 1     10/07/98 3:01p Dave
38  * 
39  * 1     10/07/98 3:00p Dave
40  * 
41  * 23    6/17/98 2:47p Hoffoss
42  * Changed so missions are single, multi or training.  Not supporting
43  * combos of the above anymore (in Fred).
44  * 
45  * 22    5/25/98 12:16p Hoffoss
46  * Removed dogfight option from dialog.  No longer supported.
47  * 
48  * 21    5/18/98 1:56a Allender
49  * respawn limit to 999 max
50  * 
51  * 20    5/05/98 11:05p Allender
52  * ability to flag mission as "no promotion" where promotions and badges
53  * are *not* granted even if they should be.  Slight fix to multiplayer
54  * problem where locking_subsys is wrong for players current target
55  * 
56  * 19    4/03/98 12:17a Allender
57  * new sexpression to detect departed or destroyed.  optionally disallow
58  * support ships.  Allow docking with escape pods 
59  * 
60  * 18    3/26/98 5:24p Allender
61  * put in respawn edit box into mission notes dialog.  Made loading of
62  * missions/campaign happen when first entering the game setup screen.
63  * 
64  * 17    3/18/98 3:17p Allender
65  * fix scramble checkbox
66  * 
67  * 16    3/18/98 10:27a Allender
68  * fixed bug with missions always being tagged a single player regardless
69  * of checkbox setting
70  * 
71  * 15    3/16/98 8:27p Allender
72  * Fred support for two new AI flags -- kamikaze and no dynamic goals.
73  * 
74  * 14    3/09/98 4:30p Allender
75  * multiplayer secondary weapon changes.  red-alert and cargo-known-delay
76  * sexpressions.  Add time cargo revealed to ship structure
77  * 
78  * 13    2/09/98 9:25p Allender
79  * team v team support.  multiple pools and breifings
80  * 
81  * 12    2/04/98 4:32p Allender
82  * support for multiple briefings and debriefings.  Changes to mission
83  * type (now a bitfield).  Bitfield defs for multiplayer modes
84  * 
85  * 11    1/02/98 4:55p Hoffoss
86  * Added support for Mission_all_attack flag to Fred and loading/saving
87  * code.
88  * 
89  * 10    9/30/97 5:56p Hoffoss
90  * Added music selection combo boxes to Fred.
91  * 
92  * 9     8/11/97 3:19p Hoffoss
93  * Implemented mission description.
94  * 
95  * 8     6/11/97 2:14p Hoffoss
96  * Added game type (mission type) selection to Fred.
97  * 
98  * 7     5/20/97 2:28p Hoffoss
99  * Added message box queries for close window operation on all modal
100  * dialog boxes.
101  * 
102  * 6     5/06/97 2:43p Hoffoss
103  * Fixed bug in Mission notes dialog, where window wasn't being destroyed.
104  * 
105  * 5     4/17/97 2:01p Hoffoss
106  * All dialog box window states are saved between sessions now.
107  * 
108  * 4     2/21/97 5:34p Hoffoss
109  * Added extensive modification detection and fixed a bug in initial
110  * orders editor.
111  * 
112  * 3     2/17/97 5:28p Hoffoss
113  * Checked RCS headers, added them were missing, changing description to
114  * something better, etc where needed.
115  *
116  * $NoKeywords: $
117  */
118
119 #include "stdafx.h"
120 #include "fred.h"
121 #include "freddoc.h"
122 #include "missionnotesdlg.h"
123 #include "management.h"
124 #include "eventmusic.h"
125
126 #ifdef _DEBUG
127 #define new DEBUG_NEW
128 #undef THIS_FILE
129 static char THIS_FILE[] = __FILE__;
130 #endif
131
132 #define NO_SQUAD                                "<none>"
133
134 // module globals to hold button information
135 CButton *coop, *team, *dogfight;
136
137 /////////////////////////////////////////////////////////////////////////////
138 // CMissionNotesDlg dialog
139
140 CMissionNotesDlg::CMissionNotesDlg(CWnd* pParent /*=NULL*/) : CDialog(CMissionNotesDlg::IDD, pParent)
141 {
142         //{{AFX_DATA_INIT(CMissionNotesDlg)
143         m_created = _T("");
144         m_modified = _T("");
145         m_mission_notes = _T("");
146         m_designer_name = _T("");
147         m_mission_title = _T("");
148         m_mission_desc = _T("");
149         m_squad_filename = _T("");
150         m_squad_name = _T(NO_SQUAD);
151         m_music = -1;
152         m_full_war = FALSE;
153         m_red_alert = FALSE;
154         m_scramble = FALSE;
155         m_num_respawns = 0;
156         m_disallow_support = FALSE;
157         m_no_promotion = FALSE;
158         m_no_builtin_msgs = FALSE;
159         m_no_traitor = FALSE;
160         //}}AFX_DATA_INIT
161 }
162
163 void CMissionNotesDlg::DoDataExchange(CDataExchange* pDX)
164 {
165         CDialog::DoDataExchange(pDX);
166         //{{AFX_DATA_MAP(CMissionNotesDlg)
167         DDX_Control(pDX, IDC_RESPAWN_SPIN, m_respawn_spin);
168         DDX_Text(pDX, IDC_CREATED, m_created);
169         DDX_Text(pDX, IDC_MODIFIED, m_modified);
170         DDX_Text(pDX, IDC_MISSION_NOTES, m_mission_notes);
171         DDX_Text(pDX, IDC_DESIGNER_NAME, m_designer_name);
172         DDX_Text(pDX, IDC_MISSION_TITLE, m_mission_title);
173         DDX_Text(pDX, IDC_MISSION_DESC, m_mission_desc);
174         DDX_Text(pDX, IDC_SQUAD_LOGO, m_squad_filename);
175         DDX_Text(pDX, IDC_SQUAD_NAME, m_squad_name);
176         DDX_CBIndex(pDX, IDC_MUSIC, m_music);
177         DDX_Check(pDX, IDC_FULL_WAR, m_full_war);
178         DDX_Check(pDX, IDC_RED_ALERT, m_red_alert);
179         DDX_Check(pDX, IDC_SCRAMBLE, m_scramble);
180         DDX_Text(pDX, IDC_RESPAWNS, m_num_respawns);
181         DDV_MinMaxUInt(pDX, m_num_respawns, 0, 999);
182         DDX_Check(pDX, IDC_SUPPORT_ALLOWED, m_disallow_support);
183         DDX_Check(pDX, IDC_NO_PROMOTION, m_no_promotion);
184         DDX_Check(pDX, IDC_DISABLE_BUILTIN_MSGS, m_no_builtin_msgs);
185         DDX_Check(pDX, IDC_NO_TRAITOR, m_no_traitor);
186         //}}AFX_DATA_MAP
187 }
188
189 BEGIN_MESSAGE_MAP(CMissionNotesDlg, CDialog)
190         //{{AFX_MSG_MAP(CMissionNotesDlg)
191         ON_WM_CLOSE()
192         ON_BN_CLICKED(IDC_TRAINING, OnTraining)
193         ON_BN_CLICKED(IDC_MULTI, OnMulti)
194         ON_BN_CLICKED(IDC_SINGLE, OnSingle)
195         ON_BN_CLICKED(IDC_SQUAD_LOGO_BUTTON, OnSquadLogo)
196         //}}AFX_MSG_MAP
197 END_MESSAGE_MAP()
198
199 /////////////////////////////////////////////////////////////////////////////
200 // CMissionNotesDlg message handlers
201
202 int CMissionNotesDlg::query_modified()
203 {
204         if (m_mission_title != m_mission_title_orig){
205                 return 1;
206         }
207         if (m_designer_name != m_designer_name_orig){
208                 return 1;
209         }
210         if (m_mission_notes != m_mission_notes_orig){
211                 return 1;
212         }
213         if (m_mission_desc != m_mission_desc_orig){
214                 return 1;
215         }
216         if (Current_soundtrack_num != m_music - 1){
217                 return 1;
218         }
219         if (Mission_all_attack != m_full_war){
220                 return 1;
221         }
222
223         return 0;
224 }
225
226 void CMissionNotesDlg::OnOK()
227 {
228         int new_m_type, flags, is_multi = 0, is_training = 0, is_single = 0;
229
230         UpdateData();
231         is_single = (((CButton *) GetDlgItem(IDC_SINGLE))->GetCheck() == 1);
232         is_multi = (((CButton *) GetDlgItem(IDC_MULTI))->GetCheck() == 1);
233         is_training = (((CButton *) GetDlgItem(IDC_TRAINING))->GetCheck() == 1);
234
235         // deal with changing the mission type.  Code is done this way since training missions
236         // just override anything else.
237         new_m_type = 0;
238         if (is_training) {
239                 new_m_type = MISSION_TYPE_TRAINING;
240         } else {
241                 if (is_single){
242                         new_m_type = MISSION_TYPE_SINGLE;
243                 }
244
245                 if (is_multi) {
246                         new_m_type |= MISSION_TYPE_MULTI;
247                         if (coop->GetCheck()){
248                                 new_m_type |= MISSION_TYPE_MULTI_COOP;
249                         } else if (team->GetCheck()){
250                                 new_m_type |= MISSION_TYPE_MULTI_TEAMS;
251                         } else if(dogfight->GetCheck()){
252                                 new_m_type |= MISSION_TYPE_MULTI_DOGFIGHT;
253                         } else {
254                                 Int3();                 // get allender -- multiplayer mode not set!!!
255                         }
256                 }
257         }
258
259         if (!new_m_type) {
260                 MessageBox("You must select the game type: training, single, or multiplayer", "Error");
261                 return;
262         }
263
264         MODIFY(The_mission.game_type, new_m_type );
265         MODIFY(The_mission.red_alert, m_red_alert );
266         MODIFY(The_mission.scramble, m_scramble );
267         MODIFY(The_mission.num_respawns, (int)m_num_respawns );
268         MODIFY(The_mission.disallow_support, (int)m_disallow_support);
269
270         // set the flags for no promotion
271         flags = The_mission.flags;
272         if ( m_no_promotion ) {
273                 The_mission.flags |= MISSION_FLAG_NO_PROMOTION;
274         } else {
275                 The_mission.flags &= ~MISSION_FLAG_NO_PROMOTION;
276         }
277
278         // set flags for no builtin messages
279         if ( m_no_builtin_msgs ) {
280                 The_mission.flags |= MISSION_FLAG_NO_BUILTIN_MSGS;
281         } else {
282                 The_mission.flags &= ~MISSION_FLAG_NO_BUILTIN_MSGS;
283         }
284
285         // set no traitor flags
286         if ( m_no_traitor ) {
287                 The_mission.flags |= MISSION_FLAG_NO_TRAITOR;
288         } else {
289                 The_mission.flags &= ~MISSION_FLAG_NO_TRAITOR;
290         }
291
292         if ( flags != The_mission.flags ){
293                 set_modified();
294         }
295
296         string_copy(The_mission.name, m_mission_title, NAME_LENGTH, 1);
297         string_copy(The_mission.author, m_designer_name, NAME_LENGTH, 1);
298         deconvert_multiline_string(The_mission.notes, m_mission_notes, NOTES_LENGTH);
299         deconvert_multiline_string(The_mission.mission_desc, m_mission_desc, MISSION_DESC_LENGTH);
300
301         // copy squad stuff
302         if(m_squad_name == CString(NO_SQUAD)){
303                 strcpy(The_mission.squad_name, "");
304                 strcpy(The_mission.squad_filename, "");
305         } else {
306                 string_copy(The_mission.squad_name, m_squad_name, NAME_LENGTH);
307                 string_copy(The_mission.squad_filename, m_squad_filename, MAX_FILENAME_LEN);
308         }
309
310         MODIFY(Current_soundtrack_num, m_music - 1);
311         MODIFY(Mission_all_attack, m_full_war);
312         if (query_modified()){
313                 set_modified();
314         }
315
316         theApp.record_window_data(&Mission_notes_wnd_data, this);
317
318         // update the Num_teams variable accoriding to mission types
319         Num_teams = 1;
320         if ( (The_mission.game_type & MISSION_TYPE_MULTI) && (The_mission.game_type & MISSION_TYPE_MULTI_TEAMS) ){
321                 Num_teams = 2;
322         }
323
324         CDialog::OnOK();
325 }
326
327 void CMissionNotesDlg::OnCancel()
328 {
329         theApp.record_window_data(&Mission_notes_wnd_data, this);
330         CDialog::OnCancel();
331 }
332
333 BOOL CMissionNotesDlg::OnInitDialog() 
334 {
335         int i;
336         CComboBox *box;
337
338         // set up the radio box states
339         coop = (CButton *)GetDlgItem(IDC_COOP);
340         team = (CButton *)GetDlgItem(IDC_TEAMVTEAM);
341         dogfight = (CButton *)GetDlgItem(IDC_DOGFIGHT);
342
343         m_mission_title_orig = m_mission_title = _T(The_mission.name);
344         m_designer_name_orig = m_designer_name = _T(The_mission.author);
345         m_created = _T(The_mission.created);
346         m_modified = _T(The_mission.modified);
347         m_mission_notes_orig = m_mission_notes = convert_multiline_string(The_mission.notes);
348         m_mission_desc_orig = m_mission_desc = convert_multiline_string(The_mission.mission_desc);
349         m_red_alert = The_mission.red_alert;
350         m_scramble = The_mission.scramble;
351         m_disallow_support = The_mission.disallow_support;
352         m_no_promotion = (The_mission.flags & MISSION_FLAG_NO_PROMOTION) ? 1 : 0;
353         m_no_builtin_msgs = (The_mission.flags & MISSION_FLAG_NO_BUILTIN_MSGS) ? 1 : 0;
354         m_no_traitor = (The_mission.flags & MISSION_FLAG_NO_TRAITOR) ? 1 : 0;
355         CDialog::OnInitDialog();
356
357         box = (CComboBox *) GetDlgItem(IDC_MUSIC);
358         box->AddString("None");
359         for (i=0; i<Num_soundtracks; i++){
360                 box->AddString(Soundtracks[i].name);            
361         }
362
363         // squad info
364         if(strlen(The_mission.squad_name) > 0){
365                 m_squad_name = _T(The_mission.squad_name);
366                 m_squad_filename = _T(The_mission.squad_filename);
367         } else {
368                 m_squad_name = _T(NO_SQUAD);
369                 m_squad_filename = _T("");
370         }
371
372         m_type = The_mission.game_type;
373         m_music = Current_soundtrack_num + 1;
374         m_full_war = Mission_all_attack;
375
376         // set up the game type checkboxes accoring to m_type
377         if ( m_type & MISSION_TYPE_SINGLE ){
378                 ((CButton *) GetDlgItem(IDC_SINGLE))->SetCheck(1);
379         }
380
381         // for multiplayer -- be sure to assign a default type if not already assigned.
382         if ( m_type & MISSION_TYPE_MULTI ){
383                 ((CButton *) GetDlgItem(IDC_MULTI))->SetCheck(1);
384         }
385
386         if ( m_type & MISSION_TYPE_TRAINING ){
387                 ((CButton *) GetDlgItem(IDC_TRAINING))->SetCheck(1);
388         }
389
390         // we need to set one of these three multiplayer modes so interface looks correct
391         if ( !(m_type & (MISSION_TYPE_MULTI_COOP | MISSION_TYPE_MULTI_DOGFIGHT | MISSION_TYPE_MULTI_TEAMS)) ){
392                 m_type |= MISSION_TYPE_MULTI_COOP;
393         }
394
395         if ( m_type & MISSION_TYPE_MULTI_COOP ){
396                 coop->SetCheck(1);
397         } else if ( m_type & MISSION_TYPE_MULTI_TEAMS ){
398                 team->SetCheck(1);
399         } else if ( m_type & MISSION_TYPE_MULTI_DOGFIGHT ){
400                 dogfight->SetCheck(1);
401         } else {
402                 Int3();                 // get allender -- multiplayer mode not set!!!
403         }
404
405         m_respawn_spin.SetRange(0, 99);
406         m_num_respawns = The_mission.num_respawns;
407
408         set_types();
409         UpdateData(FALSE);
410         theApp.init_window(&Mission_notes_wnd_data, this);
411         return TRUE;
412 }
413
414 void CMissionNotesDlg::OnClose() 
415 {
416         int z;
417
418         if (query_modified()) {
419                 z = MessageBox("Do you want to keep your changes?", "Close", MB_ICONQUESTION | MB_YESNOCANCEL);
420                 if (z == IDCANCEL){
421                         return;
422                 }
423
424                 if (z == IDYES) {
425                         OnOK();
426                         return;
427                 }
428         }
429
430         CDialog::OnClose();
431 }
432
433 // when training button is set, we need to disable all other buttons
434 void CMissionNotesDlg::OnTraining() 
435 {
436         UpdateData(TRUE);
437         set_types();
438 }
439
440 void CMissionNotesDlg::OnMulti() 
441 {
442         UpdateData(TRUE);
443         set_types();
444 }
445
446 void CMissionNotesDlg::OnSingle() 
447 {
448         UpdateData(TRUE);
449         set_types();
450 }
451
452 void CMissionNotesDlg::set_types()
453 {
454         int enable = 0;
455
456         // when training is checked, no other type is active
457         if (((CButton *) GetDlgItem(IDC_MULTI))->GetCheck() == 1){
458                 enable = 1;
459         }
460
461         coop->EnableWindow(enable);
462         team->EnableWindow(enable);
463         dogfight->EnableWindow(enable);
464         GetDlgItem(IDC_RESPAWNS)->EnableWindow(enable);
465         GetDlgItem(IDC_RESPAWN_SPIN)->EnableWindow(enable);
466 }
467
468 void CMissionNotesDlg::OnSquadLogo()
469 {       
470         CString pcx_filename;
471         int z;
472
473         // get list of squad images
474         z = cfile_push_chdir(CF_TYPE_SQUAD_IMAGES_MAIN);
475         CFileDialog dlg(TRUE, "pcx", pcx_filename, OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR, "Pcx Files (*.pcx)|*.pcx");
476
477         // if we have a result
478         if (dlg.DoModal() == IDOK) {
479                 m_squad_filename = dlg.GetFileName();           
480         } else {
481                 m_squad_filename = _T("");
482         }
483         UpdateData(FALSE);              
484
485         // restore directory
486         if (!z){
487                 cfile_pop_dir();
488         }       
489 }