|
From: <gi...@cr...> - 2011-08-30 22:46:16
|
via bce3ac8d5bab1cc6fac91f0f85b1bc6563d1b7b0 (commit)
via debb87631079d5752d736987ed139b4d3db3eff0 (commit)
via 10a7876a8a7dfe79cdb4e16dbc8a17c12d64c599 (commit)
via 8bd3ce093c488d33df3cd96786dd223a2c09e86b (commit)
from 3542ec16e3e616ce9e6042a7a7493cd33ea44ffb (commit)
-----------------------------------------------------------------------
commit bce3ac8d5bab1cc6fac91f0f85b1bc6563d1b7b0
Author: Raphael Langella <rap...@gm...>
Date: Tue Aug 30 09:41:05 2011 +0000
No stairs down mimics in minmay_temple_entry_from_below.
Any other vaults needing this?
commit debb87631079d5752d736987ed139b4d3db3eff0
Author: Raphael Langella <rap...@gm...>
Date: Tue Aug 30 09:27:39 2011 +0000
Add 2 new vault tags: mimic and no_mimic.
mimic is for placing feature mimics, no_mimic is to prevent a feature from
being randomly turned into a mimic.
commit 10a7876a8a7dfe79cdb4e16dbc8a17c12d64c599
Author: Raphael Langella <rap...@gm...>
Date: Mon Aug 29 13:18:59 2011 +0000
Rename stair mimic to staircase mimic.
commit 8bd3ce093c488d33df3cd96786dd223a2c09e86b
Author: Raphael Langella <rap...@gm...>
Date: Tue Aug 30 17:47:20 2011 +0200
Merge all the feature mimics into a single monster type.
It's now possible to create any kind of feature mimic using &M.
-----------------------------------------------------------------------
Summary of changes:
crawl-ref/source/dat/des/branches/temple.des | 2 +
crawl-ref/source/describe.cc | 17 +--
crawl-ref/source/dungeon.cc | 38 ++----
crawl-ref/source/dungeon.h | 2 +-
crawl-ref/source/enum.h | 6 +-
crawl-ref/source/fight.cc | 13 ++-
crawl-ref/source/los.cc | 13 ++-
crawl-ref/source/los.h | 1 +
crawl-ref/source/losparam.cc | 17 +--
crawl-ref/source/mapdef.cc | 16 ++-
crawl-ref/source/mapdef.h | 4 +-
crawl-ref/source/mon-data.h | 63 +--------
crawl-ref/source/mon-place.cc | 7 +-
crawl-ref/source/mon-stuff.cc | 6 +-
crawl-ref/source/mon-util.cc | 13 +-
crawl-ref/source/stash.cc | 10 --
crawl-ref/source/terrain.cc | 29 ++++-
crawl-ref/source/terrain.h | 1 +
crawl-ref/source/tilepick.cc | 12 +--
crawl-ref/source/tileview.cc | 9 +-
crawl-ref/source/wiz-dgn.cc | 181 ++++++++++++++------------
crawl-ref/source/wiz-dgn.h | 6 +-
crawl-ref/source/wiz-mon.cc | 38 +-----
23 files changed, 222 insertions(+), 282 deletions(-)
diff --git a/crawl-ref/source/dat/des/branches/temple.des b/crawl-ref/source/dat/des/branches/temple.des
index ffdf52f..85bdb8b 100644
--- a/crawl-ref/source/dat/des/branches/temple.des
+++ b/crawl-ref/source/dat/des/branches/temple.des
@@ -846,6 +846,7 @@ TAGS: temple_entry
ORIENT: float
WEIGHT: 5
KFEAT: O = enter_temple
+KFEAT: } = no_mimic stone_stairs_down_i
MAP
@
ccccccncc
@@ -861,6 +862,7 @@ TAGS: temple_entry
ORIENT: float
WEIGHT: 2
KFEAT: O = enter_temple
+KFEAT: } = no_mimic stone_stairs_down_i
MAP
@
cccccccccnccc
diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc
index 51e04d6..cb7297e 100644
--- a/crawl-ref/source/describe.cc
+++ b/crawl-ref/source/describe.cc
@@ -58,6 +58,7 @@
#include "spl-cast.h"
#include "spl-util.h"
#include "stash.h"
+#include "terrain.h"
#include "transform.h"
#include "hints.h"
#include "xom.h"
@@ -3337,17 +3338,13 @@ static std::string _monster_stat_description(const monster_info& mi)
"huge",
};
- const char *mimic_sizes[6]= {
- "as big as a fountain",
- "as big as a shop",
- "as big as a staircase",
- "as big as a trap",
- "as big as a portal",
- "as big as a door",
- };
-
if (mons_is_feat_mimic(mi.type))
- result << pronoun << " is " << mimic_sizes[MONS_FOUNTAIN_MIMIC-mi.type] << ".\n";
+ {
+ result << pronoun << " is as big as "
+ << thing_do_grammar(DESC_NOCAP_A, true, false,
+ feat_type_name(mi.get_mimic_feature()))
+ << "\n";
+ }
else if (sizes[mi.body_size()])
result << pronoun << " is " << sizes[mi.body_size()] << ".\n";
diff --git a/crawl-ref/source/dungeon.cc b/crawl-ref/source/dungeon.cc
index 43c706c..951744b 100644
--- a/crawl-ref/source/dungeon.cc
+++ b/crawl-ref/source/dungeon.cc
@@ -2053,8 +2053,13 @@ static void _place_feature_mimics(int level_number,
{
const coord_def pos = *ri;
const dungeon_feature_type feat = grd(pos);
+
+ // Vault tag prevents mimic.
+ if (map_masked(pos, MMT_NO_MIMIC))
+ continue;
+
// Only features valid for mimicing.
- if (get_feature_mimic_type(feat) == MONS_PROGRAM_BUG)
+ if (!is_valid_mimic_feat(feat))
continue;
// Don't mimic the stairs the player is going to be placed on.
@@ -3478,33 +3483,6 @@ bool door_vetoed(const coord_def pos)
return env.markers.property_at(pos, MAT_ANY, "veto_open") == "veto";
}
-monster_type get_feature_mimic_type(dungeon_feature_type feat)
-{
- // Don't risk trapping the player inside a portal vault.
- if (feat == DNGN_EXIT_PORTAL_VAULT)
- return MONS_PROGRAM_BUG;
-
- if (feat_is_portal(feat) || feat_is_gate(feat))
- return MONS_PORTAL_MIMIC;
-
- if (feat_is_stone_stair(feat) || feat_is_escape_hatch(feat)
- || feat_is_branch_stairs(feat))
- {
- return MONS_STAIR_MIMIC;
- }
-
- if (feat_is_fountain(feat))
- return MONS_FOUNTAIN_MIMIC;
-
- if (feat_is_door(feat))
- return MONS_DOOR_MIMIC;
-
- if (feat == DNGN_ENTER_SHOP)
- return MONS_SHOP_MIMIC;
-
- return MONS_PROGRAM_BUG;
-}
-
static void _builder_monsters(int level_number, level_area_type level_type, int mon_wanted)
{
if (level_type == LEVEL_PANDEMONIUM
@@ -4572,6 +4550,10 @@ static void _vault_grid_mapspec(vault_placement &place, const coord_def &where,
else if (f.feat >= 0)
{
grd(where) = static_cast<dungeon_feature_type>(f.feat);
+ if (f.mimic)
+ env.level_map_mask(where) |= MMT_MIMIC;
+ else if (f.no_mimic)
+ env.level_map_mask(where) |= MMT_NO_MIMIC;
}
else if (f.glyph >= 0)
{
diff --git a/crawl-ref/source/dungeon.h b/crawl-ref/source/dungeon.h
index 0b093b1..b433d80 100644
--- a/crawl-ref/source/dungeon.h
+++ b/crawl-ref/source/dungeon.h
@@ -63,6 +63,7 @@ enum map_mask_type
MMT_OPAQUE = 0x40, // Vault may impede connectivity.
MMT_NO_TRAP = 0x80, // No trap generation
MMT_MIMIC = 0x100, // Feature mimics
+ MMT_NO_MIMIC = 0x200, // This feature shouldn't be turned into a mimic.
};
class dgn_region;
@@ -322,5 +323,4 @@ bool join_the_dots(const coord_def &from, const coord_def &to, unsigned mmask);
int count_feature_in_box(int x0, int y0, int x1, int y1,
dungeon_feature_type feat);
bool door_vetoed(const coord_def pos);
-monster_type get_feature_mimic_type(dungeon_feature_type feat);
#endif
diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h
index 5f57be0..da004af 100644
--- a/crawl-ref/source/enum.h
+++ b/crawl-ref/source/enum.h
@@ -2051,14 +2051,14 @@ enum monster_type // (int) menv[].type
MONS_ARMOUR_MIMIC,
MONS_SCROLL_MIMIC,
MONS_POTION_MIMIC,
- MONS_DOOR_MIMIC,
- MONS_PORTAL_MIMIC,
+ MONS_FEATURE_MIMIC,
#if TAG_MAJOR_VERSION == 32
+ MONS_PORTAL_MIMIC,
MONS_TRAP_MIMIC,
-#endif
MONS_STAIR_MIMIC,
MONS_SHOP_MIMIC,
MONS_FOUNTAIN_MIMIC,
+#endif
// Plants:
MONS_TOADSTOOL,
diff --git a/crawl-ref/source/fight.cc b/crawl-ref/source/fight.cc
index ba79a18..869ade6 100644
--- a/crawl-ref/source/fight.cc
+++ b/crawl-ref/source/fight.cc
@@ -4669,6 +4669,17 @@ std::string melee_attack::mons_attack_verb(const mon_attack_def &attk)
if (attacker->type == MONS_KILLER_KLOWN && attk.type == AT_HIT)
return (RANDOM_ELEMENT(klown_attack));
+ mon_attack_type type = attk.type;
+
+ if (mons_is_feat_mimic(attacker->type))
+ {
+ const dungeon_feature_type feat = get_mimic_feat(attacker->as_monster());
+ if (feat_is_door(feat))
+ type = AT_SNAP;
+ else if (feat_is_fountain(feat))
+ type = AT_SPLASH;
+ }
+
if (attk.type == AT_TENTACLE_SLAP
&& (attacker->type == MONS_KRAKEN_TENTACLE
|| attacker->type == MONS_ELDRITCH_TENTACLE))
@@ -4705,7 +4716,7 @@ std::string melee_attack::mons_attack_verb(const mon_attack_def &attk)
ASSERT(attk.type <
static_cast<int>(sizeof(attack_types) / sizeof(const char *)));
- return (attack_types[attk.type]);
+ return (attack_types[type]);
}
std::string melee_attack::mons_attack_desc(const mon_attack_def &attk)
diff --git a/crawl-ref/source/los.cc b/crawl-ref/source/los.cc
index 0aabff2..39811fb 100644
--- a/crawl-ref/source/los.cc
+++ b/crawl-ref/source/los.cc
@@ -895,6 +895,17 @@ void losight(los_grid& sh, const coord_def& center,
losight(sh, los_param_funcs(center, opc, bounds));
}
+opacity_type mons_opacity(const monster* mon)
+{
+ if (mon->type == MONS_BUSH)
+ return OPC_HALF;
+
+ if (mons_is_feat_mimic(mon->type) && feat_is_opaque(get_mimic_feat(mon)))
+ return OPC_OPAQUE;
+
+ return OPC_CLEAR;
+}
+
/////////////////////////////////////
// A start at tracking LOS changes.
@@ -907,7 +918,7 @@ static void _handle_los_change()
static bool _mons_block_sight(const monster* mons)
{
- return (mons->type == MONS_BUSH || mons->type == MONS_DOOR_MIMIC);
+ return mons_opacity(mons) != OPC_CLEAR;
}
void los_actor_moved(const actor* act, const coord_def& oldpos)
diff --git a/crawl-ref/source/los.h b/crawl-ref/source/los.h
index 4736aab..735f88b 100644
--- a/crawl-ref/source/los.h
+++ b/crawl-ref/source/los.h
@@ -55,4 +55,5 @@ void los_monster_died(const monster* mon);
void los_terrain_changed(const coord_def& p);
void los_cloud_changed(const coord_def& p);
void los_changed();
+opacity_type mons_opacity(const monster* mon);
#endif
diff --git a/crawl-ref/source/losparam.cc b/crawl-ref/source/losparam.cc
index bf35185..93518ce 100644
--- a/crawl-ref/source/losparam.cc
+++ b/crawl-ref/source/losparam.cc
@@ -26,12 +26,7 @@ opacity_type opacity_default::operator()(const coord_def& p) const
else if (f == DNGN_TREE || f == DNGN_SWAMP_TREE)
return OPC_HALF;
if (const monster *mon = monster_at(p))
- {
- if (mon->type == MONS_BUSH)
- return OPC_HALF;
- if (mon->type == MONS_DOOR_MIMIC)
- return OPC_OPAQUE;
- }
+ return mons_opacity(mon);
return OPC_CLEAR;
}
@@ -100,14 +95,8 @@ opacity_type opacity_solid::operator()(const coord_def& p) const
return OPC_HALF;
else if (f == DNGN_TREE || f == DNGN_SWAMP_TREE)
return OPC_HALF;
- else if (monster_at(p))
- {
- if (monster_at(p)->type == MONS_DOOR_MIMIC)
- return OPC_OPAQUE;
-
- if (monster_at(p)->type == MONS_BUSH)
- return OPC_HALF;
- }
+ else if (const monster *mon = monster_at(p))
+ return mons_opacity(mon);
return OPC_CLEAR;
}
diff --git a/crawl-ref/source/mapdef.cc b/crawl-ref/source/mapdef.cc
index f4ee9f0..dc2525b 100644
--- a/crawl-ref/source/mapdef.cc
+++ b/crawl-ref/source/mapdef.cc
@@ -5539,12 +5539,14 @@ feature_spec_list keyed_mapspec::parse_feature(const std::string &str)
return (list);
}
+ const bool mimic = strip_tag(s, "mimic");
+ const bool no_mimic = strip_tag(s, "no_mimic");
const dungeon_feature_type ftype = dungeon_feature_by_name(s);
+
if (ftype == DNGN_UNSEEN)
- err = make_stringf("no features matching \"%s\"",
- str.c_str());
+ err = make_stringf("no features matching \"%s\"", str.c_str());
else
- list.push_back(feature_spec(ftype, weight));
+ list.push_back(feature_spec(ftype, weight, mimic, no_mimic));
return (list);
}
@@ -5658,15 +5660,19 @@ feature_spec::feature_spec ()
glyph = -1;
shop.reset(NULL);
trap.reset(NULL);
+ mimic = false;
+ no_mimic = false;
}
-feature_spec::feature_spec (int f, int wt)
+feature_spec::feature_spec(int f, int wt, bool _mimic, bool _no_mimic)
{
genweight = wt;
feat = f;
glyph = -1;
shop.reset(NULL);
trap.reset(NULL);
+ mimic = _mimic;
+ no_mimic = _no_mimic;
}
feature_spec::feature_spec(const feature_spec &other)
@@ -5686,6 +5692,8 @@ void feature_spec::init_with (const feature_spec& other)
genweight = other.genweight;
feat = other.feat;
glyph = other.glyph;
+ mimic = other.mimic;
+ no_mimic = other.no_mimic;
if (other.trap.get())
trap.reset(new trap_spec(*other.trap));
diff --git a/crawl-ref/source/mapdef.h b/crawl-ref/source/mapdef.h
index cbd0343..3cfb6e0 100644
--- a/crawl-ref/source/mapdef.h
+++ b/crawl-ref/source/mapdef.h
@@ -823,9 +823,11 @@ struct feature_spec
std::auto_ptr<shop_spec> shop; /**> A pointer to a shop_spec. */
std::auto_ptr<trap_spec> trap; /**> A pointer to a trap_spec. */
int glyph; /**> What glyph to use instead. */
+ bool mimic; /**> This is a feature mimic. */
+ bool no_mimic; /**> Prevents random feature mimic here. */
feature_spec();
- feature_spec(int f, int wt = 10);
+ feature_spec(int f, int wt = 10, bool _mimic = false, bool _no_mimic = false);
feature_spec(const feature_spec& other);
feature_spec& operator = (const feature_spec& other);
void init_with (const feature_spec& other);
diff --git a/crawl-ref/source/mon-data.h b/crawl-ref/source/mon-data.h
index f361624..6520cfb 100644
--- a/crawl-ref/source/mon-data.h
+++ b/crawl-ref/source/mon-data.h
@@ -216,11 +216,15 @@ static monsterentry mondata[] = {
#if TAG_MAJOR_VERSION == 32
AXED_MON(MONS_MEGABAT)
AXED_MON(MONS_GIANT_BLOWFLY)
- AXED_MON(MONS_TRAP_MIMIC)
AXED_MON(MONS_BEAR)
AXED_MON(MONS_GILA_MONSTER)
AXED_MON(MONS_GIANT_TOAD)
AXED_MON(MONS_VIPER)
+ AXED_MON(MONS_PORTAL_MIMIC)
+ AXED_MON(MONS_TRAP_MIMIC)
+ AXED_MON(MONS_STAIR_MIMIC)
+ AXED_MON(MONS_SHOP_MIMIC)
+ AXED_MON(MONS_FOUNTAIN_MIMIC)
#endif
// Real monsters begin here {dlb}:
@@ -4435,38 +4439,11 @@ static monsterentry mondata[] = {
MONUSE_NOTHING, MONEAT_NOTHING, SIZE_TINY
},
-// Feature mimics.
-{
- MONS_DOOR_MIMIC, '+', LIGHTGRAY, "door mimic",
- M_FIGHTER,
- MR_RES_POISON | MR_RES_ELEC | MR_RES_FIRE | MR_RES_COLD,
- 0, 13, MONS_DOOR_MIMIC, MONS_DOOR_MIMIC, MH_NONLIVING, -3,
- { {AT_SNAP, AF_POISON, 12}, {AT_SNAP, AF_PLAIN, 12},
- {AT_SNAP, AF_PLAIN, 12}, AT_NO_ATK },
- { 8, 3, 5, 0 },
- 5, 1, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT,
- I_NORMAL, HT_LAND, FL_NONE, 10, DEFAULT_ENERGY,
- MONUSE_NOTHING, MONEAT_NOTHING, SIZE_TINY
-},
-
-{
- MONS_PORTAL_MIMIC, '\\', ETC_SHIMMER_BLUE, "portal mimic",
- M_FIGHTER,
- MR_RES_POISON | MR_RES_ELEC | MR_RES_FIRE | MR_RES_COLD,
- 0, 13, MONS_DOOR_MIMIC, MONS_PORTAL_MIMIC, MH_NONLIVING, -3,
- { {AT_HIT, AF_POISON, 12}, {AT_HIT, AF_PLAIN, 12}, {AT_HIT, AF_PLAIN, 12},
- AT_NO_ATK },
- { 8, 3, 5, 0 },
- 5, 1, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT,
- I_NORMAL, HT_LAND, FL_NONE, 10, DEFAULT_ENERGY,
- MONUSE_NOTHING, MONEAT_NOTHING, SIZE_TINY
-},
-
{
- MONS_STAIR_MIMIC, '>', LIGHTGRAY, "stair mimic",
+ MONS_FEATURE_MIMIC, '+', LIGHTGRAY, "feature mimic",
M_FIGHTER,
MR_RES_POISON | MR_RES_ELEC | MR_RES_FIRE | MR_RES_COLD,
- 0, 13, MONS_DOOR_MIMIC, MONS_STAIR_MIMIC, MH_NONLIVING, -3,
+ 0, 13, MONS_FEATURE_MIMIC, MONS_FEATURE_MIMIC, MH_NONLIVING, -3,
{ {AT_HIT, AF_POISON, 12}, {AT_HIT, AF_PLAIN, 12}, {AT_HIT, AF_PLAIN, 12},
AT_NO_ATK },
{ 8, 3, 5, 0 },
@@ -4475,32 +4452,6 @@ static monsterentry mondata[] = {
MONUSE_NOTHING, MONEAT_NOTHING, SIZE_TINY
},
-{
- MONS_SHOP_MIMIC, '\\', YELLOW, "shop mimic",
- M_FIGHTER,
- MR_RES_POISON | MR_RES_ELEC | MR_RES_FIRE | MR_RES_COLD,
- 0, 13, MONS_DOOR_MIMIC, MONS_SHOP_MIMIC, MH_NONLIVING, -3,
- { {AT_HIT, AF_POISON, 12}, {AT_HIT, AF_PLAIN, 12}, {AT_HIT, AF_PLAIN, 12},
- AT_NO_ATK },
- { 8, 3, 5, 0 },
- 5, 1, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT,
- I_NORMAL, HT_LAND, FL_NONE, 10, DEFAULT_ENERGY,
- MONUSE_NOTHING, MONEAT_NOTHING, SIZE_TINY
-},
-
-{
- MONS_FOUNTAIN_MIMIC, '}', ETC_SHIMMER_BLUE, "fountain mimic",
- M_FIGHTER,
- MR_RES_POISON | MR_RES_ELEC | MR_RES_FIRE | MR_RES_COLD,
- 0, 13, MONS_DOOR_MIMIC, MONS_FOUNTAIN_MIMIC, MH_NONLIVING, -3,
- { {AT_SPLASH, AF_POISON, 12}, {AT_SPLASH, AF_PLAIN, 12},
- {AT_SPLASH, AF_PLAIN, 12}, AT_NO_ATK },
- { 8, 3, 5, 0 },
- 5, 1, MST_NO_SPELLS, CE_NOCORPSE, Z_NOZOMBIE, S_SILENT,
- I_NORMAL, HT_LAND, FL_NONE, 10, DEFAULT_ENERGY,
- MONUSE_NOTHING, MONEAT_NOTHING, SIZE_TINY
-},
-
// dancing weapon
// These are named more explicitly when they attack, also when you use 'x'
// to examine them.
diff --git a/crawl-ref/source/mon-place.cc b/crawl-ref/source/mon-place.cc
index 923c8e3..92311da 100644
--- a/crawl-ref/source/mon-place.cc
+++ b/crawl-ref/source/mon-place.cc
@@ -491,13 +491,8 @@ static std::vector<monster_type> _find_valid_monster_types(const level_id &place
valid_monster_types.clear();
for (int i = 0; i < NUM_MONSTERS; ++i)
if (mons_rarity(static_cast<monster_type>(i), place) > 0)
- {
- if (i == MONS_STAIR_MIMIC && your_branch().depth == 1)
- continue;
- if (i == MONS_SHOP_MIMIC && !_is_valid_shop_level())
- continue;
valid_monster_types.push_back(static_cast<monster_type>(i));
- }
+
last_monster_type_place = place;
return (valid_monster_types);
}
diff --git a/crawl-ref/source/mon-stuff.cc b/crawl-ref/source/mon-stuff.cc
index 1547463..de13818 100644
--- a/crawl-ref/source/mon-stuff.cc
+++ b/crawl-ref/source/mon-stuff.cc
@@ -183,8 +183,10 @@ item_def &get_mimic_item(const monster* mimic)
dungeon_feature_type get_mimic_feat(const monster* mimic)
{
- ASSERT(mimic->props.exists("feat_type"));
- return static_cast<dungeon_feature_type>(mimic->props["feat_type"].get_short());
+ if (mimic->props.exists("feat_type"))
+ return static_cast<dungeon_feature_type>(mimic->props["feat_type"].get_short());
+ else
+ return DNGN_FLOOR;
}
bool feature_mimic_at(const coord_def &c)
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index 208a858..8f24edf 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -185,11 +185,7 @@ void init_mon_name_cache()
|| mon == MONS_ARMOUR_MIMIC
|| mon == MONS_SCROLL_MIMIC
|| mon == MONS_POTION_MIMIC
- || mon == MONS_DOOR_MIMIC
- || mon == MONS_PORTAL_MIMIC
- || mon == MONS_SHOP_MIMIC
- || mon == MONS_STAIR_MIMIC
- || mon == MONS_FOUNTAIN_MIMIC
+ || mon == MONS_FEATURE_MIMIC
|| mon == MONS_MARA_FAKE)
{
// Keep previous entry.
@@ -867,7 +863,7 @@ bool mons_is_item_mimic(int mc)
bool mons_is_feat_mimic(int mc)
{
- return (mons_genus(mc) == MONS_DOOR_MIMIC);
+ return (mc == MONS_FEATURE_MIMIC);
}
bool discover_mimic(const coord_def& pos)
@@ -912,7 +908,7 @@ bool discover_mimic(const coord_def& pos)
// Generate and place the monster.
mgen_data mg;
mg.behaviour = BEH_WANDER;
- mg.cls = get_feature_mimic_type(feat);
+ mg.cls = MONS_FEATURE_MIMIC;
mg.pos = pos;
const int mid = place_monster(mg, true);
ASSERT(mid != -1);
@@ -940,6 +936,9 @@ bool discover_mimic(const coord_def& pos)
if (mon && mon->friendly())
behaviour_event(mon, ME_WHACK, mid);
+ // Necessary for door mimics to force LOS update.
+ mimic->set_position(pos);
+
// Announce the mimic.
if (feat == DNGN_OPEN_DOOR)
simple_monster_message(mimic, " slams shut!", MSGCH_WARN);
diff --git a/crawl-ref/source/stash.cc b/crawl-ref/source/stash.cc
index 99da5a2..38e786d 100644
--- a/crawl-ref/source/stash.cc
+++ b/crawl-ref/source/stash.cc
@@ -330,13 +330,6 @@ static bool _grid_has_mimic_item(const coord_def& pos)
return (mon && mons_is_unknown_mimic(mon) && mons_is_item_mimic(mon->type));
}
-static bool _grid_has_mimic_shop(const coord_def& pos)
-{
- const monster* mon = monster_at(pos);
- return (mon && mons_is_unknown_mimic(mon)
- && mon->type == MONS_SHOP_MIMIC);
-}
-
static bool _grid_has_perceived_item(const coord_def& pos)
{
return (you.visible_igrd(pos) != NON_ITEM || _grid_has_mimic_item(pos));
@@ -1230,9 +1223,6 @@ const ShopInfo *LevelStashes::find_shop(const coord_def& c) const
bool LevelStashes::shop_needs_visit(const coord_def& c) const
{
- if (_grid_has_mimic_shop(c))
- return true;
-
const ShopInfo *shop = find_shop(c);
return (shop && !shop->is_visited());
}
diff --git a/crawl-ref/source/terrain.cc b/crawl-ref/source/terrain.cc
index 8bc61ba..78e3eb5 100644
--- a/crawl-ref/source/terrain.cc
+++ b/crawl-ref/source/terrain.cc
@@ -833,6 +833,33 @@ bool is_valid_border_feat(dungeon_feature_type feat)
|| feat == DNGN_LAVA_SEA));
}
+bool is_valid_mimic_feat(dungeon_feature_type feat)
+{
+ // Don't risk trapping the player inside a portal vault.
+ if (feat == DNGN_EXIT_PORTAL_VAULT)
+ return false;
+
+ if (feat_is_portal(feat) || feat_is_gate(feat))
+ return true;
+
+ if (feat_is_stone_stair(feat) || feat_is_escape_hatch(feat)
+ || feat_is_branch_stairs(feat))
+ {
+ return true;
+ }
+
+ if (feat_is_fountain(feat))
+ return true;
+
+ if (feat_is_door(feat))
+ return true;
+
+ if (feat == DNGN_ENTER_SHOP)
+ return true;
+
+ return false;
+}
+
static bool _is_feature_shift_target(const coord_def &pos, void*)
{
return (grd(pos) == DNGN_FLOOR && !dungeon_events.has_listeners_at(pos));
@@ -1808,7 +1835,7 @@ const char* feat_type_name(dungeon_feature_type feat)
if (feat_is_portal(feat) || feat_is_gate(feat))
return "portal";
if (feat_is_travelable_stair(feat))
- return "stair";
+ return "staircase";
if (feat == DNGN_ENTER_SHOP)
return "shop";
if (feat_is_fountain(feat))
diff --git a/crawl-ref/source/terrain.h b/crawl-ref/source/terrain.h
index ca2e5eb..ee3996c 100644
--- a/crawl-ref/source/terrain.h
+++ b/crawl-ref/source/terrain.h
@@ -122,6 +122,7 @@ bool slide_feature_over(const coord_def &src,
bool is_critical_feature(dungeon_feature_type feat);
bool is_valid_border_feat(dungeon_feature_type feat);
+bool is_valid_mimic_feat(dungeon_feature_type feat);
void init_feat_desc_cache();
dungeon_feature_type feat_by_desc(std::string desc);
diff --git a/crawl-ref/source/tilepick.cc b/crawl-ref/source/tilepick.cc
index 265c2e6..cd1aee6 100644
--- a/crawl-ref/source/tilepick.cc
+++ b/crawl-ref/source/tilepick.cc
@@ -1523,11 +1523,7 @@ static tileidx_t _tileidx_monster_base(int type, bool in_water, int colour,
// Feature mimics actually get drawn with the dungeon code.
// See tileidx_feature.
- case MONS_DOOR_MIMIC:
- case MONS_PORTAL_MIMIC:
- case MONS_STAIR_MIMIC:
- case MONS_SHOP_MIMIC:
- case MONS_FOUNTAIN_MIMIC:
+ case MONS_FEATURE_MIMIC:
return 0;
// '5' demons
@@ -2502,11 +2498,7 @@ static tileidx_t _tileidx_monster_no_props(const monster* mon)
}
// Feature mimics get drawn with the dungeon, see tileidx_feature.
- case MONS_SHOP_MIMIC:
- case MONS_PORTAL_MIMIC:
- case MONS_DOOR_MIMIC:
- case MONS_STAIR_MIMIC:
- case MONS_FOUNTAIN_MIMIC:
+ case MONS_FEATURE_MIMIC:
return TILE_FLAG_MIMIC;
case MONS_DANCING_WEAPON:
diff --git a/crawl-ref/source/tileview.cc b/crawl-ref/source/tileview.cc
index 4dfab8a..8b2cb77 100644
--- a/crawl-ref/source/tileview.cc
+++ b/crawl-ref/source/tileview.cc
@@ -977,11 +977,14 @@ static inline void _apply_variations(const tile_flavour &flv, tileidx_t *bg,
orig = TILE_WALL_NORMAL;
}
+ const bool mimic = monster_at(gc) && mons_is_feat_mimic(monster_at(gc)->type);
+
if (orig == TILE_FLOOR_NORMAL)
*bg = flv.floor;
else if (orig == TILE_WALL_NORMAL)
*bg = flv.wall;
- else if (orig == TILE_DNGN_CLOSED_DOOR || orig == TILE_DNGN_OPEN_DOOR)
+ else if ((orig == TILE_DNGN_CLOSED_DOOR || orig == TILE_DNGN_OPEN_DOOR)
+ && !mimic)
{
tileidx_t override = flv.feat;
// Setting an override on a door specifically for undetected secret
@@ -1001,10 +1004,6 @@ static inline void _apply_variations(const tile_flavour &flv, tileidx_t *bg,
}
else
*bg = orig + std::min((int)flv.special, 3);
-
- const monster *mimic = monster_at(gc);
- if (mimic && mimic->type == MONS_DOOR_MIMIC)
- *bg = orig;
}
else if (orig == TILE_DNGN_PORTAL_WIZARD_LAB
|| orig == TILE_DNGN_ALTAR_CHEIBRIADOS)
diff --git a/crawl-ref/source/wiz-dgn.cc b/crawl-ref/source/wiz-dgn.cc
index ec308e7..c24cc67 100644
--- a/crawl-ref/source/wiz-dgn.cc
+++ b/crawl-ref/source/wiz-dgn.cc
@@ -246,14 +246,14 @@ void wizard_interlevel_travel()
_wizard_go_to_level(pos);
}
-void wizard_create_portal(const coord_def& pos)
+bool wizard_create_portal(const coord_def& pos)
{
mpr("Destination for portal (defaults to 'bazaar')? ", MSGCH_PROMPT);
char specs[256];
if (cancelable_get_line(specs, sizeof(specs)))
{
canned_msg(MSG_OK);
- return;
+ return false;
}
std::string dst = specs;
@@ -266,105 +266,119 @@ void wizard_create_portal(const coord_def& pos)
if (!find_map_by_name(dst) && !random_map_for_tag(dst))
{
mprf("No map named '%s' or tagged '%s'.", dst.c_str(), dst.c_str());
+ return false;
}
- else
- {
- map_wiz_props_marker *marker = new map_wiz_props_marker(you.pos());
- marker->set_property("dst", dst);
- marker->set_property("feature_description",
- "wizard portal, dest = " + dst);
- env.markers.add(marker);
- env.markers.clear_need_activate();
- dungeon_terrain_changed(pos, DNGN_ENTER_PORTAL_VAULT, false);
- }
+
+ map_wiz_props_marker *marker = new map_wiz_props_marker(you.pos());
+ marker->set_property("dst", dst);
+ marker->set_property("feature_description",
+ "wizard portal, dest = " + dst);
+ env.markers.add(marker);
+ env.markers.clear_need_activate();
+ dungeon_terrain_changed(pos, DNGN_ENTER_PORTAL_VAULT, false);
+ return true;
}
-void wizard_create_feature()
+bool wizard_create_feature(const coord_def& pos)
{
+ const bool mimic = (pos != you.pos());
char specs[256];
dungeon_feature_type feat;
- mpr("Create which feature? ", MSGCH_PROMPT);
+ if (mimic)
+ mpr("Create what kind of feature mimic? ", MSGCH_PROMPT);
+ else
+ mpr("Create which feature? ", MSGCH_PROMPT);
- if (!cancelable_get_line(specs, sizeof(specs)) && specs[0] != 0)
+ if (cancelable_get_line(specs, sizeof(specs)) || specs[0] == 0)
{
- if (int feat_num = atoi(specs))
- {
- feat = static_cast<dungeon_feature_type>(feat_num);
- }
- else
- {
- std::string name = lowercase_string(specs);
- name = replace_all(name, " ", "_");
- feat = dungeon_feature_by_name(name);
- if (feat == DNGN_UNSEEN) // no exact match
- {
- std::vector<std::string> matches =
- dungeon_feature_matches(name);
+ canned_msg(MSG_OK);
+ return false;
+ }
- if (matches.empty())
- {
- const feature_property_type fprop(str_to_fprop(name));
- if (fprop != FPROP_NONE)
- {
- env.pgrid(you.pos()) |= fprop;
- mprf("Set fprops \"%s\" at (%d,%d)",
- name.c_str(), you.pos().x, you.pos().y);
- }
- else
- {
- mprf(MSGCH_DIAGNOSTICS, "No features matching '%s'",
- name.c_str());
- }
- return;
- }
+ if (int feat_num = atoi(specs))
+ {
+ feat = static_cast<dungeon_feature_type>(feat_num);
+ }
+ else
+ {
+ std::string name = lowercase_string(specs);
+ name = replace_all(name, " ", "_");
+ feat = dungeon_feature_by_name(name);
+ if (feat == DNGN_UNSEEN) // no exact match
+ {
+ std::vector<std::string> matches =
+ dungeon_feature_matches(name);
- // Only one possible match, use that.
- if (matches.size() == 1)
+ if (matches.empty())
+ {
+ const feature_property_type fprop(str_to_fprop(name));
+ if (fprop != FPROP_NONE)
{
- name = matches[0];
- feat = dungeon_feature_by_name(name);
+ env.pgrid(you.pos()) |= fprop;
+ mprf("Set fprops \"%s\" at (%d,%d)",
+ name.c_str(), you.pos().x, you.pos().y);
}
- // Multiple matches, list them to wizard
else
{
- std::string prefix = "No exact match for feature '" +
- name + "', possible matches are: ";
-
- // Use mpr_comma_separated_list() because the list
- // might be *LONG*.
- mpr_comma_separated_list(prefix, matches, " and ", ", ",
- MSGCH_DIAGNOSTICS);
- return;
+ mprf(MSGCH_DIAGNOSTICS, "No features matching '%s'",
+ name.c_str());
}
+ return false;
}
- }
- if (feat == DNGN_ENTER_SHOP)
- {
- debug_make_shop();
- return;
+ // Only one possible match, use that.
+ if (matches.size() == 1)
+ {
+ name = matches[0];
+ feat = dungeon_feature_by_name(name);
+ }
+ // Multiple matches, list them to wizard
+ else
+ {
+ std::string prefix = "No exact match for feature '" +
+ name + "', possible matches are: ";
+
+ // Use mpr_comma_separated_list() because the list
+ // might be *LONG*.
+ mpr_comma_separated_list(prefix, matches, " and ", ", ",
+ MSGCH_DIAGNOSTICS);
+ return false;
+ }
}
+ }
+
+ if (mimic && !is_valid_mimic_feat(feat)
+ && !yesno("This isn't a valid feature mimic. Create it anyway? "))
+ {
+ canned_msg(MSG_OK);
+ return false;
+ }
+
+ if (feat == DNGN_ENTER_SHOP)
+ return debug_make_shop(pos);
+
+ if (feat_is_portal(feat))
+ return wizard_create_portal(pos);
#ifdef USE_TILE
- env.tile_flv(you.pos()).special = 0;
- const dungeon_feature_type old_feat = grd(you.pos());
+ env.tile_flv(pos).special = 0;
+ const dungeon_feature_type old_feat = grd(pos);
#endif
- dungeon_terrain_changed(you.pos(), feat, false);
+ dungeon_terrain_changed(pos, feat, false);
#ifdef USE_TILE
- // Update gate tiles, if existing.
- if (feat_is_door(old_feat) || feat_is_door(feat))
- {
- const coord_def left = you.pos() - coord_def(1, 0);
- const coord_def right = you.pos() + coord_def(1, 0);
- if (map_bounds(left) && feat_is_door(grd(left)))
- tile_init_flavour(left);
- if (map_bounds(right) && feat_is_door(grd(right)))
- tile_init_flavour(right);
- }
-#endif
+ // Update gate tiles, if existing.
+ if (feat_is_door(old_feat) || feat_is_door(feat))
+ {
+ const coord_def left = pos - coord_def(1, 0);
+ const coord_def right = pos + coord_def(1, 0);
+ if (map_bounds(left) && feat_is_door(grd(left)))
+ tile_init_flavour(left);
+ if (map_bounds(right) && feat_is_door(grd(right)))
+ tile_init_flavour(right);
}
- else
- canned_msg(MSG_OK);
+#endif
+
+ return true;
}
void wizard_list_branches()
@@ -534,7 +548,7 @@ void debug_make_trap()
mpr("NOTE: Shaft traps aren't valid on this level.");
}
-void debug_make_shop(const coord_def& pos)
+bool debug_make_shop(const coord_def& pos)
{
char requested_shop[80];
int gridch = grd(pos);
@@ -545,7 +559,7 @@ void debug_make_shop(const coord_def& pos)
if (gridch != DNGN_FLOOR)
{
mpr("Insufficient floor-space for new Wal-Mart.");
- return;
+ return false;
}
for (int i = 0; i < MAX_SHOPS; ++i)
@@ -560,13 +574,13 @@ void debug_make_shop(const coord_def& pos)
if (!have_shop_slots)
{
mpr("There are too many shops on this level.");
- return;
+ return false;
}
msgwin_get_line("What kind of shop? ",
requested_shop, sizeof(requested_shop));
if (!*requested_shop)
- return;
+ return false;
strlwr(requested_shop);
std::string s = replace_all_of(requested_shop, "*", "");
@@ -575,7 +589,7 @@ void debug_make_shop(const coord_def& pos)
if (new_shop_type == SHOP_UNASSIGNED || new_shop_type == -1)
{
mprf("Bad shop type: \"%s\"", requested_shop);
- return;
+ return false;
}
representative = !!strchr(requested_shop, '*');
@@ -583,6 +597,7 @@ void debug_make_shop(const coord_def& pos)
place_spec_shop(you.absdepth0, pos, new_shop_type, representative);
link_items();
mprf("Done.");
+ return true;
}
static void debug_load_map_by_name(std::string name)
diff --git a/crawl-ref/source/wiz-dgn.h b/crawl-ref/source/wiz-dgn.h
index 2440141..64c6fc0 100644
--- a/crawl-ref/source/wiz-dgn.h
+++ b/crawl-ref/source/wiz-dgn.h
@@ -10,8 +10,8 @@
#include "player.h"
-void wizard_create_portal(const coord_def& pos = you.pos());
-void wizard_create_feature();
+bool wizard_create_portal(const coord_def& pos = you.pos());
+bool wizard_create_feature(const coord_def& pos = you.pos());
void wizard_list_branches();
void wizard_reveal_traps();
void wizard_map_level();
@@ -22,7 +22,7 @@ void wizard_interlevel_travel();
void wizard_list_levels();
void wizard_recreate_level();
void debug_make_trap(void);
-void debug_make_shop(const coord_def& pos = you.pos());
+bool debug_make_shop(const coord_def& pos = you.pos());
void debug_place_map();
void debug_test_explore();
diff --git a/crawl-ref/source/wiz-mon.cc b/crawl-ref/source/wiz-mon.cc
index 65eefd3..0b7bb0c 100644
--- a/crawl-ref/source/wiz-mon.cc
+++ b/crawl-ref/source/wiz-mon.cc
@@ -67,20 +67,6 @@ void wizard_create_spec_monster(void)
}
}
-static dungeon_feature_type _get_random_stairs()
-{
- return static_cast<dungeon_feature_type>(
- coinflip()
- ? random_range(DNGN_STONE_STAIRS_DOWN_I, DNGN_ESCAPE_HATCH_UP)
- : random_range(DNGN_ENTER_FIRST_BRANCH, DNGN_ENTER_LAST_BRANCH));
-}
-
-static dungeon_feature_type _get_random_fountain()
-{
- return static_cast<dungeon_feature_type>(
- random_range(DNGN_FOUNTAIN_BLUE, DNGN_PERMADRY_FOUNTAIN));
-}
-
// Creates a specific monster by name. Uses the same patterns as
// map definitions.
void wizard_create_spec_monster_name()
@@ -142,28 +128,8 @@ void wizard_create_spec_monster_name()
if (mons_is_feat_mimic(type))
{
- switch (type)
- {
- case MONS_DOOR_MIMIC:
- dungeon_terrain_changed(place, DNGN_CLOSED_DOOR, false);
- break;
- case MONS_PORTAL_MIMIC:
- wizard_create_portal(place);
- break;
- case MONS_STAIR_MIMIC:
- dungeon_terrain_changed(place, _get_random_stairs(), false);
- break;
- case MONS_SHOP_MIMIC:
- debug_make_shop(place);
- break;
- case MONS_FOUNTAIN_MIMIC:
- dungeon_terrain_changed(place, _get_random_fountain(), false);
- break;
- default:
- die("Invalid feature mimic type.");
- }
-
- env.level_map_mask(place) |= MMT_MIMIC;
+ if (wizard_create_feature(place))
+ env.level_map_mask(place) |= MMT_MIMIC;
return;
}
--
Dungeon Crawl Stone Soup
|