Skip to content

Commit

Permalink
RPG_RT compatibility for empty parallel events.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
mateofio committed Sep 3, 2019
1 parent 723cd9f commit 0c54f4d
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 34 deletions.
39 changes: 25 additions & 14 deletions src/game_commonevent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,36 @@
#include "game_interpreter_map.h"
#include "main_data.h"
#include "reader_util.h"
#include <cassert>

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 ...
Expand Down Expand Up @@ -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));
}
2 changes: 0 additions & 2 deletions src/game_commonevent.h
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down
52 changes: 34 additions & 18 deletions src/game_event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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);
}
}
}

Expand All @@ -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);
}
}
}

Expand Down Expand Up @@ -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 ...
Expand Down Expand Up @@ -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();
Expand Down

0 comments on commit 0c54f4d

Please sign in to comment.