Merge branch 'master' into Playerbot

This commit is contained in:
Yunfan Li
2024-09-29 23:22:47 +08:00
74 changed files with 806 additions and 146 deletions
+6 -1
View File
@@ -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');
+178
View File
@@ -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;
+2 -2
View File
@@ -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);
}
+24 -6
View File
@@ -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;
+8 -6
View File
@@ -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;
}
+3 -3
View File
@@ -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
+2
View File
@@ -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);
+7 -6
View File
@@ -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);
+34 -8
View File
@@ -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))
+18 -1
View File
@@ -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();
-2
View File
@@ -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"
-1
View File
@@ -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"
-1
View File
@@ -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)
-1
View File
@@ -29,7 +29,6 @@
#include "ScriptMgr.h"
#include "SpellInfo.h"
#include "SpellMgr.h"
#include "UpdateMask.h"
#include "WorldPacket.h"
#include "WorldSession.h"
#include <cmath>
-1
View File
@@ -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"
-1
View File
@@ -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"
+3 -1
View File
@@ -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;
}
+7 -4
View File
@@ -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)
+2 -2
View File
@@ -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);
+3
View File
@@ -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);
}
+8 -1
View File
@@ -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];
+1
View File
@@ -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,
+1
View File
@@ -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);
}
+41
View File
@@ -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);
}
-1
View File
@@ -26,7 +26,6 @@
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
#include "Spell.h"
#include "WorldSession.h"
// Ours
/*######