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 33b320a5..b0ee121f 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 86341693..65d5612c 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 0f618cfd..e268914f 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 9c82eeea..4083938a 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 854a7b89..4de7b671 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 079d4ad9..b63908cb 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 8966fa69..8feba413 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 4369689f..638a9967 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 7ec2220a..4ef8a3f0 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 be35d17b..1e3d470b 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 9faeeb2a..15cb6efb 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 aee84ee2..258f8dfe 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 3518af2e..3868bbcf 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 817dbd50..173c84da 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 99ffcc64..e0ece34c 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 21b5ed57..3087f744 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 55bd712a..12328b6d 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 3919df3f..919b7707 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 b442c3f1..ce437e9c 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 7f0ed5bf..d3d49ce5 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 03e1ffd5..51c2692e 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 a3f15140..5b9dc170 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 39b3b027..7a017821 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 a7cf3bbd..ffbe8300 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 4ef8a3f0..891190da 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 c5c46aa4..db97a4da 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 56503175..8382c3b1 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 77ee30eb..39822aa1 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 0662660e..907d9411 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 6f651039..15215026 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 3c03d7ac..d8b3f9a1 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 7f15dd35..322de685 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 72b216a1..ba24d730 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 a4560d68..e2fae3c0 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 990264d7..6510e72d 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 8ff13bbe..cf26ec08 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 6dfb015a..6455dee3 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 c514dc33..54db4dac 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 d030a9ba..0859d706 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 b5978198..f5247c3f 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 ca1fae48..a828fdec 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 4643ff63..c6314bae 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 3894b459..1f8c3aee 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 0eaf3553..e9beec2d 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 ee20b83d..10ef0a31 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 258f8dfe..644872c8 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 b0ee121f..cae942af 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 3868bbcf..b41fff14 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 57735710..9c84de08 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 db6c7795..f56065b1 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 6096bca7..c904732e 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 e2fae3c0..8c00165b 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 e05c9754..9a0583f0 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 4632f154..50bedf2f 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 b41fff14..084593cd 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 d0b8b0c8..233374f8 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 919b7707..de1446ad 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 233374f8..986c11d4 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 de1446ad..12639509 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 cae942af..e2fb5d1c 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 e00eef84..d303360c 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...");