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