mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
Added logic for bots to offtank
Bot tanks will mark targets and establish themselves as main tank when necessary, announcing when ever re-assignment occurs
This commit is contained in:
@@ -440,6 +440,12 @@ bool RazorscaleAvoidDevouringFlameAction::Execute(Event event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Off tanks are following the main tank during grounded and should prioritise stacking
|
||||||
|
if (razorscaleHelper.IsGroundPhase() && (botAI->IsTank(bot) && !botAI->IsMainTank(bot)))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Handle movement from flames
|
// Handle movement from flames
|
||||||
if (closestDistance < safeDistance)
|
if (closestDistance < safeDistance)
|
||||||
{
|
{
|
||||||
@@ -477,11 +483,6 @@ bool RazorscaleAvoidSentinelAction::Execute(Event event)
|
|||||||
{
|
{
|
||||||
bool isTank = botAI->IsTank(bot);
|
bool isTank = botAI->IsTank(bot);
|
||||||
bool isMainTank = botAI->IsMainTank(bot);
|
bool isMainTank = botAI->IsMainTank(bot);
|
||||||
if (isTank && !isMainTank)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isRanged = botAI->IsRanged(bot);
|
bool isRanged = botAI->IsRanged(bot);
|
||||||
const float radius = 8.0f;
|
const float radius = 8.0f;
|
||||||
|
|
||||||
@@ -512,38 +513,76 @@ bool RazorscaleAvoidSentinelAction::Execute(Event event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark the lowest-health sentinel with Skull if main tank
|
// Check if the main tank is a human player
|
||||||
if (isMainTank && lowestHealthSentinel)
|
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
|
||||||
|
{
|
||||||
|
// 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
|
||||||
|
{
|
||||||
|
Group* group = bot->GetGroup();
|
||||||
|
if (group && lowestHealthSentinel)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
if (!currentSkullTarget || (lowestHealthSentinel->GetGUID() != currentSkullTarget))
|
||||||
|
{
|
||||||
|
group->SetTargetIcon(skullIndex, bot->GetGUID(), lowestHealthSentinel->GetGUID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break; // Stop after finding the first valid bot tank
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (isMainTank && lowestHealthSentinel) // Bot is the main tank
|
||||||
{
|
{
|
||||||
Group* group = bot->GetGroup();
|
Group* group = bot->GetGroup();
|
||||||
if (group)
|
if (group)
|
||||||
{
|
{
|
||||||
int8 skullIndex = 7; // Skull
|
int8 skullIndex = 7; // Skull
|
||||||
ObjectGuid currentSkullTarget = group->GetTargetIcon(skullIndex);
|
ObjectGuid currentSkullTarget = group->GetTargetIcon(skullIndex);
|
||||||
if (currentSkullTarget && lowestHealthSentinel->GetGUID() != currentSkullTarget)
|
|
||||||
|
// If there's no skull set yet, or the skull is on a different target, set the sentinel
|
||||||
|
if (!currentSkullTarget || (lowestHealthSentinel->GetGUID() != currentSkullTarget))
|
||||||
{
|
{
|
||||||
group->SetTargetIcon(skullIndex, bot->GetGUID(), lowestHealthSentinel->GetGUID());
|
group->SetTargetIcon(skullIndex, bot->GetGUID(), lowestHealthSentinel->GetGUID());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return movedAway; // Return true if moved
|
return movedAway; // Return true if moved
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RazorscaleAvoidSentinelAction::isUseful()
|
bool RazorscaleAvoidSentinelAction::isUseful()
|
||||||
{
|
{
|
||||||
bool isTank = botAI->IsTank(bot);
|
|
||||||
bool isMainTank = botAI->IsMainTank(bot);
|
bool isMainTank = botAI->IsMainTank(bot);
|
||||||
if (isTank && !isMainTank)
|
Unit* mainTankUnit = AI_VALUE(Unit*, "main tank");
|
||||||
{
|
Player* mainTank = mainTankUnit ? mainTankUnit->ToPlayer() : nullptr;
|
||||||
return false;
|
|
||||||
}
|
// If this bot is the main tank, it should always try to mark
|
||||||
|
|
||||||
// Main tank always tries to mark sentinel
|
|
||||||
if (isMainTank)
|
if (isMainTank)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 3; ++i)
|
||||||
|
{
|
||||||
|
if (botAI->IsAssistTankOfIndex(bot, i) && GET_PLAYERBOT_AI(bot)) // Bot is a valid tank
|
||||||
|
{
|
||||||
|
return true; // This bot should assist with marking
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool isRanged = botAI->IsRanged(bot);
|
bool isRanged = botAI->IsRanged(bot);
|
||||||
const float radius = 8.0f;
|
const float radius = 8.0f;
|
||||||
@@ -621,30 +660,62 @@ bool RazorscaleIgnoreBossAction::isUseful()
|
|||||||
Unit* boss = AI_VALUE2(Unit*, "find target", "razorscale");
|
Unit* boss = AI_VALUE2(Unit*, "find target", "razorscale");
|
||||||
if (!boss)
|
if (!boss)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the boss is flying
|
// Check if the boss is flying
|
||||||
if (boss->GetPositionZ() >= RazorscaleBossHelper::RAZORSCALE_FLYING_Z_THRESHOLD)
|
if (boss->GetPositionZ() >= RazorscaleBossHelper::RAZORSCALE_FLYING_Z_THRESHOLD)
|
||||||
{
|
{
|
||||||
bool isMainTank = botAI->IsMainTank(bot);
|
|
||||||
// Check if the bot is outside the designated area
|
// 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
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!botAI->IsTank(bot))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Group* group = bot->GetGroup();
|
||||||
|
if (!group)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the boss is already set as the moon marker
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proceed to tank-specific logic
|
||||||
|
Unit* mainTankUnit = AI_VALUE(Unit*, "main tank");
|
||||||
|
Player* mainTank = mainTankUnit ? mainTankUnit->ToPlayer() : nullptr;
|
||||||
|
|
||||||
|
// If this bot is the main tank, it needs to set the moon marker
|
||||||
|
if (mainTankUnit == bot)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// Check moon mark if main tank
|
|
||||||
if (isMainTank)
|
// 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
|
||||||
{
|
{
|
||||||
Group* group = bot->GetGroup();
|
for (int i = 0; i < 3; ++i) // Only iterate through the first 3 indexes
|
||||||
if (group)
|
|
||||||
{
|
{
|
||||||
int8 moonIndex = 4;
|
if (botAI->IsAssistTankOfIndex(bot, i) && GET_PLAYERBOT_AI(bot)) // Valid bot tank
|
||||||
ObjectGuid currentMoonTarget = group->GetTargetIcon(moonIndex);
|
{
|
||||||
return currentMoonTarget != boss->GetGUID();
|
return true; // This bot should assign the marker
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -653,13 +724,20 @@ bool RazorscaleIgnoreBossAction::Execute(Event event)
|
|||||||
Unit* boss = AI_VALUE2(Unit*, "find target", "razorscale");
|
Unit* boss = AI_VALUE2(Unit*, "find target", "razorscale");
|
||||||
if (!boss)
|
if (!boss)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isMainTank = botAI->IsMainTank(bot);
|
Group* group = bot->GetGroup();
|
||||||
if (!isMainTank)
|
if (!group)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
{
|
{
|
||||||
// Move non-tanks inside
|
|
||||||
return MoveInside(
|
return MoveInside(
|
||||||
ULDUAR_MAP_ID,
|
ULDUAR_MAP_ID,
|
||||||
RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_X,
|
RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_X,
|
||||||
@@ -670,22 +748,43 @@ bool RazorscaleIgnoreBossAction::Execute(Event event)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Group* group = bot->GetGroup();
|
if (!botAI->IsTank(bot))
|
||||||
if (!group)
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assign moon rti to boss
|
// Check if the boss is already set as the moon marker
|
||||||
int8 moonIndex = 4;
|
int8 moonIndex = 4;
|
||||||
ObjectGuid currentMoonTarget = group->GetTargetIcon(moonIndex);
|
ObjectGuid currentMoonTarget = group->GetTargetIcon(moonIndex);
|
||||||
if (currentMoonTarget != boss->GetGUID())
|
if (currentMoonTarget == boss->GetGUID())
|
||||||
|
{
|
||||||
|
return false; // Moon marker is already correctly set
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the main tank and determine role
|
||||||
|
Unit* mainTankUnit = AI_VALUE(Unit*, "main tank");
|
||||||
|
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
|
||||||
|
{
|
||||||
|
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
|
||||||
|
{
|
||||||
|
group->SetTargetIcon(moonIndex, bot->GetGUID(), boss->GetGUID());
|
||||||
|
SetNextMovementDelay(1000);
|
||||||
|
break; // Assign the moon marker and stop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mainTankUnit == bot) // If this bot is the main tank
|
||||||
{
|
{
|
||||||
group->SetTargetIcon(moonIndex, bot->GetGUID(), boss->GetGUID());
|
group->SetTargetIcon(moonIndex, bot->GetGUID(), boss->GetGUID());
|
||||||
SetNextMovementDelay(1000);
|
SetNextMovementDelay(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move main tank inside
|
// Tanks move inside the arena
|
||||||
return MoveInside(
|
return MoveInside(
|
||||||
ULDUAR_MAP_ID,
|
ULDUAR_MAP_ID,
|
||||||
RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_X,
|
RazorscaleBossHelper::RAZORSCALE_ARENA_CENTER_X,
|
||||||
@@ -792,10 +891,35 @@ bool RazorscaleGroundedAction::Execute(Event event)
|
|||||||
if (!group)
|
if (!group)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (botAI->IsMainTank(bot))
|
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
|
||||||
|
{
|
||||||
|
// 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
|
||||||
|
{
|
||||||
|
int8 moonIndex = 4;
|
||||||
|
ObjectGuid currentMoonTarget = group->GetTargetIcon(moonIndex);
|
||||||
|
|
||||||
|
// If the moon marker is set to the boss, reset it
|
||||||
|
if (currentMoonTarget == boss->GetGUID())
|
||||||
|
{
|
||||||
|
group->SetTargetIcon(moonIndex, bot->GetGUID(), ObjectGuid::Empty);
|
||||||
|
SetNextMovementDelay(1000);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (botAI->IsMainTank(bot)) // Bot is the main tank
|
||||||
{
|
{
|
||||||
int8 moonIndex = 4;
|
int8 moonIndex = 4;
|
||||||
ObjectGuid currentMoonTarget = group->GetTargetIcon(moonIndex);
|
ObjectGuid currentMoonTarget = group->GetTargetIcon(moonIndex);
|
||||||
|
|
||||||
|
// If the moon marker is set to the boss, reset it
|
||||||
if (currentMoonTarget == boss->GetGUID())
|
if (currentMoonTarget == boss->GetGUID())
|
||||||
{
|
{
|
||||||
group->SetTargetIcon(moonIndex, bot->GetGUID(), ObjectGuid::Empty);
|
group->SetTargetIcon(moonIndex, bot->GetGUID(), ObjectGuid::Empty);
|
||||||
@@ -804,24 +928,12 @@ bool RazorscaleGroundedAction::Execute(Event event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (botAI->IsTank(bot))
|
|
||||||
{
|
|
||||||
Player* mainTank = nullptr;
|
|
||||||
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
|
|
||||||
{
|
|
||||||
Player* member = ref->GetSource();
|
|
||||||
if (member && botAI->IsMainTank(member))
|
|
||||||
{
|
|
||||||
mainTank = member;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mainTank)
|
if (mainTank && (botAI->IsTank(bot) && !botAI->IsMainTank(bot)))
|
||||||
{
|
{
|
||||||
|
|
||||||
constexpr float followDistance = 2.0f;
|
constexpr float followDistance = 2.0f;
|
||||||
return MoveNear(mainTank, followDistance, MovementPriority::MOVEMENT_COMBAT);
|
return MoveNear(mainTank, followDistance, MovementPriority::MOVEMENT_COMBAT);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (botAI->IsRanged(bot))
|
if (botAI->IsRanged(bot))
|
||||||
|
|||||||
Reference in New Issue
Block a user