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;
}
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)
{
PlayerbotAI* botAi = GET_PLAYERBOT_AI(player);
@@ -1370,6 +1515,54 @@ bool PlayerbotAI::IsHeal(Player* player)
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)
{
Group* group = bot->GetGroup();
@@ -1379,8 +1572,10 @@ bool PlayerbotAI::IsMainTank(Player* player)
ObjectGuid mainTank = ObjectGuid();
Group::MemberSlotList const& slots = group->GetMemberSlots();
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;
break;
}
}
if (mainTank != ObjectGuid::Empty) {
return player->GetGUID() == mainTank;

View File

@@ -330,9 +330,21 @@ class PlayerbotAI : public PlayerbotAIBase
void Reset(bool full = false);
bool IsTank(Player* player);
bool IsHeal(Player* player);
bool IsDps(Player* player);
bool IsRanged(Player* player);
bool IsRangedDps(Player* player);
bool IsMainTank(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);
Unit* GetUnit(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())
{
pet->SetReactState(REACT_PASSIVE);
if (with_pet) {
pet->SetTarget(target->GetGUID());
// pet->GetCharmInfo()->SetCommandState(COMMAND_ATTACK);
pet->GetCharmInfo()->SetIsCommandAttack(true);
pet->AI()->AttackStart(target);
pet->SetReactState(REACT_DEFENSIVE);
// pet->SetReactState(REACT_DEFENSIVE);
} else {
// pet->GetCharmInfo()->SetCommandState(COMMAND_FOLLOW);
pet->GetCharmInfo()->SetIsCommandFollow(true);
pet->GetCharmInfo()->IsReturning();
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);
}
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 "PlayerbotAIConfig.h"
#include <cmath>
class Player;
class PlayerbotAI;
@@ -123,4 +124,43 @@ class MoveRandomAction : public MovementAction
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

View File

@@ -33,7 +33,7 @@ void HealDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
new NextAction("swiftmend on party", ACTION_CRITICAL_HEAL + 3),
new NextAction("wild growth", ACTION_CRITICAL_HEAL + 2),
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)));
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)));
triggers.push_back(new TriggerNode(
"group heal occasion",
"medium group heal occasion",
NextAction::array(0, new NextAction("tranquility", ACTION_CRITICAL_HEAL + 5), NULL)));
// LOW
@@ -51,7 +51,7 @@ void HealDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 8),
new NextAction("swiftmend on party", ACTION_MEDIUM_HEAL + 7),
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)));
// MEDIUM

View File

