From 7cacca5293559e89700e3e4726db26fc312ec34d Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Mon, 24 Jun 2024 21:56:14 +0800 Subject: [PATCH 01/18] [Optimization] Better performance --- src/strategy/Engine.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/strategy/Engine.cpp b/src/strategy/Engine.cpp index 12328b6d..cef411c6 100644 --- a/src/strategy/Engine.cpp +++ b/src/strategy/Engine.cpp @@ -144,7 +144,7 @@ bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal) ActionBasket* basket = nullptr; time_t currentTime = time(nullptr); - aiObjectContext->Update(); + // aiObjectContext->Update(); ProcessTriggers(minimal); PushDefaultActions(); @@ -469,7 +469,7 @@ bool Engine::HasStrategy(std::string const name) void Engine::ProcessTriggers(bool minimal) { - std::unordered_map fires; + // std::unordered_map fires; for (std::vector::iterator i = triggers.begin(); i != triggers.end(); i++) { TriggerNode* node = *i; @@ -499,21 +499,22 @@ void Engine::ProcessTriggers(bool minimal) if (!event) continue; - fires[trigger] = event; + // fires[trigger] = event; LogAction("T:%s", trigger->getName().c_str()); + MultiplyAndPush(node->getHandlers(), 0.0f, false, event, "trigger"); } } - for (std::vector::iterator i = triggers.begin(); i != triggers.end(); i++) - { - TriggerNode* node = *i; - Trigger* trigger = node->getTrigger(); - Event event = fires[trigger]; - if (!event) - continue; + // for (std::vector::iterator i = triggers.begin(); i != triggers.end(); i++) + // { + // TriggerNode* node = *i; + // Trigger* trigger = node->getTrigger(); + // if (fires.find(trigger) == fires.end()) + // continue; - MultiplyAndPush(node->getHandlers(), 0.0f, false, event, "trigger"); - } + // Event event = fires[trigger]; + + // } for (std::vector::iterator i = triggers.begin(); i != triggers.end(); i++) { From c950ea836e4fd54c7dd97ab546b91effee26364f Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Mon, 24 Jun 2024 21:59:21 +0800 Subject: [PATCH 02/18] [Attack target] Ignore moon mark --- src/strategy/values/DpsTargetValue.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/strategy/values/DpsTargetValue.cpp b/src/strategy/values/DpsTargetValue.cpp index fc8f6ce1..05f6199b 100644 --- a/src/strategy/values/DpsTargetValue.cpp +++ b/src/strategy/values/DpsTargetValue.cpp @@ -71,6 +71,12 @@ class CasterFindTargetSmartStrategy : public FindTargetStrategy 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; } @@ -138,6 +144,12 @@ class NonCasterFindTargetSmartStrategy : public FindTargetStrategy 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; } @@ -193,6 +205,12 @@ class ComboFindTargetSmartStrategy : public FindTargetStrategy 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; } From af5e5a3b071a64bf6f8befa67868349e38376281 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Mon, 24 Jun 2024 22:24:15 +0800 Subject: [PATCH 03/18] [Avoid aoe] Smarter position --- conf/playerbots.conf.dist | 2 +- src/strategy/actions/MovementActions.cpp | 74 +++++++++++++++++++++++- src/strategy/actions/MovementActions.h | 5 +- 3 files changed, 74 insertions(+), 7 deletions(-) diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index 88cffdce..77c00a10 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -125,7 +125,7 @@ AiPlayerbot.MinEnchantingBotLevel = 60 AiPlayerbot.LimitEnchantExpansion = 1 # Randombots checking players gear score level and deny the group invite if it's too low -# Default: 1 (enabled) +# Default: 0 (disabled) AiPlayerbot.GearScoreCheck = 0 # Quest that will be completed and rewarded to all random bots diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index 7ab12027..9eb05039 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -1645,16 +1645,23 @@ bool AvoidAoeAction::AvoidUnitWithDamageAura() return false; } -bool AvoidAoeAction::FleePosition(Position pos, float radius, std::string name) +Position AvoidAoeAction::BestPositionForMelee(Position pos, float radius) { Unit* currentTarget = AI_VALUE(Unit*, "current target"); std::vector possibleAngles; if (currentTarget) { // Normally, move to left or right is the best position - float angleLeft = bot->GetAngle(currentTarget) + M_PI / 2; - float angleRight = bot->GetAngle(currentTarget) - M_PI / 2; + bool isTanking = (currentTarget->CanFreeMove()) && (currentTarget->GetVictim() == bot); + float angle = bot->GetAngle(currentTarget); + float angleLeft = angle + M_PI / 2; + float angleRight = angle - M_PI / 2; possibleAngles.push_back(angleLeft); possibleAngles.push_back(angleRight); + if (isTanking) { + possibleAngles.push_back(angle + M_PI); + possibleAngles.push_back(angle); + possibleAngles.push_back(bot->GetAngle(&pos) - M_PI); + } } else { float angleTo = bot->GetAngle(&pos) - M_PI; possibleAngles.push_back(angleTo); @@ -1673,6 +1680,67 @@ bool AvoidAoeAction::FleePosition(Position pos, float radius, std::string name) } } if (farestDis > 0.0f) { + return bestPos; + } + return Position(); +} + +Position AvoidAoeAction::BestPositionForRanged(Position pos, float radius) +{ + Unit* currentTarget = AI_VALUE(Unit*, "current target"); + std::vector possibleAngles; + float angleToTarget = 0.0f; + float angleFleeFromCenter = bot->GetAngle(&pos) - M_PI; + if (currentTarget) { + // Normally, move to left or right is the best position + angleToTarget = bot->GetAngle(currentTarget); + float angleLeft = angleToTarget + M_PI / 2; + float angleRight = angleToTarget - M_PI / 2; + possibleAngles.push_back(angleLeft); + possibleAngles.push_back(angleRight); + possibleAngles.push_back(angleToTarget + M_PI); + possibleAngles.push_back(angleToTarget); + possibleAngles.push_back(angleFleeFromCenter); + } else { + possibleAngles.push_back(angleFleeFromCenter); + } + float farestDis = 0.0f; + Position bestPos; + for (float &angle : possibleAngles) { + float fleeDis = sPlayerbotAIConfig->fleeDistance; + Position fleePos{bot->GetPositionX() + cos(angle) * fleeDis, + bot->GetPositionY() + sin(angle) * fleeDis, + bot->GetPositionZ()}; + // backward, flee + if (currentTarget && (angle == angleToTarget + M_PI || angle == angleFleeFromCenter) + && fleePos.GetExactDist(currentTarget) > sPlayerbotAIConfig->spellDistance) { + continue; + } + // forward, flee + if (currentTarget && (angle == angleToTarget || angle == angleFleeFromCenter) + && fleePos.GetExactDist(currentTarget) < (sPlayerbotAIConfig->tooCloseDistance + 5.0f)) { + continue; + } + if (pos.GetExactDist(fleePos) > farestDis) { + farestDis = pos.GetExactDist(fleePos); + bestPos = fleePos; + } + } + if (farestDis > 0.0f) { + return bestPos; + } + return Position(); +} + +bool AvoidAoeAction::FleePosition(Position pos, float radius, std::string name) +{ + Position bestPos; + if (botAI->IsMelee(bot)) { + bestPos = BestPositionForMelee(pos, radius); + } else if (botAI->IsRanged(bot)) { + bestPos = BestPositionForRanged(pos, radius); + } + if (bestPos != Position()) { if (MoveTo(bot->GetMapId(), bestPos.GetPositionX(), bestPos.GetPositionY(), bestPos.GetPositionZ(), false, false, true)) { if (sPlayerbotAIConfig->tellWhenAvoidAoe && lastTellTimer < time(NULL) - 10) { lastTellTimer = time(NULL); diff --git a/src/strategy/actions/MovementActions.h b/src/strategy/actions/MovementActions.h index c53bf25e..3cfdc685 100644 --- a/src/strategy/actions/MovementActions.h +++ b/src/strategy/actions/MovementActions.h @@ -78,9 +78,8 @@ class AvoidAoeAction : public MovementAction bool AvoidAuraWithDynamicObj(); bool AvoidGameObjectWithDamage(); bool AvoidUnitWithDamageAura(); - // Position PositionForTank(Position pos, float radius); - // Position PositionForMelee(Position pos, float radius); - // Position PositionForRanged(Position pos, float radius); + Position BestPositionForMelee(Position pos, float radius); + Position BestPositionForRanged(Position pos, float radius); bool FleePosition(Position pos, float radius, std::string name); time_t lastTellTimer = 0; }; From fb404b27a9ab0366897c594fdf5aaaab51309b17 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Wed, 26 Jun 2024 20:30:12 +0800 Subject: [PATCH 04/18] [Initialization] Glyphs remove and dual spec --- src/TravelMgr.cpp | 4 +++- src/strategy/actions/ChangeTalentsAction.cpp | 9 +++++++-- src/strategy/actions/ChatActionContext.h | 2 ++ src/strategy/actions/TrainerAction.cpp | 9 +++++++++ src/strategy/actions/TrainerAction.h | 7 +++++++ src/strategy/generic/ChatCommandHandlerStrategy.cpp | 1 + src/strategy/triggers/ChatTriggerContext.h | 2 ++ 7 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/TravelMgr.cpp b/src/TravelMgr.cpp index 755d1103..f010df99 100644 --- a/src/TravelMgr.cpp +++ b/src/TravelMgr.cpp @@ -1495,6 +1495,8 @@ void TravelTarget::setStatus(TravelStatus status) break; case TRAVEL_STATUS_COOLDOWN: statusTime = tDestination->getCooldownDelay(); + default: + break; } } @@ -3687,7 +3689,7 @@ void TravelMgr::LoadQuestTravelTable() } } else - "all"; + out << "all"; out << "\n"; } diff --git a/src/strategy/actions/ChangeTalentsAction.cpp b/src/strategy/actions/ChangeTalentsAction.cpp index e0f3b8db..69a6b19f 100644 --- a/src/strategy/actions/ChangeTalentsAction.cpp +++ b/src/strategy/actions/ChangeTalentsAction.cpp @@ -23,10 +23,15 @@ bool ChangeTalentsAction::Execute(Event event) if (param.find("help") != std::string::npos) { out << TalentsHelp(); } else if (param.find("switch") != std::string::npos) { - if (param.find("switch 1")) { + if (param.find("switch 1") != std::string::npos) { bot->ActivateSpec(0); out << "Active first talent"; - } else if (param.find("switch 2")) { + } else if (param.find("switch 2") != std::string::npos) { + if (bot->GetSpecsCount() == 1 && bot->GetLevel() >= sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL)) + { + bot->CastSpell(bot, 63680, true, nullptr, nullptr, bot->GetGUID()); + bot->CastSpell(bot, 63624, true, nullptr, nullptr, bot->GetGUID()); + } bot->ActivateSpec(1); out << "Active second talent"; } diff --git a/src/strategy/actions/ChatActionContext.h b/src/strategy/actions/ChatActionContext.h index 2930dae0..8fb48c64 100644 --- a/src/strategy/actions/ChatActionContext.h +++ b/src/strategy/actions/ChatActionContext.h @@ -115,6 +115,7 @@ class ChatActionContext : public NamedObjectContext creators["de"] = &ChatActionContext::dead; creators["trainer"] = &ChatActionContext::trainer; creators["maintenance"] = &ChatActionContext::maintenance; + creators["remove glyph"] = &ChatActionContext::remove_glyph; creators["autogear"] = &ChatActionContext::autogear; creators["equip upgrade"] = &ChatActionContext::equip_upgrade; creators["attack my target"] = &ChatActionContext::attack_my_target; @@ -215,6 +216,7 @@ class ChatActionContext : public NamedObjectContext static Action* attack_my_target(PlayerbotAI* botAI) { return new AttackMyTargetAction(botAI); } static Action* trainer(PlayerbotAI* botAI) { return new TrainerAction(botAI); } static Action* maintenance(PlayerbotAI* botAI) { return new MaintenanceAction(botAI); } + static Action* remove_glyph(PlayerbotAI* botAI) { return new RemoveGlyphAction(botAI); } static Action* autogear(PlayerbotAI* botAI) { return new AutoGearAction(botAI); } static Action* equip_upgrade(PlayerbotAI* botAI) { return new EquipUpgradeAction(botAI); } static Action* co(PlayerbotAI* botAI) { return new ChangeCombatStrategyAction(botAI); } diff --git a/src/strategy/actions/TrainerAction.cpp b/src/strategy/actions/TrainerAction.cpp index de3fea5d..2454e563 100644 --- a/src/strategy/actions/TrainerAction.cpp +++ b/src/strategy/actions/TrainerAction.cpp @@ -175,6 +175,15 @@ bool MaintenanceAction::Execute(Event event) return true; } +bool RemoveGlyphAction::Execute(Event event) +{ + for (uint32 slotIndex = 0; slotIndex < MAX_GLYPH_SLOT_INDEX; ++slotIndex) + { + bot->SetGlyph(slotIndex, 0, true); + } + return true; +} + bool AutoGearAction::Execute(Event event) { if (!sPlayerbotAIConfig->autoGearCommand) { diff --git a/src/strategy/actions/TrainerAction.h b/src/strategy/actions/TrainerAction.h index ea1f6e66..5ea6300c 100644 --- a/src/strategy/actions/TrainerAction.h +++ b/src/strategy/actions/TrainerAction.h @@ -35,6 +35,13 @@ class MaintenanceAction : public Action bool Execute(Event event) override; }; +class RemoveGlyphAction : public Action +{ + public: + RemoveGlyphAction(PlayerbotAI* botAI) : Action(botAI, "remove glyph") { } + bool Execute(Event event) override; +}; + class AutoGearAction : public Action { public: diff --git a/src/strategy/generic/ChatCommandHandlerStrategy.cpp b/src/strategy/generic/ChatCommandHandlerStrategy.cpp index bbb1c1a4..4da74e5b 100644 --- a/src/strategy/generic/ChatCommandHandlerStrategy.cpp +++ b/src/strategy/generic/ChatCommandHandlerStrategy.cpp @@ -89,6 +89,7 @@ ChatCommandHandlerStrategy::ChatCommandHandlerStrategy(PlayerbotAI* botAI) : Pas supported.push_back("de"); supported.push_back("trainer"); supported.push_back("maintenance"); + supported.push_back("remove glyph"); supported.push_back("autogear"); supported.push_back("equip upgrade"); supported.push_back("chat"); diff --git a/src/strategy/triggers/ChatTriggerContext.h b/src/strategy/triggers/ChatTriggerContext.h index c0721390..af52cd7e 100644 --- a/src/strategy/triggers/ChatTriggerContext.h +++ b/src/strategy/triggers/ChatTriggerContext.h @@ -55,6 +55,7 @@ class ChatTriggerContext : public NamedObjectContext creators["de"] = &ChatTriggerContext::dead; creators["trainer"] = &ChatTriggerContext::trainer; creators["maintenance"] = &ChatTriggerContext::maintenance; + creators["remove glyph"] = &ChatTriggerContext::remove_glyph; creators["autogear"] = &ChatTriggerContext::autogear; creators["equip upgrade"] = &ChatTriggerContext::equip_upgrade; creators["attack"] = &ChatTriggerContext::attack; @@ -168,6 +169,7 @@ class ChatTriggerContext : public NamedObjectContext static Trigger* attack(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "attack"); } static Trigger* trainer(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "trainer"); } static Trigger* maintenance(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "maintenance"); } + static Trigger* remove_glyph(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "remove glyph"); } static Trigger* autogear(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "autogear"); } static Trigger* equip_upgrade(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "equip upgrade"); } static Trigger* co(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "co"); } From 0615e6082bca70cd7cd6d5bf2cb9b4f02674a760 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Wed, 26 Jun 2024 20:46:38 +0800 Subject: [PATCH 05/18] [Configuration] Enable avoid aoe by default --- conf/playerbots.conf.dist | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index 77c00a10..2e60259f 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -338,8 +338,8 @@ AiPlayerbot.AutoSaveMana = 1 AiPlayerbot.SaveManaThreshold = 60 # Enable auto avoid aoe (experimental) -# Default: 0 (disable) -AiPlayerbot.AutoAvoidAoe = 0 +# Default: 1 (enable) +AiPlayerbot.AutoAvoidAoe = 1 # Tell which spell is avoiding (experimental) # Default: 1 (enable) From e91debc330a1c0ea25503b1de8804dd73858bdf4 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Wed, 26 Jun 2024 22:08:04 +0800 Subject: [PATCH 06/18] [Configuration] Enable avoid aoe by default --- src/PlayerbotAIConfig.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index 87b85830..c3892b91 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -91,7 +91,7 @@ bool PlayerbotAIConfig::Initialize() mediumMana = sConfigMgr->GetOption("AiPlayerbot.MediumMana", 40); autoSaveMana = sConfigMgr->GetOption("AiPlayerbot.AutoSaveMana", true); saveManaThreshold = sConfigMgr->GetOption("AiPlayerbot.SaveManaThreshold", 60); - autoAvoidAoe = sConfigMgr->GetOption("AiPlayerbot.AutoAvoidAoe", false); + autoAvoidAoe = sConfigMgr->GetOption("AiPlayerbot.AutoAvoidAoe", true); tellWhenAvoidAoe = sConfigMgr->GetOption("AiPlayerbot.TellWhenAvoidAoe", true); randomGearLoweringChance = sConfigMgr->GetOption("AiPlayerbot.RandomGearLoweringChance", 0.15f); From d8badd453284f039be19a31291d3f73fc03fb8ef Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Wed, 26 Jun 2024 23:44:40 +0800 Subject: [PATCH 07/18] [Avoid aoe] Fix avoid aoe position --- src/strategy/actions/MovementActions.cpp | 8 +++----- src/strategy/values/AoeValues.cpp | 3 ++- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index 9eb05039..67cb4902 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -1711,13 +1711,11 @@ Position AvoidAoeAction::BestPositionForRanged(Position pos, float radius) Position fleePos{bot->GetPositionX() + cos(angle) * fleeDis, bot->GetPositionY() + sin(angle) * fleeDis, bot->GetPositionZ()}; - // backward, flee - if (currentTarget && (angle == angleToTarget + M_PI || angle == angleFleeFromCenter) + if (currentTarget // && (angle == angleToTarget + M_PI || angle == angleFleeFromCenter) && fleePos.GetExactDist(currentTarget) > sPlayerbotAIConfig->spellDistance) { continue; } - // forward, flee - if (currentTarget && (angle == angleToTarget || angle == angleFleeFromCenter) + if (currentTarget // && (angle == angleToTarget || angle == angleFleeFromCenter) && fleePos.GetExactDist(currentTarget) < (sPlayerbotAIConfig->tooCloseDistance + 5.0f)) { continue; } @@ -1737,7 +1735,7 @@ bool AvoidAoeAction::FleePosition(Position pos, float radius, std::string name) Position bestPos; if (botAI->IsMelee(bot)) { bestPos = BestPositionForMelee(pos, radius); - } else if (botAI->IsRanged(bot)) { + } else { bestPos = BestPositionForRanged(pos, radius); } if (bestPos != Position()) { diff --git a/src/strategy/values/AoeValues.cpp b/src/strategy/values/AoeValues.cpp index b27fc307..e3f44bb2 100644 --- a/src/strategy/values/AoeValues.cpp +++ b/src/strategy/values/AoeValues.cpp @@ -125,7 +125,8 @@ Aura* AreaDebuffValue::Calculate() Unit::AuraEffectList const& aurasPeriodicDamagePercent = bot->GetAuraEffectsByType(SPELL_AURA_PERIODIC_DAMAGE_PERCENT); Unit::AuraEffectList const& aurasPeriodicTriggerSpell = bot->GetAuraEffectsByType(SPELL_AURA_PERIODIC_TRIGGER_SPELL); Unit::AuraEffectList const& aurasPeriodicTriggerWithValueSpell = bot->GetAuraEffectsByType(SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE); - for (const Unit::AuraEffectList& list : {aurasPeriodicDamage, aurasPeriodicDamagePercent, aurasPeriodicTriggerSpell, aurasPeriodicTriggerWithValueSpell}) { + Unit::AuraEffectList const& aurasDummy = bot->GetAuraEffectsByType(SPELL_AURA_DUMMY); + for (const Unit::AuraEffectList& list : {aurasPeriodicDamage, aurasPeriodicDamagePercent, aurasPeriodicTriggerSpell, aurasPeriodicTriggerWithValueSpell, aurasDummy}) { for (auto i = list.begin(); i != list.end(); ++i) { AuraEffect* aurEff = *i; From 10527eed2a3499dd7f3826fa61571d4c8238c514 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Wed, 26 Jun 2024 23:54:40 +0800 Subject: [PATCH 08/18] [Log] Better bot teleport info --- src/RandomPlayerbotMgr.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/RandomPlayerbotMgr.cpp b/src/RandomPlayerbotMgr.cpp index 1c320ebd..4d6295b7 100644 --- a/src/RandomPlayerbotMgr.cpp +++ b/src/RandomPlayerbotMgr.cpp @@ -1190,6 +1190,10 @@ void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector& AreaTableEntry const* zone = sAreaTableStore.LookupEntry(map->GetZoneId(bot->GetPhaseMask(), x, y, z)); if (!zone) continue; + + AreaTableEntry const* area = sAreaTableStore.LookupEntry(map->GetAreaId(bot->GetPhaseMask(), x, y, z)); + if (!area) + continue; // Do not teleport to enemy zones if level is low if (zone->team == 4 && bot->GetTeamId() == TEAM_ALLIANCE) @@ -1218,9 +1222,14 @@ void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector& if (bot->GetLevel() <= 18 && (loc.GetMapId() != pInfo->mapId || dis > 10000.0f)) { continue; } - - LOG_INFO("playerbots", "Random teleporting bot {} (level {}) to {} {},{},{} ({}/{} locations)", - bot->GetName().c_str(), bot->GetLevel(), zone->area_name[0], x, y, z, i + 1, tlocs.size()); + LocaleConstant locale = sWorld->GetDefaultDbcLocale(); + + LOG_INFO("playerbots", "Random teleporting bot {} (level {}) to Map: {} ({}) Zone: {} ({}) Area: {} ({}) {},{},{} ({}/{} locations)", + bot->GetName().c_str(), bot->GetLevel(), + map->GetId(), map->GetMapName(), + zone->ID, zone->area_name[locale], + area->ID, area->area_name[locale], + x, y, z, i + 1, tlocs.size()); if (hearth) { From 009be18646b5acb7c0b126ee9d79a14f6d6cf9a9 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Thu, 27 Jun 2024 23:30:04 +0800 Subject: [PATCH 09/18] [Configuration] Fixed level --- conf/playerbots.conf.dist | 4 ++++ src/PlayerbotAIConfig.cpp | 1 + src/PlayerbotAIConfig.h | 1 + src/RandomItemMgr.cpp | 3 +++ src/strategy/actions/XpGainAction.cpp | 6 ++++++ 5 files changed, 15 insertions(+) diff --git a/conf/playerbots.conf.dist b/conf/playerbots.conf.dist index 2e60259f..fa867e68 100644 --- a/conf/playerbots.conf.dist +++ b/conf/playerbots.conf.dist @@ -97,6 +97,10 @@ AiPlayerbot.SummonWhenGroup = 1 AiPlayerbot.RandomBotShowHelmet = 1 AiPlayerbot.RandomBotShowCloak = 1 +# Fix the level of random bot (won't level up by grinding) +# Default: 0 (disable) +AiPlayerbot.RandomBotFixedLevel = 0 + # Disable random levels for randombots # Every bots started on the specified level and level up by killing mobs. AiPlayerbot.DisableRandomLevels = 0 diff --git a/src/PlayerbotAIConfig.cpp b/src/PlayerbotAIConfig.cpp index c3892b91..96142144 100644 --- a/src/PlayerbotAIConfig.cpp +++ b/src/PlayerbotAIConfig.cpp @@ -265,6 +265,7 @@ bool PlayerbotAIConfig::Initialize() // SPP switches enableGreet = sConfigMgr->GetOption("AiPlayerbot.EnableGreet", true); summonWhenGroup = sConfigMgr->GetOption("AiPlayerbot.SummonWhenGroup", true); + randomBotFixedLevel = sConfigMgr->GetOption("AiPlayerbot.RandomBotFixedLevel", false); disableRandomLevels = sConfigMgr->GetOption("AiPlayerbot.DisableRandomLevels", false); randomBotRandomPassword = sConfigMgr->GetOption("AiPlayerbot.RandomBotRandomPassword", true); downgradeMaxLevelBot = sConfigMgr->GetOption("AiPlayerbot.DowngradeMaxLevelBot", true); diff --git a/src/PlayerbotAIConfig.h b/src/PlayerbotAIConfig.h index 5356bc49..cc5e72be 100644 --- a/src/PlayerbotAIConfig.h +++ b/src/PlayerbotAIConfig.h @@ -174,6 +174,7 @@ class PlayerbotAIConfig bool summonWhenGroup; bool randomBotShowHelmet; bool randomBotShowCloak; + bool randomBotFixedLevel; bool disableRandomLevels; uint32 playerbotsXPrate; bool disableDeathKnightLogin; diff --git a/src/RandomItemMgr.cpp b/src/RandomItemMgr.cpp index f2ff7bcb..d909b4b0 100644 --- a/src/RandomItemMgr.cpp +++ b/src/RandomItemMgr.cpp @@ -2159,6 +2159,9 @@ void RandomItemMgr::BuildEquipCacheNew() if (IsTestItem(itemId)) { continue; } + if (itemId == 22784) { // Sunwell Orb + continue; + } equipCacheNew[proto->RequiredLevel][proto->InventoryType].push_back(itemId); } } diff --git a/src/strategy/actions/XpGainAction.cpp b/src/strategy/actions/XpGainAction.cpp index fbf313cb..a82eacff 100644 --- a/src/strategy/actions/XpGainAction.cpp +++ b/src/strategy/actions/XpGainAction.cpp @@ -4,12 +4,18 @@ #include "XpGainAction.h" #include "Event.h" +#include "PlayerbotAIConfig.h" #include "Playerbots.h" bool XpGainAction::Execute(Event event) { context->GetValue("death count")->Set(0); + if (sPlayerbotAIConfig->randomBotFixedLevel) { + bot->SetUInt32Value(PLAYER_XP, 0); + return true; + } + if (!sRandomPlayerbotMgr->IsRandomBot(bot) || sPlayerbotAIConfig->playerbotsXPrate == 1) return true; From 0129788ea3bb6785644cfe894c8b436ab998c850 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Thu, 27 Jun 2024 23:31:36 +0800 Subject: [PATCH 10/18] [Configuration] Fixed level --- src/strategy/actions/XpGainAction.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/strategy/actions/XpGainAction.cpp b/src/strategy/actions/XpGainAction.cpp index a82eacff..c446780f 100644 --- a/src/strategy/actions/XpGainAction.cpp +++ b/src/strategy/actions/XpGainAction.cpp @@ -11,11 +11,11 @@ bool XpGainAction::Execute(Event event) { context->GetValue("death count")->Set(0); - if (sPlayerbotAIConfig->randomBotFixedLevel) { + if (sRandomPlayerbotMgr->IsRandomBot(bot) && sPlayerbotAIConfig->randomBotFixedLevel) { bot->SetUInt32Value(PLAYER_XP, 0); return true; } - + if (!sRandomPlayerbotMgr->IsRandomBot(bot) || sPlayerbotAIConfig->playerbotsXPrate == 1) return true; From 7395acb660760877e841a3078008779db19490c1 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Thu, 27 Jun 2024 23:39:54 +0800 Subject: [PATCH 11/18] [Configuration] Random bots fixed level --- src/PlayerbotMgr.cpp | 6 ++++++ src/strategy/actions/XpGainAction.cpp | 5 ----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/PlayerbotMgr.cpp b/src/PlayerbotMgr.cpp index 97659583..ea239ca5 100644 --- a/src/PlayerbotMgr.cpp +++ b/src/PlayerbotMgr.cpp @@ -448,6 +448,12 @@ void PlayerbotHolder::OnBotLogin(Player* const bot) uint32 accountId = bot->GetSession()->GetAccountId(); bool isRandomAccount = sPlayerbotAIConfig->IsInRandomAccountList(accountId); + if (isRandomAccount && sPlayerbotAIConfig->randomBotFixedLevel) { + bot->SetPlayerFlag(PLAYER_FLAGS_NO_XP_GAIN); + } else { + bot->RemovePlayerFlag(PLAYER_FLAGS_NO_XP_GAIN); + } + bot->SaveToDB(false, false); if (master && isRandomAccount && master->GetLevel() < bot->GetLevel()) { // PlayerbotFactory factory(bot, master->getLevel()); diff --git a/src/strategy/actions/XpGainAction.cpp b/src/strategy/actions/XpGainAction.cpp index c446780f..31322360 100644 --- a/src/strategy/actions/XpGainAction.cpp +++ b/src/strategy/actions/XpGainAction.cpp @@ -11,11 +11,6 @@ bool XpGainAction::Execute(Event event) { context->GetValue("death count")->Set(0); - if (sRandomPlayerbotMgr->IsRandomBot(bot) && sPlayerbotAIConfig->randomBotFixedLevel) { - bot->SetUInt32Value(PLAYER_XP, 0); - return true; - } - if (!sRandomPlayerbotMgr->IsRandomBot(bot) || sPlayerbotAIConfig->playerbotsXPrate == 1) return true; From 6abc8d51e972991874c01629dbeec1067d5fe100 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Fri, 28 Jun 2024 20:09:04 +0800 Subject: [PATCH 12/18] [Attack target] Valid target check --- src/strategy/values/AttackersValue.cpp | 21 ++++++--------------- src/strategy/values/InvalidTargetValue.cpp | 4 +--- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/src/strategy/values/AttackersValue.cpp b/src/strategy/values/AttackersValue.cpp index 41ff417e..7ae853be 100644 --- a/src/strategy/values/AttackersValue.cpp +++ b/src/strategy/values/AttackersValue.cpp @@ -104,7 +104,7 @@ void AttackersValue::RemoveNonThreating(std::unordered_set& targets) for(std::unordered_set::iterator tIter = targets.begin(); tIter != targets.end();) { Unit* unit = *tIter; - if(bot->GetMapId() != unit->GetMapId() || !hasRealThreat(unit) || !IsValidTarget(unit, bot) || !bot->IsWithinLOSInMap(unit)) + if(bot->GetMapId() != unit->GetMapId() || !hasRealThreat(unit) || !IsValidTarget(unit, bot)) { std::unordered_set::iterator tIter2 = tIter; ++tIter; @@ -113,15 +113,6 @@ void AttackersValue::RemoveNonThreating(std::unordered_set& targets) else ++tIter; } - // Unit* unit = *tIter; - // if (!IsValidTarget(unit, bot) || !bot->IsWithinLOSInMap(unit)) - // { - // std::unordered_set::iterator tIter2 = tIter; - // ++tIter; - // targets.erase(tIter2); - // } - // else - // ++tIter; } bool AttackersValue::hasRealThreat(Unit *attacker) @@ -160,7 +151,7 @@ bool AttackersValue::IsPossibleTarget(Unit* attacker, Player* bot, float range) // bool inCannon = botAI->IsInVehicle(false, true); // bool enemy = botAI->GetAiObjectContext()->GetValue("enemy player target")->Get(); - return attacker && + return attacker && attacker->IsVisible() && attacker->IsInWorld() && attacker->GetMapId() == bot->GetMapId() && !attacker->isDead() && @@ -183,10 +174,10 @@ bool AttackersValue::IsPossibleTarget(Unit* attacker, Player* bot, float range) bool AttackersValue::IsValidTarget(Unit *attacker, Player *bot) { - return attacker->IsVisible() && - IsPossibleTarget(attacker, bot) && - (attacker->GetThreatMgr().getCurrentVictim() || attacker->GetGuidValue(UNIT_FIELD_TARGET) || - attacker->GetGUID().IsPlayer() || attacker->GetGUID() == GET_PLAYERBOT_AI(bot)->GetAiObjectContext()->GetValue("pull target")->Get()); + return bot->IsWithinLOSInMap(attacker) && + IsPossibleTarget(attacker, bot); + // (attacker->GetThreatMgr().getCurrentVictim() || attacker->GetGuidValue(UNIT_FIELD_TARGET) || + // attacker->GetGUID().IsPlayer() || attacker->GetGUID() == GET_PLAYERBOT_AI(bot)->GetAiObjectContext()->GetValue("pull target")->Get()); } bool PossibleAddsValue::Calculate() diff --git a/src/strategy/values/InvalidTargetValue.cpp b/src/strategy/values/InvalidTargetValue.cpp index d2499c52..c940424a 100644 --- a/src/strategy/values/InvalidTargetValue.cpp +++ b/src/strategy/values/InvalidTargetValue.cpp @@ -27,9 +27,7 @@ bool InvalidTargetValue::Calculate() target->isFeared() || target->HasUnitState(UNIT_STATE_ISOLATED) || target->IsFriendlyTo(bot) || - !AttackersValue::IsValidTarget(target, bot) || - // !bot->IsWithinDistInMap(target, sPlayerbotAIConfig->sightDistance) || - !bot->IsWithinLOSInMap(target); + !AttackersValue::IsValidTarget(target, bot); } return !target; From 3556a38dcdd155473b468db2c7f840b0cd944517 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Fri, 28 Jun 2024 20:14:22 +0800 Subject: [PATCH 13/18] [Initialization] Ammo init --- src/PlayerbotFactory.cpp | 5 ++--- src/PlayerbotMgr.cpp | 2 +- src/RandomItemMgr.cpp | 10 ++++------ src/RandomPlayerbotMgr.cpp | 4 +--- 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/PlayerbotFactory.cpp b/src/PlayerbotFactory.cpp index 1512046d..10fc482b 100644 --- a/src/PlayerbotFactory.cpp +++ b/src/PlayerbotFactory.cpp @@ -2502,8 +2502,7 @@ void PlayerbotFactory::InitAmmo() case ITEM_SUBCLASS_WEAPON_CROSSBOW: subClass = ITEM_SUBCLASS_ARROW; break; - case ITEM_SUBCLASS_WEAPON_THROWN: - subClass = ITEM_SUBCLASS_THROWN; + default: break; } @@ -2516,7 +2515,7 @@ void PlayerbotFactory::InitAmmo() if (count < maxCount / 2) { - if (Item* newItem = StoreNewItemInInventorySlot(bot, entry, maxCount / 2)) { + if (Item* newItem = StoreNewItemInInventorySlot(bot, entry, maxCount)) { newItem->AddToUpdateQueueOf(bot); } } diff --git a/src/PlayerbotMgr.cpp b/src/PlayerbotMgr.cpp index ea239ca5..099350f2 100644 --- a/src/PlayerbotMgr.cpp +++ b/src/PlayerbotMgr.cpp @@ -450,7 +450,7 @@ void PlayerbotHolder::OnBotLogin(Player* const bot) if (isRandomAccount && sPlayerbotAIConfig->randomBotFixedLevel) { bot->SetPlayerFlag(PLAYER_FLAGS_NO_XP_GAIN); - } else { + } else if (isRandomAccount && !sPlayerbotAIConfig->randomBotFixedLevel) { bot->RemovePlayerFlag(PLAYER_FLAGS_NO_XP_GAIN); } diff --git a/src/RandomItemMgr.cpp b/src/RandomItemMgr.cpp index d909b4b0..e02b865b 100644 --- a/src/RandomItemMgr.cpp +++ b/src/RandomItemMgr.cpp @@ -2202,9 +2202,7 @@ RandomItemList RandomItemMgr::Query(uint32 level, uint8 clazz, uint8 slot, uint3 void RandomItemMgr::BuildAmmoCache() { - uint32 maxLevel = sPlayerbotAIConfig->randomBotMaxLevel; - if (maxLevel > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) - maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); + uint32 maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); LOG_INFO("server.loading", "Building ammo cache for {} levels", maxLevel); @@ -2241,9 +2239,9 @@ uint32 RandomItemMgr::GetAmmo(uint32 level, uint32 subClass) void RandomItemMgr::BuildPotionCache() { - uint32 maxLevel = sPlayerbotAIConfig->randomBotMaxLevel; - if (maxLevel > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) - maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); + uint32 maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); + // if (maxLevel > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) + // maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); LOG_INFO("server.loading", "Building potion cache for {} levels", maxLevel); diff --git a/src/RandomPlayerbotMgr.cpp b/src/RandomPlayerbotMgr.cpp index 4d6295b7..334b6499 100644 --- a/src/RandomPlayerbotMgr.cpp +++ b/src/RandomPlayerbotMgr.cpp @@ -1257,9 +1257,7 @@ void RandomPlayerbotMgr::RandomTeleport(Player* bot, std::vector& void RandomPlayerbotMgr::PrepareTeleportCache() { - uint8 maxLevel = sPlayerbotAIConfig->randomBotMaxLevel; - if (maxLevel > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL)) - maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); + uint32 maxLevel = sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL); LOG_INFO("playerbots", "Preparing random teleport caches for {} levels...", maxLevel); From 4661715fcae05ef22cfec78b884c111464797624 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Fri, 28 Jun 2024 20:16:29 +0800 Subject: [PATCH 14/18] [Optimization] Valid target check order --- src/strategy/values/AttackersValue.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/strategy/values/AttackersValue.cpp b/src/strategy/values/AttackersValue.cpp index 7ae853be..527b8def 100644 --- a/src/strategy/values/AttackersValue.cpp +++ b/src/strategy/values/AttackersValue.cpp @@ -174,8 +174,7 @@ bool AttackersValue::IsPossibleTarget(Unit* attacker, Player* bot, float range) bool AttackersValue::IsValidTarget(Unit *attacker, Player *bot) { - return bot->IsWithinLOSInMap(attacker) && - IsPossibleTarget(attacker, bot); + return IsPossibleTarget(attacker, bot) && bot->IsWithinLOSInMap(attacker); // (attacker->GetThreatMgr().getCurrentVictim() || attacker->GetGuidValue(UNIT_FIELD_TARGET) || // attacker->GetGUID().IsPlayer() || attacker->GetGUID() == GET_PLAYERBOT_AI(bot)->GetAiObjectContext()->GetValue("pull target")->Get()); } From b9b4362bdd90cd52adf5364ec50872ad8c152ae2 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Fri, 28 Jun 2024 20:26:41 +0800 Subject: [PATCH 15/18] [Initialization] Ammo amount --- src/PlayerbotFactory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PlayerbotFactory.cpp b/src/PlayerbotFactory.cpp index 10fc482b..69efb9f6 100644 --- a/src/PlayerbotFactory.cpp +++ b/src/PlayerbotFactory.cpp @@ -2515,7 +2515,7 @@ void PlayerbotFactory::InitAmmo() if (count < maxCount / 2) { - if (Item* newItem = StoreNewItemInInventorySlot(bot, entry, maxCount)) { + if (Item* newItem = StoreNewItemInInventorySlot(bot, entry, maxCount / 2)) { newItem->AddToUpdateQueueOf(bot); } } From 55515f0ec579462b5704cea78f7e599a395f3605 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Sat, 29 Jun 2024 21:57:28 +0800 Subject: [PATCH 16/18] [Avoid aoe] Position selection --- src/PlayerbotFactory.cpp | 14 ++++-- src/strategy/actions/ChatShortcutActions.cpp | 1 + src/strategy/actions/MovementActions.cpp | 49 +++++++++++-------- src/strategy/actions/MovementActions.h | 4 ++ .../actions/UseMeetingStoneAction.cpp | 4 +- 5 files changed, 45 insertions(+), 27 deletions(-) diff --git a/src/PlayerbotFactory.cpp b/src/PlayerbotFactory.cpp index 69efb9f6..ec9d5729 100644 --- a/src/PlayerbotFactory.cpp +++ b/src/PlayerbotFactory.cpp @@ -2511,7 +2511,7 @@ void PlayerbotFactory::InitAmmo() uint32 entry = sRandomItemMgr->GetAmmo(level, subClass); uint32 count = bot->GetItemCount(entry); - uint32 maxCount = 5000; + uint32 maxCount = 6000; if (count < maxCount / 2) { @@ -3878,10 +3878,9 @@ float PlayerbotFactory::CalculateItemScore(uint32 item_id, Player* bot) score *= 0.1; } // spec with double hand - // fury with titan's grip, fury without duel wield, arms, bear, retribution, blood dk - if (isDoubleHand && - ((cls == CLASS_WARRIOR && tab == WARRIOR_TAB_FURY && bot->CanTitanGrip()) || - (cls == CLASS_WARRIOR && tab == WARRIOR_TAB_FURY && !bot->CanDualWield()) || + // fury without duel wield, arms, bear, retribution, blood dk + if (isDoubleHand && + ((cls == CLASS_WARRIOR && tab == WARRIOR_TAB_FURY && !bot->CanDualWield()) || (cls == CLASS_WARRIOR && tab == WARRIOR_TAB_ARMS) || (cls == CLASS_DRUID && tab == 1) || (cls == CLASS_PALADIN && tab == 2) || @@ -3889,6 +3888,11 @@ float PlayerbotFactory::CalculateItemScore(uint32 item_id, Player* bot) (cls == CLASS_SHAMAN && tab == 1 && !bot->CanDualWield()))) { score *= 10; } + // fury with titan's grip + if (isDoubleHand && proto->SubClass != ITEM_SUBCLASS_WEAPON_POLEARM && + (cls == CLASS_WARRIOR && tab == WARRIOR_TAB_FURY && bot->CanTitanGrip())) { + score *= 0.1; + } } if (proto->Class == ITEM_CLASS_WEAPON) { if (cls == CLASS_HUNTER && proto->SubClass == ITEM_SUBCLASS_WEAPON_THROWN) { diff --git a/src/strategy/actions/ChatShortcutActions.cpp b/src/strategy/actions/ChatShortcutActions.cpp index 92e259fd..be1c4496 100644 --- a/src/strategy/actions/ChatShortcutActions.cpp +++ b/src/strategy/actions/ChatShortcutActions.cpp @@ -33,6 +33,7 @@ bool FollowChatShortcutAction::Execute(Event event) botAI->Reset(); botAI->ChangeStrategy("+follow,-passive,-grind", BOT_STATE_NON_COMBAT); botAI->ChangeStrategy("-follow,-passive,-grind", BOT_STATE_COMBAT); + botAI->GetAiObjectContext()->GetValue("prioritized targets")->Set({}); PositionMap& posMap = context->GetValue("position")->Get(); PositionInfo pos = posMap["return"]; diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index 67cb4902..5c9afbb4 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -1648,32 +1648,37 @@ bool AvoidAoeAction::AvoidUnitWithDamageAura() Position AvoidAoeAction::BestPositionForMelee(Position pos, float radius) { Unit* currentTarget = AI_VALUE(Unit*, "current target"); - std::vector possibleAngles; + std::vector possibleAngles; if (currentTarget) { // Normally, move to left or right is the best position bool isTanking = (currentTarget->CanFreeMove()) && (currentTarget->GetVictim() == bot); float angle = bot->GetAngle(currentTarget); float angleLeft = angle + M_PI / 2; float angleRight = angle - M_PI / 2; - possibleAngles.push_back(angleLeft); - possibleAngles.push_back(angleRight); + possibleAngles.push_back({angleLeft, false}); + possibleAngles.push_back({angleRight, false}); + possibleAngles.push_back({angle, true}); if (isTanking) { - possibleAngles.push_back(angle + M_PI); - possibleAngles.push_back(angle); - possibleAngles.push_back(bot->GetAngle(&pos) - M_PI); + possibleAngles.push_back({angle + M_PI, false}); + possibleAngles.push_back({bot->GetAngle(&pos) - M_PI, false}); } } else { float angleTo = bot->GetAngle(&pos) - M_PI; - possibleAngles.push_back(angleTo); + possibleAngles.push_back({angleTo, false}); } float farestDis = 0.0f; Position bestPos; - for (float &angle : possibleAngles) { + for (CheckAngle &checkAngle : possibleAngles) { + float angle = checkAngle.angle; + bool strict = checkAngle.strict; float fleeDis = sPlayerbotAIConfig->fleeDistance; Position fleePos{bot->GetPositionX() + cos(angle) * fleeDis, bot->GetPositionY() + sin(angle) * fleeDis, bot->GetPositionZ()}; - // todo (Yunfan): check carefully + if (strict && currentTarget + && fleePos.GetExactDist(currentTarget) - currentTarget->GetCombatReach() > sPlayerbotAIConfig->tooCloseDistance) { + continue; + } if (pos.GetExactDist(fleePos) > farestDis) { farestDis = pos.GetExactDist(fleePos); bestPos = fleePos; @@ -1688,7 +1693,7 @@ Position AvoidAoeAction::BestPositionForMelee(Position pos, float radius) Position AvoidAoeAction::BestPositionForRanged(Position pos, float radius) { Unit* currentTarget = AI_VALUE(Unit*, "current target"); - std::vector possibleAngles; + std::vector possibleAngles; float angleToTarget = 0.0f; float angleFleeFromCenter = bot->GetAngle(&pos) - M_PI; if (currentTarget) { @@ -1696,27 +1701,29 @@ Position AvoidAoeAction::BestPositionForRanged(Position pos, float radius) angleToTarget = bot->GetAngle(currentTarget); float angleLeft = angleToTarget + M_PI / 2; float angleRight = angleToTarget - M_PI / 2; - possibleAngles.push_back(angleLeft); - possibleAngles.push_back(angleRight); - possibleAngles.push_back(angleToTarget + M_PI); - possibleAngles.push_back(angleToTarget); - possibleAngles.push_back(angleFleeFromCenter); + possibleAngles.push_back({angleLeft, false}); + possibleAngles.push_back({angleRight, false}); + possibleAngles.push_back({angleToTarget + M_PI, true}); + possibleAngles.push_back({angleToTarget, true}); + possibleAngles.push_back({angleFleeFromCenter, true}); } else { - possibleAngles.push_back(angleFleeFromCenter); + possibleAngles.push_back({angleFleeFromCenter, false}); } float farestDis = 0.0f; Position bestPos; - for (float &angle : possibleAngles) { + for (CheckAngle &checkAngle : possibleAngles) { + float angle = checkAngle.angle; + bool strict = checkAngle.strict; float fleeDis = sPlayerbotAIConfig->fleeDistance; Position fleePos{bot->GetPositionX() + cos(angle) * fleeDis, bot->GetPositionY() + sin(angle) * fleeDis, bot->GetPositionZ()}; - if (currentTarget // && (angle == angleToTarget + M_PI || angle == angleFleeFromCenter) - && fleePos.GetExactDist(currentTarget) > sPlayerbotAIConfig->spellDistance) { + if (strict && currentTarget + && fleePos.GetExactDist(currentTarget) - currentTarget->GetCombatReach() > sPlayerbotAIConfig->spellDistance) { continue; } - if (currentTarget // && (angle == angleToTarget || angle == angleFleeFromCenter) - && fleePos.GetExactDist(currentTarget) < (sPlayerbotAIConfig->tooCloseDistance + 5.0f)) { + if (strict && currentTarget + && fleePos.GetExactDist(currentTarget) - currentTarget->GetCombatReach() < (sPlayerbotAIConfig->tooCloseDistance)) { continue; } if (pos.GetExactDist(fleePos) > farestDis) { diff --git a/src/strategy/actions/MovementActions.h b/src/strategy/actions/MovementActions.h index 3cfdc685..f26991a4 100644 --- a/src/strategy/actions/MovementActions.h +++ b/src/strategy/actions/MovementActions.h @@ -82,6 +82,10 @@ class AvoidAoeAction : public MovementAction Position BestPositionForRanged(Position pos, float radius); bool FleePosition(Position pos, float radius, std::string name); time_t lastTellTimer = 0; + struct CheckAngle { + float angle; + bool strict; + }; }; class RunAwayAction : public MovementAction diff --git a/src/strategy/actions/UseMeetingStoneAction.cpp b/src/strategy/actions/UseMeetingStoneAction.cpp index 422fc3e9..3ef46e21 100644 --- a/src/strategy/actions/UseMeetingStoneAction.cpp +++ b/src/strategy/actions/UseMeetingStoneAction.cpp @@ -81,8 +81,10 @@ bool SummonAction::Execute(Event event) pet->GetCharmInfo()->IsReturning(); } - if (master->GetSession()->GetSecurity() >= SEC_PLAYER) + if (master->GetSession()->GetSecurity() >= SEC_PLAYER) { + botAI->GetAiObjectContext()->GetValue("prioritized targets")->Set({}); return Teleport(master, bot); + } if (SummonUsingGos(master, bot) || SummonUsingNpcs(master, bot)) { From ca9981bfbed1f999757136243fd6bb5c5a51ccd7 Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Sat, 29 Jun 2024 22:30:53 +0800 Subject: [PATCH 17/18] [Initialization] Titan's grip for fury warrior --- src/PlayerbotFactory.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/PlayerbotFactory.cpp b/src/PlayerbotFactory.cpp index ec9d5729..d4cf2b7d 100644 --- a/src/PlayerbotFactory.cpp +++ b/src/PlayerbotFactory.cpp @@ -3891,7 +3891,7 @@ float PlayerbotFactory::CalculateItemScore(uint32 item_id, Player* bot) // fury with titan's grip if (isDoubleHand && proto->SubClass != ITEM_SUBCLASS_WEAPON_POLEARM && (cls == CLASS_WARRIOR && tab == WARRIOR_TAB_FURY && bot->CanTitanGrip())) { - score *= 0.1; + score *= 10; } } if (proto->Class == ITEM_CLASS_WEAPON) { From 3008087833e8122455c3c3a9d6d16feb3d458e1f Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Sun, 30 Jun 2024 00:03:49 +0800 Subject: [PATCH 18/18] [Warnings] Fix double to float --- src/strategy/actions/MovementActions.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index 5c9afbb4..f2652168 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -1653,17 +1653,17 @@ Position AvoidAoeAction::BestPositionForMelee(Position pos, float radius) // Normally, move to left or right is the best position bool isTanking = (currentTarget->CanFreeMove()) && (currentTarget->GetVictim() == bot); float angle = bot->GetAngle(currentTarget); - float angleLeft = angle + M_PI / 2; - float angleRight = angle - M_PI / 2; + float angleLeft = angle + (float)M_PI / 2; + float angleRight = angle - (float)M_PI / 2; possibleAngles.push_back({angleLeft, false}); possibleAngles.push_back({angleRight, false}); possibleAngles.push_back({angle, true}); if (isTanking) { - possibleAngles.push_back({angle + M_PI, false}); - possibleAngles.push_back({bot->GetAngle(&pos) - M_PI, false}); + possibleAngles.push_back({angle + (float)M_PI, false}); + possibleAngles.push_back({bot->GetAngle(&pos) - (float)M_PI, false}); } } else { - float angleTo = bot->GetAngle(&pos) - M_PI; + float angleTo = bot->GetAngle(&pos) - (float)M_PI; possibleAngles.push_back({angleTo, false}); } float farestDis = 0.0f; @@ -1695,15 +1695,15 @@ Position AvoidAoeAction::BestPositionForRanged(Position pos, float radius) Unit* currentTarget = AI_VALUE(Unit*, "current target"); std::vector possibleAngles; float angleToTarget = 0.0f; - float angleFleeFromCenter = bot->GetAngle(&pos) - M_PI; + float angleFleeFromCenter = bot->GetAngle(&pos) - (float)M_PI; if (currentTarget) { // Normally, move to left or right is the best position angleToTarget = bot->GetAngle(currentTarget); - float angleLeft = angleToTarget + M_PI / 2; - float angleRight = angleToTarget - M_PI / 2; + float angleLeft = angleToTarget + (float)M_PI / 2; + float angleRight = angleToTarget - (float)M_PI / 2; possibleAngles.push_back({angleLeft, false}); possibleAngles.push_back({angleRight, false}); - possibleAngles.push_back({angleToTarget + M_PI, true}); + possibleAngles.push_back({angleToTarget + (float)M_PI, true}); possibleAngles.push_back({angleToTarget, true}); possibleAngles.push_back({angleFleeFromCenter, true}); } else {