aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorariel- <ariel-@users.noreply.github.com>2018-02-12 03:09:22 -0300
committerariel- <ariel-@users.noreply.github.com>2018-02-12 03:09:22 -0300
commite73bfe8df89e4fb6aecc7cb3a1e266e868510799 (patch)
tree34dba2a558f73b06202ed1a0b9aa90212c111958
parent3edf90d16758632e1ab0dfd0a3adf2e5e0116a94 (diff)
Core/Spells: implemented SpellPriority field from SpellEntry to cleanup charged mod proc behaviour
- Only one charged mod will be consumed per SpellMod apply, and it'll be compared against other mod priority - This is proper way of handling Backdraft/Backlash and Deathchill/Killing Machine Thanks to killerwife for info
-rw-r--r--src/server/game/DataStores/DBCStructure.h2
-rw-r--r--src/server/game/DataStores/DBCfmt.h2
-rw-r--r--src/server/game/Entities/Player/Player.cpp117
-rw-r--r--src/server/game/Entities/Player/Player.h1
-rw-r--r--src/server/game/Spells/SpellInfo.cpp1
-rw-r--r--src/server/game/Spells/SpellInfo.h1
6 files changed, 33 insertions, 91 deletions
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index b0bea8ca81c..8c84e4596cf 100644
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -1404,7 +1404,7 @@ struct SpellEntry
uint32 SpellVisual[2]; // 131-132 m_spellVisualID
uint32 SpellIconID; // 133 m_spellIconID
uint32 activeIconID; // 134 m_activeIconID
- //uint32 spellPriority; // 135 not used
+ uint32 SpellPriority; // 135 m_spellPriority
char* SpellName[16]; // 136-151 m_name_lang
//uint32 SpellNameFlag; // 152 not used
char* Rank[16]; // 153-168 m_nameSubtext_lang
diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h
index dd74cffb51e..6651270848b 100644
--- a/src/server/game/DataStores/DBCfmt.h
+++ b/src/server/game/DataStores/DBCfmt.h
@@ -113,7 +113,7 @@ char const SpellDifficultyfmt[] = "niiii";
const std::string CustomSpellDifficultyfmt = "ppppp";
const std::string CustomSpellDifficultyIndex = "id";
char const SpellDurationfmt[] = "niii";
-char const SpellEntryfmt[] = "niiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiiiiiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiixxfffxx";
+char const SpellEntryfmt[] = "niiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiiiiiiissssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiixxfffxx";
const std::string CustomSpellEntryfmt = "papppppppppppapapaaaaaaaaaaapaaapapppppppaaaaapaapaaaaaaaaaaaaaaaaaappppppppppppppppppppppppppppppppppppaaappppppppppppaaapppppppppaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaappppppppapppaaaaappaaaaaaa";
const std::string CustomSpellEntryIndex = "Id";
char const SpellFocusObjectfmt[] = "nxxxxxxxxxxxxxxxxx";
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 266259b8257..6874c6a1f77 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -20869,6 +20869,10 @@ bool Player::IsAffectedBySpellmod(SpellInfo const* spellInfo, SpellModifier* mod
if (mod->op == SPELLMOD_DURATION && spellInfo->GetDuration() == -1)
return false;
+ // mod crit to spells that can't crit
+ if (mod->op == SPELLMOD_CRITICAL_CHANCE && !spellInfo->HasAttribute(SPELL_ATTR0_CU_CAN_CRIT))
+ return false;
+
return spellInfo->IsAffectedBySpellMod(mod);
}
@@ -20882,103 +20886,48 @@ void Player::ApplySpellMod(uint32 spellId, SpellModOp op, T& basevalue, Spell* s
float totalmul = 1.0f;
int32 totalflat = 0;
- // Drop charges for triggering spells instead of triggered ones
- if (m_spellModTakingSpell)
- spell = m_spellModTakingSpell;
-
- switch (op)
+ auto calculateSpellMod = [&](SpellModifier* mod)
{
- // special case, if a mod makes spell instant, only consume that mod
- case SPELLMOD_CASTING_TIME:
- {
- SpellModifier* modInstantSpell = nullptr;
- for (SpellModifier* mod : m_spellMods[op])
- {
- if (!IsAffectedBySpellmod(spellInfo, mod, spell))
- continue;
-
- if (mod->type == SPELLMOD_PCT && basevalue < T(10000) && mod->value <= -100)
- {
- modInstantSpell = mod;
- break;
- }
- }
-
- if (modInstantSpell)
- {
- Player::ApplyModToSpell(modInstantSpell, spell);
- basevalue = T(0);
- return;
- }
- break;
- }
- // special case if two mods apply 100% critical chance, only consume one
- case SPELLMOD_CRITICAL_CHANCE:
- {
- SpellModifier* modCritical = nullptr;
- for (SpellModifier* mod : m_spellMods[op])
- {
- if (!IsAffectedBySpellmod(spellInfo, mod, spell))
- continue;
-
- if (mod->type == SPELLMOD_FLAT && mod->value >= 100)
- {
- modCritical = mod;
- break;
- }
- }
-
- if (modCritical)
- {
- Player::ApplyModToSpell(modCritical, spell);
- basevalue = T(100);
- return;
- }
- break;
- }
- default:
- break;
- }
-
- for (SpellModifier* mod : m_spellMods[op])
- {
- if (!IsAffectedBySpellmod(spellInfo, mod, spell))
- continue;
-
switch (mod->type)
{
case SPELLMOD_FLAT:
totalflat += mod->value;
break;
case SPELLMOD_PCT:
- {
- // skip percent mods with null basevalue (most important for spell mods with charges)
- if (basevalue == T(0))
- continue;
-
// special case (skip > 10sec spell casts for instant cast setting)
if (op == SPELLMOD_CASTING_TIME && mod->value <= -100 && basevalue >= T(10000))
- continue;
- else if (!Player::HasSpellModApplied(mod, spell))
- {
- // special case for Surge of Light, don't apply critical chance reduction if other mods not applied (ie procs while casting another spell)
- // (Surge of Light is the only PCT_MOD on critical chance)
- if (op == SPELLMOD_CRITICAL_CHANCE)
- continue;
- // special case for Backdraft, dont' apply GCD reduction if cast time reduction wasn't applied (ie when Backlash is consumed first)
- // (Backdraft is the only PCT_MOD on global cooldown)
- else if (op == SPELLMOD_GLOBAL_COOLDOWN)
- continue;
- }
+ return;
totalmul += CalculatePct(1.0f, mod->value);
break;
- }
}
Player::ApplyModToSpell(mod, spell);
+ };
+
+ // Drop charges for triggering spells instead of triggered ones
+ if (m_spellModTakingSpell)
+ spell = m_spellModTakingSpell;
+
+ SpellModifier* chargedMod = nullptr;
+ for (SpellModifier* mod : m_spellMods[op])
+ {
+ if (!IsAffectedBySpellmod(spellInfo, mod, spell))
+ continue;
+
+ if (mod->ownerAura->IsUsingCharges())
+ {
+ if (!chargedMod || (chargedMod->ownerAura->GetSpellInfo()->Priority < mod->ownerAura->GetSpellInfo()->Priority))
+ chargedMod = mod;
+ continue;
+ }
+
+ calculateSpellMod(mod);
}
+ if (chargedMod)
+ calculateSpellMod(chargedMod);
+
basevalue = T(float(basevalue + totalflat) * totalmul);
}
@@ -21023,14 +20972,6 @@ void Player::AddSpellMod(SpellModifier* mod, bool apply)
m_spellMods[mod->op].erase(mod);
}
-bool Player::HasSpellModApplied(SpellModifier* mod, Spell* spell)
-{
- if (!spell)
- return false;
-
- return spell->m_appliedMods.count(mod->ownerAura) != 0;
-}
-
void Player::ApplyModToSpell(SpellModifier* mod, Spell* spell)
{
if (!spell)
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index fd9c4230ca9..e828bdb5488 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1454,7 +1454,6 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
template <class T>
void ApplySpellMod(uint32 spellId, SpellModOp op, T& basevalue, Spell* spell = nullptr) const;
static void ApplyModToSpell(SpellModifier* mod, Spell* spell);
- static bool HasSpellModApplied(SpellModifier* mod, Spell* spell);
void SetSpellModTakingSpell(Spell* spell, bool apply);
void RemoveArenaSpellCooldowns(bool removeActivePetCooldowns = false);
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 873bfbefdcf..88958e97fd3 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -841,6 +841,7 @@ SpellInfo::SpellInfo(SpellEntry const* spellEntry)
SpellIconID = spellEntry->SpellIconID;
ActiveIconID = spellEntry->activeIconID;
+ Priority = spellEntry->SpellPriority;
for (uint8 i = 0; i < 16; ++i)
SpellName[i] = spellEntry->SpellName[i];
diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h
index e117319a7f1..5670a9052a2 100644
--- a/src/server/game/Spells/SpellInfo.h
+++ b/src/server/game/Spells/SpellInfo.h
@@ -386,6 +386,7 @@ class TC_GAME_API SpellInfo
uint32 SpellVisual[2];
uint32 SpellIconID;
uint32 ActiveIconID;
+ uint32 Priority;
char* SpellName[16];
char* Rank[16];
uint32 MaxTargetLevel;