Compare commits

..

No commits in common. "a02e4ca5c17e636ac0e36277108480293ab8358c" and "6bbead70c5d8e4899b398a252c548e89d298513e" have entirely different histories.

38 changed files with 272 additions and 8119 deletions

View File

@ -1,5 +1,4 @@
name: windows-build
on:
push:
branches: [ "master", "test-staging" ]
@ -7,7 +6,7 @@ on:
branches: [ "master", "test-staging" ]
concurrency:
group: "windows-build-${{ github.event.pull_request.number || github.ref }}"
group: "windows-build-${{ github.event.pull_request.number }}"
cancel-in-progress: true
jobs:
@ -16,108 +15,35 @@ jobs:
fail-fast: false
matrix:
os: [windows-latest]
runs-on: ${{ matrix.os }}
name: ${{ matrix.os }}
env:
BOOST_ROOT: C:\local\boost_1_87_0
CMAKE_GENERATOR: Ninja
CTOOLS_BUILD: all
BOOST_ROOT: C:\local\boost_1_82_0
steps:
- name: Checkout AzerothCore
uses: actions/checkout@v4
uses: actions/checkout@v3
with:
repository: 'mod-playerbots/azerothcore-wotlk'
ref: ${{ (github.base_ref || github.ref_name) == 'test-staging' && 'test-staging' || 'Playerbot' }}
path: a
path: 'ac'
- name: Checkout Playerbot Module
uses: actions/checkout@v4
uses: actions/checkout@v3
with:
repository: 'mod-playerbots/mod-playerbots'
path: a/modules/mod-playerbots
- name: Move source tree to short path
shell: powershell
run: |
if (Test-Path C:\ac) {
Remove-Item C:\ac -Recurse -Force
}
New-Item -ItemType Directory -Path C:\ac | Out-Null
robocopy "${{ github.workspace }}\a" "C:\ac" /MIR
if ($LASTEXITCODE -le 7) {
exit 0
}
exit $LASTEXITCODE
- name: Install Ninja
shell: powershell
run: |
choco install ninja -y
#path: 'modules/mod-playerbots'
path: ac/modules/mod-playerbots
- name: ccache
uses: hendrikmuhs/ccache-action@v1.2.13
- name: Configure OS
shell: bash
working-directory: C:\ac
working-directory: ac
env:
CONTINUOUS_INTEGRATION: true
run: |
./acore.sh install-deps
- name: Create AzerothCore CI config
shell: bash
working-directory: C:\ac
run: |
cat > conf/config.sh <<'EOF'
CCOMPILERC="cl"
CCOMPILERCXX="cl"
CTYPE="Release"
CSCRIPTS="static"
CMODULES="static"
CTOOLS_BUILD="all"
CCUSTOMOPTIONS="-DCMAKE_RC_COMPILER=rc -DCMAKE_NINJA_FORCE_RESPONSE_FILE=ON -DCMAKE_NINJA_CMCLDEPS_RC=OFF -DCMAKE_C_USE_RESPONSE_FILE_FOR_OBJECTS=ON -DCMAKE_CXX_USE_RESPONSE_FILE_FOR_OBJECTS=ON -DCMAKE_C_USE_RESPONSE_FILE_FOR_INCLUDES=ON -DCMAKE_CXX_USE_RESPONSE_FILE_FOR_INCLUDES=ON -DCMAKE_C_USE_RESPONSE_FILE_FOR_LIBRARIES=ON -DCMAKE_CXX_USE_RESPONSE_FILE_FOR_LIBRARIES=ON"
EOF
cat conf/config.sh
- name: Setup MSVC
uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756
with:
arch: x64
- name: Build
shell: bash
working-directory: C:\ac
working-directory: ac
run: |
export CTOOLS_BUILD=all
export CMAKE_GENERATOR=Ninja
export CC=cl
export CXX=cl
export RC=rc
cmake --version
ninja --version
echo "CMAKE_GENERATOR=$CMAKE_GENERATOR"
echo "CC=$CC"
echo "CXX=$CXX"
which cl || true
which rc || true
cl || true
rc || true
rm -rf var/build/obj
./acore.sh compiler build

View File

@ -576,7 +576,7 @@ AiPlayerbot.AutoGearScoreLimit = 0
# "mana" (bots have infinite mana)
# "power" (bots have infinite energy, rage, and runic power)
# "taxi" (bots may use all flight paths, though they will not actually learn them)
# "raid" (bots use certain cheats implemented into raid strategies)
# "raid" (bots use cheats implemented into raid strategies (currently only for SSC and Ulduar))
# To use multiple cheats, separate them by commas below (e.g., to enable all, use "gold,health,mana,power,raid,taxi")
# Default: food, taxi, and raid are enabled
AiPlayerbot.BotCheats = "food,taxi,raid"
@ -1430,15 +1430,15 @@ AiPlayerbot.PermanentlyInWorldTime = 31104000
#
AiPlayerbot.PremadeSpecName.1.0 = arms pve
AiPlayerbot.PremadeSpecGlyph.1.0 = 43418,43395,43423,43399,43397,43421
AiPlayerbot.PremadeSpecGlyph.1.0 = 43418,43395,43423,43399,49084,43421
AiPlayerbot.PremadeSpecLink.1.0.60 = 3022032023335100002012211231241
AiPlayerbot.PremadeSpecLink.1.0.80 = 3022032023335100102012213231251-305-2033
AiPlayerbot.PremadeSpecName.1.1 = fury pve
AiPlayerbot.PremadeSpecGlyph.1.1 = 43418,43395,43414,43396,49084,43432
AiPlayerbot.PremadeSpecGlyph.1.1 = 43418,43395,43414,43399,49084,43432
AiPlayerbot.PremadeSpecLink.1.1.60 = -305053000500310053120501351
AiPlayerbot.PremadeSpecLink.1.1.80 = 32002300233-305053000500310153120511351
AiPlayerbot.PremadeSpecName.1.2 = prot pve
AiPlayerbot.PremadeSpecGlyph.1.2 = 43429,43397,43425,43399,49084,45797
AiPlayerbot.PremadeSpecGlyph.1.2 = 43424,43395,43425,43399,49084,45793
AiPlayerbot.PremadeSpecLink.1.2.60 = --053351225000210521030113321
AiPlayerbot.PremadeSpecLink.1.2.80 = 3500030023-301-053351225000210521030113321
AiPlayerbot.PremadeSpecName.1.3 = arms pvp
@ -1467,13 +1467,13 @@ AiPlayerbot.PremadeSpecLink.1.5.80 = 0502300123-3-250031220223012521332113321
AiPlayerbot.PremadeSpecName.2.0 = holy pve
AiPlayerbot.PremadeSpecGlyph.2.0 = 41106,43367,45741,43368,43365,41109
AiPlayerbot.PremadeSpecLink.2.0.60 = 50350151020013053100515221
AiPlayerbot.PremadeSpecLink.2.0.80 = 50350152100013053100515221-50320104203
AiPlayerbot.PremadeSpecLink.2.0.80 = 50350152220013053100515221-503201312
AiPlayerbot.PremadeSpecName.2.1 = prot pve
AiPlayerbot.PremadeSpecGlyph.2.1 = 41100,43367,43869,43368,43369,45745
AiPlayerbot.PremadeSpecGlyph.2.1 = 41099,43367,43869,43368,43369,45745
AiPlayerbot.PremadeSpecLink.2.1.60 = -05005135203102311333112321
AiPlayerbot.PremadeSpecLink.2.1.80 = -05005135203102311333312321-502302012003
AiPlayerbot.PremadeSpecName.2.2 = ret pve
AiPlayerbot.PremadeSpecGlyph.2.2 = 41092,43367,41099,43368,43340,43869
AiPlayerbot.PremadeSpecGlyph.2.2 = 41092,43367,41099,43368,43369,43869
AiPlayerbot.PremadeSpecLink.2.2.60 = --05230051203331302133231131
AiPlayerbot.PremadeSpecLink.2.2.65 = -05-05230051203331302133231131
AiPlayerbot.PremadeSpecLink.2.2.80 = 050501-05-05232051203331302133231331
@ -1504,7 +1504,7 @@ AiPlayerbot.PremadeSpecName.3.0 = bm pve
AiPlayerbot.PremadeSpecGlyph.3.0 = 42912,43350,42902,43351,43338,42914
AiPlayerbot.PremadeSpecLink.3.0.40 = 512002015051122301
AiPlayerbot.PremadeSpecLink.3.0.60 = 51200201505112233110531151
AiPlayerbot.PremadeSpecLink.3.0.80 = 51200201505112233111531351-0323031-5
AiPlayerbot.PremadeSpecLink.3.0.80 = 51200201505112243130531351-005305101
AiPlayerbot.PremadeSpecName.3.1 = mm pve
AiPlayerbot.PremadeSpecGlyph.3.1 = 42912,43350,45625,43351,43338,42914
AiPlayerbot.PremadeSpecLink.3.1.60 = -035305101030013233115031151
@ -1530,8 +1530,8 @@ AiPlayerbot.PremadeSpecLink.3.5.80 = -005305201-2300302510233330533135001031
# HUNTER PET
#
# Ferocity
AiPlayerbot.PremadeHunterPetLink.0.16 = 2100003130003010101
AiPlayerbot.PremadeHunterPetLink.0.20 = 2100003130103010122
AiPlayerbot.PremadeHunterPetLink.0.16 = 2100003030103010101
AiPlayerbot.PremadeHunterPetLink.0.20 = 2100013030103010122
# Tenacity
AiPlayerbot.PremadeHunterPetLink.1.16 = 21103000300120101001
AiPlayerbot.PremadeHunterPetLink.1.20 = 21303010300120101002
@ -1552,7 +1552,7 @@ AiPlayerbot.PremadeHunterPetLink.2.20 = 21000203300002110221
AiPlayerbot.PremadeSpecName.4.0 = as pve
AiPlayerbot.PremadeSpecGlyph.4.0 = 45768,43379,45761,43380,43378,45766
AiPlayerbot.PremadeSpecLink.4.0.60 = 005303104352100520103331051
AiPlayerbot.PremadeSpecLink.4.0.80 = 005303005352100520103331051-005005003-502
AiPlayerbot.PremadeSpecLink.4.0.80 = 005303104352100520103331051-005005005003-2
AiPlayerbot.PremadeSpecName.4.1 = combat pve
AiPlayerbot.PremadeSpecGlyph.4.1 = 42962,43379,45762,43380,43378,42969
AiPlayerbot.PremadeSpecLink.4.1.60 = -0252051000035015223100501251
@ -1593,7 +1593,7 @@ AiPlayerbot.PremadeSpecGlyph.5.1 = 42408,43371,42400,43374,43342,42396
AiPlayerbot.PremadeSpecLink.5.1.60 = -035050031301152530000331331
AiPlayerbot.PremadeSpecLink.5.1.80 = 05032031-235050032302152530000331351
AiPlayerbot.PremadeSpecName.5.2 = shadow pve
AiPlayerbot.PremadeSpecGlyph.5.2 = 45753,43371,42407,43374,43370,42415
AiPlayerbot.PremadeSpecGlyph.5.2 = 42406,43371,42407,43374,43342,42415
AiPlayerbot.PremadeSpecLink.5.2.60 = --325003041203010323150301351
AiPlayerbot.PremadeSpecLink.5.2.80 = 0503203--325023051223010323152301351
AiPlayerbot.PremadeSpecName.5.3 = disc pvp
@ -1620,19 +1620,19 @@ AiPlayerbot.PremadeSpecLink.5.5.80 = 50332031003--005323241223112003102311351
#
AiPlayerbot.PremadeSpecName.6.0 = blood pve
AiPlayerbot.PremadeSpecGlyph.6.0 = 45805,43673,43538,43544,43672,43542
AiPlayerbot.PremadeSpecGlyph.6.0 = 45805,43673,43827,43544,43672,43554
AiPlayerbot.PremadeSpecLink.6.0.60 = 035502150300331320102013111-005
AiPlayerbot.PremadeSpecLink.6.0.80 = 0055021533303310201020131-305020510002-00522
AiPlayerbot.PremadeSpecLink.6.0.80 = 0355021533003313201020131351-005-005032
AiPlayerbot.PremadeSpecName.6.1 = frost pve
AiPlayerbot.PremadeSpecGlyph.6.1 = 45805,43673,43547,43544,43672,43543
AiPlayerbot.PremadeSpecLink.6.1.60 = -32003350332203012300023101351
AiPlayerbot.PremadeSpecLink.6.1.80 = -32002350352203012300033101351-230200305003
AiPlayerbot.PremadeSpecName.6.2 = unholy pve
AiPlayerbot.PremadeSpecGlyph.6.2 = 43542,43673,43546,43535,43672,43549
AiPlayerbot.PremadeSpecGlyph.6.2 = 43542,43673,43546,43544,43672,43549
AiPlayerbot.PremadeSpecLink.6.2.60 = --2301303050032151000150013131151
AiPlayerbot.PremadeSpecLink.6.2.80 = 23050202--2302303350032152000150003133151
AiPlayerbot.PremadeSpecLink.6.2.80 = -320033500002-2301303050032151000150013133151
AiPlayerbot.PremadeSpecName.6.3 = double aura blood pve
AiPlayerbot.PremadeSpecGlyph.6.3 = 45805,43673,43538,43544,43672,43554
AiPlayerbot.PremadeSpecGlyph.6.3 = 45805,43673,43827,43544,43672,43554
AiPlayerbot.PremadeSpecLink.6.3.60 = 005512153330030320102013-305
AiPlayerbot.PremadeSpecLink.6.3.80 = 005512153330030320102013-3050505002023001-002
AiPlayerbot.PremadeSpecName.6.4 = blood pvp
@ -1662,13 +1662,13 @@ AiPlayerbot.PremadeSpecLink.6.6.80 = -320050410002-23013233010021522301012031331
AiPlayerbot.PremadeSpecName.7.0 = ele pve
AiPlayerbot.PremadeSpecGlyph.7.0 = 41536,43385,41532,43386,44923,45776
AiPlayerbot.PremadeSpecLink.7.0.60 = 4530001520213351102301351
AiPlayerbot.PremadeSpecLink.7.0.80 = 4530001523213351302301351-00525003
AiPlayerbot.PremadeSpecLink.7.0.80 = 3530001523213351322301351-005050031
AiPlayerbot.PremadeSpecName.7.1 = enh pve
AiPlayerbot.PremadeSpecGlyph.7.1 = 41542,43385,41539,43386,43725,45771
AiPlayerbot.PremadeSpecGlyph.7.1 = 41530,43385,41539,43386,44923,45771
AiPlayerbot.PremadeSpecLink.7.1.60 = -30305003105021333031121131051
AiPlayerbot.PremadeSpecLink.7.1.80 = 053030152-30305003105021333031131131051
AiPlayerbot.PremadeSpecName.7.2 = resto pve
AiPlayerbot.PremadeSpecGlyph.7.2 = 41527,43385,41517,43386,43725,45775
AiPlayerbot.PremadeSpecGlyph.7.2 = 41527,43385,41517,43386,44923,45775
AiPlayerbot.PremadeSpecLink.7.2.60 = --50005301235310501102321251
AiPlayerbot.PremadeSpecLink.7.2.80 = -00502033-50005331335310501122331251
AiPlayerbot.PremadeSpecName.7.3 = ele pvp
@ -1702,7 +1702,7 @@ AiPlayerbot.PremadeSpecLink.8.0.80 = 230005231100330150323102505321-03-203303001
AiPlayerbot.PremadeSpecName.8.1 = fire pve
AiPlayerbot.PremadeSpecGlyph.8.1 = 42739,43339,45737,43364,44920,42751
AiPlayerbot.PremadeSpecLink.8.1.60 = -0055030011302231053120321341
AiPlayerbot.PremadeSpecLink.8.1.80 = 23000503110003-0055032012303330053120300351
AiPlayerbot.PremadeSpecLink.8.1.80 = 23000503110003-0055030011302331053120321351
AiPlayerbot.PremadeSpecName.8.2 = frost pve
AiPlayerbot.PremadeSpecGlyph.8.2 = 42742,43339,50045,43364,43361,42751
AiPlayerbot.PremadeSpecLink.8.2.60 = --0533030313203100030152231151
@ -1780,15 +1780,15 @@ AiPlayerbot.PremadeSpecLink.11.0.80 = 5032203105331303213305301231--205003012
AiPlayerbot.PremadeSpecName.11.1 = bear pve
AiPlayerbot.PremadeSpecGlyph.11.1 = 40897,43331,46372,43335,43332,40899
AiPlayerbot.PremadeSpecLink.11.1.60 = -500232130322110353100301310501
AiPlayerbot.PremadeSpecLink.11.1.80 = -503232132322010353120303013511-20350001
AiPlayerbot.PremadeSpecLink.11.1.80 = -501232130322110353120303313511-20350001
AiPlayerbot.PremadeSpecName.11.2 = resto pve
AiPlayerbot.PremadeSpecGlyph.11.2 = 40913,43331,40906,43335,43674,45602
AiPlayerbot.PremadeSpecGlyph.11.2 = 40913,43331,40906,43335,44922,45602
AiPlayerbot.PremadeSpecLink.11.2.60 = --230033312031500531050113051
AiPlayerbot.PremadeSpecLink.11.2.80 = 05320131003--230023312131500531050313051
AiPlayerbot.PremadeSpecLink.11.2.80 = 05320031--230033312031501531053313051
AiPlayerbot.PremadeSpecName.11.3 = cat pve
AiPlayerbot.PremadeSpecGlyph.11.3 = 40902,43331,40901,43335,43674,45604
AiPlayerbot.PremadeSpecGlyph.11.3 = 40902,43331,40901,43335,44922,45604
AiPlayerbot.PremadeSpecLink.11.3.60 = -552202032322010053100030310501
AiPlayerbot.PremadeSpecLink.11.3.80 = -553202032322010053120030310511-203503012
AiPlayerbot.PremadeSpecLink.11.3.80 = -553202032322010053100030310511-205503012
AiPlayerbot.PremadeSpecName.11.4 = balance pvp
AiPlayerbot.PremadeSpecGlyph.11.4 = 40921,43331,45622,43674,43335,45623
AiPlayerbot.PremadeSpecLink.11.4.60 = 5012203115331002213032311231

View File

@ -308,8 +308,9 @@ bool LfgAction::Execute(Event event)
allowedRoles[BOT_ROLE_HEALER] = 1;
allowedRoles[BOT_ROLE_DPS] = 3;
BotRoles role = botAI->IsTank(requester, true) ? BOT_ROLE_TANK
: (botAI->IsHeal(requester, true) ? BOT_ROLE_HEALER : BOT_ROLE_DPS);
BotRoles role = botAI->IsTank(requester, false)
? BOT_ROLE_TANK
: (botAI->IsHeal(requester, false) ? BOT_ROLE_HEALER : BOT_ROLE_DPS);
Classes cls = (Classes)requester->getClass();
if (group)
@ -382,8 +383,8 @@ bool LfgAction::Execute(Event event)
if (!botAI->IsSafe(player))
return false;
role = botAI->IsTank(player, true) ? BOT_ROLE_TANK
: (botAI->IsHeal(player, true) ? BOT_ROLE_HEALER : BOT_ROLE_DPS);
role = botAI->IsTank(player, false) ? BOT_ROLE_TANK
: (botAI->IsHeal(player, false) ? BOT_ROLE_HEALER : BOT_ROLE_DPS);
cls = (Classes)player->getClass();
if (allowedRoles[role] > 0)
@ -402,7 +403,7 @@ bool LfgAction::Execute(Event event)
allowedClassNr[cls][role]--;
}
role = botAI->IsTank(bot, true) ? BOT_ROLE_TANK : (botAI->IsHeal(bot, true) ? BOT_ROLE_HEALER : BOT_ROLE_DPS);
role = botAI->IsTank(bot, false) ? BOT_ROLE_TANK : (botAI->IsHeal(bot, false) ? BOT_ROLE_HEALER : BOT_ROLE_DPS);
cls = (Classes)bot->getClass();
if (allowedRoles[role] == 0)

View File

@ -7,7 +7,6 @@
#include "Event.h"
#include "ItemVisitors.h"
#include "PlayerbotRepository.h"
#include "Playerbots.h"
#include "ItemPackets.h"
@ -29,7 +28,6 @@ bool OutfitAction::Execute(Event event)
if (!name.empty())
{
Save(name, items);
PlayerbotRepository::instance().Save(botAI);
std::ostringstream out;
out << "Setting outfit " << name << " as " << param;
@ -88,7 +86,6 @@ bool OutfitAction::Execute(Event event)
botAI->TellMaster(out);
Save(name, ItemIds());
PlayerbotRepository::instance().Save(botAI);
return true;
}
else if (command == "update")
@ -98,7 +95,6 @@ bool OutfitAction::Execute(Event event)
botAI->TellMaster(out);
Update(name);
PlayerbotRepository::instance().Save(botAI);
return true;
}
@ -128,7 +124,6 @@ bool OutfitAction::Execute(Event event)
}
Save(name, outfit);
PlayerbotRepository::instance().Save(botAI);
}
return true;

View File

