diff --git a/data/sql/updates/db_world/2022_09_19_00.sql b/data/sql/updates/db_world/2022_09_19_00.sql new file mode 100644 index 000000000..f2621b274 --- /dev/null +++ b/data/sql/updates/db_world/2022_09_19_00.sql @@ -0,0 +1,11 @@ +-- DB update 2022_09_17_01 -> 2022_09_19_00 +-- +UPDATE `creature_template` SET `unit_flags2`=0, `AiName`='', `ScriptName`='npc_obsidian_nullifier' WHERE `entry`=15312; +DELETE FROM `smart_scripts` WHERE `entryorguid`=15312 AND `source_type`=0; + +DELETE FROM `spell_script_names` WHERE `spell_id` IN (25671,26552); +INSERT INTO `spell_script_names` VALUES +(25671,'spell_drain_mana'), +(26552,'spell_nullify'); + +UPDATE `creature_formations` SET `groupAI`=`groupAI`|0x008 WHERE `memberguid` BETWEEN 88022 AND 88029; diff --git a/data/sql/updates/db_world/2022_09_19_01.sql b/data/sql/updates/db_world/2022_09_19_01.sql new file mode 100644 index 000000000..ae623a86e --- /dev/null +++ b/data/sql/updates/db_world/2022_09_19_01.sql @@ -0,0 +1,14 @@ +-- DB update 2022_09_19_00 -> 2022_09_19_01 +-- +DELETE FROM `creature_loot_template` WHERE (`Entry` = 1675); +INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES +(1675, 159, 0, 6, 0, 1, 2, 1, 1, 'Rot Hide Mongrel - Refreshing Spring Water'), +(1675, 2589, 0, 44, 0, 1, 0, 1, 2, 'Rot Hide Mongrel - Linen Cloth'), +(1675, 2834, 0, 31, 1, 1, 0, 1, 1, 'Rot Hide Mongrel - Embalming Ichor'), +(1675, 4604, 0, 11, 0, 1, 2, 1, 1, 'Rot Hide Mongrel - Forest Mushroom Cap'), +(1675, 11111, 11111, 0.1, 0, 1, 0, 1, 1, 'Rot Hide Mongrel - (ReferenceTable)'), +(1675, 24073, 24073, 30, 0, 1, 1, 1, 1, 'Rot Hide Mongrel - (ReferenceTable)'), +(1675, 24100, 24100, 5, 0, 1, 1, 1, 1, 'Rot Hide Mongrel - (ReferenceTable)'), +(1675, 24720, 24720, 1, 0, 1, 1, 1, 1, 'Rot Hide Mongrel - (ReferenceTable)'), +(1675, 24730, 24730, 1, 0, 1, 1, 1, 1, 'Rot Hide Mongrel - (ReferenceTable)'), +(1675, 44007, 44007, 0.5, 0, 1, 1, 1, 1, 'Rot Hide Mongrel - (ReferenceTable)'); diff --git a/data/sql/updates/db_world/2022_09_19_02.sql b/data/sql/updates/db_world/2022_09_19_02.sql new file mode 100644 index 000000000..1486ce668 --- /dev/null +++ b/data/sql/updates/db_world/2022_09_19_02.sql @@ -0,0 +1,67 @@ +-- DB update 2022_09_19_01 -> 2022_09_19_02 +-- +DELETE FROM `areatrigger_scripts` WHERE `entry` IN (1946, 1986); +INSERT INTO `areatrigger_scripts` (`entry`, `ScriptName`) VALUES +(1986, 'near_scarshield_infiltrator'), +(1946, 'at_scarshield_infiltrator'); + +-- Update Position and set kneel animation +-- VMangos Position: https://github.com/vmangos/core/blob/5073ba81290178612580acba6991bfba8bed632d/sql/migrations/20220402225440_world.sql +UPDATE `creature` SET `position_x`=57.0545, `position_y`=-399.681, `position_z`=64.4311, `orientation`=2.94961, `MovementType`=0 WHERE `guid`=42798; +DELETE FROM `creature_addon` WHERE `guid` = 42798; +INSERT INTO `creature_addon` (`guid`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `visibilityDistanceType`, `auras`) VALUES (42798, 0, 0, 8, 0, 0, 0, NULL); + +-- Add condition to show gossip option +DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 15) AND (`SourceGroup` = 12039); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(15, 12039, 1, 0, 0, 2, 0, 12219, 1, 0, 0, 0, 0, '', 'Show gossip option if player has Unadorned Seal of Ascension'), +(15, 12039, 1, 0, 0, 27, 0, 57, 3, 0, 0, 0, 0, '', 'Show gossip option if player is at least level 57'), +(15, 12039, 0, 0, 0, 2, 0, 12219, 1, 0, 1, 0, 0, '', 'Show gossip option if player does not have Unadorned Seal of Ascension'), +(15, 12039, 0, 0, 0, 27, 0, 57, 3, 0, 0, 0, 0, '', 'Show gossip option if player is at least level 57'); + +-- Add condition to send the right gossip text +DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 22) AND (`SourceEntry` = 10299); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(22, 4, 10299, 0, 0, 2, 0, 12219, 1, 0, 1, 0, 0, '', 'Show gossip text if player does not have Unadorned Seal of Ascension'), +(22, 4, 10299, 0, 1, 27, 0, 57, 3, 0, 1, 0, 0, '', 'Show gossip text if player is below level 57'), +(22, 5, 10299, 0, 0, 2, 0, 12219, 1, 0, 0, 0, 0, '', 'Show gossip text if player has Unadorned Seal of Ascension'), +(22, 5, 10299, 0, 0, 27, 0, 57, 3, 0, 0, 0, 0, '', 'Show gossip text if player is at least level 57'); + +-- Link npc_text with gossip_menu +DELETE FROM `gossip_menu` WHERE `MenuID` IN (12039, 12040, 12041, 12042, 12043, 12044, 12045, 12046, 12047, 12048); +INSERT INTO `gossip_menu` (`MenuID`, `TextID`) VALUES (12039, 3301), (12039, 3311), (12040, 3302), (12041, 3303), (12042, 3304), (12043, 3305), (12044, 3306), (12045, 3307), (12046, 3308), (12047, 3309), (12048, 3310); + +-- Vaelan, Remove static Vaelan +DELETE FROM `creature` WHERE `guid` = 42797 AND `id1`= 10296; +UPDATE `creature_template` SET `AIName` = 'SmartAI', `npcflag`=1|2, `gossip_menu_id` = 12039, `MovementType` = 0, `minlevel` = 55 WHERE (`entry` = 10296); +-- Scarshield Infiltrator +UPDATE `creature_template` SET `AIName` = 'SmartAI', `gossip_menu_id` = 0, `npcflag` = 0, `MovementType` = 0, `minlevel` = 55 WHERE (`entry` = 10299); + +DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 10299); +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`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(10299, 0, 0, 0, 38, 0, 100, 1, 0, 1, 0, 0, 0, 80, 1029900, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarshield Infiltrator - On Data Set 0 1 - Run Script (No Repeat)'), +(10299, 0, 1, 0, 62, 0, 100, 0, 12039, 1, 0, 0, 0, 80, 1029901, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarshield Infiltrator - On Gossip Option 1 Selected - Run Script'), +(10299, 0, 2, 0, 62, 0, 100, 0, 12048, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarshield Infiltrator - On Gossip Option 0 Selected - Close Gossip'), +(10299, 0, 3, 0, 64, 0, 100, 0, 12039, 0, 0, 0, 0, 98, 12039, 3301, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarshield Infiltrator - On Gossip Hello - Send Gossip'), +(10299, 0, 4, 0, 64, 0, 100, 0, 12039, 0, 0, 0, 0, 98, 12039, 3311, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarshield Infiltrator - On Gossip Hello - Send Gossip'); + +-- Actionlist +DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 1029900); +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`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(1029900, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 11, 16037, 0, 0, 0, 0, 0, 21, 90, 0, 0, 0, 0, 0, 0, 0, 'Scarshield Infiltrator - Actionlist - Cast \'Mind Probe\''), +(1029900, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 91, 8, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarshield Infiltrator - Actionlist - Remove FlagStandstate Kneel'), +(1029900, 9, 2, 0, 0, 0, 100, 0, 1500, 1500, 0, 0, 0, 36, 10296, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarshield Infiltrator - Actionlist - Update Template To \'Vaelan\''), +(1029900, 9, 3, 0, 0, 0, 100, 0, 1500, 1500, 0, 0, 0, 83, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarshield Infiltrator - Actionlist - Remove Npc Flags Gossip & Questgiver'), +(1029900, 9, 4, 0, 0, 0, 100, 0, 1500, 1500, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 21, 90, 0, 0, 0, 0, 0, 0, 0, 'Scarshield Infiltrator - Actionlist - Set Orientation Closest Player'), +(1029900, 9, 5, 0, 0, 0, 100, 0, 2500, 2500, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarshield Infiltrator - Actionlist - Say Line 0'), +(1029900, 9, 6, 0, 0, 0, 100, 0, 8500, 8500, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarshield Infiltrator - Actionlist - Say Line 1'), +(1029900, 9, 7, 0, 0, 0, 100, 0, 10500, 10500, 0, 0, 0, 81, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarshield Infiltrator - Actionlist - Set Npc Flags Gossip'); +DELETE FROM `smart_scripts` WHERE (`source_type` = 9 AND `entryorguid` = 1029901); +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`, `event_param5`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES +(1029901, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarshield Infiltrator - Actionlist - Close Gossip'), +(1029901, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarshield Infiltrator - Actionlist - Remove Npc Flags Gossip'), +(1029901, 9, 2, 0, 0, 0, 100, 0, 100, 100, 0, 0, 0, 5, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarshield Infiltrator - Actionlist - Play Emote 1'), +(1029901, 9, 3, 0, 0, 0, 100, 0, 3000, 3000, 0, 0, 0, 11, 16051, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarshield Infiltrator - Actionlist - Cast \'Barrier of Light\''), +(1029901, 9, 4, 0, 0, 0, 100, 0, 3000, 3000, 0, 0, 0, 1, 2, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarshield Infiltrator - Actionlist - Say Line 2'), +(1029901, 9, 5, 0, 0, 0, 100, 0, 7500, 7500, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarshield Infiltrator - Actionlist - Say Line 3'), +(1029901, 9, 6, 0, 0, 0, 100, 0, 11500, 11500, 0, 0, 0, 82, 2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Scarshield Infiltrator - Actionlist - Add Npc Flags Questgiver'); diff --git a/data/sql/updates/db_world/2022_09_19_03.sql b/data/sql/updates/db_world/2022_09_19_03.sql new file mode 100644 index 000000000..aea94772f --- /dev/null +++ b/data/sql/updates/db_world/2022_09_19_03.sql @@ -0,0 +1,71 @@ +-- DB update 2022_09_19_02 -> 2022_09_19_03 +-- +-- Add missing quest greetings from 1.13 sniffs. +DELETE FROM `quest_greeting` WHERE `ID` IN (661, 1377, 2487, 3050, 4047, 5393, 5637, 6868, 8256, 8379, 10428, 1738, 138492, 2277, 5888, 6169, 6946, 7802); +INSERT INTO `quest_greeting` (`ID`, `type`, `Greeting`, `GreetEmoteType`, `GreetEmoteDelay`) VALUES +(661, 0, 'Greetings. What business have you with the Carevin family? Do you seek to assist the Carevins in their battle against the undead?', 0, 0), +(1377, 0, 'Driving a Steam Tank isn\'t for everyone. It takes an iron grip and nerves of steel...lucky I have both! How about you? How\'s your mettle? Want to prove it to me?', 0, 0), +(2487, 0, 'Ah, smell the fine salt air! \'Tis always nice to return to our home port of Booty Bay.', 0, 0), +(3050, 0, 'The tauren are sons and daughters of the Earthmother, and we show respect to all her children. Even the beasts we slay are cherished, as their bodies give nourishment and their skins provide warmth.', 0, 0), +(4047, 0, 'The spirits of nature are powers to respect. They offer great aid to the worthy, and mete out swift death to the foolish.', 0, 0), +(5393, 0, 'Nethergarde keep always needs more supplies - supplies to help our mages in their research, and supplies to keep our defenders in top fighting shape.', 1, 0), +(5637, 0, 'Pleased to meetcha, $c. Me name\'s Roetten. I lead Reclaimers Incorporated.$B$BMe guild and I specialize in aquiring lost goods. We usually hire brave adventurers and send them off to finish tasks for those who aren\'t able, or don\'t have the time.', 2, 0), +(6868, 0, 'Whatcha need, $c? I trust that you\'ve come out to this wasteland for a reason other than idle chit chat.', 6, 0), +(8256, 0, 'Greetings, $N.', 1, 0), +(8379, 0, 'If you are here to beg for the privilege of working for me, then your company is quite welcome. Otherwise, there is little chance you are of any use to me.', 0, 0), +(10428, 0, 'Whitereach Post started off as a small hunting camp... Now, everyone wants to set up shop and call this home.$B$B', 1, 0), +(1738, 1, 'This collection of scrolls contains various logistic and strategic information, as well as coded correspondences.', 0, 0), +(138492, 1, 'These shards glint with an unnatural sheen. It is clear that they hide a deep power within.', 0, 0); + +-- Add missing quest greetings from 1.14 sniffs. +INSERT INTO `quest_greeting` (`ID`, `type`, `Greeting`, `GreetEmoteType`, `GreetEmoteDelay`) VALUES +(2277, 0, 'I have a great deal of work to do. Are you here to aid me with my research?', 0, 0), +(5888, 0, 'The earth calls to you, $N. Go to it, and know that your brethren are proud of you and all you will accomplish.', 1, 0), +(6169, 0, 'I\'m on quest. A quest! A quest for new alloys and harder metals for the greatest invention of all!!', 5, 0), +(6946, 0, 'Mathias found me left for dead by the Venture Co. in the Barrens. Had it not been for him, I\'d have been prowler fodder. ', 0, 0), +(7802, 0, 'So few make it this far, even fewer make it past. Do not become a statistic, $N.', 0, 0); + +-- Fix wrong texts compared to 1.13 sniffs. +UPDATE `quest_greeting` SET `Greeting`='Welcome to our humble abode! It\'s always nice to see a friendly face. And what strong arms you have. My husband and I are always looking for help around the farm. Now that most the good folk have left, it\'s hard to find an able body to help out.' WHERE `ID`=235 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='Nothing but trouble in these parts. I tried to tell that fool Saldean to get out while he still could be he won\'t hear of it. But I ain\'t no fool. Verna and I are gonna mosey on out as soon as we get this wagon fixed.' WHERE `ID`=237 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='Sometimes I think there\'s a big gray cloud in the sky, just raining down bad luck upon us. First, we\'re driven off our land, and now we can\'t even get out of Westfall. Everything\'s a mess. Something needs to be done.' WHERE `ID`=238 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='Hey there, friend. My name\'s Remy. I\'m from Redridge to the east, and came here looking for business, looking for business. You got any...got any??' WHERE `ID`=241 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='Aha! Good day, good day, Master $C! Come, sit down and have a drink. You have an enterprising look in your eye, and I think you\'ll find speaking to me worth your time...' WHERE `ID`=253 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='Hello, citizen. You look like a $gman:woman; with a purpose - do you have business with the Stormwind Army?' WHERE `ID`=261 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='At ease, $C. If you are just passing though I suggest you stick to the roads and only travel by day. If your business is here in Darkshire, consider lending your abilities to The Night Watch. Our skill is unquestionable but our numbers are small.' WHERE `ID`=264 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='Hail, $N! Welcome to my humble garden. The weather has been perfect lately. Let us hope it holds steady for a ripe harvest.' WHERE `ID`=342 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='Who is this $c who goes before the Court of Lakshire in the Kingdom of Stormwind? State your business within this township, $R. The orc threat to the Kingdom is far too great to squander time in idle conversation.' WHERE `ID`=344 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='You watch where you step around here, $Gson:lass;. You might not be a part of our outfit, but that doesn\'t mean I won\'t take a cane to you if you fall out of line!' WHERE `ID`=733 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='Greetings, $g lad : girl;. I\'m Grelin Whitebeard. I\'m here to examine the threat posed by the growing numbers of trolls in Coldridge Valley. What have I found? It\'s a bit troubling...' WHERE `ID`=786 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='Hello there, $c. Normally I\'d be out on the beat looking after the folk of Stormwind, but a lot of the Stormwind guards are fighting in other lands. So here I am, deputized and offering bounties when I\'d rather be on patrol...' WHERE `ID`=823 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='If there\'s one thing time has taught me it\'s that no assignment is a dull one. Protecting the Thandol Span should have been an easy task. But with the brunt of the army fighting alongside the alliance, we were overwhelmed here and Dun Modr has fallen.' WHERE `ID`=1071 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='Curse that Brewers\' League! They have access to all the best ingredients, while we\'re stuck here grubbing for grain and hops!$B$BI really would like to give them some bitter tasting justice...' WHERE `ID`=1374 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='Greetings, $C. Be wary as you travel east toward The Bulwark. Recent surveillance reports indicate increased Scourge activity in that area, so exercise caution.' WHERE `ID`=1495 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='Ah, you there! I have tasks to give, and I need not waste time explaining their crucial nature. Listen close.' WHERE `ID`=1499 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='I hope you\'re well, all things considered.$B$BSit for a spell, and hear my tale. It\'s a tragedy, of course, but one I hope will end in revenge!' WHERE `ID`=1500 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='The Scarlet Crusade is encroaching on our homeland. The foolish zealots do not realize that the loyal servants of The Dark Lady shall see to their demise.' WHERE `ID`=1515 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='The Dark Lady has put forth the challenge. It is up to us to meet it.' WHERE `ID`=1518 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='We spent so much of our lives in flight, memories of peaceful times grow evermore distant.' WHERE `ID`=1776 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='My brother and I are on a vital mission, but we are holed up in this farmhouse. The Deathstalkers need your help.' WHERE `ID`=1950 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='I hope you\'re here to work, $C. We have a lot to do and the Horde, the Syndicate and the Ogres aren\'t going to help us.' WHERE `ID`=2263 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='When I was first offered the title of Southshore Magistrate I was elated to have earned such a commission so early in my career.$B$BBut now that I\'m here, I wonder if I\'d have been better off shuffling papers in Stormwind.' WHERE `ID`=2276 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='Hello! The spirits say you here to aid my chief. Say it loud, they do.' WHERE `ID`=2519 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='We at Refuge Pointe hold one of the few remaining patches of Stromgarde territory in the Arathi Highlands. And we\'re losing ground...$B$BIf you have words for me, then I hope they are good tidings.' WHERE `ID`=2700 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='Thanks to the Warchief, even here in the ruins of our former prison, some hope remains, and the Horde rises anew.' WHERE `ID`=2706 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='This wooden board holds roughly-made wanted posters.' WHERE `ID`=2713 && `type`=1; +UPDATE `quest_greeting` SET `Greeting`='You must be hard up to be wandering these Badlands, $c. Hard up like me.$B$BOr maybe you\'re here because you\'re crazy. Crazy, like me.' WHERE `ID`=2817 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='Hey there, $N.$B$BLotwil\'s not the most perceptive boss I\'ve had. He actually gets really involved with his work. So much so that sometimes his servants don\'t eat, or get paid.$B$B$B$BBut that doesn\'t mean you should suffer.' WHERE `ID`=2920 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='Corruption sneaks into nature\'s grove. The forest must be protected at all costs.' WHERE `ID`=2930 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='The land, the water, and the sky are all as one. It is your eyes that deceive you with such separation. The Earthmother is all those things and more.' WHERE `ID`=3338 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='The Barrens holds a wealth of substances for which we, the apothecaries or Lordaeron, may find use.' WHERE `ID`=3390 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='Yes yes yes! You\'re just the $r I\'m looking for!$B$BSit! We have much to discuss!!' WHERE `ID`=3446 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='The spirit of Stonetalon weeps. It weeps from its mountain peaks, to its rivers, to its severed, dying trees.' WHERE `ID`=4049 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='Be careful where you put that foot of yours, $gmister:ma\'am;. We\'re not all blessed with the lofty height of a $r.' WHERE `ID`=4453 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='The centaur clans rule the wastes of Desolace. If united, they would be a terrible force. It is then good that the centaur clans are not united but instead bicker and war amongst themselves.' WHERE `ID`=5412 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='The main threat Thrall wishes dealt with is the Burning Blade--members of the Horde that have given their loyalty to the demons. They seek to practice their dark magic and care little for Thrall\'s vision of the Horde\'s future here in Kalimdor.' WHERE `ID`=5641 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='Dear $g boy:girl;, you have arrived just in time to assist the Kargath Expeditionary Force.\n' WHERE `ID`=9078 && `type`=0; + +-- Fix wrong texts compared to 1.13 sniffs. +UPDATE `quest_greeting` SET `Greeting`='Keep the door closed, $C. Never know when the Dark Riders will be passing through again.' WHERE `ID`=273 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='This had better be good....' WHERE `ID`=3339 && `type`=0; +UPDATE `quest_greeting` SET `Greeting`='If we are to protect nature, then we must embrace its strength. And we must show this strength to those who would harm the land.' WHERE `ID`=5770 && `type`=0; diff --git a/data/sql/updates/db_world/2022_09_19_04.sql b/data/sql/updates/db_world/2022_09_19_04.sql new file mode 100644 index 000000000..fcf6d3e27 --- /dev/null +++ b/data/sql/updates/db_world/2022_09_19_04.sql @@ -0,0 +1,10 @@ +-- DB update 2022_09_19_03 -> 2022_09_19_04 +-- +-- New Gameobject Finds Spuh 01 + Cookpot +SET @OGUID :=7080; +DELETE FROM `gameobject` WHERE `guid` BETWEEN @OGUID+0 AND @OGUID+3; +INSERT INTO `gameobject` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `rotation0`, `rotation1`, `rotation2`, `rotation3`, `spawntimesecs`, `animprogress`, `state`, `VerifiedBuild`) VALUES +(@OGUID+0, 181488, 530, 3524, 3559, 1, 1, -4469.01904296875, -14118.9169921875, 109.05523681640625, 0.253072351217269897, 0, 0, 0.126198768615722656, 0.992004990577697753, 120, 255, 1, 0), -- 181488 (Area: 3559 - Difficulty: 0) +(@OGUID+1, 181984, 530, 3524, 0, 1, 1, -3704.78125, -13588.146484375, 8.325993537902832031, 4.127703666687011718, 0, 0, -0.8808908462524414, 0.473319470882415771, 120, 255, 1, 0), -- 181984 (Area: 0 - Difficulty: 0) +(@OGUID+2, 181495, 530, 3524, 3559, 1, 1, -4389.0087890625, -13960.84765625, 162.2950897216796875, 4.441864967346191406, -0.02709054946899414, 0.006800651550292968, -0.79592132568359375, 0.604755401611328125, 120, 255, 1, 0), -- 181495 (Area: 3559 - Difficulty: 0) +(@OGUID+3, 181489, 530, 3524, 3559, 1, 1, -4505.4619140625, -14097.103515625, 108.829376220703125, 4.860743999481201171, 0.001828670501708984, -0.02460956573486328, -0.6523294448852539, 0.757533729076385498, 120, 255, 1, 0); diff --git a/data/sql/updates/db_world/2022_09_19_05.sql b/data/sql/updates/db_world/2022_09_19_05.sql new file mode 100644 index 000000000..5dc7cf7dc --- /dev/null +++ b/data/sql/updates/db_world/2022_09_19_05.sql @@ -0,0 +1,3 @@ +-- DB update 2022_09_19_04 -> 2022_09_19_05 +-- +UPDATE `creature_template` SET `flags_extra`=`flags_extra`|0x02000000 WHERE `entry`=13996; diff --git a/data/sql/updates/db_world/2022_09_19_06.sql b/data/sql/updates/db_world/2022_09_19_06.sql new file mode 100644 index 000000000..f2ad27677 --- /dev/null +++ b/data/sql/updates/db_world/2022_09_19_06.sql @@ -0,0 +1,3 @@ +-- DB update 2022_09_19_05 -> 2022_09_19_06 +-- +UPDATE `creature_formations` SET `GroupAI`=515 WHERE `leaderGUID`=14514 AND `memberGUID` IN (14515, 14516, 14517); diff --git a/data/sql/updates/db_world/2022_09_19_07.sql b/data/sql/updates/db_world/2022_09_19_07.sql new file mode 100644 index 000000000..f1580dde2 --- /dev/null +++ b/data/sql/updates/db_world/2022_09_19_07.sql @@ -0,0 +1,8 @@ +-- DB update 2022_09_19_06 -> 2022_09_19_07 +-- +DELETE FROM `spell_script_names` WHERE `spell_id` IN (-44543,74396); +INSERT INTO `spell_script_names` VALUES +(-44543, 'spell_mage_fingers_of_frost_proc_aura'), +(74396, 'spell_mage_fingers_of_frost_proc'); + +UPDATE `spell_proc_event` SET `procPhase`=7 WHERE `entry` IN (44543,44545); diff --git a/data/sql/updates/db_world/2022_09_19_08.sql b/data/sql/updates/db_world/2022_09_19_08.sql new file mode 100644 index 000000000..a9bc11ea1 --- /dev/null +++ b/data/sql/updates/db_world/2022_09_19_08.sql @@ -0,0 +1,3 @@ +-- DB update 2022_09_19_07 -> 2022_09_19_08 +-- +UPDATE `spell_proc_event` SET `procPhase`=0 WHERE `entry`=74396; diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index 58f1f33a4..69da11bac 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -4059,6 +4059,13 @@ void SmartScript::UpdateTimer(SmartScriptHolder& e, uint32 const diff) } } + // Delay flee for assist event if casting + if (e.GetActionType() == SMART_ACTION_FLEE_FOR_ASSIST && me && me->HasUnitState(UNIT_STATE_CASTING)) + { + e.timer = 1; + return; + } + e.active = true;//activate events with cooldown switch (e.GetEventType())//process ONLY timed events { diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp index 0812b4f93..0487d6b65 100644 --- a/src/server/game/Entities/GameObject/GameObject.cpp +++ b/src/server/game/Entities/GameObject/GameObject.cpp @@ -1745,11 +1745,13 @@ void GameObject::Use(Unit* user) LOG_DEBUG("entities.gameobject", "Fishing check (skill: {} zone min skill: {} chance {} roll: {}", skill, zone_skill, chance, roll); + if (sScriptMgr->OnUpdateFishingSkill(player, skill, zone_skill, chance, roll)) + { + player->UpdateFishingSkill(); + } // but you will likely cause junk in areas that require a high fishing skill (not yet implemented) if (chance >= roll) { - player->UpdateFishingSkill(); - //TODO: I do not understand this hack. Need some explanation. // prevent removing GO at spell cancel RemoveFromOwner(); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 4f942536d..214416188 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -169,6 +169,7 @@ ProcEventInfo::ProcEventInfo(Unit* actor, Unit* actionTarget, Unit* procTarget, : _actor(actor), _actionTarget(actionTarget), _procTarget(procTarget), _typeMask(typeMask), _spellTypeMask(spellTypeMask), _spellPhaseMask(spellPhaseMask), _hitMask(hitMask), _spell(spell), _damageInfo(damageInfo), _healInfo(healInfo), _triggeredByAuraSpell(triggeredByAuraSpell), _procAuraEffectIndex(procAuraEffectIndex) { + _chance.reset(); } SpellInfo const* ProcEventInfo::GetSpellInfo() const @@ -15869,18 +15870,29 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u if (!active && !isVictim && !(procFlag & PROC_FLAG_DONE_PERIODIC) && procSpellInfo && procSpellInfo->SpellFamilyName && (procSpellInfo->HasAura(SPELL_AURA_PERIODIC_DAMAGE) || procSpellInfo->HasAura(SPELL_AURA_PERIODIC_HEAL))) active = true; - if (!IsTriggeredAtSpellProcEvent(target, triggerData.aura, attType, isVictim, active, triggerData.spellProcEvent, eventInfo)) + // AuraScript Hook + if (!triggerData.aura->CallScriptCheckProcHandlers(itr->second, eventInfo)) + { continue; + } + + bool isTriggeredAtSpellProcEvent = IsTriggeredAtSpellProcEvent(target, triggerData.aura, attType, isVictim, active, triggerData.spellProcEvent, eventInfo); + + // AuraScript Hook + triggerData.aura->CallScriptCheckAfterProcHandlers(itr->second, eventInfo); + + if (!isTriggeredAtSpellProcEvent) + { + continue; + } // do checks using conditions table ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_PROC, spellProto->Id); ConditionSourceInfo condInfo = ConditionSourceInfo(eventInfo.GetActor(), eventInfo.GetActionTarget()); if (!sConditionMgr->IsObjectMeetToConditions(condInfo, conditions)) + { continue; - - // AuraScript Hook - if (!triggerData.aura->CallScriptCheckProcHandlers(itr->second, eventInfo)) - continue; + } // Triggered spells not triggering additional spells //bool triggered = !spellProto->HasAttribute(SPELL_ATTR3_CAN_PROC_FROM_PROCS) ? @@ -17181,11 +17193,17 @@ bool Unit::IsTriggeredAtSpellProcEvent(Unit* victim, Aura* aura, WeaponAttackTyp } } + if (eventInfo.GetProcChance()) + { + chance = *eventInfo.GetProcChance(); + } + // Apply chance modifer aura if (Player* modOwner = GetSpellModOwner()) { modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_CHANCE_OF_SUCCESS, chance); } + return roll_chance_f(chance); } diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index d0513d750..e2c255e90 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -25,6 +25,7 @@ #include "HostileRefMgr.h" #include "MotionMaster.h" #include "Object.h" +#include "Optional.h" #include "SpellAuraDefines.h" #include "SpellDefines.h" #include "ThreatMgr.h" @@ -836,6 +837,7 @@ private: HealInfo* _healInfo; SpellInfo const* const _triggeredByAuraSpell; int8 _procAuraEffectIndex; + std::optional _chance; public: explicit ProcEventInfo(Unit* actor, Unit* actionTarget, Unit* procTarget, uint32 typeMask, uint32 spellTypeMask, uint32 spellPhaseMask, uint32 hitMask, Spell const* spell, DamageInfo* damageInfo, HealInfo* healInfo, SpellInfo const* triggeredByAuraSpell = nullptr, int8 procAuraEffectIndex = -1); @@ -855,6 +857,9 @@ public: [[nodiscard]] int8 GetTriggerAuraEffectIndex() const { return _procAuraEffectIndex; } [[nodiscard]] uint32 GetProcCooldown() const { return _cooldown; } void SetProcCooldown(uint32 cooldown) { _cooldown = cooldown; } + [[nodiscard]] std::optional GetProcChance() const { return _chance; } + void SetProcChance(float chance) { _chance = chance; } + void ResetProcChance() { _chance.reset(); } }; // Struct for use in Unit::CalculateMeleeDamage diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index f0c6c053c..da1a6daf4 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -422,6 +422,11 @@ void WorldSession::HandleCharCreateOpcode(WorldPacket& recvData) std::function finalizeCharacterCreation = [this, createInfo](PreparedQueryResult result) { + if (!sScriptMgr->CanAccountCreateCharacter(createInfo, GetAccountId())) + { + SendCharCreate(CHAR_CREATE_DISABLED); + return; + } bool haveSameRace = false; uint32 heroicReqLevel = sWorld->getIntConfig(CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_HEROIC_CHARACTER); bool hasHeroicReqLevel = (heroicReqLevel == 0); diff --git a/src/server/game/Mails/Mail.cpp b/src/server/game/Mails/Mail.cpp index a91107568..e33755a53 100644 --- a/src/server/game/Mails/Mail.cpp +++ b/src/server/game/Mails/Mail.cpp @@ -153,13 +153,7 @@ void MailDraft::SendReturnToSender(uint32 /*sender_acc*/, ObjectGuid::LowType se { Player* receiver = ObjectAccessor::FindPlayerByLowGUID(receiver_guid); - uint32 rc_account = 0; - if (!receiver) - { - rc_account = sCharacterCache->GetCharacterAccountIdByGuid(ObjectGuid(HighGuid::Player, receiver_guid)); - } - - if (!receiver && !rc_account) // sender not exist + if (!receiver && !sCharacterCache->GetCharacterAccountIdByGuid(ObjectGuid(HighGuid::Player, receiver_guid))) { deleteIncludedItems(trans, true); return; @@ -200,7 +194,6 @@ void MailDraft::SendMailTo(CharacterDatabaseTransaction trans, MailReceiver cons return; Player* pReceiver = receiver.GetPlayer(); // can be nullptr - Player* pSender = ObjectAccessor::FindPlayerByLowGUID(sender.GetSenderId()); if (pReceiver) prepareItems(pReceiver, trans); // generate mail template items @@ -219,14 +212,14 @@ void MailDraft::SendMailTo(CharacterDatabaseTransaction trans, MailReceiver cons else if (sender.GetMailMessageType() == MAIL_CREATURE && sBattlegroundMgr->GetBattleMasterBG(sender.GetSenderId()) != BATTLEGROUND_TYPE_NONE) expire_delay = DAY; // default case: expire time if COD 3 days, if no COD 30 days (or 90 days if sender is a game master) + else if (m_COD) + expire_delay = 3 * DAY; + else if (custom_expiration > 0) + expire_delay = custom_expiration * DAY; else { - if (m_COD) - expire_delay = 3 * DAY; - else if (custom_expiration > 0 ) - expire_delay = custom_expiration * DAY; - else - expire_delay = pSender && pSender->GetSession()->GetSecurity() ? 90 * DAY : 30 * DAY; + Player* pSender = ObjectAccessor::FindPlayerByLowGUID(sender.GetSenderId()); + expire_delay = pSender && pSender->GetSession()->GetSecurity() ? 90 * DAY : 30 * DAY; } time_t expire_time = deliver_time + expire_delay; @@ -235,27 +228,26 @@ void MailDraft::SendMailTo(CharacterDatabaseTransaction trans, MailReceiver cons uint8 index = 0; CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_MAIL); stmt->SetData( index, mailId); - stmt->SetData (++index, uint8(sender.GetMailMessageType())); - stmt->SetData (++index, int8(sender.GetStationery())); + stmt->SetData(++index, uint8(sender.GetMailMessageType())); + stmt->SetData(++index, int8(sender.GetStationery())); stmt->SetData(++index, GetMailTemplateId()); stmt->SetData(++index, sender.GetSenderId()); stmt->SetData(++index, receiver.GetPlayerGUIDLow()); stmt->SetData(++index, GetSubject()); stmt->SetData(++index, GetBody()); - stmt->SetData (++index, !m_items.empty()); + stmt->SetData(++index, !m_items.empty()); stmt->SetData(++index, uint32(expire_time)); stmt->SetData(++index, uint32(deliver_time)); stmt->SetData(++index, m_money); stmt->SetData(++index, m_COD); - stmt->SetData (++index, uint8(checked)); + stmt->SetData(++index, uint8(checked)); trans->Append(stmt); for (MailItemMap::const_iterator mailItemIter = m_items.begin(); mailItemIter != m_items.end(); ++mailItemIter) { - Item* pItem = mailItemIter->second; stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_MAIL_ITEM); stmt->SetData(0, mailId); - stmt->SetData(1, pItem->GetGUID().GetCounter()); + stmt->SetData(1, mailItemIter->second->GetGUID().GetCounter()); stmt->SetData(2, receiver.GetPlayerGUIDLow()); trans->Append(stmt); } @@ -302,7 +294,6 @@ void MailDraft::SendMailTo(CharacterDatabaseTransaction trans, MailReceiver cons } else if (!m_items.empty()) { - CharacterDatabaseTransaction temp = CharacterDatabaseTransaction(nullptr); - deleteIncludedItems(temp); + deleteIncludedItems(CharacterDatabaseTransaction(nullptr)); } } diff --git a/src/server/game/Scripting/ScriptDefines/AccountScript.cpp b/src/server/game/Scripting/ScriptDefines/AccountScript.cpp index 99ac4c799..4368e87d0 100644 --- a/src/server/game/Scripting/ScriptDefines/AccountScript.cpp +++ b/src/server/game/Scripting/ScriptDefines/AccountScript.cpp @@ -81,3 +81,18 @@ void ScriptMgr::OnFailedPasswordChange(uint32 accountId) script->OnFailedPasswordChange(accountId); }); } + +bool ScriptMgr::CanAccountCreateCharacter(std::shared_ptr createInfo, uint32 accountId) +{ + auto ret = IsValidBoolScript([&](AccountScript* script) + { + return !script->CanAccountCreateCharacter(createInfo, accountId); + }); + + if (ret && *ret) + { + return false; + } + + return true; +} diff --git a/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp b/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp index 7f28a50a2..9ab221850 100644 --- a/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp +++ b/src/server/game/Scripting/ScriptDefines/PlayerScript.cpp @@ -936,6 +936,21 @@ void ScriptMgr::OnGetMaxSkillValue(Player* player, uint32 skill, int32& result, }); } +bool ScriptMgr::OnUpdateFishingSkill(Player* player, int32 skill, int32 zone_skill, int32 chance, int32 roll) +{ + auto ret = IsValidBoolScript([&](PlayerScript* script) + { + return !script->OnUpdateFishingSkill(player, skill, zone_skill, chance, roll); + }); + + if (ret && *ret) + { + return false; + } + + return true; +} + bool ScriptMgr::CanAreaExploreAndOutdoor(Player* player) { auto ret = IsValidBoolScript([&](PlayerScript* script) diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index a9a77a354..a28145782 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -73,6 +73,7 @@ class Vehicle; class WorldObject; class WorldPacket; class WorldSocket; +class CharacterCreateInfo; struct AchievementCriteriaData; struct AuctionEntry; @@ -1251,6 +1252,8 @@ public: virtual void OnGetMaxSkillValue(Player* /*player*/, uint32 /*skill*/, int32& /*result*/, bool /*IsPure*/) { } + [[nodiscard]] virtual bool OnUpdateFishingSkill(Player* /*player*/, int32 /*skill*/, int32 /*zone_skill*/, int32 /*chance*/, int32 /*roll*/) { return true; } + [[nodiscard]] virtual bool CanAreaExploreAndOutdoor(Player* /*player*/) { return true; } virtual void OnVictimRewardBefore(Player* /*player*/, Player* /*victim*/, uint32& /*killer_title*/, uint32& /*victim_title*/) { } @@ -1458,6 +1461,9 @@ public: // Called when Password failed to change for Account virtual void OnFailedPasswordChange(uint32 /*accountId*/) { } + + // Called when creating a character on the Account + [[nodiscard]] virtual bool CanAccountCreateCharacter(std::shared_ptr /*createInfo*/, uint32 /*accountId*/) { return true;} }; class GuildScript : public ScriptObject @@ -2330,6 +2336,7 @@ public: /* PlayerScript */ void OnDeleteFromDB(CharacterDatabaseTransaction trans, uint32 guid); bool CanRepopAtGraveyard(Player* player); void OnGetMaxSkillValue(Player* player, uint32 skill, int32& result, bool IsPure); + bool OnUpdateFishingSkill(Player* player, int32 skill, int32 zone_skill, int32 chance, int32 roll); bool CanAreaExploreAndOutdoor(Player* player); void OnVictimRewardBefore(Player* player, Player* victim, uint32& killer_title, uint32& victim_title); void OnVictimRewardAfter(Player* player, Player* victim, uint32& killer_title, uint32& victim_rank, float& honor_f); @@ -2394,6 +2401,7 @@ public: /* AccountScript */ void OnFailedEmailChange(uint32 accountId); void OnPasswordChange(uint32 accountId); void OnFailedPasswordChange(uint32 accountId); + bool CanAccountCreateCharacter(std::shared_ptr createInfo, uint32 accountId); public: /* GuildScript */ void OnGuildAddMember(Guild* guild, Player* player, uint8& plRank); diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index 0a9e80332..17cce5aa3 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -1450,6 +1450,26 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b else target->AddAura(74396, target); } + break; + case 12494: // Frostbite, synchronise with Fingers of Frost + { + // Find Fingers of Frost + if (AuraEffect* aurEff = caster->GetAuraEffect(SPELL_AURA_PROC_TRIGGER_SPELL, SPELLFAMILY_MAGE, 2947, EFFECT_0)) + { + if (SpellInfo const* triggeringSpellInfo = GetTriggeredByAuraSpellInfo()) + { + uint8 fbRank = sSpellMgr->GetSpellRank(triggeringSpellInfo->Id); + uint8 fofRank = sSpellMgr->GetSpellRank(aurEff->GetId()); + uint8 chance = uint8(std::ceil(fofRank * fbRank * 16.6f)); + + if (roll_chance_i(chance)) + { + caster->CastSpell(caster, aurEff->GetSpellInfo()->Effects[EFFECT_0].TriggerSpell, true); + } + } + } + break; + } default: break; } @@ -2620,6 +2640,22 @@ bool Aura::CallScriptCheckProcHandlers(AuraApplication const* aurApp, ProcEventI return result; } +bool Aura::CallScriptCheckAfterProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo) +{ + bool result = true; + for (std::list::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr) + { + (*scritr)->_PrepareScriptCall(AURA_SCRIPT_HOOK_CHECK_AFTER_PROC, aurApp); + std::list::iterator hookItrEnd = (*scritr)->DoCheckAfterProc.end(), hookItr = (*scritr)->DoCheckAfterProc.begin(); + for (; hookItr != hookItrEnd; ++hookItr) + result &= hookItr->Call(*scritr, eventInfo); + + (*scritr)->_FinishScriptCall(); + } + + return result; +} + bool Aura::CallScriptPrepareProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo) { bool prepare = true; diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h index 4600a4242..d98f391dc 100644 --- a/src/server/game/Spells/Auras/SpellAuras.h +++ b/src/server/game/Spells/Auras/SpellAuras.h @@ -226,6 +226,7 @@ public: // Spell Proc Hooks bool CallScriptCheckProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo); + bool CallScriptCheckAfterProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo); bool CallScriptPrepareProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo); bool CallScriptProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo); void CallScriptAfterProcHandlers(AuraApplication const* aurApp, ProcEventInfo& eventInfo); diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 18a8c30ec..a2eaf13e7 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -3278,12 +3278,14 @@ void Spell::DoTriggersOnSpellHit(Unit* unit, uint8 effMask) } else { - m_caster->CastCustomSpell(i->triggeredSpell->Id, SPELLVALUE_AURA_DURATION, _duration, unit, true); + AuraEffect const* triggeringAuraEffect = m_caster->GetAuraEffect(i->triggeredByAura->Id, i->triggeredByEffIdx); + m_caster->CastCustomSpell(i->triggeredSpell->Id, SPELLVALUE_AURA_DURATION, _duration, unit, true, nullptr, triggeringAuraEffect); } } else { - m_caster->CastSpell(unit, i->triggeredSpell, true); + AuraEffect const* triggeringAuraEffect = m_caster->GetAuraEffect(i->triggeredByAura->Id, i->triggeredByEffIdx); + m_caster->CastSpell(unit, i->triggeredSpell, true, nullptr, triggeringAuraEffect); } } } @@ -8766,6 +8768,7 @@ void Spell::PrepareTriggersExecutedOnHit() HitTriggerSpell spellTriggerInfo; spellTriggerInfo.triggeredSpell = spellInfo; spellTriggerInfo.triggeredByAura = auraSpellInfo; + spellTriggerInfo.triggeredByEffIdx = (*i)->GetEffIndex(); spellTriggerInfo.chance = chance * (*i)->GetBase()->GetStackAmount(); m_hitTriggerSpells.push_back(spellTriggerInfo); } diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index d9a564871..f6e3e646f 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -741,7 +741,7 @@ public: { SpellInfo const* triggeredSpell; SpellInfo const* triggeredByAura; - // uint8 triggeredByEffIdx This might be needed at a later stage - No need known for now + uint8 triggeredByEffIdx; int32 chance; }; diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp index aa354377a..4842cede7 100644 --- a/src/server/game/Spells/SpellScript.cpp +++ b/src/server/game/Spells/SpellScript.cpp @@ -733,6 +733,10 @@ bool AuraScript::_Validate(SpellInfo const* entry) if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect()) LOG_ERROR("spells.scripts", "Spell `{}` of script `{}` does not have apply aura effect - handler bound to hook `DoCheckProc` of AuraScript won't be executed", entry->Id, m_scriptName->c_str()); + for (std::list::iterator itr = DoCheckAfterProc.begin(); itr != DoCheckAfterProc.end(); ++itr) + if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect()) + LOG_ERROR("spells.scripts", "Spell `{}` of script `{}` does not have apply aura effect - handler bound to hook `DoCheckAfterProc` of AuraScript won't be executed", entry->Id, m_scriptName->c_str()); + for (std::list::iterator itr = DoPrepareProc.begin(); itr != DoPrepareProc.end(); ++itr) if (!entry->HasEffect(SPELL_EFFECT_APPLY_AURA) && !entry->HasAreaAuraEffect()) LOG_ERROR("spells.scripts", "Spell `{}` of script `{}` does not have apply aura effect - handler bound to hook `DoPrepareProc` of AuraScript won't be executed", entry->Id, m_scriptName->c_str()); @@ -1163,6 +1167,7 @@ Unit* AuraScript::GetTarget() const case AURA_SCRIPT_HOOK_EFFECT_AFTER_MANASHIELD: case AURA_SCRIPT_HOOK_EFFECT_SPLIT: case AURA_SCRIPT_HOOK_CHECK_PROC: + case AURA_SCRIPT_HOOK_CHECK_AFTER_PROC: case AURA_SCRIPT_HOOK_PREPARE_PROC: case AURA_SCRIPT_HOOK_PROC: case AURA_SCRIPT_HOOK_AFTER_PROC: diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h index 138dafeeb..b52d2215b 100644 --- a/src/server/game/Spells/SpellScript.h +++ b/src/server/game/Spells/SpellScript.h @@ -499,6 +499,7 @@ enum AuraScriptHookType AURA_SCRIPT_HOOK_AFTER_DISPEL, // Spell Proc Hooks AURA_SCRIPT_HOOK_CHECK_PROC, + AURA_SCRIPT_HOOK_CHECK_AFTER_PROC, AURA_SCRIPT_HOOK_PREPARE_PROC, AURA_SCRIPT_HOOK_PROC, AURA_SCRIPT_HOOK_EFFECT_PROC, @@ -804,6 +805,10 @@ public: // example: DoCheckProc += AuraCheckProcFn(class::function); // where function is: bool function (ProcEventInfo& eventInfo); HookList DoCheckProc; + // executed when aura checks if it can proc + // example: DoCheckAfterProc += AuraCheckProcFn(class::function); + // where function is: bool function (ProcEventInfo& eventInfo); + HookList DoCheckAfterProc; #define AuraCheckProcFn(F) CheckProcHandlerFunction(&F) // executed before aura procs (possibility to prevent charge drop/cooldown) diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/blackrock_spire.h b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/blackrock_spire.h index dbe855aea..557b13220 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/blackrock_spire.h +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/blackrock_spire.h @@ -76,6 +76,8 @@ enum CreaturesIds NPC_BLACKHAND_INCARCERATOR = 10316, NPC_LORD_VICTOR_NEFARIUS = 10162, + NPC_SCARSHIELD_INFILTRATOR = 10299, + NPC_SOLAKAR = 10264, NPC_ROOKERY_GUARDIAN = 10258, NPC_ROOKERY_HATCHER = 10683, @@ -95,7 +97,8 @@ enum AdditionalData AREATRIGGER = 1, AREATRIGGER_DRAGONSPIRE_HALL = 2046, AREATRIGGER_BLACKROCK_STADIUM = 2026, - SAY_FINKLE_GANG = 0 + SAY_FINKLE_GANG = 0, + ITEM_UNADORNED_SEAL = 12219 }; enum GameObjectsIds diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp index 8bd9dadcd..bf0c740fa 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockSpire/instance_blackrock_spire.cpp @@ -53,7 +53,8 @@ Position SolakarPosBoss = Position(80.0f, -280.0f, 93.0f, 3.0f * M_PI / 2.0); enum Texts { SAY_NEFARIUS_REND_WIPE = 11, - SAY_SOLAKAR_FIRST_HATCHER = 0 + SAY_SOLAKAR_FIRST_HATCHER = 0, + SAY_SCARSHIELD_INF_WHISPER = 0 }; MinionData const minionData[] = @@ -823,10 +824,65 @@ public: } }; +class near_scarshield_infiltrator : public AreaTriggerScript +{ +public: + near_scarshield_infiltrator() : AreaTriggerScript("near_scarshield_infiltrator") { } + + bool OnTrigger(Player* player, const AreaTrigger* /*at*/) override + { + if (player && player->IsAlive()) + { + if (Creature* creature = player->FindNearestCreature(NPC_SCARSHIELD_INFILTRATOR, 100.0f, true)) + { + bool transformHasStarted = creature->AI()->GetData(0) == 1; + if ((player->getLevel() < 57 || !player->HasItemCount(ITEM_UNADORNED_SEAL)) && !transformHasStarted) + { + // Send whisper if not already sent + std::list::iterator itr = std::find(whisperedTargets.begin(), whisperedTargets.end(), player->GetGUID()); + if (itr == whisperedTargets.end()) + { + creature->AI()->Talk(SAY_SCARSHIELD_INF_WHISPER, player); + whisperedTargets.push_back(player->GetGUID()); + return true; + } + } + } + } + return false; + } + private: + GuidList whisperedTargets; +}; + +class at_scarshield_infiltrator : public AreaTriggerScript +{ +public: + at_scarshield_infiltrator() : AreaTriggerScript("at_scarshield_infiltrator") { } + + bool OnTrigger(Player* player, const AreaTrigger* /*at*/) override + { + if (player && player->IsAlive()) + { + if (Creature* creature = player->FindNearestCreature(NPC_SCARSHIELD_INFILTRATOR, 100.0f, true)) + { + if (player->getLevel() >= 57 && player->HasItemCount(ITEM_UNADORNED_SEAL)) + { + creature->AI()->SetData(0, 1); // Start transform into Vaelan + return true; + } + } + } + return false; + } +}; + void AddSC_instance_blackrock_spire() { new instance_blackrock_spire(); new at_dragonspire_hall(); new at_blackrock_stadium(); new go_father_flame(); + new near_scarshield_infiltrator(); + new at_scarshield_infiltrator(); } diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp index 0e1c3c4f1..27fafe6d5 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp @@ -89,6 +89,7 @@ struct boss_ayamiss : public BossAI _enraged = false; SetCombatMovement(false); _scheduler.CancelAll(); + me->SetReactState(REACT_AGGRESSIVE); } void JustSummoned(Creature* who) override @@ -120,6 +121,7 @@ struct boss_ayamiss : public BossAI me->m_Events.AddEventAtOffset([this]() { + me->SetReactState(REACT_AGGRESSIVE); if (me->GetVictim()) { me->GetMotionMaster()->MoveChase(me->GetVictim()); @@ -157,7 +159,7 @@ struct boss_ayamiss : public BossAI } context.Repeat(RAND(2400ms, 3600ms)); - }).Schedule(15s, [this](TaskContext context) { + }).Schedule(15s, 28s, [this](TaskContext context) { if (Unit* target = SelectTarget(SelectTargetMethod::Random, 0, 0, true)) { DoCast(target, SPELL_PARALYZE, true); @@ -215,6 +217,7 @@ struct boss_ayamiss : public BossAI { _phase = PHASE_GROUND; me->ClearUnitState(UNIT_STATE_ROOT); + me->SetReactState(REACT_PASSIVE); me->SetCanFly(false); me->SetDisableGravity(false); me->GetMotionMaster()->MovePath(me->GetEntry() * 10, false); diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp index 2b2866550..b59655524 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp @@ -134,8 +134,6 @@ struct boss_skeram : public BossAI { _JustDied(); Talk(SAY_DEATH); - - instance->HandleGameObject(instance->GetGuidData(AQ40_DOOR_3), true); } else me->RemoveCorpse(); diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/instance_temple_of_ahnqiraj.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/instance_temple_of_ahnqiraj.cpp index 773e8afb3..bf68a1a76 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/instance_temple_of_ahnqiraj.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/instance_temple_of_ahnqiraj.cpp @@ -31,6 +31,14 @@ ObjectData const creatureData[] = { NPC_VEKNILASH, DATA_VEKNILASH } }; +DoorData const doorData[] = +{ + { AQ40_DOOR_SKERAM, DATA_SKERAM, DOOR_TYPE_PASSAGE }, + { AQ40_DOOR_TE_ENTRANCE, DATA_TWIN_EMPERORS, DOOR_TYPE_ROOM }, + { AQ40_DOOR_TE_EXIT, DATA_TWIN_EMPERORS, DOOR_TYPE_PASSAGE }, + { 0, 0, DOOR_TYPE_ROOM} +}; + class instance_temple_of_ahnqiraj : public InstanceMapScript { public: @@ -45,9 +53,9 @@ public: { instance_temple_of_ahnqiraj_InstanceMapScript(Map* map) : InstanceScript(map) { - LoadObjectData(creatureData, nullptr); - doorGUIDs.fill(ObjectGuid::Empty); SetBossNumber(MAX_BOSS_NUMBER); + LoadObjectData(creatureData, nullptr); + LoadDoorData(doorData); } ObjectGuid SkeramGUID; @@ -57,7 +65,6 @@ public: ObjectGuid ViscidusGUID; ObjectGuid CThunGUID; GuidVector CThunGraspGUIDs; - std::array doorGUIDs; uint32 BugTrioDeathCount; uint32 CthunPhase; @@ -74,10 +81,6 @@ public: { case NPC_SKERAM: SkeramGUID = creature->GetGUID(); - if (!creature->IsAlive()) - { - HandleGameObject(doorGUIDs[2], true); - } break; case NPC_VEM: VemGUID = creature->GetGUID(); @@ -123,29 +126,6 @@ public: { switch (go->GetEntry()) { - case AQ40_DOOR_1: - doorGUIDs[0] = go->GetGUID(); - break; - case AQ40_DOOR_2: - doorGUIDs[1] = go->GetGUID(); - if (Creature* veklor = GetCreature(DATA_VEKLOR)) - { - if (!veklor->IsAlive()) - { - HandleGameObject(go->GetGUID(), true); - } - } - break; - case AQ40_DOOR_3: - doorGUIDs[2] = go->GetGUID(); - if (Creature* skeram = instance->GetCreature(SkeramGUID)) - { - if (!skeram->IsAlive()) - { - HandleGameObject(go->GetGUID(), true); - } - } - break; case GO_CTHUN_GRASP: CThunGraspGUIDs.push_back(go->GetGUID()); if (Creature* CThun = instance->GetCreature(CThunGUID)) @@ -190,12 +170,6 @@ public: return YaujGUID; case DATA_VISCIDUS: return ViscidusGUID; - case AQ40_DOOR_1: - return doorGUIDs[0]; - case AQ40_DOOR_2: - return doorGUIDs[1]; - case AQ40_DOOR_3: - return doorGUIDs[2]; } return ObjectGuid::Empty; } diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.cpp index e604bd9de..e63309b9f 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.cpp @@ -36,25 +36,30 @@ enum Spells SPELL_EXPLODE = 25699, SPELL_SUMMON_WARRIOR = 17431, SPELL_SUMMON_SWARMGUARD = 17430, - - SPELL_FEAR = 26070, - SPELL_ENTAGLING_ROOTS = 26071, - SPELL_SILENCE = 26069, - SPELL_DUST_CLOUD = 26072, - SPELL_FIRE_NOVA = 26073, - SPELL_SUMMON_LARGE_OBSIDIAN_CHUNK = 27630, // Server-side - SPELL_SHOCK_BLAST = 26458, - SPELL_DRAIN_MANA = 25671, - SPELL_DRAIN_MANA_VISUAL = 26639, - TALK_ENRAGE = 0, // Vekniss Stinger SPELL_VEKNISS_CATALYST = 26078, SPELL_STINGER_CHARGE_NORMAL = 26081, SPELL_STINGER_CHARGE_BUFFED = 26082, + + // Obsidian Eradicator + SPELL_SHOCK_BLAST = 26458, + SPELL_DRAIN_MANA = 25671, + SPELL_DRAIN_MANA_VISUAL = 26639, + + // Anubisath Warder + SPELL_FEAR = 26070, + SPELL_ENTAGLING_ROOTS = 26071, + SPELL_SILENCE = 26069, + SPELL_DUST_CLOUD = 26072, + SPELL_FIRE_NOVA = 26073, + + // Obsidian Nullifier + SPELL_NULLIFY = 26552, + SPELL_CLEAVE = 40504 }; struct npc_anubisath_defender : public ScriptedAI @@ -220,38 +225,6 @@ private: TaskScheduler _scheduler; }; -enum NPCs -{ - NPC_VEKNISS_DRONE = 15300 -}; - -class spell_aggro_drones : public SpellScript -{ - PrepareSpellScript(spell_aggro_drones); - - void HandleDummy(SpellEffIndex /*effIndex*/) - { - if (Unit* caster = GetCaster()) - { - if (Creature* target = GetHitCreature()) - { - if (target->GetEntry() == NPC_VEKNISS_DRONE) - { - if (Unit* victim = caster->GetVictim()) - { - target->AI()->AttackStart(victim); - } - } - } - } - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_aggro_drones::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); - } -}; - struct npc_obsidian_eradicator : public ScriptedAI { npc_obsidian_eradicator(Creature* creature) : ScriptedAI(creature) @@ -316,27 +289,6 @@ private: std::list _targets; }; -class spell_drain_mana : public SpellScript -{ - PrepareSpellScript(spell_drain_mana); - - void HandleScript(SpellEffIndex /*effIndex*/) - { - if (Unit* caster = GetCaster()) - { - if (Unit* target = GetHitUnit()) - { - target->CastSpell(caster, SPELL_DRAIN_MANA_VISUAL, true); - } - } - } - - void Register() override - { - OnEffectHitTarget += SpellEffectFn(spell_drain_mana::HandleScript, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT); - } -}; - struct npc_anubisath_warder : public ScriptedAI { npc_anubisath_warder(Creature* creature) : ScriptedAI(creature) @@ -406,12 +358,132 @@ private: TaskScheduler _scheduler; }; +struct npc_obsidian_nullifier : public ScriptedAI +{ + npc_obsidian_nullifier(Creature* creature) : ScriptedAI(creature) + { + } + + void Reset() override + { + _scheduler.CancelAll(); + me->SetPower(POWER_MANA, 0); + _targets.clear(); + } + + void EnterCombat(Unit* /*who*/) override + { + _scheduler.Schedule(6s, [this](TaskContext context) + { + if (_targets.empty()) + { + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* player = itr->GetSource()) + { + if (player->IsAlive() && !player->IsGameMaster() && !player->IsSpectator() && player->GetPower(POWER_MANA) > 0) + { + _targets.push_back(player); + } + } + } + + Acore::Containers::RandomResize(_targets, 11); + } + + for (Unit* target : _targets) + { + DoCast(target, SPELL_DRAIN_MANA, true); + } + + if (me->GetPowerPct(POWER_MANA) >= 100.f) + { + DoCastAOE(SPELL_NULLIFY, true); + } + + context.Repeat(6s); + }) + .Schedule(6000ms, 8400ms, [this](TaskContext context) + { + DoCastVictim(SPELL_CLEAVE, true); + context.Repeat(6000ms, 8400ms); + }); + } + + void UpdateAI(uint32 diff) override + { + if (!UpdateVictim()) + { + return; + } + + _scheduler.Update(diff, + std::bind(&ScriptedAI::DoMeleeAttackIfReady, this)); + } + +private: + TaskScheduler _scheduler; + std::list _targets; +}; + +enum NPCs +{ + NPC_VEKNISS_DRONE = 15300 +}; + +class spell_aggro_drones : public SpellScript +{ + PrepareSpellScript(spell_aggro_drones); + + void HandleDummy(SpellEffIndex /*effIndex*/) + { + if (Unit* caster = GetCaster()) + { + if (Creature* target = GetHitCreature()) + { + if (target->GetEntry() == NPC_VEKNISS_DRONE) + { + if (Unit* victim = caster->GetVictim()) + { + target->AI()->AttackStart(victim); + } + } + } + } + } + + void Register() override + { + OnEffectHitTarget += SpellEffectFn(spell_aggro_drones::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY); + } +}; + +class spell_nullify : public AuraScript +{ + PrepareAuraScript(spell_nullify); + + void HandleApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/) + { + if (Unit* target = GetTarget()) + { + target->SetHealth(1); + } + } + + void Register() override + { + AfterEffectApply += AuraEffectApplyFn(spell_nullify::HandleApply, EFFECT_1, SPELL_AURA_SCHOOL_IMMUNITY, AURA_EFFECT_HANDLE_REAL); + } +}; + void AddSC_temple_of_ahnqiraj() { RegisterTempleOfAhnQirajCreatureAI(npc_anubisath_defender); RegisterTempleOfAhnQirajCreatureAI(npc_vekniss_stinger); - RegisterSpellScript(spell_aggro_drones); RegisterTempleOfAhnQirajCreatureAI(npc_obsidian_eradicator); - RegisterSpellScript(spell_drain_mana); RegisterTempleOfAhnQirajCreatureAI(npc_anubisath_warder); + RegisterTempleOfAhnQirajCreatureAI(npc_obsidian_nullifier); + RegisterSpellScript(spell_aggro_drones); + RegisterSpellScript(spell_nullify); } diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.h b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.h index 1cba3f384..6d0ae143a 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.h +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/temple_of_ahnqiraj.h @@ -80,9 +80,9 @@ enum Creatures enum ObjectsAQ40 { - AQ40_DOOR_1 = 180634, - AQ40_DOOR_2 = 180635, - AQ40_DOOR_3 = 180636, + AQ40_DOOR_TE_ENTRANCE = 180634, + AQ40_DOOR_TE_EXIT = 180635, + AQ40_DOOR_SKERAM = 180636, GO_CTHUN_GRASP = 180745 }; diff --git a/src/server/scripts/Kalimdor/zone_ungoro_crater.cpp b/src/server/scripts/Kalimdor/zone_ungoro_crater.cpp index 84d6f1d00..58cd413c7 100644 --- a/src/server/scripts/Kalimdor/zone_ungoro_crater.cpp +++ b/src/server/scripts/Kalimdor/zone_ungoro_crater.cpp @@ -87,19 +87,25 @@ public: switch (waypointId) { case 19: - me->SummonCreature(ENTRY_STOMPER, -6391.69f, -1730.49f, -272.83f, 4.96f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - Talk(SAY_AGGRO1, player); + if (Creature* summoned = me->SummonCreature(ENTRY_STOMPER, -6391.69f, -1730.49f, -272.83f, 4.96f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000)) + { + Talk(SAY_AGGRO1, summoned); + } break; case 28: Talk(SAY_SEARCH, player); break; case 38: - me->SummonCreature(ENTRY_TARLORD, -6370.75f, -1382.84f, -270.51f, 6.06f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - Talk(SAY_AGGRO2, player); + if (Creature* summoned = me->SummonCreature(ENTRY_TARLORD, -6370.75f, -1382.84f, -270.51f, 6.06f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000)) + { + Talk(SAY_AGGRO2, summoned); + } break; case 49: - me->SummonCreature(ENTRY_TARLORD1, -6324.44f, -1181.05f, -270.17f, 4.34f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - Talk(SAY_AGGRO3, player); + if (Creature* summoned = me->SummonCreature(ENTRY_TARLORD1, -6324.44f, -1181.05f, -270.17f, 4.34f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000)) + { + Talk(SAY_AGGRO3, summoned); + } break; case 55: Talk(SAY_FINISH, player); diff --git a/src/server/scripts/Spells/spell_mage.cpp b/src/server/scripts/Spells/spell_mage.cpp index c00f88157..699ae8ff4 100644 --- a/src/server/scripts/Spells/spell_mage.cpp +++ b/src/server/scripts/Spells/spell_mage.cpp @@ -55,6 +55,7 @@ enum MageSpells SPELL_MAGE_SUMMON_WATER_ELEMENTAL_PERMANENT = 70908, SPELL_MAGE_SUMMON_WATER_ELEMENTAL_TEMPORARY = 70907, SPELL_MAGE_GLYPH_OF_BLAST_WAVE = 62126, + SPELL_MAGE_FINGERS_OF_FROST = 44543 }; class spell_mage_arcane_blast : public SpellScript @@ -932,6 +933,114 @@ class spell_mage_summon_water_elemental : public SpellScript } }; +#define FingersOfFrostScriptName "spell_mage_fingers_of_frost_proc_aura" +class spell_mage_fingers_of_frost_proc_aura : public AuraScript +{ PrepareAuraScript(spell_mage_fingers_of_frost_proc_aura); + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (eventInfo.GetSpellPhaseMask() != PROC_SPELL_PHASE_CAST) + { + eventInfo.SetProcChance(_chance); + } + + return true; + } + + bool CheckAfterProc(ProcEventInfo& eventInfo) + { + if (eventInfo.GetSpellPhaseMask() != PROC_SPELL_PHASE_CAST) + { + eventInfo.ResetProcChance(); + } + + return true; + } + + void HandleOnEffectProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo) + { + if (eventInfo.GetSpellPhaseMask() == PROC_SPELL_PHASE_CAST) + { + _chance = 100.f; + _spell = eventInfo.GetProcSpell(); + + if (!_spell || _spell->GetDelayMoment() <= 0) + { + PreventDefaultAction(); + } + } + else + { + if (eventInfo.GetSpellPhaseMask() == PROC_SPELL_PHASE_FINISH || ((_spell && _spell->GetDelayMoment() > 0) || !eventInfo.GetDamageInfo())) + { + PreventDefaultAction(); + } + + _chance = 0.f; + _spell = nullptr; + } + } + + void HandleAfterEffectProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo) + { + if (eventInfo.GetSpellPhaseMask() == PROC_SPELL_PHASE_HIT) + { + _chance = 100.f; + } + else if (eventInfo.GetSpellPhaseMask() == PROC_SPELL_PHASE_FINISH) + { + _chance = 0.f; + _spell = nullptr; + } + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_mage_fingers_of_frost_proc_aura::CheckProc); + DoCheckAfterProc += AuraCheckProcFn(spell_mage_fingers_of_frost_proc_aura::CheckAfterProc); + OnEffectProc += AuraEffectProcFn(spell_mage_fingers_of_frost_proc_aura::HandleOnEffectProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + AfterEffectProc += AuraEffectProcFn(spell_mage_fingers_of_frost_proc_aura::HandleAfterEffectProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL); + } + +public: + Spell const* GetProcSpell() const { return _spell; } + +private: + float _chance = 0.f; + Spell const* _spell = nullptr; +}; + +typedef spell_mage_fingers_of_frost_proc_aura spell_mage_fingers_of_frost_proc_aura_script; + +class spell_mage_fingers_of_frost_proc : public AuraScript +{ + PrepareAuraScript(spell_mage_fingers_of_frost_proc); + + bool CheckProc(ProcEventInfo& eventInfo) + { + if (Aura* aura = GetCaster()->GetAuraOfRankedSpell(SPELL_MAGE_FINGERS_OF_FROST)) + { + if (spell_mage_fingers_of_frost_proc_aura_script* script = dynamic_cast(aura->GetScriptByName(FingersOfFrostScriptName))) + { + if (Spell const* fofProcSpell = script->GetProcSpell()) + { + if (fofProcSpell == eventInfo.GetProcSpell()) + { + return false; + } + } + } + } + + return true; + } + + void Register() + { + DoCheckProc += AuraCheckProcFn(spell_mage_fingers_of_frost_proc::CheckProc); + } +}; + void AddSC_mage_spell_scripts() { RegisterSpellScript(spell_mage_arcane_blast); @@ -955,4 +1064,6 @@ void AddSC_mage_spell_scripts() RegisterSpellScript(spell_mage_master_of_elements); RegisterSpellScript(spell_mage_polymorph_cast_visual); RegisterSpellScript(spell_mage_summon_water_elemental); + RegisterSpellScript(spell_mage_fingers_of_frost_proc_aura); + RegisterSpellScript(spell_mage_fingers_of_frost_proc); }