1 #pragma once
2 #ifndef CATA_SRC_SUBMAP_H
3 #define CATA_SRC_SUBMAP_H
4 
5 #include <cstddef>
6 #include <cstdint>
7 #include <iosfwd>
8 #include <iterator>
9 #include <map>
10 #include <memory>
11 #include <string>
12 #include <vector>
13 
14 #include "active_item_cache.h"
15 #include "calendar.h"
16 #include "colony.h"
17 #include "computer.h"
18 #include "construction.h"
19 #include "field.h"
20 #include "game_constants.h"
21 #include "item.h"
22 #include "mapgen.h"
23 #include "point.h"
24 #include "type_id.h"
25 
26 class JsonIn;
27 class JsonOut;
28 class basecamp;
29 class map;
30 class vehicle;
31 struct furn_t;
32 struct ter_t;
33 struct trap;
34 
35 struct spawn_point {
36     point pos;
37     int count;
38     mtype_id type;
39     int faction_id;
40     int mission_id;
41     bool friendly;
42     std::string name;
43     spawn_data data;
44     explicit spawn_point( const mtype_id &T = mtype_id::NULL_ID(), int C = 0, point P = point_zero,
45                           int FAC = -1, int MIS = -1, bool F = false,
46                           const std::string &N = "NONE", spawn_data SD = spawn_data() ) :
posspawn_point47         pos( P ), count( C ), type( T ), faction_id( FAC ),
48         mission_id( MIS ), friendly( F ), name( N ), data( SD ) {}
49 };
50 
51 template<int sx, int sy>
52 struct maptile_soa {
53     ter_id             ter[sx][sy];  // Terrain on each square
54     furn_id            frn[sx][sy];  // Furniture on each square
55     std::uint8_t       lum[sx][sy];  // Number of items emitting light on each square
56     cata::colony<item> itm[sx][sy];  // Items on each square
57     field              fld[sx][sy];  // Field on each square
58     trap_id            trp[sx][sy];  // Trap on each square
59     int                rad[sx][sy];  // Irradiation of each square
60 
61     void swap_soa_tile( const point &p1, const point &p2 );
62 };
63 
64 class submap : maptile_soa<SEEX, SEEY>
65 {
66     public:
67         submap();
68         submap( submap && );
69         ~submap();
70 
71         submap &operator=( submap && );
72 
get_trap(const point & p)73         trap_id get_trap( const point &p ) const {
74             return trp[p.x][p.y];
75         }
76 
set_trap(const point & p,trap_id trap)77         void set_trap( const point &p, trap_id trap ) {
78             is_uniform = false;
79             trp[p.x][p.y] = trap;
80         }
81 
set_all_traps(const trap_id & trap)82         void set_all_traps( const trap_id &trap ) {
83             std::uninitialized_fill_n( &trp[0][0], elements, trap );
84         }
85 
get_furn(const point & p)86         furn_id get_furn( const point &p ) const {
87             return frn[p.x][p.y];
88         }
89 
set_furn(const point & p,furn_id furn)90         void set_furn( const point &p, furn_id furn ) {
91             is_uniform = false;
92             frn[p.x][p.y] = furn;
93         }
94 
set_all_furn(const furn_id & furn)95         void set_all_furn( const furn_id &furn ) {
96             std::uninitialized_fill_n( &frn[0][0], elements, furn );
97         }
98 
get_ter(const point & p)99         ter_id get_ter( const point &p ) const {
100             return ter[p.x][p.y];
101         }
102 
set_ter(const point & p,ter_id terr)103         void set_ter( const point &p, ter_id terr ) {
104             is_uniform = false;
105             ter[p.x][p.y] = terr;
106         }
107 
set_all_ter(const ter_id & terr)108         void set_all_ter( const ter_id &terr ) {
109             std::uninitialized_fill_n( &ter[0][0], elements, terr );
110         }
111 
get_radiation(const point & p)112         int get_radiation( const point &p ) const {
113             return rad[p.x][p.y];
114         }
115 
set_radiation(const point & p,const int radiation)116         void set_radiation( const point &p, const int radiation ) {
117             is_uniform = false;
118             rad[p.x][p.y] = radiation;
119         }
120 
get_lum(const point & p)121         uint8_t get_lum( const point &p ) const {
122             return lum[p.x][p.y];
123         }
124 
set_lum(const point & p,uint8_t luminance)125         void set_lum( const point &p, uint8_t luminance ) {
126             is_uniform = false;
127             lum[p.x][p.y] = luminance;
128         }
129 
update_lum_add(const point & p,const item & i)130         void update_lum_add( const point &p, const item &i ) {
131             is_uniform = false;
132             if( i.is_emissive() && lum[p.x][p.y] < 255 ) {
133                 lum[p.x][p.y]++;
134             }
135         }
136 
update_lum_rem(const point & p,const item & i)137         void update_lum_rem( const point &p, const item &i ) {
138             is_uniform = false;
139             if( !i.is_emissive() ) {
140                 return;
141             } else if( lum[p.x][p.y] && lum[p.x][p.y] < 255 ) {
142                 lum[p.x][p.y]--;
143                 return;
144             }
145 
146             // Have to scan through all items to be sure removing i will actually lower
147             // the count below 255.
148             int count = 0;
149             for( const auto &it : itm[p.x][p.y] ) {
150                 if( it.is_emissive() ) {
151                     count++;
152                 }
153             }
154 
155             if( count <= 256 ) {
156                 lum[p.x][p.y] = static_cast<uint8_t>( count - 1 );
157             }
158         }
159 
160         // TODO: Replace this as it essentially makes itm public
get_items(const point & p)161         cata::colony<item> &get_items( const point &p ) {
162             return itm[p.x][p.y];
163         }
164 
get_items(const point & p)165         const cata::colony<item> &get_items( const point &p ) const {
166             return itm[p.x][p.y];
167         }
168 
169         // TODO: Replace this as it essentially makes fld public
get_field(const point & p)170         field &get_field( const point &p ) {
171             return fld[p.x][p.y];
172         }
173 
get_field(const point & p)174         const field &get_field( const point &p ) const {
175             return fld[p.x][p.y];
176         }
177 
178         struct cosmetic_t {
179             point pos;
180             std::string type;
181             std::string str;
182         };
183 
insert_cosmetic(const point & p,const std::string & type,const std::string & str)184         void insert_cosmetic( const point &p, const std::string &type, const std::string &str ) {
185             cosmetic_t ins;
186 
187             ins.pos = p;
188             ins.type = type;
189             ins.str = str;
190 
191             cosmetics.push_back( ins );
192         }
193 
get_temperature()194         int get_temperature() const {
195             return temperature;
196         }
197 
set_temperature(int new_temperature)198         void set_temperature( int new_temperature ) {
199             temperature = new_temperature;
200         }
201 
202         bool has_graffiti( const point &p ) const;
203         const std::string &get_graffiti( const point &p ) const;
204         void set_graffiti( const point &p, const std::string &new_graffiti );
205         void delete_graffiti( const point &p );
206 
207         // Signage is a pretend union between furniture on a square and stored
208         // writing on the square. When both are present, we have signage.
209         // Its effect is meant to be cosmetic and atmospheric only.
210         bool has_signage( const point &p ) const;
211         // Dependent on furniture + cosmetics.
212         std::string get_signage( const point &p ) const;
213         // Can be used anytime (prevents code from needing to place sign first.)
214         void set_signage( const point &p, const std::string &s );
215         // Can be used anytime (prevents code from needing to place sign first.)
216         void delete_signage( const point &p );
217 
218         bool has_computer( const point &p ) const;
219         const computer *get_computer( const point &p ) const;
220         computer *get_computer( const point &p );
221         void set_computer( const point &p, const computer &c );
222         void delete_computer( const point &p );
223 
224         bool contains_vehicle( vehicle * );
225 
226         void rotate( int turns );
227 
228         void store( JsonOut &jsout ) const;
229         void load( JsonIn &jsin, const std::string &member_name, int version );
230 
231         // If is_uniform is true, this submap is a solid block of terrain
232         // Uniform submaps aren't saved/loaded, because regenerating them is faster
233         bool is_uniform = false;
234 
235         std::vector<cosmetic_t> cosmetics; // Textual "visuals" for squares
236 
237         active_item_cache active_items;
238 
239         int field_count = 0;
240         time_point last_touched = calendar::turn_zero;
241         std::vector<spawn_point> spawns;
242         /**
243          * Vehicles on this submap (their (0,0) point is on this submap).
244          * This vehicle objects are deleted by this submap when it gets
245          * deleted.
246          */
247         std::vector<std::unique_ptr<vehicle>> vehicles;
248         std::map<tripoint, partial_con> partial_constructions;
249         std::unique_ptr<basecamp> camp;  // only allowing one basecamp per submap
250 
251     private:
252         std::map<point, computer> computers;
253         std::unique_ptr<computer> legacy_computer;
254         int temperature = 0;
255 
256         void update_legacy_computer();
257 
258         static constexpr size_t elements = SEEX * SEEY;
259 };
260 
261 /**
262  * A wrapper for a submap point. Allows getting multiple map features
263  * (terrain, furniture etc.) without directly accessing submaps or
264  * doing multiple bounds checks and submap gets.
265  */
266 struct maptile {
267     private:
268         friend map; // To allow "sliding" the tile in x/y without bounds checks
269         friend submap;
270         submap *const sm;
271         point pos_;
272 
maptilemaptile273         maptile( submap *sub, const point &p ) :
274             sm( sub ), pos_( p ) { }
275     public:
posmaptile276         inline point pos() const {
277             return pos_;
278         }
279 
get_trapmaptile280         trap_id get_trap() const {
281             return sm->get_trap( pos() );
282         }
283 
get_furnmaptile284         furn_id get_furn() const {
285             return sm->get_furn( pos() );
286         }
287 
get_termaptile288         ter_id get_ter() const {
289             return sm->get_ter( pos() );
290         }
291 
get_trap_tmaptile292         const trap &get_trap_t() const {
293             return sm->get_trap( pos() ).obj();
294         }
295 
get_furn_tmaptile296         const furn_t &get_furn_t() const {
297             return sm->get_furn( pos() ).obj();
298         }
get_ter_tmaptile299         const ter_t &get_ter_t() const {
300             return sm->get_ter( pos() ).obj();
301         }
302 
get_fieldmaptile303         const field &get_field() const {
304             return sm->get_field( pos() );
305         }
306 
find_fieldmaptile307         field_entry *find_field( const field_type_id &field_to_find ) {
308             return sm->get_field( pos() ).find_field( field_to_find );
309         }
310 
get_radiationmaptile311         int get_radiation() const {
312             return sm->get_radiation( pos() );
313         }
314 
has_graffitimaptile315         bool has_graffiti() const {
316             return sm->has_graffiti( pos() );
317         }
318 
get_graffitimaptile319         const std::string &get_graffiti() const {
320             return sm->get_graffiti( pos() );
321         }
322 
has_signagemaptile323         bool has_signage() const {
324             return sm->has_signage( pos() );
325         }
326 
get_signagemaptile327         std::string get_signage() const {
328             return sm->get_signage( pos() );
329         }
330 
331         // For map::draw_maptile
get_item_countmaptile332         size_t get_item_count() const {
333             return sm->get_items( pos() ).size();
334         }
335 
336         // Assumes there is at least one item
get_uppermost_itemmaptile337         const item &get_uppermost_item() const {
338             return *std::prev( sm->get_items( pos() ).cend() );
339         }
340 };
341 
342 #endif // CATA_SRC_SUBMAP_H
343