1 #pragma once
2 #ifndef CATA_SRC_OVERMAPBUFFER_H
3 #define CATA_SRC_OVERMAPBUFFER_H
4 
5 #include <array>
6 #include <functional>
7 #include <iosfwd>
8 #include <memory>
9 #include <new>
10 #include <set>
11 #include <unordered_map>
12 #include <utility>
13 #include <vector>
14 
15 #include "coordinates.h"
16 #include "enums.h"
17 #include "memory_fast.h"
18 #include "omdata.h"
19 #include "optional.h"
20 #include "overmap_types.h"
21 #include "type_id.h"
22 
23 class basecamp;
24 class character_id;
25 class map_extra;
26 class monster;
27 class npc;
28 class overmap;
29 class overmap_special_batch;
30 class vehicle;
31 struct mongroup;
32 struct om_vehicle;
33 struct radio_tower;
34 struct regional_settings;
35 
36 struct path_type {
37     bool only_road = false;
38     bool only_water = false;
39     bool amphibious = false;
40     bool only_air = false;
41     bool avoid_danger = false;
42     bool only_known_by_player = false;
43 };
44 
45 struct radio_tower_reference {
46     /** The radio tower itself, points into @ref overmap::radios */
47     radio_tower *tower;
48     /** The global absolute position of the tower (in submap coordinates) */
49     point_abs_sm abs_sm_pos;
50     /** Perceived signal strength (tower output strength minus distance) */
51     int signal_strength;
52     explicit operator bool() const {
53         return tower != nullptr;
54     }
55 };
56 
57 struct city_reference {
58     static const city_reference invalid;
59     /** The city itself, points into @ref overmap::cities */
60     const struct city *city;
61     /** The global absolute position of the city (in submap coordinates!) */
62     tripoint_abs_sm abs_sm_pos;
63     /** Distance to center of the search */
64     int distance;
65 
66     explicit operator bool() const {
67         return city != nullptr;
68     }
69 
70     int get_distance_from_bounds() const;
71 };
72 
73 struct camp_reference {
74     static const camp_reference invalid;
75     /** The camp itself, points into @ref overmap::camps */
76     basecamp *camp;
77     /** The global absolute position of the camp (in submap coordinates!) */
78     tripoint_abs_sm abs_sm_pos;
79     /** Distance to center of the search */
80     int distance;
81 
82     explicit operator bool() const {
83         return camp != nullptr;
84     }
85 
86     int get_distance_from_bounds() const;
87 };
88 
89 struct overmap_with_local_coords {
90     overmap *om;
91     tripoint_om_omt local;
92 
93     bool operator!() const {
94         return !om;
95     }
96 
97     explicit operator bool() const {
98         return !!om;
99     }
100 };
101 
102 /*
103  * Standard arguments for finding overmap terrain
104  * @param origin Location of search
105  * @param types vector of Terrain type/matching rule to use to find the type
106  * @param search_range The maximum search distance.  If 0, OMAPX is used.
107  * @param min_distance Matches within min_distance are ignored.
108  * @param must_see If true, only terrain seen by the player should be searched.
109  * @param cant_see If true, only terrain not seen by the player should be searched
110  * @param existing_overmaps_only If true, will restrict searches to existing overmaps only. This
111  * is particularly useful if we want to attempt to add a missing overmap special to an existing
112  * overmap rather than creating many overmaps in an attempt to find it.
113  * @param om_special If set, the terrain must be part of the specified overmap special.
114 */
115 struct omt_find_params {
116     std::vector<std::pair<std::string, ot_match_type>> types;
117     int search_range = 0;
118     int min_distance = 0;
119     bool must_see = false;
120     bool cant_see = false;
121     bool existing_only = false;
122     cata::optional<overmap_special_id> om_special = cata::nullopt;
123 };
124 
125 class overmapbuffer
126 {
127     public:
128         overmapbuffer();
129 
130         static std::string terrain_filename( const point_abs_om & );
131         static std::string player_filename( const point_abs_om & );
132 
133         /**
134          * Uses overmap coordinates, that means x and y are directly
135          * compared with the position of the overmap.
136          */
137         overmap &get( const point_abs_om & );
138         void save();
139         void clear();
140         void create_custom_overmap( const point_abs_om &, overmap_special_batch &specials );
141 
142         /**
143          * Uses global overmap terrain coordinates, creates the
144          * overmap if needed.
145          */
146         const oter_id &ter( const tripoint_abs_omt &p );
147         void ter_set( const tripoint_abs_omt &p, const oter_id &id );
148         /**
149          * Uses global overmap terrain coordinates.
150          */
151         bool has_note( const tripoint_abs_omt &p );
152         bool is_marked_dangerous( const tripoint_abs_omt &p );
153         const std::string &note( const tripoint_abs_omt &p );
154         void add_note( const tripoint_abs_omt &, const std::string &message );
155         void delete_note( const tripoint_abs_omt &p );
156         void mark_note_dangerous( const tripoint_abs_omt &p, int radius, bool is_dangerous );
157         bool has_extra( const tripoint_abs_omt &p );
158         const string_id<map_extra> &extra( const tripoint_abs_omt &p );
159         void add_extra( const tripoint_abs_omt &p, const string_id<map_extra> &id );
160         void delete_extra( const tripoint_abs_omt &p );
161         bool is_explored( const tripoint_abs_omt &p );
162         void toggle_explored( const tripoint_abs_omt &p );
163         bool seen( const tripoint_abs_omt &p );
164         void set_seen( const tripoint_abs_omt &p, bool seen = true );
165         bool has_camp( const tripoint_abs_omt &p );
166         bool has_vehicle( const tripoint_abs_omt &p );
167         bool has_horde( const tripoint_abs_omt &p );
168         int get_horde_size( const tripoint_abs_omt &p );
169         std::vector<om_vehicle> get_vehicle( const tripoint_abs_omt &p );
170         const regional_settings &get_settings( const tripoint_abs_omt &p );
171         /**
172          * Accessors for horde introspection into overmaps.
173          * Probably also useful for NPC overmap-scale navigation.
174          */
175         /**
176          * Returns the 3x3 array of scent values surrounding the origin point.
177          * @param origin is in world-global omt coordinates.
178          */
179         std::array<std::array<scent_trace, 3>, 3> scents_near( const tripoint_abs_omt &origin );
180         /**
181          * Method to retrieve the scent at a given location.
182          **/
183         scent_trace scent_at( const tripoint_abs_omt &pos );
184         /**
185          * Method to set a scent trace.
186          * @param loc is in world-global omt coordinates.
187          * @param strength sets the intensity of the scent trace,
188          *     used for determining if a monster can detect the scent.
189          */
190         void set_scent( const tripoint_abs_omt &loc, int strength );
191         /**
192          * Check for any dangerous monster groups at the global overmap terrain coordinates.
193          * If there are any, it's not safe.
194          */
195         bool is_safe( const tripoint_abs_omt &p );
196 
197         /**
198          * Move the tracking mark of the given vehicle.
199          * @param veh The vehicle whose tracking device is active and
200          * that has been moved.
201          * @param old_msp The previous position (before the movement) of the
202          * vehicle. In map square coordinates (see vehicle::real_global_pos), it's
203          * used to remove the vehicle from the old overmap if the new position is
204          * on another overmap.
205          */
206         void move_vehicle( vehicle *veh, const point_abs_ms &old_msp );
207         /**
208          * Add the vehicle to be tracked in the overmap.
209          */
210         void add_vehicle( vehicle *veh );
211         /**
212          * Remove basecamp
213          */
214         void remove_camp( const basecamp &camp );
215         /**
216          * Remove the vehicle from being tracked in the overmap.
217          */
218         void remove_vehicle( const vehicle *veh );
219         /**
220          * Add Basecamp to overmapbuffer
221          */
222         void add_camp( const basecamp &camp );
223 
224         cata::optional<basecamp *> find_camp( const point_abs_omt &p );
225         /**
226          * Get all npcs in a area with given radius around given central point.
227          * Only npcs on the given z-level are considered.
228          * Uses square_dist for distance calculation.
229          * @param p Central point in submap coordinates.
230          * @param radius Maximal distance of npc from (x,y). If the npc
231          * is at most this far away from (x,y) it will be returned.
232          * A radius of 0 returns only those npcs that are on the
233          * specific submap.
234          */
235 
236         std::vector<shared_ptr_fast<npc>> get_npcs_near( const tripoint_abs_sm &p, int radius );
237         /**
238          * Get all (currently loaded!) npcs that have a companion
239          * mission set.
240          */
241         std::vector<shared_ptr_fast<npc>> get_companion_mission_npcs( int range = 100 );
242         /**
243          * Uses overmap terrain coordinates, this also means radius is
244          * in overmap terrain.
245          * A radius of 0 returns all npcs that are on that specific
246          * overmap terrain tile.
247          */
248         std::vector<shared_ptr_fast<npc>> get_npcs_near_omt( const tripoint_abs_omt &p, int radius );
249         /**
250          * Same as @ref get_npcs_near(int,int,int,int) but uses
251          * player position as center.
252          */
253         std::vector<shared_ptr_fast<npc>> get_npcs_near_player( int radius );
254         /**
255          * Find the npc with the given ID.
256          * Returns NULL if the npc could not be found.
257          * Searches all loaded overmaps.
258          */
259         shared_ptr_fast<npc> find_npc( character_id id );
260         /**
261          * Get all NPCs active on the overmap
262          */
263         std::vector<shared_ptr_fast<npc>> get_overmap_npcs();
264         /**
265          * Find npc by id and if found, erase it from the npc list
266          * and return it ( or return nullptr if not found ).
267          */
268         shared_ptr_fast<npc> remove_npc( const character_id &id );
269         /**
270          * Adds the npc to an overmap ( based on the npcs current location )
271          * and stores it there. The overmap takes ownership of the pointer.
272          */
273         void insert_npc( const shared_ptr_fast<npc> &who );
274 
275         /**
276          * Find all places with the specific overmap terrain type.
277          * The function only searches on the z-level indicated by
278          * origin.
279          * This function may create a new overmap if needed.
280          * @param origin Location of search
281          * see omt_find_params for definitions of the terms
282          */
283         std::vector<tripoint_abs_omt> find_all( const tripoint_abs_omt &origin,
284                                                 const omt_find_params &params );
285         std::vector<tripoint_abs_omt> find_all(
286             const tripoint_abs_omt &origin, const std::string &type,
287             int dist, bool must_be_seen, ot_match_type match_type = ot_match_type::type,
288             bool existing_overmaps_only = false,
289             const cata::optional<overmap_special_id> &om_special = cata::nullopt );
290 
291         /**
292          * Returns a random point of specific terrain type among those found in certain search
293          * radius.
294          * This function may create new overmaps if needed.
295          * @param origin Location of search
296          * see omt_find_params for definitions of the terms
297          */
298         tripoint_abs_omt find_random( const tripoint_abs_omt &origin,
299                                       const omt_find_params &params );
300         tripoint_abs_omt find_random(
301             const tripoint_abs_omt &origin, const std::string &type, int dist,
302             bool must_be_seen, ot_match_type match_type = ot_match_type::type,
303             bool existing_overmaps_only = false,
304             const cata::optional<overmap_special_id> &om_special = cata::nullopt );
305         /**
306          * Mark a square area around center on Z-level z
307          * as seen.
308          * @param center is in absolute overmap terrain coordinates.
309          * @param radius The half size of the square to make visible.
310          * A value of 0 makes only center visible, radius 1 makes a
311          * square 3x3 visible.
312          * @param z Z level to make area on
313          * @return true if something has actually been revealed.
314          */
315         bool reveal( const point_abs_omt &center, int radius, int z );
316         bool reveal( const tripoint_abs_omt &center, int radius );
317         bool reveal( const tripoint_abs_omt &center, int radius,
318                      const std::function<bool( const oter_id & )> &filter );
319         std::vector<tripoint_abs_omt> get_npc_path( const tripoint_abs_omt &src,
320                 const tripoint_abs_omt &dest );
321         std::vector<tripoint_abs_omt> get_npc_path(
322             const tripoint_abs_omt &src, const tripoint_abs_omt &dest, path_type &ptype );
323         bool reveal_route( const tripoint_abs_omt &source, const tripoint_abs_omt &dest,
324                            int radius = 0, bool road_only = false );
325         /**
326          * Returns the closest point of terrain type.
327          * @param origin Location of search
328          * see omt_find_params for definitions of the terms
329          */
330         tripoint_abs_omt find_closest( const tripoint_abs_omt &origin,
331                                        const omt_find_params &params );
332         tripoint_abs_omt find_closest(
333             const tripoint_abs_omt &origin, const std::string &type, int radius, bool must_be_seen,
334             ot_match_type match_type = ot_match_type::type, bool existing_overmaps_only = false,
335             const cata::optional<overmap_special_id> &om_special = cata::nullopt );
336 
337         /* These functions return the overmap that contains the given
338          * overmap terrain coordinate, and the local coordinates of that point
339          * within the overmap (for use with overmap APIs).
340          * get_existing_om_global will not create a new overmap and
341          * if the requested overmap does not yet exist it returns
342          * { nullptr, tripoint_zero }.
343          * get_om_global creates a new overmap if needed.
344          */
345         overmap_with_local_coords get_existing_om_global( const point_abs_omt &p );
346         overmap_with_local_coords get_existing_om_global( const tripoint_abs_omt &p );
347         overmap_with_local_coords get_om_global( const point_abs_omt &p );
348         overmap_with_local_coords get_om_global( const tripoint_abs_omt &p );
349 
350         /**
351          * Pass global overmap coordinates (same as @ref get).
352          * @returns true if the buffer has a overmap with
353          * the given coordinates.
354          */
355         bool has( const point_abs_om &p );
356         /**
357          * Get an existing overmap, does not create a new one
358          * and may return NULL if the requested overmap does not
359          * exist.
360          * (x,y) are global overmap coordinates (same as @ref get).
361          */
362         overmap *get_existing( const point_abs_om &p );
363         /**
364          * Returns whether or not the location has been generated (e.g. mapgen has run).
365          * @param loc is in world-global omt coordinates.
366          * @returns True if the location has been generated.
367          */
368         bool is_omt_generated( const tripoint_abs_omt &loc );
369 
370         using t_point_with_note = std::pair<point_abs_omt, std::string>;
371         using t_notes_vector = std::vector<t_point_with_note>;
get_all_notes(int z)372         t_notes_vector get_all_notes( int z ) {
373             return get_notes( z, nullptr ); // NULL => don't filter notes
374         }
find_notes(int z,const std::string & pattern)375         t_notes_vector find_notes( int z, const std::string &pattern ) {
376             return get_notes( z, &pattern ); // filter with pattern
377         }
378         using t_point_with_extra = std::pair<point_abs_omt, string_id<map_extra>>;
379         using t_extras_vector = std::vector<t_point_with_extra>;
get_all_extras(int z)380         t_extras_vector get_all_extras( int z ) {
381             return get_extras( z, nullptr ); // NULL => don't filter extras
382         }
find_extras(int z,const std::string & pattern)383         t_extras_vector find_extras( int z, const std::string &pattern ) {
384             return get_extras( z, &pattern ); // filter with pattern
385         }
386         /**
387          * Signal nearby hordes to move to given location.
388          * @param center The origin of the signal, hordes (that recognize the signal) want to go
389          * to there. In global submap coordinates.
390          * @param sig_power The signal strength, higher values means it visible farther away.
391          */
392         void signal_hordes( const tripoint_abs_sm &center, int sig_power );
393         /**
394          * Process nearby monstergroups (dying mostly).
395          */
396         void process_mongroups();
397         /**
398          * Let hordes move a step. Note that this may move monster groups inside the reality bubble,
399          * therefore you should probably call @ref map::spawn_monsters to spawn them.
400          */
401         void move_hordes();
402         // hordes -- this uses overmap terrain coordinates!
403         std::vector<mongroup *> monsters_at( const tripoint_abs_omt &p );
404         /**
405          * Monster groups at p - absolute submap coordinates.
406          * Groups with no population are not included.
407          */
408         std::vector<mongroup *> groups_at( const tripoint_abs_sm &p );
409 
410         /**
411          * Spawn monsters from the overmap onto the main map (game::m).
412          * p is an absolute *submap* coordinate.
413          */
414         void spawn_monster( const tripoint_abs_sm &p );
415         /**
416          * Despawn the monster back onto the overmap. The monsters position
417          * (monster::pos()) is interpreted as relative to the main map.
418          */
419         void despawn_monster( const monster &critter );
420         /**
421          * Find radio station with given frequency, search an unspecified area around
422          * the current player location.
423          * If no matching tower has been found, it returns an object with the tower pointer set
424          * to null.
425          */
426         radio_tower_reference find_radio_station( int frequency );
427         /**
428          * Find all radio stations that can be received around the current player location.
429          * All entries in the returned vector are valid (have a valid tower pointer).
430          */
431         std::vector<radio_tower_reference> find_all_radio_stations();
432         std::vector<camp_reference> get_camps_near( const tripoint_abs_sm &location, int radius );
433         /**
434          * Find all cities within the specified @ref radius.
435          * Result is sorted by proximity to @ref location in ascending order.
436          */
437         std::vector<city_reference> get_cities_near( const tripoint_abs_sm &location, int radius );
438         /**
439          * Find the closest city. If no city is close, returns an object with city set to nullptr.
440          * @param center The center of the search, the distance for determining the closest city is
441          * calculated as distance to this point. In global submap coordinates!
442          */
443         city_reference closest_city( const tripoint_abs_sm &center );
444 
445         city_reference closest_known_city( const tripoint_abs_sm &center );
446 
447         std::string get_description_at( const tripoint_abs_sm &where );
448 
449         /**
450          * Place the specified overmap special directly on the map using the provided location and rotation.
451          * Intended to be used when you have a special in hand, the desired location and rotation are known
452          * and the special should be directly placed rather than using the overmap's placement algorithm.
453          * @param special The overmap special to place.
454          * @param p The location to place the overmap special. Absolute overmap terrain coordinates.
455          * @param dir The direction to rotate the overmap special before placement.
456          * @param must_be_unexplored If true, will require that all of the terrains where the special would be
457          * placed are unexplored.
458          * @param force If true, placement will bypass the checks for valid placement.
459          * @returns True if the special was placed, else false.
460          */
461         bool place_special( const overmap_special &special, const tripoint_abs_omt &p,
462                             om_direction::type dir,
463                             bool must_be_unexplored, bool force );
464         /**
465          * Place the specified overmap special using the overmap's placement algorithm. Intended to be used
466          * when you have a special that you want placed but it should be placed similarly to as if it were
467          * created during overmap generation.
468          * @param special_id The id of overmap special to place.
469          * @param center Used in conjunction with radius to search the specified and adjacent overmaps for
470          * a valid placement location. Absolute overmap terrain coordinates.
471          * @param radius Used in conjunction with center. Absolute overmap terrain units.
472          * @returns True if the special was placed, else false.
473          */
474         bool place_special( const overmap_special_id &special_id, const tripoint_abs_omt &center,
475                             int radius );
476 
477     private:
478         /**
479          * Common function used by the find_closest/all/random to determine if the location is
480          * findable based on the specified criteria.
481          * @param location Location of search
482          * see omt_find_params for definitions of the terms
483          */
484         bool is_findable_location( const tripoint_abs_omt &location, const omt_find_params &params );
485 
486         std::unordered_map< point_abs_om, std::unique_ptr< overmap > > overmaps;
487         /**
488          * Set of overmap coordinates of overmaps that are known
489          * to not exist on disk. See @ref get_existing for usage.
490          */
491         mutable std::set<point_abs_om> known_non_existing;
492         // Cached result of previous call to overmapbuffer::get_existing
493         overmap mutable *last_requested_overmap;
494 
495         /**
496          * Get a list of notes in the (loaded) overmaps.
497          * @param z only this specific z-level is search for notes.
498          * @param pattern only notes that contain this pattern are returned.
499          * If the pattern is NULL, every note matches.
500          */
501         t_notes_vector get_notes( int z, const std::string *pattern );
502         /**
503          * Get a list of map extras in the (loaded) overmaps.
504          * @param z only this specific z-level is search for map extras.
505          * @param pattern only map extras that contain this pattern are returned.
506          * If the pattern is NULL, every map extra matches.
507          */
508         t_extras_vector get_extras( int z, const std::string *pattern );
509     public:
510         /**
511          * See overmap::check_ot, this uses global
512          * overmap terrain coordinates.
513          * This function may create a new overmap if needed.
514          */
515         bool check_ot( const std::string &otype, ot_match_type match_type,
516                        const tripoint_abs_omt &p );
517         bool check_overmap_special_type( const overmap_special_id &id, const tripoint_abs_omt &loc );
518 
519         /**
520         * These versions of the check_* methods will only check existing overmaps, and
521         * return false if the overmap doesn't exist. They do not create new overmaps.
522         */
523         bool check_ot_existing( const std::string &otype, ot_match_type match_type,
524                                 const tripoint_abs_omt &loc );
525         bool check_overmap_special_type_existing( const overmap_special_id &id,
526                 const tripoint_abs_omt &loc );
527     private:
528         /**
529          * Go thorough the monster groups of the overmap and move out-of-bounds
530          * groups to the correct overmap (if it exists), also removes empty groups.
531          */
532         void fix_mongroups( overmap &new_overmap );
533         /**
534          * Moves out-of-bounds NPCs to the overmaps they should be in.
535          */
536         void fix_npcs( overmap &new_overmap );
537         /**
538          * Retrieve overmaps that overlap the bounding box defined by the location and radius.
539          * The location is in absolute submap coordinates, the radius is in the same system.
540          * The overmaps are returned sorted by distance from the provided location (closest first).
541          */
542         std::vector<overmap *> get_overmaps_near( const point_abs_sm &p, int radius );
543         std::vector<overmap *> get_overmaps_near( const tripoint_abs_sm &location, int radius );
544 };
545 
546 extern overmapbuffer overmap_buffer;
547 
548 #endif // CATA_SRC_OVERMAPBUFFER_H
549