Skip to content

Commit

Permalink
Add cartridge fabricator
Browse files Browse the repository at this point in the history
  • Loading branch information
BarryNorfolk committed Jan 12, 2025
1 parent a9d799b commit 5878925
Show file tree
Hide file tree
Showing 6 changed files with 260 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Robust.Shared.Audio;

namespace Content.Shared._DV.Chemistry.Components;

[RegisterComponent]
public sealed partial class CartridgeFabricatorComponent : Component
{
[DataField]
public List<string> Whitelist = [];

[DataField]
public string InputSolution = "drink";

[DataField]
public string OutputSolution = "cartridge";

public bool Emagged = false;

[DataField]
public SoundSpecifier SuccessSound = new SoundPathSpecifier("/Audio/Machines/tray_eject.ogg");

[DataField]
public SoundSpecifier FailureSound = new SoundPathSpecifier("/Audio/Machines/custom_deny.ogg");
}
137 changes: 137 additions & 0 deletions Content.Shared/_DV/Chemistry/Systems/CartridgeFabricatorSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
using System.Linq;
using Content.Shared._DV.Chemistry.Components;
using Content.Shared.Power.EntitySystems;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Components.SolutionManager;
using Content.Shared.Chemistry.EntitySystems;
using Content.Shared.Chemistry.Reagent;
using Content.Shared.Emag.Systems;
using Content.Shared.Hands.EntitySystems;
using Content.Shared.Interaction;
using Content.Shared.Labels.Components;
using Content.Shared.Popups;
using Content.Shared.Tag;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Prototypes;
using Robust.Shared.Network;
using Content.Shared.Labels.EntitySystems;

namespace Content.Shared._DV.Chemistry.Systems;

