diff --git a/OpenRA.Game/Traits/World/ActorMap.cs b/OpenRA.Game/Traits/World/ActorMap.cs index 9a19b9c02d..b181c26297 100644 --- a/OpenRA.Game/Traits/World/ActorMap.cs +++ b/OpenRA.Game/Traits/World/ActorMap.cs @@ -98,22 +98,26 @@ namespace OpenRA.Traits WPos position; WDist range; + WDist vRange; + IEnumerable currentActors = Enumerable.Empty(); - public ProximityTrigger(WPos pos, WDist range, Action onActorEntered, Action onActorExited) + public ProximityTrigger(WPos pos, WDist range, WDist vRange, Action onActorEntered, Action onActorExited) { this.onActorEntered = onActorEntered; this.onActorExited = onActorExited; - Update(pos, range); + Update(pos, range, vRange); } - public void Update(WPos newPos, WDist newRange) + public void Update(WPos newPos, WDist newRange, WDist newVRange) { position = newPos; range = newRange; + vRange = newVRange; + + var offset = new WVec(newRange, newRange, newVRange); - var offset = new WVec(newRange, newRange, WDist.Zero); TopLeft = newPos - offset; BottomRight = newPos + offset; @@ -128,7 +132,8 @@ namespace OpenRA.Traits var oldActors = currentActors; var delta = new WVec(range, range, WDist.Zero); currentActors = am.ActorsInBox(position - delta, position + delta) - .Where(a => (a.CenterPosition - position).HorizontalLengthSquared < range.LengthSquared) + .Where(a => (a.CenterPosition - position).HorizontalLengthSquared < range.LengthSquared + && (vRange.Length == 0 || (a.World.Map.DistanceAboveTerrain(a.CenterPosition).LengthSquared <= vRange.LengthSquared))) .ToList(); var entered = currentActors.Except(oldActors); @@ -439,10 +444,10 @@ namespace OpenRA.Traits } } - public int AddProximityTrigger(WPos pos, WDist range, Action onEntry, Action onExit) + public int AddProximityTrigger(WPos pos, WDist range, WDist vRange, Action onEntry, Action onExit) { var id = nextTriggerId++; - var t = new ProximityTrigger(pos, range, onEntry, onExit); + var t = new ProximityTrigger(pos, range, vRange, onEntry, onExit); proximityTriggers.Add(id, t); foreach (var bin in BinsInBox(t.TopLeft, t.BottomRight)) @@ -463,7 +468,7 @@ namespace OpenRA.Traits t.Dispose(); } - public void UpdateProximityTrigger(int id, WPos newPos, WDist newRange) + public void UpdateProximityTrigger(int id, WPos newPos, WDist newRange, WDist newVRange) { ProximityTrigger t; if (!proximityTriggers.TryGetValue(id, out t)) @@ -472,7 +477,7 @@ namespace OpenRA.Traits foreach (var bin in BinsInBox(t.TopLeft, t.BottomRight)) bin.ProximityTriggers.Remove(t); - t.Update(newPos, newRange); + t.Update(newPos, newRange, newVRange); foreach (var bin in BinsInBox(t.TopLeft, t.BottomRight)) bin.ProximityTriggers.Add(t); diff --git a/OpenRA.Game/WVec.cs b/OpenRA.Game/WVec.cs index 068845bf37..50c306fd29 100644 --- a/OpenRA.Game/WVec.cs +++ b/OpenRA.Game/WVec.cs @@ -41,6 +41,8 @@ namespace OpenRA public int Length { get { return (int)Exts.ISqrt(LengthSquared); } } public long HorizontalLengthSquared { get { return (long)X * X + (long)Y * Y; } } public int HorizontalLength { get { return (int)Exts.ISqrt(HorizontalLengthSquared); } } + public long VerticalLengthSquared { get { return (long)Z * Z; } } + public int VerticalLength { get { return (int)Exts.ISqrt(VerticalLengthSquared); } } public WVec Rotate(WRot rot) { diff --git a/OpenRA.Mods.Common/Scripting/Global/TriggerGlobal.cs b/OpenRA.Mods.Common/Scripting/Global/TriggerGlobal.cs index aa034cd795..ef7120cc0d 100644 --- a/OpenRA.Mods.Common/Scripting/Global/TriggerGlobal.cs +++ b/OpenRA.Mods.Common/Scripting/Global/TriggerGlobal.cs @@ -373,7 +373,7 @@ namespace OpenRA.Mods.Common.Scripting } }; - triggerId = Context.World.ActorMap.AddProximityTrigger(pos, range, invokeEntry, null); + triggerId = Context.World.ActorMap.AddProximityTrigger(pos, range, WDist.Zero, invokeEntry, null); return triggerId; } @@ -400,7 +400,7 @@ namespace OpenRA.Mods.Common.Scripting } }; - triggerId = Context.World.ActorMap.AddProximityTrigger(pos, range, null, invokeExit); + triggerId = Context.World.ActorMap.AddProximityTrigger(pos, range, WDist.Zero, null, invokeExit); return triggerId; } diff --git a/OpenRA.Mods.Common/Traits/ProximityCapturable.cs b/OpenRA.Mods.Common/Traits/ProximityCapturable.cs index 135ff4bcd8..9a10ead140 100644 --- a/OpenRA.Mods.Common/Traits/ProximityCapturable.cs +++ b/OpenRA.Mods.Common/Traits/ProximityCapturable.cs @@ -67,7 +67,7 @@ namespace OpenRA.Mods.Common.Traits return; // TODO: Eventually support CellTriggers as well - proximityTrigger = self.World.ActorMap.AddProximityTrigger(self.CenterPosition, Info.Range, ActorEntered, ActorLeft); + proximityTrigger = self.World.ActorMap.AddProximityTrigger(self.CenterPosition, Info.Range, WDist.Zero, ActorEntered, ActorLeft); } void INotifyRemovedFromWorld.RemovedFromWorld(Actor self) @@ -84,7 +84,7 @@ namespace OpenRA.Mods.Common.Traits if (!self.IsInWorld || self.CenterPosition == prevPosition) return; - self.World.ActorMap.UpdateProximityTrigger(proximityTrigger, self.CenterPosition, Info.Range); + self.World.ActorMap.UpdateProximityTrigger(proximityTrigger, self.CenterPosition, Info.Range, WDist.Zero); prevPosition = self.CenterPosition; } diff --git a/OpenRA.Mods.Common/Traits/Upgrades/UpgradeActorsNear.cs b/OpenRA.Mods.Common/Traits/Upgrades/UpgradeActorsNear.cs index 92031b42d6..ec0c19ad0d 100644 --- a/OpenRA.Mods.Common/Traits/Upgrades/UpgradeActorsNear.cs +++ b/OpenRA.Mods.Common/Traits/Upgrades/UpgradeActorsNear.cs @@ -23,6 +23,10 @@ namespace OpenRA.Mods.Common.Traits [Desc("The range to search for actors to upgrade.")] public readonly WDist Range = WDist.FromCells(3); + [Desc("The maximum vertical range above terrain to search for actors to upgrade.", + "Ignored if 0 (actors are upgraded regardless of vertical distance).")] + public readonly WDist MaximumVerticalOffset = WDist.Zero; + [Desc("What diplomatic stances are affected.")] public readonly Stance ValidStances = Stance.Ally; @@ -44,6 +48,8 @@ namespace OpenRA.Mods.Common.Traits WPos cachedPosition; WDist cachedRange; WDist desiredRange; + WDist cachedVRange; + WDist desiredVRange; bool cachedDisabled = true; @@ -52,12 +58,13 @@ namespace OpenRA.Mods.Common.Traits this.info = info; this.self = self; cachedRange = info.Range; + cachedVRange = info.MaximumVerticalOffset; } public void AddedToWorld(Actor self) { cachedPosition = self.CenterPosition; - proximityTrigger = self.World.ActorMap.AddProximityTrigger(cachedPosition, cachedRange, ActorEntered, ActorExited); + proximityTrigger = self.World.ActorMap.AddProximityTrigger(cachedPosition, cachedRange, cachedVRange, ActorEntered, ActorExited); } public void RemovedFromWorld(Actor self) @@ -73,14 +80,16 @@ namespace OpenRA.Mods.Common.Traits { Game.Sound.Play(disabled ? info.DisableSound : info.EnableSound, self.CenterPosition); desiredRange = disabled ? WDist.Zero : info.Range; + desiredVRange = disabled ? WDist.Zero : info.MaximumVerticalOffset; cachedDisabled = disabled; } - if (self.CenterPosition != cachedPosition || desiredRange != cachedRange) + if (self.CenterPosition != cachedPosition || desiredRange != cachedRange || desiredVRange != cachedVRange) { cachedPosition = self.CenterPosition; cachedRange = desiredRange; - self.World.ActorMap.UpdateProximityTrigger(proximityTrigger, cachedPosition, cachedRange); + cachedVRange = desiredVRange; + self.World.ActorMap.UpdateProximityTrigger(proximityTrigger, cachedPosition, cachedRange, cachedVRange); } }