1 ///////////////////////////////////////////////////////////////////////////////
2 //            Copyright (C) 2004-2011 by The Allacrost Project
3 //            Copyright (C) 2012-2017 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_OBJECT_SUPERVISOR_HEADER__
12 #define __MAP_OBJECT_SUPERVISOR_HEADER__
13 
14 #include "modes/map/map_objects/map_object.h"
15 
16 #include "script/script_read.h"
17 
18 namespace vt_map
19 {
20 
21 namespace private_map
22 {
23 
24 class Halo;
25 class SavePoint;
26 class EscapePoint;
27 class SoundObject;
28 class Light;
29 
30 /** ****************************************************************************
31 *** \brief A helper class to MapMode responsible for management of all object and sprite data
32 ***
33 *** This class is responsible for loading, updating, and drawing all map objects
34 *** and map sprites, in addition to maintaining the map's collision grid and map
35 *** zones. This class contains the implementation of the collision detection
36 *** and path finding algorithms.
37 ***
38 *** \todo Each map object is assigned an ID and certain values of IDs are reserved
39 *** for different types of map objects. We need to find out what these are and
40 *** maintain a list of those ranges here.
41 *** ***************************************************************************/
42 class ObjectSupervisor
43 {
44     friend class vt_map::MapMode;
45     //friend void vt_defs::BindModeCode();
46 
47 public:
48     ObjectSupervisor();
49 
50     ~ObjectSupervisor();
51 
52     //! \brief Returns a unique ID integer for an object to use
53     //! Every object Id must be > 0 since 0 is reserved for speakerless dialogues.
GenerateObjectID()54     uint16_t GenerateObjectID() {
55         return ++_last_id;
56     }
57 
58     //! \brief Returns the number of objects stored by the supervisor, regardless of what layer they exist on
GetNumberObjects()59     uint32_t GetNumberObjects() const {
60         return _all_objects.size();
61     }
62 
63     /** \brief Retrieves a pointer to an object on this map
64     *** \param object_id The id number of the object to retrieve
65     *** \return A pointer to the map object, or nullptr if no object with that ID was found
66     **/
67     MapObject* GetObject(uint32_t object_id);
68 
69     /** \brief Retrieves a pointer to a sprite on this map
70     *** \param object_id The id number of the sprite to retrieve
71     *** \return A pointer to the sprite object, or nullptr if the object was not found or was not a sprite type
72     **/
73     VirtualSprite* GetSprite(uint32_t object_id);
74 
75     //! \brief Wrapper to add an object in the all objects vector.
76     //! This should only be called by the MapObject constructor.
77     void RegisterObject(MapObject* object);
78 
79     //! \brief Delete an object from memory.
80     void DeleteObject(MapObject* object);
81 
82     //! \brief Add sound objects (Done within the sound object constructor)
83     void AddAmbientSound(SoundObject* object);
84 
85     //! \brief Add a light object, often created through scripting.
86     //! Called by the Light object constructor
87     void AddLight(Light* light);
88 
89     //! \brief Add a halo object, often created through scripting.
90     //! Called by the Halo object constructor
91     void AddHalo(Halo* halo);
92 
93     //! \brief Add a save point.
94     //! Called by the SavePoint object constructor
95     void AddSavePoint(SavePoint* save_point);
96 
97     //! \brief Add a escape point.
98     //! Called by the EscapePoint object constructor
99     void AddEscapePoint(EscapePoint* escape_point);
100 
101     //! \brief Adds a new zone.
102     // Called by the Mazone constructor.
103     void AddZone(MapZone* zone);
104 
105     //! \brief Sorts objects on all three layers according to their draw order
106     void SortObjects();
107 
108     /** \brief Loads the collision grid data and saved state of all map objects
109     *** \param map_file A reference to the open map script file
110     *** \return Whether the collision data loading was successful.
111     ***
112     *** The file must be open prior to making this call and additionally must
113     *** be at the highest level scope (i.e., there are no actively open tables
114     *** in the script descriptor object).
115     **/
116     bool Load(vt_script::ReadScriptDescriptor &map_file);
117 
118     //! \brief Updates the state of all map zones and objects
119     void Update();
120 
121     /** \brief Draws the various object layers to the screen
122     *** \param frame A pointer to the information required to draw this frame
123     *** \note These functions do not reset the coordinate system and hence depend that the proper coordinate system
124     *** is already set prior to these function calls (0.0f, SCREEN_COLS, SCREEN_ROWS, 0.0f). These functions do make
125     *** modifications to the draw flags and the draw cursor position, which are not restored by the function
126     *** upon its return. Take measures to retain this information before calling these functions if necessary.
127     **/
128     //@{
129     void DrawMapPoints();
130     void DrawFlatGroundObjects();
131     void DrawGroundObjects(const bool second_pass);
132     void DrawPassObjects();
133     void DrawSkyObjects();
134     void DrawLights();
135     void DrawInteractionIcons();
136     //@}
137 
138     /** \brief Finds the nearest interactable map object within a certain distance of a sprite
139     *** \param sprite The sprite who is trying to find its nearest object
140     *** \param search_distance The maximum distance to search for an object from the sprite (default == 3.0f)
141     *** \return A pointer to the nearest map object, or nullptr if no such object was found.
142     ***
143     *** An interactable object must be in the same context as the function argument is. For an object
144     *** to be valid, it's collision rectangle must be no greater than the search distance (in units of
145     *** collision grid elements) from the sprite's "calling" axis. For example, if the search distance was 3.0f
146     *** and the sprite was facing downwards, this function draws an imaginary rectangle below the sprite of height
147     *** 3.0f and a length equal to the length of the sprite. Any objects that have their collision rectangles intersect
148     *** with any portion of this search area are put on a list of valid objects, and once this list has been fully
149     *** constructed the nearest of these objects will be returned.
150     **/
151     private_map::MapObject* FindNearestInteractionObject(const private_map::VirtualSprite* sprite,
152                                                          float search_distance = 3.0f);
153 
154     /** \brief Determines if a map object's collision rectangle intersects with a specified map area
155     *** \param rect A reference to the rectangular section of the map to do collision detection with
156     *** \param obj A pointer to a map object
157     *** \return True if the objects collide with one another
158     *** \note This test is "absolute", and does not factor in things such as map contexts or whether or
159     *** not the no_collision property is enabled on the MapObject.
160     **/
161     bool CheckObjectCollision(const vt_common::Rectangle2D& rect,
162                               const private_map::MapObject *const obj);
163 
164     /** \brief Determines if a specific map object occupies a specific element of the collision grid
165     *** \param x The x axis position
166     *** \param y The y axis position
167     *** \param object The object to check for occupation of the grid element
168     *** \return True if the grid element is occupied by the object
169     ***
170     *** \todo Take into account the object/sprite's collision property and also add a parameter for map context
171     **/
172     bool IsPositionOccupiedByObject(float x, float y, MapObject *object);
173 
174     /** \brief Tells the collision type corresponding to an object type.
175     *** \param obj A pointer to the map object to check
176     *** \return The corresponding type of collision detected.
177     **/
178     COLLISION_TYPE GetCollisionFromObjectType(MapObject *obj) const;
179 
180     /** \brief Tells the collision type of a sprite when it is at the given position
181     *** \param object A pointer to the map object to check
182     *** \param x The collision point on the x axis
183     *** \param y The collision point on the y axis
184     *** \param coll_obj A pointer to the MapObject that the sprite has collided with, if any
185     *** \return The type of collision detected, which may include NO_COLLISION
186     *** if none was detected
187     ***
188     *** This method is invoked by a map sprite who wishes to check for its own collision.
189     *** \See COLLISION_TYPE for more information.
190     **/
191     COLLISION_TYPE DetectCollision(MapObject* object, float x, float y,
192                                    MapObject **collision_object_ptr = nullptr);
193 
194     /** \brief Finds a path from a sprite's current position to a destination
195     *** \param sprite A pointer of the sprite to find the path for
196     *** \param dest The destination coordinates
197     *** \param path A vector of PathNode objects storing the path
198     *** \param max_cost Tells how far a path node can be computed agains the starting path node.
199     *** This is used to avoid heavy computations.
200     *** If this param is equal to 0, there is no limitation.
201     ***
202     *** This algorithm uses the A* algorithm to find a path from a source to a destination.
203     *** This function ignores the position of all other objects and only concerns itself with
204     *** which map grid elements are walkable.
205     ***
206     *** \note If an error is detected or a path could not be found, the function will empty the path vector before returning
207     **/
208     Path FindPath(private_map::VirtualSprite *sprite,
209                   const vt_common::Position2D& destination,
210                   uint32_t max_cost = 0);
211 
212     /** \brief Tells the object supervisor that the given sprite pointer
213     *** is the party member object.
214     *** This later permits to refresh the sprite shown based on the battle
215     *** formation front party member.
216     **/
SetPartyMemberVisibleSprite(private_map::MapSprite * sprite)217     void SetPartyMemberVisibleSprite(private_map::MapSprite *sprite) {
218         _visible_party_member = sprite;
219     }
220 
221     /** Updates the party member sprite based on the first active party member
222     *** given by the global Manager.
223     **/
224     void ReloadVisiblePartyMember();
225 
226     /** \brief Changes the state of every registered enemy sprite to 'dead'
227     *** Typically used just before a battle begins so that when the player returns to the map, they
228     *** are not swarmed by nearby enemies and quickly forced into another battle. This applies to enemies
229     *** on all object layers and in any context. Exercise caution when invoking this method.
230     **/
231     void SetAllEnemyStatesToDead();
232 
233     //! \brief Tells whether the collision coords are valid.
234     bool IsWithinMapBounds(float x, float y) const;
235 
236     //! \brief Tells whether the sprite has got valid collision coordinates.
237     bool IsWithinMapBounds(VirtualSprite *sprite) const;
238 
239     //! \brief Draw the collision rectangles. Used for debugging purpose.
240     void DrawCollisionArea(const MapFrame *frame);
241 
242     //! \brief some retrieval functions. These are all const to indicate that
243     //! external callers cannot modify the contents of the map_object;
244 
245     //! \brief get the number of rows and columns in the collision grid
GetGridAxis(uint32_t & x,uint32_t & y)246     void GetGridAxis(uint32_t &x, uint32_t &y) const {
247         x = _num_grid_x_axis;
248         y = _num_grid_y_axis;
249     }
250 
251     //! \brief checks to see if the location is a wall for the party or not. The naming is to indicate
252     //! that we only check for non-moving objects. IE, characters / NPCs / enemies are not checked
253     //! note that treasure boxes, save spots, etc are also skipped
254     //! \param x x location on collision grid
255     //! \param y y location on collision grid
256     //! \return whether the location would be a "wall" for the party or not
257     bool IsStaticCollision(float x, float y);
258 
259     //! \brief checks if the location on the grid has a simple map collision. This is different from
260     //! IsStaticCollision, in that it DOES NOT check static objects, but only the collision value for the map
IsMapCollision(uint32_t x,uint32_t y)261     bool IsMapCollision(uint32_t x, uint32_t y)
262     { return (_collision_grid[y][x] > 0); }
263 
264     //! \brief returns a const reference to the ground objects in
GetGroundObjects()265     const std::vector<MapObject *>& GetGroundObjects() const
266     { return _ground_objects; }
267 
268     //! \brief Stops sounds objects such as ambient sounds.
269     //! Used when starting a battle for instance.
270     void StopSoundObjects();
271 
272     //! \brief Restarts sounds objects that were previously stopped.
273     //! Used when leaving a battle for instance.
274     void RestartSoundObjects();
275 
276 private:
277     //! \brief Returns the nearest map point. Used by FindNearestObject.
278     private_map::MapObject* _FindNearestMapPoint(const VirtualSprite* sprite);
279 
280     //! \brief Updates save points animation and active state.
281     void _UpdateMapPoints();
282 
283     //! \brief Updates the ambient sounds volume according to the camera distance.
284     void _UpdateAmbientSounds();
285 
286     //! \brief Debug: Draws the map zones in orange
287     void _DrawMapZones();
288 
289     //! \brief Returns the MapObject vector corresponding to the draw layer.
290     std::vector<MapObject*>& _GetObjectsFromDrawLayer(MapObjectDrawLayer layer);
291 
292     /** \brief The number of rows and columns in the collision grid
293     *** The number of collision grid rows and columns is always equal to twice
294     *** that of the number of rows and columns of tiles (stored in the TileManager).
295     **/
296     uint16_t _num_grid_x_axis, _num_grid_y_axis;
297 
298     //! \brief Holds the most recently generated object ID number
299     uint16_t _last_id;
300 
301     /** \brief The party member object is used to keep in memory the active member
302     *** seen on map. This is later useful in "dungeon" maps for instance, where
303     *** the party member in front of the battle formation is the one shown on map.
304     *** Do not create or delete it in the code, this is just a reference.
305     **/
306     private_map::MapSprite* _visible_party_member;
307 
308     /** \brief A 2D vector indicating which grid element on the map sprites may be occupied by objects.
309     *** Each bit of each element in this grid corresponds to a context. So all together this entire grid
310     *** stores the collision information for all 32 possible map contexts.
311     *** \Note A position in this member is stored like this:
312     *** _collision_grid[y][x]
313     **/
314     std::vector<std::vector<uint32_t> > _collision_grid;
315 
316     /** \brief A map containing pointers to all of the sprites on a map.
317     *** This map does not include a pointer to the _virtual_focus object. The
318     *** sprite's unique identifier integer is used as the vector key.
319     *** MapObjects should only be deleted here.
320     **/
321     std::vector<MapObject *> _all_objects;
322 
323     /** \brief A container for all of the map objects located on the ground layer, and being flat.
324     *** See this layer as a pre ground object layer
325     **/
326     std::vector<MapObject *> _flat_ground_objects;
327 
328     /** \brief A container for all of the map objects located on the ground layer.
329     *** The ground object layer is where most objects and sprites exist in a typical map.
330     **/
331     std::vector<MapObject *> _ground_objects;
332 
333     /** \brief A container for all of the map objects located on the pass layer.
334     *** The pass object layer is named so because objects on this layer can both be
335     *** walked under or above by objects in the ground object layer. A good example
336     *** of an object that would typically go on this layer would be a bridge. This
337     *** layer usually has very few objects for the map.
338     **/
339     std::vector<MapObject *> _pass_objects;
340 
341     /** \brief A container for all of the map objects located on the sky layer.
342     *** The sky object layer contains the last series of elements that are drawn on
343     *** a map. These objects exist high in the sky above all other tiles and objects.
344     *** Translucent clouds can make good use of this object layer, for instance.
345     **/
346     std::vector<MapObject *> _sky_objects;
347 
348     //! \brief A container for all of the save points, quite similar as the ground objects container.
349     std::vector<SavePoint *> _save_points;
350 
351     //! \brief A container for all of the escape points, quite similar as the ground objects container.
352     std::vector<EscapePoint *> _escape_points;
353 
354     //! \brief Ambient sound objects, that plays a sound with a volume according
355     //! to the distance with the camera.
356     std::vector<SoundObject *> _sound_objects;
357 
358     //! \brief Vector used to know at what exact volume a sound should be played
359     //! when there are several instances of the same sound in a MapMode.
360     //! They are also used when restarting the MapMode.
361     std::vector<SoundObject*> _sound_object_highest_volumes;
362 
363     //! \brief Containers for all of the map source of light, quite similar as the ground objects container.
364     std::vector<Halo *> _halos;
365     std::vector<Light *> _lights;
366 
367     //! \brief Container for all zones used in this map
368     std::vector<MapZone *> _zones;
369 }; // class ObjectSupervisor
370 
371 } // namespace private_map
372 
373 } // namespace vt_map
374 
375 #endif // __MAP_OBJECT_SUPERVISOR_HEADER__
376