1 /*
2  * This file is part of EasyRPG Player.
3  *
4  * EasyRPG Player is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * EasyRPG Player is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with EasyRPG Player. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef EP_SCENE_BATTLE_RPG2K3_H
19 #define EP_SCENE_BATTLE_RPG2K3_H
20 
21 // Headers
22 #include "scene_battle.h"
23 #include "async_handler.h"
24 #include "window_actorsp.h"
25 
26 // CBA constant
27 // The CBA move frame counter is incremented twice per frame in RPG_RT,
28 // so the effective frame count is 13
29 constexpr int cba_num_move_frames = 25;
30 
31 /**
32  * Scene_Battle class.
33  * Manages the battles.
34  */
35 class Scene_Battle_Rpg2k3 : public Scene_Battle {
36 public:
37 	/** The return value from a scene action state machine callback */
38 	enum class SceneActionReturn {
39 		/** Return from Update() and wait until the next frame */
40 		eWaitTillNextFrame,
41 		/** Continue processing this frame, unless CheckWait() etc.. requires us to block */
42 		eContinueThisFrame,
43 	};
44 
45 	/** The return value from a battle action state machine callback */
46 	enum class BattleActionReturn {
47 		/** The battle action is not yet finished but we can try again this frame */
48 		eContinue,
49 		/** The battle action is not yet finished and we need to wait for another frame*/
50 		eWait,
51 		/** The battle action is finished */
52 		eFinished,
53 	};
54 
55 	enum class EventTriggerType {
56 		eBeforeBattleAction,
57 		eAfterBattleAction,
58 		eAll,
59 	};
60 
61 	enum BattleActionState {
62 		BattleActionState_Begin,
63 		BattleActionState_PreEvents,
64 		BattleActionState_Conditions,
65 		BattleActionState_Notify,
66 		BattleActionState_Combo,
67 		BattleActionState_StartAlgo,
68 		BattleActionState_CBAInit,
69 		BattleActionState_CBAMove,
70 		BattleActionState_StartAnimation,
71 		BattleActionState_CBARangedWeaponInit,
72 		BattleActionState_CBARangedWeaponMove,
73 		BattleActionState_Animation,
74 		BattleActionState_AnimationReflect,
75 		BattleActionState_FinishPose,
76 		BattleActionState_Execute,
77 		BattleActionState_SwitchEvents,
78 		BattleActionState_Apply,
79 		BattleActionState_PostAction,
80 		BattleActionState_PostEvents,
81 		BattleActionState_Finished
82 	};
83 
84 public:
85 	explicit Scene_Battle_Rpg2k3(const BattleArgs& args);
86 	~Scene_Battle_Rpg2k3() override;
87 
88 	void Start() override;
89 	void Update() override;
90 	void OnPartyChanged(Game_Actor* actor, bool add) override;
91 	void OnEventHpChanged(Game_Battler* battler, int hp) override;
92 
93 protected:
94 	void Start2();
95 	void InitAtbGauge(Game_Battler& battler, int preempt_atb, int ambush_atb);
96 	void InitBattleCondition(lcf::rpg::System::BattleCondition condition);
97 	void InitEnemies();
98 	void InitActors();
99 	void InitAtbGauges();
100 
101 	void UpdateEnemiesDirection();
102 	void UpdateActorsDirection();
103 
104 	bool IsAtbAccumulating() const;
105 	bool IsBattleActionPending() const;
106 	void CreateEnemyActions();
107 	void CreateActorAutoActions();
108 	bool UpdateAtb();
109 	void UpdateAnimations();
110 	bool UpdateBattleState();
111 
112 	void OnSystem2Ready(FileRequestResult* result);
113 	void SetupSystem2Graphics();
114 	void CreateUi() override;
115 	void CreateEnemySprites();
116 	void CreateActorSprites();
117 	void ResetAllBattlerZ();
118 
119 	void CreateBattleTargetWindow();
120 	void CreateBattleStatusWindow();
121 	void CreateBattleCommandWindow();
122 	void RefreshTargetWindow();
123 	void RefreshCommandWindow(const Game_Actor* actor);
124 	void SetActiveActor(int idx);
125 
126 	void DrawFloatText(int x, int y, int color, StringView text);
127 
128 	bool IsTransparent() const;
129 
130 
131 	void SetState(Scene_Battle::State new_state) override;
132 
133 	void FaceTarget(Game_Actor& source, const Game_Battler& target);
134 
135 	void CommandSelected();
136 	void AttackSelected() override;
137 	void SubskillSelected(int command);
138 	void SpecialSelected();
139 	void EscapeSelected();
140 	void RowSelected();
141 
142 	void ActionSelectedCallback(Game_Battler* for_battler) override;
143 
144 	void ShowNotification(std::string text);
145 	void EndNotification();
146 
147 	bool IsEscapeAllowed() const = delete; // disable accidental calls to base class version
148 	bool IsEscapeAllowedFromOptionWindow() const;
149 	bool IsEscapeAllowedFromActorCommand() const;
150 
151 	bool CheckAnimFlip(Game_Battler* battler);
152 
153 	void SetWait(int min_wait, int max_wait);
154 	bool CheckWait();
155 
156 	void ResetWindows(bool make_invisible);
157 	void MoveCommandWindows(int x, int frames);
158 
159 	void SetSceneActionSubState(int substate);
160 	void ReturnToMainBattleState();
161 
162 	// SceneAction State Machine Driver
163 	SceneActionReturn ProcessSceneAction();
164 
165 	// SceneAction State Machine Handlers
166 	SceneActionReturn ProcessSceneActionStart();
167 	SceneActionReturn ProcessSceneActionFightAutoEscape();
168 	SceneActionReturn ProcessSceneActionActor();
169 	SceneActionReturn ProcessSceneActionAutoBattle();
170 	SceneActionReturn ProcessSceneActionCommand();
171 	SceneActionReturn ProcessSceneActionItem();
172 	SceneActionReturn ProcessSceneActionSkill();
173 	SceneActionReturn ProcessSceneActionEnemyTarget();
174 	SceneActionReturn ProcessSceneActionAllyTarget();
175 	SceneActionReturn ProcessSceneActionBattle();
176 	SceneActionReturn ProcessSceneActionVictory();
177 	SceneActionReturn ProcessSceneActionDefeat();
178 	SceneActionReturn ProcessSceneActionEscape();
179 
180 	void NextTurn(Game_Battler* battler);
181 	bool CheckBattleEndAndScheduleEvents(EventTriggerType tt, Game_Battler* source);
182 	bool CheckBattleEndConditions();
183 
184 	void SetBattleActionState(BattleActionState state);
185 
186 	/** Battle Action Driver */
187 	BattleActionReturn ProcessBattleAction(Game_BattleAlgorithm::AlgorithmBase* action);
188 
189 	/** Battle Action State Machine callbacks */
190 	BattleActionReturn ProcessBattleActionBegin(Game_BattleAlgorithm::AlgorithmBase* action);
191 	BattleActionReturn ProcessBattleActionPreEvents(Game_BattleAlgorithm::AlgorithmBase* action);
192 	BattleActionReturn ProcessBattleActionConditions(Game_BattleAlgorithm::AlgorithmBase* action);
193 	BattleActionReturn ProcessBattleActionNotify(Game_BattleAlgorithm::AlgorithmBase* action);
194 	BattleActionReturn ProcessBattleActionCombo(Game_BattleAlgorithm::AlgorithmBase* action);
195 	BattleActionReturn ProcessBattleActionStartAlgo(Game_BattleAlgorithm::AlgorithmBase* action);
196 	BattleActionReturn ProcessBattleActionCBAInit(Game_BattleAlgorithm::AlgorithmBase* action);
197 	BattleActionReturn ProcessBattleActionCBAMove(Game_BattleAlgorithm::AlgorithmBase* action);
198 	BattleActionReturn ProcessBattleActionStartAnimation(Game_BattleAlgorithm::AlgorithmBase* action);
199 	BattleActionReturn ProcessBattleActionCBARangedWeaponInit(Game_BattleAlgorithm::AlgorithmBase* action);
200 	BattleActionReturn ProcessBattleActionCBARangedWeaponMove(Game_BattleAlgorithm::AlgorithmBase* action);
201 	BattleActionReturn ProcessBattleActionAnimation(Game_BattleAlgorithm::AlgorithmBase* action);
202 	BattleActionReturn ProcessBattleActionAnimationReflect(Game_BattleAlgorithm::AlgorithmBase* action);
203 	BattleActionReturn ProcessBattleActionFinishPose(Game_BattleAlgorithm::AlgorithmBase* action);
204 	BattleActionReturn ProcessBattleActionExecute(Game_BattleAlgorithm::AlgorithmBase* action);
205 	BattleActionReturn ProcessBattleActionSwitchEvents(Game_BattleAlgorithm::AlgorithmBase* action);
206 	BattleActionReturn ProcessBattleActionApply(Game_BattleAlgorithm::AlgorithmBase* action);
207 	BattleActionReturn ProcessBattleActionPostAction(Game_BattleAlgorithm::AlgorithmBase* action);
208 	BattleActionReturn ProcessBattleActionPostEvents(Game_BattleAlgorithm::AlgorithmBase* action);
209 	BattleActionReturn ProcessBattleActionFinished(Game_BattleAlgorithm::AlgorithmBase* action);
210 
211 	std::vector<std::string> GetBattleCommandNames(const Game_Actor* actor);
212 	void SetBattleCommandsDisable(Window_Command& window, const Game_Actor* actor);
213 
214 	std::unique_ptr<Sprite> ally_cursor, enemy_cursor;
215 
216 	struct FloatText {
217 		std::shared_ptr<Sprite> sprite;
218 		int remaining_time = 30;
219 	};
220 
221 	std::vector<FloatText> floating_texts;
222 	int battle_action_wait = 0;
223 	int battle_action_min_wait = 0;
224 	int scene_action_substate = 0;
225 	int battle_action_state = BattleActionState_Begin;
226 	int battle_end_timer = 0;
227 
228 	std::unique_ptr<Window_ActorSp> sp_window;
229 	void RecreateSpWindow(Game_Battler* battler);
230 
231 	FileRequestBinding request_id;
232 	std::shared_ptr<Game_BattleAlgorithm::AlgorithmBase> pending_battle_action = {};
233 	bool first_strike = false;
234 	bool running_away = false;
235 	bool resume_from_debug_scene = false;
236 	bool auto_battle = false;
237 
238 	// CBA stuff
239 	void CBAInit();
240 	void CBAMove();
241 
242 	Game_BattleAlgorithm::AlgorithmBase* cba_action;
243 	bool cba_direction_back = false;
244 	int cba_move_frame = 0;
245 	Point cba_start_pos;
246 	Point cba_end_pos;
247 
248 	std::vector<std::pair<Game_Battler&, std::unique_ptr<Sprite_Weapon>>> cba_ranged;
249 	Point cba_ranged_center;
250 	int cba_ranged_weapon_move_frame = 0;
251 	int cba_num_ranged_weapon_move_frames = 60;
252 };
253 
254 #endif
255