fix(spell): paladin and dk aggro spell, warrior

This commit is contained in:
Yunfan Li
2023-06-11 15:55:36 +08:00
parent b11fad1a46
commit 33576bd969
21 changed files with 117 additions and 62 deletions

View File

@@ -1387,7 +1387,7 @@ bool PlayerbotAI::IsMainTank(Player* player)
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) {
Player* member = ref->GetSource();
if (IsTank(member)) {
return player == member;
return player->GetGUID() == member->GetGUID();
}
}
return false;
@@ -1882,7 +1882,7 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell,
}
}
ObjectGuid oldSel = bot->GetTarget();
ObjectGuid oldSel = bot->GetSelectedUnit()->GetGUID();
Spell* spell = new Spell(bot, spellInfo, TRIGGERED_NONE);
spell->m_targets.SetUnitTarget(target);
@@ -1901,7 +1901,7 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell,
}
if (oldSel)
bot->SetTarget(oldSel);
bot->SetSelection(oldSel);
switch (result)
{

View File

@@ -137,10 +137,16 @@ CastEnchantItemAction::CastEnchantItemAction(PlayerbotAI* botAI, std::string con
bool CastEnchantItemAction::isPossible()
{
if (!CastSpellAction::isPossible())
if (!CastSpellAction::isPossible()) {
botAI->TellMasterNoFacing("Impossible: " + spell);
return false;
}
uint32 spellId = AI_VALUE2(uint32, "spell id", spell);
bool ok = AI_VALUE2(Item*, "item for spell", spellId);
botAI->TellMasterNoFacing("spell: " + spell + ", spell id: " + std::to_string(spellId) + " item for spell: " + std::to_string(ok));
return spellId && AI_VALUE2(Item*, "item for spell", spellId);
}

View File

@@ -116,7 +116,7 @@ bool HeiganDanceAction::CalculateSafe() {
uint32 curr_erupt = eventMap->GetNextEventTime(3);
uint32 curr_dance = eventMap->GetNextEventTime(4);
uint32 curr_timer = eventMap->GetTimer();
if ((curr_phase == 0 && curr_dance - curr_timer >= 80000) || (curr_phase == 1 && curr_dance - curr_timer >= 40000)) {
if ((curr_phase == 0 && curr_dance - curr_timer >= 85000) || (curr_phase == 1 && curr_dance - curr_timer >= 40000)) {
ResetSafe();
} else if (curr_erupt != prev_erupt) {
NextSafe();
@@ -131,6 +131,7 @@ bool HeiganDanceMeleeAction::Execute(Event event) {
if (prev_phase == 0 && botAI->IsMainTank(bot) && !AI_VALUE2(bool, "has aggro", "boss target")) {
return false;
}
assert(curr_safe >= 0 && curr_safe <= 3);
return MoveInside(bot->GetMapId(), waypoints[curr_safe].first, waypoints[curr_safe].second, bot->GetPositionZ(), botAI->IsMainTank(bot) ? 0 : 0);
}

View File

@@ -75,8 +75,8 @@ NextAction** BloodDKStrategy::getDefaultActions()
{
return NextAction::array(0,
new NextAction("rune strike", ACTION_NORMAL + 7),
new NextAction("heart strike", ACTION_NORMAL + 6),
new NextAction("icy touch", ACTION_NORMAL + 5),
new NextAction("icy touch", ACTION_NORMAL + 6),
new NextAction("heart strike", ACTION_NORMAL + 5),
new NextAction("death coil", ACTION_NORMAL + 4),
new NextAction("plague strike", ACTION_NORMAL + 3),
new NextAction("blood strike", ACTION_NORMAL + 2),

View File

@@ -36,10 +36,10 @@ class CastDeathchillAction : public CastBuffSpellAction
NextAction** getPrerequisites() override;
};
class CastDarkCommandAction : public CastBuffSpellAction
class CastDarkCommandAction : public CastSpellAction
{
public:
CastDarkCommandAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "dark command") { }
CastDarkCommandAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "dark command") { }
NextAction** getPrerequisites() override;
};

View File

@@ -165,16 +165,16 @@ void GenericDKStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
triggers.push_back(new TriggerNode("bone shield", NextAction::array(0, new NextAction("bone shield", ACTION_NORMAL + 1), nullptr)));
triggers.push_back(new TriggerNode("horn of winter", NextAction::array(0, new NextAction("horn of winter", ACTION_NORMAL + 1), nullptr)));
triggers.push_back(new TriggerNode("mind freeze on enemy healer", NextAction::array(0, new NextAction("mind freeze on enemy healer", ACTION_HIGH + 1), nullptr)));
triggers.push_back(new TriggerNode("enemy out of melee", NextAction::array(0, new NextAction("reach melee", ACTION_NORMAL + 8), nullptr)));
// triggers.push_back(new TriggerNode("enemy out of melee", NextAction::array(0, new NextAction("reach melee", ACTION_NORMAL + 8), nullptr)));
triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("icebound fortitude", ACTION_HIGH + 5), new NextAction("rune tap", ACTION_HIGH + 4), nullptr)));
triggers.push_back(new TriggerNode("medium health", NextAction::array(0, new NextAction("rune tap", ACTION_NORMAL + 4), new NextAction("death strike", ACTION_NORMAL + 3), nullptr)));
triggers.push_back(new TriggerNode("icy touch", NextAction::array(0, new NextAction("icy touch", ACTION_HIGH + 1), nullptr)));
// triggers.push_back(new TriggerNode("icy touch on attacker", NextAction::array(0, new NextAction("icy touch on attacker", ACTION_HIGH + 1), nullptr)));
triggers.push_back(new TriggerNode("plague strike", NextAction::array(0, new NextAction("plague strike", ACTION_HIGH + 1), nullptr)));
// triggers.push_back(new TriggerNode("plague strike on attacker", NextAction::array(0, new NextAction("plague strike on attacker", ACTION_HIGH + 1), nullptr)));
triggers.push_back(new TriggerNode("high aoe", NextAction::array(0, new NextAction("unholy blight", ACTION_NORMAL + 6), new NextAction("death and decay", ACTION_NORMAL + 5),
triggers.push_back(new TriggerNode("high aoe", NextAction::array(0, new NextAction("unholy blight", ACTION_HIGH + 6), new NextAction("death and decay", ACTION_NORMAL + 5),
new NextAction("pestilence", ACTION_NORMAL + 4), new NextAction("blood boil", ACTION_NORMAL + 3), nullptr)));
triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("death and decay", ACTION_NORMAL + 5),
triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("death and decay", ACTION_HIGH + 9),
new NextAction("pestilence", ACTION_NORMAL + 4), new NextAction("blood boil", ACTION_NORMAL + 3), nullptr)));
triggers.push_back(new TriggerNode("light aoe", NextAction::array(0, new NextAction("howling blast", ACTION_NORMAL + 5), new NextAction("pestilence", ACTION_NORMAL + 4),
new NextAction("hearth strike", ACTION_NORMAL + 3), new NextAction("blood boil", ACTION_NORMAL + 3), nullptr)));

View File

@@ -77,7 +77,8 @@ class BearTankDruidStrategyActionNodeFactory : public NamedObjectFactory<ActionN
{
return new ActionNode ("mangle (bear)",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("lacerate"), nullptr),
// /*A*/ NextAction::array(0, new NextAction("lacerate"), nullptr),
nullptr,
/*C*/ nullptr);
}
@@ -138,10 +139,10 @@ BearTankDruidStrategy::BearTankDruidStrategy(PlayerbotAI* botAI) : FeralDruidStr
NextAction** BearTankDruidStrategy::getDefaultActions()
{
return NextAction::array(0,
new NextAction("lacerate", ACTION_NORMAL + 4),
new NextAction("mangle (bear)", ACTION_NORMAL + 3),
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("faerie fire (feral)", ACTION_NORMAL + 1),
new NextAction("melee", ACTION_NORMAL),
nullptr);
}

