From a63c6b6709f94d79829019700af8b195ed054b6d Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Sun, 22 Oct 2023 01:27:37 +0800 Subject: [PATCH 01/12] smarter dps target and tank target --- src/AiFactory.cpp | 12 ++-- src/PlayerbotAI.cpp | 13 ++++ src/PlayerbotAI.h | 1 + src/PlayerbotMgr.cpp | 5 +- src/strategy/Strategy.h | 42 ++++++++----- src/strategy/deathknight/BloodDKStrategy.cpp | 18 +++--- src/strategy/deathknight/FrostDKStrategy.cpp | 10 ++-- src/strategy/deathknight/UnholyDKStrategy.cpp | 18 +++--- src/strategy/hunter/DpsHunterStrategy.cpp | 2 +- src/strategy/triggers/GenericTriggers.cpp | 2 +- src/strategy/values/AttackerCountValues.cpp | 3 +- src/strategy/values/DpsTargetValue.cpp | 59 ++++++++++++++++++- src/strategy/values/ExpectedLifetimeValue.cpp | 4 +- src/strategy/values/TankTargetValue.cpp | 48 ++++++++++++++- 14 files changed, 184 insertions(+), 53 deletions(-) diff --git a/src/AiFactory.cpp b/src/AiFactory.cpp index 33b320a56..b0ee121f4 100644 --- a/src/AiFactory.cpp +++ b/src/AiFactory.cpp @@ -292,9 +292,9 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa if (tab == 2) engine->addStrategies("tank", "tank assist", "aoe", "mark rti", nullptr); else if (player->getLevel() < 30 || tab == 0) - engine->addStrategies("arms", "aoe", "dps assist", "threat", "behind", nullptr); + engine->addStrategies("arms", "aoe", "dps assist", "threat", /*"behind",*/ nullptr); else - engine->addStrategies("fury", "aoe", "dps assist", "threat", "behind", nullptr); + engine->addStrategies("fury", "aoe", "dps assist", "threat", /*"behind",*/ nullptr); break; case CLASS_SHAMAN: if (tab == 0) @@ -335,9 +335,9 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa break; case CLASS_ROGUE: if (tab == ROGUE_TAB_ASSASSINATION) { - engine->addStrategies("melee", "threat", "dps assist", "aoe", "behind", nullptr); + engine->addStrategies("melee", "threat", "dps assist", "aoe", /*"behind",*/ nullptr); } else { - engine->addStrategies("dps", "threat", "dps assist", "aoe", "behind", nullptr); + engine->addStrategies("dps", "threat", "dps assist", "aoe", /*"behind",*/ nullptr); } break; case CLASS_WARLOCK: @@ -436,10 +436,10 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa engine->addStrategies("caster", "caster aoe", nullptr); if (player->getClass() == CLASS_DRUID && tab == 1) - engine->addStrategies("behind", "dps", nullptr); + engine->addStrategies(/*"behind",*/ "dps", nullptr); if (player->getClass() == CLASS_ROGUE) - engine->addStrategies("behind", "stealth", nullptr); + engine->addStrategies(/*"behind",*/ "stealth", nullptr); } } diff --git a/src/PlayerbotAI.cpp b/src/PlayerbotAI.cpp index 863416937..65d5612c5 100644 --- a/src/PlayerbotAI.cpp +++ b/src/PlayerbotAI.cpp @@ -1399,6 +1399,19 @@ bool PlayerbotAI::IsRangedDpsAssistantOfIndex(Player* player, int index) return false; } +bool PlayerbotAI::HasAggro(Unit* unit) +{ + if (!unit) { + return false; + } + bool isMT = IsMainTank(bot); + Unit* victim = unit->GetVictim(); + if (victim && (victim->GetGUID() == bot->GetGUID() || (!isMT && victim->ToPlayer() && IsTank(victim->ToPlayer())))) { + return true; + } + return false; +} + int32 PlayerbotAI::GetGroupSlotIndex(Player* player) { Group* group = bot->GetGroup(); diff --git a/src/PlayerbotAI.h b/src/PlayerbotAI.h index 0f618cfd9..e268914f4 100644 --- a/src/PlayerbotAI.h +++ b/src/PlayerbotAI.h @@ -338,6 +338,7 @@ class PlayerbotAI : public PlayerbotAIBase bool IsAssistTankOfIndex(Player* player, int index); bool IsHealAssistantOfIndex(Player* player, int index); bool IsRangedDpsAssistantOfIndex(Player* player, int index); + bool HasAggro(Unit* unit); int32 GetGroupSlotIndex(Player* player); int32 GetRangedIndex(Player* player); int32 GetClassIndex(Player* player, uint8_t cls); diff --git a/src/PlayerbotMgr.cpp b/src/PlayerbotMgr.cpp index 9c82eeea7..4083938a4 100644 --- a/src/PlayerbotMgr.cpp +++ b/src/PlayerbotMgr.cpp @@ -443,7 +443,7 @@ void PlayerbotHolder::OnBotLogin(Player* const bot) if (master && isRandomAccount && master->GetLevel() < bot->GetLevel()) { // PlayerbotFactory factory(bot, master->getLevel()); // factory.Randomize(false); - uint32 mixedGearScore = PlayerbotAI::GetMixedGearScore(master, false, false, 12) * sPlayerbotAIConfig->autoInitEquipLevelLimitRatio; + uint32 mixedGearScore = PlayerbotAI::GetMixedGearScore(master, true, false, 12) * sPlayerbotAIConfig->autoInitEquipLevelLimitRatio; PlayerbotFactory factory(bot, master->getLevel(), ITEM_QUALITY_LEGENDARY, mixedGearScore); factory.Randomize(false); } @@ -584,14 +584,13 @@ std::string const PlayerbotHolder::ProcessBotCommand(std::string const cmd, Obje } else if (cmd == "init=auto") { - uint32 mixedGearScore = PlayerbotAI::GetMixedGearScore(master, false, false, 12) * sPlayerbotAIConfig->autoInitEquipLevelLimitRatio; + uint32 mixedGearScore = PlayerbotAI::GetMixedGearScore(master, true, false, 12) * sPlayerbotAIConfig->autoInitEquipLevelLimitRatio; PlayerbotFactory factory(bot, master->getLevel(), ITEM_QUALITY_LEGENDARY, mixedGearScore); factory.Randomize(false); return "ok, gear score limit: " + std::to_string(mixedGearScore / (ITEM_QUALITY_EPIC + 1)) + "(for epic)"; } else if (cmd.starts_with("init=") && sscanf(cmd.c_str(), "init=%d", &gs) != -1) { - // uint32 mixedGearScore = PlayerbotAI::GetMixedGearScore(master, false, false, 12) * sPlayerbotAIConfig->autoInitEquipLevelLimitRatio; PlayerbotFactory factory(bot, master->getLevel(), ITEM_QUALITY_LEGENDARY, gs); factory.Randomize(false); return "ok, gear score limit: " + std::to_string(gs / (ITEM_QUALITY_EPIC + 1)) + "(for epic)"; diff --git a/src/strategy/Strategy.h b/src/strategy/Strategy.h index 854a7b899..4de7b6713 100644 --- a/src/strategy/Strategy.h +++ b/src/strategy/Strategy.h @@ -23,20 +23,34 @@ enum StrategyType : uint32 STRATEGY_TYPE_MELEE = 64 }; -enum ActionPriority -{ - ACTION_IDLE = 0, - ACTION_NORMAL = 10, - ACTION_HIGH = 20, - ACTION_MOVE = 30, - ACTION_INTERRUPT = 40, - ACTION_DISPEL = 50, - ACTION_RAID = 60, - ACTION_LIGHT_HEAL = 10, - ACTION_MEDIUM_HEAL = 20, - ACTION_CRITICAL_HEAL = 30, - ACTION_EMERGENCY = 90 -}; +// enum ActionPriority +// { +// ACTION_IDLE = 0, +// ACTION_DEFAULT = 5, +// ACTION_NORMAL = 10, +// ACTION_HIGH = 20, +// ACTION_MOVE = 30, +// ACTION_INTERRUPT = 40, +// ACTION_DISPEL = 50, +// ACTION_RAID = 60, +// ACTION_LIGHT_HEAL = 10, +// ACTION_MEDIUM_HEAL = 20, +// ACTION_CRITICAL_HEAL = 30, +// ACTION_EMERGENCY = 90 +// }; + +static float ACTION_IDLE = 0.0f; +static float ACTION_DEFAULT = 5.0f; +static float ACTION_NORMAL = 10.0f; +static float ACTION_HIGH = 20.0f; +static float ACTION_MOVE = 30.0f; +static float ACTION_INTERRUPT = 40.0f; +static float ACTION_DISPEL = 50.0f; +static float ACTION_RAID = 60.0f; +static float ACTION_LIGHT_HEAL = 10.0f; +static float ACTION_MEDIUM_HEAL = 20.0f; +static float ACTION_CRITICAL_HEAL = 30.0f; +static float ACTION_EMERGENCY = 90.0f; class Strategy : public PlayerbotAIAware { diff --git a/src/strategy/deathknight/BloodDKStrategy.cpp b/src/strategy/deathknight/BloodDKStrategy.cpp index 079d4ad9e..b63908cb0 100644 --- a/src/strategy/deathknight/BloodDKStrategy.cpp +++ b/src/strategy/deathknight/BloodDKStrategy.cpp @@ -80,15 +80,15 @@ BloodDKStrategy::BloodDKStrategy(PlayerbotAI* botAI) : GenericDKStrategy(botAI) NextAction** BloodDKStrategy::getDefaultActions() { return NextAction::array(0, - new NextAction("rune strike", ACTION_NORMAL + 8), - new NextAction("icy touch", ACTION_NORMAL + 7), - new NextAction("heart strike", ACTION_NORMAL + 6), - new NextAction("blood strike", ACTION_NORMAL + 5), - new NextAction("dancing rune weapon", ACTION_NORMAL + 4), - new NextAction("death coil", ACTION_NORMAL + 3), - new NextAction("plague strike", ACTION_NORMAL + 2), - new NextAction("horn of winter", ACTION_NORMAL + 1), - new NextAction("melee", ACTION_NORMAL), + new NextAction("rune strike", ACTION_DEFAULT + 0.8f), + new NextAction("icy touch", ACTION_DEFAULT + 0.7f), + new NextAction("heart strike", ACTION_DEFAULT + 0.6f), + new NextAction("blood strike", ACTION_DEFAULT + 0.5f), + new NextAction("dancing rune weapon", ACTION_DEFAULT + 0.4f), + new NextAction("death coil", ACTION_DEFAULT + 0.3f), + new NextAction("plague strike", ACTION_DEFAULT + 0.2f), + new NextAction("horn of winter", ACTION_DEFAULT + 0.1f), + new NextAction("melee", ACTION_DEFAULT), NULL); } diff --git a/src/strategy/deathknight/FrostDKStrategy.cpp b/src/strategy/deathknight/FrostDKStrategy.cpp index 8966fa694..8feba4136 100644 --- a/src/strategy/deathknight/FrostDKStrategy.cpp +++ b/src/strategy/deathknight/FrostDKStrategy.cpp @@ -78,12 +78,12 @@ FrostDKStrategy::FrostDKStrategy(PlayerbotAI* botAI) : GenericDKStrategy(botAI) NextAction** FrostDKStrategy::getDefaultActions() { return NextAction::array(0, - new NextAction("obliterate", ACTION_NORMAL + 5), - new NextAction("frost strike", ACTION_NORMAL + 4), + new NextAction("obliterate", ACTION_DEFAULT + 0.5f), + new NextAction("frost strike", ACTION_DEFAULT + 0.4f), // new NextAction("death strike", ACTION_NORMAL + 3), - new NextAction("empower rune weapon", ACTION_NORMAL + 2), - new NextAction("horn of winter", ACTION_NORMAL), - new NextAction("melee", ACTION_NORMAL), + new NextAction("empower rune weapon", ACTION_DEFAULT + 0.2f), + new NextAction("horn of winter", ACTION_DEFAULT + 0.1f), + new NextAction("melee", ACTION_DEFAULT), NULL ); } diff --git a/src/strategy/deathknight/UnholyDKStrategy.cpp b/src/strategy/deathknight/UnholyDKStrategy.cpp index 4369689fb..638a9967f 100644 --- a/src/strategy/deathknight/UnholyDKStrategy.cpp +++ b/src/strategy/deathknight/UnholyDKStrategy.cpp @@ -72,15 +72,15 @@ UnholyDKStrategy::UnholyDKStrategy(PlayerbotAI* botAI) : GenericDKStrategy(botAI NextAction** UnholyDKStrategy::getDefaultActions() { return NextAction::array(0, - new NextAction("scourge strike", ACTION_NORMAL + 7), - new NextAction("blood strike", ACTION_NORMAL + 6), - new NextAction("ghoul frenzy", ACTION_NORMAL + 5), - new NextAction("summon gargoyle", ACTION_NORMAL + 4), - new NextAction("death coil", ACTION_NORMAL + 3), - new NextAction("plague strike", ACTION_NORMAL + 2), - new NextAction("icy touch", ACTION_NORMAL + 1), - new NextAction("horn of winter", ACTION_NORMAL), - new NextAction("melee", ACTION_NORMAL), + new NextAction("scourge strike", ACTION_DEFAULT + 0.8f), + new NextAction("blood strike", ACTION_DEFAULT + 0.7f), + new NextAction("ghoul frenzy", ACTION_DEFAULT + 0.6f), + new NextAction("summon gargoyle", ACTION_DEFAULT + 0.5f), + new NextAction("death coil", ACTION_DEFAULT + 0.4f), + new NextAction("plague strike", ACTION_DEFAULT + 0.3f), + new NextAction("icy touch", ACTION_DEFAULT + 0.2f), + new NextAction("horn of winter", ACTION_DEFAULT + 0.1f), + new NextAction("melee", ACTION_DEFAULT), nullptr); } diff --git a/src/strategy/hunter/DpsHunterStrategy.cpp b/src/strategy/hunter/DpsHunterStrategy.cpp index 7ec2220a1..4ef8a3f0f 100644 --- a/src/strategy/hunter/DpsHunterStrategy.cpp +++ b/src/strategy/hunter/DpsHunterStrategy.cpp @@ -48,7 +48,7 @@ void DpsHunterStrategy::InitTriggers(std::vector& triggers) triggers.push_back(new TriggerNode("black arrow", NextAction::array(0, new NextAction("black arrow", 15.0f), nullptr))); triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("viper sting", 23.0f), nullptr))); - triggers.push_back(new TriggerNode("hunter's mark", NextAction::array(0, new NextAction("hunter's mark", 11.0f), nullptr))); + triggers.push_back(new TriggerNode("hunter's mark", NextAction::array(0, new NextAction("hunter's mark", 31.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))); diff --git a/src/strategy/triggers/GenericTriggers.cpp b/src/strategy/triggers/GenericTriggers.cpp index be35d17bb..1e3d470b5 100644 --- a/src/strategy/triggers/GenericTriggers.cpp +++ b/src/strategy/triggers/GenericTriggers.cpp @@ -406,7 +406,7 @@ bool TankAssistTrigger::IsActive() if (!tankTarget || currentTarget == tankTarget) return false; - return currentTarget->GetVictim() == AI_VALUE(Unit*, "self target"); + return AI_VALUE2(bool, "has aggro", "current target"); } bool IsBehindTargetTrigger::IsActive() diff --git a/src/strategy/values/AttackerCountValues.cpp b/src/strategy/values/AttackerCountValues.cpp index 9faeeb2a4..15cb6efb6 100644 --- a/src/strategy/values/AttackerCountValues.cpp +++ b/src/strategy/values/AttackerCountValues.cpp @@ -21,7 +21,8 @@ bool HasAggroValue::Calculate() if (!victim) { return true; } - if (victim && (victim->GetGUID() == bot->GetGUID() || (victim->ToPlayer() && botAI->IsMainTank(victim->ToPlayer())))) { + bool isMT = botAI->IsMainTank(bot); + if (victim && (victim->GetGUID() == bot->GetGUID() || (!isMT && victim->ToPlayer() && botAI->IsTank(victim->ToPlayer())))) { return true; } return false; diff --git a/src/strategy/values/DpsTargetValue.cpp b/src/strategy/values/DpsTargetValue.cpp index aee84ee28..258f8dfee 100644 --- a/src/strategy/values/DpsTargetValue.cpp +++ b/src/strategy/values/DpsTargetValue.cpp @@ -58,13 +58,70 @@ class FindMaxThreatGapTargetStrategy : public FindTargetStrategy float minThreat; }; +class FindTargetSmartStrategy : public FindTargetStrategy +{ + public: + FindTargetSmartStrategy(PlayerbotAI* botAI, float dps) : FindTargetStrategy(botAI), dps_(dps), targetExpectedLifeTime(1000000) { } + + void CheckAttacker(Unit* attacker, ThreatMgr* threatMgr) override + { + if (Group* group = botAI->GetBot()->GetGroup()) + { + ObjectGuid guid = group->GetTargetIcon(4); + if (guid && attacker->GetGUID() == guid) + return; + } + if (!attacker->IsAlive()) { + return; + } + float expectedLifeTime = attacker->GetHealth() / dps_; + // Unit* victim = attacker->GetVictim(); + if (!result || IsBetter(attacker, result)) { + targetExpectedLifeTime = expectedLifeTime; + result = attacker; + } + } + bool IsBetter(Unit* new_unit, Unit* old_unit) { + float new_time = new_unit->GetHealth() / dps_; + float old_time = old_unit->GetHealth() / dps_; + // [5-20] > (5-0] > (20-inf) + if (GetIntervalLevel(new_time) > GetIntervalLevel(old_time)) { + return true; + } + int32_t interval = GetIntervalLevel(new_time); + if (interval == 2 || interval == 0) { + return new_time < old_time; + } + // dont switch targets when all of them with low health + if (botAI->GetAiObjectContext()->GetValue("current target")->Get() == old_unit) { + return false; + } + return new_time > old_time; + } + int32_t GetIntervalLevel(float time) { + if (time >= 5 && time <= 20) { + return 2; + } + if (time < 5) { + return 1; + } + return 0; + } + + protected: + float dps_; + float targetExpectedLifeTime; +}; + Unit* DpsTargetValue::Calculate() { Unit* rti = RtiTargetValue::Calculate(); if (rti) return rti; - FindLeastHpTargetStrategy strategy(botAI); + // FindLeastHpTargetStrategy strategy(botAI); + float dps = AI_VALUE(float, "expected group dps"); + FindTargetSmartStrategy strategy(botAI, dps); // FindMaxThreatGapTargetStrategy strategy(botAI); return TargetValue::FindTarget(&strategy); } diff --git a/src/strategy/values/ExpectedLifetimeValue.cpp b/src/strategy/values/ExpectedLifetimeValue.cpp index 3518af2e3..3868bbcfb 100644 --- a/src/strategy/values/ExpectedLifetimeValue.cpp +++ b/src/strategy/values/ExpectedLifetimeValue.cpp @@ -21,11 +21,11 @@ float ExpectedGroupDpsValue::Calculate() float dps_num; Group* group = bot->GetGroup(); if (!group) { - dps_num = 1; + dps_num = 0.7; } else { dps_num = group->GetMembersCount() * 0.7; } - uint32 mixedGearScore = PlayerbotAI::GetMixedGearScore(bot, false, false, 12); + uint32 mixedGearScore = PlayerbotAI::GetMixedGearScore(bot, true, false, 12); // efficiency record based on rare gear level, is there better calculation method? // float dps_efficiency = 1; float basic_dps; diff --git a/src/strategy/values/TankTargetValue.cpp b/src/strategy/values/TankTargetValue.cpp index 817dbd500..173c84dac 100644 --- a/src/strategy/values/TankTargetValue.cpp +++ b/src/strategy/values/TankTargetValue.cpp @@ -3,6 +3,7 @@ */ #include "AttackersValue.h" +#include "PlayerbotAIConfig.h" #include "TankTargetValue.h" #include "Playerbots.h" @@ -41,8 +42,53 @@ class FindTargetForTankStrategy : public FindNonCcTargetStrategy float minThreat; }; +class FindTankTargetSmartStrategy : public FindTargetStrategy +{ + public: + FindTankTargetSmartStrategy(PlayerbotAI* botAI) : FindTargetStrategy(botAI) { } + + void CheckAttacker(Unit* attacker, ThreatMgr* threatMgr) override + { + if (Group* group = botAI->GetBot()->GetGroup()) + { + ObjectGuid guid = group->GetTargetIcon(4); + if (guid && attacker->GetGUID() == guid) + return; + } + if (!attacker->IsAlive()) { + return; + } + if (!result || IsBetter(attacker, result)) { + result = attacker; + } + } + bool IsBetter(Unit* new_unit, Unit* old_unit) { + Player* bot = botAI->GetBot(); + float new_threat = new_unit->GetThreatMgr().GetThreat(bot); + float old_threat = old_unit->GetThreatMgr().GetThreat(bot); + float new_dis = bot->GetDistance(new_unit); + float old_dis = bot->GetDistance(old_unit); + // hasAggro? -> withinMelee? -> threat + if (GetIntervalLevel(new_unit) > GetIntervalLevel(old_unit)) { + return true; + } + int32_t interval = GetIntervalLevel(new_unit); + if (interval == 1) { + return new_dis < old_dis; + } + return new_threat < old_threat; + } + int32_t GetIntervalLevel(Unit* unit) { + if (!botAI->HasAggro(unit)) { + return 1; + } + return 0; + } +}; + Unit* TankTargetValue::Calculate() { - FindTargetForTankStrategy strategy(botAI); + // FindTargetForTankStrategy strategy(botAI); + FindTankTargetSmartStrategy strategy(botAI); return FindTarget(&strategy); } From 38f8ea5fd98b0ae797f489fa29a9f346244d22f6 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Sun, 22 Oct 2023 11:28:00 +0800 Subject: [PATCH 02/12] fix rogue stealth --- src/strategy/rogue/RogueActions.cpp | 10 ---------- src/strategy/rogue/RogueActions.h | 1 - 2 files changed, 11 deletions(-) diff --git a/src/strategy/rogue/RogueActions.cpp b/src/strategy/rogue/RogueActions.cpp index 99ffcc643..e0ece34c3 100644 --- a/src/strategy/rogue/RogueActions.cpp +++ b/src/strategy/rogue/RogueActions.cpp @@ -14,16 +14,6 @@ bool CastStealthAction::isPossible() return !botAI->HasAura(23333, bot) && !botAI->HasAura(23335, bot) && !botAI->HasAura(34976, bot); } -bool CastStealthAction::Execute(Event event) -{ - if (botAI->CastSpell("stealth", bot)) - { - // botAI->ChangeStrategy("-dps,+stealthed", BOT_STATE_COMBAT); - } - - return true; -} - bool UnstealthAction::Execute(Event event) { botAI->RemoveAura("stealth"); diff --git a/src/strategy/rogue/RogueActions.h b/src/strategy/rogue/RogueActions.h index 21b5ed572..3087f744b 100644 --- a/src/strategy/rogue/RogueActions.h +++ b/src/strategy/rogue/RogueActions.h @@ -32,7 +32,6 @@ class CastStealthAction : public CastBuffSpellAction std::string const GetTargetName() override { return "self target"; } bool isPossible() override; - bool Execute(Event event) override; }; class UnstealthAction : public Action From 45d0ae00ab95cae2b078b00f1a09d04955e197a4 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Sun, 22 Oct 2023 12:50:17 +0800 Subject: [PATCH 03/12] default actions --- src/strategy/Engine.cpp | 19 ++++++++++--------- src/strategy/actions/MovementActions.cpp | 15 +++++++++++---- src/strategy/actions/MovementActions.h | 4 ++-- src/strategy/druid/BearTankDruidStrategy.cpp | 12 ++++++------ src/strategy/druid/CasterDruidStrategy.cpp | 4 ++-- src/strategy/druid/CatDpsDruidStrategy.cpp | 2 +- src/strategy/druid/MeleeDruidStrategy.cpp | 4 ++-- src/strategy/generic/GrindingStrategy.cpp | 6 +++--- src/strategy/hunter/DpsHunterStrategy.cpp | 14 +++++++------- src/strategy/mage/ArcaneMageStrategy.cpp | 5 ++++- src/strategy/mage/FireMageStrategy.cpp | 5 ++++- src/strategy/mage/FrostMageStrategy.cpp | 6 +++++- src/strategy/paladin/DpsPaladinStrategy.cpp | 10 +++++----- src/strategy/paladin/HealPaladinStrategy.cpp | 2 +- src/strategy/paladin/TankPaladinStrategy.cpp | 8 ++++---- src/strategy/priest/HealPriestStrategy.cpp | 2 +- src/strategy/priest/HolyPriestStrategy.cpp | 2 +- src/strategy/priest/ShadowPriestStrategy.cpp | 6 +++--- .../rogue/AssassinationRogueStrategy.cpp | 2 +- src/strategy/rogue/DpsRogueStrategy.cpp | 4 ++-- src/strategy/shaman/CasterShamanStrategy.cpp | 4 ++-- src/strategy/shaman/MeleeShamanStrategy.cpp | 10 +++++----- src/strategy/triggers/TriggerContext.h | 2 +- src/strategy/warlock/DpsWarlockStrategy.cpp | 7 ++++--- src/strategy/warlock/TankWarlockStrategy.cpp | 2 +- src/strategy/warrior/ArmsWarriorStrategy.cpp | 2 +- src/strategy/warrior/FuryWarriorStrategy.cpp | 12 ++++++------ src/strategy/warrior/TankWarriorStrategy.cpp | 6 +++--- 28 files changed, 98 insertions(+), 79 deletions(-) diff --git a/src/strategy/Engine.cpp b/src/strategy/Engine.cpp index 55bd712a6..12328b6dc 100644 --- a/src/strategy/Engine.cpp +++ b/src/strategy/Engine.cpp @@ -146,7 +146,8 @@ bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal) time_t currentTime = time(nullptr); aiObjectContext->Update(); ProcessTriggers(minimal); - + PushDefaultActions(); + uint32 iterations = 0; uint32 iterationsPerTick = queue.Size() * (minimal ? 2 : sPlayerbotAIConfig->iterationsPerTick); do @@ -265,15 +266,15 @@ bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal) } while (basket && ++iterations <= iterationsPerTick); - if (!basket) - { - lastRelevance = 0.0f; - PushDefaultActions(); + // if (!basket) + // { + // lastRelevance = 0.0f; + // PushDefaultActions(); - // prevent the delay after pushing default actions - if (queue.Peek() && depth < 1 && !minimal) - return DoNextAction(unit, depth + 1, minimal); - } + // // prevent the delay after pushing default actions + // if (queue.Peek() && depth < 1 && !minimal) + // return DoNextAction(unit, depth + 1, minimal); + // } // MEMORY FIX TEST /* diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index 3919df3f3..919b77072 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -132,7 +132,7 @@ bool MovementAction::MoveToLOS(WorldObject* target, bool ranged) return false; } -bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, bool react) +bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, bool react, bool normal_only) { UpdateMovementState(); if (!IsMovingAllowed(mapId, x, y, z)) { @@ -166,7 +166,11 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle, MotionMaster &mm = *bot->GetMotionMaster(); mm.Clear(); - mm.MovePoint(mapId, x, y, SearchBestGroundZForPath(x, y, z, generatePath), generatePath); + float modifiedZ = SearchBestGroundZForPath(x, y, z, generatePath, normal_only); + if (modifiedZ == INVALID_HEIGHT) { + return false; + } + mm.MovePoint(mapId, x, y, modifiedZ, generatePath); AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation()); return true; } @@ -1257,7 +1261,7 @@ bool MovementAction::MoveAway(Unit* target) 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); + return MoveTo(target->GetMapId(), dx, dy, dz, false, false, true); } bool MovementAction::MoveInside(uint32 mapId, float x, float y, float z, float distance) @@ -1268,7 +1272,7 @@ bool MovementAction::MoveInside(uint32 mapId, float x, float y, float z, float d return MoveNear(mapId, x, y, z, distance); } -float MovementAction::SearchBestGroundZForPath(float x, float y, float z, bool generatePath, float range) +float MovementAction::SearchBestGroundZForPath(float x, float y, float z, bool generatePath, float range, bool normal_only) { if (!generatePath) { return z; @@ -1299,6 +1303,9 @@ float MovementAction::SearchBestGroundZForPath(float x, float y, float z, bool g return modified_z; } } + if (normal_only) { + return INVALID_HEIGHT; + } return z; } diff --git a/src/strategy/actions/MovementActions.h b/src/strategy/actions/MovementActions.h index b442c3f18..ce437e9c0 100644 --- a/src/strategy/actions/MovementActions.h +++ b/src/strategy/actions/MovementActions.h @@ -22,7 +22,7 @@ class MovementAction : public Action protected: bool MoveNear(uint32 mapId, float x, float y, float z, float distance = sPlayerbotAIConfig->contactDistance); bool MoveToLOS(WorldObject* target, bool ranged = false); - bool MoveTo(uint32 mapId, float x, float y, float z, bool idle = false, bool react = false); + bool MoveTo(uint32 mapId, float x, float y, float z, bool idle = false, bool react = false, bool normal_only = false); bool MoveTo(Unit* target, float distance = 0.0f); bool MoveNear(WorldObject* target, float distance = sPlayerbotAIConfig->contactDistance); float GetFollowAngle(); @@ -41,7 +41,7 @@ class MovementAction : public Action bool MoveInside(uint32 mapId, float x, float y, float z, float distance = sPlayerbotAIConfig->followDistance); void CreateWp(Player* wpOwner, float x, float y, float z, float o, uint32 entry, bool important = false); private: - float SearchBestGroundZForPath(float x, float y, float z, bool generatePath, float range = 10.0f); + float SearchBestGroundZForPath(float x, float y, float z, bool generatePath, float range = 10.0f, bool normal_only = false); }; class FleeAction : public MovementAction diff --git a/src/strategy/druid/BearTankDruidStrategy.cpp b/src/strategy/druid/BearTankDruidStrategy.cpp index 7f0ed5bf3..d3d49ce5f 100644 --- a/src/strategy/druid/BearTankDruidStrategy.cpp +++ b/src/strategy/druid/BearTankDruidStrategy.cpp @@ -140,12 +140,12 @@ BearTankDruidStrategy::BearTankDruidStrategy(PlayerbotAI* botAI) : FeralDruidStr NextAction** BearTankDruidStrategy::getDefaultActions() { return NextAction::array(0, - new NextAction("mangle (bear)", ACTION_NORMAL + 5), - new NextAction("faerie fire (feral)", ACTION_NORMAL + 4), - new NextAction("lacerate", ACTION_NORMAL + 3), - new NextAction("maul", ACTION_NORMAL + 2), - new NextAction("enrage", ACTION_NORMAL + 1), - new NextAction("melee", ACTION_NORMAL), + new NextAction("mangle (bear)", ACTION_DEFAULT + 0.5f), + new NextAction("faerie fire (feral)", ACTION_DEFAULT + 0.4f), + new NextAction("lacerate", ACTION_DEFAULT + 0.3f), + new NextAction("maul", ACTION_DEFAULT + 0.2f), + new NextAction("enrage", ACTION_DEFAULT + 0.1f), + new NextAction("melee", ACTION_DEFAULT), nullptr); } diff --git a/src/strategy/druid/CasterDruidStrategy.cpp b/src/strategy/druid/CasterDruidStrategy.cpp index 03e1ffd54..51c2692ee 100644 --- a/src/strategy/druid/CasterDruidStrategy.cpp +++ b/src/strategy/druid/CasterDruidStrategy.cpp @@ -105,8 +105,8 @@ CasterDruidStrategy::CasterDruidStrategy(PlayerbotAI* botAI) : GenericDruidStrat NextAction** CasterDruidStrategy::getDefaultActions() { return NextAction::array(0, - new NextAction("starfall", ACTION_NORMAL + 2), - new NextAction("wrath", ACTION_NORMAL + 1), + new NextAction("starfall", ACTION_DEFAULT + 0.2f), + new NextAction("wrath", ACTION_DEFAULT + 0.1f), // new NextAction("starfire", ACTION_NORMAL), nullptr); } diff --git a/src/strategy/druid/CatDpsDruidStrategy.cpp b/src/strategy/druid/CatDpsDruidStrategy.cpp index a3f15140c..5b9dc1700 100644 --- a/src/strategy/druid/CatDpsDruidStrategy.cpp +++ b/src/strategy/druid/CatDpsDruidStrategy.cpp @@ -120,7 +120,7 @@ CatDpsDruidStrategy::CatDpsDruidStrategy(PlayerbotAI* botAI) : FeralDruidStrateg NextAction** CatDpsDruidStrategy::getDefaultActions() { - return NextAction::array(0, new NextAction("mangle (cat)", ACTION_NORMAL + 1), nullptr); + return NextAction::array(0, new NextAction("mangle (cat)", ACTION_DEFAULT + 0.1f), nullptr); } void CatDpsDruidStrategy::InitTriggers(std::vector& triggers) diff --git a/src/strategy/druid/MeleeDruidStrategy.cpp b/src/strategy/druid/MeleeDruidStrategy.cpp index 39b3b0279..7a0178216 100644 --- a/src/strategy/druid/MeleeDruidStrategy.cpp +++ b/src/strategy/druid/MeleeDruidStrategy.cpp @@ -12,8 +12,8 @@ MeleeDruidStrategy::MeleeDruidStrategy(PlayerbotAI* botAI) : CombatStrategy(botA NextAction** MeleeDruidStrategy::getDefaultActions() { return NextAction::array(0, - new NextAction("faerie fire", ACTION_NORMAL + 1), - new NextAction("melee", ACTION_NORMAL), + new NextAction("faerie fire", ACTION_DEFAULT + 0.1f), + new NextAction("melee", ACTION_DEFAULT), nullptr); } diff --git a/src/strategy/generic/GrindingStrategy.cpp b/src/strategy/generic/GrindingStrategy.cpp index a7cf3bbdb..ffbe8300d 100644 --- a/src/strategy/generic/GrindingStrategy.cpp +++ b/src/strategy/generic/GrindingStrategy.cpp @@ -12,9 +12,9 @@ NextAction** GrindingStrategy::getDefaultActions() void GrindingStrategy::InitTriggers(std::vector& triggers) { - triggers.push_back(new TriggerNode("timer", NextAction::array(0, new NextAction("drink", 7.0f), nullptr))); - triggers.push_back(new TriggerNode("timer", NextAction::array(0, new NextAction("food", 6.0f), nullptr))); - triggers.push_back(new TriggerNode("no target", NextAction::array(0, new NextAction("attack anything", 5.0f), nullptr))); + triggers.push_back(new TriggerNode("timer", NextAction::array(0, new NextAction("drink", 4.2f), nullptr))); + triggers.push_back(new TriggerNode("timer", NextAction::array(0, new NextAction("food", 4.1f), nullptr))); + triggers.push_back(new TriggerNode("no target", NextAction::array(0, new NextAction("attack anything", 4.0f), nullptr))); } void MoveRandomStrategy::InitTriggers(std::vector& triggers) diff --git a/src/strategy/hunter/DpsHunterStrategy.cpp b/src/strategy/hunter/DpsHunterStrategy.cpp index 4ef8a3f0f..891190daa 100644 --- a/src/strategy/hunter/DpsHunterStrategy.cpp +++ b/src/strategy/hunter/DpsHunterStrategy.cpp @@ -31,13 +31,13 @@ DpsHunterStrategy::DpsHunterStrategy(PlayerbotAI* botAI) : GenericHunterStrategy NextAction** DpsHunterStrategy::getDefaultActions() { 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), + new NextAction("kill shot", ACTION_DEFAULT + 0.6f), + new NextAction("chimera shot", ACTION_DEFAULT + 0.5f), + new NextAction("explosive shot", ACTION_DEFAULT + 0.4f), + new NextAction("aimed shot", ACTION_DEFAULT + 0.3f), + new NextAction("arcane shot", ACTION_DEFAULT + 0.2f), + new NextAction("steady shot", ACTION_DEFAULT + 0.1f), + new NextAction("auto shot", ACTION_DEFAULT), nullptr); // return NextAction::array(0, new NextAction("explosive shot", 11.0f), new NextAction("auto shot", 10.0f), new NextAction("auto attack", 9.0f), nullptr); } diff --git a/src/strategy/mage/ArcaneMageStrategy.cpp b/src/strategy/mage/ArcaneMageStrategy.cpp index c5c46aa4c..db97a4daa 100644 --- a/src/strategy/mage/ArcaneMageStrategy.cpp +++ b/src/strategy/mage/ArcaneMageStrategy.cpp @@ -57,7 +57,10 @@ ArcaneMageStrategy::ArcaneMageStrategy(PlayerbotAI* botAI) : GenericMageStrategy NextAction** ArcaneMageStrategy::getDefaultActions() { - return NextAction::array(0, new NextAction("arcane blast", 10.0f), NULL); + return NextAction::array(0, + new NextAction("arcane blast", ACTION_DEFAULT + 0.1f), + new NextAction("shoot", ACTION_DEFAULT), + NULL); } void ArcaneMageStrategy::InitTriggers(std::vector& triggers) diff --git a/src/strategy/mage/FireMageStrategy.cpp b/src/strategy/mage/FireMageStrategy.cpp index 565031751..8382c3b15 100644 --- a/src/strategy/mage/FireMageStrategy.cpp +++ b/src/strategy/mage/FireMageStrategy.cpp @@ -7,7 +7,10 @@ NextAction** FireMageStrategy::getDefaultActions() { - return NextAction::array(0, new NextAction("fireball", ACTION_NORMAL + 1), NULL); + return NextAction::array(0, + new NextAction("fireball", ACTION_DEFAULT + 0.1f), + new NextAction("shoot", ACTION_DEFAULT), + NULL); } void FireMageStrategy::InitTriggers(std::vector& triggers) diff --git a/src/strategy/mage/FrostMageStrategy.cpp b/src/strategy/mage/FrostMageStrategy.cpp index 77ee30eb9..39822aa12 100644 --- a/src/strategy/mage/FrostMageStrategy.cpp +++ b/src/strategy/mage/FrostMageStrategy.cpp @@ -11,7 +11,11 @@ FrostMageStrategy::FrostMageStrategy(PlayerbotAI* botAI) : GenericMageStrategy(b NextAction** FrostMageStrategy::getDefaultActions() { - return NextAction::array(0, new NextAction("frostbolt", 7.0f), nullptr); + return NextAction::array(0, + new NextAction("frostbolt", ACTION_DEFAULT + 0.1f), + new NextAction("shoot", ACTION_DEFAULT), + nullptr); + } void FrostMageStrategy::InitTriggers(std::vector& triggers) diff --git a/src/strategy/paladin/DpsPaladinStrategy.cpp b/src/strategy/paladin/DpsPaladinStrategy.cpp index 0662660e5..907d9411c 100644 --- a/src/strategy/paladin/DpsPaladinStrategy.cpp +++ b/src/strategy/paladin/DpsPaladinStrategy.cpp @@ -80,11 +80,11 @@ DpsPaladinStrategy::DpsPaladinStrategy(PlayerbotAI* botAI) : GenericPaladinStrat NextAction** DpsPaladinStrategy::getDefaultActions() { return NextAction::array(0, - new NextAction("judgement of wisdom", ACTION_NORMAL + 6), - new NextAction("crusader strike", ACTION_NORMAL + 5), - new NextAction("divine storm", ACTION_NORMAL + 4), - new NextAction("consecration", ACTION_NORMAL + 3), - new NextAction("melee", ACTION_NORMAL), + new NextAction("judgement of wisdom", ACTION_DEFAULT + 0.4f), + new NextAction("crusader strike", ACTION_DEFAULT + 0.3f), + new NextAction("divine storm", ACTION_DEFAULT + 0.2f), + new NextAction("consecration", ACTION_DEFAULT + 0.1f), + new NextAction("melee", ACTION_DEFAULT), NULL); } diff --git a/src/strategy/paladin/HealPaladinStrategy.cpp b/src/strategy/paladin/HealPaladinStrategy.cpp index 6f6510396..15215026d 100644 --- a/src/strategy/paladin/HealPaladinStrategy.cpp +++ b/src/strategy/paladin/HealPaladinStrategy.cpp @@ -25,7 +25,7 @@ HealPaladinStrategy::HealPaladinStrategy(PlayerbotAI* botAI) : GenericPaladinStr NextAction** HealPaladinStrategy::getDefaultActions() { - return NextAction::array(0, new NextAction("judgement of light", ACTION_NORMAL + 2), nullptr); + return NextAction::array(0, new NextAction("judgement of light", ACTION_DEFAULT + 2), nullptr); } void HealPaladinStrategy::InitTriggers(std::vector& triggers) diff --git a/src/strategy/paladin/TankPaladinStrategy.cpp b/src/strategy/paladin/TankPaladinStrategy.cpp index 3c03d7ace..d8b3f9a14 100644 --- a/src/strategy/paladin/TankPaladinStrategy.cpp +++ b/src/strategy/paladin/TankPaladinStrategy.cpp @@ -59,12 +59,12 @@ TankPaladinStrategy::TankPaladinStrategy(PlayerbotAI* botAI) : GenericPaladinStr NextAction** TankPaladinStrategy::getDefaultActions() { return NextAction::array(0, - new NextAction("shield of righteousness", ACTION_NORMAL + 6), - new NextAction("hammer of the righteous", ACTION_NORMAL + 5), - new NextAction("judgement of wisdom", ACTION_NORMAL + 4), + new NextAction("shield of righteousness", ACTION_DEFAULT + 0.6f), + new NextAction("hammer of the righteous", ACTION_DEFAULT + 0.5f), + new NextAction("judgement of wisdom", ACTION_DEFAULT + 0.4f), // new NextAction("avenger's shield", ACTION_NORMAL + 3), // new NextAction("consecration", ACTION_NORMAL + 2), - new NextAction("melee", ACTION_NORMAL), + new NextAction("melee", ACTION_DEFAULT), NULL); } diff --git a/src/strategy/priest/HealPriestStrategy.cpp b/src/strategy/priest/HealPriestStrategy.cpp index 7f15dd350..322de6854 100644 --- a/src/strategy/priest/HealPriestStrategy.cpp +++ b/src/strategy/priest/HealPriestStrategy.cpp @@ -13,7 +13,7 @@ HealPriestStrategy::HealPriestStrategy(PlayerbotAI* botAI) : GenericPriestStrate NextAction** HealPriestStrategy::getDefaultActions() { - return NextAction::array(0, new NextAction("shoot", 10.0f), nullptr); + return NextAction::array(0, new NextAction("shoot", ACTION_DEFAULT), nullptr); } void HealPriestStrategy::InitTriggers(std::vector& triggers) diff --git a/src/strategy/priest/HolyPriestStrategy.cpp b/src/strategy/priest/HolyPriestStrategy.cpp index 72b216a1e..ba24d7306 100644 --- a/src/strategy/priest/HolyPriestStrategy.cpp +++ b/src/strategy/priest/HolyPriestStrategy.cpp @@ -30,7 +30,7 @@ HolyPriestStrategy::HolyPriestStrategy(PlayerbotAI* botAI) : HealPriestStrategy( NextAction** HolyPriestStrategy::getDefaultActions() { - return NextAction::array(0, new NextAction("smite", 10.0f), new NextAction("mana burn", 9.0f), new NextAction("starshards", 8.0f), nullptr); + return NextAction::array(0, new NextAction("smite", ACTION_DEFAULT + 0.2f), new NextAction("mana burn", ACTION_DEFAULT + 0.1f), new NextAction("starshards", ACTION_DEFAULT), nullptr); } void HolyPriestStrategy::InitTriggers(std::vector& triggers) diff --git a/src/strategy/priest/ShadowPriestStrategy.cpp b/src/strategy/priest/ShadowPriestStrategy.cpp index a4560d68b..e2fae3c0a 100644 --- a/src/strategy/priest/ShadowPriestStrategy.cpp +++ b/src/strategy/priest/ShadowPriestStrategy.cpp @@ -14,10 +14,10 @@ ShadowPriestStrategy::ShadowPriestStrategy(PlayerbotAI* botAI) : GenericPriestSt NextAction** ShadowPriestStrategy::getDefaultActions() { return NextAction::array(0, - new NextAction("mind blast", 13.0f), + new NextAction("mind blast", ACTION_DEFAULT + 0.2f), // new NextAction("shadow word: death", 12.0f), - new NextAction("mind flay", 11.0f), - // new NextAction("shoot", 10.0f), + new NextAction("mind flay", ACTION_DEFAULT + 0.1f), + new NextAction("shoot", ACTION_DEFAULT), NULL); } diff --git a/src/strategy/rogue/AssassinationRogueStrategy.cpp b/src/strategy/rogue/AssassinationRogueStrategy.cpp index 990264d77..6510e72df 100644 --- a/src/strategy/rogue/AssassinationRogueStrategy.cpp +++ b/src/strategy/rogue/AssassinationRogueStrategy.cpp @@ -35,7 +35,7 @@ AssassinationRogueStrategy::AssassinationRogueStrategy(PlayerbotAI* ai) : MeleeC NextAction** AssassinationRogueStrategy::getDefaultActions() { return NextAction::array(0, - new NextAction("melee", ACTION_NORMAL), + new NextAction("melee", ACTION_DEFAULT), NULL); } diff --git a/src/strategy/rogue/DpsRogueStrategy.cpp b/src/strategy/rogue/DpsRogueStrategy.cpp index 8ff13bbe4..cf26ec084 100644 --- a/src/strategy/rogue/DpsRogueStrategy.cpp +++ b/src/strategy/rogue/DpsRogueStrategy.cpp @@ -71,8 +71,8 @@ DpsRogueStrategy::DpsRogueStrategy(PlayerbotAI* botAI) : MeleeCombatStrategy(bot NextAction** DpsRogueStrategy::getDefaultActions() { return NextAction::array(0, - new NextAction("killing spree", ACTION_NORMAL + 1), - new NextAction("melee", ACTION_NORMAL), NULL); + new NextAction("killing spree", ACTION_DEFAULT + 0.1f), + new NextAction("melee", ACTION_DEFAULT), NULL); } void DpsRogueStrategy::InitTriggers(std::vector& triggers) diff --git a/src/strategy/shaman/CasterShamanStrategy.cpp b/src/strategy/shaman/CasterShamanStrategy.cpp index 6dfb015ab..6455dee39 100644 --- a/src/strategy/shaman/CasterShamanStrategy.cpp +++ b/src/strategy/shaman/CasterShamanStrategy.cpp @@ -39,8 +39,8 @@ CasterShamanStrategy::CasterShamanStrategy(PlayerbotAI* botAI) : GenericShamanSt NextAction** CasterShamanStrategy::getDefaultActions() { return NextAction::array(0, - new NextAction("lava burst", 11.0f), - new NextAction("lightning bolt", 10.0f), + new NextAction("lava burst", ACTION_DEFAULT + 0.1f), + new NextAction("lightning bolt", ACTION_DEFAULT), NULL); } diff --git a/src/strategy/shaman/MeleeShamanStrategy.cpp b/src/strategy/shaman/MeleeShamanStrategy.cpp index c514dc337..54db4dac8 100644 --- a/src/strategy/shaman/MeleeShamanStrategy.cpp +++ b/src/strategy/shaman/MeleeShamanStrategy.cpp @@ -50,11 +50,11 @@ MeleeShamanStrategy::MeleeShamanStrategy(PlayerbotAI* botAI) : GenericShamanStra NextAction** MeleeShamanStrategy::getDefaultActions() { return NextAction::array(0, - new NextAction("stormstrike", ACTION_NORMAL + 6), - new NextAction("earth shock", ACTION_NORMAL + 5), - new NextAction("fire nova", ACTION_NORMAL + 4), - new NextAction("lava lash", ACTION_NORMAL + 1), - new NextAction("melee", ACTION_NORMAL), + new NextAction("stormstrike", ACTION_DEFAULT + 0.4f), + new NextAction("earth shock", ACTION_DEFAULT + 0.3f), + new NextAction("fire nova", ACTION_DEFAULT + 0.2f), + new NextAction("lava lash", ACTION_DEFAULT + 0.1f), + new NextAction("melee", ACTION_DEFAULT), NULL); } diff --git a/src/strategy/triggers/TriggerContext.h b/src/strategy/triggers/TriggerContext.h index d030a9ba3..0859d7069 100644 --- a/src/strategy/triggers/TriggerContext.h +++ b/src/strategy/triggers/TriggerContext.h @@ -217,7 +217,7 @@ class TriggerContext : public NamedObjectContext static Trigger* critical_aoe_heal(PlayerbotAI* botAI) { return new AoeHealTrigger(botAI, "critical aoe heal", "critical", 2); } static Trigger* low_aoe_heal(PlayerbotAI* botAI) { return new AoeHealTrigger(botAI, "low aoe heal", "low", 2); } static Trigger* medium_aoe_heal(PlayerbotAI* botAI) { return new AoeHealTrigger(botAI, "medium aoe heal", "medium", 2); } - static Trigger* group_heal_occasion(PlayerbotAI* ai) { return new AoeInGroupTrigger(ai, "group heal occasion", "almost full", 0.4); } + static Trigger* group_heal_occasion(PlayerbotAI* ai) { return new AoeInGroupTrigger(ai, "group heal occasion", "almost full", 0.6); } static Trigger* medium_group_heal_occasion(PlayerbotAI* ai) { return new AoeInGroupTrigger(ai, "group heal occasion", "medium", 0.4); } static Trigger* target_changed(PlayerbotAI* botAI) { return new TargetChangedTrigger(botAI); } static Trigger* swimming(PlayerbotAI* botAI) { return new IsSwimmingTrigger(botAI); } diff --git a/src/strategy/warlock/DpsWarlockStrategy.cpp b/src/strategy/warlock/DpsWarlockStrategy.cpp index b59781980..f5247c3f8 100644 --- a/src/strategy/warlock/DpsWarlockStrategy.cpp +++ b/src/strategy/warlock/DpsWarlockStrategy.cpp @@ -47,9 +47,10 @@ DpsWarlockStrategy::DpsWarlockStrategy(PlayerbotAI* botAI) : GenericWarlockStrat NextAction** DpsWarlockStrategy::getDefaultActions() { return NextAction::array(0, - new NextAction("haunt", 14.0f), - new NextAction("demonic empowerment", 13.0f), - new NextAction("shadow bolt", 10.0f), + new NextAction("haunt", ACTION_DEFAULT + 0.3f), + new NextAction("demonic empowerment", ACTION_DEFAULT + 0.2f), + new NextAction("shadow bolt", ACTION_DEFAULT + 0.1f), + new NextAction("shoot", ACTION_DEFAULT), nullptr); } diff --git a/src/strategy/warlock/TankWarlockStrategy.cpp b/src/strategy/warlock/TankWarlockStrategy.cpp index ca1fae486..a828fdecb 100644 --- a/src/strategy/warlock/TankWarlockStrategy.cpp +++ b/src/strategy/warlock/TankWarlockStrategy.cpp @@ -57,7 +57,7 @@ TankWarlockStrategy::TankWarlockStrategy(PlayerbotAI* botAI) : GenericWarlockStr NextAction** TankWarlockStrategy::getDefaultActions() { - return NextAction::array(0, new NextAction("shoot", 10.0f), nullptr); + return NextAction::array(0, new NextAction("shoot", ACTION_DEFAULT), nullptr); } void TankWarlockStrategy::InitTriggers(std::vector& triggers) diff --git a/src/strategy/warrior/ArmsWarriorStrategy.cpp b/src/strategy/warrior/ArmsWarriorStrategy.cpp index 4643ff63c..c6314baeb 100644 --- a/src/strategy/warrior/ArmsWarriorStrategy.cpp +++ b/src/strategy/warrior/ArmsWarriorStrategy.cpp @@ -32,7 +32,7 @@ ArmsWarriorStrategy::ArmsWarriorStrategy(PlayerbotAI* botAI) : GenericWarriorStr NextAction** ArmsWarriorStrategy::getDefaultActions() { - return NextAction::array(0, new NextAction("heroic strike", ACTION_NORMAL), nullptr); + return NextAction::array(0, new NextAction("heroic strike", ACTION_DEFAULT), nullptr); } void ArmsWarriorStrategy::InitTriggers(std::vector& triggers) diff --git a/src/strategy/warrior/FuryWarriorStrategy.cpp b/src/strategy/warrior/FuryWarriorStrategy.cpp index 3894b459c..1f8c3aeec 100644 --- a/src/strategy/warrior/FuryWarriorStrategy.cpp +++ b/src/strategy/warrior/FuryWarriorStrategy.cpp @@ -35,12 +35,12 @@ FuryWarriorStrategy::FuryWarriorStrategy(PlayerbotAI* botAI) : GenericWarriorStr NextAction** FuryWarriorStrategy::getDefaultActions() { return NextAction::array(0, - new NextAction("bloodthirst", ACTION_NORMAL + 5), - new NextAction("whirlwind", ACTION_NORMAL + 4), - new NextAction("sunder armor", ACTION_NORMAL + 3), - new NextAction("execute", ACTION_NORMAL + 2), - new NextAction("overpower", ACTION_NORMAL + 1), - new NextAction("melee", ACTION_NORMAL), + new NextAction("bloodthirst", ACTION_DEFAULT + 0.5f), + new NextAction("whirlwind", ACTION_DEFAULT + 0.4f), + new NextAction("sunder armor", ACTION_DEFAULT + 0.3f), + new NextAction("execute", ACTION_DEFAULT + 0.2f), + new NextAction("overpower", ACTION_DEFAULT + 0.1f), + new NextAction("melee", ACTION_DEFAULT), NULL); } diff --git a/src/strategy/warrior/TankWarriorStrategy.cpp b/src/strategy/warrior/TankWarriorStrategy.cpp index 0eaf3553f..e9beec2dd 100644 --- a/src/strategy/warrior/TankWarriorStrategy.cpp +++ b/src/strategy/warrior/TankWarriorStrategy.cpp @@ -43,9 +43,9 @@ TankWarriorStrategy::TankWarriorStrategy(PlayerbotAI* botAI) : GenericWarriorStr NextAction** TankWarriorStrategy::getDefaultActions() { return NextAction::array(0, - new NextAction("devastate", ACTION_NORMAL + 2), - new NextAction("revenge", ACTION_NORMAL + 1), - new NextAction("melee", ACTION_NORMAL), + new NextAction("devastate", ACTION_DEFAULT + 0.2f), + new NextAction("revenge", ACTION_DEFAULT + 0.1f), + new NextAction("melee", ACTION_DEFAULT), NULL); } From e7273979637fc258e900786afce7e409a4904c0b Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Sun, 22 Oct 2023 15:19:12 +0800 Subject: [PATCH 04/12] target && hunter auto shoot --- src/strategy/hunter/HunterActions.cpp | 2 +- src/strategy/values/DpsTargetValue.cpp | 26 ++++++++++++++++++-------- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/strategy/hunter/HunterActions.cpp b/src/strategy/hunter/HunterActions.cpp index ee20b83d7..10ef0a313 100644 --- a/src/strategy/hunter/HunterActions.cpp +++ b/src/strategy/hunter/HunterActions.cpp @@ -41,7 +41,7 @@ bool CastAutoShotAction::isUseful() if (botAI->IsInVehicle() && !botAI->IsInVehicle(false, false, true)) return false; - if (bot->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL)) { + if (bot->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL) && bot->GetCurrentSpell(CURRENT_AUTOREPEAT_SPELL)->m_targets.GetUnitTargetGUID() == AI_VALUE(Unit*, "current target")->GetGUID()) { return false; } return AI_VALUE(uint32, "active spell") != AI_VALUE2(uint32, "spell id", getName()); diff --git a/src/strategy/values/DpsTargetValue.cpp b/src/strategy/values/DpsTargetValue.cpp index 258f8dfee..644872c88 100644 --- a/src/strategy/values/DpsTargetValue.cpp +++ b/src/strategy/values/DpsTargetValue.cpp @@ -3,6 +3,7 @@ */ #include "DpsTargetValue.h" +#include "PlayerbotAIConfig.h" #include "Playerbots.h" class FindLeastHpTargetStrategy : public FindTargetStrategy @@ -85,27 +86,36 @@ class FindTargetSmartStrategy : public FindTargetStrategy float new_time = new_unit->GetHealth() / dps_; float old_time = old_unit->GetHealth() / dps_; // [5-20] > (5-0] > (20-inf) - if (GetIntervalLevel(new_time) > GetIntervalLevel(old_time)) { + if (GetIntervalLevel(new_unit) > GetIntervalLevel(old_unit)) { return true; } - int32_t interval = GetIntervalLevel(new_time); - if (interval == 2 || interval == 0) { + int32_t level = GetIntervalLevel(new_unit); + if (level % 10 == 2 || level % 10 == 0) { return new_time < old_time; } // dont switch targets when all of them with low health - if (botAI->GetAiObjectContext()->GetValue("current target")->Get() == old_unit) { + Unit* currentTarget = botAI->GetAiObjectContext()->GetValue("current target")->Get(); + if (currentTarget == new_unit) { + return true; + } + if (currentTarget == old_unit) { return false; } return new_time > old_time; } - int32_t GetIntervalLevel(float time) { + int32_t GetIntervalLevel(Unit* unit) { + float time = unit->GetHealth() / dps_; + float dis = unit->GetDistance(botAI->GetBot()); + float attackRange = botAI->IsRanged(botAI->GetBot()) ? sPlayerbotAIConfig->spellDistance : sPlayerbotAIConfig->meleeDistance; + attackRange += 5.0f; + int level = dis < attackRange ? 10 : 0; if (time >= 5 && time <= 20) { - return 2; + return level + 2; } if (time < 5) { - return 1; + return level + 1; } - return 0; + return level; } protected: From 618f2cd95e2bea93ba6835b83259924db5cd0c4b Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Sun, 22 Oct 2023 17:00:50 +0800 Subject: [PATCH 05/12] shaman bdps --- src/AiFactory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AiFactory.cpp b/src/AiFactory.cpp index b0ee121f4..cae942af3 100644 --- a/src/AiFactory.cpp +++ b/src/AiFactory.cpp @@ -302,7 +302,7 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa else if (tab == 2) engine->addStrategies("heal", "bmana", nullptr); else - engine->addStrategies("melee", "melee aoe", "bmana", "threat", nullptr); + engine->addStrategies("melee", "melee aoe", "bdps", "threat", nullptr); engine->addStrategies("dps assist", "cure", "totems", nullptr); break; From b16c104ba77991496a775dfa58a62477d143fcaf Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Sun, 22 Oct 2023 23:21:42 +0800 Subject: [PATCH 06/12] gs_modifier for expected dps --- src/strategy/values/ExpectedLifetimeValue.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/strategy/values/ExpectedLifetimeValue.cpp b/src/strategy/values/ExpectedLifetimeValue.cpp index 3868bbcfb..b41fff14b 100644 --- a/src/strategy/values/ExpectedLifetimeValue.cpp +++ b/src/strategy/values/ExpectedLifetimeValue.cpp @@ -45,7 +45,7 @@ float ExpectedGroupDpsValue::Calculate() } else if (level <= 70) { basic_dps = 350 + (level - 60) * 40; } else { - basic_dps = 750 + (level - 70) * 100; + basic_dps = 750 + (level - 70) * 125; } if (level <= 8) { @@ -59,10 +59,12 @@ float ExpectedGroupDpsValue::Calculate() } else if (level <= 80) { basic_gs = (155 + (level - 70) * 4) * 4; } + float gap = mixedGearScore - basic_gs; + float gs_modifier = (float)mixedGearScore / basic_gs - 1; + gs_modifier = gs_modifier * 3 + 1; - float gs_modifier = (float)mixedGearScore / basic_gs; if (gs_modifier < 0.5) gs_modifier = 0.5; - if (gs_modifier > 3) gs_modifier = 3; + if (gs_modifier > 4) gs_modifier = 3; return dps_num * basic_dps * gs_modifier; } \ No newline at end of file From 10462126b4da57e6be96bab1d9cbe4b7e4737833 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Wed, 25 Oct 2023 20:29:32 +0800 Subject: [PATCH 07/12] miscs --- src/PlayerbotFactory.cpp | 2 +- src/strategy/hunter/HunterTriggers.cpp | 7 +++++++ src/strategy/hunter/HunterTriggers.h | 1 + src/strategy/priest/ShadowPriestStrategy.cpp | 2 +- src/strategy/shaman/GenericShamanStrategy.cpp | 3 ++- src/strategy/triggers/CureTriggers.h | 2 +- src/strategy/values/ExpectedLifetimeValue.cpp | 2 +- 7 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/PlayerbotFactory.cpp b/src/PlayerbotFactory.cpp index 577357107..9c84de08d 100644 --- a/src/PlayerbotFactory.cpp +++ b/src/PlayerbotFactory.cpp @@ -1335,7 +1335,7 @@ void PlayerbotFactory::InitEquipment(bool incremental) float bestScoreForSlot = -1; uint32 bestItemForSlot = 0; - for (int attempts = 0; attempts < std::min((int)ids.size(), 25); attempts++) + for (int attempts = 0; attempts < std::max((int)(ids.size() * 0.75), 1); attempts++) { uint32 index = urand(0, ids.size() - 1); uint32 newItemId = ids[index]; diff --git a/src/strategy/hunter/HunterTriggers.cpp b/src/strategy/hunter/HunterTriggers.cpp index db6c77952..f56065b1c 100644 --- a/src/strategy/hunter/HunterTriggers.cpp +++ b/src/strategy/hunter/HunterTriggers.cpp @@ -7,6 +7,7 @@ #include "HunterActions.h" #include "Playerbots.h" #include "ServerFacade.h" +#include "SharedDefines.h" bool HunterAspectOfTheHawkTrigger::IsActive() { @@ -77,3 +78,9 @@ bool SwitchToMeleeTrigger::IsActive() return botAI->HasStrategy("ranged", BOT_STATE_COMBAT) && target && (target->GetVictim() == bot && sServerFacade->IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", "current target"), 8.0f)); } + +bool TargetRemoveEnrageTrigger::IsActive() +{ + Unit* target = GetTarget(); + return target && (botAI->HasAuraToDispel(target, DISPEL_ENRAGE) || botAI->HasAuraToDispel(target, DISPEL_MAGIC)); +} \ No newline at end of file diff --git a/src/strategy/hunter/HunterTriggers.h b/src/strategy/hunter/HunterTriggers.h index 6096bca75..c904732e8 100644 --- a/src/strategy/hunter/HunterTriggers.h +++ b/src/strategy/hunter/HunterTriggers.h @@ -160,5 +160,6 @@ class TargetRemoveEnrageTrigger : public TargetAuraDispelTrigger { public: TargetRemoveEnrageTrigger(PlayerbotAI* ai) : TargetAuraDispelTrigger(ai, "tranquilizing shot", DISPEL_ENRAGE) {} + bool IsActive() override; }; #endif diff --git a/src/strategy/priest/ShadowPriestStrategy.cpp b/src/strategy/priest/ShadowPriestStrategy.cpp index e2fae3c0a..8c00165b1 100644 --- a/src/strategy/priest/ShadowPriestStrategy.cpp +++ b/src/strategy/priest/ShadowPriestStrategy.cpp @@ -40,7 +40,7 @@ void ShadowPriestAoeStrategy::InitTriggers(std::vector& triggers) { triggers.push_back(new TriggerNode("shadow word: pain on attacker", NextAction::array(0, new NextAction("shadow word: pain on attacker", ACTION_NORMAL + 5), nullptr))); triggers.push_back(new TriggerNode("vampiric touch on attacker", NextAction::array(0, new NextAction("vampiric touch on attacker", ACTION_NORMAL + 4), nullptr))); - // triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("mind sear", ACTION_HIGH + 4), nullptr))); + triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("mind sear", ACTION_HIGH + 4), nullptr))); } void ShadowPriestDebuffStrategy::InitTriggers(std::vector& triggers) diff --git a/src/strategy/shaman/GenericShamanStrategy.cpp b/src/strategy/shaman/GenericShamanStrategy.cpp index e05c97540..9a0583f0f 100644 --- a/src/strategy/shaman/GenericShamanStrategy.cpp +++ b/src/strategy/shaman/GenericShamanStrategy.cpp @@ -4,6 +4,7 @@ #include "HealShamanStrategy.h" #include "Playerbots.h" +#include "Strategy.h" class GenericShamanStrategyActionNodeFactory : public NamedObjectFactory { @@ -116,7 +117,7 @@ void GenericShamanStrategy::InitTriggers(std::vector& triggers) triggers.push_back(new TriggerNode("wind shear", NextAction::array(0, new NextAction("wind shear", 23.0f), nullptr))); triggers.push_back(new TriggerNode("wind shear on enemy healer", NextAction::array(0, new NextAction("wind shear on enemy healer", 23.0f), nullptr))); - triggers.push_back(new TriggerNode("purge", NextAction::array(0, new NextAction("purge", 10.0f), nullptr))); + triggers.push_back(new TriggerNode("purge", NextAction::array(0, new NextAction("purge", ACTION_DISPEL), nullptr))); // triggers.push_back(new TriggerNode("party member medium health", NextAction::array(0, new NextAction("lesser healing wave on party", 25.0f), nullptr))); // triggers.push_back(new TriggerNode("party member low health", NextAction::array(0, new NextAction("riptide on party", 25.0f), nullptr))); // triggers.push_back(new TriggerNode("medium aoe heal", NextAction::array(0, new NextAction("chain heal", 27.0f), nullptr))); diff --git a/src/strategy/triggers/CureTriggers.h b/src/strategy/triggers/CureTriggers.h index 4632f1541..50bedf2fc 100644 --- a/src/strategy/triggers/CureTriggers.h +++ b/src/strategy/triggers/CureTriggers.h @@ -13,7 +13,7 @@ class Unit; class NeedCureTrigger : public SpellTrigger { public: - NeedCureTrigger(PlayerbotAI* botAI, std::string const spell, uint32 dispelType) : SpellTrigger(botAI, spell, 2 * 1000), dispelType(dispelType) { } + NeedCureTrigger(PlayerbotAI* botAI, std::string const spell, uint32 dispelType) : SpellTrigger(botAI, spell, 1 * 1000), dispelType(dispelType) { } std::string const GetTargetName() override { return "self target"; } bool IsActive() override; diff --git a/src/strategy/values/ExpectedLifetimeValue.cpp b/src/strategy/values/ExpectedLifetimeValue.cpp index b41fff14b..084593cd7 100644 --- a/src/strategy/values/ExpectedLifetimeValue.cpp +++ b/src/strategy/values/ExpectedLifetimeValue.cpp @@ -64,7 +64,7 @@ float ExpectedGroupDpsValue::Calculate() gs_modifier = gs_modifier * 3 + 1; if (gs_modifier < 0.5) gs_modifier = 0.5; - if (gs_modifier > 4) gs_modifier = 3; + if (gs_modifier > 4) gs_modifier = 4; return dps_num * basic_dps * gs_modifier; } \ No newline at end of file From 0a0ad09125135803de8d80a77264c206033956bd Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Thu, 26 Oct 2023 19:42:34 +0800 Subject: [PATCH 08/12] rpg strategy default actions --- src/strategy/generic/RpgStrategy.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/strategy/generic/RpgStrategy.cpp b/src/strategy/generic/RpgStrategy.cpp index d0b8b0c8d..233374f8f 100644 --- a/src/strategy/generic/RpgStrategy.cpp +++ b/src/strategy/generic/RpgStrategy.cpp @@ -26,7 +26,7 @@ RpgStrategy::RpgStrategy(PlayerbotAI* botAI) : Strategy(botAI) NextAction** RpgStrategy::getDefaultActions() { - return NextAction::array(0, new NextAction("rpg", 1.1f), nullptr); + return NextAction::array(0, new NextAction("rpg", 1.0f), nullptr); } void RpgStrategy::InitTriggers(std::vector& triggers) @@ -35,23 +35,23 @@ void RpgStrategy::InitTriggers(std::vector& triggers) triggers.push_back(new TriggerNode("far from rpg target", NextAction::array(0, new NextAction("move to rpg target", 5.0f), nullptr))); //Sub actions - triggers.push_back(new TriggerNode("rpg", NextAction::array(0, new NextAction("rpg stay", 1.001f), nullptr))); - triggers.push_back(new TriggerNode("rpg", NextAction::array(0, new NextAction("rpg work", 1.001f), nullptr))); - triggers.push_back(new TriggerNode("rpg", NextAction::array(0, new NextAction("rpg emote", 1.001f), nullptr))); - triggers.push_back(new TriggerNode("has rpg target", NextAction::array(0, new NextAction("rpg cancel", 1.001f), nullptr))); + triggers.push_back(new TriggerNode("rpg", NextAction::array(0, new NextAction("rpg stay", 1.101f), nullptr))); + triggers.push_back(new TriggerNode("rpg", NextAction::array(0, new NextAction("rpg work", 1.101f), nullptr))); + triggers.push_back(new TriggerNode("rpg", NextAction::array(0, new NextAction("rpg emote", 1.101f), nullptr))); + triggers.push_back(new TriggerNode("has rpg target", NextAction::array(0, new NextAction("rpg cancel", 1.101f), nullptr))); // triggers.push_back(new TriggerNode("rpg taxi", NextAction::array(0, new NextAction("rpg taxi", 1.005f), nullptr))); - triggers.push_back(new TriggerNode("rpg discover", NextAction::array(0, new NextAction("rpg discover", 1.110f), nullptr))); - triggers.push_back(new TriggerNode("rpg start quest", NextAction::array(0, new NextAction("rpg start quest", 1.080f), nullptr))); - triggers.push_back(new TriggerNode("rpg end quest", NextAction::array(0, new NextAction("rpg end quest", 1.090f), nullptr))); - triggers.push_back(new TriggerNode("rpg buy", NextAction::array(0, new NextAction("rpg buy", 1.030f), nullptr))); + triggers.push_back(new TriggerNode("rpg discover", NextAction::array(0, new NextAction("rpg discover", 1.210f), nullptr))); + triggers.push_back(new TriggerNode("rpg start quest", NextAction::array(0, new NextAction("rpg start quest", 1.180f), nullptr))); + triggers.push_back(new TriggerNode("rpg end quest", NextAction::array(0, new NextAction("rpg end quest", 1.190f), nullptr))); + triggers.push_back(new TriggerNode("rpg buy", NextAction::array(0, new NextAction("rpg buy", 1.130f), nullptr))); // triggers.push_back(new TriggerNode("rpg sell", NextAction::array(0, new NextAction("rpg sell", 1.100f), nullptr))); - triggers.push_back(new TriggerNode("rpg repair", NextAction::array(0, new NextAction("rpg repair", 1.095f), nullptr))); + triggers.push_back(new TriggerNode("rpg repair", NextAction::array(0, new NextAction("rpg repair", 1.195f), nullptr))); // triggers.push_back(new TriggerNode("rpg train", NextAction::array(0, new NextAction("rpg train", 1.080f), nullptr))); - triggers.push_back(new TriggerNode("rpg heal", NextAction::array(0, new NextAction("rpg heal", 1.025f), nullptr))); - triggers.push_back(new TriggerNode("rpg home bind", NextAction::array(0, new NextAction("rpg home bind", 1.060f), nullptr))); + triggers.push_back(new TriggerNode("rpg heal", NextAction::array(0, new NextAction("rpg heal", 1.125f), nullptr))); + triggers.push_back(new TriggerNode("rpg home bind", NextAction::array(0, new NextAction("rpg home bind", 1.160f), nullptr))); // triggers.push_back(new TriggerNode("rpg queue bg", NextAction::array(0, new NextAction("rpg queue bg", 1.085f), nullptr))); - triggers.push_back(new TriggerNode("rpg buy petition", NextAction::array(0, new NextAction("rpg buy petition", 1.040f), nullptr))); - triggers.push_back(new TriggerNode("rpg use", NextAction::array(0, new NextAction("rpg use", 1.002f), nullptr))); + triggers.push_back(new TriggerNode("rpg buy petition", NextAction::array(0, new NextAction("rpg buy petition", 1.140f), nullptr))); + triggers.push_back(new TriggerNode("rpg use", NextAction::array(0, new NextAction("rpg use", 1.102f), nullptr))); //triggers.push_back(new TriggerNode("rpg spell", NextAction::array(0, new NextAction("rpg spell", 1.001f), nullptr))); //triggers.push_back(new TriggerNode("rpg craft", NextAction::array(0, new NextAction("rpg craft", 1.001f), nullptr))); // triggers.push_back(new TriggerNode("rpg trade useful", NextAction::array(0, new NextAction("rpg trade useful", 1.030f), nullptr))); From 83e62b4cd30f0f029d1be10b2840679c5a18f259 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Thu, 26 Oct 2023 21:05:23 +0800 Subject: [PATCH 09/12] move random for rpg strategy --- src/strategy/actions/MovementActions.cpp | 29 +++++++++++++++++++----- src/strategy/generic/RpgStrategy.cpp | 1 + 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index 919b77072..de1446ad8 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -9,6 +9,7 @@ #include "ObjectGuid.h" #include "PathGenerator.h" #include "PlayerbotAIConfig.h" +#include "Random.h" #include "SharedDefines.h" #include "TargetedMovementGenerator.h" #include "Event.h" @@ -1257,11 +1258,27 @@ bool MovementAction::MoveAway(Unit* target) if (!target) { return false; } - 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, false, false, true); + float init_angle = target->GetAngle(bot); + for (float delta = 0; delta <= M_PI / 2; delta += M_PI / 8) { + float angle = init_angle + delta; + float dx = bot->GetPositionX() + cos(angle) * sPlayerbotAIConfig->fleeDistance; + float dy = bot->GetPositionY() + sin(angle) * sPlayerbotAIConfig->fleeDistance; + float dz = bot->GetPositionZ(); + if (MoveTo(target->GetMapId(), dx, dy, dz, false, false, true)) { + return true; + } + if (delta == 0) { + continue; + } + angle = init_angle - delta; + dx = bot->GetPositionX() + cos(angle) * sPlayerbotAIConfig->fleeDistance; + dy = bot->GetPositionY() + sin(angle) * sPlayerbotAIConfig->fleeDistance; + dz = bot->GetPositionZ(); + if (MoveTo(target->GetMapId(), dx, dy, dz, false, false, true)) { + return true; + } + } + return false; } bool MovementAction::MoveInside(uint32 mapId, float x, float y, float z, float distance) @@ -1463,7 +1480,7 @@ bool MoveRandomAction::Execute(Event event) if (map->IsInWater(bot->GetPhaseMask(), x, y, z, bot->GetCollisionHeight())) continue; - bool moved = MoveTo(bot->GetMapId(), x, y, z); + bool moved = MoveTo(bot->GetMapId(), x, y, z, false, false, true); if (moved) return true; } diff --git a/src/strategy/generic/RpgStrategy.cpp b/src/strategy/generic/RpgStrategy.cpp index 233374f8f..986c11d46 100644 --- a/src/strategy/generic/RpgStrategy.cpp +++ b/src/strategy/generic/RpgStrategy.cpp @@ -32,6 +32,7 @@ NextAction** RpgStrategy::getDefaultActions() void RpgStrategy::InitTriggers(std::vector& triggers) { triggers.push_back(new TriggerNode("no rpg target", NextAction::array(0, new NextAction("choose rpg target", 5.0f), nullptr))); + triggers.push_back(new TriggerNode("no rpg target", NextAction::array(0, new NextAction("move random", 1.10f), NULL))); triggers.push_back(new TriggerNode("far from rpg target", NextAction::array(0, new NextAction("move to rpg target", 5.0f), nullptr))); //Sub actions From e8c76f51d2c83db1e827ba51adbb90eafefe1b5f Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Thu, 26 Oct 2023 21:14:28 +0800 Subject: [PATCH 10/12] move random angle --- src/strategy/actions/MovementActions.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index de1446ad8..126395090 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -1473,8 +1473,9 @@ bool MoveRandomAction::Execute(Event event) float x = bot->GetPositionX(); float y = bot->GetPositionY(); float z = bot->GetPositionZ(); - x += urand(0, distance) - distance / 2; - y += urand(0, distance) - distance / 2; + float angle = (float)rand_norm() * static_cast(M_PI); + x += urand(0, distance) * cos(angle); + y += urand(0, distance) * sin(angle); bot->UpdateGroundPositionZ(x, y, z); if (map->IsInWater(bot->GetPhaseMask(), x, y, z, bot->GetCollisionHeight())) From b2089c5935725c8e2de501055491a9cb7744cc6d Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Fri, 27 Oct 2023 19:22:37 +0800 Subject: [PATCH 11/12] bdps for enhancement shaman --- src/AiFactory.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/AiFactory.cpp b/src/AiFactory.cpp index cae942af3..e2fb5d1c3 100644 --- a/src/AiFactory.cpp +++ b/src/AiFactory.cpp @@ -473,10 +473,10 @@ void AiFactory::AddDefaultNonCombatStrategies(Player* player, PlayerbotAI* const nonCombatEngine->addStrategies("bdps", "dps assist", "pet", nullptr); break; case CLASS_SHAMAN: - // if (tab == 0 || tab == 2) - nonCombatEngine->addStrategy("bmana"); - // else - // nonCombatEngine->addStrategy("bdps"); + if (tab == 0 || tab == 2) + nonCombatEngine->addStrategy("bmana"); + else + nonCombatEngine->addStrategy("bdps"); nonCombatEngine->addStrategies("dps assist", "cure", nullptr); break; From 4e867606f20cc5bafad621202e5d1b45a44e264b Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Fri, 27 Oct 2023 19:23:13 +0800 Subject: [PATCH 12/12] reduce database error during creation --- src/RandomPlayerbotFactory.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/RandomPlayerbotFactory.cpp b/src/RandomPlayerbotFactory.cpp index e00eef84c..d303360c5 100644 --- a/src/RandomPlayerbotFactory.cpp +++ b/src/RandomPlayerbotFactory.cpp @@ -206,11 +206,11 @@ Player* RandomPlayerbotFactory::CreateRandomBot(WorldSession* session, uint8 cls player->setCinematic(2); player->SetAtLoginFlag(AT_LOGIN_NONE); - player->SaveToDB(true, false); if (player->getClass() == CLASS_DEATH_KNIGHT) { player->learnSpell(50977, false); } + // player->SaveToDB(true, false); // player->RewardQuest(const Quest *quest, uint32 reward, Object *questGiver) LOG_DEBUG("playerbots", "Random bot created for account {} - name: \"{}\"; race: {}; class: {}", accountId, name.c_str(), race, cls); @@ -274,12 +274,14 @@ void RandomPlayerbotFactory::CreateRandomBots() LOG_INFO("playerbots", "Deleting all random bot characters, {} accounts collected...", botAccounts.size()); QueryResult results = LoginDatabase.Query("SELECT id FROM account WHERE username LIKE '{}%%'", sPlayerbotAIConfig->randomBotAccountPrefix.c_str()); + int32 deletion_count = 0; if (results) { do { Field* fields = results->Fetch(); uint32 accId = fields[0].Get(); + LOG_INFO("playerbots", "Deleting account accID: {}({})...", accId, ++deletion_count); AccountMgr::DeleteAccount(accId); } while (results->NextRow()); } @@ -288,8 +290,11 @@ void RandomPlayerbotFactory::CreateRandomBots() CharacterDatabase.Execute("UPDATE playerbots_names SET in_use=0 WHERE in_use=1"); /* TODO(yunfan): we need to sleep here to wait for async account deleted, or the newly account won't be created correctly the better way is turning the async db operation to sync db operation */ - std::this_thread::sleep_for(10ms * sPlayerbotAIConfig->randomBotAccountCount); - LOG_INFO("playerbots", "Random bot characters deleted"); + std::this_thread::sleep_for(100ms * sPlayerbotAIConfig->randomBotAccountCount); + LOG_INFO("playerbots", "Random bot characters deleted."); + LOG_INFO("playerbots", "Please reset the AiPlayerbot.DeleteRandomBotAccounts to 0 and restart the server..."); + World::StopNow(SHUTDOWN_EXIT_CODE); + return; } uint32 totalAccCount = sPlayerbotAIConfig->randomBotAccountCount; @@ -330,7 +335,7 @@ void RandomPlayerbotFactory::CreateRandomBots() if (account_creation) { /* wait for async accounts create to make character create correctly, same as account delete */ - std::this_thread::sleep_for(10ms * sPlayerbotAIConfig->randomBotAccountCount); + std::this_thread::sleep_for(100ms * sPlayerbotAIConfig->randomBotAccountCount); } LOG_INFO("playerbots", "Creating random bot characters...");