diff options
35 files changed, 543 insertions, 108 deletions
diff --git a/sql/updates/world/2011_09_03_02_spell_script_names.sql b/sql/updates/world/2011_09_03_02_world_spell_script_names.sql index b7b6907b7f1..b7b6907b7f1 100644 --- a/sql/updates/world/2011_09_03_02_spell_script_names.sql +++ b/sql/updates/world/2011_09_03_02_world_spell_script_names.sql diff --git a/sql/updates/world/2011_09_03_06_world_spell_threat.sql b/sql/updates/world/2011_09_03_06_world_spell_threat.sql new file mode 100644 index 00000000000..a59a7739350 --- /dev/null +++ b/sql/updates/world/2011_09_03_06_world_spell_threat.sql @@ -0,0 +1,134 @@ +-- ---------- +-- Tank Class Passive Threat +-- ---------- +DELETE FROM spell_linked_spell WHERE spell_effect IN (57340, 57339); +INSERT INTO spell_linked_spell VALUES + (7376, 57339, 2, 'Defensive Stance Passive - Tank Class Passive Threat'), + (21178, 57339, 2, 'Bear Form (Passive2) - Tank Class Passive Threat'), + (25780, 57340, 2, 'Righteous Fury - Tank Class Passive Threat'), + (48263, 57340, 2, 'Frost Presence - Tank Class Passive Threat'); + +-- ---------- +-- restructure spell_threat +-- ---------- +TRUNCATE TABLE `spell_threat`; +ALTER TABLE `spell_threat` CHANGE `Threat` `flatMod` int(6); +ALTER TABLE `spell_threat` ADD COLUMN `pctMod` FLOAT NOT NULL DEFAULT 1.0 COMMENT 'threat multiplier for damage/healing' AFTER `flatMod`; +ALTER TABLE `spell_threat` ADD COLUMN `apPctMod` FLOAT NOT NULL DEFAULT 0.0 COMMENT 'additional threat bonus from attack power' AFTER `pctMod`; +INSERT INTO `spell_threat` VALUES +-- Other +-- Src: SELECT id, SpellNameEN, RankEN FROM `Spell` WHERE `DescriptionEN` LIKE '%threat%' AND `SpellFamilyName` <> '0' AND NOT (Attributes & 0x40) GROUP BY SpellNameEN ORDER BY RankEN DESC; + (5676, 0, 2.00, 0.0), -- Searing Pain (Rank 1) (Warlock) + (28176, 0, 0.00, 0.0), -- Fel Armor - Heal (Rank 1) (Warlock) [Assumption] + (8056, 0, 2.00, 0.0), -- Frost Shock (Rank 1) (Shaman) [Assumption] + (26688, 0, 0.00, 0.0), -- Anesthetic Poison - Proc (Rank 1) (Rogue) + (15237, 0, 0.00, 0.0), -- Holy Nova - Heal (Rank 1) (Priest) + (23455, 0, 0.00, 0.0), -- Holy Nova - Damage (Rank 1) (Priest) + (32546, 0, 0.50, 0.0), -- Binding Heal (Rank 1) (Priest) [Assumption] + (33619, 0, 0.00, 0.0), -- Reflective Shield - Proc (Priest) + (2139, 180, 1.00, 0.0), -- Counterspell (Mage) [Assumption] +-- Death Knight +-- Src: http://www.tankspot.com/showthread.php?40485-Death-Knight-threat-values&p=113584#post113584 + (63611, 0, 0.00, 0.0), -- Blood Presence - Heal + (45524, 240, 1.00, 0.0), -- Chains of Ice + (43265, 0, 1.90, 0.0), -- Death and Decay + (49576, 110, 1.00, 0.0), -- Death Grip + (48743, 0, 0.00, 0.0), -- Death Pact + (65142, 0, 0.00, 0.0), -- Ebon Plague + (47568, 0, 0.00, 0.0), -- Empower Rune Weapon + (51209, 112, 1.00, 0.0), -- Hungering Cold + (49039, 110, 1.00, 0.0), -- Lichborn + (56815, 0, 1.75, 0.0), -- Rune Strike + (50422, 0, 0.00, 0.0), -- Scent of Blood - Proc + (55090, 51, 1.00, 0.0), -- Scourge Strike (Rank 1) + (55265, 63, 1.00, 0.0), -- Scourge Strike (Rank 2) + (55270, 98, 1.00, 0.0), -- Scourge Strike (Rank 3) + (55271, 120, 1.00, 0.0), -- Scourge Strike (Rank 4) + (49916, 138, 1.00, 0.0), -- Strangulate + (50181, 0, 0.00, 0.0), -- Vendetta - Proc +-- Druid +-- Src: http://www.tankspot.com/showthread.php?47813-WOTLK-Bear-Threat-Values&p=200948#post200948 + (17057, 0, 0.00, 0.0), -- Furor - Proc + (5211, 53, 1.00, 0.0), -- Bash (Rank 3) + (6798, 105, 1.00, 0.0), -- Bash (Rank 2) + (8983, 158, 1.00, 0.0), -- Bash (Rank 1) + (45334, 40, 1.00, 0.0), -- Feral Charge (Bear) - Root + (19675, 80, 1.00, 0.0), -- Feral Charge (Bear) - Interrupt + (34299, 0, 0.00, 0.0), -- Improved Leader of the Pack - Heal + (6807, 13, 1.00, 0.0), -- Maul (Rank 1) + (6808, 20, 1.00, 0.0), -- Maul (Rank 2) + (6809, 27, 1.00, 0.0), -- Maul (Rank 3) + (8972, 47, 1.00, 0.0), -- Maul (Rank 4) + (9745, 75, 1.00, 0.0), -- Maul (Rank 5) + (9880, 106, 1.00, 0.0), -- Maul (Rank 6) + (9881, 140, 1.00, 0.0), -- Maul (Rank 7) + (26996, 212, 1.00, 0.0), -- Maul (Rank 8) + (48479, 345, 1.00, 0.0), -- Maul (Rank 9) + (48480, 422, 1.00, 0.0), -- Maul (Rank 10) + (60089, 638, 1.00, 0.0), -- Faerie Fire (Feral) - Proc + (33745, 182, 0.50, 0.0), -- Lacerate (Rank 1) + (48567, 409, 0.50, 0.0), -- Lacerate (Rank 2) + (48568, 515, 0.50, 0.0), -- Lacerate (Rank 3) + (779, 0, 1.50, 0.0), -- Swipe (Bear) (Rank 1) + (5209, 98, 1.00, 0.0), -- Challenging Roar + (29166, 0, 10.0, 0.0), -- Innervate [base is 5 per 1 mana] +-- Paladin +-- Src: http://www.tankspot.com/showthread.php?39761-Paladin-Threat-Values-(Updated-for-3.2.2)&p=103813#post103813 + (7294, 0, 2.00, 0.0), -- Retribution Aura + (20185, 0, 0.00, 0.0), -- Judgement of Light + (19742, 0, 0.00, 0.0), -- Blessing of Wisdom (Rank 1) + (25894, 0, 0.00, 0.0), -- Greater Blessing of Wisdom (Rank 1) + (20470, 0, 0.00, 0.0), -- Righteous Fury + (498, 0, 0.00, 0.0), -- Divine Protection +-- Warrior +-- Src: http://www.tankspot.com/showthread.php?39775-WoW-3.0-Threat-Values-(Warrior)&p=103972#post103972 + (845, 8, 1.00, 0.0), -- Cleave (Rank 1) + (7369, 15, 1.00, 0.0), -- Cleave (Rank 2) + (11608, 25, 1.00, 0.0), -- Cleave (Rank 3) + (11609, 35, 1.00, 0.0), -- Cleave (Rank 4) + (20569, 48, 1.00, 0.0), -- Cleave (Rank 5) + (25231, 68, 1.00, 0.0), -- Cleave (Rank 6) + (47519, 95, 1.00, 0.0), -- Cleave (Rank 7) + (47520, 112, 1.00, 0.0), -- Cleave (Rank 8) + (78, 5, 1.00, 0.0), -- Heroic Strike (Rank 1) + (284, 10, 1.00, 0.0), -- Heroic Strike (Rank 2) + (285, 16, 1.00, 0.0), -- Heroic Strike (Rank 3) + (1608, 22, 1.00, 0.0), -- Heroic Strike (Rank 4) + (11564, 31, 1.00, 0.0), -- Heroic Strike (Rank 5) + (11565, 48, 1.00, 0.0), -- Heroic Strike (Rank 6) + (11566, 70, 1.00, 0.0), -- Heroic Strike (Rank 7) + (11567, 92, 1.00, 0.0), -- Heroic Strike (Rank 8) + (25286, 104, 1.00, 0.0), -- Heroic Strike (Rank 9) + (29707, 121, 1.00, 0.0), -- Heroic Strike (Rank 10) + (30324, 164, 1.00, 0.0), -- Heroic Strike (Rank 11) + (47449, 224, 1.00, 0.0), -- Heroic Strike (Rank 12) + (47450, 259, 1.00, 0.0), -- Heroic Strike (Rank 13) + (57755, 0, 1.50, 0.0), -- Heroic Throw + (6572, 7, 1.00, 0.0), -- Revenge (Rank 1) + (6574, 11, 1.00, 0.0), -- Revenge (Rank 2) + (7379, 15, 1.00, 0.0), -- Revenge (Rank 3) + (11600, 27, 1.00, 0.0), -- Revenge (Rank 4) + (11601, 41, 1.00, 0.0), -- Revenge (Rank 5) + (25288, 53, 1.00, 0.0), -- Revenge (Rank 6) + (25269, 58, 1.00, 0.0), -- Revenge (Rank 7) + (30357, 71, 1.00, 0.0), -- Revenge (Rank 8) + (57823, 121, 1.00, 0.0), -- Revenge (Rank 9) + (23922, 228, 1.00, 0.0), -- Shield Slam (Rank 1) + (23923, 268, 1.00, 0.0), -- Shield Slam (Rank 2) + (23924, 307, 1.00, 0.0), -- Shield Slam (Rank 3) + (23925, 347, 1.00, 0.0), -- Shield Slam (Rank 4) + (25258, 387, 1.00, 0.0), -- Shield Slam (Rank 5) + (30356, 426, 1.00, 0.0), -- Shield Slam (Rank 6) + (47487, 650, 1.00, 0.0), -- Shield Slam (Rank 7) + (47488, 770, 1.00, 0.0), -- Shield Slam (Rank 8) + (1464, 18, 1.00, 0.0), -- Slam (Rank 1) + (8820, 24, 1.00, 0.0), -- Slam (Rank 2) + (11604, 38, 1.00, 0.0), -- Slam (Rank 3) + (11605, 49, 1.00, 0.0), -- Slam (Rank 4) + (25241, 59, 1.00, 0.0), -- Slam (Rank 5) + (25242, 78, 1.00, 0.0), -- Slam (Rank 6) + (47474, 123, 1.00, 0.0), -- Slam (Rank 7) + (47475, 140, 1.00, 0.0), -- Slam (Rank 8) + (7386, 345, 1.00, 0.05), -- Sunder Armor + (20243, 0, 1.00, 0.05), -- Devastate (Rank 1) + (6343, 0, 1.85, 0.0); -- Thunder Clap (Rank 1) diff --git a/sql/updates/world/2011_09_03_07_world_achievement_criteria_data.sql b/sql/updates/world/2011_09_03_07_world_achievement_criteria_data.sql new file mode 100644 index 00000000000..7ae27745be6 --- /dev/null +++ b/sql/updates/world/2011_09_03_07_world_achievement_criteria_data.sql @@ -0,0 +1,28 @@ +DELETE FROM `disables` WHERE `entry` IN (1242, 1803, 1804, 1805, 1806, 1807, 1808, 1809, 1810, 1825, 1811, 1812, 1813, 1814, 1815, 1816, 1817, 1818, 1819, 1826, 3386, 3387, 3388, 3389) AND `sourceType` = 4; + +DELETE FROM `achievement_criteria_data` WHERE `criteria_id` IN (1242, 1803, 1804, 1805, 1806, 1807, 1808, 1809, 1810, 1825, 1811, 1812, 1813, 1814, 1815, 1816, 1817, 1818, 1819, 1826, 3386, 3387, 3388, 3389); +INSERT INTO `achievement_criteria_data` (`criteria_id`,`type`,`value1`,`value2`,`ScriptName`) VALUES +(1242, 11, 0, 0, 'achievement_bg_av_perfection'), +(1803, 11, 0, 0, 'achievement_bg_av_perfection'), +(1804, 11, 0, 0, 'achievement_bg_av_perfection'), +(1805, 11, 0, 0, 'achievement_bg_av_perfection'), +(1806, 11, 0, 0, 'achievement_bg_av_perfection'), +(1807, 11, 0, 0, 'achievement_bg_av_perfection'), +(1808, 11, 0, 0, 'achievement_bg_av_perfection'), +(1809, 11, 0, 0, 'achievement_bg_av_perfection'), +(1810, 11, 0, 0, 'achievement_bg_av_perfection'), +(1825, 11, 0, 0, 'achievement_bg_av_perfection'), +(1811, 11, 0, 0, 'achievement_bg_av_perfection'), +(1812, 11, 0, 0, 'achievement_bg_av_perfection'), +(1813, 11, 0, 0, 'achievement_bg_av_perfection'), +(1814, 11, 0, 0, 'achievement_bg_av_perfection'), +(1815, 11, 0, 0, 'achievement_bg_av_perfection'), +(1816, 11, 0, 0, 'achievement_bg_av_perfection'), +(1817, 11, 0, 0, 'achievement_bg_av_perfection'), +(1818, 11, 0, 0, 'achievement_bg_av_perfection'), +(1819, 11, 0, 0, 'achievement_bg_av_perfection'), +(1826, 11, 0, 0, 'achievement_bg_av_perfection'), +(3386, 11, 0, 0, 'achievement_everything_counts'), +(3387, 11, 0, 0, 'achievement_everything_counts'), +(3388, 11, 0, 0, 'achievement_everything_counts'), +(3389, 11, 0, 0, 'achievement_everything_counts');
\ No newline at end of file diff --git a/sql/updates/world/2011_09_03_08_world_spell_dbc.sql b/sql/updates/world/2011_09_03_08_world_spell_dbc.sql new file mode 100644 index 00000000000..4d57e320822 --- /dev/null +++ b/sql/updates/world/2011_09_03_08_world_spell_dbc.sql @@ -0,0 +1,2 @@ +ALTER TABLE `spell_dbc` ADD COLUMN `AttributesEx6` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `AttributesEx5`; +ALTER TABLE `spell_dbc` ADD COLUMN `AttributesEx7` INT UNSIGNED NOT NULL DEFAULT '0' AFTER `AttributesEx6`; diff --git a/sql/updates/world/2011_09_03_09_world_spell_dbc.sql b/sql/updates/world/2011_09_03_09_world_spell_dbc.sql new file mode 100644 index 00000000000..31d4b19b1ca --- /dev/null +++ b/sql/updates/world/2011_09_03_09_world_spell_dbc.sql @@ -0,0 +1,5 @@ +-- Dummy effect with caster as target +DELETE FROM `spell_dbc` WHERE `id` IN (68308); +INSERT INTO `spell_dbc` (`Id`, `Attributes`, `AttributesEx`, `AttributesEx2`,`AttributesEx3`,`AttributesEx4`,`AttributesEx5`,`AttributesEx6`,`Effect1`,`EffectImplicitTargetA1`,`EffectImplicitTargetB1`,`comment`) +VALUES +(68308, 0x09800100, 0x00000420, 0x00004005, 0x10040000, 0x00000080, 0x00000008, 0x00001000, 3, 1, 0, 'Vault of Archavon - Earth, Wind & Fire - Achievement Check'); diff --git a/sql/updates/world/2011_09_03_10_world_spell_dbc.sql b/sql/updates/world/2011_09_03_10_world_spell_dbc.sql new file mode 100644 index 00000000000..119bf863a8b --- /dev/null +++ b/sql/updates/world/2011_09_03_10_world_spell_dbc.sql @@ -0,0 +1,3 @@ +DELETE FROM `spell_dbc` WHERE `Id`=63975; +INSERT INTO `spell_dbc` (`Id`, `Dispel`, `Mechanic`, `Attributes`, `AttributesEx`, `AttributesEx2`, `AttributesEx3`, `AttributesEx4`, `AttributesEx5`, `Stances`, `StancesNot`, `Targets`, `CastingTimeIndex`, `AuraInterruptFlags`, `ProcFlags`, `ProcChance`, `ProcCharges`, `MaxLevel`, `BaseLevel`, `SpellLevel`, `DurationIndex`, `RangeIndex`, `StackAmount`, `EquippedItemClass`, `EquippedItemSubClassMask`, `EquippedItemInventoryTypeMask`, `Effect1`, `Effect2`, `Effect3`, `EffectDieSides1`, `EffectDieSides2`, `EffectDieSides3`, `EffectRealPointsPerLevel1`, `EffectRealPointsPerLevel2`, `EffectRealPointsPerLevel3`, `EffectBasePoints1`, `EffectBasePoints2`, `EffectBasePoints3`, `EffectMechanic1`, `EffectMechanic2`, `EffectMechanic3`, `EffectImplicitTargetA1`, `EffectImplicitTargetA2`, `EffectImplicitTargetA3`, `EffectImplicitTargetB1`, `EffectImplicitTargetB2`, `EffectImplicitTargetB3`, `EffectRadiusIndex1`, `EffectRadiusIndex2`, `EffectRadiusIndex3`, `EffectApplyAuraName1`, `EffectApplyAuraName2`, `EffectApplyAuraName3`, `EffectAmplitude1`, `EffectAmplitude2`, `EffectAmplitude3`, `EffectMultipleValue1`, `EffectMultipleValue2`, `EffectMultipleValue3`, `EffectMiscValue1`, `EffectMiscValue2`, `EffectMiscValue3`, `EffectMiscValueB1`, `EffectMiscValueB2`, `EffectMiscValueB3`, `EffectTriggerSpell1`, `EffectTriggerSpell2`, `EffectTriggerSpell3`, `EffectSpellClassMaskA1`, `EffectSpellClassMaskA2`, `EffectSpellClassMaskA3`, `EffectSpellClassMaskB1`, `EffectSpellClassMaskB2`, `EffectSpellClassMaskB3`, `EffectSpellClassMaskC1`, `EffectSpellClassMaskC2`, `EffectSpellClassMaskC3`, `MaxTargetLevel`, `SpellFamilyName`, `SpellFamilyFlags1`, `SpellFamilyFlags2`, `SpellFamilyFlags3`, `MaxAffectedTargets`, `DmgClass`, `PreventionType`, `DmgMultiplier1`, `DmgMultiplier2`, `DmgMultiplier3`, `AreaGroupId`, `SchoolMask`, `Comment`) VALUES +(63975,0,0,384,0,0,262144,128,0,0,0,0,1,0,0,0,0,0,0,0,0,13,0,-1,0,0,77,0,0,0,1,1,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,'Glyph of Blackstab - 3.2.2'); diff --git a/sql/updates/world/2011_09_04_00_world_quest_template.sql b/sql/updates/world/2011_09_04_00_world_quest_template.sql new file mode 100644 index 00000000000..4ff774b65b4 --- /dev/null +++ b/sql/updates/world/2011_09_04_00_world_quest_template.sql @@ -0,0 +1,6 @@ +UPDATE `quest_template` SET `RequiredRaces`=1101 WHERE `entry` IN (4362,4363); -- The Fate of the Kingdom & The Princess's Surprise +UPDATE `quest_template` SET `NextQuestId`=4342 WHERE `entry`=4341; -- Kharan Mighthammer +UPDATE `quest_template` SET `PrevQuestId`=4341 WHERE `entry`=4342; -- Kharan's Tale +UPDATE `quest_template` SET `PrevQuestId`=4342 WHERE `entry`=4361; -- The Bearer of Bad News +UPDATE `quest_template` SET `PrevQuestId`=4361 WHERE `entry`=4362; -- The Fate of the Kingdom +UPDATE `quest_template` SET `PrevQuestId`=4362 WHERE `entry`=4363; -- The Princess's Surprise diff --git a/sql/updates/world/2011_09_04_01_world_trinity_string.sql b/sql/updates/world/2011_09_04_01_world_trinity_string.sql new file mode 100644 index 00000000000..0f36a362db9 --- /dev/null +++ b/sql/updates/world/2011_09_04_01_world_trinity_string.sql @@ -0,0 +1,3 @@ +DELETE FROM `trinity_string` WHERE `entry`=5030; +INSERT INTO `trinity_string` (`entry`, `content_default`, `content_loc1`, `content_loc2`, `content_loc3`, `content_loc4`, `content_loc5`, `content_loc6`, `content_loc7`, `content_loc8`) VALUES +(5030, '%s attempts to run away in fear!', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL); diff --git a/sql/updates/world/2011_09_04_02_world_trinity_string.sql b/sql/updates/world/2011_09_04_02_world_trinity_string.sql new file mode 100644 index 00000000000..36722947feb --- /dev/null +++ b/sql/updates/world/2011_09_04_02_world_trinity_string.sql @@ -0,0 +1 @@ +UPDATE `trinity_string` SET `content_default`='Faction %s (%u) can''t have reputation.' WHERE `entry`=326; -- can'nt -> can't diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 0de13280376..680c0815c6b 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -692,6 +692,8 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u return; me->DoFleeToGetAssistance(); + if (e.action.flee.withEmote) + sCreatureTextMgr->SendChatString(me, sObjectMgr->GetTrinityStringForDBCLocale(LANG_FLEE), CHAT_MSG_MONSTER_EMOTE); sLog->outDebug(LOG_FILTER_DATABASE_AI, "SmartScript::ProcessAction:: SMART_ACTION_FLEE_FOR_ASSIST: Creature %u DoFleeToGetAssistance", me->GetGUIDLow()); break; } diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index d6235b05667..de60737f3b6 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -383,7 +383,7 @@ enum SMART_ACTION SMART_ACTION_SET_EVENT_PHASE = 22, // Phase SMART_ACTION_INC_EVENT_PHASE = 23, // Value (may be negative to decrement phase, should not be 0) SMART_ACTION_EVADE = 24, // No Params - SMART_ACTION_FLEE_FOR_ASSIST = 25, // No Params + SMART_ACTION_FLEE_FOR_ASSIST = 25, // With Emote SMART_ACTION_CALL_GROUPEVENTHAPPENS = 26, // QuestID SMART_ACTION_CALL_CASTEDCREATUREORGO = 27, // CreatureId, SpellId SMART_ACTION_REMOVEAURASFROMSPELL = 28, // Spellid @@ -854,6 +854,11 @@ struct SmartAction struct { + uint32 withEmote; + } flee; + + struct + { uint32 param1; uint32 param2; uint32 param3; diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp index b01385e6536..d5dbdca976f 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.cpp @@ -1491,3 +1491,62 @@ void BattlegroundAV::ResetBGSubclass() DelCreature(i); } + +bool BattlegroundAV::IsBothMinesControlledByTeam(uint32 team) const +{ + for (uint8 mine = 0; mine < 2; mine++) + if (m_Mine_Owner[mine] != team) + return false; + + return true; +} + +bool BattlegroundAV::IsAllTowersControlledAndCaptainAlive(uint32 team) const +{ + if (team == ALLIANCE) + { + for (BG_AV_Nodes i = BG_AV_NODES_DUNBALDAR_SOUTH; i <= BG_AV_NODES_STONEHEART_BUNKER; ++i) // alliance towers controlled + { + if (m_Nodes[i].State == POINT_CONTROLED) + { + if (m_Nodes[i].Owner != ALLIANCE) + return false; + } + else + return false; + } + + for (BG_AV_Nodes i = BG_AV_NODES_ICEBLOOD_TOWER; i <= BG_AV_NODES_FROSTWOLF_WTOWER; ++i) // horde towers destroyed + if (m_Nodes[i].State != POINT_DESTROYED) + return false; + + if (!m_CaptainAlive[0]) + return false; + + return true; + } + else if (team == HORDE) + { + for (BG_AV_Nodes i = BG_AV_NODES_ICEBLOOD_TOWER; i <= BG_AV_NODES_FROSTWOLF_WTOWER; ++i) // horde towers controlled + { + if (m_Nodes[i].State == POINT_CONTROLED) + { + if (m_Nodes[i].Owner != HORDE) + return false; + } + else + return false; + } + + for (BG_AV_Nodes i = BG_AV_NODES_DUNBALDAR_SOUTH; i <= BG_AV_NODES_STONEHEART_BUNKER; ++i) // alliance towers destroyed + if (m_Nodes[i].State != POINT_DESTROYED) + return false; + + if (!m_CaptainAlive[1]) + return false; + + return true; + } + + return false; +}
\ No newline at end of file diff --git a/src/server/game/Battlegrounds/Zones/BattlegroundAV.h b/src/server/game/Battlegrounds/Zones/BattlegroundAV.h index 5832a0f87c5..83fd559fdd4 100755 --- a/src/server/game/Battlegrounds/Zones/BattlegroundAV.h +++ b/src/server/game/Battlegrounds/Zones/BattlegroundAV.h @@ -1563,6 +1563,10 @@ class BattlegroundAV : public Battleground virtual WorldSafeLocsEntry const* GetClosestGraveYard(Player* player); + /* achievement req. */ + bool IsBothMinesControlledByTeam(uint32 team) const; + bool IsAllTowersControlledAndCaptainAlive(uint32 team) const; + private: virtual void PostUpdateImpl(uint32 diff); diff --git a/src/server/game/Chat/Channels/Channel.h b/src/server/game/Chat/Channels/Channel.h index 12f26022f59..c5466d65d3f 100755 --- a/src/server/game/Chat/Channels/Channel.h +++ b/src/server/game/Chat/Channels/Channel.h @@ -95,12 +95,13 @@ enum ChannelDBCFlags CHANNEL_DBC_FLAG_INITIAL = 0x00001, // General, Trade, LocalDefense, LFG CHANNEL_DBC_FLAG_ZONE_DEP = 0x00002, // General, Trade, LocalDefense, GuildRecruitment CHANNEL_DBC_FLAG_GLOBAL = 0x00004, // WorldDefense - CHANNEL_DBC_FLAG_TRADE = 0x00008, // Trade - CHANNEL_DBC_FLAG_CITY_ONLY = 0x00010, // Trade, GuildRecruitment - CHANNEL_DBC_FLAG_CITY_ONLY2 = 0x00020, // Trade, GuildRecruitment + CHANNEL_DBC_FLAG_TRADE = 0x00008, // Trade, LFG + CHANNEL_DBC_FLAG_CITY_ONLY = 0x00010, // Trade, GuildRecruitment, LFG + CHANNEL_DBC_FLAG_CITY_ONLY2 = 0x00020, // Trade, GuildRecruitment, LFG CHANNEL_DBC_FLAG_DEFENSE = 0x10000, // LocalDefense, WorldDefense CHANNEL_DBC_FLAG_GUILD_REQ = 0x20000, // GuildRecruitment - CHANNEL_DBC_FLAG_LFG = 0x40000 // LookingForGroup + CHANNEL_DBC_FLAG_LFG = 0x40000, // LFG + CHANNEL_DBC_FLAG_UNK1 = 0x80000, // General }; enum ChannelMemberFlags diff --git a/src/server/game/Combat/HostileRefManager.cpp b/src/server/game/Combat/HostileRefManager.cpp index 5d9e7d671c8..47e9a1d2508 100755 --- a/src/server/game/Combat/HostileRefManager.cpp +++ b/src/server/game/Combat/HostileRefManager.cpp @@ -40,10 +40,9 @@ void HostileRefManager::threatAssist(Unit* victim, float baseThreat, SpellInfo c threat /= getSize(); while (ref) { - if (victim == getOwner()) - ref->addThreat(threat); // It is faster to modify the threat durectly if possible - else - ref->getSource()->addThreat(victim, threat); + if (ThreatCalcHelper::isValidProcess(victim, ref->getSource()->getOwner(), threatSpell)) + ref->getSource()->doAddThreat(victim, threat); + ref = ref->next(); } } diff --git a/src/server/game/Combat/ThreatManager.cpp b/src/server/game/Combat/ThreatManager.cpp index bf3650f611e..858ef057baf 100755 --- a/src/server/game/Combat/ThreatManager.cpp +++ b/src/server/game/Combat/ThreatManager.cpp @@ -36,8 +36,14 @@ float ThreatCalcHelper::calcThreat(Unit* hatedUnit, Unit* /*hatingUnit*/, float { if (threatSpell) { - if (threatSpell->AttributesEx & SPELL_ATTR1_NO_THREAT) - return 0.0f; + if (SpellThreatEntry const* threatEntry = sSpellMgr->GetSpellThreatEntry(threatSpell->Id)) + if (threatEntry->pctMod != 1.0f) + threat *= threatEntry->pctMod; + + // Energize is not affected by Mods + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; i++) + if (threatSpell->Effects[i].Effect == SPELL_EFFECT_ENERGIZE || threatSpell->Effects[i].ApplyAuraName == SPELL_AURA_PERIODIC_ENERGIZE) + return threat; if (Player* modOwner = hatedUnit->GetSpellModOwner()) modOwner->ApplySpellMod(threatSpell->Id, SPELLMOD_THREAT, threat); @@ -46,7 +52,7 @@ float ThreatCalcHelper::calcThreat(Unit* hatedUnit, Unit* /*hatingUnit*/, float return hatedUnit->ApplyTotalThreatModifier(threat, schoolMask); } -bool ThreatCalcHelper::isValidProcess(Unit* hatedUnit, Unit* hatingUnit, SpellInfo const* /*threatSpell*/) +bool ThreatCalcHelper::isValidProcess(Unit* hatedUnit, Unit* hatingUnit, SpellInfo const* threatSpell) { //function deals with adding threat and adding players and pets into ThreatList //mobs, NPCs, guards have ThreatList and HateOfflineList @@ -68,6 +74,10 @@ bool ThreatCalcHelper::isValidProcess(Unit* hatedUnit, Unit* hatingUnit, SpellIn if (!hatedUnit->isAlive() || !hatingUnit->isAlive()) return false; + // spell not causing threat + if (threatSpell && threatSpell->AttributesEx & SPELL_ATTR1_NO_THREAT) + return false; + ASSERT(hatingUnit->GetTypeId() == TYPEID_UNIT); return true; diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h index 8f7ce9d8df3..0728a2f838e 100755 --- a/src/server/game/DataStores/DBCfmt.h +++ b/src/server/game/DataStores/DBCfmt.h @@ -99,7 +99,7 @@ const std::string CustomSpellDifficultyfmt="ppppp"; const std::string CustomSpellDifficultyIndex="id"; const char SpellDurationfmt[]="niii"; const char SpellEntryfmt[]="niiiiiiiiiiiixixiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffiiiiiiiiiiiiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiiixfffxxxiiiiixxfffxx"; -const std::string CustomSpellEntryfmt="pappppppppaapapapaaaaaaaaaaapaaapapppppppaaaaapaapaaaaaaaaaaaaaaaaaappppppppppppppppppppppppppppppppppppaaaaaapppppppppaaapppppppppaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaappppppppapppaaaaappaaaaaaa"; +const std::string CustomSpellEntryfmt="papppppppppppapapaaaaaaaaaaapaaapapppppppaaaaapaapaaaaaaaaaaaaaaaaaappppppppppppppppppppppppppppppppppppaaaaaapppppppppaaapppppppppaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaappppppppapppaaaaappaaaaaaa"; const std::string CustomSpellEntryIndex = "Id"; const char SpellFocusObjectfmt[]="nxxxxxxxxxxxxxxxxx"; const char SpellItemEnchantmentfmt[]="nxiiiiiixxxiiissssssssssssssssxiiiiiii"; diff --git a/src/server/game/Entities/Creature/GossipDef.cpp b/src/server/game/Entities/Creature/GossipDef.cpp index e17f8163bff..0d91b476fdd 100755 --- a/src/server/game/Entities/Creature/GossipDef.cpp +++ b/src/server/game/Entities/Creature/GossipDef.cpp @@ -441,7 +441,7 @@ void PlayerMenu::SendQuestQueryResponse(Quest const* quest) const data << uint32(quest->GetRepObjectiveFaction()); // shown in quest log as part of quest objective data << uint32(quest->GetRepObjectiveValue()); // shown in quest log as part of quest objective - data << uint32(quest->GetRepObjectiveFaction2()); // shown in quest log as part of quest objective OPOSITE faction + data << uint32(quest->GetRepObjectiveFaction2()); // shown in quest log as part of quest objective OPPOSITE faction data << uint32(quest->GetRepObjectiveValue2()); // shown in quest log as part of quest objective OPPOSITE faction data << uint32(quest->GetNextQuestInChain()); // client will request this quest from NPC, if not 0 diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 8742deb2eb5..e0adb99bc37 100755 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -5522,14 +5522,14 @@ void Player::RepopAtGraveyard() bool Player::CanJoinConstantChannelInZone(ChatChannelsEntry const* channel, AreaTableEntry const* zone) { - if (channel->flags & CHANNEL_DBC_FLAG_ZONE_DEP) - { - if (zone->flags & AREA_FLAG_ARENA_INSTANCE) - return false; + if (channel->flags & CHANNEL_DBC_FLAG_ZONE_DEP && zone->flags & AREA_FLAG_ARENA_INSTANCE) + return false; - if ((channel->flags & CHANNEL_DBC_FLAG_CITY_ONLY) && !(zone->flags & AREA_FLAG_CAPITAL)) - return false; - } + if ((channel->flags & CHANNEL_DBC_FLAG_CITY_ONLY) && (!(zone->flags & AREA_FLAG_SLAVE_CAPITAL))) + return false; + + if ((channel->flags & CHANNEL_DBC_FLAG_GUILD_REQ) && GetGuildId()) + return false; return true; } @@ -5577,12 +5577,6 @@ void Player::UpdateLocalChannels(uint32 newZone) { if (ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(i)) { - if (!(channel->flags & CHANNEL_DBC_FLAG_ZONE_DEP)) - continue; // Not zone dependent, don't handle it here - - if ((channel->flags & CHANNEL_DBC_FLAG_GUILD_REQ) && GetGuildId()) - continue; // Should not join to these channels automatically - Channel* usedChannel = NULL; for (JoinedChannelsList::iterator itr = m_channels.begin(); itr != m_channels.end(); ++itr) @@ -14636,10 +14630,6 @@ bool Player::CanCompleteQuest(uint32 quest_id) if (repFacId && GetReputationMgr().GetReputation(repFacId) < qInfo->GetRepObjectiveValue()) return false; - uint32 repFacId2 = qInfo->GetRepObjectiveFaction2(); - if (repFacId2 && GetReputationMgr().GetReputation(repFacId2) < qInfo->GetRepObjectiveValue2()) - return false; - return true; } } @@ -15272,6 +15262,16 @@ bool Player::SatisfyQuestReputation(Quest const* qInfo, bool msg) SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ); return false; } + + // ReputationObjective2 does not seem to be an objective requirement but a requirement + // to be able to accept the quest + uint32 fIdObj = qInfo->GetRepObjectiveFaction2(); + if (fIdObj && GetReputationMgr().GetReputation(fIdObj) >= qInfo->GetRepObjectiveValue2()) + { + if (msg) + SendCanTakeQuestResponse(INVALIDREASON_DONT_HAVE_REQ); + return false; + } return true; } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 4cea8f56005..be46e9b1ffb 100755 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -791,12 +791,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam victim->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_DIRECT_DAMAGE, spellProto ? spellProto->Id : 0); if (victim->GetTypeId() != TYPEID_PLAYER) - { - if (spellProto && IsDamageToThreatSpell(spellProto)) - victim->AddThreat(this, damage * 2.0f, damageSchoolMask, spellProto); - else victim->AddThreat(this, (float)damage, damageSchoolMask, spellProto); - } else // victim is a player { // random durability for items (HIT TAKEN) @@ -6603,6 +6598,13 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere return true; } } + // Misdirection + if (dummySpell->Id == 34477) + { + triggered_spell_id = 35079; // 4 sec buff on self + target = this; + break; + } break; } case SPELLFAMILY_PALADIN: @@ -10334,6 +10336,9 @@ void Unit::EnergizeBySpell(Unit* victim, uint32 spellID, uint32 damage, Powers p SendEnergizeSpellLog(victim, spellID, damage, powerType); // needs to be called after sending spell log victim->ModifyPower(powerType, damage); + + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellID); + victim->getHostileRefManager().threatAssist(this, float(damage) * 0.5f, spellInfo); } uint32 Unit::SpellDamageBonus(Unit* victim, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack) @@ -11622,30 +11627,6 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index) cons return false; } -bool Unit::IsDamageToThreatSpell(SpellInfo const* spellInfo) const -{ - if (!spellInfo) - return false; - - switch(spellInfo->SpellFamilyName) - { - case SPELLFAMILY_WARLOCK: - if (spellInfo->SpellFamilyFlags[0] == 0x100) // Searing Pain - return true; - break; - case SPELLFAMILY_SHAMAN: - if (spellInfo->SpellFamilyFlags[0] == SPELLFAMILYFLAG_SHAMAN_FROST_SHOCK) - return true; - break; - case SPELLFAMILY_DEATHKNIGHT: - if (spellInfo->SpellFamilyFlags[1] == 0x20000000) // Rune Strike - return true; - break; - } - - return false; -} - void Unit::MeleeDamageBonus(Unit* victim, uint32 *pdamage, WeaponAttackType attType, SpellInfo const* spellProto) { if (!victim) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index e777f16b99a..fb41914d6f7 100755 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1572,8 +1572,6 @@ class Unit : public WorldObject void SendPlaySpellVisual(uint32 id); void SendPlaySpellImpact(uint64 guid, uint32 id); - bool IsDamageToThreatSpell(SpellInfo const* spellInfo) const; - void DeMorph(); void SendAttackStateUpdate(CalcDamageInfo *damageInfo); diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index e1b37c121a7..62b2ce0c440 100755 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -3931,28 +3931,28 @@ void ObjectMgr::LoadQuests() // no changes, quest can't be done for this requirement } - if (!qinfo->RepObjectiveFaction && qinfo->RepObjectiveValue > 0) + if (!qinfo->RepObjectiveFaction && qinfo->RepObjectiveValue != 0) { sLog->outErrorDb("Quest %u has `RepObjectiveValue` = %d but `RepObjectiveFaction` is 0, value has no effect", qinfo->GetQuestId(), qinfo->RepObjectiveValue); // warning } - if (!qinfo->RepObjectiveFaction2 && qinfo->RepObjectiveValue2 > 0) + if (!qinfo->RepObjectiveFaction2 && qinfo->RepObjectiveValue2 != 0) { sLog->outErrorDb("Quest %u has `RepObjectiveValue2` = %d but `RepObjectiveFaction2` is 0, value has no effect", qinfo->GetQuestId(), qinfo->RepObjectiveValue2); // warning } - if (!qinfo->RequiredMinRepFaction && qinfo->RequiredMinRepValue > 0) + if (!qinfo->RequiredMinRepFaction && qinfo->RequiredMinRepValue != 0) { sLog->outErrorDb("Quest %u has `RequiredMinRepValue` = %d but `RequiredMinRepFaction` is 0, value has no effect", qinfo->GetQuestId(), qinfo->RequiredMinRepValue); // warning } - if (!qinfo->RequiredMaxRepFaction && qinfo->RequiredMaxRepValue > 0) + if (!qinfo->RequiredMaxRepFaction && qinfo->RequiredMaxRepValue != 0) { sLog->outErrorDb("Quest %u has `RequiredMaxRepValue` = %d but `RequiredMaxRepFaction` is 0, value has no effect", qinfo->GetQuestId(), qinfo->RequiredMaxRepValue); diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h index e824a3cf5da..9e8a4b17f84 100755 --- a/src/server/game/Miscellaneous/Language.h +++ b/src/server/game/Miscellaneous/Language.h @@ -943,6 +943,7 @@ enum TrinityStrings LANG_GOINFO_LOOTID = 5028, LANG_COMMAND_LOOKUP_MAX_RESULTS = 5029, // Room for more Trinity strings 5030-9999 + LANG_FLEE = 5030, // Level requirement notifications LANG_SAY_REQ = 6604, diff --git a/src/server/game/Server/Protocol/Handlers/ChannelHandler.cpp b/src/server/game/Server/Protocol/Handlers/ChannelHandler.cpp index 0ccfce64045..3f9609bc0e0 100755 --- a/src/server/game/Server/Protocol/Handlers/ChannelHandler.cpp +++ b/src/server/game/Server/Protocol/Handlers/ChannelHandler.cpp @@ -26,21 +26,15 @@ void WorldSession::HandleJoinChannel(WorldPacket& recvPacket) uint32 channel_id; uint8 unknown1, unknown2; std::string channelname, pass; + ChatChannelsEntry const* channel; recvPacket >> channel_id; if (channel_id) { - ChatChannelsEntry const* channel = sChatChannelsStore.LookupEntry(channel_id); + channel = sChatChannelsStore.LookupEntry(channel_id); if (!channel) return; - - AreaTableEntry const* current_zone = GetAreaEntryByAreaID(_player->GetZoneId()); - if (!current_zone) - return; - - if (!_player->CanJoinConstantChannelInZone(channel, current_zone)) - return; } recvPacket >> unknown1 >> unknown2; @@ -50,6 +44,14 @@ void WorldSession::HandleJoinChannel(WorldPacket& recvPacket) return; recvPacket >> pass; + + AreaTableEntry const* current_zone = GetAreaEntryByAreaID(_player->GetZoneId()); + if (!current_zone) + return; + + if (!_player->CanJoinConstantChannelInZone(channel, current_zone)) + return; + if (ChannelMgr* cMgr = channelMgr(_player->GetTeam())) { cMgr->team = _player->GetTeam(); diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index 8b68bff0a56..0fe54f2f2e8 100755 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -4927,22 +4927,18 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool case SPELLFAMILY_PRIEST: // Vampiric Touch if (m_spellInfo->SpellFamilyFlags[1] & 0x0400 && aurApp->GetRemoveMode() == AURA_REMOVE_BY_ENEMY_SPELL && GetEffIndex() == 0) - { if (AuraEffect const* aurEff = GetBase()->GetEffect(1)) { int32 damage = aurEff->GetAmount() * 8; // backfire damage target->CastCustomSpell(target, 64085, &damage, NULL, NULL, true, NULL, NULL, GetCasterGUID()); } - } break; case SPELLFAMILY_WARLOCK: // Haunt if (m_spellInfo->SpellFamilyFlags[1] & 0x40000) - { if (caster) target->CastCustomSpell(caster, 48210, &m_amount, 0, 0, true, NULL, this, GetCasterGUID()); - } break; case SPELLFAMILY_DRUID: // Lifebloom @@ -4965,9 +4961,16 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool } break; case SPELLFAMILY_HUNTER: - // Misdirection - if (GetId() == 34477) - target->SetReducedThreatPercent(0, 0); + switch (GetId()) + { + case 34477: // Misdirection + if (aurApp->GetRemoveMode() != AURA_REMOVE_BY_EXPIRE) + target->SetReducedThreatPercent(0, 0); + break; + case 35079: // Misdirection proc + target->SetReducedThreatPercent(0, 0); + break; + } break; case SPELLFAMILY_DEATHKNIGHT: // Summon Gargoyle (Dismiss Gargoyle at remove) diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index ed36a4ae208..5642df13d8a 100755 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2335,7 +2335,7 @@ void Spell::SelectEffectTargets(uint32 i, SpellImplicitTargetInfo const& cur) } else { - sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "SPELL: unknown target coordinates for spell ID %u", m_spellInfo->Id); + sLog->outError("SPELL: unknown target coordinates for spell ID %u", m_spellInfo->Id); Unit* target = NULL; if (uint64 guid = m_caster->GetUInt64Value(UNIT_FIELD_TARGET)) target = ObjectAccessor::GetUnit(*m_caster, guid); @@ -4536,20 +4536,53 @@ void Spell::TakeReagents() void Spell::HandleThreatSpells() { - if (!m_targets.GetUnitTarget()) + if (m_UniqueTargetInfo.empty()) return; - if (!m_targets.GetUnitTarget()->CanHaveThreatList()) + if ((m_spellInfo->AttributesEx & SPELL_ATTR1_NO_THREAT) || + (m_spellInfo->AttributesEx3 & SPELL_ATTR3_NO_INITIAL_AGGRO)) return; - uint16 threat = sSpellMgr->GetSpellThreat(m_spellInfo->Id); + float threat = 0.0f; + if (SpellThreatEntry const* threatEntry = sSpellMgr->GetSpellThreatEntry(m_spellInfo->Id)) + { + if (threatEntry->apPctMod != 0.0f) + threat += threatEntry->apPctMod * m_caster->GetTotalAttackPowerValue(BASE_ATTACK); + + threat += threatEntry->flatMod; + } + else if ((m_spellInfo->AttributesCu & SPELL_ATTR0_CU_NO_INITIAL_THREAT) == 0) + threat += m_spellInfo->SpellLevel; - if (!threat) + // past this point only multiplicative effects occur + if (threat == 0.0f) return; - m_targets.GetUnitTarget()->AddThreat(m_caster, float(threat)); + // since 2.0.1 threat from positive effects also is distributed among all targets, so the overall caused threat is at most the defined bonus + threat /= m_UniqueTargetInfo.size(); + + for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) + { + if (ihit->missCondition != SPELL_MISS_NONE) + continue; + + Unit* target = ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID); + if (!target) + continue; + + // positive spells distribute threat among all units that are in combat with target, like healing + if (m_spellInfo->_IsPositiveSpell()) + target->getHostileRefManager().threatAssist(m_caster, threat, m_spellInfo); + // for negative spells threat gets distributed among affected targets + else + { + if (!target->CanHaveThreatList()) + continue; - sLog->outStaticDebug("Spell %u, rank %u, added an additional %i threat", m_spellInfo->Id, m_spellInfo->GetRank(), threat); + target->AddThreat(m_caster, threat, m_spellInfo->GetSchoolMask(), m_spellInfo); + } + } + sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell %u, added an additional %f threat for %s %u target(s)", m_spellInfo->Id, threat, m_spellInfo->_IsPositiveSpell() ? "assisting" : "harming", uint32(m_UniqueTargetInfo.size())); } void Spell::HandleEffects(Unit *pUnitTarget, Item *pItemTarget, GameObject *pGOTarget, uint32 i) @@ -4723,7 +4756,8 @@ SpellCastResult Spell::CheckCast(bool strict) } { - SpellCastResult castResult = m_spellInfo->CheckExplicitTarget(m_caster, m_targets.GetObjectTarget()); + // Check explicit target for m_originalCaster - todo: get rid of such workarounds + SpellCastResult castResult = m_spellInfo->CheckExplicitTarget(m_originalCaster ? m_originalCaster : m_caster, m_targets.GetObjectTarget(), m_targets.GetItemTarget()); if (castResult != SPELL_CAST_OK) return castResult; } diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 93f9640b92a..8dd1cc0242d 100755 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -3275,6 +3275,7 @@ void Spell::EffectDistract(SpellEffIndex /*effIndex*/) unitTarget->SetOrientation(angle); unitTarget->StopMoving(); unitTarget->GetMotionMaster()->MoveDistract(damage * IN_MILLISECONDS); + unitTarget->SendMovementFlagUpdate(); } } diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 04e90d2083b..3e374b62cd1 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -1721,13 +1721,14 @@ SpellCastResult SpellInfo::CheckTarget(Unit const* caster, Unit const* target, b return SPELL_CAST_OK; } -SpellCastResult SpellInfo::CheckExplicitTarget(Unit const* caster, WorldObject const* target) const +SpellCastResult SpellInfo::CheckExplicitTarget(Unit const* caster, WorldObject const* target, Item const* itemTarget) const { uint32 neededTargets = GetExplicitTargetMask(); if (!target) { if (neededTargets & (TARGET_FLAG_UNIT_MASK | TARGET_FLAG_GAMEOBJECT_MASK | TARGET_FLAG_CORPSE_MASK)) - return SPELL_FAILED_BAD_TARGETS; + if (!(neededTargets & TARGET_FLAG_GAMEOBJECT_ITEM) || !itemTarget) + return SPELL_FAILED_BAD_TARGETS; return SPELL_CAST_OK; } diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index 69f160cbb0f..b79e50db001 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -24,6 +24,7 @@ class Unit; class Player; +class Item; class Spell; class SpellInfo; struct SpellChainNode; @@ -186,7 +187,7 @@ enum SpellCustomAttributes SPELL_ATTR0_CU_CONE_BACK = 0x00000002, SPELL_ATTR0_CU_CONE_LINE = 0x00000004, SPELL_ATTR0_CU_SHARE_DAMAGE = 0x00000008, - SPELL_ATTR0_CU_NONE1 = 0x00000010, // UNUSED + SPELL_ATTR0_CU_NO_INITIAL_THREAT = 0x00000010, SPELL_ATTR0_CU_NONE2 = 0x00000020, // UNUSED SPELL_ATTR0_CU_AURA_CC = 0x00000040, SPELL_ATTR0_CU_DIRECT_DAMAGE = 0x00000100, @@ -442,7 +443,7 @@ public: SpellCastResult CheckShapeshift(uint32 form) const; SpellCastResult CheckLocation(uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player = NULL) const; SpellCastResult CheckTarget(Unit const* caster, Unit const* target, bool implicit = true) const; - SpellCastResult CheckExplicitTarget(Unit const* caster, WorldObject const* target) const; + SpellCastResult CheckExplicitTarget(Unit const* caster, WorldObject const* target, Item const* itemTarget = NULL) const; bool CheckTargetCreatureType(Unit const* target) const; SpellSchoolMask GetSchoolMask() const; diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 3b546a94bfa..85139061303 100755 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -965,13 +965,19 @@ SpellBonusEntry const* SpellMgr::GetSpellBonusData(uint32 spellId) const return NULL; } -uint16 SpellMgr::GetSpellThreat(uint32 spellid) const +SpellThreatEntry const* SpellMgr::GetSpellThreatEntry(uint32 spellID) const { - SpellThreatMap::const_iterator itr = mSpellThreatMap.find(spellid); - if (itr == mSpellThreatMap.end()) - return 0; - - return itr->second; + SpellThreatMap::const_iterator itr = mSpellThreatMap.find(spellID); + if (itr != mSpellThreatMap.end()) + return &itr->second; + else + { + uint32 firstSpell = GetFirstSpellInChain(spellID); + SpellThreatMap::const_iterator itr = mSpellThreatMap.find(firstSpell); + if (itr != mSpellThreatMap.end()) + return &itr->second; + } + return NULL; } SkillLineAbilityMapBounds SpellMgr::GetSkillLineAbilityMapBounds(uint32 spell_id) const @@ -1940,8 +1946,8 @@ void SpellMgr::LoadSpellThreats() uint32 count = 0; - // 0 1 - QueryResult result = WorldDatabase.Query("SELECT entry, Threat FROM spell_threat"); + // 0 1 2 3 + QueryResult result = WorldDatabase.Query("SELECT entry, flatMod, pctMod, apPctMod FROM spell_threat"); if (!result) { sLog->outString(">> Loaded 0 aggro generating spells"); @@ -1954,7 +1960,6 @@ void SpellMgr::LoadSpellThreats() Field *fields = result->Fetch(); uint32 entry = fields[0].GetUInt32(); - uint16 Threat = fields[1].GetUInt16(); if (!GetSpellInfo(entry)) { @@ -1962,12 +1967,16 @@ void SpellMgr::LoadSpellThreats() continue; } - mSpellThreatMap[entry] = Threat; + SpellThreatEntry ste; + ste.flatMod = fields[1].GetInt16(); + ste.pctMod = fields[2].GetFloat(); + ste.apPctMod = fields[3].GetFloat(); - ++count; + mSpellThreatMap[entry] = ste; + count++; } while (result->NextRow()); - sLog->outString(">> Loaded %u aggro generating spells in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); + sLog->outString(">> Loaded %u SpellThreatEntries in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); sLog->outString(); } @@ -2634,6 +2643,18 @@ void SpellMgr::LoadSpellCustomAttr() case SPELL_AURA_MOD_STUN: spellInfo->AttributesCu |= SPELL_ATTR0_CU_AURA_CC; break; + case SPELL_AURA_PERIODIC_HEAL: + case SPELL_AURA_PERIODIC_DAMAGE: + case SPELL_AURA_PERIODIC_DAMAGE_PERCENT: + case SPELL_AURA_PERIODIC_LEECH: + case SPELL_AURA_PERIODIC_MANA_LEECH: + case SPELL_AURA_PERIODIC_HEALTH_FUNNEL: + case SPELL_AURA_PERIODIC_ENERGIZE: + case SPELL_AURA_OBS_MOD_HEALTH: + case SPELL_AURA_OBS_MOD_POWER: + case SPELL_AURA_POWER_BURN: + spellInfo->AttributesCu |= SPELL_ATTR0_CU_NO_INITIAL_THREAT; + break; } switch (spellInfo->Effects[j].Effect) @@ -2646,6 +2667,16 @@ void SpellMgr::LoadSpellCustomAttr() case SPELL_EFFECT_HEAL: spellInfo->AttributesCu |= SPELL_ATTR0_CU_DIRECT_DAMAGE; break; + case SPELL_EFFECT_POWER_DRAIN: + case SPELL_EFFECT_POWER_BURN: + case SPELL_EFFECT_HEAL_MAX_HEALTH: + case SPELL_EFFECT_HEALTH_LEECH: + case SPELL_EFFECT_HEAL_PCT: + case SPELL_EFFECT_ENERGIZE_PCT: + case SPELL_EFFECT_ENERGIZE: + case SPELL_EFFECT_HEAL_MECHANICAL: + spellInfo->AttributesCu |= SPELL_ATTR0_CU_NO_INITIAL_THREAT; + break; case SPELL_EFFECT_CHARGE: case SPELL_EFFECT_CHARGE_DEST: case SPELL_EFFECT_JUMP: @@ -3032,6 +3063,7 @@ void SpellMgr::LoadDbcDataCorrections() case 57761: // Fireball! case 39805: // Lightning Overload case 64823: // Item - Druid T8 Balance 4P Bonus + case 34477: // Misdirection case 44401: // Missile Barrage spellInfo->procCharges = 1; break; diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h index e8ac3ce9862..64d21b7c3a5 100755 --- a/src/server/game/Spells/SpellMgr.h +++ b/src/server/game/Spells/SpellMgr.h @@ -349,7 +349,14 @@ enum SpellGroupStackRule typedef std::map<SpellGroup, SpellGroupStackRule> SpellGroupStackMap; -typedef std::map<uint32, uint16> SpellThreatMap; +struct SpellThreatEntry +{ + int32 flatMod; // flat threat-value for this Spell - default: 0 + float pctMod; // threat-multiplier for this Spell - default: 1.0f + float apPctMod; // Pct of AP that is added as Threat - default: 0.0f +}; + +typedef std::map<uint32, SpellThreatEntry> SpellThreatMap; // Spell script target related declarations (accessed using SpellMgr functions) enum SpellScriptTargetType @@ -603,7 +610,7 @@ class SpellMgr SpellBonusEntry const* GetSpellBonusData(uint32 spellId) const; // Spell threat table - uint16 GetSpellThreat(uint32 spellid) const; + SpellThreatEntry const* GetSpellThreatEntry(uint32 spellID) const; SkillLineAbilityMapBounds GetSkillLineAbilityMapBounds(uint32 spell_id) const; diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp index 91cd8dee55c..7566d9bc410 100755 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/instance_trial_of_the_crusader.cpp @@ -85,7 +85,6 @@ class instance_trial_of_the_crusader : public InstanceMapScript EventStage = 0; TributeChestGUID = 0; - DataDamageTwin = 0; MainGateDoorGUID = 0; EastPortcullisGUID = 0; diff --git a/src/server/scripts/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp b/src/server/scripts/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp index 904566e13a4..8d668011f9a 100644 --- a/src/server/scripts/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp +++ b/src/server/scripts/Northrend/VaultOfArchavon/instance_vault_of_archavon.cpp @@ -41,6 +41,9 @@ class instance_archavon : public InstanceMapScript { EmalonGUID = 0; ToravonGUID = 0; + ArchavonDeath = 0; + EmalonDeath = 0; + KoralonDeath = 0; } void OnCreatureCreate(Creature* creature) @@ -73,9 +76,63 @@ class instance_archavon : public InstanceMapScript return 0; } + bool SetBossState(uint32 type, EncounterState state) + { + if (!InstanceScript::SetBossState(type, state)) + return false; + + if (state != DONE) + return true; + + switch (type) + { + case DATA_ARCHAVON: + ArchavonDeath = time(NULL); + break; + case DATA_EMALON: + EmalonDeath = time(NULL); + break; + case DATA_KORALON: + KoralonDeath = time(NULL); + break; + default: + return true; + } + + // on every death of Archavon, Emalon and Koralon check our achievement + DoCastSpellOnPlayers(SPELL_EARTH_WIND_FIRE_ACHIEVEMENT_CHECK); + + return true; + } + + bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target*/, uint32 /*miscvalue1*/) + { + switch (criteria_id) + { + case CRITERIA_EARTH_WIND_FIRE_10: + case CRITERIA_EARTH_WIND_FIRE_25: + if (ArchavonDeath && EmalonDeath && KoralonDeath) + { + // instance difficulty check is already done in db (achievement_criteria_data) + // int() for Visual Studio, compile errors with abs(time_t) + return (abs(int(ArchavonDeath-EmalonDeath)) < MINUTE && \ + abs(int(EmalonDeath-KoralonDeath)) < MINUTE && \ + abs(int(KoralonDeath-ArchavonDeath)) < MINUTE); + } + break; + default: + break; + } + + return false; + } + private: uint64 EmalonGUID; uint64 ToravonGUID; + time_t ArchavonDeath; + time_t EmalonDeath; + time_t KoralonDeath; }; InstanceScript* GetInstanceScript(InstanceMap* map) const diff --git a/src/server/scripts/Northrend/VaultOfArchavon/vault_of_archavon.h b/src/server/scripts/Northrend/VaultOfArchavon/vault_of_archavon.h index 4aa01e58f5f..04f50d3adeb 100644 --- a/src/server/scripts/Northrend/VaultOfArchavon/vault_of_archavon.h +++ b/src/server/scripts/Northrend/VaultOfArchavon/vault_of_archavon.h @@ -36,4 +36,15 @@ enum Data #define MAX_ENCOUNTER 4 +enum AchievementCriteriaIds +{ + CRITERIA_EARTH_WIND_FIRE_10 = 12018, + CRITERIA_EARTH_WIND_FIRE_25 = 12019, +}; + +enum AchievementSpells +{ + SPELL_EARTH_WIND_FIRE_ACHIEVEMENT_CHECK = 68308, +}; + #endif diff --git a/src/server/scripts/World/achievement_scripts.cpp b/src/server/scripts/World/achievement_scripts.cpp index db09c12da0b..af966e3e22e 100755 --- a/src/server/scripts/World/achievement_scripts.cpp +++ b/src/server/scripts/World/achievement_scripts.cpp @@ -21,6 +21,7 @@ #include "BattlegroundWS.h" #include "BattlegroundIC.h" #include "BattlegroundSA.h" +#include "BattlegroundAV.h" #include "Vehicle.h" class achievement_storm_glory : public AchievementCriteriaScript @@ -207,6 +208,48 @@ public: } }; +class achievement_everything_counts : public AchievementCriteriaScript +{ + public: + achievement_everything_counts() : AchievementCriteriaScript("achievement_everything_counts") { } + + bool OnCheck(Player* source, Unit* /*target*/) + { + Battleground* bg = source->GetBattleground(); + if (!bg) + return false; + + if (source->GetBattlegroundTypeId() != BATTLEGROUND_AV) + return false; + + if (static_cast<BattlegroundAV*>(bg)->IsBothMinesControlledByTeam(source->GetTeam())) + return true; + + return false; + } +}; + +class achievement_bg_av_perfection : public AchievementCriteriaScript +{ + public: + achievement_bg_av_perfection() : AchievementCriteriaScript("achievement_bg_av_perfection") { } + + bool OnCheck(Player* source, Unit* /*target*/) + { + Battleground* bg = source->GetBattleground(); + if (!bg) + return false; + + if (source->GetBattlegroundTypeId() != BATTLEGROUND_AV) + return false; + + if (static_cast<BattlegroundAV*>(bg)->IsAllTowersControlledAndCaptainAlive(source->GetTeam())) + return true; + + return false; + } +}; + class achievement_wg_didnt_stand_a_chance : public AchievementCriteriaScript { public: @@ -269,6 +312,8 @@ void AddSC_achievement_scripts() new achievement_bg_sa_artillery(); new achievement_sickly_gazelle(); new achievement_wg_didnt_stand_a_chance(); + new achievement_everything_counts(); + new achievement_bg_av_perfection(); new achievement_arena_kills("achievement_arena_2v2_kills", ARENA_TYPE_2v2); new achievement_arena_kills("achievement_arena_3v3_kills", ARENA_TYPE_3v3); new achievement_arena_kills("achievement_arena_5v5_kills", ARENA_TYPE_5v5); |