@ -20,23 +20,20 @@ private:
}
};
// Commands where trigger name =/= action name.
void ChatCommandHandlerStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
PassTroughStrategy::InitTriggers(triggers);
// Keep single action triggers on one line, and multi-action triggers on multiple lines.
triggers.push_back(new TriggerNode("rep", { NextAction("reputation", relevance) }));
triggers.push_back(new TriggerNode("pvp stats", { NextAction("tell pvp stats", relevance) }));
triggers.push_back(new TriggerNode("q",
{ NextAction("query quest", relevance),
triggers.push_back(new TriggerNode("q", { NextAction("query quest", relevance),
NextAction("query item usage", relevance) }));
triggers.push_back(new TriggerNode("add all loot",
{ NextAction("add all loot", relevance),
triggers.push_back(new TriggerNode("add all loot", { NextAction("add all loot", relevance),
NextAction("loot", relevance) }));
triggers.push_back(new TriggerNode("u", { NextAction("use", relevance) }));
triggers.push_back(new TriggerNode("c", { NextAction("item count", relevance) }));
triggers.push_back(new TriggerNode("items", { NextAction("item count", relevance) }));
triggers.push_back(
new TriggerNode("items", { NextAction("item count", relevance) }));
triggers.push_back(new TriggerNode("inv", { NextAction("item count", relevance) }));
triggers.push_back(new TriggerNode("e", { NextAction("equip", relevance) }));
triggers.push_back(new TriggerNode("ue", { NextAction("unequip", relevance) }));
@ -45,40 +42,81 @@ void ChatCommandHandlerStrategy::InitTriggers(std::vector<TriggerNode*>& trigger
triggers.push_back(new TriggerNode("s", { NextAction("sell", relevance) }));
triggers.push_back(new TriggerNode("b", { NextAction("buy", relevance) }));
triggers.push_back(new TriggerNode("r", { NextAction("reward", relevance) }));
triggers.push_back(new TriggerNode("attack", { NextAction("attack my target", relevance) }));
triggers.push_back(new TriggerNode("accept", { NextAction("accept quest", relevance) }));
triggers.push_back(new TriggerNode("follow", { NextAction("follow chat shortcut", relevance) }));
triggers.push_back(new TriggerNode("stay", { NextAction("stay chat shortcut", relevance) }));
triggers.push_back(new TriggerNode("move from group", { NextAction("move from group chat shortcut", relevance) }));
triggers.push_back(new TriggerNode("flee", { NextAction("flee chat shortcut", relevance) }));
triggers.push_back(new TriggerNode("tank attack", { NextAction("tank attack chat shortcut", relevance) }));
triggers.push_back(new TriggerNode("grind", { NextAction("grind chat shortcut", relevance) }));
triggers.push_back(new TriggerNode("talk",
{ NextAction("gossip hello", relevance),
triggers.push_back(
new TriggerNode("attack", { NextAction("attack my target", relevance) }));
triggers.push_back(
new TriggerNode("accept", { NextAction("accept quest", relevance) }));
triggers.push_back(
new TriggerNode("follow", { NextAction("follow chat shortcut", relevance) }));
triggers.push_back(
new TriggerNode("stay", { NextAction("stay chat shortcut", relevance) }));
triggers.push_back(
new TriggerNode("move from group", { NextAction("move from group chat shortcut", relevance) }));
triggers.push_back(
new TriggerNode("flee", { NextAction("flee chat shortcut", relevance) }));
triggers.push_back(new TriggerNode(
"tank attack", { NextAction("tank attack chat shortcut", relevance) }));
triggers.push_back(
new TriggerNode("grind", { NextAction("grind chat shortcut", relevance) }));
triggers.push_back(
new TriggerNode("talk", { NextAction("gossip hello", relevance),
NextAction("talk to quest giver", relevance) }));
triggers.push_back(new TriggerNode("enter vehicle", { NextAction("enter vehicle", relevance) }));
triggers.push_back(new TriggerNode("leave vehicle", { NextAction("leave vehicle", relevance) }));
triggers.push_back(new TriggerNode("cast", { NextAction("cast custom spell", relevance) }));
triggers.push_back(new TriggerNode("castnc", { NextAction("cast custom nc spell", relevance) }));
triggers.push_back(new TriggerNode("revive", { NextAction("spirit healer", relevance) }));
triggers.push_back(new TriggerNode("runaway", { NextAction("runaway chat shortcut", relevance) }));
triggers.push_back(new TriggerNode("warning", { NextAction("runaway chat shortcut", relevance) }));
triggers.push_back(new TriggerNode("max dps", { NextAction("max dps chat shortcut", relevance) }));
triggers.push_back(new TriggerNode("attackers", { NextAction("tell attackers", relevance) }));
triggers.push_back(new TriggerNode("target", { NextAction("tell target", relevance) }));
triggers.push_back(new TriggerNode("pull", { NextAction("pull my target", relevance) }));
triggers.push_back(new TriggerNode("pull back", { NextAction("pull my target", relevance) }));
triggers.push_back(new TriggerNode("pull rti", { NextAction("pull rti target", relevance) }));
triggers.push_back(new TriggerNode("ready", { NextAction("ready check", relevance) }));
triggers.push_back(new TriggerNode("naxx", {NextAction("naxx chat shortcut", relevance) }));
triggers.push_back(new TriggerNode("bwl", { NextAction("bwl chat shortcut", relevance) }));
triggers.push_back(new TriggerNode("dps", { NextAction("tell estimated dps", relevance) }));
triggers.push_back(new TriggerNode("disperse", { NextAction("disperse set", relevance) }));
triggers.push_back(new TriggerNode("qi", { NextAction("query item usage", relevance) }));
triggers.push_back(
new TriggerNode("enter vehicle", { NextAction("enter vehicle", relevance) }));
triggers.push_back(
new TriggerNode("leave vehicle", { NextAction("leave vehicle", relevance) }));
triggers.push_back(
new TriggerNode("cast", { NextAction("cast custom spell", relevance) }));
triggers.push_back(
new TriggerNode("castnc", { NextAction("cast custom nc spell", relevance) }));
triggers.push_back(
new TriggerNode("revive", { NextAction("spirit healer", relevance) }));
triggers.push_back(
new TriggerNode("runaway", { NextAction("runaway chat shortcut", relevance) }));
triggers.push_back(
new TriggerNode("warning", { NextAction("runaway chat shortcut", relevance) }));
triggers.push_back(
new TriggerNode("max dps", { NextAction("max dps chat shortcut", relevance) }));
triggers.push_back(
new TriggerNode("attackers", { NextAction("tell attackers", relevance) }));
triggers.push_back(
new TriggerNode("target", { NextAction("tell target", relevance) }));
triggers.push_back(
new TriggerNode("pull", { NextAction("pull my target", relevance) }));
triggers.push_back(
new TriggerNode("pull back", { NextAction("pull my target", relevance) }));
triggers.push_back(
new TriggerNode("pull rti", { NextAction("pull rti target", relevance) }));
triggers.push_back(
new TriggerNode("ready", { NextAction("ready check", relevance) }));
triggers.push_back(
new TriggerNode("naxx", {NextAction("naxx chat shortcut", relevance)}));
triggers.push_back(
new TriggerNode("bwl", { NextAction("bwl chat shortcut", relevance) }));
triggers.push_back(
new TriggerNode("dps", { NextAction("tell estimated dps", relevance) }));
triggers.push_back(
new TriggerNode("disperse", { NextAction("disperse set", relevance) }));
triggers.push_back(
new TriggerNode("open items", { NextAction("open items", relevance) }));
triggers.push_back(
new TriggerNode("qi", { NextAction("query item usage", relevance) }));
triggers.push_back(
new TriggerNode("unlock items", { NextAction("unlock items", relevance) }));
triggers.push_back(
new TriggerNode("unlock traded item", { NextAction("unlock traded item", relevance) }));
triggers.push_back(
new TriggerNode("wipe", { NextAction("wipe", relevance) }));
triggers.push_back(new TriggerNode("tame", { NextAction("tame", relevance) }));
triggers.push_back(new TriggerNode("glyphs", { NextAction("glyphs", relevance) })); // Added for custom Glyphs
triggers.push_back(new TriggerNode("glyph equip", { NextAction("glyph equip", relevance) })); // Added for custom Glyphs
triggers.push_back(new TriggerNode("pet", { NextAction("pet", relevance) }));
triggers.push_back(new TriggerNode("pet attack", { NextAction("pet attack", relevance) }));
triggers.push_back(new TriggerNode("roll", { NextAction("roll", relevance) }));
triggers.push_back(new TriggerNode("focus heal", { NextAction("focus heal targets", relevance) }));
triggers.push_back(new TriggerNode("emblems", { NextAction("emblems", relevance) }));
}
// Commands where trigger name == action name.
ChatCommandHandlerStrategy::ChatCommandHandlerStrategy(PlayerbotAI* botAI) : PassTroughStrategy(botAI)
{
actionNodeFactories.Add(new ChatCommandActionNodeFactoryInternal());
@ -161,15 +199,15 @@ ChatCommandHandlerStrategy::ChatCommandHandlerStrategy(PlayerbotAI* botAI) : Pas
supported.push_back("rtsc");
supported.push_back("drink");
supported.push_back("calc");
supported.push_back("roll");
supported.push_back("open items");
supported.push_back("qi");
supported.push_back("unlock items");
supported.push_back("unlock traded item");
supported.push_back("wipe");
supported.push_back("tame");
supported.push_back("glyphs");
supported.push_back("glyph equip");
supported.push_back("pet");
supported.push_back("pet attack");
supported.push_back("wait for attack time");
supported.push_back("focus heal");
}

View File

@ -29,7 +29,7 @@ public:
if (!botAI->GetBot()->IsWithinLOSInMap(unit))
return false;
return botAI->IsMovementImpaired(unit) && !botAI->HasAnyAuraOf(unit, "stealth", "prowl", nullptr);
return botAI->IsMovementImpaired(unit);
}
};

View File

@ -11,6 +11,8 @@
#include "ServerFacade.h"
#include "SharedDefines.h"
Value<Unit*>* CastPolymorphAction::GetTargetValue() { return context->GetValue<Unit*>("cc target", getName()); }
bool UseManaSapphireAction::isUseful()
{
Player* bot = botAI->GetBot();

View File

@ -215,10 +215,11 @@ public:
// CC, Interrupt, and Dispel Actions
class CastPolymorphAction : public CastCrowdControlSpellAction
class CastPolymorphAction : public CastBuffSpellAction
{
public:
CastPolymorphAction(PlayerbotAI* botAI) : CastCrowdControlSpellAction(botAI, "polymorph") {}
CastPolymorphAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "polymorph") {}
Value<Unit*>* GetTargetValue() override;
};
class CastSpellstealAction : public CastSpellAction

File diff suppressed because it is too large Load Diff

View File

@ -1,565 +0,0 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_RAIDBLACKTEMPLEACTIONS_H
#define _PLAYERBOT_RAIDBLACKTEMPLEACTIONS_H
#include "Action.h"
#include "AttackAction.h"
#include "MovementActions.h"
#include "RaidBlackTempleHelpers.h"
namespace BlackTempleHelpers
{
struct EyeBlastDangerArea;
}
// General
class BlackTempleEraseTimersAndTrackersAction : public Action
{
public:
BlackTempleEraseTimersAndTrackersAction(
PlayerbotAI* botAI) : Action(botAI, "black temple erase timers and trackers") {}
bool Execute(Event event) override;
};
// High Warlord Naj'entus
class HighWarlordNajentusMisdirectBossToMainTankAction : public AttackAction
{
public:
HighWarlordNajentusMisdirectBossToMainTankAction(
PlayerbotAI* botAI) : AttackAction(botAI, "high warlord naj'entus misdirect boss to main tank") {}
bool Execute(Event event) override;
};
class HighWarlordNajentusTanksPositionBossAction : public AttackAction
{
public:
HighWarlordNajentusTanksPositionBossAction(
PlayerbotAI* botAI) : AttackAction(botAI, "high warlord naj'entus tanks position boss") {}
bool Execute(Event event) override;
};
class HighWarlordNajentusDisperseRangedAction : public MovementAction
{
public:
HighWarlordNajentusDisperseRangedAction(
PlayerbotAI* botAI) : MovementAction(botAI, "naj'entus disperse ranged") {}
bool Execute(Event event) override;
};
class HighWarlordNajentusRemoveImpalingSpineAction : public MovementAction
{
public:
HighWarlordNajentusRemoveImpalingSpineAction(
PlayerbotAI* botAI) : MovementAction(botAI, "high warlord naj'entus remove impaling spine") {}
bool Execute(Event event) override;
};
class HighWarlordNajentusThrowImpalingSpineAction : public MovementAction
{
public:
HighWarlordNajentusThrowImpalingSpineAction(
PlayerbotAI* botAI) : MovementAction(botAI, "high warlord naj'entus throw impaling spine") {}
bool Execute(Event event) override;
};
// Supremus
class SupremusMisdirectBossToMainTankAction : public AttackAction
{
public:
SupremusMisdirectBossToMainTankAction(
PlayerbotAI* botAI) : AttackAction(botAI, "supremus misdirect boss to main tank") {}
bool Execute(Event event) override;
};
class SupremusDisperseRangedAction : public MovementAction
{
public:
SupremusDisperseRangedAction(
PlayerbotAI* botAI) : MovementAction(botAI, "supremus disperse ranged") {}
bool Execute(Event event) override;
};
class SupremusKiteBossAction : public MovementAction
{
public:
SupremusKiteBossAction(
PlayerbotAI* botAI) : MovementAction(botAI, "supremus kite boss") {}
bool Execute(Event event) override;
};
class SupremusMoveAwayFromVolcanosAction : public MovementAction
{
public:
SupremusMoveAwayFromVolcanosAction(
PlayerbotAI* botAI) : MovementAction(botAI, "supremus move away from volcanos") {}
bool Execute(Event event) override;
private:
Position FindSafestNearbyPosition(
const std::vector<Unit*>& volcanos, float maxRadius, float hazardRadius);
bool IsPathSafeFromVolcanos(const Position& start,
const Position& end, const std::vector<Unit*>& volcanos, float hazardRadius);
std::vector<Unit*> GetAllSupremusVolcanos();
};
class SupremusManagePhaseTimerAction : public Action
{
public:
SupremusManagePhaseTimerAction(
PlayerbotAI* botAI) : Action(botAI, "supremus manage phase timer") {}
bool Execute(Event event) override;
};
// Shade of Akama
class ShadeOfAkamaMeleeDpsPrioritizeChannelersAction : public AttackAction
{
public:
ShadeOfAkamaMeleeDpsPrioritizeChannelersAction(
PlayerbotAI* botAI) : AttackAction(botAI, "shade of akama melee dps prioritize channelers") {}
bool Execute(Event event) override;
};
// Teron Gorefiend
class TeronGorefiendMisdirectBossToMainTankAction : public AttackAction
{
public:
TeronGorefiendMisdirectBossToMainTankAction(
PlayerbotAI* botAI) : AttackAction(botAI, "teron gorefiend misdirect boss to main tank") {}
bool Execute(Event event) override;
};
class TeronGorefiendTanksPositionBossAction : public AttackAction
{
public:
TeronGorefiendTanksPositionBossAction(
PlayerbotAI* botAI) : AttackAction(botAI, "teron gorefiend tanks position boss") {}
bool Execute(Event event) override;
};
class TeronGorefiendPositionRangedOnBalconyAction : public MovementAction
{
public:
TeronGorefiendPositionRangedOnBalconyAction(
PlayerbotAI* botAI) : MovementAction(botAI, "teron gorefiend position ranged on balcony") {}
bool Execute(Event event) override;
};
class TeronGorefiendAvoidShadowOfDeathAction : public Action
{
public:
TeronGorefiendAvoidShadowOfDeathAction(
PlayerbotAI* botAI) : Action(botAI, "teron gorefiend avoid shadow of death") {}
bool Execute(Event event) override;
};
class TeronGorefiendMoveToCornerToDieAction : public MovementAction
{
public:
TeronGorefiendMoveToCornerToDieAction(
PlayerbotAI* botAI) : MovementAction(botAI, "teron gorefiend move to corner to die") {}
bool Execute(Event event) override;
};
class TeronGorefiendControlAndDestroyShadowyConstructsAction : public MovementAction
{
public:
TeronGorefiendControlAndDestroyShadowyConstructsAction(
PlayerbotAI* botAI) : MovementAction(botAI, "teron gorefiend control and destroy shadowy constructs") {}
bool Execute(Event event) override;
};
// Gurtogg Bloodboil
class GurtoggBloodboilMisdirectBossToMainTankAction : public AttackAction
{
public:
GurtoggBloodboilMisdirectBossToMainTankAction(
PlayerbotAI* botAI) : AttackAction(botAI, "gurtogg bloodboil misdirect boss to main tank") {}
bool Execute(Event event) override;
};
class GurtoggBloodboilTanksPositionBossAction : public AttackAction
{
public:
GurtoggBloodboilTanksPositionBossAction(
PlayerbotAI* botAI) : AttackAction(botAI, "gurtogg bloodboil tanks position boss") {}
bool Execute(Event event) override;
};
class GurtoggBloodboilRotateRangedGroupsAction : public MovementAction
{
public:
GurtoggBloodboilRotateRangedGroupsAction(
PlayerbotAI* botAI) : MovementAction(botAI, "gurtogg bloodboil rotate ranged groups") {}
bool Execute(Event event) override;
};
class GurtoggBloodboilRangedMoveAwayFromEnragedPlayerAction : public MovementAction
{
public:
GurtoggBloodboilRangedMoveAwayFromEnragedPlayerAction(
PlayerbotAI* botAI) : MovementAction(botAI, "gurtogg bloodboil ranged move away from enraged player") {}
bool Execute(Event event) override;
};
class GurtoggBloodboilManagePhaseTimerAction : public Action
{
public:
GurtoggBloodboilManagePhaseTimerAction(
PlayerbotAI* botAI) : Action(botAI, "gurtogg bloodboil manage phase timer") {}
bool Execute(Event event) override;
};
// Reliquary of Souls
class ReliquaryOfSoulsMisdirectBossToMainTankAction : public AttackAction
{
public:
ReliquaryOfSoulsMisdirectBossToMainTankAction(
PlayerbotAI* botAI) : AttackAction(botAI, "reliquary of souls misdirect boss to main tank") {}
bool Execute(Event event) override;
};
class ReliquaryOfSoulsAdjustDistanceFromSufferingAction : public MovementAction
{
public:
ReliquaryOfSoulsAdjustDistanceFromSufferingAction(
PlayerbotAI* botAI) : MovementAction(botAI, "reliquary of souls adjust distance from suffering") {}
bool Execute(Event event) override;
private:
bool TanksMoveToMinimumRange(Unit* suffering);
bool MeleeDpsStayAtMaximumRange(Unit* suffering);
bool RangedMoveAwayFromBoss(Unit* suffering);
};
class ReliquaryOfSoulsHealersDpsSufferingAction : public Action
{
public:
ReliquaryOfSoulsHealersDpsSufferingAction(
PlayerbotAI* botAI) : Action(botAI, "reliquary of souls healers dps suffering") {}
bool Execute(Event event) override;
};
class ReliquaryOfSoulsSpellstealRuneShieldAction : public Action
{
public:
ReliquaryOfSoulsSpellstealRuneShieldAction(
PlayerbotAI* botAI) : Action(botAI, "reliquary of souls spellsteal rune shield") {}
bool Execute(Event event) override;
};
class ReliquaryOfSoulsSpellReflectDeadenAction : public Action
{
public:
ReliquaryOfSoulsSpellReflectDeadenAction(
PlayerbotAI* botAI) : Action(botAI, "reliquary of souls spell reflect deaden") {}
bool Execute(Event event) override;
};
// Mother Shahraz
class MotherShahrazMisdirectBossToMainTankAction : public AttackAction
{
public:
MotherShahrazMisdirectBossToMainTankAction(
PlayerbotAI* botAI) : AttackAction(botAI, "mother shahraz misdirect boss to main tank") {}
bool Execute(Event event) override;
};
class MotherShahrazTanksPositionBossUnderPillarAction : public AttackAction
{
public:
MotherShahrazTanksPositionBossUnderPillarAction(
PlayerbotAI* botAI) : AttackAction(botAI, "mother shahraz tanks position boss under pillar") {}
bool Execute(Event event) override;
};
class MotherShahrazMeleeDpsWaitAtSafePositionAction : public MovementAction
{
public:
MotherShahrazMeleeDpsWaitAtSafePositionAction(
PlayerbotAI* botAI) : MovementAction(botAI, "mother shahraz melee dps wait at safe position") {}
bool Execute(Event event) override;
};
class MotherShahrazPositionRangedUnderPillarAction : public MovementAction
{
public:
MotherShahrazPositionRangedUnderPillarAction(
PlayerbotAI* botAI) : MovementAction(botAI, "mother shahraz position ranged under pillar") {}
bool Execute(Event event) override;
};
class MotherShahrazRunAwayToBreakFatalAttractionAction : public MovementAction
{
public:
MotherShahrazRunAwayToBreakFatalAttractionAction(
PlayerbotAI* botAI) : MovementAction(botAI, "mother shahraz run away to break fatal attraction") {}
bool Execute(Event event) override;
private:
std::vector<Player*> GetAttractedPlayers();
};
// Illidari Council
class IllidariCouncilMisdirectBossesToTanksAction : public AttackAction
{
public:
IllidariCouncilMisdirectBossesToTanksAction(
PlayerbotAI* botAI) : AttackAction(botAI, "illidari council misdirect bosses to tanks") {}
bool Execute(Event event) override;
};
class IllidariCouncilMainTankPositionGathiosAction : public AttackAction
{
public:
IllidariCouncilMainTankPositionGathiosAction(
PlayerbotAI* botAI) : AttackAction(botAI, "illidari council main tank position gathios") {}
bool Execute(Event event) override;
};
class IllidariCouncilMainTankReflectJudgementOfCommandAction : public Action
{
public:
IllidariCouncilMainTankReflectJudgementOfCommandAction(
PlayerbotAI* botAI) : Action(botAI, "illidari council main tank reflect judgement of command") {}
bool Execute(Event event) override;
};
class IllidariCouncilFirstAssistTankFocusMalandeAction : public AttackAction
{
public:
IllidariCouncilFirstAssistTankFocusMalandeAction(
PlayerbotAI* botAI) : AttackAction(botAI, "illidari council first assist tank focus malande") {}
bool Execute(Event event) override;
};
class IllidariCouncilSecondAssistTankPositionDarkshadowAction : public AttackAction
{
public:
IllidariCouncilSecondAssistTankPositionDarkshadowAction(
PlayerbotAI* botAI) : AttackAction(botAI, "illidari council second assist tank position darkshadow") {}
bool Execute(Event event) override;
};
class IllidariCouncilMageTankPositionZerevorAction : public AttackAction
{
public:
IllidariCouncilMageTankPositionZerevorAction(
PlayerbotAI* botAI) : AttackAction(botAI, "illidari council mage tank position zerevor") {}
bool Execute(Event event) override;
};
class IllidariCouncilPositionMageTankHealerAction : public AttackAction
{
public:
IllidariCouncilPositionMageTankHealerAction(
PlayerbotAI* botAI) : AttackAction(botAI, "illidari council position mage tank healer") {}
bool Execute(Event event) override;
};
class IllidariCouncilAssignDpsTargetsAction : public AttackAction
{
public:
IllidariCouncilAssignDpsTargetsAction(
PlayerbotAI* botAI) : AttackAction(botAI, "illidari council assign dps targets") {}
bool Execute(Event event) override;
};
class IllidariCouncilDisperseRangedAction : public MovementAction
{
public:
IllidariCouncilDisperseRangedAction(
PlayerbotAI* botAI) : MovementAction(botAI, "illidari council disperse ranged") {}
bool Execute(Event event) override;
};
class IllidariCouncilCommandPetsToAttackGathiosAction : public AttackAction
{
public:
IllidariCouncilCommandPetsToAttackGathiosAction(
PlayerbotAI* botAI) : AttackAction(botAI, "illidari council command pets to attack gathios") {}
bool Execute(Event event) override;
};
class IllidariCouncilManageDpsTimerAction : public Action
{
public:
IllidariCouncilManageDpsTimerAction(
PlayerbotAI* botAI) : Action(botAI, "illidari council manage dps timer") {}
bool Execute(Event event) override;
};
// Illidan Stormrage <The Betrayer>
class IllidanStormrageMisdirectToTankAction : public AttackAction
{
public:
IllidanStormrageMisdirectToTankAction(
PlayerbotAI* botAI) : AttackAction(botAI, "illidan stormrage misdirect to tank") {}
bool Execute(Event event) override;
private:
bool TryMisdirectToFlameTanks(Group* group);
bool TryMisdirectToWarlockTank(Unit* illidan);
};
class IllidanStormrageMainTankRepositionBossAction : public AttackAction
{
public:
IllidanStormrageMainTankRepositionBossAction(
PlayerbotAI* botAI) : AttackAction(botAI, "illidan stormrage main tank reposition boss") {}
bool Execute(Event event) override;
private:
bool MoveToShadowTrap(GameObject* trap);
Position FindSafestNearbyPosition(
const std::vector<Unit*>& flameCrashes, float maxRadius, float hazardRadius);
bool IsPathSafeFromFlameCrashes(const Position& start,
const Position& end, const std::vector<Unit*>& flameCrashes, float hazardRadius);
};
class IllidanStormrageIsolateBotWithParasiteAction : public MovementAction
{
public:
IllidanStormrageIsolateBotWithParasiteAction(
PlayerbotAI* botAI) : MovementAction(botAI, "illidan stormrage isolate bot with parasite") {}
bool Execute(Event event) override;
private:
bool InfectedBotMoveFromGroup(Unit* illidan, const Position& targetPos);
bool FreezeTrapShadowfiend(Player* bot, Unit* illidan, const Position& targetPos);
};
class IllidanStormrageSetEarthbindTotemAction : public Action
{
public:
IllidanStormrageSetEarthbindTotemAction(
PlayerbotAI* botAI) : Action(botAI, "illidan stormrage set earthbind totem") {}
bool Execute(Event event) override;
};
class IllidanStormrageAssistTanksHandleFlamesOfAzzinothAction : public AttackAction
{
public:
IllidanStormrageAssistTanksHandleFlamesOfAzzinothAction(
PlayerbotAI* botAI) : AttackAction(botAI, "illidan stormrage assist tanks handle flames of azzinoth") {}
bool Execute(Event event) override;
private:
bool RepositionToAvoidEyeBlast(Unit* illidan, const BlackTempleHelpers::EyeBlastDangerArea& dangerArea);
bool RepositionToAvoidBlaze(Unit* eastFlame, Unit* westFlame);
};
class IllidanStormrageControlPetAggressionAction : public Action
{
public:
IllidanStormrageControlPetAggressionAction(
PlayerbotAI* botAI) : Action(botAI, "illidan stormrage control pet aggression") {}
bool Execute(Event event) override;
};
class IllidanStormragePositionAboveGrateAction : public MovementAction
{
public:
IllidanStormragePositionAboveGrateAction(
PlayerbotAI* botAI) : MovementAction(botAI, "illidan stormrage position above grate") {}
bool Execute(Event event) override;
};
class IllidanStormrageRemoveDarkBarrageAction : public Action
{
public:
IllidanStormrageRemoveDarkBarrageAction(
PlayerbotAI* botAI) : Action(botAI, "illidan stormrage remove dark barrage") {}
bool Execute(Event event) override;
};
class IllidanStormrageMoveAwayFromLandingPointAction : public MovementAction
{
public:
IllidanStormrageMoveAwayFromLandingPointAction(
PlayerbotAI* botAI) : MovementAction(botAI, "illidan stormrage move away from landing point") {}
bool Execute(Event event) override;
};
class IllidanStormrageDisperseRangedAction : public MovementAction
{
public:
IllidanStormrageDisperseRangedAction(
PlayerbotAI* botAI) : MovementAction(botAI, "illidan stormrage disperse ranged") {}
bool Execute(Event event) override;
private:
bool FanOutBehindInHumanPhase(Unit* illidan, Group* group);
bool SpreadInCircleInDemonPhase(Unit* illidan, Group* group);
};
class IllidanStormrageMeleeGoSomewhereToNotDieAction : public MovementAction
{
public:
IllidanStormrageMeleeGoSomewhereToNotDieAction(
PlayerbotAI* botAI) : MovementAction(botAI, "illidan stormrage melee go somewhere to not die") {}
bool Execute(Event event) override;
};
class IllidanStormrageWarlockTankHandleDemonBossAction : public AttackAction
{
public:
IllidanStormrageWarlockTankHandleDemonBossAction(
PlayerbotAI* botAI) : AttackAction(botAI, "illidan stormrage warlock tank handle demon boss") {}
bool Execute(Event event) override;
};
class IllidanStormrageDpsPrioritizeAddsAction : public AttackAction
{
public:
IllidanStormrageDpsPrioritizeAddsAction(
PlayerbotAI* botAI) : AttackAction(botAI, "illidan stormrage dps prioritize adds") {}
bool Execute(Event event) override;
};
class IllidanStormrageUseShadowTrapAction : public MovementAction
{
public:
IllidanStormrageUseShadowTrapAction(
PlayerbotAI* botAI) : MovementAction(botAI, "illidan stormrage use shadow trap") {}
bool Execute(Event event) override;
};
class IllidanStormrageManageDpsTimerAndRtiAction : public Action
{
public:
IllidanStormrageManageDpsTimerAndRtiAction(
PlayerbotAI* botAI) : Action(botAI, "illidan stormrage manage dps timer and rti") {}
bool Execute(Event event) override;
};
class IllidanStormrageDestroyHazardsAction : public Action
{
public:
IllidanStormrageDestroyHazardsAction(
PlayerbotAI* botAI) : Action(botAI, "illidan stormrage destroy hazards") {}
bool Execute(Event event) override;
};
class IllidanStormrageHandleAddsCheatAction : public Action
{
public:
IllidanStormrageHandleAddsCheatAction(
PlayerbotAI* botAI) : Action(botAI, "illidan stormrage handle adds cheat") {}
bool Execute(Event event) override;
};
#endif

View File

@ -1,785 +0,0 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#include "RaidBlackTempleMultipliers.h"
#include "ChooseTargetActions.h"
#include "DKActions.h"
#include "DruidActions.h"
#include "DruidBearActions.h"
#include "DruidShapeshiftActions.h"
#include "FollowActions.h"
#include "HunterActions.h"
#include "MageActions.h"
#include "PaladinActions.h"
#include "PriestActions.h"
#include "RaidBlackTempleActions.h"
#include "RaidBlackTempleHelpers.h"
#include "ReachTargetActions.h"
#include "RogueActions.h"
#include "ShamanActions.h"
#include "WarlockActions.h"
#include "WarriorActions.h"
#include "WipeAction.h"
using namespace BlackTempleHelpers;
static bool IsDpsCooldownAction(Action* action)
{
return dynamic_cast<CastHeroismAction*>(action) ||
dynamic_cast<CastBloodlustAction*>(action) ||
dynamic_cast<CastMetamorphosisAction*>(action) ||
dynamic_cast<CastAdrenalineRushAction*>(action) ||
dynamic_cast<CastBladeFlurryAction*>(action) ||
dynamic_cast<CastIcyVeinsAction*>(action) ||
dynamic_cast<CastColdSnapAction*>(action) ||
dynamic_cast<CastArcanePowerAction*>(action) ||
dynamic_cast<CastPresenceOfMindAction*>(action) ||
dynamic_cast<CastCombustionAction*>(action) ||
dynamic_cast<CastRapidFireAction*>(action) ||
dynamic_cast<CastReadinessAction*>(action) ||
dynamic_cast<CastAvengingWrathAction*>(action) ||
dynamic_cast<CastElementalMasteryAction*>(action) ||
dynamic_cast<CastFeralSpiritAction*>(action) ||
dynamic_cast<CastFireElementalTotemAction*>(action) ||
dynamic_cast<CastFireElementalTotemMeleeAction*>(action) ||
dynamic_cast<CastForceOfNatureAction*>(action) ||
dynamic_cast<CastArmyOfTheDeadAction*>(action) ||
dynamic_cast<CastSummonGargoyleAction*>(action) ||
dynamic_cast<CastBerserkingAction*>(action) ||
dynamic_cast<CastBloodFuryAction*>(action);
}
// High Warlord Naj'entus
float HighWarlordNajentusDelayDpsCooldownsMultiplier::GetValue(Action* action)
{
Unit* najentus = AI_VALUE2(Unit*, "find target", "high warlord naj'entus");
if (!najentus || najentus->GetHealthPct() < 95.0f)
return 1.0f;
if (IsDpsCooldownAction(action) ||
(botAI->IsDps(bot) && dynamic_cast<UseTrinketAction*>(action)))
{
return 0.0f;
}
return 1.0f;
}
float HighWarlordNajentusDisableCombatFormationMoveMultiplier::GetValue(Action* action)
{
if (!AI_VALUE2(Unit*, "find target", "high warlord naj'entus"))
return 1.0f;
if (dynamic_cast<CombatFormationMoveAction*>(action) &&
!dynamic_cast<SetBehindTargetAction*>(action))
{
return 0.0f;
}
return 1.0f;
}
// Supremus
float SupremusDelayDpsCooldownsMultiplier::GetValue(Action* action)
{
Unit* supremus = AI_VALUE2(Unit*, "find target", "supremus");
if (!supremus || supremus->GetHealthPct() < 95.0f)
return 1.0f;
if (IsDpsCooldownAction(action) ||
(botAI->IsDps(bot) && dynamic_cast<UseTrinketAction*>(action)))
{
return 0.0f;
}
return 1.0f;
}
float SupremusFocusOnAvoidanceInPhase2Multiplier::GetValue(Action* action)
{
Unit* supremus = AI_VALUE2(Unit*, "find target", "supremus");
if (!supremus || supremus->GetVictim() != bot ||
!supremus->HasAura(static_cast<uint32>(BlackTempleSpells::SPELL_SNARE_SELF)))
{
return 1.0f;
}
if (dynamic_cast<MovementAction*>(action) &&
!dynamic_cast<SupremusKiteBossAction*>(action) &&
!dynamic_cast<SupremusMoveAwayFromVolcanosAction*>(action))
{
return 0.0f;
}
return 1.0f;
}
float SupremusHitboxIsBuggedMultiplier::GetValue(Action* action)
{
if (bot->getClass() != CLASS_ROGUE ||
!AI_VALUE2(Unit*, "find target", "supremus"))
{
return 1.0f;
}
if (dynamic_cast<CastKillingSpreeAction*>(action))
return 0.0f;
return 1.0f;
}
// Teron Gorefiend
float TeronGorefiendDelayDpsCooldownsMultiplier::GetValue(Action* action)
{
Unit* gorefiend = AI_VALUE2(Unit*, "find target", "teron gorefiend");
if (!gorefiend || gorefiend->GetHealthPct() < 95.0f)
return 1.0f;
if (IsDpsCooldownAction(action) ||
(botAI->IsDps(bot) && dynamic_cast<UseTrinketAction*>(action)))
{
return 0.0f;
}
return 1.0f;
}
float TeronGorefiendControlMovementMultiplier::GetValue(Action* action)
{
if (!AI_VALUE2(Unit*, "find target", "teron gorefiend"))
return 1.0f;
if (dynamic_cast<CombatFormationMoveAction*>(action) &&
!dynamic_cast<SetBehindTargetAction*>(action))
{
return 0.0f;
}
if (dynamic_cast<FollowAction*>(action) ||
dynamic_cast<FleeAction*>(action) ||
dynamic_cast<CastDisengageAction*>(action) ||
dynamic_cast<CastBlinkBackAction*>(action))
{
return 0.0f;
}
if (botAI->IsRanged(bot) && dynamic_cast<ReachTargetAction*>(action))
return 0.0f;
return 1.0f;
}
float TeronGorefiendMarkedBotOnlyMoveToDieMultiplier::GetValue(Action* action)
{
Aura* aura = bot->GetAura(
static_cast<uint32>(BlackTempleSpells::SPELL_SHADOW_OF_DEATH));
if (!aura || aura->GetDuration() >= 15000)
return 1.0f;
if (dynamic_cast<WipeAction*>(action))
return 1.0f;
else if (!dynamic_cast<TeronGorefiendMoveToCornerToDieAction*>(action))
return 0.0f;
return 1.0f;
}
float TeronGorefiendSpiritsAttackOnlyShadowyConstructsMultiplier::GetValue(Action* action)
{
if (!bot->HasAura(static_cast<uint32>(BlackTempleSpells::SPELL_SPIRITUAL_VENGEANCE)) ||
dynamic_cast<WipeAction*>(action))
{
return 1.0f;
}
if (!dynamic_cast<TeronGorefiendControlAndDestroyShadowyConstructsAction*>(action))
return 0.0f;
return 1.0f;
}
float TeronGorefiendDisableAttackingConstructsMultiplier::GetValue(Action* action)
{
if (!AI_VALUE2(Unit*, "find target", "teron gorefiend"))
return 1.0f;
if (bot->GetVictim() != nullptr &&
dynamic_cast<TankAssistAction*>(action))
{
return 0.0f;
}
if (!botAI->IsRangedDps(bot))
return 1.0f;
auto castSpellAction = dynamic_cast<CastSpellAction*>(action);
if (castSpellAction &&
castSpellAction->getThreatType() == Action::ActionThreatType::Aoe)
{
return 0.0f;
}
return 1.0f;
}
// Gurtogg Bloodboil
float GurtoggBloodboilDelayDpsCooldownsMultiplier::GetValue(Action* action)
{
Unit* gurtogg = AI_VALUE2(Unit*, "find target", "gurtogg bloodboil");
if (!gurtogg || gurtogg->GetHealthPct() < 95.0f)
return 1.0f;
if (IsDpsCooldownAction(action) ||
(botAI->IsDps(bot) && dynamic_cast<UseTrinketAction*>(action)))
{
return 0.0f;
}
return 1.0f;
}
float GurtoggBloodboilControlMovementMultiplier::GetValue(Action* action)
{
if (!AI_VALUE2(Unit*, "find target", "gurtogg bloodboil"))
return 1.0f;
if (dynamic_cast<CombatFormationMoveAction*>(action) &&
!dynamic_cast<SetBehindTargetAction*>(action))
{
return 0.0f;
}
if (dynamic_cast<FollowAction*>(action) ||
dynamic_cast<FleeAction*>(action) ||
dynamic_cast<CastDisengageAction*>(action) ||
dynamic_cast<CastBlinkBackAction*>(action))
{
return 0.0f;
}
if (bot->HasAura(static_cast<uint32>(BlackTempleSpells::SPELL_PLAYER_FEL_RAGE)) &&
(dynamic_cast<MovementAction*>(action) &&
!dynamic_cast<AttackAction*>(action)))
{
return 0.0f;
}
return 1.0f;
}
// Reliquary of Souls
float ReliquaryOfSoulsDelayDpsCooldownsMultiplier::GetValue(Action* action)
{
Unit* suffering = AI_VALUE2(Unit*, "find target", "essence of suffering");
if (!suffering || suffering->GetHealthPct() < 95.0f)
return 1.0f;
if (IsDpsCooldownAction(action) ||
(botAI->IsDps(bot) && dynamic_cast<UseTrinketAction*>(action)))
{
return 0.0f;
}
return 1.0f;
}
float ReliquaryOfSoulsDontWasteHealingMultiplier::GetValue(Action* action)
{
if (!AI_VALUE2(Unit*, "find target", "essence of suffering"))
return 1.0f;
if (dynamic_cast<CastPowerWordShieldOnAlmostFullHealthBelowAction*>(action) ||
dynamic_cast<CastPowerWordShieldOnNotFullAction*>(action) ||
dynamic_cast<CastPowerWordShieldAction*>(action) ||
dynamic_cast<CastPowerWordShieldOnPartyAction*>(action))
{
return 1.0f;
}
if (dynamic_cast<CastTreeFormAction*>(action) ||
dynamic_cast<CastHealingSpellAction*>(action))
{
return 0.0f;
}
return 1.0f;
}
// Mother Shahraz
float MotherShahrazDelayDpsCooldownsMultiplier::GetValue(Action* action)
{
Unit* shahraz = AI_VALUE2(Unit*, "find target", "mother shahraz");
if (!shahraz || shahraz->GetHealthPct() < 90.0f)
return 1.0f;
if (IsDpsCooldownAction(action) ||
(botAI->IsDps(bot) && dynamic_cast<UseTrinketAction*>(action)))
{
return 0.0f;
}
return 1.0f;
}
float MotherShahrazControlMovementMultiplier::GetValue(Action* action)
{
if (!AI_VALUE2(Unit*, "find target", "mother shahraz"))
return 1.0f;
if (dynamic_cast<CombatFormationMoveAction*>(action) &&
!dynamic_cast<SetBehindTargetAction*>(action))
{
return 0.0f;
}
if (dynamic_cast<FollowAction*>(action) ||
dynamic_cast<FleeAction*>(action) ||
dynamic_cast<CastDisengageAction*>(action) ||
dynamic_cast<CastBlinkBackAction*>(action))
{
return 0.0f;
}
return 1.0f;
}
float MotherShahrazBotsWithFatalAttractionOnlyRunAwayMultiplier::GetValue(Action* action)
{
if (!AI_VALUE2(Unit*, "find target", "mother shahraz") ||
!bot->HasAura(static_cast<uint32>(BlackTempleSpells::SPELL_FATAL_ATTRACTION)))
{
return 1.0f;
}
if (dynamic_cast<WipeAction*>(action))
return 1.0f;
if (!dynamic_cast<MotherShahrazRunAwayToBreakFatalAttractionAction*>(action))
return 0.0f;
return 1.0f;
}
// Illidari Council
float IllidariCouncilDelayDpsCooldownsMultiplier::GetValue(Action* action)
{
Unit* gathios = AI_VALUE2(Unit*, "find target", "gathios the shatterer");
if (!gathios || gathios->GetHealthPct() < 90.0f)
return 1.0f;
if (IsDpsCooldownAction(action) ||
(botAI->IsDps(bot) && dynamic_cast<UseTrinketAction*>(action)))
{
return 0.0f;
}
return 1.0f;
}
float IllidariCouncilDisableTankActionsMultiplier::GetValue(Action* action)
{
if (!botAI->IsTank(bot) ||
!AI_VALUE2(Unit*, "find target", "gathios the shatterer"))
{
return 1.0f;
}
if (bot->GetVictim() != nullptr && dynamic_cast<TankAssistAction*>(action))
return 0.0f;
if (dynamic_cast<CastTauntAction*>(action) ||
dynamic_cast<CastChallengingShoutAction*>(action) ||
dynamic_cast<CastShockwaveAction*>(action) ||
dynamic_cast<CastCleaveAction*>(action) ||
dynamic_cast<CastGrowlAction*>(action) ||
dynamic_cast<CastSwipeAction*>(action) ||
dynamic_cast<CastHandOfReckoningAction*>(action) ||
dynamic_cast<CastRighteousDefenseAction*>(action) ||
dynamic_cast<CastDarkCommandAction*>(action) ||
dynamic_cast<CastDeathAndDecayAction*>(action) ||
dynamic_cast<CastBloodBoilAction*>(action))
{
return 0.0f;
}
return 1.0f;
}
float IllidariCouncilControlMovementMultiplier::GetValue(Action* action)
{
if (!AI_VALUE2(Unit*, "find target", "high nethermancer zerevor"))
return 1.0f;
if (dynamic_cast<CombatFormationMoveAction*>(action) &&
!dynamic_cast<SetBehindTargetAction*>(action) &&
!dynamic_cast<TankFaceAction*>(action))
{
return 0.0f;
}
if (dynamic_cast<FollowAction*>(action) ||
dynamic_cast<FleeAction*>(action) ||
dynamic_cast<CastDisengageAction*>(action) ||
dynamic_cast<CastBlinkBackAction*>(action))
{
return 0.0f;
}
if (botAI->IsAssistHealOfIndex(bot, 0, true) &&
(dynamic_cast<MovementAction*>(action) &&
!dynamic_cast<IllidariCouncilPositionMageTankHealerAction*>(action)))
{
return 0.0f;
}
if (!botAI->IsAssistTankOfIndex(bot, 0, false) &&
dynamic_cast<TankFaceAction*>(action))
{
return 0.0f;
}
if ((botAI->IsMainTank(bot) ||
botAI->IsAssistTankOfIndex(bot, 0, false) ||
botAI->IsAssistTankOfIndex(bot, 1, false) ||
GetZerevorMageTank(bot) == bot) &&
dynamic_cast<AvoidAoeAction*>(action))
{
return 0.0f;
}
return 1.0f;
}
float IllidariCouncilControlMisdirectionMultiplier::GetValue(Action* action)
{
if (bot->getClass() != CLASS_HUNTER ||
!AI_VALUE2(Unit*, "find target", "high nethermancer zerevor"))
{
return 1.0f;
}
if (dynamic_cast<CastMisdirectionOnMainTankAction*>(action))
return 0.0f;
return 1.0f;
}
float IllidariCouncilDisableIceBlockMultiplier::GetValue(Action* action)
{
if (bot->getClass() != CLASS_MAGE ||
!AI_VALUE2(Unit*, "find target", "high nethermancer zerevor"))
{
return 1.0f;
}
if (GetZerevorMageTank(bot) != bot)
return 1.0f;
if (dynamic_cast<CastIceBlockAction*>(action))
return 0.0f;
return 1.0f;
}
float IllidariCouncilDisableArcaneShotOnZerevorMultiplier::GetValue(Action* action)
{
Unit* zerevor = AI_VALUE2(Unit*, "find target", "high nethermancer zerevor");
if (!zerevor)
return 1.0f;
Unit* target = AI_VALUE(Unit*, "current target");
if (!target || target->GetGUID() != zerevor->GetGUID())
return 1.0f;
if (dynamic_cast<CastArcaneShotAction*>(action))
return 0.0f;
return 1.0f;
}
float IllidariCouncilWaitForDpsMultiplier::GetValue(Action* action)
{
if (botAI->IsMainTank(bot) ||
botAI->IsAssistTankOfIndex(bot, 0, false) ||
botAI->IsAssistTankOfIndex(bot, 1, false) ||
GetZerevorMageTank(bot) == bot)
{
return 1.0f;
}
Unit* gathios = AI_VALUE2(Unit*, "find target", "gathios the shatterer");
if (!gathios)
return 1.0f;
if (dynamic_cast<IllidariCouncilMisdirectBossesToTanksAction*>(action))
return 1.0f;
const time_t now = std::time(nullptr);
constexpr uint8 dpsWaitSeconds = 5;
auto it = councilDpsWaitTimer.find(gathios->GetMap()->GetInstanceId());
if (it == councilDpsWaitTimer.end() || (now - it->second) >= dpsWaitSeconds)
return 1.0f;
if (dynamic_cast<AttackAction*>(action) ||
(dynamic_cast<CastSpellAction*>(action) &&
!dynamic_cast<CastHealingSpellAction*>(action)))
{
return 0.0f;
}
return 1.0f;
}
// Illidan Stormrage <The Betrayer>
float IllidanStormrageDelayDpsCooldownsMultiplier::GetValue(Action* action)
{
Unit* illidan = AI_VALUE2(Unit*, "find target", "illidan stormrage");
if (!illidan)
return 1.0f;
if (illidan->GetHealthPct() > 62.0f &&
(dynamic_cast<CastHeroismAction*>(action) ||
dynamic_cast<CastBloodlustAction*>(action)))
{
return 0.0f;
}
if (illidan->GetHealthPct() <= 62.0f || illidan->GetHealthPct() > 95.0f)
return 1.0f;
if (IsDpsCooldownAction(action) ||
(botAI->IsDps(bot) && dynamic_cast<UseTrinketAction*>(action)))
{
return 0.0f;
}
return 1.0f;
}
float IllidanStormrageControlTankActionsMultiplier::GetValue(Action* action)
{
if (!botAI->IsTank(bot))
return 1.0f;
Unit* illidan = AI_VALUE2(Unit*, "find target", "illidan stormrage");
if (!illidan || illidan->GetHealth() == 1)
return 1.0f;
if (dynamic_cast<TankFaceAction*>(action))
return 0.0f;
if (GetIllidanPhase(illidan) != 2)
return 1.0f;
if (botAI->IsMainTank(bot))
{
if (dynamic_cast<MovementAction*>(action) &&
!dynamic_cast<IllidanStormragePositionAboveGrateAction*>(action))
{
return 0.0f;
}
if (dynamic_cast<CastMeleeSpellAction*>(action) ||
dynamic_cast<CastReachTargetSpellAction*>(action))
{
return 0.0f;
}
}
else if (botAI->IsAssistTankOfIndex(bot, 0, false) ||
botAI->IsAssistTankOfIndex(bot, 1, false))
{
if (dynamic_cast<MovementAction*>(action) &&
!dynamic_cast<IllidanStormrageAssistTanksHandleFlamesOfAzzinothAction*>(action))
{
return 0.0f;
}
if (dynamic_cast<CastHealingSpellAction*>(action))
return 0.0f;
}
return 1.0f;
}
float IllidanStormrageDisableDefaultTargetingMultiplier::GetValue(Action* action)
{
if (bot->GetVictim() == nullptr)
return 1.0f;
Unit* illidan = AI_VALUE2(Unit*, "find target", "illidan stormrage");
if (!illidan || illidan->GetHealth() == 1)
return 1.0f;
if (dynamic_cast<TankAssistAction*>(action))
return 0.0f;
int phase = GetIllidanPhase(illidan);
if (phase == 4 && dynamic_cast<DpsAssistAction*>(action))
return 0.0f;
if (botAI->IsRangedDps(bot))
{
if (phase != 2)
context->GetValue<bool>("neglect threat")->Set(true);
if (dynamic_cast<DpsAssistAction*>(action))
return 0.0f;
}
constexpr float searchRadius = 40.0f;
Unit* shadowDemon = bot->FindNearestCreature(
static_cast<uint32>(BlackTempleNpcs::NPC_SHADOW_DEMON), searchRadius);
Unit* shadowfiend = bot->FindNearestCreature(
static_cast<uint32>(BlackTempleNpcs::NPC_PARASITIC_SHADOWFIEND), searchRadius);
if (((shadowDemon && bot->GetTarget() == shadowDemon->GetGUID()) ||
(shadowfiend && bot->GetTarget() == shadowfiend->GetGUID())) &&
dynamic_cast<CastDebuffSpellOnAttackerAction*>(action))
{
return 0.0f;
}
return 1.0f;
}
float IllidanStormrageControlNonTankMovementMultiplier::GetValue(Action* action)
{
if (botAI->IsTank(bot))
return 1.0f;
Unit* illidan = AI_VALUE2(Unit*, "find target", "illidan stormrage");
if (!illidan || illidan->GetHealth() == 1)
return 1.0f;
if (dynamic_cast<CombatFormationMoveAction*>(action) &&
!dynamic_cast<SetBehindTargetAction*>(action))
{
return 0.0f;
}
if (dynamic_cast<CastDisengageAction*>(action) ||
dynamic_cast<CastBlinkBackAction*>(action) ||
dynamic_cast<FleeAction*>(action) ||
dynamic_cast<FollowAction*>(action))
{
return 0.0f;
}
int phase = GetIllidanPhase(illidan);
if (phase == 2 &&
(dynamic_cast<SetBehindTargetAction*>(action) ||
dynamic_cast<CastKillingSpreeAction*>(action) ||
dynamic_cast<ReachTargetAction*>(action) ||
dynamic_cast<CastReachTargetSpellAction*>(action) ||
dynamic_cast<AvoidAoeAction*>(action)))
{
return 0.0f;
}
if (phase == 4 && botAI->IsHeal(bot) &&
dynamic_cast<ReachTargetAction*>(action))
{
return 0.0f;
}
return 1.0f;
}
float IllidanStormrageUseEarthbindTotemMultiplier::GetValue(Action* action)
{
if (bot->getClass() != CLASS_SHAMAN)
return 1.0f;
Unit* illidan = AI_VALUE2(Unit*, "find target", "illidan stormrage");
if (!illidan || GetIllidanPhase(illidan) == 2)
return 1.0f;
if (dynamic_cast<CastStrengthOfEarthTotemAction*>(action) ||
dynamic_cast<CastStoneskinTotemAction*>(action) ||
dynamic_cast<CastStoneclawTotemAction*>(action) ||
dynamic_cast<CastTremorTotemAction*>(action))
{
return 0.0f;
}
return 1.0f;
}
float IllidanStormrageWaitForDpsMultiplier::GetValue(Action* action)
{
Unit* illidan = AI_VALUE2(Unit*, "find target", "illidan stormrage");
if (!illidan)
return 1.0f;
if (dynamic_cast<IllidanStormrageMisdirectToTankAction*>(action))
return 1.0f;
const time_t now = std::time(nullptr);
const uint32 instanceId = illidan->GetMap()->GetInstanceId();
int phase = GetIllidanPhase(illidan);
if ((phase == 1 || phase == 3 || phase == 5) &&
!botAI->IsMainTank(bot))
{
constexpr uint8 humanoidPhaseDpsWaitSeconds = 3;
auto it = illidanBossDpsWaitTimer.find(instanceId);
if ((it == illidanBossDpsWaitTimer.end() ||
(now - it->second) < humanoidPhaseDpsWaitSeconds) &&
(dynamic_cast<AttackAction*>(action) ||
(dynamic_cast<CastSpellAction*>(action) &&
!dynamic_cast<CastHealingSpellAction*>(action))))
{
return 0.0f;
}
}
if (phase == 4 && GetIllidanWarlockTank(bot) != bot)
{
constexpr uint8 demonPhaseDpsWaitSeconds = 8;
auto it = illidanBossDpsWaitTimer.find(instanceId);
if ((it == illidanBossDpsWaitTimer.end() ||
(now - it->second) < demonPhaseDpsWaitSeconds) &&
(dynamic_cast<AttackAction*>(action) ||
(dynamic_cast<CastSpellAction*>(action) &&
!dynamic_cast<CastHealingSpellAction*>(action))))
{
return 0.0f;
}
}
if (AI_VALUE2(Unit*, "find target", "flame of azzinoth") &&
!botAI->IsAssistTankOfIndex(bot, 0, true) &&
!botAI->IsAssistTankOfIndex(bot, 1, true))
{
constexpr uint8 flamePhaseDpsWaitSeconds = 6;
auto it = illidanFlameDpsWaitTimer.find(instanceId);
if ((it == illidanFlameDpsWaitTimer.end() ||
(now - it->second) < flamePhaseDpsWaitSeconds) &&
(dynamic_cast<AttackAction*>(action) ||
(dynamic_cast<CastSpellAction*>(action) &&
!dynamic_cast<CastHealingSpellAction*>(action))))
{
return 0.0f;
}
}
return 1.0f;
}

View File

@ -1,267 +0,0 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_RAIDBLACKTEMPLEMULTIPLIERS_H
#define _PLAYERBOT_RAIDBLACKTEMPLEMULTIPLIERS_H
#include "Multiplier.h"
// High Warlord Naj'entus
class HighWarlordNajentusDelayDpsCooldownsMultiplier : public Multiplier
{
public:
HighWarlordNajentusDelayDpsCooldownsMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "high warlord naj'entus delay dps cooldowns multiplier") {}
virtual float GetValue(Action* action);
};
class HighWarlordNajentusDisableCombatFormationMoveMultiplier : public Multiplier
{
public:
HighWarlordNajentusDisableCombatFormationMoveMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "high warlord naj'entus disable combat formation move multiplier") {}
virtual float GetValue(Action* action);
};
// Supremus
class SupremusDelayDpsCooldownsMultiplier : public Multiplier
{
public:
SupremusDelayDpsCooldownsMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "supremus delay dps cooldowns multiplier") {}
virtual float GetValue(Action* action);
};
class SupremusFocusOnAvoidanceInPhase2Multiplier : public Multiplier
{
public:
SupremusFocusOnAvoidanceInPhase2Multiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "supremus focus on avoidance in phase 2 multiplier") {}
virtual float GetValue(Action* action);
};
class SupremusHitboxIsBuggedMultiplier : public Multiplier
{
public:
SupremusHitboxIsBuggedMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "supremus hitbox is bugged multiplier") {}
virtual float GetValue(Action* action);
};
// Teron Gorefiend
class TeronGorefiendDelayDpsCooldownsMultiplier : public Multiplier
{
public:
TeronGorefiendDelayDpsCooldownsMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "teron gorefiend delay dps cooldowns multiplier") {}
virtual float GetValue(Action* action);
};
class TeronGorefiendControlMovementMultiplier : public Multiplier
{
public:
TeronGorefiendControlMovementMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "teron gorefiend control movement multiplier") {}
virtual float GetValue(Action* action);
};
class TeronGorefiendMarkedBotOnlyMoveToDieMultiplier : public Multiplier
{
public:
TeronGorefiendMarkedBotOnlyMoveToDieMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "teron gorefiend marked bot only move to die multiplier") {}
virtual float GetValue(Action* action);
};
class TeronGorefiendSpiritsAttackOnlyShadowyConstructsMultiplier : public Multiplier
{
public:
TeronGorefiendSpiritsAttackOnlyShadowyConstructsMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "teron gorefiend spirits attack only shadowy constructs multiplier") {}
virtual float GetValue(Action* action);
};
class TeronGorefiendDisableAttackingConstructsMultiplier : public Multiplier
{
public:
TeronGorefiendDisableAttackingConstructsMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "teron gorefiend disable attacking constructs multiplier") {}
virtual float GetValue(Action* action);
};
// Gurtogg Bloodboil
class GurtoggBloodboilDelayDpsCooldownsMultiplier : public Multiplier
{
public:
GurtoggBloodboilDelayDpsCooldownsMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "gurtogg bloodboil delay dps cooldowns multiplier") {}
virtual float GetValue(Action* action);
};
class GurtoggBloodboilControlMovementMultiplier : public Multiplier
{
public:
GurtoggBloodboilControlMovementMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "gurtogg bloodboil control movement multiplier") {}
virtual float GetValue(Action* action);
};
// Reliquary of Souls
class ReliquaryOfSoulsDelayDpsCooldownsMultiplier : public Multiplier
{
public:
ReliquaryOfSoulsDelayDpsCooldownsMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "reliquary of souls delay dps cooldowns multiplier") {}
virtual float GetValue(Action* action);
};
class ReliquaryOfSoulsDontWasteHealingMultiplier : public Multiplier
{
public:
ReliquaryOfSoulsDontWasteHealingMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "reliquary of souls don't waste healing multiplier") {}
virtual float GetValue(Action* action);
};
// Mother Shahraz
class MotherShahrazDelayDpsCooldownsMultiplier : public Multiplier
{
public:
MotherShahrazDelayDpsCooldownsMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "mother shahraz delay dps cooldowns multiplier") {}
virtual float GetValue(Action* action);
};
class MotherShahrazControlMovementMultiplier : public Multiplier
{
public:
MotherShahrazControlMovementMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "mother shahraz control movement multiplier") {}
virtual float GetValue(Action* action);
};
class MotherShahrazBotsWithFatalAttractionOnlyRunAwayMultiplier : public Multiplier
{
public:
MotherShahrazBotsWithFatalAttractionOnlyRunAwayMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "mother shahraz bots with fatal attraction only run away multiplier") {}
virtual float GetValue(Action* action);
};
// Illidari Council
class IllidariCouncilDelayDpsCooldownsMultiplier : public Multiplier
{
public:
IllidariCouncilDelayDpsCooldownsMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "illidari council delay dps cooldowns multiplier") {}
virtual float GetValue(Action* action);
};
class IllidariCouncilDisableTankActionsMultiplier : public Multiplier
{
public:
IllidariCouncilDisableTankActionsMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "illidari council disable tank actions multiplier") {}
virtual float GetValue(Action* action);
};
class IllidariCouncilControlMovementMultiplier : public Multiplier
{
public:
IllidariCouncilControlMovementMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "illidari council control movement multiplier") {}
virtual float GetValue(Action* action);
};
class IllidariCouncilControlMisdirectionMultiplier : public Multiplier
{
public:
IllidariCouncilControlMisdirectionMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "illidari council control misdirection multiplier") {}
virtual float GetValue(Action* action);
};
class IllidariCouncilDisableArcaneShotOnZerevorMultiplier : public Multiplier
{
public:
IllidariCouncilDisableArcaneShotOnZerevorMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "illidari council disable arcane shot on zerevor multiplier") {}
virtual float GetValue(Action* action);
};
class IllidariCouncilDisableIceBlockMultiplier : public Multiplier
{
public:
IllidariCouncilDisableIceBlockMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "illidari council disable ice block multiplier") {}
virtual float GetValue(Action* action);
};
class IllidariCouncilWaitForDpsMultiplier : public Multiplier
{
public:
IllidariCouncilWaitForDpsMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "illidari council wait for dps multiplier") {}
virtual float GetValue(Action* action);
};
// Illidan Stormrage <The Betrayer>
class IllidanStormrageDelayDpsCooldownsMultiplier : public Multiplier
{
public:
IllidanStormrageDelayDpsCooldownsMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "illidan stormrage delay dps cooldowns multiplier") {}
virtual float GetValue(Action* action);
};
class IllidanStormrageControlTankActionsMultiplier : public Multiplier
{
public:
IllidanStormrageControlTankActionsMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "illidan stormrage control tank actions multiplier") {}
virtual float GetValue(Action* action);
};
class IllidanStormrageDisableDefaultTargetingMultiplier : public Multiplier
{
public:
IllidanStormrageDisableDefaultTargetingMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "illidan stormrage disable default targeting multiplier") {}
virtual float GetValue(Action* action);
};
class IllidanStormrageControlNonTankMovementMultiplier : public Multiplier
{
public:
IllidanStormrageControlNonTankMovementMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "illidan stormrage control non-tank movement multiplier") {}
virtual float GetValue(Action* action);
};
class IllidanStormrageUseEarthbindTotemMultiplier : public Multiplier
{
public:
IllidanStormrageUseEarthbindTotemMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "illidan stormrage use earthbind totem multiplier") {}
virtual float GetValue(Action* action);
};
class IllidanStormrageWaitForDpsMultiplier : public Multiplier
{
public:
IllidanStormrageWaitForDpsMultiplier(
PlayerbotAI* botAI) : Multiplier(botAI, "illidan stormrage wait for dps multiplier") {}
virtual float GetValue(Action* action);
};
#endif

