mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
Warlock Pet Re-Summon on Strategy Change
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.
This commit is contained in:
@@ -88,6 +88,9 @@ uint8 AiFactory::GetPlayerSpecTab(Player* bot)
|
||||
case CLASS_PRIEST:
|
||||
tab = PRIEST_TAB_HOLY;
|
||||
break;
|
||||
case CLASS_WARLOCK:
|
||||
tab = WARLOCK_TAB_DEMONOLOGY;
|
||||
break;
|
||||
}
|
||||
|
||||
return tab;
|
||||
|
||||
@@ -98,6 +98,7 @@ SummonImpStrategy::SummonImpStrategy(PlayerbotAI* ai) : NonCombatStrategy(ai) {}
|
||||
void SummonImpStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("summon imp", 29.0f), NULL)));
|
||||
triggers.push_back(new TriggerNode("wrong pet", NextAction::array(0, new NextAction("summon imp", 29.0f), NULL)));
|
||||
}
|
||||
|
||||
// Non-combat strategy for summoning a Voidwalker
|
||||
@@ -109,6 +110,7 @@ SummonVoidwalkerStrategy::SummonVoidwalkerStrategy(PlayerbotAI* ai) : NonCombatS
|
||||
void SummonVoidwalkerStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("summon voidwalker", 29.0f), NULL)));
|
||||
triggers.push_back(new TriggerNode("wrong pet", NextAction::array(0, new NextAction("summon voidwalker", 29.0f), NULL)));
|
||||
}
|
||||
|
||||
// Non-combat strategy for summoning a Succubus
|
||||
@@ -120,6 +122,7 @@ SummonSuccubusStrategy::SummonSuccubusStrategy(PlayerbotAI* ai) : NonCombatStrat
|
||||
void SummonSuccubusStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("summon succubus", 29.0f), NULL)));
|
||||
triggers.push_back(new TriggerNode("wrong pet", NextAction::array(0, new NextAction("summon succubus", 29.0f), NULL)));
|
||||
}
|
||||
|
||||
// Non-combat strategy for summoning a Felhunter
|
||||
@@ -131,6 +134,7 @@ SummonFelhunterStrategy::SummonFelhunterStrategy(PlayerbotAI* ai) : NonCombatStr
|
||||
void SummonFelhunterStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("summon felhunter", 29.0f), NULL)));
|
||||
triggers.push_back(new TriggerNode("wrong pet", NextAction::array(0, new NextAction("summon felhunter", 29.0f), NULL)));
|
||||
}
|
||||
|
||||
// Non-combat strategy for summoning a Felguard
|
||||
@@ -142,6 +146,7 @@ SummonFelguardStrategy::SummonFelguardStrategy(PlayerbotAI* ai) : NonCombatStrat
|
||||
void SummonFelguardStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("summon felguard", 29.0f), NULL)));
|
||||
triggers.push_back(new TriggerNode("wrong pet", NextAction::array(0, new NextAction("summon felguard", 29.0f), NULL)));
|
||||
}
|
||||
|
||||
// Non-combat strategy for selecting themselves to receive soulstone
|
||||
|
||||
@@ -171,6 +171,7 @@ public:
|
||||
creators["curse of exhaustion"] = &WarlockTriggerFactoryInternal::curse_of_exhaustion;
|
||||
creators["curse of tongues"] = &WarlockTriggerFactoryInternal::curse_of_tongues;
|
||||
creators["curse of weakness"] = &WarlockTriggerFactoryInternal::curse_of_weakness;
|
||||
creators["wrong pet"] = &WarlockTriggerFactoryInternal::wrong_pet;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -197,10 +198,7 @@ private:
|
||||
static Trigger* immolate(PlayerbotAI* botAI) { return new ImmolateTrigger(botAI); }
|
||||
static Trigger* immolate_on_attacker(PlayerbotAI* ai) { return new ImmolateOnAttackerTrigger(ai); }
|
||||
static Trigger* unstable_affliction(PlayerbotAI* ai) { return new UnstableAfflictionTrigger(ai); }
|
||||
static Trigger* unstable_affliction_on_attacker(PlayerbotAI* ai)
|
||||
{
|
||||
return new UnstableAfflictionOnAttackerTrigger(ai);
|
||||
}
|
||||
static Trigger* unstable_affliction_on_attacker(PlayerbotAI* ai) { return new UnstableAfflictionOnAttackerTrigger(ai); }
|
||||
static Trigger* haunt(PlayerbotAI* ai) { return new HauntTrigger(ai); }
|
||||
static Trigger* decimation(PlayerbotAI* ai) { return new DecimationTrigger(ai); }
|
||||
static Trigger* life_tap(PlayerbotAI* ai) { return new LifeTapTrigger(ai); }
|
||||
@@ -218,6 +216,7 @@ private:
|
||||
static Trigger* curse_of_exhaustion(PlayerbotAI* ai) { return new CurseOfExhaustionTrigger(ai); }
|
||||
static Trigger* curse_of_tongues(PlayerbotAI* ai) { return new CurseOfTonguesTrigger(ai); }
|
||||
static Trigger* curse_of_weakness(PlayerbotAI* ai) { return new CurseOfWeaknessTrigger(ai); }
|
||||
static Trigger* wrong_pet(PlayerbotAI* ai) { return new WrongPetTrigger(ai); }
|
||||
};
|
||||
|
||||
class WarlockAiObjectContextInternal : public NamedObjectContext<Action>
|
||||
|
||||
@@ -165,3 +165,66 @@ bool CurseOfWeaknessTrigger::IsActive()
|
||||
// Use default BuffTrigger logic for the rest (only trigger if debuff is missing or expiring)
|
||||
return BuffTrigger::IsActive();
|
||||
}
|
||||
|
||||
struct WarlockPetDef
|
||||
{
|
||||
const char* strategy; // The strategy string as recognized by the AI (e.g., "imp", "voidwalker", etc.)
|
||||
uint32 spellId; // The spell ID required to summon this pet
|
||||
uint32 npcEntry; // The NPC entry ID for the summoned pet creature
|
||||
};
|
||||
|
||||
// Static array with all relevant Warlock pets and their data
|
||||
static const WarlockPetDef pets[] = {{"imp", 688, 416},
|
||||
{"voidwalker", 697, 1860},
|
||||
{"succubus", 712, 1863},
|
||||
{"felhunter", 691, 417},
|
||||
{"felguard", 30146, 17252}};
|
||||
|
||||
bool WrongPetTrigger::IsActive()
|
||||
{
|
||||
// Retrieve the bot player and its current pet (if any)
|
||||
Player* bot = botAI->GetBot();
|
||||
Pet* pet = bot->GetPet();
|
||||
|
||||
// Step 1: Count how many pet strategies are currently enabled for this bot.
|
||||
// While doing so, also remember which pet strategy is the only enabled one (if that's the case).
|
||||
int enabledCount = 0;
|
||||
const WarlockPetDef* enabledPet =
|
||||
nullptr; // Pointer to the pet definition of the enabled strategy, if only one is enabled
|
||||
for (const WarlockPetDef& pd : pets)
|
||||
{
|
||||
if (botAI->HasStrategy(pd.strategy, BOT_STATE_NON_COMBAT))
|
||||
{
|
||||
enabledCount++;
|
||||
enabledPet = &pd; // Save the pointer to last enabled pet
|
||||
}
|
||||
}
|
||||
|
||||
// Step 2: If not exactly one pet strategy is enabled, we should not trigger.
|
||||
// This prevents ambiguous or conflicting situations.
|
||||
if (enabledCount != 1)
|
||||
return false;
|
||||
|
||||
// Step 3: At this point, we know only one pet strategy is enabled.
|
||||
// We check if the currently summoned pet matches the enabled strategy.
|
||||
bool correctPet = false;
|
||||
if (pet)
|
||||
{
|
||||
CreatureTemplate const* ct = pet->GetCreatureTemplate();
|
||||
// Check if the pet's NPC entry matches the expected one for the enabled strategy
|
||||
if (ct && ct->Entry == enabledPet->npcEntry)
|
||||
correctPet = true;
|
||||
}
|
||||
|
||||
// Step 4: If the correct pet is already summoned, the trigger should not activate.
|
||||
if (correctPet)
|
||||
return false;
|
||||
|
||||
// Step 5: Finally, check if the bot actually knows the spell to summon the desired pet.
|
||||
// If so, the trigger is active (bot should summon the correct pet).
|
||||
if (bot->HasSpell(enabledPet->spellId))
|
||||
return true;
|
||||
|
||||
// Step 6: If we get here, the bot doesn't know the spell required to support the active pet strategy
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -112,6 +112,14 @@ public:
|
||||
HasHealthstoneTrigger(PlayerbotAI* botAI) : WarlockConjuredItemTrigger(botAI, "healthstone") {}
|
||||
};
|
||||
|
||||
class WrongPetTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
WrongPetTrigger(PlayerbotAI* botAI) : Trigger(botAI, "wrong pet") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
|
||||
// CC and Pet Triggers
|
||||
|
||||
class BanishTrigger : public HasCcTargetTrigger
|
||||
|
||||
Reference in New Issue
Block a user