diff --git a/sql/updates/world/4.3.4/2017_12_01_00_world.sql b/sql/updates/world/4.3.4/2017_12_01_00_world.sql new file mode 100644 index 0000000000..15a6c27b61 --- /dev/null +++ b/sql/updates/world/4.3.4/2017_12_01_00_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `playercreateinfo_skills` SET `classMask`= 1 | 2 | 32 WHERE `raceMask`= 0 AND `skill`= 160; diff --git a/sql/updates/world/4.3.4/2017_12_01_01_world.sql b/sql/updates/world/4.3.4/2017_12_01_01_world.sql new file mode 100644 index 0000000000..0398f093f0 --- /dev/null +++ b/sql/updates/world/4.3.4/2017_12_01_01_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `gameobject` SET `PhaseId` = 0 WHERE `PhaseGroup` > 0; diff --git a/sql/updates/world/4.3.4/2017_12_01_02_world.sql b/sql/updates/world/4.3.4/2017_12_01_02_world.sql new file mode 100644 index 0000000000..9b2581302b --- /dev/null +++ b/sql/updates/world/4.3.4/2017_12_01_02_world.sql @@ -0,0 +1,3 @@ + +UPDATE `creature` SET `PhaseId` = 0 WHERE `PhaseGroup` > 0; + diff --git a/sql/updates/world/4.3.4/2017_12_01_03_world_from_335_was_2017_11_30_00_world.sql b/sql/updates/world/4.3.4/2017_12_01_03_world_from_335_was_2017_11_30_00_world.sql new file mode 100644 index 0000000000..bce851e958 --- /dev/null +++ b/sql/updates/world/4.3.4/2017_12_01_03_world_from_335_was_2017_11_30_00_world.sql @@ -0,0 +1,2 @@ +-- +DELETE FROM `creature` WHERE `id` IN(28369); diff --git a/sql/updates/world/4.3.4/2017_12_01_04_world_from_335_was_2017_11_30_01_world.sql b/sql/updates/world/4.3.4/2017_12_01_04_world_from_335_was_2017_11_30_01_world.sql new file mode 100644 index 0000000000..f7e7d5db9d --- /dev/null +++ b/sql/updates/world/4.3.4/2017_12_01_04_world_from_335_was_2017_11_30_01_world.sql @@ -0,0 +1,106 @@ +-- Tower of the Damned revamp +SET @CGUID := 85740; +SET @POOLENTRY := 1117; + +-- Move wrong spawns +UPDATE `creature` SET `position_x`=6455.98, `position_y`=-6347.05, `position_z`=55.178, `orientation`=1.3107, `spawndist`=0, `MovementType`=0 WHERE `guid`=82854; +UPDATE `creature` SET `position_x`=6440.71, `position_y`=-6404.61, `position_z`=48.678, `orientation`=1.2039, `spawndist`=0, `MovementType`=2 WHERE `guid`=82937; +UPDATE `creature` SET `position_x`=6437.28, `position_y`=-6360.66, `position_z`=41.276, `orientation`=1.2629, `spawndist`=0, `MovementType`=2 WHERE `guid`=82897; +UPDATE `creature` SET `position_x`=6448.90, `position_y`=-6382.36, `position_z`=41.282, `orientation`=2.7828 WHERE `guid`=82871; + +-- Delete wrong spawns +DELETE FROM `creature` WHERE `guid` IN (82879, 82899, 82870, 82841, 82823, 82864, 82915); +DELETE FROM `creature_addon` WHERE `guid` IN (82879, 82899, 82870, 82841, 82823, 82864, 82915); +-- DELETE FROM `spawn_group` WHERE `groupId`=2 AND `spawnType`=0 AND `spawnId`=82870; + +-- Add 3 Deatholme Necromancer and 3 Eyes of Dar'Khan +DELETE FROM `creature` where `guid` BETWEEN @CGUID AND @CGUID + 5; +INSERT INTO `creature` (`guid`, `id`, `map`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `curhealth`, `curmana`, `MovementType`) VALUES +(@CGUID , 16317, 530, 1, 6461.42, -6345.30, 41.233, 2.8408, 300, 377, 408, 0), +(@CGUID + 1, 16317, 530, 1, 6476.68, -6362.99, 27.201, 3.8813, 300, 377, 408, 0), +(@CGUID + 2, 16317, 530, 1, 6470.83, -6380.51, 27.202, 1.8361, 300, 377, 408, 0), +(@CGUID + 3, 16320, 530, 0, 6461.81, -6349.33, 55.178, 1.2652, 300, 404, 456, 0), +(@CGUID + 4, 16320, 530, 0, 6437.28, -6360.66, 41.276, 1.2629, 300, 404, 456, 2), +(@CGUID + 5, 16320, 530, 0, 6440.71, -6404.61, 48.678, 1.2039, 300, 404, 456, 2); + +-- Add pathing of two Wailers and two Eyes of Dar'Khan +SET @PATHID_1 := 829370; +SET @PATHID_2 := 828970; +SET @PATHID_3 := (@CGUID + 4) * 10; +SET @PATHID_4 := (@CGUID + 5) * 10; + +DELETE FROM `creature_addon` WHERE `guid` IN (82937, 82897, @CGUID + 4, @CGUID + 5); +INSERT INTO `creature_addon` (`guid`, `path_id`, `bytes2`) VALUES +(82937, @PATHID_1, 1), +(82897, @PATHID_2, 1), +(@CGUID + 4, @PATHID_3, 1), +(@CGUID + 5, @PATHID_4, 1); + +DELETE FROM `waypoint_data` WHERE `id` IN (@PATHID_1, @PATHID_2, @PATHID_3, @PATHID_4); +INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`) VALUES +(@PATHID_1, 1, 6445.87, -6388.29, 55.178), +(@PATHID_1, 2, 6462.24, -6385.64, 55.178), +(@PATHID_1, 3, 6477.23, -6373.64, 55.178), +(@PATHID_1, 4, 6472.75, -6355.57, 55.178), +(@PATHID_1, 5, 6460.20, -6343.13, 55.178), +(@PATHID_1, 6, 6465.87, -6326.58, 48.679), +(@PATHID_1, 7, 6460.20, -6343.13, 55.178), +(@PATHID_1, 8, 6443.27, -6346.17, 55.179), +(@PATHID_1, 9, 6430.45, -6358.61, 55.179), +(@PATHID_1, 10, 6433.99, -6376.20, 55.178), +(@PATHID_1, 11, 6445.87, -6388.29, 55.178), +(@PATHID_1, 12, 6440.46, -6404.84, 48.678), +(@PATHID_2, 1, 6443.78, -6340.43, 41.291), +(@PATHID_2, 2, 6459.56, -6345.86, 41.208), +(@PATHID_2, 3, 6453.16, -6365.24, 33.735), +(@PATHID_2, 4, 6446.68, -6384.37, 41.203), +(@PATHID_2, 5, 6430.96, -6379.17, 41.291), +(@PATHID_2, 6, 6437.28, -6360.66, 41.276), +(@PATHID_3, 1, 6443.78, -6340.43, 41.291), +(@PATHID_3, 2, 6459.56, -6345.86, 41.208), +(@PATHID_3, 3, 6453.16, -6365.24, 33.735), +(@PATHID_3, 4, 6446.68, -6384.37, 41.203), +(@PATHID_3, 5, 6430.96, -6379.17, 41.291), +(@PATHID_3, 6, 6437.28, -6360.66, 41.276), +(@PATHID_4, 1, 6445.87, -6388.29, 55.178), +(@PATHID_4, 2, 6462.24, -6385.64, 55.178), +(@PATHID_4, 3, 6477.23, -6373.64, 55.178), +(@PATHID_4, 4, 6472.75, -6355.57, 55.178), +(@PATHID_4, 5, 6460.20, -6343.13, 55.178), +(@PATHID_4, 6, 6465.87, -6326.58, 48.679), +(@PATHID_4, 7, 6460.20, -6343.13, 55.178), +(@PATHID_4, 8, 6443.27, -6346.17, 55.179), +(@PATHID_4, 9, 6430.45, -6358.61, 55.179), +(@PATHID_4, 10, 6433.99, -6376.20, 55.178), +(@PATHID_4, 11, 6445.87, -6388.29, 55.178), +(@PATHID_4, 12, 6440.46, -6404.84, 48.678); + +-- Eyes of Dar'Khan/Wailers shared spawns +SET @POOL_1 := @POOLENTRY; +SET @POOL_2 := @POOLENTRY + 1; + +DELETE FROM `pool_template` WHERE `entry` IN (@POOL_1, @POOL_2); +INSERT INTO `pool_template` VALUES +(@POOL_1, 1, "Eye of DarKhan/Wailer Spawn 1"), +(@POOL_2, 1, "Eye of DarKhan/Wailer Spawn 2"); + +DELETE FROM `pool_creature` WHERE `guid` IN (82897, 82937, @CGUID + 4, @CGUID + 5); +INSERT INTO `pool_creature` VALUES +(82897, @POOL_1, 0, "Wailer Spawn 1"), +(82937, @POOL_2, 0, "Wailer Spawn 2"), +(@CGUID + 4, @POOL_1, 0, "Eye of DarKhan Spawn 1"), +(@CGUID + 5, @POOL_2, 0, "Eye of DarKhan Spawn 2"); + +-- Rescript Dar'Khan Drathir and fix speech +-- by Teppic +SET @ENTRY := 16329; +DELETE FROM `smart_scripts` WHERE `entryorguid`=@ENTRY AND `source_type`=0; +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES +(@ENTRY,0,0,0,4,0,100,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,"Dar'Khan Drathir - On Aggro - Say Line 0"), +(@ENTRY,0,1,0,0,0,100,0,0,0,6000,12000,11,20791,0,0,0,0,0,2,0,0,0,0,0,0,0,"Dar'Khan Drathir - In Combat CMC - Cast 'Shadow Bolt'"), +(@ENTRY,0,2,0,0,0,100,0,7000,9000,15000,15000,11,21068,0,0,0,0,0,5,0,0,0,0,0,0,0,"Dar'Khan Drathir - In Combat CMC - Cast 'Corruption'"), +(@ENTRY,0,3,0,0,0,100,0,15000,20000,16000,20000,11,38660,0,0,0,0,0,5,0,0,0,0,0,0,0,"Dar'Khan Drathir - In Combat CMC - Cast 'Fear'"); + +DELETE FROM `creature_text` WHERE `CreatureID`=@ENTRY; +INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES +(@ENTRY, 0, 0, 'Mortal fools! The ghouls of Deatholme will feast on your remains!', 12, 0, 100, 0, 0, 0, 12224, 0, "Dar'Khan Drathir"); diff --git a/sql/updates/world/4.3.4/2017_12_01_05_world.sql b/sql/updates/world/4.3.4/2017_12_01_05_world.sql new file mode 100644 index 0000000000..ae7b531fd2 --- /dev/null +++ b/sql/updates/world/4.3.4/2017_12_01_05_world.sql @@ -0,0 +1,10 @@ +-- +DELETE FROM `quest_poi_points` WHERE `QuestID` IN (28780, 28785, 28786, 28787, 28788, 28789, 29080); +INSERT INTO `quest_poi_points` (`QuestID`, `Idx1`, `Idx2`, `X`, `Y`, `VerifiedBuild`) VALUES +(28780, 0, 0, -8828, -159, 15595), +(28785, 0, 0, -8828, -159, 15595), +(28786, 0, 0, -8828, -159, 15595), +(28787, 0, 0, -8828, -159, 15595), +(28788, 0, 0, -8828, -159, 15595), +(28789, 0, 0, -8828, -159, 15595), +(29080, 0, 0, -8828, -159, 15595); diff --git a/sql/updates/world/4.3.4/2017_12_01_06_world.sql b/sql/updates/world/4.3.4/2017_12_01_06_world.sql new file mode 100644 index 0000000000..29505545a3 --- /dev/null +++ b/sql/updates/world/4.3.4/2017_12_01_06_world.sql @@ -0,0 +1,4 @@ +-- +UPDATE `smart_scripts` SET `action_param1`=12039 WHERE `entryorguid`=4517 AND `source_type`=0 AND `id`=2; +UPDATE `smart_scripts` SET `action_type`=85, `action_param1`=79606 WHERE `entryorguid`=204019 AND `source_type`=1 AND `id`=1; +DELETE FROM `spell_target_position` WHERE `ID`=71241; diff --git a/sql/updates/world/4.3.4/2017_12_02_00_world.sql b/sql/updates/world/4.3.4/2017_12_02_00_world.sql new file mode 100644 index 0000000000..9038ac1c55 --- /dev/null +++ b/sql/updates/world/4.3.4/2017_12_02_00_world.sql @@ -0,0 +1,4 @@ +-- +DELETE FROM `spell_proc` WHERE `SpellID`= 84722; +INSERT INTO `spell_proc` (`SpellID`, `SpellFamilyName`, `SpellFamilyMask0`, `ProcFlags`, `SpellTypeMask`, `SpellPhaseMask`, `HitMask`, `AttributesMask`) VALUES +(84722 , 3, 0, 0x00010000, 0x00000004, 2, 0x00001000, 0); diff --git a/sql/updates/world/4.3.4/2017_12_02_01_world.sql b/sql/updates/world/4.3.4/2017_12_02_01_world.sql new file mode 100644 index 0000000000..9e7d1a211c --- /dev/null +++ b/sql/updates/world/4.3.4/2017_12_02_01_world.sql @@ -0,0 +1,35 @@ +-- Warlock +DELETE FROM `spell_bonus_data` WHERE `entry` IN (172, 686, 6229, 980, 603, 6789, 689, 1120, 5676, 6353, 17877, 348, 1949, 5857, 42223, 30108, 27243, 27285, 30283, 29722, 47897, 48181, 50796, 50590, 54786, 3110, 54049, 7814, 86121, 71521, 77799); +INSERT INTO `spell_bonus_data` (`entry`, `direct_bonus`, `dot_bonus`, `ap_bonus`, `ap_dot_bonus`, `comments`) VALUES +(172, 0.176, 0, 0, 0, 'Walock - Corruption'), +(686, 0.754, 0, 0, 0, 'Walock - Shadow Bolt'), +(6229, 0.807, 0, 0, 0, 'Walock - Shadow Ward'), +(980, 0, 0.133, 0, 0, 'Walock - Bane of Agony'), +(603, 0, 2.024, 0, 0, 'Walock - Bane of Doom'), +(6789, 0.188, 0, 0, 0, 'Walock - Death Coil'), +(689, 0, 0.129, 0, 0, 'Walock - Drain Life'), +(1120, 0, 0.378, 0, 0, 'Walock - Drain Soul'), +(5676, 0.378, 0, 0, 0, 'Walock - Searing Pain'), +(6353, 0.726, 0, 0, 0, 'Walock - Soul Fire'), +(17877, 1.056, 0, 0, 0, 'Walock - Shadowburn'), +(348, 0.22, 0.176, 0, 0, 'Walock - Immolate'), +(1949, 0, 0.095, 0, 0, 'Walock - Hellfire'), +(5857, 0.095, 0, 0, 0, 'Walock - Hellfire Triggered'), +(42223, 0.238, 0, 0, 0, 'Walock - Rain of Fire'), +(30108, 0, 0.2, 0, 0, 'Walock - Unstable Afflcition'), +(27243, 0, 0.2292, 0, 0, 'Walock - Seed of Corruption'), +(27285, 0.3, 0, 0, 0, 'Walock - Seed of Corruption Triggered'), +(30283, 0.214, 0, 0, 0, 'Walock - Shadowfury'), +(29722, 0.539, 0, 0, 0, 'Walock - Incinerate'), +(47897, 0.102, 0, 0, 0, 'Walock - Shadowflame'), +(48181, 0.5577, 0, 0, 0, 'Walock - Haunt'), +(50796, 0.628, 0, 0, 0, 'Walock - Chaos Bolt'), +(50590, 0.1, 0, 0, 0, 'Walock - Immolation Aura'), +(54786, 0.214, 0, 0, 0, 'Walock - Demon Leap'), +(3110, 0.657, 0, 0, 0, 'Walock - Imp - Firebolt'), +(54049, 1.228, 0, 0, 0, 'Walock - Shadow Bite'), +(7814, 0.612, 0, 0, 0, 'Walock - Lash of Pain'), +(86121, 0.2, 0, 0, 0, 'Walock - Soul Swap'), +(71521, 0.968, 0, 0, 0, 'Walock - Hand of Gul''Dan'), +(77799, 0.302, 0, 0, 0, 'Walock - Fel Flame'); + diff --git a/sql/updates/world/4.3.4/2017_12_02_02_world.sql b/sql/updates/world/4.3.4/2017_12_02_02_world.sql new file mode 100644 index 0000000000..0740cddf52 --- /dev/null +++ b/sql/updates/world/4.3.4/2017_12_02_02_world.sql @@ -0,0 +1,4 @@ +DELETE FROM `spell_proc` WHERE `SpellID` IN (84722, 84723); +INSERT INTO `spell_proc` (`SpellID`, `SpellFamilyName`, `SpellFamilyMask0`, `ProcFlags`, `SpellTypeMask`, `SpellPhaseMask`, `HitMask`, `AttributesMask`) VALUES +(84722, 3, 0, 0x00010000, 0x00000004, 2, 0x00001000, 0), +(84723, 3, 0, 0x00010000, 0x00000004, 2, 0x00001000, 0); diff --git a/sql/updates/world/4.3.4/2017_12_02_03_world.sql b/sql/updates/world/4.3.4/2017_12_02_03_world.sql new file mode 100644 index 0000000000..b73c4b1b1d --- /dev/null +++ b/sql/updates/world/4.3.4/2017_12_02_03_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `spell_proc` SET `HitMask`= 4096 WHERE `SpellID` IN (84722, 84723); diff --git a/src/common/Debugging/WheatyExceptionReport.cpp b/src/common/Debugging/WheatyExceptionReport.cpp index be011f005a..3223607d19 100644 --- a/src/common/Debugging/WheatyExceptionReport.cpp +++ b/src/common/Debugging/WheatyExceptionReport.cpp @@ -1025,7 +1025,7 @@ bool logChildren) ULONG64 length; SymGetTypeInfo(m_hProcess, modBase, innerTypeID, TI_GET_LENGTH, &length); char buffer2[50]; - FormatOutputValue(buffer2, basicType, length, (PVOID)address, sizeof(buffer)); + FormatOutputValue(buffer2, basicType, length, (PVOID)address, sizeof(buffer2)); symbolDetails.top().Value = buffer2; } bHandled = true; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index cca7f89496..f487d8da1f 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -2197,6 +2197,7 @@ void Player::RegenerateAll() Regenerate(POWER_ENERGY); Regenerate(POWER_MANA); + Regenerate(POWER_FOCUS); // Runes act as cooldowns, and they don't need to send any data if (getClass() == CLASS_DEATH_KNIGHT) @@ -2206,6 +2207,7 @@ void Player::RegenerateAll() uint8 runeToRegen = i; uint32 cd = GetRuneCooldown(i); uint32 secondRuneCd = GetRuneCooldown(i + 1); + float cdmod = GetFloatValue(PLAYER_RUNE_REGEN_1) * 10.0f; // Regenerate second rune of the same type only after first rune is off the cooldown if (secondRuneCd && (cd > secondRuneCd || !cd)) { @@ -2214,16 +2216,10 @@ void Player::RegenerateAll() } if (cd) - SetRuneCooldown(runeToRegen, (cd > m_regenTimer) ? cd - m_regenTimer : 0); + SetRuneCooldown(runeToRegen, (cd > (m_regenTimer * cdmod)) ? cd - (m_regenTimer * cdmod) : 0); } } - if (m_focusRegenTimerCount >= 1000 && getClass() == CLASS_HUNTER) - { - Regenerate(POWER_FOCUS); - m_focusRegenTimerCount -= 1000; - } - if (m_regenTimerCount >= 2000) { // Not in combat or they have regeneration @@ -2284,8 +2280,8 @@ void Player::Regenerate(Powers power) addvalue += GetFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER) * ManaIncreaseRate * ((0.001f * m_regenTimer) + CalculatePct(0.001f, spellHaste)); else addvalue += GetFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER) * ManaIncreaseRate * ((0.001f * m_regenTimer) + CalculatePct(0.001f, spellHaste)); + break; } - break; case POWER_RAGE: // Regenerate rage { if (!IsInCombat() && !HasAuraType(SPELL_AURA_INTERRUPT_REGEN)) @@ -2293,14 +2289,21 @@ void Player::Regenerate(Powers power) float RageDecreaseRate = sWorld->getRate(RATE_POWER_RAGE_LOSS); addvalue += -25 * RageDecreaseRate / meleeHaste; // 2.5 rage by tick (= 2 seconds => 1.25 rage/sec) } + break; } - break; case POWER_FOCUS: - addvalue += (6.0f + CalculatePct(6.0f, rangedHaste)) * sWorld->getRate(RATE_POWER_FOCUS); + { + float haste = (1.0f / GetFloatValue(PLAYER_FIELD_MOD_HASTE_REGEN) - 1.0f) * 100.0f; + addvalue += (5.0f + CalculatePct(5.0f, haste)) * (m_regenTimer / 1000.0f); + addvalue *= GetTotalAuraMultiplier(SPELL_AURA_HASTE_SPELLS); break; + } case POWER_ENERGY: // Regenerate energy (rogue) - addvalue += ((0.01f * m_regenTimer) + CalculatePct(0.01f, meleeHaste)) * sWorld->getRate(RATE_POWER_ENERGY); + { + float haste = (1.0f / GetFloatValue(PLAYER_FIELD_MOD_HASTE_REGEN) - 1.0f) * 100.0f; + addvalue += (10.0f + CalculatePct(10.0f, haste)) * (m_regenTimer / 1000.0f); break; + } case POWER_RUNIC_POWER: { if (!IsInCombat() && !HasAuraType(SPELL_AURA_INTERRUPT_REGEN)) @@ -2308,14 +2311,14 @@ void Player::Regenerate(Powers power) float RunicPowerDecreaseRate = sWorld->getRate(RATE_POWER_RUNICPOWER_LOSS); addvalue += -30 * RunicPowerDecreaseRate; // 3 RunicPower by tick } + break; } - break; case POWER_HOLY_POWER: // Regenerate holy power { if (!IsInCombat()) addvalue += -1.0f; // remove 1 each 10 sec + break; } - break; case POWER_RUNE: break; case POWER_HEALTH: @@ -2325,7 +2328,7 @@ void Player::Regenerate(Powers power) } // Mana regen calculated in Player::UpdateManaRegen() - if (power != POWER_MANA) + if (power != POWER_MANA && power != POWER_FOCUS && power != POWER_ENERGY) { AuraEffectList const& ModPowerRegenPCTAuras = GetAuraEffectsByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT); for (AuraEffectList::const_iterator i = ModPowerRegenPCTAuras.begin(); i != ModPowerRegenPCTAuras.end(); ++i) @@ -2844,8 +2847,6 @@ void Player::GiveLevel(uint8 level) SetLevel(level); - UpdateSkillsForLevel(); - // save base values (bonuses already included in stored stats for (uint8 i = STAT_STRENGTH; i < MAX_STATS; ++i) SetCreateStat(Stats(i), info.stats[i]); @@ -3002,6 +3003,7 @@ void Player::InitStatsForLevel(bool reapplyMods) } SetFloatValue(PLAYER_FIELD_MOD_SPELL_POWER_PCT, 1.0f); + SetFloatValue(PLAYER_FIELD_MOD_HASTE_REGEN, 1.0f); //reset attack power, damage and attack speed fields SetFloatValue(UNIT_FIELD_BASEATTACKTIME, 2000.0f); @@ -5499,35 +5501,39 @@ float Player::OCTRegenMPPerSpirit() const void Player::ApplyRatingMod(CombatRating combatRating, int32 value, bool apply) { - float oldRating = m_baseRatingValue[combatRating]; - m_baseRatingValue[combatRating] += (apply ? value : -value); - // explicit affected values - float const multiplier = GetRatingMultiplier(combatRating); - float const oldVal = oldRating * multiplier; - float const newVal = m_baseRatingValue[combatRating] * multiplier; switch (combatRating) { case CR_HASTE_MELEE: - ApplyAttackTimePercentMod(BASE_ATTACK, oldVal, false); - ApplyAttackTimePercentMod(OFF_ATTACK, oldVal, false); - ApplyAttackTimePercentMod(BASE_ATTACK, newVal, true); - ApplyAttackTimePercentMod(OFF_ATTACK, newVal, true); - if (getClass() == CLASS_DEATH_KNIGHT) - UpdateAllRunesRegen(); + { + ApplyAttackTimePercentMod(BASE_ATTACK, m_baseRatingValue[combatRating] * GetRatingMultiplier(combatRating), false); + ApplyAttackTimePercentMod(BASE_ATTACK, (m_baseRatingValue[combatRating] + (apply ? value : -value)) * GetRatingMultiplier(combatRating), true); + ApplyAttackTimePercentMod(OFF_ATTACK, m_baseRatingValue[combatRating] * GetRatingMultiplier(combatRating), false); + ApplyAttackTimePercentMod(OFF_ATTACK, (m_baseRatingValue[combatRating] + (apply ? value : -value)) * GetRatingMultiplier(combatRating), true); + ApplyRegenMod(BASE_ATTACK, m_baseRatingValue[combatRating] * GetRatingMultiplier(combatRating), false); + ApplyRegenMod(BASE_ATTACK, (m_baseRatingValue[combatRating] + (apply ? value : -value)) * GetRatingMultiplier(combatRating), true); break; + } case CR_HASTE_RANGED: - ApplyAttackTimePercentMod(RANGED_ATTACK, oldVal, false); - ApplyAttackTimePercentMod(RANGED_ATTACK, newVal, true); + { + ApplyAttackTimePercentMod(RANGED_ATTACK, m_baseRatingValue[combatRating] * GetRatingMultiplier(combatRating), false); + ApplyAttackTimePercentMod(RANGED_ATTACK, (m_baseRatingValue[combatRating] + (apply ? value : -value)) * GetRatingMultiplier(combatRating), true); + ApplyRegenMod(RANGED_ATTACK, m_baseRatingValue[combatRating] * GetRatingMultiplier(combatRating), false); + ApplyRegenMod(RANGED_ATTACK, (m_baseRatingValue[combatRating] + (apply ? value : -value)) * GetRatingMultiplier(combatRating), true); break; + } case CR_HASTE_SPELL: - ApplyCastTimePercentMod(oldVal, false); - ApplyCastTimePercentMod(newVal, true); + { + ApplyCastTimePercentMod(m_baseRatingValue[combatRating] * GetRatingMultiplier(combatRating), false); + ApplyCastTimePercentMod((m_baseRatingValue[combatRating] + (apply ? value : -value)) * GetRatingMultiplier(combatRating), true); break; + } default: break; } + m_baseRatingValue[combatRating] +=(apply ? value : -value); + UpdateRating(combatRating); } @@ -5886,7 +5892,7 @@ void Player::UpdateSkillsForLevel() uint16 field = itr->second.pos / 2; uint8 offset = itr->second.pos & 1; // itr->second.pos % 2 - //uint16 val = GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset); + uint16 val = GetUInt16Value(PLAYER_SKILL_RANK_0 + field, offset); uint16 max = GetUInt16Value(PLAYER_SKILL_MAX_RANK_0 + field, offset); /// update only level dependent max skill values @@ -24961,25 +24967,7 @@ bool Player::isTotalImmunity() const uint32 Player::GetRuneTypeBaseCooldown(RuneType runeType) const { - float cooldown = RUNE_BASE_COOLDOWN; - float hastePct = 0.0f; - - AuraEffectList const& regenAura = GetAuraEffectsByType(SPELL_AURA_MOD_POWER_REGEN_PERCENT); - for (AuraEffectList::const_iterator i = regenAura.begin();i != regenAura.end(); ++i) - if ((*i)->GetMiscValue() == POWER_RUNE && (*i)->GetMiscValueB() == runeType) - cooldown *= 1.0f - (*i)->GetAmount() / 100.0f; - - // Runes cooldown are now affected by player's haste from equipment ... - hastePct = GetRatingBonusValue(CR_HASTE_MELEE); - - // ... and some auras. - hastePct += GetTotalAuraModifier(SPELL_AURA_MOD_MELEE_HASTE); - hastePct += GetTotalAuraModifier(SPELL_AURA_MOD_MELEE_HASTE_2); - hastePct += GetTotalAuraModifier(SPELL_AURA_MOD_MELEE_HASTE_3); - - cooldown *= 1.0f - (hastePct / 100.0f); - - return cooldown; + return RUNE_BASE_COOLDOWN; } void Player::SetRuneCooldown(uint8 index, uint32 cooldown, bool casted /*= false*/) diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 0d6eb33c28..8be5ca484c 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2013,12 +2013,10 @@ class TC_GAME_API Player : public Unit, public GridObject void ApplyManaRegenBonus(int32 amount, bool apply); void ApplyHealthRegenBonus(int32 amount, bool apply); void UpdateManaRegen(); - void UpdateRuneRegen(RuneType rune); uint32 GetRuneTimer(uint8 index) const { return m_runeGraceCooldown[index]; } void SetRuneTimer(uint8 index, uint32 timer) { m_runeGraceCooldown[index] = timer; } uint32 GetLastRuneGraceTimer(uint8 index) const { return m_lastRuneGraceTimers[index]; } void SetLastRuneGraceTimer(uint8 index, uint32 timer) { m_lastRuneGraceTimers[index] = timer; } - void UpdateAllRunesRegen(); ObjectGuid GetLootGUID() const { return m_lootGuid; } void SetLootGUID(ObjectGuid guid) { m_lootGuid = guid; } diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp index ae07fcfb0c..f01b613e2b 100644 --- a/src/server/game/Entities/Unit/StatSystem.cpp +++ b/src/server/game/Entities/Unit/StatSystem.cpp @@ -765,51 +765,28 @@ void Player::ApplyHealthRegenBonus(int32 amount, bool apply) void Player::UpdateManaRegen() { - // Mana regen from spirit - float spirit_regen = OCTRegenMPPerSpirit(); - // Apply PCT bonus from SPELL_AURA_MOD_POWER_REGEN_PERCENT aura on spirit base regen - spirit_regen *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, POWER_MANA); + if (getPowerType() == POWER_MANA) + { + // Mana regen from spirit + float spirit_regen = OCTRegenMPPerSpirit(); + // Apply PCT bonus from SPELL_AURA_MOD_POWER_REGEN_PERCENT aura on spirit base regen + spirit_regen *= GetTotalAuraMultiplierByMiscValue(SPELL_AURA_MOD_POWER_REGEN_PERCENT, POWER_MANA); - // SpiritRegen(SPI, INT, LEVEL) = (0.001 + (SPI x sqrt(INT) x BASE_REGEN[LEVEL])) x 5 - if (GetStat(STAT_INTELLECT) > 0.0f) - spirit_regen *= std::sqrt(GetStat(STAT_INTELLECT)); + // SpiritRegen(SPI, INT, LEVEL) = (0.001 + (SPI x sqrt(INT) x BASE_REGEN[LEVEL])) x 5 + if (GetStat(STAT_INTELLECT) > 0.0f) + spirit_regen *= std::sqrt(GetStat(STAT_INTELLECT)); - // CombatRegen = 5% of Base Mana - float base_regen = GetCreateMana() * 0.01f + GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) / 5.0f; + // CombatRegen = 5% of Base Mana + float base_regen = GetCreateMana() * 0.01f + GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_POWER_REGEN, POWER_MANA) / 5.0f; - // Set regen rate in cast state apply only on spirit based regen - int32 modManaRegenInterrupt = GetTotalAuraModifier(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT); + // Set regen rate in cast state apply only on spirit based regen + int32 modManaRegenInterrupt = GetTotalAuraModifier(SPELL_AURA_MOD_MANA_REGEN_INTERRUPT); - SetStatFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER, base_regen + CalculatePct(spirit_regen, modManaRegenInterrupt)); - SetStatFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER, 0.001f + spirit_regen + base_regen); -} - -void Player::UpdateRuneRegen(RuneType rune) -{ - if (rune >= NUM_RUNE_TYPES) - return; - - uint32 cooldown = 0; - - for (uint32 i = 0; i < MAX_RUNES; ++i) - if (GetBaseRune(i) == rune) - { - cooldown = GetRuneBaseCooldown(i); - break; - } - - if (cooldown <= 0) - return; - - float regen = float(1 * IN_MILLISECONDS) / float(cooldown); - SetFloatValue(PLAYER_RUNE_REGEN_1 + uint8(rune), regen); -} - -void Player::UpdateAllRunesRegen() -{ - for (uint8 i = 0; i < NUM_RUNE_TYPES; ++i) - if (uint32 cooldown = GetRuneTypeBaseCooldown(RuneType(i))) - SetFloatValue(PLAYER_RUNE_REGEN_1 + i, float(1 * IN_MILLISECONDS) / float(cooldown)); + SetStatFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER, base_regen + CalculatePct(spirit_regen, modManaRegenInterrupt)); + SetStatFloatValue(UNIT_FIELD_POWER_REGEN_FLAT_MODIFIER, 0.001f + spirit_regen + base_regen); + } + else if (getClass() == CLASS_HUNTER) + SetFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER, -0.2f); } void Player::_ApplyAllStatBonuses() diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index ff5af332fb..92cc11459b 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -9343,11 +9343,14 @@ void Unit::ModSpellCastTime(SpellInfo const* spellInfo, int32 & castTime, Spell* if (Player* modOwner = GetSpellModOwner()) modOwner->ApplySpellMod(spellInfo->Id, castTime, spell); + float castSpeedMod = 1; + castSpeedMod = castSpeedMod - GetTotalAuraMultiplier(SPELL_AURA_HASTE_SPELLS) + 1.0f; + if (!(spellInfo->HasAttribute(SPELL_ATTR0_ABILITY) || spellInfo->HasAttribute(SPELL_ATTR0_TRADESPELL) || spellInfo->HasAttribute(SPELL_ATTR3_NO_DONE_BONUS)) && ((GetTypeId() == TYPEID_PLAYER && spellInfo->SpellFamilyName) || GetTypeId() == TYPEID_UNIT)) castTime = int32(float(castTime) * GetFloatValue(UNIT_MOD_CAST_SPEED)); else if (spellInfo->HasAttribute(SPELL_ATTR0_REQ_AMMO) && !spellInfo->HasAttribute(SPELL_ATTR2_AUTOREPEAT_FLAG)) - castTime = int32(float(castTime) * m_modAttackSpeedPct[RANGED_ATTACK]); + castTime = int32(float(castTime) * m_modAttackSpeedPct[RANGED_ATTACK] * castSpeedMod); else if (spellInfo->SpellVisual[0] == 3881 && HasAura(67556)) // cooking with Chef Hat. castTime = 500; } @@ -10964,7 +10967,7 @@ void Unit::ApplyAttackTimePercentMod(WeaponAttackType att, float val, bool apply if (val > 0) { ApplyPercentModFloatVar(m_modAttackSpeedPct[att], val, !apply); - ApplyPercentModFloatValue(UNIT_FIELD_BASEATTACKTIME+att, val, !apply); + ApplyPercentModFloatValue(UNIT_FIELD_BASEATTACKTIME + att, val, !apply); if (GetTypeId() == TYPEID_PLAYER) { @@ -10977,7 +10980,7 @@ void Unit::ApplyAttackTimePercentMod(WeaponAttackType att, float val, bool apply else { ApplyPercentModFloatVar(m_modAttackSpeedPct[att], -val, apply); - ApplyPercentModFloatValue(UNIT_FIELD_BASEATTACKTIME+att, -val, apply); + ApplyPercentModFloatValue(UNIT_FIELD_BASEATTACKTIME + att, -val, apply); if (GetTypeId() == TYPEID_PLAYER) { @@ -10987,9 +10990,56 @@ void Unit::ApplyAttackTimePercentMod(WeaponAttackType att, float val, bool apply ApplyPercentModFloatValue(PLAYER_FIELD_MOD_RANGED_HASTE, -val, apply); } } + m_attackTimer[att] = uint32(GetAttackTime(att) * m_modAttackSpeedPct[att] * remainingTimePct); } +void Unit::ApplyRegenMod(WeaponAttackType att, float val, bool apply) +{ + if (val > 0) + { + if (GetTypeId() == TYPEID_PLAYER) + { + if (att == BASE_ATTACK) + { + if (GetTypeId() == TYPEID_PLAYER && getClass() != CLASS_HUNTER) + ApplyPercentModFloatValue(PLAYER_FIELD_MOD_HASTE_REGEN, val, !apply); + + // Modify rune regeneration based on haste + if (getClass() == CLASS_DEATH_KNIGHT) + for (uint8 i = 0; i < NUM_RUNE_TYPES; i++) + ApplyPercentModFloatValue(PLAYER_RUNE_REGEN_1 + i, val, apply); + } + else if (att == RANGED_ATTACK) + { + if (getClass() == CLASS_HUNTER) + ApplyPercentModFloatValue(PLAYER_FIELD_MOD_HASTE_REGEN, val, !apply); + } + } + } + else + { + if (GetTypeId() == TYPEID_PLAYER) + { + if (att == BASE_ATTACK) + { + if (GetTypeId() == TYPEID_PLAYER && getClass() != CLASS_HUNTER) + ApplyPercentModFloatValue(PLAYER_FIELD_MOD_HASTE_REGEN, -val, apply); + + // Modify rune regeneration based on haste + if (getClass() == CLASS_DEATH_KNIGHT) + for (uint8 i = 0; i < NUM_RUNE_TYPES; i++) + ApplyPercentModFloatValue(PLAYER_RUNE_REGEN_1 + i, val, !apply); + } + else if (att == RANGED_ATTACK) + { + if (getClass() == CLASS_HUNTER) + ApplyPercentModFloatValue(PLAYER_FIELD_MOD_HASTE_REGEN, -val, apply); + } + } + } +} + void Unit::ApplyCastTimePercentMod(float val, bool apply) { if (val > 0) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index ff2743c689..5ea863a88d 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1433,6 +1433,7 @@ class TC_GAME_API Unit : public WorldObject uint32 GetAttackTime(WeaponAttackType att) const; void SetAttackTime(WeaponAttackType att, uint32 val) { SetFloatValue(UNIT_FIELD_BASEATTACKTIME+att, val*m_modAttackSpeedPct[att]); } void ApplyAttackTimePercentMod(WeaponAttackType att, float val, bool apply); + void ApplyRegenMod(WeaponAttackType att, float val, bool apply); void ApplyCastTimePercentMod(float val, bool apply); SheathState GetSheath() const { return SheathState(GetByteValue(UNIT_FIELD_BYTES_2, UNIT_BYTES_2_OFFSET_SHEATH_STATE)); } diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 5284d6b33a..ade3e07a82 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -845,6 +845,12 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo) ok = true; } + if (cInfo->AIName == "TotemAI") + { + TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has not-allowed `AIName` '%s' set, removing", cInfo->Entry, cInfo->AIName.c_str()); + const_cast(cInfo)->AIName.clear(); + } + if (!cInfo->AIName.empty() && !sCreatureAIRegistry->HasItem(cInfo->AIName)) { TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) has non-registered `AIName` '%s' set, removing", cInfo->Entry, cInfo->AIName.c_str()); @@ -7605,7 +7611,7 @@ void ObjectMgr::LoadQuestPOI() _questPOIStore[questId].push_back(POI); } else - TC_LOG_ERROR("server.loading", "Table quest_poi references unknown quest points for quest %u POI id %u", questId, id); + TC_LOG_ERROR("sql.sql", "Table quest_poi references unknown quest points for quest %u POI id %u", questId, id); ++count; } while (result->NextRow()); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index f39d50a23f..6aae2023c6 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -3675,7 +3675,7 @@ void AuraEffect::HandleAuraModExpertise(AuraApplication const* aurApp, uint8 mod /********************************/ /*** HEAL & ENERGIZE ***/ /********************************/ -void AuraEffect::HandleModPowerRegen(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const +void AuraEffect::HandleModPowerRegen(AuraApplication const* aurApp, uint8 mode, bool apply) const { if (!(mode & (AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK | AURA_EFFECT_HANDLE_STAT))) return; @@ -3689,12 +3689,18 @@ void AuraEffect::HandleModPowerRegen(AuraApplication const* aurApp, uint8 mode, if (GetMiscValue() == POWER_MANA) target->ToPlayer()->UpdateManaRegen(); else if (GetMiscValue() == POWER_RUNE) - target->ToPlayer()->UpdateRuneRegen(RuneType(GetMiscValueB())); + target->ApplyPercentModFloatValue(PLAYER_RUNE_REGEN_1 + GetMiscValueB(), float(GetAmount()), apply); // other powers are not immediate effects - implemented in Player::Regenerate, Creature::Regenerate } void AuraEffect::HandleModPowerRegenPCT(AuraApplication const* aurApp, uint8 mode, bool apply) const { + Unit* target = aurApp->GetTarget(); + + if (target->GetTypeId() == TYPEID_PLAYER) + target->ApplyPercentModFloatValue(PLAYER_FIELD_MOD_HASTE_REGEN, GetAmount(), !apply); + + HandleModPowerRegen(aurApp, mode, apply); } @@ -4001,6 +4007,12 @@ void AuraEffect::HandleModMeleeRangedSpeedPct(AuraApplication const* aurApp, uin target->ApplyAttackTimePercentMod(BASE_ATTACK, (float)GetAmount(), apply); target->ApplyAttackTimePercentMod(OFF_ATTACK, (float)GetAmount(), apply); target->ApplyAttackTimePercentMod(RANGED_ATTACK, (float)GetAmount(), apply); + + if (GetAuraType() != SPELL_AURA_MOD_MELEE_RANGED_HASTE_2 && GetAuraType() != SPELL_AURA_MOD_RANGED_HASTE_2) + { + target->ApplyRegenMod(BASE_ATTACK, (float)GetAmount(), apply); + target->ApplyRegenMod(RANGED_ATTACK, (float)GetAmount(), apply); + } } void AuraEffect::HandleModCombatSpeedPct(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -4024,6 +4036,11 @@ void AuraEffect::HandleModCombatSpeedPct(AuraApplication const* aurApp, uint8 mo target->ApplyAttackTimePercentMod(BASE_ATTACK, float(GetAmount()), apply); target->ApplyAttackTimePercentMod(OFF_ATTACK, float(GetAmount()), apply); target->ApplyAttackTimePercentMod(RANGED_ATTACK, float(GetAmount()), apply); + if (GetAuraType() != SPELL_AURA_MOD_MELEE_RANGED_HASTE_2 && GetAuraType() != SPELL_AURA_MOD_RANGED_HASTE_2) + { + target->ApplyRegenMod(BASE_ATTACK, (float)GetAmount(), apply); + target->ApplyRegenMod(RANGED_ATTACK, (float)GetAmount(), apply); + } } void AuraEffect::HandleModAttackSpeed(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -4034,6 +4051,8 @@ void AuraEffect::HandleModAttackSpeed(AuraApplication const* aurApp, uint8 mode, Unit* target = aurApp->GetTarget(); target->ApplyAttackTimePercentMod(BASE_ATTACK, float(GetAmount()), apply); + if (GetAuraType() != SPELL_AURA_MOD_MELEE_RANGED_HASTE_2 && GetAuraType() != SPELL_AURA_MOD_RANGED_HASTE_2) + target->ApplyRegenMod(BASE_ATTACK, (float)GetAmount(), apply); target->UpdateDamagePhysical(BASE_ATTACK); } @@ -4044,17 +4063,17 @@ void AuraEffect::HandleModMeleeSpeedPct(AuraApplication const* aurApp, uint8 mod //! ToDo: Haste auras with the same handler _CAN'T_ stack together Unit* target = aurApp->GetTarget(); - int32 spellGroupVal = target->GetHighestExclusiveSameEffectSpellGroupValue(this, SPELL_AURA_MOD_MELEE_HASTE); - if (abs(spellGroupVal) >= abs(GetAmount())) - return; + bool applyRegenPct = GetAuraType() != SPELL_AURA_MOD_MELEE_HASTE_3 && GetAuraType() != SPELL_AURA_MOD_RANGED_HASTE_2; - if (spellGroupVal) + // Auras that only increase regeneration + if (target->GetTypeId() == TYPEID_PLAYER && applyRegenPct && GetBase()->HasEffectType(SPELL_AURA_MOD_MELEE_HASTE_3)) + target->ApplyRegenMod(BASE_ATTACK, (float)GetAmount(), apply); + else { - target->ApplyAttackTimePercentMod(BASE_ATTACK, float(spellGroupVal), !apply); - target->ApplyAttackTimePercentMod(OFF_ATTACK, float(spellGroupVal), !apply); + target->ApplyAttackTimePercentMod(BASE_ATTACK, (float)GetAmount(), apply); + target->ApplyAttackTimePercentMod(OFF_ATTACK, (float)GetAmount(), apply); + target->ApplyRegenMod(BASE_ATTACK, (float)GetAmount(), apply); } - target->ApplyAttackTimePercentMod(BASE_ATTACK, float(GetAmount()), apply); - target->ApplyAttackTimePercentMod(OFF_ATTACK, float(GetAmount()), apply); } void AuraEffect::HandleAuraModRangedHaste(AuraApplication const* aurApp, uint8 mode, bool apply) const @@ -4066,6 +4085,8 @@ void AuraEffect::HandleAuraModRangedHaste(AuraApplication const* aurApp, uint8 m Unit* target = aurApp->GetTarget(); target->ApplyAttackTimePercentMod(RANGED_ATTACK, (float)GetAmount(), apply); + if (GetAuraType() != SPELL_AURA_MOD_MELEE_RANGED_HASTE_2 && GetAuraType() != SPELL_AURA_MOD_RANGED_HASTE_2) + target->ApplyRegenMod(RANGED_ATTACK, (float)GetAmount(), apply); } /********************************/ diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index fe67a8b221..ba4577cf38 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -3130,6 +3130,7 @@ void Spell::EffectInterruptCast(SpellEffIndex effIndex) { int32 duration = m_spellInfo->GetDuration(); unitTarget->GetSpellHistory()->LockSpellSchool(curSpellInfo->GetSchoolMask(), unitTarget->ModSpellDuration(m_spellInfo, unitTarget, duration, false, 1 << effIndex)); + m_originalCaster->ProcSkillsAndAuras(unitTarget, PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG, PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_HIT, PROC_HIT_INTERRUPT, nullptr, nullptr, nullptr); } ExecuteLogEffectInterruptCast(effIndex, unitTarget, curSpellInfo->Id); unitTarget->InterruptSpell(CurrentSpellTypes(i), false); diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 8a0485dc79..8d4af0a5f5 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -2617,6 +2617,22 @@ void SpellMgr::LoadSpellInfoStore() if (SpellEntry const* spellEntry = sSpellStore.LookupEntry(i)) mSpellInfoMap[i] = new SpellInfo(spellEntry, effectsBySpell[i].effects); + for (uint32 spellIndex = 0; spellIndex < GetSpellInfoStoreSize(); ++spellIndex) + { + if (!mSpellInfoMap[spellIndex]) + continue; + + for (uint32 effectIndex = 0; effectIndex < MAX_SPELL_EFFECTS; ++effectIndex) + { + if (mSpellInfoMap[spellIndex]->Effects[effectIndex].Effect >= TOTAL_SPELL_EFFECTS) + { + TC_LOG_ERROR("sql.sql", "Spell (Entry: %u) has `Effect` '%u' greater than max allowed value '%u', removing", spellIndex, mSpellInfoMap[spellIndex]->Effects[effectIndex].Effect, (TOTAL_SPELL_EFFECTS - 1)); + mSpellInfoMap[spellIndex]->Effects[effectIndex].Effect = 0; + } + } + } + + TC_LOG_INFO("server.loading", ">> Loaded SpellInfo store in %u ms", GetMSTimeDiffToNow(oldMSTime)); } diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h index 996424d4ed..f39dc33a25 100644 --- a/src/server/game/Spells/SpellMgr.h +++ b/src/server/game/Spells/SpellMgr.h @@ -227,7 +227,7 @@ enum ProcFlagsHit PROC_HIT_DEFLECT = 0x0000200, PROC_HIT_ABSORB = 0x0000400, // partial or full absorb PROC_HIT_REFLECT = 0x0000800, - PROC_HIT_INTERRUPT = 0x0001000, // (not used atm) + PROC_HIT_INTERRUPT = 0x0001000, PROC_HIT_FULL_BLOCK = 0x0002000, PROC_HIT_MASK_ALL = 0x0002FFF };