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