View File

@@ -17,10 +17,10 @@ class CastFaerieFireAction : public CastDebuffSpellAction
CastFaerieFireAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "faerie fire") { }
};
class CastFaerieFireFeralAction : public CastDebuffSpellAction
class CastFaerieFireFeralAction : public CastSpellAction
{
public:
CastFaerieFireFeralAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "faerie fire (feral)") { }
CastFaerieFireFeralAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "faerie fire (feral)") { }
};
class CastRejuvenationAction : public CastHealingSpellAction

View File

@@ -41,6 +41,6 @@ bool CastCasterFormAction::Execute(Event event)
}
bool CastTreeFormAction::isUseful() {
return GetTarget() && (GetTarget() != nullptr) && (GetTarget() != nullptr) &&
return GetTarget() &&
CastSpellAction::isUseful() && !botAI->HasAura(33891, bot);
}

View File

@@ -101,8 +101,6 @@ void FeralDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
triggers.push_back(new TriggerNode("enemy too close for melee", NextAction::array(0, new NextAction("move out of enemy contact", ACTION_NORMAL + 8), nullptr)));
triggers.push_back(new TriggerNode("critical health", NextAction::array(0, new NextAction("survival instincts", ACTION_EMERGENCY + 1), nullptr)));
triggers.push_back(new TriggerNode("omen of clarity", NextAction::array(0, new NextAction("omen of clarity", ACTION_HIGH + 9), nullptr)));
//triggers.push_back(new TriggerNode("player has no flag", NextAction::array(0, new NextAction("prowl", ACTION_HIGH + 1), nullptr)));
//triggers.push_back(new TriggerNode("enemy out of melee", NextAction::array(0, new NextAction("prowl", ACTION_INTERRUPT + 1), nullptr)));
triggers.push_back(new TriggerNode("player has flag", NextAction::array(0, new NextAction("dash", ACTION_EMERGENCY + 2), nullptr)));
triggers.push_back(new TriggerNode("enemy flagcarrier near", NextAction::array(0, new NextAction("dash", ACTION_EMERGENCY + 2), nullptr)));
}

