Implemented support for allowing most focus effects to now be usable

by NPCs (ie Heal/Damage focus, cast time, spell range ect) from
both spell buffs and items.
Rule for enabling spell focus is TRUE by default
Rule for enabling item focus is FALSE by default.

Consilidated a number of redundant client / mob functions
to use the same pathway for calculating effect values.
This commit is contained in:
KayenEQ 2014-12-08 01:22:01 -05:00
parent f81f62670e
commit 70f570dbd9
15 changed files with 250 additions and 361 deletions

View File

@ -325,6 +325,8 @@ RULE_INT ( Spells, AI_IdleBeneficialChance, 100) // Chance while idle to do a be
RULE_BOOL ( Spells, SHDProcIDOffByOne, true) // pre June 2009 SHD spell procs were off by 1, they stopped doing this in June 2009 (so UF+ spell files need this false) RULE_BOOL ( Spells, SHDProcIDOffByOne, true) // pre June 2009 SHD spell procs were off by 1, they stopped doing this in June 2009 (so UF+ spell files need this false)
RULE_BOOL ( Spells, Jun182014HundredHandsRevamp, false) // this should be true for if you import a spell file newer than June 18, 2014 RULE_BOOL ( Spells, Jun182014HundredHandsRevamp, false) // this should be true for if you import a spell file newer than June 18, 2014
RULE_BOOL ( Spells, SwarmPetTargetLock, false) // Use old method of swarm pets target locking till target dies then despawning. RULE_BOOL ( Spells, SwarmPetTargetLock, false) // Use old method of swarm pets target locking till target dies then despawning.
RULE_BOOL ( Spells, NPC_UseFocusFromSpells, true) // Allow npcs to use most spell derived focus effects.
RULE_BOOL ( Spells, NPC_UseFocusFromItems, false) // Allow npcs to use most item derived focus effects.
RULE_CATEGORY_END() RULE_CATEGORY_END()
RULE_CATEGORY( Combat ) RULE_CATEGORY( Combat )

View File

@ -519,8 +519,7 @@ void Mob::TemporaryPets(uint16 spell_id, Mob *targ, const char *name_override, u
} }
} }
if(IsClient()) pet.duration += GetFocusEffect(focusSwarmPetDuration, spell_id) / 1000;
pet.duration += (CastToClient()->GetFocusEffect(focusSwarmPetDuration, spell_id) / 1000);
pet.npc_id = record.npc_type; pet.npc_id = record.npc_type;

View File

@ -1128,8 +1128,7 @@ int32 Mob::CheckAggroAmount(uint16 spell_id, bool isproc)
int HateMod = RuleI(Aggro, SpellAggroMod); int HateMod = RuleI(Aggro, SpellAggroMod);
if (IsClient()) HateMod += GetFocusEffect(focusSpellHateMod, spell_id);
HateMod += CastToClient()->GetFocusEffect(focusSpellHateMod, spell_id);
AggroAmount = (AggroAmount * HateMod) / 100; AggroAmount = (AggroAmount * HateMod) / 100;
@ -1178,8 +1177,7 @@ int32 Mob::CheckHealAggroAmount(uint16 spell_id, uint32 heal_possible)
if (AggroAmount > 0) { if (AggroAmount > 0) {
int HateMod = RuleI(Aggro, SpellAggroMod); int HateMod = RuleI(Aggro, SpellAggroMod);
if (IsClient()) HateMod += GetFocusEffect(focusSpellHateMod, spell_id);
HateMod += CastToClient()->GetFocusEffect(focusSpellHateMod, spell_id);
//Live AA - Spell casting subtlety //Live AA - Spell casting subtlety
HateMod += aabonuses.hatemod + spellbonuses.hatemod + itembonuses.hatemod; HateMod += aabonuses.hatemod + spellbonuses.hatemod + itembonuses.hatemod;

View File

@ -1386,15 +1386,6 @@ void Client::Damage(Mob* other, int32 damage, uint16 spell_id, SkillUseTypes att
if(spell_id==0) if(spell_id==0)
spell_id = SPELL_UNKNOWN; spell_id = SPELL_UNKNOWN;
if(spell_id!=0 && spell_id != SPELL_UNKNOWN && other && damage > 0)
{
if(other->IsNPC() && !other->IsPet())
{
float npcspellscale = other->CastToNPC()->GetSpellScale();
damage = ((float)damage * npcspellscale) / (float)100;
}
}
// cut all PVP spell damage to 2/3 -solar // cut all PVP spell damage to 2/3 -solar
// Blasting ourselfs is considered PvP // Blasting ourselfs is considered PvP
//Don't do PvP mitigation if the caster is damaging himself //Don't do PvP mitigation if the caster is damaging himself
@ -3806,13 +3797,6 @@ void Mob::HealDamage(uint32 amount, Mob *caster, uint16 spell_id)
int32 curhp = GetHP(); int32 curhp = GetHP();
uint32 acthealed = 0; uint32 acthealed = 0;
if (caster && amount > 0) {
if (caster->IsNPC() && !caster->IsPet()) {
float npchealscale = caster->CastToNPC()->GetHealScale();
amount = (static_cast<float>(amount) * npchealscale) / 100.0f;
}
}
if (amount > (maxhp - curhp)) if (amount > (maxhp - curhp))
acthealed = (maxhp - curhp); acthealed = (maxhp - curhp);
else else

View File

@ -3050,6 +3050,13 @@ void NPC::CalcItemBonuses(StatBonuses *newbon)
if (cur->Worn.Effect>0 && (cur->Worn.Type == ET_WornEffect)) { // latent effects if (cur->Worn.Effect>0 && (cur->Worn.Type == ET_WornEffect)) { // latent effects
ApplySpellsBonuses(cur->Worn.Effect, cur->Worn.Level, newbon); ApplySpellsBonuses(cur->Worn.Effect, cur->Worn.Level, newbon);
} }
if (RuleB(Spells, NPC_UseFocusFromItems)){
if (cur->Focus.Effect>0 && (cur->Focus.Type == ET_Focus)){ // focus effects
ApplySpellsBonuses(cur->Focus.Effect, cur->Focus.Level, newbon, 0, true);
}
}
if (cur->Haste > newbon->haste) if (cur->Haste > newbon->haste)
newbon->haste = cur->Haste; newbon->haste = cur->Haste;
} }