View File

@ -1,406 +0,0 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_RAIDBLACKTEMPLEACTIONCONTEXT_H
#define _PLAYERBOT_RAIDBLACKTEMPLEACTIONCONTEXT_H
#include "NamedObjectContext.h"
#include "RaidBlackTempleActions.h"
class RaidBlackTempleActionContext : public NamedObjectContext<Action>
{
public:
RaidBlackTempleActionContext()
{
// General
creators["black temple erase timers and trackers"] =
&RaidBlackTempleActionContext::black_temple_erase_timers_and_trackers;
// High Warlord Naj'entus
creators["high warlord naj'entus misdirect boss to main tank"] =
&RaidBlackTempleActionContext::high_warlord_najentus_misdirect_boss_to_main_tank;
creators["high warlord naj'entus tanks position boss"] =
&RaidBlackTempleActionContext::high_warlord_najentus_tanks_position_boss;
creators["high warlord naj'entus disperse ranged"] =
&RaidBlackTempleActionContext::high_warlord_najentus_disperse_ranged;
creators["high warlord naj'entus remove impaling spine"] =
&RaidBlackTempleActionContext::high_warlord_najentus_remove_impaling_spine;
creators["high warlord naj'entus throw impaling spine"] =
&RaidBlackTempleActionContext::high_warlord_najentus_throw_impaling_spine;
// Supremus
creators["supremus misdirect boss to main tank"] =
&RaidBlackTempleActionContext::supremus_misdirect_boss_to_main_tank;
creators["supremus disperse ranged"] =
&RaidBlackTempleActionContext::supremus_disperse_ranged;
creators["supremus kite boss"] =
&RaidBlackTempleActionContext::supremus_kite_boss;
creators["supremus move away from volcanos"] =
&RaidBlackTempleActionContext::supremus_move_away_from_volcanos;
creators["supremus manage phase timer"] =
&RaidBlackTempleActionContext::supremus_manage_phase_timer;
// Shade of Akama
creators["shade of akama melee dps prioritize channelers"] =
&RaidBlackTempleActionContext::shade_of_akama_melee_dps_prioritize_channelers;
// Teron Gorefiend
creators["teron gorefiend misdirect boss to main tank"] =
&RaidBlackTempleActionContext::teron_gorefiend_misdirect_boss_to_main_tank;
creators["teron gorefiend tanks position boss"] =
&RaidBlackTempleActionContext::teron_gorefiend_tanks_position_boss;
creators["teron gorefiend position ranged on balcony"] =
&RaidBlackTempleActionContext::teron_gorefiend_position_ranged_on_balcony;
creators["teron gorefiend avoid shadow of death"] =
&RaidBlackTempleActionContext::teron_gorefiend_avoid_shadow_of_death;
creators["teron gorefiend move to corner to die"] =
&RaidBlackTempleActionContext::teron_gorefiend_move_to_corner_to_die;
creators["teron gorefiend control and destroy shadowy constructs"] =
&RaidBlackTempleActionContext::teron_gorefiend_control_and_destroy_shadowy_constructs;
// Gurtogg Bloodboil
creators["gurtogg bloodboil misdirect boss to main tank"] =
&RaidBlackTempleActionContext::gurtogg_bloodboil_misdirect_boss_to_main_tank;
creators["gurtogg bloodboil tanks position boss"] =
&RaidBlackTempleActionContext::gurtogg_bloodboil_tanks_position_boss;
creators["gurtogg bloodboil rotate ranged groups"] =
&RaidBlackTempleActionContext::gurtogg_bloodboil_rotate_ranged_groups;
creators["gurtogg bloodboil ranged move away from enraged player"] =
&RaidBlackTempleActionContext::gurtogg_bloodboil_ranged_move_away_from_enraged_player;
creators["gurtogg bloodboil manage phase timer"] =
&RaidBlackTempleActionContext::gurtogg_bloodboil_manage_phase_timer;
// Reliquary of Souls
creators["reliquary of souls misdirect boss to main tank"] =
&RaidBlackTempleActionContext::reliquary_of_souls_misdirect_boss_to_main_tank;
creators["reliquary of souls adjust distance from suffering"] =
&RaidBlackTempleActionContext::reliquary_of_souls_adjust_distance_from_suffering;
creators["reliquary of souls healers dps suffering"] =
&RaidBlackTempleActionContext::reliquary_of_souls_healers_dps_suffering;
creators["reliquary of souls spellsteal rune shield"] =
&RaidBlackTempleActionContext::reliquary_of_souls_spellsteal_rune_shield;
creators["reliquary of souls spell reflect deaden"] =
&RaidBlackTempleActionContext::reliquary_of_souls_spell_reflect_deaden;
// Mother Shahraz
creators["mother shahraz misdirect boss to main tank"] =
&RaidBlackTempleActionContext::mother_shahraz_misdirect_boss_to_main_tank;
creators["mother shahraz tanks position boss under pillar"] =
&RaidBlackTempleActionContext::mother_shahraz_tanks_position_boss_under_pillar;
creators["mother shahraz melee dps wait at safe position"] =
&RaidBlackTempleActionContext::mother_shahraz_melee_dps_wait_at_safe_position;
creators["mother shahraz position ranged under pillar"] =
&RaidBlackTempleActionContext::mother_shahraz_position_ranged_under_pillar;
creators["mother shahraz run away to break fatal attraction"] =
&RaidBlackTempleActionContext::mother_shahraz_run_away_to_break_fatal_attraction;
// Illidari Council
creators["illidari council misdirect bosses to tanks"] =
&RaidBlackTempleActionContext::illidari_council_misdirect_bosses_to_tanks;
creators["illidari council main tank position gathios"] =
&RaidBlackTempleActionContext::illidari_council_main_tank_position_gathios;
creators["illidari council main tank reflect judgement of command"] =
&RaidBlackTempleActionContext::illidari_council_main_tank_reflect_judgement_of_command;
creators["illidari council first assist tank focus malande"] =
&RaidBlackTempleActionContext::illidari_council_first_assist_tank_focus_malande;
creators["illidari council second assist tank position darkshadow"] =
&RaidBlackTempleActionContext::illidari_council_second_assist_tank_position_darkshadow;
creators["illidari council mage tank position zerevor"] =
&RaidBlackTempleActionContext::illidari_council_mage_tank_position_zerevor;
creators["illidari council position mage tank healer"] =
&RaidBlackTempleActionContext::illidari_council_position_mage_tank_healer;
creators["illidari council disperse ranged"] =
&RaidBlackTempleActionContext::illidari_council_disperse_ranged;
creators["illidari council command pets to attack gathios"] =
&RaidBlackTempleActionContext::illidari_council_command_pets_to_attack_gathios;
creators["illidari council assign dps targets"] =
&RaidBlackTempleActionContext::illidari_council_assign_dps_targets;
creators["illidari council manage dps timer"] =
&RaidBlackTempleActionContext::illidari_council_manage_dps_timer;
// Illidan Stormrage <The Betrayer>
creators["illidan stormrage misdirect to tank"] =
&RaidBlackTempleActionContext::illidan_stormrage_misdirect_to_tank;
creators["illidan stormrage main tank reposition boss"] =
&RaidBlackTempleActionContext::illidan_stormrage_main_tank_reposition_boss;
creators["illidan stormrage isolate bot with parasite"] =
&RaidBlackTempleActionContext::illidan_stormrage_isolate_bot_with_parasite;
creators["illidan stormrage set earthbind totem"] =
&RaidBlackTempleActionContext::illidan_stormrage_set_earthbind_totem;
creators["illidan stormrage assist tanks handle flames of azzinoth"] =
&RaidBlackTempleActionContext::illidan_stormrage_assist_tanks_handle_flames_of_azzinoth;
creators["illidan stormrage control pet aggression"] =
&RaidBlackTempleActionContext::illidan_stormrage_control_pet_aggression;
creators["illidan stormrage position above grate"] =
&RaidBlackTempleActionContext::illidan_stormrage_position_above_grate;
creators["illidan stormrage remove dark barrage"] =
&RaidBlackTempleActionContext::illidan_stormrage_remove_dark_barrage;
creators["illidan stormrage move away from landing point"] =
&RaidBlackTempleActionContext::illidan_stormrage_move_away_from_landing_point;
creators["illidan stormrage disperse ranged"] =
&RaidBlackTempleActionContext::illidan_stormrage_disperse_ranged;
creators["illidan stormrage melee go somewhere to not die"] =
&RaidBlackTempleActionContext::illidan_stormrage_melee_go_somewhere_to_not_die;
creators["illidan stormrage warlock tank handle demon boss"] =
&RaidBlackTempleActionContext::illidan_stormrage_warlock_tank_handle_demon_boss;
creators["illidan stormrage dps prioritize adds"] =
&RaidBlackTempleActionContext::illidan_stormrage_dps_prioritize_adds;
creators["illidan stormrage use shadow trap"] =
&RaidBlackTempleActionContext::illidan_stormrage_use_shadow_trap;
creators["illidan stormrage manage dps timer and rti"] =
&RaidBlackTempleActionContext::illidan_stormrage_manage_dps_timer_and_rti;
creators["illidan stormrage destroy hazards"] =
&RaidBlackTempleActionContext::illidan_stormrage_destroy_hazards;
creators["illidan stormrage handle adds cheat"] =
&RaidBlackTempleActionContext::illidan_stormrage_handle_adds_cheat;
}
private:
// General
static Action* black_temple_erase_timers_and_trackers(
PlayerbotAI* botAI) { return new BlackTempleEraseTimersAndTrackersAction(botAI); }
// High Warlord Naj'entus
static Action* high_warlord_najentus_misdirect_boss_to_main_tank(
PlayerbotAI* botAI) { return new HighWarlordNajentusMisdirectBossToMainTankAction(botAI); }
static Action* high_warlord_najentus_tanks_position_boss(
PlayerbotAI* botAI) { return new HighWarlordNajentusTanksPositionBossAction(botAI); }
static Action* high_warlord_najentus_disperse_ranged(
PlayerbotAI* botAI) { return new HighWarlordNajentusDisperseRangedAction(botAI); }
static Action* high_warlord_najentus_remove_impaling_spine(
PlayerbotAI* botAI) { return new HighWarlordNajentusRemoveImpalingSpineAction(botAI); }
static Action* high_warlord_najentus_throw_impaling_spine(
PlayerbotAI* botAI) { return new HighWarlordNajentusThrowImpalingSpineAction(botAI); }
// Supremus
static Action* supremus_misdirect_boss_to_main_tank(
PlayerbotAI* botAI) { return new SupremusMisdirectBossToMainTankAction(botAI); }
static Action* supremus_disperse_ranged(
PlayerbotAI* botAI) { return new SupremusDisperseRangedAction(botAI); }
static Action* supremus_kite_boss(
PlayerbotAI* botAI) { return new SupremusKiteBossAction(botAI); }
static Action* supremus_move_away_from_volcanos(
PlayerbotAI* botAI) { return new SupremusMoveAwayFromVolcanosAction(botAI); }
static Action* supremus_manage_phase_timer(
PlayerbotAI* botAI) { return new SupremusManagePhaseTimerAction(botAI); }
// Shade of Akama
static Action* shade_of_akama_melee_dps_prioritize_channelers(
PlayerbotAI* botAI) { return new ShadeOfAkamaMeleeDpsPrioritizeChannelersAction(botAI); }
// Teron Gorefiend
static Action* teron_gorefiend_misdirect_boss_to_main_tank(
PlayerbotAI* botAI) { return new TeronGorefiendMisdirectBossToMainTankAction(botAI); }
static Action* teron_gorefiend_tanks_position_boss(
PlayerbotAI* botAI) { return new TeronGorefiendTanksPositionBossAction(botAI); }
static Action* teron_gorefiend_position_ranged_on_balcony(
PlayerbotAI* botAI) { return new TeronGorefiendPositionRangedOnBalconyAction(botAI); }
static Action* teron_gorefiend_avoid_shadow_of_death(
PlayerbotAI* botAI) { return new TeronGorefiendAvoidShadowOfDeathAction(botAI); }
static Action* teron_gorefiend_move_to_corner_to_die(
PlayerbotAI* botAI) { return new TeronGorefiendMoveToCornerToDieAction(botAI); }
static Action* teron_gorefiend_control_and_destroy_shadowy_constructs(
PlayerbotAI* botAI) { return new TeronGorefiendControlAndDestroyShadowyConstructsAction(botAI); }
// Gurtogg Bloodboil
static Action* gurtogg_bloodboil_misdirect_boss_to_main_tank(
PlayerbotAI* botAI) { return new GurtoggBloodboilMisdirectBossToMainTankAction(botAI); }
static Action* gurtogg_bloodboil_tanks_position_boss(
PlayerbotAI* botAI) { return new GurtoggBloodboilTanksPositionBossAction(botAI); }
static Action* gurtogg_bloodboil_rotate_ranged_groups(
PlayerbotAI* botAI) { return new GurtoggBloodboilRotateRangedGroupsAction(botAI); }
static Action* gurtogg_bloodboil_ranged_move_away_from_enraged_player(
PlayerbotAI* botAI) { return new GurtoggBloodboilRangedMoveAwayFromEnragedPlayerAction(botAI); }
static Action* gurtogg_bloodboil_manage_phase_timer(
PlayerbotAI* botAI) { return new GurtoggBloodboilManagePhaseTimerAction(botAI); }
// Reliquary of Souls
static Action* reliquary_of_souls_misdirect_boss_to_main_tank(
PlayerbotAI* botAI) { return new ReliquaryOfSoulsMisdirectBossToMainTankAction(botAI); }
static Action* reliquary_of_souls_adjust_distance_from_suffering(
PlayerbotAI* botAI) { return new ReliquaryOfSoulsAdjustDistanceFromSufferingAction(botAI); }
static Action* reliquary_of_souls_healers_dps_suffering(
PlayerbotAI* botAI) { return new ReliquaryOfSoulsHealersDpsSufferingAction(botAI); }
static Action* reliquary_of_souls_spellsteal_rune_shield(
PlayerbotAI* botAI) { return new ReliquaryOfSoulsSpellstealRuneShieldAction(botAI); }
static Action* reliquary_of_souls_spell_reflect_deaden(
PlayerbotAI* botAI) { return new ReliquaryOfSoulsSpellReflectDeadenAction(botAI); }
// Mother Shahraz
static Action* mother_shahraz_misdirect_boss_to_main_tank(
PlayerbotAI* botAI) { return new MotherShahrazMisdirectBossToMainTankAction(botAI); }
static Action* mother_shahraz_tanks_position_boss_under_pillar(
PlayerbotAI* botAI) { return new MotherShahrazTanksPositionBossUnderPillarAction(botAI); }
static Action* mother_shahraz_melee_dps_wait_at_safe_position(
PlayerbotAI* botAI) { return new MotherShahrazMeleeDpsWaitAtSafePositionAction(botAI); }
static Action* mother_shahraz_position_ranged_under_pillar(
PlayerbotAI* botAI) { return new MotherShahrazPositionRangedUnderPillarAction(botAI); }
static Action* mother_shahraz_run_away_to_break_fatal_attraction(
PlayerbotAI* botAI) { return new MotherShahrazRunAwayToBreakFatalAttractionAction(botAI); }
// Illidari Council
static Action* illidari_council_misdirect_bosses_to_tanks(
PlayerbotAI* botAI) { return new IllidariCouncilMisdirectBossesToTanksAction(botAI); }
static Action* illidari_council_main_tank_position_gathios(
PlayerbotAI* botAI) { return new IllidariCouncilMainTankPositionGathiosAction(botAI); }
static Action* illidari_council_main_tank_reflect_judgement_of_command(
PlayerbotAI* botAI) { return new IllidariCouncilMainTankReflectJudgementOfCommandAction(botAI); }
static Action* illidari_council_first_assist_tank_focus_malande(
PlayerbotAI* botAI) { return new IllidariCouncilFirstAssistTankFocusMalandeAction(botAI); }
static Action* illidari_council_second_assist_tank_position_darkshadow(
PlayerbotAI* botAI) { return new IllidariCouncilSecondAssistTankPositionDarkshadowAction(botAI); }
static Action* illidari_council_mage_tank_position_zerevor(
PlayerbotAI* botAI) { return new IllidariCouncilMageTankPositionZerevorAction(botAI); }
static Action* illidari_council_position_mage_tank_healer(
PlayerbotAI* botAI) { return new IllidariCouncilPositionMageTankHealerAction(botAI); }
static Action* illidari_council_disperse_ranged(
PlayerbotAI* botAI) { return new IllidariCouncilDisperseRangedAction(botAI); }
static Action* illidari_council_command_pets_to_attack_gathios(
PlayerbotAI* botAI) { return new IllidariCouncilCommandPetsToAttackGathiosAction(botAI); }
static Action* illidari_council_assign_dps_targets(
PlayerbotAI* botAI) { return new IllidariCouncilAssignDpsTargetsAction(botAI); }
static Action* illidari_council_manage_dps_timer(
PlayerbotAI* botAI) { return new IllidariCouncilManageDpsTimerAction(botAI); }
// Illidan Stormrage <The Betrayer>
static Action* illidan_stormrage_misdirect_to_tank(
PlayerbotAI* botAI) { return new IllidanStormrageMisdirectToTankAction(botAI); }
static Action* illidan_stormrage_main_tank_reposition_boss(
PlayerbotAI* botAI) { return new IllidanStormrageMainTankRepositionBossAction(botAI); }
static Action* illidan_stormrage_isolate_bot_with_parasite(
PlayerbotAI* botAI) { return new IllidanStormrageIsolateBotWithParasiteAction(botAI); }
static Action* illidan_stormrage_set_earthbind_totem(
PlayerbotAI* botAI) { return new IllidanStormrageSetEarthbindTotemAction(botAI); }
static Action* illidan_stormrage_assist_tanks_handle_flames_of_azzinoth(
PlayerbotAI* botAI) { return new IllidanStormrageAssistTanksHandleFlamesOfAzzinothAction(botAI); }
static Action* illidan_stormrage_control_pet_aggression(
PlayerbotAI* botAI) { return new IllidanStormrageControlPetAggressionAction(botAI); }
static Action* illidan_stormrage_position_above_grate(
PlayerbotAI* botAI) { return new IllidanStormragePositionAboveGrateAction(botAI); }
static Action* illidan_stormrage_remove_dark_barrage(
PlayerbotAI* botAI) { return new IllidanStormrageRemoveDarkBarrageAction(botAI); }
static Action* illidan_stormrage_move_away_from_landing_point(
PlayerbotAI* botAI) { return new IllidanStormrageMoveAwayFromLandingPointAction(botAI); }
static Action* illidan_stormrage_disperse_ranged(
PlayerbotAI* botAI) { return new IllidanStormrageDisperseRangedAction(botAI); }
static Action* illidan_stormrage_melee_go_somewhere_to_not_die(
PlayerbotAI* botAI) { return new IllidanStormrageMeleeGoSomewhereToNotDieAction(botAI); }
static Action* illidan_stormrage_warlock_tank_handle_demon_boss(
PlayerbotAI* botAI) { return new IllidanStormrageWarlockTankHandleDemonBossAction(botAI); }
static Action* illidan_stormrage_dps_prioritize_adds(
PlayerbotAI* botAI) { return new IllidanStormrageDpsPrioritizeAddsAction(botAI); }
static Action* illidan_stormrage_use_shadow_trap(
PlayerbotAI* botAI) { return new IllidanStormrageUseShadowTrapAction(botAI); }
static Action* illidan_stormrage_manage_dps_timer_and_rti(
PlayerbotAI* botAI) { return new IllidanStormrageManageDpsTimerAndRtiAction(botAI); }
static Action* illidan_stormrage_destroy_hazards(
PlayerbotAI* botAI) { return new IllidanStormrageDestroyHazardsAction(botAI); }
static Action* illidan_stormrage_handle_adds_cheat(
PlayerbotAI* botAI) { return new IllidanStormrageHandleAddsCheatAction(botAI); }
};
#endif

