From 2ad567a1a8a7076f32fd09c2c59e303e563bd881 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Mon, 29 May 2023 11:45:18 +0800 Subject: [PATCH] Flee action, factory setting --- conf/playerbots.conf.dist | 4 +- src/AiFactory.cpp | 34 +++---- src/PlayerbotAI.cpp | 14 ++- src/PlayerbotFactory.cpp | 38 +++++--- src/PlayerbotMgr.cpp | 7 +- src/RandomItemMgr.cpp | 2 +- src/strategy/actions/FollowActions.cpp | 10 ++ src/strategy/actions/MovementActions.cpp | 32 +++++-- src/strategy/actions/MovementActions.h | 2 +- src/strategy/generic/UseFoodStrategy.cpp | 2 +- src/strategy/hunter/DpsHunterStrategy.cpp | 51 +++------- .../hunter/GenericHunterNonCombatStrategy.cpp | 4 +- src/strategy/hunter/GenericHunterStrategy.cpp | 8 +- src/strategy/hunter/HunterActions.h | 15 +++ src/strategy/hunter/HunterAiObjectContext.cpp | 8 ++ src/strategy/hunter/HunterBuffStrategies.cpp | 1 + src/strategy/hunter/HunterTriggers.cpp | 13 ++- src/strategy/hunter/HunterTriggers.h | 1 + src/strategy/mage/MageAiObjectContext.cpp | 32 +++---- src/strategy/triggers/GenericTriggers.cpp | 18 +++- src/strategy/triggers/GenericTriggers.h | 8 +- src/strategy/triggers/RangeTriggers.cpp | 95 ++++++++++--------- 22 files changed, 236 insertions(+), 163 deletions(-) diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index 0e9b1891..1e10b7f4 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -482,12 +482,12 @@ AiPlayerbot.LootDelay = 1000 AiPlayerbot.FarDistance = 20.0 AiPlayerbot.SightDistance = 60.0 AiPlayerbot.SpellDistance = 26.0 -AiPlayerbot.ShootDistance = 26.0 +AiPlayerbot.ShootDistance = 5.0 AiPlayerbot.ReactDistance = 150.0 AiPlayerbot.GrindDistance = 75.0 AiPlayerbot.HealDistance = 20.0 AiPlayerbot.LootDistance = 15.0 -AiPlayerbot.FleeDistance = 15.0 +AiPlayerbot.FleeDistance = 5.0 AiPlayerbot.TooCloseDistance = 5.0 AiPlayerbot.MeleeDistance = 1.5 AiPlayerbot.FollowDistance = 1.5 diff --git a/src/AiFactory.cpp b/src/AiFactory.cpp index c5ab11fc..aaf68e4c 100644 --- a/src/AiFactory.cpp +++ b/src/AiFactory.cpp @@ -260,7 +260,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa if (!player->InBattleground()) { - engine->addStrategies("racials", "chat", "default", "potions", "cast time", "duel", nullptr); + engine->addStrategies("racials", "chat", "default", "cast time", "duel", nullptr); } switch (player->getClass()) @@ -270,16 +270,10 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa { engine->addStrategies("dps", "shadow debuff", "shadow aoe", "threat", nullptr); } - else if (tab == 0) - { - engine->addStrategies("holy", "shadow debuff", "shadow aoe", "threat", nullptr); - //if (player->getLevel() >= 4) - //engine->addStrategy("dps debuff"); - } else engine->addStrategies("heal", "threat", nullptr); - engine->addStrategies("dps assist", "flee", "cure", "ranged", nullptr); + engine->addStrategies("dps assist", "cure", "ranged", nullptr); break; case CLASS_MAGE: if (tab == 0) @@ -289,7 +283,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa else engine->addStrategies("frost", "frost aoe", "threat", "dps aoe", nullptr); - engine->addStrategies("dps", "dps assist", "flee", "cure", "ranged", nullptr); + engine->addStrategies("dps", "dps assist", "cure", "ranged", nullptr); break; case CLASS_WARRIOR: if (tab == 2) @@ -301,9 +295,9 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa break; case CLASS_SHAMAN: if (tab == 0) - engine->addStrategies("caster", "caster aoe", "bmana", "threat", "flee", "ranged", nullptr); + engine->addStrategies("caster", "caster aoe", "bmana", "threat", "ranged", nullptr); else if (tab == 2) - engine->addStrategies("heal", "bmana", "flee", "ranged", nullptr); + engine->addStrategies("heal", "bmana", "ranged", nullptr); else engine->addStrategies("dps", "melee aoe", "bdps", "threat", "close", nullptr); @@ -313,7 +307,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa if (tab == 1) engine->addStrategies("tank", "tank assist", "bthreat", "cure", "baoe", "bstats", "close", nullptr); else if (tab == 0) - engine->addStrategies("heal", "bmana", "dps assist", "cure", "flee", nullptr); + engine->addStrategies("heal", "bmana", "dps assist", "cure", nullptr); else engine->addStrategies("dps", "bdps", "dps assist", "cure", "close", nullptr); @@ -330,21 +324,21 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa case CLASS_DRUID: if (tab == 0) { - engine->addStrategies("caster", "cure", "caster aoe", "threat", "flee", "dps assist", "ranged", nullptr); + engine->addStrategies("caster", "cure", "caster aoe", "threat", "dps assist", "ranged", nullptr); if (player->getLevel() > 19) engine->addStrategy("caster debuff"); } else if (tab == 2) - engine->addStrategies("heal", "cure", "flee", "dps assist", "ranged", nullptr); + engine->addStrategies("heal", "cure", "dps assist", "ranged", nullptr); else { engine->removeStrategy("ranged"); engine->removeStrategy("flee"); - engine->addStrategies("bear", "tank assist", "flee", "close", nullptr); + engine->addStrategies("bear", "tank assist", "close", nullptr); } break; case CLASS_HUNTER: - engine->addStrategies("dps", "bdps", "threat", "dps assist", "ranged", "pet", nullptr); + engine->addStrategies("dps", "aoe", "bdps", "threat", "dps assist", "ranged", nullptr); if (player->getLevel() > 19) engine->addStrategy("dps debuff"); break; @@ -355,7 +349,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa if (player->getLevel() > 19) engine->addStrategy("dps debuff"); - engine->addStrategies("dps assist", "dps", "flee", "ranged", "pet", "threat", nullptr); + engine->addStrategies("dps assist", "dps", "aoe", "ranged", "pet", "threat", nullptr); break; case CLASS_DEATH_KNIGHT: if (tab == 0) @@ -365,7 +359,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa else engine->addStrategies("unholy", "unholy aoe", "dps assist", "threat", nullptr); - engine->addStrategies("dps assist", "flee", "close", nullptr); + engine->addStrategies("dps assist", "close", nullptr); break; } @@ -376,7 +370,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa { engine->ChangeStrategy(sPlayerbotAIConfig->randomBotCombatStrategies); - engine->addStrategy("flee"); + // engine->addStrategy("flee"); engine->addStrategy("boost"); if (player->getClass() == CLASS_WARLOCK) @@ -493,7 +487,7 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const nonCombatEngine->addStrategies("barmor", nullptr); break; case CLASS_HUNTER: - nonCombatEngine->addStrategies("bdps", "dps assist", nullptr); + nonCombatEngine->addStrategies("bdps", "dps assist", "pet", nullptr); break; case CLASS_SHAMAN: if (tab == 0 || tab == 2) diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index 319b5f42..3350f263 100644 --- a/src/PlayerbotAI.cpp +++ b/src/PlayerbotAI.cpp @@ -1648,11 +1648,21 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell, if (pet->HasSpell(spellid)) return true; - if (checkHasSpell && !bot->HasSpell(spellid)) + if (checkHasSpell && !bot->HasSpell(spellid)) { + if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) { + LOG_DEBUG("playerbots", "Can cast spell failed. Bot not has spell. - target name: {}, spellid: {}, bot name: {}", + target->GetName(), spellid, bot->GetName()); + } return false; + } - if (bot->HasSpellCooldown(spellid)) + if (bot->HasSpellCooldown(spellid)) { + if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) { + LOG_DEBUG("playerbots", "Can cast spell failed. Spell not has cooldown. - target name: {}, spellid: {}, bot name: {}", + target->GetName(), spellid, bot->GetName()); + } return false; + } SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellid); if (!spellInfo) diff --git a/src/PlayerbotFactory.cpp b/src/PlayerbotFactory.cpp index a8d39f22..34cc3209 100644 --- a/src/PlayerbotFactory.cpp +++ b/src/PlayerbotFactory.cpp @@ -335,15 +335,7 @@ void PlayerbotFactory::Randomize(bool incremental) pmo = sPerformanceMonitor->start(PERF_MON_RNDBOT, "PlayerbotFactory_Save"); LOG_INFO("playerbots", "Saving to DB..."); - if (incremental) - { - uint32 money = bot->GetMoney(); - bot->SetMoney(money + 1000 * sqrt(urand(1, level * 5))); - } - else - { - bot->SetMoney(10000 * sqrt(urand(1, level * 5))); - } + bot->SetMoney(urand(level * 100000, level * 5 * 100000)); bot->SaveToDB(false, false); LOG_INFO("playerbots", "Done."); if (pmo) @@ -353,10 +345,25 @@ void PlayerbotFactory::Randomize(bool incremental) void PlayerbotFactory::Refresh() { Prepare(); + InitEquipment(true); InitAmmo(); InitFood(); - InitPotions(); InitReagents(); + InitPotions(); + InitTalents(true); + InitClassSpells(); + InitAvailableSpells(); + bot->DurabilityRepairAll(false, 1.0f, false); + uint32 money = urand(level * 1000, level * 5 * 1000); + if (bot->GetMoney() < money) + bot->SetMoney(money); + bot->SaveToDB(false, false); + + // Prepare(); + // InitAmmo(); + // InitFood(); + // InitPotions(); + //bot->SaveToDB(); } @@ -1731,12 +1738,13 @@ void PlayerbotFactory::SetRandomSkill(uint16 id) uint32 maxValue = level * 5; // do not let skill go beyond limit even if maxlevel > blizzlike - if (level > 60) - { - maxValue = (level + 10) * 5; - } + // if (level > 60) + // { + // maxValue = (level + 10) * 5; + // } - uint32 value = urand(maxValue - level, maxValue); + // uint32 value = urand(maxValue - level, maxValue); + uint32 value = maxValue; uint32 curValue = bot->GetSkillValue(id); uint16 step = bot->GetSkillValue(id) ? bot->GetSkillStep(id) : 1; diff --git a/src/PlayerbotMgr.cpp b/src/PlayerbotMgr.cpp index 58b9a302..9ab42eb3 100644 --- a/src/PlayerbotMgr.cpp +++ b/src/PlayerbotMgr.cpp @@ -3,6 +3,7 @@ */ #include "CharacterPackets.h" +#include "Common.h" #include "ObjectAccessor.h" #include "ObjectMgr.h" #include "PlayerbotMgr.h" @@ -519,6 +520,10 @@ std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, Obje if (!bot) return "bot not found"; + + if (!isRandomAccount || !isRandomBot) { + return "ERROR: You can not use this command on non-ramdom bot."; + } if (Player* master = GET_PLAYERBOT_AI(bot)->GetMaster()) { @@ -846,7 +851,7 @@ std::vector PlayerbotHolder::HandlePlayerbotCommand(char const* arg } else if (master && member != master->GetGUID()) { - out << ProcessBotCommand(cmdStr, member, master->GetGUID(), master->GetSession()->GetSecurity() >= SEC_GAMEMASTER, master->GetSession()->GetAccountId(), master->GetGuildId()); + out << ProcessBotCommand(cmdStr, member, master->GetGUID(), true, master->GetSession()->GetAccountId(), master->GetGuildId()); } else if (!master) { diff --git a/src/RandomItemMgr.cpp b/src/RandomItemMgr.cpp index a0bba9a4..bab37525 100644 --- a/src/RandomItemMgr.cpp +++ b/src/RandomItemMgr.cpp @@ -2195,7 +2195,7 @@ void RandomItemMgr::BuildAmmoCache() uint32 RandomItemMgr::GetAmmo(uint32 level, uint32 subClass) { - return ammoCache[(level - 1) / 10][subClass]; + return ammoCache[level / 10][subClass]; } void RandomItemMgr::BuildPotionCache() diff --git a/src/strategy/actions/FollowActions.cpp b/src/strategy/actions/FollowActions.cpp index 62aa933b..a457028e 100644 --- a/src/strategy/actions/FollowActions.cpp +++ b/src/strategy/actions/FollowActions.cpp @@ -27,6 +27,16 @@ bool FollowAction::Execute(Event event) moved = MoveTo(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ()); } + if (Pet* pet = bot->GetPet()) + { + if (CreatureAI* creatureAI = ((Creature*)pet)->AI()) + { + pet->SetReactState(REACT_PASSIVE); + pet->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW); + pet->GetCharmInfo()->SetIsFollowing(true); + pet->AttackStop(); + } + } //if (moved) //botAI->SetNextCheckDelay(sPlayerbotAIConfig->reactDelay); diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index bc8bb1a6..d9faa7e9 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -4,6 +4,7 @@ #include "MovementActions.h" #include "MovementGenerator.h" +#include "PlayerbotAIConfig.h" #include "TargetedMovementGenerator.h" #include "Event.h" #include "LastMovementValue.h" @@ -1211,22 +1212,33 @@ void MovementAction::ClearIdleState() context->GetValue("position")->Get()["random"].Reset(); } +bool MovementAction::MoveAway(Unit* target) +{ + float angle = target->GetAngle(bot); + float dx = bot->GetPositionX() + cos(angle) * sPlayerbotAIConfig->fleeDistance; + float dy = bot->GetPositionY() + sin(angle) * sPlayerbotAIConfig->fleeDistance; + float dz = bot->GetPositionZ(); + return MoveTo(target->GetMapId(), dx, dy, dz); +} + bool FleeAction::Execute(Event event) { - return Flee(AI_VALUE(Unit*, "current target")); + // return Flee(AI_VALUE(Unit*, "current target")); + return MoveAway(AI_VALUE(Unit*, "current target")); } bool FleeWithPetAction::Execute(Event event) { - // if (Pet* pet = bot->GetPet()) - // { - // if (CreatureAI* creatureAI = ((Creature*)pet)->AI()) - // { - // pet->SetReactState(REACT_PASSIVE); - // pet->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW); - // pet->AttackStop(); - // } - // } + if (Pet* pet = bot->GetPet()) + { + if (CreatureAI* creatureAI = ((Creature*)pet)->AI()) + { + pet->SetReactState(REACT_PASSIVE); + pet->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW); + pet->GetCharmInfo()->SetIsFollowing(true); + pet->AttackStop(); + } + } return Flee(AI_VALUE(Unit*, "current target")); } diff --git a/src/strategy/actions/MovementActions.h b/src/strategy/actions/MovementActions.h index 41e77769..56183d20 100644 --- a/src/strategy/actions/MovementActions.h +++ b/src/strategy/actions/MovementActions.h @@ -36,7 +36,7 @@ class MovementAction : public Action bool Flee(Unit *target); void ClearIdleState(); void UpdateMovementState(); - + bool MoveAway(Unit* target); void CreateWp(Player* wpOwner, float x, float y, float z, float o, uint32 entry, bool important = false); }; diff --git a/src/strategy/generic/UseFoodStrategy.cpp b/src/strategy/generic/UseFoodStrategy.cpp index 93fb0f64..f97a70f8 100644 --- a/src/strategy/generic/UseFoodStrategy.cpp +++ b/src/strategy/generic/UseFoodStrategy.cpp @@ -10,5 +10,5 @@ void UseFoodStrategy::InitTriggers(std::vector& triggers) Strategy::InitTriggers(triggers); triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("food", 3.0f), nullptr))); - triggers.push_back(new TriggerNode("high mana", NextAction::array(0, new NextAction("drink", 3.0f), nullptr))); + triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("drink", 3.0f), nullptr))); } diff --git a/src/strategy/hunter/DpsHunterStrategy.cpp b/src/strategy/hunter/DpsHunterStrategy.cpp index d62b135d..32c0acb0 100644 --- a/src/strategy/hunter/DpsHunterStrategy.cpp +++ b/src/strategy/hunter/DpsHunterStrategy.cpp @@ -11,50 +11,14 @@ class DpsHunterStrategyActionNodeFactory : public NamedObjectFactory DpsHunterStrategyActionNodeFactory() { creators["aimed shot"] = &aimed_shot; - creators["chimera shot"] = &chimera_shot; - creators["explosive shot"] = &explosive_shot; - creators["concussive shot"] = &concussive_shot; - creators["viper sting"] = &viper_sting; } private: - static ActionNode* viper_sting([[maybe_unused]] PlayerbotAI* botAI) - { - return new ActionNode ("viper sting", - /*P*/ nullptr, - /*A*/ NextAction::array(0, new NextAction("mana potion", 10.0f), nullptr), - /*C*/ nullptr); - } - static ActionNode* aimed_shot([[maybe_unused]] PlayerbotAI* botAI) { return new ActionNode ("aimed shot", /*P*/ nullptr, - /*A*/ NextAction::array(0, new NextAction("chimera shot", 10.0f), nullptr), - /*C*/ nullptr); - } - - static ActionNode* chimera_shot([[maybe_unused]] PlayerbotAI* botAI) - { - return new ActionNode ("chimera shot", - /*P*/ nullptr, - /*A*/ NextAction::array(0, new NextAction("arcane shot", 10.0f), nullptr), - /*C*/ nullptr); - } - - static ActionNode* explosive_shot([[maybe_unused]] PlayerbotAI* botAI) - { - return new ActionNode ("explosive shot", - /*P*/ nullptr, - /*A*/ NextAction::array(0, new NextAction("aimed shot"), nullptr), - /*C*/ nullptr); - } - - static ActionNode* concussive_shot([[maybe_unused]] PlayerbotAI* botAI) - { - return new ActionNode ("concussive shot", - /*P*/ nullptr, - /*A*/ nullptr, + /*A*/ NextAction::array(0, new NextAction("multi-shot", 10.0f), nullptr), /*C*/ nullptr); } }; @@ -66,7 +30,16 @@ DpsHunterStrategy::DpsHunterStrategy(PlayerbotAI* botAI) : GenericHunterStrategy NextAction** DpsHunterStrategy::getDefaultActions() { - return NextAction::array(0, new NextAction("explosive shot", 11.0f), new NextAction("auto shot", 10.0f), new NextAction("auto attack", 9.0f), nullptr); + return NextAction::array(0, + new NextAction("kill shot", 16.0f), + new NextAction("chimera shot", 15.0f), + new NextAction("explosive shot", 15.0f), + new NextAction("aimed shot", 14.0f), + new NextAction("arcane shot", 13.0f), + new NextAction("steady shot", 12.0f), + new NextAction("auto shot", 10.0f), + NULL); + // return NextAction::array(0, new NextAction("explosive shot", 11.0f), new NextAction("auto shot", 10.0f), new NextAction("auto attack", 9.0f), nullptr); } void DpsHunterStrategy::InitTriggers(std::vector& triggers) @@ -77,6 +50,8 @@ void DpsHunterStrategy::InitTriggers(std::vector& triggers) triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("viper sting", 23), nullptr))); triggers.push_back(new TriggerNode("hunter's mark", NextAction::array(0, new NextAction("hunter's mark", 19.0f), nullptr))); triggers.push_back(new TriggerNode("concussive shot on snare target", NextAction::array(0, new NextAction("concussive shot", 20.0f), nullptr))); + triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("call pet", 21.0f), NULL))); + triggers.push_back(new TriggerNode("hunters pet low health", NextAction::array(0, new NextAction("mend pet", 21.0f), NULL))); /*triggers.push_back(new TriggerNode("has aggro", NextAction::array(0, new NextAction("concussive shot", 20.0f), nullptr)));*/ } diff --git a/src/strategy/hunter/GenericHunterNonCombatStrategy.cpp b/src/strategy/hunter/GenericHunterNonCombatStrategy.cpp index c4b7e83f..1ee4bbe0 100644 --- a/src/strategy/hunter/GenericHunterNonCombatStrategy.cpp +++ b/src/strategy/hunter/GenericHunterNonCombatStrategy.cpp @@ -45,8 +45,8 @@ void GenericHunterNonCombatStrategy::InitTriggers(std::vector& tri triggers.push_back(new TriggerNode("trueshot aura", NextAction::array(0, new NextAction("trueshot aura", 2.0f), nullptr))); triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("apply oil", 1.0f), nullptr))); triggers.push_back(new TriggerNode("low ammo", NextAction::array(0, new NextAction("say::low ammo", ACTION_NORMAL), nullptr))); - triggers.push_back(new TriggerNode("no ammo", NextAction::array(0, new NextAction("switch to melee", ACTION_NORMAL + 1), new NextAction("say::no ammo", ACTION_NORMAL), nullptr))); - triggers.push_back(new TriggerNode("has ammo", NextAction::array(0, new NextAction("switch to ranged", ACTION_NORMAL), nullptr))); + // triggers.push_back(new TriggerNode("no ammo", NextAction::array(0, new NextAction("switch to melee", ACTION_NORMAL + 1), new NextAction("say::no ammo", ACTION_NORMAL), nullptr))); + // triggers.push_back(new TriggerNode("has ammo", NextAction::array(0, new NextAction("switch to ranged", ACTION_NORMAL), nullptr))); } void HunterPetStrategy::InitTriggers(std::vector& triggers) diff --git a/src/strategy/hunter/GenericHunterStrategy.cpp b/src/strategy/hunter/GenericHunterStrategy.cpp index 234a00bf..3059d07e 100644 --- a/src/strategy/hunter/GenericHunterStrategy.cpp +++ b/src/strategy/hunter/GenericHunterStrategy.cpp @@ -69,13 +69,13 @@ void GenericHunterStrategy::InitTriggers(std::vector& triggers) { CombatStrategy::InitTriggers(triggers); - triggers.push_back(new TriggerNode("enemy too close for auto shot", NextAction::array(0, new NextAction("switch to melee", ACTION_HIGH), nullptr))); + // triggers.push_back(new TriggerNode("enemy too close for auto shot", NextAction::array(0, new NextAction("switch to melee", ACTION_HIGH), nullptr))); triggers.push_back(new TriggerNode("enemy is close", NextAction::array(0, new NextAction("wing clip", ACTION_HIGH), nullptr))); triggers.push_back(new TriggerNode("medium threat", NextAction::array(0, new NextAction("feign death", 35.0f), nullptr))); triggers.push_back(new TriggerNode("hunters pet low health", NextAction::array(0, new NextAction("mend pet", ACTION_HIGH + 2), nullptr))); - triggers.push_back(new TriggerNode("switch to melee", NextAction::array(0, new NextAction("switch to melee", ACTION_HIGH + 1), nullptr))); - triggers.push_back(new TriggerNode("switch to ranged", NextAction::array(0, new NextAction("switch to ranged", ACTION_HIGH), nullptr))); - triggers.push_back(new TriggerNode("no ammo", NextAction::array(0, new NextAction("switch to melee", ACTION_HIGH + 1), new NextAction("say::no ammo", ACTION_HIGH), nullptr))); + // triggers.push_back(new TriggerNode("no ammo", NextAction::array(0, new NextAction("switch to melee", ACTION_HIGH + 1), new NextAction("say::no ammo", ACTION_HIGH), nullptr))); + triggers.push_back(new TriggerNode("aspect of the viper", NextAction::array(0, new NextAction("aspect of the viper", ACTION_HIGH), NULL))); + triggers.push_back(new TriggerNode("enemy too close for shoot", NextAction::array(0, new NextAction("flee", ACTION_HIGH + 3), NULL))); } NextAction** HunterBoostStrategy::getDefaultActions() diff --git a/src/strategy/hunter/HunterActions.h b/src/strategy/hunter/HunterActions.h index 088d8ded..91e58798 100644 --- a/src/strategy/hunter/HunterActions.h +++ b/src/strategy/hunter/HunterActions.h @@ -62,12 +62,27 @@ END_SPELL_ACTION() BEGIN_RANGED_SPELL_ACTION(CastScorpidStingAction, "scorpid sting") END_SPELL_ACTION() +BEGIN_RANGED_SPELL_ACTION(CastSteadyShotAction, "steady shot") +END_SPELL_ACTION() + +BEGIN_RANGED_SPELL_ACTION(CastKillShotAction, "kill shot") +END_SPELL_ACTION() + +BEGIN_RANGED_SPELL_ACTION(CastTranquilizingShortAction, "tranquilizing shot") +END_SPELL_ACTION() + class CastAspectOfTheHawkAction : public CastBuffSpellAction { public: CastAspectOfTheHawkAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "aspect of the hawk") { } }; +class CastAspectOfTheDragonhawkAction : public CastBuffSpellAction +{ +public: + CastAspectOfTheDragonhawkAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "aspect of the dragonhawk") {} +}; + class CastAspectOfTheWildAction : public CastBuffSpellAction { public: diff --git a/src/strategy/hunter/HunterAiObjectContext.cpp b/src/strategy/hunter/HunterAiObjectContext.cpp index 1f31bc33..ea7a3f71 100644 --- a/src/strategy/hunter/HunterAiObjectContext.cpp +++ b/src/strategy/hunter/HunterAiObjectContext.cpp @@ -148,6 +148,10 @@ class HunterAiObjectContextInternal : public NamedObjectContext creators["bestial wrath"] = &HunterAiObjectContextInternal::bestial_wrath; creators["scare beast"] = &HunterAiObjectContextInternal::scare_beast; creators["scare beast on cc"] = &HunterAiObjectContextInternal::scare_beast_on_cc; + creators["aspect of the dragonhawk"] = &HunterAiObjectContextInternal::aspect_of_the_dragonhawk; + creators["tranquilizing shot"] = &HunterAiObjectContextInternal::tranquilizing_shot; + creators["steady shot"] = &HunterAiObjectContextInternal::steady_shot; + creators["kill shot"] = &HunterAiObjectContextInternal::kill_shot; } private: @@ -186,6 +190,10 @@ class HunterAiObjectContextInternal : public NamedObjectContext static Action* aspect_of_the_cheetah(PlayerbotAI* botAI) { return new CastAspectOfTheCheetahAction(botAI); } static Action* wing_clip(PlayerbotAI* botAI) { return new CastWingClipAction(botAI); } static Action* raptor_strike(PlayerbotAI* botAI) { return new CastRaptorStrikeAction(botAI); } + static Action* aspect_of_the_dragonhawk(PlayerbotAI* ai) { return new CastAspectOfTheDragonhawkAction(ai); } + static Action* tranquilizing_shot(PlayerbotAI* ai) { return new CastTranquilizingShortAction(ai); } + static Action* steady_shot(PlayerbotAI* ai) { return new CastSteadyShotAction(ai); } + static Action* kill_shot(PlayerbotAI* ai) { return new CastKillShotAction(ai); } }; HunterAiObjectContext::HunterAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) diff --git a/src/strategy/hunter/HunterBuffStrategies.cpp b/src/strategy/hunter/HunterBuffStrategies.cpp index 9f719090..739e8e5a 100644 --- a/src/strategy/hunter/HunterBuffStrategies.cpp +++ b/src/strategy/hunter/HunterBuffStrategies.cpp @@ -7,6 +7,7 @@ void HunterBuffDpsStrategy::InitTriggers(std::vector& triggers) { + triggers.push_back(new TriggerNode("aspect of the hawk", NextAction::array(0, new NextAction("aspect of the dragonhawk", 90.0f), nullptr))); triggers.push_back(new TriggerNode("aspect of the hawk", NextAction::array(0, new NextAction("aspect of the hawk", 90.0f), nullptr))); } diff --git a/src/strategy/hunter/HunterTriggers.cpp b/src/strategy/hunter/HunterTriggers.cpp index 76da6c1b..57259306 100644 --- a/src/strategy/hunter/HunterTriggers.cpp +++ b/src/strategy/hunter/HunterTriggers.cpp @@ -7,6 +7,14 @@ #include "Playerbots.h" #include "ServerFacade.h" +bool HunterAspectOfTheHawkTrigger::IsActive() +{ + Unit* target = GetTarget(); + return SpellTrigger::IsActive() && + !botAI->HasAura("aspect of the hawk", target) && !botAI->HasAura("aspect of the dragonhawk", target) && + (!AI_VALUE2(bool, "has mana", "self target") || AI_VALUE2(uint8, "mana", "self target") > 70); +} + bool HunterNoStingsActiveTrigger::IsActive() { Unit* target = AI_VALUE(Unit*, "current target"); @@ -16,6 +24,8 @@ bool HunterNoStingsActiveTrigger::IsActive() bool HuntersPetDeadTrigger::IsActive() { + // Unit* pet = AI_VALUE(Unit*, "pet target"); + // return pet && AI_VALUE2(bool, "dead", "pet target") && !AI_VALUE2(bool, "mounted", "self target"); return AI_VALUE(bool, "pet dead") && !AI_VALUE2(bool, "mounted", "self target"); } @@ -32,7 +42,8 @@ bool HunterPetNotHappy::IsActive() bool HunterAspectOfTheViperTrigger::IsActive() { - return SpellTrigger::IsActive() && !botAI->HasAura(spell, GetTarget()); + return SpellTrigger::IsActive() && !botAI->HasAura(spell, GetTarget()) && + AI_VALUE2(uint8, "mana", "self target") < sPlayerbotAIConfig->lowMana;; } bool HunterAspectOfThePackTrigger::IsActive() diff --git a/src/strategy/hunter/HunterTriggers.h b/src/strategy/hunter/HunterTriggers.h index f16ed103..f02154d7 100644 --- a/src/strategy/hunter/HunterTriggers.h +++ b/src/strategy/hunter/HunterTriggers.h @@ -24,6 +24,7 @@ class HunterAspectOfTheHawkTrigger : public BuffTrigger { public: HunterAspectOfTheHawkTrigger(PlayerbotAI* botAI) : BuffTrigger(botAI, "aspect of the hawk") { } + bool IsActive() override; }; class HunterAspectOfTheWildTrigger : public BuffTrigger diff --git a/src/strategy/mage/MageAiObjectContext.cpp b/src/strategy/mage/MageAiObjectContext.cpp index 86473f9b..4e76715c 100644 --- a/src/strategy/mage/MageAiObjectContext.cpp +++ b/src/strategy/mage/MageAiObjectContext.cpp @@ -13,19 +13,19 @@ #include "PullStrategy.h" #include "Playerbots.h" -class StrategyFactoryInternal : public NamedObjectContext +class MageStrategyFactoryInternal : public NamedObjectContext { public: - StrategyFactoryInternal() + MageStrategyFactoryInternal() { - creators["nc"] = &StrategyFactoryInternal::nc; - creators["pull"] = &StrategyFactoryInternal::pull; - creators["fire aoe"] = &StrategyFactoryInternal::fire_aoe; - creators["frost aoe"] = &StrategyFactoryInternal::frost_aoe; - creators["cure"] = &StrategyFactoryInternal::cure; - creators["buff"] = &StrategyFactoryInternal::buff; - creators["boost"] = &StrategyFactoryInternal::boost; - creators["cc"] = &StrategyFactoryInternal::cc; + creators["nc"] = &MageStrategyFactoryInternal::nc; + creators["pull"] = &MageStrategyFactoryInternal::pull; + creators["fire aoe"] = &MageStrategyFactoryInternal::fire_aoe; + creators["frost aoe"] = &MageStrategyFactoryInternal::frost_aoe; + creators["cure"] = &MageStrategyFactoryInternal::cure; + creators["buff"] = &MageStrategyFactoryInternal::buff; + creators["boost"] = &MageStrategyFactoryInternal::boost; + creators["cc"] = &MageStrategyFactoryInternal::cc; } private: @@ -39,14 +39,14 @@ class StrategyFactoryInternal : public NamedObjectContext static Strategy* cc(PlayerbotAI* botAI) { return new MageCcStrategy(botAI); } }; -class MageStrategyFactoryInternal : public NamedObjectContext +class MageCombatStrategyFactoryInternal : public NamedObjectContext { public: - MageStrategyFactoryInternal() : NamedObjectContext(false, true) + MageCombatStrategyFactoryInternal() : NamedObjectContext(false, true) { - creators["frost"] = &MageStrategyFactoryInternal::frost; - creators["fire"] = &MageStrategyFactoryInternal::fire; - creators["arcane"] = &MageStrategyFactoryInternal::arcane; + creators["frost"] = &MageCombatStrategyFactoryInternal::frost; + creators["fire"] = &MageCombatStrategyFactoryInternal::fire; + creators["arcane"] = &MageCombatStrategyFactoryInternal::arcane; } private: @@ -213,7 +213,7 @@ class MageAiObjectContextInternal : public NamedObjectContext MageAiObjectContext::MageAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI) { strategyContexts.Add(new MageStrategyFactoryInternal()); - strategyContexts.Add(new MageStrategyFactoryInternal()); + strategyContexts.Add(new MageCombatStrategyFactoryInternal()); strategyContexts.Add(new MageBuffStrategyFactoryInternal()); actionContexts.Add(new MageAiObjectContextInternal()); triggerContexts.Add(new MageTriggerFactoryInternal()); diff --git a/src/strategy/triggers/GenericTriggers.cpp b/src/strategy/triggers/GenericTriggers.cpp index 6fa87e57..d1c2f822 100644 --- a/src/strategy/triggers/GenericTriggers.cpp +++ b/src/strategy/triggers/GenericTriggers.cpp @@ -145,7 +145,23 @@ bool MyAttackerCountTrigger::IsActive() bool AoeTrigger::IsActive() { - return AI_VALUE2(bool, "combat", "self target") && AI_VALUE(uint8, "aoe count") >= amount && AI_VALUE(uint8, "attacker count") >= amount; + Unit* current_target = AI_VALUE(Unit*, "current target"); + if (!current_target) { + return false; + } + GuidVector attackers = context->GetValue("attackers")->Get(); + int attackers_count = 0; + for (ObjectGuid const guid : attackers) + { + Unit* unit = botAI->GetUnit(guid); + if (!unit || !unit->IsAlive()) + continue; + + if (unit->GetExactDist2d(current_target) <= range) { + attackers_count++; + } + } + return attackers_count >= amount; } bool NoFoodTrigger::IsActive() diff --git a/src/strategy/triggers/GenericTriggers.h b/src/strategy/triggers/GenericTriggers.h index 85e5d172..284c2cca 100644 --- a/src/strategy/triggers/GenericTriggers.h +++ b/src/strategy/triggers/GenericTriggers.h @@ -225,19 +225,19 @@ class NoDrinkTrigger : public Trigger class LightAoeTrigger : public AoeTrigger { public: - LightAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 2, 15.0f) { } + LightAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 2, 8.0f) { } }; class MediumAoeTrigger : public AoeTrigger { public: - MediumAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 3, 17.0f) { } + MediumAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 3, 8.0f) { } }; class HighAoeTrigger : public AoeTrigger { public: - HighAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 4, 20.0f) { } + HighAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 4, 8.0f) { } }; class BuffTrigger : public SpellTrigger @@ -413,7 +413,7 @@ END_TRIGGER() class NoPetTrigger : public Trigger { public: - NoPetTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no pet", 30) { } + NoPetTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no pet", 5) { } bool IsActive() override; }; diff --git a/src/strategy/triggers/RangeTriggers.cpp b/src/strategy/triggers/RangeTriggers.cpp index 41b8cb0b..734cfc1f 100644 --- a/src/strategy/triggers/RangeTriggers.cpp +++ b/src/strategy/triggers/RangeTriggers.cpp @@ -15,33 +15,37 @@ static float GetSpeedInMotion(Unit* target) bool EnemyTooCloseForSpellTrigger::IsActive() { Unit* target = AI_VALUE(Unit*, "current target"); - if (target) - { - if (target->GetTarget() == bot->GetGUID() && !bot->GetGroup() && !target->HasUnitState(UNIT_STATE_ROOT) && GetSpeedInMotion(target) > GetSpeedInMotion(bot) * 0.65f) - return false; + return target && target->GetVictim() != bot && + target->GetObjectSize() <= 10.0f && + AI_VALUE2(float, "distance", "current target") <= sPlayerbotAIConfig->tooCloseDistance; +// Unit* target = AI_VALUE(Unit*, "current target"); +// if (!target) { +// return false; +// } - bool isBoss = false; - bool isRaid = false; - float combatReach = bot->GetCombatReach() + target->GetCombatReach(); - float targetDistance = sServerFacade->GetDistance2d(bot, target) + combatReach; - if (target->GetTypeId() == TYPEID_UNIT) - { - Creature* creature = botAI->GetCreature(target->GetGUID()); - if (creature) - { - isBoss = creature->isWorldBoss(); - } - } +// if (target->GetTarget() == bot->GetGUID() && !bot->GetGroup() && !target->HasUnitState(UNIT_STATE_ROOT) && GetSpeedInMotion(target) > GetSpeedInMotion(bot) * 0.65f) +// return false; - if (bot->GetMap() && bot->GetMap()->IsRaid()) - isRaid = true; +// bool isBoss = false; +// bool isRaid = false; +// float combatReach = bot->GetCombatReach() + target->GetCombatReach(); +// float targetDistance = sServerFacade->GetDistance2d(bot, target) + combatReach; +// if (target->GetTypeId() == TYPEID_UNIT) +// { +// Creature* creature = botAI->GetCreature(target->GetGUID()); +// if (creature) +// { +// isBoss = creature->isWorldBoss(); +// } +// } -// if (isBoss || isRaid) -// return sServerFacade->IsDistanceLessThan(targetDistance, (botAI->GetRange("spell") + combatReach) / 2); +// if (bot->GetMap() && bot->GetMap()->IsRaid()) +// isRaid = true; - return sServerFacade->IsDistanceLessOrEqualThan(targetDistance, (botAI->GetRange("spell") + combatReach / 2)); - } - return false; +// // if (isBoss || isRaid) +// // return sServerFacade->IsDistanceLessThan(targetDistance, (sPlayerbotAIConfig->tooCloseDistance + combatReach) / 2); + +// return sServerFacade->IsDistanceLessOrEqualThan(targetDistance, (sPlayerbotAIConfig->tooCloseDistance + combatReach / 2)); } bool EnemyTooCloseForAutoShotTrigger::IsActive() @@ -75,32 +79,35 @@ bool EnemyTooCloseForAutoShotTrigger::IsActive() bool EnemyTooCloseForShootTrigger::IsActive() { Unit* target = AI_VALUE(Unit*, "current target"); - if (!target) - return false; + return target && target->GetVictim() != bot && AI_VALUE2(float, "distance", "current target") <= sPlayerbotAIConfig->shootDistance; - if (target->GetTarget() == bot->GetGUID() && !bot->GetGroup() && !target->HasUnitState(UNIT_STATE_ROOT) && GetSpeedInMotion(target) > GetSpeedInMotion(bot) * 0.65f) - return false; +// Unit* target = AI_VALUE(Unit*, "current target"); +// if (!target) +// return false; - bool isBoss = false; - bool isRaid = false; - float combatReach = bot->GetCombatReach() + target->GetCombatReach(); - float targetDistance = sServerFacade->GetDistance2d(bot, target) + combatReach; - if (target->GetTypeId() == TYPEID_UNIT) - { - Creature* creature = botAI->GetCreature(target->GetGUID()); - if (creature) - { - isBoss = creature->isWorldBoss(); - } - } +// if (target->GetTarget() == bot->GetGUID() && !bot->GetGroup() && !target->HasUnitState(UNIT_STATE_ROOT) && GetSpeedInMotion(target) > GetSpeedInMotion(bot) * 0.65f) +// return false; - if (bot->GetMap() && bot->GetMap()->IsRaid()) - isRaid = true; +// bool isBoss = false; +// bool isRaid = false; +// float combatReach = bot->GetCombatReach() + target->GetCombatReach(); +// float targetDistance = sServerFacade->GetDistance2d(bot, target) + combatReach; +// if (target->GetTypeId() == TYPEID_UNIT) +// { +// Creature* creature = botAI->GetCreature(target->GetGUID()); +// if (creature) +// { +// isBoss = creature->isWorldBoss(); +// } +// } -// if (isBoss || isRaid) -// return sServerFacade->IsDistanceLessThan(targetDistance, botAI->GetRange("shoot") + combatReach); +// if (bot->GetMap() && bot->GetMap()->IsRaid()) +// isRaid = true; - return sServerFacade->IsDistanceLessOrEqualThan(targetDistance, (botAI->GetRange("shoot") + combatReach / 2)); +// // if (isBoss || isRaid) +// // return sServerFacade->IsDistanceLessThan(targetDistance, botAI->GetRange("shoot") + combatReach); + +// return sServerFacade->IsDistanceLessOrEqualThan(targetDistance, (botAI->GetRange("shoot") + combatReach / 2)); } bool EnemyTooCloseForMeleeTrigger::IsActive()