Merge branch 'liyunfan1223:master' into arms_warrior_tweak

This commit is contained in:
avirar
2024-12-30 10:37:12 +11:00
committed by GitHub
10 changed files with 208 additions and 12 deletions

View File

@@ -12,8 +12,8 @@ class WotlkDungeonOccActionContext : public NamedObjectContext<Action>
creators["avoid unstable sphere"] = &WotlkDungeonOccActionContext::avoid_unstable_sphere;
creators["mount drake"] = &WotlkDungeonOccActionContext::mount_drake;
creators["dismount drake"] = &WotlkDungeonOccActionContext::dismount_drake;
creators["fly drake"] = &WotlkDungeonOccActionContext::fly_drake;
creators["drake attack"] = &WotlkDungeonOccActionContext::drake_attack;
creators["occ fly drake"] = &WotlkDungeonOccActionContext::occ_fly_drake;
creators["occ drake attack"] = &WotlkDungeonOccActionContext::occ_drake_attack;
creators["avoid arcane explosion"] = &WotlkDungeonOccActionContext::avoid_arcane_explosion;
creators["time bomb spread"] = &WotlkDungeonOccActionContext::time_bomb_spread;
}
@@ -21,8 +21,8 @@ class WotlkDungeonOccActionContext : public NamedObjectContext<Action>
static Action* avoid_unstable_sphere(PlayerbotAI* ai) { return new AvoidUnstableSphereAction(ai); }
static Action* mount_drake(PlayerbotAI* ai) { return new MountDrakeAction(ai); }
static Action* dismount_drake(PlayerbotAI* ai) { return new DismountDrakeAction(ai); }
static Action* fly_drake(PlayerbotAI* ai) { return new OccFlyDrakeAction(ai); }
static Action* drake_attack(PlayerbotAI* ai) { return new OccDrakeAttackAction(ai); }
static Action* occ_fly_drake(PlayerbotAI* ai) { return new OccFlyDrakeAction(ai); }
static Action* occ_drake_attack(PlayerbotAI* ai) { return new OccDrakeAttackAction(ai); }
static Action* avoid_arcane_explosion(PlayerbotAI* ai) { return new AvoidArcaneExplosionAction(ai); }
static Action* time_bomb_spread(PlayerbotAI* ai) { return new TimeBombSpreadAction(ai); }
};

View File

@@ -15,9 +15,9 @@ void WotlkDungeonOccStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
triggers.push_back(new TriggerNode("drake dismount",
NextAction::array(0, new NextAction("dismount drake", ACTION_RAID + 5), nullptr)));
triggers.push_back(new TriggerNode("group flying",
NextAction::array(0, new NextAction("fly drake", ACTION_NORMAL + 1), nullptr)));
NextAction::array(0, new NextAction("occ fly drake", ACTION_NORMAL + 1), nullptr)));
triggers.push_back(new TriggerNode("drake combat",
NextAction::array(0, new NextAction("drake attack", ACTION_NORMAL + 5), nullptr)));
NextAction::array(0, new NextAction("occ drake attack", ACTION_NORMAL + 5), nullptr)));
// Varos Cloudstrider
// Seems to be no way to identify the marked cores, may need to hook boss AI..

View File

@@ -14,8 +14,8 @@ public:
creators["malygos target"] = &RaidEoEActionContext::target;
// creators["pull power spark"] = &RaidEoEActionContext::pull_power_spark;
// creators["kill power spark"] = &RaidEoEActionContext::kill_power_spark;
creators["fly drake"] = &RaidEoEActionContext::fly_drake;
creators["drake attack"] = &RaidEoEActionContext::drake_attack;
creators["eoe fly drake"] = &RaidEoEActionContext::eoe_fly_drake;
creators["eoe drake attack"] = &RaidEoEActionContext::eoe_drake_attack;
}
private:
@@ -23,8 +23,8 @@ private:
static Action* target(PlayerbotAI* ai) { return new MalygosTargetAction(ai); }
// static Action* pull_power_spark(PlayerbotAI* ai) { return new PullPowerSparkAction(ai); }
// static Action* kill_power_spark(PlayerbotAI* ai) { return new KillPowerSparkAction(ai); }
static Action* fly_drake(PlayerbotAI* ai) { return new EoEFlyDrakeAction(ai); }
static Action* drake_attack(PlayerbotAI* ai) { return new EoEDrakeAttackAction(ai); }
static Action* eoe_fly_drake(PlayerbotAI* ai) { return new EoEFlyDrakeAction(ai); }
static Action* eoe_drake_attack(PlayerbotAI* ai) { return new EoEDrakeAttackAction(ai); }
};
#endif

View File

