From: deltanedas <39013340+deltanedas@users.noreply.github.com>
Date: Mon, 6 Nov 2023 03:04:47 +0000 (+0000)
Subject: add ied (#20966)
X-Git-Url: https://git.smokeofanarchy.ru/gitweb.cgi?a=commitdiff_plain;h=96e27810cfdc9bbe4ffbbb3e82e2e567eca7ff40;p=space-station-14.git
add ied (#20966)
* MinSolution and SolutionEmpty construction conditions
* make ied sprites
* add ied
* ied crafting stuff
* deconstruct give cable yes
* fix
* tags
* tag
* 3x3
* sharing is caring
* buff damage
---------
Co-authored-by: deltanedas <@deltanedas:kde.org>
---
diff --git a/Content.Server/Construction/Conditions/MinSolution.cs b/Content.Server/Construction/Conditions/MinSolution.cs
new file mode 100644
index 0000000000..d70e84761d
--- /dev/null
+++ b/Content.Server/Construction/Conditions/MinSolution.cs
@@ -0,0 +1,83 @@
+using Content.Shared.Chemistry.EntitySystems;
+using Content.Shared.Chemistry.Reagent;
+using Content.Shared.Construction;
+using Content.Shared.Examine;
+using Content.Shared.FixedPoint;
+using Robust.Shared.Prototypes;
+
+namespace Content.Server.Construction.Conditions;
+
+///
+/// Requires that a certain solution has a minimum amount of a reagent to proceed.
+///
+[DataDefinition]
+public sealed partial class MinSolution : IGraphCondition
+{
+ ///
+ /// The solution that needs to have the reagent.
+ ///
+ [DataField(required: true)]
+ public string Solution = string.Empty;
+
+ ///
+ /// The reagent that needs to be present.
+ ///
+ [DataField(required: true)]
+ public ReagentId Reagent = new();
+
+ ///
+ /// How much of the reagent must be present.
+ ///
+ [DataField]
+ public FixedPoint2 Quantity = 1;
+
+ public bool Condition(EntityUid uid, IEntityManager entMan)
+ {
+ var containerSys = entMan.System();
+ if (!containerSys.TryGetSolution(uid, Solution, out var solution))
+ return false;
+
+ solution.TryGetReagentQuantity(Reagent, out var quantity);
+ return quantity >= Quantity;
+ }
+
+ public bool DoExamine(ExaminedEvent args)
+ {
+ var entMan = IoCManager.Resolve();
+ var uid = args.Examined;
+
+ var containerSys = entMan.System();
+ if (!containerSys.TryGetSolution(uid, Solution, out var solution))
+ return false;
+
+ solution.TryGetReagentQuantity(Reagent, out var quantity);
+
+ // already has enough so dont show examine
+ if (quantity >= Quantity)
+ return false;
+
+ args.PushMarkup(Loc.GetString("construction-examine-condition-min-solution",
+ ("quantity", Quantity - quantity), ("reagent", Name())) + "\n");
+ return true;
+ }
+
+ public IEnumerable GenerateGuideEntry()
+ {
+ yield return new ConstructionGuideEntry()
+ {
+ Localization = "construction-guide-condition-min-solution",
+ Arguments = new (string, object)[]
+ {
+ ("quantity", Quantity),
+ ("reagent", Name())
+ }
+ };
+ }
+
+ private string Name()
+ {
+ var protoMan = IoCManager.Resolve();
+ var proto = protoMan.Index(Reagent.Prototype);
+ return proto.LocalizedName;
+ }
+}
diff --git a/Content.Server/Construction/Conditions/SolutionEmpty.cs b/Content.Server/Construction/Conditions/SolutionEmpty.cs
new file mode 100644
index 0000000000..d3cbd7356e
--- /dev/null
+++ b/Content.Server/Construction/Conditions/SolutionEmpty.cs
@@ -0,0 +1,52 @@
+using Content.Shared.Chemistry.EntitySystems;
+using Content.Shared.Construction;
+using Content.Shared.Examine;
+
+namespace Content.Server.Construction.Conditions;
+
+///
+/// Requires that a certain solution be empty to proceed.
+///
+[DataDefinition]
+public sealed partial class SolutionEmpty : IGraphCondition
+{
+ ///
+ /// The solution that needs to be empty.
+ ///
+ [DataField]
+ public string Solution;
+
+ public bool Condition(EntityUid uid, IEntityManager entMan)
+ {
+ var containerSys = entMan.System();
+ if (!containerSys.TryGetSolution(uid, Solution, out var solution))
+ return false;
+
+ return solution.Volume == 0;
+ }
+
+ public bool DoExamine(ExaminedEvent args)
+ {
+ var entMan = IoCManager.Resolve();
+ var uid = args.Examined;
+
+ var containerSys = entMan.System();
+ if (!containerSys.TryGetSolution(uid, Solution, out var solution))
+ return false;
+
+ // already empty so dont show examine
+ if (solution.Volume == 0)
+ return false;
+
+ args.PushMarkup(Loc.GetString("construction-examine-condition-solution-empty"));
+ return true;
+ }
+
+ public IEnumerable GenerateGuideEntry()
+ {
+ yield return new ConstructionGuideEntry()
+ {
+ Localization = "construction-guide-condition-solution-empty"
+ };
+ }
+}
diff --git a/Resources/Locale/en-US/construction/conditions/min-solution.ftl b/Resources/Locale/en-US/construction/conditions/min-solution.ftl
new file mode 100644
index 0000000000..884a351998
--- /dev/null
+++ b/Resources/Locale/en-US/construction/conditions/min-solution.ftl
@@ -0,0 +1,2 @@
+construction-examine-condition-min-solution = First, add {$quantity}u of {$reagent}.
+construction-guide-condition-min-solution = Add {$quantity}u of {$reagent}
diff --git a/Resources/Locale/en-US/construction/conditions/solution-empty.ftl b/Resources/Locale/en-US/construction/conditions/solution-empty.ftl
new file mode 100644
index 0000000000..0fd577a0f5
--- /dev/null
+++ b/Resources/Locale/en-US/construction/conditions/solution-empty.ftl
@@ -0,0 +1,3 @@
+# SolutionEmpty
+construction-examine-condition-solution-empty = First, empty the contents.
+construction-guide-condition-solution-empty = Empty the contents.
diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cans.yml b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cans.yml
index 3595d93ea0..9fdc594ed0 100644
--- a/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cans.yml
+++ b/Resources/Prototypes/Entities/Objects/Consumable/Drinks/drinks_cans.yml
@@ -59,6 +59,9 @@
- type: PhysicalComposition
materialComposition:
Steel: 50 #reduce, reuse, recycle
+ - type: Tag
+ tags:
+ - DrinkCan
- type: entity
parent: DrinkCanBaseFull
@@ -76,12 +79,38 @@
- type: Tag
tags:
- Cola
+ - DrinkCan
- Recyclable
- type: Sprite
sprite: Objects/Consumable/Drinks/cola.rsi
- type: Item
sprite: Objects/Consumable/Drinks/cola.rsi
+# created when taking apart an ied
+- type: entity
+ parent: DrinkColaCan
+ id: DrinkColaCanEmpty
+ suffix: empty
+ components:
+ - type: SolutionContainerManager
+ solutions:
+ drink:
+ maxVol: 30
+ - type: Openable
+ opened: true
+ - type: Sprite
+ sprite: Objects/Consumable/Drinks/cola.rsi
+ layers:
+ - state: icon_open
+ - type: Item
+ sprite: Objects/Consumable/Drinks/cola.rsi
+ - type: Tag
+ tags:
+ - Cola
+ - DrinkCan
+ - Recyclable
+ - Trash
+
- type: entity
parent: DrinkCanBaseFull
id: DrinkIcedTeaCan
@@ -317,6 +346,7 @@
Quantity: 5
- type: Tag
tags:
+ - DrinkCan
- Recyclable
- type: Sprite
sprite: Objects/Consumable/Drinks/robustnukie.rsi
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Bombs/ied.yml b/Resources/Prototypes/Entities/Objects/Weapons/Bombs/ied.yml
new file mode 100644
index 0000000000..7e669aea52
--- /dev/null
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Bombs/ied.yml
@@ -0,0 +1,101 @@
+# ied crafted from random stuff
+# ideally it would be dynamic and work by actually sparking the solution but that doesnt exist yet :(
+# with that you could make napalm ied instead of welding fuel with no additional complexity
+- type: entity
+ parent: BaseItem
+ id: ImprovisedExplosive
+ name: improvised explosive device
+ description: A weak, improvised incendiary device.
+ components:
+ - type: Sprite
+ sprite: Objects/Weapons/Bombs/ied.rsi
+ layers:
+ - state: base
+ - state: fuel
+ - state: wires
+ - type: Item
+ sprite: Objects/Consumable/Drinks/cola.rsi
+ - type: OnUseTimerTrigger
+ delay: 5
+ examinable: false
+ initialBeepDelay: 0
+ beepSound: /Audio/Effects/lightburn.ogg
+ # TODO: random timer when crafted
+ - type: TriggerOnSignal
+ - type: DeviceLinkSink
+ ports:
+ - Trigger
+ - type: Explosive # Weak explosion in a very small radius. Doesn't break underplating.
+ explosionType: Default
+ totalIntensity: 50
+ intensitySlope: 5
+ maxIntensity: 6
+ canCreateVacuum: false
+ - type: ExplodeOnTrigger
+ - type: Damageable
+ damageContainer: Inorganic
+ - type: Destructible
+ thresholds:
+ - trigger:
+ !type:DamageTrigger
+ damage: 50
+ behaviors:
+ - !type:DoActsBehavior
+ acts: ["Destruction"]
+ - !type:ExplodeBehavior
+ - type: Construction
+ graph: ImprovisedExplosive
+ node: ied
+
+# has igniter but no fuel or wires
+- type: entity
+ parent: DrinkColaCanEmpty
+ id: ImprovisedExplosiveEmpty
+ name: improvised explosive device
+ suffix: empty
+ description: A weak, improvised incendiary device. This one has no fuel.
+ components:
+ - type: Sprite
+ sprite: Objects/Weapons/Bombs/ied.rsi
+ layers:
+ - state: base
+ map: ["enum.OpenableVisuals.Layer"]
+ # bad dog
+ - type: GenericVisualizer
+ visuals:
+ enum.OpenableVisuals.Opened:
+ enum.OpenableVisuals.Layer:
+ True: {state: "base"}
+ False: {state: "base"}
+ - type: Construction
+ graph: ImprovisedExplosive
+ node: empty
+ defaultTarget: ied
+ - type: Tag
+ tags:
+ - Trash
+ # no DrinkCan, prevent using it to make another ied
+
+- type: entity
+ parent: ImprovisedExplosiveEmpty
+ id: ImprovisedExplosiveFuel
+ suffix: fuel
+ description: A weak, improvised incendiary device. This one is missing wires.
+ components:
+ - type: Sprite
+ layers:
+ - state: base
+ map: ["enum.OpenableVisuals.Layer"]
+ - state: fuel
+ - type: SolutionContainerManager
+ solutions:
+ drink:
+ maxVol: 30
+ reagents:
+ - ReagentId: WeldingFuel
+ Quantity: 30
+ - type: Construction
+ node: fuel
+ defaultTarget: ied
+ - type: Tag
+ tags: []
diff --git a/Resources/Prototypes/Recipes/Crafting/Graphs/improvised/ied.yml b/Resources/Prototypes/Recipes/Crafting/Graphs/improvised/ied.yml
new file mode 100644
index 0000000000..bdf06e558f
--- /dev/null
+++ b/Resources/Prototypes/Recipes/Crafting/Graphs/improvised/ied.yml
@@ -0,0 +1,75 @@
+- type: constructionGraph
+ id: ImprovisedExplosive
+ start: start
+ graph:
+ - node: start
+ edges:
+ - to: empty
+ steps:
+ - tag: DrinkCan
+ name: an empty can
+ icon:
+ sprite: Objects/Consumable/Drinks/cola.rsi
+ state: icon_open
+ doAfter: 1
+ - tag: Igniter
+ name: an igniter
+ icon:
+ sprite: Objects/Devices/igniter.rsi
+ state: icon
+ doAfter: 1
+ - node: empty
+ entity: ImprovisedExplosiveEmpty
+ edges:
+ - to: start
+ completed:
+ - !type:SpawnPrototype
+ prototype: DrinkColaCanEmpty
+ - !type:SpawnPrototype
+ prototype: Igniter
+ - !type:DeleteEntity {}
+ steps:
+ - tool: Prying
+ doAfter: 1
+ - to: fuel
+ conditions:
+ - !type:MinSolution
+ solution: drink
+ reagent:
+ ReagentId: WeldingFuel
+ quantity: 30
+ steps:
+ - tool: Screwing
+ doAfter: 1
+ - node: fuel
+ entity: ImprovisedExplosiveFuel
+ edges:
+ - to: empty
+ conditions:
+ - !type:SolutionEmpty
+ solution: drink
+ steps:
+ - tool: Screwing
+ doAfter: 1
+ - to: ied
+ conditions: # no dumping out 29u of the fuel then adding wires :)
+ - !type:MinSolution
+ solution: drink
+ reagent:
+ ReagentId: WeldingFuel
+ quantity: 30
+ steps:
+ - material: Cable
+ amount: 5
+ doAfter: 2
+ - node: ied
+ entity: ImprovisedExplosive
+ edges:
+ - to: fuel
+ completed:
+ - !type:SpawnPrototype
+ prototype: CableApcStack1
+ amount: 5
+ steps:
+ - tool: Cutting
+ doAfter: 2
diff --git a/Resources/Prototypes/Recipes/Crafting/improvised.yml b/Resources/Prototypes/Recipes/Crafting/improvised.yml
index 2f3b34db2b..df3a3bbdab 100644
--- a/Resources/Prototypes/Recipes/Crafting/improvised.yml
+++ b/Resources/Prototypes/Recipes/Crafting/improvised.yml
@@ -162,3 +162,16 @@
icon:
sprite: Objects/Misc/rifle_stock.rsi
state: icon
+
+- type: construction
+ name: improvised explosive device
+ id: improvisedexplosive
+ graph: ImprovisedExplosive
+ startNode: start
+ targetNode: ied
+ category: construction-category-weapons
+ objectType: Item
+ description: A weak, improvised incendiary device.
+ icon:
+ sprite: Objects/Weapons/Bombs/ied.rsi
+ state: icon
diff --git a/Resources/Prototypes/tags.yml b/Resources/Prototypes/tags.yml
index 8a120d7bf0..6d72187985 100644
--- a/Resources/Prototypes/tags.yml
+++ b/Resources/Prototypes/tags.yml
@@ -407,6 +407,9 @@
- type: Tag
id: Donut
+- type: Tag
+ id: DrinkCan
+
- type: Tag
id: DrinkSpaceGlue
diff --git a/Resources/Textures/Objects/Weapons/Bombs/ied.rsi/base.png b/Resources/Textures/Objects/Weapons/Bombs/ied.rsi/base.png
new file mode 100644
index 0000000000..dda9a11195
Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Bombs/ied.rsi/base.png differ
diff --git a/Resources/Textures/Objects/Weapons/Bombs/ied.rsi/fuel.png b/Resources/Textures/Objects/Weapons/Bombs/ied.rsi/fuel.png
new file mode 100644
index 0000000000..217abeb24f
Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Bombs/ied.rsi/fuel.png differ
diff --git a/Resources/Textures/Objects/Weapons/Bombs/ied.rsi/icon.png b/Resources/Textures/Objects/Weapons/Bombs/ied.rsi/icon.png
new file mode 100644
index 0000000000..a8c37b9910
Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Bombs/ied.rsi/icon.png differ
diff --git a/Resources/Textures/Objects/Weapons/Bombs/ied.rsi/meta.json b/Resources/Textures/Objects/Weapons/Bombs/ied.rsi/meta.json
new file mode 100644
index 0000000000..6ec234fecd
--- /dev/null
+++ b/Resources/Textures/Objects/Weapons/Bombs/ied.rsi/meta.json
@@ -0,0 +1,23 @@
+{
+ "version": 1,
+ "license": "CC-BY-SA-3.0",
+ "copyright": "Created by deltanedas (github) for SS14, icon and base based on cola sprite from cev-eris",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "icon"
+ },
+ {
+ "name": "base"
+ },
+ {
+ "name": "fuel"
+ },
+ {
+ "name": "wires"
+ }
+ ]
+}
diff --git a/Resources/Textures/Objects/Weapons/Bombs/ied.rsi/wires.png b/Resources/Textures/Objects/Weapons/Bombs/ied.rsi/wires.png
new file mode 100644
index 0000000000..bfc9beed6d
Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Bombs/ied.rsi/wires.png differ