aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/updates/world/master/2019_07_28_02_world_2017_02_21_02_world.sql6
-rw-r--r--src/server/game/Entities/Player/Player.cpp39
-rw-r--r--src/server/game/Spells/SpellMgr.cpp11
-rw-r--r--src/server/game/Spells/SpellMgr.h13
4 files changed, 55 insertions, 14 deletions
diff --git a/sql/updates/world/master/2019_07_28_02_world_2017_02_21_02_world.sql b/sql/updates/world/master/2019_07_28_02_world_2017_02_21_02_world.sql
new file mode 100644
index 00000000000..fa0f11d7f80
--- /dev/null
+++ b/sql/updates/world/master/2019_07_28_02_world_2017_02_21_02_world.sql
@@ -0,0 +1,6 @@
+ALTER TABLE `spell_enchant_proc_data`
+ CHANGE `entry` `EnchantID` int(10) UNSIGNED NOT NULL,
+ CHANGE `customChance` `Chance` float DEFAULT '0' NOT NULL,
+ CHANGE `PPMChance` `ProcsPerMinute` float DEFAULT '0' NOT NULL,
+ CHANGE `procEx` `HitMask` int(10) UNSIGNED DEFAULT '0' NOT NULL,
+ ADD COLUMN `AttributesMask` int(10) UNSIGNED DEFAULT '0' NOT NULL AFTER `HitMask`;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 4c4f89c493f..b461cbb2704 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -7997,10 +7997,10 @@ void Player::CastItemCombatSpell(DamageInfo const& damageInfo, Item* item, ItemT
continue;
SpellEnchantProcEntry const* entry = sSpellMgr->GetSpellEnchantProcEvent(enchant_id);
- if (entry && entry->procEx)
+ if (entry && entry->HitMask)
{
// Check hit/crit/dodge/parry requirement
- if ((entry->procEx & damageInfo.GetHitMask()) == 0)
+ if ((entry->HitMask & damageInfo.GetHitMask()) == 0)
continue;
}
else
@@ -8011,6 +8011,10 @@ void Player::CastItemCombatSpell(DamageInfo const& damageInfo, Item* item, ItemT
continue;
}
+ // check if enchant procs only on white hits
+ if (entry && (entry->AttributesMask & ENCHANT_PROC_ATTR_WHITE_HIT) && damageInfo.GetSpellInfo())
+ continue;
+
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(pEnchant->EffectArg[s]);
if (!spellInfo)
{
@@ -8023,10 +8027,10 @@ void Player::CastItemCombatSpell(DamageInfo const& damageInfo, Item* item, ItemT
if (entry)
{
- if (entry->PPMChance)
- chance = GetPPMProcChance(proto->GetDelay(), entry->PPMChance, spellInfo);
- else if (entry->customChance)
- chance = (float)entry->customChance;
+ if (entry->ProcsPerMinute)
+ chance = GetPPMProcChance(proto->GetDelay(), entry->ProcsPerMinute, spellInfo);
+ else if (entry->Chance)
+ chance = (float)entry->Chance;
}
// Apply spell mods
@@ -8043,6 +8047,29 @@ void Player::CastItemCombatSpell(DamageInfo const& damageInfo, Item* item, ItemT
else
CastSpell(damageInfo.GetVictim(), spellInfo, true, item);
}
+
+ if (roll_chance_f(chance))
+ {
+ Unit* target = spellInfo->IsPositive() ? this : damageInfo.GetVictim();
+
+ // reduce effect values if enchant is limited
+ CustomSpellValues values;
+ if ((entry->AttributesMask & ENCHANT_PROC_ATTR_LIMIT_60) && target->GetLevelForTarget(this) > 60)
+ {
+ int32 const lvlDifference = target->GetLevelForTarget(this) - 60;
+ int32 const lvlPenaltyFactor = 4; // 4% lost effectiveness per level
+
+ int32 const effectPct = std::max(0, 100 - (lvlDifference * lvlPenaltyFactor));
+
+ for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
+ {
+ if (spellInfo->GetEffect(DIFFICULTY_NONE, i)->IsEffect())
+ values.AddSpellMod(static_cast<SpellValueMod>(SPELLVALUE_BASE_POINT0 + i), CalculatePct(spellInfo->GetEffect(DIFFICULTY_NONE, i)->CalcValue(this), effectPct));
+ }
+ }
+
+ CastCustomSpell(spellInfo->Id, values, target, TRIGGERED_FULL_MASK, item);
+ }
}
}
}
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 190eee167dc..a9dda0332fa 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -1791,8 +1791,8 @@ void SpellMgr::LoadSpellEnchantProcData()
mSpellEnchantProcEventMap.clear(); // need for reload case
- // 0 1 2 3
- QueryResult result = WorldDatabase.Query("SELECT entry, customChance, PPMChance, procEx FROM spell_enchant_proc_data");
+ // 0 1 2 3 4
+ QueryResult result = WorldDatabase.Query("SELECT EnchantID, Chance, ProcsPerMinute, HitMask, AttributesMask FROM spell_enchant_proc_data");
if (!result)
{
TC_LOG_INFO("server.loading", ">> Loaded 0 spell enchant proc event conditions. DB table `spell_enchant_proc_data` is empty.");
@@ -1815,9 +1815,10 @@ void SpellMgr::LoadSpellEnchantProcData()
SpellEnchantProcEntry spe;
- spe.customChance = fields[1].GetUInt32();
- spe.PPMChance = fields[2].GetFloat();
- spe.procEx = fields[3].GetUInt32();
+ spe.Chance = fields[1].GetFloat();
+ spe.ProcsPerMinute = fields[2].GetFloat();
+ spe.HitMask = fields[3].GetUInt32();
+ spe.AttributesMask = fields[4].GetUInt32();
mSpellEnchantProcEventMap[enchantId] = spe;
diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h
index 3b393033ec2..60a13702f94 100644
--- a/src/server/game/Spells/SpellMgr.h
+++ b/src/server/game/Spells/SpellMgr.h
@@ -282,11 +282,18 @@ struct SpellProcEntry
typedef std::unordered_map<uint32, SpellProcEntry> SpellProcMap;
+enum EnchantProcAttributes
+{
+ ENCHANT_PROC_ATTR_WHITE_HIT = 0x0000001, // enchant shall only proc off white hits (not abilities)
+ ENCHANT_PROC_ATTR_LIMIT_60 = 0x0000002 // enchant effects shall be reduced past lvl 60
+};
+
struct SpellEnchantProcEntry
{
- uint32 customChance;
- float PPMChance;
- uint32 procEx;
+ float Chance; // if nonzero - overwrite SpellItemEnchantment value
+ float ProcsPerMinute; // if nonzero - chance to proc is equal to value * aura caster's weapon speed / 60
+ uint32 HitMask; // if nonzero - bitmask for matching proc condition based on hit result, see enum ProcFlagsHit
+ uint32 AttributesMask; // bitmask, see EnchantProcAttributes
};
typedef std::unordered_map<uint32, SpellEnchantProcEntry> SpellEnchantProcEventMap;