View File

@@ -173,7 +173,7 @@ class GenericPaladinStrategyActionNodeFactory : public NamedObjectFactory<Action
}
static ActionNode* avengers_shield(PlayerbotAI* ai)
{
return new ActionNode ("righteous defense",
return new ActionNode ("avenger's shield",
/*P*/ NULL,
/*A*/ NextAction::array(0, new NextAction("judgement of wisdom"), NULL),
/*C*/ NULL);

View File

@@ -53,12 +53,12 @@ void TankPaladinStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
// triggers.push_back(new TriggerNode("medium mana", NextAction::array(0, new NextAction("judgement of wisdom", ACTION_HIGH + 6), nullptr)));
// triggers.push_back(new TriggerNode("judgement", NextAction::array(0, new NextAction("judgement", ACTION_HIGH + 6), nullptr)));
// triggers.push_back(new TriggerNode("judgement", NextAction::array(0, new NextAction("exorcism", ACTION_HIGH + 6), nullptr)));
// triggers.push_back(new TriggerNode("light aoe", NextAction::array(0, new NextAction("hammer of the righteous", ACTION_HIGH + 8), new NextAction("avenger's shield", ACTION_HIGH + 7), nullptr)));
triggers.push_back(new TriggerNode("light aoe", NextAction::array(0, new NextAction("hammer of the righteous", ACTION_HIGH + 8), new NextAction("avenger's shield", ACTION_HIGH + 7), nullptr)));
triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("consecration", ACTION_HIGH + 1), new NextAction("avenger's shield", ACTION_HIGH + 3), NULL)));
triggers.push_back(new TriggerNode("avenger's shield", NextAction::array(0, new NextAction("avenger's shield", ACTION_HIGH + 7), nullptr)));
// triggers.push_back(new TriggerNode("avenger's shield", NextAction::array(0, new NextAction("avenger's shield", ACTION_HIGH + 7), nullptr)));
triggers.push_back(new TriggerNode("lose aggro", NextAction::array(0, new NextAction("hand of reckoning", ACTION_HIGH + 7), nullptr)));
triggers.push_back(new TriggerNode("holy shield", NextAction::array(0, new NextAction("holy shield", ACTION_HIGH + 7), nullptr)));
triggers.push_back(new TriggerNode("blessing", NextAction::array(0, new NextAction("blessing of sanctuary", ACTION_HIGH + 9), nullptr)));
// triggers.push_back(new TriggerNode("blessing", NextAction::array(0, new NextAction("blessing of sanctuary", ACTION_HIGH + 9), nullptr)));
triggers.push_back(new TriggerNode("target critical health", NextAction::array(0, new NextAction("hammer of wrath", ACTION_CRITICAL_HEAL), nullptr)));
triggers.push_back(new TriggerNode(
"righteous fury",

View File

@@ -113,13 +113,17 @@ void DpsRogueStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
"light aoe",
NextAction::array(0, new NextAction("blade flurry", ACTION_HIGH + 3), NULL)));
triggers.push_back(new TriggerNode(
"enemy out of melee",
NextAction::array(0, new NextAction("stealth", ACTION_NORMAL + 9), new NextAction("reach melee", ACTION_NORMAL + 8), NULL)));
// triggers.push_back(new TriggerNode(
// "enemy out of melee",
// NextAction::array(0, new NextAction("stealth", ACTION_NORMAL + 9), new NextAction("reach melee", ACTION_NORMAL + 8), NULL)));
triggers.push_back(new TriggerNode(
"expose armor",
NextAction::array(0, new NextAction("expose armor", ACTION_HIGH + 3), NULL)));
triggers.push_back(new TriggerNode(
"tricks of the trade on main tank",
NextAction::array(0, new NextAction("tricks of the trade on main tank", ACTION_HIGH + 7), NULL)));
}
class StealthedRogueStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>

View File

@@ -60,6 +60,14 @@ bool ComboPointsAvailableTrigger::IsActive()
bool LoseAggroTrigger::IsActive()
{
Unit* mt = AI_VALUE(Unit*, "main tank");
if (mt) {
botAI->TellMasterNoFacing("Has aggro: " + std::to_string(AI_VALUE2(bool, "has aggro", "current target"))
+ " My main tank is: " + mt->GetName());
} else {
botAI->TellMasterNoFacing("Has aggro: " + std::to_string(AI_VALUE2(bool, "has aggro", "current target"))
+ " No main tank detected");
}
return !AI_VALUE2(bool, "has aggro", "current target");
}

View File

@@ -16,28 +16,42 @@ bool HasAggroValue::Calculate()
if (!target)
return true;
HostileReference *ref = bot->getHostileRefMgr().getFirst();
if (!ref)
return true; // simulate as target is not atacking anybody yet
Unit* victim = target->GetVictim();
while( ref )
{
ThreatMgr *threatManager = ref->GetSource();
Unit *attacker = threatManager->GetOwner();
if (attacker != target) {
ref = ref->next();
continue;
}
Unit *victim = attacker->GetVictim();
if (!victim) {
return true;
}
if ((victim == bot || (victim && victim->ToPlayer() && botAI->IsMainTank(victim->ToPlayer()))) && target == attacker)
return true;
ref = ref->next();
if (!victim) {
return true;
}
if (victim->GetGUID() == bot->GetGUID() || (victim->ToPlayer() && botAI->IsMainTank(victim->ToPlayer()))) {
return true;
}
botAI->TellMaster("target: " + target->GetName() + " victim: " + victim->GetName());
if (victim->ToPlayer() ) {
botAI->TellMaster("victim is mt: " + std::to_string(botAI->IsMainTank(victim->ToPlayer())));
}
return false;
// HostileReference *ref = bot->getHostileRefMgr().getFirst();
// if (!ref)
// return true; // simulate as target is not atacking anybody yet
// while( ref )
// {
// ThreatMgr *threatManager = ref->GetSource();
// Unit *attacker = threatManager->GetOwner();
// if (attacker->GetGUID() != target->GetGUID()) {
// ref = ref->next();
// continue;
// }
// Unit *victim = attacker->GetVictim();
// if (!victim) {
// return true;
// }
// if ((victim->GetGUID() == bot->GetGUID() || (victim && victim->ToPlayer() && botAI->IsMainTank(victim->ToPlayer()))) &&
// target->GetGUID() == attacker->GetGUID())
// return true;
// ref = ref->next();
// }
// Unit* target = GetTarget();
// if (!target)
// return true;

View File

@@ -33,16 +33,13 @@ Unit* PartyMemberValue::FindPartyMember(FindPlayerPredicate& predicate, bool ign
{
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
{
if (ref->GetSource() != bot)
if (ref->getSubGroup() != bot->GetSubGroup())
{
if (ref->getSubGroup() != bot->GetSubGroup())
{
nearestGroupPlayers.push_back(ref->GetSource()->GetGUID());
}
else
{
nearestGroupPlayers.push_front(ref->GetSource()->GetGUID());
}
nearestGroupPlayers.push_back(ref->GetSource()->GetGUID());
}
else
{
nearestGroupPlayers.push_front(ref->GetSource()->GetGUID());
}
}
} else {
@@ -69,7 +66,7 @@ Unit* PartyMemberValue::FindPartyMember(FindPlayerPredicate& predicate, bool ign
for (ObjectGuid const guid : nearestPlayers)
{
Player* player = botAI->GetPlayer(guid);
if (!player || player == bot)
if (!player)
continue;
if (botAI->IsHeal(player))
@@ -115,7 +112,7 @@ bool PartyMemberValue::IsTargetOfSpellCast(Player* target, SpellEntryPredicate &
for (ObjectGuid const guid : nearestPlayers)
{
Player* player = botAI->GetPlayer(guid);
if (!player || player == bot)
if (!player)
continue;
if (player->IsNonMeleeSpellCast(true))

View File

@@ -34,7 +34,14 @@ FuryWarriorStrategy::FuryWarriorStrategy(PlayerbotAI* botAI) : GenericWarriorStr
NextAction** FuryWarriorStrategy::getDefaultActions()
{
return NextAction::array(0, new NextAction("melee", ACTION_NORMAL), nullptr);
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),
NULL);
}
void FuryWarriorStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
@@ -53,10 +60,16 @@ void FuryWarriorStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
triggers.push_back(new TriggerNode("intercept on snare target", NextAction::array(0, new NextAction("intercept on snare target", ACTION_HIGH), nullptr)));
triggers.push_back(new TriggerNode("bloodthirst", NextAction::array(0, new NextAction("bloodthirst", ACTION_HIGH + 2), nullptr)));
triggers.push_back(new TriggerNode("instant slam", NextAction::array(0, new NextAction("slam", ACTION_HIGH + 1), nullptr)));
triggers.push_back(new TriggerNode("medium 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("heroic strike", ACTION_HIGH + 10), nullptr)));
triggers.push_back(new TriggerNode("berserker rage", NextAction::array(0, new NextAction("berserker rage", ACTION_HIGH + 2), nullptr)));
triggers.push_back(new TriggerNode("bloodrage", NextAction::array(0, new NextAction("bloodrage", ACTION_HIGH + 2), nullptr)));
triggers.push_back(new TriggerNode("death wish", NextAction::array(0, new NextAction("death wish", ACTION_HIGH + 2), nullptr)));
triggers.push_back(new TriggerNode("rampage", NextAction::array(0, new NextAction("rampage", ACTION_INTERRUPT + 1), nullptr)));
triggers.push_back(new TriggerNode("critical health", NextAction::array(0, new NextAction("intimidating shout", ACTION_EMERGENCY), nullptr)));
// triggers.push_back(new TriggerNode("critical health", NextAction::array(0, new NextAction("intimidating shout", ACTION_EMERGENCY), nullptr)));
// triggers.push_back(new TriggerNode(
// "slam",
// NextAction::array(0, new NextAction("slam", ACTION_HIGH + 2), NULL)));
triggers.push_back(new TriggerNode(
"high rage available",
NextAction::array(0, new NextAction("heroic strike", ACTION_HIGH + 1), NULL)));
}

View File

@@ -41,7 +41,11 @@ TankWarriorStrategy::TankWarriorStrategy(PlayerbotAI* botAI) : GenericWarriorStr
NextAction** TankWarriorStrategy::getDefaultActions()
{
return NextAction::array(0, new NextAction("melee", ACTION_NORMAL), nullptr);
return NextAction::array(0,
new NextAction("devastate", ACTION_NORMAL + 2),
new NextAction("revenge", ACTION_NORMAL + 1),
new NextAction("melee", ACTION_NORMAL),
NULL);
}
void TankWarriorStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)

View File

@@ -7,5 +7,6 @@
bool CastSunderArmorAction::isUseful()
{
return CastSpellAction::isUseful();
Aura *aura = botAI->GetAura("sunder armor", GetTarget(), false, true);
return !aura || aura->GetStackAmount() < 5 || aura->GetDuration() <= 3000;
}

View File

@@ -94,6 +94,7 @@ class WarriorTriggerFactoryInternal : public NamedObjectContext<Trigger>
creators["intercept can cast"] = &WarriorTriggerFactoryInternal::intercept_can_cast;
creators["intercept and far enemy"] = &WarriorTriggerFactoryInternal::intercept_and_far_enemy;
creators["intercept and rage"] = &WarriorTriggerFactoryInternal::intercept_and_rage;
// creators["slam"] = &WarriorTriggerFactoryInternal::slam;
}
private:
@@ -142,6 +143,7 @@ class WarriorTriggerFactoryInternal : public NamedObjectContext<Trigger>
static Trigger* overpower(PlayerbotAI* botAI) { return new OverpowerAvailableTrigger(botAI); }
static Trigger* revenge(PlayerbotAI* botAI) { return new RevengeAvailableTrigger(botAI); }
static Trigger* sunder_armor(PlayerbotAI* botAI) { return new SunderArmorDebuffTrigger(botAI); }
// static Trigger* slam(PlayerbotAI* ai) { return new SlamTrigger(ai); }
};

View File

@@ -52,4 +52,10 @@ class RendDebuffTrigger : public DebuffTrigger
public:
RendDebuffTrigger(PlayerbotAI* botAI) : DebuffTrigger(botAI, "rend", 1, true) { }
};
// class SlamTrigger : public HasAuraTrigger
// {
// public:
// SlamTrigger(PlayerbotAI* ai) : HasAuraTrigger(ai, "slam!") {}
// };
#endif