razuvious strategy

This commit is contained in:
Yunfan Li
2023-07-18 21:00:49 +08:00
parent 67a23fae3f
commit 9c1bb63d10
21 changed files with 326 additions and 265 deletions

View File

@@ -248,9 +248,9 @@ void PlayerbotAI::UpdateAI(uint32 elapsed, bool minimal)
// check activity
AllowActivity();
if (bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) {
return;
}
// if (bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) {
// return;
// }
Spell* currentSpell = bot->GetCurrentSpell(CURRENT_GENERIC_SPELL);
if (currentSpell && currentSpell->getState() == SPELL_STATE_CASTING && currentSpell->GetCastTime())
{
@@ -2007,6 +2007,12 @@ bool PlayerbotAI::CanCastSpell(uint32 spellid, Unit* target, bool checkHasSpell,
return false;
}
if (bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL) != nullptr) {
LOG_DEBUG("playerbot", "CanCastSpell() target name: {}, spellid: {}, bot name: {}, failed because has current channeled spell",
target->GetName(), spellid, bot->GetName());
return false;
}
if (bot->HasSpellCooldown(spellid)) {
if (!sPlayerbotAIConfig->logInGroupOnly || bot->GetGroup()) {
LOG_DEBUG("playerbots", "Can cast spell failed. Spell not has cooldown. - target name: {}, spellid: {}, bot name: {}",

View File

@@ -7,6 +7,7 @@
#include "Formations.h"
#include "Playerbots.h"
#include "ServerFacade.h"
#include <cstddef>
bool FollowAction::Execute(Event event)
{
@@ -23,8 +24,8 @@ bool FollowAction::Execute(Event event)
WorldLocation loc = formation->GetLocation();
if (Formation::IsNullLocation(loc) || loc.GetMapId() == -1)
return false;
moved = MoveTo(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ());
moved = MoveTo(loc.GetMapId(), loc.GetPositionX(), loc.GetPositionY(), loc.GetPositionZ() + 2.0f);
}
if (Pet* pet = bot->GetPet())
@@ -47,6 +48,9 @@ bool FollowAction::Execute(Event event)
bool FollowAction::isUseful()
{
if (bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL) != nullptr) {
return false;
}
Formation* formation = AI_VALUE(Formation*, "formation");
std::string const target = formation->GetTargetName();

View File

@@ -1255,6 +1255,14 @@ bool FleeAction::Execute(Event event)
return MoveAway(AI_VALUE(Unit*, "current target"));
}
bool FleeAction::isUseful()
{
if (bot->GetCurrentSpell(CURRENT_CHANNELED_SPELL) != nullptr) {
return false;
}
return true;
}
bool FleeWithPetAction::Execute(Event event)
{
if (Pet* pet = bot->GetPet())

View File

@@ -48,6 +48,7 @@ class FleeAction : public MovementAction
FleeAction(PlayerbotAI* botAI, float distance = sPlayerbotAIConfig->spellDistance) : MovementAction(botAI, "flee"), distance(distance) { }
bool Execute(Event event) override;
bool isUseful() override;
private:
float distance;

View File

@@ -8,6 +8,10 @@
float ThreatMultiplier::GetValue(Action* action)
{
if (AI_VALUE(bool, "neglect threat")) {
return 1.0f;
}
if (!action || action->getThreatType() == Action::ActionThreatType::None)
return 1.0f;

View File

@@ -53,15 +53,11 @@ void TankPaladinStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
"devotion aura",
NextAction::array(0, new NextAction("devotion aura", 90.0f), NULL)));
// triggers.push_back(new TriggerNode("judgement of light", NextAction::array(0, new NextAction("judgement of light", ACTION_HIGH + 6), nullptr)));
// 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("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("light aoe", NextAction::array(0, new NextAction("avenger's shield", ACTION_HIGH + 5), nullptr)));
triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("consecration", ACTION_HIGH + 7), new NextAction("avenger's shield", ACTION_HIGH + 6), 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("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("holy shield", NextAction::array(0, new NextAction("holy shield", ACTION_HIGH + 4), 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(

View File

@@ -25,8 +25,8 @@ class RaidNaxxActionContext : public NamedObjectContext<Action>
// creators["thaddius move to platform"] = &RaidNaxxActionContext::thaddius_move_to_platform;
// creators["thaddius move polarity"] = &RaidNaxxActionContext::thaddius_move_polarity;
// creators["razuvious use obedience crystal"] = &RaidNaxxActionContext::razuvious_use_obedience_crystal;
// creators["razuvious target"] = &RaidNaxxActionContext::razuvious_target;
creators["razuvious use obedience crystal"] = &RaidNaxxActionContext::razuvious_use_obedience_crystal;
creators["razuvious target"] = &RaidNaxxActionContext::razuvious_target;
// creators["horseman attract alternatively"] = &RaidNaxxActionContext::horseman_attract_alternatively;
// creators["horseman attack in order"] = &RaidNaxxActionContext::horseman_attack_in_order;
@@ -60,8 +60,8 @@ class RaidNaxxActionContext : public NamedObjectContext<Action>
// static Action* thaddius_ranged_to_place(PlayerbotAI* ai) { return new ThaddiusRangedToPlaceAction(ai); }
// static Action* thaddius_move_to_platform(PlayerbotAI* ai) { return new ThaddiusMoveToPlatformAction(ai); }
// static Action* thaddius_move_polarity(PlayerbotAI* ai) { return new ThaddiusMovePolarityAction(ai); }
// static Action* razuvious_target(PlayerbotAI* ai) { return new RazuviousTargetAction(ai); }
// static Action* razuvious_use_obedience_crystal(PlayerbotAI* ai) { return new RazuviousUseObedienceCrystalAction(ai); }
static Action* razuvious_target(PlayerbotAI* ai) { return new RazuviousTargetAction(ai); }
static Action* razuvious_use_obedience_crystal(PlayerbotAI* ai) { return new RazuviousUseObedienceCrystalAction(ai); }
// static Action* horseman_attract_alternatively(PlayerbotAI* ai) { return new HorsemanAttractAlternativelyAction(ai); }
// static Action* horseman_attack_in_order(PlayerbotAI* ai) { return new HorsemanAttactInOrderAction(ai); }
// static Action* sapphiron_ground_main_tank_position(PlayerbotAI* ai) { return new SapphironGroundMainTankPositionAction(ai); }

View File

@@ -288,121 +288,129 @@ bool HeiganDanceRangedAction::Execute(Event event) {
// return MoveTo(bot->GetMapId(), position[idx].first, position[idx].second, bot->GetPositionZ());
// }
// bool RazuviousUseObedienceCrystalAction::Execute(Event event)
// {
// if (Unit* charm = bot->GetCharm()) {
// Unit* target = AI_VALUE2(Unit*, "find target", "instructor razuvious");
// if (!target) {
// return false;
// }
// charm->GetMotionMaster()->MoveChase(target);
// charm->Attack(target, true);
// charm->SetFacingToObject(target);
// Aura* forceObedience = botAI->GetAura("force obedience", charm);
// uint32 duration_time;
// if (!forceObedience) {
// forceObedience = botAI->GetAura("mind control", charm);
// duration_time = 60000;
// } else {
// duration_time = 90000;
// }
// if (!forceObedience) {
// return false;
// }
// if (charm->GetDistance(target) <= 0.51f) {
// // taunt
// bool tauntUseful = true;
// if (forceObedience->GetDuration() <= (duration_time - 5000)) {
// if (target->GetVictim() && botAI->HasAura(29061, target->GetVictim())) {
// tauntUseful = false;
// }
// if (forceObedience->GetDuration() <= 3000) {
// tauntUseful = false;
// }
// }
// if (forceObedience->GetDuration() >= (duration_time - 500)) {
// tauntUseful = false;
// }
// if ( tauntUseful && !charm->GetSpellHistory()->HasCooldown(29060) ) {
// // shield
// if (!charm->GetSpellHistory()->HasCooldown(29061)) {
// charm->CastSpell(charm, 29061, true);
// charm->GetSpellHistory()->AddCooldown(29061, 0, Seconds(30));
// }
// charm->CastSpell(target, 29060, true);
// charm->GetSpellHistory()->AddCooldown(29060, 0, Seconds(20));
// }
// // strike
// if (!charm->GetSpellHistory()->HasCooldown(61696)) {
// charm->CastSpell(target, 61696, true);
// charm->GetSpellHistory()->AddCooldown(61696, 0, Seconds(4));
// }
// }
// } else {
// Difficulty diff = bot->GetRaidDifficulty();
// if (diff == RAID_DIFFICULTY_10MAN_NORMAL) {
// list<ObjectGuid> npcs = AI_VALUE(list<ObjectGuid>, "nearest npcs");
// for (list<ObjectGuid>::iterator i = npcs.begin(); i != npcs.end(); i++)
// {
// Creature* unit = botAI->GetCreature(*i);
// if (!unit) {
// continue;
// }
// if (botAI->IsMainTank(bot) && unit->GetSpawnId() != 128352) {
// continue;
// }
// if (!botAI->IsMainTank(bot) && unit->GetSpawnId() != 128353) {
// continue;
// }
// if (MoveTo(unit)) {
// return true;
// }
// Creature *creature = bot->GetNPCIfCanInteractWith(*i, UNIT_NPC_FLAG_SPELLCLICK);
// if (!creature)
// continue;
// creature->HandleSpellClick(bot);
// return true;
// }
// } else {
// list<ObjectGuid> attackers = context->GetValue<list<ObjectGuid> >("attackers")->Get();
// Unit* target = nullptr;
// for (list<ObjectGuid>::iterator i = attackers.begin(); i != attackers.end(); ++i) {
// Unit* unit = botAI->GetUnit(*i);
// if (!unit)
// continue;
// if (botAI->EqualLowercaseName(unit->GetName(), "death knight understudy")) {
// target = unit;
// break;
// }
// }
// if (target) {
// if (bot->GetDistance2d(target) > sPlayerbotAIConfig.spellDistance) {
// return MoveNear(target, sPlayerbotAIConfig.spellDistance);
// } else {
// return botAI->CastSpell("mind control", target);
// }
// }
// }
// }
// return false;
// }
bool RazuviousUseObedienceCrystalAction::Execute(Event event)
{
if (!helper.UpdateBossAI()) {
return false;
}
// bot->GetCharm
if (Unit* charm = bot->GetCharm()) {
Unit* target = AI_VALUE2(Unit*, "find target", "instructor razuvious");
if (!target) {
return false;
}
if (charm->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_ACTIVE) == NULL_MOTION_TYPE) {
charm->GetMotionMaster()->Clear();
charm->GetMotionMaster()->MoveChase(target);
charm->GetAI()->AttackStart(target);
}
Aura* forceObedience = botAI->GetAura("force obedience", charm);
uint32 duration_time;
if (!forceObedience) {
forceObedience = botAI->GetAura("mind control", charm);
duration_time = 60000;
} else {
duration_time = 90000;
}
if (!forceObedience) {
return false;
}
if (charm->GetDistance(target) <= 0.51f) {
// taunt
bool tauntUseful = true;
if (forceObedience->GetDuration() <= (duration_time - 5000)) {
if (target->GetVictim() && botAI->HasAura(29061, target->GetVictim())) {
tauntUseful = false;
}
if (forceObedience->GetDuration() <= 3000) {
tauntUseful = false;
}
}
if (forceObedience->GetDuration() >= (duration_time - 500)) {
tauntUseful = false;
}
if ( tauntUseful && !charm->HasSpellCooldown(29060) ) {
// shield
if (!charm->HasSpellCooldown(29061)) {
charm->CastSpell(charm, 29061, true);
charm->AddSpellCooldown(29061, 0, 30 * 1000);
}
charm->CastSpell(target, 29060, true);
charm->AddSpellCooldown(29060, 0, 20 * 1000);
}
// strike
if (!charm->HasSpellCooldown(61696)) {
charm->CastSpell(target, 61696, true);
charm->AddSpellCooldown(61696, 0, 4 * 1000);
}
}
} else {
Difficulty diff = bot->GetRaidDifficulty();
if (diff == RAID_DIFFICULTY_10MAN_NORMAL) {
GuidVector npcs = AI_VALUE(GuidVector, "nearest npcs");
for (auto i = npcs.begin(); i != npcs.end(); i++)
{
Creature* unit = botAI->GetCreature(*i);
if (!unit) {
continue;
}
if (botAI->IsMainTank(bot) && unit->GetSpawnId() != 128352) {
continue;
}
if (!botAI->IsMainTank(bot) && unit->GetSpawnId() != 128353) {
continue;
}
if (MoveTo(unit)) {
return true;
}
Creature *creature = bot->GetNPCIfCanInteractWith(*i, UNIT_NPC_FLAG_SPELLCLICK);
if (!creature)
continue;
creature->HandleSpellClick(bot);
return true;
}
} else {
GuidVector attackers = context->GetValue<GuidVector>("attackers")->Get();
Unit* target = nullptr;
for (auto i = attackers.begin(); i != attackers.end(); ++i) {
Unit* unit = botAI->GetUnit(*i);
if (!unit)
continue;
if (botAI->EqualLowercaseName(unit->GetName(), "death knight understudy")) {
target = unit;
break;
}
}
if (target) {
if (bot->GetDistance2d(target) > sPlayerbotAIConfig->spellDistance) {
return MoveNear(target, sPlayerbotAIConfig->spellDistance);
} else {
return botAI->CastSpell("mind control", target);
}
}
}
}
return false;
}
// bool RazuviousTargetAction::Execute(Event event)
// {
// Unit* razuvious = AI_VALUE2(Unit*, "find target", "instructor razuvious");
// Unit* understudy = AI_VALUE2(Unit*, "find target", "death knight understudy");
// Unit* target = nullptr;
// if (botAI->IsTank(bot)) {
// target = understudy;
// } else {
// target = razuvious;
// }
// if (AI_VALUE(Unit*, "current target") == target) {
// return false;
// }
// return Attack(target);
// }
bool RazuviousTargetAction::Execute(Event event)
{
if (!helper.UpdateBossAI()) {
return false;
}
Unit* razuvious = AI_VALUE2(Unit*, "find target", "instructor razuvious");
Unit* understudy = AI_VALUE2(Unit*, "find target", "death knight understudy");
Unit* target = nullptr;
if (botAI->IsTank(bot)) {
target = understudy;
} else {
target = razuvious;
}
if (AI_VALUE(Unit*, "current target") == target) {
return false;
}
return Attack(target);
}
// bool HorsemanAttractAlternativelyAction::Execute(Event event)
// {

View File

@@ -127,19 +127,23 @@ protected:
// virtual bool isUseful();
// };
// class RazuviousUseObedienceCrystalAction : public MovementAction
// {
// public:
// RazuviousUseObedienceCrystalAction(PlayerbotAI* ai) : MovementAction(ai, "razuvious use obedience crystal") {}
// virtual bool Execute(Event event);
// };
class RazuviousUseObedienceCrystalAction : public MovementAction
{
public:
RazuviousUseObedienceCrystalAction(PlayerbotAI* ai) : MovementAction(ai, "razuvious use obedience crystal"), helper(ai) {}
bool Execute(Event event) override;
private:
RazuviousBossHelper helper;
};
// class RazuviousTargetAction : public AttackAction
// {
// public:
// RazuviousTargetAction(PlayerbotAI* ai) : AttackAction(ai, "razuvious target") {}
// virtual bool Execute(Event event);
// };
class RazuviousTargetAction : public AttackAction
{
public:
RazuviousTargetAction(PlayerbotAI* ai) : AttackAction(ai, "razuvious target"), helper(ai) {}
bool Execute(Event event) override;
private:
RazuviousBossHelper helper;
};
// class HorsemanAttractAlternativelyAction : public AttackAction
// {

View File

@@ -18,22 +18,14 @@ const uint32 NAXX_MAP_ID = 533;
template<class BossAiType>
class GenericBossHelper : public AiObject {
};
class KelthuzadBossHelper: public AiObject {
public:
std::pair<float, float> center = {3716.19f, -5106.58f};
std::pair<float, float> tank_pos = {3709.19f, -5104.86f};
std::pair<float, float> assist_tank_pos = {3746.05f, -5112.74f};
KelthuzadBossHelper(PlayerbotAI *botAI): AiObject(botAI) {}
GenericBossHelper(PlayerbotAI* botAI, std::string name): AiObject(botAI), name_(name) {}
bool UpdateBossAI() {
Unit* target = AI_VALUE2(Unit*, "find target", "kel'thuzad");
Unit* target = AI_VALUE2(Unit*, "find target", name_);
if (!target) {
return false;
}
ai_ = dynamic_cast<boss_kelthuzad::boss_kelthuzadAI *>(target->GetAI());
ai_ = dynamic_cast<BossAiType *>(target->GetAI());
if (!ai_) {
return false;
}
@@ -43,6 +35,18 @@ class KelthuzadBossHelper: public AiObject {
}
return true;
}
protected:
std::string name_;
BossAiType *ai_;
EventMap* event_map_;
};
class KelthuzadBossHelper: public GenericBossHelper<boss_kelthuzad::boss_kelthuzadAI> {
public:
KelthuzadBossHelper(PlayerbotAI *botAI): GenericBossHelper(botAI, "kel'thuzad") {}
std::pair<float, float> center = {3716.19f, -5106.58f};
std::pair<float, float> tank_pos = {3709.19f, -5104.86f};
std::pair<float, float> assist_tank_pos = {3746.05f, -5112.74f};
bool IsPhaseOne() {
return event_map_->GetNextEventTime(KELTHUZAD_EVENT_PHASE_2) != 0;
}
@@ -63,10 +67,11 @@ class KelthuzadBossHelper: public AiObject {
}
return shadow_fissure;
}
private:
boss_kelthuzad::boss_kelthuzadAI *ai_;
EventMap* event_map_;
};
class RazuviousBossHelper: public GenericBossHelper<boss_razuvious::boss_razuviousAI> {
public:
RazuviousBossHelper(PlayerbotAI *botAI): GenericBossHelper(botAI, "instructor razuvious") {}
};
#endif

View File

@@ -16,6 +16,7 @@
#include "DruidActions.h"
#include "PaladinActions.h"
#include "WarriorActions.h"
#include "DruidBearActions.h"
float HeiganDanceMultiplier::GetValue(Action* action)
{
@@ -63,7 +64,7 @@ float HeiganDanceMultiplier::GetValue(Action* action)
// }
// context->GetValue<bool>("neglect threat")->Set(true);
// if (botAI->GetCurrentState() == BOT_STATE_COMBAT &&
// (dynamic_cast<AttackLeastHpTargetAction*>(action) ||
// (dynamic_cast<DpsAssistAction*>(action) ||
// dynamic_cast<TankAssistAction*>(action) ||
// dynamic_cast<CastDebuffSpellOnAttackerAction*>(action) ||
// dynamic_cast<FleeAction*>(action))) {
@@ -91,7 +92,7 @@ float HeiganDanceMultiplier::GetValue(Action* action)
// uint32 curr_phase = eventMap->GetPhaseMask();
// // pet phase
// if (curr_phase == 2 &&
// ( dynamic_cast<AttackLeastHpTargetAction*>(action) ||
// ( dynamic_cast<DpsAssistAction*>(action) ||
// dynamic_cast<TankAssistAction*>(action) ||
// dynamic_cast<CastDebuffSpellOnAttackerAction*>(action) ||
// dynamic_cast<ReachPartyMemberToHealAction*>(action) ||
@@ -148,24 +149,23 @@ float HeiganDanceMultiplier::GetValue(Action* action)
// return 1.0f;
// }
// float InstructorRazuviousGenericMultiplier::GetValue(Action* action)
// {
// Unit* boss = AI_VALUE2(Unit*, "find target", "instructor razuvious");
// if (!boss) {
// return 1.0f;
// }
// context->GetValue<bool>("neglect threat")->Set(true);
// if (botAI->GetCurrentState() == BOT_STATE_COMBAT &&
// (dynamic_cast<AttackLeastHpTargetAction*>(action) ||
// dynamic_cast<TankAssistAction*>(action) ||
// dynamic_cast<CastTauntAction*>(action) ||
// dynamic_cast<CastDarkCommandAction*>(action) ||
// dynamic_cast<CastHandOfReckoningAction*>(action) ||
// dynamic_cast<CastGrowlAction*>(action))) {
// return 0.0f;
// }
// return 1.0f;
// }
float InstructorRazuviousGenericMultiplier::GetValue(Action* action)
{
if (!helper.UpdateBossAI()) {
return 1.0f;
}
context->GetValue<bool>("neglect threat")->Set(true);
if (botAI->GetState() == BOT_STATE_COMBAT &&
(dynamic_cast<DpsAssistAction*>(action) ||
dynamic_cast<TankAssistAction*>(action) ||
dynamic_cast<CastTauntAction*>(action) ||
dynamic_cast<CastDarkCommandAction*>(action) ||
dynamic_cast<CastHandOfReckoningAction*>(action) ||
dynamic_cast<CastGrowlAction*>(action))) {
return 0.0f;
}
return 1.0f;
}
float KelthuzadGenericMultiplier::GetValue(Action* action)
{
@@ -205,7 +205,7 @@ float AnubrekhanGenericMultiplier::GetValue(Action* action)
return 1.0f;
}
if (
// (dynamic_cast<AttackLeastHpTargetAction*>(action) ||
// (dynamic_cast<DpsAssistAction*>(action) ||
// dynamic_cast<DpsAssistAction*>(action) ||
// dynamic_cast<TankAssistAction*>(action) ||
dynamic_cast<FollowAction*>(action)) {
@@ -228,7 +228,7 @@ float AnubrekhanGenericMultiplier::GetValue(Action* action)
// if (!boss) {
// return 1.0f;
// }
// if ((dynamic_cast<AttackLeastHpTargetAction*>(action) ||
// if ((dynamic_cast<DpsAssistAction*>(action) ||
// dynamic_cast<TankAssistAction*>(action))) {
// return 0.0f;
// }
@@ -262,7 +262,7 @@ float AnubrekhanGenericMultiplier::GetValue(Action* action)
// if (!boss) {
// return 1.0f;
// }
// if ((dynamic_cast<AttackLeastHpTargetAction*>(action) ||
// if ((dynamic_cast<DpsAssistAction*>(action) ||
// dynamic_cast<TankAssistAction*>(action) ||
// dynamic_cast<FleeAction*>(action) ||
// dynamic_cast<CastDebuffSpellOnAttackerAction*>(action) ||

View File

@@ -41,14 +41,14 @@ public:
// virtual float GetValue(Action* action);
// };
// class InstructorRazuviousGenericMultiplier : public Multiplier
// {
// public:
// InstructorRazuviousGenericMultiplier(PlayerbotAI* ai) : Multiplier(ai, "instructor razuvious generic") {}
// public:
// virtual float GetValue(Action* action);
// };
class InstructorRazuviousGenericMultiplier : public Multiplier
{
public:
InstructorRazuviousGenericMultiplier(PlayerbotAI* ai) : Multiplier(ai, "instructor razuvious generic"), helper(ai) {}
virtual float GetValue(Action* action);
private:
RazuviousBossHelper helper;
};
class KelthuzadGenericMultiplier : public Multiplier
{

View File

@@ -30,6 +30,22 @@ void RaidNaxxStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
"heigan ranged",
NextAction::array(0, new NextAction("heigan dance ranged", ACTION_RAID + 1), NULL)));
// Kel'Thuzad
triggers.push_back(new TriggerNode(
"kel'thuzad",
NextAction::array(0,
new NextAction("kel'thuzad choose target", ACTION_RAID + 1),
new NextAction("kel'thuzad position", ACTION_RAID + 1),
NULL)));
// Anub'Rekhan
triggers.push_back(new TriggerNode(
"anub'rekhan",
NextAction::array(0,
// new NextAction("anub'rekhan choose target", ACTION_RAID + 1),
new NextAction("anub'rekhan position", ACTION_RAID + 1),
NULL)));
// Thaddius
// triggers.push_back(new TriggerNode(
// "thaddius phase pet",
@@ -51,14 +67,14 @@ void RaidNaxxStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
// "thaddius phase thaddius",
// NextAction::array(0, new NextAction("thaddius move polarity", ACTION_RAID + 1), NULL)));
// // Instructor Razuvious
// triggers.push_back(new TriggerNode(
// "razuvious tank",
// NextAction::array(0, new NextAction("razuvious use obedience crystal", ACTION_RAID + 1), NULL)));
// Instructor Razuvious
triggers.push_back(new TriggerNode(
"razuvious tank",
NextAction::array(0, new NextAction("razuvious use obedience crystal", ACTION_RAID + 1), NULL)));
// triggers.push_back(new TriggerNode(
// "razuvious nontank",
// NextAction::array(0, new NextAction("razuvious target", ACTION_RAID + 1), NULL)));
triggers.push_back(new TriggerNode(
"razuvious nontank",
NextAction::array(0, new NextAction("razuvious target", ACTION_RAID + 1), NULL)));
// // four horseman
// triggers.push_back(new TriggerNode(
@@ -86,21 +102,7 @@ void RaidNaxxStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
// "sapphiron chill",
// NextAction::array(0, new NextAction("sapphiron avoid chill", ACTION_RAID + 1), NULL)));
// Kel'Thuzad
triggers.push_back(new TriggerNode(
"kel'thuzad",
NextAction::array(0,
new NextAction("kel'thuzad choose target", ACTION_RAID + 1),
new NextAction("kel'thuzad position", ACTION_RAID + 1),
NULL)));
// Anub'Rekhan
triggers.push_back(new TriggerNode(
"anub'rekhan",
NextAction::array(0,
// new NextAction("anub'rekhan choose target", ACTION_RAID + 1),
new NextAction("anub'rekhan position", ACTION_RAID + 1),
NULL)));
// // Gluth
// triggers.push_back(new TriggerNode(
@@ -115,6 +117,7 @@ void RaidNaxxStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
// "gluth main tank mortal wound",
// NextAction::array(0,
// new NextAction("taunt spell", ACTION_RAID + 1), NULL)));
// // Loatheb
// triggers.push_back(new TriggerNode(
// "loatheb",
@@ -130,7 +133,7 @@ void RaidNaxxStrategy::InitMultipliers(std::vector<Multiplier*> &multipliers)
// multipliers.push_back(new LoathebGenericMultiplier(ai));
// multipliers.push_back(new ThaddiusGenericMultiplier(ai));
// multipliers.push_back(new SapphironGenericMultiplier(ai));
// multipliers.push_back(new InstructorRazuviousGenericMultiplier(ai));
multipliers.push_back(new InstructorRazuviousGenericMultiplier(botAI));
multipliers.push_back(new KelthuzadGenericMultiplier(botAI));
multipliers.push_back(new AnubrekhanGenericMultiplier(botAI));
// multipliers.push_back(new FourhorsemanGenericMultiplier(ai));

View File

@@ -25,8 +25,8 @@ class RaidNaxxTriggerContext : public NamedObjectContext<Trigger>
// creators["thaddius phase transition"] = &RaidNaxxTriggerContext::thaddius_phase_transition;
// creators["thaddius phase thaddius"] = &RaidNaxxTriggerContext::thaddius_phase_thaddius;
// creators["razuvious tank"] = &RaidNaxxTriggerContext::razuvious_tank;
// creators["razuvious nontank"] = &RaidNaxxTriggerContext::razuvious_nontank;
creators["razuvious tank"] = &RaidNaxxTriggerContext::razuvious_tank;
creators["razuvious nontank"] = &RaidNaxxTriggerContext::razuvious_nontank;
// creators["horseman attractors"] = &RaidNaxxTriggerContext::horseman_attractors;
// creators["horseman except attractors"] = &RaidNaxxTriggerContext::horseman_except_attractors;
@@ -56,8 +56,8 @@ class RaidNaxxTriggerContext : public NamedObjectContext<Trigger>
// static Trigger* thaddius_phase_pet_lose_aggro(PlayerbotAI* ai) { return new ThaddiusPhasePetLoseAggroTrigger(ai); }
// static Trigger* thaddius_phase_transition(PlayerbotAI* ai) { return new ThaddiusPhaseTransitionTrigger(ai); }
// static Trigger* thaddius_phase_thaddius(PlayerbotAI* ai) { return new ThaddiusPhaseThaddiusTrigger(ai); }
// static Trigger* razuvious_tank(PlayerbotAI* ai) { return new RazuviousTankTrigger(ai); }
// static Trigger* razuvious_nontank(PlayerbotAI* ai) { return new RazuviousNontankTrigger(ai); }
static Trigger* razuvious_tank(PlayerbotAI* ai) { return new RazuviousTankTrigger(ai); }
static Trigger* razuvious_nontank(PlayerbotAI* ai) { return new RazuviousNontankTrigger(ai); }
// static Trigger* horseman_attractors(PlayerbotAI* ai) { return new HorsemanAttractorsTrigger(ai); }
// static Trigger* horseman_except_attractors(PlayerbotAI* ai) { return new HorsemanExceptAttractorsTrigger(ai); }

View File

@@ -91,23 +91,23 @@ bool HeiganRangedTrigger::IsActive()
return botAI->IsRanged(bot);
}
// bool RazuviousTankTrigger::IsActive()
// {
// Difficulty diff = bot->GetRaidDifficulty();
// if (diff == RAID_DIFFICULTY_10MAN_NORMAL) {
// return BossPhaseTrigger::IsActive() && botAI->IsTank(bot);
// }
// return BossPhaseTrigger::IsActive() && bot->getClass() == CLASS_PRIEST;
// }
bool RazuviousTankTrigger::IsActive()
{
Difficulty diff = bot->GetRaidDifficulty();
if (diff == RAID_DIFFICULTY_10MAN_NORMAL) {
return helper.UpdateBossAI() && botAI->IsTank(bot);
}
return helper.UpdateBossAI() && bot->getClass() == CLASS_PRIEST;
}
// bool RazuviousNontankTrigger::IsActive()
// {
// Difficulty diff = bot->GetRaidDifficulty();
// if (diff == RAID_DIFFICULTY_10MAN_NORMAL) {
// return BossPhaseTrigger::IsActive() && !(botAI->IsTank(bot));
// }
// return BossPhaseTrigger::IsActive() && !(bot->getClass() == CLASS_PRIEST);
// }
bool RazuviousNontankTrigger::IsActive()
{
Difficulty diff = bot->GetRaidDifficulty();
if (diff == RAID_DIFFICULTY_10MAN_NORMAL) {
return helper.UpdateBossAI() && !(botAI->IsTank(bot));
}
return helper.UpdateBossAI() && !(bot->getClass() == CLASS_PRIEST);
}
// bool HorsemanAttractorsTrigger::IsActive()
// {

View File

@@ -78,10 +78,43 @@ public:
};
class HeiganRangedTrigger : public Trigger
{
public:
HeiganRangedTrigger(PlayerbotAI* ai): Trigger(ai, "heigan ranged") {}
bool IsActive() override;
};
class RazuviousTankTrigger : public Trigger
{
public:
RazuviousTankTrigger(PlayerbotAI* ai) : Trigger(ai, "instructor razuvious tank"), helper(ai) {}
bool IsActive() override;
private:
RazuviousBossHelper helper;
};
class RazuviousNontankTrigger : public Trigger
{
public:
RazuviousNontankTrigger(PlayerbotAI* ai) : Trigger(ai, "instructor razuvious non-tank"), helper(ai) {}
bool IsActive() override;
private:
RazuviousBossHelper helper;
};
class KelthuzadTrigger : public Trigger
{
public:
KelthuzadTrigger(PlayerbotAI* ai) : Trigger(ai, "kel'thuzad trigger"), helper(ai) {}
bool IsActive() override;
private:
KelthuzadBossHelper helper;
};
class AnubrekhanTrigger : public BossPhaseTrigger<boss_anubrekhan::boss_anubrekhanAI>
{
public:
HeiganRangedTrigger(PlayerbotAI* ai): Trigger(ai, "heigan ranged") {}
virtual bool IsActive();
AnubrekhanTrigger(PlayerbotAI* ai) : BossPhaseTrigger(ai, "anub'rekhan", 0, "anub'rekhan trigger") {}
};
// class ThaddiusPhasePetTrigger : public BossPhaseTrigger
@@ -112,20 +145,6 @@ public:
// ThaddiusPhaseThaddiusTrigger(PlayerbotAI* ai) : BossPhaseTrigger(ai, "thaddius", 1 << (4 - 1), "thaddius phase thaddius") {}
// };
// class RazuviousTankTrigger : public BossPhaseTrigger
// {
// public:
// RazuviousTankTrigger(PlayerbotAI* ai) : BossPhaseTrigger(ai, "instructor razuvious", 0, "razuvious tank") {}
// virtual bool IsActive();
// };
// class RazuviousNontankTrigger : public BossPhaseTrigger
// {
// public:
// RazuviousNontankTrigger(PlayerbotAI* ai) : BossPhaseTrigger(ai, "instructor razuvious", 0, "razuvious nontank") {}
// virtual bool IsActive();
// };
// class HorsemanAttractorsTrigger : public BossPhaseTrigger
// {
// public:
@@ -168,20 +187,7 @@ public:
// virtual bool IsActive();
// };
class KelthuzadTrigger : public Trigger
{
public:
KelthuzadTrigger(PlayerbotAI* ai) : Trigger(ai, "kel'thuzad trigger"), helper(ai) {}
bool IsActive() override;
private:
KelthuzadBossHelper helper;
};
class AnubrekhanTrigger : public BossPhaseTrigger<boss_anubrekhan::boss_anubrekhanAI>
{
public:
AnubrekhanTrigger(PlayerbotAI* ai) : BossPhaseTrigger(ai, "anub'rekhan", 0, "anub'rekhan trigger") {}
};
// class KelthuzadPhaseTwoTrigger : public BossPhaseTrigger
// {

View File

@@ -124,9 +124,7 @@ void GenericShamanStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
// triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("riptide", 26.0f), nullptr)));
triggers.push_back(new TriggerNode("heroism", NextAction::array(0, new NextAction("heroism", 31.0f), nullptr)));
triggers.push_back(new TriggerNode("bloodlust", NextAction::array(0, new NextAction("bloodlust", 30.0f), nullptr)));
triggers.push_back(new TriggerNode(
"medium mana",
NextAction::array(0, new NextAction("mana tide totem", ACTION_EMERGENCY + 5), NULL)));
}
void ShamanBuffDpsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)

