summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/tilecell.cc
diff options
context:
space:
mode:
authorFlorian Diebold <flodiebold@gmail.com>2011-04-11 13:06:27 +0200
committerFlorian Diebold <flodiebold@gmail.com>2011-06-26 17:41:18 +0200
commit228770c101824ebc06384a2dc9bf0c27442c10e6 (patch)
treec7055c374cd68059fcf360848ff04cd78f00a56d /crawl-ref/source/tilecell.cc
parentaa9fe6c8a5b138c1f5b65810d3fd63fbf218f6ad (diff)
downloadcrawl-ref-228770c101824ebc06384a2dc9bf0c27442c10e6.tar.gz
crawl-ref-228770c101824ebc06384a2dc9bf0c27442c10e6.zip
Move rendering logic to the client, make it more complete.
Diffstat (limited to 'crawl-ref/source/tilecell.cc')
-rw-r--r--crawl-ref/source/tilecell.cc357
1 files changed, 357 insertions, 0 deletions
diff --git a/crawl-ref/source/tilecell.cc b/crawl-ref/source/tilecell.cc
new file mode 100644
index 0000000000..54d39ccad8
--- /dev/null
+++ b/crawl-ref/source/tilecell.cc
@@ -0,0 +1,357 @@
+#include "AppHdr.h"
+
+#include "tilecell.h"
+
+#include "cloud.h"
+#include "coord.h"
+#include "coordit.h"
+#include "env.h"
+#include "terrain.h"
+#include "tiledef-dngn.h"
+
+void packed_cell::clear()
+{
+ num_dngn_overlay = 0;
+ fg = 0;
+ bg = 0;
+
+ is_bloody = false;
+ is_silenced = false;
+ is_haloed = false;
+ is_moldy = false;
+ is_sanctuary = false;
+ is_liquefied = false;
+ swamp_tree_water = false;
+}
+
+bool packed_cell::operator ==(const packed_cell &other) const
+{
+ if (fg != other.fg) return false;
+ if (bg != other.bg) return false;
+
+ if (is_bloody != other.is_bloody) return false;
+ if (is_silenced != other.is_silenced) return false;
+ if (is_haloed != other.is_haloed) return false;
+ if (is_moldy != other.is_moldy) return false;
+ if (is_sanctuary != other.is_sanctuary) return false;
+ if (is_liquefied != other.is_liquefied) return false;
+ if (swamp_tree_water != other.swamp_tree_water) return false;
+
+ if (num_dngn_overlay != other.num_dngn_overlay) return false;
+ for (int i = 0; i < num_dngn_overlay; ++i)
+ {
+ if (dngn_overlay[i] != other.dngn_overlay[i]) return false;
+ }
+ return true;
+}
+
+enum wave_type
+{
+ WV_NONE = 0,
+ WV_SHALLOW,
+ WV_DEEP,
+};
+
+static wave_type _get_wave_type(bool shallow)
+{
+ return (shallow ? WV_SHALLOW : WV_DEEP);
+}
+
+static void _add_overlay(int tileidx, packed_cell *cell)
+{
+ cell->dngn_overlay[cell->num_dngn_overlay++] = tileidx;
+}
+
+static void _pack_shoal_waves(const coord_def &gc, packed_cell *cell)
+{
+ // Add wave tiles on floor adjacent to shallow water.
+ const dungeon_feature_type feat = env.map_knowledge(gc).feat();
+ const bool feat_has_ink = (cloud_type_at(coord_def(gc)) == CLOUD_INK);
+
+ if (feat == DNGN_DEEP_WATER && feat_has_ink)
+ {
+ _add_overlay(TILE_WAVE_INK_FULL, cell);
+ return;
+ }
+
+ if (feat != DNGN_FLOOR && feat != DNGN_UNDISCOVERED_TRAP
+ && feat != DNGN_SHALLOW_WATER && feat != DNGN_DEEP_WATER)
+ {
+ return;
+ }
+
+ const bool ink_only = (feat == DNGN_DEEP_WATER);
+
+ wave_type north = WV_NONE, south = WV_NONE,
+ east = WV_NONE, west = WV_NONE,
+ ne = WV_NONE, nw = WV_NONE,
+ se = WV_NONE, sw = WV_NONE;
+
+ bool inkn = false, inks = false, inke = false, inkw = false,
+ inkne = false, inknw = false, inkse = false, inksw = false;
+
+ for (radius_iterator ri(gc, 1, true, false, true); ri; ++ri)
+ {
+ if (!env.map_knowledge(*ri).seen() && !env.map_knowledge(*ri).mapped())
+ continue;
+
+ const bool ink = (cloud_type_at(coord_def(*ri)) == CLOUD_INK);
+
+ bool shallow = false;
+ if (env.map_knowledge(*ri).feat() == DNGN_SHALLOW_WATER)
+ {
+ // Adjacent shallow water is only interesting for
+ // floor cells.
+ if (!ink && feat == DNGN_SHALLOW_WATER)
+ continue;
+
+ shallow = true;
+ }
+ else if (env.map_knowledge(*ri).feat() != DNGN_DEEP_WATER)
+ continue;
+
+ if (!ink_only)
+ {
+ if (ri->x == gc.x) // orthogonals
+ {
+ if (ri->y < gc.y)
+ north = _get_wave_type(shallow);
+ else
+ south = _get_wave_type(shallow);
+ }
+ else if (ri->y == gc.y)
+ {
+ if (ri->x < gc.x)
+ west = _get_wave_type(shallow);
+ else
+ east = _get_wave_type(shallow);
+ }
+ else // diagonals
+ {
+ if (ri->x < gc.x)
+ {
+ if (ri->y < gc.y)
+ nw = _get_wave_type(shallow);
+ else
+ sw = _get_wave_type(shallow);
+ }
+ else
+ {
+ if (ri->y < gc.y)
+ ne = _get_wave_type(shallow);
+ else
+ se = _get_wave_type(shallow);
+ }
+ }
+ }
+ if (!feat_has_ink && ink)
+ {
+ if (ri->x == gc.x) // orthogonals
+ {
+ if (ri->y < gc.y)
+ inkn = true;
+ else
+ inks = true;
+ }
+ else if (ri->y == gc.y)
+ {
+ if (ri->x < gc.x)
+ inkw = true;
+ else
+ inke = true;
+ }
+ else // diagonals
+ {
+ if (ri->x < gc.x)
+ {
+ if (ri->y < gc.y)
+ inknw = true;
+ else
+ inksw = true;
+ }
+ else
+ {
+ if (ri->y < gc.y)
+ inkne = true;
+ else
+ inkse = true;
+ }
+ }
+ }
+ }
+
+ if (!ink_only)
+ {
+ // First check for shallow water.
+ if (north == WV_SHALLOW)
+ _add_overlay(TILE_WAVE_N, cell);
+ if (south == WV_SHALLOW)
+ _add_overlay(TILE_WAVE_S, cell);
+ if (east == WV_SHALLOW)
+ _add_overlay(TILE_WAVE_E, cell);
+ if (west == WV_SHALLOW)
+ _add_overlay(TILE_WAVE_W, cell);
+
+ // Then check for deep water, overwriting shallow
+ // corner waves, if necessary.
+ if (north == WV_DEEP)
+ _add_overlay(TILE_WAVE_DEEP_N, cell);
+ if (south == WV_DEEP)
+ _add_overlay(TILE_WAVE_DEEP_S, cell);
+ if (east == WV_DEEP)
+ _add_overlay(TILE_WAVE_DEEP_E, cell);
+ if (west == WV_DEEP)
+ _add_overlay(TILE_WAVE_DEEP_W, cell);
+
+ if (ne == WV_SHALLOW && !north && !east)
+ _add_overlay(TILE_WAVE_CORNER_NE, cell);
+ else if (ne == WV_DEEP && north != WV_DEEP && east != WV_DEEP)
+ _add_overlay(TILE_WAVE_DEEP_CORNER_NE, cell);
+ if (nw == WV_SHALLOW && !north && !west)
+ _add_overlay(TILE_WAVE_CORNER_NW, cell);
+ else if (nw == WV_DEEP && north != WV_DEEP && west != WV_DEEP)
+ _add_overlay(TILE_WAVE_DEEP_CORNER_NW, cell);
+ if (se == WV_SHALLOW && !south && !east)
+ _add_overlay(TILE_WAVE_CORNER_SE, cell);
+ else if (se == WV_DEEP && south != WV_DEEP && east != WV_DEEP)
+ _add_overlay(TILE_WAVE_DEEP_CORNER_SE, cell);
+ if (sw == WV_SHALLOW && !south && !west)
+ _add_overlay(TILE_WAVE_CORNER_SW, cell);
+ else if (sw == WV_DEEP && south != WV_DEEP && west != WV_DEEP)
+ _add_overlay(TILE_WAVE_DEEP_CORNER_SW, cell);
+ }
+
+ // Overlay with ink sheen, if necessary.
+ if (feat_has_ink)
+ _add_overlay(TILE_WAVE_INK_FULL, cell);
+ else
+ {
+ if (inkn)
+ _add_overlay(TILE_WAVE_INK_N, cell);
+ if (inks)
+ _add_overlay(TILE_WAVE_INK_S, cell);
+ if (inke)
+ _add_overlay(TILE_WAVE_INK_E, cell);
+ if (inkw)
+ _add_overlay(TILE_WAVE_INK_W, cell);
+ if (inkne || inkn || inke)
+ _add_overlay(TILE_WAVE_INK_CORNER_NE, cell);
+ if (inknw || inkn || inkw)
+ _add_overlay(TILE_WAVE_INK_CORNER_NW, cell);
+ if (inkse || inks || inke)
+ _add_overlay(TILE_WAVE_INK_CORNER_SE, cell);
+ if (inksw || inks || inkw)
+ _add_overlay(TILE_WAVE_INK_CORNER_SW, cell);
+ }
+}
+
+static dungeon_feature_type _safe_feat(coord_def gc)
+{
+ if (!map_bounds(gc))
+ return (DNGN_UNSEEN);
+
+ return (env.map_knowledge(gc).feat());
+}
+
+static bool _is_seen_land(coord_def gc)
+{
+ const dungeon_feature_type feat = _safe_feat(gc);
+
+ return (feat != DNGN_UNSEEN && !feat_is_water(feat) && feat != DNGN_LAVA);
+}
+
+static bool _is_seen_shallow(coord_def gc)
+{
+ const dungeon_feature_type feat = _safe_feat(gc);
+
+ return (feat == DNGN_SHALLOW_WATER || feat == DNGN_SWAMP_TREE);
+}
+
+static void _pack_default_waves(const coord_def &gc, packed_cell *cell)
+{
+ // Any tile on water with an adjacent solid tile will get an extra
+ // bit of shoreline.
+ dungeon_feature_type feat = env.map_knowledge(gc).feat();
+
+ // Treat trees in Swamp as though they were shallow water.
+ if (cell->swamp_tree_water && feat == DNGN_TREE)
+ feat = DNGN_SHALLOW_WATER;
+
+ if (!feat_is_water(feat) && feat != DNGN_LAVA || env.grid_colours(gc))
+ return;
+
+ if (feat == DNGN_DEEP_WATER)
+ {
+ if (_is_seen_shallow(coord_def(gc.x, gc.y - 1)))
+ _add_overlay(TILE_DNGN_WAVE_N, cell);
+ if (_is_seen_shallow(coord_def(gc.x + 1, gc.y - 1)))
+ _add_overlay(TILE_DNGN_WAVE_NE, cell);
+ if (_is_seen_shallow(coord_def(gc.x + 1, gc.y)))
+ _add_overlay(TILE_DNGN_WAVE_E, cell);
+ if (_is_seen_shallow(coord_def(gc.x + 1, gc.y + 1)))
+ _add_overlay(TILE_DNGN_WAVE_SE, cell);
+ if (_is_seen_shallow(coord_def(gc.x, gc.y + 1)))
+ _add_overlay(TILE_DNGN_WAVE_S, cell);
+ if (_is_seen_shallow(coord_def(gc.x - 1, gc.y + 1)))
+ _add_overlay(TILE_DNGN_WAVE_SW, cell);
+ if (_is_seen_shallow(coord_def(gc.x - 1, gc.y)))
+ _add_overlay(TILE_DNGN_WAVE_W, cell);
+ if (_is_seen_shallow(coord_def(gc.x - 1, gc.y - 1)))
+ _add_overlay(TILE_DNGN_WAVE_NW, cell);
+ }
+
+
+ bool north = _is_seen_land(coord_def(gc.x, gc.y - 1));
+ bool west = _is_seen_land(coord_def(gc.x - 1, gc.y));
+ bool east = _is_seen_land(coord_def(gc.x + 1, gc.y));
+
+ if (north || west || east)
+ {
+ if (north)
+ _add_overlay(TILE_SHORE_N, cell);
+ if (west)
+ _add_overlay(TILE_SHORE_W, cell);
+ if (east)
+ _add_overlay(TILE_SHORE_E, cell);
+ if (north && west)
+ _add_overlay(TILE_SHORE_NW, cell);
+ if (north && east)
+ _add_overlay(TILE_SHORE_NE, cell);
+ }
+}
+
+static bool _is_seen_wall(coord_def gc)
+{
+ dungeon_feature_type feat = _safe_feat(gc);
+ return (feat != DNGN_UNSEEN && feat <= DNGN_MAXWALL);
+}
+
+static void _pack_wall_shadows(const coord_def &gc, packed_cell *cell)
+{
+ if (_is_seen_wall(gc))
+ return;
+
+ if (_is_seen_wall(coord_def(gc.x - 1, gc.y)))
+ _add_overlay(TILE_DNGN_WALL_SHADOW_W, cell);
+ if (_is_seen_wall(coord_def(gc.x - 1, gc.y - 1)))
+ _add_overlay(TILE_DNGN_WALL_SHADOW_NW, cell);
+ if (_is_seen_wall(coord_def(gc.x, gc.y - 1)))
+ _add_overlay(TILE_DNGN_WALL_SHADOW_N, cell);
+ if (_is_seen_wall(coord_def(gc.x + 1, gc.y - 1)))
+ _add_overlay(TILE_DNGN_WALL_SHADOW_NE, cell);
+ if (_is_seen_wall(coord_def(gc.x + 1, gc.y)))
+ _add_overlay(TILE_DNGN_WALL_SHADOW_E, cell);
+}
+
+void pack_cell_overlays(const coord_def &gc, packed_cell *cell)
+{
+ if (player_in_branch(BRANCH_SHOALS))
+ {
+ _pack_shoal_waves(gc, cell);
+ }
+ else
+ {
+ _pack_default_waves(gc, cell);
+ _pack_wall_shadows(gc, cell);
+ }
+}