View File

@ -485,14 +485,8 @@ public:
inline virtual int32 GetDelayDeath() const { return aabonuses.DelayDeath + spellbonuses.DelayDeath + itembonuses.DelayDeath + 11; } inline virtual int32 GetDelayDeath() const { return aabonuses.DelayDeath + spellbonuses.DelayDeath + itembonuses.DelayDeath + 11; }
float GetActSpellRange(uint16 spell_id, float range, bool IsBard = false);
int32 GetActSpellDamage(uint16 spell_id, int32 value, Mob* target = nullptr);
int32 GetActSpellHealing(uint16 spell_id, int32 value, Mob* target = nullptr);
int32 GetActSpellCost(uint16 spell_id, int32); int32 GetActSpellCost(uint16 spell_id, int32);
int32 GetActSpellDuration(uint16 spell_id, int32);
int32 GetActSpellCasttime(uint16 spell_id, int32); int32 GetActSpellCasttime(uint16 spell_id, int32);
int32 GetDotFocus(uint16 spell_id, int32 value);
int32 GetActDoTDamage(uint16 spell_id, int32 value, Mob* target = nullptr);
virtual bool CheckFizzle(uint16 spell_id); virtual bool CheckFizzle(uint16 spell_id);
virtual bool CheckSpellLevelRestriction(uint16 spell_id); virtual bool CheckSpellLevelRestriction(uint16 spell_id);
virtual int GetCurrentBuffSlots() const; virtual int GetCurrentBuffSlots() const;

View File

