Mage improvement (fire mage aoe)

This commit is contained in:
Yunfan Li
2025-01-19 20:06:10 +08:00
parent a0e955d14b
commit bc33851189
13 changed files with 82 additions and 24 deletions

View File

@@ -31,7 +31,7 @@ private:
{ {
return new ActionNode("arcane barrage", return new ActionNode("arcane barrage",
/*P*/ nullptr, /*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("arcane missiles"), nullptr), /*A*/ nullptr,
/*C*/ nullptr); /*C*/ nullptr);
} }
@@ -59,8 +59,10 @@ ArcaneMageStrategy::ArcaneMageStrategy(PlayerbotAI* botAI) : GenericMageStrategy
NextAction** ArcaneMageStrategy::getDefaultActions() NextAction** ArcaneMageStrategy::getDefaultActions()
{ {
return NextAction::array(0, new NextAction("arcane blast", ACTION_DEFAULT + 0.1f), return NextAction::array(0, new NextAction("arcane blast", ACTION_DEFAULT + 0.3f),
new NextAction("shoot", ACTION_DEFAULT), NULL); // new NextAction("arcane barrage", ACTION_DEFAULT + 0.2f), // cast during movement
new NextAction("fire blast", ACTION_DEFAULT + 0.1f), // cast during movement
new NextAction("shoot", ACTION_DEFAULT), nullptr);
} }
void ArcaneMageStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void ArcaneMageStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)

View File

@@ -9,7 +9,8 @@
NextAction** FireMageStrategy::getDefaultActions() NextAction** FireMageStrategy::getDefaultActions()
{ {
return NextAction::array(0, new NextAction("fireball", ACTION_DEFAULT + 0.1f), return NextAction::array(0, new NextAction("fireball", ACTION_DEFAULT + 0.2f),
new NextAction("fire blast", ACTION_DEFAULT + 0.1f), // cast during movement
new NextAction("shoot", ACTION_DEFAULT), NULL); new NextAction("shoot", ACTION_DEFAULT), NULL);
} }
@@ -23,6 +24,8 @@ void FireMageStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
new TriggerNode("hot streak", NextAction::array(0, new NextAction("pyroblast", 25.0f), nullptr))); new TriggerNode("hot streak", NextAction::array(0, new NextAction("pyroblast", 25.0f), nullptr)));
triggers.push_back( triggers.push_back(
new TriggerNode("combustion", NextAction::array(0, new NextAction("combustion", 50.0f), nullptr))); new TriggerNode("combustion", NextAction::array(0, new NextAction("combustion", 50.0f), nullptr)));
triggers.push_back(
new TriggerNode("living bomb", NextAction::array(0, new NextAction("living bomb", 19.0f), nullptr)));
// triggers.push_back(new TriggerNode("enemy too close for spell", NextAction::array(0, new NextAction("dragon's // triggers.push_back(new TriggerNode("enemy too close for spell", NextAction::array(0, new NextAction("dragon's
// breath", 70.0f), nullptr))); // breath", 70.0f), nullptr)));
} }
@@ -30,7 +33,10 @@ void FireMageStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
void FireMageAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void FireMageAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back( triggers.push_back(
new TriggerNode("medium aoe", NextAction::array(0, new NextAction("flamestrike", 20.0f), nullptr))); new TriggerNode("medium aoe", NextAction::array(0,
triggers.push_back( new NextAction("dragon's breath", 24.0f),
new TriggerNode("living bomb", NextAction::array(0, new NextAction("living bomb", 25.0f), nullptr))); new NextAction("flamestrike", 23.0f),
new NextAction("blast wave", 22.0f),
new NextAction("living bomb on attackers", 21.0f),
new NextAction("blizzard", 20.0f), nullptr)));
} }

View File

