diff --git a/zone/bot.cpp b/zone/bot.cpp index 3308a343c..0cb352a18 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -6747,97 +6747,49 @@ int32 Bot::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) { } int32 Bot::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) { - - - if (IsNPC()) { - value += value * CastToNPC()->GetSpellFocusHeal() / 100; - } + if (target == nullptr) + target = this; int32 value_BaseEffect = 0; - int16 critical_chance = 0; - int8 critical_modifier = 1; - - if (spells[spell_id].buffduration < 1) { - critical_chance += itembonuses.CriticalHealChance + spellbonuses.CriticalHealChance + aabonuses.CriticalHealChance; - - if (spellbonuses.CriticalHealDecay) { - critical_chance += GetDecayEffectValue(spell_id, SE_CriticalHealDecay); - } - } - else { - critical_chance = itembonuses.CriticalHealOverTime + spellbonuses.CriticalHealOverTime + aabonuses.CriticalHealOverTime; - - if (spellbonuses.CriticalRegenDecay) { - critical_chance += GetDecayEffectValue(spell_id, SE_CriticalRegenDecay); - } - } - - if (critical_chance) { - - if (spells[spell_id].override_crit_chance > 0 && critical_chance > spells[spell_id].override_crit_chance) { - critical_chance = spells[spell_id].override_crit_chance; - } - - if (zone->random.Roll(critical_chance)) { - critical_modifier = 2; //At present time no critical heal amount modifier SPA exists. - } - } - - value_BaseEffect = value + (value*GetFocusEffect(focusFcBaseEffects, spell_id) / 100); - + int32 chance = 0; + int8 modifier = 1; + bool Critical = false; + value_BaseEffect = (value + (value*GetBotFocusEffect(focusFcBaseEffects, spell_id) / 100)); value = value_BaseEffect; - - if (GetClass() == CLERIC) { - value += int(value_BaseEffect*RuleI(Spells, ClericInnateHealFocus) / 100); //confirmed on live parsing clerics get an innate 5 pct heal focus - } value += int(value_BaseEffect*GetBotFocusEffect(focusImprovedHeal, spell_id) / 100); - value += int(value_BaseEffect*GetBotFocusEffect(focusFcAmplifyMod, spell_id) / 100); + if(spells[spell_id].buffduration < 1) { + chance += (itembonuses.CriticalHealChance + spellbonuses.CriticalHealChance + aabonuses.CriticalHealChance); + chance += target->GetFocusIncoming(focusFcHealPctCritIncoming, SE_FcHealPctCritIncoming, this, spell_id); + if (spellbonuses.CriticalHealDecay) + chance += GetDecayEffectValue(spell_id, SE_CriticalHealDecay); - // Instant Heals - if (spells[spell_id].buffduration < 1) { - - if (target) { - value += int(value_BaseEffect + target->GetFocusEffect(focusFcHealPctIncoming, spell_id) / 100); //SPA 393 Add before critical - value += int(value_BaseEffect + target->GetFocusEffect(focusFcHealPctCritIncoming, spell_id) / 100); //SPA 395 Add before critical (?) + if(chance && (zone->random.Int(0, 99) < chance)) { + Critical = true; + modifier = 2; } - value += GetFocusEffect(focusFcHealAmtCrit, spell_id); //SPA 396 Add before critical + value *= modifier; + value += (GetBotFocusEffect(focusFcHealAmtCrit, spell_id) * modifier); + value += GetBotFocusEffect(focusFcHealAmt, spell_id); + value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id); - if (!spells[spell_id].no_heal_damage_item_mod && itembonuses.HealAmt && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5) { - value += GetExtraSpellAmt(spell_id, itembonuses.HealAmt, value); //Item Heal Amt Add before critical - } + if(itembonuses.HealAmt && spells[spell_id].classes[(GetClass() % 17) - 1] >= GetLevel() - 5) + value += (GetExtraSpellAmt(spell_id, itembonuses.HealAmt, value) * modifier); - if (target) { - int incoming_heal_mod_percent = target->itembonuses.HealRate + target->spellbonuses.HealRate + target->aabonuses.HealRate; //SPA 120 modifies value after Focus Applied but before critical - incoming_heal_mod_percent = std::min(incoming_heal_mod_percent, -100); - value += value * incoming_heal_mod_percent / 100; - } - - /* - Apply critical hit modifier - */ - - value *= critical_modifier; - value += GetBotFocusEffect(focusFcHealAmt, spell_id); //SPA 392 Add after critical - value += GetBotFocusEffect(focusFcAmplifyAmt, spell_id); //SPA 508 ? Add after critical - - if (target) { - value += target->GetFocusEffect(focusFcHealAmtIncoming, spell_id); //SPA 394 Add after critical - } - - if (critical_modifier > 1) { + value += (value * target->GetHealRate(spell_id, this) / 100); + if (Critical) entity_list.MessageClose(this, false, 100, Chat::SpellCrit, "%s performs an exceptional heal! (%d)", GetName(), value); - } return value; - } + } else { + chance = (itembonuses.CriticalHealOverTime + spellbonuses.CriticalHealOverTime + aabonuses.CriticalHealOverTime); + chance += target->GetFocusIncoming(focusFcHealPctCritIncoming, SE_FcHealPctCritIncoming, this, spell_id); + if (spellbonuses.CriticalRegenDecay) + chance += GetDecayEffectValue(spell_id, SE_CriticalRegenDecay); - //Heal over time spells. [Heal Rate and Additional Healing effects do not increase this value] - else { - if (critical_chance && zone->random.Roll(critical_chance)) - value *= critical_modifier; + if(chance && (zone->random.Int(0,99) < chance)) + return (value * 2); } - return value; } diff --git a/zone/mob.h b/zone/mob.h index cda5285d0..3975efb90 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -803,6 +803,7 @@ public: uint16 GetSpellEffectResistChance(uint16 spell_id); int32 GetVulnerability(Mob* caster, uint32 spell_id, uint32 ticsremaining); int32 GetFcDamageAmtIncoming(Mob *caster, uint32 spell_id, bool use_skill = false, uint16 skill=0); + int32 GetFocusIncoming(focusType type, int effect, Mob *caster, uint32 spell_id); int32 GetSkillDmgTaken(const EQ::skills::SkillType skill_used, ExtraAttackOptions *opts = nullptr); int32 GetPositionalDmgTaken(Mob *attacker); int32 GetPositionalDmgTakenAmt(Mob *attacker); @@ -842,6 +843,7 @@ public: bool HarmonySpellLevelCheck(int32 spell_id, Mob* target = nullptr); bool CanFocusUseRandomEffectivenessByType(focusType type); int GetFocusRandomEffectivenessValue(int focus_base, int focus_base2, bool best_focus = 0); + int GetHealRate() const { return itembonuses.HealRate + spellbonuses.HealRate + aabonuses.HealRate; } bool TryDoubleMeleeRoundEffect(); bool GetUseDoubleMeleeRoundDmgBonus() const { return use_double_melee_round_dmg_bonus; } diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index a268327d9..5218afa69 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -6930,6 +6930,58 @@ int32 Mob::GetFcDamageAmtIncoming(Mob *caster, uint32 spell_id, bool use_skill, return dmg; } +int32 Mob::GetFocusIncoming(focusType type, int effect, Mob *caster, uint32 spell_id) { + + /* + This is a general function for calculating best focus effect values for focus effects that exist on targets but modify incoming spells. + Should be used when checking for foci that can exist on clients or npcs ect. + Example: When your target has a focus limited buff that increases amount of healing on them. + */ + + if (!caster) { + return 0; + } + + int value = 0; + + if (spellbonuses.FocusEffects[type]){ + + int32 tmp_focus = 0; + int tmp_buffslot = -1; + + int buff_count = GetMaxTotalSlots(); + for(int i = 0; i < buff_count; i++) { + + if((IsValidSpell(buffs[i].spellid) && IsEffectInSpell(buffs[i].spellid, effect))){ + + int32 focus = caster->CalcFocusEffect(type, buffs[i].spellid, spell_id); + + if (!focus) { + continue; + } + + if (tmp_focus && focus > tmp_focus){ + tmp_focus = focus; + tmp_buffslot = i; + } + + else if (!tmp_focus){ + tmp_focus = focus; + tmp_buffslot = i; + } + } + } + + value = tmp_focus; + + if (tmp_buffslot >= 0) + CheckNumHitsRemaining(NumHit::MatchingSpells, tmp_buffslot); + } + + + return value; +} + int32 Mob::ApplySpellEffectiveness(int16 spell_id, int32 value, bool IsBard, uint16 caster_id) { // 9-17-12: This is likely causing crashes, disabled till can resolve.