From 0269efcda3531b8668d513913bee21c4a84c2f11 Mon Sep 17 00:00:00 2001 From: SimpleStation14 <130339894+SimpleStation14@users.noreply.github.com> Date: Sat, 29 Jun 2024 15:46:53 -0700 Subject: [PATCH 01/15] Mirror: Throwing Knives: Syndicate Kit (#310) ## Mirror of PR #26026: [Throwing Knives: Syndicate Kit](https://github.com/space-wizards/space-station-14/pull/26026) from space-wizards [space-wizards](https://github.com/space-wizards)/[space-station-14](https://github.com/space-wizards/space-station-14) ###### `393bcbfc1346589075ad960473685c78bdbf46e5` PR opened by UbaserB at 2024-03-12 06:57:41 UTC --- PR changed 13 files with 101 additions and 8 deletions. The PR had the following labels: - No C# - Changes: Sprites ---

Original Body

> > > > ## About the PR > > > This PR adds throwing knives and a syndicate bundle in the bundle category for 6 TC which comes with 4 throwing knives in a box. Each knife does 10 slash + 15 pierce damage on throw, and 5 flash per hit (10 DPS). This makes it better than a kitchen knife, but worse than a combat knife, which is what security is fitted with. > > ## Why / Balance > > > This kit is built for weakening an enemy from a distance (from chasing, etc) while being able to fight back if cornered into a 1v1 CQC fight. Sure, you can kill several people with the kit; hence why it's so expensive, but there are drawbacks. Firstly, once it embeds into a target they are able to pull it out. Secondly, when you are pulling them out of a target, YOU are vulnerable. Thirdly, if you miss your hits the target will probably not die. Good things you have four knives and can stab them to death.. better than punches! > > ## Media > > > - [X] I have added screenshots/videos to this PR showcasing its changes ingame, **or** this PR does not require an ingame showcase > > **It embeds and kills in 4 throws on an unarmoured target.** > ![image](https://github.com/space-wizards/space-station-14/assets/134914314/05f4112d-a08c-4bde-9b34-8a5ecde0b270) > > **Item description.** > ![image](https://github.com/space-wizards/space-station-14/assets/134914314/87704a6e-8501-4f19-a158-bf89d6b4a83e) > > **4 knives.** > ![image](https://github.com/space-wizards/space-station-14/assets/134914314/44dc4c40-add3-46be-b224-b71e2f14f1e9) > > **Kit on uplink.** > [IMG NEEDS UPDATING] > > **Changelog** > > :cl: Ubaser > - add: You can now purchase a set of 4 throwing knives in the uplink as a bundle for 12 TC.
--------- Co-authored-by: SimpleStation14 Co-authored-by: VMSolidus --- .../Locale/en-US/store/uplink-catalog.ftl | 3 ++ .../Catalog/Fills/Boxes/syndicate.yml | 37 +++++++++++++----- .../Prototypes/Catalog/uplink_catalog.yml | 11 ++++++ .../Entities/Objects/Weapons/Melee/knife.yml | 29 ++++++++++++++ .../Objects/Storage/boxes.rsi/meta.json | 17 ++++---- .../Storage/boxes.rsi/throwing_knives.png | Bin 0 -> 1141 bytes .../Objects/Storage/boxicons.rsi/meta.json | 5 ++- .../Storage/boxicons.rsi/throwing_knives.png | Bin 0 -> 1392 bytes .../throwing_knife.rsi/equipped-BELT.png | Bin 0 -> 1289 bytes .../Weapons/Melee/throwing_knife.rsi/icon.png | Bin 0 -> 1593 bytes .../Melee/throwing_knife.rsi/inhand-left.png | Bin 0 -> 1296 bytes .../Melee/throwing_knife.rsi/inhand-right.png | Bin 0 -> 1298 bytes .../Melee/throwing_knife.rsi/meta.json | 26 ++++++++++++ 13 files changed, 110 insertions(+), 18 deletions(-) create mode 100644 Resources/Textures/Objects/Storage/boxes.rsi/throwing_knives.png create mode 100644 Resources/Textures/Objects/Storage/boxicons.rsi/throwing_knives.png create mode 100644 Resources/Textures/Objects/Weapons/Melee/throwing_knife.rsi/equipped-BELT.png create mode 100644 Resources/Textures/Objects/Weapons/Melee/throwing_knife.rsi/icon.png create mode 100644 Resources/Textures/Objects/Weapons/Melee/throwing_knife.rsi/inhand-left.png create mode 100644 Resources/Textures/Objects/Weapons/Melee/throwing_knife.rsi/inhand-right.png create mode 100644 Resources/Textures/Objects/Weapons/Melee/throwing_knife.rsi/meta.json diff --git a/Resources/Locale/en-US/store/uplink-catalog.ftl b/Resources/Locale/en-US/store/uplink-catalog.ftl index 70eb998bb40..4836a57d6b1 100644 --- a/Resources/Locale/en-US/store/uplink-catalog.ftl +++ b/Resources/Locale/en-US/store/uplink-catalog.ftl @@ -201,6 +201,9 @@ uplink-decoy-kit-desc = State-of-the-art distraction technology straight from RN uplink-chemistry-kit-name = Chemical Synthesis Kit uplink-chemistry-kit-desc = A starter kit for the aspiring chemist, includes toxin and vestine for all your criminal needs! +uplink-knives-kit-name = Throwing Knives Kit +uplink-knives-kit-desc = A set of 4 syndicate branded throwing knives, perfect for embedding into the body of your victims. + uplink-meds-bundle-name = Medical Bundle uplink-meds-bundle-desc = All you need to get your comrades back in the fight: mainly a combat medkit, a defibrillator and three combat medipens. diff --git a/Resources/Prototypes/Catalog/Fills/Boxes/syndicate.yml b/Resources/Prototypes/Catalog/Fills/Boxes/syndicate.yml index 53c526f0339..7b5b05a49a5 100644 --- a/Resources/Prototypes/Catalog/Fills/Boxes/syndicate.yml +++ b/Resources/Prototypes/Catalog/Fills/Boxes/syndicate.yml @@ -38,14 +38,31 @@ name: observations kit suffix: Filled components: - - type: StorageFill - contents: - - id: SyndiCrewMonitorEmpty - amount: 1 - - id: PowerCellHigh - amount: 1 - - id: ClothingEyesGlassesHiddenSecurity - amount: 1 - - id: SurveillanceCameraMonitorCircuitboard - amount: 1 + - type: StorageFill + contents: + - id: SyndiCrewMonitorEmpty + amount: 1 + - id: PowerCellHigh + amount: 1 + - id: ClothingEyesGlassesHiddenSecurity + amount: 1 + - id: SurveillanceCameraMonitorCircuitboard + amount: 1 +- type: entity + parent: BoxCardboard + id: ThrowingKnivesKit + name: throwing knives kit + description: A set of 4 syndicate branded throwing knives, perfect for embedding into the body of your victims. + components: + - type: Storage + grid: + - 0,0,3,1 + - type: StorageFill + contents: + - id: ThrowingKnife + amount: 4 + - type: Sprite + layers: + - state: box_of_doom + - state: throwing_knives diff --git a/Resources/Prototypes/Catalog/uplink_catalog.yml b/Resources/Prototypes/Catalog/uplink_catalog.yml index 1e81cdf2dd1..328ace7ba15 100644 --- a/Resources/Prototypes/Catalog/uplink_catalog.yml +++ b/Resources/Prototypes/Catalog/uplink_catalog.yml @@ -65,6 +65,17 @@ categories: - UplinkWeapons +- type: listing + id: UplinkThrowingKnivesKit + name: uplink-knives-kit-name + description: uplink-knives-kit-desc + icon: { sprite: /Textures/Objects/Storage/boxicons.rsi, state: throwing_knives } + productEntity: ThrowingKnivesKit + cost: + Telecrystal: 6 + categories: + - UplinkWeapons + - type: listing id: UplinkGlovesNorthStar name: uplink-gloves-north-star-name diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/knife.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/knife.yml index b5d597715aa..03654061ced 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/knife.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/knife.yml @@ -252,3 +252,32 @@ sprite: Objects/Weapons/Melee/uranium_shiv.rsi - type: Sprite sprite: Objects/Weapons/Melee/uranium_shiv.rsi + +- type: entity + name: throwing knife + parent: BaseKnife + id: ThrowingKnife + description: This bloodred knife is very aerodynamic and easy to throw, but good luck trying to fight someone hand-to-hand. + components: + - type: Tag + tags: + - CombatKnife + - Knife + - type: Sprite + sprite: Objects/Weapons/Melee/throwing_knife.rsi + state: icon + - type: MeleeWeapon + wideAnimationRotation: -135 + attackRate: 2 + damage: + types: + Slash: 5 + - type: EmbeddableProjectile + sound: /Audio/Weapons/star_hit.ogg + - type: DamageOtherOnHit + damage: + types: + Slash: 10 + Piercing: 15 + - type: Item + sprite: Objects/Weapons/Melee/throwing_knife.rsi diff --git a/Resources/Textures/Objects/Storage/boxes.rsi/meta.json b/Resources/Textures/Objects/Storage/boxes.rsi/meta.json index 23868a906f4..53ac39b639b 100644 --- a/Resources/Textures/Objects/Storage/boxes.rsi/meta.json +++ b/Resources/Textures/Objects/Storage/boxes.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/cc65477c04f7403ca8a457bd5bae69a01abadbf0, encryptokey was taken from Baystation12 at https://github.com/infinitystation/Baystation12/blob/073f678cdce92edb8fcd55f9ffc9f0523bf31506/icons/obj/radio.dmi and modified by lapatison. boxwidetoy, shelltoy, swab, flare, inflatable, trashbag, magazine, holo and forensic created by potato1234x (github) for ss14 based on toys.rsi, mouth_swab.rsi, flare.rsi, inflatable_wall.rsi, trashbag.rsi, caseless_pistol_mag.rsi, guardians.rsi and bureaucracy.rsi respectively, candle and darts created by TheShuEd for ss14, vials was drawn by Ubaser, evidence_markers by moomoobeef.", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/cc65477c04f7403ca8a457bd5bae69a01abadbf0, encryptokey was taken from Baystation12 at https://github.com/infinitystation/Baystation12/blob/073f678cdce92edb8fcd55f9ffc9f0523bf31506/icons/obj/radio.dmi and modified by lapatison. boxwidetoy, shelltoy, swab, flare, inflatable, trashbag, magazine, holo and forensic created by potato1234x (github) for ss14 based on toys.rsi, mouth_swab.rsi, flare.rsi, inflatable_wall.rsi, trashbag.rsi, caseless_pistol_mag.rsi, guardians.rsi and bureaucracy.rsi respectively, candle and darts created by TheShuEd for ss14, throwing_knives and vials was drawn by Ubaser, evidence_markers by moomoobeef.", "size": { "x": 32, "y": 32 @@ -35,7 +35,7 @@ "name": "sechud" }, { - "name": "bottle" + "name": "bottle" }, { "name": "box" @@ -142,6 +142,9 @@ { "name": "syringe" }, + { + "name": "throwing_knives" + }, { "name": "trashbag" }, @@ -152,12 +155,12 @@ "name": "writing_of_doom" }, { - "name": "headset" - }, + "name": "headset" + }, { - "name": "encryptokey" - }, - { + "name": "encryptokey" + }, + { "name": "inhand-left", "directions": 4 }, diff --git a/Resources/Textures/Objects/Storage/boxes.rsi/throwing_knives.png b/Resources/Textures/Objects/Storage/boxes.rsi/throwing_knives.png new file mode 100644 index 0000000000000000000000000000000000000000..834410a43ef64bd0f3dbfd9d852247d464cbd5f0 GIT binary patch literal 1141 zcmZ`&O=#0#7*2JTtvC;YZit60f{2)WZB~X2X<#$^3EEL=g=`16Hc7XzG+#)*+BgSJ z4^u%!9HT)<=$0%*`di&DU%@%;&UsW-gtBTI$qnX zp%I554$ONq(!q5-B8aU>&&x>89OD#NW(q1SYK&X9d=&3;_*m9Zfpp7;>2PkE@-;Yo z_QZf9eHAp7rsPbPJOXWv>|x?eoDyOrN%FQ@;&S3Z2*h~Qs5XK)Ri);~s@R6_ zMOA=iXl2br4oENw&8P z^E>(cRx~-Ey}kOY>*2{yt7|vq_uqb=K@7Mycl6Mok8_dE*+}P;Zi~1#+Hs@h!h`!> N%S-*k;zHl}`F|_-V#WXf literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Storage/boxicons.rsi/meta.json b/Resources/Textures/Objects/Storage/boxicons.rsi/meta.json index 858fc7c4e54..935b0b9f8b3 100644 --- a/Resources/Textures/Objects/Storage/boxicons.rsi/meta.json +++ b/Resources/Textures/Objects/Storage/boxicons.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Taken from baystation at https://github.com/Baystation12/Baystation12/commit/bc9fbb1722530596e3aa7522ee407280b323ad43, vials drawn by Ubaser, tracks made by Fazansen(https://github.com/Fazansen).", + "copyright": "Taken from baystation at https://github.com/Baystation12/Baystation12/commit/bc9fbb1722530596e3aa7522ee407280b323ad43, throwing_knives and vials are drawn by Ubaser, tracks made by Fazansen(https://github.com/Fazansen).", "size": { "x": 32, "y": 32 @@ -76,6 +76,9 @@ { "name": "syringe" }, + { + "name": "throwing_knives" + }, { "name": "ziptie" }, diff --git a/Resources/Textures/Objects/Storage/boxicons.rsi/throwing_knives.png b/Resources/Textures/Objects/Storage/boxicons.rsi/throwing_knives.png new file mode 100644 index 0000000000000000000000000000000000000000..b2af7bce88436ed9b060cec8bd6f97019537caa9 GIT binary patch literal 1392 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}e5nzhX}-P; zT0k}j5QD&_;K@Lev%n*=n1MlK76>znTPbd0U|=rE42dX-@b$4u&d=3LOvz75)vL%Y z0PC`;umUo3Q%e#RDspr3imfVamB1>jfNYSkzLEl1NlCV?QiN}Sf^&XRs)CuGfu4bq z9hZWFf=y9MnpKdC8&o@xXRDM^Qc_^0uU}qXu2*iXmtT~wZ)j<0sc&GUZ)BtkRH0j3 znOBlnp_^B%3^4>|j!SBBa#3bMNoIbY0?6FNr2NtnTO}osMQ{LdXG${Mo`TY%9I!1Z z$@-}|sky0nCB^!NdWQPg^p#|$AzYYO3=Ixo!03ZyfZ7bOYV#~8Nj3q7lxqdhJy8Dv z9hwZbx40xlA4!3}k%57Qu7Q!Rk)=M|e?aHkq$FFFWR~Qlf&&ijA8-gd=9Hj{g4Bb8 zASV+PvQ{~XdFi%F6}l;@X^EvdB}#Tl`4#c`Y4Iuf`MEaw5QV4)Ktxf^wb94o1RIdY zts;X`i}Q0zK|yb4WM*Om4h|GiL?l3TL}1l{EQ+opAS1sdADF0$GLt>?N>Ymoihv0W zVk6W(+$zw`LRcP}msw(G1T_Fn7)cjW1X(#2m6YcfWru(x10^JJs)CvX300(Y3dscE z7y#x1J1!f2c#g8;T5vFZ7clEqd%8G=L~y$v&<~>y})k!b$Ij_*Boec?7c@H{qFghl3r*G!+?2O}8vz5m}+81h%=^c1PKS83O{n;1@QN}0Z7^Xpv`mc7*YUNB{2a+8@u z6VE;{x%R3Bx1%7%JU02a%^lN%F zE%jh-`3kPxCsNfyV%|*TT~Hz7n*90eUlmUe899+_S!k}&6*}S*Quc$Du?mypn?RQoOuZK{=k6;xQ!K#XyN7Ju|PyZWn zMDN`Biup!2tQbXXfBj=p>r*o7QRYk6np)zppMvt=Rf6n1)cS_o?!bBEpWVW zzxWC@_m8>zq*a)GFBhEM{dHDh?X&sHg;q@=(~U%$M(T(8_%FTW^V-_X+1Qs2Nx-^fT8s6w~6 zGOr}DLN~8i8Da>`9GBGM~RsBTId_|A5Z7NlCUU$t=l91qU45Kj08_%qc+?1*r!G zK~5$pWUX=%^U`gVDs)p)(-KQ_N|fv}^D+|iQgn+l(=$qJ^dTxyO@N4^8f>GF#SJzf zpIb!+r55Msl!C(E&dAKf1{@wJqKH_4=!n3o16dSZM?gk?Nj@-D6=f!S=9Q!t6%+we z7{o@XeYjPin}x7EG%vHn&IoD%nlO?sq!_YtEGj9_FUk%9#|COp;#3AT3KFbHDHW0p zz)=9q2XMaQ|Ei{ z!xO@M-(SD!`>3)=h^2Je2J^D5F{d?VMa9-GwO_78j!x3y?Z zAj4G~+4hAyrlqc*dNa%HszigAoqha~oP8H+mOXafayE9a!9u>WGK-y+(MulJo4!

{Sco1*{# literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Weapons/Melee/throwing_knife.rsi/icon.png b/Resources/Textures/Objects/Weapons/Melee/throwing_knife.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..2c61755b52c35b9138c5aa7f93ec6e71bffa7871 GIT binary patch literal 1593 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}e5nzhX}-P; zT0k}j5QD&_;K@Lev%n*=7^vU~2s2LA=96Y%V9v=5i71Ki^|4CM&(%vz$xlkvtH>$0h^0y1+`OA-|-a&z*EttxDlz$&bOY>=?Nk^)#sNw%$0gl~X?bAC~(f|;Iyo`I4b zmx6+VO;JjkRgjAtR6CGotCUevQedU8UtV6WS8lAAUzDzIXlZGwZ(yWvWTXpJp<7&; zSCUwvn^&w1F$89gOKNd)QD#9&W`3Rm$lS!F{L&IzB_)tWZ~$>9$H0x+$q?iKRIuN_L*U?(xRP#^yHq5LKwUA)=^;+UR4k-v;DstH_|# z;{2RaP`KM!n%RJZ0!0uJ0T2xl*fbyuqH74q$S=tUrl+FJWY4^k)S`kSVA=xPX9Tql zw+eK#5O#;=WtP~%3_ue`(uEW^R*pp_<@rU~A>epG1R_o)P-7qgij+Pfi60#Jz|?QY zWup(zNp@V%mxb~$FfjRex;TbJaJ~)o_78Rx`Ind7Qc!9C=1{nZp6(V`<|%VS?rwO| zv`YFX^9e4~PsSA-Axxj#MNAkEdHI&OX76G=)GMZ}=rs8q-}j!mL07V^3U2f6J^AI# zoq03g8>T;Fdis2i^@6E~7#7=l^gJ%xJ+Y%+lXKaHqX+i&-QKcutMlpi*H_-Xt=jRV zd*1~6f=%ZSTsAiTP#JCb>kaF>`@6Xp?f)>h#U}3b>)o#T)52Oly*PYaWOlU5PTu2@ z`>WU4$ImIf^YZ<&n>TcNwn&$7C%_^!e&PWtFDOYqF~P)RrY}dv#vx z+mV|31?|)Bt-W|{n`iU1w>;<0W?wzjc_fLaDOPdysp~DDCN*y^+BSEpyF4%F)yewt zqVAQxxweIq_1K#BTHaROvFh!q{eFz zK3OI`antZn#mM^|`vUTx9X{?q)pV<`M@~&xT=!J%TJAry)DFy+mU5`JKlnhdpM7PB z*G*T;g$Ycu3|n7Vm0iv>{N65lwq#bQ@Z<*>?{c(v2M9F!WqQbu$Pe0yk&>D6*Hq-gd*mBP7>5; hNwHl1#vxGFf@x_avz=0K&TUY!?dj_0vd$@?2>>-FL7@Nu literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Weapons/Melee/throwing_knife.rsi/inhand-left.png b/Resources/Textures/Objects/Weapons/Melee/throwing_knife.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..5988d571dc12ca1c485efc87735bbba3ce635640 GIT binary patch literal 1296 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|_);T0(|mmy zw18|5AO?X;!IOa`XMsm#F$06fED&ZCw^H21z`$IV84^(v;p=0SoS&h?X&sHg;q@=(~U%$M(T(8_%FTW^V-_X+1Qs2Nx-^fT8s6w~6 zGOr}DLN~8i8Da>`9GBGM~RsBTId_|A5Z7NlCUU$t=l91qU45Kj08_%qc+?1*r!G zK~5$pWUX=%^U`gVDs)p)(-KQ_N|fv}^D+|iQgn+l(=$qJ^dTxyO@N4^8f>GF#SJzf zpIb!+r55Msl!C(E&dAKf1{@wJqKH_4=!n3o16dSZM?gk?Nj@-D6=f!S=9Q!t6%+we z7{o@XeYjPin}x7EG%vHn&IoD%nlO?sq!_YtEGj9_FUk%9#|COp;#3AT3KFbHDHW0p zz)=9q2X*mm#I&6k+g^W`6|5prbv@a}`Hz?!tn&ug}I zy!5S_wCuBHzq<U{MO(OH#J#lhTTXtx$E#ub`D;1*mDf3?|1NQ# p_;-Kx%DB?a9Dh3C-ua-+#BaJLkNt{4Ehnfn@^tlcS?83{1OP7tpo#zh literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Weapons/Melee/throwing_knife.rsi/inhand-right.png b/Resources/Textures/Objects/Weapons/Melee/throwing_knife.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..09c015efac56e7935ff49a7488bea47ee21f706a GIT binary patch literal 1298 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|_);T0(|mmy zw18|5AO?X;!IOa`XMsm#F$06fED&ZCw^H21z`$IV84^(v;p=0SoS&h?X&sHg;q@=(~U%$M(T(8_%FTW^V-_X+1Qs2Nx-^fT8s6w~6 zGOr}DLN~8i8Da>`9GBGM~RsBTId_|A5Z7NlCUU$t=l91qU45Kj08_%qc+?1*r!G zK~5$pWUX=%^U`gVDs)p)(-KQ_N|fv}^D+|iQgn+l(=$qJ^dTxyO@N4^8f>GF#SJzf zpIb!+r55Msl!C(E&dAKf1{@wJqKH_4=!n3o16dSZM?gk?Nj@-D6=f!S=9Q!t6%+we z7{o@XeYjPin}x7EG%vHn&IoD%nlO?sq!_YtEGj9_FUk%9#|COp;#3AT3KFbHDHW0p zz)=9q2X1D--Z+E{R|F`Dg_uaXhW6tcgx!1%pi>paAZW9~hvW5@d6(?_2pParSE_c-* z{|Wn+{=e67Ep6>X)9_3GCW~F>Grp7k(%8AgO9|B?RC`-lOEe^_b5>b}$HEbI&63Re#m1*}He%`O5qM s!?yrm-qO5?#!wak2L?tE(OAW5$7GzxZoH}C0;oLlboFyt=akR{01HQ^j{pDw literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Weapons/Melee/throwing_knife.rsi/meta.json b/Resources/Textures/Objects/Weapons/Melee/throwing_knife.rsi/meta.json new file mode 100644 index 00000000000..373d2d77701 --- /dev/null +++ b/Resources/Textures/Objects/Weapons/Melee/throwing_knife.rsi/meta.json @@ -0,0 +1,26 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Drawn by Ubaser.", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + }, + { + "name": "equipped-BELT", + "directions": 4 + } + ] +} From 6f54ed1b28908264a848c801ae6b86ed27a21734 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 29 Jun 2024 18:26:26 -0700 Subject: [PATCH 02/15] Update Credits (#495) This is an automated Pull Request. This PR updates the GitHub contributors in the credits section. Co-authored-by: SimpleStation Changelogs --- Resources/Credits/GitHub.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Credits/GitHub.txt b/Resources/Credits/GitHub.txt index b5381a4ce29..84796a94662 100644 --- a/Resources/Credits/GitHub.txt +++ b/Resources/Credits/GitHub.txt @@ -1 +1 @@ -0x6273, 2013HORSEMEATSCANDAL, 20kdc, 21Melkuu, 4dplanner, 612git, 778b, Ablankmann, Acruid, actioninja, adamsong, Admiral-Obvious-001, Adrian16199, Aerocrux, Aexxie, africalimedrop, Agoichi, Ahion, AJCM-git, AjexRose, Alekshhh, AlexMorgan3817, AlmondFlour, AlphaQwerty, Altoids1, amylizzle, ancientpower, ArchPigeon, Arendian, arimah, Arteben, AruMoon, as334, AsikKEsel, asperger-sind, aspiringLich, avghdev, AzzyIsNotHere, BananaFlambe, BasedUser, BGare, BingoJohnson-zz, BismarckShuffle, Bixkitts, Blackern5000, Blazeror, Boaz1111, BobdaBiscuit, brainfood1183, Brandon-Huu, Bribrooo, Bright0, brndd, BubblegumBlue, BYONDFuckery, c4llv07e, CaasGit, CakeQ, CaptainSqrBeard, Carbonhell, Carolyn3114, casperr04, CatTheSystem, Centronias, chairbender, Charlese2, Cheackraze, cheesePizza2, Chief-Engineer, chromiumboy, Chronophylos, clement-or, Clyybber, ColdAutumnRain, Colin-Tel, collinlunn, ComicIronic, coolmankid12345, corentt, crazybrain23, creadth, CrigCrag, Crotalus, CrudeWax, CrzyPotato, Cyberboss, d34d10cc, Daemon, daerSeebaer, dahnte, dakamakat, dakimasu, DamianX, DangerRevolution, daniel-cr, Darkenson, DawBla, dch-GH, Deahaka, DEATHB4DEFEAT, DeathCamel58, deathride58, DebugOk, Decappi, deepdarkdepths, Delete69, deltanedas, DeltaV-Bot, DerbyX, DoctorBeard, DogZeroX, dontbetank, Doru991, DoubleRiceEddiedd, DrMelon, DrSmugleaf, drteaspoon420, DTanxxx, DubiousDoggo, Duddino, Dutch-VanDerLinde, Easypoller, eclips_e, EdenTheLiznerd, EEASAS, Efruit, ElectroSR, elthundercloud, Emisse, EmoGarbage404, Endecc, enumerate0, eoineoineoin, ERORR404V1, Errant-4, estacaoespacialpirata, exincore, exp111, Fahasor, FairlySadPanda, ficcialfaint, Fildrance, FillerVK, Fishfish458, Flareguy, FluffiestFloof, FluidRock, FoLoKe, fooberticus, Fortune117, FoxxoTrystan, freeman2651, Fromoriss, FungiFellow, GalacticChimp, gbasood, Geekyhobo, Genkail, Git-Nivrak, github-actions[bot], gituhabu, GNF54, Golinth, GoodWheatley, Gotimanga, graevy, GreyMario, Guess-My-Name, gusxyz, h3half, Hanzdegloker, Hardly3D, harikattar, Hebiman, Henry12116, HerCoyote23, Hmeister-real, HoofedEar, hord-brayden, hubismal, Hugal31, Hyenh, iacore, IamVelcroboy, icekot8, igorsaux, ike709, Illiux, Ilya246, IlyaElDunaev, Injazz, Insineer, IntegerTempest, Interrobang01, IProduceWidgets, ItsMeThom, j-giebel, Jackal298, Jackrost, jamessimo, janekvap, JerryImMouse, Jessetriesagain, jessicamaybe, Jezithyr, jicksaw, JiimBob, JoeHammad1844, joelhed, JohnGinnane, johnku1, joshepvodka, jproads, Jrpl, juliangiebel, JustArt1m, JustCone14, JustinTether, JustinTrotter, KaiShibaa, kalane15, kalanosh, KEEYNy, Keikiru, Kelrak, kerisargit, keronshb, KIBORG04, Killerqu00, KingFroozy, kira-er, Kit0vras, KittenColony, Kmc2000, Ko4ergaPunk, komunre, koteq, Krunklehorn, Kukutis96513, kxvvv, Lamrr, LankLTE, lapatison, Leander-0, leonardo-dabepis, LetterN, Level10Cybermancer, lever1209, LightVillet, liltenhead, LittleBuilderJane, Lomcastar, LordCarve, LordEclipse, LovelyLophi, LudwigVonChesterfield, Lukasz825700516, lunarcomets, luringens, lvvova1, lzimann, lzk228, M3739, MACMAN2003, Macoron, MagnusCrowe, ManelNavola, matthst, Matz05, MehimoNemo, MeltedPixel, MemeProof, Menshin, Mervill, metalgearsloth, mhamsterr, MilenVolf, Minty642, Mirino97, mirrorcult, misandrie, MishaUnity, MisterMecky, Mith-randalf, Moneyl, Moomoobeef, moony, Morb0, Mr0maks, musicmanvr, Myakot, Myctai, N3X15, Nairodian, Naive817, namespace-Memory, NickPowers43, nikthechampiongr, Nimfar11, Nirnael, nmajask, nok-ko, Nopey, notafet, notquitehadouken, noudoit, noverd, nuke-haus, NULL882, OCOtheOmega, OctoRocket, OldDanceJacket, onoira, Owai-Seek, pali6, Pangogie, patrikturi, PaulRitter, Peptide90, peptron1, Phantom-Lily, PHCodes, PixelTheKermit, PJB3005, Plykiya, pofitlo, pointer-to-null, PolterTzi, PoorMansDreams, potato1234x, ProfanedBane, PrPleGoo, ps3moira, Psychpsyo, psykzz, PuroSlavKing, quatre, QuietlyWhisper, qwerltaz, Radosvik, Radrark, Rainbeon, Rainfey, Rane, ravage123321, rbertoche, Redict, RedlineTriad, RednoWCirabrab, RemberBM, RemieRichards, RemTim, rene-descartes2021, RiceMar1244, RieBi, Rinkashikachi, Rockdtben, rolfero, rosieposieeee, Saakra, Samsterious, SaphireLattice, ScalyChimp, scrato, Scribbles0, Serkket, SethLafuente, ShadowCommander, Shadowtheprotogen546, SignalWalker, SimpleStation14, Simyon264, SirDragooon, Sirionaut, siyengar04, Skarletto, Skrauz, Skyedra, SlamBamActionman, slarticodefast, Slava0135, Snowni, snowsignal, SonicHDC, SoulSloth, SpaceManiac, SpeltIncorrectyl, spoogemonster, ssdaniel24, Stealthbomber16, stellar-novas, StrawberryMoses, SweptWasTaken, Szunti, TadJohnson00, takemysoult, TaralGit, Tayrtahn, tday93, TekuNut, TemporalOroboros, tentekal, tgrkzus, thatrandomcanadianguy, TheArturZh, theashtronaut, thedraccx, themias, Theomund, theOperand, TheShuEd, TimrodDX, Titian3, tkdrg, tmtmtl30, tom-leys, tomasalves8, Tomeno, Tornado-Technology, tosatur, Tryded, TsjipTsjip, Tunguso4ka, TurboTrackerss14, Tyler-IN, Tyzemol, UbaserB, UKNOWH, UnicornOnLSD, Uriende, UristMcDorf, Vaaankas, Varen, VasilisThePikachu, veliebm, Veritius, Verslebas, VigersRay, Visne, VMSolidus, volundr-, Voomra, Vordenburg, vulppine, waylon531, weaversam8, Willhelm53, wixoaGit, WlarusFromDaSpace, wrexbe, xRiriq, yathxyz, Ygg01, YotaXP, YuriyKiss, zach-hill, Zandario, Zap527, ZelteHonor, zerorulez, zionnBE, zlodo, ZNixian, ZoldorfTheWizard, Zumorica, Zymem +0x6273, 2013HORSEMEATSCANDAL, 20kdc, 21Melkuu, 4dplanner, 612git, 778b, Ablankmann, Acruid, actioninja, adamsong, Admiral-Obvious-001, Adrian16199, Aerocrux, Aexxie, africalimedrop, Agoichi, Ahion, AJCM-git, AjexRose, Alekshhh, AlexMorgan3817, AlmondFlour, AlphaQwerty, Altoids1, amylizzle, ancientpower, ArchPigeon, Arendian, arimah, Arteben, AruMoon, as334, AsikKEsel, asperger-sind, aspiringLich, avghdev, AzzyIsNotHere, BananaFlambe, BasedUser, BGare, BingoJohnson-zz, BismarckShuffle, Bixkitts, Blackern5000, Blazeror, Boaz1111, BobdaBiscuit, brainfood1183, Brandon-Huu, Bribrooo, Bright0, brndd, BubblegumBlue, BYONDFuckery, c4llv07e, CaasGit, CakeQ, CaptainSqrBeard, Carbonhell, Carolyn3114, casperr04, CatTheSystem, Centronias, chairbender, Charlese2, Cheackraze, cheesePizza2, Chief-Engineer, chromiumboy, Chronophylos, clement-or, Clyybber, ColdAutumnRain, Colin-Tel, collinlunn, ComicIronic, coolmankid12345, corentt, crazybrain23, creadth, CrigCrag, Crotalus, CrudeWax, CrzyPotato, Cyberboss, d34d10cc, Daemon, daerSeebaer, dahnte, dakamakat, dakimasu, DamianX, DangerRevolution, daniel-cr, Darkenson, DawBla, dch-GH, Deahaka, DEATHB4DEFEAT, DeathCamel58, deathride58, DebugOk, Decappi, deepdarkdepths, Delete69, deltanedas, DeltaV-Bot, DerbyX, DoctorBeard, DogZeroX, dontbetank, Doru991, DoubleRiceEddiedd, DrMelon, DrSmugleaf, drteaspoon420, DTanxxx, DubiousDoggo, Duddino, Dutch-VanDerLinde, Easypoller, eclips_e, EdenTheLiznerd, EEASAS, Efruit, ElectroSR, elthundercloud, Emisse, EmoGarbage404, Endecc, enumerate0, eoineoineoin, ERORR404V1, Errant-4, estacaoespacialpirata, exincore, exp111, Fahasor, FairlySadPanda, ficcialfaint, Fildrance, FillerVK, Fishfish458, Flareguy, FluffiestFloof, FluidRock, FoLoKe, fooberticus, Fortune117, FoxxoTrystan, freeman2651, Fromoriss, FungiFellow, GalacticChimp, gbasood, Geekyhobo, Genkail, geraeumig, Git-Nivrak, github-actions[bot], gituhabu, GNF54, Golinth, GoodWheatley, Gotimanga, graevy, GreyMario, Guess-My-Name, gusxyz, h3half, Hanzdegloker, Hardly3D, harikattar, Hebiman, Henry12116, HerCoyote23, Hmeister-real, HoofedEar, hord-brayden, hubismal, Hugal31, Hyenh, iacore, IamVelcroboy, icekot8, igorsaux, ike709, Illiux, Ilya246, IlyaElDunaev, Injazz, Insineer, IntegerTempest, Interrobang01, IProduceWidgets, ItsMeThom, j-giebel, Jackal298, Jackrost, jamessimo, janekvap, JerryImMouse, Jessetriesagain, jessicamaybe, Jezithyr, jicksaw, JiimBob, JoeHammad1844, joelhed, JohnGinnane, johnku1, joshepvodka, jproads, Jrpl, juliangiebel, JustArt1m, JustCone14, JustinTether, JustinTrotter, KaiShibaa, kalane15, kalanosh, KEEYNy, Keikiru, Kelrak, kerisargit, keronshb, KIBORG04, Killerqu00, KingFroozy, kira-er, Kit0vras, KittenColony, Kmc2000, Ko4ergaPunk, komunre, koteq, Krunklehorn, Kukutis96513, kxvvv, Lamrr, LankLTE, lapatison, Leander-0, leonardo-dabepis, LetterN, Level10Cybermancer, lever1209, LightVillet, liltenhead, LittleBuilderJane, Lomcastar, LordCarve, LordEclipse, LovelyLophi, LudwigVonChesterfield, Lukasz825700516, lunarcomets, luringens, lvvova1, lzimann, lzk228, M3739, MACMAN2003, Macoron, MagnusCrowe, ManelNavola, matthst, Matz05, MehimoNemo, MeltedPixel, MemeProof, Menshin, Mervill, metalgearsloth, mhamsterr, MilenVolf, Minty642, Mirino97, mirrorcult, misandrie, MishaUnity, MisterMecky, Mith-randalf, Moneyl, Moomoobeef, moony, Morb0, Mr0maks, musicmanvr, Myakot, Myctai, N3X15, Nairodian, Naive817, namespace-Memory, NickPowers43, nikthechampiongr, Nimfar11, Nirnael, nmajask, nok-ko, Nopey, notafet, notquitehadouken, noudoit, noverd, nuke-haus, NULL882, OCOtheOmega, OctoRocket, OldDanceJacket, onoira, Owai-Seek, pali6, Pangogie, patrikturi, PaulRitter, Peptide90, peptron1, Phantom-Lily, PHCodes, PixelTheKermit, PJB3005, Plykiya, pofitlo, pointer-to-null, PolterTzi, PoorMansDreams, potato1234x, ProfanedBane, PrPleGoo, ps3moira, Psychpsyo, psykzz, PuroSlavKing, quatre, QuietlyWhisper, qwerltaz, Radosvik, Radrark, Rainbeon, Rainfey, Rane, ravage123321, rbertoche, Redict, RedlineTriad, RednoWCirabrab, RemberBM, RemieRichards, RemTim, rene-descartes2021, RiceMar1244, RieBi, Rinkashikachi, Rockdtben, rolfero, rosieposieeee, Saakra, Samsterious, SaphireLattice, ScalyChimp, scrato, Scribbles0, Serkket, SethLafuente, ShadowCommander, Shadowtheprotogen546, SignalWalker, SimpleStation14, Simyon264, SirDragooon, Sirionaut, siyengar04, Skarletto, Skrauz, Skyedra, SlamBamActionman, slarticodefast, Slava0135, Snowni, snowsignal, SonicHDC, SoulSloth, SpaceManiac, SpeltIncorrectyl, spoogemonster, ssdaniel24, Stealthbomber16, stellar-novas, StrawberryMoses, SweptWasTaken, Szunti, TadJohnson00, takemysoult, TaralGit, Tayrtahn, tday93, TekuNut, TemporalOroboros, tentekal, tgrkzus, thatrandomcanadianguy, TheArturZh, theashtronaut, thedraccx, themias, Theomund, theOperand, TheShuEd, TimrodDX, Titian3, tkdrg, tmtmtl30, tom-leys, tomasalves8, Tomeno, Tornado-Technology, tosatur, Tryded, TsjipTsjip, Tunguso4ka, TurboTrackerss14, Tyler-IN, Tyzemol, UbaserB, UKNOWH, UnicornOnLSD, Uriende, UristMcDorf, Vaaankas, Varen, VasilisThePikachu, veliebm, Veritius, Verslebas, VigersRay, Visne, VMSolidus, volundr-, Voomra, Vordenburg, vulppine, waylon531, weaversam8, Willhelm53, wixoaGit, WlarusFromDaSpace, wrexbe, xRiriq, yathxyz, Ygg01, YotaXP, YuriyKiss, zach-hill, Zandario, Zap527, ZelteHonor, zerorulez, zionnBE, zlodo, ZNixian, ZoldorfTheWizard, Zumorica, Zymem From f439eb70b897cd2f1424b1eed778b8a804c8c948 Mon Sep 17 00:00:00 2001 From: Mnemotechnican <69920617+Mnemotechnician@users.noreply.github.com> Date: Sun, 30 Jun 2024 21:22:28 +0300 Subject: [PATCH 03/15] Add Equip Delays to Clothing (#499) # Description For centuries SS14 had equip and unequip delays on the clothing component, and yet that feature remained unused and unheard of, not even nyanotrasen/deltav used it when designing shock collars and headcages, whose descriptions clearly suggested they should take time to take off. For centuries salvage specialists could safely swap suits in space. For centuries you could accidentally unequip your eva suit mid-spacewalk and die. Now the time has come. The time when we change it. This adds equip and unequip delays to the base clothing item. The currently chosen time is half a second - it's meant to not be too annoying, but at the same time prevent people from being able to instantly swap clothes, headsets, other things with a single click. EVA suits take 1.5 seconds to equip and 1 second to take off, so to swap EVA suits, you will have to expose your body to the dangers of space for at least 1.5 seconds. For hardsuits, both values are increased to 2.5 seconds. The values are not final and this PR will probably need polishing before it can be merged - for example, while recording the second preview video, I discovered that jetpacks do not inherit from base clothing and thus do not inherit the delays. There's probably way more such items. --- # TODO Add equip/unequip delays to: - [X] most basic clothing items - [X] hardsuits/softsuits - [X] special items (currently headcages and shock collars, possibly more later?) - [ ] Everything that was missed by the above ---

Media

Basics https://github.com/Simple-Station/Einstein-Engines/assets/69920617/3fc900b8-ee13-4968-bf5d-cddeb9a141b6 Hardsuits, eva suits, shock collars, headcages + demonstration that aghost stripping is unaffected. https://github.com/Simple-Station/Einstein-Engines/assets/69920617/a536578f-2ac3-40e1-9b27-3b167e006397

--- # Changelog :cl: - add: Most items now take time to equip and unequip, especially space suits. --- .../Entities/Clothing/OuterClothing/base_clothingouter.yml | 6 ++++++ Resources/Prototypes/Entities/Clothing/base_clothing.yml | 3 +++ .../Prototypes/Nyanotrasen/Entities/Clothing/Head/hats.yml | 2 ++ .../Nyanotrasen/Entities/Objects/Devices/shock_collar.yml | 2 ++ 4 files changed, 13 insertions(+) diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml index 13524efa9e6..902c57418e4 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/base_clothingouter.yml @@ -93,6 +93,9 @@ - Hardsuit - WhitelistChameleon - HidesHarpyWings #DeltaV: Used by harpies to help render their hardsuit sprites + - type: Clothing + equipDelay: 2.5 # Hardsuits are heavy and take a while to put on/off. + unequipDelay: 2.5 - type: entity abstract: true @@ -114,6 +117,9 @@ - type: Tag tags: - HidesHarpyWings #DeltaV: Used by harpies to help render their hardsuit sprites + - type: Clothing + equipDelay: 1.25 # Softsuits are easier to put on and off + unequipDelay: 1 - type: entity parent: ClothingOuterBase diff --git a/Resources/Prototypes/Entities/Clothing/base_clothing.yml b/Resources/Prototypes/Entities/Clothing/base_clothing.yml index 92a698dd301..810ada5429d 100644 --- a/Resources/Prototypes/Entities/Clothing/base_clothing.yml +++ b/Resources/Prototypes/Entities/Clothing/base_clothing.yml @@ -11,6 +11,9 @@ - WhitelistChameleon - type: StaticPrice price: 15 + - type: Clothing + equipDelay: 0.5 + unequipDelay: 0.5 - type: entity abstract: true diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Head/hats.yml b/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Head/hats.yml index 8278114d267..2cd9785d989 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Head/hats.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Head/hats.yml @@ -99,6 +99,8 @@ sprite: Nyanotrasen/Clothing/Head/Hats/cage.rsi - type: Clothing sprite: Nyanotrasen/Clothing/Head/Hats/cage.rsi + equipDelay: 0.5 + unequipDelay: 6 - type: HeadCage - type: entity diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/shock_collar.yml b/Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/shock_collar.yml index 35cdcae6589..1266a721fe2 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/shock_collar.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/shock_collar.yml @@ -8,6 +8,8 @@ sprite: Nyanotrasen/Clothing/Neck/Misc/shock.rsi - type: Clothing sprite: Nyanotrasen/Clothing/Neck/Misc/shock.rsi + equipDelay: 1 + unequipDelay: 10 # It's a collar meant to be used on prisoners (or not), so it probably has some sort of safety. - type: ShockCollar - type: UseDelay delay: 3 # DeltaV: prevent clocks instakilling people From 7c83c8b30c016b4f457d8d7398c282d9cba5a0da Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Sun, 30 Jun 2024 18:22:48 +0000 Subject: [PATCH 04/15] Automatic Changelog Update (#499) --- Resources/Changelog/Changelog.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 3aea1324fe4..6fe7b0ff689 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -4251,3 +4251,9 @@ Entries: message: 'Height and Width sliders have been added to character creation. ' id: 6131 time: '2024-06-27T17:46:51.0000000+00:00' +- author: Mnemotechnician + changes: + - type: Add + message: Most items now take time to equip and unequip, especially space suits. + id: 6132 + time: '2024-06-30T18:22:28.0000000+00:00' From 89a6bb3ab5897da04c0526c32ff408b90bfc70fc Mon Sep 17 00:00:00 2001 From: SimpleStation14 <130339894+SimpleStation14@users.noreply.github.com> Date: Mon, 1 Jul 2024 11:37:45 -0700 Subject: [PATCH 05/15] Mirror: StrippableSystem doafter overhaul (#205) ## Mirror of PR #25994: [StrippableSystem doafter overhaul](https://github.com/space-wizards/space-station-14/pull/25994) from space-wizards [space-wizards](https://github.com/space-wizards)/[space-station-14](https://github.com/space-wizards/space-station-14) ###### `41ca8f3dfcb986432e1e509247bf239cac137836` PR opened by Krunklehorn at 2024-03-11 12:36:28 UTC --- PR changed 7 files with 465 additions and 305 deletions. The PR had the following labels: - Status: Needs Review ---

Original Body

> ## About the PR > > Refactors Strippable DoAfter events to make them synchronous and organized. > > > ## Technical details > > ### Strippable System & Component > - Synchronous DoAfters > - Made use of `TimeSpan`, `GetStripTimeModifiers()` and `ByRefEvent` > - Reorganized checks, removed some redundant ones > - Resolve pattern where useful > - Added more asserts > - Lots of cleanup > > The DoAfters were grouped under one event to avoid copy-pasting eight separate cancel checks, asserts and function signatures. > > Let me know if this is bad for performance and I'll roll them out instead. > > > ## Media > > - [x] I have added screenshots/videos to this PR showcasing its changes ingame, **or** this PR does not require an ingame showcase > > > ## Breaking changes > > ### TimeSpans > `ThievingComponent`, `InventoryTemplatePrototype` and `ToggleableClothingSystem` use `TimeSpan` in places where they intersect with `StrippableComponent`. > > > **Changelog** > > N/A >
Signed-off-by: VMSolidus Co-authored-by: SimpleStation14 Co-authored-by: VMSolidus --- Content.Server/Strip/StrippableSystem.cs | 676 +++++++++++------- .../EntitySystems/ToggleableClothingSystem.cs | 2 +- .../Inventory/InventoryTemplatePrototype.cs | 2 +- .../Strip/Components/StrippableComponent.cs | 81 +-- .../Strip/Components/ThievingComponent.cs | 2 +- .../Strip/SharedStrippableSystem.cs | 6 +- Content.Shared/Strip/ThievingSystem.cs | 1 + 7 files changed, 465 insertions(+), 305 deletions(-) diff --git a/Content.Server/Strip/StrippableSystem.cs b/Content.Server/Strip/StrippableSystem.cs index 96b2ecc00c6..950411a8e2c 100644 --- a/Content.Server/Strip/StrippableSystem.cs +++ b/Content.Server/Strip/StrippableSystem.cs @@ -1,4 +1,3 @@ -using System.Linq; using Content.Server.Administration.Logs; using Content.Server.Ensnaring; using Content.Shared.CombatMode; @@ -21,18 +20,21 @@ using Robust.Server.GameObjects; using Robust.Shared.Player; using Robust.Shared.Utility; +using System.Linq; namespace Content.Server.Strip { public sealed class StrippableSystem : SharedStrippableSystem { - [Dependency] private readonly SharedCuffableSystem _cuffable = default!; - [Dependency] private readonly SharedHandsSystem _handsSystem = default!; [Dependency] private readonly InventorySystem _inventorySystem = default!; - [Dependency] private readonly SharedDoAfterSystem _doAfter = default!; - [Dependency] private readonly SharedPopupSystem _popup = default!; - [Dependency] private readonly EnsnareableSystem _ensnaring = default!; + [Dependency] private readonly EnsnareableSystem _ensnaringSystem = default!; [Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!; + + [Dependency] private readonly SharedCuffableSystem _cuffableSystem = default!; + [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; + [Dependency] private readonly SharedHandsSystem _handsSystem = default!; + [Dependency] private readonly SharedPopupSystem _popupSystem = default!; + [Dependency] private readonly IAdminLogManager _adminLogger = default!; // TODO: ECS popups. Not all of these have ECS equivalents yet. @@ -48,64 +50,58 @@ public override void Initialize() // BUI SubscribeLocalEvent(OnStripButtonPressed); SubscribeLocalEvent(OnStripEnsnareMessage); + + // DoAfters + SubscribeLocalEvent>(OnStrippableDoAfterRunning); + SubscribeLocalEvent(OnStrippableDoAfterFinished); } - private void OnStripEnsnareMessage(EntityUid uid, EnsnareableComponent component, StrippingEnsnareButtonPressed args) + private void AddStripVerb(EntityUid uid, StrippableComponent component, GetVerbsEvent args) { - if (args.Session.AttachedEntity is not {Valid: true} user) + if (args.Hands == null || !args.CanAccess || !args.CanInteract || args.Target == args.User) return; - foreach (var entity in component.Container.ContainedEntities) + if (!HasComp(args.User)) + return; + + Verb verb = new() { - if (!TryComp(entity, out var ensnaring)) - continue; + Text = Loc.GetString("strip-verb-get-data-text"), + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/outfit.svg.192dpi.png")), + Act = () => StartOpeningStripper(args.User, (uid, component), true), + }; - _ensnaring.TryFree(uid, user, entity, ensnaring); - return; - } + args.Verbs.Add(verb); } - private void OnStripButtonPressed(Entity strippable, ref StrippingSlotButtonPressed args) + private void AddStripExamineVerb(EntityUid uid, StrippableComponent component, GetVerbsEvent args) { - if (args.Session.AttachedEntity is not {Valid: true} user || - !TryComp(user, out var userHands)) - return; - - if (args.IsHand) - { - StripHand(user, args.Slot, strippable, userHands); + if (args.Hands == null || !args.CanAccess || !args.CanInteract || args.Target == args.User) return; - } - if (!TryComp(strippable, out var inventory)) + if (!HasComp(args.User)) return; - var hasEnt = _inventorySystem.TryGetSlotEntity(strippable, args.Slot, out var held, inventory); + ExamineVerb verb = new() + { + Text = Loc.GetString("strip-verb-get-data-text"), + Icon = new SpriteSpecifier.Texture(new("/Textures/Interface/VerbIcons/outfit.svg.192dpi.png")), + Act = () => StartOpeningStripper(args.User, (uid, component), true), + Category = VerbCategory.Examine, + }; - if (userHands.ActiveHandEntity != null && !hasEnt) - PlaceActiveHandItemInInventory(user, strippable, userHands.ActiveHandEntity.Value, args.Slot, strippable); - else if (userHands.ActiveHandEntity == null && hasEnt) - TakeItemFromInventory(user, strippable, held!.Value, args.Slot, strippable); + args.Verbs.Add(verb); } - private void StripHand(EntityUid user, string handId, Entity target, HandsComponent userHands) + private void OnActivateInWorld(EntityUid uid, StrippableComponent component, ActivateInWorldEvent args) { - if (!_handsSystem.TryGetHand(target, handId, out var hand)) + if (args.Target == args.User) return; - // is the target a handcuff? - if (TryComp(hand.HeldEntity, out VirtualItemComponent? virt) - && TryComp(target, out CuffableComponent? cuff) - && _cuffable.GetAllCuffs(cuff).Contains(virt.BlockingEntity)) - { - _cuffable.TryUncuff(target, user, virt.BlockingEntity, cuffable: cuff); + if (!HasComp(args.User)) return; - } - if (userHands.ActiveHandEntity != null && hand.HeldEntity == null) - PlaceActiveHandItemInHands(user, target, userHands.ActiveHandEntity.Value, handId, target); - else if (userHands.ActiveHandEntity == null && hand.HeldEntity != null) - TakeItemFromHands(user, target, hand.HeldEntity.Value, handId, target); + StartOpeningStripper(args.User, (uid, component)); } public override void StartOpeningStripper(EntityUid user, Entity strippable, bool openInCombat = false) @@ -123,352 +119,514 @@ public override void StartOpeningStripper(EntityUid user, Entity args) + private void OnStripButtonPressed(Entity strippable, ref StrippingSlotButtonPressed args) { - if (args.Hands == null || !args.CanAccess || !args.CanInteract || args.Target == args.User) + if (args.Session.AttachedEntity is not { Valid: true } user || + !TryComp(user, out var userHands) || + !TryComp(strippable.Owner, out var targetHands)) return; - if (!HasComp(args.User)) + if (args.IsHand) + { + StripHand((user, userHands), (strippable.Owner, targetHands), args.Slot, strippable); return; + } - Verb verb = new() - { - Text = Loc.GetString("strip-verb-get-data-text"), - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/outfit.svg.192dpi.png")), - Act = () => StartOpeningStripper(args.User, (uid, component), true), - }; - args.Verbs.Add(verb); + if (!TryComp(strippable, out var inventory)) + return; + + var hasEnt = _inventorySystem.TryGetSlotEntity(strippable, args.Slot, out var held, inventory); + + if (userHands.ActiveHandEntity != null && !hasEnt) + StartStripInsertInventory((user, userHands), strippable.Owner, userHands.ActiveHandEntity.Value, args.Slot); + else if (userHands.ActiveHandEntity == null && hasEnt) + StartStripRemoveInventory(user, strippable.Owner, held!.Value, args.Slot); } - private void AddStripExamineVerb(EntityUid uid, StrippableComponent component, GetVerbsEvent args) + private void StripHand( + Entity user, + Entity target, + string handId, + StrippableComponent? targetStrippable) { - if (args.Hands == null || !args.CanAccess || !args.CanInteract || args.Target == args.User) + if (!Resolve(user, ref user.Comp) || + !Resolve(target, ref target.Comp) || + !Resolve(target, ref targetStrippable)) return; - if (!HasComp(args.User)) + if (!_handsSystem.TryGetHand(target.Owner, handId, out var handSlot)) return; - ExamineVerb verb = new() + // Is the target a handcuff? + if (TryComp(handSlot.HeldEntity, out var virtualItem) && + TryComp(target.Owner, out var cuffable) && + _cuffableSystem.GetAllCuffs(cuffable).Contains(virtualItem.BlockingEntity)) { - Text = Loc.GetString("strip-verb-get-data-text"), - Icon = new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/outfit.svg.192dpi.png")), - Act = () => StartOpeningStripper(args.User, (uid, component), true), - Category = VerbCategory.Examine, - }; + _cuffableSystem.TryUncuff(target.Owner, user, virtualItem.BlockingEntity, cuffable); + return; + } - args.Verbs.Add(verb); + if (user.Comp.ActiveHandEntity != null && handSlot.HeldEntity == null) + StartStripInsertHand(user, target, user.Comp.ActiveHandEntity.Value, handId, targetStrippable); + else if (user.Comp.ActiveHandEntity == null && handSlot.HeldEntity != null) + StartStripRemoveHand(user, target, handSlot.HeldEntity.Value, handId, targetStrippable); } - private void OnActivateInWorld(EntityUid uid, StrippableComponent component, ActivateInWorldEvent args) + private void OnStripEnsnareMessage(EntityUid uid, EnsnareableComponent component, StrippingEnsnareButtonPressed args) { - if (args.Target == args.User) + if (args.Session.AttachedEntity is not { Valid: true } user) return; - if (!HasComp(args.User)) - return; + foreach (var entity in component.Container.ContainedEntities) + { + if (!TryComp(entity, out var ensnaring)) + continue; - StartOpeningStripper(args.User, (uid, component)); + _ensnaringSystem.TryFree(uid, user, entity, ensnaring); + return; + } } /// - /// Places item in user's active hand to an inventory slot. + /// Checks whether the item is in a user's active hand and whether it can be inserted into the inventory slot. /// - private async void PlaceActiveHandItemInInventory( - EntityUid user, + private bool CanStripInsertInventory( + Entity user, EntityUid target, EntityUid held, - string slot, - StrippableComponent component) + string slot) { - var userHands = Comp(user); + if (!Resolve(user, ref user.Comp)) + return false; + + if (user.Comp.ActiveHand == null) + return false; + + if (user.Comp.ActiveHandEntity == null) + return false; + + if (user.Comp.ActiveHandEntity != held) + return false; + + if (!_handsSystem.CanDropHeld(user, user.Comp.ActiveHand)) + { + _popupSystem.PopupCursor(Loc.GetString("strippable-component-cannot-drop"), user); + return false; + } + + if (_inventorySystem.TryGetSlotEntity(target, slot, out _)) + { + _popupSystem.PopupCursor(Loc.GetString("strippable-component-item-slot-occupied", ("owner", target)), user); + return false; + } - bool Check() + if (!_inventorySystem.CanEquip(user, target, held, slot, out _)) { - if (userHands.ActiveHandEntity != held) - return false; - - if (!_handsSystem.CanDropHeld(user, userHands.ActiveHand!)) - { - _popup.PopupCursor(Loc.GetString("strippable-component-cannot-drop"), user); - return false; - } - - if (_inventorySystem.TryGetSlotEntity(target, slot, out _)) - { - _popup.PopupCursor(Loc.GetString("strippable-component-item-slot-occupied",("owner", target)), user); - return false; - } - - if (!_inventorySystem.CanEquip(user, target, held, slot, out _)) - { - _popup.PopupCursor(Loc.GetString("strippable-component-cannot-equip-message",("owner", target)), user); - return false; - } - - return true; + _popupSystem.PopupCursor(Loc.GetString("strippable-component-cannot-equip-message", ("owner", target)), user); + return false; } + return true; + } + + /// + /// Begins a DoAfter to insert the item in the user's active hand into the inventory slot. + /// + private void StartStripInsertInventory( + Entity user, + EntityUid target, + EntityUid held, + string slot) + { + if (!Resolve(user, ref user.Comp)) + return; + + if (!CanStripInsertInventory(user, target, held, slot)) + return; + if (!_inventorySystem.TryGetSlot(target, slot, out var slotDef)) { Log.Error($"{ToPrettyString(user)} attempted to place an item in a non-existent inventory slot ({slot}) on {ToPrettyString(target)}"); return; } - var userEv = new BeforeStripEvent(slotDef.StripTime); - RaiseLocalEvent(user, userEv); - var ev = new BeforeGettingStrippedEvent(userEv.Time, userEv.Stealth); - RaiseLocalEvent(target, ev); + var (time, stealth) = GetStripTimeModifiers(user, target, slotDef.StripTime); + + if (!stealth) + _popupSystem.PopupEntity(Loc.GetString("strippable-component-alert-owner-insert", ("user", Identity.Entity(user, EntityManager)), ("item", user.Comp.ActiveHandEntity!.Value)), target, target, PopupType.Large); + + var prefix = stealth ? "stealthily " : ""; + _adminLogger.Add(LogType.Stripping, LogImpact.Low, $"{ToPrettyString(user):actor} is trying to {prefix}place the item {ToPrettyString(held):item} in {ToPrettyString(target):target}'s {slot} slot"); - var doAfterArgs = new DoAfterArgs(EntityManager, user, ev.Time, new AwaitedDoAfterEvent(), null, target: target, used: held) + var doAfterArgs = new DoAfterArgs(EntityManager, user, time, new StrippableDoAfterEvent(true, true, slot), user, target, held) { - ExtraCheck = Check, - Hidden = ev.Stealth, + Hidden = stealth, AttemptFrequency = AttemptFrequency.EveryTick, BreakOnDamage = true, BreakOnTargetMove = true, BreakOnUserMove = true, NeedHand = true, - DuplicateCondition = DuplicateConditions.SameTool // Block any other DoAfters featuring this same entity. + DuplicateCondition = DuplicateConditions.SameTool }; - if (!ev.Stealth && Check() && userHands.ActiveHandEntity != null) - { - var message = Loc.GetString("strippable-component-alert-owner-insert", - ("user", Identity.Entity(user, EntityManager)), ("item", userHands.ActiveHandEntity)); - _popup.PopupEntity(message, target, target, PopupType.Large); - } + _doAfterSystem.TryStartDoAfter(doAfterArgs); + } - var prefix = ev.Stealth ? "stealthily " : ""; - _adminLogger.Add(LogType.Stripping, LogImpact.Low, $"{ToPrettyString(user):actor} is trying to {prefix}place the item {ToPrettyString(held):item} in {ToPrettyString(target):target}'s {slot} slot"); + /// + /// Inserts the item in the user's active hand into the inventory slot. + /// + private void StripInsertInventory( + Entity user, + EntityUid target, + EntityUid held, + string slot) + { + if (!Resolve(user, ref user.Comp)) + return; - var result = await _doAfter.WaitDoAfter(doAfterArgs); - if (result != DoAfterStatus.Finished) + if (!CanStripInsertInventory(user, target, held, slot)) return; - DebugTools.Assert(userHands.ActiveHand?.HeldEntity == held); + if (!_handsSystem.TryDrop(user, handsComp: user.Comp)) + return; + + _inventorySystem.TryEquip(user, target, held, slot); + _adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):actor} has placed the item {ToPrettyString(held):item} in {ToPrettyString(target):target}'s {slot} slot"); + } - if (_handsSystem.TryDrop(user, handsComp: userHands)) + /// + /// Checks whether the item can be removed from the target's inventory. + /// + private bool CanStripRemoveInventory( + EntityUid user, + EntityUid target, + EntityUid item, + string slot) + { + if (!_inventorySystem.TryGetSlotEntity(target, slot, out var slotItem)) { - _inventorySystem.TryEquip(user, target, held, slot); + _popupSystem.PopupCursor(Loc.GetString("strippable-component-item-slot-free-message", ("owner", target)), user); + return false; + } - _adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):actor} has placed the item {ToPrettyString(held):item} in {ToPrettyString(target):target}'s {slot} slot"); + if (slotItem != item) + return false; + + if (!_inventorySystem.CanUnequip(user, target, slot, out var reason)) + { + _popupSystem.PopupCursor(Loc.GetString(reason), user); + return false; } + + return true; } /// - /// Places item in user's active hand in one of the entity's hands. + /// Begins a DoAfter to remove the item from the target's inventory and insert it in the user's active hand. /// - private async void PlaceActiveHandItemInHands( + private void StartStripRemoveInventory( EntityUid user, EntityUid target, - EntityUid held, - string handName, - StrippableComponent component) + EntityUid item, + string slot) { - var hands = Comp(target); - var userHands = Comp(user); + if (!CanStripRemoveInventory(user, target, item, slot)) + return; - bool Check() + if (!_inventorySystem.TryGetSlot(target, slot, out var slotDef)) { - if (userHands.ActiveHandEntity != held) - return false; - - if (!_handsSystem.CanDropHeld(user, userHands.ActiveHand!)) - { - _popup.PopupCursor(Loc.GetString("strippable-component-cannot-drop"), user); - return false; - } - - if (!_handsSystem.TryGetHand(target, handName, out var hand, hands) - || !_handsSystem.CanPickupToHand(target, userHands.ActiveHandEntity.Value, hand, checkActionBlocker: false, hands)) - { - _popup.PopupCursor(Loc.GetString("strippable-component-cannot-put-message",("owner", target)), user); - return false; - } - - return true; + Log.Error($"{ToPrettyString(user)} attempted to take an item from a non-existent inventory slot ({slot}) on {ToPrettyString(target)}"); + return; } - var userEv = new BeforeStripEvent(component.HandStripDelay); - RaiseLocalEvent(user, userEv); - var ev = new BeforeGettingStrippedEvent(userEv.Time, userEv.Stealth); - RaiseLocalEvent(target, ev); + var (time, stealth) = GetStripTimeModifiers(user, target, slotDef.StripTime); - var doAfterArgs = new DoAfterArgs(EntityManager, user, ev.Time, new AwaitedDoAfterEvent(), null, target: target, used: held) + if (!stealth) { - ExtraCheck = Check, - Hidden = ev.Stealth, + if (slotDef.StripHidden) + _popupSystem.PopupEntity(Loc.GetString("strippable-component-alert-owner-hidden", ("slot", slot)), target, target, PopupType.Large); + else + _popupSystem.PopupEntity(Loc.GetString("strippable-component-alert-owner", ("user", Identity.Entity(user, EntityManager)), ("item", item)), target, target, PopupType.Large); + } + + var prefix = stealth ? "stealthily " : ""; + _adminLogger.Add(LogType.Stripping, LogImpact.Low, $"{ToPrettyString(user):actor} is trying to {prefix}strip the item {ToPrettyString(item):item} from {ToPrettyString(target):target}'s {slot} slot"); + + var doAfterArgs = new DoAfterArgs(EntityManager, user, time, new StrippableDoAfterEvent(false, true, slot), user, target, item) + { + Hidden = stealth, AttemptFrequency = AttemptFrequency.EveryTick, BreakOnDamage = true, BreakOnTargetMove = true, BreakOnUserMove = true, NeedHand = true, + BreakOnHandChange = false, // Allow simultaneously removing multiple items. DuplicateCondition = DuplicateConditions.SameTool }; - var prefix = ev.Stealth ? "stealthily " : ""; - _adminLogger.Add(LogType.Stripping, LogImpact.Low, $"{ToPrettyString(user):actor} is trying to {prefix}place the item {ToPrettyString(held):item} in {ToPrettyString(target):target}'s hands"); - - var result = await _doAfter.WaitDoAfter(doAfterArgs); - if (result != DoAfterStatus.Finished) return; - - _handsSystem.TryDrop(user, checkActionBlocker: false, handsComp: userHands); - _handsSystem.TryPickup(target, held, handName, checkActionBlocker: false, animateUser: !ev.Stealth, animate: !ev.Stealth, handsComp: hands); - _adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):actor} has placed the item {ToPrettyString(held):item} in {ToPrettyString(target):target}'s hands"); - // hand update will trigger strippable update + _doAfterSystem.TryStartDoAfter(doAfterArgs); } /// - /// Takes an item from the inventory and places it in the user's active hand. + /// Removes the item from the target's inventory and inserts it in the user's active hand. /// - private async void TakeItemFromInventory( + private void StripRemoveInventory( EntityUid user, EntityUid target, EntityUid item, string slot, - Entity strippable) + bool stealth) + { + if (!CanStripRemoveInventory(user, target, item, slot)) + return; + + if (!_inventorySystem.TryUnequip(user, target, slot)) + return; + + RaiseLocalEvent(item, new DroppedEvent(user), true); // Gas tank internals etc. + + _handsSystem.PickupOrDrop(user, item, animateUser: stealth, animate: stealth); + _adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):actor} has stripped the item {ToPrettyString(item):item} from {ToPrettyString(target):target}'s {slot} slot"); + } + + /// + /// Checks whether the item in the user's active hand can be inserted into one of the target's hands. + /// + private bool CanStripInsertHand( + Entity user, + Entity target, + EntityUid held, + string handName) { - bool Check() + if (!Resolve(user, ref user.Comp) || + !Resolve(target, ref target.Comp)) + return false; + + if (user.Comp.ActiveHand == null) + return false; + + if (user.Comp.ActiveHandEntity == null) + return false; + + if (user.Comp.ActiveHandEntity != held) + return false; + + if (!_handsSystem.CanDropHeld(user, user.Comp.ActiveHand)) { - if (!_inventorySystem.TryGetSlotEntity(target, slot, out var ent) && ent == item) - { - _popup.PopupCursor(Loc.GetString("strippable-component-item-slot-free-message", ("owner", target)), user); - return false; - } - - if (!_inventorySystem.CanUnequip(user, target, slot, out var reason)) - { - _popup.PopupCursor(Loc.GetString(reason), user); - return false; - } - - return true; + _popupSystem.PopupCursor(Loc.GetString("strippable-component-cannot-drop"), user); + return false; } - if (!_inventorySystem.TryGetSlot(target, slot, out var slotDef)) + if (!_handsSystem.TryGetHand(target, handName, out var handSlot, target.Comp) || + !_handsSystem.CanPickupToHand(target, user.Comp.ActiveHandEntity.Value, handSlot, checkActionBlocker: false, target.Comp)) { - Log.Error($"{ToPrettyString(user)} attempted to take an item from a non-existent inventory slot ({slot}) on {ToPrettyString(target)}"); - return; + _popupSystem.PopupCursor(Loc.GetString("strippable-component-cannot-put-message", ("owner", target)), user); + return false; } - var userEv = new BeforeStripEvent(slotDef.StripTime); - RaiseLocalEvent(user, userEv); - var ev = new BeforeGettingStrippedEvent(userEv.Time, userEv.Stealth); - RaiseLocalEvent(target, ev); + return true; + } + + /// + /// Begins a DoAfter to insert the item in the user's active hand into one of the target's hands. + /// + private void StartStripInsertHand( + Entity user, + Entity target, + EntityUid held, + string handName, + StrippableComponent? targetStrippable = null) + { + if (!Resolve(user, ref user.Comp) || + !Resolve(target, ref target.Comp) || + !Resolve(target, ref targetStrippable)) + return; + + if (!CanStripInsertHand(user, target, held, handName)) + return; - var doAfterArgs = new DoAfterArgs(EntityManager, user, ev.Time, new AwaitedDoAfterEvent(), null, target: target, used: item) + var (time, stealth) = GetStripTimeModifiers(user, target, targetStrippable.HandStripDelay); + + var prefix = stealth ? "stealthily " : ""; + _adminLogger.Add(LogType.Stripping, LogImpact.Low, $"{ToPrettyString(user):actor} is trying to {prefix}place the item {ToPrettyString(held):item} in {ToPrettyString(target):target}'s hands"); + + var doAfterArgs = new DoAfterArgs(EntityManager, user, time, new StrippableDoAfterEvent(true, false, handName), user, target, held) { - ExtraCheck = Check, - Hidden = ev.Stealth, + Hidden = stealth, AttemptFrequency = AttemptFrequency.EveryTick, BreakOnDamage = true, BreakOnTargetMove = true, BreakOnUserMove = true, NeedHand = true, - BreakOnHandChange = false, // allow simultaneously removing multiple items. DuplicateCondition = DuplicateConditions.SameTool }; - if (!ev.Stealth && Check()) + _doAfterSystem.TryStartDoAfter(doAfterArgs); + } + + /// + /// Places the item in the user's active hand into one of the target's hands. + /// + private void StripInsertHand( + Entity user, + Entity target, + EntityUid held, + string handName, + bool stealth) + { + if (!Resolve(user, ref user.Comp) || + !Resolve(target, ref target.Comp)) + return; + + _handsSystem.TryDrop(user, checkActionBlocker: false, handsComp: user.Comp); + _handsSystem.TryPickup(target, held, handName, checkActionBlocker: false, animateUser: stealth, animate: stealth, handsComp: target.Comp); + _adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):actor} has placed the item {ToPrettyString(held):item} in {ToPrettyString(target):target}'s hands"); + + // Hand update will trigger strippable update. + } + + /// + /// Checks whether the item is in the target's hand and whether it can be dropped. + /// + private bool CanStripRemoveHand( + EntityUid user, + Entity target, + EntityUid item, + string handName) + { + if (!Resolve(target, ref target.Comp)) + return false; + + if (!_handsSystem.TryGetHand(target, handName, out var handSlot, target.Comp)) { - if (slotDef.StripHidden) - { - _popup.PopupEntity(Loc.GetString("strippable-component-alert-owner-hidden", ("slot", slot)), target, - target, PopupType.Large); - } - else if (_inventorySystem.TryGetSlotEntity(strippable, slot, out var slotItem)) - { - _popup.PopupEntity(Loc.GetString("strippable-component-alert-owner", ("user", Identity.Entity(user, EntityManager)), ("item", slotItem)), target, - target, PopupType.Large); - } + _popupSystem.PopupCursor(Loc.GetString("strippable-component-item-slot-free-message", ("owner", target)), user); + return false; } - var prefix = ev.Stealth ? "stealthily " : ""; - _adminLogger.Add(LogType.Stripping, LogImpact.Low, $"{ToPrettyString(user):actor} is trying to {prefix}strip the item {ToPrettyString(item):item} from {ToPrettyString(target):target}'s {slot} slot"); + if (HasComp(handSlot.HeldEntity)) + return false; - var result = await _doAfter.WaitDoAfter(doAfterArgs); - if (result != DoAfterStatus.Finished) - return; + if (handSlot.HeldEntity == null) + return false; - if (!_inventorySystem.TryUnequip(user, strippable, slot)) - return; - - // Raise a dropped event, so that things like gas tank internals properly deactivate when stripping - RaiseLocalEvent(item, new DroppedEvent(user), true); + if (handSlot.HeldEntity != item) + return false; - _handsSystem.PickupOrDrop(user, item, animateUser: !ev.Stealth, animate: !ev.Stealth); - _adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):actor} has stripped the item {ToPrettyString(item):item} from {ToPrettyString(target):target}'s {slot} slot"); + if (!_handsSystem.CanDropHeld(target, handSlot, false)) + { + _popupSystem.PopupCursor(Loc.GetString("strippable-component-cannot-drop-message", ("owner", target)), user); + return false; + } + return true; } /// - /// Takes an item from a hand and places it in the user's active hand. + /// Begins a DoAfter to remove the item from the target's hand and insert it in the user's active hand. /// - private async void TakeItemFromHands(EntityUid user, EntityUid target, EntityUid item, string handName, Entity strippable) + private void StartStripRemoveHand( + Entity user, + Entity target, + EntityUid item, + string handName, + StrippableComponent? targetStrippable = null) { - var hands = Comp(target); - var userHands = Comp(user); + if (!Resolve(user, ref user.Comp) || + !Resolve(target, ref target.Comp) || + !Resolve(target, ref targetStrippable)) + return; - bool Check() - { - if (!_handsSystem.TryGetHand(target, handName, out var hand, hands) || hand.HeldEntity != item) - { - _popup.PopupCursor(Loc.GetString("strippable-component-item-slot-free-message",("owner", target)), user); - return false; - } - - if (HasComp(hand.HeldEntity)) - return false; - - if (!_handsSystem.CanDropHeld(target, hand, false)) - { - _popup.PopupCursor(Loc.GetString("strippable-component-cannot-drop-message",("owner", target)), user); - return false; - } - - return true; - } + if (!CanStripRemoveHand(user, target, item, handName)) + return; - var userEv = new BeforeStripEvent(strippable.Comp.HandStripDelay); - RaiseLocalEvent(user, userEv); - var ev = new BeforeGettingStrippedEvent(userEv.Time, userEv.Stealth); - RaiseLocalEvent(target, ev); + var (time, stealth) = GetStripTimeModifiers(user, target, targetStrippable.HandStripDelay); - var doAfterArgs = new DoAfterArgs(EntityManager, user, ev.Time, new AwaitedDoAfterEvent(), null, target: target, used: item) + if (!stealth) + _popupSystem.PopupEntity( Loc.GetString("strippable-component-alert-owner", ("user", Identity.Entity(user, EntityManager)), ("item", item)), target, target); + + var prefix = stealth ? "stealthily " : ""; + _adminLogger.Add(LogType.Stripping, LogImpact.Low, $"{ToPrettyString(user):actor} is trying to {prefix}strip the item {ToPrettyString(item):item} from {ToPrettyString(target):target}'s hands"); + + var doAfterArgs = new DoAfterArgs(EntityManager, user, time, new StrippableDoAfterEvent(false, false, handName), user, target, item) { - ExtraCheck = Check, - Hidden = ev.Stealth, + Hidden = stealth, AttemptFrequency = AttemptFrequency.EveryTick, BreakOnDamage = true, BreakOnTargetMove = true, BreakOnUserMove = true, NeedHand = true, - BreakOnHandChange = false, // allow simultaneously removing multiple items. + BreakOnHandChange = false, // Allow simultaneously removing multiple items. DuplicateCondition = DuplicateConditions.SameTool }; - if (!ev.Stealth && Check() && _handsSystem.TryGetHand(target, handName, out var handSlot, hands) && handSlot.HeldEntity != null) + _doAfterSystem.TryStartDoAfter(doAfterArgs); + } + + /// + /// Takes the item from the target's hand and inserts it in the user's active hand. + /// + private void StripRemoveHand( + Entity user, + Entity target, + EntityUid item, + bool stealth) + { + if (!Resolve(user, ref user.Comp) || + !Resolve(target, ref target.Comp)) + return; + + _handsSystem.TryDrop(target, item, checkActionBlocker: false, handsComp: target.Comp); + _handsSystem.PickupOrDrop(user, item, animateUser: stealth, animate: stealth, handsComp: user.Comp); + _adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):actor} has stripped the item {ToPrettyString(item):item} from {ToPrettyString(target):target}'s hands"); + + // Hand update will trigger strippable update. + } + + private void OnStrippableDoAfterRunning(Entity entity, ref DoAfterAttemptEvent ev) + { + var args = ev.DoAfter.Args; + + DebugTools.Assert(entity.Owner == args.User); + DebugTools.Assert(args.Target != null); + DebugTools.Assert(args.Used != null); + DebugTools.Assert(ev.Event.SlotOrHandName != null); + + if (ev.Event.InventoryOrHand) { - _popup.PopupEntity( - Loc.GetString("strippable-component-alert-owner", - ("user", Identity.Entity(user, EntityManager)), ("item", item)), - strippable.Owner, - strippable.Owner); + if ( ev.Event.InsertOrRemove && !CanStripInsertInventory((entity.Owner, entity.Comp), args.Target.Value, args.Used.Value, ev.Event.SlotOrHandName) || + !ev.Event.InsertOrRemove && !CanStripRemoveInventory(entity.Owner, args.Target.Value, args.Used.Value, ev.Event.SlotOrHandName)) + ev.Cancel(); } + else + { + if ( ev.Event.InsertOrRemove && !CanStripInsertHand((entity.Owner, entity.Comp), args.Target.Value, args.Used.Value, ev.Event.SlotOrHandName) || + !ev.Event.InsertOrRemove && !CanStripRemoveHand(entity.Owner, args.Target.Value, args.Used.Value, ev.Event.SlotOrHandName)) + ev.Cancel(); + } + } - var prefix = ev.Stealth ? "stealthily " : ""; - _adminLogger.Add(LogType.Stripping, LogImpact.Low, - $"{ToPrettyString(user):actor} is trying to {prefix}strip the item {ToPrettyString(item):item} from {ToPrettyString(target):target}'s hands"); - - var result = await _doAfter.WaitDoAfter(doAfterArgs); - if (result != DoAfterStatus.Finished) + private void OnStrippableDoAfterFinished(Entity entity, ref StrippableDoAfterEvent ev) + { + if (ev.Cancelled) return; - _handsSystem.TryDrop(target, item, checkActionBlocker: false, handsComp: hands); - _handsSystem.PickupOrDrop(user, item, animateUser: !ev.Stealth, animate: !ev.Stealth, handsComp: userHands); - // hand update will trigger strippable update - _adminLogger.Add(LogType.Stripping, LogImpact.Medium, - $"{ToPrettyString(user):actor} has stripped the item {ToPrettyString(item):item} from {ToPrettyString(target):target}'s hands"); + DebugTools.Assert(entity.Owner == ev.User); + DebugTools.Assert(ev.Target != null); + DebugTools.Assert(ev.Used != null); + DebugTools.Assert(ev.SlotOrHandName != null); + + if (ev.InventoryOrHand) + { + if (ev.InsertOrRemove) + StripInsertInventory((entity.Owner, entity.Comp), ev.Target.Value, ev.Used.Value, ev.SlotOrHandName); + else StripRemoveInventory(entity.Owner, ev.Target.Value, ev.Used.Value, ev.SlotOrHandName, ev.Args.Hidden); + } + else + { + if (ev.InsertOrRemove) + StripInsertHand((entity.Owner, entity.Comp), ev.Target.Value, ev.Used.Value, ev.SlotOrHandName, ev.Args.Hidden); + else StripRemoveHand((entity.Owner, entity.Comp), ev.Target.Value, ev.Used.Value, ev.Args.Hidden); + } } } } diff --git a/Content.Shared/Clothing/EntitySystems/ToggleableClothingSystem.cs b/Content.Shared/Clothing/EntitySystems/ToggleableClothingSystem.cs index 0138de7a98f..22a1d1a8f52 100644 --- a/Content.Shared/Clothing/EntitySystems/ToggleableClothingSystem.cs +++ b/Content.Shared/Clothing/EntitySystems/ToggleableClothingSystem.cs @@ -95,7 +95,7 @@ private void StartDoAfter(EntityUid user, EntityUid item, EntityUid wearer, Togg if (component.StripDelay == null) return; - var (time, stealth) = _strippable.GetStripTimeModifiers(user, wearer, (float) component.StripDelay.Value.TotalSeconds); + var (time, stealth) = _strippable.GetStripTimeModifiers(user, wearer, component.StripDelay.Value); var args = new DoAfterArgs(EntityManager, user, time, new ToggleClothingDoAfterEvent(), item, wearer, item) { diff --git a/Content.Shared/Inventory/InventoryTemplatePrototype.cs b/Content.Shared/Inventory/InventoryTemplatePrototype.cs index a4779699629..585f80d4ce9 100644 --- a/Content.Shared/Inventory/InventoryTemplatePrototype.cs +++ b/Content.Shared/Inventory/InventoryTemplatePrototype.cs @@ -20,7 +20,7 @@ public sealed partial class SlotDefinition [DataField("slotFlags")] public SlotFlags SlotFlags { get; private set; } = SlotFlags.PREVENTEQUIP; [DataField("showInWindow")] public bool ShowInWindow { get; private set; } = true; [DataField("slotGroup")] public string SlotGroup { get; private set; } = "Default"; - [DataField("stripTime")] public float StripTime { get; private set; } = 4f; + [DataField("stripTime")] public TimeSpan StripTime { get; private set; } = TimeSpan.FromSeconds(4f); [DataField("uiWindowPos", required: true)] public Vector2i UIWindowPosition { get; private set; } diff --git a/Content.Shared/Strip/Components/StrippableComponent.cs b/Content.Shared/Strip/Components/StrippableComponent.cs index fbf99992e3c..8bf09c3f4c6 100644 --- a/Content.Shared/Strip/Components/StrippableComponent.cs +++ b/Content.Shared/Strip/Components/StrippableComponent.cs @@ -1,3 +1,4 @@ +using Content.Shared.DoAfter; using Content.Shared.Inventory; using Robust.Shared.GameStates; using Robust.Shared.Serialization; @@ -8,10 +9,10 @@ namespace Content.Shared.Strip.Components public sealed partial class StrippableComponent : Component { /// - /// The strip delay for hands. + /// The strip delay for hands. /// [ViewVariables(VVAccess.ReadWrite), DataField("handDelay")] - public float HandStripDelay = 4f; + public TimeSpan HandStripDelay = TimeSpan.FromSeconds(4f); } [NetSerializable, Serializable] @@ -21,63 +22,63 @@ public enum StrippingUiKey : byte } [NetSerializable, Serializable] - public sealed class StrippingSlotButtonPressed : BoundUserInterfaceMessage + public sealed class StrippingSlotButtonPressed(string slot, bool isHand) : BoundUserInterfaceMessage { - public readonly string Slot; - - public readonly bool IsHand; - - public StrippingSlotButtonPressed(string slot, bool isHand) - { - Slot = slot; - IsHand = isHand; - } + public readonly string Slot = slot; + public readonly bool IsHand = isHand; } [NetSerializable, Serializable] - public sealed class StrippingEnsnareButtonPressed : BoundUserInterfaceMessage - { - public StrippingEnsnareButtonPressed() - { - } - } + public sealed class StrippingEnsnareButtonPressed : BoundUserInterfaceMessage; - public abstract class BaseBeforeStripEvent : EntityEventArgs, IInventoryRelayEvent + [ByRefEvent] + public abstract class BaseBeforeStripEvent(TimeSpan initialTime, bool stealth = false) : EntityEventArgs, IInventoryRelayEvent { - public readonly float InitialTime; - public float Time => MathF.Max(InitialTime * Multiplier + Additive, 0f); - public float Additive = 0; - public float Multiplier = 1f; - public bool Stealth; + public readonly TimeSpan InitialTime = initialTime; + public TimeSpan Multiplier = TimeSpan.FromSeconds(1f); + public TimeSpan Additive = TimeSpan.Zero; + public bool Stealth = stealth; - public SlotFlags TargetSlots { get; } = SlotFlags.GLOVES; + public TimeSpan Time => TimeSpan.FromSeconds(MathF.Max(InitialTime.Seconds * Multiplier.Seconds + Additive.Seconds, 0f)); - public BaseBeforeStripEvent(float initialTime, bool stealth = false) - { - InitialTime = initialTime; - Stealth = stealth; - } + public SlotFlags TargetSlots { get; } = SlotFlags.GLOVES; } /// - /// Used to modify strip times. Raised directed at the user. + /// Used to modify strip times. Raised directed at the user. /// /// - /// This is also used by some stripping related interactions, i.e., interactions with items that are currently equipped by another player. + /// This is also used by some stripping related interactions, i.e., interactions with items that are currently equipped by another player. /// - public sealed class BeforeStripEvent : BaseBeforeStripEvent - { - public BeforeStripEvent(float initialTime, bool stealth = false) : base(initialTime, stealth) { } - } + [ByRefEvent] + public sealed class BeforeStripEvent(TimeSpan initialTime, bool stealth = false) : BaseBeforeStripEvent(initialTime, stealth); /// - /// Used to modify strip times. Raised directed at the target. + /// Used to modify strip times. Raised directed at the target. /// /// - /// This is also used by some stripping related interactions, i.e., interactions with items that are currently equipped by another player. + /// This is also used by some stripping related interactions, i.e., interactions with items that are currently equipped by another player. /// - public sealed class BeforeGettingStrippedEvent : BaseBeforeStripEvent + [ByRefEvent] + public sealed class BeforeGettingStrippedEvent(TimeSpan initialTime, bool stealth = false) : BaseBeforeStripEvent(initialTime, stealth); + + /// + /// Organizes the behavior of DoAfters for . + /// + [Serializable, NetSerializable] + public sealed partial class StrippableDoAfterEvent : DoAfterEvent { - public BeforeGettingStrippedEvent(float initialTime, bool stealth = false) : base(initialTime, stealth) { } + public readonly bool InsertOrRemove; + public readonly bool InventoryOrHand; + public readonly string SlotOrHandName; + + public StrippableDoAfterEvent(bool insertOrRemove, bool inventoryOrHand, string slotOrHandName) + { + InsertOrRemove = insertOrRemove; + InventoryOrHand = inventoryOrHand; + SlotOrHandName = slotOrHandName; + } + + public override DoAfterEvent Clone() => this; } } diff --git a/Content.Shared/Strip/Components/ThievingComponent.cs b/Content.Shared/Strip/Components/ThievingComponent.cs index 83679f132c4..a851dd5ef63 100644 --- a/Content.Shared/Strip/Components/ThievingComponent.cs +++ b/Content.Shared/Strip/Components/ThievingComponent.cs @@ -11,7 +11,7 @@ public sealed partial class ThievingComponent : Component /// [ViewVariables(VVAccess.ReadWrite)] [DataField("stripTimeReduction")] - public float StripTimeReduction = 0.5f; + public TimeSpan StripTimeReduction = TimeSpan.FromSeconds(0.5f); /// /// Should it notify the user if they're stripping a pocket? diff --git a/Content.Shared/Strip/SharedStrippableSystem.cs b/Content.Shared/Strip/SharedStrippableSystem.cs index a698ae5035a..7afd4f245a1 100644 --- a/Content.Shared/Strip/SharedStrippableSystem.cs +++ b/Content.Shared/Strip/SharedStrippableSystem.cs @@ -14,12 +14,12 @@ public override void Initialize() SubscribeLocalEvent(OnDragDrop); } - public (float Time, bool Stealth) GetStripTimeModifiers(EntityUid user, EntityUid target, float initialTime) + public (TimeSpan Time, bool Stealth) GetStripTimeModifiers(EntityUid user, EntityUid target, TimeSpan initialTime) { var userEv = new BeforeStripEvent(initialTime); - RaiseLocalEvent(user, userEv); + RaiseLocalEvent(user, ref userEv); var ev = new BeforeGettingStrippedEvent(userEv.Time, userEv.Stealth); - RaiseLocalEvent(target, ev); + RaiseLocalEvent(target, ref ev); return (ev.Time, ev.Stealth); } diff --git a/Content.Shared/Strip/ThievingSystem.cs b/Content.Shared/Strip/ThievingSystem.cs index 0ef4b66571f..2b3d3b38a00 100644 --- a/Content.Shared/Strip/ThievingSystem.cs +++ b/Content.Shared/Strip/ThievingSystem.cs @@ -1,4 +1,5 @@ using Content.Shared.Inventory; +using Content.Shared.Strip; using Content.Shared.Strip.Components; namespace Content.Shared.Strip; From ba2d53845e3f365a7423ac8f9ab6ee491e76d60d Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Mon, 1 Jul 2024 18:37:29 -0400 Subject: [PATCH 06/15] Make Spent Casing Ejection Not Suck (#478) # Description Part of #467, #460, and #474 This is a small PR that corrects a math error in SharedGunSystem, causing shell casings to be "Thrown" directly downwards instead of in an actually cinematic and exciting arc. While I'm at it, I also corrected the fixture of base shell casings to favor "Bounciness", and decreased its mass to approximately 100 grams. Finally, I added a sound for when casings bounce off of walls, which wasn't present before. https://github.com/Simple-Station/Einstein-Engines/assets/16548818/56bb4ecc-d5eb-4b36-853b-42f05374150d :cl: - fix: Spent bullet casings now fly away from a shooter in a cinematic manner, rather than fall at their feet. Co-authored-by: Danger Revolution! <142105406+DangerRevolution@users.noreply.github.com> --- Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs | 2 +- .../Guns/Ammunition/Cartridges/base_cartridge.yml | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs index cadb0a4b215..ff8b102bb57 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs @@ -443,7 +443,7 @@ protected void EjectCartridge( { Angle ejectAngle = angle.Value; ejectAngle += 3.7f; // 212 degrees; casings should eject slightly to the right and behind of a gun - ThrowingSystem.TryThrow(entity, ejectAngle.ToVec().Normalized() / 100, 5f); + ThrowingSystem.TryThrow(entity, ejectAngle.ToVec(), 625f); } if (playSound && TryComp(entity, out var cartridge)) { diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Cartridges/base_cartridge.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Cartridges/base_cartridge.yml index e188ee8c658..3bef413dffa 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Cartridges/base_cartridge.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Cartridges/base_cartridge.yml @@ -11,10 +11,10 @@ shape: !type:PhysShapeAabb bounds: "-0.10,-0.05,0.10,0.05" - density: 20 + density: 0.5 mask: - ItemMask - restitution: 0.3 # fite me + restitution: 0.7 # Small and bouncy friction: 0.2 - type: Tag tags: @@ -23,6 +23,11 @@ size: Tiny - type: SpaceGarbage - type: EmitSoundOnLand + sound: + path: /Audio/Weapons/Guns/Casings/casing_fall_1.ogg + params: + volume: -1 + - type: EmitSoundOnCollide sound: path: /Audio/Weapons/Guns/Casings/casing_fall_2.ogg params: From 2e712c00249cfe5bd254462a1efa1b6c8a1ec6bd Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Mon, 1 Jul 2024 22:37:52 +0000 Subject: [PATCH 07/15] Automatic Changelog Update (#478) --- Resources/Changelog/Changelog.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 6fe7b0ff689..515c1832db1 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -4257,3 +4257,11 @@ Entries: message: Most items now take time to equip and unequip, especially space suits. id: 6132 time: '2024-06-30T18:22:28.0000000+00:00' +- author: VMSolidus + changes: + - type: Fix + message: >- + Spent bullet casings now fly away from a shooter in a cinematic manner, + rather than fall at their feet. + id: 6133 + time: '2024-07-01T22:37:29.0000000+00:00' From 7b89ce1326c74e9d813ac56b497951c867b3af3e Mon Sep 17 00:00:00 2001 From: VMSolidus Date: Tue, 2 Jul 2024 03:15:06 -0400 Subject: [PATCH 08/15] Cherrypick "Fix StrippableSystem Blunders" (#504) --- Content.Server/Strip/StrippableSystem.cs | 16 +++++++++++----- .../Strip/Components/StrippableComponent.cs | 4 ++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Content.Server/Strip/StrippableSystem.cs b/Content.Server/Strip/StrippableSystem.cs index 950411a8e2c..3b38b65a19d 100644 --- a/Content.Server/Strip/StrippableSystem.cs +++ b/Content.Server/Strip/StrippableSystem.cs @@ -122,13 +122,12 @@ public override void StartOpeningStripper(EntityUid user, Entity strippable, ref StrippingSlotButtonPressed args) { if (args.Session.AttachedEntity is not { Valid: true } user || - !TryComp(user, out var userHands) || - !TryComp(strippable.Owner, out var targetHands)) + !TryComp(user, out var userHands)) return; if (args.IsHand) { - StripHand((user, userHands), (strippable.Owner, targetHands), args.Slot, strippable); + StripHand((user, userHands), (strippable.Owner, null), args.Slot, strippable); return; } @@ -478,6 +477,9 @@ private void StripInsertHand( !Resolve(target, ref target.Comp)) return; + if (!CanStripInsertHand(user, target, held, handName)) + return; + _handsSystem.TryDrop(user, checkActionBlocker: false, handsComp: user.Comp); _handsSystem.TryPickup(target, held, handName, checkActionBlocker: false, animateUser: stealth, animate: stealth, handsComp: target.Comp); _adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):actor} has placed the item {ToPrettyString(held):item} in {ToPrettyString(target):target}'s hands"); @@ -542,7 +544,7 @@ private void StartStripRemoveHand( var (time, stealth) = GetStripTimeModifiers(user, target, targetStrippable.HandStripDelay); if (!stealth) - _popupSystem.PopupEntity( Loc.GetString("strippable-component-alert-owner", ("user", Identity.Entity(user, EntityManager)), ("item", item)), target, target); + _popupSystem.PopupEntity(Loc.GetString("strippable-component-alert-owner", ("user", Identity.Entity(user, EntityManager)), ("item", item)), target, target); var prefix = stealth ? "stealthily " : ""; _adminLogger.Add(LogType.Stripping, LogImpact.Low, $"{ToPrettyString(user):actor} is trying to {prefix}strip the item {ToPrettyString(item):item} from {ToPrettyString(target):target}'s hands"); @@ -569,12 +571,16 @@ private void StripRemoveHand( Entity user, Entity target, EntityUid item, + string handName, bool stealth) { if (!Resolve(user, ref user.Comp) || !Resolve(target, ref target.Comp)) return; + if (!CanStripRemoveHand(user, target, item, handName)) + return; + _handsSystem.TryDrop(target, item, checkActionBlocker: false, handsComp: target.Comp); _handsSystem.PickupOrDrop(user, item, animateUser: stealth, animate: stealth, handsComp: user.Comp); _adminLogger.Add(LogType.Stripping, LogImpact.Medium, $"{ToPrettyString(user):actor} has stripped the item {ToPrettyString(item):item} from {ToPrettyString(target):target}'s hands"); @@ -625,7 +631,7 @@ private void OnStrippableDoAfterFinished(Entity entity, ref Stri { if (ev.InsertOrRemove) StripInsertHand((entity.Owner, entity.Comp), ev.Target.Value, ev.Used.Value, ev.SlotOrHandName, ev.Args.Hidden); - else StripRemoveHand((entity.Owner, entity.Comp), ev.Target.Value, ev.Used.Value, ev.Args.Hidden); + else StripRemoveHand((entity.Owner, entity.Comp), ev.Target.Value, ev.Used.Value, ev.SlotOrHandName, ev.Args.Hidden); } } } diff --git a/Content.Shared/Strip/Components/StrippableComponent.cs b/Content.Shared/Strip/Components/StrippableComponent.cs index 8bf09c3f4c6..4faca4d8f21 100644 --- a/Content.Shared/Strip/Components/StrippableComponent.cs +++ b/Content.Shared/Strip/Components/StrippableComponent.cs @@ -35,11 +35,11 @@ public sealed class StrippingEnsnareButtonPressed : BoundUserInterfaceMessage; public abstract class BaseBeforeStripEvent(TimeSpan initialTime, bool stealth = false) : EntityEventArgs, IInventoryRelayEvent { public readonly TimeSpan InitialTime = initialTime; - public TimeSpan Multiplier = TimeSpan.FromSeconds(1f); + public float Multiplier = 1f; public TimeSpan Additive = TimeSpan.Zero; public bool Stealth = stealth; - public TimeSpan Time => TimeSpan.FromSeconds(MathF.Max(InitialTime.Seconds * Multiplier.Seconds + Additive.Seconds, 0f)); + public TimeSpan Time => TimeSpan.FromSeconds(MathF.Max(InitialTime.Seconds * Multiplier + Additive.Seconds, 0f)); public SlotFlags TargetSlots { get; } = SlotFlags.GLOVES; } From 606a28d11e706681ec23f0db32eb01ddc0534a2d Mon Sep 17 00:00:00 2001 From: WarMechanic <69510347+WarMechanic@users.noreply.github.com> Date: Tue, 2 Jul 2024 17:18:27 +1000 Subject: [PATCH 09/15] Fix Loadouts Breaking when You Spend All Your Points (#506) # Description Self explanatory P.S. i genuinely dont know what the fuck i did, who wrote this? # TODO - [X] Fix shit # Media https://youtu.be/hbJbd5SgZ54 # Changelog :cl: - fix: Fixed loadouts becoming uneditable after spending all your points --- Content.Client/Preferences/UI/HumanoidProfileEditor.xaml.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Client/Preferences/UI/HumanoidProfileEditor.xaml.cs b/Content.Client/Preferences/UI/HumanoidProfileEditor.xaml.cs index c797f02a754..04810b07719 100644 --- a/Content.Client/Preferences/UI/HumanoidProfileEditor.xaml.cs +++ b/Content.Client/Preferences/UI/HumanoidProfileEditor.xaml.cs @@ -2086,7 +2086,7 @@ void AddSelector(LoadoutPreferenceSelector selector, int points, string id) selector.PreferenceChanged += preference => { // Make sure they have enough loadout points - preference = preference ? CheckPoints(points, preference) : CheckPoints(-points, preference); + preference = preference ? CheckPoints(-points, preference) : CheckPoints(points, preference); // Update Preferences Profile = Profile?.WithLoadoutPreference(id, preference); From 0d0dd4c01bfd859004b3b399d482187e6ba58ea8 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Tue, 2 Jul 2024 07:18:51 +0000 Subject: [PATCH 10/15] Automatic Changelog Update (#506) --- Resources/Changelog/Changelog.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 515c1832db1..e4e812edeb4 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -4265,3 +4265,9 @@ Entries: rather than fall at their feet. id: 6133 time: '2024-07-01T22:37:29.0000000+00:00' +- author: WarMechanic + changes: + - type: Fix + message: Fixed loadouts becoming uneditable after spending all your points + id: 6134 + time: '2024-07-02T07:18:27.0000000+00:00' From ffb9ec979ff9ffe76d81eeffa84cea0be45ac2fc Mon Sep 17 00:00:00 2001 From: Mnemotechnican <69920617+Mnemotechnician@users.noreply.github.com> Date: Tue, 2 Jul 2024 11:00:14 +0300 Subject: [PATCH 11/15] Unflip Hands for Felinid, Vulpkanin, Harpy (#503) # Description Cherry-picks https://github.com/DeltaV-Station/Delta-v/pull/1194 This is a minor issue in the yml files of custom species that will become a problem if we ever merge wizden's better hand indicators. This PR shouldn't require a preview; all credit goes to the original author of the fix. --- # Changelog Too minor for a cl. Or as some say, no cl no fun. Co-authored-by: Angelo Fallaria --- Resources/Prototypes/DeltaV/Body/Prototypes/harpy.yml | 5 ++--- Resources/Prototypes/DeltaV/Body/Prototypes/vulpkanin.yml | 6 +++--- .../Nyanotrasen/Entities/Body/Prototypes/felinid.yml | 4 ++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Resources/Prototypes/DeltaV/Body/Prototypes/harpy.yml b/Resources/Prototypes/DeltaV/Body/Prototypes/harpy.yml index 5b3615c55d8..25988f4a3a8 100644 --- a/Resources/Prototypes/DeltaV/Body/Prototypes/harpy.yml +++ b/Resources/Prototypes/DeltaV/Body/Prototypes/harpy.yml @@ -13,10 +13,10 @@ torso: part: TorsoHarpy connections: - - left arm - right arm - - left leg + - left arm - right leg + - left leg organs: heart: OrganHumanHeart lungs: OrganHarpyLungs @@ -47,4 +47,3 @@ part: RightFootHarpy left foot: part: LeftFootHarpy - diff --git a/Resources/Prototypes/DeltaV/Body/Prototypes/vulpkanin.yml b/Resources/Prototypes/DeltaV/Body/Prototypes/vulpkanin.yml index 3d1552ac81f..cdf787e4736 100644 --- a/Resources/Prototypes/DeltaV/Body/Prototypes/vulpkanin.yml +++ b/Resources/Prototypes/DeltaV/Body/Prototypes/vulpkanin.yml @@ -1,4 +1,4 @@ -- type: body +- type: body name: "vulpkanin" id: Vulpkanin root: torso @@ -19,10 +19,10 @@ liver: OrganAnimalLiver kidneys: OrganHumanKidneys connections: - - left arm - right arm - - left leg + - left arm - right leg + - left leg right arm: part: RightArmVulpkanin connections: diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Body/Prototypes/felinid.yml b/Resources/Prototypes/Nyanotrasen/Entities/Body/Prototypes/felinid.yml index 6dd2a89e5a8..a09f3b6ab7f 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Body/Prototypes/felinid.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Body/Prototypes/felinid.yml @@ -13,10 +13,10 @@ torso: part: TorsoHuman connections: - - left arm - right arm - - left leg + - left arm - right leg + - left leg organs: heart: OrganAnimalHeart lungs: OrganHumanLungs From 7a124612a1b08b0d46f9baa2025c764d1b3a08de Mon Sep 17 00:00:00 2001 From: Mnemotechnican <69920617+Mnemotechnician@users.noreply.github.com> Date: Tue, 2 Jul 2024 11:01:35 +0300 Subject: [PATCH 12/15] Cherry-Pick the Secwatch Pda App (#502) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Description Cherry-picks https://github.com/DeltaV-Station/Delta-v/pull/1237 All credit goes to the original author, deltanedas Adds a PDA app that lets seccies know who's wanted and who's about to be thrown out of an airlock without relying on the sechud and people having their IDs on them. # Media ![image](https://github.com/Simple-Station/Einstein-Engines/assets/69920617/37f5fa1a-27a5-4392-b4bb-be0f1016b499) (see the original PR for a better preview) # Changelog :cl: deltanedas - add: Security can find the new SecWatch™ app in their PDAs to see current suspects and wanted criminals. Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com> Co-authored-by: Azzy --- .../Cartridges/CrimeAssistUi.cs | 9 --- .../Cartridges/CrimeAssistUiFragment.xaml.cs | 3 - .../Cartridges/SecWatchEntryControl.xaml | 19 +++++ .../Cartridges/SecWatchEntryControl.xaml.cs | 21 ++++++ .../CartridgeLoader/Cartridges/SecWatchUi.cs | 27 +++++++ .../Cartridges/SecWatchUiFragment.xaml | 13 ++++ .../Cartridges/SecWatchUiFragment.xaml.cs | 25 +++++++ .../Cartridges/SecWatchCartridgeComponent.cs | 23 ++++++ .../Cartridges/SecWatchCartridgeSystem.cs | 73 +++++++++++++++++++ .../CrimeAssistCartridgeComponent.cs | 5 -- .../CrimeAssistCartridgeSystem.cs | 16 ---- .../Cartridges/CrimeAssistUiState.cs | 18 ----- .../Cartridges/SecWatchUiState.cs | 24 ++++++ .../deltav/cartridge-loader/secwatch.ftl | 5 ++ .../Entities/Objects/Devices/cartridges.yml | 22 +++++- .../DeltaV/Entities/Objects/Devices/pda.yml | 3 +- .../Entities/Objects/Devices/pda.yml | 24 ++++-- .../Entities/Objects/Devices/pda.yml | 3 +- 18 files changed, 271 insertions(+), 62 deletions(-) create mode 100644 Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchEntryControl.xaml create mode 100644 Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchEntryControl.xaml.cs create mode 100644 Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchUi.cs create mode 100644 Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchUiFragment.xaml create mode 100644 Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchUiFragment.xaml.cs create mode 100644 Content.Server/DeltaV/CartridgeLoader/Cartridges/SecWatchCartridgeComponent.cs create mode 100644 Content.Server/DeltaV/CartridgeLoader/Cartridges/SecWatchCartridgeSystem.cs delete mode 100644 Content.Server/DeltaV/CartridgeLoader/CrimeAssistCartridgeComponent.cs delete mode 100644 Content.Server/DeltaV/CartridgeLoader/CrimeAssistCartridgeSystem.cs delete mode 100644 Content.Shared/DeltaV/CartridgeLoader/Cartridges/CrimeAssistUiState.cs create mode 100644 Content.Shared/DeltaV/CartridgeLoader/Cartridges/SecWatchUiState.cs create mode 100644 Resources/Locale/en-US/deltav/cartridge-loader/secwatch.ftl diff --git a/Content.Client/DeltaV/CartridgeLoader/Cartridges/CrimeAssistUi.cs b/Content.Client/DeltaV/CartridgeLoader/Cartridges/CrimeAssistUi.cs index ea5aa3cf256..2dbe923b2a6 100644 --- a/Content.Client/DeltaV/CartridgeLoader/Cartridges/CrimeAssistUi.cs +++ b/Content.Client/DeltaV/CartridgeLoader/Cartridges/CrimeAssistUi.cs @@ -18,15 +18,6 @@ public override Control GetUIFragmentRoot() public override void Setup(BoundUserInterface userInterface, EntityUid? fragmentOwner) { _fragment = new CrimeAssistUiFragment(); - - _fragment.OnSync += _ => SendSyncMessage(userInterface); - } - - private void SendSyncMessage(BoundUserInterface userInterface) - { - var syncMessage = new CrimeAssistSyncMessageEvent(); - var message = new CartridgeUiMessage(syncMessage); - userInterface.SendMessage(message); } public override void UpdateState(BoundUserInterfaceState state) diff --git a/Content.Client/DeltaV/CartridgeLoader/Cartridges/CrimeAssistUiFragment.xaml.cs b/Content.Client/DeltaV/CartridgeLoader/Cartridges/CrimeAssistUiFragment.xaml.cs index e3163975d12..fb085a8a799 100644 --- a/Content.Client/DeltaV/CartridgeLoader/Cartridges/CrimeAssistUiFragment.xaml.cs +++ b/Content.Client/DeltaV/CartridgeLoader/Cartridges/CrimeAssistUiFragment.xaml.cs @@ -1,7 +1,6 @@ using Content.Client.Message; using Content.Shared.DeltaV.CartridgeLoader.Cartridges; using Robust.Client.AutoGenerated; -using Robust.Client.ResourceManagement; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.XAML; using Robust.Shared.Prototypes; @@ -13,9 +12,7 @@ namespace Content.Client.DeltaV.CartridgeLoader.Cartridges; public sealed partial class CrimeAssistUiFragment : BoxContainer { [Dependency] private readonly IPrototypeManager _prototypeManager = default!; - [Dependency] private readonly IResourceCache _resourceCache = default!; - public event Action? OnSync; private CrimeAssistPage _currentPage; private List? _pages; diff --git a/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchEntryControl.xaml b/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchEntryControl.xaml new file mode 100644 index 00000000000..2de8a37ff77 --- /dev/null +++ b/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchEntryControl.xaml @@ -0,0 +1,19 @@ + + + + + + + + + + diff --git a/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchEntryControl.xaml.cs b/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchEntryControl.xaml.cs new file mode 100644 index 00000000000..e8dd4eea446 --- /dev/null +++ b/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchEntryControl.xaml.cs @@ -0,0 +1,21 @@ +using Content.Shared.CartridgeLoader.Cartridges; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client.DeltaV.CartridgeLoader.Cartridges; + +[GenerateTypedNameReferences] +public sealed partial class SecWatchEntryControl : BoxContainer +{ + public SecWatchEntryControl(SecWatchEntry entry) + { + RobustXamlLoader.Load(this); + + Status.Text = Loc.GetString($"criminal-records-status-{entry.Status.ToString().ToLower()}"); + Title.Text = Loc.GetString("sec-watch-entry", ("name", entry.Name), ("job", entry.Job)); + + Reason.Text = entry.Reason ?? Loc.GetString("sec-watch-no-reason"); + } +} diff --git a/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchUi.cs b/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchUi.cs new file mode 100644 index 00000000000..da5ff825b91 --- /dev/null +++ b/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchUi.cs @@ -0,0 +1,27 @@ +using Content.Client.UserInterface.Fragments; +using Content.Shared.CartridgeLoader; +using Content.Shared.CartridgeLoader.Cartridges; +using Robust.Client.UserInterface; + +namespace Content.Client.DeltaV.CartridgeLoader.Cartridges; + +public sealed partial class SecWatchUi : UIFragment +{ + private SecWatchUiFragment? _fragment; + + public override Control GetUIFragmentRoot() + { + return _fragment!; + } + + public override void Setup(BoundUserInterface ui, EntityUid? owner) + { + _fragment = new SecWatchUiFragment(); + } + + public override void UpdateState(BoundUserInterfaceState state) + { + if (state is SecWatchUiState cast) + _fragment?.UpdateState(cast); + } +} diff --git a/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchUiFragment.xaml b/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchUiFragment.xaml new file mode 100644 index 00000000000..7fb2c42debc --- /dev/null +++ b/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchUiFragment.xaml @@ -0,0 +1,13 @@ + + + + diff --git a/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchUiFragment.xaml.cs b/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchUiFragment.xaml.cs new file mode 100644 index 00000000000..ad152840529 --- /dev/null +++ b/Content.Client/DeltaV/CartridgeLoader/Cartridges/SecWatchUiFragment.xaml.cs @@ -0,0 +1,25 @@ +using Content.Shared.CartridgeLoader.Cartridges; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; + +namespace Content.Client.DeltaV.CartridgeLoader.Cartridges; + +[GenerateTypedNameReferences] +public sealed partial class SecWatchUiFragment : BoxContainer +{ + public SecWatchUiFragment() + { + RobustXamlLoader.Load(this); + } + + public void UpdateState(SecWatchUiState state) + { + NoEntries.Visible = state.Entries.Count == 0; + Entries.RemoveAllChildren(); + foreach (var entry in state.Entries) + { + Entries.AddChild(new SecWatchEntryControl(entry)); + } + } +} diff --git a/Content.Server/DeltaV/CartridgeLoader/Cartridges/SecWatchCartridgeComponent.cs b/Content.Server/DeltaV/CartridgeLoader/Cartridges/SecWatchCartridgeComponent.cs new file mode 100644 index 00000000000..7ccc90ef797 --- /dev/null +++ b/Content.Server/DeltaV/CartridgeLoader/Cartridges/SecWatchCartridgeComponent.cs @@ -0,0 +1,23 @@ +using Content.Shared.Security; + +namespace Content.Server.CartridgeLoader.Cartridges; + +[RegisterComponent, Access(typeof(SecWatchCartridgeSystem))] +public sealed partial class SecWatchCartridgeComponent : Component +{ + /// + /// Only show people with these statuses. + /// + [DataField] + public List Statuses = new() + { + SecurityStatus.Suspected, + SecurityStatus.Wanted + }; + + /// + /// Station entity thats getting its records checked. + /// + [DataField] + public EntityUid? Station; +} diff --git a/Content.Server/DeltaV/CartridgeLoader/Cartridges/SecWatchCartridgeSystem.cs b/Content.Server/DeltaV/CartridgeLoader/Cartridges/SecWatchCartridgeSystem.cs new file mode 100644 index 00000000000..16da24514cb --- /dev/null +++ b/Content.Server/DeltaV/CartridgeLoader/Cartridges/SecWatchCartridgeSystem.cs @@ -0,0 +1,73 @@ +using Content.Server.Station.Systems; +using Content.Server.StationRecords; +using Content.Server.StationRecords.Systems; +using Content.Shared.CartridgeLoader; +using Content.Shared.CartridgeLoader.Cartridges; +using Content.Shared.CriminalRecords; +using Content.Shared.StationRecords; + +namespace Content.Server.CartridgeLoader.Cartridges; + +public sealed class SecWatchCartridgeSystem : EntitySystem +{ + [Dependency] private readonly CartridgeLoaderSystem _cartridgeLoader = default!; + [Dependency] private readonly StationRecordsSystem _records = default!; + [Dependency] private readonly StationSystem _station = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnRecordModified); + + SubscribeLocalEvent(OnUiReady); + } + + private void OnRecordModified(RecordModifiedEvent args) + { + // when a record is modified update the ui of every loaded cartridge tuned to the same station + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var comp, out var cartridge)) + { + if (cartridge.LoaderUid is not {} loader || comp.Station != args.Station) + continue; + + UpdateUI((uid, comp), loader); + } + } + + private void OnUiReady(Entity ent, ref CartridgeUiReadyEvent args) + { + UpdateUI(ent, args.Loader); + } + + private void UpdateUI(Entity ent, EntityUid loader) + { + // if the loader is on a grid, update the station + // if it is off grid use the cached station + if (_station.GetOwningStation(loader) is {} station) + ent.Comp.Station = station; + + if (!TryComp(ent.Comp.Station, out var records)) + return; + + station = ent.Comp.Station.Value; + + var entries = new List(); + foreach (var (id, criminal) in _records.GetRecordsOfType(station, records)) + { + if (!ent.Comp.Statuses.Contains(criminal.Status)) + continue; + + var key = new StationRecordKey(id, station); + if (!_records.TryGetRecord(key, out var general, records)) + continue; + + var status = criminal.Status; + entries.Add(new SecWatchEntry(general.Name, general.JobTitle, criminal.Status, criminal.Reason)); + } + + var state = new SecWatchUiState(entries); + _cartridgeLoader.UpdateCartridgeUiState(loader, state); + } +} diff --git a/Content.Server/DeltaV/CartridgeLoader/CrimeAssistCartridgeComponent.cs b/Content.Server/DeltaV/CartridgeLoader/CrimeAssistCartridgeComponent.cs deleted file mode 100644 index 741a6134580..00000000000 --- a/Content.Server/DeltaV/CartridgeLoader/CrimeAssistCartridgeComponent.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace Content.Server.DeltaV.CartridgeLoader.Cartridges; - -[RegisterComponent] -public sealed partial class CrimeAssistCartridgeComponent : Component -{ } diff --git a/Content.Server/DeltaV/CartridgeLoader/CrimeAssistCartridgeSystem.cs b/Content.Server/DeltaV/CartridgeLoader/CrimeAssistCartridgeSystem.cs deleted file mode 100644 index 06732c2c534..00000000000 --- a/Content.Server/DeltaV/CartridgeLoader/CrimeAssistCartridgeSystem.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Content.Shared.CartridgeLoader; -using Content.Server.DeltaV.CartridgeLoader; -using Content.Server.CartridgeLoader.Cartridges; -using Content.Server.CartridgeLoader; - -namespace Content.Server.DeltaV.CartridgeLoader.Cartridges; - -public sealed class CrimeAssistCartridgeSystem : EntitySystem -{ - [Dependency] private readonly CartridgeLoaderSystem? _cartridgeLoaderSystem = default!; - - public override void Initialize() - { - base.Initialize(); - } -} diff --git a/Content.Shared/DeltaV/CartridgeLoader/Cartridges/CrimeAssistUiState.cs b/Content.Shared/DeltaV/CartridgeLoader/Cartridges/CrimeAssistUiState.cs deleted file mode 100644 index dd820f1a0b3..00000000000 --- a/Content.Shared/DeltaV/CartridgeLoader/Cartridges/CrimeAssistUiState.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Content.Shared.CartridgeLoader; -using Robust.Shared.Serialization; - -namespace Content.Shared.DeltaV.CartridgeLoader.Cartridges; - -[Serializable, NetSerializable] -public sealed class CrimeAssistUiState : BoundUserInterfaceState -{ - public CrimeAssistUiState() - { } -} - -[Serializable, NetSerializable] -public sealed class CrimeAssistSyncMessageEvent : CartridgeMessageEvent -{ - public CrimeAssistSyncMessageEvent() - { } -} diff --git a/Content.Shared/DeltaV/CartridgeLoader/Cartridges/SecWatchUiState.cs b/Content.Shared/DeltaV/CartridgeLoader/Cartridges/SecWatchUiState.cs new file mode 100644 index 00000000000..068b54a6ffb --- /dev/null +++ b/Content.Shared/DeltaV/CartridgeLoader/Cartridges/SecWatchUiState.cs @@ -0,0 +1,24 @@ +using Content.Shared.Security; +using Robust.Shared.Serialization; + +namespace Content.Shared.CartridgeLoader.Cartridges; + +/// +/// Show a list of wanted and suspected people from criminal records. +/// +[Serializable, NetSerializable] +public sealed class SecWatchUiState : BoundUserInterfaceState +{ + public readonly List Entries; + + public SecWatchUiState(List entries) + { + Entries = entries; + } +} + +/// +/// Entry for a person who is wanted or suspected. +/// +[Serializable, NetSerializable] +public record struct SecWatchEntry(string Name, string Job, SecurityStatus Status, string? Reason); diff --git a/Resources/Locale/en-US/deltav/cartridge-loader/secwatch.ftl b/Resources/Locale/en-US/deltav/cartridge-loader/secwatch.ftl new file mode 100644 index 00000000000..a5b96eab08f --- /dev/null +++ b/Resources/Locale/en-US/deltav/cartridge-loader/secwatch.ftl @@ -0,0 +1,5 @@ +sec-watch-program-name = SecWatch +sec-watch-title = SecWatch 1.0 +sec-watch-no-entries = Everything's calm. Why not enjoy a Monkin Donut? +sec-watch-entry = {$name}, {$job} +sec-watch-no-reason = None given??? diff --git a/Resources/Prototypes/DeltaV/Entities/Objects/Devices/cartridges.yml b/Resources/Prototypes/DeltaV/Entities/Objects/Devices/cartridges.yml index e3d5e9d2138..def215cee43 100644 --- a/Resources/Prototypes/DeltaV/Entities/Objects/Devices/cartridges.yml +++ b/Resources/Prototypes/DeltaV/Entities/Objects/Devices/cartridges.yml @@ -17,4 +17,24 @@ icon: sprite: DeltaV/Icons/cri.rsi state: cri - - type: CrimeAssistCartridge + +- type: entity + parent: BaseItem + id: SecWatchCartridge + name: sec watch cartridge + description: A cartridge that tracks the status of currently wanted individuals. + components: + - type: Sprite + sprite: DeltaV/Objects/Devices/cartridge.rsi + state: cart-cri + - type: Icon + sprite: DeltaV/Objects/Devices/cartridge.rsi + state: cart-cri + - type: UIFragment + ui: !type:SecWatchUi + - type: Cartridge + programName: sec-watch-program-name + icon: + sprite: Objects/Weapons/Melee/stunbaton.rsi + state: stunbaton_on + - type: SecWatchCartridge diff --git a/Resources/Prototypes/DeltaV/Entities/Objects/Devices/pda.yml b/Resources/Prototypes/DeltaV/Entities/Objects/Devices/pda.yml index 6ee3a7543f7..d9607390cd7 100644 --- a/Resources/Prototypes/DeltaV/Entities/Objects/Devices/pda.yml +++ b/Resources/Prototypes/DeltaV/Entities/Objects/Devices/pda.yml @@ -20,12 +20,13 @@ map: [ "enum.PdaVisualLayers.IdLight" ] shader: "unshaded" visible: false - - type: CartridgeLoader # DeltaV - Crime Assist + - type: CartridgeLoader # DeltaV - Crime Assist + SecWatch preinstalled: - CrewManifestCartridge - NotekeeperCartridge - NewsReaderCartridge - CrimeAssistCartridge + - SecWatchCartridge - type: Pda id: BrigmedicIDCard state: pda-corpsman diff --git a/Resources/Prototypes/Entities/Objects/Devices/pda.yml b/Resources/Prototypes/Entities/Objects/Devices/pda.yml index 706cbd5dbbf..7155be68d74 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/pda.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/pda.yml @@ -173,12 +173,13 @@ accentVColor: "#A32D26" - type: Icon state: pda-interncadet - - type: CartridgeLoader # DeltaV - Crime Assist + - type: CartridgeLoader # DeltaV - Crime Assist + SecWatch preinstalled: - CrewManifestCartridge - NotekeeperCartridge - NewsReaderCartridge - CrimeAssistCartridge + - SecWatchCartridge - type: entity parent: BasePDA @@ -430,12 +431,13 @@ borderColor: "#6f6192" - type: Icon state: pda-lawyer - - type: CartridgeLoader # DeltaV - Crime Assist + - type: CartridgeLoader # DeltaV - Crime Assist + SecWatch preinstalled: - CrewManifestCartridge - NotekeeperCartridge - NewsReaderCartridge - CrimeAssistCartridge + - SecWatchCartridge - type: entity parent: BasePDA @@ -643,12 +645,13 @@ accentHColor: "#447987" - type: Icon state: pda-hos - - type: CartridgeLoader # DeltaV - Crime Assist + - type: CartridgeLoader # DeltaV - Crime Assist + SecWatch preinstalled: - CrewManifestCartridge - NotekeeperCartridge - NewsReaderCartridge - CrimeAssistCartridge + - SecWatchCartridge - type: entity parent: BasePDA @@ -664,12 +667,13 @@ accentVColor: "#949137" - type: Icon state: pda-warden - - type: CartridgeLoader # DeltaV - Crime Assist + - type: CartridgeLoader # DeltaV - Crime Assist + SecWatch preinstalled: - CrewManifestCartridge - NotekeeperCartridge - NewsReaderCartridge - CrimeAssistCartridge + - SecWatchCartridge - type: entity parent: BasePDA @@ -684,12 +688,13 @@ borderColor: "#A32D26" - type: Icon state: pda-security - - type: CartridgeLoader # DeltaV - Crime Assist + - type: CartridgeLoader # DeltaV - Crime Assist + SecWatch preinstalled: - CrewManifestCartridge - NotekeeperCartridge - NewsReaderCartridge - CrimeAssistCartridge + - SecWatchCartridge - type: entity parent: BasePDA @@ -979,12 +984,13 @@ borderColor: "#774705" - type: Icon state: pda-detective - - type: CartridgeLoader # DeltaV - Crime Assist + - type: CartridgeLoader # DeltaV - Crime Assist + SecWatch preinstalled: - CrewManifestCartridge - NotekeeperCartridge - NewsReaderCartridge - CrimeAssistCartridge + - SecWatchCartridge - type: entity parent: BaseMedicalPDA @@ -1001,12 +1007,13 @@ accentVColor: "#d7d7d0" - type: Icon state: pda-brigmedic - - type: CartridgeLoader # DeltaV - Crime Assist + - type: CartridgeLoader # DeltaV - Crime Assist + SecWatch preinstalled: - CrewManifestCartridge - NotekeeperCartridge - NewsReaderCartridge - CrimeAssistCartridge + - SecWatchCartridge - type: entity parent: ClownPDA @@ -1092,12 +1099,13 @@ accentVColor: "#DFDFDF" - type: Icon state: pda-seniorofficer - - type: CartridgeLoader # DeltaV - Crime Assist + - type: CartridgeLoader # DeltaV - Crime Assist + SecWatch preinstalled: - CrewManifestCartridge - NotekeeperCartridge - NewsReaderCartridge - CrimeAssistCartridge + - SecWatchCartridge - type: entity parent: SyndiPDA diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/pda.yml b/Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/pda.yml index c2fd8786aff..4e6115ba339 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/pda.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/pda.yml @@ -32,12 +32,13 @@ accentVColor: "#DFDFDF" - type: Icon state: pda-security - - type: CartridgeLoader # DeltaV - Crime Assist + - type: CartridgeLoader # DeltaV - Crime Assist + SecWatch preinstalled: - CrewManifestCartridge - NotekeeperCartridge - NewsReaderCartridge - CrimeAssistCartridge + - SecWatchCartridge - type: entity parent: BasePDA From 2dcab4d57f74e25f4a1aafa23f48463ad6251516 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Tue, 2 Jul 2024 08:01:57 +0000 Subject: [PATCH 13/15] Automatic Changelog Update (#502) --- Resources/Changelog/Changelog.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index e4e812edeb4..cd2ca0c929f 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -4271,3 +4271,11 @@ Entries: message: Fixed loadouts becoming uneditable after spending all your points id: 6134 time: '2024-07-02T07:18:27.0000000+00:00' +- author: deltanedas + changes: + - type: Add + message: >- + Security can find the new SecWatch™ app in their PDAs to see current + suspects and wanted criminals. + id: 6135 + time: '2024-07-02T08:01:36.0000000+00:00' From 2e8e56f763a5cda63511a1aaae0d649ff64eedad Mon Sep 17 00:00:00 2001 From: Mnemotechnican <69920617+Mnemotechnician@users.noreply.github.com> Date: Wed, 3 Jul 2024 22:48:28 +0300 Subject: [PATCH 14/15] Fix Clothing Quick-Equip (#507) # Description For some reason, ClothingSystem.TryEquip would return false if there's a do-after to equip the clothing. This had caused all quick-equip attempts on SMALL ITEMS to fail and ended up with every SMALL clothing item being equipped into one of the pocket slots (which have no equip delays). Also fixes quick swap - see the comments below. # Changelog :cl: - fix: Equipping clothing using the Z key works correctly again. --- Content.Shared/Clothing/EntitySystems/ClothingSystem.cs | 5 +++++ Content.Shared/Inventory/InventorySystem.Equip.cs | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Content.Shared/Clothing/EntitySystems/ClothingSystem.cs b/Content.Shared/Clothing/EntitySystems/ClothingSystem.cs index f189db005bc..976682c9903 100644 --- a/Content.Shared/Clothing/EntitySystems/ClothingSystem.cs +++ b/Content.Shared/Clothing/EntitySystems/ClothingSystem.cs @@ -62,6 +62,11 @@ private void QuickEquip( { foreach (var slotDef in userEnt.Comp1.Slots) { + // Do not attempt to quick-equip clothing in pocket slots. + // We should probably add a special flag to SlotDefinition to skip quick equip if more similar slots get added. + if (slotDef.SlotFlags.HasFlag(SlotFlags.POCKET)) + continue; + if (!_invSystem.CanEquip(userEnt, toEquipEnt, slotDef.Name, out _, slotDef, userEnt, toEquipEnt)) continue; diff --git a/Content.Shared/Inventory/InventorySystem.Equip.cs b/Content.Shared/Inventory/InventorySystem.Equip.cs index 24006b0c9f9..7bdd17ee6fa 100644 --- a/Content.Shared/Inventory/InventorySystem.Equip.cs +++ b/Content.Shared/Inventory/InventorySystem.Equip.cs @@ -176,7 +176,7 @@ public bool TryEquip(EntityUid actor, EntityUid target, EntityUid itemUid, strin }; _doAfter.TryStartDoAfter(args); - return false; + return true; // Changed to return true even if the item wasn't equipped instantly } if (!_containerSystem.Insert(itemUid, slotContainer)) From 6aaf4664ad1b9d150da9af30c27bfc31858de8d6 Mon Sep 17 00:00:00 2001 From: SimpleStation Changelogs Date: Wed, 3 Jul 2024 19:48:50 +0000 Subject: [PATCH 15/15] Automatic Changelog Update (#507) --- Resources/Changelog/Changelog.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index cd2ca0c929f..c4056561c9c 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -4279,3 +4279,9 @@ Entries: suspects and wanted criminals. id: 6135 time: '2024-07-02T08:01:36.0000000+00:00' +- author: Mnemotechnician + changes: + - type: Fix + message: Equipping clothing using the Z key works correctly again. + id: 6136 + time: '2024-07-03T19:48:29.0000000+00:00'