@@ -14,9 +14,9 @@ void RaidEoEStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
// NextAction::array(0, new NextAction("kill power spark", ACTION_RAID + 3), nullptr)));
triggers.push_back(new TriggerNode("group flying",
NextAction::array(0, new NextAction("fly drake", ACTION_NORMAL + 1), nullptr)));
NextAction::array(0, new NextAction("eoe fly drake", ACTION_NORMAL + 1), nullptr)));
triggers.push_back(new TriggerNode("drake combat",
NextAction::array(0, new NextAction("drake attack", ACTION_NORMAL + 5), nullptr)));
NextAction::array(0, new NextAction("eoe drake attack", ACTION_NORMAL + 5), nullptr)));
}
void RaidEoEStrategy::InitMultipliers(std::vector<Multiplier*> &multipliers)

View File

@@ -22,6 +22,7 @@ public:
creators["heroic throw taunt"] = &heroic_throw_taunt;
creators["taunt"] = &taunt;
creators["taunt spell"] = &taunt;
creators["vigilance"] = &vigilance;
}
private:
@@ -41,6 +42,14 @@ private:
/*A*/ NextAction::array(0, new NextAction("heroic throw taunt"), nullptr),
/*C*/ nullptr);
}
static ActionNode* vigilance(PlayerbotAI* botAI)
{
return new ActionNode("vigilance",
/*P*/ nullptr,
/*A*/ nullptr,
/*C*/ nullptr);
}
};
TankWarriorStrategy::TankWarriorStrategy(PlayerbotAI* botAI) : GenericWarriorStrategy(botAI)
@@ -59,6 +68,9 @@ void TankWarriorStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
GenericWarriorStrategy::InitTriggers(triggers);
triggers.push_back(new TriggerNode(
"vigilance",
NextAction::array(0, new NextAction("vigilance", ACTION_HIGH + 7), nullptr)));
triggers.push_back(
new TriggerNode("enemy out of melee", NextAction::array(0, new NextAction("heroic throw", ACTION_MOVE + 11),
new NextAction("charge", ACTION_MOVE + 10), nullptr)));

View File

@@ -12,3 +12,92 @@ bool CastSunderArmorAction::isUseful()
Aura* aura = botAI->GetAura("sunder armor", GetTarget(), false, true);
return !aura || aura->GetStackAmount() < 5 || aura->GetDuration() <= 6000;
}
Value<Unit*>* CastVigilanceAction::GetTargetValue()
{
Group* group = bot->GetGroup();
if (!group)
{
return new ManualSetValue<Unit*>(botAI, nullptr);
}
Player* currentVigilanceTarget = nullptr;
Player* mainTank = nullptr;
Player* assistTank1 = nullptr;
Player* assistTank2 = nullptr;
Player* highestGearScorePlayer = nullptr;
uint32 highestGearScore = 0;
// Iterate once through the group to gather all necessary information
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
{
Player* member = ref->GetSource();
if (!member || member == bot || !member->IsAlive())
continue;
// Check if member has Vigilance applied by the bot
if (!currentVigilanceTarget && botAI->HasAura("vigilance", member, false, true))
{
currentVigilanceTarget = member;
}
// Identify Main Tank
if (!mainTank && botAI->IsMainTank(member))
{
mainTank = member;
}
// Identify Assist Tanks
if (assistTank1 == nullptr && botAI->IsAssistTankOfIndex(member, 0))
{
assistTank1 = member;
}
else if (assistTank2 == nullptr && botAI->IsAssistTankOfIndex(member, 1))
{
assistTank2 = member;
}
// Determine Highest Gear Score
uint32 gearScore = botAI->GetEquipGearScore(member, false, false);
if (gearScore > highestGearScore)
{
highestGearScore = gearScore;
highestGearScorePlayer = member;
}
}
// Determine the highest-priority target
Player* highestPriorityTarget = mainTank ? mainTank :
(assistTank1 ? assistTank1 :
(assistTank2 ? assistTank2 : highestGearScorePlayer));
// If no valid target, return nullptr
if (!highestPriorityTarget)
{
return new ManualSetValue<Unit*>(botAI, nullptr);
}
// If the current target is already the highest-priority target, do nothing
if (currentVigilanceTarget == highestPriorityTarget)
{
return new ManualSetValue<Unit*>(botAI, nullptr);
}
// Assign the new target
Unit* targetUnit = highestPriorityTarget->ToUnit();
if (targetUnit)
{
return new ManualSetValue<Unit*>(botAI, targetUnit);
}
return new ManualSetValue<Unit*>(botAI, nullptr);
}
bool CastVigilanceAction::Execute(Event event)
{
Unit* target = GetTarget();
if (!target || target == bot)
return false;
return botAI->CastSpell("vigilance", target);
}

