Fix gravity shenanigans (#12866)
This commit is contained in:
@@ -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)
|
||||
{
|
||||
component.GravityActive = false;
|
||||
UpdateGravityActive(component, true);
|
||||
if (component.GravityActive &&
|
||||
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)
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user