diff options
-rw-r--r-- | sql/updates/world/2014_10_10_06_world.sql | 12 | ||||
-rw-r--r-- | sql/updates/world/2014_10_11_00_world.sql | 23 | ||||
-rw-r--r-- | sql/updates/world/2014_10_11_01_world.sql | 2 | ||||
-rw-r--r-- | sql/updates/world/2014_10_11_02_world.sql | 117 | ||||
-rw-r--r-- | sql/updates/world/2014_10_11_03_world.sql | 19 | ||||
-rw-r--r-- | sql/updates/world/2014_10_11_04_world.sql | 51 | ||||
-rw-r--r-- | src/server/game/AI/SmartScripts/SmartScript.cpp | 49 | ||||
-rw-r--r-- | src/server/game/AI/SmartScripts/SmartScript.h | 15 | ||||
-rw-r--r-- | src/server/game/AI/SmartScripts/SmartScriptMgr.cpp | 145 | ||||
-rw-r--r-- | src/server/game/AI/SmartScripts/SmartScriptMgr.h | 38 |
10 files changed, 343 insertions, 128 deletions
diff --git a/sql/updates/world/2014_10_10_06_world.sql b/sql/updates/world/2014_10_10_06_world.sql new file mode 100644 index 00000000000..c3fbca838b2 --- /dev/null +++ b/sql/updates/world/2014_10_10_06_world.sql @@ -0,0 +1,12 @@ +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=30945 AND `source_type`=0 AND `id`=3; +UPDATE `smart_scripts` SET `link`=28 WHERE `entryorguid`=28659 AND `source_type`=0 AND `id`=26; +UPDATE `smart_scripts` SET `link`=4 WHERE `entryorguid`=27788 AND `source_type`=0 AND `id`=3; +UPDATE `smart_scripts` SET `link`=1 WHERE `entryorguid`=26434 AND `source_type`=0 AND `id`=0; +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=25979 AND `source_type`=0 AND `id`=1; +UPDATE `smart_scripts` SET `event_type`=61 WHERE `entryorguid`=23859 AND `source_type`=0 AND `id`=3; +UPDATE `smart_scripts` SET `link`=6 WHERE `entryorguid` IN (34965,19643) AND `source_type`=0 AND `id`=5; +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid` BETWEEN -23715 AND -23712 AND `source_type`=0 AND `id`=0; +UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=12996 AND `source_type`=0 AND `id`=8; +UPDATE `smart_scripts` SET `link`=8 WHERE `entryorguid`=18171 AND `source_type`=0 AND `id`=7; +UPDATE `smart_scripts` SET `link`=5 WHERE `entryorguid`=19657 AND `source_type`=0 AND `id`=4; +UPDATE `smart_scripts` SET `id`=21, `link`=0, `comment`="The Leaper - In Combat - Cast Hunger For Blood" WHERE `entryorguid`=29840 AND `source_type`=0 AND `id`=7 AND `link`=21; diff --git a/sql/updates/world/2014_10_11_00_world.sql b/sql/updates/world/2014_10_11_00_world.sql new file mode 100644 index 00000000000..dcfb679e7e7 --- /dev/null +++ b/sql/updates/world/2014_10_11_00_world.sql @@ -0,0 +1,23 @@ +-- Scourge Cage +UPDATE `gameobject_template` SET `data2`=120000, AIName='SmartGameObjectAI', ScriptName='', `VerifiedBuild`=-18019 WHERE `entry` IN ( +187854, +187855, +187856, +187857, +187858, +187859, +187860, +187861, +187862, +187863, +187864, +187865, +187866, +187867, +187868, +187870, +187871, +187872, +187873, +187874 +); diff --git a/sql/updates/world/2014_10_11_01_world.sql b/sql/updates/world/2014_10_11_01_world.sql new file mode 100644 index 00000000000..b1fe0b91826 --- /dev/null +++ b/sql/updates/world/2014_10_11_01_world.sql @@ -0,0 +1,2 @@ +-- +UPDATE `creature` SET `position_x`=1875.67, `position_y`=1303.86, `position_z`=90.4382 WHERE `guid`=29809 and `id`=1506; diff --git a/sql/updates/world/2014_10_11_02_world.sql b/sql/updates/world/2014_10_11_02_world.sql new file mode 100644 index 00000000000..3256fa15c45 --- /dev/null +++ b/sql/updates/world/2014_10_11_02_world.sql @@ -0,0 +1,117 @@ +-- On Ruby Wings (12498) + +SET @QUEST := 12498; +SET @NPC_WYRMREST_VANQUISHER := 27996; -- Wyrmrest Vanquisher +SET @NPC_THIASSI_THE_LIGHNTNING_BRINGER := 28018; -- Thiassi the Lightning Bringer +SET @NPC_GRAND_NECROLORD_ANTIOK := 28006; -- Grand Necrolord Antiok +SET @NPC_WASTES_SCAVENGER := 28005; -- Wastes Scavenger +SET @SPELL_DEVOUR_GHOUL := 50430; -- Devour Ghoul +SET @SPELL_ENGULFING_FIREBALL := 55987; -- Engulfing Fireball +SET @SPELL_FLAME_FURY := 50348; -- Flame Fury +SET @SPELL_MOUNT := 50343; -- Controlling Wyrmrest Vanquisher +SET @ITEM_SCYTHE_OF_ANTIOK := 38305; -- Item Scythe of Antiok + +UPDATE `creature_template` SET npcflag=16777216, `spell1`=@SPELL_FLAME_FURY, `spell2`=@SPELL_ENGULFING_FIREBALL, `spell3`=@SPELL_DEVOUR_GHOUL, `InhabitType`=4 WHERE `entry`=@NPC_WYRMREST_VANQUISHER; + +DELETE FROM `npc_spellclick_spells` WHERE npc_entry IN (@NPC_WYRMREST_VANQUISHER); +INSERT INTO `npc_spellclick_spells` VALUES (@NPC_WYRMREST_VANQUISHER, @SPELL_MOUNT, 1, 0); + +DELETE FROM `creature_template_addon` WHERE `entry` in (@NPC_WYRMREST_VANQUISHER, @NPC_GRAND_NECROLORD_ANTIOK); +INSERT INTO `creature_template_addon` (`entry`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES +(@NPC_WYRMREST_VANQUISHER,0,0,50331648,0,0,'50345'), +(@NPC_GRAND_NECROLORD_ANTIOK,0,0,0,0,0,'50494'); + +UPDATE vehicle_template_accessory set minion=0,`summontype`=1 where entry=@NPC_THIASSI_THE_LIGHNTNING_BRINGER; + +Delete from creature_loot_template where entry =@NPC_GRAND_NECROLORD_ANTIOK and item=@ITEM_SCYTHE_OF_ANTIOK; + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=@SPELL_FLAME_FURY; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(13,1,@SPELL_FLAME_FURY,0,1,31,0,3,@NPC_WASTES_SCAVENGER,0,0,0,0,'','Flame Fury can only Hit Wastes Scavenger'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=55988; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(13, 1, 55988, 0, 2, 31, 0, 3, 26493, 0, 0, 0, 0, '', 'Engulfing Fireball targets Wastes Task Manager'), +(13, 1, 55988, 0, 1, 31, 0, 3, 26492, 0, 0, 0, 0, '', 'Engulfing Fireball targets Wastes Digger'), +(13, 1, 55988, 0, 0, 31, 0, 3, 28005, 0, 0, 0, 0, '', 'Engulfing Fireball targets Wastes Scavenger'), +(13, 2, 55988, 0, 0, 31, 0, 3, 27270, 0, 0, 0, 0, '', 'Engulfing Fireball targets Rotting Storm Giant'), +(13, 2, 55988, 0, 1, 31, 0, 3, 28018, 0, 0, 0, 0, '', 'Engulfing Fireball targets Thiassi'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (50430,50443); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES +(13,1,50430,0,0,31,0,3,28005,0,0,0,0,'','Devour Ghoul targets Wastes Scavenger'), +(13,3,50443,0,0,31,0,3,27996,0,0,0,0,'','Nourishment targets Wyrmrest Vanquisher'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`in (16,17) AND `SourceEntry` IN (27996,50426); +INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES +(16, 0, 27996, 0, 0, 23, 0, 4161, 0, 0, 0, 0, 0, '', 'Wyrmrest Vanquisher allowed in Wyrmrest Temple'), +(16, 0, 27996, 0, 4, 23, 0, 4184, 0, 0, 0, 0, 0, '', 'Wyrmrest Vanquisher allowed in Path of the Titans'), +(16, 0, 27996, 0, 3, 23, 0, 4174, 0, 0, 0, 0, 0, '', 'Wyrmrest Vanquisher allowed in The Wicked Coil'), +(16, 0, 27996, 0, 2, 23, 0, 4173, 0, 0, 0, 0, 0, '', 'Wyrmrest Vanquisher allowed in Galakronds Rest'), +(16, 0, 27996, 0, 1, 23, 0, 4254, 0, 0, 0, 0, 0, '', 'Wyrmrest Vanquisher allowed in The Dragon Wastes'), +(17, 0, 50426, 0, 3, 23, 0, 4174, 0, 0, 0, 0, 0, '', 'Wyrmrest Vanquisher can be summoned in The Wicked Coil'), +(17, 0, 50426, 0, 2, 23, 0, 4173, 0, 0, 0, 0, 0, '', 'Wyrmrest Vanquisher can be summoned in Galakronds Rest'), +(17, 0, 50426, 0, 1, 23, 0, 4254, 0, 0, 0, 0, 0, '', 'Wyrmrest Vanquisher can be summoned in The Dragon Wastes'), +(17, 0, 50426, 0, 0, 23, 0, 4161, 0, 0, 0, 0, 0, '', 'Wyrmrest Vanquisher can be summoned in Wyrmrest Temple'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=22 AND `SourceGroup`=5 and `SourceEntry`=@NPC_WYRMREST_VANQUISHER; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`, `ErrorTextId`,`ScriptName`,`Comment`) VALUES +(22,5,@NPC_WYRMREST_VANQUISHER,0,9,12498,0,0,0,'','event require quest taken to prevent despawn when the spell devour ghoul is casted'), +(22,5,@NPC_WYRMREST_VANQUISHER,1,28,12498,0,0,0,'','event require quest complete to prevent despawn when the spell devour ghoul is casted'); + +UPDATE creature_template SET AIName='SmartAI' WHERE entry IN (@NPC_GRAND_NECROLORD_ANTIOK, @NPC_THIASSI_THE_LIGHNTNING_BRINGER, @NPC_WYRMREST_VANQUISHER); +DELETE FROM smart_scripts WHERE entryorguid = @NPC_GRAND_NECROLORD_ANTIOK and source_type=0; +DELETE FROM smart_scripts WHERE entryorguid = @NPC_THIASSI_THE_LIGHNTNING_BRINGER and source_type=0; +DELETE FROM smart_scripts WHERE entryorguid = @NPC_WYRMREST_VANQUISHER and source_type=0; +DELETE FROM smart_scripts WHERE entryorguid = @NPC_WYRMREST_VANQUISHER*100 and source_type=9; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 28005 and source_type=0 and id=14; -- (there is already a script for this npc id=0 to id=13) +DELETE FROM `smart_scripts` WHERE `entryorguid` = 28005*100 and source_type=9; + +INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES + +(@NPC_GRAND_NECROLORD_ANTIOK, 0, 0, 0, 0, 0, 100, 0, 7000, 7000, 18000, 18000, 11, 32863, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Nekrolord Antiok - IC - Cast Demon Seed'), +(@NPC_GRAND_NECROLORD_ANTIOK, 0, 1, 0, 0, 0, 100, 0, 1100, 1100, 20000, 20000, 11, 50455, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Nekrolord Antiok - IC - Cast Shadow Bolt'), +(@NPC_GRAND_NECROLORD_ANTIOK, 0, 2, 0, 1, 0, 100, 0, 10000, 10000, 40000, 40000, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Nekrolord Antiok - OOC - Random Yell'), +(@NPC_GRAND_NECROLORD_ANTIOK, 0, 3, 0, 2, 0, 100, 1, 0, 25, 0, 0, 11, 50497, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Nekrolord Antiok - HP under 25% - Cast Scream of Chaos'), +(@NPC_GRAND_NECROLORD_ANTIOK, 0, 4, 0, 6, 0, 100, 0, 0, 0, 0, 0, 11, 50472, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Nekrolord Antiok - On Death - Cast Drop Scythe of Antiok'), +(@NPC_GRAND_NECROLORD_ANTIOK, 0, 5, 7, 4, 0, 100, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Nekrolord Antiok - On Aggro - Yell'), +(@NPC_GRAND_NECROLORD_ANTIOK, 0, 6, 0, 61, 0, 100, 0, 0, 0, 0, 0, 11, 55984, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Nekrolord Antiok - On Aggro - Cast Shadow Bolt'), +(@NPC_GRAND_NECROLORD_ANTIOK, 0, 7, 8, 4, 0, 100, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 19, @NPC_WYRMREST_VANQUISHER, 20, 0, 0, 0, 0, 0, 'Nekrolord Antiok - On Aggro - kill WYRMREST'), +(@NPC_GRAND_NECROLORD_ANTIOK, 0, 8, 0, 61, 0, 100, 0, 0, 0, 0, 0, 28, 50494, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Nekrolord Antiok - On Aggro - remove aura'), + +(@NPC_THIASSI_THE_LIGHNTNING_BRINGER, 0, 0, 0, 0, 0, 100, 0, 5000, 5000, 12000, 14000, 11, 50456, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Thiassi the Lightning Bringer - IC - Cast Thiassi''s Stormbolt'), +(@NPC_THIASSI_THE_LIGHNTNING_BRINGER, 0, 1, 0, 0, 0, 100, 0, 9000, 9000, 15000, 19000, 11, 15593, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Thiassi the Lightning Bringer - IC - Cast War Stomp'), +(@NPC_THIASSI_THE_LIGHNTNING_BRINGER, 0, 2, 0, 6, 0, 100, 0, 0, 0, 0, 0, 19, 2146959359, 0, 0, 0, 0, 0, 19, @NPC_GRAND_NECROLORD_ANTIOK, 10, 0, 0, 0, 0, 0, 'Thiassi the Lightning Bringer - On Death - remove unitflag from target'), + +(@NPC_WYRMREST_VANQUISHER, 0, 0, 0, 1, 0, 100, 0, 9000, 9000, 30000, 30000, 1, 0, 0, 0, 0, 0, 0, 21, 10, 0, 0, 0, 0, 0, 0, 'WYRMREST VANQUISHER - OOC - Random talk'), +(@NPC_WYRMREST_VANQUISHER, 0, 1, 0, 2, 0, 100, 1, 0, 33, 0, 0, 1, 1, 0, 0, 0, 0, 0, 21, 10, 0, 0, 0, 0, 0, 0, 'WYRMREST VANQUISHER - HP under 33% - talk'), +(@NPC_WYRMREST_VANQUISHER, 0, 3, 0, 54, 0, 100, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'WYRMREST VANQUISHER - Just summoned - react passif'), +(@NPC_WYRMREST_VANQUISHER, 0, 4, 0, 28, 0, 100, 0, 0, 0, 0, 0, 80, @NPC_WYRMREST_VANQUISHER*100, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'WYRMREST VANQUISHER - PASSENGER_REMOVED - Actionlist'), +(@NPC_WYRMREST_VANQUISHER*100, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 21, 10, 0, 0, 0, 0, 0, 0, 'WYRMREST VANQUISHER - ActionList - talk'), +(@NPC_WYRMREST_VANQUISHER*100, 9, 1, 0, 0, 0, 100, 0, 1000, 1000, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'WYRMREST VANQUISHER - ActionList - despawn'), + + +(28005, 0, 14, 0, 8, 0, 100, 0, 50430, 0, 0, 0, 80, 28005*100, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Wastes Scavenger - On spellhit Devour Ghoul - Run script'), +(28005*100, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 11, 50437, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Wastes Scavenger script - Spellcast Devour Ghoul'), +(28005*100, 9, 1, 0, 0, 0, 100, 0, 4000, 4000, 0, 0, 11, 50443, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Wastes Scavenger script - Spellcast Nourishment'), +(28005*100, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Wastes Scavenger script - Despawn'); + +DELETE FROM creature_text WHERE entry in (@NPC_GRAND_NECROLORD_ANTIOK, @NPC_WYRMREST_VANQUISHER); +INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `comment`, `BroadcastTextID`) VALUES +(@NPC_GRAND_NECROLORD_ANTIOK,0,0,'You think you''ve won, mortal? Face the unbridled power of Antiok!',14,0,100,0,0,0,'Antiok Yell1',27415), +(@NPC_GRAND_NECROLORD_ANTIOK,0,1,'Behold! The Scythe of Antiok!',14,0,100,0,0,0,'Antiok Yell2', 27416), +(@NPC_GRAND_NECROLORD_ANTIOK,1,0,'Soon, the bones of Galakrond will rise from their eternal slumber and wreak havoc upon this world!',14,0,100,0,0,0,'Antiok Yell3', 27406), +(@NPC_GRAND_NECROLORD_ANTIOK,1,1,'The Lich King demands more frost wyrms be sent to Angrathar! Meet his demands or face my wrath!',14,0,100,0,0,0,'Antiok Yell4', 27408), +(@NPC_GRAND_NECROLORD_ANTIOK,1,2,'Faster, dogs! We mustn''t relent in our assault against the interlopers!',14,0,100,0,0,0,'Antiok Yell5', 27405), +(@NPC_GRAND_NECROLORD_ANTIOK,1,3,'Attackers are upon us! Let none through to this ancient grave!',14,0,100,0,0,0,'Antiok Yell6', 27409), +(@NPC_GRAND_NECROLORD_ANTIOK,1,4,'Hear me, minions! Hear your lord, Antiok! Double your efforts or pay the consequences of failure!',14,0,100,0,0,0,'Antiok Yell7', 27407), +(@NPC_WYRMREST_VANQUISHER,0,1,'Across this vast expanse rest the bones of my ancestors. Their spirits have ascended to the Chamber of the Aspects.',12,0,100,0,0,0,'WYRMREST VANQUISHER', 27394), +(@NPC_WYRMREST_VANQUISHER,0,2,'Galakrond was the progenitor of dragonkind. It was from Galakrond that the Titans shaped the five Aspects.',12,0,100,0,0,0,'WYRMREST VANQUISHER', 27396), +(@NPC_WYRMREST_VANQUISHER,0,3,'It truly is a shame that the blue dragonflight has chosen such a heartless, cold path. It pains me greatly to do battle with Malygos''s children.',12,0,100,0,0,0,'WYRMREST VANQUISHER', 27400), +(@NPC_WYRMREST_VANQUISHER,0,4,'The queen and her council have been speaking lately of a disaster at Ulduar. Something has happened in Storm Peaks!',12,0,100,0,0,0,'WYRMREST VANQUISHER', 27399), +(@NPC_WYRMREST_VANQUISHER,0,5,'Today is a good day, friend. Long has it been since I have left Wyrmrest Temple, free to fly across the great Dragonblight.',12,0,100,0,0,0,'WYRMREST VANQUISHER', 27398), +(@NPC_WYRMREST_VANQUISHER,0,6,'What the Scourge has done here will reverberate throughout our world. The aberrations must be stopped!',12,0,100,0,0,0,'WYRMREST VANQUISHER', 27395), +(@NPC_WYRMREST_VANQUISHER,1,0,'You must remember that I have yet to mature into an elder wyrm. I must eat to renew my strength!',12,0,100,0,0,0,'WYRMREST VANQUISHER', 27397), +(@NPC_WYRMREST_VANQUISHER,2,0,'I have been called back to Wyrmrest, ally. Farewell!',12,0,100,0,0,0,'WYRMREST VANQUISHER', 27404); + +UPDATE `creature` SET `equipment_id`=0 WHERE `guid` IN(74522,74523,74524); diff --git a/sql/updates/world/2014_10_11_03_world.sql b/sql/updates/world/2014_10_11_03_world.sql new file mode 100644 index 00000000000..a6edf333508 --- /dev/null +++ b/sql/updates/world/2014_10_11_03_world.sql @@ -0,0 +1,19 @@ +DELETE FROM gameobject WHERE guid=99998; +INSERT INTO `gameobject` (guid, id, map, spawnMask, phaseMask, position_x, position_y, position_z, spawntimesecs, State) VALUES +(99998, 180673, 1, 1, 1, 6723.67, -5271.68, 778, 180, 1); + +set @Xandivious:=15623; + +Delete from creature_loot_template where entry =@Xandivious and item=21145; + +Update creature_template set `AIName`='SmartAI' where entry in (@Xandivious); + +DELETE FROM `smart_scripts` WHERE `entryorguid` = @Xandivious AND `source_type` = 0; +Insert into `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) values + +(@Xandivious, 0, 0, 0, 25, 0, 100, 0, 0, 0, 0, 0, 11, 25818, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, ' Xandivious - On reset - cast Aura of Rot'), +(@Xandivious, 0, 1, 0, 0, 0, 100, 0, 3000, 3000, 15000, 15000, 11, 11980, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Xandivious - IC - cast Curse of Weakness'), +(@Xandivious, 0, 2, 0, 0, 0, 100, 0, 5000, 5000, 15000, 15000, 11, 11639, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Xandivious - IC - cast Shadow Word: Pain'), +(@Xandivious, 0, 3, 0, 0, 0, 100, 0, 7000, 7000, 10000, 10000, 11, 16046, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Xandivious - IC - cast Blast Wave'), +(@Xandivious, 0, 4, 0, 2, 0, 100, 1, 0, 50, 0, 0, 11, 8599, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Xandivious - HP under 50% - Enrage'), +(@Xandivious, 0, 5, 0, 6, 0, 100, 0, 0, 0, 0, 0, 85, 25791, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Xandivious - On Death - invoker_Cast Xandivious Demon Bag'); diff --git a/sql/updates/world/2014_10_11_04_world.sql b/sql/updates/world/2014_10_11_04_world.sql new file mode 100644 index 00000000000..5b1eca19278 --- /dev/null +++ b/sql/updates/world/2014_10_11_04_world.sql @@ -0,0 +1,51 @@ +-- Schematic: Field Repair Bot 74A + +Update npc_text set BroadcastTextID0=9486 where `ID`=6931; +Delete from gossip_menu where `entry`=5749 and `text_id`=6931; +insert into gossip_menu (`entry`, `text_id`) values (5749, 6931); + +Update npc_text set BroadcastTextID0=9484 where `ID`=6930; +Delete from gossip_menu where `entry`=5749 and `text_id`=6930; +insert into gossip_menu (`entry`, `text_id`) values (5749, 6930); + +Update npc_text set BroadcastTextID0=9483 where `ID`=6929; +Delete from gossip_menu where `entry`=5749 and `text_id`=6929; +insert into gossip_menu (`entry`, `text_id`) values (5749, 6929); + +Update npc_text set BroadcastTextID0=9487 where `ID`=6932; +Delete from gossip_menu where `entry`=5749 and `text_id`=6932; +insert into gossip_menu (`entry`, `text_id`) values (5749, 6932); + +DELETE FROM `gossip_menu_option` WHERE `menu_id` = 5749; +INSERT INTO `gossip_menu_option` (`menu_id`, id, option_icon, `option_text`, `OptionBroadcastTextID`, `option_id`, `npc_option_npcflag`) +VALUES (5749, 0, 0, '<Copy the schematic into your engineering notebook.>', 9485, 1, 3); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId` =15 AND `SourceGroup`=5749; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`, `NegativeCondition`, `ErrorTextId`,`ScriptName`,`Comment`) VALUES +(15,5749,0,0,7,202,300,0,0,0,'','Show gossip menu if player have 300 or more in Engineering'), +(15,5749,0,0,25,22704,0,0,1,0,'','Show gossip menu if player doesn''t learned the spell'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=5749 and `SourceEntry`= 6931; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`, `NegativeCondition`, `ErrorTextId`,`ScriptName`,`Comment`) VALUES +(14,5749,6931,0,7,202,300,0,1,0,'','Show gossip menu if player is an Engineer but have less than 300'), +(14,5749,6931,0,25,4036,0,0,0,0,'','Show gossip menu if player is an Engineer'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=5749 and `SourceEntry`= 6930; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`, `ErrorTextId`,`ScriptName`,`Comment`) VALUES +(14,5749,6930,0,7,202,300,0,0,'','Show gossip menu if player have 300 or more in Engineering'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=5749 and `SourceEntry`= 6929; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`, `NegativeCondition`, `ErrorTextId`,`ScriptName`,`Comment`) VALUES +(14,5749,6929,0,25,4036,0,0,1,0,'','Show gossip menu if player is not an Engineer'); + +DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=14 AND `SourceGroup`=5749 and `SourceEntry`= 6932; +INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`, `ErrorTextId`,`ScriptName`,`Comment`) VALUES +(14,5749,6932,0,25,22704,0,0,0,'','Show gossip menu if player learned the spell'); + +UPDATE `gameobject_template` SET `AIName`='SmartGameObjectAI', ScriptName='' WHERE `entry`=179552; +DELETE FROM `smart_scripts` WHERE `entryorguid` = 179552 AND `source_type` = 1; + +INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES + +(179552, 1, 0, 0, 62, 0, 100, 0, 5749, 0, 0, 0, 85, 22864, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, '179552 - On Gossip Select - InvokerCast'), +(179552, 1, 1, 0, 62, 0, 100, 0, 5749, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, '179552 - On Gossip Select - CloseGossip'); diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index b877a4ca2c0..f3060972288 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -83,13 +83,13 @@ void SmartScript::ProcessEventsFor(SMART_EVENT e, Unit* unit, uint32 var0, uint3 { for (SmartAIEventList::iterator i = mEvents.begin(); i != mEvents.end(); ++i) { - SMART_EVENT eventType = SMART_EVENT((*i).GetEventType()); + SMART_EVENT eventType = SMART_EVENT(i->GetEventType()); if (eventType == SMART_EVENT_LINK)//special handling continue; - if (eventType == e/* && (!(*i).event.event_phase_mask || IsInPhase((*i).event.event_phase_mask)) && !((*i).event.event_flags & SMART_EVENT_FLAG_NOT_REPEATABLE && (*i).runOnce)*/) + if (eventType == e /*&& (!i->event.event_phase_mask || IsInPhase(i->event.event_phase_mask)) && !(i->event.event_flags & SMART_EVENT_FLAG_NOT_REPEATABLE && i->runOnce)*/) { - ConditionList conds = sConditionMgr->GetConditionsForSmartEvent((*i).entryOrGuid, (*i).event_id, (*i).source_type); + ConditionList conds = sConditionMgr->GetConditionsForSmartEvent(i->entryOrGuid, i->event_id, i->source_type); ConditionSourceInfo info = ConditionSourceInfo(unit, GetBaseObject()); if (sConditionMgr->IsObjectMeetToConditions(info, conds)) @@ -167,7 +167,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u for (ObjectList::const_iterator itr = targets->begin(); itr != targets->end(); ++itr) { if (IsCreature(*itr)) - sCreatureTextMgr->SendChat((*itr)->ToCreature(), uint8(e.action.talk.textGroupID), IsPlayer(GetLastInvoker())? GetLastInvoker() : 0); + sCreatureTextMgr->SendChat((*itr)->ToCreature(), uint8(e.action.talk.textGroupID), IsPlayer(GetLastInvoker()) ? GetLastInvoker() : 0); else if (IsPlayer(*itr) && me) { Unit* templastInvoker = GetLastInvoker(); @@ -2252,8 +2252,8 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (e.link && e.link != e.event_id) { - SmartScriptHolder linked = FindLinkedEvent(e.link); - if (linked.GetActionType() && linked.GetEventType() == SMART_EVENT_LINK) + SmartScriptHolder& linked = SmartAIMgr::FindLinkedEvent(mEvents, e.link); + if (linked) ProcessEvent(linked, unit, var0, var1, bvar, spell, gob); else TC_LOG_ERROR("sql.sql", "SmartScript::ProcessAction: Entry %d SourceType %u, Event %u, Link Event %u not found or invalid, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.link); @@ -2461,7 +2461,7 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* if (me && me->GetGUID() == (*itr)->GetGUID()) continue; - if (((e.target.unitRange.creature && (*itr)->ToCreature()->GetEntry() == e.target.unitRange.creature) || !e.target.unitRange.creature) && baseObject->IsInRange(*itr, (float)e.target.unitRange.minDist, (float)e.target.unitRange.maxDist)) + if ((!e.target.unitRange.creature || (*itr)->ToCreature()->GetEntry() == e.target.unitRange.creature) && baseObject->IsInRange(*itr, float(e.target.unitRange.minDist), float(e.target.unitRange.maxDist))) l->push_back(*itr); } @@ -2480,7 +2480,7 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* if (me && me->GetGUID() == (*itr)->GetGUID()) continue; - if ((e.target.unitDistance.creature && (*itr)->ToCreature()->GetEntry() == e.target.unitDistance.creature) || !e.target.unitDistance.creature) + if (!e.target.unitDistance.creature || (*itr)->ToCreature()->GetEntry() == e.target.unitDistance.creature) l->push_back(*itr); } @@ -2499,7 +2499,7 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* if (go && go->GetGUID() == (*itr)->GetGUID()) continue; - if ((e.target.goDistance.entry && (*itr)->ToGameObject()->GetEntry() == e.target.goDistance.entry) || !e.target.goDistance.entry) + if (!e.target.goDistance.entry || (*itr)->ToGameObject()->GetEntry() == e.target.goDistance.entry) l->push_back(*itr); } @@ -2518,7 +2518,7 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* if (go && go->GetGUID() == (*itr)->GetGUID()) continue; - if (((e.target.goRange.entry && IsGameObject(*itr) && (*itr)->ToGameObject()->GetEntry() == e.target.goRange.entry) || !e.target.goRange.entry) && baseObject->IsInRange((*itr), (float)e.target.goRange.minDist, (float)e.target.goRange.maxDist)) + if ((!e.target.goRange.entry && (*itr)->ToGameObject()->GetEntry() == e.target.goRange.entry) && baseObject->IsInRange(*itr, float(e.target.goRange.minDist), float(e.target.goRange.maxDist))) l->push_back(*itr); } @@ -2527,32 +2527,28 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* } case SMART_TARGET_CREATURE_GUID: { - Creature* target = NULL; if (!scriptTrigger && !baseObject) { TC_LOG_ERROR("sql.sql", "SMART_TARGET_CREATURE_GUID can not be used without invoker"); break; } - target = FindCreatureNear(scriptTrigger ? scriptTrigger : baseObject, e.target.unitGUID.dbGuid); - - if (target && (!e.target.unitGUID.entry || target->GetEntry() == e.target.unitGUID.entry)) - l->push_back(target); + if (Creature* target = FindCreatureNear(scriptTrigger ? scriptTrigger : baseObject, e.target.unitGUID.dbGuid)) + if (!e.target.unitGUID.entry || target->GetEntry() == e.target.unitGUID.entry) + l->push_back(target); break; } case SMART_TARGET_GAMEOBJECT_GUID: { - GameObject* target = NULL; if (!scriptTrigger && !baseObject) { TC_LOG_ERROR("sql.sql", "SMART_TARGET_GAMEOBJECT_GUID can not be used without invoker"); break; } - target = FindGameObjectNear(scriptTrigger ? scriptTrigger : baseObject, e.target.goGUID.dbGuid); - - if (target && (!e.target.goGUID.entry || target->GetEntry() == e.target.goGUID.entry)) - l->push_back(target); + if (GameObject* target = FindGameObjectNear(scriptTrigger ? scriptTrigger : baseObject, e.target.goGUID.dbGuid)) + if (!e.target.goGUID.entry || target->GetEntry() == e.target.goGUID.entry) + l->push_back(target); break; } case SMART_TARGET_PLAYER_RANGE: @@ -2591,26 +2587,21 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* } case SMART_TARGET_CLOSEST_CREATURE: { - Creature* target = GetClosestCreatureWithEntry(baseObject, e.target.closest.entry, (float)(e.target.closest.dist ? e.target.closest.dist : 100), !e.target.closest.dead); - if (target) + if (Creature* target = GetClosestCreatureWithEntry(baseObject, e.target.closest.entry, float(e.target.closest.dist ? e.target.closest.dist : 100), !e.target.closest.dead)) l->push_back(target); break; } case SMART_TARGET_CLOSEST_GAMEOBJECT: { - GameObject* target = GetClosestGameObjectWithEntry(baseObject, e.target.closest.entry, (float)(e.target.closest.dist ? e.target.closest.dist : 100)); - if (target) + if (GameObject* target = GetClosestGameObjectWithEntry(baseObject, e.target.closest.entry, float(e.target.closest.dist ? e.target.closest.dist : 100))) l->push_back(target); break; } case SMART_TARGET_CLOSEST_PLAYER: { if (me) - { - Player* target = me->SelectNearestPlayer((float)e.target.playerDistance.dist); - if (target) + if (Player* target = me->SelectNearestPlayer(float(e.target.playerDistance.dist))) l->push_back(target); - } break; } case SMART_TARGET_OWNER_OR_SUMMONER: @@ -2643,7 +2634,6 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* if (me) if (Unit* target = me->SelectNearestTarget(e.target.closestAttackable.maxDist, e.target.closestAttackable.playerOnly != 0)) l->push_back(target); - break; } case SMART_TARGET_CLOSEST_FRIENDLY: @@ -2651,7 +2641,6 @@ ObjectList* SmartScript::GetTargets(SmartScriptHolder const& e, Unit* invoker /* if (me) if (Unit* target = DoFindClosestFriendlyInRange(e.target.closestFriendly.maxDist, e.target.closestFriendly.playerOnly != 0)) l->push_back(target); - break; } case SMART_TARGET_POSITION: diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h index 02bc1a2b487..b59b62c5697 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.h +++ b/src/server/game/AI/SmartScripts/SmartScript.h @@ -257,21 +257,6 @@ class SmartScript } } } - SmartScriptHolder FindLinkedEvent(uint32 link) - { - if (!mEvents.empty()) - { - for (SmartAIEventList::iterator i = mEvents.begin(); i != mEvents.end(); ++i) - { - if (i->event_id == link) - { - return (*i); - } - } - } - SmartScriptHolder s; - return s; - } }; #endif diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp index 80ca1b27be4..0f0dcbc557a 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.cpp @@ -91,7 +91,6 @@ void SmartWaypointMgr::LoadFromDB() while (result->NextRow()); TC_LOG_INFO("server.loading", ">> Loaded %u SmartAI waypoint paths (total %u waypoints) in %u ms", count, total, GetMSTimeDiffToNow(oldMSTime)); - } SmartWaypointMgr::~SmartWaypointMgr() @@ -192,23 +191,23 @@ void SmartAIMgr::LoadSmartAIFromDB() } else { - CreatureData const* creature = sObjectMgr->GetCreatureData(uint32(abs(temp.entryOrGuid))); + CreatureData const* creature = sObjectMgr->GetCreatureData(uint32(std::abs(temp.entryOrGuid))); if (!creature) { - TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Creature guid (%u) does not exist, skipped loading.", uint32(abs(temp.entryOrGuid))); + TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Creature guid (%u) does not exist, skipped loading.", uint32(std::abs(temp.entryOrGuid))); continue; } CreatureTemplate const* creatureInfo = sObjectMgr->GetCreatureTemplate(creature->id); if (!creatureInfo) { - TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Creature entry (%u) guid (%u) does not exist, skipped loading.", creature->id, uint32(abs(temp.entryOrGuid))); + TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Creature entry (%u) guid (%u) does not exist, skipped loading.", creature->id, uint32(std::abs(temp.entryOrGuid))); continue; } if (creatureInfo->AIName != "SmartAI") { - TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Creature entry (%u) guid (%u) is not using SmartAI, skipped loading.", creature->id, uint32(abs(temp.entryOrGuid))); + TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Creature entry (%u) guid (%u) is not using SmartAI, skipped loading.", creature->id, uint32(std::abs(temp.entryOrGuid))); continue; } } @@ -263,26 +262,29 @@ void SmartAIMgr::LoadSmartAIFromDB() } while (result->NextRow()); - // TO-DO: Find better way - for (uint8 i = 0; i < SMART_SCRIPT_TYPE_MAX; i++) + // Post Loading Validation + for (uint8 i = 0; i < SMART_SCRIPT_TYPE_MAX; ++i) { - for (auto itr = mEventMap[i].begin(); itr != mEventMap[i].end(); ++itr) + for (SmartAIEventMap::iterator itr = mEventMap[i].begin(); itr != mEventMap[i].end(); ++itr) { - for (auto e : mEventMap[i][itr->first]) + for (SmartScriptHolder const& e : itr->second) { - bool found = false; - if (e.link && e.link != e.event_id) + if (e.link) { - for (auto linked : mEventMap[i][itr->first]) + if (!FindLinkedEvent(itr->second, e.link)) { - if (linked.event_id == e.link) - if (linked.GetActionType() && linked.GetEventType() == SMART_EVENT_LINK) - found = true; + TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Entry %d SourceType %u, Event %u, Link Event %u not found or invalid.", + e.entryOrGuid, e.GetScriptType(), e.event_id, e.link); } + } - if (!found) - TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Entry %d SourceType %u, Event %u, Link Event %u not found or invalid", - e.entryOrGuid, e.GetScriptType(), e.event_id, e.link); + if (e.GetEventType() == SMART_EVENT_LINK) + { + if (!FindLinkedSourceEvent(itr->second, e.event_id)) + { + TC_LOG_ERROR("sql.sql", "SmartAIMgr::LoadSmartAIFromDB: Entry %d SourceType %u, Event %u, Link Source Event not found or invalid. Event will never trigger.", + e.entryOrGuid, e.GetScriptType(), e.event_id); + } } } } @@ -295,8 +297,13 @@ void SmartAIMgr::LoadSmartAIFromDB() bool SmartAIMgr::IsTargetValid(SmartScriptHolder const& e) { + if (std::abs(e.target.o) > 2 * float(M_PI)) + TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u has abs(`target.o` = %f) > 2*PI (orientation is expressed in radians)", + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.target.o); + if (e.GetActionType() == SMART_ACTION_INSTALL_AI_TEMPLATE) return true; // AI template has special handling + switch (e.GetTargetType()) { case SMART_TARGET_CREATURE_DISTANCE: @@ -375,27 +382,38 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) TC_LOG_ERROR("sql.sql", "SmartAIMgr: EntryOrGuid %d using event(%u) has invalid event type (%u), skipped.", e.entryOrGuid, e.event_id, e.GetEventType()); return false; } + // in SMART_SCRIPT_TYPE_TIMED_ACTIONLIST all event types are overriden by core if (e.GetScriptType() != SMART_SCRIPT_TYPE_TIMED_ACTIONLIST && !(SmartAIEventMask[e.event.type][1] & SmartAITypeMask[e.GetScriptType()][1])) { TC_LOG_ERROR("sql.sql", "SmartAIMgr: EntryOrGuid %d, event type %u can not be used for Script type %u", e.entryOrGuid, e.GetEventType(), e.GetScriptType()); return false; } + if (e.action.type <= 0 || e.action.type >= SMART_ACTION_END) { TC_LOG_ERROR("sql.sql", "SmartAIMgr: EntryOrGuid %d using event(%u) has invalid action type (%u), skipped.", e.entryOrGuid, e.event_id, e.GetActionType()); return false; } + if (e.event.event_phase_mask > SMART_EVENT_PHASE_ALL) { TC_LOG_ERROR("sql.sql", "SmartAIMgr: EntryOrGuid %d using event(%u) has invalid phase mask (%u), skipped.", e.entryOrGuid, e.event_id, e.event.event_phase_mask); return false; } + if (e.event.event_flags > SMART_EVENT_FLAGS_ALL) { TC_LOG_ERROR("sql.sql", "SmartAIMgr: EntryOrGuid %d using event(%u) has invalid event flags (%u), skipped.", e.entryOrGuid, e.event_id, e.event.event_flags); return false; } + + if (e.link && e.link == e.event_id) + { + TC_LOG_ERROR("sql.sql", "SmartAIMgr: EntryOrGuid %d SourceType %u, Event %u, Event is linking self (infinite loop), skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id); + return false; + } + if (e.GetScriptType() == SMART_SCRIPT_TYPE_TIMED_ACTIONLIST) { e.event.type = SMART_EVENT_UPDATE_OOC;//force default OOC, can change when calling the script! @@ -407,8 +425,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) } else { - uint32 type = e.event.type; - switch (type) + switch (e.GetEventType()) { case SMART_EVENT_UPDATE: case SMART_EVENT_UPDATE_IC: @@ -568,17 +585,9 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) break; } case SMART_EVENT_TEXT_OVER: - //if (e.event.textOver.textGroupID && !IsTextValid(e, e.event.textOver.textGroupID)) return false;// 0 is a valid text group! - break; - case SMART_EVENT_LINK: - { - if (e.link && e.link == e.event_id) - { - TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u, Event %u, Link Event is linking self (infinite loop), skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id); + if (!IsTextValid(e, e.event.textOver.textGroupID)) return false; - } break; - } case SMART_EVENT_DUMMY_EFFECT: { if (!IsSpellValid(e, e.event.dummy.spell)) @@ -686,6 +695,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) return false; } break; + case SMART_EVENT_LINK: case SMART_EVENT_GO_STATE_CHANGED: case SMART_EVENT_GO_EVENT_INFORM: case SMART_EVENT_TIMED_EVENT_TRIGGERED: @@ -729,14 +739,10 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) switch (e.GetActionType()) { case SMART_ACTION_TALK: - { - if (e.GetScriptType() == SMART_SCRIPT_TYPE_CREATURE) - { - if (!IsTextValid(e, e.action.talk.textGroupID)) - return false; - } + case SMART_ACTION_SIMPLE_TALK: + if (!IsTextValid(e, e.action.talk.textGroupID)) + return false; break; - } case SMART_ACTION_SET_FACTION: if (e.action.faction.factionID && !sFactionTemplateStore.LookupEntry(e.action.faction.factionID)) { @@ -816,7 +822,7 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) if (!IsSpellValid(e, e.action.cast.spell)) return false; - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(e.action.cast.spell); + SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(e.action.cast.spell); for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j) { if (spellInfo->Effects[j].IsEffect(SPELL_EFFECT_KILL_CREDIT) || spellInfo->Effects[j].IsEffect(SPELL_EFFECT_KILL_CREDIT2)) @@ -979,10 +985,10 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) if (!NotNULL(e, e.action.item.count)) return false; - CacheSpellContainerBounds sBounds = GetCreditItemSpellContainerBounds(e.action.item.entry); + CacheSpellContainerBounds sBounds = GetCreateItemSpellContainerBounds(e.action.item.entry); for (CacheSpellContainer::const_iterator itr = sBounds.first; itr != sBounds.second; ++itr) TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u Create Item: There is a create item spell for item %u (SpellId: %u effect: %u)", - e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.item.entry, itr->second.first, itr->second.second); + e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), e.action.item.entry, itr->second.first, itr->second.second); break; } case SMART_ACTION_TELEPORT: @@ -1146,7 +1152,6 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) case SMART_ACTION_SET_NPC_FLAG: case SMART_ACTION_ADD_NPC_FLAG: case SMART_ACTION_REMOVE_NPC_FLAG: - case SMART_ACTION_SIMPLE_TALK: case SMART_ACTION_CROSS_CAST: case SMART_ACTION_CALL_RANDOM_TIMED_ACTIONLIST: case SMART_ACTION_RANDOM_MOVE: @@ -1177,49 +1182,45 @@ bool SmartAIMgr::IsEventValid(SmartScriptHolder& e) return true; } -bool SmartAIMgr::IsTextValid(SmartScriptHolder const& e, uint32 id) // unused +bool SmartAIMgr::IsTextValid(SmartScriptHolder const& e, uint32 id) { - bool error = false; + if (e.GetScriptType() != SMART_SCRIPT_TYPE_CREATURE) + return true; + uint32 entry = 0; - if (e.entryOrGuid >= 0) + if (e.GetEventType() == SMART_EVENT_TEXT_OVER) { - if (e.GetEventType() == SMART_EVENT_TEXT_OVER) - { - entry = e.event.textOver.creatureEntry; - id = e.event.textOver.textGroupID; - } - else - { - switch (e.GetTargetType()) - { - case SMART_TARGET_CREATURE_DISTANCE: - case SMART_TARGET_CREATURE_RANGE: - case SMART_TARGET_CLOSEST_CREATURE: - return true; // ignore - default: - entry = uint32(e.entryOrGuid); - break; - } - } + entry = e.event.textOver.creatureEntry; } else { - entry = uint32(abs(e.entryOrGuid)); - CreatureData const* data = sObjectMgr->GetCreatureData(entry); - if (!data) + switch (e.GetTargetType()) { - TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u using non-existent Creature guid %d, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry); - return false; + case SMART_TARGET_CREATURE_DISTANCE: + case SMART_TARGET_CREATURE_RANGE: + case SMART_TARGET_CLOSEST_CREATURE: + return true; // ignore + default: + if (e.entryOrGuid < 0) + { + entry = uint32(std::abs(e.entryOrGuid)); + CreatureData const* data = sObjectMgr->GetCreatureData(entry); + if (!data) + { + TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u using non-existent Creature guid %d, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), entry); + return false; + } + else + entry = data->id; + } + else + entry = uint32(e.entryOrGuid); + break; } - else - entry = data->id; } if (!entry || !sCreatureTextMgr->TextExist(entry, uint8(id))) - error = true; - - if (error) { TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u using non-existent Text id %d, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), id); return false; @@ -1281,7 +1282,7 @@ CacheSpellContainerBounds SmartAIMgr::GetKillCreditSpellContainerBounds(uint32 k return KillCreditSpellStore.equal_range(killCredit); } -CacheSpellContainerBounds SmartAIMgr::GetCreditItemSpellContainerBounds(uint32 itemId) const +CacheSpellContainerBounds SmartAIMgr::GetCreateItemSpellContainerBounds(uint32 itemId) const { return CreateItemSpellStore.equal_range(itemId); } diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h index 249c63f5cf6..9bb34d1347e 100644 --- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h +++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h @@ -1347,6 +1347,8 @@ struct SmartScriptHolder bool active; bool runOnce; bool enableTimed; + + operator bool() const { return entryOrGuid != 0; } }; typedef std::unordered_map<uint32, WayPoint*> WPPath; @@ -1469,6 +1471,30 @@ class SmartAIMgr } } + static SmartScriptHolder& FindLinkedSourceEvent(SmartAIEventList& list, uint32 eventId) + { + SmartAIEventList::iterator itr = std::find_if(list.begin(), list.end(), + [eventId](SmartScriptHolder& source) { return source.link == eventId; }); + + if (itr != list.end()) + return *itr; + + static SmartScriptHolder SmartScriptHolderDummy; + return SmartScriptHolderDummy; + } + + static SmartScriptHolder& FindLinkedEvent(SmartAIEventList& list, uint32 link) + { + SmartAIEventList::iterator itr = std::find_if(list.begin(), list.end(), + [link](SmartScriptHolder& linked) { return linked.event_id == link && linked.GetEventType() == SMART_EVENT_LINK; }); + + if (itr != list.end()) + return *itr; + + static SmartScriptHolder SmartScriptHolderDummy; + return SmartScriptHolderDummy; + } + private: //event stores SmartAIEventMap mEventMap[SMART_SCRIPT_TYPE_MAX]; @@ -1476,16 +1502,6 @@ class SmartAIMgr bool IsEventValid(SmartScriptHolder& e); bool IsTargetValid(SmartScriptHolder const& e); - /*inline bool IsTargetValid(SmartScriptHolder e, int32 target) - { - if (target < SMART_TARGET_NONE || target >= SMART_TARGET_END) - { - TC_LOG_ERROR("sql.sql", "SmartAIMgr: Entry %d SourceType %u Event %u Action %u uses invalid Target type %d, skipped.", e.entryOrGuid, e.GetScriptType(), e.event_id, e.GetActionType(), target); - return false; - } - return true; - }*/ - bool IsMinMaxValid(SmartScriptHolder const& e, uint32 min, uint32 max) { if (max < min) @@ -1615,7 +1631,7 @@ class SmartAIMgr CacheSpellContainerBounds GetSummonCreatureSpellContainerBounds(uint32 creatureEntry) const; CacheSpellContainerBounds GetSummonGameObjectSpellContainerBounds(uint32 gameObjectEntry) const; CacheSpellContainerBounds GetKillCreditSpellContainerBounds(uint32 killCredit) const; - CacheSpellContainerBounds GetCreditItemSpellContainerBounds(uint32 itemId) const; + CacheSpellContainerBounds GetCreateItemSpellContainerBounds(uint32 itemId) const; CacheSpellContainer SummonCreatureSpellStore; CacheSpellContainer SummonGameObjectSpellStore; |