mage and paladin strategy port

This commit is contained in:
Yunfan Li
2023-06-03 20:16:35 +08:00
parent 0f483047e5
commit e68a22d968
26 changed files with 414 additions and 172 deletions

View File

@@ -278,7 +278,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
break;
case CLASS_MAGE:
if (tab == 0)
engine->addStrategies("arcane", "threat", nullptr);
engine->addStrategies("arcane", "arcane aoe", "threat", nullptr);
else if (tab == 1)
engine->addStrategies("fire", "fire aoe", "threat", nullptr);
else

View File

@@ -213,7 +213,7 @@ Value<Unit*>* CastDebuffSpellOnAttackerAction::GetTargetValue()
return context->GetValue<Unit*>("attacker without aura", spell);
}
CastBuffSpellAction::CastBuffSpellAction(PlayerbotAI* botAI, std::string const spell) : CastAuraSpellAction(botAI, spell)
CastBuffSpellAction::CastBuffSpellAction(PlayerbotAI* botAI, std::string const spell, bool checkIsOwner) : CastAuraSpellAction(botAI, spell, checkIsOwner)
{
range = botAI->GetRange("spell");
}
@@ -274,3 +274,9 @@ bool CastVehicleSpellAction::Execute(Event event)
uint32 spellId = AI_VALUE2(uint32, "vehicle spell id", spell);
return botAI->CastVehicleSpell(spellId, GetTarget());
}
Value<Unit*>* BuffOnMainTankAction::GetTargetValue()
{
return context->GetValue<Unit*>("main tank", spell);
}

View File

@@ -66,7 +66,7 @@ class CastDebuffSpellOnAttackerAction : public CastAuraSpellAction
class CastBuffSpellAction : public CastAuraSpellAction
{
public:
CastBuffSpellAction(PlayerbotAI* botAI, std::string const spell);
CastBuffSpellAction(PlayerbotAI* botAI, std::string const spell, bool checkIsOwner = false);
std::string const GetTargetName() override { return "self target"; }
};
@@ -322,4 +322,26 @@ class CastBladeSalvoAction : public CastVehicleSpellAction
CastBladeSalvoAction(PlayerbotAI* botAI) : CastVehicleSpellAction(botAI, "blade salvo") { }
};
class MainTankActionNameSupport {
public:
MainTankActionNameSupport(std::string spell)
{
name = std::string(spell) + " on main tank";
}
virtual std::string const getName() { return name; }
private:
std::string name;
};
class BuffOnMainTankAction : public CastBuffSpellAction, public MainTankActionNameSupport
{
public:
BuffOnMainTankAction(PlayerbotAI* ai, std::string spell, bool checkIsOwner = false) :
CastBuffSpellAction(ai, spell, checkIsOwner), MainTankActionNameSupport(spell) {}
public:
virtual Value<Unit*>* GetTargetValue();
virtual std::string const getName() { return MainTankActionNameSupport::getName(); }
};
#endif

View File

@@ -67,7 +67,7 @@ class CasterDruidStrategyActionNodeFactory : public NamedObjectFactory<ActionNod
{
return new ActionNode ("starfall",
/*P*/ NextAction::array(0, new NextAction("moonkin form"), nullptr),
/*A*/ NextAction::array(0, new NextAction("hurricane"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
}
@@ -104,7 +104,10 @@ CasterDruidStrategy::CasterDruidStrategy(PlayerbotAI* botAI) : GenericDruidStrat
NextAction** CasterDruidStrategy::getDefaultActions()
{
return NextAction::array(0, new NextAction("starfire", ACTION_NORMAL + 2), new NextAction("wrath", ACTION_NORMAL + 1), nullptr);
return NextAction::array(0,
new NextAction("starfall", ACTION_NORMAL + 3),
new NextAction("starfire", ACTION_NORMAL + 2),
new NextAction("wrath", ACTION_NORMAL + 1), nullptr);
}
void CasterDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
@@ -112,16 +115,13 @@ void CasterDruidStrategy::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_MOVE), nullptr)));
triggers.push_back(new TriggerNode("medium health", NextAction::array(0, new NextAction("regrowth", ACTION_MEDIUM_HEAL + 2), nullptr)));
triggers.push_back(new TriggerNode("party member medium health", NextAction::array(0, new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 1), nullptr)));
triggers.push_back(new TriggerNode("almost full health", NextAction::array(0, new NextAction("rejuvenation", ACTION_LIGHT_HEAL + 2), nullptr)));
triggers.push_back(new TriggerNode("party member almost full health", NextAction::array(0, new NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 1), nullptr)));
triggers.push_back(new TriggerNode("insect swarm", NextAction::array(0, new NextAction("insect swarm", ACTION_NORMAL + 5), nullptr)));
triggers.push_back(new TriggerNode("insect swarm", NextAction::array(0, new NextAction("insect swarm", ACTION_NORMAL + 5), nullptr)));
triggers.push_back(new TriggerNode("moonfire", NextAction::array(0, new NextAction("moonfire", ACTION_NORMAL + 4), nullptr)));
triggers.push_back(new TriggerNode("eclipse (solar)", NextAction::array(0, new NextAction("wrath", ACTION_NORMAL + 6), nullptr)));
triggers.push_back(new TriggerNode("eclipse (lunar)", NextAction::array(0, new NextAction("starfire", ACTION_NORMAL + 6), nullptr)));
triggers.push_back(new TriggerNode("moonfire", NextAction::array(0, new NextAction("moonfire", ACTION_NORMAL + 4), nullptr)));
triggers.push_back(new TriggerNode("critical health", NextAction::array(0, new NextAction("nature's grasp", ACTION_EMERGENCY), nullptr)));
triggers.push_back(new TriggerNode("medium mana", NextAction::array(0, new NextAction("innervate", ACTION_HIGH + 5), NULL)));
triggers.push_back(new TriggerNode("enemy too close for spell", NextAction::array(0, new NextAction("flee", 49.0f), NULL)));
}
void CasterDruidAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)

View File

