This update enhances bot behavior by adding a check for both line of sight (LoS) and significant vertical height differences between the bot and its target. If the bot cannot see its target or if the height difference exceeds 5.0f, it calculates a valid path and moves closer to regain visibility and combat effectiveness. This resolves cases where bots would previously stand still when enemies jumped from elevated terrain or were behind obstacles.
Hello everyone,
I liked the channel cancel I did on mage recently, where they cancel blizzard if there is only 1 enemy left. I decided to do the same for the following classes:
Druid: Hurricane
Hunter: Volley
Priest: Mind Sear
Warlock: Rain of Fire
I moved the "ChannelCancel" action to it's own file, so other classes could benefit from it. I removed it from the mageactions.
This update enhances bot behavior in arena scenarios by addressing the issue where bots remain idle if their target moves behind line-of-sight (LoS obstacles). The bot now attempts to reposition near the target to regain LoS instead of standing still, preventing situations where enemies can recover without pressure.
Could someone test it?
Hello everyone,
This is a fix for issue #1233
I have added a clause in the CanCastSpell check that checks if the bot is in flight form/swift flight form & not in combat. It will no longer attempt to shift into a caster form and repetitively try and heal/buff party members while flying. Tested on my PC with the changes and druid now successfully flies as fast as the player with no stopping.
This was causing the issue:
static ActionNode* thorns([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("thorns",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
}
static ActionNode* thorns_on_party([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("thorns on party",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
}
static ActionNode* mark_of_the_wild([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("mark of the wild",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
}
static ActionNode* mark_of_the_wild_on_party([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("mark of the wild on party",
/*P*/ NextAction::array(0, new NextAction("caster 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("caster form"), nullptr),
/*A*/ NULL,
/*C*/ NULL);
}
static ActionNode* rejuvenation_on_party([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("rejuvenation on party",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr),
/*A*/ NULL,
/*C*/ NULL);
}
static ActionNode* remove_curse_on_party([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("remove curse on party",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr),
/*A*/ NULL,
/*C*/ NULL);
}
static ActionNode* abolish_poison_on_party([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("abolish poison on party",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr),
/*A*/ NULL,
/*C*/ NULL);
}
static ActionNode* revive([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode("revive",
/*P*/ NextAction::array(0, new NextAction("caster form"), nullptr),
/*A*/ NULL,
/*C*/ NULL);
}
The *P* stands for prior, aka before this action is taken, do this other action "caster form". This is the Caster Form action:
class CastCasterFormAction : public CastBuffSpellAction
{
public:
CastCasterFormAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "caster form") {}
bool isUseful() override;
bool isPossible() override { return true; }
bool Execute(Event event) override;
};
And this:
bool CastCasterFormAction::isUseful()
{
return botAI->HasAnyAuraOf(GetTarget(), "dire bear form", "bear form", "cat form", "travel form", "aquatic form",
"flight form", "swift flight form", "moonkin form", nullptr) &&
AI_VALUE2(uint8, "mana", "self target") > sPlayerbotAIConfig->mediumHealth;
}
bool CastCasterFormAction::Execute(Event event)
{
botAI->RemoveShapeshift();
return true;
}
So basically, the druid was triggering to heal/buff the party, and before it could do that, it had to switch into "caster form" which executed RemoveShapeshift(). After it did that, mounting back up into flight form/swift flight form had the highest priority, so it would loop the triggers/actions.
This commit focuses on the changes requested - Migrate important cooldowns over to BoostStrategy.
Just tested it, and it is working fine - The player has more control over when they can boost. Also, added Mirror Image to the Boost Strategy, after other cooldowns are used - this way the mirror images get the buffs.
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!
Hello everyone,
This PR addresses issue #1464 - Now, when you change a strategy, the new pet will be summoned accordingly - as long as the warlock knows the pet. I tested this myself with level 80 warlocks, then moved to lower level warlocks. It was nice to see that when my affliction warlock went from level 29 to 30, it automatically summoned the felhunter (while having the succubus out prior).
List of changes per file:
src\AiFactory.cpp: Set default level 1 spec to demonology for altbots - it was affliction prior. This will allow them to use Curse of agony, corruption, and immolate between levels 1-10.
src\strategy\warlock\GenericWarlockNonCombatStrategy.cpp: Added the "wrong pet" trigger to each of the 5 pet strategies, coupled with the appropriate summon action.
src\strategy\warlock\WarlockAiObjectContext.cpp: Registered the "wrong pet" trigger and moved the unstable affliction static trigger all to 1 line, cleaning it up a bit.
src\strategy\warlock\WarlockTriggers.cpp: Added the logic for the wrong pet trigger here. I tried to leave detailed comments as much as possible explaining it's thought process.
src\strategy\warlock\WarlockTriggers.h: Added the WrongPetTrigger.
Hello everyone,
I'm still working on fixing issue #1439 , and I have a theory - it could be because the clients that are having the issue are not english, and the code currently checks for strings "soul shard" and "soulstone". This PR converts the check over to the item IDs, so it should work regardless of what client is being used. I tested it myself with the english client and there is functionally no difference than before - but I hope it solves the issue #1439 for the non-english clients and community.
Hello everybody,
This PR is to address issues #1439 and #1451.
I added a 1 second cooldown to the createsoulshard action, as the warlock wouldn't ever use more than 1 soul shard per second.
I also added a cooldown check to the soulstone trigger, so it doesn't simply try to use the ss healer, ss self, ss tank, or ss master if the soulstone is present in the inventory. I checked the logs, and was able to recreate the issue of #1451 - the bot was shifting targets over and over again, and that was because previously the trigger was just checking to see if a soulstone was present at all. Now it won't fire if it's on cooldown.
Hello everyone,
I was working with hunter bots and I feel like I didn't have enough control over their pets. So I started working on a chat command for the hunter pets, and it's been a blast. Below is a description of what the commands do:
pet name <name>
Summons a tameable pet by its creature name (case-insensitive).
The bot checks if the pet is exotic and requires the Beast Mastery talent if so.
If successful, the bot announces the pet's new name and creature ID.
If not found or not tameable, an error message is given.
pet id <id>
Summons a tameable pet by its database creature ID.
The same exotic pet checks apply.
Success is announced with the pet's name and ID.
Errors are given for invalid IDs or untameable pets.
pet family <family>
Randomly selects and summons a tameable pet from the specified family (e.g., "cat", "wolf").
Only families with tameable pets are considered.
Exotic pet checks and talent requirements apply.
Success is announced with the pet's name and ID.
Errors are given if no suitable pet is found.
pet rename <new name>
Renames the hunter's current summoned pet to a new name.
The name must be 1-12 alphabetic characters (A-Z, a-z) and is automatically formatted (first letter capitalized, rest lowercased).
Forbidden or reserved names are disallowed.
After renaming, the bot sets the new name, saves the pet, and updates the client.
The bot dismisses and attempts to recall the pet using "Call Pet" (if the hunter knows it) to update the UI.
If the new name isn't visible immediately, the bot instructs the player to dismiss and recall the pet manually.
Confirmation and guidance messages are provided.
Additional Details:
All commands display errors if requirements are not met (wrong name/id/family, forbidden name, lack of Beast Mastery, or hunter below level 10).
After changing or summoning a pet (except renaming), the bot initializes the pet and its talents, then announces the result.
TLDR:
pet name <name> Summon a tameable pet by name
pet id <id> Summon a tameable pet by database creature ID
pet family <family> Randomly summon a tameable pet of the given family
pet rename <new name> Rename the current pet and refresh its name in the client UI
Description of files changed:
src\strategy\actions\ChatActionContext.h: Added the "pet" action for the whisper command.
src\strategy\actions\PetAction.cpp: New chat actions for all things related to hunter pets.
src\strategy\actions\PetAction.h: New header for the PetAction.cpp.
src\strategy\generic\ChatCommandHandlerStrategy.cpp: Linked the trigger and action in the chatcommandhandlerstrategy, for the bot to take action when whispered "pet" (trigger).
src\strategy\triggers\ChatTriggerContext.h: Added the "pet" trigger.