View File

@ -1,406 +0,0 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_RAIDBLACKTEMPLETRIGGERCONTEXT_H
#define _PLAYERBOT_RAIDBLACKTEMPLETRIGGERCONTEXT_H
#include "NamedObjectContext.h"
#include "RaidBlackTempleTriggers.h"
class RaidBlackTempleTriggerContext : public NamedObjectContext<Trigger>
{
public:
RaidBlackTempleTriggerContext()
{
// General
creators["black temple bot is not in combat"] =
&RaidBlackTempleTriggerContext::black_temple_bot_is_not_in_combat;
// High Warlord Naj'entus
creators["high warlord naj'entus pulling boss"] =
&RaidBlackTempleTriggerContext::high_warlord_najentus_pulling_boss;
creators["high warlord naj'entus boss engaged by tanks"] =
&RaidBlackTempleTriggerContext::high_warlord_najentus_boss_engaged_by_tanks;
creators["high warlord naj'entus casts needle spines"] =
&RaidBlackTempleTriggerContext::high_warlord_najentus_casts_needle_spines;
creators["high warlord naj'entus player is impaled"] =
&RaidBlackTempleTriggerContext::high_warlord_najentus_player_is_impaled;
creators["high warlord naj'entus boss has tidal shield"] =
&RaidBlackTempleTriggerContext::high_warlord_najentus_boss_has_tidal_shield;
// Supremus
creators["supremus pulling boss or changing phase"] =
&RaidBlackTempleTriggerContext::supremus_pulling_boss_or_changing_phase;
creators["supremus boss engaged by ranged"] =
&RaidBlackTempleTriggerContext::supremus_boss_engaged_by_ranged;
creators["supremus boss is fixated on bot"] =
&RaidBlackTempleTriggerContext::supremus_boss_is_fixated_on_bot;
creators["supremus volcano is nearby"] =
&RaidBlackTempleTriggerContext::supremus_volcano_is_nearby;
creators["supremus need to manage phase timer"] =
&RaidBlackTempleTriggerContext::supremus_need_to_manage_phase_timer;
// Shade of Akama
creators["shade of akama killing channelers starts phase 2"] =
&RaidBlackTempleTriggerContext::shade_of_akama_killing_channelers_starts_phase_2;
// Teron Gorefiend
creators["teron gorefiend pulling boss"] =
&RaidBlackTempleTriggerContext::teron_gorefiend_pulling_boss;
creators["teron gorefiend boss engaged by tanks"] =
&RaidBlackTempleTriggerContext::teron_gorefiend_boss_engaged_by_tanks;
creators["teron gorefiend boss engaged by ranged"] =
&RaidBlackTempleTriggerContext::teron_gorefiend_boss_engaged_by_ranged;
creators["teron gorefiend boss is casting shadow of death"] =
&RaidBlackTempleTriggerContext::teron_gorefiend_boss_is_casting_shadow_of_death;
creators["teron gorefiend bot has shadow of death"] =
&RaidBlackTempleTriggerContext::teron_gorefiend_bot_has_shadow_of_death;
creators["teron gorefiend bot transformed into vengeful spirit"] =
&RaidBlackTempleTriggerContext::teron_gorefiend_bot_transformed_into_vengeful_spirit;
// Gurtogg Bloodboil
creators["gurtogg bloodboil pulling boss"] =
&RaidBlackTempleTriggerContext::gurtogg_bloodboil_pulling_boss;
creators["gurtogg bloodboil boss engaged by tanks"] =
&RaidBlackTempleTriggerContext::gurtogg_bloodboil_boss_engaged_by_tanks;
creators["gurtogg bloodboil boss casts bloodboil"] =
&RaidBlackTempleTriggerContext::gurtogg_bloodboil_boss_casts_bloodboil;
creators["gurtogg bloodboil bot has fel rage"] =
&RaidBlackTempleTriggerContext::gurtogg_bloodboil_bot_has_fel_rage;
creators["gurtogg bloodboil need to manage phase timer"] =
&RaidBlackTempleTriggerContext::gurtogg_bloodboil_need_to_manage_phase_timer;
// Reliquary of Souls
creators["reliquary of souls aggro resets upon phase change"] =
&RaidBlackTempleTriggerContext::reliquary_of_souls_aggro_resets_upon_phase_change;
creators["reliquary of souls essence of suffering fixates on closest target"] =
&RaidBlackTempleTriggerContext::reliquary_of_souls_essence_of_suffering_fixates_on_closest_target;
creators["reliquary of souls essence of suffering disables healing"] =
&RaidBlackTempleTriggerContext::reliquary_of_souls_essence_of_suffering_disables_healing;
creators["reliquary of souls essence of desire has rune shield"] =
&RaidBlackTempleTriggerContext::reliquary_of_souls_essence_of_desire_has_rune_shield;
creators["reliquary of souls essence of desire casting deaden"] =
&RaidBlackTempleTriggerContext::reliquary_of_souls_essence_of_desire_casting_deaden;
// Mother Shahraz
creators["mother shahraz pulling boss"] =
&RaidBlackTempleTriggerContext::mother_shahraz_pulling_boss;
creators["mother shahraz boss engaged by tanks"] =
&RaidBlackTempleTriggerContext::mother_shahraz_boss_engaged_by_tanks;
creators["mother shahraz tanks are positioning boss"] =
&RaidBlackTempleTriggerContext::mother_shahraz_tanks_are_positioning_boss;
creators["mother shahraz sinister beam knocks back players"] =
&RaidBlackTempleTriggerContext::mother_shahraz_sinister_beam_knocks_back_players;
creators["mother shahraz bots are linked by fatal attraction"] =
&RaidBlackTempleTriggerContext::mother_shahraz_bots_are_linked_by_fatal_attraction;
// Illidari Council
creators["illidari council pulling bosses"] =
&RaidBlackTempleTriggerContext::illidari_council_pulling_bosses;
creators["illidari council gathios engaged by main tank"] =
&RaidBlackTempleTriggerContext::illidari_council_gathios_engaged_by_main_tank;
creators["illidari council gathios casting judgement of command"] =
&RaidBlackTempleTriggerContext::illidari_council_gathios_casting_judgement_of_command;
creators["illidari council malande engaged by first assist tank"] =
&RaidBlackTempleTriggerContext::illidari_council_malande_engaged_by_first_assist_tank;
creators["illidari council darkshadow engaged by second assist tank"] =
&RaidBlackTempleTriggerContext::illidari_council_darkshadow_engaged_by_second_assist_tank;
creators["illidari council zerevor engaged by mage tank"] =
&RaidBlackTempleTriggerContext::illidari_council_zerevor_engaged_by_mage_tank;
creators["illidari council mage tank needs dedicated healer"] =
&RaidBlackTempleTriggerContext::illidari_council_mage_tank_needs_dedicated_healer;
creators["illidari council zerevor casts dangerous aoes"] =
&RaidBlackTempleTriggerContext::illidari_council_zerevor_casts_dangerous_aoes;
creators["illidari council pets screw up the pull"] =
&RaidBlackTempleTriggerContext::illidari_council_pets_screw_up_the_pull;
creators["illidari council determining dps assignments"] =
&RaidBlackTempleTriggerContext::illidari_council_determining_dps_assignments;
creators["illidari council need to manage dps timer"] =
&RaidBlackTempleTriggerContext::illidari_council_need_to_manage_dps_timer;
// Illidan Stormrage <The Betrayer>
creators["illidan stormrage tank needs aggro"] =
&RaidBlackTempleTriggerContext::illidan_stormrage_tank_needs_aggro;
creators["illidan stormrage boss casts flame crash in front of main tank"] =
&RaidBlackTempleTriggerContext::illidan_stormrage_boss_casts_flame_crash_in_front_of_main_tank;
creators["illidan stormrage bot has parasitic shadowfiend"] =
&RaidBlackTempleTriggerContext::illidan_stormrage_bot_has_parasitic_shadowfiend;
creators["illidan stormrage parasitic shadowfiends run wild"] =
&RaidBlackTempleTriggerContext::illidan_stormrage_parasitic_shadowfiends_run_wild;
creators["illidan stormrage boss summoned flames of azzinoth"] =
&RaidBlackTempleTriggerContext::illidan_stormrage_boss_summoned_flames_of_azzinoth;
creators["illidan stormrage pets die to fire"] =
&RaidBlackTempleTriggerContext::illidan_stormrage_pets_die_to_fire;
creators["illidan stormrage grate is safe from flames"] =
&RaidBlackTempleTriggerContext::illidan_stormrage_grate_is_safe_from_flames;
creators["illidan stormrage bot struck by dark barrage"] =
&RaidBlackTempleTriggerContext::illidan_stormrage_bot_struck_by_dark_barrage;
creators["illidan stormrage boss is preparing to land"] =
&RaidBlackTempleTriggerContext::illidan_stormrage_boss_is_preparing_to_land;
creators["illidan stormrage boss deals splash damage"] =
&RaidBlackTempleTriggerContext::illidan_stormrage_boss_deals_splash_damage;
creators["illidan stormrage this expansion hates melee"] =
&RaidBlackTempleTriggerContext::illidan_stormrage_this_expansion_hates_melee;
creators["illidan stormrage boss transforms into demon"] =
&RaidBlackTempleTriggerContext::illidan_stormrage_boss_transforms_into_demon;
creators["illidan stormrage boss spawns adds"] =
&RaidBlackTempleTriggerContext::illidan_stormrage_boss_spawns_adds;
creators["illidan stormrage maiev placed shadow trap"] =
&RaidBlackTempleTriggerContext::illidan_stormrage_maiev_placed_shadow_trap;
creators["illidan stormrage need to manage dps timer and rti"] =
&RaidBlackTempleTriggerContext::illidan_stormrage_need_to_manage_dps_timer_and_rti;
creators["illidan stormrage need to clear hazards between phases"] =
&RaidBlackTempleTriggerContext::illidan_stormrage_need_to_clear_hazards_between_phases;
creators["illidan stormrage cheat"] =
&RaidBlackTempleTriggerContext::illidan_stormrage_cheat;
}
private:
// General
static Trigger* black_temple_bot_is_not_in_combat(
PlayerbotAI* botAI) { return new BlackTempleBotIsNotInCombatTrigger(botAI); }
// High Warlord Naj'entus
static Trigger* high_warlord_najentus_pulling_boss(
PlayerbotAI* botAI) { return new HighWarlordNajentusPullingBossTrigger(botAI); }
static Trigger* high_warlord_najentus_boss_engaged_by_tanks(
PlayerbotAI* botAI) { return new HighWarlordNajentusBossEngagedByTanksTrigger(botAI); }
static Trigger* high_warlord_najentus_casts_needle_spines(
PlayerbotAI* botAI) { return new HighWarlordNajentusCastsNeedleSpinesTrigger(botAI); }
static Trigger* high_warlord_najentus_player_is_impaled(
PlayerbotAI* botAI) { return new HighWarlordNajentusPlayerIsImpaledTrigger(botAI); }
static Trigger* high_warlord_najentus_boss_has_tidal_shield(
PlayerbotAI* botAI) { return new HighWarlordNajentusBossHasTidalShieldTrigger(botAI); }
// Supremus
static Trigger* supremus_pulling_boss_or_changing_phase(
PlayerbotAI* botAI) { return new SupremusPullingBossOrChangingPhaseTrigger(botAI); }
static Trigger* supremus_boss_engaged_by_ranged(
PlayerbotAI* botAI) { return new SupremusBossEngagedByRangedTrigger(botAI); }
static Trigger* supremus_boss_is_fixated_on_bot(
PlayerbotAI* botAI) { return new SupremusBossIsFixatedOnBotTrigger(botAI); }
static Trigger* supremus_volcano_is_nearby(
PlayerbotAI* botAI) { return new SupremusVolcanoIsNearbyTrigger(botAI); }
static Trigger* supremus_need_to_manage_phase_timer(
PlayerbotAI* botAI) { return new SupremusNeedToManagePhaseTimerTrigger(botAI); }
// Shade of Akama
static Trigger* shade_of_akama_killing_channelers_starts_phase_2(
PlayerbotAI* botAI) { return new ShadeOfAkamaKillingChannelersStartsPhase2Trigger(botAI); }
// Teron Gorefiend
static Trigger* teron_gorefiend_pulling_boss(
PlayerbotAI* botAI) { return new TeronGorefiendPullingBossTrigger(botAI); }
static Trigger* teron_gorefiend_boss_engaged_by_tanks(
PlayerbotAI* botAI) { return new TeronGorefiendBossEngagedByTanksTrigger(botAI); }
static Trigger* teron_gorefiend_boss_engaged_by_ranged(
PlayerbotAI* botAI) { return new TeronGorefiendBossEngagedByRangedTrigger(botAI); }
static Trigger* teron_gorefiend_boss_is_casting_shadow_of_death(
PlayerbotAI* botAI) { return new TeronGorefiendBossIsCastingShadowOfDeathTrigger(botAI); }
static Trigger* teron_gorefiend_bot_has_shadow_of_death(
PlayerbotAI* botAI) { return new TeronGorefiendBotHasShadowOfDeathTrigger(botAI); }
static Trigger* teron_gorefiend_bot_transformed_into_vengeful_spirit(
PlayerbotAI* botAI) { return new TeronGorefiendBotTransformedIntoVengefulSpiritTrigger(botAI); }
// Gurtogg Bloodboil
static Trigger* gurtogg_bloodboil_pulling_boss(
PlayerbotAI* botAI) { return new GurtoggBloodboilPullingBossTrigger(botAI); }
static Trigger* gurtogg_bloodboil_boss_engaged_by_tanks(
PlayerbotAI* botAI) { return new GurtoggBloodboilBossEngagedByTanksTrigger(botAI); }
static Trigger* gurtogg_bloodboil_boss_casts_bloodboil(
PlayerbotAI* botAI) { return new GurtoggBloodboilBossCastsBloodboilTrigger(botAI); }
static Trigger* gurtogg_bloodboil_bot_has_fel_rage(
PlayerbotAI* botAI) { return new GurtoggBloodboilBotHasFelRageTrigger(botAI); }
static Trigger* gurtogg_bloodboil_need_to_manage_phase_timer(
PlayerbotAI* botAI) { return new GurtoggBloodboilNeedToManagePhaseTimerTrigger(botAI); }
// Reliquary of Souls
static Trigger* reliquary_of_souls_aggro_resets_upon_phase_change(
PlayerbotAI* botAI) { return new ReliquaryOfSoulsAggroResetsUponPhaseChangeTrigger(botAI); }
static Trigger* reliquary_of_souls_essence_of_suffering_fixates_on_closest_target(
PlayerbotAI* botAI) { return new ReliquaryOfSoulsEssenceOfSufferingFixatesOnClosestTargetTrigger(botAI); }
static Trigger* reliquary_of_souls_essence_of_suffering_disables_healing(
PlayerbotAI* botAI) { return new ReliquaryOfSoulsEssenceOfSufferingDisablesHealingTrigger(botAI); }
static Trigger* reliquary_of_souls_essence_of_desire_has_rune_shield(
PlayerbotAI* botAI) { return new ReliquaryOfSoulsEssenceOfDesireHasRuneShieldTrigger(botAI); }
static Trigger* reliquary_of_souls_essence_of_desire_casting_deaden(
PlayerbotAI* botAI) { return new ReliquaryOfSoulsEssenceOfDesireCastingDeadenTrigger(botAI); }
// Mother Shahraz
static Trigger* mother_shahraz_pulling_boss(
PlayerbotAI* botAI) { return new MotherShahrazPullingBossTrigger(botAI); }
static Trigger* mother_shahraz_boss_engaged_by_tanks(
PlayerbotAI* botAI) { return new MotherShahrazBossEngagedByTanksTrigger(botAI); }
static Trigger* mother_shahraz_tanks_are_positioning_boss(
PlayerbotAI* botAI) { return new MotherShahrazTanksArePositioningBossTrigger(botAI); }
static Trigger* mother_shahraz_sinister_beam_knocks_back_players(
PlayerbotAI* botAI) { return new MotherShahrazSinisterBeamKnocksBackPlayersTrigger(botAI); }
static Trigger* mother_shahraz_bots_are_linked_by_fatal_attraction(
PlayerbotAI* botAI) { return new MotherShahrazBotsAreLinkedByFatalAttractionTrigger(botAI); }
// Illidari Council
static Trigger* illidari_council_pulling_bosses(
PlayerbotAI* botAI) { return new IllidariCouncilPullingBossesTrigger(botAI); }
static Trigger* illidari_council_gathios_engaged_by_main_tank(
PlayerbotAI* botAI) { return new IllidariCouncilGathiosEngagedByMainTankTrigger(botAI); }
static Trigger* illidari_council_gathios_casting_judgement_of_command(
PlayerbotAI* botAI) { return new IllidariCouncilGathiosCastingJudgementOfCommandTrigger(botAI); }
static Trigger* illidari_council_malande_engaged_by_first_assist_tank(
PlayerbotAI* botAI) { return new IllidariCouncilMalandeEngagedByFirstAssistTankTrigger(botAI); }
static Trigger* illidari_council_darkshadow_engaged_by_second_assist_tank(
PlayerbotAI* botAI) { return new IllidariCouncilDarkshadowEngagedBySecondAssistTankTrigger(botAI); }
static Trigger* illidari_council_zerevor_engaged_by_mage_tank(
PlayerbotAI* botAI) { return new IllidariCouncilZerevorEngagedByMageTankTrigger(botAI); }
static Trigger* illidari_council_mage_tank_needs_dedicated_healer(
PlayerbotAI* botAI) { return new IllidariCouncilMageTankNeedsDedicatedHealerTrigger(botAI); }
static Trigger* illidari_council_zerevor_casts_dangerous_aoes(
PlayerbotAI* botAI) { return new IllidariCouncilZerevorCastsDangerousAoesTrigger(botAI); }
static Trigger* illidari_council_pets_screw_up_the_pull(
PlayerbotAI* botAI) { return new IllidariCouncilPetsScrewUpThePullTrigger(botAI); }
static Trigger* illidari_council_determining_dps_assignments(
PlayerbotAI* botAI) { return new IllidariCouncilDeterminingDpsAssignmentsTrigger(botAI); }
static Trigger* illidari_council_need_to_manage_dps_timer(
PlayerbotAI* botAI) { return new IllidariCouncilNeedToManageDpsTimerTrigger(botAI); }
// Illidan Stormrage <The Betrayer>
static Trigger* illidan_stormrage_tank_needs_aggro(
PlayerbotAI* botAI) { return new IllidanStormrageTankNeedsAggroTrigger(botAI); }
static Trigger* illidan_stormrage_boss_casts_flame_crash_in_front_of_main_tank(
PlayerbotAI* botAI) { return new IllidanStormrageBossCastsFlameCrashInFrontOfMainTankTrigger(botAI); }
static Trigger* illidan_stormrage_bot_has_parasitic_shadowfiend(
PlayerbotAI* botAI) { return new IllidanStormrageBotHasParasiticShadowfiendTrigger(botAI); }
static Trigger* illidan_stormrage_parasitic_shadowfiends_run_wild(
PlayerbotAI* botAI) { return new IllidanStormrageParasiticShadowfiendsRunWildTrigger(botAI); }
static Trigger* illidan_stormrage_boss_summoned_flames_of_azzinoth(
PlayerbotAI* botAI) { return new IllidanStormrageBossSummonedFlamesOfAzzinothTrigger(botAI); }
static Trigger* illidan_stormrage_pets_die_to_fire(
PlayerbotAI* botAI) { return new IllidanStormragePetsDieToFireTrigger(botAI); }
static Trigger* illidan_stormrage_grate_is_safe_from_flames(
PlayerbotAI* botAI) { return new IllidanStormrageGrateIsSafeFromFlamesTrigger(botAI); }
static Trigger* illidan_stormrage_bot_struck_by_dark_barrage(
PlayerbotAI* botAI) { return new IllidanStormrageBotStruckByDarkBarrageTrigger(botAI); }
static Trigger* illidan_stormrage_boss_is_preparing_to_land(
PlayerbotAI* botAI) { return new IllidanStormrageBossIsPreparingToLandTrigger(botAI); }
static Trigger* illidan_stormrage_boss_deals_splash_damage(
PlayerbotAI* botAI) { return new IllidanStormrageBossDealsSplashDamageTrigger(botAI); }
static Trigger* illidan_stormrage_this_expansion_hates_melee(
PlayerbotAI* botAI) { return new IllidanStormrageThisExpansionHatesMeleeTrigger(botAI); }
static Trigger* illidan_stormrage_boss_transforms_into_demon(
PlayerbotAI* botAI) { return new IllidanStormrageBossTransformsIntoDemonTrigger(botAI); }
static Trigger* illidan_stormrage_boss_spawns_adds(
PlayerbotAI* botAI) { return new IllidanStormrageBossSpawnsAddsTrigger(botAI); }
static Trigger* illidan_stormrage_maiev_placed_shadow_trap(
PlayerbotAI* botAI) { return new IllidanStormrageMaievPlacedShadowTrapTrigger(botAI); }
static Trigger* illidan_stormrage_need_to_manage_dps_timer_and_rti(
PlayerbotAI* botAI) { return new IllidanStormrageNeedToManageDpsTimerAndRtiTrigger(botAI); }
static Trigger* illidan_stormrage_need_to_clear_hazards_between_phases(
PlayerbotAI* botAI) { return new IllidanStormrageNeedToClearHazardsBetweenPhasesTrigger(botAI); }
static Trigger* illidan_stormrage_cheat(
PlayerbotAI* botAI) { return new IllidanStormrageCheatTrigger(botAI); }
};
#endif

View File

