CorsixTH engine (the C++ part)
Open source implementation of Theme Hospital
Loading...
Searching...
No Matches
th_map.h
Go to the documentation of this file.
1/*
2Copyright (c) 2009 Peter "Corsix" Cawley
3
4Permission is hereby granted, free of charge, to any person obtaining a copy of
5this software and associated documentation files (the "Software"), to deal in
6the Software without restriction, including without limitation the rights to
7use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8of the Software, and to permit persons to whom the Software is furnished to do
9so, subject to the following conditions:
10
11The above copyright notice and this permission notice shall be included in all
12copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20SOFTWARE.
21*/
22
23#ifndef CORSIX_TH_TH_MAP_H_
24#define CORSIX_TH_TH_MAP_H_
25#include "config.h"
26
27#include <list>
28#include <string>
29#include <utility>
30#include <vector>
31
32#include "th.h"
33
36class map_overlay;
37class render_target;
38class sprite_sheet;
39struct drawable;
40
41/*
42 Object type enumeration uses same values as original TH does.
43 See game string table section 39 for proof. Section 1 also has
44 names in this order.
45*/
46enum class object_type : uint8_t {
47 no_object = 0,
48 desk = 1,
49 cabinet = 2,
50 door = 3,
51 bench = 4,
52 table = 5, // Not in game
53 chair = 6,
55 bed = 8,
56 inflator = 9,
57 pool_table = 10,
58 reception_desk = 11,
59 b_table = 12, // Not in game?
60 cardio = 13,
61 scanner = 14,
62 scanner_console = 15,
63 screen = 16,
64 litter_bomb = 17,
65 couch = 18,
66 sofa = 19,
67 crash = 20, // The trolley in general diagnosis
68 tv = 21,
69 ultrascan = 22,
70 dna_fixer = 23,
71 cast_remover = 24,
72 hair_restorer = 25,
73 slicer = 26,
74 xray = 27,
76 xray_viewer = 29,
77 op_table = 30,
78 lamp = 31, // Not in game?
79 sink = 32,
80 op_sink1 = 33,
81 op_sink2 = 34,
82 surgeon_screen = 35,
83 lecture_chair = 36,
84 projector = 37,
85 // 38 is unused
86 pharmacy = 39,
87 computer = 40,
88 chemical_mixer = 41,
89 blood_machine = 42,
90 extinguisher = 43,
91 radiator = 44,
92 plant = 45,
93 electro = 46,
94 jelly_vat = 47,
95 hell = 48,
96 // 49 is unused
97 bin = 50,
98 loo = 51,
99 double_door1 = 52,
100 double_door2 = 53,
101 decon_shower = 54,
102 autopsy = 55,
103 bookcase = 56,
104 video_game = 57,
107 skeleton = 60,
108 comfy_chair = 61,
109 litter = 62,
110 helicopter = 63,
111 rathole = 64,
112 // 65 through 255 are unused
113};
114
119 enum class key : uint32_t {
120 passable_mask = 1 << 0,
121 can_travel_n_mask = 1 << 1,
122 can_travel_e_mask = 1 << 2,
123 can_travel_s_mask = 1 << 3,
124 can_travel_w_mask = 1 << 4,
125 hospital_mask = 1 << 5,
126 buildable_mask = 1 << 6,
128 room_mask = 1 << 8,
129 shadow_half_mask = 1 << 9,
130 shadow_full_mask = 1 << 10,
131 shadow_wall_mask = 1 << 11,
132 door_north_mask = 1 << 12,
133 door_west_mask = 1 << 13,
134 do_not_idle_mask = 1 << 14,
135 tall_north_mask = 1 << 15,
136 tall_west_mask = 1 << 16,
137 buildable_n_mask = 1 << 17,
138 buildable_e_mask = 1 << 18,
139 buildable_s_mask = 1 << 19,
140 buildable_w_mask = 1 << 20,
141 };
142
143 bool passable;
148 bool hospital;
151 bool room;
164
167 map_tile_flags& operator=(uint32_t raw);
168
171
173 const bool& operator[](map_tile_flags::key key) const;
174
176 operator uint32_t() const;
177};
178
180 red,
183};
184
185enum tile_layer : uint8_t {
189 ui = 3,
190
191 num_tile_layers = 4
193
194struct map_tile {
195 map_tile() = default;
196 ~map_tile() = default;
197
198 // Linked list for entities rendered at this tile
200
203
213
216 uint16_t iParcelId{0};
217
219 uint16_t iRoomId{0};
220
226 uint16_t aiTemperature[2]{8192, 8192};
227
230
232 std::list<object_type> objects;
233
234 static constexpr int raw_length = 8;
235
237 std::uint8_t raw[raw_length]{};
238};
239
241
250 uint8_t);
251
253 public:
254 level_map() = default;
255 ~level_map();
256
257 bool set_size(int iWidth, int iHeight);
258 bool load_blank();
259 bool load_from_th_file(const uint8_t* pData, size_t iDataLength,
261 void* pCallbackToken);
262
263 void save(const std::string& filename);
264
266
271
273
277 void set_all_wall_draw_flags(uint8_t iFlags);
278
279 void update_pathfinding();
280 void update_shadows();
283 return current_temperature_theme;
284 }
286 uint16_t iRadiatorTemperature);
287
289 inline int get_width() const { return width; }
290
292 inline int get_height() const { return height; }
293
295 inline int get_parcel_count() const { return parcel_count - 1; }
296
297 inline int get_player_count() const { return player_count; }
298
299 void set_player_count(int count);
300
301 bool get_player_camera_tile(int iPlayer, int* pX, int* pY) const;
302 bool get_player_heliport_tile(int iPlayer, int* pX, int* pY) const;
303 void set_player_camera_tile(int iPlayer, int iX, int iY);
304 void set_player_heliport_tile(int iPlayer, int iX, int iY);
305
307 int get_parcel_tile_count(int iParcelId) const;
308
310
319 std::vector<std::pair<int, int>> set_parcel_owner(int iParcelId, int iOwner);
320
322
327 int get_parcel_owner(int iParcelId) const;
328
330
337
339
348 bool is_parcel_purchasable(int iParcelId, int iPlayer);
349
351
358 void draw(render_target* pCanvas, int iScreenX, int iScreenY, int iWidth,
359 int iHeight, int iCanvasX, int iCanvasY) const;
360
362
369 drawable* hit_test(int iTestX, int iTestY) const;
370
371 // When using the unchecked versions, the map coordinates MUST be valid.
372 // When using the normal versions, nullptr is returned for invalid co-ords.
373 map_tile* get_tile(int iX, int iY);
374 const map_tile* get_tile(int iX, int iY) const;
375 const map_tile* get_original_tile(int iX, int iY) const;
376 map_tile* get_tile_unchecked(int iX, int iY);
377 const map_tile* get_tile_unchecked(int iX, int iY) const;
378 const map_tile* get_original_tile_unchecked(int iX, int iY) const;
379
380 uint16_t get_tile_temperature(const map_tile* pNode) const;
381 int get_tile_owner(const map_tile* pNode) const;
382
384 template <typename T>
385 static inline void world_to_screen(T& x, T& y) {
386 T x_(x);
387 x = (T)32 * (x_ - y);
388 y = (T)16 * (x_ + y);
389 }
390
392 template <typename T>
393 static inline void screen_to_world(T& x, T& y) {
394 T x_(x);
395 x = y / (T)32 + x_ / (T)64;
396 y = y / (T)32 - x_ / (T)64;
397 }
398
401
403
404 private:
405 void draw_floor(render_target* pCanvas, int iScreenX, int iScreenY,
406 int iWidth, int iHeight, int iCanvasX, int iCanvasY) const;
407 void draw_north_wall(const map_tile* tile, int tile_x, int tile_y,
408 render_target* pCanvas) const;
409
410 int draw_layer(const map_tile* tile, int tile_x, int tile_y, tile_layer layer,
411 render_target* pCanvas) const;
412
414 /*
415 * @param layer Layer to investigate.
416 * @param [out] height Height of the sprite if the method returns \c true.
417 * @return Whether the sprite exists and is not empty.
418 */
419 bool layer_exists(uint16_t layer, int& height) const;
420
421 drawable* hit_test_drawables(link_list* pListStart, int iXs, int iYs,
422 int iTestX, int iTestY) const;
423 void read_tile_index(const uint8_t* pData, int& iX, int& iY) const;
424 void write_tile_index(uint8_t* pData, int iX, int iY) const;
425
436 uint32_t thermal_neighbour(uint32_t& iNeighbourSum, bool canTravel,
437 std::ptrdiff_t relative_idx, map_tile* pNode,
438 int prevTemp) const;
439
441 void make_adjacency_matrix();
442
444 void make_purchase_matrix();
445
447 void update_purchase_matrix();
448
449 int count_parcel_tiles(int iParcelId) const;
450
451 map_tile* cells{};
452 map_tile* original_cells{}; // Cells at map load time, before any changes
453 sprite_sheet* wall_blocks{};
454 map_overlay* overlay{};
455 bool owns_overlay{};
456 int* plot_owner{}; // 0 for unowned, 1 for player 1, etc.
457 int width{};
458 int height{};
459 int player_count{};
460 int initial_camera_x[4]{};
461 int initial_camera_y[4]{};
462 int heliport_x[4]{};
463 int heliport_y[4]{};
464 int parcel_count{};
465 int current_temperature_index{};
466 temperature_theme current_temperature_theme{temperature_theme::red};
467 int* parcel_tile_counts{};
468
469 // 2D symmetric array giving true if there is a path between two parcels
470 // which doesn't go into any other parcels.
471 bool* parcel_adjacency_matrix{};
472
473 // 4 by N matrix giving true if player can purchase parcel.
474 bool* purchasable_matrix{};
475};
476
478 forward = 2,
479 backward = 0,
480};
481
483
494 public:
496
509 int iWidth, int iHeight,
512
514 inline operator bool() const { return tile != nullptr; }
515
518
520 inline const map_tile* operator->() const { return tile; }
521
524 inline int tile_x_position_on_screen() const { return x_relative_to_screen; }
525
528 inline int tile_y_position_on_screen() const { return y_relative_to_screen; }
529
530 inline int tile_x() const { return world_x; }
531 inline int tile_y() const { return world_y; }
532
533 inline const level_map* get_map() { return container; }
534 inline const map_tile* get_map_tile() { return tile; }
535 inline int get_scanline_count() { return scanline_count; }
536 inline int get_tile_step() {
537 return (static_cast<int>(direction) - 1) * (1 - container->get_width());
538 }
539
541
545 inline bool is_last_on_scanline() const;
546
547 private:
548 // Maximum extents of the visible parts of a tile (pixel distances relative
549 // to the top-most corner of an isometric cell)
550 // If set too low, things will disappear when near the screen edge
551 // If set too high, rendering will slow down
552 static const int margin_top = 150;
553 static const int margin_left = 110;
554 static const int margin_right = 110;
555 static const int margin_bottom = 150;
556
558
559 const map_tile* tile{nullptr};
560 const level_map* container;
561
562 // TODO: Consider removing these, they are trivial to calculate
563 int x_relative_to_screen{};
564 int y_relative_to_screen{};
565
566 const int screen_offset_x;
567 const int screen_offset_y;
568 const int screen_width;
569 const int screen_height;
570 int base_x;
571 int base_y;
572 int world_x;
573 int world_y;
574 int scanline_count{};
576
577 void advance_until_visible();
578};
579
582 public:
584
594 int iXOffset = 0, int iYOffset = 0);
595
596 inline operator bool() const { return tile != end_tile; }
598
599 inline const map_tile* operator->() const { return tile; }
600 inline int x() const { return x_relative_to_screen; }
601 inline int y() const { return y_relative_to_screen; }
602 inline const map_tile* get_next_tile() { return tile + tile_step; }
603 inline const map_tile* get_previous_tile() { return tile - tile_step; }
605 inline const map_tile* get_tile() { return tile; }
606
607 private:
608 const map_tile* tile;
609 const map_tile* first_tile;
610 const map_tile* end_tile;
611 int tile_step;
612 int x_step;
613 int x_relative_to_screen;
614 int y_relative_to_screen;
615 int steps_taken{0};
616};
617
618#endif // CORSIX_TH_TH_MAP_H_
Definition th_map.h:252
std::vector< std::pair< int, int > > set_parcel_owner(int iParcelId, int iOwner)
Change the owner of a particular parcel.
Definition th_map.cpp:660
~level_map()
Definition th_map.cpp:255
void update_shadows()
Definition th_map.cpp:1451
bool set_size(int iWidth, int iHeight)
Definition th_map.cpp:273
level_map()=default
bool load_from_th_file(const uint8_t *pData, size_t iDataLength, map_load_object_callback_fn fnObjectCallback, void *pCallbackToken)
Definition th_map.cpp:382
int get_parcel_owner(int iParcelId) const
Get the owner of a particular parcel of land.
Definition th_map.cpp:1274
bool are_parcels_adjacent(int iParcel1, int iParcel2)
Query if two parcels are directly connected.
Definition th_map.cpp:799
void set_temperature_display(temperature_theme eTempDisplay)
Definition th_map.cpp:1286
void set_player_count(int count)
Definition th_map.cpp:817
int get_parcel_count() const
Get the number of plots of land in this map.
Definition th_map.h:295
void update_temperatures(uint16_t iAirTemperature, uint16_t iRadiatorTemperature)
Definition th_map.cpp:1346
static void screen_to_world(T &x, T &y)
Convert absolute screen coordinates to world (tile) coordinates.
Definition th_map.h:393
bool is_parcel_purchasable(int iParcelId, int iPlayer)
Query if a given player is in a position to purchase a given parcel.
Definition th_map.cpp:808
static void world_to_screen(T &x, T &y)
Convert world (tile) coordinates to absolute screen coordinates.
Definition th_map.h:385
bool load_blank()
Definition th_map.cpp:347
drawable * hit_test(int iTestX, int iTestY) const
Perform a hit-test against the animations attached to the map.
Definition th_map.cpp:1208
bool get_player_heliport_tile(int iPlayer, int *pX, int *pY) const
Definition th_map.cpp:844
void set_all_wall_draw_flags(uint8_t iFlags)
Set the draw flags on all wall blocks.
Definition th_map.cpp:935
void draw(render_target *pCanvas, int iScreenX, int iScreenY, int iWidth, int iHeight, int iCanvasX, int iCanvasY) const
Draw the map (and any attached animations)
Definition th_map.cpp:1022
int get_tile_owner(const map_tile *pNode) const
Definition th_map.cpp:1269
map_tile * get_tile_unchecked(int iX, int iY)
Definition th_map.cpp:921
void set_player_camera_tile(int iPlayer, int iX, int iY)
Definition th_map.cpp:863
temperature_theme get_temperature_display() const
Definition th_map.h:282
void set_block_sheet(sprite_sheet *pSheet)
Set the sprite sheet to be used for drawing the map.
Definition th_map.cpp:933
uint16_t get_tile_temperature(const map_tile *pNode) const
Definition th_map.cpp:1282
void save(const std::string &filename)
Definition th_map.cpp:531
int get_width() const
Get the map width (in tiles)
Definition th_map.h:289
void set_player_heliport_tile(int iPlayer, int iX, int iY)
Definition th_map.cpp:870
int get_parcel_tile_count(int iParcelId) const
Get the number of tiles inside a given parcel.
Definition th_map.cpp:877
map_tile * get_tile(int iX, int iY)
Definition th_map.cpp:897
void depersist(lua_persist_reader *pReader)
Definition th_map.cpp:1558
const map_tile * get_original_tile(int iX, int iY) const
Definition th_map.cpp:913
void persist(lua_persist_writer *pWriter) const
Definition th_map.cpp:1481
int get_player_count() const
Definition th_map.h:297
void set_overlay(map_overlay *pOverlay, bool bTakeOwnership)
Definition th_map.cpp:265
void update_pathfinding()
Definition th_map.cpp:1402
const map_tile * get_original_tile_unchecked(int iX, int iY) const
Definition th_map.cpp:929
int get_height() const
Get the map height (in tiles)
Definition th_map.h:292
bool get_player_camera_tile(int iPlayer, int *pX, int *pY) const
Definition th_map.cpp:825
Interface used for depersisting Lua objects.
Definition persist_lua.h:107
Interface used for persisting Lua objects.
Definition persist_lua.h:44
Definition th_map_overlays.h:35
Utility class for re-iterating a scanline visited by a map_tile_iterator.
Definition th_map.h:581
int x() const
Definition th_map.h:600
const map_tile * get_next_tile()
Definition th_map.h:602
map_scanline_iterator operator=(const map_scanline_iterator &iterator)
Definition th_map.cpp:1841
map_scanline_iterator & operator++()
Definition th_map.cpp:1832
int y() const
Definition th_map.h:601
map_scanline_iterator()
Definition th_map.cpp:1801
const map_tile * get_tile()
Definition th_map.h:605
const map_tile * operator->() const
Definition th_map.h:599
const map_tile * get_previous_tile()
Definition th_map.h:603
Utility class for iterating over map tiles within a screen rectangle.
Definition th_map.h:493
const level_map * get_map()
Definition th_map.h:533
int tile_x() const
Definition th_map.h:530
bool is_last_on_scanline() const
Returns true if the next tile will be on a different scanline.
Definition th_map.cpp:1796
int tile_y_position_on_screen() const
Definition th_map.h:528
int get_scanline_count()
Definition th_map.h:535
map_tile_iterator()=delete
map_tile_iterator & operator++()
Advances the iterator to the next tile.
Definition th_map.cpp:1731
const map_tile * get_map_tile()
Definition th_map.h:534
int tile_x_position_on_screen() const
Definition th_map.h:524
int get_tile_step()
Definition th_map.h:536
const map_tile * operator->() const
Accessor for the current tile.
Definition th_map.h:520
int tile_y() const
Definition th_map.h:531
Definition th_gfx_sdl.h:247
Sheet of sprites.
Definition th_gfx_sdl.h:504
Definition th_gfx.h:106
Definition th_map.h:118
bool buildable_w
Can build on the west side of the tile.
Definition th_map.h:163
bool can_travel_s
Pathfinding: Can walk to the south.
Definition th_map.h:146
bool buildable_s
Can build on the south side of the tile.
Definition th_map.h:162
bool passable_if_not_for_blueprint
Definition th_map.h:150
bool hospital
World: Tile is inside a hospital building.
Definition th_map.h:148
key
Definition th_map.h:119
bool do_not_idle
World: Humanoids should not idle on tile.
Definition th_map.h:157
bool & operator[](map_tile_flags::key key)
Get/set the flag with the given key.
Definition th_map.cpp:82
bool can_travel_n
Pathfinding: Can walk to the north.
Definition th_map.h:144
bool buildable_n
Can build on the north side of the tile.
Definition th_map.h:160
bool door_north
World: Door on north wall of tile.
Definition th_map.h:155
bool buildable
Player: Can build on this tile.
Definition th_map.h:149
bool tall_north
Shadows: Wall-like object on north wall.
Definition th_map.h:158
bool shadow_half
Rendering: Put block 75 over floor.
Definition th_map.h:152
bool shadow_wall
Rendering: Put block 156 over east wall.
Definition th_map.h:154
bool room
World: Tile is inside a room.
Definition th_map.h:151
bool buildable_e
Can build on the east side of the tile.
Definition th_map.h:161
bool tall_west
Shadows: Wall-like object on west wall.
Definition th_map.h:159
bool can_travel_e
Pathfinding: Can walk to the east.
Definition th_map.h:145
bool can_travel_w
Pathfinding: Can walk to the west.
Definition th_map.h:147
map_tile_flags & operator=(uint32_t raw)
Definition th_map.cpp:52
bool shadow_full
Rendering: Put block 74 over floor.
Definition th_map.h:153
bool door_west
World: Door on west wall of tile.
Definition th_map.h:156
bool passable
Pathfinding: Can walk on this tile.
Definition th_map.h:143
Definition th_map.h:194
uint16_t aiTemperature[2]
Definition th_map.h:226
std::uint8_t raw[raw_length]
raw data from map file for debugging
Definition th_map.h:237
std::list< object_type > objects
objects in this tile
Definition th_map.h:232
link_list entities
Definition th_map.h:199
link_list oEarlyEntities
Linked list for entities rendered in an early (right-to-left) pass.
Definition th_map.h:202
uint16_t iParcelId
Definition th_map.h:216
uint16_t tile_layers[tile_layer::num_tile_layers]
Definition th_map.h:212
map_tile()=default
~map_tile()=default
static constexpr int raw_length
Definition th_map.h:234
uint16_t iRoomId
Rooms have an ID, with room #0 being the corridor (and the outside).
Definition th_map.h:219
map_tile_flags flags
Flags for information and object type.
Definition th_map.h:229
tile_layer
Definition th_map.h:185
@ north_wall
Definition th_map.h:187
@ west_wall
Definition th_map.h:188
@ ground
Definition th_map.h:186
@ num_tile_layers
Number of layers in a tile.
Definition th_map.h:191
@ ui
Definition th_map.h:189
temperature_theme
Definition th_map.h:179
@ multi_colour
Different colours (blue, green, red)
@ red
Default warmth colouring (red gradients)
@ yellow_red
Gradients of yellow, orange, and red.
map_scanline_iterator_direction
Definition th_map.h:477
object_type
Definition th_map.h:46
void(* map_load_object_callback_fn)(void *, int, int, object_type, uint8_t)
Prototype for object callbacks from THMap::loadFromTHFile.
Definition th_map.h:249