1 // VoiceActingManager.cpp : implementation file
2 //
3
4 #include "stdafx.h"
5 #include <string.h>
6 #include "fred.h"
7 #include "freddoc.h"
8 #include "VoiceActingManager.h"
9 #include "missionui/missioncmdbrief.h"
10 #include "mission/missionbriefcommon.h"
11 #include "mission/missionmessage.h"
12 #include "mission/missiongoals.h"
13 #include "hud/hudtarget.h"
14 #include "parse/sexp.h"
15 #include "iff_defs/iff_defs.h"
16 #include "mission/missiongoals.h"
17 #include <math.h>
18
19 #ifdef _DEBUG
20 #undef THIS_FILE
21 static char THIS_FILE[] = __FILE__;
22 #endif
23
24 #define INVALID_MESSAGE ((MMessage*)SIZE_T_MAX)
25
26 // to keep track of data
27 char Voice_abbrev_briefing[NAME_LENGTH];
28 char Voice_abbrev_campaign[NAME_LENGTH];
29 char Voice_abbrev_command_briefing[NAME_LENGTH];
30 char Voice_abbrev_debriefing[NAME_LENGTH];
31 char Voice_abbrev_message[NAME_LENGTH];
32 char Voice_abbrev_mission[NAME_LENGTH];
33 bool Voice_no_replace_filenames;
34 char Voice_script_entry_format[NOTES_LENGTH];
35 int Voice_export_selection;
36 bool Voice_group_messages;
37
38
39 /////////////////////////////////////////////////////////////////////////////
40 // VoiceActingManager dialog
41
42
VoiceActingManager(CWnd * pParent)43 VoiceActingManager::VoiceActingManager(CWnd* pParent /*=NULL*/)
44 : CDialog(VoiceActingManager::IDD, pParent)
45 {
46 //{{AFX_DATA_INIT(VoiceActingManager)
47 m_abbrev_briefing = _T("");
48 m_abbrev_campaign = _T("");
49 m_abbrev_command_briefing = _T("");
50 m_abbrev_debriefing = _T("");
51 m_abbrev_message = _T("");
52 m_abbrev_mission = _T("");
53 m_use_sender_in_filename = FALSE;
54 m_example = _T("");
55 m_no_replace = FALSE;
56 m_script_entry_format = _T("");
57 m_export_everything = FALSE;
58 m_export_command_briefings = FALSE;
59 m_export_briefings = FALSE;
60 m_export_debriefings = FALSE;
61 m_export_messages = FALSE;
62 m_group_messages = FALSE;
63 //}}AFX_DATA_INIT
64 }
65
66
DoDataExchange(CDataExchange * pDX)67 void VoiceActingManager::DoDataExchange(CDataExchange* pDX)
68 {
69 CDialog::DoDataExchange(pDX);
70 //{{AFX_DATA_MAP(VoiceActingManager)
71 DDX_Text(pDX, IDC_ABBREV_BRIEFING, m_abbrev_briefing);
72 DDX_Text(pDX, IDC_ABBREV_CAMPAIGN, m_abbrev_campaign);
73 DDX_Text(pDX, IDC_ABBREV_COMMAND_BRIEFING, m_abbrev_command_briefing);
74 DDX_Text(pDX, IDC_ABBREV_DEBRIEFING, m_abbrev_debriefing);
75 DDX_Text(pDX, IDC_ABBREV_MESSAGE, m_abbrev_message);
76 DDX_Text(pDX, IDC_ABBREV_MISSION, m_abbrev_mission);
77 DDX_Text(pDX, IDC_EXAMPLE, m_example);
78 DDX_Check(pDX, IDC_NO_REPLACE, m_no_replace);
79 DDX_Check(pDX, IDC_INCLUDE_SENDER, m_use_sender_in_filename);
80 DDX_Text(pDX, IDC_ENTRY_FORMAT, m_script_entry_format);
81 DDX_Check(pDX, IDC_EXPORT_EVERYTHING, m_export_everything);
82 DDX_Check(pDX, IDC_EXPORT_COMMAND_BRIEFINGS, m_export_command_briefings);
83 DDX_Check(pDX, IDC_EXPORT_BRIEFINGS, m_export_briefings);
84 DDX_Check(pDX, IDC_EXPORT_DEBRIEFINGS, m_export_debriefings);
85 DDX_Check(pDX, IDC_EXPORT_MESSAGES, m_export_messages);
86 DDX_Check(pDX, IDC_GROUP_MESSAGES, m_group_messages);
87 //}}AFX_DATA_MAP
88 }
89
90
BEGIN_MESSAGE_MAP(VoiceActingManager,CDialog)91 BEGIN_MESSAGE_MAP(VoiceActingManager, CDialog)
92 //{{AFX_MSG_MAP(VoiceActingManager)
93 ON_WM_CLOSE()
94 ON_EN_SETFOCUS(IDC_ABBREV_BRIEFING, OnSetfocusAbbrevBriefing)
95 ON_EN_SETFOCUS(IDC_ABBREV_CAMPAIGN, OnSetfocusAbbrevCampaign)
96 ON_EN_SETFOCUS(IDC_ABBREV_COMMAND_BRIEFING, OnSetfocusAbbrevCommandBriefing)
97 ON_EN_SETFOCUS(IDC_ABBREV_DEBRIEFING, OnSetfocusAbbrevDebriefing)
98 ON_EN_SETFOCUS(IDC_ABBREV_MESSAGE, OnSetfocusAbbrevMessage)
99 ON_EN_SETFOCUS(IDC_ABBREV_MISSION, OnSetfocusAbbrevMission)
100 ON_CBN_SETFOCUS(IDC_SUFFIX, OnSetfocusSuffix)
101 ON_EN_CHANGE(IDC_ABBREV_BRIEFING, OnChangeAbbrevBriefing)
102 ON_EN_CHANGE(IDC_ABBREV_CAMPAIGN, OnChangeAbbrevCampaign)
103 ON_EN_CHANGE(IDC_ABBREV_COMMAND_BRIEFING, OnChangeAbbrevCommandBriefing)
104 ON_EN_CHANGE(IDC_ABBREV_DEBRIEFING, OnChangeAbbrevDebriefing)
105 ON_EN_CHANGE(IDC_ABBREV_MESSAGE, OnChangeAbbrevMessage)
106 ON_EN_CHANGE(IDC_ABBREV_MISSION, OnChangeAbbrevMission)
107 ON_CBN_SELCHANGE(IDC_SUFFIX, OnChangeOtherSuffix)
108 ON_BN_CLICKED(IDC_NO_REPLACE, OnChangeNoReplace)
109 ON_BN_CLICKED(IDC_GENERATE_FILE_NAMES, OnGenerateFileNames)
110 ON_BN_CLICKED(IDC_GENERATE_SCRIPT, OnGenerateScript)
111 ON_BN_CLICKED(IDC_EXPORT_EVERYTHING, OnExportEverything)
112 ON_BN_CLICKED(IDC_EXPORT_COMMAND_BRIEFINGS, OnExportCommandBriefings)
113 ON_BN_CLICKED(IDC_EXPORT_BRIEFINGS, OnExportBriefings)
114 ON_BN_CLICKED(IDC_EXPORT_DEBRIEFINGS, OnExportDebriefings)
115 ON_BN_CLICKED(IDC_EXPORT_MESSAGES, OnExportMessages)
116 ON_BN_CLICKED(IDC_INCLUDE_SENDER, OnBnClickedIncludeSender)
117 //}}AFX_MSG_MAP
118 END_MESSAGE_MAP()
119
120 /////////////////////////////////////////////////////////////////////////////
121 // VoiceActingManager message handlers
122
123 BOOL VoiceActingManager::OnInitDialog()
124 {
125 CComboBox *box = ((CComboBox *) GetDlgItem(IDC_SUFFIX));
126 box->AddString(".WAV");
127 box->AddString(".OGG");
128 box->SetCurSel(0);
129
130 // load saved data for file names
131 m_abbrev_briefing = _T(Voice_abbrev_briefing);
132 m_abbrev_campaign = _T(Voice_abbrev_campaign);
133 m_abbrev_command_briefing = _T(Voice_abbrev_command_briefing);
134 m_abbrev_debriefing = _T(Voice_abbrev_debriefing);
135 m_abbrev_message = _T(Voice_abbrev_message);
136 m_abbrev_mission = _T(Voice_abbrev_mission);
137 m_no_replace = Voice_no_replace_filenames;
138
139 // load saved data for script
140 m_script_entry_format = _T(Voice_script_entry_format);
141 m_export_everything = m_export_command_briefings = m_export_briefings = m_export_debriefings = m_export_messages = FALSE;
142 if (Voice_export_selection == 1)
143 m_export_command_briefings = TRUE;
144 else if (Voice_export_selection == 2)
145 m_export_briefings = TRUE;
146 else if (Voice_export_selection == 3)
147 m_export_debriefings = TRUE;
148 else if (Voice_export_selection == 4)
149 m_export_messages = TRUE;
150 else
151 m_export_everything = TRUE;
152 m_group_messages = Voice_group_messages;
153
154 CButton *button = ((CButton *) GetDlgItem(IDC_GROUP_MESSAGES));
155 button->EnableWindow(m_export_everything || m_export_messages);
156
157 UpdateData(FALSE);
158
159 return TRUE;
160 }
161
OnClose()162 void VoiceActingManager::OnClose()
163 {
164 UpdateData(TRUE);
165
166 // save data for file names
167 strcpy_s(Voice_abbrev_briefing, m_abbrev_briefing);
168 strcpy_s(Voice_abbrev_campaign, m_abbrev_campaign);
169 strcpy_s(Voice_abbrev_command_briefing, m_abbrev_command_briefing);
170 strcpy_s(Voice_abbrev_debriefing, m_abbrev_debriefing);
171 strcpy_s(Voice_abbrev_message, m_abbrev_message);
172 strcpy_s(Voice_abbrev_mission, m_abbrev_mission);
173 Voice_no_replace_filenames = (m_no_replace == TRUE) ? true : false;
174
175 // save data for script
176 strcpy_s(Voice_script_entry_format, m_script_entry_format);
177 if (m_export_command_briefings)
178 Voice_export_selection = 1;
179 else if (m_export_briefings)
180 Voice_export_selection = 2;
181 else if (m_export_debriefings)
182 Voice_export_selection = 3;
183 else if (m_export_messages)
184 Voice_export_selection = 4;
185 else
186 Voice_export_selection = 0;
187 Voice_group_messages = (m_group_messages == TRUE) ? true : false;
188
189 CDialog::OnClose();
190 }
191
get_suffix()192 CString VoiceActingManager::get_suffix()
193 {
194 // assign suffix
195 if (((CComboBox *) GetDlgItem(IDC_SUFFIX))->GetCurSel() == 1)
196 return ".ogg";
197 else
198 return ".wav";
199 }
200
calc_digits(int size)201 int VoiceActingManager::calc_digits(int size)
202 {
203 if (size >= 10000)
204 return 5;
205 else if (size >= 1000) // I hope we never hit this!
206 return 4;
207 else if (size >= 100)
208 return 3;
209 else
210 return 2;
211 }
212
build_example()213 void VoiceActingManager::build_example()
214 {
215 // pick a default
216
217 if (m_abbrev_command_briefing != "")
218 build_example(m_abbrev_command_briefing);
219 else if (m_abbrev_briefing != "")
220 build_example(m_abbrev_briefing);
221 else if (m_abbrev_debriefing != "")
222 build_example(m_abbrev_debriefing);
223 else if (m_abbrev_message != "")
224 build_example(m_abbrev_message);
225 else
226 build_example("");
227 }
228
build_example(CString section)229 void VoiceActingManager::build_example(CString section)
230 {
231 if (section == "")
232 {
233 m_example = "";
234 return;
235 }
236
237 m_example = generate_filename(section, 1, 2, INVALID_MESSAGE);
238 }
239
generate_filename(CString section,int number,int digits,MMessage * message)240 CString VoiceActingManager::generate_filename(CString section, int number, int digits, MMessage *message)
241 {
242 if (section == "")
243 return "none.wav";
244
245 int i;
246 CString str = "";
247 CString num;
248
249 // build prefix
250 if (m_abbrev_campaign != "")
251 str = str + m_abbrev_campaign;
252 if (m_abbrev_mission != "")
253 str = str + m_abbrev_mission;
254 str = str + section;
255
256 // build number
257 num.Format("%d", number);;
258 digits -= num.GetLength();
259 for (i = 0; i < digits; i++)
260 {
261 num = "0" + num;
262 }
263 str = str + num;
264
265
266 const CString suffix = get_suffix();
267 // append sender name if supposed to and I have been passed a message
268 // to get the sender from
269 if ( message != NULL && m_use_sender_in_filename ) {
270 size_t allow_to_copy = NAME_LENGTH - suffix.GetLength() - str.GetLength();
271 char sender[NAME_LENGTH];
272 if ( message == INVALID_MESSAGE ) {
273 strcpy_s(sender, "Alpha 1");
274 } else {
275 get_valid_sender(sender, sizeof(sender), message);
276 }
277
278 // truncate sender to that we don't overflow filename
279 sender[allow_to_copy] = '\0';
280 size_t j;
281 for( j = 0; sender[j] != '\0'; j++ ) {
282 // lower case letter
283 sender[j] = SCP_tolower(sender[j]);
284
285 // replace any non alpha numeric with a underscore
286 if ( !isalnum( sender[j] ) )
287 sender[j] = '_';
288 }
289
290 // flatten muliple underscores
291 j = 1;
292 while( sender[j] != '\0' ) {
293 if ( sender[j-1] == '_' && sender[j] == '_' ) {
294 size_t k;
295 for (k = j + 1; sender[k] != '\0'; k++ )
296 sender[k - 1] = sender[k];
297 sender[k - 1] = '\0';
298 } else {
299 // only increment on rounds when I am not moving the string down
300 j++;
301 }
302 }
303 str = str + sender;
304 }
305
306 // suffix
307 str = str + get_suffix();
308
309 Assert( str.GetLength() < NAME_LENGTH );
310
311 return str;
312 }
313
OnGenerateFileNames()314 void VoiceActingManager::OnGenerateFileNames()
315 {
316 int i;
317 int digits;
318 size_t modified_filenames = 0;
319
320 // stuff data to variables
321 UpdateData(TRUE);
322
323 // command briefings
324 digits = calc_digits(Cmd_briefs[0].num_stages);
325 for (i = 0; i < Cmd_briefs[0].num_stages; i++)
326 {
327 char *filename = Cmd_briefs[0].stage[i].wave_filename;
328
329 // generate only if we're replacing or if it has a replaceable name
330 if (!m_no_replace || !strlen(filename) || message_filename_is_generic(filename))
331 {
332 strcpy(filename, LPCTSTR(generate_filename(m_abbrev_command_briefing, i + 1, digits)));
333 modified_filenames++;
334 }
335 }
336
337 // briefings
338 digits = calc_digits(Briefings[0].num_stages);
339 for (i = 0; i < Briefings[0].num_stages; i++)
340 {
341 char *filename = Briefings[0].stages[i].voice;
342
343 // generate only if we're replacing or if it has a replaceable name
344 if (!m_no_replace || !strlen(filename) || message_filename_is_generic(filename))
345 {
346 strcpy(filename, LPCTSTR(generate_filename(m_abbrev_briefing, i + 1, digits)));
347 modified_filenames++;
348 }
349 }
350
351 // debriefings
352 digits = calc_digits(Debriefings[0].num_stages);
353 for (i = 0; i < Debriefings[0].num_stages; i++)
354 {
355 char *filename = Debriefings[0].stages[i].voice;
356
357 // generate only if we're replacing or if it has a replaceable name
358 if (!m_no_replace || !strlen(filename) || message_filename_is_generic(filename))
359 {
360 strcpy(filename, LPCTSTR(generate_filename(m_abbrev_debriefing, i + 1, digits)));
361 modified_filenames++;
362 }
363 }
364
365 // messages
366 digits = calc_digits(Num_messages - Num_builtin_messages);
367 for (i = 0; i < Num_messages - Num_builtin_messages; i++)
368 {
369 char *filename = Messages[i + Num_builtin_messages].wave_info.name;
370 MMessage *message = &Messages[i + Num_builtin_messages];
371
372 // generate only if we're replacing or if it has a replaceable name
373 if (!m_no_replace || !strlen(filename) || message_filename_is_generic(filename))
374 {
375 // free existing filename
376 if (filename != NULL)
377 free(filename);
378
379 // allocate new filename
380 Messages[i + Num_builtin_messages].wave_info.name = strdup(LPCTSTR(generate_filename(m_abbrev_message, i + 1, digits, message)));
381 modified_filenames++;
382 }
383 }
384
385 if ( modified_filenames > 0 ) {
386 // Tell FRED that we actually modified something
387 set_modified(TRUE);
388 }
389
390 // notify user that we are done and how many filenames were changed
391 char message[128] = { '\0' };
392 snprintf(message, sizeof(message)-1, "File name generation complete. Modified " SIZE_T_ARG " messages.", modified_filenames);
393 MessageBox(message, "Woohoo!");
394 }
395
OnGenerateScript()396 void VoiceActingManager::OnGenerateScript()
397 {
398 char pathname[256];
399
400 // stuff data to variables
401 UpdateData(TRUE);
402
403 // prompt to save script
404 CFileDialog dlg(FALSE, "txt", NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "Text files (*.txt)|*.txt||");
405 if (dlg.DoModal() != IDOK)
406 return;
407
408 CString dlgPathName = dlg.GetPathName( );
409 string_copy(pathname, dlgPathName, 256);
410 fp = cfopen(pathname, "wt", CFILE_NORMAL);
411 if (!fp)
412 {
413 MessageBox("Can't open file to save.", "Error!");
414 return;
415 }
416
417 fout("%s\n", Mission_filename);
418 fout("%s\n\n", The_mission.name);
419
420 if (m_export_everything || m_export_command_briefings)
421 {
422 fout("\n\nCommand Briefings\n-----------------\n\n");
423
424 for (int i = 0; i < Cmd_briefs[0].num_stages; i++)
425 {
426 CString entry = m_script_entry_format;
427 entry.Replace("\r\n", "\n");
428
429 cmd_brief_stage *stage = &Cmd_briefs[0].stage[i];
430 entry.Replace("$filename", stage->wave_filename);
431 entry.Replace("$message", stage->text.c_str());
432 entry.Replace("$persona", "<no persona specified>");
433 entry.Replace("$sender", "<no sender specified>");
434
435 fout("%s\n\n\n", (char *) (LPCTSTR) entry);
436 }
437 }
438
439 if (m_export_everything || m_export_briefings)
440 {
441 fout("\n\nBriefings\n---------\n\n");
442
443 for (int i = 0; i < Briefings[0].num_stages; i++)
444 {
445 CString entry = m_script_entry_format;
446 entry.Replace("\r\n", "\n");
447
448 brief_stage *stage = &Briefings[0].stages[i];
449 entry.Replace("$filename", stage->voice);
450 entry.Replace("$message", stage->text.c_str());
451 entry.Replace("$persona", "<no persona specified>");
452 entry.Replace("$sender", "<no sender specified>");
453
454 fout("%s\n\n\n", (char *) (LPCTSTR) entry);
455 }
456 }
457
458 if (m_export_everything || m_export_debriefings)
459 {
460 fout("\n\nDebriefings\n-----------\n\n");
461
462 for (int i = 0; i < Debriefings[0].num_stages; i++)
463 {
464 CString entry = m_script_entry_format;
465 entry.Replace("\r\n", "\n");
466
467 debrief_stage *stage = &Debriefings[0].stages[i];
468 entry.Replace("$filename", stage->voice);
469 entry.Replace("$message", stage->text.c_str());
470 entry.Replace("$persona", "<no persona specified>");
471 entry.Replace("$sender", "<no sender specified>");
472
473 fout("%s\n\n\n", (char *) (LPCTSTR) entry);
474 }
475 }
476
477 if (m_export_everything || m_export_messages)
478 {
479 fout("\n\nMessages\n--------\n\n");
480
481 if (m_group_messages)
482 {
483 SCP_vector<int> message_indexes;
484 for (int i = 0; i < Num_messages - Num_builtin_messages; i++)
485 message_indexes.push_back(i + Num_builtin_messages);
486
487 group_message_indexes(message_indexes);
488
489 for (size_t index = 0; index < message_indexes.size(); index++)
490 {
491 MMessage *message = &Messages[message_indexes[index]];
492 export_one_message(message);
493 }
494 }
495 else
496 {
497 for (int i = 0; i < Num_messages - Num_builtin_messages; i++)
498 {
499 MMessage *message = &Messages[i + Num_builtin_messages];
500 export_one_message(message);
501 }
502 }
503 }
504
505 cfclose(fp);
506
507 // notify
508 MessageBox("Script generation complete.", "Woohoo!");
509 }
510
export_one_message(MMessage * message)511 void VoiceActingManager::export_one_message(MMessage *message)
512 {
513 CString entry = m_script_entry_format;
514 entry.Replace("\r\n", "\n");
515
516 // replace file name
517 entry.Replace("$filename", message->wave_info.name);
518
519 // replace message
520 entry.Replace("$message", message->message);
521
522 // determine and replace persona
523 if (message->persona_index >= 0)
524 entry.Replace("$persona", Personas[message->persona_index].name);
525 else
526 entry.Replace("$persona", "<none>");
527
528 // determine sender
529 char sender[NAME_LENGTH+1];
530 get_valid_sender(sender, sizeof(sender), message);
531
532 // replace sender (but print #Command as Command)
533 if (*sender == '#')
534 entry.Replace("$sender", &sender[1]);
535 else
536 entry.Replace("$sender", sender);
537
538 fout("%s\n\n\n", (char *) (LPCTSTR) entry);
539 }
540
541 /** Passed sender string will have either have the senders name
542 or '\<none\>'*/
get_valid_sender(char * sender,size_t sender_size,MMessage * message)543 void VoiceActingManager::get_valid_sender(char *sender, size_t sender_size, MMessage *message)
544 {
545 Assert( sender != NULL );
546 Assert( message != NULL );
547
548 strncpy(sender, get_message_sender(message->name), sender_size);
549
550 // check if we're overriding #Command
551 if (The_mission.flags[Mission::Mission_Flags::Override_hashcommand] && !strcmp("#Command", sender))
552 {
553 memset(sender, 0, sender_size);
554 strncpy(sender, The_mission.command_sender, sender_size);
555 }
556
557 // strip hash if present
558 if ( sender[0] == '#' ) {
559 size_t i = 1;
560 for(; sender[i] != '\0'; i++ ) {
561 sender[i-1] = sender[i];
562 }
563 sender[i-1] = '\0';
564 }
565
566 int shipnum = ship_name_lookup(sender, 1); // The player's ship is valid for this search.
567
568 if (shipnum >= 0)
569 {
570 ship *shipp = &Ships[shipnum];
571
572 // we may have to use the callsign
573 if (*Fred_callsigns[shipnum])
574 {
575 hud_stuff_ship_callsign(sender, shipp);
576 }
577 // account for hidden ship names
578 else if ( ((Iff_info[shipp->team].flags & IFFF_WING_NAME_HIDDEN) && (shipp->wingnum != -1)) || (shipp->flags[Ship::Ship_Flags::Hide_ship_name]) )
579 {
580 hud_stuff_ship_class(sender, shipp);
581 }
582 // use the regular sender display name
583 else
584 {
585 strncpy(sender, shipp->get_display_name(), NAME_LENGTH);
586 sender[NAME_LENGTH] = 0;
587 }
588 }
589 }
590
OnSetfocusAbbrevBriefing()591 void VoiceActingManager::OnSetfocusAbbrevBriefing()
592 {
593 UpdateData(TRUE);
594
595 build_example(m_abbrev_briefing);
596
597 UpdateData(FALSE);
598 }
599
OnSetfocusAbbrevCampaign()600 void VoiceActingManager::OnSetfocusAbbrevCampaign()
601 {
602 UpdateData(TRUE);
603
604 build_example();
605
606 UpdateData(FALSE);
607 }
608
OnSetfocusAbbrevCommandBriefing()609 void VoiceActingManager::OnSetfocusAbbrevCommandBriefing()
610 {
611 UpdateData(TRUE);
612
613 build_example(m_abbrev_command_briefing);
614
615 UpdateData(FALSE);
616 }
617
OnSetfocusAbbrevDebriefing()618 void VoiceActingManager::OnSetfocusAbbrevDebriefing()
619 {
620 UpdateData(TRUE);
621
622 build_example(m_abbrev_debriefing);
623
624 UpdateData(FALSE);
625 }
626
OnSetfocusAbbrevMessage()627 void VoiceActingManager::OnSetfocusAbbrevMessage()
628 {
629 UpdateData(TRUE);
630
631 build_example(m_abbrev_message);
632
633 UpdateData(FALSE);
634 }
635
OnSetfocusAbbrevMission()636 void VoiceActingManager::OnSetfocusAbbrevMission()
637 {
638 UpdateData(TRUE);
639
640 build_example();
641
642 UpdateData(FALSE);
643 }
644
OnSetfocusSuffix()645 void VoiceActingManager::OnSetfocusSuffix()
646 {
647 UpdateData(TRUE);
648
649 build_example();
650
651 UpdateData(FALSE);
652 }
653
OnChangeAbbrevBriefing()654 void VoiceActingManager::OnChangeAbbrevBriefing()
655 {
656 UpdateData(TRUE);
657
658 build_example(m_abbrev_briefing);
659
660 UpdateData(FALSE);
661 }
662
OnChangeAbbrevCampaign()663 void VoiceActingManager::OnChangeAbbrevCampaign()
664 {
665 UpdateData(TRUE);
666
667 build_example();
668
669 UpdateData(FALSE);
670 }
671
OnChangeAbbrevCommandBriefing()672 void VoiceActingManager::OnChangeAbbrevCommandBriefing()
673 {
674 UpdateData(TRUE);
675
676 build_example(m_abbrev_command_briefing);
677
678 UpdateData(FALSE);
679 }
680
OnChangeAbbrevDebriefing()681 void VoiceActingManager::OnChangeAbbrevDebriefing()
682 {
683 UpdateData(TRUE);
684
685 build_example(m_abbrev_debriefing);
686
687 UpdateData(FALSE);
688 }
689
OnChangeAbbrevMessage()690 void VoiceActingManager::OnChangeAbbrevMessage()
691 {
692 UpdateData(TRUE);
693
694 build_example(m_abbrev_message);
695
696 UpdateData(FALSE);
697 }
698
OnChangeAbbrevMission()699 void VoiceActingManager::OnChangeAbbrevMission()
700 {
701 UpdateData(TRUE);
702
703 build_example();
704
705 UpdateData(FALSE);
706 }
707
OnChangeOtherSuffix()708 void VoiceActingManager::OnChangeOtherSuffix()
709 {
710 UpdateData(TRUE);
711
712 build_example();
713
714 UpdateData(FALSE);
715 }
716
OnChangeNoReplace()717 void VoiceActingManager::OnChangeNoReplace()
718 {
719 UpdateData(TRUE);
720 }
721
fout(char * format,...)722 int VoiceActingManager::fout(char *format, ...)
723 {
724 SCP_string str;
725 va_list args;
726
727 va_start(args, format);
728 vsprintf(str, format, args);
729 va_end(args);
730
731 cfputs(str.c_str(), fp);
732 return 0;
733 }
734
735 // Loops through all the sexps and finds the sender of the specified message. This assumes there is only one possible
736 // sender of the message, which is probably nearly always true (especially for voice-acted missions).
get_message_sender(char * message)737 char *VoiceActingManager::get_message_sender(char *message)
738 {
739 int i;
740
741 for (i = 0; i < Num_sexp_nodes; i++)
742 {
743 if (Sexp_nodes[i].type == SEXP_NOT_USED)
744 continue;
745
746 // stuff
747 int op = get_operator_const(i);
748 int n = CDR(i);
749
750 // find the message sexps
751 if (op == OP_SEND_MESSAGE)
752 {
753 // the first argument is the sender; the third is the message
754 if (!strcmp(message, Sexp_nodes[CDDR(n)].text))
755 return Sexp_nodes[n].text;
756 }
757 else if (op == OP_SEND_MESSAGE_LIST || op == OP_SEND_MESSAGE_CHAIN)
758 {
759 // skip the event argument
760 if (op == OP_SEND_MESSAGE_CHAIN)
761 n = CDR(n);
762
763 // check the argument list
764 while (n != -1)
765 {
766 // as before
767 if (!strcmp(message, Sexp_nodes[CDDR(n)].text))
768 return Sexp_nodes[n].text;
769
770 // iterate along the list
771 n = CDDDDR(n);
772 }
773 }
774 else if (op == OP_SEND_RANDOM_MESSAGE)
775 {
776 // as before, sort of
777 char *sender = Sexp_nodes[n].text;
778
779 // check the argument list
780 n = CDDR(n);
781 while (n != -1)
782 {
783 if (!strcmp(message, Sexp_nodes[n].text))
784 return sender;
785
786 // iterate along the list
787 n = CDR(n);
788 }
789 }
790 else if (op == OP_TRAINING_MSG)
791 {
792 // just check the message
793 if (!strcmp(message, Sexp_nodes[n].text))
794 return "Training Message";
795 }
796 }
797
798 return "<none>";
799 }
800
group_message_indexes(SCP_vector<int> & message_indexes)801 void VoiceActingManager::group_message_indexes(SCP_vector<int> &message_indexes)
802 {
803 #ifndef NDEBUG
804 size_t initial_size = message_indexes.size();
805 #endif
806
807 SCP_vector<int> temp_message_indexes = message_indexes;
808 message_indexes.clear();
809
810 // add all messages found in send-message-list or send-random-message node trees
811 for (int i = 0; i < Num_mission_events; i++)
812 {
813 mission_event *event = &Mission_events[i];
814 group_message_indexes_in_tree(event->formula, temp_message_indexes, message_indexes);
815 }
816
817 // add remaining messages
818 for (size_t index = 0; index < temp_message_indexes.size(); index++)
819 message_indexes.push_back(temp_message_indexes[index]);
820
821 #ifndef NDEBUG
822 if (initial_size > message_indexes.size())
823 {
824 Warning(LOCATION, "Initial size is greater than size after sorting!");
825 }
826 else if (initial_size < message_indexes.size())
827 {
828 Warning(LOCATION, "Initial size is less than size after sorting!");
829 }
830 #endif
831 }
832
group_message_indexes_in_tree(int node,SCP_vector<int> & source_list,SCP_vector<int> & destination_list)833 void VoiceActingManager::group_message_indexes_in_tree(int node, SCP_vector<int> &source_list, SCP_vector<int> &destination_list)
834 {
835 int op, n;
836
837 if (node < 0)
838 return;
839 if (Sexp_nodes[node].type == SEXP_NOT_USED)
840 return;
841
842 // stuff
843 op = get_operator_const(node);
844 n = CDR(node);
845
846 if (op == OP_SEND_MESSAGE_LIST || op == OP_SEND_MESSAGE_CHAIN)
847 {
848 // skip the event argument
849 if (op == OP_SEND_MESSAGE_CHAIN)
850 n = CDR(n);
851
852 // check the argument list
853 while (n != -1)
854 {
855 // the third argument is a message
856 char *message_name = Sexp_nodes[CDDR(n)].text;
857
858 // check source messages
859 for (size_t i = 0; i < source_list.size(); i++)
860 {
861 if (!strcmp(message_name, Messages[source_list[i]].name))
862 {
863 // move it from source to destination
864 destination_list.push_back(source_list[i]);
865 source_list.erase(source_list.begin() + i);
866 break;
867 }
868 }
869
870 // iterate along the list
871 n = CDDDDR(n);
872 }
873 }
874 else if (op == OP_SEND_RANDOM_MESSAGE)
875 {
876 // check the argument list
877 n = CDDR(n);
878 while (n != -1)
879 {
880 // each argument from this point on is a message
881 char *message_name = Sexp_nodes[n].text;
882
883 // check source messages
884 for (size_t i = 0; i < source_list.size(); i++)
885 {
886 if (!strcmp(message_name, Messages[source_list[i]].name))
887 {
888 // move it from source to destination
889 destination_list.push_back(source_list[i]);
890 source_list.erase(source_list.begin() + i);
891 break;
892 }
893 }
894
895 // iterate along the list
896 n = CDR(n);
897 }
898 }
899
900 // iterate on first element
901 group_message_indexes_in_tree(CAR(node), source_list, destination_list);
902
903 // iterate on rest of elements
904 group_message_indexes_in_tree(CDR(node), source_list, destination_list);
905 }
906
OnExportEverything()907 void VoiceActingManager::OnExportEverything()
908 {
909 CButton *button = ((CButton *) GetDlgItem(IDC_GROUP_MESSAGES));
910 button->EnableWindow(TRUE);
911 }
912
OnExportCommandBriefings()913 void VoiceActingManager::OnExportCommandBriefings()
914 {
915 CButton *button = ((CButton *) GetDlgItem(IDC_GROUP_MESSAGES));
916 button->EnableWindow(FALSE);
917 }
918
OnExportBriefings()919 void VoiceActingManager::OnExportBriefings()
920 {
921 CButton *button = ((CButton *) GetDlgItem(IDC_GROUP_MESSAGES));
922 button->EnableWindow(FALSE);
923 }
924
OnExportDebriefings()925 void VoiceActingManager::OnExportDebriefings()
926 {
927 CButton *button = ((CButton *) GetDlgItem(IDC_GROUP_MESSAGES));
928 button->EnableWindow(FALSE);
929 }
930
OnExportMessages()931 void VoiceActingManager::OnExportMessages()
932 {
933 CButton *button = ((CButton *) GetDlgItem(IDC_GROUP_MESSAGES));
934 button->EnableWindow(TRUE);
935 }
936
937
OnBnClickedIncludeSender()938 void VoiceActingManager::OnBnClickedIncludeSender()
939 {
940 UpdateData(TRUE);
941
942 build_example();
943
944 UpdateData(FALSE);
945 }
946