From b7eacd869e803bd1d1f0bfd32aa1ecb1816caff2 Mon Sep 17 00:00:00 2001 From: Hondacrx Date: Mon, 13 Oct 2025 14:28:02 -0400 Subject: [PATCH] Core/Spells: Simplify SortTargetsWithPriorityRules Port From (https://github.com/TrinityCore/TrinityCore/commit/03d072da463769ff02090e08d12b4da3f6a49222) --- Source/Game/Scripting/SpellScript.cs | 53 ++++++++++++++-------------- Source/Scripts/Spells/Priest.cs | 16 ++++----- 2 files changed, 35 insertions(+), 34 deletions(-) diff --git a/Source/Game/Scripting/SpellScript.cs b/Source/Game/Scripting/SpellScript.cs index be5582ced..496c98e68 100644 --- a/Source/Game/Scripting/SpellScript.cs +++ b/Source/Game/Scripting/SpellScript.cs @@ -1128,9 +1128,7 @@ namespace Game.Scripting targets.Resize(maxTargets); } - public List CreatePriorityRules(List rules) { return rules; } - - public void SortTargetsWithPriorityRules(List targets, int maxTargets, List rules) + public void SortTargetsWithPriorityRules(List targets, int maxTargets, List rules) { if (targets.Count <= maxTargets) return; @@ -1138,42 +1136,33 @@ namespace Game.Scripting List<(WorldObject, int)> prioritizedTargets = new(); // score each target based on how many rules they satisfy. - foreach (WorldObject obj in targets) + foreach (WorldObject target in targets) { - Unit unit = obj?.ToUnit(); - if (unit == null) - continue; - int score = 0; + for (int i = 0; i < rules.Count; ++i) + if (rules[i].Rule(target)) + score |= 1 << (rules.Count - 1 - i); - foreach (PriorityRules rule in rules) - { - if (rule.condition(unit)) - score += rule.weight; - } - - prioritizedTargets.Add((obj, score)); + prioritizedTargets.Add((target, score)); } // the higher the value, the higher the priority is. - prioritizedTargets.Sort((left, right) => left.Item2.CompareTo(right.Item2)); + prioritizedTargets.OrderBy(pair => pair.Item2); - int cutOff = Math.Min(maxTargets, prioritizedTargets.Count); + int tieScore = prioritizedTargets[maxTargets - 1].Item2; // if there are ties at the cutoff, shuffle them to avoid selection bias. - if (cutOff < prioritizedTargets.Count) + if (prioritizedTargets[maxTargets].Item2 == tieScore) { - int tieScore = prioritizedTargets[cutOff - 1].Item2; - bool isTieScore((WorldObject, int) entry) { return entry.Item2 == tieScore; } // scan backwards to include tied entries before the cutoff. - int tieStart = (cutOff - 1); + int tieStart = (maxTargets - 1); while (tieStart > 0 && isTieScore(prioritizedTargets[tieStart - 1])) --tieStart; // scan forward to include tied entries after the cutoff. - int tieEnd = cutOff; + int tieEnd = maxTargets; while (tieEnd < prioritizedTargets.Count && isTieScore(prioritizedTargets[tieEnd])) ++tieEnd; @@ -1183,15 +1172,27 @@ namespace Game.Scripting targets.Clear(); - for (int i = 0; i < cutOff; ++i) + for (int i = 0; i < maxTargets; ++i) targets.Add(prioritizedTargets[i].Item1); } } - public struct PriorityRules + public struct TargetPriorityRule { - public int weight; - public Func condition; + public Func Rule; + + public TargetPriorityRule(Func func) + { + Rule = (WorldObject target) => func(target); + } + public TargetPriorityRule(Func func) + { + Rule = (WorldObject target) => target.IsUnit() && func(target.ToUnit()); + } + public TargetPriorityRule(Func func) + { + Rule = (WorldObject target) => target.IsPlayer() && func(target.ToPlayer()); + } } public class AuraScript : SpellScriptBase diff --git a/Source/Scripts/Spells/Priest.cs b/Source/Scripts/Spells/Priest.cs index 9af0a39e3..9c4db0d13 100644 --- a/Source/Scripts/Spells/Priest.cs +++ b/Source/Scripts/Spells/Priest.cs @@ -2055,7 +2055,7 @@ class spell_pri_power_word_radiance : SpellScript Unit explTarget = GetExplTargetUnit(); // we must add one since explicit target is always chosen. - int maxTargets = GetEffectInfo(2).CalcValue(GetCaster()) + 1; + int maxTargets = GetEffectInfo(2).CalcValue(caster) + 1; SortTargetsWithPriorityRules(targets, maxTargets, GetRadianceRules(caster, explTarget)); @@ -2078,15 +2078,15 @@ class spell_pri_power_word_radiance : SpellScript } } - List GetRadianceRules(Unit caster, Unit explTarget) + List GetRadianceRules(Unit caster, Unit explTarget) { - return new List() + return new List() { - new PriorityRules() { weight = 1, condition = target => target.IsInRaidWith(caster) }, - new PriorityRules() { weight = 2, condition = target => target.IsPlayer() || (target.IsCreature() && target.ToCreature().IsTreatedAsRaidUnit()) }, - new PriorityRules() { weight = 4, condition = target => !target.IsFullHealth() }, - new PriorityRules() { weight = 8, condition = target => !target.HasAura(SpellIds.AtonementEffect, caster.GetGUID()) }, - new PriorityRules() { weight = 16, condition = target => target == explTarget } + new TargetPriorityRule((WorldObject target) => target == explTarget), + new TargetPriorityRule((Unit target) => !target.HasAura(SpellIds.AtonementEffect, caster.GetGUID())), + new TargetPriorityRule((Unit target) => !target.ToUnit().IsFullHealth()), + new TargetPriorityRule((WorldObject target) => target.IsPlayer() || (target.IsCreature() && target.ToCreature().IsTreatedAsRaidUnit())), + new TargetPriorityRule((Unit target) => target.ToUnit().IsInRaidWith(caster)) }; }