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