mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
- Added raid cheat to configuration to add posibility to turn off (#1465)
- Added General Vezax strategy
This commit is contained in:
@@ -501,9 +501,10 @@ AiPlayerbot.AutoGearScoreLimit = 0
|
||||
# "mana" (bots have infinite mana)
|
||||
# "power" (bots have infinite energy, rage, and runic power)
|
||||
# "taxi" (bots may use all flight paths, though they will not actually learn them)
|
||||
# "raid" (bots use cheats implemented into raid strategies)
|
||||
# To use multiple cheats, separate them by commas below (e.g., to enable all, use "gold,health,mana,power,taxi")
|
||||
# Default: taxi is enabled
|
||||
AiPlayerbot.BotCheats = "taxi"
|
||||
AiPlayerbot.BotCheats = "taxi,raid"
|
||||
|
||||
#
|
||||
#
|
||||
|
||||
@@ -448,7 +448,7 @@ bool PlayerbotAIConfig::Initialize()
|
||||
}
|
||||
|
||||
botCheats.clear();
|
||||
LoadListString<std::vector<std::string>>(sConfigMgr->GetOption<std::string>("AiPlayerbot.BotCheats", "taxi"),
|
||||
LoadListString<std::vector<std::string>>(sConfigMgr->GetOption<std::string>("AiPlayerbot.BotCheats", "taxi,raid"),
|
||||
botCheats);
|
||||
|
||||
botCheatMask = 0;
|
||||
@@ -463,6 +463,8 @@ bool PlayerbotAIConfig::Initialize()
|
||||
botCheatMask |= (uint32)BotCheatMask::mana;
|
||||
if (std::find(botCheats.begin(), botCheats.end(), "power") != botCheats.end())
|
||||
botCheatMask |= (uint32)BotCheatMask::power;
|
||||
if (std::find(botCheats.begin(), botCheats.end(), "raid") != botCheats.end())
|
||||
botCheatMask |= (uint32)BotCheatMask::raid;
|
||||
|
||||
LoadListString<std::vector<std::string>>(sConfigMgr->GetOption<std::string>("AiPlayerbot.AllowedLogFiles", ""),
|
||||
allowedLogFiles);
|
||||
|
||||
@@ -22,7 +22,8 @@ enum class BotCheatMask : uint32
|
||||
health = 4,
|
||||
mana = 8,
|
||||
power = 16,
|
||||
maxMask = 32
|
||||
raid = 32,
|
||||
maxMask = 64
|
||||
};
|
||||
|
||||
enum class HealingManaEfficiency : uint8
|
||||
|
||||
@@ -53,6 +53,9 @@ BotCheatMask CheatAction::GetCheatMask(std::string const cheat)
|
||||
if (cheat == "power")
|
||||
return BotCheatMask::power;
|
||||
|
||||
if (cheat == "raid")
|
||||
return BotCheatMask::raid;
|
||||
|
||||
return BotCheatMask::none;
|
||||
}
|
||||
|
||||
@@ -70,6 +73,8 @@ std::string const CheatAction::GetCheatName(BotCheatMask cheatMask)
|
||||
return "mana";
|
||||
case BotCheatMask::power:
|
||||
return "power";
|
||||
case BotCheatMask::raid:
|
||||
return "raid";
|
||||
default:
|
||||
return "none";
|
||||
}
|
||||
|
||||
@@ -62,6 +62,9 @@ public:
|
||||
creators["mimiron rocket strike action"] = &RaidUlduarActionContext::mimiron_rocket_strike_action;
|
||||
creators["mimiron phase 4 mark dps action"] = &RaidUlduarActionContext::mimiron_phase_4_mark_dps_action;
|
||||
creators["mimiron cheat action"] = &RaidUlduarActionContext::mimiron_cheat_action;
|
||||
creators["vezax cheat action"] = &RaidUlduarActionContext::vezax_cheat_action;
|
||||
creators["vezax shadow crash action"] = &RaidUlduarActionContext::vezax_shadow_crash_action;
|
||||
creators["vezax mark of the faceless action"] = &RaidUlduarActionContext::vezax_mark_of_the_faceless_action;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -111,6 +114,9 @@ private:
|
||||
static Action* mimiron_rocket_strike_action(PlayerbotAI* ai) { return new MimironRocketStrikeAction(ai); }
|
||||
static Action* mimiron_phase_4_mark_dps_action(PlayerbotAI* ai) { return new MimironPhase4MarkDpsAction(ai); }
|
||||
static Action* mimiron_cheat_action(PlayerbotAI* ai) { return new MimironCheatAction(ai); }
|
||||
static Action* vezax_cheat_action(PlayerbotAI* ai) { return new VezaxCheatAction(ai); }
|
||||
static Action* vezax_shadow_crash_action(PlayerbotAI* ai) { return new VezaxShadowCrashAction(ai); }
|
||||
static Action* vezax_mark_of_the_faceless_action(PlayerbotAI* ai) { return new VezaxMarkOfTheFacelessAction(ai); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -42,7 +42,6 @@ const Position ULDUAR_KOLOGARN_RESTORE_POSITION = Position(1764.3749f, -24.02903
|
||||
const Position ULDUAR_KOLOGARN_EYEBEAM_LEFT_POSITION = Position(1781.2051f, 9.34402f, 449.0f, 0.00087690353f);
|
||||
const Position ULDUAR_KOLOGARN_EYEBEAM_RIGHT_POSITION = Position(1763.2561f, -24.44305f, 449.0f, 0.00087690353f);
|
||||
const Position ULDUAR_THORIM_JUMP_START_POINT = Position(2137.137f, -291.19025f, 438.24753f, 1.7059844f);
|
||||
const Position ULDUAR_THORIM_JUMP_END_POINT = Position(2137.8818f, -278.18942f, 419.66653f);
|
||||
|
||||
bool FlameLeviathanVehicleAction::Execute(Event event)
|
||||
{
|
||||
@@ -484,12 +483,12 @@ bool RazorscaleAvoidDevouringFlameAction::isUseful()
|
||||
float distance = bot->GetDistance2d(unit);
|
||||
if (distance < safeDistance)
|
||||
{
|
||||
return true; // Bot is within the danger distance
|
||||
return true; // Bot is within the danger distance
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false; // No nearby flames or bot is at a safe distance
|
||||
return false; // No nearby flames or bot is at a safe distance
|
||||
}
|
||||
|
||||
bool RazorscaleAvoidSentinelAction::Execute(Event event)
|
||||
@@ -529,17 +528,17 @@ bool RazorscaleAvoidSentinelAction::Execute(Event event)
|
||||
Unit* mainTankUnit = AI_VALUE(Unit*, "main tank");
|
||||
Player* mainTank = mainTankUnit ? mainTankUnit->ToPlayer() : nullptr;
|
||||
|
||||
if (mainTank && !GET_PLAYERBOT_AI(mainTank)) // Main tank is a real player
|
||||
if (mainTank && !GET_PLAYERBOT_AI(mainTank)) // Main tank is a real player
|
||||
{
|
||||
// Iterate through the first 3 bot tanks to assign the Skull marker
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
if (botAI->IsAssistTankOfIndex(bot, i) && GET_PLAYERBOT_AI(bot)) // Bot is a valid tank
|
||||
if (botAI->IsAssistTankOfIndex(bot, i) && GET_PLAYERBOT_AI(bot)) // Bot is a valid tank
|
||||
{
|
||||
Group* group = bot->GetGroup();
|
||||
if (group && lowestHealthSentinel)
|
||||
{
|
||||
int8 skullIndex = 7; // Skull
|
||||
int8 skullIndex = 7; // Skull
|
||||
ObjectGuid currentSkullTarget = group->GetTargetIcon(skullIndex);
|
||||
|
||||
// If there's no skull set yet, or the skull is on a different target, set the sentinel
|
||||
@@ -548,16 +547,16 @@ bool RazorscaleAvoidSentinelAction::Execute(Event event)
|
||||
group->SetTargetIcon(skullIndex, bot->GetGUID(), lowestHealthSentinel->GetGUID());
|
||||
}
|
||||
}
|
||||
break; // Stop after finding the first valid bot tank
|
||||
break; // Stop after finding the first valid bot tank
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (isMainTank && lowestHealthSentinel) // Bot is the main tank
|
||||
else if (isMainTank && lowestHealthSentinel) // Bot is the main tank
|
||||
{
|
||||
Group* group = bot->GetGroup();
|
||||
if (group)
|
||||
{
|
||||
int8 skullIndex = 7; // Skull
|
||||
int8 skullIndex = 7; // Skull
|
||||
ObjectGuid currentSkullTarget = group->GetTargetIcon(skullIndex);
|
||||
|
||||
// If there's no skull set yet, or the skull is on a different target, set the sentinel
|
||||
@@ -568,8 +567,7 @@ bool RazorscaleAvoidSentinelAction::Execute(Event event)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return movedAway; // Return true if moved
|
||||
return movedAway; // Return true if moved
|
||||
}
|
||||
|
||||
bool RazorscaleAvoidSentinelAction::isUseful()
|
||||
@@ -585,13 +583,13 @@ bool RazorscaleAvoidSentinelAction::isUseful()
|
||||
}
|
||||
|
||||
// If the main tank is a human, check if this bot is one of the first three valid bot tanks
|
||||
if (mainTank && !GET_PLAYERBOT_AI(mainTank)) // Main tank is a human player
|
||||
if (mainTank && !GET_PLAYERBOT_AI(mainTank)) // Main tank is a human player
|
||||
{
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
if (botAI->IsAssistTankOfIndex(bot, i) && GET_PLAYERBOT_AI(bot)) // Bot is a valid tank
|
||||
if (botAI->IsAssistTankOfIndex(bot, i) && GET_PLAYERBOT_AI(bot)) // Bot is a valid tank
|
||||
{
|
||||
return true; // This bot should assist with marking
|
||||
return true; // This bot should assist with marking
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -654,7 +652,8 @@ bool RazorscaleAvoidWhirlwindAction::isUseful()
|
||||
Unit* unit = botAI->GetUnit(npc);
|
||||
if (unit && unit->GetEntry() == RazorscaleBossHelper::UNIT_DARK_RUNE_SENTINEL)
|
||||
{
|
||||
if (unit->HasAura(RazorscaleBossHelper::SPELL_SENTINEL_WHIRLWIND) || unit->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
|
||||
if (unit->HasAura(RazorscaleBossHelper::SPELL_SENTINEL_WHIRLWIND) ||
|
||||
unit->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
|
||||
{
|
||||
if (bot->GetDistance2d(unit) < radius)
|
||||
{
|
||||
@@ -679,11 +678,11 @@ bool RazorscaleIgnoreBossAction::isUseful()
|
||||
if (boss->GetPositionZ() >= RazorscaleBossHelper::RAZORSCALE_FLYING_Z_THRESHOLD)
|
||||
{
|
||||
// Check if the bot is outside the designated area
|
||||
if (bot->GetDistance2d(
|
||||
RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_X,
|
||||
RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_Y) > RazorscaleBossHelper::RAZORSCALE_ARENA_RADIUS + 25.0f)
|
||||
if (bot->GetDistance2d(RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_X,
|
||||
RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_Y) >
|
||||
RazorscaleBossHelper::RAZORSCALE_ARENA_RADIUS + 25.0f)
|
||||
{
|
||||
return true; // Movement to the center is the top priority for all bots
|
||||
return true; // Movement to the center is the top priority for all bots
|
||||
}
|
||||
|
||||
if (!botAI->IsTank(bot))
|
||||
@@ -698,11 +697,11 @@ bool RazorscaleIgnoreBossAction::isUseful()
|
||||
}
|
||||
|
||||
// Check if the boss is already set as the moon marker
|
||||
int8 moonIndex = 4; // Moon marker index
|
||||
int8 moonIndex = 4; // Moon marker index
|
||||
ObjectGuid currentMoonTarget = group->GetTargetIcon(moonIndex);
|
||||
if (currentMoonTarget == boss->GetGUID())
|
||||
{
|
||||
return false; // Moon marker is already correctly set, no further action needed
|
||||
return false; // Moon marker is already correctly set, no further action needed
|
||||
}
|
||||
|
||||
// Proceed to tank-specific logic
|
||||
@@ -716,13 +715,13 @@ bool RazorscaleIgnoreBossAction::isUseful()
|
||||
}
|
||||
|
||||
// If the main tank is a human, check if this bot is the lowest-indexed bot tank
|
||||
if (mainTank && !GET_PLAYERBOT_AI(mainTank)) // Main tank is a human player
|
||||
if (mainTank && !GET_PLAYERBOT_AI(mainTank)) // Main tank is a human player
|
||||
{
|
||||
for (int i = 0; i < 3; ++i) // Only iterate through the first 3 indexes
|
||||
for (int i = 0; i < 3; ++i) // Only iterate through the first 3 indexes
|
||||
{
|
||||
if (botAI->IsAssistTankOfIndex(bot, i) && GET_PLAYERBOT_AI(bot)) // Valid bot tank
|
||||
if (botAI->IsAssistTankOfIndex(bot, i) && GET_PLAYERBOT_AI(bot)) // Valid bot tank
|
||||
{
|
||||
return true; // This bot should assign the marker
|
||||
return true; // This bot should assign the marker
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -751,18 +750,13 @@ bool RazorscaleIgnoreBossAction::Execute(Event event)
|
||||
}
|
||||
|
||||
// Check if the bot is outside the designated area and move inside first
|
||||
if (bot->GetDistance2d(
|
||||
RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_X,
|
||||
RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_Y) > RazorscaleBossHelper::RAZORSCALE_ARENA_RADIUS + 25.0f)
|
||||
if (bot->GetDistance2d(RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_X,
|
||||
RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_Y) >
|
||||
RazorscaleBossHelper::RAZORSCALE_ARENA_RADIUS + 25.0f)
|
||||
{
|
||||
return MoveInside(
|
||||
ULDUAR_MAP_ID,
|
||||
RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_X,
|
||||
RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_Y,
|
||||
bot->GetPositionZ(),
|
||||
RazorscaleBossHelper::RAZORSCALE_ARENA_RADIUS - 10.0f,
|
||||
MovementPriority::MOVEMENT_NORMAL
|
||||
);
|
||||
return MoveInside(ULDUAR_MAP_ID, RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_X,
|
||||
RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_Y, bot->GetPositionZ(),
|
||||
RazorscaleBossHelper::RAZORSCALE_ARENA_RADIUS - 10.0f, MovementPriority::MOVEMENT_NORMAL);
|
||||
}
|
||||
|
||||
if (!botAI->IsTank(bot))
|
||||
@@ -775,7 +769,7 @@ bool RazorscaleIgnoreBossAction::Execute(Event event)
|
||||
ObjectGuid currentMoonTarget = group->GetTargetIcon(moonIndex);
|
||||
if (currentMoonTarget == boss->GetGUID())
|
||||
{
|
||||
return false; // Moon marker is already correctly set
|
||||
return false; // Moon marker is already correctly set
|
||||
}
|
||||
|
||||
// Get the main tank and determine role
|
||||
@@ -783,33 +777,28 @@ bool RazorscaleIgnoreBossAction::Execute(Event event)
|
||||
Player* mainTank = mainTankUnit ? mainTankUnit->ToPlayer() : nullptr;
|
||||
|
||||
// If the main tank is a human, assign the moon marker using the lowest-indexed bot tank
|
||||
if (mainTank && !GET_PLAYERBOT_AI(mainTank)) // Main tank is a real player
|
||||
if (mainTank && !GET_PLAYERBOT_AI(mainTank)) // Main tank is a real player
|
||||
{
|
||||
for (int i = 0; i < 3; ++i) // Only iterate through the first 3 indexes
|
||||
for (int i = 0; i < 3; ++i) // Only iterate through the first 3 indexes
|
||||
{
|
||||
if (botAI->IsAssistTankOfIndex(bot, i) && GET_PLAYERBOT_AI(bot)) // Bot is a valid tank
|
||||
if (botAI->IsAssistTankOfIndex(bot, i) && GET_PLAYERBOT_AI(bot)) // Bot is a valid tank
|
||||
{
|
||||
group->SetTargetIcon(moonIndex, bot->GetGUID(), boss->GetGUID());
|
||||
SetNextMovementDelay(1000);
|
||||
break; // Assign the moon marker and stop
|
||||
break; // Assign the moon marker and stop
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mainTankUnit == bot) // If this bot is the main tank
|
||||
else if (mainTankUnit == bot) // If this bot is the main tank
|
||||
{
|
||||
group->SetTargetIcon(moonIndex, bot->GetGUID(), boss->GetGUID());
|
||||
SetNextMovementDelay(1000);
|
||||
}
|
||||
|
||||
// Tanks move inside the arena
|
||||
return MoveInside(
|
||||
ULDUAR_MAP_ID,
|
||||
RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_X,
|
||||
RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_Y,
|
||||
bot->GetPositionZ(),
|
||||
RazorscaleBossHelper::RAZORSCALE_ARENA_RADIUS - 10.0f,
|
||||
MovementPriority::MOVEMENT_NORMAL
|
||||
);
|
||||
return MoveInside(ULDUAR_MAP_ID, RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_X,
|
||||
RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_Y, bot->GetPositionZ(),
|
||||
RazorscaleBossHelper::RAZORSCALE_ARENA_RADIUS - 10.0f, MovementPriority::MOVEMENT_NORMAL);
|
||||
}
|
||||
|
||||
bool RazorscaleGroundedAction::isUseful()
|
||||
@@ -875,9 +864,8 @@ bool RazorscaleGroundedAction::isUseful()
|
||||
float bossY = boss->GetPositionY();
|
||||
float bossZ = boss->GetPositionZ();
|
||||
|
||||
bool atInitialLandingPosition = (fabs(bossX - landingX) < 2.0f) &&
|
||||
(fabs(bossY - landingY) < 2.0f) &&
|
||||
(fabs(bossZ - landingZ) < 1.0f);
|
||||
bool atInitialLandingPosition =
|
||||
(fabs(bossX - landingX) < 2.0f) && (fabs(bossY - landingY) < 2.0f) && (fabs(bossZ - landingZ) < 1.0f);
|
||||
|
||||
constexpr float initialLandingRadius = 14.0f;
|
||||
constexpr float normalRadius = 12.0f;
|
||||
@@ -891,7 +879,8 @@ bool RazorscaleGroundedAction::isUseful()
|
||||
return distanceToAdjustedCenter > initialLandingRadius;
|
||||
}
|
||||
|
||||
float distanceToCenter = bot->GetDistance2d(RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_X, RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_Y);
|
||||
float distanceToCenter = bot->GetDistance2d(RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_X,
|
||||
RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_Y);
|
||||
return distanceToCenter > normalRadius;
|
||||
}
|
||||
|
||||
@@ -911,12 +900,12 @@ bool RazorscaleGroundedAction::Execute(Event event)
|
||||
Unit* mainTankUnit = AI_VALUE(Unit*, "main tank");
|
||||
Player* mainTank = mainTankUnit ? mainTankUnit->ToPlayer() : nullptr;
|
||||
|
||||
if (mainTank && !GET_PLAYERBOT_AI(mainTank)) // Main tank is a human player
|
||||
if (mainTank && !GET_PLAYERBOT_AI(mainTank)) // Main tank is a human player
|
||||
{
|
||||
// Iterate through the first 3 bot tanks to handle the moon marker
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
if (botAI->IsAssistTankOfIndex(bot, i) && GET_PLAYERBOT_AI(bot)) // Bot is a valid tank
|
||||
if (botAI->IsAssistTankOfIndex(bot, i) && GET_PLAYERBOT_AI(bot)) // Bot is a valid tank
|
||||
{
|
||||
int8 moonIndex = 4;
|
||||
ObjectGuid currentMoonTarget = group->GetTargetIcon(moonIndex);
|
||||
@@ -931,7 +920,7 @@ bool RazorscaleGroundedAction::Execute(Event event)
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (botAI->IsMainTank(bot)) // Bot is the main tank
|
||||
else if (botAI->IsMainTank(bot)) // Bot is the main tank
|
||||
{
|
||||
int8 moonIndex = 4;
|
||||
ObjectGuid currentMoonTarget = group->GetTargetIcon(moonIndex);
|
||||
@@ -961,33 +950,22 @@ bool RazorscaleGroundedAction::Execute(Event event)
|
||||
float bossY = boss->GetPositionY();
|
||||
float bossZ = boss->GetPositionZ();
|
||||
|
||||
bool atInitialLandingPosition = (fabs(bossX - landingX) < 2.0f) &&
|
||||
(fabs(bossY - landingY) < 2.0f) &&
|
||||
(fabs(bossZ - landingZ) < 1.0f);
|
||||
bool atInitialLandingPosition =
|
||||
(fabs(bossX - landingX) < 2.0f) && (fabs(bossY - landingY) < 2.0f) && (fabs(bossZ - landingZ) < 1.0f);
|
||||
|
||||
if (atInitialLandingPosition)
|
||||
{
|
||||
// If at the initial landing position, use 12-yard radius with a
|
||||
// 20 yard offset on the Y axis so everyone is behind the boss
|
||||
return MoveInside(
|
||||
ULDUAR_MAP_ID,
|
||||
RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_X,
|
||||
RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_Y - 20.0f,
|
||||
bot->GetPositionZ(),
|
||||
RazorscaleBossHelper::RAZORSCALE_ARENA_RADIUS - 12.0f,
|
||||
MovementPriority::MOVEMENT_COMBAT
|
||||
);
|
||||
return MoveInside(ULDUAR_MAP_ID, RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_X,
|
||||
RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_Y - 20.0f, bot->GetPositionZ(),
|
||||
RazorscaleBossHelper::RAZORSCALE_ARENA_RADIUS - 12.0f, MovementPriority::MOVEMENT_COMBAT);
|
||||
}
|
||||
|
||||
// Otherwise, move inside a 12-yard radius around the arena center
|
||||
return MoveInside(
|
||||
ULDUAR_MAP_ID,
|
||||
RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_X,
|
||||
RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_Y,
|
||||
bot->GetPositionZ(),
|
||||
12.0f,
|
||||
MovementPriority::MOVEMENT_COMBAT
|
||||
);
|
||||
return MoveInside(ULDUAR_MAP_ID, RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_X,
|
||||
RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_Y, bot->GetPositionZ(), 12.0f,
|
||||
MovementPriority::MOVEMENT_COMBAT);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1064,9 +1042,7 @@ bool RazorscaleHarpoonAction::Execute(Event event)
|
||||
float botDist = bot->GetDistance(closestHarpoon);
|
||||
if (botDist > INTERACTION_DISTANCE - 1.0f)
|
||||
{
|
||||
return MoveTo(bot->GetMapId(),
|
||||
closestHarpoon->GetPositionX(),
|
||||
closestHarpoon->GetPositionY(),
|
||||
return MoveTo(bot->GetMapId(), closestHarpoon->GetPositionX(), closestHarpoon->GetPositionY(),
|
||||
closestHarpoon->GetPositionZ());
|
||||
}
|
||||
|
||||
@@ -1453,7 +1429,12 @@ bool KologarnEyebeamAction::Execute(Event event)
|
||||
bool KologarnEyebeamAction::isUseful()
|
||||
{
|
||||
KologarnEyebeamTrigger kologarnEyebeamTrigger(botAI);
|
||||
return kologarnEyebeamTrigger.IsActive();
|
||||
if (!kologarnEyebeamTrigger.IsActive())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return botAI->HasCheat(BotCheatMask::raid);
|
||||
}
|
||||
|
||||
bool KologarnRtiTargetAction::isUseful()
|
||||
@@ -1477,7 +1458,12 @@ bool KologarnRtiTargetAction::Execute(Event event)
|
||||
bool KologarnCrunchArmorAction::isUseful()
|
||||
{
|
||||
KologarnCrunchArmorTrigger kologarnCrunchArmorTrigger(botAI);
|
||||
return kologarnCrunchArmorTrigger.IsActive();
|
||||
if (!kologarnCrunchArmorTrigger.IsActive())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return botAI->HasCheat(BotCheatMask::raid);
|
||||
}
|
||||
|
||||
bool KologarnCrunchArmorAction::Execute(Event event)
|
||||
@@ -1576,6 +1562,11 @@ bool HodirBitingColdJumpAction::Execute(Event event)
|
||||
// return true;
|
||||
}
|
||||
|
||||
bool HodirBitingColdJumpAction::isUseful()
|
||||
{
|
||||
return botAI->HasCheat(BotCheatMask::raid);
|
||||
}
|
||||
|
||||
bool FreyaMoveAwayNatureBombAction::isUseful()
|
||||
{
|
||||
// Check boss and it is alive
|
||||
@@ -1798,7 +1789,12 @@ bool FreyaMoveToHealingSporeAction::Execute(Event event)
|
||||
bool ThorimUnbalancingStrikeAction::isUseful()
|
||||
{
|
||||
ThorimUnbalancingStrikeTrigger thorimUnbalancingStrikeTrigger(botAI);
|
||||
return thorimUnbalancingStrikeTrigger.IsActive();
|
||||
if (!thorimUnbalancingStrikeTrigger.IsActive())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return botAI->HasCheat(BotCheatMask::raid);
|
||||
}
|
||||
|
||||
bool ThorimUnbalancingStrikeAction::Execute(Event event)
|
||||
@@ -2245,7 +2241,7 @@ bool MimironShockBlastAction::Execute(Event event)
|
||||
float dy = bot->GetPositionY() + sin(angle) * distance;
|
||||
float dz = bot->GetPositionZ();
|
||||
if (bot->GetMap()->CheckCollisionAndGetValidCoords(bot, bot->GetPositionX(), bot->GetPositionY(),
|
||||
bot->GetPositionZ(), dx, dy, dz))
|
||||
bot->GetPositionZ(), dx, dy, dz))
|
||||
{
|
||||
bot->TeleportTo(target->GetMapId(), dx, dy, dz, target->GetOrientation());
|
||||
return true;
|
||||
@@ -2448,7 +2444,7 @@ bool MimironAerialCommandUnitAction::Execute(Event event)
|
||||
{
|
||||
group->SetTargetIcon(crossIndex, bot->GetGUID(), boss->GetGUID());
|
||||
}
|
||||
|
||||
|
||||
if (assaultBot)
|
||||
{
|
||||
ObjectGuid skullTarget = group->GetTargetIcon(skullIndex);
|
||||
@@ -2647,3 +2643,67 @@ bool MimironCheatAction::Execute(Event event)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VezaxCheatAction::Execute(Event event)
|
||||
{
|
||||
// Restore bot's mana to full
|
||||
uint32 maxMana = bot->GetMaxPower(POWER_MANA);
|
||||
if (maxMana > 0)
|
||||
{
|
||||
bot->SetPower(POWER_MANA, maxMana);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VezaxShadowCrashAction::Execute(Event event)
|
||||
{
|
||||
// Find General Vezax boss
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "general vezax");
|
||||
if (!boss || !boss->IsAlive())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get bot's current position relative to boss
|
||||
float bossX = boss->GetPositionX();
|
||||
float bossY = boss->GetPositionY();
|
||||
float bossZ = boss->GetPositionZ();
|
||||
|
||||
float botX = bot->GetPositionX();
|
||||
float botY = bot->GetPositionY();
|
||||
|
||||
// Calculate current angle and distance from boss
|
||||
float currentAngle = atan2(botY - bossY, botX - bossX);
|
||||
float currentDistance = bot->GetDistance2d(boss);
|
||||
|
||||
// Set desired distance from boss (stay close enough for melee, far enough for ranged)
|
||||
float desiredDistance = 15.0f;
|
||||
|
||||
// If too close or too far, adjust distance first
|
||||
if (currentDistance < desiredDistance - 2.0f || currentDistance > desiredDistance + 2.0f)
|
||||
{
|
||||
currentDistance = desiredDistance;
|
||||
}
|
||||
|
||||
// Calculate movement increment - move in increments around the boss
|
||||
float angleIncrement = M_PI / 10;
|
||||
float newAngle = currentAngle + angleIncrement;
|
||||
|
||||
// Calculate new position
|
||||
float newX = bossX + currentDistance * cos(newAngle);
|
||||
float newY = bossY + currentDistance * sin(newAngle);
|
||||
float newZ = bossZ; // Keep same Z level as boss
|
||||
|
||||
// Move to the new position
|
||||
return MoveTo(boss->GetMapId(), newX, newY, newZ, false, false, false, true, MovementPriority::MOVEMENT_COMBAT,
|
||||
true);
|
||||
}
|
||||
|
||||
bool VezaxMarkOfTheFacelessAction::Execute(Event event)
|
||||
{
|
||||
return MoveTo(bot->GetMapId(), ULDUAR_VEZAX_MARK_OF_THE_FACELESS_SPOT.GetPositionX(),
|
||||
ULDUAR_VEZAX_MARK_OF_THE_FACELESS_SPOT.GetPositionY(),
|
||||
ULDUAR_VEZAX_MARK_OF_THE_FACELESS_SPOT.GetPositionZ(), false, false, false, true,
|
||||
MovementPriority::MOVEMENT_FORCED, true, false);
|
||||
}
|
||||
|
||||
@@ -198,6 +198,7 @@ class HodirBitingColdJumpAction : public MovementAction
|
||||
public:
|
||||
HodirBitingColdJumpAction(PlayerbotAI* ai) : MovementAction(ai, "hodir biting cold jump") {}
|
||||
bool Execute(Event event) override;
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class FreyaMoveAwayNatureBombAction : public MovementAction
|
||||
@@ -353,5 +354,28 @@ public:
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class VezaxCheatAction : public Action
|
||||
{
|
||||
public:
|
||||
VezaxCheatAction(PlayerbotAI* ai) : Action(ai, "vezax cheat action") {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class VezaxShadowCrashAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
VezaxShadowCrashAction(PlayerbotAI* ai) : MovementAction(ai, "vezax shadow crash action") {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
class VezaxMarkOfTheFacelessAction : public MovementAction
|
||||
{
|
||||
public:
|
||||
VezaxMarkOfTheFacelessAction(PlayerbotAI* ai) : MovementAction(ai, "vezax mark of the faceless action") {}
|
||||
|
||||
bool Execute(Event event) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -225,6 +225,21 @@ void RaidUlduarStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
triggers.push_back(new TriggerNode(
|
||||
"mimiron cheat trigger",
|
||||
NextAction::array(0, new NextAction("mimiron cheat action", ACTION_RAID), nullptr)));
|
||||
|
||||
//
|
||||
// General Vezax
|
||||
//
|
||||
triggers.push_back(new TriggerNode(
|
||||
"vezax cheat trigger",
|
||||
NextAction::array(0, new NextAction("vezax cheat action", ACTION_RAID), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"vezax shadow crash trigger",
|
||||
NextAction::array(0, new NextAction("vezax shadow crash action", ACTION_RAID), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"vezax mark of the faceless trigger",
|
||||
NextAction::array(0, new NextAction("vezax mark of the faceless action", ACTION_RAID), nullptr)));
|
||||
}
|
||||
|
||||
void RaidUlduarStrategy::InitMultipliers(std::vector<Multiplier*>& multipliers)
|
||||
|
||||
@@ -64,6 +64,9 @@ public:
|
||||
creators["mimiron rocket strike trigger"] = &RaidUlduarTriggerContext::mimiron_rocket_strike_trigger;
|
||||
creators["mimiron phase 4 mark dps trigger"] = &RaidUlduarTriggerContext::mimiron_phase_4_mark_dps_trigger;
|
||||
creators["mimiron cheat trigger"] = &RaidUlduarTriggerContext::mimiron_cheat_trigger;
|
||||
creators["vezax cheat trigger"] = &RaidUlduarTriggerContext::vezax_cheat_trigger;
|
||||
creators["vezax shadow crash trigger"] = &RaidUlduarTriggerContext::vezax_shadow_crash_trigger;
|
||||
creators["vezax mark of the faceless trigger"] = &RaidUlduarTriggerContext::vezax_mark_of_the_faceless_trigger;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -115,6 +118,9 @@ private:
|
||||
static Trigger* mimiron_rocket_strike_trigger(PlayerbotAI* ai) { return new MimironRocketStrikeTrigger(ai); }
|
||||
static Trigger* mimiron_phase_4_mark_dps_trigger(PlayerbotAI* ai) { return new MimironPhase4MarkDpsTrigger(ai); }
|
||||
static Trigger* mimiron_cheat_trigger(PlayerbotAI* ai) { return new MimironCheatTrigger(ai); }
|
||||
static Trigger* vezax_cheat_trigger(PlayerbotAI* ai) { return new VezaxCheatTrigger(ai); }
|
||||
static Trigger* vezax_shadow_crash_trigger(PlayerbotAI* ai) { return new VezaxShadowCrashTrigger(ai); }
|
||||
static Trigger* vezax_mark_of_the_faceless_trigger(PlayerbotAI* ai) { return new VezaxMarkOfTheFacelessTrigger(ai); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1533,6 +1533,11 @@ bool MimironPhase4MarkDpsTrigger::IsActive()
|
||||
|
||||
bool MimironCheatTrigger::IsActive()
|
||||
{
|
||||
if (!botAI->HasCheat(BotCheatMask::raid))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!botAI->IsMainTank(bot))
|
||||
{
|
||||
return false;
|
||||
@@ -1557,3 +1562,60 @@ bool MimironCheatTrigger::IsActive()
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VezaxCheatTrigger::IsActive()
|
||||
{
|
||||
if (!botAI->HasCheat(BotCheatMask::raid))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "general vezax");
|
||||
|
||||
// Check boss and it is alive
|
||||
if (!boss || !boss->IsAlive())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!AI_VALUE2(bool, "has mana", "self target"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return AI_VALUE2(uint8, "mana", "self target") < sPlayerbotAIConfig->lowMana;
|
||||
}
|
||||
|
||||
bool VezaxShadowCrashTrigger::IsActive()
|
||||
{
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "general vezax");
|
||||
|
||||
// Check boss and it is alive
|
||||
if (!boss || !boss->IsAlive())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return botAI->HasAura(SPELL_SHADOW_CRASH, bot);
|
||||
}
|
||||
|
||||
bool VezaxMarkOfTheFacelessTrigger::IsActive()
|
||||
{
|
||||
Unit* boss = AI_VALUE2(Unit*, "find target", "general vezax");
|
||||
|
||||
// Check boss and it is alive
|
||||
if (!boss || !boss->IsAlive())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!botAI->HasAura(SPELL_MARK_OF_THE_FACELESS, bot))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
float distance = bot->GetDistance2d(ULDUAR_VEZAX_MARK_OF_THE_FACELESS_SPOT.GetPositionX(),
|
||||
ULDUAR_VEZAX_MARK_OF_THE_FACELESS_SPOT.GetPositionY());
|
||||
|
||||
return distance > 2.0f;
|
||||
}
|
||||
|
||||
@@ -77,6 +77,10 @@ enum UlduarIDs
|
||||
SPELL_P3WX2_LASER_BARRAGE_3 = 64042,
|
||||
SPELL_P3WX2_LASER_BARRAGE_AURA_1 = 63274,
|
||||
SPELL_P3WX2_LASER_BARRAGE_AURA_2 = 63300,
|
||||
|
||||
//General Vezax
|
||||
SPELL_MARK_OF_THE_FACELESS = 63276,
|
||||
SPELL_SHADOW_CRASH = 63277,
|
||||
|
||||
// Buffs
|
||||
SPELL_FROST_TRAP = 13809
|
||||
@@ -106,6 +110,7 @@ const Position ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_5_YARDS_1 = Position(2217.8877f
|
||||
const Position ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_10_YARDS_1 = Position(2212.193f, -307.44992f, 412.1348f);
|
||||
const Position ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_10_YARDS_2 = Position(2212.1353f, -318.20795f, 412.1348f);
|
||||
const Position ULDUAR_THORIM_GAUNTLET_RIGHT_SIDE_10_YARDS_3 = Position(2212.1956f, -328.0144f, 412.1348f);
|
||||
const Position ULDUAR_THORIM_JUMP_END_POINT = Position(2137.8818f, -278.18942f, 419.66653f);
|
||||
const Position ULDUAR_THORIM_PHASE2_TANK_SPOT = Position(2134.8572f, -287.0291f, 419.4935f);
|
||||
const Position ULDUAR_THORIM_PHASE2_RANGE1_SPOT = Position(2112.8752f, -267.69305f, 419.52814f);
|
||||
const Position ULDUAR_THORIM_PHASE2_RANGE2_SPOT = Position(2134.1296f, -257.3316f, 419.8462f);
|
||||
@@ -117,6 +122,7 @@ const Position ULDUAR_MIMIRON_PHASE2_SIDE2MELEE_SPOT = Position(2739.4746f, 2569
|
||||
const Position ULDUAR_MIMIRON_PHASE2_SIDE3RANGE_SPOT = Position(2754.1294f, 2553.9954f, 364.31357f);
|
||||
const Position ULDUAR_MIMIRON_PHASE2_SIDE3MELEE_SPOT = Position(2746.8513f, 2565.4263f, 364.31357f);
|
||||
const Position ULDUAR_MIMIRON_PHASE4_TANK_SPOT = Position(2744.5754f, 2570.8657f, 364.3138f);
|
||||
const Position ULDUAR_VEZAX_MARK_OF_THE_FACELESS_SPOT = Position(1913.6501f, 122.93989f, 342.38083f);
|
||||
|
||||
//
|
||||
// Flame Levi
|
||||
@@ -418,4 +424,28 @@ public:
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
//
|
||||
// General Vezax
|
||||
//
|
||||
class VezaxCheatTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
VezaxCheatTrigger(PlayerbotAI* ai) : Trigger(ai, "vezax cheat trigger") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class VezaxShadowCrashTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
VezaxShadowCrashTrigger(PlayerbotAI* ai) : Trigger(ai, "vezax shadow crash trigger") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
class VezaxMarkOfTheFacelessTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
VezaxMarkOfTheFacelessTrigger(PlayerbotAI* ai) : Trigger(ai, "vezax mark of the faceless trigger") {}
|
||||
bool IsActive() override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user