summaryrefslogtreecommitdiffstats
path: root/crawl-ref/source/monstuff.cc
diff options
context:
space:
mode:
Diffstat (limited to 'crawl-ref/source/monstuff.cc')
-rw-r--r--crawl-ref/source/monstuff.cc106
1 files changed, 80 insertions, 26 deletions
diff --git a/crawl-ref/source/monstuff.cc b/crawl-ref/source/monstuff.cc
index f3fdf530d4..8e21c74c85 100644
--- a/crawl-ref/source/monstuff.cc
+++ b/crawl-ref/source/monstuff.cc
@@ -738,27 +738,49 @@ static bool _slime_pit_unlock_onlevel()
static void _fire_monster_death_event(monsters *monster,
killer_type killer,
- int i)
+ int i, bool polymorph)
{
+ int type = monster->type;
+
+ // Treat whatever the Royal Jelly polymorphed into as if it were still
+ // the Royal Jelly.
+ if (monster->mname == "shaped Royal Jelly")
+ type = MONS_ROYAL_JELLY;
+
// Banished monsters aren't technically dead, so no death event
// for them.
- if (killer != KILL_RESET)
+ if (killer == KILL_RESET)
{
- dungeon_events.fire_event(
- dgn_event(DET_MONSTER_DIED, monster->pos(), 0,
- monster_index(monster), killer));
+ // Give player a hint that banishing the Royal Jelly means the
+ // Slime:6 vaults stay locked.
+ if (type == MONS_ROYAL_JELLY)
+ {
+ if (you.can_see(monster))
+ mpr("You feel a great sense of loss.");
+ else
+ mpr("You feel a great sense of loss, and the brush of the "
+ "Abyss.");
+ }
+ return;
+ }
- if (monster->type == MONS_ROYAL_JELLY)
+ dungeon_events.fire_event(
+ dgn_event(DET_MONSTER_DIED, monster->pos(), 0,
+ monster_index(monster), killer));
+
+ // Don't unlock the Slime:6 vaults if the "death" was actually the
+ // Royal Jelly polymorphing into something else; the player still
+ // has to kill whatever it polymorphed into.
+ if (type == MONS_ROYAL_JELLY && !polymorph)
+ {
+ const level_id target(BRANCH_SLIME_PITS, 6);
+ if (is_existing_level(target))
{
- const level_id target(BRANCH_SLIME_PITS, 6);
- if (is_existing_level(target))
- {
- apply_to_level(
- target,
- true,
- target == level_id::current() ? _slime_pit_unlock_onlevel
- : _slime_pit_unlock_offlevel);
- }
+ apply_to_level(
+ target,
+ true,
+ target == level_id::current() ? _slime_pit_unlock_onlevel
+ : _slime_pit_unlock_offlevel);
}
}
}
@@ -1546,7 +1568,7 @@ void monster_die(monsters *monster, killer_type killer,
_place_monster_corpse(monster, silent);
}
- _fire_monster_death_event(monster, killer, killer_index);
+ _fire_monster_death_event(monster, killer, killer_index, false);
const coord_def mwhere = monster->pos();
if (drop_items)
@@ -1738,6 +1760,9 @@ bool monster_polymorph(monsters *monster, monster_type targetc,
poly_power_type power,
bool force_beh)
{
+ ASSERT(!(monster->flags & MF_TAKING_STAIRS));
+ ASSERT(!(monster->flags & MF_BANISHED) || you.level_type == LEVEL_ABYSS);
+
std::string str_polymon;
int source_power, target_power, relax;
int tries = 1000;
@@ -1820,22 +1845,42 @@ bool monster_polymorph(monsters *monster, monster_type targetc,
// the monster is still a mermaid/siren.
update_beholders(monster, true);
- // Inform listeners that the original monster is gone (and
- // unlock the vaults on Slime:6 if it's the Royal Jelly which
- // was changed).
- _fire_monster_death_event(monster, KILL_MISC, NON_MONSTER);
+ // Inform listeners that the original monster is gone.
+ _fire_monster_death_event(monster, KILL_MISC, NON_MONSTER, true);
// the actual polymorphing:
+ unsigned long flags =
+ monster->flags & ~(MF_INTERESTING | MF_SEEN | MF_ATT_CHANGE_ATTEMPT
+ | MF_WAS_IN_VIEW | MF_BAND_MEMBER
+ | MF_HONORARY_UNDEAD);
+
+ std::string name;
+
+ // Preserve the names of uniques and named monsters.
+ if (!monster->mname.empty())
+ name = monster->mname;
+ else if (mons_is_unique(monster->type))
+ {
+ flags |= MF_INTERESTING;
+
+ name = monster->name(DESC_PLAIN, true);
+ if (monster->type == MONS_ROYAL_JELLY)
+ {
+ name = "shaped Royal Jelly";
+ flags |= MF_NAME_SUFFIX;
+ }
+
+ // "Blork the orc" and similar.
+ const size_t the_pos = name.find(" the ");
+ if (the_pos != std::string::npos)
+ name = name.substr(0, the_pos);
+ }
+
const int old_hp = monster->hit_points;
const int old_hp_max = monster->max_hit_points;
const bool old_mon_caught = mons_is_caught(monster);
const char old_ench_countdown = monster->ench_countdown;
- // deal with mons_sec
- monster->type = targetc;
- monster->base_monster = MONS_PROGRAM_BUG;
- monster->number = 0;
-
mon_enchant abj = monster->get_ench(ENCH_ABJ);
mon_enchant charm = monster->get_ench(ENCH_CHARM);
mon_enchant neutral = monster->get_ench(ENCH_NEUTRAL);
@@ -1844,9 +1889,17 @@ bool monster_polymorph(monsters *monster, monster_type targetc,
mon_enchant summon = monster->get_ench(ENCH_SUMMON);
mon_enchant tp = monster->get_ench(ENCH_TP);
+ // deal with mons_sec
+ monster->type = targetc;
+ monster->base_monster = MONS_PROGRAM_BUG;
+ monster->number = 0;
+
// Note: define_monster() will clear out all enchantments! -- bwr
define_monster( monster_index(monster) );
+ monster->flags = flags;
+ monster->mname = name;
+
monster->add_ench(abj);
monster->add_ench(charm);
monster->add_ench(neutral);
@@ -4500,7 +4553,8 @@ static void _handle_nearby_ability(monsters *monster)
#define MON_SPEAK_CHANCE 21
- if (mons_class_flag(monster->type, M_SPEAKS)
+ if ((mons_class_flag(monster->type, M_SPEAKS)
+ || !monster->mname.empty())
&& (!mons_is_wandering(monster) || monster->attitude == ATT_NEUTRAL)
&& one_chance_in(MON_SPEAK_CHANCE))
{