From 96e27810cfdc9bbe4ffbbb3e82e2e567eca7ff40 Mon Sep 17 00:00:00 2001
From: deltanedas <39013340+deltanedas@users.noreply.github.com>
Date: Mon, 6 Nov 2023 03:04:47 +0000
Subject: [PATCH] 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>
---
.../Construction/Conditions/MinSolution.cs | 83 ++++++++++++++
.../Construction/Conditions/SolutionEmpty.cs | 52 +++++++++
.../construction/conditions/min-solution.ftl | 2 +
.../conditions/solution-empty.ftl | 3 +
.../Objects/Consumable/Drinks/drinks_cans.yml | 30 ++++++
.../Entities/Objects/Weapons/Bombs/ied.yml | 101 ++++++++++++++++++
.../Crafting/Graphs/improvised/ied.yml | 75 +++++++++++++
.../Recipes/Crafting/improvised.yml | 13 +++
Resources/Prototypes/tags.yml | 3 +
.../Objects/Weapons/Bombs/ied.rsi/base.png | Bin 0 -> 884 bytes
.../Objects/Weapons/Bombs/ied.rsi/fuel.png | Bin 0 -> 901 bytes
.../Objects/Weapons/Bombs/ied.rsi/icon.png | Bin 0 -> 961 bytes
.../Objects/Weapons/Bombs/ied.rsi/meta.json | 23 ++++
.../Objects/Weapons/Bombs/ied.rsi/wires.png | Bin 0 -> 651 bytes
14 files changed, 385 insertions(+)
create mode 100644 Content.Server/Construction/Conditions/MinSolution.cs
create mode 100644 Content.Server/Construction/Conditions/SolutionEmpty.cs
create mode 100644 Resources/Locale/en-US/construction/conditions/min-solution.ftl
create mode 100644 Resources/Locale/en-US/construction/conditions/solution-empty.ftl
create mode 100644 Resources/Prototypes/Entities/Objects/Weapons/Bombs/ied.yml
create mode 100644 Resources/Prototypes/Recipes/Crafting/Graphs/improvised/ied.yml
create mode 100644 Resources/Textures/Objects/Weapons/Bombs/ied.rsi/base.png
create mode 100644 Resources/Textures/Objects/Weapons/Bombs/ied.rsi/fuel.png
create mode 100644 Resources/Textures/Objects/Weapons/Bombs/ied.rsi/icon.png
create mode 100644 Resources/Textures/Objects/Weapons/Bombs/ied.rsi/meta.json
create mode 100644 Resources/Textures/Objects/Weapons/Bombs/ied.rsi/wires.png
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 0000000000000000000000000000000000000000..dda9a11195bce3c9ddcf372ec5e9e012d25759cd
GIT binary patch
literal 884
zcmV-)1B?8LP)_bRT&6~omb6cHZLZO0RqX-KSjw&E?}Ha(-Q
z2pooz33q3$g8ny;`jV)To12l^
zDZ2}oB$LF6k)psV79ImqbCOwQ-{7xrioAGqdD|3m#E~W=-hNRF($$b^if+hbQB=AA
z&(k%Bhl1|WIMhA){#y^!@4)xA?|&Wn{`WD|JiO?8M%#4-6bbfLOBdKOFl3EgiERPLyWYE`E2lH2L+6|_s_0MFud1W^v
zO+x@=In1{Xjv;XItip7L1N+x7sOz}?C)E)or-3j(SGc7xpsp+j4+)Y1C<=(hO*%&Z
zqcS`GKYR571#jPf^1qt4%l{Y!mH(ue2f`#L!lk-=4AJ#7FvMHG-eK5CMw%uo7xewU
z!|>+%bvXa})2H+;2gIk(W)RWTg!46X^Qq?mMn*;qEH5wrA4G$5!sSm46Bn*wI3JzL
z(5B}L7SqlvAipF+PZYR-oSfYM$jHe5AR2~23G(IaIsaEHDEzq-
zMMXt8|Ni~^4BKR7;b{Pr2p8YKP1|x{kI!9(13R99X&A7tsiR&Rz!zL8d?F0WlbIOg
z)qjHNhj$+`XdgJj@ap47`c+1!+}yyq;ALhi!&L_x`ewr=|AiW6oj3=#7};`A{GZ}h
zXrOs*2&{1GV;JATExPsP6C`ASmIEuIMw&Zdv`IGVfKdlf8vp>9&oz;XXO@=$0000<
KMNUMnLSTX~p`F(N
literal 0
HcmV?d00001
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 0000000000000000000000000000000000000000..217abeb24f85258c83039707872562fd4c189ee3
GIT binary patch
literal 901
zcmV;01A6?4P)_bRT&6~omb6cHZLZO0RqX-KSjw&E?}Ha(-Q
z2pooz33q3$g8ny;`jV)To12l^
zDZ2}oB$LF6k)psV79ImqbCOwQ-{7xrioAGqdD|3m#E~W=-hNRF($$b^if+hbQB=AA
z&(k%Bhl1|WIMhA){#y^!@4)xA?|&Wn{`WD|JiO|q287qV7{Nxal&0-|ABm`L=8|KKMudNQ|uiCU5Oi$~d$#C<^ZrX+b
z$a0u(4>sz6T`ms9FAe({5A0vVpswRevLi@N17UuyU>am8OiW!_4jvLD15gwYi<@+e
z7@{&e7@ocQfP%O0Kgpn`?ZObFphA*)AWU*1T&l~*5M4h5&i7@S@_+Nc9LCnKcNjL3
zk*3MY1%1EoFub{b9n8LLz`zi=eFlBY0rBax8ALQS!ED_N@{F3f`P6d&BO@aQmY0_Y
z)8L$N`4hv$g=-kjN2fBh>G^`iwDStcFNx3-1uh^bC&v&O840Fg7?dDi&Yr`tT0w!~
zN^d_|i4db8g83AeBNP=C;r#pe?=x(Zm1Vg8^eLDRN`#B=-==LE*yD4T;lPe(U>XMO
zYwD<%2Ji(}3ZDpr@?<6kdG()Q`r+M&4B7{dFueNsk$#oYDK|H8E_j)l%5c@e1}p}P
z0-9&TCI5vOW}P?(w;0)SQ2d|bR-k=t2&!;m7~jG9x4wLWgbdJfa%w}y(T>Te14bP%
b&<+3qMGGNBzcKpr00000NkvXXu0mjfz`die
literal 0
HcmV?d00001
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 0000000000000000000000000000000000000000..a8c37b99108bafae9fa2269676f3154950025ba3
GIT binary patch
literal 961
zcmV;y13vtTP)_bRT&6~omb6cHZLZO0RqX-KSjw&E?}Ha(-Q
z2pooz33q3$g8ny;`jV)To12l^
zDZ2}oB$LF6k)psV79ImqbCOwQ-{7xrioAGqdD|3m#E~W=-hNRF($$b^if+hbQB=AA
z&(k%Bhl1|WIMhA){#y^!@4)xA?|&Wn{`WD|JiiWiXwe9Kr|$v~_V*X2<{S`%nIV_UZ!|tAxq_mvR*UucqztpB(d;u=x-d
z23ZdC?ZHMJ29t1ghGx;f3`)VW3=%b#GlZ>j
zp-vFv3xOsbqyL~#fCWE#6vQZ~kQ@Rm7^xCZA_7{(@Kl$NA-aABnEyz74VZS&C}aq{
zKZ9W-rg7BG1t6btiE=O;;d5oM`Lvti+v^|TXkgh2vAELgKf|3>4;d+P04S(&fo5If
z|1(6NGJqTbvV7Ms6|i`K^b;^21fK1G$w*Nm1VsTlmY0|R4~rU5aOb%7FwCvn#L%Ya
z3%4BPD5v|p3^r3t{!={)Kta!Pmz}}d+M40$(W7wjKgvJB^u+s|44S$53~pOGNDcv_
z6@z^CsOuGjqM{;P?Ed}x4BKR78LmHl3XXpeAT=NujaC4&+fOlqv*D5lcW4s=ptuDkHc-6Fm5G6AX*UVD
z<>UgA>H?lux(%RExVQE(IMsu)A{1{S&XF^uov7Tx;t2~2}5zj_bRT&6~omb6cHZLZO0RqX-KSjw&E?}Ha(-Q
z2pooz33q3$g8ny;`jV)To12l^
zDZ2}oB$LF6k)psV79ImqbCOwQ-{7xrioAGqdD|3m#E~W=-hNRF($$b^if+hbQB=AA
z&(k%Bhl1|WIMhA){#y^!@4)xA?|&Wn{`WD|JiAy5gE|1aez
z{-0_F{{R0U1LFcPi*2Tu42%PiLxF0JAk_hsMgbGL03#zK21XBZ7=Zcu+5VS|bV+a^
z2Y`Hx%jYmTQUD{iD8Lpf$d2F=s`Ul+SAd5kKx`qaN8i4tpsyPBz+#`!4%TcvF
zKnH|;1_}Xk(f|{&3SS(0P0(?7Ry|~-OAerh&vE7gV$yaP
luq;QZ#iL*pjDk@B0|1Gih>VPvK|}xm002ovPDHLkV1l|{A`1Wj
literal 0
HcmV?d00001
--
2.51.2