]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Inflatable Module (#35100)
authorFungiFellow <151778459+FungiFellow@users.noreply.github.com>
Sat, 23 Aug 2025 22:15:28 +0000 (18:15 -0400)
committerGitHub <noreply@github.com>
Sat, 23 Aug 2025 22:15:28 +0000 (15:15 -0700)
Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com>
Co-authored-by: PJB3005 <pieterjan.briers+git@gmail.com>
20 files changed:
Content.IntegrationTests/Tests/Engineering/InflatablesDeflateTest.cs [new file with mode: 0644]
Content.IntegrationTests/Tests/Interaction/InteractionTest.Constants.cs
Content.Server/Weapons/Melee/Balloon/BalloonPopperSystem.cs
Content.Shared/Engineering/Components/InflatableSafeDisassemblyComponent.cs [new file with mode: 0644]
Content.Shared/Engineering/Systems/DisassembleOnAltVerbSystem.cs
Content.Shared/Engineering/Systems/InflatableSafeDisassemblySystem.cs [new file with mode: 0644]
Content.Shared/Weapons/Melee/Balloon/BalloonPopperComponent.cs [moved from Content.Server/Weapons/Melee/Balloon/BalloonPopperComponent.cs with 94% similarity]
Resources/Locale/en-US/engineering/inflatables.ftl [new file with mode: 0644]
Resources/Locale/en-US/robotics/borg_modules.ftl
Resources/Prototypes/Entities/Objects/Misc/inflatable_wall.yml
Resources/Prototypes/Entities/Objects/Specific/Robotics/borg_modules.yml
Resources/Prototypes/Entities/Objects/Tools/inflatable_wall.yml
Resources/Prototypes/Recipes/Lathes/Packs/robotics.yml
Resources/Prototypes/Recipes/Lathes/robot_modules.yml
Resources/Prototypes/borg_types.yml
Resources/Prototypes/tags.yml
Resources/Textures/Interface/Actions/actions_borg.rsi/inflatable-module.png [new file with mode: 0644]
Resources/Textures/Interface/Actions/actions_borg.rsi/meta.json
Resources/Textures/Objects/Specific/Robotics/borgmodule.rsi/icon-inflatable.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Robotics/borgmodule.rsi/meta.json

diff --git a/Content.IntegrationTests/Tests/Engineering/InflatablesDeflateTest.cs b/Content.IntegrationTests/Tests/Engineering/InflatablesDeflateTest.cs
new file mode 100644 (file)
index 0000000..a7203d9
--- /dev/null
@@ -0,0 +1,20 @@
+using Content.IntegrationTests.Tests.Interaction;
+using Content.Shared.Engineering.Systems;
+
+namespace Content.IntegrationTests.Tests.Engineering;
+
+[TestFixture]
+[TestOf(typeof(InflatableSafeDisassemblySystem))]
+public sealed class InflatablesDeflateTest : InteractionTest
+{
+    [Test]
+    public async Task Test()
+    {
+        await SpawnTarget(InflatableWall);
+
+        await InteractUsing(Needle);
+
+        AssertDeleted();
+        await AssertEntityLookup(new EntitySpecifier(InflatableWallStack.Id, 1));
+    }
+}
index 5db5d91d0d433669b2145bbf14056da0b307b57a..8917ba7ead558495aa05aacc0821f39db1f6c3a3 100644 (file)
@@ -1,3 +1,6 @@
+using Content.Shared.Stacks;
+using Robust.Shared.Prototypes;
+
 namespace Content.IntegrationTests.Tests.Interaction;
 
 // This partial class contains various constant prototype IDs common to interaction tests.
@@ -32,4 +35,9 @@ public abstract partial class InteractionTest
     protected const string Manipulator1 = "MicroManipulatorStockPart";
     protected const string Battery1 = "PowerCellSmall";
     protected const string Battery4 = "PowerCellHyper";
+
+    // Inflatables & Needle used to pop them
+    protected static readonly EntProtoId InflatableWall = "InflatableWall";
+    protected static readonly EntProtoId Needle = "WeaponMeleeNeedle";
+    protected static readonly ProtoId<StackPrototype> InflatableWallStack = "InflatableWall";
 }