@@ -59,7 +59,7 @@ private:
{ {
return new ActionNode("fire blast", return new ActionNode("fire blast",
/*P*/ nullptr, /*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("scorch"), nullptr), /*A*/ nullptr,
/*C*/ nullptr); /*C*/ nullptr);
} }
@@ -115,16 +115,16 @@ private:
{ {
return new ActionNode("dragon's breath", return new ActionNode("dragon's breath",
/*P*/ nullptr, /*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("blast wave"), nullptr), /*A*/ nullptr,
/*C*/ NextAction::array(0, new NextAction("flamestrike", 71.0f), nullptr)); /*C*/ nullptr);
} }
static ActionNode* blast_wave([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* blast_wave([[maybe_unused]] PlayerbotAI* botAI)
{ {
return new ActionNode("blast wave", return new ActionNode("blast wave",
/*P*/ nullptr, /*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("frost nova"), nullptr), /*A*/ nullptr,
/*C*/ NextAction::array(0, new NextAction("flamestrike", 71.0f), nullptr)); /*C*/ nullptr);
} }
static ActionNode* remove_curse([[maybe_unused]] PlayerbotAI* botAI) static ActionNode* remove_curse([[maybe_unused]] PlayerbotAI* botAI)

View File

@@ -12,6 +12,9 @@ Value<Unit*>* CastPolymorphAction::GetTargetValue() { return context->GetValue<U
bool CastFrostNovaAction::isUseful() bool CastFrostNovaAction::isUseful()
{ {
Unit* target = AI_VALUE(Unit*, "current target");
if (target && target->ToCreature() && target->ToCreature()->HasMechanicTemplateImmunity(1 << (MECHANIC_FREEZE - 1)))
return false;
return sServerFacade->IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", GetTargetName()), 10.f); return sServerFacade->IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", GetTargetName()), 10.f);
} }
@@ -21,3 +24,22 @@ bool CastConeOfColdAction::isUseful()
bool targetClose = sServerFacade->IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", GetTargetName()), 10.f); bool targetClose = sServerFacade->IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", GetTargetName()), 10.f);
return facingTarget && targetClose; return facingTarget && targetClose;
} }
bool CastDragonsBreathAction::isUseful()
{
Unit* target = AI_VALUE(Unit*, "current target");
if (!target)
return false;
bool facingTarget = AI_VALUE2(bool, "facing", "current target");
bool targetClose = bot->IsWithinCombatRange(target, 10.0f);
return facingTarget && targetClose;
}
bool CastBlastWaveAction::isUseful()
{
Unit* target = AI_VALUE(Unit*, "current target");
if (!target)
return false;
bool targetClose = bot->IsWithinCombatRange(target, 10.0f);
return targetClose;
}

View File

@@ -57,10 +57,10 @@ public:
CastPyroblastAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "pyroblast") {} CastPyroblastAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "pyroblast") {}
}; };
class CastFlamestrikeAction : public CastSpellAction class CastFlamestrikeAction : public CastDebuffSpellAction
{ {
public: public:
CastFlamestrikeAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "flamestrike") {} CastFlamestrikeAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "flamestrike", true, 0.0f) {}
ActionThreatType getThreatType() override { return ActionThreatType::Aoe; } ActionThreatType getThreatType() override { return ActionThreatType::Aoe; }
}; };
@@ -243,11 +243,18 @@ public:
CastLivingBombAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "living bomb", true) {} CastLivingBombAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "living bomb", true) {}
}; };
class CastLivingBombOnAttackersAction : public CastDebuffSpellOnAttackerAction
{
public:
CastLivingBombOnAttackersAction(PlayerbotAI* botAI) : CastDebuffSpellOnAttackerAction(botAI, "living bomb", true) {}
};
class CastDragonsBreathAction : public CastSpellAction class CastDragonsBreathAction : public CastSpellAction
{ {
public: public:
CastDragonsBreathAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "dragon's breath") {} CastDragonsBreathAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "dragon's breath") {}
ActionThreatType getThreatType() override { return ActionThreatType::Aoe; } ActionThreatType getThreatType() override { return ActionThreatType::Aoe; }
bool isUseful() override;
}; };
class CastBlastWaveAction : public CastSpellAction class CastBlastWaveAction : public CastSpellAction
@@ -255,6 +262,7 @@ class CastBlastWaveAction : public CastSpellAction
public: public:
CastBlastWaveAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "blast wave") {} CastBlastWaveAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "blast wave") {}
ActionThreatType getThreatType() override { return ActionThreatType::Aoe; } ActionThreatType getThreatType() override { return ActionThreatType::Aoe; }
bool isUseful() override;
}; };
class CastInvisibilityAction : public CastBuffSpellAction class CastInvisibilityAction : public CastBuffSpellAction