@@ -47,8 +47,8 @@ void DpsHunterStrategy::InitTriggers(std::vector<TriggerNode*>& 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("low mana", NextAction::array(0, new NextAction("viper sting", 23), 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("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", 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("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)));
@@ -58,7 +58,7 @@ void DpsHunterStrategy::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("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)));
}

View File

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

View File

@@ -36,8 +36,8 @@ class RaidNaxxActionContext : public NamedObjectContext<Action>
// creators["sapphiron flight position"] = &RaidNaxxActionContext::sapphiron_flight_position;
// creators["sapphiron avoid chill"] = &RaidNaxxActionContext::sapphiron_avoid_chill;
// creators["kel'thuzad choose target"] = &RaidNaxxActionContext::kelthuzad_choose_target;
// creators["kel'thuzad position"] = &RaidNaxxActionContext::kelthuzad_position;
creators["kel'thuzad choose target"] = &RaidNaxxActionContext::kelthuzad_choose_target;
creators["kel'thuzad position"] = &RaidNaxxActionContext::kelthuzad_position;
creators["anub'rekhan choose target"] = &RaidNaxxActionContext::anubrekhan_choose_target;
creators["anub'rekhan position"] = &RaidNaxxActionContext::anubrekhan_position;
@@ -50,8 +50,8 @@ class RaidNaxxActionContext : public NamedObjectContext<Action>
// creators["loatheb choose target"] = &RaidNaxxActionContext::loatheb_choose_target;
}
private:
static Action* go_behind_the_boss(PlayerbotAI* ai) { return new GoBehindTheBossAction(ai); }
static Action* rotate_grobbulus(PlayerbotAI* ai) { return new RotateGrobbulusAction(ai); }
static Action* go_behind_the_boss(PlayerbotAI* ai) { return new GrobbulusGoBehindAction(ai); }
static Action* rotate_grobbulus(PlayerbotAI* ai) { return new GrobbulusRotateAction(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_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_flight_position(PlayerbotAI* ai) { return new SapphironFlightPositionAction(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_position(PlayerbotAI* ai) { return new KelthuzadPositionAction(ai); }
static Action* kelthuzad_choose_target(PlayerbotAI* ai) { return new KelthuzadChooseTargetAction(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_position(PlayerbotAI* ai) { return new AnubrekhanPositionAction(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 "RaidNaxxActions.h"
#include "RaidNaxxStrategy.h"
#include "ScriptedCreature.h"
#include "SharedDefines.h"
#include "raids/naxxramas/RaidNaxxBossHelper.h"
#include <algorithm>
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");
if (!boss) {
@@ -60,22 +64,9 @@ bool GoBehindTheBossAction::Execute(Event event)
// 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()
{
@@ -92,7 +83,7 @@ uint32 RotateAroundTheCenterPointAction::FindNearestWaypoint()
return ret;
}
uint32 RotateGrobbulusAction::GetCurrWaypoint()
uint32 GrobbulusRotateAction::GetCurrWaypoint()
{
Unit* boss = AI_VALUE(Unit*, "boss target");
if (!boss) {
@@ -375,7 +366,7 @@ bool HeiganDanceRangedAction::Execute(Event event) {
// }
// } else {
// 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) {
// Unit* unit = botAI->GetUnit(*i);
// if (!unit)
@@ -401,7 +392,7 @@ bool HeiganDanceRangedAction::Execute(Event event) {
// {
// Unit* razuvious = AI_VALUE2(Unit*, "find target", "instructor razuvious");
// Unit* understudy = AI_VALUE2(Unit*, "find target", "death knight understudy");
// Unit* target = NULL;
// Unit* target = nullptr;
// if (botAI->IsTank(bot)) {
// target = understudy;
// } else {
@@ -492,7 +483,7 @@ bool HeiganDanceRangedAction::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* baron = AI_VALUE2(Unit*, "find target", "baron rivendare");
// Unit* lady = AI_VALUE2(Unit*, "find target", "lady blaumeux");
@@ -621,7 +612,7 @@ bool HeiganDanceRangedAction::Execute(Event event) {
// }
// Group::MemberSlotList const& slots = group->GetMemberSlots();
// int counter = 0;
// Player* playerWithIcebolt = NULL;
// Player* playerWithIcebolt = nullptr;
// float minDistance;
// for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) {
// 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());
// }
// bool KelthuzadChooseTargetAction::Execute(Event event)
// {
// Unit* boss = AI_VALUE2(Unit*, "find target", "kel'thuzad");
// if (!boss) {
// return false;
// }
// BossAI* boss_ai = dynamic_cast<BossAI*>(boss->GetAI());
// EventMap* eventMap = boss_botAI->GetEvents();
// std::pair<float, float> center = {3716.19f, -5106.58f};
// list<ObjectGuid> attackers = context->GetValue<list<ObjectGuid> >("attackers")->Get();
// Unit* target = NULL;
// Unit *target_soldier = NULL, *target_weaver = NULL, *target_abomination = NULL, *target_kelthuzad = NULL, *target_guardian = NULL;
// for (list<ObjectGuid>::iterator i = attackers.begin(); i != attackers.end(); ++i)
// {
// Unit* unit = botAI->GetUnit(*i);
// if (!unit)
// continue;
bool KelthuzadChooseTargetAction::Execute(Event event)
{
if (!helper.UpdateBossAI()) {
return false;
}
GuidVector attackers = context->GetValue<GuidVector>("attackers")->Get();
Unit* target = nullptr;
Unit *target_soldier = nullptr, *target_weaver = nullptr, *target_abomination = nullptr, *target_kelthuzad = nullptr, *target_guardian = nullptr;
for (auto i = attackers.begin(); i != attackers.end(); ++i)
{
Unit* unit = botAI->GetUnit(*i);
if (!unit)
continue;
// if (botAI->EqualLowercaseName(unit->GetName(), "guardian of icecrown")) {
// if (!target_guardian) {
// target_guardian = unit;
// } else if (unit->GetVictim() && target_guardian->GetVictim() &&
// unit->GetVictim()->ToPlayer() && target_guardian->GetVictim()->ToPlayer() &&
// !botAI->IsAssistTank(unit->GetVictim()->ToPlayer()) && botAI->IsAssistTank(target_guardian->GetVictim()->ToPlayer())) {
// target_guardian = unit;
// } else if (unit->GetVictim() && target_guardian->GetVictim() &&
// unit->GetVictim()->ToPlayer() && 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 = unit;
// }
// }
if (botAI->EqualLowercaseName(unit->GetName(), "guardian of icecrown")) {
if (!target_guardian) {
target_guardian = unit;
} else if (unit->GetVictim() && target_guardian->GetVictim() &&
unit->GetVictim()->ToPlayer() && target_guardian->GetVictim()->ToPlayer() &&
!botAI->IsAssistTank(unit->GetVictim()->ToPlayer()) && botAI->IsAssistTank(target_guardian->GetVictim()->ToPlayer())) {
target_guardian = unit;
} else if (unit->GetVictim() && target_guardian->GetVictim() &&
unit->GetVictim()->ToPlayer() && target_guardian->GetVictim()->ToPlayer() &&
!botAI->IsAssistTank(unit->GetVictim()->ToPlayer()) && !botAI->IsAssistTank(target_guardian->GetVictim()->ToPlayer()) &&
target_guardian->GetDistance2d(helper.center.first, helper.center.second) > bot->GetDistance2d(unit)) {
target_guardian = unit;
}
}
// if (unit->GetDistance2d(center.first, center.second) > 30.0f) {
// continue;
// }
// if (bot->GetDistance2d(unit) > sPlayerbotAIConfig.spellDistance) {
// continue;
// }
// if (botAI->EqualLowercaseName(unit->GetName(), "unstoppable abomination")) {
// if (target_abomination == NULL ||
// target_abomination->GetDistance2d(center.first, center.second) > unit->GetDistance2d(center.first, center.second)) {
// target_abomination = unit;
// }
// }
// if (botAI->EqualLowercaseName(unit->GetName(), "soldier of the frozen wastes")) {
// if (target_soldier == NULL ||
// target_soldier->GetDistance2d(center.first, center.second) > unit->GetDistance2d(center.first, center.second)) {
// target_soldier = unit;
// }
// }
// if (botAI->EqualLowercaseName(unit->GetName(), "soul weaver")) {
// if (target_weaver == NULL ||
// target_weaver->GetDistance2d(center.first, center.second) > unit->GetDistance2d(center.first, center.second)) {
// target_weaver = unit;
// }
// }
// if (botAI->EqualLowercaseName(unit->GetName(), "kel'thuzad")) {
// 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) {
// // bot->Yell("Target name: " + target->GetName(), LANG_UNIVERSAL);
// // }
// if (target_kelthuzad && target == target_kelthuzad) {
// return Attack(target, true);
// }
// return Attack(target, false);
// }
if (unit->GetDistance2d(helper.center.first, helper.center.second) > 30.0f) {
continue;
}
if (bot->GetDistance2d(unit) > sPlayerbotAIConfig->spellDistance) {
continue;
}
if (botAI->EqualLowercaseName(unit->GetName(), "unstoppable abomination")) {
if (target_abomination == nullptr ||
target_abomination->GetDistance2d(helper.center.first, helper.center.second) > unit->GetDistance2d(helper.center.first, helper.center.second)) {
target_abomination = unit;
}
}
if (botAI->EqualLowercaseName(unit->GetName(), "soldier of the frozen wastes")) {
if (target_soldier == nullptr ||
target_soldier->GetDistance2d(helper.center.first, helper.center.second) > unit->GetDistance2d(helper.center.first, helper.center.second)) {
target_soldier = unit;
}
}
if (botAI->EqualLowercaseName(unit->GetName(), "soul weaver")) {
if (target_weaver == nullptr ||
target_weaver->GetDistance2d(helper.center.first, helper.center.second) > unit->GetDistance2d(helper.center.first, helper.center.second)) {
target_weaver = unit;
}
}
if (botAI->EqualLowercaseName(unit->GetName(), "kel'thuzad")) {
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)
// {
// Unit* boss = AI_VALUE2(Unit*, "find target", "kel'thuzad");
// if (!boss) {
// return false;
// }
// BossAI* b_ai = dynamic_cast<BossAI*>(boss->GetAI());
// if (!b_ai) {
// return false;
// }
// EventMap *eventMap = b_botAI->GetEvents();
// uint8 phase_mask = eventMap->GetPhaseMask();
// if (phase_mask == 1) {
// if (AI_VALUE(Unit*, "current target") == NULL) {
// return MoveInside(533, 3716.19f, -5106.58f, bot->GetPositionZ(), 3.0f);
// }
// } else if (phase_mask == 2) {
// Unit* shadow_fissure = NULL;
// list<ObjectGuid> units = *context->GetValue<list<ObjectGuid> >("possible targets");
// for (list<ObjectGuid>::iterator 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;
// }
// }
// 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 KelthuzadPositionAction::Execute(Event event)
{
if (!helper.UpdateBossAI()) {
return false;
}
if (helper.IsPhaseOne()) {
if (AI_VALUE(Unit*, "current target") == nullptr) {
return MoveInside(NAXX_MAP_ID, helper.center.first, helper.center.second, bot->GetPositionZ(), 3.0f);
}
} else if (helper.IsPhaseTwo()) {
Unit* shadow_fissure = helper.GetAnyShadowFissure();
if (!shadow_fissure || bot->GetDistance2d(shadow_fissure) > 10.0f) {
float distance, angle;
if (botAI->IsMainTank(bot)) {
if (AI_VALUE2(bool, "has aggro", "current target")) {
return MoveTo(NAXX_MAP_ID, helper.tank_pos.first, helper.tank_pos.second, bot->GetPositionZ());
} else {
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;
}
float dx, dy;
dx = helper.center.first + cos(angle) * distance;
dy = helper.center.second + sin(angle) * distance;
return MoveTo(NAXX_MAP_ID, dx, dy, bot->GetPositionZ());
} 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(NAXX_MAP_ID, helper.assist_tank_pos.first, helper.assist_tank_pos.second, bot->GetPositionZ());
} else {
return false;
}
}
} else {
float dx, dy;
float angle;
if (!botAI->IsRanged(bot)) {
angle = shadow_fissure->GetAngle(helper.center.first, helper.center.second);
} else {
angle = bot->GetAngle(shadow_fissure) + M_PI;
}
dx = shadow_fissure->GetPositionX() + cos(angle) * 10.0f;
dy = shadow_fissure->GetPositionY() + sin(angle) * 10.0f;
return MoveTo(NAXX_MAP_ID, dx, dy, bot->GetPositionZ());
}
}
return false;
}
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();
Unit* target = NULL;
Unit *target_boss = NULL;
Unit* target = nullptr;
Unit *target_boss = nullptr;
vector<Unit*> target_guards;
for (ObjectGuid const guid : attackers)
{
@@ -882,13 +838,13 @@ bool AnubrekhanChooseTargetAction::Execute(Event event)
} else {
if (botAI->IsAssistTank(bot)) {
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;
}
}
} else {
for (Unit* t : target_guards) {
if (target == NULL || target->GetHealthPct() > t->GetHealthPct()) {
if (target == nullptr || target->GetHealthPct() > t->GetHealthPct()) {
target = t;
}
}
@@ -941,8 +897,8 @@ bool AnubrekhanPositionAction::Execute(Event event)
// BossAI* boss_ai = dynamic_cast<BossAI*>(boss->GetAI());
// EventMap* eventMap = boss_botAI->GetEvents();
// list<ObjectGuid> attackers = context->GetValue<list<ObjectGuid> >("attackers")->Get();
// Unit* target = NULL;
// Unit *target_boss = NULL;
// Unit* target = nullptr;
// Unit *target_boss = nullptr;
// vector<Unit*> target_zombies;
// for (list<ObjectGuid>::iterator i = attackers.begin(); i != attackers.end(); ++i)
// {
@@ -971,12 +927,12 @@ bool AnubrekhanPositionAction::Execute(Event event)
// } else {
// for (Unit* t : target_zombies) {
// 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;
// }
// }
// }
// if (target == NULL) {
// if (target == nullptr) {
// target = target_boss;
// }
// }
@@ -1099,9 +1055,9 @@ bool AnubrekhanPositionAction::Execute(Event event)
// BossAI* boss_ai = dynamic_cast<BossAI*>(boss->GetAI());
// EventMap* eventMap = boss_botAI->GetEvents();
// list<ObjectGuid> attackers = context->GetValue<list<ObjectGuid> >("attackers")->Get();
// Unit* target = NULL;
// Unit *target_boss = NULL;
// Unit *target_spore = NULL;
// Unit* target = nullptr;
// Unit *target_boss = nullptr;
// Unit *target_spore = nullptr;
// for (list<ObjectGuid>::iterator i = attackers.begin(); i != attackers.end(); ++i)
// {
// Unit* unit = botAI->GetUnit(*i);

View File

@@ -8,6 +8,7 @@
#include "PlayerbotAI.h"
#include "Playerbots.h"
#include "RaidNaxxScripts.h"
#include "RaidNaxxBossHelper.h"
// just for test
// class TryToGetBossAIAction : public Action
@@ -19,10 +20,10 @@
// virtual bool Execute(Event event);
// };
class GoBehindTheBossAction : public MovementAction
class GrobbulusGoBehindAction : public MovementAction
{
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->delta_angle = delta_angle;
}
@@ -31,67 +32,14 @@ protected:
float distance, delta_angle;
};
// class MoveToPointForceAction : public MovementAction
// {
// 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
class GrobbulusRotateAction : public RotateAroundTheCenterPointAction
{
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;
};
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() {
GrobbulusRotateAction(PlayerbotAI* botAI): RotateAroundTheCenterPointAction(botAI, "rotate grobbulus", 3281.23f, -3310.38f, 35.0f, 8, true, M_PI) {}
virtual bool isUseful() override {
return RotateAroundTheCenterPointAction::isUseful() && botAI->IsMainTank(bot) && AI_VALUE2(bool, "has aggro", "boss target");
}
virtual uint32 GetCurrWaypoint();
protected:
uint32 GetCurrWaypoint() override;
};
class GrobblulusMoveCenterAction : public MoveInsideAction
@@ -254,19 +202,23 @@ protected:
// virtual bool Execute(Event event);
// };
// class KelthuzadChooseTargetAction : public AttackAction
// {
// public:
// KelthuzadChooseTargetAction(PlayerbotAI* ai) : AttackAction(ai, "kel'thuzad choose target") {}
// virtual bool Execute(Event event);
// };
class KelthuzadChooseTargetAction : public AttackAction
{
public:
KelthuzadChooseTargetAction(PlayerbotAI* ai) : AttackAction(ai, "kel'thuzad choose target"), helper(ai) {}
virtual bool Execute(Event event);
private:
KelthuzadBossHelper helper;
};
// class KelthuzadPositionAction : public MovementAction
// {
// public:
// KelthuzadPositionAction(PlayerbotAI* ai) : MovementAction(ai, "kel'thuzad position") {}
// virtual bool Execute(Event event);
// };
class KelthuzadPositionAction : public MovementAction
{
public:
KelthuzadPositionAction(PlayerbotAI* ai) : MovementAction(ai, "kel'thuzad position"), helper(ai) {}
virtual bool Execute(Event event);
private:
KelthuzadBossHelper helper;
};
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;
// }
// float KelthuzadGenericMultiplier::GetValue(Action* action)
// {
// Unit* boss = AI_VALUE2(Unit*, "find target", "kel'thuzad");
// if (!boss) {
// return 1.0f;
// }
// if ((dynamic_cast<AttackLeastHpTargetAction*>(action) ||
// dynamic_cast<TankAssistAction*>(action) ||
// dynamic_cast<CastDebuffSpellOnAttackerAction*>(action) ||
// dynamic_cast<FollowAction*>(action) ||
// dynamic_cast<FleeAction*>(action))) {
// return 0.0f;
// }
// BossAI* boss_ai = dynamic_cast<BossAI*>(boss->GetAI());
// EventMap* eventMap = boss_botAI->GetEvents();
// uint32 curr_phase = eventMap->GetPhaseMask();
// if (curr_phase == 1) {
// if (dynamic_cast<CastTotemAction*>(action) ||
// dynamic_cast<CastShadowfiendAction*>(action) ||
// dynamic_cast<CastRaiseDeadAction*>(action) ||
// dynamic_cast<CastFeignDeathAction*>(action) ||
// dynamic_cast<CastInvisibilityAction*>(action) ||
// dynamic_cast<CastVanishAction*>(action)) {
// return 0.0f;
// }
// }
// if (curr_phase == 2) {
// if (dynamic_cast<CastBlizzardAction*>(action) ||
// dynamic_cast<CastFrostNovaAction*>(action)) {
// return 0.0f;
// }
// }
// return 1.0f;
// }
float KelthuzadGenericMultiplier::GetValue(Action* action)
{
if (!helper.UpdateBossAI()) {
return 1.0f;
}
if ((dynamic_cast<DpsAssistAction*>(action) ||
dynamic_cast<TankAssistAction*>(action) ||
dynamic_cast<CastDebuffSpellOnAttackerAction*>(action) ||
dynamic_cast<FollowAction*>(action) ||
dynamic_cast<FleeAction*>(action))) {
return 0.0f;
}
if (helper.IsPhaseOne()) {
if (dynamic_cast<CastTotemAction*>(action) ||
dynamic_cast<CastShadowfiendAction*>(action) ||
dynamic_cast<CastRaiseDeadAction*>(action) ||
dynamic_cast<CastFeignDeathAction*>(action) ||
dynamic_cast<CastInvisibilityAction*>(action) ||
dynamic_cast<CastVanishAction*>(action)) {
return 0.0f;
}
}
if (helper.IsPhaseTwo()) {
if (dynamic_cast<CastBlizzardAction*>(action) ||
dynamic_cast<CastFrostNovaAction*>(action)) {
return 0.0f;
}
}
return 1.0f;
}
float AnubrekhanGenericMultiplier::GetValue(Action* action)
{

View File

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

View File

@@ -1,8 +1,24 @@
#ifndef _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_grobbulus.h"
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_faerlina.h"
#include "../../../../src/server/scripts/Northrend/Naxxramas/boss_maexxna.h"
#endif
#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_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

View File

@@ -86,13 +86,13 @@ 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)));
// 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(
@@ -131,7 +131,7 @@ void RaidNaxxStrategy::InitMultipliers(std::vector<Multiplier*> &multipliers)
// multipliers.push_back(new ThaddiusGenericMultiplier(ai));
// multipliers.push_back(new SapphironGenericMultiplier(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 FourhorsemanGenericMultiplier(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 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["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_flight(PlayerbotAI* ai) { return new SapphironFlightTrigger(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* anubrekhan(PlayerbotAI* ai) { return new AnubrekhanTrigger(ai); }
// static Trigger* gluth(PlayerbotAI* ai) { return new GluthTrigger(ai); }

View File

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

View File

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

View File

@@ -123,6 +123,7 @@ class TriggerContext : public NamedObjectContext<Trigger>
creators["low aoe heal"] = &TriggerContext::low_aoe_heal;
creators["medium aoe heal"] = &TriggerContext::medium_aoe_heal;
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["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* 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* 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* swimming(PlayerbotAI* botAI) { return new IsSwimmingTrigger(botAI); }
static Trigger* no_possible_targets(PlayerbotAI* botAI) { return new NoPossibleTargetsTrigger(botAI); }

View File

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

View File

@@ -208,7 +208,7 @@ ItemUsage ItemUsageValue::QueryItemUsageForEquip(ItemTemplate const* itemProto)
float oldScore = PlayerbotFactory::CalculateItemScore(oldItemProto->ItemId, bot);
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;
}
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;
};
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

View File

@@ -19,7 +19,7 @@ class FindTargetStrategy
FindTargetStrategy(PlayerbotAI* botAI) : result(nullptr), botAI(botAI) { }
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);
protected:

View File

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