Merge pull request #512 from liyunfan1223/avoid_aoe_whitelist

Avoid aoe whitelist
This commit is contained in:
Yunfan Li
2024-09-08 17:06:24 +08:00
committed by GitHub
13 changed files with 139 additions and 97 deletions

View File

@@ -357,7 +357,7 @@ AiPlayerbot.HighMana = 65
#
#
# Bots pick their quest reward (yes = picks first useful item, no = list all rewards, ask = pick useful item and lists if multiple)
# Bots pick their quest reward (yes = picks the most useful item, no = list all rewards, ask = pick useful item and lists if multiple)
AiPlayerbot.AutoPickReward = yes
# Sync quests with player (Bots will complete quests the moment you hand them in. Bots will ignore looting quest items.)
@@ -385,9 +385,11 @@ AiPlayerbot.ApplyInstanceStrategies = 1
# Default: 1 (enable)
AiPlayerbot.AutoAvoidAoe = 1
# Tell which spell is avoiding (experimental)
# Default: 1 (enable)
AiPlayerbot.TellWhenAvoidAoe = 1
# Only avoid aoe spells with a radius smaller than this value
AiPlayerbot.MaxAoeAvoidRadius = 15.0
# A whitelist of aoe spell IDs that should not be avoided
AiPlayerbot.AoeAvoidSpellWhitelist = 50759,57491,13810
# Enable healer bot save mana
# Default: 1 (enable)
@@ -1281,6 +1283,10 @@ AiPlayerbot.LogInGroupOnly = 1
AiPlayerbot.LogValuesPerTick = 0
AiPlayerbot.RandomChangeMultiplier = 1
# Tell which spell is avoiding (experimental)
# Default: 0 (disable)
AiPlayerbot.TellWhenAvoidAoe = 0
# Enables/Disables performance monitor
AiPlayerbot.PerfMonEnabled = 0

View File

