From 203a83526494e92216809633ed37f76dee9380c8 Mon Sep 17 00:00:00 2001 From: ike709 Date: Sat, 11 Jul 2020 16:49:54 -0500 Subject: [PATCH] Emergent Sanitation Gameplay (#1378) * Emergent Sanitation Gameplay * Fix the map * Address review * Mention if it's slippery in the description --- Content.Client/IgnoredComponents.cs | 3 + .../Components/Fluids/MopComponent.cs | 47 +- .../Components/Fluids/PuddleComponent.cs | 76 +- .../Components/Fluids/SpillHelper.cs | 13 +- .../Components/GUI/InventoryComponent.cs | 15 +- .../Items/Storage/Fill/CustodialClosetFill.cs | 33 + .../Markers/ConditionalSpawnerComponent.cs | 4 +- .../Markers/TrashSpawnerComponent.cs | 86 +++ .../Components/Movement/NoSlipComponent.cs | 13 + .../Components/Movement/SlipperyComponent.cs | 4 + .../EntitySystems/EffectBlockerSystem.cs | 12 + Resources/Audio/Effects/Fluids/splat.ogg | Bin 11605 -> 19446 bytes Resources/Maps/saltern.yml | 670 +++++++++++++++++- .../Storage/Closets/job_closests.yml | 2 + .../Prototypes/Entities/Fluids/puddle.yml | 19 +- .../Entities/Items/Clothing/shoes.yml | 1 + .../Entities/Items/Consumables/trash.yml | 5 +- .../Entities/Markers/trash_spawner.yml | 44 ++ .../Interface/Misc/markers.rsi/meta.json | 9 + .../Misc/markers.rsi/spawner_trash.png | Bin 0 -> 663 bytes 20 files changed, 1011 insertions(+), 45 deletions(-) create mode 100644 Content.Server/GameObjects/Components/Items/Storage/Fill/CustodialClosetFill.cs create mode 100644 Content.Server/GameObjects/Components/Markers/TrashSpawnerComponent.cs create mode 100644 Content.Server/GameObjects/Components/Movement/NoSlipComponent.cs create mode 100644 Resources/Prototypes/Entities/Markers/trash_spawner.yml create mode 100644 Resources/Textures/Interface/Misc/markers.rsi/spawner_trash.png 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 bc84113d3472e8ddfcb39d90a931d61b55c421ac..8b65c7970625f353fc9ba66ac6886296ade39a98 100644 GIT binary patch literal 19446 zcmcG$by!`!w;;R^ZUu_F6eteGiaQi{D^MJYyF-Cf-1U@F+}&M@)PUmdRw!H5`gmKcFM=S^$6z0LHY8 zm`QKt7znnf_yB+aKp9YD^ETydhWIUs=wn^7 z`K^`til~qy)mHdXzn(oeb11AYv~?I_q(gb4iwJ;p5tF43!Bc|jjkA|3NRe|pKS^0&yErdaV27c8L;{_)eoS7GV^Z6!vK`6bo$C<)R{DQ3 z)W3L8fv`v*5u0O6pgayA&RCe@0uJ>LT2ufOL=%unz>}-N>#rdj9HmwH!=i@EGs-2c zp{b+=CU*lJ4~uCJ_h}D5-INghWxij z&Ul+_14ZGAH~C8zC^#%p4vHkkKQn-B^2SL+t|%D;>xj3~F}sOPz<$ufcb9 zM^ZP7TkybA1T2ldp+)nb@%|$gC5GukU-*B4Z$!+c*|wk>fTb(*^n*dv$GZP1K4Ku> zOlF9>GXkmnVv$Vos0*o+DBR*Old?H_8S^P(VqeLZ1gWYM(-*h}{>7XM0D`gqO7Xwh zUs3)?it`gAnfe&&1~~g!9<%aqLjt?i->@YyI6x_8;Q^&MreQPFwUS@fwxD53kGTM* zF3(u-k4Aw^r818fMJSa0zQ^ zYUy~`>wa{fZwfJ(abKSHTb_q#K{nLw*hORF@-GWdsE<%D|_S6Yo*NdwLxz-PPU9lE%}tWU6PCT zKQzZGvM438C_Hj2JeDCM**YS%v?bTBuX4Bb|M~ov=E%6vf)A)U(k`_BO>??9$Rt5+ zs%23+`3FbgQIMc+(uDt=0RYeykD>6_j;N`#PO9@vsW2DHf9jEf}^k%8V7R4nXx!h!8%#+4{XV3IV=*l5jlB&t7!gpvh@`Xluu@X z&M_P^W7voiJ=to7*~p;TLjcqO0LszL@tw$JNbYC0)DQ=12CSE#z94B#j*&H)h>MY~ z5XWpiJ#S3zXFiNbAu=N$$1I`(dBT6PNDmqjX8-`IE(rK5!N6@U4Pes)EAeE* zN!$u}bPBlADtH#txJo+7+=F;LYMNSuxLT8%TJr=-T8(r{xJnAAnp(KhTKHPy$x2!c z7Q@^Yvzl54gj$o07V`xDI-uBaDa{gSO-?CIHn>kG`x!La8>Da#az75Ggr_y>rZxW( z?98L)rlqE3p{uE-t8FnmrKL0Fr+}w5t)VoFucg(fHG5{SmF&LkrlqfAp-ZT(OW+S$ z^W`bOyyDVEht|rfvf90yS_jg${TtcTx2dTNrKQg!OKnO^?bAwa=aa#Y#ig}-pGuj* ze!Hd2^BrI-b7?6{R4G$`Da%bOQ(G%rX{ke5Ez4~o^KQrfP4xVf`!7uc109Rm3oYGq zzxj&~zoy(xE)~Zcm2@WEHQfCcr`*>**&Fe_(wg+sN)9pkVDW3(k8<(isg~9>2($-S zXGG{>IqPS{xclbxBaXIzvH&s=RGU1Br$WhX=MgT0uR5yfteB zp1uuhcle_Wt8;GV2dnF$733#_QtBG7j!a#kt{zp8KgHCYZ$6^7O$O6ck0{BX&;y53 zSC6JEAkeq1X(X_H@;FpPMLwRHO-UnxS;gPU^B*TK04JBLFjbUCCjT%XE=N}|B`?SL zc1UiUDt|&;rX(LnUyiX6go>_UMuL&GamGdogiqf3aVR;u#wooD)wQjA;q+$j8;WCaM+o9TI){75;$$xNG6 z!HIfX>A}gSdt_hX95<`R1|w^wb5>{9D;DJPDBF$r309`7k}uBSpjny~vkV@+_Dj zK#`9C0WXj^LWv|tI2b|mBmSH&X@n1%(H+JqU+^8r>{ZEkZPVy%SD1u6aRH8*HAkMN zDMk%wbUZ+SJdCOFNNRC_UQqU;)xdevxllMZz!jP}81HeJ#xnyUNOz6o=zd(aH^EFC zh5E69DtLq+v_{wxztdeY!S%~+h##3c7+YW~JqYvxK~EE(4_wn{7;5>y$g1X0Gee+4 zpokL{qz9?W=i!-Q%gdF3(}5^y@+0SfBr1DskgsrmY-k`71REywq6=V;3*xk@yaH?Y zYgdq!M6QGU1)%uxY`p=1gFtv-=6%ewG~8$e{C|Hb zwiP@ssN*+Hx)+zmM`2Rlx;vGZap$|bZT;;SG__0WYk90sm27qXj0r9QuAWVsG zFxN+?JQ$m#kP3z)!3YYGI6WPx^`Of$AkN76AyHkv#9dw8hP7ZyFRCIbQC)%Yu|yuM zscuuzFk`w)l@C(~u_7{KpaT(#dL%C+BUp;&n0gJ`9k2n6OTh6e{zfRtFmRN|QUl0A zJC1G=vlv9ciI)!$qn+XVCO@Y8%gX7mJj8?YLH$>(euHwv_~Vf`k0SJ}fasC>RG@4< zvI>+pu+;ll_qT+S@oybU&VSW`;`dKKu*<*wsDnrTs}4utpLZXJ`nRMi|8EIfg5f_6 zIRBPl*b=BY|8!QDXUG9Rf}K@C%Nwi?it+nLOa0U>QO)A%%T%Xd5O4{m1H_O3s8|fo zIf1P?%q3pFpH4!apRwknJmUscJqcF;^!KfB+DM$A1#b2GB6ffi8$dAReIl+W0pS8yuVqDlsBbh}l>E?Rqe9lrRsK zm104PK%Ep*;~)oE*j}u|i-mT-n)`w1M!XWpb|8Q)fgOkqS{pRkt}m#(LdT)>3o8g2 zx$4M&<6S5KU;)5SBmp zaAdE}=kfL0#F&9FIM9wHKq`2Y z+kK~}uniLzi!j$m4;B|kt$aVn*S`!|my!EuUP0M$WvlQWR624iML$qvr-p{BDoFrd zZx*_#QyxD(G=}+tN3A4Dq)=FzdKkt_?bqr7+&ZgJU)UHeQG+3W*U|%5Nc%WXdyO77 z2=q~$u8A)yFtaP_-H-Z+kFWPG1LV>Z5Mqtudf}(53d5j-@tLqX4R{VbSYgN%>*iky@4kIJF!7G=%n zWkIjrr2c@8_Vw7)jB^^=F}Rl(_|1boyJEr!r-5F0n00^OacJjs{q74zozJ$A+d;tE zWLo#{`-Q8Q01K-^HZt`m<}SSN8vgcDZj0(p-kHL29>|*-EkIK!GV%U?)p%b2@b%hV zcbJ*U?Rm$!@6Bn0Wdh05Y>oTFN_7haH^wM6ny=Xgfr&z@0Wf#BLhtr7qm)a*=v34x z2a&DA)~fa_M}9Y<4*Qgl{-~(j{eEI?{)>x;&YX{(2fXmX{GK#ulilc9c5$oud4pa*BI!@gW{><*4WVgRfvK%&AY}Bus*D2)7HG~@wM{oDA zE;@g~fKJ8X1qA5Q zhXBoW(v;63ZOh0CsT&c{883)cK?Crz2+??ot&_Iwtuo1$ch`Ax{m?`1d8qEXbTxabT9|8JHD{ zW*E#^8fTwI%}wzd?NW}2p1YAuviMs?@Z^{<{+EeKxsVV`%3YYLV1O=|C#Mt%;s&0;X5}4A$|QsT&A3H z;xM7lvmcVNdYodX(Az=*~=(J!u6X%V!*5sOQJ>tla@-u`e*e&kQb z{CUbvYq_IDB;55z$~$k5c_RyY*VjEX)>`JjKUtE6o{P2VrEW5ZHhl>~_ix)2f_4{W zQYxWbT%>W_Y)usCXU*7DZI$)kgLEMVuQ7^HFJJJvhWaUg&*+Qf8r^(#94q4w{8YmGJ2+QL@`A^&A z>NQ0xCv^jCfJ;<}VE(gtU|!!nyK|4!b@+n??9uSw6E1qenXh*S1**a~hw!*2wH?1F zCg?JO10w=cz$ye+m2DJ~r27=?I=$>`y*o_KXS+SUI&nSKo%4Bp=M=hG*|<^pJ!G@G zu&lH%poQBk#^2xke6q*nO|JoO>Dky|dfn$}gS-_Yxm=U|*6B~d@i30V^x`-Ak=t`w zN0pms=nY@s@C)772ha%<2i=_BTF(t74pb|Tly2y~`uh89N(J31{uJ)4lU-o;LCqTg zs(*biwa`BJ@^=G#ibE4Jj2oRnK$()v(|-# zUB}B+Los;h)InM(vfq{@q03h)4ANq2F9CnPMU)86BT5F8rTJsK{!NnK$Y`K)5&?P% zh_3+wa1*ws>6m8OkW&A1fV;cLYL*iHWjQ@ErTc4Vsf=2Cv-P^`0KPc6(EZe+QmUjNGr^jM9S!ev`r%JZsxVmw#D_dFP3iH`n>x8~GB^`Du*Zi?QWr)k|CM z?;rpL$|4`m>5~U?ykL@*#XiI=gOe5aAZRr}Am;c30xUwh5Dzg)vVUf-Odb4uQcsp+3W@iY91BY%NHUK0jX0`*Nrn<8`-T z>~Dxgb`AI20+F2`P{jms&7C>^JTg0V&sV{<$apnJ$;$C=_fJ-ox94w7+DOusneQ?M z!uAAZB%Sf;NY-Wfh`{UEd#AJaad}a_M(;R2rCpm8sGPp0O&RKP!%5TBpzkHXzt4F+ zoQ`Mi8AAWvqQoMrii_J-5~y`w;EY!(|5WLKt8dyxUGXZ+XM^A0q;GB~MdKY9kH4?i zW%pegkMDUtgHowtvYxFN61C2^tsO^bMx)^=N+j zo|sVb=Fi<{rAR0oC^4{pl;p`jKQbi;nPHZ5)aygm*L(iA%1E_*2)ZoZT4BBi>BrhI z>#w=Sw-{-D&5=JMqxFfpT7fL1R25CVSd&_EXABCAkySvk(=o|20aPbzn!Td7ZtXXGKAIAQ~Sw`*RH#>lX6 zp&m_PD8P&fg(r9`MzGds5Xh*I!_I^XAf4I zlHQnA+z&PS&d_OMB@_S)K}XpH-GvDFh|V$D7CA$%q!&7OFX4EcGdSEem4h-2GGwU+76(AurlODMCeQ~8M^drLL_b)utX zoT}s3rPfFz?%uCmr?uN5_ujs9w>4)AS_gusD(_sdWyGOeaVCC+EhM(VJ~}ce7vxJu z5U1d)oMzIMSi%Ps4)rIR(g$cjWmhJ|Fmyo^$8x1pM%76?=4j#eO-&lx7dRpSY2>%z zC>Fqd3eulxLBQS3#bcgz-sgg`)3S=*f7sx6wbf!rf}$T1>_VU#!Ob8XC9RICV$c(} zGg?7fL0cbm?Txm=jv(UQRJl)FfR|C#$?&QMUGEE$W%!@Yq7`CxlC4#5oh#hzXUApNw*#JxB zj1rs$M!&3e{1Q-8(~XdA8#|ppki7{0V@8g3qIBSz0%floY~(ZYIEfuheOZ`amr#Yg zNMpL|5xvDbLXiX48;wQ8u8Dc3{}I!FY5{*VQ0Z3*#i7*&2Mie4GCV&KSWV~sP56jf zro{qAFxSy?kg2Mfi%3Wu2eN?;G7wK&X+%K|fDSuQfBCZ!<>9dM(lIUS)*AERr^8Bj zpLbN6;f{^8Ek*gv5ErVFz6=!!!-p=4CLcy`fX9;D$Vxdah5@Pt#@z$0Ld;$zl08l~ z4_~9iXVrEY5&}qE4?~ME)GOvfjh$LyR3p+^+X!FIYa~)$)aC1@aB19v!^1A2RYE7>6b=U_kR5lZ0i-UP@iVAx2Lmtp4j%G~raGZQNl6RWtm zq=cB5sF)ZNyO5-~*wVt}^2|CT6C(>Fvk0iX+++KMw-A4ExgjjylS++#DfnxI5#I!5 zOn~B1b;WvC?8d5)Quy*mqlCOVULad2$9(Q&J`StZIx2T>cotCLHmWr$bEqlPZ#Vo6 z;v^2JDn!!LZZF8Z2wgb|&w|g5l1zz?>8al5jFOQ_fB@;;XXL z2VV`3i3Kn{x{=`@Jm)S12G$2>Q7487rk9oIn7ka=4i>Li1X*NXFwk&~Xam2_N8QT; zwkK|5k_C1e8?vE3zz~+TGPnn1+#`hDeoN4{B=(N;al$SeI)s2or0MEY|JaSI<6OdL z6Q78%C~YbtnfMq|>SLq0S$!Q29 zoA%CCJV@0HP9z0cCie4@$A-@hjD?NhyPC7rOvRe9N;&3GA>~nalS-daR}LS1;WM=s z6ki{Z-jk|Biis(Qd; z>9W9m)C0|Ase>zrZwX)P4@OJ2a$ci`9YzWti36R8Dy?!MwhBW*Xuxg@(p#RwsN5Bi@QXMY3zSy=3*gmVSWis7@ zuYcGgF@cJL>mA6)kOh`5TuMJ7c)!j=vJa8^#7G})3i$+n{RjEfE%muOF)P-U|81cJ8} z3~$A}j-Nujigh33ci{Fu77y$EBRdP(=vX%e0N9vCL%-hbnJu~HOe?u6L*eo`r480(!j3qC8}NH<;=v6 z+-CY4q&6b}SjVDxJ)prM@IWptEg}L6)(JT z>e-rq=GZBbM(ei4Cx_AgLZf0H_5}u1Vq~s0fXR(Wz)K_9 z!co>#88L^ttBk?wE=2Ju$x^#M)Bt~bPKueK&0+JRcn+TUy~Lp~mN8oX_4~a95&*ax zYAylR?40}s(&#Sh#vrwwHJuY-UmR9RJnw%o0cA2%$<@rXuANnT|gQu zVC6j|q6l0qbBPWKDd)v4_Si1{i~{C3Wqh0V+ngDFkQb`&sd}j-CDcEh(Qk+jO4nnb zNGoW`W4%#-yoZUrq=$W%gEcKOK>k zxyO&CRW>r~P_OsEQEVYVF6zWhwN$!pa zRgmI!)ky{q& zU)zzQT$e*!%^?!gY2_Cvz-JC4GuEI!n}t9pfgUcn(?9~nr3*RDdVDq@`+YitHVOVB zNvlePHhZoM0F=`iIoINq!WvXuAVzx!-lz-+CV@tOhVbVdm{5!_EV9K=t! z?WGyT_kbgQyH7U7&u-x(SfDS=1Hz-2N7nA81gWX8^BENix|lvYGgz4;U1~nSglz+# z@WU(uw*bRVVb6!X`I1$gsw#7fdv5ckxeq~`b{4(_F5aZ@q_2y#?MQYkSly(nc+T+z zZiCd~PaKOa=KXa(Cx<}27T%|b0Br3`_xHx7C$%%XQz|B^OS3NL6DbTv3(Rh`T=+G| z4og|upgTg2ohb{J z)wj|U6FmWD4)o;0{+{Ue8N->DTg7Ak=Q|Hu7xPWEpvf->Pa~4e;oQfXM30P1u@&2GdtxS3^U%;n1rOv?-*t^a z>?OqYI;#|I&N0uQz(gB)ZwJVKuc1M=@Sa;Y*3aSija9?3QmAsD7zs#c6(&i_a`S!`|AtyMi=O#K z`mj#a-56t<8*(ttijL8*9_K%&=_wBJ4@5tE-)`KF`m|DINJdBitgTO54><6#E`pznbBDQURyu>-|^$Et5y-{+@-u57j&+eH>k33irJB ze%@<~OV=o(E_rBNtIQYT# zd=4TR6v{&O27Is%jT^wYW2D(&4;O0OPyZ@ZWc3*4+>0l8QWzIv(lYjX(tq)2t5IDaLAZaKT_+gBP@63BS=wHh)C2m?Wv>}| zsKcLNWqz2j+>R;0hi484-XE$S5H}y}*`4RPq_7Ad5n)T&P@-P;$TV^w(JPlblg%Jq zz07k@Ch<9{)|p=2|8)+j{k}I(HjWHINdF7~&psv`%DfnA^I>(7k|n0~D)wWfCyWqq z%bB-AQz9nRLf7N{F8W{`q)Fp!iQAbYZ;$hgKA)|Cyhyd_rHp;RgKhVVEDkrZ9M-cP znWnF=rC$W+IyoRM*r3P|FS!$U@W0Dy@wty&Z%qJ>(80~%5Gc2IbdR9|aG$cI{;mrK~n4vsqvz3ijE3=lU63Ln@5Qs%n`Czw)c<*&|e`XLl9W@1jORqN#&C=3QsEFES>J zs#yd@?7FU*QYCViM$6vW1Nf!PQYJUVC+J%*RShzGkFTK+BFP$?wO2&UNE86o$+dwd zc(MZ~v29`VXcF(`yr*~uG1K3qFUV9TZ~1d=6tSjFDfx!mD|jM{i{^cIqb}@|r>7Xa ziZtXeP=+1qiw8VBbX0!lr$8i)o<=8@98P~(i>6VTl*~qP!e)YGF4@1zNoopQU20nL z@NGJOgNywc$kZB;Byn}G@fhrF=^ZYTc63ys#{bQ_1L1xv^c&tv6+HUpZF>;x?o+vr zYYM3gY25FLQ|q`fAxw8!BF95g7Rx~)82QLlCVh$Vp)6Jp3IM_j2r!5cf39izz6%b+ z2$G$-O3?tpDg5|c(Ca^X7zng4W_zb=!uPlgF-4q2dx%pft&=*Fu{M`!?%t>PtZpCE z4W|&($eny-AgNg_lWz>y;8|lFDevUQJ8eP`cFDzS1V&|g0mYD4Cw(F=^k zgE2WDLxJc9$fwI^KyMWI7g>1>S&OE}*Ma<2m!LS7LY(i$`%$JcBP{Pal?(r8`M$Zp2vF0Cb$ z5eYTdxSuSCyypbih0*m5aiE#q-&8CUs}wx1+^HOqf*Jcq)5VX(#mBj0*dQA~wcp&j z0J}%XI2HnMs1r@8#GRYR%(#IfZL+h)_t^B{qN~7Lhc8K4nA35xFkond zb;msDeyFsN!cb4n$HQ-Md3|jZ`*F;tg+L`ytVd_n@80CaxiWsR$kG%)*=SbMgGsm!{f~kFg;$1c-%^ftFUck78PGO zVq|0hf9OTT#s-E~``K97*q9jDM8!nt85!uGi-`_?>1Y|~WOyFU>)5&WOs%eAt;LZpjpGZyLFJO?=ofSK3iIJxU8lww20)6j zN{lMvU9cjpi;(}|0{=qq4I?W>#pa3({0k)dj6&03;m+%d_@&Q2?WOBhWv)J}ZzA$r z`RHhj-W_|MyhQ-6gBQfIIb0yFx?b$bOJh!+K71(AlRFeA|@lyS!NT zWN&NBsMv8}f9JvBYQf4?W0-vW{o2Bq>a8+whjEW3z&{4#*15G8}L} zt+6OIWoWjtI=x}y9{y$>@V-}c=PB?x+VKx~pPNLtAiyYzga`zz^4oO@7bf|rUJw-n zWf2?{8>rmx^h2$3Y$fV#jxKKKpaZlY_4i|~mCJ*;d9|7UxtGDau^zF5Z75RvBz%|j zXXF>o>q7`D0I-3E3dVClY!-hW@yXKZ-D+n?T?cQQfU7WD+t#n`Sb^yCy?!Pdl3Oax z=_~Et0ilx1HM3)zDfB|6SV(pN=O#uO2Ds}q(Ddd0*#HSB2F;p)4?7%oCIBrh{%%_h zg8vIA8U|86 zV^n%&2t%U!2=}5HHxdjoAf@pXJx!>~H)K-bNS+lpx!9NTmmWM2%zBny7vyXx&Yf{% z2$({a=-E+YHP!vYuw;)Xb&AAO!VvD4Fy&tWLL3Tt-(~YL5L>KCiqNacK5vXl?(nqx zqP8vbM&X6UJ7MA!owoe^tI6~IHkYV~N=bg0T{hG~E>AKdBZg#0L&BdIzGldVUM70% z{UUwrNF?XOdCP8@(28%zA$8T;57;pZ6JaQtqy0P{ z|GaSu$U~dAVt4DG8H6%6Lf?7qM+^;6z0%#5ga=*tej)~ej5pOsZhNr+F7oKE?Qop^ z>Cu$T4h2oFPRPxeuUj1-Su`DW-?>DV5h)_SXezl|x1~|C29`Zdn0ME}Y!NkTFk5ZN znh#k)+s*k>Cw?=zYkT1GS6zEzK0)5kwK&VzTMH zpRS@ATP>Fz_-b`HBfg&yi`!j(9f5mihCMAwjSr>wO}|dE1M)IFvM^)cwwapLCL;}s z+c@+WKar9T8}obnr?i6wnQAHzLI0z%^P8+l1vQp_*LYD|U^@S|TM_$vJn9d+sVYVH zGT#$)KP5tsj%N8-as>0S5amOnZ^?U|-w1wr^M1Vg(gQ_Id-d~_=Iv*c$zsz-O}E5^ zFMfy(FDjrT=+O5GMHG5Kiby&oL}sTR`5FQUg}` zFPtgVT{pk)-*&tyLDDpQo4ptk&^GxHh^q5hRyPy#qf6zJzOR?)B9_pmXCBZcLEwn| zi!ubTLdrLW+;-e$_r7)MlH-<=l>A7vAks)`D;y=C<9SI4ENRh(T$vT2@8ExczX|^d zuM(vAJi8&cTn2ax&HEw;Vgg?A5Ez!5NaLr$Li5!Kq_o zm}&yqPFTtinJDT_h*R+z!`;VW-r&&IOi5m!PM3B*$D{rO&1+s^Tl!$l7j@L_Ot5iy zgzkO8AMyjKd-9$@JbNUK#9lYN;+w9VG;lnM z5BfA>UcLCiNe>4<;hYf|oo?(m4427ZAZdeC7yjwM}fYaJ^LGF z^g~))#Oyt0#!3Fak+E>`ZSI>tP15b%RrA!-&+%-btQ4V9K zDbJjJ>a8spLtT$5`jd7u;>of5(oMGpSE7`bK;PuWsG=o$WFO6s^!<;6=^u+m4x+2* zg%lr;Ao!xI@K`V9}q#FWp8O~ffT%VO2#<-T`~B7y--?t!QS1 zYCQBsyKJ)7k{nWMaYHPSavq!DafBq4dggRnms}uzS`BP8brC128&gUg)2A6G<19ZXqVp zSx2!e-E-ypFTa+VR}PY|<}k8g<|n7K>>6{&O*1Fkr@YYd^NGI22f{p8K7A>`jqxmu z!+QUifQ%rqZ1gqd6PJySD?``(quia53o@}f47SQ>-;ej1du1`6h5NH>gLg$}h$G!d zALQ%?7FMNzH;mf=MjJXqv*bfDo}|@%_%D_H{QMTuJ?s{RXW15# z43+N!*jb&I$SD0{7IFv6!f=_9LAmdzH>11_rS$Wy_ifM#-EZe9&Ar5OjNdO>6hI#SwC*;aW1cx zX{kX;0elo(6oyS!ff#T>t9)#c2swB^u?Y4M9V|Vg*tgK z=}^$n7j076$59i^V}c(dtI}A_wZ?A#!oW)QC5W%EB%W*Gv-ZxqKYUf z4&Ey6Itjx;RgZS6z|&q^#NS>1(LzEeOX0+0kR8Jt6MfyTJkSg_eri3)e3Hr> zW=qXnDH=)U&&S`+DoY=ts?P#$R5XV|3|n7^Q6VZyjR#81lnm8TGVGXq_FG`vnIqhv zuWApPDk$m}uTc#OcJI)1a>GrG5YZo%=EXtyPxadgNtDT!Zl=l%2JPqq*77> zA8KFz?&|oQaPsn(06Y`We)07LAqy0t?_Y1PoiBVlKASb2&Qbdmxz6zQjTa?rD@I;9 z<-q$eAm=PXrIm-zqe)PecvTfh{W;?V8(%t9oKv`Xp7u*)d-@4a&$oo@X|8CkHySQy z`X}lQw^X$m$UDbrEkOq0^=<7|ldOR1V@7DF!q2p5`Z!P6yU#G(?f@i?n;*Oda6-1O zpHkQ38t`Hwkp6i4g+0JwKvDRnjTBLVB~8sh7}Y3s&|*sZ^{sHs7=kJ$;D;bq1&60Q zBqa{s@16X*G?sfFI$jpj;$5P&`et{pmy4c%wlB+>%6OwKq7AR25$A>)c&ADTm0!W2 z>JWlH)e3$N5t~?f$C%69gTo`X^;^m?pW61P{BfBq%3%6z#^*W`tOeAlpo5O7HM)br z#5$G3)BJ_IbLuQ2P>o`WVbDo!U&I*zJ2{D{@R}< z>h)nj9uMHgAzhZDJcIj|CPCxI$11x%{;E?Ut)Rzh+(*V+S;1Q9rTyhrc{6ERFVX`$GBQJ8nw(d}gd3{i5OW z1=}5BaPvNf&P??-Bx+yKTi1We+OEpng^hwLuZ+#NQMSIyC$;mA&-u5(l(Nc4Y0hzF z&a-!$@&aUzqMzPEpO~}8OfWcAp7 zbNmQehCxtd7 z#tOzgxpLwu)ma5z*WOw_+i`J*pimFidxc=V?DBLQ zz{%BAynP|l0r!lgoCM%QUXFtfGk5?LTJ;}ra>XOcYuIIm%2;TS+{G62rp_wB?}&nN z(*6TtOB#(y!FY~c&#kg|&cSED-~QVLBw}Jix?>*#p$TNrmT%!Yh1|1-I9+PV`_nF? z;ipOm&DgH`lx;iTFH{>B^$NbC*$dwOCXHzNMV>5}Kccp!9(?q)MM*Y2G6=yk^P5wC zd^@oGVnyatsQeX$5L;-u7fiI*Q-_!%=C=LL<Ox}x`>992L;Ya3- zy+Z{ozoP6)%W5bglt#K#%ODAtJ;*(fSL2-zW%gFQ0#9qjpz6Bf{+Iq-+aD=1;cv?)ml55DcI6Gk+| z{m}oHCFCst2j20*z>uRkX@0KmY`Smz`;z}qtHBLp>S<7`SqLf;ob+X{2hFzmkAD(A#Vt9T#pt8J!`V*ULa+iw_`-*bE^Z+OeBFl3HBHHhG%a{E zIxT1I77gFZv!5Sin#2Ion4n5p%oM+Vc8!;E0Tzl6V>sw60KnhxWaA6~ynKbe23l7S zcNz}hDa}A63k~GUi2#Uz?tEPVb}QWg0G0v@Nh`_GOTW@r3(ose;Q&dcsY+ODW|oUHntso{8`5flHR|2kWl5{LQ5)H9%ne(F>duelC9|f$2Id4jzHt|FHnL|04zfzEuQ7*@UKb zQWU7mCl47}>!m=Eptqi#0NtWIWB?{W0RVvgYc_f?-+ol<>dlLF#r9wSYrg)mF_%QF zwG3FpB?7|*005{OMjikF985C+AWI|w0J!`BSSZrt1sd!nxydf(#t1yELi=&tObrGc z^EsWc{~SWWiG3hiN%GYB&<5z7NI8l}*hxU+6S!v!YBO-DoB)UU@-zt`@ZA|gP+y3z z!Si>H64(s@03g}`zhH64!2c2eAn$Jz0npX6_!$zgRS`M>HdW+63>2UP`}juQ+!2al zEPAMo#L>~BMT^h{005lzN$t~S-(xaiKQdZDx%$O?c3w2F^tbbN(7L7PS0k3|iHP_SB8_u9VaRm!9;8I<(`Uqw`fq$~hA$ zST4PEUphu>`HXcAHQ$>n!A!*eax3*?2Q-mzN^VS%^Cv$WHBj6uqXYG@6PUTua&#) z{k3IkqdDyfIQcc%uKe_^I^;Lco;~;bjbnOlpR`DRPr+R*E-Gv1gFT(^Cjm$RoH=(@ zU9B!oN0tREPy5Od9gf^aw)AVkMh+Vd0N(DO8uspAjrUHO-{*h!{a@a<8Ir?qvoKnq zXJKOS>(t_V0|2}+%epr#r#C*53pDlfGr}O+T+jNZ16qlZ?hedPEWqlP7fvz32FZAC zG`^^0=Wea=BkLj{Yfj|vmg+N-EeimoEj4UjO)3|S700_6wTg4}&qy%ndTAgF_}DyiNVRy~4pyzVaQfv$MR~zS${p{D1Ll z?eE?9uUd9DZ?yved@c2;UEggAxg;0hD_-h@*yt^a4GoX?+Z|Y40GRm4Pgj+|a_Snjzi?G*xQ9a*Hd7nK50K_R#ME->5`9Ed~n)2%-#QbUGySH|vw{r)G z0w7c0^QvZOyY{Y~PIc?p+Uf(iz~AYm)7)jEzOATa2(E|&kiw`~*gq;lt+-=gFm85Q zD+;Jx8gf9AGwIEMLQpf!+#4Z*Axj4YCCre8omQXJ%q|9Iz>QC91-pP7l2lDXQYmsa z6Ir1I>MJeHG#IUhgg6-WL!ewqRs%u=Nmja0B6e45MKyNUACd&kG*&2~@58svLJFIc zq05DDQD)GJp)nXwWsHG!NHYzKFS+XetQqtYu7$|Ty7SeK2>8W50eL)}%RNH?;JYA| zir&kM0eJ%8B|xR(Ox5blrWVE5ihBtn53&>hXu@Z?!dWGwtToW{h;+`7?EKZ5qSczG z5r5(w4-(VW6wQegkfxXA@%+Yx3mdKMGq$w*eD%mS`$dyTTS@D^%g$LS~^P zbosAMyY@&f;$8BO0^AGB8&csmu8aspQla^1eQgEy7=ypqNdbUI1H9z=7`_}7o*NXt z^jG!_U-XRP3XZi6MlXL%N1%&%YD)_`D;;ZV3dU>J#_J2mE7wc@ZQt zB%KSLZIAiq0|0jrl5QM6uO7AF8MPF2!FsM>bZ&4u7YO`+%S0e!@qjjvsf0xp=r`|Q zszDXIMYWuQ4O&zOb%%Zb^G?pN?_ zF#o+0h$tu>5`+Oy^fG~1lDToy^Zr|KA?Q;7BQ6ZFXF8~?|G<@wz)iRR@4)r(R1+mL;)c)p#++UL2LBinV13K@mJ8Pd<_uRwQCCjn6-hgza(PuL5sw8 zq1zHsnFtUBaiPdBvk~e4W$gco5DG9ufUl`E$poMHUfSS@lBFVm-YcHBV!*4-z4BA$(bM-q2DXIl_4!X@;LgryGD>W1>QR#OGa} z(p1c)vg(l}WHAU4T1@<)E4+}1?9t$+wd#^w%#21!E+!&j&{nWdk~<457QsLY3ifG3 zx!D7H6gab@e}aA20l?rF=+GZ$v@PJVD!je$H83zr4YvXv8Y0;?1kHv(FM_N@XFo9k z84aFUcKf!B&W>`QC_Lt3;DX0I!#89vIOhg0d?Zvxh% zq9E5E-mH0w#w^v8l0JZ6vUwGQ$sa2PfIoPIKq@Z1p_&9Y9SPrs%tYV-@)TAm7=$H@ zN)gH(5Dg;&-3HBtP6?)wQqh&(27`%g3n^!^jT{~SI3Z>QyD z{0qpxMXvuI!~TC$!v~gBC4eQlcwGX}+z|trpboTfHPZwPS>{t%c1d#c4;r&H(I6>c zq5QTeAtLTUW2>HcBso+gFY5txF|(WsStuFP1G2w`8rcJirX}k0LgIaH?jd7`Zct23 zLn=V&E|Sa|u?M9)5$RYme<9e5)MlMxi@1OwJp;ge&C!@~Cex1Z(~pQ4KwcdHEKo2M zs2NCdDXuK*E}=!{05ERNibe@7B)$P_Y0*(aiwqZiEYYwF<+-SVD!6z#$`YUpT?Xe~ zj8Z@~(k^DOfWX{YnLiXRYT(v0sV+wqiL;`kFGh70iP*ufx=Xl=MWImk%jE;WS{7Jv zT`bDOodv@ERf~Z^FM+{D4M0H$fk6}T>(Z8hKpP;#hDO31un~6ZLiQ#4=`78egWnik; z#C1l1Fo2opH8W8tK`KD}{1=|M=XZLUZ)Az`YI-oj%UDVt2VepKVtfip%I*hmoAFiO zwGgNUwi2obffxZG2=^-?Ab%TISy@@c$in$mWLn9$zL`y&YhX}K#C!>YOC&EZe_6X| z%gg`$F&=Q)1zdcLUm)7@x(i{#0TU-5w}8m$**VeqmCd!Yt;M6`b6|IKlwVMo?_$Qu zp82$CLrA4|uZqXyyz_<`}l>?rn%BaQ&!hbYh9V3?rEpHxMn_U)>GK0S%VRR`v3~mxyaKj|l zgjyvlD9A@|Jjyn|0}h8PD|2J;0Qmq(j?c9-5D`{u;j4XSFPzRdrZ)Tr`-cZBPe~hR zBlNOW8b75X48|*$^R>m`Qz}CT_ll?ZYu3K|Qe#K+zRMVrcK<+4Y!{3q_8}IR+J>{w zbN0^0DHp0*M{DOtv_6bH+#ceQElIn3R_T~Lj0kx6@C25z9H%)^(HQVM;b+LavA>`O zZBvQ%`bms>1A!uGFz3@K#Ruco#3j_Q+@)B&H$=CC3m-$+3}^<_o8(Q@xm25HYD90& zhoo^(-cBY7G^ytxvBwzhdmt<2CB|8Fb6JnA_}t zIzgWu4RLxnuRyD!!G|e(xKU0{)p>cm>#c0}4H?bP^bJ^dS!~*ilUv1giA*p_gEq%8 z${f?BppUAoPL);BSKogMG}_!hpG4g4|5Nu7A)RdMpyolX*3=+QJMBnhW=h{6P`Y3z zlj2s(=rC9~5^?`K17~~qz|zN3GHl^kzXT6LvyS&OwrYH#YW4KorgihA9J!|izp6jp zyO%#kafLg>;93dM7R!R{ViwnEwGG}+%U^ZS7(s8y47JRgxb!ZAYh({>CMpW>>{WVk zryx}okL)Z!9thq--AN?pJ8#$ z!)bjphP&S5va;U3$ND0lQEQZDs@^RoNgX?3<1Oo3g9n(&VQF)05Yybwko_DID{|8T zn|x>+cyuFd)x~H+D5S&qdsv*~GI!s+s&cTMg80zwH)x_P{4{#rt#vhOy^>o>v?i3| z%o`Jcd3>Ulz-*y4T9j*t*0a7(+TP7zN-pvu* zTFd{|^*$wYtf+)IiP$@&BpEuM6h3PbvxX~I7Abz$1uGg{D6TD9(%VUz{qeMJ`Z%Sh z&~K_PLZ^$YWUAaE-TS;JXIeio&HgZT<@fL(G%I} z?Dzh@ac7%zhwDcZPqAYaE$g~Q6N37?Z-h1u=UQ4^W%>l;lKeTDT2 zbszI+K9vp}82IqrT24pZQd%g<-KtEaxnH3zVDPEs@sa!*A#fw9>S?@3-WR zHjBR@pnSwm9;Fu+hW@^=I zS340>_D8PDwl(bF*7*Kr{pzR8&~n`+D#3wBeZiU-2j*L)vbqvP z5dseaUMn$FkkmtR?w>um`{hM5dvRv7-waQpz;1%g#s;szAuC8Pb%L~+vs{o7{0k;M z_cj!ePrAeIw2#_&8|sQ8S+;YgkwSG!2A2N1^IX7~fBSs&c$sa>r{0oreMfJc?!@VL z?Sv9X!G4;IxNObggLSFw4F9N25_&H?UzFeA^&0N4Rm=>c{vc`~=wobyGD z&`-7yi!5`82;r)!0}eTCVTD0lWR#B{zbq<#i}y<#nH^C{-+K*G=gF*`Ov|I9s~Egj zCW>jm6eP#zP`bC~3U&F&9mltGbtg$C9&hmZ_eefoea7qXwCZy{Xxx?Iplq{Q#J_g8 z&aD(<6S`yE6(M?KEILFZCXRykW54irf>2Tls(YL@ck-$@lR3w+mTYVA1J2^@n;-4U zkAxtrTvZdh)}JSIKb z#(P@JzxxcM$oT~8n)V^P^1yDWhK@wmZ9AuXw=QW*sA0;v=4Ui-^*0KpLff^oyq|Ye zVs79ed#Vk2cx{f}M}@S-1_vy+#}`D>=BR#Zp_^%W*Nod3K)?muB8iLRnUS31F#cib zFGwwL2mT$|qV*}Y`Rs9EzN4fW9Nq)Z!oY}u=aYYE7A!PdEUXhVw;$&=sS_w+CFVYV z|6HlI(eH(EG>GS|t{NFOW0h*gI6#!l_s`Cd4xN*>Zk-1;Tw zZffOwY|3C*F|$a^UaQdeJ9`1qvOPOi9kOL*LUq~u-W}BR4WmO2n%MmO42QGpixV^- z>+F5A_ovU!K1C+1A$erVn8b3XgvirshYZciid;G!H>6DKo>`2W<*1DoW9RUCTRaAB zJr|RgBrGyBJOn*Ht#ClAS*F5`)eV0%3Z{}PR!e>oh{D4~95F_*-+V*R5u(h-Mv@?Po0vg=z`Zz!VVUNz+XixZ1~v^XPT)v2K6T$>-KCC)48XIN2)Kr^tx2WuXs2@31+QJX&&^g$y8`4B1EvX&2nOlQV4JyzJ#O{eElq#Xya%Sh=C_ zZtud$slgGlRxz;k>P8S*E%C;)Ve0NZrbYkE&la+=&E(@pCq#(MGb5~ z)0O|{%MmtD%&aUIYPv@FzA?75S27<{U5EkI8I12KmZLSbG=HwdH(OXU@JNR`xw|tG zTB-{NSQWy!gYE31yZw%ypQC&o_TY_Q{2YfgC8SKPscsauPbzuIY9}tJzWG?Q891rj zNOqmVeL!o#{uKj4lLk^h+o$0@+j8&Q;=4*3ebj2M+SP$@P>TCu>*XNxy?+oTpuwu`uHwSOMCt-{d-TvEm>ciJ?gMWb{> zkY7TGsN;Z0b4IvB6xY@_tnvthyIlYDjg?&8Ym@?(JU8kg&xQ}=?ga0qLVsF|%QkJJ5?5o`n3UTnrlk@Qy7eN`#r-r5vPN7!H)+^hOCm_k1@z8xlvV zBAsidk;oU}%zhbv&L#wM=v>6kUJP;Psf|qM?siuk=1WvqWoEGuw&QPWH^@AB^K_g) za6w%b=~df3*sUPQD1w|xo(tN~w-`O>NA}nZjqWzMnfV*~4DSzKHy4u%+{kI)&D!wQ znbs&+GmTFQo4Ol>J=_>rer~*MS>R|BK9#_v>uu`l$hH&<>i-- z#$E(yFgO($pCH9T83dju_h!^fbCj273ERU};&QOd6FVi-a&_2zkABwj<1{bJt;DDA z-z9M-=N0<&w>(Q3H7bt3xvOg7F_7TyJLpek(<-V#Mk8YL%j@2C4o*#P(POftVQVwY z@>6m1F=uW6j^yDy6T01r`ZE3PLZlC#VTNevVm^yfClmJszib({BfQJ6$JypZ45?5W zmy0)*O?Oy#7XUAaO=1;j#_ zdS{bdl(qo=?W@_}TgyCiCL(0yJ5Sy)c3L5jMPMYR!4`~(0)PVVyKci22#sv(_%Niq zL;q>@ngqw2CwIx6#(vi?G`JWV3eicSU6&@ftqjH#Y}O(;#N2v*{2aH|Q!Pe0w>+g~ zJxXw;q2G|`dqIfhJYuOJwh11*FI`C4 zuZvN^q>S@M_^m?dPyJy%)^C+iWU`~u;!DJDJJ@L`4Is{&Mqe>ZMFXh=11YJ$1a1s+ zRXlQ=AvoE%X`D2Dikr`>ol80>nV}cxjDE_~wC9I;zc$)QZ06$v)y1XpmQ@S8T1JG2 zz3HCx>-2jOD<|$NMtf4U7ZGD1w-UX=p)2+}w{b&}w7=Gd%m<^S_+fu-*$Ud7mHM## zl|Xuf+hjhqwbCJ?d6k$X|M&qPu{nwN{8Y|f+FRSR@jTmD&4YVx<89}8{5wk)u=Q>w z8?Jkqdio1#2&<*c{&-QX7mQFn@9^>qHuv!H@(Az?@bOLd)_$*RudC+ehsd!PQ?@3?D*fme;I57)lTRRxx;Rt2{2`5#T&3)rF^PEQ=y z4EN7R&#*;Kt7m6nwZh{*=hxfD$EI4Unw@+_lvp&M@l{+)aLZ(>RXr$ab1)meGd1+$ z?0d(79JhmaezftcCgzCw;39|~o+U~LhqO97PQq~Hb!-5{TK&q&AM?P(lP$2|%CN)K zHe^eu@fMoK!}ILXzrU$t!lyFSR@6#g>bUI?s8OEmXuK%CEP@c~H?#2>9T*lZqNjJS zmxwJ$qqcLmD=TcJ+-0p)Uu>kYCa~dc8VPd-HAHy{ktO8jStUfbi+I%~E~Qs~C`o_3 zjV{e!^w)TEJKSX?o`4j4v%2Sx->cOiwdcCquPfU{tz}v~OLH3eK6h{TV5J+>3Vl^e zAMW;;rzKS4ZR=o?9-n<43`)Fel}O!c!61Uto0AX#u2CX#NmL!lkQEKyyypFpJ_mme z=Z%0Gi2p{|cylPnxvZV^gSYqgTOQ8hZ(KaKWo;}iG zedsZ5BspVMh&r3o?F7=oO8$&?!8L~a=b7AjdZr`hxRA=nE&c-Q045` z4-_rI8}3mioI?vWquLm*)2Ns5>gt=rcm=7^DzmR+^q7ZSH7E!aN{j)#?NB$Su9QMg zq4$q78Eun9*tU)L&Q=Sh)fw>uDa`FT$h2~B%TeRa_uEwQwsW4npzuE$qGZYzLZcpP z)(UDieok!MbfK=CuM|O6t<@Uy2j-1`PQbz23~eXa4E<XSb9* zTKum^3v9yTwb#u~{*0bqJV764engTg1tOjXI-gV(a2|wrB|S`PFxT48|MI1$F+^(I zXo3)LGv_9KQ_3Sg5~it|5BpWgXzBO*YVXRuh{wZHWAZXcmpe@)*#x(CC-iD~Nlvyh zJQm}a>ZG@ngh@#n)muxF7Ev%gf@OrXT5tWc6#i4OS8n;pm0%Ak+>;d(?ejGg?a-{N zV%iVITU=M-u@W6)sa-0f^E3U^8`)i%_KD!%36HdD~nZqbv;xWdN@y)&lU8IU8->%mX zg_j|;xSWh)lqV(pUs*~tx@!ggtWXM!txH+kDe0ZS;X_+WwMLr;xdg^A)7E39OAyVT zOgj0ZbMSkz(jMY&-qYoo1Rsuq_PlbQjHnm)D?Dx@7`2{9-y&=#!7Gx^ZswGXqbsJg z_jOk~^ptXYpH#;b{EOu=DGxDe)wNur5WH(eAqu1plaV#~uls(m{xZy(1p{aQB9h`8 zH}8^2Y>VbEb*C@eD@yJ|S=jMZ}{etwCZ4YSDwN(>) z45v5Nk5P3SX=;8sdAMwBS)5f?MFBw^I)>MqzRBq46F9tVU25l$&vYK@RwYx_e2hv^ zU(j%`MEHphZ@3@tW+Cr}^pD;W^G`26{h3-NlPtE>{_y+{Iei)#JneOJjP5S8meoy6 zr=UDB+l^N$WE2V%Y*9yXHv}@T$@76R-MJ~jqrbO4z5O-x%LNr>t_$e-PB{Dqdt?Zd z7|5l|imj7emg%3m#$NNrAmDvLY4z)G$z_;#KGz<;KZQI(Bh%LCR{KQKCsnv0lc4()widJ5_tn;Jh^sgag&t zqSDu*GAEjR$9q8sOlB>{2=CjU&y5z?9}*D+e|i$8zV(xW&6qhgJ%q&QRe(G`t%BG$ zBIaPyzbRl9VDn`|h!lNqSbTL;;47h%YPPe_v-Q~vX<`dzgDQi+TJ*s~|MFQ`Y)J5`f~ z&&ARk!sHj`k26zKj1^zXpIbWPoI(7zh5wk;Mc^?7m(!ZhOs}@t zp5prcc#`Sd?WvzV3x=3c>fG#ryeQ(uJingcc0>tl3mKdG0$fV8d&U`>pCg^KKYu#d zuAV-^7t{tHX$XbsZGY5wE5=NrHB5CEn&UXcU2%9Og2IdNel}<55N$P^yn*!QU8-<6 zMMc4(wmKb4N4du76>AeFh?5^dzJC{n449F_<%KhU zr1N>C>Z)x|Z7K6S(0kVmt2QRax%S{DAE?p%*Y7yv$Wc4Bzz-afJcCI7C?u3L#_fNs z27TKN74~cFH~ z^~;uD%)iqQo=W7tC6zCsn#wv}9^Q34SKQl6HZSJCja_K9daE%uaQJkmD$Bxeqd~Rd z?!9CG6z(v!!U1*~AxgIP`^MPY%^?=;0WLT2s_ltG7!v zCb|SZwz(Ke#WjC{S39yz^>gc*jrLcQT=;pr8+Lp0DsHHok_yF=bgEBq7*+5P$A6%> zro;}raeA{yQ33yoP?~B43_{vTL(xaYVhP~w_J*_P`n%Kp4pe&QE^Pe){oS6vkmmlv z&&tI*50zdrvfj<8Cf%R4bhl4-dTWkz{D&rI8_U-plfMz_Kk#sQwzflFhJCfB|B8=HEvNFuQTkMwv$`YQdYdvDA1567p;ThqCSdb!k z=6);*YHtgYGu_ih-g|K*it3l?Zj?YR3zE;RC2lYGuO*u7(DbkzdmU{`ez`|zo+6j@ zm3UvIV6N|2B;0n`*|+EL^`jJV#(T-99sCpIa)jXx_cHdAR{L9}Zg~~YMOL|i_RCo! m*$vrR_M3b(A;XBBkkAFv#*(A{$K>@Rr|?n=i(j*;SN|6)CAQN5 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 0000000000000000000000000000000000000000..b92ba56c3d6787c907e6c6b2da408cc8075117c5 GIT binary patch literal 663 zcmV;I0%-k-P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0xU^HK~z{r%~c6< z!ypVq{Stl?ep7gpc@y20ASSI3u-%z%%h(WUSLjIGKSjvpgTpF&ekN0R+xmbmq|FBMf(8Xn0_3|I=*aMrk5NOLiT*+LZimP~cdQ8RIxE!v^T^`8&}5u&j+| zO-B!&9r+9daVBnp1cvnePH145hSt}b(0n_BI2P}_#bu6h$2J32f{J0Taq)B94dRw~ x#V}{%a9g}$n6o-OAzm@e`J{NoUvS=rbKeHpFo>>3@002ovPDHLkV1g3xA|U_( literal 0 HcmV?d00001