mirror of
https://github.com/mod-playerbots/mod-playerbots.git
synced 2026-01-14 17:39:09 +00:00
Mage Overhaul
Hello everyone, Back again with another class overhaul. Here is a list of what changes have been made: 1. Consolidated the AoE strategies into "aoe". For light aoe (2+ enemies) the mage will use Cone of Cold (frost)/Arcane Explosion (Arcane)/Multi-Dot with Living Bomb (Fire/Frostfire). For medium aoe (3+ enemies) they will use Flamestrike -> Blizzard. Also, the mage will automatically cancel channeling their blizzard if there is less than 2 enemies around. This is huge, since the mage would often stand there and finish their entire channel during a boss fight after the adds died. 2. Organized actions, triggers, and the aiobjectcontext 3. Enabled Deep Freeze to be casted on bosses regardless of their immune status. Big benefit for frost dps on boss fights. 4. Slight tweaks in the conf so Arcane gets Arcane Barrage and Frostfire gets 2/2 Firestarter 5. Streamlined Arcane DPS to use Missile Barrage proc when at 4 stacks of Arcane Blast 5. Streamlined Fire/Frostfire DPS to keep Improved Scorch active (5% spell crit) unless there is a debuff of equal type 6. Added "firestarter" strategy, that utilizes the Fire talent Firestarter better. The mage will multi-dot Living Bomb while running towards melee, and cast Dragon's Breath -> instant cast Flamestrike -> Blast Wave -> instant cast Flamestrike -> Blizzard for bonkers damage. Disabled by default - not everyone wants their mages running into melee. Enable by typing "co +firestarter" on fire and frostfire mages. 7. Streamlined Frost DPS by finally adding support for Cold Snap for mages. It will proc when both Icy Veins and Deep Freeze are on cooldown. There is an exception to this - if the mage is level 30-59, it will not check for Deep Freeze - only Icy Veins. 8. Added Conjure Mana Gem support in the generic non-combat strategy and Use Mana Gem support in the generic combat strategy. This might be the biggest benefit of the overhaul - the gem has a 90 second cooldown, not shared with mana potions. It really prevents the mage from gassing out in longer fights. And the mana gem has 3 charges! 9. Added Mana Shield ability, which triggers on low health. 10. Changed Mirror Image from a boost ability to an anti-threat tool. Not many people know this, but it's best use in PvE is it's anti-threat modifier: "Mod Total Threat - Temporary Value: -90000000". It also doesn't do good damage, and is essentially used best as a pre-pull spell. But until the mages know how to react to a pull-timer, it's going to be used to reduce threat. Let me know what y'all think!
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "Playerbots.h"
|
||||
|
||||
// ===== Action Node Factory =====
|
||||
class FrostMageStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>
|
||||
{
|
||||
public:
|
||||
@@ -16,96 +17,70 @@ public:
|
||||
creators["ice barrier"] = &ice_barrier;
|
||||
creators["summon water elemental"] = &summon_water_elemental;
|
||||
creators["deep freeze"] = &deep_freeze;
|
||||
creators["icy veins"] = &icy_veins;
|
||||
creators["frostbolt"] = &frostbolt;
|
||||
creators["ice lance"] = &ice_lance;
|
||||
creators["fire blast"] = &fire_blast;
|
||||
creators["fireball"] = &fireball;
|
||||
creators["frostfire bolt"] = &frostfire_bolt;
|
||||
}
|
||||
|
||||
private:
|
||||
static ActionNode* cold_snap([[maybe_unused]] PlayerbotAI* botAI)
|
||||
{
|
||||
return new ActionNode("cold snap",
|
||||
/*P*/ nullptr,
|
||||
/*A*/ nullptr,
|
||||
/*C*/ nullptr);
|
||||
}
|
||||
|
||||
static ActionNode* ice_barrier([[maybe_unused]] PlayerbotAI* botAI)
|
||||
{
|
||||
return new ActionNode("ice barrier",
|
||||
/*P*/ nullptr,
|
||||
/*A*/ nullptr,
|
||||
/*C*/ nullptr);
|
||||
}
|
||||
|
||||
static ActionNode* summon_water_elemental([[maybe_unused]] PlayerbotAI* botAI)
|
||||
{
|
||||
return new ActionNode("summon water elemental",
|
||||
/*P*/ nullptr,
|
||||
/*A*/ nullptr,
|
||||
/*C*/ nullptr);
|
||||
}
|
||||
|
||||
static ActionNode* deep_freeze([[maybe_unused]] PlayerbotAI* botAI)
|
||||
{
|
||||
return new ActionNode("deep freeze",
|
||||
/*P*/ nullptr,
|
||||
/*A*/ NextAction::array(0, new NextAction("ice lance"), nullptr),
|
||||
/*C*/ nullptr);
|
||||
}
|
||||
static ActionNode* cold_snap(PlayerbotAI*) { return new ActionNode("cold snap", nullptr, nullptr, nullptr); }
|
||||
static ActionNode* ice_barrier(PlayerbotAI*) { return new ActionNode("ice barrier", nullptr, nullptr, nullptr); }
|
||||
static ActionNode* summon_water_elemental(PlayerbotAI*) { return new ActionNode("summon water elemental", nullptr, nullptr, nullptr); }
|
||||
static ActionNode* deep_freeze(PlayerbotAI*) { return new ActionNode("deep freeze", nullptr, nullptr, nullptr); }
|
||||
static ActionNode* icy_veins(PlayerbotAI*) { return new ActionNode("icy veins", nullptr, nullptr, nullptr); }
|
||||
static ActionNode* frostbolt(PlayerbotAI*) { return new ActionNode("frostbolt", nullptr, nullptr, nullptr); }
|
||||
static ActionNode* ice_lance(PlayerbotAI*) { return new ActionNode("ice lance", nullptr, nullptr, nullptr); }
|
||||
static ActionNode* fire_blast(PlayerbotAI*) { return new ActionNode("fire blast", nullptr, nullptr, nullptr); }
|
||||
static ActionNode* fireball(PlayerbotAI*) { return new ActionNode("fireball", nullptr, nullptr, nullptr); }
|
||||
static ActionNode* frostfire_bolt(PlayerbotAI*) { return new ActionNode("frostfire bolt", nullptr, nullptr, nullptr); }
|
||||
};
|
||||
|
||||
// ===== Single Target Strategy =====
|
||||
FrostMageStrategy::FrostMageStrategy(PlayerbotAI* botAI) : GenericMageStrategy(botAI)
|
||||
{
|
||||
actionNodeFactories.Add(new FrostMageStrategyActionNodeFactory());
|
||||
}
|
||||
|
||||
// ===== Default Actions =====
|
||||
NextAction** FrostMageStrategy::getDefaultActions()
|
||||
{
|
||||
return NextAction::array(0, new NextAction("frostbolt", ACTION_DEFAULT + 0.3f),
|
||||
new NextAction("fire blast", ACTION_DEFAULT + 0.2f), // cast during movement
|
||||
new NextAction("shoot", ACTION_DEFAULT + 0.1f),
|
||||
new NextAction("fireball", ACTION_DEFAULT), nullptr);
|
||||
return NextAction::array(0, new NextAction("frostbolt", 5.4f),
|
||||
new NextAction("ice lance", 5.3f), // cast during movement
|
||||
new NextAction("fire blast", 5.2f), // cast during movement if ice lance is not learned
|
||||
new NextAction("shoot", 5.1f),
|
||||
new NextAction("fireball", 5.0f), nullptr);
|
||||
}
|
||||
|
||||
// ===== Trigger Initialization ===
|
||||
void FrostMageStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
GenericMageStrategy::InitTriggers(triggers);
|
||||
triggers.push_back(new TriggerNode("icy veins", NextAction::array(0, new NextAction("icy veins", 50.0f), nullptr)));
|
||||
// No logic currently for cold snap usage.. possibly use right after icy veins drops off?
|
||||
// triggers.push_back(new TriggerNode("cold snap", NextAction::array(0, new NextAction("cold snap", 50.0f),
|
||||
// nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"no pet", NextAction::array(0, new NextAction("summon water elemental", ACTION_HIGH), nullptr)));
|
||||
triggers.push_back(
|
||||
new TriggerNode("has pet", NextAction::array(0, new NextAction("toggle pet spell", ACTION_HIGH + 1), nullptr)));
|
||||
triggers.push_back(
|
||||
new TriggerNode("medium health", NextAction::array(0, new NextAction("ice barrier", ACTION_NORMAL), nullptr)));
|
||||
triggers.push_back(
|
||||
new TriggerNode("being attacked", NextAction::array(0, new NextAction("ice barrier", ACTION_HIGH + 1), nullptr)));
|
||||
triggers.push_back(new TriggerNode(
|
||||
"brain freeze", NextAction::array(0, new NextAction("frostfire bolt", ACTION_NORMAL + 3), nullptr)));
|
||||
// Combo cast the last charge of fingers of frost for double crits.
|
||||
// Should only do this on the final charge of FoF.
|
||||
triggers.push_back(new TriggerNode("fingers of frost single",
|
||||
NextAction::array(0, new NextAction("frostbolt", ACTION_NORMAL + 2),
|
||||
new NextAction("deep freeze", ACTION_NORMAL + 1), nullptr)));
|
||||
// May not need this, frostbolt is the default action so probably don't need to specify.
|
||||
// Maybe uncomment if you find the mage is prioritising auxillary spells while this buff is up, and wasting the
|
||||
// proc. triggers.push_back(new TriggerNode("fingers of frost double", NextAction::array(0, new
|
||||
// NextAction("frostbolt", ACTION_NORMAL), nullptr)));
|
||||
// Cooldown triggers
|
||||
triggers.push_back(new TriggerNode("cold snap", NextAction::array(0, new NextAction("cold snap", 28.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("icy veins", NextAction::array(0, new NextAction("icy veins", 27.5f), nullptr)));
|
||||
|
||||
// Same 2-spell combo for various freeze procs
|
||||
triggers.push_back(new TriggerNode("frost nova on target",
|
||||
NextAction::array(0, new NextAction("frostbolt", ACTION_NORMAL + 2),
|
||||
new NextAction("deep freeze", ACTION_NORMAL + 1), nullptr)));
|
||||
triggers.push_back(new TriggerNode("frostbite on target",
|
||||
NextAction::array(0, new NextAction("frostbolt", ACTION_NORMAL + 2),
|
||||
new NextAction("deep freeze", ACTION_NORMAL + 1), nullptr)));
|
||||
}
|
||||
|
||||
void FrostMageAoeStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(
|
||||
new TriggerNode("medium aoe", NextAction::array(0, new NextAction("blizzard", ACTION_HIGH), nullptr)));
|
||||
triggers.push_back(
|
||||
new TriggerNode("light aoe", NextAction::array(0, new NextAction("cone of cold", ACTION_HIGH + 1), nullptr)));
|
||||
// Pet/Defensive triggers
|
||||
triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("summon water elemental", 30.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("has pet", NextAction::array(0, new NextAction("toggle pet spell", 29.5f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("medium health", NextAction::array(0, new NextAction("ice barrier", 29.0f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("being attacked", NextAction::array(0, new NextAction("ice barrier", 29.0f), nullptr)));
|
||||
|
||||
// Proc/Freeze triggers
|
||||
triggers.push_back(new TriggerNode("brain freeze", NextAction::array(0, new NextAction("frostfire bolt", 19.5f), nullptr)));
|
||||
triggers.push_back(new TriggerNode("fingers of frost", NextAction::array(0,
|
||||
new NextAction("deep freeze", 19.0f),
|
||||
new NextAction("frostbolt", 18.0f), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode("frostbite on target", NextAction::array(0,
|
||||
new NextAction("deep freeze", 19.0f),
|
||||
new NextAction("frostbolt", 18.0f), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode("frost nova on target", NextAction::array(0,
|
||||
new NextAction("deep freeze", 19.0f),
|
||||
new NextAction("frostbolt", 18.0f), nullptr)));
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user