Electrolysis and Centrifuge (#22517)

* electrolysis and centrifuge

* sprote

* final

* bomp!

* COUGH COUGH SPROTE

* boarsd
This commit is contained in:
Nemanja
2023-12-15 04:52:46 -05:00
committed by GitHub
parent 0349c53d0c
commit 2455980090
27 changed files with 478 additions and 4 deletions

View File

@@ -0,0 +1,9 @@
using Content.Shared.Chemistry.EntitySystems;
namespace Content.Client.Chemistry.EntitySystems;
/// <inheritdoc/>
public sealed class SolutionContainerMixerSystem : SharedSolutionContainerMixerSystem
{
}

View File

@@ -0,0 +1,29 @@
using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.EntitySystems;
namespace Content.Server.Chemistry.EntitySystems;
/// <inheritdoc/>
public sealed class SolutionContainerMixerSystem : SharedSolutionContainerMixerSystem
{
/// <inheritdoc/>
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<SolutionContainerMixerComponent, PowerChangedEvent>(OnPowerChanged);
}
private void OnPowerChanged(Entity<SolutionContainerMixerComponent> ent, ref PowerChangedEvent args)
{
if (!args.Powered)
StopMix(ent);
}
protected override bool HasPower(Entity<SolutionContainerMixerComponent> entity)
{
return this.IsPowered(entity, EntityManager);
}
}

View File

@@ -0,0 +1,44 @@
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Chemistry.Reaction;
using Robust.Shared.Audio;
using Robust.Shared.Audio.Components;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
namespace Content.Shared.Chemistry.Components;
/// <summary>
/// This is used for an entity that uses <see cref="ReactionMixerComponent"/> to mix any container with a solution after a period of time.
/// </summary>
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
[Access(typeof(SharedSolutionContainerMixerSystem))]
public sealed partial class SolutionContainerMixerComponent : Component
{
[DataField, ViewVariables(VVAccess.ReadWrite)]
public string ContainerId = "mixer";
[DataField, AutoNetworkedField]
public bool Mixing;
/// <summary>
/// How long it takes for mixing to occurs.
/// </summary>
[DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
public TimeSpan MixDuration;
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite), AutoNetworkedField]
public TimeSpan MixTimeEnd;
[DataField, AutoNetworkedField]
public SoundSpecifier? MixingSound;
[DataField]
public Entity<AudioComponent>? MixingSoundEntity;
}
[Serializable, NetSerializable]
public enum SolutionContainerMixerVisuals : byte
{
Mixing
}

View File

