mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
Merge pull request #576 from liyunfan1223/assist_dps
Healer attack (healer dps strategy) and healer enhancement
This commit is contained in:
@@ -1002,16 +1002,16 @@ AiPlayerbot.PremadeSpecLink.9.2.80 = -03310030003-05203205210331051335230351
|
||||
|
||||
AiPlayerbot.PremadeSpecName.11.0 = balance pve
|
||||
AiPlayerbot.PremadeSpecGlyph.11.0 = 40916,43331,40921,43335,44922,40919
|
||||
AiPlayerbot.PremadeSpecLink.11.0.60 = 5012203115331003213302301231
|
||||
AiPlayerbot.PremadeSpecLink.11.0.80 = 5012203125331103213305301231--205003212
|
||||
AiPlayerbot.PremadeSpecLink.11.0.60 = 5022203105331003213005301231
|
||||
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 = -501232130322110353120303313511-20350001
|
||||
AiPlayerbot.PremadeSpecName.11.2 = resto pve
|
||||
AiPlayerbot.PremadeSpecGlyph.11.2 = 40913,43331,40906,43335,44922,45602
|
||||
AiPlayerbot.PremadeSpecLink.11.2.60 = --230033312031501531050013051
|
||||
AiPlayerbot.PremadeSpecLink.11.2.80 = 05320001--230033312031512531153313051
|
||||
AiPlayerbot.PremadeSpecLink.11.2.60 = --230033312031500531050113051
|
||||
AiPlayerbot.PremadeSpecLink.11.2.80 = 05320031--230033312031501531053313051
|
||||
AiPlayerbot.PremadeSpecName.11.3 = cat pve
|
||||
AiPlayerbot.PremadeSpecGlyph.11.3 = 40902,43331,40901,43335,44922,45604
|
||||
AiPlayerbot.PremadeSpecLink.11.3.60 = -552202032322010053100030310501
|
||||
|
||||
@@ -277,10 +277,6 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
|
||||
{
|
||||
engine->addStrategiesNoInit("racials", "chat", "default", "cast time", "duel", "boost", nullptr);
|
||||
}
|
||||
if (sPlayerbotAIConfig->autoSaveMana)
|
||||
{
|
||||
engine->addStrategy("save mana", false);
|
||||
}
|
||||
if (sPlayerbotAIConfig->autoAvoidAoe && facade->HasRealPlayerMaster())
|
||||
{
|
||||
engine->addStrategy("avoid aoe", false);
|
||||
@@ -394,7 +390,12 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
|
||||
if (PlayerbotAI::IsMelee(player, true) && PlayerbotAI::IsDps(player, true)) {
|
||||
engine->addStrategy("behind", false);
|
||||
}
|
||||
|
||||
if (PlayerbotAI::IsHeal(player, true))
|
||||
{
|
||||
if (sPlayerbotAIConfig->autoSaveMana)
|
||||
engine->addStrategy("save mana", false);
|
||||
engine->addStrategy("healer dps", false);
|
||||
}
|
||||
if (facade->IsRealPlayer() || sRandomPlayerbotMgr->IsRandomBot(player))
|
||||
{
|
||||
if (!player->GetGroup())
|
||||
@@ -483,8 +484,8 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
|
||||
engine->removeStrategy("threat", false);
|
||||
engine->addStrategy("boost", false);
|
||||
|
||||
if ((player->getClass() == CLASS_DRUID && tab == 2) || (player->getClass() == CLASS_SHAMAN && tab == 2))
|
||||
engine->addStrategiesNoInit("caster", "caster aoe", nullptr);
|
||||
// if ((player->getClass() == CLASS_DRUID && tab == 2) || (player->getClass() == CLASS_SHAMAN && tab == 2))
|
||||
// engine->addStrategiesNoInit("caster", "caster aoe", nullptr);
|
||||
|
||||
// if (player->getClass() == CLASS_DRUID && tab == 1)
|
||||
// engine->addStrategiesNoInit(/*"behind",*/ "dps", nullptr);
|
||||
|
||||
@@ -317,13 +317,13 @@ void PlayerbotAI::UpdateAI(uint32 elapsed, bool minimal)
|
||||
Spell* currentSpell = bot->GetCurrentSpell(CURRENT_GENERIC_SPELL);
|
||||
if (!currentSpell)
|
||||
currentSpell = bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL);
|
||||
if (currentSpell && currentSpell->getState() == SPELL_STATE_PREPARING)
|
||||
if (currentSpell && currentSpell->GetSpellInfo() && currentSpell->getState() == SPELL_STATE_PREPARING)
|
||||
{
|
||||
const SpellInfo* spellInfo = currentSpell->GetSpellInfo();
|
||||
|
||||
// interrupt if target is dead
|
||||
if (currentSpell->m_targets.GetUnitTarget() && !currentSpell->m_targets.GetUnitTarget()->IsAlive() &&
|
||||
spellInfo && !spellInfo->IsAllowingDeadTarget())
|
||||
!spellInfo->IsAllowingDeadTarget())
|
||||
{
|
||||
InterruptSpell();
|
||||
SetNextCheckDelay(sPlayerbotAIConfig->reactDelay);
|
||||
@@ -703,8 +703,7 @@ void PlayerbotAI::HandleTeleportAck()
|
||||
p << (uint32)0; // supposed to be flags? not used currently
|
||||
p << (uint32)0; // time - not currently used
|
||||
bot->GetSession()->HandleMoveTeleportAck(p);
|
||||
}
|
||||
SetNextCheckDelay(urand(1000, 3000));
|
||||
};
|
||||
}
|
||||
if (bot->IsBeingTeleportedFar())
|
||||
{
|
||||
@@ -712,13 +711,13 @@ void PlayerbotAI::HandleTeleportAck()
|
||||
{
|
||||
bot->GetSession()->HandleMoveWorldportAck();
|
||||
}
|
||||
SetNextCheckDelay(urand(2000, 5000));
|
||||
// SetNextCheckDelay(urand(2000, 5000));
|
||||
if (sPlayerbotAIConfig->applyInstanceStrategies)
|
||||
ApplyInstanceStrategies(bot->GetMapId(), true);
|
||||
Reset();
|
||||
}
|
||||
|
||||
SetNextCheckDelay(sPlayerbotAIConfig->globalCoolDown);
|
||||
Reset();
|
||||
}
|
||||
|
||||
void PlayerbotAI::Reset(bool full)
|
||||
@@ -1198,7 +1197,7 @@ void PlayerbotAI::HandleBotOutgoingPacket(WorldPacket const& packet)
|
||||
|
||||
void PlayerbotAI::SpellInterrupted(uint32 spellid)
|
||||
{
|
||||
for (uint8 type = CURRENT_MELEE_SPELL; type < CURRENT_CHANNELED_SPELL; type++)
|
||||
for (uint8 type = CURRENT_MELEE_SPELL; type <= CURRENT_CHANNELED_SPELL; type++)
|
||||
{
|
||||
Spell* spell = bot->GetCurrentSpell((CurrentSpellTypes)type);
|
||||
if (!spell)
|
||||
@@ -1206,8 +1205,8 @@ void PlayerbotAI::SpellInterrupted(uint32 spellid)
|
||||
if (spell->GetSpellInfo()->Id == spellid)
|
||||
bot->InterruptSpell((CurrentSpellTypes)type);
|
||||
}
|
||||
LastSpellCast& lastSpell = aiObjectContext->GetValue<LastSpellCast&>("last spell cast")->Get();
|
||||
lastSpell.id = 0;
|
||||
// LastSpellCast& lastSpell = aiObjectContext->GetValue<LastSpellCast&>("last spell cast")->Get();
|
||||
// lastSpell.id = 0;
|
||||
}
|
||||
|
||||
int32 PlayerbotAI::CalculateGlobalCooldown(uint32 spellid)
|
||||
@@ -3339,11 +3338,11 @@ bool PlayerbotAI::CastSpell(uint32 spellId, Unit* target, Item* itemTarget)
|
||||
// }
|
||||
// }
|
||||
|
||||
WaitForSpellCast(spell);
|
||||
if (spell->GetCastTime())
|
||||
aiObjectContext->GetValue<LastSpellCast&>("last spell cast")
|
||||
->Get()
|
||||
.Set(spellId, target->GetGUID(), time(nullptr));
|
||||
// WaitForSpellCast(spell);
|
||||
|
||||
aiObjectContext->GetValue<LastSpellCast&>("last spell cast")
|
||||
->Get()
|
||||
.Set(spellId, target->GetGUID(), time(nullptr));
|
||||
|
||||
aiObjectContext->GetValue<PositionMap&>("position")->Get()["random"].Reset();
|
||||
|
||||
@@ -3473,7 +3472,7 @@ bool PlayerbotAI::CastSpell(uint32 spellId, float x, float y, float z, Item* ite
|
||||
}
|
||||
}
|
||||
|
||||
WaitForSpellCast(spell);
|
||||
// WaitForSpellCast(spell);
|
||||
aiObjectContext->GetValue<LastSpellCast&>("last spell cast")->Get().Set(spellId, bot->GetGUID(), time(nullptr));
|
||||
aiObjectContext->GetValue<PositionMap&>("position")->Get()["random"].Reset();
|
||||
|
||||
@@ -3688,7 +3687,7 @@ bool PlayerbotAI::CastVehicleSpell(uint32 spellId, Unit* target)
|
||||
return false;
|
||||
}
|
||||
|
||||
WaitForSpellCast(spell);
|
||||
// WaitForSpellCast(spell);
|
||||
|
||||
// aiObjectContext->GetValue<LastSpellCast&>("last spell cast")->Get().Set(spellId, target->GetGUID(), time(0));
|
||||
// aiObjectContext->GetValue<botAI::PositionMap&>("position")->Get()["random"].Reset();
|
||||
@@ -3745,23 +3744,15 @@ bool PlayerbotAI::IsInVehicle(bool canControl, bool canCast, bool canAttack, boo
|
||||
|
||||
void PlayerbotAI::WaitForSpellCast(Spell* spell)
|
||||
{
|
||||
return;
|
||||
SpellInfo const* spellInfo = spell->GetSpellInfo();
|
||||
uint32 castTime = spell->GetCastTime();
|
||||
// float castTime = spell->GetCastTime();
|
||||
// if (spellInfo->IsChanneled())
|
||||
// {
|
||||
// int32 duration = spellInfo->GetDuration();
|
||||
// bot->ApplySpellMod(spellInfo->Id, SPELLMOD_DURATION, duration);
|
||||
// if (duration > 0)
|
||||
// castTime += duration;
|
||||
// }
|
||||
|
||||
// castTime = ceil(castTime);
|
||||
|
||||
// uint32 globalCooldown = CalculateGlobalCooldown(spellInfo->Id);
|
||||
// if (castTime < globalCooldown)
|
||||
// castTime = globalCooldown;
|
||||
if (spellInfo->IsChanneled())
|
||||
{
|
||||
int32 duration = spellInfo->GetDuration();
|
||||
bot->ApplySpellMod(spellInfo->Id, SPELLMOD_DURATION, duration);
|
||||
if (duration > 0)
|
||||
castTime += duration;
|
||||
}
|
||||
|
||||
SetNextCheckDelay(castTime + sPlayerbotAIConfig->reactDelay);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <string>
|
||||
|
||||
#include "Common.h"
|
||||
#include "DynamicObject.h"
|
||||
#include "NamedObjectContext.h"
|
||||
#include "PlayerbotAIAware.h"
|
||||
#include "Strategy.h"
|
||||
|
||||
@@ -202,9 +202,9 @@ bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal)
|
||||
{
|
||||
LogAction("A:%s - PREREQ", action->getName().c_str());
|
||||
|
||||
if (MultiplyAndPush(actionNode->getPrerequisites(), relevance + 0.02, false, event, "prereq"))
|
||||
if (MultiplyAndPush(actionNode->getPrerequisites(), relevance + 0.002f, false, event, "prereq"))
|
||||
{
|
||||
PushAgain(actionNode, relevance + 0.01, event);
|
||||
PushAgain(actionNode, relevance + 0.001f, event);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -226,7 +226,7 @@ bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal)
|
||||
else
|
||||
{
|
||||
LogAction("A:%s - FAILED", action->getName().c_str());
|
||||
MultiplyAndPush(actionNode->getAlternatives(), relevance + 0.03, false, event, "alt");
|
||||
MultiplyAndPush(actionNode->getAlternatives(), relevance + 0.003f, false, event, "alt");
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -246,7 +246,7 @@ bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal)
|
||||
botAI->TellMasterNoFacing(out);
|
||||
}
|
||||
LogAction("A:%s - IMPOSSIBLE", action->getName().c_str());
|
||||
MultiplyAndPush(actionNode->getAlternatives(), relevance + 0.03, false, event, "alt");
|
||||
MultiplyAndPush(actionNode->getAlternatives(), relevance + 0.003f, false, event, "alt");
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -38,7 +38,7 @@ bool TogglePetSpellAutoCastAction::Execute(Event event)
|
||||
bool shouldApply = true;
|
||||
// imp's spell, felhunte's intelligence, cat stealth
|
||||
if (spellId == 4511 || spellId == 1742 || spellId == 54424 || spellId == 57564 || spellId == 57565 ||
|
||||
spellId == 57566 || spellId == 57567 || spellId == 24450 || spellId == 53477)
|
||||
spellId == 57566 || spellId == 57567 || spellId == 24450)
|
||||
{
|
||||
shouldApply = false;
|
||||
}
|
||||
|
||||
@@ -196,8 +196,8 @@ bool CastEnchantItemAction::isPossible()
|
||||
}
|
||||
|
||||
CastHealingSpellAction::CastHealingSpellAction(PlayerbotAI* botAI, std::string const spell, uint8 estAmount,
|
||||
HealingManaEfficiency manaEfficiency)
|
||||
: CastAuraSpellAction(botAI, spell, true), estAmount(estAmount), manaEfficiency(manaEfficiency)
|
||||
HealingManaEfficiency manaEfficiency, bool isOwner)
|
||||
: CastAuraSpellAction(botAI, spell, isOwner), estAmount(estAmount), manaEfficiency(manaEfficiency)
|
||||
{
|
||||
range = botAI->GetRange("heal");
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ class CastHealingSpellAction : public CastAuraSpellAction
|
||||
{
|
||||
public:
|
||||
CastHealingSpellAction(PlayerbotAI* botAI, std::string const spell, uint8 estAmount = 15.0f,
|
||||
HealingManaEfficiency manaEfficiency = HealingManaEfficiency::MEDIUM);
|
||||
HealingManaEfficiency manaEfficiency = HealingManaEfficiency::MEDIUM, bool isOwner = true);
|
||||
|
||||
std::string const GetTargetName() override { return "self target"; }
|
||||
bool isUseful() override;
|
||||
@@ -177,8 +177,8 @@ class HealPartyMemberAction : public CastHealingSpellAction, public PartyMemberA
|
||||
{
|
||||
public:
|
||||
HealPartyMemberAction(PlayerbotAI* botAI, std::string const spell, uint8 estAmount = 15.0f,
|
||||
HealingManaEfficiency manaEfficiency = HealingManaEfficiency::MEDIUM)
|
||||
: CastHealingSpellAction(botAI, spell, estAmount, manaEfficiency), PartyMemberActionNameSupport(spell)
|
||||
HealingManaEfficiency manaEfficiency = HealingManaEfficiency::MEDIUM, bool isOwner = true)
|
||||
: CastHealingSpellAction(botAI, spell, estAmount, manaEfficiency, isOwner), PartyMemberActionNameSupport(spell)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -827,11 +827,12 @@ bool MovementAction::ReachCombatTo(Unit* target, float distance)
|
||||
float shortenTo = distance;
|
||||
|
||||
// Avoid walking too far when moving towards each other
|
||||
if (bot->GetDistance(tx, ty, tz) >= 10.0f)
|
||||
shortenTo = std::max(distance, bot->GetDistance(tx, ty, tz) / 2);
|
||||
float disToGo = bot->GetExactDist(tx, ty, tz) - distance;
|
||||
if (disToGo >= 10.0f)
|
||||
shortenTo = disToGo / 2 + distance;
|
||||
|
||||
if (bot->GetExactDist(tx, ty, tz) <= shortenTo)
|
||||
return false;
|
||||
// if (bot->GetExactDist(tx, ty, tz) <= shortenTo)
|
||||
// return false;
|
||||
|
||||
path.ShortenPathUntilDist(G3D::Vector3(tx, ty, tz), shortenTo);
|
||||
G3D::Vector3 endPos = path.GetPath().back();
|
||||
@@ -2313,7 +2314,7 @@ bool TankFaceAction::Execute(Event event)
|
||||
if (!bot->GetGroup())
|
||||
return false;
|
||||
|
||||
if (!bot->IsWithinMeleeRange(target))
|
||||
if (!bot->IsWithinMeleeRange(target) || target->isMoving())
|
||||
return false;
|
||||
|
||||
if (!AI_VALUE2(bool, "has aggro", "current target"))
|
||||
@@ -2513,7 +2514,7 @@ bool SetBehindTargetAction::Execute(Event event)
|
||||
if (target->GetVictim() == bot)
|
||||
return false;
|
||||
|
||||
if (!bot->IsWithinMeleeRange(target))
|
||||
if (!bot->IsWithinMeleeRange(target) || target->isMoving())
|
||||
return false;
|
||||
|
||||
float deltaAngle = Position::NormalizeOrientation(target->GetOrientation() - target->GetAngle(bot));
|
||||
|
||||
@@ -145,15 +145,12 @@ void CasterDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
new TriggerNode("medium mana", NextAction::array(0, new NextAction("innervate", ACTION_HIGH + 9), NULL)));
|
||||
triggers.push_back(new TriggerNode("enemy too close for spell",
|
||||
NextAction::array(0, new NextAction("flee", ACTION_MOVE + 9), nullptr)));
|
||||
triggers.push_back(
|
||||
new TriggerNode("party member remove curse",
|
||||
NextAction::array(0, new NextAction("remove curse on party", ACTION_DISPEL + 7), NULL)));
|
||||
}
|
||||
|
||||
void CasterDruidAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(
|
||||
new TriggerNode("high 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(
|
||||
"light aoe", NextAction::array(0, new NextAction("starfall", ACTION_NORMAL + 5),
|
||||
new NextAction("insect swarm on attacker", ACTION_NORMAL + 3),
|
||||
|
||||
@@ -47,4 +47,35 @@ bool CastRebirthAction::isUseful()
|
||||
{
|
||||
return CastSpellAction::isUseful() &&
|
||||
AI_VALUE2(float, "distance", GetTargetName()) <= sPlayerbotAIConfig->spellDistance;
|
||||
}
|
||||
|
||||
Unit* CastRejuvenationOnNotFullAction::GetTarget()
|
||||
{
|
||||
Group* group = bot->GetGroup();
|
||||
MinValueCalculator calc(100);
|
||||
for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next())
|
||||
{
|
||||
Player* player = gref->GetSource();
|
||||
if (!player)
|
||||
continue;
|
||||
if (player->isDead() || player->IsFullHealth())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (player->GetDistance2d(bot) > sPlayerbotAIConfig->spellDistance)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (botAI->HasAura("rejuvenation", player))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
calc.probe(player->GetHealthPct(), player);
|
||||
}
|
||||
return (Unit*)calc.param;
|
||||
}
|
||||
|
||||
bool CastRejuvenationOnNotFullAction::isUseful()
|
||||
{
|
||||
return GetTarget();
|
||||
}
|
||||
@@ -311,4 +311,16 @@ public:
|
||||
CastEnrageAction(PlayerbotAI* ai) : CastBuffSpellAction(ai, "enrage") {}
|
||||
};
|
||||
|
||||
|
||||
class CastRejuvenationOnNotFullAction : public HealPartyMemberAction
|
||||
{
|
||||
public:
|
||||
CastRejuvenationOnNotFullAction(PlayerbotAI* ai)
|
||||
: HealPartyMemberAction(ai, "rejuvenation", 5.0f, HealingManaEfficiency::VERY_HIGH)
|
||||
{
|
||||
}
|
||||
bool isUseful() override;
|
||||
Unit* GetTarget() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "DruidShapeshiftActions.h"
|
||||
#include "DruidTriggers.h"
|
||||
#include "GenericDruidNonCombatStrategy.h"
|
||||
#include "GenericDruidStrategy.h"
|
||||
#include "HealDruidStrategy.h"
|
||||
#include "MeleeDruidStrategy.h"
|
||||
#include "Playerbots.h"
|
||||
@@ -33,6 +34,7 @@ public:
|
||||
creators["buff"] = &DruidStrategyFactoryInternal::buff;
|
||||
creators["boost"] = &DruidStrategyFactoryInternal::boost;
|
||||
creators["cc"] = &DruidStrategyFactoryInternal::cc;
|
||||
creators["healer dps"] = &DruidStrategyFactoryInternal::healer_dps;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -45,6 +47,7 @@ private:
|
||||
static Strategy* buff(PlayerbotAI* botAI) { return new GenericDruidBuffStrategy(botAI); }
|
||||
static Strategy* boost(PlayerbotAI* botAI) { return new DruidBoostStrategy(botAI); }
|
||||
static Strategy* cc(PlayerbotAI* botAI) { return new DruidCcStrategy(botAI); }
|
||||
static Strategy* healer_dps(PlayerbotAI* botAI) { return new DruidHealerDpsStrategy(botAI); }
|
||||
};
|
||||
|
||||
class DruidDruidStrategyFactoryInternal : public NamedObjectContext<Strategy>
|
||||
@@ -161,6 +164,7 @@ public:
|
||||
creators["travel form"] = &DruidAiObjectContextInternal::travel_form;
|
||||
creators["aquatic form"] = &DruidAiObjectContextInternal::aquatic_form;
|
||||
creators["caster form"] = &DruidAiObjectContextInternal::caster_form;
|
||||
creators["cancel tree form"] = &DruidAiObjectContextInternal::cancel_tree_form;
|
||||
creators["mangle (bear)"] = &DruidAiObjectContextInternal::mangle_bear;
|
||||
creators["maul"] = &DruidAiObjectContextInternal::maul;
|
||||
creators["bash"] = &DruidAiObjectContextInternal::bash;
|
||||
@@ -205,6 +209,7 @@ public:
|
||||
creators["healing touch"] = &DruidAiObjectContextInternal::healing_touch;
|
||||
creators["regrowth on party"] = &DruidAiObjectContextInternal::regrowth_on_party;
|
||||
creators["rejuvenation on party"] = &DruidAiObjectContextInternal::rejuvenation_on_party;
|
||||
creators["rejuvenation on not full"] = &DruidAiObjectContextInternal::rejuvenation_on_not_full;
|
||||
creators["healing touch on party"] = &DruidAiObjectContextInternal::healing_touch_on_party;
|
||||
creators["rebirth"] = &DruidAiObjectContextInternal::rebirth;
|
||||
creators["revive"] = &DruidAiObjectContextInternal::revive;
|
||||
@@ -246,6 +251,7 @@ private:
|
||||
static Action* travel_form(PlayerbotAI* botAI) { return new CastTravelFormAction(botAI); }
|
||||
static Action* aquatic_form(PlayerbotAI* botAI) { return new CastAquaticFormAction(botAI); }
|
||||
static Action* caster_form(PlayerbotAI* botAI) { return new CastCasterFormAction(botAI); }
|
||||
static Action* cancel_tree_form(PlayerbotAI* botAI) { return new CastCancelTreeFormAction(botAI); }
|
||||
static Action* mangle_bear(PlayerbotAI* botAI) { return new CastMangleBearAction(botAI); }
|
||||
static Action* maul(PlayerbotAI* botAI) { return new CastMaulAction(botAI); }
|
||||
static Action* bash(PlayerbotAI* botAI) { return new CastBashAction(botAI); }
|
||||
@@ -290,6 +296,7 @@ private:
|
||||
static Action* healing_touch(PlayerbotAI* botAI) { return new CastHealingTouchAction(botAI); }
|
||||
static Action* regrowth_on_party(PlayerbotAI* botAI) { return new CastRegrowthOnPartyAction(botAI); }
|
||||
static Action* rejuvenation_on_party(PlayerbotAI* botAI) { return new CastRejuvenationOnPartyAction(botAI); }
|
||||
static Action* rejuvenation_on_not_full(PlayerbotAI* botAI) { return new CastRejuvenationOnNotFullAction(botAI); }
|
||||
static Action* healing_touch_on_party(PlayerbotAI* botAI) { return new CastHealingTouchOnPartyAction(botAI); }
|
||||
static Action* rebirth(PlayerbotAI* botAI) { return new CastRebirthAction(botAI); }
|
||||
static Action* revive(PlayerbotAI* botAI) { return new CastReviveAction(botAI); }
|
||||
|
||||
@@ -45,6 +45,17 @@ bool CastCasterFormAction::Execute(Event event)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CastCancelTreeFormAction::isUseful()
|
||||
{
|
||||
return botAI->HasAura(33891, bot);
|
||||
}
|
||||
|
||||
bool CastCancelTreeFormAction::Execute(Event event)
|
||||
{
|
||||
botAI->RemoveAura("tree of life");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CastTreeFormAction::isUseful()
|
||||
{
|
||||
return GetTarget() && CastSpellAction::isUseful() && !botAI->HasAura(33891, bot);
|
||||
|
||||
@@ -70,4 +70,14 @@ public:
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class CastCancelTreeFormAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastCancelTreeFormAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "cancel tree form") {}
|
||||
|
||||
bool isUseful() override;
|
||||
bool isPossible() override { return true; }
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -125,26 +125,34 @@ void GenericDruidNonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& trig
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("party member critical health",
|
||||
NextAction::array(0, new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 5),
|
||||
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 6), NULL)));
|
||||
NextAction::array(0,
|
||||
new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 7),
|
||||
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 6),
|
||||
new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 5),
|
||||
nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("party member low health",
|
||||
NextAction::array(0, new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 3),
|
||||
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 4), NULL)));
|
||||
NextAction::array(0,
|
||||
new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 5),
|
||||
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 4),
|
||||
new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 3),
|
||||
nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("party member medium health",
|
||||
NextAction::array(0, new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 1),
|
||||
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 2), NULL)));
|
||||
NextAction::array(0, new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 3),
|
||||
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 2),
|
||||
new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 1),
|
||||
nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("party member almost full health",
|
||||
NextAction::array(0, new NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 2), NULL)));
|
||||
NextAction::array(0, new NextAction("wild growth on party", ACTION_LIGHT_HEAL + 3), new NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 2), NULL)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("party member remove curse",
|
||||
NextAction::array(0, new NextAction("remove curse on party", ACTION_DISPEL + 7), NULL)));
|
||||
NextAction::array(0, new NextAction("remove curse on party", ACTION_DISPEL + 7), nullptr)));
|
||||
}
|
||||
|
||||
GenericDruidBuffStrategy::GenericDruidBuffStrategy(PlayerbotAI* botAI) : NonCombatStrategy(botAI)
|
||||
|
||||
@@ -130,6 +130,11 @@ void DruidCureStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
triggers.push_back(
|
||||
new TriggerNode("party member cure poison",
|
||||
NextAction::array(0, new NextAction("abolish poison on party", ACTION_DISPEL + 1), nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("party member remove curse",
|
||||
NextAction::array(0, new NextAction("remove curse on party", ACTION_DISPEL + 7), NULL)));
|
||||
|
||||
}
|
||||
|
||||
void DruidBoostStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
@@ -147,3 +152,22 @@ void DruidCcStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
triggers.push_back(new TriggerNode(
|
||||
"hibernate", NextAction::array(0, new NextAction("hibernate on cc", ACTION_HIGH + 3), nullptr)));
|
||||
}
|
||||
|
||||
void DruidHealerDpsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(
|
||||
new TriggerNode("healer should attack",
|
||||
NextAction::array(0,
|
||||
new NextAction("cancel tree form", ACTION_DEFAULT + 0.3f),
|
||||
new NextAction("moonfire", ACTION_DEFAULT + 0.2f),
|
||||
new NextAction("wrath", ACTION_DEFAULT + 0.1f),
|
||||
new NextAction("starfire", ACTION_DEFAULT),
|
||||
nullptr)));
|
||||
|
||||
// long cast time
|
||||
// triggers.push_back(
|
||||
// new TriggerNode("medium aoe and healer should attack",
|
||||
// NextAction::array(0,
|
||||
// new NextAction("hurricane", ACTION_DEFAULT + 0.7f),
|
||||
// nullptr)));
|
||||
}
|
||||
|
||||
@@ -46,4 +46,13 @@ public:
|
||||
std::string const getName() override { return "cc"; }
|
||||
};
|
||||
|
||||
class DruidHealerDpsStrategy : public Strategy
|
||||
{
|
||||
public:
|
||||
DruidHealerDpsStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
|
||||
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
std::string const getName() override { return "healer dps"; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -10,7 +10,12 @@
|
||||
class HealDruidStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>
|
||||
{
|
||||
public:
|
||||
HealDruidStrategyActionNodeFactory() { creators["nourish on party"] = &nourtish_on_party; }
|
||||
HealDruidStrategyActionNodeFactory() {
|
||||
creators["nourish on party"] = &nourtish_on_party;
|
||||
// creators["wild growth on party"] = &wild_growth_on_party;
|
||||
// creators["rejuvenation on party"] = &rejuvenation_on_party;
|
||||
// creators["regrowth on party"] = ®rowth_on_party;
|
||||
}
|
||||
|
||||
private:
|
||||
static ActionNode* nourtish_on_party([[maybe_unused]] PlayerbotAI* botAI)
|
||||
@@ -20,6 +25,27 @@ private:
|
||||
/*A*/ NextAction::array(0, new NextAction("healing touch on party"), nullptr),
|
||||
/*C*/ nullptr);
|
||||
}
|
||||
// static ActionNode* wild_growth_on_party([[maybe_unused]] PlayerbotAI* botAI)
|
||||
// {
|
||||
// return new ActionNode("wild growth on party",
|
||||
// /*P*/ NextAction::array(0, new NextAction("tree form"), nullptr),
|
||||
// /*A*/ nullptr,
|
||||
// /*C*/ nullptr);
|
||||
// }
|
||||
// static ActionNode* rejuvenation_on_party([[maybe_unused]] PlayerbotAI* botAI)
|
||||
// {
|
||||
// return new ActionNode("rejuvenation on party",
|
||||
// /*P*/ NextAction::array(0, new NextAction("tree form"), nullptr),
|
||||
// /*A*/ nullptr,
|
||||
// /*C*/ nullptr);
|
||||
// }
|
||||
// static ActionNode* regrowth_on_party([[maybe_unused]] PlayerbotAI* botAI)
|
||||
// {
|
||||
// return new ActionNode("regrowth on party",
|
||||
// /*P*/ NextAction::array(0, new NextAction("tree form"), nullptr),
|
||||
// /*A*/ nullptr,
|
||||
// /*C*/ nullptr);
|
||||
// }
|
||||
};
|
||||
|
||||
HealDruidStrategy::HealDruidStrategy(PlayerbotAI* botAI) : GenericDruidStrategy(botAI)
|
||||
@@ -31,61 +57,72 @@ void HealDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
GenericDruidStrategy::InitTriggers(triggers);
|
||||
|
||||
// triggers.push_back(new TriggerNode("enemy out of spell", NextAction::array(0, new NextAction("reach spell",
|
||||
// ACTION_NORMAL + 9), nullptr)));
|
||||
triggers.push_back(
|
||||
new TriggerNode("tree form", NextAction::array(0, new NextAction("tree form", ACTION_HIGH + 1), nullptr)));
|
||||
// triggers.push_back(
|
||||
// new TriggerNode("tree form", NextAction::array(0, new NextAction("tree form", ACTION_HIGH + 1), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"party member to heal out of spell range",
|
||||
NextAction::array(0, new NextAction("reach party member to heal", ACTION_CRITICAL_HEAL + 9), nullptr)));
|
||||
triggers.push_back(
|
||||
new TriggerNode("party member remove curse",
|
||||
NextAction::array(0, new NextAction("remove curse on party", ACTION_DISPEL + 7), NULL)));
|
||||
|
||||
// CRITICAL
|
||||
triggers.push_back(
|
||||
new TriggerNode("party member critical health",
|
||||
NextAction::array(0, new NextAction("swiftmend on party", ACTION_CRITICAL_HEAL + 4),
|
||||
new NextAction("wild growth", ACTION_CRITICAL_HEAL + 3),
|
||||
new NextAction("regrowth on party", ACTION_CRITICAL_HEAL + 2),
|
||||
NextAction::array(0,
|
||||
new NextAction("tree form", ACTION_CRITICAL_HEAL + 4.1f),
|
||||
new NextAction("swiftmend on party", ACTION_CRITICAL_HEAL + 4),
|
||||
new NextAction("regrowth on party", ACTION_CRITICAL_HEAL + 3),
|
||||
new NextAction("wild growth on party", ACTION_CRITICAL_HEAL + 2),
|
||||
new NextAction("nourish on party", ACTION_CRITICAL_HEAL + 1),
|
||||
// new NextAction("healing touch on party", ACTION_CRITICAL_HEAL + 0),
|
||||
NULL)));
|
||||
nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("party member critical health",
|
||||
NextAction::array(0, new NextAction("nature's swiftness", ACTION_CRITICAL_HEAL + 4), NULL)));
|
||||
NextAction::array(0, new NextAction("nature's swiftness", ACTION_CRITICAL_HEAL + 4), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"group heal setting",
|
||||
NextAction::array(0,
|
||||
new NextAction("tree form", ACTION_MEDIUM_HEAL + 2.3f),
|
||||
new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 2.2f),
|
||||
new NextAction("rejuvenation on not full", ACTION_MEDIUM_HEAL + 2.1f),
|
||||
nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("medium group heal occasion",
|
||||
NextAction::array(0, new NextAction("tranquility", ACTION_CRITICAL_HEAL + 5), NULL)));
|
||||
new TriggerNode("medium group heal setting",
|
||||
NextAction::array(0,
|
||||
new NextAction("tree form", ACTION_CRITICAL_HEAL + 0.6f),
|
||||
new NextAction("tranquility", ACTION_CRITICAL_HEAL + 0.5f), nullptr)));
|
||||
|
||||
// LOW
|
||||
triggers.push_back(
|
||||
new TriggerNode("party member low health",
|
||||
NextAction::array(0, new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 9),
|
||||
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 8),
|
||||
new NextAction("swiftmend on party", ACTION_MEDIUM_HEAL + 7),
|
||||
new NextAction("nourish on party", ACTION_MEDIUM_HEAL + 6),
|
||||
// new NextAction("healing touch on party", ACTION_MEDIUM_HEAL + 5),
|
||||
NULL)));
|
||||
NextAction::array(0, new NextAction("tree form", ACTION_MEDIUM_HEAL + 1.5f),
|
||||
new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 1.4f),
|
||||
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 1.3f),
|
||||
new NextAction("swiftmend on party", ACTION_MEDIUM_HEAL + 1.2),
|
||||
new NextAction("nourish on party", ACTION_MEDIUM_HEAL + 1.1f),
|
||||
nullptr)));
|
||||
|
||||
// MEDIUM
|
||||
triggers.push_back(
|
||||
new TriggerNode("party member medium health",
|
||||
NextAction::array(0, new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 4),
|
||||
new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 3),
|
||||
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 2),
|
||||
new NextAction("nourish on party", ACTION_MEDIUM_HEAL + 1), NULL)));
|
||||
NextAction::array(0,
|
||||
new NextAction("tree form", ACTION_MEDIUM_HEAL + 0.5f),
|
||||
new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 0.4f),
|
||||
new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 0.3f),
|
||||
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 0.2f),
|
||||
new NextAction("nourish on party", ACTION_MEDIUM_HEAL + 0.1f), nullptr)));
|
||||
|
||||
// almost full
|
||||
triggers.push_back(
|
||||
new TriggerNode("party member almost full health",
|
||||
NextAction::array(0, new NextAction("wild growth on party", ACTION_LIGHT_HEAL + 3),
|
||||
new NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 2),
|
||||
new NextAction("regrowth on party", ACTION_LIGHT_HEAL + 1), NULL)));
|
||||
NextAction::array(0, new NextAction("wild growth on party", ACTION_LIGHT_HEAL + 0.3f),
|
||||
new NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 0.2f),
|
||||
new NextAction("regrowth on party", ACTION_LIGHT_HEAL + 0.1f), nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("medium mana", NextAction::array(0, new NextAction("innervate", ACTION_HIGH + 5), NULL)));
|
||||
new TriggerNode("medium mana", NextAction::array(0, new NextAction("innervate", ACTION_HIGH + 5), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode("enemy too close for spell",
|
||||
NextAction::array(0, new NextAction("flee", ACTION_MOVE + 9), nullptr)));
|
||||
|
||||
@@ -22,7 +22,7 @@ void GenericPaladinNonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& tr
|
||||
triggers.push_back(new TriggerNode("party member almost full health",
|
||||
NextAction::array(0, new NextAction("flash of light on party", 25.0f), NULL)));
|
||||
triggers.push_back(new TriggerNode("party member medium health",
|
||||
NextAction::array(0, new NextAction("holy light on party", 26.0f), NULL)));
|
||||
NextAction::array(0, new NextAction("flash of light on party", 26.0f), NULL)));
|
||||
triggers.push_back(new TriggerNode("party member low health",
|
||||
NextAction::array(0, new NextAction("holy light on party", 27.0f), NULL)));
|
||||
triggers.push_back(new TriggerNode("party member critical health",
|
||||
|
||||
@@ -71,3 +71,17 @@ void PaladinCcStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
triggers.push_back(
|
||||
new TriggerNode("turn undead", NextAction::array(0, new NextAction("turn undead", ACTION_HIGH + 1), nullptr)));
|
||||
}
|
||||
|
||||
void PaladinHealerDpsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(
|
||||
new TriggerNode("healer should attack",
|
||||
NextAction::array(0,
|
||||
new NextAction("hammer of wrath", ACTION_DEFAULT + 0.6f),
|
||||
new NextAction("holy shock", ACTION_DEFAULT + 0.5f),
|
||||
new NextAction("shield of righteousness", ACTION_DEFAULT + 0.4f),
|
||||
new NextAction("judgement of light", ACTION_DEFAULT + 0.3f),
|
||||
new NextAction("consecration", ACTION_DEFAULT + 0.2f),
|
||||
new NextAction("exorcism", ACTION_DEFAULT+ 0.1f),
|
||||
nullptr)));
|
||||
}
|
||||
|
||||
@@ -46,4 +46,13 @@ public:
|
||||
std::string const getName() override { return "cc"; }
|
||||
};
|
||||
|
||||
class PaladinHealerDpsStrategy : public Strategy
|
||||
{
|
||||
public:
|
||||
PaladinHealerDpsStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
|
||||
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
std::string const getName() override { return "healer dps"; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,7 +22,7 @@ public:
|
||||
creators["cleanse magic"] = &cleanse_magic;
|
||||
creators["cleanse poison on party"] = &cleanse_poison_on_party;
|
||||
creators["cleanse disease on party"] = &cleanse_disease_on_party;
|
||||
// creators["seal of wisdom"] = &seal_of_wisdom;
|
||||
creators["seal of wisdom"] = &seal_of_wisdom;
|
||||
creators["seal of justice"] = &seal_of_justice;
|
||||
creators["hand of reckoning"] = &hand_of_reckoning;
|
||||
creators["judgement"] = &judgement;
|
||||
@@ -147,13 +147,13 @@ private:
|
||||
/*A*/ NextAction::array(0, new NextAction("purify disease on party"), nullptr),
|
||||
/*C*/ nullptr);
|
||||
}
|
||||
// static ActionNode* seal_of_wisdom(PlayerbotAI* ai)
|
||||
// {
|
||||
// return new ActionNode ("seal of wisdom",
|
||||
// /*P*/ NULL,
|
||||
// /*A*/ NextAction::array(0, new NextAction("seal of justice"), NULL),
|
||||
// /*C*/ NULL);
|
||||
// }
|
||||
static ActionNode* seal_of_wisdom(PlayerbotAI* ai)
|
||||
{
|
||||
return new ActionNode ("seal of wisdom",
|
||||
/*P*/ NULL,
|
||||
/*A*/ NextAction::array(0, new NextAction("seal of righteousness"), NULL),
|
||||
/*C*/ NULL);
|
||||
}
|
||||
static ActionNode* seal_of_justice(PlayerbotAI* ai)
|
||||
{
|
||||
return new ActionNode("seal of justice",
|
||||
|
||||
@@ -27,7 +27,7 @@ HealPaladinStrategy::HealPaladinStrategy(PlayerbotAI* botAI) : GenericPaladinStr
|
||||
|
||||
NextAction** HealPaladinStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0, new NextAction("judgement of light", ACTION_DEFAULT + 2), nullptr);
|
||||
return NextAction::array(0, new NextAction("judgement of light", ACTION_DEFAULT), nullptr);
|
||||
}
|
||||
|
||||
void HealPaladinStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
@@ -49,7 +49,7 @@ void HealPaladinStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
NextAction::array(0, new NextAction("reach party member to heal", ACTION_EMERGENCY + 3), nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("medium group heal occasion",
|
||||
new TriggerNode("medium group heal setting",
|
||||
NextAction::array(0, new NextAction("divine sacrifice", ACTION_CRITICAL_HEAL + 5),
|
||||
new NextAction("avenging wrath", ACTION_HIGH + 4),
|
||||
nullptr)));
|
||||
|
||||
@@ -25,6 +25,7 @@ public:
|
||||
creators["boost"] = &PaladinStrategyFactoryInternal::boost;
|
||||
creators["cc"] = &PaladinStrategyFactoryInternal::cc;
|
||||
creators["bthreat"] = &PaladinStrategyFactoryInternal::bthreat;
|
||||
creators["healer dps"] = &PaladinStrategyFactoryInternal::healer_dps;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -33,6 +34,7 @@ private:
|
||||
static Strategy* boost(PlayerbotAI* botAI) { return new PaladinBoostStrategy(botAI); }
|
||||
static Strategy* cc(PlayerbotAI* botAI) { return new PaladinCcStrategy(botAI); }
|
||||
static Strategy* bthreat(PlayerbotAI* botAI) { return new PaladinBuffThreatStrategy(botAI); }
|
||||
static Strategy* healer_dps(PlayerbotAI* botAI) { return new PaladinHealerDpsStrategy(botAI); }
|
||||
};
|
||||
|
||||
class PaladinResistanceStrategyFactoryInternal : public NamedObjectContext<Strategy>
|
||||
|
||||
@@ -73,7 +73,7 @@ void TankPaladinStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
GenericPaladinStrategy::InitTriggers(triggers);
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("seal", NextAction::array(0, new NextAction("seal of command", ACTION_HIGH), nullptr)));
|
||||
new TriggerNode("seal", NextAction::array(0, new NextAction("seal of corruption", ACTION_HIGH), nullptr)));
|
||||
triggers.push_back(
|
||||
new TriggerNode("low mana", NextAction::array(0, new NextAction("seal of wisdom", ACTION_HIGH + 9), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("devotion aura", NextAction::array(0, new NextAction("devotion aura", 90.0f),
|
||||
@@ -106,7 +106,7 @@ void TankPaladinStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
triggers.push_back(new TriggerNode(
|
||||
"righteous fury", NextAction::array(0, new NextAction("righteous fury", ACTION_HIGH + 8), nullptr)));
|
||||
triggers.push_back(
|
||||
new TriggerNode("medium group heal occasion",
|
||||
new TriggerNode("medium group heal setting",
|
||||
NextAction::array(0, new NextAction("divine sacrifice", ACTION_HIGH + 5), nullptr)));
|
||||
triggers.push_back(new TriggerNode(
|
||||
"enough mana", NextAction::array(0, new NextAction("consecration", ACTION_HIGH + 4), nullptr)));
|
||||
|
||||
@@ -87,3 +87,23 @@ void PriestCcStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
triggers.push_back(
|
||||
new TriggerNode("shackle undead", NextAction::array(0, new NextAction("shackle undead", 31.0f), nullptr)));
|
||||
}
|
||||
|
||||
void PriestHealerDpsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(
|
||||
new TriggerNode("healer should attack",
|
||||
NextAction::array(0,
|
||||
new NextAction("shadow word: pain", ACTION_DEFAULT + 0.5f),
|
||||
new NextAction("holy fire", ACTION_DEFAULT + 0.4f),
|
||||
new NextAction("smite", ACTION_DEFAULT + 0.3f),
|
||||
new NextAction("mind blast", ACTION_DEFAULT + 0.2f),
|
||||
new NextAction("shoot", ACTION_DEFAULT),
|
||||
nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("medium aoe and healer should attack",
|
||||
NextAction::array(0,
|
||||
new NextAction("mind sear", ACTION_DEFAULT + 0.5f),
|
||||
nullptr)));
|
||||
}
|
||||
|
||||
|
||||
@@ -46,4 +46,13 @@ public:
|
||||
std::string const getName() override { return "cc"; }
|
||||
};
|
||||
|
||||
class PriestHealerDpsStrategy : public Strategy
|
||||
{
|
||||
public:
|
||||
PriestHealerDpsStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
|
||||
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
std::string const getName() override { return "healer dps"; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -29,51 +29,56 @@ void HealPriestStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
// triggers.push_back(new TriggerNode(
|
||||
// "medium aoe heal",
|
||||
// NextAction::array(0,
|
||||
// new NextAction("circle of healing", ACTION_MEDIUM_HEAL + 8),
|
||||
// new NextAction("circle of healing on party", ACTION_MEDIUM_HEAL + 8),
|
||||
// // new NextAction("power word: shield on almost full health below", ACTION_MEDIUM_HEAL + 7),
|
||||
// NULL)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"group heal occasion",
|
||||
NextAction::array(0, new NextAction("circle of healing", ACTION_MEDIUM_HEAL + 8),
|
||||
new NextAction("power word: shield on almost full health below", ACTION_MEDIUM_HEAL + 7),
|
||||
NULL)));
|
||||
"group heal setting",
|
||||
NextAction::array(0,
|
||||
new NextAction("prayer of mending on party", ACTION_MEDIUM_HEAL + 8),
|
||||
new NextAction("power word: shield on not full", ACTION_MEDIUM_HEAL + 7),
|
||||
nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"medium group heal occasion",
|
||||
NextAction::array(0, new NextAction("divine hymn", ACTION_CRITICAL_HEAL + 6),
|
||||
new NextAction("prayer of healing on party", ACTION_CRITICAL_HEAL + 5), nullptr)));
|
||||
"medium group heal setting",
|
||||
NextAction::array(0, new NextAction("divine hymn", ACTION_CRITICAL_HEAL + 7),
|
||||
new NextAction("prayer of mending on party", ACTION_CRITICAL_HEAL + 6),
|
||||
new NextAction("power word: shield on not full", ACTION_CRITICAL_HEAL + 5),
|
||||
new NextAction("prayer of healing on party", ACTION_CRITICAL_HEAL + 4),
|
||||
nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"party member critical health",
|
||||
NextAction::array(0, new NextAction("power word: shield on party", ACTION_CRITICAL_HEAL + 6),
|
||||
NextAction::array(0, new NextAction("power word: shield on party", ACTION_CRITICAL_HEAL + 5),
|
||||
new NextAction("penance on party", ACTION_CRITICAL_HEAL + 4),
|
||||
new NextAction("flash heal on party", ACTION_CRITICAL_HEAL + 3),
|
||||
new NextAction("prayer of mending on party", ACTION_CRITICAL_HEAL + 2), NULL)));
|
||||
new NextAction("prayer of mending on party", ACTION_CRITICAL_HEAL + 3),
|
||||
new NextAction("flash heal on party", ACTION_CRITICAL_HEAL + 2),
|
||||
nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("party member low health",
|
||||
NextAction::array(0, new NextAction("power word: shield on party", ACTION_MEDIUM_HEAL + 4),
|
||||
new NextAction("prayer of mending on party", ACTION_MEDIUM_HEAL + 3),
|
||||
new NextAction("penance on party", ACTION_MEDIUM_HEAL + 2),
|
||||
new NextAction("circle of healing", ACTION_MEDIUM_HEAL + 2),
|
||||
new NextAction("prayer of mending on party", ACTION_MEDIUM_HEAL + 1),
|
||||
new NextAction("flash heal on party", ACTION_MEDIUM_HEAL + 0), NULL)));
|
||||
new NextAction("flash heal on party", ACTION_MEDIUM_HEAL + 0), nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("party member medium health",
|
||||
NextAction::array(0, new NextAction("power word: shield on party", ACTION_LIGHT_HEAL + 9),
|
||||
new NextAction("penance on party", ACTION_LIGHT_HEAL + 7),
|
||||
new NextAction("circle of healing", ACTION_LIGHT_HEAL + 7),
|
||||
new NextAction("prayer of mending on party", ACTION_LIGHT_HEAL + 6),
|
||||
new NextAction("prayer of mending on party", ACTION_LIGHT_HEAL + 7),
|
||||
new NextAction("penance on party", ACTION_LIGHT_HEAL + 6),
|
||||
new NextAction("flash heal on party", ACTION_LIGHT_HEAL + 5),
|
||||
// new NextAction("renew on party", ACTION_LIGHT_HEAL + 8),
|
||||
NULL)));
|
||||
nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("party member almost full health",
|
||||
NextAction::array(0,
|
||||
// new NextAction("penance on party", ACTION_LIGHT_HEAL + 3),
|
||||
new NextAction("renew on party", ACTION_LIGHT_HEAL + 2), NULL)));
|
||||
new NextAction("prayer of mending on party", ACTION_LIGHT_HEAL + 2),
|
||||
new NextAction("renew on party", ACTION_LIGHT_HEAL + 1),
|
||||
nullptr)));
|
||||
|
||||
// triggers.push_back(new TriggerNode("almost full health", NextAction::array(0, new NextAction("renew", 43.f),
|
||||
// nullptr))); triggers.push_back(new TriggerNode("party member almost full health", NextAction::array(0, new
|
||||
@@ -86,7 +91,7 @@ void HealPriestStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
NextAction::array(0, new NextAction("reach party member to heal", ACTION_CRITICAL_HEAL + 10), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("medium aoe heal", NextAction::array(0, new NextAction("prayer of
|
||||
// mending", 49.0f), nullptr))); triggers.push_back(new TriggerNode("medium aoe heal", NextAction::array(0, new
|
||||
// NextAction("circle of healing", 48.0f), nullptr))); triggers.push_back(new TriggerNode("binding heal",
|
||||
// NextAction("circle of healing on party", 48.0f), nullptr))); triggers.push_back(new TriggerNode("binding heal",
|
||||
// NextAction::array(0, new NextAction("binding heal", 52.0f), nullptr))); triggers.push_back(new TriggerNode("low
|
||||
// mana", NextAction::array(0, new NextAction("shadowfiend", ACTION_HIGH), nullptr)));
|
||||
|
||||
|
||||
@@ -63,42 +63,50 @@ void HolyHealPriestStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
GenericPriestStrategy::InitTriggers(triggers);
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("group heal occasion",
|
||||
NextAction::array(0, new NextAction("circle of healing", ACTION_MEDIUM_HEAL + 8), NULL)));
|
||||
new TriggerNode("group heal setting",
|
||||
NextAction::array(0,
|
||||
new NextAction("prayer of mending on party", ACTION_MEDIUM_HEAL + 9),
|
||||
new NextAction("circle of healing on party", ACTION_MEDIUM_HEAL + 8), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"medium group heal occasion",
|
||||
NextAction::array(0, new NextAction("divine hymn", ACTION_CRITICAL_HEAL + 6),
|
||||
new NextAction("prayer of healing on party", ACTION_CRITICAL_HEAL + 5), nullptr)));
|
||||
"medium group heal setting",
|
||||
NextAction::array(0, new NextAction("divine hymn", ACTION_CRITICAL_HEAL + 7),
|
||||
new NextAction("prayer of mending on party", ACTION_CRITICAL_HEAL + 6),
|
||||
new NextAction("circle of healing on party", ACTION_CRITICAL_HEAL + 5),
|
||||
new NextAction("prayer of healing on party", ACTION_CRITICAL_HEAL + 4), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"party member critical health",
|
||||
NextAction::array(0,
|
||||
new NextAction("guardian spirit on party", ACTION_CRITICAL_HEAL + 6),
|
||||
new NextAction("power word: shield on party", ACTION_CRITICAL_HEAL + 5),
|
||||
new NextAction("flash heal on party", ACTION_CRITICAL_HEAL + 3),
|
||||
new NextAction("prayer of mending on party", ACTION_CRITICAL_HEAL + 2), NULL)));
|
||||
new NextAction("prayer of mending on party", ACTION_CRITICAL_HEAL + 3),
|
||||
new NextAction("greater heal on party", ACTION_MEDIUM_HEAL + 2),
|
||||
new NextAction("flash heal on party", ACTION_CRITICAL_HEAL + 1),
|
||||
nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("party member low health",
|
||||
NextAction::array(0, new NextAction("circle of healing", ACTION_MEDIUM_HEAL + 4),
|
||||
new NextAction("greater heal on party", ACTION_MEDIUM_HEAL + 3),
|
||||
new NextAction("prayer of mending on party", ACTION_MEDIUM_HEAL + 2),
|
||||
new NextAction("flash heal on party", ACTION_MEDIUM_HEAL + 1), NULL)));
|
||||
NextAction::array(0, new NextAction("circle of healing on party", ACTION_MEDIUM_HEAL + 4),
|
||||
new NextAction("prayer of mending on party", ACTION_MEDIUM_HEAL + 3),
|
||||
new NextAction("greater heal on party", ACTION_MEDIUM_HEAL + 2),
|
||||
new NextAction("flash heal on party", ACTION_MEDIUM_HEAL + 1), nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("party member medium health",
|
||||
NextAction::array(0, new NextAction("circle of healing", ACTION_LIGHT_HEAL + 7),
|
||||
NextAction::array(0, new NextAction("circle of healing on party", ACTION_LIGHT_HEAL + 7),
|
||||
new NextAction("prayer of mending on party", ACTION_LIGHT_HEAL + 6),
|
||||
new NextAction("flash heal on party", ACTION_LIGHT_HEAL + 5),
|
||||
new NextAction("greater heal on party", ACTION_MEDIUM_HEAL + 5),
|
||||
new NextAction("flash heal on party", ACTION_LIGHT_HEAL + 4),
|
||||
// new NextAction("renew on party", ACTION_LIGHT_HEAL + 8),
|
||||
NULL)));
|
||||
nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("party member almost full health",
|
||||
NextAction::array(0, new NextAction("renew on party", ACTION_LIGHT_HEAL + 2),
|
||||
// new NextAction("flash heal on party", ACTION_LIGHT_HEAL + 1),
|
||||
NULL)));
|
||||
NextAction::array(0,
|
||||
new NextAction("renew on party", ACTION_LIGHT_HEAL + 2),
|
||||
new NextAction("prayer of mending on party", ACTION_LIGHT_HEAL + 1),
|
||||
nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"party member to heal out of spell range",
|
||||
|
||||
@@ -18,7 +18,7 @@ bool CastRemoveShadowformAction::Execute(Event event)
|
||||
return true;
|
||||
}
|
||||
|
||||
Unit* CastPowerWordShieldOnAlmostFullHealthBelow::GetTarget()
|
||||
Unit* CastPowerWordShieldOnAlmostFullHealthBelowAction::GetTarget()
|
||||
{
|
||||
Group* group = bot->GetGroup();
|
||||
for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next())
|
||||
@@ -47,7 +47,7 @@ Unit* CastPowerWordShieldOnAlmostFullHealthBelow::GetTarget()
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool CastPowerWordShieldOnAlmostFullHealthBelow::isUseful()
|
||||
bool CastPowerWordShieldOnAlmostFullHealthBelowAction::isUseful()
|
||||
{
|
||||
Group* group = bot->GetGroup();
|
||||
for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next())
|
||||
@@ -74,4 +74,35 @@ bool CastPowerWordShieldOnAlmostFullHealthBelow::isUseful()
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Unit* CastPowerWordShieldOnNotFullAction::GetTarget()
|
||||
{
|
||||
Group* group = bot->GetGroup();
|
||||
MinValueCalculator calc(100);
|
||||
for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next())
|
||||
{
|
||||
Player* player = gref->GetSource();
|
||||
if (!player)
|
||||
continue;
|
||||
if (player->isDead() || player->IsFullHealth())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (player->GetDistance2d(bot) > sPlayerbotAIConfig->spellDistance)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (botAI->HasAnyAuraOf(player, "weakened soul", "power word: shield", nullptr))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
calc.probe(player->GetHealthPct(), player);
|
||||
}
|
||||
return (Unit*)calc.param;
|
||||
}
|
||||
|
||||
bool CastPowerWordShieldOnNotFullAction::isUseful()
|
||||
{
|
||||
return GetTarget();
|
||||
}
|
||||
@@ -52,10 +52,23 @@ HEAL_PARTY_ACTION(CastGreaterHealOnPartyAction, "greater heal", 50.0f, HealingMa
|
||||
HEAL_PARTY_ACTION(CastPowerWordShieldOnPartyAction, "power word: shield", 15.0f, HealingManaEfficiency::VERY_HIGH);
|
||||
HEAL_PARTY_ACTION(CastFlashHealOnPartyAction, "flash heal", 15.0f, HealingManaEfficiency::LOW);
|
||||
HEAL_PARTY_ACTION(CastRenewOnPartyAction, "renew", 15.0f, HealingManaEfficiency::VERY_HIGH);
|
||||
HEAL_PARTY_ACTION(CastPrayerOfMendingAction, "prayer of mending", 15.0f, HealingManaEfficiency::MEDIUM);
|
||||
// HEAL_PARTY_ACTION(CastPrayerOfMendingAction, "prayer of mending", 10.0f, HealingManaEfficiency::HIGH);
|
||||
class CastPrayerOfMendingAction : public HealPartyMemberAction
|
||||
{
|
||||
public:
|
||||
CastPrayerOfMendingAction(PlayerbotAI* botAI) : HealPartyMemberAction(botAI, "prayer of mending", 10.0f, HealingManaEfficiency::HIGH, false) {}
|
||||
};
|
||||
|
||||
HEAL_PARTY_ACTION(CastBindingHealAction, "binding heal", 15.0f, HealingManaEfficiency::MEDIUM);
|
||||
HEAL_PARTY_ACTION(CastPrayerOfHealingAction, "prayer of healing", 15.0f, HealingManaEfficiency::MEDIUM);
|
||||
AOE_HEAL_ACTION(CastCircleOfHealingAction, "circle of healing", 15.0f, HealingManaEfficiency::HIGH);
|
||||
// AOE_HEAL_ACTION(CastCircleOfHealingAction, "circle of healing", 15.0f, HealingManaEfficiency::HIGH);
|
||||
class CastCircleOfHealingAction : public HealPartyMemberAction
|
||||
{
|
||||
public:
|
||||
CastCircleOfHealingAction(PlayerbotAI* ai) : HealPartyMemberAction(ai, "circle of healing", 15.0f, HealingManaEfficiency::HIGH)
|
||||
{
|
||||
}
|
||||
};
|
||||
AOE_HEAL_ACTION(CastLightwellAction, "lightwell", 15.0f, HealingManaEfficiency::MEDIUM);
|
||||
|
||||
SPELL_ACTION(CastSmiteAction, "smite");
|
||||
@@ -68,7 +81,13 @@ CURE_PARTY_ACTION(CastCureDiseaseOnPartyAction, "cure disease", DISPEL_DISEASE);
|
||||
CURE_ACTION(CastAbolishDiseaseAction, "abolish disease");
|
||||
CURE_PARTY_ACTION(CastAbolishDiseaseOnPartyAction, "abolish disease", DISPEL_DISEASE);
|
||||
|
||||
DEBUFF_CHECKISOWNER_ACTION(CastHolyFireAction, "holy fire");
|
||||
// DEBUFF_CHECKISOWNER_ACTION(CastHolyFireAction, "holy fire");
|
||||
class CastHolyFireAction : public CastDebuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastHolyFireAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "holy fire", true, 0.0f) {}
|
||||
};
|
||||
|
||||
// shadow 2.4.3
|
||||
// BUFF_ACTION(CastShadowfiendAction, "shadowfiend");
|
||||
SPELL_ACTION(CastShadowWordDeathAction, "shadow word: death");
|
||||
@@ -156,10 +175,10 @@ public:
|
||||
virtual std::string const GetTargetName() { return "current target"; }
|
||||
};
|
||||
|
||||
class CastPowerWordShieldOnAlmostFullHealthBelow : public HealPartyMemberAction
|
||||
class CastPowerWordShieldOnAlmostFullHealthBelowAction : public HealPartyMemberAction
|
||||
{
|
||||
public:
|
||||
CastPowerWordShieldOnAlmostFullHealthBelow(PlayerbotAI* ai)
|
||||
CastPowerWordShieldOnAlmostFullHealthBelowAction(PlayerbotAI* ai)
|
||||
: HealPartyMemberAction(ai, "power word: shield", 15.0f, HealingManaEfficiency::HIGH)
|
||||
{
|
||||
}
|
||||
@@ -167,6 +186,17 @@ public:
|
||||
Unit* GetTarget() override;
|
||||
};
|
||||
|
||||
class CastPowerWordShieldOnNotFullAction : public HealPartyMemberAction
|
||||
{
|
||||
public:
|
||||
CastPowerWordShieldOnNotFullAction(PlayerbotAI* ai)
|
||||
: HealPartyMemberAction(ai, "power word: shield", 5.0f, HealingManaEfficiency::HIGH)
|
||||
{
|
||||
}
|
||||
bool isUseful() override;
|
||||
Unit* GetTarget() override;
|
||||
};
|
||||
|
||||
class CastMindSearAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "PriestAiObjectContext.h"
|
||||
|
||||
#include "GenericPriestStrategy.h"
|
||||
#include "HolyPriestStrategy.h"
|
||||
#include "NamedObjectContext.h"
|
||||
#include "Playerbots.h"
|
||||
@@ -30,6 +31,7 @@ public:
|
||||
creators["boost"] = &PriestStrategyFactoryInternal::boost;
|
||||
creators["rshadow"] = &PriestStrategyFactoryInternal::rshadow;
|
||||
creators["cc"] = &PriestStrategyFactoryInternal::cc;
|
||||
creators["healer dps"] = &PriestStrategyFactoryInternal::healer_dps;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -42,6 +44,7 @@ private:
|
||||
static Strategy* pull(PlayerbotAI* botAI) { return new PullStrategy(botAI, "shoot"); }
|
||||
static Strategy* shadow_debuff(PlayerbotAI* botAI) { return new ShadowPriestDebuffStrategy(botAI); }
|
||||
static Strategy* cure(PlayerbotAI* botAI) { return new PriestCureStrategy(botAI); }
|
||||
static Strategy* healer_dps(PlayerbotAI* botAI) { return new PriestHealerDpsStrategy(botAI); }
|
||||
};
|
||||
|
||||
class PriestCombatStrategyFactoryInternal : public NamedObjectContext<Strategy>
|
||||
@@ -172,6 +175,8 @@ public:
|
||||
creators["power word: shield on party"] = &PriestAiObjectContextInternal::power_word_shield_on_party;
|
||||
creators["power word: shield on almost full health below"] =
|
||||
&PriestAiObjectContextInternal::power_word_shield_on_almost_full_health_below;
|
||||
creators["power word: shield on not full"] =
|
||||
&PriestAiObjectContextInternal::power_word_shield_on_not_full;
|
||||
creators["renew"] = &PriestAiObjectContextInternal::renew;
|
||||
creators["renew on party"] = &PriestAiObjectContextInternal::renew_on_party;
|
||||
creators["greater heal"] = &PriestAiObjectContextInternal::greater_heal;
|
||||
@@ -192,7 +197,7 @@ public:
|
||||
creators["fade"] = &PriestAiObjectContextInternal::fade;
|
||||
creators["inner fire"] = &PriestAiObjectContextInternal::inner_fire;
|
||||
creators["resurrection"] = &PriestAiObjectContextInternal::resurrection;
|
||||
creators["circle of healing"] = &PriestAiObjectContextInternal::circle_of_healing;
|
||||
creators["circle of healing on party"] = &PriestAiObjectContextInternal::circle_of_healing;
|
||||
creators["psychic scream"] = &PriestAiObjectContextInternal::psychic_scream;
|
||||
creators["vampiric touch"] = &PriestAiObjectContextInternal::vampiric_touch;
|
||||
creators["vampiric touch on attacker"] = &PriestAiObjectContextInternal::vampiric_touch_on_attacker;
|
||||
@@ -282,7 +287,11 @@ private:
|
||||
}
|
||||
static Action* power_word_shield_on_almost_full_health_below(PlayerbotAI* ai)
|
||||
{
|
||||
return new CastPowerWordShieldOnAlmostFullHealthBelow(ai);
|
||||
return new CastPowerWordShieldOnAlmostFullHealthBelowAction(ai);
|
||||
}
|
||||
static Action* power_word_shield_on_not_full(PlayerbotAI* ai)
|
||||
{
|
||||
return new CastPowerWordShieldOnNotFullAction(ai);
|
||||
}
|
||||
static Action* renew(PlayerbotAI* botAI) { return new CastRenewAction(botAI); }
|
||||
static Action* renew_on_party(PlayerbotAI* botAI) { return new CastRenewOnPartyAction(botAI); }
|
||||
|
||||
@@ -55,7 +55,7 @@ void PriestNonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
NextAction::array(0, new NextAction("renew on party", ACTION_LIGHT_HEAL + 3), NULL)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("medium aoe heal", NextAction::array(0, new NextAction("circle of healing", 27.0f), NULL)));
|
||||
new TriggerNode("group heal setting", NextAction::array(0, new NextAction("circle of healing on party", 27.0f), NULL)));
|
||||
}
|
||||
|
||||
void PriestBuffStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
@@ -29,7 +29,7 @@ public:
|
||||
creators["lesser heal on party"] = &lesser_heal_on_party;
|
||||
creators["flash heal"] = &flash_heal;
|
||||
creators["flash heal on party"] = &flash_heal_on_party;
|
||||
creators["circle of healing"] = &circle_of_healing;
|
||||
creators["circle of healing on party"] = &circle_of_healing;
|
||||
creators["prayer of fortitude on party"] = &prayer_of_fortitude_on_party;
|
||||
creators["prayer of spirit on party"] = &prayer_of_spirit_on_party;
|
||||
}
|
||||
@@ -128,7 +128,7 @@ private:
|
||||
}
|
||||
static ActionNode* circle_of_healing(PlayerbotAI* ai)
|
||||
{
|
||||
return new ActionNode("circle of healing",
|
||||
return new ActionNode("circle of healing on party",
|
||||
/*P*/ NextAction::array(0, new NextAction("remove shadowform"), NULL),
|
||||
// /*A*/ NextAction::array(0, new NextAction("flash heal on party"), NULL),
|
||||
/*A*/ NULL,
|
||||
|
||||
@@ -51,8 +51,8 @@ void CasterShamanStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
// triggers.push_back(new TriggerNode("enemy out of spell", NextAction::array(0, new NextAction("reach spell",
|
||||
// ACTION_NORMAL + 9), nullptr))); triggers.push_back(new TriggerNode("shaman weapon", NextAction::array(0, new
|
||||
// NextAction("flametongue weapon", 23.0f), nullptr)));
|
||||
// triggers.push_back(new TriggerNode(
|
||||
// "enough mana", NextAction::array(0, new NextAction("chain lightning", ACTION_DEFAULT + 0.1f), nullptr)));
|
||||
triggers.push_back(new TriggerNode(
|
||||
"enough mana", NextAction::array(0, new NextAction("chain lightning", ACTION_DEFAULT + 0.1f), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode("main hand weapon no imbue",
|
||||
NextAction::array(0, new NextAction("flametongue weapon", 22.0f), nullptr)));
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* and/or modify it under version 2 of the License, or (at your option), any later version.
|
||||
*/
|
||||
|
||||
#include "GenericShamanStrategy.h"
|
||||
#include "HealShamanStrategy.h"
|
||||
#include "Playerbots.h"
|
||||
#include "Strategy.h"
|
||||
@@ -17,7 +18,7 @@ public:
|
||||
creators["windfury weapon"] = &windfury_weapon;
|
||||
creators["lesser healing wave"] = &lesser_healing_wave;
|
||||
creators["lesser healing wave on party"] = &lesser_healing_wave_on_party;
|
||||
creators["chain heal"] = &chain_heal;
|
||||
creators["chain heal on party"] = &chain_heal;
|
||||
creators["riptide"] = &riptide;
|
||||
creators["riptide on party"] = &riptide_on_party;
|
||||
creators["earth shock"] = &earth_shock;
|
||||
@@ -74,9 +75,9 @@ private:
|
||||
|
||||
static ActionNode* chain_heal([[maybe_unused]] PlayerbotAI* botAI)
|
||||
{
|
||||
return new ActionNode("chain heal",
|
||||
return new ActionNode("chain heal on party",
|
||||
/*P*/ nullptr,
|
||||
/*A*/ NextAction::array(0, new NextAction("lesser healing wave"), nullptr),
|
||||
/*A*/ NextAction::array(0, new NextAction("lesser healing wave on party"), nullptr),
|
||||
/*C*/ nullptr);
|
||||
}
|
||||
|
||||
@@ -116,7 +117,7 @@ void GenericShamanStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
// triggers.push_back(new TriggerNode("party member medium health", NextAction::array(0, new NextAction("lesser
|
||||
// healing wave on party", 25.0f), nullptr))); triggers.push_back(new TriggerNode("party member low health",
|
||||
// NextAction::array(0, new NextAction("riptide on party", 25.0f), nullptr))); triggers.push_back(new
|
||||
// TriggerNode("medium aoe heal", NextAction::array(0, new NextAction("chain heal", 27.0f), nullptr)));
|
||||
// TriggerNode("medium aoe heal", NextAction::array(0, new NextAction("chain heal on party", 27.0f), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("medium health", NextAction::array(0, new NextAction("lesser healing
|
||||
// wave", 26.0f), nullptr))); triggers.push_back(new TriggerNode("low health", NextAction::array(0, new
|
||||
// NextAction("riptide", 26.0f), nullptr)));
|
||||
@@ -162,3 +163,18 @@ void ShamanCureStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
new TriggerNode("party member cleanse spirit curse",
|
||||
NextAction::array(0, new NextAction("cleanse spirit curse on party", 23.0f), nullptr)));
|
||||
}
|
||||
|
||||
void ShamanHealerDpsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(
|
||||
new TriggerNode("healer should attack",
|
||||
NextAction::array(0,
|
||||
new NextAction("flame shock", ACTION_DEFAULT + 0.2f),
|
||||
new NextAction("lava burst", ACTION_DEFAULT + 0.1f),
|
||||
new NextAction("lightning bolt", ACTION_DEFAULT), nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("medium aoe and healer should attack",
|
||||
NextAction::array(0,
|
||||
new NextAction("chain lightning", ACTION_DEFAULT + 0.3f), nullptr)));
|
||||
}
|
||||
@@ -45,4 +45,13 @@ public:
|
||||
std::string const getName() override { return "cure"; }
|
||||
};
|
||||
|
||||
class ShamanHealerDpsStrategy : public Strategy
|
||||
{
|
||||
public:
|
||||
ShamanHealerDpsStrategy(PlayerbotAI* botAI) : Strategy(botAI) {}
|
||||
|
||||
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
|
||||
std::string const getName() override { return "healer dps"; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -49,8 +49,8 @@ void HealShamanStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
triggers.push_back(new TriggerNode("main hand weapon no imbue",
|
||||
NextAction::array(0, new NextAction("earthliving weapon", 22.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode(
|
||||
"group heal occasion",
|
||||
NextAction::array(0, new NextAction("riptide on party", 23.0f), new NextAction("chain heal", 22.0f), NULL)));
|
||||
"group heal setting",
|
||||
NextAction::array(0, new NextAction("riptide on party", 23.0f), new NextAction("chain heal on party", 22.0f), NULL)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"party member critical health",
|
||||
|
||||
@@ -42,11 +42,11 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class CastChainHealAction : public CastAoeHealSpellAction
|
||||
class CastChainHealAction : public HealPartyMemberAction
|
||||
{
|
||||
public:
|
||||
CastChainHealAction(PlayerbotAI* botAI)
|
||||
: CastAoeHealSpellAction(botAI, "chain heal", 15.0f, HealingManaEfficiency::HIGH)
|
||||
: HealPartyMemberAction(botAI, "chain heal", 15.0f, HealingManaEfficiency::HIGH)
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -335,7 +335,7 @@ public:
|
||||
class CastFlameShockAction : public CastDebuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastFlameShockAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "flame shock", true) {}
|
||||
CastFlameShockAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "flame shock", true, 6.0f) {}
|
||||
};
|
||||
|
||||
class CastEarthShockAction : public CastSpellAction
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "ShamanAiObjectContext.h"
|
||||
|
||||
#include "CasterShamanStrategy.h"
|
||||
#include "GenericShamanStrategy.h"
|
||||
#include "HealShamanStrategy.h"
|
||||
#include "MeleeShamanStrategy.h"
|
||||
#include "NamedObjectContext.h"
|
||||
@@ -25,6 +26,7 @@ public:
|
||||
creators["melee aoe"] = &ShamanStrategyFactoryInternal::melee_aoe;
|
||||
creators["caster aoe"] = &ShamanStrategyFactoryInternal::caster_aoe;
|
||||
creators["cure"] = &ShamanStrategyFactoryInternal::cure;
|
||||
creators["healer dps"] = &ShamanStrategyFactoryInternal::healer_dps;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -33,6 +35,7 @@ private:
|
||||
static Strategy* melee_aoe(PlayerbotAI* botAI) { return new MeleeAoeShamanStrategy(botAI); }
|
||||
static Strategy* caster_aoe(PlayerbotAI* botAI) { return new CasterAoeShamanStrategy(botAI); }
|
||||
static Strategy* cure(PlayerbotAI* botAI) { return new ShamanCureStrategy(botAI); }
|
||||
static Strategy* healer_dps(PlayerbotAI* botAI) { return new ShamanHealerDpsStrategy(botAI); }
|
||||
};
|
||||
|
||||
class ShamanBuffStrategyFactoryInternal : public NamedObjectContext<Strategy>
|
||||
@@ -207,7 +210,7 @@ public:
|
||||
creators["lesser healing wave on party"] = &ShamanAiObjectContextInternal::lesser_healing_wave_on_party;
|
||||
creators["earth shield"] = &ShamanAiObjectContextInternal::earth_shield;
|
||||
creators["earth shield on party"] = &ShamanAiObjectContextInternal::earth_shield_on_party;
|
||||
creators["chain heal"] = &ShamanAiObjectContextInternal::chain_heal;
|
||||
creators["chain heal on party"] = &ShamanAiObjectContextInternal::chain_heal;
|
||||
creators["riptide"] = &ShamanAiObjectContextInternal::riptide;
|
||||
creators["riptide on party"] = &ShamanAiObjectContextInternal::riptide_on_party;
|
||||
creators["stormstrike"] = &ShamanAiObjectContextInternal::stormstrike;
|
||||
|
||||
@@ -39,7 +39,7 @@ void ShamanNonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
new NextAction("lesser healing wave on party", 24.0f), NULL)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("medium aoe heal", NextAction::array(0, new NextAction("chain heal", 27.0f), NULL)));
|
||||
new TriggerNode("group heal setting", NextAction::array(0, new NextAction("chain heal on party", 27.0f), NULL)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("cure poison", NextAction::array(0, new NextAction("cure poison", 21.0f), nullptr)));
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
#include "BattlegroundWS.h"
|
||||
#include "CreatureAI.h"
|
||||
#include "GameTime.h"
|
||||
#include "LastSpellCastValue.h"
|
||||
#include "ObjectGuid.h"
|
||||
#include "PlayerbotAIConfig.h"
|
||||
#include "Playerbots.h"
|
||||
@@ -76,7 +78,7 @@ bool AlmostFullManaTrigger::IsActive()
|
||||
|
||||
bool EnoughManaTrigger::IsActive()
|
||||
{
|
||||
return AI_VALUE2(bool, "has mana", "self target") && AI_VALUE2(uint8, "mana", "self target") > 65;
|
||||
return AI_VALUE2(bool, "has mana", "self target") && AI_VALUE2(uint8, "mana", "self target") > sPlayerbotAIConfig->highMana;
|
||||
}
|
||||
|
||||
bool RageAvailable::IsActive() { return AI_VALUE2(uint8, "rage", "self target") >= amount; }
|
||||
@@ -366,6 +368,39 @@ bool GenericBoostTrigger::IsActive()
|
||||
return AI_VALUE(uint8, "balance") <= balance;
|
||||
}
|
||||
|
||||
bool HealerShouldAttackTrigger::IsActive()
|
||||
{
|
||||
// nobody can help me
|
||||
if (botAI->GetNearGroupMemberCount(sPlayerbotAIConfig->sightDistance) <= 1)
|
||||
return true;
|
||||
|
||||
if (AI_VALUE2(uint8, "health", "party member to heal") < sPlayerbotAIConfig->almostFullHealth)
|
||||
return false;
|
||||
|
||||
// special check for resto druid (dont remove tree of life frequently)
|
||||
if (bot->GetAura(33891))
|
||||
{
|
||||
LastSpellCast& lastSpell = botAI->GetAiObjectContext()->GetValue<LastSpellCast&>("last spell cast")->Get();
|
||||
if (lastSpell.timer + 5 > time(nullptr))
|
||||
return false;
|
||||
}
|
||||
|
||||
int manaThreshold;
|
||||
int balance = AI_VALUE(uint8, "balance");
|
||||
// higher threshold in higher pressure
|
||||
if (balance <= 50)
|
||||
manaThreshold = 85;
|
||||
else if (balance <= 100)
|
||||
manaThreshold = sPlayerbotAIConfig->highMana;
|
||||
else
|
||||
manaThreshold = sPlayerbotAIConfig->mediumMana;
|
||||
|
||||
if (AI_VALUE2(bool, "has mana", "self target") && AI_VALUE2(uint8, "mana", "self target") < manaThreshold)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ItemCountTrigger::IsActive() { return AI_VALUE2(uint32, "item count", item) < count; }
|
||||
|
||||
bool InterruptSpellTrigger::IsActive()
|
||||
|
||||
@@ -459,6 +459,16 @@ protected:
|
||||
float balance;
|
||||
};
|
||||
|
||||
class HealerShouldAttackTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
HealerShouldAttackTrigger(PlayerbotAI* botAI)
|
||||
: Trigger(botAI, "healer should attack", 1)
|
||||
{
|
||||
}
|
||||
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class RandomTrigger : public Trigger
|
||||
{
|
||||
|
||||
@@ -24,7 +24,18 @@ bool AoeHealTrigger::IsActive() { return AI_VALUE2(uint8, "aoe heal", type) >= c
|
||||
|
||||
bool AoeInGroupTrigger::IsActive()
|
||||
{
|
||||
Group* group = bot->GetGroup();
|
||||
return group && group->GetMembersCount() >= 5 &&
|
||||
AI_VALUE2(uint8, "aoe heal", type) >= (group->GetMembersCount() * ratio);
|
||||
int32 member = botAI->GetNearGroupMemberCount();
|
||||
if (member < 5)
|
||||
return false;
|
||||
int threshold = member * 0.5;
|
||||
if (member <= 5)
|
||||
threshold = 3;
|
||||
else if (member <= 10)
|
||||
threshold = std::min(threshold, 5);
|
||||
else if (member <= 25)
|
||||
threshold = std::min(threshold, 10);
|
||||
else
|
||||
threshold = std::min(threshold, 15);
|
||||
|
||||
return AI_VALUE2(uint8, "aoe heal", type) >= threshold;
|
||||
}
|
||||
@@ -186,14 +186,13 @@ protected:
|
||||
class AoeInGroupTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
AoeInGroupTrigger(PlayerbotAI* ai, std::string name, std::string type, float ratio)
|
||||
: Trigger(ai, name), ratio(ratio), type(type)
|
||||
AoeInGroupTrigger(PlayerbotAI* ai, std::string name, std::string type)
|
||||
: Trigger(ai, name), type(type)
|
||||
{
|
||||
}
|
||||
bool IsActive() override;
|
||||
|
||||
protected:
|
||||
float ratio;
|
||||
std::string type;
|
||||
};
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ public:
|
||||
creators["almost full mana"] = &TriggerContext::AlmostFullMana;
|
||||
creators["enough mana"] = &TriggerContext::EnoughMana;
|
||||
|
||||
|
||||
creators["party member critical health"] = &TriggerContext::PartyMemberCriticalHealth;
|
||||
creators["party member low health"] = &TriggerContext::PartyMemberLowHealth;
|
||||
creators["party member medium health"] = &TriggerContext::PartyMemberMediumHealth;
|
||||
@@ -83,6 +84,9 @@ public:
|
||||
creators["medium aoe"] = &TriggerContext::MediumAoe;
|
||||
creators["high aoe"] = &TriggerContext::HighAoe;
|
||||
|
||||
creators["healer should attack"] = &TriggerContext::healer_should_attack;
|
||||
creators["medium aoe and healer should attack"] = &TriggerContext::medium_aoe_and_healer_should_attack;
|
||||
|
||||
creators["has area debuff"] = &TriggerContext::HasAreaDebuff;
|
||||
|
||||
creators["enemy out of melee"] = &TriggerContext::EnemyOutOfMelee;
|
||||
@@ -135,8 +139,8 @@ public:
|
||||
creators["medium aoe heal"] = &TriggerContext::medium_aoe_heal;
|
||||
creators["almost full aoe heal"] = &TriggerContext::almost_full_aoe_heal;
|
||||
|
||||
creators["group heal occasion"] = &TriggerContext::group_heal_occasion;
|
||||
creators["medium group heal occasion"] = &TriggerContext::medium_group_heal_occasion;
|
||||
creators["group heal setting"] = &TriggerContext::group_heal_occasion;
|
||||
creators["medium group heal setting"] = &TriggerContext::medium_group_heal_occasion;
|
||||
creators["invalid target"] = &TriggerContext::invalid_target;
|
||||
creators["lfg proposal active"] = &TriggerContext::lfg_proposal_active;
|
||||
|
||||
@@ -242,11 +246,11 @@ private:
|
||||
}
|
||||
static Trigger* group_heal_occasion(PlayerbotAI* ai)
|
||||
{
|
||||
return new AoeInGroupTrigger(ai, "group heal occasion", "almost full", 0.6);
|
||||
return new AoeInGroupTrigger(ai, "group heal setting", "almost full");
|
||||
}
|
||||
static Trigger* medium_group_heal_occasion(PlayerbotAI* ai)
|
||||
{
|
||||
return new AoeInGroupTrigger(ai, "group heal occasion", "medium", 0.6);
|
||||
return new AoeInGroupTrigger(ai, "medium group heal setting", "medium");
|
||||
}
|
||||
static Trigger* target_changed(PlayerbotAI* botAI) { return new TargetChangedTrigger(botAI); }
|
||||
static Trigger* swimming(PlayerbotAI* botAI) { return new IsSwimmingTrigger(botAI); }
|
||||
@@ -265,6 +269,8 @@ private:
|
||||
static Trigger* LightAoe(PlayerbotAI* botAI) { return new LightAoeTrigger(botAI); }
|
||||
static Trigger* MediumAoe(PlayerbotAI* botAI) { return new MediumAoeTrigger(botAI); }
|
||||
static Trigger* HighAoe(PlayerbotAI* botAI) { return new HighAoeTrigger(botAI); }
|
||||
static Trigger* healer_should_attack(PlayerbotAI* botAI) { return new HealerShouldAttackTrigger(botAI); }
|
||||
static Trigger* medium_aoe_and_healer_should_attack(PlayerbotAI* botAI) { return new TwoTriggers(botAI, "medium aoe", "healer should attack"); }
|
||||
static Trigger* HasAreaDebuff(PlayerbotAI* botAI) { return new HasAreaDebuffTrigger(botAI); }
|
||||
static Trigger* LoseAggro(PlayerbotAI* botAI) { return new LoseAggroTrigger(botAI); }
|
||||
static Trigger* HasAggro(PlayerbotAI* botAI) { return new HasAggroTrigger(botAI); }
|
||||
|
||||
@@ -94,7 +94,7 @@ uint8 BalancePercentValue::Calculate()
|
||||
level *= 3;
|
||||
break;
|
||||
case CREATURE_ELITE_WORLDBOSS:
|
||||
level *= 30;
|
||||
level *= 20;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ private:
|
||||
{
|
||||
return new ActionNode("summon felhunter",
|
||||
/*P*/ nullptr,
|
||||
/*A*/ NextAction::array(0, new NextAction("summon voidwalker"), nullptr),
|
||||
/*A*/ NextAction::array(0, new NextAction("summon succubus"), nullptr),
|
||||
/*C*/ nullptr);
|
||||
}
|
||||
static ActionNode* summon_felguard([[maybe_unused]] PlayerbotAI* botAI)
|
||||
|
||||
Reference in New Issue
Block a user