@@ -23,12 +23,20 @@ namespace ai::gbless
2323namespace
2424{
2525 constexpr uint32 GREATER_BLESSING_ASSIGNMENT_CACHE_MS = 4 * 1000 ;
26- constexpr uint32 GREATER_BLESSING_PENDING_ASSIGNMENT_CACHE_MS = 100 ;
26+ constexpr uint32 GREATER_BLESSING_PENDING_ASSIGNMENT_CACHE_MS = 500 ;
2727 constexpr uint8 MAX_BLESSING_SLOTS = 4 ;
2828 constexpr uint8 MAX_CLASS_ID = 12 ;
2929
3030 constexpr size_t BaseBlessingCategoryCount = MAX_BLESSING_SLOTS ;
3131
32+ enum PaladinBlessingCapability : uint8
33+ {
34+ PALADIN_BLESSING_CAPABILITY_NONE = 0 ,
35+ PALADIN_BLESSING_CAPABILITY_IMPROVED_WISDOM = 1 << 0 ,
36+ PALADIN_BLESSING_CAPABILITY_IMPROVED_MIGHT = 1 << 1 ,
37+ PALADIN_BLESSING_CAPABILITY_SANCTUARY = 1 << 2
38+ };
39+
3240 constexpr size_t BaseBlessingIndex (BaseBlessingCategory category)
3341 {
3442 return static_cast <size_t >(static_cast <uint8>(category) - static_cast <uint8>(BASE_MIGHT ));
@@ -58,22 +66,38 @@ namespace
5866 (!left.byRole || left.role == right.role );
5967 }
6068
61- int TalentScore (Player* player)
69+ uint8 GetPaladinBlessingCapabilities (Player* player)
6270 {
6371 if (!player)
64- return 0 ;
72+ return PALADIN_BLESSING_CAPABILITY_NONE ;
6573
66- int score = 0 ;
74+ uint8 capabilities = PALADIN_BLESSING_CAPABILITY_NONE ;
6775 if (player->HasAura (SPELL_IMPROVED_MIGHT_R1 ) ||
6876 player->HasAura (SPELL_IMPROVED_MIGHT_R2 ))
6977 {
70- score += 2 ;
78+ capabilities |= PALADIN_BLESSING_CAPABILITY_IMPROVED_MIGHT ;
7179 }
7280 if (player->HasAura (SPELL_IMPROVED_WISDOM_R1 ) ||
7381 player->HasAura (SPELL_IMPROVED_WISDOM_R2 ))
7482 {
75- score += 1 ;
83+ capabilities |= PALADIN_BLESSING_CAPABILITY_IMPROVED_WISDOM ;
7684 }
85+ if (player->HasSpell (ai::paladin::SPELL_BLESSING_OF_SANCTUARY ))
86+ capabilities |= PALADIN_BLESSING_CAPABILITY_SANCTUARY ;
87+
88+ return capabilities;
89+ }
90+
91+ int TalentScore (Player* player)
92+ {
93+ uint8 const capabilities = GetPaladinBlessingCapabilities (player);
94+ int score = 0 ;
95+
96+ if (capabilities & PALADIN_BLESSING_CAPABILITY_IMPROVED_MIGHT )
97+ score += 2 ;
98+
99+ if (capabilities & PALADIN_BLESSING_CAPABILITY_IMPROVED_WISDOM )
100+ score += 1 ;
77101
78102 return score;
79103 }
@@ -83,30 +107,74 @@ namespace
83107 if (!player)
84108 return std::numeric_limits<int >::min () / 4 ;
85109
110+ uint8 const capabilities = GetPaladinBlessingCapabilities (player);
111+
86112 if (category == BASE_SANCTUARY )
87113 {
88- if (!player-> HasSpell (ai::paladin:: SPELL_BLESSING_OF_SANCTUARY ))
114+ if (!(capabilities & PALADIN_BLESSING_CAPABILITY_SANCTUARY ))
89115 return std::numeric_limits<int >::min () / 4 ;
90116
91117 return 2 ;
92118 }
93119
94120 if (category == BASE_MIGHT &&
95- (player->HasAura (SPELL_IMPROVED_MIGHT_R1 ) ||
96- player->HasAura (SPELL_IMPROVED_MIGHT_R2 )))
121+ (capabilities & PALADIN_BLESSING_CAPABILITY_IMPROVED_MIGHT ))
97122 {
98123 return 1 ;
99124 }
100125 if (category == BASE_WISDOM &&
101- (player->HasAura (SPELL_IMPROVED_WISDOM_R1 ) ||
102- player->HasAura (SPELL_IMPROVED_WISDOM_R2 )))
126+ (capabilities & PALADIN_BLESSING_CAPABILITY_IMPROVED_WISDOM ))
103127 {
104128 return 1 ;
105129 }
106130
107131 return 0 ;
108132 }
109133
134+ void SelectActivePaladinPool (
135+ std::vector<Player*>& botPaladins)
136+ {
137+ std::sort (botPaladins.begin (), botPaladins.end (),
138+ [](Player* left, Player* right)
139+ {
140+ return left->GetGUID () < right->GetGUID ();
141+ });
142+
143+ std::vector<Player*> selectedPaladins;
144+ selectedPaladins.reserve (botPaladins.size ());
145+ std::vector<bool > selected (botPaladins.size (), false );
146+
147+ auto const selectFirstWithCapability = [&](uint8 capability)
148+ {
149+ for (size_t index = 0 ; index < botPaladins.size (); ++index)
150+ {
151+ if (selected[index])
152+ continue ;
153+
154+ if (!(GetPaladinBlessingCapabilities (botPaladins[index]) & capability))
155+ continue ;
156+
157+ selected[index] = true ;
158+ selectedPaladins.push_back (botPaladins[index]);
159+ return ;
160+ }
161+ };
162+
163+ selectFirstWithCapability (PALADIN_BLESSING_CAPABILITY_SANCTUARY );
164+ selectFirstWithCapability (PALADIN_BLESSING_CAPABILITY_IMPROVED_MIGHT );
165+ selectFirstWithCapability (PALADIN_BLESSING_CAPABILITY_IMPROVED_WISDOM );
166+
167+ for (size_t index = 0 ; index < botPaladins.size (); ++index)
168+ {
169+ if (selected[index])
170+ continue ;
171+
172+ selectedPaladins.push_back (botPaladins[index]);
173+ }
174+
175+ botPaladins = std::move (selectedPaladins);
176+ }
177+
110178 struct DesiredBlessingSet
111179 {
112180 std::array<BaseBlessingCategory, MAX_BLESSING_SLOTS > ordered = {};
@@ -593,29 +661,22 @@ namespace
593661 if (botPaladins.empty ())
594662 return false ;
595663
664+ SelectActivePaladinPool (botPaladins);
665+
666+ uint8 activePaladinCount =
667+ std::min<uint8>(static_cast <uint8>(botPaladins.size ()), MAX_BLESSING_SLOTS );
668+
596669 bool anySanctuaryAvailable = false ;
597- for (Player* paladin : botPaladins )
670+ for (uint8 paladinIndex = 0 ; paladinIndex < activePaladinCount; ++paladinIndex )
598671 {
599- if (paladin && paladin->HasSpell (ai::paladin::SPELL_BLESSING_OF_SANCTUARY ))
672+ if (GetPaladinBlessingCapabilities (botPaladins[paladinIndex]) &
673+ PALADIN_BLESSING_CAPABILITY_SANCTUARY )
600674 {
601675 anySanctuaryAvailable = true ;
602676 break ;
603677 }
604678 }
605679
606- std::sort (botPaladins.begin (), botPaladins.end (),
607- [](Player* a, Player* b)
608- {
609- int sa = TalentScore (a);
610- int sb = TalentScore (b);
611- if (sa != sb)
612- return sa > sb;
613- return a->GetGUID () < b->GetGUID ();
614- });
615-
616- uint8 activePaladinCount =
617- std::min<uint8>(static_cast <uint8>(botPaladins.size ()), MAX_BLESSING_SLOTS );
618-
619680 int mySlot = -1 ;
620681 for (size_t i = 0 ; i < botPaladins.size (); ++i)
621682 {
@@ -695,7 +756,9 @@ namespace
695756 classBuckets, botPaladins, allPaladins,
696757 classWideOwners, exclusiveOwnersByBucket, classWideBases,
697758 exclusiveBasesByBucket))
698- return false ;
759+ {
760+ continue ;
761+ }
699762
700763 for (size_t index = 0 ; index < classWideBases.size (); ++index)
701764 {
0 commit comments