@@ -0,0 +1,125 @@
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Reaction;
using Content.Shared.Interaction;
using Content.Shared.Popups;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Containers;
using Robust.Shared.Network;
using Robust.Shared.Timing;
namespace Content.Shared.Chemistry.EntitySystems;
/// <summary>
/// This handles <see cref="SolutionContainerMixerComponent"/>
/// </summary>
public abstract class SharedSolutionContainerMixerSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly INetManager _net = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly ChemicalReactionSystem _chemicalReaction = default!;
[Dependency] private readonly SharedContainerSystem _container = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly SolutionContainerSystem _solution = default!;
/// <inheritdoc/>
public override void Initialize()
{
SubscribeLocalEvent<SolutionContainerMixerComponent, ActivateInWorldEvent>(OnActivateInWorld);
SubscribeLocalEvent<SolutionContainerMixerComponent, ContainerIsRemovingAttemptEvent>(OnRemoveAttempt);
}
private void OnActivateInWorld(Entity<SolutionContainerMixerComponent> entity, ref ActivateInWorldEvent args)
{
TryStartMix(entity, args.User);
}
private void OnRemoveAttempt(Entity<SolutionContainerMixerComponent> ent, ref ContainerIsRemovingAttemptEvent args)
{
if (args.Container.ID == ent.Comp.ContainerId && ent.Comp.Mixing)
args.Cancel();
}
protected virtual bool HasPower(Entity<SolutionContainerMixerComponent> entity)
{
return true;
}
public void TryStartMix(Entity<SolutionContainerMixerComponent> entity, EntityUid? user)
{
var (uid, comp) = entity;
if (comp.Mixing)
return;
if (!HasPower(entity))
{
if (user != null)
_popup.PopupClient(Loc.GetString("solution-container-mixer-no-power"), entity, user.Value);
return;
}
if (!_container.TryGetContainer(uid, comp.ContainerId, out var container) || container.Count == 0)
{
if (user != null)
_popup.PopupClient(Loc.GetString("solution-container-mixer-popup-nothing-to-mix"), entity, user.Value);
return;
}
comp.Mixing = true;
if (_net.IsServer)
comp.MixingSoundEntity = _audio.PlayPvs(comp.MixingSound, entity, comp.MixingSound?.Params.WithLoop(true));
comp.MixTimeEnd = _timing.CurTime + comp.MixDuration;
_appearance.SetData(entity, SolutionContainerMixerVisuals.Mixing, true);
Dirty(uid, comp);
}
public void StopMix(Entity<SolutionContainerMixerComponent> entity)
{
var (uid, comp) = entity;
if (!comp.Mixing)
return;
_audio.Stop(comp.MixingSoundEntity);
_appearance.SetData(entity, SolutionContainerMixerVisuals.Mixing, false);
comp.Mixing = false;
comp.MixingSoundEntity = null;
Dirty(uid, comp);
}
public void FinishMix(Entity<SolutionContainerMixerComponent> entity)
{
var (uid, comp) = entity;
if (!comp.Mixing)
return;
StopMix(entity);
if (!TryComp<ReactionMixerComponent>(entity, out var reactionMixer)
|| !_container.TryGetContainer(uid, comp.ContainerId, out var container))
return;
foreach (var ent in container.ContainedEntities)
{
if (!_solution.TryGetFitsInDispenser(ent, out var solution))
continue;
_chemicalReaction.FullyReactSolution(solution, ent, solution.MaxVolume, reactionMixer);
}
}
public override void Update(float frameTime)
{
base.Update(frameTime);
var query = EntityQueryEnumerator<SolutionContainerMixerComponent>();
while (query.MoveNext(out var uid, out var comp))
{
if (!comp.Mixing)
continue;
if (_timing.CurTime < comp.MixTimeEnd)
continue;
FinishMix((uid, comp));
}
}
}

View File

