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 the
6 * source.
7 *
8 */
9
10
11
12 #include "stdafx.h"
13 #include "FRED.h"
14 #include "FREDDoc.h"
15 #include "EventEditor.h"
16 #include "FREDView.h"
17 #include "Management.h"
18 #include "Sexp_tree.h"
19 #include "mission/missionmessage.h"
20 #include "cfile/cfile.h"
21 #include "sound/audiostr.h"
22 #include "localization/localize.h"
23
24 #ifdef _DEBUG
25 #undef THIS_FILE
26 static char THIS_FILE[] = __FILE__;
27 #endif
28
29 event_editor *Event_editor_dlg = NULL; // global reference needed by event tree class
30
31 /////////////////////////////////////////////////////////////////////////////
32 // event_editor dialog
33
event_editor(CWnd * pParent)34 event_editor::event_editor(CWnd* pParent /*=NULL*/)
35 : CDialog(event_editor::IDD, pParent)
36 {
37 //{{AFX_DATA_INIT(event_editor)
38 m_repeat_count = 0;
39 m_trigger_count = 0;
40 m_interval = 0;
41 m_event_score = 0;
42 m_chain_delay = 0;
43 m_chained = FALSE;
44 m_obj_text = _T("");
45 m_obj_key_text = _T("");
46 m_avi_filename = _T("");
47 m_message_name = _T("");
48 m_message_text = _T("");
49 m_persona = -1;
50 m_wave_filename = _T("");
51 m_cur_msg = -1;
52 m_team = -1;
53 m_message_team = -1;
54 m_last_message_node = -1;
55 //}}AFX_DATA_INIT
56 m_event_tree.m_mode = MODE_EVENTS;
57 m_num_events = 0;
58 m_event_tree.link_modified(&modified);
59 modified = 0;
60 select_sexp_node = -1;
61 m_wave_id = -1;
62 m_log_true = 0;
63 m_log_false = 0;
64 m_log_always_false = 0;
65 m_log_1st_repeat = 0;
66 m_log_last_repeat = 0;
67 m_log_1st_trigger = 0;
68 m_log_last_trigger = 0;
69 m_log_state_change = 0;
70 }
71
DoDataExchange(CDataExchange * pDX)72 void event_editor::DoDataExchange(CDataExchange* pDX)
73 {
74 CDialog::DoDataExchange(pDX);
75 //{{AFX_DATA_MAP(event_editor)
76 DDX_Control(pDX, IDC_EVENT_TREE, m_event_tree);
77 DDX_Text(pDX, IDC_REPEAT_COUNT, m_repeat_count);
78 DDX_Text(pDX, IDC_TRIGGER_COUNT, m_trigger_count);
79 DDX_Text(pDX, IDC_INTERVAL_TIME, m_interval);
80 DDX_Text(pDX, IDC_EVENT_SCORE, m_event_score);
81 DDX_Text(pDX, IDC_CHAIN_DELAY, m_chain_delay);
82 DDX_Check(pDX, IDC_CHAINED, m_chained);
83 DDX_Text(pDX, IDC_OBJ_TEXT, m_obj_text);
84 DDX_Text(pDX, IDC_OBJ_KEY_TEXT, m_obj_key_text);
85 DDX_CBString(pDX, IDC_AVI_FILENAME, m_avi_filename);
86 DDX_Text(pDX, IDC_MESSAGE_NAME, m_message_name);
87 DDX_Text(pDX, IDC_MESSAGE_TEXT, m_message_text);
88 DDX_CBIndex(pDX, IDC_PERSONA_NAME, m_persona);
89 DDX_CBString(pDX, IDC_WAVE_FILENAME, m_wave_filename);
90 DDX_LBIndex(pDX, IDC_MESSAGE_LIST, m_cur_msg);
91 DDX_Check(pDX, IDC_MISSION_LOG_TRUE, m_log_true);
92 DDX_Check(pDX, IDC_MISSION_LOG_FALSE, m_log_false);
93 DDX_Check(pDX, IDC_MISSION_LOG_ALWAYS_FALSE, m_log_always_false);
94 DDX_Check(pDX, IDC_MISSION_LOG_1ST_REPEAT, m_log_1st_repeat);
95 DDX_Check(pDX, IDC_MISSION_LOG_LAST_REPEAT, m_log_last_repeat);
96 DDX_Check(pDX, IDC_MISSION_LOG_1ST_TRIGGER, m_log_1st_trigger);
97 DDX_Check(pDX, IDC_MISSION_LOG_LAST_TRIGGER, m_log_last_trigger);
98 DDX_Check(pDX, IDC_MISSION_LOG_STATE_CHANGE, m_log_state_change);
99
100
101 // m_team == -1 maps to 2
102 if(m_team == -1){
103 m_team = MAX_TVT_TEAMS;
104 }
105
106 DDX_CBIndex(pDX, IDC_EVENT_TEAM, m_team);
107
108 // m_message_team == -1 maps to 2
109 if(m_message_team == -1){
110 m_message_team = MAX_TVT_TEAMS;
111 }
112 DDX_CBIndex(pDX, IDC_MESSAGE_TEAM, m_message_team);
113 //}}AFX_DATA_MAP
114
115 DDV_MaxChars(pDX, m_obj_text, NAME_LENGTH - 1);
116 DDV_MaxChars(pDX, m_obj_key_text, NAME_LENGTH - 1);
117 DDV_MaxChars(pDX, m_message_name, NAME_LENGTH - 1);
118 DDV_MaxChars(pDX, m_message_text, MESSAGE_LENGTH - 1);
119 DDV_MaxChars(pDX, m_avi_filename, MAX_FILENAME_LEN - 1);
120 DDV_MaxChars(pDX, m_wave_filename, MAX_FILENAME_LEN - 1);
121 }
122
BEGIN_MESSAGE_MAP(event_editor,CDialog)123 BEGIN_MESSAGE_MAP(event_editor, CDialog)
124 //{{AFX_MSG_MAP(event_editor)
125 ON_NOTIFY(NM_RCLICK, IDC_EVENT_TREE, OnRclickEventTree)
126 ON_NOTIFY(TVN_BEGINLABELEDIT, IDC_EVENT_TREE, OnBeginlabeleditEventTree)
127 ON_NOTIFY(TVN_ENDLABELEDIT, IDC_EVENT_TREE, OnEndlabeleditEventTree)
128 ON_BN_CLICKED(IDC_BUTTON_NEW_EVENT, OnButtonNewEvent)
129 ON_BN_CLICKED(IDC_DELETE, OnDelete)
130 ON_BN_CLICKED(ID_OK, OnOk)
131 ON_WM_CLOSE()
132 ON_NOTIFY(TVN_SELCHANGED, IDC_EVENT_TREE, OnSelchangedEventTree)
133 ON_EN_UPDATE(IDC_REPEAT_COUNT, OnUpdateRepeatCount)
134 ON_EN_UPDATE(IDC_TRIGGER_COUNT, OnUpdateTriggerCount)
135 ON_BN_CLICKED(IDC_CHAINED, OnChained)
136 ON_BN_CLICKED(IDC_INSERT, OnInsert)
137 ON_LBN_SELCHANGE(IDC_MESSAGE_LIST, OnSelchangeMessageList)
138 ON_BN_CLICKED(IDC_NEW_MSG, OnNewMsg)
139 ON_BN_CLICKED(IDC_DELETE_MSG, OnDeleteMsg)
140 ON_BN_CLICKED(IDC_BROWSE_AVI, OnBrowseAvi)
141 ON_BN_CLICKED(IDC_BROWSE_WAVE, OnBrowseWave)
142 ON_CBN_SELCHANGE(IDC_WAVE_FILENAME, OnSelchangeWaveFilename)
143 ON_BN_CLICKED(IDC_PLAY, OnPlay)
144 ON_BN_CLICKED(IDC_UPDATE, OnUpdate)
145 ON_BN_CLICKED(ID_CANCEL, On_Cancel)
146 ON_CBN_SELCHANGE(IDC_EVENT_TEAM, OnSelchangeTeam)
147 ON_CBN_SELCHANGE(IDC_MESSAGE_TEAM, OnSelchangeMessageTeam)
148 ON_LBN_DBLCLK(IDC_MESSAGE_LIST, OnDblclkMessageList)
149 //}}AFX_MSG_MAP
150 END_MESSAGE_MAP()
151
152 /////////////////////////////////////////////////////////////////////////////
153 // event_editor message handlers
154
155 void maybe_add_head(CComboBox *box, char* name)
156 {
157 if (box->FindStringExact(-1, name) == CB_ERR) {
158 box->AddString(name);
159 }
160 }
161
OnInitDialog()162 BOOL event_editor::OnInitDialog()
163 {
164 int i, adjust = 0;
165 BOOL r = TRUE;
166 CListBox *list;
167 CComboBox *box;
168 MMessage msg;
169
170 CDialog::OnInitDialog(); // let the base class do the default work
171 m_play_bm.LoadBitmap(IDB_PLAY);
172 ((CButton *) GetDlgItem(IDC_PLAY)) -> SetBitmap(m_play_bm);
173
174 if (!Show_sexp_help)
175 adjust = -SEXP_HELP_BOX_SIZE;
176
177 theApp.init_window(&Events_wnd_data, this, adjust);
178 m_event_tree.setup((CEdit *) GetDlgItem(IDC_HELP_BOX));
179 load_tree();
180 create_tree();
181 if (m_num_events >= MAX_MISSION_EVENTS){
182 GetDlgItem(IDC_BUTTON_NEW_EVENT)->EnableWindow(FALSE);
183 }
184
185 update_cur_event();
186 i = m_event_tree.select_sexp_node;
187 if (i != -1) {
188 GetDlgItem(IDC_EVENT_TREE) -> SetFocus();
189 m_event_tree.hilite_item(i);
190 r = FALSE;
191 }
192
193 m_num_messages = Num_messages - Num_builtin_messages;
194 for (i=0; i<m_num_messages; i++) {
195 msg = Messages[i + Num_builtin_messages];
196 m_messages.push_back(msg);
197 if (m_messages[i].avi_info.name){
198 m_messages[i].avi_info.name = strdup(m_messages[i].avi_info.name);
199 }
200 if (m_messages[i].wave_info.name){
201 m_messages[i].wave_info.name = strdup(m_messages[i].wave_info.name);
202 }
203 }
204
205 ((CEdit *) GetDlgItem(IDC_MESSAGE_NAME))->LimitText(NAME_LENGTH - 1);
206 ((CEdit *) GetDlgItem(IDC_MESSAGE_TEXT))->LimitText(MESSAGE_LENGTH - 1);
207 ((CComboBox *) GetDlgItem(IDC_AVI_FILENAME))->LimitText(MAX_FILENAME_LEN - 1);
208 ((CComboBox *) GetDlgItem(IDC_WAVE_FILENAME))->LimitText(MAX_FILENAME_LEN - 1);
209
210 list = (CListBox *) GetDlgItem(IDC_MESSAGE_LIST);
211 list->ResetContent();
212 for (i=0; i<m_num_messages; i++) {
213 list->AddString(m_messages[i].name);
214 }
215
216 box = (CComboBox *) GetDlgItem(IDC_AVI_FILENAME);
217 box->ResetContent();
218 box->AddString("<None>");
219 for (i=0; i<Num_messages; i++) {
220 if (Messages[i].avi_info.name) {
221 maybe_add_head(box, Messages[i].avi_info.name);
222 }
223 }
224
225 // add new heads, if not already in
226 maybe_add_head(box, "Head-TP2");
227 maybe_add_head(box, "Head-VC2");
228 maybe_add_head(box, "Head-TP4");
229 maybe_add_head(box, "Head-TP5");
230 maybe_add_head(box, "Head-TP6");
231 maybe_add_head(box, "Head-TP7");
232 maybe_add_head(box, "Head-TP8");
233 maybe_add_head(box, "Head-VP2");
234 maybe_add_head(box, "Head-VP2");
235 maybe_add_head(box, "Head-CM2");
236 maybe_add_head(box, "Head-CM3");
237 maybe_add_head(box, "Head-CM4");
238 maybe_add_head(box, "Head-CM5");
239 maybe_add_head(box, "Head-BSH");
240
241 /*
242 box->AddString("Head-VC"); // force it in, since Sandeep wants it and it's not used in built-in messages
243 box->AddString("Head-VC2");
244
245 // add terran pilot heads
246 box->AddString("Head-TP4");
247 box->AddString("Head-TP5");
248 box->AddString("Head-TP6");
249 box->AddString("Head-TP7");
250 box->AddString("Head-TP8");
251
252 // add vasudan pilot heads
253 box->AddString("Head-VP2");
254
255 // BSH and CM2
256 box->AddString("Head-CM2");
257 box->AddString("Head-BSH");
258 */
259
260 box = (CComboBox *) GetDlgItem(IDC_WAVE_FILENAME);
261 box->ResetContent();
262 box->AddString("<None>");
263 for (i=0; i<Num_messages; i++){
264 if (Messages[i].wave_info.name){
265 if (box->FindStringExact(i, Messages[i].wave_info.name) == CB_ERR){
266 box->AddString(Messages[i].wave_info.name);
267 }
268 }
269 }
270
271 // add the persona names into the combo box
272 box = (CComboBox *) GetDlgItem(IDC_PERSONA_NAME);
273 box->ResetContent();
274 box->AddString("<None>");
275 for (i = 0; i < Num_personas; i++ ){
276 box->AddString( Personas[i].name );
277 }
278
279 // set the first message to be the first non-builtin message (if it exists)
280 if ( Num_messages > Num_builtin_messages ){
281 m_cur_msg = 0;
282 } else {
283 m_cur_msg = -1;
284 }
285
286 update_cur_message();
287 return r;
288 }
289
load_tree()290 void event_editor::load_tree()
291 {
292 int i;
293
294 m_event_tree.select_sexp_node = select_sexp_node;
295 select_sexp_node = -1;
296
297 m_event_tree.clear_tree();
298 m_num_events = Num_mission_events;
299 for (i=0; i<m_num_events; i++) {
300 m_events[i] = Mission_events[i];
301 if (Mission_events[i].objective_text){
302 m_events[i].objective_text = strdup(Mission_events[i].objective_text);
303 } else {
304 m_events[i].objective_text = NULL;
305 }
306
307 if (Mission_events[i].objective_key_text){
308 m_events[i].objective_key_text = strdup(Mission_events[i].objective_key_text);
309 } else {
310 m_events[i].objective_key_text = NULL;
311 }
312
313 m_sig[i] = i;
314 if (!(*m_events[i].name)){
315 strcpy_s(m_events[i].name, "<Unnamed>");
316 }
317
318 m_events[i].formula = m_event_tree.load_sub_tree(Mission_events[i].formula, false, "do-nothing");
319
320 // we must check for the case of the repeat count being 0. This would happen if the repeat
321 // count is not specified in a mission
322 if ( m_events[i].repeat_count <= 0 ){
323 m_events[i].repeat_count = 1;
324 }
325 }
326
327 m_event_tree.post_load();
328 cur_event = -1;
329 }
330
create_tree()331 void event_editor::create_tree()
332 {
333 int i;
334 HTREEITEM h;
335
336 m_event_tree.DeleteAllItems();
337 for (i=0; i<m_num_events; i++) {
338
339 // set the proper bitmap
340 int image;
341 if (m_events[i].chain_delay >= 0) {
342 image = BITMAP_CHAIN;
343 if (m_events[i].objective_text) {
344 image = BITMAP_CHAIN_DIRECTIVE;
345 }
346 } else {
347 image = BITMAP_ROOT;
348 if (m_events[i].objective_text) {
349 image = BITMAP_ROOT_DIRECTIVE;
350 }
351 }
352
353 h = m_event_tree.insert(m_events[i].name, image, image);
354
355 m_event_tree.SetItemData(h, m_events[i].formula);
356 m_event_tree.add_sub_tree(m_events[i].formula, h);
357 }
358
359 cur_event = -1;
360 }
361
OnRclickEventTree(NMHDR * pNMHDR,LRESULT * pResult)362 void event_editor::OnRclickEventTree(NMHDR* pNMHDR, LRESULT* pResult)
363 {
364 save();
365 m_event_tree.right_clicked(MODE_EVENTS);
366 *pResult = 0;
367 }
368
OnBeginlabeleditEventTree(NMHDR * pNMHDR,LRESULT * pResult)369 void event_editor::OnBeginlabeleditEventTree(NMHDR* pNMHDR, LRESULT* pResult)
370 {
371 TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
372 CEdit *edit;
373
374 if (m_event_tree.edit_label(pTVDispInfo->item.hItem) == 1) {
375 *pResult = 0;
376 modified = 1;
377 edit = m_event_tree.GetEditControl();
378 Assert(edit);
379 edit->SetLimitText(NAME_LENGTH - 1);
380
381 } else
382 *pResult = 1;
383 }
384
OnEndlabeleditEventTree(NMHDR * pNMHDR,LRESULT * pResult)385 void event_editor::OnEndlabeleditEventTree(NMHDR* pNMHDR, LRESULT* pResult)
386 {
387 TV_DISPINFO* pTVDispInfo = (TV_DISPINFO*)pNMHDR;
388
389 *pResult = m_event_tree.end_label_edit(pTVDispInfo->item);
390 }
391
392 // This is needed as a HACK around default MFC standard
393 // It is not required, but overrides default MFC and links no errors without.
OnOK()394 void event_editor::OnOK()
395 {
396 HWND h;
397 CWnd *w;
398
399 save();
400 w = GetFocus();
401 if (w) {
402 h = w->m_hWnd;
403 GetDlgItem(IDC_EVENT_TREE)->SetFocus();
404 ::SetFocus(h);
405 }
406 ((CListBox *) GetDlgItem(IDC_MESSAGE_LIST))->SetCurSel(m_cur_msg);
407 }
408
query_modified()409 int event_editor::query_modified()
410 {
411 int i;
412 char *ptr, buf[MESSAGE_LENGTH];
413
414 UpdateData(TRUE);
415 if (modified)
416 return 1;
417
418 if (Num_mission_events != m_num_events)
419 return 1;
420
421 for (i=0; i<m_num_events; i++) {
422 if (stricmp(m_events[i].name, Mission_events[i].name))
423 return 1;
424 if (m_events[i].repeat_count != Mission_events[i].repeat_count)
425 return 1;
426 if (m_events[i].trigger_count != Mission_events[i].trigger_count)
427 return 1;
428 if (m_events[i].interval != Mission_events[i].interval)
429 return 1;
430 if (m_events[i].score != Mission_events[i].score)
431 return 1;
432 if (m_events[i].chain_delay != Mission_events[i].chain_delay)
433 return 1;
434 if (advanced_stricmp(m_events[i].objective_text, Mission_events[i].objective_text))
435 return 1;
436 if (advanced_stricmp(m_events[i].objective_key_text, Mission_events[i].objective_key_text))
437 return 1;
438 if (m_events[i].mission_log_flags != Mission_events[i].mission_log_flags)
439 return 1;
440 }
441
442 if (m_cur_msg < 0)
443 return 0;
444
445 if (m_num_messages != Num_messages)
446 return 1;
447
448 ptr = (char *) (LPCTSTR) m_message_name;
449 for (i=0; i<Num_builtin_messages; i++)
450 if (!stricmp(ptr, Messages[i].name))
451 return 1;
452
453 for (i=0; i<m_num_messages; i++) {
454
455 if ((i != m_cur_msg) && (!stricmp(ptr, m_messages[m_cur_msg].name)))
456 return 1;
457 }
458
459 if (stricmp(ptr, m_messages[m_cur_msg].name))
460 return 1; // name is different and allowed to update
461
462 string_copy(buf, m_message_text, MESSAGE_LENGTH - 1);
463 if (stricmp(buf, m_messages[m_cur_msg].message))
464 return 1;
465
466 ptr = (char *) (LPCTSTR) m_avi_filename;
467 if (advanced_stricmp(ptr, m_messages[m_cur_msg].avi_info.name))
468 return 1;
469
470 ptr = (char *) (LPCTSTR) m_wave_filename;
471 if (advanced_stricmp(ptr, m_messages[m_cur_msg].wave_info.name))
472 return 1;
473
474 // check to see if persona changed. use -1 since we stuck a "None" for persona
475 // at the beginning of the list.
476 if ( (m_persona - 1 ) != m_messages[m_cur_msg].persona_index )
477 return 1;
478
479 return 0;
480 }
481
OnOk()482 void event_editor::OnOk()
483 {
484 char buf[256], names[2][MAX_MISSION_EVENTS][NAME_LENGTH];
485 int i, count;
486
487 audiostream_close_file(m_wave_id, 0);
488 m_wave_id = -1;
489
490 save();
491 if (query_modified())
492 set_modified();
493
494 for (i=0; i<Num_mission_events; i++) {
495 free_sexp2(Mission_events[i].formula);
496 if (Mission_events[i].objective_text)
497 free(Mission_events[i].objective_text);
498 if (Mission_events[i].objective_key_text)
499 free(Mission_events[i].objective_key_text);
500 }
501
502 count = 0;
503 for (i=0; i<Num_mission_events; i++)
504 Mission_events[i].result = 0; // use this as a processed flag
505
506 // rename all sexp references to old events
507 for (i=0; i<m_num_events; i++)
508 if (m_sig[i] >= 0) {
509 strcpy_s(names[0][count], Mission_events[m_sig[i]].name);
510 strcpy_s(names[1][count], m_events[i].name);
511 count++;
512 Mission_events[m_sig[i]].result = 1;
513 }
514
515 // invalidate all sexp references to deleted events.
516 for (i=0; i<Num_mission_events; i++)
517 if (!Mission_events[i].result) {
518 sprintf(buf, "<%s>", Mission_events[i].name);
519 strcpy(buf + NAME_LENGTH - 2, ">"); // force it to be not too long
520 strcpy_s(names[0][count], Mission_events[i].name);
521 strcpy_s(names[1][count], buf);
522 count++;
523 }
524
525 Num_mission_events = m_num_events;
526 for (i=0; i<m_num_events; i++) {
527 Mission_events[i] = m_events[i];
528 Mission_events[i].formula = m_event_tree.save_tree(m_events[i].formula);
529 Mission_events[i].objective_text = m_events[i].objective_text;
530 Mission_events[i].objective_key_text = m_events[i].objective_key_text;
531 Mission_events[i].mission_log_flags = m_events[i].mission_log_flags;
532 }
533
534 // now update all sexp references
535 while (count--)
536 update_sexp_references(names[0][count], names[1][count], OPF_EVENT_NAME);
537
538 for (i=Num_builtin_messages; i<Num_messages; i++) {
539 if (Messages[i].avi_info.name)
540 free(Messages[i].avi_info.name);
541
542 if (Messages[i].wave_info.name)
543 free(Messages[i].wave_info.name);
544 }
545
546 Num_messages = m_num_messages + Num_builtin_messages;
547 for (i=0; i<m_num_messages; i++)
548 Messages[i + Num_builtin_messages] = m_messages[i];
549
550 theApp.record_window_data(&Events_wnd_data, this);
551 delete Event_editor_dlg;
552 Event_editor_dlg = NULL;
553 }
554
555 // load controls with structure data
update_cur_message()556 void event_editor::update_cur_message()
557 {
558 int enable = TRUE;
559
560 audiostream_close_file(m_wave_id, 0);
561 m_wave_id = -1;
562
563 if (m_cur_msg < 0) {
564 enable = FALSE;
565 m_message_name = _T("");
566 m_message_text = _T("");
567 m_avi_filename = _T("");
568 m_wave_filename = _T("");
569 m_persona = 0;
570 m_message_team = -1;
571 } else {
572 m_message_name = m_messages[m_cur_msg].name;
573 m_message_text = m_messages[m_cur_msg].message;
574 if (m_messages[m_cur_msg].avi_info.name){
575 m_avi_filename = _T(m_messages[m_cur_msg].avi_info.name);
576 } else {
577 m_avi_filename = _T("<None>");
578 }
579
580 if (m_messages[m_cur_msg].wave_info.name){
581 m_wave_filename = _T(m_messages[m_cur_msg].wave_info.name);
582 } else {
583 m_wave_filename = _T("<None>");
584 }
585
586 // add persona id
587 if ( m_messages[m_cur_msg].persona_index != -1 ){
588 m_persona = m_messages[m_cur_msg].persona_index + 1; // add one for the "none" at the beginning of the list
589 } else {
590 m_persona = 0;
591 }
592
593 if(m_messages[m_cur_msg].multi_team >= MAX_TVT_TEAMS){
594 m_message_team = -1;
595 m_messages[m_cur_msg].multi_team = -1;
596 } else {
597 m_message_team = m_messages[m_cur_msg].multi_team;
598 }
599 /*
600 m_event_num = find_event();
601 if (m_event_num < 0) {
602 node = -1;
603 m_sender = m_priority = 0;
604
605 } else
606 node = CADR(Mission_events[m_event_num].formula);
607 */ }
608
609 GetDlgItem(IDC_MESSAGE_NAME)->EnableWindow(enable);
610 GetDlgItem(IDC_MESSAGE_TEXT)->EnableWindow(enable);
611 GetDlgItem(IDC_AVI_FILENAME)->EnableWindow(enable);
612 GetDlgItem(IDC_BROWSE_AVI)->EnableWindow(enable);
613 GetDlgItem(IDC_BROWSE_WAVE)->EnableWindow(enable);
614 GetDlgItem(IDC_WAVE_FILENAME)->EnableWindow(enable);
615 GetDlgItem(IDC_DELETE_MSG)->EnableWindow(enable);
616 GetDlgItem(IDC_PERSONA_NAME)->EnableWindow(enable);
617 GetDlgItem(IDC_MESSAGE_TEAM)->EnableWindow(enable);
618 UpdateData(FALSE);
619 }
620
handler(int code,int node,char * str)621 int event_editor::handler(int code, int node, char *str)
622 {
623 int i, index;
624
625 switch (code) {
626 case ROOT_DELETED:
627 for (i=0; i<m_num_events; i++)
628 if (m_events[i].formula == node)
629 break;
630
631 Assert(i < m_num_events);
632 index = i;
633 while (i < m_num_events - 1) {
634 m_events[i] = m_events[i + 1];
635 m_sig[i] = m_sig[i + 1];
636 i++;
637 }
638
639 m_num_events--;
640 GetDlgItem(IDC_BUTTON_NEW_EVENT)->EnableWindow(TRUE);
641
642 cur_event = index;
643 update_cur_event();
644
645 return node;
646
647 case ROOT_RENAMED:
648 for (i=0; i<m_num_events; i++)
649 if (m_events[i].formula == node)
650 break;
651
652 Assert(i < m_num_events);
653 Assert(strlen(str) < NAME_LENGTH);
654 strcpy_s(m_events[i].name, str);
655 return node;
656
657 default:
658 Int3();
659 }
660
661 return -1;
662 }
663
OnButtonNewEvent()664 void event_editor::OnButtonNewEvent()
665 {
666 if (m_num_events == MAX_MISSION_EVENTS) {
667 MessageBox("You have reached the limit on mission events.\n"
668 "Can't add any more.");
669 return;
670 }
671
672 reset_event(m_num_events++, TVI_LAST);
673 }
674
OnInsert()675 void event_editor::OnInsert()
676 {
677 int i;
678
679 if (m_num_events == MAX_MISSION_EVENTS) {
680 MessageBox("You have reached the limit on mission events.\n"
681 "Can't add any more.");
682 return;
683 }
684
685 if(cur_event < 0 || m_num_events == 0)
686 {
687 //There are no events yet, so just create one
688 reset_event(m_num_events++, TVI_LAST);
689 }
690 else
691 {
692 for (i=m_num_events; i>cur_event; i--) {
693 m_events[i] = m_events[i - 1];
694 m_sig[i] = m_sig[i - 1];
695 }
696
697 if (cur_event){
698 reset_event(cur_event, get_event_handle(cur_event - 1));
699 } else {
700 reset_event(cur_event, TVI_FIRST);
701 }
702
703 m_num_events++;
704 }
705 }
706
get_event_handle(int num)707 HTREEITEM event_editor::get_event_handle(int num)
708 {
709 HTREEITEM h;
710
711 h = m_event_tree.GetRootItem();
712 while (h) {
713 if ((int) m_event_tree.GetItemData(h) == m_events[num].formula){
714 return h;
715 }
716
717 h = m_event_tree.GetNextSiblingItem(h);
718 }
719
720 return 0;
721 }
722
reset_event(int num,HTREEITEM after)723 void event_editor::reset_event(int num, HTREEITEM after)
724 {
725 int index;
726 HTREEITEM h;
727
728 strcpy_s(m_events[num].name, "Event name");
729 h = m_event_tree.insert(m_events[num].name, BITMAP_ROOT, BITMAP_ROOT, TVI_ROOT, after);
730
731 m_events[num].repeat_count = 1;
732 m_events[num].trigger_count = 1;
733 m_events[num].interval = 1;
734 m_events[num].score = 0;
735 m_events[num].chain_delay = -1;
736 m_events[num].objective_text = NULL;
737 m_events[num].objective_key_text = NULL;
738 m_events[num].team = -1;
739 m_events[num].mission_log_flags = 0;
740 m_sig[num] = -1;
741
742 m_event_tree.item_index = -1;
743 m_event_tree.add_operator("when", h);
744 index = m_events[num].formula = m_event_tree.item_index;
745 m_event_tree.SetItemData(h, index);
746 m_event_tree.add_operator("true");
747 m_event_tree.item_index = index;
748 m_event_tree.add_operator("do-nothing");
749
750 m_event_tree.SelectItem(h);
751 // GetDlgItem(IDC_CHAIN_DELAY) -> EnableWindow(FALSE);
752 if (num >= MAX_MISSION_EVENTS){
753 GetDlgItem(IDC_BUTTON_NEW_EVENT)->EnableWindow(FALSE);
754 }
755 }
756
OnDelete()757 void event_editor::OnDelete()
758 {
759 HTREEITEM h;
760
761 // call update_cur_event to clean up local class variables so that we can correctly
762 // set up the newly selected item.
763 cur_event = -1;
764 update_cur_event();
765
766 h = m_event_tree.GetSelectedItem();
767 if (h) {
768 while (m_event_tree.GetParentItem(h))
769 h = m_event_tree.GetParentItem(h);
770
771 m_event_tree.setup_selected(h);
772 m_event_tree.OnCommand(ID_DELETE, 0);
773 }
774 }
775
776 // this is called when you hit the escape key..
OnCancel()777 void event_editor::OnCancel()
778 {
779 }
780
781 // this is called the clicking the ID_CANCEL button
On_Cancel()782 void event_editor::On_Cancel()
783 {
784 audiostream_close_file(m_wave_id, 0);
785 m_wave_id = -1;
786
787 theApp.record_window_data(&Events_wnd_data, this);
788 delete Event_editor_dlg;
789 Event_editor_dlg = NULL;
790 }
791
OnClose()792 void event_editor::OnClose()
793 {
794 int z;
795
796 audiostream_close_file(m_wave_id, 0);
797 m_wave_id = -1;
798
799 if (query_modified()) {
800 z = MessageBox("Do you want to keep your changes?", "Close", MB_ICONQUESTION | MB_YESNOCANCEL);
801 if (z == IDCANCEL){
802 return;
803 }
804
805 if (z == IDYES) {
806 OnOk();
807 return;
808 }
809 }
810
811 theApp.record_window_data(&Events_wnd_data, this);
812 delete Event_editor_dlg;
813 Event_editor_dlg = NULL;
814 }
815
insert_handler(int old,int node)816 void event_editor::insert_handler(int old, int node)
817 {
818 int i;
819
820 for (i=0; i<m_num_events; i++){
821 if (m_events[i].formula == old){
822 break;
823 }
824 }
825
826 Assert(i < m_num_events);
827 m_events[i].formula = node;
828 return;
829 }
830
save()831 void event_editor::save()
832 {
833 int m = m_cur_msg;
834
835 save_event(cur_event);
836 save_message(m);
837 }
838
save_event(int e)839 void event_editor::save_event(int e)
840 {
841 if (e < 0) {
842 return;
843 }
844
845 UpdateData(TRUE);
846 m_events[e].repeat_count = m_repeat_count;
847 m_events[e].trigger_count = m_trigger_count;
848 m_events[e].interval = m_interval;
849 m_events[e].score = m_event_score;
850
851 // handle chain
852 if (m_chained) {
853 m_events[e].chain_delay = m_chain_delay;
854 } else {
855 m_events[e].chain_delay = -1;
856 }
857
858 // handle objective text
859 if (m_events[e].objective_text) {
860 free(m_events[e].objective_text);
861 }
862
863 if (m_obj_text.IsEmpty()) {
864 m_events[e].objective_text = NULL;
865 } else {
866 m_events[e].objective_text = strdup(m_obj_text);
867 }
868
869 // handle objective key text
870 if (m_events[e].objective_key_text) {
871 free(m_events[e].objective_key_text);
872 }
873
874 if (m_obj_key_text.IsEmpty()) {
875 m_events[e].objective_key_text = NULL;
876 } else {
877 m_events[e].objective_key_text = strdup(m_obj_key_text);
878 }
879
880 // update bitmap
881 int bitmap;
882 if (m_chained) {
883 if (m_obj_text.IsEmpty()) {
884 bitmap = BITMAP_CHAIN;
885 } else {
886 bitmap = BITMAP_CHAIN_DIRECTIVE;
887 }
888 } else {
889 // not chained
890 if (m_obj_text.IsEmpty()) {
891 bitmap = BITMAP_ROOT;
892 } else {
893 bitmap = BITMAP_ROOT_DIRECTIVE;
894 }
895 }
896
897 // handle event log flags
898 m_events[e].mission_log_flags = 0;
899 if (m_log_true)
900 m_events[e].mission_log_flags |= MLF_SEXP_TRUE;
901 if (m_log_false)
902 m_events[e].mission_log_flags |= MLF_SEXP_FALSE;
903 if (m_log_always_false)
904 m_events[e].mission_log_flags |= MLF_SEXP_KNOWN_FALSE;
905 if (m_log_1st_repeat)
906 m_events[e].mission_log_flags |= MLF_FIRST_REPEAT_ONLY;
907 if (m_log_last_repeat)
908 m_events[e].mission_log_flags |= MLF_LAST_REPEAT_ONLY;
909 if (m_log_1st_trigger)
910 m_events[e].mission_log_flags |= MLF_FIRST_TRIGGER_ONLY;
911 if (m_log_last_trigger)
912 m_events[e].mission_log_flags |= MLF_LAST_TRIGGER_ONLY;
913 if (m_log_state_change)
914 m_events[e].mission_log_flags |= MLF_STATE_CHANGE;
915
916
917 // Search for item to update
918 HTREEITEM h = m_event_tree.GetRootItem();
919 while (h) {
920 if ((int) m_event_tree.GetItemData(h) == m_events[e].formula) {
921 m_event_tree.SetItemImage(h, bitmap, bitmap);
922 return;
923 }
924
925 h = m_event_tree.GetNextSiblingItem(h);
926 }
927
928 }
929
930 // this function deals with the left click on an event in the tree view. We get into this
931 // function so that we may update the other data on the screen (i.e repeat count and interval
932 // count)
OnSelchangedEventTree(NMHDR * pNMHDR,LRESULT * pResult)933 void event_editor::OnSelchangedEventTree(NMHDR* pNMHDR, LRESULT* pResult)
934 {
935 int i, z;
936 NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
937 HTREEITEM h, h2;
938
939 // before we do anything, we must check and save off any data from the current event (i.e.
940 // the repeat count and interval count)
941 save();
942 h = pNMTreeView->itemNew.hItem;
943 if (!h){
944 return;
945 }
946
947 m_event_tree.update_help(h);
948 while ((h2 = m_event_tree.GetParentItem(h))>0){
949 h = h2;
950 }
951
952 z = m_event_tree.GetItemData(h);
953 for (i=0; i<m_num_events; i++){
954 if (m_events[i].formula == z){
955 break;
956 }
957 }
958
959 Assert(i < m_num_events);
960 cur_event = i;
961 update_cur_event();
962
963 *pResult = 0;
964 }
965
update_cur_event()966 void event_editor::update_cur_event()
967 {
968 if (cur_event < 0) {
969 m_repeat_count = 1;
970 m_trigger_count = 1;
971 m_interval = 1;
972 m_chain_delay = 0;
973 m_team = -1;
974 m_obj_text.Empty();
975 m_obj_key_text.Empty();
976 GetDlgItem(IDC_INTERVAL_TIME) -> EnableWindow(FALSE);
977 GetDlgItem(IDC_REPEAT_COUNT) -> EnableWindow(FALSE);
978 GetDlgItem(IDC_TRIGGER_COUNT) -> EnableWindow(FALSE);
979 GetDlgItem(IDC_EVENT_SCORE) -> EnableWindow(FALSE);
980 GetDlgItem(IDC_CHAINED) -> EnableWindow(FALSE);
981 GetDlgItem(IDC_CHAIN_DELAY) -> EnableWindow(FALSE);
982 GetDlgItem(IDC_OBJ_TEXT) -> EnableWindow(FALSE);
983 GetDlgItem(IDC_OBJ_KEY_TEXT) -> EnableWindow(FALSE);
984 GetDlgItem(IDC_EVENT_TEAM)->EnableWindow(FALSE);
985
986 UpdateData(FALSE);
987 return;
988 }
989
990 m_team = m_events[cur_event].team;
991
992 m_repeat_count = m_events[cur_event].repeat_count;
993 m_trigger_count = m_events[cur_event].trigger_count;
994 m_interval = m_events[cur_event].interval;
995 m_event_score = m_events[cur_event].score;
996 if (m_events[cur_event].chain_delay >= 0) {
997 m_chained = TRUE;
998 m_chain_delay = m_events[cur_event].chain_delay;
999 GetDlgItem(IDC_CHAIN_DELAY) -> EnableWindow(TRUE);
1000
1001 } else {
1002 m_chained = FALSE;
1003 m_chain_delay = 0;
1004 GetDlgItem(IDC_CHAIN_DELAY) -> EnableWindow(FALSE);
1005 }
1006
1007 if (m_events[cur_event].objective_text){
1008 m_obj_text = m_events[cur_event].objective_text;
1009 } else {
1010 m_obj_text.Empty();
1011 }
1012
1013 if (m_events[cur_event].objective_key_text){
1014 m_obj_key_text = m_events[cur_event].objective_key_text;
1015 } else {
1016 m_obj_key_text.Empty();
1017 }
1018
1019 GetDlgItem(IDC_REPEAT_COUNT)->EnableWindow(TRUE);
1020 GetDlgItem(IDC_TRIGGER_COUNT)->EnableWindow(TRUE);
1021
1022 if (( m_repeat_count <= 1) && (m_trigger_count <= 1)) {
1023 m_interval = 1;
1024 GetDlgItem(IDC_INTERVAL_TIME) -> EnableWindow(FALSE);
1025 } else {
1026 GetDlgItem(IDC_INTERVAL_TIME) -> EnableWindow(TRUE);
1027 }
1028
1029 GetDlgItem(IDC_EVENT_SCORE) -> EnableWindow(TRUE);
1030 GetDlgItem(IDC_CHAINED) -> EnableWindow(TRUE);
1031 GetDlgItem(IDC_OBJ_TEXT) -> EnableWindow(TRUE);
1032 GetDlgItem(IDC_OBJ_KEY_TEXT) -> EnableWindow(TRUE);
1033 GetDlgItem(IDC_EVENT_TEAM)->EnableWindow(FALSE);
1034 if ( The_mission.game_type & MISSION_TYPE_MULTI_TEAMS ){
1035 GetDlgItem(IDC_EVENT_TEAM)->EnableWindow(TRUE);
1036 }
1037
1038 // handle event log flags
1039 if (m_events[cur_event].mission_log_flags & MLF_SEXP_TRUE) {
1040 m_log_true = TRUE;
1041 }else {
1042 m_log_true = FALSE;
1043 }
1044 if (m_events[cur_event].mission_log_flags & MLF_SEXP_FALSE) {
1045 m_log_false = TRUE;
1046 }else {
1047 m_log_false = FALSE;
1048 }
1049 if (m_events[cur_event].mission_log_flags & MLF_SEXP_KNOWN_FALSE) {
1050 m_log_always_false = TRUE;
1051 }else {
1052 m_log_always_false = FALSE;
1053 }
1054 if (m_events[cur_event].mission_log_flags & MLF_FIRST_REPEAT_ONLY) {
1055 m_log_1st_repeat = TRUE;
1056 }else {
1057 m_log_1st_repeat = FALSE;
1058 }
1059 if (m_events[cur_event].mission_log_flags & MLF_LAST_REPEAT_ONLY) {
1060 m_log_last_repeat = TRUE;
1061 }else {
1062 m_log_last_repeat = FALSE;
1063 }
1064 if (m_events[cur_event].mission_log_flags & MLF_FIRST_TRIGGER_ONLY) {
1065 m_log_1st_trigger = TRUE;
1066 }else {
1067 m_log_1st_trigger = FALSE;
1068 }
1069 if (m_events[cur_event].mission_log_flags & MLF_LAST_TRIGGER_ONLY) {
1070 m_log_last_trigger = TRUE;
1071 }else {
1072 m_log_last_trigger = FALSE;
1073 }
1074 if (m_events[cur_event].mission_log_flags & MLF_STATE_CHANGE) {
1075 m_log_state_change = TRUE;
1076 }else {
1077 m_log_state_change = FALSE;
1078 }
1079
1080 UpdateData(FALSE);
1081 }
1082
OnUpdateRepeatCount()1083 void event_editor::OnUpdateRepeatCount()
1084 {
1085 char buf[128];
1086 int count = 128;
1087 GetDlgItem(IDC_REPEAT_COUNT)->GetWindowText(buf, count);
1088 m_repeat_count = atoi(buf);
1089
1090 if ( ( m_repeat_count <= 1) && (m_trigger_count <= 1) ){
1091 GetDlgItem(IDC_INTERVAL_TIME)->EnableWindow(FALSE);
1092 } else {
1093 GetDlgItem(IDC_INTERVAL_TIME)->EnableWindow(TRUE);
1094 }
1095 }
1096
OnUpdateTriggerCount()1097 void event_editor::OnUpdateTriggerCount()
1098 {
1099 char buf[128];
1100 int count = 128;
1101
1102 GetDlgItem(IDC_TRIGGER_COUNT)->GetWindowText(buf, count);
1103 m_trigger_count = atoi(buf);
1104
1105 if ( ( m_repeat_count <= 1) && (m_trigger_count <= 1) ){
1106 GetDlgItem(IDC_INTERVAL_TIME)->EnableWindow(FALSE);
1107 } else {
1108 GetDlgItem(IDC_INTERVAL_TIME)->EnableWindow(TRUE);
1109 }
1110 }
swap_handler(int node1,int node2)1111 void event_editor::swap_handler(int node1, int node2)
1112 {
1113 int index1, index2;
1114 mission_event m;
1115
1116 save();
1117 for (index1=0; index1<m_num_events; index1++){
1118 if (m_events[index1].formula == node1){
1119 break;
1120 }
1121 }
1122
1123 Assert(index1 < m_num_events);
1124 for (index2=0; index2<m_num_events; index2++){
1125 if (m_events[index2].formula == node2){
1126 break;
1127 }
1128 }
1129
1130 Assert(index2 < m_num_events);
1131 m = m_events[index1];
1132 // m_events[index1] = m_events[index2];
1133 while (index1 < index2) {
1134 m_events[index1] = m_events[index1 + 1];
1135 m_sig[index1] = m_sig[index1 + 1];
1136 index1++;
1137 }
1138
1139 while (index1 > index2 + 1) {
1140 m_events[index1] = m_events[index1 - 1];
1141 m_sig[index1] = m_sig[index1 - 1];
1142 index1--;
1143 }
1144
1145 m_events[index1] = m;
1146 cur_event = index1;
1147 update_cur_event();
1148 }
1149
OnChained()1150 void event_editor::OnChained()
1151 {
1152 int image;
1153 HTREEITEM h;
1154
1155 UpdateData(TRUE);
1156 if (m_chained) {
1157 GetDlgItem(IDC_CHAIN_DELAY) -> EnableWindow(TRUE);
1158 if (m_obj_text.IsEmpty()) {
1159 image = BITMAP_CHAIN;
1160 } else {
1161 image = BITMAP_CHAIN_DIRECTIVE;
1162 }
1163 } else {
1164 GetDlgItem(IDC_CHAIN_DELAY) -> EnableWindow(FALSE);
1165 if (m_obj_text.IsEmpty()) {
1166 image = BITMAP_ROOT;
1167 } else {
1168 image = BITMAP_ROOT_DIRECTIVE;
1169 }
1170 }
1171
1172 h = m_event_tree.GetRootItem();
1173 while (h) {
1174 if ((int) m_event_tree.GetItemData(h) == m_events[cur_event].formula) {
1175 m_event_tree.SetItemImage(h, image, image);
1176 return;
1177 }
1178
1179 h = m_event_tree.GetNextSiblingItem(h);
1180 }
1181 }
1182
OnSelchangeMessageList()1183 void event_editor::OnSelchangeMessageList()
1184 {
1185 static int flag = 0;
1186
1187 if (flag)
1188 return;
1189 /*
1190 if (save_message(m_cur_msg)) {
1191 flag = 1;
1192 ((CListBox *) GetDlgItem(IDC_MESSAGE_LIST)) -> SetCurSel(old);
1193 m_cur_msg = old;
1194 flag = 0;
1195 return;
1196 }*/
1197
1198 save();
1199 update_cur_message();
1200 }
1201
save_message(int num)1202 int event_editor::save_message(int num)
1203 {
1204 char *ptr;
1205 int i, conflict = 0;
1206 CListBox *list;
1207
1208 UpdateData(TRUE);
1209 if (num >= 0) {
1210 ptr = (char *) (LPCTSTR) m_message_name;
1211 for (i=0; i<Num_builtin_messages; i++){
1212 if (!stricmp(m_message_name, Messages[i].name)) {
1213 conflict = 1;
1214 break;
1215 }
1216 }
1217
1218 for (i=0; i<m_num_messages; i++){
1219 if ((i != num) && (!stricmp(m_message_name, m_messages[i].name))) {
1220 conflict = 1;
1221 break;
1222 }
1223 }
1224
1225 if (!conflict) { // update name if no conflicts, otherwise keep old name
1226 string_copy(m_messages[num].name, m_message_name, NAME_LENGTH - 1);
1227
1228 list = (CListBox *) GetDlgItem(IDC_MESSAGE_LIST);
1229 list->DeleteString(num);
1230 list->InsertString(num, m_message_name);
1231 }
1232
1233 string_copy(m_messages[num].message, m_message_text, MESSAGE_LENGTH - 1);
1234 lcl_fred_replace_stuff(m_messages[num].message, MESSAGE_LENGTH - 1);
1235 if (m_messages[num].avi_info.name){
1236 free(m_messages[num].avi_info.name);
1237 }
1238
1239 ptr = (char *) (LPCTSTR) m_avi_filename;
1240 if ( !ptr || !VALID_FNAME(ptr) ) {
1241 m_messages[num].avi_info.name = NULL;
1242 } else {
1243 m_messages[num].avi_info.name = strdup(ptr);
1244 }
1245
1246 if (m_messages[num].wave_info.name){
1247 free(m_messages[num].wave_info.name);
1248 }
1249
1250 ptr = (char *) (LPCTSTR) m_wave_filename;
1251 if ( !ptr || !VALID_FNAME(ptr) ) {
1252 m_messages[num].wave_info.name = NULL;
1253 } else {
1254 m_messages[num].wave_info.name = strdup(ptr);
1255 }
1256
1257 // update the persona to the message. We subtract 1 for the "None" at the beginning of the combo
1258 // box list.
1259 m_messages[num].persona_index = m_persona - 1;
1260
1261 if(m_message_team >= MAX_TVT_TEAMS){
1262 m_messages[num].multi_team = -1;
1263 m_message_team = -1;
1264 } else {
1265 m_messages[num].multi_team = m_message_team;
1266 }
1267
1268 // possible TODO: auto-update event tree references to this message if we renamed it.
1269 }
1270
1271 return 0;
1272 }
1273
OnNewMsg()1274 void event_editor::OnNewMsg()
1275 {
1276 MMessage msg;
1277
1278 save();
1279 strcpy_s(msg.name, "<new message>");
1280 ((CListBox *) GetDlgItem(IDC_MESSAGE_LIST))->AddString("<new message>");
1281
1282 strcpy_s(msg.message, "<put description here>");
1283 msg.avi_info.name = NULL;
1284 msg.wave_info.name = NULL;
1285 msg.persona_index = -1;
1286 msg.multi_team = -1;
1287 m_messages.push_back(msg);
1288 m_cur_msg = m_num_messages++;
1289
1290 modified = 1;
1291 update_cur_message();
1292 }
1293
OnDeleteMsg()1294 void event_editor::OnDeleteMsg()
1295 {
1296 char buf[256];
1297
1298 // handle this case somewhat gracefully
1299 Assert((m_cur_msg >= 0) && (m_cur_msg < m_num_messages));
1300 if((m_cur_msg < 0) || (m_cur_msg >= m_num_messages)){
1301 return;
1302 }
1303
1304 if (m_messages[m_cur_msg].avi_info.name){
1305 free(m_messages[m_cur_msg].avi_info.name);
1306 }
1307 if (m_messages[m_cur_msg].wave_info.name){
1308 free(m_messages[m_cur_msg].wave_info.name);
1309 }
1310
1311 ((CListBox *) GetDlgItem(IDC_MESSAGE_LIST))->DeleteString(m_cur_msg);
1312 sprintf(buf, "<%s>", m_messages[m_cur_msg].name);
1313 update_sexp_references(m_messages[m_cur_msg].name, buf, OPF_MESSAGE);
1314 update_sexp_references(m_messages[m_cur_msg].name, buf, OPF_MESSAGE_OR_STRING);
1315
1316 m_messages.erase(m_messages.begin() + m_cur_msg);
1317
1318 m_num_messages--;
1319 if (m_cur_msg >= m_num_messages){
1320 m_cur_msg = m_num_messages - 1;
1321 }
1322
1323 GetDlgItem(IDC_NEW_MSG)->EnableWindow(TRUE);
1324 modified = 1;
1325 update_cur_message();
1326 }
1327
OnBrowseAvi()1328 void event_editor::OnBrowseAvi()
1329 {
1330 int z;
1331 CString name;
1332
1333 UpdateData(TRUE);
1334 if (!stricmp(m_avi_filename, "<None>"))
1335 m_avi_filename = _T("");
1336
1337 z = cfile_push_chdir(CF_TYPE_INTERFACE);
1338 CFileDialog dlg(TRUE, "ani", m_avi_filename, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR,
1339 "Ani Files (*.ani)|*.ani|Eff Files (*.eff)|*.eff|Avi Files (*.avi)|*.avi|Both (*.ani, *.avi)|*.ani;*.avi||");
1340
1341 if (dlg.DoModal() == IDOK) {
1342 m_avi_filename = dlg.GetFileName();
1343 UpdateData(FALSE);
1344 modified = 1;
1345 }
1346
1347 if (!z)
1348 cfile_pop_dir();
1349 }
1350
OnBrowseWave()1351 void event_editor::OnBrowseWave()
1352 {
1353 int z;
1354 CString name;
1355
1356 audiostream_close_file(m_wave_id, 0);
1357 m_wave_id = -1;
1358
1359 UpdateData(TRUE);
1360 if (!stricmp(m_wave_filename, "<None>"))
1361 m_wave_filename = _T("");
1362
1363 if (The_mission.game_type & MISSION_TYPE_TRAINING)
1364 z = cfile_push_chdir(CF_TYPE_VOICE_TRAINING);
1365 else
1366 z = cfile_push_chdir(CF_TYPE_VOICE_SPECIAL);
1367
1368 CFileDialog dlg(TRUE, "wav", m_wave_filename, OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR,
1369 "Voice Files (*.ogg, *.wav)|*.ogg;*.wav|Ogg Vorbis Files (*.ogg)|*.ogg|Wave Files (*.wav)|*.wav||");
1370
1371 if (dlg.DoModal() == IDOK) {
1372 m_wave_filename = dlg.GetFileName();
1373 update_persona();
1374 }
1375
1376 if (!z){
1377 cfile_pop_dir();
1378 }
1379 }
1380
current_message_name(int i)1381 char *event_editor::current_message_name(int i)
1382 {
1383 if ( (i < 0) || (i >= m_num_messages) ){
1384 return NULL;
1385 }
1386
1387 return m_messages[i].name;
1388 }
1389
get_message_list_item(int i)1390 char *event_editor::get_message_list_item(int i)
1391 {
1392 return m_messages[i].name;
1393 }
1394
update_persona()1395 void event_editor::update_persona()
1396 {
1397 int i, mask;
1398
1399 if ((m_wave_filename[0] >= '1') && (m_wave_filename[0] <= '9') && (m_wave_filename[1] == '_') ) {
1400 i = m_wave_filename[0] - '1';
1401 if ( (i < Num_personas) && (Personas[i].flags & PERSONA_FLAG_WINGMAN) ) {
1402 m_persona = i + 1;
1403 if ((m_persona==1) || (m_persona==2))
1404 m_avi_filename = "HEAD-TP1";
1405 else if ((m_persona==3) || (m_persona==4))
1406 m_avi_filename = "HEAD-TP2";
1407 else if ((m_persona==5))
1408 m_avi_filename = "HEAD-TP3";
1409 else if ((m_persona==6))
1410 m_avi_filename = "HEAD-VP1";
1411 }
1412 } else {
1413 mask = 0;
1414 if (!strnicmp(m_wave_filename, "S_", 2)) {
1415 mask = PERSONA_FLAG_SUPPORT;
1416 m_avi_filename = "HEAD-CM1";
1417 }
1418 else if (!strnicmp(m_wave_filename, "L_", 2)) {
1419 mask = PERSONA_FLAG_LARGE;
1420 m_avi_filename = "HEAD-CM1";
1421 }
1422 else if (!strnicmp(m_wave_filename, "TC_", 3)) {
1423 mask = PERSONA_FLAG_COMMAND;
1424 m_avi_filename = "HEAD-CM1";
1425 }
1426
1427 for (i=0; i<Num_personas; i++)
1428 if (Personas[i].flags & mask)
1429 m_persona = i + 1;
1430 }
1431 //GetDlgItem(IDC_ANI_FILENAME)->SetWindowText(m_avi_filename);
1432 UpdateData(FALSE);
1433 modified = 1;
1434 }
1435
OnSelchangeWaveFilename()1436 void event_editor::OnSelchangeWaveFilename()
1437 {
1438 int z;
1439 CComboBox *box;
1440
1441 audiostream_close_file(m_wave_id, 0);
1442 m_wave_id = -1;
1443
1444 box = (CComboBox *) GetDlgItem(IDC_WAVE_FILENAME);
1445 z = box -> GetCurSel();
1446 UpdateData(TRUE);
1447 UpdateData(TRUE);
1448
1449 box -> GetLBText(z, m_wave_filename);
1450 UpdateData(FALSE);
1451 update_persona();
1452 }
1453
DestroyWindow()1454 BOOL event_editor::DestroyWindow()
1455 {
1456 audiostream_close_file(m_wave_id, 0);
1457 m_wave_id = -1;
1458
1459 m_play_bm.DeleteObject();
1460 return CDialog::DestroyWindow();
1461 }
1462
OnPlay()1463 void event_editor::OnPlay()
1464 {
1465 GetDlgItem(IDC_WAVE_FILENAME)->GetWindowText(m_wave_filename);
1466
1467 if (m_wave_id >= 0) {
1468 audiostream_close_file(m_wave_id, 0);
1469 m_wave_id = -1;
1470 return;
1471 }
1472
1473 // we use ASF_EVENTMUSIC here so that it will keep the extension in place
1474 m_wave_id = audiostream_open((char *)(LPCSTR) m_wave_filename, ASF_EVENTMUSIC);
1475
1476 if (m_wave_id >= 0) {
1477 audiostream_play(m_wave_id, 1.0f, 0);
1478 }
1479 }
1480
OnUpdate()1481 void event_editor::OnUpdate()
1482 {
1483 // GetDlgItem(IDC_WAVE_FILENAME)->GetWindowText(m_wave_filename);
1484 UpdateData(TRUE);
1485 update_persona();
1486 }
1487
1488 // code when the "team" selection in the combo box changes
OnSelchangeTeam()1489 void event_editor::OnSelchangeTeam()
1490 {
1491 if ( cur_event < 0 ){
1492 return;
1493 }
1494
1495 UpdateData(TRUE);
1496
1497 // If the team isn't valid mark it as such.
1498 if((m_team >= MAX_TVT_TEAMS) || (m_team < -1) ){
1499 m_team = -1;
1500 }
1501
1502 m_events[cur_event].team = m_team;
1503 }
1504
1505 // code when the "team" selection in the combo box changes
OnSelchangeMessageTeam()1506 void event_editor::OnSelchangeMessageTeam()
1507 {
1508 if ( m_cur_msg < 0 ){
1509 return;
1510 }
1511
1512 UpdateData(TRUE);
1513
1514 // If the team isn't valid mark it as such.
1515 if((m_message_team>= MAX_TVT_TEAMS) || (m_message_team < -1) ) {
1516 m_message_team = -1;
1517 }
1518
1519 m_messages[m_cur_msg].multi_team = m_message_team;
1520 }
1521
1522 // Cycles among sexp nodes with message text
OnDblclkMessageList()1523 void event_editor::OnDblclkMessageList()
1524 {
1525 CListBox *list = (CListBox*) GetDlgItem(IDC_MESSAGE_LIST);
1526 int num_messages;
1527 int message_nodes[MAX_SEARCH_MESSAGE_DEPTH];
1528
1529 // get current message index and message name
1530 int cur_index = list->GetCurSel();
1531
1532 // check if message name is in event tree
1533 char buffer[256];
1534 list->GetText(cur_index, buffer);
1535
1536
1537 num_messages = m_event_tree.find_text(buffer, message_nodes);
1538
1539 if (num_messages == 0) {
1540 char message[256];
1541 sprintf(message, "No events using message '%s'", buffer);
1542 MessageBox(message);
1543 } else {
1544 // find last message_node
1545 if (m_last_message_node == -1) {
1546 m_last_message_node = message_nodes[0];
1547 } else {
1548
1549 if (num_messages == 1) {
1550 // only 1 message
1551 m_last_message_node = message_nodes[0];
1552 } else {
1553 // find which message and go to next message
1554 int found_pos = -1;
1555 for (int i=0; i<num_messages; i++) {
1556 if (message_nodes[i] == m_last_message_node) {
1557 found_pos = i;
1558 break;
1559 }
1560 }
1561
1562 if (found_pos == -1) {
1563 // no previous message
1564 m_last_message_node = message_nodes[0];
1565 } else if (found_pos == num_messages-1) {
1566 // cycle back to start
1567 m_last_message_node = message_nodes[0];
1568 } else {
1569 // go to next
1570 m_last_message_node = message_nodes[found_pos+1];
1571 }
1572 }
1573 }
1574
1575 // highlight next
1576 m_event_tree.hilite_item(m_last_message_node);
1577 }
1578 }
1579