latest github + bot fix

This commit is contained in:
mikx 2025-04-20 13:24:05 -04:00
parent 98f7a2ccfe
commit 3a5893003a
50 changed files with 6828 additions and 142 deletions

View File

@ -0,0 +1,51 @@
-- DB update 2025_03_21_00 -> 2025_03_22_00
--
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 13) AND (`SourceGroup` = 1) AND (`SourceEntry` IN (45635, 45635, 45635, 45635, 45635, 45635, 45623, 45635, 45623, 45635, 45633, 45633, 45633, 45622, 45633, 45633, 45633, 45622, 45633, 45633, 45585, 45585, 45585, 45585, 45585, 45585, 45585, 45585, 45585, 45586, 45585, 45586, 45585, 45585, 45585, 45585, 45585, 45585, 45585, 45585, 45585, 45585, 45585, 45585, 45585, 45585, 45585)) AND (`SourceId` = 0) AND (`ConditionTypeOrReference` = 31) AND (`ConditionTarget` = 0) AND (`ConditionValue1` = 3) AND (`ConditionValue2` = 23472) AND (`ConditionValue3` IN (54796, 54792, 54788, 54785, 54781, 54777, 54774, 54774, 54794, 54794, 54773, 54789, 54602, 54798, 54798, 54790, 54808, 54608, 54608, 54772, 54800, 54603, 54795, 54597, 54782, 54793, 54804, 54802, 54783, 54783, 54435, 54435, 54797, 54775, 54779, 54769, 54593, 54806, 54778, 54595, 54776, 54801, 54771, 54623, 54791, 54784, 54770));
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(13, 1, 45585, 0, 0, 31, 0, 3, 23472, 54435, 0, 0, 0, '', 'Felmyst - Strafe (Top) - target World Trigger '),
(13, 1, 45585, 0, 1, 31, 0, 3, 23472, 54593, 0, 0, 0, '', 'Felmyst - Strafe (Top) - target World Trigger '),
(13, 1, 45585, 0, 2, 31, 0, 3, 23472, 54595, 0, 0, 0, '', 'Felmyst - Strafe (Top) - target World Trigger '),
(13, 1, 45585, 0, 3, 31, 0, 3, 23472, 54597, 0, 0, 0, '', 'Felmyst - Strafe (Top) - target World Trigger '),
(13, 1, 45585, 0, 4, 31, 0, 3, 23472, 54603, 0, 0, 0, '', 'Felmyst - Strafe (Top) - target World Trigger '),
(13, 1, 45585, 0, 5, 31, 0, 3, 23472, 54623, 0, 0, 0, '', 'Felmyst - Strafe (Top) - target World Trigger '),
(13, 1, 45585, 0, 6, 31, 0, 3, 23472, 54769, 0, 0, 0, '', 'Felmyst - Strafe (Top) - target World Trigger '),
(13, 1, 45585, 0, 7, 31, 0, 3, 23472, 54770, 0, 0, 0, '', 'Felmyst - Strafe (Top) - target World Trigger '),
(13, 1, 45585, 0, 8, 31, 0, 3, 23472, 54771, 0, 0, 0, '', 'Felmyst - Strafe (Top) - target World Trigger '),
(13, 1, 45585, 0, 9, 31, 0, 3, 23472, 54775, 0, 0, 0, '', 'Felmyst - Strafe (Top) - target World Trigger '),
(13, 1, 45585, 0, 10, 31, 0, 3, 23472, 54776, 0, 0, 0, '', 'Felmyst - Strafe (Top) - target World Trigger '),
(13, 1, 45585, 0, 11, 31, 0, 3, 23472, 54778, 0, 0, 0, '', 'Felmyst - Strafe (Top) - target World Trigger '),
(13, 1, 45585, 0, 12, 31, 0, 3, 23472, 54779, 0, 0, 0, '', 'Felmyst - Strafe (Top) - target World Trigger '),
(13, 1, 45585, 0, 13, 31, 0, 3, 23472, 54782, 0, 0, 0, '', 'Felmyst - Strafe (Top) - target World Trigger '),
(13, 1, 45585, 0, 14, 31, 0, 3, 23472, 54783, 0, 0, 0, '', 'Felmyst - Strafe (Top) - target World Trigger '),
(13, 1, 45585, 0, 15, 31, 0, 3, 23472, 54784, 0, 0, 0, '', 'Felmyst - Strafe (Top) - target World Trigger '),
(13, 1, 45585, 0, 16, 31, 0, 3, 23472, 54791, 0, 0, 0, '', 'Felmyst - Strafe (Top) - target World Trigger '),
(13, 1, 45585, 0, 17, 31, 0, 3, 23472, 54793, 0, 0, 0, '', 'Felmyst - Strafe (Top) - target World Trigger '),
(13, 1, 45585, 0, 18, 31, 0, 3, 23472, 54795, 0, 0, 0, '', 'Felmyst - Strafe (Top) - target World Trigger '),
(13, 1, 45585, 0, 19, 31, 0, 3, 23472, 54797, 0, 0, 0, '', 'Felmyst - Strafe (Top) - target World Trigger '),
(13, 1, 45585, 0, 20, 31, 0, 3, 23472, 54800, 0, 0, 0, '', 'Felmyst - Strafe (Top) - target World Trigger '),
(13, 1, 45585, 0, 21, 31, 0, 3, 23472, 54801, 0, 0, 0, '', 'Felmyst - Strafe (Top) - target World Trigger '),
(13, 1, 45585, 0, 22, 31, 0, 3, 23472, 54802, 0, 0, 0, '', 'Felmyst - Strafe (Top) - target World Trigger '),
(13, 1, 45585, 0, 23, 31, 0, 3, 23472, 54804, 0, 0, 0, '', 'Felmyst - Strafe (Top) - target World Trigger '),
(13, 1, 45585, 0, 24, 31, 0, 3, 23472, 54806, 0, 0, 0, '', 'Felmyst - Strafe (Top) - target World Trigger '),
(13, 1, 45586, 0, 0, 31, 0, 3, 23472, 54435, 0, 0, 0, '', 'Felmyst - Strafe (Trigger Top) - target World Trigger '),
(13, 1, 45586, 0, 1, 31, 0, 3, 23472, 54783, 0, 0, 0, '', 'Felmyst - Strafe (Trigger Top) - target World Trigger '),
(13, 1, 45622, 0, 0, 31, 0, 3, 23472, 54608, 0, 0, 0, '', 'Felmyst - Strafe (Trigger Middle) - target World Trigger '),
(13, 1, 45622, 0, 1, 31, 0, 3, 23472, 54798, 0, 0, 0, '', 'Felmyst - Strafe (Trigger Middle) - target World Trigger '),
(13, 1, 45623, 0, 0, 31, 0, 3, 23472, 54774, 0, 0, 0, '', 'Felmyst - Strafe (Trigger Bottom) - target World Trigger '),
(13, 1, 45623, 0, 1, 31, 0, 3, 23472, 54794, 0, 0, 0, '', 'Felmyst - Strafe (Trigger Bottom) - target World Trigger '),
(13, 1, 45633, 0, 0, 31, 0, 3, 23472, 54602, 0, 0, 0, '', 'Felmyst - Strafe (Middle) - target World Trigger '),
(13, 1, 45633, 0, 1, 31, 0, 3, 23472, 54608, 0, 0, 0, '', 'Felmyst - Strafe (Middle) - target World Trigger '),
(13, 1, 45633, 0, 2, 31, 0, 3, 23472, 54772, 0, 0, 0, '', 'Felmyst - Strafe (Middle) - target World Trigger '),
(13, 1, 45633, 0, 3, 31, 0, 3, 23472, 54773, 0, 0, 0, '', 'Felmyst - Strafe (Middle) - target World Trigger '),
(13, 1, 45633, 0, 4, 31, 0, 3, 23472, 54789, 0, 0, 0, '', 'Felmyst - Strafe (Middle) - target World Trigger '),
(13, 1, 45633, 0, 5, 31, 0, 3, 23472, 54790, 0, 0, 0, '', 'Felmyst - Strafe (Middle) - target World Trigger '),
(13, 1, 45633, 0, 6, 31, 0, 3, 23472, 54798, 0, 0, 0, '', 'Felmyst - Strafe (Middle) - target World Trigger '),
(13, 1, 45633, 0, 7, 31, 0, 3, 23472, 54808, 0, 0, 0, '', 'Felmyst - Strafe (Middle) - target World Trigger '),
(13, 1, 45635, 0, 0, 31, 0, 3, 23472, 54774, 0, 0, 0, '', 'Felmyst - Strafe (Bottom) - target World Trigger '),
(13, 1, 45635, 0, 1, 31, 0, 3, 23472, 54777, 0, 0, 0, '', 'Felmyst - Strafe (Bottom) - target World Trigger '),
(13, 1, 45635, 0, 2, 31, 0, 3, 23472, 54781, 0, 0, 0, '', 'Felmyst - Strafe (Bottom) - target World Trigger '),
(13, 1, 45635, 0, 3, 31, 0, 3, 23472, 54785, 0, 0, 0, '', 'Felmyst - Strafe (Bottom) - target World Trigger '),
(13, 1, 45635, 0, 4, 31, 0, 3, 23472, 54788, 0, 0, 0, '', 'Felmyst - Strafe (Bottom) - target World Trigger '),
(13, 1, 45635, 0, 5, 31, 0, 3, 23472, 54792, 0, 0, 0, '', 'Felmyst - Strafe (Bottom) - target World Trigger '),
(13, 1, 45635, 0, 6, 31, 0, 3, 23472, 54794, 0, 0, 0, '', 'Felmyst - Strafe (Bottom) - target World Trigger '),
(13, 1, 45635, 0, 7, 31, 0, 3, 23472, 54796, 0, 0, 0, '', 'Felmyst - Strafe (Bottom) - target World Trigger ');

View File

@ -0,0 +1,21 @@
-- DB update 2025_03_22_00 -> 2025_03_22_01
-- Pack after Eredar Twins
DELETE FROM `creature_formations` WHERE `leaderGUID` = 47607;
INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES
(47607, 47607, 0, 0, 3, 0, 0),
(47607, 47313, 0, 0, 3, 0, 0),
(47607, 47471, 0, 0, 3, 0, 0),
(47607, 47768, 0, 0, 3, 0, 0),
(47607, 47608, 0, 0, 3, 0, 0),
(47607, 47769, 0, 0, 3, 0, 0);
-- Pack before M'uru
DELETE FROM `creature_formations` WHERE `leaderGUID` = 47470;
INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES
(47470, 47470, 0, 0, 3, 0, 0),
(47470, 47475, 0, 0, 3, 0, 0),
(47470, 47578, 0, 0, 3, 0, 0),
(47470, 47875, 0, 0, 3, 0, 0),
(47470, 47897, 0, 0, 3, 0, 0),
(47470, 47884, 0, 0, 3, 0, 0);

View File

