summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/terrain.cc
diff options
context:
space:
mode:
authorStefan O'Rear <stefanor@cox.net>2009-12-30 00:57:03 -0800
committerStefan O'Rear <stefanor@cox.net>2009-12-30 00:57:03 -0800
commit4db1d75dca2405e186a3e9869a2aa9e058cbf71f (patch)
tree87799a99c1980b14f32668f40817d581f64f203b /crawl-ref/source/terrain.cc
parent8a504d20b9992fea2daac06faa6ca5559ca63ae0 (diff)
downloadcrawl-ref-4db1d75dca2405e186a3e9869a2aa9e058cbf71f.tar.gz
crawl-ref-4db1d75dca2405e186a3e9869a2aa9e058cbf71f.zip
Allow tiles to destroy only some items.
Diffstat (limited to 'crawl-ref/source/terrain.cc')
-rw-r--r--crawl-ref/source/terrain.cc86
1 files changed, 51 insertions, 35 deletions
diff --git a/crawl-ref/source/terrain.cc b/crawl-ref/source/terrain.cc
index 9b2fe96deb..2e3ac60cc7 100644
--- a/crawl-ref/source/terrain.cc
+++ b/crawl-ref/source/terrain.cc
@@ -321,6 +321,12 @@ bool cell_is_solid(const coord_def &c)
return (feat_is_solid(grd(c)));
}
+bool feat_has_solid_floor(dungeon_feature_type feat)
+{
+ return (!feat_is_solid(feat) && feat != DNGN_DEEP_WATER &&
+ feat != DNGN_LAVA);
+}
+
bool feat_is_door(dungeon_feature_type feat)
{
return (feat == DNGN_CLOSED_DOOR || feat == DNGN_DETECTED_SECRET_DOOR
@@ -376,11 +382,6 @@ bool feat_is_watery(dungeon_feature_type feat)
return (feat_is_water(feat) || feat == DNGN_FOUNTAIN_BLUE);
}
-bool feat_destroys_items(dungeon_feature_type feat)
-{
- return (feat == DNGN_LAVA || feat == DNGN_DEEP_WATER);
-}
-
// Returns GOD_NO_GOD if feat is not an altar, otherwise returns the
// GOD_* type.
god_type feat_altar_god(dungeon_feature_type feat)
@@ -543,16 +544,30 @@ dungeon_feature_type grid_secret_door_appearance(const coord_def &where)
: ret);
}
-const char *feat_item_destruction_message(dungeon_feature_type feat)
+bool feat_destroys_item(dungeon_feature_type feat, const item_def &item,
+ bool noisy)
{
- return (feat == DNGN_DEEP_WATER ? "You hear a splash." :
- feat == DNGN_LAVA ? "You hear a sizzling splash."
- : "You hear a crunching noise.");
+ switch (feat)
+ {
+ case DNGN_DEEP_WATER:
+ if (noisy)
+ mprf(MSGCH_SOUND, "You hear a splash.");
+ return (true);
+
+ case DNGN_LAVA:
+ if (noisy)
+ mprf(MSGCH_SOUND, "You hear a sizzling splash.");
+ return (true);
+
+ default:
+ return (false);
+ }
}
static coord_def _dgn_find_nearest_square(
const coord_def &pos,
- bool (*acceptable)(const coord_def &),
+ void *thing,
+ bool (*acceptable)(const coord_def &, void *thing),
bool (*traversable)(const coord_def &) = NULL)
{
memset(travel_point_distance, 0, sizeof(travel_distance_grid_t));
@@ -568,7 +583,7 @@ static coord_def _dgn_find_nearest_square(
{
const coord_def &p = *i;
- if (p != pos && acceptable(p))
+ if (p != pos && acceptable(p, thing))
return (p);
travel_point_distance[p.x][p.y] = 1;
@@ -597,16 +612,17 @@ static coord_def _dgn_find_nearest_square(
return (unfound);
}
-static bool _item_safe_square(const coord_def &pos)
+static bool _item_safe_square(const coord_def &pos, void *item)
{
const dungeon_feature_type feat = grd(pos);
- return (feat_is_traversable(feat) && !feat_destroys_items(feat));
+ return (feat_is_traversable(feat) &&
+ !feat_destroys_item(feat, *static_cast<item_def *>(item)));
}
// Moves an item on the floor to the nearest adjacent floor-space.
static bool _dgn_shift_item(const coord_def &pos, item_def &item)
{
- const coord_def np = _dgn_find_nearest_square(pos, _item_safe_square);
+ const coord_def np = _dgn_find_nearest_square(pos, &item, _item_safe_square);
if (in_bounds(np) && np != pos)
{
int index = item.index();
@@ -622,7 +638,7 @@ bool is_critical_feature(dungeon_feature_type feat)
|| feat_altar_god(feat) != GOD_NO_GOD);
}
-static bool _is_feature_shift_target(const coord_def &pos)
+static bool _is_feature_shift_target(const coord_def &pos, void*)
{
return (grd(pos) == DNGN_FLOOR && !dungeon_events.has_listeners_at(pos));
}
@@ -634,7 +650,7 @@ static bool _dgn_shift_feature(const coord_def &pos)
return (false);
const coord_def dest =
- _dgn_find_nearest_square(pos, _is_feature_shift_target);
+ _dgn_find_nearest_square(pos, NULL, _is_feature_shift_target);
if (in_bounds(dest) && dest != pos)
{
@@ -654,27 +670,27 @@ static bool _dgn_shift_feature(const coord_def &pos)
static void _dgn_check_terrain_items(const coord_def &pos, bool preserve_items)
{
const dungeon_feature_type feat = grd(pos);
- if (feat_is_solid(feat) || feat_destroys_items(feat))
+
+ int item = igrd(pos);
+ bool did_destroy = false;
+ while (item != NON_ITEM)
{
- int item = igrd(pos);
- bool did_destroy = false;
- while (item != NON_ITEM)
- {
- const int curr = item;
- item = mitm[item].link;
+ const int curr = item;
+ item = mitm[item].link;
- // Game-critical item.
- if (preserve_items || mitm[curr].is_critical())
- _dgn_shift_item(pos, mitm[curr]);
- else
- {
- item_was_destroyed(mitm[curr]);
- destroy_item(curr);
- did_destroy = true;
- }
+ if (!feat_is_solid(feat) && !feat_destroys_item(feat, mitm[curr]))
+ continue;
+
+ // Game-critical item.
+ if (preserve_items || mitm[curr].is_critical())
+ _dgn_shift_item(pos, mitm[curr]);
+ else
+ {
+ feat_destroys_item(feat, mitm[curr], true);
+ item_was_destroyed(mitm[curr]);
+ destroy_item(curr);
+ did_destroy = true;
}
- if (did_destroy && player_can_hear(pos))
- mprf(MSGCH_SOUND, feat_item_destruction_message(feat));
}
}
@@ -704,7 +720,7 @@ static void _dgn_check_terrain_blood(const coord_def &pos,
else
{
if (feat_is_solid(old_feat) != feat_is_solid(new_feat)
- || feat_is_water(new_feat) || feat_destroys_items(new_feat)
+ || feat_is_water(new_feat) || new_feat == DNGN_LAVA
|| is_critical_feature(new_feat))
{
env.pgrid(pos) &= ~(FPROP_BLOODY);