diff --git a/src/feature.cpp b/src/feature.cpp index 136c8ec57b..c7e5e2e576 100644 --- a/src/feature.cpp +++ b/src/feature.cpp @@ -47,3 +47,12 @@ bool Feature::HasPlaceholders() { return Player::IsRPG2k3() && HasRpg2kBattleSystem() && lcf::Data::system.easyrpg_battle_use_rpg2ke_strings; } + +bool Feature::HasFixedActorFacingDirection() { + return HasRpg2k3BattleSystem() && lcf::Data::battlecommands.easyrpg_fixed_actor_facing_direction > 0; +} + +bool Feature::HasFixedEnemyFacingDirection() { + return HasRpg2k3BattleSystem() && lcf::Data::battlecommands.easyrpg_fixed_enemy_facing_direction > 0; +} + diff --git a/src/feature.h b/src/feature.h index 04f40e3a00..2710c0c785 100644 --- a/src/feature.h +++ b/src/feature.h @@ -41,6 +41,16 @@ namespace Feature { * @return true if text placeholders are used */ bool HasPlaceholders(); + + /** + * @return true if fixed actor facing direction is used + */ + bool HasFixedActorFacingDirection(); + + /** + * @return true if fixed enemy facing direction is used + */ + bool HasFixedEnemyFacingDirection(); } #endif diff --git a/src/game_battler.h b/src/game_battler.h index e8b792f2bf..a2c392c124 100644 --- a/src/game_battler.h +++ b/src/game_battler.h @@ -170,7 +170,7 @@ class Game_Battler { /** * Gets the base attribute rate when actor is damaged, without battle attribute shifts. - * + * * @param attribute_id Attribute to query * @return Attribute rate */ @@ -178,7 +178,7 @@ class Game_Battler { /** * Gets the attribute rate when actor is damaged. - * + * * @param attribute_id Attribute to query * @return Attribute rate */ @@ -431,6 +431,9 @@ class Game_Battler { /** @return whether the battler is facing the opposite it's normal direction */ bool IsDirectionFlipped() const; + /** @return whether the battler's sprite should be facing the opposite it's normal direction */ + bool IsSpriteDirectionFlipped() const; + /** * Set whether the battler is facing the opposite it's normal direction * @@ -1155,4 +1158,14 @@ inline int Game_Battler::CalculateWeaponSpCost(Weapon) const { return 0; } +inline bool Game_Battler::IsSpriteDirectionFlipped() const { + switch (GetBattleSprite()->GetFixedFacing()) { + case Sprite_Battler::AlwaysFlipped: + return true; + case Sprite_Battler::NeverFlipped: + return false; + default: + return IsDirectionFlipped(); + } +} #endif diff --git a/src/scene_battle_rpg2k3.cpp b/src/scene_battle_rpg2k3.cpp index 95fd91af00..9b4f00cb90 100644 --- a/src/scene_battle_rpg2k3.cpp +++ b/src/scene_battle_rpg2k3.cpp @@ -554,6 +554,8 @@ void Scene_Battle_Rpg2k3::CreateBattleTargetWindow() { int transp = IsTransparent() ? 160 : 255; target_window->SetBackOpacity(transp); } + + target_window->SetSingleColumnWrapping(true); } void Scene_Battle_Rpg2k3::RefreshTargetWindow() { @@ -1744,6 +1746,7 @@ Scene_Battle_Rpg2k3::SceneActionReturn Scene_Battle_Rpg2k3::ProcessSceneActionVi auto* sprite = actor->GetActorBattleSprite(); if (actor->Exists() && sprite) { sprite->SetNormalAttacking(false); + sprite->ResetFixedFacingDirection(); auto* weapon = actor->GetWeaponSprite(); if (weapon) { weapon->StopAttack(); diff --git a/src/sprite_actor.cpp b/src/sprite_actor.cpp index 93d95da4b4..7d002c85b2 100644 --- a/src/sprite_actor.cpp +++ b/src/sprite_actor.cpp @@ -28,11 +28,17 @@ #include "player.h" #include #include "output.h" +#include "feature.h" +#include "game_battle.h" Sprite_Actor::Sprite_Actor(Game_Actor* actor) : Sprite_Battler(actor, actor->GetId()) { CreateSprite(); + auto condition = Game_Battle::GetBattleCondition(); + if ((condition == lcf::rpg::System::BattleCondition_none || condition == lcf::rpg::System::BattleCondition_initiative) && Feature::HasFixedActorFacingDirection()) { + fixed_facing = static_cast(lcf::Data::battlecommands.easyrpg_fixed_actor_facing_direction); + } } Sprite_Actor::~Sprite_Actor() { @@ -60,7 +66,7 @@ void Sprite_Actor::Update() { if (animation) { // Is a battle animation - animation->SetInvert(battler->IsDirectionFlipped()); + animation->SetInvert(battler->IsSpriteDirectionFlipped()); animation->Update(); if (animation->IsDone()) { @@ -284,6 +290,7 @@ void Sprite_Actor::Draw(Bitmap& dst) { int steps = static_cast(256 / images.size()); int opacity = steps; for (auto it = images.crbegin(); it != images.crend(); ++it) { + Sprite_Battler::SetFixedFlipX(); Sprite_Battler::SetX(it->x); Sprite_Battler::SetY(it->y); Sprite_Battler::SetOpacity(std::min(opacity, 255)); diff --git a/src/sprite_battler.h b/src/sprite_battler.h index f7b078054b..e2fe93a8ba 100644 --- a/src/sprite_battler.h +++ b/src/sprite_battler.h @@ -30,6 +30,11 @@ class Game_Battler; */ class Sprite_Battler : public Sprite { public: + enum FixedFacing { + Disabled = 0, + AlwaysFlipped = 1, + NeverFlipped = 2, + }; /** * Constructor. * @@ -44,6 +49,15 @@ class Sprite_Battler : public Sprite { void SetBattler(Game_Battler* new_battler); + void ResetFixedFacingDirection(); + + FixedFacing GetFixedFacing() const; + + /** + * Sets the sprite flip when fixed facing direction is enabled. Otherwise does nothing.. + */ + void SetFixedFlipX(); + /** * Recompute the Z value for the sprite from it's Y coordinate. */ @@ -52,6 +66,7 @@ class Sprite_Battler : public Sprite { protected: Game_Battler* battler = nullptr; int battle_index = 0; + FixedFacing fixed_facing = Disabled; }; inline Game_Battler* Sprite_Battler::GetBattler() const { @@ -62,5 +77,25 @@ inline void Sprite_Battler::SetBattler(Game_Battler* new_battler) { battler = new_battler; } +inline void Sprite_Battler::ResetFixedFacingDirection() { + fixed_facing = Disabled; +} + +inline void Sprite_Battler::SetFixedFlipX() { + switch (fixed_facing) { + case AlwaysFlipped: + SetFlipX(true); + break; + case NeverFlipped: + SetFlipX(false); + break; + default: + break; + } +} + +inline Sprite_Battler::FixedFacing Sprite_Battler::GetFixedFacing() const { + return fixed_facing; +} #endif diff --git a/src/sprite_enemy.cpp b/src/sprite_enemy.cpp index 10e193b491..f19c4c90d1 100644 --- a/src/sprite_enemy.cpp +++ b/src/sprite_enemy.cpp @@ -26,11 +26,17 @@ #include "player.h" #include #include "output.h" +#include "feature.h" +#include "game_battle.h" Sprite_Enemy::Sprite_Enemy(Game_Enemy* enemy) : Sprite_Battler(enemy, enemy->GetTroopMemberId()) { CreateSprite(); + auto condition = Game_Battle::GetBattleCondition(); + if ((condition == lcf::rpg::System::BattleCondition_none || condition == lcf::rpg::System::BattleCondition_initiative) && Feature::HasFixedEnemyFacingDirection()) { + fixed_facing = static_cast(lcf::Data::battlecommands.easyrpg_fixed_enemy_facing_direction); + } } Sprite_Enemy::~Sprite_Enemy() { @@ -119,7 +125,11 @@ void Sprite_Enemy::Draw(Bitmap& dst) { SetX(enemy->GetDisplayX()); SetY(enemy->GetDisplayY()); SetFlashEffect(enemy->GetFlashColor()); - SetFlipX(enemy->IsDirectionFlipped()); + if (fixed_facing != Disabled) { + SetFixedFlipX(); + } else { + SetFlipX(enemy->IsDirectionFlipped()); + } Sprite_Battler::Draw(dst); } diff --git a/src/window_battlestatus.cpp b/src/window_battlestatus.cpp index 9ddd6e22eb..f3be182ff7 100644 --- a/src/window_battlestatus.cpp +++ b/src/window_battlestatus.cpp @@ -283,7 +283,7 @@ void Window_BattleStatus::Update() { } if (active && index >= 0) { - if (Input::IsRepeated(Input::DOWN) || Input::IsTriggered(Input::SCROLL_DOWN)) { + if (Input::IsRepeated(Input::DOWN) || Input::IsRepeated(Input::RIGHT) || Input::IsTriggered(Input::SCROLL_DOWN)) { Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Cursor)); for (int i = 1; i < item_max; i++) { int new_index = (index + i) % item_max; @@ -293,7 +293,7 @@ void Window_BattleStatus::Update() { } } } - if (Input::IsRepeated(Input::UP) || Input::IsTriggered(Input::SCROLL_UP)) { + if (Input::IsRepeated(Input::UP) || Input::IsRepeated(Input::LEFT) || Input::IsTriggered(Input::SCROLL_UP)) { Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Cursor)); for (int i = item_max - 1; i > 0; i--) { int new_index = (index + i) % item_max; diff --git a/src/window_selectable.cpp b/src/window_selectable.cpp index c8ca714e10..a414a7e260 100644 --- a/src/window_selectable.cpp +++ b/src/window_selectable.cpp @@ -195,13 +195,13 @@ void Window_Selectable::Update() { } } if (Input::IsRepeated(Input::RIGHT)) { - if (column_max >= 2 && index < item_max - 1) { + if (column_max >= wrap_limit && index < item_max - 1) { Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Cursor)); index += 1; } } if (Input::IsRepeated(Input::LEFT)) { - if (column_max >= 2 && index > 0) { + if (column_max >= wrap_limit && index > 0) { Main_Data::game_system->SePlay(Main_Data::game_system->GetSystemSE(Main_Data::game_system->SFX_Cursor)); index -= 1; } @@ -234,3 +234,7 @@ void Window_Selectable::SetEndlessScrolling(bool state) { void Window_Selectable::SetMenuItemHeight(int height) { menu_item_height = height; } + +void Window_Selectable::SetSingleColumnWrapping(bool wrap) { + wrap_limit = wrap ? 1 : 2; +} diff --git a/src/window_selectable.h b/src/window_selectable.h index 25caf3254f..b676f7140d 100644 --- a/src/window_selectable.h +++ b/src/window_selectable.h @@ -92,6 +92,14 @@ class Window_Selectable: public Window_Base { */ void SetMenuItemHeight(int height); + /** + * Allow left/right input to move cursor up/down when the selectable has only one column. + * By default this behaviour is only enabled for two and more columns. + * + * @param wrap enable/disable single column wrap + */ + void SetSingleColumnWrapping(bool wrap); + protected: void UpdateArrows(); @@ -107,6 +115,8 @@ class Window_Selectable: public Window_Base { int scroll_dir = 0; int scroll_progress = 0; + + int wrap_limit = 2; }; inline void Window_Selectable::SetItemMax(int value) {