@ -0,0 +1,15 @@
-- DB update 2025_03_22_01 -> 2025_03_22_02
-- Update Comments and row 7 added.
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 25744;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 25744);
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
(25744, 0, 0, 1, 37, 0, 100, 512, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Dark Fiend - On Initialize - Set Reactstate Passive'),
(25744, 0, 1, 2, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 11, 45934, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Dark Fiend - On Initialize - Cast \'Dark Fiend\''),
(25744, 0, 2, 3, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 11, 45936, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Dark Fiend - On Initialize - Cast \'Dark Fiend\''),
(25744, 0, 3, 0, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 42, 1, 100, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Dark Fiend - On Initialize - Set Invincibility Hp 1'),
(25744, 0, 4, 0, 60, 0, 100, 1, 0, 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 21, 50, 0, 0, 0, 0, 0, 0, 0, 'Dark Fiend - On Update - Start Attacking (No Repeat)'),
(25744, 0, 5, 6, 9, 0, 100, 1, 0, 0, 0, 0, 0, 4, 11, 45944, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Dark Fiend - Within 0-4 Range - Cast \'Dark Fiend\' (No Repeat)'),
(25744, 0, 6, 0, 61, 0, 100, 512, 0, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Dark Fiend - Within 0-0 Range - Despawn Instant (No Repeat)'),
(25744, 0, 7, 0, 23, 0, 100, 512, 45934, 0, 500, 500, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Dark Fiend - On Aura \'Dark Fiend\' - Despawn Instant');

View File

@ -0,0 +1,3 @@
-- DB update 2025_03_22_02 -> 2025_03_24_00
--
UPDATE `creature_template` SET `flags_extra` = `flags_extra` &~2147483648 WHERE `entry` = 25315;

View File

@ -0,0 +1,4 @@
-- DB update 2025_03_24_00 -> 2025_03_25_00
-- Taunt Immune
UPDATE `creature_template` SET `flags_extra` = `flags_extra`|256 WHERE `entry` IN (25166, 25165);

View File

@ -0,0 +1,9 @@
-- DB update 2025_03_25_00 -> 2025_03_25_01
-- Update Alumeth the Ascended 32300 to repeat around psychicscream ~20 sec
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 32300;
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 32300);
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
(32300, 0, 0, 0, 0, 0, 100, 0, 8000, 9000, 8000, 9000, 0, 0, 11, 60472, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Alumeth the Ascended - In Combat - Cast \'Mind Flay\''),
(32300, 0, 1, 0, 0, 0, 100, 0, 8000, 10000, 18000, 22000, 0, 0, 11, 34322, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Alumeth the Ascended - In Combat - Cast \'Psychic Scream\''),
(32300, 0, 2, 0, 0, 0, 100, 0, 9000, 12000, 9000, 12000, 0, 0, 11, 37978, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Alumeth the Ascended - In Combat - Cast \'Renew\''),
(32300, 0, 3, 0, 0, 0, 100, 0, 7000, 10000, 7000, 10000, 0, 0, 11, 34942, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Alumeth the Ascended - In Combat - Cast \'Shadow Word: Pain\'');

View File

@ -0,0 +1,4 @@
-- DB update 2025_03_25_01 -> 2025_03_27_00
-- Add Hard Reset Extra Flag
UPDATE `creature_template` SET `flags_extra` = `flags_extra`|2147483648 WHERE `entry` IN (25741);

View File

@ -0,0 +1,3 @@
-- DB update 2025_03_27_00 -> 2025_03_27_01
-- Set Kirtonos the Herald level to 60
UPDATE `creature_template` SET `minlevel` = 60, `maxlevel` = 60 WHERE (`entry` = 10506);

View File

@ -0,0 +1,6 @@
-- DB update 2025_03_27_01 -> 2025_03_28_00
-- Add Condition to use Scarlet Cannons
DELETE FROM `conditions` WHERE (`SourceTypeOrReferenceId` = 18) AND (`SourceGroup` = 28833) AND (`SourceEntry` = 52447) AND (`SourceId` = 0) AND (`ElseGroup` = 0) AND (`ConditionTypeOrReference` = 9) AND (`ConditionTarget` = 0) AND (`ConditionValue1` = 12701) AND (`ConditionValue2` = 0) AND (`ConditionValue3` = 0);
INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
(18, 28833, 52447, 0, 0, 9, 0, 12701, 0, 0, 0, 0, 0, '', 'Scarlet Cannon spellclick require Massacre at Lights Point quest taken');

View File

@ -0,0 +1,3 @@
-- DB update 2025_03_28_00 -> 2025_03_29_00
-- Matches the Heroic Faction to the base brann, Adds "Brann Bronzebeard" (1) [Heroic] to Heroic Version | 32'052 => 40'065 HP
UPDATE `creature_template` SET `faction` = 1665, `difficulty_entry_1` = 31366 WHERE (`entry` = 28070);

View File

@ -14,11 +14,11 @@ class mxwow_bosskill : public PlayerScript
public: public:
mxwow_bosskill() : PlayerScript("mxwow_bosskill") { } mxwow_bosskill() : PlayerScript("mxwow_bosskill") {}
void OnPlayerLogin(Player* player) override void OnPlayerLogin(Player* player) override
{ {
} }
void OnPlayerCreatureKill(Player* player, Creature* boss) { void OnPlayerCreatureKill(Player* player, Creature* boss) {
@ -39,37 +39,94 @@ public:
float pLife; float pLife;
bool pGrouped; bool pGrouped;
if (boss->isWorldBoss() || boss->IsDungeonBoss()) { if (boss->isWorldBoss() || boss->IsDungeonBoss()) {
if (boss->isWorldBoss()) { mType = "Raid"; } else { mType = "Donjon"; } if (boss->isWorldBoss()) { mType = "Raid"; }
else { mType = "Donjon"; }
uint32 contentDifId;
bName = boss->GetName(); bName = boss->GetName();
map = player->GetMap(); map = player->GetMap();
pName = player->GetName();
piLevel = player->GetAverageItemLevelForDF(); piLevel = player->GetAverageItemLevelForDF();
pMapName = map->GetMapName(); pMapName = map->GetMapName();
pGrouped = player->GetGroup(); pGrouped = player->GetGroup();
pLife = player->GetHealthPct(); pLife = player->GetHealthPct();
int RandIndex = rand() % 8; int RandIndex = rand() % 8;
if (player->GetMap()->IsHeroic()) { if (player->GetMap()->IsHeroic()) {
contentDifficulty = "|cffff0000"; contentDifficulty = "|cffff0000";
contentDifName = "|cffff0000Heroic"; contentDifName = "|cffff0000Heroic";
contentDifId = 1;
} }
else { else {
contentDifficulty = "|cff00ff00"; contentDifficulty = "|cff00ff00";
contentDifName = "|cff00ff00Normal"; contentDifName = "|cff00ff00Normal";
contentDifId = 0;
} }
if (sConfigMgr->GetOption<bool>("MxWoW_BossKill.Enabled", true)) if (!pGrouped) {
{ KillManager(player, boss, map);
//ss << "|cffabeeff[MxW] [" << GetPlayerColor(player) << pName << "|cffabeeff][iL"<< piLevel <<"][" << pLife << "%] a tué [|cffff1100" << bName << "|cffabeeff][" << contentDifficulty << pMapName << "|cffabeeff]"; //ss << "|cffabeeff[MxW] [" << GetPlayerColor(player) << pName << "|cffabeeff][iL"<< piLevel <<"][" << pLife << "%] a tué [|cffff1100" << bName << "|cffabeeff][" << contentDifficulty << pMapName << "|cffabeeff]";
/*pName = p->GetName();
line00 << "|cffabeeff[MxW][" << mType << "]"; line00 << "|cffabeeff[MxW][" << mType << "]";
line01 << "|cffabeeff[" << contentDifficulty << ""<< pMapName <<"|cffabeeff]["<< contentDifName <<"|cffabeeff]"; line01 << "|cffabeeff[" << contentDifficulty << "" << pMapName << "|cffabeeff][" << contentDifName << "|cffabeeff]";
line02 << "|cffabeeff["<< GetPlayerColor(player)<< pName <<"|cffabeeff][iL"<< piLevel <<"]["<< pLife <<"%]"; line02 << "|cffabeeff[" << GetPlayerColor(player) << pName << "|cffabeeff][iL" << piLevel << "][" << pLife << "%]";
line03 << "|cffabeeff[|cffff1100"<< bName <<"|cffabeeff] "<< GenKillMessage(RandIndex) <<"."; line03 << "|cffabeeff[|cffff1100" << bName << "|cffabeeff] " << GenKillMessage(RandIndex) << ".";
sWorldSessionMgr->SendServerMessage(SERVER_MSG_STRING, line00.str().c_str()); sWorldSessionMgr->SendServerMessage(SERVER_MSG_STRING, line00.str().c_str());
sWorldSessionMgr->SendServerMessage(SERVER_MSG_STRING, line01.str().c_str()); sWorldSessionMgr->SendServerMessage(SERVER_MSG_STRING, line01.str().c_str());
sWorldSessionMgr->SendServerMessage(SERVER_MSG_STRING, line02.str().c_str()); sWorldSessionMgr->SendServerMessage(SERVER_MSG_STRING, line02.str().c_str());
sWorldSessionMgr->SendServerMessage(SERVER_MSG_STRING, line03.str().c_str()); sWorldSessionMgr->SendServerMessage(SERVER_MSG_STRING, line03.str().c_str());
ChatHandler(p->GetSession()).PSendSysMessage(ss.str().c_str());*/
} }
} else {
Group* group = player->GetGroup();
Group::MemberSlotList const& groupSlot = group->GetMemberSlots();
for (Group::member_citerator itr = groupSlot.begin(); itr != groupSlot.end(); itr++)
{
Player* p = ObjectAccessor::FindPlayer(itr->guid);
KillManager(p, boss, map);
/*pName = p->GetName();
line00 << "|cffabeeff[MxW][" << mType << "]";
line01 << "|cffabeeff[" << contentDifficulty << "" << pMapName << "|cffabeeff][" << contentDifName << "|cffabeeff]";
line02 << "|cffabeeff[" << GetPlayerColor(player) << pName << "|cffabeeff][iL" << piLevel << "][" << pLife << "%]";
line03 << "|cffabeeff[|cffff1100" << bName << "|cffabeeff] " << GenKillMessage(RandIndex) << ".";
sWorldSessionMgr->SendServerMessage(SERVER_MSG_STRING, line00.str().c_str());
sWorldSessionMgr->SendServerMessage(SERVER_MSG_STRING, line01.str().c_str());
sWorldSessionMgr->SendServerMessage(SERVER_MSG_STRING, line02.str().c_str());
sWorldSessionMgr->SendServerMessage(SERVER_MSG_STRING, line03.str().c_str());
ChatHandler(p->GetSession()).PSendSysMessage(ss.str().c_str());*/
}
}
}
}
void KillManager(Player* player, Creature* boss, Map* map) {
uint32 aId = player->GetSession()->GetAccountId();
uint32 pId = player->GetGUID().GetRawValue();
uint32 mapId = map->GetId();
uint32 cId = boss->GetCreatureTemplate()->Entry;
uint32 contentDifId;
if (player->GetMap()->IsHeroic()) {
contentDifId = 1;
}
else {
contentDifId = 0;
}
QueryResult queryBossKill = LoginDatabase.Query("SELECT * FROM mxw_boss_kill WHERE accountid = {} AND charid = {} AND creatureid = {} AND instanceid = {} AND difficulty = {}", aId, pId, cId, mapId, contentDifId);
if (queryBossKill) {
uint32 killCount = (*queryBossKill)[5].Get<uint32>();
killCount++;
LoginDatabase.Execute("UPDATE mxw_boss_kill SET killcount = {} WHERE accountid = {} AND charid = {} AND creatureid = {} AND instanceid = {} AND difficulty = {}", killCount, aId, pId, cId, mapId, contentDifId);
}
else {
LoginDatabase.Execute("INSERT INTO mxw_boss_kill (accountid,charid,creatureid,instanceid,difficulty,killcount) VALUES ({}, {}, {}, {}, {}, {})", aId, pId, cId, mapId, contentDifId, 1);
}
QueryResult queryInstanceKill = LoginDatabase.Query("SELECT * FROM mxw_boss_instance WHERE instanceid = {} AND difficulty = {} AND bossid = {}", mapId, contentDifId, cId);
if (queryInstanceKill) {
uint32 killCount = (*queryInstanceKill)[3].Get<uint32>();
killCount++;
LoginDatabase.Execute("UPDATE mxw_boss_instance SET killcount = {} WHERE instanceid = {} AND difficulty = {} AND bossid = {} ", killCount, mapId, contentDifId, cId);
}
else {
LoginDatabase.Execute("INSERT INTO mxw_boss_instance (instanceid,difficulty,bossid,killcount) VALUES ({}, {}, {}, {})", mapId, contentDifId, cId, 1);
}
} }
std::string GenKillMessage(const int i) std::string GenKillMessage(const int i)

View File

@ -1,19 +1,7 @@
[worldserver] [worldserver]
##################################################################################################### ## MxWoW - Bounty (Enable / Disable)
# #
# MxWoW - Boss Kill (Enable / Disable) #
# Description: Enables or disable the script for mxwow_bosskill #
# Default: 1 (Enable) #
# 0 (Disable) #
# #
MxWoW_Bounty.Enabled = 1 MxWoW_Bounty.Enabled = 1
##################################################################################################### ## Value in copper for bounty reward.
##################################################################################################### MxWoW_Bounty.Base.Copper = 1250
# # ## Hour for daily bounty reset (0,23 / 6 = 6am / 20 = 8pm)
# MxWoW - Boss Kill (Enable / Disable) # MxWoW_Bounty.Daily.ResetHour = 6
# Description: Enables or disable the script for mxwow_bosskill #
# Default: 1 (Enable) #
# 0 (Disable) #
# #
MxWoW_Bounty.Base.Copper = 100
#####################################################################################################

View File

@ -8,6 +8,8 @@
#include "Player.h" #include "Player.h"
#include "Chat.h" #include "Chat.h"
#include <WorldSessionMgr.h> #include <WorldSessionMgr.h>
#include <ZoneManager.h>
#include <EventManager.h>
class mxwow_bounty : public PlayerScript class mxwow_bounty : public PlayerScript
{ {
@ -18,7 +20,18 @@ mxwow_bounty() : PlayerScript("mxwow_bounty") { }
void OnPlayerLogin(Player* player) override void OnPlayerLogin(Player* player) override
{ {
std::ostringstream ss;
uint32 randZone = rand() % 9;
ss << "Random Zone: " << ZoneManager::RandomZoneId(randZone) << " / " << ZoneManager::RandomZoneNameLocale_frFR(randZone);
ChatHandler(player->GetSession()).PSendSysMessage(ss.str().c_str());
//EventManager::CreateNewEvent(player);
}
void OnPlayerSave(Player* player) {
/*if (EventManager::CheckBountyReset()) {
EventManager::CleanLastEvent();
EventManager::CreateNewEvent(player);
}*/
} }
void OnPlayerCreatureKill(Player* player, Creature* creature) { void OnPlayerCreatureKill(Player* player, Creature* creature) {

View File

@ -73,7 +73,7 @@ public:
expMulti = 10; expMulti = 10;
break; break;
} }
amount = amount * expMulti; amount *= expMulti;
if (sConfigMgr->GetOption<bool>("MxWoW_ToonMaster.Verbose", true) && plevel < 80) if (sConfigMgr->GetOption<bool>("MxWoW_ToonMaster.Verbose", true) && plevel < 80)
{ {
ss << "|cffabeeff[MxW][ToonMaster]["<< cMPL <<"xNiv.80] Bonus: EXPx"<<expMulti; ss << "|cffabeeff[MxW][ToonMaster]["<< cMPL <<"xNiv.80] Bonus: EXPx"<<expMulti;

View File

@ -544,6 +544,8 @@ AiPlayerbot.DisableDeathKnightLogin = 0
# Default: 0 # Default: 0
AiPlayerbot.LimitTalentsExpansion = 0 AiPlayerbot.LimitTalentsExpansion = 0
# Allow random bots to trade
AiPlayerbot.EnableRandomBotTrading = 1
# #
# #
# #
@ -636,10 +638,10 @@ AiPlayerbot.HunterWolfPet = 0
# #
# #
# Specify percent of active bots # Specify percent of active bots
# The default is 10. With 10% of all bots going active or inactive each minute. Regardless # The default is 100%, but would be automatically adjusted if botActiveAloneSmartScale
# This value is only applied to inactive areas where no real-players are detected, when # is enabled. Regardless, this value is only applied to inactive areas where no real-players
# real-players are nearby, friend, group, guild, bg, instances etc the value is always # are detected. When real-players are nearby, friend, group, guild, BGs, instances etc,
# enforced to 100% # the value is always enforced to 100%
AiPlayerbot.BotActiveAlone = 100 AiPlayerbot.BotActiveAlone = 100
# Force botActiveAlone when bot is ... of real player # Force botActiveAlone when bot is ... of real player

View File

@ -374,7 +374,9 @@ void PlayerbotAI::UpdateAIGroupMembership()
PlayerbotAI* leaderAI = GET_PLAYERBOT_AI(leader); PlayerbotAI* leaderAI = GET_PLAYERBOT_AI(leader);
if (leaderAI && !leaderAI->IsRealPlayer()) if (leaderAI && !leaderAI->IsRealPlayer())
{ {
bot->RemoveFromGroup(); WorldPacket* packet = new WorldPacket(CMSG_GROUP_DISBAND);
bot->GetSession()->QueuePacket(packet);
// bot->RemoveFromGroup();
ResetStrategies(); ResetStrategies();
} }
} }
@ -399,7 +401,9 @@ void PlayerbotAI::UpdateAIGroupMembership()
} }
if (!hasRealPlayer) if (!hasRealPlayer)
{ {
bot->RemoveFromGroup(); WorldPacket* packet = new WorldPacket(CMSG_GROUP_DISBAND);
bot->GetSession()->QueuePacket(packet);
// bot->RemoveFromGroup();
ResetStrategies(); ResetStrategies();
} }
} }
@ -1534,7 +1538,7 @@ void PlayerbotAI::ApplyInstanceStrategies(uint32 mapId, bool tellMaster)
strategyName = "wotlk-hol"; // Halls of Lightning strategyName = "wotlk-hol"; // Halls of Lightning
break; break;
case 603: case 603:
strategyName = "uld"; strategyName = "uld"; // Ulduar
break; break;
case 604: case 604:
strategyName = "wotlk-gd"; // Gundrak strategyName = "wotlk-gd"; // Gundrak
@ -1551,8 +1555,11 @@ void PlayerbotAI::ApplyInstanceStrategies(uint32 mapId, bool tellMaster)
case 619: case 619:
strategyName = "wotlk-ok"; // Ahn'kahet: The Old Kingdom strategyName = "wotlk-ok"; // Ahn'kahet: The Old Kingdom
break; break;
case 624:
strategyName = "voa"; // Vault of Archavon
break;
case 631: case 631:
strategyName = "icc"; strategyName = "icc"; // Icecrown Citadel
break; break;
case 632: case 632:
strategyName = "wotlk-fos"; // The Forge of Souls strategyName = "wotlk-fos"; // The Forge of Souls

