diff --git a/crawl-ref/source/describe.cc b/crawl-ref/source/describe.cc index 5967c53bc88..d12d1e9b21b 100644 --- a/crawl-ref/source/describe.cc +++ b/crawl-ref/source/describe.cc @@ -4697,12 +4697,23 @@ static const char* _get_threat_desc(mon_threat_level_type threat) { switch (threat) { - case MTHRT_TRIVIAL: return "harmless"; - case MTHRT_EASY: return "easy"; - case MTHRT_TOUGH: return "dangerous"; - case MTHRT_NASTY: return "extremely dangerous"; - case MTHRT_UNDEF: - default: return "buggily threatening"; + case MTHRT_UNDEF: // ? + case MTHRT_TRIVIAL: return "Minor"; + case MTHRT_EASY: return "Low"; + case MTHRT_TOUGH: return "High"; + case MTHRT_NASTY: return "Lethal"; + default: return "Eggstreme"; + } +} + +static const char* _get_int_desc(mon_intel_type intel) +{ + switch (intel) + { + case I_BRAINLESS: return "Mindless"; + case I_ANIMAL: return "Animal"; + case I_HUMAN: return "Human"; + default: return "Eggplantelligent"; } } @@ -5487,6 +5498,17 @@ static string _monster_stat_description(const monster_info& mi, bool mark_spells const resists_t resist = mi.resists(); _add_resist_desc(resist, result); + // Less important common properties. Arguably should be lower down. + const size_type sz = mi.body_size(); + const string size_desc = sz == SIZE_LITTLE ? "V. Small" : uppercase_first(get_size_adj(sz)); + const int regen_rate = mi.regen_rate(100); + result << "\n"; + result << _padded(make_stringf("Threat: %s", _get_threat_desc(mi.threat)), 16); + result << _padded(make_stringf("Regen: %.2f", regen_rate/100.0f), 16); + result << _padded(make_stringf("Size: %s", size_desc.c_str()), 16); + result << _padded(make_stringf("Int: %s", _get_int_desc(mi.intel())), 16); + result << "See Invis: " << (mi.can_see_invisible() ? "+" : "."); + _add_speed_desc(mi, result); result << "\n\n"; @@ -5580,13 +5602,6 @@ static string _monster_stat_description(const monster_info& mi, bool mark_spells const char* pronoun = mi.pronoun(PRONOUN_SUBJECTIVE); const bool plural = mi.pronoun_plurality(); - if (mi.threat != MTHRT_UNDEF) - { - result << uppercase_first(pronoun) << " " - << conjugate_verb("look", plural) << " " - << _get_threat_desc(mi.threat) << ".\n"; - } - if (mi.has_unusual_items()) { const vector unusual_items = mi.get_unusual_items(); @@ -5642,10 +5657,6 @@ static string _monster_stat_description(const monster_info& mi, bool mark_spells << " cold-blooded and may be slowed by cold attacks.\n"; } - // Seeing invisible. - if (mi.can_see_invisible()) - result << uppercase_first(pronoun) << " can see invisible.\n"; - if (mons_class_flag(mi.type, M_INSUBSTANTIAL)) { result << uppercase_first(pronoun) << " " @@ -5658,19 +5669,6 @@ static string _monster_stat_description(const monster_info& mi, bool mark_spells // Might be better to have some place where players can see holiness & // information about holiness.......? - if (mi.intel() <= I_BRAINLESS) - { - // Matters for Ely. - result << uppercase_first(pronoun) << " " - << conjugate_verb("are", plural) << " mindless.\n"; - } - else if (mi.intel() >= I_HUMAN) - { - // Matters for Yred, Gozag, Zin, TSO, Alistair.... - result << uppercase_first(pronoun) << " " - << conjugate_verb("are", plural) << " intelligent.\n"; - } - if (mi.type == MONS_SHADOW) { // Cf. monster::action_energy() in monster.cc. @@ -5689,25 +5687,6 @@ static string _monster_stat_description(const monster_info& mi, bool mark_spells if (mi.airborne()) result << uppercase_first(pronoun) << " can fly.\n"; - // Unusual regeneration rates. - if (!mi.can_regenerate()) - result << uppercase_first(pronoun) << " cannot regenerate.\n"; - else if (mons_class_fast_regen(mi.type)) - result << uppercase_first(pronoun) << " " - << conjugate_verb("regenerate", plural) << " " - << (mi.type == MONS_PARGHIT ? "astonishingly " - : mi.type == MONS_DEMONIC_CRAWLER ? "very " - : "") - << "quickly.\n"; - - const char* mon_size = get_size_adj(mi.body_size(), true); - if (mon_size) - { - result << uppercase_first(pronoun) << " " - << conjugate_verb("are", plural) << " " - << mon_size << ".\n"; - } - if (in_good_standing(GOD_ZIN, 0) && !mi.pos.origin() && monster_at(mi.pos)) { recite_counts retval; diff --git a/crawl-ref/source/mon-act.cc b/crawl-ref/source/mon-act.cc index 353a9358c8b..8c0a58ca312 100644 --- a/crawl-ref/source/mon-act.cc +++ b/crawl-ref/source/mon-act.cc @@ -151,15 +151,11 @@ static void _monster_regenerate(monster* mons) return; } - if (mons->type == MONS_PARGHIT) - mons->heal(27); // go whoosh - else if (mons->type == MONS_DEMONIC_CRAWLER) - mons->heal(6); // go zoom - else if (mons_class_fast_regen(mons->type) + if (mons_class_fast_regen(mons->type) || mons->has_ench(ENCH_REGENERATION) || _mons_natural_regen_roll(mons)) { - mons->heal(1); + mons->heal(mons_class_regen_amount(mons->type)); } if (mons_is_hepliaklqana_ancestor(mons->type)) diff --git a/crawl-ref/source/mon-info.cc b/crawl-ref/source/mon-info.cc index eb08213b369..04582fd9819 100644 --- a/crawl-ref/source/mon-info.cc +++ b/crawl-ref/source/mon-info.cc @@ -55,7 +55,7 @@ static map trivial_ench_mb_mappings = { { ENCH_SILVER_CORONA, MB_GLOWING }, { ENCH_SLOW, MB_SLOWED }, { ENCH_SICK, MB_SICK }, - { ENCH_FRENZIED, MB_FRENZIED }, + { ENCH_FRENZIED, MB_FRENZIED }, { ENCH_HASTE, MB_HASTED }, { ENCH_MIGHT, MB_STRONG }, { ENCH_CONFUSION, MB_CONFUSED }, @@ -885,6 +885,19 @@ string monster_info::get_max_hp_desc() const return make_stringf("~%d", mhp); } +/// HP regenerated every (scale) turns. +int monster_info::regen_rate(int scale) const +{ + if (!can_regenerate() || is(MB_SICK) /* ? */) + return 0; + if (mons_class_fast_regen(type) || is(MB_REGENERATION) /* ? */) + return mons_class_regen_amount(type) * scale; + + // Duplicates monster::natural_regen_rate. + const int divider = max(((15 - hd) + 2 /*round up*/) / 4, 1); + return min(scale, max(1, hd * scale / (divider * 25))); +} + /** * Calculate some defender-specific effects on an attacker's to-hit. */ diff --git a/crawl-ref/source/mon-info.h b/crawl-ref/source/mon-info.h index 3a5342cfcfa..efcd114a41e 100644 --- a/crawl-ref/source/mon-info.h +++ b/crawl-ref/source/mon-info.h @@ -341,6 +341,7 @@ struct monster_info : public monster_info_base return get_damage_level_string(holi, dam); } string get_max_hp_desc() const; + int regen_rate(int scale) const; inline bool neutral() const { diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index c1dbe06cd76..022c406196c 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -1621,6 +1621,16 @@ bool mons_class_fast_regen(monster_type mc) return mons_class_flag(mc, M_FAST_REGEN); } +int mons_class_regen_amount(monster_type mc) +{ + switch (mc) + { + case MONS_PARGHIT: return 27; + case MONS_DEMONIC_CRAWLER: return 6; + default: return 1; + } +} + /** * Do monsters of the given type ever leave a hide? * diff --git a/crawl-ref/source/mon-util.h b/crawl-ref/source/mon-util.h index 481b7cad462..e5b9c93411b 100644 --- a/crawl-ref/source/mon-util.h +++ b/crawl-ref/source/mon-util.h @@ -301,6 +301,7 @@ bool monster_inherently_flies(const monster &mons); bool mons_class_can_regenerate(monster_type mc); bool mons_can_regenerate(const monster& mon); bool mons_class_fast_regen(monster_type mc); +int mons_class_regen_amount(monster_type mc); int mons_zombie_size(monster_type mc); monster_type mons_zombie_base(const monster& mon); bool mons_class_is_zombified(monster_type mc); diff --git a/crawl-ref/source/monster.cc b/crawl-ref/source/monster.cc index 92ee971bf80..ba0a4a6031a 100644 --- a/crawl-ref/source/monster.cc +++ b/crawl-ref/source/monster.cc @@ -2930,6 +2930,7 @@ bool monster::liquefied_ground() const } // in units of 1/25 hp/turn +// Please update monster_info::regen_rate if you change this. int monster::natural_regen_rate() const { // A HD divider ranging from 3 (at 1 HD) to 1 (at 8 HD). @@ -2944,12 +2945,8 @@ int monster::off_level_regen_rate() const if (!mons_can_regenerate(*this)) return 0; - if (type == MONS_PARGHIT) - return 2700; // whoosh - if (type == MONS_DEMONIC_CRAWLER) - return 600; // zoom if (mons_class_fast_regen(type) || type == MONS_PLAYER_GHOST) - return 100; + return mons_class_regen_amount(type) * 100; // Capped at 0.1 hp/turn. return max(natural_regen_rate() * 4, 10); }