refactor: naxxramas and kel'thuzad strategy

This commit is contained in:
Yunfan Li
2023-07-18 17:58:51 +08:00
parent 7f328b6e32
commit 7c70f42f34
26 changed files with 647 additions and 425 deletions

View File

@@ -1304,6 +1304,151 @@ bool PlayerbotAI::IsRanged(Player* player)
return true; return true;
} }
bool PlayerbotAI::IsRangedDps(Player* player)
{
return IsRanged(player) && IsDps(player);
}
bool PlayerbotAI::IsRangedDpsAssistantOfIndex(Player* player, int index)
{
Group* group = bot->GetGroup();
if (!group) {
return false;
}
Group::MemberSlotList const& slots = group->GetMemberSlots();
int counter = 0;
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) {
Player* member = ref->GetSource();
if (group->IsAssistant(member->GetGUID()) && IsRangedDps(member)) {
if (index == counter) {
return player == member;
}
counter++;
}
}
// not enough
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) {
Player* member = ref->GetSource();
if (!group->IsAssistant(member->GetGUID()) && IsRangedDps(member)) {
if (index == counter) {
return player == member;
}
counter++;
}
}
return false;
}
int32 PlayerbotAI::GetGroupSlotIndex(Player* player)
{
Group* group = bot->GetGroup();
if (!group) {
return -1;
}
Group::MemberSlotList const& slots = group->GetMemberSlots();
int counter = 0;
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) {
Player* member = ref->GetSource();
if (player == member) {
return counter;
}
counter++;
}
return 0;
}
int32 PlayerbotAI::GetRangedIndex(Player* player)
{
if (!IsRanged(player)) {
return -1;
}
Group* group = bot->GetGroup();
if (!group) {
return -1;
}
Group::MemberSlotList const& slots = group->GetMemberSlots();
int counter = 0;
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) {
Player* member = ref->GetSource();
if (player == member) {
return counter;
}
if (IsRanged(member)) {
counter++;
}
}
return 0;
}
int32 PlayerbotAI::GetClassIndex(Player* player, uint8_t cls)
{
if (player->getClass() != cls) {
return -1;
}
Group* group = bot->GetGroup();
if (!group) {
return -1;
}
Group::MemberSlotList const& slots = group->GetMemberSlots();
int counter = 0;
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) {
Player* member = ref->GetSource();
if (player == member) {
return counter;
}
if (member->getClass() == cls) {
counter++;
}
}
return 0;
}
int32 PlayerbotAI::GetRangedDpsIndex(Player* player)
{
if (!IsRangedDps(player)) {
return -1;
}
Group* group = bot->GetGroup();
if (!group) {
return -1;
}
Group::MemberSlotList const& slots = group->GetMemberSlots();
int counter = 0;
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) {
Player* member = ref->GetSource();
if (player == member) {
return counter;
}
if (IsRangedDps(member)) {
counter++;
}
}
return 0;
}
int32 PlayerbotAI::GetMeleeIndex(Player* player)
{
if (IsRanged(player)) {
return -1;
}
Group* group = bot->GetGroup();
if (!group) {
return -1;
}
Group::MemberSlotList const& slots = group->GetMemberSlots();
int counter = 0;
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) {
Player* member = ref->GetSource();
if (player == member) {
return counter;
}
if (!IsRanged(member)) {
counter++;
}
}
return 0;
}
bool PlayerbotAI::IsTank(Player* player) bool PlayerbotAI::IsTank(Player* player)
{ {
PlayerbotAI* botAi = GET_PLAYERBOT_AI(player); PlayerbotAI* botAi = GET_PLAYERBOT_AI(player);
@@ -1370,6 +1515,54 @@ bool PlayerbotAI::IsHeal(Player* player)
return false; return false;
} }
bool PlayerbotAI::IsDps(Player* player)
{
PlayerbotAI* botAi = GET_PLAYERBOT_AI(player);
if (botAi)
return botAi->ContainsStrategy(STRATEGY_TYPE_DPS);
int tab = AiFactory::GetPlayerSpecTab(player);
switch (player->getClass())
{
case CLASS_MAGE:
case CLASS_WARLOCK:
case CLASS_HUNTER:
case CLASS_ROGUE:
return true;
case CLASS_PRIEST:
if (tab == PRIEST_TAB_SHADOW) {
return true;
}
break;
case CLASS_DRUID:
if (tab == DRUID_TAB_BALANCE) {
return true;
}
break;
case CLASS_SHAMAN:
if (tab != SHAMAN_TAB_RESTORATION) {
return true;
}
break;
case CLASS_PALADIN:
if (tab == PALADIN_TAB_RETRIBUTION) {
return true;
}
break;
case CLASS_DEATH_KNIGHT:
if (tab != DEATHKNIGT_TAB_BLOOD) {
return true;
}
break;
case CLASS_WARRIOR:
if (tab != WARRIOR_TAB_PROTECTION) {
return true;
}
break;
}
return false;
}
bool PlayerbotAI::IsMainTank(Player* player) bool PlayerbotAI::IsMainTank(Player* player)
{ {
Group* group = bot->GetGroup(); Group* group = bot->GetGroup();
@@ -1379,8 +1572,10 @@ bool PlayerbotAI::IsMainTank(Player* player)
ObjectGuid mainTank = ObjectGuid(); ObjectGuid mainTank = ObjectGuid();
Group::MemberSlotList const& slots = group->GetMemberSlots(); Group::MemberSlotList const& slots = group->GetMemberSlots();
for (Group::member_citerator itr = slots.begin(); itr != slots.end(); ++itr) { for (Group::member_citerator itr = slots.begin(); itr != slots.end(); ++itr) {
if (itr->flags & MEMBER_FLAG_MAINTANK) if (itr->flags & MEMBER_FLAG_MAINTANK) {
mainTank = itr->guid; mainTank = itr->guid;
break;
}
} }
if (mainTank != ObjectGuid::Empty) { if (mainTank != ObjectGuid::Empty) {
return player->GetGUID() == mainTank; return player->GetGUID() == mainTank;

View File

@@ -330,9 +330,21 @@ class PlayerbotAI : public PlayerbotAIBase
void Reset(bool full = false); void Reset(bool full = false);
bool IsTank(Player* player); bool IsTank(Player* player);
bool IsHeal(Player* player); bool IsHeal(Player* player);
bool IsDps(Player* player);
bool IsRanged(Player* player); bool IsRanged(Player* player);
bool IsRangedDps(Player* player);
bool IsMainTank(Player* player); bool IsMainTank(Player* player);
bool IsAssistTank(Player* player); bool IsAssistTank(Player* player);
bool IsAssistTankOfIndex(Player* player, int index);
bool IsHealAssistantOfIndex(Player* player, int index);
bool IsRangedDpsAssistantOfIndex(Player* player, int index);
int32 GetGroupSlotIndex(Player* player);
int32 GetRangedIndex(Player* player);
int32 GetClassIndex(Player* player, uint8_t cls);
int32 GetRangedDpsIndex(Player* player);
int32 GetMeleeIndex(Player* player);
Creature* GetCreature(ObjectGuid guid); Creature* GetCreature(ObjectGuid guid);
Unit* GetUnit(ObjectGuid guid); Unit* GetUnit(ObjectGuid guid);
Player* GetPlayer(ObjectGuid guid); Player* GetPlayer(ObjectGuid guid);

View File

@@ -104,18 +104,16 @@ bool AttackAction::Attack(Unit* target, bool with_pet /*true*/)
if (Pet* pet = bot->GetPet()) if (Pet* pet = bot->GetPet())
{ {
pet->SetReactState(REACT_PASSIVE);
if (with_pet) { if (with_pet) {
pet->SetTarget(target->GetGUID()); pet->SetTarget(target->GetGUID());
// pet->GetCharmInfo()->SetCommandState(COMMAND_ATTACK);
pet->GetCharmInfo()->SetIsCommandAttack(true); pet->GetCharmInfo()->SetIsCommandAttack(true);
pet->AI()->AttackStart(target); pet->AI()->AttackStart(target);
pet->SetReactState(REACT_DEFENSIVE); // pet->SetReactState(REACT_DEFENSIVE);
} else { } else {
// pet->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW);
pet->GetCharmInfo()->SetIsCommandFollow(true); pet->GetCharmInfo()->SetIsCommandFollow(true);
pet->GetCharmInfo()->IsReturning(); pet->GetCharmInfo()->IsReturning();
pet->GetMotionMaster()->MoveFollow(bot, PET_FOLLOW_DIST, pet->GetFollowAngle()); pet->GetMotionMaster()->MoveFollow(bot, PET_FOLLOW_DIST, pet->GetFollowAngle());
pet->SetReactState(REACT_PASSIVE);
} }
} }

View File

@@ -1399,3 +1399,17 @@ bool MoveRandomAction::isUseful()
return !botAI->HasRealPlayerMaster() && botAI->GetAiObjectContext()->GetValue<GuidVector>("nearest friendly players")->Get().size() > urand(25, 100); return !botAI->HasRealPlayerMaster() && botAI->GetAiObjectContext()->GetValue<GuidVector>("nearest friendly players")->Get().size() > urand(25, 100);
} }
bool MoveInsideAction::Execute(Event event)
{
return MoveInside(bot->GetMapId(), x, y, bot->GetPositionZ(), distance);
}
bool RotateAroundTheCenterPointAction::Execute(Event event)
{
uint32 next_point = GetCurrWaypoint();
if (MoveTo(bot->GetMapId(), waypoints[next_point].first, waypoints[next_point].second, bot->GetPositionZ())) {
call_counters += 1;
return true;
}
return false;
}

View File

@@ -7,6 +7,7 @@
#include "Action.h" #include "Action.h"
#include "PlayerbotAIConfig.h" #include "PlayerbotAIConfig.h"
#include <cmath>
class Player; class Player;
class PlayerbotAI; class PlayerbotAI;
@@ -123,4 +124,43 @@ class MoveRandomAction : public MovementAction
bool isUseful() override; bool isUseful() override;
}; };
class MoveInsideAction : public MovementAction
{
public:
MoveInsideAction(PlayerbotAI* ai, float x, float y, float distance = 5.0f) : MovementAction(ai, "move inside") {
this->x = x;
this->y = y;
this->distance = distance;
}
virtual bool Execute(Event event);
protected:
float x, y, distance;
};
class RotateAroundTheCenterPointAction : public MovementAction
{
public:
RotateAroundTheCenterPointAction(PlayerbotAI* ai, std::string name,
float center_x, float center_y, float radius = 40.0f,
uint32 intervals = 16, bool clockwise = true, float start_angle = 0) : MovementAction(ai, name) {
this->center_x = center_x;
this->center_y = center_y;
this->radius = radius;
this->intervals = intervals;
this->clockwise = clockwise;
this->call_counters = 0;
for (int i = 0; i < intervals; i++) {
float angle = start_angle + 2 * M_PI * i / intervals;
waypoints.push_back(std::make_pair(center_x + cos(angle) * radius, center_y + sin(angle) * radius));
}
}
virtual bool Execute(Event event);
protected:
virtual uint32 GetCurrWaypoint() { return 0; }
uint32 FindNearestWaypoint();
float center_x, center_y, radius;
uint32 intervals, call_counters;
bool clockwise;
std::vector<std::pair<float, float>> waypoints;
};
#endif #endif

