mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
Channel Cancel checks for Channeled AOE DPS Spells
Hello everyone, I liked the channel cancel I did on mage recently, where they cancel blizzard if there is only 1 enemy left. I decided to do the same for the following classes: Druid: Hurricane Hunter: Volley Priest: Mind Sear Warlock: Rain of Fire I moved the "ChannelCancel" action to it's own file, so other classes could benefit from it. I removed it from the mageactions.
This commit is contained in:
@@ -63,6 +63,7 @@
|
|||||||
#include "WorldBuffAction.h"
|
#include "WorldBuffAction.h"
|
||||||
#include "XpGainAction.h"
|
#include "XpGainAction.h"
|
||||||
#include "NewRpgAction.h"
|
#include "NewRpgAction.h"
|
||||||
|
#include "CancelChannelAction.h"
|
||||||
|
|
||||||
class PlayerbotAI;
|
class PlayerbotAI;
|
||||||
|
|
||||||
@@ -189,6 +190,7 @@ public:
|
|||||||
creators["buy tabard"] = &ActionContext::buy_tabard;
|
creators["buy tabard"] = &ActionContext::buy_tabard;
|
||||||
creators["guild manage nearby"] = &ActionContext::guild_manage_nearby;
|
creators["guild manage nearby"] = &ActionContext::guild_manage_nearby;
|
||||||
creators["clean quest log"] = &ActionContext::clean_quest_log;
|
creators["clean quest log"] = &ActionContext::clean_quest_log;
|
||||||
|
creators["cancel channel"] = &ActionContext::cancel_channel;
|
||||||
|
|
||||||
// BG Tactics
|
// BG Tactics
|
||||||
creators["bg tactics"] = &ActionContext::bg_tactics;
|
creators["bg tactics"] = &ActionContext::bg_tactics;
|
||||||
@@ -298,6 +300,7 @@ private:
|
|||||||
static Action* arcane_torrent(PlayerbotAI* botAI) { return new CastArcaneTorrentAction(botAI); }
|
static Action* arcane_torrent(PlayerbotAI* botAI) { return new CastArcaneTorrentAction(botAI); }
|
||||||
static Action* mana_tap(PlayerbotAI* botAI) { return new CastManaTapAction(botAI); }
|
static Action* mana_tap(PlayerbotAI* botAI) { return new CastManaTapAction(botAI); }
|
||||||
static Action* end_pull(PlayerbotAI* botAI) { return new ChangeCombatStrategyAction(botAI, "-pull"); }
|
static Action* end_pull(PlayerbotAI* botAI) { return new ChangeCombatStrategyAction(botAI, "-pull"); }
|
||||||
|
static Action* cancel_channel(PlayerbotAI* botAI) { return new CancelChannelAction(botAI); }
|
||||||
|
|
||||||
static Action* emote(PlayerbotAI* botAI) { return new EmoteAction(botAI); }
|
static Action* emote(PlayerbotAI* botAI) { return new EmoteAction(botAI); }
|
||||||
static Action* talk(PlayerbotAI* botAI) { return new TalkAction(botAI); }
|
static Action* talk(PlayerbotAI* botAI) { return new TalkAction(botAI); }
|
||||||
|
|||||||
18
src/strategy/actions/CancelChannelAction.cpp
Normal file
18
src/strategy/actions/CancelChannelAction.cpp
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it
|
||||||
|
* and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CancelChannelAction.h"
|
||||||
|
#include "Player.h"
|
||||||
|
#include "PlayerbotAI.h"
|
||||||
|
|
||||||
|
bool CancelChannelAction::Execute(Event event)
|
||||||
|
{
|
||||||
|
if (bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
|
||||||
|
{
|
||||||
|
bot->InterruptSpell(CURRENT_CHANNELED_SPELL);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
21
src/strategy/actions/CancelChannelAction.h
Normal file
21
src/strategy/actions/CancelChannelAction.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it
|
||||||
|
* and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PLAYERBOT_CANCELCHANNELACTION_H
|
||||||
|
#define _PLAYERBOT_CANCELCHANNELACTION_H
|
||||||
|
|
||||||
|
#include "Action.h"
|
||||||
|
|
||||||
|
class PlayerbotAI;
|
||||||
|
|
||||||
|
class CancelChannelAction : public Action
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CancelChannelAction(PlayerbotAI* botAI) : Action(botAI, "cancel channel") {}
|
||||||
|
|
||||||
|
bool Execute(Event event) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -151,6 +151,8 @@ void CasterDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
|||||||
|
|
||||||
void CasterDruidAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
void CasterDruidAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||||
{
|
{
|
||||||
|
triggers.push_back(
|
||||||
|
new TriggerNode("hurricane channel check", NextAction::array(0, new NextAction("cancel channel", ACTION_HIGH + 2), nullptr)));
|
||||||
triggers.push_back(
|
triggers.push_back(
|
||||||
new TriggerNode("medium aoe", NextAction::array(0, new NextAction("hurricane", ACTION_HIGH + 1), nullptr)));
|
new TriggerNode("medium aoe", NextAction::array(0, new NextAction("hurricane", ACTION_HIGH + 1), nullptr)));
|
||||||
triggers.push_back(new TriggerNode(
|
triggers.push_back(new TriggerNode(
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ public:
|
|||||||
creators["eclipse (lunar) cooldown"] = &DruidTriggerFactoryInternal::eclipse_lunar_cooldown;
|
creators["eclipse (lunar) cooldown"] = &DruidTriggerFactoryInternal::eclipse_lunar_cooldown;
|
||||||
creators["mangle (cat)"] = &DruidTriggerFactoryInternal::mangle_cat;
|
creators["mangle (cat)"] = &DruidTriggerFactoryInternal::mangle_cat;
|
||||||
creators["ferocious bite time"] = &DruidTriggerFactoryInternal::ferocious_bite_time;
|
creators["ferocious bite time"] = &DruidTriggerFactoryInternal::ferocious_bite_time;
|
||||||
|
creators["hurricane channel check"] = &DruidTriggerFactoryInternal::hurricane_channel_check;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -147,6 +148,7 @@ private:
|
|||||||
static Trigger* eclipse_lunar_cooldown(PlayerbotAI* ai) { return new EclipseLunarCooldownTrigger(ai); }
|
static Trigger* eclipse_lunar_cooldown(PlayerbotAI* ai) { return new EclipseLunarCooldownTrigger(ai); }
|
||||||
static Trigger* mangle_cat(PlayerbotAI* ai) { return new MangleCatTrigger(ai); }
|
static Trigger* mangle_cat(PlayerbotAI* ai) { return new MangleCatTrigger(ai); }
|
||||||
static Trigger* ferocious_bite_time(PlayerbotAI* ai) { return new FerociousBiteTimeTrigger(ai); }
|
static Trigger* ferocious_bite_time(PlayerbotAI* ai) { return new FerociousBiteTimeTrigger(ai); }
|
||||||
|
static Trigger* hurricane_channel_check(PlayerbotAI* ai) { return new HurricaneChannelCheckTrigger(ai); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class DruidAiObjectContextInternal : public NamedObjectContext<Action>
|
class DruidAiObjectContextInternal : public NamedObjectContext<Action>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "DruidTriggers.h"
|
#include "DruidTriggers.h"
|
||||||
|
#include "Player.h"
|
||||||
#include "Playerbots.h"
|
#include "Playerbots.h"
|
||||||
|
|
||||||
bool MarkOfTheWildOnPartyTrigger::IsActive()
|
bool MarkOfTheWildOnPartyTrigger::IsActive()
|
||||||
@@ -34,3 +34,30 @@ bool BearFormTrigger::IsActive() { return !botAI->HasAnyAuraOf(bot, "bear form",
|
|||||||
bool TreeFormTrigger::IsActive() { return !botAI->HasAura(33891, bot); }
|
bool TreeFormTrigger::IsActive() { return !botAI->HasAura(33891, bot); }
|
||||||
|
|
||||||
bool CatFormTrigger::IsActive() { return !botAI->HasAura("cat form", bot); }
|
bool CatFormTrigger::IsActive() { return !botAI->HasAura("cat form", bot); }
|
||||||
|
|
||||||
|
const std::set<uint32> HurricaneChannelCheckTrigger::HURRICANE_SPELL_IDS = {
|
||||||
|
16914, // Hurricane Rank 1
|
||||||
|
17401, // Hurricane Rank 2
|
||||||
|
17402, // Hurricane Rank 3
|
||||||
|
27012, // Hurricane Rank 4
|
||||||
|
48467 // Hurricane Rank 5
|
||||||
|
};
|
||||||
|
|
||||||
|
bool HurricaneChannelCheckTrigger::IsActive()
|
||||||
|
{
|
||||||
|
Player* bot = botAI->GetBot();
|
||||||
|
|
||||||
|
// Check if the bot is channeling a spell
|
||||||
|
if (Spell* spell = bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
|
||||||
|
{
|
||||||
|
// Only trigger if the spell being channeled is Hurricane
|
||||||
|
if (HURRICANE_SPELL_IDS.count(spell->m_spellInfo->Id))
|
||||||
|
{
|
||||||
|
uint8 attackerCount = AI_VALUE(uint8, "attacker count");
|
||||||
|
return attackerCount < minEnemies;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not channeling Hurricane
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
#include "PlayerbotAI.h"
|
#include "PlayerbotAI.h"
|
||||||
#include "Playerbots.h"
|
#include "Playerbots.h"
|
||||||
#include "SharedDefines.h"
|
#include "SharedDefines.h"
|
||||||
|
#include "Trigger.h"
|
||||||
|
#include <set>
|
||||||
|
|
||||||
class PlayerbotAI;
|
class PlayerbotAI;
|
||||||
|
|
||||||
@@ -263,4 +265,19 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class HurricaneChannelCheckTrigger : public Trigger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HurricaneChannelCheckTrigger(PlayerbotAI* botAI, uint32 minEnemies = 2)
|
||||||
|
: Trigger(botAI, "hurricane channel check"), minEnemies(minEnemies)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsActive() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint32 minEnemies;
|
||||||
|
static const std::set<uint32> HURRICANE_SPELL_IDS;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -136,9 +136,9 @@ AoEHunterStrategy::AoEHunterStrategy(PlayerbotAI* botAI) : CombatStrategy(botAI)
|
|||||||
|
|
||||||
void AoEHunterStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
void AoEHunterStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||||
{
|
{
|
||||||
|
triggers.push_back(new TriggerNode("volley channel check", NextAction::array(0, new NextAction("cancel channel", 23.0f), nullptr)));
|
||||||
triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("volley", 22.0f), nullptr)));
|
triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("volley", 22.0f), nullptr)));
|
||||||
triggers.push_back(
|
triggers.push_back(new TriggerNode("light aoe", NextAction::array(0, new NextAction("multi-shot", 21.0f), nullptr)));
|
||||||
new TriggerNode("light aoe", NextAction::array(0, new NextAction("multi-shot", 21.0f), nullptr)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HunterBoostStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
void HunterBoostStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||||
|
|||||||
@@ -101,6 +101,7 @@ public:
|
|||||||
creators["lock and load"] = &HunterTriggerFactoryInternal::lock_and_load;
|
creators["lock and load"] = &HunterTriggerFactoryInternal::lock_and_load;
|
||||||
creators["silencing shot"] = &HunterTriggerFactoryInternal::silencing_shot;
|
creators["silencing shot"] = &HunterTriggerFactoryInternal::silencing_shot;
|
||||||
creators["intimidation"] = &HunterTriggerFactoryInternal::intimidation;
|
creators["intimidation"] = &HunterTriggerFactoryInternal::intimidation;
|
||||||
|
creators["volley channel check"] = &HunterTriggerFactoryInternal::volley_channel_check;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -141,6 +142,7 @@ private:
|
|||||||
static Trigger* lock_and_load(PlayerbotAI* botAI) { return new LockAndLoadTrigger(botAI); }
|
static Trigger* lock_and_load(PlayerbotAI* botAI) { return new LockAndLoadTrigger(botAI); }
|
||||||
static Trigger* silencing_shot(PlayerbotAI* botAI) { return new SilencingShotTrigger(botAI); }
|
static Trigger* silencing_shot(PlayerbotAI* botAI) { return new SilencingShotTrigger(botAI); }
|
||||||
static Trigger* intimidation(PlayerbotAI* botAI) { return new IntimidationTrigger(botAI); }
|
static Trigger* intimidation(PlayerbotAI* botAI) { return new IntimidationTrigger(botAI); }
|
||||||
|
static Trigger* volley_channel_check(PlayerbotAI* botAI) { return new VolleyChannelCheckTrigger(botAI); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class HunterAiObjectContextInternal : public NamedObjectContext<Action>
|
class HunterAiObjectContextInternal : public NamedObjectContext<Action>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "Playerbots.h"
|
#include "Playerbots.h"
|
||||||
#include "ServerFacade.h"
|
#include "ServerFacade.h"
|
||||||
#include "SharedDefines.h"
|
#include "SharedDefines.h"
|
||||||
|
#include "Player.h"
|
||||||
|
|
||||||
bool KillCommandTrigger::IsActive()
|
bool KillCommandTrigger::IsActive()
|
||||||
{
|
{
|
||||||
@@ -139,3 +140,31 @@ bool SerpentStingOnAttackerTrigger::IsActive()
|
|||||||
!botAI->HasAura("viper sting", target, false, true);
|
!botAI->HasAura("viper sting", target, false, true);
|
||||||
return BuffTrigger::IsActive();
|
return BuffTrigger::IsActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::set<uint32> VolleyChannelCheckTrigger::VOLLEY_SPELL_IDS = {
|
||||||
|
1510, // Volley Rank 1
|
||||||
|
14294, // Volley Rank 2
|
||||||
|
14295, // Volley Rank 3
|
||||||
|
27022, // Volley Rank 4
|
||||||
|
58431, // Volley Rank 5
|
||||||
|
58434 // Volley Rank 6
|
||||||
|
};
|
||||||
|
|
||||||
|
bool VolleyChannelCheckTrigger::IsActive()
|
||||||
|
{
|
||||||
|
Player* bot = botAI->GetBot();
|
||||||
|
|
||||||
|
// Check if the bot is channeling a spell
|
||||||
|
if (Spell* spell = bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
|
||||||
|
{
|
||||||
|
// Only trigger if the spell being channeled is Volley
|
||||||
|
if (VOLLEY_SPELL_IDS.count(spell->m_spellInfo->Id))
|
||||||
|
{
|
||||||
|
uint8 attackerCount = AI_VALUE(uint8, "attacker count");
|
||||||
|
return attackerCount < minEnemies;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not channeling Volley
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "GenericTriggers.h"
|
#include "GenericTriggers.h"
|
||||||
#include "Trigger.h"
|
#include "Trigger.h"
|
||||||
#include "PlayerbotAI.h"
|
#include "PlayerbotAI.h"
|
||||||
|
#include <set>
|
||||||
|
|
||||||
class PlayerbotAI;
|
class PlayerbotAI;
|
||||||
|
|
||||||
@@ -244,4 +245,19 @@ END_TRIGGER()
|
|||||||
BEGIN_TRIGGER(HunterPetNotHappy, Trigger)
|
BEGIN_TRIGGER(HunterPetNotHappy, Trigger)
|
||||||
END_TRIGGER()
|
END_TRIGGER()
|
||||||
|
|
||||||
|
class VolleyChannelCheckTrigger : public Trigger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VolleyChannelCheckTrigger(PlayerbotAI* botAI, uint32 minEnemies = 2)
|
||||||
|
: Trigger(botAI, "volley channel check"), minEnemies(minEnemies)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsActive() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint32 minEnemies;
|
||||||
|
static const std::set<uint32> VOLLEY_SPELL_IDS;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -142,13 +142,3 @@ bool CastBlinkBackAction::Execute(Event event)
|
|||||||
bot->SetOrientation(bot->GetAngle(target) + M_PI);
|
bot->SetOrientation(bot->GetAngle(target) + M_PI);
|
||||||
return CastSpellAction::Execute(event);
|
return CastSpellAction::Execute(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CancelChannelAction::Execute(Event event)
|
|
||||||
{
|
|
||||||
if (bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
|
|
||||||
{
|
|
||||||
bot->InterruptSpell(CURRENT_CHANNELED_SPELL);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -404,12 +404,4 @@ public:
|
|||||||
bool isUseful() override;
|
bool isUseful() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CancelChannelAction : public Action
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CancelChannelAction(PlayerbotAI* botAI) : Action(botAI, "cancel channel") {}
|
|
||||||
|
|
||||||
bool Execute(Event event) override;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -237,7 +237,6 @@ public:
|
|||||||
creators["use mana citrine"] = &MageAiObjectContextInternal::use_mana_citrine;
|
creators["use mana citrine"] = &MageAiObjectContextInternal::use_mana_citrine;
|
||||||
creators["use mana jade"] = &MageAiObjectContextInternal::use_mana_jade;
|
creators["use mana jade"] = &MageAiObjectContextInternal::use_mana_jade;
|
||||||
creators["use mana agate"] = &MageAiObjectContextInternal::use_mana_agate;
|
creators["use mana agate"] = &MageAiObjectContextInternal::use_mana_agate;
|
||||||
creators["cancel channel"] = &MageAiObjectContextInternal::cancel_channel;
|
|
||||||
creators["mana shield"] = &MageAiObjectContextInternal::mana_shield;
|
creators["mana shield"] = &MageAiObjectContextInternal::mana_shield;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,7 +298,6 @@ private:
|
|||||||
static Action* use_mana_citrine(PlayerbotAI* botAI) { return new UseManaCitrineAction(botAI); }
|
static Action* use_mana_citrine(PlayerbotAI* botAI) { return new UseManaCitrineAction(botAI); }
|
||||||
static Action* use_mana_jade(PlayerbotAI* botAI) { return new UseManaJadeAction(botAI); }
|
static Action* use_mana_jade(PlayerbotAI* botAI) { return new UseManaJadeAction(botAI); }
|
||||||
static Action* use_mana_agate(PlayerbotAI* botAI) { return new UseManaAgateAction(botAI); }
|
static Action* use_mana_agate(PlayerbotAI* botAI) { return new UseManaAgateAction(botAI); }
|
||||||
static Action* cancel_channel(PlayerbotAI* botAI) { return new CancelChannelAction(botAI); }
|
|
||||||
static Action* mana_shield(PlayerbotAI* botAI) { return new CastManaShieldAction(botAI); }
|
static Action* mana_shield(PlayerbotAI* botAI) { return new CastManaShieldAction(botAI); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ public:
|
|||||||
creators["silence"] = &PriestTriggerFactoryInternal::silence;
|
creators["silence"] = &PriestTriggerFactoryInternal::silence;
|
||||||
creators["silence on enemy healer"] = &PriestTriggerFactoryInternal::silence_on_enemy_healer;
|
creators["silence on enemy healer"] = &PriestTriggerFactoryInternal::silence_on_enemy_healer;
|
||||||
creators["shadowfiend"] = &PriestTriggerFactoryInternal::shadowfiend;
|
creators["shadowfiend"] = &PriestTriggerFactoryInternal::shadowfiend;
|
||||||
|
creators["mind sear channel check"] = &PriestTriggerFactoryInternal::mind_sear_channel_check;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -148,6 +149,7 @@ private:
|
|||||||
static Trigger* silence(PlayerbotAI* botAI) { return new SilenceTrigger(botAI); }
|
static Trigger* silence(PlayerbotAI* botAI) { return new SilenceTrigger(botAI); }
|
||||||
static Trigger* chastise(PlayerbotAI* botAI) { return new ChastiseTrigger(botAI); }
|
static Trigger* chastise(PlayerbotAI* botAI) { return new ChastiseTrigger(botAI); }
|
||||||
static Trigger* binding_heal(PlayerbotAI* botAI) { return new BindingHealTrigger(botAI); }
|
static Trigger* binding_heal(PlayerbotAI* botAI) { return new BindingHealTrigger(botAI); }
|
||||||
|
static Trigger* mind_sear_channel_check(PlayerbotAI* botAI) { return new MindSearChannelCheckTrigger(botAI); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class PriestAiObjectContextInternal : public NamedObjectContext<Action>
|
class PriestAiObjectContextInternal : public NamedObjectContext<Action>
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "PriestTriggers.h"
|
#include "PriestTriggers.h"
|
||||||
|
#include "PlayerbotAI.h"
|
||||||
|
#include "Player.h"
|
||||||
#include "Playerbots.h"
|
#include "Playerbots.h"
|
||||||
|
|
||||||
bool PowerWordFortitudeOnPartyTrigger::IsActive()
|
bool PowerWordFortitudeOnPartyTrigger::IsActive()
|
||||||
@@ -76,3 +77,27 @@ bool BindingHealTrigger::IsActive()
|
|||||||
return PartyMemberLowHealthTrigger::IsActive() &&
|
return PartyMemberLowHealthTrigger::IsActive() &&
|
||||||
AI_VALUE2(uint8, "health", "self target") < sPlayerbotAIConfig->mediumHealth;
|
AI_VALUE2(uint8, "health", "self target") < sPlayerbotAIConfig->mediumHealth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::set<uint32> MindSearChannelCheckTrigger::MIND_SEAR_SPELL_IDS = {
|
||||||
|
48045, // Mind Sear Rank 1
|
||||||
|
53023 // Mind Sear Rank 2
|
||||||
|
};
|
||||||
|
|
||||||
|
bool MindSearChannelCheckTrigger::IsActive()
|
||||||
|
{
|
||||||
|
Player* bot = botAI->GetBot();
|
||||||
|
|
||||||
|
// Check if the bot is channeling a spell
|
||||||
|
if (Spell* spell = bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
|
||||||
|
{
|
||||||
|
// Only trigger if the spell being channeled is Mind Sear
|
||||||
|
if (MIND_SEAR_SPELL_IDS.count(spell->m_spellInfo->Id))
|
||||||
|
{
|
||||||
|
uint8 attackerCount = AI_VALUE(uint8, "attacker count");
|
||||||
|
return attackerCount < minEnemies;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not channeling Mind Sear
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
#include "CureTriggers.h"
|
#include "CureTriggers.h"
|
||||||
#include "SharedDefines.h"
|
#include "SharedDefines.h"
|
||||||
|
#include "Trigger.h"
|
||||||
|
#include <set>
|
||||||
|
|
||||||
class PlayerbotAI;
|
class PlayerbotAI;
|
||||||
|
|
||||||
@@ -100,4 +102,19 @@ public:
|
|||||||
bool IsActive() override;
|
bool IsActive() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MindSearChannelCheckTrigger : public Trigger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MindSearChannelCheckTrigger(PlayerbotAI* botAI, uint32 minEnemies = 2)
|
||||||
|
: Trigger(botAI, "mind sear channel check"), minEnemies(minEnemies)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsActive() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint32 minEnemies;
|
||||||
|
static const std::set<uint32> MIND_SEAR_SPELL_IDS;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -54,6 +54,8 @@ void ShadowPriestAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
|||||||
triggers.push_back(new TriggerNode(
|
triggers.push_back(new TriggerNode(
|
||||||
"vampiric touch on attacker",
|
"vampiric touch on attacker",
|
||||||
NextAction::array(0, new NextAction("vampiric touch on attacker", ACTION_NORMAL + 4), nullptr)));
|
NextAction::array(0, new NextAction("vampiric touch on attacker", ACTION_NORMAL + 4), nullptr)));
|
||||||
|
triggers.push_back(
|
||||||
|
new TriggerNode("mind sear channel check", NextAction::array(0, new NextAction("cancel channel", ACTION_HIGH + 5), nullptr)));
|
||||||
triggers.push_back(
|
triggers.push_back(
|
||||||
new TriggerNode("medium aoe", NextAction::array(0, new NextAction("mind sear", ACTION_HIGH + 4), nullptr)));
|
new TriggerNode("medium aoe", NextAction::array(0, new NextAction("mind sear", ACTION_HIGH + 4), nullptr)));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,9 @@ void AoEWarlockStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
|||||||
new NextAction("seed of corruption on attacker", 22.0f),
|
new NextAction("seed of corruption on attacker", 22.0f),
|
||||||
new NextAction("seed of corruption", 21.5f),
|
new NextAction("seed of corruption", 21.5f),
|
||||||
new NextAction("rain of fire", 21.0f), nullptr)));
|
new NextAction("rain of fire", 21.0f), nullptr)));
|
||||||
|
|
||||||
|
triggers.push_back(
|
||||||
|
new TriggerNode("rain of fire channel check", NextAction::array(0, new NextAction("cancel channel", 21.5f), nullptr)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WarlockBoostStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
void WarlockBoostStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||||
|
|||||||
@@ -172,6 +172,7 @@ public:
|
|||||||
creators["curse of tongues"] = &WarlockTriggerFactoryInternal::curse_of_tongues;
|
creators["curse of tongues"] = &WarlockTriggerFactoryInternal::curse_of_tongues;
|
||||||
creators["curse of weakness"] = &WarlockTriggerFactoryInternal::curse_of_weakness;
|
creators["curse of weakness"] = &WarlockTriggerFactoryInternal::curse_of_weakness;
|
||||||
creators["wrong pet"] = &WarlockTriggerFactoryInternal::wrong_pet;
|
creators["wrong pet"] = &WarlockTriggerFactoryInternal::wrong_pet;
|
||||||
|
creators["rain of fire channel check"] = &WarlockTriggerFactoryInternal::rain_of_fire_channel_check;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -217,6 +218,7 @@ private:
|
|||||||
static Trigger* curse_of_tongues(PlayerbotAI* ai) { return new CurseOfTonguesTrigger(ai); }
|
static Trigger* curse_of_tongues(PlayerbotAI* ai) { return new CurseOfTonguesTrigger(ai); }
|
||||||
static Trigger* curse_of_weakness(PlayerbotAI* ai) { return new CurseOfWeaknessTrigger(ai); }
|
static Trigger* curse_of_weakness(PlayerbotAI* ai) { return new CurseOfWeaknessTrigger(ai); }
|
||||||
static Trigger* wrong_pet(PlayerbotAI* ai) { return new WrongPetTrigger(ai); }
|
static Trigger* wrong_pet(PlayerbotAI* ai) { return new WrongPetTrigger(ai); }
|
||||||
|
static Trigger* rain_of_fire_channel_check(PlayerbotAI* ai) { return new RainOfFireChannelCheckTrigger(ai); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class WarlockAiObjectContextInternal : public NamedObjectContext<Action>
|
class WarlockAiObjectContextInternal : public NamedObjectContext<Action>
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#include "WarlockTriggers.h"
|
#include "WarlockTriggers.h"
|
||||||
#include "GenericTriggers.h"
|
#include "GenericTriggers.h"
|
||||||
#include "Playerbots.h"
|
#include "Playerbots.h"
|
||||||
|
#include "PlayerbotAI.h"
|
||||||
|
#include "Player.h"
|
||||||
|
|
||||||
static const uint32 SOUL_SHARD_ITEM_ID = 6265;
|
static const uint32 SOUL_SHARD_ITEM_ID = 6265;
|
||||||
|
|
||||||
@@ -228,3 +230,32 @@ bool WrongPetTrigger::IsActive()
|
|||||||
// Step 6: If we get here, the bot doesn't know the spell required to support the active pet strategy
|
// Step 6: If we get here, the bot doesn't know the spell required to support the active pet strategy
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::set<uint32> RainOfFireChannelCheckTrigger::RAIN_OF_FIRE_SPELL_IDS = {
|
||||||
|
5740, // Rain of Fire Rank 1
|
||||||
|
6219, // Rain of Fire Rank 2
|
||||||
|
11677, // Rain of Fire Rank 3
|
||||||
|
11678, // Rain of Fire Rank 4
|
||||||
|
27212, // Rain of Fire Rank 5
|
||||||
|
47819, // Rain of Fire Rank 6
|
||||||
|
47820 // Rain of Fire Rank 7
|
||||||
|
};
|
||||||
|
|
||||||
|
bool RainOfFireChannelCheckTrigger::IsActive()
|
||||||
|
{
|
||||||
|
Player* bot = botAI->GetBot();
|
||||||
|
|
||||||
|
// Check if the bot is channeling a spell
|
||||||
|
if (Spell* spell = bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
|
||||||
|
{
|
||||||
|
// Only trigger if the spell being channeled is Rain of Fire
|
||||||
|
if (RAIN_OF_FIRE_SPELL_IDS.count(spell->m_spellInfo->Id))
|
||||||
|
{
|
||||||
|
uint8 attackerCount = AI_VALUE(uint8, "attacker count");
|
||||||
|
return attackerCount < minEnemies;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not channeling Rain of Fire
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
#include "PlayerbotAI.h"
|
#include "PlayerbotAI.h"
|
||||||
#include "Playerbots.h"
|
#include "Playerbots.h"
|
||||||
#include "CureTriggers.h"
|
#include "CureTriggers.h"
|
||||||
|
#include "Trigger.h"
|
||||||
|
#include <set>
|
||||||
|
|
||||||
class PlayerbotAI;
|
class PlayerbotAI;
|
||||||
|
|
||||||
@@ -332,4 +334,19 @@ public:
|
|||||||
: TwoTriggers(ai, "enemy too close for spell", "metamorphosis not active") {}
|
: TwoTriggers(ai, "enemy too close for spell", "metamorphosis not active") {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class RainOfFireChannelCheckTrigger : public Trigger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RainOfFireChannelCheckTrigger(PlayerbotAI* botAI, uint32 minEnemies = 2)
|
||||||
|
: Trigger(botAI, "rain of fire channel check"), minEnemies(minEnemies)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsActive() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
uint32 minEnemies;
|
||||||
|
static const std::set<uint32> RAIN_OF_FIRE_SPELL_IDS;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user