Skip to content

Commit

Permalink
Merge pull request EasyRPG#3221 from Ghabry/CallMovement2
Browse files Browse the repository at this point in the history
New command "Wait for Single Movement"
  • Loading branch information
Ghabry authored Sep 1, 2024
2 parents 1e1aa62 + 7b1cef7 commit 65f80f9
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 37 deletions.
54 changes: 32 additions & 22 deletions src/game_character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,10 +283,10 @@ void Game_Character::UpdateMoveRoute(int32_t& current_index, const lcf::rpg::Mov
TurnRandom();
break;
case Code::move_towards_hero:
TurnTowardHero();
TurnTowardCharacter(GetPlayer());
break;
case Code::move_away_from_hero:
TurnAwayFromHero();
TurnAwayFromCharacter(GetPlayer());
break;
case Code::move_forward:
break;
Expand All @@ -301,6 +301,7 @@ void Game_Character::UpdateMoveRoute(int32_t& current_index, const lcf::rpg::Mov
SetDirection(prev_direction);
SetFacing(prev_facing);
} else {
SetMoveFailureCount(GetMoveFailureCount() + 1);
return;
}
}
Expand Down Expand Up @@ -340,10 +341,10 @@ void Game_Character::UpdateMoveRoute(int32_t& current_index, const lcf::rpg::Mov
TurnRandom();
break;
case Code::face_hero:
TurnTowardHero();
TurnTowardCharacter(GetPlayer());
break;
case Code::face_away_from_hero:
TurnAwayFromHero();
TurnAwayFromCharacter(GetPlayer());
break;
default:
break;
Expand All @@ -365,6 +366,7 @@ void Game_Character::UpdateMoveRoute(int32_t& current_index, const lcf::rpg::Mov
SetFacing(prev_facing);
} else {
current_index = saved_index;
SetMoveFailureCount(GetMoveFailureCount() + 1);
return;
}
}
Expand Down Expand Up @@ -449,6 +451,7 @@ void Game_Character::UpdateMoveRoute(int32_t& current_index, const lcf::rpg::Mov
break;
}
}
SetMoveFailureCount(0);
++current_index;

if (current_index == start_index) {
Expand Down Expand Up @@ -535,9 +538,9 @@ void Game_Character::Turn90DegreeLeftOrRight() {
}
}

