Track visibility modifiers on FrozenActors.
This commit is contained in:
committed by
Oliver Brakmann
parent
5f79c31a57
commit
224377f078
@@ -46,7 +46,17 @@ namespace OpenRA.Traits
|
||||
public DamageState DamageState { get; private set; }
|
||||
readonly IHealth health;
|
||||
|
||||
// The Visible flag is tied directly to the actor visibility under the fog.
|
||||
// If Visible is true, the actor is made invisible (via FrozenUnderFog/IDefaultVisibility)
|
||||
// and this FrozenActor is rendered instead.
|
||||
// The Hidden flag covers the edge case that occurs when the backing actor was last "seen"
|
||||
// to be cloaked or otherwise not CanBeViewedByPlayer()ed. Setting Visible to true when
|
||||
// the actor is hidden under the fog would leak the actors position via the tooltips and
|
||||
// AutoTargetability, and keeping Visible as false would cause the actor to be rendered
|
||||
// under the fog.
|
||||
public bool Visible = true;
|
||||
public bool Hidden = false;
|
||||
|
||||
public bool Shrouded { get; private set; }
|
||||
public bool NeedRenderables { get; set; }
|
||||
public IRenderable[] Renderables = NoRenderables;
|
||||
@@ -101,6 +111,7 @@ namespace OpenRA.Traits
|
||||
{
|
||||
Owner = actor.Owner;
|
||||
TargetTypes = actor.GetEnabledTargetTypes();
|
||||
Hidden = !actor.CanBeViewedByPlayer(viewer);
|
||||
|
||||
if (health != null)
|
||||
{
|
||||
@@ -145,6 +156,11 @@ namespace OpenRA.Traits
|
||||
NeedRenderables |= Visible && !wasVisible;
|
||||
}
|
||||
|
||||
public void Invalidate()
|
||||
{
|
||||
Owner = null;
|
||||
}
|
||||
|
||||
public void Flash()
|
||||
{
|
||||
flashTicks = 5;
|
||||
|
||||
@@ -80,13 +80,21 @@ namespace OpenRA.Traits
|
||||
|
||||
public bool IsValidFor(Actor targeter)
|
||||
{
|
||||
if (targeter == null || Type == TargetType.Invalid)
|
||||
if (targeter == null)
|
||||
return false;
|
||||
|
||||
if (actor != null && !actor.IsTargetableBy(targeter))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
switch (Type)
|
||||
{
|
||||
case TargetType.Actor:
|
||||
return actor.IsTargetableBy(targeter);
|
||||
case TargetType.FrozenActor:
|
||||
return frozen.IsValid && frozen.Visible && !frozen.Hidden;
|
||||
case TargetType.Invalid:
|
||||
return false;
|
||||
default:
|
||||
case TargetType.Terrain:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Currently all or nothing.
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace OpenRA.Mods.Cnc.Traits
|
||||
static readonly FrozenActorAction Remove = (fufubg, fal, gps, fa) =>
|
||||
{
|
||||
// Removes the frozen actor. Once done, we no longer need to track GPS updates.
|
||||
fa.Invalidate();
|
||||
fal.Remove(fa);
|
||||
gps.UnregisterForOnGpsRefreshed(fufubg.self, fufubg);
|
||||
};
|
||||
|
||||
@@ -68,11 +68,13 @@ namespace OpenRA.Mods.Common.Traits
|
||||
frozenStates = new PlayerDictionary<FrozenState>(self.World, (player, playerIndex) =>
|
||||
{
|
||||
var frozenActor = new FrozenActor(self, footprint, player, startsRevealed);
|
||||
if (startsRevealed)
|
||||
UpdateFrozenActor(self, frozenActor, playerIndex);
|
||||
player.PlayerActor.Trait<FrozenActorLayer>().Add(frozenActor);
|
||||
return new FrozenState(frozenActor) { IsVisible = startsRevealed };
|
||||
});
|
||||
|
||||
if (startsRevealed)
|
||||
for (var playerIndex = 0; playerIndex < frozenStates.Count; playerIndex++)
|
||||
UpdateFrozenActor(self, frozenStates[playerIndex].FrozenActor, playerIndex);
|
||||
}
|
||||
|
||||
void UpdateFrozenActor(Actor self, FrozenActor frozenActor, int playerIndex)
|
||||
|
||||
@@ -246,26 +246,20 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
}
|
||||
|
||||
var frozen = world.ScreenMap.FrozenActorsAtMouse(world.RenderPlayer, worldPixel)
|
||||
.Where(a => a.TooltipInfo != null && a.IsValid)
|
||||
.Where(a => a.TooltipInfo != null && a.IsValid && a.Visible && !a.Hidden)
|
||||
.WithHighestSelectionPriority(worldPixel);
|
||||
|
||||
if (frozen != null)
|
||||
{
|
||||
var actor = frozen.Actor;
|
||||
FrozenActorTooltip = frozen;
|
||||
|
||||
// HACK: This leaks the cloak state through the fog (cloaked buildings will not show tooltips)
|
||||
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();
|
||||
|
||||
// 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;
|
||||
}
|
||||
TooltipType = WorldTooltipType.FrozenActor;
|
||||
return;
|
||||
}
|
||||
|
||||
if (resourceLayer != null)
|
||||
|
||||
Reference in New Issue
Block a user