@@ -48,13 +48,24 @@ ArcaneMageStrategy::ArcaneMageStrategy(PlayerbotAI* botAI) : GenericMageStrategy
NextAction** ArcaneMageStrategy::getDefaultActions()
{
return NextAction::array(0, new NextAction("arcane barrage", 10.0f), nullptr);
return NextAction::array(0, new NextAction("arcane blast", 10.0f), NULL);
}
void ArcaneMageStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
GenericMageStrategy::InitTriggers(triggers);
triggers.push_back(new TriggerNode("arcane blast", NextAction::array(0, new NextAction("arcane blast", 15.0f), nullptr)));
triggers.push_back(new TriggerNode("missile barrage", NextAction::array(0, new NextAction("arcane missiles", 15.0f), nullptr)));
triggers.push_back(new TriggerNode("arcane blast stack", NextAction::array(0, new NextAction("arcane missiles", 15.0f), NULL)));
}
void ArcaneMageAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
// triggers.push_back(new TriggerNode(
// "high aoe",
// NextAction::array(0, new NextAction("arcane explosion", 39.0f), NULL)));
triggers.push_back(new TriggerNode(
"medium aoe",
NextAction::array(0, new NextAction("blizzard", 40.0f), NULL)));
}

View File

@@ -19,4 +19,13 @@ class ArcaneMageStrategy : public GenericMageStrategy
NextAction** getDefaultActions() override;
};
class ArcaneMageAoeStrategy : public CombatStrategy
{
public:
ArcaneMageAoeStrategy(PlayerbotAI* ai) : CombatStrategy(ai) {}
public:
virtual void InitTriggers(std::vector<TriggerNode*>& triggers) override;
std::string const getName() override { return "arcane aoe"; }
};
#endif

View File

@@ -7,17 +7,17 @@
NextAction** FireMageStrategy::getDefaultActions()
{
return NextAction::array(0, new NextAction("scorch", 7.0f), new NextAction("fireball", 6.0f), new NextAction("fire blast", 5.0f), nullptr);
return NextAction::array(0, new NextAction("fireball", ACTION_NORMAL + 1), NULL);
}
void FireMageStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
GenericMageStrategy::InitTriggers(triggers);
triggers.push_back(new TriggerNode("pyroblast", NextAction::array(0, new NextAction("pyroblast", 10.0f), nullptr)));
// triggers.push_back(new TriggerNode("pyroblast", NextAction::array(0, new NextAction("pyroblast", 10.0f), nullptr)));
triggers.push_back(new TriggerNode("hot streak", NextAction::array(0, new NextAction("pyroblast", 25.0f), nullptr)));
triggers.push_back(new TriggerNode("combustion", NextAction::array(0, new NextAction("combustion", 50.0f), nullptr)));
triggers.push_back(new TriggerNode("enemy too close for spell", NextAction::array(0, new NextAction("dragon's breath", 70.0f), nullptr)));
// triggers.push_back(new TriggerNode("enemy too close for spell", NextAction::array(0, new NextAction("dragon's breath", 70.0f), nullptr)));
}
void FireMageAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)

View File

@@ -22,6 +22,7 @@ class MageStrategyFactoryInternal : public NamedObjectContext<Strategy>
creators["pull"] = &MageStrategyFactoryInternal::pull;
creators["fire aoe"] = &MageStrategyFactoryInternal::fire_aoe;
creators["frost aoe"] = &MageStrategyFactoryInternal::frost_aoe;
creators["arcane aoe"] = &MageStrategyFactoryInternal::arcane_aoe;
creators["cure"] = &MageStrategyFactoryInternal::cure;
creators["buff"] = &MageStrategyFactoryInternal::buff;
creators["boost"] = &MageStrategyFactoryInternal::boost;
@@ -33,6 +34,7 @@ class MageStrategyFactoryInternal : public NamedObjectContext<Strategy>
static Strategy* pull(PlayerbotAI* botAI) { return new PullStrategy(botAI, "shoot"); }
static Strategy* fire_aoe(PlayerbotAI* botAI) { return new FireMageAoeStrategy(botAI); }
static Strategy* frost_aoe(PlayerbotAI* botAI) { return new FrostMageAoeStrategy(botAI); }
static Strategy* arcane_aoe(PlayerbotAI* botAI) { return new ArcaneMageAoeStrategy(botAI); }
static Strategy* cure(PlayerbotAI* botAI) { return new MageCureStrategy(botAI); }
static Strategy* buff(PlayerbotAI* botAI) { return new MageBuffStrategy(botAI); }
static Strategy* boost(PlayerbotAI* botAI) { return new MageBoostStrategy(botAI); }
@@ -95,7 +97,7 @@ class MageTriggerFactoryInternal : public NamedObjectContext<Trigger>
creators["presence of mind"] = &MageTriggerFactoryInternal::presence_of_mind;
creators["fire ward"] = &MageTriggerFactoryInternal::fire_ward;
creators["frost ward"] = &MageTriggerFactoryInternal::frost_ward;
creators["arcane blast stack"] = &MageTriggerFactoryInternal::arcane_blast_stack;
}
private:
@@ -120,6 +122,7 @@ class MageTriggerFactoryInternal : public NamedObjectContext<Trigger>
static Trigger* missile_barrage(PlayerbotAI* botAI) { return new MissileBarrageTrigger(botAI); }
static Trigger* arcane_blast(PlayerbotAI* botAI) { return new ArcaneBlastTrigger(botAI); }
static Trigger* counterspell_enemy_healer(PlayerbotAI* botAI) { return new CounterspellEnemyHealerTrigger(botAI); }
static Trigger* arcane_blast_stack(PlayerbotAI* botAI) { return new ArcaneBlastStackTrigger(botAI); }
};
class MageAiObjectContextInternal : public NamedObjectContext<Action>

View File

@@ -133,4 +133,8 @@ class PresenceOfMindTrigger : public BuffTrigger
PresenceOfMindTrigger(PlayerbotAI* botAI) : BuffTrigger(botAI, "presence of mind") { }
};
class ArcaneBlastStackTrigger : public HasAuraStackTrigger {
public:
ArcaneBlastStackTrigger(PlayerbotAI* ai) : HasAuraStackTrigger(ai, "arcane blast", 3, 1) {}
};
#endif

View File

