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
7 // and 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 __MAP_ENEMY_SPRITE_HEADER__
12 #define __MAP_ENEMY_SPRITE_HEADER__
13 
14 #include "modes/map/map_sprites/map_sprite.h"
15 
16 #include "modes/battle/battle_enemy_info.h"
17 
18 namespace vt_map
19 {
20 
21 namespace private_map
22 {
23 
24 class SpriteEvent;
25 class EnemyZone;
26 
27 //! Standard time values for spawning enemies on a map. All values are in number of milliseconds.
28 //@{
29 //! \brief The time to spawn an enemy when the player first enters a map
30 const uint32_t STANDARD_ENEMY_FIRST_SPAWN_TIME = 1000;
31 //! \brief The standard amount of time it takes an enemy to change state from "spawning" to "hostile"
32 const uint32_t STANDARD_ENEMY_SPAWN_TIME = 5000;
33 //! \brief The duration that an enemy stays in the dead state after it has been defeated
34 const uint32_t STANDARD_ENEMY_DEAD_TIME = 5000;
35 //@}
36 
37 /** ****************************************************************************
38 *** \brief A mobile map object that induces a battle to occur if the player touches it
39 ***
40 *** There are really two types of enemy sprites. The first type behave just like
41 *** map sprites and can have scripted movement sequences. The second type belong
42 *** to EnemyZones, where they fade into existence and pursue after the player's
43 *** sprite should the player enter the zone.
44 ***
45 *** An enemy sprite in a zone can be in one of 3 states: SPAWNING, HOSTILE or DEAD.
46 *** In the spawning state, the enemy becomes gradually visible, is immobile, and
47 *** cannot be touched or attacked. In the hostile state, the enemies roams the map
48 *** and will cause a battle if touched by the player. In the dead state, the enemy
49 *** is invisible and waits for the EnemyZone to reset it in another position, so
50 *** that it may spawn once more.
51 *** ***************************************************************************/
52 class EnemySprite : public MapSprite
53 {
54 private:
55     //! \brief The states that the enemy sprite may be in
56     enum STATE {
57         SPAWNING,
58         HOSTILE,
59         DEAD
60     };
61 
62 public:
63     //! \brief The default constructor
64     EnemySprite();
65     virtual ~EnemySprite() override;
66 
67     //! \brief A C++ wrapper made to create a new object from scripting,
68     //! without letting Lua handling the object life-cycle.
69     //! \note We don't permit luabind to use constructors here as it can't currently
70     //! give the object ownership at construction time.
71     static EnemySprite* Create();
72 
73     //! \brief Resets various members of the class so that the enemy is dead, invisible, and does not produce a collision
74     void Reset();
75 
76     //! \brief Updates the sprite's position and state.
77     virtual void Update() override;
78 
79     //! \brief Draws the sprite frame in the appropriate position on the screen, if it is visible.
80     virtual void Draw() override;
81 
82     /** \brief Adds a new empty vector to the _enemy_parties member
83     *** \note Make sure to populate this vector by adding at least one enemy!
84     **/
NewEnemyParty()85     void NewEnemyParty() {
86         _enemy_parties.push_back(std::vector<vt_battle::BattleEnemyInfo>());
87     }
88 
89     /** \brief Adds an enemy with the specified ID to the last party in _enemy_parties
90     *** \param enemy_id The ID of the enemy to add
91     *** \param position_x, position_y The enemy sprite position on the battle ground in pixels
92     *** \note MapMode should have already loaded a GlobalEnemy with this ID and retained it within the MapMode#_enemies member.
93     *** If this is not the case, this function will print a warning message.
94     **/
95     void AddEnemy(uint32_t enemy_id, float position_x, float position_y);
96     //! \brief A simpler function used to auto set default enemy position on the battle ground
AddEnemy(uint32_t enemy_id)97     void AddEnemy(uint32_t enemy_id) {
98         AddEnemy(enemy_id, 0.0f, 0.0f);
99     }
100 
101     //! \brief Returns a reference to a random party of enemies
102     const std::vector<vt_battle::BattleEnemyInfo>& RetrieveRandomParty() const;
103 
104     //! \brief Returns the enemy's encounter event id.
105     //! If this event is not empty, it is triggered instead of a battle,
106     //! when encountering an enemy sprite in the map mode.
GetEncounterEvent()107     const std::string& GetEncounterEvent() const {
108         return _encounter_event;
109     }
110 
111     //! \brief Sets the enemy's encounter event id.
SetEncounterEvent(const std::string & event)112     void SetEncounterEvent(const std::string& event) {
113         _encounter_event = event;
114     }
115 
116     //! \name Class Member Access Functions
117     //@{
GetAggroRange()118     float GetAggroRange() const {
119         return _aggro_range;
120     }
121 
GetTimeBeforeNewDestination()122     uint32_t GetTimeBeforeNewDestination() const {
123         return _time_before_new_destination;
124     }
125 
GetTimeToSpawn()126     uint32_t GetTimeToSpawn() const {
127         return _time_to_spawn;
128     }
129 
GetBattleMusicTheme()130     const std::string &GetBattleMusicTheme() const {
131         return _music_theme;
132     }
133 
GetBattleBackground()134     const std::string &GetBattleBackground() const {
135         return _bg_file;
136     }
137 
GetBattleScripts()138     const std::vector<std::string>& GetBattleScripts() const {
139         return _script_files;
140     }
141 
IsDead()142     bool IsDead() const {
143         return _state == DEAD;
144     }
145 
IsSpawning()146     bool IsSpawning() const {
147         return _state == SPAWNING;
148     }
149 
IsHostile()150     bool IsHostile() const {
151         return _state == HOSTILE;
152     }
153 
IsBoss()154     bool IsBoss() const {
155         return _is_boss;
156     }
157 
SetZone(EnemyZone * zone)158     void SetZone(EnemyZone *zone) {
159         _zone = zone;
160     }
161 
GetEnemyZone()162     EnemyZone* GetEnemyZone() {
163         return _zone;
164     }
165 
SetAggroRange(float range)166     void SetAggroRange(float range) {
167         _aggro_range = range;
168     }
169 
SetTimeBeforeNewDestination(uint32_t time)170     void SetTimeBeforeNewDestination(uint32_t time) {
171         _time_before_new_destination = time;
172     }
173 
SetTimeToRespawn(uint32_t time)174     void SetTimeToRespawn(uint32_t time) {
175         _time_to_respawn = time;
176     }
177 
SetBoss(bool is_boss)178     void SetBoss(bool is_boss) {
179         _is_boss = is_boss;
180     }
181 
SetBattleMusicTheme(const std::string & music_theme)182     void SetBattleMusicTheme(const std::string &music_theme) {
183         _music_theme = music_theme;
184     }
185 
SetBattleBackground(const std::string & bg_file)186     void SetBattleBackground(const std::string &bg_file) {
187         _bg_file = bg_file;
188     }
189 
AddBattleScript(const std::string & script_file)190     void AddBattleScript(const std::string &script_file) {
191         _script_files.push_back(script_file);
192     }
193 
194     void ChangeStateDead();
195 
ChangeStateSpawning()196     void ChangeStateSpawning() {
197         _updatable = true;
198         _state = SPAWNING;
199         _collision_mask = NO_COLLISION;
200     }
201 
202     void ChangeStateHostile();
203 
204     //! Makes an enemy follow way point when not running after a hero
205     //! \note You'll have to add at least two valid way point to make those
206     //! taken into account by the enemy sprite.
207     void AddWayPoint(float destination_x, float destination_y);
208     //@}
209 
210 private:
211     //! \brief The zone that the enemy sprite belongs to
212     private_map::EnemyZone *_zone;
213 
214     //! \brief Used to gradually fade in the sprite as it is spawning by adjusting the alpha channel
215     vt_video::Color _color;
216 
217     //! \brief A timer used for spawning
218     uint32_t _time_elapsed;
219 
220     //! \brief The state that the enemy sprite is in
221     STATE _state;
222 
223     //! \brief A value which determines how close the player needs to be for the enemy to aggressively seek to confront it
224     float _aggro_range;
225 
226     //! \brief Tells the time the sprite is waiting before going to a new destination.
227     uint32_t _time_before_new_destination;
228 
229     //! \brief Tells the actual time in milliseconds the sprite will use to respawn. This will set up the fade in speed.
230     uint32_t _time_to_spawn;
231 
232     //! \brief the default time used to respawn (Set to STANDARD_ENEMY_SPAWN_TIME by default)
233     uint32_t _time_to_respawn;
234 
235     //! \brief The default battle music theme for the monster
236     std::string _music_theme;
237 
238     //! \brief The default background for the battle
239     std::string _bg_file;
240 
241     //! \brief The filenames of the script to pass to the battle
242     std::vector<std::string> _script_files;
243 
244     //! \brief Tells whether the sprite is a boss.
245     bool _is_boss;
246 
247     /** \brief Contains the possible groups of enemies that may appear in a battle should the player encounter this enemy sprite
248     *** The numbers contained within this member are ID numbers for the enemy.
249     **/
250     std::vector<std::vector<vt_battle::BattleEnemyInfo> > _enemy_parties;
251 
252     //! \brief The enemy's encounter event.
253     //! If this event is not empty, it is triggered instead of a battle.
254     std::string _encounter_event;
255 
256     //! \brief Tells whether pathfinding is used to compute the enemy movement.
257     bool _use_path;
258 
259     //! \brief Used to store the previous coordinates of the sprite during path movement,
260     //! so as to set the proper direction of the sprite as it moves
261     vt_common::Position2D _last_node_position;
262 
263     //! \brief Used to store the current node collision position (with offset)
264     vt_common::Position2D _current_node;
265 
266     //! \brief An index to the path vector containing the node that the sprite currently occupies
267     uint32_t _current_node_id;
268 
269     //! \brief The current destination of the sprite.
270     vt_common::Position2D _destination;
271 
272     //! \brief Holds the path needed to traverse from source to destination
273     Path _path;
274 
275     //! \brief Way points used by the enemy when not hostile
276     std::vector<vt_common::Position2D> _way_points;
277     uint32_t _current_way_point_id;
278 
279     //! \brief Set the new path destination of the sprite.
280     //! \param destination_x The pixel x destination to find a path to.
281     //! \param destination_y The pixel y destination to find a path to.
282     //! \param max_cost More or less the path max length in nodes or 0 if no limitations.
283     //! Use this to avoid heavy computations.
284     //! \return whether it failed.
285     bool _SetDestination(float destination_x, float destination_y, uint32_t max_cost = 20);
286 
287     //! \brief Set the actual sprite direction according to the current path node.
288     void _SetSpritePathDirection();
289 
290     //! \brief Update the sprite direction according to the current path.
291     void _UpdatePath();
292 
293     //! \brief Set a path for the sprite being the next way point given.
294     //! \return whether it failed.
295     bool _SetPathToNextWayPoint();
296 
297     //! \brief Handles behavior when the enemy is in hostile state (seeking for characters)
298     void _HandleHostileUpdate();
299 
300 };
301 
302 } // namespace private_map
303 
304 } // namespace vt_map
305 
306 #endif // __MAP_ENEMY_SPRITE_HEADER__
307