Fix gravity shenanigans (#12866)
This commit is contained in:
59
Content.Client/Gravity/GravitySystem.Shake.cs
Normal file
59
Content.Client/Gravity/GravitySystem.Shake.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
using Content.Shared.Camera;
|
||||
using Content.Shared.Gravity;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Client.Gravity;
|
||||
|
||||
public sealed partial class GravitySystem
|
||||
{
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly SharedCameraRecoilSystem _sharedCameraRecoil = default!;
|
||||
|
||||
private void InitializeShake()
|
||||
{
|
||||
SubscribeLocalEvent<GravityShakeComponent, ComponentInit>(OnShakeInit);
|
||||
}
|
||||
|
||||
private void OnShakeInit(EntityUid uid, GravityShakeComponent component, ComponentInit args)
|
||||
{
|
||||
var localPlayer = _playerManager.LocalPlayer?.ControlledEntity;
|
||||
|
||||
if (!TryComp<TransformComponent>(localPlayer, out var xform) ||
|
||||
xform.GridUid != uid && xform.MapUid != uid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Timing.IsFirstTimePredicted && TryComp<GravityComponent>(uid, out var gravity))
|
||||
{
|
||||
_audio.PlayGlobal(gravity.GravityShakeSound, Filter.Local(), true, AudioParams.Default.WithVolume(-2f));
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ShakeGrid(EntityUid uid, GravityComponent? gravity = null)
|
||||
{
|
||||
base.ShakeGrid(uid, gravity);
|
||||
|
||||
if (!Resolve(uid, ref gravity) || !Timing.IsFirstTimePredicted)
|
||||
return;
|
||||
|
||||
var localPlayer = _playerManager.LocalPlayer?.ControlledEntity;
|
||||
|
||||
if (!TryComp<TransformComponent>(localPlayer, out var xform))
|
||||
return;
|
||||
|
||||
if (xform.GridUid != uid ||
|
||||
xform.GridUid == null && xform.MapUid != uid)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var kick = new Vector2(_random.NextFloat(), _random.NextFloat()) * GravityKick;
|
||||
_sharedCameraRecoil.KickCamera(localPlayer.Value, kick);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
using Content.Shared.Gravity;
|
||||
|
||||
namespace Content.Client.Gravity
|
||||
{
|
||||
public sealed class GravitySystem : SharedGravitySystem
|
||||
{
|
||||
namespace Content.Client.Gravity;
|
||||
|
||||
public sealed partial class GravitySystem : SharedGravitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
InitializeShake();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Gravity;
|
||||
using Content.Server.Gravity.EntitySystems;
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.Coordinates;
|
||||
using NUnit.Framework;
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
using Content.Shared.Camera;
|
||||
using Content.Shared.Gravity;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server.Gravity.EntitySystems
|
||||
{
|
||||
/// <summary>
|
||||
/// Handles the grid shake effect used by the gravity generator.
|
||||
/// </summary>
|
||||
public sealed class GravityShakeSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
[Dependency] private readonly SharedCameraRecoilSystem _sharedCameraRecoil = default!;
|
||||
|
||||
private Dictionary<EntityUid, uint> _gridsToShake = new();
|
||||
|
||||
private const float GravityKick = 100.0f;
|
||||
private const uint ShakeTimes = 10;
|
||||
|
||||
private float _internalTimer;
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
if (_gridsToShake.Count > 0)
|
||||
{
|
||||
_internalTimer += frameTime;
|
||||
|
||||
if (_internalTimer > 0.2f)
|
||||
{
|
||||
// TODO: Could just have clients do this themselves via event and save bandwidth.
|
||||
ShakeGrids();
|
||||
_internalTimer -= 0.2f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_internalTimer = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
public void ShakeGrid(EntityUid gridId, GravityComponent comp)
|
||||
{
|
||||
_gridsToShake[gridId] = ShakeTimes;
|
||||
|
||||
SoundSystem.Play(comp.GravityShakeSound.GetSound(),
|
||||
Filter.BroadcastGrid(gridId), AudioParams.Default.WithVolume(-2f));
|
||||
}
|
||||
|
||||
private void ShakeGrids()
|
||||
{
|
||||
// I have to copy this because C# doesn't allow changing collections while they're
|
||||
// getting enumerated.
|
||||
var gridsToShake = new Dictionary<EntityUid, uint>(_gridsToShake);
|
||||
foreach (var gridId in _gridsToShake.Keys)
|
||||
{
|
||||
if (_gridsToShake[gridId] == 0)
|
||||
{
|
||||
gridsToShake.Remove(gridId);
|
||||
continue;
|
||||
}
|
||||
ShakeGrid(gridId);
|
||||
gridsToShake[gridId] -= 1;
|
||||
}
|
||||
|
||||
_gridsToShake = gridsToShake;
|
||||
}
|
||||
|
||||
private void ShakeGrid(EntityUid gridId)
|
||||
{
|
||||
foreach (var player in _playerManager.Sessions)
|
||||
{
|
||||
if (player.AttachedEntity is not {Valid: true} attached
|
||||
|| EntityManager.GetComponent<TransformComponent>(attached).GridUid != gridId
|
||||
|| !EntityManager.HasComponent<CameraRecoilComponent>(attached))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var kick = new Vector2(_random.NextFloat(), _random.NextFloat()) * GravityKick;
|
||||
_sharedCameraRecoil.KickCamera(player.AttachedEntity.Value, kick);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
using Content.Shared.Gravity;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace Content.Server.Gravity.EntitySystems
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class GravitySystem : SharedGravitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<GravityComponent, ComponentInit>(OnGravityInit);
|
||||
SubscribeLocalEvent<GravityComponent, ComponentShutdown>(OnGravityShutdown);
|
||||
}
|
||||
|
||||
private void OnGravityInit(EntityUid uid, GravityComponent component, ComponentInit args)
|
||||
{
|
||||
// Incase there's already a generator on the grid we'll just set it now.
|
||||
var gridId = Transform(component.Owner).GridUid;
|
||||
|
||||
if (gridId == null)
|
||||
return;
|
||||
|
||||
GravityChangedEvent message;
|
||||
|
||||
foreach (var generator in EntityManager.EntityQuery<GravityGeneratorComponent>())
|
||||
{
|
||||
if (Transform(generator.Owner).GridUid == gridId && generator.GravityActive)
|
||||
{
|
||||
component.Enabled = true;
|
||||
message = new GravityChangedEvent(gridId.Value, true);
|
||||
RaiseLocalEvent(message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
component.Enabled = false;
|
||||
message = new GravityChangedEvent(gridId.Value, false);
|
||||
RaiseLocalEvent(message);
|
||||
}
|
||||
|
||||
private void OnGravityShutdown(EntityUid uid, GravityComponent component, ComponentShutdown args)
|
||||
{
|
||||
DisableGravity(component);
|
||||
}
|
||||
|
||||
public void EnableGravity(GravityComponent comp)
|
||||
{
|
||||
if (comp.Enabled)
|
||||
return;
|
||||
|
||||
var gridId = Transform(comp.Owner).GridUid;
|
||||
Dirty(comp);
|
||||
|
||||
if (gridId == null)
|
||||
return;
|
||||
|
||||
comp.Enabled = true;
|
||||
var message = new GravityChangedEvent(gridId.Value, true);
|
||||
RaiseLocalEvent(message);
|
||||
|
||||
}
|
||||
|
||||
public void DisableGravity(GravityComponent comp)
|
||||
{
|
||||
if (!comp.Enabled)
|
||||
return;
|
||||
|
||||
comp.Enabled = false;
|
||||
Dirty(comp);
|
||||
|
||||
var gridId = Transform(comp.Owner).GridUid;
|
||||
if (gridId == null)
|
||||
return;
|
||||
|
||||
var message = new GravityChangedEvent(gridId.Value, false);
|
||||
RaiseLocalEvent(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using Content.Server.Gravity.EntitySystems;
|
||||
using Content.Shared.Gravity;
|
||||
using Content.Shared.Gravity;
|
||||
|
||||
namespace Content.Server.Gravity
|
||||
{
|
||||
@@ -36,11 +35,10 @@ namespace Content.Server.Gravity
|
||||
/// <summary>
|
||||
/// Is the gravity generator currently "producing" gravity?
|
||||
/// </summary>
|
||||
[DataField("active")]
|
||||
public bool GravityActive { get; set; } = true;
|
||||
[ViewVariables]
|
||||
public bool GravityActive { get; set; } = false;
|
||||
|
||||
// Do we need a UI update even if the charge doesn't change? Used by power button.
|
||||
[ViewVariables] public bool NeedUIUpdate { get; set; }
|
||||
[ViewVariables] public bool NeedGravityUpdate { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,23 +3,21 @@ using Content.Server.Power.Components;
|
||||
using Content.Shared.Gravity;
|
||||
using Content.Shared.Interaction;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
namespace Content.Server.Gravity.EntitySystems
|
||||
namespace Content.Server.Gravity
|
||||
{
|
||||
public sealed class GravityGeneratorSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly AmbientSoundSystem _ambientSoundSystem = default!;
|
||||
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
||||
[Dependency] private readonly GravitySystem _gravitySystem = default!;
|
||||
[Dependency] private readonly GravityShakeSystem _gravityShakeSystem = default!;
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<GravityGeneratorComponent, ComponentInit>(OnComponentInitialized);
|
||||
SubscribeLocalEvent<GravityGeneratorComponent, ComponentInit>(OnCompInit);
|
||||
SubscribeLocalEvent<GravityGeneratorComponent, ComponentShutdown>(OnComponentShutdown);
|
||||
SubscribeLocalEvent<GravityGeneratorComponent, EntParentChangedMessage>(OnParentChanged); // Or just anchor changed?
|
||||
SubscribeLocalEvent<GravityGeneratorComponent, InteractHandEvent>(OnInteractHand);
|
||||
@@ -29,17 +27,21 @@ namespace Content.Server.Gravity.EntitySystems
|
||||
|
||||
private void OnParentChanged(EntityUid uid, GravityGeneratorComponent component, ref EntParentChangedMessage args)
|
||||
{
|
||||
// TODO consider stations with more than one generator.
|
||||
if (component.GravityActive && TryComp(args.OldParent, out GravityComponent? gravity))
|
||||
_gravitySystem.DisableGravity(gravity);
|
||||
|
||||
UpdateGravityActive(component, false);
|
||||
{
|
||||
_gravitySystem.RefreshGravity(args.OldParent.Value, gravity);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnComponentShutdown(EntityUid uid, GravityGeneratorComponent component, ComponentShutdown args)
|
||||
{
|
||||
if (component.GravityActive &&
|
||||
TryComp<TransformComponent>(uid, out var xform) &&
|
||||
TryComp(xform.ParentUid, out GravityComponent? gravity))
|
||||
{
|
||||
component.GravityActive = false;
|
||||
UpdateGravityActive(component, true);
|
||||
_gravitySystem.RefreshGravity(xform.ParentUid, gravity);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
@@ -50,7 +52,7 @@ namespace Content.Server.Gravity.EntitySystems
|
||||
.EntityQuery<GravityGeneratorComponent, ApcPowerReceiverComponent>())
|
||||
{
|
||||
if (!gravGen.Intact)
|
||||
return;
|
||||
continue;
|
||||
|
||||
// Calculate charge rate based on power state and such.
|
||||
// Negative charge rate means discharging.
|
||||
@@ -75,8 +77,7 @@ namespace Content.Server.Gravity.EntitySystems
|
||||
chargeRate = -gravGen.ChargeRate;
|
||||
}
|
||||
|
||||
var updateGravity = gravGen.NeedGravityUpdate;
|
||||
var shakeGravity = false;
|
||||
var active = gravGen.GravityActive;
|
||||
var lastCharge = gravGen.Charge;
|
||||
gravGen.Charge = Math.Clamp(gravGen.Charge + frameTime * chargeRate, 0, 1);
|
||||
if (chargeRate > 0)
|
||||
@@ -84,8 +85,6 @@ namespace Content.Server.Gravity.EntitySystems
|
||||
// Charging.
|
||||
if (MathHelper.CloseTo(gravGen.Charge, 1) && !gravGen.GravityActive)
|
||||
{
|
||||
shakeGravity = true;
|
||||
updateGravity = true;
|
||||
gravGen.GravityActive = true;
|
||||
}
|
||||
}
|
||||
@@ -94,8 +93,6 @@ namespace Content.Server.Gravity.EntitySystems
|
||||
// Discharging
|
||||
if (MathHelper.CloseTo(gravGen.Charge, 0) && gravGen.GravityActive)
|
||||
{
|
||||
shakeGravity = true;
|
||||
updateGravity = true;
|
||||
gravGen.GravityActive = false;
|
||||
}
|
||||
}
|
||||
@@ -110,9 +107,19 @@ namespace Content.Server.Gravity.EntitySystems
|
||||
if (updateUI)
|
||||
UpdateUI(gravGen, powerReceiver, chargeRate);
|
||||
|
||||
if (updateGravity)
|
||||
if (active != gravGen.GravityActive &&
|
||||
TryComp<TransformComponent>(gravGen.Owner, out var xform) &&
|
||||
TryComp<GravityComponent>(xform.ParentUid, out var gravity))
|
||||
{
|
||||
UpdateGravityActive(gravGen, shakeGravity);
|
||||
// Force it on in the faster path.
|
||||
if (gravGen.GravityActive)
|
||||
{
|
||||
_gravitySystem.EnableGravity(xform.ParentUid, gravity);
|
||||
}
|
||||
else
|
||||
{
|
||||
_gravitySystem.RefreshGravity(xform.ParentUid, gravity);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -182,11 +189,8 @@ namespace Content.Server.Gravity.EntitySystems
|
||||
component.NeedUIUpdate = false;
|
||||
}
|
||||
|
||||
private void OnComponentInitialized(EntityUid uid, GravityGeneratorComponent component, ComponentInit args)
|
||||
private void OnCompInit(EntityUid uid, GravityGeneratorComponent component, ComponentInit args)
|
||||
{
|
||||
// Always update gravity on init.
|
||||
component.NeedGravityUpdate = true;
|
||||
|
||||
ApcPowerReceiverComponent? powerReceiver = null;
|
||||
if (!Resolve(uid, ref powerReceiver, false))
|
||||
return;
|
||||
@@ -195,23 +199,6 @@ namespace Content.Server.Gravity.EntitySystems
|
||||
UpdateState(component, powerReceiver);
|
||||
}
|
||||
|
||||
private void UpdateGravityActive(GravityGeneratorComponent grav, bool shake)
|
||||
{
|
||||
var gridId = EntityManager.GetComponent<TransformComponent>(grav.Owner).GridUid;
|
||||
if (!_mapManager.TryGetGrid(gridId, out var grid))
|
||||
return;
|
||||
|
||||
var gravity = EntityManager.GetComponent<GravityComponent>(gridId.Value);
|
||||
|
||||
if (grav.GravityActive)
|
||||
_gravitySystem.EnableGravity(gravity);
|
||||
else
|
||||
_gravitySystem.DisableGravity(gravity);
|
||||
|
||||
if (shake)
|
||||
_gravityShakeSystem.ShakeGrid(gridId.Value, gravity);
|
||||
}
|
||||
|
||||
private void OnInteractHand(EntityUid uid, GravityGeneratorComponent component, InteractHandEvent args)
|
||||
{
|
||||
if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor))
|
||||
@@ -233,7 +220,7 @@ namespace Content.Server.Gravity.EntitySystems
|
||||
{
|
||||
var uid = grav.Owner;
|
||||
var appearance = EntityManager.GetComponentOrNull<AppearanceComponent>(uid);
|
||||
appearance?.SetData(GravityGeneratorVisuals.Charge, grav.Charge);
|
||||
_appearance.SetData(uid, GravityGeneratorVisuals.Charge, grav.Charge, appearance);
|
||||
|
||||
if (EntityManager.TryGetComponent(uid, out PointLightComponent? pointLight))
|
||||
{
|
||||
@@ -243,48 +230,48 @@ namespace Content.Server.Gravity.EntitySystems
|
||||
|
||||
if (!grav.Intact)
|
||||
{
|
||||
MakeBroken(grav, appearance);
|
||||
MakeBroken(uid, grav, appearance);
|
||||
}
|
||||
else if (powerReceiver.PowerReceived < grav.IdlePowerUse)
|
||||
{
|
||||
MakeUnpowered(grav, appearance);
|
||||
MakeUnpowered(uid, grav, appearance);
|
||||
}
|
||||
else if (!grav.SwitchedOn)
|
||||
{
|
||||
MakeOff(grav, appearance);
|
||||
MakeOff(uid, grav, appearance);
|
||||
}
|
||||
else
|
||||
{
|
||||
MakeOn(grav, appearance);
|
||||
MakeOn(uid, grav, appearance);
|
||||
}
|
||||
}
|
||||
|
||||
private void MakeBroken(GravityGeneratorComponent component, AppearanceComponent? appearance)
|
||||
private void MakeBroken(EntityUid uid, GravityGeneratorComponent component, AppearanceComponent? appearance)
|
||||
{
|
||||
_ambientSoundSystem.SetAmbience(component.Owner, false);
|
||||
|
||||
appearance?.SetData(GravityGeneratorVisuals.State, GravityGeneratorStatus.Broken);
|
||||
_appearance.SetData(uid, GravityGeneratorVisuals.State, GravityGeneratorStatus.Broken);
|
||||
}
|
||||
|
||||
private void MakeUnpowered(GravityGeneratorComponent component, AppearanceComponent? appearance)
|
||||
private void MakeUnpowered(EntityUid uid, GravityGeneratorComponent component, AppearanceComponent? appearance)
|
||||
{
|
||||
_ambientSoundSystem.SetAmbience(component.Owner, false);
|
||||
|
||||
appearance?.SetData(GravityGeneratorVisuals.State, GravityGeneratorStatus.Unpowered);
|
||||
_appearance.SetData(uid, GravityGeneratorVisuals.State, GravityGeneratorStatus.Unpowered, appearance);
|
||||
}
|
||||
|
||||
private void MakeOff(GravityGeneratorComponent component, AppearanceComponent? appearance)
|
||||
private void MakeOff(EntityUid uid, GravityGeneratorComponent component, AppearanceComponent? appearance)
|
||||
{
|
||||
_ambientSoundSystem.SetAmbience(component.Owner, false);
|
||||
|
||||
appearance?.SetData(GravityGeneratorVisuals.State, GravityGeneratorStatus.Off);
|
||||
_appearance.SetData(uid, GravityGeneratorVisuals.State, GravityGeneratorStatus.Off, appearance);
|
||||
}
|
||||
|
||||
private void MakeOn(GravityGeneratorComponent component, AppearanceComponent? appearance)
|
||||
private void MakeOn(EntityUid uid, GravityGeneratorComponent component, AppearanceComponent? appearance)
|
||||
{
|
||||
_ambientSoundSystem.SetAmbience(component.Owner, true);
|
||||
|
||||
appearance?.SetData(GravityGeneratorVisuals.State, GravityGeneratorStatus.On);
|
||||
_appearance.SetData(uid, GravityGeneratorVisuals.State, GravityGeneratorStatus.On, appearance);
|
||||
}
|
||||
|
||||
private void OnSwitchGenerator(
|
||||
74
Content.Server/Gravity/GravitySystem.cs
Normal file
74
Content.Server/Gravity/GravitySystem.cs
Normal file
@@ -0,0 +1,74 @@
|
||||
using Content.Shared.Gravity;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.Gravity
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class GravitySystem : SharedGravitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<GravityComponent, ComponentInit>(OnGravityInit);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Iterates gravity components and checks if this entity can have gravity applied.
|
||||
/// </summary>
|
||||
public void RefreshGravity(EntityUid uid, GravityComponent? gravity = null)
|
||||
{
|
||||
if (!Resolve(uid, ref gravity))
|
||||
return;
|
||||
|
||||
var enabled = false;
|
||||
|
||||
foreach (var (comp, xform) in EntityQuery<GravityGeneratorComponent, TransformComponent>(true))
|
||||
{
|
||||
if (!comp.GravityActive || xform.ParentUid != uid)
|
||||
continue;
|
||||
|
||||
enabled = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (enabled != gravity.Enabled)
|
||||
{
|
||||
gravity.Enabled = enabled;
|
||||
var ev = new GravityChangedEvent(uid, enabled);
|
||||
RaiseLocalEvent(uid, ref ev, true);
|
||||
Dirty(gravity);
|
||||
|
||||
if (HasComp<MapGridComponent>(uid))
|
||||
{
|
||||
StartGridShake(uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnGravityInit(EntityUid uid, GravityComponent component, ComponentInit args)
|
||||
{
|
||||
RefreshGravity(uid);
|
||||
}
|
||||
|
||||
public void EnableGravity(EntityUid uid, GravityComponent? gravity = null)
|
||||
{
|
||||
if (!Resolve(uid, ref gravity))
|
||||
return;
|
||||
|
||||
if (gravity.Enabled)
|
||||
return;
|
||||
|
||||
gravity.Enabled = true;
|
||||
var ev = new GravityChangedEvent(uid, true);
|
||||
RaiseLocalEvent(uid, ref ev, true);
|
||||
Dirty(gravity);
|
||||
|
||||
if (HasComp<MapGridComponent>(uid))
|
||||
{
|
||||
StartGridShake(uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@ using System.Linq;
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.Atmos;
|
||||
using Content.Server.Atmos.Components;
|
||||
using Content.Server.Gravity.EntitySystems;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Gravity;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Content.Server.Conveyor;
|
||||
using Content.Server.Gravity.EntitySystems;
|
||||
using Content.Server.Gravity;
|
||||
using Content.Server.MachineLinking.Events;
|
||||
using Content.Server.MachineLinking.System;
|
||||
using Content.Server.Power.Components;
|
||||
|
||||
@@ -1,15 +1,5 @@
|
||||
namespace Content.Shared.Gravity
|
||||
{
|
||||
public sealed class GravityChangedEvent : EntityEventArgs
|
||||
{
|
||||
public GravityChangedEvent(EntityUid changedGridIndex, bool newGravityState)
|
||||
{
|
||||
HasGravity = newGravityState;
|
||||
ChangedGridIndex = changedGridIndex;
|
||||
}
|
||||
|
||||
public EntityUid ChangedGridIndex { get; }
|
||||
|
||||
public bool HasGravity { get; }
|
||||
}
|
||||
[ByRefEvent]
|
||||
public readonly record struct GravityChangedEvent(EntityUid ChangedGridIndex, bool HasGravity);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,8 @@ namespace Content.Shared.Gravity
|
||||
{
|
||||
if (Enabled == value) return;
|
||||
Enabled = value;
|
||||
IoCManager.Resolve<IEntityManager>().EventBus.RaiseLocalEvent(Owner, new GravityChangedEvent(Owner, value));
|
||||
var ev = new GravityChangedEvent(Owner, value);
|
||||
IoCManager.Resolve<IEntityManager>().EventBus.RaiseLocalEvent(Owner, ref ev);
|
||||
Dirty();
|
||||
}
|
||||
}
|
||||
|
||||
17
Content.Shared/Gravity/GravityShakeComponent.cs
Normal file
17
Content.Shared/Gravity/GravityShakeComponent.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||
|
||||
namespace Content.Shared.Gravity;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates this entity is shaking due to gravity changes.
|
||||
/// </summary>
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
public sealed class GravityShakeComponent : Component
|
||||
{
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("shakeTimes")]
|
||||
public int ShakeTimes;
|
||||
|
||||
[DataField("nextShake", customTypeSerializer:typeof(TimeOffsetSerializer))]
|
||||
public TimeSpan NextShake;
|
||||
}
|
||||
87
Content.Shared/Gravity/SharedGravitySystem.Shake.cs
Normal file
87
Content.Shared/Gravity/SharedGravitySystem.Shake.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Gravity;
|
||||
|
||||
public abstract partial class SharedGravitySystem
|
||||
{
|
||||
protected const float GravityKick = 100.0f;
|
||||
protected const float ShakeCooldown = 0.2f;
|
||||
|
||||
private void InitializeShake()
|
||||
{
|
||||
SubscribeLocalEvent<GravityShakeComponent, EntityUnpausedEvent>(OnShakeUnpaused);
|
||||
SubscribeLocalEvent<GravityShakeComponent, ComponentGetState>(OnShakeGetState);
|
||||
SubscribeLocalEvent<GravityShakeComponent, ComponentHandleState>(OnShakeHandleState);
|
||||
}
|
||||
|
||||
private void OnShakeUnpaused(EntityUid uid, GravityShakeComponent component, ref EntityUnpausedEvent args)
|
||||
{
|
||||
component.NextShake += args.PausedTime;
|
||||
}
|
||||
|
||||
private void UpdateShake()
|
||||
{
|
||||
var curTime = Timing.CurTime;
|
||||
var gravityQuery = GetEntityQuery<GravityComponent>();
|
||||
|
||||
foreach (var comp in EntityQuery<GravityShakeComponent>())
|
||||
{
|
||||
if (comp.NextShake <= curTime)
|
||||
{
|
||||
if (comp.ShakeTimes == 0 || !gravityQuery.TryGetComponent(comp.Owner, out var gravity))
|
||||
{
|
||||
RemCompDeferred<GravityShakeComponent>(comp.Owner);
|
||||
continue;
|
||||
}
|
||||
|
||||
ShakeGrid(comp.Owner, gravity);
|
||||
comp.ShakeTimes--;
|
||||
comp.NextShake += TimeSpan.FromSeconds(ShakeCooldown);
|
||||
Dirty(comp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void StartGridShake(EntityUid uid, GravityComponent? gravity = null)
|
||||
{
|
||||
if (!Resolve(uid, ref gravity, false))
|
||||
return;
|
||||
|
||||
if (!TryComp<GravityShakeComponent>(uid, out var shake))
|
||||
{
|
||||
shake = AddComp<GravityShakeComponent>(uid);
|
||||
shake.NextShake = Timing.CurTime;
|
||||
}
|
||||
|
||||
shake.ShakeTimes = 10;
|
||||
Dirty(shake);
|
||||
}
|
||||
|
||||
protected virtual void ShakeGrid(EntityUid uid, GravityComponent? comp = null) {}
|
||||
|
||||
private void OnShakeHandleState(EntityUid uid, GravityShakeComponent component, ref ComponentHandleState args)
|
||||
{
|
||||
if (args.Current is not GravityShakeComponentState state)
|
||||
return;
|
||||
|
||||
component.ShakeTimes = state.ShakeTimes;
|
||||
component.NextShake = state.NextShake;
|
||||
}
|
||||
|
||||
private void OnShakeGetState(EntityUid uid, GravityShakeComponent component, ref ComponentGetState args)
|
||||
{
|
||||
args.State = new GravityShakeComponentState()
|
||||
{
|
||||
ShakeTimes = component.ShakeTimes,
|
||||
NextShake = component.NextShake,
|
||||
};
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
protected sealed class GravityShakeComponentState : ComponentState
|
||||
{
|
||||
public int ShakeTimes;
|
||||
public TimeSpan NextShake;
|
||||
}
|
||||
}
|
||||
@@ -7,11 +7,13 @@ using Robust.Shared.Map;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Shared.Gravity
|
||||
{
|
||||
public abstract class SharedGravitySystem : EntitySystem
|
||||
public abstract partial class SharedGravitySystem : EntitySystem
|
||||
{
|
||||
[Dependency] protected readonly IGameTiming Timing = default!;
|
||||
[Dependency] private readonly AlertsSystem _alerts = default!;
|
||||
[Dependency] private readonly InventorySystem _inventory = default!;
|
||||
|
||||
@@ -29,8 +31,8 @@ namespace Content.Shared.Gravity
|
||||
return true;
|
||||
|
||||
// If grid / map has gravity
|
||||
if ((TryComp<GravityComponent>(xform.GridUid, out var gravity) ||
|
||||
TryComp(xform.MapUid, out gravity)) && gravity.Enabled)
|
||||
if (TryComp<GravityComponent>(xform.GridUid, out var gravity) && gravity.Enabled ||
|
||||
TryComp(xform.MapUid, out gravity) && gravity.Enabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -50,11 +52,20 @@ namespace Content.Shared.Gravity
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<GridInitializeEvent>(HandleGridInitialize);
|
||||
SubscribeLocalEvent<GridInitializeEvent>(OnGridInit);
|
||||
SubscribeLocalEvent<AlertSyncEvent>(OnAlertsSync);
|
||||
SubscribeLocalEvent<AlertsComponent, EntParentChangedMessage>(OnAlertsParentChange);
|
||||
SubscribeLocalEvent<GravityChangedEvent>(OnGravityChange);
|
||||
SubscribeLocalEvent<GravityComponent, ComponentGetState>(OnGetState);
|
||||
SubscribeLocalEvent<GravityComponent, ComponentHandleState>(OnHandleState);
|
||||
|
||||
InitializeShake();
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
UpdateShake();
|
||||
}
|
||||
|
||||
private void OnHandleState(EntityUid uid, GravityComponent component, ref ComponentHandleState args)
|
||||
@@ -71,7 +82,7 @@ namespace Content.Shared.Gravity
|
||||
args.State = new GravityComponentState(component.EnabledVV);
|
||||
}
|
||||
|
||||
private void OnGravityChange(GravityChangedEvent ev)
|
||||
private void OnGravityChange(ref GravityChangedEvent ev)
|
||||
{
|
||||
foreach (var (comp, xform) in EntityQuery<AlertsComponent, TransformComponent>(true))
|
||||
{
|
||||
@@ -88,6 +99,18 @@ namespace Content.Shared.Gravity
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAlertsSync(AlertSyncEvent ev)
|
||||
{
|
||||
if (IsWeightless(ev.Euid))
|
||||
{
|
||||
_alerts.ShowAlert(ev.Euid, AlertType.Weightless);
|
||||
}
|
||||
else
|
||||
{
|
||||
_alerts.ClearAlert(ev.Euid, AlertType.Weightless);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAlertsParentChange(EntityUid uid, AlertsComponent component, ref EntParentChangedMessage args)
|
||||
{
|
||||
if (IsWeightless(component.Owner))
|
||||
@@ -100,7 +123,7 @@ namespace Content.Shared.Gravity
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleGridInitialize(GridInitializeEvent ev)
|
||||
private void OnGridInit(GridInitializeEvent ev)
|
||||
{
|
||||
EntityManager.EnsureComponent<GravityComponent>(ev.EntityUid);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public abstract class SharedJetpackSystem : EntitySystem
|
||||
args.CanMove = true;
|
||||
}
|
||||
|
||||
private void OnJetpackUserGravityChanged(GravityChangedEvent ev)
|
||||
private void OnJetpackUserGravityChanged(ref GravityChangedEvent ev)
|
||||
{
|
||||
var gridUid = ev.ChangedGridIndex;
|
||||
var jetpackQuery = GetEntityQuery<JetpackComponent>();
|
||||
|
||||
Reference in New Issue
Block a user