Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(Core/Player): correct SpellPriority logic #21052

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 10 additions & 74 deletions src/server/game/Entities/Player/Player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9762,9 +9762,7 @@ void Player::ApplySpellMod(uint32 spellId, SpellModOp op, T& basevalue, Spell* s
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!spellInfo)
{
return;
}

float totalmul = 1.0f;
int32 totalflat = 0;
Expand All @@ -9773,146 +9771,87 @@ 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
if (temporaryPet && mod->charges != 0)
{
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)
{
// xinef: do not allow to consume more than one 100% crit increasing spell
if (mod->op == SPELLMOD_CRITICAL_CHANCE && totalflat >= 100)
{
return;
}

int32 flatValue = mod->value;

// SPELL_MOD_THREAT - divide by 100 (in packets we send threat * 100)
if (mod->op == SPELLMOD_THREAT)
{
flatValue /= 100;
}

totalflat += flatValue;
}
else if (mod->type == SPELLMOD_PCT)
{
// skip percent mods for null basevalue (most important for spell mods with charges)
if (basevalue == T(0) || totalmul == 0.0f)
{
return;
}

// special case (skip > 10sec spell casts for instant cast setting)
if (mod->op == SPELLMOD_CASTING_TIME && basevalue >= T(10000) && mod->value <= -100)
{
return;
}
// 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))
{
return;
}
// 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))
{
return;
}

// xinef: those two mods should be multiplicative (Glyph of Renew)
if (mod->op == SPELLMOD_DAMAGE || mod->op == SPELLMOD_DOT)
{
totalmul *= CalculatePct(1.0f, 100.0f + mod->value);
}
else
{
totalmul += CalculatePct(1.0f, mod->value);
}
}

DropModCharge(mod, spell);
};

// Drop charges for triggering spells instead of triggered ones
if (m_spellModTakingSpell)
{
spell = m_spellModTakingSpell;
}

SpellModifier* chargedMod = nullptr;
for (auto mod : m_spellMods[op])
{
// Charges can be set only for mods with auras
if (!mod->ownerAura)
{
ASSERT(!mod->charges);
}

if (!IsAffectedBySpellmod(spellInfo, mod, spell))
{
continue;
}

if (mod->ownerAura->IsUsingCharges())
{
if (!chargedMod || (chargedMod->ownerAura->GetSpellInfo()->SpellPriority < mod->ownerAura->GetSpellInfo()->SpellPriority))
{
chargedMod = mod;
}

continue;
}

calculateSpellMod(mod);
}

if (chargedMod)
{
calculateSpellMod(chargedMod);
}

float diff = 0.0f;
if (op == SPELLMOD_CASTING_TIME || op == SPELLMOD_DURATION)
{
diff = ((float)basevalue + totalflat) * (totalmul - 1.0f) + (float)totalflat;
}
basevalue = (basevalue + totalflat) > 0 ? (basevalue + totalflat) * totalmul : 0;
else
{
diff = (float)basevalue * (totalmul - 1.0f) + (float)totalflat;
}

basevalue = T((float)basevalue + diff);
basevalue = (basevalue * totalmul) + totalflat;
}

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, uint32& 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
class SpellModPred
struct SpellModPredicate
{
public:
SpellModPred() {}
bool operator() (SpellModifier const* a, SpellModifier const* b) const
{
if (a->type != b->type)
return a->type == SPELLMOD_FLAT;
return a->value < b->value;
}
};
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;
return a->priority > b->priority;
}
};

Expand Down Expand Up @@ -9949,10 +9888,7 @@ void Player::AddSpellMod(SpellModifier* mod, bool apply)
if (apply)
{
m_spellMods[mod->op].push_back(mod);
if (IsClass(CLASS_MAGE, CLASS_CONTEXT_ABILITY))
m_spellMods[mod->op].sort(MageSpellModPred());
else
m_spellMods[mod->op].sort(SpellModPred());
m_spellMods[mod->op].sort(SpellModPredicate());
}
else
{
Expand Down
1 change: 1 addition & 0 deletions src/server/game/Entities/Player/Player.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ struct SpellModifier
flag96 mask;
uint32 spellId{0};
Aura* const ownerAura;
uint32 priority{0};
};

typedef std::unordered_map<uint32, PlayerTalent*> PlayerTalentMap;
Expand Down
1 change: 1 addition & 0 deletions src/server/game/Spells/Auras/SpellAuraEffects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,7 @@ void AuraEffect::CalculateSpellMod()
m_spellmod->spellId = GetId();
m_spellmod->mask = GetSpellInfo()->Effects[GetEffIndex()].SpellClassMask;
m_spellmod->charges = GetBase()->GetCharges();
m_spellmod->priority = GetSpellInfo()->SpellPriority;
}
m_spellmod->value = GetAmount();
break;
Expand Down
2 changes: 1 addition & 1 deletion src/server/game/Spells/Auras/SpellAuras.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1659,7 +1659,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
if (removeMode != AURA_REMOVE_BY_EXPIRE || aurApp->GetBase()->IsExpired())
break;
if (target->HasAura(70752)) // Item - Mage T10 2P Bonus
target->CastSpell(target, 70753, true);
target->CastSpell(target, 70753, true); // Pushing the Limit
break;
default:
break;
Expand Down
18 changes: 9 additions & 9 deletions src/server/game/Spells/SpellInfoCorrections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,20 +272,13 @@ void SpellMgr::LoadSpellInfoCorrections()
54741, // Firestarter
64823, // Item - Druid T8 Balance 4P Bonus
34477, // Misdirection
44401, // Missile Barrage
18820 // Insight
18820, // Insight
57761 // Fireball!
}, [](SpellInfo* spellInfo)
{
spellInfo->ProcCharges = 1;
});

// Fireball
ApplySpellFix({ 57761 }, [](SpellInfo* spellInfo)
{
spellInfo->ProcCharges = 1;
spellInfo->SpellPriority = 50;
});

// Tidal Wave
ApplySpellFix({ 53390 }, [](SpellInfo* spellInfo)
{
Expand Down Expand Up @@ -4868,6 +4861,13 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->Effects[EFFECT_0].RealPointsPerLevel = 0;
});

// Missile Barrage
ApplySpellFix({ 44401 }, [](SpellInfo* spellInfo)
{
spellInfo->ProcCharges = 1;
spellInfo->SpellPriority = 100;
});

for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
{
SpellInfo* spellInfo = mSpellInfoMap[i];
Expand Down
Loading