@ -30,7 +30,7 @@
#include "string_ids.h" #include "string_ids.h"
#include "npc_ai.h" #include "npc_ai.h"
float Client::GetActSpellRange(uint16 spell_id, float range, bool IsBard) float Mob::GetActSpellRange(uint16 spell_id, float range, bool IsBard)
{ {
float extrange = 100; float extrange = 100;
@ -39,57 +39,17 @@ float Client::GetActSpellRange(uint16 spell_id, float range, bool IsBard)
return (range * extrange) / 100; return (range * extrange) / 100;
} }
int32 Mob::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
int32 NPC::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
//Quest scale all NPC spell damage via $npc->SetSpellFocusDMG(value)
//DoT Damage - Mob::DoBuffTic [spell_effects.cpp] / Direct Damage Mob::SpellEffect [spell_effects.cpp]
int32 dmg = value;
if (target) {
value += dmg*target->GetVulnerability(this, spell_id, 0)/100;
if (spells[spell_id].buffduration == 0)
value -= target->GetFcDamageAmtIncoming(this, spell_id);
else
value -= target->GetFcDamageAmtIncoming(this, spell_id)/spells[spell_id].buffduration;
}
value += dmg*GetSpellFocusDMG()/100;
if (AI_HasSpellsEffects()){
int16 chance = 0;
int ratio = 0;
if (spells[spell_id].buffduration == 0) {
chance += spellbonuses.CriticalSpellChance + spellbonuses.FrenziedDevastation;
if (chance && zone->random.Roll(chance)) {
ratio += spellbonuses.SpellCritDmgIncrease + spellbonuses.SpellCritDmgIncNoStack;
value += (value*ratio)/100;
entity_list.MessageClose_StringID(this, true, 100, MT_SpellCrits, OTHER_CRIT_BLAST, GetCleanName(), itoa(-value));
}
}
else {
chance += spellbonuses.CriticalDoTChance;
if (chance && zone->random.Roll(chance)) {
ratio += spellbonuses.DotCritDmgIncrease;
value += (value*ratio)/100;
}
}
}
return value;
}
int32 Client::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
if (spells[spell_id].targettype == ST_Self) if (spells[spell_id].targettype == ST_Self)
return value; return value;
if (IsNPC())
value += value*CastToNPC()->GetSpellFocusDMG()/100;
bool Critical = false; bool Critical = false;
int32 value_BaseEffect = 0; int32 value_BaseEffect = 0;
int chance = 0;
value_BaseEffect = value + (value*GetFocusEffect(focusFcBaseEffects, spell_id)/100); value_BaseEffect = value + (value*GetFocusEffect(focusFcBaseEffects, spell_id)/100);
@ -98,20 +58,20 @@ int32 Client::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
value -= (GetLevel() - 40) * 20; value -= (GetLevel() - 40) * 20;
//This adds the extra damage from the AA Unholy Touch, 450 per level to the AA Improved Harm TOuch. //This adds the extra damage from the AA Unholy Touch, 450 per level to the AA Improved Harm TOuch.
if (spell_id == SPELL_IMP_HARM_TOUCH) //Improved Harm Touch if (spell_id == SPELL_IMP_HARM_TOUCH && IsClient()) //Improved Harm Touch
value -= GetAA(aaUnholyTouch) * 450; //Unholy Touch value -= GetAA(aaUnholyTouch) * 450; //Unholy Touch
int chance = RuleI(Spells, BaseCritChance); //Wizard base critical chance is 2% (Does not scale with level) chance = RuleI(Spells, BaseCritChance); //Wizard base critical chance is 2% (Does not scale with level)
chance += itembonuses.CriticalSpellChance + spellbonuses.CriticalSpellChance + aabonuses.CriticalSpellChance; chance += itembonuses.CriticalSpellChance + spellbonuses.CriticalSpellChance + aabonuses.CriticalSpellChance;
chance += itembonuses.FrenziedDevastation + spellbonuses.FrenziedDevastation + aabonuses.FrenziedDevastation; chance += itembonuses.FrenziedDevastation + spellbonuses.FrenziedDevastation + aabonuses.FrenziedDevastation;
if (chance > 0 || (GetClass() == WIZARD && GetLevel() >= RuleI(Spells, WizCritLevel))) { //Crtical Hit Calculation pathway
if (chance > 0 || (IsClient() && GetClass() == WIZARD && GetLevel() >= RuleI(Spells, WizCritLevel))) {
int32 ratio = RuleI(Spells, BaseCritRatio); //Critical modifier is applied from spell effects only. Keep at 100 for live like criticals. int32 ratio = RuleI(Spells, BaseCritRatio); //Critical modifier is applied from spell effects only. Keep at 100 for live like criticals.
//Improved Harm Touch is a guaranteed crit if you have at least one level of SCF. //Improved Harm Touch is a guaranteed crit if you have at least one level of SCF.
if (spell_id == SPELL_IMP_HARM_TOUCH && (GetAA(aaSpellCastingFury) > 0) && (GetAA(aaUnholyTouch) > 0)) if (spell_id == SPELL_IMP_HARM_TOUCH && IsClient() && (GetAA(aaSpellCastingFury) > 0) && (GetAA(aaUnholyTouch) > 0))
chance = 100; chance = 100;
if (zone->random.Roll(chance)) { if (zone->random.Roll(chance)) {
@ -120,11 +80,15 @@ int32 Client::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
ratio += itembonuses.SpellCritDmgIncNoStack + spellbonuses.SpellCritDmgIncNoStack + aabonuses.SpellCritDmgIncNoStack; ratio += itembonuses.SpellCritDmgIncNoStack + spellbonuses.SpellCritDmgIncNoStack + aabonuses.SpellCritDmgIncNoStack;
} }
else if (GetClass() == WIZARD && (GetLevel() >= RuleI(Spells, WizCritLevel)) && (zone->random.Roll(RuleI(Spells, WizCritChance)))) { else if ((IsClient() && GetClass() == WIZARD) || (IsMerc() && GetClass() == CASTERDPS)) {
ratio += zone->random.Int(20,70); //Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio. (20-70 is parse confirmed) if ((GetLevel() >= RuleI(Spells, WizCritLevel)) && zone->random.Roll(RuleI(Spells, WizCritChance))){
//Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio. (20-70 is parse confirmed)
ratio += zone->random.Int(20,70);
Critical = true; Critical = true;
} }
}
if (IsClient() && GetClass() == WIZARD)
ratio += RuleI(Spells, WizCritRatio); //Default is zero ratio += RuleI(Spells, WizCritRatio); //Default is zero
if (Critical){ if (Critical){
@ -147,14 +111,19 @@ int32 Client::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5)
value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value)*ratio/100; value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value)*ratio/100;
else if (IsNPC() && CastToNPC()->GetSpellScale())
value = int(static_cast<float>(value) * CastToNPC()->GetSpellScale() / 100.0f);
entity_list.MessageClose_StringID(this, true, 100, MT_SpellCrits, entity_list.MessageClose_StringID(this, true, 100, MT_SpellCrits,
OTHER_CRIT_BLAST, GetName(), itoa(-value)); OTHER_CRIT_BLAST, GetName(), itoa(-value));
if (IsClient())
Message_StringID(MT_SpellCrits, YOU_CRIT_BLAST, itoa(-value)); Message_StringID(MT_SpellCrits, YOU_CRIT_BLAST, itoa(-value));
return value; return value;
} }
} }
//Non Crtical Hit Calculation pathway
value = value_BaseEffect; value = value_BaseEffect;
value += value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100; value += value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100;
@ -173,14 +142,20 @@ int32 Client::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5)
value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value); value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value);
if (IsNPC() && CastToNPC()->GetSpellScale())
value = int(static_cast<float>(value) * CastToNPC()->GetSpellScale() / 100.0f);
return value; return value;
} }
int32 Client::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) { int32 Mob::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) {
if (target == nullptr) if (target == nullptr)
return value; return value;
if (IsNPC())
value += value*CastToNPC()->GetSpellFocusDMG()/100;
int32 value_BaseEffect = 0; int32 value_BaseEffect = 0;
int32 extra_dmg = 0; int32 extra_dmg = 0;
int16 chance = 0; int16 chance = 0;
@ -209,9 +184,8 @@ int32 Client::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) {
} }
value -= extra_dmg; value -= extra_dmg;
return value;
} }
else {
value = value_BaseEffect; value = value_BaseEffect;
value += value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100; value += value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100;
@ -228,6 +202,10 @@ int32 Client::GetActDoTDamage(uint16 spell_id, int32 value, Mob* target) {
} }
value -= extra_dmg; value -= extra_dmg;
}
if (IsNPC() && CastToNPC()->GetSpellScale())
value = int(static_cast<float>(value) * CastToNPC()->GetSpellScale() / 100.0f);
return value; return value;
} }
@ -254,39 +232,14 @@ int32 Mob::GetExtraSpellAmt(uint16 spell_id, int32 extra_spell_amt, int32 base_s
return extra_spell_amt; return extra_spell_amt;
} }
int32 Mob::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
int32 NPC::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
//Scale all NPC spell healing via SetSpellFocusHeal(value)
value += value*GetSpellFocusHeal()/100;
if (target) {
value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id);
value += value*target->GetHealRate(spell_id, this)/100;
}
//Allow for critical heal chance if NPC is loading spell effect bonuses.
if (AI_HasSpellsEffects()){
if(spells[spell_id].buffduration < 1) {
if(spellbonuses.CriticalHealChance && (zone->random.Roll(spellbonuses.CriticalHealChance))) {
value = value*2;
entity_list.MessageClose_StringID(this, true, 100, MT_SpellCrits, OTHER_CRIT_HEAL, GetCleanName(), itoa(value));
}
}
else if(spellbonuses.CriticalHealOverTime && (zone->random.Roll(spellbonuses.CriticalHealOverTime))) {
value = value*2;
}
}
return value;
}
int32 Client::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
if (target == nullptr) if (target == nullptr)
target = this; target = this;
if (IsNPC())
value += value*CastToNPC()->GetSpellFocusHeal()/100;
int32 value_BaseEffect = 0; int32 value_BaseEffect = 0;
int16 chance = 0; int16 chance = 0;
int8 modifier = 1; int8 modifier = 1;
@ -323,9 +276,14 @@ int32 Client::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
value += value*target->GetHealRate(spell_id, this)/100; value += value*target->GetHealRate(spell_id, this)/100;
if (IsNPC() && CastToNPC()->GetHealScale())
value = int(static_cast<float>(value) * CastToNPC()->GetHealScale() / 100.0f);
if (Critical) { if (Critical) {
entity_list.MessageClose_StringID(this, true, 100, MT_SpellCrits, entity_list.MessageClose_StringID(this, true, 100, MT_SpellCrits,
OTHER_CRIT_HEAL, GetName(), itoa(value)); OTHER_CRIT_HEAL, GetName(), itoa(value));
if (IsClient())
Message_StringID(MT_SpellCrits, YOU_CRIT_HEAL, itoa(value)); Message_StringID(MT_SpellCrits, YOU_CRIT_HEAL, itoa(value));
} }
@ -343,9 +301,12 @@ int32 Client::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
chance += GetDecayEffectValue(spell_id, SE_CriticalRegenDecay); chance += GetDecayEffectValue(spell_id, SE_CriticalRegenDecay);
if(chance && zone->random.Roll(chance)) if(chance && zone->random.Roll(chance))
return (value * 2); value *= 2;
} }
if (IsNPC() && CastToNPC()->GetHealScale())
value = int(static_cast<float>(value) * CastToNPC()->GetHealScale() / 100.0f);
return value; return value;
} }
@ -359,9 +320,9 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost)
cost *= 2; cost *= 2;
// Formula = Unknown exact, based off a random percent chance up to mana cost(after focuses) of the cast spell // Formula = Unknown exact, based off a random percent chance up to mana cost(after focuses) of the cast spell
if(this->itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5) if(itembonuses.Clairvoyance && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5)
{ {
int16 mana_back = this->itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100; int16 mana_back = itembonuses.Clairvoyance * zone->random.Int(1, 100) / 100;
// Doesnt generate mana, so best case is a free spell // Doesnt generate mana, so best case is a free spell
if(mana_back > cost) if(mana_back > cost)
mana_back = cost; mana_back = cost;
@ -451,7 +412,7 @@ int32 Client::GetActSpellCost(uint16 spell_id, int32 cost)
return cost; return cost;
} }
int32 Client::GetActSpellDuration(uint16 spell_id, int32 duration) int32 Mob::GetActSpellDuration(uint16 spell_id, int32 duration)
{ {
if (spells[spell_id].not_extendable) if (spells[spell_id].not_extendable)
return duration; return duration;
@ -463,7 +424,7 @@ int32 Client::GetActSpellDuration(uint16 spell_id, int32 duration)
// Only need this for clients, since the change was for bard songs, I assume we should keep non bard songs getting +1 // Only need this for clients, since the change was for bard songs, I assume we should keep non bard songs getting +1
// However if its bard or not and is mez, charm or fear, we need to add 1 so that client is in sync // However if its bard or not and is mez, charm or fear, we need to add 1 so that client is in sync
if (!(IsShortDurationBuff(spell_id) && IsBardSong(spell_id)) || if (IsClient() && !(IsShortDurationBuff(spell_id) && IsBardSong(spell_id)) ||
IsFearSpell(spell_id) || IsFearSpell(spell_id) ||
IsCharmSpell(spell_id) || IsCharmSpell(spell_id) ||
IsMezSpell(spell_id) || IsMezSpell(spell_id) ||
@ -664,7 +625,7 @@ bool Client::UseDiscipline(uint32 spell_id, uint32 target) {
if(spell.recast_time > 0) if(spell.recast_time > 0)
{ {
uint32 reduced_recast = spell.recast_time / 1000; uint32 reduced_recast = spell.recast_time / 1000;
reduced_recast -= CastToClient()->GetFocusEffect(focusReduceRecastTime, spell_id); reduced_recast -= GetFocusEffect(focusReduceRecastTime, spell_id);
if(reduced_recast <= 0){ if(reduced_recast <= 0){
reduced_recast = 0; reduced_recast = 0;
if (GetPTimers().Enabled((uint32)DiscTimer)) if (GetPTimers().Enabled((uint32)DiscTimer))

View File

@ -2656,153 +2656,6 @@ int16 Merc::GetFocusEffect(focusType type, uint16 spell_id) {
return realTotal + realTotal2 + realTotal3; return realTotal + realTotal2 + realTotal3;
} }
int32 Merc::GetActSpellDamage(uint16 spell_id, int32 value, Mob* target) {
if (spells[spell_id].targettype == ST_Self)
return value;
bool Critical = false;
int32 value_BaseEffect = 0;
value_BaseEffect = value + (value*GetFocusEffect(focusFcBaseEffects, spell_id)/100);
int chance = RuleI(Spells, BaseCritChance);
chance += itembonuses.CriticalSpellChance + spellbonuses.CriticalSpellChance + aabonuses.CriticalSpellChance;
if (chance > 0){
int32 ratio = RuleI(Spells, BaseCritRatio); //Critical modifier is applied from spell effects only. Keep at 100 for live like criticals.
if (zone->random.Roll(chance)) {
Critical = true;
ratio += itembonuses.SpellCritDmgIncrease + spellbonuses.SpellCritDmgIncrease + aabonuses.SpellCritDmgIncrease;
ratio += itembonuses.SpellCritDmgIncNoStack + spellbonuses.SpellCritDmgIncNoStack + aabonuses.SpellCritDmgIncNoStack;
}
else if (GetClass() == CASTERDPS && (GetLevel() >= RuleI(Spells, WizCritLevel)) && (zone->random.Roll(RuleI(Spells, WizCritChance)))) {
ratio = zone->random.Int(1,100); //Wizard innate critical chance is calculated seperately from spell effect and is not a set ratio.
Critical = true;
}
ratio += RuleI(Spells, WizCritRatio); //Default is zero
if (Critical){
value = value_BaseEffect*ratio/100;
value += value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100;
value += int(value_BaseEffect*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100)*ratio/100;
if (target) {
value += int(value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100)*ratio/100;
value -= target->GetFcDamageAmtIncoming(this, spell_id);
}
value -= GetFocusEffect(focusFcDamageAmtCrit, spell_id)*ratio/100;
value -= GetFocusEffect(focusFcDamageAmt, spell_id);
if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5)
value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value)*ratio/100;
value = (value * GetSpellScale() / 100);
entity_list.MessageClose_StringID(this, false, 100, MT_SpellCrits,
OTHER_CRIT_BLAST, GetName(), itoa(-value));
return value;
}
}
value = value_BaseEffect;
value += value_BaseEffect*GetFocusEffect(focusImprovedDamage, spell_id)/100;
value += value_BaseEffect*GetFocusEffect(focusFcDamagePctCrit, spell_id)/100;
if (target) {
value += value_BaseEffect*target->GetVulnerability(this, spell_id, 0)/100;
value -= target->GetFcDamageAmtIncoming(this, spell_id);
}
value -= GetFocusEffect(focusFcDamageAmtCrit, spell_id);
value -= GetFocusEffect(focusFcDamageAmt, spell_id);
if(itembonuses.SpellDmg && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5)
value -= GetExtraSpellAmt(spell_id, itembonuses.SpellDmg, value);
value = (value * GetSpellScale() / 100);
return value;
}
int32 Merc::GetActSpellHealing(uint16 spell_id, int32 value, Mob* target) {
if (target == nullptr)
target = this;
int32 value_BaseEffect = 0;
int16 chance = 0;
int8 modifier = 1;
bool Critical = false;
value_BaseEffect = value + (value*GetFocusEffect(focusFcBaseEffects, spell_id)/100);
value = value_BaseEffect;
value += int(value_BaseEffect*GetFocusEffect(focusImprovedHeal, spell_id)/100);
// Instant Heals
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);
if(chance && zone->random.Roll(chance)) {
Critical = true;
modifier = 2; //At present time no critical heal amount modifier SPA exists.
}
value *= modifier;
value += GetFocusEffect(focusFcHealAmtCrit, spell_id) * modifier;
value += GetFocusEffect(focusFcHealAmt, spell_id);
value += target->GetFocusIncoming(focusFcHealAmtIncoming, SE_FcHealAmtIncoming, this, spell_id);
if(itembonuses.HealAmt && spells[spell_id].classes[(GetClass()%16) - 1] >= GetLevel() - 5)
value += GetExtraSpellAmt(spell_id, itembonuses.HealAmt, value) * modifier;
value += value*target->GetHealRate(spell_id, this)/100;
if (Critical)
entity_list.MessageClose(this, false, 100, MT_SpellCrits, "%s performs an exceptional heal! (%d)", GetName(), value);
return value;
}
//Heal over time spells. [Heal Rate and Additional Healing effects do not increase this 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);
if(chance && zone->random.Roll(chance))
return (value * 2);
}
return value;
}
int32 Merc::GetActSpellCost(uint16 spell_id, int32 cost) int32 Merc::GetActSpellCost(uint16 spell_id, int32 cost)
{ {
// Formula = Unknown exact, based off a random percent chance up to mana cost(after focuses) of the cast spell // Formula = Unknown exact, based off a random percent chance up to mana cost(after focuses) of the cast spell

View File

@ -83,8 +83,6 @@ public:
Corpse* GetGroupMemberCorpse(); Corpse* GetGroupMemberCorpse();
// Merc Spell Casting Methods // Merc Spell Casting Methods
virtual int32 GetActSpellDamage(uint16 spell_id, int32 value, Mob* target = nullptr);
virtual int32 GetActSpellHealing(uint16 spell_id, int32 value, Mob* target = nullptr);
virtual int32 GetActSpellCasttime(uint16 spell_id, int32 casttime); virtual int32 GetActSpellCasttime(uint16 spell_id, int32 casttime);
virtual int32 GetActSpellCost(uint16 spell_id, int32 cost); virtual int32 GetActSpellCost(uint16 spell_id, int32 cost);
int8 GetChanceToCastBySpellType(int16 spellType); int8 GetChanceToCastBySpellType(int16 spellType);

View File

@ -2926,6 +2926,10 @@ uint32 Mob::GetLevelHP(uint8 tlevel)
} }
int32 Mob::GetActSpellCasttime(uint16 spell_id, int32 casttime) { int32 Mob::GetActSpellCasttime(uint16 spell_id, int32 casttime) {
int32 cast_reducer = 0;
cast_reducer += GetFocusEffect(focusSpellHaste, spell_id);
if (level >= 60 && casttime > 1000) if (level >= 60 && casttime > 1000)
{ {
casttime = casttime / 2; casttime = casttime / 2;
@ -2938,6 +2942,8 @@ int32 Mob::GetActSpellCasttime(uint16 spell_id, int32 casttime) {
else else
casttime -= cast_deduction; casttime -= cast_deduction;
} }
casttime = (casttime*(100 - cast_reducer)/100);
return(casttime); return(casttime);
} }
@ -2973,8 +2979,7 @@ void Mob::ExecWeaponProc(const ItemInst *inst, uint16 spell_id, Mob *on) {
bool twinproc = false; bool twinproc = false;
int32 twinproc_chance = 0; int32 twinproc_chance = 0;
if(IsClient()) twinproc_chance = GetFocusEffect(focusTwincast, spell_id);
twinproc_chance = CastToClient()->GetFocusEffect(focusTwincast, spell_id);
if(twinproc_chance && zone->random.Roll(twinproc_chance)) if(twinproc_chance && zone->random.Roll(twinproc_chance))
twinproc = true; twinproc = true;

View File

@ -198,11 +198,12 @@ public:
bool item_bonus = false, uint32 ticsremaining = 0, int buffslot = -1, bool item_bonus = false, uint32 ticsremaining = 0, int buffslot = -1,
bool IsAISpellEffect = false, uint16 effect_id = 0, int32 se_base = 0, int32 se_limit = 0, int32 se_max = 0); bool IsAISpellEffect = false, uint16 effect_id = 0, int32 se_base = 0, int32 se_limit = 0, int32 se_max = 0);
void NegateSpellsBonuses(uint16 spell_id); void NegateSpellsBonuses(uint16 spell_id);
virtual float GetActSpellRange(uint16 spell_id, float range, bool IsBard = false) { return range;} virtual float GetActSpellRange(uint16 spell_id, float range, bool IsBard = false);
virtual int32 GetActSpellDamage(uint16 spell_id, int32 value, Mob* target = nullptr) { return value; } virtual int32 GetActSpellDamage(uint16 spell_id, int32 value, Mob* target = nullptr);
virtual int32 GetActSpellHealing(uint16 spell_id, int32 value, Mob* target = nullptr) { return value; } virtual int32 GetActDoTDamage(uint16 spell_id, int32 value, Mob* target);
virtual int32 GetActSpellHealing(uint16 spell_id, int32 value, Mob* target = nullptr);
virtual int32 GetActSpellCost(uint16 spell_id, int32 cost){ return cost;} virtual int32 GetActSpellCost(uint16 spell_id, int32 cost){ return cost;}
virtual int32 GetActSpellDuration(uint16 spell_id, int32 duration){ return duration;} virtual int32 GetActSpellDuration(uint16 spell_id, int32 duration);
virtual int32 GetActSpellCasttime(uint16 spell_id, int32 casttime); virtual int32 GetActSpellCasttime(uint16 spell_id, int32 casttime);
float ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use_resist_override = false, float ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use_resist_override = false,
int resist_override = 0, bool CharismaCheck = false, bool CharmTick = false, bool IsRoot = false); int resist_override = 0, bool CharismaCheck = false, bool CharmTick = false, bool IsRoot = false);
@ -1044,6 +1045,7 @@ protected:
int GetKickDamage(); int GetKickDamage();
int GetBashDamage(); int GetBashDamage();
virtual void ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg); virtual void ApplySpecialAttackMod(SkillUseTypes skill, int32 &dmg, int32 &mindmg);
virtual int16 GetFocusEffect(focusType type, uint16 spell_id) { return 0; }
void CalculateNewFearpoint(); void CalculateNewFearpoint();
float FindGroundZ(float new_x, float new_y, float z_offset=0.0); float FindGroundZ(float new_x, float new_y, float z_offset=0.0);
Map::Vertex UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &WaypointChange, bool &NodeReached); Map::Vertex UpdatePath(float ToX, float ToY, float ToZ, float Speed, bool &WaypointChange, bool &NodeReached);