@@ -1624,10 +1624,10 @@ void PlayerbotAI::ResetStrategies(bool load)
// sPlayerbotDbStore->Load(this);
}
bool PlayerbotAI::IsRanged(Player* player)
bool PlayerbotAI::IsRanged(Player* player, bool bySpec)
{
PlayerbotAI* botAi = GET_PLAYERBOT_AI(player);
if (botAi)
if (!bySpec && botAi)
return botAi->ContainsStrategy(STRATEGY_TYPE_RANGED);
int tab = AiFactory::GetPlayerSpecTab(player);
@@ -1660,18 +1660,18 @@ bool PlayerbotAI::IsRanged(Player* player)
return true;
}
bool PlayerbotAI::IsMelee(Player* player) { return !IsRanged(player); }
bool PlayerbotAI::IsMelee(Player* player, bool bySpec) { return !IsRanged(player, bySpec); }
bool PlayerbotAI::IsCaster(Player* player) { return IsRanged(player) && player->getClass() != CLASS_HUNTER; }
bool PlayerbotAI::IsCaster(Player* player, bool bySpec) { return IsRanged(player, bySpec) && player->getClass() != CLASS_HUNTER; }
bool PlayerbotAI::IsCombo(Player* player)
bool PlayerbotAI::IsCombo(Player* player, bool bySpec)
{
// int tab = AiFactory::GetPlayerSpecTab(player);
return player->getClass() == CLASS_ROGUE ||
(player->getClass() == CLASS_DRUID && player->HasAura(768)); // cat druid
}
bool PlayerbotAI::IsRangedDps(Player* player) { return IsRanged(player) && IsDps(player); }
bool PlayerbotAI::IsRangedDps(Player* player, bool bySpec) { return IsRanged(player, bySpec) && IsDps(player, bySpec); }
bool PlayerbotAI::IsHealAssistantOfIndex(Player* player, int index)
{
@@ -1894,10 +1894,10 @@ int32 PlayerbotAI::GetMeleeIndex(Player* player)
return 0;
}
bool PlayerbotAI::IsTank(Player* player)
bool PlayerbotAI::IsTank(Player* player, bool bySpec)
{
PlayerbotAI* botAi = GET_PLAYERBOT_AI(player);
if (botAi)
if (!bySpec && botAi)
return botAi->ContainsStrategy(STRATEGY_TYPE_TANK);
int tab = AiFactory::GetPlayerSpecTab(player);
@@ -1932,10 +1932,10 @@ bool PlayerbotAI::IsTank(Player* player)
return false;
}
bool PlayerbotAI::IsHeal(Player* player)
bool PlayerbotAI::IsHeal(Player* player, bool bySpec)
{
PlayerbotAI* botAi = GET_PLAYERBOT_AI(player);
if (botAi)
if (!bySpec && botAi)
return botAi->ContainsStrategy(STRATEGY_TYPE_HEAL);
int tab = AiFactory::GetPlayerSpecTab(player);
@@ -1969,10 +1969,10 @@ bool PlayerbotAI::IsHeal(Player* player)
return false;
}
bool PlayerbotAI::IsDps(Player* player)
bool PlayerbotAI::IsDps(Player* player, bool bySpec)
{
PlayerbotAI* botAi = GET_PLAYERBOT_AI(player);
if (botAi)
if (!bySpec && botAi)
return botAi->ContainsStrategy(STRATEGY_TYPE_DPS);
int tab = AiFactory::GetPlayerSpecTab(player);

View File

@@ -401,14 +401,14 @@ public:
void ResetStrategies(bool load = false);
void ReInitCurrentEngine();
void Reset(bool full = false);
static bool IsTank(Player* player);
static bool IsHeal(Player* player);
static bool IsDps(Player* player);
static bool IsRanged(Player* player);
static bool IsMelee(Player* player);
static bool IsCaster(Player* player);
static bool IsCombo(Player* player);
static bool IsRangedDps(Player* player);
static bool IsTank(Player* player, bool bySpec = false);
static bool IsHeal(Player* player, bool bySpec = false);
static bool IsDps(Player* player, bool bySpec = false);
static bool IsRanged(Player* player, bool bySpec = false);
static bool IsMelee(Player* player, bool bySpec = false);
static bool IsCaster(Player* player, bool bySpec = false);
static bool IsCombo(Player* player, bool bySpec = false);
static bool IsRangedDps(Player* player, bool bySpec = false);
static bool IsMainTank(Player* player);
bool IsAssistTank(Player* player);
bool IsAssistTankOfIndex(Player* player, int index);

View File

@@ -29,6 +29,19 @@ void LoadList(std::string const value, T& list)
}
}
template <class T>
void LoadSet(std::string const value, T& set)
{
std::vector<std::string> ids = split(value, ',');
for (std::vector<std::string>::iterator i = ids.begin(); i != ids.end(); i++)
{
uint32 id = atoi((*i).c_str());
// if (!id)
// continue;
set.insert(id);
}
}
template <class T>
void LoadListString(std::string const value, T& list)
{
@@ -98,7 +111,10 @@ bool PlayerbotAIConfig::Initialize()
autoSaveMana = sConfigMgr->GetOption<bool>("AiPlayerbot.AutoSaveMana", true);
saveManaThreshold = sConfigMgr->GetOption<int32>("AiPlayerbot.SaveManaThreshold", 60);
autoAvoidAoe = sConfigMgr->GetOption<bool>("AiPlayerbot.AutoAvoidAoe", true);
tellWhenAvoidAoe = sConfigMgr->GetOption<bool>("AiPlayerbot.TellWhenAvoidAoe", true);
maxAoeAvoidRadius = sConfigMgr->GetOption<float>("AiPlayerbot.MaxAoeAvoidRadius", 15.0f);
LoadSet<std::set<uint32>>(sConfigMgr->GetOption<std::string>("AiPlayerbot.AoeAvoidSpellWhitelist", "50759,57491,13810"),
aoeAvoidSpellWhitelist);
tellWhenAvoidAoe = sConfigMgr->GetOption<bool>("AiPlayerbot.TellWhenAvoidAoe", false);
randomGearLoweringChance = sConfigMgr->GetOption<float>("AiPlayerbot.RandomGearLoweringChance", 0.0f);
randomGearQualityLimit = sConfigMgr->GetOption<int32>("AiPlayerbot.RandomGearQualityLimit", 3);
@@ -792,9 +808,10 @@ std::vector<std::vector<uint32>> PlayerbotAIConfig::ParseTempPetTalentsOrder(uin
if (!((1 << spec) & talentTabInfo->petTalentMask))
continue;
// skip some duplicate spells like dash/dive
if (talentInfo->TalentID == 2201 || talentInfo->TalentID == 2208 || talentInfo->TalentID == 2219 || talentInfo->TalentID == 2203)
if (talentInfo->TalentID == 2201 || talentInfo->TalentID == 2208 || talentInfo->TalentID == 2219 ||
talentInfo->TalentID == 2203)
continue;
spells.push_back(talentInfo);
}
std::sort(spells.begin(), spells.end(),

View File

@@ -67,6 +67,8 @@ public:
bool autoSaveMana;
uint32 saveManaThreshold;
bool autoAvoidAoe;
float maxAoeAvoidRadius;
std::set<uint32> aoeAvoidSpellWhitelist;
bool tellWhenAvoidAoe;
uint32 openGoSpell;

View File

@@ -769,49 +769,61 @@ bool RandomItemMgr::CanEquipWeapon(uint8 clazz, ItemTemplate const* proto)
{
case CLASS_PRIEST:
if (proto->SubClass != ITEM_SUBCLASS_WEAPON_STAFF && proto->SubClass != ITEM_SUBCLASS_WEAPON_WAND &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE)
proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE && proto->SubClass != ITEM_SUBCLASS_WEAPON_DAGGER)
return false;
break;
case CLASS_MAGE:
case CLASS_WARLOCK:
if (proto->SubClass != ITEM_SUBCLASS_WEAPON_STAFF && proto->SubClass != ITEM_SUBCLASS_WEAPON_WAND &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_SWORD)
proto->SubClass != ITEM_SUBCLASS_WEAPON_DAGGER && proto->SubClass != ITEM_SUBCLASS_WEAPON_SWORD)
return false;
break;
case CLASS_WARRIOR:
if (proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE2 && proto->SubClass != ITEM_SUBCLASS_WEAPON_SWORD2 &&
if (proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE2 && proto->SubClass != ITEM_SUBCLASS_WEAPON_AXE &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_POLEARM && proto->SubClass != ITEM_SUBCLASS_WEAPON_SWORD2 &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE && proto->SubClass != ITEM_SUBCLASS_WEAPON_SWORD &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_GUN && proto->SubClass != ITEM_SUBCLASS_WEAPON_CROSSBOW &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_BOW && proto->SubClass != ITEM_SUBCLASS_WEAPON_AXE &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_AXE2 && proto->SubClass != ITEM_SUBCLASS_WEAPON_THROWN)
proto->SubClass != ITEM_SUBCLASS_WEAPON_BOW && proto->SubClass != ITEM_SUBCLASS_WEAPON_THROWN &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_AXE2 && proto->SubClass != ITEM_SUBCLASS_WEAPON_FIST &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_DAGGER && proto->SubClass != ITEM_SUBCLASS_WEAPON_STAFF)
return false;
break;
case CLASS_PALADIN:
if (proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE2 && proto->SubClass != ITEM_SUBCLASS_WEAPON_SWORD2 &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE && proto->SubClass != ITEM_SUBCLASS_WEAPON_SWORD)
case CLASS_DEATH_KNIGHT:
if (proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE2 && proto->SubClass != ITEM_SUBCLASS_WEAPON_POLEARM &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_SWORD2 && proto->SubClass != ITEM_SUBCLASS_WEAPON_AXE2 &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_AXE && proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_SWORD)
return false;
break;
case CLASS_SHAMAN:
if (proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE && proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE2 &&
if (proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE && proto->SubClass != ITEM_SUBCLASS_WEAPON_AXE &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_FIST && proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE2 &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_AXE2 && proto->SubClass != ITEM_SUBCLASS_WEAPON_DAGGER &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_STAFF)
return false;
break;
case CLASS_DRUID:
if (proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE && proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE2 &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_DAGGER && proto->SubClass != ITEM_SUBCLASS_WEAPON_STAFF)
proto->SubClass != ITEM_SUBCLASS_WEAPON_DAGGER && proto->SubClass != ITEM_SUBCLASS_WEAPON_STAFF &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_POLEARM)
return false;
break;
case CLASS_HUNTER:
if (proto->SubClass != ITEM_SUBCLASS_WEAPON_AXE2 && proto->SubClass != ITEM_SUBCLASS_WEAPON_SWORD2 &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_GUN && proto->SubClass != ITEM_SUBCLASS_WEAPON_CROSSBOW &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_BOW)
if (proto->SubClass != ITEM_SUBCLASS_WEAPON_DAGGER && proto->SubClass != ITEM_SUBCLASS_WEAPON_BOW &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_AXE2 && proto->SubClass != ITEM_SUBCLASS_WEAPON_AXE &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_SWORD2 && proto->SubClass != ITEM_SUBCLASS_WEAPON_SWORD &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_FIST && proto->SubClass != ITEM_SUBCLASS_WEAPON_GUN &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_CROSSBOW && proto->SubClass != ITEM_SUBCLASS_WEAPON_STAFF &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_POLEARM)
return false;
break;
case CLASS_ROGUE:
if (proto->SubClass != ITEM_SUBCLASS_WEAPON_DAGGER && proto->SubClass != ITEM_SUBCLASS_WEAPON_SWORD &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE && proto->SubClass != ITEM_SUBCLASS_WEAPON_GUN &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_CROSSBOW && proto->SubClass != ITEM_SUBCLASS_WEAPON_BOW &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_THROWN)
proto->SubClass != ITEM_SUBCLASS_WEAPON_FIST && proto->SubClass != ITEM_SUBCLASS_WEAPON_MACE &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_GUN && proto->SubClass != ITEM_SUBCLASS_WEAPON_CROSSBOW &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_BOW && proto->SubClass != ITEM_SUBCLASS_WEAPON_THROWN &&
proto->SubClass != ITEM_SUBCLASS_WEAPON_AXE)
return false;
break;
}

View File

@@ -1867,6 +1867,7 @@ void RandomPlayerbotMgr::GetBots()
PlayerbotsDatabase.GetPreparedStatement(PLAYERBOTS_SEL_RANDOM_BOTS_BY_OWNER_AND_EVENT);
stmt->SetData(0, 0);
stmt->SetData(1, "add");
uint32 maxAllowedBotCount = GetEventValue(0, "bot_count");
if (PreparedQueryResult result = PlayerbotsDatabase.Query(stmt))
{
do
@@ -1875,6 +1876,9 @@ void RandomPlayerbotMgr::GetBots()
uint32 bot = fields[0].Get<uint32>();
if (GetEventValue(bot, "add"))
currentBots.push_back(bot);
if (currentBots.size() >= maxAllowedBotCount)
break;
} while (result->NextRow());
}
}
@@ -2402,53 +2406,14 @@ void RandomPlayerbotMgr::PrintStats()
++engine_combat;
else
++engine_dead;
uint8 spec = AiFactory::GetPlayerSpecTab(bot);
switch (bot->getClass())
{
case CLASS_DRUID:
if (spec == 2)
++heal;
else
++dps;
break;
case CLASS_PALADIN:
if (spec == 1)
++tank;
else if (spec == 0)
++heal;
else
++dps;
break;
case CLASS_PRIEST:
if (spec != 2)
++heal;
else
++dps;
break;
case CLASS_SHAMAN:
if (spec == 2)
++heal;
else
++dps;
break;
case CLASS_WARRIOR:
if (spec == 2)
++tank;
else
++dps;
break;
case CLASS_DEATH_KNIGHT:
if (spec == 0)
tank++;
else
dps++;
break;
default:
++dps;
break;
}
if (botAI->IsHeal(bot, true))
++heal;
else if (botAI->IsTank(bot, true))
++tank;
else
++dps;
if (TravelTarget* target = botAI->GetAiObjectContext()->GetValue<TravelTarget*>("travel target")->Get())
{
TravelState state = target->getTravelState();

View File

@@ -94,7 +94,7 @@ private:
{
return new ActionNode("mana potion",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("drink"), nullptr),
/*A*/ nullptr,
/*C*/ nullptr);
}

View File

@@ -1819,12 +1819,17 @@ bool AvoidAoeAction::AvoidAuraWithDynamicObj()
{
return false;
}
if (sPlayerbotAIConfig->aoeAvoidSpellWhitelist.find(spellInfo->Id) != sPlayerbotAIConfig->aoeAvoidSpellWhitelist.end())
return false;
DynamicObject* dynOwner = aura->GetDynobjOwner();
if (!dynOwner || !dynOwner->IsInWorld())
{
return false;
}
float radius = dynOwner->GetRadius();
if (!radius || radius > sPlayerbotAIConfig->maxAoeAvoidRadius)
return false;
if (bot->GetDistance(dynOwner) > radius)
{
return false;
@@ -1838,7 +1843,7 @@ bool AvoidAoeAction::AvoidAuraWithDynamicObj()
lastTellTimer = time(NULL);
lastMoveTimer = getMSTime();
std::ostringstream out;
out << "I'm avoiding " << name.str() << "...";
out << "I'm avoiding " << name.str() << " (" << spellInfo->Id << ")" << " Radius " << radius << " - [Aura]";
bot->Say(out.str(), LANG_UNIVERSAL);
}
return true;
@@ -1869,17 +1874,28 @@ bool AvoidAoeAction::AvoidGameObjectWithDamage()
{
continue;
}
// 0 trap with no despawn after cast. 1 trap despawns after cast. 2 bomb casts on spawn.
if (goInfo->trap.type != 0)
continue;
uint32 spellId = goInfo->trap.spellId;
if (!spellId)
{
continue;
}
if (sPlayerbotAIConfig->aoeAvoidSpellWhitelist.find(spellId) != sPlayerbotAIConfig->aoeAvoidSpellWhitelist.end())
continue;
const SpellInfo* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!spellInfo || spellInfo->IsPositive())
{
continue;
}
float radius = (float)goInfo->trap.diameter / 2;
if (!radius || radius > sPlayerbotAIConfig->maxAoeAvoidRadius)
continue;
// for (int i = 0; i < MAX_SPELL_EFFECTS; i++) {
// if (spellInfo->Effects[i].Effect == SPELL_EFFECT_APPLY_AURA) {
// if (spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_PERIODIC_DAMAGE) {
@@ -1903,7 +1919,7 @@ bool AvoidAoeAction::AvoidGameObjectWithDamage()
lastTellTimer = time(NULL);
lastMoveTimer = getMSTime();
std::ostringstream out;
out << "I'm avoiding " << name.str() << "...";
out << "I'm avoiding " << name.str() << " (" << spellInfo->Id << ")" << " Radius " << radius << " - [Trap]";
bot->Say(out.str(), LANG_UNIVERSAL);
}
return true;
@@ -1946,6 +1962,8 @@ bool AvoidAoeAction::AvoidUnitWithDamageAura()
sSpellMgr->GetSpellInfo(spellInfo->Effects[aurEff->GetEffIndex()].TriggerSpell);
if (!triggerSpellInfo)
continue;
if (sPlayerbotAIConfig->aoeAvoidSpellWhitelist.find(triggerSpellInfo->Id) != sPlayerbotAIConfig->aoeAvoidSpellWhitelist.end())
return false;
for (int j = 0; j < MAX_SPELL_EFFECTS; j++)
{
if (triggerSpellInfo->Effects[j].Effect == SPELL_EFFECT_SCHOOL_DAMAGE)
@@ -1955,6 +1973,8 @@ bool AvoidAoeAction::AvoidUnitWithDamageAura()
{
break;
}
if (!radius || radius > sPlayerbotAIConfig->maxAoeAvoidRadius)
continue;
std::ostringstream name;
name << triggerSpellInfo->SpellName[LOCALE_enUS]; //<< "] (unit)";
if (FleePosition(unit->GetPosition(), radius))
@@ -1964,7 +1984,7 @@ bool AvoidAoeAction::AvoidUnitWithDamageAura()
lastTellTimer = time(NULL);
lastMoveTimer = getMSTime();
std::ostringstream out;
out << "I'm avoiding " << name.str() << "...";
out << "I'm avoiding " << name.str() << " (" << triggerSpellInfo->Id << ")" << " Radius " << radius << " - [Unit Trigger]";
bot->Say(out.str(), LANG_UNIVERSAL);
}
}

View File

@@ -11,6 +11,7 @@
#include "Object.h"
#include "Playerbots.h"
#include "QuestDef.h"
#include "StatsWeightCalculator.h"
#include "WorldPacket.h"
#include "BroadcastHelper.h"
@@ -176,8 +177,20 @@ void TalkToQuestGiverAction::RewardMultipleItem(Quest const* quest, Object* ques
bestIds = BestRewards(quest);
if (!bestIds.empty())
{
ItemTemplate const* item = sObjectMgr->GetItemTemplate(quest->RewardChoiceItemId[*bestIds.begin()]);
bot->RewardQuest(quest, *bestIds.begin(), questGiver, true);
StatsWeightCalculator calc(bot);
uint32 best = 0;
float bestScore = 0;
for (uint32 id : bestIds)
{
float score = calc.CalculateItem(quest->RewardChoiceItemId[id]);
if (score > bestScore)
{
bestScore = score;
best = id;
}
}
ItemTemplate const* item = sObjectMgr->GetItemTemplate(quest->RewardChoiceItemId[best]);
bot->RewardQuest(quest, best, questGiver, true);
out << "Rewarded " << ChatHelper::FormatItem(item);
}
else

View File

@@ -64,6 +64,7 @@ public:
this->prev_phase = 0;
this->prev_erupt = 0;
this->prev_timer = 0;
ResetSafe();
waypoints.push_back(std::make_pair(2793.58f, -3665.93f));
waypoints.push_back(std::make_pair(2775.49f, -3674.43f));
waypoints.push_back(std::make_pair(2762.30f, -3684.59f));

View File

@@ -145,6 +145,9 @@ Aura* AreaDebuffValue::Calculate()
{
continue;
}
// float radius = dynOwner->GetRadius();
// if (radius > 12.0f)
// continue;
return aura;
}
}

