mech air overhaul (#19140)

Co-authored-by: deltanedas <@deltanedas:kde.org>
This commit is contained in:
deltanedas
2023-09-03 07:30:26 +01:00
committed by GitHub
parent b52b063d6f
commit 79394e7e70
6 changed files with 161 additions and 59 deletions

View File

@@ -0,0 +1,81 @@
using Content.Server.Atmos;
using Content.Server.Atmos.Piping.Components;
using Content.Server.Mech.Components;
using Content.Shared.Atmos;
using Content.Shared.Mech.Components;
using Robust.Shared.GameObjects;
namespace Content.Server.Mech.Systems;
// TODO: this could be reused for gasmask or something if MechAir wasnt a thing
public sealed partial class MechSystem
{
[Dependency] private readonly SharedTransformSystem _transform = default!;
private void InitializeFiltering()
{
SubscribeLocalEvent<MechAirIntakeComponent, AtmosDeviceUpdateEvent>(OnIntakeUpdate);
SubscribeLocalEvent<MechAirFilterComponent, AtmosDeviceUpdateEvent>(OnFilterUpdate);
}
private void OnIntakeUpdate(EntityUid uid, MechAirIntakeComponent intake, AtmosDeviceUpdateEvent args)
{
if (!TryComp<MechComponent>(uid, out var mech) || !mech.Airtight || !TryComp<MechAirComponent>(uid, out var mechAir))
return;
// if the mech is filled there is nothing to do
if (mechAir.Air.Pressure >= intake.Pressure)
return;
var environment = _atmosphere.GetContainingMixture(uid, true, true);
// nothing to intake from
if (environment == null)
return;
// absolute maximum pressure change
var pressureDelta = args.dt * intake.TargetPressureChange;
pressureDelta = MathF.Min(pressureDelta, intake.Pressure - mechAir.Air.Pressure);
if (pressureDelta <= 0)
return;
// how many moles to transfer to change internal pressure by pressureDelta
// ignores temperature difference because lazy
var transferMoles = pressureDelta * mechAir.Air.Volume / (environment.Temperature * Atmospherics.R);
_atmosphere.Merge(mechAir.Air, environment.Remove(transferMoles));
}
private void OnFilterUpdate(EntityUid uid, MechAirFilterComponent filter, AtmosDeviceUpdateEvent args)
{
if (!TryComp<MechComponent>(uid, out var mech) || !mech.Airtight || !TryComp<MechAirComponent>(uid, out var mechAir))
return;
var ratio = MathF.Min(1f, args.dt * filter.TransferRate / mechAir.Air.Volume);
var removed = mechAir.Air.RemoveRatio(ratio);
// nothing left to remove from the mech
if (MathHelper.CloseToPercent(removed.TotalMoles, 0f))
return;
var coordinates = Transform(uid).MapPosition;
GasMixture? destination = null;
if (_map.TryFindGridAt(coordinates, out _, out var grid))
{
var tile = grid.GetTileRef(coordinates);
destination = _atmosphere.GetTileMixture(tile.GridUid, null, tile.GridIndices, true);
}
if (destination != null)
{
_atmosphere.ScrubInto(removed, destination, filter.Gases);
}
else
{
// filtering into space/planet so just discard them
foreach (var gas in filter.Gases)
{
removed.SetMoles(gas, 0f);
}
}
_atmosphere.Merge(mechAir.Air, removed);
}
}

View File

@@ -24,17 +24,17 @@ using Robust.Shared.Map;
namespace Content.Server.Mech.Systems;
/// <inheritdoc/>
public sealed class MechSystem : SharedMechSystem
public sealed partial class MechSystem : SharedMechSystem
{
[Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;
[Dependency] private readonly AtmosphereSystem _atmosphere = default!;
[Dependency] private readonly BatterySystem _battery = default!;
[Dependency] private readonly ContainerSystem _container = default!;
[Dependency] private readonly DamageableSystem _damageable = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly IMapManager _map = default!;
[Dependency] private readonly UserInterfaceSystem _ui = default!;
[Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly BatterySystem _batterySystem = default!;
[Dependency] private readonly UserInterfaceSystem _ui = default!;
private ISawmill _sawmill = default!;
@@ -45,6 +45,8 @@ public sealed class MechSystem : SharedMechSystem
_sawmill = Logger.GetSawmill("mech");
InitializeFiltering();
SubscribeLocalEvent<MechComponent, InteractUsingEvent>(OnInteractUsing);
SubscribeLocalEvent<MechComponent, EntInsertedIntoContainerMessage>(OnInsertBattery);
SubscribeLocalEvent<MechComponent, MapInitEvent>(OnMapInit);
@@ -127,11 +129,14 @@ public sealed class MechSystem : SharedMechSystem
private void OnMapInit(EntityUid uid, MechComponent component, MapInitEvent args)
{
var xform = Transform(uid);
foreach (var ent in component.StartingEquipment.Select(equipment => Spawn(equipment, xform.Coordinates)))
// TODO: this should use containerfill?
foreach (var equipment in component.StartingEquipment)
{
var ent = Spawn(equipment, xform.Coordinates);
InsertEquipment(uid, ent, component);
}
// TODO: this should just be damage and battery
component.Integrity = component.MaxIntegrity;
component.Energy = component.MaxEnergy;
@@ -305,56 +310,6 @@ public sealed class MechSystem : SharedMechSystem
UserInterfaceSystem.SetUiState(ui, state);
}
public override bool TryInsert(EntityUid uid, EntityUid? toInsert, MechComponent? component = null)
{
if (!Resolve(uid, ref component))
return false;
if (!base.TryInsert(uid, toInsert, component))
return false;
if (component.Airtight && TryComp(uid, out MechAirComponent? mechAir))
{
var coordinates = Transform(uid).MapPosition;
if (_map.TryFindGridAt(coordinates, out _, out var grid))
{
var tile = grid.GetTileRef(coordinates);
if (_atmosphere.GetTileMixture(tile.GridUid, null, tile.GridIndices, true) is { } environment)
{
_atmosphere.Merge(mechAir.Air, environment.RemoveVolume(MechAirComponent.GasMixVolume));
}
}
}
return true;
}
public override bool TryEject(EntityUid uid, MechComponent? component = null)
{
if (!Resolve(uid, ref component))
return false;
if (!base.TryEject(uid, component))
return false;
if (component.Airtight && TryComp(uid, out MechAirComponent? mechAir))
{
var coordinates = Transform(uid).MapPosition;
if (_map.TryFindGridAt(coordinates, out _, out var grid))
{
var tile = grid.GetTileRef(coordinates);
if (_atmosphere.GetTileMixture(tile.GridUid, null, tile.GridIndices, true) is { } environment)
{
_atmosphere.Merge(environment, mechAir.Air);
mechAir.Air.Clear();
}
}
}
return true;
}
public override void BreakMech(EntityUid uid, MechComponent? component = null)
{
base.BreakMech(uid, component);
@@ -378,7 +333,7 @@ public sealed class MechSystem : SharedMechSystem
if (!TryComp<BatteryComponent>(battery, out var batteryComp))
return false;
_batterySystem.SetCharge(battery!.Value, batteryComp.CurrentCharge + delta.Float(), batteryComp);
_battery.SetCharge(battery!.Value, batteryComp.CurrentCharge + delta.Float(), batteryComp);
if (batteryComp.CurrentCharge != component.Energy) //if there's a discrepency, we have to resync them
{
_sawmill.Debug($"Battery charge was not equal to mech charge. Battery {batteryComp.CurrentCharge}. Mech {component.Energy}");