diff --git a/Content.Client/IgnoredComponents.cs b/Content.Client/IgnoredComponents.cs index 3829cfda87..c77bf8357c 100644 --- a/Content.Client/IgnoredComponents.cs +++ b/Content.Client/IgnoredComponents.cs @@ -132,6 +132,9 @@ "EmitSoundOnThrow", "Flash", "DamageOnToolInteract", + "CustodialClosetFill", + "NoSlip", + "TrashSpawner", }; } } diff --git a/Content.Server/GameObjects/Components/Fluids/MopComponent.cs b/Content.Server/GameObjects/Components/Fluids/MopComponent.cs index 665b2d5e26..22f08f9ea8 100644 --- a/Content.Server/GameObjects/Components/Fluids/MopComponent.cs +++ b/Content.Server/GameObjects/Components/Fluids/MopComponent.cs @@ -65,17 +65,16 @@ namespace Content.Server.GameObjects.Components.Fluids { if (!InteractionChecks.InRangeUnobstructed(eventArgs)) return; - Solution solution; + if (CurrentVolume <= 0) + { + return; + } + + //Solution solution; if (eventArgs.Target == null) { - if (CurrentVolume <= 0) - { - return; - } - // Drop the liquid on the mop on to the ground I guess? Potentially change by design - // Maybe even use a toggle mode instead of "Pickup" and "dropoff" - solution = _contents.SplitSolution(CurrentVolume); - SpillHelper.SpillAt(eventArgs.ClickLocation, solution, "PuddleSmear"); + // Drop the liquid on the mop on to the ground + SpillHelper.SpillAt(eventArgs.ClickLocation, _contents.SplitSolution(CurrentVolume), "PuddleSmear"); return; } @@ -88,18 +87,34 @@ namespace Content.Server.GameObjects.Components.Fluids // - _pickupAmount, // - whatever's left in the puddle, or // - whatever we can still hold (whichever's smallest) - var transferAmount = ReagentUnit.Min(ReagentUnit.New(5), puddleComponent.CurrentVolume, MaxVolume - CurrentVolume); + var transferAmount = ReagentUnit.Min(ReagentUnit.New(5), puddleComponent.CurrentVolume, CurrentVolume); + bool puddleCleaned = puddleComponent.CurrentVolume - transferAmount <= 0; + if (transferAmount == 0) { - return; + if(puddleComponent.EmptyHolder) //The puddle doesn't actually *have* reagents, for example vomit because there's no "vomit" reagent. + { + puddleComponent.Owner.Delete(); + transferAmount = ReagentUnit.Min(ReagentUnit.New(5), CurrentVolume); + puddleCleaned = true; + } + else + { + return; + } + } + else + { + puddleComponent.SplitSolution(transferAmount); } - solution = puddleComponent.SplitSolution(transferAmount); - // Probably don't recolor a mop? Could work, if we layered it maybe - if (!_contents.TryAddSolution(solution, false, true)) + if (puddleCleaned) //After cleaning the puddle, make a new puddle with solution from the mop as a "wet floor". Then evaporate it slowly. { - // I can't imagine why this would happen - throw new InvalidOperationException(); + SpillHelper.SpillAt(eventArgs.ClickLocation, _contents.SplitSolution(transferAmount), "PuddleSmear"); + } + else + { + _contents.SplitSolution(transferAmount); } // Give some visual feedback shit's happening (for anyone who can't hear sound) diff --git a/Content.Server/GameObjects/Components/Fluids/PuddleComponent.cs b/Content.Server/GameObjects/Components/Fluids/PuddleComponent.cs index 4eae6d7379..221cd19604 100644 --- a/Content.Server/GameObjects/Components/Fluids/PuddleComponent.cs +++ b/Content.Server/GameObjects/Components/Fluids/PuddleComponent.cs @@ -2,7 +2,9 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading; +using Content.Server.GameObjects.Components.Movement; using Content.Server.GameObjects.Components.Chemistry; +using Content.Server.GameObjects.EntitySystems.Click; using Content.Shared.Chemistry; using Content.Shared.Physics; using Robust.Server.GameObjects; @@ -15,6 +17,7 @@ using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.Map; using Robust.Shared.Interfaces.Random; using Robust.Shared.IoC; +using Robust.Shared.Localization; using Robust.Shared.Maths; using Robust.Shared.Serialization; using Robust.Shared.Utility; @@ -27,7 +30,7 @@ namespace Content.Server.GameObjects.Components.Fluids /// Puddle on a floor /// [RegisterComponent] - public class PuddleComponent : Component + public class PuddleComponent : Component, IExamine { // Current design: Something calls the SpillHelper.Spill, that will either // A) Add to an existing puddle at the location (normalised to tile-center) or @@ -44,12 +47,25 @@ namespace Content.Server.GameObjects.Components.Fluids #pragma warning disable 649 [Dependency] private readonly IMapManager _mapManager; + [Dependency] private readonly ILocalizationManager _loc; #pragma warning restore 649 public override string Name => "Puddle"; private CancellationTokenSource _evaporationToken; private ReagentUnit _evaporateThreshold; // How few we can hold prior to self-destructing + public ReagentUnit EvaporateThreshold + { + get => _evaporateThreshold; + set => _evaporateThreshold = value; + } + private ReagentUnit _slipThreshold = ReagentUnit.New(3); + public ReagentUnit SlipThreshold + { + get => _slipThreshold; + set => _slipThreshold = value; + } + private bool _slippery = false; private float _evaporateTime; private string _spillSound; @@ -78,6 +94,7 @@ namespace Content.Server.GameObjects.Components.Fluids private ReagentUnit OverflowLeft => CurrentVolume - OverflowVolume; private SolutionComponent _contents; + public bool EmptyHolder => _contents.ReagentList.Count == 0; private int _spriteVariants; // Whether the underlying solution color should be used private bool _recolor; @@ -87,11 +104,12 @@ namespace Content.Server.GameObjects.Components.Fluids { serializer.DataFieldCached(ref _spillSound, "spill_sound", "/Audio/Effects/Fluids/splat.ogg"); serializer.DataField(ref _overflowVolume, "overflow_volume", ReagentUnit.New(20)); - serializer.DataField(ref _evaporateTime, "evaporate_time", 600.0f); + serializer.DataField(ref _evaporateTime, "evaporate_time", 5.0f); // Long-term probably have this based on the underlying reagents - serializer.DataField(ref _evaporateThreshold, "evaporate_threshold", ReagentUnit.New(2)); + serializer.DataField(ref _evaporateThreshold, "evaporate_threshold", ReagentUnit.New(20)); serializer.DataField(ref _spriteVariants, "variants", 1); serializer.DataField(ref _recolor, "recolor", false); + } public override void Initialize() @@ -121,6 +139,16 @@ namespace Content.Server.GameObjects.Components.Fluids _spriteComponent.LayerSetState(0, $"{baseName}-{randomVariant}"); // TODO: Remove hardcode _spriteComponent.Rotation = Angle.FromDegrees(robustRandom.Next(0, 359)); // UpdateAppearance should get called soon after this so shouldn't need to call Dirty() here + + UpdateStatus(); + } + + void IExamine.Examine(FormattedMessage message, bool inDetailsRange) + { + if(_slippery) + { + message.AddText(_loc.GetString("It looks slippery.")); + } } // Flow rate should probably be controlled globally so this is it for now @@ -174,12 +202,28 @@ namespace Content.Server.GameObjects.Components.Fluids } } - private void UpdateStatus() + public void Evaporate() { - // If UpdateStatus is getting called again it means more fluid has been updated so let's just wait - _evaporationToken?.Cancel(); + _contents.SplitSolution(ReagentUnit.Min(ReagentUnit.New(1), _contents.CurrentVolume)); + if (CurrentVolume == 0) + { + Owner.Delete(); + } + else + { + UpdateStatus(); + } + } - if (CurrentVolume > _evaporateThreshold) + public void UpdateStatus() + { + _evaporationToken?.Cancel(); + if(Owner.Deleted) return; + + UpdateAppearance(); + UpdateSlip(); + + if (_evaporateThreshold == ReagentUnit.New(-1) || CurrentVolume > _evaporateThreshold) { return; } @@ -187,12 +231,26 @@ namespace Content.Server.GameObjects.Components.Fluids _evaporationToken = new CancellationTokenSource(); // KYS to evaporate - Timer.Spawn(TimeSpan.FromSeconds(_evaporateTime), CheckEvaporate, _evaporationToken.Token); + Timer.Spawn(TimeSpan.FromSeconds(_evaporateTime), Evaporate, _evaporationToken.Token); + } + + private void UpdateSlip() + { + if ((_slipThreshold == ReagentUnit.New(-1) || CurrentVolume < _slipThreshold) && Owner.TryGetComponent(out SlipperyComponent existingSlipperyComponent)) + { + Owner.RemoveComponent(); + _slippery = false; + } + else if (CurrentVolume >= _slipThreshold && !Owner.TryGetComponent(out SlipperyComponent newSlipperyComponent)) + { + Owner.AddComponent(); + _slippery = true; + } } private void UpdateAppearance() { - if (Owner.Deleted) + if (Owner.Deleted || EmptyHolder) { return; } diff --git a/Content.Server/GameObjects/Components/Fluids/SpillHelper.cs b/Content.Server/GameObjects/Components/Fluids/SpillHelper.cs index e064a61e80..d7898c0ef9 100644 --- a/Content.Server/GameObjects/Components/Fluids/SpillHelper.cs +++ b/Content.Server/GameObjects/Components/Fluids/SpillHelper.cs @@ -1,3 +1,4 @@ +#nullable enable using Content.Shared.Chemistry; using Robust.Server.Interfaces.GameObjects; @@ -31,11 +32,11 @@ namespace Content.Server.GameObjects.Components.Fluids /// /// Initial solution for the prototype /// Prototype to use - internal static void SpillAt(GridCoordinates gridCoordinates, Solution solution, string prototype) + internal static PuddleComponent? SpillAt(GridCoordinates gridCoordinates, Solution solution, string prototype) { if (solution.TotalVolume == 0) { - return; + return null; } var mapManager = IoCManager.Resolve(); @@ -48,7 +49,7 @@ namespace Content.Server.GameObjects.Components.Fluids var tileRef = mapGrid.GetTileRef(gridCoordinates); if (tileRef.Tile.IsEmpty) { - return; + return null; } // Get normalized co-ordinate for spill location and spill it in the centre @@ -78,11 +79,13 @@ namespace Content.Server.GameObjects.Components.Fluids // Did we add to an existing puddle if (spilt) { - return; + return null; } var puddle = serverEntityManager.SpawnEntity(prototype, spillGridCoords); - puddle.GetComponent().TryAddSolution(solution); + var newPuddleComponent = puddle.GetComponent(); + newPuddleComponent.TryAddSolution(solution); + return newPuddleComponent; } } diff --git a/Content.Server/GameObjects/Components/GUI/InventoryComponent.cs b/Content.Server/GameObjects/Components/GUI/InventoryComponent.cs index 4c3b903490..1b4cb47971 100644 --- a/Content.Server/GameObjects/Components/GUI/InventoryComponent.cs +++ b/Content.Server/GameObjects/Components/GUI/InventoryComponent.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using Content.Server.GameObjects.Components; +using Content.Shared.GameObjects.Components.Inventory; using Content.Server.GameObjects.EntitySystems.Click; using Content.Server.Interfaces.GameObjects.Components.Interaction; using Content.Server.Interfaces; @@ -23,7 +24,7 @@ using static Content.Shared.GameObjects.SharedInventoryComponent.ClientInventory namespace Content.Server.GameObjects { [RegisterComponent] - public class InventoryComponent : SharedInventoryComponent, IExAct + public class InventoryComponent : SharedInventoryComponent, IExAct, IEffectBlocker { #pragma warning disable 649 [Dependency] private readonly IEntitySystemManager _entitySystemManager; @@ -46,6 +47,18 @@ namespace Content.Server.GameObjects } } + bool IEffectBlocker.CanSlip() + { + if(Owner.TryGetComponent(out InventoryComponent inventoryComponent) && + inventoryComponent.TryGetSlotItem(EquipmentSlotDefines.Slots.SHOES, out ItemComponent shoes) + ) + { + return EffectBlockerSystem.CanSlip(shoes.Owner); + } + + return true; + } + public override void OnRemove() { var slots = SlotContainers.Keys.ToList(); diff --git a/Content.Server/GameObjects/Components/Items/Storage/Fill/CustodialClosetFill.cs b/Content.Server/GameObjects/Components/Items/Storage/Fill/CustodialClosetFill.cs new file mode 100644 index 0000000000..a8a65b3fb8 --- /dev/null +++ b/Content.Server/GameObjects/Components/Items/Storage/Fill/CustodialClosetFill.cs @@ -0,0 +1,33 @@ +using Robust.Server.Interfaces.GameObjects; +using Robust.Shared.GameObjects; +using Robust.Shared.Interfaces.Random; +using Robust.Shared.IoC; +using Robust.Shared.Random; + +namespace Content.Server.GameObjects.Components.Items.Storage.Fill +{ + [RegisterComponent] + internal sealed class CustodialClosetFillComponent : Component, IMapInit + { + public override string Name => "CustodialClosetFill"; + + void IMapInit.MapInit() + { + var storage = Owner.GetComponent(); + var random = IoCManager.Resolve(); + + void Spawn(string prototype) + { + storage.Insert(Owner.EntityManager.SpawnEntity(prototype, Owner.Transform.GridPosition)); + } + + Spawn("MopItem"); + Spawn("MopBucket"); + Spawn("WetFloorSign"); + Spawn("WetFloorSign"); + Spawn("WetFloorSign"); + Spawn("TrashBag"); + Spawn("TrashBag"); + } + } +} diff --git a/Content.Server/GameObjects/Components/Markers/ConditionalSpawnerComponent.cs b/Content.Server/GameObjects/Components/Markers/ConditionalSpawnerComponent.cs index 53dfca85c1..820803140a 100644 --- a/Content.Server/GameObjects/Components/Markers/ConditionalSpawnerComponent.cs +++ b/Content.Server/GameObjects/Components/Markers/ConditionalSpawnerComponent.cs @@ -77,7 +77,7 @@ namespace Content.Server.GameObjects.Components.Markers } } - private void Spawn() + public virtual void Spawn() { if (Chance != 1.0f && !_robustRandom.Prob(Chance)) return; @@ -92,7 +92,7 @@ namespace Content.Server.GameObjects.Components.Markers _entityManager.SpawnEntity(_robustRandom.Pick(Prototypes), Owner.Transform.GridPosition); } - public void MapInit() + public virtual void MapInit() { _gameTicker.OnRuleAdded += RuleAdded; diff --git a/Content.Server/GameObjects/Components/Markers/TrashSpawnerComponent.cs b/Content.Server/GameObjects/Components/Markers/TrashSpawnerComponent.cs new file mode 100644 index 0000000000..24403ad67c --- /dev/null +++ b/Content.Server/GameObjects/Components/Markers/TrashSpawnerComponent.cs @@ -0,0 +1,86 @@ +using System; +using Content.Server.GameObjects.Components.Markers; +using System.Collections.Generic; +using Content.Server.GameTicking; +using Content.Server.Interfaces.GameTicking; +using Robust.Server.Interfaces.GameObjects; +using Robust.Shared.GameObjects; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Interfaces.Random; +using Robust.Shared.Maths; +using Robust.Shared.IoC; +using Robust.Shared.Random; +using Robust.Shared.Serialization; +using Robust.Shared.ViewVariables; +using Logger = Robust.Shared.Log.Logger; + +namespace Content.Server.GameObjects.Components.Markers +{ + [RegisterComponent] + public class TrashSpawnerComponent : ConditionalSpawnerComponent + { + public override string Name => "TrashSpawner"; + +#pragma warning disable 649 + [Dependency] private IEntityManager _entityManager; + [Dependency] private IRobustRandom _robustRandom; +#pragma warning restore 649 + + [ViewVariables(VVAccess.ReadWrite)] + public List RarePrototypes { get; set; } = new List(); + + [ViewVariables(VVAccess.ReadWrite)] + private List _gameRules = new List(); + + [ViewVariables(VVAccess.ReadWrite)] + public float RareChance { get; set; } = 0.05f; + + [ViewVariables(VVAccess.ReadWrite)] + public float Offset { get; set; } = 0.2f; + + public override void ExposeData(ObjectSerializer serializer) + { + base.ExposeData(serializer); + serializer.DataField(this, x => RarePrototypes, "rarePrototypes", new List()); + serializer.DataField(this, x => RareChance, "rareChance", 0.05f); + serializer.DataField(this, x => Offset, "offset", 0.2f); + } + public override void Spawn() + { + if (RarePrototypes.Count > 0 && (RareChance == 1.0f || _robustRandom.Prob(RareChance))) + { + _entityManager.SpawnEntity(_robustRandom.Pick(RarePrototypes), Owner.Transform.GridPosition); + return; + } + + if (Chance != 1.0f && !_robustRandom.Prob(Chance)) + { + return; + } + + if (Prototypes.Count == 0) + { + Logger.Warning($"Prototype list in TrashSpawnComponent is empty! Entity: {Owner}"); + return; + } + + if(!Owner.Deleted) + { + var random = IoCManager.Resolve(); + + var x_negative = random.Prob(0.5f) ? -1 : 1; + var y_negative = random.Prob(0.5f) ? -1 : 1; + + var entity = _entityManager.SpawnEntity(_robustRandom.Pick(Prototypes), Owner.Transform.GridPosition); + entity.Transform.LocalPosition += new Vector2(random.NextFloat() * Offset * x_negative, random.NextFloat() * Offset * y_negative); + } + + } + + public override void MapInit() + { + Spawn(); + Owner.Delete(); + } + } +} diff --git a/Content.Server/GameObjects/Components/Movement/NoSlipComponent.cs b/Content.Server/GameObjects/Components/Movement/NoSlipComponent.cs new file mode 100644 index 0000000000..5812dce344 --- /dev/null +++ b/Content.Server/GameObjects/Components/Movement/NoSlipComponent.cs @@ -0,0 +1,13 @@ +using Robust.Shared.GameObjects; +using Content.Shared.GameObjects.EntitySystems; + +namespace Content.Server.GameObjects.Components.Movement +{ + [RegisterComponent] + public class NoSlipComponent : Component, IEffectBlocker + { + public override string Name => "NoSlip"; + + bool IEffectBlocker.CanSlip() => false; + } +} diff --git a/Content.Server/GameObjects/Components/Movement/SlipperyComponent.cs b/Content.Server/GameObjects/Components/Movement/SlipperyComponent.cs index ef83d60373..76204c2b86 100644 --- a/Content.Server/GameObjects/Components/Movement/SlipperyComponent.cs +++ b/Content.Server/GameObjects/Components/Movement/SlipperyComponent.cs @@ -3,6 +3,7 @@ using System.Timers; using Content.Server.GameObjects.Components.Mobs; using Content.Server.Throw; using Content.Shared.Audio; +using Content.Shared.GameObjects.EntitySystems; using Content.Shared.Physics; using Robust.Server.GameObjects.EntitySystems; using Robust.Shared.Containers; @@ -90,6 +91,9 @@ namespace Content.Server.GameObjects.Components.Movement if (percentage < IntersectPercentage) return; + if(!EffectBlockerSystem.CanSlip(collidedWith)) + return; + stun.Paralyze(5f); _slipped.Add(collidedWith.Uid); diff --git a/Content.Shared/GameObjects/EntitySystems/EffectBlockerSystem.cs b/Content.Shared/GameObjects/EntitySystems/EffectBlockerSystem.cs index 26602a64f5..c7e003f03a 100644 --- a/Content.Shared/GameObjects/EntitySystems/EffectBlockerSystem.cs +++ b/Content.Shared/GameObjects/EntitySystems/EffectBlockerSystem.cs @@ -10,6 +10,7 @@ namespace Content.Shared.GameObjects.EntitySystems public interface IEffectBlocker { bool CanFall() => true; + bool CanSlip() => true; } /// @@ -28,5 +29,16 @@ namespace Content.Shared.GameObjects.EntitySystems return canFall; } + + public static bool CanSlip(IEntity entity) + { + var canSlip = true; + foreach (var blocker in entity.GetAllComponents()) + { + canSlip &= blocker.CanSlip(); // Sets var to false if false + } + + return canSlip; + } } } diff --git a/Resources/Audio/Effects/Fluids/splat.ogg b/Resources/Audio/Effects/Fluids/splat.ogg index bc84113d34..8b65c79706 100644 Binary files a/Resources/Audio/Effects/Fluids/splat.ogg and b/Resources/Audio/Effects/Fluids/splat.ogg differ diff --git a/Resources/Maps/saltern.yml b/Resources/Maps/saltern.yml index 8b53572552..405b34af97 100644 --- a/Resources/Maps/saltern.yml +++ b/Resources/Maps/saltern.yml @@ -27621,7 +27621,7 @@ entities: WireSeed: 772636827 type: Wires - uid: 2915 - type: AirlockServiceLocked + type: Airlock components: - name: Custodial Closet type: MetaData @@ -27632,6 +27632,9 @@ entities: - SerialNumber: BJWI-6517 WireSeed: 1001186873 type: Wires + - access: + - - Janitor + type: AccessReader - uid: 2916 type: AirlockMaintCommonLocked components: @@ -29503,4 +29506,669 @@ entities: components: - parent: 3112 type: Transform +- uid: 3114 + type: TrashSpawner + components: + - parent: 0 + pos: -21.5,10.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3115 + type: TrashSpawner + components: + - parent: 0 + pos: -31.5,7.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3116 + type: TrashSpawner + components: + - parent: 0 + pos: -32.5,11.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3117 + type: TrashSpawner + components: + - parent: 0 + pos: -30.5,14.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3118 + type: TrashSpawner + components: + - parent: 0 + pos: -25.5,13.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3119 + type: TrashSpawner + components: + - parent: 0 + pos: -23.5,14.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3120 + type: TrashSpawner + components: + - parent: 0 + pos: -21.5,12.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3121 + type: TrashSpawner + components: + - parent: 0 + pos: -17.5,13.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3122 + type: TrashSpawner + components: + - parent: 0 + pos: -15.5,9.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3123 + type: TrashSpawner + components: + - parent: 0 + pos: -18.5,19.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3124 + type: TrashSpawner + components: + - parent: 0 + pos: -18.5,25.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3125 + type: TrashSpawner + components: + - parent: 0 + pos: -15.5,24.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3126 + type: TrashSpawner + components: + - parent: 0 + pos: -8.5,25.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3127 + type: TrashSpawner + components: + - parent: 0 + pos: -7.5,23.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3128 + type: TrashSpawner + components: + - parent: 0 + pos: -4.5,22.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3129 + type: TrashSpawner + components: + - parent: 0 + pos: -2.5,20.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3130 + type: TrashSpawner + components: + - parent: 0 + pos: -3.5,7.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3131 + type: TrashSpawner + components: + - parent: 0 + pos: 0.5,8.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3132 + type: TrashSpawner + components: + - parent: 0 + pos: -36.5,10.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3133 + type: TrashSpawner + components: + - parent: 0 + pos: -35.5,-2.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3134 + type: TrashSpawner + components: + - parent: 0 + pos: -32.5,5.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3135 + type: TrashSpawner + components: + - parent: 0 + pos: -22.5,6.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3136 + type: TrashSpawner + components: + - parent: 0 + pos: -30.5,1.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3137 + type: TrashSpawner + components: + - parent: 0 + pos: -30.5,-8.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3138 + type: TrashSpawner + components: + - parent: 0 + pos: -19.5,-5.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3139 + type: TrashSpawner + components: + - parent: 0 + pos: -32.5,-0.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3140 + type: TrashSpawner + components: + - parent: 0 + pos: -33.5,-7.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3141 + type: TrashSpawner + components: + - parent: 0 + pos: -33.5,-11.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3142 + type: TrashSpawner + components: + - parent: 0 + pos: -32.5,-5.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3143 + type: TrashSpawner + components: + - parent: 0 + pos: -28.5,-11.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3144 + type: TrashSpawner + components: + - parent: 0 + pos: -21.5,-10.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3145 + type: TrashSpawner + components: + - parent: 0 + pos: -21.5,-12.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3146 + type: TrashSpawner + components: + - parent: 0 + pos: -18.5,-13.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3147 + type: TrashSpawner + components: + - parent: 0 + pos: -12.5,-15.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3148 + type: TrashSpawner + components: + - parent: 0 + pos: -8.5,-15.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3149 + type: TrashSpawner + components: + - parent: 0 + pos: -9.5,-12.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3150 + type: TrashSpawner + components: + - parent: 0 + pos: -8.5,-11.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3151 + type: TrashSpawner + components: + - parent: 0 + pos: -11.5,-6.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3152 + type: TrashSpawner + components: + - parent: 0 + pos: -16.5,-5.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3153 + type: TrashSpawner + components: + - parent: 0 + pos: -6.5,-9.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3154 + type: TrashSpawner + components: + - parent: 0 + pos: -2.5,-10.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3155 + type: TrashSpawner + components: + - parent: 0 + pos: -0.5,-9.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3156 + type: TrashSpawner + components: + - parent: 0 + pos: -0.5,-8.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3157 + type: TrashSpawner + components: + - parent: 0 + pos: 0.5,-6.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3158 + type: TrashSpawner + components: + - parent: 0 + pos: -11.5,-23.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3159 + type: TrashSpawner + components: + - parent: 0 + pos: -11.5,-27.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3160 + type: TrashSpawner + components: + - parent: 0 + pos: -9.5,-25.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3161 + type: TrashSpawner + components: + - parent: 0 + pos: -5.5,-27.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3162 + type: TrashSpawner + components: + - parent: 0 + pos: -2.5,-26.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3163 + type: TrashSpawner + components: + - parent: 0 + pos: -0.5,-22.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3164 + type: TrashSpawner + components: + - parent: 0 + pos: -10.5,-17.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3165 + type: TrashSpawner + components: + - parent: 0 + pos: 7.5,-18.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3166 + type: TrashSpawner + components: + - parent: 0 + pos: 12.5,-19.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3167 + type: TrashSpawner + components: + - parent: 0 + pos: 14.5,-21.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3168 + type: TrashSpawner + components: + - parent: 0 + pos: 14.5,-24.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3169 + type: TrashSpawner + components: + - parent: 0 + pos: 18.5,-25.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3170 + type: TrashSpawner + components: + - parent: 0 + pos: 22.5,-23.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3171 + type: TrashSpawner + components: + - parent: 0 + pos: 21.5,-20.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3172 + type: TrashSpawner + components: + - parent: 0 + pos: 21.5,-17.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3173 + type: TrashSpawner + components: + - parent: 0 + pos: 26.5,-17.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3174 + type: TrashSpawner + components: + - parent: 0 + pos: 27.5,-13.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3175 + type: TrashSpawner + components: + - parent: 0 + pos: 24.5,-9.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3176 + type: TrashSpawner + components: + - parent: 0 + pos: 27.5,-7.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3177 + type: TrashSpawner + components: + - parent: 0 + pos: 27.5,-3.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3178 + type: TrashSpawner + components: + - parent: 0 + pos: 25.5,-1.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3179 + type: TrashSpawner + components: + - parent: 0 + pos: 21.5,-2.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3180 + type: TrashSpawner + components: + - parent: 0 + pos: 20.5,0.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3181 + type: TrashSpawner + components: + - parent: 0 + pos: 32.5,-6.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3182 + type: TrashSpawner + components: + - parent: 0 + pos: 37.5,-7.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3183 + type: TrashSpawner + components: + - parent: 0 + pos: 37.5,-3.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3184 + type: TrashSpawner + components: + - parent: 0 + pos: 42.5,-2.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3185 + type: TrashSpawner + components: + - parent: 0 + pos: 44.5,6.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3186 + type: TrashSpawner + components: + - parent: 0 + pos: 35.5,2.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3187 + type: TrashSpawner + components: + - parent: 0 + pos: 27.5,0.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3188 + type: TrashSpawner + components: + - parent: 0 + pos: 28.5,8.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3189 + type: TrashSpawner + components: + - parent: 0 + pos: 26.5,10.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3190 + type: TrashSpawner + components: + - parent: 0 + pos: 27.5,13.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3191 + type: TrashSpawner + components: + - parent: 0 + pos: 24.5,11.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3192 + type: TrashSpawner + components: + - parent: 0 + pos: 12.5,12.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3193 + type: TrashSpawner + components: + - parent: 0 + pos: 12.5,7.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3194 + type: TrashSpawner + components: + - parent: 0 + pos: 6.5,1.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3195 + type: TrashSpawner + components: + - parent: 0 + pos: 25.5,6.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3196 + type: TrashSpawner + components: + - parent: 0 + pos: 19.5,3.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3197 + type: TrashSpawner + components: + - parent: 0 + pos: -7.5,5.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3198 + type: TrashSpawner + components: + - parent: 0 + pos: -1.5,-0.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3199 + type: TrashSpawner + components: + - parent: 0 + pos: -8.5,-1.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3200 + type: TrashSpawner + components: + - parent: 0 + pos: -17.5,3.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3201 + type: TrashSpawner + components: + - parent: 0 + pos: -25.5,0.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3202 + type: TrashSpawner + components: + - parent: 0 + pos: -22.5,-6.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3203 + type: TrashSpawner + components: + - parent: 0 + pos: 4.5,9.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3204 + type: TrashSpawner + components: + - parent: 0 + pos: 1.5,16.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3205 + type: TrashSpawner + components: + - parent: 0 + pos: 13.5,19.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3206 + type: TrashSpawner + components: + - parent: 0 + pos: 12.5,15.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3207 + type: TrashSpawner + components: + - parent: 0 + pos: 9.5,13.5 + rot: -1.5707963267948966 rad + type: Transform +- uid: 3208 + type: TrashSpawner + components: + - parent: 0 + pos: 7.5,13.5 + rot: -1.5707963267948966 rad + type: Transform ... diff --git a/Resources/Prototypes/Entities/Buildings/Storage/Closets/job_closests.yml b/Resources/Prototypes/Entities/Buildings/Storage/Closets/job_closests.yml index 4cf72def1b..0de263da73 100644 --- a/Resources/Prototypes/Entities/Buildings/Storage/Closets/job_closests.yml +++ b/Resources/Prototypes/Entities/Buildings/Storage/Closets/job_closests.yml @@ -18,6 +18,8 @@ parent: WardrobeMixed name: "custodial closet" description: "It's a storage unit for janitorial clothes and gear." + components: + - type: CustodialClosetFill # Legal - type: entity diff --git a/Resources/Prototypes/Entities/Fluids/puddle.yml b/Resources/Prototypes/Entities/Fluids/puddle.yml index cf4d208424..7f28f6986f 100644 --- a/Resources/Prototypes/Entities/Fluids/puddle.yml +++ b/Resources/Prototypes/Entities/Fluids/puddle.yml @@ -30,7 +30,7 @@ name: gibblets id: PuddleGibblet parent: PuddleBase - description: Holds spilt milk + description: Gross. components: - type: Sprite sprite: Fluids/gibblet.rsi # Placeholder @@ -42,10 +42,10 @@ variants: 5 - type: entity - name: smear + name: puddle id: PuddleSmear parent: PuddleBase - description: Holds spilt milk + description: A puddle of liquid. components: - type: Sprite sprite: Fluids/smear.rsi # Placeholder @@ -57,10 +57,10 @@ variants: 7 - type: entity - name: splatter + name: puddle id: PuddleSplatter parent: PuddleBase - description: Holds spilt milk + description: A puddle of liquid. components: - type: Sprite sprite: Fluids/splatter.rsi # Placeholder @@ -75,7 +75,7 @@ name: vomit id: PuddleVomit parent: PuddleBase - description: + description: Gross. components: - type: Sprite sprite: Fluids/vomit.rsi @@ -86,12 +86,13 @@ - type: Puddle variants: 4 recolor: false + evaporate_threshold: -1 - type: entity name: toxins vomit id: PuddleVomitToxin - parent: PuddleBase - description: You probably don't want to get too close to this + parent: PuddleVomit + description: You probably don't want to get too close to this. components: - type: Sprite sprite: Fluids/vomit_toxin.rsi @@ -107,7 +108,7 @@ name: writing id: PuddleWriting parent: PuddleBase - description: Holds spilt milk + description: A bit of liquid. components: - type: Sprite sprite: Fluids/writing.rsi # Placeholder diff --git a/Resources/Prototypes/Entities/Items/Clothing/shoes.yml b/Resources/Prototypes/Entities/Items/Clothing/shoes.yml index 06f1a03c7b..bf998a48cf 100644 --- a/Resources/Prototypes/Entities/Items/Clothing/shoes.yml +++ b/Resources/Prototypes/Entities/Items/Clothing/shoes.yml @@ -387,6 +387,7 @@ sprite: Clothing/Shoes/galoshes.rsi - type: Clothing sprite: Clothing/Shoes/galoshes.rsi + - type: NoSlip - type: entity parent: ShoesBase diff --git a/Resources/Prototypes/Entities/Items/Consumables/trash.yml b/Resources/Prototypes/Entities/Items/Consumables/trash.yml index 462cbb9a6c..e028a15231 100644 --- a/Resources/Prototypes/Entities/Items/Consumables/trash.yml +++ b/Resources/Prototypes/Entities/Items/Consumables/trash.yml @@ -170,9 +170,8 @@ - type: Icon sprite: Objects/Consumable/Trash/tastybread.rsi -# TODO: Container - type: entity - name: trash bag (trash) + name: trash bag parent: TrashBase id: TrashBag components: @@ -180,6 +179,8 @@ sprite: Objects/Consumable/Trash/trashbag.rsi - type: Icon sprite: Objects/Consumable/Trash/trashbag.rsi + - type: Storage + Capacity: 125 - type: entity name: tray (trash) diff --git a/Resources/Prototypes/Entities/Markers/trash_spawner.yml b/Resources/Prototypes/Entities/Markers/trash_spawner.yml new file mode 100644 index 0000000000..b274b2263f --- /dev/null +++ b/Resources/Prototypes/Entities/Markers/trash_spawner.yml @@ -0,0 +1,44 @@ +- type: entity + name: Trash Spawner + id: TrashSpawner + components: + - type: Sprite + netsync: false + visible: false + sprite: Interface/Misc/markers.rsi + state: spawner_trash + - type: Icon + sprite: Interface/Misc/markers.rsi + state: spawner_trash + - type: Marker + - type: Clickable + - type: InteractionOutline + - type: Collidable + - type: TrashSpawner + rarePrototypes: + - PuddleVomit + - TrashPizzaBoxMessy + - TrashPlate + - TrashSnackBowl + - TrashTray + rareChance: 0.05 + prototypes: + - TrashRaisins + - TrashCandy + - TrashCheesieHonkers + - TrashChips + - TrashCornCob + - TrashLiquidFood + - TrashPistachiosPack + - TrashPizzaBoxMessy + - TrashPlasticBag + - TrashPopcorn + - TrashSemkiPack + - TrashSOSJerky + - TrashSyndiCakes + - TrashTastyBread + chance: 0.75 + offset: 0.2 + placement: + mode: AlignTileAny + diff --git a/Resources/Textures/Interface/Misc/markers.rsi/meta.json b/Resources/Textures/Interface/Misc/markers.rsi/meta.json index 251af4f644..a1fa3f2b53 100644 --- a/Resources/Textures/Interface/Misc/markers.rsi/meta.json +++ b/Resources/Textures/Interface/Misc/markers.rsi/meta.json @@ -465,6 +465,15 @@ 1.0 ] ] + }, + { + "name": "spawner_trash", + "directions": 1, + "delays": [ + [ + 1.0 + ] + ] }, { "name": "spawner_xenoai", diff --git a/Resources/Textures/Interface/Misc/markers.rsi/spawner_trash.png b/Resources/Textures/Interface/Misc/markers.rsi/spawner_trash.png new file mode 100644 index 0000000000..b92ba56c3d Binary files /dev/null and b/Resources/Textures/Interface/Misc/markers.rsi/spawner_trash.png differ