Skip to content
6 changes: 6 additions & 0 deletions src/Ai/Class/Paladin/Action/PaladinActions.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,12 @@ class CastHandOfReckoningAction : public CastSpellAction
CastHandOfReckoningAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "hand of reckoning") {}
};

class CastHandOfSalvationAction : public CastSpellAction
{
public:
CastHandOfSalvationAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "hand of salvation") {}
};

class CastRighteousDefenseAction : public CastSpellAction
{
public:
Expand Down
3 changes: 3 additions & 0 deletions src/Ai/Raid/RaidStrategyContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "RaidUlduarStrategy.h"
#include "RaidOnyxiaStrategy.h"
#include "RaidIccStrategy.h"
#include "RaidZGStrategy.h"

class RaidStrategyContext : public NamedObjectContext<Strategy>
{
Expand All @@ -34,6 +35,7 @@ class RaidStrategyContext : public NamedObjectContext<Strategy>
creators["ssc"] = &RaidStrategyContext::ssc;
creators["tempestkeep"] = &RaidStrategyContext::tempestkeep;
creators["zulaman"] = &RaidStrategyContext::zulaman;
creators["zg"] = &RaidStrategyContext::zg;
creators["wotlk-os"] = &RaidStrategyContext::wotlk_os;
creators["wotlk-eoe"] = &RaidStrategyContext::wotlk_eoe;
creators["voa"] = &RaidStrategyContext::voa;
Expand All @@ -53,6 +55,7 @@ class RaidStrategyContext : public NamedObjectContext<Strategy>
static Strategy* ssc(PlayerbotAI* botAI) { return new RaidSSCStrategy(botAI); }
static Strategy* tempestkeep(PlayerbotAI* botAI) { return new RaidTempestKeepStrategy(botAI); }
static Strategy* zulaman(PlayerbotAI* botAI) { return new RaidZulAmanStrategy(botAI); }
static Strategy* zg(PlayerbotAI* botAI) { return new RaidZGStrategy(botAI); }
static Strategy* wotlk_os(PlayerbotAI* botAI) { return new RaidOsStrategy(botAI); }
static Strategy* wotlk_eoe(PlayerbotAI* botAI) { return new RaidEoEStrategy(botAI); }
static Strategy* voa(PlayerbotAI* botAI) { return new RaidVoAStrategy(botAI); }
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#pragma once

#include "Unit.h"
#include "Player.h"
#include "Spell.h"

#include "GridNotifiers.h"
// Necessary due to a poor implementation by AC.
#include "GridNotifiersImpl.h"

#include "Cell.h"
#include "CellImpl.h"

#include "../definition/enum/BloodlordMandokirEnum.h"


#include "PlayerbotAIConfig.h"

class BloodlordMandokirAssistant
{
public:
BloodlordMandokirAssistant() = default;
~BloodlordMandokirAssistant() = default;

BloodlordMandokirAssistant(const BloodlordMandokirAssistant&) = default;
BloodlordMandokirAssistant& operator=(const BloodlordMandokirAssistant&) = default;

BloodlordMandokirAssistant(BloodlordMandokirAssistant&&) = default;
BloodlordMandokirAssistant& operator=(BloodlordMandokirAssistant&&) = default;

[[nodiscard]] bool isInCombatWithBloodlordMandokir(Player& bot) const noexcept
{
const Unit* const BloodlordMandokir = this->findActiveBoss(bot);

if (BloodlordMandokir == nullptr)
{
return false;
}

return bot.IsInCombatWith(BloodlordMandokir) || BloodlordMandokir->IsInCombatWith(&bot);
}

[[nodiscard]] Creature* findActiveBoss(Player& bot) const noexcept
{
return bot.FindNearestCreature(uint32_t(BloodlordMandokirEnum::ENTRY), PlayerbotAIConfig::instance().sightDistance, true);
}

[[nodiscard]] bool isAtSafeDistanceFromBloodlordMandokir(Player& bot) const noexcept
{
const Unit* const BloodlordMandokir = this->findActiveBoss(bot);

if (BloodlordMandokir == nullptr)
{
return true;
}

const float distanceToBloodlordMandokir = bot.GetExactDist2d(BloodlordMandokir->GetPositionX(), BloodlordMandokir->GetPositionY());

return distanceToBloodlordMandokir > float(BloodlordMandokirEnum::SPELL_WHIRLWIND_SAFE_DISTANCE);
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once

#include <cstdint>

enum class BloodlordMandokirEnum : uint32_t
{
ENTRY = 11382u,
SPELL_THREATENING_GAZE = 24314u,
SPELL_WHIRLWIND = 13736u,
SPELL_WHIRLWIND_SAFE_DISTANCE = 15u
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#pragma once

#include "Spell.h"
#include "AiObjectContext.h"
#include "MovementActions.h"
#include "PlayerbotAI.h"

#include "raid/leader/RaidLeaderRegistry.h"

class BloodlordMandokirWhirlwindAction : public MovementAction
{
public:
BloodlordMandokirWhirlwindAction(
PlayerbotAI* botAI,
const std::string name = "bloodlord mandokir whirlwind"
) : MovementAction(botAI, name) {}

bool Execute(Event) override
{
if (this->bot == nullptr)
{
return false;
}

const uint32_t instanceId = this->bot->GetInstanceId();
RaidLeaderRegistry& raidRegistry = RaidLeaderRegistry::GetInstance();
const ZulGurubRaidLeader& raidLeader = raidRegistry.getOrBind<ZulGurubRaidLeader>(instanceId, MAP_ZUL_GURUB);
const BloodlordMandokirAssistant& bloodlordMandokirAssistant = raidLeader.getBloodlordMandokirAssistant();
Unit* const bloodlordMandokir = bloodlordMandokirAssistant.findActiveBoss(*this->bot);

if (bloodlordMandokir == nullptr)
{
return false;
}

const float safeDistance = float(BloodlordMandokirEnum::SPELL_WHIRLWIND_SAFE_DISTANCE) - this->bot->GetDistance2d(bloodlordMandokir);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable should be named distanceFromSafety or safeDistanceDelta


if (safeDistance <= 0.0f)
{
return false;
}

this->MoveAway(bloodlordMandokir, safeDistance);

return true;
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#pragma once

#include "AiObjectContext.h"
#include "BloodlordMandokirWhirlwindAction.h"
#include "MovementActions.h"
#include "Multiplier.h"
#include "PlayerbotAI.h"
#include "Value.h"

#include "GenericSpellActions.h"
#include "raid/leader/RaidLeaderRegistry.h"


class BloodlordMandokirWhirlwindMultiplier : public Multiplier
{
public:
BloodlordMandokirWhirlwindMultiplier(PlayerbotAI* botAI) : Multiplier(botAI, "bloodlord mandokir whirlwind") {}

float GetValue(Action& action) override
{
if (this->bot == nullptr)
{
return 0.0f;
}

const uint32_t instanceId = this->bot->GetInstanceId();
RaidLeaderRegistry& raidRegistry = RaidLeaderRegistry::GetInstance();
const ZulGurubRaidLeader& raidLeader = raidRegistry.getOrBind<ZulGurubRaidLeader>(instanceId, MAP_ZUL_GURUB);
const BloodlordMandokirAssistant& bloodlordMandokirAssistant = raidLeader.getBloodlordMandokirAssistant();

const Creature* const bloodlordMandokir = bloodlordMandokirAssistant.findActiveBoss(*this->bot);

if (bloodlordMandokir == nullptr)
{
return 1.0f;
}

if (bloodlordMandokir->HasAura(uint32_t(BloodlordMandokirEnum::SPELL_WHIRLWIND)) == false)
{
return 1.0f;
}

if (bloodlordMandokirAssistant.isAtSafeDistanceFromBloodlordMandokir(*this->bot) == true)
{
return 1.0f;
}

const BloodlordMandokirWhirlwindAction* const movementAction = dynamic_cast<const BloodlordMandokirWhirlwindAction*>(&action);

if (movementAction != nullptr)
{
return 1.0f;
}

return 0.0f;
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
#pragma once

#include "AiObjectContext.h"
#include "BloodlordMandokir/assistant/BloodlordMandokirAssistant.h"
#include "PlayerbotAI.h"
#include "Trigger.h"

#include "raid/leader/RaidLeaderRegistry.h"

class BloodlordMandokirWhirlwindTrigger : public Trigger
{
public:
BloodlordMandokirWhirlwindTrigger(PlayerbotAI* botAI) : Trigger(botAI, "bloodlord mandokir whirlwind") {}

bool IsActive() override
{
if (this->bot == nullptr)
{
return false;
}

if (this->botAI == nullptr)
{
return false;
}

const uint32_t instanceId = this->bot->GetInstanceId();
RaidLeaderRegistry& raidRegistry = RaidLeaderRegistry::GetInstance();
const ZulGurubRaidLeader& raidLeader = raidRegistry.getOrBind<ZulGurubRaidLeader>(instanceId, MAP_ZUL_GURUB);
const BloodlordMandokirAssistant& bloodlordMandokirAssistant = raidLeader.getBloodlordMandokirAssistant();

if (bloodlordMandokirAssistant.isInCombatWithBloodlordMandokir(*this->bot) == false)
{
return false;
}

const Creature* const bloodlordMandokir = bloodlordMandokirAssistant.findActiveBoss(*this->bot);

if (bloodlordMandokir == nullptr)
{
return false;
}

if (bloodlordMandokir->HasAura(uint32_t(BloodlordMandokirEnum::SPELL_WHIRLWIND)) == false)
{
return false;
}

if (bloodlordMandokirAssistant.isAtSafeDistanceFromBloodlordMandokir(*this->bot) == true)
{
return false;
}

return true;
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#pragma once

#include "Unit.h"
#include "Player.h"
#include "Spell.h"

#include "GridNotifiers.h"
// Necessary due to a poor implementation by AC.
#include "GridNotifiersImpl.h"

#include "Cell.h"
#include "CellImpl.h"

#include "../definition/enum/GrilekTheWandererEnum.h"
#include <unordered_map>


#include "PlayerbotAIConfig.h"

class GrilekTheWandererAssistant
{
public:
GrilekTheWandererAssistant() = default;
~GrilekTheWandererAssistant() = default;

GrilekTheWandererAssistant(const GrilekTheWandererAssistant&) = default;
GrilekTheWandererAssistant& operator=(const GrilekTheWandererAssistant&) = default;

GrilekTheWandererAssistant(GrilekTheWandererAssistant&&) = default;
GrilekTheWandererAssistant& operator=(GrilekTheWandererAssistant&&) = default;

[[nodiscard]] bool isInCombatWithGrilekTheWanderer(Player& bot) const noexcept
{
const Unit* const grilekTheWanderer = this->findActiveBoss(bot);

if (grilekTheWanderer == nullptr)
{
return false;
}

return bot.IsInCombatWith(grilekTheWanderer) || grilekTheWanderer->IsInCombatWith(&bot);
}

[[nodiscard]] Creature* findActiveBoss(Player& bot) const noexcept
{
return bot.FindNearestCreature(uint32_t(GrilekTheWandererEnum::ENTRY), PlayerbotAIConfig::instance().sightDistance, true);
}

// [[nodiscard]] Creature* findActiveBoss(Player& bot) const noexcept
// {
// if (!bot.IsInCombat())
// {
// return nullptr;
// }

// Map* map = bot.GetMap();

// if (map == nullptr)
// {
// return nullptr;
// }

// const std::unordered_multimap<ObjectGuid::LowType, Creature*> store = map->GetCreatureBySpawnIdStore();
// const std::unordered_multimap<ObjectGuid::LowType, Creature*>::const_iterator it = store.find(uint32_t(GrilekTheWandererEnum::ENTRY));
// const std::unordered_multimap<ObjectGuid::LowType, Creature*>::const_iterator end = store.end();

// if (it == end)
// {
// LOG_ERROR("playerbots")

// return nullptr;
// }

// Creature* grilekTheWanderer = it->second;

// if (grilekTheWanderer == nullptr)
// {
// LOG_ERROR("playerbots", "Grilek not found in map.");

// return nullptr;
// }

// if (!grilekTheWanderer->IsAlive())
// {
// LOG_ERROR("playerbots", "Grilek dead");
// return nullptr;
// }

// if (grilekTheWanderer->GetEntry() != uint32_t(GrilekTheWandererEnum::ENTRY))
// {
// LOG_ERROR("playerbots", "Grilek entry does not match.");

// return nullptr;
// }

// return grilekTheWanderer;
// };

[[nodiscard]] bool isAtSafeDistanceFromGrilekTheWanderer(Player& bot) const noexcept
{
const Unit* const grilekTheWanderer = this->findActiveBoss(bot);

if (grilekTheWanderer == nullptr)
{
return true;
}

const float distanceToGrilekTheWanderer = bot.GetExactDist2d(grilekTheWanderer->GetPositionX(), grilekTheWanderer->GetPositionY());

return distanceToGrilekTheWanderer > float(GrilekTheWandererEnum::AVATAR_SAFE_DISTANCE);
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once

#include <cstdint>

enum class GrilekTheWandererEnum : uint32_t
{
ENTRY = 15082u,
SPELL_AVATAR = 24646u,
AVATAR_SAFE_DISTANCE = 15u,
};
Loading