diff --git a/Source/Game/Scripting/SpellScript.cs b/Source/Game/Scripting/SpellScript.cs index d45825725..d9cf5c254 100644 --- a/Source/Game/Scripting/SpellScript.cs +++ b/Source/Game/Scripting/SpellScript.cs @@ -20,6 +20,7 @@ using Game.Entities; using Game.Spells; using System; using System.Collections.Generic; +using System.Linq; namespace Game.Scripting { @@ -866,6 +867,66 @@ namespace Game.Scripting m_spell.m_customError = result; } + + public void SelectRandomInjuredTargets(List targets, uint maxTargets, bool prioritizePlayers) + { + if (targets.Count <= maxTargets) + return; + + //List of all player targets. + var tempPlayers = targets.Where(p => p.IsPlayer()).ToList(); + + //List of all injured non player targets. + var tempInjuredUnits = targets.Where(target => target.IsUnit() && !target.ToUnit().IsFullHealth()).ToList(); + + //List of all none injured non player targets. + var tempNoneInjuredUnits = targets.Where(target => target.IsUnit() && target.ToUnit().IsFullHealth()).ToList(); + + targets.Clear(); + if (prioritizePlayers) + { + if (tempPlayers.Count < maxTargets) + { + // not enough players, add nonplayer targets + // prioritize injured nonplayers over full health nonplayers + + if (tempPlayers.Count + tempInjuredUnits.Count < maxTargets) + { + // not enough players + injured nonplayers + // fill remainder with random full health nonplayers + targets.AddRange(tempPlayers); + targets.AddRange(tempInjuredUnits); + targets.AddRange(tempNoneInjuredUnits.Shuffle()); + } + else if (tempPlayers.Count + tempInjuredUnits.Count > maxTargets) + { + // randomize injured nonplayers order + // final list will contain all players + random injured nonplayers + targets.AddRange(tempPlayers); + targets.AddRange(tempInjuredUnits.Shuffle()); + } + + targets.Resize(maxTargets); + return; + } + } + + var lookupPlayers = tempPlayers.ToLookup(target => !target.ToUnit().IsFullHealth()); + if (lookupPlayers[true].Count() < maxTargets) + { + // not enough injured units + // fill remainder with full health units + targets.AddRange(lookupPlayers[true]); + targets.AddRange(lookupPlayers[false].Shuffle())); + } + else if (lookupPlayers[true].Count() > maxTargets) + { + // select random injured units + targets.AddRange(lookupPlayers[true].Shuffle()); + } + + targets.Resize(maxTargets); + } } public class AuraScript : BaseSpellScript diff --git a/Source/Scripts/Spells/Shaman.cs b/Source/Scripts/Spells/Shaman.cs index 293129067..fb1da07e9 100644 --- a/Source/Scripts/Spells/Shaman.cs +++ b/Source/Scripts/Spells/Shaman.cs @@ -177,7 +177,7 @@ namespace Scripts.Spells.Shaman void ResizeTargets(List targets) { - targets.Resize(3); + SelectRandomInjuredTargets(targets, 3, true); } public override void Register() @@ -310,12 +310,7 @@ namespace Scripts.Spells.Shaman void FilterTargets(List targets) { - uint maxTargets = 6; - if (targets.Count > maxTargets) - { - targets.Sort(new HealthPctOrderPred()); - targets.Resize(maxTargets); - } + SelectRandomInjuredTargets(targets, 6, true); } void CountEffectivelyHealedTarget() @@ -586,18 +581,27 @@ namespace Scripts.Spells.Shaman OnEffectPeriodic.Add(new EffectPeriodicHandler(HandleEffectPeriodic, 1, AuraType.PeriodicDummy)); } } + + [Script] // 73921 - Healing Rain + class spell_sha_healing_rain_target_limit : SpellScript + { + void SelectTargets(List targets) + { + SelectRandomInjuredTargets(targets, 6, true); + } + + public override void Register() + { + OnObjectAreaTargetSelect.Add(new ObjectAreaTargetSelectHandler(SelectTargets, 0, Targets.UnitDestAreaAlly)); + } + } [Script] // 52042 - Healing Stream Totem class spell_sha_healing_stream_totem_heal : SpellScript { void SelectTargets(List targets) { - targets.RemoveAll(target => !target.ToUnit() || target.ToUnit().IsFullHealth()); - - targets.RandomResize(1); - - if (targets.Empty()) - targets.Add(GetOriginalCaster()); + SelectRandomInjuredTargets(targets, 1, true); } public override void Register()