@@ -69,7 +69,12 @@ DpsPaladinStrategy::DpsPaladinStrategy(PlayerbotAI* botAI) : GenericPaladinStrat
NextAction** DpsPaladinStrategy::getDefaultActions()
{
return NextAction::array(0, new NextAction("crusader strike", ACTION_NORMAL + 1), nullptr);
return NextAction::array(0, new NextAction("crusader strike", ACTION_NORMAL + 6),
new NextAction("judgement of wisdom", ACTION_NORMAL + 5),
new NextAction("divine storm", ACTION_NORMAL + 4),
new NextAction("consecration", ACTION_NORMAL + 3),
new NextAction("melee", ACTION_NORMAL),
NULL);
}
void DpsPaladinStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
@@ -79,14 +84,21 @@ void DpsPaladinStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
triggers.push_back(new TriggerNode("seal", NextAction::array(0, new NextAction("seal of command", 90.0f), nullptr)));
triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("seal of wisdom", 91.0f), nullptr)));
triggers.push_back(new TriggerNode("sanctity aura", NextAction::array(0, new NextAction("sanctity aura", 90.0f), nullptr)));
triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("repentance or shield", ACTION_CRITICAL_HEAL + 3), new NextAction("holy light", ACTION_CRITICAL_HEAL + 2), nullptr)));
triggers.push_back(new TriggerNode("judgement of wisdom", NextAction::array(0, new NextAction("judgement of wisdom", ACTION_NORMAL + 10), nullptr)));
triggers.push_back(new TriggerNode("judgement", NextAction::array(0, new NextAction("judgement", ACTION_HIGH + 10), nullptr)));
triggers.push_back(new TriggerNode("enemy is close", NextAction::array(0, new NextAction("consecration", ACTION_INTERRUPT), nullptr)));
triggers.push_back(new TriggerNode("repentance on enemy healer", NextAction::array(0, new NextAction("repentance on enemy healer", ACTION_INTERRUPT + 2), nullptr)));
triggers.push_back(new TriggerNode("repentance on snare target", NextAction::array(0, new NextAction("repentance on snare target", ACTION_INTERRUPT + 2), nullptr)));
triggers.push_back(new TriggerNode("repentance", NextAction::array(0, new NextAction("repentance", ACTION_INTERRUPT + 2), nullptr)));
triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("divine storm", ACTION_HIGH + 1), new NextAction("consecration", ACTION_HIGH + 1), nullptr)));
// triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("repentance or shield", ACTION_CRITICAL_HEAL + 3), new NextAction("holy light", ACTION_CRITICAL_HEAL + 2), nullptr)));
// triggers.push_back(new TriggerNode("judgement of wisdom", NextAction::array(0, new NextAction("judgement of wisdom", ACTION_NORMAL + 10), nullptr)));
// triggers.push_back(new TriggerNode("judgement", NextAction::array(0, new NextAction("judgement", ACTION_HIGH + 10), nullptr)));
// triggers.push_back(new TriggerNode("enemy is close", NextAction::array(0, new NextAction("consecration", ACTION_INTERRUPT), nullptr)));
// triggers.push_back(new TriggerNode("repentance on enemy healer", NextAction::array(0, new NextAction("repentance on enemy healer", ACTION_INTERRUPT + 2), nullptr)));
// triggers.push_back(new TriggerNode("repentance on snare target", NextAction::array(0, new NextAction("repentance on snare target", ACTION_INTERRUPT + 2), nullptr)));
// triggers.push_back(new TriggerNode("repentance", NextAction::array(0, new NextAction("repentance", ACTION_INTERRUPT + 2), nullptr)));
// triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("divine storm", ACTION_HIGH + 1), new NextAction("consecration", ACTION_HIGH + 1), nullptr)));
triggers.push_back(new TriggerNode("art of war", NextAction::array(0, new NextAction("exorcism", ACTION_HIGH + 2), nullptr)));
triggers.push_back(new TriggerNode("target critical health", NextAction::array(0, new NextAction("hammer of wrath", ACTION_CRITICAL_HEAL), nullptr)));
triggers.push_back(new TriggerNode(
"not facing target",
NextAction::array(0, new NextAction("set facing", ACTION_NORMAL + 7), NULL)));
triggers.push_back(new TriggerNode(
"enemy out of melee",
NextAction::array(0, new NextAction("reach melee", ACTION_NORMAL + 8), NULL)));
}

View File

@@ -16,6 +16,9 @@ void GenericPaladinNonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& tr
NonCombatStrategy::InitTriggers(triggers);
triggers.push_back(new TriggerNode("party member dead", NextAction::array(0, new NextAction("redemption", 30.0f), nullptr)));
triggers.push_back(new TriggerNode("almost full health", NextAction::array(0, new NextAction("flash of light", 23.0f), nullptr)));
triggers.push_back(new TriggerNode("party member almost full health", NextAction::array(0, new NextAction("flash of light on party", 24.0f), nullptr)));
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)));
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", NextAction::array(0, new NextAction("holy light on party", 28.0f), NULL)));
}

View File

@@ -22,6 +22,9 @@ void GenericPaladinStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
triggers.push_back(new TriggerNode("critical health", NextAction::array(0, new NextAction("lay on hands", ACTION_EMERGENCY), nullptr)));
triggers.push_back(new TriggerNode("party member critical health", NextAction::array(0, new NextAction("lay on hands on party", ACTION_EMERGENCY + 1), nullptr)));
triggers.push_back(new TriggerNode("protect party member", NextAction::array(0, new NextAction("blessing of protection on party", ACTION_EMERGENCY + 2), nullptr)));
triggers.push_back(new TriggerNode(
"medium mana",
NextAction::array(0, new NextAction("divine plea", ACTION_HIGH), NULL)));
}
void PaladinCureStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)

View File

