noD3wE-!9RNOUUq0m3{jk74f5fcWADFZ!
zy1KEZ6z#LfGf_`LFMyMG`o8C=;o`=*w>9tTvf}&f5#-VLMqaeAo%sRLG{
zQ~QlY7XF(?BW3w^PY>quJ2kV+smcOH4|4=xI@mkY+#^
z#y>65iT#!{oUJslkFlJONCk!`j6+`n5AYAz|Kykky9m$4=!w?mGds;ZXy>Srd?yCA
zNbzRr+-z}70rDiPW`hLQ(a$UKP7E2ypSV%>G)xclv9EvOS(JptdwB+8VZ125_uF4t
ze*`LnM_y_0{ZY9nO}xOzZvIs-W2V3?`O(G$YQ0N@If4t2_C)&PZbketvk?)8Bi!DC
z8^(V4W0?yTBi?fS9rqEJ^IkW^T%!`#T|X~l{r{C>|BZnCO@k8V=ZSSUzi?#!kovh{
zA!)zY!D~&_ff|KBgq2J>ncQyBj%#!7squaoi|&qs3rxiYwSG@-PFnIK%_XlwQN=~k
zzaeOUh$k3p&H`{N{Pb#oK*UB6I(^LW&)Y9rFJI+wOJgeX|66~hdHRb_P2WcA`p&*d
zApV$Or&sdIv_zcgW6TQTwR;_9C|RnNfjEc!J8_P^`dc-2zbw{NNp2{4pk5MF@j|LI
zVmpLratY+x>*IE!(BJvDGT=;b58iH}4@d7zm-ZZH8e_2YfuH|6H@0cyUgzRZxhwj3
zGx)W$XZOPv!7bQgvy$AQHidFSUyOazt<^vZWy>grBBLeLag6HNa`xN34QAes155Z9
zGTvx8AmF$ogivq4K)e&_df{~Aex&m0Lyh&lg$*YFn4(qf1u~afg{EFQ>-bbnQ#+M|
zcrEFE=`8PnIh>sINP1!Ja6|P!W1>Rk2;UZuRM>0$pbgyPB4IGxvklwS86o<9PFwph
z@RG>|(B6-pjDB8;k=%Eqn~knIN)m5KBvtI0ay7=mK^X#vVKO?n+G}WKOA)e&)X>l{
zaQaO~qNWVHz0q9WS|ydc`}2U2zhABfQJ>4RIdkG&-j}!ueIv^DE1Mpv{1PK7cAzlM
zabc`AbT1>1yPIP}X6$!ST0?uu(hv(Lm*Jh*q@mGRkCXG8j)=osMvKhtI7b(_xU_UH
zd9=4Md#v!Fw~z)O=7IC~rft?&p=;!cmN-*|{&UFwb+q#29jtDUZ#s&mN3aXv8RTa6
z#Oi(7**cM8-jJs(_@_0qnxlUjWW$6dNsVx~{`>Zg5VloEY#se1slf*S+|oB4GjAyI
zj?0`!w6FjCgi=2B9sqPS2wXDeQpOX~f~e~uQUd$nbgG(y3G8*h~$O+~zC
znN4>r9L4lS3Rg1g#+K%bI7zQ6ef6VfQmR9Cf>Fe%T9SV8ajQ|>AeX*N=a)BWp7=Fl%v!`VfoB$a@7}%n8?8I^dNW8q=HYiUgU^
zZ}x+J(dV-Wx+jOMetM>d+2uaQn_=h&r|*d9G#jE$5kLL%_vmkGkkBwAQXD;Fg{OiP4?B+GjM(d@-4D
zR~@mu+0AQD4qu@xO6PZNB`8roBj>xk!;PPC)7LEI?F?Iw@(c>T`%Ru51J<)6BR33%
z0qTi!!Y@`;S$XU@k-oviFvHgU%8CYdWSaSw=h!*~&GlQszB~U{7(JS2rZJ!;$=P_Q
zDf@qt)4}ft!t9(X_L#mYhW{av@OMQ9*x3Qp`ML;SewDGm3w{C8%HFcx!YB2Ax^hzn
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Mobs/Species/arachne.rsi/spider_body_front.png b/Resources/Textures/Mobs/Species/arachne.rsi/spider_body_front.png
new file mode 100644
index 0000000000000000000000000000000000000000..0171f16fe385fe420c6f1b1142b5381e2284ba92
GIT binary patch
literal 761
zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSoCO|{#S9F5M?jcysy3fA0|V1U
zPZ!6KiaBrZ9`qM>6gmF!{+8Vi+G2O6t>rz%CBtGXu=nNv`4z?wm8z7c6lHq3>b})`
z_pMSxSHic)aOSLUzju~yJ9%bb<>#{RUsQlrUqp7-u2zqhRC<9m~TO#Ecr>eQ`KzJ5W|QoS~ZL{9TeyS3u#mg`xS{f-Zc
zH_f%!X2A2MsQ$i*T>MNm)e}>_W+zHysQ0bC`&KU}RO?vs)5>*@^G?6XTR*qBXwtFA
z8^4=YdN(}xOj>-=W3fqaYOe1jv*p+4EHOEo_W!p@d(eyKnVA+ct77#2PhxNl{A2R0
zdpb*n)NwJE$t#b!F0?ssYWp|XHPA;)WQzDUp%86RR>uVfJSFu&(@%YlIrnpaYQAWK
zDo<#?QtY?iRXg^r%WppT=GK>T+b$K|ce7vG#C`gA#G7eO`R;X3=3HIuan6#L?fS0z
zL&DF`SgJptqxZXZuI_`E?Ms&2+_L26pSR6=nPzVzKYu(_&xt({v4}Q2eYn;6dH3B|
zW8+XQ(Y^MT3$0(+uIJ~^HIX`LxtxFb@_R{-x7O}C6S6jJ>n@>JZ!cb4Q~zoA3IjA^m*&&Ubxth`@pA}Idyk3R@{B*k#_1*$lJK{*`{;6U*7GLyP1~j
zeE)L{|Ekc^YTMW^zrDXo+~`y4mgbG+Z|7=u2#??YV$uJ~l}VU>`gfN9lgpc9^P48s
h0VVlTBRtc5eHpZXY!0a6OTm*tEKgTImvv4FO#o58J(mCg
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Mobs/Species/eyes.rsi/eyes.png b/Resources/Textures/Mobs/Species/eyes.rsi/eyes.png
new file mode 100644
index 0000000000000000000000000000000000000000..b6250e22b38a17c35b2b54789f66bb5cda1db308
GIT binary patch
literal 5553
zcmeHLd010d77wzDfU+qtI*oAw(U<*YD`7_yA&4vjF4dQp7kGv&B!L86pehy>DYz6x
z+^PsjQNew*D4Cj1VsF%-#4G%wDXtA_mcO{J?D4N`JHp_
z&CRB;(0R7jZq@_>!B!{;3+LUzb6pP>{BCSwBd-3s8TDXcmhV$rl>F?
zrpKiOg8ti|qUGBuD6e4r(()_S&dwh;ly&Ze7H8ZK$ViEwy6j9e**Q+o+j(Hzfqlr7^SjpC9IQV%`BOpX
zfO%S`qVsQUulSx7YzMcD6zl6B7g_DM%N*ngezo(8rP~N?em%Ej+ruBmI=t{)&=d9e
zcK#&iwRY?^E(@D7~|K?a=iT2gR2*G
zdfny4mCl)V7c}OVcJUikHM_grZ(g=4n_Yst_a^!*ZzxT#YK#313eS0%?0+h7(BtET
z&&@ZE{o(vFL9KbZ6Y|U~PH>qJGflYT$1v#(f0C_P)VT(S^BPTyHs`{Kv)
zqJ0;VI|?6E1z5a9+YZ*ubxpc+B|Jaz$nK)hJ=pz>!ZXvqICrNmIIpbYS^c*`9eMq>
z_n(TlvLh75Y*~EN8sD57LUn_$%O`>rOZSeM6QA5*cgUr2x27Sx`l0it7KysSf{U)8
zhCVsN_x-Ev(aDJ`fTizb~a_~yBBbx|7)MJiYTAX
z${j7yQ-1#JlH~@%{TC?Tog%{_eMYe6`i-&=n%cYkCx6twE*H6yf(+=*d
zUPwRicml_2f;O%!Ilj@MI_!Ms;?t+&nFY=c6=!yOo;sq|Om5()&(;+P!cP1!n45sM
z%&~C0*4lLLgqhmvFwxyXa=rZftoW;F$85=@w5cA5XY}(M+b3e#@W}_OWL8CE107k1
zgnqYNez`>z*IxXjb^Vmu8553vAzNK7>*$!grjGxp^)@Z71?kNb^qcgV^bHbPIwU)O
zVRMW4>tnjNmk%{>q2?c9%`GOi>myOLwHivuKP0W3gbC4H1!8!4s
zr_(|IV&}z4)blUL=QF3zB4@9YRaNc3dUXAklgI3itt0lDK6%=9_$g_|+B~PlSM;i;
znpHiOJ&$zhUl&vBpSf8wAF=LU->|E`Y%~A3)zr;?1e4vd*9xW=KK`(>%l>i4vVyo*
z`};L7OH#JnhDp!oFhcg|*XvX7vN%6G&WjN)+H`AEZHQ-1Z*IrtT4li&@;EPsSbC@X
zioLk}Vby%gliNz{7ueTEii%cG?I^EH*>ZAGN%^9^0~swBD=Tg$<<|(r_Q5$se?MC+
za>caJ($LKr%%9v>4=j8@$qk+w?V2@tT(ST9&c3R_$2w(Mb=!tKr%=KpN_IDG%*)O(
z_5WyH{lSN!-DXzarqQY2EteA*`wu_(ZgHp8(`F0uvG4LLESGi>0v2pcs5|C#c$Sm(
z<$l*S5q2);%>88_H81YxtRc|vmEN;esjRXl&RX^8pO3!WyQaSV6v9K5axx-OiZQZYt^$iWf#Bt%S0Shj(-Os49IoJ#e!g&tM8qY0QZy{0
zic|quJT6F8V-cyLk!Y$66onSiLki6_1H=$UAf`dpxJrvF6+{CjB3348`6Ln;C%*Pit`dnx
z;1!x-762a*flMXRxFau$5
zVLF$Nje=O9#z9pg38TF-KuG`;gUM#oq%01^kuWfb$v|L;!(qb^Mx((jHj6Ex(`ZI0
z3Cf$RRLc>NPF#+}VHA}j&NyHooaYxNKjQ|0-}`y13oDPS0w4*3`F8`EJBMI
z*rc&oEDjw+%waKL7M=b^X%VK@fJ!uA(x_y{(1;-|JP-^Z7BSQ*05DpBSa<AX+34(P99UN~iN^R34obN#pRCR36NMs7xMpl)h4eOH=-v
zwxM~5UPCDt;2JQ0icvJwQ4v_;(9_Uk0&Z+2BGK3sJOmvIL4zb?5~H60YiJ0KM-*`w
zSUrZz^|c)TgHk}aAaM+a7~-(#42X%M5(r_#bchWjTqX=^gpEqyM%O5%S{hO3Fe3#1?;+Abh}8dIh-@ZXOA&A*^9*Qt$bo
hzP5mNy-}2IJLTr*?u{XN5l)6@VNht`G5;0o{taf-31t8P
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Mobs/Species/eyes.rsi/meta.json b/Resources/Textures/Mobs/Species/eyes.rsi/meta.json
new file mode 100644
index 00000000000..a98aba406f1
--- /dev/null
+++ b/Resources/Textures/Mobs/Species/eyes.rsi/meta.json
@@ -0,0 +1,15 @@
+{
+ "version": 1,
+ "license": "CC-BY-SA-3.0",
+ "copyright": "Created by @Rane#7518",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "eyes",
+ "directions": 4
+ }
+ ]
+}
diff --git a/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon1.png b/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon1.png
new file mode 100644
index 0000000000000000000000000000000000000000..27741fdf314bc38be7153151d603479000af1891
GIT binary patch
literal 669
zcmV;O0%HA%P)$5Dx(m
zFBXfsFs^ZhFvIKhs_Q@?a2Eu|Znw+%d={V2CxgL2(&@BRt5s77QvgGJv)QP)!{Lxf
zBqH5zS3;qX0suChPIdoDARG?Ma5&VIZq5}t7z~=4e3$?qrcx<&lF#R5GMOk0#n$Wf
zbgvNx%x1I6<#LhTZYQJB=)MNvY>Qb6p90{%P$;MnB8HP#EGF%CTX=>j_YedE$8-R|
z2pY9PD*b+6(|S1pqs>SHF&0TClhWyQ6o&J|;UM$*{N4f71zSRDY#+4%AZuXAG5}6)
zJ*{FSF&>X~3xL8MAVy2#m^3I#?&oqjg$5#%$!M*-lmLq%x>zjq8dr$n%mCybVgTLx
zUR_f8)C2?Ph&LJyX|-C`y5LqQR|<#N5hY3%&StYJXt<{%0O37mT984J0?BUyP@joE
zOaO?F549B$#R;MmAA^~AnE_;<*&=3=1DK@06q*z%=`4(1e*jw4~
z0qlJMWovU6H!CGJl-MY-xwmdtq%iY)ns=JT%y?aMo6Y-_-gBJS`Tw5(^PJ}DNTn6v)$^dz}l
z?&{uG0e*DwrC2OVzu#ADv6;^I`F#40Q3}HmU~mHGDA`>A1U8Z_U5_|(ZouJi__HaQ
zb4ntSh&q9ItyYt6w|oCZ)ai881#Y-_Jg%Y$7#{#)v6!9+#DQ$JTE_40cff%7ZsL
z)@(La1XswMBT4plyIm@kirRiH^P2&PUpCc0o8Q&ftnh~bj4)&Ervm)TumCIo3*Z}`
WA1sKIggnat0000>)WwzxBKr~01&TMs}c%@WV_wUYPFI?BEi)4t02Yzh&P)}+3)w-zg#X-
zDwPz3@mqWv#0bC=C*w>eBcstsa=Dy%JRWspHk*mt?Us7It}P&@5XKH5PW1czd*+CH
zy=I<#amf@8*aR#6tkGuT&~3hV6jRB0QN)BpQv%Znx93ryd@e$n4R$MNZwy{|3K8G+z
z!Wb@C4gm4&)`v%71mO4kWiS|M;ZcBOY1xfC6eHr)fzRi=uS=y;5BGiuKv5kI2Xz3D
zbULj^5ex=jy*HoFRS*~g7kH2Lwg7s)9`;=ujfVCSW>Y>rs(-WDs2hPmKqp|B26zX=cKp8o0}g-#@aF*j10gEyIQQql
Q8~^|S07*qoM6N<$f*=3`Hvj+t
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon_large1.png b/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon_large1.png
new file mode 100644
index 0000000000000000000000000000000000000000..f9431f6428586fe569344878961bd645cbc04fc6
GIT binary patch
literal 762
zcmVgc
z)HGVt5GrUW(MCfaUs*`R6?PUu8&3|
zNvG3tb#*1>a@o1Oyxf|EOMu{L0LW@nhDS$7QYw{P@YQN1KA%r^cX!o}?e_MT;npOS
z0IYMloFtP;d3$?vgMWN{xLH0wKdZ(L0YI@wA`ywlP)iTC$+wedl~_5y~WPfkvBj3y>__7w^Rr`>L^
z5zz`*DNQVxW%cy*B;jyavm+Di%jHt5z#cw`quGZf5((9|PBO$gJv}9kQ>j#T)_MSj
znM}ql8BVj=Oq~EE3y3gB=JUBr#MYRT2ni7n!3I&PNX3w1u}F_;pC|#GC@tUs6Lhgy
zXaidIcHUNUn{!$Y^}?1i+)CY#N=3DoO#J%UXS&qe~DNc>iKw1&f>5L*PT;*8~QGffs!}
zpU=Pki~!)>Zr7AbC3$_n-??}$BvKPl@Or&&PN$QpR;%WCJR0t~kVr)!dh+Mb%Vi;e0@UO25G7E>wo((o??RzquGg!nR4V3jxrFbX&*%3O
z0E81G`|WlU5)_17DiwjiTW>rbi}%=(&*ww%*=%N(%jNq**lxEagrpwNU$2*_ffB3L
z${IWs0l-J2k@(Mp0$hEk3tY;H0N}k|Po8sfE##*a31Y2Q6cTGIE(O#1Pj;9&toXiW$VheODDlgT8zK?E?T*O80l5Ya3g
z4hJEF1z2KRP8L9d0(`w*ixt?Qz^Fn+hf<~lIGK9w2T~;8?RMdb)e4s!I1vDV(_;Z@
zaAJsPK?p0bYO~p7OCV?~nE~2@bb^MDJU|djc%Q%;i;ZYaz@K~`sb}CY@i-+99Y(s8
zAhX?W!`+Zni39-V>bIfvJK>}Bq&oirjJ71z@AtXHst`+{)9H8sBQF4W&yONKK#(DT
zyoWmEg6Am1XCX43PGd<}SpWz>hyvPj6oG^YkErDOS?<#jTvI6!Y&B08jIW6P@f20a
z0#hxX%$l3vJF)B8X%5)#dD~4${QyPKZkme+
R_X7X`002ovPDHLkV1mDMGcW)E
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon_large3.png b/Resources/Textures/Nyanotrasen/Structures/cocoon.rsi/cocoon_large3.png
new file mode 100644
index 0000000000000000000000000000000000000000..9a033961ffa27e1796d98c10f6fc9d563f13066a
GIT binary patch
literal 876
zcmV-y1C#uTP)P6p9*9R5b`t4M~gH+uwv|vr7wIu9v%9!kbKXc6WH6-}`4~`Dy;KodM1O
zXMq0~pwVbJn!mrlo5#n;AAbb^VFc^-x=E+g=JoZ}j(k4v%;$5{ZnsYYISByqTrOv7
zwVJuOxG?MW+Hj9uUtgQaWWv-r1tK&6;zS*dMolahvjAM5pPy|e7K??sy1FuzN`)+h
z4k{FY#EEjXTG^3ICM^VmdolqKFsu)og-`&AM8Z1e${_WsJ@>Nhc5BBe_9ejW?XBZB
zm`y#x5`1}ivC#uTHvG^27y#ncYSqq_b|M4;|
za|~gkCEcuJOs7*jPO%RF_xJZssZ{bB3Nbl}=HBV1Z
zwiJ4&5-<=Js4E;0Z#J9Wx8hhy0swb+ced-*Ob8%O#Hm!ut2qXwj8m{&E;Dt2K-~3Z
z-|aHx9D)b{5EUJdai!im;UbZUd3$@a5Tu<>M;N1I7(2#YZ_f>Sf#zjBr>G0;d{&+S
z01k;V?-3skhjz|8t_T9m
z+}|fW$GGwZB@4Y?FOY=*0ClCCHQ-*^ct8vPUUAI}K#JNiLu*@g_>hbjTa
zp9$BgLl%fe;>v~^j7|qqe@X^I;+0IbvLu-NH#yC###c+Y{tIbhlW
zM6IJ*<
Date: Tue, 6 Aug 2024 04:52:58 +0000
Subject: [PATCH 004/135] Automatic Changelog Update (#438)
---
Resources/Changelog/Changelog.yml | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml
index 35142b8bbfa..afe00fec1f2 100644
--- a/Resources/Changelog/Changelog.yml
+++ b/Resources/Changelog/Changelog.yml
@@ -4940,3 +4940,11 @@ Entries:
message: Added an unlockable PKA and Jetpack module to Salvage Cyborgs
id: 6218
time: '2024-08-06T01:14:31.0000000+00:00'
+- author: VMSolidus
+ changes:
+ - type: Add
+ message: Arachne have been reimplemented!
+ - type: Add
+ message: Oneirophages are back!
+ id: 6219
+ time: '2024-08-06T04:52:32.0000000+00:00'
From aed3baba152a568b0b291fe714beb68f6934761c Mon Sep 17 00:00:00 2001
From: VMSolidus
Date: Tue, 6 Aug 2024 01:28:53 -0400
Subject: [PATCH 005/135] CPR Remake (#487)
# Description
This is a re implementation and complete rewrite of the original
Nyanotrasen CPR feature, this time as its own completely standalone
system. Unlike the original CPR, this system requires no modification of
base game code, and can be toggled on and off via CVars while the server
is running.
Fixes #473
Fixes #49
# Changelog
:cl:
- add: CPR has been added to the game. People with CPR training can now
perform CPR on anyone who is in either crit or dead states.
- add: CPR Training has been added to the game as a new positive trait.
All medical staff start with this trait for free.
---------
Signed-off-by: VMSolidus
---
Content.Server/Atmos/Rotting/RottingSystem.cs | 107 +------------
.../Atmos/Rotting/SharedRottingSystem.cs | 141 +++++++++++++++++-
Content.Shared/CCVar/CCVars.cs | 49 ++++++
.../CPR/Components/CPRTrainingComponent.cs | 33 ++++
.../Medical/CPR/Systems/CPRSystem.CVars.cs | 27 ++++
.../Medical/CPR/Systems/CPRSystem.cs | 132 ++++++++++++++++
Resources/Audio/Effects/CPR.ogg | Bin 0 -> 68840 bytes
.../components/cpr-training-component.ftl | 6 +
Resources/Locale/en-US/traits/traits.ftl | 7 +
.../DeltaV/Roles/Jobs/Security/brigmedic.yml | 3 +
.../Prototypes/Roles/Jobs/Medical/chemist.yml | 4 +
.../Jobs/Medical/chief_medical_officer.yml | 1 +
.../Roles/Jobs/Medical/medical_doctor.yml | 4 +
.../Roles/Jobs/Medical/medical_intern.yml | 4 +
.../Roles/Jobs/Medical/paramedic.yml | 4 +
.../Roles/Jobs/Medical/senior_physician.yml | 4 +
Resources/Prototypes/Traits/skills.yml | 17 +++
17 files changed, 431 insertions(+), 112 deletions(-)
create mode 100644 Content.Shared/Medical/CPR/Components/CPRTrainingComponent.cs
create mode 100644 Content.Shared/Medical/CPR/Systems/CPRSystem.CVars.cs
create mode 100644 Content.Shared/Medical/CPR/Systems/CPRSystem.cs
create mode 100644 Resources/Audio/Effects/CPR.ogg
create mode 100644 Resources/Locale/en-US/medical/components/cpr-training-component.ftl
diff --git a/Content.Server/Atmos/Rotting/RottingSystem.cs b/Content.Server/Atmos/Rotting/RottingSystem.cs
index 47bac84e0ca..5070b3f197f 100644
--- a/Content.Server/Atmos/Rotting/RottingSystem.cs
+++ b/Content.Server/Atmos/Rotting/RottingSystem.cs
@@ -1,15 +1,9 @@
-using Content.Shared.Damage;
-using Content.Shared.Atmos;
using Content.Server.Atmos.EntitySystems;
using Content.Server.Body.Components;
using Content.Server.Temperature.Components;
+using Content.Shared.Atmos;
using Content.Shared.Atmos.Rotting;
-using Content.Shared.Examine;
-using Content.Shared.IdentityManagement;
-using Content.Shared.Mobs;
-using Content.Shared.Mobs.Components;
-using Content.Shared.Mobs.Systems;
-using Content.Shared.Rejuvenate;
+using Content.Shared.Damage;
using Robust.Server.Containers;
using Robust.Shared.Physics.Components;
using Robust.Shared.Timing;
@@ -22,83 +16,16 @@ public sealed class RottingSystem : SharedRottingSystem
[Dependency] private readonly AtmosphereSystem _atmosphere = default!;
[Dependency] private readonly ContainerSystem _container = default!;
[Dependency] private readonly DamageableSystem _damageable = default!;
- [Dependency] private readonly MobStateSystem _mobState = default!;
public override void Initialize()
{
base.Initialize();
- SubscribeLocalEvent(OnPerishableMapInit);
- SubscribeLocalEvent(OnMobStateChanged);
- SubscribeLocalEvent(OnPerishableExamined);
-
- SubscribeLocalEvent(OnShutdown);
- SubscribeLocalEvent(OnRottingMobStateChanged);
SubscribeLocalEvent(OnGibbed);
- SubscribeLocalEvent(OnRejuvenate);
SubscribeLocalEvent(OnTempIsRotting);
}
- private void OnPerishableMapInit(EntityUid uid, PerishableComponent component, MapInitEvent args)
- {
- component.RotNextUpdate = _timing.CurTime + component.PerishUpdateRate;
- }
-
- private void OnMobStateChanged(EntityUid uid, PerishableComponent component, MobStateChangedEvent args)
- {
- if (args.NewMobState != MobState.Dead && args.OldMobState != MobState.Dead)
- return;
-
- if (HasComp(uid))
- return;
-
- component.RotAccumulator = TimeSpan.Zero;
- component.RotNextUpdate = _timing.CurTime + component.PerishUpdateRate;
- }
-
- private void OnShutdown(EntityUid uid, RottingComponent component, ComponentShutdown args)
- {
- if (TryComp(uid, out var perishable))
- {
- perishable.RotNextUpdate = TimeSpan.Zero;
- }
- }
-
- private void OnRottingMobStateChanged(EntityUid uid, RottingComponent component, MobStateChangedEvent args)
- {
- if (args.NewMobState == MobState.Dead)
- return;
- RemCompDeferred(uid, component);
- }
-
- public bool IsRotProgressing(EntityUid uid, PerishableComponent? perishable)
- {
- // things don't perish by default.
- if (!Resolve(uid, ref perishable, false))
- return false;
-
- // only dead things or inanimate objects can rot
- if (TryComp(uid, out var mobState) && !_mobState.IsDead(uid, mobState))
- return false;
-
- if (_container.TryGetOuterContainer(uid, Transform(uid), out var container) &&
- HasComp(container.Owner))
- {
- return false;
- }
-
- var ev = new IsRottingEvent();
- RaiseLocalEvent(uid, ref ev);
-
- return !ev.Handled;
- }
-
- public bool IsRotten(EntityUid uid, RottingComponent? rotting = null)
- {
- return Resolve(uid, ref rotting, false);
- }
-
private void OnGibbed(EntityUid uid, RottingComponent component, BeingGibbedEvent args)
{
if (!TryComp(uid, out var physics))
@@ -112,36 +39,6 @@ private void OnGibbed(EntityUid uid, RottingComponent component, BeingGibbedEven
tileMix?.AdjustMoles(Gas.Ammonia, molsToDump);
}
- private void OnPerishableExamined(Entity perishable, ref ExaminedEvent args)
- {
- int stage = PerishStage(perishable, MaxStages);
- if (stage < 1 || stage > MaxStages)
- {
- // We dont push an examined string if it hasen't started "perishing" or it's already rotting
- return;
- }
-
- var isMob = HasComp(perishable);
- var description = "perishable-" + stage + (!isMob ? "-nonmob" : string.Empty);
- args.PushMarkup(Loc.GetString(description, ("target", Identity.Entity(perishable, EntityManager))));
- }
-
- ///
- /// Return an integer from 0 to maxStage representing how close to rotting an entity is. Used to
- /// generate examine messages for items that are starting to rot.
- ///
- public int PerishStage(Entity perishable, int maxStages)
- {
- if (perishable.Comp.RotAfter.TotalSeconds == 0 || perishable.Comp.RotAccumulator.TotalSeconds == 0)
- return 0;
- return (int)(1 + maxStages * perishable.Comp.RotAccumulator.TotalSeconds / perishable.Comp.RotAfter.TotalSeconds);
- }
-
- private void OnRejuvenate(EntityUid uid, RottingComponent component, RejuvenateEvent args)
- {
- RemCompDeferred(uid);
- }
-
private void OnTempIsRotting(EntityUid uid, TemperatureComponent component, ref IsRottingEvent args)
{
if (args.Handled)
diff --git a/Content.Shared/Atmos/Rotting/SharedRottingSystem.cs b/Content.Shared/Atmos/Rotting/SharedRottingSystem.cs
index 5e1758203a8..840818dee59 100644
--- a/Content.Shared/Atmos/Rotting/SharedRottingSystem.cs
+++ b/Content.Shared/Atmos/Rotting/SharedRottingSystem.cs
@@ -1,29 +1,85 @@
using Content.Shared.Examine;
using Content.Shared.IdentityManagement;
+using Content.Shared.Mobs;
using Content.Shared.Mobs.Components;
+using Content.Shared.Mobs.Systems;
+using Content.Shared.Rejuvenate;
+using Robust.Shared.Containers;
+using Robust.Shared.Timing;
namespace Content.Shared.Atmos.Rotting;
public abstract class SharedRottingSystem : EntitySystem
{
+ [Dependency] private readonly IGameTiming _timing = default!;
+ [Dependency] private readonly SharedContainerSystem _container = default!;
+ [Dependency] private readonly MobStateSystem _mobState = default!;
+
public const int MaxStages = 3;
public override void Initialize()
{
base.Initialize();
+ SubscribeLocalEvent(OnPerishableMapInit);
+ SubscribeLocalEvent(OnMobStateChanged);
+ SubscribeLocalEvent(OnPerishableExamined);
+
+ SubscribeLocalEvent(OnShutdown);
+ SubscribeLocalEvent(OnRottingMobStateChanged);
+ SubscribeLocalEvent(OnRejuvenate);
SubscribeLocalEvent(OnExamined);
}
- ///
- /// Return the rot stage, usually from 0 to 2 inclusive.
- ///
- public int RotStage(EntityUid uid, RottingComponent? comp = null, PerishableComponent? perishable = null)
+ private void OnPerishableMapInit(EntityUid uid, PerishableComponent component, MapInitEvent args)
{
- if (!Resolve(uid, ref comp, ref perishable))
- return 0;
+ component.RotNextUpdate = _timing.CurTime + component.PerishUpdateRate;
+ }
- return (int) (comp.TotalRotTime.TotalSeconds / perishable.RotAfter.TotalSeconds);
+ private void OnMobStateChanged(EntityUid uid, PerishableComponent component, MobStateChangedEvent args)
+ {
+ if (args.NewMobState != MobState.Dead && args.OldMobState != MobState.Dead)
+ return;
+
+ if (HasComp(uid))
+ return;
+
+ component.RotAccumulator = TimeSpan.Zero;
+ component.RotNextUpdate = _timing.CurTime + component.PerishUpdateRate;
+ }
+
+ private void OnPerishableExamined(Entity perishable, ref ExaminedEvent args)
+ {
+ int stage = PerishStage(perishable, MaxStages);
+ if (stage < 1 || stage > MaxStages)
+ {
+ // We dont push an examined string if it hasen't started "perishing" or it's already rotting
+ return;
+ }
+
+ var isMob = HasComp(perishable);
+ var description = "perishable-" + stage + (!isMob ? "-nonmob" : string.Empty);
+ args.PushMarkup(Loc.GetString(description, ("target", Identity.Entity(perishable, EntityManager))));
+ }
+
+ private void OnShutdown(EntityUid uid, RottingComponent component, ComponentShutdown args)
+ {
+ if (TryComp(uid, out var perishable))
+ {
+ perishable.RotNextUpdate = TimeSpan.Zero;
+ }
+ }
+
+ private void OnRottingMobStateChanged(EntityUid uid, RottingComponent component, MobStateChangedEvent args)
+ {
+ if (args.NewMobState == MobState.Dead)
+ return;
+ RemCompDeferred(uid, component);
+ }
+
+ private void OnRejuvenate(EntityUid uid, RottingComponent component, RejuvenateEvent args)
+ {
+ RemCompDeferred(uid);
}
private void OnExamined(EntityUid uid, RottingComponent component, ExaminedEvent args)
@@ -41,4 +97,75 @@ private void OnExamined(EntityUid uid, RottingComponent component, ExaminedEvent
args.PushMarkup(Loc.GetString(description, ("target", Identity.Entity(uid, EntityManager))));
}
+
+ ///
+ /// Return an integer from 0 to maxStage representing how close to rotting an entity is. Used to
+ /// generate examine messages for items that are starting to rot.
+ ///
+ public int PerishStage(Entity perishable, int maxStages)
+ {
+ if (perishable.Comp.RotAfter.TotalSeconds == 0 || perishable.Comp.RotAccumulator.TotalSeconds == 0)
+ return 0;
+ return (int)(1 + maxStages * perishable.Comp.RotAccumulator.TotalSeconds / perishable.Comp.RotAfter.TotalSeconds);
+ }
+
+ public bool IsRotProgressing(EntityUid uid, PerishableComponent? perishable)
+ {
+ // things don't perish by default.
+ if (!Resolve(uid, ref perishable, false))
+ return false;
+
+ // only dead things or inanimate objects can rot
+ if (TryComp(uid, out var mobState) && !_mobState.IsDead(uid, mobState))
+ return false;
+
+ if (_container.TryGetOuterContainer(uid, Transform(uid), out var container) &&
+ HasComp(container.Owner))
+ {
+ return false;
+ }
+
+ var ev = new IsRottingEvent();
+ RaiseLocalEvent(uid, ref ev);
+
+ return !ev.Handled;
+ }
+
+ public bool IsRotten(EntityUid uid, RottingComponent? rotting = null)
+ {
+ return Resolve(uid, ref rotting, false);
+ }
+
+ public void ReduceAccumulator(EntityUid uid, TimeSpan time)
+ {
+ if (!TryComp(uid, out var perishable))
+ return;
+
+ if (!TryComp(uid, out var rotting))
+ {
+ perishable.RotAccumulator -= time;
+ return;
+ }
+ var total = (rotting.TotalRotTime + perishable.RotAccumulator) - time;
+
+ if (total < perishable.RotAfter)
+ {
+ RemCompDeferred(uid, rotting);
+ perishable.RotAccumulator = total;
+ }
+
+ else
+ rotting.TotalRotTime = total - perishable.RotAfter;
+ }
+
+ ///
+ /// Return the rot stage, usually from 0 to 2 inclusive.
+ ///
+ public int RotStage(EntityUid uid, RottingComponent? comp = null, PerishableComponent? perishable = null)
+ {
+ if (!Resolve(uid, ref comp, ref perishable))
+ return 0;
+
+ return (int) (comp.TotalRotTime.TotalSeconds / perishable.RotAfter.TotalSeconds);
+ }
}
diff --git a/Content.Shared/CCVar/CCVars.cs b/Content.Shared/CCVar/CCVars.cs
index facbd1d71b6..3fc7e7247e6 100644
--- a/Content.Shared/CCVar/CCVars.cs
+++ b/Content.Shared/CCVar/CCVars.cs
@@ -2291,6 +2291,55 @@ public static readonly CVarDef
///
public static readonly CVarDef StationGoalsChance =
CVarDef.Create("game.station_goals_chance", 0.1f, CVar.SERVERONLY);
+
+
+ #region CPR System
+ ///
+ /// Controls whether the entire CPR system runs. When false, nobody can perform CPR. You should probably remove the trait too
+ /// if you are wishing to permanently disable the system on your server.
+ ///
+ public static readonly CVarDef EnableCPR =
+ CVarDef.Create("cpr.enable", true, CVar.REPLICATED | CVar.SERVER);
+
+ ///
+ /// Toggles whether or not CPR reduces rot timers(As an abstraction of delaying brain death, the IRL actual purpose of CPR)
+ ///
+ public static readonly CVarDef CPRReducesRot =
+ CVarDef.Create("cpr.reduces_rot", true, CVar.REPLICATED | CVar.SERVER);
+
+ ///
+ /// Toggles whether or not CPR heals airloss, included for completeness sake. I'm not going to stop you if your intention is to make CPR do nothing.
+ /// I guess it might be funny to troll your players with? I won't judge.
+ ///
+ public static readonly CVarDef CPRHealsAirloss =
+ CVarDef.Create("cpr.heals_airloss", true, CVar.REPLICATED | CVar.SERVER);
+
+ ///
+ /// The chance for a patient to be resuscitated when CPR is successfully performed.
+ /// Setting this above 0 isn't very realistic, but people who see CPR in movies and TV will expect CPR to work this way.
+ ///
+ public static readonly CVarDef CPRResuscitationChance =
+ CVarDef.Create("cpr.resuscitation_chance", 0.05f, CVar.REPLICATED | CVar.SERVER);
+
+ ///
+ /// By default, CPR reduces rot timers by an amount of seconds equal to the time spent performing CPR. This is an optional multiplier that can increase or decrease the amount
+ /// of rot reduction. Set it to 2 for if you want 3 seconds of CPR to reduce 6 seconds of rot.
+ ///
+ ///
+ /// If you're wondering why there isn't a CVar for setting the duration of the doafter, that's because it's not actually possible to have a timespan in cvar form
+ /// Curiously, it's also not possible for **shared** systems to set variable timespans. Which is where this system lives.
+ ///
+ public static readonly CVarDef CPRRotReductionMultiplier =
+ CVarDef.Create("cpr.rot_reduction_multiplier", 1f, CVar.REPLICATED | CVar.SERVER);
+
+ ///
+ /// By default, CPR heals airloss by 1 point for every second spent performing CPR. Just like above, this directly multiplies the healing amount.
+ /// Set it to 2 to get 6 points of airloss healing for every 3 seconds of CPR.
+ ///
+ public static readonly CVarDef CPRAirlossReductionMultiplier =
+ CVarDef.Create("cpr.airloss_reduction_multiplier", 1f, CVar.REPLICATED | CVar.SERVER);
+
+ #endregion
#region Contests System
diff --git a/Content.Shared/Medical/CPR/Components/CPRTrainingComponent.cs b/Content.Shared/Medical/CPR/Components/CPRTrainingComponent.cs
new file mode 100644
index 00000000000..e01250858a1
--- /dev/null
+++ b/Content.Shared/Medical/CPR/Components/CPRTrainingComponent.cs
@@ -0,0 +1,33 @@
+using Robust.Shared.GameStates;
+using Content.Shared.DoAfter;
+using Robust.Shared.Audio;
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.Medical.CPR
+{
+ [RegisterComponent, NetworkedComponent]
+ public sealed partial class CPRTrainingComponent : Component
+ {
+ [DataField]
+ public SoundSpecifier CPRSound = new SoundPathSpecifier("/Audio/Effects/CPR.ogg");
+
+ ///
+ /// How long the doafter for CPR takes
+ ///
+ [DataField]
+ public TimeSpan DoAfterDuration = TimeSpan.FromSeconds(3);
+
+ [DataField]
+ public int AirlossHeal = 6;
+
+ [DataField]
+ public float CrackRibsModifier = 1f;
+ public EntityUid? CPRPlayingStream;
+ }
+
+ [Serializable, NetSerializable]
+ public sealed partial class CPRDoAfterEvent : SimpleDoAfterEvent
+ {
+
+ }
+}
diff --git a/Content.Shared/Medical/CPR/Systems/CPRSystem.CVars.cs b/Content.Shared/Medical/CPR/Systems/CPRSystem.CVars.cs
new file mode 100644
index 00000000000..9840b8ffbd4
--- /dev/null
+++ b/Content.Shared/Medical/CPR/Systems/CPRSystem.CVars.cs
@@ -0,0 +1,27 @@
+using Content.Shared.CCVar;
+using Robust.Shared.Configuration;
+
+namespace Content.Shared.Medical.CPR
+{
+ public sealed partial class CPRSystem
+ {
+ [Dependency] private readonly IConfigurationManager _cfg = default!;
+
+ public bool EnableCPR { get; private set; }
+ public bool HealsAirloss { get; private set; }
+ public bool ReducesRot { get; private set; }
+ public float ResuscitationChance { get; private set; }
+ public float RotReductionMultiplier { get; private set; }
+ public float AirlossReductionMultiplier { get; private set; }
+
+ private void InitializeCVars()
+ {
+ Subs.CVar(_cfg, CCVars.EnableCPR, value => EnableCPR = value, true);
+ Subs.CVar(_cfg, CCVars.CPRHealsAirloss, value => HealsAirloss = value, true);
+ Subs.CVar(_cfg, CCVars.CPRReducesRot, value => ReducesRot = value, true);
+ Subs.CVar(_cfg, CCVars.CPRResuscitationChance, value => ResuscitationChance = value, true);
+ Subs.CVar(_cfg, CCVars.CPRRotReductionMultiplier, value => RotReductionMultiplier = value, true);
+ Subs.CVar(_cfg, CCVars.CPRAirlossReductionMultiplier, value => AirlossReductionMultiplier = value, true);
+ }
+ }
+}
diff --git a/Content.Shared/Medical/CPR/Systems/CPRSystem.cs b/Content.Shared/Medical/CPR/Systems/CPRSystem.cs
new file mode 100644
index 00000000000..799c0664a66
--- /dev/null
+++ b/Content.Shared/Medical/CPR/Systems/CPRSystem.cs
@@ -0,0 +1,132 @@
+using Content.Shared.Popups;
+using Content.Shared.Atmos.Rotting;
+using Content.Shared.Damage;
+using Content.Shared.DoAfter;
+using Content.Shared.Inventory;
+using Content.Shared.Mobs;
+using Content.Shared.Mobs.Components;
+using Content.Shared.Mobs.Systems;
+using Content.Shared.Verbs;
+using Robust.Shared.Network;
+using Robust.Shared.Utility;
+using Robust.Shared.Random;
+using Robust.Shared.Audio.Systems;
+
+namespace Content.Shared.Medical.CPR
+{
+ public sealed partial class CPRSystem : EntitySystem
+ {
+ [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
+ [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
+ [Dependency] private readonly MobStateSystem _mobStateSystem = default!;
+ [Dependency] private readonly DamageableSystem _damageable = default!;
+ [Dependency] private readonly MobThresholdSystem _mobThreshold = default!;
+ [Dependency] private readonly IRobustRandom _robustRandom = default!;
+ [Dependency] private readonly SharedRottingSystem _rottingSystem = default!;
+ [Dependency] private readonly InventorySystem _inventory = default!;
+ [Dependency] private readonly SharedAudioSystem _audio = default!;
+ [Dependency] private readonly INetManager _net = default!;
+ public override void Initialize()
+ {
+ base.Initialize();
+ InitializeCVars();
+ SubscribeLocalEvent>(AddCPRVerb);
+ SubscribeLocalEvent(OnCPRDoAfter);
+ }
+
+ private void AddCPRVerb(EntityUid uid, CPRTrainingComponent component, GetVerbsEvent args)
+ {
+ if (!EnableCPR || !args.CanInteract || !args.CanAccess
+ || !TryComp(args.Target, out var targetState)
+ || targetState.CurrentState == MobState.Alive)
+ return;
+
+ InnateVerb verb = new()
+ {
+ Act = () =>
+ {
+ StartCPR(uid, args.Target, component);
+ },
+ Text = Loc.GetString("cpr-verb"),
+ Icon = new SpriteSpecifier.Rsi(new("Interface/Alerts/human_alive.rsi"), "health4"),
+ Priority = 2
+ };
+ args.Verbs.Add(verb);
+ }
+
+ private void StartCPR(EntityUid performer, EntityUid target, CPRTrainingComponent cprComponent)
+ {
+ if (HasComp(target))
+ {
+ _popupSystem.PopupEntity(Loc.GetString("cpr-target-rotting", ("entity", target)), performer, performer);
+ return;
+ }
+
+ if (_inventory.TryGetSlotEntity(target, "outerClothing", out var outer))
+ {
+ _popupSystem.PopupEntity(Loc.GetString("cpr-must-remove", ("clothing", outer)), performer, performer, PopupType.MediumCaution);
+ return;
+ }
+
+ if (_inventory.TryGetSlotEntity(target, "mask", out var mask))
+ {
+ _popupSystem.PopupEntity(Loc.GetString("cpr-must-remove", ("clothing", mask)), performer, performer, PopupType.MediumCaution);
+ return;
+ }
+
+ if (_inventory.TryGetSlotEntity(performer, "mask", out var maskSelf))
+ {
+ _popupSystem.PopupEntity(Loc.GetString("cpr-must-remove-own-mask", ("clothing", maskSelf)), performer, performer, PopupType.MediumCaution);
+ return;
+ }
+
+ if (_net.IsServer)
+ {
+ _popupSystem.PopupEntity(Loc.GetString("cpr-start-second-person", ("target", target)), target, performer, PopupType.Medium);
+ _popupSystem.PopupEntity(Loc.GetString("cpr-start-second-person-patient", ("user", performer)), target, target, PopupType.Medium);
+ cprComponent.CPRPlayingStream = _audio.PlayPvs(cprComponent.CPRSound, performer).Value.Entity;
+ }
+
+ _doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, performer, cprComponent.DoAfterDuration, new CPRDoAfterEvent(), performer, target, performer)
+ {
+ BreakOnTargetMove = true,
+ BreakOnUserMove = true,
+ NeedHand = true,
+ BlockDuplicate = true
+ });
+ }
+
+ private void OnCPRDoAfter(EntityUid performer, CPRTrainingComponent component, CPRDoAfterEvent args)
+ {
+ component.CPRPlayingStream = _audio.Stop(component.CPRPlayingStream);
+
+ if (args.Target == null)
+ return;
+
+ if (HealsAirloss)
+ {
+ // There is PROBABLY a better way to do this, by all means let me know
+ var healing = new DamageSpecifier()
+ {
+ DamageDict = new()
+ {
+ { "Asphyxiation", -component.AirlossHeal * AirlossReductionMultiplier}
+ }
+ };
+ _damageable.TryChangeDamage(args.Target, healing, true, origin: performer);
+ }
+
+ if (ReducesRot)
+ _rottingSystem.ReduceAccumulator((EntityUid) args.Target, component.DoAfterDuration * RotReductionMultiplier);
+
+ if (_robustRandom.Prob(ResuscitationChance)
+ && _mobThreshold.TryGetThresholdForState((EntityUid) args.Target, MobState.Dead, out var threshold)
+ && TryComp(args.Target, out var damageableComponent)
+ && TryComp(args.Target, out var state)
+ && damageableComponent.TotalDamage < threshold)
+ {
+ _mobStateSystem.ChangeMobState(args.Target.Value, MobState.Critical, state, performer);
+ }
+ }
+ }
+}
diff --git a/Resources/Audio/Effects/CPR.ogg b/Resources/Audio/Effects/CPR.ogg
new file mode 100644
index 0000000000000000000000000000000000000000..2c7cedd2033c906029dcd1a8d90ab45b68bb0eba
GIT binary patch
literal 68840
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.mL>w?>>sa5J>hq2ux0H{*l6BSYS#*3Iz*
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