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;
|
using Content.Shared.Gravity;
|
||||||
|
|
||||||
namespace Content.Client.Gravity
|
namespace Content.Client.Gravity;
|
||||||
{
|
|
||||||
public sealed class GravitySystem : SharedGravitySystem
|
|
||||||
{
|
|
||||||
|
|
||||||
|
public sealed partial class GravitySystem : SharedGravitySystem
|
||||||
|
{
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
InitializeShake();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Content.Server.Gravity;
|
using Content.Server.Gravity;
|
||||||
using Content.Server.Gravity.EntitySystems;
|
|
||||||
using Content.Shared.Alert;
|
using Content.Shared.Alert;
|
||||||
using Content.Shared.Coordinates;
|
using Content.Shared.Coordinates;
|
||||||
using NUnit.Framework;
|
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
|
namespace Content.Server.Gravity
|
||||||
{
|
{
|
||||||
@@ -36,11 +35,10 @@ namespace Content.Server.Gravity
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Is the gravity generator currently "producing" gravity?
|
/// Is the gravity generator currently "producing" gravity?
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("active")]
|
[ViewVariables]
|
||||||
public bool GravityActive { get; set; } = true;
|
public bool GravityActive { get; set; } = false;
|
||||||
|
|
||||||
// Do we need a UI update even if the charge doesn't change? Used by power button.
|
// 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 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.Gravity;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Map;
|
|
||||||
|
|
||||||
namespace Content.Server.Gravity.EntitySystems
|
namespace Content.Server.Gravity
|
||||||
{
|
{
|
||||||
public sealed class GravityGeneratorSystem : EntitySystem
|
public sealed class GravityGeneratorSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
|
||||||
[Dependency] private readonly AmbientSoundSystem _ambientSoundSystem = default!;
|
[Dependency] private readonly AmbientSoundSystem _ambientSoundSystem = default!;
|
||||||
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
|
||||||
[Dependency] private readonly GravitySystem _gravitySystem = 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()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
SubscribeLocalEvent<GravityGeneratorComponent, ComponentInit>(OnComponentInitialized);
|
SubscribeLocalEvent<GravityGeneratorComponent, ComponentInit>(OnCompInit);
|
||||||
SubscribeLocalEvent<GravityGeneratorComponent, ComponentShutdown>(OnComponentShutdown);
|
SubscribeLocalEvent<GravityGeneratorComponent, ComponentShutdown>(OnComponentShutdown);
|
||||||
SubscribeLocalEvent<GravityGeneratorComponent, EntParentChangedMessage>(OnParentChanged); // Or just anchor changed?
|
SubscribeLocalEvent<GravityGeneratorComponent, EntParentChangedMessage>(OnParentChanged); // Or just anchor changed?
|
||||||
SubscribeLocalEvent<GravityGeneratorComponent, InteractHandEvent>(OnInteractHand);
|
SubscribeLocalEvent<GravityGeneratorComponent, InteractHandEvent>(OnInteractHand);
|
||||||
@@ -29,17 +27,21 @@ namespace Content.Server.Gravity.EntitySystems
|
|||||||
|
|
||||||
private void OnParentChanged(EntityUid uid, GravityGeneratorComponent component, ref EntParentChangedMessage args)
|
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))
|
if (component.GravityActive && TryComp(args.OldParent, out GravityComponent? gravity))
|
||||||
_gravitySystem.DisableGravity(gravity);
|
{
|
||||||
|
_gravitySystem.RefreshGravity(args.OldParent.Value, gravity);
|
||||||
UpdateGravityActive(component, false);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnComponentShutdown(EntityUid uid, GravityGeneratorComponent component, ComponentShutdown args)
|
private void OnComponentShutdown(EntityUid uid, GravityGeneratorComponent component, ComponentShutdown args)
|
||||||
{
|
{
|
||||||
component.GravityActive = false;
|
if (component.GravityActive &&
|
||||||
UpdateGravityActive(component, true);
|
TryComp<TransformComponent>(uid, out var xform) &&
|
||||||
|
TryComp(xform.ParentUid, out GravityComponent? gravity))
|
||||||
|
{
|
||||||
|
component.GravityActive = false;
|
||||||
|
_gravitySystem.RefreshGravity(xform.ParentUid, gravity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
@@ -50,7 +52,7 @@ namespace Content.Server.Gravity.EntitySystems
|
|||||||
.EntityQuery<GravityGeneratorComponent, ApcPowerReceiverComponent>())
|
.EntityQuery<GravityGeneratorComponent, ApcPowerReceiverComponent>())
|
||||||
{
|
{
|
||||||
if (!gravGen.Intact)
|
if (!gravGen.Intact)
|
||||||
return;
|
continue;
|
||||||
|
|
||||||
// Calculate charge rate based on power state and such.
|
// Calculate charge rate based on power state and such.
|
||||||
// Negative charge rate means discharging.
|
// Negative charge rate means discharging.
|
||||||
@@ -75,8 +77,7 @@ namespace Content.Server.Gravity.EntitySystems
|
|||||||
chargeRate = -gravGen.ChargeRate;
|
chargeRate = -gravGen.ChargeRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
var updateGravity = gravGen.NeedGravityUpdate;
|
var active = gravGen.GravityActive;
|
||||||
var shakeGravity = false;
|
|
||||||
var lastCharge = gravGen.Charge;
|
var lastCharge = gravGen.Charge;
|
||||||
gravGen.Charge = Math.Clamp(gravGen.Charge + frameTime * chargeRate, 0, 1);
|
gravGen.Charge = Math.Clamp(gravGen.Charge + frameTime * chargeRate, 0, 1);
|
||||||
if (chargeRate > 0)
|
if (chargeRate > 0)
|
||||||
@@ -84,8 +85,6 @@ namespace Content.Server.Gravity.EntitySystems
|
|||||||
// Charging.
|
// Charging.
|
||||||
if (MathHelper.CloseTo(gravGen.Charge, 1) && !gravGen.GravityActive)
|
if (MathHelper.CloseTo(gravGen.Charge, 1) && !gravGen.GravityActive)
|
||||||
{
|
{
|
||||||
shakeGravity = true;
|
|
||||||
updateGravity = true;
|
|
||||||
gravGen.GravityActive = true;
|
gravGen.GravityActive = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,8 +93,6 @@ namespace Content.Server.Gravity.EntitySystems
|
|||||||
// Discharging
|
// Discharging
|
||||||
if (MathHelper.CloseTo(gravGen.Charge, 0) && gravGen.GravityActive)
|
if (MathHelper.CloseTo(gravGen.Charge, 0) && gravGen.GravityActive)
|
||||||
{
|
{
|
||||||
shakeGravity = true;
|
|
||||||
updateGravity = true;
|
|
||||||
gravGen.GravityActive = false;
|
gravGen.GravityActive = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -110,9 +107,19 @@ namespace Content.Server.Gravity.EntitySystems
|
|||||||
if (updateUI)
|
if (updateUI)
|
||||||
UpdateUI(gravGen, powerReceiver, chargeRate);
|
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;
|
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;
|
ApcPowerReceiverComponent? powerReceiver = null;
|
||||||
if (!Resolve(uid, ref powerReceiver, false))
|
if (!Resolve(uid, ref powerReceiver, false))
|
||||||
return;
|
return;
|
||||||
@@ -195,23 +199,6 @@ namespace Content.Server.Gravity.EntitySystems
|
|||||||
UpdateState(component, powerReceiver);
|
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)
|
private void OnInteractHand(EntityUid uid, GravityGeneratorComponent component, InteractHandEvent args)
|
||||||
{
|
{
|
||||||
if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor))
|
if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor))
|
||||||
@@ -233,7 +220,7 @@ namespace Content.Server.Gravity.EntitySystems
|
|||||||
{
|
{
|
||||||
var uid = grav.Owner;
|
var uid = grav.Owner;
|
||||||
var appearance = EntityManager.GetComponentOrNull<AppearanceComponent>(uid);
|
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))
|
if (EntityManager.TryGetComponent(uid, out PointLightComponent? pointLight))
|
||||||
{
|
{
|
||||||
@@ -243,48 +230,48 @@ namespace Content.Server.Gravity.EntitySystems
|
|||||||
|
|
||||||
if (!grav.Intact)
|
if (!grav.Intact)
|
||||||
{
|
{
|
||||||
MakeBroken(grav, appearance);
|
MakeBroken(uid, grav, appearance);
|
||||||
}
|
}
|
||||||
else if (powerReceiver.PowerReceived < grav.IdlePowerUse)
|
else if (powerReceiver.PowerReceived < grav.IdlePowerUse)
|
||||||
{
|
{
|
||||||
MakeUnpowered(grav, appearance);
|
MakeUnpowered(uid, grav, appearance);
|
||||||
}
|
}
|
||||||
else if (!grav.SwitchedOn)
|
else if (!grav.SwitchedOn)
|
||||||
{
|
{
|
||||||
MakeOff(grav, appearance);
|
MakeOff(uid, grav, appearance);
|
||||||
}
|
}
|
||||||
else
|
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);
|
_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);
|
_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);
|
_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);
|
_ambientSoundSystem.SetAmbience(component.Owner, true);
|
||||||
|
|
||||||
appearance?.SetData(GravityGeneratorVisuals.State, GravityGeneratorStatus.On);
|
_appearance.SetData(uid, GravityGeneratorVisuals.State, GravityGeneratorStatus.On, appearance);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSwitchGenerator(
|
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.Administration;
|
||||||
using Content.Server.Atmos;
|
using Content.Server.Atmos;
|
||||||
using Content.Server.Atmos.Components;
|
using Content.Server.Atmos.Components;
|
||||||
using Content.Server.Gravity.EntitySystems;
|
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
using Content.Shared.Atmos;
|
using Content.Shared.Atmos;
|
||||||
using Content.Shared.Gravity;
|
using Content.Shared.Gravity;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
using Content.Server.Conveyor;
|
using Content.Server.Conveyor;
|
||||||
using Content.Server.Gravity.EntitySystems;
|
using Content.Server.Gravity;
|
||||||
using Content.Server.MachineLinking.Events;
|
using Content.Server.MachineLinking.Events;
|
||||||
using Content.Server.MachineLinking.System;
|
using Content.Server.MachineLinking.System;
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
|
|||||||
@@ -1,15 +1,5 @@
|
|||||||
namespace Content.Shared.Gravity
|
namespace Content.Shared.Gravity
|
||||||
{
|
{
|
||||||
public sealed class GravityChangedEvent : EntityEventArgs
|
[ByRefEvent]
|
||||||
{
|
public readonly record struct GravityChangedEvent(EntityUid ChangedGridIndex, bool HasGravity);
|
||||||
public GravityChangedEvent(EntityUid changedGridIndex, bool newGravityState)
|
|
||||||
{
|
|
||||||
HasGravity = newGravityState;
|
|
||||||
ChangedGridIndex = changedGridIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EntityUid ChangedGridIndex { get; }
|
|
||||||
|
|
||||||
public bool HasGravity { get; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ namespace Content.Shared.Gravity
|
|||||||
{
|
{
|
||||||
if (Enabled == value) return;
|
if (Enabled == value) return;
|
||||||
Enabled = value;
|
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();
|
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;
|
||||||
using Robust.Shared.Physics.Components;
|
using Robust.Shared.Physics.Components;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
namespace Content.Shared.Gravity
|
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 AlertsSystem _alerts = default!;
|
||||||
[Dependency] private readonly InventorySystem _inventory = default!;
|
[Dependency] private readonly InventorySystem _inventory = default!;
|
||||||
|
|
||||||
@@ -29,8 +31,8 @@ namespace Content.Shared.Gravity
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
// If grid / map has gravity
|
// If grid / map has gravity
|
||||||
if ((TryComp<GravityComponent>(xform.GridUid, out var gravity) ||
|
if (TryComp<GravityComponent>(xform.GridUid, out var gravity) && gravity.Enabled ||
|
||||||
TryComp(xform.MapUid, out gravity)) && gravity.Enabled)
|
TryComp(xform.MapUid, out gravity) && gravity.Enabled)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -50,11 +52,20 @@ namespace Content.Shared.Gravity
|
|||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
SubscribeLocalEvent<GridInitializeEvent>(HandleGridInitialize);
|
SubscribeLocalEvent<GridInitializeEvent>(OnGridInit);
|
||||||
|
SubscribeLocalEvent<AlertSyncEvent>(OnAlertsSync);
|
||||||
SubscribeLocalEvent<AlertsComponent, EntParentChangedMessage>(OnAlertsParentChange);
|
SubscribeLocalEvent<AlertsComponent, EntParentChangedMessage>(OnAlertsParentChange);
|
||||||
SubscribeLocalEvent<GravityChangedEvent>(OnGravityChange);
|
SubscribeLocalEvent<GravityChangedEvent>(OnGravityChange);
|
||||||
SubscribeLocalEvent<GravityComponent, ComponentGetState>(OnGetState);
|
SubscribeLocalEvent<GravityComponent, ComponentGetState>(OnGetState);
|
||||||
SubscribeLocalEvent<GravityComponent, ComponentHandleState>(OnHandleState);
|
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)
|
private void OnHandleState(EntityUid uid, GravityComponent component, ref ComponentHandleState args)
|
||||||
@@ -71,7 +82,7 @@ namespace Content.Shared.Gravity
|
|||||||
args.State = new GravityComponentState(component.EnabledVV);
|
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))
|
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)
|
private void OnAlertsParentChange(EntityUid uid, AlertsComponent component, ref EntParentChangedMessage args)
|
||||||
{
|
{
|
||||||
if (IsWeightless(component.Owner))
|
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);
|
EntityManager.EnsureComponent<GravityComponent>(ev.EntityUid);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public abstract class SharedJetpackSystem : EntitySystem
|
|||||||
args.CanMove = true;
|
args.CanMove = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnJetpackUserGravityChanged(GravityChangedEvent ev)
|
private void OnJetpackUserGravityChanged(ref GravityChangedEvent ev)
|
||||||
{
|
{
|
||||||
var gridUid = ev.ChangedGridIndex;
|
var gridUid = ev.ChangedGridIndex;
|
||||||
var jetpackQuery = GetEntityQuery<JetpackComponent>();
|
var jetpackQuery = GetEntityQuery<JetpackComponent>();
|
||||||
|
|||||||
Reference in New Issue
Block a user