Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix frozen actor regressions #14619

Merged
merged 4 commits into from
Jan 1, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions OpenRA.Game/Network/Order.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,15 +107,18 @@ public static Order Deserialize(World world, BinaryReader r)

case TargetType.FrozenActor:
{
var playerActorID = r.ReadUInt32();
var frozenActorID = r.ReadUInt32();

Actor playerActor;
if (world == null || !TryGetActorFromUInt(world, r.ReadUInt32(), out playerActor))
if (world == null || !TryGetActorFromUInt(world, playerActorID, out playerActor))
break;

var frozenLayer = playerActor.TraitOrDefault<FrozenActorLayer>();
if (frozenLayer == null)
break;

var frozen = frozenLayer.FromID(r.ReadUInt32());
var frozen = frozenLayer.FromID(frozenActorID);
if (frozen != null)
target = Target.FromFrozenActor(frozen);

Expand Down Expand Up @@ -281,7 +284,7 @@ public byte[] Serialize()
w.Write(UIntFromActor(Target.SerializableActor));
break;
case TargetType.FrozenActor:
w.Write(Target.FrozenActor.Owner.PlayerActor.ActorID);
w.Write(Target.FrozenActor.Viewer.PlayerActor.ActorID);
w.Write(Target.FrozenActor.ID);
break;
case TargetType.Terrain:
Expand Down
66 changes: 37 additions & 29 deletions OpenRA.Game/Traits/Player/FrozenActorLayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public class FrozenActor
public readonly PPos[] Footprint;
public readonly WPos CenterPosition;
readonly Actor actor;
readonly Player viewer;
readonly Shroud shroud;

public Player Owner { get; private set; }
Expand Down Expand Up @@ -59,10 +60,11 @@ public class FrozenActor

int flashTicks;

public FrozenActor(Actor self, PPos[] footprint, Shroud shroud, bool startsRevealed)
public FrozenActor(Actor actor, PPos[] footprint, Player viewer, bool startsRevealed)
{
actor = self;
this.shroud = shroud;
this.actor = actor;
this.viewer = viewer;
shroud = viewer.Shroud;
NeedRenderables = startsRevealed;

// Consider all cells inside the map area (ignoring the current map bounds)
Expand All @@ -81,11 +83,11 @@ public FrozenActor(Actor self, PPos[] footprint, Shroud shroud, bool startsRevea
footprint.Select(p => p.ToString()).JoinWith("|"),
footprint.Select(p => shroud.Contains(p).ToString()).JoinWith("|")));

CenterPosition = self.CenterPosition;
CenterPosition = actor.CenterPosition;
TargetTypes = new HashSet<string>();

tooltips = self.TraitsImplementing<ITooltip>().ToArray();
health = self.TraitOrDefault<IHealth>();
tooltips = actor.TraitsImplementing<ITooltip>().ToArray();
health = actor.TraitOrDefault<IHealth>();

UpdateVisibility();
}
Expand All @@ -94,6 +96,7 @@ public FrozenActor(Actor self, PPos[] footprint, Shroud shroud, bool startsRevea
public bool IsValid { get { return Owner != null; } }
public ActorInfo Info { get { return actor.Info; } }
public Actor Actor { get { return !actor.IsDead ? actor : null; } }
public Player Viewer { get { return viewer; } }

public void RefreshState()
{
Expand Down Expand Up @@ -251,33 +254,38 @@ Rectangle FootprintBounds(FrozenActor fa)

void ITick.Tick(Actor self)
{
UpdateDirtyFrozenActorsFromDirtyBins();
// Update visibility at the end of the tick to make sure that
// the fog/shroud state has been updated for the tick
self.World.AddFrameEndTask(w =>
{
UpdateDirtyFrozenActorsFromDirtyBins();

var frozenActorsToRemove = new List<FrozenActor>();
VisibilityHash = 0;
FrozenHash = 0;
var frozenActorsToRemove = new List<FrozenActor>();
VisibilityHash = 0;
FrozenHash = 0;

foreach (var kvp in frozenActorsById)
{
var id = kvp.Key;
var hash = (int)id;
FrozenHash += hash;

var frozenActor = kvp.Value;
frozenActor.Tick();
if (dirtyFrozenActorIds.Contains(id))
frozenActor.UpdateVisibility();

if (frozenActor.Visible)
VisibilityHash += hash;
else if (frozenActor.Actor == null)
frozenActorsToRemove.Add(frozenActor);
}
foreach (var kvp in frozenActorsById)
{
var id = kvp.Key;
var hash = (int)id;
FrozenHash += hash;

var frozenActor = kvp.Value;
frozenActor.Tick();
if (dirtyFrozenActorIds.Contains(id))
frozenActor.UpdateVisibility();

if (frozenActor.Visible)
VisibilityHash += hash;
else if (frozenActor.Actor == null)
frozenActorsToRemove.Add(frozenActor);
}

dirtyFrozenActorIds.Clear();
dirtyFrozenActorIds.Clear();

foreach (var fa in frozenActorsToRemove)
Remove(fa);
foreach (var fa in frozenActorsToRemove)
Remove(fa);
});
}

void UpdateDirtyFrozenActorsFromDirtyBins()
Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Mods.Common/Traits/Modifiers/FrozenUnderFog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ void INotifyCreated.Created(Actor self)
{
frozenStates = new PlayerDictionary<FrozenState>(self.World, (player, playerIndex) =>
{
var frozenActor = new FrozenActor(self, footprint, player.Shroud, startsRevealed);
var frozenActor = new FrozenActor(self, footprint, player, startsRevealed);
if (startsRevealed)
UpdateFrozenActor(self, frozenActor, playerIndex);
player.PlayerActor.Trait<FrozenActorLayer>().Add(frozenActor);
Expand Down
8 changes: 7 additions & 1 deletion OpenRA.Mods.Common/Widgets/ViewportControllerWidget.cs
Original file line number Diff line number Diff line change
Expand Up @@ -252,11 +252,17 @@ public void UpdateMouseover()
if (frozen != null)
{
var actor = frozen.Actor;
if (actor != null && actor.TraitsImplementing<IVisibilityModifier>().All(t => t.IsVisible(actor, world.RenderPlayer)))

// HACK: This leaks the cloak state through the fog (cloaked buildings will not show tooltips)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not even a HACK. More like a BUG?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a hack that then causes a bug.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IDEs have keyword detection for HACK, but not for BUG, so i'd prefer to keep this as it is.

if (actor == null || actor.TraitsImplementing<IVisibilityModifier>().All(t => t.IsVisible(actor, world.RenderPlayer)))
{
FrozenActorTooltip = frozen;

// HACK: This leaks the tooltip state through the fog
// This will cause issues for any downstream mods that use IProvideTooltipInfo on enemy actors
if (frozen.Actor != null)
ActorTooltipExtra = frozen.Actor.TraitsImplementing<IProvideTooltipInfo>().ToArray();

TooltipType = WorldTooltipType.FrozenActor;
return;
}
Expand Down