From 368d4dd273a740998a298088c8a3df26f30877b0 Mon Sep 17 00:00:00 2001 From: Schuyler Duryee Date: Thu, 2 Oct 2025 01:51:20 -0700 Subject: [PATCH 1/7] Add utility knife/box cutter (#39567) * add sprites for box cutter * move box cutter to melee, add yaml * remove unneeded soundHit yaml * add opening sound effect to box cutter * modify sprites to look more like actual box cutters * add BoxCutter tag and add to belts * rename box cutter to utility knife * remove accidental backtick * move utility knife to correct place in tags * remove SECOND accidental backtick?? * Fix utility knife arbitrage by reducing steel to 50 * Reduce damage to 4 * Reduce knife bounty reward to $2000 * modify utility knife icon to be larger * Make utility knife extendable/retractable * move slicing out of ComponentToggler * change utility knife extend/retract sound * Use TiniestShark's larger inhand images for utility knife * utilty knife is now only Slicing when activated --- Resources/Audio/Weapons/attributions.yml | 7 +- Resources/Audio/Weapons/utilityknifeclose.ogg | Bin 0 -> 11804 bytes Resources/Audio/Weapons/utilityknifeopen.ogg | Bin 0 -> 11134 bytes .../Prototypes/Catalog/Bounties/bounties.yml | 6 +- .../Entities/Clothing/Belt/belts.yml | 2 + .../Entities/Objects/Weapons/Melee/knife.yml | 64 ++++++++++++++++++ .../Prototypes/Recipes/Lathes/Packs/cargo.yml | 1 + Resources/Prototypes/Recipes/Lathes/cargo.yml | 7 ++ Resources/Prototypes/tags.yml | 3 + .../Weapons/Melee/utility_knife.rsi/icon.png | Bin 0 -> 349 bytes .../utility_knife.rsi/inhand-left-blade.png | Bin 0 -> 150 bytes .../Melee/utility_knife.rsi/inhand-left.png | Bin 0 -> 226 bytes .../utility_knife.rsi/inhand-right-blade.png | Bin 0 -> 161 bytes .../Melee/utility_knife.rsi/inhand-right.png | Bin 0 -> 231 bytes .../Weapons/Melee/utility_knife.rsi/meta.json | 36 ++++++++++ .../utility_knife.rsi/utility_knife_blade.png | Bin 0 -> 190 bytes .../utility_knife_handle.png | Bin 0 -> 278 bytes 17 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 Resources/Audio/Weapons/utilityknifeclose.ogg create mode 100644 Resources/Audio/Weapons/utilityknifeopen.ogg create mode 100644 Resources/Textures/Objects/Weapons/Melee/utility_knife.rsi/icon.png create mode 100644 Resources/Textures/Objects/Weapons/Melee/utility_knife.rsi/inhand-left-blade.png create mode 100644 Resources/Textures/Objects/Weapons/Melee/utility_knife.rsi/inhand-left.png create mode 100644 Resources/Textures/Objects/Weapons/Melee/utility_knife.rsi/inhand-right-blade.png create mode 100644 Resources/Textures/Objects/Weapons/Melee/utility_knife.rsi/inhand-right.png create mode 100644 Resources/Textures/Objects/Weapons/Melee/utility_knife.rsi/meta.json create mode 100644 Resources/Textures/Objects/Weapons/Melee/utility_knife.rsi/utility_knife_blade.png create mode 100644 Resources/Textures/Objects/Weapons/Melee/utility_knife.rsi/utility_knife_handle.png diff --git a/Resources/Audio/Weapons/attributions.yml b/Resources/Audio/Weapons/attributions.yml index 310b01b728..989e2472f6 100644 --- a/Resources/Audio/Weapons/attributions.yml +++ b/Resources/Audio/Weapons/attributions.yml @@ -82,8 +82,13 @@ license: "CC0-1.0" copyright: "Taken from ScreamStudio on freesound.org" source: "https://freesound.org/people/ScreamStudio/sounds/392617/" - + - files: ["pop.ogg"] license: "CC0-1.0" copyright: "Taken from 0ne_one111yt on freesound.org" source: "https://freesound.org/people/0ne_one111yt/sounds/478213/" + +- files: ["utilityknifeopen.ogg, utilityknifeclose.ogg"] + license: "CC0-1.0" + copyright: "Taken from FilmOrbit on freesound.org" + source: "https://freesound.org/s/554299/" diff --git a/Resources/Audio/Weapons/utilityknifeclose.ogg b/Resources/Audio/Weapons/utilityknifeclose.ogg new file mode 100644 index 0000000000000000000000000000000000000000..8c620d216516f0a1f27a8dfd90f919f1dad0d18e GIT binary patch literal 11804 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 literal 0 HcmV?d00001 diff --git a/Resources/Audio/Weapons/utilityknifeopen.ogg b/Resources/Audio/Weapons/utilityknifeopen.ogg new file mode 100644 index 0000000000000000000000000000000000000000..5053c8089c64d90bcae231110a8fa70c038f73ea GIT binary patch literal 11134 zcmaiY2Ut^2v-b(TOD_r#DBS zP|m!~kdnsfU~)jHt85>^WyBE7&|^ckSZL zOLe8-%g+p?5blBoDGM)WCp@~foc}ud)(Wg@NQP3dYD7^PF{))=+C*ab)NKH{nEFpc zetr%pxEC1`HVaxAvNQJ2;kn7KAgjN}f&y6Zn81TLMuiH--U{~qVQ$sm0_qH6!yiN;35FnEanKTc7 zb@k$_Z^&1K!J)+jfW?_gpycsa;qk8(a;)t$ROeFw2sq`eWMc5S z|D#&zCRzU9Rm!G|50CB23C;_h@6AU)S`7XaE+3MJ6)D*C`pwA1YlSRc5{ zcH@-$x0Nsa%Lr#?2LLGqd%FvJH>eGi;73<6Z8ynrH{ID+!$NJnK6YKZM`vN7CRIG7A_}KE4anOu6>9AUWmSg7yP! z^Pnx^JullcUk>5j1{A39Ie&ZJ^eLnz1tZ`X+hQtB2b(E44>N)%Etu2+*Xj=8f8@Vq z1bbn)lxx**HUIMa2NnfJsRQqjbKr`w&nb3q$qm8Yfko=ie)6-i{|+B1&~By^tQ~2A zP~T`0Ge*u_&VG9{_P>S%Jza9k| z6>1SHO~Q8WB%#T!J@7oxEB@1PzqkkKIEMeD4sNom)AN9JSXfX)L=vru*7kJJec|z? zHpFnkV`kiUW<1K6CG@`o>%Tk)0G%fI+$V8nk%-RJphq&~e+~RE&v9YwjAQSP<5sHV zRv8iK|1GMzB|6L?r!K0Z!DKkhM#*7N zq3&`l|7idKXpN;(I*%jjD8W&b*eFU6ttt7xdkjb&6;=5t3Mw`c0Kj<81sXY+HrzE< z#!*s-4Do}TI15RV^?@}wk5+^VNqyBlR{EM`T|BalYHJn+W0F-4isHE$4W)jcYoM?o zK?a6BB0wDgu!t_i2Ugbsh3-t*0R(v(t_yiBCt*YZE||nB0_Vx4H=j>^J)+Q^jbl{` zPs^q^4=Vu|0i@uMGHWQ72_nS^0A^Gu3U~+(H30t+i|Rovu%i@_d8rx$NHUJ#9t25R z5G_21U1I>=$sXJ%y^tC-Bn<-qXe$K#$-qP{ox#NIN@||->8){ol?xA&={q)B}=5~GOSkE|*k9vSq(=kiaT8|kR29L3Q zm0yU56&4m0);JWFmgv7)DtuMgQ)yjTTHI4vR#a-g3Q|k+3o8W*3k8ZQi;oHgR%`ML z>q~kn%Tr2=R%Yw*j&*GD-!qkn&auXWJ1s0pDJ)v8bmVU|%IMcx?$Vgqu94Tc`6 zEKYs`tONug;ap_Ypyg|ay3?XopxK%T5>B^AitX$;HAP!a+$X*csAjZ6S84*iq7583 zf+EezQB$VSf*y3d54%UDRpfvjEz#Vab7B*vrqQWMTt1w|_=z-!_amBC#pDprJ`^z0F1sVI9f za91F!ctv}`4n2M4Y7bgH%JW^7RBPGUmUMu^d2(2l6f3Hk?Hmz5E-GS5&V(1VGwVl# z!Zqx~a>s1X2>K3^V|X{klCe*yD3D<8&@_to+4$GV&1?lb#>`62g!5G-#)HCteAbIZ z;zrCsR`IAvaD~48+uS5ukbp-;RR8$wW-qq;Nw4@!h7$OOaEp1nqXkACEFmC;CAZ8x z3n6E2EBzcbpn#!u?L+dB%k&|y6}T$Pz~SgVX)>Pb0VEvWK87UY$zfLF6KvPAgTuj7 z2!eUXx!aPcgtbE`sCCH!S2AX$p2QpR*sr>9B(v`Wr_~sLZGkp-^{CVLrNGWyNa+0iZ@p zJU}SqwD;-RmQ+nhk(Gpu2`lk{P_QcbkgUfK0Bhie*3RPy4-iWVNU^>K~WDlm{>qrfvks)IOw*kJZ`jB8lD+3b1d@m~qY;tfTX9SeuG87zx=eVB{a3~4@ z;By8uqH=W$x4^heFlG_}-e)mW5lNbblZSUeaq%cn9C)MxS1M3m{-^c&R+5err|8G5gyAlv`|JeXiEfl1{ zDd{Dx2NLj$lmcgGq@@89y|!d<$0QuVq41^bV9-2S_Z5*a9uOsPI0zrmqj7qQFWpcm zKAxPUv(WKLPf-x$P0EuqhOz~v+#<`V`gA60Li!;*XG||b5Og_3@X;(%EEEM!X`e7F zMr4nmK>uVlF9sb*&ko$Wogln=%q+4R)IS&@#>^tb#`GwGSx098`>@<4G%@?l`{CJh zTXTZRw#>P<&n^Zi&=#3zXyKGq1W|Q{5zb)H41dRhWB+T6_SWKGXn}xQ{5ub)CUXug zvMg{6&H;i9cHZLwd*pu;xN|TD(}SrT4&?lI3`Y;jI8X0zs53-@syQQ^L-o8z&UvP; z^U0il*Pi8qAVdkzqA=GI_v@ak_M&s|3Ds=66ag$10Ju!puENKq10tgD^uiQW6rI6tBN#$}Hn@u_?zs*XJwsu@E3;dGj)6%R zDV8cKsw#qVNw}5RaLNN33?<@x-VR}m#Rf4rKK@3nTKA6pmRt_a`E7d^04@VSJT>&{ zRXj49CgwscZ5&-ZeF6gxgf9S;L$DVBEI0A<=g+O8U$@N@a?4r-XMgxk#B)wQYskp{ zUR8+B`~Td=Z~rBq-Nw(v$cX4rN?b=Egnq*LuOSd(ANjBGT@$(?B02?!!33`hO~ZJ2 zU?SIrW<*60-}r<|mh*3I9UA=xu{&CpaXMTEhQI1|7=p@83B1ZcHly}(ex7l>w0J*MW~D{+k0For%(NhfgE$7($72ffx6cBi_$M`M8|9OrmrLew}eVw z5ok;rvrbnD91&IWP<29VZ`fd=jN~tW@lKy^x=j@q5NY{1m~fO^#Rs%NCTA5< zAuLdmUub#qkKQ1TR2|jfICE>*-azr5rFM}*Bn6M?xI*RT_r&qtlQ{u>6=;%Lm6qC_ z16oHeQ9Zk%bX}q38QiDc#k6>z$djuInL=$9?YevEt05IGROR_k?{z2`eb^)Te1P19 z3^u5_4zIJ9yOS@@`FzqYhDZ@(m8^DVGEQAwD*Y!nDUz8t+-j9WR9b&CdrRyrs_%tQ z(L8sXipkSkMyj(Ul*_iWtL2{@+>;)7C1gZmqQcsH5t;3A1?@}#9J7|$MoukJ3x7sZ zntYRaMlz>(d2>lF;1*BfXnCKzR)@sh`PUN7_aH=cy$AM~!7a%9&xNB<`U|(0wo_rD z&l3q_e-BS1LJT0V6*8)EG$YVXEkIlbp`hn~pmz6B>xXwl?kH(u^$(DlS~a`M>KCSq z-u=G!sXAC7224ujH4Z2{(GBa1`4)ZM_}s6iOPHOp`Vzxxzd`dmVI8^6nj$HzpQD@o z`um>40UW}MjHF_|(6k1+pNM5qy)wb9o^dx4>DXf7ml|cunsb4fdK5;qtdd0y19$uA7J~VbO zrqfu`Phf5C^#yI2m^vcPgm7oaC-OttWba;awW$n+xMG+wx}9kDJiJ35A1l1mbFhW(&BSfY9?b4*>Bg9B7_ zWwb-e+!Lzy(y^`*$qjF~;0~8Q8Btc=PW*K9XG9i#gazTF1cGhWGV|Y|kElm>o;2|R zF+^0If*#ayY?th)CDW%*2h~$AAN4-dWfi0Vwi&(X%3l&0yoJcp$`A{g;+0d9aZIoJ zxwJO&>)DRtqgU>@r-ZQGVJpid!7UP&`4Pvq@0~<7NAjk>UKKg`z*3TTVuBz}`BJ?6 z=)Rp0nVhAzIOI+A+CYzdR{rFShTY@U3x&E ze`BuFwC6*7{%y~aYJ$Y-v26W6SARqAU%XgYI-loQw!iTEW{KbNG+?(2*;F&)GLS-N zQE)gj@Xoz$zd@K)oP+~t-(4W4V)CLRS*;Y0Y)Ez?ptBT`_%vt7xM1`e=KOUAoAN%u z{>g~go}kekfRU-!l%Q?6+%Hw+;u2w7)vr-J2ZZ{YQ}+G6=+k(%>8yaPCKoFs2sn?G z<+VLk!Mrms$r9RGye0q5Q07$SEmoh5OP|+{o?oX9;o*=bB;x7i6sOQBKSXBIU*vt( zT$U%1E`GR{(5XG~tuNDK_`}cHMXLL;`ybrJWdR%^ve%BQdO~5Z#+b%%T;XO7o}BuSk!Xp)-O(A9%8B6s{~BK z74xo7sOn3)wVWdHKYksr`ORhAXgOZ&$@Sb{-S#u(8x64iMuEL{?=G%Ocx$Iq7mZe6 z;mp{w+hcCwon6dPYySR@G~>@Czm%Z*rUqOYBf6ulg@*iE=!x%tal2Gy^HR;xUKXnn zN_ZbZJX`(vy)+gR7vLitQV_rHbeX}b->E$P>#8n4^R|-G<&Z$*45ot-$)d56?XfxM&sNt|RcB$XE?eTB)CYPXkLG*t|z5 zs8IZB;T64c$cV%&FWq9T%QvKFB_9^vTqA}m$l@{6SEXF?%Qf5<1C%un{! zYm-P}Rmn;b+~meifIO9WOAM!nv+2IKa7iV^bC+|F#QVZQ;yX&}d_#s+)@|A{;?~$n zsfaBWg5=inQH_aRO)F=$LhEVTi%iDbVRM%uQxUTs5KX3tu&njRWFzYLc+{e>R}gk) z6{T8FZB*yPR}7v7+^tJ%JUT9e2QY=L)n5{ryXY+o-~_!icI|(WkpH1p8&G(<1yi;y zF#GnW=BQz^`q6_j7xP(1x@{iEgfOCPK0g`@q;X8(vTkVNVbX`RQ-8c$bH=LvcXXk| z2Rr?`0rs-mS|~c?9;{oU)8%QGC@BHTa?0e}a!Ml=%jLqk^-I3g&%CE~yI7zG7fHWa!p)vfb`sYNMc&2tM|We|=iU2jFY=a5?&ZZVZ)7X! zI^EK5leropqF_vI+xXEK@_8PrdO)w6KAu zrZ7(nna<#%WH)PU+n~@dJB5R%;e6z!CXk=kq`zLwAFXw>GyF)T!h|K!onyY|?#AVu zfj#ncyA*D|)mu@_R7n8L9F{<%@!-IVy93@ZvZC*bPhs#>>TeyMmwJi3({nTIW3N*Jn#eMS^@!?>z*lPk zMwe3Uo`-CAp>TTM=JWoLy}XDUjhUM_;=e?BCMX&oLZ~udyQvbmOO}m$XNJp28?#!F z^`16zP-}E35f$o5jsLMzV}Vs%cgOBc?4~?poD>@{n7>3oSjjYHLNjq=OBh|&_t<-D zdEFh4so_8}XcOl$Ir4?-Pbw0c5Z2SmrY7r(S`x!L7@8Jp>L+@@@^5VJ5F7;M?M zR;meuk(FO}{)zbcg0oG{BD%*TplCOy?(_csRZ1tzj4YAMsg_EL=_MHjQMq9j{i)p? zKMi(;Dw`B;q5*91t6-5Z{{7YW>bzKz466zQZiTqnUQ&(a(Dx!nmu7QMDj&)(I7;2k zn~YyH)|!HtJd=gll`xOLlga1)Ez>dv(3MBk*6;9D~UR=9_^Y z4?=*7+$-YpvVv^C`271reF9#xyNgd$*yE(tUv-M#j=Ji++$+NRU=)bINTtl_6{bh{ zozPDa%B9n$Ify4=xOZyru80);T@H0j_;xB@82Dt>BU1E5`aO522uLup_xQ3y)hZSA zJA>$RPOb^ZUj=p#X}H_tq8ys3PE><@2YG94qT54nei0iU|FeoGqso@<#q`)X+?7Sy z>U|+wiWO~vMf8_{6?V6({^ej!^l>qH_;cm&>BcA_fVSW;cRQ1U{335(neKoIL6bI< z-mq=kmu0#eZWG?=4eD5hkUu?p#H&(jHrYCKg{~%BJ72owXEFwl2Ms6x>}CJvIDX8R zl4uup_>qQ(9NI=V+$pFm5j4F zII~K=D1+0375@6Sa=_=lk7h;$9mYfjS_aNC#zPY|7muVMH!{T_cAdKBLr!g(I|lS! zB7bg0te=QK}2hwfmB-WOeVEX=Ps6PW-|EWHEZKrN)pUb9NI$Vp{PB zSaJyUJ;&N(%|eg)6P61chsYbz;a$^DIQsS%gex**xkR!PE5y=Z*yKoTr!DxY*Dnmb zeJOu)HRL9cVR-8ow%g3ya(7kU?`Hou`KULp#T*nYIj&(r__)0yk(nS#-u{^RrpRup z{m1ReBE4{GpC=B3clAFxJBpfK_xmNnSNDL3+T5tmF&!U}jwp->SuO`vsrbj9lTDq-G`7FbDcu(S* zB?8f9HIy_L9OJs9@@Kb?7i_#ujK#HdlZX(cf)CiD+Pp4Nb~2O6KLu)YjR-VO;vs?- z)*Bz?$XD}Tr3kEioc2mR?xCf&6;D&6gaj`dUZ0R8=A#i|(I^p#{ls_-qfDgA>@fYR zne`wz$m8}UeM)$e8BI>|b+52s`qpR9y9w6>luE)y`#JIikA{Q@ey>FniE)pIDq0a$ z+PvbZd#tUqC%i$kCg4RBPT_J*X#GXM5Ua&w-yw(5e15L}IeX({MPMX0rU+JpI%XtFo_e^MFe<>{A3_Iv|B{6Ic`KMSH}`8j=e^DBg*Y zr(rMDW)#=Ek5dkABihIWzkGZ_+Mrq2PPi=;feZgiY_22bkt}8Mboz)MB-D{nSA+M z9JlB738tXErbi`{3t^ZFLfHhSR-{kj>+GVbs$n&)M)Ez6I{x>0X$q&#-++S$U4%2? zp+q>2GGT1?K#cv2U$)4G$+WA-o1Z(@b{UfFuJxF5sLi|EvB0{H-!Or@!;=F=JZXO;%F)`t~7pc<5S=6m+ zFy#_7i6&pV!R1GWOK%OnX|KABr~K5{#{2a$)O|k4lwoPMhJP8q}aghksd!sPoI}l$Okvq}mYJbMwmu?H?ylZgv zzDkE>Raf`i*~tdd2F!zpo`j-I{!ju_p`cjV!$NF+N9uZekv$!^z=zx__XFlCx>8Sp zOA-vCO?T$KAO>`0C;>T2g^zx`0j{1TygEE-&; zsP%_3F9ZQ)1!Mlt<*X#n`>&CzaV|MU^C?$iN`1b+XF7e8+bBSFmsr2aZ(myS(NBZ; zsuc@@TjG7i-pwj2v+BWo@Voc69vT0*lolGR1WBME?Ou*2ysrf9#|Mx?*0qaFe~z9M z>u@u()1n8NTBk`Zs*;Cb^B9Wy!(8F{+oDwB*3G|pWTrz_>*11 zK`Ot|U&6{O-Ef0or;x1>=FyUV#boXnep#fG69PWoXOLunbHyRl=V&or+~?jO&yx*l*0)tN zo4>TovY)F})^E=+xzuGuF}96_uW_^ArOIc^ojiI9OzUuX3BR^3@xG%+@$*&xK;!7g zI3L8MsXK1p?rRLKUwz5*&oEgoO-5zI9!V!(dX*-;r%5o0T7rqUqet;knYWOp1z>`! zlazIN&aw3;)ASm4jEy5JvDa;q8fa@WyrWzsC#lcrY#6B#YR{-kJ6w8$oWlAU&8!_| z0&qE0_F7Y@MOW!mh>DqaCSDj@!8dBIrSd~zcBIg-j@d8gTIBc-$A+)l6P`z}-we{n ztn_P=#Orv9f$Q23lzECa0?^ix8h&Ud&mJ=Hq{dn{ANq+P8EvF|~<>3k*qq`A7+6l-W&%xnK=KhgLhuvamn! zy1u*G->Sk_I;fS|hAXRD39DSUo)Rnu5au6ijo>rmrVd7=-d7A>p5T*sf(M$x*PZ7T zU8)!YOv3BVvRe>kJ^`PDSS~@rq>?cS1-q7(ov|-PDa{v2(@q*URJCFjHR>D^m0G|2 zGFPlQQ2T8m2=mqG$;Bh_GtcsfM});urFPrB+vv@dZ)!i2l49;DBB=n-8lmJi;RIQB~12^y48g=SEjgQW7wwXTIDYjmUZ~ui>m}# zqpch(`Muv&i(2MxM!evtTJeU^+3GmFBn+WwE-{*uQXA6l;PojG#&MI)Z3G1#{O(i# zr9rrLmxS8;NtyFfWw^`)Wz4>RibKtJ*IE{{n<8~6C;pd)IeMJ8V3~7vz;sCDv!hG% zKOP!|LS5FovV>?`v!k*f{SMCuls~_0KWbU6FHgUt5LMKO$R=+~?k zy6Ve%L5-Oz&9ewIN9P38bIvEe_W`%L_TrFVL8>8Z_p#1bd6<-5d|DW%6-lO?=gjfJ z=Md7pn&+352TqSAf1o_ZX)gBY%qG8he6X-Z6?rSHt+y<`LNJ+b=x41UyGwL);tx*G zTQ7zN#htEVue@j>FORaSkf2f5|oRvT9W^ zPp^=TKKmo243w*(8xrxs#`2GhzM*kIV0F91qoc>Ye@eW_fUyvR((M=7=A0b)Y*&~C z2Qso4r0U|E)!@1qz`n^(dt=>Dl+|y;)-7-jP1*2lWT}`~lUeMlHMda)PiWwe$?xso>`lwI0cjX=JlJ@B%*WsBaii#8ocNc&ZISg zXwLzPT&>4^)*R23U-b-d#&e%29Vr|RAQir;Zn!=JG^Z@vIU4Mr3?@wm(d^P6ZGVcI z<~Q)%E@cED*E5W=?=?Mh2c{&%cv<}yzpV$QBcx(vH19{fR>08vBJSN0FOfP3$$BS` zCRmebYJ*IsCu>pozxh1GZ!*T;kbSMu`H$U*;V@kIH7`M?ur#nH(N0yI&`cXAJ_UzJ z!y@mhTHI#Jl6kr;vR1fMOBNj>her_{--)VBmmir9-a3^C5RHAq;6QCqk$UpfFp+PI zDGZUON*m1*?OIi@9WtE*uv14Iuf0)^uZ9U{94rGLpvhO=Ca|hsUGF^YdE)Wsj*~E} zt%lollP<~9YE|P?*QXALLFC(1WzT91=j3=N_*GU+jCC}B7x}lm;g8xA$!7BD$WL6f z{lU{z@`ylrf9LhX-wWCi{+wyRlt39DuR^t^v_pa64I2#E)jQjq{y*Jsr+MzSl6gp6 zPtd_lJ#ba2QC@3_hO8lP6hc0S1lOM2l$0v&S2K;YQy!#pU@uC;GF|3jN{Y3jCcCOc z+Un~ur_ikQBW>Rqf9$o`D7??RF|B*W$Zw&i#`#xdpgl|2;E#J$57j?(2bDdQR8QoC z;0Ua3>aCzB54sw%2nMKR$&K;vWZ;Jw>5L0Mo&DQHN3fNS>I}gHw*H27d$nG$EP_x^_Xs^6v5T0E{Prh^KA4!DD=TmrP987KIX!34ND*($ZgN literal 0 HcmV?d00001 diff --git a/Resources/Prototypes/Catalog/Bounties/bounties.yml b/Resources/Prototypes/Catalog/Bounties/bounties.yml index 28adfb16ac..60fa5147b8 100644 --- a/Resources/Prototypes/Catalog/Bounties/bounties.yml +++ b/Resources/Prototypes/Catalog/Bounties/bounties.yml @@ -202,14 +202,16 @@ - type: cargoBounty id: BountyKnife - reward: 6000 + reward: 2000 description: bounty-description-knife entries: - name: bounty-item-knife amount: 5 whitelist: components: - - Sharp + - Sharp + tags: + - UtilityKnife # required because retracted utility knives are not Sharp - type: cargoBounty id: BountyLemon diff --git a/Resources/Prototypes/Entities/Clothing/Belt/belts.yml b/Resources/Prototypes/Entities/Clothing/Belt/belts.yml index 06c38cc694..5273fa1453 100644 --- a/Resources/Prototypes/Entities/Clothing/Belt/belts.yml +++ b/Resources/Prototypes/Entities/Clothing/Belt/belts.yml @@ -35,6 +35,7 @@ - GPS - WeldingMask - RemoteSignaller + - UtilityKnife components: - StationMap - SprayPainter @@ -120,6 +121,7 @@ - HolofanProjector - Multitool - AppraisalTool + - UtilityKnife components: - StationMap - SprayPainter diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/knife.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/knife.yml index aadf15153e..bd20659696 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/knife.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/knife.yml @@ -336,3 +336,67 @@ - ItemMask restitution: 0.3 friction: 0.2 + +- type: entity + name: utility knife + parent: BaseItem + id: UtilityKnife + description: A knife with a retractable, tiny blade. Useful as a box cutter and letter opener, among other things. + components: + - type: Appearance + - type: ComponentToggler + components: + - type: Execution + doAfterDuration: 4.0 + - type: Sharp + - type: Utensil + types: + - Knife + - type: Tool + qualities: + - Slicing + useSound: + path: /Audio/Items/Culinary/chop.ogg + - type: Item + size: Tiny + sprite: Objects/Weapons/Melee/utility_knife.rsi + - type: ItemToggle + soundActivate: + path: /Audio/Weapons/utilityknifeopen.ogg + soundDeactivate: + path: /Audio/Weapons/utilityknifeclose.ogg + - type: ItemToggleMeleeWeapon + activatedSoundOnHit: + path: /Audio/Weapons/bladeslice.ogg + activatedDamage: + types: + Slash: 4 + - type: MeleeWeapon + wideAnimationRotation: -135 + attackRate: 1 + damage: + types: + Blunt: 1 + - type: PhysicalComposition + materialComposition: + Steel: 50 + - type: Sprite + sprite: Objects/Weapons/Melee/utility_knife.rsi + layers: + - state: utility_knife_handle + - state: utility_knife_blade + visible: false + map: [ "blade" ] + - type: Tag + tags: + - Knife + - UtilityKnife + - type: ToggleableVisuals + spriteLayer: blade + inhandVisuals: + left: + - state: inhand-left-blade + right: + - state: inhand-right-blade + - type: UseDelay + delay: 0.2 diff --git a/Resources/Prototypes/Recipes/Lathes/Packs/cargo.yml b/Resources/Prototypes/Recipes/Lathes/Packs/cargo.yml index 6ca2ef8566..8160cef767 100644 --- a/Resources/Prototypes/Recipes/Lathes/Packs/cargo.yml +++ b/Resources/Prototypes/Recipes/Lathes/Packs/cargo.yml @@ -5,6 +5,7 @@ recipes: - AppraisalTool - Pickaxe + - UtilityKnife - type: latheRecipePack id: CargoBoardsStatic diff --git a/Resources/Prototypes/Recipes/Lathes/cargo.yml b/Resources/Prototypes/Recipes/Lathes/cargo.yml index 0679132ec0..8c0f1e07f2 100644 --- a/Resources/Prototypes/Recipes/Lathes/cargo.yml +++ b/Resources/Prototypes/Recipes/Lathes/cargo.yml @@ -12,3 +12,10 @@ completetime: 4 materials: Steel: 500 + +- type: latheRecipe + id: UtilityKnife + result: UtilityKnife + completetime: 2 + materials: + Steel: 100 diff --git a/Resources/Prototypes/tags.yml b/Resources/Prototypes/tags.yml index 184daa337a..6b705abf48 100644 --- a/Resources/Prototypes/tags.yml +++ b/Resources/Prototypes/tags.yml @@ -1460,6 +1460,9 @@ - type: Tag id: UtilityBelt +- type: Tag + id: UtilityKnife + - type: Tag id: Vegetable diff --git a/Resources/Textures/Objects/Weapons/Melee/utility_knife.rsi/icon.png b/Resources/Textures/Objects/Weapons/Melee/utility_knife.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..9f41d1a08efd389e10cfa20c3b2ba2d6b75be71e GIT binary patch literal 349 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?3oArNM~bhqvg0|O(! zr;B4qgnM#=1nXi&11TmTaX|5a2k-Cjj~^R*e)22zrHU+)uw1xWaJ{U~6DtQ-SJpLK z-(J<;@U(5do#7mIt0Om0wmm$1`#X=kU2R%L#eYG^$1^!r9a#9_++1q|$qi5UFR)2D z&G}PqNox*!gA>DxYLU~9Y=>(6dY+0{GNkM@n{?jZ*_lD)&57U0hE0x1!V7jbWHc|}^7LYUVaGm`@w4U5g`OoM z54g)FJUy^Lom=23L)0-#NA?CC_N8SK3(A_5HF*PW7fo2+q1BaGIY%tAH$kK!rgP5G tjCtozdYxK4%gs5#gvHIdp-F&&LAJRqO7yrMH!!>yJYD@<);T3K0RZPMfI$EN literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Weapons/Melee/utility_knife.rsi/inhand-left-blade.png b/Resources/Textures/Objects/Weapons/Melee/utility_knife.rsi/inhand-left-blade.png new file mode 100644 index 0000000000000000000000000000000000000000..b53a19e93807f1cc62fb4440dd0170560d4934fa GIT binary patch literal 150 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|0z6$DLn`LH zy>*cDfPw&vgXjOdKLjszDJ+>7(Xy^C?cV8F#@$PS>KItAeEWCuPuKG!lkN6p$bm$F qK+o&zAM5vS-x*iVyI%+7H<$`1a*6YriLH7AlJ<1O>;lVWX Xd<)B2zrOP=18Mej^>bP0l+XkK-$PqF literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Weapons/Melee/utility_knife.rsi/inhand-right-blade.png b/Resources/Textures/Objects/Weapons/Melee/utility_knife.rsi/inhand-right-blade.png new file mode 100644 index 0000000000000000000000000000000000000000..acddabce4c8d9c1a486ec944eb7c82a3566c1107 GIT binary patch literal 161 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|qCH(4Ln`LH zy|t0E!9jrKz|nuZ4Fz*t1@;N%J}{hMFQ1~e=Y`olU!Y2cNo#J`o&A@%WVwy^`-(Yh zzbst;SC=0o0R)#ra=BJ*=ek>aKsr=*Po6vjL&L{B_e^o#(!?p#K?*!w{an^LB{Ts5 DasM^& literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Weapons/Melee/utility_knife.rsi/inhand-right.png b/Resources/Textures/Objects/Weapons/Melee/utility_knife.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..4abf5049bd0638a2503c351677e7cf566bec264f GIT binary patch literal 231 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|7J9lkhE&XX zduy-YVFezxfLOK!E-U@lmNqlkFEB0XJZ<6kN4WTV96yJw`)5ripoRyjT1)@#Zd0z= zbv*g}qusZI{@-RhGt)4o>~4#q@v}4c%_Wqh)^5GcCbMe#^bfgnSJxj%>Ur_#Q}?}B ztU%oi3=5>wpSPvI+pj4dQyiL6bVi@p-EV9R b4To(QFZx=}Vz~J{0i@Z})z4*}Q$iB}+;>{U literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Weapons/Melee/utility_knife.rsi/meta.json b/Resources/Textures/Objects/Weapons/Melee/utility_knife.rsi/meta.json new file mode 100644 index 0000000000..6d96094dee --- /dev/null +++ b/Resources/Textures/Objects/Weapons/Melee/utility_knife.rsi/meta.json @@ -0,0 +1,36 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Icon sprited for SS14 by GitHub user sudobeans. Inhand sprites sprited for SS14 by Github user TiniestShark.", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "utility_knife_blade" + }, + { + "name": "utility_knife_handle" + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + }, + { + "name": "inhand-right-blade", + "directions": 4 + }, + { + "name": "inhand-left-blade", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Objects/Weapons/Melee/utility_knife.rsi/utility_knife_blade.png b/Resources/Textures/Objects/Weapons/Melee/utility_knife.rsi/utility_knife_blade.png new file mode 100644 index 0000000000000000000000000000000000000000..07599b94f5a8542fe2aa7abd94b99af7ac573bba GIT binary patch literal 190 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?3oArNM~bhqvgP_V$$ z#W5tpJvl*wb+Mv>6cdm*pm@L|_c!;cSO1k~TP|EJxL#K0N?F6^$-IYWZ+|aoSM%%4 zhY$ahn~oU^hBz)_N;%E>Q!d5isw~52OT%fCUzk6dvUoY;qmtfLQoM~91tgG(i84$K Y(pMB>7Te#L1hkvM)78&qol`;+085iV$p8QV literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Weapons/Melee/utility_knife.rsi/utility_knife_handle.png b/Resources/Textures/Objects/Weapons/Melee/utility_knife.rsi/utility_knife_handle.png new file mode 100644 index 0000000000000000000000000000000000000000..9769850ddd2c072b095bbada29e172bcf772a0bc GIT binary patch literal 278 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz&H|6fVg?3oArNM~bhqvgQ1FDO zi(^QH``gLZe1{AKT-aUS2Jcw>C{3odxIpNggZn|oNquS+0@|(arf}mm2E}A4Huxk~%j%|L%p=>OV|))`cZ9GS%<=;NamP;&(QWu|j|Ff_qz9&gXtV zq#2?5AiQ8IgXiuWyRSXDbbdPoOJG5{lXH Yab1ngn`RZB5A+j*r>mdKI;Vst02~E!Gynhq literal 0 HcmV?d00001 From de9593c0e7206189fc2b3ded585390a53f75405b Mon Sep 17 00:00:00 2001 From: Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> Date: Fri, 3 Oct 2025 03:32:56 +1300 Subject: [PATCH 2/7] Remove static IoC from client & server EntryPoint (#40562) * Remove static IoC from client & server EntryPoint * Fix missing log manager initialization * file namespace --- Content.Client/Entry/EntryPoint.cs | 11 +- Content.Client/IoC/ClientContentIoC.cs | 6 +- Content.Server/Entry/EntryPoint.cs | 209 +++++++++++++------------ Content.Server/IoC/ServerContentIoC.cs | 98 ++++++------ Content.Shared/Entry/EntryPoint.cs | 1 - Content.Shared/IoC/SharedContentIoC.cs | 6 +- Content.Tests/ContentUnitTest.cs | 9 +- 7 files changed, 176 insertions(+), 164 deletions(-) diff --git a/Content.Client/Entry/EntryPoint.cs b/Content.Client/Entry/EntryPoint.cs index a458e24aed..f35272b63a 100644 --- a/Content.Client/Entry/EntryPoint.cs +++ b/Content.Client/Entry/EntryPoint.cs @@ -77,18 +77,21 @@ namespace Content.Client.Entry [Dependency] private readonly IEntitySystemManager _entitySystemManager = default!; [Dependency] private readonly ClientsidePlaytimeTrackingManager _clientsidePlaytimeManager = default!; - public override void Init() + public override void PreInit() { - ClientContentIoC.Register(); + ClientContentIoC.Register(Dependencies); foreach (var callback in TestingCallbacks) { var cast = (ClientModuleTestingCallbacks) callback; cast.ClientBeforeIoC?.Invoke(); } + } - IoCManager.BuildGraph(); - IoCManager.InjectDependencies(this); + public override void Init() + { + Dependencies.BuildGraph(); + Dependencies.InjectDependencies(this); _contentLoc.Initialize(); _componentFactory.DoAutoRegistrations(); diff --git a/Content.Client/IoC/ClientContentIoC.cs b/Content.Client/IoC/ClientContentIoC.cs index ed2199bb81..8f81f90311 100644 --- a/Content.Client/IoC/ClientContentIoC.cs +++ b/Content.Client/IoC/ClientContentIoC.cs @@ -23,6 +23,7 @@ using Content.Client.Lobby; using Content.Client.Players.RateLimiting; using Content.Shared.Administration.Managers; using Content.Shared.Chat; +using Content.Shared.IoC; using Content.Shared.Players.PlayTimeTracking; using Content.Shared.Players.RateLimiting; @@ -30,10 +31,9 @@ namespace Content.Client.IoC { internal static class ClientContentIoC { - public static void Register() + public static void Register(IDependencyCollection collection) { - var collection = IoCManager.Instance!; - + SharedContentIoC.Register(collection); collection.Register(); collection.Register(); collection.Register(); diff --git a/Content.Server/Entry/EntryPoint.cs b/Content.Server/Entry/EntryPoint.cs index df4af14f1e..7ebb546879 100644 --- a/Content.Server/Entry/EntryPoint.cs +++ b/Content.Server/Entry/EntryPoint.cs @@ -15,8 +15,6 @@ using Content.Server.Info; using Content.Server.IoC; using Content.Server.Maps; using Content.Server.NodeContainer.NodeGroups; -using Content.Server.Objectives; -using Content.Server.Players; using Content.Server.Players.JobWhitelist; using Content.Server.Players.PlayTimeTracking; using Content.Server.Players.RateLimiting; @@ -42,124 +40,131 @@ namespace Content.Server.Entry internal const string ConfigPresetsDir = "/ConfigPresets/"; private const string ConfigPresetsDirBuild = $"{ConfigPresetsDir}Build/"; - private EuiManager _euiManager = default!; - private IVoteManager _voteManager = default!; - private ServerUpdateManager _updateManager = default!; - private PlayTimeTrackingManager? _playTimeTracking; - private IEntitySystemManager? _sysMan; - private IServerDbManager? _dbManager; - private IWatchlistWebhookManager _watchlistWebhookManager = default!; - private IConnectionManager? _connectionManager; + [Dependency] private readonly CVarControlManager _cvarCtrl = default!; + [Dependency] private readonly ContentLocalizationManager _loc = default!; + [Dependency] private readonly ContentNetworkResourceManager _netResMan = default!; + [Dependency] private readonly DiscordChatLink _discordChatLink = default!; + [Dependency] private readonly DiscordLink _discordLink = default!; + [Dependency] private readonly EuiManager _euiManager = default!; + [Dependency] private readonly GhostKickManager _ghostKick = default!; + [Dependency] private readonly IAdminManager _admin = default!; + [Dependency] private readonly IAdminLogManager _adminLog = default!; + [Dependency] private readonly IAfkManager _afk = default!; + [Dependency] private readonly IBanManager _ban = default!; + [Dependency] private readonly IChatManager _chatSan = default!; + [Dependency] private readonly IChatSanitizationManager _chat = default!; + [Dependency] private readonly IComponentFactory _factory = default!; + [Dependency] private readonly IConfigurationManager _cfg = default!; + [Dependency] private readonly IConnectionManager _connection = default!; + [Dependency] private readonly IEntitySystemManager _entSys = default!; + [Dependency] private readonly IGameMapManager _gameMap = default!; + [Dependency] private readonly ILogManager _log = default!; + [Dependency] private readonly INodeGroupFactory _nodeFactory = default!; + [Dependency] private readonly IPrototypeManager _proto = default!; + [Dependency] private readonly IResourceManager _res = default!; + [Dependency] private readonly IServerDbManager _dbManager = default!; + [Dependency] private readonly IServerPreferencesManager _preferences = default!; + [Dependency] private readonly IStatusHost _host = default!; + [Dependency] private readonly IVoteManager _voteManager = default!; + [Dependency] private readonly IWatchlistWebhookManager _watchlistWebhookManager = default!; + [Dependency] private readonly JobWhitelistManager _job = default!; + [Dependency] private readonly MultiServerKickManager _multiServerKick = default!; + [Dependency] private readonly PlayTimeTrackingManager _playTimeTracking = default!; + [Dependency] private readonly PlayerRateLimitManager _rateLimit = default!; + [Dependency] private readonly RecipeManager _recipe = default!; + [Dependency] private readonly RulesManager _rules = default!; + [Dependency] private readonly ServerApi _serverApi = default!; + [Dependency] private readonly ServerInfoManager _serverInfo = default!; + [Dependency] private readonly ServerUpdateManager _updateManager = default!; + + public override void PreInit() + { + ServerContentIoC.Register(Dependencies); + foreach (var callback in TestingCallbacks) + { + var cast = (ServerModuleTestingCallbacks)callback; + cast.ServerBeforeIoC?.Invoke(); + } + } /// public override void Init() { base.Init(); + Dependencies.BuildGraph(); + Dependencies.InjectDependencies(this); - var cfg = IoCManager.Resolve(); - var res = IoCManager.Resolve(); - var logManager = IoCManager.Resolve(); + LoadConfigPresets(_cfg, _res, _log.GetSawmill("configpreset")); - LoadConfigPresets(cfg, res, logManager.GetSawmill("configpreset")); + var aczProvider = new ContentMagicAczProvider(Dependencies); + _host.SetMagicAczProvider(aczProvider); - var aczProvider = new ContentMagicAczProvider(IoCManager.Resolve()); - IoCManager.Resolve().SetMagicAczProvider(aczProvider); + _factory.DoAutoRegistrations(); + _factory.IgnoreMissingComponents("Visuals"); + _factory.RegisterIgnore(IgnoredComponents.List); + _factory.GenerateNetIds(); - var factory = IoCManager.Resolve(); - var prototypes = IoCManager.Resolve(); + _proto.RegisterIgnore("parallax"); - factory.DoAutoRegistrations(); - factory.IgnoreMissingComponents("Visuals"); + _loc.Initialize(); - factory.RegisterIgnore(IgnoredComponents.List); + var dest = _cfg.GetCVar(CCVars.DestinationFile); + if (!string.IsNullOrEmpty(dest)) + return; //hacky but it keeps load times for the generator down. - prototypes.RegisterIgnore("parallax"); + _log.GetSawmill("Storage").Level = LogLevel.Info; + _log.GetSawmill("db.ef").Level = LogLevel.Info; - ServerContentIoC.Register(); - - foreach (var callback in TestingCallbacks) - { - var cast = (ServerModuleTestingCallbacks) callback; - cast.ServerBeforeIoC?.Invoke(); - } - - IoCManager.BuildGraph(); - factory.GenerateNetIds(); - var configManager = IoCManager.Resolve(); - var dest = configManager.GetCVar(CCVars.DestinationFile); - IoCManager.Resolve().Initialize(); - if (string.IsNullOrEmpty(dest)) //hacky but it keeps load times for the generator down. - { - _euiManager = IoCManager.Resolve(); - _voteManager = IoCManager.Resolve(); - _updateManager = IoCManager.Resolve(); - _playTimeTracking = IoCManager.Resolve(); - _connectionManager = IoCManager.Resolve(); - _sysMan = IoCManager.Resolve(); - _dbManager = IoCManager.Resolve(); - _watchlistWebhookManager = IoCManager.Resolve(); - - logManager.GetSawmill("Storage").Level = LogLevel.Info; - logManager.GetSawmill("db.ef").Level = LogLevel.Info; - - IoCManager.Resolve().Initialize(); - IoCManager.Resolve().Initialize(); - _dbManager.Init(); - IoCManager.Resolve().Init(); - IoCManager.Resolve().Initialize(); - IoCManager.Resolve().Initialize(); - IoCManager.Resolve().Initialize(); - IoCManager.Resolve().Initialize(); - IoCManager.Resolve().Initialize(); - - _voteManager.Initialize(); - _updateManager.Initialize(); - _playTimeTracking.Initialize(); - _watchlistWebhookManager.Initialize(); - IoCManager.Resolve().Initialize(); - IoCManager.Resolve().Initialize(); - } + _adminLog.Initialize(); + _connection.Initialize(); + _dbManager.Init(); + _preferences.Init(); + _nodeFactory.Initialize(); + _netResMan.Initialize(); + _ghostKick.Initialize(); + _serverInfo.Initialize(); + _serverApi.Initialize(); + _voteManager.Initialize(); + _updateManager.Initialize(); + _playTimeTracking.Initialize(); + _watchlistWebhookManager.Initialize(); + _job.Initialize(); + _rateLimit.Initialize(); } public override void PostInit() { base.PostInit(); - IoCManager.Resolve().Initialize(); - IoCManager.Resolve().Initialize(); - var configManager = IoCManager.Resolve(); - var resourceManager = IoCManager.Resolve(); - var dest = configManager.GetCVar(CCVars.DestinationFile); + _chatSan.Initialize(); + _chat.Initialize(); + var dest = _cfg.GetCVar(CCVars.DestinationFile); if (!string.IsNullOrEmpty(dest)) { var resPath = new ResPath(dest).ToRootedPath(); - var file = resourceManager.UserData.OpenWriteText(resPath.WithName("chem_" + dest)); + var file = _res.UserData.OpenWriteText(resPath.WithName("chem_" + dest)); ChemistryJsonGenerator.PublishJson(file); file.Flush(); - file = resourceManager.UserData.OpenWriteText(resPath.WithName("react_" + dest)); + file = _res.UserData.OpenWriteText(resPath.WithName("react_" + dest)); ReactionJsonGenerator.PublishJson(file); file.Flush(); - IoCManager.Resolve().Shutdown("Data generation done"); + Dependencies.Resolve().Shutdown("Data generation done"); + return; } - else - { - IoCManager.Resolve().Initialize(); - IoCManager.Resolve().Initialize(); - IoCManager.Resolve().Initialize(); - IoCManager.Resolve().Initialize(); - IoCManager.Resolve().Initialize(); - IoCManager.Resolve().Initialize(); - - _euiManager.Initialize(); - - IoCManager.Resolve().Initialize(); - IoCManager.Resolve().GetEntitySystem().PostInitialize(); - IoCManager.Resolve().Initialize(); - IoCManager.Resolve().PostInit(); - IoCManager.Resolve().Initialize(); - IoCManager.Resolve().Initialize(); - } + _recipe.Initialize(); + _admin.Initialize(); + _afk.Initialize(); + _rules.Initialize(); + _discordLink.Initialize(); + _discordChatLink.Initialize(); + _euiManager.Initialize(); + _gameMap.Initialize(); + _entSys.GetEntitySystem().PostInitialize(); + _ban.Initialize(); + _connection.PostInit(); + _multiServerKick.Initialize(); + _cvarCtrl.Initialize(); } public override void Update(ModUpdateLevel level, FrameEventArgs frameEventArgs) @@ -177,21 +182,27 @@ namespace Content.Server.Entry case ModUpdateLevel.FramePostEngine: _updateManager.Update(); - _playTimeTracking?.Update(); + _playTimeTracking.Update(); _watchlistWebhookManager.Update(); - _connectionManager?.Update(); + _connection.Update(); break; } } protected override void Dispose(bool disposing) { - _playTimeTracking?.Shutdown(); - _dbManager?.Shutdown(); - IoCManager.Resolve().Shutdown(); + var dest = _cfg.GetCVar(CCVars.DestinationFile); + if (!string.IsNullOrEmpty(dest)) + { + _playTimeTracking.Shutdown(); + _dbManager.Shutdown(); + } - IoCManager.Resolve().Shutdown(); - IoCManager.Resolve().Shutdown(); + _serverApi.Shutdown(); + + // TODO Should this be awaited? + _discordLink.Shutdown(); + _discordChatLink.Shutdown(); } private static void LoadConfigPresets(IConfigurationManager cfg, IResourceManager res, ISawmill sawmill) diff --git a/Content.Server/IoC/ServerContentIoC.cs b/Content.Server/IoC/ServerContentIoC.cs index b4d999bef4..b6b5316da7 100644 --- a/Content.Server/IoC/ServerContentIoC.cs +++ b/Content.Server/IoC/ServerContentIoC.cs @@ -26,59 +26,59 @@ using Content.Server.Worldgen.Tools; using Content.Shared.Administration.Logs; using Content.Shared.Administration.Managers; using Content.Shared.Chat; +using Content.Shared.IoC; using Content.Shared.Kitchen; using Content.Shared.Players.PlayTimeTracking; using Content.Shared.Players.RateLimiting; -namespace Content.Server.IoC -{ - internal static class ServerContentIoC - { - public static void Register() - { - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); - IoCManager.Register(); +namespace Content.Server.IoC; - IoCManager.Register(); - IoCManager.Register(); - } +internal static class ServerContentIoC +{ + public static void Register(IDependencyCollection deps) + { + SharedContentIoC.Register(deps); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); + deps.Register(); } } diff --git a/Content.Shared/Entry/EntryPoint.cs b/Content.Shared/Entry/EntryPoint.cs index df267b08cb..db8d6a6abd 100644 --- a/Content.Shared/Entry/EntryPoint.cs +++ b/Content.Shared/Entry/EntryPoint.cs @@ -27,7 +27,6 @@ namespace Content.Shared.Entry public override void PreInit() { IoCManager.InjectDependencies(this); - SharedContentIoC.Register(); } public override void Shutdown() diff --git a/Content.Shared/IoC/SharedContentIoC.cs b/Content.Shared/IoC/SharedContentIoC.cs index c20cdbc111..f23b9f8355 100644 --- a/Content.Shared/IoC/SharedContentIoC.cs +++ b/Content.Shared/IoC/SharedContentIoC.cs @@ -5,10 +5,10 @@ namespace Content.Shared.IoC { public static class SharedContentIoC { - public static void Register() + public static void Register(IDependencyCollection deps) { - IoCManager.Register(); - IoCManager.Register(); + deps.Register(); + deps.Register(); } } } diff --git a/Content.Tests/ContentUnitTest.cs b/Content.Tests/ContentUnitTest.cs index 827c4e2f43..18938ac4ea 100644 --- a/Content.Tests/ContentUnitTest.cs +++ b/Content.Tests/ContentUnitTest.cs @@ -2,8 +2,8 @@ using System.Collections.Generic; using System.Reflection; using Content.Client.IoC; using Content.Server.IoC; -using Content.Shared.IoC; using Robust.Shared.Analyzers; +using Robust.Shared.IoC; using Robust.UnitTesting; using EntryPoint = Content.Server.Entry.EntryPoint; @@ -15,16 +15,15 @@ namespace Content.Tests protected override void OverrideIoC() { base.OverrideIoC(); - - SharedContentIoC.Register(); + var dependencies = IoCManager.Instance!; if (Project == UnitTestProject.Server) { - ServerContentIoC.Register(); + ServerContentIoC.Register(dependencies); } else if (Project == UnitTestProject.Client) { - ClientContentIoC.Register(); + ClientContentIoC.Register(dependencies); } } From 07c7d6284ee2b4a7140654235b6ca59a5d1fa834 Mon Sep 17 00:00:00 2001 From: Princess Cheeseballs <66055347+Princess-Cheeseballs@users.noreply.github.com> Date: Thu, 2 Oct 2025 09:52:07 -0700 Subject: [PATCH 3/7] [HOTFIX] Fix Antags failing to roll. (#40658) Use TryGetCached instead of GetCached Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com> --- Content.Server/Antag/AntagSelectionSystem.API.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Content.Server/Antag/AntagSelectionSystem.API.cs b/Content.Server/Antag/AntagSelectionSystem.API.cs index 6703b7b7ca..5debd10b6e 100644 --- a/Content.Server/Antag/AntagSelectionSystem.API.cs +++ b/Content.Server/Antag/AntagSelectionSystem.API.cs @@ -174,7 +174,10 @@ public sealed partial class AntagSelectionSystem if (roles.Count == 0) return false; - var pref = (HumanoidCharacterProfile) _pref.GetPreferences(session.UserId).SelectedCharacter; + if (!_pref.TryGetCachedPreferences(session.UserId, out var pref)) + return false; + + var character = (HumanoidCharacterProfile) pref.SelectedCharacter; var valid = false; @@ -183,8 +186,7 @@ public sealed partial class AntagSelectionSystem { var list = new List>{role}; - - if (pref.AntagPreferences.Contains(role) + if (character.AntagPreferences.Contains(role) && !_ban.IsRoleBanned(session, list) && _playTime.IsAllowed(session, list)) valid = true; From 47c79dca67cde43bf1b8ccea60ea54d733150093 Mon Sep 17 00:00:00 2001 From: Zeneganto Date: Fri, 3 Oct 2025 03:04:43 +1000 Subject: [PATCH 4/7] Fix lockbox ERRORing (#40642) bruh --- .../Prototypes/Entities/Structures/Storage/Crates/crates.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Resources/Prototypes/Entities/Structures/Storage/Crates/crates.yml b/Resources/Prototypes/Entities/Structures/Storage/Crates/crates.yml index a08ba4aacd..55a0c72e7c 100644 --- a/Resources/Prototypes/Entities/Structures/Storage/Crates/crates.yml +++ b/Resources/Prototypes/Entities/Structures/Storage/Crates/crates.yml @@ -489,6 +489,8 @@ - CrateMask #this is so they can go under plastic flaps layer: - MachineLayer + - type: Paintable + group: null - type: entity id: CrateLockBoxEngineering From 9b7c87bd7e90191404e03f55be0acab46b6e891f Mon Sep 17 00:00:00 2001 From: kosticia Date: Thu, 2 Oct 2025 23:00:39 +0300 Subject: [PATCH 5/7] Fix anomaly shuffle particles type (#40624) * dev it * screw it * Revert "screw it" This reverts commit 5657a1d20128e630bebbaf38f4dcb4dbac28d026. * Revert "dev it" This reverts commit f3d7c355da17de92e43c145efbd348f8378d6146. * slarti best * Revert "slarti best" This reverts commit 8de1caafb254515202aa21d2b96029a1fce24df2. * Reapply "dev it" This reverts commit c603940a73246f8a22a171c5559eb3f3f995e7bc. * Reapply "screw it" This reverts commit 468722abe7bde7e30bc3b421bc28fa90a013bd63. * refactor: renaming +xml-doc --------- Co-authored-by: pa.pecherskij --- Content.Server/Anomaly/AnomalySystem.cs | 3 +++ .../Effects/ShuffleParticlesAnomalySystem.cs | 13 +++++-------- .../Components/AnomalousParticleComponent.cs | 5 +---- .../Anomaly/Components/AnomalyComponent.cs | 7 +++++++ 4 files changed, 16 insertions(+), 12 deletions(-) rename {Content.Server => Content.Shared}/Anomaly/Components/AnomalousParticleComponent.cs (95%) diff --git a/Content.Server/Anomaly/AnomalySystem.cs b/Content.Server/Anomaly/AnomalySystem.cs index 69f18e5eeb..102391baff 100644 --- a/Content.Server/Anomaly/AnomalySystem.cs +++ b/Content.Server/Anomaly/AnomalySystem.cs @@ -126,6 +126,9 @@ public sealed partial class AnomalySystem : SharedAnomalySystem if (_random.Prob(anomaly.Comp.Continuity)) SetBehavior(anomaly, GetRandomBehavior()); } + + var ev = new AnomalyAffectedByParticleEvent(anomaly, args.OtherEntity); + RaiseLocalEvent(anomaly, ref ev); } /// diff --git a/Content.Server/Anomaly/Effects/ShuffleParticlesAnomalySystem.cs b/Content.Server/Anomaly/Effects/ShuffleParticlesAnomalySystem.cs index 925c826fb5..2139967691 100644 --- a/Content.Server/Anomaly/Effects/ShuffleParticlesAnomalySystem.cs +++ b/Content.Server/Anomaly/Effects/ShuffleParticlesAnomalySystem.cs @@ -1,9 +1,9 @@ using Content.Server.Anomaly.Components; using Content.Shared.Anomaly.Components; -using Robust.Shared.Physics.Events; using Robust.Shared.Random; namespace Content.Server.Anomaly.Effects; + public sealed class ShuffleParticlesAnomalySystem : EntitySystem { [Dependency] private readonly AnomalySystem _anomaly = default!; @@ -12,19 +12,16 @@ public sealed class ShuffleParticlesAnomalySystem : EntitySystem public override void Initialize() { SubscribeLocalEvent(OnPulse); - SubscribeLocalEvent(OnStartCollide); + SubscribeLocalEvent(OnAffectedByParticle); } - private void OnStartCollide(Entity ent, ref StartCollideEvent args) + private void OnAffectedByParticle(Entity ent, ref AnomalyAffectedByParticleEvent args) { - if (!TryComp(ent, out var anomaly)) - return; - - if (!HasComp(args.OtherEntity)) + if (!TryComp(ent, out var anomalyComp)) return; if (ent.Comp.ShuffleOnParticleHit && _random.Prob(ent.Comp.Prob)) - _anomaly.ShuffleParticlesEffect((ent, anomaly)); + _anomaly.ShuffleParticlesEffect((args.Anomaly, anomalyComp)); } private void OnPulse(Entity ent, ref AnomalyPulseEvent args) diff --git a/Content.Server/Anomaly/Components/AnomalousParticleComponent.cs b/Content.Shared/Anomaly/Components/AnomalousParticleComponent.cs similarity index 95% rename from Content.Server/Anomaly/Components/AnomalousParticleComponent.cs rename to Content.Shared/Anomaly/Components/AnomalousParticleComponent.cs index 5b05522bb9..47c49956c9 100644 --- a/Content.Server/Anomaly/Components/AnomalousParticleComponent.cs +++ b/Content.Shared/Anomaly/Components/AnomalousParticleComponent.cs @@ -1,7 +1,4 @@ -using Content.Shared.Anomaly; -using Content.Shared.Anomaly.Components; - -namespace Content.Server.Anomaly.Components; +namespace Content.Shared.Anomaly.Components; /// /// This is used for projectiles which affect anomalies through colliding with them. diff --git a/Content.Shared/Anomaly/Components/AnomalyComponent.cs b/Content.Shared/Anomaly/Components/AnomalyComponent.cs index fb281ca9a3..47320ece03 100644 --- a/Content.Shared/Anomaly/Components/AnomalyComponent.cs +++ b/Content.Shared/Anomaly/Components/AnomalyComponent.cs @@ -324,3 +324,10 @@ public readonly record struct AnomalyHealthChangedEvent(EntityUid Anomaly, float /// [ByRefEvent] public readonly record struct AnomalyBehaviorChangedEvent(EntityUid Anomaly, ProtoId? Old, ProtoId? New); + +/// +/// Event of anomaly being affected by exotic particle. +/// Is raised when particle collides with artifact. +/// +[ByRefEvent] +public record struct AnomalyAffectedByParticleEvent(EntityUid Anomaly, EntityUid Particle); From bfc65b1554d42843e00c8bd948ea4b1f93db54c4 Mon Sep 17 00:00:00 2001 From: lzk <124214523+lzk228@users.noreply.github.com> Date: Thu, 2 Oct 2025 23:16:35 +0200 Subject: [PATCH 6/7] some entities name fixes (#40663) --- Resources/Prototypes/Entities/Mobs/Player/silicon.yml | 6 +++--- .../Entities/Objects/Devices/Circuitboards/computer.yml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml index 91fb6baa40..a7b90be0f7 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml @@ -1,4 +1,4 @@ -# Be careful with these as they get removed on shutdown too! +# Be careful with these as they get removed on shutdown too! - type: entity id: AiHeld description: Components added / removed from an entity that gets inserted into an AI core. @@ -169,7 +169,7 @@ # Empty AI core - type: entity id: PlayerStationAiEmpty - name: AI Core + name: AI core description: The latest in Artificial Intelligences. parent: - BaseStructure @@ -330,7 +330,7 @@ - type: entity parent: BaseStructure id: PlayerStationAiAssembly - name: AI Core Assembly + name: AI core assembly description: An unfinished computer core for housing an artifical intelligence. components: - type: Anchorable diff --git a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/computer.yml b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/computer.yml index 0735c8d950..9ac187c9c9 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/computer.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/computer.yml @@ -1,4 +1,4 @@ -- type: entity +- type: entity parent: BaseItem id: BaseComputerCircuitboard name: computer board @@ -564,7 +564,7 @@ - type: entity parent: BaseComputerCircuitboard id: StationAiFixerCircuitboard - name: AI restoration console + name: AI restoration console board description: A computer printed circuit board for an AI restoration console console. components: - type: Sprite From 3db18aa7b29bd8c9d704b536e7bbaed78cfd51bc Mon Sep 17 00:00:00 2001 From: Archee Date: Thu, 2 Oct 2025 23:35:48 +0100 Subject: [PATCH 7/7] Material Door rebalancing (#36597) * refactors in material_doors.yml, lowers destructible thresholds on most doors, changes damageable modifiers for doors lowering their resistances, adds partial material drops to doors being destroyed * adds poster break sound to paper door breaking * merge conflicts --------- Co-authored-by: iaada --- .../Doors/MaterialDoors/material_doors.yml | 348 +++++++++++++----- .../Construction/Graphs/structures/doors.yml | 58 +-- 2 files changed, 286 insertions(+), 120 deletions(-) diff --git a/Resources/Prototypes/Entities/Structures/Doors/MaterialDoors/material_doors.yml b/Resources/Prototypes/Entities/Structures/Doors/MaterialDoors/material_doors.yml index 510b76b41e..26db89ed32 100644 --- a/Resources/Prototypes/Entities/Structures/Doors/MaterialDoors/material_doors.yml +++ b/Resources/Prototypes/Entities/Structures/Doors/MaterialDoors/material_doors.yml @@ -55,7 +55,7 @@ thresholds: - trigger: !type:DamageTrigger - damage: 200 + damage: 300 behaviors: - !type:DoActsBehavior acts: ["Destruction"] @@ -69,6 +69,8 @@ components: - type: NavMapDoor +### Metal doors ### + - type: entity id: MetalDoor name: metal door @@ -77,6 +79,183 @@ - type: Construction graph: DoorGraph node: metalDoor + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 200 + behaviors: + - !type:DoActsBehavior + acts: ["Destruction"] + - trigger: + !type:DamageTrigger + damage: 150 + behaviors: + - !type:DoActsBehavior + acts: ["Destruction"] + - !type:PlaySoundBehavior + sound: + collection: MetalBreak + - !type:SpawnEntitiesBehavior + spawn: + SheetSteel1: + min: 3 + max: 5 + +- type: entity + id: PlasmaDoor + name: plasma door + parent: BaseMaterialDoorNavMap + description: A door, where will it lead? + components: + - type: Sprite + sprite: Structures/Doors/MineralDoors/plasma_door.rsi + layers: + - state: closed + map: ["enum.DoorVisualLayers.Base"] + - type: Construction + graph: DoorGraph + node: plasmaDoor + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 200 + behaviors: + - !type:DoActsBehavior + acts: ["Destruction"] + - trigger: + !type:DamageTrigger + damage: 150 + behaviors: + - !type:DoActsBehavior + acts: ["Destruction"] + - !type:PlaySoundBehavior + sound: + collection: MetalBreak + - !type:SpawnEntitiesBehavior + spawn: + SheetPlasma1: + min: 3 + max: 5 + +- type: entity + id: GoldDoor + name: gold door + parent: BaseMaterialDoorNavMap + description: A door, where will it lead? + components: + - type: Sprite + sprite: Structures/Doors/MineralDoors/gold_door.rsi + layers: + - state: closed + map: ["enum.DoorVisualLayers.Base"] + - type: Construction + graph: DoorGraph + node: goldDoor + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 200 + behaviors: + - !type:DoActsBehavior + acts: ["Destruction"] + - trigger: + !type:DamageTrigger + damage: 150 + behaviors: + - !type:DoActsBehavior + acts: ["Destruction"] + - !type:PlaySoundBehavior + sound: + collection: MetalBreak + - !type:SpawnEntitiesBehavior + spawn: + IngotGold1: + min: 3 + max: 5 + +- type: entity + id: SilverDoor + name: silver door + parent: BaseMaterialDoorNavMap + description: A door, where will it lead? + components: + - type: Sprite + sprite: Structures/Doors/MineralDoors/silver_door.rsi + layers: + - state: closed + map: ["enum.DoorVisualLayers.Base"] + - type: Construction + graph: DoorGraph + node: silverDoor + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 200 + behaviors: + - !type:DoActsBehavior + acts: ["Destruction"] + - trigger: + !type:DamageTrigger + damage: 150 + behaviors: + - !type:DoActsBehavior + acts: ["Destruction"] + - !type:PlaySoundBehavior + sound: + collection: MetalBreak + - !type:SpawnEntitiesBehavior + spawn: + IngotSilver1: + min: 3 + max: 5 + +- type: entity + id: BananiumDoor + name: bananium door + parent: BaseMaterialDoorNavMap + description: A door, where will it lead? + components: + - type: Sprite + sprite: Structures/Doors/MineralDoors/bananium_door.rsi + layers: + - state: closed + map: ["enum.DoorVisualLayers.Base"] + - type: Door + openSound: + path: /Audio/Items/bikehorn.ogg + closeSound: + path: /Audio/Items/bikehorn.ogg + - type: Construction + graph: DoorGraph + node: bananiumDoor + - type: Destructible + thresholds: + - trigger: + !type:DamageTrigger + damage: 200 + behaviors: + - !type:DoActsBehavior + acts: ["Destruction"] + - trigger: + !type:DamageTrigger + damage: 150 + behaviors: + - !type:DoActsBehavior + acts: ["Destruction"] + - !type:PlaySoundBehavior + sound: + collection: MetalBreak + - !type:SpawnEntitiesBehavior + spawn: + MaterialBananium1: + min: 1 + max: 2 + +### Other doors ### - type: entity id: WoodDoor @@ -90,6 +269,9 @@ path: /Audio/Effects/door_open.ogg closeSound: path: /Audio/Effects/door_close.ogg + - type: Construction + graph: DoorGraph + node: woodDoor - type: Damageable damageContainer: StructuralInorganic damageModifierSet: Wood @@ -97,97 +279,69 @@ thresholds: - trigger: !type:DamageTrigger - damage: 100 + damage: 150 behaviors: - !type:DoActsBehavior acts: ["Destruction"] - - type: Construction - graph: DoorGraph - node: woodDoor + - trigger: + !type:DamageTrigger + damage: 75 + behaviors: + - !type:PlaySoundBehavior + sound: + collection: WoodDestroy + - !type:DoActsBehavior + acts: ["Destruction"] + - !type:SpawnEntitiesBehavior + spawn: + MaterialWoodPlank1: + min: 3 + max: 5 - type: entity id: PaperDoor name: paper door parent: BaseMaterialDoorNavMap + description: A door, where will it lead? components: - type: Sprite sprite: Structures/Doors/MineralDoors/paper_door.rsi + layers: + - state: closed + map: ["enum.DoorVisualLayers.Base"] + - type: Door + openSound: + path: /Audio/Effects/paperdoor_openclose.ogg + closeSound: + path: /Audio/Effects/paperdoor_openclose.ogg + - type: Construction + graph: DoorGraph + node: paperDoor + - type: Damageable + damageContainer: StructuralInorganic + damageModifierSet: Wood - type: Destructible thresholds: + - trigger: + !type:DamageTrigger + damage: 150 + behaviors: + - !type:DoActsBehavior + acts: ["Destruction"] - trigger: !type:DamageTrigger damage: 50 behaviors: + - !type:PlaySoundBehavior + sound: + path: /Audio/Effects/poster_broken.ogg - !type:DoActsBehavior acts: ["Destruction"] - - type: Construction - graph: DoorGraph - node: paperDoor - - type: Door - openSound: - path: /Audio/Effects/paperdoor_openclose.ogg - closeSound: - path: /Audio/Effects/paperdoor_openclose.ogg - -- type: entity - id: PlasmaDoor - name: plasma door - parent: BaseMaterialDoorNavMap - components: - - type: Sprite - sprite: Structures/Doors/MineralDoors/plasma_door.rsi - - type: Damageable - damageContainer: StructuralInorganic - damageModifierSet: StructuralMetallicStrong - - type: Destructible - thresholds: - - trigger: - !type:DamageTrigger - damage: 300 - behaviors: - - !type:DoActsBehavior - acts: ["Destruction"] - - type: Construction - graph: DoorGraph - node: plasmaDoor - -- type: entity - id: GoldDoor - name: gold door - parent: BaseMaterialDoorNavMap - components: - - type: Sprite - sprite: Structures/Doors/MineralDoors/gold_door.rsi - - type: Construction - graph: DoorGraph - node: goldDoor - -- type: entity - id: SilverDoor - name: silver door - parent: BaseMaterialDoorNavMap - components: - - type: Sprite - sprite: Structures/Doors/MineralDoors/silver_door.rsi - - type: Construction - graph: DoorGraph - node: silverDoor - -- type: entity - id: BananiumDoor - name: bananium door - parent: BaseMaterialDoorNavMap - components: - - type: Sprite - sprite: Structures/Doors/MineralDoors/bananium_door.rsi - - type: Construction - graph: DoorGraph - node: bananiumDoor - - type: Door - openSound: - path: /Audio/Items/bikehorn.ogg - closeSound: - path: /Audio/Items/bikehorn.ogg + - !type:SpawnEntitiesBehavior + spawn: + SheetPaper1: + min: 3 + max: 5 - type: entity id: WebDoor @@ -197,9 +351,19 @@ components: - type: Sprite sprite: Structures/Doors/web_door.rsi + layers: + - state: closed + map: ["enum.DoorVisualLayers.Base"] + - type: Door + closeSound: + path: /Audio/Effects/rustle1.ogg + openSound: + path: /Audio/Effects/rustle2.ogg - type: Construction graph: WebStructures node: door + - type: Damageable + damageModifierSet: Web - type: Destructible thresholds: - trigger: # Excess damage, don't spawn entities @@ -211,6 +375,12 @@ collection: WoodDestroy - !type:DoActsBehavior acts: ["Destruction"] + - trigger: + !type:DamageTrigger + damage: 150 + behaviors: + - !type:DoActsBehavior + acts: ["Destruction"] - trigger: !type:DamageTrigger damage: 50 @@ -222,16 +392,9 @@ collection: WoodDestroy - !type:SpawnEntitiesBehavior spawn: - MaterialWebSilk: - min: 3 - max: 5 - - type: Damageable - damageModifierSet: Web - - type: Door - closeSound: - path: /Audio/Effects/rustle1.ogg - openSound: - path: /Audio/Effects/rustle2.ogg + MaterialWebSilk1: + min: 1 + max: 2 - type: entity id: CardDoor @@ -242,9 +405,12 @@ sprite: Structures/Doors/MineralDoors/card_door.rsi - type: Door openSound: - path: /Audio/Effects/card_drag.ogg + path: /Audio/Effects/card_drag.ogg closeSound: path: /Audio/Effects/card_drag.ogg + - type: Construction + graph: DoorGraph + node: cardDoor - type: MeleeSound soundGroups: Brute: @@ -265,13 +431,13 @@ !type:DamageTrigger damage: 30 behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - !type:PlaySoundBehavior + sound: + collection: WoodDestroy - !type:SpawnEntitiesBehavior spawn: MaterialCardboard: - min: 2 - max: 4 - - !type:DoActsBehavior - acts: [ "Destruction" ] - - type: Construction - graph: DoorGraph - node: cardDoor + min: 3 + max: 5 diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/structures/doors.yml b/Resources/Prototypes/Recipes/Construction/Graphs/structures/doors.yml index 2c8260269f..d675a0f7f8 100644 --- a/Resources/Prototypes/Recipes/Construction/Graphs/structures/doors.yml +++ b/Resources/Prototypes/Recipes/Construction/Graphs/structures/doors.yml @@ -11,57 +11,57 @@ - !type:SnapToGrid { } steps: - material: Steel - amount: 20 - doAfter: 15 + amount: 10 + doAfter: 8 - to: woodDoor completed: - !type:SnapToGrid { } steps: - material: WoodPlank - amount: 20 - doAfter: 15 + amount: 10 + doAfter: 8 - to: plasmaDoor completed: - !type:SnapToGrid { } steps: - material: Plasma - amount: 20 - doAfter: 15 + amount: 10 + doAfter: 8 - to: goldDoor completed: - !type:SnapToGrid { } steps: - material: Gold - amount: 20 - doAfter: 15 + amount: 10 + doAfter: 8 - to: silverDoor completed: - !type:SnapToGrid { } steps: - material: Silver - amount: 20 - doAfter: 15 + amount: 10 + doAfter: 8 - to: bananiumDoor completed: - !type:SnapToGrid { } steps: - material: Bananium amount: 5 - doAfter: 15 + doAfter: 8 - to: paperDoor completed: - !type:SnapToGrid { } steps: - material: Paper - amount: 20 - doAfter: 15 + amount: 10 + doAfter: 8 - to: cardDoor completed: - !type:SnapToGrid { } steps: - material: Cardboard - amount: 5 - doAfter: 6 + amount: 10 + doAfter: 8 - node: metalDoor entity: MetalDoor edges: @@ -69,10 +69,10 @@ completed: - !type:SpawnPrototype prototype: SheetSteel1 - amount: 20 + amount: 10 steps: - tool: Anchoring - doAfter: 15 + doAfter: 8 - node: woodDoor entity: WoodDoor edges: @@ -80,10 +80,10 @@ completed: - !type:SpawnPrototype prototype: MaterialWoodPlank1 - amount: 20 + amount: 10 steps: - tool: Anchoring - doAfter: 15 + doAfter: 8 - node: plasmaDoor entity: PlasmaDoor edges: @@ -91,10 +91,10 @@ completed: - !type:SpawnPrototype prototype: SheetPlasma - amount: 20 + amount: 10 steps: - tool: Anchoring - doAfter: 15 + doAfter: 8 - node: goldDoor entity: GoldDoor edges: @@ -102,10 +102,10 @@ completed: - !type:SpawnPrototype prototype: IngotGold1 - amount: 20 + amount: 10 steps: - tool: Anchoring - doAfter: 15 + doAfter: 8 - node: silverDoor entity: SilverDoor edges: @@ -113,10 +113,10 @@ completed: - !type:SpawnPrototype prototype: IngotSilver1 - amount: 20 + amount: 10 steps: - tool: Anchoring - doAfter: 15 + doAfter: 8 - node: paperDoor entity: PaperDoor edges: @@ -124,10 +124,10 @@ completed: - !type:SpawnPrototype prototype: SheetPaper1 - amount: 20 + amount: 10 steps: - tool: Anchoring - doAfter: 15 + doAfter: 8 - node: cardDoor entity: CardDoor edges: @@ -137,7 +137,7 @@ sound: /Audio/Items/Toys/ToyFall2.ogg - !type:SpawnPrototype prototype: MaterialCardboard1 - amount: 5 + amount: 8 - !type:DeleteEntity {} steps: - tool: Slicing @@ -152,4 +152,4 @@ amount: 5 steps: - tool: Anchoring - doAfter: 15 + doAfter: 8