Inflatable Module (#35100)

Co-authored-by: ArtisticRoomba <145879011+ArtisticRoomba@users.noreply.github.com>
Co-authored-by: PJB3005 <pieterjan.briers+git@gmail.com>
This commit is contained in:
FungiFellow
2025-08-23 18:15:28 -04:00
committed by GitHub
parent 7429f56bd1
commit ed7bea8e01
20 changed files with 199 additions and 51 deletions

View File

@@ -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));
}
}

View 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";
}

View 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;

View File

@@ -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;

View 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

View File

@@ -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;
}
}

View 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.

View File

@@ -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.

View 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

View 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

View File

@@ -489,6 +489,36 @@
- 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

View 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
@@ -29,21 +32,24 @@
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
@@ -51,27 +57,27 @@
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

View File

@@ -14,6 +14,7 @@
- BorgModuleTool
- BorgModuleCable
- BorgModuleFireExtinguisher
- BorgModuleInflatable
- type: latheRecipePack
id: BorgLimbsStatic

View File

@@ -37,6 +37,11 @@
id: BorgModuleFireExtinguisher
result: BorgModuleFireExtinguisher
- type: latheRecipe
parent: BaseBorgModuleRecipe
id: BorgModuleInflatable
result: BorgModuleInflatable
# Cargo Modules
- type: latheRecipe

View File

@@ -14,6 +14,7 @@
defaultModules:
- BorgModuleTool
- BorgModuleInflatable
- BorgModuleArtifact
- BorgModuleAnomaly
radioChannels:

View File

@@ -801,6 +801,9 @@
- type: Tag
id: Ingot
- type: Tag
id: Inflatable
- type: Tag
id: InstantDoAfters

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

View 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"
},

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

View 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"
},
@@ -226,4 +229,5 @@
"directions": 4
}
]
}