View File

@@ -97,5 +97,9 @@ void HealShamanStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
"enemy too close for spell",
NextAction::array(0, new NextAction("flee", 49.0f), NULL)));
triggers.push_back(new TriggerNode(
"medium mana",
NextAction::array(0, new NextAction("mana tide totem", ACTION_HIGH + 5), NULL)));
triggers.push_back(new TriggerNode("party member to heal out of spell range", NextAction::array(0, new NextAction("reach party member to heal", ACTION_CRITICAL_HEAL + 1), nullptr)));
}

View File

@@ -225,19 +225,19 @@ class NoDrinkTrigger : public Trigger
class LightAoeTrigger : public AoeTrigger
{
public:
LightAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 2, 8.0f) { }
LightAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 2, 10.0f) { }
};
class MediumAoeTrigger : public AoeTrigger
{
public:
MediumAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 3, 8.0f) { }
MediumAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 3, 10.0f) { }
};
class HighAoeTrigger : public AoeTrigger
{
public:
HighAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 4, 8.0f) { }
HighAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 4, 10.0f) { }
};
class BuffTrigger : public SpellTrigger

View File

@@ -22,4 +22,16 @@ class ThreatValue : public Uint8CalculatedValue, public Qualified
uint8 Calculate(Unit* target);
};
class NeglectThreatResetValue : public ManualSetValue<bool>
{
public:
NeglectThreatResetValue(PlayerbotAI* ai, bool defaultValue = false, std::string name = "neglect threat") :
ManualSetValue<bool>(ai, defaultValue, name) {}
virtual bool Get() {
bool ret = value;
Reset();
return ret;
}
};
#endif

View File

@@ -291,6 +291,7 @@ class ValueContext : public NamedObjectContext<UntypedValue>
creators["find target"] = &ValueContext::find_target;
creators["boss target"] = &ValueContext::boss_target;
creators["nearest triggers"] = &ValueContext::nearest_triggers;
creators["neglect threat"] = &ValueContext::neglect_threat;
}
private:
@@ -486,6 +487,7 @@ class ValueContext : public NamedObjectContext<UntypedValue>
static UntypedValue* find_target(PlayerbotAI* ai) { return new FindTargetValue(ai); }
static UntypedValue* boss_target(PlayerbotAI* ai) { return new BossTargetValue(ai); }
static UntypedValue* nearest_triggers(PlayerbotAI* ai) { return new NearestTriggersValue(ai); }
static UntypedValue* neglect_threat(PlayerbotAI* ai) { return new NeglectThreatResetValue(ai); }
};
#endif