Merge branch 'master' into Playerbot
This commit is contained in:
@@ -31,7 +31,8 @@ def parsing_file(directory: str) -> None:
|
||||
multiple_blank_lines_check(file, file_path)
|
||||
trailing_whitespace_check(file, file_path)
|
||||
get_counter_check(file, file_path)
|
||||
misc_codestyle_check(file, file_path)
|
||||
if not file_name.endswith('.cmake') and file_name != 'CMakeLists.txt':
|
||||
misc_codestyle_check(file, file_path)
|
||||
if file_name != 'Object.h':
|
||||
get_typeid_check(file, file_path)
|
||||
if file_name != 'Unit.h':
|
||||
@@ -223,6 +224,10 @@ def misc_codestyle_check(file: io, file_path: str) -> None:
|
||||
print(
|
||||
f"Please use the syntax 'Class/ObjectType const*' instead of 'const Class/ObjectType*': {file_path} at line {line_number}")
|
||||
check_failed = True
|
||||
if [match for match in [' if(', ' if ( '] if match in line]:
|
||||
print(
|
||||
f"AC have as standard: if (XXXX). Please check spaces in your condition': {file_path} at line {line_number}")
|
||||
check_failed = True
|
||||
# Handle the script error and update the result output
|
||||
if check_failed:
|
||||
error_handler = True
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
-- DB update 2024_09_22_02 -> 2024_09_22_03
|
||||
|
||||
UPDATE `item_template` SET `BuyCount` = 20 WHERE (`entry` = 32453);
|
||||
UPDATE `item_template` SET `BuyCount` = 5 WHERE (`entry` = 32455);
|
||||
@@ -0,0 +1,27 @@
|
||||
-- DB update 2024_09_22_03 -> 2024_09_23_00
|
||||
-- Bug Report #19575
|
||||
|
||||
-- Unlink from engineering quest chain:
|
||||
-- 3638 (Goblin Engineering - Pledge of Secrecy)
|
||||
-- 3640 (gnome engineering - pledge of secrecy, alliance)
|
||||
-- 3642 (gnome engineering - pledge of secrecy, horde)
|
||||
UPDATE `quest_template` SET `RewardNextQuest`=0 WHERE `ID`=3638 OR `ID`=3640 OR `ID`=3642;
|
||||
UPDATE `quest_template` SET `RewardNextQuest`=3639 WHERE `ID`=3526 OR `ID`=3629 OR `ID`=3633 OR `ID`=4181;
|
||||
UPDATE `quest_template` SET `RewardNextQuest`=3641 WHERE `ID`=3630 OR `ID`=3632 OR `ID`=3634;
|
||||
UPDATE `quest_template` SET `RewardNextQuest`=3643 WHERE `ID`=3635 OR `ID`=3637;
|
||||
|
||||
-- Remove Pledge of Secrecy from creature_queststarter
|
||||
DELETE FROM `creature_queststarter` WHERE `quest`=3638 OR `quest`=3640 OR `quest`=3642;
|
||||
-- Remove Pledge of Secrecy from creature_questender
|
||||
DELETE FROM `creature_questender` WHERE `quest`=3638 OR `quest`=3640 OR `quest`=3642;
|
||||
|
||||
-- Link quests together:
|
||||
-- 3526, 3629, 3633, 4181 (Goblin Engineering) -> 3639 (Goblin Engineering - Show Your Work)
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID`=3633 WHERE `ID`=3639;
|
||||
UPDATE `quest_template_addon` SET `NextQuestID`=3639 WHERE `ID`=3526 OR `ID`=3629 OR `ID`=3633 OR `ID`=4181;
|
||||
-- 3630, 3632, 3634 (Gnome Engineering - Alliance) -> 3641 (Gnome Engineering - Show Your Work - Alliance)
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID`=3634 WHERE `ID`=3641;
|
||||
UPDATE `quest_template_addon` SET `NextQuestID`=3641 WHERE `ID`=3630 OR `ID`=3632 OR `ID`=3634;
|
||||
-- 3635, 3637 (Gnome Engineering - Horde) -> 3643 (Gnome Engineering - Show Your Work - Horde)
|
||||
UPDATE `quest_template_addon` SET `PrevQuestID`=3635 WHERE `ID`=3643;
|
||||
UPDATE `quest_template_addon` SET `NextQuestID`=3643 WHERE `ID`=3635 OR `ID`=3637;
|
||||
@@ -0,0 +1,9 @@
|
||||
-- DB update 2024_09_23_00 -> 2024_09_23_01
|
||||
--
|
||||
DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_item_skyguard_blasting_charges';
|
||||
INSERT INTO `spell_script_names` (`spell_id`,`ScriptName`) VALUES
|
||||
(39844, 'spell_item_skyguard_blasting_charges');
|
||||
|
||||
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 17) AND (`SourceGroup` = 0) AND (`SourceEntry` = 39844) AND (`SourceId` = 0) AND (`ElseGroup` = 0) AND (`ConditionTypeOrReference` = 30) AND (`ConditionTarget` = 0) AND (`ConditionValue1` = 185549) AND (`ConditionValue2` = 30) AND (`ConditionValue3` = 0);
|
||||
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
|
||||
(17, 0, 39844, 0, 0, 30, 0, 185549, 30, 0, 0, 0, 0, '', ' Launch a blasting charge from your flying mount at monstrous kaliri eggs.');
|
||||
@@ -0,0 +1,12 @@
|
||||
-- DB update 2024_09_23_01 -> 2024_09_23_02
|
||||
-- Updating loot for Hound of Culuthas (Entry: 20141)
|
||||
DELETE FROM `creature_loot_template` WHERE `Entry` = 20141 AND `Item` IN (25418, 25421);
|
||||
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
|
||||
(20141, 25418, 0, 80, 0, 1, 2, 1, 1, 'Hound of Culuthas - Razor Sharp Fang'),
|
||||
(20141, 25421, 0, 0, 0, 1, 2, 1, 1, 'Hound of Culuthas - Gnarled Claw');
|
||||
|
||||
-- Updating loot for Eye of Culuthas (Entry: 20394)
|
||||
DELETE FROM `creature_loot_template` WHERE `Entry` = 20394 AND `Item` IN (29799, 29800);
|
||||
INSERT INTO `creature_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`, `Comment`) VALUES
|
||||
(20394, 29799, 0, 80, 0, 1, 2, 1, 1, 'Eye of Culuthas - Lifeless Tendril'),
|
||||
(20394, 29800, 0, 0, 0, 1, 2, 1, 1, 'Eye of Culuthas - Evil Eye');
|
||||
@@ -0,0 +1,178 @@
|
||||
-- DB update 2024_09_23_02 -> 2024_09_24_00
|
||||
--
|
||||
-- Boat summoners
|
||||
SET @GUID := 52030;
|
||||
DELETE FROM `creature` WHERE `id1` IN (37964,37981,36817) AND (`guid` BETWEEN @GUID AND @GUID+2);
|
||||
INSERT INTO `creature` (`guid`, `id1`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `wander_distance`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `VerifiedBuild`) VALUES
|
||||
(@GUID, 37964, 0, 0, 0, 1, 1, 0, 1484.662, 348.019, -64.54687, 0.8377581, 120, 0, 0, 1, 0, 0, 0, 0, 0, 0),
|
||||
(@GUID+1, 37981, 1, 0, 0, 1, 1, 0, 9843.134, 2430.733, 1313.6, 5.5676, 120, 0, 0, 1, 0, 0, 0, 0, 0, 0),
|
||||
(@GUID+2, 36817, 0, 0, 0, 1, 1, 0, -8796.021, 775.0364, 95.22309, 0.01745329, 120, 0, 0, 1, 0, 0, 0, 0, 0, 0);
|
||||
|
||||
DELETE FROM `game_event_creature` WHERE `eventEntry`=8 AND `guid` BETWEEN @GUID AND @GUID+2;
|
||||
INSERT INTO `game_event_creature` (`eventEntry`, `guid`) VALUES
|
||||
(8, @GUID),
|
||||
(8, @GUID+1),
|
||||
(8, @GUID+2);
|
||||
|
||||
UPDATE `creature_template` SET `npcflag`=16777216,`VehicleId`=616,`IconName`='vehichleCursor' WHERE `entry`=37966;
|
||||
UPDATE `creature_template` SET `npcflag`=16777216,`VehicleId`=615,`IconName`='vehichleCursor' WHERE `entry`=37980;
|
||||
UPDATE `creature_template` SET `npcflag`=16777216,`VehicleId`=548,`IconName`='vehichleCursor' WHERE `entry`=36812;
|
||||
|
||||
-- trigger NPC, make invisible to players
|
||||
UPDATE `creature_template` SET `flags_extra` = `flags_extra` | 128 WHERE (`entry` IN (36817, 37964, 37981));
|
||||
|
||||
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` IN (37966,37964,37981,37980,36817,36812);
|
||||
DELETE FROM `smart_scripts` WHERE `entryorguid` IN (37966,37964,37980,37981,36817,36812) 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`, `event_param5`, `event_param6`, `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
|
||||
(36812, 0, 0, 0, 1, 0, 100, 1, 5000, 5000, 0, 0, 0, 0, 53, 0, 36812, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Stormwind Love Boat - Out of Combat - Start Waypoint Path 36812 (No Repeat)'),
|
||||
(36812, 0, 1, 2, 40, 0, 100, 0, 21, 36812, 0, 0, 0, 0, 11, 50630, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Stormwind Love Boat - On Point 21 of Path 36812 Reached - Cast \'Eject All Passengers\''),
|
||||
(36812, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 2000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Stormwind Love Boat - On Point 21 of Path 36812 Reached - Despawn In 2000 ms'),
|
||||
(36812, 0, 3, 4, 54, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 70143, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Stormwind Love Boat - On Just Summoned - Cast \'Vehicle Test\''),
|
||||
(36812, 0, 4, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 48, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Stormwind Love Boat - On Just Summoned - Set Active On'),
|
||||
(36812, 0, 5, 0, 1, 0, 100, 0, 0, 0, 3000, 3000, 0, 0, 75, 69341, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Stormwind Love Boat - Out of Combat - Add Aura \'Love Boat\''),
|
||||
(36812, 0, 6, 0, 23, 0, 100, 0, 69342, 2, 1000, 1000, 0, 0, 75, 69352, 0, 0, 0, 0, 0, 17, 0, 20, 0, 0, 0, 0, 0, 0, 'Stormwind Love Boat - On Aura \'Ride Vehicle\' - Add Aura \'Romantic\''),
|
||||
(36812, 0, 7, 0, 28, 0, 100, 0, 0, 0, 0, 0, 0, 0, 28, 69352, 0, 0, 0, 0, 0, 17, 0, 20, 0, 0, 0, 0, 0, 0, 'Stormwind Love Boat - On Passenger Removed - Remove Aura \'Romantic\''),
|
||||
(37966, 0, 0, 0, 1, 0, 100, 1, 5000, 5000, 0, 0, 0, 0, 53, 0, 37966, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Undercity Love Boat - Out of Combat - Start Waypoint Path 37966 (No Repeat)'),
|
||||
(37966, 0, 1, 2, 40, 0, 100, 0, 31, 37966, 0, 0, 0, 0, 11, 50630, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Undercity Love Boat - On Point 31 of Path 37966 Reached - Cast \'Eject All Passengers\''),
|
||||
(37966, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 2000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Undercity Love Boat - On Point 31 of Path 37966 Reached - Despawn In 2000 ms'),
|
||||
(37966, 0, 3, 4, 54, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 70143, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Undercity Love Boat - On Just Summoned - Cast \'Vehicle Test\''),
|
||||
(37966, 0, 4, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 48, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Undercity Love Boat - On Just Summoned - Set Active On'),
|
||||
(37966, 0, 5, 0, 1, 0, 100, 0, 0, 0, 3000, 3000, 0, 0, 75, 69341, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Undercity Love Boat - Out of Combat - Add Aura \'Love Boat\''),
|
||||
(37966, 0, 6, 0, 23, 0, 100, 0, 69342, 2, 1000, 1000, 0, 0, 75, 69352, 0, 0, 0, 0, 0, 17, 0, 20, 0, 0, 0, 0, 0, 0, 'Undercity Love Boat - On Aura \'Ride Vehicle\' - Add Aura \'Romantic\''),
|
||||
(37966, 0, 7, 0, 28, 0, 100, 0, 0, 0, 0, 0, 0, 0, 28, 69352, 0, 0, 0, 0, 0, 17, 0, 20, 0, 0, 0, 0, 0, 0, 'Undercity Love Boat - On Passenger Removed - Remove Aura \'Romantic\''),
|
||||
(37980, 0, 0, 0, 1, 0, 100, 1, 5000, 5000, 0, 0, 0, 0, 53, 0, 37980, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Darnassus Love Boat - Out of Combat - Start Waypoint Path 37980 (No Repeat)'),
|
||||
(37980, 0, 1, 2, 40, 0, 100, 0, 60, 37980, 0, 0, 0, 0, 11, 50630, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Darnassus Love Boat - On Point 60 of Path 37980 Reached - Cast \'Eject All Passengers\''),
|
||||
(37980, 0, 2, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 2000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Darnassus Love Boat - On Point 60 of Path 37980 Reached - Despawn In 2000 ms'),
|
||||
(37980, 0, 3, 4, 54, 0, 100, 0, 0, 0, 0, 0, 0, 0, 11, 70143, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Darnassus Love Boat - On Just Summoned - Cast \'Vehicle Test\''),
|
||||
(37980, 0, 4, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 48, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Darnassus Love Boat - On Just Summoned - Set Active On'),
|
||||
(37980, 0, 5, 0, 1, 0, 100, 0, 0, 0, 3000, 3000, 0, 0, 75, 69341, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Darnassus Love Boat - Out of Combat - Add Aura \'Love Boat\''),
|
||||
(37980, 0, 6, 0, 23, 0, 100, 0, 69342, 2, 1000, 1000, 0, 0, 75, 69352, 0, 0, 0, 0, 0, 17, 0, 20, 0, 0, 0, 0, 0, 0, 'Darnassus Love Boat - On Aura \'Ride Vehicle\' - Add Aura \'Romantic\''),
|
||||
(37980, 0, 7, 0, 28, 0, 100, 0, 0, 0, 0, 0, 0, 0, 28, 69352, 0, 0, 0, 0, 0, 17, 0, 20, 0, 0, 0, 0, 0, 0, 'Darnassus Love Boat - On Passenger Removed - Remove Aura \'Romantic\''),
|
||||
(36817, 0, 0, 0, 1, 0, 100, 0, 0, 0, 20000, 20000, 0, 0, 11, 69371, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, '[DND] Love Boat Summoner - Out of Combat - Cast \'Love Boat Summon\''),
|
||||
(36817, 0, 1, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 48, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, '[DND] Love Boat Summoner - On Respawn - Set Active On'),
|
||||
(37964, 0, 0, 0, 1, 0, 100, 0, 0, 0, 20000, 20000, 0, 0, 11, 70846, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, '[DND] Love Boat Summoner 02 - Out of Combat - Cast \'Love Boat Summon\''),
|
||||
(37964, 0, 1, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 48, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, '[DND] Love Boat Summoner 02 - On Respawn - Set Active On'),
|
||||
(37981, 0, 0, 0, 1, 0, 100, 0, 0, 0, 20000, 20000, 0, 0, 11, 70863, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, '[DND] Love Boat Summoner 03 - Out of Combat - Cast \'Love Boat Summon\''),
|
||||
(37981, 0, 1, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 48, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, '[DND] Love Boat Summoner 03 - On Respawn - Set Active On');
|
||||
|
||||
DELETE FROM `npc_spellclick_spells` WHERE `npc_entry` IN (37966,37980,36812);
|
||||
INSERT INTO `npc_spellclick_spells` (`npc_entry`, `spell_id`, `cast_flags`, `user_type`) VALUES
|
||||
(37966, 69342, 1, 0),
|
||||
(37980, 69342, 1, 0),
|
||||
(36812, 69342, 1, 0);
|
||||
|
||||
DELETE FROM `waypoints` WHERE `entry` IN (37966,37980,36812);
|
||||
INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES
|
||||
(37966, 1, 1485.332, 348.7621, -64.54687, 'Undercity Love Boat'),
|
||||
(37966, 2, 1487.063, 350.9445, -64.86743, 'Undercity Love Boat'),
|
||||
(37966, 3, 1494.434, 360.592, -64.86742, 'Undercity Love Boat'),
|
||||
(37966, 4, 1505.792, 368.026, -64.81186, 'Undercity Love Boat'),
|
||||
(37966, 5, 1520.413, 376.7361, -64.81187, 'Undercity Love Boat'),
|
||||
(37966, 6, 1542.724, 389.7309, -64.81187, 'Undercity Love Boat'),
|
||||
(37966, 7, 1555.352, 393.1875, -64.81187, 'Undercity Love Boat'),
|
||||
(37966, 8, 1577.076, 397.1563, -64.81187, 'Undercity Love Boat'),
|
||||
(37966, 9, 1618.071, 395.9705, -64.81187, 'Undercity Love Boat'),
|
||||
(37966, 10, 1642.727, 391.0139, -64.81187, 'Undercity Love Boat'),
|
||||
(37966, 11, 1685.007, 370.4167, -64.81187, 'Undercity Love Boat'),
|
||||
(37966, 12, 1711.104, 350.4514, -64.81187, 'Undercity Love Boat'),
|
||||
(37966, 13, 1738.417, 310.0278, -64.81187, 'Undercity Love Boat'),
|
||||
(37966, 14, 1746.345, 286.441, -64.81187, 'Undercity Love Boat'),
|
||||
(37966, 15, 1752.087, 240.5399, -64.81187, 'Undercity Love Boat'),
|
||||
(37966, 16, 1750.016, 206.7309, -64.81187, 'Undercity Love Boat'),
|
||||
(37966, 17, 1737.47, 167.8559, -64.81187, 'Undercity Love Boat'),
|
||||
(37966, 18, 1707.885, 128.5122, -64.81187, 'Undercity Love Boat'),
|
||||
(37966, 19, 1667.977, 99.80035, -64.81187, 'Undercity Love Boat'),
|
||||
(37966, 20, 1624.948, 85.43229, -64.81187, 'Undercity Love Boat'),
|
||||
(37966, 21, 1583.814, 83.33507, -64.81187, 'Undercity Love Boat'),
|
||||
(37966, 22, 1539.444, 94.43403, -64.81187, 'Undercity Love Boat'),
|
||||
(37966, 23, 1502.849, 114.3142, -64.81187, 'Undercity Love Boat'),
|
||||
(37966, 24, 1482.955, 132.6806, -64.81187, 'Undercity Love Boat'),
|
||||
(37966, 25, 1456.214, 170.0521, -64.81187, 'Undercity Love Boat'),
|
||||
(37966, 26, 1441.738, 207.8819, -64.81187, 'Undercity Love Boat'),
|
||||
(37966, 27, 1438.825, 244.4427, -64.81187, 'Undercity Love Boat'),
|
||||
(37966, 28, 1450.882, 299.3177, -64.81187, 'Undercity Love Boat'),
|
||||
(37966, 29, 1462.38, 320.4583, -64.81187, 'Undercity Love Boat'),
|
||||
(37966, 30, 1467.97, 333.1337, -64.81187, 'Undercity Love Boat'),
|
||||
(37966, 31, 1471.193, 337.8559, -64.81187, 'Undercity Love Boat'),
|
||||
(37980, 1, 9843.134, 2430.733, 1313.6, 'Darnassus Love Boat'),
|
||||
(37980, 2, 9847.023, 2427.627, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 3, 9856.224, 2423.156, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 4, 9871.393, 2416.719, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 5, 9888.688, 2408.337, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 6, 9901.832, 2399.545, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 7, 9915.912, 2390.616, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 8, 9930.722, 2381.382, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 9, 9946.339, 2377.861, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 10, 9964.972, 2377.967, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 11, 9977.46, 2379.141, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 12, 9989.397, 2375.556, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 13, 10006.68, 2364.491, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 14, 10022.01, 2353.608, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 15, 10031.78, 2353.427, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 16, 10041.6, 2366.207, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 17, 10043.1, 2373.267, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 18, 10040.94, 2384.248, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 19, 10040.11, 2396.392, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 20, 10043.54, 2406.759, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 21, 10051.08, 2414.868, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 22, 10059.58, 2421.014, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 23, 10061.45, 2433.856, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 24, 10056.65, 2445.88, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 25, 10049.1, 2453.844, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 26, 10039.64, 2458.193, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 27, 10030.21, 2461.353, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 28, 10013.85, 2465.007, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 29, 10007.3, 2472.648, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 30, 10001.77, 2490.97, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 31, 10007.02, 2503.859, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 32, 10014.66, 2519.925, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 33, 10022.5, 2532.248, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 34, 10032.06, 2559.106, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 35, 10032.88, 2579.188, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 36, 10032.36, 2598.909, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 37, 10029.7, 2612.815, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 38, 10022.64, 2648.693, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 39, 9999.638, 2667.306, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 40, 9985.304, 2673.353, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 41, 9967.442, 2671.7, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 42, 9938.718, 2668.114, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 43, 9898.393, 2665.895, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 44, 9874.026, 2660.383, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 45, 9848.894, 2657.903, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 46, 9834.57, 2658.452, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 47, 9820.689, 2652.576, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 48, 9802.497, 2636.835, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 49, 9795.239, 2622.99, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 50, 9785.92, 2605.789, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 51, 9784.899, 2593.911, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 52, 9793.405, 2574.175, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 53, 9812.471, 2555.666, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 54, 9829.779, 2539.537, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 55, 9841.714, 2520.574, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 56, 9847.395, 2499.439, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 57, 9850.591, 2481.936, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 58, 9846.033, 2466.465, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 59, 9838.938, 2451.995, 1313.516, 'Darnassus Love Boat'),
|
||||
(37980, 60, 9833.917, 2446.236, 1313.516, 'Darnassus Love Boat'),
|
||||
(36812, 1, -8795.021, 775.0364, 95.22309, 'Stormwind Love Boat'),
|
||||
(36812, 2, -8791.573, 776.316, 95.0583, 'Stormwind Love Boat'),
|
||||
(36812, 3, -8783.189, 778.1111, 95.0583, 'Stormwind Love Boat'),
|
||||
(36812, 4, -8769.04, 777.9063, 95.0583, 'Stormwind Love Boat'),
|
||||
(36812, 5, -8757.161, 764.092, 95.0583, 'Stormwind Love Boat'),
|
||||
(36812, 6, -8750.976, 741.6354, 95.08608, 'Stormwind Love Boat'),
|
||||
(36812, 7, -8733.618, 717.3299, 95.08608, 'Stormwind Love Boat'),
|
||||
(36812, 8, -8717.854, 698.5886, 95.0583, 'Stormwind Love Boat'),
|
||||
(36812, 9, -8698.192, 662.2465, 95.0583, 'Stormwind Love Boat'),
|
||||
(36812, 10, -8688.56, 630.1719, 95.11386, 'Stormwind Love Boat'),
|
||||
(36812, 11, -8696.212, 596.9983, 95.08608, 'Stormwind Love Boat'),
|
||||
(36812, 12, -8702.024, 577.2761, 95.0583, 'Stormwind Love Boat'),
|
||||
(36812, 13, -8691.561, 565.0538, 95.0583, 'Stormwind Love Boat'),
|
||||
(36812, 14, -8671.857, 565.382, 95.0583, 'Stormwind Love Boat'),
|
||||
(36812, 15, -8646.634, 563.7743, 95.0583, 'Stormwind Love Boat'),
|
||||
(36812, 16, -8631.895, 554.441, 95.0583, 'Stormwind Love Boat'),
|
||||
(36812, 17, -8618.281, 557.4114, 95.0583, 'Stormwind Love Boat'),
|
||||
(36812, 18, -8608.049, 577.191, 95.0583, 'Stormwind Love Boat'),
|
||||
(36812, 19, -8602.768, 595.4983, 95.0583, 'Stormwind Love Boat'),
|
||||
(36812, 20, -8594.357, 623.566, 95.0583, 'Stormwind Love Boat'),
|
||||
(36812, 21, -8581.717, 629.7882, 95.08608, 'Stormwind Love Boat');
|
||||
@@ -0,0 +1,5 @@
|
||||
-- DB update 2024_09_24_00 -> 2024_09_24_01
|
||||
--
|
||||
DELETE FROM `spell_script_names` WHERE `spell_id` = 36092;
|
||||
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
|
||||
(36092, 'spell_kaelthas_kael_explodes');
|
||||
@@ -0,0 +1,3 @@
|
||||
-- DB update 2024_09_24_01 -> 2024_09_25_00
|
||||
--
|
||||
UPDATE `creature_template` SET `flags_extra` = `flags_extra`|512 WHERE `entry` = 22917;
|
||||
@@ -0,0 +1,30 @@
|
||||
-- DB update 2024_09_25_00 -> 2024_09_25_01
|
||||
--
|
||||
DELETE FROM `smart_scripts` WHERE `entryorguid`=24077 AND `source_type`=0;
|
||||
DELETE FROM `smart_scripts` WHERE `entryorguid`=2407700 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`, `event_param5`, `event_param6`, `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
|
||||
(24077, 0, 0, 0, 11, 0, 100, 0, 0, 0, 0, 0, 0, 0, 50, 186565, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Impaled Valgarde Scout - On Repawn - Summon Ceremonial Dragonflayer Harpoon'),
|
||||
(24077, 0, 1, 0, 8, 0, 100, 1, 42968, 0, 0, 0, 0, 0, 80, 2407700, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Impaled Valgarde Scout - On spell hit - Start Script'),
|
||||
(2407700, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 99, 3, 0, 0, 0, 0, 0, 20, 186565, 10, 0, 0, 0, 0, 0, 0, 'Impaled Valgarde Scout - On Script - Set loot state'),
|
||||
(2407700, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Impaled Valgarde Scout - On Script - Talk 0'),
|
||||
(2407700, 9, 2, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 0, 0, 91, 255, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Impaled Valgarde Scout - On Script - Remove Bytes '),
|
||||
(2407700, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 90, 8, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Impaled Valgarde Scout - On Script - Set Bytes 1'),
|
||||
(2407700, 9, 4, 0, 0, 0, 100, 0, 1000, 1000, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Impaled Valgarde Scout - On Script - Talk 1'),
|
||||
(2407700, 9, 5, 0, 0, 0, 100, 0, 4000, 4000, 0, 0, 0, 0, 37, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Impaled Valgarde Scout - On Script - Kill Self'),
|
||||
(2407700, 9, 6, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 5000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Impaled Valgarde Scout - On Script - Despawn');
|
||||
|
||||
DELETE FROM `creature_text` WHERE `CreatureID`=24077;
|
||||
INSERT INTO `creature_text` (`CreatureID`, `GroupID`, `ID`, `Text`, `Type`, `Language`, `Probability`, `Emote`, `Duration`, `Sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
|
||||
(24077, 0, 0, '%s groans.', 16, 0, 100, 0, 0, 0, 22743, 0, 'Impaled Valgarde Scout'),
|
||||
(24077, 0, 1, '%s screams in agony as the harpoon is removed.', 16, 0, 100, 0, 0, 0, 22744, 0, 'Impaled Valgarde Scout'),
|
||||
(24077, 0, 2, '%s whimpers.', 16, 0, 100, 0, 0, 0, 22745, 0, 'Impaled Valgarde Scout'),
|
||||
(24077, 1, 0, 'Don\'t let my death go unavenged, stranger... give ... them... hell...', 12, 0, 100, 0, 0, 0, 22752, 0, 'Impaled Valgarde Scout'),
|
||||
(24077, 1, 1, 'I\'m done for... too much blood lost... Forget about me, tell Keller... People still alive inside...', 12, 0, 100, 0, 0, 0, 22749, 0, 'Impaled Valgarde Scout'),
|
||||
(24077, 1, 2, 'Not... no... Our people... Wrymskull... some live...', 12, 0, 100, 0, 0, 0, 22747, 0, 'Impaled Valgarde Scout'),
|
||||
(24077, 1, 3, 'My injuries are too great. I won\'t make it... Our citizenry held in cages... ritual...', 12, 0, 100, 0, 0, 0, 22748, 0, 'Impaled Valgarde Scout'),
|
||||
(24077, 1, 4, 'They left us here impaled as a warning to the others... Several still alive... prisoners of...', 12, 0, 100, 0, 0, 0, 22751, 0, 'Impaled Valgarde Scout'),
|
||||
(24077, 1, 5, 'My family must know... I... for them... always for them...', 12, 0, 100, 0, 0, 0, 22750, 0, 'Impaled Valgarde Scout');
|
||||
|
||||
DELETE FROM `gameobject` WHERE `id`=186565;
|
||||
|
||||
UPDATE `gameobject_template_locale` SET `castBarCaption`='Quitando' WHERE `entry`=186565 AND `locale` IN ('esES', 'esMX');
|
||||
@@ -0,0 +1,54 @@
|
||||
-- DB update 2024_09_25_01 -> 2024_09_25_02
|
||||
--
|
||||
UPDATE `creature_template` SET `flags_extra` = `flags_extra` | 2048 WHERE `entry` IN (
|
||||
3672, -- Boahn
|
||||
4403, -- Muckshell Pincer
|
||||
4540, -- Scarlet Monk
|
||||
7033, -- Firegut Ogre
|
||||
8218, -- Witherheart the Stalker
|
||||
10478, -- Splintered Skeleton
|
||||
10488, -- Risen Construct
|
||||
11022, -- Alexi Barov
|
||||
12100, -- Lava Reaver
|
||||
12262, -- Ziggurat Protector
|
||||
12263, -- Slaughterhouse Protector
|
||||
14688, -- Prince Sandoval
|
||||
14882, -- Atal'ai Mistress
|
||||
16299, -- Skeletal Shocktrooper
|
||||
16422, -- Skeletal Soldier
|
||||
16593, -- Shattered Hand Brawler
|
||||
16808, -- Warchief Kargath Bladefist
|
||||
16936, -- Dreghood Wanderer
|
||||
18120, -- Ango'rosh Mauler
|
||||
18211, -- Murkblood Brute
|
||||
18541, -- Urdak
|
||||
18860, -- Daughter of Destiny
|
||||
19191, -- Arazzius the Cruel
|
||||
20456, -- Ethereum Researcher
|
||||
20582, -- Shattered Hand Brawler (1)
|
||||
20597, -- Warchief Kargath Bladefist (1)
|
||||
20683, -- Prophetess Cavrylin
|
||||
20783, -- Porfus the Gem Gorger
|
||||
20784, -- Armbreaker Huffaz
|
||||
20785, -- Fel Tinkerer Zortan
|
||||
20786, -- Gul'bor
|
||||
20790, -- Malevus the Mad
|
||||
20929, -- Wrath Lord
|
||||
20984, -- Protectorate Defender
|
||||
21639, -- Illidari Slayer
|
||||
21717, -- Dragonmaw Wrangler
|
||||
21805, -- Protectorate Avenger
|
||||
21877, -- Karsius the Ancient Watcher
|
||||
22004, -- Leoroxx
|
||||
22076, -- Torloth the Magnificent
|
||||
22082, -- Shadowmoon Slayer
|
||||
22199, -- Slaag
|
||||
22377, -- Akuno
|
||||
22825, -- Matron Li-sahar
|
||||
23008, -- Ethereum Jailor
|
||||
23410, -- Spirit of Udalo
|
||||
23411, -- Spirit of Olum
|
||||
24882, -- Brutallus
|
||||
37132, -- Ymirjar Battle-Maiden
|
||||
38132 -- Ymirjar Battle-Maiden (1)
|
||||
);
|
||||
@@ -0,0 +1,6 @@
|
||||
-- DB update 2024_09_25_02 -> 2024_09_25_03
|
||||
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 21806;
|
||||
|
||||
DELETE FROM `smart_scripts` WHERE (`entryorguid` = 21806) AND (`source_type` = 0) AND (`id` IN (2));
|
||||
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`, `event_param6`, `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
|
||||
(21806, 0, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 39, 20, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Greyheart Spellbinder - In Combat - Call For Help');
|
||||
@@ -0,0 +1,2 @@
|
||||
-- DB update 2024_09_25_03 -> 2024_09_26_00
|
||||
UPDATE `creature_template` SET `unit_flags` = `unit_flags`|33554432|32768|512|256 WHERE `entry` = 21812;
|
||||
@@ -0,0 +1,15 @@
|
||||
-- DB update 2024_09_26_00 -> 2024_09_27_00
|
||||
--
|
||||
UPDATE `gossip_menu_option` SET `OptionBroadcastTextID`=5316 WHERE `MenuID`=2849 AND `OptionID`=0;
|
||||
UPDATE `gossip_menu_option` SET `OptionBroadcastTextID`=10359 WHERE `MenuID`=2849 AND `OptionID`=4;
|
||||
UPDATE `gossip_menu_option` SET `OptionBroadcastTextID`=2870 WHERE `MenuID`=2849 AND `OptionID`=5;
|
||||
UPDATE `gossip_menu_option` SET `OptionBroadcastTextID`=4895 WHERE `MenuID`=2849 AND `OptionID`=8;
|
||||
UPDATE `gossip_menu_option` SET `OptionBroadcastTextID`=7253 WHERE `MenuID`=2849 AND `OptionID`=10;
|
||||
UPDATE `gossip_menu_option` SET `OptionBroadcastTextID`=5518 WHERE `MenuID`=2849 AND `OptionID`=11;
|
||||
UPDATE `gossip_menu_option` SET `OptionBroadcastTextID`=5316 WHERE `MenuID`=7633 AND `OptionID`=0;
|
||||
UPDATE `gossip_menu_option` SET `OptionBroadcastTextID`=2870 WHERE `MenuID`=7633 AND `OptionID`=3;
|
||||
UPDATE `gossip_menu_option` SET `OptionBroadcastTextID`=4895 WHERE `MenuID`=7633 AND `OptionID`=5;
|
||||
UPDATE `gossip_menu_option` SET `OptionBroadcastTextID`=7253 WHERE `MenuID`=7633 AND `OptionID`=7;
|
||||
UPDATE `gossip_menu_option` SET `OptionBroadcastTextID`=2870 WHERE `MenuID`=8185 AND `OptionID`=1;
|
||||
UPDATE `gossip_menu_option` SET `OptionBroadcastTextID`=4895 WHERE `MenuID`=8357 AND `OptionID`=4;
|
||||
UPDATE `gossip_menu_option` SET `OptionBroadcastTextID`=10359 WHERE `MenuID`=8357 AND `OptionID`=6;
|
||||
@@ -0,0 +1,11 @@
|
||||
-- DB update 2024_09_27_00 -> 2024_09_28_00
|
||||
--
|
||||
UPDATE `creature_template` SET `flags_extra` = `flags_extra` & ~2048 WHERE `entry` IN (
|
||||
3672, -- Boahn
|
||||
20783, -- Porfus the Gem Gorger
|
||||
21639, -- Illidari Slayer
|
||||
21717, -- Dragonmaw Wrangler
|
||||
12100, -- Lava Reaver
|
||||
22076, -- Torloth the Magnificent
|
||||
22004 -- Leoroxx
|
||||
);
|
||||
@@ -0,0 +1,3 @@
|
||||
-- DB update 2024_09_28_00 -> 2024_09_28_01
|
||||
--
|
||||
UPDATE `creature_template` SET `mechanic_immune_mask` = `mechanic_immune_mask` & ~2048 WHERE (`entry` = 22056);
|
||||
@@ -0,0 +1,3 @@
|
||||
-- DB update 2024_09_28_01 -> 2024_09_28_02
|
||||
DELETE FROM `skill_extra_item_template` WHERE `spellId` = 28551;
|
||||
INSERT INTO `skill_extra_item_template` (`spellId`, `requiredSpecialization`, `additionalCreateChance`, `additionalMaxNum`) VALUES (28551, 28675, 14, 4);
|
||||
@@ -3675,6 +3675,13 @@ Battleground.BerserkingBuffRespawn = 120
|
||||
|
||||
Battleground.SpeedBuffRespawn = 150
|
||||
|
||||
#
|
||||
# Battleground.Override.LowLevels.MinPlayers
|
||||
# Description: Overrides the minimum number of required players per team for all levels < MaxPlayerLevel
|
||||
# Default: 0 (Disabled)
|
||||
|
||||
Battleground.Override.LowLevels.MinPlayers = 0
|
||||
|
||||
#
|
||||
###################################################################################################
|
||||
|
||||
|
||||
@@ -188,7 +188,7 @@ bool MySQLConnection::Execute(std::string_view sql)
|
||||
LOG_INFO("sql.sql", "SQL: {}", sql);
|
||||
LOG_ERROR("sql.sql", "[{}] {}", lErrno, mysql_error(m_Mysql));
|
||||
|
||||
if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||
if (_HandleMySQLErrno(lErrno, mysql_error(m_Mysql))) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||
return Execute(sql); // Try again
|
||||
|
||||
return false;
|
||||
@@ -226,7 +226,7 @@ bool MySQLConnection::Execute(PreparedStatementBase* stmt)
|
||||
uint32 lErrno = mysql_errno(m_Mysql);
|
||||
LOG_ERROR("sql.sql", "SQL(p): {}\n [ERROR]: [{}] {}", m_mStmt->getQueryString(), lErrno, mysql_stmt_error(msql_STMT));
|
||||
|
||||
if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||
if (_HandleMySQLErrno(lErrno, mysql_stmt_error(msql_STMT))) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||
return Execute(stmt); // Try again
|
||||
|
||||
m_mStmt->ClearParameters();
|
||||
@@ -238,7 +238,7 @@ bool MySQLConnection::Execute(PreparedStatementBase* stmt)
|
||||
uint32 lErrno = mysql_errno(m_Mysql);
|
||||
LOG_ERROR("sql.sql", "SQL(p): {}\n [ERROR]: [{}] {}", m_mStmt->getQueryString(), lErrno, mysql_stmt_error(msql_STMT));
|
||||
|
||||
if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||
if (_HandleMySQLErrno(lErrno, mysql_stmt_error(msql_STMT))) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||
return Execute(stmt); // Try again
|
||||
|
||||
m_mStmt->ClearParameters();
|
||||
@@ -278,7 +278,7 @@ bool MySQLConnection::_Query(PreparedStatementBase* stmt, MySQLPreparedStatement
|
||||
uint32 lErrno = mysql_errno(m_Mysql);
|
||||
LOG_ERROR("sql.sql", "SQL(p): {}\n [ERROR]: [{}] {}", m_mStmt->getQueryString(), lErrno, mysql_stmt_error(msql_STMT));
|
||||
|
||||
if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||
if (_HandleMySQLErrno(lErrno, mysql_stmt_error(msql_STMT))) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||
return _Query(stmt, mysqlStmt, pResult, pRowCount, pFieldCount); // Try again
|
||||
|
||||
m_mStmt->ClearParameters();
|
||||
@@ -290,7 +290,7 @@ bool MySQLConnection::_Query(PreparedStatementBase* stmt, MySQLPreparedStatement
|
||||
uint32 lErrno = mysql_errno(m_Mysql);
|
||||
LOG_ERROR("sql.sql", "SQL(p): {}\n [ERROR]: [{}] {}", m_mStmt->getQueryString(), lErrno, mysql_stmt_error(msql_STMT));
|
||||
|
||||
if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||
if (_HandleMySQLErrno(lErrno, mysql_stmt_error(msql_STMT))) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||
return _Query(stmt, mysqlStmt, pResult, pRowCount, pFieldCount); // Try again
|
||||
|
||||
m_mStmt->ClearParameters();
|
||||
@@ -338,7 +338,7 @@ bool MySQLConnection::_Query(std::string_view sql, MySQLResult** pResult, MySQLF
|
||||
LOG_INFO("sql.sql", "SQL: {}", sql);
|
||||
LOG_ERROR("sql.sql", "[{}] {}", lErrno, mysql_error(m_Mysql));
|
||||
|
||||
if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||
if (_HandleMySQLErrno(lErrno, mysql_error(m_Mysql))) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||
return _Query(sql, pResult, pFields, pRowCount, pFieldCount); // We try again
|
||||
|
||||
return false;
|
||||
@@ -553,8 +553,9 @@ PreparedResultSet* MySQLConnection::Query(PreparedStatementBase* stmt)
|
||||
return new PreparedResultSet(mysqlStmt->GetSTMT(), result, rowCount, fieldCount);
|
||||
}
|
||||
|
||||
bool MySQLConnection::_HandleMySQLErrno(uint32 errNo, uint8 attempts /*= 5*/)
|
||||
bool MySQLConnection::_HandleMySQLErrno(uint32 errNo, char const* err, uint8 attempts /*= 5*/)
|
||||
{
|
||||
std::string str = "";
|
||||
switch (errNo)
|
||||
{
|
||||
case CR_SERVER_GONE_ERROR:
|
||||
@@ -582,9 +583,10 @@ bool MySQLConnection::_HandleMySQLErrno(uint32 errNo, uint8 attempts /*= 5*/)
|
||||
// Don't remove 'this' pointer unless you want to skip loading all prepared statements...
|
||||
if (!this->PrepareStatements())
|
||||
{
|
||||
LOG_FATAL("sql.sql", "Could not re-prepare statements!");
|
||||
str = "Could not re-prepare statements!";
|
||||
LOG_FATAL("sql.sql", "{}", str);
|
||||
std::this_thread::sleep_for(10s);
|
||||
ABORT();
|
||||
ABORT("{}\n\n[{}] {}", str, errNo, err);
|
||||
}
|
||||
|
||||
LOG_INFO("sql.sql", "Successfully reconnected to {} @{}:{} ({}).",
|
||||
@@ -599,19 +601,21 @@ bool MySQLConnection::_HandleMySQLErrno(uint32 errNo, uint8 attempts /*= 5*/)
|
||||
{
|
||||
// Shut down the server when the mysql server isn't
|
||||
// reachable for some time
|
||||
LOG_FATAL("sql.sql", "Failed to reconnect to the MySQL server, terminating the server to prevent data corruption!");
|
||||
str = "Failed to reconnect to the MySQL server, terminating the server to prevent data corruption!";
|
||||
LOG_FATAL("sql.sql", "{}", str);
|
||||
|
||||
// We could also initiate a shutdown through using std::raise(SIGTERM)
|
||||
std::this_thread::sleep_for(10s);
|
||||
ABORT();
|
||||
ABORT("{}\n\n[{}] {}", str, errNo, err);
|
||||
}
|
||||
else
|
||||
{
|
||||
// It's possible this attempted reconnect throws 2006 at us.
|
||||
// To prevent crazy recursive calls, sleep here.
|
||||
std::this_thread::sleep_for(3s); // Sleep 3 seconds
|
||||
return _HandleMySQLErrno(lErrno, attempts); // Call self (recursive)
|
||||
return _HandleMySQLErrno(lErrno, mysql_error(m_Mysql), attempts); // Call self (recursive)
|
||||
}
|
||||
[[fallthrough]];
|
||||
}
|
||||
|
||||
case ER_LOCK_DEADLOCK:
|
||||
@@ -625,14 +629,16 @@ bool MySQLConnection::_HandleMySQLErrno(uint32 errNo, uint8 attempts /*= 5*/)
|
||||
// Outdated table or database structure - terminate core
|
||||
case ER_BAD_FIELD_ERROR:
|
||||
case ER_NO_SUCH_TABLE:
|
||||
LOG_ERROR("sql.sql", "Your database structure is not up to date. Please make sure you've executed all queries in the sql/updates folders.");
|
||||
str = "Your database structure is not up to date. Please make sure you've executed all queries in the sql/updates folders.";
|
||||
LOG_FATAL("sql.sql", "{}", str);
|
||||
std::this_thread::sleep_for(10s);
|
||||
ABORT();
|
||||
ABORT("{}\n\n[{}] {}", str, errNo, err);
|
||||
return false;
|
||||
case ER_PARSE_ERROR:
|
||||
LOG_ERROR("sql.sql", "Error while parsing SQL. Core fix required.");
|
||||
str = "Error while parsing SQL. Core fix required.";
|
||||
LOG_FATAL("sql.sql", "{}", str);
|
||||
std::this_thread::sleep_for(10s);
|
||||
ABORT();
|
||||
ABORT("{}\n\n[{}] {}", str, errNo, err);
|
||||
return false;
|
||||
default:
|
||||
LOG_ERROR("sql.sql", "Unhandled MySQL errno {}. Unexpected behaviour possible.", errNo);
|
||||
|
||||
@@ -99,7 +99,7 @@ protected:
|
||||
void PrepareStatement(uint32 index, std::string_view sql, ConnectionFlags flags);
|
||||
|
||||
virtual void DoPrepareStatements() = 0;
|
||||
virtual bool _HandleMySQLErrno(uint32 errNo, uint8 attempts = 5);
|
||||
virtual bool _HandleMySQLErrno(uint32 errNo, char const* err = "", uint8 attempts = 5);
|
||||
|
||||
typedef std::vector<std::unique_ptr<MySQLPreparedStatement>> PreparedStatementContainer;
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ void UnitAI::DoMeleeAttackIfReady()
|
||||
if (me->isAttackReady())
|
||||
{
|
||||
// xinef: prevent base and off attack in same time, delay attack at 0.2 sec
|
||||
if (me->haveOffhandWeapon())
|
||||
if (me->HasOffhandWeaponForAttack())
|
||||
if (me->getAttackTimer(OFF_ATTACK) < ATTACK_DISPLAY_DELAY)
|
||||
me->setAttackTimer(OFF_ATTACK, ATTACK_DISPLAY_DELAY);
|
||||
|
||||
@@ -60,7 +60,7 @@ void UnitAI::DoMeleeAttackIfReady()
|
||||
me->resetAttackTimer();
|
||||
}
|
||||
|
||||
if (me->haveOffhandWeapon() && me->isAttackReady(OFF_ATTACK))
|
||||
if (me->HasOffhandWeaponForAttack() && me->isAttackReady(OFF_ATTACK))
|
||||
{
|
||||
// xinef: delay main hand attack if both will hit at the same time (players code)
|
||||
if (me->getAttackTimer(BASE_ATTACK) < ATTACK_DISPLAY_DELAY)
|
||||
|
||||
@@ -522,17 +522,33 @@ void ScriptedAI::SetEquipmentSlots(bool loadDefault, int32 mainHand /*= EQUIP_NO
|
||||
if (loadDefault)
|
||||
{
|
||||
me->LoadEquipment(me->GetOriginalEquipmentId(), true);
|
||||
if (me->HasWeapon(OFF_ATTACK))
|
||||
me->SetCanDualWield(true);
|
||||
else
|
||||
me->SetCanDualWield(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mainHand >= 0)
|
||||
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(mainHand));
|
||||
{
|
||||
me->SetVirtualItem(0, uint32(mainHand));
|
||||
me->UpdateDamagePhysical(BASE_ATTACK);
|
||||
}
|
||||
|
||||
if (offHand >= 0)
|
||||
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(offHand));
|
||||
{
|
||||
me->SetVirtualItem(1, uint32(offHand));
|
||||
if (offHand >= 1)
|
||||
me->SetCanDualWield(true);
|
||||
else
|
||||
me->SetCanDualWield(false);
|
||||
}
|
||||
|
||||
if (ranged >= 0)
|
||||
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2, uint32(ranged));
|
||||
{
|
||||
me->SetVirtualItem(2, uint32(ranged));
|
||||
me->UpdateDamagePhysical(RANGED_ATTACK);
|
||||
}
|
||||
}
|
||||
|
||||
enum eNPCs
|
||||
|
||||
@@ -146,6 +146,7 @@ Battleground::Battleground()
|
||||
m_LastResurrectTime = 0;
|
||||
m_ArenaType = 0;
|
||||
m_IsArena = false;
|
||||
m_IsTemplate = true;
|
||||
m_WinnerId = PVP_TEAM_NEUTRAL;
|
||||
m_StartTime = 0;
|
||||
m_ResetStatTimer = 0;
|
||||
@@ -1006,6 +1007,10 @@ void Battleground::RemovePlayerAtLeave(Player* player)
|
||||
// BG subclass specific code
|
||||
RemovePlayer(player);
|
||||
|
||||
// should remove spirit of redemption
|
||||
if (player->HasAuraType(SPELL_AURA_SPIRIT_OF_REDEMPTION))
|
||||
player->RemoveAurasByType(SPELL_AURA_MOD_SHAPESHIFT);
|
||||
|
||||
// if the player was a match participant
|
||||
if (participant)
|
||||
{
|
||||
@@ -1049,9 +1054,6 @@ void Battleground::RemovePlayerAtLeave(Player* player)
|
||||
}
|
||||
}
|
||||
|
||||
// Remove shapeshift auras
|
||||
player->RemoveAurasByType(SPELL_AURA_MOD_SHAPESHIFT);
|
||||
|
||||
player->SetBattlegroundId(0, BATTLEGROUND_TYPE_NONE, PLAYER_MAX_BATTLEGROUND_QUEUES, false, false, TEAM_NEUTRAL);
|
||||
|
||||
// Xinef: remove all criterias on bg leave
|
||||
@@ -1821,6 +1823,7 @@ GraveyardStruct const* Battleground::GetClosestGraveyard(Player* player)
|
||||
|
||||
void Battleground::SetBracket(PvPDifficultyEntry const* bracketEntry)
|
||||
{
|
||||
m_IsTemplate = false;
|
||||
m_BracketId = bracketEntry->GetBracketId();
|
||||
SetLevelRange(bracketEntry->minLevel, bracketEntry->maxLevel);
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "DBCEnums.h"
|
||||
#include "GameObject.h"
|
||||
#include "SharedDefines.h"
|
||||
#include "World.h"
|
||||
|
||||
class Creature;
|
||||
class GameObject;
|
||||
@@ -47,11 +48,15 @@ struct GraveyardStruct;
|
||||
|
||||
enum BattlegroundDesertionType : uint8
|
||||
{
|
||||
BG_DESERTION_TYPE_LEAVE_BG = 0, // player leaves the BG
|
||||
BG_DESERTION_TYPE_OFFLINE = 1, // player is kicked from BG because offline
|
||||
BG_DESERTION_TYPE_LEAVE_QUEUE = 2, // player is invited to join and refuses to do it
|
||||
BG_DESERTION_TYPE_NO_ENTER_BUTTON = 3, // player is invited to join and do nothing (time expires)
|
||||
BG_DESERTION_TYPE_INVITE_LOGOUT = 4, // player is invited to join and logs out
|
||||
BG_DESERTION_TYPE_LEAVE_BG = 0, // player leaves the BG
|
||||
BG_DESERTION_TYPE_OFFLINE = 1, // player is kicked from BG because offline
|
||||
BG_DESERTION_TYPE_LEAVE_QUEUE = 2, // player is invited to join and refuses to do it
|
||||
BG_DESERTION_TYPE_NO_ENTER_BUTTON = 3, // player is invited to join and do nothing (time expires)
|
||||
BG_DESERTION_TYPE_INVITE_LOGOUT = 4, // player is invited to join and logs out
|
||||
ARENA_DESERTION_TYPE_LEAVE_BG = 5, // player leaves the Arena
|
||||
ARENA_DESERTION_TYPE_LEAVE_QUEUE = 6, // player is invited to join arena and refuses to do it
|
||||
ARENA_DESERTION_TYPE_NO_ENTER_BUTTON = 7, // player is invited to join arena and do nothing (time expires)
|
||||
ARENA_DESERTION_TYPE_INVITE_LOGOUT = 8, // player is invited to join arena and logs out
|
||||
};
|
||||
|
||||
enum BattlegroundMaps
|
||||
@@ -334,8 +339,20 @@ public:
|
||||
[[nodiscard]] uint32 GetMinLevel() const { return m_LevelMin; }
|
||||
[[nodiscard]] uint32 GetMaxLevel() const { return m_LevelMax; }
|
||||
|
||||
[[nodiscard]] bool isTemplate() const { return m_IsTemplate; }
|
||||
[[nodiscard]] bool isMaxLevel() const
|
||||
{
|
||||
// NOTE: this only works when the BG is not a template but the real BG
|
||||
auto maxPlayerLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL);
|
||||
return GetMinLevel() <= maxPlayerLevel && maxPlayerLevel <= GetMaxLevel();
|
||||
}
|
||||
|
||||
[[nodiscard]] uint32 GetMaxPlayersPerTeam() const { return m_MaxPlayersPerTeam; }
|
||||
[[nodiscard]] uint32 GetMinPlayersPerTeam() const { return m_MinPlayersPerTeam; }
|
||||
[[nodiscard]] uint32 GetMinPlayersPerTeam() const
|
||||
{
|
||||
auto lowLevelsOverride = sWorld->getIntConfig(CONFIG_BATTLEGROUND_OVERRIDE_LOWLEVELS_MINPLAYERS);
|
||||
return (lowLevelsOverride && !isTemplate() && !isMaxLevel() && !isArena()) ? lowLevelsOverride : m_MinPlayersPerTeam;
|
||||
}
|
||||
|
||||
[[nodiscard]] int32 GetStartDelayTime() const { return m_StartDelayTime; }
|
||||
[[nodiscard]] uint8 GetArenaType() const { return m_ArenaType; }
|
||||
@@ -655,6 +672,7 @@ private:
|
||||
bool _InBGFreeSlotQueue{ false }; // used to make sure that BG is only once inserted into the BattlegroundMgr.BGFreeSlotQueue[bgTypeId] deque
|
||||
bool m_SetDeleteThis; // used for safe deletion of the bg after end / all players leave
|
||||
bool m_IsArena;
|
||||
bool m_IsTemplate;
|
||||
PvPTeamId m_WinnerId;
|
||||
int32 m_StartDelayTime;
|
||||
bool m_IsRated; // is this battle rated?
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
#include "ScriptMgr.h"
|
||||
#include <unordered_map>
|
||||
|
||||
#include "BattlegroundUtils.h"
|
||||
|
||||
/*********************************************************/
|
||||
/*** BATTLEGROUND QUEUE SYSTEM ***/
|
||||
/*********************************************************/
|
||||
@@ -760,7 +762,7 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 diff, BattlegroundTypeId
|
||||
}
|
||||
|
||||
// get min and max players per team
|
||||
uint32 MinPlayersPerTeam = bg_template->GetMinPlayersPerTeam();
|
||||
uint32 MinPlayersPerTeam = GetMinPlayersPerTeam(bg_template, bracketEntry);
|
||||
uint32 MaxPlayersPerTeam = bg_template->GetMaxPlayersPerTeam();
|
||||
|
||||
if (bg_template->isArena())
|
||||
@@ -996,7 +998,7 @@ void BattlegroundQueue::BattlegroundQueueAnnouncerUpdate(uint32 diff, Battlegrou
|
||||
_queueAnnouncementTimer[bracket_id] = -1;
|
||||
|
||||
auto bgName = bg_template->GetName();
|
||||
uint32 MaxPlayers = bg_template->GetMinPlayersPerTeam() * 2;
|
||||
uint32 MaxPlayers = GetMinPlayersPerTeam(bg_template, bracketEntry) * 2;
|
||||
uint32 q_min_level = std::min(bracketEntry->minLevel, (uint32) 80);
|
||||
uint32 q_max_level = std::min(bracketEntry->maxLevel, (uint32) 80);
|
||||
|
||||
@@ -1047,7 +1049,7 @@ void BattlegroundQueue::SendMessageBGQueue(Player* leader, Battleground* bg, PvP
|
||||
|
||||
BattlegroundBracketId bracketId = bracketEntry->GetBracketId();
|
||||
auto bgName = bg->GetName();
|
||||
uint32 MinPlayers = bg->GetMinPlayersPerTeam();
|
||||
uint32 MinPlayers = GetMinPlayersPerTeam(bg, bracketEntry);
|
||||
uint32 MaxPlayers = MinPlayers * 2;
|
||||
uint32 q_min_level = std::min(bracketEntry->minLevel, (uint32)80);
|
||||
uint32 q_max_level = std::min(bracketEntry->maxLevel, (uint32)80);
|
||||
@@ -1357,6 +1359,9 @@ bool BGQueueRemoveEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/)
|
||||
sScriptMgr->OnBattlegroundDesertion(player, BG_DESERTION_TYPE_NO_ENTER_BUTTON);
|
||||
}
|
||||
|
||||
if (bg && bg->isArena() && (bg->GetStatus() == STATUS_IN_PROGRESS || bg->GetStatus() == STATUS_WAIT_JOIN))
|
||||
sScriptMgr->OnBattlegroundDesertion(player, ARENA_DESERTION_TYPE_NO_ENTER_BUTTON);
|
||||
|
||||
LOG_DEBUG("bg.battleground", "Battleground: removing player {} from bg queue for instance {} because of not pressing enter battle in time.", player->GetGUID().ToString(), m_BgInstanceGUID);
|
||||
|
||||
player->RemoveBattlegroundQueueId(m_BgQueueTypeId);
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
#include "BattlegroundUtils.h"
|
||||
#include "World.h"
|
||||
|
||||
uint32 GetMinPlayersPerTeam(Battleground* bg, PvPDifficultyEntry const* bracketEntry)
|
||||
{
|
||||
// The problem addressed here is that methods such as bg->GetMinLevel() and bg->GetMaxLevel() have a different meaning
|
||||
// according to whether the BG is a template (then it's the value from the `battleground_template` table)
|
||||
// or if it's the real BG (then it's the specific bracket minimum level, e.g. "60" for "60-69").
|
||||
|
||||
if (!bg->isTemplate() || bg->isArena())
|
||||
{
|
||||
return bg->GetMinPlayersPerTeam();
|
||||
}
|
||||
|
||||
auto maxPlayerLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL);
|
||||
auto isMaxLevel = bracketEntry->minLevel <= maxPlayerLevel && maxPlayerLevel <= bracketEntry->maxLevel;
|
||||
auto lowLevelsOverride = sWorld->getIntConfig(CONFIG_BATTLEGROUND_OVERRIDE_LOWLEVELS_MINPLAYERS);
|
||||
|
||||
return (lowLevelsOverride && !isMaxLevel) ? lowLevelsOverride : bg->GetMinPlayersPerTeam();
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#ifndef BATTLEGROUNDUTILS_H
|
||||
#define BATTLEGROUNDUTILS_H
|
||||
|
||||
#include "Battleground.h"
|
||||
|
||||
uint32 GetMinPlayersPerTeam(Battleground* bg, PvPDifficultyEntry const* bracketEntry);
|
||||
|
||||
#endif // BATTLEGROUNDUTILS_H
|
||||
@@ -524,6 +524,8 @@ bool Creature::InitEntry(uint32 Entry, const CreatureData* data)
|
||||
|
||||
SetFloatValue(UNIT_FIELD_HOVERHEIGHT, cinfo->HoverHeight);
|
||||
|
||||
SetCanDualWield(cinfo->flags_extra & CREATURE_FLAG_EXTRA_USE_OFFHAND_ATTACK);
|
||||
|
||||
// checked at loading
|
||||
m_defaultMovementType = MovementGeneratorType(cinfo->MovementType);
|
||||
if (!m_wanderDistance && m_defaultMovementType == RANDOM_MOTION_TYPE)
|
||||
@@ -568,6 +570,8 @@ bool Creature::UpdateEntry(uint32 Entry, const CreatureData* data, bool changele
|
||||
|
||||
ReplaceAllDynamicFlags(dynamicflags);
|
||||
|
||||
SetCanDualWield(cInfo->flags_extra & CREATURE_FLAG_EXTRA_USE_OFFHAND_ATTACK);
|
||||
|
||||
SetAttackTime(BASE_ATTACK, cInfo->BaseAttackTime);
|
||||
SetAttackTime(OFF_ATTACK, cInfo->BaseAttackTime);
|
||||
SetAttackTime(RANGED_ATTACK, cInfo->RangeAttackTime);
|
||||
@@ -3173,6 +3177,14 @@ bool Creature::IsImmuneToKnockback() const
|
||||
return cinfo && (cinfo->flags_extra & CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK);
|
||||
}
|
||||
|
||||
bool Creature::HasWeapon(WeaponAttackType type) const
|
||||
{
|
||||
const uint8 slot = uint8(type);
|
||||
ItemEntry const* item = sItemStore.LookupEntry(GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + slot));
|
||||
|
||||
return ((item && item->ClassID == ITEM_CLASS_WEAPON) || (type == OFF_ATTACK && CanDualWield()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable or disable the creature's walk mode by removing: MOVEMENTFLAG_WALKING. Infom also the client
|
||||
*/
|
||||
|
||||
@@ -190,6 +190,8 @@ public:
|
||||
void UpdateAttackPowerAndDamage(bool ranged = false) override;
|
||||
void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, float& minDamage, float& maxDamage, uint8 damageIndex) override;
|
||||
|
||||
bool HasWeapon(WeaponAttackType type) const override;
|
||||
bool HasWeaponForAttack(WeaponAttackType type) const override { return (Unit::HasWeaponForAttack(type) && HasWeapon(type)); }
|
||||
void SetCanDualWield(bool value) override;
|
||||
[[nodiscard]] int8 GetOriginalEquipmentId() const { return m_originalEquipmentId; }
|
||||
uint8 GetCurrentEquipmentId() { return m_equipmentId; }
|
||||
|
||||
@@ -54,7 +54,7 @@ enum CreatureFlagsExtra : uint32
|
||||
CREATURE_FLAG_EXTRA_NO_TAUNT = 0x00000100, // creature is immune to taunt auras and 'attack me' effects
|
||||
CREATURE_FLAG_EXTRA_NO_MOVE_FLAGS_UPDATE = 0x00000200, // creature won't update movement flags
|
||||
CREATURE_FLAG_EXTRA_GHOST_VISIBILITY = 0x00000400, // creature will only be visible to dead players
|
||||
CREATURE_FLAG_EXTRA_UNUSED_12 = 0x00000800, /// @todo: Implement CREATURE_FLAG_EXTRA_USE_OFFHAND_ATTACK (creature will use offhand attacks)
|
||||
CREATURE_FLAG_EXTRA_USE_OFFHAND_ATTACK = 0x00000800, // creature will use offhand attacks
|
||||
CREATURE_FLAG_EXTRA_NO_SELL_VENDOR = 0x00001000, // players can't sell items to this vendor
|
||||
CREATURE_FLAG_EXTRA_IGNORE_COMBAT = 0x00002000,
|
||||
CREATURE_FLAG_EXTRA_WORLDEVENT = 0x00004000, // custom flag for world event creatures (left room for merging)
|
||||
@@ -77,9 +77,7 @@ enum CreatureFlagsExtra : uint32
|
||||
CREATURE_FLAG_EXTRA_HARD_RESET = 0x80000000,
|
||||
|
||||
// Masks
|
||||
CREATURE_FLAG_EXTRA_UNUSED = (CREATURE_FLAG_EXTRA_UNUSED_12), // SKIP
|
||||
|
||||
CREATURE_FLAG_EXTRA_DB_ALLOWED = (0xFFFFFFFF & ~(CREATURE_FLAG_EXTRA_UNUSED | CREATURE_FLAG_EXTRA_DUNGEON_BOSS)) // SKIP
|
||||
CREATURE_FLAG_EXTRA_DB_ALLOWED = (0xFFFFFFFF & ~CREATURE_FLAG_EXTRA_DUNGEON_BOSS) // SKIP
|
||||
};
|
||||
|
||||
enum class CreatureGroundMovementType : uint8
|
||||
|
||||
@@ -42,7 +42,7 @@ AC_API_EXPORT EnumText EnumUtils<CreatureFlagsExtra>::ToString(CreatureFlagsExtr
|
||||
case CREATURE_FLAG_EXTRA_NO_TAUNT: return { "CREATURE_FLAG_EXTRA_NO_TAUNT", "CREATURE_FLAG_EXTRA_NO_TAUNT", "creature is immune to taunt auras and 'attack me' effects" };
|
||||
case CREATURE_FLAG_EXTRA_NO_MOVE_FLAGS_UPDATE: return { "CREATURE_FLAG_EXTRA_NO_MOVE_FLAGS_UPDATE", "CREATURE_FLAG_EXTRA_NO_MOVE_FLAGS_UPDATE", "creature won't update movement flags" };
|
||||
case CREATURE_FLAG_EXTRA_GHOST_VISIBILITY: return { "CREATURE_FLAG_EXTRA_GHOST_VISIBILITY", "CREATURE_FLAG_EXTRA_GHOST_VISIBILITY", "creature will only be visible to dead players" };
|
||||
case CREATURE_FLAG_EXTRA_UNUSED_12: return { "CREATURE_FLAG_EXTRA_UNUSED_12", "CREATURE_FLAG_EXTRA_UNUSED_12", "/ @todo: Implement CREATURE_FLAG_EXTRA_USE_OFFHAND_ATTACK (creature will use offhand attacks)" };
|
||||
case CREATURE_FLAG_EXTRA_USE_OFFHAND_ATTACK: return { "CREATURE_FLAG_EXTRA_USE_OFFHAND_ATTACK", "CREATURE_FLAG_EXTRA_USE_OFFHAND_ATTACK", "/ @todo: Implement CREATURE_FLAG_EXTRA_USE_OFFHAND_ATTACK (creature will use offhand attacks)" };
|
||||
case CREATURE_FLAG_EXTRA_NO_SELL_VENDOR: return { "CREATURE_FLAG_EXTRA_NO_SELL_VENDOR", "CREATURE_FLAG_EXTRA_NO_SELL_VENDOR", "players can't sell items to this vendor" };
|
||||
case CREATURE_FLAG_EXTRA_IGNORE_COMBAT: return { "CREATURE_FLAG_EXTRA_IGNORE_COMBAT", "CREATURE_FLAG_EXTRA_IGNORE_COMBAT", "" };
|
||||
case CREATURE_FLAG_EXTRA_WORLDEVENT: return { "CREATURE_FLAG_EXTRA_WORLDEVENT", "CREATURE_FLAG_EXTRA_WORLDEVENT", "custom flag for world event creatures (left room for merging)" };
|
||||
@@ -86,7 +86,7 @@ AC_API_EXPORT CreatureFlagsExtra EnumUtils<CreatureFlagsExtra>::FromIndex(std::s
|
||||
case 8: return CREATURE_FLAG_EXTRA_NO_TAUNT;
|
||||
case 9: return CREATURE_FLAG_EXTRA_NO_MOVE_FLAGS_UPDATE;
|
||||
case 10: return CREATURE_FLAG_EXTRA_GHOST_VISIBILITY;
|
||||
case 11: return CREATURE_FLAG_EXTRA_UNUSED_12;
|
||||
case 11: return CREATURE_FLAG_EXTRA_USE_OFFHAND_ATTACK;
|
||||
case 12: return CREATURE_FLAG_EXTRA_NO_SELL_VENDOR;
|
||||
case 13: return CREATURE_FLAG_EXTRA_IGNORE_COMBAT;
|
||||
case 14: return CREATURE_FLAG_EXTRA_WORLDEVENT;
|
||||
@@ -127,7 +127,7 @@ AC_API_EXPORT std::size_t EnumUtils<CreatureFlagsExtra>::ToIndex(CreatureFlagsEx
|
||||
case CREATURE_FLAG_EXTRA_NO_TAUNT: return 8;
|
||||
case CREATURE_FLAG_EXTRA_NO_MOVE_FLAGS_UPDATE: return 9;
|
||||
case CREATURE_FLAG_EXTRA_GHOST_VISIBILITY: return 10;
|
||||
case CREATURE_FLAG_EXTRA_UNUSED_12: return 11;
|
||||
case CREATURE_FLAG_EXTRA_USE_OFFHAND_ATTACK: return 11;
|
||||
case CREATURE_FLAG_EXTRA_NO_SELL_VENDOR: return 12;
|
||||
case CREATURE_FLAG_EXTRA_IGNORE_COMBAT: return 13;
|
||||
case CREATURE_FLAG_EXTRA_WORLDEVENT: return 14;
|
||||
|
||||
@@ -2725,17 +2725,17 @@ bool WorldObject::GetClosePoint(float& x, float& y, float& z, float size, float
|
||||
return true;
|
||||
}
|
||||
|
||||
Position WorldObject::GetNearPosition(float dist, float angle)
|
||||
Position WorldObject::GetNearPosition(float dist, float angle, bool disableWarning)
|
||||
{
|
||||
Position pos = GetPosition();
|
||||
MovePosition(pos, dist, angle);
|
||||
MovePosition(pos, dist, angle, disableWarning);
|
||||
return pos;
|
||||
}
|
||||
|
||||
Position WorldObject::GetRandomNearPosition(float radius)
|
||||
Position WorldObject::GetRandomNearPosition(float radius, bool disableWarning)
|
||||
{
|
||||
Position pos = GetPosition();
|
||||
MovePosition(pos, radius * (float) rand_norm(), (float) rand_norm() * static_cast<float>(2 * M_PI));
|
||||
MovePosition(pos, radius * (float) rand_norm(), (float) rand_norm() * static_cast<float>(2 * M_PI), disableWarning);
|
||||
return pos;
|
||||
}
|
||||
|
||||
@@ -2773,7 +2773,7 @@ void WorldObject::GetChargeContactPoint(WorldObject const* obj, float& x, float&
|
||||
return (m_valuesCount > UNIT_FIELD_COMBATREACH) ? m_floatValues[UNIT_FIELD_COMBATREACH] : DEFAULT_WORLD_OBJECT_SIZE * GetObjectScale();
|
||||
}
|
||||
|
||||
void WorldObject::MovePosition(Position& pos, float dist, float angle)
|
||||
void WorldObject::MovePosition(Position& pos, float dist, float angle, bool disableWarning)
|
||||
{
|
||||
angle += GetOrientation();
|
||||
float destx, desty, destz, ground, floor;
|
||||
@@ -2783,7 +2783,9 @@ void WorldObject::MovePosition(Position& pos, float dist, float angle)
|
||||
// Prevent invalid coordinates here, position is unchanged
|
||||
if (!Acore::IsValidMapCoord(destx, desty))
|
||||
{
|
||||
LOG_FATAL("entities.object", "WorldObject::MovePosition invalid coordinates X: {} and Y: {} were passed!", destx, desty);
|
||||
if (!disableWarning)
|
||||
LOG_FATAL("entities.object", "WorldObject::MovePosition invalid coordinates X: {} and Y: {} were passed!", destx, desty);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -420,13 +420,13 @@ public:
|
||||
void GetNearPoint(WorldObject const* searcher, float& x, float& y, float& z, float searcher_size, float distance2d, float absAngle, float controlZ = 0, Position const* startPos = nullptr) const;
|
||||
void GetVoidClosePoint(float& x, float& y, float& z, float size, float distance2d = 0, float relAngle = 0, float controlZ = 0) const;
|
||||
bool GetClosePoint(float& x, float& y, float& z, float size, float distance2d = 0, float angle = 0, WorldObject const* forWho = nullptr, bool force = false) const;
|
||||
void MovePosition(Position& pos, float dist, float angle);
|
||||
Position GetNearPosition(float dist, float angle);
|
||||
void MovePosition(Position& pos, float dist, float angle, bool disableWarning = false);
|
||||
Position GetNearPosition(float dist, float angle, bool disableWarning = false);
|
||||
void MovePositionToFirstCollision(Position& pos, float dist, float angle);
|
||||
Position GetFirstCollisionPosition(float startX, float startY, float startZ, float destX, float destY);
|
||||
Position GetFirstCollisionPosition(float destX, float destY, float destZ);
|
||||
Position GetFirstCollisionPosition(float dist, float angle);
|
||||
Position GetRandomNearPosition(float radius);
|
||||
Position GetRandomNearPosition(float radius, bool disableWarning = false);
|
||||
|
||||
void GetContactPoint(WorldObject const* obj, float& x, float& y, float& z, float distance2d = CONTACT_DISTANCE) const;
|
||||
void GetChargeContactPoint(WorldObject const* obj, float& x, float& y, float& z, float distance2d = CONTACT_DISTANCE) const;
|
||||
|
||||
@@ -11347,6 +11347,9 @@ void Player::LeaveBattleground(Battleground* bg)
|
||||
sScriptMgr->OnBattlegroundDesertion(this, BG_DESERTION_TYPE_LEAVE_BG);
|
||||
}
|
||||
|
||||
if (bg->isArena() && (bg->GetStatus() == STATUS_IN_PROGRESS || bg->GetStatus() == STATUS_WAIT_JOIN))
|
||||
sScriptMgr->OnBattlegroundDesertion(this, ARENA_DESERTION_TYPE_LEAVE_BG);
|
||||
|
||||
bg->RemovePlayerAtLeave(this);
|
||||
|
||||
// xinef: reset corpse reclaim time
|
||||
|
||||
@@ -1238,6 +1238,8 @@ public:
|
||||
return GetItemByPos(bag, slot);
|
||||
}
|
||||
[[nodiscard]] Item* GetWeaponForAttack(WeaponAttackType attackType, bool useable = false) const;
|
||||
bool HasWeapon(WeaponAttackType type) const override { return GetWeaponForAttack(type, false); }
|
||||
bool HasWeaponForAttack(WeaponAttackType type) const override { return (Unit::HasWeaponForAttack(type) && GetWeaponForAttack(type, true)); }
|
||||
[[nodiscard]] Item* GetShield(bool useable = false) const;
|
||||
static uint8 GetAttackBySlot(uint8 slot); // MAX_ATTACK if not weapon slot
|
||||
std::vector<Item*>& GetItemUpdateQueue() { return m_itemUpdateQueue; }
|
||||
|
||||
@@ -195,7 +195,7 @@ void Player::Update(uint32 p_time)
|
||||
|
||||
// prevent base and off attack in same time, delay attack at
|
||||
// 0.2 sec
|
||||
if (haveOffhandWeapon())
|
||||
if (HasOffhandWeaponForAttack())
|
||||
if (getAttackTimer(OFF_ATTACK) < ATTACK_DISPLAY_DELAY)
|
||||
setAttackTimer(OFF_ATTACK, ATTACK_DISPLAY_DELAY);
|
||||
|
||||
@@ -205,7 +205,7 @@ void Player::Update(uint32 p_time)
|
||||
}
|
||||
}
|
||||
|
||||
if (haveOffhandWeapon() && isAttackReady(OFF_ATTACK))
|
||||
if (HasOffhandWeaponForAttack() && isAttackReady(OFF_ATTACK))
|
||||
{
|
||||
if (!IsWithinMeleeRange(victim))
|
||||
setAttackTimer(OFF_ATTACK, 100);
|
||||
|
||||
@@ -512,7 +512,7 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
|
||||
else
|
||||
{
|
||||
UpdateDamagePhysical(BASE_ATTACK);
|
||||
if (CanDualWield() && haveOffhandWeapon()) //allow update offhand damage only if player knows DualWield Spec and has equipped offhand weapon
|
||||
if (CanDualWield() && HasOffhandWeaponForAttack()) //allow update offhand damage only if player knows DualWield Spec and has equipped offhand weapon
|
||||
UpdateDamagePhysical(OFF_ATTACK);
|
||||
if (IsClass(CLASS_SHAMAN, CLASS_CONTEXT_STATS) || IsClass(CLASS_PALADIN, CLASS_CONTEXT_STATS)) // mental quickness
|
||||
UpdateSpellDamageAndHealingBonus();
|
||||
@@ -567,7 +567,7 @@ void Player::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bo
|
||||
float weaponMinDamage = GetWeaponDamageRange(attType, MINDAMAGE);
|
||||
float weaponMaxDamage = GetWeaponDamageRange(attType, MAXDAMAGE);
|
||||
|
||||
if (IsInFeralForm()) // check if player is druid and in cat or bear forms
|
||||
if (IsAttackSpeedOverridenShapeShift()) // forms with no override on attack speed use normal weapon damage
|
||||
{
|
||||
uint8 lvl = GetLevel();
|
||||
if (lvl > 60)
|
||||
@@ -1118,7 +1118,7 @@ void Creature::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized,
|
||||
break;
|
||||
}
|
||||
|
||||
if (attType == OFF_ATTACK && !haveOffhandWeapon())
|
||||
if (attType == OFF_ATTACK && !HasOffhandWeaponForAttack())
|
||||
{
|
||||
minDamage = 0.0f;
|
||||
maxDamage = 0.0f;
|
||||
@@ -1128,10 +1128,11 @@ void Creature::CalculateMinMaxDamage(WeaponAttackType attType, bool normalized,
|
||||
float weaponMinDamage = GetWeaponDamageRange(attType, MINDAMAGE);
|
||||
float weaponMaxDamage = GetWeaponDamageRange(attType, MAXDAMAGE);
|
||||
|
||||
if (!CanUseAttackType(attType)) // disarm case
|
||||
// Disarm for creatures
|
||||
if (HasWeapon(attType) && !HasWeaponForAttack(attType))
|
||||
{
|
||||
weaponMinDamage = 0.0f;
|
||||
weaponMaxDamage = 0.0f;
|
||||
minDamage *= 0.5f;
|
||||
maxDamage *= 0.5f;
|
||||
}
|
||||
|
||||
float attackPower = GetTotalAttackPowerValue(attType);
|
||||
|
||||
@@ -1856,7 +1856,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
|
||||
float offtime = float(victim->getAttackTimer(OFF_ATTACK));
|
||||
float basetime = float(victim->getAttackTimer(BASE_ATTACK));
|
||||
// Reduce attack time
|
||||
if (victim->haveOffhandWeapon() && offtime < basetime)
|
||||
if (victim->HasOffhandWeaponForAttack() && offtime < basetime)
|
||||
{
|
||||
float percent20 = victim->GetAttackTime(OFF_ATTACK) * 0.20f;
|
||||
float percent60 = 3.0f * percent20;
|
||||
@@ -8430,7 +8430,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
|
||||
if (dummySpell->SpellIconID == 2023)
|
||||
{
|
||||
// Must Dual Wield
|
||||
if (!procSpell || !haveOffhandWeapon())
|
||||
if (!procSpell || !HasOffhandWeaponForAttack())
|
||||
return false;
|
||||
// Chance as basepoints for dummy aura
|
||||
if (!roll_chance_i(triggerAmount))
|
||||
@@ -10365,9 +10365,9 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
|
||||
SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
|
||||
}
|
||||
|
||||
// delay offhand weapon attack to next attack time
|
||||
if (haveOffhandWeapon() && isAttackReady(OFF_ATTACK))
|
||||
setAttackTimer(OFF_ATTACK, ATTACK_DISPLAY_DELAY);
|
||||
// delay offhand weapon attack by 50% of the base attack time
|
||||
if (HasOffhandWeaponForAttack() && isAttackReady(OFF_ATTACK))
|
||||
setAttackTimer(OFF_ATTACK, std::max(getAttackTimer(OFF_ATTACK), getAttackTimer(BASE_ATTACK) + int32(CalculatePct(GetFloatValue(UNIT_FIELD_BASEATTACKTIME), 50))));
|
||||
|
||||
if (meleeAttack)
|
||||
SendMeleeAttackStart(victim);
|
||||
@@ -13417,7 +13417,7 @@ float Unit::GetWeaponProcChance() const
|
||||
// (odd formula...)
|
||||
if (isAttackReady(BASE_ATTACK))
|
||||
return (GetAttackTime(BASE_ATTACK) * 1.8f / 1000.0f);
|
||||
else if (haveOffhandWeapon() && isAttackReady(OFF_ATTACK))
|
||||
else if (HasOffhandWeaponForAttack() && isAttackReady(OFF_ATTACK))
|
||||
return (GetAttackTime(OFF_ATTACK) * 1.6f / 1000.0f);
|
||||
return 0;
|
||||
}
|
||||
@@ -15423,7 +15423,7 @@ float Unit::GetTotalAttackPowerValue(WeaponAttackType attType, Unit* victim) con
|
||||
|
||||
float Unit::GetWeaponDamageRange(WeaponAttackType attType, WeaponDamageRange type, uint8 damageIndex /*= 0*/) const
|
||||
{
|
||||
if (attType == OFF_ATTACK && !haveOffhandWeapon())
|
||||
if (attType == OFF_ATTACK && !HasOffhandWeaponForAttack())
|
||||
return 0.0f;
|
||||
|
||||
return m_weaponDamage[attType][type][damageIndex];
|
||||
@@ -18984,7 +18984,7 @@ float Unit::MeleeSpellMissChance(Unit const* victim, WeaponAttackType attType, i
|
||||
float missChance = victim->GetUnitMissChance(attType);
|
||||
|
||||
// Check if dual wielding, add additional miss penalty - when mainhand has on next swing spell, offhand doesnt suffer penalty
|
||||
if (!spellId && (attType != RANGED_ATTACK) && haveOffhandWeapon() && (!m_currentSpells[CURRENT_MELEE_SPELL] || !m_currentSpells[CURRENT_MELEE_SPELL]->IsNextMeleeSwingSpell()))
|
||||
if (!spellId && (attType != RANGED_ATTACK) && HasOffhandWeaponForAttack() && (!m_currentSpells[CURRENT_MELEE_SPELL] || !m_currentSpells[CURRENT_MELEE_SPELL]->IsNextMeleeSwingSpell()))
|
||||
{
|
||||
missChance += 19;
|
||||
}
|
||||
@@ -19498,6 +19498,16 @@ Unit* Unit::GetRedirectThreatTarget() const
|
||||
return _redirectThreatInfo.GetTargetGUID() ? ObjectAccessor::GetUnit(*this, _redirectThreatInfo.GetTargetGUID()) : nullptr;
|
||||
}
|
||||
|
||||
bool Unit::IsAttackSpeedOverridenShapeShift() const
|
||||
{
|
||||
// Mirroring clientside gameplay logic
|
||||
if (ShapeshiftForm form = GetShapeshiftForm())
|
||||
if (SpellShapeshiftFormEntry const* entry = sSpellShapeshiftFormStore.LookupEntry(form))
|
||||
return entry->attackSpeed > 0;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Unit::JumpTo(float speedXY, float speedZ, bool forward)
|
||||
{
|
||||
float angle = forward ? 0 : M_PI;
|
||||
@@ -21151,6 +21161,22 @@ void Unit::Whisper(std::string_view text, Language language, Player* target, boo
|
||||
target->SendDirectMessage(&data);
|
||||
}
|
||||
|
||||
uint32 Unit::GetVirtualItemId(uint32 slot) const
|
||||
{
|
||||
if (slot >= MAX_EQUIPMENT_ITEMS)
|
||||
return 0;
|
||||
|
||||
return GetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + slot);
|
||||
}
|
||||
|
||||
void Unit::SetVirtualItem(uint32 slot, uint32 itemId)
|
||||
{
|
||||
if (slot >= MAX_EQUIPMENT_ITEMS)
|
||||
return;
|
||||
|
||||
SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + slot, itemId);
|
||||
}
|
||||
|
||||
void Unit::Talk(uint32 textId, ChatMsg msgType, float textRange, WorldObject const* target)
|
||||
{
|
||||
if (!sObjectMgr->GetBroadcastText(textId))
|
||||
|
||||
@@ -1053,6 +1053,17 @@ public:
|
||||
[[nodiscard]] float GetUnitMissChance(WeaponAttackType attType) const;
|
||||
float GetUnitCriticalChance(WeaponAttackType attackType, Unit const* victim) const;
|
||||
int32 GetMechanicResistChance(SpellInfo const* spell);
|
||||
|
||||
virtual bool HasWeapon(WeaponAttackType type) const = 0;
|
||||
inline bool HasMainhandWeapon() const { return HasWeapon(BASE_ATTACK); }
|
||||
inline bool HasOffhandWeapon() const { return HasWeapon(OFF_ATTACK); }
|
||||
inline bool HasRangedWeapon() const { return HasWeapon(RANGED_ATTACK); }
|
||||
|
||||
inline bool hasMainhandWeaponForAttack() const { return HasWeaponForAttack(BASE_ATTACK); }
|
||||
virtual bool HasWeaponForAttack(WeaponAttackType type) const { return CanUseAttackType(type); }
|
||||
inline bool HasMainhandWeaponForAttack() const { return HasWeaponForAttack(BASE_ATTACK); }
|
||||
inline bool HasOffhandWeaponForAttack() const { return HasWeaponForAttack(OFF_ATTACK); }
|
||||
inline bool HasRangedWeaponForAttack() const { return HasWeaponForAttack(RANGED_ATTACK); }
|
||||
[[nodiscard]] bool CanUseAttackType(uint8 attacktype) const
|
||||
{
|
||||
switch (attacktype)
|
||||
@@ -1063,8 +1074,9 @@ public:
|
||||
return !HasUnitFlag2(UNIT_FLAG2_DISARM_OFFHAND);
|
||||
case RANGED_ATTACK:
|
||||
return !HasUnitFlag2(UNIT_FLAG2_DISARM_RANGED);
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
[[nodiscard]] virtual uint32 GetShieldBlockValue() const = 0;
|
||||
@@ -1468,6 +1480,8 @@ public:
|
||||
SetByteValue(UNIT_FIELD_BYTES_2, 3, form);
|
||||
}
|
||||
|
||||
bool IsAttackSpeedOverridenShapeShift() const;
|
||||
|
||||
[[nodiscard]] bool IsInFeralForm() const
|
||||
{
|
||||
ShapeshiftForm form = GetShapeshiftForm();
|
||||
@@ -1762,6 +1776,9 @@ public:
|
||||
[[nodiscard]] float GetCollisionWidth() const override;
|
||||
[[nodiscard]] float GetCollisionRadius() const override;
|
||||
|
||||
uint32 GetVirtualItemId(uint32 slot) const;
|
||||
void SetVirtualItem(uint32 slot, uint32 itemId);
|
||||
|
||||
void ProcessPositionDataChanged(PositionFullTerrainStatus const& data) override;
|
||||
virtual void ProcessTerrainStatusUpdate();
|
||||
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
#ifndef __ADDONHANDLER_H
|
||||
#define __ADDONHANDLER_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "Config.h"
|
||||
#include "WorldPacket.h"
|
||||
|
||||
class AddonHandler
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include "Opcodes.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "UpdateMask.h"
|
||||
#include "World.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "WorldSession.h"
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include "DBCStores.h"
|
||||
#include "Item.h"
|
||||
#include "Log.h"
|
||||
#include "Opcodes.h"
|
||||
#include "Player.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "WorldSession.h"
|
||||
|
||||
@@ -580,6 +580,9 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket& recvData)
|
||||
|
||||
sScriptMgr->OnBattlegroundDesertion(_player, BG_DESERTION_TYPE_LEAVE_QUEUE);
|
||||
}
|
||||
|
||||
if (bg->isArena() && (bg->GetStatus() == STATUS_IN_PROGRESS || bg->GetStatus() == STATUS_WAIT_JOIN))
|
||||
sScriptMgr->OnBattlegroundDesertion(_player, ARENA_DESERTION_TYPE_LEAVE_QUEUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,7 +53,6 @@
|
||||
#include "StringConvert.h"
|
||||
#include "Tokenize.h"
|
||||
#include "Transport.h"
|
||||
#include "UpdateMask.h"
|
||||
#include "Util.h"
|
||||
#include "World.h"
|
||||
#include "WorldPacket.h"
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include "CreatureAI.h"
|
||||
#include "Log.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "ObjectDefines.h"
|
||||
#include "Opcodes.h"
|
||||
#include "Player.h"
|
||||
#include "Vehicle.h"
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include "Log.h"
|
||||
#include "Opcodes.h"
|
||||
#include "Player.h"
|
||||
#include "UpdateData.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "WorldSession.h"
|
||||
|
||||
|
||||
@@ -20,10 +20,7 @@
|
||||
#include "GuildPackets.h"
|
||||
#include "Log.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "Opcodes.h"
|
||||
#include "SocialMgr.h"
|
||||
#include "World.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "WorldSession.h"
|
||||
|
||||
void WorldSession::HandleGuildQueryOpcode(WorldPackets::Guild::QueryGuildInfo& query)
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include "ScriptMgr.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "UpdateMask.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "WorldSession.h"
|
||||
#include <cmath>
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
#include "Pet.h"
|
||||
#include "PetPackets.h"
|
||||
#include "Player.h"
|
||||
#include "QueryHolder.h"
|
||||
#include "Spell.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "SpellMgr.h"
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
#include "Log.h"
|
||||
#include "Opcodes.h"
|
||||
#include "Pet.h"
|
||||
#include "Player.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "WorldPacket.h"
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "SpellAuras.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "TemporarySummon.h"
|
||||
#include "Totem.h"
|
||||
#include "TotemPackets.h"
|
||||
#include "Vehicle.h"
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "Opcodes.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptMgr.h"
|
||||
#include "UpdateMask.h"
|
||||
#include "WaypointMovementGenerator.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "WorldSession.h"
|
||||
|
||||
@@ -700,7 +700,9 @@ QuestItemList* Loot::FillQuestLoot(Player* player)
|
||||
}
|
||||
|
||||
// Player is not the loot owner, and loot owner still needs this quest item
|
||||
if (!item.freeforall && lootOwner != player && item.AllowedForPlayer(lootOwner, sourceWorldObjectGUID))
|
||||
if (!item.freeforall &&
|
||||
lootOwner && lootOwner != player &&
|
||||
item.AllowedForPlayer(lootOwner, sourceWorldObjectGUID))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -520,7 +520,7 @@ void MotionMaster::MoveLand(uint32 id, float x, float y, float z, float speed /*
|
||||
/**
|
||||
* @brief Use to move the unit from the ground to the air. Doesn't work with UNIT_FLAG_DISABLE_MOVE
|
||||
*/
|
||||
void MotionMaster::MoveTakeoff(uint32 id, Position const& pos, float speed /* = 0.0f*/)
|
||||
void MotionMaster::MoveTakeoff(uint32 id, Position const& pos, float speed /* = 0.0f*/, bool skipAnimation)
|
||||
{
|
||||
if (_owner->HasUnitFlag(UNIT_FLAG_DISABLE_MOVE))
|
||||
return;
|
||||
@@ -538,7 +538,10 @@ void MotionMaster::MoveTakeoff(uint32 id, Position const& pos, float speed /* =
|
||||
init.SetVelocity(speed);
|
||||
}
|
||||
|
||||
init.SetAnimation(Movement::ToFly);
|
||||
if (!skipAnimation)
|
||||
{
|
||||
init.SetAnimation(Movement::ToFly);
|
||||
}
|
||||
init.Launch();
|
||||
Mutate(new EffectMovementGenerator(id), MOTION_SLOT_ACTIVE);
|
||||
}
|
||||
@@ -546,10 +549,10 @@ void MotionMaster::MoveTakeoff(uint32 id, Position const& pos, float speed /* =
|
||||
/**
|
||||
* @brief Use to move the unit from the air to the ground. Doesn't work with UNIT_FLAG_DISABLE_MOVE
|
||||
*/
|
||||
void MotionMaster::MoveTakeoff(uint32 id, float x, float y, float z, float speed /* = 0.0f*/)
|
||||
void MotionMaster::MoveTakeoff(uint32 id, float x, float y, float z, float speed /* = 0.0f*/, bool skipAnimation)
|
||||
{
|
||||
Position pos = {x, y, z, 0.0f};
|
||||
MoveTakeoff(id, pos, speed);
|
||||
MoveTakeoff(id, pos, speed, skipAnimation);
|
||||
}
|
||||
|
||||
void MotionMaster::MoveKnockbackFrom(float srcX, float srcY, float speedXY, float speedZ)
|
||||
|
||||
@@ -217,8 +217,8 @@ public:
|
||||
// These two movement types should only be used with creatures having landing/takeoff animations
|
||||
void MoveLand(uint32 id, Position const& pos, float speed = 0.0f);
|
||||
void MoveLand(uint32 id, float x, float y, float z, float speed = 0.0f); // pussywizard: added for easy calling by passing 3 floats x, y, z
|
||||
void MoveTakeoff(uint32 id, Position const& pos, float speed = 0.0f);
|
||||
void MoveTakeoff(uint32 id, float x, float y, float z, float speed = 0.0f); // pussywizard: added for easy calling by passing 3 floats x, y, z
|
||||
void MoveTakeoff(uint32 id, Position const& pos, float speed = 0.0f, bool skipAnimation = false);
|
||||
void MoveTakeoff(uint32 id, float x, float y, float z, float speed = 0.0f, bool skipAnimation = false); // pussywizard: added for easy calling by passing 3 floats x, y, z
|
||||
|
||||
void MoveCharge(float x, float y, float z, float speed = SPEED_CHARGE, uint32 id = EVENT_CHARGE, const Movement::PointsArray* path = nullptr, bool generatePath = false, float orientation = 0.0f, ObjectGuid targetGUID = ObjectGuid::Empty);
|
||||
void MoveCharge(PathGenerator const& path, float speed = SPEED_CHARGE, ObjectGuid targetGUID = ObjectGuid::Empty);
|
||||
|
||||
@@ -661,6 +661,9 @@ void WorldSession::LogoutPlayer(bool save)
|
||||
sScriptMgr->OnBattlegroundDesertion(_player, BG_DESERTION_TYPE_INVITE_LOGOUT);
|
||||
}
|
||||
|
||||
if (bgQueueTypeId >= BATTLEGROUND_QUEUE_2v2 && bgQueueTypeId < MAX_BATTLEGROUND_QUEUE_TYPES && _player->IsInvitedForBattlegroundQueueType(bgQueueTypeId))
|
||||
sScriptMgr->OnBattlegroundDesertion(_player, ARENA_DESERTION_TYPE_INVITE_LOGOUT);
|
||||
|
||||
_player->RemoveBattlegroundQueueId(bgQueueTypeId);
|
||||
sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId).RemovePlayer(_player->GetGUID(), true);
|
||||
}
|
||||
|
||||
@@ -3160,6 +3160,13 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA
|
||||
|
||||
if (m_spellAura)
|
||||
{
|
||||
// Prevent aura application if target is immuned
|
||||
if (m_targets.GetUnitTarget() && m_targets.GetUnitTarget()->IsImmunedToDamageOrSchool(m_spellAura->GetSpellInfo()))
|
||||
{
|
||||
m_spellAura->Remove();
|
||||
return SPELL_MISS_IMMUNE;
|
||||
}
|
||||
|
||||
// Set aura stack amount to desired value
|
||||
if (m_spellValue->AuraStackAmount > 1)
|
||||
{
|
||||
@@ -4061,7 +4068,7 @@ void Spell::_cast(bool skipCheck)
|
||||
{
|
||||
m_caster->resetAttackTimer(BASE_ATTACK);
|
||||
|
||||
if (m_caster->haveOffhandWeapon())
|
||||
if (m_caster->HasOffhandWeaponForAttack())
|
||||
{
|
||||
m_caster->resetAttackTimer(OFF_ATTACK);
|
||||
}
|
||||
|
||||
@@ -4837,6 +4837,19 @@ void SpellMgr::LoadSpellInfoCorrections()
|
||||
spellInfo->AttributesEx5 |= SPELL_ATTR5_ALLOW_ACTION_DURING_CHANNEL;
|
||||
});
|
||||
|
||||
// Fatal Attraction
|
||||
ApplySpellFix({ 40870 }, [](SpellInfo* spellInfo)
|
||||
{
|
||||
spellInfo->MaxAffectedTargets = 1;
|
||||
});
|
||||
|
||||
// Removing Dragonflayer Harpoon
|
||||
ApplySpellFix({ 42968 }, [](SpellInfo* spellInfo)
|
||||
{
|
||||
spellInfo->MaxAffectedTargets = 1;
|
||||
spellInfo->RangeEntry = sSpellRangeStore.LookupEntry(7);
|
||||
});
|
||||
|
||||
for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
|
||||
{
|
||||
SpellInfo* spellInfo = mSpellInfoMap[i];
|
||||
|
||||
@@ -309,6 +309,7 @@ enum WorldIntConfigs
|
||||
CONFIG_DEATH_SICKNESS_LEVEL,
|
||||
CONFIG_INSTANT_LOGOUT,
|
||||
CONFIG_DISABLE_BREATHING,
|
||||
CONFIG_BATTLEGROUND_OVERRIDE_LOWLEVELS_MINPLAYERS,
|
||||
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_SPAM_DELAY,
|
||||
CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_TIMER,
|
||||
CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER,
|
||||
|
||||
@@ -1113,6 +1113,7 @@ void World::LoadConfigSettings(bool reload)
|
||||
_float_configs[CONFIG_LISTEN_RANGE_TEXTEMOTE] = sConfigMgr->GetOption<float>("ListenRange.TextEmote", 25.0f);
|
||||
_float_configs[CONFIG_LISTEN_RANGE_YELL] = sConfigMgr->GetOption<float>("ListenRange.Yell", 300.0f);
|
||||
|
||||
_int_configs[CONFIG_BATTLEGROUND_OVERRIDE_LOWLEVELS_MINPLAYERS] = sConfigMgr->GetOption<uint32>("Battleground.Override.LowLevels.MinPlayers", 0);
|
||||
_bool_configs[CONFIG_BATTLEGROUND_DISABLE_QUEST_SHARE_IN_BG] = sConfigMgr->GetOption<bool>("Battleground.DisableQuestShareInBG", false);
|
||||
_bool_configs[CONFIG_BATTLEGROUND_DISABLE_READY_CHECK_IN_BG] = sConfigMgr->GetOption<bool>("Battleground.DisableReadyCheckInBG", false);
|
||||
_bool_configs[CONFIG_BATTLEGROUND_CAST_DESERTER] = sConfigMgr->GetOption<bool>("Battleground.CastDeserter", true);
|
||||
|
||||
@@ -28,7 +28,6 @@ EndScriptData */
|
||||
#include "CommandScript.h"
|
||||
#include "DBCStores.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "Log.h"
|
||||
#include "ObjectAccessor.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "Player.h"
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include "SpellInfo.h"
|
||||
#include "SpellScript.h"
|
||||
#include "SpellScriptLoader.h"
|
||||
#include "Vehicle.h"
|
||||
|
||||
/*######
|
||||
## npc_eye_of_acherus
|
||||
|
||||
@@ -2417,6 +2417,8 @@ public:
|
||||
ObjectGuid _grabbedPlayer;
|
||||
bool didbelow50pct;
|
||||
bool dropped;
|
||||
bool grabbed;
|
||||
float _lastSpeed;
|
||||
InstanceScript* _instance;
|
||||
|
||||
bool IsHeroic() { return me->GetMap()->IsHeroic(); }
|
||||
@@ -2547,6 +2549,8 @@ public:
|
||||
if (me->HasUnitState(UNIT_STATE_CASTING | UNIT_STATE_STUNNED))
|
||||
return;
|
||||
|
||||
HandleSpeedChangeIfNeeded();
|
||||
|
||||
switch (_events.ExecuteEvent())
|
||||
{
|
||||
case EVENT_GRAB_PLAYER:
|
||||
@@ -2557,6 +2561,8 @@ public:
|
||||
}
|
||||
break;
|
||||
case EVENT_MOVE_TO_DROP_POS:
|
||||
grabbed = true;
|
||||
_lastSpeed = me->GetSpeed(MOVE_WALK);
|
||||
me->AddUnitState(UNIT_STATE_NO_ENVIRONMENT_UPD);
|
||||
me->SetCanFly(false);
|
||||
me->SetDisableGravity(false);
|
||||
@@ -2596,6 +2602,24 @@ public:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// For some reason, when the Valkyr has a slowdown effect, the speed of PointMovementGenerator
|
||||
// and the speed on the client side differ, which leads to a "teleportation" effect when a stun aura is applied.
|
||||
// Restarting the motion master on speed change ensures the movement is synced between the server and client.
|
||||
void HandleSpeedChangeIfNeeded()
|
||||
{
|
||||
if (!grabbed || dropped)
|
||||
return;
|
||||
|
||||
if (me->GetSpeed(MOVE_WALK) == _lastSpeed)
|
||||
return;
|
||||
|
||||
_lastSpeed = me->GetSpeed(MOVE_WALK);
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->StopMovingOnCurrentPos();
|
||||
|
||||
_events.ScheduleEvent(EVENT_MOVE_TO_DROP_POS, 0);
|
||||
}
|
||||
};
|
||||
|
||||
CreatureAI* GetAI(Creature* creature) const override
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "PassiveAI.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptedEscortAI.h"
|
||||
#include "ScriptedGossip.h"
|
||||
#include "SmartAI.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "SpellScriptLoader.h"
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include "PassiveAI.h"
|
||||
#include "Player.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptedGossip.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "SpellScript.h"
|
||||
#include "SpellScriptLoader.h"
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "SpellAuras.h"
|
||||
#include "SpellScript.h"
|
||||
#include "SpellScriptLoader.h"
|
||||
#include "Vehicle.h"
|
||||
#include "ulduar.h"
|
||||
|
||||
#define SPELL_FLAME_JETS_10 62680
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#include "Player.h"
|
||||
#include "ScriptedCreature.h"
|
||||
#include "Transport.h"
|
||||
#include "Vehicle.h"
|
||||
#include "WorldPacket.h"
|
||||
#include "ulduar.h"
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ struct boss_gurtogg_bloodboil : public BossAI
|
||||
|
||||
bool CanAIAttack(Unit const* who) const override
|
||||
{
|
||||
return !who->IsImmunedToDamage(SPELL_SCHOOL_MASK_ALL);
|
||||
return !who->IsImmunedToDamage(SPELL_SCHOOL_MASK_ALL) && !who->HasUnitState(UNIT_STATE_CONFUSED);
|
||||
}
|
||||
|
||||
void KilledUnit(Unit* /*victim*/) override
|
||||
|
||||
@@ -196,6 +196,17 @@ class spell_mother_shahraz_saber_lash_aura : public AuraScript
|
||||
}
|
||||
};
|
||||
|
||||
const Position validTeleportStairsPos[4] =
|
||||
{
|
||||
{966.87f, 184.45f, 192.84f},
|
||||
{927.22f, 187.04f, 192.84f},
|
||||
{922.54f, 110.09f, 192.84f},
|
||||
{958.01f, 110.47f, 192.84f}
|
||||
};
|
||||
|
||||
constexpr float minTeleportDist = 30.f;
|
||||
constexpr float maxTeleportDist = 50.f;
|
||||
|
||||
class spell_mother_shahraz_fatal_attraction : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_mother_shahraz_fatal_attraction);
|
||||
@@ -212,7 +223,44 @@ class spell_mother_shahraz_fatal_attraction : public SpellScript
|
||||
|
||||
void SetDest(SpellDestination& dest)
|
||||
{
|
||||
dest.Relocate(GetCaster()->GetRandomNearPosition(50.0f));
|
||||
Position finalDest;
|
||||
|
||||
// Check if the boss is near stairs to avoid players falling through the platform with random teleports.
|
||||
if (GetCaster()->GetPositionY() < 194.f)
|
||||
finalDest = validTeleportStairsPos[urand(0, 3)];
|
||||
else
|
||||
{
|
||||
finalDest = GetCaster()->GetNearPosition(frand(minTeleportDist, maxTeleportDist), static_cast<float>(rand_norm()) * static_cast<float>(2 * M_PI), true);
|
||||
|
||||
// Maybe not necessary but just in case to avoid LOS issues with an object
|
||||
if (!GetCaster()->IsWithinLOS(finalDest.GetPositionX(), finalDest.GetPositionY(), finalDest.GetPositionZ()))
|
||||
finalDest = GetCaster()->GetNearPosition(frand(minTeleportDist, maxTeleportDist), static_cast<float>(rand_norm()) * static_cast<float>(2 * M_PI), true);
|
||||
|
||||
/* @note: To avoid teleporting players near a walls, we will define a safe area.
|
||||
* As the boss have an area boudary around y: 320.f. We will limit the safe area to this value, avoiding wird issues.
|
||||
* x limit: 932.f/960.f | y limit: 224.f/320.f
|
||||
*/
|
||||
if (finalDest.m_positionX < 932.f)
|
||||
finalDest.m_positionX = 932.f;
|
||||
else if (finalDest.m_positionX > 960.f)
|
||||
finalDest.m_positionX = 960.f;
|
||||
|
||||
if (finalDest.m_positionY < 224.f)
|
||||
finalDest.m_positionY = 224.f;
|
||||
else if (finalDest.m_positionY > 320.f)
|
||||
finalDest.m_positionY = 320.f;
|
||||
|
||||
// After relocate a finalDest outside the safe area, we need to recheck the distance with the boss
|
||||
if (GetCaster()->GetExactDist2d(finalDest) < minTeleportDist)
|
||||
{
|
||||
if (finalDest.m_positionX == 932.f || finalDest.m_positionX == 960.f)
|
||||
finalDest.m_positionY = finalDest.m_positionY + (minTeleportDist - GetCaster()->GetExactDist2d(finalDest));
|
||||
else if (finalDest.m_positionY == 224.f || finalDest.m_positionY == 320.f)
|
||||
finalDest.m_positionX = finalDest.m_positionX + (minTeleportDist - GetCaster()->GetExactDist2d(finalDest));
|
||||
}
|
||||
}
|
||||
|
||||
dest.Relocate(finalDest);
|
||||
}
|
||||
|
||||
void HandleTeleportUnits(SpellEffIndex /*effIndex*/)
|
||||
@@ -235,7 +283,13 @@ class spell_mother_shahraz_fatal_attraction_dummy : public SpellScript
|
||||
|
||||
bool Validate(SpellInfo const* /*spellInfo*/) override
|
||||
{
|
||||
return ValidateSpellInfo({ SPELL_FATAL_ATTRACTION_DAMAGE });
|
||||
return ValidateSpellInfo({ SPELL_FATAL_ATTRACTION_DAMAGE, SPELL_FATAL_ATTRACTION_AURA });
|
||||
}
|
||||
|
||||
void FilterTargets(std::list<WorldObject*>& targets)
|
||||
{
|
||||
if (targets.empty())
|
||||
GetCaster()->RemoveAurasDueToSpell(SPELL_FATAL_ATTRACTION_AURA);
|
||||
}
|
||||
|
||||
void HandleDummy(SpellEffIndex /*effIndex*/)
|
||||
@@ -255,6 +309,7 @@ class spell_mother_shahraz_fatal_attraction_dummy : public SpellScript
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_mother_shahraz_fatal_attraction_dummy::FilterTargets, EFFECT_ALL, TARGET_UNIT_SRC_AREA_ALLY);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_mother_shahraz_fatal_attraction_dummy::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -178,6 +178,13 @@ public:
|
||||
for (ObjectGuid const& guid : ashtongueGUIDs)
|
||||
if (Creature* ashtongue = instance->GetCreature(guid))
|
||||
ashtongue->SetFaction(FACTION_ASHTONGUE_DEATHSWORN);
|
||||
[[fallthrough]];
|
||||
case DATA_TERON_GOREFIEND:
|
||||
case DATA_GURTOGG_BLOODBOIL:
|
||||
case DATA_RELIQUARY_OF_SOULS:
|
||||
if (AllBossesDone({ DATA_SHADE_OF_AKAMA, DATA_TERON_GOREFIEND, DATA_GURTOGG_BLOODBOIL, DATA_RELIQUARY_OF_SOULS }))
|
||||
if (Creature* trigger = GetCreature(DATA_BLACK_TEMPLE_TRIGGER))
|
||||
trigger->AI()->Talk(EMOTE_LOWER_TEMPLE_DEFEATED);
|
||||
break;
|
||||
case DATA_ILLIDARI_COUNCIL:
|
||||
if (Creature* akama = GetCreature(DATA_AKAMA_ILLIDAN))
|
||||
@@ -186,10 +193,6 @@ public:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (AllBossesDone({ DATA_SHADE_OF_AKAMA, DATA_TERON_GOREFIEND, DATA_GURTOGG_BLOODBOIL, DATA_RELIQUARY_OF_SOULS }))
|
||||
if (Creature* trigger = GetCreature(DATA_BLACK_TEMPLE_TRIGGER))
|
||||
trigger->AI()->Talk(EMOTE_LOWER_TEMPLE_DEFEATED);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#define DEF_BLOOD_FURNACE_H
|
||||
|
||||
#include "CreatureAIImpl.h"
|
||||
#include "Player.h"
|
||||
|
||||
#define DataHeader "BF"
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ enum KTSpells
|
||||
SPELL_KAEL_EXPLODES4 = 36354,
|
||||
SPELL_KAEL_EXPLODES5 = 36092,
|
||||
SPELL_GROW = 36184,
|
||||
SPELL_KEAL_STUNNED = 36185,
|
||||
SPELL_KAEL_STUNNED = 36185,
|
||||
SPELL_KAEL_FULL_POWER = 36187,
|
||||
SPELL_FLOATING_DROWNED = 36550,
|
||||
SPELL_DARK_BANISH_STATE = 52241, // wrong visual apparently
|
||||
@@ -153,8 +153,7 @@ enum KTMisc
|
||||
{
|
||||
POINT_MIDDLE = 1,
|
||||
POINT_AIR = 2,
|
||||
POINT_LAND = 3,
|
||||
POINT_START_LAST_PHASE = 4,
|
||||
POINT_START_LAST_PHASE = 3,
|
||||
|
||||
DATA_RESURRECT_CAST = 1,
|
||||
|
||||
@@ -191,7 +190,9 @@ enum KTTransitionScene
|
||||
EVENT_SCENE_13 = 62,
|
||||
EVENT_SCENE_14 = 63,
|
||||
EVENT_SCENE_15 = 64,
|
||||
EVENT_SCENE_16 = 65
|
||||
EVENT_SCENE_16 = 65,
|
||||
EVENT_SCENE_17 = 66,
|
||||
EVENT_SCENE_18 = 67
|
||||
};
|
||||
|
||||
enum KTActions
|
||||
@@ -280,7 +281,7 @@ struct boss_kaelthas : public BossAI
|
||||
_phase = PHASE_NONE;
|
||||
_transitionSceneReached = false;
|
||||
|
||||
me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_HOVER, true);
|
||||
me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_HOVER, true); // hover effect 36550 - Floating Drowned
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE);
|
||||
SetRoomState(GO_STATE_READY);
|
||||
@@ -405,13 +406,17 @@ struct boss_kaelthas : public BossAI
|
||||
|
||||
void MovementInform(uint32 type, uint32 point) override
|
||||
{
|
||||
if (type != POINT_MOTION_TYPE)
|
||||
if (type != POINT_MOTION_TYPE && type != EFFECT_MOTION_TYPE)
|
||||
return;
|
||||
|
||||
if (point == POINT_MIDDLE)
|
||||
{
|
||||
ExecuteMiddleEvent();
|
||||
}
|
||||
else if (point == POINT_AIR)
|
||||
{
|
||||
me->SetDisableGravity(true, false, false); // updating AnimationTier will break drowning animation later
|
||||
}
|
||||
else if (point == POINT_START_LAST_PHASE)
|
||||
{
|
||||
me->SetDisableGravity(false);
|
||||
@@ -479,6 +484,8 @@ struct boss_kaelthas : public BossAI
|
||||
|
||||
void ExecuteMiddleEvent()
|
||||
{
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->RemoveAllAttackers();
|
||||
scheduler.ClearValidator();
|
||||
me->SetTarget();
|
||||
me->SetFacingTo(M_PI);
|
||||
@@ -498,7 +505,7 @@ struct boss_kaelthas : public BossAI
|
||||
trigger->CastSpell(me, SPELL_NETHERBEAM1 + i, false);
|
||||
me->SetDisableGravity(true);
|
||||
me->SendMovementFlagUpdate();
|
||||
me->GetMotionMaster()->MoveTakeoff(POINT_AIR, me->GetPositionX(), me->GetPositionY(), 75.0f, 2.99);
|
||||
me->GetMotionMaster()->MoveTakeoff(POINT_AIR, me->GetPositionX(), me->GetPositionY(), 75.0f, 2.99, true); // AnimType Movement::ToFly does not exist for Kael
|
||||
DoCastSelf(SPELL_GROW, true);
|
||||
}, EVENT_SCENE_3);
|
||||
ScheduleUniqueTimedEvent(7000ms, [&]
|
||||
@@ -538,8 +545,6 @@ struct boss_kaelthas : public BossAI
|
||||
me->RemoveAurasDueToSpell(SPELL_NETHERBEAM_AURA2);
|
||||
me->RemoveAurasDueToSpell(SPELL_NETHERBEAM_AURA3);
|
||||
DoCastSelf(SPELL_KAEL_EXPLODES5, true);
|
||||
DoCastSelf(SPELL_FLOATING_DROWNED);
|
||||
//me->CastSpell(me, SPELL_KEAL_STUNNED, true);
|
||||
}, EVENT_SCENE_8);
|
||||
ScheduleUniqueTimedEvent(22000ms, [&]
|
||||
{
|
||||
@@ -580,25 +585,34 @@ struct boss_kaelthas : public BossAI
|
||||
if (Creature* trigger = me->SummonCreature(WORLD_TRIGGER, me->GetPositionX()-5, me->GetPositionY()+5, me->GetPositionZ()+15.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 60000))
|
||||
trigger->CastSpell(me, SPELL_PURE_NETHER_BEAM3, true);
|
||||
}, EVENT_SCENE_14);
|
||||
ScheduleUniqueTimedEvent(30500ms, [&]
|
||||
{
|
||||
me->SetFacingTo(M_PI);
|
||||
me->RemoveAurasDueToSpell(SPELL_FLOATING_DROWNED);
|
||||
me->CastStop();
|
||||
}, EVENT_SCENE_15);
|
||||
ScheduleUniqueTimedEvent(30700ms, [&]
|
||||
{
|
||||
me->CastStop();
|
||||
DoCastSelf(SPELL_KAEL_FULL_POWER);
|
||||
}, EVENT_SCENE_16);
|
||||
ScheduleUniqueTimedEvent(32000ms, [&]
|
||||
{
|
||||
me->RemoveAurasDueToSpell(SPELL_FLOATING_DROWNED);
|
||||
me->RemoveAurasDueToSpell(SPELL_KEAL_STUNNED);
|
||||
DoCastSelf(SPELL_KAEL_FULL_POWER);
|
||||
DoCastSelf(SPELL_KAEL_PHASE_TWO, true);
|
||||
DoCastSelf(SPELL_PURE_NETHER_BEAM4, true);
|
||||
DoCastSelf(SPELL_PURE_NETHER_BEAM5, true);
|
||||
DoCastSelf(SPELL_PURE_NETHER_BEAM6, true);
|
||||
}, EVENT_SCENE_15);
|
||||
}, EVENT_SCENE_17);
|
||||
ScheduleUniqueTimedEvent(36000ms, [&]
|
||||
{
|
||||
summons.DespawnEntry(WORLD_TRIGGER);
|
||||
me->CastStop();
|
||||
me->GetMotionMaster()->Clear();
|
||||
me->RemoveAurasDueToSpell(SPELL_DARK_BANISH_STATE); // WRONG VISUAL
|
||||
me->GetMotionMaster()->MoveLand(POINT_LAND, me->GetPositionX(), me->GetPositionY(), 48.0f, 2.99f); // Moveland doesn't handle POINT_START_LAST_PHASE so we need to use MovePoint
|
||||
me->GetMotionMaster()->MovePoint(POINT_START_LAST_PHASE, me->GetHomePosition(), false, true);
|
||||
}, EVENT_SCENE_16);
|
||||
me->SetDisableGravity(true);
|
||||
me->SendMovementFlagUpdate();
|
||||
me->GetMotionMaster()->MoveLand(POINT_START_LAST_PHASE, me->GetHomePosition(), 2.99f);
|
||||
}, EVENT_SCENE_18);
|
||||
}
|
||||
|
||||
void IntroduceNewAdvisor(KTYells talkIntroduction, KTActions kaelAction)
|
||||
@@ -689,21 +703,10 @@ struct boss_kaelthas : public BossAI
|
||||
{
|
||||
_transitionSceneReached = true;
|
||||
scheduler.CancelAll();
|
||||
me->AttackStop();
|
||||
me->CastStop();
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->GetMotionMaster()->MovePoint(POINT_MIDDLE, me->GetHomePosition(), true, true);
|
||||
me->ClearUnitState(UNIT_STATE_MELEE_ATTACKING);
|
||||
me->SendMeleeAttackStop();
|
||||
|
||||
ThreatContainer::StorageType threatList = me->GetThreatMgr().GetThreatList();
|
||||
for (ThreatContainer::StorageType::const_iterator i = threatList.begin(); i != threatList.end(); ++i)
|
||||
{
|
||||
if (Unit* target = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid()))
|
||||
{
|
||||
target->AttackStop();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
ScheduleTimedEvent(1000ms, [&]
|
||||
@@ -1349,6 +1352,27 @@ class spell_kaelthas_remove_enchanted_weapons : public SpellScript
|
||||
}
|
||||
};
|
||||
|
||||
// 36092 - Kael Explodes
|
||||
class spell_kaelthas_kael_explodes : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_kaelthas_kael_explodes);
|
||||
|
||||
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
Unit* caster = GetCaster();
|
||||
caster->CastSpell((Unit*)nullptr, SPELL_FLOATING_DROWNED, true);
|
||||
// caster->CastSpell((Unit*)nullptr, SPELL_KAEL_STUNNED, true);
|
||||
caster->PlayDirectSound(3320);
|
||||
caster->PlayDirectSound(10845);
|
||||
caster->PlayDirectSound(6539);
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_kaelthas_kael_explodes::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_boss_kaelthas()
|
||||
{
|
||||
RegisterTheEyeAI(boss_kaelthas);
|
||||
@@ -1368,4 +1392,5 @@ void AddSC_boss_kaelthas()
|
||||
RegisterSpellScript(spell_kaelthas_summon_nether_vapor);
|
||||
RegisterSpellScript(spell_kael_pyroblast);
|
||||
RegisterSpellScript(spell_kaelthas_remove_enchanted_weapons);
|
||||
RegisterSpellScript(spell_kaelthas_kael_explodes);
|
||||
}
|
||||
|
||||
@@ -375,16 +375,6 @@ class spell_gen_bg_preparation : public AuraScript
|
||||
{
|
||||
PrepareAuraScript(spell_gen_bg_preparation)
|
||||
|
||||
void HandleEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
GetTarget()->ApplySpellImmune(GetId(), IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_ALL, true);
|
||||
}
|
||||
|
||||
void HandleEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
|
||||
{
|
||||
GetTarget()->ApplySpellImmune(GetId(), IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_ALL, false);
|
||||
}
|
||||
|
||||
void CalcPeriodic(AuraEffect const* /*effect*/, bool& isPeriodic, int32& amplitude)
|
||||
{
|
||||
isPeriodic = true;
|
||||
@@ -405,9 +395,6 @@ class spell_gen_bg_preparation : public AuraScript
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectApply += AuraEffectApplyFn(spell_gen_bg_preparation::HandleEffectApply, EFFECT_0, SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT, AURA_EFFECT_HANDLE_REAL);
|
||||
OnEffectRemove += AuraEffectRemoveFn(spell_gen_bg_preparation::HandleEffectRemove, EFFECT_0, SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT, AURA_EFFECT_HANDLE_REAL);
|
||||
|
||||
DoEffectCalcPeriodic += AuraEffectCalcPeriodicFn(spell_gen_bg_preparation::CalcPeriodic, EFFECT_0, SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT);
|
||||
OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_gen_bg_preparation::Update, EFFECT_0, SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT);
|
||||
}
|
||||
|
||||
@@ -4051,6 +4051,46 @@ class spell_item_gor_dreks_ointment : public SpellScript
|
||||
}
|
||||
};
|
||||
|
||||
enum Skettis
|
||||
{
|
||||
QUEST_FIRES_OVER_SKETTIS = 11008
|
||||
};
|
||||
|
||||
class spell_item_skyguard_blasting_charges : public SpellScript
|
||||
{
|
||||
PrepareSpellScript(spell_item_skyguard_blasting_charges);
|
||||
|
||||
void HandleOpenObject(SpellEffIndex effIndex)
|
||||
{
|
||||
PreventHitDefaultEffect(effIndex);
|
||||
if (GameObject* go = GetHitGObj())
|
||||
go->UseDoorOrButton();
|
||||
}
|
||||
|
||||
void HandleDummy(SpellEffIndex /*effIndex*/)
|
||||
{
|
||||
if (Unit* kaliri = GetHitUnit())
|
||||
kaliri->ToCreature()->DespawnOrUnsummon(0s, 30s);
|
||||
}
|
||||
|
||||
SpellCastResult CheckQuest()
|
||||
{
|
||||
if (Player* playerCaster = GetCaster()->ToPlayer())
|
||||
{
|
||||
if (playerCaster->GetQuestStatus(QUEST_FIRES_OVER_SKETTIS) == QUEST_STATUS_INCOMPLETE)
|
||||
return SPELL_CAST_OK;
|
||||
}
|
||||
return SPELL_FAILED_DONT_REPORT;
|
||||
}
|
||||
|
||||
void Register() override
|
||||
{
|
||||
OnEffectHitTarget += SpellEffectFn(spell_item_skyguard_blasting_charges::HandleOpenObject, EFFECT_1, SPELL_EFFECT_ACTIVATE_OBJECT);
|
||||
OnEffectHitTarget += SpellEffectFn(spell_item_skyguard_blasting_charges::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
|
||||
OnCheckCast += SpellCheckCastFn(spell_item_skyguard_blasting_charges::CheckQuest);
|
||||
}
|
||||
};
|
||||
|
||||
void AddSC_item_spell_scripts()
|
||||
{
|
||||
RegisterSpellScript(spell_item_massive_seaforium_charge);
|
||||
@@ -4175,4 +4215,5 @@ void AddSC_item_spell_scripts()
|
||||
RegisterSpellAndAuraScriptPair(spell_item_eye_of_grillok, spell_item_eye_of_grillok_aura);
|
||||
RegisterSpellScript(spell_item_fel_mana_potion);
|
||||
RegisterSpellScript(spell_item_gor_dreks_ointment);
|
||||
RegisterSpellScript(spell_item_skyguard_blasting_charges);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
#include "ScriptedCreature.h"
|
||||
#include "ScriptedGossip.h"
|
||||
#include "Spell.h"
|
||||
#include "WorldSession.h"
|
||||
|
||||
// Ours
|
||||
/*######
|
||||
|
||||
Reference in New Issue
Block a user