View File

@@ -184,6 +184,7 @@ public:
creators["polymorph"] = &MageAiObjectContextInternal::polymorph; creators["polymorph"] = &MageAiObjectContextInternal::polymorph;
creators["spellsteal"] = &MageAiObjectContextInternal::spellsteal; creators["spellsteal"] = &MageAiObjectContextInternal::spellsteal;
creators["living bomb"] = &MageAiObjectContextInternal::living_bomb; creators["living bomb"] = &MageAiObjectContextInternal::living_bomb;
creators["living bomb on attackers"] = &MageAiObjectContextInternal::living_bomb_on_attackers;
creators["dragon's breath"] = &MageAiObjectContextInternal::dragons_breath; creators["dragon's breath"] = &MageAiObjectContextInternal::dragons_breath;
creators["blast wave"] = &MageAiObjectContextInternal::blast_wave; creators["blast wave"] = &MageAiObjectContextInternal::blast_wave;
creators["invisibility"] = &MageAiObjectContextInternal::invisibility; creators["invisibility"] = &MageAiObjectContextInternal::invisibility;
@@ -242,6 +243,7 @@ private:
static Action* polymorph(PlayerbotAI* botAI) { return new CastPolymorphAction(botAI); } static Action* polymorph(PlayerbotAI* botAI) { return new CastPolymorphAction(botAI); }
static Action* spellsteal(PlayerbotAI* botAI) { return new CastSpellstealAction(botAI); } static Action* spellsteal(PlayerbotAI* botAI) { return new CastSpellstealAction(botAI); }
static Action* living_bomb(PlayerbotAI* botAI) { return new CastLivingBombAction(botAI); } static Action* living_bomb(PlayerbotAI* botAI) { return new CastLivingBombAction(botAI); }
static Action* living_bomb_on_attackers(PlayerbotAI* botAI) { return new CastLivingBombOnAttackersAction(botAI); }
static Action* dragons_breath(PlayerbotAI* botAI) { return new CastDragonsBreathAction(botAI); } static Action* dragons_breath(PlayerbotAI* botAI) { return new CastDragonsBreathAction(botAI); }
static Action* blast_wave(PlayerbotAI* botAI) { return new CastBlastWaveAction(botAI); } static Action* blast_wave(PlayerbotAI* botAI) { return new CastBlastWaveAction(botAI); }
static Action* invisibility(PlayerbotAI* botAI) { return new CastInvisibilityAction(botAI); } static Action* invisibility(PlayerbotAI* botAI) { return new CastInvisibilityAction(botAI); }

View File

@@ -33,6 +33,17 @@ bool FingersOfFrostSingleTrigger::IsActive()
return (aura && aura->GetCharges() == 1); return (aura && aura->GetCharges() == 1);
} }
bool ArcaneBlastStackTrigger::IsActive()
{
Aura* aura = botAI->GetAura(getName(), GetTarget(), false, true, 3);
if (!aura)
return false;
if (aura->GetStackAmount() >= 4)
return true;
bool hasMissileBarrage = botAI->HasAura(44401, bot);
return hasMissileBarrage;
}
bool FrostNovaOnTargetTrigger::IsActive() bool FrostNovaOnTargetTrigger::IsActive()
{ {
Unit* target = GetTarget(); Unit* target = GetTarget();

View File

@@ -171,6 +171,7 @@ class ArcaneBlastStackTrigger : public HasAuraStackTrigger
{ {
public: public:
ArcaneBlastStackTrigger(PlayerbotAI* botAI) : HasAuraStackTrigger(botAI, "arcane blast", 3, 1) {} ArcaneBlastStackTrigger(PlayerbotAI* botAI) : HasAuraStackTrigger(botAI, "arcane blast", 3, 1) {}
bool IsActive() override;
}; };
class MirrorImageTrigger : public BoostTrigger class MirrorImageTrigger : public BoostTrigger

View File

@@ -15,10 +15,10 @@ ShadowPriestStrategy::ShadowPriestStrategy(PlayerbotAI* botAI) : GenericPriestSt
NextAction** ShadowPriestStrategy::getDefaultActions() NextAction** ShadowPriestStrategy::getDefaultActions()
{ {
return NextAction::array(0, new NextAction("mind blast", ACTION_DEFAULT + 0.2f), return NextAction::array(0, new NextAction("mind blast", ACTION_DEFAULT + 0.3f),
// new NextAction("shadow word: death", 12.0f), new NextAction("mind flay", ACTION_DEFAULT + 0.2f),
new NextAction("mind flay", ACTION_DEFAULT + 0.1f), new NextAction("shadow word: death", ACTION_DEFAULT + 0.1f), // cast during movement
new NextAction("shoot", ACTION_DEFAULT), NULL); new NextAction("shoot", ACTION_DEFAULT), nullptr);
} }
void ShadowPriestStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void ShadowPriestStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)

View File

@@ -41,7 +41,9 @@ CasterShamanStrategy::CasterShamanStrategy(PlayerbotAI* botAI) : GenericShamanSt
NextAction** CasterShamanStrategy::getDefaultActions() NextAction** CasterShamanStrategy::getDefaultActions()
{ {
return NextAction::array(0, new NextAction("lava burst", ACTION_DEFAULT + 0.2f), return NextAction::array(0, new NextAction("lava burst", ACTION_DEFAULT + 0.2f),
new NextAction("lightning bolt", ACTION_DEFAULT), NULL); new NextAction("lightning bolt", ACTION_DEFAULT + 0.1f),
// new NextAction("earth shock", ACTION_DEFAULT), // cast during movement
nullptr);
} }
void CasterShamanStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void CasterShamanStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)