View File

@@ -135,4 +135,13 @@ public:
bool isUseful() override;
};
class CastVigilanceAction : public BuffOnPartyAction
{
public:
CastVigilanceAction(PlayerbotAI* botAI) : BuffOnPartyAction(botAI, "vigilance") {}
Value<Unit*>* GetTargetValue() override;
bool Execute(Event event) override;
};
#endif

View File

@@ -99,6 +99,8 @@ public:
creators["intercept and far enemy"] = &WarriorTriggerFactoryInternal::intercept_and_far_enemy;
creators["intercept and rage"] = &WarriorTriggerFactoryInternal::intercept_and_rage;
// creators["slam"] = &WarriorTriggerFactoryInternal::slam;
creators["vigilance"] = &WarriorTriggerFactoryInternal::vigilance;
}
private:
@@ -168,6 +170,8 @@ private:
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); }
static Trigger* vigilance(PlayerbotAI* botAI) { return new VigilanceTrigger(botAI); }
};
class WarriorAiObjectContextInternal : public NamedObjectContext<Action>
@@ -237,6 +241,7 @@ public:
creators["heroic throw"] = &WarriorAiObjectContextInternal::heroic_throw;
creators["heroic throw on snare target"] = &WarriorAiObjectContextInternal::heroic_throw_on_snare_target;
creators["shattering throw"] = &WarriorAiObjectContextInternal::shattering_throw;
creators["vigilance"] = &WarriorAiObjectContextInternal::vigilance;
}
private:
@@ -306,6 +311,7 @@ private:
static Action* heroic_throw_on_snare_target(PlayerbotAI* botAI) { return new CastHeroicThrowSnareAction(botAI); }
static Action* heroic_throw(PlayerbotAI* botAI) { return new CastHeroicThrowAction(botAI); }
static Action* bladestorm(PlayerbotAI* botAI) { return new CastBladestormAction(botAI); }
static Action* vigilance(PlayerbotAI* botAI) { return new CastVigilanceAction(botAI); }
};
WarriorAiObjectContext::WarriorAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI)

View File

@@ -12,3 +12,75 @@ bool BloodrageBuffTrigger::IsActive()
return AI_VALUE2(uint8, "health", "self target") >= sPlayerbotAIConfig->mediumHealth &&
AI_VALUE2(uint8, "rage", "self target") < 20;
}
bool VigilanceTrigger::IsActive()
{
if (!bot->HasSpell(50720))
{
return false;
}
Group* group = bot->GetGroup();
if (!group)
{
return false;
}
Player* currentVigilanceTarget = nullptr;
Player* mainTank = nullptr;
Player* assistTank1 = nullptr;
Player* assistTank2 = nullptr;
Player* highestGearScorePlayer = nullptr;
uint32 highestGearScore = 0;
// Iterate once through the group to gather all necessary information
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
{
Player* member = ref->GetSource();
if (!member || member == bot || !member->IsAlive())
continue;
// Check if member has Vigilance applied by the bot
if (!currentVigilanceTarget && botAI->HasAura("vigilance", member, false, true))
{
currentVigilanceTarget = member;
}
// Identify Main Tank
if (!mainTank && botAI->IsMainTank(member))
{
mainTank = member;
}
// Identify Assist Tanks
if (assistTank1 == nullptr && botAI->IsAssistTankOfIndex(member, 0))
{
assistTank1 = member;
}
else if (assistTank2 == nullptr && botAI->IsAssistTankOfIndex(member, 1))
{
assistTank2 = member;
}
// Determine Highest Gear Score
uint32 gearScore = botAI->GetEquipGearScore(member, false, false);
if (gearScore > highestGearScore)
{
highestGearScore = gearScore;
highestGearScorePlayer = member;
}
}
// Determine the highest-priority target
Player* highestPriorityTarget = mainTank ? mainTank :
(assistTank1 ? assistTank1 :
(assistTank2 ? assistTank2 : highestGearScorePlayer));
// Trigger if no Vigilance is active or the current target is not the highest-priority target
if (!currentVigilanceTarget || currentVigilanceTarget != highestPriorityTarget)
{
return true;
}
return false; // No need to reassign Vigilance
}

View File

@@ -64,6 +64,14 @@ public:
RendDebuffTrigger(PlayerbotAI* botAI) : DebuffTrigger(botAI, "rend", 1, true) {}
};
class VigilanceTrigger : public BuffOnPartyTrigger
{
public:
VigilanceTrigger(PlayerbotAI* botAI) : BuffOnPartyTrigger(botAI, "vigilance") {}
bool IsActive() override;
};
// class SlamTrigger : public HasAuraTrigger
// {
// public: