From 5fc7f218538900ca5b21b1806136a73d3a70311e Mon Sep 17 00:00:00 2001 From: forthbridge <79264743+forthbridge@users.noreply.github.com> Date: Tue, 1 Aug 2023 22:10:48 +0800 Subject: [PATCH] Add Spaceshrooms (#17092) Co-authored-by: metalgearsloth --- .../RandomFillSolutionComponent.cs | 11 +- .../EntitySystems/SolutionRandomFillSystem.cs | 14 +- Content.Server/Gatherable/GatherableSystem.cs | 22 +++- .../Random/Helpers/SharedRandomExtensions.cs | 57 ++++++++ Content.Shared/Random/RandomFillSolution.cs | 33 +++++ .../WeightedRandomFillSolutionPrototype.cs | 18 +++ .../Locale/en-US/flavors/flavor-profiles.ftl | 2 + .../Markers/Spawners/Random/maintenance.yml | 17 +++ .../Prototypes/Entities/Mobs/Species/base.yml | 4 + .../Entities/Objects/Misc/spaceshroom.yml | 123 ++++++++++++++++++ .../Objects/Specific/Medical/randompill.yml | 77 ++++++----- Resources/Prototypes/Flavors/flavors.yml | 10 ++ .../Recipes/Cooking/meal_recipes.yml | 8 ++ Resources/Prototypes/ore.yml | 7 + .../Objects/Misc/spaceshroom.rsi/meta.json | 20 +++ .../Objects/Misc/spaceshroom.rsi/object.png | Bin 0 -> 6512 bytes .../spaceshroom.rsi/spaceshroom_cooked.png | Bin 0 -> 7453 bytes .../Misc/spaceshroom.rsi/structure.png | Bin 0 -> 1653 bytes 18 files changed, 369 insertions(+), 54 deletions(-) create mode 100644 Content.Shared/Random/RandomFillSolution.cs create mode 100644 Content.Shared/Random/WeightedRandomFillSolutionPrototype.cs create mode 100644 Resources/Prototypes/Entities/Objects/Misc/spaceshroom.yml create mode 100644 Resources/Textures/Objects/Misc/spaceshroom.rsi/meta.json create mode 100644 Resources/Textures/Objects/Misc/spaceshroom.rsi/object.png create mode 100644 Resources/Textures/Objects/Misc/spaceshroom.rsi/spaceshroom_cooked.png create mode 100644 Resources/Textures/Objects/Misc/spaceshroom.rsi/structure.png diff --git a/Content.Server/Chemistry/Components/SolutionManager/RandomFillSolutionComponent.cs b/Content.Server/Chemistry/Components/SolutionManager/RandomFillSolutionComponent.cs index bf75df03a7..409665fb0d 100644 --- a/Content.Server/Chemistry/Components/SolutionManager/RandomFillSolutionComponent.cs +++ b/Content.Server/Chemistry/Components/SolutionManager/RandomFillSolutionComponent.cs @@ -1,5 +1,4 @@ using Content.Server.Chemistry.EntitySystems; -using Content.Shared.FixedPoint; using Content.Shared.Random; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; @@ -18,14 +17,8 @@ public sealed class RandomFillSolutionComponent : Component public string Solution { get; set; } = "default"; /// - /// Weighted random prototype Id. Used to pick reagent. + /// Weighted random fill prototype Id. Used to pick reagent and quantity. /// - [DataField("weightedRandomId", required: true, customTypeSerializer: typeof(PrototypeIdSerializer))] + [DataField("weightedRandomId", required: true, customTypeSerializer: typeof(PrototypeIdSerializer))] public string WeightedRandomId { get; set; } = "default"; - - /// - /// Amount of reagent to add. - /// - [DataField("quantity")] - public FixedPoint2 Quantity { get; set; } = 0; } diff --git a/Content.Server/Chemistry/EntitySystems/SolutionRandomFillSystem.cs b/Content.Server/Chemistry/EntitySystems/SolutionRandomFillSystem.cs index 0d653e1da9..78afda9910 100644 --- a/Content.Server/Chemistry/EntitySystems/SolutionRandomFillSystem.cs +++ b/Content.Server/Chemistry/EntitySystems/SolutionRandomFillSystem.cs @@ -20,18 +20,20 @@ public sealed class SolutionRandomFillSystem : EntitySystem SubscribeLocalEvent(OnRandomSolutionFillMapInit); } - public void OnRandomSolutionFillMapInit(EntityUid uid, RandomFillSolutionComponent component, MapInitEvent args) + private void OnRandomSolutionFillMapInit(EntityUid uid, RandomFillSolutionComponent component, MapInitEvent args) { var target = _solutionsSystem.EnsureSolution(uid, component.Solution); - var reagent = _proto.Index(component.WeightedRandomId).Pick(_random); + var pick = _proto.Index(component.WeightedRandomId).Pick(_random); - if (!_proto.TryIndex(reagent, out ReagentPrototype? reagentProto)) + var reagent = pick.reagent; + var quantity = pick.quantity; + + if (!_proto.HasIndex(reagent)) { - Logger.Error( - $"Tried to add invalid reagent Id {reagent} using SolutionRandomFill."); + Log.Error($"Tried to add invalid reagent Id {reagent} using SolutionRandomFill."); return; } - target.AddReagent(reagent, component.Quantity); + target.AddReagent(reagent, quantity); } } diff --git a/Content.Server/Gatherable/GatherableSystem.cs b/Content.Server/Gatherable/GatherableSystem.cs index b9a375d284..abee3e4549 100644 --- a/Content.Server/Gatherable/GatherableSystem.cs +++ b/Content.Server/Gatherable/GatherableSystem.cs @@ -25,25 +25,29 @@ public sealed partial class GatherableSystem : EntitySystem { base.Initialize(); + SubscribeLocalEvent(OnActivate); SubscribeLocalEvent(OnInteractUsing); SubscribeLocalEvent(OnDoAfter); InitializeProjectile(); } - private void OnInteractUsing(EntityUid uid, GatherableComponent component, InteractUsingEvent args) + private void Gather(EntityUid gatheredUid, EntityUid user, EntityUid used, GatheringToolComponent? tool = null, GatherableComponent? component = null) { - if (!TryComp(args.Used, out var tool) || component.ToolWhitelist?.IsValid(args.Used) == false) + if (!Resolve(used, ref tool, false) || !Resolve(gatheredUid, ref component, false) || + component.ToolWhitelist?.IsValid(used) == false) + { return; + } // Can't gather too many entities at once. if (tool.MaxGatheringEntities < tool.GatheringEntities.Count + 1) return; - var damageRequired = _destructible.DestroyedAt(uid); + var damageRequired = _destructible.DestroyedAt(gatheredUid); var damageTime = (damageRequired / tool.Damage.Total).Float(); damageTime = Math.Max(1f, damageTime); - var doAfter = new DoAfterArgs(args.User, damageTime, new GatherableDoAfterEvent(), uid, target: uid, used: args.Used) + var doAfter = new DoAfterArgs(user, damageTime, new GatherableDoAfterEvent(), gatheredUid, target: gatheredUid, used: used) { BreakOnDamage = true, BreakOnTargetMove = true, @@ -54,6 +58,16 @@ public sealed partial class GatherableSystem : EntitySystem _doAfterSystem.TryStartDoAfter(doAfter); } + private void OnActivate(EntityUid uid, GatherableComponent component, ActivateInWorldEvent args) + { + Gather(uid, args.User, args.User); + } + + private void OnInteractUsing(EntityUid uid, GatherableComponent component, InteractUsingEvent args) + { + Gather(uid, args.User, args.Used, component: component); + } + private void OnDoAfter(EntityUid uid, GatherableComponent component, GatherableDoAfterEvent args) { if(!TryComp(args.Args.Used, out var tool)) diff --git a/Content.Shared/Random/Helpers/SharedRandomExtensions.cs b/Content.Shared/Random/Helpers/SharedRandomExtensions.cs index 4544bf65fa..d68fac2509 100644 --- a/Content.Shared/Random/Helpers/SharedRandomExtensions.cs +++ b/Content.Shared/Random/Helpers/SharedRandomExtensions.cs @@ -1,5 +1,6 @@ using System.Linq; using Content.Shared.Dataset; +using Content.Shared.FixedPoint; using Robust.Shared.Random; namespace Content.Shared.Random.Helpers @@ -75,5 +76,61 @@ namespace Content.Shared.Random.Helpers throw new InvalidOperationException($"Invalid weighted pick"); } + + public static (string reagent, FixedPoint2 quantity) Pick(this WeightedRandomFillSolutionPrototype prototype, IRobustRandom? random = null) + { + var randomFill = prototype.PickRandomFill(random); + + IoCManager.Resolve(ref random); + + var sum = randomFill.Reagents.Count; + var accumulated = 0f; + + var rand = random.NextFloat() * sum; + + foreach (var reagent in randomFill.Reagents) + { + accumulated += 1f; + + if (accumulated >= rand) + { + return (reagent, randomFill.Quantity); + } + } + + // Shouldn't happen + throw new InvalidOperationException($"Invalid weighted pick for {prototype.ID}!"); + } + + public static RandomFillSolution PickRandomFill(this WeightedRandomFillSolutionPrototype prototype, IRobustRandom? random = null) + { + IoCManager.Resolve(ref random); + + var fills = prototype.Fills; + Dictionary picks = new(); + + foreach (var fill in fills) + { + picks[fill] = fill.Weight; + } + + var sum = picks.Values.Sum(); + var accumulated = 0f; + + var rand = random.NextFloat() * sum; + + foreach (var (randSolution, weight) in picks) + { + accumulated += weight; + + if (accumulated >= rand) + { + return randSolution; + } + } + + // Shouldn't happen + throw new InvalidOperationException($"Invalid weighted pick for {prototype.ID}!"); + } } } diff --git a/Content.Shared/Random/RandomFillSolution.cs b/Content.Shared/Random/RandomFillSolution.cs new file mode 100644 index 0000000000..acbd97db87 --- /dev/null +++ b/Content.Shared/Random/RandomFillSolution.cs @@ -0,0 +1,33 @@ +using Content.Shared.Chemistry.Reagent; +using Content.Shared.FixedPoint; +using Robust.Shared.Serialization; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; + +namespace Content.Shared.Random; + +/// +/// Data that specifies reagents that share the same weight and quantity for use with WeightedRandomSolution. +/// +[Serializable, NetSerializable] +[DataDefinition] +public sealed class RandomFillSolution +{ + /// + /// Quantity of listed reagents. + /// + [DataField("quantity")] + public FixedPoint2 Quantity = 0; + + /// + /// Random weight of listed reagents. + /// + [DataField("weight")] + public float Weight = 0; + + /// + /// Listed reagents that the weight and quantity apply to. + /// + [DataField("reagents", required: true, customTypeSerializer: typeof(PrototypeIdListSerializer))] + public List Reagents = new(); +} diff --git a/Content.Shared/Random/WeightedRandomFillSolutionPrototype.cs b/Content.Shared/Random/WeightedRandomFillSolutionPrototype.cs new file mode 100644 index 0000000000..8a6f133d09 --- /dev/null +++ b/Content.Shared/Random/WeightedRandomFillSolutionPrototype.cs @@ -0,0 +1,18 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.Random; + +/// +/// Random weighting dataset for solutions, able to specify reagents quantity. +/// +[Prototype("weightedRandomFillSolution")] +public sealed class WeightedRandomFillSolutionPrototype : IPrototype +{ + [IdDataField] public string ID { get; } = default!; + + /// + /// List of RandomFills that can be picked from. + /// + [DataField("fills", required: true)] + public List Fills = new(); +} diff --git a/Resources/Locale/en-US/flavors/flavor-profiles.ftl b/Resources/Locale/en-US/flavors/flavor-profiles.ftl index 54e763ae6c..ebf341ed18 100644 --- a/Resources/Locale/en-US/flavors/flavor-profiles.ftl +++ b/Resources/Locale/en-US/flavors/flavor-profiles.ftl @@ -42,6 +42,7 @@ flavor-base-cheap = cheap flavor-base-piquant = piquant flavor-base-sharp = sharp flavor-base-syrupy = syrupy +flavor-base-spaceshroom = mysterious # lmao flavor-base-terrible = terrible @@ -145,6 +146,7 @@ flavor-complex-electrons = like electrons flavor-complex-parents = like someone's parents flavor-complex-plastic = like plastic flavor-complex-glue = like glue +flavor-complex-spaceshroom-cooked = like space umami # Drink-specific flavors. diff --git a/Resources/Prototypes/Entities/Markers/Spawners/Random/maintenance.yml b/Resources/Prototypes/Entities/Markers/Spawners/Random/maintenance.yml index 8f0f576dfd..c1a1d13500 100644 --- a/Resources/Prototypes/Entities/Markers/Spawners/Random/maintenance.yml +++ b/Resources/Prototypes/Entities/Markers/Spawners/Random/maintenance.yml @@ -131,3 +131,20 @@ - ClothingEyesBlindfold chance: 0.6 offset: 0.0 + +- type: entity + name: Maint Loot Spawner + suffix: Plants + id: MaintenancePlantSpawner + parent: MarkerBase + components: + - type: Sprite + layers: + - state: red + - sprite: Objects/Misc/spaceshroom.rsi + state: spaceshroom + - type: RandomSpawner + prototypes: + - FoodSpaceshroom + chance: 0.6 + offset: 0.0 diff --git a/Resources/Prototypes/Entities/Mobs/Species/base.yml b/Resources/Prototypes/Entities/Mobs/Species/base.yml index ebbd76d7a5..1746e091e5 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/base.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/base.yml @@ -34,6 +34,10 @@ - type: Polymorphable - type: Identity - type: Hands + - type: GatheringTool + damage: + types: + Structural: 50 - type: MovementSpeedModifier - type: MovedByPressure - type: Barotrauma diff --git a/Resources/Prototypes/Entities/Objects/Misc/spaceshroom.yml b/Resources/Prototypes/Entities/Objects/Misc/spaceshroom.yml new file mode 100644 index 0000000000..9ec6ce0ed1 --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Misc/spaceshroom.yml @@ -0,0 +1,123 @@ +- type: entity + name: spaceshroom + parent: BaseStructure + id: Spaceshroom + suffix: Structure + description: A cluster of wild mushrooms that likes to grow in dark, moist environments. + components: + - type: Sprite + sprite: Objects/Misc/spaceshroom.rsi + state: structure + - type: Transform + anchored: true + - type: Physics + bodyType: Static + - type: Fixtures + fixtures: + fix1: + shape: + !type:PhysShapeCircle + radius: 0.2 + - type: InteractionOutline + # TODO: Nuke this shit + - type: OreVein + oreChance: 1.0 + currentOre: SpaceShrooms + - type: Gatherable + whitelist: + components: + - Hands + - type: Damageable + damageContainer: Inorganic + damageModifierSet: Wood + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 150 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + +- type: entity + name: spaceshroom + parent: FoodProduceBase + id: FoodSpaceshroom + description: A wild mushroom. There's no telling what effect it could have... + components: + - type: Produce + - type: Sprite + sprite: Objects/Misc/spaceshroom.rsi + state: object + - type: FlavorProfile + flavors: + - spaceshroom + - type: Extractable + juiceSolution: + reagents: + - ReagentId: SpaceDrugs + Quantity: 10 + - type: SolutionContainerManager + solutions: + food: + maxVol: 20 + reagents: + - ReagentId: Nutriment + Quantity: 3 + - ReagentId: Vitamin + Quantity: 2 + - type: RandomFillSolution + solution: food + weightedRandomId: RandomFillSpaceshroom + - type: StaticPrice + price: 20 + +- type: weightedRandomFillSolution + id: RandomFillSpaceshroom + fills: + - quantity: 10 + weight: 10 + reagents: + - SpaceDrugs + - quantity: 0 + weight: 5 + reagents: + - Water + - quantity: 10 + weight: 3 + reagents: + - Ephedrine + - quantity: 10 + weight: 1 + reagents: + - Lexorin + - quantity: 15 + weight: 1 + reagents: + - Amatoxin + +# Cooked Object +- type: entity + name: cooked spaceshroom + parent: FoodProduceBase + id: FoodSpaceshroomCooked + description: A wild mushroom that has been cooked through. It seems the heat has removed its chemical effects. + components: + - type: FlavorProfile + flavors: + - spaceshroomcooked + - type: SolutionContainerManager + solutions: + food: + maxVol: 15 + reagents: + - ReagentId: Nutriment + Quantity: 10 + - ReagentId: Vitamin + Quantity: 5 + - type: Sprite + sprite: Objects/Misc/spaceshroom.rsi + state: spaceshroom_cooked + - type: Produce + - type: StaticPrice + price: 40 diff --git a/Resources/Prototypes/Entities/Objects/Specific/Medical/randompill.yml b/Resources/Prototypes/Entities/Objects/Specific/Medical/randompill.yml index 14bc13343b..fcd738f0db 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Medical/randompill.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Medical/randompill.yml @@ -1,38 +1,46 @@ -- type: weightedRandom +- type: weightedRandomFillSolution id: RandomFillStrangePill - weights: - # Elements - Aluminium: 1 - Carbon: 1 - Chlorine: 1 - Copper: 1 - Fluorine: 1 - Hydrogen: 1 - Iodine: 1 - Lithium: 1 - Mercury: 1 - Potassium: 1 - Phosphorus: 1 - Radium: 1 - Silicon: 1 - Sulfur: 1 - Sodium: 1 - # Medicines - Ipecac: 3 - Omnizine: 2 - Tricordrazine: 3 - # Narcotics - Desoxyephedrine: 3 - Ephedrine: 3 - SpaceDrugs: 5 - Nocturine: 3 - MuteToxin: 3 - NorepinephricAcid: 3 - # Toxins - ChloralHydrate: 3 - Mold: 3 - Pax: 3 - Toxin: 5 + fills: + - quantity: 20 + weight: 1 + reagents: + - Aluminium + - Carbon + - Chlorine + - Copper + - Fluorine + - Hydrogen + - Iodine + - Lithium + - Mercury + - Potassium + - Phosphorus + - Radium + - Silicon + - Sulfur + - Sodium + - quantity: 20 + weight: 2 + reagents: + - Omnizine + - quantity: 20 + weight: 3 + reagents: + - ChloralHydrate + - Desoxyephedrine + - Ephedrine + - Ipecac + - Mold + - MuteToxin + - Nocturine + - NorepinephricAcid + - Pax + - Tricordrazine + - quantity: 20 + weight: 5 + reagents: + - SpaceDrugs + - Toxin - type: entity name: strange pill @@ -47,7 +55,6 @@ - type: RandomFillSolution solution: food weightedRandomId: RandomFillStrangePill - quantity: 20 - type: Sprite sprite: Objects/Specific/Chemistry/pills.rsi layers: diff --git a/Resources/Prototypes/Flavors/flavors.yml b/Resources/Prototypes/Flavors/flavors.yml index 7e61b24334..ab82a13fcb 100644 --- a/Resources/Prototypes/Flavors/flavors.yml +++ b/Resources/Prototypes/Flavors/flavors.yml @@ -823,3 +823,13 @@ id: rocksandstones flavorType: Complex description: flavor-complex-rocksandstones + +- type: flavor + id: spaceshroom + flavorType: Base + description: flavor-base-spaceshroom + +- type: flavor + id: spaceshroomcooked + flavorType: Complex + description: flavor-complex-spaceshroom-cooked \ No newline at end of file diff --git a/Resources/Prototypes/Recipes/Cooking/meal_recipes.yml b/Resources/Prototypes/Recipes/Cooking/meal_recipes.yml index 2cb601ccd7..0b26f65dcc 100644 --- a/Resources/Prototypes/Recipes/Cooking/meal_recipes.yml +++ b/Resources/Prototypes/Recipes/Cooking/meal_recipes.yml @@ -1632,3 +1632,11 @@ solids: FoodChevreSlice: 1 FoodBreadBaguetteSlice: 1 + +- type: microwaveMealRecipe + id: RecipeCookedSpaceshroom + name: cooked spaceshroom recipe + result: FoodSpaceshroomCooked + time: 5 + solids: + FoodSpaceshroom: 1 \ No newline at end of file diff --git a/Resources/Prototypes/ore.yml b/Resources/Prototypes/ore.yml index 33f17a5e01..b17e0839a2 100644 --- a/Resources/Prototypes/ore.yml +++ b/Resources/Prototypes/ore.yml @@ -1,3 +1,10 @@ +# TODO: Kill ore veins +# Split it into 2 components, 1 for "spawn XYZ on destruction" and 1 for "randomly select one of these for spawn on destruction" +# You could even just use an entityspawncollection instead. +- type: ore + id: SpaceShrooms + oreEntity: FoodSpaceshroom + # High yields - type: ore id: OreSteel diff --git a/Resources/Textures/Objects/Misc/spaceshroom.rsi/meta.json b/Resources/Textures/Objects/Misc/spaceshroom.rsi/meta.json new file mode 100644 index 0000000000..46d9ba04e4 --- /dev/null +++ b/Resources/Textures/Objects/Misc/spaceshroom.rsi/meta.json @@ -0,0 +1,20 @@ +{ + "version": 1, + "license": "CC0-1.0", + "copyright": "Created by @UbaserB (GitHub)", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "object" + }, + { + "name": "spaceshroom_cooked" + }, + { + "name": "structure" + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Objects/Misc/spaceshroom.rsi/object.png b/Resources/Textures/Objects/Misc/spaceshroom.rsi/object.png new file mode 100644 index 0000000000000000000000000000000000000000..6a5b84993dd84449b3f0acb3226ae7b268456b49 GIT binary patch literal 6512 zcmdUzdt6L;AIB$bauyBUTvDOv@micY=gc`Xk#tu=r5i1p=CaLJj2f4UQf)RxO2jH7 zvWgy++}aR^Zkxr{Q*Mrv1Ih(@E0vRPo^2xdLe_-G<8coSpXl`yVIbi3w zZgaImN>giclk=PEOX)&`)+YOGu+ZWjGOmK-$;!G8OeKpb68cHboMvFkL!Q_kJR9bI^(dH zx|_lGg~?6}k9A_J=umL5XK}} zI2*@duwiVBjc~vTi>$!L06zqbsQg@UO*VHAP|c2CszAr(y>=9e#9SIgj@=y*9Ad&a z3l|U=I8fOcjKC<0@X0193qt?}55~a$&IT3!Dy*c@)SzCwZ1fe;ATY>!ASermP%bJU zSOknSa1{5%nFNNwID#{A0(j-4JOtqjJUu-H2m-FNag4meBv2;CLt%_Zz!(ai1-U>N zi{KF8MJ7scFg_E*!3+dZ6ug8Wr~u`|9F$A2P!5O@yomG2W;jTVtZ^>RCs6VpM0Nl) zz%|K%a^yGu_qdFtM+QiE%9vOfj|uVtJOUB}fguzFQIQ9X@Z^g};3)7xl7Jw&;4uux zQ4SNqFbw|#hx{Ii!h#44>@dnf1c-o;Z3v$LvM)4;bryi8Le23|E zW_oD;M%F&g%-_V?K+Jru))Za_^Pf%4qOWQIL<%!h$pHva1r*ib3iWPA!6Kgrmx$WC z_o@$~k1<0P>_dq9(8pANzEJiAYXAAfnzDW%a~}^ z{4|A?^BAsI3BQ^b^EQ6i*r(UbHT11Ds>e$2JQ;V?d}&8*sRrx7;?rl&)Rw=xx3N4o z@M4QZ-vec62YJs%qIIv{c2&N`kZipoMvbO1y}VXi?;bZRXmg7MK3&O4ZP%@EY+tE$ zqV`!99JkTGsOYB8;_@Zc0TUl=ep#N~e(J<}n#1iMYTuI0>`VJ(kxE5YcC&XqFJ7N&c)H(+&Es2>khdqaQV6y;j;Vk z+=$7HNfq~_yzXmGkHI9@j@`V$={)=G$k97Q#f*;NiTv%m-CgZw`n4gi+nSlL#f^2o zZ&oiGf6uS1s8*y$R}q;l@^t+LebTw9Blx?{upp1S0lRFi+uO8%wk>&BpEP<2$Lr21 zztqzc=Bw_lr{@c9>s3as60|uoLyj*^T6W*+p}`$+Ab4` g8T5~Ts)r1j5aQdV+7_MwKB3cWEEij3n0bW#7fC#*Z2$lO literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Misc/spaceshroom.rsi/spaceshroom_cooked.png b/Resources/Textures/Objects/Misc/spaceshroom.rsi/spaceshroom_cooked.png new file mode 100644 index 0000000000000000000000000000000000000000..633d4a26757305ce87a120c4dd22f6dadd4da40c GIT binary patch literal 7453 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 K`boNuoc{tQ0dq?L literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Misc/spaceshroom.rsi/structure.png b/Resources/Textures/Objects/Misc/spaceshroom.rsi/structure.png new file mode 100644 index 0000000000000000000000000000000000000000..c23bed8ee0f50bc31549765b34d91afc6d132155 GIT binary patch literal 1653 zcmV-*28#KKP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1`0_;K~z{rkQJqemqLCvP7A}gEG{*fLw49S$%)F0`D zGd1>y)ii(>KFK#q3&bw($D#z14Ja(T_kNvwSr-r_)_?u&oW1*<@9g=0-}%lt-^BwD z&hxx)Y)Oq{M)of_j=|{?AqWEUkGG85ug?TH4s6xZ1aOQ;2+bF>(Xlap}#ObL>oN}2FM8IdLphTJ#7Z$NEa`KoT1Qtl+NhJGsf5}e$c#;7;$@p;J3}q5}2;fOp zB*!bdq7ycV^yx;A*KhE&XvQ(JBTA08suAmri@=+-m_*N`B-MBQ$4GN~cf5)ZKG~19 zA#*{YX4WN{ke!_kMl=~?*q8e;)M_;Z@gH354sx)M_4kBhnQIWhM@X3X6yY zPqUKp-$x^+v$bgn$p88^(Gh(UiICN?Cm|swUs3RtaHMRYnHEiNj) zWl&NNhefMrIp%20$^8u7%QCUv6alM72e(^7x_KrglLT$Q8-5;pH$}a(sR4Q-GKhAr z(%#MjYJR7!Fm$PioJd*3jF{kTgRMLemRSRdJ8A?Nh5ho{bx`qYP^l}DSnwUKCZVIF zLphc^btZ5s2xR9LT^`K<n6-$(+BL7Zx5Cb z-&K}qbQ*N%4Df?P=Z7Dz*WvtR19okE0eK-h9JEZuzRQ=q)xgv7fb~J`3F#eZh;-Kc zB<$I+iRMMvD*uG-uM3E^grUXy2ij`OJeEU{PNu80YIYzrj4@j^s|t%_cJt#bf%LLO zkVKJy6TFRPuGz%$Uru2wOx~bCLpIyDZDvQZH?ug|eh4_I*@C2J7|#VL`eC#iNv2V+ zuL%giPCA0zkcmjEy^I%k?Szfy=A}G_PT7!&-sHdm35m)??T19L0-7n~{6`P&CxH!EU#E z9Z^oOS2kq8;cy_zZ1!jeA-XATsUJAnuX!|gf&4Q$gyA7UY*AP!3-^n+M>87S-Z+jRAVXfvMX5%ebXdT7*_^3i znc=UDwN&H&T$fUcGMV|2JhMdl!`j}1(ni-^hc!AzC2%iD^a+}5qSr3E1I&ReBiW4F z+FJCx`Vbjz1SdBeL5|;8yB`jp2*d{KVG!I{v2Ydw#2a)k+$OCP4cD6B|f`Jy1jF3bFGSV`r3AJPOyi`o;(?G*bKyB+71}fs8kqf)O7dk3H|dhN#FHzOnEHv>scNu|VmT@|dR^wBWt%?9h&P*twq$Q)e9P zl;eSqCpG{*E!sQew8M#vT>U*HH}2Etg9_k3c3)UQL3XKr00000NkvXXu0mjf)6o(@ literal 0 HcmV?d00001