Stasis bed cleanup and bugfixes. (#38762)
* Stasis bed sent to shed * Code Review * Code Review 2
This commit is contained in:
@@ -1,23 +1,15 @@
|
||||
using Content.Server.Bed.Components;
|
||||
using Content.Server.Power.EntitySystems;
|
||||
using Content.Shared.Bed;
|
||||
using Content.Shared.Bed.Components;
|
||||
using Content.Shared.Bed.Sleep;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Body.Events;
|
||||
using Content.Shared.Buckle.Components;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Emag.Systems;
|
||||
using Content.Shared.Mobs.Systems;
|
||||
using Content.Shared.Power;
|
||||
|
||||
namespace Content.Server.Bed
|
||||
{
|
||||
public sealed class BedSystem : SharedBedSystem
|
||||
{
|
||||
[Dependency] private readonly DamageableSystem _damageableSystem = default!;
|
||||
[Dependency] private readonly EmagSystem _emag = default!;
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
|
||||
|
||||
private EntityQuery<SleepingComponent> _sleepingQuery;
|
||||
@@ -27,11 +19,6 @@ namespace Content.Server.Bed
|
||||
base.Initialize();
|
||||
|
||||
_sleepingQuery = GetEntityQuery<SleepingComponent>();
|
||||
|
||||
SubscribeLocalEvent<StasisBedComponent, StrappedEvent>(OnStasisStrapped);
|
||||
SubscribeLocalEvent<StasisBedComponent, UnstrappedEvent>(OnStasisUnstrapped);
|
||||
SubscribeLocalEvent<StasisBedComponent, PowerChangedEvent>(OnPowerChanged);
|
||||
SubscribeLocalEvent<StasisBedComponent, GotEmaggedEvent>(OnEmagged);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
@@ -63,61 +50,5 @@ namespace Content.Server.Bed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateAppearance(EntityUid uid, bool isOn)
|
||||
{
|
||||
_appearance.SetData(uid, StasisBedVisuals.IsOn, isOn);
|
||||
}
|
||||
|
||||
private void OnStasisStrapped(Entity<StasisBedComponent> bed, ref StrappedEvent args)
|
||||
{
|
||||
if (!HasComp<BodyComponent>(args.Buckle) || !this.IsPowered(bed, EntityManager))
|
||||
return;
|
||||
|
||||
var metabolicEvent = new ApplyMetabolicMultiplierEvent(args.Buckle, bed.Comp.Multiplier, true);
|
||||
RaiseLocalEvent(args.Buckle, ref metabolicEvent);
|
||||
}
|
||||
|
||||
private void OnStasisUnstrapped(Entity<StasisBedComponent> bed, ref UnstrappedEvent args)
|
||||
{
|
||||
if (!HasComp<BodyComponent>(args.Buckle) || !this.IsPowered(bed, EntityManager))
|
||||
return;
|
||||
|
||||
var metabolicEvent = new ApplyMetabolicMultiplierEvent(args.Buckle, bed.Comp.Multiplier, false);
|
||||
RaiseLocalEvent(args.Buckle, ref metabolicEvent);
|
||||
}
|
||||
|
||||
private void OnPowerChanged(EntityUid uid, StasisBedComponent component, ref PowerChangedEvent args)
|
||||
{
|
||||
UpdateAppearance(uid, args.Powered);
|
||||
UpdateMetabolisms(uid, component, args.Powered);
|
||||
}
|
||||
|
||||
private void OnEmagged(EntityUid uid, StasisBedComponent component, ref GotEmaggedEvent args)
|
||||
{
|
||||
if (!_emag.CompareFlag(args.Type, EmagType.Interaction))
|
||||
return;
|
||||
|
||||
if (_emag.CheckFlag(uid, EmagType.Interaction))
|
||||
return;
|
||||
|
||||
// Reset any metabolisms first so they receive the multiplier correctly
|
||||
UpdateMetabolisms(uid, component, false);
|
||||
component.Multiplier = 1 / component.Multiplier;
|
||||
UpdateMetabolisms(uid, component, true);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void UpdateMetabolisms(EntityUid uid, StasisBedComponent component, bool shouldApply)
|
||||
{
|
||||
if (!TryComp<StrapComponent>(uid, out var strap) || strap.BuckledEntities.Count == 0)
|
||||
return;
|
||||
|
||||
foreach (var buckledEntity in strap.BuckledEntities)
|
||||
{
|
||||
var metabolicEvent = new ApplyMetabolicMultiplierEvent(buckledEntity, component.Multiplier, shouldApply);
|
||||
RaiseLocalEvent(buckledEntity, ref metabolicEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
namespace Content.Server.Bed.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed partial class StasisBedComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// What the metabolic update rate will be multiplied by (higher = slower metabolism)
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadOnly)] // Writing is is not supported. ApplyMetabolicMultiplierEvent needs to be refactored first
|
||||
[DataField]
|
||||
public float Multiplier = 10f;
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,18 @@ namespace Content.Server.Body.Components
|
||||
[DataField]
|
||||
public TimeSpan UpdateInterval = TimeSpan.FromSeconds(1);
|
||||
|
||||
/// <summary>
|
||||
/// Multiplier applied to <see cref="UpdateInterval"/> for adjusting based on metabolic rate multiplier.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float UpdateIntervalMultiplier = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// Adjusted update interval based off of the multiplier value.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public TimeSpan AdjustedUpdateInterval => UpdateInterval * UpdateIntervalMultiplier;
|
||||
|
||||
/// <summary>
|
||||
/// From which solution will this metabolizer attempt to metabolize chemicals
|
||||
/// </summary>
|
||||
@@ -46,14 +58,14 @@ namespace Content.Server.Body.Components
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[Access(typeof(MetabolizerSystem), Other = AccessPermissions.ReadExecute)] // FIXME Friends
|
||||
public HashSet<ProtoId<MetabolizerTypePrototype>>? MetabolizerTypes = null;
|
||||
public HashSet<ProtoId<MetabolizerTypePrototype>>? MetabolizerTypes;
|
||||
|
||||
/// <summary>
|
||||
/// Should this metabolizer remove chemicals that have no metabolisms defined?
|
||||
/// As a stop-gap, basically.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public bool RemoveEmpty = false;
|
||||
public bool RemoveEmpty;
|
||||
|
||||
/// <summary>
|
||||
/// How many reagents can this metabolizer process at once?
|
||||
@@ -67,7 +79,7 @@ namespace Content.Server.Body.Components
|
||||
/// A list of metabolism groups that this metabolizer will act on, in order of precedence.
|
||||
/// </summary>
|
||||
[DataField("groups")]
|
||||
public List<MetabolismGroupEntry>? MetabolismGroups = default!;
|
||||
public List<MetabolismGroupEntry>? MetabolismGroups;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -78,7 +90,7 @@ namespace Content.Server.Body.Components
|
||||
public sealed partial class MetabolismGroupEntry
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public ProtoId<MetabolismGroupPrototype> Id = default!;
|
||||
public ProtoId<MetabolismGroupPrototype> Id;
|
||||
|
||||
[DataField("rateModifier")]
|
||||
public FixedPoint2 MetabolismRateModifier = 1.0;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Chat.Prototypes;
|
||||
using Content.Shared.Damage;
|
||||
@@ -8,7 +7,7 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||
|
||||
namespace Content.Server.Body.Components
|
||||
{
|
||||
[RegisterComponent, Access(typeof(RespiratorSystem))]
|
||||
[RegisterComponent, Access(typeof(RespiratorSystem)), AutoGenerateComponentPause]
|
||||
public sealed partial class RespiratorComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
@@ -36,7 +35,7 @@ namespace Content.Server.Body.Components
|
||||
/// <summary>
|
||||
/// The next time that this body will inhale or exhale.
|
||||
/// </summary>
|
||||
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer))]
|
||||
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoPausedField]
|
||||
public TimeSpan NextUpdate;
|
||||
|
||||
/// <summary>
|
||||
@@ -46,6 +45,18 @@ namespace Content.Server.Body.Components
|
||||
[DataField]
|
||||
public TimeSpan UpdateInterval = TimeSpan.FromSeconds(2);
|
||||
|
||||
/// <summary>
|
||||
/// Multiplier applied to <see cref="UpdateInterval"/> for adjusting based on metabolic rate multiplier.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public float UpdateIntervalMultiplier = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// Adjusted update interval based off of the multiplier value.
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
public TimeSpan AdjustedUpdateInterval => UpdateInterval * UpdateIntervalMultiplier;
|
||||
|
||||
/// <summary>
|
||||
/// Saturation level. Reduced by UpdateInterval each tick.
|
||||
/// Can be thought of as 'how many seconds you have until you start suffocating' in this configuration.
|
||||
|
||||
@@ -2,6 +2,7 @@ using Content.Server.Body.Components;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Body.Events;
|
||||
using Content.Shared.Body.Organ;
|
||||
using Content.Shared.Body.Systems;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
@@ -18,7 +19,8 @@ using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server.Body.Systems
|
||||
{
|
||||
public sealed class MetabolizerSystem : EntitySystem
|
||||
/// <inheritdoc/>
|
||||
public sealed class MetabolizerSystem : SharedMetabolizerSystem
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
@@ -45,7 +47,7 @@ namespace Content.Server.Body.Systems
|
||||
|
||||
private void OnMapInit(Entity<MetabolizerComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
ent.Comp.NextUpdate = _gameTiming.CurTime + ent.Comp.UpdateInterval;
|
||||
ent.Comp.NextUpdate = _gameTiming.CurTime + ent.Comp.AdjustedUpdateInterval;
|
||||
}
|
||||
|
||||
private void OnUnpaused(Entity<MetabolizerComponent> ent, ref EntityUnpausedEvent args)
|
||||
@@ -65,20 +67,9 @@ namespace Content.Server.Body.Systems
|
||||
}
|
||||
}
|
||||
|
||||
private void OnApplyMetabolicMultiplier(
|
||||
Entity<MetabolizerComponent> ent,
|
||||
ref ApplyMetabolicMultiplierEvent args)
|
||||
private void OnApplyMetabolicMultiplier(Entity<MetabolizerComponent> ent, ref ApplyMetabolicMultiplierEvent args)
|
||||
{
|
||||
// TODO REFACTOR THIS
|
||||
// This will slowly drift over time due to floating point errors.
|
||||
// Instead, raise an event with the base rates and allow modifiers to get applied to it.
|
||||
if (args.Apply)
|
||||
{
|
||||
ent.Comp.UpdateInterval *= args.Multiplier;
|
||||
return;
|
||||
}
|
||||
|
||||
ent.Comp.UpdateInterval /= args.Multiplier;
|
||||
ent.Comp.UpdateIntervalMultiplier = args.Multiplier;
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
@@ -99,7 +90,7 @@ namespace Content.Server.Body.Systems
|
||||
if (_gameTiming.CurTime < metab.NextUpdate)
|
||||
continue;
|
||||
|
||||
metab.NextUpdate += metab.UpdateInterval;
|
||||
metab.NextUpdate += metab.AdjustedUpdateInterval;
|
||||
TryMetabolize((uid, metab));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,6 @@ public sealed class RespiratorSystem : EntitySystem
|
||||
// We want to process lung reagents before we inhale new reagents.
|
||||
UpdatesAfter.Add(typeof(MetabolizerSystem));
|
||||
SubscribeLocalEvent<RespiratorComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<RespiratorComponent, EntityUnpausedEvent>(OnUnpaused);
|
||||
SubscribeLocalEvent<RespiratorComponent, ApplyMetabolicMultiplierEvent>(OnApplyMetabolicMultiplier);
|
||||
SubscribeLocalEvent<BodyComponent, InhaledGasEvent>(OnGasInhaled);
|
||||
SubscribeLocalEvent<BodyComponent, ExhaledGasEvent>(OnGasExhaled);
|
||||
@@ -56,25 +55,20 @@ public sealed class RespiratorSystem : EntitySystem
|
||||
|
||||
private void OnMapInit(Entity<RespiratorComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
ent.Comp.NextUpdate = _gameTiming.CurTime + ent.Comp.UpdateInterval;
|
||||
}
|
||||
|
||||
private void OnUnpaused(Entity<RespiratorComponent> ent, ref EntityUnpausedEvent args)
|
||||
{
|
||||
ent.Comp.NextUpdate += args.PausedTime;
|
||||
ent.Comp.NextUpdate = _gameTiming.CurTime + ent.Comp.AdjustedUpdateInterval;
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
var query = EntityQueryEnumerator<RespiratorComponent, BodyComponent>();
|
||||
while (query.MoveNext(out var uid, out var respirator, out var body))
|
||||
var query = EntityQueryEnumerator<RespiratorComponent>();
|
||||
while (query.MoveNext(out var uid, out var respirator))
|
||||
{
|
||||
if (_gameTiming.CurTime < respirator.NextUpdate)
|
||||
continue;
|
||||
|
||||
respirator.NextUpdate += respirator.UpdateInterval;
|
||||
respirator.NextUpdate += respirator.AdjustedUpdateInterval;
|
||||
|
||||
if (_mobState.IsDead(uid))
|
||||
continue;
|
||||
@@ -396,27 +390,9 @@ public sealed class RespiratorSystem : EntitySystem
|
||||
Math.Clamp(respirator.Saturation, respirator.MinSaturation, respirator.MaxSaturation);
|
||||
}
|
||||
|
||||
private void OnApplyMetabolicMultiplier(
|
||||
Entity<RespiratorComponent> ent,
|
||||
ref ApplyMetabolicMultiplierEvent args)
|
||||
private void OnApplyMetabolicMultiplier(Entity<RespiratorComponent> ent, ref ApplyMetabolicMultiplierEvent args)
|
||||
{
|
||||
// TODO REFACTOR THIS
|
||||
// This will slowly drift over time due to floating point errors.
|
||||
// Instead, raise an event with the base rates and allow modifiers to get applied to it.
|
||||
if (args.Apply)
|
||||
{
|
||||
ent.Comp.UpdateInterval *= args.Multiplier;
|
||||
ent.Comp.Saturation *= args.Multiplier;
|
||||
ent.Comp.MaxSaturation *= args.Multiplier;
|
||||
ent.Comp.MinSaturation *= args.Multiplier;
|
||||
return;
|
||||
}
|
||||
|
||||
// This way we don't have to worry about it breaking if the stasis bed component is destroyed
|
||||
ent.Comp.UpdateInterval /= args.Multiplier;
|
||||
ent.Comp.Saturation /= args.Multiplier;
|
||||
ent.Comp.MaxSaturation /= args.Multiplier;
|
||||
ent.Comp.MinSaturation /= args.Multiplier;
|
||||
ent.Comp.UpdateIntervalMultiplier = args.Multiplier;
|
||||
}
|
||||
|
||||
private void OnGasInhaled(Entity<BodyComponent> entity, ref InhaledGasEvent args)
|
||||
|
||||
@@ -45,6 +45,7 @@ namespace Content.Server.Power.EntitySystems
|
||||
UpdatesAfter.Add(typeof(NodeGroupSystem));
|
||||
_solver = new(_cfg.GetCVar(CCVars.DebugPow3rDisableParallel));
|
||||
|
||||
SubscribeLocalEvent<ApcPowerReceiverComponent, MapInitEvent>(ApcPowerReceiverMapInit);
|
||||
SubscribeLocalEvent<ApcPowerReceiverComponent, ComponentInit>(ApcPowerReceiverInit);
|
||||
SubscribeLocalEvent<ApcPowerReceiverComponent, ComponentShutdown>(ApcPowerReceiverShutdown);
|
||||
SubscribeLocalEvent<ApcPowerReceiverComponent, ComponentRemove>(ApcPowerReceiverRemove);
|
||||
@@ -74,6 +75,11 @@ namespace Content.Server.Power.EntitySystems
|
||||
_solver = new(val);
|
||||
}
|
||||
|
||||
private void ApcPowerReceiverMapInit(Entity<ApcPowerReceiverComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
_appearance.SetData(ent, PowerDeviceVisuals.Powered, ent.Comp.Powered);
|
||||
}
|
||||
|
||||
private void ApcPowerReceiverInit(EntityUid uid, ApcPowerReceiverComponent component, ComponentInit args)
|
||||
{
|
||||
AllocLoad(component.NetworkLoad);
|
||||
|
||||
Reference in New Issue
Block a user