From 378254af3f1f8db9a6116a1a158da8a41916fb82 Mon Sep 17 00:00:00 2001 From: Crow Date: Sat, 24 Jan 2026 14:26:49 -0600 Subject: [PATCH] Fix Assistant Assignment Functions (#1930) IsHealAssistantOfIndex() and IsRangedDpsAssistantOfIndex() are supposed to iterate through the group and first return members with the applicable role that have the assistant flag, and then iterate through non-assistants only if there are not enough assistants for the designated index. They are not written properly and actually completely ignore the assistant flag. I rely on these functions for significant roles in SSC and TK (which I have decided I'll PR in the same way as SSC, as a long-term draft). I have them fixed on my own fork, but it is problematic for testers if these functions do not work. So I've done three things here: 1. Fixed the functions to prefer members with the assistant flag. 2. Added a third parameter for ignoreDeadPlayers, like IsAssistTankOfIndex() has. Note that the parameter is by default false for IsAssistTankOfIndex(), meaning dead players are _not_ ignored. This is not my preferred design choice--I think the default should be to ignore dead players, but I have not changed the default and have made the default the same for IsAssistHealOfIndex() and IsAssistRangedDpsOfIndex(), since I don't know the intent of the pre-existing boss strats that use the functions. 3. Changed the names to IsAssistHealOfIndex() and IsAssistRangedDpsOfIndex() so they parallel IsAssistTankOfIndex(), and made corresponding changes in the few boss strats that use the functions. Also, note that the functions _do _not_ exclude real players. I think there are arguments for and against excluding real players. A fourth parameter for this could be useful, but I've not made any change in that regard. --- .../Trigger/RaidOsTriggers.cpp | 6 +- src/Bot/PlayerbotAI.cpp | 92 +++++++++++-------- src/Bot/PlayerbotAI.h | 4 +- 3 files changed, 58 insertions(+), 44 deletions(-) diff --git a/src/Ai/Raid/ObsidianSanctum/Trigger/RaidOsTriggers.cpp b/src/Ai/Raid/ObsidianSanctum/Trigger/RaidOsTriggers.cpp index 2c375885..710e3cac 100644 --- a/src/Ai/Raid/ObsidianSanctum/Trigger/RaidOsTriggers.cpp +++ b/src/Ai/Raid/ObsidianSanctum/Trigger/RaidOsTriggers.cpp @@ -78,19 +78,19 @@ bool SartharionMeleePositioningTrigger::IsActive() bool TwilightPortalEnterTrigger::IsActive() { - if (botAI->IsMainTank(bot) || botAI->IsHealAssistantOfIndex(bot, 0)) { return false; } + if (botAI->IsMainTank(bot) || botAI->IsAssistHealOfIndex(bot, 0)) { return false; } // In 25-man, take two healers in. Otherwise just take one // if (bot->GetRaidDifficulty() == RAID_DIFFICULTY_25MAN_NORMAL) // { - // if (botAI->IsHealAssistantOfIndex(bot, 0) || botAI->IsHealAssistantOfIndex(bot, 1)) + // if (botAI->IsAssistHealOfIndex(bot, 0) || botAI->IsAssistHealOfIndex(bot, 1)) // { // return false; // } // } // else // { - // if (botAI->IsHealAssistantOfIndex(bot, 0)) + // if (botAI->IsAssistHealOfIndex(bot, 0)) // { // return false; // } diff --git a/src/Bot/PlayerbotAI.cpp b/src/Bot/PlayerbotAI.cpp index 49efe092..39db7c59 100644 --- a/src/Bot/PlayerbotAI.cpp +++ b/src/Bot/PlayerbotAI.cpp @@ -1796,35 +1796,46 @@ bool PlayerbotAI::IsCombo(Player* player) bool PlayerbotAI::IsRangedDps(Player* player, bool bySpec) { return IsRanged(player, bySpec) && IsDps(player, bySpec); } -bool PlayerbotAI::IsHealAssistantOfIndex(Player* player, int index) +bool PlayerbotAI::IsAssistHealOfIndex(Player* player, int index, bool ignoreDeadPlayers) { Group* group = player->GetGroup(); if (!group) - { return false; - } int counter = 0; + // First, assistants for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) { Player* member = ref->GetSource(); - if (!member) - { continue; - } - if (IsHeal(member)) // Check if the member is a healer + if (ignoreDeadPlayers && !member->IsAlive()) + continue; + + if (group->IsAssistant(member->GetGUID()) && IsHeal(member)) { - bool isAssistant = group->IsAssistant(member->GetGUID()); - - // Check if the index matches for both assistant and non-assistant healers - if ((isAssistant && index == counter) || (!isAssistant && index == counter)) - { + if (index == counter) return player == member; - } + counter++; + } + } + // If not enough assistants, get non-assistants + for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) + { + Player* member = ref->GetSource(); + if (!member) + continue; + + if (ignoreDeadPlayers && !member->IsAlive()) + continue; + + if (!group->IsAssistant(member->GetGUID()) && IsHeal(member)) + { + if (index == counter) + return player == member; counter++; } } @@ -1832,35 +1843,46 @@ bool PlayerbotAI::IsHealAssistantOfIndex(Player* player, int index) return false; } -bool PlayerbotAI::IsRangedDpsAssistantOfIndex(Player* player, int index) +bool PlayerbotAI::IsAssistRangedDpsOfIndex(Player* player, int index, bool ignoreDeadPlayers) { Group* group = player->GetGroup(); if (!group) - { return false; - } int counter = 0; + // First, assistants for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) { Player* member = ref->GetSource(); - if (!member) - { continue; - } - if (IsRangedDps(member)) // Check if the member is a ranged DPS + if (ignoreDeadPlayers && !member->IsAlive()) + continue; + + if (group->IsAssistant(member->GetGUID()) && IsRangedDps(member)) { - bool isAssistant = group->IsAssistant(member->GetGUID()); - - // Check the index for both assistant and non-assistant ranges - if ((isAssistant && index == counter) || (!isAssistant && index == counter)) - { + if (index == counter) return player == member; - } + counter++; + } + } + // If not enough assistants, get non-assistants + for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) + { + Player* member = ref->GetSource(); + if (!member) + continue; + + if (ignoreDeadPlayers && !member->IsAlive()) + continue; + + if (!group->IsAssistant(member->GetGUID()) && IsRangedDps(member)) + { + if (index == counter) + return player == member; counter++; } } @@ -2335,18 +2357,16 @@ bool PlayerbotAI::IsAssistTankOfIndex(Player* player, int index, bool ignoreDead { Group* group = player->GetGroup(); if (!group) - { return false; - } + int counter = 0; + + // First, assistants for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) { Player* member = ref->GetSource(); - if (!member) - { continue; - } if (ignoreDeadPlayers && !member->IsAlive()) continue; @@ -2354,21 +2374,17 @@ bool PlayerbotAI::IsAssistTankOfIndex(Player* player, int index, bool ignoreDead if (group->IsAssistant(member->GetGUID()) && IsAssistTank(member)) { if (index == counter) - { return player == member; - } counter++; } } - // not enough + + // If not enough assistants, get non-assistants for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next()) { Player* member = ref->GetSource(); - if (!member) - { continue; - } if (ignoreDeadPlayers && !member->IsAlive()) continue; @@ -2376,9 +2392,7 @@ bool PlayerbotAI::IsAssistTankOfIndex(Player* player, int index, bool ignoreDead if (!group->IsAssistant(member->GetGUID()) && IsAssistTank(member)) { if (index == counter) - { return player == member; - } counter++; } } diff --git a/src/Bot/PlayerbotAI.h b/src/Bot/PlayerbotAI.h index 4de4bf4a..b2df4352 100644 --- a/src/Bot/PlayerbotAI.h +++ b/src/Bot/PlayerbotAI.h @@ -429,8 +429,8 @@ public: static uint32 GetGroupTankNum(Player* player); static bool IsAssistTank(Player* player); static bool IsAssistTankOfIndex(Player* player, int index, bool ignoreDeadPlayers = false); - static bool IsHealAssistantOfIndex(Player* player, int index); - static bool IsRangedDpsAssistantOfIndex(Player* player, int index); + static bool IsAssistHealOfIndex(Player* player, int index, bool ignoreDeadPlayers = false); + static bool IsAssistRangedDpsOfIndex(Player* player, int index, bool ignoreDeadPlayers = false); bool HasAggro(Unit* unit); static int32 GetAssistTankIndex(Player* player); int32 GetGroupSlotIndex(Player* player);