funcdef void character_dialog_speak_callback(const string& in message, bool interrupt); string characterDialogSoundPath = "sounds/dialog"; bool characterDialogShowUsageInstructions = true; bool characterDialogUsageInstructionsShown = false; bool characterDialogSoundLoaded = false; sound characterDialogSound; character_dialog_speak_callback @characterDialogSpeakCallback = null; void character_dialog_set_speak_callback(character_dialog_speak_callback @callback) { @characterDialogSpeakCallback = @callback; } void character_dialog_set_sound_path(const string soundPath) { characterDialogSoundPath = soundPath; characterDialogSoundLoaded = false; characterDialogSound.close(); } void character_dialog_set_show_usage_instructions(bool enabled) { characterDialogShowUsageInstructions = enabled; } void character_dialog_reset_usage_instructions() { characterDialogUsageInstructionsShown = false; } void character_dialog_reset() { characterDialogUsageInstructionsShown = false; characterDialogSoundLoaded = false; characterDialogSound.close(); } void character_dialog_speak(const string& in message, bool interrupt) { if (@characterDialogSpeakCallback !is null) { characterDialogSpeakCallback(message, interrupt); return; } screen_reader_speak(message, interrupt); } bool character_dialog_should_skip() { return key_pressed(KEY_ESCAPE) || key_pressed(KEY_AC_BACK); } bool character_dialog_ensure_sound_loaded() { if (characterDialogSoundLoaded) { return true; } characterDialogSound.close(); if (characterDialogSound.load(characterDialogSoundPath)) { characterDialogSoundLoaded = true; return true; } if (characterDialogSound.load(characterDialogSoundPath + ".ogg")) { characterDialogSoundLoaded = true; return true; } if (!characterDialogSound.load(characterDialogSoundPath + ".wav")) { return false; } characterDialogSoundLoaded = true; return true; } bool character_dialog_use_word_sound_sequence() { if (characterDialogSoundPath == "sounds/dialog" || characterDialogSoundPath == "sounds/dialog.ogg" || characterDialogSoundPath == "sounds/dialog.wav") { return true; } return false; } int character_dialog_count_words(const string& in message) { if (message == "") { return 0; } int wordCount = 0; bool inWord = false; for (uint charIndex = 0; charIndex < message.length(); charIndex++) { string character = message.substr(charIndex, 1); bool isWhitespace = character == " " || character == "\t" || character == "\n" || character == "\r"; if (isWhitespace) { inWord = false; continue; } if (!inWord) { wordCount++; inWord = true; } } return wordCount; } bool character_dialog_play_word_sound_sequence(const string& in message) { if (!character_dialog_ensure_sound_loaded()) { return false; } int playCount = 1; if (character_dialog_use_word_sound_sequence()) { playCount = character_dialog_count_words(message); } for (int wordIndex = 0; wordIndex < playCount; wordIndex++) { characterDialogSound.play(); while (characterDialogSound.playing) { wait(5); if (character_dialog_should_skip()) { return true; } } } return false; } bool character_dialog_repeat_requested() { if (key_down(KEY_RETURN) || key_down(KEY_NUMPAD_ENTER) || key_down(KEY_ESCAPE) || key_down(KEY_AC_BACK)) { return false; } return total_keys_down() > 0; } int character_dialog_wait_for_action(const string& in currentLine, bool interrupt) { bool keyHeld = false; while (true) { wait(5); if (character_dialog_should_skip()) { return -1; } if (key_pressed(KEY_RETURN) || key_pressed(KEY_NUMPAD_ENTER)) { return 1; } bool repeatRequested = character_dialog_repeat_requested(); if (repeatRequested) { if (!keyHeld) { character_dialog_speak(currentLine, interrupt); keyHeld = true; } } else { keyHeld = false; } } return -1; } bool character_dialog_show_lines(const string[] @dialogLines, bool interrupt = true) { if (@dialogLines is null || dialogLines.length() == 0) { return true; } for (uint lineIndex = 0; lineIndex < dialogLines.length(); lineIndex++) { string currentLine = dialogLines[lineIndex]; if (currentLine == "") { continue; } if (character_dialog_play_word_sound_sequence(currentLine)) { character_dialog_speak(" ", true); return false; } string displayLine = currentLine; if (characterDialogShowUsageInstructions && !characterDialogUsageInstructionsShown) { displayLine += "\nPress enter to continue, escape to skip, or any other key to repeat."; characterDialogUsageInstructionsShown = true; } character_dialog_speak(displayLine, interrupt); int action = character_dialog_wait_for_action(currentLine, interrupt); if (action < 0) { character_dialog_speak(" ", true); return false; } } character_dialog_speak(" ", true); return true; } void character_dialog_show(const string[] @dialogLines, bool interrupt = true) { /* The orange goblins speak to me in the night, as the moon casts shadows pumpkins come to life! */ character_dialog_show_lines(dialogLines, interrupt); }