@ -1,253 +0,0 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#include "RaidBlackTempleStrategy.h"
#include "RaidBlackTempleMultipliers.h"
void RaidBlackTempleStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
// General
triggers.push_back(new TriggerNode("black temple bot is not in combat", {
NextAction("black temple erase timers and trackers", ACTION_EMERGENCY + 11) }));
// High Warlord Naj'entus
triggers.push_back(new TriggerNode("high warlord naj'entus pulling boss", {
NextAction("high warlord naj'entus misdirect boss to main tank", ACTION_RAID + 2) }));
triggers.push_back(new TriggerNode("high warlord naj'entus boss engaged by tanks", {
NextAction("high warlord naj'entus tanks position boss", ACTION_RAID + 1) }));
triggers.push_back(new TriggerNode("high warlord naj'entus casts needle spines", {
NextAction("high warlord naj'entus disperse ranged", ACTION_RAID + 1) }));
triggers.push_back(new TriggerNode("high warlord naj'entus player is impaled", {
NextAction("high warlord naj'entus remove impaling spine", ACTION_EMERGENCY + 1) }));
triggers.push_back(new TriggerNode("high warlord naj'entus boss has tidal shield", {
NextAction("high warlord naj'entus throw impaling spine", ACTION_RAID + 2) }));
// Supremus
triggers.push_back(new TriggerNode("supremus pulling boss or changing phase", {
NextAction("supremus misdirect boss to main tank", ACTION_RAID + 2) }));
triggers.push_back(new TriggerNode("supremus boss engaged by ranged", {
NextAction("supremus disperse ranged", ACTION_RAID + 1) }));
triggers.push_back(new TriggerNode("supremus boss is fixated on bot", {
NextAction("supremus kite boss", ACTION_EMERGENCY + 7) }));
triggers.push_back(new TriggerNode("supremus volcano is nearby", {
NextAction("supremus move away from volcanos", ACTION_EMERGENCY + 6) }));
triggers.push_back(new TriggerNode("supremus need to manage phase timer", {
NextAction("supremus manage phase timer", ACTION_EMERGENCY + 10) }));
// Shade of Akama
triggers.push_back(new TriggerNode("shade of akama killing channelers starts phase 2", {
NextAction("shade of akama melee dps prioritize channelers", ACTION_RAID + 1) }));
// Teron Gorefiend
triggers.push_back(new TriggerNode("teron gorefiend pulling boss", {
NextAction("teron gorefiend misdirect boss to main tank", ACTION_RAID + 2) }));
triggers.push_back(new TriggerNode("teron gorefiend boss engaged by tanks", {
NextAction("teron gorefiend tanks position boss", ACTION_RAID + 1) }));
triggers.push_back(new TriggerNode("teron gorefiend boss engaged by ranged", {
NextAction("teron gorefiend position ranged on balcony", ACTION_RAID + 1) }));
triggers.push_back(new TriggerNode("teron gorefiend boss is casting shadow of death", {
NextAction("teron gorefiend avoid shadow of death", ACTION_EMERGENCY + 10) }));
triggers.push_back(new TriggerNode("teron gorefiend bot has shadow of death", {
NextAction("teron gorefiend move to corner to die", ACTION_EMERGENCY + 10) }));
triggers.push_back(new TriggerNode("teron gorefiend bot transformed into vengeful spirit", {
NextAction("teron gorefiend control and destroy shadowy constructs", ACTION_EMERGENCY + 10) }));
// Gurtogg Bloodboil
triggers.push_back(new TriggerNode("gurtogg bloodboil pulling boss", {
NextAction("gurtogg bloodboil misdirect boss to main tank", ACTION_RAID + 2) }));
triggers.push_back(new TriggerNode("gurtogg bloodboil boss engaged by tanks", {
NextAction("gurtogg bloodboil tanks position boss", ACTION_RAID + 1) }));
triggers.push_back(new TriggerNode("gurtogg bloodboil boss casts bloodboil", {
NextAction("gurtogg bloodboil rotate ranged groups", ACTION_RAID + 1) }));
triggers.push_back(new TriggerNode("gurtogg bloodboil bot has fel rage", {
NextAction("gurtogg bloodboil ranged move away from enraged player", ACTION_RAID + 1) }));
triggers.push_back(new TriggerNode("gurtogg bloodboil need to manage phase timer", {
NextAction("gurtogg bloodboil manage phase timer", ACTION_EMERGENCY + 10) }));
// Reliquary of Souls
triggers.push_back(new TriggerNode("reliquary of souls aggro resets upon phase change", {
NextAction("reliquary of souls misdirect boss to main tank", ACTION_RAID + 3) }));
triggers.push_back(new TriggerNode("reliquary of souls essence of suffering fixates on closest target", {
NextAction("reliquary of souls adjust distance from suffering", ACTION_RAID + 2) }));
triggers.push_back(new TriggerNode("reliquary of souls essence of suffering disables healing", {
NextAction("reliquary of souls healers dps suffering", ACTION_RAID + 1) }));
triggers.push_back(new TriggerNode("reliquary of souls essence of desire has rune shield", {
NextAction("reliquary of souls spellsteal rune shield", ACTION_EMERGENCY + 6) }));
triggers.push_back(new TriggerNode("reliquary of souls essence of desire casting deaden", {
NextAction("reliquary of souls spell reflect deaden", ACTION_EMERGENCY + 6) }));
// Mother Shahraz
triggers.push_back(new TriggerNode("mother shahraz pulling boss", {
NextAction("mother shahraz misdirect boss to main tank", ACTION_RAID + 2) }));
triggers.push_back(new TriggerNode("mother shahraz boss engaged by tanks", {
NextAction("mother shahraz tanks position boss under pillar", ACTION_RAID + 1) }));
triggers.push_back(new TriggerNode("mother shahraz tanks are positioning boss", {
NextAction("mother shahraz melee dps wait at safe position", ACTION_EMERGENCY + 1) }));
triggers.push_back(new TriggerNode("mother shahraz sinister beam knocks back players", {
NextAction("mother shahraz position ranged under pillar", ACTION_RAID + 1) }));
triggers.push_back(new TriggerNode("mother shahraz bots are linked by fatal attraction", {
NextAction("mother shahraz run away to break fatal attraction", ACTION_EMERGENCY + 10) }));
// Illidari Council
triggers.push_back(new TriggerNode("illidari council pulling bosses", {
NextAction("illidari council misdirect bosses to tanks", ACTION_RAID + 4) }));
triggers.push_back(new TriggerNode("illidari council gathios engaged by main tank", {
NextAction("illidari council main tank position gathios", ACTION_RAID + 1) }));
triggers.push_back(new TriggerNode("illidari council gathios casting judgement of command", {
NextAction("illidari council main tank reflect judgement of command", ACTION_EMERGENCY + 1) }));
triggers.push_back(new TriggerNode("illidari council malande engaged by first assist tank", {
NextAction("illidari council first assist tank focus malande", ACTION_RAID + 1) }));
triggers.push_back(new TriggerNode("illidari council darkshadow engaged by second assist tank", {
NextAction("illidari council second assist tank position darkshadow", ACTION_RAID + 1) }));
triggers.push_back(new TriggerNode("illidari council zerevor engaged by mage tank", {
NextAction("illidari council mage tank position zerevor", ACTION_EMERGENCY + 6) }));
triggers.push_back(new TriggerNode("illidari council mage tank needs dedicated healer", {
NextAction("illidari council position mage tank healer", ACTION_RAID + 1) }));
triggers.push_back(new TriggerNode("illidari council zerevor casts dangerous aoes", {
NextAction("illidari council disperse ranged", ACTION_RAID + 2) }));
triggers.push_back(new TriggerNode("illidari council pets screw up the pull", {
NextAction("illidari council command pets to attack gathios", ACTION_RAID + 3) }));
triggers.push_back(new TriggerNode("illidari council determining dps assignments", {
NextAction("illidari council assign dps targets", ACTION_RAID + 1) }));
triggers.push_back(new TriggerNode("illidari council need to manage dps timer", {
NextAction("illidari council manage dps timer", ACTION_EMERGENCY + 10) }));
// Illidan Stormrage <The Betrayer>
triggers.push_back(new TriggerNode("illidan stormrage tank needs aggro", {
NextAction("illidan stormrage misdirect to tank", ACTION_RAID + 3) }));
triggers.push_back(new TriggerNode("illidan stormrage boss casts flame crash in front of main tank", {
NextAction("illidan stormrage main tank reposition boss", ACTION_EMERGENCY + 1) }));
triggers.push_back(new TriggerNode("illidan stormrage bot has parasitic shadowfiend", {
NextAction("illidan stormrage isolate bot with parasite", ACTION_RAID + 3) }));
triggers.push_back(new TriggerNode("illidan stormrage parasitic shadowfiends run wild", {
NextAction("illidan stormrage set earthbind totem", ACTION_RAID + 1) }));
triggers.push_back(new TriggerNode("illidan stormrage boss summoned flames of azzinoth", {
NextAction("illidan stormrage assist tanks handle flames of azzinoth", ACTION_EMERGENCY + 1) }));
triggers.push_back(new TriggerNode("illidan stormrage pets die to fire", {
NextAction("illidan stormrage control pet aggression", ACTION_RAID + 4) }));
triggers.push_back(new TriggerNode("illidan stormrage grate is safe from flames", {
NextAction("illidan stormrage position above grate", ACTION_EMERGENCY + 2) }));
triggers.push_back(new TriggerNode("illidan stormrage bot struck by dark barrage", {
NextAction("illidan stormrage remove dark barrage", ACTION_EMERGENCY + 6) }));
triggers.push_back(new TriggerNode("illidan stormrage boss is preparing to land", {
NextAction("illidan stormrage move away from landing point", ACTION_EMERGENCY + 3) }));
triggers.push_back(new TriggerNode("illidan stormrage boss deals splash damage", {
NextAction("illidan stormrage disperse ranged", ACTION_RAID + 2) }));
triggers.push_back(new TriggerNode("illidan stormrage this expansion hates melee", {
NextAction("illidan stormrage melee go somewhere to not die", ACTION_RAID + 2) }));
triggers.push_back(new TriggerNode("illidan stormrage boss transforms into demon", {
NextAction("illidan stormrage warlock tank handle demon boss", ACTION_EMERGENCY + 9) }));
triggers.push_back(new TriggerNode("illidan stormrage boss spawns adds", {
NextAction("illidan stormrage dps prioritize adds", ACTION_EMERGENCY + 1) }));
triggers.push_back(new TriggerNode("illidan stormrage maiev placed shadow trap", {
NextAction("illidan stormrage use shadow trap", ACTION_EMERGENCY + 1) }));
triggers.push_back(new TriggerNode("illidan stormrage need to manage dps timer and rti", {
NextAction("illidan stormrage manage dps timer and rti", ACTION_EMERGENCY + 11) }));
triggers.push_back(new TriggerNode("illidan stormrage need to clear hazards between phases", {
NextAction("illidan stormrage destroy hazards", ACTION_EMERGENCY + 10) }));
triggers.push_back(new TriggerNode("illidan stormrage cheat", {
NextAction("illidan stormrage handle adds cheat", ACTION_EMERGENCY + 10) }));
}
void RaidBlackTempleStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers)
{
// High Warlord Naj'entus
multipliers.push_back(new HighWarlordNajentusDelayDpsCooldownsMultiplier(botAI));
multipliers.push_back(new HighWarlordNajentusDisableCombatFormationMoveMultiplier(botAI));
// Supremus
multipliers.push_back(new SupremusDelayDpsCooldownsMultiplier(botAI));
multipliers.push_back(new SupremusFocusOnAvoidanceInPhase2Multiplier(botAI));
multipliers.push_back(new SupremusHitboxIsBuggedMultiplier(botAI));
// Teron Gorefiend
multipliers.push_back(new TeronGorefiendDelayDpsCooldownsMultiplier(botAI));
multipliers.push_back(new TeronGorefiendControlMovementMultiplier(botAI));
multipliers.push_back(new TeronGorefiendMarkedBotOnlyMoveToDieMultiplier(botAI));
multipliers.push_back(new TeronGorefiendSpiritsAttackOnlyShadowyConstructsMultiplier(botAI));
multipliers.push_back(new TeronGorefiendDisableAttackingConstructsMultiplier(botAI));
// Gurtogg Bloodboil
multipliers.push_back(new GurtoggBloodboilDelayDpsCooldownsMultiplier(botAI));
multipliers.push_back(new GurtoggBloodboilControlMovementMultiplier(botAI));
// Reliquary of Souls
multipliers.push_back(new ReliquaryOfSoulsDelayDpsCooldownsMultiplier(botAI));
multipliers.push_back(new ReliquaryOfSoulsDontWasteHealingMultiplier(botAI));
// Mother Shahraz
multipliers.push_back(new MotherShahrazDelayDpsCooldownsMultiplier(botAI));
multipliers.push_back(new MotherShahrazControlMovementMultiplier(botAI));
multipliers.push_back(new MotherShahrazBotsWithFatalAttractionOnlyRunAwayMultiplier(botAI));
// Illidari Council
multipliers.push_back(new IllidariCouncilDelayDpsCooldownsMultiplier(botAI));
multipliers.push_back(new IllidariCouncilDisableTankActionsMultiplier(botAI));
multipliers.push_back(new IllidariCouncilControlMovementMultiplier(botAI));
multipliers.push_back(new IllidariCouncilControlMisdirectionMultiplier(botAI));
multipliers.push_back(new IllidariCouncilDisableArcaneShotOnZerevorMultiplier(botAI));
multipliers.push_back(new IllidariCouncilDisableIceBlockMultiplier(botAI));
multipliers.push_back(new IllidariCouncilWaitForDpsMultiplier(botAI));
// Illidan Stormrage <The Betrayer>
multipliers.push_back(new IllidanStormrageDelayDpsCooldownsMultiplier(botAI));
multipliers.push_back(new IllidanStormrageControlTankActionsMultiplier(botAI));
multipliers.push_back(new IllidanStormrageDisableDefaultTargetingMultiplier(botAI));
multipliers.push_back(new IllidanStormrageControlNonTankMovementMultiplier(botAI));
multipliers.push_back(new IllidanStormrageUseEarthbindTotemMultiplier(botAI));
multipliers.push_back(new IllidanStormrageWaitForDpsMultiplier(botAI));
}

View File

@ -1,22 +0,0 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_RAIDBLACKTEMPLESTRATEGY_H_
#define _PLAYERBOT_RAIDBLACKTEMPLESTRATEGY_H_
#include "Strategy.h"
class RaidBlackTempleStrategy : public Strategy
{
public:
RaidBlackTempleStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
std::string const getName() override { return "blacktemple"; }
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
void InitMultipliers(std::vector<Multiplier*>& multipliers) override;
};
#endif

View File

@ -1,863 +0,0 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#include "RaidBlackTempleTriggers.h"
#include "AiFactory.h"
#include "Playerbots.h"
#include "RaidBlackTempleActions.h"
#include "RaidBlackTempleHelpers.h"
#include "RaidBossHelpers.h"
#include "SharedDefines.h"
using namespace BlackTempleHelpers;
// General
bool BlackTempleBotIsNotInCombatTrigger::IsActive()
{
return !bot->IsInCombat() && bot->GetMapId() == BLACK_TEMPLE_MAP_ID;
}
// High Warlord Naj'entus
bool HighWarlordNajentusPullingBossTrigger::IsActive()
{
if (bot->getClass() != CLASS_HUNTER)
return false;
Unit* najentus = AI_VALUE2(Unit*, "find target", "high warlord naj'entus");
return najentus && najentus->GetHealthPct() > 95.0f;
}
bool HighWarlordNajentusBossEngagedByTanksTrigger::IsActive()
{
return botAI->IsTank(bot) &&
AI_VALUE2(Unit*, "find target", "high warlord naj'entus");
}
bool HighWarlordNajentusCastsNeedleSpinesTrigger::IsActive()
{
return botAI->IsRanged(bot) &&
AI_VALUE2(Unit*, "find target", "high warlord naj'entus");
}
bool HighWarlordNajentusPlayerIsImpaledTrigger::IsActive()
{
if (botAI->IsTank(bot))
return false;
if (!AI_VALUE2(Unit*, "find target", "high warlord naj'entus"))
return false;
Group* group = bot->GetGroup();
if (!group)
return false;
Player* impaledPlayer = nullptr;
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
{
Player* member = ref->GetSource();
if (!member || member == bot)
continue;
if (member->HasAura(
static_cast<uint32>(BlackTempleSpells::SPELL_IMPALING_SPINE)))
{
impaledPlayer = member;
break;
}
}
Player* closestBot = nullptr;
float closestDist = std::numeric_limits<float>::max();
if (impaledPlayer)
{
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
{
Player* member = ref->GetSource();
if (!member || !member->IsAlive() || member == impaledPlayer ||
!GET_PLAYERBOT_AI(member) || botAI->IsTank(member))
{
continue;
}
float dist = member->GetDistance(impaledPlayer);
if (dist < closestDist)
{
closestDist = dist;
closestBot = member;
}
}
}
return closestBot == bot;
}
bool HighWarlordNajentusBossHasTidalShieldTrigger::IsActive()
{
Unit* najentus = AI_VALUE2(Unit*, "find target", "high warlord naj'entus");
if (!najentus || !najentus->HasAura(
static_cast<uint32>(BlackTempleSpells::SPELL_TIDAL_SHIELD)))
{
return false;
}
return botAI->HasItemInInventory(
static_cast<uint32>(BlackTempleItems::ITEM_NAJENTUS_SPINE));
}
// Supremus
bool SupremusPullingBossOrChangingPhaseTrigger::IsActive()
{
if (bot->getClass() != CLASS_HUNTER)
return false;
Unit* supremus = AI_VALUE2(Unit*, "find target", "supremus");
if (!supremus)
return false;
auto it = supremusPhaseTimer.find(supremus->GetMap()->GetInstanceId());
if (it == supremusPhaseTimer.end())
return false;
const time_t now = time(nullptr);
const time_t elapsed = now - it->second;
// Active during first 10 seconds, or during 60-70, 120-130, etc.
return (elapsed < 10) || ((elapsed % 60) < 10 && elapsed >= 60);
}
bool SupremusBossEngagedByRangedTrigger::IsActive()
{
if (!botAI->IsRanged(bot))
return false;
Unit* supremus = AI_VALUE2(Unit*, "find target", "supremus");
return supremus && !supremus->HasAura(
static_cast<uint32>(BlackTempleSpells::SPELL_SNARE_SELF));
}
bool SupremusBossIsFixatedOnBotTrigger::IsActive()
{
Unit* supremus = AI_VALUE2(Unit*, "find target", "supremus");
return supremus && supremus->GetVictim() == bot &&
supremus->HasAura(static_cast<uint32>(
BlackTempleSpells::SPELL_SNARE_SELF));
}
bool SupremusVolcanoIsNearbyTrigger::IsActive()
{
return AI_VALUE2(Unit*, "find target", "supremus") &&
HasSupremusVolcanoNearby(botAI, bot);
}
bool SupremusNeedToManagePhaseTimerTrigger::IsActive()
{
if (!botAI->IsDps(bot))
return false;
if (!AI_VALUE2(Unit*, "find target", "supremus"))
return false;
return IsMechanicTrackerBot(botAI, bot, BLACK_TEMPLE_MAP_ID);
}
// Shade of Akama
bool ShadeOfAkamaKillingChannelersStartsPhase2Trigger::IsActive()
{
if (!botAI->IsDps(bot) || !botAI->IsMelee(bot))
return false;
constexpr float searchRadius = 30.0f;
Unit* channeler = bot->FindNearestCreature(
static_cast<uint32>(BlackTempleNpcs::NPC_ASHTONGUE_CHANNELER),
searchRadius, true);
return channeler && !channeler->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
}
// Teron Gorefiend
bool TeronGorefiendPullingBossTrigger::IsActive()
{
if (bot->getClass() != CLASS_HUNTER)
return false;
Unit* gorefiend =
AI_VALUE2(Unit*, "find target", "teron gorefiend");
return gorefiend && gorefiend->GetHealthPct() > 95.0f;
}
bool TeronGorefiendBossEngagedByTanksTrigger::IsActive()
{
return botAI->IsTank(bot) &&
AI_VALUE2(Unit*, "find target", "teron gorefiend");
}
bool TeronGorefiendBossEngagedByRangedTrigger::IsActive()
{
return botAI->IsRanged(bot) &&
AI_VALUE2(Unit*, "find target", "teron gorefiend");
}
bool TeronGorefiendBossIsCastingShadowOfDeathTrigger::IsActive()
{
if (bot->getClass() != CLASS_HUNTER && bot->getClass() != CLASS_MAGE &&
bot->getClass() != CLASS_PALADIN && bot->getClass() != CLASS_ROGUE)
{
return false;
}
Unit* gorefiend = AI_VALUE2(Unit*, "find target", "teron gorefiend");
if (!gorefiend)
return false;
if (botAI->HasAura("feign death", bot))
{
botAI->RemoveAura("feign death");
return true;
}
else if (botAI->HasAura("ice block", bot))
{
botAI->RemoveAura("ice block");
return true;
}
else if (!botAI->IsHeal(bot) && botAI->HasAura("divine shield", bot))
{
botAI->RemoveAura("divine shield");
return true;
}
if (!gorefiend->HasUnitState(UNIT_STATE_CASTING))
return false;
Spell* spell = gorefiend->GetCurrentSpell(CURRENT_GENERIC_SPELL);
if (!spell || spell->m_spellInfo->Id !=
static_cast<uint32>(BlackTempleSpells::SPELL_SHADOW_OF_DEATH))
{
return false;
}
Unit* target = spell->m_targets.GetUnitTarget();
return target && target->GetGUID() == bot->GetGUID();
}
bool TeronGorefiendBotHasShadowOfDeathTrigger::IsActive()
{
Aura* aura = bot->GetAura(
static_cast<uint32>(BlackTempleSpells::SPELL_SHADOW_OF_DEATH));
return aura && aura->GetDuration() < 12000;
}
bool TeronGorefiendBotTransformedIntoVengefulSpiritTrigger::IsActive()
{
return bot->HasAura(
static_cast<uint32>(BlackTempleSpells::SPELL_SPIRITUAL_VENGEANCE));
}
// Gurtogg Bloodboil
bool GurtoggBloodboilPullingBossTrigger::IsActive()
{
if (bot->getClass() != CLASS_HUNTER)
return false;
Unit* gurtogg = AI_VALUE2(Unit*, "find target", "gurtogg bloodboil");
if (!gurtogg)
return false;
auto it = gurtoggPhaseTimer.find(gurtogg->GetMap()->GetInstanceId());
if (it == gurtoggPhaseTimer.end())
return false;
const time_t elapsed = std::time(nullptr) - it->second;
return elapsed < 10;
}
bool GurtoggBloodboilBossEngagedByTanksTrigger::IsActive()
{
if (!botAI->IsTank(bot))
return false;
Unit* gurtogg = AI_VALUE2(Unit*, "find target", "gurtogg bloodboil");
return gurtogg && !gurtogg->HasAura(
static_cast<uint32>(BlackTempleSpells::SPELL_BOSS_FEL_RAGE));
}
bool GurtoggBloodboilBossCastsBloodboilTrigger::IsActive()
{
if (!botAI->IsRanged(bot))
return false;
Unit* gurtogg = AI_VALUE2(Unit*, "find target", "gurtogg bloodboil");
return gurtogg && !gurtogg->HasAura(
static_cast<uint32>(BlackTempleSpells::SPELL_BOSS_FEL_RAGE));
}
bool GurtoggBloodboilBotHasFelRageTrigger::IsActive()
{
if (!botAI->IsRanged(bot))
return false;
Unit* gurtogg = AI_VALUE2(Unit*, "find target", "gurtogg bloodboil");
if (!gurtogg || !gurtogg->HasAura(
static_cast<uint32>(BlackTempleSpells::SPELL_BOSS_FEL_RAGE)))
{
return false;
}
if (Group* group = bot->GetGroup())
{
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
{
Player* member = ref->GetSource();
if (member && member->HasAura
(static_cast<uint32>(BlackTempleSpells::SPELL_PLAYER_FEL_RAGE)))
{
return true;
}
}
}
return false;
}
bool GurtoggBloodboilNeedToManagePhaseTimerTrigger::IsActive()
{
return AI_VALUE2(Unit*, "find target", "gurtogg bloodboil") &&
IsMechanicTrackerBot(botAI, bot, BLACK_TEMPLE_MAP_ID);
}
// Reliquary of Souls
bool ReliquaryOfSoulsAggroResetsUponPhaseChangeTrigger::IsActive()
{
return bot->getClass() == CLASS_HUNTER &&
AI_VALUE2(Unit*, "find target", "reliquary of the lost");
}
bool ReliquaryOfSoulsEssenceOfSufferingFixatesOnClosestTargetTrigger::IsActive()
{
return AI_VALUE2(Unit*, "find target", "essence of suffering");
}
bool ReliquaryOfSoulsEssenceOfSufferingDisablesHealingTrigger::IsActive()
{
if (!botAI->IsHeal(bot))
return false;
if (bot->getClass() == CLASS_PRIEST &&
AiFactory::GetPlayerSpecTab(bot) == PRIEST_TAB_DISCIPLINE)
{
return false;
}
return AI_VALUE2(Unit*, "find target", "essence of suffering");
}
bool ReliquaryOfSoulsEssenceOfDesireHasRuneShieldTrigger::IsActive()
{
if (bot->getClass() != CLASS_MAGE)
return false;
Unit* desire = AI_VALUE2(Unit*, "find target", "essence of desire");
return desire && desire->HasAura(
static_cast<uint32>(BlackTempleSpells::SPELL_RUNE_SHIELD));
}
bool ReliquaryOfSoulsEssenceOfDesireCastingDeadenTrigger::IsActive()
{
if (!botAI->IsTank(bot) || bot->getClass() != CLASS_WARRIOR)
return false;
Unit* desire = AI_VALUE2(Unit*, "find target", "essence of desire");
if (!desire || !desire->HasUnitState(UNIT_STATE_CASTING))
return false;
Spell* spell = desire->GetCurrentSpell(CURRENT_GENERIC_SPELL);
if (!spell || spell->m_spellInfo->Id !=
static_cast<uint32>(BlackTempleSpells::SPELL_DEADEN))
{
return false;
}
Unit* target = spell->m_targets.GetUnitTarget();
return target && target->GetGUID() == bot->GetGUID();
}
// Mother Shahraz
bool MotherShahrazPullingBossTrigger::IsActive()
{
if (bot->getClass() != CLASS_HUNTER)
return false;
Unit* shahraz = AI_VALUE2(Unit*, "find target", "mother shahraz");
return shahraz && shahraz->GetHealthPct() > 95.0f;
}
bool MotherShahrazBossEngagedByTanksTrigger::IsActive()
{
if (!botAI->IsTank(bot))
return false;
if (!AI_VALUE2(Unit*, "find target", "mother shahraz"))
return false;
return !bot->HasAura(
static_cast<uint32>(BlackTempleSpells::SPELL_FATAL_ATTRACTION));
}
bool MotherShahrazTanksArePositioningBossTrigger::IsActive()
{
if (!botAI->IsMelee(bot) || !botAI->IsDps(bot))
return false;
Unit* shahraz = AI_VALUE2(Unit*, "find target", "mother shahraz");
if (!shahraz || shahraz->GetHealthPct() < 90.0f)
return false;
TankPositionState tankState = GetShahrazTankPositionState(botAI, bot);
return tankState != TankPositionState::Positioned;
}
bool MotherShahrazSinisterBeamKnocksBackPlayersTrigger::IsActive()
{
if (!botAI->IsRanged(bot))
return false;
if (!AI_VALUE2(Unit*, "find target", "mother shahraz"))
return false;
return !bot->HasAura(
static_cast<uint32>(BlackTempleSpells::SPELL_FATAL_ATTRACTION));
}
bool MotherShahrazBotsAreLinkedByFatalAttractionTrigger::IsActive()
{
return bot->HasAura(
static_cast<uint32>(BlackTempleSpells::SPELL_FATAL_ATTRACTION));
}
// Illidari Council
bool IllidariCouncilPullingBossesTrigger::IsActive()
{
if (bot->getClass() != CLASS_HUNTER)
return false;
Unit* gathios = AI_VALUE2(Unit*, "find target", "gathios the shatterer");
return gathios && gathios->GetHealthPct() > 95.0f;
}
bool IllidariCouncilGathiosEngagedByMainTankTrigger::IsActive()
{
return botAI->IsMainTank(bot) &&
AI_VALUE2(Unit*, "find target", "gathios the shatterer");
}
bool IllidariCouncilGathiosCastingJudgementOfCommandTrigger::IsActive()
{
if (bot->getClass() != CLASS_WARRIOR || !botAI->IsMainTank(bot))
return false;
Unit* gathios = AI_VALUE2(Unit*, "find target", "gathios the shatterer");
if (!gathios || !gathios->HasUnitState(UNIT_STATE_CASTING) || !gathios->HasAura(
static_cast<uint32>(BlackTempleSpells::SPELL_SEAL_OF_COMMAND)))
{
return false;
}
Spell* spell = gathios->GetCurrentSpell(CURRENT_GENERIC_SPELL);
if (!spell || spell->m_spellInfo->Id !=
static_cast<uint32>(BlackTempleSpells::SPELL_JUDGEMENT))
{
return false;
}
Unit* target = spell->m_targets.GetUnitTarget();
return target && target->GetGUID() == bot->GetGUID();
}
bool IllidariCouncilMalandeEngagedByFirstAssistTankTrigger::IsActive()
{
return botAI->IsAssistTankOfIndex(bot, 0, false) &&
AI_VALUE2(Unit*, "find target", "lady malande");
}
bool IllidariCouncilDarkshadowEngagedBySecondAssistTankTrigger::IsActive()
{
if (!botAI->IsAssistTankOfIndex(bot, 1, false))
return false;
Unit* darkshadow = AI_VALUE2(Unit*, "find target", "veras darkshadow");
return darkshadow && !darkshadow->HasAura(
static_cast<uint32>(BlackTempleSpells::SPELL_VANISH));
}
bool IllidariCouncilZerevorEngagedByMageTankTrigger::IsActive()
{
if (bot->getClass() != CLASS_MAGE || GetZerevorMageTank(bot) != bot)
return false;
return AI_VALUE2(Unit*, "find target", "high nethermancer zerevor");
}
bool IllidariCouncilMageTankNeedsDedicatedHealerTrigger::IsActive()
{
return botAI->IsAssistHealOfIndex(bot, 0, true) &&
AI_VALUE2(Unit*, "find target", "high nethermancer zerevor");
}
bool IllidariCouncilZerevorCastsDangerousAoesTrigger::IsActive()
{
if (!botAI->IsRanged(bot))
return false;
if (!AI_VALUE2(Unit*, "find target", "high nethermancer zerevor"))
return false;
return !HasDangerousCouncilAura(bot);
}
bool IllidariCouncilPetsScrewUpThePullTrigger::IsActive()
{
if (bot->getClass() != CLASS_HUNTER && bot->getClass() != CLASS_WARLOCK)
return false;
Pet* pet = bot->GetPet();
if (!pet || !pet->IsAlive())
return false;
return AI_VALUE2(Unit*, "find target", "gathios the shatterer");
}
bool IllidariCouncilDeterminingDpsAssignmentsTrigger::IsActive()
{
if (botAI->IsHeal(bot))
return false;
if (!AI_VALUE2(Unit*, "find target", "gathios the shatterer"))
return false;
if (botAI->IsMainTank(bot) || botAI->IsAssistTankOfIndex(bot, 0, false) ||
GetZerevorMageTank(bot) == bot)
{
return false;
}
Unit* darkshadow = AI_VALUE2(Unit*, "find target", "veras darkshadow");
if (botAI->IsTank(bot) && botAI->IsAssistTankOfIndex(bot, 1, false) &&
darkshadow && !darkshadow->HasAura(
static_cast<uint32>(BlackTempleSpells::SPELL_VANISH)))
{
return false;
}
return true;
}
bool IllidariCouncilNeedToManageDpsTimerTrigger::IsActive()
{
if (!botAI->IsDps(bot))
return false;
if (!AI_VALUE2(Unit*, "find target", "gathios the shatterer"))
return false;
return IsMechanicTrackerBot(
botAI, bot, BLACK_TEMPLE_MAP_ID, GetZerevorMageTank(bot));
}
// Illidan Stormrage <The Betrayer>
bool IllidanStormrageTankNeedsAggroTrigger::IsActive()
{
if (bot->getClass() != CLASS_HUNTER)
return false;
Unit* illidan = AI_VALUE2(Unit*, "find target", "illidan stormrage");
return illidan && illidan->GetHealth() > 1;
}
bool IllidanStormrageBossCastsFlameCrashInFrontOfMainTankTrigger::IsActive()
{
if (!botAI->IsMainTank(bot))
return false;
Unit* illidan = AI_VALUE2(Unit*, "find target", "illidan stormrage");
if (!illidan)
return false;
int phase = GetIllidanPhase(illidan);
return phase == 1 || phase == 3 || phase == 5;
}
bool IllidanStormrageBotHasParasiticShadowfiendTrigger::IsActive()
{
Unit* illidan = AI_VALUE2(Unit*, "find target", "illidan stormrage");
if (!illidan || illidan->GetHealth() == 1 ||
illidan->GetVictim() == bot)
{
return false;
}
int phase = GetIllidanPhase(illidan);
if (phase == 2 || phase == 4)
return false;
if (botAI->IsMainTank(bot))
return false;
if (phase == 5 && FindNearestTrap(botAI, bot))
return false;
Player* infected = GetBotWithParasiticShadowfiend(bot);
if (!infected)
return false;
if (infected == bot ||
(phase != 1 && bot->getClass() == CLASS_HUNTER))
{
return true;
}
return false;
}
bool IllidanStormrageParasiticShadowfiendsRunWildTrigger::IsActive()
{
if (bot->getClass() != CLASS_SHAMAN)
return false;
Unit* illidan = AI_VALUE2(Unit*, "find target", "illidan stormrage");
if (!illidan || illidan->GetHealth() == 1 || GetIllidanPhase(illidan) == 2)
return false;
ObjectGuid guid = bot->m_SummonSlot[SUMMON_SLOT_TOTEM_EARTH];
if (guid.IsEmpty())
return true;
Creature* totem = bot->GetMap()->GetCreature(guid);
return !totem || totem->GetDistance(bot) > 20.0f ||
totem->GetUInt32Value(UNIT_CREATED_BY_SPELL) !=
static_cast<uint32>(BlackTempleSpells::SPELL_EARTHBIND_TOTEM);
}
bool IllidanStormrageBossSummonedFlamesOfAzzinothTrigger::IsActive()
{
if (!botAI->IsAssistTankOfIndex(bot, 0, true) &&
!botAI->IsAssistTankOfIndex(bot, 1, true))
{
return false;
}
Unit* illidan = AI_VALUE2(Unit*, "find target", "illidan stormrage");
return illidan && GetIllidanPhase(illidan) == 2;
}
bool IllidanStormragePetsDieToFireTrigger::IsActive()
{
Unit* illidan = AI_VALUE2(Unit*, "find target", "illidan stormrage");
if (!illidan || illidan->GetHealth() == 1)
return false;
Pet* pet = bot->GetPet();
return pet && pet->IsAlive();
}
bool IllidanStormrageGrateIsSafeFromFlamesTrigger::IsActive()
{
if (botAI->IsAssistTankOfIndex(bot, 0, true) ||
botAI->IsAssistTankOfIndex(bot, 1, true))
{
return false;
}
Unit* illidan = AI_VALUE2(Unit*, "find target", "illidan stormrage");
return illidan && GetIllidanPhase(illidan) == 2;
}
bool IllidanStormrageBotStruckByDarkBarrageTrigger::IsActive()
{
if (bot->getClass() != CLASS_MAGE && bot->getClass() != CLASS_PALADIN &&
bot->getClass() != CLASS_ROGUE)
{
return false;
}
if (!AI_VALUE2(Unit*, "find target", "illidan stormrage"))
return false;
if (botAI->HasAura("ice block", bot))
{
botAI->RemoveAura("ice block");
return true;
}
else if (!botAI->IsHeal(bot) && botAI->HasAura("divine shield", bot))
{
botAI->RemoveAura("divine shield");
return true;
}
return bot->HasAura(
static_cast<uint32>(BlackTempleSpells::SPELL_DARK_BARRAGE));
}
bool IllidanStormrageBossIsPreparingToLandTrigger::IsActive()
{
if (botAI->IsMainTank(bot))
return false;
Unit* illidan = AI_VALUE2(Unit*, "find target", "illidan stormrage");
return illidan && GetIllidanPhase(illidan) == 0;
}
bool IllidanStormrageBossDealsSplashDamageTrigger::IsActive()
{
if (!botAI->IsRanged(bot))
return false;
Unit* illidan = AI_VALUE2(Unit*, "find target", "illidan stormrage");
if (!illidan || illidan->HasAura
(static_cast<uint32>(BlackTempleSpells::SPELL_CAGED)))
{
return false;
}
int phase = GetIllidanPhase(illidan);
if (phase == 4 && GetIllidanWarlockTank(bot) == bot)
return false;
return phase == 3 || phase == 4 || phase == 5;
}
bool IllidanStormrageThisExpansionHatesMeleeTrigger::IsActive()
{
if (!botAI->IsMelee(bot))
return false;
Unit* illidan = AI_VALUE2(Unit*, "find target", "illidan stormrage");
return illidan && GetIllidanPhase(illidan) == 4;
}
bool IllidanStormrageBossTransformsIntoDemonTrigger::IsActive()
{
if (bot->getClass() != CLASS_WARLOCK)
return false;
Unit* illidan = AI_VALUE2(Unit*, "find target", "illidan stormrage");
if (!illidan || GetIllidanPhase(illidan) != 4)
return false;
return GetIllidanWarlockTank(bot) == bot;
}
bool IllidanStormrageBossSpawnsAddsTrigger::IsActive()
{
if (botAI->IsHeal(bot))
return false;
Unit* illidan = AI_VALUE2(Unit*, "find target", "illidan stormrage");
if (!illidan || illidan->GetHealth() == 1)
return false;
if (botAI->IsTank(bot) && GetIllidanPhase(illidan) != 4)
return false;
return true;
}
bool IllidanStormrageMaievPlacedShadowTrapTrigger::IsActive()
{
Unit* illidan = AI_VALUE2(Unit*, "find target", "illidan stormrage");
if (!illidan || illidan->GetHealth() == 1 ||
GetIllidanPhase(illidan) != 5)
{
return false;
}
GameObject* trap = FindNearestTrap(botAI, bot);
if (!trap)
return false;
Group* group = bot->GetGroup();
if (!group)
return false;
Player* closestBot = nullptr;
float closestDist = std::numeric_limits<float>::max();
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
{
Player* member = ref->GetSource();
if (!member || !member->IsAlive() || illidan->GetVictim() == member ||
!GET_PLAYERBOT_AI(member) || botAI->IsMainTank(member))
{
continue;
}
float dist = member->GetDistance(trap);
if (dist < closestDist)
{
closestDist = dist;
closestBot = member;
}
}
return closestBot == bot;
}
bool IllidanStormrageNeedToManageDpsTimerAndRtiTrigger::IsActive()
{
if (!botAI->IsDps(bot))
return false;
Unit* illidan = AI_VALUE2(Unit*, "find target", "illidan stormrage");
if (!illidan || illidan->GetHealth() == 1)
return false;
return IsMechanicTrackerBot(
botAI, bot, BLACK_TEMPLE_MAP_ID, GetIllidanWarlockTank(bot));
}
// Destroying hazards behind phases is not gated behind CheatMask
// The strategy simply cannot work without doing this
bool IllidanStormrageNeedToClearHazardsBetweenPhasesTrigger::IsActive()
{
if (!botAI->IsDps(bot))
return false;
Unit* illidan = AI_VALUE2(Unit*, "find target", "illidan stormrage");
if (!illidan || illidan->GetHealth() == 1)
return false;
int phase = GetIllidanPhase(illidan);
if (phase != 0 && phase != 2 && phase != 4)
return false;
return IsMechanicTrackerBot(
botAI, bot, BLACK_TEMPLE_MAP_ID, GetIllidanWarlockTank(bot));
}
bool IllidanStormrageCheatTrigger::IsActive()
{
if (!botAI->HasCheat(BotCheatMask::raid) || !botAI->IsDps(bot))
return false;
Unit* illidan = AI_VALUE2(Unit*, "find target", "illidan stormrage");
if (!illidan)
return false;
int phase = GetIllidanPhase(illidan);
return phase == 2 || phase == 4;
}

