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