@@ -24,6 +24,7 @@ class GenericPaladinStrategyActionNodeFactory : public NamedObjectFactory<Action
creators["seal of wisdom"] = &seal_of_wisdom;
creators["seal of justice"] = &seal_of_justice;
creators["hand of reckoning"] = &hand_of_reckoning;
creators["judgement"] = &judgement;
creators["judgement of wisdom"] = &judgement_of_wisdom;
creators["divine shield"] = &divine_shield;
creators["flash of light"] = &flash_of_light;
@@ -38,189 +39,200 @@ class GenericPaladinStrategyActionNodeFactory : public NamedObjectFactory<Action
creators["blessing of kings on party"] = &blessing_of_kings_on_party;
creators["blessing of wisdom on party"] = &blessing_of_wisdom_on_party;
creators["blessing of sanctuary"] = &blessing_of_sanctuary;
creators["seal of command"] = &seal_of_command;
creators["taunt spell"] = &hand_of_reckoning;
creators["righteous defense"] = &righteous_defense;
creators["avenger's shield"] = &avengers_shield;
}
private:
static ActionNode* blessing_of_sanctuary(PlayerbotAI* botAI)
static ActionNode* blessing_of_sanctuary(PlayerbotAI* ai)
{
return new ActionNode ("blessing of sanctuary",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ NULL,
/*A*/ NULL,
/*C*/ NULL);
}
static ActionNode* blessing_of_kings(PlayerbotAI* botAI)
static ActionNode* blessing_of_kings(PlayerbotAI* ai)
{
return new ActionNode ("blessing of kings",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ NULL,
/*A*/ NULL,
/*C*/ NULL);
}
static ActionNode* blessing_of_wisdom(PlayerbotAI* botAI)
static ActionNode* blessing_of_wisdom(PlayerbotAI* ai)
{
return new ActionNode ("blessing of wisdom",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ NULL,
/*A*/ NULL,
/*C*/ NULL);
}
static ActionNode* blessing_of_kings_on_party(PlayerbotAI* botAI)
static ActionNode* blessing_of_kings_on_party(PlayerbotAI* ai)
{
return new ActionNode ("blessing of kings on party",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ NULL,
/*A*/ NULL,
/*C*/ NULL);
}
static ActionNode* blessing_of_wisdom_on_party(PlayerbotAI* botAI)
static ActionNode* blessing_of_wisdom_on_party(PlayerbotAI* ai)
{
return new ActionNode ("blessing of wisdom on party",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ NULL,
/*A*/ NULL,
/*C*/ NULL);
}
static ActionNode* retribution_aura(PlayerbotAI* botAI)
static ActionNode* retribution_aura(PlayerbotAI* ai)
{
return new ActionNode ("retribution aura",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("devotion aura"), nullptr),
/*C*/ nullptr);
/*P*/ NULL,
/*A*/ NextAction::array(0, new NextAction("devotion aura"), NULL),
/*C*/ NULL);
}
static ActionNode* lay_on_hands(PlayerbotAI* botAI)
static ActionNode* lay_on_hands(PlayerbotAI* ai)
{
return new ActionNode ("lay on hands",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("divine shield"), new NextAction("flash of light"), nullptr),
/*C*/ nullptr);
/*P*/ NULL,
/*A*/ NULL, // NextAction::array(0, new NextAction("divine shield"), new NextAction("flash of light"), NULL),
/*C*/ NULL);
}
static ActionNode* lay_on_hands_on_party(PlayerbotAI* botAI)
static ActionNode* lay_on_hands_on_party(PlayerbotAI* ai)
{
return new ActionNode ("lay on hands on party",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("flash of light on party"), nullptr),
/*C*/ nullptr);
/*P*/ NULL,
/*A*/ NULL, // NextAction::array(0, new NextAction("flash of light"), NULL),
/*C*/ NULL);
}
static ActionNode* seal_of_light(PlayerbotAI* botAI)
static ActionNode* seal_of_light(PlayerbotAI* ai)
{
return new ActionNode ("seal of light",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("seal of justice"), nullptr),
/*C*/ nullptr);
/*P*/ NULL,
/*A*/ NextAction::array(0, new NextAction("seal of justice"), NULL),
/*C*/ NULL);
}
static ActionNode* cleanse_poison(PlayerbotAI* botAI)
static ActionNode* cleanse_poison(PlayerbotAI* ai)
{
return new ActionNode ("cleanse poison",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("purify poison"), nullptr),
/*C*/ nullptr);
/*P*/ NULL,
/*A*/ NextAction::array(0, new NextAction("purify poison"), NULL),
/*C*/ NULL);
}
static ActionNode* cleanse_magic(PlayerbotAI* botAI)
static ActionNode* cleanse_magic(PlayerbotAI* ai)
{
return new ActionNode ("cleanse magic",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
/*P*/ NULL,
/*A*/ NULL,
/*C*/ NULL);
}
static ActionNode* cleanse_disease(PlayerbotAI* botAI)
static ActionNode* cleanse_disease(PlayerbotAI* ai)
{
return new ActionNode ("cleanse disease",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("purify disease"), nullptr),
/*C*/ nullptr);
/*P*/ NULL,
/*A*/ NextAction::array(0, new NextAction("purify disease"), NULL),
/*C*/ NULL);
}
static ActionNode* cleanse_poison_on_party(PlayerbotAI* botAI)
static ActionNode* cleanse_poison_on_party(PlayerbotAI* ai)
{
return new ActionNode ("cleanse poison on party",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("purify poison on party"), nullptr),
/*C*/ nullptr);
/*P*/ NULL,
/*A*/ NextAction::array(0, new NextAction("purify poison on party"), NULL),
/*C*/ NULL);
}
static ActionNode* cleanse_disease_on_party(PlayerbotAI* botAI)
static ActionNode* cleanse_disease_on_party(PlayerbotAI* ai)
{
return new ActionNode ("cleanse disease on party",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("purify disease on party"), nullptr),
/*C*/ nullptr);
/*P*/ NULL,
/*A*/ NextAction::array(0, new NextAction("purify disease on party"), NULL),
/*C*/ NULL);
}
static ActionNode* seal_of_wisdom(PlayerbotAI* botAI)
static ActionNode* seal_of_wisdom(PlayerbotAI* ai)
{
return new ActionNode ("seal of wisdom",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("seal of justice"), nullptr),
/*C*/ nullptr);
/*P*/ NULL,
/*A*/ NextAction::array(0, new NextAction("seal of justice"), NULL),
/*C*/ NULL);
}
static ActionNode* seal_of_justice(PlayerbotAI* botAI)
static ActionNode* seal_of_justice(PlayerbotAI* ai)
{
return new ActionNode ("seal of justice",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("seal of righteousness"), nullptr),
/*C*/ nullptr);
/*P*/ NULL,
/*A*/ NextAction::array(0, new NextAction("seal of righteousness"), NULL),
/*C*/ NULL);
}
static ActionNode* hand_of_reckoning(PlayerbotAI* botAI)
static ActionNode* hand_of_reckoning(PlayerbotAI* ai)
{
return new ActionNode ("hand of reckoning",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("judgement of justice"), nullptr),
/*C*/ nullptr);
/*P*/ NULL,
/*A*/ NextAction::array(0, new NextAction("righteous defense"), NULL),
/*C*/ NULL);
}
static ActionNode* judgement_of_wisdom(PlayerbotAI* botAI)
static ActionNode* righteous_defense(PlayerbotAI* ai)
{
return new ActionNode ("righteous defense",
/*P*/ NULL,
/*A*/ NextAction::array(0, new NextAction("avenger's shield"), NULL),
/*C*/ NULL);
}
static ActionNode* avengers_shield(PlayerbotAI* ai)
{
return new ActionNode ("righteous defense",
/*P*/ NULL,
/*A*/ NextAction::array(0, new NextAction("judgement of wisdom"), NULL),
/*C*/ NULL);
}
static ActionNode* judgement_of_wisdom(PlayerbotAI* ai)
{
return new ActionNode ("judgement of wisdom",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("judgement of light"), nullptr),
/*C*/ nullptr);
/*P*/ NULL,
/*A*/ NextAction::array(0, new NextAction("judgement of light"), NULL),
/*C*/ NULL);
}
static ActionNode* divine_shield(PlayerbotAI* botAI)
static ActionNode* judgement(PlayerbotAI* ai)
{
return new ActionNode ("judgement",
/*P*/ NULL,
/*A*/ NULL,
/*C*/ NULL);
}
static ActionNode* divine_shield(PlayerbotAI* ai)
{
return new ActionNode ("divine shield",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("divine protection"), nullptr),
/*C*/ nullptr);
/*P*/ NULL,
/*A*/ NextAction::array(0, new NextAction("divine protection"), NULL),
/*C*/ NULL);
}
static ActionNode* flash_of_light(PlayerbotAI* botAI)
static ActionNode* flash_of_light(PlayerbotAI* ai)
{
return new ActionNode ("flash of light",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("holy light"), nullptr),
/*C*/ nullptr);
/*P*/ NULL,
/*A*/ NextAction::array(0, new NextAction("holy light"), NULL),
/*C*/ NULL);
}
static ActionNode* flash_of_light_on_party(PlayerbotAI* botAI)
static ActionNode* flash_of_light_on_party(PlayerbotAI* ai)
{
return new ActionNode ("flash of light on party",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("holy light on party"), nullptr),
/*C*/ nullptr);
/*P*/ NULL,
/*A*/ NextAction::array(0, new NextAction("holy light on party"), NULL),
/*C*/ NULL);
}
static ActionNode* holy_wrath(PlayerbotAI* botAI)
static ActionNode* holy_wrath(PlayerbotAI* ai)
{
return new ActionNode ("holy wrath",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("consecration"), nullptr),
/*C*/ nullptr);
/*P*/ NULL,
/*A*/ NextAction::array(0, new NextAction("consecration"), NULL),
/*C*/ NULL);
}
static ActionNode* hammer_of_wrath(PlayerbotAI* botAI)
static ActionNode* hammer_of_wrath(PlayerbotAI* ai)
{
return new ActionNode ("hammer of wrath",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("melee"), nullptr),
/*C*/ nullptr);
/*P*/ NULL,
/*A*/ NextAction::array(0, new NextAction("melee"), NULL),
/*C*/ NULL);
}
static ActionNode* seal_of_command(PlayerbotAI* ai)
{
return new ActionNode ("seal of command",
/*P*/ NULL,
/*A*/ NextAction::array(0, new NextAction("seal of righteousness"), NULL),
/*C*/ NULL);
}
};

