void Window_Message::Update() { Window_Selectable::Update(); number_input_window->Update(); gold_window->Update(); if (pause) { WaitForInput(); } else if (active) { InputChoice(); } else if (number_input_window->GetVisible()) { InputNumber(); } else if (!text.empty()) { // Output the remaining text for the current page UpdateMessage(); } else if (IsNextMessagePossible()) { // Output a new page if (Game_Temp::inn_calling) { ShowGoldWindow(); } StartMessageProcessing(); //printf("Text: %s\n", text.c_str()); if (!visible) { // The MessageBox is not open yet but text output is needed // Open and Close Animations are skipped in battle SetOpenAnimation(Game_Temp::battle_running ? 0 : 5); } else if (closing) { // Cancel closing animation SetOpenAnimation(0); } Game_Message::visible = true; } else if (!Game_Message::message_waiting && Game_Message::visible) { if (visible && !closing) { // Start the closing animation SetCloseAnimation(Game_Temp::battle_running ? 0 : 5); } else if (!visible) { // The closing animation has finished Game_Message::visible = false; Game_Message::owner_id = 0; } } }
void Window_Message::UpdateMessage() { // Message Box Show Message rendering loop // Contains at what frame the sleep is over static int sleep_until = -1; bool instant_speed = false; if (Player::debug_flag && Input::IsPressed(Input::SHIFT)) { sleep_until = -1; instant_speed = true; } if (sleep_until > -1) { if (Player::GetFrames() >= sleep_until) { // Sleep over sleep_until = -1; } else { return; } } int loop_count = 0; int loop_max = speed_table[speed_modifier] == 0 ? 2 : 1; while (instant_speed || loop_count < loop_max) { if (!instant_speed) { // It's assumed that speed_modifier is between 0 and 20 ++speed_frame_counter; if (speed_table[speed_modifier] != 0 && speed_table[speed_modifier] != speed_frame_counter) { break; } speed_frame_counter = 0; } ++loop_count; if (text_index == end) { FinishMessageProcessing(); break; } else if (line_count == 4) { pause = true; new_page_after_pause = true; break; } else if (pause) { break; } if (*text_index == '\n') { if (instant_speed) { // instant_speed stops at the end of the line, unless // there's a /> at the beginning of the next line if (std::distance(text_index, end) > 2 && *(text_index + 1) == escape_char && *(text_index + 2) == '>') { text_index += 2; } else { instant_speed = false; } } InsertNewLine(); } else if (*text_index == '\f') { instant_speed = false; ++text_index; if (*text_index == '\n') { ++text_index; } if (text_index != end) { pause = true; new_page_after_pause = true; } break; } else if (*text_index == escape_char && std::distance(text_index, end) > 1) { // Special message codes ++text_index; int parameter; bool is_valid; switch (tolower(*text_index)) { case 'c': // Color parameter = ParseParameter(is_valid); text_color = parameter > 19 ? 0 : parameter; break; case 's': // Speed modifier parameter = ParseParameter(is_valid); speed_modifier = max(0, min(parameter, 20)); break; case '_': // Insert half size space contents_x += contents->GetFont()->GetSize(" ").width / 2; break; case '$': // Show Gold Window ShowGoldWindow(); break; case '!': // Text pause pause = true; break; case '^': // Force message close // The close happens at the end of the message, not where // the ^ is encountered kill_message = true; break; case '>': // Instant speed start instant_speed = true; break; case '<': // Instant speed stop instant_speed = false; break; case '.': // 1/4 second sleep if (instant_speed) break; sleep_until = Player::GetFrames() + 60 / 4; ++text_index; return; case '|': // Second sleep if (instant_speed) break; sleep_until = Player::GetFrames() + 60; ++text_index; return; case '\n': case '\f': // \ followed by linebreak, don't skip them --text_index; break; default: if (*text_index == escape_char) { // Show Escape Symbol contents->TextDraw(contents_x, contents_y, text_color, Player::escape_symbol); contents_x += contents->GetFont()->GetSize(Player::escape_symbol).width; } } } else if (*text_index == '$' && std::distance(text_index, end) > 1 && std::isalpha(*std::next(text_index))) { // ExFont std::string const glyph(Utils::EncodeUTF(std::u32string(text_index, std::next(text_index, 2)))); contents->TextDraw(contents_x, contents_y, text_color, glyph); contents_x += 12; ++loop_count; ++text_index; } else { std::string const glyph(Utils::EncodeUTF(std::u32string(text_index, std::next(text_index)))); contents->TextDraw(contents_x, contents_y, text_color, glyph); int glyph_width = contents->GetFont()->GetSize(glyph).width; // Show full-width characters twice as slow as half-width characters if (glyph_width >= 12) loop_count++; contents_x += glyph_width; } ++text_index; } }
void Window_Message::UpdateMessage() { // Message Box Show Message rendering loop // Contains at what frame the sleep is over static int sleep_until = -1; bool instant_speed = false; if (Player::debug_flag && Input::IsPressed(Input::SHIFT)) { sleep_until = -1; instant_speed = true; } if (sleep_until > -1) { if (Player::GetFrames() >= sleep_until) { // Sleep over sleep_until = -1; } else { return; } } int loop_count = 0; int loop_max = speed_table[speed_modifier] == 0 ? 2 : 1; while (instant_speed || loop_count < loop_max) { // It's assumed that speed_modifier is between 0 and 20 ++speed_frame_counter; if (speed_table[speed_modifier] != 0 && speed_table[speed_modifier] != speed_frame_counter) { break; } speed_frame_counter = 0; ++loop_count; if (text_index == end) { FinishMessageProcessing(); break; } else if (line_count == 4) { pause = true; new_page_after_pause = true; break; } else if (pause) { break; } if (*text_index == '\n') { instant_speed = false; InsertNewLine(); } else if (*text_index == '\f') { instant_speed = false; ++text_index; if (*text_index == '\n') { ++text_index; } if (text_index != end) { pause = true; new_page_after_pause = true; } break; } else if (*text_index == escape_char && std::distance(text_index, end) > 1) { // Special message codes ++text_index; std::string command_result; switch (tolower(*text_index)) { case 'c': case 'n': case 's': case 'v': // These commands support indirect access via \v[] command_result = ParseCommandCode(); contents->TextDraw(contents_x, contents_y, text_color, command_result); contents_x += contents->GetFont()->GetSize(command_result).width; break; case '_': // Insert half size space contents_x += contents->GetFont()->GetSize(" ").width / 2; break; case '$': // Show Gold Window ShowGoldWindow(); break; case '!': // Text pause pause = true; break; case '^': // Force message close // The close happens at the end of the message, not where // the ^ is encountered kill_message = true; break; case '>': // Instant speed start instant_speed = true; break; case '<': // Instant speed stop instant_speed = false; break; case '.': // 1/4 second sleep sleep_until = Player::GetFrames() + 60 / 4; ++text_index; return; break; case '|': // Second sleep sleep_until = Player::GetFrames() + 60; ++text_index; return; break; default: if (*text_index == escape_char) { // Show Escape Symbol contents->TextDraw(contents_x, contents_y, text_color, Player::escape_symbol); contents_x += contents->GetFont()->GetSize(Player::escape_symbol).width; } } } else if (*text_index == '$' && std::distance(text_index, end) > 1 && std::isalpha(*boost::next(text_index))) { // ExFont contents->TextDraw(contents_x, contents_y, text_color, std::string(text_index.base(), boost::next(text_index, 2).base())); contents_x += 12; ++text_index; } else { std::string const glyph(text_index.base(), boost::next(text_index).base()); contents->TextDraw(contents_x, contents_y, text_color, glyph); contents_x += contents->GetFont()->GetSize(glyph).width; } ++text_index; } loop_count = 0; }