diff --git a/OpenRA.Game/Traits/Player/FrozenActorLayer.cs b/OpenRA.Game/Traits/Player/FrozenActorLayer.cs index 54ce10142e..dc74e6c188 100644 --- a/OpenRA.Game/Traits/Player/FrozenActorLayer.cs +++ b/OpenRA.Game/Traits/Player/FrozenActorLayer.cs @@ -40,7 +40,7 @@ namespace OpenRA.Traits public bool Visible; - public FrozenActor(Actor self, MPos[] footprint, CellRegion footprintRegion) + public FrozenActor(Actor self, MPos[] footprint, CellRegion footprintRegion, Shroud shroud) { actor = self; Footprint = footprint; @@ -48,6 +48,8 @@ namespace OpenRA.Traits CenterPosition = self.CenterPosition; Bounds = self.Bounds; + + UpdateVisibility(shroud); } public uint ID { get { return actor.ActorID; } } @@ -56,7 +58,15 @@ namespace OpenRA.Traits public Actor Actor { get { return !actor.IsDead ? actor : null; } } int flashTicks; - public void Tick(World world, Shroud shroud) + public void Tick(Shroud shroud) + { + UpdateVisibility(shroud); + + if (flashTicks > 0) + flashTicks--; + } + + void UpdateVisibility(Shroud shroud) { // We are doing the following LINQ manually to avoid allocating an extra delegate since this is a hot path. // Visible = !Footprint.Any(shroud.IsVisibleTest(FootprintRegion)); @@ -68,9 +78,6 @@ namespace OpenRA.Traits Visible = false; break; } - - if (flashTicks > 0) - flashTicks--; } public void Flash() @@ -129,22 +136,24 @@ namespace OpenRA.Traits VisibilityHash = 0; FrozenHash = 0; - foreach (var kv in frozen) + foreach (var kvp in frozen) { - FrozenHash += (int)kv.Key; + var hash = (int)kvp.Key; + FrozenHash += hash; - kv.Value.Tick(self.World, self.Owner.Shroud); - if (kv.Value.Visible) - VisibilityHash += (int)kv.Key; + var frozenActor = kvp.Value; + frozenActor.Tick(self.Owner.Shroud); - if (!kv.Value.Visible && kv.Value.Actor == null) - remove.Add(kv.Key); + if (frozenActor.Visible) + VisibilityHash += hash; + else if (frozenActor.Actor == null) + remove.Add(kvp.Key); } - foreach (var r in remove) + foreach (var actorID in remove) { - world.ScreenMap.Remove(owner, frozen[r]); - frozen.Remove(r); + world.ScreenMap.Remove(owner, frozen[actorID]); + frozen.Remove(actorID); } } diff --git a/OpenRA.Mods.Common/Traits/Modifiers/FrozenUnderFog.cs b/OpenRA.Mods.Common/Traits/Modifiers/FrozenUnderFog.cs index 5daf8bcc61..9ffaa2356e 100644 --- a/OpenRA.Mods.Common/Traits/Modifiers/FrozenUnderFog.cs +++ b/OpenRA.Mods.Common/Traits/Modifiers/FrozenUnderFog.cs @@ -48,7 +48,6 @@ namespace OpenRA.Mods.Common.Traits footprint = footprintCells.Select(cell => cell.ToMPos(init.World.Map)).ToArray(); footprintRegion = CellRegion.BoundingRegion(init.World.Map.TileShape, footprintCells); tooltip = Exts.Lazy(() => init.Self.TraitsImplementing().FirstOrDefault()); - tooltip = Exts.Lazy(() => init.Self.TraitsImplementing().FirstOrDefault()); health = Exts.Lazy(() => init.Self.TraitOrDefault()); frozen = new Dictionary(); @@ -66,55 +65,43 @@ namespace OpenRA.Mods.Common.Traits return; VisibilityHash = 0; - foreach (var p in self.World.Players) - { - // We are doing the following LINQ manually to avoid allocating an extra delegate since this is a hot path. - // var isVisible = footprint.Any(p.Shroud.IsVisibleTest(footprintRegion)); - var isVisibleTest = p.Shroud.IsVisibleTest(footprintRegion); - var isVisible = false; - foreach (var uv in footprint) - if (isVisibleTest(uv)) - { - isVisible = true; - break; - } - - visible[p] = isVisible; - if (isVisible) - VisibilityHash += p.ClientIndex; - } - - if (!initialized) - { - foreach (var p in self.World.Players) - { - visible[p] |= startsRevealed; - p.PlayerActor.Trait().Add(frozen[p] = new FrozenActor(self, footprint, footprintRegion)); - } - - initialized = true; - } - foreach (var player in self.World.Players) { - if (!visible[player]) + bool isVisible; + FrozenActor frozenActor; + if (!initialized) + { + frozen[player] = frozenActor = new FrozenActor(self, footprint, footprintRegion, player.Shroud); + player.PlayerActor.Trait().Add(frozenActor); + isVisible = visible[player] |= startsRevealed; + } + else + { + frozenActor = frozen[player]; + isVisible = visible[player] = !frozenActor.Visible; + } + + if (isVisible) + VisibilityHash += player.ClientIndex; + else continue; - var actor = frozen[player]; - actor.Owner = self.Owner; + frozenActor.Owner = self.Owner; if (health.Value != null) { - actor.HP = health.Value.HP; - actor.DamageState = health.Value.DamageState; + frozenActor.HP = health.Value.HP; + frozenActor.DamageState = health.Value.DamageState; } if (tooltip.Value != null) { - actor.TooltipInfo = tooltip.Value.TooltipInfo; - actor.TooltipOwner = tooltip.Value.Owner; + frozenActor.TooltipInfo = tooltip.Value.TooltipInfo; + frozenActor.TooltipOwner = tooltip.Value.Owner; } } + + initialized = true; } public void TickRender(WorldRenderer wr, Actor self)