From 46ec3b402afffc6123cbc15ecc9d87aeae960b4d Mon Sep 17 00:00:00 2001
From: slarticodefast <161409025+slarticodefast@users.noreply.github.com>
Date: Mon, 7 Jul 2025 23:43:33 +0200
Subject: [PATCH] New science unlock: the H.A.R.M.P.A.C.K (#38824)
---
.../ExtraHandsEquipmentComponent.cs | 18 ++++++++
.../ExtraHandsEquipmentSystem.cs | 43 ++++++++++++++++++
.../Locale/en-US/research/technologies.ftl | 1 +
.../Entities/Clothing/Back/specific.yml | 22 +++++++++
.../Recipes/Lathes/Packs/science.yml | 1 +
.../Recipes/Lathes/Packs/security.yml | 1 +
.../Prototypes/Recipes/Lathes/security.yml | 12 +++++
Resources/Prototypes/Research/arsenal.yml | 12 +++++
.../harmpack.rsi/equipped-BACKPACK.png | Bin 0 -> 1521 bytes
.../Back/Specific/harmpack.rsi/icon.png | Bin 0 -> 657 bytes
.../Specific/harmpack.rsi/inhand-left.png | Bin 0 -> 487 bytes
.../Specific/harmpack.rsi/inhand-right.png | Bin 0 -> 521 bytes
.../Back/Specific/harmpack.rsi/meta.json | 26 +++++++++++
13 files changed, 136 insertions(+)
create mode 100644 Content.Shared/Hands/Components/ExtraHandsEquipmentComponent.cs
create mode 100644 Content.Shared/Hands/EntitySystems/ExtraHandsEquipmentSystem.cs
create mode 100644 Resources/Textures/Clothing/Back/Specific/harmpack.rsi/equipped-BACKPACK.png
create mode 100644 Resources/Textures/Clothing/Back/Specific/harmpack.rsi/icon.png
create mode 100644 Resources/Textures/Clothing/Back/Specific/harmpack.rsi/inhand-left.png
create mode 100644 Resources/Textures/Clothing/Back/Specific/harmpack.rsi/inhand-right.png
create mode 100644 Resources/Textures/Clothing/Back/Specific/harmpack.rsi/meta.json
diff --git a/Content.Shared/Hands/Components/ExtraHandsEquipmentComponent.cs b/Content.Shared/Hands/Components/ExtraHandsEquipmentComponent.cs
new file mode 100644
index 0000000000..fb3685c386
--- /dev/null
+++ b/Content.Shared/Hands/Components/ExtraHandsEquipmentComponent.cs
@@ -0,0 +1,18 @@
+using Robust.Shared.GameStates;
+using Content.Shared.Hands.EntitySystems;
+
+namespace Content.Shared.Hands.Components;
+
+///
+/// An entity with this component will give you extra hands when you equip it in your inventory.
+///
+[RegisterComponent, NetworkedComponent]
+[Access(typeof(ExtraHandsEquipmentSystem))]
+public sealed partial class ExtraHandsEquipmentComponent : Component
+{
+ ///
+ /// Dictionary relating a unique hand ID corresponding to a container slot on the attached entity to a struct containing information about the Hand itself.
+ ///
+ [DataField]
+ public Dictionary Hands = new();
+}
diff --git a/Content.Shared/Hands/EntitySystems/ExtraHandsEquipmentSystem.cs b/Content.Shared/Hands/EntitySystems/ExtraHandsEquipmentSystem.cs
new file mode 100644
index 0000000000..4b96f89d81
--- /dev/null
+++ b/Content.Shared/Hands/EntitySystems/ExtraHandsEquipmentSystem.cs
@@ -0,0 +1,43 @@
+using Content.Shared.Hands.Components;
+using Content.Shared.Inventory.Events;
+
+namespace Content.Shared.Hands.EntitySystems;
+
+public sealed class ExtraHandsEquipmentSystem : EntitySystem
+{
+ [Dependency] private readonly SharedHandsSystem _hands = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnEquipped);
+ SubscribeLocalEvent(OnUnequipped);
+ }
+
+ private void OnEquipped(Entity ent, ref GotEquippedEvent args)
+ {
+ if (!TryComp(args.Equipee, out var handsComp))
+ return;
+
+ foreach (var (handName, hand) in ent.Comp.Hands)
+ {
+ // add the NetEntity id to the container name to prevent multiple items with this component from conflicting
+ var handId = $"{GetNetEntity(ent.Owner).Id}-{handName}";
+ _hands.AddHand((args.Equipee, handsComp), handId, hand.Location);
+ }
+ }
+
+ private void OnUnequipped(Entity ent, ref GotUnequippedEvent args)
+ {
+ if (!TryComp(args.Equipee, out var handsComp))
+ return;
+
+ foreach (var handName in ent.Comp.Hands.Keys)
+ {
+ // add the NetEntity id to the container name to prevent multiple items with this component from conflicting
+ var handId = $"{GetNetEntity(ent.Owner).Id}-{handName}";
+ _hands.RemoveHand((args.Equipee, handsComp), handId);
+ }
+ }
+}
diff --git a/Resources/Locale/en-US/research/technologies.ftl b/Resources/Locale/en-US/research/technologies.ftl
index 876579eea5..62432b8dd6 100644
--- a/Resources/Locale/en-US/research/technologies.ftl
+++ b/Resources/Locale/en-US/research/technologies.ftl
@@ -39,6 +39,7 @@ research-technology-kinetic-modifications = Kinetic Modifications
research-technology-basic-shuttle-armament = Shuttle Basic Armament
research-technology-advanced-shuttle-weapon = Advanced Shuttle Weapons
research-technology-thermal-weaponry = Thermal Weaponry
+research-technology-dual-wielding-technology = Dual Wielding Technology
research-technology-basic-robotics = Basic Robotics
research-technology-basic-anomalous-research = Basic Anomalous Research
diff --git a/Resources/Prototypes/Entities/Clothing/Back/specific.yml b/Resources/Prototypes/Entities/Clothing/Back/specific.yml
index ff06b93bbf..d303aa166c 100644
--- a/Resources/Prototypes/Entities/Clothing/Back/specific.yml
+++ b/Resources/Prototypes/Entities/Clothing/Back/specific.yml
@@ -98,3 +98,25 @@
- type: Construction
graph: ClothingBagPet
node: bagPet
+
+- type: entity
+ parent: Clothing
+ id: ClothingBackpackHarmpack
+ name: H.A.R.M.P.A.C.K.
+ description: Now you can reload, punch, and eat a snack - simultaneously.
+ components:
+ - type: Sprite
+ sprite: Clothing/Back/Specific/harmpack.rsi
+ state: icon
+ - type: Item
+ size: Ginormous
+ - type: Clothing
+ slots: BACK
+ - type: ExtraHandsEquipment
+ hands:
+ # middle hands to prevent overlapping inhand sprites
+ # This can be changed once we have per-hand displacement maps
+ extra_hand_1:
+ location: Middle
+ extra_hand_2:
+ location: Middle
diff --git a/Resources/Prototypes/Recipes/Lathes/Packs/science.yml b/Resources/Prototypes/Recipes/Lathes/Packs/science.yml
index 6308570e6f..164a85dc44 100644
--- a/Resources/Prototypes/Recipes/Lathes/Packs/science.yml
+++ b/Resources/Prototypes/Recipes/Lathes/Packs/science.yml
@@ -30,6 +30,7 @@
- SignallerAdvanced
- DeviceQuantumSpinInverter
- DeviceDesynchronizer
+ - ClothingBackpackHarmpack
- type: latheRecipePack
id: ScienceClothing
diff --git a/Resources/Prototypes/Recipes/Lathes/Packs/security.yml b/Resources/Prototypes/Recipes/Lathes/Packs/security.yml
index 4beee0f9d1..f3e8891b25 100644
--- a/Resources/Prototypes/Recipes/Lathes/Packs/security.yml
+++ b/Resources/Prototypes/Recipes/Lathes/Packs/security.yml
@@ -75,6 +75,7 @@
- PowerCageMedium
- PowerCageSmall
- TelescopicShield
+ - ClothingBackpackHarmpack
- type: latheRecipePack
id: SecurityBoards
diff --git a/Resources/Prototypes/Recipes/Lathes/security.yml b/Resources/Prototypes/Recipes/Lathes/security.yml
index 606e628669..71f815e5aa 100644
--- a/Resources/Prototypes/Recipes/Lathes/security.yml
+++ b/Resources/Prototypes/Recipes/Lathes/security.yml
@@ -84,6 +84,18 @@
Plasma: 500
Glass: 500
+- type: latheRecipe
+ id: ClothingBackpackHarmpack
+ result: ClothingBackpackHarmpack
+ categories:
+ - Clothing
+ completetime: 15
+ materials:
+ Steel: 2000
+ Plastic: 1000
+ Plasma: 500
+ Gold: 500
+
# Shields
- type: latheRecipe
parent: BaseShieldRecipe
diff --git a/Resources/Prototypes/Research/arsenal.yml b/Resources/Prototypes/Research/arsenal.yml
index 7ba7cea9da..bb12a2c25f 100644
--- a/Resources/Prototypes/Research/arsenal.yml
+++ b/Resources/Prototypes/Research/arsenal.yml
@@ -191,6 +191,18 @@
technologyPrerequisites:
- SalvageWeapons
+- type: technology
+ id: DualWieldingTechnology
+ name: research-technology-dual-wielding-technology
+ icon:
+ sprite: Clothing/Back/Specific/harmpack.rsi
+ state: icon
+ discipline: Arsenal
+ tier: 2
+ cost: 10000
+ recipeUnlocks:
+ - ClothingBackpackHarmpack
+
# Tier 3
- type: technology
diff --git a/Resources/Textures/Clothing/Back/Specific/harmpack.rsi/equipped-BACKPACK.png b/Resources/Textures/Clothing/Back/Specific/harmpack.rsi/equipped-BACKPACK.png
new file mode 100644
index 0000000000000000000000000000000000000000..f1f9e5aff718d17e8f3168c5a6efda1ca5745cf2
GIT binary patch
literal 1521
zcmVPx)t4TybRCt{2nm=gUSRBW{3L$iCgUrzk(Pb#ck-&s#%`$>9hn5r>zP7f~#vHJHM?;rxWGe^zKp3w<9j
zw)KAceSh!i_ax)r58!Y(91e%`qavgYl*?tRC<;u|1OOw*}w#>E7O6Fir@8=Xuok
zeU!^(dVYQ`7={rGB#%A-Wa%Fr9l`f~FemrvJBg{(dl$3Aq4Ez>2#=V+mL1XTKZrafKmE<`0xS!en0UF
zF=x82L)Ue>ySp0*>AFtYc-nb{5Mh3Po~2^!3Qp1|gupNi;pF6m0>Ja<&&N_)6h+*>
ze?M`rXX#Hf=bEOm)C;amQXsp#y8@eV^mvkZ_$te?jM>@Qv19CWUVQ*~^ym>B$HCpZ
zcZ2sgZ{8%@PST$OfJUQ1mzI`LsZ+dx&6wGofT1BHBsRRJ{>)ud}nWOntVvE1RFj^rrwoRaL=t-CXG(
zo;)MZB4lZ(sw!BPHBq14d{UaQrpVHlbJ
z^M5JKKhp}wfYCy*xY;<1JI!b67BEc{7Z(@7_vPhfEG#UHUG>AmLxBabwY8O4Hos|f
zT@N}$*4NkR;o)HrPrKa~78Vw;yu2LPUtC-SeMU*7E&%J+s8*|#RZ(8Nco9pZ;cz%s
zlKPqzm#}YL*XeLLjM=al2_dLft2C`Mgps-c`}_MsrBXqqQi;{`!$cb+vTVPUsPD9<
z3}(yX&w2_>Cmm$_=XK)>tZyI-+qThcHmM{@5JeG|Hp0CKY(7cxBxV3>KEkMPpin5FR4S$3;99Mg(ChW!I8I=T35CzRFdwB-357xd
zj^hNq32FAs*8Zr*<`X3|1G?QVL{Y?G09Lxr47S(nVK5lvvb`>rWkD20^m@JAw#C)|
zV=;b9&w#`QV5q7pbh};3K5uMnBzAbQo&iD#c6N4x<2Ut490eZe8itYBrvLyO8yocP
z+qYwJXZg-tfT)9+nVHylQXn_|TOerPx%OG!jQR9J=Wma%IhK@`S+dmP&&jq9Yau{+czOBA~+Y=wZ3<^<0o&1Jbl2-seA
zrTzhOl@bD}0)d01v|mzWQFbk@wKM?BvJ^nMT-FMO!s`mKEK7|>BYfXS*L8rPpGYJEQLiGP
zR4OUo_mNTpAcO!|`qy=xtE;QXcHcxHnWm|d$z6Bb97sXzH+uK_V!{Ge|I(9w!e=-1vSM!w_qCVPy`yEA+@@GPo{`
z$7A4EyDGA8Ut0lZv3>vH2d?YF_YDQq>vgT!Y$_o{P-qqnhe1k-5CYeAsn_c(k78&Y
zXf~UQ2-*A`rfI@cAnSM=mEwFpuhQu>sZ{F4`N3d-=Xuz+9ocSZ9aw}A0?+eS&U>D>
zbY%a!0A1G+LU49=rsebbrOdW%TPqfeYJNjTMWj0L9K~W$@w6lJi05OQV&nHfsZ>%t
ry#cPTueG`JdE}d1#anE##eadHM6BcFo<#(600000NkvXXu0mjf5+*j>
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Clothing/Back/Specific/harmpack.rsi/inhand-left.png b/Resources/Textures/Clothing/Back/Specific/harmpack.rsi/inhand-left.png
new file mode 100644
index 0000000000000000000000000000000000000000..6b3dfd73ed24ebb3ad7f1718bebb25cb3b80b577
GIT binary patch
literal 487
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D%z7kaulhE&XX
zduyZLAqN?@5B!g%FPyd5WngjQ$hED9uFPH8S@Maqz$kAIlPB-`gy3V-o0d3`#JtN}I>|_w{OvD>Fkblvr);d;I4|Tvo4H
z2Ty|8>_~RB!hc2DWUUmaX-M48^mChGutSz*bQR+*sE-cR6
zdhNt#nb}jjPi92^WIi?X=^C>+=Da(K?lUmFU*BNJc0Q0rqIvmmcZp;MhP&CVdJKE6
zoYqPAeC^SqvD9Gx`S1S@I|`JbxB>(^b
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Clothing/Back/Specific/harmpack.rsi/inhand-right.png b/Resources/Textures/Clothing/Back/Specific/harmpack.rsi/inhand-right.png
new file mode 100644
index 0000000000000000000000000000000000000000..224065dc6856518f2f49b18bddba4bf7e041ce41
GIT binary patch
literal 521
zcmV+k0`~ohP)Px$!%0LzRCt{2+ObN*Ko|$`f5kU2n>f03uwbWd2c4=;*$ah$&E(YaoW!lKP*Cy;
zhPo8)2?`PE9uRH_eTH+Yq^4l%^konP-Fq#Ykj`8t>*?={^iO5qFu-j4Z{!=y8#MAp`>L!}gEvsrG}JkM(hAuL6$>RmdRz5vDAj