mirror of
https://github.com/CorsixTH/CorsixTH.git
synced 2025-07-23 12:23:05 +02:00
Merge pull request #2880 from Alberth289346/refactor-th-map-cpp
Refactor th map cpp
This commit is contained in:
@@ -79,8 +79,8 @@ SOFTWARE.
|
||||
#endif
|
||||
|
||||
/** Standard includes **/
|
||||
#include <cstddef> // IWYU pragma: export
|
||||
#include <cstdint> // IWYU pragma: export
|
||||
#include <cstddef> // IWYU pragma: export
|
||||
#include <cstdint> // IWYU pragma: export
|
||||
|
||||
// We bring in the most common stddef and stdint types to avoid typing
|
||||
// clang-format off
|
||||
|
@@ -259,7 +259,7 @@ int l_map_updateblueprint(lua_State* L) {
|
||||
for (int iY = iOldY; iY < iOldY + iOldH; ++iY) {
|
||||
for (int iX = iOldX; iX < iOldX + iOldW; ++iX) {
|
||||
map_tile* pNode = pMap->get_tile_unchecked(iX, iY);
|
||||
pNode->iBlock[3] = 0;
|
||||
pNode->tile_layers[tile_layer::ui] = 0;
|
||||
pNode->flags.passable |= pNode->flags.passable_if_not_for_blueprint;
|
||||
pNode->flags.passable_if_not_for_blueprint = false;
|
||||
}
|
||||
@@ -270,9 +270,9 @@ int l_map_updateblueprint(lua_State* L) {
|
||||
for (int iX = iNewX; iX < iNewX + iNewW; ++iX) {
|
||||
map_tile* pNode = pMap->get_tile_unchecked(iX, iY);
|
||||
if (is_valid(entire_invalid, pNode, pMap, player_id)) {
|
||||
pNode->iBlock[3] = iFloorTileGood;
|
||||
pNode->tile_layers[tile_layer::ui] = iFloorTileGood;
|
||||
} else {
|
||||
pNode->iBlock[3] = iFloorTileBad;
|
||||
pNode->tile_layers[tile_layer::ui] = iFloorTileBad;
|
||||
valid = false;
|
||||
}
|
||||
pNode->flags.passable_if_not_for_blueprint = pNode->flags.passable;
|
||||
@@ -285,20 +285,20 @@ int l_map_updateblueprint(lua_State* L) {
|
||||
int iCenterY = iNewY + (iNewH - 2) / 2;
|
||||
|
||||
map_tile* pNode = pMap->get_tile_unchecked(iCenterX, iCenterY);
|
||||
if (pNode->iBlock[3] == iFloorTileGood)
|
||||
pNode->iBlock[3] = iFloorTileGoodCenter + 2;
|
||||
if (pNode->tile_layers[tile_layer::ui] == iFloorTileGood)
|
||||
pNode->tile_layers[tile_layer::ui] = iFloorTileGoodCenter + 2;
|
||||
|
||||
pNode = pMap->get_tile_unchecked(iCenterX + 1, iCenterY);
|
||||
if (pNode->iBlock[3] == iFloorTileGood)
|
||||
pNode->iBlock[3] = iFloorTileGoodCenter + 1;
|
||||
if (pNode->tile_layers[tile_layer::ui] == iFloorTileGood)
|
||||
pNode->tile_layers[tile_layer::ui] = iFloorTileGoodCenter + 1;
|
||||
|
||||
pNode = pMap->get_tile_unchecked(iCenterX, iCenterY + 1);
|
||||
if (pNode->iBlock[3] == iFloorTileGood)
|
||||
pNode->iBlock[3] = iFloorTileGoodCenter + 0;
|
||||
if (pNode->tile_layers[tile_layer::ui] == iFloorTileGood)
|
||||
pNode->tile_layers[tile_layer::ui] = iFloorTileGoodCenter + 0;
|
||||
|
||||
pNode = pMap->get_tile_unchecked(iCenterX + 1, iCenterY + 1);
|
||||
if (pNode->iBlock[3] == iFloorTileGood)
|
||||
pNode->iBlock[3] = iFloorTileGoodCenter + 3;
|
||||
if (pNode->tile_layers[tile_layer::ui] == iFloorTileGood)
|
||||
pNode->tile_layers[tile_layer::ui] = iFloorTileGoodCenter + 3;
|
||||
}
|
||||
|
||||
// Set wall animations
|
||||
@@ -467,16 +467,16 @@ int l_map_getcell(lua_State* L) {
|
||||
iX + 1, iY + 1));
|
||||
}
|
||||
if (lua_isnoneornil(L, 4)) {
|
||||
lua_pushinteger(L, pNode->iBlock[0]);
|
||||
lua_pushinteger(L, pNode->iBlock[1]);
|
||||
lua_pushinteger(L, pNode->iBlock[2]);
|
||||
lua_pushinteger(L, pNode->iBlock[3]);
|
||||
lua_pushinteger(L, pNode->tile_layers[tile_layer::ground]);
|
||||
lua_pushinteger(L, pNode->tile_layers[tile_layer::north_wall]);
|
||||
lua_pushinteger(L, pNode->tile_layers[tile_layer::west_wall]);
|
||||
lua_pushinteger(L, pNode->tile_layers[tile_layer::ui]);
|
||||
return 4;
|
||||
} else {
|
||||
lua_Integer iLayer = luaL_checkinteger(L, 4) - 1;
|
||||
if (iLayer < 0 || iLayer >= 4)
|
||||
return luaL_argerror(L, 4, "Layer index is out of bounds (1-4)");
|
||||
lua_pushinteger(L, pNode->iBlock[iLayer]);
|
||||
if (iLayer < tile_layer::ground || iLayer >= tile_layer::num_tile_layers)
|
||||
return luaL_argerror(L, 4, "Tile layer index is out of bounds (1-4)");
|
||||
lua_pushinteger(L, pNode->tile_layers[iLayer]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -658,16 +658,20 @@ int l_map_setcell(lua_State* L) {
|
||||
return luaL_argerror(L, 2, "Map coordinates out of bounds");
|
||||
}
|
||||
if (lua_gettop(L) >= 7) {
|
||||
pNode->iBlock[0] = (uint16_t)luaL_checkinteger(L, 4);
|
||||
pNode->iBlock[1] = (uint16_t)luaL_checkinteger(L, 5);
|
||||
pNode->iBlock[2] = (uint16_t)luaL_checkinteger(L, 6);
|
||||
pNode->iBlock[3] = (uint16_t)luaL_checkinteger(L, 7);
|
||||
pNode->tile_layers[tile_layer::ground] =
|
||||
static_cast<uint16_t>(luaL_checkinteger(L, 4));
|
||||
pNode->tile_layers[tile_layer::north_wall] =
|
||||
static_cast<uint16_t>(luaL_checkinteger(L, 5));
|
||||
pNode->tile_layers[tile_layer::west_wall] =
|
||||
static_cast<uint16_t>(luaL_checkinteger(L, 6));
|
||||
pNode->tile_layers[tile_layer::ui] =
|
||||
static_cast<uint16_t>(luaL_checkinteger(L, 7));
|
||||
} else {
|
||||
lua_Integer iLayer = luaL_checkinteger(L, 4) - 1;
|
||||
if (iLayer < 0 || iLayer >= 4)
|
||||
return luaL_argerror(L, 4, "Layer index is out of bounds (1-4)");
|
||||
uint16_t iBlock = static_cast<uint16_t>(luaL_checkinteger(L, 5));
|
||||
pNode->iBlock[iLayer] = iBlock;
|
||||
lua_Integer layer = luaL_checkinteger(L, 4) - 1;
|
||||
if (layer < tile_layer::ground || layer >= tile_layer::num_tile_layers)
|
||||
return luaL_argerror(L, 4, "Tile layer index is out of bounds (1-4)");
|
||||
uint16_t blk = static_cast<uint16_t>(luaL_checkinteger(L, 5));
|
||||
pNode->tile_layers[layer] = blk;
|
||||
}
|
||||
|
||||
lua_settop(L, 1);
|
||||
@@ -705,8 +709,8 @@ int l_map_mark_room(lua_State* L) {
|
||||
for (int iY = iY_; iY < iY_ + iH; ++iY) {
|
||||
for (int iX = iX_; iX < iX_ + iW; ++iX) {
|
||||
map_tile* pNode = pMap->get_tile_unchecked(iX, iY);
|
||||
pNode->iBlock[0] = iTile;
|
||||
pNode->iBlock[3] = 0;
|
||||
pNode->tile_layers[tile_layer::ground] = iTile;
|
||||
pNode->tile_layers[tile_layer::ui] = 0;
|
||||
pNode->flags.room = true;
|
||||
pNode->flags.passable |= pNode->flags.passable_if_not_for_blueprint;
|
||||
pNode->flags.passable_if_not_for_blueprint = false;
|
||||
@@ -735,7 +739,9 @@ int l_map_unmark_room(lua_State* L) {
|
||||
for (int iY = iY_; iY < iY_ + iH; ++iY) {
|
||||
for (int iX = iX_; iX < iX_ + iW; ++iX) {
|
||||
map_tile* pNode = pMap->get_tile_unchecked(iX, iY);
|
||||
pNode->iBlock[0] = pMap->get_original_tile_unchecked(iX, iY)->iBlock[0];
|
||||
pNode->tile_layers[tile_layer::ground] =
|
||||
pMap->get_original_tile_unchecked(iX, iY)
|
||||
->tile_layers[tile_layer::ground];
|
||||
pNode->flags.room = false;
|
||||
pNode->iRoomId = 0;
|
||||
}
|
||||
|
@@ -48,13 +48,13 @@ uint8_t range_scale(uint16_t low, uint16_t high, uint16_t val, uint16_t start,
|
||||
}
|
||||
|
||||
inline bool is_wall(uint16_t blk) {
|
||||
return ((82 <= ((blk) & 0xFF)) && (((blk) & 0xFF) <= 164));
|
||||
return 82 <= (blk & 0xFF) && (blk & 0xFF) <= 164;
|
||||
}
|
||||
|
||||
inline bool is_wall_drawn(const level_map& map, const map_tile& node,
|
||||
const map_tile& original_node, size_t n) {
|
||||
return map.get_tile_owner(&node) != 0 ? is_wall(node.iBlock[n])
|
||||
: is_wall(original_node.iBlock[n]);
|
||||
const map_tile& original_node, tile_layer n) {
|
||||
return map.get_tile_owner(&node) != 0 ? is_wall(node.tile_layers[n])
|
||||
: is_wall(original_node.tile_layers[n]);
|
||||
}
|
||||
|
||||
int l_town_map_draw(lua_State* L) {
|
||||
@@ -133,7 +133,8 @@ int l_town_map_draw(lua_State* L) {
|
||||
pCanvas->fill_rect(iColour, iCanvasX, iCanvasY, 3, 3);
|
||||
}
|
||||
dont_paint_tile:
|
||||
if (is_wall_drawn(*pMap, *pNode, *pOriginalNode, 1)) {
|
||||
if (is_wall_drawn(*pMap, *pNode, *pOriginalNode,
|
||||
tile_layer::north_wall)) {
|
||||
pCanvas->fill_rect(iColourWall, iCanvasX, iCanvasY, 3, 1);
|
||||
|
||||
// Draw entrance door
|
||||
@@ -146,7 +147,7 @@ int l_town_map_draw(lua_State* L) {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_wall_drawn(*pMap, *pNode, *pOriginalNode, 2)) {
|
||||
if (is_wall_drawn(*pMap, *pNode, *pOriginalNode, tile_layer::west_wall)) {
|
||||
pCanvas->fill_rect(iColourWall, iCanvasX, iCanvasY, 1, 3);
|
||||
|
||||
// Draw entrance door
|
||||
|
@@ -248,17 +248,17 @@ map_tile_flags::operator uint32_t() const {
|
||||
}
|
||||
|
||||
map_tile::map_tile() : iParcelId(0), iRoomId(0), flags({}), objects() {
|
||||
iBlock[0] = 0;
|
||||
iBlock[1] = 0;
|
||||
iBlock[2] = 0;
|
||||
iBlock[3] = 0;
|
||||
tile_layers[tile_layer::ground] = 0;
|
||||
tile_layers[tile_layer::north_wall] = 0;
|
||||
tile_layers[tile_layer::west_wall] = 0;
|
||||
tile_layers[tile_layer::ui] = 0;
|
||||
aiTemperature[0] = aiTemperature[1] = 8192;
|
||||
}
|
||||
|
||||
level_map::level_map()
|
||||
: cells(nullptr),
|
||||
original_cells(nullptr),
|
||||
blocks(nullptr),
|
||||
wall_blocks(nullptr),
|
||||
overlay(nullptr),
|
||||
owns_overlay(false),
|
||||
plot_owner(nullptr),
|
||||
@@ -381,7 +381,8 @@ bool level_map::load_blank() {
|
||||
map_tile* pOriginalNode = original_cells;
|
||||
for (int iY = 0; iY < height; ++iY) {
|
||||
for (int iX = 0; iX < width; ++iX, ++pNode, ++pOriginalNode) {
|
||||
pNode->iBlock[0] = static_cast<uint16_t>(2 + (iX % 2));
|
||||
pNode->tile_layers[tile_layer::ground] =
|
||||
static_cast<uint16_t>(2 + (iX % 2));
|
||||
}
|
||||
}
|
||||
plot_owner = new int[1];
|
||||
@@ -450,28 +451,29 @@ bool level_map::load_from_th_file(const uint8_t* pData, size_t iDataLength,
|
||||
pNode->flags.can_travel_s = false;
|
||||
}
|
||||
|
||||
pNode->iBlock[0] = iBaseTile;
|
||||
pNode->tile_layers[tile_layer::ground] = iBaseTile;
|
||||
if (pData[3] == 0 || is_divider_wall(pData[3])) {
|
||||
// Tiles 71, 72 and 73 (pond foliage) are used as floor tiles,
|
||||
// but are too tall to be floor tiles, so move them to a wall,
|
||||
// and replace the floor with something similar (pond base).
|
||||
if (71 <= iBaseTile && iBaseTile <= 73) {
|
||||
pNode->iBlock[1] = iBaseTile;
|
||||
pNode->iBlock[0] = 69;
|
||||
pNode->tile_layers[tile_layer::north_wall] = iBaseTile;
|
||||
pNode->tile_layers[tile_layer::ground] = 69;
|
||||
} else {
|
||||
pNode->iBlock[1] = 0;
|
||||
pNode->tile_layers[tile_layer::north_wall] = 0;
|
||||
}
|
||||
} else {
|
||||
pNode->iBlock[1] = gs_iTHMapBlockLUT[pData[3]];
|
||||
pNode->tile_layers[tile_layer::north_wall] =
|
||||
gs_iTHMapBlockLUT[pData[3]];
|
||||
pNode->flags.can_travel_n = false;
|
||||
if (iY != 0) {
|
||||
pNode[-this->width].flags.can_travel_s = false;
|
||||
}
|
||||
}
|
||||
if (pData[4] == 0 || is_divider_wall(pData[4])) {
|
||||
pNode->iBlock[2] = 0;
|
||||
pNode->tile_layers[tile_layer::west_wall] = 0;
|
||||
} else {
|
||||
pNode->iBlock[2] = gs_iTHMapBlockLUT[pData[4]];
|
||||
pNode->tile_layers[tile_layer::west_wall] = gs_iTHMapBlockLUT[pData[4]];
|
||||
pNode->flags.can_travel_w = false;
|
||||
if (iX != 0) {
|
||||
pNode[-1].flags.can_travel_e = false;
|
||||
@@ -508,10 +510,12 @@ bool level_map::load_from_th_file(const uint8_t* pData, size_t iDataLength,
|
||||
|
||||
*pOriginalNode = *pNode;
|
||||
if (is_divider_wall(pData[3])) {
|
||||
pOriginalNode->iBlock[1] = gs_iTHMapBlockLUT[pData[3]];
|
||||
pOriginalNode->tile_layers[tile_layer::north_wall] =
|
||||
gs_iTHMapBlockLUT[pData[3]];
|
||||
}
|
||||
if (is_divider_wall(pData[4])) {
|
||||
pOriginalNode->iBlock[2] = gs_iTHMapBlockLUT[pData[4]];
|
||||
pOriginalNode->tile_layers[tile_layer::west_wall] =
|
||||
gs_iTHMapBlockLUT[pData[4]];
|
||||
}
|
||||
|
||||
if (pData[1] != 0 && fnObjectCallback != nullptr) {
|
||||
@@ -568,9 +572,12 @@ void level_map::save(const std::string& filename) {
|
||||
: pNode->objects.front());
|
||||
|
||||
// Blocks
|
||||
aBuffer[iBufferNext++] = aReverseBlockLUT[pNode->iBlock[0] & 0xFF];
|
||||
aBuffer[iBufferNext++] = aReverseBlockLUT[pNode->iBlock[1] & 0xFF];
|
||||
aBuffer[iBufferNext++] = aReverseBlockLUT[pNode->iBlock[2] & 0xFF];
|
||||
aBuffer[iBufferNext++] =
|
||||
aReverseBlockLUT[pNode->tile_layers[tile_layer::ground] & 0xFF];
|
||||
aBuffer[iBufferNext++] =
|
||||
aReverseBlockLUT[pNode->tile_layers[tile_layer::north_wall] & 0xFF];
|
||||
aBuffer[iBufferNext++] =
|
||||
aReverseBlockLUT[pNode->tile_layers[tile_layer::west_wall] & 0xFF];
|
||||
|
||||
// Flags (TODO: Set a few more flag bits?)
|
||||
uint8_t iFlags = 63;
|
||||
@@ -650,17 +657,17 @@ namespace {
|
||||
*/
|
||||
bool addRemoveDividerWalls(level_map* pMap, map_tile* pNode,
|
||||
const map_tile* pOriginalNode, int iXY, int delta,
|
||||
int block, int iParcelId) {
|
||||
tile_layer layer, int iParcelId) {
|
||||
if (iXY > 0 && pOriginalNode->flags.hospital &&
|
||||
pOriginalNode[-delta].flags.hospital &&
|
||||
pNode->iParcelId != pNode[-delta].iParcelId) {
|
||||
int iOwner = pMap->get_parcel_owner(pNode->iParcelId);
|
||||
int iOtherOwner = pMap->get_parcel_owner(pNode[-delta].iParcelId);
|
||||
if (iOwner != iOtherOwner) {
|
||||
pNode->iBlock[block] = block + (iOwner ? 143 : 141);
|
||||
pNode->tile_layers[layer] = layer + (iOwner ? 143 : 141);
|
||||
} else if (pNode->iParcelId == iParcelId ||
|
||||
pNode[-delta].iParcelId == iParcelId) {
|
||||
pNode->iBlock[block] = 0;
|
||||
pNode->tile_layers[layer] = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -684,31 +691,36 @@ std::vector<std::pair<int, int>> level_map::set_parcel_owner(int iParcelId,
|
||||
for (int iX = 0; iX < this->width; ++iX, ++pNode, ++pOriginalNode) {
|
||||
if (pNode->iParcelId == iParcelId) {
|
||||
if (iOwner != 0) {
|
||||
pNode->iBlock[0] = pOriginalNode->iBlock[0];
|
||||
pNode->iBlock[1] = pOriginalNode->iBlock[1];
|
||||
pNode->iBlock[2] = pOriginalNode->iBlock[2];
|
||||
pNode->tile_layers[tile_layer::ground] =
|
||||
pOriginalNode->tile_layers[tile_layer::ground];
|
||||
pNode->tile_layers[tile_layer::north_wall] =
|
||||
pOriginalNode->tile_layers[tile_layer::north_wall];
|
||||
pNode->tile_layers[tile_layer::west_wall] =
|
||||
pOriginalNode->tile_layers[tile_layer::west_wall];
|
||||
pNode->flags = pOriginalNode->flags;
|
||||
} else {
|
||||
// Nicely mown grass pattern
|
||||
pNode->iBlock[0] = static_cast<uint16_t>(((iX & 1) << 1) + 1);
|
||||
pNode->tile_layers[tile_layer::ground] =
|
||||
static_cast<uint16_t>(((iX & 1) << 1) + 1);
|
||||
|
||||
pNode->iBlock[1] = 0;
|
||||
pNode->iBlock[2] = 0;
|
||||
pNode->tile_layers[tile_layer::north_wall] = 0;
|
||||
pNode->tile_layers[tile_layer::west_wall] = 0;
|
||||
pNode->flags = {};
|
||||
|
||||
// Random decoration
|
||||
if (((iX | iY) & 0x7) == 0) {
|
||||
int iWhich = (iX ^ iY) % 9;
|
||||
pNode->iBlock[1] = static_cast<uint16_t>(192 + iWhich);
|
||||
pNode->tile_layers[tile_layer::north_wall] =
|
||||
static_cast<uint16_t>(192 + iWhich);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (addRemoveDividerWalls(this, pNode, pOriginalNode, iX, 1, 2,
|
||||
iParcelId)) {
|
||||
if (addRemoveDividerWalls(this, pNode, pOriginalNode, iX, 1,
|
||||
tile_layer::west_wall, iParcelId)) {
|
||||
vSplitTiles.push_back(std::make_pair(iX, iY));
|
||||
}
|
||||
if (addRemoveDividerWalls(this, pNode, pOriginalNode, iY, this->width, 1,
|
||||
iParcelId)) {
|
||||
if (addRemoveDividerWalls(this, pNode, pOriginalNode, iY, this->width,
|
||||
tile_layer::north_wall, iParcelId)) {
|
||||
vSplitTiles.push_back(std::make_pair(iX, iY));
|
||||
}
|
||||
}
|
||||
@@ -937,16 +949,16 @@ const map_tile* level_map::get_original_tile_unchecked(int iX, int iY) const {
|
||||
return original_cells + iY * width + iX;
|
||||
}
|
||||
|
||||
void level_map::set_block_sheet(sprite_sheet* pSheet) { blocks = pSheet; }
|
||||
void level_map::set_block_sheet(sprite_sheet* pSheet) { wall_blocks = pSheet; }
|
||||
|
||||
void level_map::set_all_wall_draw_flags(uint8_t iFlags) {
|
||||
uint16_t iBlockOr = static_cast<uint16_t>(iFlags << 8);
|
||||
uint16_t draw_flags = static_cast<uint16_t>(iFlags << 8);
|
||||
map_tile* pNode = cells;
|
||||
for (int i = 0; i < width * height; ++i, ++pNode) {
|
||||
pNode->iBlock[1] =
|
||||
static_cast<uint16_t>((pNode->iBlock[1] & 0xFF) | iBlockOr);
|
||||
pNode->iBlock[2] =
|
||||
static_cast<uint16_t>((pNode->iBlock[2] & 0xFF) | iBlockOr);
|
||||
pNode->tile_layers[tile_layer::north_wall] = static_cast<uint16_t>(
|
||||
(pNode->tile_layers[tile_layer::north_wall] & 0xFF) | draw_flags);
|
||||
pNode->tile_layers[tile_layer::west_wall] = static_cast<uint16_t>(
|
||||
(pNode->tile_layers[tile_layer::west_wall] & 0xFF) | draw_flags);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -972,7 +984,7 @@ void level_map::draw(render_target* pCanvas, int iScreenX, int iScreenY,
|
||||
2) For each tile, left to right, the west wall, then the late entities
|
||||
*/
|
||||
|
||||
if (blocks == nullptr || cells == nullptr) {
|
||||
if (wall_blocks == nullptr || cells == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -987,26 +999,26 @@ void level_map::draw(render_target* pCanvas, int iScreenX, int iScreenY,
|
||||
itrNode1; ++itrNode1) {
|
||||
// First, draw the floor tile as it should be below everything else.
|
||||
int iH = 32;
|
||||
unsigned int iBlock = itrNode1->iBlock[0];
|
||||
blocks->get_sprite_size(iBlock & 0xFF, nullptr, &iH);
|
||||
blocks->draw_sprite(
|
||||
pCanvas, iBlock & 0xFF,
|
||||
uint16_t layer = itrNode1->tile_layers[tile_layer::ground];
|
||||
wall_blocks->get_sprite_size(layer & 0xFF, nullptr, &iH);
|
||||
wall_blocks->draw_sprite(
|
||||
pCanvas, layer & 0xFF,
|
||||
itrNode1.tile_x_position_on_screen() + iCanvasX - 32,
|
||||
itrNode1.tile_y_position_on_screen() + iCanvasY - iH + 32,
|
||||
(iBlock >> 8) | thdf_nearest);
|
||||
(layer >> 8) | thdf_nearest);
|
||||
|
||||
// Draw floor shadows immediately after floor tiles ensuring that all
|
||||
// shadow pixels are drawn onto freshly drawn opaque floor tile pixels.
|
||||
if (itrNode1->flags.shadow_full) {
|
||||
blocks->draw_sprite(pCanvas, 74,
|
||||
itrNode1.tile_x_position_on_screen() + iCanvasX - 32,
|
||||
itrNode1.tile_y_position_on_screen() + iCanvasY,
|
||||
thdf_alpha_75 | thdf_nearest);
|
||||
wall_blocks->draw_sprite(
|
||||
pCanvas, 74, itrNode1.tile_x_position_on_screen() + iCanvasX - 32,
|
||||
itrNode1.tile_y_position_on_screen() + iCanvasY,
|
||||
thdf_alpha_75 | thdf_nearest);
|
||||
} else if (itrNode1->flags.shadow_half) {
|
||||
blocks->draw_sprite(pCanvas, 75,
|
||||
itrNode1.tile_x_position_on_screen() + iCanvasX - 32,
|
||||
itrNode1.tile_y_position_on_screen() + iCanvasY,
|
||||
thdf_alpha_75 | thdf_nearest);
|
||||
wall_blocks->draw_sprite(
|
||||
pCanvas, 75, itrNode1.tile_x_position_on_screen() + iCanvasX - 32,
|
||||
itrNode1.tile_y_position_on_screen() + iCanvasY,
|
||||
thdf_alpha_75 | thdf_nearest);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1023,12 +1035,12 @@ void level_map::draw(render_target* pCanvas, int iScreenX, int iScreenY,
|
||||
iCanvasY);
|
||||
itrNode; ++itrNode) {
|
||||
int iH;
|
||||
unsigned int iBlock = itrNode->iBlock[1];
|
||||
if (iBlock != 0 && blocks->get_sprite_size(iBlock & 0xFF, nullptr, &iH) &&
|
||||
iH > 0) {
|
||||
blocks->draw_sprite(pCanvas, iBlock & 0xFF, itrNode.x() - 32,
|
||||
itrNode.y() - iH + 32,
|
||||
(iBlock >> 8) | thdf_nearest);
|
||||
uint16_t layer = itrNode->tile_layers[tile_layer::north_wall];
|
||||
if (layer != 0 &&
|
||||
wall_blocks->get_sprite_size(layer & 0xFF, nullptr, &iH) && iH > 0) {
|
||||
wall_blocks->draw_sprite(pCanvas, layer & 0xFF, itrNode.x() - 32,
|
||||
itrNode.y() - iH + 32,
|
||||
(layer >> 8) | thdf_nearest);
|
||||
if (itrNode->flags.shadow_wall) {
|
||||
clip_rect rcNewClip;
|
||||
rcNewClip.x = static_cast<clip_rect::x_y_type>(itrNode.x() - 32);
|
||||
@@ -1037,8 +1049,9 @@ void level_map::draw(render_target* pCanvas, int iScreenX, int iScreenY,
|
||||
rcNewClip.w = static_cast<clip_rect::w_h_type>(64);
|
||||
rcNewClip.h = static_cast<clip_rect::w_h_type>(86 - 4);
|
||||
render_target::scoped_clip clip(pCanvas, &rcNewClip);
|
||||
blocks->draw_sprite(pCanvas, 156, itrNode.x() - 32, itrNode.y() - 56,
|
||||
thdf_alpha_75 | thdf_nearest);
|
||||
wall_blocks->draw_sprite(pCanvas, 156, itrNode.x() - 32,
|
||||
itrNode.y() - 56,
|
||||
thdf_alpha_75 | thdf_nearest);
|
||||
}
|
||||
}
|
||||
drawable* pItem = static_cast<drawable*>(itrNode->oEarlyEntities.next);
|
||||
@@ -1065,23 +1078,23 @@ void level_map::draw(render_target* pCanvas, int iScreenX, int iScreenY,
|
||||
for (; itrNode; ++itrNode) {
|
||||
bool bNeedsRedraw = false;
|
||||
int iH;
|
||||
unsigned int iBlock = itrNode->iBlock[2];
|
||||
if (iBlock != 0 && blocks->get_sprite_size(iBlock & 0xFF, nullptr, &iH) &&
|
||||
iH > 0) {
|
||||
blocks->draw_sprite(pCanvas, iBlock & 0xFF, itrNode.x() - 32,
|
||||
itrNode.y() - iH + 32,
|
||||
(iBlock >> 8) | thdf_nearest);
|
||||
uint16_t layer = itrNode->tile_layers[tile_layer::west_wall];
|
||||
if (layer != 0 &&
|
||||
wall_blocks->get_sprite_size(layer & 0xFF, nullptr, &iH) && iH > 0) {
|
||||
wall_blocks->draw_sprite(pCanvas, layer & 0xFF, itrNode.x() - 32,
|
||||
itrNode.y() - iH + 32,
|
||||
(layer >> 8) | thdf_nearest);
|
||||
}
|
||||
iBlock = itrNode->iBlock[3];
|
||||
if (iBlock != 0 && blocks->get_sprite_size(iBlock & 0xFF, nullptr, &iH) &&
|
||||
iH > 0) {
|
||||
blocks->draw_sprite(pCanvas, iBlock & 0xFF, itrNode.x() - 32,
|
||||
itrNode.y() - iH + 32,
|
||||
(iBlock >> 8) | thdf_nearest);
|
||||
layer = itrNode->tile_layers[tile_layer::ui];
|
||||
if (layer != 0 &&
|
||||
wall_blocks->get_sprite_size(layer & 0xFF, nullptr, &iH) && iH > 0) {
|
||||
wall_blocks->draw_sprite(pCanvas, layer & 0xFF, itrNode.x() - 32,
|
||||
itrNode.y() - iH + 32,
|
||||
(layer >> 8) | thdf_nearest);
|
||||
}
|
||||
iBlock = itrNode->iBlock[1];
|
||||
if (iBlock != 0 && blocks->get_sprite_size(iBlock & 0xFF, nullptr, &iH) &&
|
||||
iH > 0) {
|
||||
layer = itrNode->tile_layers[tile_layer::north_wall];
|
||||
if (layer != 0 &&
|
||||
wall_blocks->get_sprite_size(layer & 0xFF, nullptr, &iH) && iH > 0) {
|
||||
bNeedsRedraw = true;
|
||||
}
|
||||
if (itrNode->oEarlyEntities.next) {
|
||||
@@ -1140,12 +1153,14 @@ void level_map::draw(render_target* pCanvas, int iScreenX, int iScreenY,
|
||||
// north side or a wall to the north redraw that tile
|
||||
if (bTileNeedsRedraw) {
|
||||
// redraw the north wall
|
||||
unsigned int iBlock = itrNode.get_previous_tile()->iBlock[1];
|
||||
if (iBlock != 0 &&
|
||||
blocks->get_sprite_size(iBlock & 0xFF, nullptr, &iH) && iH > 0) {
|
||||
blocks->draw_sprite(pCanvas, iBlock & 0xFF, itrNode.x() - 96,
|
||||
itrNode.y() - iH + 32,
|
||||
(iBlock >> 8) | thdf_nearest);
|
||||
uint16_t layer =
|
||||
itrNode.get_previous_tile()->tile_layers[tile_layer::north_wall];
|
||||
if (layer != 0 &&
|
||||
wall_blocks->get_sprite_size(layer & 0xFF, nullptr, &iH) &&
|
||||
iH > 0) {
|
||||
wall_blocks->draw_sprite(pCanvas, layer & 0xFF, itrNode.x() - 96,
|
||||
itrNode.y() - iH + 32,
|
||||
(layer >> 8) | thdf_nearest);
|
||||
if (itrNode.get_previous_tile()->flags.shadow_wall) {
|
||||
clip_rect rcNewClip;
|
||||
rcNewClip.x = static_cast<clip_rect::x_y_type>(itrNode.x() - 96);
|
||||
@@ -1154,9 +1169,9 @@ void level_map::draw(render_target* pCanvas, int iScreenX, int iScreenY,
|
||||
rcNewClip.w = static_cast<clip_rect::w_h_type>(64);
|
||||
rcNewClip.h = static_cast<clip_rect::w_h_type>(86 - 4);
|
||||
render_target::scoped_clip clip(pCanvas, &rcNewClip);
|
||||
blocks->draw_sprite(pCanvas, 156, itrNode.x() - 96,
|
||||
itrNode.y() - 56,
|
||||
thdf_alpha_75 | thdf_nearest);
|
||||
wall_blocks->draw_sprite(pCanvas, 156, itrNode.x() - 96,
|
||||
itrNode.y() - 56,
|
||||
thdf_alpha_75 | thdf_nearest);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1198,7 +1213,7 @@ drawable* level_map::hit_test(int iTestX, int iTestY) const {
|
||||
// This function needs to hitTest each drawable object, in the reverse
|
||||
// order to that in which they would be drawn.
|
||||
|
||||
if (blocks == nullptr || cells == nullptr) {
|
||||
if (wall_blocks == nullptr || cells == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -1408,13 +1423,13 @@ void level_map::update_pathfinding() {
|
||||
pNode->flags.can_travel_s = false;
|
||||
}
|
||||
|
||||
if (pNode->iBlock[1] & 0xFF) {
|
||||
if (pNode->tile_layers[tile_layer::north_wall] & 0xFF) {
|
||||
pNode->flags.can_travel_n = false;
|
||||
if (iY != 0) {
|
||||
pNode[-this->width].flags.can_travel_s = false;
|
||||
}
|
||||
}
|
||||
if (pNode->iBlock[2] & 0xFF) {
|
||||
if (pNode->tile_layers[tile_layer::west_wall] & 0xFF) {
|
||||
pNode->flags.can_travel_w = false;
|
||||
if (iX != 0) {
|
||||
pNode[-1].flags.can_travel_e = false;
|
||||
@@ -1429,9 +1444,9 @@ namespace {
|
||||
//! For shadow casting, a tile is considered to have a wall on a direction
|
||||
//! if it has a door in that direction, or the block is from the hardcoded
|
||||
//! range of wall-like blocks.
|
||||
bool is_wall(map_tile* tile, size_t block, bool flag) {
|
||||
return flag || (82 <= (tile->iBlock[block] & 0xFF) &&
|
||||
(tile->iBlock[block] & 0xFF) <= 164);
|
||||
bool is_wall(map_tile* tile, tile_layer layer, bool flag) {
|
||||
return flag || (82 <= (tile->tile_layers[layer] & 0xFF) &&
|
||||
(tile->tile_layers[layer] & 0xFF) <= 164);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -1443,14 +1458,15 @@ void level_map::update_shadows() {
|
||||
pNode->flags.shadow_full = false;
|
||||
pNode->flags.shadow_half = false;
|
||||
pNode->flags.shadow_wall = false;
|
||||
if (is_wall(pNode, 2, pNode->flags.tall_west)) {
|
||||
if (is_wall(pNode, tile_layer::west_wall, pNode->flags.tall_west)) {
|
||||
pNode->flags.shadow_half = true;
|
||||
if (is_wall(pNode, 1, pNode->flags.tall_north)) {
|
||||
if (is_wall(pNode, tile_layer::north_wall, pNode->flags.tall_north)) {
|
||||
pNode->flags.shadow_wall = true;
|
||||
} else if (iY != 0) {
|
||||
map_tile* pNeighbour = pNode - this->width;
|
||||
pNeighbour->flags.shadow_full = true;
|
||||
if (iX != 0 && !is_wall(pNeighbour, 2, pNode->flags.tall_west)) {
|
||||
if (iX != 0 && !is_wall(pNeighbour, tile_layer::west_wall,
|
||||
pNode->flags.tall_west)) {
|
||||
// Wrap the shadow around a corner (no need to continue
|
||||
// all the way along the wall, as the shadow would be
|
||||
// occluded by the wall. If Debug->Transparent Walls is
|
||||
@@ -1491,10 +1507,10 @@ void level_map::persist(lua_persist_writer* pWriter) const {
|
||||
oEncoder.initialise(6);
|
||||
for (map_tile *pNode = cells, *pLimitNode = cells + width * height;
|
||||
pNode != pLimitNode; ++pNode) {
|
||||
oEncoder.write(pNode->iBlock[0]);
|
||||
oEncoder.write(pNode->iBlock[1]);
|
||||
oEncoder.write(pNode->iBlock[2]);
|
||||
oEncoder.write(pNode->iBlock[3]);
|
||||
oEncoder.write(pNode->tile_layers[tile_layer::ground]);
|
||||
oEncoder.write(pNode->tile_layers[tile_layer::north_wall]);
|
||||
oEncoder.write(pNode->tile_layers[tile_layer::west_wall]);
|
||||
oEncoder.write(pNode->tile_layers[tile_layer::ui]);
|
||||
oEncoder.write(pNode->iParcelId);
|
||||
oEncoder.write(pNode->iRoomId);
|
||||
// Flags include THOB values, and other things which do not work
|
||||
@@ -1520,9 +1536,9 @@ void level_map::persist(lua_persist_writer* pWriter) const {
|
||||
for (map_tile *pNode = original_cells,
|
||||
*pLimitNode = original_cells + width * height;
|
||||
pNode != pLimitNode; ++pNode) {
|
||||
oEncoder.write(pNode->iBlock[0]);
|
||||
oEncoder.write(pNode->iBlock[1]);
|
||||
oEncoder.write(pNode->iBlock[2]);
|
||||
oEncoder.write(pNode->tile_layers[tile_layer::ground]);
|
||||
oEncoder.write(pNode->tile_layers[tile_layer::north_wall]);
|
||||
oEncoder.write(pNode->tile_layers[tile_layer::west_wall]);
|
||||
oEncoder.write(pNode->iParcelId);
|
||||
oEncoder.write(static_cast<uint32_t>(pNode->flags));
|
||||
}
|
||||
@@ -1626,10 +1642,13 @@ void level_map::depersist(lua_persist_reader* pReader) {
|
||||
oDecoder.initialise(6, pReader);
|
||||
for (map_tile *pNode = cells, *pLimitNode = cells + width * height;
|
||||
pNode != pLimitNode; ++pNode) {
|
||||
pNode->iBlock[0] = static_cast<uint16_t>(oDecoder.read());
|
||||
pNode->iBlock[1] = static_cast<uint16_t>(oDecoder.read());
|
||||
pNode->iBlock[2] = static_cast<uint16_t>(oDecoder.read());
|
||||
pNode->iBlock[3] = static_cast<uint16_t>(oDecoder.read());
|
||||
pNode->tile_layers[tile_layer::ground] =
|
||||
static_cast<uint16_t>(oDecoder.read());
|
||||
pNode->tile_layers[tile_layer::north_wall] =
|
||||
static_cast<uint16_t>(oDecoder.read());
|
||||
pNode->tile_layers[tile_layer::west_wall] =
|
||||
static_cast<uint16_t>(oDecoder.read());
|
||||
pNode->tile_layers[tile_layer::ui] = static_cast<uint16_t>(oDecoder.read());
|
||||
pNode->iParcelId = static_cast<uint16_t>(oDecoder.read());
|
||||
pNode->iRoomId = static_cast<uint16_t>(oDecoder.read());
|
||||
}
|
||||
@@ -1637,9 +1656,12 @@ void level_map::depersist(lua_persist_reader* pReader) {
|
||||
for (map_tile *pNode = original_cells,
|
||||
*pLimitNode = original_cells + width * height;
|
||||
pNode != pLimitNode; ++pNode) {
|
||||
pNode->iBlock[0] = static_cast<uint16_t>(oDecoder.read());
|
||||
pNode->iBlock[1] = static_cast<uint16_t>(oDecoder.read());
|
||||
pNode->iBlock[2] = static_cast<uint16_t>(oDecoder.read());
|
||||
pNode->tile_layers[tile_layer::ground] =
|
||||
static_cast<uint16_t>(oDecoder.read());
|
||||
pNode->tile_layers[tile_layer::north_wall] =
|
||||
static_cast<uint16_t>(oDecoder.read());
|
||||
pNode->tile_layers[tile_layer::west_wall] =
|
||||
static_cast<uint16_t>(oDecoder.read());
|
||||
pNode->iParcelId = static_cast<uint16_t>(oDecoder.read());
|
||||
pNode->flags = oDecoder.read();
|
||||
}
|
||||
|
@@ -182,6 +182,15 @@ enum class temperature_theme {
|
||||
yellow_red //!< Gradients of yellow, orange, and red
|
||||
};
|
||||
|
||||
enum tile_layer : uint8_t {
|
||||
ground = 0,
|
||||
north_wall = 1,
|
||||
west_wall = 2,
|
||||
ui = 3,
|
||||
|
||||
num_tile_layers = 4 //!< Number of layers in a tile.
|
||||
};
|
||||
|
||||
struct map_tile {
|
||||
map_tile();
|
||||
~map_tile() = default;
|
||||
@@ -192,15 +201,15 @@ struct map_tile {
|
||||
//! Linked list for entities rendered in an early (right-to-left) pass
|
||||
link_list oEarlyEntities;
|
||||
|
||||
//! Block tiles for rendering
|
||||
//! For each tile, the lower byte is the index in the sprite sheet, and the
|
||||
//! Tile layers for rendering.
|
||||
//! For each layer, the lower byte is the index in the sprite sheet, and the
|
||||
//! upper byte is for the drawing flags.
|
||||
//! Layer 0 is for the floor
|
||||
//! Layer 1 is for the north wall
|
||||
//! Layer 2 is for the west wall
|
||||
//! Layer 3 is for the UI
|
||||
//! NB: In Lua, layers are numbered 1 - 4 rather than 0 - 3
|
||||
uint16_t iBlock[4];
|
||||
uint16_t tile_layers[tile_layer::num_tile_layers];
|
||||
|
||||
//! Parcels (plots) of land have an ID, with each tile in the plot having
|
||||
//! that ID. Parcel 0 is the outside.
|
||||
@@ -420,7 +429,7 @@ class level_map {
|
||||
|
||||
map_tile* cells;
|
||||
map_tile* original_cells; // Cells at map load time, before any changes
|
||||
sprite_sheet* blocks;
|
||||
sprite_sheet* wall_blocks;
|
||||
map_overlay* overlay;
|
||||
bool owns_overlay;
|
||||
int* plot_owner; // 0 for unowned, 1 for player 1, etc.
|
||||
|
Reference in New Issue
Block a user