View File

@ -1,518 +0,0 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_RAIDBLACKTEMPLETRIGGERS_H
#define _PLAYERBOT_RAIDBLACKTEMPLETRIGGERS_H
#include "Trigger.h"
// General
class BlackTempleBotIsNotInCombatTrigger : public Trigger
{
public:
BlackTempleBotIsNotInCombatTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "black temple bot is not in combat") {}
bool IsActive() override;
};
// High Warlord Naj'entus
class HighWarlordNajentusPullingBossTrigger : public Trigger
{
public:
HighWarlordNajentusPullingBossTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "high warlord naj'entus pulling boss") {}
bool IsActive() override;
};
class HighWarlordNajentusBossEngagedByTanksTrigger : public Trigger
{
public:
HighWarlordNajentusBossEngagedByTanksTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "high warlord naj'entus boss engaged by tanks") {}
bool IsActive() override;
};
class HighWarlordNajentusCastsNeedleSpinesTrigger : public Trigger
{
public:
HighWarlordNajentusCastsNeedleSpinesTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "high warlord naj'entus casts needle spines") {}
bool IsActive() override;
};
class HighWarlordNajentusPlayerIsImpaledTrigger : public Trigger
{
public:
HighWarlordNajentusPlayerIsImpaledTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "high warlord naj'entus player is impaled") {}
bool IsActive() override;
};
class HighWarlordNajentusBossHasTidalShieldTrigger : public Trigger
{
public:
HighWarlordNajentusBossHasTidalShieldTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "high warlord naj'entus boss has tidal shield") {}
bool IsActive() override;
};
// Supremus
class SupremusPullingBossOrChangingPhaseTrigger : public Trigger
{
public:
SupremusPullingBossOrChangingPhaseTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "supremus pulling boss or changing phase") {}
bool IsActive() override;
};
class SupremusBossEngagedByRangedTrigger : public Trigger
{
public:
SupremusBossEngagedByRangedTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "supremus boss engaged by ranged") {}
bool IsActive() override;
};
class SupremusBossIsFixatedOnBotTrigger : public Trigger
{
public:
SupremusBossIsFixatedOnBotTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "supremus boss is fixated on bot") {}
bool IsActive() override;
};
class SupremusVolcanoIsNearbyTrigger : public Trigger
{
public:
SupremusVolcanoIsNearbyTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "supremus volcano is nearby") {}
bool IsActive() override;
};
class SupremusNeedToManagePhaseTimerTrigger : public Trigger
{
public:
SupremusNeedToManagePhaseTimerTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "supremus need to manage phase timer") {}
bool IsActive() override;
};
// Shade of Akama
class ShadeOfAkamaKillingChannelersStartsPhase2Trigger : public Trigger
{
public:
ShadeOfAkamaKillingChannelersStartsPhase2Trigger(
PlayerbotAI* botAI) : Trigger(botAI, "shade of akama killing channelers starts phase 2") {}
bool IsActive() override;
};
// Teron Gorefiend
class TeronGorefiendPullingBossTrigger : public Trigger
{
public:
TeronGorefiendPullingBossTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "teron gorefiend pulling boss") {}
bool IsActive() override;
};
class TeronGorefiendBossEngagedByTanksTrigger : public Trigger
{
public:
TeronGorefiendBossEngagedByTanksTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "teron gorefiend boss engaged by tanks") {}
bool IsActive() override;
};
class TeronGorefiendBossEngagedByRangedTrigger : public Trigger
{
public:
TeronGorefiendBossEngagedByRangedTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "teron gorefiend boss engaged by ranged") {}
bool IsActive() override;
};
class TeronGorefiendBossIsCastingShadowOfDeathTrigger : public Trigger
{
public:
TeronGorefiendBossIsCastingShadowOfDeathTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "teron gorefiend boss is casting shadow of death") {}
bool IsActive() override;
};
class TeronGorefiendBotHasShadowOfDeathTrigger : public Trigger
{
public:
TeronGorefiendBotHasShadowOfDeathTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "teron gorefiend bot has shadow of death") {}
bool IsActive() override;
};
class TeronGorefiendBotTransformedIntoVengefulSpiritTrigger : public Trigger
{
public:
TeronGorefiendBotTransformedIntoVengefulSpiritTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "teron gorefiend bot transformed into vengeful spirit") {}
bool IsActive() override;
};
// Gurtogg Bloodboil
class GurtoggBloodboilPullingBossTrigger : public Trigger
{
public:
GurtoggBloodboilPullingBossTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "gurtogg bloodboil pulling boss") {}
bool IsActive() override;
};
class GurtoggBloodboilBossEngagedByTanksTrigger : public Trigger
{
public:
GurtoggBloodboilBossEngagedByTanksTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "gurtogg bloodboil boss engaged by tanks") {}
bool IsActive() override;
};
class GurtoggBloodboilBossCastsBloodboilTrigger : public Trigger
{
public:
GurtoggBloodboilBossCastsBloodboilTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "gurtogg bloodboil boss casts bloodboil") {}
bool IsActive() override;
};
class GurtoggBloodboilBotHasFelRageTrigger : public Trigger
{
public:
GurtoggBloodboilBotHasFelRageTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "gurtogg bloodboil bot has fel rage") {}
bool IsActive() override;
};
class GurtoggBloodboilNeedToManagePhaseTimerTrigger : public Trigger
{
public:
GurtoggBloodboilNeedToManagePhaseTimerTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "gurtogg bloodboil need to manage phase timer") {}
bool IsActive() override;
};
// Reliquary of Souls
class ReliquaryOfSoulsAggroResetsUponPhaseChangeTrigger : public Trigger
{
public:
ReliquaryOfSoulsAggroResetsUponPhaseChangeTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "reliquary of souls aggro resets upon phase change") {}
bool IsActive() override;
};
class ReliquaryOfSoulsEssenceOfSufferingFixatesOnClosestTargetTrigger : public Trigger
{
public:
ReliquaryOfSoulsEssenceOfSufferingFixatesOnClosestTargetTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "reliquary of souls essence of suffering fixates on closest target") {}
bool IsActive() override;
};
class ReliquaryOfSoulsEssenceOfSufferingDisablesHealingTrigger : public Trigger
{
public:
ReliquaryOfSoulsEssenceOfSufferingDisablesHealingTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "reliquary of souls essence of suffering disables healing") {}
bool IsActive() override;
};
class ReliquaryOfSoulsEssenceOfDesireHasRuneShieldTrigger : public Trigger
{
public:
ReliquaryOfSoulsEssenceOfDesireHasRuneShieldTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "reliquary of souls essence of desire has rune shield") {}
bool IsActive() override;
};
class ReliquaryOfSoulsEssenceOfDesireCastingDeadenTrigger : public Trigger
{
public:
ReliquaryOfSoulsEssenceOfDesireCastingDeadenTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "reliquary of souls essence of desire casting deaden") {}
bool IsActive() override;
};
// Mother Shahraz
class MotherShahrazPullingBossTrigger : public Trigger
{
public:
MotherShahrazPullingBossTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "mother shahraz pulling boss") {}
bool IsActive() override;
};
class MotherShahrazBossEngagedByTanksTrigger : public Trigger
{
public:
MotherShahrazBossEngagedByTanksTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "mother shahraz boss engaged by tanks") {}
bool IsActive() override;
};
class MotherShahrazTanksArePositioningBossTrigger : public Trigger
{
public:
MotherShahrazTanksArePositioningBossTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "mother shahraz tanks are positioning boss") {}
bool IsActive() override;
};
class MotherShahrazSinisterBeamKnocksBackPlayersTrigger : public Trigger
{
public:
MotherShahrazSinisterBeamKnocksBackPlayersTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "mother shahraz sinister beam knocks back players") {}
bool IsActive() override;
};
class MotherShahrazBotsAreLinkedByFatalAttractionTrigger : public Trigger
{
public:
MotherShahrazBotsAreLinkedByFatalAttractionTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "mother shahraz bots are linked by fatal attraction") {}
bool IsActive() override;
};
// Illidari Council
class IllidariCouncilPullingBossesTrigger : public Trigger
{
public:
IllidariCouncilPullingBossesTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidari council pulling bosses") {}
bool IsActive() override;
};
class IllidariCouncilGathiosEngagedByMainTankTrigger : public Trigger
{
public:
IllidariCouncilGathiosEngagedByMainTankTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidari council gathios engaged by main tank") {}
bool IsActive() override;
};
class IllidariCouncilGathiosCastingJudgementOfCommandTrigger : public Trigger
{
public:
IllidariCouncilGathiosCastingJudgementOfCommandTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidari council gathios casting judgement of command") {}
bool IsActive() override;
};
class IllidariCouncilMalandeEngagedByFirstAssistTankTrigger : public Trigger
{
public:
IllidariCouncilMalandeEngagedByFirstAssistTankTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidari council malande engaged by first assist tank") {}
bool IsActive() override;
};
class IllidariCouncilDarkshadowEngagedBySecondAssistTankTrigger : public Trigger
{
public:
IllidariCouncilDarkshadowEngagedBySecondAssistTankTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidari council darkshadow engaged by second assist tank") {}
bool IsActive() override;
};
class IllidariCouncilZerevorEngagedByMageTankTrigger : public Trigger
{
public:
IllidariCouncilZerevorEngagedByMageTankTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidari council zerevor engaged by mage tank") {}
bool IsActive() override;
};
class IllidariCouncilMageTankNeedsDedicatedHealerTrigger : public Trigger
{
public:
IllidariCouncilMageTankNeedsDedicatedHealerTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidari council mage tank needs dedicated healer") {}
bool IsActive() override;
};
class IllidariCouncilZerevorCastsDangerousAoesTrigger : public Trigger
{
public:
IllidariCouncilZerevorCastsDangerousAoesTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidari council zerevor casts dangerous aoes") {}
bool IsActive() override;
};
class IllidariCouncilPetsScrewUpThePullTrigger : public Trigger
{
public:
IllidariCouncilPetsScrewUpThePullTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidari council pets screw up the pull") {}
bool IsActive() override;
};
class IllidariCouncilNeedToManageDpsTimerTrigger : public Trigger
{
public:
IllidariCouncilNeedToManageDpsTimerTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidari council need to manage dps timer") {}
bool IsActive() override;
};
class IllidariCouncilDeterminingDpsAssignmentsTrigger : public Trigger
{
public:
IllidariCouncilDeterminingDpsAssignmentsTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidari council determining dps assignments") {}
bool IsActive() override;
};
// Illidan Stormrage <The Betrayer>
class IllidanStormrageTankNeedsAggroTrigger : public Trigger
{
public:
IllidanStormrageTankNeedsAggroTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidan stormrage tank needs aggro") {}
bool IsActive() override;
};
class IllidanStormrageBossCastsFlameCrashInFrontOfMainTankTrigger : public Trigger
{
public:
IllidanStormrageBossCastsFlameCrashInFrontOfMainTankTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidan stormrage boss casts flame crash in front of main tank") {}
bool IsActive() override;
};
class IllidanStormrageBotHasParasiticShadowfiendTrigger : public Trigger
{
public:
IllidanStormrageBotHasParasiticShadowfiendTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidan stormrage bot has parasitic shadowfiend") {}
bool IsActive() override;
};
class IllidanStormrageParasiticShadowfiendsRunWildTrigger : public Trigger
{
public:
IllidanStormrageParasiticShadowfiendsRunWildTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidan stormrage parasitic shadowfiends run wild") {}
bool IsActive() override;
};
class IllidanStormrageBossSummonedFlamesOfAzzinothTrigger : public Trigger
{
public:
IllidanStormrageBossSummonedFlamesOfAzzinothTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidan stormrage boss summoned flames of azzinoth") {}
bool IsActive() override;
};
class IllidanStormragePetsDieToFireTrigger : public Trigger
{
public:
IllidanStormragePetsDieToFireTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidan stormrage pets die to fire") {}
bool IsActive() override;
};
class IllidanStormrageGrateIsSafeFromFlamesTrigger : public Trigger
{
public:
IllidanStormrageGrateIsSafeFromFlamesTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidan stormrage grate is safe from flames") {}
bool IsActive() override;
};
class IllidanStormrageBotStruckByDarkBarrageTrigger : public Trigger
{
public:
IllidanStormrageBotStruckByDarkBarrageTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidan stormrage bot struck by dark barrage") {}
bool IsActive() override;
};
class IllidanStormrageBossIsPreparingToLandTrigger : public Trigger
{
public:
IllidanStormrageBossIsPreparingToLandTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidan stormrage boss is preparing to land") {}
bool IsActive() override;
};
class IllidanStormrageBossDealsSplashDamageTrigger : public Trigger
{
public:
IllidanStormrageBossDealsSplashDamageTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidan stormrage boss deals splash damage") {}
bool IsActive() override;
};
class IllidanStormrageThisExpansionHatesMeleeTrigger : public Trigger
{
public:
IllidanStormrageThisExpansionHatesMeleeTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidan stormrage this expansion hates melee") {}
bool IsActive() override;
};
class IllidanStormrageBossTransformsIntoDemonTrigger : public Trigger
{
public:
IllidanStormrageBossTransformsIntoDemonTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidan stormrage boss transforms into demon") {}
bool IsActive() override;
};
class IllidanStormrageBossSpawnsAddsTrigger : public Trigger
{
public:
IllidanStormrageBossSpawnsAddsTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidan stormrage boss spawns adds") {}
bool IsActive() override;
};
class IllidanStormrageMaievPlacedShadowTrapTrigger : public Trigger
{
public:
IllidanStormrageMaievPlacedShadowTrapTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidan stormrage maiev placed shadow trap") {}
bool IsActive() override;
};
class IllidanStormrageNeedToManageDpsTimerAndRtiTrigger : public Trigger
{
public:
IllidanStormrageNeedToManageDpsTimerAndRtiTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidan stormrage need to manage dps timer and rti") {}
bool IsActive() override;
};
class IllidanStormrageNeedToClearHazardsBetweenPhasesTrigger : public Trigger
{
public:
IllidanStormrageNeedToClearHazardsBetweenPhasesTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidan stormrage need to clear hazards between phases") {}
bool IsActive() override;
};
class IllidanStormrageCheatTrigger : public Trigger
{
public:
IllidanStormrageCheatTrigger(
PlayerbotAI* botAI) : Trigger(botAI, "illidan stormrage cheat") {}
bool IsActive() override;
};
#endif

View File

@ -1,468 +0,0 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#include "RaidBlackTempleHelpers.h"
#include "Playerbots.h"
#include "RaidBossHelpers.h"
namespace BlackTempleHelpers
{
// High Warlord Naj'entus
const Position NAJENTUS_TANK_POSITION = { 438.515f, 772.436f, 11.931f };
// Supremus
std::unordered_map<uint32, time_t> supremusPhaseTimer;
bool HasSupremusVolcanoNearby(PlayerbotAI* botAI, Player* bot)
{
constexpr float searchRadius = 20.0f;
std::list<Creature*> creatureList;
bot->GetCreatureListWithEntryInGrid(
creatureList, static_cast<uint32>(
BlackTempleNpcs::NPC_SUPREMUS_VOLCANO), searchRadius);
for (Creature* creature : creatureList)
{
if (creature && creature->IsAlive())
return true;
}
return false;
}
// Shade of Akama
const Position AKAMA_CHANNELER_POSITION = { 467.851f, 401.622f, 118.538f };
std::unordered_set<ObjectGuid> hasReachedAkamaChannelerPosition;
// Teron Gorefiend
const Position GOREFIEND_TANK_POSITION = { 597.653f, 402.284f, 187.090f };
const Position GOREFIEND_DIE_POSITION = { 525.709f, 377.177f, 193.203f };
// Gurtogg Bloodboil
const Position GURTOGG_TANK_POSITION = { 735.987f, 272.451f, 063.554f };
const Position GURTOGG_RANGED_POSITION = { 762.265f, 277.183f, 063.781f };
const Position GURTOGG_SOAKER_POSITION = { 769.348f, 280.116f, 063.780f };
std::unordered_map<uint32, time_t> gurtoggPhaseTimer;
std::vector<std::vector<Player*>> GetGurtoggRangedRotationGroups(Player* bot)
{
Group* group = bot->GetGroup();
std::vector<Player*> rangedMembers;
std::vector<std::vector<Player*>> groups(3);
if (!group)
return groups;
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
{
Player* member = ref->GetSource();
if (member && member->IsAlive())
{
PlayerbotAI* memberAI = GET_PLAYERBOT_AI(member);
if (memberAI && memberAI->IsRanged(member))
rangedMembers.push_back(member);
}
}
for (size_t i = 0; i < rangedMembers.size(); ++i)
{
groups[i / 5].push_back(rangedMembers[i]);
if (groups[2].size() == 5)
break;
}
return groups;
}
int GetGurtoggActiveRotationGroup(Unit* gurtogg)
{
if (!gurtogg)
return -1;
auto it = gurtoggPhaseTimer.find(gurtogg->GetMap()->GetInstanceId());
if (it == gurtoggPhaseTimer.end())
return -1;
const time_t now = std::time(nullptr);
const time_t elapsed = now - it->second;
const int groupIndex = (elapsed % 30) / 10; // 3 groups, swapping every 10 seconds
return groupIndex;
}
// Mother Shahraz
const Position SHAHRAZ_TANK_POSITION = { 960.438f, 178.989f, 192.826f };
const Position SHAHRAZ_TRANSITION_POSITION = { 951.327f, 179.550f, 192.550f };
const Position SHAHRAZ_RANGED_POSITION = { 935.267f, 175.459f, 192.821f };
std::unordered_map<ObjectGuid, TankPositionState> shahrazTankStep;
TankPositionState GetShahrazTankPositionState(PlayerbotAI* botAI, Player* bot)
{
Player* mainTank = GetGroupMainTank(botAI, bot);
if (!mainTank)
return TankPositionState::Unknown;
auto it = shahrazTankStep.find(mainTank->GetGUID());
if (it != shahrazTankStep.end())
return it->second;
return TankPositionState::Unknown;
}
// Illidari Council
const std::array<Position, 4> GATHIOS_TANK_POSITIONS = {{
{ 662.977f, 296.246f, 271.688f },
{ 636.238f, 283.719f, 271.629f },
{ 655.571f, 261.377f, 271.687f },
{ 673.789f, 274.139f, 271.689f }
}};
const Position ZEREVOR_TANK_POSITION = { 686.219f, 377.644f, 271.689f };
const std::array<Position, 2> ZEREVOR_HEALER_POSITIONS = {{
{ 661.385f, 351.219f, 271.690f },
{ 667.003f, 363.768f, 271.690f }
}};
const Position MALANDE_TANK_POSITION = { 690.590f, 299.790f, 277.443f };
std::unordered_map<uint32, time_t> councilDpsWaitTimer;
std::unordered_map<ObjectGuid, uint8> gathiosTankStep;
std::unordered_map<ObjectGuid, uint8> zerevorHealStep;
// (1) First priority is an assistant Mage (real player or bot)
// (2) If no assistant Mage, then look for any Mage bot
Player* GetZerevorMageTank(Player* bot)
{
Group* group = bot->GetGroup();
if (!group)
return nullptr;
Player* fallbackMage = nullptr;
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
{
Player* member = ref->GetSource();
if (!member || !member->IsAlive() || member->getClass() != CLASS_MAGE)
continue;
if (group->IsAssistant(member->GetGUID()))
return member;
if (!fallbackMage && GET_PLAYERBOT_AI(member))
fallbackMage = member;
}
return fallbackMage;
}
bool HasDangerousCouncilAura(Unit* unit)
{
static const std::array<uint32, 3> dangerousAuras =
{
static_cast<uint32>(BlackTempleSpells::SPELL_CONSECRATION),
static_cast<uint32>(BlackTempleSpells::SPELL_BLIZZARD),
static_cast<uint32>(BlackTempleSpells::SPELL_FLAMESTRIKE)
};
for (uint32 aura : dangerousAuras)
{
if (unit->HasAura(aura))
return true;
}
return false;
}
// Illidan Stormrage <The Betrayer>
const Position ILLIDAN_LANDING_POSITION = { 676.648f, 304.761f, 354.189f };
const Position ILLIDAN_N_GRATE_POSITION = { 682.100f, 306.000f, 353.192f };
const Position ILLIDAN_E_GRATE_POSITION = { 673.500f, 298.500f, 353.192f };
const Position ILLIDAN_W_GRATE_POSITION = { 672.400f, 312.500f, 353.192f };
const std::array<Position, 3> GRATE_POSITIONS = {{
ILLIDAN_N_GRATE_POSITION,
ILLIDAN_E_GRATE_POSITION,
ILLIDAN_W_GRATE_POSITION
}};
const Position ILLIDAN_E_GLAIVE_WAITING_POSITION = { 677.656f, 294.066f, 353.192f };
const std::array<Position, 7> E_GLAIVE_TANK_POSITIONS = {{
{ 683.000f, 295.000f, 354.000f },
{ 696.969f, 300.982f, 354.302f },
{ 691.112f, 287.461f, 354.363f },
{ 676.674f, 280.797f, 354.268f },
{ 664.414f, 284.834f, 354.271f },
{ 656.826f, 295.113f, 354.165f },
{ 665.000f, 304.000f, 354.000f }
}};
const Position ILLIDAN_W_GLAIVE_WAITING_POSITION = { 676.102f, 316.305f, 353.192f };
const std::array<Position, 7> W_GLAIVE_TANK_POSITIONS = {{
{ 697.208f, 313.475f, 354.234f },
{ 681.000f, 318.000f, 354.000f },
{ 664.000f, 307.000f, 354.000f },
{ 656.161f, 314.132f, 354.092f },
{ 665.080f, 326.905f, 354.128f },
{ 678.809f, 329.968f, 354.387f },
{ 690.889f, 324.277f, 354.204f }
}};
std::unordered_map<ObjectGuid, size_t> flameTankWaypointIndex;
std::unordered_map<ObjectGuid, ObjectGuid> illidanShadowTrapGuid;
std::unordered_map<ObjectGuid, Position> illidanShadowTrapDestination;
std::unordered_map<uint32, int> illidanLastPhase;
std::unordered_map<uint32, time_t> illidanBossDpsWaitTimer;
std::unordered_map<uint32, time_t> illidanFlameDpsWaitTimer;
std::unordered_map<uint32, ObjectGuid> eastFlameGuid;
std::unordered_map<uint32, ObjectGuid> westFlameGuid;
int GetIllidanPhase(Unit* illidan)
{
if (!illidan || illidan->GetHealth() == 1 || illidan->HasAura(
static_cast<uint32>(BlackTempleSpells::SPELL_SHADOW_PRISON)))
{
return -1;
}
// Transitioning from Phase 2 to Phase 3
float x, y, z;
illidan->GetMotionMaster()->GetDestination(x, y, z);
Position dest(x, y, z);
if ((dest.GetExactDist2d(ILLIDAN_LANDING_POSITION) < 0.2f ||
illidan->GetExactDist2d(ILLIDAN_LANDING_POSITION) < 0.2f) &&
illidan->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE))
{
return 0;
}
// Phase 2: Flying
if (illidan->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE))
return 2;
// Phase 1: Health > 65%
if (illidan->GetHealthPct() > 65.0f)
return 1;
// Phase 4: Demon Form
if (!illidan->HasAura(static_cast<uint32>(BlackTempleSpells::SPELL_CAGED)) &&
(illidan->HasAura(static_cast<uint32>(BlackTempleSpells::SPELL_DEMON_FORM)) ||
illidan->HasAura(static_cast<uint32>(BlackTempleSpells::SPELL_DEMON_TRANSFORM_1)) ||
illidan->HasAura(static_cast<uint32>(BlackTempleSpells::SPELL_DEMON_TRANSFORM_2)) ||
illidan->HasAura(static_cast<uint32>(BlackTempleSpells::SPELL_DEMON_TRANSFORM_3))))
{
return 4;
}
// Phase 3: Normal (ground, 65-30%, not demon)
if (illidan->GetHealthPct() > 30.0f)
return 3;
// Phase 5: Health <= 30%
if (illidan->GetHealthPct() <= 30.0f)
return 5;
return -1;
}
std::vector<Unit*> GetAllFlameCrashes(Player* bot)
{
std::vector<Unit*> flameCrashes;
std::list<Creature*> creatureList;
constexpr float searchRadius = 30.0f;
bot->GetCreatureListWithEntryInGrid(
creatureList, static_cast<uint32>(BlackTempleNpcs::NPC_FLAME_CRASH), searchRadius);
for (Creature* creature : creatureList)
{
if (creature && creature->IsAlive())
flameCrashes.push_back(creature);
}
return flameCrashes;
}
std::pair<Unit*, Unit*> GetFlamesOfAzzinoth(Player* bot)
{
Unit* eastFlame = nullptr;
Unit* westFlame = nullptr;
const uint32 instanceId = bot->GetMap()->GetInstanceId();
if (eastFlameGuid.find(instanceId) != eastFlameGuid.end())
{
if (Unit* unit = ObjectAccessor::GetUnit(*bot, eastFlameGuid[instanceId]))
{
if (unit->IsAlive())
eastFlame = unit;
}
}
if (westFlameGuid.find(instanceId) != westFlameGuid.end())
{
if (Unit* unit = ObjectAccessor::GetUnit(*bot, westFlameGuid[instanceId]))
{
if (unit->IsAlive())
westFlame = unit;
}
}
return { eastFlame, westFlame };
}
// (1) First priority is an assistant Warlock (real player or bot)
// (2) If no assistant Warlock, then look for any Warlock bot
Player* GetIllidanWarlockTank(Player* bot)
{
Group* group = bot->GetGroup();
if (!group)
return nullptr;
Player* fallbackWarlock = nullptr;
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
{
Player* member = ref->GetSource();
if (!member || !member->IsAlive() || member->getClass() != CLASS_WARLOCK)
continue;
if (group->IsAssistant(member->GetGUID()))
return member;
if (!fallbackWarlock && GET_PLAYERBOT_AI(member))
fallbackWarlock = member;
}
return fallbackWarlock;
}
bool HasParasiticShadowfiend(Player* member)
{
if (!member)
return false;
constexpr uint32 shadowfiendAura1 =
static_cast<uint32>(BlackTempleSpells::SPELL_PARASITIC_SHADOWFIEND_1);
constexpr uint32 shadowfiendAura2 =
static_cast<uint32>(BlackTempleSpells::SPELL_PARASITIC_SHADOWFIEND_2);
return member->HasAura(shadowfiendAura1) || member->HasAura(shadowfiendAura2);
}
// Get the first bot hunter that doesn't have Parasitic Shadowfiend
Player* GetIllidanTrapperHunter(Player* bot)
{
Group* group = bot->GetGroup();
if (!group)
return nullptr;
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
{
Player* member = ref->GetSource();
if (member && member->IsAlive() && member->getClass() == CLASS_HUNTER &&
GET_PLAYERBOT_AI(member) && !HasParasiticShadowfiend(member))
{
return member;
}
}
return nullptr;
}
Player* GetBotWithParasiticShadowfiend(Player* bot)
{
Group* group = bot->GetGroup();
if (!group)
return nullptr;
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
{
Player* member = ref->GetSource();
if (member && member->IsAlive() && GET_PLAYERBOT_AI(member) &&
HasParasiticShadowfiend(member))
{
return member;
}
}
return nullptr;
}
EyeBlastDangerArea GetEyeBlastDangerArea(Player* bot)
{
constexpr float searchRadius = 100.0f;
std::list<Creature*> creatureList;
bot->GetCreatureListWithEntryInGrid(
creatureList, static_cast<uint32>(BlackTempleNpcs::NPC_ILLIDAN_DB_TARGET), searchRadius);
Creature* eyeBlastTrigger = nullptr;
for (Creature* creature : creatureList)
{
if (creature && creature->IsAlive())
{
eyeBlastTrigger = creature;
break;
}
}
if (!eyeBlastTrigger)
return {};
Position startPos = Position(eyeBlastTrigger->GetPositionX(), eyeBlastTrigger->GetPositionY(),
eyeBlastTrigger->GetPositionZ());
float destX, destY, destZ;
eyeBlastTrigger->GetMotionMaster()->GetDestination(destX, destY, destZ);
Position endPos(destX, destY, destZ);
if (startPos.GetExactDist2d(endPos) < 0.1f)
return {};
constexpr float eyeBlastWidth = 9.0f;
return { startPos, endPos, eyeBlastWidth };
}
bool IsPositionInEyeBlastDangerArea(const Position& pos, const EyeBlastDangerArea& area)
{
const float dx = area.end.GetPositionX() - area.start.GetPositionX();
const float dy = area.end.GetPositionY() - area.start.GetPositionY();
const float length = area.start.GetExactDist2d(area.end.GetPositionX(), area.end.GetPositionY());
if (length < 0.1f)
return false;
const float projectionFactor = (
(pos.GetPositionX() - area.start.GetPositionX()) * dx + (
pos.GetPositionY() - area.start.GetPositionY()) * dy) / (length * length);
const float clampedProjectionFactor = std::clamp(projectionFactor, 0.0f, 1.0f);
const float closestX = area.start.GetPositionX() + clampedProjectionFactor * dx;
const float closestY = area.start.GetPositionY() + clampedProjectionFactor * dy;
const float distToLine = pos.GetExactDist2d(closestX, closestY);
return distToLine < area.width;
}
GameObject* FindNearestTrap(PlayerbotAI* botAI, Player* bot)
{
GuidVector const& gos =
botAI->GetAiObjectContext()->GetValue<GuidVector>("nearest game objects")->Get();
GameObject* nearestTrap = nullptr;
for (ObjectGuid const& guid : gos)
{
GameObject* go = botAI->GetGameObject(guid);
if (go && go->isSpawned() &&
go->GetEntry() == static_cast<uint32>(BlackTempleObjects::GO_SHADOW_TRAP))
{
nearestTrap = go;
break;
}
}
return nearestTrap;
}
}

View File

