Let movement trigger visibility recalculation.

This commit is contained in:
tovl
2019-11-28 16:43:59 +01:00
committed by abcdefg30
parent 695d9a6cb1
commit fbfef903ac
2 changed files with 53 additions and 14 deletions

View File

@@ -32,7 +32,8 @@ namespace OpenRA.Mods.Common.Traits
public readonly VisibilityType Type = VisibilityType.Footprint; public readonly VisibilityType Type = VisibilityType.Footprint;
} }
public abstract class AffectsShroud : ConditionalTrait<AffectsShroudInfo>, ITick, ISync, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyMoving public abstract class AffectsShroud : ConditionalTrait<AffectsShroudInfo>, ISync, INotifyAddedToWorld,
INotifyRemovedFromWorld, INotifyMoving, INotifyVisualPositionChanged, ITick
{ {
static readonly PPos[] NoCells = { }; static readonly PPos[] NoCells = { };
@@ -47,7 +48,6 @@ namespace OpenRA.Mods.Common.Traits
[Sync] [Sync]
protected bool CachedTraitDisabled { get; private set; } protected bool CachedTraitDisabled { get; private set; }
bool dirty;
WPos cachedPos; WPos cachedPos;
protected abstract void AddCellsToPlayerShroud(Actor self, Player player, PPos[] uv); protected abstract void AddCellsToPlayerShroud(Actor self, Player player, PPos[] uv);
@@ -86,7 +86,7 @@ namespace OpenRA.Mods.Common.Traits
.ToArray(); .ToArray();
} }
void ITick.Tick(Actor self) void INotifyVisualPositionChanged.VisualPositionChanged(Actor self, byte oldLayer, byte newLayer)
{ {
if (!self.IsInWorld) if (!self.IsInWorld)
return; return;
@@ -94,22 +94,37 @@ namespace OpenRA.Mods.Common.Traits
var centerPosition = self.CenterPosition; var centerPosition = self.CenterPosition;
var projectedPos = centerPosition - new WVec(0, centerPosition.Z, centerPosition.Z); var projectedPos = centerPosition - new WVec(0, centerPosition.Z, centerPosition.Z);
var projectedLocation = self.World.Map.CellContaining(projectedPos); var projectedLocation = self.World.Map.CellContaining(projectedPos);
var traitDisabled = IsTraitDisabled;
var range = Range;
var pos = self.CenterPosition; var pos = self.CenterPosition;
if (Info.MoveRecalculationThreshold.Length > 0 && (pos - cachedPos).LengthSquared > Info.MoveRecalculationThreshold.LengthSquared) var dirty = Info.MoveRecalculationThreshold.Length > 0 && (pos - cachedPos).LengthSquared > Info.MoveRecalculationThreshold.LengthSquared;
dirty = true; if (!dirty && cachedLocation == projectedLocation)
return;
if (!dirty && cachedLocation == projectedLocation && cachedRange == range && traitDisabled == CachedTraitDisabled) cachedLocation = projectedLocation;
cachedPos = pos;
UpdateShroudCells(self);
}
void ITick.Tick(Actor self)
{
if (!self.IsInWorld)
return;
var traitDisabled = IsTraitDisabled;
var range = Range;
if (cachedRange == range && traitDisabled == CachedTraitDisabled)
return; return;
cachedRange = range; cachedRange = range;
cachedLocation = projectedLocation;
CachedTraitDisabled = traitDisabled; CachedTraitDisabled = traitDisabled;
cachedPos = pos;
dirty = false;
UpdateShroudCells(self);
}
void UpdateShroudCells(Actor self)
{
var cells = ProjectedCells(self); var cells = ProjectedCells(self);
foreach (var p in self.World.Players) foreach (var p in self.World.Players)
{ {
@@ -123,6 +138,7 @@ namespace OpenRA.Mods.Common.Traits
var centerPosition = self.CenterPosition; var centerPosition = self.CenterPosition;
var projectedPos = centerPosition - new WVec(0, centerPosition.Z, centerPosition.Z); var projectedPos = centerPosition - new WVec(0, centerPosition.Z, centerPosition.Z);
cachedLocation = self.World.Map.CellContaining(projectedPos); cachedLocation = self.World.Map.CellContaining(projectedPos);
cachedPos = centerPosition;
CachedTraitDisabled = IsTraitDisabled; CachedTraitDisabled = IsTraitDisabled;
var cells = ProjectedCells(self); var cells = ProjectedCells(self);
@@ -141,8 +157,18 @@ namespace OpenRA.Mods.Common.Traits
void INotifyMoving.MovementTypeChanged(Actor self, MovementType type) void INotifyMoving.MovementTypeChanged(Actor self, MovementType type)
{ {
// Recalculate the visiblity at our final stop position // Recalculate the visiblity at our final stop position
if (type == MovementType.None) if (type == MovementType.None && self.IsInWorld)
dirty = true; {
var centerPosition = self.CenterPosition;
var projectedPos = centerPosition - new WVec(0, centerPosition.Z, centerPosition.Z);
var projectedLocation = self.World.Map.CellContaining(projectedPos);
var pos = self.CenterPosition;
cachedLocation = projectedLocation;
cachedPos = pos;
UpdateShroudCells(self);
}
} }
} }
} }