@@ -112,7 +112,8 @@ namespace Content.Shared.Chemistry.Reaction
{
lowestUnitReactions = FixedPoint2.Zero;
return false;
} else if(solution.Temperature > reaction.MaximumTemperature)
}
if (solution.Temperature > reaction.MaximumTemperature)
{
lowestUnitReactions = FixedPoint2.Zero;
return false;
@@ -126,7 +127,7 @@ namespace Content.Shared.Chemistry.Reaction
}
var attempt = new ReactionAttemptEvent(reaction, solution);
RaiseLocalEvent(owner, attempt, false);
RaiseLocalEvent(owner, attempt);
if (attempt.Cancelled)
{
lowestUnitReactions = FixedPoint2.Zero;

View File

@@ -0,0 +1,14 @@
using Robust.Shared.Prototypes;
namespace Content.Shared.Chemistry.Reaction;
/// <summary>
/// This is a prototype for a method of chemical mixing, to be used by <see cref="ReactionMixerComponent"/>
/// </summary>
[Prototype("mixingCategory")]
public sealed partial class MixingCategoryPrototype : IPrototype
{
/// <inheritdoc/>
[IdDataField]
public string ID { get; } = default!;
}

View File

@@ -1,4 +1,5 @@
using Content.Shared.Chemistry.Components;
using Robust.Shared.Prototypes;
namespace Content.Shared.Chemistry.Reaction;
@@ -10,7 +11,7 @@ public sealed partial class ReactionMixerComponent : Component
/// </summary>
[ViewVariables]
[DataField]
public List<string> ReactionTypes = default!;
public List<ProtoId<MixingCategoryPrototype>> ReactionTypes = default!;
/// <summary>
/// A string which identifies the string to be sent when successfully mixing a solution

View File

@@ -48,7 +48,7 @@ namespace Content.Shared.Chemistry.Reaction
/// The required mixing categories for an entity to mix the solution with for the reaction to occur
/// </summary>
[DataField("requiredMixerCategories")]
public List<string>? MixingCategories = null;
public List<ProtoId<MixingCategoryPrototype>>? MixingCategories;
/// <summary>
/// Reagents created when the reaction occurs.

View File

@@ -8,6 +8,16 @@
copyright: "Created by dotY21."
source: "https://freesound.org/people/dotY21/sounds/330726/"
- files: ["buzz_loop.ogg"]
license: "CC0-1.0"
copyright: "Created by Duasun, converted to OGG by EmoGarbage404 (github)."
source: "https://freesound.org/people/Duasun/sounds/712127/"
- files: ["spinning.ogg"]
license: "CC0-1.0"
copyright: "Created by MrLindstrom, modified and converted to OGG by EmoGarbage404 (github)."
source: "https://freesound.org/people/MrLindstrom/sounds/543964/"
- files: ["vending_restock_start.ogg"]
license: "CC0-1.0"
copyright: "https://freesound.org/people/Defaultv/"

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,3 @@
solution-container-mixer-activate = Activate
solution-container-mixer-no-power = No power!
solution-container-mixer-popup-nothing-to-mix = Nothing inside!

View File

@@ -0,0 +1,8 @@
- type: mixingCategory
id: Centrifuge
- type: mixingCategory
id: Electrolysis
- type: mixingCategory
id: Holy

View File

@@ -808,6 +808,36 @@
Cable: 3
Steel: 2
- type: entity
id: ElectrolysisUnitMachineCircuitboard
parent: BaseMachineCircuitboard
name: electrolysis unit machine board
description: A machine printed circuit board for an electrolysis unit.
components:
- type: Sprite
state: medical
- type: MachineBoard
prototype: MachineElectrolysisUnit
requirements:
Capacitor: 2
materialRequirements:
Cable: 1
- type: entity
id: CentrifugeMachineCircuitboard
parent: BaseMachineCircuitboard
name: centrifuge machine board
description: A machine printed circuit board for a centrifuge.
components:
- type: Sprite
state: medical
- type: MachineBoard
prototype: MachineCentrifuge
requirements:
Manipulator: 1
materialRequirements:
Steel: 1
- type: entity
id: MaterialReclaimerMachineCircuitboard
parent: BaseMachineCircuitboard

View File

@@ -0,0 +1,119 @@
- type: entity
id: BaseTabletopChemicalMachine
parent: [ BaseMachinePowered, ConstructibleMachine ]
abstract: true
components:
- type: Transform
anchored: true
- type: SolutionContainerMixer
- type: ReactionMixer
- type: Sprite
drawdepth: SmallObjects
snapCardinals: true
- type: Appearance
- type: Physics
- type: Fixtures
fixtures:
fix1:
shape:
!type:PhysShapeAabb
bounds: "-0.17,0,0.20,0.4"
mask:
- TabletopMachineMask
layer:
- TabletopMachineLayer
- type: ItemSlots
slots:
mixer:
whitelist:
components:
- FitsInDispenser
- type: Machine
- type: Wires
layoutId: chem
- type: WiresPanel
- type: WiresVisuals
- type: ContainerContainer
containers:
mixer: !type:ContainerSlot
machine_board: !type:Container
machine_parts: !type:Container
- type: entity
id: MachineElectrolysisUnit
parent: BaseTabletopChemicalMachine
name: electrolysis unit
description: The latest in medicinal electrocution technology.
components:
- type: SolutionContainerMixer
mixDuration: 5
mixingSound:
path: /Audio/Machines/buzz_loop.ogg
params:
volume: -5
- type: ReactionMixer
reactionTypes:
- Electrolysis
- type: Sprite
sprite: Structures/Machines/Medical/electrolysis.rsi
offset: "0.0,0.4"
layers:
- state: base
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
visible: false
- state: unshaded
map: ["enum.PowerDeviceVisualLayers.Powered"]
shader: unshaded
- type: GenericVisualizer
visuals:
enum.SolutionContainerMixerVisuals.Mixing:
enum.PowerDeviceVisualLayers.Powered:
True: {state: "spinning"}
False: {state: "unshaded"}
enum.PowerDeviceVisuals.Powered:
enum.PowerDeviceVisualLayers.Powered:
True: { visible: True }
False: { visible: False }
- type: Machine
board: ElectrolysisUnitMachineCircuitboard
- type: entity
id: MachineCentrifuge
parent: BaseTabletopChemicalMachine
name: tabletop centrifuge
description: Around and around it goes...
components:
- type: SolutionContainerMixer
mixDuration: 10
mixingSound:
path: /Audio/Machines/spinning.ogg
params:
volume: -4
- type: ReactionMixer
reactionTypes:
- Centrifuge
- type: Sprite
sprite: Structures/Machines/Medical/centrifuge.rsi
offset: "0.0,0.4"
layers:
- state: base
map: ["beyblade"]
- state: panel
map: ["enum.WiresVisualLayers.MaintenancePanel"]
visible: false
- state: unshaded
map: ["enum.PowerDeviceVisualLayers.Powered"]
shader: unshaded
- type: GenericVisualizer
visuals:
enum.SolutionContainerMixerVisuals.Mixing:
beyblade:
True: {state: "base-spinning"}
False: {state: "base"}
enum.PowerDeviceVisuals.Powered:
enum.PowerDeviceVisualLayers.Powered:
True: { visible: True }
False: { visible: False }
- type: Machine
board: CentrifugeMachineCircuitboard

View File

@@ -308,6 +308,8 @@
idleState: icon
runningState: building
staticRecipes:
- ElectrolysisUnitMachineCircuitboard
- CentrifugeMachineCircuitboard
- CondenserMachineCircuitBoard
dynamicRecipes:
- ThermomachineFreezerMachineCircuitBoard

View File

@@ -360,6 +360,22 @@
Glass: 900
Gold: 100
- type: latheRecipe
id: ElectrolysisUnitMachineCircuitboard
result: ElectrolysisUnitMachineCircuitboard
completetime: 4
materials:
Steel: 100
Glass: 900
- type: latheRecipe
id: CentrifugeMachineCircuitboard
result: CentrifugeMachineCircuitboard
completetime: 4
materials:
Steel: 100
Glass: 900
- type: latheRecipe
id: MaterialReclaimerMachineCircuitboard
result: MaterialReclaimerMachineCircuitboard

Binary file not shown.

After

Width:  |  Height:  |  Size: 810 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 626 B

View File

@@ -0,0 +1,31 @@
{
"version": 1,
"license": "CC0-1.0",
"copyright": "Adapted from CEV-Eris by EmoGarbage404 (github) for Space Station 14.",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "base"
},
{
"name": "base-spinning",
"delays":
[
[
0.1,
0.1,
0.1
]
]
},
{
"name": "panel"
},
{
"name": "unshaded"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 670 B

View File

@@ -0,0 +1,32 @@
{
"version": 1,
"license": "CC0-1.0",
"copyright": "Adapted from CEV-Eris by EmoGarbage404 (github) for Space Station 14.",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "base"
},
{
"name": "spinning",
"delays":
[
[
0.25,
0.25,
0.25,
0.25
]
]
},
{
"name": "panel"
},
{
"name": "unshaded"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 194 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 B