_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>
z>$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<1nK*zRfE;x>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](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'