Skip to content

Commit

Permalink
Call Movement Action + Wait for Single Movement( can Detect fail cases)
Browse files Browse the repository at this point in the history
Call Movement Action:
`@raw 2050, "SetMoveSpeed", 0, 10001, 1, 3`
@2050("typeOfAction",[targetIsVar,target, parameterIsvar, parameter])

```js
@raw 2051, "", 0, 10001 //Wait for Single Movement
@raw 20140, "Fails to move x times", 8 // start fail branch
@raw 10 //empty space for more cmds
@raw 20141 // end of fail branch
```

-------------------------------

old commits comments:
Update Feature - Support Detecting when Move Route Fails
Thanks @MackValentine Mack for solving some Core Issues
  • Loading branch information
jetrotal committed Oct 2, 2023
1 parent ad6e823 commit 6452470
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 0 deletions.
17 changes: 17 additions & 0 deletions src/game_character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,23 @@ void Game_Character::CancelMoveRoute() {
SetMoveRouteFinished(false);
}

bool Game_Character::isStuck(int i) {
if(i == 0 ) i =1;
int currentPose = 500;
if (GetMoveRouteIndex() < GetMoveRoute().move_commands.size()) {
if (IsStopping() && GetMoveRoute().move_commands[GetMoveRouteIndex()].command_id < 12) {
failsMove++;
} else {
failsMove = 0;
}
} else {
failsMove = 0;
}

//Output::Warning("stuck? - {} {} {} -- {}", failsMove, IsPaused(), i, GetMaxStopCount());
return failsMove > i && (GetStopCount() == 0 || GetStopCount() > GetMaxStopCount());
}

int Game_Character::GetSpriteX() const {
int x = GetX() * SCREEN_TILE_SIZE;

Expand Down
3 changes: 3 additions & 0 deletions src/game_character.h
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,9 @@ class Game_Character {
static constexpr int GetDxFromDirection(int dir);
static constexpr int GetDyFromDirection(int dir);

int failsMove = 0;
bool isStuck(int i);

protected:
explicit Game_Character(Type type, lcf::rpg::SaveMapEventBase* d);
/** Check for and fix incorrect data after loading save game */
Expand Down
85 changes: 85 additions & 0 deletions src/game_interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,10 @@ bool Game_Interpreter::ExecuteCommand(lcf::rpg::EventCommand const& com) {
return CommandManiacSetGameOption(com);
case Cmd::Maniac_CallCommand:
return CommandManiacCallCommand(com);
case static_cast<Game_Interpreter::Cmd>(2050): //Cmd::EasyRpg_CallMovement
return CommandCallMovement(com);
case static_cast<Game_Interpreter::Cmd>(2051): //Cmd::EasyRpg_WaitForMovement
return CommandWaitForMovement(com);
default:
return true;
}
Expand Down Expand Up @@ -4643,6 +4647,87 @@ bool Game_Interpreter::CommandManiacCallCommand(lcf::rpg::EventCommand const&) {
return true;
}

bool Game_Interpreter::CommandCallMovement(lcf::rpg::EventCommand const& com) {
// CommandSetMovement("moveCommand",[useVarID, ID, useVarOutput, output])

int eventID = ValueOrVariable(com.parameters[0], com.parameters[1]);
int outputParam = ValueOrVariable(com.parameters[2], com.parameters[3]);

Game_Character* event = GetCharacter(eventID);
Game_Character* target;

std::string moveCommand = ToString(com.string);
std::string outputString = event->GetSpriteName();

std::size_t pos = moveCommand.find('/');

if (pos != std::string::npos) {
outputString = moveCommand.substr(pos + 1);
moveCommand = moveCommand.substr(0, pos);
}

if (moveCommand == "SetMoveSpeed")event->SetMoveSpeed(outputParam);
if (moveCommand == "SetMoveFrequency")event->SetMoveFrequency(outputParam);
if (moveCommand == "SetTransparency")event->SetTransparency(outputParam);

if (moveCommand == "Event2Event") {
target = GetCharacter(outputParam);
event->SetFacing(target->GetFacing());
event->SetDirection(target->GetDirection());
event->SetX(target->GetX());
event->SetY(target->GetY());
}

if (moveCommand == "SetFacingLocked")event->SetFacingLocked(outputParam);
if (moveCommand == "SetLayer")event->SetLayer(outputParam);
if (moveCommand == "SetFlying")event->SetFlying(outputParam); //FIXME: I wish any event could imitate an airship, lacks more work.
if (moveCommand == "ChangeCharset")event->SetSpriteGraphic(outputString,outputParam); // syntax ChangeCharset/actor1

if (moveCommand == "StopMovement")event->CancelMoveRoute();

return true;
}

bool Game_Interpreter::CommandWaitForMovement(lcf::rpg::EventCommand const& com) {
// CommandWaitForMovement(useVarID, ID)

// Needed for ShowChoice
auto* frame = GetFramePtr();
const auto& list = frame->commands;
auto& index = frame->current_command;

// Retrieve event ID
int eventID = ValueOrVariable(com.parameters[0], com.parameters[1]);
if (eventID == 0)
eventID = GetCurrentEventId();

// Get the character associated with the event ID
Game_Character* ev = GetCharacter(eventID);

// Check if movement exists and if it's currently running
bool movementExists = !ev->GetMoveRoute().move_commands.empty();
bool movementIsRunning = movementExists && (ev->IsMoveRouteOverwritten() && !ev->IsMoveRouteFinished());

int i = frame->current_command + 1;

// Check the next command for a specific condition
const auto& cmd = list[i];
const int32_t failBranch = static_cast<int>(Cmd::ShowChoiceOption);

// If the next command is "Fails to move x times" and the character is stuck, cancel movement
if (cmd.code == failBranch && cmd.string == "Fails to move x times")
if (ev->isStuck(cmd.parameters[0])) {
ev->failsMove = 0;
ev->CancelMoveRoute();
frame->current_command = i + 1;
return true;
}

// Return false if movement is still in progress
if(!movementIsRunning) ev->failsMove = 0;
return !movementIsRunning;
}

Game_Interpreter& Game_Interpreter::GetForegroundInterpreter() {
return Game_Battle::IsBattleRunning()
? Game_Battle::GetInterpreter()
Expand Down
2 changes: 2 additions & 0 deletions src/game_interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,8 @@ class Game_Interpreter
bool CommandManiacChangePictureId(lcf::rpg::EventCommand const& com);
bool CommandManiacSetGameOption(lcf::rpg::EventCommand const& com);
bool CommandManiacCallCommand(lcf::rpg::EventCommand const& com);
bool CommandCallMovement(lcf::rpg::EventCommand const& com);
bool CommandWaitForMovement(lcf::rpg::EventCommand const& com);

int DecodeInt(lcf::DBArray<int32_t>::const_iterator& it);
const std::string DecodeString(lcf::DBArray<int32_t>::const_iterator& it);
Expand Down

0 comments on commit 6452470

Please sign in to comment.