View File

@@ -24,7 +24,8 @@ HealPaladinStrategy::HealPaladinStrategy(PlayerbotAI* botAI) : GenericPaladinStr
NextAction** HealPaladinStrategy::getDefaultActions()
{
return NextAction::array(0, new NextAction("reach party member to heal", ACTION_NORMAL + 1), new NextAction("judgement", ACTION_NORMAL), nullptr);
return NextAction::array(0, new NextAction("judgement of light", ACTION_NORMAL + 2),
new NextAction("reach party member to heal", ACTION_NORMAL + 1), nullptr);
}
void HealPaladinStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
@@ -32,16 +33,42 @@ void HealPaladinStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
GenericPaladinStrategy::InitTriggers(triggers);
triggers.push_back(new TriggerNode("concentration aura", NextAction::array(0, new NextAction("concentration aura", 90.0f), nullptr)));
triggers.push_back(new TriggerNode("seal", NextAction::array(0, new NextAction("seal of light", ACTION_HIGH), nullptr)));
triggers.push_back(new TriggerNode("enemy is close", NextAction::array(0, new NextAction("judgement of light", ACTION_HIGH + 10), nullptr)));
triggers.push_back(new TriggerNode("enemy is close", NextAction::array(0, new NextAction("judgement", ACTION_HIGH + 10), nullptr)));
triggers.push_back(new TriggerNode("seal", NextAction::array(0, new NextAction("seal of wisdom", ACTION_HIGH), nullptr)));
triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("divine favor", ACTION_HIGH + 1), nullptr)));
triggers.push_back(new TriggerNode("almost full health", NextAction::array(0, new NextAction("flash of light", ACTION_LIGHT_HEAL + 2), nullptr)));
triggers.push_back(new TriggerNode("party member almost full health", NextAction::array(0, new NextAction("flash of light on party", ACTION_LIGHT_HEAL + 1), nullptr)));
triggers.push_back(new TriggerNode("medium health", NextAction::array(0, new NextAction("flash of light", ACTION_MEDIUM_HEAL + 2), nullptr)));
triggers.push_back(new TriggerNode("party member medium health", NextAction::array(0, new NextAction("flash of light on party", ACTION_MEDIUM_HEAL + 1), nullptr)));
triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("divine favor", ACTION_MEDIUM_HEAL + 4), new NextAction("holy shock", ACTION_MEDIUM_HEAL + 3), new NextAction("holy light", ACTION_MEDIUM_HEAL + 2), nullptr)));
triggers.push_back(new TriggerNode("party member low health", NextAction::array(0, new NextAction("divine favor", ACTION_MEDIUM_HEAL + 7), new NextAction("holy shock on party", ACTION_MEDIUM_HEAL + 6), new NextAction("holy light on party", ACTION_MEDIUM_HEAL + 5), nullptr)));
triggers.push_back(new TriggerNode("blessing", NextAction::array(0, new NextAction("blessing of sanctuary", ACTION_HIGH + 9), nullptr)));
// triggers.push_back(new TriggerNode("blessing", NextAction::array(0, new NextAction("blessing of sanctuary", ACTION_HIGH + 9), 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_EMERGENCY + 3), nullptr)));
triggers.push_back(new TriggerNode(
"party member critical health",
NextAction::array(0,
new NextAction("holy shock on party", ACTION_CRITICAL_HEAL + 5),
new NextAction("holy light on party", ACTION_CRITICAL_HEAL + 4),
NULL)));
triggers.push_back(new TriggerNode(
"party member low health",
NextAction::array(0,
new NextAction("holy light on party", ACTION_MEDIUM_HEAL + 5),
NULL)));
triggers.push_back(new TriggerNode(
"party member medium health",
NextAction::array(0,
new NextAction("holy light on party", ACTION_LIGHT_HEAL + 9),
new NextAction("flash of light on party", ACTION_LIGHT_HEAL + 8),
NULL)));
triggers.push_back(new TriggerNode(
"party member almost full health",
NextAction::array(0,
new NextAction("flash of light on party", ACTION_LIGHT_HEAL + 3),
NULL)));
triggers.push_back(new TriggerNode(
"beacon of light on main tank",
NextAction::array(0, new NextAction("beacon of light on main tank", ACTION_CRITICAL_HEAL + 7), NULL)));
triggers.push_back(new TriggerNode(
"sacred shield on main tank",
NextAction::array(0, new NextAction("sacred shield on main tank", ACTION_CRITICAL_HEAL + 6), NULL)));
}

