Auto avoid aoe config

This commit is contained in:
Yunfan Li
2024-04-14 13:03:18 +08:00
parent df1b280b14
commit 0499e5da46
10 changed files with 76 additions and 9 deletions

View File

@@ -322,6 +322,9 @@ AiPlayerbot.AutoSaveMana = 1
# Default: 60 (60%)
AiPlayerbot.SaveManaThreshold = 60
# Enable auto avoid aoe (experimental)
# Default: 0 (disable)
AiPlayerbot.AutoAvoidAoe = 0
# Random bot default strategies (applied after defaults)
AiPlayerbot.RandomBotCombatStrategies = "+dps,+dps assist,-threat"

View File

@@ -266,9 +266,14 @@ void AiFactory::AddDefaultCombatStrategies(Player* player, PlayerbotAI* const fa
{
engine->addStrategies("racials", "chat", "default", "cast time", "duel", "boost", nullptr);
}
if (sPlayerbotAIConfig->autoSaveMana) {
if (sPlayerbotAIConfig->autoSaveMana)
{
engine->addStrategy("auto save mana");
}
if (sPlayerbotAIConfig->autoAvoidAoe && facade->HasRealPlayerMaster())
{
engine->addStrategy("avoid aoe");
}
switch (player->getClass())
{
case CLASS_PRIEST:

View File

@@ -91,6 +91,7 @@ bool PlayerbotAIConfig::Initialize()
mediumMana = sConfigMgr->GetOption<int32>("AiPlayerbot.MediumMana", 40);
autoSaveMana = sConfigMgr->GetOption<bool>("AiPlayerbot.AutoSaveMana", true);
saveManaThreshold = sConfigMgr->GetOption<int32>("AiPlayerbot.SaveManaThreshold", 60);
autoAvoidAoe = sConfigMgr->GetOption<bool>("AiPlayerbot.AutoAvoidAoe", false);
randomGearLoweringChance = sConfigMgr->GetOption<float>("AiPlayerbot.RandomGearLoweringChance", 0.15f);
randomBotMaxLevelChance = sConfigMgr->GetOption<float>("AiPlayerbot.RandomBotMaxLevelChance", 0.15f);

View File

@@ -64,6 +64,7 @@ class PlayerbotAIConfig
uint32 lowMana, mediumMana;
bool autoSaveMana;
uint32 saveManaThreshold;
bool autoAvoidAoe;
uint32 openGoSpell;
bool randomBotAutologin;

View File

@@ -1492,6 +1492,16 @@ bool AvoidAoeAction::isUseful()
bool AvoidAoeAction::Execute(Event event)
{
// Case #1: Aura with dynamic object
if (AvoidAuraWithDynamicObj()) {
return true;
}
// Case #2: Trap game object with spell
// Case #3: Trigger npc
return false;
}
bool AvoidAoeAction::AvoidAuraWithDynamicObj()
{
Aura* aura = AI_VALUE(Aura*, "area debuff");
if (!aura) {
return false;
@@ -1523,8 +1533,6 @@ bool AvoidAoeAction::Execute(Event event)
}
float farestDis = 0.0f;
Position bestPos;
// float disToDyn = bot->GetExactDist(dynOwner);
// float maxDisToGo = radius > disToDyn ? std::sqrt(radius * radius - disToDyn * disToDyn) + 0.5f : 0.5f;
for (float &angle : possibleAngles) {
float fleeDis = sPlayerbotAIConfig->fleeDistance;
Position pos{bot->GetPositionX() + cos(angle) * fleeDis,
@@ -1537,10 +1545,12 @@ bool AvoidAoeAction::Execute(Event event)
}
}
if (farestDis > 0.0f) {
if (MoveTo(bot->GetMapId(), bestPos.GetPositionX(), bestPos.GetPositionY(), bestPos.GetPositionZ(), false, false, true)) {
std::ostringstream out;
out << "I'm avoiding aoe spell [" << aura->GetSpellInfo()->SpellName[0] << "]...";
bot->Say(out.str(), LANG_UNIVERSAL);
return MoveTo(bot->GetMapId(), bestPos.GetPositionX(), bestPos.GetPositionY(), bestPos.GetPositionZ(), false, false, true);
return true;
}
}
return false;
}

View File

@@ -73,6 +73,9 @@ class AvoidAoeAction : public MovementAction
bool isUseful() override;
bool Execute(Event event) override;
protected:
bool AvoidAuraWithDynamicObj();
};
class RunAwayAction : public MovementAction

View File

@@ -5,6 +5,7 @@
#ifndef _PLAYERBOT_AOEVALUES_H
#define _PLAYERBOT_AOEVALUES_H
#include "GameObject.h"
#include "Object.h"
#include "Value.h"
#include "AiObjectContext.h"

View File

@@ -7,6 +7,7 @@
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "Playerbots.h"
#include "SharedDefines.h"
class AnyGameObjectInObjectRangeCheck
{
@@ -42,3 +43,30 @@ GuidVector NearestGameObjects::Calculate()
return result;
}
GuidVector NearestTrapWithDamageValue::Calculate()
{
std::list<GameObject*> targets;
AnyGameObjectInObjectRangeCheck u_check(bot, range);
Acore::GameObjectListSearcher<AnyGameObjectInObjectRangeCheck> searcher(bot, targets, u_check);
Cell::VisitAllObjects(bot, searcher, range);
GuidVector result;
for (GameObject* go : targets)
{
if (go->GetGoType() != GAMEOBJECT_TYPE_TRAP)
{
continue;
}
uint32 spellId = go->GetSpellId();
if (!spellId)
{
continue;
}
// if (ignoreLos || bot->IsWithinLOSInMap(go))
result.push_back(go->GetGUID());
}
return result;
}

View File

@@ -24,4 +24,17 @@ class NearestGameObjects : public ObjectGuidListCalculatedValue
bool ignoreLos;
};
class NearestTrapWithDamageValue : public ObjectGuidListCalculatedValue
{
public:
NearestTrapWithDamageValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig->sightDistance) :
ObjectGuidListCalculatedValue(botAI, "nearest trap with damage", 1 * 1000), range(range) { }
protected:
GuidVector Calculate() override;
private:
float range;
};
#endif

View File

@@ -299,6 +299,7 @@ class ValueContext : public NamedObjectContext<UntypedValue>
creators["expected lifetime"] = &ValueContext::expected_lifetime;
creators["expected group dps"] = &ValueContext::expected_group_dps;
creators["area debuff"] = &ValueContext::area_debuff;
creators["nearest trap with damage"] = &ValueContext::nearest_trap_with_damange;
}
private:
@@ -501,6 +502,7 @@ class ValueContext : public NamedObjectContext<UntypedValue>
static UntypedValue* expected_lifetime(PlayerbotAI* ai) { return new ExpectedLifetimeValue(ai); }
static UntypedValue* expected_group_dps(PlayerbotAI* ai) { return new ExpectedGroupDpsValue(ai); }
static UntypedValue* area_debuff(PlayerbotAI* ai) { return new AreaDebuffValue(ai); }
static UntypedValue* nearest_trap_with_damange(PlayerbotAI* ai) { return new NearestTrapWithDamageValue(ai); }
};
#endif