View File

@ -505,6 +505,7 @@ bool PlayerbotAIConfig::Initialize()
limitGearExpansion = sConfigMgr->GetOption<int32>("AiPlayerbot.LimitGearExpansion", 1); limitGearExpansion = sConfigMgr->GetOption<int32>("AiPlayerbot.LimitGearExpansion", 1);
randombotStartingLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.RandombotStartingLevel", 5); randombotStartingLevel = sConfigMgr->GetOption<int32>("AiPlayerbot.RandombotStartingLevel", 5);
enablePeriodicOnlineOffline = sConfigMgr->GetOption<bool>("AiPlayerbot.EnablePeriodicOnlineOffline", false); enablePeriodicOnlineOffline = sConfigMgr->GetOption<bool>("AiPlayerbot.EnablePeriodicOnlineOffline", false);
enableRandomBotTrading = sConfigMgr->GetOption<bool>("AiPlayerbot.EnableRandomBotTrading", true);
periodicOnlineOfflineRatio = sConfigMgr->GetOption<float>("AiPlayerbot.PeriodicOnlineOfflineRatio", 2.0); periodicOnlineOfflineRatio = sConfigMgr->GetOption<float>("AiPlayerbot.PeriodicOnlineOfflineRatio", 2.0);
gearscorecheck = sConfigMgr->GetOption<bool>("AiPlayerbot.GearScoreCheck", false); gearscorecheck = sConfigMgr->GetOption<bool>("AiPlayerbot.GearScoreCheck", false);
randomBotPreQuests = sConfigMgr->GetOption<bool>("AiPlayerbot.PreQuests", true); randomBotPreQuests = sConfigMgr->GetOption<bool>("AiPlayerbot.PreQuests", true);

View File

@ -313,6 +313,7 @@ public:
bool autoLearnQuestSpells; bool autoLearnQuestSpells;
bool autoTeleportForLevel; bool autoTeleportForLevel;
bool randomBotGroupNearby; bool randomBotGroupNearby;
bool enableRandomBotTrading;
uint32 tweakValue; // Debugging config uint32 tweakValue; // Debugging config
uint32 randomBotArenaTeamCount; uint32 randomBotArenaTeamCount;

View File

@ -27,6 +27,8 @@
#include "raids/obsidiansanctum/RaidOsActionContext.h" #include "raids/obsidiansanctum/RaidOsActionContext.h"
#include "raids/obsidiansanctum/RaidOsTriggerContext.h" #include "raids/obsidiansanctum/RaidOsTriggerContext.h"
#include "raids/eyeofeternity/RaidEoEActionContext.h" #include "raids/eyeofeternity/RaidEoEActionContext.h"
#include "raids/vaultofarchavon/RaidVoATriggerContext.h"
#include "raids/vaultofarchavon/RaidVoAActionContext.h"
#include "raids/eyeofeternity/RaidEoETriggerContext.h" #include "raids/eyeofeternity/RaidEoETriggerContext.h"
#include "raids/moltencore/RaidMcActionContext.h" #include "raids/moltencore/RaidMcActionContext.h"
#include "raids/moltencore/RaidMcTriggerContext.h" #include "raids/moltencore/RaidMcTriggerContext.h"
@ -54,6 +56,7 @@ AiObjectContext::AiObjectContext(PlayerbotAI* botAI) : PlayerbotAIAware(botAI)
actionContexts.Add(new RaidNaxxActionContext()); actionContexts.Add(new RaidNaxxActionContext());
actionContexts.Add(new RaidOsActionContext()); actionContexts.Add(new RaidOsActionContext());
actionContexts.Add(new RaidEoEActionContext()); actionContexts.Add(new RaidEoEActionContext());
actionContexts.Add(new RaidVoAActionContext());
actionContexts.Add(new RaidUlduarActionContext()); actionContexts.Add(new RaidUlduarActionContext());
actionContexts.Add(new RaidIccActionContext()); actionContexts.Add(new RaidIccActionContext());
actionContexts.Add(new WotlkDungeonUKActionContext()); actionContexts.Add(new WotlkDungeonUKActionContext());
@ -79,6 +82,7 @@ AiObjectContext::AiObjectContext(PlayerbotAI* botAI) : PlayerbotAIAware(botAI)
triggerContexts.Add(new RaidNaxxTriggerContext()); triggerContexts.Add(new RaidNaxxTriggerContext());
triggerContexts.Add(new RaidOsTriggerContext()); triggerContexts.Add(new RaidOsTriggerContext());
triggerContexts.Add(new RaidEoETriggerContext()); triggerContexts.Add(new RaidEoETriggerContext());
triggerContexts.Add(new RaidVoATriggerContext());
triggerContexts.Add(new RaidUlduarTriggerContext()); triggerContexts.Add(new RaidUlduarTriggerContext());
triggerContexts.Add(new RaidIccTriggerContext()); triggerContexts.Add(new RaidIccTriggerContext());
triggerContexts.Add(new WotlkDungeonUKTriggerContext()); triggerContexts.Add(new WotlkDungeonUKTriggerContext());

