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",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("arcane missiles"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
}
@@ -59,8 +59,10 @@ ArcaneMageStrategy::ArcaneMageStrategy(PlayerbotAI* botAI) : GenericMageStrategy
NextAction** ArcaneMageStrategy::getDefaultActions()
{
return NextAction::array(0, new NextAction("arcane blast", ACTION_DEFAULT + 0.1f),
new NextAction("shoot", ACTION_DEFAULT), NULL);
return NextAction::array(0, new NextAction("arcane blast", ACTION_DEFAULT + 0.3f),
// 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)

View File

@@ -9,7 +9,8 @@
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);
}
@@ -23,6 +24,8 @@ void FireMageStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
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("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
// breath", 70.0f), nullptr)));
}
@@ -30,7 +33,10 @@ void FireMageStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
void FireMageAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
triggers.push_back(
new TriggerNode("medium aoe", NextAction::array(0, new NextAction("flamestrike", 20.0f), nullptr)));
triggers.push_back(
new TriggerNode("living bomb", NextAction::array(0, new NextAction("living bomb", 25.0f), nullptr)));
new TriggerNode("medium aoe", NextAction::array(0,
new NextAction("dragon's breath", 24.0f),
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",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("scorch"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
}
@@ -115,16 +115,16 @@ private:
{
return new ActionNode("dragon's breath",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("blast wave"), nullptr),
/*C*/ NextAction::array(0, new NextAction("flamestrike", 71.0f), nullptr));
/*A*/ nullptr,
/*C*/ nullptr);
}
static ActionNode* blast_wave([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("blast wave",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("frost nova"), nullptr),
/*C*/ NextAction::array(0, new NextAction("flamestrike", 71.0f), nullptr));
/*A*/ nullptr,
/*C*/ nullptr);
}
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()
{
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);
}
@@ -21,3 +24,22 @@ bool CastConeOfColdAction::isUseful()
bool targetClose = sServerFacade->IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", GetTargetName()), 10.f);
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") {}
};
class CastFlamestrikeAction : public CastSpellAction
class CastFlamestrikeAction : public CastDebuffSpellAction
{
public:
CastFlamestrikeAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "flamestrike") {}
CastFlamestrikeAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "flamestrike", true, 0.0f) {}
ActionThreatType getThreatType() override { return ActionThreatType::Aoe; }
};
@@ -243,11 +243,18 @@ public:
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
{
public:
CastDragonsBreathAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "dragon's breath") {}
ActionThreatType getThreatType() override { return ActionThreatType::Aoe; }
bool isUseful() override;
};
class CastBlastWaveAction : public CastSpellAction
@@ -255,6 +262,7 @@ class CastBlastWaveAction : public CastSpellAction
public:
CastBlastWaveAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "blast wave") {}
ActionThreatType getThreatType() override { return ActionThreatType::Aoe; }
bool isUseful() override;
};
class CastInvisibilityAction : public CastBuffSpellAction

View File

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

View File

@@ -33,6 +33,17 @@ bool FingersOfFrostSingleTrigger::IsActive()
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()
{
Unit* target = GetTarget();

View File

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

View File

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

View File

@@ -41,7 +41,9 @@ CasterShamanStrategy::CasterShamanStrategy(PlayerbotAI* botAI) : GenericShamanSt
NextAction** CasterShamanStrategy::getDefaultActions()
{
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)

View File

@@ -302,7 +302,7 @@ public:
class FlameShockTrigger : public DebuffTrigger
{
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

View File

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

View File

@@ -49,8 +49,8 @@ DpsWarlockStrategy::DpsWarlockStrategy(PlayerbotAI* botAI) : GenericWarlockStrat
NextAction** DpsWarlockStrategy::getDefaultActions()
{
return NextAction::array(
0, new NextAction("haunt", ACTION_DEFAULT + 0.3f), new NextAction("demonic empowerment", ACTION_DEFAULT + 0.2f),
new NextAction("shadow bolt", ACTION_DEFAULT + 0.1f), new NextAction("shoot", ACTION_DEFAULT), nullptr);
0, new NextAction("haunt", ACTION_DEFAULT + 0.4f), new NextAction("demonic empowerment", ACTION_DEFAULT + 0.3f),
new NextAction("shadow bolt", ACTION_DEFAULT + 0.2f), new NextAction("shoot", ACTION_DEFAULT), nullptr);
}
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)));
// 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(