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