View File

@ -31,7 +31,10 @@ bool AttackEnemyFlagCarrierAction::isUseful()
bool AttackAnythingAction::isUseful() bool AttackAnythingAction::isUseful()
{ {
if (!botAI->AllowActivity(GRIND_ACTIVITY)) // Bot not allowed to be active if (!bot || !botAI) // Prevents invalid accesses
return false;
if (!botAI->AllowActivity(GRIND_ACTIVITY)) // Bot cannot be active
return false; return false;
if (botAI->HasStrategy("stay", BOT_STATE_NON_COMBAT)) if (botAI->HasStrategy("stay", BOT_STATE_NON_COMBAT))
@ -41,19 +44,17 @@ bool AttackAnythingAction::isUseful()
return false; return false;
Unit* target = GetTarget(); Unit* target = GetTarget();
if (!target || !target->IsInWorld()) // Checks if the target is valid and in the world
if (!target)
return false; return false;
std::string const name = std::string(target->GetName()); std::string const name = std::string(target->GetName());
// Check for invalid targets: Dummy, Charge Target, Melee Target, Ranged Target
if (!name.empty() && if (!name.empty() &&
(name.find("Dummy") != std::string::npos || (name.find("Dummy") != std::string::npos ||
name.find("Charge Target") != std::string::npos || name.find("Charge Target") != std::string::npos ||
name.find("Melee Target") != std::string::npos || name.find("Melee Target") != std::string::npos ||
name.find("Ranged Target") != std::string::npos)) name.find("Ranged Target") != std::string::npos))
{ {
return false; // Target is one of the disallowed types return false;
} }
return true; return true;

View File

@ -53,6 +53,9 @@ bool InviteNearbyToGroupAction::Execute(Event event)
if (!player) if (!player)
continue; continue;
if (!player->GetMapId() != bot->GetMapId())
continue;
if (player->GetGroup()) if (player->GetGroup())
continue; continue;

View File

@ -12,6 +12,7 @@
#include "Opcodes.h" #include "Opcodes.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "World.h" #include "World.h"
#include "WorldPacket.h"
using namespace lfg; using namespace lfg;
@ -179,9 +180,12 @@ bool LfgRoleCheckAction::Execute(Event event)
// if (currentRoles == newRoles) // if (currentRoles == newRoles)
// return false; // return false;
sLFGMgr->SetRoles(bot->GetGUID(), newRoles);
WorldPacket* packet = new WorldPacket(CMSG_LFG_SET_ROLES);
sLFGMgr->UpdateRoleCheck(group->GetGUID(), bot->GetGUID(), newRoles); *packet << (uint8)newRoles;
bot->GetSession()->QueuePacket(packet);
// sLFGMgr->SetRoles(bot->GetGUID(), newRoles);
// sLFGMgr->UpdateRoleCheck(group->GetGUID(), bot->GetGUID(), newRoles);
LOG_INFO("playerbots", "Bot {} {}:{} <{}>: LFG roles checked", bot->GetGUID().ToString().c_str(), LOG_INFO("playerbots", "Bot {} {}:{} <{}>: LFG roles checked", bot->GetGUID().ToString().c_str(),
bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", bot->GetLevel(), bot->GetName().c_str()); bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", bot->GetLevel(), bot->GetName().c_str());
@ -206,11 +210,13 @@ bool LfgAcceptAction::Execute(Event event)
if (bot->IsInCombat() || bot->isDead()) if (bot->IsInCombat() || bot->isDead())
{ {
/// @FIXME: Race condition
LOG_INFO("playerbots", "Bot {} {}:{} <{}> is in combat and refuses LFG proposal {}", LOG_INFO("playerbots", "Bot {} {}:{} <{}> is in combat and refuses LFG proposal {}",
bot->GetGUID().ToString().c_str(), bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", bot->GetLevel(), bot->GetGUID().ToString().c_str(), bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", bot->GetLevel(),
bot->GetName().c_str(), id); bot->GetName().c_str(), id);
sLFGMgr->UpdateProposal(id, bot->GetGUID(), true); WorldPacket* packet = new WorldPacket(CMSG_LFG_PROPOSAL_RESULT);
*packet << (uint32)id << (bool)false;
bot->GetSession()->QueuePacket(packet);
// sLFGMgr->UpdateProposal(id, bot->GetGUID(), true);
return true; return true;
} }
@ -220,8 +226,10 @@ bool LfgAcceptAction::Execute(Event event)
botAI->GetAiObjectContext()->GetValue<uint32>("lfg proposal")->Set(0); botAI->GetAiObjectContext()->GetValue<uint32>("lfg proposal")->Set(0);
bot->ClearUnitState(UNIT_STATE_ALL_STATE); bot->ClearUnitState(UNIT_STATE_ALL_STATE);
/// @FIXME: Race condition WorldPacket* packet = new WorldPacket(CMSG_LFG_PROPOSAL_RESULT);
sLFGMgr->UpdateProposal(id, bot->GetGUID(), true); *packet << (uint32)id << (bool)true;
bot->GetSession()->QueuePacket(packet);
// sLFGMgr->UpdateProposal(id, bot->GetGUID(), true);
if (sRandomPlayerbotMgr->IsRandomBot(bot) && !bot->GetGroup()) if (sRandomPlayerbotMgr->IsRandomBot(bot) && !bot->GetGroup())
{ {
@ -259,7 +267,9 @@ bool LfgLeaveAction::Execute(Event event)
if (sLFGMgr->GetState(bot->GetGUID()) > LFG_STATE_QUEUED) if (sLFGMgr->GetState(bot->GetGUID()) > LFG_STATE_QUEUED)
return false; return false;
sLFGMgr->LeaveLfg(bot->GetGUID()); WorldPacket* packet = new WorldPacket(CMSG_LFG_LEAVE);
bot->GetSession()->QueuePacket(packet);
// sLFGMgr->LeaveLfg(bot->GetGUID());
return true; return true;
} }
@ -278,7 +288,10 @@ bool LfgTeleportAction::Execute(Event event)
bot->ClearUnitState(UNIT_STATE_ALL_STATE); bot->ClearUnitState(UNIT_STATE_ALL_STATE);
sLFGMgr->TeleportPlayer(bot, out); WorldPacket* packet = new WorldPacket(CMSG_LFG_TELEPORT);
*packet << out;
bot->GetSession()->QueuePacket(packet);
// sLFGMgr->TeleportPlayer(bot, out);
return true; return true;
} }

View File

@ -32,6 +32,12 @@ bool TradeStatusAction::Execute(Event event)
return false; return false;
} }
if (!sPlayerbotAIConfig->enableRandomBotTrading && sRandomPlayerbotMgr->IsRandomBot(bot))
{
bot->Whisper("Trading is disabled", LANG_UNIVERSAL, trader);
return false;
}
// Allow trades from group members or bots // Allow trades from group members or bots
if ((!bot->GetGroup() || !bot->GetGroup()->IsMember(trader->GetGUID())) && if ((!bot->GetGroup() || !bot->GetGroup()->IsMember(trader->GetGUID())) &&
(trader != master || !botAI->GetSecurity()->CheckLevelFor(PLAYERBOT_SECURITY_ALLOW_ALL, true, master)) && (trader != master || !botAI->GetSecurity()->CheckLevelFor(PLAYERBOT_SECURITY_ALLOW_ALL, true, master)) &&
@ -49,7 +55,7 @@ bool TradeStatusAction::Execute(Event event)
uint32 status; uint32 status;
p >> status; p >> status;
if (status == TRADE_STATUS_TRADE_ACCEPT) if (status == TRADE_STATUS_TRADE_ACCEPT || (status == TRADE_STATUS_BACK_TO_TRADE && trader->GetTradeData() && trader->GetTradeData()->IsAccepted()))
{ {
WorldPacket p; WorldPacket p;
uint32 status = 0; uint32 status = 0;
@ -122,12 +128,13 @@ bool TradeStatusAction::Execute(Event event)
void TradeStatusAction::BeginTrade() void TradeStatusAction::BeginTrade()
{ {
Player* trader = bot->GetTrader();
if (!trader || GET_PLAYERBOT_AI(bot->GetTrader()))
return;
WorldPacket p; WorldPacket p;
bot->GetSession()->HandleBeginTradeOpcode(p); bot->GetSession()->HandleBeginTradeOpcode(p);
if (GET_PLAYERBOT_AI(bot->GetTrader()))
return;
ListItemsVisitor visitor; ListItemsVisitor visitor;
IterateItems(&visitor); IterateItems(&visitor);
@ -149,7 +156,7 @@ void TradeStatusAction::BeginTrade()
bool TradeStatusAction::CheckTrade() bool TradeStatusAction::CheckTrade()
{ {
Player* trader = bot->GetTrader(); Player* trader = bot->GetTrader();
if (!bot->GetTradeData() || !trader->GetTradeData()) if (!bot->GetTradeData() || !trader || !trader->GetTradeData())
return false; return false;
if (!botAI->HasActivePlayerMaster() && GET_PLAYERBOT_AI(bot->GetTrader())) if (!botAI->HasActivePlayerMaster() && GET_PLAYERBOT_AI(bot->GetTrader()))

View File

@ -48,8 +48,8 @@ bool UseMeetingStoneAction::Execute(Event event)
return false; return false;
GameObjectTemplate const* goInfo = gameObject->GetGOInfo(); GameObjectTemplate const* goInfo = gameObject->GetGOInfo();
if (!goInfo || goInfo->type != GAMEOBJECT_TYPE_SUMMONING_RITUAL) if (!goInfo || goInfo->entry != 179944)
return false; return false;
return Teleport(master, bot); return Teleport(master, bot);
} }
@ -217,7 +217,11 @@ bool SummonAction::Teleport(Player* summoner, Player* player)
if (bot->isDead() && revive) if (bot->isDead() && revive)
{ {
if (!botAI->IsSafe(player) || !botAI->IsSafe(summoner))
return false;
bot->ResurrectPlayer(1.0f, false); bot->ResurrectPlayer(1.0f, false);
bot->SpawnCorpseBones();
botAI->TellMasterNoFacing("I live, again!"); botAI->TellMasterNoFacing("I live, again!");
botAI->GetAiObjectContext()->GetValue<GuidVector>("prioritized targets")->Reset(); botAI->GetAiObjectContext()->GetValue<GuidVector>("prioritized targets")->Reset();
} }
@ -240,6 +244,7 @@ bool SummonAction::Teleport(Player* summoner, Player* player)
} }
} }
botAI->TellError("Not enough place to summon"); if(summoner != player)
botAI->TellError("Not enough place to summon");
return false; return false;
} }

