diff --git a/.gitignore b/.gitignore index 0c6acf0127..1a433e6997 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,4 @@ texture_replacements/* # generated cmake files svnrev.h ci-artifacts/ +out/build/ diff --git a/common/goos/ReplUtils.cpp b/common/goos/ReplUtils.cpp index f6b8b6d6e4..03242bc2f4 100644 --- a/common/goos/ReplUtils.cpp +++ b/common/goos/ReplUtils.cpp @@ -57,13 +57,9 @@ void ReplWrapper::add_to_history(const std::string& line) { } void ReplWrapper::save_history() { - std::filesystem::path path = file_util::get_user_config_dir(); - file_util::create_dir_if_needed(path); - if (exists(path)) { - repl.history_save((path / ".opengoal.repl.history").string()); - } else { - fmt::print("Couldn't save REPL history file to '{}'", path.string()); - } + std::filesystem::path path = file_util::get_user_config_dir() / ".opengoal.repl.history"; + file_util::create_dir_if_needed_for_file(path.string()); + repl.history_save(path.string()); } void ReplWrapper::load_history() { @@ -71,7 +67,7 @@ void ReplWrapper::load_history() { if (std::filesystem::exists(path)) { repl.history_load(path.string()); } else { - fmt::print("Couldn't locate REPL history file at '{}'", path.string()); + fmt::print("Couldn't locate REPL history file at '{}'\n", path.string()); } } diff --git a/common/util/FileUtil.cpp b/common/util/FileUtil.cpp index 4a08586527..bbf31a62ce 100644 --- a/common/util/FileUtil.cpp +++ b/common/util/FileUtil.cpp @@ -186,7 +186,8 @@ std::string get_file_path(const std::vector& input) { bool create_dir_if_needed(const std::filesystem::path& path) { if (!std::filesystem::is_directory(path)) { - return std::filesystem::create_directories(path); + std::filesystem::create_directories(path); + return true; } return false; } diff --git a/common/util/FontUtils.cpp b/common/util/FontUtils.cpp index cdbd8ddd98..453fcff44c 100644 --- a/common/util/FontUtils.cpp +++ b/common/util/FontUtils.cpp @@ -189,6 +189,9 @@ std::string GameTextFontBank::convert_utf8_to_game_with_escape(const std::string ASSERT(value < 256); newstr.push_back(char(value)); i += 3; + } else if (p == '"') { + newstr.push_back(p); + i += 1; } else { throw std::runtime_error("unknown string escape code"); } diff --git a/game/assets/jak1/subtitle/subtitle-editor-db.json b/game/assets/jak1/subtitle/subtitle-editor-db.json index c539d4616a..bd301cc36b 100644 --- a/game/assets/jak1/subtitle/subtitle-editor-db.json +++ b/game/assets/jak1/subtitle/subtitle-editor-db.json @@ -301,6 +301,125 @@ "(close-specific-task! (game-task rolling-plants) (task-status need-introduction))" ] }, + "assistant-village2-introduction-room": { + "entity_type": "assistant-bluehut", + "process_name": "assistant-bluehut-1", + "continue_name": "village2-start", + "move_to": [379.93, 22.37, -1545.63], + "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", + "requirements": [ + "(close-specific-task! (game-task village2-levitator) (task-status need-reminder-a))" + ] + }, + "sage-bluehut-introduction-prec-arm": { + "entity_type": "sage-bluehut", + "process_name": "sage-bluehut-1", + "continue_name": "village2-start", + "move_to": [194.6, 11.0, -1605.9], + "move_first": true, + "delay": 250, + "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", + "requirements": [ + "(close-specific-task! (game-task village2-levitator) (task-status need-introduction))", + "(close-specific-task! (game-task rolling-plants) (task-status need-resolution))", + "(move-to-point! (-> *target* control) (new 'static 'vector :x (meters 384.90) :y (meters 22.37) :z (meters -1550.32)))" + ] + }, + "assistant-village2-reminder-1-room": { + "entity_type": "assistant-bluehut", + "process_name": "assistant-bluehut-1", + "continue_name": "village2-start", + "move_to": [379.93, 22.37, -1545.63], + "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", + "requirements": [ + "(close-specific-task! (game-task village2-levitator) (task-status need-reminder-a))", + "(close-specific-task! (game-task sunken-room) (task-status need-introduction))" + ] + }, + "sage-bluehut-reminder-1-prec-arm": { + "entity_type": "sage-bluehut", + "process_name": "sage-bluehut-1", + "continue_name": "village2-start", + "move_to": [194.6, 11.0, -1605.9], + "move_first": true, + "delay": 250, + "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", + "requirements": [ + "(close-specific-task! (game-task village2-levitator) (task-status need-introduction))", + "(close-specific-task! (game-task rolling-plants) (task-status need-resolution))", + "(close-specific-task! (game-task swamp-tether-1) (task-status need-introduction))", + "(close-specific-task! (game-task swamp-tether-2) (task-status need-introduction))", + "(close-specific-task! (game-task swamp-tether-3) (task-status need-introduction))", + "(close-specific-task! (game-task swamp-tether-4) (task-status need-introduction))", + "(close-specific-task! (game-task swamp-arm) (task-status need-introduction))", + "(move-to-point! (-> *target* control) (new 'static 'vector :x (meters 384.90) :y (meters 22.37) :z (meters -1550.32)))" + ] + }, + "assistant-village2-introduction-flutflut": { + "entity_type": "assistant-bluehut", + "process_name": "assistant-bluehut-1", + "continue_name": "village2-start", + "move_to": [379.93, 22.37, -1545.63], + "move_first": true, + "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", + "requirements": [ + "(close-specific-task! (game-task village2-levitator) (task-status need-reminder-a))", + "(close-specific-task! (game-task sunken-room) (task-status need-resolution))", + "(close-specific-task! (game-task rolling-robbers) (task-status need-resolution))", + "(close-specific-task! (game-task beach-flutflut) (task-status need-resolution))" + ] + }, + "assistant-village2-reminder-1-flutflut": { + "entity_type": "assistant-bluehut", + "process_name": "assistant-bluehut-1", + "continue_name": "village2-start", + "move_to": [379.93, 22.37, -1545.63], + "move_first": true, + "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", + "requirements": [ + "(close-specific-task! (game-task village2-levitator) (task-status need-reminder-a))", + "(close-specific-task! (game-task sunken-room) (task-status need-resolution))", + "(close-specific-task! (game-task rolling-robbers) (task-status need-resolution))", + "(close-specific-task! (game-task beach-flutflut) (task-status need-resolution))", + "(close-specific-task! (game-task swamp-flutflut) (task-status need-introduction))" + ] + }, + "assistant-village2-introduction-robbers": { + "entity_type": "assistant-bluehut", + "process_name": "assistant-bluehut-1", + "continue_name": "village2-start", + "move_to": [379.93, 22.37, -1545.63], + "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", + "requirements": [ + "(close-specific-task! (game-task village2-levitator) (task-status need-reminder-a))", + "(close-specific-task! (game-task sunken-room) (task-status need-resolution))" + ] + }, + "assistant-village2-reminder-1-robbers": { + "entity_type": "assistant-bluehut", + "process_name": "assistant-bluehut-1", + "continue_name": "village2-start", + "move_to": [379.93, 22.37, -1545.63], + "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", + "requirements": [ + "(close-specific-task! (game-task village2-levitator) (task-status need-reminder-a))", + "(close-specific-task! (game-task sunken-room) (task-status need-resolution))", + "(close-specific-task! (game-task rolling-robbers) (task-status need-introduction))" + ] + }, + "assistant-village2-resolution": { + "entity_type": "assistant-levitator", + "process_name": "assistant-levitator-1", + "continue_name": "village2-dock", + "move_to": [356.84, 1.94, -1760.70], + "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", + "requirements": [ + "(close-specific-task! (game-task village2-levitator) (task-status need-reminder-a))", + "(close-specific-task! (game-task sunken-room) (task-status need-resolution))", + "(close-specific-task! (game-task rolling-robbers) (task-status need-resolution))", + "(dm-levitator-ready 0 (debug-menu-msg press))" + ] + }, "geologist-introduction": { "entity_type": "geologist", "process_name": "geologist-1", @@ -451,6 +570,14 @@ "execute_code": "", "requirements": [] }, + "assistant-village3-reminder": { + "entity_type": "assistant-villagec", + "process_name": "assistant-villagec-1", + "continue_name": "village3-start", + "move_to": [1110.63, 54.86, -3488.42], + "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", + "requirements": [] + }, "sage-village3-introduction-dark-eco": { "entity_type": "sage-villagec", "process_name": "sage-villagec-1", @@ -481,13 +608,41 @@ "(close-specific-task! (game-task cave-dark-crystals) (task-status need-resolution))" ] }, + "sage-village3-reminder-1-rams": { + "entity_type": "sage-villagec", + "process_name": "sage-villagec-1", + "continue_name": "village3-start", + "move_to": [1110.63, 54.86, -3488.42], + "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", + "requirements": [ + "(close-specific-task! (game-task village3-button) (task-status need-introduction))", + "(close-specific-task! (game-task cave-dark-crystals) (task-status need-resolution))", + "(close-specific-task! (game-task snow-ram) (task-status need-introduction))" + ] + }, "minershort-introduction-orbs": { "entity_type": "minershort", "process_name": "minershort-1", "continue_name": "village3-farside", "move_to": [1083.86, 45.79, -3594.14], "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", - "requirements": [] + "requirements": [ + "(dm-task-get-money 0 (debug-menu-msg press))" + ] + }, + "minershort-resolution-1-orbs": { + "entity_type": "minershort", + "process_name": "minershort-1", + "continue_name": "village3-farside", + "move_to": [1083.86, 45.79, -3594.14], + "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", + "requirements": [ + "(close-specific-task! (game-task village3-miner-money1) (task-status need-introduction))", + "(close-specific-task! (game-task village3-miner-money2) (task-status need-introduction))", + "(close-specific-task! (game-task village3-miner-money3) (task-status need-introduction))", + "(close-specific-task! (game-task village3-miner-money4) (task-status need-introduction))", + "(dm-task-get-money 0 (debug-menu-msg press))" + ] }, "minershort-reminder-2-orbs": { "entity_type": "minershort", @@ -545,6 +700,53 @@ "(close-specific-task! (game-task cave-gnawers) (task-status need-introduction))" ] }, + "minershort-introduction-switch": { + "entity_type": "minershort", + "process_name": "minershort-1", + "continue_name": "village3-farside", + "move_to": [1083.86, 45.79, -3594.14], + "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", + "requirements": [ + "(close-specific-task! (game-task village3-miner-money1) (task-status need-reward-speech))", + "(close-specific-task! (game-task village3-miner-money2) (task-status need-reward-speech))", + "(close-specific-task! (game-task village3-miner-money3) (task-status need-reward-speech))", + "(close-specific-task! (game-task cave-gnawers) (task-status need-introduction))" + ] + }, + "minershort-resolution-2-orbs": { + "entity_type": "minershort", + "process_name": "minershort-1", + "continue_name": "village3-farside", + "move_to": [1083.86, 45.79, -3594.14], + "execute_code": "", + "requirements": [ + "(close-specific-task! (game-task village3-miner-money1) (task-status need-reward-speech))", + "(close-specific-task! (game-task village3-miner-money2) (task-status need-reward-speech))", + "(close-specific-task! (game-task village3-miner-money3) (task-status need-reward-speech))", + "(close-specific-task! (game-task cave-gnawers) (task-status need-resolution))", + "(close-specific-task! (game-task snow-eggtop) (task-status need-resolution))", + "(dm-task-get-money 0 (debug-menu-msg press))", + "(save-reminder (-> __GET-PROCESS__ tasks) 3 2)" + ] + }, + "assistant-lavatube-start-resolution": { + "entity_type": "assistant-lavatube-start", + "process_name": "assistant-lavatube-start-1", + "continue_name": "lavatube-start", + "move_to": [1338.56, 33.39, -3557.54], + "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", + "requirements": [ + "(dm-lavabike-ready 0 (debug-menu-msg press))" + ] + }, + "assistant-lavatube-end-resolution": { + "entity_type": "assistant-lavatube-start", + "process_name": "assistant-lavatube-start-1", + "continue_name": "lavatube-end", + "move_to": [2799.52, -36.38, -4441.90], + "execute_code": "", + "requirements": [] + }, "green-sagecage-introduction": { "entity_type": "green-sagecage", "process_name": "green-sagecage-1", @@ -558,13 +760,25 @@ "process_name": "green-sagecage-1", "continue_name": "citadel-elevator", "move_to": [262.35, 2.28, -231.83], - "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", + "execute_code": "", "requirements": [ "(close-specific-task! (game-task citadel-sage-blue) (task-status need-hint))", "(close-specific-task! (game-task citadel-sage-red) (task-status need-hint))", "(close-specific-task! (game-task citadel-sage-green) (task-status need-hint))", - "(close-specific-task! (game-task citadel-sage-yellow) (task-status need-hint))", - "(dm-give-all-cells 0 (debug-menu-msg press))" + "(close-specific-task! (game-task citadel-sage-yellow) (task-status need-hint))" + ] + }, + "green-sagecage-outro-preboss": { + "entity_type": "green-sagecage", + "process_name": "green-sagecage-1", + "continue_name": "citadel-elevator", + "move_to": [262.35, 2.28, -231.83], + "execute_code": "", + "requirements": [ + "(close-specific-task! (game-task citadel-sage-blue) (task-status need-hint))", + "(close-specific-task! (game-task citadel-sage-red) (task-status need-hint))", + "(close-specific-task! (game-task citadel-sage-green) (task-status need-hint))", + "(close-specific-task! (game-task citadel-sage-yellow) (task-status need-hint))" ] }, "mayor-introduction": { @@ -633,6 +847,22 @@ "(dm-task-hint 112 (debug-menu-msg press))" ] }, + "oracle-intro-2": { + "entity_type": "oracle", + "process_name": "oracle-2", + "continue_name": "village2-start", + "move_to": [238.48, 11.9, -1532.6], + "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", + "requirements": [] + }, + "oracle-intro-3": { + "entity_type": "oracle", + "process_name": "oracle-3", + "continue_name": "village3-start", + "move_to": [1024.94, 40.07, -3507.05], + "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", + "requirements": [] + }, "oracle-left-eye-1": { "entity_type": "oracle", "process_name": "oracle-1", @@ -640,11 +870,11 @@ "move_to": [82.8, 18.2, 14.3], "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", "requirements": [ - "(dm-task-hint 104 (debug-menu-msg press))", - "(dm-task-hint 112 (debug-menu-msg press))", + "(close-specific-task! (game-task village1-oracle-money1) (task-status need-introduction))", + "(close-specific-task! (game-task village1-oracle-money2) (task-status need-introduction))", + "(close-specific-task! (game-task village1-oracle-money1) (task-status need-resolution))", "(dm-task-get-money 0 (debug-menu-msg press))", - "(dm-task-get-money 0 (debug-menu-msg press))", - "(dm-give-cell (game-task village1-oracle-money1))" + "(dm-task-get-money 0 (debug-menu-msg press))" ] }, "oracle-left-eye-2": { @@ -654,12 +884,11 @@ "move_to": [238.48, 11.9, -1532.6], "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", "requirements": [ - "(dm-task-hint 104 (debug-menu-msg press))", - "(dm-task-hint 112 (debug-menu-msg press))", - "(close-status! (-> __GET-PROCESS__ tasks) (task-status need-introduction))", + "(close-specific-task! (game-task village2-oracle-money1) (task-status need-introduction))", + "(close-specific-task! (game-task village2-oracle-money2) (task-status need-introduction))", + "(close-specific-task! (game-task village2-oracle-money1) (task-status need-resolution))", "(dm-task-get-money 0 (debug-menu-msg press))", - "(dm-task-get-money 0 (debug-menu-msg press))", - "(dm-give-cell (game-task village2-oracle-money1))" + "(dm-task-get-money 0 (debug-menu-msg press))" ] }, "oracle-left-eye-3": { @@ -669,12 +898,11 @@ "move_to": [1024.94, 40.07, -3507.05], "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", "requirements": [ - "(dm-task-hint 104 (debug-menu-msg press))", - "(dm-task-hint 112 (debug-menu-msg press))", - "(close-status! (-> __GET-PROCESS__ tasks) (task-status need-introduction))", + "(close-specific-task! (game-task village3-oracle-money1) (task-status need-introduction))", + "(close-specific-task! (game-task village3-oracle-money2) (task-status need-introduction))", + "(close-specific-task! (game-task village3-oracle-money1) (task-status need-resolution))", "(dm-task-get-money 0 (debug-menu-msg press))", - "(dm-task-get-money 0 (debug-menu-msg press))", - "(dm-give-cell (game-task village3-oracle-money1))" + "(dm-task-get-money 0 (debug-menu-msg press))" ] }, "oracle-reminder-1": { @@ -684,9 +912,30 @@ "move_to": [82.8, 18.2, 14.3], "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", "requirements": [ - "(dm-task-hint 104 (debug-menu-msg press))", - "(dm-task-hint 112 (debug-menu-msg press))", - "(close-status! (-> __GET-PROCESS__ tasks) (task-status need-introduction))" + "(close-specific-task! (game-task village1-oracle-money1) (task-status need-introduction))", + "(close-specific-task! (game-task village1-oracle-money2) (task-status need-introduction))" + ] + }, + "oracle-reminder-2": { + "entity_type": "oracle", + "process_name": "oracle-2", + "continue_name": "village2-start", + "move_to": [238.48, 11.9, -1532.6], + "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", + "requirements": [ + "(close-specific-task! (game-task village2-oracle-money1) (task-status need-introduction))", + "(close-specific-task! (game-task village2-oracle-money2) (task-status need-introduction))" + ] + }, + "oracle-reminder-3": { + "entity_type": "oracle", + "process_name": "oracle-3", + "continue_name": "village3-start", + "move_to": [1024.94, 40.07, -3507.05], + "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", + "requirements": [ + "(close-specific-task! (game-task village3-oracle-money1) (task-status need-introduction))", + "(close-specific-task! (game-task village3-oracle-money2) (task-status need-introduction))" ] }, "oracle-right-eye-1": { @@ -696,9 +945,8 @@ "move_to": [82.8, 18.2, 14.3], "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", "requirements": [ - "(dm-task-hint 104 (debug-menu-msg press))", - "(dm-task-hint 112 (debug-menu-msg press))", - "(close-status! (-> __GET-PROCESS__ tasks) (task-status need-introduction))", + "(close-specific-task! (game-task village1-oracle-money1) (task-status need-introduction))", + "(close-specific-task! (game-task village1-oracle-money2) (task-status need-introduction))", "(dm-task-get-money 0 (debug-menu-msg press))", "(dm-task-get-money 0 (debug-menu-msg press))" ] @@ -710,9 +958,8 @@ "move_to": [238.48, 11.9, -1532.6], "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", "requirements": [ - "(dm-task-hint 104 (debug-menu-msg press))", - "(dm-task-hint 112 (debug-menu-msg press))", - "(close-status! (-> __GET-PROCESS__ tasks) (task-status need-introduction))", + "(close-specific-task! (game-task village2-oracle-money1) (task-status need-introduction))", + "(close-specific-task! (game-task village2-oracle-money2) (task-status need-introduction))", "(dm-task-get-money 0 (debug-menu-msg press))", "(dm-task-get-money 0 (debug-menu-msg press))" ] @@ -724,9 +971,8 @@ "move_to": [1024.94, 40.07, -3507.05], "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", "requirements": [ - "(dm-task-hint 104 (debug-menu-msg press))", - "(dm-task-hint 112 (debug-menu-msg press))", - "(close-status! (-> __GET-PROCESS__ tasks) (task-status need-introduction))", + "(close-specific-task! (game-task village3-oracle-money1) (task-status need-introduction))", + "(close-specific-task! (game-task village3-oracle-money2) (task-status need-introduction))", "(dm-task-get-money 0 (debug-menu-msg press))", "(dm-task-get-money 0 (debug-menu-msg press))" ] @@ -832,6 +1078,25 @@ "(dm-task-resolution 120 (debug-menu-msg press))" ] }, + "sage-reminder-2-generic": { + "entity_type": "sage", + "process_name": "sage-23", + "continue_name": "village1-hut", + "move_to": [], + "execute_code": "(send-event __GET-PROCESS__ 'play-anim)", + "requirements": [ + "(dm-task-resolution 736 (debug-menu-msg press))", + "(dm-task-resolution 744 (debug-menu-msg press))", + "(dm-task-resolution 752 (debug-menu-msg press))", + "(dm-task-resolution 760 (debug-menu-msg press))", + "(dm-task-resolution 872 (debug-menu-msg press))", + "(dm-task-introduction 120 (debug-menu-msg press))", + "(dm-task-introduction 208 (debug-menu-msg press))", + "(dm-task-reminder 208 (debug-menu-msg press))", + "(dm-task-resolution 120 (debug-menu-msg press))", + "(save-reminder (-> __GET-PROCESS__ tasks) 3 0)" + ] + }, "sage-reminder-1-misty-cannon": { "entity_type": "sage", "process_name": "sage-23", @@ -902,5 +1167,68 @@ "(close-specific-task! (game-task citadel-sage-green) (task-status need-hint))", "(close-specific-task! (game-task citadel-sage-yellow) (task-status need-hint))" ] + }, + "finalbosscam-white-eco": { + "entity_type": "robotboss", + "process_name": "robotboss-3", + "continue_name": "finalboss-fight", + "move_to": [], + "delay": 500, + "execute_code": "(go-process __GET-PROCESS__ robotboss-white-eco-movie)", + "requirements": [] + }, + "green-sagecage-daxter-sacrifice": { + "entity_type": "robotboss", + "process_name": "robotboss-3", + "continue_name": "finalboss-fight", + "move_to": [], + "delay": 500, + "execute_code": "(go-process __GET-PROCESS__ robotboss-white-eco-movie)", + "requirements": [] + }, + "green-sagecage-outro-beat-boss-a": { + "entity_type": "robotboss", + "process_name": "robotboss-3", + "continue_name": "finalboss-fight", + "move_to": [], + "delay": 500, + "execute_code": "(go-process __GET-PROCESS__ robotboss-white-eco-movie)", + "requirements": [] + }, + "green-sagecage-outro-beat-boss-b": { + "entity_type": "robotboss", + "process_name": "robotboss-3", + "continue_name": "finalboss-fight", + "move_to": [], + "delay": 500, + "execute_code": "(go-process __GET-PROCESS__ robotboss-white-eco-movie)", + "requirements": [] + }, + "green-sagecage-outro-beat-boss-need-cells": { + "entity_type": "robotboss", + "process_name": "robotboss-3", + "continue_name": "finalboss-fight", + "move_to": [], + "delay": 500, + "execute_code": "(go-process __GET-PROCESS__ robotboss-white-eco-movie)", + "requirements": [] + }, + "green-sagecage-outro-beat-boss-enough-cells": { + "entity_type": "robotboss", + "process_name": "robotboss-3", + "continue_name": "finalboss-fight", + "move_to": [], + "delay": 500, + "execute_code": "(go-process __GET-PROCESS__ robotboss-white-eco-movie)", + "requirements": ["(dm-give-all-cells 0 (debug-menu-msg press))"] + }, + "green-sagecage-outro-big-finish": { + "entity_type": "robotboss", + "process_name": "robotboss-3", + "continue_name": "finalboss-fight", + "move_to": [], + "delay": 500, + "execute_code": "(go-process __GET-PROCESS__ robotboss-white-eco-movie)", + "requirements": ["(dm-give-all-cells 0 (debug-menu-msg press))"] } } diff --git a/game/tools/subtitles/subtitle_editor.cpp b/game/tools/subtitles/subtitle_editor.cpp index b40498d2b9..2dd943b143 100644 --- a/game/tools/subtitles/subtitle_editor.cpp +++ b/game/tools/subtitles/subtitle_editor.cpp @@ -96,7 +96,16 @@ void SubtitleEditor::repl_execute_cutscene_code(const SubtitleEditorDB::Entry& e temp = std::regex_replace(temp, std::regex("__GET-PROCESS__"), repl_get_process_string(entry.entity_type, entry.process_name)); m_repl.eval("(send-event *camera* 'teleport)"); - m_repl.eval(temp); + if (entry.delay_frames == 0) { + m_repl.eval(temp); + } else { + // We do this in a separate thread to introduce a delay -- allow the game to catch up before + // running the critical section + auto code = + fmt::format("(process-spawn-function process (lambda () (dotimes (i {}) (suspend)) {}))", + entry.delay_frames, temp); + m_repl.eval(code); + } } } @@ -264,6 +273,11 @@ void SubtitleEditor::update_subtitle_editor_db() { new_entry.process_name = val.at("process_name").get(); new_entry.continue_name = val.at("continue_name").get(); new_entry.move_to = val.at("move_to").get>(); + if (val.contains("delay")) { + new_entry.delay_frames = val.at("delay").get(); + } else { + new_entry.delay_frames = 0; + } if (val.contains("move_first")) { new_entry.move_first = val.at("move_first").get(); } else { @@ -378,9 +392,11 @@ bool SubtitleEditor::any_cutscenes_in_group(const std::string& group_name) { auto& scenes = m_subtitle_db.m_banks.at(m_current_language)->m_scenes; auto scenes_in_group = m_subtitle_db.m_subtitle_groups->m_groups[group_name]; for (auto& scene_name : scenes_in_group) { - auto& scene_info = scenes.at(scene_name); - if (scene_info.m_kind == SubtitleSceneKind::Movie) { - return true; + if (scenes.count(scene_name) != 0) { + auto& scene_info = scenes.at(scene_name); + if (scene_info.m_kind == SubtitleSceneKind::Movie) { + return true; + } } } return false; @@ -407,9 +423,11 @@ bool SubtitleEditor::any_hints_in_group(const std::string& group_name) { auto& scenes = m_subtitle_db.m_banks.at(m_current_language)->m_scenes; auto scenes_in_group = m_subtitle_db.m_subtitle_groups->m_groups[group_name]; for (auto& scene_name : scenes_in_group) { - auto& scene_info = scenes.at(scene_name); - if (scene_info.m_kind != SubtitleSceneKind::Movie) { - return true; + if (scenes.count(scene_name) != 0) { + auto& scene_info = scenes.at(scene_name); + if (scene_info.m_kind != SubtitleSceneKind::Movie) { + return true; + } } } return false; @@ -458,9 +476,7 @@ void SubtitleEditor::draw_all_scenes(std::string group_name, bool base_cutscenes } if (base_cutscenes) { ImGui::PushStyleColor(ImGuiCol_Text, m_disabled_text_color); - } - - if (m_db.count(scene_name) == 0) { + } else if (m_db.count(scene_name) == 0) { ImGui::PushStyleColor(ImGuiCol_Text, m_warning_color); } @@ -616,13 +632,16 @@ void SubtitleEditor::draw_subtitle_options(GameSubtitleSceneInfo& scene, bool cu ImGui::InputText("Speaker", &subtitleLine.speaker); ImGui::InputText("Text", &linetext); ImGui::Checkbox("Offscreen?", &subtitleLine.offscreen); - ImGui::PushStyleColor(ImGuiCol_Button, m_warning_color); - if (scene.m_lines.size() > 1) { // prevent creating an empty scene - if (ImGui::Button("Remove Line")) { - scene.m_lines.erase(scene.m_lines.begin() + i); - } - } - ImGui::PopStyleColor(); + // TODO - deleting while iterating is a bad pattern, especially with imgui's declarative + // style + // disabling this for now, it's not working in it's current state. + // if (scene.m_lines.size() > 1) { // prevent creating an empty scene + // ImGui::PushStyleColor(ImGuiCol_Button, m_warning_color); + // if (ImGui::Button("Remove Line")) { + // scene.m_lines.erase(scene.m_lines.begin() + i); + // } + // ImGui::PopStyleColor(); + //} ImGui::TreePop(); } else if (linetext.empty() || subtitleLine.offscreen) { ImGui::PopStyleColor(); diff --git a/game/tools/subtitles/subtitle_editor.h b/game/tools/subtitles/subtitle_editor.h index 6bea33961e..ecf4fd1f97 100644 --- a/game/tools/subtitles/subtitle_editor.h +++ b/game/tools/subtitles/subtitle_editor.h @@ -15,6 +15,7 @@ class SubtitleEditorDB { std::string process_name; std::string continue_name; std::vector move_to; + int delay_frames; std::string execute_code; bool move_first; std::vector requirements;