Let movement trigger visibility recalculation.
This commit is contained in:
@@ -32,7 +32,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
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 = { };
|
||||
|
||||
@@ -47,7 +48,6 @@ namespace OpenRA.Mods.Common.Traits
|
||||
[Sync]
|
||||
protected bool CachedTraitDisabled { get; private set; }
|
||||
|
||||
bool dirty;
|
||||
WPos cachedPos;
|
||||
|
||||
protected abstract void AddCellsToPlayerShroud(Actor self, Player player, PPos[] uv);
|
||||
@@ -86,7 +86,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
void ITick.Tick(Actor self)
|
||||
void INotifyVisualPositionChanged.VisualPositionChanged(Actor self, byte oldLayer, byte newLayer)
|
||||
{
|
||||
if (!self.IsInWorld)
|
||||
return;
|
||||
@@ -94,22 +94,37 @@ namespace OpenRA.Mods.Common.Traits
|
||||
var centerPosition = self.CenterPosition;
|
||||
var projectedPos = centerPosition - new WVec(0, centerPosition.Z, centerPosition.Z);
|
||||
var projectedLocation = self.World.Map.CellContaining(projectedPos);
|
||||
var traitDisabled = IsTraitDisabled;
|
||||
var range = Range;
|
||||
var pos = self.CenterPosition;
|
||||
|
||||
if (Info.MoveRecalculationThreshold.Length > 0 && (pos - cachedPos).LengthSquared > Info.MoveRecalculationThreshold.LengthSquared)
|
||||
dirty = true;
|
||||
var dirty = Info.MoveRecalculationThreshold.Length > 0 && (pos - cachedPos).LengthSquared > Info.MoveRecalculationThreshold.LengthSquared;
|
||||
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;
|
||||
|
||||
cachedRange = range;
|
||||
cachedLocation = projectedLocation;
|
||||
CachedTraitDisabled = traitDisabled;
|
||||
cachedPos = pos;
|
||||
dirty = false;
|
||||
|
||||
UpdateShroudCells(self);
|
||||
}
|
||||
|
||||
void UpdateShroudCells(Actor self)
|
||||
{
|
||||
var cells = ProjectedCells(self);
|
||||
foreach (var p in self.World.Players)
|
||||
{
|
||||
@@ -123,6 +138,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
var centerPosition = self.CenterPosition;
|
||||
var projectedPos = centerPosition - new WVec(0, centerPosition.Z, centerPosition.Z);
|
||||
cachedLocation = self.World.Map.CellContaining(projectedPos);
|
||||
cachedPos = centerPosition;
|
||||
CachedTraitDisabled = IsTraitDisabled;
|
||||
var cells = ProjectedCells(self);
|
||||
|
||||
@@ -141,8 +157,18 @@ namespace OpenRA.Mods.Common.Traits
|
||||
void INotifyMoving.MovementTypeChanged(Actor self, MovementType type)
|
||||
{
|
||||
// Recalculate the visiblity at our final stop position
|
||||
if (type == MovementType.None)
|
||||
dirty = true;
|
||||
if (type == MovementType.None && self.IsInWorld)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,6 +200,7 @@ namespace OpenRA.Mods.Common.Traits
|
||||
IDisposable reservation;
|
||||
IEnumerable<int> speedModifiers;
|
||||
INotifyMoving[] notifyMoving;
|
||||
INotifyVisualPositionChanged[] notifyVisualPositionChanged;
|
||||
IOverrideAircraftLanding overrideAircraftLanding;
|
||||
|
||||
[Sync]
|
||||
@@ -218,6 +219,8 @@ namespace OpenRA.Mods.Common.Traits
|
||||
bool requireForceMove;
|
||||
int creationActivityDelay;
|
||||
|
||||
bool notify = true;
|
||||
|
||||
public static WPos GroundPosition(Actor self)
|
||||
{
|
||||
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();
|
||||
positionOffsets = self.TraitsImplementing<IAircraftCenterPositionOffset>().ToArray();
|
||||
overrideAircraftLanding = self.TraitOrDefault<IOverrideAircraftLanding>();
|
||||
|
||||
notifyVisualPositionChanged = self.TraitsImplementing<INotifyVisualPositionChanged>().ToArray();
|
||||
base.Created(self);
|
||||
}
|
||||
|
||||
@@ -382,7 +385,12 @@ namespace OpenRA.Mods.Common.Traits
|
||||
return;
|
||||
|
||||
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));
|
||||
notify = true;
|
||||
}
|
||||
|
||||
public virtual WVec GetRepulsionForce()
|
||||
@@ -732,6 +740,11 @@ namespace OpenRA.Mods.Common.Traits
|
||||
else if (!isCruising && cruising)
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user