View File

@ -6,8 +6,8 @@ bool MoveFromWhirlwindAction::Execute(Event event)
{ {
Unit* boss = nullptr; Unit* boss = nullptr;
uint8 faction = bot->GetTeamId(); uint8 faction = bot->GetTeamId();
float targetDist = 10.0f; // Whirlwind has range of 8, add a couple for safety buffer float targetDist = 10.0f; // Whirlwind has a range of 8, adding a safety buffer
switch (bot->GetMap()->GetDifficulty()) switch (bot->GetMap()->GetDifficulty())
{ {
case DUNGEON_DIFFICULTY_NORMAL: case DUNGEON_DIFFICULTY_NORMAL:
@ -15,7 +15,7 @@ bool MoveFromWhirlwindAction::Execute(Event event)
{ {
boss = AI_VALUE2(Unit*, "find target", "horde commander"); boss = AI_VALUE2(Unit*, "find target", "horde commander");
} }
else //if (faction == TEAM_HORDE) else // TEAM_HORDE
{ {
boss = AI_VALUE2(Unit*, "find target", "alliance commander"); boss = AI_VALUE2(Unit*, "find target", "alliance commander");
} }
@ -25,7 +25,7 @@ bool MoveFromWhirlwindAction::Execute(Event event)
{ {
boss = AI_VALUE2(Unit*, "find target", "commander kolurg"); boss = AI_VALUE2(Unit*, "find target", "commander kolurg");
} }
else //if (faction == TEAM_HORDE) else // TEAM_HORDE
{ {
boss = AI_VALUE2(Unit*, "find target", "commander stoutbeard"); boss = AI_VALUE2(Unit*, "find target", "commander stoutbeard");
} }
@ -33,11 +33,22 @@ bool MoveFromWhirlwindAction::Execute(Event event)
default: default:
break; break;
} }
float bossDistance = bot->GetExactDist2d(boss->GetPosition());
if (!boss || bossDistance > targetDist) // Ensure boss is valid before accessing its methods
if (!boss)
{ {
return false; return false;
} }
float bossDistance = bot->GetExactDist2d(boss->GetPosition());
// Check if the bot is already at a safe distance
if (bossDistance > targetDist)
{
return false;
}
// Move away from the boss to avoid Whirlwind
return MoveAway(boss, targetDist - bossDistance); return MoveAway(boss, targetDist - bossDistance);
} }

View File

@ -10,6 +10,7 @@
#include "RaidMcStrategy.h" #include "RaidMcStrategy.h"
#include "RaidAq20Strategy.h" #include "RaidAq20Strategy.h"
#include "RaidIccStrategy.h" #include "RaidIccStrategy.h"
#include "RaidVoAStrategy.h"
class RaidStrategyContext : public NamedObjectContext<Strategy> class RaidStrategyContext : public NamedObjectContext<Strategy>
{ {
@ -25,6 +26,7 @@ public:
creators["naxx"] = &RaidStrategyContext::naxx; creators["naxx"] = &RaidStrategyContext::naxx;
creators["wotlk-os"] = &RaidStrategyContext::wotlk_os; creators["wotlk-os"] = &RaidStrategyContext::wotlk_os;
creators["wotlk-eoe"] = &RaidStrategyContext::wotlk_eoe; creators["wotlk-eoe"] = &RaidStrategyContext::wotlk_eoe;
creators["voa"] = &RaidStrategyContext::voa;
creators["uld"] = &RaidStrategyContext::uld; creators["uld"] = &RaidStrategyContext::uld;
creators["icc"] = &RaidStrategyContext::icc; creators["icc"] = &RaidStrategyContext::icc;
} }
@ -36,6 +38,7 @@ private:
static Strategy* naxx(PlayerbotAI* botAI) { return new RaidNaxxStrategy(botAI); } static Strategy* naxx(PlayerbotAI* botAI) { return new RaidNaxxStrategy(botAI); }
static Strategy* wotlk_os(PlayerbotAI* botAI) { return new RaidOsStrategy(botAI); } static Strategy* wotlk_os(PlayerbotAI* botAI) { return new RaidOsStrategy(botAI); }
static Strategy* wotlk_eoe(PlayerbotAI* botAI) { return new RaidEoEStrategy(botAI); } static Strategy* wotlk_eoe(PlayerbotAI* botAI) { return new RaidEoEStrategy(botAI); }
static Strategy* voa(PlayerbotAI* botAI) { return new RaidVoAStrategy(botAI); }
static Strategy* uld(PlayerbotAI* botAI) { return new RaidUlduarStrategy(botAI); } static Strategy* uld(PlayerbotAI* botAI) { return new RaidUlduarStrategy(botAI); }
static Strategy* icc(PlayerbotAI* botAI) { return new RaidIccStrategy(botAI); } static Strategy* icc(PlayerbotAI* botAI) { return new RaidIccStrategy(botAI); }
}; };

View File

@ -1255,32 +1255,36 @@ bool HodirMoveSnowpackedIcicleAction::Execute(Event event)
bool HodirBitingColdJumpAction::Execute(Event event) bool HodirBitingColdJumpAction::Execute(Event event)
{ {
// This needs improving but maybe it should be done in the playerbot core. bot->RemoveAurasDueToSpell(SPELL_BITING_COLD_PLAYER_AURA);
int mapId = bot->GetMap()->GetId();
int x = bot->GetPositionX();
int y = bot->GetPositionY();
int z = bot->GetPositionZ() + 3.98f;
float speed = 7.96f;
UpdateMovementState();
if (!IsMovingAllowed(mapId, x, y, z))
{
return false;
}
MovementPriority priority;
if (IsWaitingForLastMove(priority))
{
return false;
}
MotionMaster& mm = *bot->GetMotionMaster();
mm.Clear();
mm.MoveJump(x, y, z, speed, speed, 1, AI_VALUE(Unit*, "current target"));
mm.MoveFall(0, true);
AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation(), 1000, priority);
return true; return true;
// Backup when the overall strategy without cheat will be more vialable
// int mapId = bot->GetMap()->GetId();
// int x = bot->GetPositionX();
// int y = bot->GetPositionY();
// int z = bot->GetPositionZ() + 3.98f;
// float speed = 7.96f;
// UpdateMovementState();
// if (!IsMovingAllowed(mapId, x, y, z))
//{
// return false;
// }
// MovementPriority priority;
// if (IsWaitingForLastMove(priority))
//{
// return false;
// }
// MotionMaster& mm = *bot->GetMotionMaster();
// mm.Clear();
// mm.MoveJump(x, y, z, speed, speed, 1, AI_VALUE(Unit*, "current target"));
// mm.MoveFall(0, true);
// AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation(), 1000, priority);
// return true;
} }
bool FreyaMoveAwayNatureBombAction::isUseful() bool FreyaMoveAwayNatureBombAction::isUseful()

View File

@ -287,13 +287,12 @@ bool HodirBitingColdTrigger::IsActive()
return false; return false;
} }
// Override if boss is casting Flash Freeze Player* master = botAI->GetMaster();
if (!boss->HasUnitState(UNIT_STATE_CASTING) || !boss->FindCurrentSpellBySpellId(SPELL_FLASH_FREEZE)) if (!master || !master->IsAlive())
{ return false;
return true;
}
return boss && botAI->GetAura("biting cold", bot, false, false, 2); return botAI->GetAura("biting cold", bot, false, false, 2) &&
!botAI->GetAura("biting cold", master, false, false, 2);
} }
//Snowpacked Icicle Target //Snowpacked Icicle Target

View File

@ -21,6 +21,7 @@ enum UlduarIDs
NPC_SNOWPACKED_ICICLE = 33174, NPC_SNOWPACKED_ICICLE = 33174,
NPC_TOASTY_FIRE = 33342, NPC_TOASTY_FIRE = 33342,
SPELL_FLASH_FREEZE = 61968, SPELL_FLASH_FREEZE = 61968,
SPELL_BITING_COLD_PLAYER_AURA = 62039,
// Freya // Freya
NPC_EONARS_GIFT = 33228, NPC_EONARS_GIFT = 33228,

View File

