Added sink (#14348)
@@ -36,6 +36,13 @@ namespace Content.Client.Chemistry.Visualizers
|
||||
[DataField("metamorphicNameFull")]
|
||||
public string MetamorphicNameFull = "transformable-container-component-glass";
|
||||
|
||||
/// <summary>
|
||||
/// Which solution of the SolutionContainerManagerComponent to represent.
|
||||
/// If not set, will work as default.
|
||||
/// </summary>
|
||||
[DataField("solutionName")]
|
||||
public string SolutionName = "";
|
||||
|
||||
public string InitialName = string.Empty;
|
||||
public string InitialDescription = string.Empty;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,16 @@ public sealed class SolutionContainerVisualsSystem : VisualizerSystem<SolutionCo
|
||||
|
||||
protected override void OnAppearanceChange(EntityUid uid, SolutionContainerVisualsComponent component, ref AppearanceChangeEvent args)
|
||||
{
|
||||
// Check if the solution that was updated is the one set as represented
|
||||
if (!string.IsNullOrEmpty(component.SolutionName))
|
||||
{
|
||||
if (AppearanceSystem.TryGetData<string>(uid, SolutionContainerVisuals.SolutionName, out var name,
|
||||
args.Component) && name != component.SolutionName)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!AppearanceSystem.TryGetData<float>(uid, SolutionContainerVisuals.FillFraction, out var fraction, args.Component))
|
||||
return;
|
||||
|
||||
|
||||
@@ -152,6 +152,10 @@ public sealed partial class SolutionContainerSystem : EntitySystem
|
||||
|
||||
_appearance.SetData(uid, SolutionContainerVisuals.FillFraction, solution.FillFraction, appearanceComponent);
|
||||
_appearance.SetData(uid, SolutionContainerVisuals.Color, solution.GetColor(_prototypeManager), appearanceComponent);
|
||||
if (solution.Name != null)
|
||||
{
|
||||
_appearance.SetData(uid, SolutionContainerVisuals.SolutionName, solution.Name, appearanceComponent);
|
||||
}
|
||||
|
||||
if (solution.GetPrimaryReagentId() is { } reagent)
|
||||
{
|
||||
|
||||
@@ -1,18 +1,106 @@
|
||||
using Content.Server.Chemistry.Components.SolutionManager;
|
||||
using Content.Server.Fluids.Components;
|
||||
using Content.Server.Chemistry.EntitySystems;
|
||||
using Content.Server.DoAfter;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Audio;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Fluids;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Tag;
|
||||
using Content.Shared.Verbs;
|
||||
using Content.Shared.Fluids.Components;
|
||||
using Robust.Shared.Collections;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.Fluids.EntitySystems
|
||||
namespace Content.Server.Fluids.EntitySystems;
|
||||
|
||||
public sealed class DrainSystem : SharedDrainSystem
|
||||
{
|
||||
public sealed class DrainSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||
[Dependency] private readonly SolutionContainerSystem _solutionSystem = default!;
|
||||
[Dependency] private readonly SharedAmbientSoundSystem _ambientSoundSystem = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audioSystem = default!;
|
||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||
[Dependency] private readonly TagSystem _tagSystem = default!;
|
||||
[Dependency] private readonly DoAfterSystem _doAfterSystem = default!;
|
||||
[Dependency] private readonly PuddleSystem _puddleSystem = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<DrainComponent, GetVerbsEvent<Verb>>(AddEmptyVerb);
|
||||
SubscribeLocalEvent<DrainComponent, ExaminedEvent>(OnExamined);
|
||||
SubscribeLocalEvent<DrainComponent, AfterInteractUsingEvent>(OnInteract);
|
||||
SubscribeLocalEvent<DrainComponent, DrainDoAfterEvent>(OnDoAfter);
|
||||
}
|
||||
|
||||
private void AddEmptyVerb(EntityUid uid, DrainComponent component, GetVerbsEvent<Verb> args)
|
||||
{
|
||||
if (!args.CanAccess || !args.CanInteract || args.Using == null)
|
||||
return;
|
||||
|
||||
if (!TryComp(args.Using, out SpillableComponent? spillable) ||
|
||||
!TryComp(args.Target, out DrainComponent? drain))
|
||||
return;
|
||||
|
||||
Verb verb = new()
|
||||
{
|
||||
Text = Loc.GetString("drain-component-empty-verb-inhand", ("object", Name(args.Using.Value))),
|
||||
Act = () =>
|
||||
{
|
||||
Empty(args.Using.Value, spillable, args.Target, drain);
|
||||
},
|
||||
Impact = LogImpact.Low,
|
||||
Icon = new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/eject.svg.192dpi.png"))
|
||||
|
||||
};
|
||||
args.Verbs.Add(verb);
|
||||
}
|
||||
|
||||
private void Empty(EntityUid container, SpillableComponent spillable, EntityUid target, DrainComponent drain)
|
||||
{
|
||||
// Find the solution in the container that is emptied
|
||||
if (!_solutionSystem.TryGetDrainableSolution(container, out var containerSolution) ||
|
||||
containerSolution.Volume == FixedPoint2.Zero)
|
||||
{
|
||||
_popupSystem.PopupEntity(
|
||||
Loc.GetString("drain-component-empty-verb-using-is-empty-message", ("object", container)),
|
||||
container);
|
||||
return;
|
||||
}
|
||||
|
||||
// try to find the drain's solution
|
||||
if (!_solutionSystem.TryGetSolution(target, DrainComponent.SolutionName, out var drainSolution))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to transfer as much solution as possible to the drain
|
||||
|
||||
var transferSolution = _solutionSystem.SplitSolution(container, containerSolution,
|
||||
FixedPoint2.Min(containerSolution.Volume, drainSolution.AvailableVolume));
|
||||
|
||||
_solutionSystem.TryAddSolution(target, drainSolution, transferSolution);
|
||||
|
||||
_audioSystem.PlayPvs(drain.ManualDrainSound, target);
|
||||
_ambientSoundSystem.SetAmbience(target, true);
|
||||
|
||||
// If drain is full, spill
|
||||
|
||||
if (drainSolution.MaxVolume == drainSolution.Volume)
|
||||
{
|
||||
_puddleSystem.TrySpillAt(Transform(target).Coordinates, containerSolution, out var puddle);
|
||||
_popupSystem.PopupEntity(
|
||||
Loc.GetString("drain-component-empty-verb-target-is-full-message", ("object", target)),
|
||||
container);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
@@ -31,6 +119,13 @@ namespace Content.Server.Fluids.EntitySystems
|
||||
}
|
||||
drain.Accumulator -= drain.DrainFrequency;
|
||||
|
||||
// Disable ambient sound from emptying manually
|
||||
if (!drain.AutoDrain)
|
||||
{
|
||||
_ambientSoundSystem.SetAmbience(drain.Owner, false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!managerQuery.TryGetComponent(drain.Owner, out var manager))
|
||||
continue;
|
||||
|
||||
@@ -40,6 +135,12 @@ namespace Content.Server.Fluids.EntitySystems
|
||||
if (drainSolution is null)
|
||||
continue;
|
||||
|
||||
if (drainSolution.AvailableVolume <= 0)
|
||||
{
|
||||
_ambientSoundSystem.SetAmbience(drain.Owner, false);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Remove a bit from the buffer
|
||||
_solutionSystem.SplitSolution(drain.Owner, drainSolution, (drain.UnitsDestroyedPerSecond * drain.DrainFrequency));
|
||||
|
||||
@@ -97,5 +198,68 @@ namespace Content.Server.Fluids.EntitySystems
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnExamined(EntityUid uid, DrainComponent component, ExaminedEvent args)
|
||||
{
|
||||
if (!args.IsInDetailsRange ||
|
||||
!TryComp(uid, out SolutionContainerManagerComponent? solutionComp) ||
|
||||
!_solutionSystem.TryGetSolution(uid, DrainComponent.SolutionName, out var drainSolution))
|
||||
{ return; }
|
||||
|
||||
var text = drainSolution.AvailableVolume != 0 ?
|
||||
Loc.GetString("drain-component-examine-volume", ("volume", drainSolution.AvailableVolume)) :
|
||||
Loc.GetString("drain-component-examine-hint-full");
|
||||
args.Message.AddMarkup($"\n\n{text}");
|
||||
}
|
||||
|
||||
private void OnInteract(EntityUid uid, DrainComponent component, InteractEvent args)
|
||||
{
|
||||
if (!args.CanReach || args.Target == null ||
|
||||
!_tagSystem.HasTag(args.Used, DrainComponent.PlungerTag) ||
|
||||
!_solutionSystem.TryGetSolution(args.Target.Value, DrainComponent.SolutionName, out var drainSolution))
|
||||
{ return; }
|
||||
|
||||
if (drainSolution.AvailableVolume > 0)
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("drain-component-unclog-notapplicable", ("object", args.Target.Value)), args.Target.Value);
|
||||
return;
|
||||
}
|
||||
|
||||
_audioSystem.PlayPvs(component.PlungerSound, uid);
|
||||
|
||||
|
||||
var doAfterArgs = new DoAfterArgs(args.User, component.UnclogDuration, new DrainDoAfterEvent(),uid, args.Used)
|
||||
{
|
||||
BreakOnTargetMove = true,
|
||||
BreakOnUserMove = true,
|
||||
BreakOnDamage = true,
|
||||
BreakOnHandChange = true
|
||||
};
|
||||
|
||||
_doAfterSystem.TryStartDoAfter(doAfterArgs);
|
||||
}
|
||||
|
||||
private void OnDoAfter(EntityUid uid, DrainComponent component, DoAfterEvent args)
|
||||
{
|
||||
if (args.Target == null)
|
||||
return;
|
||||
|
||||
if (!_random.Prob(component.UnclogProbability))
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("drain-component-unclog-fail", ("object", args.Target.Value)), args.Target.Value);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!_solutionSystem.TryGetSolution(args.Target.Value, DrainComponent.SolutionName,
|
||||
out var drainSolution))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
_solutionSystem.RemoveAllSolution(args.Target.Value, drainSolution);
|
||||
_audioSystem.PlayPvs(component.UnclogSound, args.Target.Value);
|
||||
_popupSystem.PopupEntity(Loc.GetString("drain-component-unclog-success", ("object", args.Target.Value)), args.Target.Value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Server.Fluids.Components;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.DragDrop;
|
||||
using Content.Shared.FixedPoint;
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace Content.Shared.Chemistry
|
||||
Color,
|
||||
FillFraction,
|
||||
BaseOverride,
|
||||
SolutionName
|
||||
}
|
||||
|
||||
public enum SolutionContainerLayers : byte
|
||||
|
||||
@@ -89,7 +89,7 @@ public abstract partial class SharedDoAfterSystem : EntitySystem
|
||||
// I feel like this is somewhat cursed, but its the only way I can think of without having to just send
|
||||
// redundant data over the network and increasing DoAfter boilerplate.
|
||||
var evType = typeof(DoAfterAttemptEvent<>).MakeGenericType(args.Event.GetType());
|
||||
doAfter.AttemptEvent = _factory.CreateInstance(evType, new object[] { doAfter, args.Event }, inject: false);
|
||||
doAfter.AttemptEvent = _factory.CreateInstance(evType, new object[] { doAfter, args.Event });
|
||||
}
|
||||
|
||||
if (args.EventTarget != null)
|
||||
|
||||
@@ -1,15 +1,31 @@
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Audio;
|
||||
|
||||
namespace Content.Shared.Fluids.Components;
|
||||
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
/// <summary>
|
||||
/// A Drain allows an entity to absorb liquid in a disposal goal. Drains can be filled manually (with the Empty verb)
|
||||
/// or they can absorb puddles of liquid around them when AutoDrain is set to true.
|
||||
/// When the entity also has a SolutionContainerManager attached with a solution named drainBuffer, this solution
|
||||
/// gets filled until the drain is full.
|
||||
/// When the drain is full, it can be unclogged using a plunger (i.e. an entity with a Plunger tag attached).
|
||||
/// Later this can be refactored into a proper Plunger component if needed.
|
||||
/// </summary>
|
||||
[RegisterComponent, Access(typeof(SharedDrainSystem))]
|
||||
public sealed class DrainComponent : Component
|
||||
{
|
||||
public const string SolutionName = "drainBuffer";
|
||||
public const string PlungerTag = "Plunger";
|
||||
|
||||
[DataField("accumulator")]
|
||||
public float Accumulator = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// Does this drain automatically absorb surrouding puddles? Or is it a drain designed to empty
|
||||
/// solutions in it manually?
|
||||
/// </summary>
|
||||
[DataField("autoDrain"), ViewVariables(VVAccess.ReadOnly)]
|
||||
public bool AutoDrain = true;
|
||||
|
||||
/// <summary>
|
||||
/// How many units per second the drain can absorb from the surrounding puddles.
|
||||
/// Divided by puddles, so if there are 5 puddles this will take 1/5 from each puddle.
|
||||
@@ -28,7 +44,7 @@ public sealed class DrainComponent : Component
|
||||
/// How many (unobstructed) tiles away the drain will
|
||||
/// drain puddles from.
|
||||
/// </summary>
|
||||
[DataField("range")]
|
||||
[DataField("range"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public float Range = 2f;
|
||||
|
||||
/// <summary>
|
||||
@@ -37,4 +53,25 @@ public sealed class DrainComponent : Component
|
||||
/// </summary>
|
||||
[DataField("drainFrequency")]
|
||||
public float DrainFrequency = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// How much time it takes to unclog it with a plunger
|
||||
/// </summary>
|
||||
[DataField("unclogDuration"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public float UnclogDuration = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// What's the probability of uncloging on each try
|
||||
/// </summary>
|
||||
[DataField("unclogProbability"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public float UnclogProbability = 0.3f;
|
||||
|
||||
[DataField("manualDrainSound"), ViewVariables(VVAccess.ReadOnly)]
|
||||
public SoundSpecifier ManualDrainSound = new SoundPathSpecifier("/Audio/Effects/Fluids/slosh.ogg");
|
||||
|
||||
[DataField("plungerSound"), ViewVariables(VVAccess.ReadOnly)]
|
||||
public SoundSpecifier PlungerSound = new SoundPathSpecifier("/Audio/Items/Janitor/plunger.ogg");
|
||||
|
||||
[DataField("unclogSound"), ViewVariables(VVAccess.ReadOnly)]
|
||||
public SoundSpecifier UnclogSound = new SoundPathSpecifier("/Audio/Effects/Fluids/glug.ogg");
|
||||
}
|
||||
|
||||
12
Content.Shared/Fluids/SharedDrainSystem.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using Content.Shared.DoAfter;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.Fluids;
|
||||
|
||||
public class SharedDrainSystem : EntitySystem
|
||||
{
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class DrainDoAfterEvent : SimpleDoAfterEvent
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
blood1.ogg under CC-0 from https://freesound.org/people/kyles/sounds/453769/
|
||||
blood2.ogg under CC-BY 3.0 from https://freesound.org/people/EminYILDIRIM/sounds/554284/
|
||||
14
Resources/Audio/Effects/Fluids/attributions.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
- files: ["blood1.ogg"]
|
||||
license: "CC0-1.0"
|
||||
copyright: "Created by Kyles"
|
||||
source: "https://freesound.org/people/kyles/sounds/453769/"
|
||||
|
||||
- files: ["blood2.ogg"]
|
||||
license: "CC-BY-4.0"
|
||||
copyright: "Created by EminYILDIRIM"
|
||||
source: "https://freesound.org/people/EminYILDIRIM/sounds/554284/"
|
||||
|
||||
- files: ["glug.ogg"]
|
||||
license: "CC0-1.0"
|
||||
copyright: "Created by brittmosel"
|
||||
source: "https://freesound.org/people/brittmosel/sounds/529300/"
|
||||
BIN
Resources/Audio/Effects/Fluids/glug.ogg
Normal file
4
Resources/Audio/Items/Janitor/attributions.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
- files: ["plunger.ogg"]
|
||||
license: "CC-BY-4.0"
|
||||
copyright: "Created by tosha73"
|
||||
source: "https://freesound.org/people/tosha73/sounds/540784/"
|
||||
BIN
Resources/Audio/Items/Janitor/plunger.ogg
Normal file
@@ -0,0 +1,8 @@
|
||||
drain-component-empty-verb-using-is-empty-message = { CAPITALIZE(THE($object)) } is empty!
|
||||
drain-component-empty-verb-target-is-full-message = { CAPITALIZE(THE($object)) } is full!
|
||||
drain-component-empty-verb-inhand = Empty {$object}
|
||||
drain-component-examine-hint-full = [color="blue"]It is filled to the brim. Maybe a plunger can help?[/color]
|
||||
drain-component-examine-volume = [color="blue"]Remaining space - {$volume}u.[/color]
|
||||
drain-component-unclog-fail = { CAPITALIZE(THE($object)) } is still full.
|
||||
drain-component-unclog-success = { CAPITALIZE(THE($object)) } unclogs.
|
||||
drain-component-unclog-notapplicable = { CAPITALIZE(THE($object)) } isn't clogged.
|
||||
@@ -4,7 +4,7 @@
|
||||
sprite: Objects/Specific/Janitorial/janitorial.rsi
|
||||
state: cleaner
|
||||
product: CrateServiceJanitorialSupplies
|
||||
cost: 500
|
||||
cost: 560
|
||||
category: Service
|
||||
group: market
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
amount: 2
|
||||
- id: TrashBag
|
||||
amount: 2
|
||||
- id: Plunger
|
||||
amount: 2
|
||||
|
||||
- type: entity
|
||||
id: CrateServiceReplacementLights
|
||||
|
||||
@@ -71,6 +71,8 @@
|
||||
amount: 2
|
||||
- id: FlashlightLantern
|
||||
amount: 2
|
||||
- id: Plunger
|
||||
amount: 2
|
||||
|
||||
- type: entity
|
||||
id: ClosetLegalFilled
|
||||
|
||||
@@ -94,6 +94,7 @@
|
||||
- SheetSteel
|
||||
- SheetPlastic
|
||||
- ResearchDisk
|
||||
- Plunger
|
||||
chance: 0.6
|
||||
offset: 0.0
|
||||
|
||||
|
||||
@@ -317,6 +317,26 @@
|
||||
path: /Audio/Effects/metalbreak.ogg
|
||||
- type: ItemMapper
|
||||
mapLayers:
|
||||
cart_plunger:
|
||||
whitelist:
|
||||
tags:
|
||||
- Plunger
|
||||
cart_mop:
|
||||
whitelist:
|
||||
tags:
|
||||
- Mop
|
||||
cart_garbage:
|
||||
whitelist:
|
||||
tags:
|
||||
- TrashBag
|
||||
cart_replacer:
|
||||
whitelist:
|
||||
components:
|
||||
- LightReplacer
|
||||
cart_spray:
|
||||
whitelist:
|
||||
tags:
|
||||
- Spray
|
||||
cart_sign1: # this is like stack of floor signs
|
||||
minCount: 1
|
||||
whitelist:
|
||||
@@ -337,26 +357,10 @@
|
||||
whitelist:
|
||||
tags:
|
||||
- WetFloorSign
|
||||
cart_spray:
|
||||
whitelist:
|
||||
tags:
|
||||
- Spray
|
||||
cart_garbage:
|
||||
whitelist:
|
||||
tags:
|
||||
- TrashBag
|
||||
cart_replacer:
|
||||
whitelist:
|
||||
components:
|
||||
- LightReplacer
|
||||
cart_bucket:
|
||||
whitelist:
|
||||
tags:
|
||||
- Bucket
|
||||
cart_mop:
|
||||
whitelist:
|
||||
tags:
|
||||
- Mop
|
||||
sprite: Objects/Specific/Janitorial/janitorial_cart.rsi
|
||||
- type: Appearance
|
||||
- type: SolutionContainerVisuals
|
||||
@@ -392,7 +396,11 @@
|
||||
- type: Sprite
|
||||
drawdepth: FloorObjects
|
||||
sprite: Objects/Specific/Janitorial/drain.rsi
|
||||
state: icon
|
||||
layers:
|
||||
- state: icon
|
||||
- map: [ "enum.SolutionContainerLayers.Fill" ]
|
||||
state: fill-1
|
||||
visible: false
|
||||
- type: InteractionOutline
|
||||
- type: Clickable
|
||||
- type: Transform
|
||||
@@ -400,13 +408,18 @@
|
||||
- type: Physics
|
||||
bodyType: Static
|
||||
canCollide: false
|
||||
- type: Drain
|
||||
- type: AmbientSound
|
||||
enabled: false
|
||||
volume: -8
|
||||
range: 8
|
||||
sound:
|
||||
path: /Audio/Ambience/Objects/drain.ogg
|
||||
- type: Drain
|
||||
- type: Appearance
|
||||
- type: SolutionContainerVisuals
|
||||
maxFillLevels: 1
|
||||
fillBaseName: fill-
|
||||
solutionName: drainBuffer
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
drainBuffer:
|
||||
@@ -433,6 +446,24 @@
|
||||
- !type:PlaySoundBehavior
|
||||
sound:
|
||||
path: /Audio/Effects/metalbreak.ogg
|
||||
|
||||
- type: entity
|
||||
name: plunger
|
||||
id: Plunger
|
||||
parent: BaseItem
|
||||
description: A plunger with a red plastic suction-cup and a wooden handle. Used to unclog drains.
|
||||
components:
|
||||
- type: Tag
|
||||
tags:
|
||||
- Plunger
|
||||
- type: Sprite
|
||||
netsync: false
|
||||
sprite: Objects/Specific/Janitorial/janitorial.rsi
|
||||
state: plunger
|
||||
- type: Item
|
||||
sprite: Objects/Specific/Janitorial/janitorial.rsi
|
||||
heldPrefix: plunger
|
||||
- type: ItemCooldown
|
||||
- type: GuideHelp
|
||||
guides:
|
||||
- Janitorial
|
||||
|
||||
@@ -10,9 +10,21 @@
|
||||
- type: InteractionOutline
|
||||
- type: Sprite
|
||||
sprite: Structures/Furniture/sink.rsi
|
||||
state: sink_stem
|
||||
layers:
|
||||
- state: sink_stem
|
||||
- map: [ "enum.SolutionContainerLayers.Fill" ]
|
||||
state: sink-fill-1
|
||||
visible: false
|
||||
netsync: false
|
||||
- type: Appearance
|
||||
- type: SolutionContainerVisuals
|
||||
maxFillLevels: 1
|
||||
fillBaseName: sink-fill-
|
||||
solutionName: drainBuffer
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
drainBuffer:
|
||||
maxVol: 100
|
||||
tank:
|
||||
maxVol: 500
|
||||
- type: SolutionRegeneration
|
||||
@@ -24,6 +36,8 @@
|
||||
- type: DrainableSolution
|
||||
solution: tank
|
||||
- type: ReagentTank
|
||||
- type: Drain
|
||||
autoDrain: false
|
||||
- type: Damageable
|
||||
damageContainer: Inorganic
|
||||
damageModifierSet: Metallic
|
||||
@@ -44,6 +58,13 @@
|
||||
- !type:PlaySoundBehavior
|
||||
sound:
|
||||
path: /Audio/Effects/metalbreak.ogg
|
||||
- type: AmbientSound
|
||||
enabled: false
|
||||
volume: -8
|
||||
range: 8
|
||||
sound:
|
||||
path: /Audio/Ambience/Objects/drain.ogg
|
||||
|
||||
|
||||
- type: entity
|
||||
name: sink
|
||||
@@ -53,6 +74,8 @@
|
||||
components:
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
drainBuffer:
|
||||
maxVol: 200
|
||||
tank:
|
||||
reagents:
|
||||
- ReagentId: Water
|
||||
@@ -65,7 +88,15 @@
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: Structures/Furniture/sink.rsi
|
||||
state: sink_wide
|
||||
layers:
|
||||
- state: sink_wide
|
||||
- map: [ "enum.SolutionContainerLayers.Fill" ]
|
||||
state: sink_wide-fill-1
|
||||
visible: false
|
||||
- type: SolutionContainerVisuals
|
||||
maxFillLevels: 1
|
||||
fillBaseName: sink_wide-fill-
|
||||
solutionName: drainBuffer
|
||||
|
||||
#Stemless Sink
|
||||
|
||||
@@ -76,7 +107,11 @@
|
||||
components:
|
||||
- type: Sprite
|
||||
sprite: Structures/Furniture/sink.rsi
|
||||
state: sink
|
||||
layers:
|
||||
- state: sink
|
||||
- map: [ "enum.SolutionContainerLayers.Fill" ]
|
||||
state: sink-fill-1
|
||||
visible: false
|
||||
|
||||
- type: entity
|
||||
name: sink
|
||||
@@ -86,6 +121,8 @@
|
||||
components:
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
drainBuffer:
|
||||
maxVol: 100
|
||||
tank:
|
||||
reagents:
|
||||
- ReagentId: Water
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
stash: !type:ContainerSlot {}
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
drainBuffer:
|
||||
maxVol: 500
|
||||
toilet:
|
||||
maxVol: 250
|
||||
- type: Transform
|
||||
@@ -32,6 +34,12 @@
|
||||
graph: Toilet
|
||||
node: toilet
|
||||
- type: Appearance
|
||||
- type: Drain
|
||||
autoDrain: false
|
||||
- type: SolutionContainerVisuals
|
||||
maxFillLevels: 1
|
||||
fillBaseName: fill-
|
||||
solutionName: drainBuffer
|
||||
- type: StaticPrice
|
||||
price: 25
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
result: Bucket
|
||||
completetime: 2
|
||||
materials:
|
||||
Plastic: 100
|
||||
Steel: 100
|
||||
|
||||
- type: latheRecipe
|
||||
id: WetFloorSign
|
||||
@@ -81,6 +81,14 @@
|
||||
Steel: 100
|
||||
Glass: 100
|
||||
|
||||
- type: latheRecipe
|
||||
id: Plunger
|
||||
result: Plunger
|
||||
completetime: 2
|
||||
materials:
|
||||
Plastic: 50
|
||||
Wood: 200
|
||||
|
||||
- type: latheRecipe
|
||||
id: WeaponSprayNozzle
|
||||
result: WeaponSprayNozzle
|
||||
|
||||
@@ -631,9 +631,13 @@
|
||||
- type: Tag
|
||||
id: Plastic
|
||||
|
||||
- type: Tag
|
||||
id: Plunger
|
||||
|
||||
- type: Tag
|
||||
id: PlushieGhost
|
||||
|
||||
|
||||
- type: Tag
|
||||
id: Powerdrill
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 3.3 KiB |
@@ -5,11 +5,15 @@
|
||||
"y":32
|
||||
},
|
||||
"license":"CC-BY-SA-3.0",
|
||||
"copyright":"Created by EmoGarbage",
|
||||
"copyright":"Created by EmoGarbage, fill-1 created by Topy for SS14",
|
||||
"states":[
|
||||
{
|
||||
"name":"icon",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "fill-1",
|
||||
"directions": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
},
|
||||
{
|
||||
"name": "mopbucket_water-3"
|
||||
},
|
||||
{
|
||||
"name": "plunger"
|
||||
},
|
||||
{
|
||||
"name": "inhand-left",
|
||||
@@ -36,6 +39,14 @@
|
||||
{
|
||||
"name": "equipped-BELT",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "plunger-inhand-left",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "plunger-inhand-right",
|
||||
"directions": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
@@ -46,6 +46,10 @@
|
||||
{
|
||||
"name": "cart_spray",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "cart_plunger",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "cart_water-1",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"y": 32
|
||||
},
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Taken from tgstation https://github.com/tgstation/tgstation/commit/f01afc7edd39b28dd718407d5bbfca3a5dfe995f#diff-378d1b8f0f0a73185e7c82e4ccfdb65102561992a7abb306090ce851f8419780",
|
||||
"copyright": "Taken from tgstation https://github.com/tgstation/tgstation/commit/f01afc7edd39b28dd718407d5bbfca3a5dfe995f#diff-378d1b8f0f0a73185e7c82e4ccfdb65102561992a7abb306090ce851f8419780, sink-fill-1 and sink_wide-fill-1 made by Topy for SS14",
|
||||
"states": [
|
||||
{
|
||||
"name": "sink",
|
||||
@@ -18,6 +18,14 @@
|
||||
{
|
||||
"name": "sink_stem",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "sink-fill-1",
|
||||
"directions": 4
|
||||
},
|
||||
{
|
||||
"name": "sink_wide-fill-1",
|
||||
"directions": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
BIN
Resources/Textures/Structures/Furniture/sink.rsi/sink-fill-1.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.8 KiB |