diff options
Diffstat (limited to 'crawl-ref/source')
-rw-r--r-- | crawl-ref/source/dat/database/monspeak.txt | 5 | ||||
-rw-r--r-- | crawl-ref/source/describe.cc | 8 | ||||
-rw-r--r-- | crawl-ref/source/directn.cc | 33 | ||||
-rw-r--r-- | crawl-ref/source/enum.h | 9 | ||||
-rw-r--r-- | crawl-ref/source/externs.h | 4 | ||||
-rw-r--r-- | crawl-ref/source/hiscores.cc | 5 | ||||
-rw-r--r-- | crawl-ref/source/mon-util.cc | 45 | ||||
-rw-r--r-- | crawl-ref/source/monspeak.cc | 31 | ||||
-rw-r--r-- | crawl-ref/source/monstuff.cc | 106 | ||||
-rw-r--r-- | crawl-ref/source/output.cc | 6 |
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 { |