From 4f9ae1116e9319c06f725b306ea0dae82c1529df Mon Sep 17 00:00:00 2001 From: Nemanja <98561806+EmoGarbage404@users.noreply.github.com> Date: Sat, 22 Apr 2023 03:03:50 -0400 Subject: [PATCH] Lipid Extractor (#15597) --- .../Components/FatExtractorComponent.cs | 94 ++++++++++ .../EntitySystems/FatExtractorSystem.cs | 164 ++++++++++++++++++ Content.Shared/Lock/LockComponent.cs | 6 + Content.Shared/Lock/LockSystem.cs | 4 +- .../Components/SharedFatExtractor.cs | 16 ++ .../nutrition/components/fat-extractor.ftl | 8 + .../Catalog/Research/technologies.yml | 1 + .../Advertisements/fatextractor.yml | 9 + .../Circuitboards/Machine/production.yml | 17 ++ .../Structures/Machines/fatextractor.yml | 113 ++++++++++++ .../Entities/Structures/Machines/lathe.yml | 1 + .../Prototypes/Recipes/Lathes/electronics.yml | 8 + .../Machines/fat_sucker.rsi/fat.png | Bin 0 -> 804 bytes .../Machines/fat_sucker.rsi/fat_door_off.png | Bin 0 -> 407 bytes .../Machines/fat_sucker.rsi/fat_door_on.png | Bin 0 -> 462 bytes .../Machines/fat_sucker.rsi/fat_green.png | Bin 0 -> 191 bytes .../Machines/fat_sucker.rsi/fat_panel.png | Bin 0 -> 195 bytes .../Machines/fat_sucker.rsi/fat_red.png | Bin 0 -> 188 bytes .../Machines/fat_sucker.rsi/fat_smoke.png | Bin 0 -> 534 bytes .../Machines/fat_sucker.rsi/fat_stack.png | Bin 0 -> 224 bytes .../Machines/fat_sucker.rsi/fat_yellow.png | Bin 0 -> 190 bytes .../Machines/fat_sucker.rsi/meta.json | 47 +++++ 22 files changed, 486 insertions(+), 2 deletions(-) create mode 100644 Content.Server/Nutrition/Components/FatExtractorComponent.cs create mode 100644 Content.Server/Nutrition/EntitySystems/FatExtractorSystem.cs create mode 100644 Content.Shared/Nutrition/Components/SharedFatExtractor.cs create mode 100644 Resources/Locale/en-US/nutrition/components/fat-extractor.ftl create mode 100644 Resources/Prototypes/Catalog/VendingMachines/Advertisements/fatextractor.yml create mode 100644 Resources/Prototypes/Entities/Structures/Machines/fatextractor.yml create mode 100644 Resources/Textures/Structures/Machines/fat_sucker.rsi/fat.png create mode 100644 Resources/Textures/Structures/Machines/fat_sucker.rsi/fat_door_off.png create mode 100644 Resources/Textures/Structures/Machines/fat_sucker.rsi/fat_door_on.png create mode 100644 Resources/Textures/Structures/Machines/fat_sucker.rsi/fat_green.png create mode 100644 Resources/Textures/Structures/Machines/fat_sucker.rsi/fat_panel.png create mode 100644 Resources/Textures/Structures/Machines/fat_sucker.rsi/fat_red.png create mode 100644 Resources/Textures/Structures/Machines/fat_sucker.rsi/fat_smoke.png create mode 100644 Resources/Textures/Structures/Machines/fat_sucker.rsi/fat_stack.png create mode 100644 Resources/Textures/Structures/Machines/fat_sucker.rsi/fat_yellow.png create mode 100644 Resources/Textures/Structures/Machines/fat_sucker.rsi/meta.json diff --git a/Content.Server/Nutrition/Components/FatExtractorComponent.cs b/Content.Server/Nutrition/Components/FatExtractorComponent.cs new file mode 100644 index 0000000000..8a0826c29c --- /dev/null +++ b/Content.Server/Nutrition/Components/FatExtractorComponent.cs @@ -0,0 +1,94 @@ +using Content.Server.Nutrition.EntitySystems; +using Content.Shared.Construction.Prototypes; +using Content.Shared.Nutrition.Components; +using Robust.Shared.Audio; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + +namespace Content.Server.Nutrition.Components; + +/// +/// This is used for a machine that extracts hunger from entities and creates meat. Yum! +/// +[RegisterComponent, Access(typeof(FatExtractorSystem))] +public sealed class FatExtractorComponent : Component +{ + /// + /// Whether or not the extractor is currently extracting fat from someone + /// + [DataField("processing")] + public bool Processing = true; + + /// + /// How much nutrition is extracted per second. + /// + [DataField("nutritionPerSecond"), ViewVariables(VVAccess.ReadWrite)] + public int NutritionPerSecond = 10; + + /// + /// The base rate of extraction + /// + [DataField("baseNutritionPerSecond"), ViewVariables(VVAccess.ReadWrite)] + public int BaseNutritionPerSecond = 10; + + #region Machine Upgrade + /// + /// Which machine part affects the nutrition rate + /// + [DataField("machinePartNutritionRate", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MachinePartNutritionRate = "Laser"; + + /// + /// The increase in rate per each rating above 1. + /// + [DataField("partRatingRateMultiplier")] + public float PartRatingRateMultiplier = 10; + #endregion + + /// + /// An accumulator which tracks extracted nutrition to determine + /// when to spawn a meat. + /// + [DataField("nutrientAccumulator"), ViewVariables(VVAccess.ReadWrite)] + public int NutrientAccumulator; + + /// + /// How high has to be to spawn meat + /// + [DataField("nutrientPerMeat"), ViewVariables(VVAccess.ReadWrite)] + public int NutrientPerMeat = 60; + + /// + /// Meat spawned by the extractor. + /// + [DataField("meatPrototype", customTypeSerializer: typeof(PrototypeIdSerializer)), ViewVariables(VVAccess.ReadWrite)] + public string MeatPrototype = "FoodMeat"; + + /// + /// When the next update will occur + /// + [DataField("nextUpdate", customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)] + public TimeSpan NextUpdate; + + /// + /// How long each update takes + /// + [DataField("updateTime"), ViewVariables(VVAccess.ReadWrite)] + public TimeSpan UpdateTime = TimeSpan.FromSeconds(1); + + /// + /// The sound played when extracting + /// + [DataField("processSound")] + public SoundSpecifier? ProcessSound; + + public IPlayingAudioStream? Stream; + + /// + /// A minium hunger threshold for extracting nutrition. + /// Ignored when emagged. + /// + [DataField("minHungerThreshold")] + public HungerThreshold MinHungerThreshold = HungerThreshold.Okay; +} diff --git a/Content.Server/Nutrition/EntitySystems/FatExtractorSystem.cs b/Content.Server/Nutrition/EntitySystems/FatExtractorSystem.cs new file mode 100644 index 0000000000..6ab432d490 --- /dev/null +++ b/Content.Server/Nutrition/EntitySystems/FatExtractorSystem.cs @@ -0,0 +1,164 @@ +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using Content.Server.Construction; +using Content.Server.Nutrition.Components; +using Content.Server.Power.Components; +using Content.Server.Power.EntitySystems; +using Content.Server.Storage.Components; +using Content.Shared.Emag.Components; +using Content.Shared.Emag.Systems; +using Content.Shared.Nutrition.Components; +using Content.Shared.Nutrition.EntitySystems; +using Content.Shared.Storage.Components; +using Robust.Shared.Timing; + +namespace Content.Server.Nutrition.EntitySystems; + +/// +/// This handles logic and interactions relating to +/// +public sealed class FatExtractorSystem : EntitySystem +{ + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly HungerSystem _hunger = default!; + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + + /// + public override void Initialize() + { + SubscribeLocalEvent(OnRefreshParts); + SubscribeLocalEvent(OnUpgradeExamine); + SubscribeLocalEvent(OnUnpaused); + SubscribeLocalEvent(OnGotEmagged); + SubscribeLocalEvent(OnClosed); + SubscribeLocalEvent(OnOpen); + SubscribeLocalEvent(OnPowerChanged); + } + + private void OnRefreshParts(EntityUid uid, FatExtractorComponent component, RefreshPartsEvent args) + { + var rating = args.PartRatings[component.MachinePartNutritionRate] - 1; + component.NutritionPerSecond = component.BaseNutritionPerSecond + (int) (component.PartRatingRateMultiplier * rating); + } + + private void OnUpgradeExamine(EntityUid uid, FatExtractorComponent component, UpgradeExamineEvent args) + { + args.AddPercentageUpgrade("fat-extractor-component-rate", (float) component.NutritionPerSecond / component.BaseNutritionPerSecond); + } + + private void OnUnpaused(EntityUid uid, FatExtractorComponent component, ref EntityUnpausedEvent args) + { + component.NextUpdate += args.PausedTime; + } + + private void OnGotEmagged(EntityUid uid, FatExtractorComponent component, ref GotEmaggedEvent args) + { + args.Handled = true; + args.Repeatable = false; + } + + private void OnClosed(EntityUid uid, FatExtractorComponent component, ref StorageAfterCloseEvent args) + { + StartProcessing(uid, component); + } + + private void OnOpen(EntityUid uid, FatExtractorComponent component, ref StorageAfterOpenEvent args) + { + StopProcessing(uid, component); + } + + private void OnPowerChanged(EntityUid uid, FatExtractorComponent component, ref PowerChangedEvent args) + { + if (!args.Powered) + StopProcessing(uid, component); + } + + public void StartProcessing(EntityUid uid, FatExtractorComponent? component = null, EntityStorageComponent? storage = null) + { + if (!Resolve(uid, ref component, ref storage)) + return; + + if (component.Processing) + return; + + if (!this.IsPowered(uid, EntityManager)) + return; + + if (!TryGetValidOccupant(uid, out _, component, storage)) + return; + + component.Processing = true; + _appearance.SetData(uid, FatExtractorVisuals.Processing, true); + component.Stream = _audio.PlayPvs(component.ProcessSound, uid); + component.NextUpdate = _timing.CurTime + component.UpdateTime; + } + + public void StopProcessing(EntityUid uid, FatExtractorComponent? component = null) + { + if (!Resolve(uid, ref component)) + return; + + if (!component.Processing) + return; + + component.Processing = false; + _appearance.SetData(uid, FatExtractorVisuals.Processing, false); + component.Stream?.Stop(); + } + + public bool TryGetValidOccupant(EntityUid uid, [NotNullWhen(true)] out EntityUid? occupant, FatExtractorComponent? component = null, EntityStorageComponent? storage = null) + { + occupant = null; + if (!Resolve(uid, ref component, ref storage)) + return false; + + occupant = storage.Contents.ContainedEntities.FirstOrDefault(); + + if (!TryComp(occupant, out var hunger)) + return false; + + if (hunger.CurrentHunger < component.NutritionPerSecond) + return false; + + if (hunger.CurrentThreshold < component.MinHungerThreshold && !HasComp(uid)) + return false; + + return true; + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var fat, out var storage)) + { + if (TryGetValidOccupant(uid, out var occupant, fat, storage)) + { + if (!fat.Processing) + StartProcessing(uid, fat, storage); + } + else + { + StopProcessing(uid, fat); + continue; + } + + if (!fat.Processing) + continue; + + if (_timing.CurTime < fat.NextUpdate) + continue; + fat.NextUpdate += fat.UpdateTime; + + _hunger.ModifyHunger(occupant.Value, -fat.NutritionPerSecond); + fat.NutrientAccumulator += fat.NutritionPerSecond; + if (fat.NutrientAccumulator >= fat.NutrientPerMeat) + { + fat.NutrientAccumulator -= fat.NutrientPerMeat; + Spawn(fat.MeatPrototype, Transform(uid).Coordinates); + } + } + } +} diff --git a/Content.Shared/Lock/LockComponent.cs b/Content.Shared/Lock/LockComponent.cs index d8c0963830..fae5788612 100644 --- a/Content.Shared/Lock/LockComponent.cs +++ b/Content.Shared/Lock/LockComponent.cs @@ -34,6 +34,12 @@ public sealed class LockComponent : Component /// [DataField("lockingSound"), ViewVariables(VVAccess.ReadWrite)] public SoundSpecifier LockSound = new SoundPathSpecifier("/Audio/Machines/door_lock_on.ogg"); + + /// + /// Whether or not an emag disables it. + /// + [DataField("breakOnEmag")] + public bool BreakOnEmag = true; } [Serializable, NetSerializable] diff --git a/Content.Shared/Lock/LockSystem.cs b/Content.Shared/Lock/LockSystem.cs index 2af6366982..79a0e26fbd 100644 --- a/Content.Shared/Lock/LockSystem.cs +++ b/Content.Shared/Lock/LockSystem.cs @@ -203,7 +203,7 @@ public sealed class LockSystem : EntitySystem private bool HasUserAccess(EntityUid uid, EntityUid user, AccessReaderComponent? reader = null, bool quiet = true) { // Not having an AccessComponent means you get free access. woo! - if (!Resolve(uid, ref reader)) + if (!Resolve(uid, ref reader, false)) return true; if (_accessReader.IsAllowed(user, reader)) @@ -234,7 +234,7 @@ public sealed class LockSystem : EntitySystem private void OnEmagged(EntityUid uid, LockComponent component, ref GotEmaggedEvent args) { - if (!component.Locked) + if (!component.Locked || !component.BreakOnEmag) return; _audio.PlayPredicted(component.UnlockSound, uid, null, AudioParams.Default.WithVolume(-5)); _appearanceSystem.SetData(uid, StorageVisuals.Locked, false); diff --git a/Content.Shared/Nutrition/Components/SharedFatExtractor.cs b/Content.Shared/Nutrition/Components/SharedFatExtractor.cs new file mode 100644 index 0000000000..b52e1a9022 --- /dev/null +++ b/Content.Shared/Nutrition/Components/SharedFatExtractor.cs @@ -0,0 +1,16 @@ +using Robust.Shared.Serialization; + +namespace Content.Shared.Nutrition.Components; + +[Serializable, NetSerializable] +public enum FatExtractorVisuals : byte +{ + Processing +} + +public enum FatExtractorVisualLayers : byte +{ + Light, + Stack, + Smoke +} diff --git a/Resources/Locale/en-US/nutrition/components/fat-extractor.ftl b/Resources/Locale/en-US/nutrition/components/fat-extractor.ftl new file mode 100644 index 0000000000..b2df0e079e --- /dev/null +++ b/Resources/Locale/en-US/nutrition/components/fat-extractor.ftl @@ -0,0 +1,8 @@ +fat-extractor-component-rate = extraction rate + +fat-extractor-fact-1 = Fats are triglycerides made up of a combination of different building blocks; glycerol and fatty acids. +fat-extractor-fact-2 = Adults should get a recommended 20-35% of their energy intake from fat. +fat-extractor-fact-3 = Being overweight or obese puts you at an increased risk of chronic diseases, such as cardiovascular diseases, metabolic syndrome, type 2 diabetes, and some types of cancers. +fat-extractor-fact-4 = Not all fats are bad. A certain amount of fat is an essential part of a healthy balanced diet. +fat-extractor-fact-5 = Saturated fat should form no more than 11% of your daily calories. +fat-extractor-fact-6 = Unsaturated fat, that is monounsaturated fats, polyunsaturated fats, and omega-3 fatty acids, is found in plants and fish. \ No newline at end of file diff --git a/Resources/Prototypes/Catalog/Research/technologies.yml b/Resources/Prototypes/Catalog/Research/technologies.yml index bfbae68d97..8641bc892e 100644 --- a/Resources/Prototypes/Catalog/Research/technologies.yml +++ b/Resources/Prototypes/Catalog/Research/technologies.yml @@ -61,6 +61,7 @@ - MicrowaveMachineCircuitboard - BoozeDispenserMachineCircuitboard - SodaDispenserMachineCircuitboard + - FatExtractorMachineCircuitboard # Biological Technology Tree diff --git a/Resources/Prototypes/Catalog/VendingMachines/Advertisements/fatextractor.yml b/Resources/Prototypes/Catalog/VendingMachines/Advertisements/fatextractor.yml new file mode 100644 index 0000000000..4e8b3eb88e --- /dev/null +++ b/Resources/Prototypes/Catalog/VendingMachines/Advertisements/fatextractor.yml @@ -0,0 +1,9 @@ +- type: advertisementsPack + id: FatExtractorFacts + advertisements: + - fat-extractor-fact-1 + - fat-extractor-fact-2 + - fat-extractor-fact-3 + - fat-extractor-fact-4 + - fat-extractor-fact-5 + - fat-extractor-fact-6 diff --git a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml index 4ace8ea4f0..7df228de48 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml @@ -673,6 +673,23 @@ Glass: 2 Cable: 2 +- type: entity + id: FatExtractorMachineCircuitboard + parent: BaseMachineCircuitboard + name: lipid extractor machine board + components: + - type: Sprite + state: service + - type: MachineBoard + prototype: FatExtractor + requirements: + Laser: 1 + componentRequirements: + Utensil: + Amount: 1 + DefaultPrototype: ForkPlastic + ExamineName: Utensil + - type: entity id: EmitterCircuitboard parent: BaseMachineCircuitboard diff --git a/Resources/Prototypes/Entities/Structures/Machines/fatextractor.yml b/Resources/Prototypes/Entities/Structures/Machines/fatextractor.yml new file mode 100644 index 0000000000..3914f5e5e2 --- /dev/null +++ b/Resources/Prototypes/Entities/Structures/Machines/fatextractor.yml @@ -0,0 +1,113 @@ +- type: entity + id: FatExtractor + parent: BaseMachinePowered + name: lipid extractor + description: Safely and efficiently extracts excess fat from a subject. + components: + - type: FatExtractor + processSound: + path: /Audio/Machines/microwave_loop.ogg + params: + loop: true + maxdistance: 5 + - type: Sprite + netsync: false + sprite: Structures/Machines/fat_sucker.rsi + snapCardinals: true + layers: + - state: fat + - state: fat_door_off + map: ["enum.StorageVisualLayers.Door"] + - state: fat_red + shader: unshaded + map: ["enum.PowerDeviceVisualLayers.Powered"] + - state: fat_green + shader: unshaded + visible: false + map: ["enum.FatExtractorVisualLayers.Light"] + - state: fat_panel + visible: false + map: ["enum.WiresVisualLayers.MaintenancePanel"] + - state: fat_stack #cash cash cash + visible: false + map: ["enum.FatExtractorVisualLayers.Stack"] + - state: fat_smoke + visible: false + map: ["enum.FatExtractorVisualLayers.Smoke"] + - type: Lock + breakOnEmag: false + - type: GenericVisualizer + visuals: + enum.StorageVisuals.Open: + enum.StorageVisualLayers.Door: + True: { visible: false } + False: { visible: true } + enum.FatExtractorVisuals.Processing: + enum.StorageVisualLayers.Door: + True: { state: fat_door_on } + False: { state: fat_door_off } + enum.FatExtractorVisualLayers.Smoke: + True: { visible: true } + False: { visible: false } + enum.FatExtractorVisualLayers.Stack: + True: { visible: true } + False: { visible: false } + enum.FatExtractorVisualLayers.Light: + True: { visible: true } + False: { visible: false } + enum.PowerDeviceVisuals.Powered: + enum.FatExtractorVisualLayers.Light: + False: { visible: false } + enum.PowerDeviceVisualLayers.Powered: + True: { visible: true } + False: { visible: false } + enum.StorageVisuals.HasContents: + enum.PowerDeviceVisualLayers.Powered: + True: { state: fat_yellow } + False: { state: fat_red } + enum.WiresVisuals.MaintenancePanelState: + enum.WiresVisualLayers.MaintenancePanel: + True: { visible: true } + False: { visible: false } + - type: Construction + graph: Machine + node: machine + containers: + - machine_board + - machine_parts + - entity_storage + - type: EmptyOnMachineDeconstruct + containers: + - entity_storage + - type: Damageable + damageContainer: Inorganic + damageModifierSet: StrongMetallic + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 100 + behaviors: + - !type:ChangeConstructionNodeBehavior + node: machineFrame + - !type:DoActsBehavior + acts: ["Destruction"] + - type: Machine + board: FatExtractorMachineCircuitboard + - type: Wires + BoardName: FatExtractor + LayoutId: FatExtractor + - type: Appearance + - type: Speech + - type: Advertise + pack: FatExtractorFacts + - type: StaticPrice + price: 1000 + - type: ResistLocker + - type: EntityStorage + capacity: 1 + - type: ContainerContainer + containers: + machine_board: !type:Container + machine_parts: !type:Container + entity_storage: !type:Container diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index 62a89a3dda..18bae43997 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -300,6 +300,7 @@ - ReagentGrinderMachineCircuitboard - HotplateMachineCircuitboard - MicrowaveMachineCircuitboard + - FatExtractorMachineCircuitboard - UniformPrinterMachineCircuitboard - ShuttleConsoleCircuitboard - RadarConsoleCircuitboard diff --git a/Resources/Prototypes/Recipes/Lathes/electronics.yml b/Resources/Prototypes/Recipes/Lathes/electronics.yml index 468c0e5a56..5cb7cf7c5d 100644 --- a/Resources/Prototypes/Recipes/Lathes/electronics.yml +++ b/Resources/Prototypes/Recipes/Lathes/electronics.yml @@ -424,6 +424,14 @@ Steel: 100 Glass: 900 +- type: latheRecipe + id: FatExtractorMachineCircuitboard + result: FatExtractorMachineCircuitboard + completetime: 4 + materials: + Steel: 100 + Glass: 900 + - type: latheRecipe id: SurveillanceCameraRouterCircuitboard result: SurveillanceCameraRouterCircuitboard diff --git a/Resources/Textures/Structures/Machines/fat_sucker.rsi/fat.png b/Resources/Textures/Structures/Machines/fat_sucker.rsi/fat.png new file mode 100644 index 0000000000000000000000000000000000000000..cbd63ae3eeca4685ae30d26740ab87c205a6c40b GIT binary patch literal 804 zcmV+<1Ka$GP)ovdj-rdt9&tsLS zf?9Sy|MK;FCkW>Xa1yN6G=l)bV>X8v81t7FYN5PV0A78PxcsWIDpUa=$YWN)s|n53 ztL8~kZ<{G+0NiI20Oq_pHp2fXW3x}Z0l48<+!N;N;!Mr?8i2X0C2btD(@$EXGofqd zDmiv!G#sk|K*x@ch~vzwS+c3KD?=aNJa>v)Ut3L#alQpE&DPF*0f5z?I65p(PEtC0 zboWj)!2NpFi~A!s04ud=gK^7*>)&3fVJhf!Ea0ju<|s`p{2#(Wz=~v8sI>_*&wdHV0*qH z>;tO)1m^IWDntPIG$G7?H-3U6k1Awj(1nZVoVI3PA#Wf7Apu|xh-$qm%(*AhQZxVfW^4sm+#69JqdvlS z0`5QZ@rw_NtN^42VUq2$%%+9KWv$VXAO9mOfb!t|0AY+k(EkqvcfXli0yMk7S$-I@ zu{wsf@9Y=H?<-%drX0(qSM%^#0DP^LY4r4%xG?>+AYL4}*y>h6tWJh@^!8f;zSTEc z$A9K(PDoY&#w>nD1BrbAlNbWR{o@2lQXgYB=Xu&bFjp)@egm2yTmf|@NirevU&%=l iz$SB&3f0CuO@9G-`H058j|@@(0000VQ!Pj5=V{0VFw~pk?8I7<)oZJR>#KlN>BaP{_MB!}Pzr!U-KFg4J?tA^|}0CEH}`1bWHS>}-K0Bu!S z6i0Azb7RPZLV#ut09k(Y@JWUTx9>41s48L5!~%-4Auh{7w6(1{Z5)6c?6@pP4gvJE zLa_s2aSx(F0OnJ48kPn?^zD0(sOJEfj|k-gSOTPa2v8f)+yR8j2eKT19H**Ea$x%D z%eM^D;=*t?48X*w>HuVmVGaUW1aky3n-Cz|0U%3}9f9m?QUFy#00dyZri%m6EeG*I zi48f(i3xs^9RO-nOkK7gYdZi`8R1It_!=)HhX5=GpoaoBKuna7>;RZ=qB1+cAt5F$ z36BDprLUeo2eX$=uOQfLBRdfiV>mHj_!q^5008xhqF#b?bf*9S002ovPDHLkV1n2a BmyQ4c literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Machines/fat_sucker.rsi/fat_door_on.png b/Resources/Textures/Structures/Machines/fat_sucker.rsi/fat_door_on.png new file mode 100644 index 0000000000000000000000000000000000000000..a47692a251e973c81a1f5a30894646403bd369b1 GIT binary patch literal 462 zcmV;<0WtoGP)VQ!Pj5=V{0VFw~pk?8I7<)oZJR>#KlN>BaP{_MB!}Pzr!U-KFg4J?tA^|}0CEH}`1bWHS>}-K0Bu!S zh6l&4!TH>1@(Na3;1Hmh13;F`KUl-y@ZX-{0OLUhhv)=`14|dc=?4rU3=CXMv~vIm zIP?WF94K0kVL8ZA3yCy?WCtL}J&NU^kU(+-11JO-Fw+Xf4gkeH$WTxmgMxYC(J#OV z4}tm^!3W8|2Bra!`rG#&QO^M|AAxC6Ubr}VE_e-1fK(3wY6F@(fKd5BmIILER8>h1 zOh0}3mO)xv7|w5+ZfNU|$K_H7@jzDG;0%SV?WGS*EkbO-Gph^gU0L<5PaR9pI zAU-IuAqP1z!B4USK#hv2%l2b!2XJw7<4p1R8ZRV=04xWfhXOW0Oq7u90GMy0GCRN_ zAto&ej{=ybubw^!vzJY;AlPgpI}s9NI5A-O7sZ4C0Bwh=JhkU{iU0rr07*qoM6N<$ Ef;3>O>Hq)$ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Machines/fat_sucker.rsi/fat_green.png b/Resources/Textures/Structures/Machines/fat_sucker.rsi/fat_green.png new file mode 100644 index 0000000000000000000000000000000000000000..d971f3d6c092d2a27872e0a8f45d174fad4fbbe1 GIT binary patch literal 191 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5C|Ky} z;uumf=k4W%f(-^dtq;HOxg~P=m?vA|o&7H^RpIoC{l^gTb3%1s=jqqHH=ayu>>UG>FVdQ&MBb@0Ct2y(f|Me literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Machines/fat_sucker.rsi/fat_panel.png b/Resources/Textures/Structures/Machines/fat_sucker.rsi/fat_panel.png new file mode 100644 index 0000000000000000000000000000000000000000..7062b2646fde72065f511a60d3b551a9ed5eef57 GIT binary patch literal 195 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5C|K(0 z;uumf=k1k^yax<8SR5v7npppzGeM21v)kpR;!)+u6IbVNeCpiR&A`N=&;TYH>KS~( zLgIIZ#6&ZS_VM(-x%*I@!CK^*X=8!MdzN{#-+d525H>g7>1w)Kz(KL^$uf)~iOLr& lTF=`ztkj;N#dM5O-MK?H^6f5$nLr0Hc)I$ztaD0e0sxBnKp_AC literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Machines/fat_sucker.rsi/fat_red.png b/Resources/Textures/Structures/Machines/fat_sucker.rsi/fat_red.png new file mode 100644 index 0000000000000000000000000000000000000000..c3f17feffc6d990835f56932a68114ad8d2d5259 GIT binary patch literal 188 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5D46Hz z;uumf=k4XQybTHhE)NwqN_cNzn7vV6ShJ038_Vv-H-ei#vdPsHw;ZlHeST3tGf)o* z%-~vaD?7+j@ql@MZs<1S%z$}MWe=Rz-#yh-Z@v11$^AOte@xhPX{~Q9^Tn_KUW-T literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Machines/fat_sucker.rsi/fat_smoke.png b/Resources/Textures/Structures/Machines/fat_sucker.rsi/fat_smoke.png new file mode 100644 index 0000000000000000000000000000000000000000..0a5575dbbbaf59bda743c3ad74c688675874484d GIT binary patch literal 534 zcmeAS@N?(olHy`uVBq!ia0vp^4nUm1!3HGP9xZtRq&N#aB8wRq_>O=u<5X=vX$A(y z6P_-PAr*7p&N}FK*g(LAePy`7eNOSbj_CZ3X#Ed!IqVi>Obpw!#^T;Bzo_hIb8j7s zynX)LvY>AaMYCA;?2|n&|Ni*yz_;r>CpX-m|NhmJH@mh-T+*n2xI_F} z{t~_g>hBaU-MGK~YeQ@P=QE|1QJtqu_yWE!y<>7$SRm zeZ|>Nta|a6-%sP1K>Y3n(;t4E>+NFMro`T$v$G`Y{r}t7^$b>INg5o;NYY(?gHd5a z{$(Y%70D74GIv=v1R1<)2xRZEO1Q$fm`|egzzSwJS%eVtI|hc(-P&Ag^D7&Hu4C|Y L^>bP0l+XkKXp&Hs literal 0 HcmV?d00001 diff --git a/Resources/Textures/Structures/Machines/fat_sucker.rsi/fat_yellow.png b/Resources/Textures/Structures/Machines/fat_sucker.rsi/fat_yellow.png new file mode 100644 index 0000000000000000000000000000000000000000..b1546fc397ed4a911488a1f9391836f85044590c GIT binary patch literal 190 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?4jBOuH;Rhv&5C|Ka> z;uumf=k4W