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