diff options
author | Nicholas Feinberg <pleasingfung@gmail.com> | 2014-07-13 15:38:23 -0700 |
---|---|---|
committer | Nicholas Feinberg <pleasingfung@gmail.com> | 2014-07-13 17:19:02 -0700 |
commit | d22ebac678fa1c1d0a60048a72ba445e3ed190d1 (patch) | |
tree | a63ccd59b4bb01408be9fc5843c20f2f878e2cd2 | |
parent | 5562ea36cc1ba917da155a9dd93e6bf71d022771 (diff) | |
download | crawl-ref-d22ebac678fa1c1d0a60048a72ba445e3ed190d1.tar.gz crawl-ref-d22ebac678fa1c1d0a60048a72ba445e3ed190d1.zip |
Separate 'permanent' and 'temporary' monster hit dice
As part of a wider scheme to make draining temporary.
48 files changed, 343 insertions, 276 deletions
diff --git a/crawl-ref/source/actor.h b/crawl-ref/source/actor.h index 78c5f2ed82..8d38a1de43 100644 --- a/crawl-ref/source/actor.h +++ b/crawl-ref/source/actor.h @@ -88,6 +88,7 @@ public: // Returns true if the actor is exceptionally well balanced. virtual bool extra_balanced() const = 0; + virtual int get_hit_dice() const = 0; virtual int get_experience_level() const = 0; virtual bool shove(const char* feat_name = "") = 0; diff --git a/crawl-ref/source/art-func.h b/crawl-ref/source/art-func.h index 9cb0083faf..b942a78ba7 100644 --- a/crawl-ref/source/art-func.h +++ b/crawl-ref/source/art-func.h @@ -687,7 +687,7 @@ static void _WYRMBANE_melee_effects(item_def* weapon, actor* attacker, // Since the target will become a DEAD MONSTER if it dies due to the extra // damage to dragons, we need to grab this information now. - int hd = min(defender->as_monster()->hit_dice, 18); + int hd = min(defender->as_monster()->get_experience_level(), 18); string name = defender->name(DESC_THE); if (!mondied) @@ -1131,7 +1131,7 @@ static void _FLAMING_DEATH_melee_effects(item_def* weapon, actor* attacker, napalm_monster( defender->as_monster(), attacker, - min(4, 1 + random2(attacker->get_experience_level())/2)); + min(4, 1 + random2(attacker->get_hit_dice())/2)); } } } diff --git a/crawl-ref/source/attack.cc b/crawl-ref/source/attack.cc index 04aa655d61..db5a5b43a7 100644 --- a/crawl-ref/source/attack.cc +++ b/crawl-ref/source/attack.cc @@ -782,7 +782,7 @@ void attack::chaos_affects_defender() } case CHAOS_MISCAST: { - int level = defender->get_experience_level(); + int level = defender->get_hit_dice(); // At level == 27 there's a 13.9% chance of a level 3 miscast. int level0_chance = level; @@ -1814,7 +1814,7 @@ bool attack::apply_damage_brand(const char *what) (defender->holiness() == MH_NATURAL ? random2(30) : random2(22)); if (mons_class_is_confusable(defender->type) - && hdcheck >= defender->get_experience_level() + && hdcheck >= defender->get_hit_dice() && !one_chance_in(5) && !defender->as_monster()->check_clarity(false)) { diff --git a/crawl-ref/source/attitude-change.cc b/crawl-ref/source/attitude-change.cc index 0708d5d4e5..00f8533279 100644 --- a/crawl-ref/source/attitude-change.cc +++ b/crawl-ref/source/attitude-change.cc @@ -88,7 +88,7 @@ void beogh_follower_convert(monster* mons, bool orc_hit) { mons->flags |= MF_ATT_CHANGE_ATTEMPT; - const int hd = mons->hit_dice; + const int hd = mons->get_experience_level(); if (you.piety >= piety_breakpoint(2) && !player_under_penance() && random2(you.piety / 15) + random2(4 + you.experience_level / 3) @@ -173,7 +173,7 @@ bool yred_slaves_abandon_you() { num_slaves++; - const int hd = mons->hit_dice; + const int hd = mons->get_experience_level(); // During penance, followers get a saving throw. if (random2((you.piety - you.penance[GOD_YREDELEMNUL]) / 18) @@ -231,7 +231,7 @@ bool beogh_followers_abandon_you() && !mons_is_confused(mons) && !mons->cannot_act()) { - const int hd = mons->hit_dice; + const int hd = mons->get_experience_level(); // During penance, followers get a saving throw. if (random2((you.piety - you.penance[GOD_BEOGH]) / 18) diff --git a/crawl-ref/source/beam.cc b/crawl-ref/source/beam.cc index 288a0659f7..b14b8b932a 100644 --- a/crawl-ref/source/beam.cc +++ b/crawl-ref/source/beam.cc @@ -4511,7 +4511,7 @@ static bool _dazzle_monster(monster* mons, actor* act) return false; } - if (x_chance_in_y(95 - mons->hit_dice * 5 , 100)) + if (x_chance_in_y(95 - mons->get_hit_dice() * 5 , 100)) { simple_monster_message(mons, " is dazzled."); mons->add_ench(mon_enchant(ENCH_BLIND, 1, act, 40 + random2(40))); @@ -5372,7 +5372,7 @@ mon_resist_type bolt::apply_enchantment_to_monster(monster* mon) case BEAM_ENSLAVE_SOUL: { - dprf(DIAG_BEAM, "HD: %d; pow: %d", mon->hit_dice, ench_power); + dprf(DIAG_BEAM, "HD: %d; pow: %d", mon->get_hit_dice(), ench_power); if (!mons_can_be_zombified(mon) || mons_intel(mon) < I_NORMAL) return MON_UNAFFECTED; @@ -5733,7 +5733,7 @@ mon_resist_type bolt::apply_enchantment_to_monster(monster* mon) break; const int dur = - random2(div_rand_round(ench_power, mon->hit_dice) + 1) + random2(div_rand_round(ench_power, mon->get_hit_dice()) + 1) * BASELINE_DELAY; mon->add_ench(mon_enchant(ENCH_ANTIMAGIC, 0, agent(), // doesn't matter diff --git a/crawl-ref/source/cloud.cc b/crawl-ref/source/cloud.cc index 68c20a0d4c..4f094282a2 100644 --- a/crawl-ref/source/cloud.cc +++ b/crawl-ref/source/cloud.cc @@ -916,8 +916,8 @@ static int _actor_cloud_resist(const actor *act, const cloud_struct &cloud) static bool _mephitic_cloud_roll(const monster* mons) { const int meph_hd_cap = 21; - return mons->hit_dice >= meph_hd_cap? one_chance_in(50) - : !x_chance_in_y(mons->hit_dice, meph_hd_cap); + return mons->get_hit_dice() >= meph_hd_cap? one_chance_in(50) + : !x_chance_in_y(mons->get_hit_dice(), meph_hd_cap); } // Applies cloud messages and side-effects and returns true if the @@ -1349,7 +1349,7 @@ static bool _mons_avoids_cloud(const monster* mons, const cloud_struct& cloud, if (mons_intel(mons) >= I_ANIMAL && mons->res_poison() < 0) return true; - if (x_chance_in_y(mons->hit_dice - 1, 5)) + if (x_chance_in_y(mons->get_hit_dice() - 1, 5)) return false; if (mons->hit_points >= random2avg(19, 2)) diff --git a/crawl-ref/source/dbg-scan.cc b/crawl-ref/source/dbg-scan.cc index 990da069a9..b822eb86e2 100644 --- a/crawl-ref/source/dbg-scan.cc +++ b/crawl-ref/source/dbg-scan.cc @@ -1419,7 +1419,7 @@ void objstat_record_monster(monster *mons) _record_monster_stat(lev, mons_ind, "MonsXP", exper_value(mons)); _record_monster_stat(lev, mons_ind, "TotalXP", exper_value(mons)); _record_monster_stat(lev, mons_ind, "MonsHP", mons->max_hit_points); - _record_monster_stat(lev, mons_ind, "MonsHD", mons->hit_dice); + _record_monster_stat(lev, mons_ind, "MonsHD", mons->get_experience_level()); // Record chunks/nutrition if monster leaves a corpse. if (chunk_effect != CE_NOCORPSE && mons_weight(mons->type)) { diff --git a/crawl-ref/source/decks.cc b/crawl-ref/source/decks.cc index 07c962cf29..6a23d291d9 100644 --- a/crawl-ref/source/decks.cc +++ b/crawl-ref/source/decks.cc @@ -2339,7 +2339,7 @@ static void _crusade_card(int power, deck_rarity_type rarity) // (though not immunity) check. Specifically, // you can convert Killer Klowns this way. // Might be too good. - if (mi->hit_dice * 35 < random2(power)) + if (mi->get_hit_dice() * 35 < random2(power)) { simple_monster_message(*mi, " is converted."); mi->add_ench(ENCH_CHARM); @@ -2809,7 +2809,8 @@ static void _degeneration_card(int power, deck_rarity_type rarity) } if (mons && - x_chance_in_y((power_level + 1) * 5 + random2(5), mons->hit_dice)) + x_chance_in_y((power_level + 1) * 5 + random2(5), + mons->get_hit_dice())) { effects = true; monster_polymorph(mons, RANDOM_MONSTER, PPT_LESS); diff --git a/crawl-ref/source/effects.cc b/crawl-ref/source/effects.cc index 6e98d0e4cf..cdd57e9058 100644 --- a/crawl-ref/source/effects.cc +++ b/crawl-ref/source/effects.cc @@ -473,7 +473,7 @@ void direct_effect(monster* source, spell_type spell, pbolt.flavour = BEAM_AIR; pbolt.aux_source = "by the air"; - damage_taken = 10 + 2 * source->hit_dice; + damage_taken = 10 + 2 * source->get_hit_dice(); damage_taken = defender->beam_resists(pbolt, damage_taken, false); @@ -497,7 +497,7 @@ void direct_effect(monster* source, spell_type spell, pbolt.flavour = BEAM_WATER; pbolt.aux_source = "by the raging water"; - damage_taken = roll_dice(3, 7 + source->hit_dice); + damage_taken = roll_dice(3, 7 + source->get_hit_dice()); damage_taken = defender->beam_resists(pbolt, damage_taken, false); damage_taken = defender->apply_ac(damage_taken); diff --git a/crawl-ref/source/godabil.cc b/crawl-ref/source/godabil.cc index 871a5bd061..0368c0b881 100644 --- a/crawl-ref/source/godabil.cc +++ b/crawl-ref/source/godabil.cc @@ -707,7 +707,7 @@ bool zin_recite_to_single_monster(const coord_def& where) // Resistance is now based on HD. You can affect up to (30+30)/2 = 30 'power' (HD). int power = (skill_bump(SK_INVOCATIONS, 10) + you.piety * 3 / 2) / 20; // Old recite was mostly deterministic, which is bad. - int resist = mon->get_experience_level() + random2(6); + int resist = mon->get_hit_dice() + random2(6); int check = power - resist; // We abort if we didn't *beat* their HD - but first we might get a cute message. @@ -1113,7 +1113,7 @@ static void _zin_saltify(monster* mon) const monster_type pillar_type = mons_is_zombified(mon) ? mons_zombie_base(mon) : mons_species(mon->type); - const int hd = mon->get_experience_level(); + const int hd = mon->get_hit_dice(); simple_monster_message(mon, " is turned into a pillar of salt by the wrath of Zin!"); @@ -1773,12 +1773,11 @@ void yred_make_enslaved_soul(monster* mon, bool force_hostile) // the proper stats from it. define_zombie(mon, mon->type, MONS_SPECTRAL_THING); - // If the original monster has been drained or levelled up, its HD - // might be different from its class HD, in which case its HP should - // be rerolled to match. - if (mon->hit_dice != orig.hit_dice) + // If the original monster has been levelled up, its HD might be different + // from its class HD, in which case its HP should be rerolled to match. + if (mon->get_experience_level() != orig.get_experience_level()) { - mon->hit_dice = max(orig.hit_dice, 1); + mon->set_hit_dice(max(orig.get_experience_level(), 1)); roll_zombie_hp(mon); } @@ -3138,7 +3137,8 @@ void fedhas_evolve_flora() if (plant->type == MONS_HYPERACTIVE_BALLISTOMYCETE) plant->add_ench(ENCH_EXPLODING); - plant->hit_dice += you.skill_rdiv(SK_INVOCATIONS); + plant->set_hit_dice(plant->get_experience_level() + + you.skill_rdiv(SK_INVOCATIONS)); if (upgrade.fruit_cost) { @@ -3215,7 +3215,8 @@ void cheibriados_time_bend(int pow) monster* mon = monster_at(*ai); if (mon && !mon->is_stationary()) { - int res_margin = roll_dice(mon->hit_dice, 3) - random2avg(pow, 2); + int res_margin = roll_dice(mon->get_hit_dice(), 3) + - random2avg(pow, 2); if (res_margin > 0) { mprf("%s%s", @@ -3671,11 +3672,11 @@ monster* shadow_monster(bool equip) | MF_WAS_IN_VIEW | MF_HARD_RESET | MF_ACTUAL_SPELLS; mon->hit_points = you.hp; - mon->hit_dice = min(27, max(1, + mon->set_hit_dice(min(27, max(1, you.skill_rdiv(wpn_index != NON_ITEM ? melee_skill(mitm[wpn_index]) : SK_UNARMED_COMBAT, 10, 20) - + you.skill_rdiv(SK_FIGHTING, 10, 20))); + + you.skill_rdiv(SK_FIGHTING, 10, 20)))); mon->set_position(you.pos()); mon->mid = MID_PLAYER; mon->inv[MSLOT_WEAPON] = wpn_index; @@ -3769,9 +3770,9 @@ void dithmenos_shadow_spell(bolt* orig_beam, spell_type spell) return; // Don't let shadow spells get too powerful. - mon->hit_dice = max(1, - min(3 * spell_difficulty(spell), - you.experience_level) / 2); + mon->set_hit_dice(max(1, + min(3 * spell_difficulty(spell), + you.experience_level) / 2)); mon->target = target; if (actor_at(target)) diff --git a/crawl-ref/source/godcompanions.cc b/crawl-ref/source/godcompanions.cc index 9b655ebed3..a8c83aed14 100644 --- a/crawl-ref/source/godcompanions.cc +++ b/crawl-ref/source/godcompanions.cc @@ -117,7 +117,8 @@ void populate_offlevel_recall_list(vector<pair<mid_t, int> > &recall_list) if (comp->level.branch == BRANCH_ABYSS) continue; - pair<mid_t, int> p = make_pair(mid, comp->mons.mons.hit_dice); + pair<mid_t, int> p = make_pair(mid, + comp->mons.mons.get_experience_level()); recall_list.push_back(p); } } diff --git a/crawl-ref/source/godconduct.cc b/crawl-ref/source/godconduct.cc index 2c4a9d6c39..ead27fdf53 100644 --- a/crawl-ref/source/godconduct.cc +++ b/crawl-ref/source/godconduct.cc @@ -1179,7 +1179,7 @@ void set_attack_conducts(god_conduct_trigger conduct[3], const monster* mon, } if (mon->is_holy() && !mon->is_illusion()) - conduct[2].set(DID_ATTACK_HOLY, mon->hit_dice, known, mon); + conduct[2].set(DID_ATTACK_HOLY, mon->get_experience_level(), known, mon); _first_attack_conduct.set(midx); } diff --git a/crawl-ref/source/godprayer.cc b/crawl-ref/source/godprayer.cc index 3171e77cbd..75b89699dc 100644 --- a/crawl-ref/source/godprayer.cc +++ b/crawl-ref/source/godprayer.cc @@ -636,7 +636,7 @@ static piety_gain_t _sac_corpse(const item_def& item) const monsterentry *m = get_monster_data(dummy.type); int hp = hit_points(hd, m->hpdice[1], m->hpdice[2]) + m->hpdice[3]; - dummy.hit_dice = hd; + dummy.set_hit_dice(hd); dummy.max_hit_points = hp; } int gain = get_fuzzied_monster_difficulty(&dummy); diff --git a/crawl-ref/source/godwrath.cc b/crawl-ref/source/godwrath.cc index acc37b75f5..e1b9a20e5d 100644 --- a/crawl-ref/source/godwrath.cc +++ b/crawl-ref/source/godwrath.cc @@ -466,7 +466,7 @@ static bool _makhleb_retribution() avatar->mname = "the fury of Makhleb"; avatar->flags |= MF_NAME_REPLACE; avatar->attitude = ATT_HOSTILE; - avatar->hit_dice = you.experience_level; + avatar->set_hit_dice(you.experience_level); spell_type spell = SPELL_NO_SPELL; const int severity = min(random_range(you.experience_level / 14, @@ -1020,7 +1020,7 @@ static bool _vehumet_retribution() avatar->mname = "the wrath of Vehumet"; avatar->flags |= MF_NAME_REPLACE; avatar->attitude = ATT_HOSTILE; - avatar->hit_dice = you.experience_level; + avatar->set_hit_dice(you.experience_level); spell_type spell = SPELL_NO_SPELL; const int severity = min(random_range(1 + you.experience_level / 5, diff --git a/crawl-ref/source/l_mons.cc b/crawl-ref/source/l_mons.cc index 4184a0c881..1860b6c93e 100644 --- a/crawl-ref/source/l_mons.cc +++ b/crawl-ref/source/l_mons.cc @@ -145,7 +145,7 @@ LUANAMEFN(mbase_name, mons->base_name(dtype, true)) MDEF(hd) { - PLUARET(number, mons->hit_dice); + PLUARET(number, mons->get_hit_dice()); } MDEF(targetx) diff --git a/crawl-ref/source/melee_attack.cc b/crawl-ref/source/melee_attack.cc index 2a38ecca36..22f2895f44 100644 --- a/crawl-ref/source/melee_attack.cc +++ b/crawl-ref/source/melee_attack.cc @@ -1113,7 +1113,7 @@ void melee_attack::player_aux_setup(unarmed_attack_type atk) { //Change formula to fangs_level*2 + 2*XL/3 aux_damage -= str_bite_damage; - aux_damage += div_rand_round(2 * you.get_experience_level(), 3); + aux_damage += div_rand_round(2 * you.get_hit_dice(), 3); damage_brand = SPWPN_ANTIMAGIC; } @@ -1923,7 +1923,7 @@ bool melee_attack::player_monattk_hit_effects() if (stab_attempt && stab_bonus > 0 && weapon && weapon->base_type == OBJ_WEAPONS && weapon->sub_type == WPN_CLUB - && damage_done + special_damage > random2(defender->get_experience_level()) + && damage_done + special_damage > random2(defender->get_hit_dice()) && defender->alive() && !defender->as_monster()->has_ench(ENCH_CONFUSION) && mons_class_is_confusable(defender->type)) @@ -2662,8 +2662,8 @@ bool melee_attack::mons_do_poison() if (attk_flavour == AF_POISON_STRONG) { - amount = random_range(attacker->get_experience_level() * 11 / 3, - attacker->get_experience_level() * 13 / 2); + amount = random_range(attacker->get_hit_dice() * 11 / 3, + attacker->get_hit_dice() * 13 / 2); if (defender->res_poison() > 0 && defender->has_lifeforce()) { @@ -2673,8 +2673,8 @@ bool melee_attack::mons_do_poison() } else { - amount = random_range(attacker->get_experience_level() * 2, - attacker->get_experience_level() * 4); + amount = random_range(attacker->get_hit_dice() * 2, + attacker->get_hit_dice() * 4); } if (!defender->poison(attacker, amount, force)) @@ -2718,7 +2718,7 @@ void melee_attack::mons_do_napalm() napalm_monster( defender->as_monster(), attacker, - min(4, 1 + random2(attacker->get_experience_level())/2)); + min(4, 1 + random2(attacker->get_hit_dice())/2)); } } } @@ -2914,8 +2914,8 @@ void melee_attack::mons_apply_attack_flavour() break; case AF_FIRE: - base_damage = attacker->get_experience_level() - + random2(attacker->get_experience_level()); + base_damage = attacker->get_hit_dice() + + random2(attacker->get_hit_dice()); special_damage = resist_adjust_damage(defender, BEAM_FIRE, @@ -2937,8 +2937,8 @@ void melee_attack::mons_apply_attack_flavour() break; case AF_COLD: - base_damage = attacker->get_experience_level() - + random2(2 * attacker->get_experience_level()); + base_damage = attacker->get_hit_dice() + + random2(2 * attacker->get_hit_dice()); special_damage = resist_adjust_damage(defender, BEAM_COLD, @@ -2961,8 +2961,8 @@ void melee_attack::mons_apply_attack_flavour() break; case AF_ELEC: - base_damage = attacker->get_experience_level() - + random2(attacker->get_experience_level() / 2); + base_damage = attacker->get_hit_dice() + + random2(attacker->get_hit_dice() / 2); special_damage = resist_adjust_damage(defender, @@ -3045,7 +3045,9 @@ void melee_attack::mons_apply_attack_flavour() if (defender->is_unbreathing()) break; - if (--(attacker->as_monster()->hit_dice) <= 0) + monster *attkmon = attacker->as_monster(); + attkmon->set_hit_dice(attkmon->get_experience_level() - 1); + if (attkmon->get_hit_dice() <= 0) attacker->as_monster()->suicide(); if (defender_visible) @@ -3060,7 +3062,7 @@ void melee_attack::mons_apply_attack_flavour() || (damage_done > 2 && one_chance_in(3))) { defender->confuse(attacker, - 1 + random2(3+attacker->get_experience_level())); + 1 + random2(3+attacker->get_hit_dice())); } break; @@ -3085,8 +3087,8 @@ void melee_attack::mons_apply_attack_flavour() if (attacker->type == MONS_RED_WASP || one_chance_in(3)) { - int dmg = random_range(attacker->get_experience_level() * 3 / 2, - attacker->get_experience_level() * 5 / 2); + int dmg = random_range(attacker->get_hit_dice() * 3 / 2, + attacker->get_hit_dice() * 5 / 2); defender->poison(attacker, dmg); } @@ -3160,7 +3162,7 @@ void melee_attack::mons_apply_attack_flavour() break; case AF_ANTIMAGIC: - antimagic_affects_defender(attacker->get_experience_level() * 12); + antimagic_affects_defender(attacker->get_hit_dice() * 12); if (mons_genus(attacker->type) == MONS_VINE_STALKER && attacker->is_monster()) @@ -3250,8 +3252,8 @@ void melee_attack::mons_apply_attack_flavour() if (attacker->type == MONS_FIRE_VORTEX) attacker->as_monster()->suicide(-10); - special_damage = (attacker->get_experience_level() * 3 / 2 - + random2(attacker->get_experience_level())); + special_damage = (attacker->get_hit_dice() * 3 / 2 + + random2(attacker->get_hit_dice())); special_damage = defender->apply_ac(special_damage, 0, AC_HALF); special_damage = resist_adjust_damage(defender, BEAM_FIRE, @@ -3329,8 +3331,8 @@ void melee_attack::mons_apply_attack_flavour() if (defender->res_water_drowning() <= 0) { - special_damage = attacker->get_experience_level() * 3 / 4 - + random2(attacker->get_experience_level() * 3 / 4); + special_damage = attacker->get_hit_dice() * 3 / 4 + + random2(attacker->get_hit_dice() * 3 / 4); special_damage_flavour = BEAM_WATER; if (needs_message) @@ -3345,8 +3347,8 @@ void melee_attack::mons_apply_attack_flavour() break; case AF_FIREBRAND: - base_damage = attacker->get_experience_level() - + random2(attacker->get_experience_level()); + base_damage = attacker->get_hit_dice() + + random2(attacker->get_hit_dice()); special_damage = resist_adjust_damage(defender, BEAM_FIRE, @@ -3514,8 +3516,8 @@ void melee_attack::tendril_disarm() && adjacent(you.pos(), mon->pos()) && you.can_see(mon) && one_chance_in(5) - && (random2(you.dex()) > (mons_class_flag(mon->type, M_FIGHTER)) ? mon->hit_dice * 1.5 : mon->hit_dice - || random2(you.strength()) > (mons_class_flag(mon->type, M_FIGHTER)) ? mon->hit_dice * 1.5 : mon->hit_dice) + && (random2(you.dex()) > (mons_class_flag(mon->type, M_FIGHTER)) ? mon->get_hit_dice() * 1.5 : mon->get_hit_dice() + || random2(you.strength()) > (mons_class_flag(mon->type, M_FIGHTER)) ? mon->get_hit_dice() * 1.5 : mon->get_hit_dice()) && !mons_wpn->cursed()) { mprf("Your tendrils lash around %s %s and pull it to the ground!", @@ -3950,7 +3952,7 @@ int melee_attack::calc_mon_to_hit_base() const bool fighter = attacker->is_monster() && attacker->as_monster()->is_fighter(); const int hd_mult = fighter ? 25 : 15; - return 18 + attacker->get_experience_level() * hd_mult / 10; + return 18 + attacker->get_hit_dice() * hd_mult / 10; } /** diff --git a/crawl-ref/source/mon-abil.cc b/crawl-ref/source/mon-abil.cc index fe4ff0b71d..7a7fdfa4c9 100644 --- a/crawl-ref/source/mon-abil.cc +++ b/crawl-ref/source/mon-abil.cc @@ -321,8 +321,8 @@ static void _merge_ench_durations(monster* initial, monster* merge_to, bool useh { mon_enchant_list::iterator i; - int initial_count = usehd ? initial->hit_dice : initial->number; - int merge_to_count = usehd ? merge_to->hit_dice : merge_to->number; + int initial_count = usehd ? initial->get_hit_dice() : initial->number; + int merge_to_count = usehd ? merge_to->get_hit_dice() : merge_to->number; int total_count = initial_count + merge_to_count; for (i = initial->enchantments.begin(); @@ -416,7 +416,7 @@ static monster* _do_split(monster* thing, coord_def & target) thing->number -= split_off; new_slime->number = split_off; - new_slime->hit_dice = thing->hit_dice; + new_slime->set_hit_dice(thing->get_experience_level()); _stats_from_blob_count(thing, max_per_blob, current_per_blob); _stats_from_blob_count(new_slime, max_per_blob, current_per_blob); @@ -457,8 +457,8 @@ static void _lose_turn(monster* mons, bool has_gone) // abomination. static bool _do_merge_crawlies(monster* crawlie, monster* merge_to) { - const int orighd = merge_to->hit_dice; - int addhd = crawlie->hit_dice; + const int orighd = merge_to->get_experience_level(); + int addhd = crawlie->get_experience_level(); // Abomination is fully healed. if (merge_to->type == MONS_ABOMINATION_LARGE @@ -536,7 +536,7 @@ static bool _do_merge_crawlies(monster* crawlie, monster* merge_to) change_monster_type(merge_to, new_type); // Combine enchantment durations (weighted by original HD). - merge_to->hit_dice = orighd; + merge_to->set_hit_dice(orighd); _merge_ench_durations(crawlie, merge_to, true); init_abomination(merge_to, newhd); @@ -1149,7 +1149,7 @@ static int _battle_cry(monster* chief, battlecry_type type) && chief->can_see(foe) && coinflip()) { - const int level = chief->hit_dice > 12? 2 : 1; + const int level = chief->get_hit_dice() > 12? 2 : 1; vector<monster* > seen_affected; for (monster_near_iterator mi(chief, LOS_NO_TRANS); mi; ++mi) { @@ -1160,7 +1160,7 @@ static int _battle_cry(monster* chief, battlecry_type type) && !mi->has_ench(ENCH_MIGHT) && !mi->cannot_move() && !mi->confused() - && (mi->hit_dice < chief->hit_dice + && (mi->get_hit_dice() < chief->get_hit_dice() || type == BATTLECRY_CHERUB_HYMN)) { mon_enchant ench = mi->get_ench(battlecry); @@ -1850,7 +1850,7 @@ static bool _lost_soul_teleport(monster* mons) { if (_lost_soul_affectable(*mi) && mons_aligned(mons, *mi)) { - mon_quality m(*mi, min(mi->hit_dice, 18) + random2(8)); + mon_quality m(*mi, min(mi->get_experience_level(), 18) + random2(8)); candidates.push_back(m); } } @@ -1906,9 +1906,9 @@ static bool _worthy_sacrifice(monster* soul, const monster* target) --count; } - return count <= -1 || target->hit_dice > 9 - || x_chance_in_y(target->hit_dice * target->hit_dice * target->hit_dice, - 1200); + const int target_hd = target->get_experience_level(); + return count <= -1 || target_hd > 9 + || x_chance_in_y(target_hd * target_hd * target_hd, 1200); } bool lost_soul_revive(monster* mons) @@ -3241,10 +3241,10 @@ void siren_song(monster* mons) if (*mi != mons && mons_aligned(mons, *mi) && !mons_is_firewood(*mi) && mi->type != MONS_DROWNED_SOUL) { - ally_hd += mi->hit_dice; + ally_hd += mi->get_experience_level(); } } - if (ally_hd > mons->hit_dice) + if (ally_hd > mons->get_experience_level()) { if (mons->props.exists("siren_call")) { @@ -3298,7 +3298,7 @@ void siren_song(monster* mons) // Scale down drowned soul damage for low level sirens if (soul) - soul->hit_dice = mons->hit_dice; + soul->set_hit_dice(mons->get_hit_dice()); } } } @@ -3451,7 +3451,7 @@ bool mon_special_ability(monster* mons, bolt & beem) beem.name = "bolt of electricity"; beem.aux_source = "bolt of electricity"; beem.range = 8; - beem.damage = dice_def(3, 3 + mons->hit_dice); + beem.damage = dice_def(3, 3 + mons->get_hit_dice()); beem.hit = 35; beem.colour = LIGHTCYAN; beem.glyph = dchar_glyph(DCHAR_FIRED_ZAP); @@ -3489,7 +3489,7 @@ bool mon_special_ability(monster* mons, bolt & beem) if (mons->type == MONS_OKLOB_PLANT) { // reduced chance in zotdef - spit = x_chance_in_y(mons->hit_dice, + spit = x_chance_in_y(mons->get_hit_dice(), crawl_state.game_is_zotdef() ? 40 : 30); } if (mons->type == MONS_OKLOB_SAPLING) @@ -3750,7 +3750,7 @@ bool mon_special_ability(monster* mons, bolt & beem) if (mons_genus(mons->type) == MONS_CRAB) { beem.is_big_cloud = true; - beem.damage = dice_def(1, (mons->hit_dice*3)/2); + beem.damage = dice_def(1, (mons->get_hit_dice()*3)/2); } // Fire tracer. @@ -3850,7 +3850,7 @@ bool mon_special_ability(monster* mons, bolt & beem) // Once mesmerised by a particular monster, you cannot resist // anymore. if (!already_mesmerised - && (you.check_res_magic(mons->hit_dice * 22 / 3 + 15) > 0 + && (you.check_res_magic(mons->get_hit_dice() * 22 / 3 + 15) > 0 || you.clarity()) || you.duration[DUR_MESMERISE_IMMUNE]) { @@ -4120,7 +4120,7 @@ bool mon_special_ability(monster* mons, bolt & beem) if (foe && mons->can_see(foe) && one_chance_in(4)) { simple_monster_message(mons, " exhales a fierce blast of wind!"); - wind_blast(mons, 12 * mons->hit_dice, foe->pos()); + wind_blast(mons, 12 * mons->get_hit_dice(), foe->pos()); mon_enchant breath_timeout = mon_enchant(ENCH_BREATH_WEAPON, 1, mons, (4 + random2(9)) * 10); @@ -4305,7 +4305,7 @@ bool mon_special_ability(monster* mons, bolt & beem) if (!victim) break; used = _do_throw(mons, actor_by_mid(throw_choice), - mons->hit_dice * 4); + mons->get_hit_dice() * 4); } break; @@ -4419,7 +4419,7 @@ void mon_nearby_ability(monster* mons) interrupt_activity(AI_MONSTER_ATTACKS, mons); } - int res_margin = foe->check_res_magic((mons->hit_dice * 5) + int res_margin = foe->check_res_magic((mons->get_hit_dice() * 5) * confuse_power); if (res_margin > 0) { diff --git a/crawl-ref/source/mon-act.cc b/crawl-ref/source/mon-act.cc index 0738645d39..949493ee6d 100644 --- a/crawl-ref/source/mon-act.cc +++ b/crawl-ref/source/mon-act.cc @@ -79,6 +79,29 @@ static spell_type _map_wand_to_mspell(wand_type kind); // [dshaligram] Doesn't need to be extern. static coord_def mmov; +/** + * Get the monster's "hit dice". + * + * @return The monster's HD. + */ +int monster::get_hit_dice() const +{ + const int base_hd = get_experience_level(); + //TODO: add the ench! + return base_hd; +} + +/** + * Get the monster's "experience level" - their hit dice, unmodified by + * temporary enchantments (draining). + * + * @return The monster's XL. + */ +int monster::get_experience_level() const +{ + return hit_dice; +} + static const coord_def mon_compass[8] = { coord_def(-1,-1), coord_def(0,-1), coord_def(1,-1), coord_def(1,0), @@ -1098,7 +1121,7 @@ static bool _setup_wand_beam(bolt& beem, monster* mons) return false; // set up the beam - int power = 30 + mons->hit_dice; + int power = 30 + mons->get_hit_dice(); bolt theBeam = mons_spell_beam(mons, mzap, power); beem = _generate_item_beem(beem, theBeam, mons); @@ -2727,7 +2750,7 @@ static bool _jelly_divide(monster* parent) if (!mons_class_flag(parent->type, M_SPLITS)) return false; - const int reqd = max(parent->hit_dice * 8, 50); + const int reqd = max(parent->get_experience_level() * 8, 50); if (parent->hit_points < reqd) return false; diff --git a/crawl-ref/source/mon-cast.cc b/crawl-ref/source/mon-cast.cc index f2e8b3fa4f..2471cd3117 100644 --- a/crawl-ref/source/mon-cast.cc +++ b/crawl-ref/source/mon-cast.cc @@ -744,7 +744,7 @@ bolt mons_spell_beam(monster* mons, spell_type spell_cast, int power, beam.damage = dice_def(3, 2 + (power / 30)); // Natural ability, so don't use spell_hd here - beam.hit = 20 + (3 * mons->hit_dice); + beam.hit = 20 + (3 * mons->get_hit_dice()); beam.flavour = BEAM_ACID; break; @@ -825,7 +825,7 @@ bolt mons_spell_beam(monster* mons, spell_type spell_cast, int power, beam.name = "blast of flame"; beam.aux_source = "blast of fiery breath"; beam.short_name = "flames"; - beam.damage = dice_def(3, (mons->hit_dice * 2)); + beam.damage = dice_def(3, (mons->get_hit_dice() * 2)); beam.colour = RED; beam.hit = 30; beam.flavour = BEAM_FIRE; @@ -835,7 +835,7 @@ bolt mons_spell_beam(monster* mons, spell_type spell_cast, int power, case SPELL_CHAOS_BREATH: beam.name = "blast of chaos"; beam.aux_source = "blast of chaotic breath"; - beam.damage = dice_def(3, (mons->hit_dice * 2)); + beam.damage = dice_def(3, (mons->get_hit_dice() * 2)); beam.colour = ETC_RANDOM; beam.hit = 30; beam.flavour = BEAM_CHAOS; @@ -846,7 +846,7 @@ bolt mons_spell_beam(monster* mons, spell_type spell_cast, int power, beam.name = "blast of cold"; beam.aux_source = "blast of icy breath"; beam.short_name = "frost"; - beam.damage = dice_def(3, (mons->hit_dice * 2)); + beam.damage = dice_def(3, (mons->get_hit_dice() * 2)); beam.colour = WHITE; beam.hit = 30; beam.flavour = BEAM_COLD; @@ -855,7 +855,7 @@ bolt mons_spell_beam(monster* mons, spell_type spell_cast, int power, case SPELL_HOLY_BREATH: beam.name = "blast of cleansing flame"; - beam.damage = dice_def(3, (mons->hit_dice * 2)); + beam.damage = dice_def(3, (mons->get_hit_dice() * 2)); beam.colour = ETC_HOLY; beam.flavour = BEAM_HOLY; beam.hit = 18 + power / 25; @@ -864,7 +864,7 @@ bolt mons_spell_beam(monster* mons, spell_type spell_cast, int power, break; case SPELL_DRACONIAN_BREATH: - beam.damage = dice_def(3, (mons->hit_dice * 2)); + beam.damage = dice_def(3, (mons->get_hit_dice() * 2)); beam.hit = 30; beam.is_beam = true; break; @@ -1475,7 +1475,7 @@ static bool _valid_blink_away_ally(const monster* caster, const monster* target, static bool _valid_druids_call_target(const monster* caller, const monster* callee) { return mons_aligned(caller, callee) && mons_is_beast(callee->type) - && callee->hit_dice <= 20 + && callee->get_experience_level() <= 20 && !callee->is_shapeshifter() && !caller->see_cell(callee->pos()) && mons_habitat(callee) != HT_WATER @@ -2214,7 +2214,7 @@ static bool _should_recall(monster* caller) if (*mi != caller && caller->can_see(*mi) && mons_aligned(caller, *mi) && !mons_is_firewood(*mi)) { - ally_hd += mi->hit_dice; + ally_hd += mi->get_experience_level(); } } return 25 + roll_dice(2, 22) > ally_hd; @@ -2438,8 +2438,9 @@ static void _cast_druids_call(const monster* mon) shuffle_array(mon_list); const actor* target = mon->get_foe(); - const int num = min((int)mon_list.size(), mon->hit_dice > 10 ? random_range(2, 3) - : random_range(1, 2)); + const int num = min((int)mon_list.size(), + mon->get_experience_level() > 10 ? random_range(2, 3) + : random_range(1, 2)); for (int i = 0; i < num; ++i) _place_druids_call_beast(mon, mon_list[i], target); @@ -2633,14 +2634,14 @@ static bool _trace_los(monster* agent, bool (*vulnerable)(actor*)) tracer.friend_info.count++; tracer.friend_info.power += ai->is_player() ? you.experience_level - : ai->as_monster()->hit_dice; + : ai->as_monster()->get_experience_level(); } else { tracer.foe_info.count++; tracer.foe_info.power += ai->is_player() ? you.experience_level - : ai->as_monster()->hit_dice; + : ai->as_monster()->get_experience_level(); } } return mons_should_fire(tracer); @@ -2890,7 +2891,7 @@ bool handle_mon_spell(monster* mons, bolt &beem) } // Servitors never fail to (try) to cast a spell else if (mons->type != MONS_SPELLFORGED_SERVITOR - && random2(200) > mons->hit_dice + 50) + && random2(200) > mons->get_hit_dice() + 50) { return false; } @@ -3513,7 +3514,7 @@ static int _monster_abjure_target(monster* target, int pow, bool actual) bool shielded = false; if (you_worship(GOD_SHINING_ONE)) { - pow = pow * (30 - target->hit_dice) / 30; + pow = pow * (30 - target->get_hit_dice()) / 30; if (pow < duration) { simple_god_message(" protects your fellow warrior from evil " @@ -4753,7 +4754,7 @@ void mons_cast(monster* mons, bolt &pbolt, spell_type spell_cast, MSGCH_MONSTER_SPELL); // Not spell_hd(spell_cast); this is an invocation const int dur = BASELINE_DELAY - * min(5 + roll_dice(2, (mons->hit_dice * 10) / 3 + 1), 100); + * min(5 + roll_dice(2, (mons->get_hit_dice() * 10) / 3 + 1), 100); mons->add_ench(mon_enchant(ENCH_RAISED_MR, 0, mons, dur)); mons->add_ench(mon_enchant(ENCH_REGENERATION, 0, mons, dur)); dprf("Trog's Hand cast (dur: %d aut)", dur); @@ -5117,12 +5118,15 @@ void mons_cast(monster* mons, bolt &pbolt, spell_type spell_cast, case SPELL_BROTHERS_IN_ARMS: { // Invocation; don't use spell_hd - const int power = (mons->hit_dice * 20)+ random2(mons->hit_dice * 5) - random2(mons->hit_dice * 5); + const int power = (mons->get_hit_dice() * 20) + + random2(mons->get_hit_dice() * 5) + - random2(mons->get_hit_dice() * 5); monster_type to_summon; if (mons->type == MONS_SPRIGGAN_BERSERKER) { - monster_type berserkers[] = { MONS_POLAR_BEAR, MONS_ELEPHANT, MONS_DEATH_YAK }; + monster_type berserkers[] = { MONS_POLAR_BEAR, MONS_ELEPHANT, + MONS_DEATH_YAK }; to_summon = RANDOM_ELEMENT(berserkers); } else diff --git a/crawl-ref/source/mon-chimera.cc b/crawl-ref/source/mon-chimera.cc index b895f259c0..361546ba2b 100644 --- a/crawl-ref/source/mon-chimera.cc +++ b/crawl-ref/source/mon-chimera.cc @@ -177,7 +177,7 @@ void ghost_demon::_apply_chimera_part(monster* mon, monster_type part, ac = dummy.ac; ev = dummy.ev; max_hp = dummy.max_hit_points; - xl = dummy.hit_dice; + xl = dummy.get_hit_dice(); // Copy all spells from first part for (int n = 0; n < NUM_MONSTER_SPELL_SLOTS; ++n) spells[n] = dummy.spells[n]; diff --git a/crawl-ref/source/mon-death.cc b/crawl-ref/source/mon-death.cc index a67f6773a8..dc90afe3fe 100644 --- a/crawl-ref/source/mon-death.cc +++ b/crawl-ref/source/mon-death.cc @@ -137,7 +137,7 @@ monster_type fill_out_corpse(const monster* mons, if (mons) { - corpse.props[MONSTER_HIT_DICE] = short(mons->hit_dice); + corpse.props[MONSTER_HIT_DICE] = short(mons->get_experience_level()); corpse.props[MONSTER_NUMBER] = short(mons->number); // XXX: Appears to be a safe conversion? corpse.props[MONSTER_MID] = int(mons->mid); @@ -315,20 +315,18 @@ static void _beogh_spread_experience(int exp) for (monster_near_iterator mi(&you); mi; ++mi) { if (is_orcish_follower(*mi)) - total_hd += mi->hit_dice; + total_hd += mi->get_experience_level(); } - if (total_hd > 0) - { - for (monster_near_iterator mi(&you); mi; ++mi) + if (total_hd <= 0) + return; + + for (monster_near_iterator mi(&you); mi; ++mi) + if (is_orcish_follower(*mi)) { - if (is_orcish_follower(*mi)) - { - _give_monster_experience(exp * mi->hit_dice / total_hd, + _give_monster_experience(exp * mi->get_experience_level() / total_hd, mi->mindex()); - } } - } } static int _calc_player_experience(const monster* mons) @@ -747,13 +745,14 @@ static bool _beogh_forcibly_convert_orc(monster* mons, killer_type killer, mprf(MSGCH_DIAGNOSTICS, "Death convert attempt on %s, HD: %d, " "your xl: %d", mons->name(DESC_PLAIN).c_str(), - mons->hit_dice, + mons->get_hit_dice(), you.experience_level); #endif if (random2(you.piety) >= piety_breakpoint(0) - && random2(you.experience_level) >= random2(mons->hit_dice) + && random2(you.experience_level) >= + random2(mons->get_hit_dice()) // Bias beaten-up-conversion towards the stronger orcs. - && random2(mons->hit_dice) > 2) + && random2(mons->get_experience_level()) > 2) { beogh_convert_orc(mons, true, MON_KILL(killer)); return true; @@ -775,7 +774,7 @@ static bool _lost_soul_nearby(const coord_def pos) static bool _monster_avoided_death(monster* mons, killer_type killer, int i) { - if (mons->max_hit_points <= 0 || mons->hit_dice < 1) + if (mons->max_hit_points <= 0 || mons->get_hit_dice() < 1) return false; // Before the hp check since this should not care about the power of the @@ -987,11 +986,11 @@ static void _setup_lightning_explosion(bolt & beam, const monster& origin) { _setup_base_explosion(beam, origin); beam.flavour = BEAM_ELECTRICITY; - beam.damage = dice_def(3, 5 + origin.hit_dice * 5 / 4); + beam.damage = dice_def(3, 5 + origin.get_hit_dice() * 5 / 4); beam.name = "blast of lightning"; beam.noise_msg = "You hear a clap of thunder!"; beam.colour = LIGHTCYAN; - beam.ex_size = x_chance_in_y(origin.hit_dice, 24) ? 3 : 2; + beam.ex_size = x_chance_in_y(origin.get_hit_dice(), 24) ? 3 : 2; // Don't credit the player for ally-summoned ball lightning explosions. if (origin.summoner && origin.summoner != MID_PLAYER) beam.thrower = KILL_MON; @@ -1001,8 +1000,9 @@ static void _setup_prism_explosion(bolt& beam, const monster& origin) { _setup_base_explosion(beam, origin); beam.flavour = BEAM_MMISSILE; - beam.damage = (origin.number == 2 ? dice_def(3, 6 + origin.hit_dice * 7 / 4) - : dice_def(2, 6 + origin.hit_dice * 7 / 4)); + beam.damage = (origin.number == 2 ? + dice_def(3, 6 + origin.get_hit_dice() * 7 / 4) + : dice_def(2, 6 + origin.get_hit_dice() * 7 / 4)); beam.name = "blast of energy"; beam.colour = MAGENTA; beam.ex_size = origin.number; @@ -1317,12 +1317,12 @@ static void _make_spectral_thing(monster* mons, bool quiet) if (!quiet) mpr("A glowing mist starts to gather..."); - // If the original monster has been drained or levelled up, - // its HD might be different from its class HD, in which - // case its HP should be rerolled to match. - if (spectre->hit_dice != mons->hit_dice) + // If the original monster has been levelled up, its HD might be + // different from its class HD, in which case its HP should be + // rerolled to match. + if (spectre->get_experience_level() != mons->get_experience_level()) { - spectre->hit_dice = max(mons->hit_dice, 1); + spectre->set_hit_dice(max(mons->get_experience_level(), 1)); roll_zombie_hp(spectre); } @@ -1355,13 +1355,15 @@ static void _druid_final_boon(const monster* mons) } shuffle_array(beasts); - int num = min((int)beasts.size(), random_range(mons->hit_dice / 3, - mons->hit_dice / 2 + 1)); + int num = min((int)beasts.size(), + random_range(mons->get_hit_dice() / 3, + mons->get_hit_dice() / 2 + 1)); // Healing and empowering done in two separate loops for tidier messages for (int i = 0; i < num; ++i) { - if (beasts[i]->heal(roll_dice(3, mons->hit_dice)) && you.can_see(beasts[i])) + if (beasts[i]->heal(roll_dice(3, mons->get_hit_dice())) + && you.can_see(beasts[i])) { mprf("%s %s healed.", beasts[i]->name(DESC_THE).c_str(), beasts[i]->conj_verb("are").c_str()); @@ -1836,68 +1838,68 @@ int monster_die(monster* mons, killer_type killer, if (targ_holy == MH_DEMONIC || mons_is_demonspawn(mons->type)) { did_god_conduct(DID_KILL_DEMON, - mons->hit_dice, true, mons); + mons->get_experience_level(), true, mons); } else if (targ_holy == MH_NATURAL) { did_god_conduct(DID_KILL_LIVING, - mons->hit_dice, true, mons); + mons->get_experience_level(), true, mons); // TSO hates natural evil and unholy beings. if (mons->is_unholy()) { did_god_conduct(DID_KILL_NATURAL_UNHOLY, - mons->hit_dice, true, mons); + mons->get_experience_level(), true, mons); } else if (mons->is_evil()) { did_god_conduct(DID_KILL_NATURAL_EVIL, - mons->hit_dice, true, mons); + mons->get_experience_level(), true, mons); } } else if (targ_holy == MH_UNDEAD) { did_god_conduct(DID_KILL_UNDEAD, - mons->hit_dice, true, mons); + mons->get_experience_level(), true, mons); } // Zin hates unclean and chaotic beings. if (mons->how_unclean()) { did_god_conduct(DID_KILL_UNCLEAN, - mons->hit_dice, true, mons); + mons->get_experience_level(), true, mons); } else if (mons->how_chaotic()) { did_god_conduct(DID_KILL_CHAOTIC, - mons->hit_dice, true, mons); + mons->get_experience_level(), true, mons); } // jmf: Trog hates wizards. if (mons->is_actual_spellcaster()) { did_god_conduct(DID_KILL_WIZARD, - mons->hit_dice, true, mons); + mons->get_experience_level(), true, mons); } // Beogh hates priests of other gods. if (mons->is_priest()) { did_god_conduct(DID_KILL_PRIEST, - mons->hit_dice, true, mons); + mons->get_experience_level(), true, mons); } // Jiyva hates you killing slimes, but eyeballs // mutation can confuse without you meaning it. if (mons_is_slime(mons) && killer != KILL_YOU_CONF && bad_kill) { - did_god_conduct(DID_KILL_SLIME, mons->hit_dice, + did_god_conduct(DID_KILL_SLIME, mons->get_experience_level(), true, mons); } if (fedhas_protects(mons)) { - did_god_conduct(DID_KILL_PLANT, mons->hit_dice, + did_god_conduct(DID_KILL_PLANT, mons->get_experience_level(), true, mons); } @@ -1905,21 +1907,21 @@ int monster_die(monster* mons, killer_type killer, if (cheibriados_thinks_mons_is_fast(mons) && !mons->cannot_move()) { - did_god_conduct(DID_KILL_FAST, mons->hit_dice, + did_god_conduct(DID_KILL_FAST, mons->get_experience_level(), true, mons); } // Yredelemnul hates artificial beings. if (mons->is_artificial()) { - did_god_conduct(DID_KILL_ARTIFICIAL, mons->hit_dice, + did_god_conduct(DID_KILL_ARTIFICIAL, mons->get_experience_level(), true, mons); } // Holy kills are always noticed. if (mons->is_holy()) { - did_god_conduct(DID_KILL_HOLY, mons->hit_dice, + did_god_conduct(DID_KILL_HOLY, mons->get_experience_level(), true, mons); } @@ -1928,12 +1930,12 @@ int monster_die(monster* mons, killer_type killer, // messages appears.) if (mons_is_illuminating(mons)) { - did_god_conduct(DID_KILL_ILLUMINATING, mons->hit_dice, - true, mons); + did_god_conduct(DID_KILL_ILLUMINATING, + mons->get_experience_level(), true, mons); } else if (mons_is_fiery(mons)) { - did_god_conduct(DID_KILL_FIERY, mons->hit_dice, + did_god_conduct(DID_KILL_FIERY, mons->get_experience_level(), true, mons); } } @@ -1954,14 +1956,15 @@ int monster_die(monster* mons, killer_type killer, switch (you.religion) { case GOD_MAKHLEB: - hp_heal = mons->hit_dice + random2(mons->hit_dice); + hp_heal = mons->get_experience_level() + + random2(mons->get_experience_level()); break; case GOD_SHINING_ONE: - hp_heal = random2(1 + 2 * mons->hit_dice); - mp_heal = random2(2 + mons->hit_dice / 3); + hp_heal = random2(1 + 2 * mons->get_experience_level()); + mp_heal = random2(2 + mons->get_experience_level() / 3); break; case GOD_VEHUMET: - mp_heal = 1 + random2(mons->hit_dice / 2); + mp_heal = 1 + random2(mons->get_experience_level() / 2); break; default: die("bad kill-on-healing god!"); @@ -2024,13 +2027,14 @@ int monster_die(monster* mons, killer_type killer, did_god_conduct(mon_intel > 0 ? DID_SOULED_FRIEND_DIED : DID_FRIEND_DIED, - 1 + (mons->hit_dice / 2), + 1 + (mons->get_experience_level() / 2), true, mons); } if (pet_kill && fedhas_protects(mons)) { - did_god_conduct(DID_PLANT_KILLED_BY_SERVANT, 1 + (mons->hit_dice / 2), + did_god_conduct(DID_PLANT_KILLED_BY_SERVANT, + 1 + (mons->get_experience_level() / 2), true, mons); } @@ -2080,33 +2084,33 @@ int monster_die(monster* mons, killer_type killer, did_god_conduct( !confused ? DID_DEMON_KILLED_BY_UNDEAD_SLAVE : DID_DEMON_KILLED_BY_SERVANT, - mons->hit_dice); + mons->get_experience_level()); } else if (targ_holy == MH_NATURAL) { did_god_conduct( !confused ? DID_LIVING_KILLED_BY_UNDEAD_SLAVE : DID_LIVING_KILLED_BY_SERVANT, - mons->hit_dice); + mons->get_experience_level()); } else if (targ_holy == MH_UNDEAD) { did_god_conduct( !confused ? DID_UNDEAD_KILLED_BY_UNDEAD_SLAVE : DID_UNDEAD_KILLED_BY_SERVANT, - mons->hit_dice); + mons->get_experience_level()); } if (mons->how_unclean()) { did_god_conduct(DID_UNCLEAN_KILLED_BY_SERVANT, - mons->hit_dice); + mons->get_experience_level()); } if (mons->how_chaotic()) { did_god_conduct(DID_CHAOTIC_KILLED_BY_SERVANT, - mons->hit_dice); + mons->get_experience_level()); } if (mons->is_artificial()) @@ -2114,7 +2118,7 @@ int monster_die(monster* mons, killer_type killer, did_god_conduct( !confused ? DID_ARTIFICIAL_KILLED_BY_UNDEAD_SLAVE : DID_ARTIFICIAL_KILLED_BY_SERVANT, - mons->hit_dice); + mons->get_experience_level()); } } // Yes, we are splitting undead pets from the others @@ -2130,48 +2134,48 @@ int monster_die(monster* mons, killer_type killer, || mons_is_demonspawn(mons->type)) { did_god_conduct(DID_DEMON_KILLED_BY_SERVANT, - mons->hit_dice); + mons->get_experience_level()); } else if (targ_holy == MH_NATURAL) { did_god_conduct(DID_LIVING_KILLED_BY_SERVANT, - mons->hit_dice); + mons->get_experience_level()); // TSO hates natural evil and unholy beings. if (mons->is_unholy()) { did_god_conduct( DID_NATURAL_UNHOLY_KILLED_BY_SERVANT, - mons->hit_dice); + mons->get_experience_level()); } else if (mons->is_evil()) { did_god_conduct(DID_NATURAL_EVIL_KILLED_BY_SERVANT, - mons->hit_dice); + mons->get_experience_level()); } } else if (targ_holy == MH_UNDEAD) { did_god_conduct(DID_UNDEAD_KILLED_BY_SERVANT, - mons->hit_dice); + mons->get_experience_level()); } if (mons->how_unclean()) { did_god_conduct(DID_UNCLEAN_KILLED_BY_SERVANT, - mons->hit_dice); + mons->get_experience_level()); } if (mons->how_chaotic()) { did_god_conduct(DID_CHAOTIC_KILLED_BY_SERVANT, - mons->hit_dice); + mons->get_experience_level()); } if (mons->is_artificial()) { did_god_conduct(DID_ARTIFICIAL_KILLED_BY_SERVANT, - mons->hit_dice); + mons->get_experience_level()); } } @@ -2192,12 +2196,13 @@ int monster_die(monster* mons, killer_type killer, did_god_conduct( !confused ? DID_HOLY_KILLED_BY_UNDEAD_SLAVE : DID_HOLY_KILLED_BY_SERVANT, - mons->hit_dice, true, mons); + mons->get_experience_level(), true, mons); } else { did_god_conduct(DID_HOLY_KILLED_BY_SERVANT, - mons->hit_dice, true, mons); + mons->get_experience_level(), + true, mons); } } @@ -2219,7 +2224,7 @@ int monster_die(monster* mons, killer_type killer, { simple_monster_message(killer_mon, " looks invigorated."); - killer_mon->heal(1 + random2(mons->hit_dice / 4)); + killer_mon->heal(1 + random2(mons->get_experience_level() / 4)); } } diff --git a/crawl-ref/source/mon-ench.cc b/crawl-ref/source/mon-ench.cc index 3b854da602..2f3f5d5da8 100644 --- a/crawl-ref/source/mon-ench.cc +++ b/crawl-ref/source/mon-ench.cc @@ -198,7 +198,7 @@ void monster::add_enchantment_effect(const mon_enchant &ench, bool quiet) case ENCH_STONESKIN: { // player gets 2+earth/5 - const int ac_bonus = hit_dice / 2; + const int ac_bonus = get_hit_dice() / 2; ac += ac_bonus; // the monster may get drained or level up, we need to store the bonus @@ -209,7 +209,7 @@ void monster::add_enchantment_effect(const mon_enchant &ench, bool quiet) case ENCH_OZOCUBUS_ARMOUR: { // player gets 4+ice/3 - const int ac_bonus = 4 + hit_dice / 3; + const int ac_bonus = 4 + get_hit_dice() / 3; ac += ac_bonus; // the monster may get drained or level up, we need to store the bonus @@ -1700,7 +1700,8 @@ void monster::apply_enchantment(const mon_enchant &me) if (!(flags & MF_TAKING_STAIRS) && !(paralysed() || petrified() || petrifying() || asleep()) && (type == MONS_SHAPESHIFTER - || x_chance_in_y(1000 / (15 * max(1, hit_dice) / 5), 1000))) + || x_chance_in_y(1000 / (15 * max(1, get_hit_dice()) / 5), + 1000))) { monster_polymorph(this, RANDOM_MONSTER); } @@ -2191,7 +2192,7 @@ actor* mon_enchant::agent() const int mon_enchant::modded_speed(const monster* mons, int hdplus) const { - return _mod_speed(mons->hit_dice + hdplus, mons->speed); + return _mod_speed(mons->get_hit_dice() + hdplus, mons->speed); } int mon_enchant::calc_duration(const monster* mons, diff --git a/crawl-ref/source/mon-gear.cc b/crawl-ref/source/mon-gear.cc index 2d0ad745e6..a487a0f9cb 100644 --- a/crawl-ref/source/mon-gear.cc +++ b/crawl-ref/source/mon-gear.cc @@ -146,8 +146,9 @@ static void _give_wand(monster* mon, int level) // Don't give top-tier wands before 5 HD, except to Ijyb and not in sprint. const bool no_high_tier = - (mon->hit_dice < 5 || mons_class_flag(mon->type, M_NO_HT_WAND)) - && (mon->type != MONS_IJYB || crawl_state.game_is_sprint()); + (mon->get_experience_level() < 5 + || mons_class_flag(mon->type, M_NO_HT_WAND)) + && (mon->type != MONS_IJYB || crawl_state.game_is_sprint()); while (1) { @@ -1519,7 +1520,7 @@ static void _give_weapon(monster* mon, int level, bool melee_only = false, if (!force_item && mons_is_unique(mon->type)) { - if (x_chance_in_y(10 + mon->hit_dice, 100)) + if (x_chance_in_y(10 + mon->get_experience_level(), 100)) level = MAKE_GOOD_ITEM; else if (level != MAKE_GOOD_ITEM) level += 5; @@ -2449,7 +2450,7 @@ static void _give_armour(monster* mon, int level, bool spectral_orcs, bool merc) if (!force_item && mons_is_unique(mon->type) && level != MAKE_GOOD_ITEM) { - if (x_chance_in_y(9 + mon->hit_dice, 100)) + if (x_chance_in_y(9 + mon->get_experience_level(), 100)) level = MAKE_GOOD_ITEM; else level = level * 2 + 5; diff --git a/crawl-ref/source/mon-grow.cc b/crawl-ref/source/mon-grow.cc index 293ba77eb9..fa3dde071d 100644 --- a/crawl-ref/source/mon-grow.cc +++ b/crawl-ref/source/mon-grow.cc @@ -137,11 +137,7 @@ void monster::upgrade_type(monster_type after, bool adjust_hd, ev += m->ev - orig->ev; if (adjust_hd) - { - const int minhd = dummy.hit_dice; - if (hit_dice < minhd) - hit_dice += minhd - hit_dice; - } + set_hit_dice(max(get_experience_level(), dummy.get_hit_dice())); if (adjust_hp) { @@ -162,7 +158,9 @@ void monster::upgrade_type(monster_type after, bool adjust_hd, bool monster::level_up_change() { - if (const monster_level_up *lup = _monster_level_up_target(type, hit_dice)) + const monster_level_up *lup = _monster_level_up_target(type, + get_experience_level()); + if (lup) { upgrade_type(lup->after, false, lup->adjust_hp); return true; @@ -171,7 +169,7 @@ bool monster::level_up_change() { base_monster = type; monster_type upgrade = resolve_monster_type(RANDOM_NONBASE_DRACONIAN, type); - if (static_cast<int>(get_monster_data(upgrade)->hpdice[0]) == hit_dice) + if (static_cast<int>(get_monster_data(upgrade)->hpdice[0]) == get_experience_level()) upgrade_type(upgrade, false, true); } return false; @@ -179,23 +177,24 @@ bool monster::level_up_change() bool monster::level_up() { - if (hit_dice >= MAX_MONS_HD) + if (get_experience_level() >= MAX_MONS_HD) return false; - ++hit_dice; + set_hit_dice(get_experience_level() + 1); // A little maxhp boost. if (max_hit_points < 1000) { int hpboost = - (hit_dice > 3? max_hit_points / 8 : max_hit_points / 4) + (get_experience_level() > 3? max_hit_points / 8 : max_hit_points / 4) + random2(5); // Not less than 3 hp, not more than 25. hpboost = min(max(hpboost, 3), 25); dprf("%s: HD: %d, maxhp: %d, boost: %d", - name(DESC_PLAIN).c_str(), hit_dice, max_hit_points, hpboost); + name(DESC_PLAIN).c_str(), get_experience_level(), + max_hit_points, hpboost); max_hit_points += hpboost; hit_points += hpboost; @@ -211,8 +210,8 @@ void monster::init_experience() { if (experience || !alive()) return; - hit_dice = max(hit_dice, 1); - experience = mexplevs[min(hit_dice, MAX_MONS_HD)]; + set_hit_dice(max(get_experience_level(), 1)); + experience = mexplevs[min(get_experience_level(), MAX_MONS_HD)]; } bool monster::gain_exp(int exp, int max_levels_to_gain) @@ -221,7 +220,7 @@ bool monster::gain_exp(int exp, int max_levels_to_gain) return false; init_experience(); - if (hit_dice >= MAX_MONS_HD) + if (get_experience_level() >= MAX_MONS_HD) return false; // Only natural monsters can level-up. @@ -241,8 +240,8 @@ bool monster::gain_exp(int exp, int max_levels_to_gain) const monster mcopy(*this); int levels_gained = 0; // Monsters can normally gain a maximum of two levels from one kill. - while (hit_dice < MAX_MONS_HD - && experience >= mexplevs[hit_dice + 1] + while (get_experience_level() < MAX_MONS_HD + && experience >= mexplevs[get_experience_level() + 1] && level_up() && ++levels_gained < max_levels_to_gain); @@ -254,8 +253,12 @@ bool monster::gain_exp(int exp, int max_levels_to_gain) simple_monster_message(&mcopy, " looks stronger."); } - if (hit_dice < MAX_MONS_HD && experience >= mexplevs[hit_dice + 1]) - experience = (mexplevs[hit_dice] + mexplevs[hit_dice + 1]) / 2; + if (get_experience_level() < MAX_MONS_HD + && experience >= mexplevs[get_experience_level() + 1]) + { + experience = (mexplevs[get_experience_level()] + + mexplevs[get_experience_level() + 1]) / 2; + } // If the monster has leveled up to a monster that will be angered // by the player, handle it properly. diff --git a/crawl-ref/source/mon-place.cc b/crawl-ref/source/mon-place.cc index 0f7c11995b..13c2c206a7 100644 --- a/crawl-ref/source/mon-place.cc +++ b/crawl-ref/source/mon-place.cc @@ -1454,7 +1454,7 @@ static monster* _place_monster_aux(const mgen_data &mg, const monster *leader, bonus2 = mbase->hpdice[2]; bonus3 = mbase->hpdice[3]; } - mon->hit_dice = mg.hd; + mon->set_hit_dice(mg.hd); // Re-roll HP. int hp = hit_points(mg.hd, m_ent->hpdice[1] + bonus1, m_ent->hpdice[2] + bonus2); @@ -1935,20 +1935,20 @@ void roll_zombie_hp(monster* mon) switch (mon->type) { case MONS_ZOMBIE: - hp = hit_points(mon->hit_dice, 6, 5); + hp = hit_points(mon->get_hit_dice(), 6, 5); break; case MONS_SKELETON: - hp = hit_points(mon->hit_dice, 5, 4); + hp = hit_points(mon->get_hit_dice(), 5, 4); break; case MONS_SIMULACRUM: // Simulacra aren't tough, but you can create piles of them. - bwr - hp = hit_points(mon->hit_dice, 1, 4); + hp = hit_points(mon->get_hit_dice(), 1, 4); break; case MONS_SPECTRAL_THING: - hp = hit_points(mon->hit_dice, 4, 4); + hp = hit_points(mon->get_hit_dice(), 4, 4); break; default: diff --git a/crawl-ref/source/mon-poly.cc b/crawl-ref/source/mon-poly.cc index 6409519a71..5db33b41dd 100644 --- a/crawl-ref/source/mon-poly.cc +++ b/crawl-ref/source/mon-poly.cc @@ -450,7 +450,7 @@ bool monster_polymorph(monster* mons, monster_type targetc, // for the monster class. By using the current hit dice // the player gets the opportunity to use draining more // effectively against shapeshifters. - bwr - source_power = mons->hit_dice; + source_power = mons->get_hit_dice(); source_tier = mons_demon_tier(mons->type); // There's not a single valid target on the '&' demon tier, so unless we @@ -498,7 +498,7 @@ bool monster_polymorph(monster* mons, monster_type targetc, for (int mc = 0; mc < NUM_MONSTERS; ++mc) { const monsterentry *me = get_monster_data((monster_type) mc); - int delta = (int) me->hpdice[0] - mons->hit_dice; + int delta = (int) me->hpdice[0] - mons->get_hit_dice(); if (delta != 1) continue; if (!_valid_morph(mons, (monster_type) mc)) @@ -592,7 +592,7 @@ void slimify_monster(monster* mon, bool hostile) { monster_type target = MONS_JELLY; - const int x = mon->hit_dice + (coinflip() ? 1 : -1) * random2(5); + const int x = mon->get_hit_dice() + (coinflip() ? 1 : -1) * random2(5); if (x < 3) target = MONS_OOZE; @@ -695,7 +695,8 @@ void seen_monster(monster* mons) && !mons_class_flag(mons->type, M_NO_EXP_GAIN) && !crawl_state.game_is_arena()) { - did_god_conduct(DID_SEE_MONSTER, mons->hit_dice, true, mons); + did_god_conduct(DID_SEE_MONSTER, mons->get_experience_level(), + true, mons); } mons->flags |= MF_TSO_SEEN; } diff --git a/crawl-ref/source/mon-project.cc b/crawl-ref/source/mon-project.cc index fad0a806df..ac8c91717a 100644 --- a/crawl-ref/source/mon-project.cc +++ b/crawl-ref/source/mon-project.cc @@ -203,7 +203,7 @@ static bool _iood_shielded(monster& mon, actor &victim) return false; const int to_hit = 15 + (mons_is_projectile(mon.type) ? - mon.props["iood_pow"].get_short()/12 : mon.hit_dice/2); + mon.props["iood_pow"].get_short()/12 : mon.get_hit_dice()/2); const int con_block = random2(to_hit + victim.shield_block_penalty()); const int pro_block = victim.shield_bonus(); dprf("iood shield: pro %d, con %d", pro_block, con_block); diff --git a/crawl-ref/source/mon-util.cc b/crawl-ref/source/mon-util.cc index 5b4a75f228..19804309ae 100644 --- a/crawl-ref/source/mon-util.cc +++ b/crawl-ref/source/mon-util.cc @@ -1960,7 +1960,7 @@ int exper_value(const monster* mon, bool real) // These four are the original arguments. const monster_type mc = mon->type; - int hd = mon->hit_dice; + int hd = mon->get_experience_level(); int maxhp = mon->max_hit_points; // pghosts and pillusions have no reasonable base values, and you can look @@ -2382,7 +2382,7 @@ bool init_abomination(monster* mon, int hd) if (mon->type == MONS_CRAWLING_CORPSE || mon->type == MONS_MACABRE_MASS) { - mon->hit_points = mon->max_hit_points = mon->hit_dice = hd; + mon->set_hit_dice(mon->hit_points = mon->max_hit_points = hd); return true; } else if (mon->type != MONS_ABOMINATION_LARGE @@ -2394,7 +2394,7 @@ bool init_abomination(monster* mon, int hd) const int max_hd = mon->type == MONS_ABOMINATION_LARGE ? 30 : 15; const int max_ac = mon->type == MONS_ABOMINATION_LARGE ? 20 : 10; - mon->hit_dice = min(max_hd, hd); + mon->set_hit_dice(min(max_hd, hd)); const monsterentry *m = get_monster_data(mon->type); int hp = hit_points(hd, m->hpdice[1], m->hpdice[2]) + m->hpdice[3]; @@ -2556,7 +2556,7 @@ void define_monster(monster* mons) hp_max = hp; // So let it be written, so let it be done. - mons->hit_dice = hd; + mons->set_hit_dice(hd); mons->hit_points = hp; mons->max_hit_points = hp_max; mons->ac = ac; @@ -3841,7 +3841,7 @@ bool monster_senior(const monster* m1, const monster* m2, bool fleeing) // &s are the evillest demons of all, well apart from Geryon, who really // profits from *not* pushing past beasts. if (mchar1 == '&' && isadigit(mchar2) && m1->type != MONS_GERYON) - return fleeing || m1->hit_dice > m2->hit_dice; + return fleeing || m1->get_hit_dice() > m2->get_hit_dice(); // If they're the same holiness, monsters smart enough to use stairs can // push past monsters too stupid to use stairs (so that e.g. non-zombified @@ -3877,7 +3877,8 @@ bool monster_senior(const monster* m1, const monster* m2, bool fleeing) return true; } - return mchar1 == mchar2 && (fleeing || m1->hit_dice > m2->hit_dice); + return mchar1 == mchar2 && (fleeing || + m1->get_hit_dice() > m2->get_hit_dice()); } bool mons_class_can_pass(monster_type mc, const dungeon_feature_type grid) diff --git a/crawl-ref/source/monster.cc b/crawl-ref/source/monster.cc index 0162d2cfab..cab7b88615 100644 --- a/crawl-ref/source/monster.cc +++ b/crawl-ref/source/monster.cc @@ -73,13 +73,14 @@ #define smc get_monster_data(mc) monster::monster() - : hit_points(0), max_hit_points(0), hit_dice(0), + : hit_points(0), max_hit_points(0), ac(0), ev(0), speed(0), speed_increment(0), target(), firing_pos(), patrol_point(), travel_target(MTRAV_NONE), inv(NON_ITEM), spells(), attitude(ATT_HOSTILE), behaviour(BEH_WANDER), foe(MHITYOU), enchantments(), flags(0), experience(0), base_monster(MONS_NO_MONSTER), number(0), colour(BLACK), foe_memory(0), - god(GOD_NO_GOD), ghost(), seen_context(SC_NONE), client_id(0) + god(GOD_NO_GOD), ghost(), seen_context(SC_NONE), client_id(0), + hit_dice(0) { type = MONS_NO_MONSTER; @@ -2138,7 +2139,7 @@ bool monster::pickup_wand(item_def &item, int near) return false; // Only low-HD monsters bother with wands. - if (hit_dice >= 14) + if (get_hit_dice() >= 14) return false; // Holy monsters and worshippers of good gods won't pick up evil @@ -2834,9 +2835,14 @@ int monster::mindex() const return this - menv.buffer(); } -int monster::get_experience_level() const +/** + * Sets the monster's "hit dice". Doesn't currently handle adjusting HP, etc. + * + * @param new_hit_dice The new value to set HD to. + */ +void monster::set_hit_dice(int new_hit_dice) { - return hit_dice; + hit_dice = new_hit_dice; } void monster::moveto(const coord_def& c, bool clear_net) @@ -3029,7 +3035,10 @@ void monster::banish(actor *agent, const string &) // distinguishable from others of the same kind in the Abyss. if (agent->is_player()) - did_god_conduct(DID_BANISH, hit_dice, true /*possibly wrong*/, this); + { + did_god_conduct(DID_BANISH, get_experience_level(), + true /*possibly wrong*/, this); + } } monster_die(this, KILL_BANISHED, NON_MONSTER); @@ -3229,9 +3238,9 @@ bool monster::liquefied_ground() const int monster::natural_regen_rate() const { // A HD divider ranging from 3 (at 1 HD) to 1 (at 8 HD). - int divider = max(div_rand_round(15 - hit_dice, 4), 1); + int divider = max(div_rand_round(15 - get_hit_dice(), 4), 1); - return max(div_rand_round(hit_dice, divider), 1); + return max(div_rand_round(get_hit_dice(), divider), 1); } // in units of 1/100 hp/turn @@ -3297,7 +3306,7 @@ int monster::shield_bonus() const int shld_c = property(*shld, PARM_AC) + shld->plus * 2; shld_c = shld_c * 2 + (body_size(PSIZE_TORSO) - SIZE_MEDIUM) * (shld->sub_type - ARM_LARGE_SHIELD); - return random2avg(shld_c + hit_dice * 4 / 3, 2) / 2; + return random2avg(shld_c + get_hit_dice() * 4 / 3, 2) / 2; } return -100; } @@ -3316,7 +3325,7 @@ void monster::shield_block_succeeded(actor *attacker) int monster::shield_bypass_ability(int) const { - return 15 + hit_dice * 2 / 3; + return 15 + get_hit_dice() * 2 / 3; } int monster::missile_deflection() const @@ -4036,7 +4045,7 @@ int monster::res_magic() const // Negative values get multiplied with monster hit dice. if (u < 0) - u = hit_dice * -u * 4 / 3; + u = get_hit_dice() * -u * 4 / 3; // Resistance from artefact properties. u += 40 * scan_artefacts(ARTP_MAGIC); @@ -4126,7 +4135,7 @@ int monster::skill(skill_type sk, int scale, bool real, bool drained) const if (mons_intel(this) < I_NORMAL && !mons_is_avatar(this->type)) return 0; - int hd = scale * hit_dice; + const int hd = scale * get_hit_dice(); int ret; switch (sk) { @@ -4332,7 +4341,7 @@ int monster::hurt(const actor *agent, int amount, beam_type flavour, && mons_species(true) == MONS_DEEP_DWARF) { // Deep Dwarves get to shave _any_ hp loss. Player version: - int shave = 1 + random2(2 + random2(1 + hit_dice / 3)); + int shave = 1 + random2(2 + random2(1 + get_hit_dice() / 3)); dprf("(mon) HP shaved: %d.", shave); amount -= shave; if (amount <= 0) @@ -4364,7 +4373,7 @@ int monster::hurt(const actor *agent, int amount, beam_type flavour, if (amount == INSTANT_DEATH) amount = hit_points; - else if (hit_dice <= 0) + else if (get_hit_dice() <= 0) amount = hit_points; else if (amount <= 0 && hit_points <= max_hit_points) return 0; @@ -4412,7 +4421,8 @@ int monster::hurt(const actor *agent, int amount, beam_type flavour, behaviour_event(this, ME_HURT); } - if (cleanup_dead && (hit_points <= 0 || hit_dice <= 0) && type != MONS_NO_MONSTER) + if (cleanup_dead && (hit_points <= 0 || get_hit_dice() <= 0) + && type != MONS_NO_MONSTER) { if (agent == NULL) monster_die(this, KILL_MISC, NON_MONSTER); @@ -4806,7 +4816,7 @@ bool monster::needs_abyss_transit() const { return (mons_is_unique(type) || (flags & MF_BANISHED) - || hit_dice > 8 + random2(25) + || get_experience_level() > 8 + random2(25) && mons_can_use_stairs(this)) && !has_ench(ENCH_ABJ) && type != MONS_BATTLESPHERE; // can use stairs otherwise @@ -4994,7 +5004,7 @@ void monster::check_speed() { dprf("Bad speed: %s, spd: %d, spi: %d, hd: %d, ench: %s", name(DESC_PLAIN).c_str(), - speed, speed_increment, hit_dice, + speed, speed_increment, get_hit_dice(), describe_enchantments().c_str()); calc_speed(); @@ -6360,7 +6370,7 @@ bool monster::attempt_escape(int attempts) randfact = roll_dice(1,5) + 5; const monster* themonst = monster_by_mid(constricted_by); ASSERT(themonst); - randfact += roll_dice(1, themonst->hit_dice); + randfact += roll_dice(1, themonst->get_hit_dice()); } else randfact = roll_dice(1, you.strength()); @@ -6536,7 +6546,7 @@ int monster::aug_amount() const // for Archmagi, etc. to have an impact in some cases. int monster::spell_hd(spell_type spell) const { - return hit_dice + 2 * aug_amount(); + return get_hit_dice() + 2 * aug_amount(); } void monster::align_avatars(bool force_friendly) diff --git a/crawl-ref/source/monster.h b/crawl-ref/source/monster.h index 53d286793a..f52674b73d 100644 --- a/crawl-ref/source/monster.h +++ b/crawl-ref/source/monster.h @@ -29,7 +29,6 @@ public: int hit_points; int max_hit_points; - int hit_dice; int ac; int ev; int speed; @@ -83,6 +82,8 @@ public: void reset_client_id(); void ensure_has_client_id(); + void set_hit_dice(int new_hd); + mon_attitude_type temp_attitude() const; // Returns true if the monster is named with a proper name, or is @@ -206,6 +207,7 @@ public: // actor interface int mindex() const; + int get_hit_dice() const; int get_experience_level() const; god_type deity() const; bool alive() const; @@ -520,6 +522,9 @@ public: void remove_avatars(); private: + int hit_dice; + +private: void init_with(const monster& mons); void swap_slots(mon_inv_type a, mon_inv_type b); bool need_message(int &near) const; diff --git a/crawl-ref/source/ouch.cc b/crawl-ref/source/ouch.cc index f518a3b04f..a33a047b07 100644 --- a/crawl-ref/source/ouch.cc +++ b/crawl-ref/source/ouch.cc @@ -595,7 +595,7 @@ static void _xom_checks_damage(kill_method_type death_type, return; } - int leveldif = mons->hit_dice - you.experience_level; + int leveldif = mons->get_experience_level() - you.experience_level; if (leveldif == 0) leveldif = 1; diff --git a/crawl-ref/source/player-act.cc b/crawl-ref/source/player-act.cc index 4890b519c6..bb99615eef 100644 --- a/crawl-ref/source/player-act.cc +++ b/crawl-ref/source/player-act.cc @@ -150,6 +150,11 @@ bool player::extra_balanced() const || !form_changed_physiology()); } +int player::get_hit_dice() const +{ + return experience_level; +} + int player::get_experience_level() const { return experience_level; diff --git a/crawl-ref/source/player.cc b/crawl-ref/source/player.cc index 84164a2a96..8909a7006d 100644 --- a/crawl-ref/source/player.cc +++ b/crawl-ref/source/player.cc @@ -8036,7 +8036,7 @@ bool player::attempt_escape(int attempts) // player breaks free if (4+n)d(8+str/4) >= 5d(8+HD/4) if (roll_dice(4 + escape_attempts, 8 + div_rand_round(strength(), 4)) - >= roll_dice(5, 8 + div_rand_round(themonst->hit_dice, 4))) + >= roll_dice(5, 8 + div_rand_round(themonst->get_hit_dice(), 4))) { mprf("You escape %s's grasp.", themonst->name(DESC_THE, true).c_str()); diff --git a/crawl-ref/source/player.h b/crawl-ref/source/player.h index 3a70419039..9ff9ef32a5 100644 --- a/crawl-ref/source/player.h +++ b/crawl-ref/source/player.h @@ -484,6 +484,7 @@ public: // actor int mindex() const; + int get_hit_dice() const; int get_experience_level() const; actor_type atype() const { return ACT_PLAYER; } monster* as_monster() { return NULL; } diff --git a/crawl-ref/source/ranged_attack.cc b/crawl-ref/source/ranged_attack.cc index 7c7ef2c9cd..376921ddae 100644 --- a/crawl-ref/source/ranged_attack.cc +++ b/crawl-ref/source/ranged_attack.cc @@ -70,7 +70,7 @@ int ranged_attack::calc_to_hit(bool random) orig_to_hit += (attacker->is_player()) ? maybe_random2(you.attribute[ATTR_PORTAL_PROJECTILE] / 4, random) - : 3 * attacker->as_monster()->hit_dice; + : 3 * attacker->as_monster()->get_hit_dice(); } int hit = orig_to_hit; @@ -374,7 +374,7 @@ int ranged_attack::calc_mon_to_hit_base() { ASSERT(attacker->is_monster()); const int hd_mult = attacker->as_monster()->is_archer() ? 15 : 9; - return 18 + attacker->get_experience_level() * hd_mult / 6; + return 18 + attacker->get_hit_dice() * hd_mult / 6; } int ranged_attack::apply_damage_modifiers(int damage, int damage_max, @@ -383,7 +383,7 @@ int ranged_attack::apply_damage_modifiers(int damage, int damage_max, ASSERT(attacker->is_monster()); if (attacker->as_monster()->is_archer()) { - const int bonus = attacker->get_experience_level() * 4 / 3; + const int bonus = attacker->get_hit_dice() * 4 / 3; damage += random2avg(bonus, 2); } half_ac = false; @@ -565,8 +565,8 @@ bool ranged_attack::blowgun_check(special_missile_type type) if (attacker->is_monster()) { - int chance = 85 - ((defender->get_experience_level() - - attacker->get_experience_level()) * 5 / 2); + int chance = 85 - ((defender->get_hit_dice() + - attacker->get_hit_dice()) * 5 / 2); chance += enchantment * 4; chance = min(95, chance); @@ -582,15 +582,15 @@ bool ranged_attack::blowgun_check(special_missile_type type) // You have a really minor chance of hitting with no skills or good // enchants. - if (defender->get_experience_level() < 15 && random2(100) <= 2) + if (defender->get_hit_dice() < 15 && random2(100) <= 2) return true; const int resist_roll = 2 + random2(4 + skill + enchantment); dprf("Brand rolled %d against defender HD: %d.", - resist_roll, defender->get_experience_level()); + resist_roll, defender->get_hit_dice()); - if (resist_roll < defender->get_experience_level()) + if (resist_roll < defender->get_hit_dice()) { if (needs_message) { @@ -615,7 +615,7 @@ int ranged_attack::blowgun_duration_roll(special_missile_type type) return 2; const int base_power = (attacker->is_monster()) - ? attacker->get_experience_level() + ? attacker->get_hit_dice() : attacker->skill_rdiv(SK_THROWING); const int plus = using_weapon() ? weapon->plus : 0; diff --git a/crawl-ref/source/shout.cc b/crawl-ref/source/shout.cc index ee24f7ee55..293dcf770d 100644 --- a/crawl-ref/source/shout.cc +++ b/crawl-ref/source/shout.cc @@ -302,7 +302,7 @@ bool check_awaken(monster* mons) return true; // I assume that creatures who can sense invisible are very perceptive. - int mons_perc = 10 + (mons_intel(mons) * 4) + mons->hit_dice + int mons_perc = 10 + (mons_intel(mons) * 4) + mons->get_hit_dice() + mons_sense_invis(mons) * 5; bool unnatural_stealthy = false; // "stealthy" only because of invisibility? diff --git a/crawl-ref/source/spl-cast.cc b/crawl-ref/source/spl-cast.cc index a6cb5bf6eb..69371a68e0 100644 --- a/crawl-ref/source/spl-cast.cc +++ b/crawl-ref/source/spl-cast.cc @@ -1031,7 +1031,7 @@ static void _try_monster_cast(spell_type spell, int powc, mon->flags = (MF_NO_REWARD | MF_JUST_SUMMONED | MF_SEEN | MF_WAS_IN_VIEW | MF_HARD_RESET); mon->hit_points = you.hp; - mon->hit_dice = you.experience_level; + mon->set_hit_dice(you.experience_level); mon->set_position(you.pos()); mon->target = spd.target; mon->mid = MID_PLAYER; diff --git a/crawl-ref/source/spl-clouds.cc b/crawl-ref/source/spl-clouds.cc index 400b70f4b3..0ed204953c 100644 --- a/crawl-ref/source/spl-clouds.cc +++ b/crawl-ref/source/spl-clouds.cc @@ -331,7 +331,7 @@ int holy_flames(monster* caster, actor* defender) { const coord_def pos = defender->pos(); int cloud_count = 0; - const int dur = 8 + random2avg(caster->hit_dice * 3, 2); + const int dur = 8 + random2avg(caster->get_hit_dice() * 3, 2); for (adjacent_iterator ai(pos); ai; ++ai) { diff --git a/crawl-ref/source/spl-damage.cc b/crawl-ref/source/spl-damage.cc index 25aea58cda..19f31aa1a4 100644 --- a/crawl-ref/source/spl-damage.cc +++ b/crawl-ref/source/spl-damage.cc @@ -756,12 +756,12 @@ spret_type cast_los_attack_spell(spell_type spell, int pow, actor* agent, if (mons_atts_aligned(m->attitude, mons->attitude)) { beam.friend_info.count++; - beam.friend_info.power += (m->hit_dice * this_damage / hurted); + beam.friend_info.power += (m->get_hit_dice() * this_damage / hurted); } else { beam.foe_info.count++; - beam.foe_info.power += (m->hit_dice * this_damage / hurted); + beam.foe_info.power += (m->get_hit_dice() * this_damage / hurted); } } } @@ -1357,8 +1357,8 @@ bool mons_shatter(monster* caster, bool actual) } } - int pow = 5 + div_rand_round(caster->hit_dice * 9, 2); - int rad = 3 + div_rand_round(caster->hit_dice, 5); + int pow = 5 + div_rand_round(caster->get_hit_dice() * 9, 2); + int rad = 3 + div_rand_round(caster->get_hit_dice(), 5); int dest = 0; for (distance_iterator di(caster->pos(), true, true, rad); di; ++di) @@ -2536,7 +2536,7 @@ void forest_message(const coord_def pos, const string &msg, msg_channel_type ch) void forest_damage(const actor *mon) { const coord_def pos = mon->pos(); - const int hd = mon->get_experience_level(); + const int hd = mon->get_hit_dice(); if (one_chance_in(4)) { @@ -2823,7 +2823,7 @@ void toxic_radiance_effect(actor* agent, int mult) if (agent->is_player()) pow = calc_spell_power(SPELL_OLGREBS_TOXIC_RADIANCE, true); else - pow = agent->as_monster()->hit_dice * 8; + pow = agent->as_monster()->get_hit_dice() * 8; bool break_sanctuary = (agent->is_player() && is_sanctuary(you.pos())); diff --git a/crawl-ref/source/spl-miscast.cc b/crawl-ref/source/spl-miscast.cc index d00664d849..b130ea4429 100644 --- a/crawl-ref/source/spl-miscast.cc +++ b/crawl-ref/source/spl-miscast.cc @@ -1606,7 +1606,7 @@ void MiscastEffect::_divination_mon(int severity) mon_msg_seen = "@The_monster@ looks disoriented."; target->confuse( act_source, - 1 + random2(3 + act_source->get_experience_level())); + 1 + random2(3 + act_source->get_hit_dice())); break; } break; @@ -1615,7 +1615,7 @@ void MiscastEffect::_divination_mon(int severity) mon_msg_seen = "@The_monster@ shudders."; target->confuse( act_source, - 5 + random2(3 + act_source->get_experience_level())); + 5 + random2(3 + act_source->get_hit_dice())); break; case 3: // nasty @@ -1624,7 +1624,7 @@ void MiscastEffect::_divination_mon(int severity) target_as_monster()->forget_random_spell(); target->confuse( act_source, - 8 + random2(3 + act_source->get_experience_level())); + 8 + random2(3 + act_source->get_hit_dice())); break; } do_msg(); @@ -2209,7 +2209,7 @@ void MiscastEffect::_fire(int severity) { monster* mon_target = target_as_monster(); mon_target->add_ench(mon_enchant(ENCH_STICKY_FLAME, - min(4, 1 + random2(mon_target->hit_dice) / 2), + min(4, 1 + random2(mon_target->get_hit_dice()) / 2), guilty)); } break; diff --git a/crawl-ref/source/spl-monench.cc b/crawl-ref/source/spl-monench.cc index 53bb977891..e11219c641 100644 --- a/crawl-ref/source/spl-monench.cc +++ b/crawl-ref/source/spl-monench.cc @@ -37,7 +37,7 @@ int englaciate(coord_def where, int pow, int, actor *agent) } int duration = (roll_dice(3, pow) / 6 - - random2(victim->get_experience_level())) + - random2(victim->get_hit_dice())) * BASELINE_DELAY; if (duration <= 0) diff --git a/crawl-ref/source/spl-other.cc b/crawl-ref/source/spl-other.cc index f259ae41ca..85886dc579 100644 --- a/crawl-ref/source/spl-other.cc +++ b/crawl-ref/source/spl-other.cc @@ -209,7 +209,7 @@ void start_recall(int type) continue; } - mid_hd m(mi->mid, mi->hit_dice); + mid_hd m(mi->mid, mi->get_experience_level()); rlist.push_back(m); } diff --git a/crawl-ref/source/spl-summoning.cc b/crawl-ref/source/spl-summoning.cc index bbd6672b65..def56802b5 100644 --- a/crawl-ref/source/spl-summoning.cc +++ b/crawl-ref/source/spl-summoning.cc @@ -1225,7 +1225,7 @@ spret_type cast_shadow_creatures(int st, god_type god, level_id place, else { // Choose a new duration based on HD. - int x = max(mons->hit_dice - 3, 1); + int x = max(mons->get_experience_level() - 3, 1); int d = div_rand_round(17,x); if (scroll) d++; @@ -1781,9 +1781,9 @@ static bool _raise_remains(const coord_def &pos, int corps, beh_type beha, // If the original monster has been drained or levelled up, its HD // might be different from its class HD, in which case its HP should // be rerolled to match. - if (mons->hit_dice != hd) + if (mons->get_experience_level() != hd) { - mons->hit_dice = max(hd, 1); + mons->set_hit_dice(max(hd, 1)); roll_zombie_hp(mons); } @@ -2484,7 +2484,7 @@ static int _abjuration(int pow, monster *mon) // TSO and Trog's abjuration protection. if (mons_is_god_gift(mon, GOD_SHINING_ONE)) { - sockage = sockage * (30 - mon->hit_dice) / 45; + sockage = sockage * (30 - mon->get_hit_dice()) / 45; if (sockage < duration) { simple_god_message(" protects a fellow warrior from your evil magic!", @@ -2561,7 +2561,7 @@ spret_type cast_forceful_dismissal(int pow, bool fail) if (mi->friendly() && mi->is_summoned() && mi->summoner == you.mid && you.see_cell_no_trans(mi->pos())) { - explode.push_back(make_pair(mi->pos(), mi->hit_dice)); + explode.push_back(make_pair(mi->pos(), mi->get_hit_dice())); } } @@ -2993,7 +2993,7 @@ bool fire_battlesphere(monster* mons) beam.name = "barrage of energy"; beam.range = LOS_RADIUS; beam.hit = AUTOMATIC_HIT; - beam.damage = dice_def(2, 5 + mons->hit_dice); + beam.damage = dice_def(2, 5 + mons->get_hit_dice()); beam.glyph = dchar_glyph(DCHAR_FIRED_ZAP); beam.colour = MAGENTA; beam.flavour = BEAM_MMISSILE; diff --git a/crawl-ref/source/spl-tornado.cc b/crawl-ref/source/spl-tornado.cc index 4cb398eda0..b3aba1ac2b 100644 --- a/crawl-ref/source/spl-tornado.cc +++ b/crawl-ref/source/spl-tornado.cc @@ -236,7 +236,7 @@ void tornado_damage(actor *caster, int dur) if (caster->is_player()) pow = calc_spell_power(SPELL_TORNADO, true); else - pow = caster->as_monster()->hit_dice * 4; + pow = caster->as_monster()->get_hit_dice() * 4; dprf("Doing tornado, dur %d, effective power %d", dur, pow); const coord_def org = caster->pos(); int noise = 0; diff --git a/crawl-ref/source/tags.cc b/crawl-ref/source/tags.cc index 8695640fcd..dec1eb6a90 100644 --- a/crawl-ref/source/tags.cc +++ b/crawl-ref/source/tags.cc @@ -4134,7 +4134,7 @@ void marshallMonster(writer &th, const monster& m) marshallString(th, m.mname); marshallByte(th, m.ac); marshallByte(th, m.ev); - marshallByte(th, m.hit_dice); + marshallByte(th, m.get_experience_level()); marshallByte(th, m.speed); marshallByte(th, m.speed_increment); marshallByte(th, m.behaviour); @@ -4865,13 +4865,13 @@ void unmarshallMonster(reader &th, monster& m) m.mname = unmarshallString(th); m.ac = unmarshallByte(th); m.ev = unmarshallByte(th); - m.hit_dice = unmarshallByte(th); + m.set_hit_dice( unmarshallByte(th)); #if TAG_MAJOR_VERSION == 34 // Draining used to be able to take a monster to 0 HD, but that // caused crashes if they tried to cast spells. - m.hit_dice = max(m.hit_dice, 1); + m.set_hit_dice(max(m.get_experience_level(), 1)); #else - ASSERT(m.hit_dice > 0); + ASSERT(m.get_experience_level() > 0); #endif m.speed = unmarshallByte(th); // Avoid sign extension when loading files (Elethiomel's hang) diff --git a/crawl-ref/source/wiz-fsim.cc b/crawl-ref/source/wiz-fsim.cc index ee41b1bfe9..f0e1bce236 100644 --- a/crawl-ref/source/wiz-fsim.cc +++ b/crawl-ref/source/wiz-fsim.cc @@ -154,7 +154,7 @@ static void _write_mon(FILE * o, monster &mon) { fprintf(o, "%s: HD %d AC %d EV %d\n", mon.name(DESC_PLAIN, true).c_str(), - mon.hit_dice, + mon.get_experience_level(), mon.ac, mon.ev); } diff --git a/crawl-ref/source/wiz-mon.cc b/crawl-ref/source/wiz-mon.cc index 26ed106fd7..f2409ba8e4 100644 --- a/crawl-ref/source/wiz-mon.cc +++ b/crawl-ref/source/wiz-mon.cc @@ -584,7 +584,7 @@ void debug_stethoscope(int mon) mprf(MSGCH_DIAGNOSTICS, "HD=%d (%u) HP=%d/%d AC=%d(%d) EV=%d MR=%d XP=%d SP=%d " "energy=%d%s%s mid=%u num=%d stealth=%d flags=%04" PRIx64, - mons.hit_dice, + mons.get_experience_level(), mons.experience, mons.hit_points, mons.max_hit_points, mons.ac, mons.armour_class(), diff --git a/crawl-ref/source/xom.cc b/crawl-ref/source/xom.cc index cc7d38c9f2..c03a21dfdb 100644 --- a/crawl-ref/source/xom.cc +++ b/crawl-ref/source/xom.cc @@ -1632,10 +1632,11 @@ static int _xom_snakes_to_sticks(int sever, bool debug = false) const int sub_type = (base_type == OBJ_MISSILES ? (x_chance_in_y(3,5) ? MI_ARROW : MI_JAVELIN) - : _xom_random_stickable(mi->hit_dice)); + : _xom_random_stickable(mi->get_experience_level())); int thing_created = items(0, base_type, sub_type, true, - mi->hit_dice / 3 - 1, 0, 0, -1, -1); + mi->get_experience_level() / 3 - 1, + 0, 0, -1, -1); if (thing_created == NON_ITEM) continue; |