View File

@@ -17,7 +17,7 @@ class HealPaladinStrategy : public GenericPaladinStrategy
void InitTriggers(std::vector<TriggerNode*>& triggers) override;
std::string const getName() override { return "heal"; }
NextAction** getDefaultActions() override;
uint32 GetType() const override { return STRATEGY_TYPE_HEAL | STRATEGY_TYPE_MELEE; }
uint32 GetType() const override { return STRATEGY_TYPE_HEAL | STRATEGY_TYPE_RANGED; }
};
#endif

View File

@@ -77,7 +77,16 @@ bool CastSealSpellAction::isUseful()
return AI_VALUE2(bool, "combat", "self target");
}
Value<Unit*>* CastTurnUndeadAction:: GetTargetValue()
Value<Unit*>* CastTurnUndeadAction::GetTargetValue()
{
return context->GetValue<Unit*>("cc target", getName());
}
Unit* CastRighteousDefenseAction::GetTarget()
{
Unit* current_target = AI_VALUE(Unit*, "current target");
if (!current_target) {
return NULL;
}
return current_target->GetVictim();
}

View File

@@ -259,6 +259,7 @@ class CastRighteousDefenseAction : public CastSpellAction
{
public:
CastRighteousDefenseAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "righteous defense") { }
virtual Unit* GetTarget() override;
};
class CastCleansePoisonAction : public CastCureSpellAction
@@ -343,4 +344,27 @@ class CastTurnUndeadAction : public CastBuffSpellAction
PROTECT_ACTION(CastBlessingOfProtectionProtectAction, "blessing of protection");
class CastDivinePleaAction : public CastBuffSpellAction
{
public:
CastDivinePleaAction(PlayerbotAI* ai) : CastBuffSpellAction(ai, "divine plea") {}
};
class ShieldOfRighteousnessAction : public CastMeleeSpellAction
{
public:
ShieldOfRighteousnessAction(PlayerbotAI* ai) : CastMeleeSpellAction(ai, "shield of righteousness") {}
};
class CastBeaconOfLightOnMainTankAction : public BuffOnMainTankAction
{
public:
CastBeaconOfLightOnMainTankAction(PlayerbotAI* ai) : BuffOnMainTankAction(ai, "beacon of light", true) {}
};
class CastSacredShieldOnMainTankAction : public BuffOnMainTankAction
{
public:
CastSacredShieldOnMainTankAction(PlayerbotAI* ai) : BuffOnMainTankAction(ai, "sacred shield", false) {}
};
#endif

View File

