Add Paper Centrifuge (#42040)
* init * sound * sprite, half functional construction * proper recipe * oops * loop sound * inhands * review * review squared
@@ -1,4 +1,5 @@
|
||||
using Content.Shared.DoAfter;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization;
|
||||
@@ -20,17 +21,34 @@ public sealed partial class ReactionMixerComponent : Component
|
||||
[DataField, AutoNetworkedField]
|
||||
public LocId MixMessage = "default-mixing-success";
|
||||
|
||||
/// <summary>
|
||||
/// The sound to play when mixing.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public SoundSpecifier? MixingSound;
|
||||
|
||||
/// <summary>
|
||||
/// Defines if interacting is enough to mix with this component.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public bool MixOnInteract = true;
|
||||
public ReactionMixerType MixerType = ReactionMixerType.Machine;
|
||||
|
||||
/// <summary>
|
||||
/// How long it takes to mix with this.
|
||||
/// </summary>
|
||||
[DataField, AutoNetworkedField]
|
||||
public TimeSpan TimeToMix = TimeSpan.Zero;
|
||||
|
||||
// Used to cancel the played sound.
|
||||
public EntityUid? AudioStream;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum ReactionMixerType
|
||||
{
|
||||
None, // Mixing is handled by its own system.
|
||||
Machine, // Mixing is handled via interaction.
|
||||
Handheld // Mixing is handled via using in hand
|
||||
}
|
||||
|
||||
[ByRefEvent]
|
||||
|
||||
@@ -4,7 +4,10 @@ using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Nutrition.EntitySystems;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Popups;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Network;
|
||||
|
||||
namespace Content.Shared.Chemistry.Reaction;
|
||||
|
||||
@@ -13,24 +16,64 @@ public sealed partial class ReactionMixerSystem : EntitySystem
|
||||
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!;
|
||||
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly INetManager _net = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<ReactionMixerComponent, UseInHandEvent>(OnUseInHand);
|
||||
SubscribeLocalEvent<ReactionMixerComponent, AfterInteractEvent>(OnAfterInteract, before: [typeof(IngestionSystem)]);
|
||||
SubscribeLocalEvent<ReactionMixerComponent, ShakeEvent>(OnShake);
|
||||
SubscribeLocalEvent<ReactionMixerComponent, ReactionMixDoAfterEvent>(OnDoAfter);
|
||||
}
|
||||
|
||||
private void OnUseInHand(Entity<ReactionMixerComponent> ent, ref UseInHandEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
if (ent.Comp.MixerType != ReactionMixerType.Handheld)
|
||||
return;
|
||||
|
||||
args.Handled = true;
|
||||
|
||||
if (!CanMix(ent.AsNullable(), ent))
|
||||
return;
|
||||
|
||||
if (_net.IsServer) // Cannot cancel predicted audio.
|
||||
ent.Comp.AudioStream = _audio.PlayPvs(ent.Comp.MixingSound, ent)?.Entity;
|
||||
|
||||
var doAfterArgs = new DoAfterArgs(EntityManager,
|
||||
args.User,
|
||||
ent.Comp.TimeToMix,
|
||||
new ReactionMixDoAfterEvent(),
|
||||
ent,
|
||||
ent,
|
||||
ent)
|
||||
{
|
||||
NeedHand = true,
|
||||
BreakOnDamage = true,
|
||||
BreakOnDropItem = true,
|
||||
BreakOnHandChange = true,
|
||||
BreakOnMove = true
|
||||
};
|
||||
|
||||
_doAfter.TryStartDoAfter(doAfterArgs);
|
||||
}
|
||||
|
||||
private void OnAfterInteract(Entity<ReactionMixerComponent> ent, ref AfterInteractEvent args)
|
||||
{
|
||||
if (!args.Target.HasValue || !args.CanReach || !ent.Comp.MixOnInteract)
|
||||
if (!args.Target.HasValue || !args.CanReach || ent.Comp.MixerType != ReactionMixerType.Machine)
|
||||
return;
|
||||
|
||||
if (!CanMix(ent.AsNullable(), args.Target.Value))
|
||||
return;
|
||||
|
||||
if (_net.IsServer) // Cannot cancel predicted audio.
|
||||
ent.Comp.AudioStream = _audio.PlayPvs(ent.Comp.MixingSound, ent)?.Entity;
|
||||
|
||||
var doAfterArgs = new DoAfterArgs(EntityManager, args.User, ent.Comp.TimeToMix, new ReactionMixDoAfterEvent(), ent, args.Target.Value, ent);
|
||||
|
||||
_doAfter.TryStartDoAfter(doAfterArgs);
|
||||
@@ -39,6 +82,11 @@ public sealed partial class ReactionMixerSystem : EntitySystem
|
||||
|
||||
private void OnDoAfter(Entity<ReactionMixerComponent> ent, ref ReactionMixDoAfterEvent args)
|
||||
{
|
||||
ent.Comp.AudioStream = _audio.Stop(ent.Comp.AudioStream);
|
||||
|
||||
if (args.Cancelled)
|
||||
return;
|
||||
|
||||
if (args.Target == null)
|
||||
return;
|
||||
|
||||
@@ -46,8 +94,7 @@ public sealed partial class ReactionMixerSystem : EntitySystem
|
||||
return;
|
||||
|
||||
_popup.PopupClient(
|
||||
Loc.GetString(
|
||||
ent.Comp.MixMessage,
|
||||
Loc.GetString(ent.Comp.MixMessage,
|
||||
("mixed", Identity.Entity(args.Target.Value, EntityManager)),
|
||||
("mixer", Identity.Entity(ent.Owner, EntityManager))),
|
||||
args.User,
|
||||
@@ -69,14 +116,18 @@ public sealed partial class ReactionMixerSystem : EntitySystem
|
||||
if (!Resolve(ent, ref ent.Comp, false)) // The used entity needs the component to be able to mix a solution
|
||||
return false;
|
||||
|
||||
if (!_solutionContainer.TryGetMixableSolution(target, out _, out var mixableSolution))
|
||||
return false;
|
||||
|
||||
// Can't mix nothing.
|
||||
if (mixableSolution.Volume <= 0)
|
||||
return false;
|
||||
|
||||
var mixAttemptEvent = new MixingAttemptEvent(ent);
|
||||
RaiseLocalEvent(ent, ref mixAttemptEvent);
|
||||
if (mixAttemptEvent.Cancelled)
|
||||
return false;
|
||||
|
||||
if (!_solutionContainer.TryGetMixableSolution(target, out _, out _))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
copyright: "Taken from FM Synthesis on freesound.org"
|
||||
source: "https://freesound.org/people/FreqMan/sounds/32683/"
|
||||
|
||||
- files: ["paper_centrifuge.ogg"]
|
||||
license: "CC-BY-4.0"
|
||||
copyright: "Taken from temawas on freesound. Cut, converted to .ogg"
|
||||
source: "https://freesound.org/people/temawas/sounds/179248/"
|
||||
|
||||
- files: ["jet_injector.ogg"]
|
||||
license: "CC-BY-3.0"
|
||||
copyright: "Orginal audio by EminYILDIRIM -- https://freesound.org/s/548009/ -- License: Attribution 4.0, 2imitk -- https://freesound.org/s/279044/ -- License: Attribution 3.0 and brunoboselli -- https://freesound.org/s/457294/ -- License: Creative Commons 0 -- https://freesound.org/s/460586/ -- License: Attribution NonCommercial 4.0, modified by Princess-Cheeseballs (GitHub)"
|
||||
|
||||
BIN
Resources/Audio/Items/Medical/paper_centrifuge.ogg
Normal file
@@ -14,4 +14,5 @@ mixing-verb-shake = shake
|
||||
default-mixing-success = You mix the {$mixed} with the {$mixer}
|
||||
bible-mixing-success = You bless the {$mixed} with the {$mixer}
|
||||
spoon-mixing-success = You stir the {$mixed} with the {$mixer}
|
||||
handheld-centrifuge-success = You seperate chemicals in the {$mixed}
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ construction-graph-tag-apron = an apron
|
||||
construction-graph-tag-utility-belt = a utility belt
|
||||
soil-construction-graph-any-mushroom = any mushroom
|
||||
construction-graph-tag-mop-basic = mop
|
||||
construction-graph-tag-paper = office paper
|
||||
construction-graph-tag-core-pinpointer-piece = piece of core pinpointer
|
||||
|
||||
# toys
|
||||
@@ -153,3 +154,6 @@ construction-graph-tag-spationaut-hardsuit = spationaut hardsuit
|
||||
|
||||
# clothing
|
||||
construction-graph-tag-backpack = backpack
|
||||
|
||||
# chemistry
|
||||
construction-graph-tag-centrifuge-compatible = centrifugable container
|
||||
|
||||
@@ -131,7 +131,7 @@
|
||||
Steel: 50
|
||||
- type: Shakeable
|
||||
- type: ReactionMixer
|
||||
mixOnInteract: false
|
||||
mixerType: None
|
||||
reactionTypes:
|
||||
- Shake
|
||||
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
- type: entity
|
||||
abstract: true
|
||||
parent: BaseItem
|
||||
id: BaseHandheldMixer
|
||||
components:
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
mixer:
|
||||
maxVol: 10
|
||||
- type: MixableSolution
|
||||
solution: mixer
|
||||
- type: RefillableSolution
|
||||
solution: mixer
|
||||
- type: DrainableSolution
|
||||
solution: mixer
|
||||
- type: ExaminableSolution
|
||||
solution: mixer
|
||||
exactVolume: true
|
||||
- type: DrawableSolution
|
||||
solution: mixer
|
||||
- type: InjectableSolution
|
||||
solution: mixer
|
||||
- type: Spillable
|
||||
solution: mixer
|
||||
- type: SolutionTransfer
|
||||
- type: SolutionItemStatus
|
||||
solution: mixer
|
||||
- type: Appearance
|
||||
- type: DnaSubstanceTrace
|
||||
- type: ReactionMixer
|
||||
|
||||
- type: entity
|
||||
parent: BaseHandheldMixer
|
||||
id: HandheldMixerPaperCentrifuge
|
||||
name: paper centrifuge
|
||||
description: A small portable makeshift centrifuge. Works by rotating the paper sheets when its cords are pulled.
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: Objects/Specific/Chemistry/paper_centrifuge.rsi
|
||||
layers:
|
||||
- state: icon
|
||||
- state: fill-1
|
||||
map: [ "enum.SolutionContainerLayers.Fill" ]
|
||||
visible: false
|
||||
- type: SolutionContainerVisuals
|
||||
maxFillLevels: 4
|
||||
fillBaseName: fill-
|
||||
- type: Construction
|
||||
graph: MakeshiftCentrifuge
|
||||
node: makeshiftCentrifuge
|
||||
- type: ReactionMixer
|
||||
reactionTypes:
|
||||
- Centrifuge
|
||||
mixerType: Handheld
|
||||
mixMessage: handheld-centrifuge-success
|
||||
timeToMix: 10
|
||||
mixingSound: !type:SoundPathSpecifier
|
||||
path: /Audio/Items/Medical/paper_centrifuge.ogg
|
||||
params:
|
||||
loop: true
|
||||
@@ -45,3 +45,11 @@
|
||||
targetNode: random_gate
|
||||
category: construction-category-tools
|
||||
objectType: Item
|
||||
|
||||
- type: construction
|
||||
id: MakeshiftCentrifuge
|
||||
graph: MakeshiftCentrifuge
|
||||
startNode: start
|
||||
targetNode: makeshiftCentrifuge
|
||||
category: construction-category-tools
|
||||
objectType: Item
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
# Mortar
|
||||
- type: constructionGraph
|
||||
id: MakeshiftCentrifuge
|
||||
start: start
|
||||
graph:
|
||||
- node: start
|
||||
edges:
|
||||
- to: makeshiftCentrifuge
|
||||
steps:
|
||||
- material: MetalRod
|
||||
amount: 2
|
||||
- material: Cable
|
||||
amount: 15
|
||||
doAfter: 2
|
||||
- tag: CentrifugeCompatible
|
||||
icon:
|
||||
sprite: Objects/Specific/Chemistry/vial.rsi
|
||||
state: vial
|
||||
name: construction-graph-tag-centrifuge-compatible
|
||||
doAfter: 2
|
||||
- tag: CentrifugeCompatible
|
||||
icon:
|
||||
sprite: Objects/Specific/Chemistry/vial.rsi
|
||||
state: vial
|
||||
name: construction-graph-tag-centrifuge-compatible
|
||||
doAfter: 2
|
||||
- tag: Paper
|
||||
icon:
|
||||
sprite: Objects/Misc/bureaucracy.rsi
|
||||
state: paper
|
||||
name: construction-graph-tag-paper
|
||||
- tag: Paper
|
||||
icon:
|
||||
sprite: Objects/Misc/bureaucracy.rsi
|
||||
state: paper
|
||||
name: construction-graph-tag-paper
|
||||
|
||||
- node: makeshiftCentrifuge
|
||||
entity: HandheldMixerPaperCentrifuge
|
||||
|
After Width: | Height: | Size: 120 B |
|
After Width: | Height: | Size: 127 B |
|
After Width: | Height: | Size: 129 B |
|
After Width: | Height: | Size: 129 B |
|
After Width: | Height: | Size: 825 B |
|
After Width: | Height: | Size: 297 B |
|
After Width: | Height: | Size: 297 B |
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"version": 1,
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Sprites created by DispenserG0inUp(Discord)",
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "icon"
|
||||
},
|
||||
{
|
||||
"name": "fill-1"
|
||||
},
|
||||
{
|
||||
"name": "fill-2"
|
||||
},
|
||||
{
|
||||
"name": "fill-3"
|
||||
},
|
||||
{
|
||||
"name": "fill-4"
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "inhand-right",
|
||||
"directions": 4
|
||||
}
|
||||
]
|
||||
}
|
||||