Add multipart machines system (#35969)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using Content.Server.ParticleAccelerator.Components;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Machines.Components;
|
||||
using Content.Shared.Singularity.Components;
|
||||
using Robust.Shared.Utility;
|
||||
using System.Diagnostics;
|
||||
@@ -10,6 +11,8 @@ using Content.Shared.Power;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Player;
|
||||
using Content.Shared.ParticleAccelerator;
|
||||
using Content.Shared.Machines.Events;
|
||||
|
||||
namespace Content.Server.ParticleAccelerator.EntitySystems;
|
||||
|
||||
@@ -20,12 +23,11 @@ public sealed partial class ParticleAcceleratorSystem
|
||||
|
||||
private void InitializeControlBoxSystem()
|
||||
{
|
||||
SubscribeLocalEvent<ParticleAcceleratorControlBoxComponent, ComponentStartup>(OnComponentStartup);
|
||||
SubscribeLocalEvent<ParticleAcceleratorControlBoxComponent, ComponentShutdown>(OnComponentShutdown);
|
||||
SubscribeLocalEvent<ParticleAcceleratorControlBoxComponent, PowerChangedEvent>(OnControlBoxPowerChange);
|
||||
SubscribeLocalEvent<ParticleAcceleratorControlBoxComponent, ParticleAcceleratorSetEnableMessage>(OnUISetEnableMessage);
|
||||
SubscribeLocalEvent<ParticleAcceleratorControlBoxComponent, ParticleAcceleratorSetPowerStateMessage>(OnUISetPowerMessage);
|
||||
SubscribeLocalEvent<ParticleAcceleratorControlBoxComponent, ParticleAcceleratorRescanPartsMessage>(OnUIRescanMessage);
|
||||
SubscribeLocalEvent<ParticleAcceleratorControlBoxComponent, MultipartMachineAssemblyStateChanged>(OnMachineAssembledChanged);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
@@ -40,14 +42,12 @@ public sealed partial class ParticleAcceleratorSystem
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
private void EverythingIsWellToFire(ParticleAcceleratorControlBoxComponent controller)
|
||||
private void EverythingIsWellToFire(ParticleAcceleratorControlBoxComponent controller,
|
||||
Entity<MultipartMachineComponent> machine)
|
||||
{
|
||||
DebugTools.Assert(controller.Powered);
|
||||
DebugTools.Assert(controller.SelectedStrength != ParticleAcceleratorPowerState.Standby);
|
||||
DebugTools.Assert(controller.Assembled);
|
||||
DebugTools.Assert(EntityManager.EntityExists(controller.PortEmitter));
|
||||
DebugTools.Assert(EntityManager.EntityExists(controller.ForeEmitter));
|
||||
DebugTools.Assert(EntityManager.EntityExists(controller.StarboardEmitter));
|
||||
DebugTools.Assert(machine.Comp.IsAssembled);
|
||||
}
|
||||
|
||||
public void Fire(EntityUid uid, TimeSpan curTime, ParticleAcceleratorControlBoxComponent? comp = null)
|
||||
@@ -58,12 +58,17 @@ public sealed partial class ParticleAcceleratorSystem
|
||||
comp.LastFire = curTime;
|
||||
comp.NextFire = curTime + comp.ChargeTime;
|
||||
|
||||
EverythingIsWellToFire(comp);
|
||||
if (!TryComp<MultipartMachineComponent>(uid, out var machineComp))
|
||||
return;
|
||||
|
||||
var machine = (uid, machineComp);
|
||||
EverythingIsWellToFire(comp, machine);
|
||||
|
||||
var strength = comp.SelectedStrength;
|
||||
FireEmitter(comp.PortEmitter!.Value, strength);
|
||||
FireEmitter(comp.ForeEmitter!.Value, strength);
|
||||
FireEmitter(comp.StarboardEmitter!.Value, strength);
|
||||
|
||||
FireEmitter(_multipartMachine.GetPartEntity(machine, AcceleratorParts.PortEmitter)!.Value, strength);
|
||||
FireEmitter(_multipartMachine.GetPartEntity(machine, AcceleratorParts.ForeEmitter)!.Value, strength);
|
||||
FireEmitter(_multipartMachine.GetPartEntity(machine, AcceleratorParts.StarboardEmitter)!.Value, strength);
|
||||
}
|
||||
|
||||
public void SwitchOn(EntityUid uid, EntityUid? user = null, ParticleAcceleratorControlBoxComponent? comp = null)
|
||||
@@ -71,7 +76,7 @@ public sealed partial class ParticleAcceleratorSystem
|
||||
if (!Resolve(uid, ref comp))
|
||||
return;
|
||||
|
||||
DebugTools.Assert(comp.Assembled);
|
||||
DebugTools.Assert(_multipartMachine.IsAssembled((uid, null)));
|
||||
|
||||
if (comp.Enabled || !comp.CanBeEnabled)
|
||||
return;
|
||||
@@ -82,9 +87,11 @@ public sealed partial class ParticleAcceleratorSystem
|
||||
comp.Enabled = true;
|
||||
UpdatePowerDraw(uid, comp);
|
||||
|
||||
if (!TryComp<PowerConsumerComponent>(comp.PowerBox, out var powerConsumer)
|
||||
|| powerConsumer.ReceivedPower >= powerConsumer.DrawRate * ParticleAcceleratorControlBoxComponent.RequiredPowerRatio)
|
||||
if (!TryComp<PowerConsumerComponent>(_multipartMachine.GetPartEntity(uid, AcceleratorParts.PowerBox), out var powerConsumer)
|
||||
|| powerConsumer.ReceivedPower >= powerConsumer.DrawRate * ParticleAcceleratorControlBoxComponent.RequiredPowerRatio)
|
||||
{
|
||||
PowerOn(uid, comp);
|
||||
}
|
||||
|
||||
UpdateUI(uid, comp);
|
||||
}
|
||||
@@ -112,7 +119,7 @@ public sealed partial class ParticleAcceleratorSystem
|
||||
return;
|
||||
|
||||
DebugTools.Assert(comp.Enabled);
|
||||
DebugTools.Assert(comp.Assembled);
|
||||
DebugTools.Assert(_multipartMachine.IsAssembled((uid, null)));
|
||||
|
||||
if (comp.Powered)
|
||||
return;
|
||||
@@ -211,7 +218,10 @@ public sealed partial class ParticleAcceleratorSystem
|
||||
return;
|
||||
}
|
||||
|
||||
EverythingIsWellToFire(comp);
|
||||
if (!TryComp<MultipartMachineComponent>(uid, out var machine))
|
||||
return;
|
||||
|
||||
EverythingIsWellToFire(comp, (uid, machine));
|
||||
|
||||
var curTime = _gameTiming.CurTime;
|
||||
comp.LastFire = curTime;
|
||||
@@ -223,7 +233,8 @@ public sealed partial class ParticleAcceleratorSystem
|
||||
{
|
||||
if (!Resolve(uid, ref comp))
|
||||
return;
|
||||
if (!TryComp<PowerConsumerComponent>(comp.PowerBox, out var powerConsumer))
|
||||
|
||||
if (!TryComp<PowerConsumerComponent>(_multipartMachine.GetPartEntity(uid, AcceleratorParts.PowerBox), out var powerConsumer))
|
||||
return;
|
||||
|
||||
var powerDraw = comp.BasePowerDraw;
|
||||
@@ -244,30 +255,35 @@ public sealed partial class ParticleAcceleratorSystem
|
||||
var draw = 0f;
|
||||
var receive = 0f;
|
||||
|
||||
if (TryComp<PowerConsumerComponent>(comp.PowerBox, out var powerConsumer))
|
||||
if (TryComp<PowerConsumerComponent>(_multipartMachine.GetPartEntity(uid, AcceleratorParts.PowerBox), out var powerConsumer))
|
||||
{
|
||||
draw = powerConsumer.DrawRate;
|
||||
receive = powerConsumer.ReceivedPower;
|
||||
}
|
||||
|
||||
_uiSystem.SetUiState(uid,
|
||||
ParticleAcceleratorControlBoxUiKey.Key,
|
||||
new ParticleAcceleratorUIState(
|
||||
comp.Assembled,
|
||||
if (!TryComp<MultipartMachineComponent>(uid, out var machineComp))
|
||||
return;
|
||||
|
||||
var machine = (uid, machineComp);
|
||||
|
||||
var uiState = new ParticleAcceleratorUIState(
|
||||
machineComp.IsAssembled,
|
||||
comp.Enabled,
|
||||
comp.SelectedStrength,
|
||||
(int) draw,
|
||||
(int) receive,
|
||||
comp.StarboardEmitter != null,
|
||||
comp.ForeEmitter != null,
|
||||
comp.PortEmitter != null,
|
||||
comp.PowerBox != null,
|
||||
comp.FuelChamber != null,
|
||||
comp.EndCap != null,
|
||||
(int)draw,
|
||||
(int)receive,
|
||||
_multipartMachine.HasPart(machine, AcceleratorParts.StarboardEmitter),
|
||||
_multipartMachine.HasPart(machine, AcceleratorParts.ForeEmitter),
|
||||
_multipartMachine.HasPart(machine, AcceleratorParts.PortEmitter),
|
||||
_multipartMachine.HasPart(machine, AcceleratorParts.PowerBox),
|
||||
_multipartMachine.HasPart(machine, AcceleratorParts.FuelChamber),
|
||||
_multipartMachine.HasPart(machine, AcceleratorParts.EndCap),
|
||||
comp.InterfaceDisabled,
|
||||
comp.MaxStrength,
|
||||
comp.StrengthLocked
|
||||
));
|
||||
);
|
||||
|
||||
_uiSystem.SetUiState(uid, ParticleAcceleratorControlBoxUiKey.Key, uiState);
|
||||
}
|
||||
|
||||
private void UpdateAppearance(EntityUid uid, ParticleAcceleratorControlBoxComponent? comp = null, AppearanceComponent? appearance = null)
|
||||
@@ -292,55 +308,58 @@ public sealed partial class ParticleAcceleratorSystem
|
||||
|
||||
var state = controller.Powered ? (ParticleAcceleratorVisualState) controller.SelectedStrength : ParticleAcceleratorVisualState.Unpowered;
|
||||
|
||||
if (!TryComp<MultipartMachineComponent>(uid, out var machineComp))
|
||||
return;
|
||||
|
||||
var machine = (uid, machineComp);
|
||||
|
||||
// UpdatePartVisualState(ControlBox); (We are the control box)
|
||||
if (controller.FuelChamber.HasValue)
|
||||
_appearanceSystem.SetData(controller.FuelChamber!.Value, ParticleAcceleratorVisuals.VisualState, state);
|
||||
if (controller.PowerBox.HasValue)
|
||||
_appearanceSystem.SetData(controller.PowerBox!.Value, ParticleAcceleratorVisuals.VisualState, state);
|
||||
if (controller.PortEmitter.HasValue)
|
||||
_appearanceSystem.SetData(controller.PortEmitter!.Value, ParticleAcceleratorVisuals.VisualState, state);
|
||||
if (controller.ForeEmitter.HasValue)
|
||||
_appearanceSystem.SetData(controller.ForeEmitter!.Value, ParticleAcceleratorVisuals.VisualState, state);
|
||||
if (controller.StarboardEmitter.HasValue)
|
||||
_appearanceSystem.SetData(controller.StarboardEmitter!.Value, ParticleAcceleratorVisuals.VisualState, state);
|
||||
if (_multipartMachine.TryGetPartEntity(machine, AcceleratorParts.FuelChamber, out var fuelChamber))
|
||||
_appearanceSystem.SetData(fuelChamber.Value, ParticleAcceleratorVisuals.VisualState, state);
|
||||
if (_multipartMachine.TryGetPartEntity(machine, AcceleratorParts.PowerBox, out var powerBox))
|
||||
_appearanceSystem.SetData(powerBox.Value, ParticleAcceleratorVisuals.VisualState, state);
|
||||
if (_multipartMachine.TryGetPartEntity(machine, AcceleratorParts.PortEmitter, out var portEmitter))
|
||||
_appearanceSystem.SetData(portEmitter.Value, ParticleAcceleratorVisuals.VisualState, state);
|
||||
if (_multipartMachine.TryGetPartEntity(machine, AcceleratorParts.ForeEmitter, out var foreEmitter))
|
||||
_appearanceSystem.SetData(foreEmitter.Value, ParticleAcceleratorVisuals.VisualState, state);
|
||||
if (_multipartMachine.TryGetPartEntity(machine, AcceleratorParts.StarboardEmitter, out var starboardEmitter))
|
||||
_appearanceSystem.SetData(starboardEmitter.Value, ParticleAcceleratorVisuals.VisualState, state);
|
||||
//no endcap because it has no powerlevel-sprites
|
||||
}
|
||||
|
||||
private IEnumerable<EntityUid> AllParts(EntityUid uid, ParticleAcceleratorControlBoxComponent? comp = null)
|
||||
/// <summary>
|
||||
/// Handles when a multipart machine has had some assembled/disassembled state change, or had parts added/removed.
|
||||
/// </summary>
|
||||
/// <param name="ent">Multipart machine entity</param>
|
||||
/// <param name="args">Args for this event</param>
|
||||
private void OnMachineAssembledChanged(Entity<ParticleAcceleratorControlBoxComponent> ent, ref MultipartMachineAssemblyStateChanged args)
|
||||
{
|
||||
if (Resolve(uid, ref comp))
|
||||
if (args.IsAssembled)
|
||||
{
|
||||
if (comp.FuelChamber.HasValue)
|
||||
yield return comp.FuelChamber.Value;
|
||||
if (comp.EndCap.HasValue)
|
||||
yield return comp.EndCap.Value;
|
||||
if (comp.PowerBox.HasValue)
|
||||
yield return comp.PowerBox.Value;
|
||||
if (comp.PortEmitter.HasValue)
|
||||
yield return comp.PortEmitter.Value;
|
||||
if (comp.ForeEmitter.HasValue)
|
||||
yield return comp.ForeEmitter.Value;
|
||||
if (comp.StarboardEmitter.HasValue)
|
||||
yield return comp.StarboardEmitter.Value;
|
||||
UpdatePowerDraw(ent, ent.Comp);
|
||||
UpdateUI(ent, ent.Comp);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnComponentStartup(EntityUid uid, ParticleAcceleratorControlBoxComponent comp, ComponentStartup args)
|
||||
{
|
||||
if (TryComp<ParticleAcceleratorPartComponent>(uid, out var part))
|
||||
part.Master = uid;
|
||||
}
|
||||
|
||||
private void OnComponentShutdown(EntityUid uid, ParticleAcceleratorControlBoxComponent comp, ComponentShutdown args)
|
||||
{
|
||||
if (TryComp<ParticleAcceleratorPartComponent>(uid, out var partStatus))
|
||||
partStatus.Master = null;
|
||||
|
||||
var partQuery = GetEntityQuery<ParticleAcceleratorPartComponent>();
|
||||
foreach (var part in AllParts(uid, comp))
|
||||
else
|
||||
{
|
||||
if (partQuery.TryGetComponent(part, out var partData))
|
||||
partData.Master = null;
|
||||
if (ent.Comp.Powered)
|
||||
{
|
||||
SwitchOff(ent, args.User, ent.Comp);
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateAppearance(ent, ent.Comp);
|
||||
UpdateUI(ent, ent.Comp);
|
||||
}
|
||||
|
||||
// Because the parts are already removed from the multipart machine, updating the visual appearance won't find any valid entities.
|
||||
// We know which parts have been removed so we can update the visual state to unpowered in a more manual way here.
|
||||
foreach (var (key, part) in args.PartsRemoved)
|
||||
{
|
||||
if (key is AcceleratorParts.EndCap)
|
||||
continue; // No endcap powerlevel-sprites
|
||||
|
||||
_appearanceSystem.SetData(part, ParticleAcceleratorVisuals.VisualState, ParticleAcceleratorVisualState.Unpowered);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,7 +384,7 @@ public sealed partial class ParticleAcceleratorSystem
|
||||
|
||||
if (msg.Enabled)
|
||||
{
|
||||
if (comp.Assembled)
|
||||
if (_multipartMachine.IsAssembled((uid, null)))
|
||||
SwitchOn(uid, msg.Actor, comp);
|
||||
}
|
||||
else
|
||||
@@ -397,9 +416,13 @@ public sealed partial class ParticleAcceleratorSystem
|
||||
if (TryComp<ApcPowerReceiverComponent>(uid, out var apcPower) && !apcPower.Powered)
|
||||
return;
|
||||
|
||||
RescanParts(uid, msg.Actor, comp);
|
||||
if (!TryComp<MultipartMachineComponent>(uid, out var machineComp))
|
||||
return;
|
||||
|
||||
UpdateUI(uid, comp);
|
||||
// User has requested a manual rescan of the machine, if anything HAS changed that the multipart
|
||||
// machine system has missed then a AssemblyStateChanged event will be raised at the machine.
|
||||
var machine = new Entity<MultipartMachineComponent>(uid, machineComp);
|
||||
_multipartMachine.Rescan(machine, msg.Actor);
|
||||
}
|
||||
|
||||
public static int GetPANumericalLevel(ParticleAcceleratorPowerState state)
|
||||
|
||||
Reference in New Issue
Block a user