summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crawl-ref/source/dat/database/monspeak.txt5
-rw-r--r--crawl-ref/source/describe.cc8
-rw-r--r--crawl-ref/source/directn.cc33
-rw-r--r--crawl-ref/source/enum.h9
-rw-r--r--crawl-ref/source/externs.h4
-rw-r--r--crawl-ref/source/hiscores.cc5
-rw-r--r--crawl-ref/source/mon-util.cc45
-rw-r--r--crawl-ref/source/monspeak.cc31
-rw-r--r--crawl-ref/source/monstuff.cc106
-rw-r--r--crawl-ref/source/output.cc6
10 files changed, 174 insertions, 78 deletions
diff --git a/crawl-ref/source/dat/database/monspeak.txt b/crawl-ref/source/dat/database/monspeak.txt
index 702ed66bfb..d35abd11da 100644
--- a/crawl-ref/source/dat/database/monspeak.txt
+++ b/crawl-ref/source/dat/database/monspeak.txt
@@ -1078,6 +1078,11 @@ _Agnes_rare_
## END Agnes ##
%%%%
+# In case Blork ends up polymorphed.
+Blork
+
+@Blork the orc@
+%%%%
Blork the orc
@_Blork_common_@
diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc
index 81e6c96234..477f9bddbe 100644
--- a/crawl-ref/source/describe.cc
+++ b/crawl-ref/source/describe.cc
@@ -2406,13 +2406,7 @@ void describe_monsters(const monsters& mons)
std::ostringstream body;
std::string title, prefix, suffix, quote;
- const std::string capname = mons.name(DESC_CAP_A);
- title = capname;
- if (mons.has_base_name())
- {
- title += ", ";
- title += mons.base_name(DESC_NOCAP_THE, false);
- }
+ title = mons.full_name(DESC_CAP_A, true);
std::string db_name = mons.base_name(DESC_DBNAME);
if (mons_is_mimic(mons.type) && mons.type != MONS_GOLD_MIMIC)
diff --git a/crawl-ref/source/directn.cc b/crawl-ref/source/directn.cc
index 335ce7d016..45c079f662 100644
--- a/crawl-ref/source/directn.cc
+++ b/crawl-ref/source/directn.cc
@@ -1581,29 +1581,21 @@ std::string get_terse_square_desc(const coord_def &gc)
{
std::string desc;
const char *unseen_desc = "[unseen terrain]";
- bool is_feature = false;
if (gc == you.pos())
- {
desc = you.your_name;
- }
else if (!map_bounds(gc))
- {
desc = unseen_desc;
- }
else if (!see_grid(gc))
{
if (is_terrain_seen(gc))
{
desc = "[" + feature_description(gc, false, DESC_PLAIN, false)
+ "]";
- is_feature = true;
}
else
- {
desc = unseen_desc;
- }
}
- else if (mgrd(gc) != NON_MONSTER)
+ else if (mgrd(gc) != NON_MONSTER && you.can_see(&menv[mgrd(gc)]))
{
const monsters &mons = menv[mgrd(gc)];
@@ -1614,24 +1606,12 @@ std::string get_terse_square_desc(const coord_def &gc)
desc = item.name(DESC_PLAIN);
}
else
- {
- desc = mons.name(DESC_PLAIN);
- if (mons.has_base_name())
- {
- desc += ", ";
- desc += mons.base_name(DESC_NOCAP_THE);
- }
- }
+ desc = mons.full_name(DESC_PLAIN, true);
}
else if (igrd(gc) != NON_ITEM)
- {
desc = mitm[igrd(gc)].name(DESC_PLAIN);
- }
else
- {
desc = feature_description(gc, false, DESC_PLAIN, false);
- is_feature = true;
- }
return desc;
}
@@ -2899,14 +2879,7 @@ std::string get_monster_desc(const monsters *mon, bool full_desc,
std::string desc = "";
if (mondtype != DESC_NONE)
{
- desc = mon->name(mondtype);
- // For named monsters also mention the base type in the form of
- // "Morbeogh the orc priest", "Sigmund the human zombie".
- // Note that the only difference between DESC_BASENAME and DESC_PLAIN
- // is that basename will ignore mname, so the monster _must_ be named
- // for this to make any sense.
- if (mon->has_base_name())
- desc += " the " + mon->name(DESC_BASENAME);
+ desc = mon->full_name(mondtype);
if (print_attitude)
{
diff --git a/crawl-ref/source/enum.h b/crawl-ref/source/enum.h
index 8762ee968d..d18eea0572 100644
--- a/crawl-ref/source/enum.h
+++ b/crawl-ref/source/enum.h
@@ -2069,9 +2069,16 @@ enum monster_flag_type
// holiness, regardless of its actual type;
// currently used for abominations created
// via Twisted Resurrection
- MF_ENSLAVED_SOUL = 0x8000 // An undead monster soul enslaved by
+ MF_ENSLAVED_SOUL = 0x8000, // An undead monster soul enslaved by
// Yredelemnul's power, or the natural
// monster from whom the soul is taken
+
+ MF_NAME_SUFFIX = 0x10000, // mname is a suffix.
+ MF_NAME_NO_THE = 0x20000, // mname is a prefix with no "the"
+ // between it and the monster type name.
+ MF_NAME_REPLACE = 0x30000, // mname entirely replaces normal monster
+ // name.
+ MF_NAME_MASK = 0x30000
};
// Adding slots breaks saves. YHBW.
diff --git a/crawl-ref/source/externs.h b/crawl-ref/source/externs.h
index 5ffddad96c..301b663592 100644
--- a/crawl-ref/source/externs.h
+++ b/crawl-ref/source/externs.h
@@ -1418,6 +1418,10 @@ public:
// "orc priest".
std::string base_name(description_level_type type,
bool force_visible = false) const;
+ // Full name of the monster. For an orc priest named Arbolt, full_name()
+ // will return "Arbolt the orc priest".
+ std::string full_name(description_level_type type,
+ bool use_comma = false) const;
std::string pronoun(pronoun_type pro, bool force_visible = false) const;
std::string conj_verb(const std::string &verb) const;
std::string hand_name(bool plural, bool *can_plural = NULL) const;
diff --git a/crawl-ref/source/hiscores.cc b/crawl-ref/source/hiscores.cc
index dab6d8a920..bd6fcd7a67 100644
--- a/crawl-ref/source/hiscores.cc
+++ b/crawl-ref/source/hiscores.cc
@@ -813,9 +813,8 @@ void scorefile_entry::init_death_cause(int dam, int dsrc,
death_type == KILLED_BY_SPORE ? DESC_PLAIN : DESC_NOCAP_A;
death_source_name = monster->name(desc, death);
- if (monster->has_base_name())
- death_source_name +=
- ", " + monster->base_name(desc, death);
+ if (death || you.can_see(monster))
+ death_source_name = monster->full_name(desc, true);
if (monster->has_ench(ENCH_SHAPESHIFTER))
death_source_name += " (shapeshifter)";
diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc
index 221ced5137..5d9c0d0fde 100644
--- a/crawl-ref/source/mon-util.cc
+++ b/crawl-ref/source/mon-util.cc
@@ -4922,7 +4922,11 @@ std::string monsters::name(description_level_type desc, bool force_vis) const
if (possessive)
desc = DESC_NOCAP_THE;
- std::string monnam = _str_monam(*this, desc, force_vis);
+ std::string monnam;
+ if ((flags & MF_NAME_MASK) && (force_vis || you.can_see(this)))
+ monnam = full_name(desc);
+ else
+ monnam = _str_monam(*this, desc, force_vis);
return (possessive ? apostrophise(monnam) : monnam);
}
@@ -4940,6 +4944,38 @@ std::string monsters::base_name(description_level_type desc, bool force_vis)
}
}
+std::string monsters::full_name(description_level_type desc,
+ bool use_comma) const
+{
+ std::string title = _str_monam(*this, desc, true);
+
+ if (has_base_name())
+ {
+ const unsigned long flag = flags & MF_NAME_MASK;
+ if (flag == MF_NAME_SUFFIX)
+ {
+ title = base_name(desc, true);
+ title += " ";
+ title += mname;
+ }
+ else if (flag == MF_NAME_NO_THE)
+ {
+ title += " ";
+ title += base_name(DESC_PLAIN, true);
+ }
+ else if (flag == MF_NAME_REPLACE)
+ ;
+ else
+ {
+ if (use_comma)
+ title += ",";
+ title += " ";
+ title += base_name(DESC_NOCAP_THE, true);
+ }
+ }
+ return (title);
+}
+
std::string monsters::pronoun(pronoun_type pro, bool force_visible) const
{
return (mons_pronoun(static_cast<monster_type>(type), pro,
@@ -7796,11 +7832,10 @@ std::string do_mon_str_replacements(const std::string &in_msg,
std::string msg = in_msg;
description_level_type nocap = DESC_NOCAP_THE, cap = DESC_CAP_THE;
- std::string name =
- monster->is_named()? monster->name(DESC_CAP_THE) : "";
-
- if (!name.empty() && player_monster_visible(monster))
+ if (monster->is_named() && player_monster_visible(monster))
{
+ std::string name = monster->name(DESC_CAP_THE);
+
msg = replace_all(msg, "@the_something@", name);
msg = replace_all(msg, "@The_something@", name);
msg = replace_all(msg, "@the_monster@", name);
diff --git a/crawl-ref/source/monspeak.cc b/crawl-ref/source/monspeak.cc
index 059ad562cc..2619563f2b 100644
--- a/crawl-ref/source/monspeak.cc
+++ b/crawl-ref/source/monspeak.cc
@@ -200,6 +200,27 @@ static std::string _player_ghost_speak_str(const monsters *monster,
return msg;
}
+// If the monster was originally a unique which has been polymorphed into
+// a non-unique, is its current monter type capable of using it's old
+// speech?
+static bool _polyd_can_speak(const monsters* monster)
+{
+ // Wizard and priest monsters can always speak.
+ if (mons_class_flag(monster->type, M_ACTUAL_SPELLS | M_PRIEST))
+ return (true);
+
+ // Silent or non-sentient monsters can't use the original speech.
+ if (mons_intel(monster) < I_NORMAL
+ || mons_shouts(monster->type) == S_SILENT)
+ {
+ return (false);
+ }
+
+ // Does it have the proper vocal equipment?
+ const mon_body_shape shape = get_mon_shape(monster);
+ return (shape >= MON_SHAPE_HUMANOID && shape <= MON_SHAPE_NAGA);
+}
+
// Returns true if something is said.
bool mons_speaks(const monsters *monster)
{
@@ -316,7 +337,15 @@ bool mons_speaks(const monsters *monster)
msg = _get_speak_string(prefixes, "pandemonium lord", monster);
}
else
- msg = _get_speak_string(prefixes, monster->name(DESC_PLAIN), monster);
+ {
+ if (!monster->mname.empty() && _polyd_can_speak(monster))
+ msg = _get_speak_string(prefixes, monster->name(DESC_PLAIN),
+ monster);
+
+ if (msg.empty())
+ msg = _get_speak_string(prefixes, monster->base_name(DESC_PLAIN),
+ monster);
+ }
// The exact name brought no results, try monster genus.
if ((msg.empty() || msg == "__NEXT")
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))
{
diff --git a/crawl-ref/source/output.cc b/crawl-ref/source/output.cc
index eb0e98043a..1679e71728 100644
--- a/crawl-ref/source/output.cc
+++ b/crawl-ref/source/output.cc
@@ -1262,11 +1262,7 @@ void monster_pane_info::to_string( int count, std::string& desc,
if (mons_is_mimic(m_mon->type))
out << mons_type_name(m_mon->type, DESC_PLAIN);
else
- {
- out << m_mon->name(DESC_PLAIN);
- if (!(m_mon->mname).empty() && m_mon->type != MONS_PLAYER_GHOST)
- out << " the " << mons_type_name(m_mon->type, DESC_PLAIN);
- }
+ out << m_mon->full_name(DESC_PLAIN);
}
else
{