Misc stealth and box changes (#11809)

* git mv

* Disable shader while box is open

* Hide entity menu / prevent examine

* fix recursion fix recursion fix recursion fix recursion

* Better visibility checks

* min and max visibility fields

* fix reference point
This commit is contained in:
Leon Friedrich
2022-10-15 17:15:25 +13:00
committed by GitHub
parent 8199d361c1
commit 6f4bb040e4
12 changed files with 222 additions and 52 deletions

View File

@@ -12,6 +12,12 @@ namespace Content.Shared.Stealth.Components;
[Access(typeof(SharedStealthSystem))]
public sealed class StealthComponent : Component
{
/// <summary>
/// Whether or not the stealth effect should currently be applied.
/// </summary>
[DataField("enabled")]
public bool Enabled = true;
/// <summary>
/// Whether or not the entity previously had an interaction outline prior to cloaking.
/// </summary>
@@ -19,12 +25,21 @@ public sealed class StealthComponent : Component
public bool HadOutline;
/// <summary>
/// Last set level of visibility. Ranges from 1 (fully visible) and -1 (fully hidden). To get the actual current
/// visibility, use <see cref="SharedStealthSystem.GetVisibility(EntityUid, StealthComponent?)"/>
/// Minimum visibility before the entity becomes unexaminable (and thus no longer appears on context menus).
/// </summary>
[DataField("examineThreshold")]
public readonly float ExamineThreshold = 0.5f;
/// <summary>
/// Last set level of visibility. The visual effect ranges from 1 (fully visible) and -1 (fully hidden). Values
/// outside of this range simply act as a buffer for the visual effect (i.e., a delay before turning invisible). To
/// get the actual current visibility, use <see cref="SharedStealthSystem.GetVisibility(EntityUid,
/// StealthComponent?)"/>
/// </summary>
[DataField("lastVisibility")]
[Access(typeof(SharedStealthSystem), Other = AccessPermissions.None)]
public float LastVisibility;
public float LastVisibility = 1;
/// <summary>
/// Time at which <see cref="LastVisibility"/> was set. Null implies the entity is currently paused and not
@@ -44,17 +59,31 @@ public sealed class StealthComponent : Component
/// </summary>
[DataField("movementVisibilityRate")]
public readonly float MovementVisibilityRate = 0.2f;
/// <summary>
/// Minimum visibility. Note that the visual effect caps out at -1, but this value is allowed to be larger or smaller.
/// </summary>
[DataField("minVisibility")]
public readonly float MinVisibility = -1f;
/// <summary>
/// Maximum visibility. Note that the visual effect caps out at +1, but this value is allowed to be larger or smaller.
/// </summary>
[DataField("maxVisibility")]
public readonly float MaxVisibility = 1.5f;
}
[Serializable, NetSerializable]
public sealed class StealthComponentState : ComponentState
{
public float Visibility;
public TimeSpan? LastUpdated;
public readonly float Visibility;
public readonly TimeSpan? LastUpdated;
public readonly bool Enabled;
public StealthComponentState(float stealthLevel, TimeSpan? lastUpdated)
public StealthComponentState(float stealthLevel, TimeSpan? lastUpdated, bool enabled)
{
Visibility = stealthLevel;
LastUpdated = lastUpdated;
Enabled = enabled;
}
}

View File

@@ -1,3 +1,4 @@
using Content.Shared.Examine;
using Content.Shared.Stealth.Components;
using Robust.Shared.GameStates;
using Robust.Shared.Timing;
@@ -17,6 +18,35 @@ public abstract class SharedStealthSystem : EntitySystem
SubscribeLocalEvent<StealthComponent, MoveEvent>(OnMove);
SubscribeLocalEvent<StealthComponent, EntityPausedEvent>(OnPaused);
SubscribeLocalEvent<StealthComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<StealthComponent, ExamineAttemptEvent>(OnExamine);
}
private void OnExamine(EntityUid uid, StealthComponent component, ExamineAttemptEvent args)
{
if (!component.Enabled || GetVisibility(uid, component) > component.ExamineThreshold)
return;
// Don't block examine for owner or children of the cloaked entity.
// Containers and the like should already block examining, so not bothering to check for occluding containers.
var source = args.Examiner;
do
{
if (source == uid)
return;
source = Transform(source).ParentUid;
}
while (source.IsValid());
args.Cancel();
}
public virtual void SetEnabled(EntityUid uid, bool value, StealthComponent? component = null)
{
if (!Resolve(uid, ref component, false) || component.Enabled == value)
return;
component.Enabled = value;
Dirty(component);
}
private void OnPaused(EntityUid uid, StealthComponent component, EntityPausedEvent args)
@@ -44,7 +74,7 @@ public abstract class SharedStealthSystem : EntitySystem
private void OnStealthGetState(EntityUid uid, StealthComponent component, ref ComponentGetState args)
{
args.State = new StealthComponentState(component.LastVisibility, component.LastUpdated);
args.State = new StealthComponentState(component.LastVisibility, component.LastUpdated, component.Enabled);
}
private void OnStealthHandleState(EntityUid uid, StealthComponent component, ref ComponentHandleState args)
@@ -52,6 +82,7 @@ public abstract class SharedStealthSystem : EntitySystem
if (args.Current is not StealthComponentState cast)
return;
SetEnabled(uid, cast.Enabled, component);
component.LastVisibility = cast.Visibility;
component.LastUpdated = cast.LastUpdated;
}
@@ -83,7 +114,7 @@ public abstract class SharedStealthSystem : EntitySystem
component.LastUpdated = _timing.CurTime;
}
component.LastVisibility = Math.Clamp(component.LastVisibility + delta, -1f, 1f);
component.LastVisibility = Math.Clamp(component.LastVisibility + delta, component.MinVisibility, component.MaxVisibility);
Dirty(component);
}
@@ -96,7 +127,7 @@ public abstract class SharedStealthSystem : EntitySystem
if (!Resolve(uid, ref component))
return;
component.LastVisibility = value;
component.LastVisibility = Math.Clamp(value, component.MinVisibility, component.MaxVisibility);
if (component.LastUpdated != null)
component.LastUpdated = _timing.CurTime;
@@ -107,16 +138,18 @@ public abstract class SharedStealthSystem : EntitySystem
/// Gets the current visibility from the <see cref="StealthComponent"/>
/// Use this instead of getting LastVisibility from the component directly.
/// </summary>
/// <returns>Returns a calculation that accounts for any stealth change that happened since last update, otherwise returns based on if it can resolve the component.</returns>
/// <returns>Returns a calculation that accounts for any stealth change that happened since last update, otherwise
/// returns based on if it can resolve the component. Note that the returned value may be larger than the components
/// maximum stealth value if it is currently disabled.</returns>
public float GetVisibility(EntityUid uid, StealthComponent? component = null)
{
if (!Resolve(uid, ref component))
if (!Resolve(uid, ref component) || !component.Enabled)
return 1;
if (component.LastUpdated == null)
return component.LastVisibility;
var deltaTime = _timing.CurTime - component.LastUpdated.Value;
return Math.Clamp(component.LastVisibility + (float) deltaTime.TotalSeconds * component.PassiveVisibilityRate, -1f, 1f);
return Math.Clamp(component.LastVisibility + (float) deltaTime.TotalSeconds * component.PassiveVisibilityRate, component.MinVisibility, component.MaxVisibility);
}
}