1 ////////////////////////////////////////////////////////////////////////////////
2 //            Copyright (C) 2004-2010 by The Allacrost Project
3 //                         All Rights Reserved
4 //
5 // This code is licensed under the GNU GPL version 2. It is free software and
6 // you may modify it and/or redistribute it under the terms of this license.
7 // See http://www.gnu.org/copyleft/gpl.html for details.
8 ////////////////////////////////////////////////////////////////////////////////
9 
10 /** ****************************************************************************
11 *** \file    battle_actors.h
12 *** \author  Viljami Korhonen, mindflayer@allacrost.org
13 *** \author  Corey Hoffstein, visage@allacrost.org
14 *** \author  Andy Gardner, chopperdave@allacrost.org
15 *** \brief   Header file for actors present in battles.
16 ***
17 *** This code contains the implementation of battle actors (characters and
18 *** enemies) whom are represented on the field of battle.
19 *** ***************************************************************************/
20 
21 #ifndef __BATTLE_ACTORS_HEADER__
22 #define __BATTLE_ACTORS_HEADER__
23 
24 #include "defs.h"
25 #include "utils.h"
26 
27 #include "global_skills.h"
28 #include "global_actors.h"
29 #include "global_effects.h"
30 
31 #include "battle_utils.h"
32 
33 namespace hoa_battle {
34 
35 namespace private_battle {
36 
37 /** ****************************************************************************
38 *** \brief An abstract class for representing an actor in the battle
39 ***
40 *** An "actor" is a term used to represent both characters and enemies in battle.
41 *** This abstract class contains members and methods that are common to both types of
42 *** actors. As such, many of the implemented methods in this class are virtual.
43 ***
44 *** The BattleActor class contains a pointer to a GlobalActor object that represents
45 *** the character or enemy. BattleActor contains its own members for all actor stats such
46 *** as HP, strength, evade rating, etc. There are two reasons why BattleActor uses its own
47 *** members instead of directly accessing and modifying the members of the GlobalActor pointer.
48 *** First, various effects can occur in battle which can modify otherwise static stats such as
49 *** agility. We need the ability to restore each stat to its base value, and the GlobalActor
50 *** class retains that unaltered value. Second, if the player loses the battle and chooses to
51 *** retry, we need to restore all actors back to their original state before the battle began.
52 *** Retreiving the values of the GlobalActor class allows us to do so.
53 ***
54 *** Throughout the battle, actors progress through a series of states. The
55 *** standard set of states that an actor cylces through while they are "alive"
56 *** and participating in the battle are as follows.
57 ***
58 *** -# ACTOR_STATE_IDLE
59 *** -# ACTOR_STATE_COMMAND
60 *** -# ACTOR_STATE_WARM_UP
61 *** -# ACTOR_STATE_READY
62 *** -# ACTOR_STATE_ACTING
63 *** -# ACTOR_STATE_COOL_DOWN
64 ***
65 *** Throughout each cycle, the actor will select or be given an action to execute.
66 *** This action may be to attack an actor on the opposing team, heal a teammate,
67 *** use an item, or perform some sort of skill. Each actor is responsible for the
68 *** management of the action that they intend to take.
69 *** ***************************************************************************/
70 class BattleActor : public hoa_global::GlobalActor {
71 public:
72 	BattleActor(hoa_global::GlobalActor* actor);
73 
74 	virtual ~BattleActor();
75 
76 	//! \brief Returns true if the actor is considered an enemy of the character party
77 	virtual bool IsEnemy() const = 0;
78 
79 	//! \brief Returns true so long as the actor is not in the "dead" state
IsAlive()80 	bool IsAlive() const
81 		{ return (_state != ACTOR_STATE_DEAD); }
82 
83 	//! \brief Empty method. Required because this is a pure virtual method of GlobalActor
AddSkill(uint32 skill_id)84 	void AddSkill(uint32 skill_id)
85 		{}
86 
87 	/** \brief Changes the state of the actor and modifies the actor's properties accordingly
88 	*** \param new_state The state to set the actor to
89 	**/
90 	virtual void ChangeState(ACTOR_STATE new_state);
91 
92 	//! \brief Returns the width of the actor's sprite image
93 	virtual float GetSpriteWidth() const = 0;
94 
95 	//! \brief Returns the height of the actor's sprite image
96 	virtual float GetSpriteHeight() const = 0;
97 
98 	/** \brief Changes the actor's current sprite animation image
99 	*** \param alias The alias text used to identify the animation to change
100 	***
101 	*** \note Not all forms of battle sprites have multiple animations or any animations at all. For
102 	*** example, enemies typically only have a standard set of unanimated damage frames for their
103 	*** sprites. The reason this method is defined for all actors is so that the same skills may be
104 	*** reused for both characters and enemies, since some skill implementations will wish to call
105 	*** this method on the actor performing the skill.
106 	**/
107 	virtual void ChangeSpriteAnimation(const std::string& alias) = 0;
108 
109 	/** \brief Deals damage to the actor by reducing its hit points by a certain amount
110 	*** \param amount The number of hit points to decrease on the actor
111 	***
112 	*** If the state of the actor is ACTOR_STATE_DEAD, this function will print a warning and change nothing.
113 	*** If the amount of damage dealt is greater than the actor's current hit points, the actor will be placed
114 	*** in the ACTOR_STATE_DEAD state.
115 	**/
116 	void RegisterDamage(uint32 amount);
117 
118 	/** \brief Heals the actor by restoring a certain amount of hit points
119 	*** \param amount The number of hit points to add to the actor
120 	***
121 	*** If the state of the actor is ACTOR_STATE_DEAD, this function will print a warning and change nothing.
122 	*** The number of hit points on the actor are not allowed to increase beyond the actor's maximum hit
123 	*** points.
124 	**/
125 	void RegisterHealing(uint32 amount);
126 
127 	//! \brief Indicates that an action failed to connect on this target
128 	void RegisterMiss();
129 
130 	/** \brief Causes a change in a character's status
131 	*** \param status The type of status to change
132 	*** \param intensity The intensity of the change
133 	***
134 	*** This is the single method for registering a change in status for an actor. It can be used to add
135 	*** a new status, remove an existing status, or change the intensity level of an existing status. A
136 	*** positive intensity argument will increase the intensity while a negative intensity will decrease
137 	*** the intensity. Many different changes can occur depending upon the current state of the actor and
138 	*** any active status effects when this function is called, as the list below describes.
139 	***
140 	*** - If this status is not already active on the character and the intensity argument is positive,
141 	***   the actor will have the new status added at that intensity.
142 	*** - If this status is not already active on the character and the intensity argument is negative,
143 	***   no change will occur.
144 	*** - If this status is active and intensity is positive, intensity will be increased but will not
145 	***   exceed the maximum intensity level.
146 	*** - If this status is active, the intensity is positive, and the current intensity of the status
147 	***   is already at the maximum level, the status timer will be reset and the intensity will not change.
148 	*** - If this status is active and intensity is negative, intensity will be decreased but not allowed
149 	***   to go lower than the neutral level. If the neutral level is reached, the status will be removed.
150 	*** - If this status is active and the intensity is GLOBAL_INTENSITY_NEG_EXTREME, the status will be
151 	***   removed regardless of its current intensity level.
152 	*** - If this status has an opposite status type that is active on the actor and the intensity argument
153 	***   is positive, this will decrease the intensity of the opposite status by the degree of intensity.
154 	***   This may cause that opposite status to be removed and this new status to be added if the intensity
155 	***   change is significantly high.
156 	**/
157 	void RegisterStatusChange(hoa_global::GLOBAL_STATUS status, hoa_global::GLOBAL_INTENSITY intensity);
158 
159 	/** \brief Increases or decreases the current skill points of the actor
160 	*** \param amount The number of skill points to increase or decrease
161 	***
162 	*** If the actor is dead, no change will take place. If the amount is positive, the actor will
163 	*** not be allowed to exceed above their maximum skill points.
164 	***
165 	*** Any non-zero change in skill points will be reflected via increase/decrease text that will
166 	*** be drawn to the screen near the actor's sprite. If the value of the amount argument is zero,
167 	*** the word "Miss" will be drawn instead;
168 	**/
169 	void ChangeSkillPoints(int32 amount);
170 
171 	//! \brief Updates the state of the actor
172 	virtual void Update();
173 
174 	//! \brief Draws the actor's current sprite animation frame
175 	virtual void DrawSprite() = 0;
176 
177 	//! \brief Draws all active indicator text and graphics for the actor
178 	void DrawIndicators() const;
179 
180 	/** \brief Sets the action that the actor should execute next
181 	*** \param action A pointer to the action that the actor should execute
182 	***
183 	*** The actor assumes responsibility for the memory management of the action that is given to it with
184 	*** this method and will delete the object at the appropriate time. You should only call the method
185 	*** when the actor is in the state ACTOR_STATE_COMMAND. Invoking it at any other time will result in a
186 	*** warning and no operation, and the action object will be deleted immediately. A warning is also
187 	*** printed in the case where the actor has another action prepared.
188 	**/
189 	void SetAction(BattleAction* action);
190 
191 	//! \brief Resets actor stats to their original values
192 	//@{
ResetHitPoints()193 	void ResetHitPoints()
194 		{ SetHitPoints(_global_actor->GetHitPoints()); }
195 
ResetMaxHitPoints()196 	void ResetMaxHitPoints()
197 		{ SetMaxHitPoints(_global_actor->GetMaxHitPoints()); }
198 
ResetSkillPoints()199 	void ResetSkillPoints()
200 		{ SetSkillPoints(_global_actor->GetSkillPoints()); }
201 
ResetMaxSkillPoints()202 	void ResetMaxSkillPoints()
203 		{ SetMaxSkillPoints(_global_actor->GetMaxSkillPoints()); }
204 
ResetStrength()205 	void ResetStrength()
206 		{ SetStrength(_global_actor->GetStrength()); }
207 
ResetVigor()208 	void ResetVigor()
209 		{ SetVigor(_global_actor->GetVigor()); }
210 
ResetFortitude()211 	void ResetFortitude()
212 		{ SetFortitude(_global_actor->GetFortitude()); }
213 
ResetProtection()214 	void ResetProtection()
215 		{ SetProtection(_global_actor->GetProtection()); }
216 
ResetAgility()217 	void ResetAgility()
218 		{ SetAgility(_global_actor->GetAgility()); }
219 
ResetEvade()220 	void ResetEvade()
221 		{ SetEvade(_global_actor->GetEvade()); }
222 	//@}
223 
224 	//! \brief Returns the average defense/evasion totals of all of the actor's attack points
225 	//@{
226 	uint32 TotalPhysicalDefense();
227 
228 	uint32 TotalMetaphysicalDefense();
229 
230 	float TotalEvadeRating();
231 	//@}
232 
233 	//! \name Class member access methods
234 	//@{
GetState()235 	ACTOR_STATE GetState() const
236 		{ return _state; }
237 
GetGlobalActor()238 	hoa_global::GlobalActor* GetGlobalActor()
239 		{ return _global_actor; }
240 
GetAction()241 	BattleAction* GetAction()
242 		{ return _action; }
243 
GetXOrigin()244 	float GetXOrigin() const
245 		{ return _x_origin; }
246 
GetYOrigin()247 	float GetYOrigin() const
248 		{ return _y_origin; }
249 
GetXLocation()250 	float GetXLocation() const
251 		{ return _x_location; }
252 
GetYLocation()253 	float GetYLocation() const
254 		{ return _y_location; }
255 
GetIdleStateTime()256 	uint32 GetIdleStateTime() const
257 		{ return _idle_state_time; }
258 
GetStaminaIcon()259 	hoa_video::StillImage& GetStaminaIcon()
260 		{ return _stamina_icon; }
261 
GetStateTimer()262 	hoa_system::SystemTimer& GetStateTimer()
263 		{ return _state_timer; }
264 
SetXOrigin(float x_origin)265 	void SetXOrigin(float x_origin)
266 		{ _x_origin = x_origin; }
267 
SetYOrigin(float y_origin)268 	void SetYOrigin(float y_origin)
269 		{ _y_origin = y_origin; }
270 
SetXLocation(float x_location)271 	void SetXLocation(float x_location)
272 		{ _x_location = x_location; }
273 
SetYLocation(float y_location)274 	void SetYLocation(float y_location)
275 		{ _y_location = y_location; }
276 
277 	//! \note If the actor is in the idle state, this will not affect the state timer
SetIdleStateTime(uint32 time)278 	 void SetIdleStateTime(uint32 time)
279 		{ _idle_state_time = time; }
280 	//@}
281 
282 protected:
283 	//! \brief The state that the actor is currently in
284 	ACTOR_STATE _state;
285 
286 	//! \brief A pointer to the global actor object which the battle actor represents
287 	hoa_global::GlobalActor* _global_actor;
288 
289 	//! \brief A pointer to the action that the actor is preparing to perform or is currently performing
290 	BattleAction* _action;
291 
292 	//! \brief The "home" coordinates for the actor's default location on the battle field
293 	float _x_origin, _y_origin;
294 
295 	//! \brief The x and y coordinates of the actor's current location on the battle field
296 	float _x_location, _y_location;
297 
298 	//! \brief Set to true when the actor is in the ACTING state and the execution of the action is complete
299 	bool _execution_finished;
300 
301 	//! \brief The amount of time (in milliseconds) that the actor needs to wait to pass through the idle state
302 	uint32 _idle_state_time;
303 
304 	//! \brief A timer used as the character progresses through the standard series of actor states
305 	hoa_system::SystemTimer _state_timer;
306 
307 	//! \brief The actor's icon for the stamina meter
308 	hoa_video::StillImage _stamina_icon;
309 
310 	//! \brief An assistant class to the actor that manages all the actor's status and elemental effects
311 	EffectsSupervisor* _effects_supervisor;
312 
313 	//! \brief An assistant class to the actor that manages all the actor's indicator text and graphics
314 	IndicatorSupervisor* _indicator_supervisor;
315 }; // class BattleActor
316 
317 
318 /** ****************************************************************************
319 *** \brief Represents a player-controlled character in the battle
320 ***
321 *** Character actors have a series of animated images that reflect their current
322 *** state and actions. Each character also has a custom set of progressive damage
323 *** battle portraits (5 in total) that are drawn when the character is selected.
324 *** ***************************************************************************/
325 class BattleCharacter : public BattleActor {
326 public:
327 	BattleCharacter(hoa_global::GlobalCharacter* character);
328 
329 	~BattleCharacter();
330 
IsEnemy()331 	bool IsEnemy() const
332 		{ return false; }
333 
334 	void ChangeState(ACTOR_STATE new_state);
335 
GetSpriteWidth()336 	float GetSpriteWidth() const
337 		{ return 0.0f; } // TEMP: should retrieve width of current sprite animation
338 
GetSpriteHeight()339 	float GetSpriteHeight() const
340 		{ return 0.0f; } // TEMP: should retrieve height of current sprite animation
341 
342 	void ChangeSpriteAnimation(const std::string& alias);
343 
344 	//! \brief Updates the state of the character. Must be called every frame!
345 	void Update();
346 
347 	//! \brief Draws the character's current sprite animation frame
348 	void DrawSprite();
349 
350 	//! \brief Draws the character's damage-blended face portrait
351 	void DrawPortrait();
352 
353 	/** \brief Draws the character's status in the bottom area of the screen
354 	*** \param order The order position of the character [0-3] used to determine draw positions
355 	**/
356 	void DrawStatus(uint32 order);
357 
GetGlobalCharacter()358 	hoa_global::GlobalCharacter* GetGlobalCharacter()
359 		{ return _global_character; }
360 
GetSpriteAnimationAlias()361 	const std::string& GetSpriteAnimationAlias() const
362 		{ return _sprite_animation_alias; }
363 
364 protected:
365 	//! \brief A pointer to the global character object which the battle character represents
366 	hoa_global::GlobalCharacter* _global_character;
367 
368 	//! \brief Contains the identifier text of the current sprite animation
369 	std::string _sprite_animation_alias;
370 
371 	//! \brief Contains countdown timer of current animation
372 	hoa_system::SystemTimer _animation_timer;
373 
374 	//! \brief Rendered text of the character's name
375 	hoa_video::TextImage _name_text;
376 
377 	//! \brief Rendered text of the character's current hit points
378 	hoa_video::TextImage _hit_points_text;
379 
380 	//! \brief Rendered text of the character's current skill points
381 	hoa_video::TextImage _skill_points_text;
382 }; // class BattleCharacter
383 
384 
385 /** ****************************************************************************
386 *** \brief Represents the entity for an enemy in the battle
387 ***
388 *** This class is a wrapper around a GlobalEnemy object.
389 *** ***************************************************************************/
390 class BattleEnemy : public BattleActor {
391 public:
392 	BattleEnemy(hoa_global::GlobalEnemy* enemy);
393 
394 	~BattleEnemy();
395 
IsEnemy()396 	bool IsEnemy() const
397 		{ return true; }
398 
399 	void ChangeState(ACTOR_STATE new_state);
400 
GetSpriteWidth()401 	float GetSpriteWidth() const
402 		{ return _global_enemy->GetBattleSpriteFrames()->at(0).GetWidth(); }
403 
GetSpriteHeight()404 	float GetSpriteHeight() const
405 		{ return _global_enemy->GetBattleSpriteFrames()->at(0).GetHeight(); }
406 
407 	//! \note Enemies do not have animations so calling this function will achieve nothing
ChangeSpriteAnimation(const std::string & alias)408 	void ChangeSpriteAnimation(const std::string& alias)
409 		{ return; }
410 
411 	void Update();
412 
413 	//! \brief Draws the damage blended enemy sprite image on to the battle field
414 	void DrawSprite();
415 
GetGlobalEnemy()416 	hoa_global::GlobalEnemy* GetGlobalEnemy()
417 		{ return _global_enemy; }
418 
419 	//! \brief Compares the Y-coordinates of the actors, used for sorting the actors up-down when drawing
420 	bool operator<(const BattleEnemy & other) const;
421 
422 protected:
423 	//! \brief A pointer to the global enemy object which the battle enemy represents
424 	hoa_global::GlobalEnemy* _global_enemy;
425 
426 	/** \brief Decides what action that the enemy should execute and the target
427 	*** \todo This function is extremely rudimentary right now. Later, it should be given a more complete
428 	*** AI decision making algorithm
429 	**/
430 	void _DecideAction();
431 }; // class BattleEnemy
432 
433 } // namespace private_battle
434 
435 } // namespace hoa_battle
436 
437 #endif // __BATTLE_ACTORS_HEADER__
438