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