Core/Spells: Simplify SortTargetsWithPriorityRules
Port From (https://github.com/TrinityCore/TrinityCore/commit/03d072da463769ff02090e08d12b4da3f6a49222)
This commit is contained in:
@@ -1128,9 +1128,7 @@ namespace Game.Scripting
|
|||||||
targets.Resize(maxTargets);
|
targets.Resize(maxTargets);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<PriorityRules> CreatePriorityRules(List<PriorityRules> rules) { return rules; }
|
public void SortTargetsWithPriorityRules(List<WorldObject> targets, int maxTargets, List<TargetPriorityRule> rules)
|
||||||
|
|
||||||
public void SortTargetsWithPriorityRules(List<WorldObject> targets, int maxTargets, List<PriorityRules> rules)
|
|
||||||
{
|
{
|
||||||
if (targets.Count <= maxTargets)
|
if (targets.Count <= maxTargets)
|
||||||
return;
|
return;
|
||||||
@@ -1138,42 +1136,33 @@ namespace Game.Scripting
|
|||||||
List<(WorldObject, int)> prioritizedTargets = new();
|
List<(WorldObject, int)> prioritizedTargets = new();
|
||||||
|
|
||||||
// score each target based on how many rules they satisfy.
|
// 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;
|
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)
|
prioritizedTargets.Add((target, score));
|
||||||
{
|
|
||||||
if (rule.condition(unit))
|
|
||||||
score += rule.weight;
|
|
||||||
}
|
|
||||||
|
|
||||||
prioritizedTargets.Add((obj, score));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// the higher the value, the higher the priority is.
|
// 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 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; }
|
bool isTieScore((WorldObject, int) entry) { return entry.Item2 == tieScore; }
|
||||||
|
|
||||||
// scan backwards to include tied entries before the cutoff.
|
// scan backwards to include tied entries before the cutoff.
|
||||||
int tieStart = (cutOff - 1);
|
int tieStart = (maxTargets - 1);
|
||||||
while (tieStart > 0 && isTieScore(prioritizedTargets[tieStart - 1]))
|
while (tieStart > 0 && isTieScore(prioritizedTargets[tieStart - 1]))
|
||||||
--tieStart;
|
--tieStart;
|
||||||
|
|
||||||
// scan forward to include tied entries after the cutoff.
|
// scan forward to include tied entries after the cutoff.
|
||||||
int tieEnd = cutOff;
|
int tieEnd = maxTargets;
|
||||||
while (tieEnd < prioritizedTargets.Count && isTieScore(prioritizedTargets[tieEnd]))
|
while (tieEnd < prioritizedTargets.Count && isTieScore(prioritizedTargets[tieEnd]))
|
||||||
++tieEnd;
|
++tieEnd;
|
||||||
|
|
||||||
@@ -1183,15 +1172,27 @@ namespace Game.Scripting
|
|||||||
|
|
||||||
targets.Clear();
|
targets.Clear();
|
||||||
|
|
||||||
for (int i = 0; i < cutOff; ++i)
|
for (int i = 0; i < maxTargets; ++i)
|
||||||
targets.Add(prioritizedTargets[i].Item1);
|
targets.Add(prioritizedTargets[i].Item1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public struct PriorityRules
|
public struct TargetPriorityRule
|
||||||
{
|
{
|
||||||
public int weight;
|
public Func<WorldObject, bool> Rule;
|
||||||
public Func<Unit, bool> condition;
|
|
||||||
|
public TargetPriorityRule(Func<WorldObject, bool> func)
|
||||||
|
{
|
||||||
|
Rule = (WorldObject target) => func(target);
|
||||||
|
}
|
||||||
|
public TargetPriorityRule(Func<Unit, bool> func)
|
||||||
|
{
|
||||||
|
Rule = (WorldObject target) => target.IsUnit() && func(target.ToUnit());
|
||||||
|
}
|
||||||
|
public TargetPriorityRule(Func<Player, bool> func)
|
||||||
|
{
|
||||||
|
Rule = (WorldObject target) => target.IsPlayer() && func(target.ToPlayer());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AuraScript : SpellScriptBase
|
public class AuraScript : SpellScriptBase
|
||||||
|
|||||||
@@ -2055,7 +2055,7 @@ class spell_pri_power_word_radiance : SpellScript
|
|||||||
Unit explTarget = GetExplTargetUnit();
|
Unit explTarget = GetExplTargetUnit();
|
||||||
|
|
||||||
// we must add one since explicit target is always chosen.
|
// 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));
|
SortTargetsWithPriorityRules(targets, maxTargets, GetRadianceRules(caster, explTarget));
|
||||||
|
|
||||||
@@ -2078,15 +2078,15 @@ class spell_pri_power_word_radiance : SpellScript
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<PriorityRules> GetRadianceRules(Unit caster, Unit explTarget)
|
List<TargetPriorityRule> GetRadianceRules(Unit caster, Unit explTarget)
|
||||||
{
|
{
|
||||||
return new List<PriorityRules>()
|
return new List<TargetPriorityRule>()
|
||||||
{
|
{
|
||||||
new PriorityRules() { weight = 1, condition = target => target.IsInRaidWith(caster) },
|
new TargetPriorityRule((WorldObject target) => target == explTarget),
|
||||||
new PriorityRules() { weight = 2, condition = target => target.IsPlayer() || (target.IsCreature() && target.ToCreature().IsTreatedAsRaidUnit()) },
|
new TargetPriorityRule((Unit target) => !target.HasAura(SpellIds.AtonementEffect, caster.GetGUID())),
|
||||||
new PriorityRules() { weight = 4, condition = target => !target.IsFullHealth() },
|
new TargetPriorityRule((Unit target) => !target.ToUnit().IsFullHealth()),
|
||||||
new PriorityRules() { weight = 8, condition = target => !target.HasAura(SpellIds.AtonementEffect, caster.GetGUID()) },
|
new TargetPriorityRule((WorldObject target) => target.IsPlayer() || (target.IsCreature() && target.ToCreature().IsTreatedAsRaidUnit())),
|
||||||
new PriorityRules() { weight = 16, condition = target => target == explTarget }
|
new TargetPriorityRule((Unit target) => target.ToUnit().IsInRaidWith(caster))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user