From 58d585e2a6b4d3d1f7ba481ffd0d302154fd7828 Mon Sep 17 00:00:00 2001 From: KayenEQ Date: Fri, 4 Jul 2014 23:35:15 -0400 Subject: [PATCH] Updated SE_Sanctuary - Adjust way hate lowering effect worked to be more accurate Updated SE_SympatheticProc - Revised proc rate formula to be accurate to live. Sympathetic foci on items with proc rate mod will now benefit from that modifier. Sympathetic foci can now be placed on AA's (This should always be slot1 in the AA) Implemented SE_IllusionPersistence- Allows illusions to last until you die or the illusion is forcibly removed. Added rule 'PreNerftBardAEDot' for SE_BardAEDot to allow it to once again do damage to moving targets. (Set to true) --- changelog.txt | 11 + common/ruletypes.h | 1 + common/spdat.h | 2 +- .../git/required/2014_07_04_AA_Updates.sql | 6 + zone/bonuses.cpp | 19 ++ zone/bot.cpp | 6 +- zone/client.h | 5 +- zone/common.h | 2 +- zone/hate_list.cpp | 10 + zone/mob.cpp | 8 + zone/mob.h | 3 +- zone/spell_effects.cpp | 229 ++++++++++-------- 12 files changed, 187 insertions(+), 115 deletions(-) create mode 100644 utils/sql/git/required/2014_07_04_AA_Updates.sql diff --git a/changelog.txt b/changelog.txt index 1e371109d..59f39c327 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,16 @@ EQEMu Changelog (Started on Sept 24, 2003 15:50) ------------------------------------------------------- +== 07/5/2014 == +Kayen: Updated SE_Sanctuary - Adjust way hate lowering effect worked to be more accurate +Kayen: Updated SE_SympatheticProc - Revised proc rate formula to be accurate to live. +Sympathetic foci on items with proc rate mod will now benefit from that modifier. +Sympathetic foci can now be placed on AA's (This should always be slot1 in the AA) +Kayen: Implemented SE_IllusionPersistence- Allows illusions to last until you die or the illusion is forcibly removed. +Kayen: Added rule 'PreNerftBardAEDot' for SE_BardAEDot to allow it to once again do damage to moving targets. (Set to true) + +Required SQL: utils/sql/git/required/2014_07_04_AA_Update.sql + + == 07/2/2014 == Kayen: Implemented SE_Sanctuary - Places caster at bottom hate list, effect fades if caster cast spell on targets other than self. Kayen: Implemented SE_ResourceTap - Coverts a percent of dmg from dmg spells(DD/DoT) to hp/mana/end. diff --git a/common/ruletypes.h b/common/ruletypes.h index 6f5fe0769..8c9ac543e 100644 --- a/common/ruletypes.h +++ b/common/ruletypes.h @@ -310,6 +310,7 @@ RULE_INT ( Spells, FRProjectileItem_SOF, 80684) // Item id for SOF clients for F RULE_INT ( Spells, FRProjectileItem_NPC, 80684) // Item id for NPC Fire 'spell projectile'. RULE_BOOL ( Spells, UseLiveSpellProjectileGFX, false) // Use spell projectile graphics set in the spells_new table (player_1). Server must be using UF+ spell file. RULE_BOOL ( Spells, FocusCombatProcs, false) //Allow all combat procs to receive focus effects. +RULE_BOOL ( Spells, PreNerfBardAEDoT, false) //Allow bard AOE dots to damage targets when moving. RULE_CATEGORY_END() RULE_CATEGORY( Combat ) diff --git a/common/spdat.h b/common/spdat.h index 02dca8ff7..42091338a 100644 --- a/common/spdat.h +++ b/common/spdat.h @@ -385,7 +385,7 @@ typedef enum { #define SE_ChannelChanceSpells 235 // implemented[AA] - chance to channel from SPELLS *No longer used on live. //#define SE_FreePet 236 // not used #define SE_GivePetGroupTarget 237 // implemented[AA] - (Pet Affinity) -//#define SE_IllusionPersistence 238 // *not implemented - lends persistence to your illusionary disguises, causing them to last until you die or the illusion is forcibly removed. +#define SE_IllusionPersistence 238 // implemented - lends persistence to your illusionary disguises, causing them to last until you die or the illusion is forcibly removed. //#define SE_FeignedCastOnChance 239 // *not implemented as bonus - ability gives you an increasing chance for your feigned deaths to not be revealed by spells cast upon you. //#define SE_StringUnbreakable 240 // not used [Likely related to above - you become immune to feign breaking on a resisted spell and have a good chance of feigning through a spell that successfully lands upon you.] #define SE_ImprovedReclaimEnergy 241 // implemented - increase the amount of mana returned to you when reclaiming your pet. diff --git a/utils/sql/git/required/2014_07_04_AA_Updates.sql b/utils/sql/git/required/2014_07_04_AA_Updates.sql new file mode 100644 index 000000000..a943e8c15 --- /dev/null +++ b/utils/sql/git/required/2014_07_04_AA_Updates.sql @@ -0,0 +1,6 @@ +-- AA Permanent Illusion +INSERT INTO `aa_effects` (`aaid`, `slot`, `effectid`, `base1`, `base2`) VALUES ('158', '1', '238', '1', '0'); + +-- AA Sanctuary +INSERT INTO `altadv_vars` (`skill_id`, `name`, `cost`, `max_level`, `hotkey_sid`, `hotkey_sid2`, `title_sid`, `desc_sid`, `type`, `spellid`, `prereq_skill`, `prereq_minpoints`, `spell_type`, `spell_refresh`, `classes`, `berserker`, `class_type`, `cost_inc`, `aa_expansion`, `special_category`, `sof_type`, `sof_cost_inc`, `sof_max_level`, `sof_next_skill`, `clientver`, `account_time_required`, `sof_current_level`,`sof_next_id`,`level_inc`) VALUES ('1209', 'Sanctuary', '12', '1', '1209', '4294967295', '1209', '1209', '3', '5912', '0', '0', '14', '4320', '4', '0', '70', '0', '8', '4294967295', '3', '0', '1', '1209', '1', '0', '0', '0', '0'); +INSERT INTO `aa_actions` (`aaid`, `rank`, `reuse_time`, `spell_id`, `target`, `nonspell_action`, `nonspell_mana`, `nonspell_duration`, `redux_aa`, `redux_rate`, `redux_aa2`, `redux_rate2`) VALUES ('1209', '0', '4320', '5912', '1', '0', '0', '0', '0', '0', '0', '0'); diff --git a/zone/bonuses.cpp b/zone/bonuses.cpp index 48a3d95e1..b21eeaa0a 100644 --- a/zone/bonuses.cpp +++ b/zone/bonuses.cpp @@ -1329,6 +1329,10 @@ void Client::ApplyAABonuses(uint32 aaid, uint32 slots, StatBonuses* newbon) break; } + case SE_IllusionPersistence: + newbon->IllusionPersistence = true; + break; + } } } @@ -2876,6 +2880,10 @@ void Mob::ApplySpellsBonuses(uint16 spell_id, uint8 casterlevel, StatBonuses* ne break; } + case SE_IllusionPersistence: + newbon->IllusionPersistence = true; + break; + //Special custom cases for loading effects on to NPC from 'npc_spels_effects' table if (IsAISpellEffect) { @@ -4356,6 +4364,17 @@ void Mob::NegateSpellsBonuses(uint16 spell_id) aabonuses.FactionModPct = effect_value; break; + case SE_MeleeVulnerability: + spellbonuses.MeleeVulnerability = effect_value; + itembonuses.MeleeVulnerability = effect_value; + aabonuses.MeleeVulnerability = effect_value; + break; + + case SE_IllusionPersistence: + spellbonuses.IllusionPersistence = effect_value; + itembonuses.IllusionPersistence = effect_value; + aabonuses.IllusionPersistence = effect_value; + break; } } } diff --git a/zone/bot.cpp b/zone/bot.cpp index e961bd7ec..a1a31740e 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -7641,10 +7641,8 @@ int16 Bot::CalcBotFocusEffect(BotfocusType bottype, uint16 focus_id, uint16 spel { if(bottype == BotfocusSympatheticProc) { - float ProcChance, ProcBonus; - int16 ProcRateMod = focus_spell.base[i]; //Baseline is 100 for most Sympathetic foci - int32 cast_time = GetActSpellCasttime(spell_id, spells[spell_id].cast_time); - GetSympatheticProcChances(ProcBonus, ProcChance, cast_time, ProcRateMod); + + float ProcChance = GetSympatheticProcChances(spell_id, focus_spell.base[i]); if(MakeRandomFloat(0, 1) <= ProcChance) value = focus_id; diff --git a/zone/client.h b/zone/client.h index 9e2503df2..e26465628 100644 --- a/zone/client.h +++ b/zone/client.h @@ -776,7 +776,10 @@ public: int GetSpentAA() { return m_pp.aapoints_spent; } void RefundAA(); void IncrementAA(int aa_id); - + int32 GetAAEffectDataBySlot(uint32 aa_ID, uint32 slot_id, bool GetEffect, bool GetBase1, bool GetBase2); + int32 GetAAEffectid(uint32 aa_ID, uint32 slot_id) { return GetAAEffectDataBySlot(aa_ID, slot_id, true, false,false); } + int32 GetAABase1(uint32 aa_ID, uint32 slot_id) { return GetAAEffectDataBySlot(aa_ID, slot_id, false, true,false); } + int32 GetAABase2(uint32 aa_ID, uint32 slot_id) { return GetAAEffectDataBySlot(aa_ID, slot_id, false, false,true); } int16 acmod(); // Item methods diff --git a/zone/common.h b/zone/common.h index e3a9dfb09..98e2ebcec 100644 --- a/zone/common.h +++ b/zone/common.h @@ -431,7 +431,7 @@ struct StatBonuses { uint32 Assassinate[2]; // Assassinate AA (Massive dmg vs humaniod w/ assassinate) 0= ? 1= Dmg uint8 AssassinateLevel; // Max Level Assassinate will be effective at. int32 PetMeleeMitigation; // Add AC to owner's pet. - + bool IllusionPersistence; // Causes illusions not to fade. }; typedef struct diff --git a/zone/hate_list.cpp b/zone/hate_list.cpp index 68dd2a6cb..abe32b5a7 100644 --- a/zone/hate_list.cpp +++ b/zone/hate_list.cpp @@ -308,6 +308,16 @@ Mob *HateList::GetTop(Mob *center) } } + if (cur->ent->Sanctuary()) { + if(hate == -1) + { + top = cur->ent; + hate = 1; + } + ++iterator; + continue; + } + if(cur->ent->DivineAura() || cur->ent->IsMezzed() || cur->ent->IsFeared()){ if(hate == -1) { diff --git a/zone/mob.cpp b/zone/mob.cpp index 59e02568b..93b9f5047 100644 --- a/zone/mob.cpp +++ b/zone/mob.cpp @@ -2761,6 +2761,14 @@ bool Mob::DivineAura() const return false; } +bool Mob::Sanctuary() const +{ + if (spellbonuses.Sanctuary) + return true; + + return false; +} + int16 Mob::GetResist(uint8 type) const { if (IsNPC()) diff --git a/zone/mob.h b/zone/mob.h index 0476a20dc..cb44dd80c 100644 --- a/zone/mob.h +++ b/zone/mob.h @@ -820,6 +820,7 @@ public: void SetNextIncHPEvent( int inchpevent ); bool DivineAura() const; + bool Sanctuary() const; bool HasNPCSpecialAtk(const char* parse); int GetSpecialAbility(int ability); @@ -1009,7 +1010,7 @@ protected: Map::Vertex UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &WaypointChange, bool &NodeReached); void PrintRoute(); - virtual float GetSympatheticProcChances(float &ProcBonus, float &ProcChance, int32 cast_time, int16 ProcRateMod); + virtual float GetSympatheticProcChances(uint16 spell_id, int16 ProcRateMod, int32 ItemProcRate = 0); enum {MAX_PROCS = 4}; tProc PermaProcs[MAX_PROCS]; diff --git a/zone/spell_effects.cpp b/zone/spell_effects.cpp index 61333edfd..b92ea524c 100644 --- a/zone/spell_effects.cpp +++ b/zone/spell_effects.cpp @@ -1430,7 +1430,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) for(int x = 0; x < 7; x++){ SendWearChange(x); } - if(caster && caster->GetAA(aaPermanentIllusion)) + if(caster && (caster->spellbonuses.IllusionPersistence || caster->aabonuses.IllusionPersistence + || caster->itembonuses.IllusionPersistence)) buffs[buffslot].persistant_buff = 1; else buffs[buffslot].persistant_buff = 0; @@ -2329,7 +2330,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) if (buffslot >= 0) break; //This effect does no damage if target is moving. - if (IsMoving()) + if (!RuleB(Spells, PreNerfBardAEDoT) && IsMoving()) break; // for offensive spells check if we have a spell rune on @@ -2735,22 +2736,6 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) break; } - case SE_Sanctuary: - { - std::list npc_list; - entity_list.GetNPCList(npc_list); - - for(std::list::iterator itr = npc_list.begin(); itr != npc_list.end(); ++itr) { - - NPC* npc = *itr; - - if (npc && npc->CheckAggro(this)) - npc->SetHate(caster, 1); - - } - break; - } - // Handled Elsewhere case SE_ImmuneFleeing: case SE_NegateSpellEffect: @@ -2984,6 +2969,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial) case SE_AssassinateLevel: case SE_FactionModPct: case SE_LimitSpellClass: + case SE_Sanctuary: { break; } @@ -3403,7 +3389,7 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste { effect_value = CalcSpellEffectValue(spell_id, i, caster_level, caster); - if (IsMoving() || invulnerable || /*effect_value > 0 ||*/ DivineAura()) + if ((!RuleB(Spells, PreNerfBardAEDoT) && IsMoving()) || invulnerable || /*effect_value > 0 ||*/ DivineAura()) break; if(effect_value < 0) { @@ -3630,21 +3616,6 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste break; } - case SE_Sanctuary: - { - std::list npc_list; - entity_list.GetNPCList(npc_list); - - for(std::list::iterator itr = npc_list.begin(); itr != npc_list.end(); ++itr) { - - NPC* npc = *itr; - - if (npc && npc->CheckAggro(this)) - npc->SetHate(caster, 1); - - } - break; - } default: { @@ -4084,39 +4055,41 @@ void Mob::BuffFadeBySlot(int slot, bool iRecalcBonuses) CalcBonuses(); } -/* No longer used. -int16 Client::CalcAAFocusEffect(focusType type, uint16 focus_spell, uint16 spell_id) +int32 Client::GetAAEffectDataBySlot(uint32 aa_ID, uint32 slot_id, bool GetEffect, bool GetBase1, bool GetBase2) { - uint32 slots = 0; - uint32 aa_AA = 0; - uint32 aa_value = 0; + int32 aa_effects_data[3] = { 0 }; + uint32 effect = 0; + int32 base1 = 0; + int32 base2 = 0; + uint32 slot = 0; - int32 value = 0; - // Iterate through all of the client's AAs - for (int i = 0; i < MAX_PP_AA_ARRAY; i++) + + std::map >::const_iterator find_iter = aa_effects.find(aa_ID); + if(find_iter == aa_effects.end()) + return 0; + + for (std::map::const_iterator iter = aa_effects[aa_ID].begin(); iter != aa_effects[aa_ID].end(); ++iter) { - aa_AA = this->aa[i]->AA; - aa_value = this->aa[i]->value; - if (aa_AA > 0 || aa_value > 0) - { - slots = zone->GetTotalAALevels(aa_AA); - if (slots > 0) - for(int j = 1;j <= slots; j++) - { - switch (aa_effects[aa_AA][j].skill_id) - { - case SE_TriggerOnCast: - // If focus_spell matches the spell listed in the DB, load these restrictions - if(type == focusTriggerOnCast && focus_spell == aa_effects[aa_AA][j].base1) - value = CalcAAFocus(type, aa_AA, spell_id); - break; - } - } + effect = iter->second.skill_id; + base1 = iter->second.base1; + base2 = iter->second.base2; + slot = iter->second.slot; + + if (slot && slot == slot_id) { + + if (GetEffect) + return effect; + + if (GetBase1) + return base1; + + if (GetBase2) + return base2; } } - return value; + + return 0; } -*/ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) @@ -4496,9 +4469,11 @@ int16 Client::CalcAAFocus(focusType type, uint32 aa_ID, uint16 spell_id) value = base1; break; - case SE_SympatheticProc: - //No AA support at this time. - break; + //Note if using these as AA, make sure this is first focus used. + case SE_SympatheticProc: + if(type == focusSympatheticProc) + value = base2; + break; case SE_FcDamageAmt: if(type == focusFcDamageAmt) @@ -4962,16 +4937,7 @@ int16 Mob::CalcFocusEffect(focusType type, uint16 focus_id, uint16 spell_id, boo case SE_SympatheticProc: if(type == focusSympatheticProc) { - float ProcChance, ProcBonus; - int16 ProcRateMod = focus_spell.base[i]; //Baseline is 100 for most Sympathetic foci - int32 cast_time = GetActSpellCasttime(spell_id, spells[spell_id].cast_time); - GetSympatheticProcChances(ProcBonus, ProcChance, cast_time, ProcRateMod); - - if(MakeRandomFloat(0, 1) <= ProcChance) - value = focus_id; - - else - value = 0; + value = focus_id; } break; @@ -5089,8 +5055,8 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { return 0; uint16 proc_spellid = 0; - uint8 SizeProcList = 0; uint8 MAX_SYMPATHETIC = 10; + float ProcChance = 0.0f; std::vector SympatheticProcList; @@ -5101,7 +5067,7 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { for(int x=0; x<=21; x++) { - if (SizeProcList > MAX_SYMPATHETIC) + if (SympatheticProcList.size() > MAX_SYMPATHETIC) continue; TempItem = nullptr; @@ -5109,20 +5075,22 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { if (!ins) continue; TempItem = ins->GetItem(); - if (TempItem && TempItem->Focus.Effect > 0 && TempItem->Focus.Effect != SPELL_UNKNOWN) { + if (TempItem && TempItem->Focus.Effect > 0 && IsValidSpell(TempItem->Focus.Effect)) { - proc_spellid = CalcFocusEffect(type, TempItem->Focus.Effect, spell_id); + proc_spellid = CalcFocusEffect(type, TempItem->Focus.Effect, spell_id); + + if (IsValidSpell(proc_spellid)){ - if (proc_spellid > 0) - { - SympatheticProcList.push_back(proc_spellid); - SizeProcList = SympatheticProcList.size(); - } + ProcChance = GetSympatheticProcChances(spell_id, spells[TempItem->Focus.Effect].base[0], TempItem->ProcRate); + + if(MakeRandomFloat(0, 1) <= ProcChance) + SympatheticProcList.push_back(proc_spellid); + } } for(int y = 0; y < MAX_AUGMENT_SLOTS; ++y) { - if (SizeProcList > MAX_SYMPATHETIC) + if (SympatheticProcList.size() > MAX_SYMPATHETIC) continue; ItemInst *aug = nullptr; @@ -5130,14 +5098,16 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { if(aug) { const Item_Struct* TempItemAug = aug->GetItem(); - if (TempItemAug && TempItemAug->Focus.Effect > 0 && TempItemAug->Focus.Effect != SPELL_UNKNOWN) { + if (TempItemAug && TempItemAug->Focus.Effect > 0 && IsValidSpell(TempItemAug->Focus.Effect)) { proc_spellid = CalcFocusEffect(type, TempItemAug->Focus.Effect, spell_id); - if (proc_spellid > 0) - { - SympatheticProcList.push_back(proc_spellid); - SizeProcList = SympatheticProcList.size(); + if (IsValidSpell(proc_spellid)){ + + ProcChance = GetSympatheticProcChances(spell_id, spells[TempItem->Focus.Effect].base[0], TempItemAug->ProcRate); + + if(MakeRandomFloat(0, 1) <= ProcChance) + SympatheticProcList.push_back(proc_spellid); } } } @@ -5152,26 +5122,57 @@ int16 Client::GetSympatheticFocusEffect(focusType type, uint16 spell_id) { uint32 buff_max = GetMaxTotalSlots(); for (buff_slot = 0; buff_slot < buff_max; buff_slot++) { - if (SizeProcList > MAX_SYMPATHETIC) + if (SympatheticProcList.size() > MAX_SYMPATHETIC) continue; focusspellid = buffs[buff_slot].spellid; - if (focusspellid == 0 || focusspellid >= SPDAT_RECORDS) + if (IsValidSpell(focusspellid)) continue; proc_spellid = CalcFocusEffect(type, focusspellid, spell_id); - if (proc_spellid > 0) - { - SympatheticProcList.push_back(proc_spellid); - SizeProcList = SympatheticProcList.size(); - } + if (IsValidSpell(proc_spellid)){ + + ProcChance = GetSympatheticProcChances(spell_id, spells[focusspellid].base[0]); + + if(MakeRandomFloat(0, 1) <= ProcChance) + SympatheticProcList.push_back(proc_spellid); + } } } - if (SizeProcList > 0) + /*Note: At present, ff designing custom AA to have a sympathetic proc effect, only use one focus + effect within the aa_effects data for each AA*[No live AA's use this effect to my knowledge]*/ + if (aabonuses.FocusEffects[type]){ + + uint32 aa_AA = 0; + uint32 aa_value = 0; + + for (int i = 0; i < MAX_PP_AA_ARRAY; i++) + { + aa_AA = this->aa[i]->AA; + aa_value = this->aa[i]->value; + if (aa_AA < 1 || aa_value < 1) + continue; + + if (SympatheticProcList.size() > MAX_SYMPATHETIC) + continue; + + proc_spellid = CalcAAFocus(type, aa_AA, spell_id); + + if (IsValidSpell(proc_spellid)){ + + ProcChance = GetSympatheticProcChances(spell_id, GetAABase1(aa_AA, 1)); + + if(MakeRandomFloat(0, 1) <= ProcChance) + SympatheticProcList.push_back(proc_spellid); + } + } + } + + if (SympatheticProcList.size() > 0) { - uint8 random = MakeRandomInt(0, SizeProcList-1); + uint8 random = MakeRandomInt(0, SympatheticProcList.size()-1); int FinalSympatheticProc = SympatheticProcList[random]; SympatheticProcList.clear(); return FinalSympatheticProc; @@ -5674,17 +5675,31 @@ bool Mob::AffectedBySpellExcludingSlot(int slot, int effect) return false; } -float Mob::GetSympatheticProcChances(float &ProcBonus, float &ProcChance, int32 cast_time, int16 ProcRateMod) { +float Mob::GetSympatheticProcChances(uint16 spell_id, int16 ProcRateMod, int32 ItemProcRate) { - ProcChance = 0; + float ProcChance = 0.0f; + int32 total_cast_time = 0; + float cast_time_mod = 0.0f; + ProcRateMod -= 100; + - if(cast_time > 0) - { - ProcChance = ((float)cast_time * RuleR(Casting, AvgSpellProcsPerMinute) / 60000.0f); - ProcChance = ProcChance * (float)(ProcRateMod/100); - } - return ProcChance; -} + if (spells[spell_id].recast_time >= spells[spell_id].recovery_time) + total_cast_time = spells[spell_id].recast_time + spells[spell_id].cast_time; + else + total_cast_time = spells[spell_id].recovery_time + spells[spell_id].cast_time; + + if (total_cast_time > 0 && total_cast_time <= 2500) + cast_time_mod = 0.25f; + else if (total_cast_time > 2500 && total_cast_time < 7000) + cast_time_mod = 0.167*((static_cast(total_cast_time) - 1000.0f)/1000.0f); + else + cast_time_mod = static_cast(total_cast_time) / 7000.0f; + + ProcChance = (RuleR(Casting, AvgSpellProcsPerMinute)/100.0f) * (static_cast(100.0f + ProcRateMod) / 10.0f) + * cast_time_mod * (static_cast(100.0f + ItemProcRate)/100.0f); + + return ProcChance; + } bool Mob::DoHPToManaCovert(uint16 mana_cost) {