View File

@@ -302,7 +302,7 @@ public:
class FlameShockTrigger : public DebuffTrigger class FlameShockTrigger : public DebuffTrigger
{ {
public: public:
FlameShockTrigger(PlayerbotAI* ai) : DebuffTrigger(ai, "flame shock", 1, true) {} FlameShockTrigger(PlayerbotAI* ai) : DebuffTrigger(ai, "flame shock", 1, true, 6.0f) {}
}; };
class WrathOfAirTotemTrigger : public TotemTrigger class WrathOfAirTotemTrigger : public TotemTrigger

View File

@@ -618,8 +618,8 @@ public:
{ {
} }
std::string const GetTargetName() { return "self target"; } std::string const GetTargetName() override { return "self target"; }
virtual bool IsActive(); bool IsActive() override;
private: private:
int stack; int stack;

View File

@@ -49,8 +49,8 @@ DpsWarlockStrategy::DpsWarlockStrategy(PlayerbotAI* botAI) : GenericWarlockStrat
NextAction** DpsWarlockStrategy::getDefaultActions() NextAction** DpsWarlockStrategy::getDefaultActions()
{ {
return NextAction::array( return NextAction::array(
0, new NextAction("haunt", ACTION_DEFAULT + 0.3f), new NextAction("demonic empowerment", ACTION_DEFAULT + 0.2f), 0, new NextAction("haunt", ACTION_DEFAULT + 0.4f), new NextAction("demonic empowerment", ACTION_DEFAULT + 0.3f),
new NextAction("shadow bolt", ACTION_DEFAULT + 0.1f), new NextAction("shoot", ACTION_DEFAULT), nullptr); new NextAction("shadow bolt", ACTION_DEFAULT + 0.2f), new NextAction("shoot", ACTION_DEFAULT), nullptr);
} }
void DpsWarlockStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void DpsWarlockStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
@@ -71,6 +71,10 @@ void DpsWarlockStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
triggers.push_back(new TriggerNode("decimation", NextAction::array(0, new NextAction("soul fire", 16.0f), NULL))); triggers.push_back(new TriggerNode("decimation", NextAction::array(0, new NextAction("soul fire", 16.0f), NULL)));
// cast during movement
triggers.push_back(
new TriggerNode("high mana", NextAction::array(0, new NextAction("life tap", ACTION_DEFAULT + 0.1f), nullptr)));
triggers.push_back(new TriggerNode("life tap glyph buff", NextAction::array(0, new NextAction("life tap", 28.0f), NULL))); triggers.push_back(new TriggerNode("life tap glyph buff", NextAction::array(0, new NextAction("life tap", 28.0f), NULL)));
triggers.push_back( triggers.push_back(