diff --git a/src/strategy/actions/ActionContext.h b/src/strategy/actions/ActionContext.h index 7573225e..0b5568ef 100644 --- a/src/strategy/actions/ActionContext.h +++ b/src/strategy/actions/ActionContext.h @@ -225,7 +225,7 @@ class ActionContext : public NamedObjectContext creators["rpg mount anim"] = &ActionContext::rpg_mount_anim; creators["toggle pet spell"] = &ActionContext::toggle_pet_spell; - + creators["pet attack"] = &ActionContext::pet_attack; } @@ -390,7 +390,7 @@ class ActionContext : public NamedObjectContext static Action* rpg_mount_anim(PlayerbotAI* botAI) { return new RpgMountAnimAction(botAI); } static Action* toggle_pet_spell(PlayerbotAI* ai) { return new TogglePetSpellAutoCastAction(ai); } - + static Action* pet_attack(PlayerbotAI* ai) { return new PetAttackAction(ai); } }; diff --git a/src/strategy/actions/AttackAction.cpp b/src/strategy/actions/AttackAction.cpp index 83df7b37..20e496c3 100644 --- a/src/strategy/actions/AttackAction.cpp +++ b/src/strategy/actions/AttackAction.cpp @@ -116,22 +116,22 @@ bool AttackAction::Attack(Unit* target, bool with_pet /*true*/) return false; } /* prevent pet dead immediately in group */ - if (bot->GetMap()->IsDungeon() && bot->GetGroup() && !target->IsInCombat()) { - with_pet = false; - } - if (Pet* pet = bot->GetPet()) - { - if (with_pet) { - pet->SetReactState(REACT_DEFENSIVE); - pet->SetTarget(target->GetGUID()); - pet->GetCharmInfo()->SetIsCommandAttack(true); - pet->AI()->AttackStart(target); - } else { - pet->SetReactState(REACT_PASSIVE); - pet->GetCharmInfo()->SetIsCommandFollow(true); - pet->GetCharmInfo()->IsReturning(); - } - } + // if (bot->GetMap()->IsDungeon() && bot->GetGroup() && !target->IsInCombat()) { + // with_pet = false; + // } + // if (Pet* pet = bot->GetPet()) + // { + // if (with_pet) { + // pet->SetReactState(REACT_DEFENSIVE); + // pet->SetTarget(target->GetGUID()); + // pet->GetCharmInfo()->SetIsCommandAttack(true); + // pet->AI()->AttackStart(target); + // } else { + // pet->SetReactState(REACT_PASSIVE); + // pet->GetCharmInfo()->SetIsCommandFollow(true); + // pet->GetCharmInfo()->IsReturning(); + // } + // } return true; } diff --git a/src/strategy/actions/GenericActions.cpp b/src/strategy/actions/GenericActions.cpp index b2a987a2..5e292369 100644 --- a/src/strategy/actions/GenericActions.cpp +++ b/src/strategy/actions/GenericActions.cpp @@ -3,6 +3,7 @@ */ #include "GenericActions.h" +#include "CreatureAI.h" #include "Playerbots.h" bool MeleeAction::isUseful() @@ -39,4 +40,29 @@ bool TogglePetSpellAutoCastAction::Execute(Event event) { } } return true; +} + +bool PetAttackAction::Execute(Event event) +{ + Guardian* pet = bot->GetGuardianPet(); + if (!pet) { + return false; + } + Unit* target = AI_VALUE(Unit*, "current target"); + if (!target) { + return false; + } + // pet->SetReactState(REACT_DEFENSIVE); + pet->ClearUnitState(UNIT_STATE_FOLLOW); + pet->AttackStop(); + pet->SetTarget(target->GetGUID()); + + pet->GetCharmInfo()->SetIsCommandAttack(true); + pet->GetCharmInfo()->SetIsAtStay(false); + pet->GetCharmInfo()->SetIsFollowing(false); + pet->GetCharmInfo()->SetIsCommandFollow(false); + pet->GetCharmInfo()->SetIsReturning(false); + + pet->ToCreature()->AI()->AttackStart(target); + return true; } \ No newline at end of file diff --git a/src/strategy/actions/GenericActions.h b/src/strategy/actions/GenericActions.h index 66385008..1b34c82c 100644 --- a/src/strategy/actions/GenericActions.h +++ b/src/strategy/actions/GenericActions.h @@ -25,4 +25,12 @@ public: virtual bool Execute(Event event) override; }; +class PetAttackAction: public Action +{ +public: + PetAttackAction(PlayerbotAI* ai): Action(ai, "pet attack") {} + virtual bool Execute(Event event) override; +}; + + #endif diff --git a/src/strategy/generic/CombatStrategy.cpp b/src/strategy/generic/CombatStrategy.cpp index 7781ebbc..10878326 100644 --- a/src/strategy/generic/CombatStrategy.cpp +++ b/src/strategy/generic/CombatStrategy.cpp @@ -13,6 +13,7 @@ void CombatStrategy::InitTriggers(std::vector &triggers) // triggers.push_back(new TriggerNode("out of react range", NextAction::array(0, new NextAction("flee to master", 55), nullptr))); triggers.push_back(new TriggerNode("combat stuck", NextAction::array(0, new NextAction("reset", 1.0f), nullptr))); triggers.push_back(new TriggerNode("not facing target", NextAction::array(0, new NextAction("set facing", ACTION_MOVE + 7), nullptr))); + triggers.push_back(new TriggerNode("pet attack", NextAction::array(0, new NextAction("pet attack", ACTION_NORMAL), nullptr))); // triggers.push_back(new TriggerNode("combat long stuck", NextAction::array(0, new NextAction("hearthstone", 0.9f), new NextAction("repop", 0.8f), nullptr))); } diff --git a/src/strategy/priest/GenericPriestStrategy.cpp b/src/strategy/priest/GenericPriestStrategy.cpp index 31677e82..ab66777c 100644 --- a/src/strategy/priest/GenericPriestStrategy.cpp +++ b/src/strategy/priest/GenericPriestStrategy.cpp @@ -45,7 +45,6 @@ void GenericPriestStrategy::InitTriggers(std::vector& triggers) NextAction::array(0, new NextAction("hymn of hope", ACTION_HIGH), NULL))); triggers.push_back(new TriggerNode("enemy too close for spell", NextAction::array(0, new NextAction("flee", ACTION_MOVE + 9), nullptr))); - triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("apply oil", 1.0f), nullptr))); } diff --git a/src/strategy/raids/naxxramas/RaidNaxxMultipliers.cpp b/src/strategy/raids/naxxramas/RaidNaxxMultipliers.cpp index 47f1fb4b..4fde1803 100644 --- a/src/strategy/raids/naxxramas/RaidNaxxMultipliers.cpp +++ b/src/strategy/raids/naxxramas/RaidNaxxMultipliers.cpp @@ -1,4 +1,5 @@ #include "RaidNaxxMultipliers.h" +#include "GenericActions.h" #include "MovementActions.h" #include "ScriptedCreature.h" #include "RaidNaxxActions.h" @@ -173,7 +174,8 @@ float KelthuzadGenericMultiplier::GetValue(Action* action) dynamic_cast(action) || dynamic_cast(action) || dynamic_cast(action) || - dynamic_cast(action)) { + dynamic_cast(action) || + dynamic_cast(action)) { return 0.0f; } } @@ -268,5 +270,11 @@ float GluthGenericMultiplier::GetValue(Action* action) } } } + if (dynamic_cast(action)) { + Unit* target = AI_VALUE(Unit*, "current target"); + if (target && target->GetEntry() == NPC_ZOMBIE_CHOW) { + return 0.0f; + } + } return 1.0f; } diff --git a/src/strategy/triggers/GenericTriggers.cpp b/src/strategy/triggers/GenericTriggers.cpp index 1e3d470b..7f55be58 100644 --- a/src/strategy/triggers/GenericTriggers.cpp +++ b/src/strategy/triggers/GenericTriggers.cpp @@ -4,6 +4,7 @@ #include "GenericTriggers.h" #include "BattlegroundWS.h" +#include "CreatureAI.h" #include "ObjectGuid.h" #include "Playerbots.h" #include "SharedDefines.h" @@ -34,6 +35,25 @@ bool HasPetTrigger::IsActive() { return (AI_VALUE(Unit*, "pet target")) && !AI_VALUE2(bool, "mounted", "self target");; } +bool PetAttackTrigger::IsActive() +{ + Guardian* pet = bot->GetGuardianPet(); + if (!pet) { + return false; + } + Unit* target = AI_VALUE(Unit*, "current target"); + if (!target) { + return false; + } + if (pet->GetVictim() == target && pet->GetCharmInfo()->IsCommandAttack()) { + return false; + } + if (bot->GetMap()->IsDungeon() && bot->GetGroup() && !target->IsInCombat()) { + return false; + } + return true; +} + bool HighManaTrigger::IsActive() { return AI_VALUE2(bool, "has mana", "self target") && AI_VALUE2(uint8, "mana", "self target") < 65; diff --git a/src/strategy/triggers/GenericTriggers.h b/src/strategy/triggers/GenericTriggers.h index d72ad48a..2731f9ef 100644 --- a/src/strategy/triggers/GenericTriggers.h +++ b/src/strategy/triggers/GenericTriggers.h @@ -453,6 +453,14 @@ public: virtual bool IsActive() override; }; +class PetAttackTrigger : public Trigger +{ +public: + PetAttackTrigger(PlayerbotAI* ai) : Trigger(ai, "pet attack") {} + + virtual bool IsActive() override; +}; + class ItemCountTrigger : public Trigger { public: diff --git a/src/strategy/triggers/TriggerContext.h b/src/strategy/triggers/TriggerContext.h index 0859d706..6f689e68 100644 --- a/src/strategy/triggers/TriggerContext.h +++ b/src/strategy/triggers/TriggerContext.h @@ -101,6 +101,8 @@ class TriggerContext : public NamedObjectContext creators["combat party member dead"] = &TriggerContext::CombatPartyMemberDead; creators["no pet"] = &TriggerContext::no_pet; creators["has pet"] = &TriggerContext::has_pet; + creators["pet attack"] = &TriggerContext::pet_attack; + creators["has attackers"] = &TriggerContext::has_attackers; creators["no possible targets"] = &TriggerContext::no_possible_targets; creators["possible adds"] = &TriggerContext::possible_adds; @@ -289,6 +291,7 @@ class TriggerContext : public NamedObjectContext static Trigger* protect_party_member(PlayerbotAI* botAI) { return new ProtectPartyMemberTrigger(botAI); } static Trigger* no_pet(PlayerbotAI* botAI) { return new NoPetTrigger(botAI); } static Trigger* has_pet(PlayerbotAI* botAI) { return new HasPetTrigger(botAI); } + static Trigger* pet_attack(PlayerbotAI* botAI) { return new PetAttackTrigger(botAI); } static Trigger* has_attackers(PlayerbotAI* botAI) { return new HasAttackersTrigger(botAI); } static Trigger* random_bot_update_trigger(PlayerbotAI* botAI) { return new RandomBotUpdateTrigger(botAI); } static Trigger* no_non_bot_players_around(PlayerbotAI* botAI) { return new NoNonBotPlayersAroundTrigger(botAI); } diff --git a/src/strategy/warrior/TankWarriorStrategy.cpp b/src/strategy/warrior/TankWarriorStrategy.cpp index c13c6149..42f71fa2 100644 --- a/src/strategy/warrior/TankWarriorStrategy.cpp +++ b/src/strategy/warrior/TankWarriorStrategy.cpp @@ -31,12 +31,12 @@ class TankWarriorStrategyActionNodeFactory : public NamedObjectFactory