1 ////////////////////////////////////////////////////////////////////////////////
2 //            Copyright (C) 2004-2011 by The Allacrost Project
3 //            Copyright (C) 2012-2016 by Bertram (Valyria Tear)
4 //                         All Rights Reserved
5 //
6 // This code is licensed under the GNU GPL version 2. It is free software and
7 // you may modify it and/or redistribute it under the terms of this license.
8 // See https://www.gnu.org/copyleft/gpl.html for details.
9 ////////////////////////////////////////////////////////////////////////////////
10 
11 #ifndef __BATTLE_ACTOR_HEADER__
12 #define __BATTLE_ACTOR_HEADER__
13 
14 #include "common/global/actors/global_actor.h"
15 #include "modes/battle/objects/battle_object.h"
16 #include "modes/battle/battle_damage.h"
17 
18 #include "engine/video/text.h"
19 #include "engine/system.h"
20 
21 namespace vt_battle
22 {
23 
24 namespace private_battle
25 {
26 
27 class BattleAction;
28 class BattleStatusEffectsSupervisor;
29 
30 //! \brief Represents the possible states that a BattleActor may be in
31 enum ACTOR_STATE {
32     ACTOR_STATE_INVALID       = -1,
33     ACTOR_STATE_IDLE          =  0, //!< Actor is recovering stamina so they can execute another action
34     ACTOR_STATE_COMMAND       =  1, //!< Actor is finished with the idle state and needs to select an action to execute
35     ACTOR_STATE_WARM_UP       =  2, //!< Actor has selected an action and is preparing to execute it
36     ACTOR_STATE_READY         =  3, //!< Actor is prepared to execute action and is waiting their turn to act
37     ACTOR_STATE_SHOWNOTICE    =  4, //!< Actor is waiting for the special skill short notice to disappear
38     ACTOR_STATE_NOTICEDONE    =  5, //!< Actor is has shown the special skill short notice and is ready to act.
39     ACTOR_STATE_ACTING        =  6, //!< Actor is in the process of executing their selected action
40     ACTOR_STATE_COOL_DOWN     =  7, //!< Actor is finished with previous action execution and recovering
41     ACTOR_STATE_DYING         =  8, //!< Actor is in the transitive dying state.
42     ACTOR_STATE_DEAD          =  9, //!< Actor has perished and is inactive in battle
43     ACTOR_STATE_REVIVE        =  10, //!< Actor coming back from coma, and in the process to stand up again.
44     ACTOR_STATE_PARALYZED     =  11, //!< Actor is in some state of paralysis and can not act nor recover stamina
45     ACTOR_STATE_TOTAL         =  12
46 };
47 
48 /** \brief An abstract class for representing an actor in the battle
49 ***
50 *** An "actor" is a term used to represent both characters and enemies in battle.
51 *** This abstract class contains members and methods that are common to both types of
52 *** actors. As such, many of the implemented methods in this class are virtual.
53 ***
54 *** The BattleActor class contains a pointer to a GlobalActor object that represents
55 *** the character or enemy. BattleActor contains its own members for all actor stats such
56 *** as HP, phys_atk, evade rating, etc. There are two reasons why BattleActor uses its own
57 *** members instead of directly accessing and modifying the members of the GlobalActor pointer.
58 *** First, various effects can occur in battle which can modify otherwise static stats such as
59 *** stamina. We need the ability to restore each stat to its base value, and the GlobalActor
60 *** class retains that unaltered value. Second, if the player loses the battle and chooses to
61 *** retry, we need to restore all actors back to their original state before the battle began.
62 *** Retrieving the values of the GlobalActor class allows us to do so.
63 **/
64 class BattleActor : public vt_global::GlobalActor, public BattleObject
65 {
66 public:
67     BattleActor(vt_global::GlobalActor *actor);
68 
69     virtual ~BattleActor();
70 
71     //! \brief Returns true if the actor is considered an enemy of the character party
72     virtual bool IsEnemy() const = 0;
73 
74     //! \brief Returns true as long as the actor is not in the "dead" state
IsAlive()75     bool IsAlive() const {
76         return (_state != ACTOR_STATE_DEAD);
77     }
78 
79     //! \brief Returns true if the actor can still fight.
CanFight()80     bool CanFight() const {
81         return (_state != ACTOR_STATE_DYING && IsAlive());
82     }
83 
84     /** \brief Restores an actor to the initial state it was in when the battle began
85     ***
86     *** This includes resetting the actor's state, attributes, status effect, and animations.
87     **/
88     virtual void ResetActor();
89 
90     /** \brief Changes the state of the actor and modifies the actor's properties accordingly
91     *** \param new_state The state to set the actor to
92     **/
93     virtual void ChangeState(ACTOR_STATE new_state);
94 
95     //! \brief Returns the width of the actor's sprite image
96     virtual float GetSpriteWidth() const = 0;
97 
98     //! \brief Returns the height of the actor's sprite image
99     virtual float GetSpriteHeight() const = 0;
100 
101     /** \brief Changes the actor's current sprite animation image
102     *** \param alias The alias text used to identify the animation to change
103     ***
104     *** \note Not all forms of battle sprites have multiple animations or any animations at all. For
105     *** example, enemies typically only have a standard set of unanimated damage frames for their
106     *** sprites. The reason this method is defined for all actors is so that the same skills may be
107     *** reused for both characters and enemies, since some skill implementations will wish to call
108     *** this method on the actor performing the skill.
109     ***
110     *** \warning This function is not a pure virtual one because it needs to be accessed by Lua
111     *** and there is an issue with using Luabind on pure virtual functions.
112     **/
ChangeSpriteAnimation(const std::string &)113     virtual void ChangeSpriteAnimation(const std::string & /*alias*/)
114     {}
115 
GetSpriteAlpha()116     inline float GetSpriteAlpha() const {
117         return _sprite_alpha;
118     }
119 
120     //! Set the sprite alpha, useful for custom death sequences and other effects on sprites.
SetSpriteAlpha(float alpha)121     void SetSpriteAlpha(float alpha) {
122         if (alpha > 1.0f) alpha = 1.0f;
123         if (alpha < 0.0f) alpha = 0.0f;
124         _sprite_alpha = alpha;
125     }
126 
127     /** \brief Deals damage to the actor by reducing its hit points by a certain amount
128     *** \param amount The number of hit points to decrease on the actor
129     ***
130     *** If the state of the actor is ACTOR_STATE_DEAD, this function will print a warning and change nothing.
131     *** If the amount of damage dealt is greater than the actor's current hit points, the actor will be placed
132     *** in the ACTOR_STATE_DEAD state.
133     **/
134     virtual void RegisterDamage(uint32_t amount);
135 
136     //! \brief Steals the actor skill points
137     void RegisterSPDamage(uint32_t amount);
138 
139     /** \brief Deals damage to the actor by reducing its hit points by a certain amount
140     *** \param amount The number of hit points to decrease on the actor
141     *** \param target A pointer to the target information that was used to inflict this damage
142     ***
143     *** In addition to dealing damage, this function will use the second target argument to determine if this
144     *** damage was inflicted on an attack point (as opposed to the actor as a whole). If so, it analyzes the
145     *** attack point on the actor to see if it has any status effect vulnerabilities. If this is indeed the
146     *** case, then it applies the status effect to the actor if the random probability calculation determines
147     *** that the effect has been triggered.
148     **/
149     void RegisterDamage(uint32_t amount, BattleTarget *target);
150 
151     /** \brief Heals the actor by restoring a certain amount of points
152     *** \param amount The number of points to add to the actor.
153     *** \param hit_points whether hit points of skill points will be restored.
154     ***
155     *** If the state of the actor is ACTOR_STATE_DEAD, this function will print a warning and change nothing.
156     *** The number of hit points on the actor are not allowed to increase beyond the actor's maximum hit
157     *** points.
158     **/
159     void RegisterHealing(uint32_t amount, bool hit_points = true);
160 
161     /** \brief Heals a dead actor and permits him to go back in shape for the battle.
162     *** \param amount The number of points to add to the actor. Must be > 0.
163     **/
164     void RegisterRevive(uint32_t amount);
165 
166     /** \brief Indicates that an action failed to connect on this target
167     *** \param was_attacked Tells whether the miss is due to a missed attack
168     *** It will be used to make the actor play a dodge animation.
169     **/
170     void RegisterMiss(bool was_attacked = false);
171 
172     /** \brief Causes a change in a character's status
173     *** \param status The type of status to change
174     *** \param intensity The intensity of the change
175     *** \param duration A potential duration time (in milliseconds) used to setup custom effect lengths.
176     *** A fall back value is used otherwise.
177     ***
178     *** This is the single method for registering a change in status for an actor. It can be used to add
179     *** a new status, remove an existing status, or change the intensity level of an existing status. A
180     *** positive intensity argument will increase the intensity while a negative intensity will decrease
181     *** the intensity. Many different changes can occur depending upon the current state of the actor and
182     *** any active status effects when this function is called, as the list below describes.
183     ***
184     *** - If this status is not already active on the character and the intensity argument is positive,
185     ***   the actor will have the new status added at that intensity.
186     *** - If this status is not already active on the character and the intensity argument is negative,
187     ***   no change will occur.
188     *** - If this status is active and intensity is positive, intensity will be increased but will not
189     ***   exceed the maximum intensity level.
190     *** - If this status is active, the intensity is positive, and the current intensity of the status
191     ***   is already at the maximum level, the status timer will be reset and the intensity will not change.
192     *** - If this status is active and intensity is negative, intensity will be decreased but not allowed
193     ***   to go lower than the neutral level. If the neutral level is reached, the status will be removed.
194     *** - If this status is active and the intensity is GLOBAL_INTENSITY_NEG_EXTREME, the status will be
195     ***   removed regardless of its current intensity level.
196     *** - If this status has an opposite status type that is active on the actor and the intensity argument
197     ***   is positive, this will decrease the intensity of the opposite status by the degree of intensity.
198     ***   This may cause that opposite status to be removed and this new status to be added if the value of
199     ***   the intensity change is high enough.
200     ***
201     *** If the desired effect does yield a change in status, this function will prepare an indicator image
202     *** to be displayed representing the change in status.
203     **/
204     void ApplyActiveStatusEffect(vt_global::GLOBAL_STATUS status, vt_global::GLOBAL_INTENSITY intensity,
205                                  uint32_t duration = 0);
206 
207     //! \brief Removes the given status effect, calling the according BattleRemove() script function.
208     void RemoveActiveStatusEffect(vt_global::GLOBAL_STATUS status_effect);
209 
210     //! \brief Tells the intensity of the active status effect currently applied on the character,
211     //! or GLOBAL_STATUS_NEUTRAL if there is no such effect.
212     vt_global::GLOBAL_INTENSITY GetActiveStatusEffectIntensity(vt_global::GLOBAL_STATUS status);
213 
214     /** \brief Increases or decreases the current skill points of the actor
215     *** \param amount The number of skill points to increase or decrease
216     ***
217     *** If the actor is dead, no change will take place. If the amount is positive, the actor will
218     *** not be allowed to exceed above their maximum skill points.
219     ***
220     *** Any non-zero change in skill points will be reflected via increase/decrease text that will
221     *** be drawn to the screen near the actor's sprite. If the value of the amount argument is zero,
222     *** the word "Miss" will be drawn instead;
223     **/
224     void ChangeSkillPoints(int32_t amount);
225 
226     //! \brief Stuns the BattleActor, preventing its state timer to update.
227     //! \param stun Whether the actor should be stunned.
SetStunned(bool stun)228     void SetStunned(bool stun) {
229         _is_stunned = stun;
230     }
231 
232     //! \brief Tells whether the actor is stunned.
IsStunned()233     bool IsStunned() const {
234         return _is_stunned;
235     }
236 
237     /** \brief Updates the state of the actor
238     ***
239     *** The optional boolean parameter is primarily used by battle sequences which desire to update the sprite graphics
240     *** but not any battle state.
241     **/
242     virtual void Update();
243 
244     //! \brief Draws the stamina icon - default implementation
245     virtual void DrawStaminaIcon(const vt_video::Color &color = vt_video::Color::white) const;
246 
247     /** \brief Sets the action that the actor should execute next
248     *** \param action A pointer to the action that the actor should execute
249     ***
250     *** The actor assumes responsibility for the memory management of the action that is given to it with
251     *** this method and will delete the object at the appropriate time. You should only call the method
252     *** when the actor is in the state ACTOR_STATE_COMMAND. Invoking it at any other time will result in a
253     *** warning and no operation, and the action object will be deleted immediately. A warning is also
254     *** printed in the case where the actor has another action prepared.
255     **/
256     void SetAction(BattleAction *action);
257 
258     //! \brief Convenience wrapper for all targets type skills
259     //! This one useful for self target-type skills, and all allies/enemies target-type skills.
SetAction(uint32_t skill_id)260     void SetAction(uint32_t skill_id) {
261         SetAction(skill_id, nullptr);
262     }
263 
264     //! \brief Convenience wrapper for single target type skills
265     void SetAction(uint32_t skill_id, BattleActor* target_actor);
266 
267     //! \brief Resets actor stats to their original values
268     //@{
ResetHitPoints()269     void ResetHitPoints() {
270         SetHitPoints(_global_actor->GetHitPoints());
271     }
272 
ResetMaxHitPoints()273     void ResetMaxHitPoints() {
274         SetMaxHitPoints(_global_actor->GetMaxHitPoints());
275     }
276 
ResetSkillPoints()277     void ResetSkillPoints() {
278         SetSkillPoints(_global_actor->GetSkillPoints());
279     }
280 
ResetMaxSkillPoints()281     void ResetMaxSkillPoints() {
282         SetMaxSkillPoints(_global_actor->GetMaxSkillPoints());
283     }
284 
ResetPhysAtk()285     void ResetPhysAtk() {
286         SetPhysAtk(_global_actor->GetPhysAtk());
287         SetPhysAtkModifier(1.0f);
288     }
289 
ResetMagAtk()290     void ResetMagAtk() {
291         SetMagAtk(_global_actor->GetMagAtk());
292         SetMagAtkModifier(1.0f);
293     }
294 
ResetPhysDef()295     void ResetPhysDef() {
296         SetPhysDef(_global_actor->GetPhysDef());
297         SetPhysDefModifier(1.0f);
298     }
299 
ResetMagDef()300     void ResetMagDef() {
301         SetMagDef(_global_actor->GetMagDef());
302         SetMagDefModifier(1.0f);
303     }
304 
ResetStamina()305     void ResetStamina() {
306         SetStamina(_global_actor->GetStamina());
307         SetStaminaModifier(1.0f);
308     }
309 
310     //! SetStamina() overloading the GlobalActor one, to permit updating the idle State timer also.
311     void SetStamina(uint32_t stamina);
312 
313     //! SetStaminaModifier() overloading the GlobalActor one, to permit updating the idle State timer also.
314     void SetStaminaModifier(float modifier);
315 
ResetEvade()316     void ResetEvade() {
317         SetEvade(_global_actor->GetEvade());
318         SetEvadeModifier(1.0f);
319     }
320     //@}
321 
322     //! \name Class member access methods
323     //@{
GetState()324     ACTOR_STATE GetState() const {
325         return _state;
326     }
327 
GetGlobalActor()328     vt_global::GlobalActor* GetGlobalActor() {
329         return _global_actor;
330     }
331 
GetAmmoAnimationFile()332     const std::string& GetAmmoAnimationFile() const {
333         return _ammo_animation_file;
334     }
335 
GetAction()336     BattleAction* GetAction() {
337         return _action;
338     }
339 
IsActionSet()340     bool IsActionSet() const {
341         return (_action != nullptr);
342     }
343 
GetIdleStateTime()344     uint32_t GetIdleStateTime() const {
345         return _idle_state_time;
346     }
347 
GetStaminaIcon()348     vt_video::StillImage& GetStaminaIcon() {
349         return _stamina_icon;
350     }
351 
GetStateTimer()352     vt_system::SystemTimer& GetStateTimer() {
353         return _state_timer;
354     }
355 
356     //! \note If the actor is in the idle state, this will not affect the state timer
SetIdleStateTime(uint32_t time)357     void SetIdleStateTime(uint32_t time) {
358         _idle_state_time = time;
359     }
360     //@}
361 
362 protected:
363     //! \brief The state that the actor is currently in
364     ACTOR_STATE _state;
365 
366     //! \brief A pointer to the global actor object which the battle actor represents
367     vt_global::GlobalActor* _global_actor;
368 
369     //! \brief The ammo animation filename, when the actor weapon uses ammo. Empty otherwise.
370     std::string _ammo_animation_file;
371 
372     //! \brief A pointer to the action that the actor is preparing to perform or is currently performing
373     BattleAction* _action;
374 
375     //! \brief The amount of time (in milliseconds) that the actor needs to wait to pass through the idle state
376     uint32_t _idle_state_time;
377 
378     //! \brief A timer used as the character progresses through the standard series of actor states
379     vt_system::SystemTimer _state_timer;
380 
381     //! \brief A timer telling the time the character is hurt, making it visually shaking.
382     vt_system::SystemTimer _hurt_timer;
383 
384     //! \brief Tells whether the actor is stunned, preventing its idle state time to update.
385     bool _is_stunned;
386 
387     //! \brief Contains the alpha value to draw the sprite at: useful for fading effects
388     float _sprite_alpha;
389 
390     //! \brief Used to assist in the animation of actors as they move on the battlefield
391     vt_system::SystemTimer _animation_timer;
392 
393     //! \brief The x and y coordinates of the actor's current stamina icon on the stamina bar.
394     vt_common::Position2D _stamina_location;
395 
396     //! \brief An assistant class to the actor that manages all the actor's status and elemental effects
397     BattleStatusEffectsSupervisor* _effects_supervisor;
398 
399     //! \brief Script object used when playing the death sequence.
400     //! A default sequence is played one of those is invalid.
401     vt_script::ReadScriptDescriptor _death_script;
402     luabind::object _death_update;
403     luabind::object _death_init;
404     //! This function permits to draw something along with the Battle enemy sprite
405     luabind::object _death_draw_on_sprite;
406 
407     //! \brief The battle AI script.
408     vt_script::ReadScriptDescriptor _ai_script;
409     //! \brief The "DecideAction" ai script.
410     luabind::object _ai_decide_action;
411 
412     //! \brief Loads the potential death animation scripted functions.
413     void _LoadDeathAnimationScript();
414 
415     //! \brief Loads the potential battle AI scripted function.
416     void _LoadAIScript();
417 
418     /** \brief Decides what action that the hero or enemy should execute and the target
419     *** This function is used as a fallback when no AI script is set for the given enemy.
420     *** \note More complete AI decision making algorithms should be supported
421     *** through lua scripts.
422     **/
423     void _DecideAction();
424 
425     //! \brief Updates the Stamina Icon position.
426     void _UpdateStaminaIconPosition();
427 
428     //! \brief Updates the actor state
429     void _UpdateState();
430 
431     //! \brief Initializes the Battle Actor stats values.
432     //! The global actor final stats are used as base for the battle actors.
433     //! This means that the final phys_atk value of the global actor is the base value
434     //! of the battle actor.
435     //! This way, equipment modifiers aren't touched in battles, but battle modifiers
436     //! are applied on top of the global actor values and properly reset to the global
437     //! (and equipment values) when the battle effects disappear.
438     void _InitStats();
439 
440     //! Returns the text style corresponding to the damage/healing type and amount
441     vt_video::TextStyle _GetDamageTextStyle(uint32_t amount, bool is_sp_damage);
442     vt_video::TextStyle _GetHealingTextStyle(uint32_t amount, bool is_hp);
443 };
444 
445 } // namespace private_battle
446 
447 } // namespace vt_battle
448 
449 #endif // __BATTLE_ACTORS_HEADER__
450