@ -1,216 +0,0 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU AGPL v3 license, you may redistribute it
* and/or modify it under version 3 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_RAIDBLACKTEMPLEHELPERS_H_
#define _PLAYERBOT_RAIDBLACKTEMPLEHELPERS_H_
#include <array>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
#include "Common.h"
#include "ObjectGuid.h"
#include "Position.h"
class GameObject;
class Player;
class PlayerbotAI;
class Unit;
namespace BlackTempleHelpers
{
enum class BlackTempleSpells : uint32
{
// High Warlord Naj'entus
SPELL_IMPALING_SPINE = 39837,
SPELL_TIDAL_SHIELD = 39872,
// Supremus
SPELL_SNARE_SELF = 41922,
// Teron Gorefiend
SPELL_SHADOW_OF_DEATH = 40251,
SPELL_SPIRITUAL_VENGEANCE = 40268,
SPELL_SPIRIT_LANCE = 40157,
SPELL_SPIRIT_CHAINS = 40175,
SPELL_SPIRIT_VOLLEY = 40314,
SPELL_SPIRIT_STRIKE = 40325,
// Gurtogg Bloodboil
SPELL_BOSS_FEL_RAGE = 40594,
SPELL_PLAYER_FEL_RAGE = 40604,
SPELL_BLOODBOIL = 42005,
// Reliquary of Souls
SPELL_DEADEN = 41410,
SPELL_RUNE_SHIELD = 41431,
// Mother Shahraz
SPELL_FATAL_ATTRACTION = 41001,
// Gathios the Shatterer
SPELL_BLESSING_OF_PROTECTION = 41450,
SPELL_BLESSING_OF_SPELL_WARDING = 41451,
SPELL_JUDGEMENT = 41467,
SPELL_SEAL_OF_COMMAND = 41469,
SPELL_CONSECRATION = 41541,
// Veras Darkshadow
SPELL_VANISH = 41476,
// High Nethermancer Zerevor
SPELL_DAMPEN_MAGIC = 41478,
SPELL_FLAMESTRIKE = 41481,
SPELL_BLIZZARD = 41482,
// Illidan Stormrage <The Betrayer>
SPELL_DEMON_TRANSFORM_1 = 40511,
SPELL_DEMON_TRANSFORM_2 = 40398,
SPELL_DEMON_TRANSFORM_3 = 40510,
SPELL_DEMON_FORM = 40506,
SPELL_DARK_BARRAGE = 40585,
SPELL_SHADOW_PRISON = 40647,
SPELL_CAGED = 40695,
SPELL_PARASITIC_SHADOWFIEND_1 = 41917, // cast by Illidan (primary infection)
SPELL_PARASITIC_SHADOWFIEND_2 = 41914, // cast by Shadowfiend on contact (secondary infection)
// Hunter
SPELL_FROST_TRAP = 13809,
SPELL_MISDIRECTION = 35079,
// Shaman
SPELL_EARTHBIND_TOTEM = 2484,
};
enum class BlackTempleNpcs : uint32
{
// Supremus
NPC_SUPREMUS_VOLCANO = 23085,
// Shade of Akama
NPC_ASHTONGUE_CHANNELER = 23421,
// Teron Gorefiend
NPC_SHADOWY_CONSTRUCT = 23111,
// Illidan Stormrage <The Betrayer>
NPC_FLAME_OF_AZZINOTH = 22997,
NPC_DEMON_FIRE = 23069,
NPC_ILLIDAN_DB_TARGET = 23070,
NPC_BLAZE = 23259,
NPC_FLAME_CRASH = 23336,
NPC_SHADOW_DEMON = 23375,
NPC_PARASITIC_SHADOWFIEND = 23498,
};
enum class BlackTempleItems : uint32
{
// High Warlord Naj'entus
ITEM_NAJENTUS_SPINE = 32408,
};
enum class BlackTempleObjects : uint32
{
// High Warlord Naj'entus
GO_NAJENTUS_SPINE = 185584,
// Illidan Stormrage <The Betrayer>
GO_SHADOW_TRAP = 185916,
};
enum class TankPositionState : uint8
{
MovingToTransition = 0,
MovingToFinal = 1,
Positioned = 2,
Unknown = 255,
};
constexpr uint32 BLACK_TEMPLE_MAP_ID = 564;
// High Warlord Naj'entus
extern const Position NAJENTUS_TANK_POSITION;
// Supremus
extern std::unordered_map<uint32, time_t> supremusPhaseTimer;
bool HasSupremusVolcanoNearby(PlayerbotAI* botAI, Player* bot);
// Shade of Akama
extern const Position AKAMA_CHANNELER_POSITION;
extern std::unordered_set<ObjectGuid> hasReachedAkamaChannelerPosition;
// Teron Gorefiend
extern const Position GOREFIEND_TANK_POSITION;
extern const Position GOREFIEND_DIE_POSITION;
// Gurtogg Bloodboil
extern const Position GURTOGG_TANK_POSITION;
extern const Position GURTOGG_RANGED_POSITION;
extern const Position GURTOGG_SOAKER_POSITION;
extern std::unordered_map<uint32, time_t> gurtoggPhaseTimer;
std::vector<std::vector<Player*>> GetGurtoggRangedRotationGroups(Player* bot);
int GetGurtoggActiveRotationGroup(Unit* gurtogg);
// Mother Shahraz
extern const Position SHAHRAZ_TANK_POSITION;
extern const Position SHAHRAZ_TRANSITION_POSITION;
extern const Position SHAHRAZ_RANGED_POSITION;
extern std::unordered_map<ObjectGuid, TankPositionState> shahrazTankStep;
TankPositionState GetShahrazTankPositionState(PlayerbotAI* botAI, Player* bot);
// Illidari Council
constexpr float COUNCIL_FLOOR_Z_THRESHOLD = 270.000f;
extern const std::array<Position, 4> GATHIOS_TANK_POSITIONS;
extern const Position MALANDE_TANK_POSITION;
extern const Position ZEREVOR_TANK_POSITION;
extern const std::array<Position, 2> ZEREVOR_HEALER_POSITIONS;
extern std::unordered_map<uint32, time_t> councilDpsWaitTimer;
extern std::unordered_map<ObjectGuid, uint8> gathiosTankStep;
extern std::unordered_map<ObjectGuid, uint8> zerevorHealStep;
Player* GetZerevorMageTank(Player* bot);
bool HasDangerousCouncilAura(Unit* unit);
// Illidan Stormrage <The Betrayer>
extern const Position ILLIDAN_LANDING_POSITION;
extern const Position ILLIDAN_N_GRATE_POSITION;
extern const Position ILLIDAN_E_GRATE_POSITION;
extern const Position ILLIDAN_W_GRATE_POSITION;
extern const std::array<Position, 3> GRATE_POSITIONS;
extern const Position ILLIDAN_E_GLAIVE_WAITING_POSITION;
extern const std::array<Position, 7> E_GLAIVE_TANK_POSITIONS;
extern const Position ILLIDAN_W_GLAIVE_WAITING_POSITION;
extern const std::array<Position, 7> W_GLAIVE_TANK_POSITIONS;
extern std::unordered_map<ObjectGuid, size_t> flameTankWaypointIndex;
extern std::unordered_map<ObjectGuid, ObjectGuid> illidanShadowTrapGuid;
extern std::unordered_map<ObjectGuid, Position> illidanShadowTrapDestination;
extern std::unordered_map<uint32, int> illidanLastPhase;
extern std::unordered_map<uint32, time_t> illidanBossDpsWaitTimer;
extern std::unordered_map<uint32, time_t> illidanFlameDpsWaitTimer;
extern std::unordered_map<uint32, ObjectGuid> eastFlameGuid;
extern std::unordered_map<uint32, ObjectGuid> westFlameGuid;
int GetIllidanPhase(Unit* illidan);
std::vector<Unit*> GetAllFlameCrashes(Player* bot);
std::pair<Unit*, Unit*> GetFlamesOfAzzinoth(Player* bot);
Player* GetIllidanWarlockTank(Player* bot);
bool HasParasiticShadowfiend(Player* member);
Player* GetIllidanTrapperHunter(Player* bot);
Player* GetBotWithParasiticShadowfiend(Player* bot);
struct EyeBlastDangerArea
{
Position start;
Position end;
float width;
};
EyeBlastDangerArea GetEyeBlastDangerArea(Player* bot);
bool IsPositionInEyeBlastDangerArea(const Position& pos, const EyeBlastDangerArea& area);
GameObject* FindNearestTrap(PlayerbotAI* botAI, Player* bot);
}
#endif

View File

@ -19,7 +19,7 @@ bool HighKingMaulgarMainTankAttackMaulgarAction::Execute(Event /*event*/)
MarkTargetWithSquare(bot, maulgar);
SetRtiTarget(botAI, "square", maulgar);
if (AI_VALUE(Unit*, "current target") != maulgar)
if (bot->GetVictim() != maulgar)
return Attack(maulgar);
if (maulgar->GetVictim() == bot)
@ -53,7 +53,7 @@ bool HighKingMaulgarFirstAssistTankAttackOlmAction::Execute(Event /*event*/)
MarkTargetWithCircle(bot, olm);
SetRtiTarget(botAI, "circle", olm);
if (AI_VALUE(Unit*, "current target") != olm)
if (bot->GetVictim() != olm)
return Attack(olm);
if (olm->GetVictim() == bot)
@ -88,7 +88,7 @@ bool HighKingMaulgarSecondAssistTankAttackBlindeyeAction::Execute(Event /*event*
MarkTargetWithStar(bot, blindeye);
SetRtiTarget(botAI, "star", blindeye);
if (AI_VALUE(Unit*, "current target") != blindeye)
if (bot->GetVictim() != blindeye)
return Attack(blindeye);
if (blindeye->GetVictim() == bot)
@ -128,7 +128,7 @@ bool HighKingMaulgarMageTankAttackKroshAction::Execute(Event /*event*/)
if (!bot->HasAura(SPELL_SPELL_SHIELD) && botAI->CanCastSpell("fire ward", bot))
return botAI->CastSpell("fire ward", bot);
if (AI_VALUE(Unit*, "current target") != krosh)
if (bot->GetTarget() != krosh->GetGUID())
return Attack(krosh);
if (krosh->GetVictim() == bot)
@ -175,7 +175,7 @@ bool HighKingMaulgarMoonkinTankAttackKigglerAction::Execute(Event /*event*/)
MarkTargetWithDiamond(bot, kiggler);
SetRtiTarget(botAI, "diamond", kiggler);
if (AI_VALUE(Unit*, "current target") != kiggler)
if (bot->GetTarget() != kiggler->GetGUID())
return Attack(kiggler);
Position safePos;
@ -205,7 +205,7 @@ bool HighKingMaulgarAssignDPSPriorityAction::Execute(Event /*event*/)
SetRtiTarget(botAI, "star", blindeye);
if (AI_VALUE(Unit*, "current target") != blindeye)
if (bot->GetTarget() != blindeye->GetGUID())
return Attack(blindeye);
return false;
@ -226,7 +226,7 @@ bool HighKingMaulgarAssignDPSPriorityAction::Execute(Event /*event*/)
SetRtiTarget(botAI, "circle", olm);
if (AI_VALUE(Unit*, "current target") != olm)
if (bot->GetTarget() != olm->GetGUID())
return Attack(olm);
return false;
@ -247,7 +247,7 @@ bool HighKingMaulgarAssignDPSPriorityAction::Execute(Event /*event*/)
SetRtiTarget(botAI, "triangle", krosh);
if (AI_VALUE(Unit*, "current target") != krosh)
if (bot->GetTarget() != krosh->GetGUID())
return Attack(krosh);
return false;
@ -268,7 +268,7 @@ bool HighKingMaulgarAssignDPSPriorityAction::Execute(Event /*event*/)
SetRtiTarget(botAI, "diamond", kiggler);
if (AI_VALUE(Unit*, "current target") != kiggler)
if (bot->GetTarget() != kiggler->GetGUID())
return Attack(kiggler);
return false;
@ -289,7 +289,7 @@ bool HighKingMaulgarAssignDPSPriorityAction::Execute(Event /*event*/)
SetRtiTarget(botAI, "square", maulgar);
if (AI_VALUE(Unit*, "current target") != maulgar)
if (bot->GetTarget() != maulgar->GetGUID())
return Attack(maulgar);
}
@ -499,7 +499,7 @@ bool GruulTheDragonkillerTanksPositionBossAction::Execute(Event /*event*/)
if (!gruul)
return false;
if (AI_VALUE(Unit*, "current target") != gruul)
if (bot->GetVictim() != gruul)
return Attack(gruul);
if (gruul->GetVictim() == bot)

View File

