From 0c54f4d8c97215d925ffb81be739c715d89d5c07 Mon Sep 17 00:00:00 2001 From: Matthew Fioravante Date: Wed, 28 Aug 2019 22:56:06 -0400 Subject: [PATCH] RPG_RT compatibility for empty parallel events. RPG_RT save games always have an empty base stack frame allocated for parallel map events and common events. We add these to our saves to be compatible, however if we have empty data, we won't create an interpreter object or load any data. --- src/game_commonevent.cpp | 39 +++++++++++++++++++----------- src/game_commonevent.h | 2 -- src/game_event.cpp | 52 ++++++++++++++++++++++++++-------------- 3 files changed, 59 insertions(+), 34 deletions(-) diff --git a/src/game_commonevent.cpp b/src/game_commonevent.cpp index d087dc26c9..e3b58f7b47 100644 --- a/src/game_commonevent.cpp +++ b/src/game_commonevent.cpp @@ -22,27 +22,36 @@ #include "game_interpreter_map.h" #include "main_data.h" #include "reader_util.h" +#include Game_CommonEvent::Game_CommonEvent(int common_event_id) : - common_event_id(common_event_id) { + common_event_id(common_event_id) +{ + auto* ce = ReaderUtil::GetElement(Data::commonevents, common_event_id); - if (GetTrigger() == RPG::EventPage::Trigger_parallel) { + if (ce->trigger == RPG::EventPage::Trigger_parallel + && !ce->event_commands.empty()) { interpreter.reset(new Game_Interpreter_Map()); + interpreter->Push(this); } + + } void Game_CommonEvent::SetSaveData(const RPG::SaveEventExecState& data) { - if (interpreter && !data.stack.empty()) { + // RPG_RT Savegames have empty stacks for parallel events. + // We are LSD compatible but don't load these into interpreter. + if (!data.stack.empty() && !data.stack.front().commands.empty()) { + if (!interpreter) { + interpreter.reset(new Game_Interpreter_Map()); + } interpreter->SetState(data); } } bool Game_CommonEvent::Update() { if (interpreter && IsWaitingBackgroundExecution()) { - if (!interpreter->IsRunning()) { - interpreter->Clear(); - interpreter->Push(this); - } + assert(interpreter->IsRunning()); interpreter->Update(); // Suspend due to async op ... @@ -85,20 +94,22 @@ RPG::SaveEventExecState Game_CommonEvent::GetSaveData() { if (interpreter) { state = interpreter->GetState(); } + if (GetTrigger() == RPG::EventPage::Trigger_parallel && state.stack.empty()) { + // RPG_RT always stores an empty stack frame for parallel events. + state.stack.push_back({}); + } return state; } -bool Game_CommonEvent::IsWaitingExecution(RPG::EventPage::Trigger trigger) const { +bool Game_CommonEvent::IsWaitingForegroundExecution() const { auto* ce = ReaderUtil::GetElement(Data::commonevents, common_event_id); - return ce->trigger == trigger && + return ce->trigger == RPG::EventPage::Trigger_auto_start && (!ce->switch_flag || Game_Switches.Get(ce->switch_id)) && !ce->event_commands.empty(); } -bool Game_CommonEvent::IsWaitingForegroundExecution() const { - return IsWaitingExecution(RPG::EventPage::Trigger_auto_start); -} - bool Game_CommonEvent::IsWaitingBackgroundExecution() const { - return IsWaitingExecution(RPG::EventPage::Trigger_parallel); + auto* ce = ReaderUtil::GetElement(Data::commonevents, common_event_id); + return ce->trigger == RPG::EventPage::Trigger_parallel && + (!ce->switch_flag || Game_Switches.Get(ce->switch_id)); } diff --git a/src/game_commonevent.h b/src/game_commonevent.h index b04519e69b..41c6aaddb7 100644 --- a/src/game_commonevent.h +++ b/src/game_commonevent.h @@ -105,8 +105,6 @@ class Game_CommonEvent { bool IsAsyncPending() const; private: - bool IsWaitingExecution(RPG::EventPage::Trigger trigger) const; - int common_event_id; /** Interpreter for parallel common events. */ diff --git a/src/game_event.cpp b/src/game_event.cpp index e79d2180e3..bcd86b8a0b 100644 --- a/src/game_event.cpp +++ b/src/game_event.cpp @@ -55,11 +55,6 @@ Game_Event::Game_Event(int map_id, const RPG::Event& event, const RPG::SaveMapEv this->event.ID = data()->ID; - if (!data()->parallel_event_execstate.stack.empty()) { - interpreter.reset(new Game_Interpreter_Map()); - interpreter->SetState(data()->parallel_event_execstate); - } - Refresh(true); } @@ -128,8 +123,14 @@ void Game_Event::Setup(const RPG::EventPage* new_page) { SetLayer(page->layer); data()->overlap_forbidden = page->overlap_forbidden; - if (!interpreter && GetTrigger() == RPG::EventPage::Trigger_parallel) { - interpreter.reset(new Game_Interpreter_Map()); + if (GetTrigger() == RPG::EventPage::Trigger_parallel) { + if (!page->event_commands.empty()) { + if (!interpreter) { + interpreter.reset(new Game_Interpreter_Map()); + } + interpreter->Clear(); + interpreter->Push(this); + } } } @@ -142,10 +143,16 @@ void Game_Event::SetupFromSave(const RPG::EventPage* new_page) { original_move_frequency = page->move_frequency; - // Trigger parallel events when the interpreter wasn't already running - // (because it was the middle of a parallel event while saving) - if (!interpreter && GetTrigger() == RPG::EventPage::Trigger_parallel) { - interpreter.reset(new Game_Interpreter_Map()); + if (GetTrigger() == RPG::EventPage::Trigger_parallel) { + auto& state = data()->parallel_event_execstate; + // RPG_RT Savegames have empty stacks for parallel events. + // We are LSD compatible but don't load these into interpreter. + if (!state.stack.empty() && !state.stack.front().commands.empty()) { + if (!interpreter) { + interpreter.reset(new Game_Interpreter_Map()); + } + interpreter->SetState(state); + } } } @@ -501,12 +508,10 @@ bool Game_Event::Update() { // the interpreter will run multiple times per frame. // This results in event waits to finish quicker during collisions as // the wait will tick by 1 each time the interpreter is invoked. - if (GetTrigger() == RPG::EventPage::Trigger_parallel) { + if (GetTrigger() == RPG::EventPage::Trigger_parallel && interpreter) { assert(interpreter != nullptr); - if (!interpreter->IsRunning()) { - interpreter->Clear(); - interpreter->Push(this); - } + assert(interpreter->IsRunning()); + interpreter->Update(); // Suspend due to async op ... @@ -555,9 +560,20 @@ const RPG::EventPage *Game_Event::GetActivePage() const { } const RPG::SaveMapEvent& Game_Event::GetSaveData() { - if (interpreter) { - data()->parallel_event_execstate = interpreter->GetState(); + RPG::SaveEventExecState state; + if (page && page->trigger == RPG::EventPage::Trigger_parallel) { + if (interpreter) { + state = interpreter->GetState(); + } + + if (state.stack.empty()) { + // RPG_RT always stores an empty stack frame for parallel events. + RPG::SaveEventExecFrame frame; + frame.event_id = GetId(); + state.stack.push_back(std::move(frame)); + } } + data()->parallel_event_execstate = std::move(state); data()->ID = event.ID; return *data();