Converts the particle accelerator over to ECS + misc (#17075)
Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com>
@@ -1,6 +1,5 @@
|
|||||||
using Content.Shared.Singularity.Components;
|
using Content.Shared.Singularity.Components;
|
||||||
using Robust.Client.GameObjects;
|
using Robust.Client.GameObjects;
|
||||||
using Robust.Shared.GameObjects;
|
|
||||||
|
|
||||||
namespace Content.Client.ParticleAccelerator.UI
|
namespace Content.Client.ParticleAccelerator.UI
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ namespace Content.Client.ParticleAccelerator.UI
|
|||||||
{
|
{
|
||||||
private readonly ShaderInstance _greyScaleShader;
|
private readonly ShaderInstance _greyScaleShader;
|
||||||
|
|
||||||
private readonly ParticleAcceleratorBoundUserInterface Owner;
|
private readonly ParticleAcceleratorBoundUserInterface _owner;
|
||||||
|
|
||||||
private readonly Label _drawLabel;
|
private readonly Label _drawLabel;
|
||||||
private readonly NoiseGenerator _drawNoiseGenerator;
|
private readonly FastNoiseLite _drawNoiseGenerator;
|
||||||
private readonly Button _onButton;
|
private readonly Button _onButton;
|
||||||
private readonly Button _offButton;
|
private readonly Button _offButton;
|
||||||
private readonly Button _scanButton;
|
private readonly Button _scanButton;
|
||||||
@@ -36,9 +36,9 @@ namespace Content.Client.ParticleAccelerator.UI
|
|||||||
private readonly PASegmentControl _fuelChamberTexture;
|
private readonly PASegmentControl _fuelChamberTexture;
|
||||||
private readonly PASegmentControl _controlBoxTexture;
|
private readonly PASegmentControl _controlBoxTexture;
|
||||||
private readonly PASegmentControl _powerBoxTexture;
|
private readonly PASegmentControl _powerBoxTexture;
|
||||||
private readonly PASegmentControl _emitterCenterTexture;
|
private readonly PASegmentControl _emitterForeTexture;
|
||||||
private readonly PASegmentControl _emitterRightTexture;
|
private readonly PASegmentControl _emitterPortTexture;
|
||||||
private readonly PASegmentControl _emitterLeftTexture;
|
private readonly PASegmentControl _emitterStarboardTexture;
|
||||||
|
|
||||||
private float _time;
|
private float _time;
|
||||||
private int _lastDraw;
|
private int _lastDraw;
|
||||||
@@ -47,14 +47,16 @@ namespace Content.Client.ParticleAccelerator.UI
|
|||||||
private bool _blockSpinBox;
|
private bool _blockSpinBox;
|
||||||
private bool _assembled;
|
private bool _assembled;
|
||||||
private bool _shouldContinueAnimating;
|
private bool _shouldContinueAnimating;
|
||||||
|
private int _maxStrength = 3;
|
||||||
|
|
||||||
public ParticleAcceleratorControlMenu(ParticleAcceleratorBoundUserInterface owner)
|
public ParticleAcceleratorControlMenu(ParticleAcceleratorBoundUserInterface owner)
|
||||||
{
|
{
|
||||||
SetSize = (400, 320);
|
SetSize = (400, 320);
|
||||||
_greyScaleShader = IoCManager.Resolve<IPrototypeManager>().Index<ShaderPrototype>("Greyscale").Instance();
|
_greyScaleShader = IoCManager.Resolve<IPrototypeManager>().Index<ShaderPrototype>("Greyscale").Instance();
|
||||||
|
|
||||||
Owner = owner;
|
_owner = owner;
|
||||||
_drawNoiseGenerator = new NoiseGenerator(NoiseGenerator.NoiseType.Fbm);
|
_drawNoiseGenerator = new();
|
||||||
|
_drawNoiseGenerator.SetFractalType(FastNoiseLite.FractalType.FBm);
|
||||||
_drawNoiseGenerator.SetFrequency(0.5f);
|
_drawNoiseGenerator.SetFrequency(0.5f);
|
||||||
|
|
||||||
var resourceCache = IoCManager.Resolve<IResourceCache>();
|
var resourceCache = IoCManager.Resolve<IResourceCache>();
|
||||||
@@ -98,7 +100,7 @@ namespace Content.Client.ParticleAccelerator.UI
|
|||||||
MouseFilter = MouseFilterMode.Pass
|
MouseFilter = MouseFilterMode.Pass
|
||||||
});
|
});
|
||||||
|
|
||||||
_stateSpinBox = new SpinBox {Value = 0, IsValid = StrengthSpinBoxValid,};
|
_stateSpinBox = new SpinBox { Value = 0, IsValid = StrengthSpinBoxValid };
|
||||||
_stateSpinBox.InitDefaultButtons();
|
_stateSpinBox.InitDefaultButtons();
|
||||||
_stateSpinBox.ValueChanged += PowerStateChanged;
|
_stateSpinBox.ValueChanged += PowerStateChanged;
|
||||||
_stateSpinBox.LineEditDisabled = true;
|
_stateSpinBox.LineEditDisabled = true;
|
||||||
@@ -227,7 +229,8 @@ namespace Content.Client.ParticleAccelerator.UI
|
|||||||
Align = Label.AlignMode.Center
|
Align = Label.AlignMode.Center
|
||||||
},
|
},
|
||||||
serviceManual
|
serviceManual
|
||||||
}
|
},
|
||||||
|
Visible = false,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -267,9 +270,9 @@ namespace Content.Client.ParticleAccelerator.UI
|
|||||||
new Control {MinSize = imgSize},
|
new Control {MinSize = imgSize},
|
||||||
(_powerBoxTexture = Segment("power_box")),
|
(_powerBoxTexture = Segment("power_box")),
|
||||||
new Control {MinSize = imgSize},
|
new Control {MinSize = imgSize},
|
||||||
(_emitterLeftTexture = Segment("emitter_left")),
|
(_emitterStarboardTexture = Segment("emitter_starboard")),
|
||||||
(_emitterCenterTexture = Segment("emitter_center")),
|
(_emitterForeTexture = Segment("emitter_fore")),
|
||||||
(_emitterRightTexture = Segment("emitter_right")),
|
(_emitterPortTexture = Segment("emitter_port")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -312,7 +315,7 @@ namespace Content.Client.ParticleAccelerator.UI
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
_scanButton.OnPressed += args => Owner.SendScanPartsMessage();
|
_scanButton.OnPressed += args => _owner.SendScanPartsMessage();
|
||||||
|
|
||||||
_alarmControl.AnimationCompleted += s =>
|
_alarmControl.AnimationCompleted += s =>
|
||||||
{
|
{
|
||||||
@@ -336,7 +339,7 @@ namespace Content.Client.ParticleAccelerator.UI
|
|||||||
|
|
||||||
private bool StrengthSpinBoxValid(int n)
|
private bool StrengthSpinBoxValid(int n)
|
||||||
{
|
{
|
||||||
return (n >= 0 && n <= 3 && !_blockSpinBox);
|
return n >= 0 && n <= _maxStrength && !_blockSpinBox;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PowerStateChanged(ValueChangedEventArgs e)
|
private void PowerStateChanged(ValueChangedEventArgs e)
|
||||||
@@ -356,16 +359,15 @@ namespace Content.Client.ParticleAccelerator.UI
|
|||||||
case 3:
|
case 3:
|
||||||
newState = ParticleAcceleratorPowerState.Level2;
|
newState = ParticleAcceleratorPowerState.Level2;
|
||||||
break;
|
break;
|
||||||
// They can't reach this level anyway and I just want to fix the bugginess for now.
|
case 4:
|
||||||
//case 4:
|
newState = ParticleAcceleratorPowerState.Level3;
|
||||||
// newState = ParticleAcceleratorPowerState.Level3;
|
break;
|
||||||
// break;
|
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_stateSpinBox.SetButtonDisabled(true);
|
_stateSpinBox.SetButtonDisabled(true);
|
||||||
Owner.SendPowerStateMessage(newState);
|
_owner.SendPowerStateMessage(newState);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override DragMode GetDragModeFor(Vector2 relativeMousePos)
|
protected override DragMode GetDragModeFor(Vector2 relativeMousePos)
|
||||||
@@ -402,14 +404,15 @@ namespace Content.Client.ParticleAccelerator.UI
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
_shouldContinueAnimating = false;
|
_maxStrength = maxState == ParticleAcceleratorPowerState.Level3 ? 4 : 3;
|
||||||
_alarmControl.StopAnimation("warningAnim");
|
if (_maxStrength > 3 && enabled && assembled)
|
||||||
_alarmControl.Visible = false;
|
|
||||||
if (maxState == ParticleAcceleratorPowerState.Level3 && enabled && assembled)
|
|
||||||
{
|
{
|
||||||
_shouldContinueAnimating = true;
|
_shouldContinueAnimating = true;
|
||||||
|
if (!_alarmControl.Visible)
|
||||||
_alarmControl.PlayAnimation(_alarmControlAnimation, "warningAnim");
|
_alarmControl.PlayAnimation(_alarmControlAnimation, "warningAnim");
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
_shouldContinueAnimating = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateUI(bool assembled, bool blocked, bool enabled, bool powerBlock)
|
private void UpdateUI(bool assembled, bool blocked, bool enabled, bool powerBlock)
|
||||||
@@ -430,12 +433,12 @@ namespace Content.Client.ParticleAccelerator.UI
|
|||||||
private void UpdatePreview(ParticleAcceleratorUIState updateMessage)
|
private void UpdatePreview(ParticleAcceleratorUIState updateMessage)
|
||||||
{
|
{
|
||||||
_endCapTexture.SetPowerState(updateMessage, updateMessage.EndCapExists);
|
_endCapTexture.SetPowerState(updateMessage, updateMessage.EndCapExists);
|
||||||
_fuelChamberTexture.SetPowerState(updateMessage, updateMessage.FuelChamberExists);
|
|
||||||
_controlBoxTexture.SetPowerState(updateMessage, true);
|
_controlBoxTexture.SetPowerState(updateMessage, true);
|
||||||
|
_fuelChamberTexture.SetPowerState(updateMessage, updateMessage.FuelChamberExists);
|
||||||
_powerBoxTexture.SetPowerState(updateMessage, updateMessage.PowerBoxExists);
|
_powerBoxTexture.SetPowerState(updateMessage, updateMessage.PowerBoxExists);
|
||||||
_emitterCenterTexture.SetPowerState(updateMessage, updateMessage.EmitterCenterExists);
|
_emitterStarboardTexture.SetPowerState(updateMessage, updateMessage.EmitterStarboardExists);
|
||||||
_emitterLeftTexture.SetPowerState(updateMessage, updateMessage.EmitterLeftExists);
|
_emitterForeTexture.SetPowerState(updateMessage, updateMessage.EmitterForeExists);
|
||||||
_emitterRightTexture.SetPowerState(updateMessage, updateMessage.EmitterRightExists);
|
_emitterPortTexture.SetPowerState(updateMessage, updateMessage.EmitterPortExists);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void FrameUpdate(FrameEventArgs args)
|
protected override void FrameUpdate(FrameEventArgs args)
|
||||||
@@ -453,7 +456,7 @@ namespace Content.Client.ParticleAccelerator.UI
|
|||||||
var watts = 0;
|
var watts = 0;
|
||||||
if (_lastDraw != 0)
|
if (_lastDraw != 0)
|
||||||
{
|
{
|
||||||
var val = _drawNoiseGenerator.GetNoise(_time);
|
var val = _drawNoiseGenerator.GetNoise(_time, 0f);
|
||||||
watts = (int) (_lastDraw + val * 5);
|
watts = (int) (_lastDraw + val * 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ public sealed class MachineBoardTest
|
|||||||
"MachineParticleAcceleratorFuelChamberCircuitboard",
|
"MachineParticleAcceleratorFuelChamberCircuitboard",
|
||||||
"MachineParticleAcceleratorFuelChamberCircuitboard",
|
"MachineParticleAcceleratorFuelChamberCircuitboard",
|
||||||
"MachineParticleAcceleratorPowerBoxCircuitboard",
|
"MachineParticleAcceleratorPowerBoxCircuitboard",
|
||||||
"MachineParticleAcceleratorEmitterLeftCircuitboard",
|
"MachineParticleAcceleratorEmitterStarboardCircuitboard",
|
||||||
"MachineParticleAcceleratorEmitterCenterCircuitboard",
|
"MachineParticleAcceleratorEmitterForeCircuitboard",
|
||||||
"MachineParticleAcceleratorEmitterRightCircuitboard",
|
"MachineParticleAcceleratorEmitterPortCircuitboard",
|
||||||
"ParticleAcceleratorComputerCircuitboard"
|
"ParticleAcceleratorComputerCircuitboard"
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -46,6 +46,8 @@ public sealed class MachineBoardTest
|
|||||||
continue;
|
continue;
|
||||||
var mId = mbc.Prototype;
|
var mId = mbc.Prototype;
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
Assert.That(mId, Is.Not.Null, $"Machine board {p.ID} does not have a corresponding machine.");
|
Assert.That(mId, Is.Not.Null, $"Machine board {p.ID} does not have a corresponding machine.");
|
||||||
Assert.That(protoMan.TryIndex<EntityPrototype>(mId, out var mProto),
|
Assert.That(protoMan.TryIndex<EntityPrototype>(mId, out var mProto),
|
||||||
$"Machine board {p.ID}'s corresponding machine has an invalid prototype.");
|
$"Machine board {p.ID}'s corresponding machine has an invalid prototype.");
|
||||||
@@ -53,6 +55,7 @@ public sealed class MachineBoardTest
|
|||||||
$"Machine board {p.ID}'s corresponding machine {mId} does not have MachineComponent");
|
$"Machine board {p.ID}'s corresponding machine {mId} does not have MachineComponent");
|
||||||
Assert.That(mComp.BoardPrototype, Is.EqualTo(p.ID),
|
Assert.That(mComp.BoardPrototype, Is.EqualTo(p.ID),
|
||||||
$"Machine {mId}'s BoardPrototype is not equal to it's corresponding machine board, {p.ID}");
|
$"Machine {mId}'s BoardPrototype is not equal to it's corresponding machine board, {p.ID}");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -79,6 +82,8 @@ public sealed class MachineBoardTest
|
|||||||
continue;
|
continue;
|
||||||
var cId = cbc.Prototype;
|
var cId = cbc.Prototype;
|
||||||
|
|
||||||
|
Assert.Multiple(() =>
|
||||||
|
{
|
||||||
Assert.That(cId, Is.Not.Null, $"Computer board \"{p.ID}\" does not have a corresponding computer.");
|
Assert.That(cId, Is.Not.Null, $"Computer board \"{p.ID}\" does not have a corresponding computer.");
|
||||||
Assert.That(protoMan.TryIndex<EntityPrototype>(cId, out var cProto),
|
Assert.That(protoMan.TryIndex<EntityPrototype>(cId, out var cProto),
|
||||||
$"Computer board \"{p.ID}\"'s corresponding computer has an invalid prototype.");
|
$"Computer board \"{p.ID}\"'s corresponding computer has an invalid prototype.");
|
||||||
@@ -86,6 +91,7 @@ public sealed class MachineBoardTest
|
|||||||
$"Computer board {p.ID}'s corresponding computer \"{cId}\" does not have ComputerComponent");
|
$"Computer board {p.ID}'s corresponding computer \"{cId}\" does not have ComputerComponent");
|
||||||
Assert.That(cComp.BoardPrototype, Is.EqualTo(p.ID),
|
Assert.That(cComp.BoardPrototype, Is.EqualTo(p.ID),
|
||||||
$"Computer \"{cId}\"'s BoardPrototype is not equal to it's corresponding computer board, \"{p.ID}\"");
|
$"Computer \"{cId}\"'s BoardPrototype is not equal to it's corresponding computer board, \"{p.ID}\"");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,8 @@
|
|||||||
using System.Diagnostics;
|
using Content.Server.ParticleAccelerator.Wires;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using System.Threading;
|
|
||||||
using Content.Server.Administration.Logs;
|
|
||||||
using Content.Server.Mind.Components;
|
|
||||||
using Content.Server.Power.Components;
|
|
||||||
using Content.Server.Power.EntitySystems;
|
|
||||||
using Content.Server.UserInterface;
|
|
||||||
using Content.Shared.Database;
|
|
||||||
using Content.Shared.Singularity.Components;
|
using Content.Shared.Singularity.Components;
|
||||||
using Robust.Server.GameObjects;
|
|
||||||
using Robust.Server.Player;
|
|
||||||
using Robust.Shared.Map;
|
|
||||||
using Robust.Shared.Map.Components;
|
|
||||||
using Robust.Shared.Utility;
|
|
||||||
using Timer = Robust.Shared.Timing.Timer;
|
|
||||||
// using Content.Server.WireHacking;
|
|
||||||
// using static Content.Shared.Wires.SharedWiresComponent;
|
|
||||||
|
|
||||||
namespace Content.Server.ParticleAccelerator.Components
|
namespace Content.Server.ParticleAccelerator.Components;
|
||||||
{
|
|
||||||
// This component is in control of the PA's logic because it's the one to contain the wires for hacking.
|
// This component is in control of the PA's logic because it's the one to contain the wires for hacking.
|
||||||
// And also it's the only PA component that meaningfully needs to work on its own.
|
// And also it's the only PA component that meaningfully needs to work on its own.
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -26,40 +10,125 @@ namespace Content.Server.ParticleAccelerator.Components
|
|||||||
/// Also contains primary logic for actual PA behavior, part scanning, etc...
|
/// Also contains primary logic for actual PA behavior, part scanning, etc...
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public sealed class ParticleAcceleratorControlBoxComponent : ParticleAcceleratorPartComponent
|
public sealed class ParticleAcceleratorControlBoxComponent : Component
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IEntityManager _entMan = default!;
|
/// <summary>
|
||||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
/// Whether the PA parts have been correctly arranged to make a functional device.
|
||||||
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
/// </summary>
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
private BoundUserInterface? UserInterface => Owner.GetUIOrNull(ParticleAcceleratorControlBoxUiKey.Key);
|
public bool Assembled = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Power receiver for the control console itself.
|
/// Whether the PA is currently set to fire at the console.
|
||||||
|
/// Requires <see cref="Assembled"/> to be true.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[ViewVariables] private ApcPowerReceiverComponent _apcPowerReceiverComponent = default!;
|
[ViewVariables]
|
||||||
|
public bool Enabled = false;
|
||||||
|
|
||||||
[ViewVariables] private ParticleAcceleratorFuelChamberComponent? _partFuelChamber;
|
/// <summary>
|
||||||
[ViewVariables] private ParticleAcceleratorEndCapComponent? _partEndCap;
|
/// Whether the PA actually has the power necessary to fire.
|
||||||
[ViewVariables] private ParticleAcceleratorPowerBoxComponent? _partPowerBox;
|
/// Requires <see cref="Enabled"/> to be true.
|
||||||
[ViewVariables] private ParticleAcceleratorEmitterComponent? _partEmitterLeft;
|
/// </summary>
|
||||||
[ViewVariables] private ParticleAcceleratorEmitterComponent? _partEmitterCenter;
|
[ViewVariables]
|
||||||
[ViewVariables] private ParticleAcceleratorEmitterComponent? _partEmitterRight;
|
public bool Powered = false;
|
||||||
[ViewVariables] private ParticleAcceleratorPowerState _selectedStrength = ParticleAcceleratorPowerState.Standby;
|
|
||||||
|
|
||||||
[ViewVariables] private bool _isAssembled;
|
/// <summary>
|
||||||
|
/// Whether the PA is currently firing or charging to fire.
|
||||||
|
/// Requires <see cref="Powered"/> to be true.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables]
|
||||||
|
public bool Firing = false;
|
||||||
|
|
||||||
// Enabled: power switch is on
|
/// <summary>
|
||||||
[ViewVariables] private bool _isEnabled;
|
/// Whether the PA is currently firing or charging to fire.
|
||||||
|
/// Bounded by <see cref="ParticleAcceleratorPowerState.Standby"/> and <see cref="MaxStrength"/>.
|
||||||
|
/// Modified by <see cref="ParticleAcceleratorStrengthWireAction"/>.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public ParticleAcceleratorPowerState SelectedStrength = ParticleAcceleratorPowerState.Standby;
|
||||||
|
|
||||||
// Powered: power switch is on AND the PA is actively firing (if not on standby)
|
/// <summary>
|
||||||
[ViewVariables] private bool _isPowered;
|
/// The maximum strength level this particle accelerator can be set to operate at.
|
||||||
[ViewVariables] private bool _wireInterfaceBlocked;
|
/// Modified by <see cref="ParticleAcceleratorLimiterWireAction"/>.
|
||||||
[ViewVariables] private bool _wirePowerBlocked;
|
/// </summary>
|
||||||
[ViewVariables] private bool _wireLimiterCut;
|
[ViewVariables]
|
||||||
[ViewVariables] private bool _wireStrengthCut;
|
public ParticleAcceleratorPowerState MaxStrength = ParticleAcceleratorPowerState.Level2;
|
||||||
[ViewVariables] private CancellationTokenSource? _fireCancelTokenSrc;
|
|
||||||
|
/// <summary>
|
||||||
|
/// The power supply unit of the assembled particle accelerator.
|
||||||
|
/// Implies the existance of a <see cref="ParticleAcceleratorPowerBoxComponent"/> attached to this entity.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables]
|
||||||
|
public EntityUid? PowerBox;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the PA is currently firing or charging to fire.
|
||||||
|
/// Implies the existance of a <see cref="ParticleAcceleratorEndCapComponent"/> attached to this entity.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables]
|
||||||
|
public EntityUid? EndCap;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the PA is currently firing or charging to fire.
|
||||||
|
/// Implies the existance of a <see cref="ParticleAcceleratorFuelChamberComponent"/> attached to this entity.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables]
|
||||||
|
public EntityUid? FuelChamber;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the PA is currently firing or charging to fire.
|
||||||
|
/// Implies the existance of a <see cref="ParticleAcceleratorEmitterComponent"/> attached to this entity.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables]
|
||||||
|
public EntityUid? PortEmitter;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the PA is currently firing or charging to fire.
|
||||||
|
/// Implies the existance of a <see cref="ParticleAcceleratorEmitterComponent"/> attached to this entity.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables]
|
||||||
|
public EntityUid? ForeEmitter;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the PA is currently firing or charging to fire.
|
||||||
|
/// Implies the existance of a <see cref="ParticleAcceleratorEmitterComponent"/> attached to this entity.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables]
|
||||||
|
public EntityUid? StarboardEmitter;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The amount of power the particle accelerator must be provided with relative to the expected power draw to function.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables]
|
||||||
|
public const float RequiredPowerRatio = 0.999f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The amount of power (in watts) the PA draws just by existing as a functional machine.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("powerDrawBase")]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public int BasePowerDraw = 500;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The amount of power (in watts) the PA draws per level when turned on.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("powerDrawMult")]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public int LevelPowerDraw = 1500;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The time at which the PA last fired a wave of particles.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("lastFire")]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public TimeSpan LastFire;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The time at which the PA will next fire a wave of particles.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("nextFire")]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public TimeSpan NextFire;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delay between consecutive PA shots.
|
/// Delay between consecutive PA shots.
|
||||||
@@ -74,642 +143,28 @@ namespace Content.Server.ParticleAccelerator.Components
|
|||||||
// So the *actual* effective firing delay of the PA is 6 seconds, not 5 as listed in the code.
|
// So the *actual* effective firing delay of the PA is 6 seconds, not 5 as listed in the code.
|
||||||
// So...
|
// So...
|
||||||
// I have reflected that here to be authentic.
|
// I have reflected that here to be authentic.
|
||||||
[ViewVariables(VVAccess.ReadWrite)] [DataField("fireDelay")] private TimeSpan _firingDelay = TimeSpan.FromSeconds(6);
|
[DataField("chargeTime")]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
[ViewVariables(VVAccess.ReadWrite)] [DataField("powerDrawBase")] private int _powerDrawBase = 500;
|
public TimeSpan ChargeTime = TimeSpan.FromSeconds(6.0);
|
||||||
[ViewVariables(VVAccess.ReadWrite)] [DataField("powerDrawMult")] private int _powerDrawMult = 1500;
|
|
||||||
|
|
||||||
[ViewVariables] private bool ConsolePowered => _apcPowerReceiverComponent?.Powered ?? true;
|
|
||||||
|
|
||||||
public ParticleAcceleratorControlBoxComponent()
|
|
||||||
{
|
|
||||||
Master = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ParticleAcceleratorPowerState MaxPower => _wireLimiterCut
|
|
||||||
? ParticleAcceleratorPowerState.Level3
|
|
||||||
: ParticleAcceleratorPowerState.Level2;
|
|
||||||
|
|
||||||
protected override void Initialize()
|
|
||||||
{
|
|
||||||
base.Initialize();
|
|
||||||
if (UserInterface != null)
|
|
||||||
{
|
|
||||||
UserInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
Owner.EnsureComponent(out _apcPowerReceiverComponent);
|
|
||||||
|
|
||||||
_apcPowerReceiverComponent.Load = 250;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is the power state for the PA control box itself.
|
|
||||||
// Keep in mind that the PA itself can keep firing as long as the HV cable under the power box has... power.
|
|
||||||
public void OnPowerStateChanged(PowerChangedEvent e)
|
|
||||||
{
|
|
||||||
UpdateAppearance();
|
|
||||||
|
|
||||||
if (!e.Powered)
|
|
||||||
{
|
|
||||||
UserInterface?.CloseAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UserInterfaceOnOnReceiveMessage(ServerBoundUserInterfaceMessage obj)
|
|
||||||
{
|
|
||||||
if (!ConsolePowered)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_wireInterfaceBlocked)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (obj.Message)
|
|
||||||
{
|
|
||||||
case ParticleAcceleratorSetEnableMessage enableMessage:
|
|
||||||
if (enableMessage.Enabled)
|
|
||||||
{
|
|
||||||
SwitchOn(obj.Session);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SwitchOff(obj.Session);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ParticleAcceleratorSetPowerStateMessage stateMessage:
|
|
||||||
SetStrength(stateMessage.State, obj.Session);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ParticleAcceleratorRescanPartsMessage _:
|
|
||||||
RescanParts(obj.Session);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateUI();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateUI()
|
|
||||||
{
|
|
||||||
var draw = 0f;
|
|
||||||
var receive = 0f;
|
|
||||||
|
|
||||||
if (_isEnabled)
|
|
||||||
{
|
|
||||||
draw = _partPowerBox!.PowerConsumerComponent!.DrawRate;
|
|
||||||
receive = _partPowerBox!.PowerConsumerComponent!.ReceivedPower;
|
|
||||||
}
|
|
||||||
|
|
||||||
var state = new ParticleAcceleratorUIState(
|
|
||||||
_isAssembled,
|
|
||||||
_isEnabled,
|
|
||||||
_selectedStrength,
|
|
||||||
(int) draw,
|
|
||||||
(int) receive,
|
|
||||||
_partEmitterLeft != null,
|
|
||||||
_partEmitterCenter != null,
|
|
||||||
_partEmitterRight != null,
|
|
||||||
_partPowerBox != null,
|
|
||||||
_partFuelChamber != null,
|
|
||||||
_partEndCap != null,
|
|
||||||
_wireInterfaceBlocked,
|
|
||||||
MaxPower,
|
|
||||||
_wirePowerBlocked);
|
|
||||||
|
|
||||||
UserInterface?.SetState(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnRemove()
|
|
||||||
{
|
|
||||||
_fireCancelTokenSrc?.Cancel();
|
|
||||||
_fireCancelTokenSrc = null;
|
|
||||||
|
|
||||||
Master = null;
|
|
||||||
foreach (var part in AllParts())
|
|
||||||
{
|
|
||||||
if (_entMan.TryGetComponent(part.Owner, out ParticleAcceleratorPartComponent? paPart))
|
|
||||||
paPart.Master = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
base.OnRemove();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
void IWires.RegisterWires(WiresComponent.WiresBuilder builder)
|
|
||||||
{
|
|
||||||
builder.CreateWire(ParticleAcceleratorControlBoxWires.Toggle);
|
|
||||||
builder.CreateWire(ParticleAcceleratorControlBoxWires.Strength);
|
|
||||||
builder.CreateWire(ParticleAcceleratorControlBoxWires.Interface);
|
|
||||||
builder.CreateWire(ParticleAcceleratorControlBoxWires.Limiter);
|
|
||||||
builder.CreateWire(ParticleAcceleratorControlBoxWires.Nothing);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void WiresUpdate(WiresUpdateEventArgs args)
|
|
||||||
{
|
|
||||||
switch (args.Identifier)
|
|
||||||
{
|
|
||||||
case ParticleAcceleratorControlBoxWires.Toggle:
|
|
||||||
if (args.Action == WiresAction.Pulse)
|
|
||||||
{
|
|
||||||
if (_isEnabled)
|
|
||||||
{
|
|
||||||
SwitchOff();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SwitchOn();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_wirePowerBlocked = args.Action == WiresAction.Cut;
|
|
||||||
if (_isEnabled)
|
|
||||||
{
|
|
||||||
SwitchOff();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ParticleAcceleratorControlBoxWires.Strength:
|
|
||||||
if (args.Action == WiresAction.Pulse)
|
|
||||||
{
|
|
||||||
SetStrength(_selectedStrength + 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_wireStrengthCut = args.Action == WiresAction.Cut;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ParticleAcceleratorControlBoxWires.Interface:
|
|
||||||
if (args.Action == WiresAction.Pulse)
|
|
||||||
{
|
|
||||||
_wireInterfaceBlocked ^= true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_wireInterfaceBlocked = args.Action == WiresAction.Cut;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ParticleAcceleratorControlBoxWires.Limiter:
|
|
||||||
if (args.Action == WiresAction.Pulse)
|
|
||||||
{
|
|
||||||
Owner.PopupMessageEveryone(Loc.GetString("particle-accelerator-control-box-component-wires-update-limiter-on-pulse"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_wireLimiterCut = args.Action == WiresAction.Cut;
|
|
||||||
if (_selectedStrength == ParticleAcceleratorPowerState.Level3 && !_wireLimiterCut)
|
|
||||||
{
|
|
||||||
// Yes, it's a feature that mending this wire WON'T WORK if the strength wire is also cut.
|
|
||||||
// Since that blocks SetStrength().
|
|
||||||
SetStrength(ParticleAcceleratorPowerState.Level2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateUI();
|
|
||||||
UpdateWireStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateWireStatus()
|
|
||||||
{
|
|
||||||
if (!_entMan.TryGetComponent(Owner, out WiresComponent? wires))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var powerBlock = _wirePowerBlocked;
|
|
||||||
var keyboardLight = new StatusLightData(Color.LimeGreen,
|
|
||||||
_wireInterfaceBlocked
|
|
||||||
? StatusLightState.BlinkingFast
|
|
||||||
: StatusLightState.On,
|
|
||||||
"KEYB");
|
|
||||||
|
|
||||||
var powerLight = new StatusLightData(
|
|
||||||
Color.Yellow,
|
|
||||||
powerBlock ? StatusLightState.Off : StatusLightState.On,
|
|
||||||
"POWR");
|
|
||||||
|
|
||||||
var limiterLight = new StatusLightData(
|
|
||||||
_wireLimiterCut ? Color.Purple : Color.Teal,
|
|
||||||
StatusLightState.On,
|
|
||||||
"LIMT");
|
|
||||||
|
|
||||||
var strengthLight = new StatusLightData(
|
|
||||||
Color.Blue,
|
|
||||||
_wireStrengthCut ? StatusLightState.BlinkingSlow : StatusLightState.On,
|
|
||||||
"STRC");
|
|
||||||
|
|
||||||
wires.SetStatus(ParticleAcceleratorWireStatus.Keyboard, keyboardLight);
|
|
||||||
wires.SetStatus(ParticleAcceleratorWireStatus.Power, powerLight);
|
|
||||||
wires.SetStatus(ParticleAcceleratorWireStatus.Limiter, limiterLight);
|
|
||||||
wires.SetStatus(ParticleAcceleratorWireStatus.Strength, strengthLight);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
public void RescanParts(IPlayerSession? playerSession = null)
|
|
||||||
{
|
|
||||||
SwitchOff(playerSession, true);
|
|
||||||
foreach (var part in AllParts())
|
|
||||||
{
|
|
||||||
if (_entMan.TryGetComponent(part.Owner, out ParticleAcceleratorPartComponent? paPart))
|
|
||||||
paPart.Master = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
_isAssembled = false;
|
|
||||||
_partFuelChamber = null;
|
|
||||||
_partEndCap = null;
|
|
||||||
_partPowerBox = null;
|
|
||||||
_partEmitterLeft = null;
|
|
||||||
_partEmitterCenter = null;
|
|
||||||
_partEmitterRight = null;
|
|
||||||
|
|
||||||
var xform = _entMan.GetComponent<TransformComponent>(Owner);
|
|
||||||
|
|
||||||
// Find fuel chamber first by scanning cardinals.
|
|
||||||
if (xform.Anchored && _entMan.TryGetComponent(xform.GridUid, out MapGridComponent? grid))
|
|
||||||
{
|
|
||||||
foreach (var maybeFuel in grid.GetCardinalNeighborCells(xform.Coordinates))
|
|
||||||
{
|
|
||||||
if (_entMan.TryGetComponent(maybeFuel, out _partFuelChamber))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_partFuelChamber == null)
|
|
||||||
{
|
|
||||||
UpdateUI();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Align ourselves to match fuel chamber orientation.
|
|
||||||
// This means that if you mess up the orientation of the control box it's not a big deal,
|
|
||||||
// because the sprite is far from obvious about the orientation.
|
|
||||||
xform.LocalRotation = _entMan.GetComponent<TransformComponent>(_partFuelChamber.Owner).LocalRotation;
|
|
||||||
|
|
||||||
var offsetEndCap = RotateOffset((1, 1));
|
|
||||||
var offsetPowerBox = RotateOffset((1, -1));
|
|
||||||
var offsetEmitterLeft = RotateOffset((0, -2));
|
|
||||||
var offsetEmitterCenter = RotateOffset((1, -2));
|
|
||||||
var offsetEmitterRight = RotateOffset((2, -2));
|
|
||||||
|
|
||||||
ScanPart(offsetEndCap, out _partEndCap);
|
|
||||||
ScanPart(offsetPowerBox, out _partPowerBox);
|
|
||||||
|
|
||||||
if (!ScanPart(offsetEmitterCenter, out _partEmitterCenter) ||
|
|
||||||
_partEmitterCenter.Type != ParticleAcceleratorEmitterType.Center)
|
|
||||||
{
|
|
||||||
// if it's the wrong type we need to clear this to avoid shenanigans.
|
|
||||||
_partEmitterCenter = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ScanPart(offsetEmitterLeft, out _partEmitterLeft) &&
|
|
||||||
_partEmitterLeft.Type != ParticleAcceleratorEmitterType.Left)
|
|
||||||
{
|
|
||||||
_partEmitterLeft = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ScanPart(offsetEmitterRight, out _partEmitterRight) &&
|
|
||||||
_partEmitterRight.Type != ParticleAcceleratorEmitterType.Right)
|
|
||||||
{
|
|
||||||
_partEmitterRight = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
_isAssembled = _partFuelChamber != null &&
|
|
||||||
_partPowerBox != null &&
|
|
||||||
_partEmitterCenter != null &&
|
|
||||||
_partEmitterLeft != null &&
|
|
||||||
_partEmitterRight != null &&
|
|
||||||
_partEndCap != null;
|
|
||||||
|
|
||||||
foreach (var part in AllParts())
|
|
||||||
{
|
|
||||||
if (_entMan.TryGetComponent(part.Owner, out ParticleAcceleratorPartComponent? paPart))
|
|
||||||
paPart.Master = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateUI();
|
|
||||||
|
|
||||||
Vector2i RotateOffset(in Vector2i vec)
|
|
||||||
{
|
|
||||||
var rot = new Angle(_entMan.GetComponent<TransformComponent>(Owner).LocalRotation);
|
|
||||||
return (Vector2i) rot.RotateVec(vec);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool ScanPart<T>(Vector2i offset, [NotNullWhen(true)] out T? part)
|
|
||||||
where T : Component
|
|
||||||
{
|
|
||||||
var xform = _entMan.GetComponent<TransformComponent>(Owner);
|
|
||||||
if (!_mapManager.TryGetGrid(xform.GridUid, out var grid))
|
|
||||||
{
|
|
||||||
part = default;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var coords = xform.Coordinates;
|
|
||||||
foreach (var ent in grid.GetOffset(coords, offset))
|
|
||||||
{
|
|
||||||
if (_entMan.TryGetComponent(ent, out part) && !part.Deleted)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
part = default;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<Component> AllParts()
|
|
||||||
{
|
|
||||||
if (_partFuelChamber != null)
|
|
||||||
yield return _partFuelChamber;
|
|
||||||
if (_partEndCap != null)
|
|
||||||
yield return _partEndCap;
|
|
||||||
if (_partPowerBox != null)
|
|
||||||
yield return _partPowerBox;
|
|
||||||
if (_partEmitterLeft != null)
|
|
||||||
yield return _partEmitterLeft;
|
|
||||||
if (_partEmitterCenter != null)
|
|
||||||
yield return _partEmitterCenter;
|
|
||||||
if (_partEmitterRight != null)
|
|
||||||
yield return _partEmitterRight;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SwitchOn(IPlayerSession? playerSession = null)
|
|
||||||
{
|
|
||||||
DebugTools.Assert(_isAssembled);
|
|
||||||
|
|
||||||
if (_isEnabled)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Logging
|
|
||||||
_entMan.TryGetComponent(playerSession?.AttachedEntity, out MindComponent? mindComponent);
|
|
||||||
if(mindComponent != null)
|
|
||||||
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{_entMan.ToPrettyString(mindComponent.Owner):player} has set {_entMan.ToPrettyString(Owner)} to on");
|
|
||||||
|
|
||||||
_isEnabled = true;
|
|
||||||
UpdatePowerDraw();
|
|
||||||
// If we don't have power yet we'll turn on when we receive more power from the powernet.
|
|
||||||
// if we do we'll just go and turn on right now.
|
|
||||||
if (_partPowerBox!.PowerConsumerComponent!.ReceivedPower >= _partPowerBox.PowerConsumerComponent.DrawRate)
|
|
||||||
{
|
|
||||||
PowerOn();
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateUI();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdatePowerDraw()
|
|
||||||
{
|
|
||||||
_partPowerBox!.PowerConsumerComponent!.DrawRate = PowerDrawFor(_selectedStrength);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SwitchOff(IPlayerSession? playerSession = null, bool rescan = false)
|
|
||||||
{
|
|
||||||
// Logging
|
|
||||||
_entMan.TryGetComponent(playerSession?.AttachedEntity, out MindComponent? mindComponent);
|
|
||||||
if(mindComponent != null)
|
|
||||||
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{_entMan.ToPrettyString(mindComponent.Owner):player} has set {_entMan.ToPrettyString(Owner)} to off{(rescan ? " via rescan" : "")}");
|
|
||||||
|
|
||||||
_isEnabled = false;
|
|
||||||
PowerOff();
|
|
||||||
UpdateUI();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void PowerOn()
|
|
||||||
{
|
|
||||||
DebugTools.Assert(_isEnabled);
|
|
||||||
DebugTools.Assert(_isAssembled);
|
|
||||||
|
|
||||||
if (_isPowered)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_isPowered = true;
|
|
||||||
UpdateFiring();
|
|
||||||
UpdatePartVisualStates();
|
|
||||||
UpdateUI();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void PowerOff()
|
|
||||||
{
|
|
||||||
if (!_isPowered)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_isPowered = false;
|
|
||||||
UpdateFiring();
|
|
||||||
UpdateUI();
|
|
||||||
UpdatePartVisualStates();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void SetStrength(ParticleAcceleratorPowerState state, IPlayerSession? playerSession = null)
|
|
||||||
{
|
|
||||||
if (_wireStrengthCut)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
state = (ParticleAcceleratorPowerState) MathHelper.Clamp(
|
|
||||||
(int) state,
|
|
||||||
(int) ParticleAcceleratorPowerState.Standby,
|
|
||||||
(int) MaxPower);
|
|
||||||
|
|
||||||
_selectedStrength = state;
|
|
||||||
UpdateAppearance();
|
|
||||||
UpdatePartVisualStates();
|
|
||||||
|
|
||||||
// Logging
|
|
||||||
_entMan.TryGetComponent(playerSession?.AttachedEntity, out MindComponent? mindComponent);
|
|
||||||
LogImpact impact;
|
|
||||||
switch (state)
|
|
||||||
{
|
|
||||||
default:
|
|
||||||
case ParticleAcceleratorPowerState.Standby:
|
|
||||||
case ParticleAcceleratorPowerState.Level0:
|
|
||||||
impact = LogImpact.Low;
|
|
||||||
break;
|
|
||||||
case ParticleAcceleratorPowerState.Level1:
|
|
||||||
impact = LogImpact.High;
|
|
||||||
break;
|
|
||||||
case ParticleAcceleratorPowerState.Level2:
|
|
||||||
case ParticleAcceleratorPowerState.Level3:
|
|
||||||
impact = LogImpact.Extreme;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if(mindComponent != null)
|
|
||||||
_adminLogger.Add(LogType.Action, impact, $"{_entMan.ToPrettyString(mindComponent.Owner):player} has set the strength of {_entMan.ToPrettyString(Owner)} to {state}");
|
|
||||||
|
|
||||||
if (_isEnabled)
|
|
||||||
{
|
|
||||||
UpdatePowerDraw();
|
|
||||||
UpdateFiring();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateAppearance()
|
|
||||||
{
|
|
||||||
if (_entMan.TryGetComponent(Owner, out AppearanceComponent? appearance))
|
|
||||||
{
|
|
||||||
appearance.SetData(ParticleAcceleratorVisuals.VisualState,
|
|
||||||
_apcPowerReceiverComponent!.Powered
|
|
||||||
? (ParticleAcceleratorVisualState) _selectedStrength
|
|
||||||
: ParticleAcceleratorVisualState.Unpowered);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateFiring()
|
|
||||||
{
|
|
||||||
if (!_isPowered || _selectedStrength == ParticleAcceleratorPowerState.Standby)
|
|
||||||
{
|
|
||||||
StopFiring();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
StartFiring();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void StartFiring()
|
|
||||||
{
|
|
||||||
EverythingIsWellToFire();
|
|
||||||
|
|
||||||
_fireCancelTokenSrc?.Cancel();
|
|
||||||
_fireCancelTokenSrc = new CancellationTokenSource();
|
|
||||||
var cancelToken = _fireCancelTokenSrc.Token;
|
|
||||||
Timer.SpawnRepeating(_firingDelay, Fire, cancelToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Fire()
|
|
||||||
{
|
|
||||||
EverythingIsWellToFire();
|
|
||||||
|
|
||||||
_partEmitterCenter!.Fire(_selectedStrength);
|
|
||||||
_partEmitterLeft!.Fire(_selectedStrength);
|
|
||||||
_partEmitterRight!.Fire(_selectedStrength);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Conditional("DEBUG")]
|
|
||||||
private void EverythingIsWellToFire()
|
|
||||||
{
|
|
||||||
DebugTools.Assert(!Deleted);
|
|
||||||
DebugTools.Assert(_isPowered);
|
|
||||||
DebugTools.Assert(_selectedStrength != ParticleAcceleratorPowerState.Standby);
|
|
||||||
DebugTools.Assert(_isAssembled);
|
|
||||||
DebugTools.Assert(_partEmitterCenter != null);
|
|
||||||
DebugTools.Assert(_partEmitterLeft != null);
|
|
||||||
DebugTools.Assert(_partEmitterRight != null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void StopFiring()
|
|
||||||
{
|
|
||||||
_fireCancelTokenSrc?.Cancel();
|
|
||||||
_fireCancelTokenSrc = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int PowerDrawFor(ParticleAcceleratorPowerState strength)
|
|
||||||
{
|
|
||||||
return strength switch
|
|
||||||
{
|
|
||||||
ParticleAcceleratorPowerState.Standby => 0,
|
|
||||||
ParticleAcceleratorPowerState.Level0 => 1,
|
|
||||||
ParticleAcceleratorPowerState.Level1 => 3,
|
|
||||||
ParticleAcceleratorPowerState.Level2 => 4,
|
|
||||||
ParticleAcceleratorPowerState.Level3 => 5,
|
|
||||||
_ => 0
|
|
||||||
} * _powerDrawMult + _powerDrawBase;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PowerBoxReceivedChanged(PowerConsumerReceivedChanged eventArgs)
|
|
||||||
{
|
|
||||||
DebugTools.Assert(_isAssembled);
|
|
||||||
|
|
||||||
if (!_isEnabled)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var isPowered = eventArgs.ReceivedPower >= eventArgs.DrawRate;
|
|
||||||
if (isPowered)
|
|
||||||
{
|
|
||||||
PowerOn();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PowerOff();
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateUI();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdatePartVisualStates()
|
|
||||||
{
|
|
||||||
// UpdatePartVisualState(ControlBox);
|
|
||||||
UpdatePartVisualState(_partFuelChamber);
|
|
||||||
UpdatePartVisualState(_partPowerBox);
|
|
||||||
UpdatePartVisualState(_partEmitterCenter);
|
|
||||||
UpdatePartVisualState(_partEmitterLeft);
|
|
||||||
UpdatePartVisualState(_partEmitterRight);
|
|
||||||
//no endcap because it has no powerlevel-sprites
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdatePartVisualState(Component? component)
|
|
||||||
{
|
|
||||||
if (component == null || !_entMan.TryGetComponent<AppearanceComponent?>(component.Owner, out var appearanceComponent))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var state = _isPowered
|
|
||||||
? (ParticleAcceleratorVisualState) _selectedStrength
|
|
||||||
: ParticleAcceleratorVisualState.Unpowered;
|
|
||||||
appearanceComponent.SetData(ParticleAcceleratorVisuals.VisualState, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum ParticleAcceleratorControlBoxWires
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Pulse toggles Power. Cut permanently turns off until Mend.
|
|
||||||
/// </summary>
|
|
||||||
Toggle,
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Pulsing increases level until at limit.
|
/// Whether the interface has been disabled via a cut wire or not.
|
||||||
|
/// Modified by <see cref="ParticleAcceleratorKeyboardWireAction"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Strength,
|
[ViewVariables]
|
||||||
|
public bool InterfaceDisabled = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Pulsing toggles Button-Disabled on UI. Cut disables, Mend enables.
|
/// Whether the ability to change the strength of the PA has been disabled via a cut wire or not.
|
||||||
|
/// Modified by <see cref="ParticleAcceleratorStrengthWireAction"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Interface,
|
[ViewVariables]
|
||||||
|
public bool StrengthLocked = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Pulsing will produce short message about whirring noise. Cutting increases the max level to 3. Mending reduces it back to 2.
|
/// Whether the PA can be turned on.
|
||||||
|
/// Modified by <see cref="ParticleAcceleratorPowerWireAction"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Limiter,
|
[ViewVariables]
|
||||||
|
public bool CanBeEnabled = true;
|
||||||
/// <summary>
|
|
||||||
/// Does Nothing
|
|
||||||
/// </summary>
|
|
||||||
Nothing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,17 @@
|
|||||||
using Content.Shared.Singularity.Components;
|
using Content.Shared.Singularity.Components;
|
||||||
|
|
||||||
namespace Content.Server.ParticleAccelerator.Components
|
namespace Content.Server.ParticleAccelerator.Components;
|
||||||
{
|
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public sealed class ParticleAcceleratorEmitterComponent : Component
|
public sealed class ParticleAcceleratorEmitterComponent : Component
|
||||||
{
|
{
|
||||||
|
[DataField("emittedPrototype")]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public string EmittedPrototype = "ParticlesProjectile";
|
||||||
|
|
||||||
[DataField("emitterType")]
|
[DataField("emitterType")]
|
||||||
public ParticleAcceleratorEmitterType Type = ParticleAcceleratorEmitterType.Center;
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public ParticleAcceleratorEmitterType Type = ParticleAcceleratorEmitterType.Fore;
|
||||||
public void Fire(ParticleAcceleratorPowerState strength)
|
|
||||||
{
|
|
||||||
var entities = IoCManager.Resolve<IEntityManager>();
|
|
||||||
var projectile = entities.SpawnEntity("ParticlesProjectile", entities.GetComponent<TransformComponent>(Owner).Coordinates);
|
|
||||||
|
|
||||||
if (!entities.TryGetComponent<ParticleProjectileComponent?>(projectile, out var particleProjectileComponent))
|
|
||||||
{
|
|
||||||
Logger.Error("ParticleAcceleratorEmitter tried firing particles, but they was spawned without a ParticleProjectileComponent");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
particleProjectileComponent.Fire(strength, entities.GetComponent<TransformComponent>(Owner).WorldRotation, Owner);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
@@ -29,8 +21,7 @@ namespace Content.Server.ParticleAccelerator.Components
|
|||||||
|
|
||||||
public enum ParticleAcceleratorEmitterType
|
public enum ParticleAcceleratorEmitterType
|
||||||
{
|
{
|
||||||
Left,
|
Port,
|
||||||
Center,
|
Fore,
|
||||||
Right
|
Starboard
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,39 +1,8 @@
|
|||||||
namespace Content.Server.ParticleAccelerator.Components
|
namespace Content.Server.ParticleAccelerator.Components;
|
||||||
{
|
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
[Virtual]
|
public sealed class ParticleAcceleratorPartComponent : Component
|
||||||
public class ParticleAcceleratorPartComponent : Component
|
|
||||||
{
|
{
|
||||||
[ViewVariables] public ParticleAcceleratorControlBoxComponent? Master;
|
[ViewVariables]
|
||||||
|
public EntityUid? Master;
|
||||||
protected override void Initialize()
|
|
||||||
{
|
|
||||||
base.Initialize();
|
|
||||||
// FIXME: this has to be an entity system, full stop.
|
|
||||||
|
|
||||||
IoCManager.Resolve<IEntityManager>().GetComponent<TransformComponent>(Owner).Anchored = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnAnchorChanged()
|
|
||||||
{
|
|
||||||
RescanIfPossible();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnRemove()
|
|
||||||
{
|
|
||||||
base.OnRemove();
|
|
||||||
|
|
||||||
RescanIfPossible();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RescanIfPossible()
|
|
||||||
{
|
|
||||||
Master?.RescanParts();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Moved()
|
|
||||||
{
|
|
||||||
RescanIfPossible();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,6 @@
|
|||||||
using Content.Server.Power.Components;
|
namespace Content.Server.ParticleAccelerator.Components;
|
||||||
|
|
||||||
namespace Content.Server.ParticleAccelerator.Components;
|
|
||||||
|
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public sealed class ParticleAcceleratorPowerBoxComponent : Component
|
public sealed class ParticleAcceleratorPowerBoxComponent : Component
|
||||||
{
|
{
|
||||||
[ViewVariables] public PowerConsumerComponent? PowerConsumerComponent;
|
|
||||||
|
|
||||||
protected override void Initialize()
|
|
||||||
{
|
|
||||||
base.Initialize();
|
|
||||||
|
|
||||||
PowerConsumerComponent = Owner.EnsureComponentWarn<PowerConsumerComponent>();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,66 +1,9 @@
|
|||||||
using Content.Server.Projectiles;
|
|
||||||
using Content.Server.Singularity.Components;
|
|
||||||
using Content.Shared.Projectiles;
|
|
||||||
using Content.Shared.Singularity.Components;
|
using Content.Shared.Singularity.Components;
|
||||||
using Robust.Shared.Physics.Components;
|
|
||||||
using Robust.Shared.Physics.Systems;
|
|
||||||
using Robust.Shared.Timing;
|
|
||||||
|
|
||||||
namespace Content.Server.ParticleAccelerator.Components
|
namespace Content.Server.ParticleAccelerator.Components;
|
||||||
{
|
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public sealed class ParticleProjectileComponent : Component
|
public sealed class ParticleProjectileComponent : Component
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IEntityManager _entMan = default!;
|
|
||||||
|
|
||||||
public ParticleAcceleratorPowerState State;
|
public ParticleAcceleratorPowerState State;
|
||||||
|
|
||||||
public void Fire(ParticleAcceleratorPowerState state, Angle angle, EntityUid firer)
|
|
||||||
{
|
|
||||||
State = state;
|
|
||||||
|
|
||||||
if (!_entMan.TryGetComponent<PhysicsComponent>(Owner, out var physicsComponent))
|
|
||||||
{
|
|
||||||
Logger.Error("ParticleProjectile tried firing, but it was spawned without a CollidableComponent");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var physics = _entMan.System<SharedPhysicsSystem>();
|
|
||||||
physics.SetBodyStatus(physicsComponent, BodyStatus.InAir);
|
|
||||||
|
|
||||||
if (!_entMan.TryGetComponent<ProjectileComponent>(Owner, out var projectileComponent))
|
|
||||||
{
|
|
||||||
Logger.Error("ParticleProjectile tried firing, but it was spawned without a ProjectileComponent");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_entMan.EntitySysManager.GetEntitySystem<ProjectileSystem>().SetShooter(projectileComponent, firer);
|
|
||||||
|
|
||||||
if (!_entMan.TryGetComponent<SinguloFoodComponent>(Owner, out var singuloFoodComponent))
|
|
||||||
{
|
|
||||||
Logger.Error("ParticleProjectile tried firing, but it was spawned without a SinguloFoodComponent");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var multiplier = State switch
|
|
||||||
{
|
|
||||||
ParticleAcceleratorPowerState.Standby => 0,
|
|
||||||
ParticleAcceleratorPowerState.Level0 => 1,
|
|
||||||
ParticleAcceleratorPowerState.Level1 => 3,
|
|
||||||
ParticleAcceleratorPowerState.Level2 => 6,
|
|
||||||
ParticleAcceleratorPowerState.Level3 => 10,
|
|
||||||
_ => 0
|
|
||||||
};
|
|
||||||
singuloFoodComponent.Energy = 10 * multiplier;
|
|
||||||
|
|
||||||
if (_entMan.TryGetComponent(Owner, out AppearanceComponent? appearance))
|
|
||||||
{
|
|
||||||
appearance.SetData(ParticleAcceleratorVisuals.VisualState, state);
|
|
||||||
}
|
|
||||||
|
|
||||||
physics.SetLinearVelocity(Owner, angle.ToWorldVec() * 20f, body: physicsComponent);
|
|
||||||
|
|
||||||
_entMan.GetComponent<TransformComponent>(Owner).LocalRotation = angle;
|
|
||||||
Timer.Spawn(3000, () => _entMan.DeleteEntity(Owner));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
|
using Content.Server.Mind.Components;
|
||||||
using Content.Server.ParticleAccelerator.Components;
|
using Content.Server.ParticleAccelerator.Components;
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
|
using Content.Shared.Database;
|
||||||
|
using Content.Shared.Singularity.Components;
|
||||||
|
using Robust.Server.Player;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace Content.Server.ParticleAccelerator.EntitySystems;
|
namespace Content.Server.ParticleAccelerator.EntitySystems;
|
||||||
|
|
||||||
@@ -7,11 +13,361 @@ public sealed partial class ParticleAcceleratorSystem
|
|||||||
{
|
{
|
||||||
private void InitializeControlBoxSystem()
|
private void InitializeControlBoxSystem()
|
||||||
{
|
{
|
||||||
|
SubscribeLocalEvent<ParticleAcceleratorControlBoxComponent, ComponentStartup>(OnComponentStartup);
|
||||||
|
SubscribeLocalEvent<ParticleAcceleratorControlBoxComponent, ComponentShutdown>(OnComponentShutdown);
|
||||||
SubscribeLocalEvent<ParticleAcceleratorControlBoxComponent, PowerChangedEvent>(OnControlBoxPowerChange);
|
SubscribeLocalEvent<ParticleAcceleratorControlBoxComponent, PowerChangedEvent>(OnControlBoxPowerChange);
|
||||||
|
SubscribeLocalEvent<ParticleAcceleratorControlBoxComponent, ParticleAcceleratorSetEnableMessage>(OnUISetEnableMessage);
|
||||||
|
SubscribeLocalEvent<ParticleAcceleratorControlBoxComponent, ParticleAcceleratorSetPowerStateMessage>(OnUISetPowerMessage);
|
||||||
|
SubscribeLocalEvent<ParticleAcceleratorControlBoxComponent, ParticleAcceleratorRescanPartsMessage>(OnUIRescanMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void OnControlBoxPowerChange(EntityUid uid, ParticleAcceleratorControlBoxComponent component, ref PowerChangedEvent args)
|
public override void Update(float frameTime)
|
||||||
{
|
{
|
||||||
component.OnPowerStateChanged(args);
|
var curTime = _gameTiming.CurTime;
|
||||||
|
var query = EntityQueryEnumerator<ParticleAcceleratorControlBoxComponent>();
|
||||||
|
while (query.MoveNext(out var uid, out var controller))
|
||||||
|
{
|
||||||
|
if (controller.Firing && curTime >= controller.NextFire)
|
||||||
|
Fire(uid, curTime, controller);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Conditional("DEBUG")]
|
||||||
|
private void EverythingIsWellToFire(ParticleAcceleratorControlBoxComponent controller)
|
||||||
|
{
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Fire(EntityUid uid, TimeSpan curTime, ParticleAcceleratorControlBoxComponent? comp = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref comp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
comp.LastFire = curTime;
|
||||||
|
comp.NextFire = curTime + comp.ChargeTime;
|
||||||
|
|
||||||
|
EverythingIsWellToFire(comp);
|
||||||
|
|
||||||
|
var strength = comp.SelectedStrength;
|
||||||
|
FireEmitter(comp.PortEmitter!.Value, strength);
|
||||||
|
FireEmitter(comp.ForeEmitter!.Value, strength);
|
||||||
|
FireEmitter(comp.StarboardEmitter!.Value, strength);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SwitchOn(EntityUid uid, IPlayerSession? user = null, ParticleAcceleratorControlBoxComponent? comp = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref comp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
DebugTools.Assert(comp.Assembled);
|
||||||
|
|
||||||
|
if (comp.Enabled || !comp.CanBeEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (HasComp<MindComponent>(user?.AttachedEntity))
|
||||||
|
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{EntityManager.ToPrettyString((EntityUid) user!.AttachedEntity):player} has turned {EntityManager.ToPrettyString(uid)} on");
|
||||||
|
|
||||||
|
comp.Enabled = true;
|
||||||
|
UpdatePowerDraw(uid, comp);
|
||||||
|
|
||||||
|
if (!TryComp<PowerConsumerComponent>(comp.PowerBox, out var powerConsumer)
|
||||||
|
|| powerConsumer.ReceivedPower >= powerConsumer.DrawRate * ParticleAcceleratorControlBoxComponent.RequiredPowerRatio)
|
||||||
|
PowerOn(uid, comp);
|
||||||
|
|
||||||
|
UpdateUI(uid, comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SwitchOff(EntityUid uid, IPlayerSession? user = null, ParticleAcceleratorControlBoxComponent? comp = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref comp))
|
||||||
|
return;
|
||||||
|
if (!comp.Enabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (HasComp<MindComponent>(user?.AttachedEntity))
|
||||||
|
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{EntityManager.ToPrettyString((EntityUid) user!.AttachedEntity):player} has turned {EntityManager.ToPrettyString(uid)} off");
|
||||||
|
|
||||||
|
comp.Enabled = false;
|
||||||
|
UpdatePowerDraw(uid, comp);
|
||||||
|
PowerOff(uid, comp);
|
||||||
|
UpdateUI(uid, comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PowerOn(EntityUid uid, ParticleAcceleratorControlBoxComponent? comp = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref comp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
DebugTools.Assert(comp.Enabled);
|
||||||
|
DebugTools.Assert(comp.Assembled);
|
||||||
|
|
||||||
|
if (comp.Powered)
|
||||||
|
return;
|
||||||
|
|
||||||
|
comp.Powered = true;
|
||||||
|
UpdatePowerDraw(uid, comp);
|
||||||
|
UpdateFiring(uid, comp);
|
||||||
|
UpdatePartVisualStates(uid, comp);
|
||||||
|
UpdateUI(uid, comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PowerOff(EntityUid uid, ParticleAcceleratorControlBoxComponent? comp = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref comp))
|
||||||
|
return;
|
||||||
|
if (!comp.Powered)
|
||||||
|
return;
|
||||||
|
|
||||||
|
comp.Powered = false;
|
||||||
|
UpdatePowerDraw(uid, comp);
|
||||||
|
UpdateFiring(uid, comp);
|
||||||
|
UpdatePartVisualStates(uid, comp);
|
||||||
|
UpdateUI(uid, comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetStrength(EntityUid uid, ParticleAcceleratorPowerState strength, IPlayerSession? user = null, ParticleAcceleratorControlBoxComponent? comp = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref comp))
|
||||||
|
return;
|
||||||
|
if (comp.StrengthLocked)
|
||||||
|
return;
|
||||||
|
|
||||||
|
strength = (ParticleAcceleratorPowerState) MathHelper.Clamp(
|
||||||
|
(int) strength,
|
||||||
|
(int) ParticleAcceleratorPowerState.Standby,
|
||||||
|
(int) comp.MaxStrength
|
||||||
|
);
|
||||||
|
|
||||||
|
if (strength == comp.SelectedStrength)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (HasComp<MindComponent>(user?.AttachedEntity))
|
||||||
|
{
|
||||||
|
var impact = strength switch
|
||||||
|
{
|
||||||
|
ParticleAcceleratorPowerState.Standby => LogImpact.Low,
|
||||||
|
ParticleAcceleratorPowerState.Level0 => LogImpact.Medium,
|
||||||
|
ParticleAcceleratorPowerState.Level1 => LogImpact.High,
|
||||||
|
ParticleAcceleratorPowerState.Level2
|
||||||
|
or ParticleAcceleratorPowerState.Level3
|
||||||
|
or _ => LogImpact.Extreme,
|
||||||
|
};
|
||||||
|
|
||||||
|
_adminLogger.Add(LogType.Action, impact, $"{EntityManager.ToPrettyString(user!.AttachedEntity!.Value):player} has set the strength of {EntityManager.ToPrettyString(uid)} to {strength}");
|
||||||
|
}
|
||||||
|
|
||||||
|
comp.SelectedStrength = strength;
|
||||||
|
UpdateAppearance(uid, comp);
|
||||||
|
UpdatePartVisualStates(uid, comp);
|
||||||
|
|
||||||
|
if (comp.Enabled)
|
||||||
|
{
|
||||||
|
UpdatePowerDraw(uid, comp);
|
||||||
|
UpdateFiring(uid, comp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateFiring(EntityUid uid, ParticleAcceleratorControlBoxComponent? comp = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref comp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!comp.Powered || comp.SelectedStrength < ParticleAcceleratorPowerState.Level0)
|
||||||
|
{
|
||||||
|
comp.Firing = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
EverythingIsWellToFire(comp);
|
||||||
|
|
||||||
|
var curTime = _gameTiming.CurTime;
|
||||||
|
comp.LastFire = curTime;
|
||||||
|
comp.NextFire = curTime + comp.ChargeTime;
|
||||||
|
comp.Firing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdatePowerDraw(EntityUid uid, ParticleAcceleratorControlBoxComponent? comp = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref comp))
|
||||||
|
return;
|
||||||
|
if (!TryComp<PowerConsumerComponent>(comp.PowerBox, out var powerConsumer))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var powerDraw = comp.BasePowerDraw;
|
||||||
|
if (comp.Enabled)
|
||||||
|
powerDraw += comp.LevelPowerDraw * (int) comp.SelectedStrength;
|
||||||
|
|
||||||
|
powerConsumer.DrawRate = powerDraw;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateUI(EntityUid uid, ParticleAcceleratorControlBoxComponent? comp = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref comp))
|
||||||
|
return;
|
||||||
|
if (!_uiSystem.TryGetUi(uid, ParticleAcceleratorControlBoxUiKey.Key, out var bui))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var draw = 0f;
|
||||||
|
var receive = 0f;
|
||||||
|
|
||||||
|
if (TryComp<PowerConsumerComponent>(comp.PowerBox, out var powerConsumer))
|
||||||
|
{
|
||||||
|
draw = powerConsumer.DrawRate;
|
||||||
|
receive = powerConsumer.ReceivedPower;
|
||||||
|
}
|
||||||
|
|
||||||
|
_uiSystem.SetUiState(bui, new ParticleAcceleratorUIState(
|
||||||
|
comp.Assembled,
|
||||||
|
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,
|
||||||
|
comp.InterfaceDisabled,
|
||||||
|
comp.MaxStrength,
|
||||||
|
comp.StrengthLocked
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateAppearance(EntityUid uid, ParticleAcceleratorControlBoxComponent? comp = null, AppearanceComponent? appearance = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref comp))
|
||||||
|
return;
|
||||||
|
|
||||||
|
_appearanceSystem.SetData(
|
||||||
|
uid,
|
||||||
|
ParticleAcceleratorVisuals.VisualState,
|
||||||
|
TryComp<ApcPowerReceiverComponent>(uid, out var apcPower) && !apcPower.Powered
|
||||||
|
? ParticleAcceleratorVisualState.Unpowered
|
||||||
|
: (ParticleAcceleratorVisualState) comp.SelectedStrength,
|
||||||
|
appearance
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdatePartVisualStates(EntityUid uid, ParticleAcceleratorControlBoxComponent? controller = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref controller))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var state = controller.Powered ? (ParticleAcceleratorVisualState) controller.SelectedStrength : ParticleAcceleratorVisualState.Unpowered;
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
//no endcap because it has no powerlevel-sprites
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<EntityUid> AllParts(EntityUid uid, ParticleAcceleratorControlBoxComponent? comp = null)
|
||||||
|
{
|
||||||
|
if (Resolve(uid, ref comp))
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
if (partQuery.TryGetComponent(part, out var partData))
|
||||||
|
partData.Master = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is the power state for the PA control box itself.
|
||||||
|
// Keep in mind that the PA itself can keep firing as long as the HV cable under the power box has... power.
|
||||||
|
private void OnControlBoxPowerChange(EntityUid uid, ParticleAcceleratorControlBoxComponent comp, ref PowerChangedEvent args)
|
||||||
|
{
|
||||||
|
UpdateAppearance(uid, comp);
|
||||||
|
|
||||||
|
if (!args.Powered)
|
||||||
|
_uiSystem.TryCloseAll(uid, ParticleAcceleratorControlBoxUiKey.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUISetEnableMessage(EntityUid uid, ParticleAcceleratorControlBoxComponent comp, ParticleAcceleratorSetEnableMessage msg)
|
||||||
|
{
|
||||||
|
if (!ParticleAcceleratorControlBoxUiKey.Key.Equals(msg.UiKey))
|
||||||
|
return;
|
||||||
|
if (comp.InterfaceDisabled)
|
||||||
|
return;
|
||||||
|
if (TryComp<ApcPowerReceiverComponent>(uid, out var apcPower) && !apcPower.Powered)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (msg.Enabled)
|
||||||
|
{
|
||||||
|
if (comp.Assembled)
|
||||||
|
SwitchOn(uid, (IPlayerSession?) msg.Session, comp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
SwitchOff(uid, (IPlayerSession?) msg.Session, comp);
|
||||||
|
|
||||||
|
UpdateUI(uid, comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUISetPowerMessage(EntityUid uid, ParticleAcceleratorControlBoxComponent comp, ParticleAcceleratorSetPowerStateMessage msg)
|
||||||
|
{
|
||||||
|
if (!ParticleAcceleratorControlBoxUiKey.Key.Equals(msg.UiKey))
|
||||||
|
return;
|
||||||
|
if (comp.InterfaceDisabled)
|
||||||
|
return;
|
||||||
|
if (TryComp<ApcPowerReceiverComponent>(uid, out var apcPower) && !apcPower.Powered)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SetStrength(uid, msg.State, (IPlayerSession?) msg.Session, comp);
|
||||||
|
|
||||||
|
UpdateUI(uid, comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUIRescanMessage(EntityUid uid, ParticleAcceleratorControlBoxComponent comp, ParticleAcceleratorRescanPartsMessage msg)
|
||||||
|
{
|
||||||
|
if (!ParticleAcceleratorControlBoxUiKey.Key.Equals(msg.UiKey))
|
||||||
|
return;
|
||||||
|
if (comp.InterfaceDisabled)
|
||||||
|
return;
|
||||||
|
if (TryComp<ApcPowerReceiverComponent>(uid, out var apcPower) && !apcPower.Powered)
|
||||||
|
return;
|
||||||
|
|
||||||
|
RescanParts(uid, (IPlayerSession?) msg.Session, comp);
|
||||||
|
|
||||||
|
UpdateUI(uid, comp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
using Content.Server.ParticleAccelerator.Components;
|
||||||
|
using Content.Server.Singularity.Components;
|
||||||
|
using Content.Shared.Projectiles;
|
||||||
|
using Content.Shared.Singularity.Components;
|
||||||
|
using Robust.Shared.Physics.Components;
|
||||||
|
|
||||||
|
namespace Content.Server.ParticleAccelerator.EntitySystems;
|
||||||
|
|
||||||
|
public sealed partial class ParticleAcceleratorSystem
|
||||||
|
{
|
||||||
|
private void FireEmitter(EntityUid uid, ParticleAcceleratorPowerState strength, ParticleAcceleratorEmitterComponent? emitter = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref emitter))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var xformQuery = GetEntityQuery<TransformComponent>();
|
||||||
|
if (!xformQuery.TryGetComponent(uid, out var xform))
|
||||||
|
{
|
||||||
|
Logger.Error("ParticleAccelerator attempted to emit a particle without (having) a transform from which to base its initial position and orientation.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var emitted = Spawn(emitter.EmittedPrototype, xform.Coordinates);
|
||||||
|
|
||||||
|
if (xformQuery.TryGetComponent(emitted, out var particleXform))
|
||||||
|
_transformSystem.SetLocalRotation(emitted, xform.LocalRotation, particleXform);
|
||||||
|
|
||||||
|
if (TryComp<PhysicsComponent>(emitted, out var particlePhys))
|
||||||
|
{
|
||||||
|
var angle = _transformSystem.GetWorldRotation(uid, xformQuery);
|
||||||
|
_physicsSystem.SetBodyStatus(particlePhys, BodyStatus.InAir);
|
||||||
|
|
||||||
|
var velocity = angle.ToWorldVec() * 20f;
|
||||||
|
if (TryComp<PhysicsComponent>(uid, out var phys))
|
||||||
|
velocity += phys.LinearVelocity; // Inherit velocity from parent so if the clown has strapped a dozen engines to departures we don't outpace the particles.
|
||||||
|
|
||||||
|
_physicsSystem.SetLinearVelocity(emitted, velocity, body: particlePhys);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TryComp<ProjectileComponent>(emitted, out var proj))
|
||||||
|
_projectileSystem.SetShooter(proj, uid);
|
||||||
|
|
||||||
|
if (TryComp<SinguloFoodComponent>(emitted, out var food))
|
||||||
|
{
|
||||||
|
// TODO: Unhardcode this.
|
||||||
|
food.Energy = strength switch
|
||||||
|
{
|
||||||
|
ParticleAcceleratorPowerState.Standby => 0,
|
||||||
|
ParticleAcceleratorPowerState.Level0 => 1,
|
||||||
|
ParticleAcceleratorPowerState.Level1 => 3,
|
||||||
|
ParticleAcceleratorPowerState.Level2 => 6,
|
||||||
|
ParticleAcceleratorPowerState.Level3 => 10,
|
||||||
|
_ => 0,
|
||||||
|
} * 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TryComp<ParticleProjectileComponent>(emitted, out var particle))
|
||||||
|
particle.State = strength;
|
||||||
|
|
||||||
|
_appearanceSystem.SetData(emitted, ParticleAcceleratorVisuals.VisualState, strength);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,30 +1,162 @@
|
|||||||
using Content.Server.ParticleAccelerator.Components;
|
using Content.Server.ParticleAccelerator.Components;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Shared.Physics.Components;
|
using Robust.Server.Player;
|
||||||
|
using Robust.Shared.Map.Components;
|
||||||
using Robust.Shared.Physics.Events;
|
using Robust.Shared.Physics.Events;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Content.Server.ParticleAccelerator.EntitySystems;
|
||||||
|
|
||||||
namespace Content.Server.ParticleAccelerator.EntitySystems
|
|
||||||
{
|
|
||||||
[UsedImplicitly]
|
[UsedImplicitly]
|
||||||
public sealed partial class ParticleAcceleratorSystem
|
public sealed partial class ParticleAcceleratorSystem
|
||||||
{
|
{
|
||||||
private void InitializePartSystem()
|
private void InitializePartSystem()
|
||||||
{
|
{
|
||||||
|
SubscribeLocalEvent<ParticleAcceleratorPartComponent, ComponentShutdown>(OnComponentShutdown);
|
||||||
SubscribeLocalEvent<ParticleAcceleratorPartComponent, MoveEvent>(OnMoveEvent);
|
SubscribeLocalEvent<ParticleAcceleratorPartComponent, MoveEvent>(OnMoveEvent);
|
||||||
SubscribeLocalEvent<ParticleAcceleratorPartComponent, PhysicsBodyTypeChangedEvent>(BodyTypeChanged);
|
SubscribeLocalEvent<ParticleAcceleratorPartComponent, PhysicsBodyTypeChangedEvent>(BodyTypeChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void BodyTypeChanged(
|
public void RescanParts(EntityUid uid, IPlayerSession? user = null, ParticleAcceleratorControlBoxComponent? controller = null)
|
||||||
EntityUid uid,
|
|
||||||
ParticleAcceleratorPartComponent component,
|
|
||||||
ref PhysicsBodyTypeChangedEvent args)
|
|
||||||
{
|
{
|
||||||
component.OnAnchorChanged();
|
if (!Resolve(uid, ref controller))
|
||||||
|
return;
|
||||||
|
|
||||||
|
SwitchOff(uid, user, controller);
|
||||||
|
|
||||||
|
var partQuery = GetEntityQuery<ParticleAcceleratorPartComponent>();
|
||||||
|
foreach (var part in AllParts(uid, controller))
|
||||||
|
{
|
||||||
|
if (partQuery.TryGetComponent(part, out var partState))
|
||||||
|
partState.Master = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void OnMoveEvent(EntityUid uid, ParticleAcceleratorPartComponent component, ref MoveEvent args)
|
controller.Assembled = false;
|
||||||
|
controller.FuelChamber = null;
|
||||||
|
controller.EndCap = null;
|
||||||
|
controller.PowerBox = null;
|
||||||
|
controller.PortEmitter = null;
|
||||||
|
controller.ForeEmitter = null;
|
||||||
|
controller.StarboardEmitter = null;
|
||||||
|
|
||||||
|
var xformQuery = GetEntityQuery<TransformComponent>();
|
||||||
|
if (!xformQuery.TryGetComponent(uid, out var xform) || !xform.Anchored)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var gridUid = xform.GridUid;
|
||||||
|
if (gridUid == null || gridUid != xform.ParentUid || !_mapManager.TryGetGrid(gridUid, out var grid))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Find fuel chamber first by scanning cardinals.
|
||||||
|
var fuelQuery = GetEntityQuery<ParticleAcceleratorFuelChamberComponent>();
|
||||||
|
foreach (var adjacent in grid.GetCardinalNeighborCells(xform.Coordinates))
|
||||||
{
|
{
|
||||||
component.Moved();
|
if (fuelQuery.HasComponent(adjacent)
|
||||||
|
&& partQuery.TryGetComponent(adjacent, out var partState)
|
||||||
|
&& partState.Master == null)
|
||||||
|
{
|
||||||
|
controller.FuelChamber = adjacent;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (controller.FuelChamber == null)
|
||||||
|
{
|
||||||
|
UpdateUI(uid, controller);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Align ourselves to match fuel chamber orientation.
|
||||||
|
// This means that if you mess up the orientation of the control box it's not a big deal,
|
||||||
|
// because the sprite is far from obvious about the orientation.
|
||||||
|
var fuelXform = xformQuery.GetComponent(controller.FuelChamber!.Value);
|
||||||
|
var rotation = fuelXform.LocalRotation;
|
||||||
|
_transformSystem.SetLocalRotation(uid, rotation, xform);
|
||||||
|
|
||||||
|
// Calculate offsets for each of the parts of the PA.
|
||||||
|
// These are all done relative to the fuel chamber BC that is basically the center of the machine.
|
||||||
|
var positionFuelChamber = grid.TileIndicesFor(fuelXform.Coordinates); // //
|
||||||
|
var positionEndCap = positionFuelChamber + (Vector2i) rotation.RotateVec((0, 1)); // n // n: End Cap
|
||||||
|
var positionPowerBox = positionFuelChamber + (Vector2i) rotation.RotateVec((0, -1)); // CF // C: Control Box, F: Fuel Chamber
|
||||||
|
var positionPortEmitter = positionFuelChamber + (Vector2i) rotation.RotateVec((1, -2)); // P // P: Power Box
|
||||||
|
var positionForeEmitter = positionFuelChamber + (Vector2i) rotation.RotateVec((0, -2)); // EEE // E: Emitter (Starboard, Fore, Port)
|
||||||
|
var positionStarboardEmitter = positionFuelChamber + (Vector2i) rotation.RotateVec((-1, -2)); // //
|
||||||
|
|
||||||
|
ScanPart<ParticleAcceleratorEndCapComponent>(gridUid!.Value, positionEndCap, rotation, out controller.EndCap, out var _, grid);
|
||||||
|
ScanPart<ParticleAcceleratorPowerBoxComponent>(gridUid!.Value, positionPowerBox, rotation, out controller.PowerBox, out var _, grid);
|
||||||
|
|
||||||
|
if (!ScanPart<ParticleAcceleratorEmitterComponent>(gridUid!.Value, positionPortEmitter, rotation, out controller.PortEmitter, out var portEmitter, grid)
|
||||||
|
|| portEmitter!.Type != ParticleAcceleratorEmitterType.Port)
|
||||||
|
controller.PortEmitter = null;
|
||||||
|
|
||||||
|
if (!ScanPart<ParticleAcceleratorEmitterComponent>(gridUid!.Value, positionForeEmitter, rotation, out controller.ForeEmitter, out var foreEmitter, grid)
|
||||||
|
|| foreEmitter!.Type != ParticleAcceleratorEmitterType.Fore)
|
||||||
|
controller.ForeEmitter = null;
|
||||||
|
|
||||||
|
if (!ScanPart<ParticleAcceleratorEmitterComponent>(gridUid!.Value, positionStarboardEmitter, rotation, out controller.StarboardEmitter, out var starboardEmitter, grid)
|
||||||
|
|| starboardEmitter!.Type != ParticleAcceleratorEmitterType.Starboard)
|
||||||
|
controller.StarboardEmitter = null;
|
||||||
|
|
||||||
|
controller.Assembled =
|
||||||
|
controller.FuelChamber.HasValue
|
||||||
|
&& controller.EndCap.HasValue
|
||||||
|
&& controller.PowerBox.HasValue
|
||||||
|
&& controller.PortEmitter.HasValue
|
||||||
|
&& controller.ForeEmitter.HasValue
|
||||||
|
&& controller.StarboardEmitter.HasValue;
|
||||||
|
|
||||||
|
foreach (var part in AllParts(uid, controller))
|
||||||
|
{
|
||||||
|
if (partQuery.TryGetComponent(part, out var partState))
|
||||||
|
partState.Master = uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdatePowerDraw(uid, controller);
|
||||||
|
UpdateUI(uid, controller);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool ScanPart<T>(EntityUid uid, Vector2i coordinates, Angle? rotation, [NotNullWhen(true)] out EntityUid? part, [NotNullWhen(true)] out T? comp, MapGridComponent? grid = null)
|
||||||
|
where T : Component
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref grid))
|
||||||
|
{
|
||||||
|
part = null;
|
||||||
|
comp = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var compQuery = GetEntityQuery<T>();
|
||||||
|
foreach (var entity in grid.GetAnchoredEntities(coordinates))
|
||||||
|
{
|
||||||
|
if (compQuery.TryGetComponent(entity, out comp)
|
||||||
|
&& TryComp<ParticleAcceleratorPartComponent>(entity, out var partState) && partState.Master == null
|
||||||
|
&& (rotation == null || MathHelper.CloseTo(Transform(entity).LocalRotation.Theta, rotation!.Value.Theta)))
|
||||||
|
{
|
||||||
|
part = entity;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
part = null;
|
||||||
|
comp = null;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnComponentShutdown(EntityUid uid, ParticleAcceleratorPartComponent comp, ComponentShutdown args)
|
||||||
|
{
|
||||||
|
if (EntityManager.EntityExists(comp.Master))
|
||||||
|
RescanParts(comp.Master!.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BodyTypeChanged(EntityUid uid, ParticleAcceleratorPartComponent comp, ref PhysicsBodyTypeChangedEvent args)
|
||||||
|
{
|
||||||
|
if (EntityManager.EntityExists(comp.Master))
|
||||||
|
RescanParts(comp.Master!.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnMoveEvent(EntityUid uid, ParticleAcceleratorPartComponent comp, ref MoveEvent args)
|
||||||
|
{
|
||||||
|
if (EntityManager.EntityExists(comp.Master))
|
||||||
|
RescanParts(comp.Master!.Value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
using Content.Server.ParticleAccelerator.Components;
|
using Content.Server.ParticleAccelerator.Components;
|
||||||
using Content.Server.Power.EntitySystems;
|
using Content.Server.Power.EntitySystems;
|
||||||
|
|
||||||
namespace Content.Server.ParticleAccelerator.EntitySystems
|
namespace Content.Server.ParticleAccelerator.EntitySystems;
|
||||||
{
|
|
||||||
public sealed partial class ParticleAcceleratorSystem
|
public sealed partial class ParticleAcceleratorSystem
|
||||||
{
|
{
|
||||||
private void InitializePowerBoxSystem()
|
private void InitializePowerBoxSystem()
|
||||||
@@ -10,13 +10,19 @@ namespace Content.Server.ParticleAccelerator.EntitySystems
|
|||||||
SubscribeLocalEvent<ParticleAcceleratorPowerBoxComponent, PowerConsumerReceivedChanged>(PowerBoxReceivedChanged);
|
SubscribeLocalEvent<ParticleAcceleratorPowerBoxComponent, PowerConsumerReceivedChanged>(PowerBoxReceivedChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PowerBoxReceivedChanged(
|
private void PowerBoxReceivedChanged(EntityUid uid, ParticleAcceleratorPowerBoxComponent component, ref PowerConsumerReceivedChanged args)
|
||||||
EntityUid uid,
|
|
||||||
ParticleAcceleratorPowerBoxComponent component,
|
|
||||||
ref PowerConsumerReceivedChanged args)
|
|
||||||
{
|
{
|
||||||
if (TryComp(uid, out ParticleAcceleratorPartComponent? paPart))
|
if (!TryComp<ParticleAcceleratorPartComponent>(uid, out var part))
|
||||||
paPart.Master?.PowerBoxReceivedChanged(args);
|
return;
|
||||||
}
|
if (!TryComp<ParticleAcceleratorControlBoxComponent>(part.Master, out var controller))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var master = part.Master!.Value;
|
||||||
|
if (controller.Enabled && args.ReceivedPower >= args.DrawRate * ParticleAcceleratorControlBoxComponent.RequiredPowerRatio)
|
||||||
|
PowerOn(master, comp: controller);
|
||||||
|
else
|
||||||
|
PowerOff(master, comp: controller);
|
||||||
|
|
||||||
|
UpdateUI(master, controller);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,23 @@
|
|||||||
|
using Content.Server.Administration.Logs;
|
||||||
|
using Content.Server.Projectiles;
|
||||||
|
using Robust.Shared.Physics.Systems;
|
||||||
|
using Robust.Shared.Map;
|
||||||
|
using Robust.Shared.Timing;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
|
||||||
namespace Content.Server.ParticleAccelerator.EntitySystems;
|
namespace Content.Server.ParticleAccelerator.EntitySystems;
|
||||||
|
|
||||||
public sealed partial class ParticleAcceleratorSystem : EntitySystem
|
public sealed partial class ParticleAcceleratorSystem : EntitySystem
|
||||||
{
|
{
|
||||||
|
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
||||||
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||||
|
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||||
|
[Dependency] private readonly ProjectileSystem _projectileSystem = default!;
|
||||||
|
[Dependency] private readonly SharedAppearanceSystem _appearanceSystem = default!;
|
||||||
|
[Dependency] private readonly SharedPhysicsSystem _physicsSystem = default!;
|
||||||
|
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
|
||||||
|
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
using Content.Server.ParticleAccelerator.Components;
|
||||||
|
using Content.Server.Wires;
|
||||||
|
using Content.Shared.Singularity.Components;
|
||||||
|
using Content.Shared.Wires;
|
||||||
|
|
||||||
|
namespace Content.Server.ParticleAccelerator.Wires;
|
||||||
|
|
||||||
|
public sealed class ParticleAcceleratorKeyboardWireAction : ComponentWireAction<ParticleAcceleratorControlBoxComponent>
|
||||||
|
{
|
||||||
|
public override string Name { get; set; } = "wire-name-pa-keyboard";
|
||||||
|
public override Color Color { get; set; } = Color.LimeGreen;
|
||||||
|
public override object StatusKey { get; } = ParticleAcceleratorWireStatus.Keyboard;
|
||||||
|
|
||||||
|
public override StatusLightState? GetLightState(Wire wire, ParticleAcceleratorControlBoxComponent component)
|
||||||
|
{
|
||||||
|
return component.InterfaceDisabled ? StatusLightState.BlinkingFast : StatusLightState.On;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Cut(EntityUid user, Wire wire, ParticleAcceleratorControlBoxComponent controller)
|
||||||
|
{
|
||||||
|
controller.InterfaceDisabled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Mend(EntityUid user, Wire wire, ParticleAcceleratorControlBoxComponent controller)
|
||||||
|
{
|
||||||
|
controller.InterfaceDisabled = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Pulse(EntityUid user, Wire wire, ParticleAcceleratorControlBoxComponent controller)
|
||||||
|
{
|
||||||
|
controller.InterfaceDisabled = !controller.InterfaceDisabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
using Content.Server.ParticleAccelerator.Components;
|
||||||
|
using Content.Server.ParticleAccelerator.EntitySystems;
|
||||||
|
using Content.Server.Popups;
|
||||||
|
using Content.Server.Wires;
|
||||||
|
using Content.Shared.Popups;
|
||||||
|
using Content.Shared.Singularity.Components;
|
||||||
|
using Content.Shared.Wires;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
|
||||||
|
namespace Content.Server.ParticleAccelerator.Wires;
|
||||||
|
|
||||||
|
public sealed class ParticleAcceleratorLimiterWireAction : ComponentWireAction<ParticleAcceleratorControlBoxComponent>
|
||||||
|
{
|
||||||
|
public override string Name { get; set; } = "wire-name-pa-limiter";
|
||||||
|
public override Color Color { get; set; } = Color.Teal;
|
||||||
|
public override object StatusKey { get; } = ParticleAcceleratorWireStatus.Limiter;
|
||||||
|
|
||||||
|
public override StatusLightData? GetStatusLightData(Wire wire)
|
||||||
|
{
|
||||||
|
var result = base.GetStatusLightData(wire);
|
||||||
|
|
||||||
|
if (result.HasValue
|
||||||
|
&& EntityManager.TryGetComponent<ParticleAcceleratorControlBoxComponent>(wire.Owner, out var controller)
|
||||||
|
&& controller.MaxStrength >= ParticleAcceleratorPowerState.Level3)
|
||||||
|
result = new(Color.Purple, result.Value.State, result.Value.Text);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override StatusLightState? GetLightState(Wire wire, ParticleAcceleratorControlBoxComponent component)
|
||||||
|
{
|
||||||
|
return StatusLightState.On;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Cut(EntityUid user, Wire wire, ParticleAcceleratorControlBoxComponent controller)
|
||||||
|
{
|
||||||
|
controller.MaxStrength = ParticleAcceleratorPowerState.Level3;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Mend(EntityUid user, Wire wire, ParticleAcceleratorControlBoxComponent controller)
|
||||||
|
{
|
||||||
|
|
||||||
|
controller.MaxStrength = ParticleAcceleratorPowerState.Level2;
|
||||||
|
if (controller.SelectedStrength <= controller.MaxStrength || controller.StrengthLocked)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Yes, it's a feature that mending this wire WON'T WORK if the strength wire is also cut.
|
||||||
|
// Since that blocks SetStrength().
|
||||||
|
var paSystem = EntityManager.System<ParticleAcceleratorSystem>();
|
||||||
|
var userSession = EntityManager.TryGetComponent<ActorComponent>(user, out var actor) ? actor.PlayerSession : null;
|
||||||
|
paSystem.SetStrength(wire.Owner, controller.MaxStrength, userSession, controller);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Pulse(EntityUid user, Wire wire, ParticleAcceleratorControlBoxComponent controller)
|
||||||
|
{
|
||||||
|
EntityManager.System<PopupSystem>().PopupEntity(
|
||||||
|
Loc.GetString("particle-accelerator-control-box-component-wires-update-limiter-on-pulse"),
|
||||||
|
user,
|
||||||
|
PopupType.SmallCaution
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update(Wire wire)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
using Content.Server.ParticleAccelerator.Components;
|
||||||
|
using Content.Server.ParticleAccelerator.EntitySystems;
|
||||||
|
using Content.Server.Wires;
|
||||||
|
using Content.Shared.Singularity.Components;
|
||||||
|
using Content.Shared.Wires;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
|
namespace Content.Server.ParticleAccelerator.Wires;
|
||||||
|
|
||||||
|
public sealed class ParticleAcceleratorStrengthWireAction : ComponentWireAction<ParticleAcceleratorControlBoxComponent>
|
||||||
|
{
|
||||||
|
public override string Name { get; set; } = "wire-name-pa-strength";
|
||||||
|
public override Color Color { get; set; } = Color.Blue;
|
||||||
|
public override object StatusKey { get; } = ParticleAcceleratorWireStatus.Strength;
|
||||||
|
|
||||||
|
public override StatusLightState? GetLightState(Wire wire, ParticleAcceleratorControlBoxComponent component)
|
||||||
|
{
|
||||||
|
return component.StrengthLocked ? StatusLightState.BlinkingSlow : StatusLightState.On;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Cut(EntityUid user, Wire wire, ParticleAcceleratorControlBoxComponent controller)
|
||||||
|
{
|
||||||
|
controller.StrengthLocked = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Mend(EntityUid user, Wire wire, ParticleAcceleratorControlBoxComponent controller)
|
||||||
|
{
|
||||||
|
controller.StrengthLocked = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Pulse(EntityUid user, Wire wire, ParticleAcceleratorControlBoxComponent controller)
|
||||||
|
{
|
||||||
|
var paSystem = EntityManager.System<ParticleAcceleratorSystem>();
|
||||||
|
var userSession = EntityManager.TryGetComponent<ActorComponent>(user, out var actor) ? actor.PlayerSession : null;
|
||||||
|
paSystem.SetStrength(wire.Owner, (ParticleAcceleratorPowerState) ((int) controller.SelectedStrength + 1), userSession, controller);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
using Content.Server.ParticleAccelerator.Components;
|
||||||
|
using Content.Server.ParticleAccelerator.EntitySystems;
|
||||||
|
using Content.Server.Wires;
|
||||||
|
using Content.Shared.Singularity.Components;
|
||||||
|
using Content.Shared.Wires;
|
||||||
|
using Robust.Server.GameObjects;
|
||||||
|
|
||||||
|
namespace Content.Server.ParticleAccelerator.Wires;
|
||||||
|
|
||||||
|
public sealed class ParticleAcceleratorPowerWireAction : ComponentWireAction<ParticleAcceleratorControlBoxComponent>
|
||||||
|
{
|
||||||
|
public override string Name { get; set; } = "wire-name-pa-power";
|
||||||
|
public override Color Color { get; set; } = Color.Yellow;
|
||||||
|
public override object StatusKey { get; } = ParticleAcceleratorWireStatus.Power;
|
||||||
|
|
||||||
|
public override StatusLightState? GetLightState(Wire wire, ParticleAcceleratorControlBoxComponent component)
|
||||||
|
{
|
||||||
|
if (!component.CanBeEnabled)
|
||||||
|
return StatusLightState.Off;
|
||||||
|
return component.Enabled ? StatusLightState.On : StatusLightState.BlinkingSlow;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Cut(EntityUid user, Wire wire, ParticleAcceleratorControlBoxComponent controller)
|
||||||
|
{
|
||||||
|
var paSystem = EntityManager.System<ParticleAcceleratorSystem>();
|
||||||
|
var userSession = EntityManager.TryGetComponent<ActorComponent>(user, out var actor) ? actor.PlayerSession : null;
|
||||||
|
|
||||||
|
controller.CanBeEnabled = false;
|
||||||
|
paSystem.SwitchOff(wire.Owner, userSession, controller);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Mend(EntityUid user, Wire wire, ParticleAcceleratorControlBoxComponent controller)
|
||||||
|
{
|
||||||
|
controller.CanBeEnabled = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Pulse(EntityUid user, Wire wire, ParticleAcceleratorControlBoxComponent controller)
|
||||||
|
{
|
||||||
|
var paSystem = EntityManager.System<ParticleAcceleratorSystem>();
|
||||||
|
var userSession = EntityManager.TryGetComponent<ActorComponent>(user, out var actor) ? actor.PlayerSession : null;
|
||||||
|
|
||||||
|
if (controller.Enabled)
|
||||||
|
paSystem.SwitchOff(wire.Owner, userSession, controller);
|
||||||
|
else if (controller.Assembled)
|
||||||
|
paSystem.SwitchOn(wire.Owner, userSession, controller);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -43,8 +43,8 @@ public sealed class SingularityGeneratorSystem : EntitySystem
|
|||||||
if (!Resolve(uid, ref comp))
|
if (!Resolve(uid, ref comp))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
SetPower(comp, 0);
|
SetPower(uid, 0, comp);
|
||||||
EntityManager.SpawnEntity(comp.SpawnPrototype, Transform(comp.Owner).Coordinates);
|
EntityManager.SpawnEntity(comp.SpawnPrototype, Transform(uid).Coordinates);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Getters/Setters
|
#region Getters/Setters
|
||||||
@@ -54,15 +54,18 @@ public sealed class SingularityGeneratorSystem : EntitySystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="comp">The singularity generator component.</param>
|
/// <param name="comp">The singularity generator component.</param>
|
||||||
/// <param name="value">The new power level for the generator component to have.</param>
|
/// <param name="value">The new power level for the generator component to have.</param>
|
||||||
public void SetPower(SingularityGeneratorComponent comp, float value)
|
public void SetPower(EntityUid uid, float value, SingularityGeneratorComponent? comp = null)
|
||||||
{
|
{
|
||||||
|
if (!Resolve(uid, ref comp))
|
||||||
|
return;
|
||||||
|
|
||||||
var oldValue = comp.Power;
|
var oldValue = comp.Power;
|
||||||
if (value == oldValue)
|
if (value == oldValue)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
comp.Power = value;
|
comp.Power = value;
|
||||||
if (comp.Power >= comp.Threshold && oldValue < comp.Threshold)
|
if (comp.Power >= comp.Threshold && oldValue < comp.Threshold)
|
||||||
OnPassThreshold(comp.Owner, comp);
|
OnPassThreshold(uid, comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -71,45 +74,19 @@ public sealed class SingularityGeneratorSystem : EntitySystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="comp">The singularity generator component.</param>
|
/// <param name="comp">The singularity generator component.</param>
|
||||||
/// <param name="value">The new threshold power level for the generator component to have.</param>
|
/// <param name="value">The new threshold power level for the generator component to have.</param>
|
||||||
public void SetThreshold(SingularityGeneratorComponent comp, float value)
|
public void SetThreshold(EntityUid uid, float value, SingularityGeneratorComponent? comp = null)
|
||||||
{
|
{
|
||||||
|
if (!Resolve(uid, ref comp))
|
||||||
|
return;
|
||||||
|
|
||||||
var oldValue = comp.Threshold;
|
var oldValue = comp.Threshold;
|
||||||
if (value == comp.Threshold)
|
if (value == comp.Threshold)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
comp.Power = value;
|
comp.Power = value;
|
||||||
if (comp.Power >= comp.Threshold && comp.Power < oldValue)
|
if (comp.Power >= comp.Threshold && comp.Power < oldValue)
|
||||||
OnPassThreshold(comp.Owner, comp);
|
OnPassThreshold(uid, comp);
|
||||||
}
|
}
|
||||||
#region VV
|
|
||||||
/// <summary>
|
|
||||||
/// VV setter for <see cref="SingularityGeneratorComponent.Power"/>
|
|
||||||
/// If the singularity generator passes its threshold it also spawns a singularity.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="uid">The entity hosting the singularity generator that is being modified.</param>
|
|
||||||
/// <param name="value">The value of the new power level the singularity generator should have.</param>
|
|
||||||
/// <param name="comp">The singularity generator to change the power level of.</param>
|
|
||||||
public void SetPower(EntityUid uid, float value, SingularityGeneratorComponent? comp)
|
|
||||||
{
|
|
||||||
if(!Resolve(uid, ref comp))
|
|
||||||
return;
|
|
||||||
SetPower(comp, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// VV setter for <see cref="SingularityGeneratorComponent.Threshold"/>
|
|
||||||
/// If the singularity generator has passed its new threshold it also spawns a singularity.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="uid">The entity hosting the singularity generator that is being modified.</param>
|
|
||||||
/// <param name="value">The value of the new threshold power level the singularity generator should have.</param>
|
|
||||||
/// <param name="comp">The singularity generator to change the threshold power level of.</param>
|
|
||||||
public void SetThreshold(EntityUid uid, float value, SingularityGeneratorComponent? comp)
|
|
||||||
{
|
|
||||||
if(!Resolve(uid, ref comp))
|
|
||||||
return;
|
|
||||||
SetThreshold(comp, value);
|
|
||||||
}
|
|
||||||
#endregion VV
|
|
||||||
#endregion Getters/Setters
|
#endregion Getters/Setters
|
||||||
|
|
||||||
#region Event Handlers
|
#region Event Handlers
|
||||||
@@ -123,10 +100,10 @@ public sealed class SingularityGeneratorSystem : EntitySystem
|
|||||||
/// <param name="args">The state of the beginning of the collision.</param>
|
/// <param name="args">The state of the beginning of the collision.</param>
|
||||||
private void HandleParticleCollide(EntityUid uid, ParticleProjectileComponent component, ref StartCollideEvent args)
|
private void HandleParticleCollide(EntityUid uid, ParticleProjectileComponent component, ref StartCollideEvent args)
|
||||||
{
|
{
|
||||||
if (EntityManager.TryGetComponent<SingularityGeneratorComponent?>(args.OtherEntity, out var singularityGeneratorComponent))
|
if (EntityManager.TryGetComponent<SingularityGeneratorComponent>(args.OtherEntity, out var singularityGeneratorComponent))
|
||||||
{
|
{
|
||||||
SetPower(
|
SetPower(
|
||||||
singularityGeneratorComponent,
|
args.OtherEntity,
|
||||||
singularityGeneratorComponent.Power + component.State switch
|
singularityGeneratorComponent.Power + component.State switch
|
||||||
{
|
{
|
||||||
ParticleAcceleratorPowerState.Standby => 0,
|
ParticleAcceleratorPowerState.Standby => 0,
|
||||||
@@ -135,7 +112,9 @@ public sealed class SingularityGeneratorSystem : EntitySystem
|
|||||||
ParticleAcceleratorPowerState.Level2 => 4,
|
ParticleAcceleratorPowerState.Level2 => 4,
|
||||||
ParticleAcceleratorPowerState.Level3 => 8,
|
ParticleAcceleratorPowerState.Level3 => 8,
|
||||||
_ => 0
|
_ => 0
|
||||||
});
|
},
|
||||||
|
singularityGeneratorComponent
|
||||||
|
);
|
||||||
EntityManager.QueueDeleteEntity(uid);
|
EntityManager.QueueDeleteEntity(uid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Content.Server.Administration;
|
using Content.Server.Administration;
|
||||||
using Content.Server.ParticleAccelerator.Components;
|
using Content.Server.ParticleAccelerator.Components;
|
||||||
|
using Content.Server.ParticleAccelerator.EntitySystems;
|
||||||
using Content.Server.Singularity.Components;
|
using Content.Server.Singularity.Components;
|
||||||
using Content.Server.Singularity.EntitySystems;
|
using Content.Server.Singularity.EntitySystems;
|
||||||
using Content.Shared.Administration;
|
using Content.Shared.Administration;
|
||||||
@@ -44,12 +45,18 @@ namespace Content.Server.Singularity
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Setup PA
|
// Setup PA
|
||||||
foreach (var comp in entityManager.EntityQuery<ParticleAcceleratorControlBoxComponent>())
|
var paSystem = entitySystemManager.GetEntitySystem<ParticleAcceleratorSystem>();
|
||||||
|
var paQuery = entityManager.EntityQueryEnumerator<ParticleAcceleratorControlBoxComponent>();
|
||||||
|
while (paQuery.MoveNext(out var paId, out var paControl))
|
||||||
{
|
{
|
||||||
comp.RescanParts();
|
paSystem.RescanParts(paId, controller: paControl);
|
||||||
comp.SetStrength(ParticleAcceleratorPowerState.Level0);
|
if (!paControl.Assembled)
|
||||||
comp.SwitchOn();
|
continue;
|
||||||
|
|
||||||
|
paSystem.SetStrength(paId, ParticleAcceleratorPowerState.Level0, comp: paControl);
|
||||||
|
paSystem.SwitchOn(paId, comp: paControl);
|
||||||
}
|
}
|
||||||
|
|
||||||
shell.WriteLine("Done!");
|
shell.WriteLine("Done!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,13 +22,13 @@ namespace Content.Shared.Singularity.Components
|
|||||||
}
|
}
|
||||||
|
|
||||||
[NetSerializable, Serializable]
|
[NetSerializable, Serializable]
|
||||||
public enum ParticleAcceleratorPowerState
|
public enum ParticleAcceleratorPowerState : byte
|
||||||
{
|
{
|
||||||
Standby = ParticleAcceleratorVisualState.Powered,
|
Standby = ParticleAcceleratorVisualState.Powered,
|
||||||
Level0 = ParticleAcceleratorVisualState.Level0,
|
Level0 = ParticleAcceleratorVisualState.Level0,
|
||||||
Level1 = ParticleAcceleratorVisualState.Level1,
|
Level1 = ParticleAcceleratorVisualState.Level1,
|
||||||
Level2 = ParticleAcceleratorVisualState.Level2,
|
Level2 = ParticleAcceleratorVisualState.Level2,
|
||||||
Level3 = ParticleAcceleratorVisualState.Level3
|
Level3 = ParticleAcceleratorVisualState.Level3,
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ParticleAcceleratorVisualLayers
|
public enum ParticleAcceleratorVisualLayers
|
||||||
@@ -56,9 +56,9 @@ namespace Content.Shared.Singularity.Components
|
|||||||
public int PowerReceive;
|
public int PowerReceive;
|
||||||
|
|
||||||
//dont need a bool for the controlbox because... this is sent to the controlbox :D
|
//dont need a bool for the controlbox because... this is sent to the controlbox :D
|
||||||
public bool EmitterLeftExists;
|
public bool EmitterStarboardExists;
|
||||||
public bool EmitterCenterExists;
|
public bool EmitterForeExists;
|
||||||
public bool EmitterRightExists;
|
public bool EmitterPortExists;
|
||||||
public bool PowerBoxExists;
|
public bool PowerBoxExists;
|
||||||
public bool FuelChamberExists;
|
public bool FuelChamberExists;
|
||||||
public bool EndCapExists;
|
public bool EndCapExists;
|
||||||
@@ -67,16 +67,16 @@ namespace Content.Shared.Singularity.Components
|
|||||||
public ParticleAcceleratorPowerState MaxLevel;
|
public ParticleAcceleratorPowerState MaxLevel;
|
||||||
public bool WirePowerBlock;
|
public bool WirePowerBlock;
|
||||||
|
|
||||||
public ParticleAcceleratorUIState(bool assembled, bool enabled, ParticleAcceleratorPowerState state, int powerReceive, int powerDraw, bool emitterLeftExists, bool emitterCenterExists, bool emitterRightExists, bool powerBoxExists, bool fuelChamberExists, bool endCapExists, bool interfaceBlock, ParticleAcceleratorPowerState maxLevel, bool wirePowerBlock)
|
public ParticleAcceleratorUIState(bool assembled, bool enabled, ParticleAcceleratorPowerState state, int powerReceive, int powerDraw, bool emitterStarboardExists, bool emitterForeExists, bool emitterPortExists, bool powerBoxExists, bool fuelChamberExists, bool endCapExists, bool interfaceBlock, ParticleAcceleratorPowerState maxLevel, bool wirePowerBlock)
|
||||||
{
|
{
|
||||||
Assembled = assembled;
|
Assembled = assembled;
|
||||||
Enabled = enabled;
|
Enabled = enabled;
|
||||||
State = state;
|
State = state;
|
||||||
PowerDraw = powerDraw;
|
PowerDraw = powerDraw;
|
||||||
PowerReceive = powerReceive;
|
PowerReceive = powerReceive;
|
||||||
EmitterLeftExists = emitterLeftExists;
|
EmitterStarboardExists = emitterStarboardExists;
|
||||||
EmitterCenterExists = emitterCenterExists;
|
EmitterForeExists = emitterForeExists;
|
||||||
EmitterRightExists = emitterRightExists;
|
EmitterPortExists = emitterPortExists;
|
||||||
PowerBoxExists = powerBoxExists;
|
PowerBoxExists = powerBoxExists;
|
||||||
FuelChamberExists = fuelChamberExists;
|
FuelChamberExists = fuelChamberExists;
|
||||||
EndCapExists = endCapExists;
|
EndCapExists = endCapExists;
|
||||||
|
|||||||
@@ -14,3 +14,7 @@ wire-name-power = POWR
|
|||||||
wire-name-arcade-invincible = MNGR
|
wire-name-arcade-invincible = MNGR
|
||||||
wire-name-vending-contraband = MNGR
|
wire-name-vending-contraband = MNGR
|
||||||
wire-name-vending-eject = VEND
|
wire-name-vending-eject = VEND
|
||||||
|
wire-name-pa-keyboard = KEYB
|
||||||
|
wire-name-pa-limiter = LIMT
|
||||||
|
wire-name-pa-power = POWR
|
||||||
|
wire-name-pa-strength = STRC
|
||||||
|
|||||||
@@ -69,9 +69,9 @@
|
|||||||
- type: StorageFill
|
- type: StorageFill
|
||||||
contents:
|
contents:
|
||||||
- id: MachineParticleAcceleratorEndCapCircuitboard
|
- id: MachineParticleAcceleratorEndCapCircuitboard
|
||||||
- id: MachineParticleAcceleratorEmitterLeftCircuitboard
|
- id: MachineParticleAcceleratorEmitterStarboardCircuitboard
|
||||||
- id: MachineParticleAcceleratorEmitterCenterCircuitboard
|
- id: MachineParticleAcceleratorEmitterForeCircuitboard
|
||||||
- id: MachineParticleAcceleratorEmitterRightCircuitboard
|
- id: MachineParticleAcceleratorEmitterPortCircuitboard
|
||||||
- id: MachineParticleAcceleratorFuelChamberCircuitboard
|
- id: MachineParticleAcceleratorFuelChamberCircuitboard
|
||||||
- id: MachineParticleAcceleratorPowerBoxCircuitboard
|
- id: MachineParticleAcceleratorPowerBoxCircuitboard
|
||||||
- id: ParticleAcceleratorComputerCircuitboard
|
- id: ParticleAcceleratorComputerCircuitboard
|
||||||
|
|||||||
@@ -48,43 +48,43 @@
|
|||||||
# Emitter
|
# Emitter
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: MachineParticleAcceleratorEmitterLeftCircuitboard
|
id: MachineParticleAcceleratorEmitterStarboardCircuitboard
|
||||||
parent: BaseMachineCircuitboard
|
parent: BaseMachineCircuitboard
|
||||||
name: PA emitter left board
|
name: PA starboard emitter board
|
||||||
description: A machine board for a particle accelerator left emitter
|
description: A machine board for a particle accelerator left emitter
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
state: engineering
|
state: engineering
|
||||||
- type: MachineBoard
|
- type: MachineBoard
|
||||||
prototype: ParticleAcceleratorEmitterLeftUnfinished
|
prototype: ParticleAcceleratorEmitterStarboardUnfinished
|
||||||
materialRequirements:
|
materialRequirements:
|
||||||
Glass: 5
|
Glass: 5
|
||||||
Steel: 5
|
Steel: 5
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: MachineParticleAcceleratorEmitterCenterCircuitboard
|
id: MachineParticleAcceleratorEmitterForeCircuitboard
|
||||||
parent: BaseMachineCircuitboard
|
parent: BaseMachineCircuitboard
|
||||||
name: PA emitter center board
|
name: PA fore emitter board
|
||||||
description: A machine board for a particle accelerator center emitter
|
description: A machine board for a particle accelerator center emitter
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
state: engineering
|
state: engineering
|
||||||
- type: MachineBoard
|
- type: MachineBoard
|
||||||
prototype: ParticleAcceleratorEmitterCenterUnfinished
|
prototype: ParticleAcceleratorEmitterForeUnfinished
|
||||||
materialRequirements:
|
materialRequirements:
|
||||||
Glass: 5
|
Glass: 5
|
||||||
Steel: 5
|
Steel: 5
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: MachineParticleAcceleratorEmitterRightCircuitboard
|
id: MachineParticleAcceleratorEmitterPortCircuitboard
|
||||||
parent: BaseMachineCircuitboard
|
parent: BaseMachineCircuitboard
|
||||||
name: PA emitter right board
|
name: PA port emitter board
|
||||||
description: A machine board for a particle accelerator right emitter
|
description: A machine board for a particle accelerator right emitter
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
state: engineering
|
state: engineering
|
||||||
- type: MachineBoard
|
- type: MachineBoard
|
||||||
prototype: ParticleAcceleratorEmitterRightUnfinished
|
prototype: ParticleAcceleratorEmitterPortUnfinished
|
||||||
materialRequirements:
|
materialRequirements:
|
||||||
Glass: 5
|
Glass: 5
|
||||||
Steel: 5
|
Steel: 5
|
||||||
|
|||||||
@@ -1,28 +1,17 @@
|
|||||||
- type: entity
|
- type: entity
|
||||||
parent: ParticleAcceleratorBase
|
parent: ParticleAcceleratorFinishedPart
|
||||||
id: ParticleAcceleratorControlBox
|
id: ParticleAcceleratorControlBox
|
||||||
name: PA control computer
|
name: PA control computer
|
||||||
description: This controls the density of the particles.
|
description: This controls the density of the particles.
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Structures/Power/Generation/PA/control_box.rsi
|
sprite: Structures/Power/Generation/PA/control_box.rsi
|
||||||
layers:
|
- type: ParticleAcceleratorControlBox
|
||||||
- state: completed
|
|
||||||
map: [ "enum.ParticleAcceleratorVisualLayers.Base" ]
|
|
||||||
- state: unlitp
|
|
||||||
map: [ "enum.ParticleAcceleratorVisualLayers.Unlit" ]
|
|
||||||
shader: unshaded
|
|
||||||
visible: false
|
|
||||||
- type: Appearance
|
|
||||||
- type: ParticleAcceleratorPartVisuals
|
|
||||||
stateBase: unlit
|
|
||||||
- type: ApcPowerReceiver
|
- type: ApcPowerReceiver
|
||||||
powerLoad: 250
|
powerLoad: 250
|
||||||
- type: ExtensionCableReceiver
|
- type: ExtensionCableReceiver
|
||||||
- type: ParticleAcceleratorControlBox
|
|
||||||
- type: Construction
|
- type: Construction
|
||||||
graph: ParticleAcceleratorControlBox
|
graph: ParticleAcceleratorControlBox
|
||||||
node: completed
|
|
||||||
- type: ActivatableUI
|
- type: ActivatableUI
|
||||||
key: enum.ParticleAcceleratorControlBoxUiKey.Key
|
key: enum.ParticleAcceleratorControlBoxUiKey.Key
|
||||||
- type: ActivatableUIRequiresPower
|
- type: ActivatableUIRequiresPower
|
||||||
|
|||||||
@@ -1,76 +1,76 @@
|
|||||||
- type: entity
|
- type: entity
|
||||||
parent: ParticleAcceleratorFinishedPart
|
parent: ParticleAcceleratorFinishedPart
|
||||||
id: ParticleAcceleratorEmitterLeft
|
id: ParticleAcceleratorEmitterPort
|
||||||
name: PA containment emitter L
|
name: PA port containment emitter
|
||||||
description: This launchs the Alpha particles, might not want to stand near this end.
|
description: This launchs the Alpha particles, might not want to stand near this end.
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Structures/Power/Generation/PA/emitter_left.rsi
|
sprite: Structures/Power/Generation/PA/emitter_port.rsi
|
||||||
- type: ParticleAcceleratorEmitter
|
- type: ParticleAcceleratorEmitter
|
||||||
emitterType: Left
|
emitterType: Port
|
||||||
- type: Construction
|
- type: Construction
|
||||||
graph: ParticleAcceleratorEmitterLeft
|
graph: ParticleAcceleratorEmitterPort
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ParticleAcceleratorFinishedPart
|
parent: ParticleAcceleratorFinishedPart
|
||||||
id: ParticleAcceleratorEmitterCenter
|
id: ParticleAcceleratorEmitterFore
|
||||||
name: PA containment emitter C
|
name: PA fore containment emitter
|
||||||
description: This launchs the Alpha particles, might not want to stand near this end.
|
description: This launchs the Alpha particles, might not want to stand near this end.
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Structures/Power/Generation/PA/emitter_center.rsi
|
sprite: Structures/Power/Generation/PA/emitter_fore.rsi
|
||||||
- type: ParticleAcceleratorEmitter
|
- type: ParticleAcceleratorEmitter
|
||||||
emitterType: Center
|
emitterType: Fore
|
||||||
- type: Construction
|
- type: Construction
|
||||||
graph: ParticleAcceleratorEmitterCenter
|
graph: ParticleAcceleratorEmitterFore
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ParticleAcceleratorFinishedPart
|
parent: ParticleAcceleratorFinishedPart
|
||||||
id: ParticleAcceleratorEmitterRight
|
id: ParticleAcceleratorEmitterStarboard
|
||||||
name: PA containment emitter R
|
name: PA starboard containment emitter
|
||||||
description: This launchs the Alpha particles, might not want to stand near this end.
|
description: This launchs the Alpha particles, might not want to stand near this end.
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Structures/Power/Generation/PA/emitter_right.rsi
|
sprite: Structures/Power/Generation/PA/emitter_starboard.rsi
|
||||||
- type: ParticleAcceleratorEmitter
|
- type: ParticleAcceleratorEmitter
|
||||||
emitterType: Right
|
emitterType: Starboard
|
||||||
- type: Construction
|
- type: Construction
|
||||||
graph: ParticleAcceleratorEmitterRight
|
graph: ParticleAcceleratorEmitterStarboard
|
||||||
|
|
||||||
# Unfinished
|
# Unfinished
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ParticleAcceleratorUnfinishedBase
|
parent: ParticleAcceleratorUnfinishedBase
|
||||||
id: ParticleAcceleratorEmitterLeftUnfinished
|
id: ParticleAcceleratorEmitterPortUnfinished
|
||||||
name: PA containment emitter L
|
name: PA port containment emitter
|
||||||
suffix: Unfinished, Left
|
suffix: Unfinished, Port
|
||||||
description: This launchs the Alpha particles, might not want to stand near this end. It looks unfinished.
|
description: This launchs the Alpha particles, might not want to stand near this end. It looks unfinished.
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Structures/Power/Generation/PA/emitter_left.rsi
|
sprite: Structures/Power/Generation/PA/emitter_port.rsi
|
||||||
- type: Construction
|
- type: Construction
|
||||||
graph: ParticleAcceleratorEmitterLeft
|
graph: ParticleAcceleratorEmitterPort
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ParticleAcceleratorUnfinishedBase
|
parent: ParticleAcceleratorUnfinishedBase
|
||||||
id: ParticleAcceleratorEmitterCenterUnfinished
|
id: ParticleAcceleratorEmitterForeUnfinished
|
||||||
name: PA containment emitter C
|
name: PA fore containment emitter
|
||||||
suffix: Unfinished
|
suffix: Unfinished, Fore
|
||||||
description: This launchs the Alpha particles, might not want to stand near this end. It looks unfinished.
|
description: This launchs the Alpha particles, might not want to stand near this end. It looks unfinished.
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Structures/Power/Generation/PA/emitter_center.rsi
|
sprite: Structures/Power/Generation/PA/emitter_fore.rsi
|
||||||
- type: Construction
|
- type: Construction
|
||||||
graph: ParticleAcceleratorEmitterCenter
|
graph: ParticleAcceleratorEmitterFore
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
parent: ParticleAcceleratorUnfinishedBase
|
parent: ParticleAcceleratorUnfinishedBase
|
||||||
id: ParticleAcceleratorEmitterRightUnfinished
|
id: ParticleAcceleratorEmitterStarboardUnfinished
|
||||||
name: PA containment emitter R
|
name: PA starboard containment emitter
|
||||||
suffix: Unfinished
|
suffix: Unfinished, Starboard
|
||||||
description: This launchs the Alpha particles, might not want to stand near this end. It looks unfinished.
|
description: This launchs the Alpha particles, might not want to stand near this end. It looks unfinished.
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Structures/Power/Generation/PA/emitter_right.rsi
|
sprite: Structures/Power/Generation/PA/emitter_starboard.rsi
|
||||||
- type: Construction
|
- type: Construction
|
||||||
graph: ParticleAcceleratorEmitterRight
|
graph: ParticleAcceleratorEmitterStarboard
|
||||||
|
|||||||
@@ -34,6 +34,8 @@
|
|||||||
- type: ParticleProjectile
|
- type: ParticleProjectile
|
||||||
- type: SinguloFood
|
- type: SinguloFood
|
||||||
# Energy is setup by the PA particle fire function.
|
# Energy is setup by the PA particle fire function.
|
||||||
|
- type: TimedDespawn
|
||||||
|
lifetime: 3.0
|
||||||
- type: Appearance
|
- type: Appearance
|
||||||
- type: GenericVisualizer
|
- type: GenericVisualizer
|
||||||
visuals:
|
visuals:
|
||||||
|
|||||||
@@ -29,4 +29,3 @@
|
|||||||
sprite: Structures/Power/Generation/PA/power_box.rsi
|
sprite: Structures/Power/Generation/PA/power_box.rsi
|
||||||
- type: Construction
|
- type: Construction
|
||||||
graph: ParticleAcceleratorPowerBox
|
graph: ParticleAcceleratorPowerBox
|
||||||
|
|
||||||
|
|||||||
@@ -197,11 +197,11 @@
|
|||||||
doAfter: 0.5
|
doAfter: 0.5
|
||||||
|
|
||||||
- type: constructionGraph
|
- type: constructionGraph
|
||||||
id: ParticleAcceleratorEmitterLeft
|
id: ParticleAcceleratorEmitterPort
|
||||||
start: start
|
start: start
|
||||||
graph:
|
graph:
|
||||||
- node: start
|
- node: start
|
||||||
entity: ParticleAcceleratorEmitterLeftUnfinished
|
entity: ParticleAcceleratorEmitterPortUnfinished
|
||||||
actions:
|
actions:
|
||||||
- !type:AppearanceChange
|
- !type:AppearanceChange
|
||||||
edges:
|
edges:
|
||||||
@@ -213,7 +213,7 @@
|
|||||||
doAfter: 0.5
|
doAfter: 0.5
|
||||||
|
|
||||||
- node: wired
|
- node: wired
|
||||||
entity: ParticleAcceleratorEmitterLeftUnfinished
|
entity: ParticleAcceleratorEmitterPortUnfinished
|
||||||
actions:
|
actions:
|
||||||
- !type:AppearanceChange
|
- !type:AppearanceChange
|
||||||
edges:
|
edges:
|
||||||
@@ -236,7 +236,7 @@
|
|||||||
doAfter: 0.5
|
doAfter: 0.5
|
||||||
|
|
||||||
- node: completed
|
- node: completed
|
||||||
entity: ParticleAcceleratorEmitterLeft
|
entity: ParticleAcceleratorEmitterPort
|
||||||
edges:
|
edges:
|
||||||
- to: wired
|
- to: wired
|
||||||
conditions:
|
conditions:
|
||||||
@@ -246,11 +246,11 @@
|
|||||||
doAfter: 0.5
|
doAfter: 0.5
|
||||||
|
|
||||||
- type: constructionGraph
|
- type: constructionGraph
|
||||||
id: ParticleAcceleratorEmitterCenter
|
id: ParticleAcceleratorEmitterFore
|
||||||
start: start
|
start: start
|
||||||
graph:
|
graph:
|
||||||
- node: start
|
- node: start
|
||||||
entity: ParticleAcceleratorEmitterCenterUnfinished
|
entity: ParticleAcceleratorEmitterForeUnfinished
|
||||||
actions:
|
actions:
|
||||||
- !type:AppearanceChange
|
- !type:AppearanceChange
|
||||||
edges:
|
edges:
|
||||||
@@ -262,7 +262,7 @@
|
|||||||
doAfter: 0.5
|
doAfter: 0.5
|
||||||
|
|
||||||
- node: wired
|
- node: wired
|
||||||
entity: ParticleAcceleratorEmitterCenterUnfinished
|
entity: ParticleAcceleratorEmitterForeUnfinished
|
||||||
actions:
|
actions:
|
||||||
- !type:AppearanceChange
|
- !type:AppearanceChange
|
||||||
edges:
|
edges:
|
||||||
@@ -285,7 +285,7 @@
|
|||||||
doAfter: 0.5
|
doAfter: 0.5
|
||||||
|
|
||||||
- node: completed
|
- node: completed
|
||||||
entity: ParticleAcceleratorEmitterCenter
|
entity: ParticleAcceleratorEmitterFore
|
||||||
edges:
|
edges:
|
||||||
- to: wired
|
- to: wired
|
||||||
conditions:
|
conditions:
|
||||||
@@ -295,11 +295,11 @@
|
|||||||
doAfter: 0.5
|
doAfter: 0.5
|
||||||
|
|
||||||
- type: constructionGraph
|
- type: constructionGraph
|
||||||
id: ParticleAcceleratorEmitterRight
|
id: ParticleAcceleratorEmitterStarboard
|
||||||
start: start
|
start: start
|
||||||
graph:
|
graph:
|
||||||
- node: start
|
- node: start
|
||||||
entity: ParticleAcceleratorEmitterRightUnfinished
|
entity: ParticleAcceleratorEmitterStarboardUnfinished
|
||||||
actions:
|
actions:
|
||||||
- !type:AppearanceChange
|
- !type:AppearanceChange
|
||||||
edges:
|
edges:
|
||||||
@@ -311,7 +311,7 @@
|
|||||||
doAfter: 0.5
|
doAfter: 0.5
|
||||||
|
|
||||||
- node: wired
|
- node: wired
|
||||||
entity: ParticleAcceleratorEmitterRightUnfinished
|
entity: ParticleAcceleratorEmitterStarboardUnfinished
|
||||||
actions:
|
actions:
|
||||||
- !type:AppearanceChange
|
- !type:AppearanceChange
|
||||||
edges:
|
edges:
|
||||||
@@ -334,7 +334,7 @@
|
|||||||
doAfter: 0.5
|
doAfter: 0.5
|
||||||
|
|
||||||
- node: completed
|
- node: completed
|
||||||
entity: ParticleAcceleratorEmitterRight
|
entity: ParticleAcceleratorEmitterStarboard
|
||||||
edges:
|
edges:
|
||||||
- to: wired
|
- to: wired
|
||||||
conditions:
|
conditions:
|
||||||
|
|||||||
@@ -75,3 +75,12 @@
|
|||||||
wires:
|
wires:
|
||||||
- !type:PowerWireAction
|
- !type:PowerWireAction
|
||||||
- !type:CryoPodEjectLockWireAction
|
- !type:CryoPodEjectLockWireAction
|
||||||
|
|
||||||
|
- type: wireLayout
|
||||||
|
id: ParticleAccelerator
|
||||||
|
dummyWires: 1
|
||||||
|
wires:
|
||||||
|
- !type:ParticleAcceleratorKeyboardWireAction
|
||||||
|
- !type:ParticleAcceleratorLimiterWireAction
|
||||||
|
- !type:ParticleAcceleratorPowerWireAction
|
||||||
|
- !type:ParticleAcceleratorStrengthWireAction
|
||||||
|
|||||||
@@ -48,9 +48,9 @@ They connect to HV cables and generate power from nearby radiation sources when
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box>
|
<Box>
|
||||||
<GuideEntityEmbed Entity="ParticleAcceleratorEmitterLeft" Caption="Emitter L"/>
|
<GuideEntityEmbed Entity="ParticleAcceleratorEmitterStarboard" Caption="Starboard Emitter"/>
|
||||||
<GuideEntityEmbed Entity="ParticleAcceleratorEmitterCenter" Caption="Emitter C"/>
|
<GuideEntityEmbed Entity="ParticleAcceleratorEmitterFore" Caption="Fore Emitter"/>
|
||||||
<GuideEntityEmbed Entity="ParticleAcceleratorEmitterRight" Caption="Emitter R"/>
|
<GuideEntityEmbed Entity="ParticleAcceleratorEmitterPort" Caption="Port Emitter"/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
The Particle Accelerator (PA) is a multi-tile structure that launches acclerated particles from its emitters. Its emitters should always face the gravitational singularity generator.
|
The Particle Accelerator (PA) is a multi-tile structure that launches acclerated particles from its emitters. Its emitters should always face the gravitational singularity generator.
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 232 B After Width: | Height: | Size: 232 B |
|
Before Width: | Height: | Size: 359 B After Width: | Height: | Size: 359 B |
|
Before Width: | Height: | Size: 402 B After Width: | Height: | Size: 402 B |
|
Before Width: | Height: | Size: 385 B After Width: | Height: | Size: 385 B |
|
Before Width: | Height: | Size: 368 B After Width: | Height: | Size: 368 B |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 232 B After Width: | Height: | Size: 232 B |
|
Before Width: | Height: | Size: 359 B After Width: | Height: | Size: 359 B |
|
Before Width: | Height: | Size: 401 B After Width: | Height: | Size: 401 B |
|
Before Width: | Height: | Size: 383 B After Width: | Height: | Size: 383 B |
|
Before Width: | Height: | Size: 368 B After Width: | Height: | Size: 368 B |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 232 B After Width: | Height: | Size: 232 B |
|
Before Width: | Height: | Size: 359 B After Width: | Height: | Size: 359 B |
|
Before Width: | Height: | Size: 402 B After Width: | Height: | Size: 402 B |
|
Before Width: | Height: | Size: 385 B After Width: | Height: | Size: 385 B |
|
Before Width: | Height: | Size: 369 B After Width: | Height: | Size: 369 B |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
@@ -60,3 +60,17 @@ OrGate: null
|
|||||||
IHSVoidsuit: null
|
IHSVoidsuit: null
|
||||||
ClothingHeadHelmetIHSVoidHelm: null
|
ClothingHeadHelmetIHSVoidHelm: null
|
||||||
ClothingHandsGlovesIhscombat: null
|
ClothingHandsGlovesIhscombat: null
|
||||||
|
|
||||||
|
# 2023-06-02
|
||||||
|
# Yes, this is right. They were, in fact, reversed because the default orientation of the particle accelerator was _down_ relative to the screen.
|
||||||
|
# This resulted in the parts being named assuming that the person building the accelerator treated it like a rocket with the particles coming out the _back_.
|
||||||
|
# As this was confusing they were converted to nautical orientation with forward being towards the emitters.
|
||||||
|
MachineParticleAcceleratorEmitterCenterCircuitboard: MachineParticleAcceleratorEmitterForeCircuitboard
|
||||||
|
MachineParticleAcceleratorEmitterLeftCircuitboard: MachineParticleAcceleratorEmitterStarboardCircuitboard
|
||||||
|
MachineParticleAcceleratorEmitterRightCircuitboard: MachineParticleAcceleratorEmitterPortCircuitboard
|
||||||
|
ParticleAcceleratorEmitterCenter: ParticleAcceleratorEmitterFore
|
||||||
|
ParticleAcceleratorEmitterCenterUnfinished: ParticleAcceleratorEmitterForeUnfinished
|
||||||
|
ParticleAcceleratorEmitterLeft: ParticleAcceleratorEmitterStarboard
|
||||||
|
ParticleAcceleratorEmitterLeftUnfinished: ParticleAcceleratorEmitterStarboardUnfinished
|
||||||
|
ParticleAcceleratorEmitterRight: ParticleAcceleratorEmitterPort
|
||||||
|
ParticleAcceleratorEmitterRightUnfinished: ParticleAcceleratorEmitterPortUnfinished
|
||||||
|
|||||||