From 12088ee111dec77058a8e0b1196d7d6e5d30b43f Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Fri, 18 Dec 2020 00:38:43 +0100 Subject: [PATCH 01/29] Fix MobStateChangedMessage not reaching AISystem (#2760) --- .../GameObjects/Components/Mobs/State/SharedMobStateComponent.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Content.Shared/GameObjects/Components/Mobs/State/SharedMobStateComponent.cs b/Content.Shared/GameObjects/Components/Mobs/State/SharedMobStateComponent.cs index cd34d1297b..784fd84c3a 100644 --- a/Content.Shared/GameObjects/Components/Mobs/State/SharedMobStateComponent.cs +++ b/Content.Shared/GameObjects/Components/Mobs/State/SharedMobStateComponent.cs @@ -269,6 +269,7 @@ namespace Content.Shared.GameObjects.Components.Mobs.State var message = new MobStateChangedMessage(this, old, state); SendMessage(message); + Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, message); } bool IActionBlocker.CanInteract() From dc07718a7c4d4e92c8d29f933ebe3b8c7ea56702 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Fri, 18 Dec 2020 01:35:59 +0100 Subject: [PATCH 02/29] Fix click detection of sprite-rotated entities. --- Content.Client/GameObjects/Components/ClickableComponent.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Client/GameObjects/Components/ClickableComponent.cs b/Content.Client/GameObjects/Components/ClickableComponent.cs index 63d4622648..d55c58affe 100644 --- a/Content.Client/GameObjects/Components/ClickableComponent.cs +++ b/Content.Client/GameObjects/Components/ClickableComponent.cs @@ -46,7 +46,7 @@ namespace Content.Client.GameObjects.Components var localPos = Owner.Transform.InvWorldMatrix.Transform(worldPos); - var worldRotation = Owner.Transform.WorldRotation; + var worldRotation = new Angle(Owner.Transform.WorldRotation - sprite.Rotation); if (sprite.Directional) { localPos = new Angle(worldRotation).RotateVec(localPos); From a679e691c25a521db04972c8e085b290dc0c5fa6 Mon Sep 17 00:00:00 2001 From: daniel-cr Date: Fri, 18 Dec 2020 01:31:58 -0600 Subject: [PATCH 03/29] Conveyor Belt appearance when power is off (#2762) * Conveyor Belt appearance when power is off If the conveyor belt is running and the power turns off the belt stops pushing things but the animation continues. This changes it so the animation stops if there is no power and resumes when it returns. * Change from using Initialize, to OnAdd and OnRemove --- .../Components/Conveyor/ConveyorComponent.cs | 45 ++++++++++++++++--- .../Specific/Conveyor/conveyor.yml | 2 +- 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/Content.Server/GameObjects/Components/Conveyor/ConveyorComponent.cs b/Content.Server/GameObjects/Components/Conveyor/ConveyorComponent.cs index 2d50e5c052..d6441ae935 100644 --- a/Content.Server/GameObjects/Components/Conveyor/ConveyorComponent.cs +++ b/Content.Server/GameObjects/Components/Conveyor/ConveyorComponent.cs @@ -1,4 +1,4 @@ -#nullable enable +#nullable enable using System.Threading.Tasks; using Content.Server.GameObjects.Components.Interactable; using Content.Server.GameObjects.Components.Items.Storage; @@ -28,6 +28,8 @@ namespace Content.Server.GameObjects.Components.Conveyor { public override string Name => "Conveyor"; + [ViewVariables] private bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered; + /// /// The angle to move entities by in relation to the owner's rotation. /// @@ -41,7 +43,6 @@ namespace Content.Server.GameObjects.Components.Conveyor private float _speed; private ConveyorState _state; - /// /// The current state of this conveyor /// @@ -52,13 +53,45 @@ namespace Content.Server.GameObjects.Components.Conveyor set { _state = value; + UpdateAppearance(); + } + } - if (!Owner.TryGetComponent(out AppearanceComponent? appearance)) + public override void OnAdd() + { + base.OnAdd(); + if (Owner.TryGetComponent(out PowerReceiverComponent? receiver)) + { + receiver.OnPowerStateChanged += OnPowerChanged; + } + } + + public override void OnRemove() + { + base.OnRemove(); + if (Owner.TryGetComponent(out PowerReceiverComponent? receiver)) + { + receiver.OnPowerStateChanged -= OnPowerChanged; + } + } + + private void OnPowerChanged(object? sender, PowerStateEventArgs e) + { + UpdateAppearance(); + } + + private void UpdateAppearance() + { + if (Owner.TryGetComponent(out var appearance)) + { + if (Powered) { - return; + appearance.SetData(ConveyorVisuals.State, _state); + } + else + { + appearance.SetData(ConveyorVisuals.State, ConveyorState.Off); } - - appearance.SetData(ConveyorVisuals.State, value); } } diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Conveyor/conveyor.yml b/Resources/Prototypes/Entities/Constructible/Specific/Conveyor/conveyor.yml index 3a6e2f43bc..a456138250 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/Conveyor/conveyor.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/Conveyor/conveyor.yml @@ -27,6 +27,7 @@ drawdepth: FloorObjects - type: SignalReceiver maxTransmitters: 1 + - type: PowerReceiver - type: Conveyor - type: Appearance visuals: @@ -34,7 +35,6 @@ state_running: conveyor_started_cw state_stopped: conveyor_stopped_cw state_reversed: conveyor_started_cw_r - - type: PowerReceiver - type: Construction graph: ConveyorGraph node: entity From 740fe65a39c2d715d12d5df0537bc3e827419362 Mon Sep 17 00:00:00 2001 From: Swept Date: Fri, 18 Dec 2020 10:09:53 +0000 Subject: [PATCH 04/29] Fixes ID card sprites (#2764) --- .../Objects/Misc/identification_cards.yml | 46 +- .../Objects/Misc/id_cards.rsi/assigned.png | Bin 125 -> 0 bytes .../Objects/Misc/id_cards.rsi/idassistant.png | Bin 162 -> 171 bytes .../Objects/Misc/id_cards.rsi/idbotanist.png | Bin 182 -> 175 bytes .../Objects/Misc/id_cards.rsi/idcentcom.png | Bin 180 -> 184 bytes .../Misc/id_cards.rsi/idchiefengineer.png | Bin 245 -> 231 bytes .../id_cards.rsi/idchiefmedicalofficer.png | Bin 221 -> 234 bytes .../Misc/id_cards.rsi/idgeneticist.png | Bin 196 -> 187 bytes .../Misc/id_cards.rsi/idmedicaldoctor.png | Bin 194 -> 191 bytes .../Objects/Misc/id_cards.rsi/idparamedic.png | Bin 207 -> 197 bytes .../Misc/id_cards.rsi/idresearchdirector.png | Bin 218 -> 206 bytes .../Misc/id_cards.rsi/idroboticist.png | Bin 221 -> 214 bytes .../Objects/Misc/id_cards.rsi/idscientist.png | Bin 187 -> 178 bytes .../Misc/id_cards.rsi/idvirologist.png | Bin 211 -> 210 bytes .../Objects/Misc/id_cards.rsi/idwarden.png | Bin 165 -> 214 bytes .../Objects/Misc/id_cards.rsi/meta.json | 846 +++++------------- 16 files changed, 246 insertions(+), 646 deletions(-) delete mode 100644 Resources/Textures/Objects/Misc/id_cards.rsi/assigned.png diff --git a/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml b/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml index 16617ddfc2..2ea4423887 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml @@ -7,7 +7,6 @@ components: - type: Sprite sprite: Objects/Misc/id_cards.rsi - - type: Clothing Slots: - idcard @@ -26,9 +25,7 @@ - type: Sprite layers: - state: default - - state: assigned - state: idassistant - - type: PresetIdCard job: Assistant @@ -40,9 +37,7 @@ - type: Sprite layers: - state: gold - - state: assigned - state: idcaptain - - type: Clothing HeldPrefix: gold - type: PresetIdCard @@ -56,9 +51,7 @@ - type: Sprite layers: - state: default - - state: assigned - state: idsecurityofficer - - type: PresetIdCard job: SecurityOfficer @@ -70,9 +63,7 @@ - type: Sprite layers: - state: default - - state: assigned - state: idwarden - - type: PresetIdCard job: Warden @@ -84,9 +75,7 @@ - type: Sprite layers: - state: default - - state: assigned - state: idstationengineer - - type: PresetIdCard job: StationEngineer @@ -98,9 +87,7 @@ - type: Sprite layers: - state: default - - state: assigned - state: idmedicaldoctor - - type: PresetIdCard job: MedicalDoctor @@ -112,9 +99,7 @@ - type: Sprite layers: - state: default - - state: assigned - state: idcargotechnician - - type: PresetIdCard job: CargoTechnician @@ -126,9 +111,7 @@ - type: Sprite layers: - state: default - - state: assigned - state: idquartermaster - - type: PresetIdCard job: Quartermaster @@ -140,9 +123,7 @@ - type: Sprite layers: - state: default - - state: assigned - state: idscientist - - type: PresetIdCard job: Scientist @@ -154,9 +135,7 @@ - type: Sprite layers: - state: default - - state: assigned - state: idclown - - type: PresetIdCard job: Clown @@ -168,9 +147,7 @@ - type: Sprite layers: - state: default - - state: assigned - state: idmime - - type: PresetIdCard job: Mime @@ -182,7 +159,7 @@ # - type: Sprite # layers: # - state: default -# - state: assigned +# # - state: idchaplain # # - type: PresetIdCard @@ -196,9 +173,7 @@ - type: Sprite layers: - state: default - - state: assigned - state: idjanitor - - type: PresetIdCard job: Janitor @@ -210,9 +185,7 @@ - type: Sprite layers: - state: default - - state: assigned - state: idbartender - - type: PresetIdCard job: Bartender @@ -224,9 +197,7 @@ - type: Sprite layers: - state: default - - state: assigned - state: idcook - - type: PresetIdCard job: Chef @@ -238,13 +209,10 @@ - type: Sprite layers: - state: default - - state: assigned - state: idbotanist - - type: PresetIdCard job: Botanist - - type: entity parent: IDCardStandard id: HoPIDCard @@ -253,9 +221,7 @@ - type: Sprite layers: - state: silver - - state: assigned - state: idheadofpersonnel - - type: Clothing HeldPrefix: silver - type: PresetIdCard @@ -269,9 +235,7 @@ - type: Sprite layers: - state: silver - - state: assigned - state: idchiefengineer - - type: Clothing HeldPrefix: silver - type: PresetIdCard @@ -285,9 +249,7 @@ - type: Sprite layers: - state: silver - - state: assigned - state: idchiefmedicalofficer - - type: Clothing HeldPrefix: silver - type: PresetIdCard @@ -301,9 +263,7 @@ - type: Sprite layers: - state: silver - - state: assigned - state: idresearchdirector - - type: Clothing HeldPrefix: silver - type: PresetIdCard @@ -317,9 +277,7 @@ - type: Sprite layers: - state: silver - - state: assigned - state: idheadofsecurity - - type: Clothing HeldPrefix: silver - type: PresetIdCard @@ -333,9 +291,7 @@ - type: Sprite layers: - state: gold - - state: assigned - state: idcentcom - - type: Clothing HeldPrefix: gold - type: IdCard diff --git a/Resources/Textures/Objects/Misc/id_cards.rsi/assigned.png b/Resources/Textures/Objects/Misc/id_cards.rsi/assigned.png deleted file mode 100644 index ffaf2654ccf32d672d0879903a1f7f892ccb4a6a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 125 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz7f%<*kcv5PFBtLxC7c5-qR-#m z{L diff --git a/Resources/Textures/Objects/Misc/id_cards.rsi/idassistant.png b/Resources/Textures/Objects/Misc/id_cards.rsi/idassistant.png index 0f92b2edf1e836b822395803cca8de005b46734f..397b416a591ecaa5809de6df1dba0055e873c61b 100644 GIT binary patch delta 143 zcmV;A0C4}J0jmL!B!2;OQb$4nuFf3k0001GNkl; xpAT>?tu_>(e}M{n$&{4?tnm#2002Ji1Y7JT>k=T2F8}}l00>D%PDHLkV1lO7I*8b-9*&{Po&I;|*Cp<_upsLq> n);5-JV0nP={R0310B<`1W!6O*A^z`200000NkvXXu0mjf2xT|m diff --git a/Resources/Textures/Objects/Misc/id_cards.rsi/idbotanist.png b/Resources/Textures/Objects/Misc/id_cards.rsi/idbotanist.png index effef4daf33309192ae33a48397f1c8d3e82426e..f5dfdb86629a95fc39ad7527f15b0941b3ea1be4 100644 GIT binary patch delta 147 zcmdnSxSnx>N`0B9i(^PcYqA9E;slYNCP99QPF{xXJ9++JJX)qIyk1^h;S|G!r%tzK zJbJ$_=pBbzkchtdaSoO)#*2Imk#d!jCcf%Zux45DRA7>fL+ch=G}znPIPvLd%XlVZ1yHK;Y@>=d#Wzp$Py`|2C%p delta 154 zcmZ3_xQ%gwN`0-Ti(^Q|oa6)v*2M`TJxvq&Bs>G(m`#6Zzw5@jluKt6ZZqZ;Oa9}| zOzzsh+iRxs43DcD?#L($XfUZ*ChYuK-*#ehPe>_?tD*yM`-C?PSy6rynI(Wg$v< diff --git a/Resources/Textures/Objects/Misc/id_cards.rsi/idcentcom.png b/Resources/Textures/Objects/Misc/id_cards.rsi/idcentcom.png index c0ee96e36521c06216263f68080d50a6c7628597..25b7017a708426506ecf8398e33f92794fc2f86c 100644 GIT binary patch delta 156 zcmdnOxPx(mNGZx^prw85kIfJY5_^B3hFZBv=zopr0COZhApigX delta 152 zcmV;J0B8TW0ki>-B!7EJL_t(|oMT`Z1*2dTjDnF47_kZR8u#_2);00004y{qX(f)d?HdZ|4(S zD=(g)c&&)>c!|aTlm9Y#j3iGxocTY+s;N`LRU!Vc?tDSk%`&cYmhm;PS{gA}vdp&d zm0@63@Rq#b)EMLtBE`UJdZs9)`(R+fYXMh31x>CCwZ6R?5-uNdEVw$j4%uGh`9F8B z=jqSY+v8FTBE4?ZEP5>Pgd<4Cq30>sVSxr*5bP0l+XkK Dsx(br delta 217 zcmaFP_?2;jO8p*B7srr_ImrnUtcw#wdYUHkNq7dHS)2BKej^Y>dd+_Le)DP`5Qxv0 zRXWL2a=@wUDO2Cef`60$UY1BPnr3KVVDM-85ka3LS}D^mxkcD1bER2!S@_B_a2KU~ zNO2PhE1YG)a5G4Pmz&j#;bLY(q?dG_<)))&f^PBfY!Bj__?BVPVuridr??$#NIx9t zQ1anzXWEbVZ+xTX-QWFHtNC=$pRx%e_0@|c|4m*rZ^BcsD+3LGZx^prw85kIrc)B=-M6@O+NU$zW5b0@}$S2VmdSY$b_xX)L z5a~7h;rq?2c|agOUsfr~Uhja@nx{;CFF6=Xr6pe5FYQZEaub}GDHmqSa5AtV$MWvt zhKRzT0}bhi106yHq>hIFHUHeNc=AE8^mKzc(Kp;K)GT^@L1W)5drdxtW1j*IxZDnE dNU(y;XHb4`qHB{LtO#@!gQu&X%Q~loCIFc|L|*^^ delta 166 zcmaFGc$aa4it7?j7srr_ImrnUtcw#wdYUHkNq7dHS)2BKej^Y>dd+_Le)DP`5Qxv0 zRXWL2a=@wUDO2A|4#rYxiP!e3eF;ioiWAG^!j?9y(Qw!{=Ut$~8jFny2R1*{P_X*Z z^Jw+I**}j@Ncpj{*IVM8ZqDIscF&LLBJp46i+pX-k%!nBcmN0(7=kNIbc1rWs~CX5 M)78&qol`;+01|jcGXMYp diff --git a/Resources/Textures/Objects/Misc/id_cards.rsi/idgeneticist.png b/Resources/Textures/Objects/Misc/id_cards.rsi/idgeneticist.png index 56d8e50c90ac5fbe69663ea0e47f8de7106c2346..1303135aa5aff3870fe09fb7c72a4cfce7ee6b7c 100644 GIT binary patch delta 159 zcmV;Q0AT;b0lNW^B!7ZQL_t(og<}{6qhJ(_f)NiGi46e9+C~4-#r8MH5v`vh0J1!K z`kwzFfJ|d^6sdq|ppyVe4v3ktmtjeUGngI_2f!=`(F5WDT7Us}z|hEs!x|73gsI9I z{~g4gND7AoFZVIbzB_}U`9#Md$PuJCfEde1!6+C7qhJ&;Fc>f}0060RFwDy5jYR+e N002ovPDHLkV1jBIKd1lz delta 168 zcmdnZc!Y6+N`1Gdi(^Q|oa6)v*2M`TJxvq&Bsv41MC^WHzw5@oXBLaT1o6mZi~sGP zx9|CXAPCIJ=~H4i2s|vX%R(XTSX`T`mdKI;Vst0QQ+gs{jB1 diff --git a/Resources/Textures/Objects/Misc/id_cards.rsi/idmedicaldoctor.png b/Resources/Textures/Objects/Misc/id_cards.rsi/idmedicaldoctor.png index 3e716b01953b3a3fc154abe06b903d9e6261745a..9e390bb606fd14bb0d4cb290545f9c57cfbf94df 100644 GIT binary patch delta 163 zcmX@axSw%?N`0HBi(^PcYqA9E;slYNCP99QPF{xNw_N{UJo?T2xZqlOafMS16P^YI z1xY+QKhJjY4MCqJSrL;S`gGP#v1CZIG?jIn#GI7&#&zM#cMMt4e$$v&@Uq!R_c1MM zx}dS|)&80FJf4lES&xOj1GFvBK!(eWkr@aW3XGKnS}Ou1 P7=Xaj)z4*}Q$iB}+cZ3I delta 166 zcmV;X09pUP0m1>0B!7uXL_t(|oMT`Z1*2dTjDnF47>QBjSi9&yy4e2aIHL4Y>;T8w zMgOIwq%g#vJ$ptKM=+71cu9scrS_5U0GQ>}b_CH5h?%h$g{Hd$Xkj_Y4xj}X@N75= z2nM53eARz5{}_@CJ+*NO!?}fRL`4x%ij3l`Fwy`%K&<7XU>_8Wf>AIE7#J8B0Q@r} U5T{hMw*UYD07*qoM6N<$f^zjnF8}}l diff --git a/Resources/Textures/Objects/Misc/id_cards.rsi/idparamedic.png b/Resources/Textures/Objects/Misc/id_cards.rsi/idparamedic.png index 2a1fe45f390773b074d3a7dd4f12e97a24da837a..1881839e9658d2570fb600f091ee1997f2deb0dd 100644 GIT binary patch delta 169 zcmX@lc$9I1N_~%~i(^PcYqA9E;slYNCP99QPF{xNw_N{UJo?T2xZv9PN(`H9s(#J; zuh8I=Tr9G(p)=yEx6z!BpH8ys9C_6}bECNS>^wz-1q>qB4H&$c6&$XcG|0WV($%(b zB5%8?f)+>bqt*Xr|2#fHgm1Z-UZTbJ4ZRC~x*S(LA-Ke%LE^NM`#}w`)doPoz~HdR Vqtm}=T_yt%c)I$ztaD0e0s!@~MJoUR delta 179 zcmX@gc%E^BO8qoX7srr_ImrnUtcw#wdYUHkNpuE2iP-(Ze%FnE&ny;w3F48-7XRBn zZ{PF(KoFRb)2GC4Ah^n}K~t|cP=Yo3Db4>aJC a00M@jnI4@pl@eqafWXt$&t;ucLK6V;1V|kK diff --git a/Resources/Textures/Objects/Misc/id_cards.rsi/idresearchdirector.png b/Resources/Textures/Objects/Misc/id_cards.rsi/idresearchdirector.png index 13f49572043bb95fa010a66bfab0ecdb2cd8704a..420378538c9f25c2cac248d8d4a381d80e9627e9 100644 GIT binary patch delta 178 zcmV;j08Rhe0nP!CB!87jL_t(og<}{6qhJ(_f)NiGi46d5HM{>HnpsMl;qSAnV6m^a z4iT-NA^@^nI(_MXWB}sB97PFWB1SLB*QAJ(0*G<|EXau!r@8}Z30R0R8y3_u8Ot!m zZyln&D`}YshekFW)_|xWOjXYK?;!3(QaBuVxsPG?-5CVUCo4J*L5?8B0mN873P!;w g7zLw%fq{Vm0KmpborLW{q5uE@07*qoM6N<$f)r3j#Q*>R delta 190 zcmX@dc#Cm@O8r7l7srr_ImrnUtcw#wdYUHkNq7dHS)2BKej^Y>dd+_Le)DP`5Qxv0 zRXWMDiE;a^yY(->Ed4*RvE}$FC|nR?l9jK8eTN{zH-c;WxXDKiqN*`m zj-d;HMFA}6VSw&YK+T|sfdS8kqkyO&OjXYK?;!3(QeYi;xigPp_T3o-%_lkzL5?8B o0mN873P!;w7zLw%fq{Vm0Ae6m?0RRGi~s-t07*qoM6N<$f;PcP%m4rY delta 193 zcmcb{c$aa4O8pW~7srr_ImrnUtcw#wdYUHkNpuEY$-VGjK6cF)C&j=j%`%7Wj{obe zqnR!4=S*TgymAjSPdi`yf?3KORt%DJ&fNVE1{+(sEE`%ST$g|1J8*M@zyh%ZrLcuJ zRoHosUtm43h(YX&fx~x=1!WfwA81HF9Oz&m5j@rSpLK_o^~97HjnjWiq}`wE7$PFL qR3p@~d5MVsnx|mb1R8Kj00G0%`4MmCTDCed0D-5gpUXO@geCwaj8ZB9 diff --git a/Resources/Textures/Objects/Misc/id_cards.rsi/idscientist.png b/Resources/Textures/Objects/Misc/id_cards.rsi/idscientist.png index 7322d0b8bc7c2d954787d6fd22cb281141322165..a5be2ca63228245faa280bed3a3113b2fb4873a1 100644 GIT binary patch delta 150 zcmV;H0BQfb0kQ#*B!78HL_t(og<}{6qhJ(_f)NiGi4A~mgZ}^MVx<=fiPldM09k%A zcmIE60ODhF6sdq|pp(F;16W8=d@Aq2z&gNek^|KpGc>Z{um(g0VXAV*e+O|VlEUG@ z%Y6*9@6I4-KGAUqas(+3Aja}hFbYP&C>R9{3=9kaEnqHr(+^)4`~Uy|07*qoM6N<$ Eg8dyjMF0Q* delta 159 zcmdnQxSMf;N_~^3i(^Q|oa6)v*2M`TJxvq&Bsv4H%aSm9#o)!jy^+iRsjNf<`wZWrhRrKq&Nw)qx7}7jqG#nP$^WuP z=6V=?IdHm`XY>1W3R+zqK~q-EaSU4NzUC>|sz3uS2@qg-_Cv2S?x)d41|aZs^>bP0 Hl+XkK@Sj9| diff --git a/Resources/Textures/Objects/Misc/id_cards.rsi/idvirologist.png b/Resources/Textures/Objects/Misc/id_cards.rsi/idvirologist.png index bbcf4456f06d6235cd887065daa363e2eaabe060..cc0b6c4774e7a8620980b9e98c6bbe8c6b51ebc4 100644 GIT binary patch delta 182 zcmV;n07?JT0n!1GB!8JnL_t(og<}{6qhJ(_f)NiGi46e9+C~4-#r8MH5v?B=U?SFX zDJdz2eNC|pAR30TIf_)kLaK%(8P0IFQ{7@p?I$h-kU`9hy8pT)rH}j7nDX>m$T*7c}VJ{m&^NEf_kRwQO05O)2 kf>AIEM!_gxU|?VX0RK)X3zSgd;Q#;t07*qoM6N<$fQBjSi9&yy4e2aIHL3t0!+kM zE+r+!u&*hWK}t#rjRB!fPsO50RW#hC<`)fE7AY}002ovPDHLkV1m8;N%#N& diff --git a/Resources/Textures/Objects/Misc/id_cards.rsi/idwarden.png b/Resources/Textures/Objects/Misc/id_cards.rsi/idwarden.png index f2c207fa17139d49b7c5b3a335d3d451126e0111..0b4086478caee80731fde6cdd45785545bef8503 100644 GIT binary patch delta 186 zcmV;r07d_$0oDPKB!8VrL_t(oh3%9v3d1lAMZZFh)HR?nhsxMPc@$*rog73mm{Kaa zX%d3 Date: Fri, 18 Dec 2020 11:18:29 +0000 Subject: [PATCH 05/29] Prunes weapon descriptions (#2765) --- .../Objects/Weapons/Guns/Battery/battery_guns.yml | 4 ++-- .../Entities/Objects/Weapons/Guns/LMGs/lmgs.yml | 4 ++-- .../Objects/Weapons/Guns/Launchers/launchers.yml | 4 ++-- .../Objects/Weapons/Guns/Pistols/pistols.yml | 14 +++++++------- .../Objects/Weapons/Guns/Rifles/rifles.yml | 14 +++++++------- .../Entities/Objects/Weapons/Guns/SMGs/smgs.yml | 2 +- .../Objects/Weapons/Guns/Shotguns/shotguns.yml | 8 ++++---- .../Objects/Weapons/Guns/Snipers/snipers.yml | 6 +++--- 8 files changed, 28 insertions(+), 28 deletions(-) diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml index 00df4ea10a..43d4ee7eb9 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Battery/battery_guns.yml @@ -2,7 +2,7 @@ name: retro laser gun parent: BaseItem id: LaserGun - description: A weapon using light amplified by the stimulated emission of radiation. Ancient inefficient model. + description: A weapon using light amplified by the stimulated emission of radiation. components: - type: Sprite netsync: false @@ -42,7 +42,7 @@ name: laser cannon parent: BaseItem id: LaserCannon - description: With the L.A.S.E.R. cannon, the lasing medium is enclosed in a tube lined with uranium-235 and subjected to high neutron flux in a nuclear reactor core. This incredible technology may help YOU achieve high excitation rates with small laser volumes! + description: Pew pew. components: - type: Sprite netsync: false diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/LMGs/lmgs.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/LMGs/lmgs.yml index 1708167025..fdf5f67b87 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/LMGs/lmgs.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/LMGs/lmgs.yml @@ -38,7 +38,7 @@ name: L6 SAW id: LMGL6 parent: LMGBase - description: A rather traditionally made L6 SAW with a pleasantly lacquered wooden pistol grip. This one is unmarked. + description: A rather traditionally made LMG with a pleasantly lacquered wooden pistol grip. components: - type: Sprite sprite: Objects/Weapons/Guns/LMGs/l6.rsi @@ -74,7 +74,7 @@ name: pulemyot kalashnikova id: LMGPK parent: LMGBase - description: Kalashnikov's Machinegun, a well preserved and maintained antique weapon of war. + description: A well preserved and maintained antique weapon of war. components: - type: Sprite sprite: Objects/Weapons/Guns/LMGs/pk.rsi diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Launchers/launchers.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Launchers/launchers.yml index 3b4d8fd1c0..b8cd8d9c9d 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Launchers/launchers.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Launchers/launchers.yml @@ -15,7 +15,7 @@ name: china lake parent: LauncherBase id: LauncherChinaLake - description: This centuries-old design was recently rediscovered and adapted for use in modern battlefields. Working similar to a pump-action combat shotgun, its light weight and robust design quickly made it a popular weapon. It uses specialised grenade shells. + description: PLOOP components: - type: Sprite sprite: Objects/Weapons/Guns/Launchers/china_lake.rsi @@ -48,7 +48,7 @@ name: RPG-7 parent: LauncherBase id: LauncherRocket - description: A modified ancient rocket-propelled grenade launcher, this design is centuries old, but well preserved. + description: A modified ancient rocket-propelled grenade launcher. components: - type: Sprite sprite: Objects/Weapons/Guns/Launchers/rocket.rsi diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Pistols/pistols.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Pistols/pistols.yml index c4d8aa2b28..c979894e65 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Pistols/pistols.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Pistols/pistols.yml @@ -108,7 +108,7 @@ name: giskard parent: PistolBase id: PistolGiskard - description: A popular "Frozen Star" brand pocket pistol chambered for the ubiquitous .35 auto round. Uses standard capacity magazines. + description: A popular "Frozen Star" brand pocket pistol. components: - type: Sprite sprite: Objects/Weapons/Guns/Pistols/giskard.rsi @@ -219,7 +219,7 @@ name: mandella parent: PistolBase id: PistolMandella - description: A rugged, robust operator handgun with inbuilt silencer. Chambered in caseless rifle ammunition, this time-tested handgun is your absolute choice if you need to take someone down silently, as it's deadly, produces no sound, and leaves no trace. + description: A rugged, robust operator handgun with inbuilt silencer. components: - type: Sprite sprite: Objects/Weapons/Guns/Pistols/mandella.rsi @@ -253,7 +253,7 @@ name: mk 58 parent: PistolBase id: PistolMk58 - description: The NT Mk58 is a cheap, ubiquitous sidearm, that was produced by a NanoTrasen subsidiary. + description: A cheap, ubiquitous sidearm, produced by a NanoTrasen subsidiary. components: - type: Sprite sprite: Objects/Weapons/Guns/Pistols/mk58.rsi @@ -285,7 +285,7 @@ name: mk 58 (wood) parent: PistolBase id: PistolMk58Wood - description: The NT Mk58 is a cheap, ubiquitous sidearm, that was produced by a NanoTrasen subsidiary. + description: A cheap, ubiquitous sidearm, that was produced by a NanoTrasen subsidiary. components: - type: Sprite sprite: Objects/Weapons/Guns/Pistols/mk58_wood.rsi @@ -317,7 +317,7 @@ name: molly parent: PistolBase id: PistolMolly - description: An experimental fully automatic pistol, designed as a middle ground between SMGs and Pistols. Primarily employed in CQC scenarios or as a civilian self defence tool. Takes both highcap pistol and smg mags. + description: An experimental fully automatic pistol. components: - type: Sprite sprite: Objects/Weapons/Guns/Pistols/molly.rsi @@ -347,7 +347,7 @@ name: olivaw parent: PistolBase id: PistolOlivaw - description: A popular "Frozen Star" machine pistol. This one has a two-round burst-fire mode and is chambered for .35 auto. It can use normal and high capacity magazines. + description: A popular "Frozen Star" machine pistol. components: - type: Sprite sprite: Objects/Weapons/Guns/Pistols/olivaw_civil.rsi @@ -380,7 +380,7 @@ name: paco parent: PistolBase id: PistolPaco - description: A modern and reliable sidearm for the soldier in the field. Commonly issued as a sidearm to Ironhammer Operatives. + description: A modern and reliable sidearm for the soldier in the field. components: - type: Sprite sprite: Objects/Weapons/Guns/Pistols/paco.rsi diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Rifles/rifles.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Rifles/rifles.yml index 1d144ed9e7..161e87fa22 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Rifles/rifles.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Rifles/rifles.yml @@ -34,7 +34,7 @@ name: AKMS parent: RifleBase id: RifleAk - description: Weapon of the oppressed, oppressors, and extremists of all flavours. This is a copy of an ancient semi-automatic rifle chambered for .30 Rifle. If it won't fire, percussive maintenance should get it working again. It is known for its easy maintenance, and low price. This gun is not in active military service anymore, but has become ubiquitous among criminals and insurgents. This is a high-quality copy, which has an automatic fire mode. + description: An iconic weapon of war. components: - type: Sprite sprite: Objects/Weapons/Guns/Rifles/ak.rsi @@ -73,7 +73,7 @@ name: black AK parent: RifleBase id: RifleBlackAk - description: Weapon of the oppressed, oppressors, and extremists of all flavours. This is a copy of an ancient semi-automatic rifle chambered for .30 Rifle. If it won't fire, percussive maintenance should get it working again. It is known for its easy maintenance, and low price. This gun is not in active military service anymore, but has become ubiquitous among criminals and insurgents. This is a high-quality copy, which has an automatic fire mode. + description: An iconic weapon of war; painted black. components: - type: Sprite sprite: Objects/Weapons/Guns/Rifles/black_ak.rsi @@ -112,7 +112,7 @@ name: Z8 Bulldog parent: RifleBase id: RifleCarbine - description: The Z8 Bulldog is an older bullpup carbine model, made by Frozen Star. + description: An older bullpup carbine model, made by Frozen Star. components: - type: Sprite sprite: Objects/Weapons/Guns/Rifles/carbine.rsi @@ -155,7 +155,7 @@ name: Dallas parent: RifleBase id: RifleDallas - description: Dallas is a pulse-action air-cooled automatic assault rifle made by unknown manufacturer. This weapon is very rare, but deadly efficient. It's used by elite mercenaries, assassins or bald marines. + description: A pulse-action air-cooled automatic assault rifle. components: - type: Sprite sprite: Objects/Weapons/Guns/Rifles/dallas.rsi @@ -195,7 +195,7 @@ name: STS-35 parent: RifleBase id: RifleSTS - description: The rugged STS-35 is a durable automatic weapon, popular on frontier worlds. Uses .30 Rifle rounds. This one is unmarked. + description: A rugged and durable automatic weapon. components: - type: Sprite sprite: Objects/Weapons/Guns/Rifles/sts.rsi @@ -237,7 +237,7 @@ name: Vintorez parent: RifleBase id: RifleVintorez - description: This gun is a copy of a design from a country that no longer exists. It is still highly prized for its armor piercing capabilities. + description: Highly prized for its armor piercing capabilities. components: - type: Sprite sprite: Objects/Weapons/Guns/Rifles/vintorez.rsi @@ -276,7 +276,7 @@ name: Wintermute parent: RifleBase id: RifleWintermute - description: A high end military grade assault rifle, designed as a modern ballistic infantry weapon. Primarily used by and produced for IH troops. + description: A high end military grade assault rifle. components: - type: Sprite sprite: Objects/Weapons/Guns/Rifles/wintermute.rsi diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/SMGs/smgs.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/SMGs/smgs.yml index e044460f3e..171c3ac910 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/SMGs/smgs.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/SMGs/smgs.yml @@ -122,7 +122,7 @@ name: Drozd parent: SmgBase id: SmgDrozd - description: An excellent fully automatic Heavy SMG. Rifled to take a larger caliber than a typical submachine gun, but unlike other heavy SMGs makes use of increased caliber to achieve excellent armor penetration capabilities. Suffers a bit less from poor recoil control and has worse than average fire rate. + description: An excellent fully automatic Heavy SMG. components: - type: Sprite sprite: Objects/Weapons/Guns/SMGs/drozd.rsi diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml index 36978465b2..9e43bdc4a0 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Shotguns/shotguns.yml @@ -32,7 +32,7 @@ name: Bojevic parent: ShotgunBase id: ShotgunBojevic - description: It's a magazine-fed shotgun designed for close quarters combat, nicknamed 'Striker' by boarding parties. A robust and reliable design allows you to swap magazines on the go and dump as many shells at your foes as you want... if you can manage the recoil, of course. + description: It's a magazine-fed shotgun designed for close quarters combat. components: - type: Sprite netsync: false @@ -120,7 +120,7 @@ name: Bull parent: ShotgunBase id: ShotgunBull - description: A Frozen Star pump-action shotgun. A marvel of engineering, this gun is often used by Ironhammer tactical units. Due to shorter than usual barrels, recoil kicks slightly harder. + description: A Frozen Star pump-action shotgun. components: - type: Sprite sprite: Objects/Weapons/Guns/Shotguns/bull.rsi @@ -150,7 +150,7 @@ name: Gladstone parent: ShotgunBase id: ShotgunGladstone - description: It is a next-generation Frozen Star shotgun intended as a cost-effective competitor to the aging NT "Regulator 1000". It has a semi-rifled lightweight full-length barrel which gives it exceptional accuracy with all types of ammunition, with a high-capacity magazine tube below it. + description: A next-generation Frozen Star shotgun. components: - type: Sprite sprite: Objects/Weapons/Guns/Shotguns/gladstone.rsi @@ -167,7 +167,7 @@ name: Regulator 1000 parent: ShotgunBase id: ShotgunRegulator - description: Designed for close quarters combat, the Regulator is widely regarded as a weapon of choice for repelling boarders. Some may say that it's too old, but it actually proved itself useful. + description: Ol' reliable. components: - type: Sprite sprite: Objects/Weapons/Guns/Shotguns/regulator.rsi diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Snipers/snipers.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Snipers/snipers.yml index 5718881ebe..3b7cb37869 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Snipers/snipers.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Snipers/snipers.yml @@ -34,7 +34,7 @@ name: Kardashev-Mosin parent: SniperBase id: SniperBoltGun - description: Weapon for hunting, or endless trench warfare. If you’re on a budget, it’s a darn good rifle for just about everything. + description: Weapon for hunting, or endless trench warfare. components: - type: Sprite sprite: Objects/Weapons/Guns/Snipers/bolt_gun.rsi @@ -50,7 +50,7 @@ name: Kardashev-Mosin parent: SniperBase id: SniperBoltGunWood - description: Weapon for hunting, or endless trench warfare. If you’re on a budget, it’s a darn good rifle for just about everything. + description: Weapon for hunting, or endless trench warfare. components: - type: Sprite sprite: Objects/Weapons/Guns/Snipers/bolt_gun_wood.rsi @@ -64,7 +64,7 @@ name: Hristov parent: SniperBase id: SniperHeavy - description: A portable anti-armour rifle, fitted with a scope, it was originally designed for use against armoured exosuits. It is capable of punching through windows and non-reinforced walls with ease. Fires armor piercing 14.5mm shells. + description: A portable anti-armour rifle. Fires armor piercing 14.5mm shells. components: - type: Sprite sprite: Objects/Weapons/Guns/Snipers/heavy_sniper.rsi From 9c381dc174dc88c1bbb1678c9741727113889227 Mon Sep 17 00:00:00 2001 From: Swept Date: Fri, 18 Dec 2020 11:42:02 +0000 Subject: [PATCH 06/29] Shuttle can be called even when comms console is off (#2763) --- .../Components/Command/CommunicationsConsoleComponent.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Content.Server/GameObjects/Components/Command/CommunicationsConsoleComponent.cs b/Content.Server/GameObjects/Components/Command/CommunicationsConsoleComponent.cs index c32d7d9f91..2e3f6f6f48 100644 --- a/Content.Server/GameObjects/Components/Command/CommunicationsConsoleComponent.cs +++ b/Content.Server/GameObjects/Components/Command/CommunicationsConsoleComponent.cs @@ -1,4 +1,4 @@ -#nullable enable +#nullable enable using Content.Server.GameObjects.Components.Power.ApcNetComponents; using Content.Server.GameObjects.EntitySystems; using Content.Server.Utility; @@ -77,11 +77,12 @@ namespace Content.Server.GameObjects.Components.Command { if (!eventArgs.User.TryGetComponent(out IActorComponent? actor)) return; - +/* if (!Powered) { return; } +*/ OpenUserInterface(actor.playerSession); } } From 19bd739b0de81b9ed776613c80fdcf995483a726 Mon Sep 17 00:00:00 2001 From: Morshu32 Date: Fri, 18 Dec 2020 20:12:53 +0100 Subject: [PATCH 07/29] PreventCollision with strap component while buckled to it (#2694) * AvoidCollision if collided entity is the one that the character is buckled to * Attempt to PreventCollision after the player is unbuckled but still colliding with StrapComponent * Moved PreventCollide to the Shared script. * Add WakeBody to keep updating the physics collision while being on a collidable strap component. * Addressed some of metalgearsloth's suggestions: - Made EntityBuckledTo,IsOnStrapEntityThisFrame and DontCollide not virtual -Made EntityBuckledTo nullable -Don't call update on Paused BuckleComponents -Removed EntityBuckledTo variable declaration in BuckleComponent because it's not needed anymore -Call TryUnbuckle if (!IsOnStrapEntityThisFrame && DontCollide) to set BuckledTo entity to null. * Formatting Co-authored-by: DrSmugleaf * Formatting Co-authored-by: DrSmugleaf * Formatting again :P Co-authored-by: DrSmugleaf * Formatting Co-authored-by: DrSmugleaf * Formatting Co-authored-by: DrSmugleaf * Renamed variable EntityBuckledTo to LastEntityBuckledTo * As per DrSmugLeaf suggestion: Added [ComponentDependency] to the Body variable. Co-authored-by: DrSmugleaf --- .../Components/Buckle/BuckleComponent.cs | 4 ++- .../Components/Buckle/BuckleComponent.cs | 26 ++++++++++++-- .../GameObjects/EntitySystems/BuckleSystem.cs | 8 +++++ .../Buckle/SharedBuckleComponent.cs | 36 ++++++++++++++++--- 4 files changed, 67 insertions(+), 7 deletions(-) diff --git a/Content.Client/GameObjects/Components/Buckle/BuckleComponent.cs b/Content.Client/GameObjects/Components/Buckle/BuckleComponent.cs index 491be6c91d..a3020c85bc 100644 --- a/Content.Client/GameObjects/Components/Buckle/BuckleComponent.cs +++ b/Content.Client/GameObjects/Components/Buckle/BuckleComponent.cs @@ -1,4 +1,4 @@ -using Content.Shared.GameObjects.Components.Buckle; +using Content.Shared.GameObjects.Components.Buckle; using Robust.Client.GameObjects; using Robust.Shared.GameObjects; using Robust.Shared.Interfaces.GameObjects; @@ -27,6 +27,8 @@ namespace Content.Client.GameObjects.Components.Buckle } _buckled = buckle.Buckled; + LastEntityBuckledTo = buckle.LastEntityBuckledTo; + DontCollide = buckle.DontCollide; if (!Owner.TryGetComponent(out SpriteComponent ownerSprite)) { diff --git a/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs b/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs index 5fef60e9de..d6bdd0fa58 100644 --- a/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs +++ b/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs @@ -27,6 +27,7 @@ using Robust.Shared.Interfaces.Timing; using Robust.Shared.IoC; using Robust.Shared.Localization; using Robust.Shared.Maths; +using Robust.Shared.Physics; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; @@ -49,7 +50,6 @@ namespace Content.Server.GameObjects.Components.Buckle /// [ViewVariables] private float _range; - /// /// The amount of time that must pass for this entity to /// be able to unbuckle after recently buckling. @@ -69,6 +69,7 @@ namespace Content.Server.GameObjects.Components.Buckle public Vector2 BuckleOffset { get; private set; } private StrapComponent? _buckledTo; + /// /// The strap that this component is buckled to. @@ -266,6 +267,8 @@ namespace Content.Server.GameObjects.Components.Buckle AppearanceComponent?.SetData(BuckleVisuals.Buckled, true); BuckledTo = strap; + LastEntityBuckledTo = BuckledTo.Owner.Uid; + DontCollide = true; ReAttach(strap); UpdateBuckleStatus(); @@ -418,8 +421,9 @@ namespace Content.Server.GameObjects.Components.Buckle { drawDepth = BuckledTo.SpriteComponent.DrawDepth - 1; } + - return new BuckleComponentState(Buckled, drawDepth); + return new BuckleComponentState(Buckled, drawDepth, LastEntityBuckledTo, DontCollide); } bool IInteractHand.InteractHand(InteractHandEventArgs eventArgs) @@ -427,6 +431,24 @@ namespace Content.Server.GameObjects.Components.Buckle return TryUnbuckle(eventArgs.User); } + + public void Update() + { + if (!DontCollide || Body == null) + return; + + Body.WakeBody(); + + if (!IsOnStrapEntityThisFrame && DontCollide) + { + DontCollide = false; + TryUnbuckle(Owner); + Dirty(); + } + + IsOnStrapEntityThisFrame = false; + } + /// /// Allows the unbuckling of the owning entity through a verb if /// anyone right clicks them. diff --git a/Content.Server/GameObjects/EntitySystems/BuckleSystem.cs b/Content.Server/GameObjects/EntitySystems/BuckleSystem.cs index 1993021296..596aa1c319 100644 --- a/Content.Server/GameObjects/EntitySystems/BuckleSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/BuckleSystem.cs @@ -26,6 +26,14 @@ namespace Content.Server.GameObjects.EntitySystems SubscribeLocalEvent(ContainerModified); } + public override void Update(float frameTime) + { + foreach (var comp in ComponentManager.EntityQuery(false)) + { + comp.Update(); + } + } + public override void Shutdown() { base.Shutdown(); diff --git a/Content.Shared/GameObjects/Components/Buckle/SharedBuckleComponent.cs b/Content.Shared/GameObjects/Components/Buckle/SharedBuckleComponent.cs index 221d1cb845..068ce878c7 100644 --- a/Content.Shared/GameObjects/Components/Buckle/SharedBuckleComponent.cs +++ b/Content.Shared/GameObjects/Components/Buckle/SharedBuckleComponent.cs @@ -1,30 +1,54 @@ -using System; +#nullable enable +using System; using Content.Shared.GameObjects.Components.Strap; using Content.Shared.GameObjects.EntitySystems; using Content.Shared.Interfaces.GameObjects.Components; using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.ComponentDependencies; +using Robust.Shared.GameObjects.Components; using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Physics; using Robust.Shared.Serialization; namespace Content.Shared.GameObjects.Components.Buckle { - public abstract class SharedBuckleComponent : Component, IActionBlocker, IEffectBlocker, IDraggable + public abstract class SharedBuckleComponent : Component, IActionBlocker, IEffectBlocker, IDraggable, ICollideSpecial { public sealed override string Name => "Buckle"; public sealed override uint? NetID => ContentNetIDs.BUCKLE; - /// /// True if the entity is buckled, false otherwise. /// public abstract bool Buckled { get; } + public EntityUid? LastEntityBuckledTo { get; set; } + public bool IsOnStrapEntityThisFrame { get; set; } + public bool DontCollide { get; set; } public abstract bool TryBuckle(IEntity user, IEntity to); + [ComponentDependency] protected IPhysicsComponent? Body; + + bool ICollideSpecial.PreventCollide(IPhysBody collidedwith) + { + if (collidedwith.Entity.Uid == LastEntityBuckledTo) + { + IsOnStrapEntityThisFrame = true; + return Buckled || DontCollide; + } + + return false; + } + bool IActionBlocker.CanMove() { return !Buckled; } + public override void Initialize() + { + base.Initialize(); + Owner.TryGetComponent(out Body); + } bool IActionBlocker.CanChangeDirection() { @@ -50,13 +74,17 @@ namespace Content.Shared.GameObjects.Components.Buckle [Serializable, NetSerializable] public sealed class BuckleComponentState : ComponentState { - public BuckleComponentState(bool buckled, int? drawDepth) : base(ContentNetIDs.BUCKLE) + public BuckleComponentState(bool buckled, int? drawDepth, EntityUid? lastEntityBuckledTo, bool dontCollide) : base(ContentNetIDs.BUCKLE) { Buckled = buckled; DrawDepth = drawDepth; + LastEntityBuckledTo = lastEntityBuckledTo; + DontCollide = dontCollide; } public bool Buckled { get; } + public EntityUid? LastEntityBuckledTo { get; } + public bool DontCollide { get; } public int? DrawDepth; } From 9bb42d52517623ddc03b9a998ceb960eae0e80cc Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Fri, 18 Dec 2020 23:55:29 +0100 Subject: [PATCH 08/29] Don't fail to start server if invalid jobs exist in preferences. --- Content.Server/GameTicking/GameTicker.JobController.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Content.Server/GameTicking/GameTicker.JobController.cs b/Content.Server/GameTicking/GameTicker.JobController.cs index 32fb69e2e8..1051af0f65 100644 --- a/Content.Server/GameTicking/GameTicker.JobController.cs +++ b/Content.Server/GameTicking/GameTicker.JobController.cs @@ -45,7 +45,11 @@ namespace Content.Server.GameTicking .Where(j => { var (jobId, priority) = j; - var job = _prototypeManager.Index(jobId); + if (!_prototypeManager.TryIndex(jobId, out JobPrototype job)) + { + // Job doesn't exist, probably old data? + return false; + } if (job.IsHead != heads) { return false; From 185923a7da3dee8cb759f9f0e4040133996ad37c Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Sat, 19 Dec 2020 02:34:41 +0100 Subject: [PATCH 09/29] Fix errors. about mommi config variables --- Content.Server/MoMMILink.cs | 6 ++++++ Content.Shared/CCVars.cs | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Content.Server/MoMMILink.cs b/Content.Server/MoMMILink.cs index 1455598c47..facd9ce93f 100644 --- a/Content.Server/MoMMILink.cs +++ b/Content.Server/MoMMILink.cs @@ -82,6 +82,12 @@ namespace Content.Server var password = _configurationManager.GetCVar(CCVars.StatusMoMMIPassword); + if (string.IsNullOrEmpty(password)) + { + response.StatusCode = (int) HttpStatusCode.Forbidden; + return true; + } + OOCPostMessage message = null; try { diff --git a/Content.Shared/CCVars.cs b/Content.Shared/CCVars.cs index 06a99baa82..db9b5bc90c 100644 --- a/Content.Shared/CCVars.cs +++ b/Content.Shared/CCVars.cs @@ -12,10 +12,10 @@ namespace Content.Shared */ public static readonly CVarDef StatusMoMMIUrl = - CVarDef.Create("status.mommiurl", null); + CVarDef.Create("status.mommiurl", "", CVar.SERVERONLY); public static readonly CVarDef StatusMoMMIPassword = - CVarDef.Create("status.mommipassword", null); + CVarDef.Create("status.mommipassword", "", CVar.SERVERONLY); /* From 89f8d0f34c35c6cb1694bf7dbd62c2185f82efdc Mon Sep 17 00:00:00 2001 From: GraniteSidewalk <32942106+GraniteSidewalk@users.noreply.github.com> Date: Fri, 18 Dec 2020 20:14:26 -0600 Subject: [PATCH 10/29] Cargo Telepad (#2579) * Cargo telepad * fixes error * more efficient tile lookup Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> --- Content.Client/IgnoredComponents.cs | 5 +- .../UserInterface/Cargo/CargoConsoleMenu.cs | 3 +- .../Components/Cargo/CargoConsoleComponent.cs | 135 +++++++++++------- .../Components/Cargo/CargoTelepadComponent.cs | 101 +++++++++++++ Resources/Audio/Machines/phasein.ogg | Bin 0 -> 20244 bytes Resources/Audio/Misc/windowsXP_error.ogg | Bin 0 -> 12623 bytes Resources/Audio/Misc/windowsXP_shutdown.ogg | Bin 0 -> 17519 bytes Resources/Audio/Misc/windowsXP_startup.ogg | Bin 0 -> 27591 bytes .../Constructible/Specific/cargo_telepad.yml | 26 ++++ .../Power/cargo_teleporter.rsi/meta.json | 45 ++++++ .../Power/cargo_teleporter.rsi/pad-beam.png | Bin 0 -> 1660 bytes .../Power/cargo_teleporter.rsi/pad-idle.png | Bin 0 -> 1138 bytes .../cargo_teleporter.rsi/pad-offline.png | Bin 0 -> 580 bytes 13 files changed, 262 insertions(+), 53 deletions(-) create mode 100644 Content.Server/GameObjects/Components/Cargo/CargoTelepadComponent.cs create mode 100644 Resources/Audio/Machines/phasein.ogg create mode 100644 Resources/Audio/Misc/windowsXP_error.ogg create mode 100644 Resources/Audio/Misc/windowsXP_shutdown.ogg create mode 100644 Resources/Audio/Misc/windowsXP_startup.ogg create mode 100644 Resources/Prototypes/Entities/Constructible/Specific/cargo_telepad.yml create mode 100644 Resources/Textures/Constructible/Power/cargo_teleporter.rsi/meta.json create mode 100644 Resources/Textures/Constructible/Power/cargo_teleporter.rsi/pad-beam.png create mode 100644 Resources/Textures/Constructible/Power/cargo_teleporter.rsi/pad-idle.png create mode 100644 Resources/Textures/Constructible/Power/cargo_teleporter.rsi/pad-offline.png diff --git a/Content.Client/IgnoredComponents.cs b/Content.Client/IgnoredComponents.cs index 9df1ab57ce..b1a223cee4 100644 --- a/Content.Client/IgnoredComponents.cs +++ b/Content.Client/IgnoredComponents.cs @@ -1,4 +1,4 @@ -namespace Content.Client +namespace Content.Client { public static class IgnoredComponents { @@ -225,7 +225,8 @@ "MachineFrame", "MachineBoard", "ChemicalAmmo", - "BiologicalSurgeryData" + "BiologicalSurgeryData", + "CargoTelepad", }; } } diff --git a/Content.Client/UserInterface/Cargo/CargoConsoleMenu.cs b/Content.Client/UserInterface/Cargo/CargoConsoleMenu.cs index b955ec5493..697c73a689 100644 --- a/Content.Client/UserInterface/Cargo/CargoConsoleMenu.cs +++ b/Content.Client/UserInterface/Cargo/CargoConsoleMenu.cs @@ -109,7 +109,8 @@ namespace Content.Client.UserInterface.Cargo var buttons = new HBoxContainer(); CallShuttleButton = new Button() { - Text = Loc.GetString("Call Shuttle"), + //Text = Loc.GetString("Call Shuttle"), + Text = Loc.GetString("Activate Telepad"), //Shuttle code pending TextAlign = Label.AlignMode.Center, SizeFlagsHorizontal = SizeFlags.FillExpand }; diff --git a/Content.Server/GameObjects/Components/Cargo/CargoConsoleComponent.cs b/Content.Server/GameObjects/Components/Cargo/CargoConsoleComponent.cs index 35c9577c7a..b48ebd83bb 100644 --- a/Content.Server/GameObjects/Components/Cargo/CargoConsoleComponent.cs +++ b/Content.Server/GameObjects/Components/Cargo/CargoConsoleComponent.cs @@ -1,4 +1,4 @@ -#nullable enable +#nullable enable using Content.Server.Cargo; using Content.Server.GameObjects.Components.Power.ApcNetComponents; using Content.Server.GameObjects.EntitySystems; @@ -10,10 +10,15 @@ using Robust.Server.GameObjects.Components.UserInterface; using Robust.Server.Interfaces.GameObjects; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Systems; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Interfaces.Map; using Robust.Shared.IoC; using Robust.Shared.Log; +using Robust.Shared.Maths; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; +using System.Collections.Generic; +using System.Linq; namespace Content.Server.GameObjects.Components.Cargo { @@ -22,6 +27,7 @@ namespace Content.Server.GameObjects.Components.Cargo public class CargoConsoleComponent : SharedCargoConsoleComponent, IActivate { [Dependency] private readonly ICargoOrderDataManager _cargoOrderDataManager = default!; + [Dependency] private readonly IMapManager _mapManager = default!; [ViewVariables] public int Points = 1000; @@ -113,59 +119,88 @@ namespace Content.Server.GameObjects.Components.Cargo switch (message) { case CargoConsoleAddOrderMessage msg: - { - if (msg.Amount <= 0 || _bankAccount == null) { - break; - } - - _cargoOrderDataManager.AddOrder(orders.Database.Id, msg.Requester, msg.Reason, msg.ProductId, msg.Amount, _bankAccount.Id); - break; - } - case CargoConsoleRemoveOrderMessage msg: - { - _cargoOrderDataManager.RemoveOrder(orders.Database.Id, msg.OrderNumber); - break; - } - case CargoConsoleApproveOrderMessage msg: - { - if (_requestOnly || - !orders.Database.TryGetOrder(msg.OrderNumber, out var order) || - _bankAccount == null) - { - break; - } - - PrototypeManager.TryIndex(order.ProductId, out CargoProductPrototype product); - if (product == null!) - break; - var capacity = _cargoOrderDataManager.GetCapacity(orders.Database.Id); - if (capacity.CurrentCapacity == capacity.MaxCapacity) - break; - if (!_cargoConsoleSystem.ChangeBalance(_bankAccount.Id, (-product.PointCost) * order.Amount)) - break; - _cargoOrderDataManager.ApproveOrder(orders.Database.Id, msg.OrderNumber); - UpdateUIState(); - break; - } - case CargoConsoleShuttleMessage _: - { - var approvedOrders = _cargoOrderDataManager.RemoveAndGetApprovedFrom(orders.Database); - orders.Database.ClearOrderCapacity(); - // TODO replace with shuttle code - - // TEMPORARY loop for spawning stuff on top of console - foreach (var order in approvedOrders) - { - if (!PrototypeManager.TryIndex(order.ProductId, out CargoProductPrototype product)) - continue; - for (var i = 0; i < order.Amount; i++) + if (msg.Amount <= 0 || _bankAccount == null) { - Owner.EntityManager.SpawnEntity(product.Product, Owner.Transform.Coordinates); + break; } + + _cargoOrderDataManager.AddOrder(orders.Database.Id, msg.Requester, msg.Reason, msg.ProductId, msg.Amount, _bankAccount.Id); + break; + } + case CargoConsoleRemoveOrderMessage msg: + { + _cargoOrderDataManager.RemoveOrder(orders.Database.Id, msg.OrderNumber); + break; + } + case CargoConsoleApproveOrderMessage msg: + { + if (_requestOnly || + !orders.Database.TryGetOrder(msg.OrderNumber, out var order) || + _bankAccount == null) + { + break; + } + + PrototypeManager.TryIndex(order.ProductId, out CargoProductPrototype product); + if (product == null!) + break; + var capacity = _cargoOrderDataManager.GetCapacity(orders.Database.Id); + if (capacity.CurrentCapacity == capacity.MaxCapacity) + break; + if (!_cargoConsoleSystem.ChangeBalance(_bankAccount.Id, (-product.PointCost) * order.Amount)) + break; + _cargoOrderDataManager.ApproveOrder(orders.Database.Id, msg.OrderNumber); + UpdateUIState(); + break; + } + case CargoConsoleShuttleMessage _: + { + //var approvedOrders = _cargoOrderDataManager.RemoveAndGetApprovedFrom(orders.Database); + //orders.Database.ClearOrderCapacity(); + + // TODO replace with shuttle code + // TEMPORARY loop for spawning stuff on telepad (looks for a telepad adjacent to the console) + IEntity? cargoTelepad = null; + var indices = Owner.Transform.Coordinates.ToVector2i(Owner.EntityManager, _mapManager); + var offsets = new Vector2i[] { new Vector2i(0, 1), new Vector2i(1, 1), new Vector2i(1, 0), new Vector2i(1, -1), + new Vector2i(0, -1), new Vector2i(-1, -1), new Vector2i(-1, 0), new Vector2i(-1, 1), }; + var adjacentEntities = new List>(); //Probably better than IEnumerable.concat + foreach (var offset in offsets) + { + adjacentEntities.Add((indices+offset).GetEntitiesInTileFast(Owner.Transform.GridID)); + } + + foreach (var enumerator in adjacentEntities) + { + foreach (IEntity entity in enumerator) + { + if (entity.HasComponent() && entity.TryGetComponent(out var powerReceiver) && powerReceiver.Powered) + { + cargoTelepad = entity; + break; + } + } + } + if (cargoTelepad != null) + { + if (cargoTelepad.TryGetComponent(out var telepadComponent)) + { + var approvedOrders = _cargoOrderDataManager.RemoveAndGetApprovedFrom(orders.Database); + orders.Database.ClearOrderCapacity(); + foreach (var order in approvedOrders) + { + if (!PrototypeManager.TryIndex(order.ProductId, out CargoProductPrototype product)) + continue; + for (var i = 0; i < order.Amount; i++) + { + telepadComponent.QueueTeleport(product); + } + } + } + } + break; } - break; - } } } diff --git a/Content.Server/GameObjects/Components/Cargo/CargoTelepadComponent.cs b/Content.Server/GameObjects/Components/Cargo/CargoTelepadComponent.cs new file mode 100644 index 0000000000..a85c8386a3 --- /dev/null +++ b/Content.Server/GameObjects/Components/Cargo/CargoTelepadComponent.cs @@ -0,0 +1,101 @@ +#nullable enable +using Content.Server.GameObjects.Components.Power.ApcNetComponents; +using Content.Shared.Interfaces.GameObjects.Components; +using Content.Shared.Prototypes.Cargo; +using Robust.Server.GameObjects; +using Robust.Server.GameObjects.EntitySystems; +using Robust.Shared.Audio; +using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Components.Timers; +using Robust.Shared.GameObjects.Systems; +using System.Collections.Generic; + +namespace Content.Server.GameObjects.Components.Cargo +{ + + //This entire class is a PLACEHOLDER for the cargo shuttle. + + [RegisterComponent] + public class CargoTelepadComponent : Component + { + public override string Name => "CargoTelepad"; + + private const float TeleportDuration = 0.5f; + private const float TeleportDelay = 15f; + private List _teleportQueue = new List(); + private CargoTelepadState _currentState = CargoTelepadState.Unpowered; + + + public override void OnAdd() + { + base.OnAdd(); + + var receiver = Owner.EnsureComponent(); + receiver.OnPowerStateChanged += PowerUpdate; + } + + public override void OnRemove() + { + if (Owner.TryGetComponent(out PowerReceiverComponent? receiver)) + { + receiver.OnPowerStateChanged -= PowerUpdate; + } + base.OnRemove(); + } + + public void QueueTeleport(CargoProductPrototype product) + { + _teleportQueue.Add(product); + TeleportLoop(); + } + + private void PowerUpdate(object? sender, PowerStateEventArgs args) + { + if (args.Powered && _currentState == CargoTelepadState.Unpowered) { + _currentState = CargoTelepadState.Idle; + if(Owner.TryGetComponent(out var spriteComponent)) + spriteComponent.LayerSetState(0, "pad-idle"); + TeleportLoop(); + } + else if (!args.Powered) + { + _currentState = CargoTelepadState.Unpowered; + if (Owner.TryGetComponent(out var spriteComponent)) + spriteComponent.LayerSetState(0, "pad-offline"); + } + } + private void TeleportLoop() + { + if (_currentState == CargoTelepadState.Idle && _teleportQueue.Count > 0) + { + _currentState = CargoTelepadState.Charging; + if (Owner.TryGetComponent(out var spriteComponent)) + spriteComponent.LayerSetState(0, "pad-idle"); + Owner.SpawnTimer((int) (TeleportDelay * 1000), () => + { + if (!Deleted && !Owner.Deleted && _currentState == CargoTelepadState.Charging && _teleportQueue.Count > 0) + { + _currentState = CargoTelepadState.Teleporting; + if (Owner.TryGetComponent(out var spriteComponent)) + spriteComponent.LayerSetState(0, "pad-beam"); + Owner.SpawnTimer((int) (TeleportDuration * 1000), () => + { + if (!Deleted && !Owner.Deleted && _currentState == CargoTelepadState.Teleporting && _teleportQueue.Count > 0) + { + EntitySystem.Get().PlayFromEntity("/Audio/machines/phasein.ogg", Owner, AudioParams.Default.WithVolume(-8f)); + Owner.EntityManager.SpawnEntity(_teleportQueue[0].Product, Owner.Transform.Coordinates); + _teleportQueue.RemoveAt(0); + if (Owner.TryGetComponent(out var spriteComponent)) + spriteComponent.LayerSetState(0, "pad-idle"); + _currentState = CargoTelepadState.Idle; + TeleportLoop(); + } + }); + } + }); + } + } + + private enum CargoTelepadState { Unpowered, Idle, Charging, Teleporting }; + } +} diff --git a/Resources/Audio/Machines/phasein.ogg b/Resources/Audio/Machines/phasein.ogg new file mode 100644 index 0000000000000000000000000000000000000000..9bb4d443f0d9bc68e1aef7a83b52dfc06afd961b GIT binary patch literal 20244 zcmeFZd00~E`!Ie$z}-NBNUadf5V4UGQ(FcU%(X;;5UWA7VzbPprX4X2ahWnRGcCd; zL}(zvwyDtqD_hMat7)0`#inhhrq%ag^Z9%~zwht8-uHK1@AdodJ=fv*oM%1Hy*>AR zKlkH;<;&9mDDcn4hkQ#6dfaw`OoFUlnI{zI+q0ky{XbP!eXD!~vcTT*-hx(dDAPjGV97k@{8Z+gw1TCXvH}sFo>d@TxxyLDXVBTqIbb(o0pLr_ zg5+f8e0JKLd3l*@@v$p^oSKi%UYaFanJE>oSdPzMS-2t_0{`|+LD4Z>2;c;^q9oyM z@+;do0DuGlK|qklj%D#dEj9azYwK#_>?vDlSzS$;4VP6x>G{_KAC`>)02m-AI#)G4 zikDo9T#lPsm8Xsr&yP5OcT};)Sc1URzywZS}_Vx{{0|8`F=JWDJ)qeqWM_EB)vGd*hw= z_IqsVcnF~OkF32Pq#<}~?nP=Gwv_6jK(-wuc;{+DP<2y$>oUnf@t#gmduPu1L*(;^ z+{UVa)MCdr0I0?Ft^cokS$gf#|NTu9oh1P@5SC|F`JP!7z)TG|lSg(OgYa1Z#3?P6 zY|9IqmmhW}e>Ql}D`1?fNxJxF(zt&i!H#wSpiz8nt9;La&`1sG&!aBPpK~og`5Fic zJ4F81SJ4=~fD`d+TvjWQJI&aZIR+Lv*e!0qQ;gfUk-!Sd{SWZF+LM@0ohEt!~d424$Bf+y`+P)VtfJ-hHJ$|5ChLeapAhTF*U>hPJC<-h{^u9z7E> z!FuAW^^R@Vd0^Z0EA@}GN6}!atY*(t%Te~X{{A70wj~Xhx+8xFTa?|{BR%T87)*W0 zZusM(vpw&>lMfBVTjnsXr%{35ScMRx{aXEYOe*-vV~3h@HmG@0WmRlKTX9P2gsCkB zim{pF0bmPqjEevD7$fCxRNP#xBJ~nGE=)g9wmDXq)v4LSgF#eX91RlsG`#J>NyFTeI> zc}@ZEzUd)pGv;vEoQ11%(svc!JY2GPxbV)kjd!k9{xH7uzZ2HKIR^llX3H2))(9&o zXBvv~H*@V_``75dC}-*ejo5)TC=UnO6B6Sm-OSf3Y@6_%WaS=@&y?8h!m3t!w% zUE0rCI=Fi2_0FXkhc~8o{=+ce*yhf)!vEkLJBtt^tM12D!~TnN)WoWL5mo;2)dA_% zfop4*m({oJ-utvol!022Vuj zmbxqPCFp^Be96Roc6p^CJB}XG*^}z`Q0oYaJttuQ1i<4A#5dW&H_-v)Jo^>j4+bfIn>Xe!pO-JOTo2y-%yg$G-}bXQjWI z{iAo1*IgcV_PBb-{(o@?xWK*%`*G6jajnkV!p7}&yj(2)x55eF*MbFm!OC&=g2&ze zqHFL&UL|?8I`?gnKxg-F5uXan)cwytP7VNah$A2eyn1Q>{-&llPXLIh&Q1sQi@55g z5J0{(eXk<`R4-jS>3`nM|M%SgHXuY!1c0p?9yZtaJhUn+omNeD6{G{n4nKO+&=7lN zsQv4F!lqyyiDB7O03;l^n~OewHH`HjqP9h>IlGFS*w5I$6jXxB2w`9nwfFJbR_Dua z!Fdx^8Zi`HUO=$J?O+cVC6GN*L}wEKd;rk(dqnNSwHl%d)Sq;{tH|fyGFa&3G|u8( z_j$FC%QVFLR^72_;6RthmMBoU6V?AaJ1iLuN?}kMFCJh2sLbAjPIu51tl1xy4A#5` z*NEy{+jQVcLK~|%Sh#q+(w?USR~M+g5@+$XolE6nu-&nPWC!-Q_X%p9?%A<}!RG-` zfx5nPX*%Mr{p}DL0Pc1{0DPBI)H&@TC!gdauK=|7Ap)QTX`v!BfzslZ1-2GnF3K(wsUyA*7`?74EmQI-w2UoSGU02jmkYz#q@4q*M$GYhxu(3rZwg$`<8FSk&ffgjZz#lUn8SpH|C%*)RWpriS@agM|y=E|oaY(zjI3&<8YPsu1J74|xJkpv_i6 zS5lq?)Kn)VV4^D`iBopg@>PatCB>SEr@naIHB#|1uZo-sbg)O##Cg`6t!!ro*?bk zq=M~Az%jn*&LBWsz%j-O5BEXNhN)I1;wv}UHbWxLag&=9GnfEhn}89 z8{=8fLPI*5%tQS4ioD+VctcFA_ak-laJ-|Rg_pP#Pw$OSXjC`_A=*kRNG)|cYNOBB zrMd}&DFqdjd65s<(Pwa=$W{P=18TaL6Pi|35B9ppB6=?38JmEpMKN95BS z7G1F|c8qq4Mk;u|G>CIV#P6k3Z@=2&)1XdcKcj(N0Kg>RE-2cr0|bI*_x&fY{sx>; z6a0cGk#y8p@hsqP0EkPKE0v;05mB?}(xMr$aS2KDQ@{^^jIEM10OI8I%^0=6J2`!G zuF&R=wIBOfyI$LU-_vt^=&k1;M%~{0`DPUO^l=pW_3fuo&ry$2^2E0jAGA=~rtPZw z;PK{a9ebDKKn8~qJ--wM&{Bdm%lsa%o_uQaoq3+4s+Ws*Pl;OordS;=6qUNuo7tidDOb`;XY@lMrW&?YC=5zUYKV4GZnuAyAjJ*W z?TwL+*tq)EVO(e6yVf$Busd{c632?Pa5(L02e?!oXK?4NuZ2*hCZ<>-ns}l24?e@i`(A>;AZ~3<`eT~Cls$zYFG@^ zhd*B5c{Ymin|QZ7cj)W;yC~js2ms-Wz~ zLx@>cEQK*3St*6X9em&b*+fv4B!}aMMYl*pYy;OKKy_(j2X!QkvXV&n!Wp&5M{lFW zt8>!wKCj%fs<=NfstRpQ&f;^VDM%SvInKGS$skT@aSwm-$T}Y~E{(S4T z!%sY%(W+%v2zW&-($;FZV>`7Y^77lgH}_xJIiUQ4dUG#sP$Z5R@Y{OjLG{Ak*)Qkr zt0b8I%=kg-PgJUufT&WVi$V{AV-tkK*-F4^$dECtgmX=1Hq9E!mT>_fg$f1KD)B@& zG$#cBERrT%sUOcV(ThgM-vW6<&M`;;Mv@o3+t`f&U1)nrC4cY!WsXRsO=WLb?*{##9n`ot& z+{3+58Pv%7slEy(S%p{is5GKI@gFMKeFBb~2zf<`rjcX5TmGY|{@DvYC;jY3S!?g| zycHQPx**$V6 zBj+4yDap*lNrHxw+Dp|Oy@)ZWl*lNZDk@RSb??)>Lxl&eX`T3&>d{%bTxSvbtg@`A zON~E#3*!-d%01d6)JYy&v3=sIy{Q+ZWMY?ELsX;i!{mfFIgh8zuBvZ&edp)x0Bf)P;~c&i-~7(X2x$F*bC@ zX-U@b%`)*+?ks(HI8Gv^qGCeedj^h`WC~SIPs}dDtjWK=-E7%he3D0clOO(K=7Kzs zNY5=etK6~Lw7NAKx$Mb8`NCk8Md#k5mWM@|f1ENn6J0BFc8<82J#S82^)d$+c`T$$ zt`f1BTLl1M)WL!3da~^@X9iwH;2S~!`4c3KfiXxD+X1{vF202T80}s(uq&MsPGd14 z1NCAK=u`%}jVp)%50waX=|aK)U`ZnUkmKk}bxGHc7B+tUt5FZWQ^lJ2ZM)1l=bj4N zQdf~29VuJqxR*Kv`o-GUHo!REQqQG=6wV(RfzQgYnN9q`p&lV0G$+_b6a!{8(i!kB z9nT`P)t2%F!(<7BYh&x%+9X76OJSmwHV}%j450V^^avqL9=#B`u~^A0mXlnLp8S+I zEJ}eeU@1RsCx7y}2yYzi+$?wR#4!DJg8_z#&kNx$_hM5?b6@#A%JjUy&q-W=-Fzu- zSQVF$HybTiQQJ%X2ojPYGa1k;l1uliy#UaK;x{Z12O(VKb+v+N4o8#511F{MJh#s? zL%%pCn*S?VK#RMyd(L(Loy9TWjJL9dGwysB;AI_~G2mu$FfFubm13!hGGH7QESFk_ z%MAqX0D+67B=rk%o#v{ROz-eIu0a?CmREsz?%$h6rzHCXHGpOE+f((2aY<;=`yW$|ncV1Efl9~cz8`LFp`uD0fRZu?bsCC5hXF85eTFxd%YjgH+DIfo2MD|X zwJscxOGX_5MpVo>wKuZ~lz4NGPocSeyhD49D7hX25ndTZsAdv>$!0B}tG0EoU1m&; zjEIP6&dWu5#XS_=oJN~$$GMtkQYxtkz0EjW_pUWaAkFdz)gM5RWeFT|cl9ywYz(q3 zwSdnG@n#-SYUu3>52lpKG79xtXHn{LjFgGE-uK6|+PBpW%zfShgTwiQ$m@Qat9c~; z!L50$`!TQzk7D<2>zk)s-F#%P=U?$#vbPUAldGCV;uDP4tT$)=Uix>(5jX*1!~zi7 zl_vu(-uvf>f1Up{T(EdwH{ai-$0c0gG?WbQA}K7L5}x8G61@by4Wu#3~>H!*Ve}qT_ivKtcdK zLH;K30ig^(?2Uw>R(-mzB&i|YJ&3IZyT5#WnO6Plt{W*cFSbwf3_N>(TkUTr?%&xs z;{9FfiJ#`C+&j6G6?f5B#ZAZcoh;va@Z*DLuJO$QTbo-HpN}tah0pdT=(wQsGh7G+ zb7ft84(f`e0^B!}aNL83^nL*CQ&x~+GiFjlNj&VsouUV^;j~2sT8n_yT9qLw9 zhI^N`VA3!)Ub`@Z?Z4*wF?03X@7ZLeL1n^K;0ZcZ1rKA+7dwqtWcx35o3#D(dk(To zCkLh0#?pbgMlMyYL_y*s9Ju#Rzue)TC;iY9u!5vGusZgM7w>Hi`3IfjgSg8tzY6st z2;85$4YFneOCMtqGU1Reh0q^VlDqhg!vMh>9j4~Ve85i*HKfx43JmhR^@faJSL%+% z0&+D}Dekz)O=iG>NgG-)@Yi=7d_!rkc5>0y&Es;rfL*4M6>X`Jd2u^c!z>cT(XojA zi2|^_>>vPm3{%Gpne`HKmdPOn(=Gr8PSqFsn7R?B6*hBdXtK1GSb;|F+!uo4a-#{yS$0)|Is=F=pUwq)}0f|P60 z*}8+**2YO0HpVR4E%A6OPA|zpbrWT%3L4a%iiVCjK=Ym79S5t#ZjbY&73pLV+k{tG zQvckYa4U0pJ)w9t#;VhbAnpLRZ-0GIe&Pi&^LW|w-u*wHjn>_A-80?dyL#AEw(3c+3EyI(~wM-7!0^#eKcV}$g5chaid z2lz*KX(ONpdsp-WE=gh6U(~BxD=RtHQ1bANOxvX}3c1yfJA&$$m^ze|!@{YO@_Ilu z>{Hq%C+TvStU{a&ZZP2JEE_hfd_EG1hM;ajiLquUpLdfs2a}u1T+!1SY>ngS9KdK% zxZI7nvD^QTiEGc)tctn!vV+;qKO`DAe0DPRue)>FcCMpd>U%ow9OHOG>XCJ?P1a{C zEP1@oQ4^4hCy)REeNgFqc%kF9jo}#4&yzEa++vklOX4RwSj|9+>mEafHiWFVFSx0I zd@^wIyv<*fKXL9hmm_PA{s_xCc-k=)@;=d$iloOfj_@H7cAN|5c~pVuR|en7KVVefs$f{JRXOfgOrjKy3EB%C^DJ-PI9bG7ytQW+0XSM z_l{HuC~}QWQV9Eq-NlJMy(8xD<0}pMui)Pqb20rvsO8s3OR2}_2CO+8atMM340z29 z=5s!?;Fp3w`2o>``3RbufD!CEOSJ`lGmTNfw%{mgq0}NIeih7n+EeT^*zvWHC*+wV zO)h}isZ%Xt$-1I=mV>1&`&%=0)aOt+PFOFwLDXU+B?m~{lY>ZecL0&v zCvpRp=rLYylnp72S6HbH7UMP<~YlAt?KlbYd^RC@?)B1DTiah+Q2nB2S@&MYdp1ilP1b_?}etLkgo?- zSHk!J(gET7H42>p2@^7m_b+!;nhNGv5^p|$vr*%;YfzjgKfYdXzOCh=XjcfaEJL3P z)MAGf9DkCkP$@8KPU~WkjRZN5=`Tt_7I<^)YJ4!Xw1mG9ZdsA(3Q63<0@XHi3mnio z0=J)I8eQEc15f@^U4oa61Aa+eyuH^Ab?WHMu7U^nE~|&o!^6Yc&(dwoG}$3S(-UGV z;Oz+MPlFO3L*L4yfqoAr+pXK!cPcDIU!L5_2+?~FaVlfmV>oQ|;1DT_%`DgT6?Jow zCT;}|>8`u`^tUKFjWOuNV`l$8L?_(fxNIN!Pz#mI5w5k8o*fJC{;|){u&uS6Dj#3> z0LuT^&W+d!be@cj5>~vANBY=N*Hw+g^o@FT_KQBm>OIfmpr#^cl$UQ36Y$L zsHTrP5V~f9e$ldxp0hxW=>ZXAs`H<35v*9=W$#=K0Oge@#1w58HUD*!;PGn;OS%d?#d=d!~Wl-kCMY297sYWi$T9X^`d3`m;N3Xp;?vF)mg3; z_=Hd>XdqZc9$r4|s@AHoeF8{<1{4$A=R-CZ6`xm+lgAzy^5&T3kclpK@i9ri(;fb0 zB|tNB!_j~K3IRUt?d>ia?(W|1PoX$&-F+x$dDoaO-IW5c2e>(*hMN^U%enewoUj99 zMD8KWI=fVSj^4ZUhPGD0aWz@HmOT&W+0aOiYf@6XhK}jex#+aQ8ySdm26_P&wUE0n z>_dT^lQ=_k^5M@d8J>#!C4cQst%}@Ly@pW#sF?lJlW7@o>-cPwDz;k}lI{J2M@AMs zQ~>ibP;a9SpTD+Yif+U8#|oO`>t5fQsN>Af)Ax1#*nxt}q|8t#D1+b?+9-XWi#&(Y zHTpeJi{L4#aM}S?4nwa~3p+{*T_GuuP^AbBW1-;%c684j8FY2~3~~P3ef?ihhs`wT zrj@->ETl52ygS@BrM8!Tp%0yp4_uvFw-#KI0l?qxG1fT|VqfSbd}|74mYy4vb4ZfO zv!t{m2t2A@A!6#aDg-KpMsMOn;DC=?Cn6>=^~+1nAe(B~(^^)4s`;UHV@~+eVx`iF z&u~*dN5#B5Y0aG`otnnTIHo#YyOEr-XTcAvKu0W>d&gPqtQ z`{~blw=y=(y6PMJwgI?UkZOMJ&}Z7Vy+bvv(DPnL6#M3>xSflYkUp_l$3#~mDl~Gc zH~YC+IFVloN*ScgsK9ged=fYvt#>6TT-LX^N~cd!N5>D|4qnXL@fyG+=x(obz?aS$ zEXYOL4d}Rspp3cs2ipz;m96K}P#8H}m6>Hi%`&CgdUTpj;SC<2B^^rc*D0MywY3tl z*ndc$?q!kaN>m&U%1x=^&v@j$d@4am(W}ulnjfWdv zkDPmVoA@M!hGh0><6P7J%Go5)Y;QPZWx@HylNV2p+;syszhlt3xMASIb(M|+2r%?` zFE7u4LKVA$;rI08vzLKi4sWkro>1wmo|;-lsHsncqg_p<7zbBZ6obt!kKNicR8*q7 zp>+XGi@+hYRTYwB6ar8HKO})H*)ZtkTG8xL9`W`4DfVP7?$Q z7d*Usmv%vD6}I{M4)@iT&$7eA!ZBGaGX{FN?j~>CunN;&X*hAhMSvTUS&e8fi#e2H zy&9%3$4Tl0DxSHMj?vd|7}^mbsSlj-c`%Ame)e;NLlstf?a1_d=NJbtCn`U@TpM`r zZLj|I<>-wsW(R*)yHWOb^XI6a@vQX$kAHAVJEq<$Fys{Hh>%ZxwmP*9e@Ohvy4}Mc z;8sx|zW=)R*}`>{?-JA0Bn78YXd~!IBoZE>qQWuEK?##A2}R@tx(pKWryqH}5$!A`Piytq~d@1y$GZNBwo{3%- z76zf+v_kncF}JmtETa=aWK*dj%q9n$$f{9h+Kdw0u{!%iw4mBB4)|JLg4v3j8>ew@ z`GKsDu)d;uCKDIO%KHz*{Bbt3HDOh59FrXW7{VJ@L89VVt_#Vu{EnBZEjjDcA{Rae% zL~+;|t{NyYFwjXjXCG?B6P^LN0@Xs(t8-6OZHPS36bsCIsZf{T8zV^*_c*ZOVB0WNpN+^tCtMLHn^;Iz9;y^DDKbBTFXfoT7Wgsf?q z^dxe{Zu}@@3R`($B`Uow7J=ruekzEYGOdUW>L3mGx~d*QaAOWuIVTH^4(7EZ zgjwB}x`r-+#wirg@dkR(m|$*_kNasOvfC`Qxd?P6I#MaW!z_dtv^^>)7m4Tj+pUc+qT>A9@T$xDCm*!;1NRq7a>e8@^b4uqZy1l4~feg4%Ci&`YC%!EKeOoBwm49B7IIdey+RDC1Se=W<<|DIK=Z4wrVXktqzhwFH8`t@Ru#8#3 zwZcK8(dg`zn8B|Lzj-Pabvnh>6?F5v1`C6<;)zD|02+g?kmJls+a3N8dVsdT`>$V6 zMt3c?(W%bj_u+0Vvehuebn|j;M`)cc)$BdB{cJj7?T4$;PsM(l&#!$!Y$14N-+Vu3 z@rJ|vC~eTD>0(2$m)Lsl>dqzQ69Q-NX!`xkr~SsT#xwo5Ue^Eo`{5?bwtC@VkAR5F zK9I0ZoklI;FiZ+28dTB1sIDlC9s{(KK<{_w^;8B7)EH)=9=xLEl!t8U<{$N4LBW{dUb(4OL;XC_?mrgkrsY+f0?o zMhx#-#mg-ng5_DuIqi*u2+)V^*D59Q;UCc09qBV=aT=Jq ziVTV-nK_C{KR}43Ag)09Zr**$SPqBLj>u`Z|oB%yiNUSWXbUz&A}sXp!MDiI_naq#Ex`TrKVmSb9cFw z-`HQ8X<=pf`1q{v4@;SKnwt|Mal|PywV9bb(>a6#HJL06hq+Q2DM@0(hrF#kOq0Y- z$X*})r_V_BSQgLDhci>qO#diLEOVXU^KW4srPR!JPiTneu9;a ztB{X7dwawyU~VXME`I$k=k0GQc=mmm^0LUh2l&88w2`}K`w$>`(2SI1O!y14UDl&t^at*Fkgygib# z3dI38J2gaa1K!&xNp^F!g`y}hOYG;LB8G&!G3FQZqTU8oEt&uOK7QP1ok``vY$6Ju zZ#&SNmLwm>cJs>b7R>ML{Tkch-yD}T+V;oy@)~yRXi!f6LB-}$+WF1n&Stz|(BzO8 zFE6Dn>45a%c}Pm@JM>e+6+xd8YvfMVip46PMa4gzB5mc`aXR-CV|)48SW$vJd+6d^ z)&s&JRJ|vDcj4iskf59yJN@TXrM7^}2@=$;&h{06yat-V<+#$y#!M3jc^aM3A8QQ* zJ(zBmw8Z{pmOk?`zCbC?RC(x0cm=mx8%6EZ5(p}deIJ2C0~i)308y#Md$hltpAdxH zreda$6}mJVmRt0>TrFW7ki$(Ix$X;KfWbW+*RA8VQ=tf9)#|6TVD6P5sFp+xz~lk~ zLk|{Zdbx9P;|R=A7d~&|?qfCM{GT7%S8=+Gs3iynHB?-ti+Xp;X*HB@f+FU4{d`;k zlZLx==5Ror|HJwRwd`U6Ob=(06(Twu*7zh8Yaj^2yo>oW41B74yF|=GJqJnYq|20v z6K2fT7HxaMAwE4@_dDHvi|p4eL`nRVt4HB=V8DG{1c!7F?dW)qU1hb{B}fXThtQ*i z>jmWo+mOUk*C|wq%R}5jzOdG3Hc?H&4#P8ccN8Y1lV|SXLnu0(gd@#y8^(tdyiEeV z*5%Wk^9Mo&_X*e72pq;is}NO)j09nK?AZ-(GUs_X@1FTQ{soHgCIe{{VSKE=HP>H7 z@k9CTLI>p53~BqP&P(KpBR>!Ug2sgpIrb@hf^#H$;2`~}?^EUO3gczQ>RmIT70m$5 zosVXrU+)T>@Km(t)6FuxBE&^xOMo5y`dvECg_lO|QURsBIt`aB%M>S?!a~^YcGS=9 zHM>tf1e@{&LA^!n58rUsv*u5qfr72Wuxm(%1G6HK9sWYBKXwn)!{go!J2-~xJ6D(5 z!eprOOwPa(*@!#GGM>sn`sA3Apc-yDXGWejvQ4C+5PCAp3q>(#i(0&gl4Fv8Tv!V| zUK5F&d{oOg|6!X`_tcY*v=hE>uG}2Vi90-Zdk62Ab?Nb$P@0|zm?D}UMR^`{{Bo;* zguoN5cXWw9ylTnImE)XD=9kKmOAkH{@yn^PNI>rmGx3VyobLYj4JZJG%I+aD5%pqzEilCH`6|yue|{~ydOX)8|oJ& zzWR0gxn{&#n%lm>Yo4Fq*URC{_Eh->E&w%8p%C1$e@e9byXD}9k}BnpUVvOMt7@}U7s7P+vRwb zfWa6PHa^SyAt&pogHN!4*{31$Q{XZP>c@|d7nh+$7^@IzCuasjW>QMTM{ms~oJftV zPrLc%2j!I4-bY_7^>^G+-{k)Gz-r#9PmNI>*f+R~BTEiWz4_rix5^zK@q6dPg^T_7 zsd$XyZdKnfjvb1-aH%O5go8m z_pg8c{p=0s=WqsJr-FZ>qrfO3${fY!u-HjHb`VbTfmgi@E&9_{_4iMe&@*f5XdmIs z&%Z8RmOgW7baU9v8$*xI_BDW(OKK!?7P5mz+G^KM067&wap9Q+CQgiAav%`9zP+S{ zlh{6lIvr}*!_$#mRKzHNLoZgP$7Y7P;ITIq`IyZdWF@#=CZQMeAPh_~mq8Xh6-C3h^7QnNzMb-L-HM-kwwF;`|DaVbiu~{lq0nknxJpUh>aY*0 z>3>!oy5I$A;zsEF%bU99^;hq@cxS^<=!d^Tz8jZV*dur;`s>$=8`dYtP<<*K92V*% z==RQkie@gjz0`UC_GyV+L6EXUF3ud(-N?RJKWvX9+_dhYA8P0K&{GF!HN3ee-fUC$ zPKNxRhEE`Gb^wwH!xMd55^O@D(CR_%@$jfxZHGik0FaR}>$H$*)vV^amLj)0%sv0R zORC3DkcBCF7jBLj+(QT(2nA!-F{nhDQL>n0UAOzE1v?uy?K*hA`eSUbm$g&lqTsUO z<{p9og@pf5xo$IF3$8Xqg6QvKhV}0@WL{fjNtpZF_itrc`_?RpTu`;_Ejz-pM`?&^ z@0rFV@OF79@q?o~j8k9CXkPjK>`ym_4*xpmjPLLq@kq=yF1U1iqVNa&zm)NIZqP*# zuBo<9O%xaae3U7K8!{McB9SEi5?idEZ)cFN>!!F@lsk@$fAIeK&alvFlZ-!XyYmAC zIB0R5v2(Z}w}!;L;D<5sNRFm4LI5|ILrVR^xu<)uw3_qES6jMsC(Qjl4U%%2RLh&G zzb;Gk={B#Jp~C3-s$n_D)wNxrRgrKQJ;fX21EFvMGN6DnGFBe!>5B9|a6Q*G4~3+m z%tI0x+Cbr9WM@XR@qrJV8kW5t*Qq(pr7G!kz^4LHe5$W023e`Lz!`MR_Ltq!pCg|I ze7!q+#m0zSWbEH5Y?hlY7UOzqL-fhK7YnWmd^6Rjc5T`T6jQhrqMt>c>8GxLzvkSU zC!CHuY%O(ZL#L2AaOx`5)q1QXsCFnP(;jF7+?MWK49oAv?c4Uldc&b|!8F``uQ$(= z5uqJ^jdr`v(|>;aL)r+akK7FfLvsK?Vxh`LlGd;H%1CqLSn69t-mTVjN|sL*4vU5b zb>ZoJCtbqk_}^NFvO_pEEOaBHU8`^zn6Zlatp1dPk*-f;P6bpJE|WoZQfjCo_H!e% z_{Sd}NQKlL&aXlaZ}=kKb?y}os&L1KoSnYr?Q+0XLqvoenxD7&#EShl^t(GaE8hP# zh{Pnn*>dI7@YK|VFNJ$I)ovp#bRH+#5?~zBv>*Hq*{U$41yX(y-F#u7BG8%DHDr=hWQYPh&`6K#0}1 zuC6Q%1$smAx9xMs2~7)qW`WxY?cS=v`7d%zbrPkjk`rR!cSw@S`uft6i{X1TSVF6S zKf_iVUIg*Z^3n5v$*Iz&W6_+sVO%EK!AV}8dtB4UG-A~lm_OgFk%Zm*@NS&vCrRBO zZ;#(^d8KS}jK8=h(3{mBIsOaV9GH=_BImE$zlK=GUu>_qarHYPvz#O+0YArHIpSem z_#L6A7`r!|6Ap0@(Aw2?57+)szaW{RBKsCqPbkYBdCm?s2stL<4KU`WugyM*Nzc(u z6;$}WA14S7lozU4J@wF4zqlFuUu4W50Zo&lh@B25e@84bx5n<*lV|R@IAlF_D$sN; zHYSOanCRLbp3X5DTUzQ%gCwew8!{yr5mj2E6_TS0pjd`g7i$t&RiYd?MPFXlMo=3D z4z@^LMfs)~mk$5@$MT5^7ovt!QADsT-8%HU2}pYwXDym>^=kE{un&_zPJi)vA}^&- z(C*ZuY@3cbS$F|9*YoPx@0`B>erVn!a#9@AUxf=*U~o4VWGVCG8cmhY&~+iw8S>#VjAAM66A2^=oZutL-!|>kwZI z%`sn(9!NFZ+=7+D>E#+czHw3H$BB7YuP)vfS$hWt131=G^}LIXs|#6v&B{$u$xGl; zK>VudmpA?~Y0DH;`sf_O-%7T4NU8QV3Leb)xOwo|%Vp2U!JcnRxj0$>b^(lBkbE`D zgsVmW?iar;CfidZe!D%U8NR4(2lw&zx7!0A|EYMmWZkX#>gs(4&l09XEE1V@;&}Ax zJ}~-u@3Sq*Fc)L=*Tlk8flxTlZ}dbetJ1T?N!S`8>+hx~C0!^2=j!V_ZES}Wu;9>A zy_T1T0UX@Qoh4$|;L=JiMK93uO)N{{vny@N9vv98QYe=&*zmz2UO6$G3(r8lNO0dL z+_I)j+#Bn~W}{M4GSKA~uDw1U%R~ZU8Vr+hfX8B)y?y$IQa5e4ZvFcUHIVS|)QbGi z>0xx`e*WYecXoKFe|@R!K;KK4IsP+J(?(oY{lmv=vnIXIDG8{%zvye4ujlBzSOw#k zw6ABE=Z<_u_Sxdhz}v*H6^rJXN2c7}J%j|2b^At5WluJw89w#6Seh2@y#u}t+c47l zzI0JM`PA;~G~H8?|LVJF$JMzE^4&O@-9IN#8QdifSf7kp>)Q$(sUCuPO!&2ZK1+PoJ7v|hH|tk=8?j3iWJz>u z*CSCYp?ad#y0f?FdS+B%rqSN2E2ZDqp~YCJ?z7rM!i9C=rJ1PiP$oSkOOIj=;3%>e z?o_uF0G&u>TaUq&S|W*?)XsCDvS`wFxswRp3o|#NX(@ez3L=l4LQ%8&cqT+eC9eY9 zcHuN>b&4QeOTw*JY@}4n;{;=sM8f!!=RR_4GoL3k+-E1>Y3!Tc_GQJprNc+|#|M0` zhn5mcaXiZkXLTA3LZg(P>EUnst}}P*gH`Y2D%g`nquZcKsc#JM>n8*#6x;+Fy>J#) zXj6&IIub$_0$Oaqre5oIWv}yt(zJ75(gLd(?D_ba4GDkTF+s1?Hasn6SNS%~O?x!K zwasd+8}?g(T4M(T_q1@h-Jr_k%xZ5Wc1r5QhgFTBDS}CJx0v`Wlea{!X$|TmXqEfn z9E?q)77nVoOb(iE)-aV-*txpnN9jBZ7y!}4>^j9D_P4*vT#Fb&QcxHMXVcyiRi!{? z;8e)*+zJ;&qsXLyLy*tHe+0S+azW*=hLuySfM=L^5E{MDiOXgbb1jwLxyjNmWV`xvK(QQRQ}PCdHqX$cv;pXID3;wQ1pSoq zX%g{8t5M<&dR=tZvT>gQ=R=+BGOx*hLp-xzBr=oZ=-FFloS4+?nHzQ(e$;=St1l{k z_S;JP)}a8#tnfya3zNa90pW7xjr4)r5;(^}8qQaS43dOx&(KmU*Ifzj3~NLfS1c;; z(*x}}gWHP@idc?KfO0(>ykkQq0GiQ#nISs0!bxD(35!X5Sp^u(n`T;Z%gjD)bO{G| zQl>2PVzf1t1wk_!lq4)*=9^V;wWPjQNu_MlPXDc_5(<5So>)gZx6`2uh`pkmZ-Vq+ zRf<xhS|jAh{SA^ln#3DptLo>xPLz_lFMFJ1^^bM2|1|!vh7+>T5F*`Ct$UiQxSl z3?<$V2TVFsHwhu+Ihu?NTDLd2%K;2`LO3@!wL>@cZo#y+ICMG(-3s#J*426p2R0Wt zu6CQXN>zM%(YEPjX;!PX^+=vQhDvU`MB@6CiG^( zV?vT*^t{6eg}6Sj7R#lu-K7)L&G75DcBq`x6jh&MXUT@IK%`|x3wjlG=^I39b>Qo* zZV(@qS?HifQE(>tpi$x;ObQfwx3;ZJM=EW?J{;t=p{Evr^8CHYx>%V}4)0#}c#dwC zrOX2e78Z9ObPbvtRJixrk~t3R7)M`j^mO-s{&})V30f~)Dp7=CnYeV|?+(8xR${PF zTvVyWfU$&)b_l44a>__t8+HP4Qa9j*x;ievZPmh^>j=>wi?;av0htqVfZC1rT1Wz2 z*loO|in@r)&gFJ8Q49G@8K=uiXl<-Ci1{*otHHUhw577sXgr9;V#Cu-EVtlRof1`{ zQ%l@6Ca4_FVj@w&-VR!twPn*epRWf;f+noKg&}B$DC`h0s#WF|WgXHHqhw;E<`Y2A zLIJJ_MuCJ%ie)o7p{D!&w(oizN{|rmcA}F);rFSf_2iGycMc!<)ZK7z`t-;AU5M2g zDVH$6)ZVbXb2>Pf^ zMxj7l9Ad36>_?u~@rJKnMf9tv&%?dJZIfX&7`fejjKfJwG8t3I*3gh7j+-=f3Z*J~ z^?0ENc*x&`V9UTG2W*th`{;U53sduu(i8@bf=cvZ18BGd0@bLvG=HzOV^=)HmCs_( z7{t*YPUn3v1jU5k7w(f2?eG@UzGWh(WTAm_?ql6g@6A4WPyH7%f68BEEy{9j*EIeX zojn_)H_3(NT`flwfDiB#Vr{r~iV6xkv+Sr>7D`=k;TgDwi-F)9u%y1GDK62U*fwEl zR>F=vv{($ALT!>=m_>|F51H@cTrhdWL{WV!8&`)AkD`2$4UqB1jS&F z@W!yJh&hr>rMUTkVG4r9NvDkrwxKQ4n;;OtV6tEW|7Mg7fMl_aN)Kj*ayVX@@T7NK z_Iv7)^T%Qa_wyZutjbf1A55Em^ZoR36ISkbXG6M=Ijac-qC&|lk4-MWj8A#{sY|?g zw6h zP9$$Mq)`{DzuvyMclqjtGfCh%JzO837h|vab*;5rc>`+OGWu3I9%X^6oJYYJ3TI=aJ%WNp zex$T1C#EK!BJh#OF);hl;6@9@Hi_bvHZlTo5`_U#Ml22bU6pIyaeSEY|z zHyAbjDD3vnHZZ>0gizkuhOV@@fN}bUCqM;0}pFZd)*FIRF))3DpaCR<8llxyTRA~fmtb6C;IQ8ecO*Qi#R=)WX=eDL-B>C34z z{J`^T>#(i>?l~Li0wWL$1pE#J7ZWVhLGd_g4!8m=aT|!GrnpM6T)2F1oWpH#v#ZO; zBH^h&!mh&MUucxf&2ZodVr-k|h;L-xF*(kwJckiA=1Tz3w4{Cns8pEhTKD(v4D@rV z!oiqFp#o<&OVvfLKEtAbV|lo`S|y)ijVf&^(J48oavjr#y}RSdit)VraOTOW4?L|Q zS!H|cLx;U7sv)^mucAr#$i|Dhb2y1%;^^jIWgXYTZ@yEdL)*7*o3SOUnA3mi zYL`l@bZ-TvMl5;|{8u7(0@DUmYS8p^286>fmGDNkQ`aTPBz}eC_`d;%>3Jf`q(yff z+|Hi;`E12Doy%@no3GMl_3donRs0xLzvsxe&GA^eNf@dT@+~VmcsSu;ptKd^$~tWZ zcQ3E%l1sH>jD^kaQ$m_}DP3HS9)tF8CU4xmZ{URYqV$B5foFcbv3<_UenMQce*dAz zG1bp2M2A=899y!v@J+LheJzg-r*rfWFs8SiZ)BNJ6IDuVMpGKQa)`^4@ohR?GS88P zmYmr#n;~v%#GUHc$U10R-LpQ~tiqMsR4#agI|-^N8G3+x2q2|>P|}b}XHoZK!6Ps_ zkxgrto&axH>&57ER%uWWfRck`z+__L*GTfL35UMl_R*#Pv2i5(>{r^e;H1MlU1fsA zhiALD1E$mH#8oxDeQ3PhEeVtxDhG{evn*a-Rzf&JQ+i?$6b(rk&xZxWf+j6b$2qOT zfg!^fP7{XAweiEC8WA&?;QvxdL|!7h!Cd*p;3+3#%kfr0*T)j%Ocx`TUctQZGbLVc z!Oi+L<*`Cl%5NV;3Bm@IJ^(qP>uvhQ?8-Rrym{up+`U{$Nm^_4l z#~KuB5d&7vOJSblyDiwQ;u*Ib_1`xOj_X;9=z*)ve%Nx zfncXMlSPrgKUnl%$qg5;^gJRC2CTNWr8+CY6M;#>vA|3@&o-1|vUGH4GX<7&S5=t) zQ>U()B^Sf2^(|n0;t&{j?oP2CQ))Fgh&qlt5C7WZb5;gJ3a>=TWaYeaT-WqFjeZk+ zXw)e8PFyiwfnq+Mn)mKdf!F@1jfyQ>G$g){gZy>;b%hS0Cn){l4RCNr)_WsDch;98l6jp)NxL(~;Q9%c|_iJV1+u(Smb_a1^5uS&YB{ zXQw4ii|039C+{oRgMGvRn*Q`>$1Qwaps^CAaW<^G*BKD(Di_JrRYz8_ou)1LBU|qrpe;C z(Ml{0`J2yblX0ZV*94fr118|!gX275+HZEMrn#4^RF(CT<@G|#@byeVomN@NG)gjW zdAhp#xT7fU16IW8P*lGW-A?k9cKwe4xC2N0q0j=L7%UdLK5)EQV-dk(u*KV#xny&j zY4=_FMnP3|YPE={V%gwiL1)3Z1-gc_C%l6IPytjiRyB$nRvAHv%HOPYhk&jH%+s&S zkkW3Ev^U1Nm|8D+jBd`fI77dvLc|XS5CB0Gi->3hLi9rc07MZZIurl|t%zs=MZ{_i z0RR91zG#dG4e39CjH_?a7!MlKe*hU*-@T9~fpxkg2ZvM+VvZa*m6!uDI}kt*3>{un@vkgw0Y>ioPfNis>TLER8Y0k zC8O@A2|~vHNIh~z&p|V&s8$dVt*Xh#6A(+%aO}hNNyo;w3XpW-lp~Bm5uIX-#R4?w zAh%XYlzKV4IVL7|P*61j2o|w)xB^7}fRQ$xfd$?jez6|#Fa;8(`=EsYz^y|d^7ZoD zod5v7XN0Ry;vY7-+BzG%XN0Ry;vY7-+BzHi3Yig7oiYfAHXxM)k*ORUr8uwyu>&(P z00000z^DOht*F6Z4OT0FVu+Z6Y1NuoF~!1`*3`O%sF)VkEmXx4K}-uvYo-7OTVo?4 zm7G}px+}xfxIiXHm(8(i%~DhZRZKy!pdx|+1++y#UEFGBz_E(#OGk;RVWUw6V-#$o z)z|_C1W?&0)P&r1rSMfM)P4SIU+-}Rg)s7jc;9Av`nc(-2d{5X071)QXyhb+KZhCWvXpidHZN(W%3#AR^cz7C>x` zRxt>GAVyU%0)Mi|ysknAtP^sHvsPm<*n$yJJIId6Seq}5fU407f+16^GP9ZQ@ljc= zQok;4jaaN`MN~nw8ud<SCxBe8 z0KR4H#~dk&=ft0?ux0GW94U(D#Gk5gVSCsd#Mr?hh1h|Zn3-f^000000AjVVHw+uo z#)4^JTCr-)x(znlVBNs9ury4=(wbERv9w|-hNXpxg-#th6(d$uMO9Sc@~7g~t5wWZ zew_fDYklvpZ+){Sb7uC;?0t5d*=NqlVQ+6c01Et0 zpG8&qwyHSq!M`9oAQ2}++_sbSeO#0HCC9PtMuF&d>8_qpQqC&eFGP z&+E*`&(Pbz+MCX+n6twmEEKEl0g`|NG-YId$b!jg=jR;~%Yr0~%D`4FK1m}>BHk$b zvD2DN<`a`uqm>;t(>>66&CU$CgM+lo-$T(v~dJYLB}pJsy3pb9_$WjPQm^(&i);5fG> zJP3d~C6I9gA!_EK+5@46=3%A-VZ@;<%23Nuo_{F;R6Cdm!fIxAh69;~W5POPZ0!+Y z8hSW-T-4+WCM2jv(9^m~&2^>H#UBc#%=YJT{=g)sp zQY})z?nYr9DlYn-k%UmrC;Z~`t$Y7}4Q@Va%b69PwsOuRuSZnM- z9pJ^^n6OgQnX-3JZCNf3ZP2&yuWWhfq*@6YxN_w$j{=p7^+-2HNNoE@LT(7?6(up; z|5V&t+?b&BgMZ|)cT%7+|FY+8W2XKQ5$Je1eD-F%^Gx{D>GMygQ;&-$csl0%TmHp5 z$O*9JPTTI7<(7gUD2zR1!u3nRzdgr1SY+Um)X*iIbu-RpLT%)|_TdlO4}{G?bFmY3 zejpmo7W1^zb!O{$vZF0ms>F|Gg4(K+r`f1NC{@ruZ7WLBP zEHiM984BB;Q=M1*s=Dkyc}|HB<7zJBDxI-HPg6?D@lDFFX)6o3*Ra<9-{!wP2Xq)P zn~`y5|K>R?ywm~Ed79O1KK$a*=mEGogqex|Qvm?LO6RrST1s#vvicNRXNs&&r5I8F zyEL`sTA*OF0YCx(dTuODgp8$@Sg4q{Jj@`y!1YOC7$q_Gp?sp+bjxHJH*OgPd=9?> zvv3k)rz{al2@Q~;&@K54m}F&yIuf*7Bv2{=@DD(6!%&gnWC;crfUo2BWz-o{tg)dtS{J+k08MHC0kP(REL4-aOdf4Pe;T8*n6*8 z4O9dR0$^E4gQ2Qsq@>NQw}1$ySr(v!wvgg#g|Fmw7c${4btRfu$as*+D$14ICMxpT zWMhlU3bLk^dSwooLnb@Jsv28CCM$CQG-*BX=YWh)sDlIV!D!EYYtvrAnONbM3qyru zD$!tMQ!V1Y72{-O;K4xWkkzYP5T;n^aUXRz~LYOP-%1x zkIO7;Vu2eSbZfti!y}c!m}?MQfikgBj!*x0^M}wVAOPiG4+d2JeC}WY)`V8-wwl|p z|JA}Cz(&NwScl^HYUK(=QaQvh%|ZZ@6V#|N9sd#s#&hu~_i;;$$`-V096Hw4%BsF4 z*KkEDj_l;8-oK>3f~}ZzO2I2kgPc_6xFt8;5;IXzZh7cdH-ye6`>D60{a^Q0Wm#F{ z`_cXy{mWZ}A37!D4Q>iqr{MdY;spEq#N6vzre#wEoBJl5>RS-*DNSuHGkzm&Xt|UI z^%i^o5e^{NP!Ax;&*=47O*lUD2?AFM2<-{@5C$5F`<5+$Do0k6Q}n?b10S49v&iIa z>j9%dTNCBViWL0vcE?tH>Z|N|Uw^9uj8wBG$ZLh6;Ee6SRlaf(dLI&Gr(zJJ01nn*dAAr^{*HhY+9p zG{I~!x2qC=?1+}*mQX0!wmlC3;4RN0TdJGI$X22&a!lk!Lv6_nrBHryUA4(5b{Ut= zz{h39QZzZU$@h)9Wju+>i27`_L4R&}uAfS&J1@A#8UsLdIv1R~ghfCAQdpb?1c>KI z;1`r7q(EWM7bg$^7I{fRRPIbabfaURPHyo7F!)I(Toi zGg}Ve=I2KMo47x|*CcioFZmt+sG)}gmmLP&c)Yjj)yDL-n?O1H~URBwYn`c zVC|YVbGZZup(7y!P2c~#bG_c`D*KgoJ^K}U9e4GMm8Zg-<)L@k_lOKC1R=j~EQrZ| zRq@yNm&8-km-lHQxO^F zZT|lE{RCA2qu3@%=9N;%wL6ve2Ps6VaDdFufur-0q`==-=^H<@#zp)dn@ZK)`?+YA zc}nZ2^X_(WIb=CuOcL{L@7Lh^xJ1D(z!F!dci%?FRLrpOnK8yw`C5+8WKuNbDv}pn zuA=8flvL)Gm(9OEU+}b7TyiB`xe&dw3VW#t@&8#2H#}JRz3y1Z=-Cvj&yJl-g{L@Y z?1YY3+Ug|Km~yZmi^asKqwu156uoEesPWrxFP}Efe|H-a`XKto9LQJE-8^i{QR6jZ zmGK|d_b@=IOev<>9&SjQ6agUn=MP5Wd=@y$45@KYLKap~Gg`1tR5eDF)JwxxQF|TA zbIVBTFEtvKZX7fys?^{Ol#Ogm+%umP8Xc9>%!3u@H(oYxpP^f|wQDUvGE(u1% z1*CV;k3S;r*YXO`mL@-COz)rxrQ(IH1X3?G6G@dmweO_J*Bh#;b-Mh8A!k9&1> z$l}74Lx?+}&ii=FJPNH*@jhRUe|0iR@=X8LDmuMI_Yy9K*@-uT;PHPuEv;(N8C1Rtf5bp z`CYGeT6gPGK|};=1lx)Lwy2sLN;*h0S!HYw61*4xm^yV+hQLF%cA*5NMk!de2& z>SX{5WoBW5;*N&9;xNL11SBDK)Z2vUZ$^TNq)bc_P0I!7_S)%P7QisY(jXQmdrQ{% zc{uItr)-nd_SNE(dX5bvZN~%zRx8O*qN?Po9q1czrVe_w8JI7qu#%9GX+5pC_2pL} zI}tSIPM%Yf?GA56?yRhp&xHcCmzxevocCbQN$f{SH@w)0ZiIZ z`FG(nv{w#2>PTN9y#lz%#WG%FlNjTq8g6v&2~jDvgmRZY4OCB8jhJe#F4dHntn8-K zMG@WWg`y%|eJV5m`Iwy_aKYHm{ zId{di(C{}&mz&?Sa-BTVa#6vL_l6up06_dD+xcDhpQn^L(?m^nz_0AS>Pr&2bAz~a zL~QvCdDW6h^$S0G=kRDCroZm&N^O`~$%rYZkfosJ90wt!dJYKh@qORdzKMdH%3c)? z4|G`|C~A=A;hMnw(fRfZ?Ay^^M@rf{!vA8Pf{nDYIGS9qbg(iH%kK6mq0}LH0km#` zDE>8*;jG4F1o~6i{oG>ABx(=2sfLjxtJ_+S?*pi?$woXMhe#8WZ-yr2V$MsG)V`lj zLLE{VQldO|4t*heT-r`wcr@zV+1}QW3zxs@g!y9u54wY9*HcvkM(Crjw)^n6R~0(z zPgrZ+7SFrb^2uzhyidAUZ;eyj{;}nr%%};8y%qu|UT7UUk^$3;Az%;WzT!RGQa6%# z12DN0@XYo(q4a?i0e~$4e-iIpzOum0fEi|PyimLqvk2_gG*dBi6fS)2@@_5c3$F?n zhOPo20NY*%aEWp77ZE-nZER}8*#mEJV>slt64_3ay51~STx+?5#%Vs6m>Dtl4TOk} z91@80bVZiRc|dXI@*+!T_^USi*+h#;k_Q2rxLi|Iv|~D@xpP84d(Y)&54#_mLJ7CcjG=X>k*|po zJdyGXcaA<0PTezG_}6OkEd|70tiZwPz$lKy&CAQ&Ef&UeQPN#M!-fNja%gbJF*bFGOqINVjad{pr#ESKqy7dWHZU1#at-2SBmmwpRKL z?dNb8cfJOV41bZjXU`_n95wUxOQc~pkFk(8N)$YsqB#V(4G6N`oTQ|9Nm4dFQ082N zuBaenZ-6P4x37i+p%N40Hj^uc{AR5c7otrNf+i-)1gc4tA*_YcTyYE5wAd3O2NbU7 zYkv5;_l?*5t=h61Q7UY6%?ELNj%HE{dUYTP-!9GbKPNj~e;K$lO3~kBlD&{1gH;WY z($5;Q?o?iod<&e{g!5eNXw^RPP$IUp6+TXA#bEEK%`bfuBpoWBVKql)u9=(ar@Fy* zlMmiAN%goAH!XvJ?S7l}HpWd2pt-@R{$}-}eImEfXfZ!`*Zc%X0;4k3)rp(oYNlpt z%Oddduv?S51d$v7LQs@nie@%tQ(Df&v-=e~=;z5<;v&k!%#8*tqdo}iQWZ-o9-fF3 z`Ct&iedc2mBu&eRmHXAfn+ttLh%a+V{B~VoCC&+%^ zy;f+|b@=iNvu|z}ORe;E^t%?OUS3?9G(CQ+Cq0^F41)twe@e|)eBG-J>kAYu?kUi| zkmyx%tG=6WucbyLhodkS8TYmwktBl>%7UALD*)?;-eca|7+Iz(vOtB59JTE>S{0^1yw2mr-RESSf237fDB+(Qd7chG0*=5gR z&32k(b+d#hcn-l@-H7?N!4Lrr16%}aV|}%VJt*@!ro#-G*P4B(rIDM7MMt#Q;f;BDIH(k3 zD&G+Y@?Y_^B`jT;MF@%r^15ppYJ`ntrOC!=u!ppsSdBf$LeJ%|=kYPwWx%l-_WQ;P zuIgvwvaSUGo6RY05id(>9Wk%v2R%bVzI^E3z~VSl35MwDqJgD__gB>`N>(hr2T@N7 zUq_~qqAXhYCz8VycBX3s7$~PU!3X$rtuuB1gXb=K_RprzN?s@%=nAUq_SEFu!$mW; zc$uDK!6A>K2%-U&2>U^oaZ{;SEtRh;NLxK2M%li{3t1wIjj=JEgj%y1Evc>!4ub6Q z3zD!iPmho03ID88ymKs!v~+3bkqbsDIAK#roQ3DUu$!xs#$HUQu{In_km;x%`97Vz z7fWW?Z|Lux8g88j=(4Dcz`8xMNm18zx^5)9m(D(&e(?G0H6fWM3O}6N`1o=0aIM&DG)Z{EWx>6;uAd}D#>oN z?V_yT$ngQtlIGpH(FZb!^KUO_zgxo;{X9#EE`9ykS|DOs{1yEICKgh-bEeKsv(;UY zrAq*WGGt3VWVroUMS+*rQu6uwzoiLi8tv4i(+|H$*PS?8q;kKtLcIXdnmFZ8}*{P27Ckq+zbq6)+5*~#+(XcijwT0UR6G2+mc)rC+zdgl{45O(Wz{3~WAeN&Ix_I>8k4<5 z;UyO>(I;XghXE`F*Xt7Ug8vNht9n9ZThhY(>u9LxfS^Tfg=P=#~G za;p#X%GE`&z`pf4ZML}*Y)CuCb%U9=&qTt4DY(8z9q=O7ycjCz!0tu~#Xu1dz_zJI zt_ocRZiPuDer{D$eo*kxpvXQ@(q6qWkjkM`U+>Tbwf5%$&%9V@VLXkOA$ZA*-gW;@ zr(|?F(jAC{=*Pq_j|zBkOXtt!c}d(JQF!ByTbWlHIG=a-vrvC7I)p+n6_SNRz9>|y zdF=<}Ww`WjqZd6RI z`G|M2as4H(S|IHJ1QQNK-TwJ$jP{@;dhPY6+5NDCv51Dtmu?@0m$bZ>$QqD~tEvG{ z5HzT-BWh#$3Y_p1O0QQiT(nkJw?`wuk&&AtW=|v?0M~$CZ4$fH8UH#ek>SSa;1om0 z_QK%~4i57_dcyskTXpaA9d(1JS-He^@d>0fPQ#4`?&VL#%yoDs1V8AKjOsTw@oTW~ z*fkt{HY!i`!Sjh&bG}S3rN>qpmc>o#!8To{kG}tTD;jyD*ki89iR)*Z+Ji4FLhzv? zOiODOm$JkOE;vVz3~(p;{OHbS5w-zGX8QK6TnyT))T(||Ofq7}E4WZ(hHe$O3;;lt zYj9(MEWfOMFT+W+r<*l#a8jdBNXKTD?&6f}>mKb}Q>H?D+^j1zgcAQlOZT#*`r@LF zGMWZNciYQk zOmL6>$qKlPB(OxUc&ypoUF~}O5%1*ZO@oP;Setzc&*V9UiH$MAO(I>VzMpK_XaOu` z#PJVScApzJc0SYljCeo`ktGaG*NQrOe)C$Rly=X)C&zaFR8`{~X%yJ4DSPQ&zDwr7 zbFC^IYN|v9pwR{01#3$l(w#76%=pwmm}C!`qpzPr)tKs5;np>Fk#n=UvEcuC#fH11 z*Kzl1)Uz9kHo}^~N=tcvf45*_!#;xv%)n>3uz2z=Z)0@$kbq z{?BK00`8ZM7^4S7_A4J`P4BiEJkn--Y`?FMvfrp_p=UlL(9A}l3)guE#jCe#bB)sF zqVdRMKiU@hD9&X8*yn%#v$q~Z=%L2HDsP1@IVK=i1xIlukwt{axODKOoEs>4h`}=$ zR5PmJZQrh5?cSiqd}h%@bWM$$tFm8xMpv%}{{hQ)Z5A*K2)+^E%2-U5u8F*-NU%ONr?J)I_}U!=7h5W*<`(Z%+Q&f0Mn&&yzLW;nr~yjUB`Oz%X}TlWZjsh1`qiQ zo6JXc;`p<4&aAytJ^eoAgJ6K%K$PFkc$pr-c-*d=aY8W}EnOdY0A6AKtN`GS%K0x> zG(^YMr0gpN{t{+F^W%H^5?r}>cbHiqjV-|sghau&2v|1*he;JbZe2Sw4w4|nOxh+n zH^-q0{V<~GhF_HfJ=*CA;8NA%%e51^u(0n?-y5t>Y-*X1o`&P;^I^cf`$FZXIc<+T zjetzBi(_!nPf6#O%V$4W%WLSsQvX;C*;r$9*H(R=JmdPOO}Iex>*U7AYv-?jQ^-T@ zl}!soF#jC>Kn>m$cCTLfW6hlq=#rTGY z^@>=lIymIptJPy#scQGd6ketW2EDl6c68uGukP{2y~M=YGhuNqo`bf~f!F0FpT~$9 z64#^-T+vh9(Jh~vw74QSR5Px0?#_=qXKG;NCf-BeI!g@$yM%Zd9{jERj+eu>VFe$@IIs(R|H z_5mw5uf0E2d=)Of$LH?TPrMtrHbx8Tb%}d75G%a1O4B=Mxbr1_M@t-`Wp?xDP(ach z`;fVLr!_0ZXFrxzI&!OGEmNf-ki{olOg8D5yYZ00=VbU#FP(ZjgQ0z2&qdS#ahK?_ z9+7lN5DRig!f5W)qLP8Twqn=qf7HKcT+;Cqp(PUpxC|NTC5RUsf>7}Io6v+7Z7E|k z*;DG7CG@H}+dh=F^w2NO0oL~gG$nqKiE~j<}dKs5q*5kH5Z$C|MtFb zZ|YiZ_|Aq4bJ%5QzB_#p8;uXkw+Yb|A>?Ii03qL=BY|V9KP<)ueR)&32FNSsXAT~6 zcOmM{d%o{_<8U4?ZTtD_$iCJEA$ zWeHWZ5_E!Z4R3UkEDymIr#DCkAaR4tqN|xP=>f(L6`ws1-!LMU11WcUCAOv0_U^qV{`KdUtCwUo#ViElli;-*&oj?M`k&8QzCZ) z3n6XiQ>G1%7XOSrEbke5qLSkSVxFt>`?W7Zwm9MWLoeqp^j)UO=DocGrf_FCkTn@fs&4o5x z@gbbAt1YgM7vsG?6(s~^F(Kls3&8x>a|5T=$rxPFseMo1N#D*wa6J(ZjMd_bj2qxF zmG5$~g@Ff+jczqIfqn)UF+4?$?ivo*@lE zC{fk^wMJcTLTbL4EW_8`)d^gah^k`r$2lYsDLIT_-&YZRBnOFyP#fPZw`^^^IAYjj z{zfzORH+I_x>`QhokM*KfuSY4iF2bzZ#D1RywS>-Fr44f*D`RbAw&tS_6Qhs$;9pD zZV%-U&O7*JZO@%6i`e%1j>o(DIreGyv!&-L0{j%efvWAC2WFG@W0 zRC6>h`zGOV=&-1bn2X=)w?>zr4_Y5r@$F61epfC>o){|N@fCiZd07%J3~RIM*b|(3 zLhbIx$wuOZVvD&~dC$I2A9-jMem;tJuz^oU(npAU5aJ^a%;$DowcgyNV5a-rpE%E! zKO>$gTky{LM*Umo+Jc}3lR&tJeCfvauq&c!&6%m;Zo(SX5%l~HL;6PDcUpn73y#<6C)w6*o{ApnkxUU(YICh< zX;1v2WQ!JU)%|^4o6-TYMT^5xJkMr1h}MN&Y>8tPujJDGsJ8P17BL7n9I|%Oja1xJt|ul^azL> zkTWjEM9QExsTjQu z4?3HmVa+@+m?gwn@x!;de@QTWG|sxgKkKheX?%4lj=x#4I$(X+xdL0SIJIiid7>i%@hjepr)ux2uN+N2ZP5VF*e5i-dEke|&ip41yRBL-Tq=Dz9H_8=aXCQ# zB!@(!lW@k6h9Eu@23-<`0{bqXyQN$vG?h*b8k667f>C9v<01Ow`@u-VW5{U5F#-;; zb;Qc_9X?33_E+_*iua|bws5o(TLd{cNb7#XWHk6c)e&?Urze`y}Mso43A`s*?r8 z*2+}-zI%uQ|LODeS^^cd6ZsCS{vCt2%s?2gvx$Y zA61N?bWY%v{b(Am7?B@LCMBQlOrlZzbn25$SwjsZn2<_C4T|?8hx%Vl`%TwTZ-!|IxX9oGc1Huw}t za(^lzFLZWPx$8OSbWP7*iX2%Jr!4e#mbz>EPr84^gPgA|(jx+&J|uNP=d!0yO=fnPUO~eK3i-JblQ&r*QgE3ez9Z!cT$NY{hvw zk&pX0zW#jNe|Orh`Z_4Q!_!G9jayz#q@-Lkp=(y&u>Q#ge^k$^yk=4nnvYy%=)L^l z$mPMLd>tz(d)IR~eZeQEK4?)E_+FgIn|FpG+UxvG&gDN#kF%&;!ZQVAseax+{#=z* zYa-D=fAY=TshtVA+uWJ!!kO#JREWvTq&NRd`Dg0LnZOC9F#nlIK84v&-u0{xYEu6( zO$d@<+lz-?Z<*wrn0n(m6h81PeH9%T6IDKb_JTxtOjAb3MP{yAW+p*-%0+p`MeAja z!OL2^nMpgNB)f$(-~UovY3`>e4*(nT@ABj$^W@*HJc(xlWz&}e0Og%Fu}0=TdAA}T z&!mu)r;xGwGRNGyz{0Df2z*ZhyCb~Sku02H&*<2 zh3j6yV*y||?qP4-L!^Q$ASh}BE`Ut3LnM=f|x+@1$X6M902@} z6`VN|S^l{MAXZda5e&%k@Ad!D50Xm;6r9TXuS>pTWLW|)O8vJ}Bo{~t10=OY0 z{+0s=03IrgasYrMlhPQ{H;(eZKm`C~gnaP7@9n?83q$q>M*(1PtT$Q1v55eT1b|EO zisBi+1p2|2RIo8117lwlj-J{_ny`i9`A_u;jD<5oJqSRT z`^=$wBsxSaGp4C!nYtd4!x~v&Rl>$UaCGnN`L#$>*F5hUi%Uwdm5)SUklayfh1^l5 zA}LF@+y8@d!j(QU$1?Sfa=Q_Rj1>Gx_h>+lQNQ4Y+i%1A!EJex6|5^qhM2;T9lpm;~ z_$d1hquc|P|D)4~|4+Td|2NbM{})E|e`j9*fA@k7497SE!@fM(xFl3xhyZz{4Me|) z;>{=1Fa3OGXr}mig2L=?^BIL%>F3FL@4vjY+BWad z0As-?0E}t6O1NENMAsOJLqKpOifX601B`bDprY7I;XEjbNgqt82&F`}-PNR^kC1kQ zK_9Fp#hU;6=TqdK0A|b?iq8$j7qt;*ola90q1~o~Alm zaRQMP=A+OIGVnc}DkOvyz0RS*oczC#ZMf)r1#sDII$i^Dy z?BN#@miR6%Ci-1+Z1TIPu&@YtLQG;7fb+EFRDg z9NZ&re(8;Ps||(XN&xP#w%UEPqctyg}_o(>q4pUkqg=VuysdRb@%cN+ybk zAKEYBabjY{f?y1HbA}~MG^M$Rja)xfYNb`wUC0{Uy41||YIqHs|HMrSbSC@P1{I?B zNO-8G=8fo%ETtSNfUCaPhoJ%+tG93Gkbwr+WrhHw1o~Nfn@T(Y?Ju&mF!`Gbq7DCN zyo3T>{a+I#j4utdANc1DN={NV!_wxI9|9?uXu|;G{W|=b8!xg?|3UtXnw%&-fg%o#Rcjb(1Gy!Vr9YQzkh#n+lo{Ux;FYF zl0R@fN(6yOfyGs~GFU_KqI)(!Nrg9o0W?VhU)MEOtx4q;vwymd))oBSB zMxL&cznuIVc>ZyvL+F|E+k{ug~assK-L~R4l0A><&Agjj$56H7YGdBpASH)#0 z?$-XHXSM(GYuc0dtD#gH9q0tIY<#(CdP!_iGyuX=a4(9(=DqlB!C>YLlKM{&jaBN#5&jygN`OXtIXt`F}#Kwj123F9UNQHyoCe*bn%$nKZ=>J4UH0iTnNc26nc@0 z@o{`+wmA8|N7e$=IU|r*0stg(UZgH(2tEMx)^PCvh76Y#h8utXNs|O6_Up^H#&|7s z00$9#5_lHiZwf9X>RhdkpLff9($1<@MkBq$Zt5)- zax^?wXBF=2me#dE79R`^NEb08sLds=V-7JX+V*k4L(9ejzv3-D*tmLz35*&!=>gB+ z57L3WSFg!noCIqDI=^~|+J$-QxQbue)6!B%*Tke9#J*+)0KK4(qfRLfju_smfpJ|&I4b{7an zu9UR#XpRI;bggXS?VaMNk>=1k{P>QyyxMHkIc;y`efpt9&zJS)ExF1%@hmw27eed_ zLSl!^`+g|3juOUR>8MZxU;-;NGJ2B@vYR@=LnSL|(`HR%LQc%1O>170 zKE|P0j%!6~>SvEy)lxsJX8Fi_?nYSZNG&bI$}Z6{h8#59_?@b5PEZ2~#fn2HYrwgx zej~N-1C(N&&$T|`O<8Ei$xc`ZPnz0Z;H0Jvy;<8ndM#3#>*&cqVMg$7ZN5@3DUEsO##+o3H>3o45|;2;rxXgLX3wPf4hq zhjPzD?QWl>zd&4JF|!JKadMD580(de(;-I$6p1;j**B4Yy;9*rAt6Uc2liRJE0YU( zC4}D$8|re}(&aS)i*Ds`7!cke)J#y6Trwb68G3VX?8PIPoqFNs4!Q928){&&s@0-5^V%`3rSbFE(1~622>tg! z+qnqv14az&^vr|xd6;}AgaVJ_K+)sGtSkc{mEbSIk<)x@^ybo^hRqR*G3n+xiTduB zGgN04=LIe?Lk$d}m@TEWzw3><>@ZNed@DR~&xRsoRHXIheFGQk*3|wck1LU|j zkF>6d)70v6k~`C)a3~Vl5X5)tBWAY|-7EasI|{#T#TE~MeQP>V9a@cqg|;9gt`Cd;m=&k0#yCgm^Gm@63^h%fw!i90mT zbV@%1w6pdni;3hc(6+rm?NRJwP|FIL^Eq!^QwpL6Ywi zICDP^aEb8<0Q_$^V~jqn^2f6)Rt~UaVEVqn0~*l@&63jB*anh&t@(f-GN`Z6gknH& zs#xrEdN#XPhYw6scsuQj36!?<&feqM;w~*XGpi7!0^+lVeHgaCJMzv857g`EDa4Xh zDSoSte8(Hv$k!Hj{%+;O8C_^~XWSb+-aixgQ(=E@3pp1mosB#jI86hqV}{I_zX_7_ zwqS3p++qO31gh{bT@SCebPyM6Gh!(aY80#}-PjM8|mP#v@Hy?P|@fdufy% zurMB+5V5{g2^%tcR42rE+He2zugh;5YQU$_6&(h-0m(+e0mbQuGH|}R@6C1i@M?z2 z*L1i9$x*FSCDN~E*}e?uho(j(yS{lZ;Eo^@xZQ1JBm$89Pl#)8vR|KFuM5@`P4Sdv zjIm539)DTNWZKd=PObRl%B+$*%2s%fsj4MzFSGfcNJ@<1T<+Zd3Uklw6ko^FFI7Fe zX_4A7*8*C+c~JmSe{7(;9t5j4kvBjk%E@DM$s^_1#G9!)X1qO%tQ#arg*4I&^H(de zo^d>~U2P|kk6u1lHTx=@B&?$z6pBN;ld*zfzQLXA07D~Ej+|<`1%4ZKOCJ`7NHs@_ zQxT95>hcOy(%;<0CU|4W%V}D>gWq+c3+Dz12N!;~P{-QeXU%U}RiGYct^goz0l&It z#DORSJT{P9uV?TV9^Bn}4hf%JFpLc*b%9RFWcG~&d%St(I8R3-G^_f|;nZgPeP zJi!w}0I^-MjA1g#Xnd|yF#X!2xsl+24^VKkq>xs4NlM{}0FcjU$z%tQWnN()J^ zJ`JFA2;QO=!}a0yfBew}M%4Lt-v5Ae%=*vjr*ztHXdyQk0Imc+p&=SjavC7QTJ`66 z4Y9VR`?q{Ll8PT0u4>YRljw`rfr8gb=v zll4~D2X}3Z*~$;^6*w<}RNWXe4k(DAC)MFvBe%*^6`aNL7{*%zzl!pO zuqJ_8u}~Rfnh2O;_kf*m-Sf|Im%h9J<5o+Hn7_~u*!(%ceA!ta-`FH#a`J7m`PAOL zsd67c^k;0ML|<1aUbT+Tdy&4MF}s%SJB{2njh5Jz8`m1y>?OMy0s&*=JIE|8a*NZj z{>T{{!Lrah<2Y~$!-o$HCl&roRXb-)_X z3}Ugn4PvZ;P8}g`*2Uj<=WgDoUqlb*RiUu3)~7i;wSm6?TU4N`X%^(pjsw$xRK3H* z)jXKT%Xi{vqD3F$YENzE!peRQt}m}?l)|!C6q;<7%x^8esh1WEC4Vp$rjGV+#$o49 z^1yw@0hzJ@{4mdTXk$V{eM5qxlfz@9!{R^0M1+I{M#MzMM~B6Pg$GB{+EjFM$`W3x z4?p>d3>1Qy+>a3o;f=(ew1w*2z$>1QU2%*)K8e z-rwrPPTP@6h~G&vxNI;Z_(PQG4|k0(PshmfZ~dcRnZPAdZj-<1X=0J%!}OPJU}j&L z^37X$p6!p45vLb+dpT<=0Dmg}z8Jm@Qb=bOuE*)*jkG%1|8B}P7PYmUU0|L#_fQ{C z;zJ&I-r8-J5B;@Ue%5DQu_#rDA8VlO6s;fFovTf=5%c6OdRN_^oV`4$*mYEY#n#qg z?Z>oBmDLwNe;#zPH3*z-tq7$H4f|teC;bTnmx*~AJ7G1yWn`kC1Ou6xBQ*)wwnn+v zppn@H-?d&xUSVO?8h04Iv zIex3ED|Ia7lQ!^Eh4h8UGHtdw6u-M`i{;yoAn}8lisf_0mf9KDSN47h9clR3&gLI6 zTfE<$KcGfcHeqwJj*n7Vq_HD3P=N9ai;2SHI=&&|k^BK^2h6w!5K2Kegzr@P4ntZK zL8|}QUZVbTV#5qdD~HWK0kF8O1(Jv9p!qfZf`9aepkoj3hof2(;0pez5}Any0TnE8 zN1ORWfoJw4G1?8|FFD3hWMV6u!eYG>BV4dEkc=r&gULeb-wM+7>f}jB#!Fist9N!- zmDOL~iy#SK0^iL>HK;w=v3jGW-`(Q|8jZN6)E>DtJ;~iyR3Hh@q}QaM_CeR=kWQdC z`_+W=ImI4chsPevkKBxsLj&}d1b(DN6#04(Q#8=5OTUqQ>2$DN-TZ-~U8lzK7#GDa z&25p?6_e&`nN^vA$TCh50n;tvROv?U3&#v2qIzeLBDCV4G(! zRv$Vk)D0^b2FExWcxzlh5acP$l9L$xaxNAFrGcB;&=DEasr>ZqIbNCcaha?zzui@4 ztZ3R(lMb%a;rCTpU92$dnGpNqYTns_V%UG$i6VQzNY>~B^NnoY#u7JKlwrBzo+2E# z+sCa-e~9C5wBy2Bub$R_2PTGhg}zmqds}bKFHHR$S(BLY^v)=3%2u_fGdo$^2QV<_ZFJ-uM81@_(=fzQ z?*nN2lm0Nigf)&lu5P&|(cLagX{tC^?mNjfpSZQtd*K_I5%nvzy;R@8QbsE-tAD#lMla5`O;%O{<5zQUKxX?)|;zfp}@stVpqB0{)y9 z&d48ku|A>b1NF^oeS#vL5hXd9%wYX#Fv(9Oumymu)16C{?G_!Z&)aWcS*Jppfc;R$ zXpdNv=PuC8$up8hyJ}8&mChh>O(n5vjM~?K$eKk_NpsTq2iHgxvcUfP|mCyP< zzTRwLin90gro8v-$Fg3im1f~#Aayu^Xq>!GPw0HF*l2WNNA3~xDRK>u+RH;ASS$%%xkf)cuXPq9x9%A|D0YOh|Ka+>O(U~`0L!CM{ z+I&CP@yAy%%bAE@)7vU*I89cS`9c2uOs_I?rb^*oXC=`Fo|fI4ld%y(r|y+dpK$F6 ztlg=}L)LiF?PfdwYd_s9zpKj6tH(n)uEvn}WLfxarEv)XFJFS29y(~$+lrHWY&C6r>xo!gkts0~_r1k(SYHs5i{KltFZa7g8b-$}Ks)7^VK7%?*JLW@z;|-5Xi>C&Udm?a)p&ayy zJy%DQJ*UIBwvF6y{Zu^Np9~3JmbJ*Ly;aiU4n6T+hUtHLF+3(8kMQU6h(hA_O zuicO2`kY6gY17^)OZXiW* zsN~8MTdhe-U@?wxUum}V@#9zudYi6cf`bUzp*X@$|4B`uF8dU{FqddQfc9I(GD!M* zn1`uG%{Q`P8&kqKoDTOkTU>@ahEsEPDU4@I=K9XRwD~fTb1cr#)wbx?7E9(Q11T52 z+n?$_TYuU(y4n$wk9bqv@L7MwiP%vdhjk1Ml9f&b1gM~bb!m7XVHm5k{Prl1ta)%) ztX$i#3_6Q}Moyi7e66linEDIpfqm@HYoj4jMrK%t0`nz!9zFcwdK#mJ$UzWcf1!_b=%Xq=o2h4(X zO)$`g6?%pFme2e}Wq ze4!wK(bB0&WrLWA?lZR@3lea)vcBRb;2?OFB}009p9~sxJGlMk)FL-D(6XmY;J}04 z<@+|R$I_CQ3;^#em1YqWE`Q!BF_v{`s@3f!0+-U0X<=JuGta}bXEHY zfVe`*%hApQj!SphmDItoUKF*rF#aEC=Hcyk*S~4 z9h{F-7|MOHqR({(8$y3>WH{qfnZ@yRmQ+r_8Me8rM}TGhS3hyvsIBjsp=T&!0cg+pIHY(LOw{|#+t&;n@7Xm4=3Pd_xZKTQ=n(RgU?et}~4 ztw=_FtP@9P$+o_ORIO@x;@-(VZyq+zEuEoj@wA@OWK5WI!Gb@T6%}_K#0zUqCNrZ* z4!}j_7m8rt11_#Hz`sCrk?)$&hy8$Avg%Mmprks!LBsaf&db=>#C~z>z2O7xpIrx) zRo6bcYdjx|5<%LE;R%Z8jFIMdiI?@r?R?M9$PMJ{NrbOm$4Z`J?vVZ~drwK{w_&Zp ze`d!ceeZxhgnd(^&`f6F0O*Frxar>hyX^MPbt(OW0yr3%enf4X_>5}SRJ|7 z-otE;AndM1Z1p+@RNW1r^Fg~^T18`&(6Uu5w`FxSp(bx<)2rV@7d5S%e(!~9RB|y8 zrS?0-acdZ<{(RY9q(Q$+uRHM(3`z*AW6gV8&99xC3apl=bMnvNq-EiJwy6Lc&t42%I{r=X^pQ zSH$l=DiQel5sWA`Y@^OTP~*9koa7oj=h(KN?zb}bZ^L1 ztpn*%p6TU|YRT!^eh*SVAt@29((Be~h*l##23)D^_X;l$! zHx7h@KqIe?wK-&4D|a#NERumr#vO&Q-=hG}E3 z`Lep7{I2LEXh;`&8iAHE|i9eHt+DS`EW zmc`%vi?@Ymi_&(#&1?)}u~hJ<|K;$4>gZfYhVS(=X~*HFP9NYooxJc9)cUvaqjG4J z?kE&N`XhZ60&U?VMz$aiCHu31=h~>pLd@*o1Cd_r9byg3uA_WMq%$o*4rqK+G8+E7i+~& zPDUrs8EwX0_g&rlFFA_MS1d&mJ)8n?=1Xa3jEZj12Qoi)&z*o;zT5OXy0q>cC-L=r zLdRxHA>(9Nd>?k@g$6yl`c2YGZ{ntHRFmPKsXj)Ti?#Hz55DJ=k$8YZ5(vk%^kpL< zF;#|*0{ECHZ~?IG&(9YEFwBN?)|%% zh~sJ^)XzBp#R8wxn8EY z`RVO%Dp~WgVsi_Q>Ad%bxs$LrZoGN!ST zBGFOsAIoIz#+tRh`A_&PPY!l@bvU$pAFk1%UqlsDJ|)T8*lkaW-} z`V`ARwbo*;B)-S&hZEdPxsgN&45gNj4X#(*#_L-m8{+`;92K)t4kGACoHpODWOsGD=r3iV_n~1mTgt_og zsd!wZfWo+=$EHM&JI@EPF=l9>P}Y`~nJU@jjO5t02Qe78x~- zZ;u?hFs3gSB`+{yxD@+{o8q_w?_riL9kawj<3etFHO(%{nJAUxWZ2cfwcptG9zmT< zXX{NFDnvR}G8=YF)*hQe<&VCrOzn26;JRABSft-o6M)4Kvaa= z5+OMkDbC_r?k1|A)quU{IFa%X9LIle_=+4ONQtv?aF?O-_G%#PY~MrgxPMISd-!99 zZRAT?#V3+CPZ&fWV!C}~^-bvtJXJP(*!H$|gZnV~3)@lsVlK5dcDk47h47@y1Dr?I ztqx*B-R?%8s@-$m0pipxy&}=uK{*0cX5aO1o`sz%dgWi2s=y3L4MMsK3tYl*NT%5C z*QUPG2>(-anV483BFlfWB04Ki4uGp<7yA30PDSC^-}+aIq7krzFtfNb2jj4te8s5c z!(H)EUXik)0Kzq0tj0_>{8Um{!+iYpXUf%k;Y?ziGQ85!HRO*=pD(<>&`L5?1Q3^V zGdQD1@r!ihcCXMXchIbwQ%f#%6d*6_a;9*SL|(NSBksc&#kGfj)3)v2U(8JZ11`P? zOwQrBqx+6ae=|Cj9Zm$0AGJkppjv((vNx{^jf3mxpydf0@xZqDHl$TvWt@!8B*jY6 zJ&H_@_fDdsd*hxY$=r=^CjR1a)3m3?+<*={HwZx`evA`(_K57d{Dn@}#9uDDA13~f zC~r$X6se9(oV2!8B1O}=>~(n;)vhJpVf%@V1|Sy1uDdN~o(Q7>lR9o5n@tk)ibE%T85HQjX2CfFI4$VrMrkBl)KbH#N( zmptme2RmwYtGAXu?KdH`D(gK?`rQ!#;KCQ>f7mtf;lzdGddl?_dzcopnqGhq`Rc8d z1G6~<<$)ho6T3ICcmi4!QfV4tsL_DD-nyJ^*-H>v#y&Y0&am9Vc8`z0ToQF#rx2Vr zUSUSdVDlU1#J!OTlXwc7i>zFj`vys)bIJM0EbeZE)`&h%P`4knR&$?n1;VEILI%<+ zH_*rxEkcxvgvNidP|t2CAU6NE_#(=S}RDD?>kc(%sU@8c=3eh@TIsG zsr@`4uJ3mt5^W*Z`JTi&^6OHr5A2r_&o$+Xx}2e@4;cJtwZ=jf7j$8YdeP^pb4IcZhyvep8S48@vb?sCBfBojEl{IwX<&)V zl#5S49fB1XY}9abKWYDWafB8mD7c*Izl4Rf`W-Bj+%6AyB=a8j*j*m3rZ*!HzK$q| z}QW zl6z-!-n4mmQatLK)e>ePC#-x-e^iIcS6Q_c26Vq~!-QYKmSW!mTJtXS&$1qQ=%E3Q z!pgL`yqo$$Qr@3E8bop*C%o&`kkGof|=vet^pxzF1FLTr7 zW}e~DbBU1yKA1k8=k+fZ@UDQ}YM={q#LK*Mn9yc;^*JWGX}M=dp71ocZuDD%GSYbS zgz+bd9Z&aQ|21~*Y_L}U;{l*qw$mimuU_|M2@~JZoLF)zgNJdP$ z*y)OMf!x`2Pj?&kA`uC|1H0Yu74DY9-7kPUG2#L7t?U5A1!&W>L-`Z!<;JN+M?E`n zDWE^ebtBF@o)@uEf2{aBE5Xn%As&KZNbPqbV*NMSr)H5bwKJ4%50rKSfg(x^hdbB9 z@XueE8gwKs-}{nb3H+AOBg-GRUXU`2WLM*u%-V0-!`|*)!4~9^c$LOK;3edcXc@e` zR^SPlLOE3%xYY>t7b$)C!Hi?!8%lmSQT>tg$gk~}b7x;Aeo`yO)vkTu&!>~75q3Xn z?TyV~16r{CrjTy-JNMWvz)8BAx?Fb7XlU}=$aqL7rQ;Dx)TLuR237?aoC%ln2S7W&8d^10 z_#!detP=rXo9!xK7~n~$4Q-s7pqU|^c5a`FHT?0wP-&z*UR5`;XPtJXST|z?&2XzZ z5y$GQ_-H9+YGRNr;0o?I@SMgM1gVY1-G-6D#R>lR1s0vU^W(D^rMjcD(&zqs zv{$Ot7+ki%YZ(xzF@l7x?Kc>R<*L%7c}_9(h24CQXE7;FzBM&dWp|}@X#9EcY{h3Q zPeHSwqy!8+y>uO}xMkiCn{)i2mM!0I&ggBFE{O*1t&%4=epA$qo7~}u{;lv-kKO)W zAvA((tgfSfk`wD)b5|daZO9j{o9cSzEjLU?B5*^)GS7@!8e5EyE;l$3`+wVvKq1jw zFcYToL)srYgs*k;)a+xc2VkA~OC_Ly!;RMGJvsHOa?V6I1#*vGMO+UksrH=QT=@T{ z3nT?HwwkAK+(aZa2PB~5TD+v!oA`g;c)v(veB*_!{7twWZ%1}OVEulfHa7QG=NroL zPyXnCckKOub8tSrDUxyG{_xbHXs)~;fWwBe95KF;f^i{>$DE+LG2$#)0Nzpx0_ISF zUS$HwG)HkN)&P^|?M_Pek7_A-v5Z#2iMq7pGeeK(zN&svLaL5$H*wRZgzr>by@~{n zP(|Rv9{4wc=<6Sc#>H4u15&XM+^5}vC!F{=>!kPClc(`_ZgbrQ`JVEt>kSRLRMA$| z$9^oKp?ErcwAj^)Cn9hk&;WIoB*j}`bcLQA1qc!QSvM3oOGcCztg1MJX3N-UwMyOY zc|avyTX^uYej&5>ke7CI4hBP;I^bGh>1L-yPt&>|70cR8maB zheE`r?`68lZ}F{17j=0_NC>ul#!eesm+VuF;9S6T)jBp)ovcAyrqO&tI!lQX>5RBf z+m=~<5RHC%_5o$BKO6OSX0?Mno%6Om_YET!qU-=XZocDMhyJo=#b@>v zJU_$QpZjN+LRhOD5#r(BLtUpbJE46F05~O^_J}% z#`r`p123LBgpd@VXrO%V94X%%#JS1+RjCWmZuwr)bf3g=U+biJk?OP>ZFc@Sh|?aC zSf_~*Cx6K4rPG%EL zBB_|&|4iwwnH2E=NG)sPj6QnA72oP=y;V}bb+f}_yZp#4-ru@Nf8_m(NV4!DopCkC zFwo~f-y-mAAKs>tuy38(rm zEG@E?kHq(lvi_=2HaOd%tVz&%?vt31kz1tMG_mg+>OPttk)(j5wcyc*rpCKI-k;P+ z|IX8J)DY@snITkp?v?uev&%1S9s8bRy8%T?b0@Bwj|6+dFJAT#M<;5mGO&@6`EA~8 zkehz}o8`$^0rm6pKjCCpa38ex$bF@8EKGCeyx>b7eUVxqABGh+Ft98R))yzexe!1iQg5K58mHaJIBZDn&JyB NzAF?F9I=GJ{{WT23*7(! literal 0 HcmV?d00001 diff --git a/Resources/Audio/Misc/windowsXP_startup.ogg b/Resources/Audio/Misc/windowsXP_startup.ogg new file mode 100644 index 0000000000000000000000000000000000000000..32cd462de35e74e635fddf75380e194de3055d1a GIT binary patch literal 27591 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
Yh}oKwj|tSyUsSyL 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 Men`#eH}MVoKSlG>-2eap literal 0 HcmV?d00001 diff --git a/Resources/Prototypes/Entities/Constructible/Specific/cargo_telepad.yml b/Resources/Prototypes/Entities/Constructible/Specific/cargo_telepad.yml new file mode 100644 index 0000000000..7e7ec8d028 --- /dev/null +++ b/Resources/Prototypes/Entities/Constructible/Specific/cargo_telepad.yml @@ -0,0 +1,26 @@ +- type: entity + name: cargo telepad + id: cargoTelepad + description: "Temporary cargo delivery for developing Nanotrasen stations! Warning: destroying this while goods are in transit will lose them forever!" + placement: + mode: SnapgridCenter + components: + - type: Clickable + - type: InteractionOutline + - type: Physics + mass: 25 + anchored: true + shapes: + - !type:PhysShapeAabb + bounds: "-0.45, -0.45, 0.00, 0.45" + layer: [ Passable ] + - type: Sprite + sprite: Constructible/Power/cargo_teleporter.rsi + state: pad-offline + - type: Destructible + deadThreshold: 75 + resistances: metallicResistances + - type: Anchorable + - type: Pullable + - type: PowerReceiver + - type: CargoTelepad \ No newline at end of file diff --git a/Resources/Textures/Constructible/Power/cargo_teleporter.rsi/meta.json b/Resources/Textures/Constructible/Power/cargo_teleporter.rsi/meta.json new file mode 100644 index 0000000000..668446e50b --- /dev/null +++ b/Resources/Textures/Constructible/Power/cargo_teleporter.rsi/meta.json @@ -0,0 +1,45 @@ +{ + "version":1, + "size":{ + "x":32, + "y":32 + }, + "license":"CC-BY-SA-3.0", + "copyright":"Taken from /vg/station at commit 5c50dee8fb2a55d6be3b3c9c90a782a618a5506e", + "states":[ + { + "name":"pad-beam", + "directions":1, + "delays":[ + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name":"pad-idle", + "directions":1, + "delays":[ + [ + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + }, + { + "name":"pad-offline", + "directions":1, + "delays":[ + [ + 1.0 + ] + ] + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Constructible/Power/cargo_teleporter.rsi/pad-beam.png b/Resources/Textures/Constructible/Power/cargo_teleporter.rsi/pad-beam.png new file mode 100644 index 0000000000000000000000000000000000000000..08e4dd0edadf3954b885f88271a2cd147d02cf65 GIT binary patch literal 1660 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 Eg3tgoV*mgE literal 0 HcmV?d00001 diff --git a/Resources/Textures/Constructible/Power/cargo_teleporter.rsi/pad-offline.png b/Resources/Textures/Constructible/Power/cargo_teleporter.rsi/pad-offline.png new file mode 100644 index 0000000000000000000000000000000000000000..e701d9994d2227227fad91902511f593dfac985e GIT binary patch literal 580 zcmV-K0=xZ*P)o*=%i_)!Y6qyYqPa{{MMzW+5gfCMG5(CIV^0l2L1% zi6U$*F3{gb0_>0biKu2yMY-OT#Y{?;>&?hrn2NMv$zmoYqmE&sZE3@j*5U#m*4`w7 zasS#pyX(EXKQCxCg5xOHo3g+CDRfL;AZ=JOJAaM?cL#vaU%w~(!pk>GnC2X9yF;y7 z;bZ?Bqpf$$UAf6s>!KHT-4U&gu4bf|Ny$>RL2oc*_~nOY#5;uh<9>p9A^nDwFrbOI z?GD!}HAY)#;_9isX>IVk-Y#8xm86-U=z_KoLdZfcOV?fvb}BNe1CHZpnxWTFB^Pp8 z0D6PrVSC4Wn8qybc#rd!F0;P!kmXyqwYX`_(t7iQZs1kyOZKY1itHs-Phf=jcsoKzLgzX+eZUOumg)-ycfr_ca3XnAON9L(IVd8MipU^*o zAW1XNfxF|02lM{c_7fTK7pqk(09;>M0^t6GN1h4Ay}Ne+c)z&`K-=z|$iPHfggCs4 z{+6j&P|S}qr3m}}s4<)xA%qk{$fr*pOZ7f&t*IUPMgQ5(qL`SLnd4LbFTVgUq3&3M S;;TLY0000 Date: Sat, 19 Dec 2020 14:39:59 +0100 Subject: [PATCH 11/29] Update RobustToolbox --- RobustToolbox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RobustToolbox b/RobustToolbox index 7ef2cec121..58560f589f 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit 7ef2cec121edb831a73a0e02d4e7283b4f3d08e5 +Subproject commit 58560f589f6defe7e092cecd71b2353d26a2220d From d7e489f2b851529444f6056927a117e2e86a34a0 Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Sat, 19 Dec 2020 17:11:08 +0100 Subject: [PATCH 12/29] Fix EntityTest SpawnTest --- Content.Server/GameObjects/EntitySystems/AI/AiSystem.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Content.Server/GameObjects/EntitySystems/AI/AiSystem.cs b/Content.Server/GameObjects/EntitySystems/AI/AiSystem.cs index d5a17bf19c..5a7e6bb994 100644 --- a/Content.Server/GameObjects/EntitySystems/AI/AiSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/AI/AiSystem.cs @@ -70,7 +70,8 @@ namespace Content.Server.GameObjects.EntitySystems.AI foreach (var message in _queuedMobStateMessages) { - if (!message.Entity.TryGetComponent(out AiControllerComponent? controller)) + if (message.Entity.Deleted || + !message.Entity.TryGetComponent(out AiControllerComponent? controller)) { continue; } From 8ac3779d1ddf3354b50237ed3d4ba4c1bf6c247b Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Sat, 19 Dec 2020 17:18:29 +0100 Subject: [PATCH 13/29] Fix cargo telepad destructible component --- .../Entities/Constructible/Specific/cargo_telepad.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Resources/Prototypes/Entities/Constructible/Specific/cargo_telepad.yml b/Resources/Prototypes/Entities/Constructible/Specific/cargo_telepad.yml index 7e7ec8d028..7d1fe9fb29 100644 --- a/Resources/Prototypes/Entities/Constructible/Specific/cargo_telepad.yml +++ b/Resources/Prototypes/Entities/Constructible/Specific/cargo_telepad.yml @@ -17,10 +17,13 @@ - type: Sprite sprite: Constructible/Power/cargo_teleporter.rsi state: pad-offline - - type: Destructible - deadThreshold: 75 + - type: Damageable resistances: metallicResistances + - type: Destructible + thresholds: + 75: + Acts: ["Destruction"] - type: Anchorable - type: Pullable - type: PowerReceiver - - type: CargoTelepad \ No newline at end of file + - type: CargoTelepad From 3e9a36ac4c51747318ea2dd8d52b01a87f1add18 Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Sat, 19 Dec 2020 17:34:18 +0100 Subject: [PATCH 14/29] Add test for enum parity between JobPriority and DbJobPriority --- .../Tests/Job/JobPriorityTest.cs | 31 +++++++++++++++++++ Content.Server.Database/Model.cs | 2 +- Content.Shared/Preferences/JobPriority.cs | 2 +- 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 Content.IntegrationTests/Tests/Job/JobPriorityTest.cs diff --git a/Content.IntegrationTests/Tests/Job/JobPriorityTest.cs b/Content.IntegrationTests/Tests/Job/JobPriorityTest.cs new file mode 100644 index 0000000000..03e12ae964 --- /dev/null +++ b/Content.IntegrationTests/Tests/Job/JobPriorityTest.cs @@ -0,0 +1,31 @@ +using System; +using Content.Server.Database; +using Content.Shared.Preferences; +using NUnit.Framework; + +namespace Content.IntegrationTests.Tests.Job +{ + [TestFixture] + [TestOf(typeof(JobPriority))] + [TestOf(typeof(DbJobPriority))] + public class JobPriorityTest + { + [Test] + public void JobPriorityEnumParityTest() + { + var priorities = Enum.GetValues(); + var dbPriorities = Enum.GetValues(); + + Assert.That(priorities.Length, Is.EqualTo(dbPriorities.Length)); + + for (var i = 0; i < priorities.Length; i++) + { + var priority = priorities[i]; + var dbPriority = dbPriorities[i]; + + Assert.That((int) priority, Is.EqualTo((int) dbPriority)); + Assert.That(priority.ToString(), Is.EqualTo(dbPriority.ToString())); + } + } + } +} diff --git a/Content.Server.Database/Model.cs b/Content.Server.Database/Model.cs index 39f80bec76..2b2ac59a14 100644 --- a/Content.Server.Database/Model.cs +++ b/Content.Server.Database/Model.cs @@ -119,7 +119,7 @@ namespace Content.Server.Database public enum DbJobPriority { - // These enum values HAVE to match the ones in JobPriority in Shared. + // These enum values HAVE to match the ones in JobPriority in Content.Shared Never = 0, Low = 1, Medium = 2, diff --git a/Content.Shared/Preferences/JobPriority.cs b/Content.Shared/Preferences/JobPriority.cs index 73deac3523..bf0bbf6aad 100644 --- a/Content.Shared/Preferences/JobPriority.cs +++ b/Content.Shared/Preferences/JobPriority.cs @@ -2,7 +2,7 @@ namespace Content.Shared.Preferences { public enum JobPriority { - // These enum values HAVE to match the ones in DbJobPriority in Server.Database. + // These enum values HAVE to match the ones in DbJobPriority in Content.Server.Database Never = 0, Low = 1, Medium = 2, From b44cb0095a09e8b7b0c607d504311ef092315b8b Mon Sep 17 00:00:00 2001 From: Swept Date: Sat, 19 Dec 2020 23:16:50 +0000 Subject: [PATCH 15/29] Traitor Uplink Content (#2778) * Adds syndicate toolbox * Ancient jumpsuit * Disk, Extra-bright lantern, syn med/ammo duffels etc. * Disk sprite fixed * Final * Addressed reviews * Update duffel.yml Co-authored-by: DrSmugleaf --- .../Components/PDA/UplinkCategory.cs | 6 + Resources/Prototypes/Catalog/Fills/duffel.yml | 128 +++++++++- .../Prototypes/Catalog/uplink_catalog.yml | 225 +++++++++++++++++- .../Entities/Clothing/Hands/gloves.yml | 11 + .../Entities/Clothing/Shoes/specific.yml | 10 + .../Entities/Clothing/Uniforms/jumpsuits.yml | 33 +++ .../Entities/Objects/Consumable/food.yml | 20 -- .../Entities/Objects/Devices/pda.yml | 9 + .../Entities/Objects/Misc/dat_fukken_disk.yml | 19 ++ .../Objects/Misc/identification_cards.yml | 16 ++ .../Objects/Specific/rehydrateable.yml | 34 +++ .../Entities/Objects/Tools/jaws-of-life.yml | 41 ++++ .../Entities/Objects/Tools/lantern.yml | 13 + .../Entities/Objects/Tools/toolbox.yml | 21 +- .../Entities/Objects/Tools/tools.yml | 27 --- .../Back/Duffels/syndicate.rsi/icon-ammo.png | Bin 0 -> 294 bytes .../Back/Duffels/syndicate.rsi/icon-med.png | Bin 0 -> 289 bytes .../Back/Duffels/syndicate.rsi/meta.json | 8 + .../ancient.rsi/equipped-INNERCLOTHING.png | Bin 0 -> 1312 bytes .../Uniforms/Jumpsuit/ancient.rsi/icon.png | Bin 0 -> 455 bytes .../Jumpsuit/ancient.rsi/inhand-left.png | Bin 0 -> 287 bytes .../Jumpsuit/ancient.rsi/inhand-right.png | Bin 0 -> 321 bytes .../Uniforms/Jumpsuit/ancient.rsi/meta.json | 27 +++ .../equipped-INNERCLOTHING.png | Bin 0 -> 1420 bytes .../Jumpsuit/centcom_officer.rsi/icon.png | Bin 0 -> 437 bytes .../centcom_officer.rsi/inhand-left.png | Bin 0 -> 284 bytes .../centcom_officer.rsi/inhand-right.png | Bin 0 -> 321 bytes .../Jumpsuit/centcom_officer.rsi/meta.json | 27 +++ .../equipped-INNERCLOTHING.png | Bin 0 -> 717 bytes .../Jumpsuit/centcom_official.rsi/icon.png | Bin 0 -> 273 bytes .../centcom_official.rsi/inhand-left.png | Bin 0 -> 416 bytes .../centcom_official.rsi/inhand-right.png | Bin 0 -> 452 bytes .../Jumpsuit/centcom_official.rsi/meta.json | 27 +++ .../Misc/id_cards.rsi/blue-inhand-left.png | Bin 0 -> 256 bytes .../Misc/id_cards.rsi/blue-inhand-right.png | Bin 0 -> 356 bytes .../Objects/Misc/id_cards.rsi/meta.json | 16 ++ .../Misc/id_cards.rsi/orange-inhand-left.png | Bin 0 -> 283 bytes .../Misc/id_cards.rsi/orange-inhand-right.png | Bin 0 -> 284 bytes .../Objects/Misc/nukedisk.rsi/icon.png | Bin 0 -> 353 bytes .../Objects/Misc/nukedisk.rsi/meta.json | 21 ++ .../Objects/Tools/jaws_of_life.rsi/meta.json | 84 ++++++- .../jaws_of_life.rsi/syn_jaws_cutter.png | Bin 0 -> 598 bytes .../Tools/jaws_of_life.rsi/syn_jaws_pry.png | Bin 0 -> 525 bytes 43 files changed, 771 insertions(+), 52 deletions(-) create mode 100644 Resources/Prototypes/Entities/Objects/Misc/dat_fukken_disk.yml create mode 100644 Resources/Prototypes/Entities/Objects/Specific/rehydrateable.yml create mode 100644 Resources/Prototypes/Entities/Objects/Tools/jaws-of-life.yml create mode 100644 Resources/Textures/Clothing/Back/Duffels/syndicate.rsi/icon-ammo.png create mode 100644 Resources/Textures/Clothing/Back/Duffels/syndicate.rsi/icon-med.png create mode 100644 Resources/Textures/Clothing/Uniforms/Jumpsuit/ancient.rsi/equipped-INNERCLOTHING.png create mode 100644 Resources/Textures/Clothing/Uniforms/Jumpsuit/ancient.rsi/icon.png create mode 100644 Resources/Textures/Clothing/Uniforms/Jumpsuit/ancient.rsi/inhand-left.png create mode 100644 Resources/Textures/Clothing/Uniforms/Jumpsuit/ancient.rsi/inhand-right.png create mode 100644 Resources/Textures/Clothing/Uniforms/Jumpsuit/ancient.rsi/meta.json create mode 100644 Resources/Textures/Clothing/Uniforms/Jumpsuit/centcom_officer.rsi/equipped-INNERCLOTHING.png create mode 100644 Resources/Textures/Clothing/Uniforms/Jumpsuit/centcom_officer.rsi/icon.png create mode 100644 Resources/Textures/Clothing/Uniforms/Jumpsuit/centcom_officer.rsi/inhand-left.png create mode 100644 Resources/Textures/Clothing/Uniforms/Jumpsuit/centcom_officer.rsi/inhand-right.png create mode 100644 Resources/Textures/Clothing/Uniforms/Jumpsuit/centcom_officer.rsi/meta.json create mode 100644 Resources/Textures/Clothing/Uniforms/Jumpsuit/centcom_official.rsi/equipped-INNERCLOTHING.png create mode 100644 Resources/Textures/Clothing/Uniforms/Jumpsuit/centcom_official.rsi/icon.png create mode 100644 Resources/Textures/Clothing/Uniforms/Jumpsuit/centcom_official.rsi/inhand-left.png create mode 100644 Resources/Textures/Clothing/Uniforms/Jumpsuit/centcom_official.rsi/inhand-right.png create mode 100644 Resources/Textures/Clothing/Uniforms/Jumpsuit/centcom_official.rsi/meta.json create mode 100644 Resources/Textures/Objects/Misc/id_cards.rsi/blue-inhand-left.png create mode 100644 Resources/Textures/Objects/Misc/id_cards.rsi/blue-inhand-right.png create mode 100644 Resources/Textures/Objects/Misc/id_cards.rsi/orange-inhand-left.png create mode 100644 Resources/Textures/Objects/Misc/id_cards.rsi/orange-inhand-right.png create mode 100644 Resources/Textures/Objects/Misc/nukedisk.rsi/icon.png create mode 100644 Resources/Textures/Objects/Misc/nukedisk.rsi/meta.json create mode 100644 Resources/Textures/Objects/Tools/jaws_of_life.rsi/syn_jaws_cutter.png create mode 100644 Resources/Textures/Objects/Tools/jaws_of_life.rsi/syn_jaws_pry.png diff --git a/Content.Shared/GameObjects/Components/PDA/UplinkCategory.cs b/Content.Shared/GameObjects/Components/PDA/UplinkCategory.cs index 13f8ad5245..a9278bba79 100644 --- a/Content.Shared/GameObjects/Components/PDA/UplinkCategory.cs +++ b/Content.Shared/GameObjects/Components/PDA/UplinkCategory.cs @@ -4,6 +4,12 @@ namespace Content.Shared.GameObjects.Components.PDA { Weapons, Ammo, + Explosives, + Misc, + Bundles, + Tools, Utility, + Armor, + Pointless, } } diff --git a/Resources/Prototypes/Catalog/Fills/duffel.yml b/Resources/Prototypes/Catalog/Fills/duffel.yml index b86c279f9d..4a6180c7c9 100644 --- a/Resources/Prototypes/Catalog/Fills/duffel.yml +++ b/Resources/Prototypes/Catalog/Fills/duffel.yml @@ -1,7 +1,7 @@ - type: entity parent: ClothingBackpackDuffelMedical id: ClothingBackpackDuffelSurgeryFilled - name: surgical duffel bag + name: surgical duffelbag description: "A large duffel bag for holding extra medical supplies - this one seems to be designed for holding surgical tools." components: - type: StorageFill @@ -14,3 +14,129 @@ - name: Scalpel - type: Storage capacity: 30 + +- type: entity + parent: ClothingBackpackDuffelSyndicate + id: ClothingBackpackDuffelSyndicateFilledMedical + name: syndicate surgical duffelbag + description: "A large duffel bag for holding extra medical supplies - this one seems to be designed for holding surgical tools." + components: + - type: Sprite + state: icon-med + - type: StorageFill + contents: + - name: Hemostat + - name: BoneSaw + - name: Drill + - name: Cautery + - name: Retractor + - name: Scalpel + - type: Storage + capacity: 30 + +- type: entity + parent: ClothingBackpackDuffelSyndicate + id: ClothingBackpackDuffelSyndicateFilledShotgun + name: Bojevic bundle + description: "Lean and mean: Contains the popular Bojevic Shotgun, a 12g beanbag drum and 2 12g buckshot drums." #, and a pair of Thermal Imaging Goggles. + components: + - type: Sprite + state: icon-ammo + - type: StorageFill + contents: + - name: ShotgunBojevic + - name: MagazineShotgun + - name: MagazineShotgunBeanbag +# - name: ThermalImagingGoggles + - type: Storage + capacity: 100 + +- type: entity + parent: ClothingBackpackDuffelSyndicate + id: ClothingBackpackDuffelSyndicateFilledSMG + name: C-20r bundle + description: "Old faithful: The classic C-20r Submachine Gun, bundled with three magazines." #, and a Suppressor. + components: + - type: Sprite + state: icon-ammo + - type: StorageFill + contents: + - name: SmgC20r + - name: MagazinePistolSmg + amount: 2 +# - name: SMGSuppressor + - type: Storage + capacity: 100 + +- type: entity + parent: ClothingBackpackDuffelSyndicate + id: ClothingBackpackDuffelSyndicateFilledLMG + name: L6 Saw bundle + description: "More dakka: The iconic L6 lightmachinegun, bundled with 2 box magazines." + components: + - type: Sprite + state: icon-ammo + - type: StorageFill + contents: + - name: LMGL6 + - name: MagazineLRifleBox + - type: Storage + capacity: 100 + +- type: entity + parent: ClothingBackpackDuffelSyndicate + id: ClothingBackpackDuffelSyndicateFilledGrenadeLauncher + name: China-Lake bundle + description: "An old China-Lake grenade launcher bundled with 9 rounds of various destruction capability." + components: + - type: Sprite + state: icon-ammo + - type: StorageFill + contents: + - name: LauncherChinaLake + - name: GrenadeBlast + amount: 3 + - name: GrenadeFlash + amount: 3 + - name: GrenadeFrag + amount: 3 + - type: Storage + capacity: 200 + +- type: entity + parent: ClothingBackpackDuffel + id: ClothingBackpackDuffelSyndicateCostumeCentcom + name: Centcom official costume duffelbag + description: "Contains a full CentCom Official uniform set, headset and clipboard included. The headset comes without an encryption key." + components: + - type: StorageFill + contents: + - name: ClothingHeadHatCaptain + - name: ClothingEyesGlassesSunglasses + - name: ClothingUniformJumpsuitCentcomOfficial + - name: ClothingShoesBootsJack + - name: ClothingHandsGlovesColorGray + - name: ClothingHeadsetService + - name: ClothingOuterVestKevlar + - name: Paper + - name: Pen + - name: CentcomPDA + - type: Storage + capacity: 50 + +- type: entity + parent: ClothingBackpackDuffelClown + id: ClothingBackpackDuffelSyndicateCostumeClown + name: clown costume duffelbag + description: "Contains a complete Clown outfit." + components: + - type: StorageFill + contents: + - name: ClothingUniformJumpsuitClown + - name: ClothingShoesClown + - name: ClothingMaskClown + - name: BikeHorn + - name: ClownPDA + - name: ClothingHeadsetService + - type: Storage + capacity: 30 diff --git a/Resources/Prototypes/Catalog/uplink_catalog.yml b/Resources/Prototypes/Catalog/uplink_catalog.yml index 1c1542f2ef..6a5d0c75d5 100644 --- a/Resources/Prototypes/Catalog/uplink_catalog.yml +++ b/Resources/Prototypes/Catalog/uplink_catalog.yml @@ -1,17 +1,238 @@ +# Guns + - type: uplinkListing id: UplinkPistolClarissa category: Weapons itemId: PistolClarissa - price: 15 + price: 6 + +- type: uplinkListing + id: UplinkRevolverInspector + category: Weapons + itemId: RevolverInspector + price: 8 + +# Inbuilt suppressor so it's sneaky + more expensive. +- type: uplinkListing + id: UplinkPistolMandella + category: Weapons + itemId: PistolMandella + price: 8 + +#- type: uplinkListing +# id: UplinkCrossbowEnergyMini +# category: Weapons +# itemId: CrossbowEnergyMini +# price: 8 + +# bug swept to make +#- type: uplinkListing +# id: UplinkESword +# category: Weapons +# itemId: ESword +# price: 8 + +# bug swept to make +#- type: uplinkListing +# id: UplinkDoubleBladedESword +# category: Weapons +# itemId: DoubleBladedESword +# price: 16 + +# bug swept to make +#- type: uplinkListing +# id: UplinkEnergyDagger +# category: Weapons +# itemId: EnergyDagger +# price: 2 + +# Explosives + +- type: uplinkListing + id: UplinkExplosiveGrenade + category: Explosives + itemId: ExGrenade + price: 4 + +- type: uplinkListing + id: UplinkExplosiveGrenadeFlash + category: Explosives + itemId: GrenadeFlashBang + price: 4 + +- type: uplinkListing + id: UplinkSyndieMiniBomb + category: Explosives + itemId: SyndieMiniBomb + price: 6 + +#- type: uplinkListing +# id: UplinkExplosiveC4 +# category: Weapons +# itemId: ExplosiveC4 +# price: 5 + +#- type: uplinkListing +# id: UplinkDuffelExplosiveC4 +# category: Weapons +# itemId: DuffelExplosiveC4 +# price: 15 + +# Ammo - type: uplinkListing id: UplinkPistol9mmMagazine category: Ammo itemId: magazine_9mm + price: 2 + +# For the Mandella +- type: uplinkListing + id: UplinkMagazineClRiflePistol + category: Ammo + itemId: MagazineClRiflePistol + price: 2 + +# For the Inspector +- type: uplinkListing + id: UplinkSLMagnum + category: Ammo + itemId: SLMagnum + price: 2 + +# Bundles + +- type: uplinkListing + id: UplinkC20RBundle + category: Bundles + itemId: ClothingBackpackDuffelSyndicateFilledSMG + price: 14 + +- type: uplinkListing + id: UplinkBojevicBundle + category: Bundles + itemId: ClothingBackpackDuffelSyndicateFilledShotgun + price: 13 + +- type: uplinkListing + id: UplinkL6SawBundle + category: Bundles + itemId: ClothingBackpackDuffelSyndicateFilledLMG + price: 18 + +- type: uplinkListing + id: UplinkGrenadeLauncherBundle + category: Bundles + itemId: ClothingBackpackDuffelSyndicateFilledGrenadeLauncher + price: 25 + +# Tools + +- type: uplinkListing + id: UplinkToolbox + category: Tools + itemId: ToolboxSyndicateFilled price: 5 +- type: uplinkListing + id: UplinkSyndicateJawsOfLife + category: Tools + itemId: SyndicateJawsOfLife + price: 2 + +- type: uplinkListing + id: UplinkDuffelSurgery + category: Tools + itemId: ClothingBackpackDuffelSyndicateFilledMedical + price: 5 + +- type: uplinkListing + id: UplinkCarpDehydrated + category: Tools + itemId: DehydratedSpaceCarp + price: 5 + +# Armor + +# Should be cameleon shoes, change when implemented. +- type: uplinkListing + id: UplinkClothingNoSlipsShoes + category: Armor + itemId: ClothingShoesChameleonNoSlips + price: 2 + +- type: uplinkListing + id: UplinkClothingOuterVestWeb + category: Armor + itemId: ClothingOuterVestWeb + price: 5 + +- type: uplinkListing + id: UplinkHardsuitSyndie + category: Armor + itemId: ClothingOuterHardsuitSyndie + price: 5 + +- type: uplinkListing + id: UplinkHardsuitSyndieHelmet + category: Armor + itemId: ClothingHeadHelmetHardsuitSyndie + price: 5 + +# Misc + +- type: uplinkListing + id: UplinkBalloon + category: Misc + itemId: BalloonSyn + price: 20 + +- type: uplinkListing + id: UplinkDecoyDisk + category: Misc + itemId: NukeDiskFake + price: 1 + +- type: uplinkListing + id: UplinkRevolverCapGun + category: Misc + itemId: RevolverCapGun + price: 4 + - type: uplinkListing id: UplinkPen - category: Utility + category: Misc itemId: Pen price: 2 + +- type: uplinkListing + id: UplinkSoapSyndie + category: Misc + itemId: SoapSyndie + price: 1 + +- type: uplinkListing + id: UplinkUltrabrightLantern + category: Misc + itemId: lanternextrabright + price: 2 + +#- type: uplinkListing +# id: UplinkTelecrystal +# category: Misc +# itemId: Telecrystal +# price: 1 + +# Pointless + +- type: uplinkListing + id: UplinkCostumeCentcom + category: Pointless + itemId: ClothingBackpackDuffelSyndicateCostumeCentcom + price: 4 + +- type: uplinkListing + id: UplinkCostumeClown + category: Pointless + itemId: ClothingBackpackDuffelSyndicateCostumeClown + price: 4 diff --git a/Resources/Prototypes/Entities/Clothing/Hands/gloves.yml b/Resources/Prototypes/Entities/Clothing/Hands/gloves.yml index 34489d77ae..af8bdb86c9 100644 --- a/Resources/Prototypes/Entities/Clothing/Hands/gloves.yml +++ b/Resources/Prototypes/Entities/Clothing/Hands/gloves.yml @@ -125,3 +125,14 @@ sprite: Clothing/Hands/Gloves/spaceninja.rsi - type: Clothing sprite: Clothing/Hands/Gloves/spaceninja.rsi + +- type: entity + parent: ClothingHandsBase + id: ClothingHandsGlovesCombat + name: combat gloves + description: These tactical gloves are fireproof and shock resistant. + components: + - type: Sprite + sprite: Clothing/Hands/Gloves/Color/black.rsi + - type: Clothing + sprite: Clothing/Hands/Gloves/Color/black.rsi diff --git a/Resources/Prototypes/Entities/Clothing/Shoes/specific.yml b/Resources/Prototypes/Entities/Clothing/Shoes/specific.yml index 37e5bb9aa0..5ad0b459a6 100644 --- a/Resources/Prototypes/Entities/Clothing/Shoes/specific.yml +++ b/Resources/Prototypes/Entities/Clothing/Shoes/specific.yml @@ -79,3 +79,13 @@ sprite: Clothing/Shoes/Specific/wizard.rsi - type: Clothing sprite: Clothing/Shoes/Specific/wizard.rsi + +- type: entity + parent: ClothingShoesColorBlack + id: ClothingShoesChameleonNoSlips + name: no-slip shoes + #name: no-slip chameleon shoes + #description: These shoes have an action button to change shape, but unlike the chameleon shoes from the kit they also protect you from slips. + description: These protect you from slips while looking like normal sneakers. + components: + - type: NoSlip diff --git a/Resources/Prototypes/Entities/Clothing/Uniforms/jumpsuits.yml b/Resources/Prototypes/Entities/Clothing/Uniforms/jumpsuits.yml index 740398223d..9d7a21edee 100644 --- a/Resources/Prototypes/Entities/Clothing/Uniforms/jumpsuits.yml +++ b/Resources/Prototypes/Entities/Clothing/Uniforms/jumpsuits.yml @@ -1,3 +1,14 @@ +- type: entity + parent: ClothingUniformBase + id: ClothingUniformJumpsuitAncient + name: ancient jumpsuit + description: A terribly ragged and frayed grey jumpsuit. It looks like it hasn't been washed in over a decade. + components: + - type: Sprite + sprite: Clothing/Uniforms/Jumpsuit/ancient.rsi + - type: Clothing + sprite: Clothing/Uniforms/Jumpsuit/ancient.rsi + - type: entity parent: ClothingUniformBase id: ClothingUniformJumpsuitBartender @@ -74,6 +85,28 @@ - type: Clothing sprite: Clothing/Uniforms/Jumpsuit/chaplain.rsi +- type: entity + parent: ClothingUniformBase + id: ClothingUniformJumpsuitCentcomOfficial + name: centcom official's jumpsuit + description: It's a jumpsuit worn by CentCom's officials. + components: + - type: Sprite + sprite: Clothing/Uniforms/Jumpsuit/centcom_official.rsi + - type: Clothing + sprite: Clothing/Uniforms/Jumpsuit/centcom_official.rsi + +- type: entity + parent: ClothingUniformBase + id: ClothingUniformJumpsuitCentcomOfficer + name: centcom officer's jumpsuit + description: It's a jumpsuit worn by CentCom Officers. + components: + - type: Sprite + sprite: Clothing/Uniforms/Jumpsuit/centcom_officer.rsi + - type: Clothing + sprite: Clothing/Uniforms/Jumpsuit/centcom_officer.rsi + - type: entity parent: ClothingUniformBase id: ClothingUniformJumpsuitChef diff --git a/Resources/Prototypes/Entities/Objects/Consumable/food.yml b/Resources/Prototypes/Entities/Objects/Consumable/food.yml index 84197458e6..0d5a0f08e2 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/food.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/food.yml @@ -1763,25 +1763,6 @@ sprite: Objects/Consumable/Food/hburger.rsi - type: Grindable -- type: entity - parent: FoodBase - id: FoodMonkeyCube - name: monkey cube - description: Just add water! - components: - - type: SolutionContainer - contents: - reagents: - - ReagentId: chem.Nutriment - Quantity: 10 - maxVol: 11 # needs room for water - caps: AddTo, RemoveFrom, FitsInDispenser - - type: Sprite - sprite: Objects/Consumable/Food/monkeycube.rsi - - type: Rehydratable - target: MonkeyMob_Content - - type: Grindable - - type: entity parent: FoodBase id: FoodMonkeysDelight @@ -2997,4 +2978,3 @@ sprite: Objects/Consumable/Food/memoryleek.rsi state: memoryLeek - type: Grindable - diff --git a/Resources/Prototypes/Entities/Objects/Devices/pda.yml b/Resources/Prototypes/Entities/Objects/Devices/pda.yml index d4fe1f426f..f39b7d6e0d 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/pda.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/pda.yml @@ -350,3 +350,12 @@ state: pda-security - type: Icon state: pda-security + +- type: entity + name: Centcom PDA + parent: AssistantPDA + id: CentcomPDA + description: Colored the numbing grey of bureaucracy. + components: + - type: PDA + idCard: CentcomIDCardSyndie diff --git a/Resources/Prototypes/Entities/Objects/Misc/dat_fukken_disk.yml b/Resources/Prototypes/Entities/Objects/Misc/dat_fukken_disk.yml new file mode 100644 index 0000000000..c1107f0d7f --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Misc/dat_fukken_disk.yml @@ -0,0 +1,19 @@ +- type: entity + name: nuclear authentication disk + parent: BaseItem + id: NukeDisk + description: GET DAT FUCKKEN DISK + components: + - type: Sprite + netsync: false + sprite: Objects/Misc/nukedisk.rsi + state: icon + - type: Item + size: 12 + sprite: Objects/Misc/nukedisk.rsi + state: icon + +- type: entity + parent: NukeDisk + id: NukeDiskFake + description: GET DAT FUCK- wait a second... diff --git a/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml b/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml index 2ea4423887..91916f84af 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/identification_cards.yml @@ -320,3 +320,19 @@ - Kitchen - Janitor - Theatre + +- type: entity + parent: IDCardStandard + id: CentcomIDCardSyndie + name: Centcom ID card + components: + - type: Sprite + layers: + - state: centcom + - type: Clothing + HeldPrefix: blue + - type: IdCard + jobTitle: Central Commander + - type: Access + tags: + - Maintenance diff --git a/Resources/Prototypes/Entities/Objects/Specific/rehydrateable.yml b/Resources/Prototypes/Entities/Objects/Specific/rehydrateable.yml new file mode 100644 index 0000000000..8039c156e5 --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Specific/rehydrateable.yml @@ -0,0 +1,34 @@ +- type: entity + parent: FoodBase + id: MonkeyCube + name: monkey cube + description: Just add water! + components: + - type: SolutionContainer + contents: + reagents: + - ReagentId: chem.Nutriment + Quantity: 10 + maxVol: 11 # needs room for water + caps: AddTo, RemoveFrom, FitsInDispenser + - type: Sprite + sprite: Objects/Consumable/Food/monkeycube.rsi + - type: Rehydratable + target: MonkeyMob_Content + - type: Grindable + +- type: entity + parent: PlushieCarp + id: DehydratedSpaceCarp + name: dehydrated space carp + description: Looks like a plush toy carp, but just add water and it becomes a real-life space carp! + components: + - type: SolutionContainer + contents: + reagents: + - ReagentId: chem.Nutriment + Quantity: 10 + maxVol: 11 # needs room for water + caps: AddTo, RemoveFrom, FitsInDispenser + - type: Rehydratable + target: CarpMob_Content diff --git a/Resources/Prototypes/Entities/Objects/Tools/jaws-of-life.yml b/Resources/Prototypes/Entities/Objects/Tools/jaws-of-life.yml new file mode 100644 index 0000000000..eaf81c2e3f --- /dev/null +++ b/Resources/Prototypes/Entities/Objects/Tools/jaws-of-life.yml @@ -0,0 +1,41 @@ +- type: entity + name: jaws of life + parent: BaseItem + id: JawsOfLife + description: A set of jaws of life, compressed through the magic of science. + components: + - type: Sprite + sprite: Objects/Tools/jaws_of_life.rsi + state: jaws_pry + - type: Item + sprite: Objects/Tools/jaws_of_life.rsi + - type: TilePrying + - type: Tool + qualities: + - Prying + statusShowBehavior: true + - type: MultiTool + tools: + - behavior: Prying + state: jaws_pry + useSound: /Audio/Items/jaws_pry.ogg + changeSound: /Audio/Items/change_jaws.ogg + - behavior: Cutting + state: jaws_cutter + useSound: /Audio/Items/jaws_cut.ogg + changeSound: /Audio/Items/change_jaws.ogg + +- type: entity + name: syndicate jaws of life + parent: JawsOfLife + id: SyndicateJawsOfLife + description: Useful for entering the station or its departments. + components: + - type: Sprite + state: syn_jaws_pry + - type: MultiTool + tools: + - behavior: Prying + state: syn_jaws_pry + - behavior: Cutting + state: syn_jaws_cutter diff --git a/Resources/Prototypes/Entities/Objects/Tools/lantern.yml b/Resources/Prototypes/Entities/Objects/Tools/lantern.yml index a8f62030fd..e50fc08d74 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/lantern.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/lantern.yml @@ -27,3 +27,16 @@ - type: Appearance visuals: - type: LanternVisualizer + +- type: entity + name: extra-bright lantern + parent: lantern + id: lanternextrabright + description: Blinding. + components: + - type: PointLight + enabled: false + radius: 5 + energy: 10 + color: "#FFC458" + - type: LoopingSound diff --git a/Resources/Prototypes/Entities/Objects/Tools/toolbox.yml b/Resources/Prototypes/Entities/Objects/Tools/toolbox.yml index b310ee431a..282b5d590f 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/toolbox.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/toolbox.yml @@ -9,6 +9,7 @@ size: 9999 - type: ItemCooldown - type: MeleeWeapon + damage: 10 hitSound: "/Audio/Weapons/smash.ogg" - type: entity @@ -98,7 +99,7 @@ sprite: Objects/Tools/Toolboxes/toolbox_green.rsi - type: entity - name: syndicate toolbox + name: suspicious toolbox parent: ToolboxBase id: ToolboxSyndicate description: A sinister looking toolbox filled with elite syndicate tools. @@ -108,6 +109,24 @@ state: icon - type: Item sprite: Objects/Tools/Toolboxes/toolbox_syn.rsi + - type: MeleeWeapon + damage: 15 + +- type: entity + id: ToolboxSyndicateFilled + name: suspicious toolbox + suffix: Filled + parent: ToolboxSyndicate + components: + - type: StorageFill + contents: + - name: Screwdriver + - name: Wrench + - name: Welder + - name: Crowbar + - name: Multitool + - name: Wirecutter + - name: ClothingHandsGlovesCombat - type: entity name: golden toolbox diff --git a/Resources/Prototypes/Entities/Objects/Tools/tools.yml b/Resources/Prototypes/Entities/Objects/Tools/tools.yml index cafa7ee90f..b9fdc3a66f 100644 --- a/Resources/Prototypes/Entities/Objects/Tools/tools.yml +++ b/Resources/Prototypes/Entities/Objects/Tools/tools.yml @@ -133,33 +133,6 @@ - Multitool - type: SignalLinker -- type: entity - name: jaws of life - parent: BaseItem - id: JawsOfLife - description: A set of jaws of life, compressed through the magic of science. - components: - - type: Sprite - sprite: Objects/Tools/jaws_of_life.rsi - state: jaws_pry - - type: Item - sprite: Objects/Tools/jaws_of_life.rsi - - type: TilePrying - - type: Tool - qualities: - - Prying - statusShowBehavior: true - - type: MultiTool - tools: - - behavior: Prying - state: jaws_pry - useSound: /Audio/Items/jaws_pry.ogg - changeSound: /Audio/Items/change_jaws.ogg - - behavior: Cutting - state: jaws_cutter - useSound: /Audio/Items/jaws_cut.ogg - changeSound: /Audio/Items/change_jaws.ogg - - type: entity name: power drill parent: BaseItem diff --git a/Resources/Textures/Clothing/Back/Duffels/syndicate.rsi/icon-ammo.png b/Resources/Textures/Clothing/Back/Duffels/syndicate.rsi/icon-ammo.png new file mode 100644 index 0000000000000000000000000000000000000000..8f16dfb3528e01fed8556356c86acef9f404c2d4 GIT binary patch literal 294 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyHUT~%t_Kbr;OFNT5)!IsWGrW7 zR8&;7WnfTOSHFLm;o>odBfA(RBqT&cM9!W)tEHtipMhZt14BClgOih!kB?9GEdC0h zIgBMie!&b5&u*jvIWs(6978O6-%dC!bXbAIRhMfE@51%}|6gA;Niy|P&gPeeidE;G z^1bT)9$vCMaXgoep{TLfs!fK`P~1gDDM$H?rE zYHZLsP^GbfJFEY~{X@SmU*Dy@#k{19<$tSi{ltiEa#mZ}IS<`PS?TN7B)PHXp$Lzp qjCIQ$o^^f6?K5^iezWxXN7k~p>_uKz&MX1Ck-^i|&t;ucLK6VGL2R!8 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Back/Duffels/syndicate.rsi/icon-med.png b/Resources/Textures/Clothing/Back/Duffels/syndicate.rsi/icon-med.png new file mode 100644 index 0000000000000000000000000000000000000000..210878cb81d512761ea5beb03befa16864fa85b2 GIT binary patch literal 289 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy#sNMdt_Kbr;OFNT5)!IsWGrW7 zR8&;7WnfTOSO4XIn}|7;GeE}qZn(O z@D>}V^{wBR_a|#^F)tBo`g`cZeh!^=~aQgFKP)fv*a%t&3^o$1Es|23E7GJ%;F_~cs?;gcL`WkD{(uSr zHIPR9*TN_&o@f+NFMN}G%j~+@+nK$;nE7DYnYo$y-h1=r&D`vefq{X6fq{X6!GDS; zUTViDe%kUA@ehe`I4sgHem%F^ek%Qv!296ffW|^EJ^KuTw+FEVHy<1vw0fGHoV3!f z!{avo&{(}EW07BZpnPj~jk*5zQxXlZG&tj_hgT~IjrkB^Tj6bgy5va&Mq zMjqul{GO}8-rk;g1Umn`c)s%};9XT!CCYgO+}i2Dt)IKQJJ+7%a$CC~2AJr4_aKs= zoSZzU=PYw;rvtZsii?Ydp&J_;MgHpQN+?@cSm?_Ckv@7d``!oS3oz1WXJ_I8?(gr# zyP&{VJP&4oqoX65o}LzI1iazlVX@|-+(IaGmReq3rmn6o5qz-%$?y95dRkv!CwivV zr;-7nv>X6AAaYr%Why9odV0jZV_;xF^n}<0gK(agX%#3>0eQy<1IYPI8vxkZ*`e<4 zZjnX+uBfOG>6Migt^TxP055s6!m=SUiPF+inw_1sRw4W+z%qy_paZ?gkyIXQZZ<|; z2BsS;%m4h4ckWI6LfZh31^>MPlw*LK%VXP_uC1>QzgKxGC>h|v7PHg6EK|UKpZEL% zVfQi>C>@FYiwJxm^4MVvkOwm46vhB~AVW@J43Gyh+fAd`*}lnlVi_xAQ$4->~?v8)&Y z9N_YjMWsJw4*(IcySqzMQ&Sf4=;$aN9v-T8rwnj_ii!6} zMbw2$uCA_T+yJ-_AkTMM7I}&G3uO%333{nlD4)s>ged8>gsA*SXfZ)P8r|;7dXK!Z@zSP zg32F8UVR%+aInJ{S)PweOH1^oF_N)+!ZM(=ydmSDjQH^WX-w&^u(Ah$07SV`9sn0O zDH(hri<|O(p!IJMyD`S~^>x-hjLHBfxZPw@L7-b=5a9CiGN>-vNC$VI0}%+YxVT7( zMD~vczzOc4MhIj8zN#v_Vz$7XEQ2lr-4U9bn-l*7bb?P%fD_!1A=~$q3=AF%i0C(I W0L@Y0YF~)}0000jyIPerDb`Z{9ql2@@tvxO&{E5>N!6H908W%H?t?=8s?UDqYUFeph9nmyf@{6U5ucKBVK05_EY(_wQNj^k9PW-5 zOa~D_P`LoPAX࿖}pijWD&@~;pespH83WgL@g{ xUES9EBLcM+OUE|brW=Amzhqr~JYnt^2XV<-9Q$yAs+Q962 zWp&osRa!o*9D!o%r>>4MSnD8E8o!gLTmMd&UU`G@M(u`9qpWv#S9U1&tDJiA^wHCf zl?Po$2b(c;U_M$sf{OCaUUrf6z)W;WU&vBFM`i=4Q5AmCKJ4 P=phDAS3j3^P6fp8`RJ`d~#Oh!pZ< z>PsLBf)uT_R1|ZeFO}3o?vyBLqckb?(j)(DljiSTR(^9go4w2Bc4ziq$q&*RoXNHxBqHaE4)X8 za!bqK4B^Y(5OUd9bEZtIKiv2}YP9cQhBlO@{6P9VD}yIH?&kt5X#S(LUi+GQfa657 zRB_~GIsa-y51zVm5K`wQ2L=E8{!4gv;yt;1>HPPQ`Xi?G1YcLHB(?6v#GxKET->nZ znwi4d!*z0+mpekkxYrwUs0OG-fb8Ho6eL>wKsbi2%FPgg2cHYi;v!ZmD|41{5lkBb z6wuPGsGMd&X9Z8?Oc)EGfSfn~&f74R(|ID~6@acjU1d3_a4dh*>2lsXSbYQVtIvZ< zj!nUJdlH_+T1KOkrhF<#S}dwZ_0_Cv?g6|zD|>+wo^R&ZC!9B~vm+nVcN1}}I9)8y zvCYShlwO~i%Q%nMQ*A$A;pzSe0{szTr@y5-{SoArN;~iLhSy)no^)7a;-m zjaFdC9WUzZ>v8hrr62e^v2hO4^gLDv!VYq5<;;*}uf>rLo@{Vm4vp8~hqs?$WozdK zWncLDraunz;MXHjd{=dorN3$mGjT9JD;$t8=64&G%(Pj*j%VsX$)DRm26ynhO&A7qL_5>w6JXQ&XGD z{uJCI6rKbAc-qBoLrTV)1Na#)z+E#a+MF=%ni{FgyC3( zA)92|=mjt&fcv2;c9fRIW?nPkHn|Ua(KiWp2PNgWS3Z9i68jH00005===54p(=MAS%G4K!C#6AovM&csPTG0;&jHuOz)R z*9vmUv1Il>+Dj;z1zh(@F1xcc*_oZWorOlDnR*OP0z^Ds%&mx3GcV_z%fnQ^cycYr zmvD&FkG9;CwK0GhZUxBsrddD^25JXI*tRX#X(XA}Nl$kFURAl{aaG{;Me936p{tbDptd!1@Pd zq;EZJ_e)rCO<0zN`tCWr`W?#U9bC1K(Cv2Nx*_gMeHH)wR&4ICiO;19P|S@K^LgNX zIFkK91{&TxvwuQ%22%F6q8T+CKfZQJlcF_6lpZ6Qg+iQxN+HUIA4Cm_$}|Y%>7no# fX*3$mlmp-kj8=qNn0$I|00000NkvXXu0mjfV$8rL literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Uniforms/Jumpsuit/centcom_officer.rsi/inhand-left.png b/Resources/Textures/Clothing/Uniforms/Jumpsuit/centcom_officer.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..5456486c2589acec3dd4dc1e6ac4ad79c3ef5a13 GIT binary patch literal 284 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0J3?w7mbKU|etpJ}8R}k$jViYBAW@cuaFY8*X z7&28WY=(B^9G%n?R#{nDO-)UGeSIfRoCuS790gR(SQ6wH%;50sMjDW_z|+Ms#N+te z$+lcA1_EyG0y#%#--tTfm3^W%=Th!NK^M;tD%|&cKTP*b+ZNls=auXJ39lGklx8VNU&9Y4gTW%IetWcE6xGmXz<;8(B*Az^DwUll9*mG&u%N@(^bi8@+ z=gy|)B~km9rk5;`{`;vXXwU0A+dZCiuKj#xt#|Y4QpSY^>q=j8g2+OHe=;1c#cRE7 cR(%kaeqg-#;!YP8pj#O{UHx3vIVCg!0K;Z?^#A|> literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Uniforms/Jumpsuit/centcom_officer.rsi/inhand-right.png b/Resources/Textures/Clothing/Uniforms/Jumpsuit/centcom_officer.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..23855a8759e370493aafc27569cb8e04fc93a7cb GIT binary patch literal 321 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0J3?w7mbKU|etpJ}8R}k$jViYBAW@cuaFY8*X z7&28WY=(B^9G%n?R#{nDO-)UGeSIfRoCuS790gR(SQ6wH%;50sMjDWF)YHW=#N&8! zf&}a0hIa=V8}Bj(Uy)T|WYgj0(b1Loq@cJ$<8%qzcg-1G%d9szyV|Bt3psaW1GDFq z%|++Vc=@n$1d5%HG>$b`>mXD*-;}po|4y23d4usr?S@XHsJC}hI~4m>PQ7^f=w-)B z2G5WaS3ManbG=!#I6>qB`vwDpDGx#)FuL&l5UCK`5b`MafKlv=Tx%17(f~@-ieco1E{ta?c6q OAqG!ZKbLh*2~7awGIwqO literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Uniforms/Jumpsuit/centcom_officer.rsi/meta.json b/Resources/Textures/Clothing/Uniforms/Jumpsuit/centcom_officer.rsi/meta.json new file mode 100644 index 0000000000..d01e147030 --- /dev/null +++ b/Resources/Textures/Clothing/Uniforms/Jumpsuit/centcom_officer.rsi/meta.json @@ -0,0 +1,27 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c838ba21dae97db345e0113f99596decd1d66039", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon", + "directions": 1 + }, + { + "name": "equipped-INNERCLOTHING", + "directions": 4 + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Clothing/Uniforms/Jumpsuit/centcom_official.rsi/equipped-INNERCLOTHING.png b/Resources/Textures/Clothing/Uniforms/Jumpsuit/centcom_official.rsi/equipped-INNERCLOTHING.png new file mode 100644 index 0000000000000000000000000000000000000000..aef08cee2cd2ed35099643ea18ab461e0862fa50 GIT binary patch literal 717 zcmV;;0y6!HP)YCm3;=oN8u#?^89V?00j5brK~z|U?UvhagD?<8y-sZG5}FIXkO2Mv&+KBF zL~5Ajr4OmZC>9TAJ&f@xwo;omy_-mvhbG8(`~7|=aAT{gvIbPFap%2vwzB29$hGnQ z!+WCvpH$nrJYOqj?hhVtE^rl-GTfp;;Rk^`(vA5vjVAY6apwl`sX#pvs6_+yNU*>a znMOSlsK)&M(06VCFM1|e)-wUnGXdsC;OcndUeRg%=jCSp-6H9Dn)8#VL00000NkvXXu0mjf5+5$y literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Uniforms/Jumpsuit/centcom_official.rsi/icon.png b/Resources/Textures/Clothing/Uniforms/Jumpsuit/centcom_official.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..9fcf7ace5a2268473e36d2f1e3f50a1019e49e4f GIT binary patch literal 273 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyP60k4uKyVrbo05bCi1qnw%SbP zUA1bJlFzvFLp}VK-l^f`Ci8*u!58J2n3NU(Y2b(zY_k z_T;9cb9fjh_Nxb&9$V4$^fF6!PP9vbU*f`Zy{vzU-#v$Q9>-rg^Zc_B5}Z(c&1!+uU*|2&9Fx2p-86OnR~%(se}mP- Ua0dTNphFluUHx3vIVCg!0Hm>GssI20 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Uniforms/Jumpsuit/centcom_official.rsi/inhand-left.png b/Resources/Textures/Clothing/Uniforms/Jumpsuit/centcom_official.rsi/inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..942a5247abd17f910f0f5e933936d1c09fcfc9e4 GIT binary patch literal 416 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0J3?w7mbKU|e-2k5uS0G(bz`)SP@clajLmUIc zHimWU7^0)29UUDdBqV}^gF8Ap7_1l=JQ)~r7$mQ8@&Yw5mIV0)GdMiEkp|@CRE0#8 zxTF>*7iAWdWaj5FFjUM54l5`s{r)Am;N#aPTHd-^=gyoD-VkbV(fGk5o%24LCmD)* zdUseD2N_>B_EMPhXws2MAqv5os^4^2yh370Z@2MU4MTI$BW6#6!V10? zGfML?R4teKyIF+q9MImCo-U3d9-YYv60D088X5$cn;BYE4;)Zw&^(`U=s*HTqNKqF zi6pHA&Y}da#!V7)oD4*Fv@KiGX0>2bfar?0_EjLp+5%(qV#nl#l7fuJ;s>1=9cuYr z=%gI5NdDT@nV}?0QdI*0A2t9wg9fK09#vIK|w(n7#LGiQ;3L&06G8wNdN$B02$T^4FCWD0d!JM zQvg8b*k%9#0Bm|xSad{Xb7OL8aCB*JZU6vyoKseCa&`CgQ*iP1YCm3;=qk8vU~r4$c4o0L@86K~zYIV_+Bsqk!%}fPqN>Q&b2f0S1f) z3@nBi@{A@73{X*)AO@!p3 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Clothing/Uniforms/Jumpsuit/centcom_official.rsi/meta.json b/Resources/Textures/Clothing/Uniforms/Jumpsuit/centcom_official.rsi/meta.json new file mode 100644 index 0000000000..d01e147030 --- /dev/null +++ b/Resources/Textures/Clothing/Uniforms/Jumpsuit/centcom_official.rsi/meta.json @@ -0,0 +1,27 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c838ba21dae97db345e0113f99596decd1d66039", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon", + "directions": 1 + }, + { + "name": "equipped-INNERCLOTHING", + "directions": 4 + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + } + ] +} diff --git a/Resources/Textures/Objects/Misc/id_cards.rsi/blue-inhand-left.png b/Resources/Textures/Objects/Misc/id_cards.rsi/blue-inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..9adcd4b6a3c02f8ac0b92c94b19bf4054a69e1f9 GIT binary patch literal 256 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=$30yfLn`LHy|t0I*@34uG5*vW z2jNp1xoHXfUTLRTbP9|o%rcTxe(TzIgvG`^;@5t*i#9*!m6+TB>IH!}W<1Wp+g6<8 z7B$TYdFLtl%z544jJqb<$@Mnoi&!EVZ$Gque>8q}R>b+2%XU`gxo~b`%3AyMSJjQ5 zMdtPE{zml8**!6iQT|+e&9vDiCsy1MsQa(Hk1=p3#B?BeLgnhehFkXzd)N2aSW-L^Y)fu-ys8m*2LLG z{Ei!^WJI5v@THnLs&BKd`GWJZ)2viQWSXvJaCs}NeKN7ogTe~DWM4fzs`^A literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Misc/id_cards.rsi/meta.json b/Resources/Textures/Objects/Misc/id_cards.rsi/meta.json index a097ce4dbd..0fc51bd2b7 100644 --- a/Resources/Textures/Objects/Misc/id_cards.rsi/meta.json +++ b/Resources/Textures/Objects/Misc/id_cards.rsi/meta.json @@ -242,6 +242,22 @@ { "name": "silver-inhand-right", "directions": 4 + }, + { + "name": "orange-inhand-left", + "directions": 4 + }, + { + "name": "orange-inhand-right", + "directions": 4 + }, + { + "name": "blue-inhand-left", + "directions": 4 + }, + { + "name": "blue-inhand-right", + "directions": 4 } ] } diff --git a/Resources/Textures/Objects/Misc/id_cards.rsi/orange-inhand-left.png b/Resources/Textures/Objects/Misc/id_cards.rsi/orange-inhand-left.png new file mode 100644 index 0000000000000000000000000000000000000000..5937b9cd210ed553f914c758cacc0e35c3a32b01 GIT binary patch literal 283 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0L3?#3!&-4XSJOMr-u0Yzu!{cVH!!ZVRrvj-@ zKt5whkY6x^!?PP{Ku%s&NJNQCYH@N=WKhlO#F@nvH#g*lHV9hnrO5Ujah!%*Kg)ZEy$v)fp8 z^9qS26T6MqY8aY}9x;0o6jt!Hm{FRSVY9n*%Tld?M?jmMJzX3_EP9g@Bv?ZjnF^S= zWE@zyo6g^0P_h(c%JFwdnaAvOltnD^&r9Atdi*h^u~qe(|5g(w7T?$(=#l>UH a1~kO4gk_z>m$_?!Oa@O^KbLh*2~7Y>Q((IQ literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Misc/nukedisk.rsi/icon.png b/Resources/Textures/Objects/Misc/nukedisk.rsi/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1ef83e9abb0681830b298e14ffded29c54db34bb GIT binary patch literal 353 zcmV-n0iOPeP)V=-0C=2JR&a84_w-Y6@%7{?OD!tS%+FJ>RWQ*r;NmRL zOex6#a*U0*I5Sc+(=$pSoZ^zil2jm5DX%m+CpEDsC9^nNiHkEOv#1y-YRJWzR+N~V z3St8_rljU1R)U0e47rpQT>V_YHUR*X)gR9P5HIln003c0L_t(IjbmUK1=ItKf=WtC zg1Gq%jK(TqLB;|&`9vuQMN<%ps=yp*XR!cIK2V@@U1#t350et`f&t)WY(`DjE00000NkvXXu0mjflG%m} literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Misc/nukedisk.rsi/meta.json b/Resources/Textures/Objects/Misc/nukedisk.rsi/meta.json new file mode 100644 index 0000000000..81c0661e3c --- /dev/null +++ b/Resources/Textures/Objects/Misc/nukedisk.rsi/meta.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/a7215663648f4289d2446a1c82aec1c9a406310c", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon", + "directions": 1, + "delays": [ + [ + 0.1, + 0.1 + ] + ] + } + ] +} diff --git a/Resources/Textures/Objects/Tools/jaws_of_life.rsi/meta.json b/Resources/Textures/Objects/Tools/jaws_of_life.rsi/meta.json index 2ab00fd169..6f0fd01ae1 100644 --- a/Resources/Textures/Objects/Tools/jaws_of_life.rsi/meta.json +++ b/Resources/Textures/Objects/Tools/jaws_of_life.rsi/meta.json @@ -1 +1,83 @@ -{"version": 1, "size": {"x": 32, "y": 32}, "license": "CC BY-SA 3.0", "copyright": "Taken from https://github.com/tgstation/tgstation at commit ea59fb4b810decbb5996b36d8876614b57c3d189", "states": [{"name": "jaws_cutter", "directions": 1, "delays": [[1.0]]}, {"name": "jaws_pry", "directions": 1, "delays": [[1.0]]}, {"name": "inhand-left", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}, {"name": "inhand-right", "directions": 4, "delays": [[1.0], [1.0], [1.0], [1.0]]}]} \ No newline at end of file +{ + "version": 1, + "license": "CC BY-SA 3.0", + "copyright": "Taken from https://github.com/tgstation/tgstation at commit ea59fb4b810decbb5996b36d8876614b57c3d189", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "jaws_cutter", + "directions": 1, + "delays": [ + [ + 1 + ] + ] + }, + { + "name": "jaws_pry", + "directions": 1, + "delays": [ + [ + 1 + ] + ] + }, + { + "name": "syn_jaws_cutter", + "directions": 1, + "delays": [ + [ + 1 + ] + ] + }, + { + "name": "syn_jaws_pry", + "directions": 1, + "delays": [ + [ + 1 + ] + ] + }, + { + "name": "inhand-left", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + }, + { + "name": "inhand-right", + "directions": 4, + "delays": [ + [ + 1 + ], + [ + 1 + ], + [ + 1 + ], + [ + 1 + ] + ] + } + ] +} diff --git a/Resources/Textures/Objects/Tools/jaws_of_life.rsi/syn_jaws_cutter.png b/Resources/Textures/Objects/Tools/jaws_of_life.rsi/syn_jaws_cutter.png new file mode 100644 index 0000000000000000000000000000000000000000..973b1428b80485c15188bbd8931bfc44a4963cfe GIT binary patch literal 598 zcmV-c0;&CpP)q*$ zVOLmTS657eosS zJ_-sJ5)wo`Jg1tPdv0z+JUl!$HpfJKl>h($0d!JMQvg8b*k%9#0Ov_WK~y-6V_+Bs zLk%#30hq}I1*r1OK)}KRQo+Q^#?HaX#m$4Hf{~YxkB^^4K#+xzkx58cL{v;%LQ+Z^ zu7XiU76jzv6%>_}l$4brqRPrjj4%Z%s;a7LYHI50N*Wp(np)Z*K^Pw1EIdMnj+#w#IhGAYkvHq+|$H;0Odxj?OMFO0KT1 zZpQ9l1sxgs=rSe)(Yy00OHZb?Jy`6aWAK07*qoM6N<$g1p4w%K!iX literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Tools/jaws_of_life.rsi/syn_jaws_pry.png b/Resources/Textures/Objects/Tools/jaws_of_life.rsi/syn_jaws_pry.png new file mode 100644 index 0000000000000000000000000000000000000000..ed36af3d67b4b5bf494d31510bd3bfa2412beabe GIT binary patch literal 525 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy4+DHcTn`*LpeQTb-_TH;o}L^T zY0kjl?%?o0(ei(S<^Ndo|Iudu!;Jq28T|Lr`|qKprK*$|hU^v9UP$?!>C?b*+5uq%rypVxm1_MJs14AnVLp1|KhO~6Nq*R!= zxC=M89T%5!Vb^`2e#Vj@zhDN3XE)M-oLinQjv*Gk$q5py&HM&NMvtbaC8aU0PH1H+ z$rLj)Gn>E^R>tS2mnRozmm->wSyxxLKz9vOlhYxkMM;l@Cav-K1QOKD%*>RO>{!s# zV{*o~M`u%jg08x{`uYVNLLot66DK$CjuK_Mdd1Yl#N_AJEu|%2zwq*ynk>+g=uL27 z&S*8<&w0Zt*f=wjcZFcjGY3X)@61eYZEfxBI_V8e(bn44J4Ab)J^Lee$>GI=2M=C6 zdGqMivv&_)K5Y;w=;?VTcInbIF@^d=j9CYajG`hU9`I&66&jvlWVjkGULR|Bj0Y5E Mp00i_>zopr05k->cK`qY literal 0 HcmV?d00001 From c0a0547b390422c4548ac8a70f0c88d59def5c14 Mon Sep 17 00:00:00 2001 From: Vera Aguilera Puerto Date: Sun, 20 Dec 2020 01:00:48 +0100 Subject: [PATCH 16/29] Cleanup markers - Removes PhysicsComponent from all of them. - Makes most spawners/markers actually inherit MarkerBase --- .../Entities/Constructible/Power/arcade.yml | 1 + .../Markers/gamemode_conditional_spawners.yml | 13 +------------ .../Entities/Effects/Markers/marker_base.yml | 3 ++- .../Entities/Effects/Markers/spawn_points.yml | 13 +------------ .../Entities/Effects/Markers/toy_spawner.yml | 16 ++-------------- 5 files changed, 7 insertions(+), 39 deletions(-) diff --git a/Resources/Prototypes/Entities/Constructible/Power/arcade.yml b/Resources/Prototypes/Entities/Constructible/Power/arcade.yml index 59a771a9e9..f670343f7e 100644 --- a/Resources/Prototypes/Entities/Constructible/Power/arcade.yml +++ b/Resources/Prototypes/Entities/Constructible/Power/arcade.yml @@ -62,6 +62,7 @@ - type: entity id: RandomArcade name: Random Arcade Spawner + parent: MarkerBase components: - type: RandomArcade - type: Sprite diff --git a/Resources/Prototypes/Entities/Effects/Markers/gamemode_conditional_spawners.yml b/Resources/Prototypes/Entities/Effects/Markers/gamemode_conditional_spawners.yml index 68d1485e5f..71939a4229 100644 --- a/Resources/Prototypes/Entities/Effects/Markers/gamemode_conditional_spawners.yml +++ b/Resources/Prototypes/Entities/Effects/Markers/gamemode_conditional_spawners.yml @@ -1,21 +1,10 @@ - type: entity name: base conditional spawner id: BaseConditionalSpawner + parent: MarkerBase abstract: true components: - - type: Sprite - netsync: false - visible: false - sprite: Interface/Misc/markers.rsi - state: cross_blue - - - type: Marker - - type: Clickable - - type: InteractionOutline - - type: Physics - type: ConditionalSpawner - placement: - mode: AlignTileAny - type: entity name: Suspicion Rifle Spawner diff --git a/Resources/Prototypes/Entities/Effects/Markers/marker_base.yml b/Resources/Prototypes/Entities/Effects/Markers/marker_base.yml index 66c9fa0352..9ef628f01e 100644 --- a/Resources/Prototypes/Entities/Effects/Markers/marker_base.yml +++ b/Resources/Prototypes/Entities/Effects/Markers/marker_base.yml @@ -5,12 +5,13 @@ - type: Marker - type: Clickable - type: InteractionOutline - - type: Physics - type: Sprite netsync: false visible: false sprite: Interface/Misc/markers.rsi state: cross_blue + placement: + mode: AlignTileAny diff --git a/Resources/Prototypes/Entities/Effects/Markers/spawn_points.yml b/Resources/Prototypes/Entities/Effects/Markers/spawn_points.yml index 897cd496e7..3b1faefe13 100644 --- a/Resources/Prototypes/Entities/Effects/Markers/spawn_points.yml +++ b/Resources/Prototypes/Entities/Effects/Markers/spawn_points.yml @@ -1,21 +1,10 @@ - type: entity name: spawn point id: SpawnPoint + parent: MarkerBase abstract: true components: - - type: Sprite - netsync: false - visible: false - sprite: Interface/Misc/markers.rsi - state: cross_blue - - type: SpawnPoint - - type: Marker - - type: Clickable - - type: InteractionOutline - - type: Physics - placement: - mode: AlignTileAny - type: entity name: latejoin spawn point diff --git a/Resources/Prototypes/Entities/Effects/Markers/toy_spawner.yml b/Resources/Prototypes/Entities/Effects/Markers/toy_spawner.yml index 96e9b06f2a..cbd285d48e 100644 --- a/Resources/Prototypes/Entities/Effects/Markers/toy_spawner.yml +++ b/Resources/Prototypes/Entities/Effects/Markers/toy_spawner.yml @@ -1,17 +1,13 @@ - type: entity name: Toy Spawner id: ToySpawner + parent: MarkerBase components: - type: Sprite netsync: false visible: false sprite: Interface/Misc/markers.rsi state: spawner_toy - - - type: Marker - - type: Clickable - - type: InteractionOutline - - type: Physics - type: TrashSpawner rarePrototypes: - CarvingHelpMe @@ -32,23 +28,17 @@ - ToyMouse chance: 0.5 offset: 0.2 - placement: - mode: AlignTileAny - type: entity name: Figure Spawner id: FigureSpawner + parent: MarkerBase components: - type: Sprite netsync: false visible: false sprite: Interface/Misc/markers.rsi state: spawner_figure - - - type: Marker - - type: Clickable - - type: InteractionOutline - - type: Physics - type: TrashSpawner prototypes: - ToyAi @@ -72,5 +62,3 @@ - ToySkeleton chance: 0.5 offset: 0.2 - placement: - mode: AlignTileAny From c9e9d9f4dd896c0c8e144316148d56ab88c1e3c1 Mon Sep 17 00:00:00 2001 From: Vera Aguilera Puerto Date: Sun, 20 Dec 2020 01:43:29 +0100 Subject: [PATCH 17/29] Instruments have a property for enabling/disabling MIDI limits. - Added unlimited super synth that doesn't respect MIDI limits! Adminbuse it to your heart's content and blast your epic MIDIs, fellow badmins. --- .../Instruments/InstrumentComponent.cs | 7 +++- .../Instruments/InstrumentComponent.cs | 37 ++++++++++++------- .../Instruments/SharedInstrumentComponent.cs | 14 ++++++- .../Entities/Objects/Fun/instruments.yml | 12 ++++++ 4 files changed, 54 insertions(+), 16 deletions(-) diff --git a/Content.Client/GameObjects/Components/Instruments/InstrumentComponent.cs b/Content.Client/GameObjects/Components/Instruments/InstrumentComponent.cs index 3896718c1a..85d6119014 100644 --- a/Content.Client/GameObjects/Components/Instruments/InstrumentComponent.cs +++ b/Content.Client/GameObjects/Components/Instruments/InstrumentComponent.cs @@ -52,6 +52,8 @@ namespace Content.Client.GameObjects.Components.Instruments private bool _allowProgramChange; + private bool _respectMidiLimits; + /// /// A queue of MidiEvents to be sent to the server. /// @@ -239,6 +241,7 @@ namespace Content.Client.GameObjects.Components.Instruments serializer.DataField(ref _instrumentBank, "bank", (byte) 0); serializer.DataField(ref _allowPercussion, "allowPercussion", false); serializer.DataField(ref _allowProgramChange, "allowProgramChange", false); + serializer.DataField(ref _respectMidiLimits, "respectMidiLimits", true); } public override void HandleNetworkMessage(ComponentMessage message, INetChannel channel, ICommonSession? session = null) @@ -429,7 +432,9 @@ namespace Content.Client.GameObjects.Components.Instruments if (_midiEventBuffer.Count == 0) return; - var max = Math.Min(_instrumentSystem.MaxMidiEventsPerBatch, _instrumentSystem.MaxMidiEventsPerSecond - _sentWithinASec); + var max = _respectMidiLimits ? + Math.Min(_instrumentSystem.MaxMidiEventsPerBatch, _instrumentSystem.MaxMidiEventsPerSecond - _sentWithinASec) + : _midiEventBuffer.Count; if (max <= 0) { diff --git a/Content.Server/GameObjects/Components/Instruments/InstrumentComponent.cs b/Content.Server/GameObjects/Components/Instruments/InstrumentComponent.cs index 40269775d1..289ebcce79 100644 --- a/Content.Server/GameObjects/Components/Instruments/InstrumentComponent.cs +++ b/Content.Server/GameObjects/Components/Instruments/InstrumentComponent.cs @@ -78,8 +78,8 @@ namespace Content.Server.GameObjects.Components.Instruments private byte _instrumentBank; private bool _allowPercussion; private bool _allowProgramChange; + private bool _respectMidiLimits; - [ViewVariables(VVAccess.ReadWrite)] public override byte InstrumentProgram { get => _instrumentProgram; set { @@ -88,7 +88,6 @@ namespace Content.Server.GameObjects.Components.Instruments } } - [ViewVariables(VVAccess.ReadWrite)] public override byte InstrumentBank { get => _instrumentBank; set { @@ -97,7 +96,6 @@ namespace Content.Server.GameObjects.Components.Instruments } } - [ViewVariables(VVAccess.ReadWrite)] public override bool AllowPercussion { get => _allowPercussion; set { @@ -106,7 +104,6 @@ namespace Content.Server.GameObjects.Components.Instruments } } - [ViewVariables(VVAccess.ReadWrite)] public override bool AllowProgramChange { get => _allowProgramChange; set { @@ -115,6 +112,14 @@ namespace Content.Server.GameObjects.Components.Instruments } } + public override bool RespectMidiLimits { get => _respectMidiLimits; + set + { + _respectMidiLimits = value; + Dirty(); + } + } + /// /// Whether the instrument is an item which can be held or not. /// @@ -181,11 +186,12 @@ namespace Content.Server.GameObjects.Components.Instruments serializer.DataField(ref _instrumentBank, "bank", (byte) 0); serializer.DataField(ref _allowPercussion, "allowPercussion", false); serializer.DataField(ref _allowProgramChange, "allowProgramChange", false); + serializer.DataField(ref _respectMidiLimits, "respectMidiLimits", true); } public override ComponentState GetComponentState() { - return new InstrumentState(Playing, InstrumentProgram, InstrumentBank, AllowPercussion, AllowProgramChange, _lastSequencerTick); + return new InstrumentState(Playing, InstrumentProgram, InstrumentBank, AllowPercussion, AllowProgramChange, RespectMidiLimits, _lastSequencerTick); } public override void HandleNetworkMessage(ComponentMessage message, INetChannel channel, ICommonSession? session = null) @@ -217,14 +223,17 @@ namespace Content.Server.GameObjects.Components.Instruments _laggedBatches++; - if (_laggedBatches == (int) (maxMidiLaggedBatches * (1 / 3d) + 1)) + if (_respectMidiLimits) { - Owner.PopupMessage(InstrumentPlayer.AttachedEntity, - Loc.GetString("Your fingers are beginning to a cramp a little!")); - } else if (_laggedBatches == (int) (maxMidiLaggedBatches * (2 / 3d) + 1)) - { - Owner.PopupMessage(InstrumentPlayer.AttachedEntity, - Loc.GetString("Your fingers are seriously cramping up!")); + if (_laggedBatches == (int) (maxMidiLaggedBatches * (1 / 3d) + 1)) + { + Owner.PopupMessage(InstrumentPlayer.AttachedEntity, + Loc.GetString("Your fingers are beginning to a cramp a little!")); + } else if (_laggedBatches == (int) (maxMidiLaggedBatches * (2 / 3d) + 1)) + { + Owner.PopupMessage(InstrumentPlayer.AttachedEntity, + Loc.GetString("Your fingers are seriously cramping up!")); + } } if (_laggedBatches > maxMidiLaggedBatches) @@ -250,7 +259,7 @@ namespace Content.Server.GameObjects.Components.Instruments send = false; } - if (send) + if (send || !_respectMidiLimits) { SendNetworkMessage(midiEventMsg); } @@ -367,7 +376,7 @@ namespace Content.Server.GameObjects.Components.Instruments if ((_batchesDropped >= maxMidiBatchDropped || _laggedBatches >= maxMidiLaggedBatches) - && InstrumentPlayer != null) + && InstrumentPlayer != null && _respectMidiLimits) { var mob = InstrumentPlayer.AttachedEntity; diff --git a/Content.Shared/GameObjects/Components/Instruments/SharedInstrumentComponent.cs b/Content.Shared/GameObjects/Components/Instruments/SharedInstrumentComponent.cs index 17b7c5a6df..65f96d9103 100644 --- a/Content.Shared/GameObjects/Components/Instruments/SharedInstrumentComponent.cs +++ b/Content.Shared/GameObjects/Components/Instruments/SharedInstrumentComponent.cs @@ -11,11 +11,21 @@ namespace Content.Shared.GameObjects.Components.Instruments public override string Name => "Instrument"; public override uint? NetID => ContentNetIDs.INSTRUMENTS; + [ViewVariables(VVAccess.ReadWrite)] public virtual byte InstrumentProgram { get; set; } + + [ViewVariables(VVAccess.ReadWrite)] public virtual byte InstrumentBank { get; set; } + + [ViewVariables(VVAccess.ReadWrite)] public virtual bool AllowPercussion { get; set; } + + [ViewVariables(VVAccess.ReadWrite)] public virtual bool AllowProgramChange { get ; set; } + [ViewVariables(VVAccess.ReadWrite)] + public virtual bool RespectMidiLimits { get; set; } + public virtual void Update(float delta) { } @@ -61,14 +71,16 @@ namespace Content.Shared.GameObjects.Components.Instruments public byte InstrumentBank { get; } public bool AllowPercussion { get; } public bool AllowProgramChange { get; } + public bool RespectMidiLimits { get; } - public InstrumentState(bool playing, byte instrumentProgram, byte instrumentBank, bool allowPercussion, bool allowProgramChange, uint sequencerTick = 0) : base(ContentNetIDs.INSTRUMENTS) + public InstrumentState(bool playing, byte instrumentProgram, byte instrumentBank, bool allowPercussion, bool allowProgramChange, bool respectMidiLimits, uint sequencerTick = 0) : base(ContentNetIDs.INSTRUMENTS) { Playing = playing; InstrumentProgram = instrumentProgram; InstrumentBank = instrumentBank; AllowPercussion = allowPercussion; AllowProgramChange = allowProgramChange; + RespectMidiLimits = respectMidiLimits; } } diff --git a/Resources/Prototypes/Entities/Objects/Fun/instruments.yml b/Resources/Prototypes/Entities/Objects/Fun/instruments.yml index 6656842ab9..1ed3f2dce3 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/instruments.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/instruments.yml @@ -223,3 +223,15 @@ - type: Item size: 24 sprite: Objects/Fun/Instruments/h_synthesizer.rsi + +- type: entity + name: super synthesizer + suffix: no MIDI limits + description: Blasting the ghetto with Touhou MIDIs since 2020. + id: SuperSynthesizerUnlimitedInstrument + parent: SuperSynthesizerInstrument + components: + - type: Instrument + allowPercussion: true + allowProgramChange: true + respectMidiLimits: false From dc5f77f6c808707d4648ae94a150635217a15f02 Mon Sep 17 00:00:00 2001 From: Vera Aguilera Puerto Date: Sun, 20 Dec 2020 02:16:15 +0100 Subject: [PATCH 18/29] Remove unlimited synth prototype. Maybe it isn't the greatest of ideas, given how anybody could spawn it in sandbox mode. --- .../Prototypes/Entities/Objects/Fun/instruments.yml | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/Resources/Prototypes/Entities/Objects/Fun/instruments.yml b/Resources/Prototypes/Entities/Objects/Fun/instruments.yml index 1ed3f2dce3..6656842ab9 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/instruments.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/instruments.yml @@ -223,15 +223,3 @@ - type: Item size: 24 sprite: Objects/Fun/Instruments/h_synthesizer.rsi - -- type: entity - name: super synthesizer - suffix: no MIDI limits - description: Blasting the ghetto with Touhou MIDIs since 2020. - id: SuperSynthesizerUnlimitedInstrument - parent: SuperSynthesizerInstrument - components: - - type: Instrument - allowPercussion: true - allowProgramChange: true - respectMidiLimits: false From 49f6a6304cff7ccac4bc0f6e1a79f4730fcf0467 Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Sun, 20 Dec 2020 02:41:02 +0100 Subject: [PATCH 19/29] Add total damage test --- .../{Damageable => Damage}/DamageTest.cs | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) rename Content.IntegrationTests/Tests/{Damageable => Damage}/DamageTest.cs (77%) diff --git a/Content.IntegrationTests/Tests/Damageable/DamageTest.cs b/Content.IntegrationTests/Tests/Damage/DamageTest.cs similarity index 77% rename from Content.IntegrationTests/Tests/Damageable/DamageTest.cs rename to Content.IntegrationTests/Tests/Damage/DamageTest.cs index 3cc065aac4..caeea3865a 100644 --- a/Content.IntegrationTests/Tests/Damageable/DamageTest.cs +++ b/Content.IntegrationTests/Tests/Damage/DamageTest.cs @@ -147,5 +147,53 @@ namespace Content.IntegrationTests.Tests.Damageable } }); } + + [Test] + public async Task TotalDamageTest() + { + var server = StartServerDummyTicker(new ServerContentIntegrationOption + { + ExtraPrototypes = Prototypes + }); + + await server.WaitIdleAsync(); + + var sEntityManager = server.ResolveDependency(); + var sMapManager = server.ResolveDependency(); + + IEntity sDamageableEntity; + IDamageableComponent sDamageableComponent = null; + + await server.WaitPost(() => + { + var mapId = sMapManager.NextMapId(); + var coordinates = new MapCoordinates(0, 0, mapId); + sMapManager.CreateMap(mapId); + + sDamageableEntity = sEntityManager.SpawnEntity(DamageableEntityId, coordinates); + sDamageableComponent = sDamageableEntity.GetComponent(); + }); + + await server.WaitAssertion(() => + { + var damageType = DamageClass.Brute; + var damage = 10; + + Assert.True(sDamageableComponent.ChangeDamage(DamageClass.Brute, damage, true)); + Assert.That(sDamageableComponent.TotalDamage, Is.EqualTo(10)); + + var totalTypeDamage = 0; + + foreach (var type in damageType.ToTypes()) + { + Assert.True(sDamageableComponent.TryGetDamage(type, out var typeDamage)); + Assert.That(typeDamage, Is.LessThanOrEqualTo(damage)); + + totalTypeDamage += typeDamage; + } + + Assert.That(totalTypeDamage, Is.EqualTo(damage)); + }); + } } } From f7edb9ce7e96bc25f90fe0d1b5c6df96824d2170 Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Sun, 20 Dec 2020 04:01:04 +0100 Subject: [PATCH 20/29] Ignore GlassBeaker and TraitorDeathMatchRedemption components on the client --- Content.Client/IgnoredComponents.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Content.Client/IgnoredComponents.cs b/Content.Client/IgnoredComponents.cs index b1a223cee4..676c7f33ca 100644 --- a/Content.Client/IgnoredComponents.cs +++ b/Content.Client/IgnoredComponents.cs @@ -227,6 +227,8 @@ namespace Content.Client "ChemicalAmmo", "BiologicalSurgeryData", "CargoTelepad", + "TraitorDeathMatchRedemption", + "GlassBeaker" }; } } From 026d96fd2d44b6763bc44b99ffdae87f48fb42b2 Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Sun, 20 Dec 2020 04:14:41 +0100 Subject: [PATCH 21/29] Replace MaybeNullWhen(false) with NotNullWhen(true) --- .../Components/Items/HandsComponent.cs | 2 +- Content.Server/Atmos/AtmosHelpers.cs | 29 +++++++++---------- .../Atmos/IGridAtmosphereComponent.cs | 7 +++-- .../Components/AnchorableComponent.cs | 2 +- .../Components/Atmos/GasAnalyzerComponent.cs | 4 +-- .../Atmos/GridAtmosphereComponent.cs | 3 -- .../Components/Buckle/BuckleComponent.cs | 8 ++--- .../Components/GUI/HandsComponent.cs | 7 ++--- .../Components/Recycling/RecyclerComponent.cs | 17 ++++++----- .../Components/Items/IHandsComponent.cs | 4 +-- .../EntitySystems/SharedMoverSystem.cs | 6 ++-- 11 files changed, 41 insertions(+), 48 deletions(-) diff --git a/Content.Client/GameObjects/Components/Items/HandsComponent.cs b/Content.Client/GameObjects/Components/Items/HandsComponent.cs index 654f7e6c0c..21f112d031 100644 --- a/Content.Client/GameObjects/Components/Items/HandsComponent.cs +++ b/Content.Client/GameObjects/Components/Items/HandsComponent.cs @@ -55,7 +55,7 @@ namespace Content.Client.GameObjects.Components.Items return Hands.FirstOrDefault(hand => hand.Name == name); } - private bool TryHand(string name, [MaybeNullWhen(false)] out Hand hand) + private bool TryHand(string name, [NotNullWhen(true)] out Hand? hand) { return (hand = GetHand(name)) != null; } diff --git a/Content.Server/Atmos/AtmosHelpers.cs b/Content.Server/Atmos/AtmosHelpers.cs index f0bdeab213..2761bf3457 100644 --- a/Content.Server/Atmos/AtmosHelpers.cs +++ b/Content.Server/Atmos/AtmosHelpers.cs @@ -13,7 +13,7 @@ namespace Content.Server.Atmos { public static class AtmosHelpers { - public static TileAtmosphere GetTileAtmosphere(this EntityCoordinates coordinates, IEntityManager? entityManager = null) + public static TileAtmosphere? GetTileAtmosphere(this EntityCoordinates coordinates, IEntityManager? entityManager = null) { entityManager ??= IoCManager.Resolve(); @@ -24,19 +24,19 @@ namespace Content.Server.Atmos public static GasMixture? GetTileAir(this EntityCoordinates coordinates, IEntityManager? entityManager = null) { - return coordinates.GetTileAtmosphere(entityManager).Air; + return coordinates.GetTileAtmosphere(entityManager)?.Air; } - public static bool TryGetTileAtmosphere(this EntityCoordinates coordinates, [MaybeNullWhen(false)] out TileAtmosphere atmosphere) + public static bool TryGetTileAtmosphere(this EntityCoordinates coordinates, [NotNullWhen(true)] out TileAtmosphere? atmosphere) { // ReSharper disable once ConditionIsAlwaysTrueOrFalse - return !Equals(atmosphere = coordinates.GetTileAtmosphere()!, default); + return !Equals(atmosphere = coordinates.GetTileAtmosphere(), default); } - public static bool TryGetTileAir(this EntityCoordinates coordinates, [MaybeNullWhen(false)] out GasMixture air, IEntityManager? entityManager = null) + public static bool TryGetTileAir(this EntityCoordinates coordinates, [NotNullWhen(true)] out GasMixture? air, IEntityManager? entityManager = null) { // ReSharper disable once ConditionIsAlwaysTrueOrFalse - return !Equals(air = coordinates.GetTileAir(entityManager)!, default); + return !Equals(air = coordinates.GetTileAir(entityManager), default); } public static bool IsTileAirProbablySafe(this EntityCoordinates coordinates) @@ -56,7 +56,7 @@ namespace Content.Server.Atmos return true; } - public static TileAtmosphere GetTileAtmosphere(this Vector2i indices, GridId gridId) + public static TileAtmosphere? GetTileAtmosphere(this Vector2i indices, GridId gridId) { var gridAtmos = EntitySystem.Get().GetGridAtmosphere(gridId); @@ -69,28 +69,25 @@ namespace Content.Server.Atmos } public static bool TryGetTileAtmosphere(this Vector2i indices, GridId gridId, - [MaybeNullWhen(false)] out TileAtmosphere atmosphere) + [NotNullWhen(true)] out TileAtmosphere? atmosphere) { // ReSharper disable once ConditionIsAlwaysTrueOrFalse - return !Equals(atmosphere = indices.GetTileAtmosphere(gridId)!, default); + return !Equals(atmosphere = indices.GetTileAtmosphere(gridId), default); } - public static bool TryGetTileAir(this Vector2i indices, GridId gridId, [MaybeNullWhen(false)] out GasMixture air) + public static bool TryGetTileAir(this Vector2i indices, GridId gridId, [NotNullWhen(true)] out GasMixture? air) { // ReSharper disable once ConditionIsAlwaysTrueOrFalse - return !Equals(air = indices.GetTileAir(gridId)!, default); + return !Equals(air = indices.GetTileAir(gridId), default); } public static bool InvalidateTileAir(this ITransformComponent transform, AtmosphereSystem? atmosSystem = null) { - return InvalidateTileAir(transform.Coordinates, atmosSystem); + return InvalidateTileAir(transform.Coordinates); } - public static bool InvalidateTileAir(this EntityCoordinates coordinates, AtmosphereSystem? atmosSystem = null, IEntityManager? entityManager = null) + public static bool InvalidateTileAir(this EntityCoordinates coordinates) { - atmosSystem ??= EntitySystem.Get(); - entityManager ??= IoCManager.Resolve(); - if (!coordinates.TryGetTileAtmosphere(out var tileAtmos)) { return false; diff --git a/Content.Server/Atmos/IGridAtmosphereComponent.cs b/Content.Server/Atmos/IGridAtmosphereComponent.cs index c84dd507e9..016551464c 100644 --- a/Content.Server/Atmos/IGridAtmosphereComponent.cs +++ b/Content.Server/Atmos/IGridAtmosphereComponent.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +#nullable enable +using System.Collections.Generic; using Content.Server.GameObjects.Components.Atmos; using Content.Server.GameObjects.Components.Atmos.Piping; using Content.Server.GameObjects.Components.NodeContainer.NodeGroups; @@ -120,7 +121,7 @@ namespace Content.Server.Atmos /// /// /// - TileAtmosphere GetTile(Vector2i indices, bool createSpace = true); + TileAtmosphere? GetTile(Vector2i indices, bool createSpace = true); /// /// Returns a tile. @@ -128,7 +129,7 @@ namespace Content.Server.Atmos /// /// /// - TileAtmosphere GetTile(EntityCoordinates coordinates, bool createSpace = true); + TileAtmosphere? GetTile(EntityCoordinates coordinates, bool createSpace = true); /// /// Returns if the tile in question is air-blocked. diff --git a/Content.Server/GameObjects/Components/AnchorableComponent.cs b/Content.Server/GameObjects/Components/AnchorableComponent.cs index 2fec6e340c..3e9cfb6f25 100644 --- a/Content.Server/GameObjects/Components/AnchorableComponent.cs +++ b/Content.Server/GameObjects/Components/AnchorableComponent.cs @@ -42,7 +42,7 @@ namespace Content.Server.GameObjects.Components /// The tool being used, can be null if forcing it /// Whether or not to check if the tool is valid /// true if it is valid, false otherwise - private async Task Valid(IEntity user, IEntity? utilizing, [MaybeNullWhen(false)] bool force = false) + private async Task Valid(IEntity user, IEntity? utilizing, [NotNullWhen(true)] bool force = false) { if (!Owner.HasComponent()) { diff --git a/Content.Server/GameObjects/Components/Atmos/GasAnalyzerComponent.cs b/Content.Server/GameObjects/Components/Atmos/GasAnalyzerComponent.cs index 4f3c527292..a63a27d274 100644 --- a/Content.Server/GameObjects/Components/Atmos/GasAnalyzerComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/GasAnalyzerComponent.cs @@ -130,7 +130,7 @@ namespace Content.Server.GameObjects.Components.Atmos // Already get the pressure before Dirty(), because we can't get the EntitySystem in that thread or smth var pressure = 0f; var gam = EntitySystem.Get().GetGridAtmosphere(Owner.Transform.GridID); - var tile = gam?.GetTile(Owner.Transform.Coordinates).Air; + var tile = gam?.GetTile(Owner.Transform.Coordinates)?.Air; if (tile != null) { pressure = tile.Pressure; @@ -190,7 +190,7 @@ namespace Content.Server.GameObjects.Components.Atmos var atmosSystem = EntitySystem.Get(); var gam = atmosSystem.GetGridAtmosphere(pos.GetGridId(Owner.EntityManager)); - var tile = gam?.GetTile(pos).Air; + var tile = gam.GetTile(pos)?.Air; if (tile == null) { error = "No Atmosphere!"; diff --git a/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs b/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs index 0c03c2f292..12ee989ebd 100644 --- a/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/GridAtmosphereComponent.cs @@ -2,7 +2,6 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Runtime.CompilerServices; using Content.Server.Atmos; @@ -10,7 +9,6 @@ using Content.Server.GameObjects.Components.Atmos.Piping; using Content.Server.GameObjects.Components.NodeContainer.NodeGroups; using Content.Server.GameObjects.EntitySystems; using Content.Server.GameObjects.EntitySystems.Atmos; -using Content.Shared; using Content.Shared.Atmos; using Content.Shared.Maps; using Robust.Server.GameObjects.EntitySystems.TileLookup; @@ -19,7 +17,6 @@ using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.ComponentDependencies; using Robust.Shared.GameObjects.Components.Map; using Robust.Shared.GameObjects.Systems; -using Robust.Shared.Interfaces.Configuration; using Robust.Shared.Interfaces.Map; using Robust.Shared.Log; using Robust.Shared.Map; diff --git a/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs b/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs index d6bdd0fa58..df9725041a 100644 --- a/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs +++ b/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs @@ -9,7 +9,6 @@ using Content.Server.GameObjects.Components.Strap; using Content.Server.GameObjects.EntitySystems; using Content.Shared.Alert; using Content.Shared.GameObjects.Components.Buckle; -using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.Components.Strap; using Content.Shared.GameObjects.EntitySystems; using Content.Shared.GameObjects.Verbs; @@ -27,7 +26,6 @@ using Robust.Shared.Interfaces.Timing; using Robust.Shared.IoC; using Robust.Shared.Localization; using Robust.Shared.Maths; -using Robust.Shared.Physics; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; @@ -69,7 +67,7 @@ namespace Content.Server.GameObjects.Components.Buckle public Vector2 BuckleOffset { get; private set; } private StrapComponent? _buckledTo; - + /// /// The strap that this component is buckled to. @@ -157,7 +155,7 @@ namespace Content.Server.GameObjects.Components.Buckle } } - private bool CanBuckle(IEntity? user, IEntity to, [MaybeNullWhen(false)] out StrapComponent strap) + private bool CanBuckle(IEntity? user, IEntity to, [NotNullWhen(true)] out StrapComponent? strap) { strap = null; @@ -421,7 +419,7 @@ namespace Content.Server.GameObjects.Components.Buckle { drawDepth = BuckledTo.SpriteComponent.DrawDepth - 1; } - + return new BuckleComponentState(Buckled, drawDepth, LastEntityBuckledTo, DontCollide); } diff --git a/Content.Server/GameObjects/Components/GUI/HandsComponent.cs b/Content.Server/GameObjects/Components/GUI/HandsComponent.cs index 35b22f0c59..5181d442fe 100644 --- a/Content.Server/GameObjects/Components/GUI/HandsComponent.cs +++ b/Content.Server/GameObjects/Components/GUI/HandsComponent.cs @@ -105,10 +105,9 @@ namespace Content.Server.GameObjects.Components.GUI return GetHand(handName)?.Entity?.GetComponent(); } - public bool TryGetItem(string handName, [MaybeNullWhen(false)] out ItemComponent item) + public bool TryGetItem(string handName, [NotNullWhen(true)] out ItemComponent? item) { - item = GetItem(handName); - return item != null; + return (item = GetItem(handName)) != null; } public ItemComponent? GetActiveHand => ActiveHand == null @@ -240,7 +239,7 @@ namespace Content.Server.GameObjects.Components.GUI return true; } - public bool TryHand(IEntity entity, [MaybeNullWhen(false)] out string handName) + public bool TryHand(IEntity entity, [NotNullWhen(true)] out string? handName) { handName = null; diff --git a/Content.Server/GameObjects/Components/Recycling/RecyclerComponent.cs b/Content.Server/GameObjects/Components/Recycling/RecyclerComponent.cs index 909b9239b8..64485491b5 100644 --- a/Content.Server/GameObjects/Components/Recycling/RecyclerComponent.cs +++ b/Content.Server/GameObjects/Components/Recycling/RecyclerComponent.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +#nullable enable +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using Content.Server.GameObjects.Components.Conveyor; using Content.Server.GameObjects.Components.Items.Storage; @@ -40,12 +41,12 @@ namespace Content.Server.GameObjects.Components.Recycling private int _efficiency; // TODO private bool Powered => - !Owner.TryGetComponent(out PowerReceiverComponent receiver) || + !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered; private void Bloodstain() { - if (Owner.TryGetComponent(out AppearanceComponent appearance)) + if (Owner.TryGetComponent(out AppearanceComponent? appearance)) { appearance.SetData(RecyclerVisuals.Bloody, true); } @@ -53,7 +54,7 @@ namespace Content.Server.GameObjects.Components.Recycling private void Clean() { - if (Owner.TryGetComponent(out AppearanceComponent appearance)) + if (Owner.TryGetComponent(out AppearanceComponent? appearance)) { appearance.SetData(RecyclerVisuals.Bloody, false); } @@ -64,7 +65,7 @@ namespace Content.Server.GameObjects.Components.Recycling return entity.HasComponent() && !_safe && Powered; } - private bool CanRecycle(IEntity entity, [MaybeNullWhen(false)] out ConstructionPrototype prototype) + private bool CanRecycle(IEntity entity, [NotNullWhen(true)] out ConstructionPrototype? prototype) { prototype = null; @@ -100,7 +101,7 @@ namespace Content.Server.GameObjects.Components.Recycling private bool CanRun() { - if (Owner.TryGetComponent(out PowerReceiverComponent receiver) && + if (Owner.TryGetComponent(out PowerReceiverComponent? receiver) && !receiver.Powered) { return false; @@ -121,7 +122,7 @@ namespace Content.Server.GameObjects.Components.Recycling return false; } - if (!entity.TryGetComponent(out IPhysicsComponent physics) || + if (!entity.TryGetComponent(out IPhysicsComponent? physics) || physics.Anchored) { return false; @@ -165,7 +166,7 @@ namespace Content.Server.GameObjects.Components.Recycling continue; } - if (entity.TryGetComponent(out IPhysicsComponent physics)) + if (entity.TryGetComponent(out IPhysicsComponent? physics)) { var controller = physics.EnsureController(); controller.Move(direction, frameTime, entity.Transform.WorldPosition - Owner.Transform.WorldPosition); diff --git a/Content.Server/Interfaces/GameObjects/Components/Items/IHandsComponent.cs b/Content.Server/Interfaces/GameObjects/Components/Items/IHandsComponent.cs index d2da0870d0..8de07084ff 100644 --- a/Content.Server/Interfaces/GameObjects/Components/Items/IHandsComponent.cs +++ b/Content.Server/Interfaces/GameObjects/Components/Items/IHandsComponent.cs @@ -47,7 +47,7 @@ namespace Content.Server.Interfaces.GameObjects.Components.Items /// The name of the hand to get. /// The item in the held, null if no item is held /// Whether it was holding an item - bool TryGetItem(string handName, [MaybeNullWhen(false)] out ItemComponent item); + bool TryGetItem(string handName, [NotNullWhen(true)] out ItemComponent? item); /// /// Gets item held by the current active hand @@ -102,7 +102,7 @@ namespace Content.Server.Interfaces.GameObjects.Components.Items /// /// true if the entity is held, false otherwise /// - bool TryHand(IEntity entity, [MaybeNullWhen(false)] out string handName); + bool TryHand(IEntity entity, [NotNullWhen(true)] out string? handName); /// /// Drops the item contained in the slot to the same position as our entity. diff --git a/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs b/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs index ee0ce1b188..7a8f266e9c 100644 --- a/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs +++ b/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs @@ -50,7 +50,7 @@ namespace Content.Shared.GameObjects.EntitySystems } //TODO: reorganize this to make more logical sense - protected void UpdateKinematics(ITransformComponent transform, IMoverComponent mover, IPhysicsComponent physics) + protected void UpdateKinematics(ITransformComponent transform, IMoverComponent mover, IPhysicsComponent physics) { physics.EnsureController(); @@ -71,7 +71,7 @@ namespace Content.Shared.GameObjects.EntitySystems // TODO: movement check. var (walkDir, sprintDir) = mover.VelocityDir; var combined = walkDir + sprintDir; - if (combined.LengthSquared < 0.001 || !ActionBlockerSystem.CanMove(mover.Owner) && !weightless) + if (combined.LengthSquared < 0.001 || !ActionBlockerSystem.CanMove(mover.Owner) && !weightless) { if (physics.TryGetController(out MoverController controller)) { @@ -177,7 +177,7 @@ namespace Content.Shared.GameObjects.EntitySystems moverComp.SetSprinting(subTick, walking); } - private static bool TryGetAttachedComponent(ICommonSession? session, [MaybeNullWhen(false)] out T component) + private static bool TryGetAttachedComponent(ICommonSession? session, [NotNullWhen(true)] out T? component) where T : class, IComponent { component = default; From fcd52fa90c587e74c53b0217ac467c71fa6d2e83 Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Sun, 20 Dec 2020 04:26:21 +0100 Subject: [PATCH 22/29] Add ActionBlockerExtensions --- .../Tests/Buckle/BuckleTest.cs | 1 + .../ActionBlocker/CanMoveCon.cs | 1 + Content.Server/Actions/ScreamAction.cs | 1 + Content.Server/Chat/ChatManager.cs | 1 + .../Access/IdCardConsoleComponent.cs | 1 + .../ActionBlocking/CuffableComponent.cs | 1 + .../ActionBlocking/HandcuffComponent.cs | 1 + .../Arcade/BlockGameArcadeComponent.cs | 1 + .../Arcade/SpaceVillainArcadeComponent.cs | 1 + .../Components/Atmos/FlammableComponent.cs | 1 + .../Components/Atmos/GasCanisterComponent.cs | 1 + .../Components/Atmos/GasTankComponent.cs | 1 + .../Components/Botany/LogComponent.cs | 1 + .../Components/Botany/PlantHolderComponent.cs | 1 + .../Components/Buckle/BuckleComponent.cs | 1 + .../Chemistry/ChemMasterComponent.cs | 1 + .../Chemistry/ReagentDispenserComponent.cs | 1 + .../Chemistry/SolutionContainerComponent.cs | 1 + .../ConstructionComponent.Verbs.cs | 1 + .../Disposal/DisposalMailingUnitComponent.cs | 1 + .../Disposal/DisposalRouterComponent.cs | 1 + .../Disposal/DisposalTaggerComponent.cs | 1 + .../Disposal/DisposalUnitComponent.cs | 1 + .../Components/Fluids/SpillableComponent.cs | 1 + .../Components/Fluids/SprayComponent.cs | 1 + .../Components/GUI/HandsComponent.cs | 1 + .../Components/GUI/InventoryComponent.cs | 1 + .../Components/GUI/StrippableComponent.cs | 1 + .../Instruments/InstrumentComponent.cs | 1 + .../Interactable/ExpendableLightComponent.cs | 1 + .../Interactable/HandheldLightComponent.cs | 1 + .../Components/Interactable/ToolComponent.cs | 1 + .../Items/Storage/EntityStorageComponent.cs | 1 + .../Components/Items/Storage/ItemComponent.cs | 1 + .../Storage/SecureEntityStorageComponent.cs | 1 + .../MachineLinking/SignalSwitchComponent.cs | 1 + .../Components/Medical/HealingComponent.cs | 1 + .../Medical/MedicalScannerComponent.cs | 1 + .../Metabolism/MetabolismComponent.cs | 1 + .../Components/Mobs/ServerActionsComponent.cs | 1 + .../Morgue/BodyBagEntityStorageComponent.cs | 1 + .../CrematoriumEntityStorageComponent.cs | 1 + .../Components/Movement/ClimbableComponent.cs | 1 + .../ParticleAcceleratorControlBoxComponent.cs | 1 + .../Components/PDA/PDAComponent.cs | 1 + .../Power/AME/AMEControllerComponent.cs | 1 + .../PowerReceiverUsers/BaseCharger.cs | 1 + .../Power/PowerCellSlotComponent.cs | 1 + .../Rotatable/FlippableComponent.cs | 1 + .../Rotatable/RotatableComponent.cs | 1 + .../Components/Strap/StrapComponent.cs | 1 + .../Weapon/Melee/StunbatonComponent.cs | 1 + .../Ranged/Ammunition/AmmoBoxComponent.cs | 1 + .../Barrels/BoltActionBarrelComponent.cs | 1 + .../Ranged/Barrels/RevolverBarrelComponent.cs | 1 + .../Barrels/ServerBatteryBarrelComponent.cs | 1 + .../Barrels/ServerMagazineBarrelComponent.cs | 1 + .../Ranged/ServerRangedWeaponComponent.cs | 1 + .../AI/Steering/AiSteeringSystem.cs | 1 + .../EntitySystems/Click/InteractionSystem.cs | 1 + .../EntitySystems/ConstructionSystem.cs | 1 + .../EntitySystems/PointingSystem.cs | 1 + .../Components/Items/IHandsComponent.cs | 1 + Content.Server/Throw/ThrowHelper.cs | 1 + .../ActionBlocking/SharedCuffableComponent.cs | 1 + .../Buckle/SharedBuckleComponent.cs | 1 + .../GUI/SharedStrippableComponent.cs | 1 + .../Mobs/SharedStunnableComponent.cs | 1 + .../Components/Mobs/State/IMobState.cs | 1 + .../Mobs/State/SharedMobStateComponent.cs | 1 + .../Movement/SharedClimbingComponent.cs | 1 + .../Observer/SharedGhostComponent.cs | 1 + .../Storage/SharedStorageComponent.cs | 1 + .../ActionBlocker/ActionBlockerExtensions.cs | 77 +++++++ .../ActionBlocker/ActionBlockerSystem.cs | 178 ++++++++++++++++ .../ActionBlocker/IActionBlocker.cs | 37 ++++ .../EntitySystems/ActionBlockerSystem.cs | 195 ------------------ .../EntitySystems/EffectBlockerSystem.cs | 3 +- .../EntitySystems/SharedMoverSystem.cs | 1 + .../Physics/ThrowKnockbackController.cs | 1 + 80 files changed, 369 insertions(+), 196 deletions(-) create mode 100644 Content.Shared/GameObjects/EntitySystems/ActionBlocker/ActionBlockerExtensions.cs create mode 100644 Content.Shared/GameObjects/EntitySystems/ActionBlocker/ActionBlockerSystem.cs create mode 100644 Content.Shared/GameObjects/EntitySystems/ActionBlocker/IActionBlocker.cs delete mode 100644 Content.Shared/GameObjects/EntitySystems/ActionBlockerSystem.cs diff --git a/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs b/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs index 394dd11e7c..b6918abae8 100644 --- a/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs +++ b/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs @@ -7,6 +7,7 @@ using Content.Shared.GameObjects.Components.Body; using Content.Shared.GameObjects.Components.Body.Part; using Content.Shared.GameObjects.Components.Buckle; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Utility; using NUnit.Framework; using Robust.Shared.Interfaces.GameObjects; diff --git a/Content.Server/AI/Utility/Considerations/ActionBlocker/CanMoveCon.cs b/Content.Server/AI/Utility/Considerations/ActionBlocker/CanMoveCon.cs index c45230589b..b53c0d0190 100644 --- a/Content.Server/AI/Utility/Considerations/ActionBlocker/CanMoveCon.cs +++ b/Content.Server/AI/Utility/Considerations/ActionBlocker/CanMoveCon.cs @@ -1,6 +1,7 @@ using Content.Server.AI.WorldState; using Content.Server.AI.WorldState.States; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; namespace Content.Server.AI.Utility.Considerations.ActionBlocker { diff --git a/Content.Server/Actions/ScreamAction.cs b/Content.Server/Actions/ScreamAction.cs index e89d2452e7..58a8acc480 100644 --- a/Content.Server/Actions/ScreamAction.cs +++ b/Content.Server/Actions/ScreamAction.cs @@ -5,6 +5,7 @@ using Content.Shared.Actions; using Content.Shared.Audio; using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Preferences; using Content.Shared.Utility; using JetBrains.Annotations; diff --git a/Content.Server/Chat/ChatManager.cs b/Content.Server/Chat/ChatManager.cs index afeb0c11b2..7e291f5cef 100644 --- a/Content.Server/Chat/ChatManager.cs +++ b/Content.Server/Chat/ChatManager.cs @@ -11,6 +11,7 @@ using Content.Server.Interfaces.Chat; using Content.Shared.Chat; using Content.Shared.GameObjects.Components.Inventory; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Interfaces; using Robust.Server.Interfaces.GameObjects; using Robust.Server.Interfaces.Player; diff --git a/Content.Server/GameObjects/Components/Access/IdCardConsoleComponent.cs b/Content.Server/GameObjects/Components/Access/IdCardConsoleComponent.cs index 3457142e88..c611bd2957 100644 --- a/Content.Server/GameObjects/Components/Access/IdCardConsoleComponent.cs +++ b/Content.Server/GameObjects/Components/Access/IdCardConsoleComponent.cs @@ -11,6 +11,7 @@ using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; using Content.Shared.GameObjects.Verbs; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Robust.Server.GameObjects.Components.Container; using Robust.Server.GameObjects.Components.UserInterface; using Robust.Server.Interfaces.GameObjects; diff --git a/Content.Server/GameObjects/Components/ActionBlocking/CuffableComponent.cs b/Content.Server/GameObjects/Components/ActionBlocking/CuffableComponent.cs index b9613c4391..e82dada792 100644 --- a/Content.Server/GameObjects/Components/ActionBlocking/CuffableComponent.cs +++ b/Content.Server/GameObjects/Components/ActionBlocking/CuffableComponent.cs @@ -10,6 +10,7 @@ using Content.Shared.Alert; using Content.Shared.GameObjects.Components.ActionBlocking; using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; using Content.Shared.Utility; diff --git a/Content.Server/GameObjects/Components/ActionBlocking/HandcuffComponent.cs b/Content.Server/GameObjects/Components/ActionBlocking/HandcuffComponent.cs index 8fb013e5ea..18f4892d11 100644 --- a/Content.Server/GameObjects/Components/ActionBlocking/HandcuffComponent.cs +++ b/Content.Server/GameObjects/Components/ActionBlocking/HandcuffComponent.cs @@ -5,6 +5,7 @@ using Content.Server.GameObjects.Components.Mobs; using Content.Server.GameObjects.EntitySystems.DoAfter; using Content.Shared.GameObjects.Components.ActionBlocking; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; using Content.Shared.Utility; diff --git a/Content.Server/GameObjects/Components/Arcade/BlockGameArcadeComponent.cs b/Content.Server/GameObjects/Components/Arcade/BlockGameArcadeComponent.cs index c3e6c0bf36..8045d71ffb 100644 --- a/Content.Server/GameObjects/Components/Arcade/BlockGameArcadeComponent.cs +++ b/Content.Server/GameObjects/Components/Arcade/BlockGameArcadeComponent.cs @@ -8,6 +8,7 @@ using Content.Server.Utility; using Content.Shared.Arcade; using Content.Shared.GameObjects; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Interfaces.GameObjects.Components; using Robust.Server.GameObjects.Components.UserInterface; using Robust.Server.Interfaces.GameObjects; diff --git a/Content.Server/GameObjects/Components/Arcade/SpaceVillainArcadeComponent.cs b/Content.Server/GameObjects/Components/Arcade/SpaceVillainArcadeComponent.cs index 285ad7c4c3..99c46516e8 100644 --- a/Content.Server/GameObjects/Components/Arcade/SpaceVillainArcadeComponent.cs +++ b/Content.Server/GameObjects/Components/Arcade/SpaceVillainArcadeComponent.cs @@ -6,6 +6,7 @@ using Content.Server.Utility; using Content.Shared.GameObjects.Components; using Content.Shared.GameObjects.Components.Arcade; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Interfaces.GameObjects.Components; using Robust.Server.GameObjects.Components.UserInterface; using Robust.Server.GameObjects.EntitySystems; diff --git a/Content.Server/GameObjects/Components/Atmos/FlammableComponent.cs b/Content.Server/GameObjects/Components/Atmos/FlammableComponent.cs index 17c40e111b..c3b6f7bbb1 100644 --- a/Content.Server/GameObjects/Components/Atmos/FlammableComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/FlammableComponent.cs @@ -12,6 +12,7 @@ using Content.Shared.GameObjects.Components.Atmos; using Content.Shared.GameObjects.Components.Damage; using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; using Robust.Server.GameObjects; diff --git a/Content.Server/GameObjects/Components/Atmos/GasCanisterComponent.cs b/Content.Server/GameObjects/Components/Atmos/GasCanisterComponent.cs index 3ad88356e0..348ba46956 100644 --- a/Content.Server/GameObjects/Components/Atmos/GasCanisterComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/GasCanisterComponent.cs @@ -17,6 +17,7 @@ using Content.Shared.GameObjects.EntitySystems; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; using Content.Shared.Atmos; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Robust.Server.GameObjects; using Robust.Server.GameObjects.Components.UserInterface; using Robust.Server.Interfaces.GameObjects; diff --git a/Content.Server/GameObjects/Components/Atmos/GasTankComponent.cs b/Content.Server/GameObjects/Components/Atmos/GasTankComponent.cs index 5dd0bcb40d..0956c66645 100644 --- a/Content.Server/GameObjects/Components/Atmos/GasTankComponent.cs +++ b/Content.Server/GameObjects/Components/Atmos/GasTankComponent.cs @@ -11,6 +11,7 @@ using Content.Shared.Audio; using Content.Shared.GameObjects.Components.Atmos.GasTank; using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces.GameObjects.Components; using JetBrains.Annotations; diff --git a/Content.Server/GameObjects/Components/Botany/LogComponent.cs b/Content.Server/GameObjects/Components/Botany/LogComponent.cs index 3bebc0a902..753d887fa5 100644 --- a/Content.Server/GameObjects/Components/Botany/LogComponent.cs +++ b/Content.Server/GameObjects/Components/Botany/LogComponent.cs @@ -1,5 +1,6 @@ using System.Threading.Tasks; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Interfaces.GameObjects.Components; using Content.Shared.Utility; using Robust.Shared.GameObjects; diff --git a/Content.Server/GameObjects/Components/Botany/PlantHolderComponent.cs b/Content.Server/GameObjects/Components/Botany/PlantHolderComponent.cs index e1a520a351..6d481b80ed 100644 --- a/Content.Server/GameObjects/Components/Botany/PlantHolderComponent.cs +++ b/Content.Server/GameObjects/Components/Botany/PlantHolderComponent.cs @@ -13,6 +13,7 @@ using Content.Shared.Audio; using Content.Shared.Chemistry; using Content.Shared.GameObjects.Components.Botany; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; using Content.Shared.Utility; diff --git a/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs b/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs index df9725041a..f6f4c640f5 100644 --- a/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs +++ b/Content.Server/GameObjects/Components/Buckle/BuckleComponent.cs @@ -11,6 +11,7 @@ using Content.Shared.Alert; using Content.Shared.GameObjects.Components.Buckle; using Content.Shared.GameObjects.Components.Strap; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; diff --git a/Content.Server/GameObjects/Components/Chemistry/ChemMasterComponent.cs b/Content.Server/GameObjects/Components/Chemistry/ChemMasterComponent.cs index 8a80d98b7a..293b4fa0da 100644 --- a/Content.Server/GameObjects/Components/Chemistry/ChemMasterComponent.cs +++ b/Content.Server/GameObjects/Components/Chemistry/ChemMasterComponent.cs @@ -12,6 +12,7 @@ using Content.Server.Utility; using Content.Shared.Chemistry; using Content.Shared.GameObjects.Components.Chemistry.ChemMaster; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; using Content.Shared.Utility; diff --git a/Content.Server/GameObjects/Components/Chemistry/ReagentDispenserComponent.cs b/Content.Server/GameObjects/Components/Chemistry/ReagentDispenserComponent.cs index 8546b0bb41..e27612606c 100644 --- a/Content.Server/GameObjects/Components/Chemistry/ReagentDispenserComponent.cs +++ b/Content.Server/GameObjects/Components/Chemistry/ReagentDispenserComponent.cs @@ -11,6 +11,7 @@ using Content.Server.Utility; using Content.Shared.Chemistry; using Content.Shared.GameObjects.Components.Chemistry.ReagentDispenser; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; using Content.Shared.GameObjects.Verbs; diff --git a/Content.Server/GameObjects/Components/Chemistry/SolutionContainerComponent.cs b/Content.Server/GameObjects/Components/Chemistry/SolutionContainerComponent.cs index afc7899304..d2d72ac1fd 100644 --- a/Content.Server/GameObjects/Components/Chemistry/SolutionContainerComponent.cs +++ b/Content.Server/GameObjects/Components/Chemistry/SolutionContainerComponent.cs @@ -6,6 +6,7 @@ using Content.Server.GameObjects.EntitySystems; using Content.Shared.Chemistry; using Content.Shared.GameObjects.Components.Chemistry; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Utility; using Robust.Server.GameObjects; diff --git a/Content.Server/GameObjects/Components/Construction/ConstructionComponent.Verbs.cs b/Content.Server/GameObjects/Components/Construction/ConstructionComponent.Verbs.cs index 61e517f101..04a1d0c739 100644 --- a/Content.Server/GameObjects/Components/Construction/ConstructionComponent.Verbs.cs +++ b/Content.Server/GameObjects/Components/Construction/ConstructionComponent.Verbs.cs @@ -1,4 +1,5 @@ using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; using Robust.Shared.GameObjects; diff --git a/Content.Server/GameObjects/Components/Disposal/DisposalMailingUnitComponent.cs b/Content.Server/GameObjects/Components/Disposal/DisposalMailingUnitComponent.cs index f358fc1d5d..83069957b0 100644 --- a/Content.Server/GameObjects/Components/Disposal/DisposalMailingUnitComponent.cs +++ b/Content.Server/GameObjects/Components/Disposal/DisposalMailingUnitComponent.cs @@ -17,6 +17,7 @@ using Content.Shared.GameObjects.Components; using Content.Shared.GameObjects.Components.Body; using Content.Shared.GameObjects.Components.Disposal; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; diff --git a/Content.Server/GameObjects/Components/Disposal/DisposalRouterComponent.cs b/Content.Server/GameObjects/Components/Disposal/DisposalRouterComponent.cs index 6e62479d38..5a72ff74e4 100644 --- a/Content.Server/GameObjects/Components/Disposal/DisposalRouterComponent.cs +++ b/Content.Server/GameObjects/Components/Disposal/DisposalRouterComponent.cs @@ -6,6 +6,7 @@ using Content.Server.GameObjects.Components.Mobs; using Content.Server.Interfaces.GameObjects.Components.Items; using Content.Server.Utility; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; diff --git a/Content.Server/GameObjects/Components/Disposal/DisposalTaggerComponent.cs b/Content.Server/GameObjects/Components/Disposal/DisposalTaggerComponent.cs index e3bc82e674..41d90e1664 100644 --- a/Content.Server/GameObjects/Components/Disposal/DisposalTaggerComponent.cs +++ b/Content.Server/GameObjects/Components/Disposal/DisposalTaggerComponent.cs @@ -21,6 +21,7 @@ using Robust.Shared.Localization; using Robust.Shared.Maths; using Robust.Shared.ViewVariables; using System; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using static Content.Shared.GameObjects.Components.Disposal.SharedDisposalTaggerComponent; namespace Content.Server.GameObjects.Components.Disposal diff --git a/Content.Server/GameObjects/Components/Disposal/DisposalUnitComponent.cs b/Content.Server/GameObjects/Components/Disposal/DisposalUnitComponent.cs index 31a1ac6a86..f366eebe37 100644 --- a/Content.Server/GameObjects/Components/Disposal/DisposalUnitComponent.cs +++ b/Content.Server/GameObjects/Components/Disposal/DisposalUnitComponent.cs @@ -20,6 +20,7 @@ using Content.Shared.GameObjects.Components.Disposal; using Content.Shared.GameObjects.Components.Items; using Content.Shared.GameObjects.Components.Mobs.State; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; diff --git a/Content.Server/GameObjects/Components/Fluids/SpillableComponent.cs b/Content.Server/GameObjects/Components/Fluids/SpillableComponent.cs index c6528086de..62b2a5ec6c 100644 --- a/Content.Server/GameObjects/Components/Fluids/SpillableComponent.cs +++ b/Content.Server/GameObjects/Components/Fluids/SpillableComponent.cs @@ -1,6 +1,7 @@ using Content.Server.GameObjects.Components.Chemistry; using Content.Shared.Chemistry; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; using Robust.Shared.GameObjects; diff --git a/Content.Server/GameObjects/Components/Fluids/SprayComponent.cs b/Content.Server/GameObjects/Components/Fluids/SprayComponent.cs index 5d0c4ef416..71f09c780e 100644 --- a/Content.Server/GameObjects/Components/Fluids/SprayComponent.cs +++ b/Content.Server/GameObjects/Components/Fluids/SprayComponent.cs @@ -7,6 +7,7 @@ using Content.Shared.GameObjects.Components; using Content.Shared.GameObjects.Components.Fluids; using Content.Shared.GameObjects.Components.Items; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; using Robust.Server.GameObjects; diff --git a/Content.Server/GameObjects/Components/GUI/HandsComponent.cs b/Content.Server/GameObjects/Components/GUI/HandsComponent.cs index 5181d442fe..9d1aa7cef9 100644 --- a/Content.Server/GameObjects/Components/GUI/HandsComponent.cs +++ b/Content.Server/GameObjects/Components/GUI/HandsComponent.cs @@ -9,6 +9,7 @@ using Content.Server.Interfaces.GameObjects.Components.Items; using Content.Shared.GameObjects.Components.Body.Part; using Content.Shared.GameObjects.Components.Items; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Physics.Pull; using Robust.Server.GameObjects; using Robust.Server.GameObjects.Components.Container; diff --git a/Content.Server/GameObjects/Components/GUI/InventoryComponent.cs b/Content.Server/GameObjects/Components/GUI/InventoryComponent.cs index 33152537ec..593fdf7e80 100644 --- a/Content.Server/GameObjects/Components/GUI/InventoryComponent.cs +++ b/Content.Server/GameObjects/Components/GUI/InventoryComponent.cs @@ -7,6 +7,7 @@ using Content.Server.GameObjects.EntitySystems.Click; using Content.Server.Interfaces.GameObjects; using Content.Shared.GameObjects.Components.Inventory; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Interfaces; using Robust.Server.GameObjects.Components.Container; using Robust.Shared.Containers; diff --git a/Content.Server/GameObjects/Components/GUI/StrippableComponent.cs b/Content.Server/GameObjects/Components/GUI/StrippableComponent.cs index ff755d3cdd..6abb62df94 100644 --- a/Content.Server/GameObjects/Components/GUI/StrippableComponent.cs +++ b/Content.Server/GameObjects/Components/GUI/StrippableComponent.cs @@ -7,6 +7,7 @@ using Content.Server.GameObjects.EntitySystems.DoAfter; using Content.Server.Utility; using Content.Shared.GameObjects.Components.GUI; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; diff --git a/Content.Server/GameObjects/Components/Instruments/InstrumentComponent.cs b/Content.Server/GameObjects/Components/Instruments/InstrumentComponent.cs index 289ebcce79..233874b533 100644 --- a/Content.Server/GameObjects/Components/Instruments/InstrumentComponent.cs +++ b/Content.Server/GameObjects/Components/Instruments/InstrumentComponent.cs @@ -7,6 +7,7 @@ using Content.Server.Utility; using Content.Shared; using Content.Shared.GameObjects.Components.Instruments; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; using Robust.Server.GameObjects; diff --git a/Content.Server/GameObjects/Components/Interactable/ExpendableLightComponent.cs b/Content.Server/GameObjects/Components/Interactable/ExpendableLightComponent.cs index 2958f649ff..7529820fb4 100644 --- a/Content.Server/GameObjects/Components/Interactable/ExpendableLightComponent.cs +++ b/Content.Server/GameObjects/Components/Interactable/ExpendableLightComponent.cs @@ -4,6 +4,7 @@ using Content.Server.GameObjects.Components.Items.Storage; using Content.Server.GameObjects.Components.Sound; using Content.Shared.GameObjects.Components; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces.GameObjects.Components; using Robust.Server.GameObjects; diff --git a/Content.Server/GameObjects/Components/Interactable/HandheldLightComponent.cs b/Content.Server/GameObjects/Components/Interactable/HandheldLightComponent.cs index 958ec9768f..430d0e785d 100644 --- a/Content.Server/GameObjects/Components/Interactable/HandheldLightComponent.cs +++ b/Content.Server/GameObjects/Components/Interactable/HandheldLightComponent.cs @@ -11,6 +11,7 @@ using Content.Server.GameObjects.Components.Weapon.Ranged.Barrels; using Content.Shared.GameObjects.Components; using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; diff --git a/Content.Server/GameObjects/Components/Interactable/ToolComponent.cs b/Content.Server/GameObjects/Components/Interactable/ToolComponent.cs index 7bc3c0739a..19e16ae678 100644 --- a/Content.Server/GameObjects/Components/Interactable/ToolComponent.cs +++ b/Content.Server/GameObjects/Components/Interactable/ToolComponent.cs @@ -5,6 +5,7 @@ using Content.Server.GameObjects.EntitySystems.DoAfter; using Content.Shared.Audio; using Content.Shared.GameObjects.Components.Interactable; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Robust.Server.GameObjects.EntitySystems; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Systems; diff --git a/Content.Server/GameObjects/Components/Items/Storage/EntityStorageComponent.cs b/Content.Server/GameObjects/Components/Items/Storage/EntityStorageComponent.cs index 79f360cb07..632bfd4402 100644 --- a/Content.Server/GameObjects/Components/Items/Storage/EntityStorageComponent.cs +++ b/Content.Server/GameObjects/Components/Items/Storage/EntityStorageComponent.cs @@ -9,6 +9,7 @@ using Content.Shared.GameObjects.Components.Body; using Content.Shared.GameObjects.Components.Interactable; using Content.Shared.GameObjects.Components.Storage; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; diff --git a/Content.Server/GameObjects/Components/Items/Storage/ItemComponent.cs b/Content.Server/GameObjects/Components/Items/Storage/ItemComponent.cs index b55870af4b..67c32b1c84 100644 --- a/Content.Server/GameObjects/Components/Items/Storage/ItemComponent.cs +++ b/Content.Server/GameObjects/Components/Items/Storage/ItemComponent.cs @@ -5,6 +5,7 @@ using Content.Shared.GameObjects; using Content.Shared.GameObjects.Components.Items; using Content.Shared.GameObjects.Components.Storage; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces.GameObjects.Components; using Content.Shared.Utility; diff --git a/Content.Server/GameObjects/Components/Items/Storage/SecureEntityStorageComponent.cs b/Content.Server/GameObjects/Components/Items/Storage/SecureEntityStorageComponent.cs index 1f7228d25a..5e4f9076fa 100644 --- a/Content.Server/GameObjects/Components/Items/Storage/SecureEntityStorageComponent.cs +++ b/Content.Server/GameObjects/Components/Items/Storage/SecureEntityStorageComponent.cs @@ -1,6 +1,7 @@ using Content.Server.GameObjects.Components.Access; using Content.Shared.GameObjects.Components.Storage; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; diff --git a/Content.Server/GameObjects/Components/MachineLinking/SignalSwitchComponent.cs b/Content.Server/GameObjects/Components/MachineLinking/SignalSwitchComponent.cs index a73bc74e89..9643aa242d 100644 --- a/Content.Server/GameObjects/Components/MachineLinking/SignalSwitchComponent.cs +++ b/Content.Server/GameObjects/Components/MachineLinking/SignalSwitchComponent.cs @@ -1,4 +1,5 @@ using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; diff --git a/Content.Server/GameObjects/Components/Medical/HealingComponent.cs b/Content.Server/GameObjects/Components/Medical/HealingComponent.cs index f717e831de..cb4684238a 100644 --- a/Content.Server/GameObjects/Components/Medical/HealingComponent.cs +++ b/Content.Server/GameObjects/Components/Medical/HealingComponent.cs @@ -4,6 +4,7 @@ using Content.Server.GameObjects.Components.Stack; using Content.Shared.Damage; using Content.Shared.GameObjects.Components.Damage; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Interfaces.GameObjects.Components; using Content.Shared.Utility; using Robust.Shared.GameObjects; diff --git a/Content.Server/GameObjects/Components/Medical/MedicalScannerComponent.cs b/Content.Server/GameObjects/Components/Medical/MedicalScannerComponent.cs index 5b5fff76f2..8013453635 100644 --- a/Content.Server/GameObjects/Components/Medical/MedicalScannerComponent.cs +++ b/Content.Server/GameObjects/Components/Medical/MedicalScannerComponent.cs @@ -13,6 +13,7 @@ using Content.Shared.GameObjects.Components.Damage; using Content.Shared.GameObjects.Components.Medical; using Content.Shared.GameObjects.Components.Mobs.State; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces.GameObjects.Components; using Robust.Server.GameObjects; diff --git a/Content.Server/GameObjects/Components/Metabolism/MetabolismComponent.cs b/Content.Server/GameObjects/Components/Metabolism/MetabolismComponent.cs index f745d6b720..bb459bf544 100644 --- a/Content.Server/GameObjects/Components/Metabolism/MetabolismComponent.cs +++ b/Content.Server/GameObjects/Components/Metabolism/MetabolismComponent.cs @@ -14,6 +14,7 @@ using Content.Shared.GameObjects.Components.Body.Mechanism; using Content.Shared.GameObjects.Components.Damage; using Content.Shared.GameObjects.Components.Mobs.State; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Interfaces; using Content.Shared.Interfaces.Chemistry; using Robust.Shared.GameObjects; diff --git a/Content.Server/GameObjects/Components/Mobs/ServerActionsComponent.cs b/Content.Server/GameObjects/Components/Mobs/ServerActionsComponent.cs index e5e80544b5..ffaebf02f8 100644 --- a/Content.Server/GameObjects/Components/Mobs/ServerActionsComponent.cs +++ b/Content.Server/GameObjects/Components/Mobs/ServerActionsComponent.cs @@ -3,6 +3,7 @@ using System; using Content.Shared.Actions; using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Robust.Server.Interfaces.GameObjects; using Robust.Shared.GameObjects; using Robust.Shared.Interfaces.GameObjects; diff --git a/Content.Server/GameObjects/Components/Morgue/BodyBagEntityStorageComponent.cs b/Content.Server/GameObjects/Components/Morgue/BodyBagEntityStorageComponent.cs index 3c8d91150b..e4731b2f7f 100644 --- a/Content.Server/GameObjects/Components/Morgue/BodyBagEntityStorageComponent.cs +++ b/Content.Server/GameObjects/Components/Morgue/BodyBagEntityStorageComponent.cs @@ -20,6 +20,7 @@ using Robust.Shared.Localization; using Robust.Shared.Utility; using Robust.Shared.ViewVariables; using System.Threading.Tasks; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; namespace Content.Server.GameObjects.Components.Morgue { diff --git a/Content.Server/GameObjects/Components/Morgue/CrematoriumEntityStorageComponent.cs b/Content.Server/GameObjects/Components/Morgue/CrematoriumEntityStorageComponent.cs index 7b9b6a311b..0ba0ddd75d 100644 --- a/Content.Server/GameObjects/Components/Morgue/CrematoriumEntityStorageComponent.cs +++ b/Content.Server/GameObjects/Components/Morgue/CrematoriumEntityStorageComponent.cs @@ -2,6 +2,7 @@ using Content.Server.GameObjects.Components.Items.Storage; using Content.Shared.GameObjects.Components.Morgue; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; diff --git a/Content.Server/GameObjects/Components/Movement/ClimbableComponent.cs b/Content.Server/GameObjects/Components/Movement/ClimbableComponent.cs index efdb161935..97f9d4e21d 100644 --- a/Content.Server/GameObjects/Components/Movement/ClimbableComponent.cs +++ b/Content.Server/GameObjects/Components/Movement/ClimbableComponent.cs @@ -6,6 +6,7 @@ using Content.Shared.GameObjects.Components.Body; using Content.Shared.GameObjects.Components.Body.Part; using Content.Shared.GameObjects.Components.Movement; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; diff --git a/Content.Server/GameObjects/Components/PA/ParticleAcceleratorControlBoxComponent.cs b/Content.Server/GameObjects/Components/PA/ParticleAcceleratorControlBoxComponent.cs index 4525a42a25..542878fc98 100644 --- a/Content.Server/GameObjects/Components/PA/ParticleAcceleratorControlBoxComponent.cs +++ b/Content.Server/GameObjects/Components/PA/ParticleAcceleratorControlBoxComponent.cs @@ -10,6 +10,7 @@ using Content.Server.GameObjects.Components.VendingMachines; using Content.Server.Utility; using Content.Shared.GameObjects.Components; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Interfaces.GameObjects.Components; using Robust.Server.GameObjects; using Robust.Server.GameObjects.Components.UserInterface; diff --git a/Content.Server/GameObjects/Components/PDA/PDAComponent.cs b/Content.Server/GameObjects/Components/PDA/PDAComponent.cs index 0a83101a6a..c5ed36ede8 100644 --- a/Content.Server/GameObjects/Components/PDA/PDAComponent.cs +++ b/Content.Server/GameObjects/Components/PDA/PDAComponent.cs @@ -14,6 +14,7 @@ using Content.Server.Interfaces.PDA; using Content.Server.Utility; using Content.Shared.GameObjects.Components.PDA; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; diff --git a/Content.Server/GameObjects/Components/Power/AME/AMEControllerComponent.cs b/Content.Server/GameObjects/Components/Power/AME/AMEControllerComponent.cs index 8e5f590e24..eb6bf1e9fc 100644 --- a/Content.Server/GameObjects/Components/Power/AME/AMEControllerComponent.cs +++ b/Content.Server/GameObjects/Components/Power/AME/AMEControllerComponent.cs @@ -11,6 +11,7 @@ using Content.Server.Interfaces.GameObjects.Components.Items; using Content.Server.Utility; using Content.Shared.GameObjects.Components.Power.AME; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; using Robust.Server.GameObjects; diff --git a/Content.Server/GameObjects/Components/Power/ApcNetComponents/PowerReceiverUsers/BaseCharger.cs b/Content.Server/GameObjects/Components/Power/ApcNetComponents/PowerReceiverUsers/BaseCharger.cs index 986b404aea..9cc926434d 100644 --- a/Content.Server/GameObjects/Components/Power/ApcNetComponents/PowerReceiverUsers/BaseCharger.cs +++ b/Content.Server/GameObjects/Components/Power/ApcNetComponents/PowerReceiverUsers/BaseCharger.cs @@ -6,6 +6,7 @@ using Content.Server.GameObjects.Components.Items.Storage; using Content.Server.GameObjects.Components.Weapon.Ranged.Barrels; using Content.Shared.GameObjects.Components.Power; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; diff --git a/Content.Server/GameObjects/Components/Power/PowerCellSlotComponent.cs b/Content.Server/GameObjects/Components/Power/PowerCellSlotComponent.cs index c898b29497..79366c366c 100644 --- a/Content.Server/GameObjects/Components/Power/PowerCellSlotComponent.cs +++ b/Content.Server/GameObjects/Components/Power/PowerCellSlotComponent.cs @@ -4,6 +4,7 @@ using Content.Server.GameObjects.Components.GUI; using Content.Server.GameObjects.Components.Items.Storage; using Content.Shared.Audio; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Robust.Server.GameObjects.Components.Container; using Robust.Server.GameObjects.EntitySystems; diff --git a/Content.Server/GameObjects/Components/Rotatable/FlippableComponent.cs b/Content.Server/GameObjects/Components/Rotatable/FlippableComponent.cs index 3d890b8883..ff95843d07 100644 --- a/Content.Server/GameObjects/Components/Rotatable/FlippableComponent.cs +++ b/Content.Server/GameObjects/Components/Rotatable/FlippableComponent.cs @@ -1,5 +1,6 @@ #nullable enable using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; using Robust.Shared.GameObjects; diff --git a/Content.Server/GameObjects/Components/Rotatable/RotatableComponent.cs b/Content.Server/GameObjects/Components/Rotatable/RotatableComponent.cs index 403b7d73fd..18613346ad 100644 --- a/Content.Server/GameObjects/Components/Rotatable/RotatableComponent.cs +++ b/Content.Server/GameObjects/Components/Rotatable/RotatableComponent.cs @@ -1,4 +1,5 @@ using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; using Robust.Shared.GameObjects; diff --git a/Content.Server/GameObjects/Components/Strap/StrapComponent.cs b/Content.Server/GameObjects/Components/Strap/StrapComponent.cs index a6ad9585b5..253a299ca7 100644 --- a/Content.Server/GameObjects/Components/Strap/StrapComponent.cs +++ b/Content.Server/GameObjects/Components/Strap/StrapComponent.cs @@ -5,6 +5,7 @@ using Content.Server.GameObjects.Components.Buckle; using Content.Shared.Alert; using Content.Shared.GameObjects.Components.Strap; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces.GameObjects.Components; using Content.Shared.Utility; diff --git a/Content.Server/GameObjects/Components/Weapon/Melee/StunbatonComponent.cs b/Content.Server/GameObjects/Components/Weapon/Melee/StunbatonComponent.cs index 03de47d17d..53291488ab 100644 --- a/Content.Server/GameObjects/Components/Weapon/Melee/StunbatonComponent.cs +++ b/Content.Server/GameObjects/Components/Weapon/Melee/StunbatonComponent.cs @@ -8,6 +8,7 @@ using Content.Server.GameObjects.Components.Power; using Content.Server.Interfaces.GameObjects.Components.Items; using Content.Shared.Audio; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; diff --git a/Content.Server/GameObjects/Components/Weapon/Ranged/Ammunition/AmmoBoxComponent.cs b/Content.Server/GameObjects/Components/Weapon/Ranged/Ammunition/AmmoBoxComponent.cs index 9c0b83af28..267cffbcf9 100644 --- a/Content.Server/GameObjects/Components/Weapon/Ranged/Ammunition/AmmoBoxComponent.cs +++ b/Content.Server/GameObjects/Components/Weapon/Ranged/Ammunition/AmmoBoxComponent.cs @@ -6,6 +6,7 @@ using Content.Server.GameObjects.Components.Items.Storage; using Content.Server.GameObjects.Components.Weapon.Ranged.Barrels; using Content.Shared.GameObjects.Components.Weapons.Ranged.Barrels; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; diff --git a/Content.Server/GameObjects/Components/Weapon/Ranged/Barrels/BoltActionBarrelComponent.cs b/Content.Server/GameObjects/Components/Weapon/Ranged/Barrels/BoltActionBarrelComponent.cs index 94565b01be..ebd5c16eb8 100644 --- a/Content.Server/GameObjects/Components/Weapon/Ranged/Barrels/BoltActionBarrelComponent.cs +++ b/Content.Server/GameObjects/Components/Weapon/Ranged/Barrels/BoltActionBarrelComponent.cs @@ -4,6 +4,7 @@ using Content.Server.GameObjects.Components.Weapon.Ranged.Ammunition; using Content.Shared.GameObjects; using Content.Shared.GameObjects.Components.Weapons.Ranged.Barrels; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; diff --git a/Content.Server/GameObjects/Components/Weapon/Ranged/Barrels/RevolverBarrelComponent.cs b/Content.Server/GameObjects/Components/Weapon/Ranged/Barrels/RevolverBarrelComponent.cs index d45af23d24..0037bd7343 100644 --- a/Content.Server/GameObjects/Components/Weapon/Ranged/Barrels/RevolverBarrelComponent.cs +++ b/Content.Server/GameObjects/Components/Weapon/Ranged/Barrels/RevolverBarrelComponent.cs @@ -4,6 +4,7 @@ using Content.Server.GameObjects.Components.Weapon.Ranged.Ammunition; using Content.Shared.GameObjects; using Content.Shared.GameObjects.Components.Weapons.Ranged.Barrels; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; diff --git a/Content.Server/GameObjects/Components/Weapon/Ranged/Barrels/ServerBatteryBarrelComponent.cs b/Content.Server/GameObjects/Components/Weapon/Ranged/Barrels/ServerBatteryBarrelComponent.cs index 418c1bf93f..639ceae889 100644 --- a/Content.Server/GameObjects/Components/Weapon/Ranged/Barrels/ServerBatteryBarrelComponent.cs +++ b/Content.Server/GameObjects/Components/Weapon/Ranged/Barrels/ServerBatteryBarrelComponent.cs @@ -9,6 +9,7 @@ using Content.Shared.Damage; using Content.Shared.GameObjects; using Content.Shared.GameObjects.Components.Weapons.Ranged.Barrels; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces.GameObjects.Components; using Robust.Server.GameObjects; diff --git a/Content.Server/GameObjects/Components/Weapon/Ranged/Barrels/ServerMagazineBarrelComponent.cs b/Content.Server/GameObjects/Components/Weapon/Ranged/Barrels/ServerMagazineBarrelComponent.cs index 9d77992065..1f2b7acba8 100644 --- a/Content.Server/GameObjects/Components/Weapon/Ranged/Barrels/ServerMagazineBarrelComponent.cs +++ b/Content.Server/GameObjects/Components/Weapon/Ranged/Barrels/ServerMagazineBarrelComponent.cs @@ -8,6 +8,7 @@ using Content.Shared.GameObjects; using Content.Shared.GameObjects.Components.Weapons.Ranged; using Content.Shared.GameObjects.Components.Weapons.Ranged.Barrels; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameObjects.Verbs; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; diff --git a/Content.Server/GameObjects/Components/Weapon/Ranged/ServerRangedWeaponComponent.cs b/Content.Server/GameObjects/Components/Weapon/Ranged/ServerRangedWeaponComponent.cs index e8ea1a012a..f1331d4e7e 100644 --- a/Content.Server/GameObjects/Components/Weapon/Ranged/ServerRangedWeaponComponent.cs +++ b/Content.Server/GameObjects/Components/Weapon/Ranged/ServerRangedWeaponComponent.cs @@ -6,6 +6,7 @@ using Content.Shared.Damage; using Content.Shared.GameObjects.Components.Damage; using Content.Shared.GameObjects.Components.Weapons.Ranged; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Interfaces; using Content.Shared.Interfaces.GameObjects.Components; using Robust.Server.GameObjects.EntitySystems; diff --git a/Content.Server/GameObjects/EntitySystems/AI/Steering/AiSteeringSystem.cs b/Content.Server/GameObjects/EntitySystems/AI/Steering/AiSteeringSystem.cs index 4287f5d23f..2350ccb47b 100644 --- a/Content.Server/GameObjects/EntitySystems/AI/Steering/AiSteeringSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/AI/Steering/AiSteeringSystem.cs @@ -8,6 +8,7 @@ using Content.Server.GameObjects.EntitySystems.AI.Pathfinding; using Content.Server.GameObjects.EntitySystems.AI.Pathfinding.Pathfinders; using Content.Server.GameObjects.EntitySystems.JobQueues; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Utility; using Robust.Server.Interfaces.Timing; using Robust.Shared.GameObjects.Components; diff --git a/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs b/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs index f2ac56a7f7..08119c5363 100644 --- a/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/Click/InteractionSystem.cs @@ -11,6 +11,7 @@ using Content.Shared.GameObjects.Components.Inventory; using Content.Shared.GameObjects.Components.Items; using Content.Shared.GameObjects.EntitySystemMessages; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Input; using Content.Shared.Interfaces.GameObjects.Components; using Content.Shared.Utility; diff --git a/Content.Server/GameObjects/EntitySystems/ConstructionSystem.cs b/Content.Server/GameObjects/EntitySystems/ConstructionSystem.cs index 973c249a07..41640fa5b9 100644 --- a/Content.Server/GameObjects/EntitySystems/ConstructionSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/ConstructionSystem.cs @@ -11,6 +11,7 @@ using Content.Server.GameObjects.EntitySystems.DoAfter; using Content.Shared.Construction; using Content.Shared.GameObjects.Components; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Interfaces; using Content.Shared.Utility; using JetBrains.Annotations; diff --git a/Content.Server/GameObjects/EntitySystems/PointingSystem.cs b/Content.Server/GameObjects/EntitySystems/PointingSystem.cs index 84862a76db..016d92312e 100644 --- a/Content.Server/GameObjects/EntitySystems/PointingSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/PointingSystem.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using Content.Server.GameObjects.Components.Pointing; using Content.Server.Players; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Input; using Content.Shared.Interfaces; using Content.Shared.Utility; diff --git a/Content.Server/Interfaces/GameObjects/Components/Items/IHandsComponent.cs b/Content.Server/Interfaces/GameObjects/Components/Items/IHandsComponent.cs index 8de07084ff..c5fd4c9865 100644 --- a/Content.Server/Interfaces/GameObjects/Components/Items/IHandsComponent.cs +++ b/Content.Server/Interfaces/GameObjects/Components/Items/IHandsComponent.cs @@ -5,6 +5,7 @@ using System.Diagnostics.CodeAnalysis; using Content.Server.GameObjects.Components.Items.Storage; using Content.Shared.GameObjects.Components.Items; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Robust.Server.GameObjects.Components.Container; using Robust.Server.GameObjects.EntitySystemMessages; using Robust.Shared.Interfaces.GameObjects; diff --git a/Content.Server/Throw/ThrowHelper.cs b/Content.Server/Throw/ThrowHelper.cs index 300460f578..4d760383f7 100644 --- a/Content.Server/Throw/ThrowHelper.cs +++ b/Content.Server/Throw/ThrowHelper.cs @@ -2,6 +2,7 @@ using Content.Server.GameObjects.Components.Projectiles; using Content.Shared.GameObjects.Components.Movement; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Physics; using Robust.Shared.GameObjects.Components; using Robust.Shared.Interfaces.GameObjects; diff --git a/Content.Shared/GameObjects/Components/ActionBlocking/SharedCuffableComponent.cs b/Content.Shared/GameObjects/Components/ActionBlocking/SharedCuffableComponent.cs index ce5be9f0e6..188a3bd555 100644 --- a/Content.Shared/GameObjects/Components/ActionBlocking/SharedCuffableComponent.cs +++ b/Content.Shared/GameObjects/Components/ActionBlocking/SharedCuffableComponent.cs @@ -1,5 +1,6 @@ using System; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Robust.Shared.GameObjects; using Robust.Shared.Maths; using Robust.Shared.Serialization; diff --git a/Content.Shared/GameObjects/Components/Buckle/SharedBuckleComponent.cs b/Content.Shared/GameObjects/Components/Buckle/SharedBuckleComponent.cs index 068ce878c7..807c9035a0 100644 --- a/Content.Shared/GameObjects/Components/Buckle/SharedBuckleComponent.cs +++ b/Content.Shared/GameObjects/Components/Buckle/SharedBuckleComponent.cs @@ -2,6 +2,7 @@ using System; using Content.Shared.GameObjects.Components.Strap; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Interfaces.GameObjects.Components; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.ComponentDependencies; diff --git a/Content.Shared/GameObjects/Components/GUI/SharedStrippableComponent.cs b/Content.Shared/GameObjects/Components/GUI/SharedStrippableComponent.cs index 9b172820a4..77f41e77a4 100644 --- a/Content.Shared/GameObjects/Components/GUI/SharedStrippableComponent.cs +++ b/Content.Shared/GameObjects/Components/GUI/SharedStrippableComponent.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using Content.Shared.GameObjects.Components.Items; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Interfaces.GameObjects.Components; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Components.UserInterface; diff --git a/Content.Shared/GameObjects/Components/Mobs/SharedStunnableComponent.cs b/Content.Shared/GameObjects/Components/Mobs/SharedStunnableComponent.cs index 9620d186ae..794ab734be 100644 --- a/Content.Shared/GameObjects/Components/Mobs/SharedStunnableComponent.cs +++ b/Content.Shared/GameObjects/Components/Mobs/SharedStunnableComponent.cs @@ -3,6 +3,7 @@ using System.Threading; using Content.Shared.Alert; using Content.Shared.GameObjects.Components.Movement; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Interfaces.GameObjects.Components; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Components.Timers; diff --git a/Content.Shared/GameObjects/Components/Mobs/State/IMobState.cs b/Content.Shared/GameObjects/Components/Mobs/State/IMobState.cs index e17fa2f2b2..1cacbe57ab 100644 --- a/Content.Shared/GameObjects/Components/Mobs/State/IMobState.cs +++ b/Content.Shared/GameObjects/Components/Mobs/State/IMobState.cs @@ -1,4 +1,5 @@ using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.Serialization; diff --git a/Content.Shared/GameObjects/Components/Mobs/State/SharedMobStateComponent.cs b/Content.Shared/GameObjects/Components/Mobs/State/SharedMobStateComponent.cs index 784fd84c3a..4bcda6ac00 100644 --- a/Content.Shared/GameObjects/Components/Mobs/State/SharedMobStateComponent.cs +++ b/Content.Shared/GameObjects/Components/Mobs/State/SharedMobStateComponent.cs @@ -6,6 +6,7 @@ using System.Linq; using Content.Shared.Alert; using Content.Shared.GameObjects.Components.Damage; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Robust.Shared.GameObjects; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Serialization; diff --git a/Content.Shared/GameObjects/Components/Movement/SharedClimbingComponent.cs b/Content.Shared/GameObjects/Components/Movement/SharedClimbingComponent.cs index cf81cdd7ac..e55e599f63 100644 --- a/Content.Shared/GameObjects/Components/Movement/SharedClimbingComponent.cs +++ b/Content.Shared/GameObjects/Components/Movement/SharedClimbingComponent.cs @@ -1,5 +1,6 @@ using System; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Physics; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Components; diff --git a/Content.Shared/GameObjects/Components/Observer/SharedGhostComponent.cs b/Content.Shared/GameObjects/Components/Observer/SharedGhostComponent.cs index 9d17d1258e..3eebfdc8ae 100644 --- a/Content.Shared/GameObjects/Components/Observer/SharedGhostComponent.cs +++ b/Content.Shared/GameObjects/Components/Observer/SharedGhostComponent.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Robust.Shared.GameObjects; using Robust.Shared.Serialization; diff --git a/Content.Shared/GameObjects/Components/Storage/SharedStorageComponent.cs b/Content.Shared/GameObjects/Components/Storage/SharedStorageComponent.cs index 2bbdb8ffe1..2bdbc43363 100644 --- a/Content.Shared/GameObjects/Components/Storage/SharedStorageComponent.cs +++ b/Content.Shared/GameObjects/Components/Storage/SharedStorageComponent.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Linq; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Interfaces.GameObjects.Components; using Robust.Shared.GameObjects; using Robust.Shared.Interfaces.GameObjects; diff --git a/Content.Shared/GameObjects/EntitySystems/ActionBlocker/ActionBlockerExtensions.cs b/Content.Shared/GameObjects/EntitySystems/ActionBlocker/ActionBlockerExtensions.cs new file mode 100644 index 0000000000..c8052699d2 --- /dev/null +++ b/Content.Shared/GameObjects/EntitySystems/ActionBlocker/ActionBlockerExtensions.cs @@ -0,0 +1,77 @@ +using Robust.Shared.Interfaces.GameObjects; + +namespace Content.Shared.GameObjects.EntitySystems.ActionBlocker +{ + public static class ActionBlockerExtensions + { + public static bool CanMove(this IEntity entity) + { + return ActionBlockerSystem.CanMove(entity); + } + + public static bool CanInteract(this IEntity entity) + { + return ActionBlockerSystem.CanInteract(entity); + } + + public static bool CanUse(this IEntity entity) + { + return ActionBlockerSystem.CanUse(entity); + } + + public static bool CanThrow(this IEntity entity) + { + return ActionBlockerSystem.CanThrow(entity); + } + + public static bool CanSpeak(this IEntity entity) + { + return ActionBlockerSystem.CanSpeak(entity); + } + + public static bool CanDrop(this IEntity entity) + { + return ActionBlockerSystem.CanDrop(entity); + } + + public static bool CanPickup(this IEntity entity) + { + return ActionBlockerSystem.CanPickup(entity); + } + + public static bool CanEmote(this IEntity entity) + { + return ActionBlockerSystem.CanEmote(entity); + } + + public static bool CanAttack(this IEntity entity) + { + return ActionBlockerSystem.CanAttack(entity); + } + + public static bool CanEquip(this IEntity entity) + { + return ActionBlockerSystem.CanEquip(entity); + } + + public static bool CanUnequip(this IEntity entity) + { + return ActionBlockerSystem.CanUnequip(entity); + } + + public static bool CanChangeDirection(this IEntity entity) + { + return ActionBlockerSystem.CanChangeDirection(entity); + } + + public static bool CanShiver(this IEntity entity) + { + return ActionBlockerSystem.CanShiver(entity); + } + + public static bool CanSweat(this IEntity entity) + { + return ActionBlockerSystem.CanSweat(entity); + } + } +} diff --git a/Content.Shared/GameObjects/EntitySystems/ActionBlocker/ActionBlockerSystem.cs b/Content.Shared/GameObjects/EntitySystems/ActionBlocker/ActionBlockerSystem.cs new file mode 100644 index 0000000000..094ef7b8fa --- /dev/null +++ b/Content.Shared/GameObjects/EntitySystems/ActionBlocker/ActionBlockerSystem.cs @@ -0,0 +1,178 @@ +using JetBrains.Annotations; +using Robust.Shared.GameObjects.Systems; +using Robust.Shared.Interfaces.GameObjects; + +namespace Content.Shared.GameObjects.EntitySystems.ActionBlocker +{ + /// + /// Utility methods to check if a specific entity is allowed to perform an action. + /// For effects see + /// + [UsedImplicitly] + public class ActionBlockerSystem : EntitySystem + { + public static bool CanMove(IEntity entity) + { + var canMove = true; + + foreach (var blockers in entity.GetAllComponents()) + { + canMove &= blockers.CanMove(); // Sets var to false if false + } + + return canMove; + } + + public static bool CanInteract(IEntity entity) + { + var canInteract = true; + + foreach (var blockers in entity.GetAllComponents()) + { + canInteract &= blockers.CanInteract(); + } + + return canInteract; + } + + public static bool CanUse(IEntity entity) + { + var canUse = true; + + foreach (var blockers in entity.GetAllComponents()) + { + canUse &= blockers.CanUse(); + } + + return canUse; + } + + public static bool CanThrow(IEntity entity) + { + var canThrow = true; + + foreach (var blockers in entity.GetAllComponents()) + { + canThrow &= blockers.CanThrow(); + } + + return canThrow; + } + + public static bool CanSpeak(IEntity entity) + { + var canSpeak = true; + + foreach (var blockers in entity.GetAllComponents()) + { + canSpeak &= blockers.CanSpeak(); + } + + return canSpeak; + } + + public static bool CanDrop(IEntity entity) + { + var canDrop = true; + + foreach (var blockers in entity.GetAllComponents()) + { + canDrop &= blockers.CanDrop(); + } + + return canDrop; + } + + public static bool CanPickup(IEntity entity) + { + var canPickup = true; + + foreach (var blockers in entity.GetAllComponents()) + { + canPickup &= blockers.CanPickup(); + } + + return canPickup; + } + + public static bool CanEmote(IEntity entity) + { + var canEmote = true; + + foreach (var blockers in entity.GetAllComponents()) + { + canEmote &= blockers.CanEmote(); + } + + return canEmote; + } + + public static bool CanAttack(IEntity entity) + { + var canAttack = true; + + foreach (var blockers in entity.GetAllComponents()) + { + canAttack &= blockers.CanAttack(); + } + + return canAttack; + } + + public static bool CanEquip(IEntity entity) + { + var canEquip = true; + + foreach (var blockers in entity.GetAllComponents()) + { + canEquip &= blockers.CanEquip(); + } + + return canEquip; + } + + public static bool CanUnequip(IEntity entity) + { + var canUnequip = true; + + foreach (var blockers in entity.GetAllComponents()) + { + canUnequip &= blockers.CanUnequip(); + } + + return canUnequip; + } + + public static bool CanChangeDirection(IEntity entity) + { + var canChangeDirection = true; + + foreach (var blockers in entity.GetAllComponents()) + { + canChangeDirection &= blockers.CanChangeDirection(); + } + + return canChangeDirection; + } + + public static bool CanShiver(IEntity entity) + { + var canShiver = true; + foreach (var component in entity.GetAllComponents()) + { + canShiver &= component.CanShiver(); + } + return canShiver; + } + + public static bool CanSweat(IEntity entity) + { + var canSweat = true; + foreach (var component in entity.GetAllComponents()) + { + canSweat &= component.CanSweat(); + } + return canSweat; + } + } +} diff --git a/Content.Shared/GameObjects/EntitySystems/ActionBlocker/IActionBlocker.cs b/Content.Shared/GameObjects/EntitySystems/ActionBlocker/IActionBlocker.cs new file mode 100644 index 0000000000..0c47f44dca --- /dev/null +++ b/Content.Shared/GameObjects/EntitySystems/ActionBlocker/IActionBlocker.cs @@ -0,0 +1,37 @@ +namespace Content.Shared.GameObjects.EntitySystems.ActionBlocker +{ + /// + /// This interface gives components the ability to block certain actions from + /// being done by the owning entity. For effects see + /// + public interface IActionBlocker + { + bool CanMove() => true; + + bool CanInteract() => true; + + bool CanUse() => true; + + bool CanThrow() => true; + + bool CanSpeak() => true; + + bool CanDrop() => true; + + bool CanPickup() => true; + + bool CanEmote() => true; + + bool CanAttack() => true; + + bool CanEquip() => true; + + bool CanUnequip() => true; + + bool CanChangeDirection() => true; + + bool CanShiver() => true; + + bool CanSweat() => true; + } +} \ No newline at end of file diff --git a/Content.Shared/GameObjects/EntitySystems/ActionBlockerSystem.cs b/Content.Shared/GameObjects/EntitySystems/ActionBlockerSystem.cs deleted file mode 100644 index b0fc6baf20..0000000000 --- a/Content.Shared/GameObjects/EntitySystems/ActionBlockerSystem.cs +++ /dev/null @@ -1,195 +0,0 @@ -using Robust.Shared.GameObjects.Systems; -using Robust.Shared.Interfaces.GameObjects; - -namespace Content.Shared.GameObjects.EntitySystems -{ - /// - /// This interface gives components the ability to block certain actions from - /// being done by the owning entity. For effects see - /// - public interface IActionBlocker - { - bool CanMove() => true; - bool CanInteract() => true; - bool CanUse() => true; - bool CanThrow() => true; - bool CanSpeak() => true; - bool CanDrop() => true; - bool CanPickup() => true; - bool CanEmote() => true; - bool CanAttack() => true; - - bool CanEquip() => true; - - bool CanUnequip() => true; - - bool CanChangeDirection() => true; - - bool CanShiver() => true; - bool CanSweat() => true; - } - - /// - /// Utility methods to check if a specific entity is allowed to perform an action. - /// For effects see - /// - public class ActionBlockerSystem : EntitySystem - { - public static bool CanMove(IEntity entity) - { - bool canmove = true; - foreach (var actionblockercomponents in entity.GetAllComponents()) - { - canmove &= actionblockercomponents.CanMove(); // Sets var to false if false - } - - return canmove; - } - - public static bool CanInteract(IEntity entity) - { - bool caninteract = true; - foreach (var actionblockercomponents in entity.GetAllComponents()) - { - caninteract &= actionblockercomponents.CanInteract(); - } - - return caninteract; - } - - public static bool CanUse(IEntity entity) - { - bool canuse = true; - foreach (var actionblockercomponents in entity.GetAllComponents()) - { - canuse &= actionblockercomponents.CanUse(); - } - - return canuse; - } - - public static bool CanThrow(IEntity entity) - { - bool canthrow = true; - foreach (var actionblockercomponents in entity.GetAllComponents()) - { - canthrow &= actionblockercomponents.CanThrow(); - } - - return canthrow; - } - - public static bool CanSpeak(IEntity entity) - { - bool canspeak = true; - foreach (var actionblockercomponents in entity.GetAllComponents()) - { - canspeak &= actionblockercomponents.CanSpeak(); - } - - return canspeak; - } - - public static bool CanDrop(IEntity entity) - { - bool candrop = true; - foreach (var actionblockercomponents in entity.GetAllComponents()) - { - candrop &= actionblockercomponents.CanDrop(); - } - - return candrop; - } - - public static bool CanPickup(IEntity entity) - { - bool canpickup = true; - foreach (var actionblockercomponents in entity.GetAllComponents()) - { - canpickup &= actionblockercomponents.CanPickup(); - } - - return canpickup; - } - - public static bool CanEmote(IEntity entity) - { - bool canemote = true; - - foreach (var actionblockercomponents in entity.GetAllComponents()) - { - canemote &= actionblockercomponents.CanEmote(); - } - - return canemote; - } - - public static bool CanAttack(IEntity entity) - { - bool canattack = true; - - foreach (var actionblockercomponents in entity.GetAllComponents()) - { - canattack &= actionblockercomponents.CanAttack(); - } - - return canattack; - } - - public static bool CanEquip(IEntity entity) - { - bool canequip = true; - - foreach (var actionblockercomponents in entity.GetAllComponents()) - { - canequip &= actionblockercomponents.CanEquip(); - } - - return canequip; - } - - public static bool CanUnequip(IEntity entity) - { - bool canunequip = true; - - foreach (var actionblockercomponents in entity.GetAllComponents()) - { - canunequip &= actionblockercomponents.CanUnequip(); - } - - return canunequip; - } - - public static bool CanChangeDirection(IEntity entity) - { - bool canchangedirection = true; - - foreach (var actionblockercomponents in entity.GetAllComponents()) - { - canchangedirection &= actionblockercomponents.CanChangeDirection(); - } - - return canchangedirection; - } - - public static bool CanShiver(IEntity entity) - { - var canShiver = true; - foreach (var component in entity.GetAllComponents()) - { - canShiver &= component.CanShiver(); - } - return canShiver; - } - - public static bool CanSweat(IEntity entity) - { - var canSweat = true; - foreach (var component in entity.GetAllComponents()) - { - canSweat &= component.CanSweat(); - } - return canSweat; - } - } -} diff --git a/Content.Shared/GameObjects/EntitySystems/EffectBlockerSystem.cs b/Content.Shared/GameObjects/EntitySystems/EffectBlockerSystem.cs index c7e003f03a..2458dfd847 100644 --- a/Content.Shared/GameObjects/EntitySystems/EffectBlockerSystem.cs +++ b/Content.Shared/GameObjects/EntitySystems/EffectBlockerSystem.cs @@ -1,4 +1,5 @@ -using Robust.Shared.GameObjects.Systems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; +using Robust.Shared.GameObjects.Systems; using Robust.Shared.Interfaces.GameObjects; namespace Content.Shared.GameObjects.EntitySystems diff --git a/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs b/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs index 7a8f266e9c..127cd56b8a 100644 --- a/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs +++ b/Content.Shared/GameObjects/EntitySystems/SharedMoverSystem.cs @@ -2,6 +2,7 @@ using System.Diagnostics.CodeAnalysis; using Content.Shared.GameObjects.Components.Items; using Content.Shared.GameObjects.Components.Movement; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.Physics; using Content.Shared.Physics.Pull; using Robust.Shared.Configuration; diff --git a/Content.Shared/Physics/ThrowKnockbackController.cs b/Content.Shared/Physics/ThrowKnockbackController.cs index d6bf507174..0b11cab2a3 100644 --- a/Content.Shared/Physics/ThrowKnockbackController.cs +++ b/Content.Shared/Physics/ThrowKnockbackController.cs @@ -1,5 +1,6 @@ using Content.Shared.GameObjects.Components.Movement; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Robust.Shared.Interfaces.Physics; using Robust.Shared.IoC; using Robust.Shared.Maths; From a3fdcd3a681a6f6077aab21d79828f0b7136350c Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Sun, 20 Dec 2020 04:31:04 +0100 Subject: [PATCH 23/29] Add EffectBlockerExtensions --- .../Tests/Buckle/BuckleTest.cs | 1 + .../Components/GUI/InventoryComponent.cs | 1 + .../Components/Movement/NoSlipComponent.cs | 1 + .../Buckle/SharedBuckleComponent.cs | 1 + .../Movement/SharedSlipperyComponent.cs | 1 + .../ActionBlocker/ActionBlockerSystem.cs | 51 ++++++++++--------- .../ActionBlocker/IActionBlocker.cs | 6 ++- .../EffectBlocker/EffectBlockerExtensions.cs | 17 +++++++ .../EffectBlockerSystem.cs | 16 ++---- .../EffectBlocker/IEffectBlocker.cs | 14 +++++ .../SharedStandingStateSystem.cs | 1 + 11 files changed, 72 insertions(+), 38 deletions(-) create mode 100644 Content.Shared/GameObjects/EntitySystems/EffectBlocker/EffectBlockerExtensions.cs rename Content.Shared/GameObjects/EntitySystems/{ => EffectBlocker}/EffectBlockerSystem.cs (73%) create mode 100644 Content.Shared/GameObjects/EntitySystems/EffectBlocker/IEffectBlocker.cs diff --git a/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs b/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs index b6918abae8..2bf519db3f 100644 --- a/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs +++ b/Content.IntegrationTests/Tests/Buckle/BuckleTest.cs @@ -8,6 +8,7 @@ using Content.Shared.GameObjects.Components.Body.Part; using Content.Shared.GameObjects.Components.Buckle; using Content.Shared.GameObjects.EntitySystems; using Content.Shared.GameObjects.EntitySystems.ActionBlocker; +using Content.Shared.GameObjects.EntitySystems.EffectBlocker; using Content.Shared.Utility; using NUnit.Framework; using Robust.Shared.Interfaces.GameObjects; diff --git a/Content.Server/GameObjects/Components/GUI/InventoryComponent.cs b/Content.Server/GameObjects/Components/GUI/InventoryComponent.cs index 593fdf7e80..2ef74a187e 100644 --- a/Content.Server/GameObjects/Components/GUI/InventoryComponent.cs +++ b/Content.Server/GameObjects/Components/GUI/InventoryComponent.cs @@ -8,6 +8,7 @@ using Content.Server.Interfaces.GameObjects; using Content.Shared.GameObjects.Components.Inventory; using Content.Shared.GameObjects.EntitySystems; using Content.Shared.GameObjects.EntitySystems.ActionBlocker; +using Content.Shared.GameObjects.EntitySystems.EffectBlocker; using Content.Shared.Interfaces; using Robust.Server.GameObjects.Components.Container; using Robust.Shared.Containers; diff --git a/Content.Server/GameObjects/Components/Movement/NoSlipComponent.cs b/Content.Server/GameObjects/Components/Movement/NoSlipComponent.cs index c541377f4b..0e40b39bed 100644 --- a/Content.Server/GameObjects/Components/Movement/NoSlipComponent.cs +++ b/Content.Server/GameObjects/Components/Movement/NoSlipComponent.cs @@ -1,4 +1,5 @@ using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.EffectBlocker; using Robust.Shared.GameObjects; namespace Content.Server.GameObjects.Components.Movement diff --git a/Content.Shared/GameObjects/Components/Buckle/SharedBuckleComponent.cs b/Content.Shared/GameObjects/Components/Buckle/SharedBuckleComponent.cs index 807c9035a0..a78bd4a35c 100644 --- a/Content.Shared/GameObjects/Components/Buckle/SharedBuckleComponent.cs +++ b/Content.Shared/GameObjects/Components/Buckle/SharedBuckleComponent.cs @@ -3,6 +3,7 @@ using System; using Content.Shared.GameObjects.Components.Strap; using Content.Shared.GameObjects.EntitySystems; using Content.Shared.GameObjects.EntitySystems.ActionBlocker; +using Content.Shared.GameObjects.EntitySystems.EffectBlocker; using Content.Shared.Interfaces.GameObjects.Components; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.ComponentDependencies; diff --git a/Content.Shared/GameObjects/Components/Movement/SharedSlipperyComponent.cs b/Content.Shared/GameObjects/Components/Movement/SharedSlipperyComponent.cs index 6e79a32faa..de3b2bdd8f 100644 --- a/Content.Shared/GameObjects/Components/Movement/SharedSlipperyComponent.cs +++ b/Content.Shared/GameObjects/Components/Movement/SharedSlipperyComponent.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using Content.Shared.GameObjects.Components.Mobs; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.EffectBlocker; using Content.Shared.Physics; using Robust.Shared.Containers; using Robust.Shared.GameObjects; diff --git a/Content.Shared/GameObjects/EntitySystems/ActionBlocker/ActionBlockerSystem.cs b/Content.Shared/GameObjects/EntitySystems/ActionBlocker/ActionBlockerSystem.cs index 094ef7b8fa..63367caa19 100644 --- a/Content.Shared/GameObjects/EntitySystems/ActionBlocker/ActionBlockerSystem.cs +++ b/Content.Shared/GameObjects/EntitySystems/ActionBlocker/ActionBlockerSystem.cs @@ -1,4 +1,5 @@ -using JetBrains.Annotations; +using Content.Shared.GameObjects.EntitySystems.EffectBlocker; +using JetBrains.Annotations; using Robust.Shared.GameObjects.Systems; using Robust.Shared.Interfaces.GameObjects; @@ -15,9 +16,9 @@ namespace Content.Shared.GameObjects.EntitySystems.ActionBlocker { var canMove = true; - foreach (var blockers in entity.GetAllComponents()) + foreach (var blocker in entity.GetAllComponents()) { - canMove &= blockers.CanMove(); // Sets var to false if false + canMove &= blocker.CanMove(); // Sets var to false if false } return canMove; @@ -27,9 +28,9 @@ namespace Content.Shared.GameObjects.EntitySystems.ActionBlocker { var canInteract = true; - foreach (var blockers in entity.GetAllComponents()) + foreach (var blocker in entity.GetAllComponents()) { - canInteract &= blockers.CanInteract(); + canInteract &= blocker.CanInteract(); } return canInteract; @@ -39,9 +40,9 @@ namespace Content.Shared.GameObjects.EntitySystems.ActionBlocker { var canUse = true; - foreach (var blockers in entity.GetAllComponents()) + foreach (var blocker in entity.GetAllComponents()) { - canUse &= blockers.CanUse(); + canUse &= blocker.CanUse(); } return canUse; @@ -51,9 +52,9 @@ namespace Content.Shared.GameObjects.EntitySystems.ActionBlocker { var canThrow = true; - foreach (var blockers in entity.GetAllComponents()) + foreach (var blocker in entity.GetAllComponents()) { - canThrow &= blockers.CanThrow(); + canThrow &= blocker.CanThrow(); } return canThrow; @@ -63,9 +64,9 @@ namespace Content.Shared.GameObjects.EntitySystems.ActionBlocker { var canSpeak = true; - foreach (var blockers in entity.GetAllComponents()) + foreach (var blocker in entity.GetAllComponents()) { - canSpeak &= blockers.CanSpeak(); + canSpeak &= blocker.CanSpeak(); } return canSpeak; @@ -75,9 +76,9 @@ namespace Content.Shared.GameObjects.EntitySystems.ActionBlocker { var canDrop = true; - foreach (var blockers in entity.GetAllComponents()) + foreach (var blocker in entity.GetAllComponents()) { - canDrop &= blockers.CanDrop(); + canDrop &= blocker.CanDrop(); } return canDrop; @@ -87,9 +88,9 @@ namespace Content.Shared.GameObjects.EntitySystems.ActionBlocker { var canPickup = true; - foreach (var blockers in entity.GetAllComponents()) + foreach (var blocker in entity.GetAllComponents()) { - canPickup &= blockers.CanPickup(); + canPickup &= blocker.CanPickup(); } return canPickup; @@ -99,9 +100,9 @@ namespace Content.Shared.GameObjects.EntitySystems.ActionBlocker { var canEmote = true; - foreach (var blockers in entity.GetAllComponents()) + foreach (var blocker in entity.GetAllComponents()) { - canEmote &= blockers.CanEmote(); + canEmote &= blocker.CanEmote(); } return canEmote; @@ -111,9 +112,9 @@ namespace Content.Shared.GameObjects.EntitySystems.ActionBlocker { var canAttack = true; - foreach (var blockers in entity.GetAllComponents()) + foreach (var blocker in entity.GetAllComponents()) { - canAttack &= blockers.CanAttack(); + canAttack &= blocker.CanAttack(); } return canAttack; @@ -123,9 +124,9 @@ namespace Content.Shared.GameObjects.EntitySystems.ActionBlocker { var canEquip = true; - foreach (var blockers in entity.GetAllComponents()) + foreach (var blocker in entity.GetAllComponents()) { - canEquip &= blockers.CanEquip(); + canEquip &= blocker.CanEquip(); } return canEquip; @@ -135,9 +136,9 @@ namespace Content.Shared.GameObjects.EntitySystems.ActionBlocker { var canUnequip = true; - foreach (var blockers in entity.GetAllComponents()) + foreach (var blocker in entity.GetAllComponents()) { - canUnequip &= blockers.CanUnequip(); + canUnequip &= blocker.CanUnequip(); } return canUnequip; @@ -147,9 +148,9 @@ namespace Content.Shared.GameObjects.EntitySystems.ActionBlocker { var canChangeDirection = true; - foreach (var blockers in entity.GetAllComponents()) + foreach (var blocker in entity.GetAllComponents()) { - canChangeDirection &= blockers.CanChangeDirection(); + canChangeDirection &= blocker.CanChangeDirection(); } return canChangeDirection; diff --git a/Content.Shared/GameObjects/EntitySystems/ActionBlocker/IActionBlocker.cs b/Content.Shared/GameObjects/EntitySystems/ActionBlocker/IActionBlocker.cs index 0c47f44dca..8d23ceea0d 100644 --- a/Content.Shared/GameObjects/EntitySystems/ActionBlocker/IActionBlocker.cs +++ b/Content.Shared/GameObjects/EntitySystems/ActionBlocker/IActionBlocker.cs @@ -1,4 +1,6 @@ -namespace Content.Shared.GameObjects.EntitySystems.ActionBlocker +using Content.Shared.GameObjects.EntitySystems.EffectBlocker; + +namespace Content.Shared.GameObjects.EntitySystems.ActionBlocker { /// /// This interface gives components the ability to block certain actions from @@ -34,4 +36,4 @@ bool CanSweat() => true; } -} \ No newline at end of file +} diff --git a/Content.Shared/GameObjects/EntitySystems/EffectBlocker/EffectBlockerExtensions.cs b/Content.Shared/GameObjects/EntitySystems/EffectBlocker/EffectBlockerExtensions.cs new file mode 100644 index 0000000000..842695f3ec --- /dev/null +++ b/Content.Shared/GameObjects/EntitySystems/EffectBlocker/EffectBlockerExtensions.cs @@ -0,0 +1,17 @@ +using Robust.Shared.Interfaces.GameObjects; + +namespace Content.Shared.GameObjects.EntitySystems.EffectBlocker +{ + public static class EffectBlockerExtensions + { + public static bool CanFall(this IEntity entity) + { + return EffectBlockerSystem.CanFall(entity); + } + + public static bool CanSlip(this IEntity entity) + { + return EffectBlockerSystem.CanSlip(entity); + } + } +} diff --git a/Content.Shared/GameObjects/EntitySystems/EffectBlockerSystem.cs b/Content.Shared/GameObjects/EntitySystems/EffectBlocker/EffectBlockerSystem.cs similarity index 73% rename from Content.Shared/GameObjects/EntitySystems/EffectBlockerSystem.cs rename to Content.Shared/GameObjects/EntitySystems/EffectBlocker/EffectBlockerSystem.cs index 2458dfd847..215630014c 100644 --- a/Content.Shared/GameObjects/EntitySystems/EffectBlockerSystem.cs +++ b/Content.Shared/GameObjects/EntitySystems/EffectBlocker/EffectBlockerSystem.cs @@ -1,28 +1,21 @@ using Content.Shared.GameObjects.EntitySystems.ActionBlocker; +using JetBrains.Annotations; using Robust.Shared.GameObjects.Systems; using Robust.Shared.Interfaces.GameObjects; -namespace Content.Shared.GameObjects.EntitySystems +namespace Content.Shared.GameObjects.EntitySystems.EffectBlocker { - /// - /// This interface gives components the ability to block certain effects - /// from affecting the owning entity. For actions see - /// - public interface IEffectBlocker - { - bool CanFall() => true; - bool CanSlip() => true; - } - /// /// Utility methods to check if an effect is allowed to affect a specific entity. /// For actions see /// + [UsedImplicitly] public class EffectBlockerSystem : EntitySystem { public static bool CanFall(IEntity entity) { var canFall = true; + foreach (var blocker in entity.GetAllComponents()) { canFall &= blocker.CanFall(); // Sets var to false if false @@ -34,6 +27,7 @@ namespace Content.Shared.GameObjects.EntitySystems public static bool CanSlip(IEntity entity) { var canSlip = true; + foreach (var blocker in entity.GetAllComponents()) { canSlip &= blocker.CanSlip(); // Sets var to false if false diff --git a/Content.Shared/GameObjects/EntitySystems/EffectBlocker/IEffectBlocker.cs b/Content.Shared/GameObjects/EntitySystems/EffectBlocker/IEffectBlocker.cs new file mode 100644 index 0000000000..5cce28829d --- /dev/null +++ b/Content.Shared/GameObjects/EntitySystems/EffectBlocker/IEffectBlocker.cs @@ -0,0 +1,14 @@ +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; + +namespace Content.Shared.GameObjects.EntitySystems.EffectBlocker +{ + /// + /// This interface gives components the ability to block certain effects + /// from affecting the owning entity. For actions see + /// + public interface IEffectBlocker + { + bool CanFall() => true; + bool CanSlip() => true; + } +} diff --git a/Content.Shared/GameObjects/EntitySystems/SharedStandingStateSystem.cs b/Content.Shared/GameObjects/EntitySystems/SharedStandingStateSystem.cs index 9526b5414a..46fb1dec2e 100644 --- a/Content.Shared/GameObjects/EntitySystems/SharedStandingStateSystem.cs +++ b/Content.Shared/GameObjects/EntitySystems/SharedStandingStateSystem.cs @@ -1,3 +1,4 @@ +using Content.Shared.GameObjects.EntitySystems.EffectBlocker; using Robust.Shared.GameObjects.Systems; using Robust.Shared.Interfaces.GameObjects; From 0172613a7deabe4a16ded890203b52d9b336543a Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Sun, 20 Dec 2020 04:31:39 +0100 Subject: [PATCH 24/29] Remove wireless surgery (#2785) * Remove wireless surgery * Change surgery window title to Surgery * Remove todo * Check only tools with a window open --- .../Components/Body/Surgery/SurgeryWindow.cs | 2 +- .../Messages/SurgeryWindowCloseMessage.cs | 12 +++ .../Messages/SurgeryWindowOpenMessage.cs | 14 ++++ .../Body/Surgery/SurgeryToolComponent.cs | 79 +++++++++++-------- .../Body/Surgery/SurgeryToolSystem.cs | 64 +++++++++++++++ 5 files changed, 136 insertions(+), 35 deletions(-) create mode 100644 Content.Server/GameObjects/Components/Body/Surgery/Messages/SurgeryWindowCloseMessage.cs create mode 100644 Content.Server/GameObjects/Components/Body/Surgery/Messages/SurgeryWindowOpenMessage.cs create mode 100644 Content.Server/GameObjects/EntitySystems/Body/Surgery/SurgeryToolSystem.cs diff --git a/Content.Client/GameObjects/Components/Body/Surgery/SurgeryWindow.cs b/Content.Client/GameObjects/Components/Body/Surgery/SurgeryWindow.cs index d380569b46..656aeda4a7 100644 --- a/Content.Client/GameObjects/Components/Body/Surgery/SurgeryWindow.cs +++ b/Content.Client/GameObjects/Components/Body/Surgery/SurgeryWindow.cs @@ -19,7 +19,7 @@ namespace Content.Client.GameObjects.Components.Body.Surgery public SurgeryWindow() { - Title = Loc.GetString("Select surgery target..."); + Title = Loc.GetString("Surgery"); RectClipContent = true; var vSplitContainer = new VBoxContainer diff --git a/Content.Server/GameObjects/Components/Body/Surgery/Messages/SurgeryWindowCloseMessage.cs b/Content.Server/GameObjects/Components/Body/Surgery/Messages/SurgeryWindowCloseMessage.cs new file mode 100644 index 0000000000..e149aa40d4 --- /dev/null +++ b/Content.Server/GameObjects/Components/Body/Surgery/Messages/SurgeryWindowCloseMessage.cs @@ -0,0 +1,12 @@ +namespace Content.Server.GameObjects.Components.Body.Surgery.Messages +{ + public class SurgeryWindowCloseMessage + { + public SurgeryWindowCloseMessage(SurgeryToolComponent tool) + { + Tool = tool; + } + + public SurgeryToolComponent Tool { get; } + } +} diff --git a/Content.Server/GameObjects/Components/Body/Surgery/Messages/SurgeryWindowOpenMessage.cs b/Content.Server/GameObjects/Components/Body/Surgery/Messages/SurgeryWindowOpenMessage.cs new file mode 100644 index 0000000000..5b79acb0a6 --- /dev/null +++ b/Content.Server/GameObjects/Components/Body/Surgery/Messages/SurgeryWindowOpenMessage.cs @@ -0,0 +1,14 @@ +using Robust.Shared.GameObjects; + +namespace Content.Server.GameObjects.Components.Body.Surgery.Messages +{ + public class SurgeryWindowOpenMessage : ComponentMessage + { + public SurgeryWindowOpenMessage(SurgeryToolComponent tool) + { + Tool = tool; + } + + public SurgeryToolComponent Tool { get; } + } +} diff --git a/Content.Server/GameObjects/Components/Body/Surgery/SurgeryToolComponent.cs b/Content.Server/GameObjects/Components/Body/Surgery/SurgeryToolComponent.cs index 7173bde58f..ac1aaa3ad7 100644 --- a/Content.Server/GameObjects/Components/Body/Surgery/SurgeryToolComponent.cs +++ b/Content.Server/GameObjects/Components/Body/Surgery/SurgeryToolComponent.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; +using Content.Server.GameObjects.Components.Body.Surgery.Messages; using Content.Server.Utility; using Content.Shared.GameObjects; using Content.Shared.GameObjects.Components.Body; @@ -37,18 +38,18 @@ namespace Content.Server.GameObjects.Components.Body.Surgery private float _baseOperateTime; - private IBody? _bodyCache; - private ISurgeon.MechanismRequestCallback? _callbackCache; private int _idHash; - private IEntity? _performerCache; - private SurgeryType _surgeryType; [ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(SurgeryUIKey.Key); + public IBody? BodyCache { get; private set; } + + public IEntity? PerformerCache { get; private set; } + async Task IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs) { if (eventArgs.Target == null) @@ -62,11 +63,6 @@ namespace Content.Server.GameObjects.Components.Body.Surgery } CloseAllSurgeryUIs(); - _optionsCache.Clear(); - - _performerCache = null; - _bodyCache = null; - _callbackCache = null; // Attempt surgery on a body by sending a list of operable parts for the client to choose from if (eventArgs.Target.TryGetComponent(out IBody? body)) @@ -88,8 +84,8 @@ namespace Content.Server.GameObjects.Components.Body.Surgery { OpenSurgeryUI(actor.playerSession); UpdateSurgeryUIBodyPartRequest(actor.playerSession, toSend); - _performerCache = eventArgs.User; // Also, cache the data. - _bodyCache = body; + PerformerCache = eventArgs.User; // Also, cache the data. + BodyCache = body; } else // If surgery cannot be performed, show message saying so. { @@ -99,7 +95,7 @@ namespace Content.Server.GameObjects.Components.Body.Surgery else if (eventArgs.Target.TryGetComponent(out var part)) { // Attempt surgery on a DroppedBodyPart - there's only one possible target so no need for selection UI - _performerCache = eventArgs.User; + PerformerCache = eventArgs.User; // If surgery can be performed... if (!part.SurgeryCheck(_surgeryType)) @@ -132,10 +128,10 @@ namespace Content.Server.GameObjects.Components.Body.Surgery toSend.Add(mechanism.Name, _idHash++); } - if (_optionsCache.Count > 0 && _performerCache != null) + if (_optionsCache.Count > 0 && PerformerCache != null) { - OpenSurgeryUI(_performerCache.GetComponent().playerSession); - UpdateSurgeryUIMechanismRequest(_performerCache.GetComponent().playerSession, + OpenSurgeryUI(PerformerCache.GetComponent().playerSession); + UpdateSurgeryUIMechanismRequest(PerformerCache.GetComponent().playerSession, toSend); _callbackCache = callback; } @@ -146,6 +142,14 @@ namespace Content.Server.GameObjects.Components.Body.Surgery } } + public override void ExposeData(ObjectSerializer serializer) + { + base.ExposeData(serializer); + + serializer.DataField(ref _surgeryType, "surgeryType", SurgeryType.Incision); + serializer.DataField(ref _baseOperateTime, "baseOperateTime", 5); + } + public override void Initialize() { base.Initialize(); @@ -156,10 +160,14 @@ namespace Content.Server.GameObjects.Components.Body.Surgery } } - // TODO BODY add checks to close UI if user walks too far away from tool or target. private void OpenSurgeryUI(IPlayerSession session) { UserInterface?.Open(session); + + var message = new SurgeryWindowOpenMessage(this); + + SendMessage(message); + Owner.EntityManager.EventBus.RaiseEvent(EventSource.Local, message); } private void UpdateSurgeryUIBodyPartRequest(IPlayerSession session, Dictionary options) @@ -172,14 +180,25 @@ namespace Content.Server.GameObjects.Components.Body.Surgery UserInterface?.SendMessage(new RequestMechanismSurgeryUIMessage(options), session); } + private void ClearUIData() + { + _optionsCache.Clear(); + + PerformerCache = null; + BodyCache = null; + _callbackCache = null; + } + private void CloseSurgeryUI(IPlayerSession session) { UserInterface?.Close(session); + ClearUIData(); } - private void CloseAllSurgeryUIs() + public void CloseAllSurgeryUIs() { UserInterface?.CloseAll(); + ClearUIData(); } private void UserInterfaceOnOnReceiveMessage(ServerBoundUserInterfaceMessage message) @@ -201,8 +220,8 @@ namespace Content.Server.GameObjects.Components.Body.Surgery /// private void HandleReceiveBodyPart(int key) { - if (_performerCache == null || - !_performerCache.TryGetComponent(out IActorComponent? actor)) + if (PerformerCache == null || + !PerformerCache.TryGetComponent(out IActorComponent? actor)) { return; } @@ -210,7 +229,7 @@ namespace Content.Server.GameObjects.Components.Body.Surgery CloseSurgeryUI(actor.playerSession); // TODO: sanity checks to see whether user is in range, user is still able-bodied, target is still the same, etc etc if (!_optionsCache.TryGetValue(key, out var targetObject) || - _bodyCache == null) + BodyCache == null) { NotUsefulAnymorePopup(); return; @@ -219,7 +238,7 @@ namespace Content.Server.GameObjects.Components.Body.Surgery var target = (IBodyPart) targetObject!; // TODO BODY Reconsider - if (!target.AttemptSurgery(_surgeryType, _bodyCache, this, _performerCache)) + if (!target.AttemptSurgery(_surgeryType, BodyCache, this, PerformerCache)) { NotUsefulAnymorePopup(); } @@ -233,8 +252,8 @@ namespace Content.Server.GameObjects.Components.Body.Surgery { // TODO: sanity checks to see whether user is in range, user is still able-bodied, target is still the same, etc etc if (!_optionsCache.TryGetValue(key, out var targetObject) || - _performerCache == null || - !_performerCache.TryGetComponent(out IActorComponent? actor)) + PerformerCache == null || + !PerformerCache.TryGetComponent(out IActorComponent? actor)) { NotUsefulAnymorePopup(); return; @@ -243,27 +262,19 @@ namespace Content.Server.GameObjects.Components.Body.Surgery var target = targetObject as MechanismComponent; CloseSurgeryUI(actor.playerSession); - _callbackCache?.Invoke(target, _bodyCache, this, _performerCache); + _callbackCache?.Invoke(target, BodyCache, this, PerformerCache); } private void NotUsefulPopup() { - _bodyCache?.Owner.PopupMessage(_performerCache, + BodyCache?.Owner.PopupMessage(PerformerCache, Loc.GetString("You see no useful way to use {0:theName}.", Owner)); } private void NotUsefulAnymorePopup() { - _bodyCache?.Owner.PopupMessage(_performerCache, + BodyCache?.Owner.PopupMessage(PerformerCache, Loc.GetString("You see no useful way to use {0:theName} anymore.", Owner)); } - - public override void ExposeData(ObjectSerializer serializer) - { - base.ExposeData(serializer); - - serializer.DataField(ref _surgeryType, "surgeryType", SurgeryType.Incision); - serializer.DataField(ref _baseOperateTime, "baseOperateTime", 5); - } } } diff --git a/Content.Server/GameObjects/EntitySystems/Body/Surgery/SurgeryToolSystem.cs b/Content.Server/GameObjects/EntitySystems/Body/Surgery/SurgeryToolSystem.cs new file mode 100644 index 0000000000..a7e6205e0c --- /dev/null +++ b/Content.Server/GameObjects/EntitySystems/Body/Surgery/SurgeryToolSystem.cs @@ -0,0 +1,64 @@ +using System.Collections.Generic; +using Content.Server.GameObjects.Components.Body.Surgery; +using Content.Server.GameObjects.Components.Body.Surgery.Messages; +using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameTicking; +using Content.Shared.Utility; +using JetBrains.Annotations; +using Robust.Shared.GameObjects.Systems; + +namespace Content.Server.GameObjects.EntitySystems.Body.Surgery +{ + [UsedImplicitly] + public class SurgeryToolSystem : EntitySystem, IResettingEntitySystem + { + private readonly HashSet _openSurgeryUIs = new(); + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnSurgeryWindowOpen); + SubscribeLocalEvent(OnSurgeryWindowClose); + } + + public void Reset() + { + _openSurgeryUIs.Clear(); + } + + private void OnSurgeryWindowOpen(SurgeryWindowOpenMessage ev) + { + _openSurgeryUIs.Add(ev.Tool); + } + + private void OnSurgeryWindowClose(SurgeryWindowCloseMessage ev) + { + _openSurgeryUIs.Remove(ev.Tool); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + foreach (var tool in _openSurgeryUIs) + { + if (tool.PerformerCache == null) + { + continue; + } + + if (tool.BodyCache == null) + { + continue; + } + + if (!ActionBlockerSystem.CanInteract(tool.PerformerCache) || + !tool.PerformerCache.InRangeUnobstructed(tool.BodyCache)) + { + tool.CloseAllSurgeryUIs(); + } + } + } + } +} From 5909a4102862ea18db19de014f20ec88a1d10eaf Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Sun, 20 Dec 2020 04:31:56 +0100 Subject: [PATCH 25/29] Move damage class and type mappings to DamageSystem (#2784) * Move damage class and type mappings to DamageSystem * Make the properties static again --- Content.Shared/Damage/DamageClass.cs | 26 +++---- Content.Shared/Damage/DamageType.cs | 33 +++------ .../Components/Damage/DamageableComponent.cs | 2 +- .../GameObjects/EntitySystems/DamageSystem.cs | 67 +++++++++++++++++++ 4 files changed, 90 insertions(+), 38 deletions(-) create mode 100644 Content.Shared/GameObjects/EntitySystems/DamageSystem.cs diff --git a/Content.Shared/Damage/DamageClass.cs b/Content.Shared/Damage/DamageClass.cs index 55e6a47045..0801728f39 100644 --- a/Content.Shared/Damage/DamageClass.cs +++ b/Content.Shared/Damage/DamageClass.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; +using Content.Shared.GameObjects.EntitySystems; +using Robust.Shared.GameObjects.Systems; using Robust.Shared.Serialization; namespace Content.Shared.Damage @@ -18,27 +20,21 @@ namespace Content.Shared.Damage public static class DamageClassExtensions { - // TODO DAMAGE This but not hardcoded - private static readonly ImmutableDictionary> ClassToType = - new Dictionary> - { - {DamageClass.Brute, new List {DamageType.Blunt, DamageType.Slash, DamageType.Piercing}}, - {DamageClass.Burn, new List {DamageType.Heat, DamageType.Shock, DamageType.Cold}}, - {DamageClass.Toxin, new List {DamageType.Poison, DamageType.Radiation}}, - {DamageClass.Airloss, new List {DamageType.Asphyxiation, DamageType.Bloodloss}}, - {DamageClass.Genetic, new List {DamageType.Cellular}} - }.ToImmutableDictionary(); - - public static List ToTypes(this DamageClass @class) + public static ImmutableList ToTypes(this DamageClass @class) { - return ClassToType[@class]; + return DamageSystem.ClassToType[@class]; } - public static Dictionary ToDictionary() + public static Dictionary ToNewDictionary() { return Enum.GetValues(typeof(DamageClass)) .Cast() - .ToDictionary(@class => @class, type => 0); + .ToDictionary(@class => @class, _ => default(T)); + } + + public static Dictionary ToNewDictionary() + { + return ToNewDictionary(); } } } diff --git a/Content.Shared/Damage/DamageType.cs b/Content.Shared/Damage/DamageType.cs index 6b139e2569..a16bc2794a 100644 --- a/Content.Shared/Damage/DamageType.cs +++ b/Content.Shared/Damage/DamageType.cs @@ -1,7 +1,8 @@ using System; using System.Collections.Generic; -using System.Collections.Immutable; using System.Linq; +using Content.Shared.GameObjects.EntitySystems; +using Robust.Shared.GameObjects.Systems; using Robust.Shared.Serialization; namespace Content.Shared.Damage @@ -24,38 +25,26 @@ namespace Content.Shared.Damage public static class DamageTypeExtensions { - // TODO: Automatically generate this - private static readonly ImmutableDictionary TypeToClass = - new Dictionary - { - {DamageType.Blunt, DamageClass.Brute}, - {DamageType.Slash, DamageClass.Brute}, - {DamageType.Piercing, DamageClass.Brute}, - {DamageType.Heat, DamageClass.Burn}, - {DamageType.Shock, DamageClass.Burn}, - {DamageType.Cold, DamageClass.Burn}, - {DamageType.Poison, DamageClass.Toxin}, - {DamageType.Radiation, DamageClass.Toxin}, - {DamageType.Asphyxiation, DamageClass.Airloss}, - {DamageType.Bloodloss, DamageClass.Airloss}, - {DamageType.Cellular, DamageClass.Genetic} - }.ToImmutableDictionary(); - public static DamageClass ToClass(this DamageType type) { - return TypeToClass[type]; + return DamageSystem.TypeToClass[type]; } - public static Dictionary ToDictionary() + public static Dictionary ToNewDictionary() { return Enum.GetValues(typeof(DamageType)) .Cast() - .ToDictionary(type => type, type => 0); + .ToDictionary(type => type, _ => default(T)); + } + + public static Dictionary ToNewDictionary() + { + return ToNewDictionary(); } public static Dictionary ToClassDictionary(IReadOnlyDictionary types) { - var classes = DamageClassExtensions.ToDictionary(); + var classes = DamageClassExtensions.ToNewDictionary(); foreach (var @class in classes.Keys.ToList()) { diff --git a/Content.Shared/GameObjects/Components/Damage/DamageableComponent.cs b/Content.Shared/GameObjects/Components/Damage/DamageableComponent.cs index c42f6f7cc9..548d546044 100644 --- a/Content.Shared/GameObjects/Components/Damage/DamageableComponent.cs +++ b/Content.Shared/GameObjects/Components/Damage/DamageableComponent.cs @@ -34,7 +34,7 @@ namespace Content.Shared.GameObjects.Components.Damage public override uint? NetID => ContentNetIDs.DAMAGEABLE; - private readonly Dictionary _damageList = DamageTypeExtensions.ToDictionary(); + private readonly Dictionary _damageList = DamageTypeExtensions.ToNewDictionary(); private readonly HashSet _supportedTypes = new(); private readonly HashSet _supportedClasses = new(); private DamageFlag _flags; diff --git a/Content.Shared/GameObjects/EntitySystems/DamageSystem.cs b/Content.Shared/GameObjects/EntitySystems/DamageSystem.cs new file mode 100644 index 0000000000..502d71062d --- /dev/null +++ b/Content.Shared/GameObjects/EntitySystems/DamageSystem.cs @@ -0,0 +1,67 @@ +using System.Collections.Generic; +using System.Collections.Immutable; +using Content.Shared.Damage; +using JetBrains.Annotations; +using Robust.Shared.GameObjects.Systems; + +namespace Content.Shared.GameObjects.EntitySystems +{ + [UsedImplicitly] + public class DamageSystem : EntitySystem + { + public static ImmutableDictionary> ClassToType { get; } = DefaultClassToType(); + + public static ImmutableDictionary TypeToClass { get; } = DefaultTypeToClass(); + + private static ImmutableDictionary> DefaultClassToType() + { + return new Dictionary> + { + [DamageClass.Brute] = new List + { + DamageType.Blunt, + DamageType.Slash, + DamageType.Piercing + }.ToImmutableList(), + [DamageClass.Burn] = new List + { + DamageType.Heat, + DamageType.Shock, + DamageType.Cold + }.ToImmutableList(), + [DamageClass.Toxin] = new List + { + DamageType.Poison, + DamageType.Radiation + }.ToImmutableList(), + [DamageClass.Airloss] = new List + { + DamageType.Asphyxiation, + DamageType.Bloodloss + }.ToImmutableList(), + [DamageClass.Genetic] = new List + { + DamageType.Cellular + }.ToImmutableList() + }.ToImmutableDictionary(); + } + + private static ImmutableDictionary DefaultTypeToClass() + { + return new Dictionary + { + {DamageType.Blunt, DamageClass.Brute}, + {DamageType.Slash, DamageClass.Brute}, + {DamageType.Piercing, DamageClass.Brute}, + {DamageType.Heat, DamageClass.Burn}, + {DamageType.Shock, DamageClass.Burn}, + {DamageType.Cold, DamageClass.Burn}, + {DamageType.Poison, DamageClass.Toxin}, + {DamageType.Radiation, DamageClass.Toxin}, + {DamageType.Asphyxiation, DamageClass.Airloss}, + {DamageType.Bloodloss, DamageClass.Airloss}, + {DamageType.Cellular, DamageClass.Genetic} + }.ToImmutableDictionary(); + } + } +} From 0b24d425d276574f4881fc4ddec3c2b1587773d9 Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Sun, 20 Dec 2020 04:33:10 +0100 Subject: [PATCH 26/29] Add job categories to the lobby screen (#2770) * Rename department property to departments * WIP Categories * Add better spacing to categories * Fix first separator and sync selectors * You want some types with that * Apply changes to latejoin as well * Add category sorting to the late join gui as well * CONTROL STUCK --- .../UserInterface/HumanoidProfileEditor.cs | 85 ++++++++--- Content.Client/UserInterface/LateJoinGui.cs | 144 +++++++++++------- Content.Shared/Roles/JobPrototype.cs | 4 +- .../Roles/Jobs/Cargo/cargo_technician.yml | 2 +- .../Roles/Jobs/Cargo/quartermaster.yml | 2 +- .../Roles/Jobs/Civilian/assistant.yml | 2 +- .../Roles/Jobs/Civilian/bartender.yml | 2 +- .../Roles/Jobs/Civilian/botanist.yml | 2 +- .../Roles/Jobs/Civilian/chaplain.yml | 2 +- .../Prototypes/Roles/Jobs/Civilian/chef.yml | 2 +- .../Prototypes/Roles/Jobs/Civilian/clown.yml | 2 +- .../Roles/Jobs/Civilian/janitor.yml | 2 +- .../Prototypes/Roles/Jobs/Civilian/mime.yml | 2 +- .../Prototypes/Roles/Jobs/Command/captain.yml | 2 +- .../Roles/Jobs/Command/head_of_personnel.yml | 2 +- .../Roles/Jobs/Engineering/chief_engineer.yml | 2 +- .../Jobs/Engineering/station_engineer.yml | 2 +- .../Jobs/Medical/chief_medical_officer.yml | 2 +- .../Roles/Jobs/Medical/medical_doctor.yml | 2 +- .../Roles/Jobs/Science/research_director.yml | 2 +- .../Roles/Jobs/Science/scientist.yml | 2 +- .../Roles/Jobs/Security/head_of_security.yml | 2 +- .../Roles/Jobs/Security/security_officer.yml | 2 +- .../Prototypes/Roles/Jobs/Security/warden.yml | 2 +- 24 files changed, 184 insertions(+), 91 deletions(-) diff --git a/Content.Client/UserInterface/HumanoidProfileEditor.cs b/Content.Client/UserInterface/HumanoidProfileEditor.cs index baacc607a9..3ab41fa719 100644 --- a/Content.Client/UserInterface/HumanoidProfileEditor.cs +++ b/Content.Client/UserInterface/HumanoidProfileEditor.cs @@ -43,8 +43,11 @@ namespace Content.Client.UserInterface private readonly Button _sexClassifiedButton; private readonly HairStylePicker _hairPicker; private readonly FacialHairStylePicker _facialHairPicker; + private readonly List _jobPriorities; private readonly OptionButton _preferenceUnavailableButton; + private readonly Dictionary _jobCategories; + private readonly List _antagPreferences; private readonly IEntity _previewDummy; @@ -313,31 +316,79 @@ namespace Content.Client.UserInterface }; _jobPriorities = new List(); + _jobCategories = new Dictionary(); + + var firstCategory = true; foreach (var job in prototypeManager.EnumeratePrototypes().OrderBy(j => j.Name)) { - var selector = new JobPrioritySelector(job); - jobList.AddChild(selector); - _jobPriorities.Add(selector); - - selector.PriorityChanged += priority => + foreach (var department in job.Departments) { - Profile = Profile.WithJobPriority(job.ID, priority); - IsDirty = true; - - if (priority == JobPriority.High) + if (!_jobCategories.TryGetValue(department, out var category)) { - // Lower any other high priorities to medium. + category = new VBoxContainer + { + Name = department, + ToolTip = Loc.GetString("Jobs in the {0} department", department) + }; + + if (firstCategory) + { + firstCategory = false; + } + else + { + category.AddChild(new Control + { + CustomMinimumSize = new Vector2(0, 23), + }); + } + + category.AddChild(new PanelContainer + { + PanelOverride = new StyleBoxFlat {BackgroundColor = Color.FromHex("#464966")}, + Children = + { + new Label + { + Text = Loc.GetString("{0} jobs", department) + } + } + }); + + _jobCategories[department] = category; + jobList.AddChild(category); + } + + var selector = new JobPrioritySelector(job); + category.AddChild(selector); + _jobPriorities.Add(selector); + + selector.PriorityChanged += priority => + { + Profile = Profile.WithJobPriority(job.ID, priority); + IsDirty = true; + foreach (var jobSelector in _jobPriorities) { - if (jobSelector != selector && jobSelector.Priority == JobPriority.High) + // Sync other selectors with the same job in case of multiple department jobs + if (jobSelector.Job == selector.Job) { - jobSelector.Priority = JobPriority.Medium; - Profile = Profile.WithJobPriority(jobSelector.Job.ID, JobPriority.Medium); + jobSelector.Priority = priority; + } + + // Lower any other high priorities to medium. + if (priority == JobPriority.High) + { + if (jobSelector.Job != selector.Job && jobSelector.Priority == JobPriority.High) + { + jobSelector.Priority = JobPriority.Medium; + Profile = Profile.WithJobPriority(jobSelector.Job.ID, JobPriority.Medium); + } } } - } - }; + }; + } } } @@ -452,7 +503,7 @@ namespace Content.Client.UserInterface SizeFlagsHorizontal = SizeFlags.FillExpand, }; hbox.AddChild(vBox); - + #region Preview _previewDummy = entityManager.SpawnEntity("HumanMob_Dummy", MapCoordinates.Nullspace); @@ -495,7 +546,7 @@ namespace Content.Client.UserInterface box.AddChild(_previewSpriteSide); #endregion - + #endregion if (preferencesManager.ServerDataLoaded) diff --git a/Content.Client/UserInterface/LateJoinGui.cs b/Content.Client/UserInterface/LateJoinGui.cs index 13eed2a6ab..c1449ceb11 100644 --- a/Content.Client/UserInterface/LateJoinGui.cs +++ b/Content.Client/UserInterface/LateJoinGui.cs @@ -4,6 +4,8 @@ using System.Linq; using Content.Client.Interfaces; using Content.Shared.Roles; using Robust.Client.Console; +using Robust.Client.Graphics.Drawing; +using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; using Robust.Client.Utility; @@ -27,6 +29,7 @@ namespace Content.Client.UserInterface public event Action SelectedId; private readonly Dictionary _jobButtons = new(); + private readonly Dictionary _jobCategories = new(); public LateJoinGui() { @@ -37,65 +40,108 @@ namespace Content.Client.UserInterface var jobList = new VBoxContainer(); var vBox = new VBoxContainer { - Children = + Children = + { + new ScrollContainer { - new ScrollContainer + SizeFlagsVertical = SizeFlags.FillExpand, + Children = { - SizeFlagsVertical = SizeFlags.FillExpand, - Children = - { - jobList - } + jobList } } - }; + } + }; + Contents.AddChild(vBox); + var firstCategory = true; + foreach (var job in _prototypeManager.EnumeratePrototypes().OrderBy(j => j.Name)) { - var jobButton = new JobButton + foreach (var department in job.Departments) { - JobId = job.ID - }; + if (!_jobCategories.TryGetValue(department, out var category)) + { + category = new VBoxContainer + { + Name = department, + ToolTip = Loc.GetString("Jobs in the {0} department", department) + }; - var jobSelector = new HBoxContainer - { - SizeFlagsHorizontal = SizeFlags.FillExpand - }; + if (firstCategory) + { + firstCategory = false; + } + else + { + category.AddChild(new Control + { + CustomMinimumSize = new Vector2(0, 23), + }); + } - var icon = new TextureRect - { - TextureScale = (2, 2), - Stretch = TextureRect.StretchMode.KeepCentered - }; + category.AddChild(new PanelContainer + { + PanelOverride = new StyleBoxFlat {BackgroundColor = Color.FromHex("#464966")}, + Children = + { + new Label + { + Text = Loc.GetString("{0} jobs", department) + } + } + }); - if (job.Icon != null) - { - var specifier = new SpriteSpecifier.Rsi(new ResourcePath("/Textures/Interface/Misc/job_icons.rsi"), job.Icon); - icon.Texture = specifier.Frame0(); + _jobCategories[department] = category; + jobList.AddChild(category); + } + + var jobButton = new JobButton + { + JobId = job.ID + }; + + var jobSelector = new HBoxContainer + { + SizeFlagsHorizontal = SizeFlags.FillExpand + }; + + var icon = new TextureRect + { + TextureScale = (2, 2), + Stretch = TextureRect.StretchMode.KeepCentered + }; + + if (job.Icon != null) + { + var specifier = new SpriteSpecifier.Rsi(new ResourcePath("/Textures/Interface/Misc/job_icons.rsi"), job.Icon); + icon.Texture = specifier.Frame0(); + } + + jobSelector.AddChild(icon); + + var jobLabel = new Label + { + Text = job.Name + }; + + jobSelector.AddChild(jobLabel); + jobButton.AddChild(jobSelector); + category.AddChild(jobButton); + + jobButton.OnPressed += _ => + { + SelectedId?.Invoke(jobButton.JobId); + }; + + if (!_gameTicker.JobsAvailable.Contains(job.ID)) + { + jobButton.Disabled = true; + } + + _jobButtons[job.ID] = jobButton; } - jobSelector.AddChild(icon); - - var jobLabel = new Label - { - Text = job.Name - }; - - jobSelector.AddChild(jobLabel); - - jobButton.AddChild(jobSelector); - jobList.AddChild(jobButton); - jobButton.OnPressed += args => - { - SelectedId?.Invoke(jobButton.JobId); - }; - - if (!_gameTicker.JobsAvailable.Contains(job.ID)) - { - jobButton.Disabled = true; - } - - _jobButtons[job.ID] = jobButton; } SelectedId += jobId => @@ -108,11 +154,6 @@ namespace Content.Client.UserInterface _gameTicker.LobbyJobsAvailableUpdated += JobsAvailableUpdated; } - public string ReturnId() - { - return SelectedId.ToString(); - } - private void JobsAvailableUpdated(IReadOnlyList jobs) { foreach (var (id, button) in _jobButtons) @@ -129,6 +170,7 @@ namespace Content.Client.UserInterface { _gameTicker.LobbyJobsAvailableUpdated -= JobsAvailableUpdated; _jobButtons.Clear(); + _jobCategories.Clear(); } } } diff --git a/Content.Shared/Roles/JobPrototype.cs b/Content.Shared/Roles/JobPrototype.cs index 63aea01f21..08bf12e340 100644 --- a/Content.Shared/Roles/JobPrototype.cs +++ b/Content.Shared/Roles/JobPrototype.cs @@ -42,7 +42,7 @@ namespace Content.Shared.Roles public JobSpecial Special { get; private set; } - public IReadOnlyCollection Department { get; private set; } + public IReadOnlyCollection Departments { get; private set; } public IReadOnlyCollection Access { get; private set; } public void LoadFrom(YamlMappingNode mapping) @@ -51,7 +51,7 @@ namespace Content.Shared.Roles ID = srz.ReadDataField("id"); Name = Loc.GetString(srz.ReadDataField("name")); StartingGear = srz.ReadDataField("startingGear"); - Department = srz.ReadDataField>("department"); + Departments = srz.ReadDataField>("departments"); TotalPositions = srz.ReadDataField("positions"); srz.DataField(this, p => p.SpawnPositions, "spawnPositions", TotalPositions); diff --git a/Resources/Prototypes/Roles/Jobs/Cargo/cargo_technician.yml b/Resources/Prototypes/Roles/Jobs/Cargo/cargo_technician.yml index 80b764c620..5f9d492902 100644 --- a/Resources/Prototypes/Roles/Jobs/Cargo/cargo_technician.yml +++ b/Resources/Prototypes/Roles/Jobs/Cargo/cargo_technician.yml @@ -4,7 +4,7 @@ positions: 2 spawnPositions: 1 startingGear: CargoTechGear - department: + departments: - Cargo icon: "CargoTechnician" access: diff --git a/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml b/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml index c733b02d29..9c2ac826f0 100644 --- a/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml +++ b/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml @@ -4,7 +4,7 @@ positions: 1 spawnPositions: 1 startingGear: QuartermasterGear - department: + departments: - Cargo icon: "QuarterMaster" access: diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/assistant.yml b/Resources/Prototypes/Roles/Jobs/Civilian/assistant.yml index 3df6e98b9d..07a5162534 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/assistant.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/assistant.yml @@ -3,7 +3,7 @@ name: "assistant" positions: -1 # Treated as infinite. startingGear: AssistantGear - department: + departments: - Civilian icon: "Assistant" access: diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/bartender.yml b/Resources/Prototypes/Roles/Jobs/Civilian/bartender.yml index c40b5162c0..04d367ae25 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/bartender.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/bartender.yml @@ -3,7 +3,7 @@ name: "bartender" positions: 1 startingGear: BartenderGear - department: + departments: - Civilian icon: "Bartender" access: diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/botanist.yml b/Resources/Prototypes/Roles/Jobs/Civilian/botanist.yml index 7d20c703bc..94c8d0ab37 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/botanist.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/botanist.yml @@ -4,7 +4,7 @@ positions: 2 spawnPositions: 2 startingGear: BotanistGear - department: + departments: - Civilian icon: "Botanist" access: diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/chaplain.yml b/Resources/Prototypes/Roles/Jobs/Civilian/chaplain.yml index bb67525c43..3f4736aa89 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/chaplain.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/chaplain.yml @@ -3,7 +3,7 @@ # name: "chaplain" # positions: 1 # startingGear: ChaplainGear -# department: +# departments: # - Civilian # icon: "Chaplain" # access: diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/chef.yml b/Resources/Prototypes/Roles/Jobs/Civilian/chef.yml index 0c06658301..bc62b37288 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/chef.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/chef.yml @@ -3,7 +3,7 @@ name: "chef" positions: 1 startingGear: ChefGear - department: + departments: - Civilian icon: "Chef" access: diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml b/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml index c709f8ff76..15bdd058e8 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml @@ -3,7 +3,7 @@ name: "clown" positions: 1 startingGear: ClownGear - department: + departments: - Civilian icon: "Clown" access: diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/janitor.yml b/Resources/Prototypes/Roles/Jobs/Civilian/janitor.yml index 8701597c8a..5b5f6824d5 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/janitor.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/janitor.yml @@ -3,7 +3,7 @@ name: "janitor" positions: 1 startingGear: JanitorGear - department: + departments: - Civilian icon: "Janitor" access: diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/mime.yml b/Resources/Prototypes/Roles/Jobs/Civilian/mime.yml index 4e0dd184d6..c2053ca915 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/mime.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/mime.yml @@ -3,7 +3,7 @@ name: "mime" positions: 1 startingGear: MimeGear - department: + departments: - Civilian icon: "Mime" access: diff --git a/Resources/Prototypes/Roles/Jobs/Command/captain.yml b/Resources/Prototypes/Roles/Jobs/Command/captain.yml index 849e517d00..2000efb720 100644 --- a/Resources/Prototypes/Roles/Jobs/Command/captain.yml +++ b/Resources/Prototypes/Roles/Jobs/Command/captain.yml @@ -4,7 +4,7 @@ head: true positions: 1 startingGear: CaptainGear - department: + departments: - Command icon: "Captain" access: diff --git a/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml b/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml index 716e0ded13..ec51cd6a54 100644 --- a/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml +++ b/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml @@ -4,7 +4,7 @@ head: true positions: 1 startingGear: HoPGear - department: + departments: - Command - Civilian icon: "HeadOfPersonnel" diff --git a/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml b/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml index 7ebf03b75b..fea846c5a4 100644 --- a/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml +++ b/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml @@ -4,7 +4,7 @@ head: true positions: 1 startingGear: ChiefEngineerGear - department: + departments: - Command - Engineering icon: "ChiefEngineer" diff --git a/Resources/Prototypes/Roles/Jobs/Engineering/station_engineer.yml b/Resources/Prototypes/Roles/Jobs/Engineering/station_engineer.yml index 0e3e49807c..d99ed5d635 100644 --- a/Resources/Prototypes/Roles/Jobs/Engineering/station_engineer.yml +++ b/Resources/Prototypes/Roles/Jobs/Engineering/station_engineer.yml @@ -4,7 +4,7 @@ positions: 3 spawnPositions: 2 startingGear: StationEngineerGear - department: + departments: - Engineering icon: "StationEngineer" access: diff --git a/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml b/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml index 7eb6037b6c..570a0c0c88 100644 --- a/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml +++ b/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml @@ -6,7 +6,7 @@ head: true positions: 1 startingGear: CMOGear - department: + departments: - Command - Medical icon: "ChiefMedicalOfficer" diff --git a/Resources/Prototypes/Roles/Jobs/Medical/medical_doctor.yml b/Resources/Prototypes/Roles/Jobs/Medical/medical_doctor.yml index 8e4e3b6080..55b09224aa 100644 --- a/Resources/Prototypes/Roles/Jobs/Medical/medical_doctor.yml +++ b/Resources/Prototypes/Roles/Jobs/Medical/medical_doctor.yml @@ -4,7 +4,7 @@ positions: 3 spawnPositions: 2 startingGear: DoctorGear - department: + departments: - Medical icon: "MedicalDoctor" access: diff --git a/Resources/Prototypes/Roles/Jobs/Science/research_director.yml b/Resources/Prototypes/Roles/Jobs/Science/research_director.yml index 9034e9a6b5..791d95ab78 100644 --- a/Resources/Prototypes/Roles/Jobs/Science/research_director.yml +++ b/Resources/Prototypes/Roles/Jobs/Science/research_director.yml @@ -4,7 +4,7 @@ head: true positions: 1 startingGear: ResearchDirectorGear - department: + departments: - Command - Science icon: "ResearchDirector" diff --git a/Resources/Prototypes/Roles/Jobs/Science/scientist.yml b/Resources/Prototypes/Roles/Jobs/Science/scientist.yml index 72ae62d7c8..dd32adf4fb 100644 --- a/Resources/Prototypes/Roles/Jobs/Science/scientist.yml +++ b/Resources/Prototypes/Roles/Jobs/Science/scientist.yml @@ -4,7 +4,7 @@ positions: 3 spawnPositions: 2 startingGear: ScientistGear - department: + departments: - Science icon: "Scientist" access: diff --git a/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml b/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml index 0e24f9ebdb..bc170284fa 100644 --- a/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml +++ b/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml @@ -4,7 +4,7 @@ head: true positions: 1 startingGear: HoSGear - department: + departments: - Command - Security icon: "HeadOfSecurity" diff --git a/Resources/Prototypes/Roles/Jobs/Security/security_officer.yml b/Resources/Prototypes/Roles/Jobs/Security/security_officer.yml index 3bd87c2371..2cb0c2efdf 100644 --- a/Resources/Prototypes/Roles/Jobs/Security/security_officer.yml +++ b/Resources/Prototypes/Roles/Jobs/Security/security_officer.yml @@ -4,7 +4,7 @@ positions: 3 spawnPositions: 2 startingGear: SecurityOfficerGear - department: + departments: - Security icon: "SecurityOfficer" access: diff --git a/Resources/Prototypes/Roles/Jobs/Security/warden.yml b/Resources/Prototypes/Roles/Jobs/Security/warden.yml index d659f558ea..5780ffd4d7 100644 --- a/Resources/Prototypes/Roles/Jobs/Security/warden.yml +++ b/Resources/Prototypes/Roles/Jobs/Security/warden.yml @@ -4,7 +4,7 @@ positions: 1 spawnPositions: 1 startingGear: WardenGear - department: + departments: - Security icon: "Warden" access: From 21dbd501284a38f71584e8dae113653ee111e245 Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Sun, 20 Dec 2020 04:36:08 +0100 Subject: [PATCH 27/29] Fix build --- .../GameObjects/EntitySystems/Body/Surgery/SurgeryToolSystem.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Content.Server/GameObjects/EntitySystems/Body/Surgery/SurgeryToolSystem.cs b/Content.Server/GameObjects/EntitySystems/Body/Surgery/SurgeryToolSystem.cs index a7e6205e0c..6e7d65b03b 100644 --- a/Content.Server/GameObjects/EntitySystems/Body/Surgery/SurgeryToolSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/Body/Surgery/SurgeryToolSystem.cs @@ -2,6 +2,7 @@ using Content.Server.GameObjects.Components.Body.Surgery; using Content.Server.GameObjects.Components.Body.Surgery.Messages; using Content.Shared.GameObjects.EntitySystems; +using Content.Shared.GameObjects.EntitySystems.ActionBlocker; using Content.Shared.GameTicking; using Content.Shared.Utility; using JetBrains.Annotations; From 91e2dd2276cc1d0d998a746d843d24b603d5e5d4 Mon Sep 17 00:00:00 2001 From: DrSmugleaf Date: Sun, 20 Dec 2020 04:48:13 +0100 Subject: [PATCH 28/29] Add command to enable the lobby, restart the round and set a preset (#2786) --- .../Commands/GameTicking/GoLobbyCommand.cs | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 Content.Server/Commands/GameTicking/GoLobbyCommand.cs diff --git a/Content.Server/Commands/GameTicking/GoLobbyCommand.cs b/Content.Server/Commands/GameTicking/GoLobbyCommand.cs new file mode 100644 index 0000000000..35d2691f00 --- /dev/null +++ b/Content.Server/Commands/GameTicking/GoLobbyCommand.cs @@ -0,0 +1,50 @@ +#nullable enable +using System; +using Content.Server.Administration; +using Content.Server.Interfaces.GameTicking; +using Content.Shared; +using Content.Shared.Administration; +using Robust.Server.Interfaces.Console; +using Robust.Server.Interfaces.Player; +using Robust.Shared.Interfaces.Configuration; +using Robust.Shared.IoC; +using Robust.Shared.Localization; + +namespace Content.Server.Commands.GameTicking +{ + [AdminCommand(AdminFlags.Server)] + public class GoLobbyCommand : IClientCommand + { + public string Command => "golobby"; + public string Description => "Enables the lobby and restarts the round."; + public string Help => $"Usage: {Command} / {Command} "; + public void Execute(IConsoleShell shell, IPlayerSession? player, string[] args) + { + Type? preset = null; + var presetName = string.Join(" ", args); + + var ticker = IoCManager.Resolve(); + + if (args.Length > 0) + { + if (!ticker.TryGetPreset(presetName, out preset)) + { + shell.SendText(player, $"No preset found with name {presetName}"); + return; + } + } + + var config = IoCManager.Resolve(); + config.SetCVar(CCVars.GameLobbyEnabled, true); + + ticker.RestartRound(); + + if (preset != null) + { + ticker.SetStartPreset(preset); + } + + shell.SendText(player, $"Enabling the lobby and restarting the round.{(preset == null ? "" : $"\nPreset set to {presetName}")}"); + } + } +} From 921f7ab642f33be755adf449621b290fb8a41d00 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Sun, 20 Dec 2020 16:13:45 +0100 Subject: [PATCH 29/29] Clean up stale preferences data on load at the server. This fixes further bugs with "nonexistant job selected in character preferences" like the client blowing up in the lobby. --- .../Preferences/ServerPreferencesManager.cs | 32 ++++++++++++++++++- .../Preferences/HumanoidCharacterProfile.cs | 4 +-- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/Content.Server/Preferences/ServerPreferencesManager.cs b/Content.Server/Preferences/ServerPreferencesManager.cs index a17bdbbb45..96a0cf2d8c 100644 --- a/Content.Server/Preferences/ServerPreferencesManager.cs +++ b/Content.Server/Preferences/ServerPreferencesManager.cs @@ -7,6 +7,7 @@ using Content.Server.Interfaces; using Content.Shared; using Content.Shared.Network.NetMessages; using Content.Shared.Preferences; +using Content.Shared.Roles; using Robust.Server.Interfaces.Player; using Robust.Shared.Interfaces.Configuration; using Robust.Shared.Interfaces.Network; @@ -250,7 +251,36 @@ namespace Content.Server.Preferences return await _db.InitPrefsAsync(userId, HumanoidCharacterProfile.Default()); } - return prefs; + return SanitizePreferences(prefs); + } + + private PlayerPreferences SanitizePreferences(PlayerPreferences prefs) + { + // Clean up preferences in case of changes to the game, + // such as removed jobs still being selected. + + return new PlayerPreferences(prefs.Characters.Select(p => + { + ICharacterProfile newProf; + switch (p.Value) + { + case HumanoidCharacterProfile hp: + { + newProf = hp + .WithJobPriorities( + hp.JobPriorities.Where(job => + _protos.HasIndex(job.Key))) + .WithAntagPreferences( + hp.AntagPreferences.Where(antag => + _protos.HasIndex(antag))); + break; + } + default: + throw new NotSupportedException(); + } + + return new KeyValuePair(p.Key, newProf); + }), prefs.SelectedCharacterIndex); } public IEnumerable> GetSelectedProfilesForPlayers( diff --git a/Content.Shared/Preferences/HumanoidCharacterProfile.cs b/Content.Shared/Preferences/HumanoidCharacterProfile.cs index a2b1104730..371d30d429 100644 --- a/Content.Shared/Preferences/HumanoidCharacterProfile.cs +++ b/Content.Shared/Preferences/HumanoidCharacterProfile.cs @@ -106,7 +106,7 @@ namespace Content.Shared.Preferences return new(Name, Age, Sex, appearance, _jobPriorities, PreferenceUnavailable, _antagPreferences); } - public HumanoidCharacterProfile WithJobPriorities(IReadOnlyDictionary jobPriorities) + public HumanoidCharacterProfile WithJobPriorities(IEnumerable> jobPriorities) { return new( Name, @@ -138,7 +138,7 @@ namespace Content.Shared.Preferences return new(Name, Age, Sex, Appearance, _jobPriorities, mode, _antagPreferences); } - public HumanoidCharacterProfile WithAntagPreferences(IReadOnlyList antagPreferences) + public HumanoidCharacterProfile WithAntagPreferences(IEnumerable antagPreferences) { return new( Name,