@ -242,7 +242,7 @@ bool NewRpgMoveNpcAction::Execute(Event event)
} }
WorldObject* object = ObjectAccessor::GetWorldObject(*bot, info.near_npc.npcOrGo); WorldObject* object = ObjectAccessor::GetWorldObject(*bot, info.near_npc.npcOrGo);
if (object && bot->GetDistance(object) <= INTERACTION_DISTANCE) if (object && IsWithinInteractionDist(object))
{ {
if (!info.near_npc.lastReach) if (!info.near_npc.lastReach)
{ {

View File

@ -247,6 +247,134 @@ bool NewRpgBaseAction::InteractWithNpcOrGameObjectForQuest(ObjectGuid guid)
return true; return true;
} }
bool NewRpgBaseAction::CanInteractWithQuestGiver(Object* questGiver)
{
// This is a variant of Player::CanInteractWithQuestGiver
// that removes the distance check and keeps all other checks
switch (questGiver->GetTypeId())
{
case TYPEID_UNIT:
{
ObjectGuid guid = questGiver->GetGUID();
uint32 npcflagmask = UNIT_NPC_FLAG_QUESTGIVER;
// unit checks
if (!guid)
return false;
if (!bot->IsInWorld())
return false;
if (bot->IsInFlight())
return false;
// exist (we need look pets also for some interaction (quest/etc)
Creature* creature = ObjectAccessor::GetCreatureOrPetOrVehicle(*bot, guid);
if (!creature)
return false;
// Deathstate checks
if (!bot->IsAlive() && !(creature->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_VISIBLE_TO_GHOSTS))
return false;
// alive or spirit healer
if (!creature->IsAlive() && !(creature->GetCreatureTemplate()->type_flags & CREATURE_TYPE_FLAG_INTERACT_WHILE_DEAD))
return false;
// appropriate npc type
if (npcflagmask && !creature->HasNpcFlag(NPCFlags(npcflagmask)))
return false;
// not allow interaction under control, but allow with own pets
if (creature->GetCharmerGUID())
return false;
// xinef: perform better check
if (creature->GetReactionTo(bot) <= REP_UNFRIENDLY)
return false;
// pussywizard: many npcs have missing conditions for class training and rogue trainer can for eg. train dual wield to a shaman :/ too many to change in sql and watch in the future
// pussywizard: this function is not used when talking, but when already taking action (buy spell, reset talents, show spell list)
if (npcflagmask & (UNIT_NPC_FLAG_TRAINER | UNIT_NPC_FLAG_TRAINER_CLASS) && creature->GetCreatureTemplate()->trainer_type == TRAINER_TYPE_CLASS && !bot->IsClass((Classes)creature->GetCreatureTemplate()->trainer_class, CLASS_CONTEXT_CLASS_TRAINER))
return false;
return true;
}
case TYPEID_GAMEOBJECT:
{
ObjectGuid guid = questGiver->GetGUID();
GameobjectTypes type = GAMEOBJECT_TYPE_QUESTGIVER;
if (GameObject* go = bot->GetMap()->GetGameObject(guid))
{
if (go->GetGoType() == type)
{
// Players cannot interact with gameobjects that use the "Point" icon
if (go->GetGOInfo()->IconName == "Point")
{
return false;
}
return true;
}
}
return false;
}
// unused for now
// case TYPEID_PLAYER:
// return bot->IsAlive() && questGiver->ToPlayer()->IsAlive();
// case TYPEID_ITEM:
// return bot->IsAlive();
default:
break;
}
return false;
}
bool NewRpgBaseAction::IsWithinInteractionDist(Object* questGiver)
{
// This is a variant of Player::CanInteractWithQuestGiver
// that only keep the distance check
switch (questGiver->GetTypeId())
{
case TYPEID_UNIT:
{
ObjectGuid guid = questGiver->GetGUID();
// unit checks
if (!guid)
return false;
// exist (we need look pets also for some interaction (quest/etc)
Creature* creature = ObjectAccessor::GetCreatureOrPetOrVehicle(*bot, guid);
if (!creature)
return false;
if (!creature->IsWithinDistInMap(bot, INTERACTION_DISTANCE))
return false;
return true;
}
case TYPEID_GAMEOBJECT:
{
ObjectGuid guid = questGiver->GetGUID();
GameobjectTypes type = GAMEOBJECT_TYPE_QUESTGIVER;
if (GameObject* go = bot->GetMap()->GetGameObject(guid))
{
if (go->IsWithinDistInMap(bot))
{
return true;
}
}
return false;
}
// case TYPEID_PLAYER:
// return bot->IsAlive() && questGiver->ToPlayer()->IsAlive();
// case TYPEID_ITEM:
// return bot->IsAlive();
default:
break;
}
return false;
}
bool NewRpgBaseAction::AcceptQuest(Quest const* quest, ObjectGuid guid) bool NewRpgBaseAction::AcceptQuest(Quest const* quest, ObjectGuid guid)
{ {
WorldPacket p(CMSG_QUESTGIVER_ACCEPT_QUEST); WorldPacket p(CMSG_QUESTGIVER_ACCEPT_QUEST);
@ -283,7 +411,7 @@ bool NewRpgBaseAction::TurnInQuest(Quest const* quest, ObjectGuid guid)
} }
else else
{ {
uint32 bestId = BestReward(quest); uint32 bestId = BestRewardIndex(quest);
p << bestId; p << bestId;
bot->GetSession()->HandleQuestgiverChooseRewardOpcode(p); bot->GetSession()->HandleQuestgiverChooseRewardOpcode(p);
} }
@ -291,7 +419,7 @@ bool NewRpgBaseAction::TurnInQuest(Quest const* quest, ObjectGuid guid)
return true; return true;
} }
uint32 NewRpgBaseAction::BestReward(Quest const* quest) uint32 NewRpgBaseAction::BestRewardIndex(Quest const* quest)
{ {
ItemIds returnIds; ItemIds returnIds;
ItemUsage bestUsage = ITEM_USAGE_NONE; ItemUsage bestUsage = ITEM_USAGE_NONE;
@ -486,7 +614,7 @@ ObjectGuid NewRpgBaseAction::ChooseNpcOrGameObjectToInteract(bool questgiverOnly
if (distanceLimit && bot->GetDistance(object) > distanceLimit) if (distanceLimit && bot->GetDistance(object) > distanceLimit)
continue; continue;
if (HasQuestToAcceptOrReward(object)) if (CanInteractWithQuestGiver(object) && HasQuestToAcceptOrReward(object))
{ {
if (!nearestObject || bot->GetExactDist(nearestObject) > bot->GetExactDist(object)) if (!nearestObject || bot->GetExactDist(nearestObject) > bot->GetExactDist(object))
nearestObject = object; nearestObject = object;
@ -504,7 +632,7 @@ ObjectGuid NewRpgBaseAction::ChooseNpcOrGameObjectToInteract(bool questgiverOnly
if (distanceLimit && bot->GetDistance(object) > distanceLimit) if (distanceLimit && bot->GetDistance(object) > distanceLimit)
continue; continue;
if (HasQuestToAcceptOrReward(object)) if (CanInteractWithQuestGiver(object) && HasQuestToAcceptOrReward(object))
{ {
if (!nearestObject || bot->GetExactDist(nearestObject) > bot->GetExactDist(object)) if (!nearestObject || bot->GetExactDist(nearestObject) > bot->GetExactDist(object))
nearestObject = object; nearestObject = object;

View File

@ -32,16 +32,19 @@ protected:
bool MoveRandomNear(float moveStep = 50.0f, MovementPriority priority = MovementPriority::MOVEMENT_NORMAL); bool MoveRandomNear(float moveStep = 50.0f, MovementPriority priority = MovementPriority::MOVEMENT_NORMAL);
bool ForceToWait(uint32 duration, MovementPriority priority = MovementPriority::MOVEMENT_NORMAL); bool ForceToWait(uint32 duration, MovementPriority priority = MovementPriority::MOVEMENT_NORMAL);
// QUEST RELATED // QUEST RELATED CHECK
bool SearchQuestGiverAndAcceptOrReward();
ObjectGuid ChooseNpcOrGameObjectToInteract(bool questgiverOnly = false, float distanceLimit = 0.0f); ObjectGuid ChooseNpcOrGameObjectToInteract(bool questgiverOnly = false, float distanceLimit = 0.0f);
bool HasQuestToAcceptOrReward(WorldObject* object); bool HasQuestToAcceptOrReward(WorldObject* object);
bool InteractWithNpcOrGameObjectForQuest(ObjectGuid guid); bool InteractWithNpcOrGameObjectForQuest(ObjectGuid guid);
bool AcceptQuest(Quest const* quest, ObjectGuid guid); bool CanInteractWithQuestGiver(Object* questGiver);
bool TurnInQuest(Quest const* quest, ObjectGuid guid); bool IsWithinInteractionDist(Object* object);
uint32 BestReward(Quest const* quest); uint32 BestRewardIndex(Quest const* quest);
bool IsQuestWorthDoing(Quest const* quest); bool IsQuestWorthDoing(Quest const* quest);
bool IsQuestCapableDoing(Quest const* quest); bool IsQuestCapableDoing(Quest const* quest);
// QUEST RELATED ACTION
bool SearchQuestGiverAndAcceptOrReward();
bool AcceptQuest(Quest const* quest, ObjectGuid guid);
bool TurnInQuest(Quest const* quest, ObjectGuid guid);
bool OrganizeQuestLog(); bool OrganizeQuestLog();
protected: protected:

View File

@ -21,6 +21,9 @@ Unit* FlagCarrierValue::Calculate()
{ {
BattlegroundWS* bg = (BattlegroundWS*)botAI->GetBot()->GetBattleground(); BattlegroundWS* bg = (BattlegroundWS*)botAI->GetBot()->GetBattleground();
if (!bg)
return nullptr;
if ((!sameTeam && bot->GetTeamId() == TEAM_HORDE || (sameTeam && bot->GetTeamId() == TEAM_ALLIANCE)) && if ((!sameTeam && bot->GetTeamId() == TEAM_HORDE || (sameTeam && bot->GetTeamId() == TEAM_ALLIANCE)) &&
!bg->GetFlagPickerGUID(TEAM_HORDE).IsEmpty()) !bg->GetFlagPickerGUID(TEAM_HORDE).IsEmpty())
carrier = ObjectAccessor::GetPlayer(bg->GetBgMap(), bg->GetFlagPickerGUID(TEAM_HORDE)); carrier = ObjectAccessor::GetPlayer(bg->GetBgMap(), bg->GetFlagPickerGUID(TEAM_HORDE));
@ -44,6 +47,9 @@ Unit* FlagCarrierValue::Calculate()
{ {
BattlegroundEY* bg = (BattlegroundEY*)botAI->GetBot()->GetBattleground(); BattlegroundEY* bg = (BattlegroundEY*)botAI->GetBot()->GetBattleground();
if (!bg)
return nullptr;
if (bg->GetFlagPickerGUID().IsEmpty()) if (bg->GetFlagPickerGUID().IsEmpty())
return nullptr; return nullptr;

1675
playerbots.conf Normal file

File diff suppressed because it is too large Load Diff

View File

@ -20474,10 +20474,10 @@ void Unit::PetSpellFail(SpellInfo const* spellInfo, Unit* target, uint32 result)
} }
} }
int32 Unit::CalculateAOEDamageReduction(int32 damage, uint32 schoolMask, Unit* caster) const int32 Unit::CalculateAOEDamageReduction(int32 damage, uint32 schoolMask, bool npcCaster) const
{ {
damage = int32(float(damage) * GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, schoolMask)); damage = int32(float(damage) * GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, schoolMask));
if (caster && caster->IsCreature()) if (npcCaster)
damage = int32(float(damage) * GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE, schoolMask)); damage = int32(float(damage) * GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE, schoolMask));
return damage; return damage;

View File

@ -1187,7 +1187,7 @@ public:
uint32 SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack = 1); uint32 SpellDamageBonusTaken(Unit* caster, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack = 1);
// AOE damages // AOE damages
int32 CalculateAOEDamageReduction(int32 damage, uint32 schoolMask, Unit* caster) const; int32 CalculateAOEDamageReduction(int32 damage, uint32 schoolMask, bool npcCaster) const;
// Armor reduction // Armor reduction
static bool IsDamageReducedByArmor(SpellSchoolMask damageSchoolMask, SpellInfo const* spellInfo = nullptr, uint8 effIndex = MAX_SPELL_EFFECTS); static bool IsDamageReducedByArmor(SpellSchoolMask damageSchoolMask, SpellInfo const* spellInfo = nullptr, uint8 effIndex = MAX_SPELL_EFFECTS);

View File

@ -159,6 +159,18 @@ Map::EnterState MapMgr::PlayerCannotEnter(uint32 mapid, Player* player, bool log
if (player->IsGameMaster()) if (player->IsGameMaster())
return Map::CAN_ENTER; return Map::CAN_ENTER;
QueryResult queryAccount = LoginDatabase.Query("SELECT * FROM account WHERE id = {}", player->GetSession()->GetAccountId());
if (queryAccount) {
std::string userName = (*queryAccount)[1].Get<std::string>();
if (userName.find("RNDBOT") != std::string::npos) {
// Is a bot
return Map::CAN_ENTER;
}
else {
// Is a real player
}
}
char const* mapName = entry->name[player->GetSession()->GetSessionDbcLocale()]; char const* mapName = entry->name[player->GetSession()->GetSessionDbcLocale()];
if (!sScriptMgr->OnPlayerCanEnterMap(player, entry, instance, mapDiff, loginCheck)) if (!sScriptMgr->OnPlayerCanEnterMap(player, entry, instance, mapDiff, loginCheck))

View File

@ -6692,9 +6692,17 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
damage = Unit::SpellCriticalDamageBonus(caster, m_spellInfo, damage, target); damage = Unit::SpellCriticalDamageBonus(caster, m_spellInfo, damage, target);
// Auras reducing damage from AOE spells // Auras reducing damage from AOE spells
if (GetSpellInfo()->Effects[GetEffIndex()].IsAreaAuraEffect() || GetSpellInfo()->Effects[GetEffIndex()].IsTargetingArea() || GetSpellInfo()->Effects[GetEffIndex()].Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA) // some persistent area auras have targets like A=53 B=28 if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_IGNORE_DAMAGE_TAKEN_MODIFIERS))
{ {
damage = target->CalculateAOEDamageReduction(damage, GetSpellInfo()->SchoolMask, caster); if (GetSpellInfo()->Effects[GetEffIndex()].IsAreaAuraEffect() ||
GetSpellInfo()->Effects[GetEffIndex()].IsTargetingArea() ||
GetSpellInfo()->Effects[GetEffIndex()].Effect == SPELL_EFFECT_PERSISTENT_AREA_AURA || // some persistent area auras have targets like A=53 B=28
GetSpellInfo()->HasAttribute(SPELL_ATTR5_TREAT_AS_AREA_EFFECT) ||
GetSpellInfo()->HasAttribute(SPELL_ATTR7_TREAT_AS_NPC_AOE))
{
bool npcCaster = (caster && !caster->IsControlledByPlayer()) || GetSpellInfo()->HasAttribute(SPELL_ATTR7_TREAT_AS_NPC_AOE);
damage = target->CalculateAOEDamageReduction(damage, GetSpellInfo()->SchoolMask, npcCaster);
}
} }
int32 dmg = damage; int32 dmg = damage;

View File

@ -8352,7 +8352,8 @@ void Spell::DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier)
// Xinef: Area Auras, AoE Targetting spells AND Chain Target spells (cleave etc.) // Xinef: Area Auras, AoE Targetting spells AND Chain Target spells (cleave etc.)
if (m_spellInfo->Effects[i].IsAreaAuraEffect() || m_spellInfo->Effects[i].IsTargetingArea() || (m_spellInfo->Effects[i].ChainTarget > 1 && m_spellInfo->DmgClass != SPELL_DAMAGE_CLASS_MAGIC)) if (m_spellInfo->Effects[i].IsAreaAuraEffect() || m_spellInfo->Effects[i].IsTargetingArea() || (m_spellInfo->Effects[i].ChainTarget > 1 && m_spellInfo->DmgClass != SPELL_DAMAGE_CLASS_MAGIC))
{ {
m_damage = unit->CalculateAOEDamageReduction(m_damage, m_spellInfo->SchoolMask, m_caster); bool npcCaster = (m_caster && !m_caster->IsControlledByPlayer()) || GetSpellInfo()->HasAttribute(SPELL_ATTR7_TREAT_AS_NPC_AOE);
m_damage = unit->CalculateAOEDamageReduction(m_damage, m_spellInfo->SchoolMask, npcCaster);
if (m_caster->IsPlayer()) if (m_caster->IsPlayer())
{ {
uint32 targetAmount = m_UniqueTargetInfo.size(); uint32 targetAmount = m_UniqueTargetInfo.size();

View File

@ -4885,6 +4885,25 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->Effects[EFFECT_2].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ENEMY); spellInfo->Effects[EFFECT_2].TargetA = SpellImplicitTargetInfo(TARGET_UNIT_TARGET_ENEMY);
}); });
// Felmyst Strafe (Top)
ApplySpellFix({ 45585 }, [](SpellInfo* spellInfo)
{
spellInfo->MaxAffectedTargets = 3;
spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_70_YARDS);
});
// Felmyst Strafe (Middle, Bottom)
ApplySpellFix({ 45633, 45635 }, [](SpellInfo* spellInfo)
{
spellInfo->Effects[EFFECT_0].RadiusEntry = sSpellRadiusStore.LookupEntry(EFFECT_RADIUS_70_YARDS);
});
// Encapsulate
ApplySpellFix({ 45662 }, [](SpellInfo* spellInfo)
{
spellInfo->AttributesEx7 |= SPELL_ATTR7_TREAT_AS_NPC_AOE;
});
for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i) for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
{ {
SpellInfo* spellInfo = mSpellInfoMap[i]; SpellInfo* spellInfo = mSpellInfoMap[i];

View File

@ -182,6 +182,7 @@ enum WorldBoolConfigs
CONFIG_MUNCHING_BLIZZLIKE, CONFIG_MUNCHING_BLIZZLIKE,
CONFIG_ENABLE_DAZE, CONFIG_ENABLE_DAZE,
CONFIG_SPELL_QUEUE_ENABLED, CONFIG_SPELL_QUEUE_ENABLED,
MXWCORE_WORLD_INSTANCE_SKIP_NORMAL,
BOOL_CONFIG_VALUE_COUNT BOOL_CONFIG_VALUE_COUNT
}; };

View File

@ -664,6 +664,8 @@ void World::LoadConfigSettings(bool reload)
_int_configs[CONFIG_INSTANCE_RESET_TIME_RELATIVE_TIMESTAMP] = sConfigMgr->GetOption<int32>("Instance.ResetTimeRelativeTimestamp", 1135814400); _int_configs[CONFIG_INSTANCE_RESET_TIME_RELATIVE_TIMESTAMP] = sConfigMgr->GetOption<int32>("Instance.ResetTimeRelativeTimestamp", 1135814400);
_int_configs[CONFIG_INSTANCE_UNLOAD_DELAY] = sConfigMgr->GetOption<int32>("Instance.UnloadDelay", 30 * MINUTE * IN_MILLISECONDS); _int_configs[CONFIG_INSTANCE_UNLOAD_DELAY] = sConfigMgr->GetOption<int32>("Instance.UnloadDelay", 30 * MINUTE * IN_MILLISECONDS);
_bool_configs[MXWCORE_WORLD_INSTANCE_SKIP_NORMAL] = sConfigMgr->GetOption<bool>("MxWCore.Instance.Skip.Normal", false);
_int_configs[CONFIG_MAX_PRIMARY_TRADE_SKILL] = sConfigMgr->GetOption<int32>("MaxPrimaryTradeSkill", 2); _int_configs[CONFIG_MAX_PRIMARY_TRADE_SKILL] = sConfigMgr->GetOption<int32>("MaxPrimaryTradeSkill", 2);
_int_configs[CONFIG_MIN_PETITION_SIGNS] = sConfigMgr->GetOption<int32>("MinPetitionSigns", 9); _int_configs[CONFIG_MIN_PETITION_SIGNS] = sConfigMgr->GetOption<int32>("MinPetitionSigns", 9);
if (_int_configs[CONFIG_MIN_PETITION_SIGNS] > 9 || int32(_int_configs[CONFIG_MIN_PETITION_SIGNS]) < 0) if (_int_configs[CONFIG_MIN_PETITION_SIGNS] > 9 || int32(_int_configs[CONFIG_MIN_PETITION_SIGNS]) < 0)

View File

@ -50,6 +50,7 @@ enum Spells
SPELL_ENRAGE = 46587, SPELL_ENRAGE = 46587,
SPELL_EMPOWER = 45366, SPELL_EMPOWER = 45366,
SPELL_DARK_FLAME = 45345, SPELL_DARK_FLAME = 45345,
SPELL_FIREBLAST = 45232,
//Lady Sacrolash spells //Lady Sacrolash spells
SPELL_SHADOWFORM = 45455, SPELL_SHADOWFORM = 45455,
@ -78,6 +79,21 @@ struct boss_sacrolash : public BossAI
{ {
boss_sacrolash(Creature* creature) : BossAI(creature, DATA_EREDAR_TWINS), _isSisterDead(false) {} boss_sacrolash(Creature* creature) : BossAI(creature, DATA_EREDAR_TWINS), _isSisterDead(false) {}
bool CheckInRoom() override
{
if (me->GetExactDist2d(me->GetHomePosition()) >= 50.f)
{
DoCastAOE(SPELL_FIREBLAST, true);
if (Creature* alythess = instance->GetCreature(DATA_ALYTHESS))
alythess->AI()->DoCastAOE(SPELL_FIREBLAST, true);
return false;
}
return true;
}
void Reset() override void Reset() override
{ {
DoCastSelf(SPELL_SHADOWFORM, true); DoCastSelf(SPELL_SHADOWFORM, true);
@ -104,7 +120,11 @@ struct boss_sacrolash : public BossAI
Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 1, 100.0f); Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 1, 100.0f);
if (!target) if (!target)
target = me->GetVictim(); target = me->GetVictim();
me->CastSpell(target, SPELL_CONFLAGRATION, false);
DoCast(target, SPELL_CONFLAGRATION);
if (Creature* alythess = instance->GetCreature(DATA_ALYTHESS))
alythess->AI()->Talk(EMOTE_CONFLAGRATION, target);
}, 30s, 35s); }, 30s, 35s);
} }
} }
@ -190,6 +210,13 @@ struct boss_alythess : public BossAI
sacrolash->Respawn(true); sacrolash->Respawn(true);
} }
void AttackStart(Unit* who) override
{
if (who && who->isTargetableForAttack() && me->GetReactState() != REACT_PASSIVE)
if (me->Attack(who, false))
me->AddThreat(who, 0.0f);
}
void DoAction(int32 param) override void DoAction(int32 param) override
{ {
if (param == ACTION_SISTER_DIED) if (param == ACTION_SISTER_DIED)
@ -200,12 +227,16 @@ struct boss_alythess : public BossAI
me->CastSpell(me, SPELL_EMPOWER, true); me->CastSpell(me, SPELL_EMPOWER, true);
scheduler.CancelGroup(GROUP_SPECIAL_ABILITY); scheduler.CancelGroup(GROUP_SPECIAL_ABILITY);
ScheduleTimedEvent(20s, [&] { ScheduleTimedEvent(20s, 26s, [&] {
Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 1, 100.0f); Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 1, 100.0f);
if (!target) if (!target)
target = me->GetVictim(); target = me->GetVictim();
DoCast(target, SPELL_SHADOW_NOVA); DoCast(target, SPELL_SHADOW_NOVA);
}, 30s, 35s);
if (Creature * sacrolash = instance->GetCreature(DATA_SACROLASH))
sacrolash->AI()->Talk(EMOTE_SHADOW_NOVA, target);
}, 20s, 26s);
} }
} }
@ -226,9 +257,9 @@ struct boss_alythess : public BossAI
DoCastSelf(SPELL_PYROGENICS); DoCastSelf(SPELL_PYROGENICS);
}, 15s); }, 15s);
ScheduleTimedEvent(20s, [&] { ScheduleTimedEvent(10s, 15s, [&] {
me->CastCustomSpell(SPELL_FLAME_SEAR, SPELLVALUE_MAX_TARGETS, 5, me, TRIGGERED_NONE); me->CastCustomSpell(SPELL_FLAME_SEAR, SPELLVALUE_MAX_TARGETS, urand(4, 5), me, TRIGGERED_NONE);
}, 15s); }, 10s, 15s);
scheduler.Schedule(20s, GROUP_SPECIAL_ABILITY, [this](TaskContext context) { scheduler.Schedule(20s, GROUP_SPECIAL_ABILITY, [this](TaskContext context) {
Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 1, 100.0f); Unit* target = SelectTarget(SelectTargetMethod::MaxThreat, 1, 100.0f);

View File

@ -49,6 +49,12 @@ enum Spells
SPELL_ENCAPSULATE_CHANNEL = 45661, SPELL_ENCAPSULATE_CHANNEL = 45661,
//Flight phase //Flight phase
SPELL_TRIGGER_TOP_STRAFE = 45586,
SPELL_TRIGGER_MIDDLE_STRAFE = 45622,
SPELL_TRIGGER_BOTTOM_STRAFE = 45623,
SPELL_STRAFE_TOP = 45585,
SPELL_STRAFE_MIDDLE = 45633,
SPELL_STRAFE_BOTTOM = 45635,
SPELL_SUMMON_DEMONIC_VAPOR = 45391, SPELL_SUMMON_DEMONIC_VAPOR = 45391,
SPELL_DEMONIC_VAPOR_SPAWN_TRIGGER = 45388, // Triggers visual beam SPELL_DEMONIC_VAPOR_SPAWN_TRIGGER = 45388, // Triggers visual beam
SPELL_DEMONIC_VAPOR_PERIODIC = 45411, // Spawns cloud and deals damage SPELL_DEMONIC_VAPOR_PERIODIC = 45411, // Spawns cloud and deals damage
@ -110,18 +116,17 @@ public:
bool Execute(uint64 /*execTime*/, uint32 /*diff*/) override bool Execute(uint64 /*execTime*/, uint32 /*diff*/) override
{ {
std::list<Creature*> creatureList; switch (_currentLane)
_caster->GetCreaturesWithEntryInRange(creatureList, 70.0f, NPC_FOG_TRIGGER);
for (auto const& creature : creatureList)
{ {
if (_caster->GetExactDist2d(creature) <= 11.0f) case 0: // top
{ _caster->CastSpell(_caster, SPELL_STRAFE_TOP, true);
creature->CastSpell(creature, SPELL_FOG_OF_CORRUPTION, true); break;
continue; case 1: // middle
} _caster->CastSpell(_caster, SPELL_STRAFE_MIDDLE, true);
break;
if (!_currentLane && creature->GetPositionX() > 1510.0f) case 2: // bottom
creature->CastSpell(creature, SPELL_FOG_OF_CORRUPTION, true); _caster->CastSpell(_caster, SPELL_STRAFE_BOTTOM, true);
break;
} }
return true; return true;
} }
@ -183,6 +188,12 @@ struct boss_felmyst : public BossAI
Talk(YELL_KILL); Talk(YELL_KILL);
} }
void SpellHitTarget(Unit* target, const SpellInfo* spell) override
{
if (spell->Id == SPELL_STRAFE_TOP || spell->Id == SPELL_STRAFE_MIDDLE || spell->Id == SPELL_STRAFE_BOTTOM)
target->CastSpell(target, SPELL_FOG_OF_CORRUPTION, true);
}
void JustDied(Unit* killer) override void JustDied(Unit* killer) override
{ {
BossAI::JustDied(killer); BossAI::JustDied(killer);
@ -297,15 +308,8 @@ struct boss_felmyst : public BossAI
case POINT_LANE: case POINT_LANE:
Talk(EMOTE_BREATH); Talk(EMOTE_BREATH);
me->m_Events.AddEventAtOffset([&] { me->m_Events.AddEventAtOffset([&] {
me->m_Events.AddEvent(new CorruptTriggers(me, _currentLane), me->m_Events.CalculateTime(0)); for (uint8 i = 0; i < 16; ++i)
me->m_Events.AddEvent(new CorruptTriggers(me, _currentLane), me->m_Events.CalculateTime(500)); me->m_Events.AddEvent(new CorruptTriggers(me, _currentLane), me->m_Events.CalculateTime(i*250));
me->m_Events.AddEvent(new CorruptTriggers(me, _currentLane), me->m_Events.CalculateTime(1000));
me->m_Events.AddEvent(new CorruptTriggers(me, _currentLane), me->m_Events.CalculateTime(1500));
me->m_Events.AddEvent(new CorruptTriggers(me, _currentLane), me->m_Events.CalculateTime(2000));
me->m_Events.AddEvent(new CorruptTriggers(me, _currentLane), me->m_Events.CalculateTime(2500));
me->m_Events.AddEvent(new CorruptTriggers(me, _currentLane), me->m_Events.CalculateTime(3000));
me->m_Events.AddEvent(new CorruptTriggers(me, _currentLane), me->m_Events.CalculateTime(3500));
me->m_Events.AddEvent(new CorruptTriggers(me, _currentLane), me->m_Events.CalculateTime(4000));
}, 5s); }, 5s);
me->m_Events.AddEventAtOffset([&] { me->m_Events.AddEventAtOffset([&] {

View File

@ -450,6 +450,7 @@ struct boss_kiljaeden : public BossAI
if (me->GetReactState() == REACT_PASSIVE) if (me->GetReactState() == REACT_PASSIVE)
return; return;
ScriptedAI::EnterEvadeMode(why); ScriptedAI::EnterEvadeMode(why);
me->DespawnOrUnsummon();
} }
void AttackStart(Unit* who) override void AttackStart(Unit* who) override

View File

@ -293,7 +293,7 @@ class spell_entropius_void_zone_visual_aura : public AuraScript
void Register() override void Register() override
{ {
OnEffectApply += AuraEffectApplyFn(spell_entropius_void_zone_visual_aura::HandleApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); OnEffectApply += AuraEffectApplyFn(spell_entropius_void_zone_visual_aura::HandleApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
OnEffectRemove += AuraEffectRemoveFn(spell_entropius_void_zone_visual_aura::HandleApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL); OnEffectRemove += AuraEffectRemoveFn(spell_entropius_void_zone_visual_aura::HandleRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
} }
}; };

View File

@ -319,7 +319,7 @@ class spell_dk_death_and_decay : public SpellScript
// Xinef: include AOE damage reducing auras // Xinef: include AOE damage reducing auras
if (target) if (target)
damage = target->CalculateAOEDamageReduction(damage, GetSpellInfo()->SchoolMask, caster); damage = target->CalculateAOEDamageReduction(damage, GetSpellInfo()->SchoolMask, false);
SetHitDamage(damage); SetHitDamage(damage);
} }

View File

@ -664,7 +664,7 @@ enum SpellAttr7 : uint32
SPELL_ATTR7_NO_ATTACK_DODGE = 0x00800000, // TITLE Spell cannot be dodged 23@Attr7 DESCRIPTION Motivate, Mutilate, Shattering Throw SPELL_ATTR7_NO_ATTACK_DODGE = 0x00800000, // TITLE Spell cannot be dodged 23@Attr7 DESCRIPTION Motivate, Mutilate, Shattering Throw
SPELL_ATTR7_NO_ATTACK_PARRY = 0x01000000, // TITLE Spell cannot be parried 24@Attr7 DESCRIPTION Motivate, Mutilate, Perform Speech, Shattering Throw SPELL_ATTR7_NO_ATTACK_PARRY = 0x01000000, // TITLE Spell cannot be parried 24@Attr7 DESCRIPTION Motivate, Mutilate, Perform Speech, Shattering Throw
SPELL_ATTR7_NO_ATTACK_MISS = 0x02000000, // TITLE Spell cannot be missed 25@Attr7 SPELL_ATTR7_NO_ATTACK_MISS = 0x02000000, // TITLE Spell cannot be missed 25@Attr7
SPELL_ATTR7_TREAT_AS_NPC_AOE = 0x04000000, // TITLE Unknown attribute 26@Attr7 SPELL_ATTR7_TREAT_AS_NPC_AOE = 0x04000000, // TITLE Treat as NPC AoE
SPELL_ATTR7_BYPASS_NO_RESURRECTION_AURA = 0x08000000, // TITLE Bypasses the prevent resurrection aura SPELL_ATTR7_BYPASS_NO_RESURRECTION_AURA = 0x08000000, // TITLE Bypasses the prevent resurrection aura
SPELL_ATTR7_DO_NOT_COUNT_FOR_PVP_SCOREBOARD = 0x10000000, // TITLE Consolidate in raid buff frame (client only) SPELL_ATTR7_DO_NOT_COUNT_FOR_PVP_SCOREBOARD = 0x10000000, // TITLE Consolidate in raid buff frame (client only)
SPELL_ATTR7_REFLECTION_ONLY_DEFENDS = 0x20000000, // TITLE Unknown attribute 29@Attr7 DESCRIPTION only 69028, 71237 SPELL_ATTR7_REFLECTION_ONLY_DEFENDS = 0x20000000, // TITLE Unknown attribute 29@Attr7 DESCRIPTION only 69028, 71237

View File

@ -1087,7 +1087,7 @@ AC_API_EXPORT EnumText EnumUtils<SpellAttr7>::ToString(SpellAttr7 value)
case SPELL_ATTR7_NO_ATTACK_DODGE: return { "SPELL_ATTR7_NO_ATTACK_DODGE", "Spell cannot be dodged 23@Attr7", "Motivate, Mutilate, Shattering Throw" }; case SPELL_ATTR7_NO_ATTACK_DODGE: return { "SPELL_ATTR7_NO_ATTACK_DODGE", "Spell cannot be dodged 23@Attr7", "Motivate, Mutilate, Shattering Throw" };
case SPELL_ATTR7_NO_ATTACK_PARRY: return { "SPELL_ATTR7_NO_ATTACK_PARRY", "Spell cannot be parried 24@Attr7", "Motivate, Mutilate, Perform Speech, Shattering Throw" }; case SPELL_ATTR7_NO_ATTACK_PARRY: return { "SPELL_ATTR7_NO_ATTACK_PARRY", "Spell cannot be parried 24@Attr7", "Motivate, Mutilate, Perform Speech, Shattering Throw" };
case SPELL_ATTR7_NO_ATTACK_MISS: return { "SPELL_ATTR7_NO_ATTACK_MISS", "Spell cannot be missed 25@Attr7", "" }; case SPELL_ATTR7_NO_ATTACK_MISS: return { "SPELL_ATTR7_NO_ATTACK_MISS", "Spell cannot be missed 25@Attr7", "" };
case SPELL_ATTR7_TREAT_AS_NPC_AOE: return { "SPELL_ATTR7_TREAT_AS_NPC_AOE", "Unknown attribute 26@Attr7", "" }; case SPELL_ATTR7_TREAT_AS_NPC_AOE: return { "SPELL_ATTR7_TREAT_AS_NPC_AOE", "Treat as NPC AoE", "" };
case SPELL_ATTR7_BYPASS_NO_RESURRECTION_AURA: return { "SPELL_ATTR7_BYPASS_NO_RESURRECTION_AURA", "Bypasses the prevent resurrection aura", "" }; case SPELL_ATTR7_BYPASS_NO_RESURRECTION_AURA: return { "SPELL_ATTR7_BYPASS_NO_RESURRECTION_AURA", "Bypasses the prevent resurrection aura", "" };
case SPELL_ATTR7_DO_NOT_COUNT_FOR_PVP_SCOREBOARD: return { "SPELL_ATTR7_DO_NOT_COUNT_FOR_PVP_SCOREBOARD", "Consolidate in raid buff frame (client only)", "" }; case SPELL_ATTR7_DO_NOT_COUNT_FOR_PVP_SCOREBOARD: return { "SPELL_ATTR7_DO_NOT_COUNT_FOR_PVP_SCOREBOARD", "Consolidate in raid buff frame (client only)", "" };
case SPELL_ATTR7_REFLECTION_ONLY_DEFENDS: return { "SPELL_ATTR7_REFLECTION_ONLY_DEFENDS", "Unknown attribute 29@Attr7", "only 69028, 71237" }; case SPELL_ATTR7_REFLECTION_ONLY_DEFENDS: return { "SPELL_ATTR7_REFLECTION_ONLY_DEFENDS", "Unknown attribute 29@Attr7", "only 69028, 71237" };

4556
worldserver.conf Normal file

File diff suppressed because it is too large Load Diff