View File

@@ -65,7 +65,10 @@ void ArmsWarriorStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
"victory rush", NextAction::array(0, new NextAction("victory rush", ACTION_INTERRUPT), nullptr)));
triggers.push_back(new TriggerNode(
"high rage available", NextAction::array(0, new NextAction("heroic strike", ACTION_HIGH + 10), nullptr)));
triggers.push_back(new TriggerNode("medium rage available", NextAction::array(0, new NextAction("slam", ACTION_HIGH + 1), nullptr)));
triggers.push_back(new TriggerNode("medium rage available",
NextAction::array(0, new NextAction("slam", ACTION_HIGH + 1),
new NextAction("thunder clap", ACTION_HIGH),
nullptr)));
triggers.push_back(
new TriggerNode("bloodrage", NextAction::array(0, new NextAction("bloodrage", ACTION_HIGH + 2), nullptr)));
triggers.push_back(
@@ -76,5 +79,5 @@ void ArmsWarriorStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
triggers.push_back(new TriggerNode(
"critical health", NextAction::array(0, new NextAction("intimidating shout", ACTION_EMERGENCY), nullptr)));
triggers.push_back(new TriggerNode("medium aoe",
NextAction::array(0, new NextAction("thunder clap", ACTION_HIGH + 1), nullptr)));
NextAction::array(0, new NextAction("thunder clap", ACTION_HIGH + 2), nullptr)));
}