View File

@ -135,9 +135,6 @@ public:
void CalcNPCRegen(); void CalcNPCRegen();
void CalcNPCDamage(); void CalcNPCDamage();
int32 GetActSpellDamage(uint16 spell_id, int32 value, Mob* target = nullptr);
int32 GetActSpellHealing(uint16 spell_id, int32 value, Mob* target = nullptr);
virtual void SetTarget(Mob* mob); virtual void SetTarget(Mob* mob);
virtual uint16 GetSkill(SkillUseTypes skill_num) const { if (skill_num <= HIGHEST_SKILL) { return skills[skill_num]; } return 0; } virtual uint16 GetSkill(SkillUseTypes skill_num) const { if (skill_num <= HIGHEST_SKILL) { return skills[skill_num]; } return 0; }
@ -406,6 +403,8 @@ public:
bool IsRaidTarget() const { return raid_target; }; bool IsRaidTarget() const { return raid_target; };
int16 GetFocusEffect(focusType type, uint16 spell_id);
protected: protected:
const NPCType* NPCTypedata; const NPCType* NPCTypedata;
@ -446,6 +445,7 @@ protected:
virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0); virtual bool AIDoSpellCast(uint8 i, Mob* tar, int32 mana_cost, uint32* oDontDoAgainBefore = 0);
AISpellsVar_Struct AISpellVar; AISpellsVar_Struct AISpellVar;
uint32 npc_spells_effects_id; uint32 npc_spells_effects_id;
std::vector<AISpellsEffects_Struct> AIspellsEffects; std::vector<AISpellsEffects_Struct> AIspellsEffects;
bool HasAISpellEffects; bool HasAISpellEffects;