index a8460a8c6600c3a4b63b87b4a07b182fa69ea633..d4ab81ae10f74bf1f0f2e3ac18f55cabe73737c5 100644 (file)
@@ -5,6 +5,7 @@ using Content.Shared.Popups;
 using Content.Shared.Tag;
 using Content.Shared.Weapons.Melee.Events;
 using Content.Shared.Throwing;
+using Content.Shared.Weapons.Melee.Balloon;
 using Robust.Shared.Audio.Systems;
 
 namespace Content.Server.Weapons.Melee.Balloon;
diff --git a/Content.Shared/Engineering/Components/InflatableSafeDisassemblyComponent.cs b/Content.Shared/Engineering/Components/InflatableSafeDisassemblyComponent.cs
new file mode 100644 (file)
index 0000000..47591b6
--- /dev/null
@@ -0,0 +1,14 @@
+using Content.Shared.Engineering.Systems;
+using Content.Shared.Weapons.Melee.Balloon;
+
+namespace Content.Shared.Engineering.Components;
+
+/// <summary>
+/// Implements logic to allow inflatable objects to be safely deflated by <see cref="BalloonPopperComponent"/> items.
+/// </summary>
+/// <remarks>
+/// The owning entity must have <see cref="DisassembleOnAltVerbComponent"/> to implement the logic.
+/// </remarks>
+/// <seealso cref="InflatableSafeDisassemblySystem"/>
+[RegisterComponent]
+public sealed partial class InflatableSafeDisassemblyComponent : Component;
index 150688d3d4c3e818890022ed493f2ee5b0c2ca1b..0c2e5398fc0b3e15d7e5203a0008749fd889f636 100644 (file)
@@ -19,14 +19,12 @@ public sealed partial class DisassembleOnAltVerbSystem : EntitySystem
         SubscribeLocalEvent<DisassembleOnAltVerbComponent, GetVerbsEvent<AlternativeVerb>>(AddDisassembleVerb);
         SubscribeLocalEvent<DisassembleOnAltVerbComponent, DisassembleDoAfterEvent>(OnDisassembleDoAfter);
     }
