mirror of
https://github.com/space-syndicate/space-station-14.git
synced 2026-10-09 18:31:17 +03:00
Revert "Directional visibility for wall-mounted entities" (#44770)
Revert "Directional visibility for wall-mounted entities (#43476)"
This reverts commit c17429daa4.
This commit is contained in:
parent
63765280a3
commit
f3cff7bb8c
7 changed files with 13 additions and 586 deletions
|
|
@ -1,11 +0,0 @@
|
|||
using Content.Shared.Wall;
|
||||
using Robust.Shared.ComponentTrees;
|
||||
using Robust.Shared.Physics;
|
||||
|
||||
namespace Content.Client.Wall.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
public sealed partial class WallMountTreeComponent : Component, IComponentTreeComponent<WallMountComponent>
|
||||
{
|
||||
public DynamicTree<ComponentTreeEntry<WallMountComponent>> Tree { get; set; } = default!;
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
using System.Numerics;
|
||||
using Content.Client.Wall.Components;
|
||||
using Content.Shared.Wall;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.ComponentTrees;
|
||||
using Robust.Shared.Physics;
|
||||
|
||||
namespace Content.Client.Wall.Systems;
|
||||
|
||||
public sealed partial class WallMountTreeSystem : ComponentTreeSystem<WallMountTreeComponent, WallMountComponent>
|
||||
{
|
||||
[Dependency] private SpriteSystem _sprite = default!;
|
||||
|
||||
protected override bool DoFrameUpdate => true;
|
||||
protected override bool DoTickUpdate => false;
|
||||
protected override bool Recursive => false;
|
||||
|
||||
protected override Box2 ExtractAabb(in ComponentTreeEntry<WallMountComponent> entry, Vector2 pos, Angle rot)
|
||||
{
|
||||
return _sprite.CalculateBounds((entry.Uid, Comp<SpriteComponent>(entry.Uid)), pos, rot, default).CalcBoundingBox();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,187 +0,0 @@
|
|||
using System.Linq;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.GameTicking;
|
||||
using Content.Shared.Tag;
|
||||
using Content.Shared.Wall;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Client.Wall.Systems;
|
||||
|
||||
/// <summary>
|
||||
/// Manages the directional visibility overlay for wall-mounted entities.
|
||||
/// </summary>
|
||||
public sealed partial class WallMountVisibilitySystem : EntitySystem
|
||||
{
|
||||
[Dependency] private IConfigurationManager _cfg = default!;
|
||||
[Dependency] private IGameTiming _timing = default!;
|
||||
[Dependency] private IOverlayManager _overlay = default!;
|
||||
[Dependency] private SharedMapSystem _map = default!;
|
||||
[Dependency] private SpriteSystem _sprite = default!;
|
||||
[Dependency] private TagSystem _tag = default!;
|
||||
[Dependency] private TransformSystem _xform = default!;
|
||||
[Dependency] private WallMountTreeSystem _tree = default!;
|
||||
|
||||
[Dependency] private EntityQuery<MapGridComponent> _gridQuery = default!;
|
||||
[Dependency] private EntityQuery<SpriteComponent> _spriteQuery = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Tags that block visibility when present on the same tile.
|
||||
/// </summary>
|
||||
private static readonly ProtoId<TagPrototype>[] BlockingTags = ["Wall"];
|
||||
|
||||
/// <summary>
|
||||
/// Caches for whether a tile has any blocking entity.
|
||||
/// </summary>
|
||||
private readonly Dictionary<(EntityUid Grid, Vector2i Tile), bool> _tileCache = [];
|
||||
|
||||
private WallMountVisibilityOverlay _overlayInstance = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Whether directional visibility is currently enabled.
|
||||
/// </summary>
|
||||
internal bool DirectionalVisibilityEnabled = true;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_overlayInstance = new WallMountVisibilityOverlay(_timing, _map, _sprite, _xform, _tree, this, _gridQuery, _spriteQuery);
|
||||
Subs.CVar(_cfg, CCVars.WallMountDirectionalVisibility, OnDirectionalVisibilityChanged, true);
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
{
|
||||
base.Shutdown();
|
||||
|
||||
_overlay.RemoveOverlay(_overlayInstance);
|
||||
}
|
||||
|
||||
private void OnDirectionalVisibilityChanged(bool enabled)
|
||||
{
|
||||
DirectionalVisibilityEnabled = enabled;
|
||||
|
||||
if (enabled)
|
||||
_overlay.AddOverlay(_overlayInstance);
|
||||
else
|
||||
{
|
||||
_overlay.RemoveOverlay(_overlayInstance);
|
||||
SetAllVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invalidates tile cache when anchor state changes for a blocking entity.
|
||||
/// </summary>
|
||||
[SubscribeLocalEvent]
|
||||
private void OnTagAnchorChanged(Entity<TagComponent> ent, ref AnchorStateChangedEvent args)
|
||||
{
|
||||
if (!_tag.HasAnyTag(ent.Comp, BlockingTags))
|
||||
return;
|
||||
|
||||
var xform = args.Transform;
|
||||
if (xform.GridUid is not { } gridUid)
|
||||
return;
|
||||
|
||||
if (!_gridQuery.TryGetComponent(gridUid, out var grid))
|
||||
return;
|
||||
|
||||
var tile = _map.TileIndicesFor(gridUid, grid, xform.Coordinates);
|
||||
_tileCache.Remove((gridUid, tile));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Makes the entity visible again on component shutdown.
|
||||
/// </summary>
|
||||
[SubscribeLocalEvent]
|
||||
private void OnWallMountShutdown(Entity<WallMountComponent> ent, ref ComponentShutdown args)
|
||||
{
|
||||
if (TerminatingOrDeleted(ent))
|
||||
return;
|
||||
|
||||
if (!TryComp<SpriteComponent>(ent, out var sprite))
|
||||
return;
|
||||
|
||||
_sprite.SetVisible((ent, sprite), true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Makes the entity visible again if directional visibility is disabled for this mount.
|
||||
/// </summary>
|
||||
[SubscribeLocalEvent]
|
||||
private void OnWallMountAfterHandleState(Entity<WallMountComponent> ent, ref AfterAutoHandleStateEvent args)
|
||||
{
|
||||
if (ent.Comp.DirectionalVisibility)
|
||||
return;
|
||||
|
||||
if (!TryComp<SpriteComponent>(ent, out var sprite))
|
||||
return;
|
||||
|
||||
_sprite.SetVisible((ent, sprite), true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all cached entries for a grid that is being removed.
|
||||
/// </summary>
|
||||
[SubscribeLocalEvent]
|
||||
private void OnGridRemoval(GridRemovalEvent ev)
|
||||
{
|
||||
foreach (var key in _tileCache.Keys.Where(k => k.Grid == ev.EntityUid).ToList())
|
||||
{
|
||||
_tileCache.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears tile cache and resets all wall-mount visibility on round restart.
|
||||
/// </summary>
|
||||
[SubscribeNetworkEvent]
|
||||
private void OnRoundRestart(RoundRestartCleanupEvent ev)
|
||||
{
|
||||
_tileCache.Clear();
|
||||
SetAllVisible(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Forces all wall-mount entities to become visible or hidden.
|
||||
/// </summary>
|
||||
internal void SetAllVisible(bool visible)
|
||||
{
|
||||
var query = AllEntityQuery<WallMountComponent, SpriteComponent>();
|
||||
while (query.MoveNext(out var uid, out _, out var sprite))
|
||||
{
|
||||
_sprite.SetVisible((uid, sprite), visible);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the tile contains any anchored blocking entity.
|
||||
/// </summary>
|
||||
internal bool IsTileBlocked(EntityUid gridUid, Vector2i tile, EntityUid? ignoreUid = null)
|
||||
{
|
||||
if (!_gridQuery.TryGetComponent(gridUid, out var grid))
|
||||
return false;
|
||||
|
||||
var key = (gridUid, tile);
|
||||
if (_tileCache.TryGetValue(key, out var cached))
|
||||
return cached;
|
||||
|
||||
var enumerator = _map.GetAnchoredEntitiesEnumerator(gridUid, grid, tile);
|
||||
while (enumerator.MoveNext(out var anchored))
|
||||
{
|
||||
if (anchored == ignoreUid)
|
||||
continue;
|
||||
|
||||
if (!_tag.HasAnyTag(anchored.Value, BlockingTags))
|
||||
continue;
|
||||
|
||||
return _tileCache[key] = true;
|
||||
}
|
||||
|
||||
return _tileCache[key] = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,88 +0,0 @@
|
|||
using Robust.Client.GameObjects;
|
||||
|
||||
namespace Content.Client.Wall;
|
||||
|
||||
/// <summary>
|
||||
/// Tracks fade progress for a wall-mounted entity.
|
||||
/// </summary>
|
||||
internal struct WallMountFadeState
|
||||
{
|
||||
public float OriginalAlpha;
|
||||
public float CurrentAlpha;
|
||||
public float TargetAlpha;
|
||||
|
||||
/// <summary>
|
||||
/// Sprite alpha after applying the fade multiplier.
|
||||
/// </summary>
|
||||
public readonly float EffectiveAlpha => OriginalAlpha * CurrentAlpha;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the entity should be rendered as visible at the current fade level.
|
||||
/// </summary>
|
||||
public readonly bool IsVisible => CurrentAlpha > 0f;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new fade state snapped immediately to the given target alpha.
|
||||
/// </summary>
|
||||
public static WallMountFadeState Snapped(float originalAlpha, float targetAlpha)
|
||||
{
|
||||
return new()
|
||||
{
|
||||
OriginalAlpha = originalAlpha,
|
||||
CurrentAlpha = targetAlpha,
|
||||
TargetAlpha = targetAlpha,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves <see cref="CurrentAlpha"/> one step towards <see cref="TargetAlpha"/>.
|
||||
/// </summary>
|
||||
public void StepTowards(float fadeStep)
|
||||
{
|
||||
if (MathHelper.CloseTo(CurrentAlpha, TargetAlpha))
|
||||
return;
|
||||
|
||||
var delta = TargetAlpha - CurrentAlpha;
|
||||
var step = MathF.Sign(delta) * MathF.Min(MathF.Abs(delta), fadeStep);
|
||||
CurrentAlpha = Math.Clamp(CurrentAlpha + step, 0f, 1f);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Per-viewport fade state for wall-mounted entities.
|
||||
/// </summary>
|
||||
internal sealed class ViewportFadeState(SpriteSystem sprite, EntityQuery<SpriteComponent> spriteQuery) : IDisposable
|
||||
{
|
||||
private readonly SpriteSystem _sprite = sprite;
|
||||
private readonly EntityQuery<SpriteComponent> _spriteQuery = spriteQuery;
|
||||
|
||||
/// <summary>
|
||||
/// Fade states for entities tracked in this viewport.
|
||||
/// </summary>
|
||||
public readonly Dictionary<EntityUid, WallMountFadeState> FadeStates = [];
|
||||
|
||||
/// <summary>
|
||||
/// Entities visible this frame.
|
||||
/// </summary>
|
||||
public readonly HashSet<EntityUid> SeenThisFrame = [];
|
||||
|
||||
/// <summary>
|
||||
/// Whether FOV was enabled during the previous frame.
|
||||
/// </summary>
|
||||
public bool WasFovEnabled = true;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var (uid, state) in FadeStates)
|
||||
{
|
||||
if (!_spriteQuery.TryGetComponent(uid, out var sprite))
|
||||
continue;
|
||||
|
||||
_sprite.SetColor((uid, sprite), sprite.Color.WithAlpha(state.OriginalAlpha));
|
||||
_sprite.SetVisible((uid, sprite), true);
|
||||
}
|
||||
|
||||
FadeStates.Clear();
|
||||
SeenThisFrame.Clear();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,242 +0,0 @@
|
|||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Content.Client.Graphics;
|
||||
using Content.Client.Wall.Systems;
|
||||
using Content.Shared.Wall;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Graphics;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Client.Wall;
|
||||
|
||||
/// <summary>
|
||||
/// Renders wall-mounted entities conditionally based on their facing arc relative to the viewport's eye.
|
||||
/// </summary>
|
||||
public sealed partial class WallMountVisibilityOverlay(
|
||||
IGameTiming timing,
|
||||
SharedMapSystem map,
|
||||
SpriteSystem sprite,
|
||||
TransformSystem xform,
|
||||
WallMountTreeSystem tree,
|
||||
WallMountVisibilitySystem visibility,
|
||||
EntityQuery<MapGridComponent> gridQuery,
|
||||
EntityQuery<SpriteComponent> spriteQuery) : Overlay
|
||||
{
|
||||
private readonly IGameTiming _timing = timing;
|
||||
private readonly SharedMapSystem _map = map;
|
||||
private readonly SpriteSystem _sprite = sprite;
|
||||
private readonly TransformSystem _xform = xform;
|
||||
private readonly WallMountTreeSystem _tree = tree;
|
||||
private readonly WallMountVisibilitySystem _visibility = visibility;
|
||||
|
||||
private readonly EntityQuery<MapGridComponent> _gridQuery = gridQuery;
|
||||
private readonly EntityQuery<SpriteComponent> _spriteQuery = spriteQuery;
|
||||
|
||||
/// <summary>
|
||||
/// Caches <see cref="ViewportFadeState"/> instances per viewport.
|
||||
/// </summary>
|
||||
private readonly OverlayResourceCache<ViewportFadeState> _fadeCache = new();
|
||||
|
||||
/// <summary>
|
||||
/// Original sprite alphas, shared across viewports to avoid capturing values modified by another viewport.
|
||||
/// </summary>
|
||||
private readonly Dictionary<EntityUid, float> _originalAlphas = [];
|
||||
|
||||
/// <summary>
|
||||
/// Alpha change per second during fade.
|
||||
/// </summary>
|
||||
private const float FadeSpeed = 9f;
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowEntities;
|
||||
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
if (!_visibility.DirectionalVisibilityEnabled)
|
||||
return;
|
||||
|
||||
if (args.Viewport.Eye is not { } eye)
|
||||
return;
|
||||
|
||||
var viewportState = _fadeCache.GetForViewport(args.Viewport, _ => new ViewportFadeState(_sprite, _spriteQuery));
|
||||
|
||||
if (!eye.DrawFov)
|
||||
{
|
||||
HandleFovDisabled(args, viewportState);
|
||||
return;
|
||||
}
|
||||
|
||||
viewportState.WasFovEnabled = true;
|
||||
|
||||
var fadeStep = FadeSpeed * (float)_timing.FrameTime.TotalSeconds;
|
||||
var matrix = args.Viewport.GetWorldToLocalMatrix();
|
||||
|
||||
viewportState.SeenThisFrame.Clear();
|
||||
ProcessVisibleEntities(args, eye, matrix, fadeStep, viewportState);
|
||||
|
||||
// Remove entities that left the viewport this frame.
|
||||
foreach (var uid in viewportState.FadeStates.Keys.Except(viewportState.SeenThisFrame).ToList())
|
||||
{
|
||||
RemoveTrackedEntity(uid, viewportState);
|
||||
}
|
||||
|
||||
ApplyFadeToVisibleEntities(viewportState);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When FOV gets disabled, clears fade state and restores sprites.
|
||||
/// On subsequent frames, keeps wall-mounts visible and restores alpha modified by other viewports.
|
||||
/// </summary>
|
||||
private void HandleFovDisabled(in OverlayDrawArgs args, ViewportFadeState viewportState)
|
||||
{
|
||||
if (viewportState.WasFovEnabled)
|
||||
{
|
||||
ClearViewportFadeState(viewportState);
|
||||
viewportState.WasFovEnabled = false;
|
||||
}
|
||||
|
||||
// Restore alpha modified by other viewports.
|
||||
foreach (var entity in _tree.QueryAabb(args.MapId, args.WorldBounds))
|
||||
{
|
||||
var uid = entity.Uid;
|
||||
if (!_spriteQuery.TryGetComponent(uid, out var sprite))
|
||||
continue;
|
||||
|
||||
if (_originalAlphas.Remove(uid, out var origAlpha))
|
||||
_sprite.SetColor((uid, sprite), sprite.Color.WithAlpha(origAlpha));
|
||||
|
||||
_sprite.SetVisible((uid, sprite), true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates fade state for all wall-mounted entities in the viewport.
|
||||
/// </summary>
|
||||
private void ProcessVisibleEntities(in OverlayDrawArgs args, IEye eye, Matrix3x2 matrix, float fadeStep, ViewportFadeState viewportState)
|
||||
{
|
||||
foreach (var entity in _tree.QueryAabb(args.MapId, args.WorldBounds))
|
||||
{
|
||||
var (wallmount, xform) = entity;
|
||||
var uid = entity.Uid;
|
||||
|
||||
if (!_spriteQuery.TryGetComponent(uid, out var sprite))
|
||||
continue;
|
||||
|
||||
// Capture original alpha before any viewport modifies it.
|
||||
if (!_originalAlphas.TryGetValue(uid, out var originalAlpha))
|
||||
_originalAlphas[uid] = originalAlpha = sprite.Color.A;
|
||||
|
||||
viewportState.SeenThisFrame.Add(uid);
|
||||
|
||||
var targetAlpha = ComputeTargetAlpha(uid, wallmount, xform, eye, matrix);
|
||||
UpdateFadeState(uid, originalAlpha, targetAlpha, fadeStep, viewportState);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns 1 if the entity is within its facing arc relative to the eye, 0 otherwise.
|
||||
/// </summary>
|
||||
private float ComputeTargetAlpha(EntityUid uid, WallMountComponent wallmount, TransformComponent xform, IEye eye, Matrix3x2 matrix)
|
||||
{
|
||||
if (!wallmount.DirectionalVisibility || wallmount.Arc >= Math.Tau)
|
||||
return 1f;
|
||||
|
||||
if (xform.GridUid is not { } gridUid || !_gridQuery.TryGetComponent(gridUid, out var grid))
|
||||
return 1f;
|
||||
|
||||
var tile = _map.TileIndicesFor(gridUid, grid, xform.Coordinates);
|
||||
if (!_visibility.IsTileBlocked(gridUid, tile, uid))
|
||||
return 1f;
|
||||
|
||||
var (pos, rot) = _xform.GetWorldPositionRotation(xform);
|
||||
var facingAngle = rot + eye.Rotation + wallmount.Direction;
|
||||
|
||||
var entityScreenPos = Vector2.Transform(pos, matrix);
|
||||
var eyeScreenPos = Vector2.Transform(eye.Position.Position, matrix);
|
||||
var toEntity = entityScreenPos - eyeScreenPos;
|
||||
var eyeToEntityAngle = (toEntity with { X = -toEntity.X }).ToWorldAngle();
|
||||
|
||||
var angleDiff = Angle.ShortestDistance(eyeToEntityAngle, facingAngle);
|
||||
return Math.Abs(angleDiff) < wallmount.Arc / 2 ? 1f : 0f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies the current fade state to all entities seen this frame.
|
||||
/// </summary>
|
||||
private void ApplyFadeToVisibleEntities(ViewportFadeState viewportState)
|
||||
{
|
||||
foreach (var uid in viewportState.SeenThisFrame)
|
||||
{
|
||||
if (!viewportState.FadeStates.TryGetValue(uid, out var state))
|
||||
continue;
|
||||
|
||||
if (!_spriteQuery.TryGetComponent(uid, out var sprite))
|
||||
{
|
||||
RemoveTrackedEntity(uid, viewportState);
|
||||
continue;
|
||||
}
|
||||
|
||||
_sprite.SetColor((uid, sprite), sprite.Color.WithAlpha(state.EffectiveAlpha));
|
||||
_sprite.SetVisible((uid, sprite), state.IsVisible);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates fade target for a tracked entity. Newly seen entities snap immediately without fading.
|
||||
/// </summary>
|
||||
private static void UpdateFadeState(EntityUid uid, float originalAlpha, float targetAlpha, float fadeStep, ViewportFadeState viewportState)
|
||||
{
|
||||
if (viewportState.FadeStates.TryGetValue(uid, out var state))
|
||||
{
|
||||
state.TargetAlpha = targetAlpha;
|
||||
state.StepTowards(fadeStep);
|
||||
viewportState.FadeStates[uid] = state;
|
||||
return;
|
||||
}
|
||||
|
||||
viewportState.FadeStates[uid] = WallMountFadeState.Snapped(originalAlpha, targetAlpha);
|
||||
}
|
||||
|
||||
private void RestoreSprite(EntityUid uid, WallMountFadeState state)
|
||||
{
|
||||
if (!_spriteQuery.TryGetComponent(uid, out var sprite))
|
||||
return;
|
||||
|
||||
_sprite.SetColor((uid, sprite), sprite.Color.WithAlpha(state.OriginalAlpha));
|
||||
_sprite.SetVisible((uid, sprite), true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes an entity from fade tracking and restores its sprite.
|
||||
/// </summary>
|
||||
private void RemoveTrackedEntity(EntityUid uid, ViewportFadeState viewportState)
|
||||
{
|
||||
if (viewportState.FadeStates.Remove(uid, out var state))
|
||||
RestoreSprite(uid, state);
|
||||
|
||||
_originalAlphas.Remove(uid);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all fade tracking for a viewport and restores sprites.
|
||||
/// </summary>
|
||||
private void ClearViewportFadeState(ViewportFadeState viewportState)
|
||||
{
|
||||
foreach (var (uid, state) in viewportState.FadeStates)
|
||||
{
|
||||
RestoreSprite(uid, state);
|
||||
_originalAlphas.Remove(uid);
|
||||
}
|
||||
|
||||
viewportState.FadeStates.Clear();
|
||||
viewportState.SeenThisFrame.Clear();
|
||||
}
|
||||
|
||||
protected override void DisposeBehavior()
|
||||
{
|
||||
_fadeCache.Dispose();
|
||||
base.DisposeBehavior();
|
||||
}
|
||||
}
|
||||
|
|
@ -435,10 +435,4 @@ public sealed partial class CCVars
|
|||
/// </remarks>
|
||||
public static readonly CVarDef<string> NewCharacterJobs =
|
||||
CVarDef.Create("game.new_character_jobs", "Passenger", CVar.REPLICATED);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether wall-mounted entities are hidden when viewed from outside their facing arc.
|
||||
/// </summary>
|
||||
public static readonly CVarDef<bool> WallMountDirectionalVisibility =
|
||||
CVarDef.Create("game.wallmount_directional_visibility", true, CVar.SERVER | CVar.REPLICATED);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,45 +1,28 @@
|
|||
using Robust.Shared.ComponentTrees;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Physics;
|
||||
|
||||
namespace Content.Shared.Wall;
|
||||
|
||||
/// <summary>
|
||||
/// Marks an entity as wall-mounted.
|
||||
/// Allows interaction through other anchored entities on the same tile within the <see cref="Arc"/>.
|
||||
/// Hides the sprite when viewed from outside that arc.
|
||||
/// This component enables an entity to ignore some obstructions for interaction checks.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(raiseAfterAutoHandleState: true)]
|
||||
public sealed partial class WallMountComponent : Component, IComponentTreeEntry<WallMountComponent>
|
||||
/// <remarks>
|
||||
/// This will only exempt anchored entities that intersect the wall-mount. Additionally, this exemption will apply
|
||||
/// in a limited arc, providing basic functionality for directional wall mounts.
|
||||
/// </remarks>
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||
public sealed partial class WallMountComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// Range of angles where interaction through other anchored entities on the same tile is allowed.
|
||||
/// Bigger is more permissive.
|
||||
/// Range of angles for which the exemption applies. Bigger is more permissive.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("arc"), AutoNetworkedField]
|
||||
public Angle Arc = new(MathF.PI);
|
||||
|
||||
/// <summary>
|
||||
/// The direction the allowed angle range faces, relative to the entity's rotation.
|
||||
/// Defaults to south.
|
||||
/// The direction in which the exemption arc is facing, relative to the entity's rotation. Defaults to south.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("direction"), AutoNetworkedField]
|
||||
public Angle Direction = Angle.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// If true, the sprite is only visible from within the facing <see cref="Arc"/>.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public bool DirectionalVisibility = true;
|
||||
|
||||
[ViewVariables]
|
||||
public EntityUid? TreeUid { get; set; }
|
||||
|
||||
[ViewVariables]
|
||||
public DynamicTree<ComponentTreeEntry<WallMountComponent>>? Tree { get; set; }
|
||||
|
||||
[ViewVariables]
|
||||
public bool AddToTree => Arc < Math.Tau && DirectionalVisibility;
|
||||
|
||||
public bool TreeUpdateQueued { get; set; }
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue