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_GAME_BATTLEALGORITHM_H
19 #define EP_GAME_BATTLEALGORITHM_H
20 
21 #include <string>
22 #include <vector>
23 #include <bitset>
24 #include <lcf/rpg/fwd.h>
25 #include <lcf/rpg/state.h>
26 #include "string_view.h"
27 #include "game_battler.h"
28 
29 class Game_Battler;
30 class Game_Party_Base;
31 
32 /**
33  * Contains algorithms to handle the different battle attacks, skills and items.
34  * The algorithms support single targets and party targets.
35  * For party targets the caller is responsible for retargeting using TargetNext.
36  *
37  * The action is simulated using Execute and the results can be applied after the
38  * simulation by calling Apply.
39  */
40 namespace Game_BattleAlgorithm {
41 
42 enum class Type {
43 	None,
44 	Normal,
45 	Skill,
46 	Item,
47 	Defend,
48 	Observe,
49 	Charge,
50 	SelfDestruct,
51 	Escape,
52 	Transform,
53 	DoNothing,
54 };
55 
56 struct StateEffect {
57 	enum Effect : int16_t {
58 		None,
59 		Inflicted,
60 		AlreadyInflicted,
61 		Healed,
62 		HealedByAttack
63 	};
64 	int16_t state_id = 0;
65 	Effect effect = None;
66 
67 	StateEffect() = default;
StateEffectStateEffect68 	StateEffect(int state_id, Effect effect)
69 		: state_id(state_id), effect(effect) {}
70 };
71 
72 struct AttributeEffect {
73 	int16_t attr_id = 0;
74 	int16_t shift = 0;
75 
76 	AttributeEffect() = default;
AttributeEffectAttributeEffect77 	AttributeEffect(int id, int shift)
78 		: attr_id(id), shift(shift) {}
79 };
80 
81 class AlgorithmBase {
82 public:
~AlgorithmBase()83 	virtual ~AlgorithmBase() {}
84 
85 	/** @return the source of the battle action. */
86 	Game_Battler* GetSource() const;
87 
88 	/** @return current target battler */
89 	Game_Battler* GetTarget() const;
90 
91 	/** @return If the action was reflected, returns the target which triggered the reflect */
92 	Game_Battler* GetReflectTarget() const;
93 
94 	/** @return true if this algorithm targets a party */
95 	Game_Party_Base* GetOriginalPartyTarget() const;
96 
97 	/** @return the original targets of the action before reflect or other modifications */
98 	Span<Game_Battler* const> GetOriginalTargets() const;
99 
100 	/** @return If the action originally had a single target, return that target. Otherwise return nullptr */
101 	Game_Battler* GetOriginalSingleTarget() const;
102 
103 	/** @return the current repetition of the algorithm */
104 	int GetCurrentRepeat() const;
105 
106 	/** @return the total number of times this algo will repeat */
107 	int GetTotalRepetitions() const;
108 
109 	/** Initializes targetting and performs any initial actions such as sp cost reduction for the user. */
110 	void Start();
111 
112 	/**
113 	 * If IsReflected(target) true on any target, will reflect the action back on the source or the source's party.
114 	 *
115 	 * @return true if this algo was reflected.
116 	 */
117 	bool ReflectTargets();
118 
119 	/**
120 	 * Add a new target to the algo.
121 	 *
122 	 * @param target the target to add
123 	 * @param set_current Whether or not to reset the current target to this one
124 	 */
125 	void AddTarget(Game_Battler* target, bool set_current);
126 
127 	/**
128 	 * Add all party targets to the algo.
129 	 *
130 	 * @param targets the party to add
131 	 * @param set_current Whether or not to reset the current target to the first member of the party
132 	 */
133 	void AddTargets(Game_Party_Base* party, bool set_current);
134 
135 	/**
136 	 * Changes the target reference to the next target.
137 	 * When reaches the last target, will return false and reset back to first target.
138 	 *
139 	 * @return true if there was a next target available.
140 	 */
141 	bool TargetNext();
142 
143 	/**
144 	 * Performs the next repeated action.
145 	 *
146 	 * @param require_valid_target only repeat if current target is valid.
147 	 * @return true if the action should be repeated. Once false is returned, the repetition resets.
148 	 */
149 	bool RepeatNext(bool require_valid_target);
150 
151 	/**
152 	 * Defines switches that will be switched on after the action is finished.
153 	 * Multiple calls to this function will add additional switches to the list.
154 	 *
155 	 * @param switch_id Switch to turn on
156 	 */
157 	void SetSwitchEnable(int switch_id);
158 
159 	/**
160 	 * Defines switches that will be switched off after the action is finished.
161 	 * Multiple calls to this function will add additional switches to the list.
162 	 *
163 	 * @param switch_id Switch to turn off
164 	 */
165 	void SetSwitchDisable(int switch_id);
166 
167 	/** @return activated switch id or 0 when algorithm didn't affect a switch */
168 	int GetAffectedSwitch() const;
169 
170 	/** @return true if this action affects hp. */
171 	bool IsAffectHp() const;
172 
173 	/** @return true if this action absorbs hp. */
174 	bool IsAbsorbHp() const;
175 
176 	/** @return true if this action affects sp. */
177 	bool IsAffectSp() const;
178 
179 	/** @return true if this action absorbs sp. */
180 	bool IsAbsorbSp() const;
181 
182 	/** @return true if this action affects atk. */
183 	bool IsAffectAtk() const;
184 
185 	/** @return true if this action absorbs atk. */
186 	bool IsAbsorbAtk() const;
187 
188 	/** @return true if this action affects def. */
189 	bool IsAffectDef() const;
190 
191 	/** @return true if this action absorbs def. */
192 	bool IsAbsorbDef() const;
193 
194 	/** @return true if this action affects spi. */
195 	bool IsAffectSpi() const;
196 
197 	/** @return true if this action absorbs spi. */
198 	bool IsAbsorbSpi() const;
199 
200 	/** @return true if this action affects agi. */
201 	bool IsAffectAgi() const;
202 
203 	/** @return true if this action affects agi. */
204 	bool IsAbsorbAgi() const;
205 
206 	/** @return signed value of how much hp is to be gained or lost */
207 	int GetAffectedHp() const;
208 
209 	/** @return signed value of how much sp is to be gained or lost */
210 	int GetAffectedSp() const;
211 
212 	/** @return signed value of how much attack is to be gained or lost */
213 	int GetAffectedAtk() const;
214 
215 	/** @return signed value of how much defense is to be gained or lost */
216 	int GetAffectedDef() const;
217 
218 	/** @return signed value of how much spirit is to be gained or lost */
219 	int GetAffectedSpi() const;
220 
221 	/** @return signed value of how much agility is to be gained or lost */
222 	int GetAffectedAgi() const;
223 
224 	/** @return all states changes caused by this action in order. */
225 	const std::vector<StateEffect>& GetStateEffects() const;
226 
227 	/** @return all attributes which are shifited by this action. */
228 	const std::vector<AttributeEffect>& GetShiftedAttributes() const;
229 
230 	/**
231 	 * Returns whether the action hit the target.
232 	 * This function returns the same as the last Execute-call.
233 	 *
234 	 * @return if the action hit the target
235 	 */
236 	bool IsSuccess() const;
237 
238 	/** @return Whether action was positive (e.g. healing) instead of damage. */
239 	bool IsPositive() const;
240 
241 	/** @return Whether target will be revived from death */
242 	bool IsRevived() const;
243 
244 	/** @return if the last action was a critical hit.  */
245 	bool IsCriticalHit() const;
246 
247 	/**
248 	 * Gets the Battle Animation that is assigned to the Algorithm
249 	 *
250 	 * @param i Which animation to fetch, starting from 0.
251 	 * @return Battle Animation id or 0 if no animation is assigned
252 	 */
253 	virtual int GetAnimationId(int i) const;
254 
255 	/**
256 	 * Plays the battle animation on all valid targets starting from the current target to the last target.
257 	 * Takes care of single and multi-target animations.
258 	 *
259 	 * @param anim_id the ID of the animation to play.
260 	 * @param sound_only Only play sounds
261 	 * @param cutoff If >= 0 maximum number of frames to play
262 	 * @param invert Flips the animation
263 	 * @return the number of frames the animation will play
264 	 */
265 	int PlayAnimation(int anim_id, bool sound_only = false, int cutoff = -1, bool invert = false);
266 
267 	/**
268 	 * Executes the algorithm. Must be called before using the other functions.
269 	 * This function only simulates the Algorithm, call Apply to add the
270 	 * changes of the last Execute call to the target.
271 	 *
272 	 * @return true if the action was successful, false if failed/dodged
273 	 */
274 	bool Execute();
275 
276 	/** Apply custom effects */
277 	virtual void ApplyCustomEffect();
278 
279 	/**
280 	 * Apply switch enabled by action
281 	 * @return the switch id enabled, or 0 if none.
282 	 */
283 	int ApplySwitchEffect();
284 
285 	/**
286 	 * Apply hp damage or healing.
287 	 * @note Hp healing is not applied if the action revivies
288 	 * @return the amount of hp changed.
289 	 */
290 	int ApplyHpEffect();
291 
292 	/**
293 	 * Apply sp increase or decrease.
294 	 * @return the amount of sp changed.
295 	 */
296 	int ApplySpEffect();
297 
298 	/**
299 	 * Apply atk increase or decrease.
300 	 * @return the amount of atk changed.
301 	 */
302 	int ApplyAtkEffect();
303 
304 	/**
305 	 * Apply def increase or decrease.
306 	 * @return the amount of def changed.
307 	 */
308 	int ApplyDefEffect();
309 
310 	/**
311 	 * Apply spi increase or decrease.
312 	 * @return the amount of spi changed.
313 	 */
314 	int ApplySpiEffect();
315 
316 	/**
317 	 * Apply agi increase or decrease.
318 	 * @return the amount of agi changed.
319 	 */
320 	int ApplyAgiEffect();
321 
322 	/**
323 	 * Apply the given state effect.
324 	 * @return true if state was successfully added or removed.
325 	 */
326 	bool ApplyStateEffect(StateEffect se);
327 
328 	/** Apply all state effects */
329 	void ApplyStateEffects();
330 
331 	/**
332 	 * Apply the given attribute effect
333 	 * @return the amount the attribute was shifted.
334 	 */
335 	int ApplyAttributeShiftEffect(AttributeEffect ae);
336 
337 	/** Apply all attribute effects */
338 	void ApplyAttributeShiftEffects();
339 
340 	/** Apply all effects in order */
341 	void ApplyAll();
342 
343 	/** Apply switches set on the action externally (e.g. enemy actions) */
344 	void ProcessPostActionSwitches();
345 
346 	/**
347 	 * Tests if it makes sense to apply an action on the target.
348 	 * E.g. when it is dead.
349 	 *
350 	 * @param target the target to check
351 	 * @return true if valid, in case of false another target should be selected.
352 	 */
353 	virtual bool IsTargetValid(const Game_Battler& target) const;
354 
355 	/** @return whether the current target is valid */
356 	bool IsCurrentTargetValid() const;
357 
358 	/**
359 	 * Gets the first line message that is displayed when the action is invoked.
360 	 * Usually of style "[Name] uses/casts [Weapon/Item/Skill]".
361 	 *
362 	 * @param line which line of the message to fetch
363 	 * @return message
364 	 */
365 	virtual std::string GetStartMessage(int line) const;
366 
367 	/** @return the pose the source should be in when performing the action */
368 	virtual int GetSourcePose() const;
369 
370 	/** @return the CBA movement to use when performing the action */
371 	virtual int GetCBAMovement() const;
372 
373 	/** @return the CBA afterimage setting to use when performing the action */
374 	virtual int GetCBAAfterimage() const;
375 
376 	/** @return true if it is still possible to perform this action now.  */
377 	virtual bool ActionIsPossible() const;
378 
379 	/** @return the weapon animation data for this action (if applicable) */
380 	virtual const lcf::rpg::BattlerAnimationItemSkill* GetWeaponAnimationData() const;
381 
382 	/** @return the weapon data for this action (if applicable) */
383 	virtual const lcf::rpg::Item* GetWeaponData() const;
384 
385 	/**
386 	 * Gets the sound effect that is played when the action is starting.
387 	 *
388 	 * @return start se
389 	 */
390 	virtual const lcf::rpg::Sound* GetStartSe() const;
391 
392 	/**
393 	 * Gets the sound effect that is played then the action fails.
394 	 *
395 	 * @return result se
396 	 */
397 	virtual const lcf::rpg::Sound* GetFailureSe() const;
398 
399 	/**
400 	 * Returns the message used when the action fails.
401 	 *
402 	 * @return failure message
403 	 */
404 	virtual std::string GetFailureMessage() const;
405 
406 	/**
407 	 * Returns whether the attack would be reflected if used upon the target.
408 	 *
409 	 * @param the target to check
410 	 * @return true when reflected
411 	 */
412 	virtual bool IsReflected(const Game_Battler& target) const;
413 
414 	/**
415 	 * Returns the algorithm type of this object.
416 	 */
417 	Type GetType() const;
418 
419 	/**
420 	 * Set number of times to repeat the same action on a target
421 	 */
422 	void SetRepeat(int repeat);
423 
424 	/**
425 	 * Apply a combo number of hits to repeat the action.
426 	 *
427 	 * @param hits the number of combo hits
428 	 */
429 	virtual void ApplyComboHitsMultiplier(int hits);
430 
431 	/**
432 	 * Set the affected switch id
433 	 * @param s the switch id
434 	 */
435 	int SetAffectedSwitch(int s);
436 
437 	/**
438 	 * Set the affected hp
439 	 * @param hp the signed hp gain/loss value
440 	 */
441 	int SetAffectedHp(int hp);
442 
443 	/**
444 	 * Set whether the effect will absorb hp from the target
445 	 * @param a whether to absorb or not.
446 	 */
447 	bool SetIsAbsorbHp(bool a);
448 
449 	/**
450 	 * Set the affected sp
451 	 * @param hp the signed sp gain/loss value
452 	 */
453 	int SetAffectedSp(int sp);
454 
455 	/**
456 	 * Set whether the effect will absorb sp from the target
457 	 * @param a whether to absorb or not.
458 	 */
459 	bool SetIsAbsorbSp(bool a);
460 
461 	/**
462 	 * Set the affected atk
463 	 * @param hp the signed atk gain/loss value
464 	 */
465 	int SetAffectedAtk(int hp);
466 
467 	/**
468 	 * Set whether the effect will absorb atk from the target
469 	 * @param a whether to absorb or not.
470 	 */
471 	bool SetIsAbsorbAtk(bool a);
472 
473 	/**
474 	 * Set the affected def
475 	 * @param hp the signed def gain/loss value
476 	 */
477 	int SetAffectedDef(int hp);
478 
479 	/**
480 	 * Set whether the effect will absorb def from the target
481 	 * @param a whether to absorb or not.
482 	 */
483 	bool SetIsAbsorbDef(bool a);
484 
485 	/**
486 	 * Set the affected spi
487 	 * @param hp the signed spi gain/loss value
488 	 */
489 	int SetAffectedSpi(int hp);
490 
491 	/**
492 	 * Set whether the effect will absorb spi from the target
493 	 * @param a whether to absorb or not.
494 	 */
495 	bool SetIsAbsorbSpi(bool a);
496 
497 	/**
498 	 * Set the affected agi
499 	 * @param hp the signed agi gain/loss value
500 	 */
501 	int SetAffectedAgi(int hp);
502 
503 	/**
504 	 * Set whether the effect will absorb agi from the target
505 	 * @param a whether to absorb or not.
506 	 */
507 	bool SetIsAbsorbAgi(bool a);
508 
509 	/**
510 	 * Add a state effect
511 	 * @param se the state effect to add
512 	 */
513 	void AddAffectedState(StateEffect se);
514 
515 	/**
516 	 * Add an attribute shift effect
517 	 * @param se the attribute shift effect to add
518 	 */
519 	void AddAffectedAttribute(AttributeEffect ae);
520 
521 	/**
522 	 * Set if the original intention was positive (healing)
523 	 * @param p if positive or not
524 	 */
525 	bool SetIsPositive(bool p);
526 
527 	/**
528 	 * Set if the effect was a critical hit
529 	 * @param c if critical hit or not
530 	 */
531 	bool SetIsCriticalHit(bool c);
532 
533 	/** Set if the algo was a success  */
534 	bool SetIsSuccess();
535 
536 	/**
537 	 * Set the algo to successful if the condition is true. If it's false, no change.
538 	 * @param x condition to check
539 	 */
540 	bool SetIsSuccessIf(bool x);
541 
542 	/** Set if the algo failed  */
543 	bool SetIsFailure();
544 
545 protected:
546 	AlgorithmBase(Type t, Game_Battler* source, Game_Battler* target);
547 	AlgorithmBase(Type t, Game_Battler* source, std::vector<Game_Battler*> targets);
548 	AlgorithmBase(Type t, Game_Battler* source, Game_Party_Base* target);
549 	virtual bool vStart();
550 	virtual bool vExecute();
551 
552 	void Reset();
553 
554 	/**
555 	 * Implements logic of TargetNext but ignores reflect.
556 	 * Used by const-functions that restore the old state afterwards.
557 	 * So technically this function is non-const but due to the help of the
558 	 * other functions the behaviour to the callee is const...
559 	 *
560 	 * @return true if there was a next target available
561 	 */
562 	bool TargetNextInternal();
563 
564 	void BattlePhysicalStateHeal(int physical_rate, std::vector<int16_t>& target_states, const PermanentStates& ps);
565 
566 private:
567 	Type type = Type::None;
568 	Game_Battler* source = nullptr;
569 	std::vector<Game_Battler*> targets;
570 	std::vector<Game_Battler*>::iterator current_target;
571 	Game_Party_Base* party_target = nullptr;
572 	Game_Battler* reflect_target = nullptr;
573 
574 	int hp = 0;
575 	int sp = 0;
576 	int attack = 0;
577 	int defense = 0;
578 	int spirit = 0;
579 	int agility = 0;
580 	int switch_id = 0;
581 
582 	enum Flag {
583 		eSuccess,
584 		ePositive,
585 		eCriticalHit,
586 		eRevived,
587 		eAffectHp,
588 		eAbsorbHp,
589 		eAffectSp,
590 		eAbsorbSp,
591 		eAffectAtk,
592 		eAbsorbAtk,
593 		eAffectDef,
594 		eAbsorbDef,
595 		eAffectSpi,
596 		eAbsorbSpi,
597 		eAffectAgi,
598 		eAbsorbAgi,
599 	};
600 	std::bitset<64> flags = {};
601 	int num_original_targets = 0;
602 	int cur_repeat = 0;
603 	int repeat = 1;
604 
605 	std::vector<StateEffect> states;
606 	std::vector<AttributeEffect> attributes;
607 	std::vector<int> switch_on;
608 	std::vector<int> switch_off;
609 
610 	bool SetFlag(Flag f, bool value);
611 	bool GetFlag(Flag f) const;
612 };
613 
614 // Special algorithm for handling non-moving because of states
615 class None : public AlgorithmBase {
616 public:
617 	None(Game_Battler* source);
618 };
619 
620 
621 class Normal : public AlgorithmBase {
622 public:
623 	enum Style {
624 		/** 2k style, single combined attack with both weapons */
625 		Style_Combined,
626 		/** 2k3 style, multiple attacks, one per weapon */
627 		Style_MultiHit,
628 	};
629 
630 	static Style GetDefaultStyle();
631 
632 	Normal(Game_Battler* source, Game_Battler* target, int hits_multiplier = 1, Style style = GetDefaultStyle());
633 	Normal(Game_Battler* source, Game_Party_Base* target, int hits_multiplier = 1, Style style = GetDefaultStyle());
634 
635 	bool vExecute() override;
636 	bool vStart() override;
637 
638 	int GetAnimationId(int i) const override;
639 	std::string GetStartMessage(int line) const override;
640 	int GetSourcePose() const override;
641 	int GetCBAMovement() const override;
642 	int GetCBAAfterimage() const override;
643 	const lcf::rpg::BattlerAnimationItemSkill* GetWeaponAnimationData() const override;
644 	const lcf::rpg::Item* GetWeaponData() const override;
645 	const lcf::rpg::Sound* GetStartSe() const override;
646 	Game_Battler::Weapon GetWeapon() const;
647 	void ApplyComboHitsMultiplier(int hits) override;
648 
649 	// Emulates an RPG_RT bug where whenver an actor attacks an enemy, the hit rate and damage
650 	// is adjusted as if the enemy were in the front row.
651 	void SetTreatEnemiesAsIfInFrontRow(bool v);
652 
653 	// Return true if this is a charged attack.
654 	bool IsChargedAttack() const;
655 private:
656 	void Init(Style style);
657 	int hits_multiplier = 1;
658 	int weapon_style = -1;
659 	bool charged_attack = false;
660 	bool treat_enemies_asif_in_front_row = false;
661 };
662 
663 class Skill : public AlgorithmBase {
664 public:
665 	Skill(Game_Battler* source, Game_Battler* target, const lcf::rpg::Skill& skill, const lcf::rpg::Item* item = NULL);
666 	Skill(Game_Battler* source, Game_Party_Base* target, const lcf::rpg::Skill& skill, const lcf::rpg::Item* item = NULL);
667 	Skill(Game_Battler* source, const lcf::rpg::Skill& skill, const lcf::rpg::Item* item = NULL);
668 
669 	bool IsTargetValid(const Game_Battler&) const override;
670 	bool vExecute() override;
671 	bool vStart() override;
672 
673 	int GetAnimationId(int i) const override;
674 	std::string GetStartMessage(int line) const override;
675 	int GetSourcePose() const override;
676 	int GetCBAMovement() const override;
677 	int GetCBAAfterimage() const override;
678 	const lcf::rpg::Sound* GetStartSe() const override;
679 	const lcf::rpg::Sound* GetFailureSe() const override;
680 	std::string GetFailureMessage() const override;
681 	bool IsReflected(const Game_Battler&) const override;
682 	bool ActionIsPossible() const override;
683 
684 	const lcf::rpg::Skill& GetSkill() const;
685 	const lcf::rpg::Item* GetItem() const;
686 
687 private:
688 	void Init();
689 	std::string GetFirstStartMessage() const;
690 	std::string GetSecondStartMessage() const;
691 	const lcf::rpg::Skill& skill;
692 	const lcf::rpg::Item* item;
693 };
694 
695 class Item : public AlgorithmBase {
696 public:
697 	Item(Game_Battler* source, Game_Battler* target, const lcf::rpg::Item& item);
698 	Item(Game_Battler* source, Game_Party_Base* target, const lcf::rpg::Item& item);
699 	Item(Game_Battler* source, const lcf::rpg::Item& item);
700 
701 	bool IsTargetValid(const Game_Battler&) const override;
702 	bool vExecute() override;
703 	bool vStart() override;
704 
705 	std::string GetStartMessage(int line) const override;
706 	int GetSourcePose() const override;
707 	int GetCBAMovement() const override;
708 	const lcf::rpg::Sound* GetStartSe() const override;
709 	bool ActionIsPossible() const override;
710 
711 private:
712 	std::string GetFirstStartMessage() const;
713 	std::string GetSecondStartMessage() const;
714 	const lcf::rpg::Item& item;
715 };
716 
717 class Defend : public AlgorithmBase {
718 public:
719 	Defend(Game_Battler* source);
720 
721 	std::string GetStartMessage(int line) const override;
722 	int GetSourcePose() const override;
723 };
724 
725 class Observe : public AlgorithmBase {
726 public:
727 	Observe(Game_Battler* source);
728 
729 	std::string GetStartMessage(int line) const override;
730 };
731 
732 class Charge : public AlgorithmBase {
733 public:
734 	Charge(Game_Battler* source);
735 
736 	std::string GetStartMessage(int line) const override;
737 	void ApplyCustomEffect() override;
738 };
739 
740 class SelfDestruct : public AlgorithmBase {
741 public:
742 	SelfDestruct(Game_Battler* source, Game_Party_Base* target);
743 
744 	std::string GetStartMessage(int line) const override;
745 	const lcf::rpg::Sound* GetStartSe() const override;
746 	bool vExecute() override;
747 	void ApplyCustomEffect() override;
748 private:
749 	bool animate = true;
750 };
751 
752 class Escape : public AlgorithmBase {
753 public:
754 	Escape(Game_Battler* source);
755 
756 	std::string GetStartMessage(int line) const override;
757 	int GetSourcePose() const override;
758 	const lcf::rpg::Sound* GetStartSe() const override;
759 	void ApplyCustomEffect() override;
760 };
761 
762 class Transform : public AlgorithmBase {
763 public:
764 	Transform(Game_Battler* source, int new_monster_id);
765 
766 	std::string GetStartMessage(int line) const override;
767 	void ApplyCustomEffect() override;
768 
769 private:
770 	int new_monster_id;
771 };
772 
773 // EnemyAi "Do Nothing" action. Handled slightly differently than None.
774 class DoNothing : public AlgorithmBase {
775 public:
776 	DoNothing(Game_Battler* source);
777 };
778 
GetType()779 inline Type AlgorithmBase::GetType() const {
780 	return type;
781 }
782 
GetStateEffects()783 inline const std::vector<StateEffect>& AlgorithmBase::GetStateEffects() const {
784 	return states;
785 }
786 
GetOriginalPartyTarget()787 inline Game_Party_Base* AlgorithmBase::GetOriginalPartyTarget() const {
788 	return party_target;
789 }
790 
GetAffectedHp()791 inline int Game_BattleAlgorithm::AlgorithmBase::GetAffectedHp() const {
792 	return hp;
793 }
794 
GetAffectedSp()795 inline int Game_BattleAlgorithm::AlgorithmBase::GetAffectedSp() const {
796 	return sp;
797 }
798 
GetAffectedAtk()799 inline int Game_BattleAlgorithm::AlgorithmBase::GetAffectedAtk() const {
800 	return attack;
801 }
802 
GetAffectedDef()803 inline int Game_BattleAlgorithm::AlgorithmBase::GetAffectedDef() const {
804 	return defense;
805 }
806 
GetAffectedSpi()807 inline int Game_BattleAlgorithm::AlgorithmBase::GetAffectedSpi() const {
808 	return spirit;
809 }
810 
GetAffectedAgi()811 inline int Game_BattleAlgorithm::AlgorithmBase::GetAffectedAgi() const {
812 	return agility;
813 }
814 
GetShiftedAttributes()815 inline const std::vector<Game_BattleAlgorithm::AttributeEffect>& Game_BattleAlgorithm::AlgorithmBase::GetShiftedAttributes() const {
816 	return attributes;
817 }
818 
GetAffectedSwitch()819 inline int Game_BattleAlgorithm::AlgorithmBase::GetAffectedSwitch() const {
820 	return switch_id;
821 }
822 
IsPositive()823 inline bool Game_BattleAlgorithm::AlgorithmBase::IsPositive() const {
824 	return GetFlag(ePositive);
825 }
826 
IsRevived()827 inline bool Game_BattleAlgorithm::AlgorithmBase::IsRevived() const {
828 	return GetFlag(eRevived);
829 }
830 
ActionIsPossible()831 inline bool Game_BattleAlgorithm::AlgorithmBase::ActionIsPossible() const {
832 	return true;
833 }
834 
GetAnimationId(int)835 inline int Game_BattleAlgorithm::AlgorithmBase::GetAnimationId(int) const {
836 	return 0;
837 }
838 
IsAffectHp()839 inline bool Game_BattleAlgorithm::AlgorithmBase::IsAffectHp() const {
840 	return GetFlag(eAffectHp);
841 }
842 
IsAbsorbHp()843 inline bool Game_BattleAlgorithm::AlgorithmBase::IsAbsorbHp() const {
844 	return GetFlag(eAbsorbHp);
845 }
846 
IsAffectSp()847 inline bool Game_BattleAlgorithm::AlgorithmBase::IsAffectSp() const {
848 	return GetFlag(eAffectSp);
849 }
850 
IsAbsorbSp()851 inline bool Game_BattleAlgorithm::AlgorithmBase::IsAbsorbSp() const {
852 	return GetFlag(eAbsorbSp);
853 }
854 
IsAffectAtk()855 inline bool Game_BattleAlgorithm::AlgorithmBase::IsAffectAtk() const {
856 	return GetFlag(eAffectAtk);
857 }
858 
IsAbsorbAtk()859 inline bool Game_BattleAlgorithm::AlgorithmBase::IsAbsorbAtk() const {
860 	return GetFlag(eAbsorbAtk);
861 }
862 
IsAffectDef()863 inline bool Game_BattleAlgorithm::AlgorithmBase::IsAffectDef() const {
864 	return GetFlag(eAffectDef);
865 }
866 
IsAbsorbDef()867 inline bool Game_BattleAlgorithm::AlgorithmBase::IsAbsorbDef() const {
868 	return GetFlag(eAbsorbDef);
869 }
870 
IsAffectSpi()871 inline bool Game_BattleAlgorithm::AlgorithmBase::IsAffectSpi() const {
872 	return GetFlag(eAffectSpi);
873 }
874 
IsAbsorbSpi()875 inline bool Game_BattleAlgorithm::AlgorithmBase::IsAbsorbSpi() const {
876 	return GetFlag(eAbsorbSpi);
877 }
878 
IsAffectAgi()879 inline bool Game_BattleAlgorithm::AlgorithmBase::IsAffectAgi() const {
880 	return GetFlag(eAffectAgi);
881 }
882 
IsAbsorbAgi()883 inline bool Game_BattleAlgorithm::AlgorithmBase::IsAbsorbAgi() const {
884 	return GetFlag(eAbsorbAgi);
885 }
886 
887 
GetReflectTarget()888 inline Game_Battler* Game_BattleAlgorithm::AlgorithmBase::GetReflectTarget() const {
889 	return reflect_target;
890 }
891 
GetOriginalTargets()892 inline Span<Game_Battler* const> Game_BattleAlgorithm::AlgorithmBase::GetOriginalTargets() const {
893 	assert(num_original_targets <= static_cast<int>(targets.size()));
894 	return Span<Game_Battler* const>(targets.data(), num_original_targets);
895 }
896 
GetOriginalSingleTarget()897 inline Game_Battler* Game_BattleAlgorithm::AlgorithmBase::GetOriginalSingleTarget() const {
898 	assert(num_original_targets <= static_cast<int>(targets.size()));
899 	return (GetOriginalPartyTarget() == nullptr && num_original_targets == 1) ? targets.front() : nullptr;
900 }
901 
SetAffectedSwitch(int s)902 inline int Game_BattleAlgorithm::AlgorithmBase::SetAffectedSwitch(int s) {
903 	return this->switch_id = s;
904 }
905 
SetAffectedHp(int hp)906 inline int Game_BattleAlgorithm::AlgorithmBase::SetAffectedHp(int hp) {
907 	SetFlag(eAffectHp, true);
908 	return this->hp = hp;
909 }
910 
SetAffectedSp(int sp)911 inline int Game_BattleAlgorithm::AlgorithmBase::SetAffectedSp(int sp) {
912 	SetFlag(eAffectSp, true);
913 	return this->sp = sp;
914 }
915 
SetAffectedAtk(int atk)916 inline int Game_BattleAlgorithm::AlgorithmBase::SetAffectedAtk(int atk) {
917 	SetFlag(eAffectAtk, true);
918 	return this->attack = atk;
919 }
920 
SetAffectedDef(int def)921 inline int Game_BattleAlgorithm::AlgorithmBase::SetAffectedDef(int def) {
922 	SetFlag(eAffectDef, true);
923 	return this->defense = def;
924 }
925 
SetAffectedSpi(int spi)926 inline int Game_BattleAlgorithm::AlgorithmBase::SetAffectedSpi(int spi) {
927 	SetFlag(eAffectSpi, true);
928 	return this->spirit = spi;
929 }
930 
SetAffectedAgi(int agi)931 inline int Game_BattleAlgorithm::AlgorithmBase::SetAffectedAgi(int agi) {
932 	SetFlag(eAffectAgi, true);
933 	return this->agility = agi;
934 }
935 
SetIsPositive(bool p)936 inline bool Game_BattleAlgorithm::AlgorithmBase::SetIsPositive(bool p) {
937 	return SetFlag(ePositive, p);
938 }
939 
SetIsCriticalHit(bool c)940 inline bool Game_BattleAlgorithm::AlgorithmBase::SetIsCriticalHit(bool c) {
941 	return SetFlag(eCriticalHit, c);
942 }
943 
SetIsSuccess()944 inline bool Game_BattleAlgorithm::AlgorithmBase::SetIsSuccess() {
945 	return SetFlag(eSuccess, true);
946 }
947 
SetIsSuccessIf(bool x)948 inline bool Game_BattleAlgorithm::AlgorithmBase::SetIsSuccessIf(bool x) {
949 	return SetFlag(eSuccess, GetFlag(eSuccess) | x);
950 }
951 
SetIsFailure()952 inline bool Game_BattleAlgorithm::AlgorithmBase::SetIsFailure() {
953 	return SetFlag(eSuccess, false);
954 }
955 
IsSuccess()956 inline bool Game_BattleAlgorithm::AlgorithmBase::IsSuccess() const {
957 	return GetFlag(eSuccess);
958 }
959 
IsCriticalHit()960 inline bool Game_BattleAlgorithm::AlgorithmBase::IsCriticalHit() const {
961 	return GetFlag(eCriticalHit);
962 }
963 
GetSource()964 inline Game_Battler* Game_BattleAlgorithm::AlgorithmBase::GetSource() const {
965 	return source;
966 }
967 
GetCurrentRepeat()968 inline int Game_BattleAlgorithm::AlgorithmBase::GetCurrentRepeat() const {
969 	return cur_repeat;
970 }
971 
GetTotalRepetitions()972 inline int Game_BattleAlgorithm::AlgorithmBase::GetTotalRepetitions() const {
973 	return repeat;
974 }
975 
SetFlag(Flag f,bool value)976 inline bool Game_BattleAlgorithm::AlgorithmBase::SetFlag(Flag f, bool value) {
977 	flags.set(uint64_t(f), value);
978 	return value;
979 }
980 
GetFlag(Flag f)981 inline bool Game_BattleAlgorithm::AlgorithmBase::GetFlag(Flag f) const {
982 	return flags.test(uint64_t(f));
983 }
984 
SetIsAbsorbHp(bool a)985 inline bool Game_BattleAlgorithm::AlgorithmBase::SetIsAbsorbHp(bool a) {
986 	SetFlag(eAbsorbHp, a);
987 	return a;
988 }
989 
SetIsAbsorbSp(bool a)990 inline bool Game_BattleAlgorithm::AlgorithmBase::SetIsAbsorbSp(bool a) {
991 	SetFlag(eAbsorbSp, a);
992 	return a;
993 }
994 
SetIsAbsorbAtk(bool a)995 inline bool Game_BattleAlgorithm::AlgorithmBase::SetIsAbsorbAtk(bool a) {
996 	SetFlag(eAbsorbAtk, a);
997 	return a;
998 }
999 
SetIsAbsorbDef(bool a)1000 inline bool Game_BattleAlgorithm::AlgorithmBase::SetIsAbsorbDef(bool a) {
1001 	SetFlag(eAbsorbDef, a);
1002 	return a;
1003 }
1004 
SetIsAbsorbSpi(bool a)1005 inline bool Game_BattleAlgorithm::AlgorithmBase::SetIsAbsorbSpi(bool a) {
1006 	SetFlag(eAbsorbSpi, a);
1007 	return a;
1008 }
1009 
SetIsAbsorbAgi(bool a)1010 inline bool Game_BattleAlgorithm::AlgorithmBase::SetIsAbsorbAgi(bool a) {
1011 	SetFlag(eAbsorbAgi, a);
1012 	return a;
1013 }
1014 
SetTreatEnemiesAsIfInFrontRow(bool v)1015 inline void Game_BattleAlgorithm::Normal::SetTreatEnemiesAsIfInFrontRow(bool v) {
1016 	treat_enemies_asif_in_front_row = v;
1017 }
1018 
IsChargedAttack()1019 inline bool Game_BattleAlgorithm::Normal::IsChargedAttack() const {
1020 	return charged_attack;
1021 }
1022 
GetSkill()1023 inline const lcf::rpg::Skill& Game_BattleAlgorithm::Skill::GetSkill() const {
1024 	return skill;
1025 }
1026 
GetItem()1027 inline const lcf::rpg::Item* Game_BattleAlgorithm::Skill::GetItem() const {
1028 	return item;
1029 }
1030 
1031 } //namespace Game_BattleAlgorithm
1032 
1033 #endif
1034