View File

@@ -200,6 +200,7 @@ namespace OpenRA.Mods.Common.Traits
IDisposable reservation; IDisposable reservation;
IEnumerable<int> speedModifiers; IEnumerable<int> speedModifiers;
INotifyMoving[] notifyMoving; INotifyMoving[] notifyMoving;
INotifyVisualPositionChanged[] notifyVisualPositionChanged;
IOverrideAircraftLanding overrideAircraftLanding; IOverrideAircraftLanding overrideAircraftLanding;
[Sync] [Sync]
@@ -218,6 +219,8 @@ namespace OpenRA.Mods.Common.Traits
bool requireForceMove; bool requireForceMove;
int creationActivityDelay; int creationActivityDelay;
bool notify = true;
public static WPos GroundPosition(Actor self) public static WPos GroundPosition(Actor self)
{ {
return self.CenterPosition - new WVec(WDist.Zero, WDist.Zero, self.World.Map.DistanceAboveTerrain(self.CenterPosition)); return self.CenterPosition - new WVec(WDist.Zero, WDist.Zero, self.World.Map.DistanceAboveTerrain(self.CenterPosition));
@@ -296,7 +299,7 @@ namespace OpenRA.Mods.Common.Traits
notifyMoving = self.TraitsImplementing<INotifyMoving>().ToArray(); notifyMoving = self.TraitsImplementing<INotifyMoving>().ToArray();
positionOffsets = self.TraitsImplementing<IAircraftCenterPositionOffset>().ToArray(); positionOffsets = self.TraitsImplementing<IAircraftCenterPositionOffset>().ToArray();
overrideAircraftLanding = self.TraitOrDefault<IOverrideAircraftLanding>(); overrideAircraftLanding = self.TraitOrDefault<IOverrideAircraftLanding>();
notifyVisualPositionChanged = self.TraitsImplementing<INotifyVisualPositionChanged>().ToArray();
base.Created(self); base.Created(self);
} }
@@ -382,7 +385,12 @@ namespace OpenRA.Mods.Common.Traits
return; return;
var speed = Info.RepulsionSpeed != -1 ? Info.RepulsionSpeed : MovementSpeed; var speed = Info.RepulsionSpeed != -1 ? Info.RepulsionSpeed : MovementSpeed;
// HACK: Prevent updating visibility twice per tick. We really shouldn't be
// moving twice in a tick in the first place.
notify = false;
SetPosition(self, CenterPosition + FlyStep(speed, repulsionForce.Yaw.Facing)); SetPosition(self, CenterPosition + FlyStep(speed, repulsionForce.Yaw.Facing));
notify = true;
} }
public virtual WVec GetRepulsionForce() public virtual WVec GetRepulsionForce()
@@ -732,6 +740,11 @@ namespace OpenRA.Mods.Common.Traits
else if (!isCruising && cruising) else if (!isCruising && cruising)
OnCruisingAltitudeLeft(); OnCruisingAltitudeLeft();
// NB: This can be called from the constructor before notifyVisualPositionChanged is assigned.
if (notify && notifyVisualPositionChanged != null)
foreach (var n in notifyVisualPositionChanged)
n.VisualPositionChanged(self, 0, 0);
FinishedMoving(self); FinishedMoving(self);
} }