diff --git a/rsrc/dialogs/debug-crash-confirm.xml b/rsrc/dialogs/debug-crash-confirm.xml new file mode 100644 index 00000000..0c7b0fbf --- /dev/null +++ b/rsrc/dialogs/debug-crash-confirm.xml @@ -0,0 +1,12 @@ + + + + + + You are about to crash the game on purpose.
+
+ Are you sure you want to do this? +
+ + +
diff --git a/src/dialogxml/keycodes.cpp b/src/dialogxml/keycodes.cpp index 4083db6f..50c34a36 100644 --- a/src/dialogxml/keycodes.cpp +++ b/src/dialogxml/keycodes.cpp @@ -66,6 +66,8 @@ cKey charToKey(char ch) { return {false, w('/'), mod_shift}; case '~': return {false, w('`'), mod_shift}; + case '\\': + return {false, w('\\'), mod_none}; } throw std::string {"Tried to convert unsupported char '"} + ch + "' to cKey!"; } diff --git a/src/game/boe.actions.cpp b/src/game/boe.actions.cpp index a39c54a4..435fa45b 100644 --- a/src/game/boe.actions.cpp +++ b/src/game/boe.actions.cpp @@ -2456,7 +2456,7 @@ void debug_launch_scen(std::string scen_name) { } // Non-comprehensive list of unused keys: -// chjklnoqvy -_+[]{},.'"`\|;: +// chjklnoqvy -_+[]{},.'"`|;: // We want to keep lower-case for normal gameplay. void init_debug_actions() { // optional `true` argument means you can use this action in the startup menu. @@ -2507,6 +2507,7 @@ void init_debug_actions() { add_debug_action({'^'}, "Fight special encounter from this section", []() {debug_fight_encounter(false);}); add_debug_action({'/', '?'}, "Bring up this window", show_debug_help, true); add_debug_action({'Z'}, "Save the current action log for bug reporting", save_replay_log, true); + add_debug_action({'\\'}, "Crash the game", debug_crash, true); } // Later we might want to know whether the key is used or not @@ -4066,6 +4067,18 @@ void save_replay_log(){ start_log_file(out_file.string()); } +void debug_crash() { + // If they don't confirm, the game can continue normally, and we'll need to replay + // that the confirmation opened and closed. + if(recording){ + record_action("debug_crash", ""); + } + std::string confirm = cChoiceDlog("debug-crash-confirm",{"yes","no"}).show(); + if(confirm == "yes"){ + throw std::string { "Be careful what you wish for!" }; + } +} + void clear_trapped_monst() { if(recording){ record_action("clear_trapped_monst", ""); diff --git a/src/game/boe.actions.hpp b/src/game/boe.actions.hpp index 215b5ba8..de4ce1f8 100644 --- a/src/game/boe.actions.hpp +++ b/src/game/boe.actions.hpp @@ -120,6 +120,7 @@ void easter_egg(int idx); void preview_dialog_xml(); void preview_every_dialog_xml(); void save_replay_log(); +void debug_crash(); void clear_trapped_monst(); #endif diff --git a/src/game/boe.main.cpp b/src/game/boe.main.cpp index 38f8ddc6..4ebad1b8 100644 --- a/src/game/boe.main.cpp +++ b/src/game/boe.main.cpp @@ -954,6 +954,8 @@ static void replay_action(Element& action) { clear_trapped_monst(); }else if(t == "error"){ // The error is recorded for debugging only. It should be triggered by replaying the actions. + }else if(t == "debug_crash"){ + debug_crash(); }else if(t == "advance_time"){ // This is bad regardless of strictness, because visual changes may have occurred which won't get redrawn/reprinted throw std::string { "Replay system internal error! advance_time() was supposed to be called by the last action, but wasn't: " } + _last_action_type;