@ -15,9 +15,6 @@ using namespace GruulsLairHelpers;
float HighKingMaulgarDisableTankAssistMultiplier::GetValue(Action* action)
{
if (bot->GetVictim() == nullptr)
return 1.0f;
if (IsAnyOgreBossAlive(botAI) && dynamic_cast<TankAssistAction*>(action))
return 0.0f;
@ -49,8 +46,9 @@ float HighKingMaulgarAvoidWhirlwindMultiplier::GetValue(Action* action)
float HighKingMaulgarDisableArcaneShotOnKroshMultiplier::GetValue(Action* action)
{
Unit* krosh = AI_VALUE2(Unit*, "find target", "krosh firehand");
Unit* target = AI_VALUE(Unit*, "current target");
if (krosh && AI_VALUE(Unit*, "current target") == krosh &&
if (krosh && target && target->GetGUID() == krosh->GetGUID() &&
dynamic_cast<CastArcaneShotAction*>(action))
return 0.0f;

View File

@ -97,7 +97,7 @@ bool RageWinterchillMainTankPositionBossAction::Execute(Event /*event*/)
if (!winterchill)
return false;
if (AI_VALUE(Unit*, "current target") != winterchill)
if (bot->GetVictim() != winterchill)
return Attack(winterchill);
if (winterchill->GetVictim() == bot)
@ -265,7 +265,7 @@ bool AnetheronMainTankPositionBossAction::Execute(Event /*event*/)
MarkTargetWithSquare(bot, anetheron);
SetRtiTarget(botAI, "square", anetheron);
if (AI_VALUE(Unit*, "current target") != anetheron)
if (bot->GetVictim() != anetheron)
return Attack(anetheron);
if (anetheron->GetVictim() == bot)
@ -395,7 +395,7 @@ bool AnetheronFirstAssistTankPickUpInfernalsAction::Execute(Event /*event*/)
MarkTargetWithDiamond(bot, infernal);
SetRtiTarget(botAI, "diamond", infernal);
if (AI_VALUE(Unit*, "current target") != infernal)
if (bot->GetVictim() != infernal)
return Attack(infernal);
if ((infernoTarget && infernoTarget == bot) ||
@ -432,7 +432,7 @@ bool AnetheronAssignDpsPriorityAction::Execute(Event /*event*/)
{
SetRtiTarget(botAI, "square", anetheron);
if (AI_VALUE(Unit*, "current target") != anetheron)
if (bot->GetVictim() != anetheron)
return Attack(anetheron);
return false;
@ -455,7 +455,7 @@ bool AnetheronAssignDpsPriorityAction::Execute(Event /*event*/)
{
SetRtiTarget(botAI, "diamond", infernal);
if (AI_VALUE(Unit*, "current target") != infernal)
if (bot->GetTarget() != infernal->GetGUID())
return Attack(infernal);
}
}
@ -464,7 +464,7 @@ bool AnetheronAssignDpsPriorityAction::Execute(Event /*event*/)
{
SetRtiTarget(botAI, "square", anetheron);
if (AI_VALUE(Unit*, "current target") != anetheron)
if (bot->GetTarget() != anetheron->GetGUID())
return Attack(anetheron);
}
@ -500,7 +500,7 @@ bool KazrogalMainTankPositionBossAction::Execute(Event /*event*/)
if (!kazrogal)
return false;
if (AI_VALUE(Unit*, "current target") != kazrogal)
if (bot->GetVictim() != kazrogal)
return Attack(kazrogal);
if (kazrogal->GetVictim() == bot && bot->IsWithinMeleeRange(kazrogal))
@ -734,7 +734,7 @@ bool AzgalorMainTankPositionBossAction::Execute(Event /*event*/)
MarkTargetWithStar(bot, azgalor);
SetRtiTarget(botAI, "star", azgalor);
if (AI_VALUE(Unit*, "current target") != azgalor)
if (bot->GetVictim() != azgalor)
return Attack(azgalor);
if (azgalor->GetVictim() == bot && bot->IsWithinMeleeRange(azgalor))
@ -801,7 +801,7 @@ bool AzgalorDisperseRangedAction::Execute(Event /*event*/)
{
return FleePosition(doomguard->GetPosition(), safeDistFromDoomguard);
}
else if (!doomguard || AI_VALUE(Unit*, "current target") != doomguard)
else if (!doomguard || bot->GetTarget() != doomguard->GetGUID())
{
Unit* nearestPlayer = GetNearestPlayerInRadius(bot, safeDistFromPlayer);
if (nearestPlayer)
@ -848,7 +848,7 @@ bool AzgalorMeleeGetOutOfFireAndSwapTargetsAction::Execute(Event /*event*/)
}
}
if (AI_VALUE(Unit*, "current target") != desiredTarget)
if (bot->GetVictim() != desiredTarget || bot->GetTarget() != desiredTarget->GetGUID())
return Attack(desiredTarget);
return false;
@ -912,7 +912,7 @@ bool AzgalorFirstAssistTankPositionDoomguardAction::Execute(Event /*event*/)
MarkTargetWithCircle(bot, doomguard);
SetRtiTarget(botAI, "circle", doomguard);
if (AI_VALUE(Unit*, "current target") != doomguard)
if (bot->GetVictim() != doomguard)
return Attack(doomguard);
if (doomguard->GetVictim() == bot && bot->IsWithinMeleeRange(doomguard) &&
@ -963,7 +963,7 @@ bool AzgalorRangedDpsPrioritizeDoomguardsAction::Execute(Event /*event*/)
{
SetRtiTarget(botAI, "circle", doomguard);
if (AI_VALUE(Unit*, "current target") != doomguard)
if (bot->GetTarget() != doomguard->GetGUID())
return Attack(doomguard);
}
}
@ -971,7 +971,7 @@ bool AzgalorRangedDpsPrioritizeDoomguardsAction::Execute(Event /*event*/)
{
SetRtiTarget(botAI, "star", azgalor);
if (AI_VALUE(Unit*, "current target") != azgalor)
if (bot->GetTarget() != azgalor->GetGUID())
return Attack(azgalor);
}
@ -1007,7 +1007,7 @@ bool ArchimondeMoveBossToInitialPositionAction::Execute(Event /*event*/)
if (!archimonde)
return false;
if (AI_VALUE(Unit*, "current target") != archimonde)
if (bot->GetVictim() != archimonde)
return Attack(archimonde);
if (archimonde->GetVictim() == bot && bot->IsWithinMeleeRange(archimonde) &&

View File

@ -50,9 +50,11 @@ bool AttumenTheHuntsmanMarkTargetAction::Execute(Event /*event*/)
SetRtiTarget(botAI, "star", attumenMounted);
if (AI_VALUE(Unit*, "current target") != attumenMounted)
if (bot->GetTarget() != attumenMounted->GetGUID())
{
bot->SetTarget(attumenMounted->GetGUID());
return Attack(attumenMounted);
}
}
else if (Unit* midnight = AI_VALUE2(Unit*, "find target", "midnight"))
{
@ -63,10 +65,13 @@ bool AttumenTheHuntsmanMarkTargetAction::Execute(Event /*event*/)
{
SetRtiTarget(botAI, "star", midnight);
if (AI_VALUE(Unit*, "current target") != midnight)
if (bot->GetTarget() != midnight->GetGUID())
{
bot->SetTarget(midnight->GetGUID());
return Attack(midnight);
}
}
}
return false;
}
@ -85,7 +90,7 @@ bool AttumenTheHuntsmanSplitBossesAction::Execute(Event /*event*/)
MarkTargetWithSquare(bot, attumen);
SetRtiTarget(botAI, "square", attumen);
if (AI_VALUE(Unit*, "current target") != attumen)
if (bot->GetVictim() != attumen)
return Attack(attumen);
if (attumen->GetVictim() == bot && midnight->GetVictim() != bot)
@ -157,7 +162,7 @@ bool MoroesMainTankAttackBossAction::Execute(Event /*event*/)
MarkTargetWithCircle(bot, moroes);
SetRtiTarget(botAI, "circle", moroes);
if (AI_VALUE(Unit*, "current target") != moroes)
if (bot->GetVictim() != moroes)
return Attack(moroes);
return false;
@ -195,7 +200,7 @@ bool MaidenOfVirtueMoveBossToHealerAction::Execute(Event /*event*/)
if (!maiden)
return false;
if (AI_VALUE(Unit*, "current target") != maiden)
if (bot->GetVictim() != maiden)
return Attack(maiden);
Unit* healer = nullptr;
@ -289,7 +294,7 @@ bool BigBadWolfPositionBossAction::Execute(Event /*event*/)
if (!wolf)
return false;
if (AI_VALUE(Unit*, "current target") != wolf)
if (bot->GetVictim() != wolf)
return Attack(wolf);
if (wolf->GetVictim() == bot)
@ -420,7 +425,7 @@ bool TheCuratorPositionBossAction::Execute(Event /*event*/)
MarkTargetWithCircle(bot, curator);
SetRtiTarget(botAI, "circle", curator);
if (AI_VALUE(Unit*, "current target") != curator)
if (bot->GetVictim() != curator)
return Attack(curator);
if (curator->GetVictim() == bot)
@ -1188,7 +1193,7 @@ bool PrinceMalchezaarMainTankMovementAction::Execute(Event /*event*/)
if (!malchezaar)
return false;
if (AI_VALUE(Unit*, "current target") != malchezaar)
if (bot->GetVictim() != malchezaar)
return Attack(malchezaar);
std::vector<Unit*> infernals = GetSpawnedInfernals(botAI);
@ -1256,7 +1261,7 @@ bool NightbaneGroundPhasePositionBossAction::Execute(Event /*event*/)
MarkTargetWithSkull(bot, nightbane);
if (AI_VALUE(Unit*, "current target") != nightbane)
if (bot->GetVictim() != nightbane)
return Attack(nightbane);
const ObjectGuid botGuid = bot->GetGUID();
@ -1395,7 +1400,8 @@ bool NightbaneFlightPhaseMovementAction::Execute(Event /*event*/)
MarkTargetWithMoon(bot, nightbane);
if (AI_VALUE(Unit*, "current target") == nightbane)
Unit* botTarget = botAI->GetUnit(bot->GetTarget());
if (botTarget && botTarget == nightbane)
{
bot->AttackStop();
bot->InterruptNonMeleeSpells(true);

View File

@ -61,7 +61,7 @@ bool MagtheridonMainTankAttackFirstThreeChannelersAction::Execute(Event /*event*
SetRtiTarget(botAI, rtiName, currentTarget);
if (currentTarget && AI_VALUE(Unit*, "current target") != currentTarget)
if (currentTarget && bot->GetVictim() != currentTarget)
return Attack(currentTarget);
return false;
@ -76,7 +76,7 @@ bool MagtheridonFirstAssistTankAttackNWChannelerAction::Execute(Event /*event*/)
MarkTargetWithDiamond(bot, channelerDiamond);
SetRtiTarget(botAI, "diamond", channelerDiamond);
if (AI_VALUE(Unit*, "current target") != channelerDiamond)
if (bot->GetVictim() != channelerDiamond)
return Attack(channelerDiamond);
if (channelerDiamond->GetVictim() == bot)
@ -109,7 +109,7 @@ bool MagtheridonSecondAssistTankAttackNEChannelerAction::Execute(Event /*event*/
MarkTargetWithTriangle(bot, channelerTriangle);
SetRtiTarget(botAI, "triangle", channelerTriangle);
if (AI_VALUE(Unit*, "current target") != channelerTriangle)
if (bot->GetVictim() != channelerTriangle)
return Attack(channelerTriangle);
if (channelerTriangle->GetVictim() == bot)
@ -219,7 +219,7 @@ bool MagtheridonAssignDPSPriorityAction::Execute(Event /*event*/)
{
SetRtiTarget(botAI, "square", channelerSquare);
if (AI_VALUE(Unit*, "current target") != channelerSquare)
if (bot->GetTarget() != channelerSquare->GetGUID())
return Attack(channelerSquare);
return false;
@ -230,7 +230,7 @@ bool MagtheridonAssignDPSPriorityAction::Execute(Event /*event*/)
{
SetRtiTarget(botAI, "star", channelerStar);
if (AI_VALUE(Unit*, "current target") != channelerStar)
if (bot->GetTarget() != channelerStar->GetGUID())
return Attack(channelerStar);
return false;
@ -241,7 +241,7 @@ bool MagtheridonAssignDPSPriorityAction::Execute(Event /*event*/)
{
SetRtiTarget(botAI, "circle", channelerCircle);
if (AI_VALUE(Unit*, "current target") != channelerCircle)
if (bot->GetTarget() != channelerCircle->GetGUID())
return Attack(channelerCircle);
return false;
@ -252,7 +252,7 @@ bool MagtheridonAssignDPSPriorityAction::Execute(Event /*event*/)
{
SetRtiTarget(botAI, "diamond", channelerDiamond);
if (AI_VALUE(Unit*, "current target") != channelerDiamond)
if (bot->GetTarget() != channelerDiamond->GetGUID())
return Attack(channelerDiamond);
return false;
@ -263,7 +263,7 @@ bool MagtheridonAssignDPSPriorityAction::Execute(Event /*event*/)
{
SetRtiTarget(botAI, "triangle", channelerTriangle);
if (AI_VALUE(Unit*, "current target") != channelerTriangle)
if (bot->GetTarget() != channelerTriangle->GetGUID())
return Attack(channelerTriangle);
return false;
@ -276,7 +276,7 @@ bool MagtheridonAssignDPSPriorityAction::Execute(Event /*event*/)
{
SetRtiTarget(botAI, "cross", magtheridon);
if (AI_VALUE(Unit*, "current target") != magtheridon)
if (bot->GetTarget() != magtheridon->GetGUID())
return Attack(magtheridon);
}
@ -347,7 +347,7 @@ bool MagtheridonMainTankPositionBossAction::Execute(Event /*event*/)
MarkTargetWithCross(bot, magtheridon);
SetRtiTarget(botAI, "cross", magtheridon);
if (AI_VALUE(Unit*, "current target") != magtheridon)
if (bot->GetVictim() != magtheridon)
return Attack(magtheridon);
if (magtheridon->GetVictim() == bot)

View File

@ -12,7 +12,6 @@
#include "RaidSSCStrategy.h"
#include "RaidTempestKeepStrategy.h"
#include "RaidHyjalSummitStrategy.h"
#include "RaidBlackTempleStrategy.h"
#include "RaidZulAmanStrategy.h"
#include "RaidOsStrategy.h"
#include "RaidEoEStrategy.h"
@ -36,7 +35,6 @@ public:
creators["ssc"] = &RaidStrategyContext::ssc;
creators["tempestkeep"] = &RaidStrategyContext::tempestkeep;
creators["hyjal"] = &RaidStrategyContext::hyjal;
creators["blacktemple"] = &RaidStrategyContext::blacktemple;
creators["zulaman"] = &RaidStrategyContext::zulaman;
creators["wotlk-os"] = &RaidStrategyContext::wotlk_os;
creators["wotlk-eoe"] = &RaidStrategyContext::wotlk_eoe;
@ -57,7 +55,6 @@ private:
static Strategy* ssc(PlayerbotAI* botAI) { return new RaidSSCStrategy(botAI); }
static Strategy* tempestkeep(PlayerbotAI* botAI) { return new RaidTempestKeepStrategy(botAI); }
static Strategy* hyjal(PlayerbotAI* botAI) { return new RaidHyjalSummitStrategy(botAI); }
static Strategy* blacktemple(PlayerbotAI* botAI) { return new RaidBlackTempleStrategy(botAI); }
static Strategy* zulaman(PlayerbotAI* botAI) { return new RaidZulAmanStrategy(botAI); }
static Strategy* wotlk_os(PlayerbotAI* botAI) { return new RaidOsStrategy(botAI); }
static Strategy* wotlk_eoe(PlayerbotAI* botAI) { return new RaidEoEStrategy(botAI); }

View File

@ -153,7 +153,7 @@ bool HydrossTheUnstablePositionFrostTankAction::Execute(Event /*event*/)
MarkTargetWithSquare(bot, hydross);
SetRtiTarget(botAI, "square", hydross);
if (AI_VALUE(Unit*, "current target") != hydross)
if (bot->GetTarget() != hydross->GetGUID())
return Attack(hydross);
if (hydross->GetVictim() == bot && bot->IsWithinMeleeRange(hydross))
@ -233,7 +233,7 @@ bool HydrossTheUnstablePositionNatureTankAction::Execute(Event /*event*/)
MarkTargetWithTriangle(bot, hydross);
SetRtiTarget(botAI, "triangle", hydross);
if (AI_VALUE(Unit*, "current target") != hydross)
if (bot->GetTarget() != hydross->GetGUID())
return Attack(hydross);
if (hydross->GetVictim() == bot && bot->IsWithinMeleeRange(hydross))
@ -308,7 +308,7 @@ bool HydrossTheUnstablePrioritizeElementalAddsAction::Execute(Event /*event*/)
SetRtiTarget(botAI, "skull", waterElemental);
if (AI_VALUE(Unit*, "current target") != waterElemental)
if (bot->GetTarget() != waterElemental->GetGUID())
return Attack(waterElemental);
}
else if (Unit* natureElemental = GetFirstAliveUnitByEntry(botAI, NPC_TAINTED_SPAWN_OF_HYDROSS))
@ -318,7 +318,7 @@ bool HydrossTheUnstablePrioritizeElementalAddsAction::Execute(Event /*event*/)
SetRtiTarget(botAI, "skull", natureElemental);
if (AI_VALUE(Unit*, "current target") != natureElemental)
if (bot->GetTarget() != natureElemental->GetGUID())
return Attack(natureElemental);
}
@ -518,7 +518,7 @@ bool TheLurkerBelowPositionMainTankAction::Execute(Event /*event*/)
if (!lurker)
return false;
if (AI_VALUE(Unit*, "current target") != lurker)
if (bot->GetTarget() != lurker->GetGUID())
return Attack(lurker);
const Position& position = LURKER_MAIN_TANK_POSITION;
@ -639,7 +639,7 @@ bool TheLurkerBelowTanksPickUpAddsAction::Execute(Event /*event*/)
MarkTargetWithIcon(bot, guardian, rtiIndices[i]);
SetRtiTarget(botAI, rtiNames[i], guardian);
if (AI_VALUE(Unit*, "current target") != guardian)
if (bot->GetVictim() != guardian)
return Attack(guardian);
}
}
@ -841,7 +841,7 @@ bool LeotherasTheBlindDestroyInnerDemonAction::Execute(Event /*event*/)
// Roles without a strategy need to affirmatively attack their Inner Demons
// Because DPS assist is disabled via multipliers
if (AI_VALUE(Unit*, "current target") != innerDemon)
if (bot->GetTarget() != innerDemon->GetGUID())
return Attack(innerDemon);
}
@ -978,7 +978,7 @@ bool LeotherasTheBlindFinalPhaseAssignDpsPriorityAction::Execute(Event /*event*/
MarkTargetWithStar(bot, leotherasHuman);
SetRtiTarget(botAI, "star", leotherasHuman);
if (AI_VALUE(Unit*, "current target") != leotherasHuman)
if (bot->GetTarget() != leotherasHuman->GetGUID())
return Attack(leotherasHuman);
Unit* leotherasDemon = GetPhase3LeotherasDemon(bot);
@ -1092,7 +1092,7 @@ bool FathomLordKarathressMainTankPositionBossAction::Execute(Event /*event*/)
MarkTargetWithTriangle(bot, karathress);
SetRtiTarget(botAI, "triangle", karathress);
if (AI_VALUE(Unit*, "current target") != karathress)
if (bot->GetTarget() != karathress->GetGUID())
return Attack(karathress);
if (karathress->GetVictim() == bot && bot->IsWithinMeleeRange(karathress))
@ -1128,7 +1128,7 @@ bool FathomLordKarathressFirstAssistTankPositionCaribdisAction::Execute(Event /*
MarkTargetWithDiamond(bot, caribdis);
SetRtiTarget(botAI, "diamond", caribdis);
if (AI_VALUE(Unit*, "current target") != caribdis)
if (bot->GetTarget() != caribdis->GetGUID())
return Attack(caribdis);
if (caribdis->GetVictim() == bot)
@ -1163,7 +1163,7 @@ bool FathomLordKarathressSecondAssistTankPositionSharkkisAction::Execute(Event /
MarkTargetWithStar(bot, sharkkis);
SetRtiTarget(botAI, "star", sharkkis);
if (AI_VALUE(Unit*, "current target") != sharkkis)
if (bot->GetTarget() != sharkkis->GetGUID())
return Attack(sharkkis);
if (sharkkis->GetVictim() == bot && bot->IsWithinMeleeRange(sharkkis))
@ -1198,7 +1198,7 @@ bool FathomLordKarathressThirdAssistTankPositionTidalvessAction::Execute(Event /
MarkTargetWithCircle(bot, tidalvess);
SetRtiTarget(botAI, "circle", tidalvess);
if (AI_VALUE(Unit*, "current target") != tidalvess)
if (bot->GetTarget() != tidalvess->GetGUID())
return Attack(tidalvess);
if (tidalvess->GetVictim() == bot && bot->IsWithinMeleeRange(tidalvess))
@ -1322,7 +1322,7 @@ bool FathomLordKarathressAssignDpsPriorityAction::Execute(Event /*event*/)
MarkTargetWithSkull(bot, totem);
SetRtiTarget(botAI, "skull", totem);
if (AI_VALUE(Unit*, "current target") != totem)
if (bot->GetTarget() != totem->GetGUID())
return Attack(totem);
// Direct movement order due to path between Sharkkis and totem sometimes being screwy
@ -1343,7 +1343,7 @@ bool FathomLordKarathressAssignDpsPriorityAction::Execute(Event /*event*/)
MarkTargetWithCircle(bot, tidalvess);
SetRtiTarget(botAI, "circle", tidalvess);
if (AI_VALUE(Unit*, "current target") != tidalvess)
if (bot->GetTarget() != tidalvess->GetGUID())
return Attack(tidalvess);
return false;
@ -1363,7 +1363,7 @@ bool FathomLordKarathressAssignDpsPriorityAction::Execute(Event /*event*/)
position.GetPositionZ(), 8.0f, MovementPriority::MOVEMENT_COMBAT);
}
if (AI_VALUE(Unit*, "current target") != caribdis)
if (bot->GetTarget() != caribdis->GetGUID())
return Attack(caribdis);
return false;
@ -1376,7 +1376,7 @@ bool FathomLordKarathressAssignDpsPriorityAction::Execute(Event /*event*/)
MarkTargetWithStar(bot, sharkkis);
SetRtiTarget(botAI, "star", sharkkis);
if (AI_VALUE(Unit*, "current target") != sharkkis)
if (bot->GetTarget() != sharkkis->GetGUID())
return Attack(sharkkis);
return false;
@ -1389,7 +1389,7 @@ bool FathomLordKarathressAssignDpsPriorityAction::Execute(Event /*event*/)
MarkTargetWithCross(bot, fathomSporebat);
SetRtiTarget(botAI, "cross", fathomSporebat);
if (AI_VALUE(Unit*, "current target") != fathomSporebat)
if (bot->GetTarget() != fathomSporebat->GetGUID())
return Attack(fathomSporebat);
return false;
@ -1401,7 +1401,7 @@ bool FathomLordKarathressAssignDpsPriorityAction::Execute(Event /*event*/)
MarkTargetWithSquare(bot, fathomLurker);
SetRtiTarget(botAI, "square", fathomLurker);
if (AI_VALUE(Unit*, "current target") != fathomLurker)
if (bot->GetTarget() != fathomLurker->GetGUID())
return Attack(fathomLurker);
return false;
@ -1414,7 +1414,7 @@ bool FathomLordKarathressAssignDpsPriorityAction::Execute(Event /*event*/)
MarkTargetWithTriangle(bot, karathress);
SetRtiTarget(botAI, "triangle", karathress);
if (AI_VALUE(Unit*, "current target") != karathress)
if (bot->GetTarget() != karathress->GetGUID())
return Attack(karathress);
}
@ -1460,7 +1460,7 @@ bool MorogrimTidewalkerMoveBossToTankPositionAction::Execute(Event /*event*/)
if (!tidewalker)
return false;
if (AI_VALUE(Unit*, "current target") != tidewalker)
if (bot->GetTarget() != tidewalker->GetGUID())
return Attack(tidewalker);
if (tidewalker->GetVictim() == bot && bot->IsWithinMeleeRange(tidewalker))
@ -1610,7 +1610,7 @@ bool LadyVashjMainTankPositionBossAction::Execute(Event /*event*/)
if (!vashj)
return false;
if (AI_VALUE(Unit*, "current target") != vashj)
if (bot->GetTarget() != vashj->GetGUID())
return Attack(vashj);
if (vashj->GetVictim() == bot && bot->IsWithinMeleeRange(vashj))
@ -1929,8 +1929,7 @@ bool LadyVashjAssignPhase2AndPhase3DpsPriorityAction::Execute(Event /*event*/)
currentTarget = nullptr;
}
if (target && currentTarget != target &&
AI_VALUE(Unit*, "current target") != target)
if (target && currentTarget != target && bot->GetTarget() != target->GetGUID())
return Attack(target);
// If bots have wandered too far from the center, move them back
@ -1985,8 +1984,7 @@ bool LadyVashjTankAttackAndMoveAwayStriderAction::Execute(Event /*event*/)
if (!bot->HasAura(SPELL_FEAR_WARD))
bot->AddAura(SPELL_FEAR_WARD, bot);
if (botAI->IsAssistTankOfIndex(bot, 0, true) &&
AI_VALUE(Unit*, "current target") != strider)
if (botAI->IsAssistTankOfIndex(bot, 0, true) && bot->GetTarget() != strider->GetGUID())
return Attack(strider);
float currentDistance = bot->GetExactDist2d(vashj);
@ -2042,7 +2040,7 @@ bool LadyVashjTeleportToTaintedElementalAction::Execute(Event /*event*/)
tainted->GetPositionZ(), tainted->GetOrientation());
}
if (AI_VALUE(Unit*, "current target") != tainted)
if (bot->GetTarget() != tainted->GetGUID())
{
MarkTargetWithStar(bot, tainted);
SetRtiTarget(botAI, "star", tainted);

View File

@ -752,7 +752,7 @@ float LadyVashjDisableAutomaticTargetingAndMovementModifier::GetValue(Action *ac
return 0.0f;
Unit* enchanted = AI_VALUE2(Unit*, "find target", "enchanted elemental");
if (enchanted && AI_VALUE(Unit*, "current target") == enchanted &&
if (enchanted && bot->GetVictim() == enchanted &&
dynamic_cast<CastDebuffSpellOnAttackerAction*>(action))
return 0.0f;
}
@ -772,7 +772,7 @@ float LadyVashjDisableAutomaticTargetingAndMovementModifier::GetValue(Action *ac
dynamic_cast<FleeAction*>(action))
return 0.0f;
if (enchanted && AI_VALUE(Unit*, "current target") == enchanted &&
if (enchanted && bot->GetVictim() == enchanted &&
dynamic_cast<CastDebuffSpellOnAttackerAction*>(action))
return 0.0f;
}

View File

@ -209,24 +209,35 @@ namespace SerpentShrineCavernHelpers
{
Unit* vashj =
botAI->GetAiObjectContext()->GetValue<Unit*>("find target", "lady vashj")->Get();
if (!vashj)
return false;
return vashj && vashj->GetHealthPct() > 70.0f;
Creature* vashjCreature = vashj->ToCreature();
return vashjCreature && vashjCreature->GetHealthPct() > 70.0f &&
vashjCreature->GetReactState() != REACT_PASSIVE;
}
bool IsLadyVashjInPhase2(PlayerbotAI* botAI)
{
Unit* vashj =
botAI->GetAiObjectContext()->GetValue<Unit*>("find target", "lady vashj")->Get();
if (!vashj)
return false;
return vashj && vashj->GetHealthPct() <= 70.0f && vashj->HasAura(SPELL_MAGIC_BARRIER);
Creature* vashjCreature = vashj->ToCreature();
return vashjCreature && vashjCreature->GetReactState() == REACT_PASSIVE;
}
bool IsLadyVashjInPhase3(PlayerbotAI* botAI)
{
Unit* vashj =
botAI->GetAiObjectContext()->GetValue<Unit*>("find target", "lady vashj")->Get();
if (!vashj)
return false;
return vashj && vashj->GetHealthPct() <= 70.0f && !vashj->HasAura(SPELL_MAGIC_BARRIER);
Creature* vashjCreature = vashj->ToCreature();
return vashjCreature && vashjCreature->GetHealthPct() <= 50.0f &&
vashjCreature->GetReactState() != REACT_PASSIVE;
}
bool IsValidLadyVashjCombatNpc(Unit* unit, PlayerbotAI* botAI)

View File

@ -48,7 +48,6 @@ namespace SerpentShrineCavernHelpers
// Lady Vashj <Coilfang Matron>
SPELL_FEAR_WARD = 6346,
SPELL_MAGIC_BARRIER = 38112,
SPELL_POISON_BOLT = 38253,
SPELL_STATIC_CHARGE = 38280,
SPELL_ENTANGLE = 38316,

View File

@ -93,7 +93,7 @@ bool AlarBossTanksMoveBetweenPlatformsAction::PositionMainTank(
MovementPriority::MOVEMENT_COMBAT, true, false);
}
else if ((locationIndex == PLATFORM_0_IDX || locationIndex == PLATFORM_2_IDX) &&
AI_VALUE(Unit*, "current target") != alar)
bot->GetTarget() != alar->GetGUID())
return Attack(alar);
}
@ -116,7 +116,7 @@ bool AlarBossTanksMoveBetweenPlatformsAction::PositionAssistTank(
MovementPriority::MOVEMENT_COMBAT, true, false);
}
else if ((locationIndex == PLATFORM_1_IDX || locationIndex == PLATFORM_3_IDX) &&
AI_VALUE(Unit*, "current target") != alar)
bot->GetTarget() != alar->GetGUID())
return Attack(alar);
}
@ -152,7 +152,7 @@ bool AlarMeleeDpsMoveBetweenPlatformsAction::Execute(Event /*event*/)
MovementPriority::MOVEMENT_COMBAT, true, false);
}
if (AI_VALUE(Unit*, "current target") != alar)
if (bot->GetTarget() != alar->GetGUID())
return Attack(alar);
}
@ -227,7 +227,7 @@ bool AlarAssistTanksPickUpEmbersAction::HandlePhase1Embers(Unit* alar)
MarkTargetWithSquare(bot, ember);
SetRtiTarget(botAI, "square", ember);
if (AI_VALUE(Unit*, "current target") != ember)
if (bot->GetTarget() != ember->GetGUID())
return Attack(ember);
if (ember->GetVictim() == bot)
@ -286,7 +286,7 @@ bool AlarAssistTanksPickUpEmbersAction::HandlePhase2Embers()
if (firstEmber->GetVictim() != bot)
{
if (AI_VALUE(Unit*, "current target") != firstEmber)
if (bot->GetTarget() != firstEmber->GetGUID())
return Attack(firstEmber);
return botAI->DoSpecificAction("taunt spell", Event(), true);
@ -305,7 +305,7 @@ bool AlarAssistTanksPickUpEmbersAction::HandlePhase2Embers()
if (secondEmber->GetVictim() != bot)
{
if (AI_VALUE(Unit*, "current target") != secondEmber)
if (bot->GetTarget() != secondEmber->GetGUID())
return Attack(secondEmber);
return botAI->DoSpecificAction("taunt spell", Event(), true);
@ -336,7 +336,7 @@ bool AlarRangedDpsPrioritizeEmbersAction::Execute(Event /*event*/)
}
SetRtiTarget(botAI, "square", firstEmber);
if (AI_VALUE(Unit*, "current target") != firstEmber)
if (bot->GetTarget() != firstEmber->GetGUID())
return Attack(firstEmber);
}
else if (secondEmber)
@ -349,13 +349,13 @@ bool AlarRangedDpsPrioritizeEmbersAction::Execute(Event /*event*/)
}
SetRtiTarget(botAI, "circle", secondEmber);
if (AI_VALUE(Unit*, "current target") != secondEmber)
if (bot->GetTarget() != secondEmber->GetGUID())
return Attack(secondEmber);
}
else if (Unit* alar = AI_VALUE2(Unit*, "find target", "al'ar"))
{
SetRtiTarget(botAI, "star", alar);
if (AI_VALUE(Unit*, "current target") != alar)
if (bot->GetTarget() != alar->GetGUID())
return Attack(alar);
}
@ -469,7 +469,7 @@ bool AlarSwapTanksOnBossAction::Execute(Event /*event*/)
if (alar->GetHealth() == alar->GetMaxHealth())
{
SetRtiTarget(botAI, "star", alar);
if (AI_VALUE(Unit*, "current target") != alar)
if (bot->GetTarget() != alar->GetGUID())
return Attack(alar);
}
@ -477,7 +477,7 @@ bool AlarSwapTanksOnBossAction::Execute(Event /*event*/)
if (secondEmberTank && secondEmberTank != bot)
{
SetRtiTarget(botAI, "star", alar);
if (AI_VALUE(Unit*, "current target") != alar)
if (bot->GetTarget() != alar->GetGUID())
return Attack(alar);
else if (alar->GetVictim() != bot)
return botAI->DoSpecificAction("taunt spell", Event(), true);
@ -555,7 +555,7 @@ bool AlarReturnToRoomCenterAction::Execute(Event /*event*/)
{
constexpr float distFromCenter = 45.0f;
const Position& center = ALAR_ROOM_CENTER;
if (AI_VALUE(Unit*, "current target") == nullptr &&
if (bot->GetVictim() == nullptr &&
bot->GetExactDist2d(center.GetPositionX(), center.GetPositionY()) > distFromCenter)
{
return MoveInside(TEMPEST_KEEP_MAP_ID, center.GetPositionX(), center.GetPositionY(),
@ -887,7 +887,7 @@ bool HighAstromancerSolarianTargetSolariumPriestsAction::Execute(Event /*event*/
SetRtiTarget(botAI, "star", targetPriest);
}
if (AI_VALUE(Unit*, "current target") != targetPriest)
if (bot->GetTarget() != targetPriest->GetGUID())
return Attack(targetPriest);
return false;
@ -1047,7 +1047,7 @@ bool KaelthasSunstriderMainTankPositionSanguinarAction::Execute(Event /*event*/)
MarkTargetWithStar(bot, sanguinar);
SetRtiTarget(botAI, "star", sanguinar);
if (AI_VALUE(Unit*, "current target") != sanguinar)
if (bot->GetTarget() != sanguinar->GetGUID())
return Attack(sanguinar);
if (sanguinar->GetVictim() == bot && bot->IsWithinMeleeRange(sanguinar))
@ -1090,7 +1090,7 @@ bool KaelthasSunstriderWarlockTankPositionCapernianAction::Execute(Event /*event
MarkTargetWithCircle(bot, capernian);
SetRtiTarget(botAI, "circle", capernian);
if (AI_VALUE(Unit*, "current target") != capernian &&
if (bot->GetTarget() != capernian->GetGUID() &&
botAI->CanCastSpell("searing pain", capernian) &&
botAI->CastSpell("searing pain", capernian))
return true;
@ -1251,7 +1251,7 @@ bool KaelthasSunstriderFirstAssistTankPositionTelonicusAction::Execute(Event /*e
MarkTargetWithTriangle(bot, telonicus);
SetRtiTarget(botAI, "triangle", telonicus);
if (AI_VALUE(Unit*, "current target") != telonicus)
if (bot->GetTarget() != telonicus->GetGUID())
return Attack(telonicus);
if (telonicus->GetVictim() == bot && bot->IsWithinMeleeRange(telonicus))
@ -1331,7 +1331,7 @@ bool KaelthasSunstriderAssignAdvisorDpsPriorityAction::Execute(Event /*event*/)
MarkTargetWithSquare(bot, thaladred);
SetRtiTarget(botAI, "square", thaladred);
if (AI_VALUE(Unit*, "current target") != thaladred)
if (bot->GetTarget() != thaladred->GetGUID())
return Attack(thaladred);
return false;
@ -1346,7 +1346,7 @@ bool KaelthasSunstriderAssignAdvisorDpsPriorityAction::Execute(Event /*event*/)
{
SetRtiTarget(botAI, "circle", capernian);
if (AI_VALUE(Unit*, "current target") != capernian)
if (bot->GetTarget() != capernian->GetGUID())
return Attack(capernian);
return false;
@ -1360,7 +1360,7 @@ bool KaelthasSunstriderAssignAdvisorDpsPriorityAction::Execute(Event /*event*/)
{
SetRtiTarget(botAI, "star", sanguinar);
if (AI_VALUE(Unit*, "current target") != sanguinar)
if (bot->GetTarget() != sanguinar->GetGUID())
return Attack(sanguinar);
return false;
@ -1373,7 +1373,7 @@ bool KaelthasSunstriderAssignAdvisorDpsPriorityAction::Execute(Event /*event*/)
!telonicus->HasAura(SPELL_PERMANENT_FEIGN_DEATH))
{
SetRtiTarget(botAI, "triangle", telonicus);
if (AI_VALUE(Unit*, "current target") != telonicus)
if (bot->GetTarget() != telonicus->GetGUID())
return Attack(telonicus);
// Melee DPS need to stay at max-ish melee range behind Telonicus to avoid bombs
@ -1461,7 +1461,7 @@ bool KaelthasSunstriderAssignLegendaryWeaponDpsPriorityAction::Execute(Event /*e
MarkTargetWithSkull(bot, staff);
SetRtiTarget(botAI, "skull", staff);
if (AI_VALUE(Unit*, "current target") != staff)
if (bot->GetTarget() != staff->GetGUID())
return Attack(staff);
}
// Priority 2: Cosmic Infuser (Skull)
@ -1470,7 +1470,7 @@ bool KaelthasSunstriderAssignLegendaryWeaponDpsPriorityAction::Execute(Event /*e
MarkTargetWithSkull(bot, mace);
SetRtiTarget(botAI, "skull", mace);
if (AI_VALUE(Unit*, "current target") != mace)
if (bot->GetTarget() != mace->GetGUID())
return Attack(mace);
}
// Priority 3: Warp Slicer (Skull)
@ -1479,7 +1479,7 @@ bool KaelthasSunstriderAssignLegendaryWeaponDpsPriorityAction::Execute(Event /*e
MarkTargetWithSkull(bot, sword);
SetRtiTarget(botAI, "skull", sword);
if (AI_VALUE(Unit*, "current target") != sword)
if (bot->GetTarget() != sword->GetGUID())
return Attack(sword);
}
// Priority 4: Infinity Blades (Skull)
@ -1488,7 +1488,7 @@ bool KaelthasSunstriderAssignLegendaryWeaponDpsPriorityAction::Execute(Event /*e
MarkTargetWithSkull(bot, dagger);
SetRtiTarget(botAI, "skull", dagger);
if (AI_VALUE(Unit*, "current target") != dagger)
if (bot->GetTarget() != dagger->GetGUID())
return Attack(dagger);
}
// Priority 5: Devastation - ranged only (Diamond--marked in other method by main tank)
@ -1496,7 +1496,7 @@ bool KaelthasSunstriderAssignLegendaryWeaponDpsPriorityAction::Execute(Event /*e
{
SetRtiTarget(botAI, "diamond", axe);
if (AI_VALUE(Unit*, "current target") != axe)
if (bot->GetTarget() != axe->GetGUID())
return Attack(axe);
}
// Priority 6: Netherstrand Longbow (Skull)
@ -1505,7 +1505,7 @@ bool KaelthasSunstriderAssignLegendaryWeaponDpsPriorityAction::Execute(Event /*e
MarkTargetWithSkull(bot, longbow);
SetRtiTarget(botAI, "skull", longbow);
if (AI_VALUE(Unit*, "current target") != longbow)
if (bot->GetTarget() != longbow->GetGUID())
return Attack(longbow);
}
// Priority 7: Phaseshift Bulwark (Skull)
@ -1514,7 +1514,7 @@ bool KaelthasSunstriderAssignLegendaryWeaponDpsPriorityAction::Execute(Event /*e
MarkTargetWithSkull(bot, shield);
SetRtiTarget(botAI, "skull", shield);
if (AI_VALUE(Unit*, "current target") != shield)
if (bot->GetTarget() != shield->GetGUID())
return Attack(shield);
}
}
@ -1531,7 +1531,7 @@ bool KaelthasSunstriderMoveDevastationAwayAction::Execute(Event /*event*/)
MarkTargetWithDiamond(bot, axe);
SetRtiTarget(botAI, "diamond", axe);
if (AI_VALUE(Unit*, "current target") != axe)
if (bot->GetTarget() != axe->GetGUID())
return Attack(axe);
constexpr float safeDistance = 13.0f;
@ -1764,7 +1764,7 @@ bool KaelthasSunstriderMainTankPositionBossAction::Execute(Event /*event*/)
MarkTargetWithStar(bot, kaelthas);
SetRtiTarget(botAI, "star", kaelthas);
if (AI_VALUE(Unit*, "current target") != kaelthas)
if (bot->GetTarget() != kaelthas->GetGUID())
return Attack(kaelthas);
if (kaelthas->GetVictim() == bot && bot->IsWithinMeleeRange(kaelthas))
@ -1862,7 +1862,7 @@ bool KaelthasSunstriderHandlePhoenixesAndEggsAction::AssistTanksPickUpPhoenixes(
if (!targetPhoenix)
return false;
if (AI_VALUE(Unit*, "current target") != targetPhoenix)
if (bot->GetTarget() != targetPhoenix->GetGUID())
return Attack(targetPhoenix);
constexpr float safeDistance = 12.0f;
@ -1886,7 +1886,7 @@ bool KaelthasSunstriderHandlePhoenixesAndEggsAction::NonTanksDestroyEggsAndAvoid
MarkTargetWithDiamond(bot, phoenixEgg);
SetRtiTarget(botAI, "diamond", phoenixEgg);
if (AI_VALUE(Unit*, "current target") != phoenixEgg)
if (bot->GetTarget() != phoenixEgg->GetGUID())
return Attack(phoenixEgg);
}
}
@ -1991,7 +1991,7 @@ bool KaelthasSunstriderBreakThroughShockBarrierAction::Execute(Event /*event*/)
return botAI->CastSpell(spell, kaelthas);
}
}
else if (AI_VALUE(Unit*, "current target") != kaelthas)
else if (bot->GetTarget() != kaelthas->GetGUID())
{
SetRtiTarget(botAI, "star", kaelthas);
return Attack(kaelthas);

View File

@ -100,7 +100,7 @@ float AlarPhase2NoTankingIfArmorMeltedMultiplier::GetValue(Action* action)
return 1.0f;
Unit* alar = AI_VALUE2(Unit*, "find target", "al'ar");
if (!alar || AI_VALUE(Unit*, "current target") != alar)
if (!alar || bot->GetTarget() != alar->GetGUID())
return 1.0f;
if (dynamic_cast<CastTauntAction*>(action) ||

View File

@ -56,7 +56,7 @@ bool AkilzonTanksPositionBossAction::Execute(Event /*event*/)
if (!akilzon)
return false;
if (AI_VALUE(Unit*, "current target") != akilzon)
if (bot->GetVictim() != akilzon)
return Attack(akilzon);
if (akilzon->GetVictim() == bot)
@ -168,7 +168,7 @@ bool NalorakkTanksPositionBossAction::MainTankPositionTrollForm(Unit* nalorakk)
{
if (!nalorakk->HasAura(static_cast<uint32>(ZulAmanSpells::SPELL_BEARFORM)))
{
if (AI_VALUE(Unit*, "current target") != nalorakk)
if (bot->GetVictim() != nalorakk)
return Attack(nalorakk);
if (nalorakk->GetVictim() != bot)
@ -198,7 +198,7 @@ bool NalorakkTanksPositionBossAction::FirstAssistTankPositionBearForm(Unit* nalo
{
if (nalorakk->HasAura(static_cast<uint32>(ZulAmanSpells::SPELL_BEARFORM)))
{
if (AI_VALUE(Unit*, "current target") != nalorakk)
if (bot->GetVictim() != nalorakk)
return Attack(nalorakk);
if (nalorakk->GetVictim() != bot)
@ -262,7 +262,7 @@ bool JanalaiTanksPositionBossAction::Execute(Event /*event*/)
if (!janalai)
return false;
if (AI_VALUE(Unit*, "current target") != janalai)
if (bot->GetVictim() != janalai)
return Attack(janalai);
if (janalai->GetVictim() == bot)
@ -409,7 +409,7 @@ bool HalazziMainTankPositionBossAction::Execute(Event /*event*/)
MarkTargetWithStar(bot, halazzi);
SetRtiTarget(botAI, "star", halazzi);
if (AI_VALUE(Unit*, "current target") != halazzi)
if (bot->GetVictim() != halazzi)
return Attack(halazzi);
if (halazzi->GetVictim() == bot)
@ -443,7 +443,7 @@ bool HalazziFirstAssistTankAttackSpiritLynxAction::Execute(Event /*event*/)
MarkTargetWithCircle(bot, lynx);
SetRtiTarget(botAI, "circle", lynx);
if (AI_VALUE(Unit*, "current target") != lynx)
if (bot->GetVictim() != lynx)
return Attack(lynx);
if (lynx->GetVictim() != bot)
@ -455,7 +455,7 @@ bool HalazziFirstAssistTankAttackSpiritLynxAction::Execute(Event /*event*/)
{
SetRtiTarget(botAI, "star", halazzi);
if (AI_VALUE(Unit*, "current target") != halazzi)
if (bot->GetVictim() != halazzi)
return Attack(halazzi);
targetFound = true;
@ -492,7 +492,7 @@ bool HalazziAssignDpsPriorityAction::Execute(Event /*event*/)
MarkTargetWithSkull(bot, totem);
SetRtiTarget(botAI, "skull", totem);
if (AI_VALUE(Unit*, "current target") != totem)
if (bot->GetTarget() != totem->GetGUID())
return Attack(totem);
return false;
@ -503,7 +503,7 @@ bool HalazziAssignDpsPriorityAction::Execute(Event /*event*/)
{
SetRtiTarget(botAI, "star", halazzi);
if (AI_VALUE(Unit*, "current target") != halazzi)
if (bot->GetTarget() != halazzi->GetGUID())
return Attack(halazzi);
}
@ -602,7 +602,7 @@ bool HexLordMalacrassCastersStopAttackingAction::Execute(Event /*event*/)
!malacrass->HasAura(static_cast<uint32>(ZulAmanSpells::SPELL_HEX_LORD_SPELL_REFLECTION)))
return false;
if (AI_VALUE(Unit*, "current target") == malacrass)
if (bot->GetVictim() == malacrass)
{
bot->AttackStop();
bot->InterruptNonMeleeSpells(true);
@ -657,7 +657,7 @@ bool ZuljinTanksPositionBossAction::Execute(Event /*event*/)
if (!zuljin)
return false;
if (AI_VALUE(Unit*, "current target") != zuljin)
if (bot->GetVictim() != zuljin)
return Attack(zuljin);
if (zuljin->GetVictim() == bot)

View File

@ -267,7 +267,7 @@ float HexLordMalacrassStopAttackingDuringSpellReflectionMultiplier::GetValue(Act
return 1.0f;
if (castSpellAction->getThreatType() == Action::ActionThreatType::Aoe ||
(AI_VALUE(Unit*, "current target") == malacrass &&
(bot->GetVictim() == malacrass &&
castSpellAction->getThreatType() == Action::ActionThreatType::Single))
return 0.0f;

View File

@ -12,7 +12,6 @@
#include "Ai/Raid/SerpentshrineCavern/RaidSSCActionContext.h"
#include "Ai/Raid/TempestKeep/RaidTempestKeepActionContext.h"
#include "Ai/Raid/HyjalSummit/RaidHyjalSummitActionContext.h"
#include "Ai/Raid/BlackTemple/RaidBlackTempleActionContext.h"
#include "Ai/Raid/ZulAman/RaidZulAmanActionContext.h"
#include "Ai/Raid/ObsidianSanctum/RaidOsActionContext.h"
#include "Ai/Raid/EyeOfEternity/RaidEoEActionContext.h"
@ -37,7 +36,6 @@ void AiObjectContext::BuildSharedActionContexts(SharedNamedObjectContextList<Act
actionContexts.Add(new RaidSSCActionContext());
actionContexts.Add(new RaidTempestKeepActionContext());
actionContexts.Add(new RaidHyjalSummitActionContext());
actionContexts.Add(new RaidBlackTempleActionContext());
actionContexts.Add(new RaidZulAmanActionContext());
actionContexts.Add(new RaidNaxxActionContext());
actionContexts.Add(new RaidOsActionContext());

View File

@ -12,7 +12,6 @@
#include "Ai/Raid/SerpentshrineCavern/RaidSSCTriggerContext.h"
#include "Ai/Raid/TempestKeep/RaidTempestKeepTriggerContext.h"
#include "Ai/Raid/HyjalSummit/RaidHyjalSummitTriggerContext.h"
#include "Ai/Raid/BlackTemple/RaidBlackTempleTriggerContext.h"
#include "Ai/Raid/ZulAman/RaidZulAmanTriggerContext.h"
#include "Ai/Raid/ObsidianSanctum/RaidOsTriggerContext.h"
#include "Ai/Raid/EyeOfEternity/RaidEoETriggerContext.h"
@ -38,7 +37,6 @@ void AiObjectContext::BuildSharedTriggerContexts(SharedNamedObjectContextList<Tr
triggerContexts.Add(new RaidSSCTriggerContext());
triggerContexts.Add(new RaidTempestKeepTriggerContext());
triggerContexts.Add(new RaidHyjalSummitTriggerContext());
triggerContexts.Add(new RaidBlackTempleTriggerContext());
triggerContexts.Add(new RaidZulAmanTriggerContext());
triggerContexts.Add(new RaidOsTriggerContext());
triggerContexts.Add(new RaidEoETriggerContext());

View File

@ -1619,9 +1619,9 @@ void PlayerbotAI::ApplyInstanceStrategies(uint32 mapId, bool tellMaster)
{
static const std::vector<std::string> allInstanceStrategies =
{
"aq20", "blacktemple", "bwl", "gruulslair", "hyjal", "icc", "karazhan",
"magtheridon", "moltencore", "naxx", "onyxia", "ssc", "tbc-ac", "tempestkeep",
"ulduar", "voa", "wotlk-an", "wotlk-cos", "wotlk-dtk", "wotlk-eoe", "wotlk-fos",
"aq20", "bwl", "karazhan", "gruulslair", "hyjal", "icc", "magtheridon",
"moltencore", "naxx", "onyxia", "ssc", "tbc-ac", "tempestkeep", "ulduar",
"voa", "wotlk-an", "wotlk-cos", "wotlk-dtk", "wotlk-eoe", "wotlk-fos",
"wotlk-gd", "wotlk-hol", "wotlk-hor", "wotlk-hos", "wotlk-nex", "wotlk-occ",
"wotlk-ok", "wotlk-os", "wotlk-pos", "wotlk-toc", "wotlk-uk", "wotlk-up",
"wotlk-vh", "zulaman"
@ -1669,9 +1669,6 @@ void PlayerbotAI::ApplyInstanceStrategies(uint32 mapId, bool tellMaster)
case 558:
strategyName = "tbc-ac"; // Auchindoun: Auchenai Crypts
break;
case 564:
strategyName = "blacktemple"; // Black Temple
break;
case 565:
strategyName = "gruulslair"; // Gruul's Lair
break;
@ -2877,7 +2874,7 @@ bool PlayerbotAI::SayToParty(const std::string& msg)
bool PlayerbotAI::SayToRaid(const std::string& msg)
{
if (!bot->GetGroup() || !bot->GetGroup()->isRaidGroup())
if (!bot->GetGroup() || bot->GetGroup()->isRaidGroup())
return false;
WorldPacket data;
@ -5563,7 +5560,7 @@ Item* PlayerbotAI::FindStoneFor(Item* weapon) const
SOLID_SHARPENING_STONE, HEAVY_SHARPENING_STONE, COARSE_SHARPENING_STONE, ROUGH_SHARPENING_STONE};
static const std::vector<uint32_t> uPrioritizedWeightStoneIds = {
ADAMANTITE_WEIGHTSTONE, FEL_WEIGHTSTONE, ELEMENTAL_SHARPENING_STONE, DENSE_WEIGHTSTONE, SOLID_WEIGHTSTONE,
ADAMANTITE_WEIGHTSTONE, FEL_WEIGHTSTONE, DENSE_WEIGHTSTONE, SOLID_WEIGHTSTONE,
HEAVY_WEIGHTSTONE, COARSE_WEIGHTSTONE, ROUGH_WEIGHTSTONE};
Item* stone = nullptr;

View File

@ -39,8 +39,6 @@ void PlayerbotRepository::Load(PlayerbotAI* botAI)
botAI->ChangeStrategy(value, BOT_STATE_DEAD);
} while (result->NextRow());
botAI->GetAiObjectContext()->GetUntypedValue("outfit list");
botAI->GetAiObjectContext()->Load(values);
}
}