View File

@ -230,7 +230,7 @@ void Mob::MakePoweredPet(uint16 spell_id, const char* pettype, int16 petpower,
int16 act_power = 0; // The actual pet power we'll use. int16 act_power = 0; // The actual pet power we'll use.
if (petpower == -1) { if (petpower == -1) {
if (this->IsClient()) { if (this->IsClient()) {
act_power = CastToClient()->GetFocusEffect(focusPetPower, spell_id); act_power = CastToClient()->GetFocusEffect(focusPetPower, spell_id);//Client only
act_power = CastToClient()->mod_pet_power(act_power, spell_id); act_power = CastToClient()->mod_pet_power(act_power, spell_id);
} }
} }

View File

@ -179,11 +179,8 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
int numhit = spells[spell_id].numhits; int numhit = spells[spell_id].numhits;
if (caster && caster->IsClient()){ numhit += numhit*caster->GetFocusEffect(focusFcLimitUse, spell_id)/100;
numhit += numhit*caster->CastToClient()->GetFocusEffect(focusFcLimitUse, spell_id)/100; numhit += caster->GetFocusEffect(focusIncreaseNumHits, spell_id);
numhit += caster->CastToClient()->GetFocusEffect(focusIncreaseNumHits, spell_id);
}
buffs[buffslot].numhits = numhit; buffs[buffslot].numhits = numhit;
} }
@ -714,7 +711,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
mlog(COMBAT__HITS, "Stunned. We had %d percent resist chance.", stun_resist); mlog(COMBAT__HITS, "Stunned. We had %d percent resist chance.", stun_resist);
if (caster->IsClient()) if (caster->IsClient())
effect_value += effect_value*caster->CastToClient()->GetFocusEffect(focusFcStunTimeMod, spell_id)/100; effect_value += effect_value*caster->GetFocusEffect(focusFcStunTimeMod, spell_id)/100;
Stun(effect_value); Stun(effect_value);
} else { } else {
@ -2265,8 +2262,7 @@ bool Mob::SpellEffect(Mob* caster, uint16 spell_id, float partial)
int16 focus = 0; int16 focus = 0;
int ReuseTime = spells[spell_id].recast_time + spells[spell_id].recovery_time; int ReuseTime = spells[spell_id].recast_time + spells[spell_id].recovery_time;
if(caster->IsClient()) focus = caster->GetFocusEffect(focusFcBaseEffects, spell_id);
focus = caster->CastToClient()->GetFocusEffect(focusFcBaseEffects, spell_id);
switch(spells[spell_id].skill) switch(spells[spell_id].skill)
{ {
@ -3469,30 +3465,18 @@ void Mob::DoBuffTic(uint16 spell_id, int slot, uint32 ticsremaining, uint8 caste
{ {
effect_value = CalcSpellEffectValue(spell_id, i, caster_level, caster, ticsremaining); effect_value = CalcSpellEffectValue(spell_id, i, caster_level, caster, ticsremaining);
//Handle client cast DOTs here. //Handle client cast DOTs here.
if (caster && caster->IsClient() && IsDetrimentalSpell(spell_id) && effect_value < 0) { if (caster && effect_value < 0 && IsDetrimentalSpell(spell_id)){
effect_value = caster->CastToClient()->GetActDoTDamage(spell_id, effect_value, this);
if (caster->IsClient()){
if (!caster->CastToClient()->GetFeigned()) if (!caster->CastToClient()->GetFeigned())
AddToHateList(caster, -effect_value); AddToHateList(caster, -effect_value);
} }
else if (!IsClient()) //Allow NPC's to generate hate if casted on other NPC's.
if(effect_value < 0)
{
if(caster)
{
if(!caster->IsClient()){
if (!IsClient()) //Allow NPC's to generate hate if casted on other NPC's.
AddToHateList(caster, -effect_value); AddToHateList(caster, -effect_value);
}
if(caster->IsNPC()) effect_value = caster->GetActDoTDamage(spell_id, effect_value, this);
effect_value = caster->CastToNPC()->GetActSpellDamage(spell_id, effect_value, this);
caster->ResourceTap(-effect_value, spell_id); caster->ResourceTap(-effect_value, spell_id);
}
effect_value = -effect_value; effect_value = -effect_value;
Damage(caster, effect_value, spell_id, spell.skill, false, i, true); Damage(caster, effect_value, spell_id, spell.skill, false, i, true);
} else if(effect_value > 0) { } else if(effect_value > 0) {
@ -5318,11 +5302,8 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) {
//Improved Healing, Damage & Mana Reduction are handled differently in that some are random percentages //Improved Healing, Damage & Mana Reduction are handled differently in that some are random percentages
//In these cases we need to find the most powerful effect, so that each piece of gear wont get its own chance //In these cases we need to find the most powerful effect, so that each piece of gear wont get its own chance
if((type == focusManaCost || type == focusImprovedHeal || type == focusImprovedDamage) if(RuleB(Spells, LiveLikeFocusEffects) && (type == focusManaCost || type == focusImprovedHeal || type == focusImprovedDamage))
&& RuleB(Spells, LiveLikeFocusEffects))
{
rand_effectiveness = true; rand_effectiveness = true;
}
//Check if item focus effect exists for the client. //Check if item focus effect exists for the client.
if (itembonuses.FocusEffects[type]){ if (itembonuses.FocusEffects[type]){
@ -5540,6 +5521,122 @@ int16 Client::GetFocusEffect(focusType type, uint16 spell_id) {
return realTotal + realTotal2 + realTotal3; return realTotal + realTotal2 + realTotal3;
} }
int16 NPC::GetFocusEffect(focusType type, uint16 spell_id) {
int16 realTotal = 0;
int16 realTotal2 = 0;
bool rand_effectiveness = false;
//Improved Healing, Damage & Mana Reduction are handled differently in that some are random percentages
//In these cases we need to find the most powerful effect, so that each piece of gear wont get its own chance
if(RuleB(Spells, LiveLikeFocusEffects) && (type == focusManaCost || type == focusImprovedHeal || type == focusImprovedDamage))
rand_effectiveness = true;
if (RuleB(Spells, NPC_UseFocusFromItems) && itembonuses.FocusEffects[type]){
const Item_Struct* TempItem = 0;
const Item_Struct* UsedItem = 0;
uint16 UsedFocusID = 0;
int16 Total = 0;
int16 focus_max = 0;
int16 focus_max_real = 0;
//item focus
for(int i = 0; i < EmuConstants::EQUIPMENT_SIZE; i++){
const Item_Struct *cur = database.GetItem(equipment[i]);
if(!cur)
continue;
TempItem = cur;
if (TempItem && TempItem->Focus.Effect > 0 && TempItem->Focus.Effect != SPELL_UNKNOWN) {
if(rand_effectiveness) {
focus_max = CalcFocusEffect(type, TempItem->Focus.Effect, spell_id, true);
if (focus_max > 0 && focus_max_real >= 0 && focus_max > focus_max_real) {
focus_max_real = focus_max;
UsedItem = TempItem;
UsedFocusID = TempItem->Focus.Effect;
} else if (focus_max < 0 && focus_max < focus_max_real) {
focus_max_real = focus_max;
UsedItem = TempItem;
UsedFocusID = TempItem->Focus.Effect;
}
}
else {
Total = CalcFocusEffect(type, TempItem->Focus.Effect, spell_id);
if (Total > 0 && realTotal >= 0 && Total > realTotal) {
realTotal = Total;
UsedItem = TempItem;
UsedFocusID = TempItem->Focus.Effect;
} else if (Total < 0 && Total < realTotal) {
realTotal = Total;
UsedItem = TempItem;
UsedFocusID = TempItem->Focus.Effect;
}
}
}
}
if(UsedItem && rand_effectiveness && focus_max_real != 0)
realTotal = CalcFocusEffect(type, UsedFocusID, spell_id);
}
if (RuleB(Spells, NPC_UseFocusFromSpells) && spellbonuses.FocusEffects[type]){
//Spell Focus
int16 Total2 = 0;
int16 focus_max2 = 0;
int16 focus_max_real2 = 0;
int buff_tracker = -1;
int buff_slot = 0;
uint16 focusspellid = 0;
uint16 focusspell_tracker = 0;
int buff_max = GetMaxTotalSlots();
for (buff_slot = 0; buff_slot < buff_max; buff_slot++) {
focusspellid = buffs[buff_slot].spellid;
if (focusspellid == 0 || focusspellid >= SPDAT_RECORDS)
continue;
if(rand_effectiveness) {
focus_max2 = CalcFocusEffect(type, focusspellid, spell_id, true);
if (focus_max2 > 0 && focus_max_real2 >= 0 && focus_max2 > focus_max_real2) {
focus_max_real2 = focus_max2;
buff_tracker = buff_slot;
focusspell_tracker = focusspellid;
} else if (focus_max2 < 0 && focus_max2 < focus_max_real2) {
focus_max_real2 = focus_max2;
buff_tracker = buff_slot;
focusspell_tracker = focusspellid;
}
}
else {
Total2 = CalcFocusEffect(type, focusspellid, spell_id);
if (Total2 > 0 && realTotal2 >= 0 && Total2 > realTotal2) {
realTotal2 = Total2;
buff_tracker = buff_slot;
focusspell_tracker = focusspellid;
} else if (Total2 < 0 && Total2 < realTotal2) {
realTotal2 = Total2;
buff_tracker = buff_slot;
focusspell_tracker = focusspellid;
}
}
}
if(focusspell_tracker && rand_effectiveness && focus_max_real2 != 0)
realTotal2 = CalcFocusEffect(type, focusspell_tracker, spell_id);
// For effects like gift of mana that only fire once, save the spellid into an array that consists of all available buff slots.
if(buff_tracker >= 0 && buffs[buff_tracker].numhits > 0) {
m_spellHitsLeft[buff_tracker] = focusspell_tracker;
}
}
return realTotal + realTotal2;
}
void Mob::CheckNumHitsRemaining(uint8 type, int32 buff_slot, uint16 spell_id) void Mob::CheckNumHitsRemaining(uint8 type, int32 buff_slot, uint16 spell_id)
{ {
/* /*
@ -5946,15 +6043,13 @@ int32 Mob::ApplySpellEffectiveness(Mob* caster, int16 spell_id, int32 value, boo
if (!caster) if (!caster)
return value; return value;
if (caster->IsClient()){ int16 focus = GetFocusEffect(focusFcBaseEffects, spell_id);
int16 focus = caster->CastToClient()->GetFocusEffect(focusFcBaseEffects, spell_id);
if (IsBard) if (IsBard)
value += focus; value += focus;
else else
value += value*focus/100; value += value*focus/100;
}
return value; return value;
} }

View File

@ -176,7 +176,7 @@ bool Mob::CastSpell(uint16 spell_id, uint16 target_id, uint16 slot,
BuffFadeByEffect(SE_Sanctuary); BuffFadeByEffect(SE_Sanctuary);
if(IsClient()){ if(IsClient()){
int chance = CastToClient()->GetFocusEffect(focusFcMute, spell_id); int chance = CastToClient()->GetFocusEffect(focusFcMute, spell_id);//Client only
if (zone->random.Roll(chance)) { if (zone->random.Roll(chance)) {
Message_StringID(13, SILENCED_STRING); Message_StringID(13, SILENCED_STRING);
@ -1043,7 +1043,7 @@ void Mob::CastedSpellFinished(uint16 spell_id, uint32 target_id, uint16 slot,
// Check for consumables and Reagent focus items // Check for consumables and Reagent focus items
// first check for component reduction // first check for component reduction
if(IsClient()) { if(IsClient()) {
int reg_focus = CastToClient()->GetFocusEffect(focusReagentCost,spell_id); int reg_focus = CastToClient()->GetFocusEffect(focusReagentCost,spell_id);//Client only
if(zone->random.Roll(reg_focus)) { if(zone->random.Roll(reg_focus)) {
mlog(SPELLS__CASTING, "Spell %d: Reagent focus item prevented reagent consumption (%d chance)", spell_id, reg_focus); mlog(SPELLS__CASTING, "Spell %d: Reagent focus item prevented reagent consumption (%d chance)", spell_id, reg_focus);
} else { } else {
@ -2237,7 +2237,7 @@ bool Mob::SpellFinished(uint16 spell_id, Mob *spell_target, uint16 slot, uint16
{ {
recast -= GetAA(aaTouchoftheWicked) * 420; recast -= GetAA(aaTouchoftheWicked) * 420;
} }
int reduction = CastToClient()->GetFocusEffect(focusReduceRecastTime, spell_id); int reduction = CastToClient()->GetFocusEffect(focusReduceRecastTime, spell_id);//Client only
if(reduction) if(reduction)
recast -= reduction; recast -= reduction;
@ -4189,14 +4189,8 @@ float Mob::ResistSpell(uint8 resist_type, uint16 spell_id, Mob *caster, bool use
//Get resist modifier and adjust it based on focus 2 resist about eq to 1% resist chance //Get resist modifier and adjust it based on focus 2 resist about eq to 1% resist chance
int resist_modifier = (use_resist_override) ? resist_override : spells[spell_id].ResistDiff; int resist_modifier = (use_resist_override) ? resist_override : spells[spell_id].ResistDiff;
if(caster->IsClient()) int focus_resist = caster->GetFocusEffect(focusResistRate, spell_id);
{
if(IsValidSpell(spell_id))
{
int focus_resist = caster->CastToClient()->GetFocusEffect(focusResistRate, spell_id);
resist_modifier -= 2 * focus_resist; resist_modifier -= 2 * focus_resist;
}
}
//Check for fear resist //Check for fear resist
bool IsFear = false; bool IsFear = false;
@ -4580,16 +4574,13 @@ float Mob::GetAOERange(uint16 spell_id) {
if(range == 0) if(range == 0)
range = 10; //something.... range = 10; //something....
if (IsClient()) {
if(IsBardSong(spell_id) && IsBeneficialSpell(spell_id)) { if(IsBardSong(spell_id) && IsBeneficialSpell(spell_id)) {
//Live AA - Extended Notes, SionachiesCrescendo //Live AA - Extended Notes, SionachiesCrescendo
float song_bonus = static_cast<float>(aabonuses.SongRange + spellbonuses.SongRange + itembonuses.SongRange); float song_bonus = static_cast<float>(aabonuses.SongRange + spellbonuses.SongRange + itembonuses.SongRange);
range += range*song_bonus /100.0f; range += range*song_bonus /100.0f;
} }
range = CastToClient()->GetActSpellRange(spell_id, range); range = GetActSpellRange(spell_id, range);
}
return(range); return(range);
} }