View File

@@ -33,7 +33,7 @@ void HealDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
new NextAction("swiftmend on party", ACTION_CRITICAL_HEAL + 3), new NextAction("swiftmend on party", ACTION_CRITICAL_HEAL + 3),
new NextAction("wild growth", ACTION_CRITICAL_HEAL + 2), new NextAction("wild growth", ACTION_CRITICAL_HEAL + 2),
new NextAction("nourish on party", ACTION_CRITICAL_HEAL + 1), new NextAction("nourish on party", ACTION_CRITICAL_HEAL + 1),
// new NextAction("healing touch on party", ACTION_CRITICAL_HEAL + 0), new NextAction("healing touch on party", ACTION_CRITICAL_HEAL + 0),
NULL))); NULL)));
triggers.push_back(new TriggerNode( triggers.push_back(new TriggerNode(
@@ -41,7 +41,7 @@ void HealDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
NextAction::array(0, new NextAction("nature's swiftness", ACTION_CRITICAL_HEAL + 4), NULL))); NextAction::array(0, new NextAction("nature's swiftness", ACTION_CRITICAL_HEAL + 4), NULL)));
triggers.push_back(new TriggerNode( triggers.push_back(new TriggerNode(
"group heal occasion", "medium group heal occasion",
NextAction::array(0, new NextAction("tranquility", ACTION_CRITICAL_HEAL + 5), NULL))); NextAction::array(0, new NextAction("tranquility", ACTION_CRITICAL_HEAL + 5), NULL)));
// LOW // LOW
@@ -51,7 +51,7 @@ void HealDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 8), new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 8),
new NextAction("swiftmend on party", ACTION_MEDIUM_HEAL + 7), new NextAction("swiftmend on party", ACTION_MEDIUM_HEAL + 7),
new NextAction("nourish on party", ACTION_MEDIUM_HEAL + 6), new NextAction("nourish on party", ACTION_MEDIUM_HEAL + 6),
// new NextAction("healing touch on party", ACTION_MEDIUM_HEAL + 5), new NextAction("healing touch on party", ACTION_MEDIUM_HEAL + 5),
NULL))); NULL)));
// MEDIUM // MEDIUM

View File

@@ -47,8 +47,8 @@ void DpsHunterStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
GenericHunterStrategy::InitTriggers(triggers); GenericHunterStrategy::InitTriggers(triggers);
triggers.push_back(new TriggerNode("black arrow", NextAction::array(0, new NextAction("black arrow", 15.0f), nullptr))); triggers.push_back(new TriggerNode("black arrow", NextAction::array(0, new NextAction("black arrow", 15.0f), nullptr)));
triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("viper sting", 23), nullptr))); triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("viper sting", 23.0f), nullptr)));
triggers.push_back(new TriggerNode("hunter's mark", NextAction::array(0, new NextAction("hunter's mark", 19.0f), nullptr))); triggers.push_back(new TriggerNode("hunter's mark", NextAction::array(0, new NextAction("hunter's mark", 11.0f), nullptr)));
triggers.push_back(new TriggerNode("concussive shot on snare target", NextAction::array(0, new NextAction("concussive shot", 20.0f), nullptr))); triggers.push_back(new TriggerNode("concussive shot on snare target", NextAction::array(0, new NextAction("concussive shot", 20.0f), nullptr)));
triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("call pet", 21.0f), NULL))); triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("call pet", 21.0f), NULL)));
triggers.push_back(new TriggerNode("hunters pet low health", NextAction::array(0, new NextAction("mend pet", 21.0f), NULL))); triggers.push_back(new TriggerNode("hunters pet low health", NextAction::array(0, new NextAction("mend pet", 21.0f), NULL)));
@@ -58,7 +58,7 @@ void DpsHunterStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
void DpsAoeHunterStrategy::InitTriggers(std::vector<TriggerNode*>& triggers) void DpsAoeHunterStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{ {
triggers.push_back(new TriggerNode("light aoe", NextAction::array(0, new NextAction("multi-shot", 20.0f), nullptr))); triggers.push_back(new TriggerNode("light aoe", NextAction::array(0, new NextAction("multi-shot", 20.0f), nullptr)));
triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("volley", 20.0f), nullptr))); triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("volley", 21.0f), nullptr)));
triggers.push_back(new TriggerNode("serpent sting on attacker", NextAction::array(0, new NextAction("serpent sting on attacker", 17.0f), nullptr))); triggers.push_back(new TriggerNode("serpent sting on attacker", NextAction::array(0, new NextAction("serpent sting on attacker", 17.0f), nullptr)));
} }

View File

