Fix FrozenUnderFog / FrozenActor visibility consistency.
This fixes cases where both objects return visible / not when queried at the wrong time during a tick.
This commit is contained in:
@@ -18,6 +18,11 @@ using OpenRA.Primitives;
|
|||||||
|
|
||||||
namespace OpenRA.Traits
|
namespace OpenRA.Traits
|
||||||
{
|
{
|
||||||
|
public interface ICreatesFrozenActors
|
||||||
|
{
|
||||||
|
void OnVisibilityChanged(FrozenActor frozen);
|
||||||
|
}
|
||||||
|
|
||||||
[Desc("Required for FrozenUnderFog to work. Attach this to the player actor.")]
|
[Desc("Required for FrozenUnderFog to work. Attach this to the player actor.")]
|
||||||
public class FrozenActorLayerInfo : Requires<ShroudInfo>, ITraitInfo
|
public class FrozenActorLayerInfo : Requires<ShroudInfo>, ITraitInfo
|
||||||
{
|
{
|
||||||
@@ -32,6 +37,7 @@ namespace OpenRA.Traits
|
|||||||
public readonly PPos[] Footprint;
|
public readonly PPos[] Footprint;
|
||||||
public readonly WPos CenterPosition;
|
public readonly WPos CenterPosition;
|
||||||
readonly Actor actor;
|
readonly Actor actor;
|
||||||
|
readonly ICreatesFrozenActors frozenTrait;
|
||||||
readonly Player viewer;
|
readonly Player viewer;
|
||||||
readonly Shroud shroud;
|
readonly Shroud shroud;
|
||||||
|
|
||||||
@@ -70,9 +76,10 @@ namespace OpenRA.Traits
|
|||||||
|
|
||||||
int flashTicks;
|
int flashTicks;
|
||||||
|
|
||||||
public FrozenActor(Actor actor, PPos[] footprint, Player viewer, bool startsRevealed)
|
public FrozenActor(Actor actor, ICreatesFrozenActors frozenTrait, PPos[] footprint, Player viewer, bool startsRevealed)
|
||||||
{
|
{
|
||||||
this.actor = actor;
|
this.actor = actor;
|
||||||
|
this.frozenTrait = frozenTrait;
|
||||||
this.viewer = viewer;
|
this.viewer = viewer;
|
||||||
shroud = viewer.Shroud;
|
shroud = viewer.Shroud;
|
||||||
NeedRenderables = startsRevealed;
|
NeedRenderables = startsRevealed;
|
||||||
@@ -153,6 +160,11 @@ namespace OpenRA.Traits
|
|||||||
Shrouded = false;
|
Shrouded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Force the backing trait to update so other actors can't
|
||||||
|
// query inconsistent state (both hidden or both visible)
|
||||||
|
if (Visible != wasVisible)
|
||||||
|
frozenTrait.OnVisibilityChanged(this);
|
||||||
|
|
||||||
NeedRenderables |= Visible && !wasVisible;
|
NeedRenderables |= Visible && !wasVisible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -27,7 +28,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
public object Create(ActorInitializer init) { return new FrozenUnderFog(init, this); }
|
public object Create(ActorInitializer init) { return new FrozenUnderFog(init, this); }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class FrozenUnderFog : IRenderModifier, IDefaultVisibility, ITick, ITickRender, ISync, INotifyCreated
|
public class FrozenUnderFog : ICreatesFrozenActors, IRenderModifier, IDefaultVisibility, ITick, ITickRender, ISync, INotifyCreated
|
||||||
{
|
{
|
||||||
[Sync] public int VisibilityHash;
|
[Sync] public int VisibilityHash;
|
||||||
|
|
||||||
@@ -37,6 +38,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
PlayerDictionary<FrozenState> frozenStates;
|
PlayerDictionary<FrozenState> frozenStates;
|
||||||
bool isRendering;
|
bool isRendering;
|
||||||
|
bool created;
|
||||||
|
|
||||||
class FrozenState
|
class FrozenState
|
||||||
{
|
{
|
||||||
@@ -67,7 +69,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
{
|
{
|
||||||
frozenStates = new PlayerDictionary<FrozenState>(self.World, (player, playerIndex) =>
|
frozenStates = new PlayerDictionary<FrozenState>(self.World, (player, playerIndex) =>
|
||||||
{
|
{
|
||||||
var frozenActor = new FrozenActor(self, footprint, player, startsRevealed);
|
var frozenActor = new FrozenActor(self, this, footprint, player, startsRevealed);
|
||||||
player.PlayerActor.Trait<FrozenActorLayer>().Add(frozenActor);
|
player.PlayerActor.Trait<FrozenActorLayer>().Add(frozenActor);
|
||||||
return new FrozenState(frozenActor) { IsVisible = startsRevealed };
|
return new FrozenState(frozenActor) { IsVisible = startsRevealed };
|
||||||
});
|
});
|
||||||
@@ -75,6 +77,8 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
if (startsRevealed)
|
if (startsRevealed)
|
||||||
for (var playerIndex = 0; playerIndex < frozenStates.Count; playerIndex++)
|
for (var playerIndex = 0; playerIndex < frozenStates.Count; playerIndex++)
|
||||||
UpdateFrozenActor(self, frozenStates[playerIndex].FrozenActor, playerIndex);
|
UpdateFrozenActor(self, frozenStates[playerIndex].FrozenActor, playerIndex);
|
||||||
|
|
||||||
|
created = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateFrozenActor(Actor self, FrozenActor frozenActor, int playerIndex)
|
void UpdateFrozenActor(Actor self, FrozenActor frozenActor, int playerIndex)
|
||||||
@@ -83,6 +87,17 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
frozenActor.RefreshState();
|
frozenActor.RefreshState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ICreatesFrozenActors.OnVisibilityChanged(FrozenActor frozen)
|
||||||
|
{
|
||||||
|
// Ignore callbacks during initial setup
|
||||||
|
if (!created)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Update state visibility to match the frozen actor to ensure consistency within the tick
|
||||||
|
// The rest of the state will be updated by ITick.Tick below
|
||||||
|
frozenStates[frozen.Viewer].IsVisible = !frozen.Visible;
|
||||||
|
}
|
||||||
|
|
||||||
bool IsVisibleInner(Actor self, Player byPlayer)
|
bool IsVisibleInner(Actor self, Player byPlayer)
|
||||||
{
|
{
|
||||||
// If fog is disabled visibility is determined by shroud
|
// If fog is disabled visibility is determined by shroud
|
||||||
|
|||||||
Reference in New Issue
Block a user