@@ -126,6 +126,8 @@ class PaladinTriggerFactoryInternal : public NamedObjectContext<Trigger>
creators["repentance on enemy healer"] = &PaladinTriggerFactoryInternal::repentance_on_enemy_healer;
creators["repentance on snare target"] = &PaladinTriggerFactoryInternal::repentance_on_snare_target;
creators["repentance interrupt"] = &PaladinTriggerFactoryInternal::repentance_interrupt;
creators["beacon of light on main tank"] = &PaladinTriggerFactoryInternal::beacon_of_light_on_main_tank;
creators["sacred shield on main tank"] = &PaladinTriggerFactoryInternal::sacred_shield_on_main_tank;
}
private:
@@ -163,6 +165,8 @@ class PaladinTriggerFactoryInternal : public NamedObjectContext<Trigger>
static Trigger* repentance_on_enemy_healer(PlayerbotAI* botAI) { return new RepentanceOnHealerTrigger(botAI); }
static Trigger* repentance_on_snare_target(PlayerbotAI* botAI) { return new RepentanceSnareTrigger(botAI); }
static Trigger* repentance_interrupt(PlayerbotAI* botAI) { return new RepentanceInterruptTrigger(botAI); }
static Trigger* beacon_of_light_on_main_tank(PlayerbotAI* ai) { return new BeaconOfLightOnMainTankTrigger(ai); }
static Trigger* sacred_shield_on_main_tank(PlayerbotAI* ai) { return new SacredShieldOnMainTankTrigger(ai); }
};
class PaladinAiObjectContextInternal : public NamedObjectContext<Action>
@@ -238,6 +242,10 @@ class PaladinAiObjectContextInternal : public NamedObjectContext<Action>
creators["sanctity aura"] = &PaladinAiObjectContextInternal::sanctity_aura;
creators["holy shock"] = &PaladinAiObjectContextInternal::holy_shock;
creators["holy shock on party"] = &PaladinAiObjectContextInternal::holy_shock_on_party;
creators["divine plea"] = &PaladinAiObjectContextInternal::divine_plea;
creators["shield of righteousness"] = &PaladinAiObjectContextInternal::shield_of_righteousness;
creators["beacon of light on main tank"] = &PaladinAiObjectContextInternal::beacon_of_light_on_main_tank;
creators["sacred shield on main tank"] = &PaladinAiObjectContextInternal::sacred_shield_on_main_tank;
}
private:
@@ -309,6 +317,10 @@ class PaladinAiObjectContextInternal : public NamedObjectContext<Action>
static Action* sanctity_aura(PlayerbotAI* botAI) { return new CastSanctityAuraAction(botAI); }
static Action* holy_shock(PlayerbotAI* botAI) { return new CastHolyShockAction(botAI); }
static Action* holy_shock_on_party(PlayerbotAI* botAI) { return new CastHolyShockOnPartyAction(botAI); }
static Action* divine_plea(PlayerbotAI* ai) { return new CastDivinePleaAction(ai); }
static Action* shield_of_righteousness(PlayerbotAI* ai) { return new ShieldOfRighteousnessAction(ai); }
static Action* beacon_of_light_on_main_tank(PlayerbotAI* ai) { return new CastBeaconOfLightOnMainTankAction(ai); }
static Action* sacred_shield_on_main_tank(PlayerbotAI* ai) { return new CastSacredShieldOnMainTankAction(ai); }
};
PaladinAiObjectContext::PaladinAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI)

View File

@@ -160,4 +160,15 @@ class TurnUndeadTrigger : public HasCcTargetTrigger
DEBUFF_TRIGGER(AvengerShieldTrigger, "avenger's shield");
class BeaconOfLightOnMainTankTrigger : public BuffOnMainTankTrigger
{
public:
BeaconOfLightOnMainTankTrigger(PlayerbotAI* ai) : BuffOnMainTankTrigger(ai, "beacon of light", true) {}
};
class SacredShieldOnMainTankTrigger : public BuffOnMainTankTrigger
{
public:
SacredShieldOnMainTankTrigger(PlayerbotAI* ai) : BuffOnMainTankTrigger(ai, "sacred shield", false) {}
};
#endif

View File

@@ -33,7 +33,14 @@ TankPaladinStrategy::TankPaladinStrategy(PlayerbotAI* botAI) : GenericPaladinStr
NextAction** TankPaladinStrategy::getDefaultActions()
{
return NextAction::array(0, new NextAction("melee", ACTION_NORMAL), nullptr);
return NextAction::array(0,
new NextAction("shield of righteousness", ACTION_NORMAL + 6),
new NextAction("hammer of the righteous", ACTION_NORMAL + 5),
new NextAction("judgement of wisdom", ACTION_NORMAL + 4),
// new NextAction("avenger's shield", ACTION_NORMAL + 3),
// new NextAction("consecration", ACTION_NORMAL + 2),
new NextAction("melee", ACTION_NORMAL),
NULL);
}
void TankPaladinStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
@@ -42,16 +49,26 @@ void TankPaladinStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
triggers.push_back(new TriggerNode("seal", NextAction::array(0, new NextAction("seal of vengeance", 90.0f), NULL)));
triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("seal of wisdom", 91.0f), nullptr)));
triggers.push_back(new TriggerNode("judgement of light", NextAction::array(0, new NextAction("judgement of light", ACTION_HIGH + 6), nullptr)));
triggers.push_back(new TriggerNode("medium mana", NextAction::array(0, new NextAction("judgement of wisdom", ACTION_HIGH + 6), nullptr)));
triggers.push_back(new TriggerNode("judgement", NextAction::array(0, new NextAction("judgement", ACTION_HIGH + 6), nullptr)));
triggers.push_back(new TriggerNode("judgement", NextAction::array(0, new NextAction("exorcism", ACTION_HIGH + 6), nullptr)));
triggers.push_back(new TriggerNode("light aoe", NextAction::array(0, new NextAction("hammer of the righteous", ACTION_HIGH + 8), new NextAction("avenger's shield", ACTION_HIGH + 7), nullptr)));
// triggers.push_back(new TriggerNode("judgement of light", NextAction::array(0, new NextAction("judgement of light", ACTION_HIGH + 6), nullptr)));
// triggers.push_back(new TriggerNode("medium mana", NextAction::array(0, new NextAction("judgement of wisdom", ACTION_HIGH + 6), nullptr)));
// triggers.push_back(new TriggerNode("judgement", NextAction::array(0, new NextAction("judgement", ACTION_HIGH + 6), nullptr)));
// triggers.push_back(new TriggerNode("judgement", NextAction::array(0, new NextAction("exorcism", ACTION_HIGH + 6), nullptr)));
// triggers.push_back(new TriggerNode("light aoe", NextAction::array(0, new NextAction("hammer of the righteous", ACTION_HIGH + 8), new NextAction("avenger's shield", ACTION_HIGH + 7), nullptr)));
triggers.push_back(new TriggerNode(
"medium aoe",
NextAction::array(0, new NextAction("consecration", ACTION_HIGH + 1), new NextAction("avenger's shield", ACTION_HIGH + 3), NULL)));
triggers.push_back(new TriggerNode("avenger's shield", NextAction::array(0, new NextAction("avenger's shield", ACTION_HIGH + 7), nullptr)));
triggers.push_back(new TriggerNode("enemy is close", NextAction::array(0, new NextAction("consecration", ACTION_INTERRUPT), nullptr)));
triggers.push_back(new TriggerNode("lose aggro", NextAction::array(0, new NextAction("hand of reckoning", ACTION_HIGH + 7), nullptr)));
triggers.push_back(new TriggerNode("lose aggro", NextAction::array(0, new NextAction("exorcism", ACTION_HIGH + 8), nullptr)));
triggers.push_back(new TriggerNode("holy shield", NextAction::array(0, new NextAction("holy shield", ACTION_HIGH + 7), nullptr)));
triggers.push_back(new TriggerNode("blessing", NextAction::array(0, new NextAction("blessing of sanctuary", ACTION_HIGH + 9), nullptr)));
triggers.push_back(new TriggerNode("target critical health", NextAction::array(0, new NextAction("hammer of wrath", ACTION_CRITICAL_HEAL), nullptr)));
triggers.push_back(new TriggerNode(
"righteous fury",
NextAction::array(0, new NextAction("righteous fury", ACTION_HIGH + 8), NULL)));
triggers.push_back(new TriggerNode(
"not facing target",
NextAction::array(0, new NextAction("set facing", ACTION_NORMAL + 7), NULL)));
triggers.push_back(new TriggerNode(
"enemy out of melee",
NextAction::array(0, new NextAction("reach melee", ACTION_NORMAL + 8), NULL)));
}