public sealed class CartridgeFabricatorSystem : EntitySystem
{
[Dependency] private readonly INetManager _net = default!;
[Dependency] private readonly SharedSolutionContainerSystem _container = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly TagSystem _tags = default!;
[Dependency] private readonly SharedHandsSystem _hands = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly SharedPowerReceiverSystem _power = default!;
[Dependency] private readonly SharedLabelSystem _labels = default!;
private static readonly ProtoId<TagPrototype>[] BottleTags = ["Bottle"];

public override void Initialize()
{
base.Initialize();

SubscribeLocalEvent<CartridgeFabricatorComponent, InteractUsingEvent>(OnInteractUsing);

SubscribeLocalEvent<CartridgeFabricatorComponent, OnAttemptEmagEvent>(OnAttemptEmag);
SubscribeLocalEvent<CartridgeFabricatorComponent, GotEmaggedEvent>(OnEmagged);
}

private bool ContainsDisallowedReagents(CartridgeFabricatorComponent fab, Solution solution)
{
foreach (ReagentQuantity reagent in solution.Contents)
{
_prototype.TryIndex<ReagentPrototype>(reagent.Reagent.Prototype, out var prototype);
if (fab.Whitelist.Any(entry => entry != prototype?.Group))
{
return true;
}
}
return false;
}

private void OnInteractUsing(Entity<CartridgeFabricatorComponent> entity, ref InteractUsingEvent args)
{
if (args.Handled || !_power.IsPowered(entity.Owner))
return;

if (!TryComp(args.Used, out SolutionContainerManagerComponent? manager))
return;

if (!_tags.HasAnyTag(args.Used, BottleTags))
return;

if (!_container.TryGetSolution((args.Used, manager),
entity.Comp.InputSolution,
out var _,
out var fromSolution))
return;

// This looks to be something we can handle
args.Handled = true;

if (fromSolution.Volume == 0)
{
_popup.PopupClient(Loc.GetString("cartridge-fabricator-empty-input"), args.User, PopupType.Medium);
_audio.PlayPredicted(entity.Comp.FailureSound, entity.Owner, args.User);
return;
}

// Emagging allows users to make cartridges out of anything
if (!entity.Comp.Emagged &&
ContainsDisallowedReagents(entity.Comp, fromSolution))
{
_popup.PopupClient(Loc.GetString("cartridge-fabricator-denied"), args.User, PopupType.Medium);
_audio.PlayPredicted(entity.Comp.FailureSound, entity.Owner, args.User);
return;
}

if (_net.IsServer)
{
var coords = Transform(entity.Owner).Coordinates;
var cartridge = Spawn("BaseEmptyHypoCartridge", coords);

var cartridgeManager = EnsureComp<SolutionContainerManagerComponent>(cartridge);
if (!_container.TryGetSolution((cartridge, cartridgeManager),
entity.Comp.OutputSolution,
out var cartridgeSolutionEnt,
out var _))
return; // Something very wrong here?

if (!_container.TryAddSolution(cartridgeSolutionEnt.Value, fromSolution))
return;

if (TryComp<LabelComponent>(args.Used, out var bottleLabel))
{
// Propagate the label from the bottle onto the cartridge
_labels.Label(cartridge, bottleLabel.CurrentLabel);
}

QueueDel(args.Used); // Ensure the bottle is gone
_hands.TryPickupAnyHand(args.User, cartridge);
}

_popup.PopupClient(Loc.GetString("cartridge-fabricator-success", ("amount", fromSolution.Volume)), args.User, PopupType.Medium);
_audio.PlayPredicted(entity.Comp.SuccessSound, entity.Owner, args.User);
}

private void OnAttemptEmag(Entity<CartridgeFabricatorComponent> entity, ref OnAttemptEmagEvent args)
{
if (entity.Comp.Emagged)
{
// No point in raising more local events when we're already emagged
args.Handled = true;
return;
}
}

private void OnEmagged(Entity<CartridgeFabricatorComponent> entity, ref GotEmaggedEvent args)
{
entity.Comp.Emagged = true;
args.Handled = true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
cartridge-fabricator-success = Created a cartridge with {$amount}u
cartridge-fabricator-denied = Input contains non-medical reagents
cartridge-fabricator-empty-input = Input contains no reagents
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

- type: entity
id: CartridgeFabricatorMachineCircuitboard
parent: BaseMachineCircuitboard
name: cartridge fabricator machine board
description: A machine printed circuit board for a cartridge fabricator
components:
- type: Sprite
state: service
- type: MachineBoard
prototype: CartridgeFabricator
stackRequirements:
Manipulator: 2
Capacitor: 1
# replacing the console screen
Glass: 1
Cable: 2
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,47 @@

- type: entity
id: BaseEmptyHypoCartridge
name: hypo cartridge
name: cartridge
parent: [BaseItem, BaseRestrictedContraband]
# TODO: Make these destructible
components:
- type: Damageable
damageContainer: Inorganic
damageModifierSet: Glass
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 5
behaviors:
- !type:PlaySoundBehavior
sound:
collection: GlassBreak
params:
volume: -4
- !type:SpillBehavior
solution: beaker
- !type:SpawnEntitiesBehavior
spawn:
ShardGlass:
min: 1
max: 1
transferForensics: true
- !type:DoActsBehavior
acts: [ "Destruction" ]
- type: DamageOnLand
damage:
types:
Blunt: 10 # glass resistance set reduces damage. Need to land twice (w/o hitting wall)
- type: DamageOtherOnHit
damage:
types:
Blunt: 5
- type: DamageOnHighSpeedImpact
minimumSpeed: 2
damage:
types:
Blunt: 5
- type: SolutionContainerManager
solutions:
cartridge:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
- type: entity
id: CartridgeFabricator
name: cartridge fabricator
parent: [ BaseMachinePowered, ConstructibleMachine ]
description: Converts bottles of chemicals into hypospray cartridges
components:
# TODO: Make this not the seed extractor
- type: Sprite
sprite: Structures/Machines/seed_extractor.rsi
snapCardinals: true
layers:
- state: seedextractor-off
- state: seedextractor-unlit
shader: unshaded
map: ["enum.PowerDeviceVisualLayers.Powered"]
- type: Physics
bodyType: Static
- type: Fixtures
fixtures:
fix1:
shape:
!type:PhysShapeAabb
bounds: "-0.25,-0.4,0.25,0.4"
density: 190
mask:
- MachineMask
layer:
- MachineLayer
- type: Appearance
- type: GenericVisualizer
visuals:
enum.PowerDeviceVisuals.Powered:
enum.PowerDeviceVisualLayers.Powered:
True: { visible: true }
False: { visible: false }
- type: CartridgeFabricator
whitelist:
- Medicine
- type: Machine
board: CartridgeFabricatorMachineCircuitboard

0 comments on commit 5878925

Please sign in to comment.