mirror of
https://github.com/liyunfan1223/azerothcore-wotlk.git
synced 2026-08-09 08:17:56 +00:00
fix(Core/Player): correct SpellPriority logic (#21052)
Co-authored-by: killerwife <killerwife@gmail.com> Co-authored-by: Kitzunu <24550914+Kitzunu@users.noreply.github.com>
This commit is contained in:
@@ -9791,9 +9791,7 @@ void Player::ApplySpellMod(uint32 spellId, SpellModOp op, T& basevalue, Spell* s
|
|||||||
{
|
{
|
||||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
|
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
|
||||||
if (!spellInfo)
|
if (!spellInfo)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
float totalmul = 1.0f;
|
float totalmul = 1.0f;
|
||||||
int32 totalflat = 0;
|
int32 totalflat = 0;
|
||||||
@@ -9802,25 +9800,24 @@ void Player::ApplySpellMod(uint32 spellId, SpellModOp op, T& basevalue, Spell* s
|
|||||||
{
|
{
|
||||||
// xinef: temporary pets cannot use charged mods of owner, needed for mirror image QQ they should use their own auras
|
// xinef: temporary pets cannot use charged mods of owner, needed for mirror image QQ they should use their own auras
|
||||||
if (temporaryPet && mod->charges != 0)
|
if (temporaryPet && mod->charges != 0)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
// skip if already instant or cost is free
|
||||||
|
if (mod->op == SPELLMOD_CASTING_TIME || mod->op == SPELLMOD_COST)
|
||||||
|
if (((float)basevalue + (float)basevalue * (totalmul - 1.0f) + (float)totalflat) <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
if (mod->type == SPELLMOD_FLAT)
|
if (mod->type == SPELLMOD_FLAT)
|
||||||
{
|
{
|
||||||
// xinef: do not allow to consume more than one 100% crit increasing spell
|
// xinef: do not allow to consume more than one 100% crit increasing spell
|
||||||
if (mod->op == SPELLMOD_CRITICAL_CHANCE && totalflat >= 100)
|
if (mod->op == SPELLMOD_CRITICAL_CHANCE && totalflat >= 100)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
int32 flatValue = mod->value;
|
int32 flatValue = mod->value;
|
||||||
|
|
||||||
// SPELL_MOD_THREAT - divide by 100 (in packets we send threat * 100)
|
// SPELL_MOD_THREAT - divide by 100 (in packets we send threat * 100)
|
||||||
if (mod->op == SPELLMOD_THREAT)
|
if (mod->op == SPELLMOD_THREAT)
|
||||||
{
|
|
||||||
flatValue /= 100;
|
flatValue /= 100;
|
||||||
}
|
|
||||||
|
|
||||||
totalflat += flatValue;
|
totalflat += flatValue;
|
||||||
}
|
}
|
||||||
@@ -9828,35 +9825,23 @@ void Player::ApplySpellMod(uint32 spellId, SpellModOp op, T& basevalue, Spell* s
|
|||||||
{
|
{
|
||||||
// skip percent mods for null basevalue (most important for spell mods with charges)
|
// skip percent mods for null basevalue (most important for spell mods with charges)
|
||||||
if (basevalue == T(0) || totalmul == 0.0f)
|
if (basevalue == T(0) || totalmul == 0.0f)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// special case (skip > 10sec spell casts for instant cast setting)
|
// special case (skip > 10sec spell casts for instant cast setting)
|
||||||
if (mod->op == SPELLMOD_CASTING_TIME && basevalue >= T(10000) && mod->value <= -100)
|
if (mod->op == SPELLMOD_CASTING_TIME && basevalue >= T(10000) && mod->value <= -100)
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
// xinef: special exception for surge of light, dont affect crit chance if previous mods were not applied
|
// xinef: special exception for surge of light, dont affect crit chance if previous mods were not applied
|
||||||
else if (mod->op == SPELLMOD_CRITICAL_CHANCE && spell && !HasSpellMod(mod, spell))
|
else if (mod->op == SPELLMOD_CRITICAL_CHANCE && spell && !HasSpellMod(mod, spell))
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
// xinef: special case for backdraft gcd reduce with backlast time reduction, dont affect gcd if cast time was not applied
|
// xinef: special case for backdraft gcd reduce with backlast time reduction, dont affect gcd if cast time was not applied
|
||||||
else if (mod->op == SPELLMOD_GLOBAL_COOLDOWN && spell && !HasSpellMod(mod, spell))
|
else if (mod->op == SPELLMOD_GLOBAL_COOLDOWN && spell && !HasSpellMod(mod, spell))
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// xinef: those two mods should be multiplicative (Glyph of Renew)
|
// xinef: those two mods should be multiplicative (Glyph of Renew)
|
||||||
if (mod->op == SPELLMOD_DAMAGE || mod->op == SPELLMOD_DOT)
|
if (mod->op == SPELLMOD_DAMAGE || mod->op == SPELLMOD_DOT)
|
||||||
{
|
|
||||||
totalmul *= CalculatePct(1.0f, 100.0f + mod->value);
|
totalmul *= CalculatePct(1.0f, 100.0f + mod->value);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
totalmul += CalculatePct(1.0f, mod->value);
|
totalmul += CalculatePct(1.0f, mod->value);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DropModCharge(mod, spell);
|
DropModCharge(mod, spell);
|
||||||
@@ -9864,53 +9849,24 @@ void Player::ApplySpellMod(uint32 spellId, SpellModOp op, T& basevalue, Spell* s
|
|||||||
|
|
||||||
// Drop charges for triggering spells instead of triggered ones
|
// Drop charges for triggering spells instead of triggered ones
|
||||||
if (m_spellModTakingSpell)
|
if (m_spellModTakingSpell)
|
||||||
{
|
|
||||||
spell = m_spellModTakingSpell;
|
spell = m_spellModTakingSpell;
|
||||||
}
|
|
||||||
|
|
||||||
SpellModifier* chargedMod = nullptr;
|
|
||||||
for (auto mod : m_spellMods[op])
|
for (auto mod : m_spellMods[op])
|
||||||
{
|
{
|
||||||
// Charges can be set only for mods with auras
|
// Charges can be set only for mods with auras
|
||||||
if (!mod->ownerAura)
|
if (!mod->ownerAura)
|
||||||
{
|
|
||||||
ASSERT(!mod->charges);
|
ASSERT(!mod->charges);
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsAffectedBySpellmod(spellInfo, mod, spell))
|
if (!IsAffectedBySpellmod(spellInfo, mod, spell))
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
if (mod->ownerAura->IsUsingCharges())
|
|
||||||
{
|
|
||||||
if (!chargedMod || (chargedMod->ownerAura->GetSpellInfo()->SpellPriority < mod->ownerAura->GetSpellInfo()->SpellPriority))
|
|
||||||
{
|
|
||||||
chargedMod = mod;
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
calculateSpellMod(mod);
|
calculateSpellMod(mod);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chargedMod)
|
|
||||||
{
|
|
||||||
calculateSpellMod(chargedMod);
|
|
||||||
}
|
|
||||||
|
|
||||||
float diff = 0.0f;
|
|
||||||
if (op == SPELLMOD_CASTING_TIME || op == SPELLMOD_DURATION)
|
if (op == SPELLMOD_CASTING_TIME || op == SPELLMOD_DURATION)
|
||||||
{
|
basevalue = (basevalue + totalflat) > 0 ? (basevalue + totalflat) * totalmul : 0;
|
||||||
diff = ((float)basevalue + totalflat) * (totalmul - 1.0f) + (float)totalflat;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
basevalue = (basevalue * totalmul) + totalflat;
|
||||||
diff = (float)basevalue * (totalmul - 1.0f) + (float)totalflat;
|
|
||||||
}
|
|
||||||
|
|
||||||
basevalue = T((float)basevalue + diff);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template AC_GAME_API void Player::ApplySpellMod(uint32 spellId, SpellModOp op, int32& basevalue, Spell* spell, bool temporaryPet);
|
template AC_GAME_API void Player::ApplySpellMod(uint32 spellId, SpellModOp op, int32& basevalue, Spell* spell, bool temporaryPet);
|
||||||
@@ -9918,30 +9874,13 @@ template AC_GAME_API void Player::ApplySpellMod(uint32 spellId, SpellModOp op, u
|
|||||||
template AC_GAME_API void Player::ApplySpellMod(uint32 spellId, SpellModOp op, float& basevalue, Spell* spell, bool temporaryPet);
|
template AC_GAME_API void Player::ApplySpellMod(uint32 spellId, SpellModOp op, float& basevalue, Spell* spell, bool temporaryPet);
|
||||||
|
|
||||||
// Binary predicate for sorting SpellModifiers
|
// Binary predicate for sorting SpellModifiers
|
||||||
class SpellModPred
|
struct SpellModPredicate
|
||||||
{
|
{
|
||||||
public:
|
|
||||||
SpellModPred() {}
|
|
||||||
bool operator() (SpellModifier const* a, SpellModifier const* b) const
|
bool operator() (SpellModifier const* a, SpellModifier const* b) const
|
||||||
{
|
{
|
||||||
if (a->type != b->type)
|
if (a->type != b->type)
|
||||||
return a->type == SPELLMOD_FLAT;
|
return a->type == SPELLMOD_FLAT;
|
||||||
return a->value < b->value;
|
return a->priority > b->priority;
|
||||||
}
|
|
||||||
};
|
|
||||||
class MageSpellModPred
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
MageSpellModPred() {}
|
|
||||||
bool operator() (SpellModifier const* a, SpellModifier const* b) const
|
|
||||||
{
|
|
||||||
if (a->type != b->type)
|
|
||||||
return a->type == SPELLMOD_FLAT;
|
|
||||||
if (a->spellId == 44401)
|
|
||||||
return true;
|
|
||||||
if (b->spellId == 44401)
|
|
||||||
return false;
|
|
||||||
return a->value < b->value;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -9978,10 +9917,7 @@ void Player::AddSpellMod(SpellModifier* mod, bool apply)
|
|||||||
if (apply)
|
if (apply)
|
||||||
{
|
{
|
||||||
m_spellMods[mod->op].push_back(mod);
|
m_spellMods[mod->op].push_back(mod);
|
||||||
if (IsClass(CLASS_MAGE, CLASS_CONTEXT_ABILITY))
|
m_spellMods[mod->op].sort(SpellModPredicate());
|
||||||
m_spellMods[mod->op].sort(MageSpellModPred());
|
|
||||||
else
|
|
||||||
m_spellMods[mod->op].sort(SpellModPred());
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -187,6 +187,7 @@ struct SpellModifier
|
|||||||
flag96 mask;
|
flag96 mask;
|
||||||
uint32 spellId{0};
|
uint32 spellId{0};
|
||||||
Aura* const ownerAura;
|
Aura* const ownerAura;
|
||||||
|
uint32 priority{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::unordered_map<uint32, PlayerTalent*> PlayerTalentMap;
|
typedef std::unordered_map<uint32, PlayerTalent*> PlayerTalentMap;
|
||||||
|
|||||||
@@ -701,6 +701,7 @@ void AuraEffect::CalculateSpellMod()
|
|||||||
m_spellmod->spellId = GetId();
|
m_spellmod->spellId = GetId();
|
||||||
m_spellmod->mask = GetSpellInfo()->Effects[GetEffIndex()].SpellClassMask;
|
m_spellmod->mask = GetSpellInfo()->Effects[GetEffIndex()].SpellClassMask;
|
||||||
m_spellmod->charges = GetBase()->GetCharges();
|
m_spellmod->charges = GetBase()->GetCharges();
|
||||||
|
m_spellmod->priority = GetSpellInfo()->SpellPriority;
|
||||||
}
|
}
|
||||||
m_spellmod->value = GetAmount();
|
m_spellmod->value = GetAmount();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1659,7 +1659,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
|
|||||||
if (removeMode != AURA_REMOVE_BY_EXPIRE || aurApp->GetBase()->IsExpired())
|
if (removeMode != AURA_REMOVE_BY_EXPIRE || aurApp->GetBase()->IsExpired())
|
||||||
break;
|
break;
|
||||||
if (target->HasAura(70752)) // Item - Mage T10 2P Bonus
|
if (target->HasAura(70752)) // Item - Mage T10 2P Bonus
|
||||||
target->CastSpell(target, 70753, true);
|
target->CastSpell(target, 70753, true); // Pushing the Limit
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -272,20 +272,13 @@ void SpellMgr::LoadSpellInfoCorrections()
|
|||||||
54741, // Firestarter
|
54741, // Firestarter
|
||||||
64823, // Item - Druid T8 Balance 4P Bonus
|
64823, // Item - Druid T8 Balance 4P Bonus
|
||||||
34477, // Misdirection
|
34477, // Misdirection
|
||||||
44401, // Missile Barrage
|
18820, // Insight
|
||||||
18820 // Insight
|
57761 // Fireball!
|
||||||
}, [](SpellInfo* spellInfo)
|
}, [](SpellInfo* spellInfo)
|
||||||
{
|
{
|
||||||
spellInfo->ProcCharges = 1;
|
spellInfo->ProcCharges = 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
// Fireball
|
|
||||||
ApplySpellFix({ 57761 }, [](SpellInfo* spellInfo)
|
|
||||||
{
|
|
||||||
spellInfo->ProcCharges = 1;
|
|
||||||
spellInfo->SpellPriority = 50;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Tidal Wave
|
// Tidal Wave
|
||||||
ApplySpellFix({ 53390 }, [](SpellInfo* spellInfo)
|
ApplySpellFix({ 53390 }, [](SpellInfo* spellInfo)
|
||||||
{
|
{
|
||||||
@@ -4922,6 +4915,13 @@ void SpellMgr::LoadSpellInfoCorrections()
|
|||||||
spellInfo->MaxAffectedTargets = 1;
|
spellInfo->MaxAffectedTargets = 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Missile Barrage
|
||||||
|
ApplySpellFix({ 44401 }, [](SpellInfo* spellInfo)
|
||||||
|
{
|
||||||
|
spellInfo->ProcCharges = 1;
|
||||||
|
spellInfo->SpellPriority = 100;
|
||||||
|
});
|
||||||
|
|
||||||
for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
|
for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
|
||||||
{
|
{
|
||||||
SpellInfo* spellInfo = mSpellInfoMap[i];
|
SpellInfo* spellInfo = mSpellInfoMap[i];
|
||||||
|
|||||||
Reference in New Issue
Block a user