int mon_spell_lore_damage(int spell, const monster_race *race, bool know_hp) { int hp; if (!mon_spell_is_valid(spell) || !mon_spell_has_damage(spell)) return 0; hp = (know_hp) ? race->avg_hp : 0; return mon_spell_dam(spell, hp, race->level, MAXIMISE); }
/** * Calculate a monster's maximum spell power. * * \param r_ptr is the monster we're studying * \param resist is the degree of resistance we're assuming to any * attack type (-1 = vulnerable ... 3 = immune) */ int best_spell_power(const monster_race *r_ptr, int resist) { const struct mon_spell *rs_ptr; const struct spell_effect *re_ptr; int dam = 0, best_dam = 0; /* Extract the monster level */ int rlev = ((r_ptr->level >= 1) ? r_ptr->level : 1); for (rs_ptr = mon_spell_table; rs_ptr->index < RSF_MAX; rs_ptr++) { if (rsf_has(r_ptr->spell_flags, rs_ptr->index)) { /* Get the maximum basic damage output of the spell (could be 0) */ dam = mon_spell_dam(rs_ptr->index, mon_hp(r_ptr, MAXIMISE), rlev, MAXIMISE); /* For all attack forms the player can save against, damage * is halved */ if (rs_ptr->save) dam /= 2; /* Adjust the real damage by the assumed resistance (if it is a * resistable type) */ if (rs_ptr->gf) dam = adjust_dam(p_ptr, rs_ptr->gf, dam, MAXIMISE, resist); /* Add the power ratings assigned to the various possible spell * effects (which is crucial for non-damaging spells) */ for (re_ptr = spell_effect_table; re_ptr->index < RSE_MAX; re_ptr++) { if ((re_ptr->method && (re_ptr->method == rs_ptr->index)) || (re_ptr->gf && (re_ptr->gf == rs_ptr->gf))) { /* First we adjust the real damage if necessary */ if (re_ptr->power.dice) dam = (dam * re_ptr->power.dice) / 100; /* Then we add any flat rating for this effect */ dam += re_ptr->power.base; /* Then we add any rlev-dependent rating */ if (re_ptr->power.m_bonus < 0) dam += re_ptr->power.sides / (rlev + 1); else if (re_ptr->power.m_bonus > 0) dam += (re_ptr->power.sides * rlev) / 100; } } /* Update the best_dam tracker */ if (dam > best_dam) best_dam = dam; } } return best_dam; }
int mon_spell_lore_damage(int index, const struct monster_race *race, bool know_hp) { int hp; if (!mon_spell_is_valid(index) || !mon_spell_has_damage(index)) return 0; hp = (know_hp) ? race->avg_hp : 0; return mon_spell_dam(index, hp, race, MAXIMISE); }
/** * Calculate a monster's maximum spell power. * * \param race is the monster we're studying * \param resist is the degree of resistance we're assuming to any * attack type (-1 = vulnerable ... 3 = immune) */ int best_spell_power(const struct monster_race *race, int resist) { const struct mon_spell_info *info; int dam = 0, best_dam = 0; /* Extract the monster level */ int rlev = ((race->level >= 1) ? race->level : 1); for (info = mon_spell_types; info->index < RSF_MAX; info++) { if (rsf_has(race->spell_flags, info->index)) { /* Get the spell */ const struct monster_spell *spell = monster_spell_by_index(info->index); if (!spell) continue; /* Get the maximum basic damage output of the spell (could be 0) */ dam = mon_spell_dam(info->index, mon_hp(race, MAXIMISE), race, MAXIMISE); /* For all attack forms the player can save against, damage * is halved */ if (spell->save_message) dam /= 2; /* Adjust the real damage by the assumed resistance (if it is a * resistable type) */ if (monster_spell_is_projectable(info->index)) dam = adjust_dam(player, spell->effect->params[0], dam, MAXIMISE, 1); /* Add the power rating (crucial for non-damaging spells) */ /* First we adjust the real damage if necessary */ if (spell->power.dice) dam = (dam * spell->power.dice) / 100; /* Then we add any flat rating for this effect */ dam += spell->power.base; /* Then we add any rlev-dependent rating */ if (spell->power.m_bonus == 1) dam += (spell->power.sides * rlev) / 100; else if (spell->power.m_bonus == 2) dam += spell->power.sides / (rlev + 1); } /* Update the best_dam tracker */ if (dam > best_dam) best_dam = dam; } return best_dam; }
/** * Process a monster spell * * \param spell is the monster spell flag (RSF_FOO) * \param m_idx is the attacking monster * \param seen is whether the player can see the monster at this moment */ void do_mon_spell(int spell, int m_idx, bool seen) { const struct mon_spell *rs_ptr = &mon_spell_table[spell]; monster_type *m_ptr = cave_monster(cave, m_idx); monster_race *r_ptr = &r_info[m_ptr->r_idx]; char m_name[80], ddesc[80]; bool hits = FALSE; int dam = 0, flag = 0, rad = 0; /* Extract the monster level */ int rlev = ((r_ptr->level >= 1) ? r_ptr->level : 1); /* Get the monster name (or "it") */ monster_desc(m_name, sizeof(m_name), m_ptr, 0x00); /* See if it hits */ if (rs_ptr->hit == 100) hits = TRUE; else if (rs_ptr->hit == 0) hits = FALSE; else hits = check_hit(p_ptr, rs_ptr->hit, rlev); /* Tell the player what's going on */ disturb(p_ptr, 1,0); if (!seen) msg("Something %s.", rs_ptr->blind_verb); else if (!hits) { msg("%^s %s %s, but misses.", m_name, rs_ptr->verb, rs_ptr->desc); return; } else if (rs_ptr->msgt) msgt(rs_ptr->msgt, "%^s %s %s.", m_name, rs_ptr->verb, rs_ptr->desc); else msg("%^s %s %s.", m_name, rs_ptr->verb, rs_ptr->desc); /* Try a saving throw if available */ if (rs_ptr->save && randint0(100) < p_ptr->state.skills[SKILL_SAVE]) { msg("You avoid the effects!"); return; } /* Calculate the damage */ dam = mon_spell_dam(spell, m_ptr->hp, rlev, RANDOMISE); /* Get the "died from" name in case this attack kills @ */ monster_desc(ddesc, sizeof(ddesc), m_ptr, MDESC_SHOW | MDESC_IND2); /* Display the attack, adjust for resists and apply effects */ if (rs_ptr->type & RST_BOLT) flag = PROJECT_STOP | PROJECT_KILL; else if (rs_ptr->type & (RST_BALL | RST_BREATH)) { flag = PROJECT_GRID | PROJECT_ITEM | PROJECT_KILL; rad = rf_has(r_ptr->flags, RF_POWERFUL) ? 3 : 2; } if (rs_ptr->gf) { (void)project(m_idx, rad, p_ptr->py, p_ptr->px, dam, rs_ptr->gf, flag); monster_learn_resists(m_ptr, p_ptr, rs_ptr->gf); } else /* Note that non-projectable attacks are unresistable */ take_hit(p_ptr, dam, ddesc); do_side_effects(spell, dam, m_idx, seen); return; }