@@ -13,7 +13,7 @@
inline std::string const GetActualBlessingOfMight(Unit* target) inline std::string const GetActualBlessingOfMight(Unit* target)
{ {
if (!target->ToPlayer()) { if (!target->ToPlayer()) {
return {""}; return "blessing of might";
} }
int tab = AiFactory::GetPlayerSpecTab(target->ToPlayer()); int tab = AiFactory::GetPlayerSpecTab(target->ToPlayer());
switch (target->getClass()) switch (target->getClass())
@@ -46,7 +46,7 @@ inline std::string const GetActualBlessingOfMight(Unit* target)
inline std::string const GetActualBlessingOfWisdom(Unit* target) inline std::string const GetActualBlessingOfWisdom(Unit* target)
{ {
if (!target->ToPlayer()) { if (!target->ToPlayer()) {
return {""}; return "blessing of might";
} }
int tab = AiFactory::GetPlayerSpecTab(target->ToPlayer()); int tab = AiFactory::GetPlayerSpecTab(target->ToPlayer());
switch (target->getClass()) switch (target->getClass())

View File

@@ -36,8 +36,8 @@ class RaidNaxxActionContext : public NamedObjectContext<Action>
// creators["sapphiron flight position"] = &RaidNaxxActionContext::sapphiron_flight_position; // creators["sapphiron flight position"] = &RaidNaxxActionContext::sapphiron_flight_position;
// creators["sapphiron avoid chill"] = &RaidNaxxActionContext::sapphiron_avoid_chill; // creators["sapphiron avoid chill"] = &RaidNaxxActionContext::sapphiron_avoid_chill;
// creators["kel'thuzad choose target"] = &RaidNaxxActionContext::kelthuzad_choose_target; creators["kel'thuzad choose target"] = &RaidNaxxActionContext::kelthuzad_choose_target;
// creators["kel'thuzad position"] = &RaidNaxxActionContext::kelthuzad_position; creators["kel'thuzad position"] = &RaidNaxxActionContext::kelthuzad_position;
creators["anub'rekhan choose target"] = &RaidNaxxActionContext::anubrekhan_choose_target; creators["anub'rekhan choose target"] = &RaidNaxxActionContext::anubrekhan_choose_target;
creators["anub'rekhan position"] = &RaidNaxxActionContext::anubrekhan_position; creators["anub'rekhan position"] = &RaidNaxxActionContext::anubrekhan_position;
@@ -50,8 +50,8 @@ class RaidNaxxActionContext : public NamedObjectContext<Action>
// creators["loatheb choose target"] = &RaidNaxxActionContext::loatheb_choose_target; // creators["loatheb choose target"] = &RaidNaxxActionContext::loatheb_choose_target;
} }
private: private:
static Action* go_behind_the_boss(PlayerbotAI* ai) { return new GoBehindTheBossAction(ai); } static Action* go_behind_the_boss(PlayerbotAI* ai) { return new GrobbulusGoBehindAction(ai); }
static Action* rotate_grobbulus(PlayerbotAI* ai) { return new RotateGrobbulusAction(ai); } static Action* rotate_grobbulus(PlayerbotAI* ai) { return new GrobbulusRotateAction(ai); }
static Action* grobbulus_move_center(PlayerbotAI* ai) { return new GrobblulusMoveCenterAction(ai); } static Action* grobbulus_move_center(PlayerbotAI* ai) { return new GrobblulusMoveCenterAction(ai); }
static Action* heigan_dance_melee(PlayerbotAI* ai) { return new HeiganDanceMeleeAction(ai); } static Action* heigan_dance_melee(PlayerbotAI* ai) { return new HeiganDanceMeleeAction(ai); }
static Action* heigan_dance_ranged(PlayerbotAI* ai) { return new HeiganDanceRangedAction(ai); } static Action* heigan_dance_ranged(PlayerbotAI* ai) { return new HeiganDanceRangedAction(ai); }
@@ -68,8 +68,8 @@ class RaidNaxxActionContext : public NamedObjectContext<Action>
// static Action* sapphiron_ground_position(PlayerbotAI* ai) { return new SapphironGroundPositionAction(ai); } // static Action* sapphiron_ground_position(PlayerbotAI* ai) { return new SapphironGroundPositionAction(ai); }
// static Action* sapphiron_flight_position(PlayerbotAI* ai) { return new SapphironFlightPositionAction(ai); } // static Action* sapphiron_flight_position(PlayerbotAI* ai) { return new SapphironFlightPositionAction(ai); }
// static Action* sapphiron_avoid_chill(PlayerbotAI* ai) { return new SapphironAvoidChillAction(ai); } // static Action* sapphiron_avoid_chill(PlayerbotAI* ai) { return new SapphironAvoidChillAction(ai); }
// static Action* kelthuzad_choose_target(PlayerbotAI* ai) { return new KelthuzadChooseTargetAction(ai); } static Action* kelthuzad_choose_target(PlayerbotAI* ai) { return new KelthuzadChooseTargetAction(ai); }
// static Action* kelthuzad_position(PlayerbotAI* ai) { return new KelthuzadPositionAction(ai); } static Action* kelthuzad_position(PlayerbotAI* ai) { return new KelthuzadPositionAction(ai); }
static Action* anubrekhan_choose_target(PlayerbotAI* ai) { return new AnubrekhanChooseTargetAction(ai); } static Action* anubrekhan_choose_target(PlayerbotAI* ai) { return new AnubrekhanChooseTargetAction(ai); }
static Action* anubrekhan_position(PlayerbotAI* ai) { return new AnubrekhanPositionAction(ai); } static Action* anubrekhan_position(PlayerbotAI* ai) { return new AnubrekhanPositionAction(ai); }
// static Action* gluth_choose_target(PlayerbotAI* ai) { return new GluthChooseTargetAction(ai); } // static Action* gluth_choose_target(PlayerbotAI* ai) { return new GluthChooseTargetAction(ai); }

View File

@@ -1,8 +1,12 @@
#include "ObjectGuid.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "RaidNaxxActions.h" #include "RaidNaxxActions.h"
#include "RaidNaxxStrategy.h" #include "RaidNaxxStrategy.h"
#include "ScriptedCreature.h" #include "ScriptedCreature.h"
#include "SharedDefines.h"
#include "raids/naxxramas/RaidNaxxBossHelper.h"
#include <algorithm>
using namespace std; using namespace std;
@@ -39,7 +43,7 @@ using namespace std;
// } // }
bool GoBehindTheBossAction::Execute(Event event) bool GrobbulusGoBehindAction::Execute(Event event)
{ {
Unit* boss = AI_VALUE(Unit*, "boss target"); Unit* boss = AI_VALUE(Unit*, "boss target");
if (!boss) { if (!boss) {
@@ -60,22 +64,9 @@ bool GoBehindTheBossAction::Execute(Event event)
// return MoveTo(bot->GetMapId(), x, y, bot->GetPositionZ(), true); // return MoveTo(bot->GetMapId(), x, y, bot->GetPositionZ(), true);
// } // }
bool MoveInsideAction::Execute(Event event)
{
return MoveInside(bot->GetMapId(), x, y, bot->GetPositionZ(), distance);
}
bool RotateAroundTheCenterPointAction::Execute(Event event)
{
// uint32 nearest = FindNearestWaypoint();
// uint32 next_point = (nearest + 1) % intervals;
uint32 next_point = GetCurrWaypoint();
if (MoveTo(bot->GetMapId(), waypoints[next_point].first, waypoints[next_point].second, bot->GetPositionZ())) {
call_counters += 1;
return true;
}
return false;
}
uint32 RotateAroundTheCenterPointAction::FindNearestWaypoint() uint32 RotateAroundTheCenterPointAction::FindNearestWaypoint()
{ {
@@ -92,7 +83,7 @@ uint32 RotateAroundTheCenterPointAction::FindNearestWaypoint()
return ret; return ret;
} }
uint32 RotateGrobbulusAction::GetCurrWaypoint() uint32 GrobbulusRotateAction::GetCurrWaypoint()
{ {
Unit* boss = AI_VALUE(Unit*, "boss target"); Unit* boss = AI_VALUE(Unit*, "boss target");
if (!boss) { if (!boss) {
@@ -375,7 +366,7 @@ bool HeiganDanceRangedAction::Execute(Event event) {
// } // }
// } else { // } else {
// list<ObjectGuid> attackers = context->GetValue<list<ObjectGuid> >("attackers")->Get(); // list<ObjectGuid> attackers = context->GetValue<list<ObjectGuid> >("attackers")->Get();
// Unit* target = NULL; // Unit* target = nullptr;
// for (list<ObjectGuid>::iterator i = attackers.begin(); i != attackers.end(); ++i) { // for (list<ObjectGuid>::iterator i = attackers.begin(); i != attackers.end(); ++i) {
// Unit* unit = botAI->GetUnit(*i); // Unit* unit = botAI->GetUnit(*i);
// if (!unit) // if (!unit)
@@ -401,7 +392,7 @@ bool HeiganDanceRangedAction::Execute(Event event) {
// { // {
// Unit* razuvious = AI_VALUE2(Unit*, "find target", "instructor razuvious"); // Unit* razuvious = AI_VALUE2(Unit*, "find target", "instructor razuvious");
// Unit* understudy = AI_VALUE2(Unit*, "find target", "death knight understudy"); // Unit* understudy = AI_VALUE2(Unit*, "find target", "death knight understudy");
// Unit* target = NULL; // Unit* target = nullptr;
// if (botAI->IsTank(bot)) { // if (botAI->IsTank(bot)) {
// target = understudy; // target = understudy;
// } else { // } else {
@@ -492,7 +483,7 @@ bool HeiganDanceRangedAction::Execute(Event event) {
// bool HorsemanAttactInOrderAction::Execute(Event event) // bool HorsemanAttactInOrderAction::Execute(Event event)
// { // {
// Unit* target = NULL; // Unit* target = nullptr;
// Unit* thane = AI_VALUE2(Unit*, "find target", "thane korth'azz"); // Unit* thane = AI_VALUE2(Unit*, "find target", "thane korth'azz");
// Unit* baron = AI_VALUE2(Unit*, "find target", "baron rivendare"); // Unit* baron = AI_VALUE2(Unit*, "find target", "baron rivendare");
// Unit* lady = AI_VALUE2(Unit*, "find target", "lady blaumeux"); // Unit* lady = AI_VALUE2(Unit*, "find target", "lady blaumeux");
@@ -621,7 +612,7 @@ bool HeiganDanceRangedAction::Execute(Event event) {
// } // }
// Group::MemberSlotList const& slots = group->GetMemberSlots(); // Group::MemberSlotList const& slots = group->GetMemberSlots();
// int counter = 0; // int counter = 0;
// Player* playerWithIcebolt = NULL; // Player* playerWithIcebolt = nullptr;
// float minDistance; // float minDistance;
// for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) { // for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) {
// Player* member = ref->GetSource(); // Player* member = ref->GetSource();
@@ -679,188 +670,153 @@ bool HeiganDanceRangedAction::Execute(Event event) {
// return MoveTo(bot->GetMapId(), bot->GetPositionX() + cos(angle) * 5.0f, bot->GetPositionY() + sin(angle) * 5.0f, bot->GetPositionZ()); // return MoveTo(bot->GetMapId(), bot->GetPositionX() + cos(angle) * 5.0f, bot->GetPositionY() + sin(angle) * 5.0f, bot->GetPositionZ());
// } // }
// bool KelthuzadChooseTargetAction::Execute(Event event) bool KelthuzadChooseTargetAction::Execute(Event event)
// { {
// Unit* boss = AI_VALUE2(Unit*, "find target", "kel'thuzad"); if (!helper.UpdateBossAI()) {
// if (!boss) { return false;
// return false; }
// } GuidVector attackers = context->GetValue<GuidVector>("attackers")->Get();
// BossAI* boss_ai = dynamic_cast<BossAI*>(boss->GetAI()); Unit* target = nullptr;
// EventMap* eventMap = boss_botAI->GetEvents(); Unit *target_soldier = nullptr, *target_weaver = nullptr, *target_abomination = nullptr, *target_kelthuzad = nullptr, *target_guardian = nullptr;
// std::pair<float, float> center = {3716.19f, -5106.58f}; for (auto i = attackers.begin(); i != attackers.end(); ++i)
// list<ObjectGuid> attackers = context->GetValue<list<ObjectGuid> >("attackers")->Get(); {
// Unit* target = NULL; Unit* unit = botAI->GetUnit(*i);
// Unit *target_soldier = NULL, *target_weaver = NULL, *target_abomination = NULL, *target_kelthuzad = NULL, *target_guardian = NULL; if (!unit)
// for (list<ObjectGuid>::iterator i = attackers.begin(); i != attackers.end(); ++i) continue;
// {
// Unit* unit = botAI->GetUnit(*i);
// if (!unit)
// continue;
// if (botAI->EqualLowercaseName(unit->GetName(), "guardian of icecrown")) { if (botAI->EqualLowercaseName(unit->GetName(), "guardian of icecrown")) {
// if (!target_guardian) { if (!target_guardian) {
// target_guardian = unit; target_guardian = unit;
// } else if (unit->GetVictim() && target_guardian->GetVictim() && } else if (unit->GetVictim() && target_guardian->GetVictim() &&
// unit->GetVictim()->ToPlayer() && target_guardian->GetVictim()->ToPlayer() && unit->GetVictim()->ToPlayer() && target_guardian->GetVictim()->ToPlayer() &&
// !botAI->IsAssistTank(unit->GetVictim()->ToPlayer()) && botAI->IsAssistTank(target_guardian->GetVictim()->ToPlayer())) { !botAI->IsAssistTank(unit->GetVictim()->ToPlayer()) && botAI->IsAssistTank(target_guardian->GetVictim()->ToPlayer())) {
// target_guardian = unit; target_guardian = unit;
// } else if (unit->GetVictim() && target_guardian->GetVictim() && } else if (unit->GetVictim() && target_guardian->GetVictim() &&
// unit->GetVictim()->ToPlayer() && target_guardian->GetVictim()->ToPlayer() && unit->GetVictim()->ToPlayer() && target_guardian->GetVictim()->ToPlayer() &&
// !botAI->IsAssistTank(unit->GetVictim()->ToPlayer()) && !botAI->IsAssistTank(target_guardian->GetVictim()->ToPlayer()) && !botAI->IsAssistTank(unit->GetVictim()->ToPlayer()) && !botAI->IsAssistTank(target_guardian->GetVictim()->ToPlayer()) &&
// target_guardian->GetDistance2d(center.first, center.second) > bot->GetDistance2d(unit)) { target_guardian->GetDistance2d(helper.center.first, helper.center.second) > bot->GetDistance2d(unit)) {
// target_guardian = unit; target_guardian = unit;
// } }
// } }
// if (unit->GetDistance2d(center.first, center.second) > 30.0f) { if (unit->GetDistance2d(helper.center.first, helper.center.second) > 30.0f) {
// continue; continue;
// } }
// if (bot->GetDistance2d(unit) > sPlayerbotAIConfig.spellDistance) { if (bot->GetDistance2d(unit) > sPlayerbotAIConfig->spellDistance) {
// continue; continue;
// } }
// if (botAI->EqualLowercaseName(unit->GetName(), "unstoppable abomination")) { if (botAI->EqualLowercaseName(unit->GetName(), "unstoppable abomination")) {
// if (target_abomination == NULL || if (target_abomination == nullptr ||
// target_abomination->GetDistance2d(center.first, center.second) > unit->GetDistance2d(center.first, center.second)) { target_abomination->GetDistance2d(helper.center.first, helper.center.second) > unit->GetDistance2d(helper.center.first, helper.center.second)) {
// target_abomination = unit; target_abomination = unit;
// } }
// } }
// if (botAI->EqualLowercaseName(unit->GetName(), "soldier of the frozen wastes")) { if (botAI->EqualLowercaseName(unit->GetName(), "soldier of the frozen wastes")) {
// if (target_soldier == NULL || if (target_soldier == nullptr ||
// target_soldier->GetDistance2d(center.first, center.second) > unit->GetDistance2d(center.first, center.second)) { target_soldier->GetDistance2d(helper.center.first, helper.center.second) > unit->GetDistance2d(helper.center.first, helper.center.second)) {
// target_soldier = unit; target_soldier = unit;
// } }
// } }
// if (botAI->EqualLowercaseName(unit->GetName(), "soul weaver")) { if (botAI->EqualLowercaseName(unit->GetName(), "soul weaver")) {
// if (target_weaver == NULL || if (target_weaver == nullptr ||
// target_weaver->GetDistance2d(center.first, center.second) > unit->GetDistance2d(center.first, center.second)) { target_weaver->GetDistance2d(helper.center.first, helper.center.second) > unit->GetDistance2d(helper.center.first, helper.center.second)) {
// target_weaver = unit; target_weaver = unit;
// } }
// } }
// if (botAI->EqualLowercaseName(unit->GetName(), "kel'thuzad")) { if (botAI->EqualLowercaseName(unit->GetName(), "kel'thuzad")) {
// target_kelthuzad = unit; target_kelthuzad = unit;
// } }
}
vector<Unit*> targets;
if (botAI->IsRanged(bot)) {
if (botAI->GetRangedDpsIndex(bot) <= 1) {
targets = {target_soldier, target_weaver, target_abomination, target_kelthuzad};
} else {
targets = {target_weaver, target_soldier, target_abomination, target_kelthuzad};
}
} else if (botAI->IsAssistTank(bot)) {
targets = {target_abomination, target_guardian, target_kelthuzad};
} else {
targets = {target_abomination, target_kelthuzad};
}
for (Unit* t : targets) {
if (t) {
target = t;
break;
}
}
if (context->GetValue<Unit*>("current target")->Get() == target) {
return false;
}
if (target_kelthuzad && target == target_kelthuzad) {
return Attack(target, true);
}
return Attack(target, false);
}
// } bool KelthuzadPositionAction::Execute(Event event)
// vector<Unit*> targets; {
// if (botAI->IsRanged(bot)) { if (!helper.UpdateBossAI()) {
// if (botAI->GetRangedDpsIndex(bot) <= 1) { return false;
// targets = {target_soldier, target_weaver, target_abomination, target_kelthuzad}; }
// } else { if (helper.IsPhaseOne()) {
// targets = {target_weaver, target_soldier, target_abomination, target_kelthuzad}; if (AI_VALUE(Unit*, "current target") == nullptr) {
// } return MoveInside(NAXX_MAP_ID, helper.center.first, helper.center.second, bot->GetPositionZ(), 3.0f);
// } else if (botAI->IsAssistTank(bot)) { }
// targets = {target_abomination, target_guardian, target_kelthuzad}; } else if (helper.IsPhaseTwo()) {
// } else { Unit* shadow_fissure = helper.GetAnyShadowFissure();
// targets = {target_abomination, target_kelthuzad}; if (!shadow_fissure || bot->GetDistance2d(shadow_fissure) > 10.0f) {
// } float distance, angle;
// for (Unit* t : targets) { if (botAI->IsMainTank(bot)) {
// if (t) { if (AI_VALUE2(bool, "has aggro", "current target")) {
// target = t; return MoveTo(NAXX_MAP_ID, helper.tank_pos.first, helper.tank_pos.second, bot->GetPositionZ());
// break; } else {
// } return false;
// } }
// if (context->GetValue<Unit*>("current target")->Get() == target) { } else if (botAI->IsRanged(bot)) {
// return false; uint32 index = botAI->GetRangedIndex(bot);
// } if (index < 8) {
// // if (target) { distance = 20.0f;
// // bot->Yell("Target name: " + target->GetName(), LANG_UNIVERSAL); angle = index * M_PI / 4;
// // } } else {
// if (target_kelthuzad && target == target_kelthuzad) { distance = 32.0f;
// return Attack(target, true); angle = (index - 8) * M_PI / 4;
// } }
// return Attack(target, false); float dx, dy;
// } dx = helper.center.first + cos(angle) * distance;
dy = helper.center.second + sin(angle) * distance;
// bool KelthuzadPositionAction::Execute(Event event) return MoveTo(NAXX_MAP_ID, dx, dy, bot->GetPositionZ());
// { } else if (botAI->IsTank(bot)) {
// Unit* boss = AI_VALUE2(Unit*, "find target", "kel'thuzad"); Unit* cur_tar = AI_VALUE(Unit*, "current target");
// if (!boss) { if (cur_tar && cur_tar->GetVictim() && cur_tar->GetVictim()->ToPlayer() &&
// return false; botAI->EqualLowercaseName(cur_tar->GetName(), "guardian of icecrown") &&
// } botAI->IsAssistTank(cur_tar->GetVictim()->ToPlayer()) ) {
// BossAI* b_ai = dynamic_cast<BossAI*>(boss->GetAI()); return MoveTo(NAXX_MAP_ID, helper.assist_tank_pos.first, helper.assist_tank_pos.second, bot->GetPositionZ());
// if (!b_ai) { } else {
// return false; return false;
// } }
// EventMap *eventMap = b_botAI->GetEvents(); }
// uint8 phase_mask = eventMap->GetPhaseMask(); } else {
// if (phase_mask == 1) { float dx, dy;
// if (AI_VALUE(Unit*, "current target") == NULL) { float angle;
// return MoveInside(533, 3716.19f, -5106.58f, bot->GetPositionZ(), 3.0f); if (!botAI->IsRanged(bot)) {
// } angle = shadow_fissure->GetAngle(helper.center.first, helper.center.second);
// } else if (phase_mask == 2) { } else {
// Unit* shadow_fissure = NULL; angle = bot->GetAngle(shadow_fissure) + M_PI;
}
// list<ObjectGuid> units = *context->GetValue<list<ObjectGuid> >("possible targets"); dx = shadow_fissure->GetPositionX() + cos(angle) * 10.0f;
// for (list<ObjectGuid>::iterator i = units.begin(); i != units.end(); i++) dy = shadow_fissure->GetPositionY() + sin(angle) * 10.0f;
// { return MoveTo(NAXX_MAP_ID, dx, dy, bot->GetPositionZ());
// Unit* unit = botAI->GetUnit(*i); }
// if (!unit) }
// continue; return false;
}
// if (botAI->EqualLowercaseName(unit->GetName(), "shadow fissure")) {
// shadow_fissure = unit;
// }
// }
// if (!shadow_fissure || bot->GetDistance2d(shadow_fissure) > 8.0f) {
// float distance, angle;
// if (botAI->IsMainTank(bot)) {
// if (AI_VALUE2(bool, "has aggro", "current target")) {
// return MoveTo(533, 3709.19f, -5104.86f, bot->GetPositionZ());
// // return false;
// }
// } else if (botAI->IsRanged(bot)) {
// uint32 index = botAI->GetRangedIndex(bot);
// if (index < 8) {
// distance = 20.0f;
// angle = index * M_PI / 4;
// } else {
// distance = 32.0f;
// angle = (index - 8) * M_PI / 4;
// }
// } else if (botAI->IsTank(bot)) {
// Unit* cur_tar = AI_VALUE(Unit*, "current target");
// if (cur_tar && cur_tar->GetVictim() && cur_tar->GetVictim()->ToPlayer() &&
// botAI->EqualLowercaseName(cur_tar->GetName(), "guardian of icecrown") &&
// botAI->IsAssistTank(cur_tar->GetVictim()->ToPlayer()) ) {
// return MoveTo(533, 3746.05f, -5112.74f, bot->GetPositionZ());
// } else {
// return false;
// }
// } else {
// return false;
// }
// std::pair<float, float> center = {3716.19f, -5106.58f};
// float dx, dy;
// dx = center.first + cos(angle) * distance;
// dy = center.second + sin(angle) * distance;
// return MoveTo(533, dx, dy, bot->GetPositionZ());
// } else {
// float dx, dy;
// float angle;
// if (!botAI->IsRanged(bot)) {
// angle = shadow_fissure->GetAngle(3716.19f, -5106.58f);
// } else {
// angle = bot->GetAngle(shadow_fissure) + M_PI;
// }
// dx = shadow_fissure->GetPositionX() + cos(angle) * 8.0f;
// dy = shadow_fissure->GetPositionY() + sin(angle) * 8.0f;
// return MoveTo(533, dx, dy, bot->GetPositionZ());
// }
// }
// return false;
// }
bool AnubrekhanChooseTargetAction::Execute(Event event) bool AnubrekhanChooseTargetAction::Execute(Event event)
{ {
Unit* boss = AI_VALUE2(Unit*, "find target", "anub'rekhan");
if (!boss) {
return false;
}
BossAI* boss_ai = dynamic_cast<BossAI*>(boss->GetAI());
GuidVector attackers = context->GetValue<GuidVector >("attackers")->Get(); GuidVector attackers = context->GetValue<GuidVector >("attackers")->Get();
Unit* target = NULL; Unit* target = nullptr;
Unit *target_boss = NULL; Unit *target_boss = nullptr;
vector<Unit*> target_guards; vector<Unit*> target_guards;
for (ObjectGuid const guid : attackers) for (ObjectGuid const guid : attackers)
{ {
@@ -882,13 +838,13 @@ bool AnubrekhanChooseTargetAction::Execute(Event event)
} else { } else {
if (botAI->IsAssistTank(bot)) { if (botAI->IsAssistTank(bot)) {
for (Unit* t : target_guards) { for (Unit* t : target_guards) {
if (target == NULL || (target->GetVictim() && target->GetVictim()->ToPlayer() && botAI->IsTank(target->GetVictim()->ToPlayer()))) { if (target == nullptr || (target->GetVictim() && target->GetVictim()->ToPlayer() && botAI->IsTank(target->GetVictim()->ToPlayer()))) {
target = t; target = t;
} }
} }
} else { } else {
for (Unit* t : target_guards) { for (Unit* t : target_guards) {
if (target == NULL || target->GetHealthPct() > t->GetHealthPct()) { if (target == nullptr || target->GetHealthPct() > t->GetHealthPct()) {
target = t; target = t;
} }
} }
@@ -941,8 +897,8 @@ bool AnubrekhanPositionAction::Execute(Event event)
// BossAI* boss_ai = dynamic_cast<BossAI*>(boss->GetAI()); // BossAI* boss_ai = dynamic_cast<BossAI*>(boss->GetAI());
// EventMap* eventMap = boss_botAI->GetEvents(); // EventMap* eventMap = boss_botAI->GetEvents();
// list<ObjectGuid> attackers = context->GetValue<list<ObjectGuid> >("attackers")->Get(); // list<ObjectGuid> attackers = context->GetValue<list<ObjectGuid> >("attackers")->Get();
// Unit* target = NULL; // Unit* target = nullptr;
// Unit *target_boss = NULL; // Unit *target_boss = nullptr;
// vector<Unit*> target_zombies; // vector<Unit*> target_zombies;
// for (list<ObjectGuid>::iterator i = attackers.begin(); i != attackers.end(); ++i) // for (list<ObjectGuid>::iterator i = attackers.begin(); i != attackers.end(); ++i)
// { // {
@@ -971,12 +927,12 @@ bool AnubrekhanPositionAction::Execute(Event event)
// } else { // } else {
// for (Unit* t : target_zombies) { // for (Unit* t : target_zombies) {
// if (t->GetHealthPct() <= 10.0f) { // if (t->GetHealthPct() <= 10.0f) {
// if (target == NULL || target->GetDistance2d(3331.48f, -3109.06f) > t->GetDistance2d(3331.48f, -3109.06f)) { // if (target == nullptr || target->GetDistance2d(3331.48f, -3109.06f) > t->GetDistance2d(3331.48f, -3109.06f)) {
// target = t; // target = t;
// } // }
// } // }
// } // }
// if (target == NULL) { // if (target == nullptr) {
// target = target_boss; // target = target_boss;
// } // }
// } // }
@@ -1099,9 +1055,9 @@ bool AnubrekhanPositionAction::Execute(Event event)
// BossAI* boss_ai = dynamic_cast<BossAI*>(boss->GetAI()); // BossAI* boss_ai = dynamic_cast<BossAI*>(boss->GetAI());
// EventMap* eventMap = boss_botAI->GetEvents(); // EventMap* eventMap = boss_botAI->GetEvents();
// list<ObjectGuid> attackers = context->GetValue<list<ObjectGuid> >("attackers")->Get(); // list<ObjectGuid> attackers = context->GetValue<list<ObjectGuid> >("attackers")->Get();
// Unit* target = NULL; // Unit* target = nullptr;
// Unit *target_boss = NULL; // Unit *target_boss = nullptr;
// Unit *target_spore = NULL; // Unit *target_spore = nullptr;
// for (list<ObjectGuid>::iterator i = attackers.begin(); i != attackers.end(); ++i) // for (list<ObjectGuid>::iterator i = attackers.begin(); i != attackers.end(); ++i)
// { // {
// Unit* unit = botAI->GetUnit(*i); // Unit* unit = botAI->GetUnit(*i);

View File

@@ -8,6 +8,7 @@
#include "PlayerbotAI.h" #include "PlayerbotAI.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "RaidNaxxScripts.h" #include "RaidNaxxScripts.h"
#include "RaidNaxxBossHelper.h"
// just for test // just for test
// class TryToGetBossAIAction : public Action // class TryToGetBossAIAction : public Action
@@ -19,10 +20,10 @@
// virtual bool Execute(Event event); // virtual bool Execute(Event event);
// }; // };
class GoBehindTheBossAction : public MovementAction class GrobbulusGoBehindAction : public MovementAction
{ {
public: public:
GoBehindTheBossAction(PlayerbotAI* ai, float distance = 24.0f, float delta_angle = M_PI / 8) : MovementAction(ai, "grobbulus go behind the boss") { GrobbulusGoBehindAction(PlayerbotAI* ai, float distance = 24.0f, float delta_angle = M_PI / 8) : MovementAction(ai, "grobbulus go behind") {
this->distance = distance; this->distance = distance;
this->delta_angle = delta_angle; this->delta_angle = delta_angle;
} }
@@ -31,67 +32,14 @@ protected:
float distance, delta_angle; float distance, delta_angle;
}; };
// class MoveToPointForceAction : public MovementAction class GrobbulusRotateAction : public RotateAroundTheCenterPointAction
// {
// public:
// MoveToPointForceAction(PlayerbotAI* ai, float x, float y) : MovementAction(ai, "move to point force") {
// this->x = x;
// this->y = y;
// }
// virtual bool Execute(Event event);
// protected:
// float x, y;
// };
class MoveInsideAction : public MovementAction
{ {
public: public:
MoveInsideAction(PlayerbotAI* ai, float x, float y, float distance = 5.0f) : MovementAction(ai, "move inside") { GrobbulusRotateAction(PlayerbotAI* botAI): RotateAroundTheCenterPointAction(botAI, "rotate grobbulus", 3281.23f, -3310.38f, 35.0f, 8, true, M_PI) {}
this->x = x; virtual bool isUseful() override {
this->y = y;
this->distance = distance;
}
virtual bool Execute(Event event);
protected:
float x, y, distance;
};
class RotateAroundTheCenterPointAction : public MovementAction
{
public:
RotateAroundTheCenterPointAction(PlayerbotAI* ai, std::string name,
float center_x, float center_y, float radius = 40.0f,
uint32 intervals = 16, bool clockwise = true, float start_angle = 0) : MovementAction(ai, name) {
this->center_x = center_x;
this->center_y = center_y;
this->radius = radius;
this->intervals = intervals;
this->clockwise = clockwise;
this->call_counters = 0;
for (int i = 0; i < intervals; i++) {
float angle = start_angle + 2 * M_PI * i / intervals;
waypoints.push_back(std::make_pair(center_x + cos(angle) * radius, center_y + sin(angle) * radius));
}
}
virtual bool Execute(Event event);
protected:
virtual uint32 GetCurrWaypoint() { return 0; }
uint32 FindNearestWaypoint();
float center_x, center_y, radius;
uint32 intervals, call_counters;
bool clockwise;
std::vector<std::pair<float, float>> waypoints;
};
class RotateGrobbulusAction : public RotateAroundTheCenterPointAction
{
public:
RotateGrobbulusAction(PlayerbotAI* botAI): RotateAroundTheCenterPointAction(botAI, "rotate grobbulus", 3281.23f, -3310.38f, 35.0f, 8, true, M_PI) {}
virtual bool isUseful() {
return RotateAroundTheCenterPointAction::isUseful() && botAI->IsMainTank(bot) && AI_VALUE2(bool, "has aggro", "boss target"); return RotateAroundTheCenterPointAction::isUseful() && botAI->IsMainTank(bot) && AI_VALUE2(bool, "has aggro", "boss target");
} }
virtual uint32 GetCurrWaypoint(); uint32 GetCurrWaypoint() override;
protected:
}; };
class GrobblulusMoveCenterAction : public MoveInsideAction class GrobblulusMoveCenterAction : public MoveInsideAction
@@ -254,19 +202,23 @@ protected:
// virtual bool Execute(Event event); // virtual bool Execute(Event event);
// }; // };
// class KelthuzadChooseTargetAction : public AttackAction class KelthuzadChooseTargetAction : public AttackAction
// { {
// public: public:
// KelthuzadChooseTargetAction(PlayerbotAI* ai) : AttackAction(ai, "kel'thuzad choose target") {} KelthuzadChooseTargetAction(PlayerbotAI* ai) : AttackAction(ai, "kel'thuzad choose target"), helper(ai) {}
// virtual bool Execute(Event event); virtual bool Execute(Event event);
// }; private:
KelthuzadBossHelper helper;
};
// class KelthuzadPositionAction : public MovementAction class KelthuzadPositionAction : public MovementAction
// { {
// public: public:
// KelthuzadPositionAction(PlayerbotAI* ai) : MovementAction(ai, "kel'thuzad position") {} KelthuzadPositionAction(PlayerbotAI* ai) : MovementAction(ai, "kel'thuzad position"), helper(ai) {}
// virtual bool Execute(Event event); virtual bool Execute(Event event);
// }; private:
KelthuzadBossHelper helper;
};
class AnubrekhanChooseTargetAction : public AttackAction class AnubrekhanChooseTargetAction : public AttackAction
{ {

View File

@@ -0,0 +1,72 @@
#ifndef _PLAYERBOT_RAIDNAXXBOSSHELPER_H
#define _PLAYERBOT_RAIDNAXXBOSSHELPER_H
#include "AiObject.h"
#include "AiObjectContext.h"
#include "EventMap.h"
#include "ObjectGuid.h"
#include "Player.h"
#include "PlayerbotAI.h"
#include "Playerbots.h"
#include "ScriptedCreature.h"
#include "RaidNaxxScripts.h"
#include "SharedDefines.h"
#include <string>
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) {}
bool UpdateBossAI() {
Unit* target = AI_VALUE2(Unit*, "find target", "kel'thuzad");
if (!target) {
return false;
}
ai_ = dynamic_cast<boss_kelthuzad::boss_kelthuzadAI *>(target->GetAI());
if (!ai_) {
return false;
}
event_map_ = &ai_->events;
if (!event_map_) {
return false;
}
return true;
}
bool IsPhaseOne() {
return event_map_->GetNextEventTime(KELTHUZAD_EVENT_PHASE_2) != 0;
}
bool IsPhaseTwo() {
return !IsPhaseOne();
}
Unit* GetAnyShadowFissure() {
Unit* shadow_fissure = nullptr;
GuidVector units = *context->GetValue<GuidVector>("nearest triggers");
for (auto i = units.begin(); i != units.end(); i++)
{
Unit* unit = botAI->GetUnit(*i);
if (!unit)
continue;
if (botAI->EqualLowercaseName(unit->GetName(), "shadow fissure")) {
shadow_fissure = unit;
}
}
return shadow_fissure;
}
private:
boss_kelthuzad::boss_kelthuzadAI *ai_;
EventMap* event_map_;
};
#endif

View File

@@ -167,42 +167,36 @@ float HeiganDanceMultiplier::GetValue(Action* action)
// return 1.0f; // return 1.0f;
// } // }
// float KelthuzadGenericMultiplier::GetValue(Action* action) float KelthuzadGenericMultiplier::GetValue(Action* action)
// { {
// Unit* boss = AI_VALUE2(Unit*, "find target", "kel'thuzad"); if (!helper.UpdateBossAI()) {
// if (!boss) { return 1.0f;
// return 1.0f; }
// } if ((dynamic_cast<DpsAssistAction*>(action) ||
// if ((dynamic_cast<AttackLeastHpTargetAction*>(action) || dynamic_cast<TankAssistAction*>(action) ||
// dynamic_cast<TankAssistAction*>(action) || dynamic_cast<CastDebuffSpellOnAttackerAction*>(action) ||
// dynamic_cast<CastDebuffSpellOnAttackerAction*>(action) || dynamic_cast<FollowAction*>(action) ||
// dynamic_cast<FollowAction*>(action) || dynamic_cast<FleeAction*>(action))) {
// dynamic_cast<FleeAction*>(action))) { return 0.0f;
// return 0.0f; }
// } if (helper.IsPhaseOne()) {
// BossAI* boss_ai = dynamic_cast<BossAI*>(boss->GetAI()); if (dynamic_cast<CastTotemAction*>(action) ||
// EventMap* eventMap = boss_botAI->GetEvents(); dynamic_cast<CastShadowfiendAction*>(action) ||
// uint32 curr_phase = eventMap->GetPhaseMask(); dynamic_cast<CastRaiseDeadAction*>(action) ||
dynamic_cast<CastFeignDeathAction*>(action) ||
// if (curr_phase == 1) { dynamic_cast<CastInvisibilityAction*>(action) ||
// if (dynamic_cast<CastTotemAction*>(action) || dynamic_cast<CastVanishAction*>(action)) {
// dynamic_cast<CastShadowfiendAction*>(action) || return 0.0f;
// dynamic_cast<CastRaiseDeadAction*>(action) || }
// dynamic_cast<CastFeignDeathAction*>(action) || }
// dynamic_cast<CastInvisibilityAction*>(action) || if (helper.IsPhaseTwo()) {
// dynamic_cast<CastVanishAction*>(action)) { if (dynamic_cast<CastBlizzardAction*>(action) ||
// return 0.0f; dynamic_cast<CastFrostNovaAction*>(action)) {
// } return 0.0f;
// } }
// if (curr_phase == 2) { }
// if (dynamic_cast<CastBlizzardAction*>(action) || return 1.0f;
// dynamic_cast<CastFrostNovaAction*>(action)) { }
// return 0.0f;
// }
// }
// return 1.0f;
// }
float AnubrekhanGenericMultiplier::GetValue(Action* action) float AnubrekhanGenericMultiplier::GetValue(Action* action)
{ {

View File

@@ -3,6 +3,7 @@
#define _PLAYERRBOT_RAIDNAXXMULTIPLIERS_H_ #define _PLAYERRBOT_RAIDNAXXMULTIPLIERS_H_
#include "Multiplier.h" #include "Multiplier.h"
#include "raids/naxxramas/RaidNaxxBossHelper.h"
class HeiganDanceMultiplier : public Multiplier class HeiganDanceMultiplier : public Multiplier
{ {
@@ -49,14 +50,14 @@ public:
// virtual float GetValue(Action* action); // virtual float GetValue(Action* action);
// }; // };
// class KelthuzadGenericMultiplier : public Multiplier class KelthuzadGenericMultiplier : public Multiplier
// { {
// public: public:
// KelthuzadGenericMultiplier(PlayerbotAI* ai) : Multiplier(ai, "kelthuzad generic") {} KelthuzadGenericMultiplier(PlayerbotAI* ai) : Multiplier(ai, "kelthuzad generic"), helper(ai) {}
virtual float GetValue(Action* action);
// public: private:
// virtual float GetValue(Action* action); KelthuzadBossHelper helper;
// }; };
class AnubrekhanGenericMultiplier : public Multiplier class AnubrekhanGenericMultiplier : public Multiplier
{ {

View File

@@ -1,8 +1,24 @@
#ifndef _PLAYERBOT_RAIDNAXXSCRIPTS_H #ifndef _PLAYERBOT_RAIDNAXXSCRIPTS_H
#define _PLAYERBOT_RAIDNAXXSCRIPTS_H #define _PLAYERBOT_RAIDNAXXSCRIPTS_H
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_heigan.h"
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.h" #include "../../../../src/server/scripts/Northrend/Naxxramas/boss_anubrekhan.h"
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_faerlina.h"
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_maexxna.h"
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_noth.h"
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_heigan.h"
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_loatheb.h"
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_patchwerk.h"
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_grobbulus.h" #include "../../../../src/server/scripts/Northrend/Naxxramas/boss_grobbulus.h"
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_gluth.h"
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_thaddius.h"
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_razuvious.h"
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_gothik.h"
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.h"
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_sapphiron.h"
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.h"
#endif #endif

View File

@@ -86,13 +86,13 @@ void RaidNaxxStrategy::InitTriggers(std::vector<TriggerNode*> &triggers)
// "sapphiron chill", // "sapphiron chill",
// NextAction::array(0, new NextAction("sapphiron avoid chill", ACTION_RAID + 1), NULL))); // NextAction::array(0, new NextAction("sapphiron avoid chill", ACTION_RAID + 1), NULL)));
// // Kel'Thuzad // Kel'Thuzad
// triggers.push_back(new TriggerNode( triggers.push_back(new TriggerNode(
// "kel'thuzad", "kel'thuzad",
// NextAction::array(0, NextAction::array(0,
// new NextAction("kel'thuzad choose target", ACTION_RAID + 1), new NextAction("kel'thuzad choose target", ACTION_RAID + 1),
// new NextAction("kel'thuzad position", ACTION_RAID + 1), new NextAction("kel'thuzad position", ACTION_RAID + 1),
// NULL))); NULL)));
// Anub'Rekhan // Anub'Rekhan
triggers.push_back(new TriggerNode( triggers.push_back(new TriggerNode(
@@ -131,7 +131,7 @@ void RaidNaxxStrategy::InitMultipliers(std::vector<Multiplier*> &multipliers)
// multipliers.push_back(new ThaddiusGenericMultiplier(ai)); // multipliers.push_back(new ThaddiusGenericMultiplier(ai));
// multipliers.push_back(new SapphironGenericMultiplier(ai)); // multipliers.push_back(new SapphironGenericMultiplier(ai));
// multipliers.push_back(new InstructorRazuviousGenericMultiplier(ai)); // multipliers.push_back(new InstructorRazuviousGenericMultiplier(ai));
// multipliers.push_back(new KelthuzadGenericMultiplier(ai)); multipliers.push_back(new KelthuzadGenericMultiplier(botAI));
multipliers.push_back(new AnubrekhanGenericMultiplier(botAI)); multipliers.push_back(new AnubrekhanGenericMultiplier(botAI));
// multipliers.push_back(new FourhorsemanGenericMultiplier(ai)); // multipliers.push_back(new FourhorsemanGenericMultiplier(ai));
// multipliers.push_back(new GothikGenericMultiplier(ai)); // multipliers.push_back(new GothikGenericMultiplier(ai));

View File

@@ -36,7 +36,7 @@ class RaidNaxxTriggerContext : public NamedObjectContext<Trigger>
// creators["sapphiron flight"] = &RaidNaxxTriggerContext::sapphiron_flight; // creators["sapphiron flight"] = &RaidNaxxTriggerContext::sapphiron_flight;
// creators["sapphiron chill"] = &RaidNaxxTriggerContext::sapphiron_ground_chill; // creators["sapphiron chill"] = &RaidNaxxTriggerContext::sapphiron_ground_chill;
// creators["kel'thuzad"] = &RaidNaxxTriggerContext::kelthuzad; creators["kel'thuzad"] = &RaidNaxxTriggerContext::kelthuzad;
// creators["kel'thuzad phase two"] = &RaidNaxxTriggerContext::kelthuzad_phase_two; // creators["kel'thuzad phase two"] = &RaidNaxxTriggerContext::kelthuzad_phase_two;
creators["anub'rekhan"] = &RaidNaxxTriggerContext::anubrekhan; creators["anub'rekhan"] = &RaidNaxxTriggerContext::anubrekhan;
@@ -65,7 +65,7 @@ class RaidNaxxTriggerContext : public NamedObjectContext<Trigger>
// static Trigger* sapphiron_ground_except_main_tank(PlayerbotAI* ai) { return new SapphironGroundExceptMainTankTrigger(ai); } // static Trigger* sapphiron_ground_except_main_tank(PlayerbotAI* ai) { return new SapphironGroundExceptMainTankTrigger(ai); }
// static Trigger* sapphiron_flight(PlayerbotAI* ai) { return new SapphironFlightTrigger(ai); } // static Trigger* sapphiron_flight(PlayerbotAI* ai) { return new SapphironFlightTrigger(ai); }
// static Trigger* sapphiron_ground_chill(PlayerbotAI* ai) { return new SapphironGroundChillTrigger(ai); } // static Trigger* sapphiron_ground_chill(PlayerbotAI* ai) { return new SapphironGroundChillTrigger(ai); }
// static Trigger* kelthuzad(PlayerbotAI* ai) { return new KelthuzadTrigger(ai); } static Trigger* kelthuzad(PlayerbotAI* ai) { return new KelthuzadTrigger(ai); }
// static Trigger* kelthuzad_phase_two(PlayerbotAI* ai) { return new KelthuzadPhaseTwoTrigger(ai); } // static Trigger* kelthuzad_phase_two(PlayerbotAI* ai) { return new KelthuzadPhaseTwoTrigger(ai); }
static Trigger* anubrekhan(PlayerbotAI* ai) { return new AnubrekhanTrigger(ai); } static Trigger* anubrekhan(PlayerbotAI* ai) { return new AnubrekhanTrigger(ai); }
// static Trigger* gluth(PlayerbotAI* ai) { return new GluthTrigger(ai); } // static Trigger* gluth(PlayerbotAI* ai) { return new GluthTrigger(ai); }

View File

@@ -166,5 +166,9 @@ bool HeiganRangedTrigger::IsActive()
// return true; // return true;
// } // }
bool KelthuzadTrigger::IsActive() {
return helper.UpdateBossAI();
}
template bool BossEventTrigger<boss_grobbulus::boss_grobbulusAI>::IsActive(); template bool BossEventTrigger<boss_grobbulus::boss_grobbulusAI>::IsActive();
template bool BossPhaseTrigger<boss_anubrekhan::boss_anubrekhanAI>::IsActive(); template bool BossPhaseTrigger<boss_anubrekhan::boss_anubrekhanAI>::IsActive();

View File

@@ -7,6 +7,7 @@
#include "PlayerbotAIConfig.h" #include "PlayerbotAIConfig.h"
#include "GenericTriggers.h" #include "GenericTriggers.h"
#include "RaidNaxxScripts.h" #include "RaidNaxxScripts.h"
#include "raids/naxxramas/RaidNaxxBossHelper.h"
using namespace std; using namespace std;
@@ -167,11 +168,14 @@ public:
// virtual bool IsActive(); // virtual bool IsActive();
// }; // };
// class KelthuzadTrigger : public BossPhaseTrigger class KelthuzadTrigger : public Trigger
// { {
// public: public:
// KelthuzadTrigger(PlayerbotAI* ai) : BossPhaseTrigger(ai, "kel'thuzad", 0, "kel'thuzad trigger") {} KelthuzadTrigger(PlayerbotAI* ai) : Trigger(ai, "kel'thuzad trigger"), helper(ai) {}
// }; bool IsActive() override;
private:
KelthuzadBossHelper helper;
};
class AnubrekhanTrigger : public BossPhaseTrigger<boss_anubrekhan::boss_anubrekhanAI> class AnubrekhanTrigger : public BossPhaseTrigger<boss_anubrekhan::boss_anubrekhanAI>
{ {

View File

@@ -123,6 +123,7 @@ class TriggerContext : public NamedObjectContext<Trigger>
creators["low aoe heal"] = &TriggerContext::low_aoe_heal; creators["low aoe heal"] = &TriggerContext::low_aoe_heal;
creators["medium aoe heal"] = &TriggerContext::medium_aoe_heal; creators["medium aoe heal"] = &TriggerContext::medium_aoe_heal;
creators["group heal occasion"] = &TriggerContext::group_heal_occasion; creators["group heal occasion"] = &TriggerContext::group_heal_occasion;
creators["medium group heal occasion"] = &TriggerContext::medium_group_heal_occasion;
creators["invalid target"] = &TriggerContext::invalid_target; creators["invalid target"] = &TriggerContext::invalid_target;
creators["lfg proposal active"] = &TriggerContext::lfg_proposal_active; creators["lfg proposal active"] = &TriggerContext::lfg_proposal_active;
@@ -216,6 +217,7 @@ class TriggerContext : public NamedObjectContext<Trigger>
static Trigger* low_aoe_heal(PlayerbotAI* botAI) { return new AoeHealTrigger(botAI, "low aoe heal", "low", 2); } static Trigger* low_aoe_heal(PlayerbotAI* botAI) { return new AoeHealTrigger(botAI, "low aoe heal", "low", 2); }
static Trigger* medium_aoe_heal(PlayerbotAI* botAI) { return new AoeHealTrigger(botAI, "medium aoe heal", "medium", 2); } static Trigger* medium_aoe_heal(PlayerbotAI* botAI) { return new AoeHealTrigger(botAI, "medium aoe heal", "medium", 2); }
static Trigger* group_heal_occasion(PlayerbotAI* ai) { return new AoeInGroupTrigger(ai, "group heal occasion", "almost full", 0.4); } static Trigger* group_heal_occasion(PlayerbotAI* ai) { return new AoeInGroupTrigger(ai, "group heal occasion", "almost full", 0.4); }
static Trigger* medium_group_heal_occasion(PlayerbotAI* ai) { return new AoeInGroupTrigger(ai, "group heal occasion", "medium", 0.4); }
static Trigger* target_changed(PlayerbotAI* botAI) { return new TargetChangedTrigger(botAI); } static Trigger* target_changed(PlayerbotAI* botAI) { return new TargetChangedTrigger(botAI); }
static Trigger* swimming(PlayerbotAI* botAI) { return new IsSwimmingTrigger(botAI); } static Trigger* swimming(PlayerbotAI* botAI) { return new IsSwimmingTrigger(botAI); }
static Trigger* no_possible_targets(PlayerbotAI* botAI) { return new NoPossibleTargetsTrigger(botAI); } static Trigger* no_possible_targets(PlayerbotAI* botAI) { return new NoPossibleTargetsTrigger(botAI); }

View File

@@ -4,6 +4,7 @@
#include "AttackerCountValues.h" #include "AttackerCountValues.h"
#include "Playerbots.h" #include "Playerbots.h"
#include "SharedDefines.h"
uint8 MyAttackerCountValue::Calculate() uint8 MyAttackerCountValue::Calculate()
{ {
@@ -13,80 +14,17 @@ uint8 MyAttackerCountValue::Calculate()
bool HasAggroValue::Calculate() bool HasAggroValue::Calculate()
{ {
Unit* target = GetTarget(); Unit* target = GetTarget();
if (!target) if (!target) {
return true; return true;
}
Unit* victim = target->GetVictim(); Unit* victim = target->GetVictim();
if (!victim) { if (!victim) {
return true; return true;
} }
if (victim && (victim->GetGUID() == bot->GetGUID() || (victim->ToPlayer() && botAI->IsMainTank(victim->ToPlayer())))) {
if (victim->GetGUID() == bot->GetGUID() || (victim->ToPlayer() && botAI->IsMainTank(victim->ToPlayer()))) {
return true; 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; 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;
// HostileReference *ref = bot->getHostileRefMgr().getFirst();
// if (!ref)
// return true; // simulate as target is not atacking anybody yet
// while( ref )
// {
// ThreatMgr* threatMgr = ref->GetSource();
// Unit* attacker = threatMgr->GetOwner();
// Unit* victim = attacker->GetVictim();
// if (victim == bot && target == attacker)
// return true;
// ref = ref->next();
// }
// ref = target->GetThreatMgr().getCurrentVictim();
// if (ref)
// {
// if (Unit* victim = ref->getTarget())
// {
// if (Player* pl = victim->ToPlayer())
// {
// if (botAI->IsMainTank(pl))
// {
// return true;
// }
// }
// }
// }
// return false;
} }
uint8 AttackerCountValue::Calculate() uint8 AttackerCountValue::Calculate()

View File

@@ -208,7 +208,7 @@ ItemUsage ItemUsageValue::QueryItemUsageForEquip(ItemTemplate const* itemProto)
float oldScore = PlayerbotFactory::CalculateItemScore(oldItemProto->ItemId, bot); float oldScore = PlayerbotFactory::CalculateItemScore(oldItemProto->ItemId, bot);
if (itemScore || oldScore) if (itemScore || oldScore)
{ {
shouldEquip = itemScore >= oldScore * 1.2; shouldEquip = itemScore >= oldScore * 1.5;
} }
} }

View File

@@ -39,3 +39,15 @@ bool NearestVehiclesValue::AcceptUnit(Unit* unit)
return true; return true;
} }
void NearestTriggersValue::FindUnits(std::list<Unit*>& targets)
{
Acore::AnyUnfriendlyUnitInObjectRangeCheck u_check(bot, bot, range);
Acore::UnitListSearcher<Acore::AnyUnfriendlyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
Cell::VisitAllObjects(bot, searcher, range);
}
bool NearestTriggersValue::AcceptUnit(Unit* unit)
{
return !unit->IsPlayer();
}

View File

@@ -30,4 +30,13 @@ class NearestVehiclesValue : public NearestUnitsValue
bool AcceptUnit(Unit* unit) override; bool AcceptUnit(Unit* unit) override;
}; };
class NearestTriggersValue : public NearestUnitsValue
{
public:
NearestTriggersValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig->sightDistance) : NearestUnitsValue(botAI, "nearest triggers", range) { }
protected:
void FindUnits(std::list<Unit*>& targets) override;
bool AcceptUnit(Unit* unit) override;
};
#endif #endif

View File

@@ -19,7 +19,7 @@ class FindTargetStrategy
FindTargetStrategy(PlayerbotAI* botAI) : result(nullptr), botAI(botAI) { } FindTargetStrategy(PlayerbotAI* botAI) : result(nullptr), botAI(botAI) { }
Unit* GetResult(); Unit* GetResult();
virtual void CheckAttacker(Unit* attacker, ThreatMgr* threatMgr) = 0; virtual void CheckAttacker(Unit* attacker, ThreatMgr* threatMgr) = 0;
void GetPlayerCount(Unit* creature, uint32* tankCount, uint32* dpsCount); void GetPlayerCount(Unit* creature, uint32* tankCount, uint32* dpsCount);
protected: protected:

View File

@@ -85,6 +85,7 @@
#include "TankTargetValue.h" #include "TankTargetValue.h"
#include "ThreatValues.h" #include "ThreatValues.h"
#include "TradeValues.h" #include "TradeValues.h"
#include "Value.h"
class PlayerbotAI; class PlayerbotAI;
@@ -289,6 +290,7 @@ class ValueContext : public NamedObjectContext<UntypedValue>
creators["main tank"] = &ValueContext::main_tank; creators["main tank"] = &ValueContext::main_tank;
creators["find target"] = &ValueContext::find_target; creators["find target"] = &ValueContext::find_target;
creators["boss target"] = &ValueContext::boss_target; creators["boss target"] = &ValueContext::boss_target;
creators["nearest triggers"] = &ValueContext::nearest_triggers;
} }
private: private:
@@ -483,6 +485,7 @@ class ValueContext : public NamedObjectContext<UntypedValue>
static UntypedValue* main_tank(PlayerbotAI* ai) { return new PartyMemberMainTankValue(ai); } static UntypedValue* main_tank(PlayerbotAI* ai) { return new PartyMemberMainTankValue(ai); }
static UntypedValue* find_target(PlayerbotAI* ai) { return new FindTargetValue(ai); } static UntypedValue* find_target(PlayerbotAI* ai) { return new FindTargetValue(ai); }
static UntypedValue* boss_target(PlayerbotAI* ai) { return new BossTargetValue(ai); } static UntypedValue* boss_target(PlayerbotAI* ai) { return new BossTargetValue(ai); }
static UntypedValue* nearest_triggers(PlayerbotAI* ai) { return new NearestTriggersValue(ai); }
}; };
#endif #endif