-    private void AddDisassembleVerb(Entity<DisassembleOnAltVerbComponent> entity, ref GetVerbsEvent<AlternativeVerb> args)
-    {
-        if (!args.CanInteract || !args.CanAccess || args.Hands == null)
-            return;
 
+    public void StartDisassembly(Entity<DisassembleOnAltVerbComponent> entity, EntityUid user)
+    {
         // Doafter setup
         var doAfterArgs = new DoAfterArgs(EntityManager,
-            args.User,
+            user,
             entity.Comp.DisassembleTime,
             new DisassembleDoAfterEvent(),
             entity,
@@ -35,12 +33,22 @@ public sealed partial class DisassembleOnAltVerbSystem : EntitySystem
             BreakOnMove = true,
         };
 
+        _doAfter.TryStartDoAfter(doAfterArgs);
+    }
+
+    private void AddDisassembleVerb(Entity<DisassembleOnAltVerbComponent> entity, ref GetVerbsEvent<AlternativeVerb> args)
+    {
+        if (!args.CanInteract || !args.CanAccess || args.Hands == null)
+            return;
+
+        var user = args.User;
+
         // Actual verb stuff
         AlternativeVerb verb = new()
         {
             Act = () =>
             {
-                _doAfter.TryStartDoAfter(doAfterArgs);
+                StartDisassembly(entity, user);
             },
             Text = Loc.GetString("disassemble-system-verb-disassemble"),
             Priority = 2
diff --git a/Content.Shared/Engineering/Systems/InflatableSafeDisassemblySystem.cs b/Content.Shared/Engineering/Systems/InflatableSafeDisassemblySystem.cs
new file mode 100644 (file)
index 0000000..7852036
--- /dev/null
@@ -0,0 +1,39 @@
+using Content.Shared.Engineering.Components;
+using Content.Shared.Interaction;
+using Content.Shared.Popups;
+using Content.Shared.Weapons.Melee.Balloon;
+
+namespace Content.Shared.Engineering.Systems;
+
+/// <summary>
+/// Implements <see cref="InflatableSafeDisassemblyComponent"/>
+/// </summary>
+public sealed class InflatableSafeDisassemblySystem : EntitySystem
+{
+    [Dependency] private readonly DisassembleOnAltVerbSystem _disassembleOnAltVerbSystem = null!;
+    [Dependency] private readonly SharedPopupSystem _popupSystem = null!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        SubscribeLocalEvent<InflatableSafeDisassemblyComponent, InteractUsingEvent>(InteractHandler);
+    }
+
+    private void InteractHandler(Entity<InflatableSafeDisassemblyComponent> ent, ref InteractUsingEvent args)
+    {
+        if (args.Handled)
+            return;
+
+        if (!HasComp<BalloonPopperComponent>(args.Used))
+            return;
+
+        _popupSystem.PopupPredicted(
+            Loc.GetString("inflatable-safe-disassembly", ("item", args.Used), ("target", ent.Owner)),
+            ent,
+            args.User);
+
+        _disassembleOnAltVerbSystem.StartDisassembly((ent, Comp<DisassembleOnAltVerbComponent>(ent)), args.User);
+        args.Handled = true;
+    }
+}
similarity index 94%
rename from Content.Server/Weapons/Melee/Balloon/BalloonPopperComponent.cs
rename to Content.Shared/Weapons/Melee/Balloon/BalloonPopperComponent.cs
index e7f318d61c11df3480d0914ceea8e6a679d08815..7e90b2b4eaa363f5407399b1fff9fc0770fd6af5 100644 (file)
@@ -2,7 +2,7 @@
 using Robust.Shared.Audio;
 using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
 
-namespace Content.Server.Weapons.Melee.Balloon;
+namespace Content.Shared.Weapons.Melee.Balloon;
 
 /// <summary>
 /// This is used for weapons that pop balloons on attack.
diff --git a/Resources/Locale/en-US/engineering/inflatables.ftl b/Resources/Locale/en-US/engineering/inflatables.ftl
new file mode 100644 (file)
index 0000000..0c4a2d4
--- /dev/null
@@ -0,0 +1 @@
+inflatable-safe-disassembly = You expertly use { THE($item) } to open the valve on { THE($target) }, and start deflating { OBJECT($target) } without causing damage.
index b6c55447e709ca4c83f2da8b727692ed17a6cb6d..ba5ee602a57882e01c299b7e3d3b467d9e27b672 100644 (file)
@@ -10,3 +10,5 @@ borg-slot-documents-empty = Books and papers
 borg-slot-soap-empty = Soap
 borg-slot-instruments-empty = Instruments
 borg-slot-beakers-empty = Beakers
+borg-slot-inflatable-door-empty = Inflatable Door
+borg-slot-inflatable-wall-empty = Inflatable Wall
index 06410848476e327461aeee2472d9d9d1bb74ece5..577ab1dddde2d8c495b61666122feddf4b4877d5 100644 (file)
@@ -33,6 +33,7 @@
   - type: DisassembleOnAltVerb
     prototypeToSpawn: InflatableWallStack1
     disassembleTime: 3
+  - type: InflatableSafeDisassembly
   - type: Airtight
   - type: Transform
     anchored: true
@@ -81,5 +82,6 @@
   - type: DisassembleOnAltVerb
     prototypeToSpawn: InflatableDoorStack1
     disassembleTime: 3
+  - type: InflatableSafeDisassembly
   - type: Occluder
     enabled: false
index 2a971d71ea904ca4d864d31d26798cebb43170e6..675d9efa7029c01a94284bd26d3e99d816d5d09f 100644 (file)
   - type: BorgModuleIcon
     icon: { sprite: Interface/Actions/actions_borg.rsi, state: tool-module }
 
+- type: entity
+  id: BorgModuleInflatable
+  parent: [ BaseBorgModule, BaseProviderBorgModule ]
+  name: inflatable cyborg module
+  components:
+  - type: Sprite
+    layers:
+    - state: generic
+    - state: icon-inflatable
+  - type: ItemBorgModule
+    hands:
+    - item: InflatableDoorStack
+      hand:
+        emptyRepresentative: InflatableDoorStack
+        emptyLabel: borg-slot-inflatable-door-empty
+        whitelist:
+          tags:
+          - Inflatable
+    - item: InflatableWallStack
+      hand:
+        emptyRepresentative: InflatableWallStack
+        emptyLabel: borg-slot-inflatable-wall-empty
+        whitelist:
+          tags:
+          - Inflatable
+    - item: BoxInflatable
+    - item: WeaponMeleeNeedle
+  - type: BorgModuleIcon
+    icon: { sprite: Interface/Actions/actions_borg.rsi, state: inflatable-module }
+
 # cargo modules
 - type: entity
   id: BorgModuleAppraisal
index f5e05b4e285b86f04fdf290514ba6394f7f794c7..4f55d5c1649d228f924ac3f693b914b0a8742361 100644 (file)
@@ -5,21 +5,24 @@
   description: A folded membrane which rapidly expands into a large cubical shape on activation.
   suffix: Full
   components:
-    - type: Stack
-      stackType: InflatableWall
-      count: 10
-    - type: Sprite
-      sprite: Objects/Misc/inflatable_wall.rsi
-      state: item_wall
-    - type: Item
-      sprite: Objects/Misc/inflatable_wall.rsi
-      size: Small
-    - type: SpawnAfterInteract
-      prototype: InflatableWall
-      doAfter: 1
-      removeOnInteract: true
-    - type: Clickable
-    - type: PhysicalComposition
+  - type: Stack
+    stackType: InflatableWall
+    count: 10
+  - type: Sprite
+    sprite: Objects/Misc/inflatable_wall.rsi
+    state: item_wall
+  - type: Item
+    sprite: Objects/Misc/inflatable_wall.rsi
+    size: Small
+  - type: SpawnAfterInteract
+    prototype: InflatableWall
+    doAfter: 1
+    removeOnInteract: true
+  - type: Clickable
+  - type: PhysicalComposition
+  - type: Tag
+    tags:
+    - Inflatable
 # TODO: Add stack sprites + visuals.
 
 - type: entity
   description: A folded membrane which rapidly expands into a large cubical shape on activation.
   suffix: Full
   components:
-    - type: Stack
-      stackType: InflatableDoor
-      count: 4
-    - type: Sprite
-      sprite: Objects/Misc/inflatable_door.rsi
-      state: item_door
-    - type: Item
-      sprite: Objects/Misc/inflatable_door.rsi
-      size: Small
-    - type: SpawnAfterInteract
-      prototype: InflatableDoor
-      doAfter: 1
-      removeOnInteract: true
-    - type: Clickable
-    - type: PhysicalComposition
+  - type: Stack
+    stackType: InflatableDoor
+    count: 4
+  - type: Sprite
+    sprite: Objects/Misc/inflatable_door.rsi
+    state: item_door
+  - type: Item
+    sprite: Objects/Misc/inflatable_door.rsi
+    size: Small
+  - type: SpawnAfterInteract
+    prototype: InflatableDoor
+    doAfter: 1
+    removeOnInteract: true
+  - type: Clickable
+  - type: PhysicalComposition
+  - type: Tag
+    tags:
+    - Inflatable
 # TODO: Add stack sprites + visuals.
 
 - type: entity
   id: InflatableWallStack5
   suffix: 5
   components:
-    - type: Sprite
-      state: item_wall
-    - type: Stack
-      count: 5
+  - type: Sprite
+    state: item_wall
+  - type: Stack
+    count: 5
 
 - type: entity
   parent: InflatableWallStack
   id: InflatableWallStack1
   suffix: 1
   components:
-    - type: Sprite
-      state: item_wall
-    - type: Stack
-      count: 1
+  - type: Sprite
+    state: item_wall
+  - type: Stack
+    count: 1
 
 - type: entity
   parent: InflatableDoorStack
   id: InflatableDoorStack1
   suffix: 1
   components:
-    - type: Sprite
-      state: item_door
-    - type: Stack
-      count: 1
+  - type: Sprite
+    state: item_door
+  - type: Stack
+    count: 1
index f22cde9c528889f866fe81a25ea4b5dec2cbae98..2db59977be4725f610b3ec2b1b656ee2e7b11000 100644 (file)
@@ -14,6 +14,7 @@
   - BorgModuleTool
   - BorgModuleCable
   - BorgModuleFireExtinguisher
+  - BorgModuleInflatable
 
 - type: latheRecipePack
   id: BorgLimbsStatic
index 9210529a1d34f232f2cb163a0b3a84264ef66fdc..9465d7b87ad8b2e2c976bb9c2f49ee463835df8b 100644 (file)
   id: BorgModuleFireExtinguisher
   result: BorgModuleFireExtinguisher
 
+- type: latheRecipe
+  parent: BaseBorgModuleRecipe
+  id: BorgModuleInflatable
+  result: BorgModuleInflatable
+
 # Cargo Modules
 
 - type: latheRecipe
index 1c49713e26476af03b510573b422ac9e0ec871e4..1d88af8455dee618576e5a07b5daac1ce2226002 100644 (file)
@@ -14,6 +14,7 @@
 
   defaultModules:
   - BorgModuleTool
+  - BorgModuleInflatable
   - BorgModuleArtifact
   - BorgModuleAnomaly
   radioChannels:
index 95b261466f90970a471d529eca56e9b9889ee87a..a9b927cdcf78b8ada58b23dee569ea18caff4f48 100644 (file)
 - type: Tag
   id: Ingot
 
+- type: Tag
+  id: Inflatable
+
 - type: Tag
   id: InstantDoAfters
 
diff --git a/Resources/Textures/Interface/Actions/actions_borg.rsi/inflatable-module.png b/Resources/Textures/Interface/Actions/actions_borg.rsi/inflatable-module.png
new file mode 100644 (file)
index 0000000..15e1c86
Binary files /dev/null and b/Resources/Textures/Interface/Actions/actions_borg.rsi/inflatable-module.png differ
index ae485c26c5bf35dc76a4562cf4062d6528c66299..1766f0a7dea0e9fe63a11e2b5e18a3ee62e8bdce 100644 (file)
@@ -1,7 +1,7 @@
 {
     "version": 1,
     "license": "CC-BY-SA-3.0",
-    "copyright": "Taken from vgstation at commit https://github.com/vgstation-coders/vgstation13/commit/cdbcb1e858b11f083994a7a269ed67ef5b452ce9, Module actions by Scarky0. chem, adv-chem, and adv-mining by mubururu_, xenoborg actions by Samuka-C (github), advclown by ThatGuyUSA. c20r and esword by RedBookcase on Github.",
+    "copyright": "Taken from vgstation at commit https://github.com/vgstation-coders/vgstation13/commit/cdbcb1e858b11f083994a7a269ed67ef5b452ce9, inflatable module by FungiFellow (GitHub), Module actions by Scarky0. chem, adv-chem, and adv-mining by mubururu_, xenoborg actions by Samuka-C (github), advclown by ThatGuyUSA.  c20r and esword by RedBookcase on Github.",
     "size": {
         "x": 32,
         "y": 32
@@ -28,6 +28,9 @@
         {
             "name":"geiger-module"
         },
+        {
+            "name":"inflatable-module"
+        },
         {
             "name":"rcd-module"
         },
diff --git a/Resources/Textures/Objects/Specific/Robotics/borgmodule.rsi/icon-inflatable.png b/Resources/Textures/Objects/Specific/Robotics/borgmodule.rsi/icon-inflatable.png
new file mode 100644 (file)
index 0000000..8a6a2fa
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Robotics/borgmodule.rsi/icon-inflatable.png differ
index ae64caaa1538c6a3de7e4e14ec69f8fc8bda9011..922981560111639137f20d7d525cd67162279ee7 100644 (file)
@@ -1,7 +1,7 @@
 {
     "version": 1,
     "license": "CC0-1.0",
-    "copyright": "Created by EmoGarbage404 (github) for Space Station 14. icon-construction.png created by deltanedas (github). syndicateborgbomb.png created by Mangohydra (github). layered inhands by mubururu_ (github), icon-chem.png & icon-mining-adv.png created by mubururu_ (github), Xenoborg modules sprites by Samuka-C (github)",
+    "copyright": "Created by EmoGarbage404 (github) for Space Station 14. icon-construction.png created by deltanedas (github). syndicateborgbomb.png created by Mangohydra (github). icon-chem.png & icon-mining-adv.png created by mubururu_ (github) icon-inflatable.png made by FungiFellow (GitHub), Xenoborg modules sprites by Samuka-C (github)",
     "size": {
         "x": 32,
         "y": 32
@@ -28,6 +28,9 @@
         {
             "name": "icon-cables"
         },
+        {
+            "name": "icon-inflatable"
+        },
         {
             "name": "icon-chemist"
         },
             "directions": 4
         }
     ]
+
 }