Files
tbd-station-14/Content.Shared/Gravity/SharedGravitySystem.cs
Nemanja 3644602fb8 Fix magboots not needing a grid to work (#29034)
* Fix magboots not needing a grid to work

* ok fix it for realsies
2024-06-16 13:38:17 +10:00

172 lines
5.7 KiB
C#

using Content.Shared.Alert;
using Content.Shared.Inventory;
using Content.Shared.Movement.Components;
using Robust.Shared.GameStates;
using Robust.Shared.Physics;
using Robust.Shared.Physics.Components;
using Robust.Shared.Serialization;
using Robust.Shared.Timing;
namespace Content.Shared.Gravity
{
public abstract partial class SharedGravitySystem : EntitySystem
{
[Dependency] protected readonly IGameTiming Timing = default!;
[Dependency] private readonly AlertsSystem _alerts = default!;
[ValidatePrototypeId<AlertPrototype>]
public const string WeightlessAlert = "Weightless";
private EntityQuery<GravityComponent> _gravityQuery;
public bool IsWeightless(EntityUid uid, PhysicsComponent? body = null, TransformComponent? xform = null)
{
Resolve(uid, ref body, false);
if ((body?.BodyType & (BodyType.Static | BodyType.Kinematic)) != 0)
return false;
if (TryComp<MovementIgnoreGravityComponent>(uid, out var ignoreGravityComponent))
return ignoreGravityComponent.Weightless;
var ev = new IsWeightlessEvent(uid);
RaiseLocalEvent(uid, ref ev);
if (ev.Handled)
return ev.IsWeightless;
if (!Resolve(uid, ref xform))
return true;
// If grid / map has gravity
if (EntityGridOrMapHaveGravity((uid, xform)))
return false;
return true;
}
/// <summary>
/// Checks if a given entity is currently standing on a grid or map that supports having gravity at all.
/// </summary>
public bool EntityOnGravitySupportingGridOrMap(Entity<TransformComponent?> entity)
{
entity.Comp ??= Transform(entity);
return _gravityQuery.HasComp(entity.Comp.GridUid) ||
_gravityQuery.HasComp(entity.Comp.MapUid);
}
/// <summary>
/// Checks if a given entity is currently standing on a grid or map that has gravity of some kind.
/// </summary>
public bool EntityGridOrMapHaveGravity(Entity<TransformComponent?> entity)
{
entity.Comp ??= Transform(entity);
return _gravityQuery.TryComp(entity.Comp.GridUid, out var gravity) && gravity.Enabled ||
_gravityQuery.TryComp(entity.Comp.MapUid, out var mapGravity) && mapGravity.Enabled;
}
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<GridInitializeEvent>(OnGridInit);
SubscribeLocalEvent<AlertSyncEvent>(OnAlertsSync);
SubscribeLocalEvent<AlertsComponent, EntParentChangedMessage>(OnAlertsParentChange);
SubscribeLocalEvent<GravityChangedEvent>(OnGravityChange);
SubscribeLocalEvent<GravityComponent, ComponentGetState>(OnGetState);
SubscribeLocalEvent<GravityComponent, ComponentHandleState>(OnHandleState);
_gravityQuery = GetEntityQuery<GravityComponent>();
}
public override void Update(float frameTime)
{
base.Update(frameTime);
UpdateShake();
}
private void OnHandleState(EntityUid uid, GravityComponent component, ref ComponentHandleState args)
{
if (args.Current is not GravityComponentState state)
return;
if (component.EnabledVV == state.Enabled)
return;
component.EnabledVV = state.Enabled;
var ev = new GravityChangedEvent(uid, component.EnabledVV);
RaiseLocalEvent(uid, ref ev, true);
}
private void OnGetState(EntityUid uid, GravityComponent component, ref ComponentGetState args)
{
args.State = new GravityComponentState(component.EnabledVV);
}
private void OnGravityChange(ref GravityChangedEvent ev)
{
var alerts = AllEntityQuery<AlertsComponent, TransformComponent>();
while(alerts.MoveNext(out var uid, out _, out var xform))
{
if (xform.GridUid != ev.ChangedGridIndex)
continue;
if (!ev.HasGravity)
{
_alerts.ShowAlert(uid, WeightlessAlert);
}
else
{
_alerts.ClearAlert(uid, WeightlessAlert);
}
}
}
private void OnAlertsSync(AlertSyncEvent ev)
{
if (IsWeightless(ev.Euid))
{
_alerts.ShowAlert(ev.Euid, WeightlessAlert);
}
else
{
_alerts.ClearAlert(ev.Euid, WeightlessAlert);
}
}
private void OnAlertsParentChange(EntityUid uid, AlertsComponent component, ref EntParentChangedMessage args)
{
if (IsWeightless(uid))
{
_alerts.ShowAlert(uid, WeightlessAlert);
}
else
{
_alerts.ClearAlert(uid, WeightlessAlert);
}
}
private void OnGridInit(GridInitializeEvent ev)
{
EntityManager.EnsureComponent<GravityComponent>(ev.EntityUid);
}
[Serializable, NetSerializable]
private sealed class GravityComponentState : ComponentState
{
public bool Enabled { get; }
public GravityComponentState(bool enabled)
{
Enabled = enabled;
}
}
}
[ByRefEvent]
public record struct IsWeightlessEvent(EntityUid Entity, bool IsWeightless = false, bool Handled = false) : IInventoryRelayEvent
{
SlotFlags IInventoryRelayEvent.TargetSlots => ~SlotFlags.POCKET;
}
}