int Game_Character::GetDirectionToHero() {
int sx = DistanceXfromPlayer();
int sy = DistanceYfromPlayer();
int Game_Character::GetDirectionToCharacter(const Game_Character& target) {
int sx = GetDistanceXfromCharacter(target);
int sy = GetDistanceYfromCharacter(target);

if ( std::abs(sx) > std::abs(sy) ) {
return (sx > 0) ? Left : Right;
Expand All @@ -546,9 +549,9 @@ int Game_Character::GetDirectionToHero() {
}
}

int Game_Character::GetDirectionAwayHero() {
int sx = DistanceXfromPlayer();
int sy = DistanceYfromPlayer();
int Game_Character::GetDirectionAwayCharacter(const Game_Character& target) {
int sx = GetDistanceXfromCharacter(target);
int sy = GetDistanceYfromCharacter(target);

if ( std::abs(sx) > std::abs(sy) ) {
return (sx > 0) ? Right : Left;
Expand All @@ -557,12 +560,12 @@ int Game_Character::GetDirectionAwayHero() {
}
}

void Game_Character::TurnTowardHero() {
SetDirection(GetDirectionToHero());
void Game_Character::TurnTowardCharacter(const Game_Character& target) {
SetDirection(GetDirectionToCharacter(target));
}

void Game_Character::TurnAwayFromHero() {
SetDirection(GetDirectionAwayHero());
void Game_Character::TurnAwayFromCharacter(const Game_Character& target) {
SetDirection(GetDirectionAwayCharacter(target));
}

void Game_Character::TurnRandom() {
Expand Down Expand Up @@ -598,10 +601,10 @@ bool Game_Character::BeginMoveRouteJump(int32_t& current_index, const lcf::rpg::
TurnRandom();
break;
case Code::move_towards_hero:
TurnTowardHero();
TurnTowardCharacter(GetPlayer());
break;
case Code::move_away_from_hero:
TurnAwayFromHero();
TurnAwayFromCharacter(GetPlayer());
break;
case Code::move_forward:
break;
Expand Down Expand Up @@ -642,10 +645,10 @@ bool Game_Character::BeginMoveRouteJump(int32_t& current_index, const lcf::rpg::
TurnRandom();
break;
case Code::face_hero:
TurnTowardHero();
TurnTowardCharacter(GetPlayer());
break;
case Code::face_away_from_hero:
TurnAwayFromHero();
TurnAwayFromCharacter(GetPlayer());
break;
default:
break;
Expand Down Expand Up @@ -731,8 +734,8 @@ bool Game_Character::Jump(int x, int y) {
return true;
}

int Game_Character::DistanceXfromPlayer() const {
int sx = GetX() - Main_Data::game_player->GetX();
int Game_Character::GetDistanceXfromCharacter(const Game_Character& target) const {
int sx = GetX() - target.GetX();
if (Game_Map::LoopHorizontal()) {
if (std::abs(sx) > Game_Map::GetTilesX() / 2) {
if (sx > 0)
Expand All @@ -744,8 +747,8 @@ int Game_Character::DistanceXfromPlayer() const {
return sx;
}

int Game_Character::DistanceYfromPlayer() const {
int sy = GetY() - Main_Data::game_player->GetY();
int Game_Character::GetDistanceYfromCharacter(const Game_Character& target) const {
int sy = GetY() - target.GetY();
if (Game_Map::LoopVertical()) {
if (std::abs(sy) > Game_Map::GetTilesY() / 2) {
if (sy > 0)
Expand All @@ -770,6 +773,7 @@ void Game_Character::ForceMoveRoute(const lcf::rpg::MoveRoute& new_route,
SetMoveFrequency(frequency);
SetMoveRouteOverwritten(true);
SetMoveRoute(new_route);
SetMoveFailureCount(0);
if (frequency != original_move_frequency) {
SetMaxStopCountForStep();
}
Expand Down Expand Up @@ -884,6 +888,12 @@ Game_Character* Game_Character::GetCharacter(int character_id, int event_id) {
}
}

Game_Character& Game_Character::GetPlayer() {
assert(Main_Data::game_player);

return *Main_Data::game_player;
}

int Game_Character::ReverseDir(int dir) {
constexpr static char reversed[] =
{ Down, Left, Up, Right, DownLeft, UpLeft, UpRight, DownRight };
Expand Down
56 changes: 46 additions & 10 deletions src/game_character.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,18 @@ class Game_Character {
*/
void SetMoveRouteFinished(bool finished);

/**
* @return How often the current move action failed.
*/
int GetMoveFailureCount() const;

/**
* Sets how often the current move action failed.
*
* @param count amount
*/
void SetMoveFailureCount(int count);

/**
* Gets sprite name. Usually the name of the graphic file.
*
Expand Down Expand Up @@ -627,11 +639,17 @@ class Game_Character {
*/
void Turn90DegreeLeftOrRight();

/** @return the direction we would need to face the hero. */
int GetDirectionToHero();
/**
* @param target Target character
* @return the direction we would need to face the target
*/
int GetDirectionToCharacter(const Game_Character& target);

/** @return the direction we would need to face away from hero. */
int GetDirectionAwayHero();
/**
* @param target Target character
* @return the direction we would need to face away from the target.
*/
int GetDirectionAwayCharacter(const Game_Character& target);

/**
* @param dir input direction
Expand Down Expand Up @@ -660,14 +678,14 @@ class Game_Character {
void TurnRandom();

/**
* Character looks towards the hero.
* @param target character looks towards this target.
*/
void TurnTowardHero();
void TurnTowardCharacter(const Game_Character& target);

/**
* Character looks away from the hero.
* @param target character looks away from this target.
*/
void TurnAwayFromHero();
void TurnAwayFromCharacter(const Game_Character& target);

/**
* Character waits for 20 frames more.
Expand Down Expand Up @@ -763,8 +781,17 @@ class Game_Character {
*/
void SetAnimationType(AnimType anim_type);

int DistanceXfromPlayer() const;
int DistanceYfromPlayer() const;
/**
* @param target Target to calculate distance of
* @return X distance to target
*/
int GetDistanceXfromCharacter(const Game_Character& target) const;

/**
* @param target Target to calculate distance of
* @return Y distance to target
*/
int GetDistanceYfromCharacter(const Game_Character& target) const;

/**
* Tests if the character is currently on the tile at x/y or moving
Expand Down Expand Up @@ -877,6 +904,7 @@ class Game_Character {
static int ReverseDir(int dir);

static Game_Character* GetCharacter(int character_id, int event_id);
static Game_Character& GetPlayer();

static constexpr int GetDxFromDirection(int dir);
static constexpr int GetDyFromDirection(int dir);
Expand Down Expand Up @@ -1059,6 +1087,14 @@ inline void Game_Character::SetMoveRouteFinished(bool finished) {
data()->move_route_finished = finished;
}

inline int Game_Character::GetMoveFailureCount() const {
return data()->easyrpg_move_failure_count;
}

inline void Game_Character::SetMoveFailureCount(int count) {
data()->easyrpg_move_failure_count = count;
}

inline const std::string& Game_Character::GetSpriteName() const {
return data()->sprite_name;
}
Expand Down
6 changes: 3 additions & 3 deletions src/game_event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ bool Game_Event::ScheduleForegroundExecution(bool by_decision_key, bool face_pla
}

if (face_player && !(IsFacingLocked() || IsSpinning())) {
SetFacing(GetDirectionToHero());
SetFacing(GetDirectionToCharacter(GetPlayer()));
}

data()->waiting_execution = true;
Expand Down Expand Up @@ -570,8 +570,8 @@ void Game_Event::MoveTypeTowardsOrAwayPlayer(bool towards) {
dir = Rand::GetRandomNumber(0, 3);
} else {
dir = towards
? GetDirectionToHero()
: GetDirectionAwayHero();
? GetDirectionToCharacter(GetPlayer())
: GetDirectionAwayCharacter(GetPlayer());
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/game_interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -833,7 +833,7 @@ bool Game_Interpreter::ExecuteCommand(lcf::rpg::EventCommand const& com) {
return CommandManiacControlStrings(com);
case Cmd::Maniac_CallCommand:
return CommandManiacCallCommand(com);
case static_cast<Game_Interpreter::Cmd>(2053): //Cmd::EasyRpg_SetInterpreterFlag
case Cmd::EasyRpg_SetInterpreterFlag: //Cmd::EasyRpg_SetInterpreterFlag
return CommandEasyRpgSetInterpreterFlag(com);
default:
return true;
Expand Down
63 changes: 62 additions & 1 deletion src/game_interpreter_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,10 @@ bool Game_Interpreter_Map::ExecuteCommand(lcf::rpg::EventCommand const& com) {
return CommandOpenLoadMenu(com);
case Cmd::ToggleAtbMode:
return CommandToggleAtbMode(com);
case static_cast <Game_Interpreter::Cmd>(2002): // Cmd::EasyRpg_TriggerEventAt
case Cmd::EasyRpg_TriggerEventAt:
return CommandEasyRpgTriggerEventAt(com);
case Cmd::EasyRpg_WaitForSingleMovement:
return CommandEasyRpgWaitForSingleMovement(com);
default:
return Game_Interpreter::ExecuteCommand(com);
}
Expand Down Expand Up @@ -781,3 +783,62 @@ bool Game_Interpreter_Map::CommandEasyRpgTriggerEventAt(lcf::rpg::EventCommand c

return true;
}

bool Game_Interpreter_Map::CommandEasyRpgWaitForSingleMovement(lcf::rpg::EventCommand const& com) {
if (!Player::HasEasyRpgExtensions()) {
return true;
}

_state.easyrpg_parameters.resize(3);

int& event_id = _state.easyrpg_parameters[0];
int& failure_limit = _state.easyrpg_parameters[1];
int& output_var = _state.easyrpg_parameters[2];

if (!_state.easyrpg_active) {
event_id = ValueOrVariable(com.parameters[0], com.parameters[1]);

if (com.parameters.size() >= 4) {
failure_limit = ValueOrVariable(com.parameters[2], com.parameters[3]);
}

if (com.parameters.size() >= 6) {
output_var = ValueOrVariable(com.parameters[4], com.parameters[5]);
}
}

_state.easyrpg_active = false;

Game_Character* chara = GetCharacter(event_id);
if (chara == nullptr) {
return true;
}

bool exists = chara->IsMoveRouteOverwritten();
bool finished = chara->IsMoveRouteFinished();

if (!exists || (exists && finished)) {
if (output_var > 0) {
// Move route inexistant or ended: Report success (1)
Main_Data::game_variables->Set(output_var, 1);
Game_Map::SetNeedRefresh(true);
}
return true;
}

// !finished
if (failure_limit == 0 || chara->GetMoveFailureCount() < failure_limit) {
// Below threshold: Yield
_state.easyrpg_active = true;
return false;
}

// Cancel move route and report abort (0)
chara->CancelMoveRoute();
if (output_var > 0) {
Main_Data::game_variables->Set(output_var, 0);
Game_Map::SetNeedRefresh(true);
}

return true;
}
1 change: 1 addition & 0 deletions src/game_interpreter_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ class Game_Interpreter_Map : public Game_Interpreter
bool CommandToggleAtbMode(lcf::rpg::EventCommand const& com);

bool CommandEasyRpgTriggerEventAt(lcf::rpg::EventCommand const& com);
bool CommandEasyRpgWaitForSingleMovement(lcf::rpg::EventCommand const& com);

AsyncOp ContinuationShowInnStart(int indent, int choice_result, int price);

Expand Down

0 comments on commit 65f80f9

Please sign in to comment.