From 0aefd8748581673ecbfc89b9e8ac1230f7743a1f Mon Sep 17 00:00:00 2001 From: reaperrr Date: Sun, 23 Oct 2016 20:09:52 +0200 Subject: [PATCH 1/4] Make Shroud object- instead of actor-based --- OpenRA.Game/Traits/World/Shroud.cs | 60 +++++----------------- OpenRA.Mods.Common/Traits/CreatesShroud.cs | 11 +++- OpenRA.Mods.Common/Traits/RevealsShroud.cs | 10 +++- 3 files changed, 31 insertions(+), 50 deletions(-) diff --git a/OpenRA.Game/Traits/World/Shroud.cs b/OpenRA.Game/Traits/World/Shroud.cs index cbfc695c81..aeece72891 100644 --- a/OpenRA.Game/Traits/World/Shroud.cs +++ b/OpenRA.Game/Traits/World/Shroud.cs @@ -54,8 +54,8 @@ namespace OpenRA.Traits // Cache of visibility that was added, so no matter what crazy trait code does, it // can't make us invalid. - readonly Dictionary visibility = new Dictionary(); - readonly Dictionary generation = new Dictionary(); + readonly Dictionary visibility = new Dictionary(); + readonly Dictionary generation = new Dictionary(); [Sync] bool disabled; public bool Disabled @@ -135,11 +135,8 @@ namespace OpenRA.Traits return ProjectedCellsInRange(map, map.CenterOfCell(cell), range); } - public void AddProjectedVisibility(Actor a, PPos[] visible) + public void AddProjectedVisibility(object key, PPos[] visible) { - if (!a.Owner.IsAlliedWith(self.Owner)) - return; - foreach (var puv in visible) { // Force cells outside the visible bounds invisible @@ -151,17 +148,17 @@ namespace OpenRA.Traits explored[uv] = true; } - if (visibility.ContainsKey(a)) + if (visibility.ContainsKey(key)) throw new InvalidOperationException("Attempting to add duplicate actor visibility"); - visibility[a] = visible; + visibility[key] = visible; Invalidate(visible); } - public void RemoveVisibility(Actor a) + public void RemoveVisibility(object key) { PPos[] visible; - if (!visibility.TryGetValue(a, out visible)) + if (!visibility.TryGetValue(key, out visible)) return; foreach (var puv in visible) @@ -171,64 +168,35 @@ namespace OpenRA.Traits visibleCount[(MPos)puv]--; } - visibility.Remove(a); + visibility.Remove(key); Invalidate(visible); } - public void AddProjectedShroudGeneration(Actor a, PPos[] shrouded) + public void AddProjectedShroudGeneration(object key, PPos[] shrouded) { - if (a.Owner.IsAlliedWith(self.Owner)) - return; - foreach (var uv in shrouded) generatedShroudCount[(MPos)uv]++; - if (generation.ContainsKey(a)) + if (generation.ContainsKey(key)) throw new InvalidOperationException("Attempting to add duplicate shroud generation"); - generation[a] = shrouded; + generation[key] = shrouded; Invalidate(shrouded); } - public void RemoveShroudGeneration(Actor a) + public void RemoveShroudGeneration(object key) { PPos[] shrouded; - if (!generation.TryGetValue(a, out shrouded)) + if (!generation.TryGetValue(key, out shrouded)) return; foreach (var uv in shrouded) generatedShroudCount[(MPos)uv]--; - generation.Remove(a); + generation.Remove(key); Invalidate(shrouded); } - public void UpdatePlayerStance(World w, Player player, Stance oldStance, Stance newStance) - { - if (oldStance == newStance) - return; - - foreach (var a in w.Actors.Where(a => a.Owner == player)) - { - PPos[] visible = null; - PPos[] shrouded = null; - foreach (var p in self.World.Players) - { - if (p.Shroud.visibility.TryGetValue(self, out visible)) - { - p.Shroud.RemoveVisibility(self); - p.Shroud.AddProjectedVisibility(self, visible); - } - - if (p.Shroud.generation.TryGetValue(self, out shrouded)) - { - p.Shroud.RemoveShroudGeneration(self); - p.Shroud.AddProjectedShroudGeneration(self, shrouded); - } - } - } - } - public void ExploreProjectedCells(World world, IEnumerable cells) { var changed = new HashSet(); diff --git a/OpenRA.Mods.Common/Traits/CreatesShroud.cs b/OpenRA.Mods.Common/Traits/CreatesShroud.cs index 4ff16dcb37..eb291a0243 100644 --- a/OpenRA.Mods.Common/Traits/CreatesShroud.cs +++ b/OpenRA.Mods.Common/Traits/CreatesShroud.cs @@ -20,8 +20,15 @@ namespace OpenRA.Mods.Common.Traits { public CreatesShroud(Actor self, CreatesShroudInfo info) : base(self, info) { } - protected override void AddCellsToPlayerShroud(Actor self, Player p, PPos[] uv) { p.Shroud.AddProjectedShroudGeneration(self, uv); } - protected override void RemoveCellsFromPlayerShroud(Actor self, Player p) { p.Shroud.RemoveShroudGeneration(self); } + + protected override void AddCellsToPlayerShroud(Actor self, Player p, PPos[] uv) + { + if (!self.Owner.IsAlliedWith(p)) + p.Shroud.AddProjectedShroudGeneration(this, uv); + } + + protected override void RemoveCellsFromPlayerShroud(Actor self, Player p) { p.Shroud.RemoveShroudGeneration(this); } + protected override bool IsDisabled(Actor self) { return self.IsDisabled(); } } } \ No newline at end of file diff --git a/OpenRA.Mods.Common/Traits/RevealsShroud.cs b/OpenRA.Mods.Common/Traits/RevealsShroud.cs index 654650cd19..4d904dbe03 100644 --- a/OpenRA.Mods.Common/Traits/RevealsShroud.cs +++ b/OpenRA.Mods.Common/Traits/RevealsShroud.cs @@ -20,7 +20,13 @@ namespace OpenRA.Mods.Common.Traits { public RevealsShroud(Actor self, RevealsShroudInfo info) : base(self, info) { } - protected override void AddCellsToPlayerShroud(Actor self, Player p, PPos[] uv) { p.Shroud.AddProjectedVisibility(self, uv); } - protected override void RemoveCellsFromPlayerShroud(Actor self, Player p) { p.Shroud.RemoveVisibility(self); } + + protected override void AddCellsToPlayerShroud(Actor self, Player p, PPos[] uv) + { + if (self.Owner.IsAlliedWith(p)) + p.Shroud.AddProjectedVisibility(this, uv); + } + + protected override void RemoveCellsFromPlayerShroud(Actor self, Player p) { p.Shroud.RemoveVisibility(this); } } } From a7e64bd8d834d76d23eef986cbc6c3ffb0412b10 Mon Sep 17 00:00:00 2001 From: reaperrr Date: Thu, 20 Oct 2016 14:02:59 +0200 Subject: [PATCH 2/4] Make AffectsShroud use explicit interfaces --- OpenRA.Mods.Common/Traits/AffectsShroud.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenRA.Mods.Common/Traits/AffectsShroud.cs b/OpenRA.Mods.Common/Traits/AffectsShroud.cs index 97f015497f..49b1de313f 100644 --- a/OpenRA.Mods.Common/Traits/AffectsShroud.cs +++ b/OpenRA.Mods.Common/Traits/AffectsShroud.cs @@ -55,7 +55,7 @@ namespace OpenRA.Mods.Common.Traits .ToArray(); } - public void Tick(Actor self) + void ITick.Tick(Actor self) { if (!self.IsInWorld) return; @@ -79,7 +79,7 @@ namespace OpenRA.Mods.Common.Traits } } - public void AddedToWorld(Actor self) + void INotifyAddedToWorld.AddedToWorld(Actor self) { var centerPosition = self.CenterPosition; var projectedPos = centerPosition - new WVec(0, centerPosition.Z, centerPosition.Z); @@ -90,7 +90,7 @@ namespace OpenRA.Mods.Common.Traits AddCellsToPlayerShroud(self, p, cells); } - public void RemovedFromWorld(Actor self) + void INotifyRemovedFromWorld.RemovedFromWorld(Actor self) { foreach (var p in self.World.Players) RemoveCellsFromPlayerShroud(self, p); From 6b5e7b8c1278dd1b29d6a2bb8e17d0b2898434ff Mon Sep 17 00:00:00 2001 From: reaperrr Date: Thu, 20 Oct 2016 14:10:46 +0200 Subject: [PATCH 3/4] Make AffectsShroud and derivatives upgradable --- OpenRA.Mods.Common/Traits/AffectsShroud.cs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/OpenRA.Mods.Common/Traits/AffectsShroud.cs b/OpenRA.Mods.Common/Traits/AffectsShroud.cs index 49b1de313f..357b01a7e8 100644 --- a/OpenRA.Mods.Common/Traits/AffectsShroud.cs +++ b/OpenRA.Mods.Common/Traits/AffectsShroud.cs @@ -14,30 +14,29 @@ using OpenRA.Traits; namespace OpenRA.Mods.Common.Traits { - public abstract class AffectsShroudInfo : ITraitInfo + public abstract class AffectsShroudInfo : UpgradableTraitInfo { public readonly WDist Range = WDist.Zero; [Desc("Possible values are CenterPosition (measure range from the center) and ", "Footprint (measure range from the footprint)")] public readonly VisibilityType Type = VisibilityType.Footprint; - - public abstract object Create(ActorInitializer init); } - public abstract class AffectsShroud : ITick, ISync, INotifyAddedToWorld, INotifyRemovedFromWorld + public abstract class AffectsShroud : UpgradableTrait, ITick, ISync, INotifyAddedToWorld, INotifyRemovedFromWorld { static readonly PPos[] NoCells = { }; - readonly AffectsShroudInfo info; [Sync] CPos cachedLocation; [Sync] bool cachedDisabled; + [Sync] bool cachedTraitDisabled; protected abstract void AddCellsToPlayerShroud(Actor self, Player player, PPos[] uv); protected abstract void RemoveCellsFromPlayerShroud(Actor self, Player player); protected virtual bool IsDisabled(Actor self) { return false; } - public AffectsShroud(Actor self, AffectsShroudInfo info) { this.info = info; } + public AffectsShroud(Actor self, AffectsShroudInfo info) + : base(info) { } PPos[] ProjectedCells(Actor self) { @@ -46,7 +45,7 @@ namespace OpenRA.Mods.Common.Traits if (range == WDist.Zero) return NoCells; - if (info.Type == VisibilityType.Footprint) + if (Info.Type == VisibilityType.Footprint) return self.OccupiesSpace.OccupiedCells() .SelectMany(kv => Shroud.ProjectedCellsInRange(map, kv.First, range)) .Distinct().ToArray(); @@ -64,12 +63,14 @@ namespace OpenRA.Mods.Common.Traits var projectedPos = centerPosition - new WVec(0, centerPosition.Z, centerPosition.Z); var projectedLocation = self.World.Map.CellContaining(projectedPos); var disabled = IsDisabled(self); + var traitDisabled = IsTraitDisabled; - if (cachedLocation == projectedLocation && cachedDisabled == disabled) + if (cachedLocation == projectedLocation && traitDisabled == cachedTraitDisabled && cachedDisabled == disabled) return; cachedLocation = projectedLocation; cachedDisabled = disabled; + cachedTraitDisabled = traitDisabled; var cells = ProjectedCells(self); foreach (var p in self.World.Players) @@ -85,7 +86,9 @@ namespace OpenRA.Mods.Common.Traits var projectedPos = centerPosition - new WVec(0, centerPosition.Z, centerPosition.Z); cachedLocation = self.World.Map.CellContaining(projectedPos); cachedDisabled = IsDisabled(self); + cachedTraitDisabled = IsTraitDisabled; var cells = ProjectedCells(self); + foreach (var p in self.World.Players) AddCellsToPlayerShroud(self, p, cells); } @@ -96,6 +99,6 @@ namespace OpenRA.Mods.Common.Traits RemoveCellsFromPlayerShroud(self, p); } - public WDist Range { get { return cachedDisabled ? WDist.Zero : info.Range; } } + public WDist Range { get { return (cachedDisabled || cachedTraitDisabled) ? WDist.Zero : Info.Range; } } } } From cafd50ef4372faa5cf1967e1d3e7956e283d4fa0 Mon Sep 17 00:00:00 2001 From: reaperrr Date: Tue, 25 Oct 2016 15:56:12 +0200 Subject: [PATCH 4/4] Make RevealsShroud and CreatesShroud use stances Instead of hardcoded (!)IsAlliedWith checks. --- OpenRA.Mods.Common/Traits/CreatesShroud.cs | 15 ++++++++++++--- OpenRA.Mods.Common/Traits/RevealsShroud.cs | 15 ++++++++++++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/OpenRA.Mods.Common/Traits/CreatesShroud.cs b/OpenRA.Mods.Common/Traits/CreatesShroud.cs index eb291a0243..4b6bb0af60 100644 --- a/OpenRA.Mods.Common/Traits/CreatesShroud.cs +++ b/OpenRA.Mods.Common/Traits/CreatesShroud.cs @@ -9,22 +9,31 @@ */ #endregion +using OpenRA.Traits; + namespace OpenRA.Mods.Common.Traits { public class CreatesShroudInfo : AffectsShroudInfo { + [Desc("Stance the watching player needs to see the generated shroud.")] + public readonly Stance ValidStances = Stance.Neutral | Stance.Enemy; + public override object Create(ActorInitializer init) { return new CreatesShroud(init.Self, this); } } public class CreatesShroud : AffectsShroud { + readonly CreatesShroudInfo info; + public CreatesShroud(Actor self, CreatesShroudInfo info) - : base(self, info) { } + : base(self, info) { this.info = info; } protected override void AddCellsToPlayerShroud(Actor self, Player p, PPos[] uv) { - if (!self.Owner.IsAlliedWith(p)) - p.Shroud.AddProjectedShroudGeneration(this, uv); + if (!info.ValidStances.HasStance(p.Stances[self.Owner])) + return; + + p.Shroud.AddProjectedShroudGeneration(this, uv); } protected override void RemoveCellsFromPlayerShroud(Actor self, Player p) { p.Shroud.RemoveShroudGeneration(this); } diff --git a/OpenRA.Mods.Common/Traits/RevealsShroud.cs b/OpenRA.Mods.Common/Traits/RevealsShroud.cs index 4d904dbe03..059e2d390c 100644 --- a/OpenRA.Mods.Common/Traits/RevealsShroud.cs +++ b/OpenRA.Mods.Common/Traits/RevealsShroud.cs @@ -9,22 +9,31 @@ */ #endregion +using OpenRA.Traits; + namespace OpenRA.Mods.Common.Traits { public class RevealsShroudInfo : AffectsShroudInfo { + [Desc("Stance the watching player needs to see the shroud removed.")] + public readonly Stance ValidStances = Stance.Ally; + public override object Create(ActorInitializer init) { return new RevealsShroud(init.Self, this); } } public class RevealsShroud : AffectsShroud { + readonly RevealsShroudInfo info; + public RevealsShroud(Actor self, RevealsShroudInfo info) - : base(self, info) { } + : base(self, info) { this.info = info; } protected override void AddCellsToPlayerShroud(Actor self, Player p, PPos[] uv) { - if (self.Owner.IsAlliedWith(p)) - p.Shroud.AddProjectedVisibility(this, uv); + if (!info.ValidStances.HasStance(p.Stances[self.Owner])) + return; + + p.Shroud.AddProjectedVisibility(this, uv); } protected override void RemoveCellsFromPlayerShroud(Actor self, Player p) { p.Shroud.RemoveVisibility(this); }