View File

@@ -22,15 +22,6 @@ bool MediumManaTrigger::IsActive()
bool NoPetTrigger::IsActive()
{
// Guardian* gp = bot->GetGuardianPet();
// bot->getpet
// if (gp) {
// bot->Yell("Guardian name: " + gp->GetName(), LANG_UNIVERSAL);
// }
// Minion* minion = bot->GetFirstMinion();
// if (minion) {
// bot->Yell("has minion: " + minion->GetName(), LANG_UNIVERSAL);
// }
return (bot->GetMinionGUID().IsEmpty()) &&
(!AI_VALUE(Unit*, "pet target")) &&
(!bot->GetGuardianPet()) &&
@@ -351,6 +342,13 @@ bool HasAuraTrigger::IsActive()
return botAI->HasAura(getName(), GetTarget(), false, false, -1, true);
}
bool HasAuraStackTrigger::IsActive()
{
Aura *aura = botAI->GetAura(getName(), GetTarget(), false, true, stack);
// sLog->outMessage("playerbot", LOG_LEVEL_DEBUG, "HasAuraStackTrigger::IsActive %s %d", getName(), aura ? aura->GetStackAmount() : -1);
return aura;
}
bool TimerTrigger::IsActive()
{
if (time(nullptr) != lastCheck)
@@ -553,3 +551,8 @@ bool HasAreaDebuffTrigger::IsActive()
{
return AI_VALUE2(bool, "has area debuff", "self target");
}
Value<Unit*>* BuffOnMainTankTrigger::GetTargetValue()
{
return context->GetValue<Unit*>("main tank", spell);
}

View File

@@ -457,6 +457,17 @@ class HasAuraTrigger : public Trigger
};
class HasAuraStackTrigger : public Trigger {
public:
HasAuraStackTrigger(PlayerbotAI* ai, std::string spell, int stack, int checkInterval = 1) : Trigger(ai, spell, checkInterval),
stack(stack) {}
std::string const GetTargetName() { return "self target"; }
virtual bool IsActive();
private:
int stack;
};
class HasNoAuraTrigger : public Trigger
{
public:
@@ -720,4 +731,11 @@ class HasAreaDebuffTrigger : public Trigger {
bool IsActive() override;
};
class BuffOnMainTankTrigger : public BuffTrigger
{
public:
BuffOnMainTankTrigger(PlayerbotAI* botAI, std::string spell, bool checkIsOwner = false) : BuffTrigger(botAI, spell, 1, checkIsOwner) {}
public:
virtual Value<Unit*>* GetTargetValue();
};
#endif

View File

@@ -139,3 +139,27 @@ bool PartyMemberValue::IsTargetOfSpellCast(Player* target, SpellEntryPredicate &
return false;
}
class FindMainTankPlayer : public FindPlayerPredicate
{
public:
FindMainTankPlayer(PlayerbotAI* botAI) : botAI(botAI) {}
virtual bool Check(Unit* unit)
{
Player* player = unit->ToPlayer();
if (!player) {
return false;
}
return botAI->IsMainTank(player);
}
private:
PlayerbotAI* botAI;
};
Unit* PartyMemberMainTankValue::Calculate()
{
FindMainTankPlayer findMainTankPlayer(botAI);
return FindPartyMember(findMainTankPlayer);
}

View File

@@ -35,4 +35,11 @@ class PartyMemberValue : public UnitCalculatedValue
virtual bool Check(Unit* player);
};
class PartyMemberMainTankValue : public PartyMemberValue
{
public:
PartyMemberMainTankValue(PlayerbotAI* botAI) : PartyMemberValue(botAI) {}
virtual Unit* Calculate();
};
#endif

View File

@@ -285,6 +285,8 @@ class ValueContext : public NamedObjectContext<UntypedValue>
creators["RTSC saved location"] = &ValueContext::RTSC_saved_location;
creators["has area debuff"] = &ValueContext::has_area_debuff;
creators["main tank"] = &ValueContext::main_tank;
}
private:
@@ -475,6 +477,8 @@ class ValueContext : public NamedObjectContext<UntypedValue>
static UntypedValue* RTSC_saved_location(PlayerbotAI* botAI) { return new RTSCSavedLocationValue(botAI); }
static UntypedValue* has_area_debuff(PlayerbotAI* botAI) { return new HasAreaDebuffValue(botAI); }
static UntypedValue* main_tank(PlayerbotAI* ai) { return new PartyMemberMainTankValue(ai); }
};
#endif

View File

@@ -240,6 +240,7 @@ class CastDemonicEmpowermentAction : public CastBuffSpellAction
{
public:
CastDemonicEmpowermentAction(PlayerbotAI* ai) : CastBuffSpellAction(ai, "demonic empowerment") {}
std::string const GetTargetName() override { return "pet target"; }
};
class CastMetamorphosisAction : public CastBuffSpellAction