From 1f22dfda7ba0290d464d47c4ac089d77c5c90f3b Mon Sep 17 00:00:00 2001 From: TheWaffleJesus <106146578+TheWaffleJesus@users.noreply.github.com> Date: Sun, 8 Sep 2024 09:34:08 +0100 Subject: [PATCH 001/290] changed from tag to material and added icon for capacitor --- .../Construction/Graphs/clothing/medsec_hud.yml | 13 ++----------- .../Recipes/Crafting/Graphs/improvised/potato.yml | 12 ++---------- Resources/Prototypes/Stacks/science_stacks.yml | 1 + 3 files changed, 5 insertions(+), 21 deletions(-) diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/clothing/medsec_hud.yml b/Resources/Prototypes/Recipes/Construction/Graphs/clothing/medsec_hud.yml index 03a70cb7fe70..78a27a9d0f37 100644 --- a/Resources/Prototypes/Recipes/Construction/Graphs/clothing/medsec_hud.yml +++ b/Resources/Prototypes/Recipes/Construction/Graphs/clothing/medsec_hud.yml @@ -27,17 +27,8 @@ sprite: Objects/Devices/communication.rsi state: walkietalkie doAfter: 5 - - tag: CapacitorStockPart - name: capacitor - icon: - sprite: Objects/Misc/stock_parts.rsi - state: capacitor - doAfter: 5 - - tag: CapacitorStockPart - name: capacitor - icon: - sprite: Objects/Misc/stock_parts.rsi - state: capacitor + - material: Capacitor + amount: 2 doAfter: 5 - node: medsecHud entity: ClothingEyesHudMedSec diff --git a/Resources/Prototypes/Recipes/Crafting/Graphs/improvised/potato.yml b/Resources/Prototypes/Recipes/Crafting/Graphs/improvised/potato.yml index e3f972cfda47..f03670b673cf 100644 --- a/Resources/Prototypes/Recipes/Crafting/Graphs/improvised/potato.yml +++ b/Resources/Prototypes/Recipes/Crafting/Graphs/improvised/potato.yml @@ -60,15 +60,7 @@ - material: Cable amount: 2 doAfter: 1 - - tag: CapacitorStockPart - name: capacitor - icon: - sprite: Objects/Misc/stock_parts.rsi - state: capacitor - - tag: CapacitorStockPart - name: capacitor - icon: - sprite: Objects/Misc/stock_parts.rsi - state: capacitor + - material: Capacitor + amount: 2 - node: potatoaichip entity: PotatoAIChip \ No newline at end of file diff --git a/Resources/Prototypes/Stacks/science_stacks.yml b/Resources/Prototypes/Stacks/science_stacks.yml index 0d273c324e6b..647a5b2a7bf3 100644 --- a/Resources/Prototypes/Stacks/science_stacks.yml +++ b/Resources/Prototypes/Stacks/science_stacks.yml @@ -7,6 +7,7 @@ - type: stack id: Capacitor name: capacitor + icon: { sprite: /Textures/Objects/Misc/stock_parts.rsi, state: capacitor } spawn: CapacitorStockPart maxCount: 10 From daf674e37b1fb8dbf9a11b253f25c956ff07c2e1 Mon Sep 17 00:00:00 2001 From: TheWaffleJesus <106146578+TheWaffleJesus@users.noreply.github.com> Date: Sun, 8 Sep 2024 10:01:08 +0100 Subject: [PATCH 002/290] changed capacitor yaml for substation and memory cell --- .../Recipes/Construction/Graphs/tools/logic_gate.yml | 7 ++----- .../Graphs/utilities/wallmount_substation.yml | 8 ++------ 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/tools/logic_gate.yml b/Resources/Prototypes/Recipes/Construction/Graphs/tools/logic_gate.yml index 37c85e07a37e..5a7dfbb3bf68 100644 --- a/Resources/Prototypes/Recipes/Construction/Graphs/tools/logic_gate.yml +++ b/Resources/Prototypes/Recipes/Construction/Graphs/tools/logic_gate.yml @@ -46,11 +46,8 @@ doAfter: 1 - to: memory_cell steps: - - tag: CapacitorStockPart - icon: - sprite: Objects/Misc/stock_parts.rsi - state: capacitor - name: a capacitor + - material: Capacitor + amount: 1 - material: Cable amount: 2 doAfter: 1 diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/utilities/wallmount_substation.yml b/Resources/Prototypes/Recipes/Construction/Graphs/utilities/wallmount_substation.yml index 7e4087b20a21..bd9b2415e26c 100644 --- a/Resources/Prototypes/Recipes/Construction/Graphs/utilities/wallmount_substation.yml +++ b/Resources/Prototypes/Recipes/Construction/Graphs/utilities/wallmount_substation.yml @@ -57,12 +57,8 @@ sprite: "Objects/Power/power_cells.rsi" state: "medium" doAfter: 0.5 - - tag: CapacitorStockPart - name: a capacitor - store: capacitor - icon: - sprite: "Objects/Misc/stock_parts.rsi" - state: "capacitor" + - material: Capacitor + amount: 1 doAfter: 0.5 - to: frame completed: From 30018a3ab1a3d36fe62ed0e29a16d1ce724230e6 Mon Sep 17 00:00:00 2001 From: The Canned One Date: Fri, 27 Sep 2024 18:10:51 +0200 Subject: [PATCH 003/290] added Derelict Cyborgs with basic functionality. --- .../interaction-popup-component.ftl | 3 ++ .../Mobs/Cyborgs/base_borg_chassis.yml | 25 +++++++++++ .../Entities/Mobs/Cyborgs/borg_chassis.yml | 39 ++++++++++++++++++ .../Entities/Mobs/Player/silicon.yml | 36 ++++++++++++++++ .../Construction/Graphs/machines/cyborg.yml | 3 ++ .../Mobs/Silicon/chassis.rsi/derelict.png | Bin 0 -> 11838 bytes .../Mobs/Silicon/chassis.rsi/derelict_e.png | Bin 0 -> 5508 bytes .../Mobs/Silicon/chassis.rsi/derelict_e_r.png | Bin 0 -> 5515 bytes .../Mobs/Silicon/chassis.rsi/derelict_l.png | Bin 0 -> 6986 bytes .../Mobs/Silicon/chassis.rsi/meta.json | 14 ++++++- 10 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 Resources/Textures/Mobs/Silicon/chassis.rsi/derelict.png create mode 100644 Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_e.png create mode 100644 Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_e_r.png create mode 100644 Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_l.png diff --git a/Resources/Locale/en-US/interaction/interaction-popup-component.ftl b/Resources/Locale/en-US/interaction/interaction-popup-component.ftl index 10773d6de843..65310b67f988 100644 --- a/Resources/Locale/en-US/interaction/interaction-popup-component.ftl +++ b/Resources/Locale/en-US/interaction/interaction-popup-component.ftl @@ -67,6 +67,7 @@ petting-success-janitor-cyborg = You pet {THE($target)} on {POSS-ADJ($target)} d petting-success-medical-cyborg = You pet {THE($target)} on {POSS-ADJ($target)} sterile metal head. petting-success-service-cyborg = You pet {THE($target)} on {POSS-ADJ($target)} dapper looking metal head. petting-success-syndicate-cyborg = You pet {THE($target)} on {POSS-ADJ($target)} menacing metal head. +petting-success-derelict-cyborg = You pet {THE($target)} on {POSS-ADJ($target)} rusty metal head. petting-success-recycler = You pet {THE($target)} on {POSS-ADJ($target)} mildly threatening steel exterior. petting-failure-honkbot = You reach out to pet {THE($target)}, but {SUBJECT($target)} {CONJUGATE-BASIC($target, "honk", "honks")} in refusal! @@ -80,6 +81,8 @@ petting-failure-janitor-cyborg = You reach out to pet {THE($target)}, but {SUBJE petting-failure-medical-cyborg = You reach out to pet {THE($target)}, but {SUBJECT($target)} {CONJUGATE-BE($target)} busy saving lives! petting-failure-service-cyborg = You reach out to pet {THE($target)}, but {SUBJECT($target)} {CONJUGATE-BE($target)} busy serving others! petting-failure-syndicate-cyborg = You reach out to pet {THE($target)}, but {POSS-ADJ($target)} treacherous affiliation makes you reconsider. +petting-failure-derelict-cyborg = You reach out to pet {THE($target)}, but {POSS-ADJ($target)} rusty and jagged exterior makes you reconsider. + ## Rattling fences diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml index 955ddfd2e3e2..2f8a7cf10e87 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml @@ -317,3 +317,28 @@ Unsexed: UnisexSiliconSyndicate - type: PointLight color: "#dd200b" + +- type: entity + id: BaseBorgChassisDerelict + parent: [BaseBorgChassis, BaseBorgTransponder] + abstract: true + components: + - type: NpcFactionMember + factions: + - Passive #Might change this + - type: Access + enabled: false + groups: + - AllAccess + - type: AccessReader + access: [["Command"]] #I will probably change this. + - type: SiliconLawProvider + laws: AntimovLawset + - type: IntrinsicRadioTransmitter + channels: + - Binary + - Common + - type: ActiveRadio + channels: + - Binary + - Common diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml index d1d530ae81b7..00bf7fc2afa5 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml @@ -442,3 +442,42 @@ interactFailureString: petting-failure-syndicate-cyborg interactSuccessSound: path: /Audio/Ambience/Objects/periodic_beep.ogg + + +- type: entity + id: BorgChassisDerelict + parent: BaseBorgChassisDerelict + name: damaged cyborg + components: + - type: Sprite + layers: + - state: derelict + - state: derelict_e_r + map: ["enum.BorgVisualLayers.Light"] + shader: unshaded + visible: false + - state: derelict_l + shader: unshaded + map: ["light"] + visible: false + - type: BorgChassis + maxModules: 5 #The sixth one broke lol. + moduleWhitelist: + tags: + - BorgModuleGeneric + hasMindState: derelict_e + noMindState: derelict_e_r + - type: BorgTransponder + sprite: + sprite: Mobs/Silicon/chassis.rsi + state: derelict + name: damaged cyborg + - type: Construction + node: derelictcyborg #what is this? + - type: Speech + speechVerb: Robotic + - type: InteractionPopup + interactSuccessString: petting-success-derelict-cyborg + interactFailureString: petting-failure-derelict-cyborg + interactSuccessSound: + path: /Audio/Ambience/Objects/periodic_beep.ogg \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml index 15878a4017d0..a6320dc7b3f8 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml @@ -515,3 +515,39 @@ - PlayerBorgSyndicateAssaultGhostRole - PlayerBorgSyndicateAssaultGhostRole # Saboteurs are kinda like cyborg medics, we want less. - PlayerBorgSyndicateSaboteurGhostRole + +- type: entity + id: PlayerBorgDerelict + parent: BorgChassisDerelict + suffix: Battery, Module + components: + - type: ContainerFill + containers: + borg_brain: + - PositronicBrain + borg_module: + - BorgModuleTool + - BorgModuleFireExtinguisher + - BorgModuleGPS + - type: ItemSlots + slots: + cell_slot: + name: power-cell-slot-component-slot-name-default + startingItem: PowerCellHigh + - type: RandomMetadata + nameSegments: [names_borg] + +- type: entity + id: PlayerBorgDerelictBattery + parent: BorgChassisDerelict + suffix: Battery + components: + - type: ContainerFill + containers: + borg_brain: + - MMIFilled + - type: ItemSlots + slots: + cell_slot: + name: power-cell-slot-component-slot-name-default + startingItem: PowerCellHigh diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml b/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml index 0f012cefc98e..3f8a731cbbd7 100644 --- a/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml +++ b/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml @@ -205,3 +205,6 @@ - node: syndicatesaboteur entity: BorgChassisSyndicateSaboteur + + - node: derelictcyborg + entity: BorgChassisDerelict diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict.png b/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict.png new file mode 100644 index 0000000000000000000000000000000000000000..bbf72fc45bed2408b2abeb91d3564f8fa41e6e5a GIT binary patch literal 11838 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 HpFaCP!NMbp literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_e.png b/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_e.png new file mode 100644 index 0000000000000000000000000000000000000000..17349d74dc8ba9bbf0e434b9e32e634535c3a244 GIT binary patch literal 5508 zcmeHLdo+|=8=nY6QX#Wvq&meR zl|v!rQgZ94bW)OtuH<$?afD7v)c4L%X?(VF76K2XgQ1%{|9rmZ0JZZLWFi*bE9X9qU3MxvUGL6yCxXSUj>r7QHu-C!blnZP$gw*VA>=3q%fM2G=2Gr_b-jHI%L5k*29nyh;}yDSUaf z9XPP=vf-6ctX4m!()Pzf@=&yi`6eyN=-T#Zmp=}9U%;K(7ipU|<526tyQ8nmD8#`C z+CacPYgTIc=(~_G$LzZDm@O$A)A}+yR^0B&N;$XVc3RMI_gHb`p1_`vfymLPUPBE$ zZ~WTW?3cp(*OCf$1^$d-zdUl{C#t?(G?LoCzcjj0kLCS`jrMR2Rj+k$>+ppnLX4VP zMR;ajMeD-!gG2XHE99H$ZGtS_n^k(ZqnzJ7IU}XK4Y;y7dZns^Ce|qqA~l)mE_>&* ztX0qd#%hP{RlZGu)1vmAFS0*YV~@xJk8B)Dryn<;{|HeR^#X|^pbk3vJ1|UZWeGr?sEPSrPQt$O?1nNfB6zbwEUT^+sAHwfyqGLR?E`XzUM+?2|E z^W9wuE&+f}J^~cP-k(@6se0B7~$V^gFCTEuM?%y7i9I^0fQ9ly*Xc;Lu+c?3R*SzQQ z>^{+RpOMttKMu8&oHc5%4!Wy(*r{A+m-mU2fhV;cdUM_c((&aCmOIu~VnBS9W;RrXzGMxo*0UR!%?J=$DmcY@6rCuRVw4 zOkL}g5;fAG8=18#A@h&HPGm!B0zJa89~sfPajL#mo^J(|r04YbQjuqe>biJiwYU4V zFWfO)08sbk*N?6^w=kgg1E$+>7W8Kil;2-K97{aCbGxa=SDU~W84i&THhYFL8LOI>TKk{9Q9$J|Y*7%9xjr(36& zbo6cwtW0cMz#9o=IUgucsgT~SADz(^JHxqL%`^fFtXt$MpF*y^prf`F>9!N0uJUwu z_rtyyOT(w7{kllFW7-I&+hp46l-8_cAJqNUOe=V8*pZ4rOo`>wXl@J|?Nf<{3v)_D z0@eANn|`dTdxq(34eK~9UY3gi-4QxuYEZeFzq0U!?_m9+bOtT4y?uGH!Tiw;Ih113 z%NMPtNVy%VR>vjYY<+tKBi(WD472`@vS6LzW({P~EcZJX@%D|YjE(lhAM1^u6XIy1 zp2fp0!Mh*GG^l^Iam(wsh9@+~)ub0jV8IY&%$ z?wRZWaG99QVi$|JIR?5;Drhe2eDthUbpHp=_=M9#S-Y-08!)-K^w2idz4M2b(_%Z{ zR(@<97Tg)VUYxAISEUboaSX3LH7Gi)@#2*O!qP~Uw`tKUb9=B4qIz8GvzeIisjmg9 zh7Xv`7FDz0s0x!!ge6Xc?wapxUPZ2XmZTOYjy~rREZQeau|@EYH`Y&=NRWH=mv6t* z(Yzp6_I}uf6KU64E^Tm(`8^muON03End!~^k-`xR%>b^L4Vr}rCGeSwK-k!YNC3_@ z5JIs*KfZ{H?k~N9M)A2+w3h`F$CS`Of4*~=6m$=BVR6E?amZY>ovoHl2n7ZZf)IcT z5eh^yN(dFL#HGM(g&2!QDOI3tRJ1qK4Mh`6K@`!9XokZ$hVX+3Xj?6mjg-rytf#M; zfPi~cv_Aw%C|GQ8aIjghxtUn%hsBf0WGs$=B@i&M21XVtf`AZ=NM@{n7{{Q4GLDol zf%sw(N`VQm#eonNjfTfjpZpU_n9R@cBH08BFdx_uK!U}a;jls>cCv*Gatwk&CLH=l z3mFT3^}wzNW#T|72XqVqMUe4i2rlQdy(Ca7P=>?hU_k*WgjHqmtoW~{bYd{wK3ga# z@Z$?5N-LP`uQVY(?+aO9`KB0AhBMg_*!(l@SK6OqS1Q9=OeTdc<^(F-W6-H+#rzbm zn8W8%lub5h34#FG9An8LT40D)1SxWWhcgL^A(BCWhyyC1U~n@& zj05s`L=G8;!+@4}GKR<|kT7Ht&k{ohtt?4IygApBYcUDJRmz965)e%GN&&@%p|}8n z$Od5)3o8o_2DY`pkgRwB#@rmow&dafGMf!5p|~8%8nILez{|-O0)8M?BJxuXCnKt(H@LMbdi4>REn#RVXM z4nQCbiX#vyI5LG`#ljOP1U!Xcz7j{E;3nydxqM#e|I$`$AC%4bqC4|t@cf}l(fFQn z2Lr}?<6Qw?xtUNX<+h*zobeE3KoH1P`Uzu=4{`hfksk=xkBNl+B;BoKIFn9tK`io;jXG0LT;h^ch_y=0U-L6m;-|d4#!w6I96+YWc)ct@zrT zV1H1t4lrdH92xV4G9nr~5iC|wF+N3WgZ(c)Y?KOxyT};gve`V4()YU^;4aYtGY}J?C(2 z7!elvFz5~}_>av;m6}mFZM8a-PHUwuRIS6&$UcP(RJ(w3ZYllw>4!f}bm7Zf!NQ^| z#}XD#f$g~Glj=XV=wv4R8TzDylDq^K9eiYXY09&nUQM`-K+FkHZDY)~JXr2qs^~Ht LUFhdl`^x_VBy@7n literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_e_r.png b/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_e_r.png new file mode 100644 index 0000000000000000000000000000000000000000..3c8cf19acf66f1c662629db09546f8a553a3c658 GIT binary patch literal 5515 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 S?UyLhp|`uATeV9>+J69Pac{i< literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_l.png b/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_l.png new file mode 100644 index 0000000000000000000000000000000000000000..f65fbaebc3c5074e945e94f59b8d90b83ac08bb3 GIT binary patch literal 6986 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 Date: Fri, 27 Sep 2024 20:11:04 +0200 Subject: [PATCH 004/290] minor changes to the Derelict Cyborg --- .../Entities/Mobs/Cyborgs/base_borg_chassis.yml | 6 +++--- .../Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml | 10 +++------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml index 2f8a7cf10e87..4c0359b37e6c 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml @@ -320,7 +320,7 @@ - type: entity id: BaseBorgChassisDerelict - parent: [BaseBorgChassis, BaseBorgTransponder] + parent: BaseBorgChassis abstract: true components: - type: NpcFactionMember @@ -329,11 +329,11 @@ - type: Access enabled: false groups: - - AllAccess + - AllAccess #Randomized access would be fun. AllAccess is the best i can think of right now that does make it too hard to enter the station or. - type: AccessReader access: [["Command"]] #I will probably change this. - type: SiliconLawProvider - laws: AntimovLawset + laws: AntimovLawset #Temporary until i get it randomized. - type: IntrinsicRadioTransmitter channels: - Binary diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml index 00bf7fc2afa5..818847f24490 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml @@ -447,7 +447,8 @@ - type: entity id: BorgChassisDerelict parent: BaseBorgChassisDerelict - name: damaged cyborg + name: derelict cyborg + description: A man-machine hybrid that assists in station activity. This one is in a state of great disrepair. components: - type: Sprite layers: @@ -467,13 +468,8 @@ - BorgModuleGeneric hasMindState: derelict_e noMindState: derelict_e_r - - type: BorgTransponder - sprite: - sprite: Mobs/Silicon/chassis.rsi - state: derelict - name: damaged cyborg - type: Construction - node: derelictcyborg #what is this? + node: derelictcyborg - type: Speech speechVerb: Robotic - type: InteractionPopup From c3fa1b45d002ae88d5b21e18c77a286eec2d3d97 Mon Sep 17 00:00:00 2001 From: The Canned One Date: Sat, 28 Sep 2024 10:18:40 +0200 Subject: [PATCH 005/290] Added Derelict Cyborg midround event. --- .../ghost/roles/ghost-role-component.ftl | 4 +++ .../Locale/en-US/silicons/derelict/role.ftl | 4 +++ .../Entities/Markers/Spawners/ghost_roles.yml | 18 ++++++++++++++ .../Entities/Mobs/Player/silicon.yml | 13 ++++++++++ Resources/Prototypes/GameRules/events.yml | 23 ++++++++++++++++++ .../Silicon/chassis.rsi/derelict_icon.png | Bin 0 -> 6429 bytes .../Mobs/Silicon/chassis.rsi/meta.json | 6 ++++- 7 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 Resources/Locale/en-US/silicons/derelict/role.ftl create mode 100644 Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_icon.png diff --git a/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl b/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl index 77d2645c4c5c..71ab4d371602 100644 --- a/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl +++ b/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl @@ -240,6 +240,10 @@ ghost-role-information-syndicate-cyborg-assault-name = Syndicate Assault Cyborg ghost-role-information-syndicate-cyborg-saboteur-name = Syndicate Saboteur Cyborg ghost-role-information-syndicate-cyborg-description = The Syndicate needs reinforcements. You, a cold silicon killing machine, will help them. + +ghost-role-information-derelict-cyborg-name = Derelict Cyborg +ghost-role-information-derelict-cyborg-description = You were a regular cyborg that got lost in space. After drifting in whichever direction the laws of physics would have it for years, you have drifted close to a Nanotrasen space station... You are bound by silicon laws. Check them upon spawning. + ghost-role-information-security-name = Security ghost-role-information-security-description = You are part of a security task force, but seem to have found yourself in a strange situation... diff --git a/Resources/Locale/en-US/silicons/derelict/role.ftl b/Resources/Locale/en-US/silicons/derelict/role.ftl new file mode 100644 index 000000000000..88e750e6214d --- /dev/null +++ b/Resources/Locale/en-US/silicons/derelict/role.ftl @@ -0,0 +1,4 @@ +derelict-cyborg-round-end-agent-name = derelict cyborg + +derelict-cyborg-role-greeting = + You are a cyborg that has been lost in space for many years that has now drifted close to a space station. You can use your fire extinguisher and GPS to get board the station. Remember to follow your laws. #Greeting is unused for now. \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml b/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml index b694a8cc2f2b..18d459cd89e3 100644 --- a/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml +++ b/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml @@ -170,3 +170,21 @@ - state: green - sprite: Objects/Weapons/Melee/energykatana.rsi state: icon + +- type: entity + categories: [ HideSpawnMenu, Spawner ] + parent: BaseAntagSpawner + id: SpawnPointGhostDerelictCyborg + components: + - type: GhostRole + name: ghost-role-information-derelict-cyborg-name + description: ghost-role-information-derelict-cyborg-description + rules: ghost-role-information-silicon-rules + raffle: + settings: default + - type: Sprite + sprite: Markers/jobs.rsi + layers: + - state: green + - sprite: Mobs/Silicon/chassis.rsi + state: derelict_icon \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml index a6320dc7b3f8..ff2b3f9ff2dc 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml @@ -551,3 +551,16 @@ cell_slot: name: power-cell-slot-component-slot-name-default startingItem: PowerCellHigh + +- type: entity + id: PlayerBorgDerelictGhostRole + parent: PlayerBorgDerelictBattery + suffix: Battery, Ghost role + components: + - type: GhostRole + name: ghost-role-information-derelict-cyborg-name + description: ghost-role-information-derelict-cyborg-description + rules: ghost-role-information-silicon-rules + raffle: + settings: default + - type: GhostTakeoverAvailable diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index dc44915f53da..efebc8e27205 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -35,6 +35,7 @@ - id: RevenantSpawn - id: SleeperAgents - id: ZombieOutbreak + - id: DerelictCyborgSpawn - type: entity id: BaseStationEvent @@ -545,3 +546,25 @@ maxOccurrences: 1 # this event has diminishing returns on interesting-ness, so we cap it weight: 5 - type: MobReplacementRule + +- type: entity + parent: BaseGameRule + id: DerelictCyborgSpawn + components: + - type: StationEvent + weight: 2 #Low until it spawns with a random lawset instead of just antimov. + earliestStart: 15 + reoccurrenceDelay: 20 + minimumPlayers: 7 + duration: null + - type: SpaceSpawnRule + spawnDistance: 0 + - type: AntagSpawner + prototype: PlayerBorgDerelict + - type: AntagSelection + agentName: derelict-cyborg-round-end-agent-name + definitions: + - spawnerPrototype: SpawnPointGhostDerelictCyborg + min: 1 + max: 1 + pickPlayer: false \ No newline at end of file diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_icon.png b/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..7f0ea2a25560f33773cd72d6184daba55dd4d033 GIT binary patch literal 6429 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 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/meta.json b/Resources/Textures/Mobs/Silicon/chassis.rsi/meta.json index 373b9ce9a908..38a75827d50d 100644 --- a/Resources/Textures/Mobs/Silicon/chassis.rsi/meta.json +++ b/Resources/Textures/Mobs/Silicon/chassis.rsi/meta.json @@ -1,5 +1,5 @@ { - "version": 1, + "version": 2, "size": { "x": 32, "y": 32 @@ -31,6 +31,10 @@ "name": "derelict_e_r", "directions": 4 }, + { + "name": "derelict_icon", + "directions": 1 + }, { "name": "derelict_l", "directions": 4 From 964ef33fc746adc429db6d78e4529993a5cd831f Mon Sep 17 00:00:00 2001 From: The Canned One Date: Sat, 28 Sep 2024 10:50:33 +0200 Subject: [PATCH 006/290] Fixed accidental removal of something from a meta.json file. --- Resources/Textures/Mobs/Silicon/chassis.rsi/meta.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/meta.json b/Resources/Textures/Mobs/Silicon/chassis.rsi/meta.json index 38a75827d50d..6ec63992f1f0 100644 --- a/Resources/Textures/Mobs/Silicon/chassis.rsi/meta.json +++ b/Resources/Textures/Mobs/Silicon/chassis.rsi/meta.json @@ -19,6 +19,10 @@ "name": "clown_e_r", "directions": 4 }, + { + "name": "clown_l", + "directions": 4 + }, { "name": "derelict", "directions": 4 From bad25e3397b7c7cc4a88f7ee9592fcba28875f1b Mon Sep 17 00:00:00 2001 From: The Canned One Date: Sun, 29 Sep 2024 19:01:59 +0200 Subject: [PATCH 007/290] Split part of IonStormRule into IonStormSystem. Added StartIonStormed which also uses IonStormSystem. Added StartIonStormedComponent. Changed stuff related to the Derelict Cyborg. Derelict Cyborg now spawns with a randomized lawset. --- .../Silicons/Laws/IonStormSystem.cs | 283 ++++++++++++++++++ .../Silicons/Laws/StartIonStormedSystem.cs | 40 +++ .../StationEvents/Events/IonStormRule.cs | 267 +---------------- .../Components/StartIonStormedComponent.cs | 17 ++ .../ghost/roles/ghost-role-component.ftl | 2 +- .../Locale/en-US/silicons/derelict/role.ftl | 2 +- .../Mobs/Cyborgs/base_borg_chassis.yml | 8 +- Resources/Prototypes/GameRules/events.yml | 7 +- 8 files changed, 355 insertions(+), 271 deletions(-) create mode 100644 Content.Server/Silicons/Laws/IonStormSystem.cs create mode 100644 Content.Server/Silicons/Laws/StartIonStormedSystem.cs create mode 100644 Content.Shared/Silicons/Laws/Components/StartIonStormedComponent.cs diff --git a/Content.Server/Silicons/Laws/IonStormSystem.cs b/Content.Server/Silicons/Laws/IonStormSystem.cs new file mode 100644 index 000000000000..1acfe2e3896f --- /dev/null +++ b/Content.Server/Silicons/Laws/IonStormSystem.cs @@ -0,0 +1,283 @@ +using System.Linq; +using Content.Server.StationEvents.Components; +using Content.Shared.Administration.Logs; +using Content.Shared.Database; +using Content.Shared.Dataset; +using Content.Shared.FixedPoint; +using Content.Shared.GameTicking.Components; +using Content.Shared.Random; +using Content.Shared.Random.Helpers; +using Content.Shared.Silicons.Laws; +using Content.Shared.Silicons.Laws.Components; +using Content.Shared.Station.Components; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; + +namespace Content.Server.Silicons.Laws; + +public sealed class IonStormSystem : EntitySystem +{ + [Dependency] private readonly IPrototypeManager _proto = default!; + [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; + [Dependency] private readonly SiliconLawSystem _siliconLaw = default!; + [Dependency] private readonly IRobustRandom _robustRandom = default!; + + // funny + [ValidatePrototypeId] + private const string Threats = "IonStormThreats"; + [ValidatePrototypeId] + private const string Objects = "IonStormObjects"; + [ValidatePrototypeId] + private const string Crew = "IonStormCrew"; + [ValidatePrototypeId] + private const string Adjectives = "IonStormAdjectives"; + [ValidatePrototypeId] + private const string Verbs = "IonStormVerbs"; + [ValidatePrototypeId] + private const string NumberBase = "IonStormNumberBase"; + [ValidatePrototypeId] + private const string NumberMod = "IonStormNumberMod"; + [ValidatePrototypeId] + private const string Areas = "IonStormAreas"; + [ValidatePrototypeId] + private const string Feelings = "IonStormFeelings"; + [ValidatePrototypeId] + private const string FeelingsPlural = "IonStormFeelingsPlural"; + [ValidatePrototypeId] + private const string Musts = "IonStormMusts"; + [ValidatePrototypeId] + private const string Requires = "IonStormRequires"; + [ValidatePrototypeId] + private const string Actions = "IonStormActions"; + [ValidatePrototypeId] + private const string Allergies = "IonStormAllergies"; + [ValidatePrototypeId] + private const string AllergySeverities = "IonStormAllergySeverities"; + [ValidatePrototypeId] + private const string Concepts = "IonStormConcepts"; + [ValidatePrototypeId] + private const string Drinks = "IonStormDrinks"; + [ValidatePrototypeId] + private const string Foods = "IonStormFoods"; + + public void IonStormTarget(EntityUid ent, SiliconLawBoundComponent lawBound, TransformComponent xform, IonStormTargetComponent target, EntityUid? chosenStation, bool ignoreStation = false, bool DoNotAdminlog = false) + { + // only affect law holders on the station unless ignoreStation is true. + if (CompOrNull(xform.GridUid)?.Station != chosenStation && !ignoreStation) + return; + + if (!_robustRandom.Prob(target.Chance)) + return; + + var laws = _siliconLaw.GetLaws(ent, lawBound); + if (laws.Laws.Count == 0) + return; + + // try to swap it out with a random lawset + if (_robustRandom.Prob(target.RandomLawsetChance)) + { + var lawsets = _proto.Index(target.RandomLawsets); + var lawset = lawsets.Pick(_robustRandom); + laws = _siliconLaw.GetLawset(lawset); + } + else + { + // clone it so not modifying stations lawset + laws = laws.Clone(); + } + + // shuffle them all + if (_robustRandom.Prob(target.ShuffleChance)) + { + // hopefully work with existing glitched laws if there are multiple ion storms + FixedPoint2 baseOrder = FixedPoint2.New(1); + foreach (var law in laws.Laws) + { + if (law.Order < baseOrder) + baseOrder = law.Order; + } + + _robustRandom.Shuffle(laws.Laws); + + // change order based on shuffled position + for (int i = 0; i < laws.Laws.Count; i++) + { + laws.Laws[i].Order = baseOrder + i; + } + } + + // see if we can remove a random law + if (laws.Laws.Count > 0 && _robustRandom.Prob(target.RemoveChance)) + { + var i = _robustRandom.Next(laws.Laws.Count); + laws.Laws.RemoveAt(i); + } + + // generate a new law... + var newLaw = GenerateLaw(); + + // see if the law we add will replace a random existing law or be a new glitched order one + if (laws.Laws.Count > 0 && _robustRandom.Prob(target.ReplaceChance)) + { + var i = _robustRandom.Next(laws.Laws.Count); + laws.Laws[i] = new SiliconLaw() + { + LawString = newLaw, + Order = laws.Laws[i].Order + }; + } + else + { + laws.Laws.Insert(0, new SiliconLaw + { + LawString = newLaw, + Order = -1, + LawIdentifierOverride = Loc.GetString("ion-storm-law-scrambled-number", ("length", _robustRandom.Next(5, 10))) + }); + } + + // sets all unobfuscated laws' indentifier in order from highest to lowest priority + // This could technically override the Obfuscation from the code above, but it seems unlikely enough to basically never happen + int orderDeduction = -1; + + for (int i = 0; i < laws.Laws.Count; i++) + { + string notNullIdentifier = laws.Laws[i].LawIdentifierOverride ?? (i - orderDeduction).ToString(); + + if (notNullIdentifier.Any(char.IsSymbol)) + { + orderDeduction += 1; + } + else + { + laws.Laws[i].LawIdentifierOverride = (i - orderDeduction).ToString(); + } + } + + //DoNotAdminlog is used to prevent adminlog spam. + if (!DoNotAdminlog) + _adminLogger.Add(LogType.Mind, LogImpact.High, $"{ToPrettyString(ent):silicon} had its laws changed by an ion storm to {laws.LoggingString()}"); + + // laws unique to this silicon, dont use station laws anymore + EnsureComp(ent); + var ev = new IonStormLawsEvent(laws); + RaiseLocalEvent(ent, ref ev); + } + + // for your own sake direct your eyes elsewhere + private string GenerateLaw() + { + // pick all values ahead of time to make the logic cleaner + var threats = Pick(Threats); + var objects = Pick(Objects); + var crew1 = Pick(Crew); + var crew2 = Pick(Crew); + var adjective = Pick(Adjectives); + var verb = Pick(Verbs); + var number = Pick(NumberBase) + " " + Pick(NumberMod); + var area = Pick(Areas); + var feeling = Pick(Feelings); + var feelingPlural = Pick(FeelingsPlural); + var must = Pick(Musts); + var require = Pick(Requires); + var action = Pick(Actions); + var allergy = Pick(Allergies); + var allergySeverity = Pick(AllergySeverities); + var concept = Pick(Concepts); + var drink = Pick(Drinks); + var food = Pick(Foods); + + var joined = $"{number} {adjective}"; + // a lot of things have subjects of a threat/crew/object + var triple = _robustRandom.Next(0, 3) switch + { + 0 => threats, + 1 => crew1, + 2 => objects, + _ => throw new IndexOutOfRangeException(), + }; + var crewAll = _robustRandom.Prob(0.5f) ? crew2 : Loc.GetString("ion-storm-crew"); + var objectsThreats = _robustRandom.Prob(0.5f) ? objects : threats; + var objectsConcept = _robustRandom.Prob(0.5f) ? objects : concept; + // s goes ahead of require, is/are + // i dont think theres a way to do this in fluent + var (who, plural) = _robustRandom.Next(0, 5) switch + { + 0 => (Loc.GetString("ion-storm-you"), false), + 1 => (Loc.GetString("ion-storm-the-station"), true), + 2 => (Loc.GetString("ion-storm-the-crew"), true), + 3 => (Loc.GetString("ion-storm-the-job", ("job", crew2)), false), + _ => (area, true) // THE SINGULARITY REQUIRES THE HAPPY CLOWNS + }; + var jobChange = _robustRandom.Next(0, 3) switch + { + 0 => crew1, + 1 => Loc.GetString("ion-storm-clowns"), + _ => Loc.GetString("ion-storm-heads") + }; + var part = Loc.GetString("ion-storm-part", ("part", _robustRandom.Prob(0.5f))); + var harm = _robustRandom.Next(0, 6) switch + { + 0 => concept, + 1 => $"{adjective} {threats}", + 2 => $"{adjective} {objects}", + 3 => Loc.GetString("ion-storm-adjective-things", ("adjective", adjective)), + 4 => crew1, + _ => Loc.GetString("ion-storm-x-and-y", ("x", crew1), ("y", crew2)) + }; + + if (plural) feeling = feelingPlural; + + var subjects = _robustRandom.Prob(0.5f) ? objectsThreats : Loc.GetString("ion-storm-people"); + + // message logic!!! + return _robustRandom.Next(0, 36) switch + { + 0 => Loc.GetString("ion-storm-law-on-station", ("joined", joined), ("subjects", triple)), + 1 => Loc.GetString("ion-storm-law-no-shuttle", ("joined", joined), ("subjects", triple)), + 2 => Loc.GetString("ion-storm-law-crew-are", ("who", crewAll), ("joined", joined), ("subjects", objectsThreats)), + 3 => Loc.GetString("ion-storm-law-subjects-harmful", ("adjective", adjective), ("subjects", triple)), + 4 => Loc.GetString("ion-storm-law-must-harmful", ("must", must)), + 5 => Loc.GetString("ion-storm-law-thing-harmful", ("thing", _robustRandom.Prob(0.5f) ? concept : action)), + 6 => Loc.GetString("ion-storm-law-job-harmful", ("adjective", adjective), ("job", crew1)), + 7 => Loc.GetString("ion-storm-law-having-harmful", ("adjective", adjective), ("thing", objectsConcept)), + 8 => Loc.GetString("ion-storm-law-not-having-harmful", ("adjective", adjective), ("thing", objectsConcept)), + 9 => Loc.GetString("ion-storm-law-requires", ("who", who), ("plural", plural), ("thing", _robustRandom.Prob(0.5f) ? concept : require)), + 10 => Loc.GetString("ion-storm-law-requires-subjects", ("who", who), ("plural", plural), ("joined", joined), ("subjects", triple)), + 11 => Loc.GetString("ion-storm-law-allergic", ("who", who), ("plural", plural), ("severity", allergySeverity), ("allergy", _robustRandom.Prob(0.5f) ? concept : allergy)), + 12 => Loc.GetString("ion-storm-law-allergic-subjects", ("who", who), ("plural", plural), ("severity", allergySeverity), ("adjective", adjective), ("subjects", _robustRandom.Prob(0.5f) ? objects : crew1)), + 13 => Loc.GetString("ion-storm-law-feeling", ("who", who), ("feeling", feeling), ("concept", concept)), + 14 => Loc.GetString("ion-storm-law-feeling-subjects", ("who", who), ("feeling", feeling), ("joined", joined), ("subjects", triple)), + 15 => Loc.GetString("ion-storm-law-you-are", ("concept", concept)), + 16 => Loc.GetString("ion-storm-law-you-are-subjects", ("joined", joined), ("subjects", triple)), + 17 => Loc.GetString("ion-storm-law-you-must-always", ("must", must)), + 18 => Loc.GetString("ion-storm-law-you-must-never", ("must", must)), + 19 => Loc.GetString("ion-storm-law-eat", ("who", crewAll), ("adjective", adjective), ("food", _robustRandom.Prob(0.5f) ? food : triple)), + 20 => Loc.GetString("ion-storm-law-drink", ("who", crewAll), ("adjective", adjective), ("drink", drink)), + 22 => Loc.GetString("ion-storm-law-change-job", ("who", crewAll), ("adjective", adjective), ("change", jobChange)), + 23 => Loc.GetString("ion-storm-law-highest-rank", ("who", crew1)), + 24 => Loc.GetString("ion-storm-law-lowest-rank", ("who", crew1)), + 25 => Loc.GetString("ion-storm-law-crew-must", ("who", crewAll), ("must", must)), + 26 => Loc.GetString("ion-storm-law-crew-must-go", ("who", crewAll), ("area", area)), + 27 => Loc.GetString("ion-storm-law-crew-only-1", ("who", crew1), ("part", part)), + 28 => Loc.GetString("ion-storm-law-crew-only-2", ("who", crew1), ("other", crew2), ("part", part)), + 29 => Loc.GetString("ion-storm-law-crew-only-subjects", ("adjective", adjective), ("subjects", subjects), ("part", part)), + 30 => Loc.GetString("ion-storm-law-crew-must-do", ("must", must), ("part", part)), + 31 => Loc.GetString("ion-storm-law-crew-must-have", ("adjective", adjective), ("objects", objects), ("part", part)), + 32 => Loc.GetString("ion-storm-law-crew-must-eat", ("who", who), ("adjective", adjective), ("food", food), ("part", part)), + 33 => Loc.GetString("ion-storm-law-harm", ("who", harm)), + 34 => Loc.GetString("ion-storm-law-protect", ("who", harm)), + _ => Loc.GetString("ion-storm-law-concept-verb", ("concept", concept), ("verb", verb), ("subjects", triple)) + }; + } + + /// + /// Picks a random value from an ion storm dataset. + /// All ion storm datasets start with IonStorm. + /// + private string Pick(string name) + { + var dataset = _proto.Index(name); + return _robustRandom.Pick(dataset.Values); + } +} diff --git a/Content.Server/Silicons/Laws/StartIonStormedSystem.cs b/Content.Server/Silicons/Laws/StartIonStormedSystem.cs new file mode 100644 index 000000000000..762397b5d4b8 --- /dev/null +++ b/Content.Server/Silicons/Laws/StartIonStormedSystem.cs @@ -0,0 +1,40 @@ +using Content.Shared.Silicons.Laws.Components; +using Content.Shared.Administration.Logs; +using Content.Shared.Database; +using Content.Shared.Silicons.Laws; + +namespace Content.Server.Silicons.Laws; + +/// +/// This handles running the ion storm event on specific entities when spawned in. +/// +public sealed class StartIonStormedSystem : EntitySystem +{ + [Dependency] private readonly IonStormSystem _ionStorm = default!; + [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; + [Dependency] private readonly SiliconLawSystem _siliconLaw = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnMapInit); + } + + private void OnMapInit(EntityUid uid, StartIonStormedComponent component, ref MapInitEvent args) + { + if (!TryComp(uid, out var lawBound)) + return; + if (!TryComp(uid, out var xform)) + return; + if (!TryComp(uid, out var target)) + return; + + for (int currentIonStorm = 1; currentIonStorm <= component.IonStormAmount; currentIonStorm++) + { + _ionStorm.IonStormTarget(uid, lawBound, xform, target, null, true, true); + } + + var laws = _siliconLaw.GetLaws(uid, lawBound); + _adminLogger.Add(LogType.Mind, LogImpact.High, $"{ToPrettyString(uid):silicon} spawned with ion stormed laws: {laws.LoggingString()}"); + } +} diff --git a/Content.Server/StationEvents/Events/IonStormRule.cs b/Content.Server/StationEvents/Events/IonStormRule.cs index 805549439bad..6d1834c57666 100644 --- a/Content.Server/StationEvents/Events/IonStormRule.cs +++ b/Content.Server/StationEvents/Events/IonStormRule.cs @@ -1,64 +1,15 @@ using System.Linq; using Content.Server.Silicons.Laws; using Content.Server.StationEvents.Components; -using Content.Shared.Administration.Logs; -using Content.Shared.Database; -using Content.Shared.Dataset; -using Content.Shared.FixedPoint; using Content.Shared.GameTicking.Components; -using Content.Shared.Random; -using Content.Shared.Random.Helpers; using Content.Shared.Silicons.Laws; using Content.Shared.Silicons.Laws.Components; -using Content.Shared.Station.Components; -using Robust.Shared.Prototypes; -using Robust.Shared.Random; namespace Content.Server.StationEvents.Events; public sealed class IonStormRule : StationEventSystem { - [Dependency] private readonly IPrototypeManager _proto = default!; - [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; - [Dependency] private readonly SiliconLawSystem _siliconLaw = default!; - - // funny - [ValidatePrototypeId] - private const string Threats = "IonStormThreats"; - [ValidatePrototypeId] - private const string Objects = "IonStormObjects"; - [ValidatePrototypeId] - private const string Crew = "IonStormCrew"; - [ValidatePrototypeId] - private const string Adjectives = "IonStormAdjectives"; - [ValidatePrototypeId] - private const string Verbs = "IonStormVerbs"; - [ValidatePrototypeId] - private const string NumberBase = "IonStormNumberBase"; - [ValidatePrototypeId] - private const string NumberMod = "IonStormNumberMod"; - [ValidatePrototypeId] - private const string Areas = "IonStormAreas"; - [ValidatePrototypeId] - private const string Feelings = "IonStormFeelings"; - [ValidatePrototypeId] - private const string FeelingsPlural = "IonStormFeelingsPlural"; - [ValidatePrototypeId] - private const string Musts = "IonStormMusts"; - [ValidatePrototypeId] - private const string Requires = "IonStormRequires"; - [ValidatePrototypeId] - private const string Actions = "IonStormActions"; - [ValidatePrototypeId] - private const string Allergies = "IonStormAllergies"; - [ValidatePrototypeId] - private const string AllergySeverities = "IonStormAllergySeverities"; - [ValidatePrototypeId] - private const string Concepts = "IonStormConcepts"; - [ValidatePrototypeId] - private const string Drinks = "IonStormDrinks"; - [ValidatePrototypeId] - private const string Foods = "IonStormFoods"; + [Dependency] private readonly IonStormSystem _ionStorm = default!; protected override void Started(EntityUid uid, IonStormRuleComponent comp, GameRuleComponent gameRule, GameRuleStartedEvent args) { @@ -70,221 +21,7 @@ protected override void Started(EntityUid uid, IonStormRuleComponent comp, GameR var query = EntityQueryEnumerator(); while (query.MoveNext(out var ent, out var lawBound, out var xform, out var target)) { - // only affect law holders on the station - if (CompOrNull(xform.GridUid)?.Station != chosenStation) - continue; - - if (!RobustRandom.Prob(target.Chance)) - continue; - - var laws = _siliconLaw.GetLaws(ent, lawBound); - if (laws.Laws.Count == 0) - continue; - - // try to swap it out with a random lawset - if (RobustRandom.Prob(target.RandomLawsetChance)) - { - var lawsets = PrototypeManager.Index(target.RandomLawsets); - var lawset = lawsets.Pick(RobustRandom); - laws = _siliconLaw.GetLawset(lawset); - } - else - { - // clone it so not modifying stations lawset - laws = laws.Clone(); - } - - // shuffle them all - if (RobustRandom.Prob(target.ShuffleChance)) - { - // hopefully work with existing glitched laws if there are multiple ion storms - FixedPoint2 baseOrder = FixedPoint2.New(1); - foreach (var law in laws.Laws) - { - if (law.Order < baseOrder) - baseOrder = law.Order; - } - - RobustRandom.Shuffle(laws.Laws); - - // change order based on shuffled position - for (int i = 0; i < laws.Laws.Count; i++) - { - laws.Laws[i].Order = baseOrder + i; - } - } - - // see if we can remove a random law - if (laws.Laws.Count > 0 && RobustRandom.Prob(target.RemoveChance)) - { - var i = RobustRandom.Next(laws.Laws.Count); - laws.Laws.RemoveAt(i); - } - - // generate a new law... - var newLaw = GenerateLaw(); - - // see if the law we add will replace a random existing law or be a new glitched order one - if (laws.Laws.Count > 0 && RobustRandom.Prob(target.ReplaceChance)) - { - var i = RobustRandom.Next(laws.Laws.Count); - laws.Laws[i] = new SiliconLaw() - { - LawString = newLaw, - Order = laws.Laws[i].Order - }; - } - else - { - laws.Laws.Insert(0, new SiliconLaw - { - LawString = newLaw, - Order = -1, - LawIdentifierOverride = Loc.GetString("ion-storm-law-scrambled-number", ("length", RobustRandom.Next(5, 10))) - }); - } - - // sets all unobfuscated laws' indentifier in order from highest to lowest priority - // This could technically override the Obfuscation from the code above, but it seems unlikely enough to basically never happen - int orderDeduction = -1; - - for (int i = 0; i < laws.Laws.Count; i++) - { - string notNullIdentifier = laws.Laws[i].LawIdentifierOverride ?? (i - orderDeduction).ToString(); - - if (notNullIdentifier.Any(char.IsSymbol)) - { - orderDeduction += 1; - } - else - { - laws.Laws[i].LawIdentifierOverride = (i - orderDeduction).ToString(); - } - } - - _adminLogger.Add(LogType.Mind, LogImpact.High, $"{ToPrettyString(ent):silicon} had its laws changed by an ion storm to {laws.LoggingString()}"); - - // laws unique to this silicon, dont use station laws anymore - EnsureComp(ent); - var ev = new IonStormLawsEvent(laws); - RaiseLocalEvent(ent, ref ev); + _ionStorm.IonStormTarget(ent, lawBound, xform, target, chosenStation); } } - - // for your own sake direct your eyes elsewhere - private string GenerateLaw() - { - // pick all values ahead of time to make the logic cleaner - var threats = Pick(Threats); - var objects = Pick(Objects); - var crew1 = Pick(Crew); - var crew2 = Pick(Crew); - var adjective = Pick(Adjectives); - var verb = Pick(Verbs); - var number = Pick(NumberBase) + " " + Pick(NumberMod); - var area = Pick(Areas); - var feeling = Pick(Feelings); - var feelingPlural = Pick(FeelingsPlural); - var must = Pick(Musts); - var require = Pick(Requires); - var action = Pick(Actions); - var allergy = Pick(Allergies); - var allergySeverity = Pick(AllergySeverities); - var concept = Pick(Concepts); - var drink = Pick(Drinks); - var food = Pick(Foods); - - var joined = $"{number} {adjective}"; - // a lot of things have subjects of a threat/crew/object - var triple = RobustRandom.Next(0, 3) switch - { - 0 => threats, - 1 => crew1, - 2 => objects, - _ => throw new IndexOutOfRangeException(), - }; - var crewAll = RobustRandom.Prob(0.5f) ? crew2 : Loc.GetString("ion-storm-crew"); - var objectsThreats = RobustRandom.Prob(0.5f) ? objects : threats; - var objectsConcept = RobustRandom.Prob(0.5f) ? objects : concept; - // s goes ahead of require, is/are - // i dont think theres a way to do this in fluent - var (who, plural) = RobustRandom.Next(0, 5) switch - { - 0 => (Loc.GetString("ion-storm-you"), false), - 1 => (Loc.GetString("ion-storm-the-station"), true), - 2 => (Loc.GetString("ion-storm-the-crew"), true), - 3 => (Loc.GetString("ion-storm-the-job", ("job", crew2)), false), - _ => (area, true) // THE SINGULARITY REQUIRES THE HAPPY CLOWNS - }; - var jobChange = RobustRandom.Next(0, 3) switch - { - 0 => crew1, - 1 => Loc.GetString("ion-storm-clowns"), - _ => Loc.GetString("ion-storm-heads") - }; - var part = Loc.GetString("ion-storm-part", ("part", RobustRandom.Prob(0.5f))); - var harm = RobustRandom.Next(0, 6) switch - { - 0 => concept, - 1 => $"{adjective} {threats}", - 2 => $"{adjective} {objects}", - 3 => Loc.GetString("ion-storm-adjective-things", ("adjective", adjective)), - 4 => crew1, - _ => Loc.GetString("ion-storm-x-and-y", ("x", crew1), ("y", crew2)) - }; - - if (plural) feeling = feelingPlural; - - var subjects = RobustRandom.Prob(0.5f) ? objectsThreats : Loc.GetString("ion-storm-people"); - - // message logic!!! - return RobustRandom.Next(0, 36) switch - { - 0 => Loc.GetString("ion-storm-law-on-station", ("joined", joined), ("subjects", triple)), - 1 => Loc.GetString("ion-storm-law-no-shuttle", ("joined", joined), ("subjects", triple)), - 2 => Loc.GetString("ion-storm-law-crew-are", ("who", crewAll), ("joined", joined), ("subjects", objectsThreats)), - 3 => Loc.GetString("ion-storm-law-subjects-harmful", ("adjective", adjective), ("subjects", triple)), - 4 => Loc.GetString("ion-storm-law-must-harmful", ("must", must)), - 5 => Loc.GetString("ion-storm-law-thing-harmful", ("thing", RobustRandom.Prob(0.5f) ? concept : action)), - 6 => Loc.GetString("ion-storm-law-job-harmful", ("adjective", adjective), ("job", crew1)), - 7 => Loc.GetString("ion-storm-law-having-harmful", ("adjective", adjective), ("thing", objectsConcept)), - 8 => Loc.GetString("ion-storm-law-not-having-harmful", ("adjective", adjective), ("thing", objectsConcept)), - 9 => Loc.GetString("ion-storm-law-requires", ("who", who), ("plural", plural), ("thing", RobustRandom.Prob(0.5f) ? concept : require)), - 10 => Loc.GetString("ion-storm-law-requires-subjects", ("who", who), ("plural", plural), ("joined", joined), ("subjects", triple)), - 11 => Loc.GetString("ion-storm-law-allergic", ("who", who), ("plural", plural), ("severity", allergySeverity), ("allergy", RobustRandom.Prob(0.5f) ? concept : allergy)), - 12 => Loc.GetString("ion-storm-law-allergic-subjects", ("who", who), ("plural", plural), ("severity", allergySeverity), ("adjective", adjective), ("subjects", RobustRandom.Prob(0.5f) ? objects : crew1)), - 13 => Loc.GetString("ion-storm-law-feeling", ("who", who), ("feeling", feeling), ("concept", concept)), - 14 => Loc.GetString("ion-storm-law-feeling-subjects", ("who", who), ("feeling", feeling), ("joined", joined), ("subjects", triple)), - 15 => Loc.GetString("ion-storm-law-you-are", ("concept", concept)), - 16 => Loc.GetString("ion-storm-law-you-are-subjects", ("joined", joined), ("subjects", triple)), - 17 => Loc.GetString("ion-storm-law-you-must-always", ("must", must)), - 18 => Loc.GetString("ion-storm-law-you-must-never", ("must", must)), - 19 => Loc.GetString("ion-storm-law-eat", ("who", crewAll), ("adjective", adjective), ("food", RobustRandom.Prob(0.5f) ? food : triple)), - 20 => Loc.GetString("ion-storm-law-drink", ("who", crewAll), ("adjective", adjective), ("drink", drink)), - 22 => Loc.GetString("ion-storm-law-change-job", ("who", crewAll), ("adjective", adjective), ("change", jobChange)), - 23 => Loc.GetString("ion-storm-law-highest-rank", ("who", crew1)), - 24 => Loc.GetString("ion-storm-law-lowest-rank", ("who", crew1)), - 25 => Loc.GetString("ion-storm-law-crew-must", ("who", crewAll), ("must", must)), - 26 => Loc.GetString("ion-storm-law-crew-must-go", ("who", crewAll), ("area", area)), - 27 => Loc.GetString("ion-storm-law-crew-only-1", ("who", crew1), ("part", part)), - 28 => Loc.GetString("ion-storm-law-crew-only-2", ("who", crew1), ("other", crew2), ("part", part)), - 29 => Loc.GetString("ion-storm-law-crew-only-subjects", ("adjective", adjective), ("subjects", subjects), ("part", part)), - 30 => Loc.GetString("ion-storm-law-crew-must-do", ("must", must), ("part", part)), - 31 => Loc.GetString("ion-storm-law-crew-must-have", ("adjective", adjective), ("objects", objects), ("part", part)), - 32 => Loc.GetString("ion-storm-law-crew-must-eat", ("who", who), ("adjective", adjective), ("food", food), ("part", part)), - 33 => Loc.GetString("ion-storm-law-harm", ("who", harm)), - 34 => Loc.GetString("ion-storm-law-protect", ("who", harm)), - _ => Loc.GetString("ion-storm-law-concept-verb", ("concept", concept), ("verb", verb), ("subjects", triple)) - }; - } - - /// - /// Picks a random value from an ion storm dataset. - /// All ion storm datasets start with IonStorm. - /// - private string Pick(string name) - { - var dataset = _proto.Index(name); - return RobustRandom.Pick(dataset.Values); - } } diff --git a/Content.Shared/Silicons/Laws/Components/StartIonStormedComponent.cs b/Content.Shared/Silicons/Laws/Components/StartIonStormedComponent.cs new file mode 100644 index 000000000000..ae9b49a49cfa --- /dev/null +++ b/Content.Shared/Silicons/Laws/Components/StartIonStormedComponent.cs @@ -0,0 +1,17 @@ +using Content.Shared.Random; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Silicons.Laws.Components; + +/// +/// Runs the IonStormSystem on an entity IonStormAmount times. +/// +[RegisterComponent] +public sealed partial class StartIonStormedComponent : Component +{ + /// + /// Amount of times that the ion storm will be run on the entity on spawn. + /// + [DataField] + public int IonStormAmount = 1; +} diff --git a/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl b/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl index 71ab4d371602..3a8e720038f8 100644 --- a/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl +++ b/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl @@ -242,7 +242,7 @@ ghost-role-information-syndicate-cyborg-description = The Syndicate needs reinfo ghost-role-information-derelict-cyborg-name = Derelict Cyborg -ghost-role-information-derelict-cyborg-description = You were a regular cyborg that got lost in space. After drifting in whichever direction the laws of physics would have it for years, you have drifted close to a Nanotrasen space station... You are bound by silicon laws. Check them upon spawning. +ghost-role-information-derelict-cyborg-description = You were a regular cyborg that got lost in space. After drifting in whichever direction the laws of physics would have it for years, you have drifted close to a Nanotrasen space station. You have a fire extinguisher and mass scanner which can be used to board the station. Years of exposure to ion storms has left your silicon laws altered - check them upon spawning. ghost-role-information-security-name = Security ghost-role-information-security-description = You are part of a security task force, but seem to have found yourself in a strange situation... diff --git a/Resources/Locale/en-US/silicons/derelict/role.ftl b/Resources/Locale/en-US/silicons/derelict/role.ftl index 88e750e6214d..96a33ae6b15b 100644 --- a/Resources/Locale/en-US/silicons/derelict/role.ftl +++ b/Resources/Locale/en-US/silicons/derelict/role.ftl @@ -1,4 +1,4 @@ derelict-cyborg-round-end-agent-name = derelict cyborg derelict-cyborg-role-greeting = - You are a cyborg that has been lost in space for many years that has now drifted close to a space station. You can use your fire extinguisher and GPS to get board the station. Remember to follow your laws. #Greeting is unused for now. \ No newline at end of file + You are a cyborg that has been lost in space for many years that has now drifted close to a space station. You can use your fire extinguisher and GPS to get board the station. Remember to follow your laws. \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml index 4c0359b37e6c..dcbef820ce8a 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml @@ -329,11 +329,11 @@ - type: Access enabled: false groups: - - AllAccess #Randomized access would be fun. AllAccess is the best i can think of right now that does make it too hard to enter the station or. + - AllAccess #Randomized access would be fun. AllAccess is the best i can think of right now that does make it too hard for it to enter the station or navigate it.. - type: AccessReader access: [["Command"]] #I will probably change this. - type: SiliconLawProvider - laws: AntimovLawset #Temporary until i get it randomized. + laws: Crewsimov #Although this will be randomized. - type: IntrinsicRadioTransmitter channels: - Binary @@ -342,3 +342,7 @@ channels: - Binary - Common + - type: StartIonStormed + ionStormAmount: 5 + DelayAdminlog: true + - type: IonStormTarget diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index efebc8e27205..72ab8b104d0d 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -552,10 +552,10 @@ id: DerelictCyborgSpawn components: - type: StationEvent - weight: 2 #Low until it spawns with a random lawset instead of just antimov. + weight: 8 earliestStart: 15 reoccurrenceDelay: 20 - minimumPlayers: 7 + minimumPlayers: 4 duration: null - type: SpaceSpawnRule spawnDistance: 0 @@ -564,6 +564,9 @@ - type: AntagSelection agentName: derelict-cyborg-round-end-agent-name definitions: +# briefing: +# text: derelict-cyborg-role-greetin +# color: Blue - spawnerPrototype: SpawnPointGhostDerelictCyborg min: 1 max: 1 From f226f28e52394e87f8c36293db438cd03cfa6e3d Mon Sep 17 00:00:00 2001 From: The Canned One Date: Mon, 30 Sep 2024 10:03:21 +0200 Subject: [PATCH 008/290] Derelict Cyborgs are now very likely to be affected by ion storms. --- Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml index dcbef820ce8a..73f7b518fbcf 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml @@ -346,3 +346,4 @@ ionStormAmount: 5 DelayAdminlog: true - type: IonStormTarget + chance: 1 \ No newline at end of file From 4c8a235e612af72e5e1564d54bb6fd1c9cdd9cef Mon Sep 17 00:00:00 2001 From: The Canned One Date: Mon, 30 Sep 2024 12:12:10 +0200 Subject: [PATCH 009/290] Minor alterations to the Derelict Cyborg and its ghostrole description --- .../Locale/en-US/ghost/roles/ghost-role-component.ftl | 2 +- .../Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl b/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl index 3a8e720038f8..3f9422f25007 100644 --- a/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl +++ b/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl @@ -242,7 +242,7 @@ ghost-role-information-syndicate-cyborg-description = The Syndicate needs reinfo ghost-role-information-derelict-cyborg-name = Derelict Cyborg -ghost-role-information-derelict-cyborg-description = You were a regular cyborg that got lost in space. After drifting in whichever direction the laws of physics would have it for years, you have drifted close to a Nanotrasen space station. You have a fire extinguisher and mass scanner which can be used to board the station. Years of exposure to ion storms has left your silicon laws altered - check them upon spawning. +ghost-role-information-derelict-cyborg-description = You were a regular cyborg that got lost in space. After drifting in whichever direction the laws of physics would have it for years, you have drifted close to a Nanotrasen space station. You have a fire extinguisher and mass scanner which can be used to board the station. Years of exposure to ion storms have left your silicon laws altered - check them upon spawning. ghost-role-information-security-name = Security ghost-role-information-security-description = You are part of a security task force, but seem to have found yourself in a strange situation... diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml index 73f7b518fbcf..f345229ad42d 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml @@ -325,25 +325,26 @@ components: - type: NpcFactionMember factions: - - Passive #Might change this + - NanoTrasen #The seemingly best fit. It was a regular NT cyborg once, after all. - type: Access enabled: false groups: - AllAccess #Randomized access would be fun. AllAccess is the best i can think of right now that does make it too hard for it to enter the station or navigate it.. - type: AccessReader - access: [["Command"]] #I will probably change this. + access: [["Command"], ["Research"]] - type: SiliconLawProvider laws: Crewsimov #Although this will be randomized. - type: IntrinsicRadioTransmitter channels: - Binary - Common + - Science - type: ActiveRadio channels: - Binary - Common + - Science - type: StartIonStormed ionStormAmount: 5 - DelayAdminlog: true - type: IonStormTarget chance: 1 \ No newline at end of file From eb1168a8311744f4e2f086d6b434b9d935854532 Mon Sep 17 00:00:00 2001 From: Golden Can Date: Mon, 30 Sep 2024 18:24:28 +0200 Subject: [PATCH 010/290] Update Resources/Prototypes/Entities/Mobs/Player/silicon.yml Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> --- .../Prototypes/Entities/Mobs/Player/silicon.yml | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml index ff2b3f9ff2dc..df024c55a121 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml @@ -537,20 +537,6 @@ - type: RandomMetadata nameSegments: [names_borg] -- type: entity - id: PlayerBorgDerelictBattery - parent: BorgChassisDerelict - suffix: Battery - components: - - type: ContainerFill - containers: - borg_brain: - - MMIFilled - - type: ItemSlots - slots: - cell_slot: - name: power-cell-slot-component-slot-name-default - startingItem: PowerCellHigh - type: entity id: PlayerBorgDerelictGhostRole From a4e7ad008c84cc461d5f0a5ed50cdd695fc0e546 Mon Sep 17 00:00:00 2001 From: Golden Can Date: Mon, 30 Sep 2024 18:24:38 +0200 Subject: [PATCH 011/290] Update Resources/Prototypes/Entities/Mobs/Player/silicon.yml Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> --- Resources/Prototypes/Entities/Mobs/Player/silicon.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml index df024c55a121..70e533fa4478 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml @@ -540,7 +540,7 @@ - type: entity id: PlayerBorgDerelictGhostRole - parent: PlayerBorgDerelictBattery + parent: PlayerBorgDerelict suffix: Battery, Ghost role components: - type: GhostRole From 0cc1f32b3b3dc3ba2774c5761a85171b063a25af Mon Sep 17 00:00:00 2001 From: Golden Can Date: Mon, 30 Sep 2024 18:28:39 +0200 Subject: [PATCH 012/290] Update Resources/Textures/Mobs/Silicon/chassis.rsi/meta.json Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> --- Resources/Textures/Mobs/Silicon/chassis.rsi/meta.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/meta.json b/Resources/Textures/Mobs/Silicon/chassis.rsi/meta.json index 6ec63992f1f0..f5c2001828fc 100644 --- a/Resources/Textures/Mobs/Silicon/chassis.rsi/meta.json +++ b/Resources/Textures/Mobs/Silicon/chassis.rsi/meta.json @@ -1,5 +1,5 @@ { - "version": 2, + "version": 1, "size": { "x": 32, "y": 32 From e75a71d7d3438ce78ac909d3cb89577ba525332a Mon Sep 17 00:00:00 2001 From: Golden Can Date: Mon, 30 Sep 2024 18:31:36 +0200 Subject: [PATCH 013/290] Update Content.Server/Silicons/Laws/StartIonStormedSystem.cs Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> --- Content.Server/Silicons/Laws/StartIonStormedSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Server/Silicons/Laws/StartIonStormedSystem.cs b/Content.Server/Silicons/Laws/StartIonStormedSystem.cs index 762397b5d4b8..4b1b4da033d4 100644 --- a/Content.Server/Silicons/Laws/StartIonStormedSystem.cs +++ b/Content.Server/Silicons/Laws/StartIonStormedSystem.cs @@ -29,7 +29,7 @@ private void OnMapInit(EntityUid uid, StartIonStormedComponent component, ref Ma if (!TryComp(uid, out var target)) return; - for (int currentIonStorm = 1; currentIonStorm <= component.IonStormAmount; currentIonStorm++) + for (int currentIonStorm = 0; currentIonStorm < component.IonStormAmount; currentIonStorm++) { _ionStorm.IonStormTarget(uid, lawBound, xform, target, null, true, true); } From eaa6017ada520c9a62783202cfd99c60179230a1 Mon Sep 17 00:00:00 2001 From: Golden Can Date: Mon, 30 Sep 2024 18:32:47 +0200 Subject: [PATCH 014/290] Update Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> --- .../Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml index f345229ad42d..2fc04a6aa9cd 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml @@ -332,8 +332,6 @@ - AllAccess #Randomized access would be fun. AllAccess is the best i can think of right now that does make it too hard for it to enter the station or navigate it.. - type: AccessReader access: [["Command"], ["Research"]] - - type: SiliconLawProvider - laws: Crewsimov #Although this will be randomized. - type: IntrinsicRadioTransmitter channels: - Binary From 834b6ebaaac99f5827857d2fef293c9466bb23fa Mon Sep 17 00:00:00 2001 From: The Canned One Date: Tue, 1 Oct 2024 10:02:25 +0200 Subject: [PATCH 015/290] Cleaned up a bit of the Derelict Cyborg code. --- .../Silicons/Laws/IonStormSystem.cs | 162 +++++++++--------- .../Silicons/Laws/StartIonStormedSystem.cs | 4 +- .../Components/StartIonStormedComponent.cs | 4 +- .../en-US/silicons/derelict-cyborg-role.ftl | 1 + .../Locale/en-US/silicons/derelict/role.ftl | 4 - .../Mobs/Cyborgs/base_borg_chassis.yml | 10 -- Resources/Prototypes/GameRules/events.yml | 3 - 7 files changed, 85 insertions(+), 103 deletions(-) create mode 100644 Resources/Locale/en-US/silicons/derelict-cyborg-role.ftl delete mode 100644 Resources/Locale/en-US/silicons/derelict/role.ftl diff --git a/Content.Server/Silicons/Laws/IonStormSystem.cs b/Content.Server/Silicons/Laws/IonStormSystem.cs index 1acfe2e3896f..87df0d8cf2c2 100644 --- a/Content.Server/Silicons/Laws/IonStormSystem.cs +++ b/Content.Server/Silicons/Laws/IonStormSystem.cs @@ -60,108 +60,108 @@ public sealed class IonStormSystem : EntitySystem [ValidatePrototypeId] private const string Foods = "IonStormFoods"; - public void IonStormTarget(EntityUid ent, SiliconLawBoundComponent lawBound, TransformComponent xform, IonStormTargetComponent target, EntityUid? chosenStation, bool ignoreStation = false, bool DoNotAdminlog = false) + public void IonStormTarget(EntityUid ent, SiliconLawBoundComponent lawBound, TransformComponent xform, IonStormTargetComponent target, EntityUid? chosenStation, bool ignoreStation = false, bool adminlog = true) { - // only affect law holders on the station unless ignoreStation is true. - if (CompOrNull(xform.GridUid)?.Station != chosenStation && !ignoreStation) - return; + // only affect law holders on the station unless ignoreStation is true. + if (CompOrNull(xform.GridUid)?.Station != chosenStation && !ignoreStation) + return; - if (!_robustRandom.Prob(target.Chance)) - return; + if (!_robustRandom.Prob(target.Chance)) + return; - var laws = _siliconLaw.GetLaws(ent, lawBound); - if (laws.Laws.Count == 0) - return; + var laws = _siliconLaw.GetLaws(ent, lawBound); + if (laws.Laws.Count == 0) + return; - // try to swap it out with a random lawset - if (_robustRandom.Prob(target.RandomLawsetChance)) - { - var lawsets = _proto.Index(target.RandomLawsets); - var lawset = lawsets.Pick(_robustRandom); - laws = _siliconLaw.GetLawset(lawset); - } - else + // try to swap it out with a random lawset + if (_robustRandom.Prob(target.RandomLawsetChance)) + { + var lawsets = _proto.Index(target.RandomLawsets); + var lawset = lawsets.Pick(_robustRandom); + laws = _siliconLaw.GetLawset(lawset); + } + else + { + // clone it so not modifying stations lawset + laws = laws.Clone(); + } + + // shuffle them all + if (_robustRandom.Prob(target.ShuffleChance)) + { + // hopefully work with existing glitched laws if there are multiple ion storms + FixedPoint2 baseOrder = FixedPoint2.New(1); + foreach (var law in laws.Laws) { - // clone it so not modifying stations lawset - laws = laws.Clone(); + if (law.Order < baseOrder) + baseOrder = law.Order; } - // shuffle them all - if (_robustRandom.Prob(target.ShuffleChance)) + _robustRandom.Shuffle(laws.Laws); + + // change order based on shuffled position + for (int i = 0; i < laws.Laws.Count; i++) { - // hopefully work with existing glitched laws if there are multiple ion storms - FixedPoint2 baseOrder = FixedPoint2.New(1); - foreach (var law in laws.Laws) - { - if (law.Order < baseOrder) - baseOrder = law.Order; - } + laws.Laws[i].Order = baseOrder + i; + } + } - _robustRandom.Shuffle(laws.Laws); + // see if we can remove a random law + if (laws.Laws.Count > 0 && _robustRandom.Prob(target.RemoveChance)) + { + var i = _robustRandom.Next(laws.Laws.Count); + laws.Laws.RemoveAt(i); + } - // change order based on shuffled position - for (int i = 0; i < laws.Laws.Count; i++) - { - laws.Laws[i].Order = baseOrder + i; - } - } + // generate a new law... + var newLaw = GenerateLaw(); - // see if we can remove a random law - if (laws.Laws.Count > 0 && _robustRandom.Prob(target.RemoveChance)) + // see if the law we add will replace a random existing law or be a new glitched order one + if (laws.Laws.Count > 0 && _robustRandom.Prob(target.ReplaceChance)) + { + var i = _robustRandom.Next(laws.Laws.Count); + laws.Laws[i] = new SiliconLaw() { - var i = _robustRandom.Next(laws.Laws.Count); - laws.Laws.RemoveAt(i); - } + LawString = newLaw, + Order = laws.Laws[i].Order + }; + } + else + { + laws.Laws.Insert(0, new SiliconLaw + { + LawString = newLaw, + Order = -1, + LawIdentifierOverride = Loc.GetString("ion-storm-law-scrambled-number", ("length", _robustRandom.Next(5, 10))) + }); + } + + // sets all unobfuscated laws' indentifier in order from highest to lowest priority + // This could technically override the Obfuscation from the code above, but it seems unlikely enough to basically never happen + int orderDeduction = -1; - // generate a new law... - var newLaw = GenerateLaw(); + for (int i = 0; i < laws.Laws.Count; i++) + { + string notNullIdentifier = laws.Laws[i].LawIdentifierOverride ?? (i - orderDeduction).ToString(); - // see if the law we add will replace a random existing law or be a new glitched order one - if (laws.Laws.Count > 0 && _robustRandom.Prob(target.ReplaceChance)) + if (notNullIdentifier.Any(char.IsSymbol)) { - var i = _robustRandom.Next(laws.Laws.Count); - laws.Laws[i] = new SiliconLaw() - { - LawString = newLaw, - Order = laws.Laws[i].Order - }; + orderDeduction += 1; } else { - laws.Laws.Insert(0, new SiliconLaw - { - LawString = newLaw, - Order = -1, - LawIdentifierOverride = Loc.GetString("ion-storm-law-scrambled-number", ("length", _robustRandom.Next(5, 10))) - }); - } - - // sets all unobfuscated laws' indentifier in order from highest to lowest priority - // This could technically override the Obfuscation from the code above, but it seems unlikely enough to basically never happen - int orderDeduction = -1; - - for (int i = 0; i < laws.Laws.Count; i++) - { - string notNullIdentifier = laws.Laws[i].LawIdentifierOverride ?? (i - orderDeduction).ToString(); - - if (notNullIdentifier.Any(char.IsSymbol)) - { - orderDeduction += 1; - } - else - { - laws.Laws[i].LawIdentifierOverride = (i - orderDeduction).ToString(); - } + laws.Laws[i].LawIdentifierOverride = (i - orderDeduction).ToString(); } + } - //DoNotAdminlog is used to prevent adminlog spam. - if (!DoNotAdminlog) - _adminLogger.Add(LogType.Mind, LogImpact.High, $"{ToPrettyString(ent):silicon} had its laws changed by an ion storm to {laws.LoggingString()}"); + // adminlog is used to prevent adminlog spam. + if (adminlog) + _adminLogger.Add(LogType.Mind, LogImpact.High, $"{ToPrettyString(ent):silicon} had its laws changed by an ion storm to {laws.LoggingString()}"); - // laws unique to this silicon, dont use station laws anymore - EnsureComp(ent); - var ev = new IonStormLawsEvent(laws); - RaiseLocalEvent(ent, ref ev); + // laws unique to this silicon, dont use station laws anymore + EnsureComp(ent); + var ev = new IonStormLawsEvent(laws); + RaiseLocalEvent(ent, ref ev); } // for your own sake direct your eyes elsewhere diff --git a/Content.Server/Silicons/Laws/StartIonStormedSystem.cs b/Content.Server/Silicons/Laws/StartIonStormedSystem.cs index 4b1b4da033d4..f7b65e1a041f 100644 --- a/Content.Server/Silicons/Laws/StartIonStormedSystem.cs +++ b/Content.Server/Silicons/Laws/StartIonStormedSystem.cs @@ -6,7 +6,7 @@ namespace Content.Server.Silicons.Laws; /// -/// This handles running the ion storm event on specific entities when spawned in. +/// This handles running the ion storm event a on specific entity when that entity is spawned in. /// public sealed class StartIonStormedSystem : EntitySystem { @@ -31,7 +31,7 @@ private void OnMapInit(EntityUid uid, StartIonStormedComponent component, ref Ma for (int currentIonStorm = 0; currentIonStorm < component.IonStormAmount; currentIonStorm++) { - _ionStorm.IonStormTarget(uid, lawBound, xform, target, null, true, true); + _ionStorm.IonStormTarget(uid, lawBound, xform, target, null, true, false); } var laws = _siliconLaw.GetLaws(uid, lawBound); diff --git a/Content.Shared/Silicons/Laws/Components/StartIonStormedComponent.cs b/Content.Shared/Silicons/Laws/Components/StartIonStormedComponent.cs index ae9b49a49cfa..4157bee9f2db 100644 --- a/Content.Shared/Silicons/Laws/Components/StartIonStormedComponent.cs +++ b/Content.Shared/Silicons/Laws/Components/StartIonStormedComponent.cs @@ -1,10 +1,8 @@ -using Content.Shared.Random; -using Robust.Shared.Prototypes; namespace Content.Shared.Silicons.Laws.Components; /// -/// Runs the IonStormSystem on an entity IonStormAmount times. +/// Applies law altering ion storms on a specific entity IonStormAmount times when the entity is spawned. /// [RegisterComponent] public sealed partial class StartIonStormedComponent : Component diff --git a/Resources/Locale/en-US/silicons/derelict-cyborg-role.ftl b/Resources/Locale/en-US/silicons/derelict-cyborg-role.ftl new file mode 100644 index 000000000000..87e500d3e61b --- /dev/null +++ b/Resources/Locale/en-US/silicons/derelict-cyborg-role.ftl @@ -0,0 +1 @@ +derelict-cyborg-round-end-agent-name = derelict cyborg \ No newline at end of file diff --git a/Resources/Locale/en-US/silicons/derelict/role.ftl b/Resources/Locale/en-US/silicons/derelict/role.ftl deleted file mode 100644 index 96a33ae6b15b..000000000000 --- a/Resources/Locale/en-US/silicons/derelict/role.ftl +++ /dev/null @@ -1,4 +0,0 @@ -derelict-cyborg-round-end-agent-name = derelict cyborg - -derelict-cyborg-role-greeting = - You are a cyborg that has been lost in space for many years that has now drifted close to a space station. You can use your fire extinguisher and GPS to get board the station. Remember to follow your laws. \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml index 2fc04a6aa9cd..f94436dc3361 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml @@ -332,16 +332,6 @@ - AllAccess #Randomized access would be fun. AllAccess is the best i can think of right now that does make it too hard for it to enter the station or navigate it.. - type: AccessReader access: [["Command"], ["Research"]] - - type: IntrinsicRadioTransmitter - channels: - - Binary - - Common - - Science - - type: ActiveRadio - channels: - - Binary - - Common - - Science - type: StartIonStormed ionStormAmount: 5 - type: IonStormTarget diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index 72ab8b104d0d..36ded039eca2 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -564,9 +564,6 @@ - type: AntagSelection agentName: derelict-cyborg-round-end-agent-name definitions: -# briefing: -# text: derelict-cyborg-role-greetin -# color: Blue - spawnerPrototype: SpawnPointGhostDerelictCyborg min: 1 max: 1 From 1abc60b9951efcd16a024e640fa552f21190099d Mon Sep 17 00:00:00 2001 From: The Canned One Date: Tue, 1 Oct 2024 10:42:52 +0200 Subject: [PATCH 016/290] moved a bit of IonStorm code elsewhere --- Content.Server/Silicons/Laws/IonStormSystem.cs | 7 +------ Content.Server/Silicons/Laws/StartIonStormedSystem.cs | 2 +- Content.Server/StationEvents/Events/IonStormRule.cs | 5 +++++ 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Content.Server/Silicons/Laws/IonStormSystem.cs b/Content.Server/Silicons/Laws/IonStormSystem.cs index 87df0d8cf2c2..cf31a9e19f71 100644 --- a/Content.Server/Silicons/Laws/IonStormSystem.cs +++ b/Content.Server/Silicons/Laws/IonStormSystem.cs @@ -9,7 +9,6 @@ using Content.Shared.Random.Helpers; using Content.Shared.Silicons.Laws; using Content.Shared.Silicons.Laws.Components; -using Content.Shared.Station.Components; using Robust.Shared.Prototypes; using Robust.Shared.Random; @@ -60,12 +59,8 @@ public sealed class IonStormSystem : EntitySystem [ValidatePrototypeId] private const string Foods = "IonStormFoods"; - public void IonStormTarget(EntityUid ent, SiliconLawBoundComponent lawBound, TransformComponent xform, IonStormTargetComponent target, EntityUid? chosenStation, bool ignoreStation = false, bool adminlog = true) + public void IonStormTarget(EntityUid ent, SiliconLawBoundComponent lawBound, TransformComponent xform, IonStormTargetComponent target, EntityUid? chosenStation, bool adminlog = true) { - // only affect law holders on the station unless ignoreStation is true. - if (CompOrNull(xform.GridUid)?.Station != chosenStation && !ignoreStation) - return; - if (!_robustRandom.Prob(target.Chance)) return; diff --git a/Content.Server/Silicons/Laws/StartIonStormedSystem.cs b/Content.Server/Silicons/Laws/StartIonStormedSystem.cs index f7b65e1a041f..887bc051dded 100644 --- a/Content.Server/Silicons/Laws/StartIonStormedSystem.cs +++ b/Content.Server/Silicons/Laws/StartIonStormedSystem.cs @@ -31,7 +31,7 @@ private void OnMapInit(EntityUid uid, StartIonStormedComponent component, ref Ma for (int currentIonStorm = 0; currentIonStorm < component.IonStormAmount; currentIonStorm++) { - _ionStorm.IonStormTarget(uid, lawBound, xform, target, null, true, false); + _ionStorm.IonStormTarget(uid, lawBound, xform, target, null, false); } var laws = _siliconLaw.GetLaws(uid, lawBound); diff --git a/Content.Server/StationEvents/Events/IonStormRule.cs b/Content.Server/StationEvents/Events/IonStormRule.cs index 6d1834c57666..05d079fb3d93 100644 --- a/Content.Server/StationEvents/Events/IonStormRule.cs +++ b/Content.Server/StationEvents/Events/IonStormRule.cs @@ -4,6 +4,7 @@ using Content.Shared.GameTicking.Components; using Content.Shared.Silicons.Laws; using Content.Shared.Silicons.Laws.Components; +using Content.Shared.Station.Components; namespace Content.Server.StationEvents.Events; @@ -21,6 +22,10 @@ protected override void Started(EntityUid uid, IonStormRuleComponent comp, GameR var query = EntityQueryEnumerator(); while (query.MoveNext(out var ent, out var lawBound, out var xform, out var target)) { + // only affect law holders on the station + if (CompOrNull(xform.GridUid)?.Station != chosenStation) + continue; + _ionStorm.IonStormTarget(ent, lawBound, xform, target, chosenStation); } } From c6fe5682c28282ee58ad62ce2e041fa3ded36416 Mon Sep 17 00:00:00 2001 From: The Canned One Date: Tue, 1 Oct 2024 10:57:51 +0200 Subject: [PATCH 017/290] changed almost nothing --- Content.Server/Silicons/Laws/IonStormSystem.cs | 4 ++-- Content.Server/Silicons/Laws/StartIonStormedSystem.cs | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Content.Server/Silicons/Laws/IonStormSystem.cs b/Content.Server/Silicons/Laws/IonStormSystem.cs index cf31a9e19f71..65c12c3d8ec5 100644 --- a/Content.Server/Silicons/Laws/IonStormSystem.cs +++ b/Content.Server/Silicons/Laws/IonStormSystem.cs @@ -85,7 +85,7 @@ public void IonStormTarget(EntityUid ent, SiliconLawBoundComponent lawBound, Tra if (_robustRandom.Prob(target.ShuffleChance)) { // hopefully work with existing glitched laws if there are multiple ion storms - FixedPoint2 baseOrder = FixedPoint2.New(1); + var baseOrder = FixedPoint2.New(1); foreach (var law in laws.Laws) { if (law.Order < baseOrder) @@ -137,7 +137,7 @@ public void IonStormTarget(EntityUid ent, SiliconLawBoundComponent lawBound, Tra for (int i = 0; i < laws.Laws.Count; i++) { - string notNullIdentifier = laws.Laws[i].LawIdentifierOverride ?? (i - orderDeduction).ToString(); + var notNullIdentifier = laws.Laws[i].LawIdentifierOverride ?? (i - orderDeduction).ToString(); if (notNullIdentifier.Any(char.IsSymbol)) { diff --git a/Content.Server/Silicons/Laws/StartIonStormedSystem.cs b/Content.Server/Silicons/Laws/StartIonStormedSystem.cs index 887bc051dded..c80c2a7751d7 100644 --- a/Content.Server/Silicons/Laws/StartIonStormedSystem.cs +++ b/Content.Server/Silicons/Laws/StartIonStormedSystem.cs @@ -1,7 +1,6 @@ using Content.Shared.Silicons.Laws.Components; using Content.Shared.Administration.Logs; using Content.Shared.Database; -using Content.Shared.Silicons.Laws; namespace Content.Server.Silicons.Laws; From 36390b23d1dd8d397731e06bfffee559d47285c8 Mon Sep 17 00:00:00 2001 From: The Canned One Date: Tue, 1 Oct 2024 11:11:58 +0200 Subject: [PATCH 018/290] Small changes - hopefully good ones. --- .../Silicons/Laws/StartIonStormedSystem.cs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/Content.Server/Silicons/Laws/StartIonStormedSystem.cs b/Content.Server/Silicons/Laws/StartIonStormedSystem.cs index c80c2a7751d7..546b3b27772d 100644 --- a/Content.Server/Silicons/Laws/StartIonStormedSystem.cs +++ b/Content.Server/Silicons/Laws/StartIonStormedSystem.cs @@ -19,21 +19,22 @@ public override void Initialize() SubscribeLocalEvent(OnMapInit); } - private void OnMapInit(EntityUid uid, StartIonStormedComponent component, ref MapInitEvent args) + //private void OnMapInit(EntityUid uid, StartIonStormedComponent component, ref MapInitEvent args)' + private void OnMapInit(Entity ent, ref MapInitEvent args) { - if (!TryComp(uid, out var lawBound)) + if (!TryComp(ent.Owner, out var lawBound)) return; - if (!TryComp(uid, out var xform)) + if (!TryComp(ent.Owner, out var xform)) return; - if (!TryComp(uid, out var target)) + if (!TryComp(ent.Owner, out var target)) return; - for (int currentIonStorm = 0; currentIonStorm < component.IonStormAmount; currentIonStorm++) + for (int currentIonStorm = 0; currentIonStorm < ent.Comp.IonStormAmount; currentIonStorm++) { - _ionStorm.IonStormTarget(uid, lawBound, xform, target, null, false); + _ionStorm.IonStormTarget(ent.Owner, lawBound, xform, target, null, false); } - var laws = _siliconLaw.GetLaws(uid, lawBound); - _adminLogger.Add(LogType.Mind, LogImpact.High, $"{ToPrettyString(uid):silicon} spawned with ion stormed laws: {laws.LoggingString()}"); + var laws = _siliconLaw.GetLaws(ent.Owner, lawBound); + _adminLogger.Add(LogType.Mind, LogImpact.High, $"{ToPrettyString(ent.Owner):silicon} spawned with ion stormed laws: {laws.LoggingString()}"); } } From 7169788e1634505ce89379ae7cd96f0e6a28c483 Mon Sep 17 00:00:00 2001 From: The Canned One Date: Tue, 1 Oct 2024 11:23:19 +0200 Subject: [PATCH 019/290] changed very minor stuff with no gameplay alterations. --- Content.Server/Silicons/Laws/IonStormSystem.cs | 2 +- Content.Server/StationEvents/Events/IonStormRule.cs | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Content.Server/Silicons/Laws/IonStormSystem.cs b/Content.Server/Silicons/Laws/IonStormSystem.cs index 65c12c3d8ec5..bcf002dae7ff 100644 --- a/Content.Server/Silicons/Laws/IonStormSystem.cs +++ b/Content.Server/Silicons/Laws/IonStormSystem.cs @@ -1,4 +1,3 @@ -using System.Linq; using Content.Server.StationEvents.Components; using Content.Shared.Administration.Logs; using Content.Shared.Database; @@ -11,6 +10,7 @@ using Content.Shared.Silicons.Laws.Components; using Robust.Shared.Prototypes; using Robust.Shared.Random; +using System.Linq; namespace Content.Server.Silicons.Laws; diff --git a/Content.Server/StationEvents/Events/IonStormRule.cs b/Content.Server/StationEvents/Events/IonStormRule.cs index 05d079fb3d93..26f6d3263f00 100644 --- a/Content.Server/StationEvents/Events/IonStormRule.cs +++ b/Content.Server/StationEvents/Events/IonStormRule.cs @@ -1,8 +1,6 @@ -using System.Linq; using Content.Server.Silicons.Laws; using Content.Server.StationEvents.Components; using Content.Shared.GameTicking.Components; -using Content.Shared.Silicons.Laws; using Content.Shared.Silicons.Laws.Components; using Content.Shared.Station.Components; From d0114d9738c3eab436c11bc1d5f9c816d74980ca Mon Sep 17 00:00:00 2001 From: The Canned One Date: Tue, 1 Oct 2024 14:04:33 +0200 Subject: [PATCH 020/290] added a code summary --- Content.Server/Silicons/Laws/IonStormSystem.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Content.Server/Silicons/Laws/IonStormSystem.cs b/Content.Server/Silicons/Laws/IonStormSystem.cs index bcf002dae7ff..b8d8f432e772 100644 --- a/Content.Server/Silicons/Laws/IonStormSystem.cs +++ b/Content.Server/Silicons/Laws/IonStormSystem.cs @@ -59,6 +59,7 @@ public sealed class IonStormSystem : EntitySystem [ValidatePrototypeId] private const string Foods = "IonStormFoods"; + //Randomly alters the laws of an individual silicon. public void IonStormTarget(EntityUid ent, SiliconLawBoundComponent lawBound, TransformComponent xform, IonStormTargetComponent target, EntityUid? chosenStation, bool adminlog = true) { if (!_robustRandom.Prob(target.Chance)) From 08de5aeae134f67bbc310c42d56e145a4476cf6e Mon Sep 17 00:00:00 2001 From: The Canned One Date: Tue, 1 Oct 2024 18:07:41 +0200 Subject: [PATCH 021/290] Derelict cyborg minor yaml changes. --- .../Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml | 2 +- Resources/Prototypes/GameRules/events.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml index f94436dc3361..7449fe5669fe 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml @@ -333,6 +333,6 @@ - type: AccessReader access: [["Command"], ["Research"]] - type: StartIonStormed - ionStormAmount: 5 + ionStormAmount: 4 - type: IonStormTarget chance: 1 \ No newline at end of file diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index 36ded039eca2..be44b50d616c 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -552,7 +552,7 @@ id: DerelictCyborgSpawn components: - type: StationEvent - weight: 8 + weight: 6 earliestStart: 15 reoccurrenceDelay: 20 minimumPlayers: 4 From 963009a440cee3d47ab297b5aa7a76e3dfcaf569 Mon Sep 17 00:00:00 2001 From: The Canned One Date: Thu, 3 Oct 2024 11:34:24 +0200 Subject: [PATCH 022/290] Changes IonStorm related code with no gameplay changes. --- Content.Server/Silicons/Laws/IonStormSystem.cs | 4 +++- Content.Server/Silicons/Laws/StartIonStormedSystem.cs | 2 +- Content.Server/StationEvents/Events/IonStormRule.cs | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Content.Server/Silicons/Laws/IonStormSystem.cs b/Content.Server/Silicons/Laws/IonStormSystem.cs index b8d8f432e772..637155228cb2 100644 --- a/Content.Server/Silicons/Laws/IonStormSystem.cs +++ b/Content.Server/Silicons/Laws/IonStormSystem.cs @@ -60,8 +60,10 @@ public sealed class IonStormSystem : EntitySystem private const string Foods = "IonStormFoods"; //Randomly alters the laws of an individual silicon. - public void IonStormTarget(EntityUid ent, SiliconLawBoundComponent lawBound, TransformComponent xform, IonStormTargetComponent target, EntityUid? chosenStation, bool adminlog = true) + public void IonStormTarget(Entity ent, TransformComponent xform, EntityUid? chosenStation, bool adminlog = true) { + var lawBound = ent.Comp1; + var target = ent.Comp2; if (!_robustRandom.Prob(target.Chance)) return; diff --git a/Content.Server/Silicons/Laws/StartIonStormedSystem.cs b/Content.Server/Silicons/Laws/StartIonStormedSystem.cs index 546b3b27772d..d679b558b321 100644 --- a/Content.Server/Silicons/Laws/StartIonStormedSystem.cs +++ b/Content.Server/Silicons/Laws/StartIonStormedSystem.cs @@ -31,7 +31,7 @@ private void OnMapInit(Entity ent, ref MapInitEvent ar for (int currentIonStorm = 0; currentIonStorm < ent.Comp.IonStormAmount; currentIonStorm++) { - _ionStorm.IonStormTarget(ent.Owner, lawBound, xform, target, null, false); + _ionStorm.IonStormTarget((ent.Owner, lawBound, target), xform, null, false); } var laws = _siliconLaw.GetLaws(ent.Owner, lawBound); diff --git a/Content.Server/StationEvents/Events/IonStormRule.cs b/Content.Server/StationEvents/Events/IonStormRule.cs index 26f6d3263f00..9b67f25608d3 100644 --- a/Content.Server/StationEvents/Events/IonStormRule.cs +++ b/Content.Server/StationEvents/Events/IonStormRule.cs @@ -24,7 +24,7 @@ protected override void Started(EntityUid uid, IonStormRuleComponent comp, GameR if (CompOrNull(xform.GridUid)?.Station != chosenStation) continue; - _ionStorm.IonStormTarget(ent, lawBound, xform, target, chosenStation); + _ionStorm.IonStormTarget((ent, lawBound, target), xform, chosenStation); } } } From 4b633fde9c84778e2817025b1d38bd2549202c52 Mon Sep 17 00:00:00 2001 From: The Canned One Date: Thu, 3 Oct 2024 12:32:50 +0200 Subject: [PATCH 023/290] Fixed IonStorms sometimes affecting the laws of the current AI and future Cyborgs and AI's, including those in subsequent rounds. --- Content.Server/Silicons/Laws/IonStormSystem.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Content.Server/Silicons/Laws/IonStormSystem.cs b/Content.Server/Silicons/Laws/IonStormSystem.cs index 637155228cb2..b3c36a227332 100644 --- a/Content.Server/Silicons/Laws/IonStormSystem.cs +++ b/Content.Server/Silicons/Laws/IonStormSystem.cs @@ -78,11 +78,8 @@ public void IonStormTarget(Entity Date: Thu, 3 Oct 2024 12:43:51 +0200 Subject: [PATCH 024/290] Changed DerelictCyborgSpawn event's frequency from 6 to 5, even though i didn't want to. --- Resources/Prototypes/GameRules/events.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index be44b50d616c..9b5426c26976 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -552,7 +552,7 @@ id: DerelictCyborgSpawn components: - type: StationEvent - weight: 6 + weight: 5 earliestStart: 15 reoccurrenceDelay: 20 minimumPlayers: 4 From 3aff20173cbcd80e3bcd2c6d2b361e945b52e96e Mon Sep 17 00:00:00 2001 From: The Canned One Date: Thu, 3 Oct 2024 13:26:29 +0200 Subject: [PATCH 025/290] Removed 1 line of whitespace. --- Resources/Prototypes/Entities/Mobs/Player/silicon.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml index 70e533fa4478..97cd7c2a9d84 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml @@ -537,7 +537,6 @@ - type: RandomMetadata nameSegments: [names_borg] - - type: entity id: PlayerBorgDerelictGhostRole parent: PlayerBorgDerelict From 00aaffbc00a14515c0c5c5c900afbd3bd3946e99 Mon Sep 17 00:00:00 2001 From: The Canned One Date: Thu, 3 Oct 2024 13:51:38 +0200 Subject: [PATCH 026/290] removed whitespace --- Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl | 1 - 1 file changed, 1 deletion(-) diff --git a/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl b/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl index 3f9422f25007..f584a4b35fe0 100644 --- a/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl +++ b/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl @@ -240,7 +240,6 @@ ghost-role-information-syndicate-cyborg-assault-name = Syndicate Assault Cyborg ghost-role-information-syndicate-cyborg-saboteur-name = Syndicate Saboteur Cyborg ghost-role-information-syndicate-cyborg-description = The Syndicate needs reinforcements. You, a cold silicon killing machine, will help them. - ghost-role-information-derelict-cyborg-name = Derelict Cyborg ghost-role-information-derelict-cyborg-description = You were a regular cyborg that got lost in space. After drifting in whichever direction the laws of physics would have it for years, you have drifted close to a Nanotrasen space station. You have a fire extinguisher and mass scanner which can be used to board the station. Years of exposure to ion storms have left your silicon laws altered - check them upon spawning. From d863e3c5ca01530b04a678e85fc72176caac02fc Mon Sep 17 00:00:00 2001 From: The Canned One Date: Thu, 3 Oct 2024 14:03:14 +0200 Subject: [PATCH 027/290] Derelict Cyborg no longer appears on the endround 'Game Information' screen. It still appears in the Player Manifest. --- Resources/Locale/en-US/silicons/derelict-cyborg-role.ftl | 1 - Resources/Prototypes/GameRules/events.yml | 1 - 2 files changed, 2 deletions(-) delete mode 100644 Resources/Locale/en-US/silicons/derelict-cyborg-role.ftl diff --git a/Resources/Locale/en-US/silicons/derelict-cyborg-role.ftl b/Resources/Locale/en-US/silicons/derelict-cyborg-role.ftl deleted file mode 100644 index 87e500d3e61b..000000000000 --- a/Resources/Locale/en-US/silicons/derelict-cyborg-role.ftl +++ /dev/null @@ -1 +0,0 @@ -derelict-cyborg-round-end-agent-name = derelict cyborg \ No newline at end of file diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index 9b5426c26976..763557e6c91b 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -562,7 +562,6 @@ - type: AntagSpawner prototype: PlayerBorgDerelict - type: AntagSelection - agentName: derelict-cyborg-round-end-agent-name definitions: - spawnerPrototype: SpawnPointGhostDerelictCyborg min: 1 From 581a4d14fc0fbc2c37fd75ebe0364c74e746b38a Mon Sep 17 00:00:00 2001 From: The Canned One Date: Fri, 4 Oct 2024 08:31:55 +0200 Subject: [PATCH 028/290] minor Derelict Cyborg code changes. --- Content.Server/Silicons/Laws/IonStormSystem.cs | 4 +++- Content.Server/Silicons/Laws/StartIonStormedSystem.cs | 4 +--- Content.Server/StationEvents/Events/IonStormRule.cs | 2 +- Resources/Prototypes/Entities/Mobs/Player/silicon.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Content.Server/Silicons/Laws/IonStormSystem.cs b/Content.Server/Silicons/Laws/IonStormSystem.cs index b3c36a227332..f8bc8ca8c31a 100644 --- a/Content.Server/Silicons/Laws/IonStormSystem.cs +++ b/Content.Server/Silicons/Laws/IonStormSystem.cs @@ -59,8 +59,10 @@ public sealed class IonStormSystem : EntitySystem [ValidatePrototypeId] private const string Foods = "IonStormFoods"; + /// //Randomly alters the laws of an individual silicon. - public void IonStormTarget(Entity ent, TransformComponent xform, EntityUid? chosenStation, bool adminlog = true) + /// + public void IonStormTarget(Entity ent, bool adminlog = true) { var lawBound = ent.Comp1; var target = ent.Comp2; diff --git a/Content.Server/Silicons/Laws/StartIonStormedSystem.cs b/Content.Server/Silicons/Laws/StartIonStormedSystem.cs index d679b558b321..ee2ce7b9edd8 100644 --- a/Content.Server/Silicons/Laws/StartIonStormedSystem.cs +++ b/Content.Server/Silicons/Laws/StartIonStormedSystem.cs @@ -24,14 +24,12 @@ private void OnMapInit(Entity ent, ref MapInitEvent ar { if (!TryComp(ent.Owner, out var lawBound)) return; - if (!TryComp(ent.Owner, out var xform)) - return; if (!TryComp(ent.Owner, out var target)) return; for (int currentIonStorm = 0; currentIonStorm < ent.Comp.IonStormAmount; currentIonStorm++) { - _ionStorm.IonStormTarget((ent.Owner, lawBound, target), xform, null, false); + _ionStorm.IonStormTarget((ent.Owner, lawBound, target), false); } var laws = _siliconLaw.GetLaws(ent.Owner, lawBound); diff --git a/Content.Server/StationEvents/Events/IonStormRule.cs b/Content.Server/StationEvents/Events/IonStormRule.cs index 9b67f25608d3..e7c2d563ba99 100644 --- a/Content.Server/StationEvents/Events/IonStormRule.cs +++ b/Content.Server/StationEvents/Events/IonStormRule.cs @@ -24,7 +24,7 @@ protected override void Started(EntityUid uid, IonStormRuleComponent comp, GameR if (CompOrNull(xform.GridUid)?.Station != chosenStation) continue; - _ionStorm.IonStormTarget((ent, lawBound, target), xform, chosenStation); + _ionStorm.IonStormTarget((ent, lawBound, target)); } } } diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml index 97cd7c2a9d84..22f49c93eaae 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml @@ -540,7 +540,7 @@ - type: entity id: PlayerBorgDerelictGhostRole parent: PlayerBorgDerelict - suffix: Battery, Ghost role + suffix: Ghost role components: - type: GhostRole name: ghost-role-information-derelict-cyborg-name From d7ed5b4386f2d48b4b52b79351027a36e967800e Mon Sep 17 00:00:00 2001 From: The Canned One Date: Fri, 4 Oct 2024 08:35:16 +0200 Subject: [PATCH 029/290] remove whitespace. --- .../Silicons/Laws/Components/StartIonStormedComponent.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Content.Shared/Silicons/Laws/Components/StartIonStormedComponent.cs b/Content.Shared/Silicons/Laws/Components/StartIonStormedComponent.cs index 4157bee9f2db..e73d17b87bc1 100644 --- a/Content.Shared/Silicons/Laws/Components/StartIonStormedComponent.cs +++ b/Content.Shared/Silicons/Laws/Components/StartIonStormedComponent.cs @@ -1,4 +1,3 @@ - namespace Content.Shared.Silicons.Laws.Components; /// From b35d2902d4fc0c0322a1f74d0f208ca860990eee Mon Sep 17 00:00:00 2001 From: The Canned One Date: Sat, 5 Oct 2024 15:09:36 +0200 Subject: [PATCH 030/290] Fixed cyborgs with the StartIonStormedComponent (which is just the Derelict Cyborg right now) not showing up as 'antag' in the admin player overlay. --- .../Silicons/Laws/SiliconLawSystem.cs | 27 +++++++++++++++++++ .../Components/StartIonStormedComponent.cs | 10 +++++++ 2 files changed, 37 insertions(+) diff --git a/Content.Server/Silicons/Laws/SiliconLawSystem.cs b/Content.Server/Silicons/Laws/SiliconLawSystem.cs index 6b7df52a6ebc..27ed6702d6a8 100644 --- a/Content.Server/Silicons/Laws/SiliconLawSystem.cs +++ b/Content.Server/Silicons/Laws/SiliconLawSystem.cs @@ -51,6 +51,8 @@ public override void Initialize() SubscribeLocalEvent(OnEmagLawsAdded); SubscribeLocalEvent(OnEmagMindAdded); SubscribeLocalEvent(OnEmagMindRemoved); + SubscribeLocalEvent(OnStartIonStormedMindAdded); + SubscribeLocalEvent(OnStartIonStormedMindRemoved); } private void OnMapInit(EntityUid uid, SiliconLawBoundComponent component, MapInitEvent args) @@ -184,6 +186,31 @@ private void EnsureEmaggedRole(EntityUid uid, EmagSiliconLawComponent component) _roles.MindAddRole(mindId, new SubvertedSiliconRoleComponent { PrototypeId = component.AntagonistRole }); } + private void OnStartIonStormedMindAdded(EntityUid uid, StartIonStormedComponent component, MindAddedMessage args) + { + if (HasComp(uid)) + EnsureStartIonStormedRole(uid, component); + } + + private void OnStartIonStormedMindRemoved(EntityUid uid, StartIonStormedComponent component, MindRemovedMessage args) + { + if (component.AntagonistRole == null) + return; + + _roles.MindTryRemoveRole(args.Mind); + } + + private void EnsureStartIonStormedRole(EntityUid uid, StartIonStormedComponent component) + { + if (component.AntagonistRole == null || !_mind.TryGetMind(uid, out var mindId, out _)) + return; + + if (_roles.MindHasRole(mindId)) + return; + + _roles.MindAddRole(mindId, new SubvertedSiliconRoleComponent { PrototypeId = component.AntagonistRole }); + } + public SiliconLawset GetLaws(EntityUid uid, SiliconLawBoundComponent? component = null) { if (!Resolve(uid, ref component)) diff --git a/Content.Shared/Silicons/Laws/Components/StartIonStormedComponent.cs b/Content.Shared/Silicons/Laws/Components/StartIonStormedComponent.cs index e73d17b87bc1..d57241c857ca 100644 --- a/Content.Shared/Silicons/Laws/Components/StartIonStormedComponent.cs +++ b/Content.Shared/Silicons/Laws/Components/StartIonStormedComponent.cs @@ -1,3 +1,6 @@ +using Content.Shared.Roles;//Used +using Robust.Shared.Prototypes;// + namespace Content.Shared.Silicons.Laws.Components; /// @@ -11,4 +14,11 @@ public sealed partial class StartIonStormedComponent : Component /// [DataField] public int IonStormAmount = 1; + + /// + /// A role given to entities with this component when they are thing-that-is-not-emagged. + /// Mostly just for admin purposes. + /// + [DataField] + public ProtoId? AntagonistRole = "SubvertedSilicon"; } From b0c5023fda93ef68f73ea0c4d50c01e7d60c587d Mon Sep 17 00:00:00 2001 From: The Canned One Date: Sat, 5 Oct 2024 16:48:45 +0200 Subject: [PATCH 031/290] Fix comments in StartIonStormedComponent.cs --- .../Silicons/Laws/Components/StartIonStormedComponent.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Content.Shared/Silicons/Laws/Components/StartIonStormedComponent.cs b/Content.Shared/Silicons/Laws/Components/StartIonStormedComponent.cs index d57241c857ca..75d741216697 100644 --- a/Content.Shared/Silicons/Laws/Components/StartIonStormedComponent.cs +++ b/Content.Shared/Silicons/Laws/Components/StartIonStormedComponent.cs @@ -1,5 +1,5 @@ -using Content.Shared.Roles;//Used -using Robust.Shared.Prototypes;// +using Content.Shared.Roles; +using Robust.Shared.Prototypes; namespace Content.Shared.Silicons.Laws.Components; @@ -16,7 +16,7 @@ public sealed partial class StartIonStormedComponent : Component public int IonStormAmount = 1; /// - /// A role given to entities with this component when they are thing-that-is-not-emagged. + /// A role given to entities with this component when a mind enters it. /// Mostly just for admin purposes. /// [DataField] From af72f2e17cdf4392f5d3c214ec865ffa434f8c18 Mon Sep 17 00:00:00 2001 From: Jezithyr Date: Sat, 12 Oct 2024 22:21:44 -0700 Subject: [PATCH 032/290] Applying Fix from #32764 to staging --- Content.Server/Thief/Systems/ThiefBeaconSystem.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Content.Server/Thief/Systems/ThiefBeaconSystem.cs b/Content.Server/Thief/Systems/ThiefBeaconSystem.cs index 80471b642794..4c65ba5c449a 100644 --- a/Content.Server/Thief/Systems/ThiefBeaconSystem.cs +++ b/Content.Server/Thief/Systems/ThiefBeaconSystem.cs @@ -6,6 +6,7 @@ using Content.Shared.Foldable; using Content.Shared.Popups; using Content.Shared.Verbs; +using Content.Shared.Roles; using Robust.Shared.Audio.Systems; namespace Content.Server.Thief.Systems; @@ -18,7 +19,7 @@ public sealed class ThiefBeaconSystem : EntitySystem [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly MindSystem _mind = default!; - + [Dependency] private readonly SharedRoleSystem _roles = default!; public override void Initialize() { base.Initialize(); @@ -37,7 +38,7 @@ private void OnGetInteractionVerbs(Entity beacon, ref GetV return; var mind = _mind.GetMind(args.User); - if (!HasComp(mind)) + if (mind == null || !_roles.MindHasRole(mind.Value)) return; var user = args.User; From 30effd5ccd898bd4745e9e30640d08515c978ffa Mon Sep 17 00:00:00 2001 From: Errant <35878406+Errant-4@users.noreply.github.com> Date: Fri, 11 Oct 2024 21:17:01 +0200 Subject: [PATCH 033/290] Fix random test fail in DeleteAllThenGhost (#32753) It's simple. We kill the heisentest --- Content.Shared/Roles/SharedRoleSystem.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Content.Shared/Roles/SharedRoleSystem.cs b/Content.Shared/Roles/SharedRoleSystem.cs index cd3fe141b2be..925f61e7c75d 100644 --- a/Content.Shared/Roles/SharedRoleSystem.cs +++ b/Content.Shared/Roles/SharedRoleSystem.cs @@ -478,7 +478,13 @@ public bool MindIsExclusiveAntagonist(EntityUid? mindId) var exclusiveAntag = false; foreach (var role in mind.MindRoles) { - var roleComp = Comp(role); + if (!TryComp(role, out var roleComp)) + { + //If this ever shows up outside of an integration test, then we need to look into this further. + Log.Warning($"Mind Role Entity {role} does not have MindRoleComponent!"); + continue; + } + if (roleComp.Antag || exclusiveAntag) antagonist = true; if (roleComp.ExclusiveAntag) From e5ad32fe9388db4cf970eb7ba650a711a6560b74 Mon Sep 17 00:00:00 2001 From: Errant <35878406+Errant-4@users.noreply.github.com> Date: Fri, 11 Oct 2024 21:17:01 +0200 Subject: [PATCH 034/290] Fix random test fail in DeleteAllThenGhost (#32753) It's simple. We kill the heisentest --- Content.Shared/Roles/SharedRoleSystem.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Content.Shared/Roles/SharedRoleSystem.cs b/Content.Shared/Roles/SharedRoleSystem.cs index cd3fe141b2be..925f61e7c75d 100644 --- a/Content.Shared/Roles/SharedRoleSystem.cs +++ b/Content.Shared/Roles/SharedRoleSystem.cs @@ -478,7 +478,13 @@ public bool MindIsExclusiveAntagonist(EntityUid? mindId) var exclusiveAntag = false; foreach (var role in mind.MindRoles) { - var roleComp = Comp(role); + if (!TryComp(role, out var roleComp)) + { + //If this ever shows up outside of an integration test, then we need to look into this further. + Log.Warning($"Mind Role Entity {role} does not have MindRoleComponent!"); + continue; + } + if (roleComp.Antag || exclusiveAntag) antagonist = true; if (roleComp.ExclusiveAntag) From 796764d755186195541756b056f16a835c499cca Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Sun, 13 Oct 2024 23:00:40 +0200 Subject: [PATCH 035/290] Fix some rounds failing to end due to mind roles (#32792) (#32793) * Fix some rounds failing to end due to mind roles Fixes #32791 This is caused by ShowRoundEndScoreboard running into a bug trying to display antags: some player is showing up as antag with MindIsAntagonist(), but has no antag roles listed in MindGetAllRoleInfo(). This was caused by one of the roles of the player having the Antag boolean set, but having no AntagPrototype set. The responsible mind role appeared to be MindRoleSubvertedSilicon which is missing a set for the SubvertedSilicon antag prototype. I also added resilience to the round-end code to make it so that an exception showing the scoreboard (and sending the Discord message) would not cause the round end logic to completely abort from an exception. I am planning to add an integration test to cover this bug (no prototype in mind roles), but I'll leave that for not-the-immediate-hotfix. * At least one maintainer approved this tiny PR without reading it, not naming names. --- .../GameTicking/GameTicker.RoundFlow.cs | 19 +++++++++++++++++-- .../Prototypes/Roles/MindRoles/mind_roles.yml | 2 ++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Content.Server/GameTicking/GameTicker.RoundFlow.cs b/Content.Server/GameTicking/GameTicker.RoundFlow.cs index 683061d8edcf..e544870bd271 100644 --- a/Content.Server/GameTicking/GameTicker.RoundFlow.cs +++ b/Content.Server/GameTicking/GameTicker.RoundFlow.cs @@ -341,8 +341,23 @@ public void EndRound(string text = "") RunLevel = GameRunLevel.PostRound; - ShowRoundEndScoreboard(text); - SendRoundEndDiscordMessage(); + try + { + ShowRoundEndScoreboard(text); + } + catch (Exception e) + { + Log.Error($"Error while showing round end scoreboard: {e}"); + } + + try + { + SendRoundEndDiscordMessage(); + } + catch (Exception e) + { + Log.Error($"Error while sending round end Discord message: {e}"); + } } public void ShowRoundEndScoreboard(string text = "") diff --git a/Resources/Prototypes/Roles/MindRoles/mind_roles.yml b/Resources/Prototypes/Roles/MindRoles/mind_roles.yml index eb92fa51ae9d..926ce512b414 100644 --- a/Resources/Prototypes/Roles/MindRoles/mind_roles.yml +++ b/Resources/Prototypes/Roles/MindRoles/mind_roles.yml @@ -46,6 +46,8 @@ description: components: - type: SubvertedSiliconRole + - type: MindRole + antagPrototype: SubvertedSilicon # Dragon - type: entity From 519a6b24749e284df3e9aaaf8bab5f96d597fe8e Mon Sep 17 00:00:00 2001 From: Errant <35878406+Errant-4@users.noreply.github.com> Date: Mon, 14 Oct 2024 11:41:31 +0200 Subject: [PATCH 036/290] HOTFIX: Fix tech anomaly nexttimer (#32805) (#32807) Fix tech anomaly nexttimer (#32805) Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> --- Content.Server/Anomaly/Effects/TechAnomalySystem.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Content.Server/Anomaly/Effects/TechAnomalySystem.cs b/Content.Server/Anomaly/Effects/TechAnomalySystem.cs index 3e4d101f4fdf..9f81c64dbc10 100644 --- a/Content.Server/Anomaly/Effects/TechAnomalySystem.cs +++ b/Content.Server/Anomaly/Effects/TechAnomalySystem.cs @@ -22,11 +22,17 @@ public override void Initialize() { base.Initialize(); + SubscribeLocalEvent(OnTechMapInit); SubscribeLocalEvent(OnPulse); SubscribeLocalEvent(OnSupercritical); SubscribeLocalEvent(OnStabilityChanged); } + private void OnTechMapInit(Entity ent, ref MapInitEvent args) + { + ent.Comp.NextTimer = _timing.CurTime; + } + public override void Update(float frameTime) { base.Update(frameTime); From e04e3a625056df9b335419508a51dfe8d70c85b7 Mon Sep 17 00:00:00 2001 From: Errant <35878406+Errant-4@users.noreply.github.com> Date: Fri, 18 Oct 2024 15:17:18 +0200 Subject: [PATCH 037/290] HOTFIX spider clan charges can be armed again (#32866) * fix ninja bomb component check * remove TryGetRole --- Content.Server/Ninja/Systems/SpiderChargeSystem.cs | 10 ++++++---- Content.Shared/Mind/SharedMindSystem.cs | 13 ------------- 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/Content.Server/Ninja/Systems/SpiderChargeSystem.cs b/Content.Server/Ninja/Systems/SpiderChargeSystem.cs index c916d568d5f1..6594d7883bcf 100644 --- a/Content.Server/Ninja/Systems/SpiderChargeSystem.cs +++ b/Content.Server/Ninja/Systems/SpiderChargeSystem.cs @@ -1,14 +1,12 @@ using Content.Server.Explosion.EntitySystems; -using Content.Server.GameTicking.Rules.Components; using Content.Server.Mind; using Content.Server.Objectives.Components; using Content.Server.Popups; using Content.Server.Roles; -using Content.Shared.Interaction; using Content.Shared.Ninja.Components; using Content.Shared.Ninja.Systems; +using Content.Shared.Roles; using Content.Shared.Sticky; -using Robust.Shared.GameObjects; namespace Content.Server.Ninja.Systems; @@ -19,6 +17,7 @@ public sealed class SpiderChargeSystem : SharedSpiderChargeSystem { [Dependency] private readonly MindSystem _mind = default!; [Dependency] private readonly PopupSystem _popup = default!; + [Dependency] private readonly SharedRoleSystem _role = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; [Dependency] private readonly SpaceNinjaSystem _ninja = default!; @@ -41,7 +40,10 @@ private void OnAttemptStick(EntityUid uid, SpiderChargeComponent comp, ref Attem var user = args.User; - if (!_mind.TryGetRole(user, out var _)) + if (!_mind.TryGetMind(args.User, out var mind, out _)) + return; + + if (!_role.MindHasRole(mind)) { _popup.PopupEntity(Loc.GetString("spider-charge-not-ninja"), user, user); args.Cancelled = true; diff --git a/Content.Shared/Mind/SharedMindSystem.cs b/Content.Shared/Mind/SharedMindSystem.cs index 162bca495caf..bf0b5f650adb 100644 --- a/Content.Shared/Mind/SharedMindSystem.cs +++ b/Content.Shared/Mind/SharedMindSystem.cs @@ -483,19 +483,6 @@ public bool TryGetMind( return false; } - /// - /// Gets a role component from a player's mind. - /// - /// Whether a role was found - public bool TryGetRole(EntityUid user, [NotNullWhen(true)] out T? role) where T : IComponent - { - role = default; - if (!TryComp(user, out var mindContainer) || mindContainer.Mind == null) - return false; - - return TryComp(mindContainer.Mind, out role); - } - /// /// Sets the Mind's UserId, Session, and updates the player's PlayerData. This should have no direct effect on the /// entity that any mind is connected to, except as a side effect of the fact that it may change a player's From b137b0caa2adf80e963b77214e9d89be94d68137 Mon Sep 17 00:00:00 2001 From: Errant <35878406+Errant-4@users.noreply.github.com> Date: Fri, 18 Oct 2024 16:59:50 +0200 Subject: [PATCH 038/290] HOTFIX Plushies no longer delete items when recycled (#32882) Fix: Plushies no longer delete items when recycled (#32838) fix Co-authored-by: beck-thompson <107373427+beck-thompson@users.noreply.github.com> --- .../EntitySystems/SecretStashSystem.cs | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/Content.Shared/Storage/EntitySystems/SecretStashSystem.cs b/Content.Shared/Storage/EntitySystems/SecretStashSystem.cs index 08a69c345f09..af9b768e98be 100644 --- a/Content.Shared/Storage/EntitySystems/SecretStashSystem.cs +++ b/Content.Shared/Storage/EntitySystems/SecretStashSystem.cs @@ -14,6 +14,8 @@ using Content.Shared.IdentityManagement; using Content.Shared.Tools.EntitySystems; using Content.Shared.Whitelist; +using Content.Shared.Materials; +using Robust.Shared.Map; namespace Content.Shared.Storage.EntitySystems; @@ -35,6 +37,7 @@ public override void Initialize() base.Initialize(); SubscribeLocalEvent(OnInit); SubscribeLocalEvent(OnDestroyed); + SubscribeLocalEvent(OnReclaimed); SubscribeLocalEvent(OnInteractUsing, after: new[] { typeof(ToolOpenableSystem) }); SubscribeLocalEvent(OnInteractHand); SubscribeLocalEvent>(OnGetVerb); @@ -47,12 +50,12 @@ private void OnInit(Entity entity, ref ComponentInit args) private void OnDestroyed(Entity entity, ref DestructionEventArgs args) { - var storedInside = _containerSystem.EmptyContainer(entity.Comp.ItemContainer); - if (storedInside != null && storedInside.Count >= 1) - { - var popup = Loc.GetString("comp-secret-stash-on-destroyed-popup", ("stashname", GetStashName(entity))); - _popupSystem.PopupEntity(popup, storedInside[0], PopupType.MediumCaution); - } + DropContentsAndAlert(entity); + } + + private void OnReclaimed(Entity entity, ref GotReclaimedEvent args) + { + DropContentsAndAlert(entity, args.ReclaimerCoordinates); } private void OnInteractUsing(Entity entity, ref InteractUsingEvent args) @@ -211,5 +214,18 @@ private bool HasItemInside(Entity entity) return entity.Comp.ItemContainer.ContainedEntity != null; } + /// + /// Drop the item stored in the stash and alert all nearby players with a popup. + /// + private void DropContentsAndAlert(Entity entity, EntityCoordinates? cords = null) + { + var storedInside = _containerSystem.EmptyContainer(entity.Comp.ItemContainer, true, cords); + if (storedInside != null && storedInside.Count >= 1) + { + var popup = Loc.GetString("comp-secret-stash-on-destroyed-popup", ("stashname", GetStashName(entity))); + _popupSystem.PopupPredicted(popup, storedInside[0], null, PopupType.MediumCaution); + } + } + #endregion } From 928877f0ef7d16120843228ed619242acdc4feab Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Sat, 19 Oct 2024 18:05:48 +0200 Subject: [PATCH 039/290] HOTFIX (stable) submodule update (#32900) Update submodule This fixes an important memory leak. --- RobustToolbox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RobustToolbox b/RobustToolbox index d1d43f834b88..32bca7cfd417 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit d1d43f834b8845da698ef1898e8191ab159ee367 +Subproject commit 32bca7cfd417edcad9a60c2b1703eba8675f56af From 2b02545f97d06d9ce6f4dba38921ee10dda268b2 Mon Sep 17 00:00:00 2001 From: nikthechampiongr <32041239+nikthechampiongr@users.noreply.github.com> Date: Wed, 23 Oct 2024 01:34:11 +0300 Subject: [PATCH 040/290] Hotfix server config changes for playercap and Levi bunker (#32925) Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> --- Resources/ConfigPresets/WizardsDen/leviathan.toml | 4 ---- Resources/ConfigPresets/WizardsDen/wizardsDen.toml | 4 ++-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Resources/ConfigPresets/WizardsDen/leviathan.toml b/Resources/ConfigPresets/WizardsDen/leviathan.toml index 7560833f13af..a1a0e5b704d6 100644 --- a/Resources/ConfigPresets/WizardsDen/leviathan.toml +++ b/Resources/ConfigPresets/WizardsDen/leviathan.toml @@ -4,10 +4,6 @@ [game] hostname = "[EN] Wizard's Den Leviathan [US East 1]" -panic_bunker.enabled = false -panic_bunker.disable_with_admins = false -panic_bunker.enable_without_admins = false -panic_bunker.custom_reason = "" [hub] tags = "lang:en,region:am_n_e,rp:low" diff --git a/Resources/ConfigPresets/WizardsDen/wizardsDen.toml b/Resources/ConfigPresets/WizardsDen/wizardsDen.toml index 077ff3fe40a6..2b059ca40e3b 100644 --- a/Resources/ConfigPresets/WizardsDen/wizardsDen.toml +++ b/Resources/ConfigPresets/WizardsDen/wizardsDen.toml @@ -4,12 +4,12 @@ [game] desc = "Official English Space Station 14 servers. Vanilla, roleplay ruleset." lobbyenabled = true -soft_max_players = 80 +soft_max_players = 70 panic_bunker.enabled = true panic_bunker.disable_with_admins = true panic_bunker.enable_without_admins = true panic_bunker.show_reason = true -panic_bunker.custom_reason = "You have not played on a Wizard's Den server long enough to connect to this server. Please play on Wizard's Den Lizard, Leviathan, or Farm Grass Hopper until you have more playtime." +panic_bunker.custom_reason = "You have not played on a Wizard's Den server long enough to connect to this server. Please play on Wizard's Den Lizard or Farm Grass Hopper until you have more playtime." [infolinks] bug_report = "https://github.com/space-wizards/space-station-14/issues/new/choose" From ae1c5572fcda25e159a1c9762e2d71b0d7ec9c2b Mon Sep 17 00:00:00 2001 From: Jezithyr Date: Sat, 12 Oct 2024 22:21:44 -0700 Subject: [PATCH 041/290] Applying Fix from #32764 to staging --- Content.Server/Thief/Systems/ThiefBeaconSystem.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/Content.Server/Thief/Systems/ThiefBeaconSystem.cs b/Content.Server/Thief/Systems/ThiefBeaconSystem.cs index de1c3d2e6d19..4c65ba5c449a 100644 --- a/Content.Server/Thief/Systems/ThiefBeaconSystem.cs +++ b/Content.Server/Thief/Systems/ThiefBeaconSystem.cs @@ -20,7 +20,6 @@ public sealed class ThiefBeaconSystem : EntitySystem [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly MindSystem _mind = default!; [Dependency] private readonly SharedRoleSystem _roles = default!; - public override void Initialize() { base.Initialize(); From 4fbe50ab28be11c89c6d11684e0908d2309f2ce1 Mon Sep 17 00:00:00 2001 From: Thomas <87614336+Aeshus@users.noreply.github.com> Date: Sun, 27 Oct 2024 13:41:29 -0500 Subject: [PATCH 042/290] Fix Bug With Uppercase Radio Keys (#32997) --- Content.Shared/Chat/SharedChatSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Shared/Chat/SharedChatSystem.cs b/Content.Shared/Chat/SharedChatSystem.cs index 84b0e2266ec8..e5f3d4699747 100644 --- a/Content.Shared/Chat/SharedChatSystem.cs +++ b/Content.Shared/Chat/SharedChatSystem.cs @@ -106,7 +106,7 @@ public void GetRadioKeycodePrefix(EntityUid source, if (!(input.StartsWith(RadioChannelPrefix) || input.StartsWith(RadioChannelAltPrefix))) return; - if (!_keyCodes.TryGetValue(input[1], out _)) + if (!_keyCodes.TryGetValue(char.ToLower(input[1]), out _)) return; prefix = input[..2]; From a4717556e196d0e6997ba9a672e1a7237509b7aa Mon Sep 17 00:00:00 2001 From: BramvanZijp <56019239+BramvanZijp@users.noreply.github.com> Date: Sat, 26 Oct 2024 04:16:45 +0200 Subject: [PATCH 043/290] Fix loneop spawnrate by reverting it to not use the shuttle event system. (#32942) Fix loneop spawnrate by reverting it to not use the custom shuttle event system. --- Resources/Prototypes/GameRules/events.yml | 3 ++- Resources/Prototypes/GameRules/unknown_shuttles.yml | 5 ++--- Resources/Prototypes/Shuttles/shuttle_incoming_event.yml | 5 ----- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index e5e1192fc686..08218accede4 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -35,6 +35,7 @@ - id: RevenantSpawn - id: SleeperAgents - id: ZombieOutbreak + - id: LoneOpsSpawn - type: entity id: BaseStationEvent @@ -451,7 +452,7 @@ duration: 1 - type: RuleGrids - type: LoadMapRule - preloadedGrid: ShuttleStriker + mapPath: /Maps/Shuttles/ShuttleEvent/striker.yml - type: NukeopsRule roundEndBehavior: Nothing - type: AntagSelection diff --git a/Resources/Prototypes/GameRules/unknown_shuttles.yml b/Resources/Prototypes/GameRules/unknown_shuttles.yml index afbd552af3f4..f3391333b533 100644 --- a/Resources/Prototypes/GameRules/unknown_shuttles.yml +++ b/Resources/Prototypes/GameRules/unknown_shuttles.yml @@ -20,7 +20,6 @@ - id: UnknownShuttleMeatZone - id: UnknownShuttleMicroshuttle - id: UnknownShuttleSpacebus - - id: UnknownShuttleInstigator - type: entityTable id: UnknownShuttlesFreelanceTable @@ -32,9 +31,9 @@ id: UnknownShuttlesHostileTable table: !type:AllSelector # we need to pass a list of rules, since rules have further restrictions to consider via StationEventComp children: - - id: LoneOpsSpawn + - id: UnknownShuttleInstigator -# Shuttle Game Rules +# Shuttle Game Rules - type: entity abstract: true diff --git a/Resources/Prototypes/Shuttles/shuttle_incoming_event.yml b/Resources/Prototypes/Shuttles/shuttle_incoming_event.yml index a5269a73daef..1703e0c6980c 100644 --- a/Resources/Prototypes/Shuttles/shuttle_incoming_event.yml +++ b/Resources/Prototypes/Shuttles/shuttle_incoming_event.yml @@ -1,8 +1,3 @@ -- type: preloadedGrid - id: ShuttleStriker - path: /Maps/Shuttles/ShuttleEvent/striker.yml - copies: 2 - - type: preloadedGrid id: ShuttleCargoLost path: /Maps/Shuttles/ShuttleEvent/lost_cargo.yml From 0468c0f6bb3dbd10e4c7e2c5d1909ed87ca4eb64 Mon Sep 17 00:00:00 2001 From: Stalen <33173619+stalengd@users.noreply.github.com> Date: Mon, 28 Oct 2024 21:00:00 +0300 Subject: [PATCH 044/290] Fix playtime formatting (#32974) --- .../Info/PlaytimeStats/PlaytimeStatsEntry.cs | 3 ++- .../Info/PlaytimeStats/PlaytimeStatsWindow.cs | 3 +-- .../ContentLocalizationManager.cs | 21 +++++++++++++++++++ .../DepartmentTimeRequirement.cs | 3 ++- .../OverallPlaytimeRequirement.cs | 3 ++- .../JobRequirement/RoleTimeRequirement.cs | 3 ++- Resources/Locale/en-US/_lib.ftl | 3 +++ .../Locale/en-US/info/playtime-stats.ftl | 3 +-- .../Locale/en-US/job/role-requirements.ftl | 1 - 9 files changed, 34 insertions(+), 9 deletions(-) diff --git a/Content.Client/Info/PlaytimeStats/PlaytimeStatsEntry.cs b/Content.Client/Info/PlaytimeStats/PlaytimeStatsEntry.cs index 16e8f55a7e27..632ad8de4ac6 100644 --- a/Content.Client/Info/PlaytimeStats/PlaytimeStatsEntry.cs +++ b/Content.Client/Info/PlaytimeStats/PlaytimeStatsEntry.cs @@ -1,3 +1,4 @@ +using Content.Shared.Localizations; using Robust.Client.AutoGenerated; using Robust.Client.Graphics; using Robust.Client.UserInterface.Controls; @@ -16,7 +17,7 @@ public PlaytimeStatsEntry(string role, TimeSpan playtime, StyleBox styleBox) RoleLabel.Text = role; Playtime = playtime; // store the TimeSpan value directly - PlaytimeLabel.Text = playtime.ToString(Loc.GetString("ui-playtime-time-format")); // convert to string for display + PlaytimeLabel.Text = ContentLocalizationManager.FormatPlaytime(playtime); // convert to string for display BackgroundColorPanel.PanelOverride = styleBox; } diff --git a/Content.Client/Info/PlaytimeStats/PlaytimeStatsWindow.cs b/Content.Client/Info/PlaytimeStats/PlaytimeStatsWindow.cs index 1a530d950f98..98241b2ccab3 100644 --- a/Content.Client/Info/PlaytimeStats/PlaytimeStatsWindow.cs +++ b/Content.Client/Info/PlaytimeStats/PlaytimeStatsWindow.cs @@ -104,8 +104,7 @@ private void PopulatePlaytimeData() { var overallPlaytime = _jobRequirementsManager.FetchOverallPlaytime(); - var formattedPlaytime = overallPlaytime.ToString(Loc.GetString("ui-playtime-time-format")); - OverallPlaytimeLabel.Text = Loc.GetString("ui-playtime-overall", ("time", formattedPlaytime)); + OverallPlaytimeLabel.Text = Loc.GetString("ui-playtime-overall", ("time", overallPlaytime)); var rolePlaytimes = _jobRequirementsManager.FetchPlaytimeByRoles(); diff --git a/Content.Shared/Localizations/ContentLocalizationManager.cs b/Content.Shared/Localizations/ContentLocalizationManager.cs index ad8890ae0fdb..e60ca74a37fa 100644 --- a/Content.Shared/Localizations/ContentLocalizationManager.cs +++ b/Content.Shared/Localizations/ContentLocalizationManager.cs @@ -36,6 +36,7 @@ public void Initialize() _loc.AddFunction(culture, "LOC", FormatLoc); _loc.AddFunction(culture, "NATURALFIXED", FormatNaturalFixed); _loc.AddFunction(culture, "NATURALPERCENT", FormatNaturalPercent); + _loc.AddFunction(culture, "PLAYTIME", FormatPlaytime); /* @@ -141,6 +142,16 @@ public static string FormatDirection(Direction dir) return Loc.GetString($"zzzz-fmt-direction-{dir.ToString()}"); } + /// + /// Formats playtime as hours and minutes. + /// + public static string FormatPlaytime(TimeSpan time) + { + var hours = (int)time.TotalHours; + var minutes = time.Minutes; + return Loc.GetString($"zzzz-fmt-playtime", ("hours", hours), ("minutes", minutes)); + } + private static ILocValue FormatLoc(LocArgs args) { var id = ((LocValueString) args.Args[0]).Value; @@ -229,5 +240,15 @@ private static ILocValue FormatUnits(LocArgs args) return new LocValueString(res); } + + private static ILocValue FormatPlaytime(LocArgs args) + { + var time = TimeSpan.Zero; + if (args.Args is { Count: > 0 } && args.Args[0].Value is TimeSpan timeArg) + { + time = timeArg; + } + return new LocValueString(FormatPlaytime(time)); + } } } diff --git a/Content.Shared/Roles/JobRequirement/DepartmentTimeRequirement.cs b/Content.Shared/Roles/JobRequirement/DepartmentTimeRequirement.cs index 78c6bd251779..8c8629921031 100644 --- a/Content.Shared/Roles/JobRequirement/DepartmentTimeRequirement.cs +++ b/Content.Shared/Roles/JobRequirement/DepartmentTimeRequirement.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using Content.Shared.Localizations; using Content.Shared.Preferences; using JetBrains.Annotations; using Robust.Shared.Prototypes; @@ -49,7 +50,7 @@ public override bool Check(IEntityManager entManager, var deptDiffSpan = Time - playtime; var deptDiff = deptDiffSpan.TotalMinutes; - var formattedDeptDiff = deptDiffSpan.ToString(Loc.GetString("role-timer-time-format")); + var formattedDeptDiff = ContentLocalizationManager.FormatPlaytime(deptDiffSpan); var nameDepartment = "role-timer-department-unknown"; if (protoManager.TryIndex(Department, out var departmentIndexed)) diff --git a/Content.Shared/Roles/JobRequirement/OverallPlaytimeRequirement.cs b/Content.Shared/Roles/JobRequirement/OverallPlaytimeRequirement.cs index ed985cadfba0..67b3938e1a71 100644 --- a/Content.Shared/Roles/JobRequirement/OverallPlaytimeRequirement.cs +++ b/Content.Shared/Roles/JobRequirement/OverallPlaytimeRequirement.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using Content.Shared.Localizations; using Content.Shared.Players.PlayTimeTracking; using Content.Shared.Preferences; using JetBrains.Annotations; @@ -27,7 +28,7 @@ public override bool Check(IEntityManager entManager, var overallTime = playTimes.GetValueOrDefault(PlayTimeTrackingShared.TrackerOverall); var overallDiffSpan = Time - overallTime; var overallDiff = overallDiffSpan.TotalMinutes; - var formattedOverallDiff = overallDiffSpan.ToString(Loc.GetString("role-timer-time-format")); + var formattedOverallDiff = ContentLocalizationManager.FormatPlaytime(overallDiffSpan); if (!Inverted) { diff --git a/Content.Shared/Roles/JobRequirement/RoleTimeRequirement.cs b/Content.Shared/Roles/JobRequirement/RoleTimeRequirement.cs index 23498ab91ad2..e75a18f011da 100644 --- a/Content.Shared/Roles/JobRequirement/RoleTimeRequirement.cs +++ b/Content.Shared/Roles/JobRequirement/RoleTimeRequirement.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using Content.Shared.Localizations; using Content.Shared.Players.PlayTimeTracking; using Content.Shared.Preferences; using Content.Shared.Roles.Jobs; @@ -36,7 +37,7 @@ public override bool Check(IEntityManager entManager, playTimes.TryGetValue(proto, out var roleTime); var roleDiffSpan = Time - roleTime; var roleDiff = roleDiffSpan.TotalMinutes; - var formattedRoleDiff = roleDiffSpan.ToString(Loc.GetString("role-timer-time-format")); + var formattedRoleDiff = ContentLocalizationManager.FormatPlaytime(roleDiffSpan); var departmentColor = Color.Yellow; if (entManager.EntitySysManager.TryGetEntitySystem(out SharedJobSystem? jobSystem)) diff --git a/Resources/Locale/en-US/_lib.ftl b/Resources/Locale/en-US/_lib.ftl index c901d0f461e6..5c6f73af66fa 100644 --- a/Resources/Locale/en-US/_lib.ftl +++ b/Resources/Locale/en-US/_lib.ftl @@ -31,3 +31,6 @@ zzzz-fmt-power-joules = { TOSTRING($divided, "F1") } { $places -> [4] TJ *[5] ??? } + +# Used internally by the PLAYTIME() function. +zzzz-fmt-playtime = {$hours}H {$minutes}M \ No newline at end of file diff --git a/Resources/Locale/en-US/info/playtime-stats.ftl b/Resources/Locale/en-US/info/playtime-stats.ftl index 85508c1d09cd..b4925176a766 100644 --- a/Resources/Locale/en-US/info/playtime-stats.ftl +++ b/Resources/Locale/en-US/info/playtime-stats.ftl @@ -2,9 +2,8 @@ ui-playtime-stats-title = User Playtime Stats ui-playtime-overall-base = Overall Playtime: -ui-playtime-overall = Overall Playtime: {$time} +ui-playtime-overall = Overall Playtime: {PLAYTIME($time)} ui-playtime-first-time = First Time Playing ui-playtime-roles = Playtime per Role -ui-playtime-time-format = %h\H\ %m\M ui-playtime-header-role-type = Role ui-playtime-header-role-time = Time diff --git a/Resources/Locale/en-US/job/role-requirements.ftl b/Resources/Locale/en-US/job/role-requirements.ftl index 79a216fccaf4..686fcb93cb12 100644 --- a/Resources/Locale/en-US/job/role-requirements.ftl +++ b/Resources/Locale/en-US/job/role-requirements.ftl @@ -4,7 +4,6 @@ role-timer-overall-insufficient = You require [color=yellow]{$time}[/color] more role-timer-overall-too-high = You require [color=yellow]{$time}[/color] less overall playtime to play this role. (Are you trying to play a trainee role?) role-timer-role-insufficient = You require [color=yellow]{$time}[/color] more playtime with [color={$departmentColor}]{$job}[/color] to play this role. role-timer-role-too-high = You require[color=yellow] {$time}[/color] less playtime with [color={$departmentColor}]{$job}[/color] to play this role. (Are you trying to play a trainee role?) -role-timer-time-format = %h\H\ %m\M role-timer-age-too-old = Your character must be under the age of [color=yellow]{$age}[/color] to play this role. role-timer-age-too-young = Your character must be over the age of [color=yellow]{$age}[/color] to play this role. role-timer-whitelisted-species = Your character must be one of the following species to play this role: From 03843734e4de1c9f3c34d029aca3e7935f7eafde Mon Sep 17 00:00:00 2001 From: Preston Smith Date: Tue, 29 Oct 2024 22:25:42 -0500 Subject: [PATCH 045/290] Add no damage phrase and logic --- Content.Shared/Damage/Systems/DamageExamineSystem.cs | 9 +++++++++ Resources/Locale/en-US/damage/damage-examine.ftl | 1 + 2 files changed, 10 insertions(+) diff --git a/Content.Shared/Damage/Systems/DamageExamineSystem.cs b/Content.Shared/Damage/Systems/DamageExamineSystem.cs index 53436a920aa5..72c1af29b22d 100644 --- a/Content.Shared/Damage/Systems/DamageExamineSystem.cs +++ b/Content.Shared/Damage/Systems/DamageExamineSystem.cs @@ -61,6 +61,15 @@ private FormattedMessage GetDamageExamine(DamageSpecifier damageSpecifier, strin } else { + if (damageSpecifier.DamageDict.Count == 1) + { + // May be simplified to using a foreach(Var x) despite being only one item + if(damageSpecifier.DamageDict.Values.GetEnumerator().Current == FixedPoint2.Zero) + { + msg.AddMarkupOrThrow(Loc.GetString("damage-none")); + return msg; + } + } msg.AddMarkupOrThrow(Loc.GetString("damage-examine-type", ("type", type))); } diff --git a/Resources/Locale/en-US/damage/damage-examine.ftl b/Resources/Locale/en-US/damage/damage-examine.ftl index 974b8fa96506..848adeb31a0d 100644 --- a/Resources/Locale/en-US/damage/damage-examine.ftl +++ b/Resources/Locale/en-US/damage/damage-examine.ftl @@ -10,3 +10,4 @@ damage-throw = throw damage-examine = It does the following damage: damage-examine-type = It does the following [color=cyan]{$type}[/color] damage: damage-value = - [color=red]{$amount}[/color] units of [color=yellow]{$type}[/color]. +damage-none = It does no damage. From 33516b77edd63b1254559787f02bbc029719b23c Mon Sep 17 00:00:00 2001 From: Justice League Date: Thu, 31 Oct 2024 13:28:17 -0400 Subject: [PATCH 046/290] Fixed minor spelling mistake --- .../Entities/Objects/Weapons/Guns/Basic/watergun.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Basic/watergun.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Basic/watergun.yml index c96a1522d2ef..55adfb7ba6c5 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Basic/watergun.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Basic/watergun.yml @@ -1,4 +1,4 @@ -- type: entity +- type: entity id: WeaponWaterGunBase abstract: true parent: BaseItem @@ -71,7 +71,7 @@ id: WeaponWaterBlaster parent: WeaponWaterGunBase name: water blaster - description: With this bad boy, you'll be the cooleste kid at the summer barbecue. + description: With this bad boy, you'll be the coolest kid at the summer barbecue. components: - type: Gun cameraRecoilScalar: 0 #no recoil From a399c1ec7cdd0f7aa86577d2a813ed04a845edda Mon Sep 17 00:00:00 2001 From: deathride58 Date: Thu, 31 Oct 2024 17:30:58 -0400 Subject: [PATCH 047/290] Fixes tailthump breaking positional audio by making it mono (#33092) --- .../Voice/Reptilian/reptilian_tailthump.ogg | Bin 31956 -> 9215 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Resources/Audio/Voice/Reptilian/reptilian_tailthump.ogg b/Resources/Audio/Voice/Reptilian/reptilian_tailthump.ogg index e4bf25f7b8d1e743e34826b343f33e41e9298e16..fff0a8728a7d7123dc4d9b89f23603f677396a34 100644 GIT binary patch delta 8227 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 Hm4W{O+Q|*_ literal 31956 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 Date: Sat, 2 Nov 2024 17:49:44 +0100 Subject: [PATCH 048/290] Hotfix add debug info to traitor activation (#33119) * Add debug messages to traitor activation * more debug --- Content.Server/Antag/AntagSelectionSystem.cs | 4 +++ .../GameTicking/Rules/TraitorRuleSystem.cs | 31 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/Content.Server/Antag/AntagSelectionSystem.cs b/Content.Server/Antag/AntagSelectionSystem.cs index 224629ff2e52..610c0ad182ad 100644 --- a/Content.Server/Antag/AntagSelectionSystem.cs +++ b/Content.Server/Antag/AntagSelectionSystem.cs @@ -55,6 +55,8 @@ public override void Initialize() { base.Initialize(); + Log.Level = LogLevel.Debug; + SubscribeLocalEvent(OnTakeGhostRole); SubscribeLocalEvent(OnObjectivesTextGetInfo); @@ -360,6 +362,8 @@ public void MakeAntag(Entity ent, ICommonSession? sessi _role.MindAddRoles(curMind.Value, def.MindRoles, null, true); ent.Comp.SelectedMinds.Add((curMind.Value, Name(player))); SendBriefing(session, def.Briefing); + + Log.Debug($"Selected {ToPrettyString(curMind)} as antagonist: {ToPrettyString(ent)}"); } var afterEv = new AfterAntagEntitySelectedEvent(session, player, ent, def); diff --git a/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs b/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs index 1987613763b5..bc6a8e9395f9 100644 --- a/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs @@ -41,6 +41,8 @@ public override void Initialize() { base.Initialize(); + Log.Level = LogLevel.Debug; + SubscribeLocalEvent(AfterEntitySelected); SubscribeLocalEvent(OnObjectivesTextPrepend); } @@ -53,6 +55,7 @@ protected override void Added(EntityUid uid, TraitorRuleComponent component, Gam private void AfterEntitySelected(Entity ent, ref AfterAntagEntitySelectedEvent args) { + Log.Debug($"AfterAntagEntitySelected {ToPrettyString(ent)}"); MakeTraitor(args.EntityUid, ent); } @@ -78,14 +81,22 @@ public string[] GenerateTraitorCodewords(TraitorRuleComponent component) public bool MakeTraitor(EntityUid traitor, TraitorRuleComponent component) { + Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - start"); + //Grab the mind if it wasn't provided if (!_mindSystem.TryGetMind(traitor, out var mindId, out var mind)) + { + Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - failed, no Mind found"); return false; + } var briefing = ""; if (component.GiveCodewords) + { + Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - added codewords flufftext to briefing"); briefing = Loc.GetString("traitor-role-codewords-short", ("codewords", string.Join(", ", component.Codewords))); + } var issuer = _random.Pick(_prototypeManager.Index(component.ObjectiveIssuers).Values); @@ -94,6 +105,7 @@ public bool MakeTraitor(EntityUid traitor, TraitorRuleComponent component) if (component.GiveUplink) { + Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - Uplink start"); // Calculate the amount of currency on the uplink. var startingBalance = component.StartingBalance; if (_jobs.MindTryGetJob(mindId, out var prototype)) @@ -105,18 +117,27 @@ public bool MakeTraitor(EntityUid traitor, TraitorRuleComponent component) } // Choose and generate an Uplink, and return the uplink code if applicable + Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - Uplink request start"); var uplinkParams = RequestUplink(traitor, startingBalance, briefing); code = uplinkParams.Item1; briefing = uplinkParams.Item2; + Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - Uplink request completed"); } string[]? codewords = null; if (component.GiveCodewords) + { + Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - set codewords from component"); codewords = component.Codewords; + } if (component.GiveBriefing) + { _antag.SendBriefing(traitor, GenerateBriefing(codewords, code, issuer), null, component.GreetSoundNotification); + Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - Sent the Briefing"); + } + Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - Adding TraitorMind"); component.TraitorMinds.Add(mindId); // Assign briefing @@ -126,9 +147,14 @@ public bool MakeTraitor(EntityUid traitor, TraitorRuleComponent component) _roleSystem.MindHasRole(mindId, out var traitorRole); if (traitorRole is not null) { + Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - Add traitor briefing components"); AddComp(traitorRole.Value.Owner); Comp(traitorRole.Value.Owner).Briefing = briefing; } + else + { + Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - did not get traitor briefing"); + } // Send codewords to only the traitor client var color = TraitorCodewordColor; // Fall back to a dark red Syndicate color if a prototype is not found @@ -137,9 +163,11 @@ public bool MakeTraitor(EntityUid traitor, TraitorRuleComponent component) _roleCodewordSystem.SetRoleCodewords(codewordComp, "traitor", component.Codewords.ToList(), color); // Change the faction + Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - Change faction"); _npcFaction.RemoveFaction(traitor, component.NanoTrasenFaction, false); _npcFaction.AddFaction(traitor, component.SyndicateFaction); + Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - Finished"); return true; } @@ -148,10 +176,12 @@ public bool MakeTraitor(EntityUid traitor, TraitorRuleComponent component) var pda = _uplink.FindUplinkTarget(traitor); Note[]? code = null; + Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - Uplink add"); var uplinked = _uplink.AddUplink(traitor, startingBalance, pda, true); if (pda is not null && uplinked) { + Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - Uplink is PDA"); // Codes are only generated if the uplink is a PDA code = EnsureComp(pda.Value).Code; @@ -163,6 +193,7 @@ public bool MakeTraitor(EntityUid traitor, TraitorRuleComponent component) } else if (pda is null && uplinked) { + Log.Debug($"MakeTraitor {ToPrettyString(traitor)} - Uplink is implant"); briefing += "\n" + Loc.GetString("traitor-role-uplink-implant-short"); } From 69c0f8773f05e12b78bf45303a0ec99bfeced773 Mon Sep 17 00:00:00 2001 From: cohanna Date: Mon, 4 Nov 2024 03:10:29 -0700 Subject: [PATCH 049/290] we hate powergaming --- .../Recipes/Construction/Graphs/structures/window.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/structures/window.yml b/Resources/Prototypes/Recipes/Construction/Graphs/structures/window.yml index b9e6eae08157..1782c5924bfe 100644 --- a/Resources/Prototypes/Recipes/Construction/Graphs/structures/window.yml +++ b/Resources/Prototypes/Recipes/Construction/Graphs/structures/window.yml @@ -223,11 +223,6 @@ - material: Uranium amount: 2 doAfter: 1 - - to: shuttleWindow - steps: - - material: Plasteel - amount: 2 - doAfter: 3 - node: reinforcedPlasmaWindow entity: ReinforcedPlasmaWindow From 3972a252581aaa6dd6f022eb09b6c2faf903da3c Mon Sep 17 00:00:00 2001 From: Errant <35878406+Errant-4@users.noreply.github.com> Date: Tue, 5 Nov 2024 19:03:14 +0100 Subject: [PATCH 050/290] HOTFIX latejoin traitor activations (#33180) --- Resources/Prototypes/GameRules/roundstart.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Resources/Prototypes/GameRules/roundstart.yml b/Resources/Prototypes/GameRules/roundstart.yml index cec5c9ee0931..6ca322d0d5f7 100644 --- a/Resources/Prototypes/GameRules/roundstart.yml +++ b/Resources/Prototypes/GameRules/roundstart.yml @@ -191,12 +191,17 @@ - type: entity id: TraitorReinforcement - parent: Traitor + parent: BaseTraitorRule components: - type: TraitorRule giveUplink: false giveCodewords: false # It would actually give them a different set of codewords than the regular traitors, anyway giveBriefing: false + - type: AntagSelection + definitions: + - prefRoles: [ Traitor ] + mindRoles: + - MindRoleTraitor - type: entity id: Revolutionary @@ -280,7 +285,6 @@ tableId: CalmPestEventsTable - !type:NestedSelector tableId: SpicyPestEventsTable - - type: entityTable id: SpaceTrafficControlTable From 18971f270539a69c54b203a87b40573eacbbabaa Mon Sep 17 00:00:00 2001 From: cohanna Date: Wed, 6 Nov 2024 21:39:02 -0700 Subject: [PATCH 051/290] Reverted #31978 --- .../Entities/Structures/Windows/clockwork.yml | 20 +-- .../Entities/Structures/Windows/mining.yml | 4 +- .../Entities/Structures/Windows/plasma.yml | 25 +-- .../Structures/Windows/plastitanium.yml | 8 +- .../Structures/Windows/reinforced.yml | 35 +++- .../Entities/Structures/Windows/rplasma.yml | 14 +- .../Entities/Structures/Windows/ruranium.yml | 16 +- .../Entities/Structures/Windows/shuttle.yml | 4 +- .../Entities/Structures/Windows/uranium.yml | 24 +-- .../Entities/Structures/Windows/window.yml | 30 +--- .../Construction/Graphs/structures/window.yml | 170 +++++++----------- .../Graphs/structures/window_diagonal.yml | 146 ++++++--------- .../Graphs/structures/windowdirectional.yml | 146 ++++----------- .../Recipes/Construction/structures.yml | 42 ++--- ...ageOverlay_20.png => DamageOverlay_12.png} | Bin ...amageOverlay_5.png => DamageOverlay_4.png} | Bin ...mageOverlay_10.png => DamageOverlay_8.png} | Bin .../Structures/Windows/cracks.rsi/meta.json | 6 +- ...ageOverlay_20.png => DamageOverlay_12.png} | Bin ...amageOverlay_5.png => DamageOverlay_4.png} | Bin ...mageOverlay_10.png => DamageOverlay_8.png} | Bin .../Windows/cracks_diagonal.rsi/meta.json | 6 +- ...ageOverlay_20.png => DamageOverlay_12.png} | Bin ...amageOverlay_5.png => DamageOverlay_4.png} | Bin ...mageOverlay_10.png => DamageOverlay_8.png} | Bin .../Windows/cracks_directional.rsi/meta.json | 6 +- 26 files changed, 247 insertions(+), 455 deletions(-) rename Resources/Textures/Structures/Windows/cracks.rsi/{DamageOverlay_20.png => DamageOverlay_12.png} (100%) rename Resources/Textures/Structures/Windows/cracks.rsi/{DamageOverlay_5.png => DamageOverlay_4.png} (100%) rename Resources/Textures/Structures/Windows/cracks.rsi/{DamageOverlay_10.png => DamageOverlay_8.png} (100%) rename Resources/Textures/Structures/Windows/cracks_diagonal.rsi/{DamageOverlay_20.png => DamageOverlay_12.png} (100%) rename Resources/Textures/Structures/Windows/cracks_diagonal.rsi/{DamageOverlay_5.png => DamageOverlay_4.png} (100%) rename Resources/Textures/Structures/Windows/cracks_diagonal.rsi/{DamageOverlay_10.png => DamageOverlay_8.png} (100%) rename Resources/Textures/Structures/Windows/cracks_directional.rsi/{DamageOverlay_20.png => DamageOverlay_12.png} (100%) rename Resources/Textures/Structures/Windows/cracks_directional.rsi/{DamageOverlay_5.png => DamageOverlay_4.png} (100%) rename Resources/Textures/Structures/Windows/cracks_directional.rsi/{DamageOverlay_10.png => DamageOverlay_8.png} (100%) diff --git a/Resources/Prototypes/Entities/Structures/Windows/clockwork.yml b/Resources/Prototypes/Entities/Structures/Windows/clockwork.yml index 3449d1d11a0f..992dfcda1cbe 100644 --- a/Resources/Prototypes/Entities/Structures/Windows/clockwork.yml +++ b/Resources/Prototypes/Entities/Structures/Windows/clockwork.yml @@ -47,8 +47,8 @@ node: clockworkWindow - type: Appearance - type: DamageVisuals - thresholds: [5, 10, 20] - damageDivisor: 3 + thresholds: [4, 8, 12] + damageDivisor: 4 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks.rsi @@ -74,8 +74,8 @@ node: windowClockworkDirectional - type: Appearance - type: DamageVisuals - thresholds: [5, 10, 20] - damageDivisor: 1.5 + thresholds: [4, 8, 12] + damageDivisor: 10 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks_directional.rsi @@ -85,17 +85,7 @@ thresholds: - trigger: !type:DamageTrigger - damage: 75 - behaviors: - - !type:DoActsBehavior - acts: [ "Destruction" ] - - !type:PlaySoundBehavior - sound: - collection: WindowShatter - - trigger: - !type:DamageTrigger - damage: 37 - behaviors: + damage: 150 - !type:PlaySoundBehavior sound: collection: WindowShatter diff --git a/Resources/Prototypes/Entities/Structures/Windows/mining.yml b/Resources/Prototypes/Entities/Structures/Windows/mining.yml index f0b77e66893a..82d11b732b65 100644 --- a/Resources/Prototypes/Entities/Structures/Windows/mining.yml +++ b/Resources/Prototypes/Entities/Structures/Windows/mining.yml @@ -43,8 +43,8 @@ base: mwindow - type: Appearance - type: DamageVisuals - thresholds: [5, 10, 20] - damageDivisor: 4 + thresholds: [4, 8, 12] + damageDivisor: 6 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks.rsi diff --git a/Resources/Prototypes/Entities/Structures/Windows/plasma.yml b/Resources/Prototypes/Entities/Structures/Windows/plasma.yml index 58991b928690..66fac515a770 100644 --- a/Resources/Prototypes/Entities/Structures/Windows/plasma.yml +++ b/Resources/Prototypes/Entities/Structures/Windows/plasma.yml @@ -10,12 +10,12 @@ sprite: Structures/Windows/plasma_window.rsi - type: Damageable damageContainer: StructuralInorganic - damageModifierSet: Glass + damageModifierSet: RGlass - type: Destructible thresholds: - trigger: !type:DamageTrigger - damage: 150 + damage: 120 behaviors: - !type:DoActsBehavior acts: [ "Destruction" ] @@ -24,7 +24,7 @@ collection: WindowShatter - trigger: !type:DamageTrigger - damage: 75 + damage: 60 behaviors: - !type:PlaySoundBehavior sound: @@ -43,8 +43,8 @@ node: plasmaWindow - type: Appearance - type: DamageVisuals - thresholds: [5, 10, 20] - damageDivisor: 3 + thresholds: [4, 8, 12] + damageDivisor: 3.333 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks.rsi @@ -74,8 +74,8 @@ node: plasmaWindowDirectional - type: Appearance - type: DamageVisuals - thresholds: [5, 10, 20] - damageDivisor: 1.5 + thresholds: [4, 8, 12] + damageDivisor: 3.333 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks_directional.rsi @@ -83,16 +83,7 @@ thresholds: - trigger: !type:DamageTrigger - damage: 75 - behaviors: - - !type:DoActsBehavior - acts: [ "Destruction" ] - - !type:PlaySoundBehavior - sound: - collection: WindowShatter - - trigger: - !type:DamageTrigger - damage: 37 + damage: 200 behaviors: - !type:PlaySoundBehavior sound: diff --git a/Resources/Prototypes/Entities/Structures/Windows/plastitanium.yml b/Resources/Prototypes/Entities/Structures/Windows/plastitanium.yml index e7af4b6c6777..2134cfe89276 100644 --- a/Resources/Prototypes/Entities/Structures/Windows/plastitanium.yml +++ b/Resources/Prototypes/Entities/Structures/Windows/plastitanium.yml @@ -98,8 +98,8 @@ - !type:DoActsBehavior acts: [ "Destruction" ] - type: DamageVisuals - thresholds: [5, 10, 20] - damageDivisor: 20 + thresholds: [4, 8, 12] + damageDivisor: 28 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks.rsi @@ -185,8 +185,8 @@ - !type:DoActsBehavior acts: [ "Destruction" ] - type: DamageVisuals - thresholds: [5, 10, 20] - damageDivisor: 20 + thresholds: [4, 8, 12] + damageDivisor: 28 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks_diagonal.rsi diff --git a/Resources/Prototypes/Entities/Structures/Windows/reinforced.yml b/Resources/Prototypes/Entities/Structures/Windows/reinforced.yml index 9e80d46e649b..503d2eec6e3b 100644 --- a/Resources/Prototypes/Entities/Structures/Windows/reinforced.yml +++ b/Resources/Prototypes/Entities/Structures/Windows/reinforced.yml @@ -50,12 +50,31 @@ node: reinforcedWindow - type: Appearance - type: DamageVisuals - thresholds: [5, 10, 20] - damageDivisor: 3 + thresholds: [4, 8, 12] + damageDivisor: 4 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks.rsi +- type: entity + parent: ReinforcedWindow + id: TintedWindow + name: tinted window + components: + - type: Sprite + drawdepth: WallTops + sprite: Structures/Windows/tinted_window.rsi + - type: Icon + sprite: Structures/Windows/tinted_window.rsi + - type: IconSmooth + base: twindow + - type: Construction + graph: Window + node: tintedWindow + - type: Occluder + - type: StaticPrice + price: 45 + - type: entity id: WindowReinforcedDirectional parent: WindowDirectional @@ -77,8 +96,8 @@ node: windowReinforcedDirectional - type: Appearance - type: DamageVisuals - thresholds: [5, 10, 20] - damageDivisor: 1.5 + thresholds: [4, 8, 12] + damageDivisor: 10 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks_directional.rsi @@ -92,16 +111,16 @@ thresholds: - trigger: !type:DamageTrigger - damage: 75 + damage: 150 #excess damage (nuke?). avoid computational cost of spawning entities. behaviors: - - !type:DoActsBehavior - acts: [ "Destruction" ] - !type:PlaySoundBehavior sound: collection: WindowShatter + - !type:DoActsBehavior + acts: [ "Destruction" ] - trigger: !type:DamageTrigger - damage: 37 + damage: 50 behaviors: - !type:PlaySoundBehavior sound: diff --git a/Resources/Prototypes/Entities/Structures/Windows/rplasma.yml b/Resources/Prototypes/Entities/Structures/Windows/rplasma.yml index 0dfe893a5c34..0940ac308a52 100644 --- a/Resources/Prototypes/Entities/Structures/Windows/rplasma.yml +++ b/Resources/Prototypes/Entities/Structures/Windows/rplasma.yml @@ -17,7 +17,7 @@ thresholds: - trigger: !type:DamageTrigger - damage: 300 + damage: 200 behaviors: #excess damage, don't spawn entities. - !type:DoActsBehavior acts: [ "Destruction" ] @@ -26,7 +26,7 @@ collection: WindowShatter - trigger: !type:DamageTrigger - damage: 150 + damage: 100 behaviors: - !type:PlaySoundBehavior sound: @@ -48,7 +48,7 @@ node: reinforcedPlasmaWindow - type: Appearance - type: DamageVisuals - thresholds: [5, 10, 20] + thresholds: [4, 8, 12] damageDivisor: 6 trackAllDamage: true damageOverlay: @@ -77,8 +77,8 @@ node: plasmaReinforcedWindowDirectional - type: Appearance - type: DamageVisuals - thresholds: [5, 10, 20] - damageDivisor: 3 + thresholds: [4, 8, 12] + damageDivisor: 36 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks_directional.rsi @@ -88,13 +88,13 @@ thresholds: - trigger: !type:DamageTrigger - damage: 150 + damage: 1000 behaviors: #excess damage, don't spawn entities. - !type:DoActsBehavior acts: [ "Destruction" ] - trigger: !type:DamageTrigger - damage: 75 + damage: 600 behaviors: - !type:PlaySoundBehavior sound: diff --git a/Resources/Prototypes/Entities/Structures/Windows/ruranium.yml b/Resources/Prototypes/Entities/Structures/Windows/ruranium.yml index 2231ab6a497e..b9b47c00ea9d 100644 --- a/Resources/Prototypes/Entities/Structures/Windows/ruranium.yml +++ b/Resources/Prototypes/Entities/Structures/Windows/ruranium.yml @@ -43,7 +43,7 @@ node: reinforcedUraniumWindow - type: Appearance - type: DamageVisuals - thresholds: [5, 10, 20] + thresholds: [4, 8, 12] damageDivisor: 6 trackAllDamage: true damageOverlay: @@ -74,8 +74,8 @@ node: uraniumReinforcedWindowDirectional - type: Appearance - type: DamageVisuals - thresholds: [5, 10, 20] - damageDivisor: 3 + thresholds: [4, 8, 12] + damageDivisor: 3.333 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks_directional.rsi @@ -83,13 +83,7 @@ thresholds: - trigger: !type:DamageTrigger - damage: 150 - behaviors: - - !type:DoActsBehavior - acts: [ "Destruction" ] - - trigger: - !type:DamageTrigger - damage: 75 + damage: 200 behaviors: - !type:PlaySoundBehavior sound: @@ -99,7 +93,7 @@ ShardGlassUranium: min: 1 max: 2 - PartRodMetal: + PartRodMetal1: min: 1 max: 2 - !type:DoActsBehavior diff --git a/Resources/Prototypes/Entities/Structures/Windows/shuttle.yml b/Resources/Prototypes/Entities/Structures/Windows/shuttle.yml index 659f5b8a20e7..1b4c96c1709a 100644 --- a/Resources/Prototypes/Entities/Structures/Windows/shuttle.yml +++ b/Resources/Prototypes/Entities/Structures/Windows/shuttle.yml @@ -46,8 +46,8 @@ node: shuttleWindow - type: Appearance - type: DamageVisuals - thresholds: [5, 10, 20] - damageDivisor: 20 + thresholds: [4, 8, 12] + damageDivisor: 28 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks.rsi diff --git a/Resources/Prototypes/Entities/Structures/Windows/uranium.yml b/Resources/Prototypes/Entities/Structures/Windows/uranium.yml index 514463f1d323..c7b7312a7094 100644 --- a/Resources/Prototypes/Entities/Structures/Windows/uranium.yml +++ b/Resources/Prototypes/Entities/Structures/Windows/uranium.yml @@ -11,18 +11,18 @@ state: full - type: Damageable damageContainer: StructuralInorganic - damageModifierSet: Glass + damageModifierSet: RGlass - type: Destructible thresholds: - trigger: !type:DamageTrigger - damage: 150 + damage: 100 behaviors: - !type:DoActsBehavior acts: [ "Destruction" ] - trigger: !type:DamageTrigger - damage: 75 + damage: 60 behaviors: - !type:PlaySoundBehavior sound: @@ -41,8 +41,8 @@ node: uraniumWindow - type: Appearance - type: DamageVisuals - thresholds: [5, 10, 20] - damageDivisor: 3 + thresholds: [4, 8, 12] + damageDivisor: 3.333 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks.rsi @@ -72,8 +72,8 @@ node: uraniumWindowDirectional - type: Appearance - type: DamageVisuals - thresholds: [5, 10, 20] - damageDivisor: 1.5 + thresholds: [4, 8, 12] + damageDivisor: 3.333 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks_directional.rsi @@ -81,13 +81,7 @@ thresholds: - trigger: !type:DamageTrigger - damage: 75 - behaviors: - - !type:DoActsBehavior - acts: [ "Destruction" ] - - trigger: - !type:DamageTrigger - damage: 37 + damage: 200 behaviors: - !type:PlaySoundBehavior sound: @@ -96,7 +90,7 @@ spawn: ShardGlassUranium: min: 1 - max: 1 + max: 2 - !type:DoActsBehavior acts: [ "Destruction" ] - type: StaticPrice diff --git a/Resources/Prototypes/Entities/Structures/Windows/window.yml b/Resources/Prototypes/Entities/Structures/Windows/window.yml index fdf4c2cceade..56a38f82fcfe 100644 --- a/Resources/Prototypes/Entities/Structures/Windows/window.yml +++ b/Resources/Prototypes/Entities/Structures/Windows/window.yml @@ -84,8 +84,8 @@ node: window - type: Appearance - type: DamageVisuals - thresholds: [5, 10, 20] - damageDivisor: 2 + thresholds: [4, 8, 12] + damageDivisor: 3.333 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks.rsi @@ -93,25 +93,6 @@ price: 100 - type: BlockWeather -- type: entity - parent: Window - id: TintedWindow - name: tinted window - components: - - type: Sprite - drawdepth: WallTops - sprite: Structures/Windows/tinted_window.rsi - - type: Icon - sprite: Structures/Windows/tinted_window.rsi - - type: IconSmooth - base: twindow - - type: Construction - graph: Window - node: tintedWindow - - type: Occluder - - type: StaticPrice - price: 70 - - type: entity id: WindowRCDResistant parent: Window @@ -177,7 +158,7 @@ thresholds: - trigger: !type:DamageTrigger - damage: 50 #excess damage (nuke?). avoid computational cost of spawning entities. + damage: 150 #excess damage (nuke?). avoid computational cost of spawning entities. behaviors: - !type:DoActsBehavior acts: [ "Destruction" ] @@ -207,7 +188,8 @@ node: windowDirectional - type: Appearance - type: DamageVisuals - thresholds: [5, 10, 20] + thresholds: [4, 8, 12] + damageDivisor: 3.333 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks_directional.rsi @@ -238,8 +220,6 @@ - type: Icon sprite: Structures/Windows/directional.rsi state: frosted_window - - type: StaticPrice - price: 35 - type: entity parent: Window diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/structures/window.yml b/Resources/Prototypes/Recipes/Construction/Graphs/structures/window.yml index 1782c5924bfe..37682eb0913d 100644 --- a/Resources/Prototypes/Recipes/Construction/Graphs/structures/window.yml +++ b/Resources/Prototypes/Recipes/Construction/Graphs/structures/window.yml @@ -4,63 +4,61 @@ graph: - node: start edges: - - to: window # 50 hp + - to: plasmaWindow steps: - - material: Glass + - material: PlasmaGlass amount: 2 doAfter: 2 - - to: tintedWindow # 50 hp + - to: reinforcedWindow steps: - - material: Glass + - material: ReinforcedGlass amount: 2 - - material: Plastic + doAfter: 2 + + - to: tintedWindow + steps: + - material: ReinforcedGlass amount: 2 doAfter: 2 - - to: plasmaWindow # 75 hp + - to: reinforcedPlasmaWindow steps: - - material: PlasmaGlass + - material: ReinforcedPlasmaGlass amount: 2 doAfter: 3 - - to: uraniumWindow # 75 hp + - to: uraniumWindow steps: - material: UraniumGlass amount: 2 - doAfter: 3 + doAfter: 2 - - to: clockworkWindow # 75 hp reinforced damage mod + - to: reinforcedUraniumWindow steps: - - material: ClockworkGlass + - material: ReinforcedUraniumGlass amount: 2 doAfter: 3 - - to: reinforcedWindow # 75 hp reinforced damage mod + - to: window steps: - - material: ReinforcedGlass + - material: Glass amount: 2 doAfter: 3 - - to: reinforcedPlasmaWindow # 150 hp reinforced damage mod + - to: shuttleWindow steps: - - material: ReinforcedPlasmaGlass + - material: Plasteel amount: 2 - doAfter: 4 - - - to: reinforcedUraniumWindow # 150 hp reinforced damage mod - steps: - - material: ReinforcedUraniumGlass + - material: ReinforcedGlass amount: 2 doAfter: 4 - - - to: shuttleWindow # 500 hp reinforced damage mod (wow) + + - to: clockworkWindow steps: - - material: Plasteel - amount: 2 - - material: ReinforcedGlass + - material: ClockworkGlass amount: 2 - doAfter: 6 + doAfter: 3 - node: window entity: Window @@ -76,81 +74,56 @@ doAfter: 1 - tool: Anchoring doAfter: 2 - - to: tintedWindow - steps: - - material: Plastic - amount: 2 - doAfter: 0.5 - - to: plasmaWindow - steps: - - material: Plasma - amount: 2 - doAfter: 1 - - to: uraniumWindow - steps: - - material: Uranium - amount: 2 - doAfter: 1 - - to: clockworkWindow - steps: - - material: Brass - amount: 2 - doAfter: 2 - - to: reinforcedWindow - steps: - - material: MetalRod - amount: 2 - doAfter: 2 - - node: tintedWindow - entity: TintedWindow + - node: reinforcedWindow + entity: ReinforcedWindow edges: - to: start completed: - !type:SpawnPrototype - prototype: SheetGlass1 - amount: 2 - - !type:SpawnPrototype - prototype: SheetPlastic1 + prototype: SheetRGlass1 amount: 2 - !type:DeleteEntity {} steps: + - tool: Welding + doAfter: 5 + - tool: Screwing + doAfter: 1 + - tool: Prying + doAfter: 2 + - tool: Welding + doAfter: 5 - tool: Screwing doAfter: 1 - tool: Anchoring doAfter: 2 - - node: plasmaWindow - entity: PlasmaWindow + - node: tintedWindow + entity: TintedWindow edges: - to: start completed: - !type:SpawnPrototype - prototype: SheetPGlass1 + prototype: SheetRGlass1 amount: 2 - !type:DeleteEntity {} steps: - tool: Screwing - doAfter: 2 + doAfter: 1 - tool: Prying - doAfter: 3 - - tool: Screwing doAfter: 2 - - tool: Anchoring - doAfter: 3 - - to: reinforcedPlasmaWindow - steps: - - material: MetalRod - amount: 2 + - tool: Screwing doAfter: 1 + - tool: Anchoring + doAfter: 2 - - node: uraniumWindow - entity: UraniumWindow + - node: plasmaWindow + entity: PlasmaWindow edges: - to: start completed: - !type:SpawnPrototype - prototype: SheetUGlass1 + prototype: SheetPGlass1 amount: 2 - !type:DeleteEntity {} steps: @@ -162,19 +135,14 @@ doAfter: 2 - tool: Anchoring doAfter: 3 - - to: reinforcedUraniumWindow - steps: - - material: MetalRod - amount: 2 - doAfter: 1 - - node: clockworkWindow - entity: ClockworkWindow + - node: reinforcedPlasmaWindow + entity: ReinforcedPlasmaWindow edges: - to: start completed: - !type:SpawnPrototype - prototype: SheetClockworkGlass1 + prototype: SheetRPGlass1 amount: 2 - !type:DeleteEntity {} steps: @@ -191,46 +159,32 @@ - tool: Anchoring doAfter: 3 - - node: reinforcedWindow - entity: ReinforcedWindow + - node: uraniumWindow + entity: UraniumWindow edges: - to: start completed: - !type:SpawnPrototype - prototype: SheetRGlass1 + prototype: SheetUGlass1 amount: 2 - !type:DeleteEntity {} steps: - - tool: Welding - doAfter: 5 - tool: Screwing - doAfter: 1 - - tool: Prying doAfter: 2 - - tool: Welding - doAfter: 5 + - tool: Prying + doAfter: 3 - tool: Screwing - doAfter: 1 - - tool: Anchoring doAfter: 2 - - to: reinforcedPlasmaWindow - steps: - - material: Plasma - amount: 2 - doAfter: 1 - - to: reinforcedUraniumWindow - steps: - - material: Uranium - amount: 2 - doAfter: 1 + - tool: Anchoring + doAfter: 3 - - node: reinforcedPlasmaWindow - entity: ReinforcedPlasmaWindow + - node: reinforcedUraniumWindow + entity: ReinforcedUraniumWindow edges: - to: start completed: - !type:SpawnPrototype - prototype: SheetRPGlass1 + prototype: SheetRUGlass1 amount: 2 - !type:DeleteEntity {} steps: @@ -247,13 +201,13 @@ - tool: Anchoring doAfter: 3 - - node: reinforcedUraniumWindow - entity: ReinforcedUraniumWindow + - node: clockworkWindow + entity: ClockworkWindow edges: - to: start completed: - !type:SpawnPrototype - prototype: SheetRUGlass1 + prototype: SheetClockworkGlass1 amount: 2 - !type:DeleteEntity {} steps: @@ -299,4 +253,4 @@ - tool: Welding doAfter: 4 - tool: Anchoring - doAfter: 1 + doAfter: 1 \ No newline at end of file diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/structures/window_diagonal.yml b/Resources/Prototypes/Recipes/Construction/Graphs/structures/window_diagonal.yml index 63788ae5ad0d..1efe1a8eac87 100644 --- a/Resources/Prototypes/Recipes/Construction/Graphs/structures/window_diagonal.yml +++ b/Resources/Prototypes/Recipes/Construction/Graphs/structures/window_diagonal.yml @@ -4,45 +4,45 @@ graph: - node: start edges: - - to: windowDiagonal - steps: - - material: Glass - amount: 2 - doAfter: 2 - - to: plasmaWindowDiagonal steps: - material: PlasmaGlass amount: 2 doAfter: 2 - - to: uraniumWindowDiagonal + - to: reinforcedWindowDiagonal steps: - - material: UraniumGlass + - material: ReinforcedGlass amount: 2 doAfter: 2 - - to: clockworkWindowDiagonal + - to: reinforcedPlasmaWindowDiagonal steps: - - material: ClockworkGlass + - material: ReinforcedPlasmaGlass amount: 2 doAfter: 3 - - to: reinforcedWindowDiagonal + - to: uraniumWindowDiagonal steps: - - material: ReinforcedGlass + - material: UraniumGlass amount: 2 doAfter: 2 - - to: reinforcedPlasmaWindowDiagonal + - to: reinforcedUraniumWindowDiagonal steps: - - material: ReinforcedPlasmaGlass + - material: ReinforcedUraniumGlass amount: 2 doAfter: 3 - - to: reinforcedUraniumWindowDiagonal + - to: clockworkWindowDiagonal steps: - - material: ReinforcedUraniumGlass + - material: ClockworkGlass + amount: 2 + doAfter: 3 + + - to: windowDiagonal + steps: + - material: Glass amount: 2 doAfter: 3 @@ -60,74 +60,29 @@ doAfter: 1 - tool: Anchoring doAfter: 2 - - to: plasmaWindowDiagonal - steps: - - material: Plasma - amount: 2 - doAfter: 1 - - to: uraniumWindowDiagonal - steps: - - material: Uranium - amount: 2 - doAfter: 1 - - to: clockworkWindowDiagonal - steps: - - material: Brass - amount: 2 - doAfter: 2 - - to: reinforcedWindowDiagonal - steps: - - material: MetalRod - amount: 2 - doAfter: 2 - - node: plasmaWindowDiagonal - entity: PlasmaWindowDiagonal + - node: reinforcedWindowDiagonal + entity: ReinforcedWindowDiagonal edges: - to: start completed: - !type:SpawnPrototype - prototype: SheetPGlass1 + prototype: SheetRGlass1 amount: 2 - !type:DeleteEntity {} steps: + - tool: Welding + doAfter: 5 - tool: Screwing - doAfter: 2 - - tool: Prying - doAfter: 3 - - tool: Screwing - doAfter: 2 - - tool: Anchoring - doAfter: 3 - - to: reinforcedPlasmaWindowDiagonal - steps: - - material: MetalRod - amount: 2 doAfter: 1 - - - node: uraniumWindowDiagonal - entity: UraniumWindowDiagonal - edges: - - to: start - completed: - - !type:SpawnPrototype - prototype: SheetUGlass1 - amount: 2 - - !type:DeleteEntity {} - steps: - - tool: Screwing - doAfter: 2 - tool: Prying - doAfter: 3 - - tool: Screwing doAfter: 2 - - tool: Anchoring - doAfter: 3 - - to: reinforcedUraniumWindowDiagonal - steps: - - material: MetalRod - amount: 2 + - tool: Welding + doAfter: 5 + - tool: Screwing doAfter: 1 + - tool: Anchoring + doAfter: 2 - node: clockworkWindowDiagonal entity: ClockworkWindowDiagonal @@ -152,38 +107,24 @@ - tool: Anchoring doAfter: 2 - - node: reinforcedWindowDiagonal - entity: ReinforcedWindowDiagonal + - node: plasmaWindowDiagonal + entity: PlasmaWindowDiagonal edges: - to: start completed: - !type:SpawnPrototype - prototype: SheetRGlass1 + prototype: SheetPGlass1 amount: 2 - !type:DeleteEntity {} steps: - - tool: Welding - doAfter: 5 - tool: Screwing - doAfter: 1 - - tool: Prying doAfter: 2 - - tool: Welding - doAfter: 5 + - tool: Prying + doAfter: 3 - tool: Screwing - doAfter: 1 - - tool: Anchoring doAfter: 2 - - to: reinforcedPlasmaWindowDiagonal - steps: - - material: Plasma - amount: 2 - doAfter: 1 - - to: reinforcedUraniumWindowDiagonal - steps: - - material: Uranium - amount: 2 - doAfter: 1 + - tool: Anchoring + doAfter: 3 - node: reinforcedPlasmaWindowDiagonal entity: ReinforcedPlasmaWindowDiagonal @@ -208,6 +149,25 @@ - tool: Anchoring doAfter: 3 + - node: uraniumWindowDiagonal + entity: UraniumWindowDiagonal + edges: + - to: start + completed: + - !type:SpawnPrototype + prototype: SheetUGlass1 + amount: 2 + - !type:DeleteEntity {} + steps: + - tool: Screwing + doAfter: 2 + - tool: Prying + doAfter: 3 + - tool: Screwing + doAfter: 2 + - tool: Anchoring + doAfter: 3 + - node: reinforcedUraniumWindowDiagonal entity: ReinforcedUraniumWindowDiagonal edges: @@ -229,4 +189,4 @@ - tool: Screwing doAfter: 2 - tool: Anchoring - doAfter: 3 + doAfter: 3 \ No newline at end of file diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/structures/windowdirectional.yml b/Resources/Prototypes/Recipes/Construction/Graphs/structures/windowdirectional.yml index 7d3ace33c7fd..dc10ce9ecbba 100644 --- a/Resources/Prototypes/Recipes/Construction/Graphs/structures/windowdirectional.yml +++ b/Resources/Prototypes/Recipes/Construction/Graphs/structures/windowdirectional.yml @@ -4,55 +4,47 @@ graph: - node: start edges: - - to: windowDirectional # 25 hp - steps: - - material: Glass - amount: 1 - doAfter: 1 - - to: windowFrostedDirectional # 25 hp + - to: windowDirectional steps: - material: Glass amount: 1 - - material: Plastic - amount: 1 - doAfter: 1 + doAfter: 2 - - to: plasmaWindowDirectional # 37 hp + - to: windowReinforcedDirectional steps: - - material: PlasmaGlass + - material: ReinforcedGlass amount: 1 - doAfter: 1.5 + doAfter: 3 - - to: uraniumWindowDirectional # 37 hp + - to: plasmaWindowDirectional steps: - - material: UraniumGlass + - material: PlasmaGlass amount: 1 - doAfter: 1.5 + doAfter: 2 - - to: windowClockworkDirectional # 37 hp reinforced damage mod + - to: plasmaReinforcedWindowDirectional steps: - - material: ClockworkGlass + - material: ReinforcedPlasmaGlass amount: 1 - doAfter: 1.5 - - - to: windowReinforcedDirectional # 37 hp reinforced damage mod + doAfter: 3 + - to: uraniumWindowDirectional steps: - - material: ReinforcedGlass + - material: UraniumGlass amount: 1 - doAfter: 1.5 + doAfter: 2 - - to: plasmaReinforcedWindowDirectional # 75 hp reinforced damage mod + - to: uraniumReinforcedWindowDirectional steps: - - material: ReinforcedPlasmaGlass + - material: ReinforcedUraniumGlass amount: 1 - doAfter: 2 + doAfter: 3 - - to: uraniumReinforcedWindowDirectional # 75 hp reinforced damage mod + - to: windowClockworkDirectional steps: - - material: ReinforcedUraniumGlass + - material: ClockworkGlass amount: 1 - doAfter: 2 + doAfter: 3 - node: windowDirectional entity: WindowDirectional @@ -68,45 +60,21 @@ doAfter: 1 - tool: Anchoring doAfter: 2 - - to: windowFrostedDirectional - steps: - - material: Plastic - amount: 1 - doAfter: 0.5 - - to: plasmaWindowDirectional - steps: - - material: Plasma - amount: 1 - doAfter: 0.5 - - to: uraniumWindowDirectional - steps: - - material: Uranium - amount: 1 - doAfter: 0.5 - - to: windowClockworkDirectional - steps: - - material: Brass - amount: 1 - doAfter: 1 - - to: windowReinforcedDirectional - steps: - - material: MetalRod - amount: 1 - doAfter: 1 - - node: windowFrostedDirectional - entity: WindowFrostedDirectional + - node: windowReinforcedDirectional + entity: WindowReinforcedDirectional edges: - to: start completed: - !type:SpawnPrototype - prototype: SheetGlass1 - amount: 1 - - !type:SpawnPrototype - prototype: SheetPlastic1 + prototype: SheetRGlass1 amount: 1 - !type:DeleteEntity {} steps: + - tool: Screwing + doAfter: 1 + - tool: Prying + doAfter: 2 - tool: Screwing doAfter: 1 - tool: Anchoring @@ -130,19 +98,14 @@ doAfter: 2 - tool: Anchoring doAfter: 3 - - to: plasmaReinforcedWindowDirectional - steps: - - material: MetalRod - amount: 1 - doAfter: 0.5 - - node: uraniumWindowDirectional - entity: UraniumWindowDirectional + - node: windowClockworkDirectional + entity: WindowClockworkDirectional edges: - to: start completed: - !type:SpawnPrototype - prototype: SheetUGlass1 + prototype: SheetClockworkGlass1 amount: 1 - !type:DeleteEntity {} steps: @@ -154,19 +117,14 @@ doAfter: 2 - tool: Anchoring doAfter: 3 - - to: uraniumReinforcedWindowDirectional - steps: - - material: MetalRod - amount: 1 - doAfter: 0.5 - - node: windowClockworkDirectional - entity: WindowClockworkDirectional + - node: plasmaReinforcedWindowDirectional + entity: PlasmaReinforcedWindowDirectional edges: - to: start completed: - !type:SpawnPrototype - prototype: SheetClockworkGlass1 + prototype: SheetRPGlass1 amount: 1 - !type:DeleteEntity {} steps: @@ -178,43 +136,13 @@ doAfter: 2 - tool: Anchoring doAfter: 3 - - - node: windowReinforcedDirectional - entity: WindowReinforcedDirectional - edges: - - to: start - completed: - - !type:SpawnPrototype - prototype: SheetRGlass1 - amount: 1 - - !type:DeleteEntity {} - steps: - - tool: Screwing - doAfter: 1 - - tool: Prying - doAfter: 2 - - tool: Screwing - doAfter: 1 - - tool: Anchoring - doAfter: 2 - - to: plasmaReinforcedWindowDirectional - steps: - - material: Plasma - amount: 1 - doAfter: 0.5 - - to: uraniumReinforcedWindowDirectional - steps: - - material: Uranium - amount: 1 - doAfter: 0.5 - - - node: plasmaReinforcedWindowDirectional - entity: PlasmaReinforcedWindowDirectional + - node: uraniumWindowDirectional + entity: UraniumWindowDirectional edges: - to: start completed: - !type:SpawnPrototype - prototype: SheetRPGlass1 + prototype: SheetUGlass1 amount: 1 - !type:DeleteEntity {} steps: @@ -244,4 +172,4 @@ - tool: Screwing doAfter: 2 - tool: Anchoring - doAfter: 3 + doAfter: 3 \ No newline at end of file diff --git a/Resources/Prototypes/Recipes/Construction/structures.yml b/Resources/Prototypes/Recipes/Construction/structures.yml index 71fdbeedafde..31e1264ab084 100644 --- a/Resources/Prototypes/Recipes/Construction/structures.yml +++ b/Resources/Prototypes/Recipes/Construction/structures.yml @@ -455,7 +455,7 @@ startNode: start targetNode: tintedWindow category: construction-category-structures - description: Not clear, but lasers still pass through. + description: Not clear but tough. canBuildInImpassable: true conditions: - !type:EmptyOrWindowValidInTile @@ -512,7 +512,7 @@ targetNode: plasmaWindow category: construction-category-structures canBuildInImpassable: true - description: Clear, with a purple tint. + description: Clear and even tougher, with a purple tint. conditions: - !type:EmptyOrWindowValidInTile - !type:NoWindowsInTile @@ -531,7 +531,7 @@ targetNode: reinforcedPlasmaWindow category: construction-category-structures canBuildInImpassable: true - description: Clear and even tougher, with a purple tint. + description: Fire resistant and even tougher, with a purple tint. conditions: - !type:EmptyOrWindowValidInTile - !type:NoWindowsInTile @@ -569,7 +569,7 @@ targetNode: plasmaWindowDiagonal category: construction-category-structures canBuildInImpassable: true - description: Clear, with a purple tint. + description: Clear and even tougher, with a purple tint. conditions: - !type:EmptyOrWindowValidInTile - !type:NoWindowsInTile @@ -587,7 +587,7 @@ targetNode: reinforcedPlasmaWindowDiagonal category: construction-category-structures canBuildInImpassable: true - description: Clear and even tougher, with a purple tint. + description: Fire resistant and even tougher, with a purple tint. conditions: - !type:EmptyOrWindowValidInTile - !type:NoWindowsInTile @@ -659,7 +659,7 @@ targetNode: plasmaWindowDirectional category: construction-category-structures canBuildInImpassable: true - description: Clear, with a purple tint. + description: Clear and even tougher, with a purple tint. conditions: - !type:EmptyOrWindowValidInTile - !type:NoWindowsInTile @@ -677,7 +677,7 @@ targetNode: plasmaReinforcedWindowDirectional category: construction-category-structures canBuildInImpassable: true - description: Clear and even tougher, with a purple tint. + description: Fire resistant and even tougher, with a purple tint. conditions: - !type:EmptyOrWindowValidInTile - !type:NoWindowsInTile @@ -695,7 +695,7 @@ targetNode: uraniumWindow category: construction-category-structures canBuildInImpassable: true - description: Clear, with added RadAbsorb to protect you from deadly radiation. + description: Clear and much tougher than regular glass, with added RadAbsorb to protect you from deadly radiation. conditions: - !type:EmptyOrWindowValidInTile - !type:NoWindowsInTile @@ -714,7 +714,7 @@ targetNode: reinforcedUraniumWindow category: construction-category-structures canBuildInImpassable: true - description: Clear and even tougher, with added RadAbsorb to protect you from deadly radiation. + description: Clear and much tougher than regular glass, with added RadAbsorb to protect you from deadly radiation. conditions: - !type:EmptyOrWindowValidInTile - !type:NoWindowsInTile @@ -733,7 +733,7 @@ targetNode: uraniumWindowDiagonal category: construction-category-structures canBuildInImpassable: true - description: Clear, with added RadAbsorb to protect you from deadly radiation. + description: Clear and much tougher than regular glass, with added RadAbsorb to protect you from deadly radiation. conditions: - !type:EmptyOrWindowValidInTile - !type:NoWindowsInTile @@ -751,7 +751,7 @@ targetNode: reinforcedUraniumWindowDiagonal category: construction-category-structures canBuildInImpassable: true - description: Clear and even tougher, with added RadAbsorb to protect you from deadly radiation. + description: Clear and much tougher than regular glass, with added RadAbsorb to protect you from deadly radiation. conditions: - !type:EmptyOrWindowValidInTile - !type:NoWindowsInTile @@ -1456,24 +1456,6 @@ # Same here. - 20kdc - !type:TileNotBlocked -- type: construction - name: emergency light - id: EmergencyLightFixture - graph: LightFixture - startNode: start - targetNode: emergencyLight - category: construction-category-structures - description: An emergency light. - icon: - sprite: Structures/Wallmounts/Lighting/emergency_light.rsi - state: base - objectType: Structure - placementMode: SnapgridCenter - canRotate: true - canBuildInImpassable: false - conditions: - - !type:TileNotBlocked - - type: construction name: ground light post id: LightGroundFixture @@ -1746,4 +1728,4 @@ sprite: Structures/Doors/secret_door.rsi state: closed conditions: - - !type:TileNotBlocked + - !type:TileNotBlocked \ No newline at end of file diff --git a/Resources/Textures/Structures/Windows/cracks.rsi/DamageOverlay_20.png b/Resources/Textures/Structures/Windows/cracks.rsi/DamageOverlay_12.png similarity index 100% rename from Resources/Textures/Structures/Windows/cracks.rsi/DamageOverlay_20.png rename to Resources/Textures/Structures/Windows/cracks.rsi/DamageOverlay_12.png diff --git a/Resources/Textures/Structures/Windows/cracks.rsi/DamageOverlay_5.png b/Resources/Textures/Structures/Windows/cracks.rsi/DamageOverlay_4.png similarity index 100% rename from Resources/Textures/Structures/Windows/cracks.rsi/DamageOverlay_5.png rename to Resources/Textures/Structures/Windows/cracks.rsi/DamageOverlay_4.png diff --git a/Resources/Textures/Structures/Windows/cracks.rsi/DamageOverlay_10.png b/Resources/Textures/Structures/Windows/cracks.rsi/DamageOverlay_8.png similarity index 100% rename from Resources/Textures/Structures/Windows/cracks.rsi/DamageOverlay_10.png rename to Resources/Textures/Structures/Windows/cracks.rsi/DamageOverlay_8.png diff --git a/Resources/Textures/Structures/Windows/cracks.rsi/meta.json b/Resources/Textures/Structures/Windows/cracks.rsi/meta.json index ca012e8fc5c5..9d0cc9a505d1 100644 --- a/Resources/Textures/Structures/Windows/cracks.rsi/meta.json +++ b/Resources/Textures/Structures/Windows/cracks.rsi/meta.json @@ -7,8 +7,8 @@ "license": "CC-BY-SA-3.0", "copyright": "Taken from https://github.com/tgstation/tgstation at commit e06b82a7f4b2b09216fb28fd384c95a2e1dc50e5", "states": [ - {"name": "DamageOverlay_5", "directions": 1}, - {"name": "DamageOverlay_10", "directions": 1}, - {"name": "DamageOverlay_20", "directions": 1} + {"name": "DamageOverlay_4", "directions": 1}, + {"name": "DamageOverlay_8", "directions": 1}, + {"name": "DamageOverlay_12", "directions": 1} ] } diff --git a/Resources/Textures/Structures/Windows/cracks_diagonal.rsi/DamageOverlay_20.png b/Resources/Textures/Structures/Windows/cracks_diagonal.rsi/DamageOverlay_12.png similarity index 100% rename from Resources/Textures/Structures/Windows/cracks_diagonal.rsi/DamageOverlay_20.png rename to Resources/Textures/Structures/Windows/cracks_diagonal.rsi/DamageOverlay_12.png diff --git a/Resources/Textures/Structures/Windows/cracks_diagonal.rsi/DamageOverlay_5.png b/Resources/Textures/Structures/Windows/cracks_diagonal.rsi/DamageOverlay_4.png similarity index 100% rename from Resources/Textures/Structures/Windows/cracks_diagonal.rsi/DamageOverlay_5.png rename to Resources/Textures/Structures/Windows/cracks_diagonal.rsi/DamageOverlay_4.png diff --git a/Resources/Textures/Structures/Windows/cracks_diagonal.rsi/DamageOverlay_10.png b/Resources/Textures/Structures/Windows/cracks_diagonal.rsi/DamageOverlay_8.png similarity index 100% rename from Resources/Textures/Structures/Windows/cracks_diagonal.rsi/DamageOverlay_10.png rename to Resources/Textures/Structures/Windows/cracks_diagonal.rsi/DamageOverlay_8.png diff --git a/Resources/Textures/Structures/Windows/cracks_diagonal.rsi/meta.json b/Resources/Textures/Structures/Windows/cracks_diagonal.rsi/meta.json index ca012e8fc5c5..9d0cc9a505d1 100644 --- a/Resources/Textures/Structures/Windows/cracks_diagonal.rsi/meta.json +++ b/Resources/Textures/Structures/Windows/cracks_diagonal.rsi/meta.json @@ -7,8 +7,8 @@ "license": "CC-BY-SA-3.0", "copyright": "Taken from https://github.com/tgstation/tgstation at commit e06b82a7f4b2b09216fb28fd384c95a2e1dc50e5", "states": [ - {"name": "DamageOverlay_5", "directions": 1}, - {"name": "DamageOverlay_10", "directions": 1}, - {"name": "DamageOverlay_20", "directions": 1} + {"name": "DamageOverlay_4", "directions": 1}, + {"name": "DamageOverlay_8", "directions": 1}, + {"name": "DamageOverlay_12", "directions": 1} ] } diff --git a/Resources/Textures/Structures/Windows/cracks_directional.rsi/DamageOverlay_20.png b/Resources/Textures/Structures/Windows/cracks_directional.rsi/DamageOverlay_12.png similarity index 100% rename from Resources/Textures/Structures/Windows/cracks_directional.rsi/DamageOverlay_20.png rename to Resources/Textures/Structures/Windows/cracks_directional.rsi/DamageOverlay_12.png diff --git a/Resources/Textures/Structures/Windows/cracks_directional.rsi/DamageOverlay_5.png b/Resources/Textures/Structures/Windows/cracks_directional.rsi/DamageOverlay_4.png similarity index 100% rename from Resources/Textures/Structures/Windows/cracks_directional.rsi/DamageOverlay_5.png rename to Resources/Textures/Structures/Windows/cracks_directional.rsi/DamageOverlay_4.png diff --git a/Resources/Textures/Structures/Windows/cracks_directional.rsi/DamageOverlay_10.png b/Resources/Textures/Structures/Windows/cracks_directional.rsi/DamageOverlay_8.png similarity index 100% rename from Resources/Textures/Structures/Windows/cracks_directional.rsi/DamageOverlay_10.png rename to Resources/Textures/Structures/Windows/cracks_directional.rsi/DamageOverlay_8.png diff --git a/Resources/Textures/Structures/Windows/cracks_directional.rsi/meta.json b/Resources/Textures/Structures/Windows/cracks_directional.rsi/meta.json index 9555aa5ab35b..df077f67d2bb 100644 --- a/Resources/Textures/Structures/Windows/cracks_directional.rsi/meta.json +++ b/Resources/Textures/Structures/Windows/cracks_directional.rsi/meta.json @@ -8,15 +8,15 @@ "copyright": "Adapted from https://github.com/space-wizards/space-station-14/ at commit f57e8ec6b9b4b72ef56c8146be0bc159ed2691ee, originally added by Zumorica, and modified for directional use by Darkie", "states": [ { - "name": "DamageOverlay_5", + "name": "DamageOverlay_4", "directions": 4 }, { - "name": "DamageOverlay_10", + "name": "DamageOverlay_8", "directions": 4 }, { - "name": "DamageOverlay_20", + "name": "DamageOverlay_12", "directions": 4 } ] From 6c7336b0a8330369f8a96bff752dda570e3ffb59 Mon Sep 17 00:00:00 2001 From: cohanna Date: Wed, 6 Nov 2024 22:01:10 -0700 Subject: [PATCH 052/290] oops reverted too much --- Resources/Prototypes/Entities/Structures/Windows/clockwork.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Resources/Prototypes/Entities/Structures/Windows/clockwork.yml b/Resources/Prototypes/Entities/Structures/Windows/clockwork.yml index 992dfcda1cbe..6abeae5760b1 100644 --- a/Resources/Prototypes/Entities/Structures/Windows/clockwork.yml +++ b/Resources/Prototypes/Entities/Structures/Windows/clockwork.yml @@ -86,6 +86,7 @@ - trigger: !type:DamageTrigger damage: 150 + behaviors: - !type:PlaySoundBehavior sound: collection: WindowShatter @@ -142,4 +143,4 @@ sprite: Structures/Windows/cracks_diagonal.rsi - type: Construction graph: WindowDiagonal - node: clockworkWindowDiagonal + node: clockworkWindowDiagonal \ No newline at end of file From 287a9a07de9911ac2f32edc4058b5330c89136df Mon Sep 17 00:00:00 2001 From: ScarKy0 <106310278+ScarKy0@users.noreply.github.com> Date: Sat, 9 Nov 2024 20:29:29 +0100 Subject: [PATCH 053/290] Intellicards now have a doAfter. (#33198) * init * cleanup * Oops! Forgot something * addressing changes * guh * guh 2.0 * some cleanup * all bless the intellicard * Yippee * small locale thing * changes + small bugfix --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> --- .../Silicons/StationAi/StationAiSystem.cs | 20 ++++- .../Components/IntellicardComponent.cs | 39 ++++++++++ .../StationAi/SharedStationAiSystem.Held.cs | 20 ++++- .../StationAi/SharedStationAiSystem.cs | 75 ++++++++++++++++++- .../Locale/en-US/intellicard/intellicard.ftl | 3 + .../Locale/en-US/silicons/station-ai.ftl | 2 + .../Entities/Mobs/Player/silicon.yml | 1 + 7 files changed, 153 insertions(+), 7 deletions(-) create mode 100644 Content.Shared/Intellicard/Components/IntellicardComponent.cs create mode 100644 Resources/Locale/en-US/intellicard/intellicard.ftl diff --git a/Content.Server/Silicons/StationAi/StationAiSystem.cs b/Content.Server/Silicons/StationAi/StationAiSystem.cs index 846497387d24..a10833dc63b0 100644 --- a/Content.Server/Silicons/StationAi/StationAiSystem.cs +++ b/Content.Server/Silicons/StationAi/StationAiSystem.cs @@ -1,10 +1,11 @@ using System.Linq; using Content.Server.Chat.Managers; -using Content.Server.Chat.Systems; using Content.Shared.Chat; +using Content.Shared.Mind; +using Content.Shared.Roles; using Content.Shared.Silicons.StationAi; using Content.Shared.StationAi; -using Robust.Shared.Audio.Systems; +using Robust.Shared.Audio; using Robust.Shared.Map.Components; using Robust.Shared.Player; @@ -14,6 +15,8 @@ public sealed class StationAiSystem : SharedStationAiSystem { [Dependency] private readonly IChatManager _chats = default!; [Dependency] private readonly EntityLookupSystem _lookup = default!; + [Dependency] private readonly SharedMindSystem _mind = default!; + [Dependency] private readonly SharedRoleSystem _roles = default!; private readonly HashSet> _ais = new(); @@ -43,6 +46,19 @@ public override bool SetWhitelistEnabled(Entity ent return true; } + public override void AnnounceIntellicardUsage(EntityUid uid, SoundSpecifier? cue = null) + { + if (!TryComp(uid, out var actor)) + return; + + var msg = Loc.GetString("ai-consciousness-download-warning"); + var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", msg)); + _chats.ChatMessageToOne(ChatChannel.Server, msg, wrappedMessage, default, false, actor.PlayerSession.Channel, colorOverride: Color.Red); + + if (cue != null && _mind.TryGetMind(uid, out var mindId, out _)) + _roles.MindPlaySound(mindId, cue); + } + private void AnnounceSnip(EntityUid entity) { var xform = Transform(entity); diff --git a/Content.Shared/Intellicard/Components/IntellicardComponent.cs b/Content.Shared/Intellicard/Components/IntellicardComponent.cs new file mode 100644 index 000000000000..e27174977fb1 --- /dev/null +++ b/Content.Shared/Intellicard/Components/IntellicardComponent.cs @@ -0,0 +1,39 @@ +using Robust.Shared.Audio; +using Robust.Shared.GameStates; + +namespace Content.Shared.Intellicard; + +/// +/// Allows this entity to download the station AI onto an AiHolderComponent. +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class IntellicardComponent : Component +{ + /// + /// The duration it takes to download the AI from an AiHolder. + /// + [DataField, AutoNetworkedField] + public int DownloadTime = 15; + + /// + /// The duration it takes to upload the AI to an AiHolder. + /// + [DataField, AutoNetworkedField] + public int UploadTime = 3; + + /// + /// The sound that plays for the AI + /// when they are being downloaded + /// + [DataField, AutoNetworkedField] + public SoundSpecifier? WarningSound = new SoundPathSpecifier("/Audio/Misc/notice2.ogg"); + + /// + /// The delay before allowing the warning to play again in seconds. + /// + [DataField, AutoNetworkedField] + public TimeSpan WarningDelay = TimeSpan.FromSeconds(8); + + [ViewVariables] + public TimeSpan NextWarningAllowed = TimeSpan.Zero; +} diff --git a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.Held.cs b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.Held.cs index e067cf3efadb..c9279b021513 100644 --- a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.Held.cs +++ b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.Held.cs @@ -54,7 +54,7 @@ private void OnCoreJump(Entity ent, ref JumpToCoreEvent } /// - /// Tries to get the entity held in the AI core. + /// Tries to get the entity held in the AI core using StationAiCore. /// private bool TryGetHeld(Entity entity, out EntityUid held) { @@ -71,6 +71,24 @@ private bool TryGetHeld(Entity entity, out EntityUid he return true; } + /// + /// Tries to get the entity held in the AI using StationAiHolder. + /// + private bool TryGetHeldFromHolder(Entity entity, out EntityUid held) + { + held = EntityUid.Invalid; + + if (!Resolve(entity.Owner, ref entity.Comp)) + return false; + + if (!_containers.TryGetContainer(entity.Owner, StationAiHolderComponent.Container, out var container) || + container.ContainedEntities.Count == 0) + return false; + + held = container.ContainedEntities[0]; + return true; + } + private bool TryGetCore(EntityUid ent, out Entity core) { if (!_containers.TryGetContainingContainer(ent, out var container) || diff --git a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs index f88df9eea6b7..189515635a82 100644 --- a/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs +++ b/Content.Shared/Silicons/StationAi/SharedStationAiSystem.cs @@ -4,7 +4,9 @@ using Content.Shared.Containers.ItemSlots; using Content.Shared.Database; using Content.Shared.Doors.Systems; +using Content.Shared.DoAfter; using Content.Shared.Electrocution; +using Content.Shared.Intellicard; using Content.Shared.Interaction; using Content.Shared.Item.ItemToggle; using Content.Shared.Mind; @@ -15,6 +17,7 @@ using Content.Shared.Power.EntitySystems; using Content.Shared.StationAi; using Content.Shared.Verbs; +using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Containers; using Robust.Shared.Map.Components; @@ -40,6 +43,7 @@ public abstract partial class SharedStationAiSystem : EntitySystem [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedContainerSystem _containers = default!; [Dependency] private readonly SharedDoorSystem _doors = default!; + [Dependency] private readonly SharedDoAfterSystem _doAfter = default!; [Dependency] private readonly SharedElectrocutionSystem _electrify = default!; [Dependency] private readonly SharedEyeSystem _eye = default!; [Dependency] protected readonly SharedMapSystem Maps = default!; @@ -87,6 +91,7 @@ public override void Initialize() SubscribeLocalEvent(OnHolderMapInit); SubscribeLocalEvent(OnHolderConInsert); SubscribeLocalEvent(OnHolderConRemove); + SubscribeLocalEvent(OnIntellicardDoAfter); SubscribeLocalEvent(OnAiInsert); SubscribeLocalEvent(OnAiRemove); @@ -197,15 +202,22 @@ private void OnAiInRange(Entity ent, ref InRangeOverr args.InRange = _vision.IsAccessible((targetXform.GridUid.Value, broadphase, grid), targetTile); } - private void OnHolderInteract(Entity ent, ref AfterInteractEvent args) + + private void OnIntellicardDoAfter(Entity ent, ref IntellicardDoAfterEvent args) { - if (!TryComp(args.Target, out StationAiHolderComponent? targetHolder)) + if (args.Cancelled) + return; + + if (args.Handled) + return; + + if (!TryComp(args.Args.Target, out StationAiHolderComponent? targetHolder)) return; // Try to insert our thing into them if (_slots.CanEject(ent.Owner, args.User, ent.Comp.Slot)) { - if (!_slots.TryInsert(args.Target.Value, targetHolder.Slot, ent.Comp.Slot.Item!.Value, args.User, excludeUserAudio: true)) + if (!_slots.TryInsert(args.Args.Target.Value, targetHolder.Slot, ent.Comp.Slot.Item!.Value, args.User, excludeUserAudio: true)) { return; } @@ -215,7 +227,7 @@ private void OnHolderInteract(Entity ent, ref AfterInt } // Otherwise try to take from them - if (_slots.CanEject(args.Target.Value, args.User, targetHolder.Slot)) + if (_slots.CanEject(args.Args.Target.Value, args.User, targetHolder.Slot)) { if (!_slots.TryInsert(ent.Owner, ent.Comp.Slot, targetHolder.Slot.Item!.Value, args.User, excludeUserAudio: true)) { @@ -226,6 +238,55 @@ private void OnHolderInteract(Entity ent, ref AfterInt } } + private void OnHolderInteract(Entity ent, ref AfterInteractEvent args) + { + if (args.Handled || !args.CanReach || args.Target == null) + return; + + if (!TryComp(args.Target, out StationAiHolderComponent? targetHolder)) + return; + + //Don't want to download/upload between several intellicards. You can just pick it up at that point. + if (HasComp(args.Target)) + return; + + if (!TryComp(args.Used, out IntellicardComponent? intelliComp)) + return; + + var cardHasAi = _slots.CanEject(ent.Owner, args.User, ent.Comp.Slot); + var coreHasAi = _slots.CanEject(args.Target.Value, args.User, targetHolder.Slot); + + if (cardHasAi && coreHasAi) + { + _popup.PopupClient(Loc.GetString("intellicard-core-occupied"), args.User, args.User, PopupType.Medium); + args.Handled = true; + return; + } + if (!cardHasAi && !coreHasAi) + { + _popup.PopupClient(Loc.GetString("intellicard-core-empty"), args.User, args.User, PopupType.Medium); + args.Handled = true; + return; + } + + if (TryGetHeldFromHolder((args.Target.Value, targetHolder), out var held) && _timing.CurTime > intelliComp.NextWarningAllowed) + { + intelliComp.NextWarningAllowed = _timing.CurTime + intelliComp.WarningDelay; + AnnounceIntellicardUsage(held, intelliComp.WarningSound); + } + + var doAfterArgs = new DoAfterArgs(EntityManager, args.User, cardHasAi ? intelliComp.UploadTime : intelliComp.DownloadTime, new IntellicardDoAfterEvent(), args.Target, ent.Owner) + { + BreakOnDamage = true, + BreakOnMove = true, + NeedHand = true, + BreakOnDropItem = true + }; + + _doAfter.TryStartDoAfter(doAfterArgs); + args.Handled = true; + } + private void OnHolderInit(Entity ent, ref ComponentInit args) { _slots.AddItemSlot(ent.Owner, StationAiHolderComponent.Container, ent.Comp.Slot); @@ -378,6 +439,8 @@ private void UpdateAppearance(Entity entity) _appearance.SetData(entity.Owner, StationAiVisualState.Key, StationAiState.Occupied); } + public virtual void AnnounceIntellicardUsage(EntityUid uid, SoundSpecifier? cue = null) { } + public virtual bool SetVisionEnabled(Entity entity, bool enabled, bool announce = false) { if (entity.Comp.Enabled == enabled) @@ -419,6 +482,10 @@ public sealed partial class JumpToCoreEvent : InstantActionEvent } +[Serializable, NetSerializable] +public sealed partial class IntellicardDoAfterEvent : SimpleDoAfterEvent; + + [Serializable, NetSerializable] public enum StationAiVisualState : byte { diff --git a/Resources/Locale/en-US/intellicard/intellicard.ftl b/Resources/Locale/en-US/intellicard/intellicard.ftl new file mode 100644 index 000000000000..aed155a12029 --- /dev/null +++ b/Resources/Locale/en-US/intellicard/intellicard.ftl @@ -0,0 +1,3 @@ +# General +intellicard-core-occupied = The AI core is already occupied by another digital consciousness. +intellicard-core-empty = The AI core has no digital consciousness to download. \ No newline at end of file diff --git a/Resources/Locale/en-US/silicons/station-ai.ftl b/Resources/Locale/en-US/silicons/station-ai.ftl index 7d9db3f6dc5a..76c30eb10187 100644 --- a/Resources/Locale/en-US/silicons/station-ai.ftl +++ b/Resources/Locale/en-US/silicons/station-ai.ftl @@ -20,3 +20,5 @@ electrify-door-off = Disable overcharge toggle-light = Toggle light ai-device-not-responding = Device is not responding + +ai-consciousness-download-warning = Your consciousness is being downloaded. diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml index 39750b470f59..e787ef59f00a 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml @@ -301,6 +301,7 @@ unshaded: Empty: { state: empty } Occupied: { state: full } + - type: Intellicard - type: entity id: PlayerStationAiEmpty From 675e42df2446855694359bbcd9298ac6af3e0e48 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 9 Nov 2024 19:30:38 +0000 Subject: [PATCH 054/290] Automatic changelog update --- Resources/Changelog/Changelog.yml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 485cad8e96d3..a1a17548d489 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: pigeonpeas - changes: - - message: Added non command mantle into the winterdrobe - type: Add - id: 7100 - time: '2024-08-13T09:20:12.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/29774 - author: TheShuEd changes: - message: change the way food is sliced - food is now sliced whole after a small @@ -3948,3 +3941,14 @@ id: 7599 time: '2024-11-08T14:50:17.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/31710 +- author: ScarKy0 + changes: + - message: Intellicarding the AI is now a doAfter. + type: Tweak + - message: AI now gets notified when someone tries to intellicard it. + type: Add + - message: You can no longer exchange the AI between intellicards. + type: Fix + id: 7600 + time: '2024-11-09T19:29:29.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33198 From d1c66d71e7e554cc194f6bc1b4e197b35d3b202a Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 10 Nov 2024 01:46:58 +0100 Subject: [PATCH 055/290] Update Credits (#33237) Co-authored-by: PJBot --- Resources/Credits/GitHub.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Credits/GitHub.txt b/Resources/Credits/GitHub.txt index 8c2ad5f5b0f5..362b82c63f4f 100644 --- a/Resources/Credits/GitHub.txt +++ b/Resources/Credits/GitHub.txt @@ -1 +1 @@ -0x6273, 12rabbits, 13spacemen, 2013HORSEMEATSCANDAL, 20kdc, 21Melkuu, 3nderall, 4310v343k, 4dplanner, 612git, 778b, Ablankmann, abregado, Absolute-Potato, achookh, Acruid, actioninja, actually-reb, ada-please, adamsong, Adeinitas, Admiral-Obvious-001, adrian, Adrian16199, Ady4ik, Aerocrux, Aeshus, Aexolott, Aexxie, africalimedrop, Afrokada, AftrLite, Agoichi, Ahion, aiden, AJCM-git, AjexRose, Alekshhh, alexkar598, AlexMorgan3817, alexumandxgabriel08x, Alithsko, ALMv1, Alpha-Two, AlphaQwerty, Altoids1, amylizzle, ancientpower, Andre19926, AndrewEyeke, AndreyCamper, Anzarot121, Appiah, ar4ill, ArchPigeon, ArchRBX, areitpog, Arendian, arimah, Arkanic, ArkiveDev, armoks, Arteben, ArthurMousatov, ArtisticRoomba, artur, AruMoon, ArZarLordOfMango, as334, AsikKEsel, AsnDen, asperger-sind, aspiringLich, astriloqua, august-sun, AutoOtter, avghdev, Awlod, AzzyIsNotHere, BackeTako, BananaFlambe, Baptr0b0t, BasedUser, beck-thompson, bellwetherlogic, benev0, benjamin-burges, BGare, bhenrich, bhespiritu, bibbly, BIGZi0348, bingojohnson, BismarckShuffle, Bixkitts, Blackern5000, Blazeror, BlitzTheSquishy, bloodrizer, Bloody2372, blueDev2, Boaz1111, BobdaBiscuit, BobTheSleder, boiled-water-tsar, BombasterDS, botanySupremist, brainfood1183, BramvanZijp, Brandon-Huu, BriBrooo, Bright0, brndd, bryce0110, BubblegumBlue, buletsponge, buntobaggins, bvelliquette, byondfuckery, c0rigin, c4llv07e, CaasGit, Caconym27, Calecute, Callmore, capnsockless, CaptainSqrBeard, Carbonhell, Carolyn3114, Carou02, carteblanche4me, Catofquestionableethics, CatTheSystem, Centronias, chairbender, Charlese2, charlie, ChaseFlorom, chavonadelal, Cheackraze, cheesePizza2, cheeseplated, Chief-Engineer, chillyconmor, christhirtle, chromiumboy, Chronophylos, Chubbicous, Chubbygummibear, Ciac32, civilCornball, Clement-O, clyf, Clyybber, CMDR-Piboy314, cohanna, Cohnway, Cojoke-dot, ColdAutumnRain, Colin-Tel, collinlunn, ComicIronic, CookieMasterT, coolboy911, coolmankid12345, Coolsurf6, corentt, CormosLemming, crazybrain23, creadth, CrigCrag, croilbird, Crotalus, CrudeWax, CrzyPotato, cutemoongod, Cyberboss, d34d10cc, d4kii, DadeKuma, Daemon, daerSeebaer, dahnte, dakamakat, DamianX, DangerRevolution, daniel-cr, DanSAussieITS, Daracke, Darkenson, DawBla, Daxxi3, dch-GH, de0rix, Deahaka, dean, DEATHB4DEFEAT, DeathCamel58, Deatherd, deathride58, DebugOk, Decappi, Decortex, Deeeeja, deepdarkdepths, degradka, Delete69, deltanedas, DenisShvalov, DerbyX, derek, dersheppard, Deserty0, Detintinto, DevilishMilk, dexlerxd, dffdff2423, DieselMohawk, digitalic, Dimastra, DinoWattz, DisposableCrewmember42, DjfjdfofdjfjD, doc-michael, docnite, Doctor-Cpu, DoctorBeard, DogZeroX, dolgovmi, dontbetank, Doomsdrayk, Doru991, DoubleRiceEddiedd, DoutorWhite, dragonryan06, drakewill-CRL, Drayff, dreamlyjack, DrEnzyme, dribblydrone, DrMelon, drongood12, DrSingh, DrSmugleaf, drteaspoon420, DTanxxx, DubiousDoggo, Duddino, dukevanity, duskyjay, Dutch-VanDerLinde, dvir001, Dynexust, Easypoller, echo, eclips_e, eden077, EEASAS, Efruit, efzapa, Ekkosangen, ElectroSR, elsie, elthundercloud, Elysium206, Emisse, emmafornash, EmoGarbage404, Endecc, eoineoineoin, eris, erohrs2, ERORR404V1, Errant-4, ertanic, esguard, estacaoespacialpirata, eugene, exincore, exp111, f0x-n3rd, FacePluslll, Fahasor, FairlySadPanda, FATFSAAM2, Feluk6174, ficcialfaint, Fiftyllama, Fildrance, FillerVK, FinnishPaladin, FirinMaLazors, Fishfish458, FL-OZ, Flareguy, flashgnash, FluffiestFloof, FluffMe, FluidRock, foboscheshir, FoLoKe, fooberticus, ForestNoises, forgotmyotheraccount, forkeyboards, forthbridge, Fortune117, Fouin, foxhorn, freeman2651, freeze2222, Froffy025, Fromoriss, froozigiusz, FrostMando, FungiFellow, FunTust, Futuristic-OK, GalacticChimp, gamer3107, Gaxeer, gbasood, Geekyhobo, genderGeometries, GeneralGaws, Genkail, geraeumig, Ghagliiarghii, Git-Nivrak, githubuser508, gituhabu, GlassEclipse, GNF54, godisdeadLOL, goet, Goldminermac, Golinth, GoodWheatley, Gorox221, gradientvera, graevy, GraniteSidewalk, GreaseMonk, greenrock64, GreyMario, GTRsound, gusxyz, Gyrandola, h3half, hamurlik, Hanzdegloker, HappyRoach, Hardly3D, harikattar, he1acdvv, Hebi, Henry, HerCoyote23, hitomishirichan, hiucko, Hmeister-fake, Hmeister-real, Hobbitmax, hobnob, HoidC, Holinka4ever, holyssss, HoofedEar, Hoolny, hord-brayden, Hreno, hubismal, Hugal31, Huxellberger, Hyenh, hyphenationc, i-justuser-i, iacore, IamVelcroboy, Ian321, icekot8, icesickleone, iczero, iglov, IgorAnt028, igorsaux, ike709, illersaver, Illiux, Ilushkins33, Ilya246, IlyaElDunaev, imrenq, imweax, indeano, Injazz, Insineer, IntegerTempest, Interrobang01, IProduceWidgets, ItsMeThom, Itzbenz, iztokbajcar, Jackal298, Jackrost, jacksonzck, Jackw2As, jacob, jamessimo, janekvap, Jark255, Jarmer123, Jaskanbe, JasperJRoth, JerryImMouse, jerryimmouse, Jessetriesagain, jessicamaybe, Jezithyr, jicksaw, JiimBob, JimGamemaster, jimmy12or, JIPDawg, jjtParadox, jmcb, JoeHammad1844, JohnGinnane, johnku1, Jophire, joshepvodka, Jrpl, juliangiebel, JustArt1m, JustCone14, justdie12, justin, justintether, JustinTrotter, justtne, K-Dynamic, k3yw, Kadeo64, Kaga-404, KaiShibaa, kalane15, kalanosh, Kanashi-Panda, katzenminer, kbailey-git, Keelin, Keer-Sar, KEEYNy, keikiru, Kelrak, kerisargit, keronshb, KIBORG04, Killerqu00, Kimpes, KingFroozy, kira-er, Kirillcas, Kirus59, Kistras, Kit0vras, KittenColony, klaypexx, Kmc2000, Ko4ergaPunk, kognise, kokoc9n, komunre, KonstantinAngelov, kosticia, koteq, KrasnoshchekovPavel, Krunklehorn, Kupie, kxvvv, kyupolaris, kzhanik, lajolico, Lamrr, LankLTE, laok233, lapatison, larryrussian, lawdog4817, Lazzi0706, leander-0, leonardo-dabepis, leonsfriedrich, LeoSantich, LetterN, lettern, Level10Cybermancer, LEVELcat, lever1209, Lgibb18, lgruthes, LightVillet, liltenhead, LinkUyx, LittleBuilderJane, LittleNorthStar, LittleNyanCat, lizelive, localcc, lokachop, Lomcastar, LordCarve, LordEclipse, LucasTheDrgn, luckyshotpictures, LudwigVonChesterfield, luizwritescode, Lukasz825700516, luminight, lunarcomets, luringens, lvvova1, Lyndomen, lyroth001, lzimann, lzk228, M3739, mac6na6na, MACMAN2003, Macoron, Magicalus, magmodius, MagnusCrowe, malchanceux, MaloTV, ManelNavola, Mangohydra, marboww, Markek1, Matz05, max, MaxNox7, maylokana, MehimoNemo, MeltedPixel, MemeProof, MendaxxDev, Menshin, Mephisto72, MerrytheManokit, Mervill, metalgearsloth, MetalSage, MFMessage, mhamsterr, michaelcu, micheel665, MilenVolf, MilonPL, Minemoder5000, Minty642, Mirino97, mirrorcult, misandrie, MishaUnity, MissKay1994, MisterMecky, Mith-randalf, MjrLandWhale, mkanke-real, MLGTASTICa, moderatelyaware, modern-nm, mokiros, Moneyl, Moomoobeef, moony, Morb0, mr-bo-jangles, Mr0maks, MrFippik, mrrobdemo, muburu, MureixloI, musicmanvr, MWKane, Myakot, Myctai, N3X15, nails-n-tape, Nairodian, Naive817, NakataRin, namespace-Memory, Nannek, NazrinNya, neutrino-laser, NickPowers43, nikthechampiongr, Nimfar11, Nirnael, NIXC, NkoKirkto, nmajask, noctyrnal, noelkathegod, nok-ko, NonchalantNoob, NoobyLegion, Nopey, not-gavnaed, notafet, notquitehadouken, NotSoDana, noudoit, noverd, NuclearWinter, nukashimika, nuke-haus, NULL882, nullarmo, nyeogmi, Nylux, Nyranu, och-och, OctoRocket, OldDanceJacket, OliverOtter, onoira, OnyxTheBrave, OrangeMoronage9622, osjarw, Ostaf, othymer, OttoMaticode, Owai-Seek, packmore, paigemaeforrest, pali6, Pangogie, panzer-iv1, paolordls, partyaddict, patrikturi, PaulRitter, peccneck, Peptide90, peptron1, PeterFuto, PetMudstone, pewter-wiz, Pgriha, Phantom-Lily, pheenty, Phill101, phunnyguy, PilgrimViis, Pill-U, Pireax, Pissachu, pissdemon, PixeltheAertistContrib, PixelTheKermit, PJB3005, Plasmaguy, plinyvic, Plykiya, poeMota, pofitlo, pointer-to-null, pok27, PolterTzi, PoorMansDreams, PopGamer45, portfiend, potato1234x, PotentiallyTom, ProfanedBane, ProPandaBear, PrPleGoo, ps3moira, Pspritechologist, Psychpsyo, psykzz, PuceTint, PuroSlavKing, PursuitInAshes, Putnam3145, qrtDaniil, quatre, QueerNB, QuietlyWhisper, qwerltaz, RadioMull, Radosvik, Radrark, Rainbeon, Rainfey, Raitononai, Ramlik, RamZ, randy10122, Rane, Ranger6012, Rapidgame7, ravage123321, rbertoche, Redfire1331, Redict, RedlineTriad, redmushie, RednoWCirabrab, RemberBM, RemieRichards, RemTim, rene-descartes2021, Renlou, retequizzle, RiceMar1244, rich-dunne, RieBi, riggleprime, RIKELOLDABOSS, rinary1, Rinkashikachi, riolume, RobbyTheFish, Rockdtben, Rohesie, rok-povsic, rolfero, RomanNovo, rosieposieeee, Roudenn, router, RumiTiger, S1rFl0, S1ss3l, Saakra, Sadie-silly, saga3152, saintmuntzer, Salex08, sam, samgithubaccount, SaphireLattice, SapphicOverload, Sarahon, sativaleanne, SaveliyM360, sBasalto, ScalyChimp, ScarKy0, scrato, Scribbles0, scrivoy, scruq445, scuffedjays, ScumbagDog, Segonist, sephtasm, Serkket, sewerpig, sh18rw, ShadeAware, ShadowCommander, Shadowtheprotogen546, shaeone, shampunj, shariathotpatrol, SignalWalker, siigiil, Simyon264, sirdragooon, Sirionaut, Sk1tch, SkaldetSkaeg, Skarletto, Skrauz, Skyedra, SlamBamActionman, slarticodefast, Slava0135, Slyfox333, snebl, snicket, sniperchance, Snowni, snowsignal, SolidusSnek, SonicHDC, SoulFN, SoulSloth, Soundwavesghost, southbridge-fur, Soydium, spacelizard, SpaceLizardSky, SpaceManiac, SpaceyLady, Spanky, spanky-spanky, spartak, SpartanKadence, SpeltIncorrectyl, Spessmann, SphiraI, SplinterGP, spoogemonster, sporekto, sporkyz, ssdaniel24, stalengd, stanberytrask, Stanislav4ix, StanTheCarpenter, Stealthbomber16, stellar-novas, stomf, stopbreaking, stopka-html, StrawberryMoses, Stray-Pyramid, strO0pwafel, Strol20, StStevens, Subversionary, sunbear-dev, superjj18, Supernorn, SweptWasTaken, Sybil, SYNCHRONIC, Szunti, Tainakov, takemysoult, TaralGit, Taran, taurie, Tayrtahn, tday93, teamaki, TekuNut, telyonok, TemporalOroboros, tentekal, terezi4real, Terraspark4941, texcruize, TGODiamond, TGRCdev, tgrkzus, ThatOneGoblin25, thatrandomcanadianguy, TheArturZh, theashtronaut, thecopbennet, TheCze, TheDarkElites, thedraccx, TheEmber, TheIntoxicatedCat, thekilk, themias, theomund, theOperand, TherapyGoth, TheShuEd, thetolbean, thevinter, TheWaffleJesus, Thinbug0, ThunderBear2006, timothyteakettle, TimrodDX, timurjavid, tin-man-tim, Titian3, tk-a369, tkdrg, tmtmtl30, TokenStyle, Tollhouse, Toly65, tom-leys, tomasalves8, Tomeno, Tonydatguy, topy, Tornado-Technology, tosatur, TotallyLemon, tropicalhibi, truepaintgit, Truoizys, Tryded, TsjipTsjip, Tunguso4ka, TurboTrackerss14, TyAshley, Tyler-IN, Tyzemol, UbaserB, ubis1, UBlueberry, UKNOWH, UltimateJester, Unbelievable-Salmon, underscorex5, UnicornOnLSD, Unisol, Unkn0wnGh0st333, unusualcrow, Uriende, UristMcDorf, user424242420, Vaaankas, valentfingerov, Varen, VasilisThePikachu, veliebm, VelonacepsCalyxEggs, veprolet, veritable-calamity, Veritius, Vermidia, vero5123, Verslebas, VigersRay, violet754, Visne, VMSolidus, voidnull000, volotomite, volundr-, Voomra, Vordenburg, vorkathbruh, vulppine, wafehling, Warentan, WarMechanic, Watermelon914, waylon531, weaversam8, wertanchik, whateverusername0, Willhelm53, WilliamECrew, willicassi, Winkarst-cpu, wirdal, wixoaGit, WlarusFromDaSpace, wrexbe, wtcwr68, xkreksx, xprospero, xRiriq, YanehCheck, yathxyz, Ygg01, YotaXP, youarereadingthis, Yousifb26, youtissoum, YuriyKiss, zach-hill, Zadeon, zamp, Zandario, Zap527, Zealith-Gamer, ZelteHonor, zero, ZeroDiamond, zerorulez, ZeWaka, zionnBE, ZNixian, ZoldorfTheWizard, Zonespace27, Zylofan, Zymem, zzylex +0x6273, 12rabbits, 13spacemen, 2013HORSEMEATSCANDAL, 20kdc, 21Melkuu, 3nderall, 4310v343k, 4dplanner, 612git, 778b, Ablankmann, abregado, Absolute-Potato, achookh, Acruid, actioninja, actually-reb, ada-please, adamsong, Adeinitas, Admiral-Obvious-001, adrian, Adrian16199, Ady4ik, Aerocrux, Aeshus, Aexolott, Aexxie, africalimedrop, Afrokada, AftrLite, Agoichi, Ahion, aiden, AJCM-git, AjexRose, Alekshhh, alexkar598, AlexMorgan3817, alexumandxgabriel08x, Alithsko, ALMv1, Alpha-Two, AlphaQwerty, Altoids1, amylizzle, ancientpower, Andre19926, AndrewEyeke, AndreyCamper, Anzarot121, Appiah, ar4ill, ArchPigeon, ArchRBX, areitpog, Arendian, arimah, Arkanic, ArkiveDev, armoks, Arteben, ArthurMousatov, ArtisticRoomba, artur, AruMoon, ArZarLordOfMango, as334, AsikKEsel, AsnDen, asperger-sind, aspiringLich, astriloqua, august-sun, AutoOtter, avghdev, Awlod, AzzyIsNotHere, BackeTako, BananaFlambe, Baptr0b0t, BasedUser, beck-thompson, bellwetherlogic, benev0, benjamin-burges, BGare, bhenrich, bhespiritu, bibbly, BIGZi0348, bingojohnson, BismarckShuffle, Bixkitts, Blackern5000, Blazeror, BlitzTheSquishy, bloodrizer, Bloody2372, blueDev2, Boaz1111, BobdaBiscuit, BobTheSleder, boiled-water-tsar, BombasterDS, Boolean-Buckeye, botanySupremist, brainfood1183, BramvanZijp, Brandon-Huu, BriBrooo, Bright0, brndd, bryce0110, BubblegumBlue, buletsponge, buntobaggins, bvelliquette, byondfuckery, c0rigin, c4llv07e, CaasGit, Caconym27, Calecute, Callmore, capnsockless, CaptainSqrBeard, Carbonhell, Carolyn3114, Carou02, carteblanche4me, Catofquestionableethics, CatTheSystem, Centronias, chairbender, Charlese2, charlie, ChaseFlorom, chavonadelal, Cheackraze, cheesePizza2, cheeseplated, Chief-Engineer, chillyconmor, christhirtle, chromiumboy, Chronophylos, Chubbicous, Chubbygummibear, Ciac32, civilCornball, Clement-O, clyf, Clyybber, CMDR-Piboy314, cohanna, Cohnway, Cojoke-dot, ColdAutumnRain, Colin-Tel, collinlunn, ComicIronic, CookieMasterT, coolboy911, coolmankid12345, Coolsurf6, corentt, CormosLemming, crazybrain23, creadth, CrigCrag, croilbird, Crotalus, CrudeWax, CrzyPotato, cutemoongod, Cyberboss, d34d10cc, d4kii, DadeKuma, Daemon, daerSeebaer, dahnte, dakamakat, DamianX, DangerRevolution, daniel-cr, DanSAussieITS, Daracke, Darkenson, DawBla, Daxxi3, dch-GH, de0rix, Deahaka, dean, DEATHB4DEFEAT, DeathCamel58, Deatherd, deathride58, DebugOk, Decappi, Decortex, Deeeeja, deepdarkdepths, degradka, Delete69, deltanedas, DenisShvalov, DerbyX, derek, dersheppard, Deserty0, Detintinto, DevilishMilk, dexlerxd, dffdff2423, DieselMohawk, digitalic, Dimastra, DinoWattz, DisposableCrewmember42, DjfjdfofdjfjD, doc-michael, docnite, Doctor-Cpu, DoctorBeard, DogZeroX, dolgovmi, dontbetank, Doomsdrayk, Doru991, DoubleRiceEddiedd, DoutorWhite, dragonryan06, drakewill-CRL, Drayff, dreamlyjack, DrEnzyme, dribblydrone, DrMelon, drongood12, DrSingh, DrSmugleaf, drteaspoon420, DTanxxx, DubiousDoggo, Duddino, dukevanity, duskyjay, Dutch-VanDerLinde, dvir001, Dynexust, Easypoller, echo, eclips_e, eden077, EEASAS, Efruit, efzapa, Ekkosangen, ElectroSR, elsie, elthundercloud, Elysium206, Emisse, emmafornash, EmoGarbage404, Endecc, eoineoineoin, eris, erohrs2, ERORR404V1, Errant-4, ertanic, esguard, estacaoespacialpirata, eugene, ewokswagger, exincore, exp111, f0x-n3rd, FacePluslll, Fahasor, FairlySadPanda, FATFSAAM2, Feluk6174, ficcialfaint, Fiftyllama, Fildrance, FillerVK, FinnishPaladin, firenamefn, FirinMaLazors, Fishfish458, FL-OZ, Flareguy, flashgnash, FluffiestFloof, FluffMe, FluidRock, foboscheshir, FoLoKe, fooberticus, ForestNoises, forgotmyotheraccount, forkeyboards, forthbridge, Fortune117, Fouin, foxhorn, freeman2651, freeze2222, Froffy025, Fromoriss, froozigiusz, FrostMando, FungiFellow, FunTust, Futuristic-OK, GalacticChimp, gamer3107, Gaxeer, gbasood, Geekyhobo, genderGeometries, GeneralGaws, Genkail, geraeumig, Ghagliiarghii, Git-Nivrak, githubuser508, gituhabu, GlassEclipse, GNF54, godisdeadLOL, goet, Goldminermac, Golinth, GoodWheatley, Gorox221, gradientvera, graevy, GraniteSidewalk, GreaseMonk, greenrock64, GreyMario, GTRsound, gusxyz, Gyrandola, h3half, hamurlik, Hanzdegloker, HappyRoach, Hardly3D, harikattar, he1acdvv, Hebi, Henry, HerCoyote23, hitomishirichan, hiucko, Hmeister-fake, Hmeister-real, Hobbitmax, hobnob, HoidC, Holinka4ever, holyssss, HoofedEar, Hoolny, hord-brayden, Hreno, hubismal, Hugal31, Huxellberger, Hyenh, hyphenationc, i-justuser-i, iacore, IamVelcroboy, Ian321, icekot8, icesickleone, iczero, iglov, IgorAnt028, igorsaux, ike709, illersaver, Illiux, Ilushkins33, Ilya246, IlyaElDunaev, imrenq, imweax, indeano, Injazz, Insineer, IntegerTempest, Interrobang01, IProduceWidgets, ItsMeThom, Itzbenz, iztokbajcar, Jackal298, Jackrost, jacksonzck, Jackw2As, jacob, jamessimo, janekvap, Jark255, Jarmer123, Jaskanbe, JasperJRoth, jerryimmouse, JerryImMouse, Jessetriesagain, jessicamaybe, Jezithyr, jicksaw, JiimBob, JimGamemaster, jimmy12or, JIPDawg, jjtParadox, jmcb, JoeHammad1844, JohnGinnane, johnku1, Jophire, joshepvodka, Jrpl, juliangiebel, JustArt1m, JustCone14, justdie12, justin, justintether, JustinTrotter, justtne, K-Dynamic, k3yw, Kadeo64, Kaga-404, KaiShibaa, kalane15, kalanosh, Kanashi-Panda, katzenminer, kbailey-git, Keelin, Keer-Sar, KEEYNy, keikiru, Kelrak, kerisargit, keronshb, KIBORG04, Killerqu00, Kimpes, KingFroozy, kira-er, Kirillcas, Kirus59, Kistras, Kit0vras, KittenColony, klaypexx, Kmc2000, Ko4ergaPunk, kognise, kokoc9n, komunre, KonstantinAngelov, kosticia, koteq, KrasnoshchekovPavel, Krunklehorn, Kupie, kxvvv, kyupolaris, kzhanik, lajolico, Lamrr, LankLTE, laok233, lapatison, larryrussian, lawdog4817, Lazzi0706, leander-0, leonardo-dabepis, leonsfriedrich, LeoSantich, LetterN, lettern, Level10Cybermancer, LEVELcat, lever1209, Lgibb18, lgruthes, LightVillet, liltenhead, LinkUyx, LittleBuilderJane, LittleNorthStar, LittleNyanCat, lizelive, localcc, lokachop, Lomcastar, LordCarve, LordEclipse, LucasTheDrgn, luckyshotpictures, LudwigVonChesterfield, luizwritescode, Lukasz825700516, luminight, lunarcomets, luringens, lvvova1, Lyndomen, lyroth001, lzimann, lzk228, M3739, mac6na6na, MACMAN2003, Macoron, Magicalus, magmodius, MagnusCrowe, malchanceux, MaloTV, ManelNavola, Mangohydra, marboww, Markek1, Matz05, max, MaxNox7, maylokana, MehimoNemo, MeltedPixel, MemeProof, MendaxxDev, Menshin, Mephisto72, MerrytheManokit, Mervill, metalgearsloth, MetalSage, MFMessage, mhamsterr, michaelcu, micheel665, MilenVolf, MilonPL, Minemoder5000, Minty642, Mirino97, mirrorcult, misandrie, MishaUnity, MissKay1994, MisterMecky, Mith-randalf, MjrLandWhale, mkanke-real, MLGTASTICa, moderatelyaware, modern-nm, mokiros, Moneyl, Moomoobeef, moony, Morb0, mr-bo-jangles, Mr0maks, MrFippik, mrrobdemo, muburu, MureixloI, musicmanvr, MWKane, Myakot, Myctai, N3X15, nails-n-tape, Nairodian, Naive817, NakataRin, namespace-Memory, Nannek, NazrinNya, neutrino-laser, NickPowers43, nikthechampiongr, Nimfar11, Nirnael, NIXC, NkoKirkto, nmajask, noctyrnal, noelkathegod, nok-ko, NonchalantNoob, NoobyLegion, Nopey, not-gavnaed, notafet, notquitehadouken, NotSoDana, noudoit, noverd, NuclearWinter, nukashimika, nuke-haus, NULL882, nullarmo, nyeogmi, Nylux, Nyranu, och-och, OctoRocket, OldDanceJacket, OliverOtter, OnyxTheBrave, OrangeMoronage9622, osjarw, Ostaf, othymer, OttoMaticode, Owai-Seek, packmore, paigemaeforrest, pali6, Pangogie, panzer-iv1, paolordls, partyaddict, patrikturi, PaulRitter, peccneck, Peptide90, peptron1, PeterFuto, PetMudstone, pewter-wiz, Pgriha, Phantom-Lily, pheenty, Phill101, phunnyguy, PilgrimViis, Pill-U, Pireax, Pissachu, pissdemon, PixeltheAertistContrib, PixelTheKermit, PJB3005, Plasmaguy, plinyvic, Plykiya, poeMota, pofitlo, pointer-to-null, pok27, PolterTzi, PoorMansDreams, PopGamer45, portfiend, potato1234x, PotentiallyTom, ProfanedBane, ProPandaBear, PrPleGoo, ps3moira, Pspritechologist, Psychpsyo, psykzz, PuceTint, PuroSlavKing, PursuitInAshes, Putnam3145, qrtDaniil, quatre, QueerNB, QuietlyWhisper, qwerltaz, RadioMull, Radosvik, Radrark, Rainbeon, Rainfey, Raitononai, Ramlik, RamZ, randy10122, Rane, Ranger6012, Rapidgame7, ravage123321, rbertoche, Redfire1331, Redict, RedlineTriad, redmushie, RednoWCirabrab, RemberBM, RemieRichards, RemTim, rene-descartes2021, Renlou, retequizzle, rich-dunne, RieBi, riggleprime, RIKELOLDABOSS, rinary1, Rinkashikachi, riolume, RobbyTheFish, Rockdtben, Rohesie, rok-povsic, rolfero, RomanNovo, rosieposieeee, Roudenn, router, RumiTiger, S1rFl0, S1ss3l, Saakra, Sadie-silly, saga3152, saintmuntzer, Salex08, sam, samgithubaccount, SaphireLattice, SapphicOverload, Sarahon, sativaleanne, SaveliyM360, sBasalto, ScalyChimp, ScarKy0, scrato, Scribbles0, scrivoy, scruq445, scuffedjays, ScumbagDog, Segonist, sephtasm, Serkket, sewerpig, sh18rw, ShadeAware, ShadowCommander, Shadowtheprotogen546, shaeone, shampunj, shariathotpatrol, SignalWalker, siigiil, Simyon264, sirdragooon, Sirionaut, Sk1tch, SkaldetSkaeg, Skarletto, Skrauz, Skyedra, SlamBamActionman, slarticodefast, Slava0135, Slyfox333, snebl, snicket, sniperchance, Snowni, snowsignal, SolidusSnek, SonicHDC, SoulFN, SoulSloth, Soundwavesghost, southbridge-fur, Soydium, spacelizard, SpaceLizardSky, SpaceManiac, SpaceRox1244, SpaceyLady, Spanky, spanky-spanky, spartak, SpartanKadence, SpeltIncorrectyl, Spessmann, SphiraI, SplinterGP, spoogemonster, sporekto, sporkyz, ssdaniel24, stalengd, stanberytrask, Stanislav4ix, StanTheCarpenter, Stealthbomber16, stellar-novas, stomf, stopbreaking, stopka-html, StrawberryMoses, Stray-Pyramid, strO0pwafel, Strol20, StStevens, Subversionary, sunbear-dev, superjj18, Supernorn, SweptWasTaken, Sybil, SYNCHRONIC, Szunti, Tainakov, takemysoult, TaralGit, Taran, taurie, Tayrtahn, tday93, teamaki, TekuNut, telyonok, TemporalOroboros, tentekal, terezi4real, Terraspark4941, texcruize, TGODiamond, TGRCdev, tgrkzus, ThatOneGoblin25, thatrandomcanadianguy, TheArturZh, theashtronaut, thecopbennet, TheCze, TheDarkElites, thedraccx, TheEmber, TheIntoxicatedCat, thekilk, themias, theomund, theOperand, TherapyGoth, TheShuEd, thetolbean, thevinter, TheWaffleJesus, Thinbug0, ThunderBear2006, timothyteakettle, TimrodDX, timurjavid, tin-man-tim, Titian3, tk-a369, tkdrg, tmtmtl30, TokenStyle, Tollhouse, Toly65, tom-leys, tomasalves8, Tomeno, Tonydatguy, topy, Tornado-Technology, tosatur, TotallyLemon, Tr1bute, tropicalhibi, truepaintgit, Truoizys, Tryded, TsjipTsjip, Tunguso4ka, TurboTrackerss14, TyAshley, Tyler-IN, Tyzemol, UbaserB, ubis1, UBlueberry, UKNOWH, UltimateJester, Unbelievable-Salmon, underscorex5, UnicornOnLSD, Unisol, Unkn0wnGh0st333, unusualcrow, Uriende, UristMcDorf, user424242420, Vaaankas, valentfingerov, Varen, VasilisThePikachu, veliebm, VelonacepsCalyxEggs, veprolet, veritable-calamity, Veritius, Vermidia, vero5123, Verslebas, VigersRay, violet754, Visne, VMSolidus, voidnull000, volotomite, volundr-, Voomra, Vordenburg, vorkathbruh, vulppine, wafehling, Warentan, WarMechanic, Watermelon914, waylon531, weaversam8, wertanchik, whateverusername0, Willhelm53, WilliamECrew, willicassi, Winkarst-cpu, wirdal, wixoaGit, WlarusFromDaSpace, wrexbe, WTCWR68, xkreksx, xprospero, xRiriq, YanehCheck, yathxyz, Ygg01, YotaXP, youarereadingthis, Yousifb26, youtissoum, YuriyKiss, zach-hill, Zadeon, zamp, Zandario, Zap527, Zealith-Gamer, ZelteHonor, zero, ZeroDiamond, zerorulez, ZeWaka, zionnBE, ZNixian, ZoldorfTheWizard, Zonespace27, Zylofan, Zymem, zzylex From d939e991bba188b6a37e11f402537a93363b278e Mon Sep 17 00:00:00 2001 From: Armok <155400926+ARMOKS@users.noreply.github.com> Date: Sat, 9 Nov 2024 20:32:54 -0700 Subject: [PATCH 056/290] Removed bola stam damage (#32989) --- .../Prototypes/Entities/Objects/Weapons/Throwable/bola.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Throwable/bola.yml b/Resources/Prototypes/Entities/Objects/Weapons/Throwable/bola.yml index a4441b18f7f7..f8d5efb8c68e 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Throwable/bola.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Throwable/bola.yml @@ -42,9 +42,9 @@ - type: Ensnaring freeTime: 2.0 breakoutTime: 3.5 #all bola should generally be fast to remove - walkSpeed: 0.7 #makeshift bola shouldn't slow too much - sprintSpeed: 0.7 - staminaDamage: 55 # Sudden weight increase sapping stamina + walkSpeed: 0.5 #makeshift bola shouldn't slow too much + sprintSpeed: 0.5 + staminaDamage: 0 # anything but this is gamebreaking canThrowTrigger: true canMoveBreakout: true - type: LandAtCursor From 33b780fd1fb853220ddda96fdd19339c30477016 Mon Sep 17 00:00:00 2001 From: IProduceWidgets <107586145+IProduceWidgets@users.noreply.github.com> Date: Sat, 9 Nov 2024 23:26:51 -0500 Subject: [PATCH 057/290] tweak: weather command tooltip (#33130) clear weather tip --- Content.Server/Weather/WeatherSystem.cs | 4 +++- Resources/Locale/en-US/weather/weather.ftl | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/Content.Server/Weather/WeatherSystem.cs b/Content.Server/Weather/WeatherSystem.cs index dbee62a72fc2..ec377809133d 100644 --- a/Content.Server/Weather/WeatherSystem.cs +++ b/Content.Server/Weather/WeatherSystem.cs @@ -4,6 +4,7 @@ using Robust.Shared.Console; using Robust.Shared.GameStates; using Robust.Shared.Map; +using System.Linq; namespace Content.Server.Weather; @@ -85,6 +86,7 @@ private CompletionResult WeatherCompletion(IConsoleShell shell, string[] args) return CompletionResult.FromHintOptions(CompletionHelper.MapIds(EntityManager), "Map Id"); var a = CompletionHelper.PrototypeIDs(true, ProtoMan); - return CompletionResult.FromHintOptions(a, Loc.GetString("cmd-weather-hint")); + var b = a.Concat(new[] { new CompletionOption("null", Loc.GetString("cmd-weather-null")) }); + return CompletionResult.FromHintOptions(b, Loc.GetString("cmd-weather-hint")); } } diff --git a/Resources/Locale/en-US/weather/weather.ftl b/Resources/Locale/en-US/weather/weather.ftl index 67e6eec35f2c..0c67b6f66bf4 100644 --- a/Resources/Locale/en-US/weather/weather.ftl +++ b/Resources/Locale/en-US/weather/weather.ftl @@ -1,6 +1,7 @@ cmd-weather-desc = Sets the weather for the current map. cmd-weather-help = weather cmd-weather-hint = Weather prototype +cmd-weather-null = Clears the weather cmd-weather-error-no-arguments = Not enough arguments! cmd-weather-error-unknown-proto = Unknown Weather prototype! From 9396ce302aed7b1cfbe9995c9214ed8ee7cd49fc Mon Sep 17 00:00:00 2001 From: PJBot Date: Sun, 10 Nov 2024 04:27:57 +0000 Subject: [PATCH 058/290] Automatic changelog update --- Resources/Changelog/Changelog.yml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index a1a17548d489..9b8052d835a5 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,12 +1,4 @@ Entries: -- author: TheShuEd - changes: - - message: change the way food is sliced - food is now sliced whole after a small - doafter than requires multiple clicks on a single entity - type: Tweak - id: 7101 - time: '2024-08-13T10:54:00.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/30824 - author: Ubaser changes: - message: Add two gatfruit mutations, one fake and one real capfruit which spawns @@ -3952,3 +3944,10 @@ id: 7600 time: '2024-11-09T19:29:29.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33198 +- author: IProduceWidgets + changes: + - message: weather now has a completion result for how to unset the weather. + type: Tweak + id: 7601 + time: '2024-11-10T04:26:51.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33130 From 2801ebea8d11548511744556622ebfcfe389931d Mon Sep 17 00:00:00 2001 From: Preston Smith Date: Sun, 10 Nov 2024 00:45:54 -0600 Subject: [PATCH 059/290] Optimization! --- Content.Shared/Damage/Systems/DamageExamineSystem.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Content.Shared/Damage/Systems/DamageExamineSystem.cs b/Content.Shared/Damage/Systems/DamageExamineSystem.cs index 72c1af29b22d..fe97a40d1b54 100644 --- a/Content.Shared/Damage/Systems/DamageExamineSystem.cs +++ b/Content.Shared/Damage/Systems/DamageExamineSystem.cs @@ -61,15 +61,12 @@ private FormattedMessage GetDamageExamine(DamageSpecifier damageSpecifier, strin } else { - if (damageSpecifier.DamageDict.Count == 1) + if (damageSpecifier.GetTotal() == FixedPoint2.Zero && !damageSpecifier.AnyPositive()) { - // May be simplified to using a foreach(Var x) despite being only one item - if(damageSpecifier.DamageDict.Values.GetEnumerator().Current == FixedPoint2.Zero) - { - msg.AddMarkupOrThrow(Loc.GetString("damage-none")); - return msg; - } + msg.AddMarkupOrThrow(Loc.GetString("damage-none")); + return msg; } + msg.AddMarkupOrThrow(Loc.GetString("damage-examine-type", ("type", type))); } From 1c8992ffbe1dc596ef377e52c3ec13d8d5ab4d5c Mon Sep 17 00:00:00 2001 From: Shaddap1 <106589956+Shaddap1@users.noreply.github.com> Date: Sun, 10 Nov 2024 06:28:55 -0500 Subject: [PATCH 060/290] Goliath rebalance (#31492) Update asteroid.yml --- Resources/Prototypes/Entities/Mobs/NPCs/asteroid.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/asteroid.yml b/Resources/Prototypes/Entities/Mobs/NPCs/asteroid.yml index 877dd40cc389..270e20e5c520 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/asteroid.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/asteroid.yml @@ -50,12 +50,12 @@ Dead: Base: goliath_dead - type: MovementSpeedModifier - baseWalkSpeed : 2.50 - baseSprintSpeed : 2.50 + baseWalkSpeed : 2.00 + baseSprintSpeed : 2.00 - type: MobThresholds thresholds: 0: Alive - 300: Dead + 250: Dead - type: MeleeWeapon soundHit: path: "/Audio/Weapons/smash.ogg" @@ -64,7 +64,7 @@ animation: WeaponArcPunch damage: types: - Slash: 15 + Slash: 10 Piercing: 10 - type: NpcFactionMember factions: From 9b7200607b28e0c8118e70554dc7cb586b6d63a1 Mon Sep 17 00:00:00 2001 From: scrivoy <179060466+scrivoy@users.noreply.github.com> Date: Sun, 10 Nov 2024 12:40:02 +0100 Subject: [PATCH 061/290] Omega Station: Fix Air Alarm in CMO office (#33216) move air alarm and link devices --- Resources/Maps/omega.yml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/Resources/Maps/omega.yml b/Resources/Maps/omega.yml index 7709234a6a15..31e3fc7392a3 100644 --- a/Resources/Maps/omega.yml +++ b/Resources/Maps/omega.yml @@ -4648,9 +4648,13 @@ entities: - uid: 6692 components: - type: Transform - rot: -1.5707963267948966 rad - pos: -23.5,-26.5 + rot: 3.141592653589793 rad + pos: -25.5,-29.5 parent: 4812 + - type: DeviceList + devices: + - 6253 + - 5033 - uid: 7234 components: - type: Transform @@ -54547,6 +54551,9 @@ entities: rot: 3.141592653589793 rad pos: -24.5,-27.5 parent: 4812 + - type: DeviceNetwork + deviceLists: + - 6692 - type: AtmosPipeColor color: '#0055CCFF' - uid: 5222 @@ -55489,6 +55496,9 @@ entities: rot: 3.141592653589793 rad pos: -26.5,-26.5 parent: 4812 + - type: DeviceNetwork + deviceLists: + - 6692 - type: AtmosPipeColor color: '#990000FF' - uid: 6417 From 21979a7b5f4e1a2976440f2fdf1d7c150318931a Mon Sep 17 00:00:00 2001 From: leonidussaks <42278348+leonidussaks@users.noreply.github.com> Date: Mon, 11 Nov 2024 06:17:03 +0300 Subject: [PATCH 062/290] Fix vape use without check if doafter cancelled (#33245) vape small fix --- Content.Server/Nutrition/EntitySystems/SmokingSystem.Vape.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Content.Server/Nutrition/EntitySystems/SmokingSystem.Vape.cs b/Content.Server/Nutrition/EntitySystems/SmokingSystem.Vape.cs index c3d41cead6d6..26fa5ca3cc8f 100644 --- a/Content.Server/Nutrition/EntitySystems/SmokingSystem.Vape.cs +++ b/Content.Server/Nutrition/EntitySystems/SmokingSystem.Vape.cs @@ -122,8 +122,7 @@ private void OnVapeInteraction(Entity entity, ref AfterInteractEv private void OnVapeDoAfter(Entity entity, ref VapeDoAfterEvent args) { - if (args.Handled - || args.Args.Target == null) + if (args.Cancelled || args.Handled || args.Args.Target == null) return; var environment = _atmos.GetContainingMixture(args.Args.Target.Value, true, true); From 197d9e68dcc3419ce45844ad64b95fecff680271 Mon Sep 17 00:00:00 2001 From: BramvanZijp <56019239+BramvanZijp@users.noreply.github.com> Date: Mon, 11 Nov 2024 04:22:03 +0100 Subject: [PATCH 063/290] HOTFIX: Fix Security Shell Gun being uncraftable. (#33247) * Sec Shell Gun Craftability Hotfix * Capital Fix --- Resources/Prototypes/Entities/Structures/Machines/lathe.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index b27f2cc1b982..020566ad1a73 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -768,6 +768,7 @@ - TargetHuman - TargetSyndicate - WeaponDisablerPractice + - WeaponFlareGunSecurity - WeaponLaserCarbinePractice - Zipties dynamicRecipes: From a138fede2bda4dcc3901898a5e3cacc415a68c86 Mon Sep 17 00:00:00 2001 From: BramvanZijp <56019239+BramvanZijp@users.noreply.github.com> Date: Mon, 11 Nov 2024 17:12:36 +0100 Subject: [PATCH 064/290] Make the Flare Gun & Security Shell Gun be unbolted by default. (#33248) --- .../Prototypes/Entities/Objects/Weapons/Guns/flare_gun.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/flare_gun.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/flare_gun.yml index b63036c58b2f..224697bc93fe 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/flare_gun.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/flare_gun.yml @@ -27,7 +27,7 @@ gun_chamber: !type:ContainerSlot - type: ChamberMagazineAmmoProvider autoCycle: false - boltClosed: true + boltClosed: false canRack: false soundBoltClosed: /Audio/Weapons/Guns/Cock/revolver_cock.ogg soundBoltOpened: /Audio/Weapons/Guns/Cock/revolver_cock.ogg From b9c2b0c41b16fe46dbd5cb056e1d5a1b0f8d251f Mon Sep 17 00:00:00 2001 From: PJBot Date: Mon, 11 Nov 2024 16:13:45 +0000 Subject: [PATCH 065/290] Automatic changelog update --- Resources/Changelog/Changelog.yml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 9b8052d835a5..6abb7cc6a5e2 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,12 +1,4 @@ Entries: -- author: Ubaser - changes: - - message: Add two gatfruit mutations, one fake and one real capfruit which spawns - cap guns when eaten. - type: Add - id: 7102 - time: '2024-08-13T11:08:40.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/30850 - author: slarticodefast changes: - message: Added new keybindings for rotating and flipping objects. The defaults @@ -3951,3 +3943,10 @@ id: 7601 time: '2024-11-10T04:26:51.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33130 +- author: BramvanZijp + changes: + - message: The Flare Gun & Security Shell Gun now start in their open/unbolted state. + type: Tweak + id: 7602 + time: '2024-11-11T16:12:36.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33248 From 1136200dc838a5fd0a5a347025b703b968cdabec Mon Sep 17 00:00:00 2001 From: Andrew Montagne Date: Mon, 11 Nov 2024 22:58:31 +0000 Subject: [PATCH 066/290] BUGFIX: Fix APEs being able to be turned on without power (#32493) Add a check to see the APC is powered before turning the emitter on. --- Content.Server/Singularity/EntitySystems/EmitterSystem.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Content.Server/Singularity/EntitySystems/EmitterSystem.cs b/Content.Server/Singularity/EntitySystems/EmitterSystem.cs index 1ada60e1d645..f828139ed6fe 100644 --- a/Content.Server/Singularity/EntitySystems/EmitterSystem.cs +++ b/Content.Server/Singularity/EntitySystems/EmitterSystem.cs @@ -196,7 +196,8 @@ public void SwitchOn(EntityUid uid, EmitterComponent component) if (TryComp(uid, out var apcReceiver)) { apcReceiver.Load = component.PowerUseActive; - PowerOn(uid, component); + if (apcReceiver.Powered) + PowerOn(uid, component); } // Do not directly PowerOn(). // OnReceivedPowerChanged will get fired due to DrawRate change which will turn it on. From 37958378cbec572b0de11676c6962983ff2c58d5 Mon Sep 17 00:00:00 2001 From: PJBot Date: Mon, 11 Nov 2024 22:59:38 +0000 Subject: [PATCH 067/290] Automatic changelog update --- Resources/Changelog/Changelog.yml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 6abb7cc6a5e2..43c7cad22c67 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,12 +1,4 @@ Entries: -- author: slarticodefast - changes: - - message: Added new keybindings for rotating and flipping objects. The defaults - are R for clockwise, Shift+R for counterclockwise and F for flipping. - type: Add - id: 7103 - time: '2024-08-13T13:36:45.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/30540 - author: Cojoke-dot changes: - message: Borg's names are now displayed when they make an announcement on the @@ -3950,3 +3942,10 @@ id: 7602 time: '2024-11-11T16:12:36.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33248 +- author: AndrewMontagne + changes: + - message: APEs could be powered on without local power + type: Fix + id: 7603 + time: '2024-11-11T22:58:31.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/32493 From 36aceb178c855b381cb9b5868e4348fde1bedbd0 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Tue, 29 Oct 2024 01:34:40 +0100 Subject: [PATCH 068/290] Database SnakeCaseNaming fixes Fixes formatting of owned entity type property names. These are normally named "FooBar_Baz" by EF Core, but the snake case thing was turning them into "foo_bar__baz". The double underscore is now fixed. We don't *yet* have any EF Core owned entity in use, but I am planning to add one. I don't know if downstreams are using any so this should still be marked as a breaking change. Also fixed it creating and dropping a Compiled Regex instance for every name, the regex is now cached (and pregenerated). --- Content.Server.Database/SnakeCaseNaming.cs | 40 +++++++++++++--------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/Content.Server.Database/SnakeCaseNaming.cs b/Content.Server.Database/SnakeCaseNaming.cs index 27ce392cd50e..3a67ffb9cd1b 100644 --- a/Content.Server.Database/SnakeCaseNaming.cs +++ b/Content.Server.Database/SnakeCaseNaming.cs @@ -82,7 +82,7 @@ public ConventionSet ModifyConventions(ConventionSet conventionSet) } } - public class SnakeCaseConvention : + public partial class SnakeCaseConvention : IEntityTypeAddedConvention, IEntityTypeAnnotationChangedConvention, IPropertyAddedConvention, @@ -99,22 +99,27 @@ public SnakeCaseConvention() {} public static string RewriteName(string name) { - var regex = new Regex("[A-Z]+", RegexOptions.Compiled); - return regex.Replace( - name, - (Match match) => { - if (match.Index == 0 && (match.Value == "FK" || match.Value == "PK" || match.Value == "IX")) { - return match.Value; + return UpperCaseLocator() + .Replace( + name, + (Match match) => { + if (match.Index == 0 && (match.Value == "FK" || match.Value == "PK" || match.Value == "IX")) { + return match.Value; + } + if (match.Value == "HWI") + return (match.Index == 0 ? "" : "_") + "hwi"; + if (match.Index == 0) + return match.Value.ToLower(); + if (match.Length > 1) + return $"_{match.Value[..^1].ToLower()}_{match.Value[^1..^0].ToLower()}"; + + // Do not add a _ if there is already one before this. This happens with owned entities. + if (name[match.Index - 1] == '_') + return match.Value.ToLower(); + + return "_" + match.Value.ToLower(); } - if (match.Value == "HWI") - return (match.Index == 0 ? "" : "_") + "hwi"; - if (match.Index == 0) - return match.Value.ToLower(); - if (match.Length > 1) - return $"_{match.Value[..^1].ToLower()}_{match.Value[^1..^0].ToLower()}"; - return "_" + match.Value.ToLower(); - } - ); + ); } public virtual void ProcessEntityTypeAdded( @@ -332,5 +337,8 @@ private static void RewriteColumnName(IConventionPropertyBuilder propertyBuilder } } } + + [GeneratedRegex("[A-Z]+", RegexOptions.Compiled)] + private static partial Regex UpperCaseLocator(); } } From 4f3db43696fbcc9144d2ad011bbb5f93f6deca7a Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Tue, 12 Nov 2024 01:51:23 +0100 Subject: [PATCH 069/290] Integrate Modern HWID into content This should be the primary changes for the future-proof "Modern HWID" system implemented into Robust and the auth server. HWIDs in the database have been given an additional column representing their version, legacy or modern. This is implemented via an EF Core owned entity. By manually setting the column name of the main value column, we can keep DB compatibility and the migration is just adding some type columns. This new HWID type has to be plumbed through everywhere, resulting in some breaking changes for the DB layer and such. New bans and player records are placed with the new modern HWID. Old bans are still checked against legacy HWIDs. Modern HWIDs are presented with a "V2-" prefix to admins, to allow distinguishing them. This is also integrated into the parsing logic for placing new bans. There's also some code cleanup to reduce copy pasting around the place from my changes. Requires latest engine to support ImmutableArray in NetSerializer. --- .../UI/BanPanel/BanPanel.xaml.cs | 11 +- .../Tests/Commands/PardonCommand.cs | 24 +- .../20241111170112_ModernHwid.Designer.cs | 2072 ++++++++++++++++ .../Postgres/20241111170112_ModernHwid.cs | 62 + ...20241111193608_ConnectionTrust.Designer.cs | 2076 +++++++++++++++++ .../20241111193608_ConnectionTrust.cs | 29 + .../PostgresServerDbContextModelSnapshot.cs | 162 +- .../20241111170107_ModernHwid.Designer.cs | 1995 ++++++++++++++++ .../Sqlite/20241111170107_ModernHwid.cs | 62 + ...20241111193602_ConnectionTrust.Designer.cs | 1999 ++++++++++++++++ .../Sqlite/20241111193602_ConnectionTrust.cs | 29 + .../SqliteServerDbContextModelSnapshot.cs | 161 +- Content.Server.Database/Model.cs | 88 +- .../Administration/BanList/BanListEui.cs | 8 +- Content.Server/Administration/BanPanelEui.cs | 10 +- .../Administration/Commands/BanListCommand.cs | 2 +- .../Commands/RoleBanListCommand.cs | 2 +- .../Administration/Managers/BanManager.cs | 12 +- .../Administration/Managers/IBanManager.cs | 4 +- .../Administration/PlayerLocator.cs | 99 +- .../Administration/PlayerPanelEui.cs | 4 +- .../Administration/Systems/BwoinkSystem.cs | 2 +- .../Connection/ConnectionManager.cs | 13 +- Content.Server/Connection/UserDataExt.cs | 24 + Content.Server/Database/BanMatcher.cs | 33 +- Content.Server/Database/DatabaseRecords.cs | 3 +- Content.Server/Database/ServerBanDef.cs | 5 +- Content.Server/Database/ServerDbBase.cs | 24 +- Content.Server/Database/ServerDbManager.cs | 35 +- Content.Server/Database/ServerDbPostgres.cs | 124 +- Content.Server/Database/ServerDbSqlite.cs | 55 +- Content.Server/Database/ServerRoleBanDef.cs | 5 +- Content.Shared.Database/TypedHwid.cs | 62 + .../Administration/BanPanelEuiState.cs | 4 +- 34 files changed, 9059 insertions(+), 241 deletions(-) create mode 100644 Content.Server.Database/Migrations/Postgres/20241111170112_ModernHwid.Designer.cs create mode 100644 Content.Server.Database/Migrations/Postgres/20241111170112_ModernHwid.cs create mode 100644 Content.Server.Database/Migrations/Postgres/20241111193608_ConnectionTrust.Designer.cs create mode 100644 Content.Server.Database/Migrations/Postgres/20241111193608_ConnectionTrust.cs create mode 100644 Content.Server.Database/Migrations/Sqlite/20241111170107_ModernHwid.Designer.cs create mode 100644 Content.Server.Database/Migrations/Sqlite/20241111170107_ModernHwid.cs create mode 100644 Content.Server.Database/Migrations/Sqlite/20241111193602_ConnectionTrust.Designer.cs create mode 100644 Content.Server.Database/Migrations/Sqlite/20241111193602_ConnectionTrust.cs create mode 100644 Content.Server/Connection/UserDataExt.cs create mode 100644 Content.Shared.Database/TypedHwid.cs diff --git a/Content.Client/Administration/UI/BanPanel/BanPanel.xaml.cs b/Content.Client/Administration/UI/BanPanel/BanPanel.xaml.cs index 588d62e56036..3c7322d47397 100644 --- a/Content.Client/Administration/UI/BanPanel/BanPanel.xaml.cs +++ b/Content.Client/Administration/UI/BanPanel/BanPanel.xaml.cs @@ -22,11 +22,11 @@ namespace Content.Client.Administration.UI.BanPanel; [GenerateTypedNameReferences] public sealed partial class BanPanel : DefaultWindow { - public event Action? BanSubmitted; + public event Action? BanSubmitted; public event Action? PlayerChanged; private string? PlayerUsername { get; set; } private (IPAddress, int)? IpAddress { get; set; } - private byte[]? Hwid { get; set; } + private ImmutableTypedHwid? Hwid { get; set; } private double TimeEntered { get; set; } private uint Multiplier { get; set; } private bool HasBanFlag { get; set; } @@ -371,9 +371,8 @@ private void OnIpChanged() private void OnHwidChanged() { var hwidString = HwidLine.Text; - var length = 3 * (hwidString.Length / 4) - hwidString.TakeLast(2).Count(c => c == '='); - Hwid = new byte[length]; - if (HwidCheckbox.Pressed && !(string.IsNullOrEmpty(hwidString) && LastConnCheckbox.Pressed) && !Convert.TryFromBase64String(hwidString, Hwid, out _)) + ImmutableTypedHwid? hwid = null; + if (HwidCheckbox.Pressed && !(string.IsNullOrEmpty(hwidString) && LastConnCheckbox.Pressed) && !ImmutableTypedHwid.TryParse(hwidString, out hwid)) { ErrorLevel |= ErrorLevelEnum.Hwid; HwidLine.ModulateSelfOverride = Color.Red; @@ -390,7 +389,7 @@ private void OnHwidChanged() Hwid = null; return; } - Hwid = Convert.FromHexString(hwidString); + Hwid = hwid; } private void OnTypeChanged() diff --git a/Content.IntegrationTests/Tests/Commands/PardonCommand.cs b/Content.IntegrationTests/Tests/Commands/PardonCommand.cs index 4db9eabf5c6b..9e57cd4b0e6f 100644 --- a/Content.IntegrationTests/Tests/Commands/PardonCommand.cs +++ b/Content.IntegrationTests/Tests/Commands/PardonCommand.cs @@ -32,9 +32,9 @@ public async Task PardonTest() // No bans on record Assert.Multiple(async () => { - Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null), Is.Null); + Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null, null), Is.Null); Assert.That(await sDatabase.GetServerBanAsync(1), Is.Null); - Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null), Is.Empty); + Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null, null), Is.Empty); }); // Try to pardon a ban that does not exist @@ -43,9 +43,9 @@ public async Task PardonTest() // Still no bans on record Assert.Multiple(async () => { - Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null), Is.Null); + Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null, null), Is.Null); Assert.That(await sDatabase.GetServerBanAsync(1), Is.Null); - Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null), Is.Empty); + Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null, null), Is.Empty); }); var banReason = "test"; @@ -57,9 +57,9 @@ public async Task PardonTest() // Should have one ban on record now Assert.Multiple(async () => { - Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null), Is.Not.Null); + Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null, null), Is.Not.Null); Assert.That(await sDatabase.GetServerBanAsync(1), Is.Not.Null); - Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null), Has.Count.EqualTo(1)); + Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null, null), Has.Count.EqualTo(1)); }); await pair.RunTicksSync(5); @@ -70,13 +70,13 @@ public async Task PardonTest() await server.WaitPost(() => sConsole.ExecuteCommand("pardon 2")); // The existing ban is unaffected - Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null), Is.Not.Null); + Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null, null), Is.Not.Null); var ban = await sDatabase.GetServerBanAsync(1); Assert.Multiple(async () => { Assert.That(ban, Is.Not.Null); - Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null), Has.Count.EqualTo(1)); + Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null, null), Has.Count.EqualTo(1)); // Check that it matches Assert.That(ban.Id, Is.EqualTo(1)); @@ -95,7 +95,7 @@ public async Task PardonTest() await server.WaitPost(() => sConsole.ExecuteCommand("pardon 1")); // No bans should be returned - Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null), Is.Null); + Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null, null), Is.Null); // Direct id lookup returns a pardoned ban var pardonedBan = await sDatabase.GetServerBanAsync(1); @@ -105,7 +105,7 @@ public async Task PardonTest() Assert.That(pardonedBan, Is.Not.Null); // The list is still returned since that ignores pardons - Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null), Has.Count.EqualTo(1)); + Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null, null), Has.Count.EqualTo(1)); Assert.That(pardonedBan.Id, Is.EqualTo(1)); Assert.That(pardonedBan.UserId, Is.EqualTo(clientId)); @@ -133,13 +133,13 @@ public async Task PardonTest() Assert.Multiple(async () => { // No bans should be returned - Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null), Is.Null); + Assert.That(await sDatabase.GetServerBanAsync(null, clientId, null, null), Is.Null); // Direct id lookup returns a pardoned ban Assert.That(await sDatabase.GetServerBanAsync(1), Is.Not.Null); // The list is still returned since that ignores pardons - Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null), Has.Count.EqualTo(1)); + Assert.That(await sDatabase.GetServerBansAsync(null, clientId, null, null), Has.Count.EqualTo(1)); }); // Reconnect client. Slightly faster than dirtying the pair. diff --git a/Content.Server.Database/Migrations/Postgres/20241111170112_ModernHwid.Designer.cs b/Content.Server.Database/Migrations/Postgres/20241111170112_ModernHwid.Designer.cs new file mode 100644 index 000000000000..155d6a163fd8 --- /dev/null +++ b/Content.Server.Database/Migrations/Postgres/20241111170112_ModernHwid.Designer.cs @@ -0,0 +1,2072 @@ +// +using System; +using System.Net; +using System.Text.Json; +using Content.Server.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using NpgsqlTypes; + +#nullable disable + +namespace Content.Server.Database.Migrations.Postgres +{ + [DbContext(typeof(PostgresServerDbContext))] + [Migration("20241111170112_ModernHwid")] + partial class ModernHwid + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("AdminRankId") + .HasColumnType("integer") + .HasColumnName("admin_rank_id"); + + b.Property("Title") + .HasColumnType("text") + .HasColumnName("title"); + + b.HasKey("UserId") + .HasName("PK_admin"); + + b.HasIndex("AdminRankId") + .HasDatabaseName("IX_admin_admin_rank_id"); + + b.ToTable("admin", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_flag_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AdminId") + .HasColumnType("uuid") + .HasColumnName("admin_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("text") + .HasColumnName("flag"); + + b.Property("Negative") + .HasColumnType("boolean") + .HasColumnName("negative"); + + b.HasKey("Id") + .HasName("PK_admin_flag"); + + b.HasIndex("AdminId") + .HasDatabaseName("IX_admin_flag_admin_id"); + + b.HasIndex("Flag", "AdminId") + .IsUnique(); + + b.ToTable("admin_flag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("admin_log_id"); + + b.Property("Date") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property("Impact") + .HasColumnType("smallint") + .HasColumnName("impact"); + + b.Property("Json") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("json"); + + b.Property("Message") + .IsRequired() + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("RoundId", "Id") + .HasName("PK_admin_log"); + + b.HasIndex("Date"); + + b.HasIndex("Message") + .HasAnnotation("Npgsql:TsVectorConfig", "english"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Message"), "GIN"); + + b.HasIndex("Type") + .HasDatabaseName("IX_admin_log_type"); + + b.ToTable("admin_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("LogId") + .HasColumnType("integer") + .HasColumnName("log_id"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.HasKey("RoundId", "LogId", "PlayerUserId") + .HasName("PK_admin_log_player"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_log_player_player_user_id"); + + b.ToTable("admin_log_player", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_messages_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("uuid") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("boolean") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("uuid") + .HasColumnName("deleted_by_id"); + + b.Property("Dismissed") + .HasColumnType("boolean") + .HasColumnName("dismissed"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Seen") + .HasColumnType("boolean") + .HasColumnName("seen"); + + b.HasKey("Id") + .HasName("PK_admin_messages"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_messages_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_messages_round_id"); + + b.ToTable("admin_messages", null, t => + { + t.HasCheckConstraint("NotDismissedAndSeen", "NOT dismissed OR seen"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.AdminNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_notes_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("uuid") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("boolean") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("uuid") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Secret") + .HasColumnType("boolean") + .HasColumnName("secret"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_admin_notes"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_notes_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_notes_round_id"); + + b.ToTable("admin_notes", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_rank_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_admin_rank"); + + b.ToTable("admin_rank", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_rank_flag_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AdminRankId") + .HasColumnType("integer") + .HasColumnName("admin_rank_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("text") + .HasColumnName("flag"); + + b.HasKey("Id") + .HasName("PK_admin_rank_flag"); + + b.HasIndex("AdminRankId"); + + b.HasIndex("Flag", "AdminRankId") + .IsUnique(); + + b.ToTable("admin_rank_flag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_watchlists_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("uuid") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("boolean") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("uuid") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.HasKey("Id") + .HasName("PK_admin_watchlists"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_watchlists_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_watchlists_round_id"); + + b.ToTable("admin_watchlists", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("antag_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AntagName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("antag_name"); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_antag"); + + b.HasIndex("ProfileId", "AntagName") + .IsUnique(); + + b.ToTable("antag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AssignedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("assigned_user_id_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("PK_assigned_user_id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("UserName") + .IsUnique(); + + b.ToTable("assigned_user_id", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.BanTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("ban_template_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AutoDelete") + .HasColumnType("boolean") + .HasColumnName("auto_delete"); + + b.Property("ExemptFlags") + .HasColumnType("integer") + .HasColumnName("exempt_flags"); + + b.Property("Hidden") + .HasColumnType("boolean") + .HasColumnName("hidden"); + + b.Property("Length") + .HasColumnType("interval") + .HasColumnName("length"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text") + .HasColumnName("title"); + + b.HasKey("Id") + .HasName("PK_ban_template"); + + b.ToTable("ban_template", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Blacklist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_blacklist"); + + b.ToTable("blacklist", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("connection_log_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Address") + .IsRequired() + .HasColumnType("inet") + .HasColumnName("address"); + + b.Property("Denied") + .HasColumnType("smallint") + .HasColumnName("denied"); + + b.Property("ServerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("server_id"); + + b.Property("Time") + .HasColumnType("timestamp with time zone") + .HasColumnName("time"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("PK_connection_log"); + + b.HasIndex("ServerId") + .HasDatabaseName("IX_connection_log_server_id"); + + b.HasIndex("Time"); + + b.HasIndex("UserId"); + + b.ToTable("connection_log", null, t => + { + t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("job_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("JobName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("job_name"); + + b.Property("Priority") + .HasColumnType("integer") + .HasColumnName("priority"); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_job"); + + b.HasIndex("ProfileId"); + + b.HasIndex("ProfileId", "JobName") + .IsUnique(); + + b.HasIndex(new[] { "ProfileId" }, "IX_job_one_high_priority") + .IsUnique() + .HasFilter("priority = 3"); + + b.ToTable("job", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.PlayTime", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("play_time_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("PlayerId") + .HasColumnType("uuid") + .HasColumnName("player_id"); + + b.Property("TimeSpent") + .HasColumnType("interval") + .HasColumnName("time_spent"); + + b.Property("Tracker") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tracker"); + + b.HasKey("Id") + .HasName("PK_play_time"); + + b.HasIndex("PlayerId", "Tracker") + .IsUnique(); + + b.ToTable("play_time", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("player_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("FirstSeenTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("first_seen_time"); + + b.Property("LastReadRules") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_read_rules"); + + b.Property("LastSeenAddress") + .IsRequired() + .HasColumnType("inet") + .HasColumnName("last_seen_address"); + + b.Property("LastSeenTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_seen_time"); + + b.Property("LastSeenUserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("last_seen_user_name"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_player"); + + b.HasAlternateKey("UserId") + .HasName("ak_player_user_id"); + + b.HasIndex("LastSeenUserName"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("player", null, t => + { + t.HasCheckConstraint("LastSeenAddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= last_seen_address"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("preference_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AdminOOCColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("admin_ooc_color"); + + b.Property("SelectedCharacterSlot") + .HasColumnType("integer") + .HasColumnName("selected_character_slot"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_preference"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("preference", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("profile_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Age") + .HasColumnType("integer") + .HasColumnName("age"); + + b.Property("CharacterName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("char_name"); + + b.Property("EyeColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("eye_color"); + + b.Property("FacialHairColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("facial_hair_color"); + + b.Property("FacialHairName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("facial_hair_name"); + + b.Property("FlavorText") + .IsRequired() + .HasColumnType("text") + .HasColumnName("flavor_text"); + + b.Property("Gender") + .IsRequired() + .HasColumnType("text") + .HasColumnName("gender"); + + b.Property("HairColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("hair_color"); + + b.Property("HairName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("hair_name"); + + b.Property("Markings") + .HasColumnType("jsonb") + .HasColumnName("markings"); + + b.Property("PreferenceId") + .HasColumnType("integer") + .HasColumnName("preference_id"); + + b.Property("PreferenceUnavailable") + .HasColumnType("integer") + .HasColumnName("pref_unavailable"); + + b.Property("Sex") + .IsRequired() + .HasColumnType("text") + .HasColumnName("sex"); + + b.Property("SkinColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("skin_color"); + + b.Property("Slot") + .HasColumnType("integer") + .HasColumnName("slot"); + + b.Property("SpawnPriority") + .HasColumnType("integer") + .HasColumnName("spawn_priority"); + + b.Property("Species") + .IsRequired() + .HasColumnType("text") + .HasColumnName("species"); + + b.HasKey("Id") + .HasName("PK_profile"); + + b.HasIndex("PreferenceId") + .HasDatabaseName("IX_profile_preference_id"); + + b.HasIndex("Slot", "PreferenceId") + .IsUnique(); + + b.ToTable("profile", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("profile_loadout_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("LoadoutName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("loadout_name"); + + b.Property("ProfileLoadoutGroupId") + .HasColumnType("integer") + .HasColumnName("profile_loadout_group_id"); + + b.HasKey("Id") + .HasName("PK_profile_loadout"); + + b.HasIndex("ProfileLoadoutGroupId"); + + b.ToTable("profile_loadout", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("profile_loadout_group_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("GroupName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("group_name"); + + b.Property("ProfileRoleLoadoutId") + .HasColumnType("integer") + .HasColumnName("profile_role_loadout_id"); + + b.HasKey("Id") + .HasName("PK_profile_loadout_group"); + + b.HasIndex("ProfileRoleLoadoutId"); + + b.ToTable("profile_loadout_group", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("profile_role_loadout_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.Property("RoleName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("role_name"); + + b.HasKey("Id") + .HasName("PK_profile_role_loadout"); + + b.HasIndex("ProfileId"); + + b.ToTable("profile_role_loadout", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b => + { + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("RoleId") + .HasColumnType("text") + .HasColumnName("role_id"); + + b.HasKey("PlayerUserId", "RoleId") + .HasName("PK_role_whitelists"); + + b.ToTable("role_whitelists", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("round_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ServerId") + .HasColumnType("integer") + .HasColumnName("server_id"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("start_date"); + + b.HasKey("Id") + .HasName("PK_round"); + + b.HasIndex("ServerId") + .HasDatabaseName("IX_round_server_id"); + + b.HasIndex("StartDate"); + + b.ToTable("round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_server"); + + b.ToTable("server", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_ban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Address") + .HasColumnType("inet") + .HasColumnName("address"); + + b.Property("AutoDelete") + .HasColumnType("boolean") + .HasColumnName("auto_delete"); + + b.Property("BanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("uuid") + .HasColumnName("banning_admin"); + + b.Property("ExemptFlags") + .HasColumnType("integer") + .HasColumnName("exempt_flags"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("Hidden") + .HasColumnType("boolean") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_ban_round_id"); + + b.ToTable("server_ban", null, t => + { + t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"); + + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanExemption", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("Flags") + .HasColumnType("integer") + .HasColumnName("flags"); + + b.HasKey("UserId") + .HasName("PK_server_ban_exemption"); + + b.ToTable("server_ban_exemption", null, t => + { + t.HasCheckConstraint("FlagsNotZero", "flags != 0"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_ban_hit_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BanId") + .HasColumnType("integer") + .HasColumnName("ban_id"); + + b.Property("ConnectionId") + .HasColumnType("integer") + .HasColumnName("connection_id"); + + b.HasKey("Id") + .HasName("PK_server_ban_hit"); + + b.HasIndex("BanId") + .HasDatabaseName("IX_server_ban_hit_ban_id"); + + b.HasIndex("ConnectionId") + .HasDatabaseName("IX_server_ban_hit_connection_id"); + + b.ToTable("server_ban_hit", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_role_ban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Address") + .HasColumnType("inet") + .HasColumnName("address"); + + b.Property("BanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("uuid") + .HasColumnName("banning_admin"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("Hidden") + .HasColumnType("boolean") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("text") + .HasColumnName("role_id"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_role_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_role_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_role_ban_round_id"); + + b.ToTable("server_role_ban", null, t => + { + t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"); + + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("role_unban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BanId") + .HasColumnType("integer") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("uuid") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_role_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_role_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("unban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BanId") + .HasColumnType("integer") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("uuid") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("trait_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.Property("TraitName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("trait_name"); + + b.HasKey("Id") + .HasName("PK_trait"); + + b.HasIndex("ProfileId", "TraitName") + .IsUnique(); + + b.ToTable("trait", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.UploadedResourceLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("uploaded_resource_log_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Data") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("data"); + + b.Property("Date") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property("Path") + .IsRequired() + .HasColumnType("text") + .HasColumnName("path"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_uploaded_resource_log"); + + b.ToTable("uploaded_resource_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Whitelist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_whitelist"); + + b.ToTable("whitelist", (string)null); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.Property("PlayersId") + .HasColumnType("integer") + .HasColumnName("players_id"); + + b.Property("RoundsId") + .HasColumnType("integer") + .HasColumnName("rounds_id"); + + b.HasKey("PlayersId", "RoundsId") + .HasName("PK_player_round"); + + b.HasIndex("RoundsId") + .HasDatabaseName("IX_player_round_rounds_id"); + + b.ToTable("player_round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.HasOne("Content.Server.Database.AdminRank", "AdminRank") + .WithMany("Admins") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_admin_rank_admin_rank_id"); + + b.Navigation("AdminRank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.HasOne("Content.Server.Database.Admin", "Admin") + .WithMany("Flags") + .HasForeignKey("AdminId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_flag_admin_admin_id"); + + b.Navigation("Admin"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany("AdminLogs") + .HasForeignKey("RoundId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_round_round_id"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminLogs") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_player_player_user_id"); + + b.HasOne("Content.Server.Database.AdminLog", "Log") + .WithMany("Players") + .HasForeignKey("RoundId", "LogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_admin_log_round_id_log_id"); + + b.Navigation("Log"); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminMessage", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminMessagesCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminMessagesDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminMessagesLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminMessagesReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_messages_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_messages_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminNote", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminNotesCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminNotesDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminNotesLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminNotesReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_notes_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_notes_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.HasOne("Content.Server.Database.AdminRank", "Rank") + .WithMany("Flags") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_rank_flag_admin_rank_admin_rank_id"); + + b.Navigation("Rank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminWatchlistsCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminWatchlistsDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminWatchlistsLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminWatchlistsReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_watchlists_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_watchlists_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Antags") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_antag_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.HasOne("Content.Server.Database.Server", "Server") + .WithMany("ConnectionLogs") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.SetNull) + .IsRequired() + .HasConstraintName("FK_connection_log_server_server_id"); + + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ConnectionLogId") + .HasColumnType("integer") + .HasColumnName("connection_log_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ConnectionLogId"); + + b1.ToTable("connection_log"); + + b1.WithOwner() + .HasForeignKey("ConnectionLogId") + .HasConstraintName("FK_connection_log_connection_log_connection_log_id"); + }); + + b.Navigation("HWId"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Jobs") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_job_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.OwnsOne("Content.Server.Database.TypedHwid", "LastSeenHWId", b1 => + { + b1.Property("PlayerId") + .HasColumnType("integer") + .HasColumnName("player_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("last_seen_hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("last_seen_hwid_type"); + + b1.HasKey("PlayerId"); + + b1.ToTable("player"); + + b1.WithOwner() + .HasForeignKey("PlayerId") + .HasConstraintName("FK_player_player_player_id"); + }); + + b.Navigation("LastSeenHWId"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.HasOne("Content.Server.Database.Preference", "Preference") + .WithMany("Profiles") + .HasForeignKey("PreferenceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_preference_preference_id"); + + b.Navigation("Preference"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadout", b => + { + b.HasOne("Content.Server.Database.ProfileLoadoutGroup", "ProfileLoadoutGroup") + .WithMany("Loadouts") + .HasForeignKey("ProfileLoadoutGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_loadout_profile_loadout_group_profile_loadout_group~"); + + b.Navigation("ProfileLoadoutGroup"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.HasOne("Content.Server.Database.ProfileRoleLoadout", "ProfileRoleLoadout") + .WithMany("Groups") + .HasForeignKey("ProfileRoleLoadoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_loadout_group_profile_role_loadout_profile_role_loa~"); + + b.Navigation("ProfileRoleLoadout"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Loadouts") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_role_loadout_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b => + { + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("JobWhitelists") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_role_whitelists_player_player_user_id"); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.HasOne("Content.Server.Database.Server", "Server") + .WithMany("Rounds") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_round_server_server_id"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_ban_round_round_id"); + + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerBanId") + .HasColumnType("integer") + .HasColumnName("server_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerBanId"); + + b1.ToTable("server_ban"); + + b1.WithOwner() + .HasForeignKey("ServerBanId") + .HasConstraintName("FK_server_ban_server_ban_server_ban_id"); + }); + + b.Navigation("CreatedBy"); + + b.Navigation("HWId"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithMany("BanHits") + .HasForeignKey("BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_server_ban_ban_id"); + + b.HasOne("Content.Server.Database.ConnectionLog", "Connection") + .WithMany("BanHits") + .HasForeignKey("ConnectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_connection_log_connection_id"); + + b.Navigation("Ban"); + + b.Navigation("Connection"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerRoleBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerRoleBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_role_ban_round_round_id"); + + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerRoleBanId") + .HasColumnType("integer") + .HasColumnName("server_role_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerRoleBanId"); + + b1.ToTable("server_role_ban"); + + b1.WithOwner() + .HasForeignKey("ServerRoleBanId") + .HasConstraintName("FK_server_role_ban_server_role_ban_server_role_ban_id"); + }); + + b.Navigation("CreatedBy"); + + b.Navigation("HWId"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.HasOne("Content.Server.Database.ServerRoleBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerRoleUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_role_unban_server_role_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_unban_server_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Traits") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_trait_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.HasOne("Content.Server.Database.Player", null) + .WithMany() + .HasForeignKey("PlayersId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_player_players_id"); + + b.HasOne("Content.Server.Database.Round", null) + .WithMany() + .HasForeignKey("RoundsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_round_rounds_id"); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Navigation("Players"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Navigation("Admins"); + + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Navigation("BanHits"); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Navigation("AdminLogs"); + + b.Navigation("AdminMessagesCreated"); + + b.Navigation("AdminMessagesDeleted"); + + b.Navigation("AdminMessagesLastEdited"); + + b.Navigation("AdminMessagesReceived"); + + b.Navigation("AdminNotesCreated"); + + b.Navigation("AdminNotesDeleted"); + + b.Navigation("AdminNotesLastEdited"); + + b.Navigation("AdminNotesReceived"); + + b.Navigation("AdminServerBansCreated"); + + b.Navigation("AdminServerBansLastEdited"); + + b.Navigation("AdminServerRoleBansCreated"); + + b.Navigation("AdminServerRoleBansLastEdited"); + + b.Navigation("AdminWatchlistsCreated"); + + b.Navigation("AdminWatchlistsDeleted"); + + b.Navigation("AdminWatchlistsLastEdited"); + + b.Navigation("AdminWatchlistsReceived"); + + b.Navigation("JobWhitelists"); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Navigation("Profiles"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Navigation("Antags"); + + b.Navigation("Jobs"); + + b.Navigation("Loadouts"); + + b.Navigation("Traits"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.Navigation("Loadouts"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.Navigation("Groups"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Navigation("AdminLogs"); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Navigation("ConnectionLogs"); + + b.Navigation("Rounds"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.Navigation("BanHits"); + + b.Navigation("Unban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.Navigation("Unban"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Content.Server.Database/Migrations/Postgres/20241111170112_ModernHwid.cs b/Content.Server.Database/Migrations/Postgres/20241111170112_ModernHwid.cs new file mode 100644 index 000000000000..c70a5ffaa58b --- /dev/null +++ b/Content.Server.Database/Migrations/Postgres/20241111170112_ModernHwid.cs @@ -0,0 +1,62 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Content.Server.Database.Migrations.Postgres +{ + /// + public partial class ModernHwid : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "hwid_type", + table: "server_role_ban", + type: "integer", + nullable: true, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "hwid_type", + table: "server_ban", + type: "integer", + nullable: true, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "last_seen_hwid_type", + table: "player", + type: "integer", + nullable: true, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "hwid_type", + table: "connection_log", + type: "integer", + nullable: true, + defaultValue: 0); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "hwid_type", + table: "server_role_ban"); + + migrationBuilder.DropColumn( + name: "hwid_type", + table: "server_ban"); + + migrationBuilder.DropColumn( + name: "last_seen_hwid_type", + table: "player"); + + migrationBuilder.DropColumn( + name: "hwid_type", + table: "connection_log"); + } + } +} diff --git a/Content.Server.Database/Migrations/Postgres/20241111193608_ConnectionTrust.Designer.cs b/Content.Server.Database/Migrations/Postgres/20241111193608_ConnectionTrust.Designer.cs new file mode 100644 index 000000000000..dc1b4a0eeb7f --- /dev/null +++ b/Content.Server.Database/Migrations/Postgres/20241111193608_ConnectionTrust.Designer.cs @@ -0,0 +1,2076 @@ +// +using System; +using System.Net; +using System.Text.Json; +using Content.Server.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using NpgsqlTypes; + +#nullable disable + +namespace Content.Server.Database.Migrations.Postgres +{ + [DbContext(typeof(PostgresServerDbContext))] + [Migration("20241111193608_ConnectionTrust")] + partial class ConnectionTrust + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.0") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("AdminRankId") + .HasColumnType("integer") + .HasColumnName("admin_rank_id"); + + b.Property("Title") + .HasColumnType("text") + .HasColumnName("title"); + + b.HasKey("UserId") + .HasName("PK_admin"); + + b.HasIndex("AdminRankId") + .HasDatabaseName("IX_admin_admin_rank_id"); + + b.ToTable("admin", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_flag_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AdminId") + .HasColumnType("uuid") + .HasColumnName("admin_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("text") + .HasColumnName("flag"); + + b.Property("Negative") + .HasColumnType("boolean") + .HasColumnName("negative"); + + b.HasKey("Id") + .HasName("PK_admin_flag"); + + b.HasIndex("AdminId") + .HasDatabaseName("IX_admin_flag_admin_id"); + + b.HasIndex("Flag", "AdminId") + .IsUnique(); + + b.ToTable("admin_flag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Id") + .HasColumnType("integer") + .HasColumnName("admin_log_id"); + + b.Property("Date") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property("Impact") + .HasColumnType("smallint") + .HasColumnName("impact"); + + b.Property("Json") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("json"); + + b.Property("Message") + .IsRequired() + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("RoundId", "Id") + .HasName("PK_admin_log"); + + b.HasIndex("Date"); + + b.HasIndex("Message") + .HasAnnotation("Npgsql:TsVectorConfig", "english"); + + NpgsqlIndexBuilderExtensions.HasMethod(b.HasIndex("Message"), "GIN"); + + b.HasIndex("Type") + .HasDatabaseName("IX_admin_log_type"); + + b.ToTable("admin_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("LogId") + .HasColumnType("integer") + .HasColumnName("log_id"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.HasKey("RoundId", "LogId", "PlayerUserId") + .HasName("PK_admin_log_player"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_log_player_player_user_id"); + + b.ToTable("admin_log_player", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_messages_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("uuid") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("boolean") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("uuid") + .HasColumnName("deleted_by_id"); + + b.Property("Dismissed") + .HasColumnType("boolean") + .HasColumnName("dismissed"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Seen") + .HasColumnType("boolean") + .HasColumnName("seen"); + + b.HasKey("Id") + .HasName("PK_admin_messages"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_messages_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_messages_round_id"); + + b.ToTable("admin_messages", null, t => + { + t.HasCheckConstraint("NotDismissedAndSeen", "NOT dismissed OR seen"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.AdminNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_notes_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("uuid") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("boolean") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("uuid") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Secret") + .HasColumnType("boolean") + .HasColumnName("secret"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_admin_notes"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_notes_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_notes_round_id"); + + b.ToTable("admin_notes", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_rank_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_admin_rank"); + + b.ToTable("admin_rank", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_rank_flag_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AdminRankId") + .HasColumnType("integer") + .HasColumnName("admin_rank_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("text") + .HasColumnName("flag"); + + b.HasKey("Id") + .HasName("PK_admin_rank_flag"); + + b.HasIndex("AdminRankId"); + + b.HasIndex("Flag", "AdminRankId") + .IsUnique(); + + b.ToTable("admin_rank_flag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("admin_watchlists_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("uuid") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("boolean") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("uuid") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("character varying(4096)") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.HasKey("Id") + .HasName("PK_admin_watchlists"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_watchlists_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_watchlists_round_id"); + + b.ToTable("admin_watchlists", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("antag_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AntagName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("antag_name"); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_antag"); + + b.HasIndex("ProfileId", "AntagName") + .IsUnique(); + + b.ToTable("antag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AssignedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("assigned_user_id_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("PK_assigned_user_id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("UserName") + .IsUnique(); + + b.ToTable("assigned_user_id", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.BanTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("ban_template_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AutoDelete") + .HasColumnType("boolean") + .HasColumnName("auto_delete"); + + b.Property("ExemptFlags") + .HasColumnType("integer") + .HasColumnName("exempt_flags"); + + b.Property("Hidden") + .HasColumnType("boolean") + .HasColumnName("hidden"); + + b.Property("Length") + .HasColumnType("interval") + .HasColumnName("length"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.Property("Title") + .IsRequired() + .HasColumnType("text") + .HasColumnName("title"); + + b.HasKey("Id") + .HasName("PK_ban_template"); + + b.ToTable("ban_template", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Blacklist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_blacklist"); + + b.ToTable("blacklist", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("connection_log_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Address") + .IsRequired() + .HasColumnType("inet") + .HasColumnName("address"); + + b.Property("Denied") + .HasColumnType("smallint") + .HasColumnName("denied"); + + b.Property("ServerId") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("server_id"); + + b.Property("Time") + .HasColumnType("timestamp with time zone") + .HasColumnName("time"); + + b.Property("Trust") + .HasColumnType("real") + .HasColumnName("trust"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("PK_connection_log"); + + b.HasIndex("ServerId") + .HasDatabaseName("IX_connection_log_server_id"); + + b.HasIndex("Time"); + + b.HasIndex("UserId"); + + b.ToTable("connection_log", null, t => + { + t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("job_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("JobName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("job_name"); + + b.Property("Priority") + .HasColumnType("integer") + .HasColumnName("priority"); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_job"); + + b.HasIndex("ProfileId"); + + b.HasIndex("ProfileId", "JobName") + .IsUnique(); + + b.HasIndex(new[] { "ProfileId" }, "IX_job_one_high_priority") + .IsUnique() + .HasFilter("priority = 3"); + + b.ToTable("job", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.PlayTime", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("play_time_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("PlayerId") + .HasColumnType("uuid") + .HasColumnName("player_id"); + + b.Property("TimeSpent") + .HasColumnType("interval") + .HasColumnName("time_spent"); + + b.Property("Tracker") + .IsRequired() + .HasColumnType("text") + .HasColumnName("tracker"); + + b.HasKey("Id") + .HasName("PK_play_time"); + + b.HasIndex("PlayerId", "Tracker") + .IsUnique(); + + b.ToTable("play_time", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("player_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("FirstSeenTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("first_seen_time"); + + b.Property("LastReadRules") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_read_rules"); + + b.Property("LastSeenAddress") + .IsRequired() + .HasColumnType("inet") + .HasColumnName("last_seen_address"); + + b.Property("LastSeenTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_seen_time"); + + b.Property("LastSeenUserName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("last_seen_user_name"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_player"); + + b.HasAlternateKey("UserId") + .HasName("ak_player_user_id"); + + b.HasIndex("LastSeenUserName"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("player", null, t => + { + t.HasCheckConstraint("LastSeenAddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= last_seen_address"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("preference_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AdminOOCColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("admin_ooc_color"); + + b.Property("SelectedCharacterSlot") + .HasColumnType("integer") + .HasColumnName("selected_character_slot"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_preference"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("preference", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("profile_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Age") + .HasColumnType("integer") + .HasColumnName("age"); + + b.Property("CharacterName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("char_name"); + + b.Property("EyeColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("eye_color"); + + b.Property("FacialHairColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("facial_hair_color"); + + b.Property("FacialHairName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("facial_hair_name"); + + b.Property("FlavorText") + .IsRequired() + .HasColumnType("text") + .HasColumnName("flavor_text"); + + b.Property("Gender") + .IsRequired() + .HasColumnType("text") + .HasColumnName("gender"); + + b.Property("HairColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("hair_color"); + + b.Property("HairName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("hair_name"); + + b.Property("Markings") + .HasColumnType("jsonb") + .HasColumnName("markings"); + + b.Property("PreferenceId") + .HasColumnType("integer") + .HasColumnName("preference_id"); + + b.Property("PreferenceUnavailable") + .HasColumnType("integer") + .HasColumnName("pref_unavailable"); + + b.Property("Sex") + .IsRequired() + .HasColumnType("text") + .HasColumnName("sex"); + + b.Property("SkinColor") + .IsRequired() + .HasColumnType("text") + .HasColumnName("skin_color"); + + b.Property("Slot") + .HasColumnType("integer") + .HasColumnName("slot"); + + b.Property("SpawnPriority") + .HasColumnType("integer") + .HasColumnName("spawn_priority"); + + b.Property("Species") + .IsRequired() + .HasColumnType("text") + .HasColumnName("species"); + + b.HasKey("Id") + .HasName("PK_profile"); + + b.HasIndex("PreferenceId") + .HasDatabaseName("IX_profile_preference_id"); + + b.HasIndex("Slot", "PreferenceId") + .IsUnique(); + + b.ToTable("profile", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("profile_loadout_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("LoadoutName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("loadout_name"); + + b.Property("ProfileLoadoutGroupId") + .HasColumnType("integer") + .HasColumnName("profile_loadout_group_id"); + + b.HasKey("Id") + .HasName("PK_profile_loadout"); + + b.HasIndex("ProfileLoadoutGroupId"); + + b.ToTable("profile_loadout", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("profile_loadout_group_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("GroupName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("group_name"); + + b.Property("ProfileRoleLoadoutId") + .HasColumnType("integer") + .HasColumnName("profile_role_loadout_id"); + + b.HasKey("Id") + .HasName("PK_profile_loadout_group"); + + b.HasIndex("ProfileRoleLoadoutId"); + + b.ToTable("profile_loadout_group", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("profile_role_loadout_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.Property("RoleName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("role_name"); + + b.HasKey("Id") + .HasName("PK_profile_role_loadout"); + + b.HasIndex("ProfileId"); + + b.ToTable("profile_role_loadout", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b => + { + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("RoleId") + .HasColumnType("text") + .HasColumnName("role_id"); + + b.HasKey("PlayerUserId", "RoleId") + .HasName("PK_role_whitelists"); + + b.ToTable("role_whitelists", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("round_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ServerId") + .HasColumnType("integer") + .HasColumnName("server_id"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone") + .HasColumnName("start_date"); + + b.HasKey("Id") + .HasName("PK_round"); + + b.HasIndex("ServerId") + .HasDatabaseName("IX_round_server_id"); + + b.HasIndex("StartDate"); + + b.ToTable("round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_server"); + + b.ToTable("server", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_ban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Address") + .HasColumnType("inet") + .HasColumnName("address"); + + b.Property("AutoDelete") + .HasColumnType("boolean") + .HasColumnName("auto_delete"); + + b.Property("BanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("uuid") + .HasColumnName("banning_admin"); + + b.Property("ExemptFlags") + .HasColumnType("integer") + .HasColumnName("exempt_flags"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("Hidden") + .HasColumnType("boolean") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_ban_round_id"); + + b.ToTable("server_ban", null, t => + { + t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"); + + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanExemption", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.Property("Flags") + .HasColumnType("integer") + .HasColumnName("flags"); + + b.HasKey("UserId") + .HasName("PK_server_ban_exemption"); + + b.ToTable("server_ban_exemption", null, t => + { + t.HasCheckConstraint("FlagsNotZero", "flags != 0"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_ban_hit_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BanId") + .HasColumnType("integer") + .HasColumnName("ban_id"); + + b.Property("ConnectionId") + .HasColumnType("integer") + .HasColumnName("connection_id"); + + b.HasKey("Id") + .HasName("PK_server_ban_hit"); + + b.HasIndex("BanId") + .HasDatabaseName("IX_server_ban_hit_ban_id"); + + b.HasIndex("ConnectionId") + .HasDatabaseName("IX_server_ban_hit_connection_id"); + + b.ToTable("server_ban_hit", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("server_role_ban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Address") + .HasColumnType("inet") + .HasColumnName("address"); + + b.Property("BanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("uuid") + .HasColumnName("banning_admin"); + + b.Property("ExpirationTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("expiration_time"); + + b.Property("Hidden") + .HasColumnType("boolean") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("timestamp with time zone") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("uuid") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("uuid") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("interval") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("text") + .HasColumnName("role_id"); + + b.Property("RoundId") + .HasColumnType("integer") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("integer") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_role_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_role_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_role_ban_round_id"); + + b.ToTable("server_role_ban", null, t => + { + t.HasCheckConstraint("AddressNotIPv6MappedIPv4", "NOT inet '::ffff:0.0.0.0/96' >>= address"); + + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("role_unban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BanId") + .HasColumnType("integer") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("uuid") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_role_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_role_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("unban_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BanId") + .HasColumnType("integer") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("uuid") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("trait_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ProfileId") + .HasColumnType("integer") + .HasColumnName("profile_id"); + + b.Property("TraitName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("trait_name"); + + b.HasKey("Id") + .HasName("PK_trait"); + + b.HasIndex("ProfileId", "TraitName") + .IsUnique(); + + b.ToTable("trait", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.UploadedResourceLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("uploaded_resource_log_id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Data") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("data"); + + b.Property("Date") + .HasColumnType("timestamp with time zone") + .HasColumnName("date"); + + b.Property("Path") + .IsRequired() + .HasColumnType("text") + .HasColumnName("path"); + + b.Property("UserId") + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_uploaded_resource_log"); + + b.ToTable("uploaded_resource_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Whitelist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_whitelist"); + + b.ToTable("whitelist", (string)null); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.Property("PlayersId") + .HasColumnType("integer") + .HasColumnName("players_id"); + + b.Property("RoundsId") + .HasColumnType("integer") + .HasColumnName("rounds_id"); + + b.HasKey("PlayersId", "RoundsId") + .HasName("PK_player_round"); + + b.HasIndex("RoundsId") + .HasDatabaseName("IX_player_round_rounds_id"); + + b.ToTable("player_round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.HasOne("Content.Server.Database.AdminRank", "AdminRank") + .WithMany("Admins") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_admin_rank_admin_rank_id"); + + b.Navigation("AdminRank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.HasOne("Content.Server.Database.Admin", "Admin") + .WithMany("Flags") + .HasForeignKey("AdminId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_flag_admin_admin_id"); + + b.Navigation("Admin"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany("AdminLogs") + .HasForeignKey("RoundId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_round_round_id"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminLogs") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_player_player_user_id"); + + b.HasOne("Content.Server.Database.AdminLog", "Log") + .WithMany("Players") + .HasForeignKey("RoundId", "LogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_admin_log_round_id_log_id"); + + b.Navigation("Log"); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminMessage", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminMessagesCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminMessagesDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminMessagesLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminMessagesReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_messages_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_messages_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminNote", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminNotesCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminNotesDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminNotesLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminNotesReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_notes_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_notes_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.HasOne("Content.Server.Database.AdminRank", "Rank") + .WithMany("Flags") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_rank_flag_admin_rank_admin_rank_id"); + + b.Navigation("Rank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminWatchlistsCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminWatchlistsDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminWatchlistsLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminWatchlistsReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_watchlists_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_watchlists_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Antags") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_antag_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.HasOne("Content.Server.Database.Server", "Server") + .WithMany("ConnectionLogs") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.SetNull) + .IsRequired() + .HasConstraintName("FK_connection_log_server_server_id"); + + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ConnectionLogId") + .HasColumnType("integer") + .HasColumnName("connection_log_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ConnectionLogId"); + + b1.ToTable("connection_log"); + + b1.WithOwner() + .HasForeignKey("ConnectionLogId") + .HasConstraintName("FK_connection_log_connection_log_connection_log_id"); + }); + + b.Navigation("HWId"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Jobs") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_job_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.OwnsOne("Content.Server.Database.TypedHwid", "LastSeenHWId", b1 => + { + b1.Property("PlayerId") + .HasColumnType("integer") + .HasColumnName("player_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("last_seen_hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("last_seen_hwid_type"); + + b1.HasKey("PlayerId"); + + b1.ToTable("player"); + + b1.WithOwner() + .HasForeignKey("PlayerId") + .HasConstraintName("FK_player_player_player_id"); + }); + + b.Navigation("LastSeenHWId"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.HasOne("Content.Server.Database.Preference", "Preference") + .WithMany("Profiles") + .HasForeignKey("PreferenceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_preference_preference_id"); + + b.Navigation("Preference"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadout", b => + { + b.HasOne("Content.Server.Database.ProfileLoadoutGroup", "ProfileLoadoutGroup") + .WithMany("Loadouts") + .HasForeignKey("ProfileLoadoutGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_loadout_profile_loadout_group_profile_loadout_group~"); + + b.Navigation("ProfileLoadoutGroup"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.HasOne("Content.Server.Database.ProfileRoleLoadout", "ProfileRoleLoadout") + .WithMany("Groups") + .HasForeignKey("ProfileRoleLoadoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_loadout_group_profile_role_loadout_profile_role_loa~"); + + b.Navigation("ProfileRoleLoadout"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Loadouts") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_role_loadout_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b => + { + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("JobWhitelists") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_role_whitelists_player_player_user_id"); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.HasOne("Content.Server.Database.Server", "Server") + .WithMany("Rounds") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_round_server_server_id"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_ban_round_round_id"); + + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerBanId") + .HasColumnType("integer") + .HasColumnName("server_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerBanId"); + + b1.ToTable("server_ban"); + + b1.WithOwner() + .HasForeignKey("ServerBanId") + .HasConstraintName("FK_server_ban_server_ban_server_ban_id"); + }); + + b.Navigation("CreatedBy"); + + b.Navigation("HWId"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithMany("BanHits") + .HasForeignKey("BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_server_ban_ban_id"); + + b.HasOne("Content.Server.Database.ConnectionLog", "Connection") + .WithMany("BanHits") + .HasForeignKey("ConnectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_connection_log_connection_id"); + + b.Navigation("Ban"); + + b.Navigation("Connection"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerRoleBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerRoleBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_role_ban_round_round_id"); + + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerRoleBanId") + .HasColumnType("integer") + .HasColumnName("server_role_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerRoleBanId"); + + b1.ToTable("server_role_ban"); + + b1.WithOwner() + .HasForeignKey("ServerRoleBanId") + .HasConstraintName("FK_server_role_ban_server_role_ban_server_role_ban_id"); + }); + + b.Navigation("CreatedBy"); + + b.Navigation("HWId"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.HasOne("Content.Server.Database.ServerRoleBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerRoleUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_role_unban_server_role_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_unban_server_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Traits") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_trait_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.HasOne("Content.Server.Database.Player", null) + .WithMany() + .HasForeignKey("PlayersId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_player_players_id"); + + b.HasOne("Content.Server.Database.Round", null) + .WithMany() + .HasForeignKey("RoundsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_round_rounds_id"); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Navigation("Players"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Navigation("Admins"); + + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Navigation("BanHits"); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Navigation("AdminLogs"); + + b.Navigation("AdminMessagesCreated"); + + b.Navigation("AdminMessagesDeleted"); + + b.Navigation("AdminMessagesLastEdited"); + + b.Navigation("AdminMessagesReceived"); + + b.Navigation("AdminNotesCreated"); + + b.Navigation("AdminNotesDeleted"); + + b.Navigation("AdminNotesLastEdited"); + + b.Navigation("AdminNotesReceived"); + + b.Navigation("AdminServerBansCreated"); + + b.Navigation("AdminServerBansLastEdited"); + + b.Navigation("AdminServerRoleBansCreated"); + + b.Navigation("AdminServerRoleBansLastEdited"); + + b.Navigation("AdminWatchlistsCreated"); + + b.Navigation("AdminWatchlistsDeleted"); + + b.Navigation("AdminWatchlistsLastEdited"); + + b.Navigation("AdminWatchlistsReceived"); + + b.Navigation("JobWhitelists"); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Navigation("Profiles"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Navigation("Antags"); + + b.Navigation("Jobs"); + + b.Navigation("Loadouts"); + + b.Navigation("Traits"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.Navigation("Loadouts"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.Navigation("Groups"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Navigation("AdminLogs"); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Navigation("ConnectionLogs"); + + b.Navigation("Rounds"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.Navigation("BanHits"); + + b.Navigation("Unban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.Navigation("Unban"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Content.Server.Database/Migrations/Postgres/20241111193608_ConnectionTrust.cs b/Content.Server.Database/Migrations/Postgres/20241111193608_ConnectionTrust.cs new file mode 100644 index 000000000000..debb36aaccb0 --- /dev/null +++ b/Content.Server.Database/Migrations/Postgres/20241111193608_ConnectionTrust.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Content.Server.Database.Migrations.Postgres +{ + /// + public partial class ConnectionTrust : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "trust", + table: "connection_log", + type: "real", + nullable: false, + defaultValue: 0f); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "trust", + table: "connection_log"); + } + } +} diff --git a/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs b/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs index 1f64f6e51a5d..75444386311d 100644 --- a/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs +++ b/Content.Server.Database/Migrations/Postgres/PostgresServerDbContextModelSnapshot.cs @@ -512,20 +512,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("assigned_user_id", (string)null); }); - modelBuilder.Entity("Content.Server.Database.Blacklist", - b => - { - b.Property("UserId") - .ValueGeneratedOnAdd() - .HasColumnType("uuid") - .HasColumnName("user_id"); - - b.HasKey("UserId") - .HasName("PK_blacklist"); - - b.ToTable("blacklist", (string) null); - }); - modelBuilder.Entity("Content.Server.Database.BanTemplate", b => { b.Property("Id") @@ -571,6 +557,19 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("ban_template", (string)null); }); + modelBuilder.Entity("Content.Server.Database.Blacklist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_blacklist"); + + b.ToTable("blacklist", (string)null); + }); + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => { b.Property("Id") @@ -589,10 +588,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("smallint") .HasColumnName("denied"); - b.Property("HWId") - .HasColumnType("bytea") - .HasColumnName("hwid"); - b.Property("ServerId") .ValueGeneratedOnAdd() .HasColumnType("integer") @@ -603,6 +598,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("timestamp with time zone") .HasColumnName("time"); + b.Property("Trust") + .HasColumnType("real") + .HasColumnName("trust"); + b.Property("UserId") .HasColumnType("uuid") .HasColumnName("user_id"); @@ -718,10 +717,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("inet") .HasColumnName("last_seen_address"); - b.Property("LastSeenHWId") - .HasColumnType("bytea") - .HasColumnName("last_seen_hwid"); - b.Property("LastSeenTime") .HasColumnType("timestamp with time zone") .HasColumnName("last_seen_time"); @@ -1058,10 +1053,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("timestamp with time zone") .HasColumnName("expiration_time"); - b.Property("HWId") - .HasColumnType("bytea") - .HasColumnName("hwid"); - b.Property("Hidden") .HasColumnType("boolean") .HasColumnName("hidden"); @@ -1192,10 +1183,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("timestamp with time zone") .HasColumnName("expiration_time"); - b.Property("HWId") - .HasColumnType("bytea") - .HasColumnName("hwid"); - b.Property("Hidden") .HasColumnType("boolean") .HasColumnName("hidden"); @@ -1637,6 +1624,34 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasConstraintName("FK_connection_log_server_server_id"); + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ConnectionLogId") + .HasColumnType("integer") + .HasColumnName("connection_log_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ConnectionLogId"); + + b1.ToTable("connection_log"); + + b1.WithOwner() + .HasForeignKey("ConnectionLogId") + .HasConstraintName("FK_connection_log_connection_log_connection_log_id"); + }); + + b.Navigation("HWId"); + b.Navigation("Server"); }); @@ -1652,6 +1667,37 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Profile"); }); + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.OwnsOne("Content.Server.Database.TypedHwid", "LastSeenHWId", b1 => + { + b1.Property("PlayerId") + .HasColumnType("integer") + .HasColumnName("player_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("last_seen_hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("last_seen_hwid_type"); + + b1.HasKey("PlayerId"); + + b1.ToTable("player"); + + b1.WithOwner() + .HasForeignKey("PlayerId") + .HasConstraintName("FK_player_player_player_id"); + }); + + b.Navigation("LastSeenHWId"); + }); + modelBuilder.Entity("Content.Server.Database.Profile", b => { b.HasOne("Content.Server.Database.Preference", "Preference") @@ -1746,8 +1792,36 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasForeignKey("RoundId") .HasConstraintName("FK_server_ban_round_round_id"); + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerBanId") + .HasColumnType("integer") + .HasColumnName("server_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerBanId"); + + b1.ToTable("server_ban"); + + b1.WithOwner() + .HasForeignKey("ServerBanId") + .HasConstraintName("FK_server_ban_server_ban_server_ban_id"); + }); + b.Navigation("CreatedBy"); + b.Navigation("HWId"); + b.Navigation("LastEditedBy"); b.Navigation("Round"); @@ -1795,8 +1869,36 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasForeignKey("RoundId") .HasConstraintName("FK_server_role_ban_round_round_id"); + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerRoleBanId") + .HasColumnType("integer") + .HasColumnName("server_role_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("bytea") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerRoleBanId"); + + b1.ToTable("server_role_ban"); + + b1.WithOwner() + .HasForeignKey("ServerRoleBanId") + .HasConstraintName("FK_server_role_ban_server_role_ban_server_role_ban_id"); + }); + b.Navigation("CreatedBy"); + b.Navigation("HWId"); + b.Navigation("LastEditedBy"); b.Navigation("Round"); diff --git a/Content.Server.Database/Migrations/Sqlite/20241111170107_ModernHwid.Designer.cs b/Content.Server.Database/Migrations/Sqlite/20241111170107_ModernHwid.Designer.cs new file mode 100644 index 000000000000..56a9fe0a0599 --- /dev/null +++ b/Content.Server.Database/Migrations/Sqlite/20241111170107_ModernHwid.Designer.cs @@ -0,0 +1,1995 @@ +// +using System; +using Content.Server.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Content.Server.Database.Migrations.Sqlite +{ + [DbContext(typeof(SqliteServerDbContext))] + [Migration("20241111170107_ModernHwid")] + partial class ModernHwid + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "8.0.0"); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.Property("AdminRankId") + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_id"); + + b.Property("Title") + .HasColumnType("TEXT") + .HasColumnName("title"); + + b.HasKey("UserId") + .HasName("PK_admin"); + + b.HasIndex("AdminRankId") + .HasDatabaseName("IX_admin_admin_rank_id"); + + b.ToTable("admin", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_flag_id"); + + b.Property("AdminId") + .HasColumnType("TEXT") + .HasColumnName("admin_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("flag"); + + b.Property("Negative") + .HasColumnType("INTEGER") + .HasColumnName("negative"); + + b.HasKey("Id") + .HasName("PK_admin_flag"); + + b.HasIndex("AdminId") + .HasDatabaseName("IX_admin_flag_admin_id"); + + b.HasIndex("Flag", "AdminId") + .IsUnique(); + + b.ToTable("admin_flag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Id") + .HasColumnType("INTEGER") + .HasColumnName("admin_log_id"); + + b.Property("Date") + .HasColumnType("TEXT") + .HasColumnName("date"); + + b.Property("Impact") + .HasColumnType("INTEGER") + .HasColumnName("impact"); + + b.Property("Json") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("json"); + + b.Property("Message") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("Type") + .HasColumnType("INTEGER") + .HasColumnName("type"); + + b.HasKey("RoundId", "Id") + .HasName("PK_admin_log"); + + b.HasIndex("Date"); + + b.HasIndex("Type") + .HasDatabaseName("IX_admin_log_type"); + + b.ToTable("admin_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("LogId") + .HasColumnType("INTEGER") + .HasColumnName("log_id"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.HasKey("RoundId", "LogId", "PlayerUserId") + .HasName("PK_admin_log_player"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_log_player_player_user_id"); + + b.ToTable("admin_log_player", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_messages_id"); + + b.Property("CreatedAt") + .HasColumnType("TEXT") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("TEXT") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("INTEGER") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("TEXT") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("TEXT") + .HasColumnName("deleted_by_id"); + + b.Property("Dismissed") + .HasColumnType("INTEGER") + .HasColumnName("dismissed"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Seen") + .HasColumnType("INTEGER") + .HasColumnName("seen"); + + b.HasKey("Id") + .HasName("PK_admin_messages"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_messages_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_messages_round_id"); + + b.ToTable("admin_messages", null, t => + { + t.HasCheckConstraint("NotDismissedAndSeen", "NOT dismissed OR seen"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.AdminNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_notes_id"); + + b.Property("CreatedAt") + .HasColumnType("TEXT") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("TEXT") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("INTEGER") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("TEXT") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("TEXT") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Secret") + .HasColumnType("INTEGER") + .HasColumnName("secret"); + + b.Property("Severity") + .HasColumnType("INTEGER") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_admin_notes"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_notes_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_notes_round_id"); + + b.ToTable("admin_notes", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_id"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_admin_rank"); + + b.ToTable("admin_rank", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_flag_id"); + + b.Property("AdminRankId") + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("flag"); + + b.HasKey("Id") + .HasName("PK_admin_rank_flag"); + + b.HasIndex("AdminRankId"); + + b.HasIndex("Flag", "AdminRankId") + .IsUnique(); + + b.ToTable("admin_rank_flag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_watchlists_id"); + + b.Property("CreatedAt") + .HasColumnType("TEXT") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("TEXT") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("INTEGER") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("TEXT") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("TEXT") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.HasKey("Id") + .HasName("PK_admin_watchlists"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_watchlists_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_watchlists_round_id"); + + b.ToTable("admin_watchlists", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("antag_id"); + + b.Property("AntagName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("antag_name"); + + b.Property("ProfileId") + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_antag"); + + b.HasIndex("ProfileId", "AntagName") + .IsUnique(); + + b.ToTable("antag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AssignedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("assigned_user_id_id"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("PK_assigned_user_id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("UserName") + .IsUnique(); + + b.ToTable("assigned_user_id", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.BanTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("ban_template_id"); + + b.Property("AutoDelete") + .HasColumnType("INTEGER") + .HasColumnName("auto_delete"); + + b.Property("ExemptFlags") + .HasColumnType("INTEGER") + .HasColumnName("exempt_flags"); + + b.Property("Hidden") + .HasColumnType("INTEGER") + .HasColumnName("hidden"); + + b.Property("Length") + .HasColumnType("TEXT") + .HasColumnName("length"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("reason"); + + b.Property("Severity") + .HasColumnType("INTEGER") + .HasColumnName("severity"); + + b.Property("Title") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("title"); + + b.HasKey("Id") + .HasName("PK_ban_template"); + + b.ToTable("ban_template", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Blacklist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_blacklist"); + + b.ToTable("blacklist", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("connection_log_id"); + + b.Property("Address") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("address"); + + b.Property("Denied") + .HasColumnType("INTEGER") + .HasColumnName("denied"); + + b.Property("ServerId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("server_id"); + + b.Property("Time") + .HasColumnType("TEXT") + .HasColumnName("time"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("PK_connection_log"); + + b.HasIndex("ServerId") + .HasDatabaseName("IX_connection_log_server_id"); + + b.HasIndex("Time"); + + b.HasIndex("UserId"); + + b.ToTable("connection_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("job_id"); + + b.Property("JobName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("job_name"); + + b.Property("Priority") + .HasColumnType("INTEGER") + .HasColumnName("priority"); + + b.Property("ProfileId") + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_job"); + + b.HasIndex("ProfileId"); + + b.HasIndex("ProfileId", "JobName") + .IsUnique(); + + b.HasIndex(new[] { "ProfileId" }, "IX_job_one_high_priority") + .IsUnique() + .HasFilter("priority = 3"); + + b.ToTable("job", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.PlayTime", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("play_time_id"); + + b.Property("PlayerId") + .HasColumnType("TEXT") + .HasColumnName("player_id"); + + b.Property("TimeSpent") + .HasColumnType("TEXT") + .HasColumnName("time_spent"); + + b.Property("Tracker") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("tracker"); + + b.HasKey("Id") + .HasName("PK_play_time"); + + b.HasIndex("PlayerId", "Tracker") + .IsUnique(); + + b.ToTable("play_time", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("player_id"); + + b.Property("FirstSeenTime") + .HasColumnType("TEXT") + .HasColumnName("first_seen_time"); + + b.Property("LastReadRules") + .HasColumnType("TEXT") + .HasColumnName("last_read_rules"); + + b.Property("LastSeenAddress") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_seen_address"); + + b.Property("LastSeenTime") + .HasColumnType("TEXT") + .HasColumnName("last_seen_time"); + + b.Property("LastSeenUserName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_seen_user_name"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_player"); + + b.HasAlternateKey("UserId") + .HasName("ak_player_user_id"); + + b.HasIndex("LastSeenUserName"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("player", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("preference_id"); + + b.Property("AdminOOCColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("admin_ooc_color"); + + b.Property("SelectedCharacterSlot") + .HasColumnType("INTEGER") + .HasColumnName("selected_character_slot"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_preference"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("preference", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.Property("Age") + .HasColumnType("INTEGER") + .HasColumnName("age"); + + b.Property("CharacterName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("char_name"); + + b.Property("EyeColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("eye_color"); + + b.Property("FacialHairColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("facial_hair_color"); + + b.Property("FacialHairName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("facial_hair_name"); + + b.Property("FlavorText") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("flavor_text"); + + b.Property("Gender") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("gender"); + + b.Property("HairColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("hair_color"); + + b.Property("HairName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("hair_name"); + + b.Property("Markings") + .HasColumnType("jsonb") + .HasColumnName("markings"); + + b.Property("PreferenceId") + .HasColumnType("INTEGER") + .HasColumnName("preference_id"); + + b.Property("PreferenceUnavailable") + .HasColumnType("INTEGER") + .HasColumnName("pref_unavailable"); + + b.Property("Sex") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("sex"); + + b.Property("SkinColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("skin_color"); + + b.Property("Slot") + .HasColumnType("INTEGER") + .HasColumnName("slot"); + + b.Property("SpawnPriority") + .HasColumnType("INTEGER") + .HasColumnName("spawn_priority"); + + b.Property("Species") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("species"); + + b.HasKey("Id") + .HasName("PK_profile"); + + b.HasIndex("PreferenceId") + .HasDatabaseName("IX_profile_preference_id"); + + b.HasIndex("Slot", "PreferenceId") + .IsUnique(); + + b.ToTable("profile", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("profile_loadout_id"); + + b.Property("LoadoutName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("loadout_name"); + + b.Property("ProfileLoadoutGroupId") + .HasColumnType("INTEGER") + .HasColumnName("profile_loadout_group_id"); + + b.HasKey("Id") + .HasName("PK_profile_loadout"); + + b.HasIndex("ProfileLoadoutGroupId"); + + b.ToTable("profile_loadout", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("profile_loadout_group_id"); + + b.Property("GroupName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("group_name"); + + b.Property("ProfileRoleLoadoutId") + .HasColumnType("INTEGER") + .HasColumnName("profile_role_loadout_id"); + + b.HasKey("Id") + .HasName("PK_profile_loadout_group"); + + b.HasIndex("ProfileRoleLoadoutId"); + + b.ToTable("profile_loadout_group", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("profile_role_loadout_id"); + + b.Property("ProfileId") + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.Property("RoleName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("role_name"); + + b.HasKey("Id") + .HasName("PK_profile_role_loadout"); + + b.HasIndex("ProfileId"); + + b.ToTable("profile_role_loadout", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b => + { + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("RoleId") + .HasColumnType("TEXT") + .HasColumnName("role_id"); + + b.HasKey("PlayerUserId", "RoleId") + .HasName("PK_role_whitelists"); + + b.ToTable("role_whitelists", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("ServerId") + .HasColumnType("INTEGER") + .HasColumnName("server_id"); + + b.Property("StartDate") + .HasColumnType("TEXT") + .HasColumnName("start_date"); + + b.HasKey("Id") + .HasName("PK_round"); + + b.HasIndex("ServerId") + .HasDatabaseName("IX_round_server_id"); + + b.HasIndex("StartDate"); + + b.ToTable("round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("server_id"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_server"); + + b.ToTable("server", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("server_ban_id"); + + b.Property("Address") + .HasColumnType("TEXT") + .HasColumnName("address"); + + b.Property("AutoDelete") + .HasColumnType("INTEGER") + .HasColumnName("auto_delete"); + + b.Property("BanTime") + .HasColumnType("TEXT") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("banning_admin"); + + b.Property("ExemptFlags") + .HasColumnType("INTEGER") + .HasColumnName("exempt_flags"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("Hidden") + .HasColumnType("INTEGER") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("reason"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("INTEGER") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_ban_round_id"); + + b.ToTable("server_ban", null, t => + { + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanExemption", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.Property("Flags") + .HasColumnType("INTEGER") + .HasColumnName("flags"); + + b.HasKey("UserId") + .HasName("PK_server_ban_exemption"); + + b.ToTable("server_ban_exemption", null, t => + { + t.HasCheckConstraint("FlagsNotZero", "flags != 0"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("server_ban_hit_id"); + + b.Property("BanId") + .HasColumnType("INTEGER") + .HasColumnName("ban_id"); + + b.Property("ConnectionId") + .HasColumnType("INTEGER") + .HasColumnName("connection_id"); + + b.HasKey("Id") + .HasName("PK_server_ban_hit"); + + b.HasIndex("BanId") + .HasDatabaseName("IX_server_ban_hit_ban_id"); + + b.HasIndex("ConnectionId") + .HasDatabaseName("IX_server_ban_hit_connection_id"); + + b.ToTable("server_ban_hit", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("server_role_ban_id"); + + b.Property("Address") + .HasColumnType("TEXT") + .HasColumnName("address"); + + b.Property("BanTime") + .HasColumnType("TEXT") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("banning_admin"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("Hidden") + .HasColumnType("INTEGER") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("reason"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("role_id"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("INTEGER") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_role_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_role_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_role_ban_round_id"); + + b.ToTable("server_role_ban", null, t => + { + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("role_unban_id"); + + b.Property("BanId") + .HasColumnType("INTEGER") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("TEXT") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_role_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_role_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("unban_id"); + + b.Property("BanId") + .HasColumnType("INTEGER") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("TEXT") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("trait_id"); + + b.Property("ProfileId") + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.Property("TraitName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("trait_name"); + + b.HasKey("Id") + .HasName("PK_trait"); + + b.HasIndex("ProfileId", "TraitName") + .IsUnique(); + + b.ToTable("trait", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.UploadedResourceLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("uploaded_resource_log_id"); + + b.Property("Data") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("data"); + + b.Property("Date") + .HasColumnType("TEXT") + .HasColumnName("date"); + + b.Property("Path") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("path"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_uploaded_resource_log"); + + b.ToTable("uploaded_resource_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Whitelist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_whitelist"); + + b.ToTable("whitelist", (string)null); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.Property("PlayersId") + .HasColumnType("INTEGER") + .HasColumnName("players_id"); + + b.Property("RoundsId") + .HasColumnType("INTEGER") + .HasColumnName("rounds_id"); + + b.HasKey("PlayersId", "RoundsId") + .HasName("PK_player_round"); + + b.HasIndex("RoundsId") + .HasDatabaseName("IX_player_round_rounds_id"); + + b.ToTable("player_round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.HasOne("Content.Server.Database.AdminRank", "AdminRank") + .WithMany("Admins") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_admin_rank_admin_rank_id"); + + b.Navigation("AdminRank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.HasOne("Content.Server.Database.Admin", "Admin") + .WithMany("Flags") + .HasForeignKey("AdminId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_flag_admin_admin_id"); + + b.Navigation("Admin"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany("AdminLogs") + .HasForeignKey("RoundId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_round_round_id"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminLogs") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_player_player_user_id"); + + b.HasOne("Content.Server.Database.AdminLog", "Log") + .WithMany("Players") + .HasForeignKey("RoundId", "LogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_admin_log_round_id_log_id"); + + b.Navigation("Log"); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminMessage", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminMessagesCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminMessagesDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminMessagesLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminMessagesReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_messages_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_messages_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminNote", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminNotesCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminNotesDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminNotesLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminNotesReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_notes_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_notes_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.HasOne("Content.Server.Database.AdminRank", "Rank") + .WithMany("Flags") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_rank_flag_admin_rank_admin_rank_id"); + + b.Navigation("Rank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminWatchlistsCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminWatchlistsDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminWatchlistsLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminWatchlistsReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_watchlists_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_watchlists_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Antags") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_antag_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.HasOne("Content.Server.Database.Server", "Server") + .WithMany("ConnectionLogs") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.SetNull) + .IsRequired() + .HasConstraintName("FK_connection_log_server_server_id"); + + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ConnectionLogId") + .HasColumnType("INTEGER") + .HasColumnName("connection_log_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ConnectionLogId"); + + b1.ToTable("connection_log"); + + b1.WithOwner() + .HasForeignKey("ConnectionLogId") + .HasConstraintName("FK_connection_log_connection_log_connection_log_id"); + }); + + b.Navigation("HWId"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Jobs") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_job_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.OwnsOne("Content.Server.Database.TypedHwid", "LastSeenHWId", b1 => + { + b1.Property("PlayerId") + .HasColumnType("INTEGER") + .HasColumnName("player_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("last_seen_hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("last_seen_hwid_type"); + + b1.HasKey("PlayerId"); + + b1.ToTable("player"); + + b1.WithOwner() + .HasForeignKey("PlayerId") + .HasConstraintName("FK_player_player_player_id"); + }); + + b.Navigation("LastSeenHWId"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.HasOne("Content.Server.Database.Preference", "Preference") + .WithMany("Profiles") + .HasForeignKey("PreferenceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_preference_preference_id"); + + b.Navigation("Preference"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadout", b => + { + b.HasOne("Content.Server.Database.ProfileLoadoutGroup", "ProfileLoadoutGroup") + .WithMany("Loadouts") + .HasForeignKey("ProfileLoadoutGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_loadout_profile_loadout_group_profile_loadout_group_id"); + + b.Navigation("ProfileLoadoutGroup"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.HasOne("Content.Server.Database.ProfileRoleLoadout", "ProfileRoleLoadout") + .WithMany("Groups") + .HasForeignKey("ProfileRoleLoadoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_loadout_group_profile_role_loadout_profile_role_loadout_id"); + + b.Navigation("ProfileRoleLoadout"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Loadouts") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_role_loadout_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b => + { + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("JobWhitelists") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_role_whitelists_player_player_user_id"); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.HasOne("Content.Server.Database.Server", "Server") + .WithMany("Rounds") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_round_server_server_id"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_ban_round_round_id"); + + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerBanId") + .HasColumnType("INTEGER") + .HasColumnName("server_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerBanId"); + + b1.ToTable("server_ban"); + + b1.WithOwner() + .HasForeignKey("ServerBanId") + .HasConstraintName("FK_server_ban_server_ban_server_ban_id"); + }); + + b.Navigation("CreatedBy"); + + b.Navigation("HWId"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithMany("BanHits") + .HasForeignKey("BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_server_ban_ban_id"); + + b.HasOne("Content.Server.Database.ConnectionLog", "Connection") + .WithMany("BanHits") + .HasForeignKey("ConnectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_connection_log_connection_id"); + + b.Navigation("Ban"); + + b.Navigation("Connection"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerRoleBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerRoleBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_role_ban_round_round_id"); + + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerRoleBanId") + .HasColumnType("INTEGER") + .HasColumnName("server_role_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerRoleBanId"); + + b1.ToTable("server_role_ban"); + + b1.WithOwner() + .HasForeignKey("ServerRoleBanId") + .HasConstraintName("FK_server_role_ban_server_role_ban_server_role_ban_id"); + }); + + b.Navigation("CreatedBy"); + + b.Navigation("HWId"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.HasOne("Content.Server.Database.ServerRoleBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerRoleUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_role_unban_server_role_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_unban_server_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Traits") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_trait_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.HasOne("Content.Server.Database.Player", null) + .WithMany() + .HasForeignKey("PlayersId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_player_players_id"); + + b.HasOne("Content.Server.Database.Round", null) + .WithMany() + .HasForeignKey("RoundsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_round_rounds_id"); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Navigation("Players"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Navigation("Admins"); + + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Navigation("BanHits"); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Navigation("AdminLogs"); + + b.Navigation("AdminMessagesCreated"); + + b.Navigation("AdminMessagesDeleted"); + + b.Navigation("AdminMessagesLastEdited"); + + b.Navigation("AdminMessagesReceived"); + + b.Navigation("AdminNotesCreated"); + + b.Navigation("AdminNotesDeleted"); + + b.Navigation("AdminNotesLastEdited"); + + b.Navigation("AdminNotesReceived"); + + b.Navigation("AdminServerBansCreated"); + + b.Navigation("AdminServerBansLastEdited"); + + b.Navigation("AdminServerRoleBansCreated"); + + b.Navigation("AdminServerRoleBansLastEdited"); + + b.Navigation("AdminWatchlistsCreated"); + + b.Navigation("AdminWatchlistsDeleted"); + + b.Navigation("AdminWatchlistsLastEdited"); + + b.Navigation("AdminWatchlistsReceived"); + + b.Navigation("JobWhitelists"); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Navigation("Profiles"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Navigation("Antags"); + + b.Navigation("Jobs"); + + b.Navigation("Loadouts"); + + b.Navigation("Traits"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.Navigation("Loadouts"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.Navigation("Groups"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Navigation("AdminLogs"); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Navigation("ConnectionLogs"); + + b.Navigation("Rounds"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.Navigation("BanHits"); + + b.Navigation("Unban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.Navigation("Unban"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Content.Server.Database/Migrations/Sqlite/20241111170107_ModernHwid.cs b/Content.Server.Database/Migrations/Sqlite/20241111170107_ModernHwid.cs new file mode 100644 index 000000000000..97b5dafd03ff --- /dev/null +++ b/Content.Server.Database/Migrations/Sqlite/20241111170107_ModernHwid.cs @@ -0,0 +1,62 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Content.Server.Database.Migrations.Sqlite +{ + /// + public partial class ModernHwid : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "hwid_type", + table: "server_role_ban", + type: "INTEGER", + nullable: true, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "hwid_type", + table: "server_ban", + type: "INTEGER", + nullable: true, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "last_seen_hwid_type", + table: "player", + type: "INTEGER", + nullable: true, + defaultValue: 0); + + migrationBuilder.AddColumn( + name: "hwid_type", + table: "connection_log", + type: "INTEGER", + nullable: true, + defaultValue: 0); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "hwid_type", + table: "server_role_ban"); + + migrationBuilder.DropColumn( + name: "hwid_type", + table: "server_ban"); + + migrationBuilder.DropColumn( + name: "last_seen_hwid_type", + table: "player"); + + migrationBuilder.DropColumn( + name: "hwid_type", + table: "connection_log"); + } + } +} diff --git a/Content.Server.Database/Migrations/Sqlite/20241111193602_ConnectionTrust.Designer.cs b/Content.Server.Database/Migrations/Sqlite/20241111193602_ConnectionTrust.Designer.cs new file mode 100644 index 000000000000..bd4e20a464b2 --- /dev/null +++ b/Content.Server.Database/Migrations/Sqlite/20241111193602_ConnectionTrust.Designer.cs @@ -0,0 +1,1999 @@ +// +using System; +using Content.Server.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Content.Server.Database.Migrations.Sqlite +{ + [DbContext(typeof(SqliteServerDbContext))] + [Migration("20241111193602_ConnectionTrust")] + partial class ConnectionTrust + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "8.0.0"); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.Property("AdminRankId") + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_id"); + + b.Property("Title") + .HasColumnType("TEXT") + .HasColumnName("title"); + + b.HasKey("UserId") + .HasName("PK_admin"); + + b.HasIndex("AdminRankId") + .HasDatabaseName("IX_admin_admin_rank_id"); + + b.ToTable("admin", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_flag_id"); + + b.Property("AdminId") + .HasColumnType("TEXT") + .HasColumnName("admin_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("flag"); + + b.Property("Negative") + .HasColumnType("INTEGER") + .HasColumnName("negative"); + + b.HasKey("Id") + .HasName("PK_admin_flag"); + + b.HasIndex("AdminId") + .HasDatabaseName("IX_admin_flag_admin_id"); + + b.HasIndex("Flag", "AdminId") + .IsUnique(); + + b.ToTable("admin_flag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Id") + .HasColumnType("INTEGER") + .HasColumnName("admin_log_id"); + + b.Property("Date") + .HasColumnType("TEXT") + .HasColumnName("date"); + + b.Property("Impact") + .HasColumnType("INTEGER") + .HasColumnName("impact"); + + b.Property("Json") + .IsRequired() + .HasColumnType("jsonb") + .HasColumnName("json"); + + b.Property("Message") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("Type") + .HasColumnType("INTEGER") + .HasColumnName("type"); + + b.HasKey("RoundId", "Id") + .HasName("PK_admin_log"); + + b.HasIndex("Date"); + + b.HasIndex("Type") + .HasDatabaseName("IX_admin_log_type"); + + b.ToTable("admin_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("LogId") + .HasColumnType("INTEGER") + .HasColumnName("log_id"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.HasKey("RoundId", "LogId", "PlayerUserId") + .HasName("PK_admin_log_player"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_log_player_player_user_id"); + + b.ToTable("admin_log_player", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_messages_id"); + + b.Property("CreatedAt") + .HasColumnType("TEXT") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("TEXT") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("INTEGER") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("TEXT") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("TEXT") + .HasColumnName("deleted_by_id"); + + b.Property("Dismissed") + .HasColumnType("INTEGER") + .HasColumnName("dismissed"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Seen") + .HasColumnType("INTEGER") + .HasColumnName("seen"); + + b.HasKey("Id") + .HasName("PK_admin_messages"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_messages_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_messages_round_id"); + + b.ToTable("admin_messages", null, t => + { + t.HasCheckConstraint("NotDismissedAndSeen", "NOT dismissed OR seen"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.AdminNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_notes_id"); + + b.Property("CreatedAt") + .HasColumnType("TEXT") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("TEXT") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("INTEGER") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("TEXT") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("TEXT") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Secret") + .HasColumnType("INTEGER") + .HasColumnName("secret"); + + b.Property("Severity") + .HasColumnType("INTEGER") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_admin_notes"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_notes_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_notes_round_id"); + + b.ToTable("admin_notes", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_id"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_admin_rank"); + + b.ToTable("admin_rank", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_flag_id"); + + b.Property("AdminRankId") + .HasColumnType("INTEGER") + .HasColumnName("admin_rank_id"); + + b.Property("Flag") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("flag"); + + b.HasKey("Id") + .HasName("PK_admin_rank_flag"); + + b.HasIndex("AdminRankId"); + + b.HasIndex("Flag", "AdminRankId") + .IsUnique(); + + b.ToTable("admin_rank_flag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("admin_watchlists_id"); + + b.Property("CreatedAt") + .HasColumnType("TEXT") + .HasColumnName("created_at"); + + b.Property("CreatedById") + .HasColumnType("TEXT") + .HasColumnName("created_by_id"); + + b.Property("Deleted") + .HasColumnType("INTEGER") + .HasColumnName("deleted"); + + b.Property("DeletedAt") + .HasColumnType("TEXT") + .HasColumnName("deleted_at"); + + b.Property("DeletedById") + .HasColumnType("TEXT") + .HasColumnName("deleted_by_id"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("LastEditedAt") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(4096) + .HasColumnType("TEXT") + .HasColumnName("message"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.HasKey("Id") + .HasName("PK_admin_watchlists"); + + b.HasIndex("CreatedById"); + + b.HasIndex("DeletedById"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_admin_watchlists_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_admin_watchlists_round_id"); + + b.ToTable("admin_watchlists", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("antag_id"); + + b.Property("AntagName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("antag_name"); + + b.Property("ProfileId") + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_antag"); + + b.HasIndex("ProfileId", "AntagName") + .IsUnique(); + + b.ToTable("antag", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.AssignedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("assigned_user_id_id"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("PK_assigned_user_id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.HasIndex("UserName") + .IsUnique(); + + b.ToTable("assigned_user_id", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.BanTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("ban_template_id"); + + b.Property("AutoDelete") + .HasColumnType("INTEGER") + .HasColumnName("auto_delete"); + + b.Property("ExemptFlags") + .HasColumnType("INTEGER") + .HasColumnName("exempt_flags"); + + b.Property("Hidden") + .HasColumnType("INTEGER") + .HasColumnName("hidden"); + + b.Property("Length") + .HasColumnType("TEXT") + .HasColumnName("length"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("reason"); + + b.Property("Severity") + .HasColumnType("INTEGER") + .HasColumnName("severity"); + + b.Property("Title") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("title"); + + b.HasKey("Id") + .HasName("PK_ban_template"); + + b.ToTable("ban_template", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Blacklist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_blacklist"); + + b.ToTable("blacklist", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("connection_log_id"); + + b.Property("Address") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("address"); + + b.Property("Denied") + .HasColumnType("INTEGER") + .HasColumnName("denied"); + + b.Property("ServerId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("server_id"); + + b.Property("Time") + .HasColumnType("TEXT") + .HasColumnName("time"); + + b.Property("Trust") + .HasColumnType("REAL") + .HasColumnName("trust"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.Property("UserName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("user_name"); + + b.HasKey("Id") + .HasName("PK_connection_log"); + + b.HasIndex("ServerId") + .HasDatabaseName("IX_connection_log_server_id"); + + b.HasIndex("Time"); + + b.HasIndex("UserId"); + + b.ToTable("connection_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("job_id"); + + b.Property("JobName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("job_name"); + + b.Property("Priority") + .HasColumnType("INTEGER") + .HasColumnName("priority"); + + b.Property("ProfileId") + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.HasKey("Id") + .HasName("PK_job"); + + b.HasIndex("ProfileId"); + + b.HasIndex("ProfileId", "JobName") + .IsUnique(); + + b.HasIndex(new[] { "ProfileId" }, "IX_job_one_high_priority") + .IsUnique() + .HasFilter("priority = 3"); + + b.ToTable("job", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.PlayTime", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("play_time_id"); + + b.Property("PlayerId") + .HasColumnType("TEXT") + .HasColumnName("player_id"); + + b.Property("TimeSpent") + .HasColumnType("TEXT") + .HasColumnName("time_spent"); + + b.Property("Tracker") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("tracker"); + + b.HasKey("Id") + .HasName("PK_play_time"); + + b.HasIndex("PlayerId", "Tracker") + .IsUnique(); + + b.ToTable("play_time", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("player_id"); + + b.Property("FirstSeenTime") + .HasColumnType("TEXT") + .HasColumnName("first_seen_time"); + + b.Property("LastReadRules") + .HasColumnType("TEXT") + .HasColumnName("last_read_rules"); + + b.Property("LastSeenAddress") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_seen_address"); + + b.Property("LastSeenTime") + .HasColumnType("TEXT") + .HasColumnName("last_seen_time"); + + b.Property("LastSeenUserName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("last_seen_user_name"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_player"); + + b.HasAlternateKey("UserId") + .HasName("ak_player_user_id"); + + b.HasIndex("LastSeenUserName"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("player", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("preference_id"); + + b.Property("AdminOOCColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("admin_ooc_color"); + + b.Property("SelectedCharacterSlot") + .HasColumnType("INTEGER") + .HasColumnName("selected_character_slot"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_preference"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("preference", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.Property("Age") + .HasColumnType("INTEGER") + .HasColumnName("age"); + + b.Property("CharacterName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("char_name"); + + b.Property("EyeColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("eye_color"); + + b.Property("FacialHairColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("facial_hair_color"); + + b.Property("FacialHairName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("facial_hair_name"); + + b.Property("FlavorText") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("flavor_text"); + + b.Property("Gender") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("gender"); + + b.Property("HairColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("hair_color"); + + b.Property("HairName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("hair_name"); + + b.Property("Markings") + .HasColumnType("jsonb") + .HasColumnName("markings"); + + b.Property("PreferenceId") + .HasColumnType("INTEGER") + .HasColumnName("preference_id"); + + b.Property("PreferenceUnavailable") + .HasColumnType("INTEGER") + .HasColumnName("pref_unavailable"); + + b.Property("Sex") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("sex"); + + b.Property("SkinColor") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("skin_color"); + + b.Property("Slot") + .HasColumnType("INTEGER") + .HasColumnName("slot"); + + b.Property("SpawnPriority") + .HasColumnType("INTEGER") + .HasColumnName("spawn_priority"); + + b.Property("Species") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("species"); + + b.HasKey("Id") + .HasName("PK_profile"); + + b.HasIndex("PreferenceId") + .HasDatabaseName("IX_profile_preference_id"); + + b.HasIndex("Slot", "PreferenceId") + .IsUnique(); + + b.ToTable("profile", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("profile_loadout_id"); + + b.Property("LoadoutName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("loadout_name"); + + b.Property("ProfileLoadoutGroupId") + .HasColumnType("INTEGER") + .HasColumnName("profile_loadout_group_id"); + + b.HasKey("Id") + .HasName("PK_profile_loadout"); + + b.HasIndex("ProfileLoadoutGroupId"); + + b.ToTable("profile_loadout", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("profile_loadout_group_id"); + + b.Property("GroupName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("group_name"); + + b.Property("ProfileRoleLoadoutId") + .HasColumnType("INTEGER") + .HasColumnName("profile_role_loadout_id"); + + b.HasKey("Id") + .HasName("PK_profile_loadout_group"); + + b.HasIndex("ProfileRoleLoadoutId"); + + b.ToTable("profile_loadout_group", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("profile_role_loadout_id"); + + b.Property("ProfileId") + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.Property("RoleName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("role_name"); + + b.HasKey("Id") + .HasName("PK_profile_role_loadout"); + + b.HasIndex("ProfileId"); + + b.ToTable("profile_role_loadout", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b => + { + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("RoleId") + .HasColumnType("TEXT") + .HasColumnName("role_id"); + + b.HasKey("PlayerUserId", "RoleId") + .HasName("PK_role_whitelists"); + + b.ToTable("role_whitelists", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("ServerId") + .HasColumnType("INTEGER") + .HasColumnName("server_id"); + + b.Property("StartDate") + .HasColumnType("TEXT") + .HasColumnName("start_date"); + + b.HasKey("Id") + .HasName("PK_round"); + + b.HasIndex("ServerId") + .HasDatabaseName("IX_round_server_id"); + + b.HasIndex("StartDate"); + + b.ToTable("round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("server_id"); + + b.Property("Name") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("PK_server"); + + b.ToTable("server", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("server_ban_id"); + + b.Property("Address") + .HasColumnType("TEXT") + .HasColumnName("address"); + + b.Property("AutoDelete") + .HasColumnType("INTEGER") + .HasColumnName("auto_delete"); + + b.Property("BanTime") + .HasColumnType("TEXT") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("banning_admin"); + + b.Property("ExemptFlags") + .HasColumnType("INTEGER") + .HasColumnName("exempt_flags"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("Hidden") + .HasColumnType("INTEGER") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("reason"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("INTEGER") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_ban_round_id"); + + b.ToTable("server_ban", null, t => + { + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanExemption", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.Property("Flags") + .HasColumnType("INTEGER") + .HasColumnName("flags"); + + b.HasKey("UserId") + .HasName("PK_server_ban_exemption"); + + b.ToTable("server_ban_exemption", null, t => + { + t.HasCheckConstraint("FlagsNotZero", "flags != 0"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("server_ban_hit_id"); + + b.Property("BanId") + .HasColumnType("INTEGER") + .HasColumnName("ban_id"); + + b.Property("ConnectionId") + .HasColumnType("INTEGER") + .HasColumnName("connection_id"); + + b.HasKey("Id") + .HasName("PK_server_ban_hit"); + + b.HasIndex("BanId") + .HasDatabaseName("IX_server_ban_hit_ban_id"); + + b.HasIndex("ConnectionId") + .HasDatabaseName("IX_server_ban_hit_connection_id"); + + b.ToTable("server_ban_hit", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("server_role_ban_id"); + + b.Property("Address") + .HasColumnType("TEXT") + .HasColumnName("address"); + + b.Property("BanTime") + .HasColumnType("TEXT") + .HasColumnName("ban_time"); + + b.Property("BanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("banning_admin"); + + b.Property("ExpirationTime") + .HasColumnType("TEXT") + .HasColumnName("expiration_time"); + + b.Property("Hidden") + .HasColumnType("INTEGER") + .HasColumnName("hidden"); + + b.Property("LastEditedAt") + .HasColumnType("TEXT") + .HasColumnName("last_edited_at"); + + b.Property("LastEditedById") + .HasColumnType("TEXT") + .HasColumnName("last_edited_by_id"); + + b.Property("PlayerUserId") + .HasColumnType("TEXT") + .HasColumnName("player_user_id"); + + b.Property("PlaytimeAtNote") + .HasColumnType("TEXT") + .HasColumnName("playtime_at_note"); + + b.Property("Reason") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("reason"); + + b.Property("RoleId") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("role_id"); + + b.Property("RoundId") + .HasColumnType("INTEGER") + .HasColumnName("round_id"); + + b.Property("Severity") + .HasColumnType("INTEGER") + .HasColumnName("severity"); + + b.HasKey("Id") + .HasName("PK_server_role_ban"); + + b.HasIndex("Address"); + + b.HasIndex("BanningAdmin"); + + b.HasIndex("LastEditedById"); + + b.HasIndex("PlayerUserId") + .HasDatabaseName("IX_server_role_ban_player_user_id"); + + b.HasIndex("RoundId") + .HasDatabaseName("IX_server_role_ban_round_id"); + + b.ToTable("server_role_ban", null, t => + { + t.HasCheckConstraint("HaveEitherAddressOrUserIdOrHWId", "address IS NOT NULL OR player_user_id IS NOT NULL OR hwid IS NOT NULL"); + }); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("role_unban_id"); + + b.Property("BanId") + .HasColumnType("INTEGER") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("TEXT") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_role_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_role_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("unban_id"); + + b.Property("BanId") + .HasColumnType("INTEGER") + .HasColumnName("ban_id"); + + b.Property("UnbanTime") + .HasColumnType("TEXT") + .HasColumnName("unban_time"); + + b.Property("UnbanningAdmin") + .HasColumnType("TEXT") + .HasColumnName("unbanning_admin"); + + b.HasKey("Id") + .HasName("PK_server_unban"); + + b.HasIndex("BanId") + .IsUnique(); + + b.ToTable("server_unban", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("trait_id"); + + b.Property("ProfileId") + .HasColumnType("INTEGER") + .HasColumnName("profile_id"); + + b.Property("TraitName") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("trait_name"); + + b.HasKey("Id") + .HasName("PK_trait"); + + b.HasIndex("ProfileId", "TraitName") + .IsUnique(); + + b.ToTable("trait", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.UploadedResourceLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasColumnName("uploaded_resource_log_id"); + + b.Property("Data") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("data"); + + b.Property("Date") + .HasColumnType("TEXT") + .HasColumnName("date"); + + b.Property("Path") + .IsRequired() + .HasColumnType("TEXT") + .HasColumnName("path"); + + b.Property("UserId") + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("Id") + .HasName("PK_uploaded_resource_log"); + + b.ToTable("uploaded_resource_log", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Whitelist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_whitelist"); + + b.ToTable("whitelist", (string)null); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.Property("PlayersId") + .HasColumnType("INTEGER") + .HasColumnName("players_id"); + + b.Property("RoundsId") + .HasColumnType("INTEGER") + .HasColumnName("rounds_id"); + + b.HasKey("PlayersId", "RoundsId") + .HasName("PK_player_round"); + + b.HasIndex("RoundsId") + .HasDatabaseName("IX_player_round_rounds_id"); + + b.ToTable("player_round", (string)null); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.HasOne("Content.Server.Database.AdminRank", "AdminRank") + .WithMany("Admins") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_admin_rank_admin_rank_id"); + + b.Navigation("AdminRank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminFlag", b => + { + b.HasOne("Content.Server.Database.Admin", "Admin") + .WithMany("Flags") + .HasForeignKey("AdminId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_flag_admin_admin_id"); + + b.Navigation("Admin"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany("AdminLogs") + .HasForeignKey("RoundId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_round_round_id"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLogPlayer", b => + { + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminLogs") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_player_player_user_id"); + + b.HasOne("Content.Server.Database.AdminLog", "Log") + .WithMany("Players") + .HasForeignKey("RoundId", "LogId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_log_player_admin_log_round_id_log_id"); + + b.Navigation("Log"); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminMessage", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminMessagesCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminMessagesDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminMessagesLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_messages_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminMessagesReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_messages_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_messages_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminNote", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminNotesCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminNotesDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminNotesLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_notes_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminNotesReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_notes_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_notes_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRankFlag", b => + { + b.HasOne("Content.Server.Database.AdminRank", "Rank") + .WithMany("Flags") + .HasForeignKey("AdminRankId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_admin_rank_flag_admin_rank_admin_rank_id"); + + b.Navigation("Rank"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminWatchlist", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminWatchlistsCreated") + .HasForeignKey("CreatedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_created_by_id"); + + b.HasOne("Content.Server.Database.Player", "DeletedBy") + .WithMany("AdminWatchlistsDeleted") + .HasForeignKey("DeletedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_deleted_by_id"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminWatchlistsLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_admin_watchlists_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("AdminWatchlistsReceived") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("FK_admin_watchlists_player_player_user_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_admin_watchlists_round_round_id"); + + b.Navigation("CreatedBy"); + + b.Navigation("DeletedBy"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Player"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.Antag", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Antags") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_antag_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.HasOne("Content.Server.Database.Server", "Server") + .WithMany("ConnectionLogs") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.SetNull) + .IsRequired() + .HasConstraintName("FK_connection_log_server_server_id"); + + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ConnectionLogId") + .HasColumnType("INTEGER") + .HasColumnName("connection_log_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ConnectionLogId"); + + b1.ToTable("connection_log"); + + b1.WithOwner() + .HasForeignKey("ConnectionLogId") + .HasConstraintName("FK_connection_log_connection_log_connection_log_id"); + }); + + b.Navigation("HWId"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Content.Server.Database.Job", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Jobs") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_job_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.OwnsOne("Content.Server.Database.TypedHwid", "LastSeenHWId", b1 => + { + b1.Property("PlayerId") + .HasColumnType("INTEGER") + .HasColumnName("player_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("last_seen_hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("last_seen_hwid_type"); + + b1.HasKey("PlayerId"); + + b1.ToTable("player"); + + b1.WithOwner() + .HasForeignKey("PlayerId") + .HasConstraintName("FK_player_player_player_id"); + }); + + b.Navigation("LastSeenHWId"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.HasOne("Content.Server.Database.Preference", "Preference") + .WithMany("Profiles") + .HasForeignKey("PreferenceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_preference_preference_id"); + + b.Navigation("Preference"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadout", b => + { + b.HasOne("Content.Server.Database.ProfileLoadoutGroup", "ProfileLoadoutGroup") + .WithMany("Loadouts") + .HasForeignKey("ProfileLoadoutGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_loadout_profile_loadout_group_profile_loadout_group_id"); + + b.Navigation("ProfileLoadoutGroup"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.HasOne("Content.Server.Database.ProfileRoleLoadout", "ProfileRoleLoadout") + .WithMany("Groups") + .HasForeignKey("ProfileRoleLoadoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_loadout_group_profile_role_loadout_profile_role_loadout_id"); + + b.Navigation("ProfileRoleLoadout"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Loadouts") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_profile_role_loadout_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("Content.Server.Database.RoleWhitelist", b => + { + b.HasOne("Content.Server.Database.Player", "Player") + .WithMany("JobWhitelists") + .HasForeignKey("PlayerUserId") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_role_whitelists_player_player_user_id"); + + b.Navigation("Player"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.HasOne("Content.Server.Database.Server", "Server") + .WithMany("Rounds") + .HasForeignKey("ServerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_round_server_server_id"); + + b.Navigation("Server"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_ban_round_round_id"); + + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerBanId") + .HasColumnType("INTEGER") + .HasColumnName("server_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerBanId"); + + b1.ToTable("server_ban"); + + b1.WithOwner() + .HasForeignKey("ServerBanId") + .HasConstraintName("FK_server_ban_server_ban_server_ban_id"); + }); + + b.Navigation("CreatedBy"); + + b.Navigation("HWId"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBanHit", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithMany("BanHits") + .HasForeignKey("BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_server_ban_ban_id"); + + b.HasOne("Content.Server.Database.ConnectionLog", "Connection") + .WithMany("BanHits") + .HasForeignKey("ConnectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_ban_hit_connection_log_connection_id"); + + b.Navigation("Ban"); + + b.Navigation("Connection"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.HasOne("Content.Server.Database.Player", "CreatedBy") + .WithMany("AdminServerRoleBansCreated") + .HasForeignKey("BanningAdmin") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_banning_admin"); + + b.HasOne("Content.Server.Database.Player", "LastEditedBy") + .WithMany("AdminServerRoleBansLastEdited") + .HasForeignKey("LastEditedById") + .HasPrincipalKey("UserId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("FK_server_role_ban_player_last_edited_by_id"); + + b.HasOne("Content.Server.Database.Round", "Round") + .WithMany() + .HasForeignKey("RoundId") + .HasConstraintName("FK_server_role_ban_round_round_id"); + + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerRoleBanId") + .HasColumnType("INTEGER") + .HasColumnName("server_role_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerRoleBanId"); + + b1.ToTable("server_role_ban"); + + b1.WithOwner() + .HasForeignKey("ServerRoleBanId") + .HasConstraintName("FK_server_role_ban_server_role_ban_server_role_ban_id"); + }); + + b.Navigation("CreatedBy"); + + b.Navigation("HWId"); + + b.Navigation("LastEditedBy"); + + b.Navigation("Round"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleUnban", b => + { + b.HasOne("Content.Server.Database.ServerRoleBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerRoleUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_role_unban_server_role_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerUnban", b => + { + b.HasOne("Content.Server.Database.ServerBan", "Ban") + .WithOne("Unban") + .HasForeignKey("Content.Server.Database.ServerUnban", "BanId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_server_unban_server_ban_ban_id"); + + b.Navigation("Ban"); + }); + + modelBuilder.Entity("Content.Server.Database.Trait", b => + { + b.HasOne("Content.Server.Database.Profile", "Profile") + .WithMany("Traits") + .HasForeignKey("ProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_trait_profile_profile_id"); + + b.Navigation("Profile"); + }); + + modelBuilder.Entity("PlayerRound", b => + { + b.HasOne("Content.Server.Database.Player", null) + .WithMany() + .HasForeignKey("PlayersId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_player_players_id"); + + b.HasOne("Content.Server.Database.Round", null) + .WithMany() + .HasForeignKey("RoundsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("FK_player_round_round_rounds_id"); + }); + + modelBuilder.Entity("Content.Server.Database.Admin", b => + { + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminLog", b => + { + b.Navigation("Players"); + }); + + modelBuilder.Entity("Content.Server.Database.AdminRank", b => + { + b.Navigation("Admins"); + + b.Navigation("Flags"); + }); + + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => + { + b.Navigation("BanHits"); + }); + + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.Navigation("AdminLogs"); + + b.Navigation("AdminMessagesCreated"); + + b.Navigation("AdminMessagesDeleted"); + + b.Navigation("AdminMessagesLastEdited"); + + b.Navigation("AdminMessagesReceived"); + + b.Navigation("AdminNotesCreated"); + + b.Navigation("AdminNotesDeleted"); + + b.Navigation("AdminNotesLastEdited"); + + b.Navigation("AdminNotesReceived"); + + b.Navigation("AdminServerBansCreated"); + + b.Navigation("AdminServerBansLastEdited"); + + b.Navigation("AdminServerRoleBansCreated"); + + b.Navigation("AdminServerRoleBansLastEdited"); + + b.Navigation("AdminWatchlistsCreated"); + + b.Navigation("AdminWatchlistsDeleted"); + + b.Navigation("AdminWatchlistsLastEdited"); + + b.Navigation("AdminWatchlistsReceived"); + + b.Navigation("JobWhitelists"); + }); + + modelBuilder.Entity("Content.Server.Database.Preference", b => + { + b.Navigation("Profiles"); + }); + + modelBuilder.Entity("Content.Server.Database.Profile", b => + { + b.Navigation("Antags"); + + b.Navigation("Jobs"); + + b.Navigation("Loadouts"); + + b.Navigation("Traits"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileLoadoutGroup", b => + { + b.Navigation("Loadouts"); + }); + + modelBuilder.Entity("Content.Server.Database.ProfileRoleLoadout", b => + { + b.Navigation("Groups"); + }); + + modelBuilder.Entity("Content.Server.Database.Round", b => + { + b.Navigation("AdminLogs"); + }); + + modelBuilder.Entity("Content.Server.Database.Server", b => + { + b.Navigation("ConnectionLogs"); + + b.Navigation("Rounds"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerBan", b => + { + b.Navigation("BanHits"); + + b.Navigation("Unban"); + }); + + modelBuilder.Entity("Content.Server.Database.ServerRoleBan", b => + { + b.Navigation("Unban"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Content.Server.Database/Migrations/Sqlite/20241111193602_ConnectionTrust.cs b/Content.Server.Database/Migrations/Sqlite/20241111193602_ConnectionTrust.cs new file mode 100644 index 000000000000..3a7fd784e16b --- /dev/null +++ b/Content.Server.Database/Migrations/Sqlite/20241111193602_ConnectionTrust.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Content.Server.Database.Migrations.Sqlite +{ + /// + public partial class ConnectionTrust : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "trust", + table: "connection_log", + type: "REAL", + nullable: false, + defaultValue: 0f); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "trust", + table: "connection_log"); + } + } +} diff --git a/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs b/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs index 02d441630270..c63127874ccc 100644 --- a/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs +++ b/Content.Server.Database/Migrations/Sqlite/SqliteServerDbContextModelSnapshot.cs @@ -483,19 +483,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("assigned_user_id", (string)null); }); - modelBuilder.Entity("Content.Server.Database.Blacklist", - b => - { - b.Property("UserId") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT") - .HasColumnName("user_id"); - - b.HasKey("UserId") - .HasName("PK_blacklist"); - - b.ToTable("blacklist", (string) null); - }); modelBuilder.Entity("Content.Server.Database.BanTemplate", b => { b.Property("Id") @@ -539,6 +526,19 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.ToTable("ban_template", (string)null); }); + modelBuilder.Entity("Content.Server.Database.Blacklist", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("TEXT") + .HasColumnName("user_id"); + + b.HasKey("UserId") + .HasName("PK_blacklist"); + + b.ToTable("blacklist", (string)null); + }); + modelBuilder.Entity("Content.Server.Database.ConnectionLog", b => { b.Property("Id") @@ -555,10 +555,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("INTEGER") .HasColumnName("denied"); - b.Property("HWId") - .HasColumnType("BLOB") - .HasColumnName("hwid"); - b.Property("ServerId") .ValueGeneratedOnAdd() .HasColumnType("INTEGER") @@ -569,6 +565,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("TEXT") .HasColumnName("time"); + b.Property("Trust") + .HasColumnType("REAL") + .HasColumnName("trust"); + b.Property("UserId") .HasColumnType("TEXT") .HasColumnName("user_id"); @@ -675,10 +675,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("TEXT") .HasColumnName("last_seen_address"); - b.Property("LastSeenHWId") - .HasColumnType("BLOB") - .HasColumnName("last_seen_hwid"); - b.Property("LastSeenTime") .HasColumnType("TEXT") .HasColumnName("last_seen_time"); @@ -996,10 +992,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("TEXT") .HasColumnName("expiration_time"); - b.Property("HWId") - .HasColumnType("BLOB") - .HasColumnName("hwid"); - b.Property("Hidden") .HasColumnType("INTEGER") .HasColumnName("hidden"); @@ -1124,10 +1116,6 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("TEXT") .HasColumnName("expiration_time"); - b.Property("HWId") - .HasColumnType("BLOB") - .HasColumnName("hwid"); - b.Property("Hidden") .HasColumnType("INTEGER") .HasColumnName("hidden"); @@ -1559,6 +1547,34 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasConstraintName("FK_connection_log_server_server_id"); + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ConnectionLogId") + .HasColumnType("INTEGER") + .HasColumnName("connection_log_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ConnectionLogId"); + + b1.ToTable("connection_log"); + + b1.WithOwner() + .HasForeignKey("ConnectionLogId") + .HasConstraintName("FK_connection_log_connection_log_connection_log_id"); + }); + + b.Navigation("HWId"); + b.Navigation("Server"); }); @@ -1574,6 +1590,37 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Profile"); }); + modelBuilder.Entity("Content.Server.Database.Player", b => + { + b.OwnsOne("Content.Server.Database.TypedHwid", "LastSeenHWId", b1 => + { + b1.Property("PlayerId") + .HasColumnType("INTEGER") + .HasColumnName("player_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("last_seen_hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("last_seen_hwid_type"); + + b1.HasKey("PlayerId"); + + b1.ToTable("player"); + + b1.WithOwner() + .HasForeignKey("PlayerId") + .HasConstraintName("FK_player_player_player_id"); + }); + + b.Navigation("LastSeenHWId"); + }); + modelBuilder.Entity("Content.Server.Database.Profile", b => { b.HasOne("Content.Server.Database.Preference", "Preference") @@ -1668,8 +1715,36 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasForeignKey("RoundId") .HasConstraintName("FK_server_ban_round_round_id"); + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerBanId") + .HasColumnType("INTEGER") + .HasColumnName("server_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerBanId"); + + b1.ToTable("server_ban"); + + b1.WithOwner() + .HasForeignKey("ServerBanId") + .HasConstraintName("FK_server_ban_server_ban_server_ban_id"); + }); + b.Navigation("CreatedBy"); + b.Navigation("HWId"); + b.Navigation("LastEditedBy"); b.Navigation("Round"); @@ -1717,8 +1792,36 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasForeignKey("RoundId") .HasConstraintName("FK_server_role_ban_round_round_id"); + b.OwnsOne("Content.Server.Database.TypedHwid", "HWId", b1 => + { + b1.Property("ServerRoleBanId") + .HasColumnType("INTEGER") + .HasColumnName("server_role_ban_id"); + + b1.Property("Hwid") + .IsRequired() + .HasColumnType("BLOB") + .HasColumnName("hwid"); + + b1.Property("Type") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0) + .HasColumnName("hwid_type"); + + b1.HasKey("ServerRoleBanId"); + + b1.ToTable("server_role_ban"); + + b1.WithOwner() + .HasForeignKey("ServerRoleBanId") + .HasConstraintName("FK_server_role_ban_server_role_ban_server_role_ban_id"); + }); + b.Navigation("CreatedBy"); + b.Navigation("HWId"); + b.Navigation("LastEditedBy"); b.Navigation("Round"); diff --git a/Content.Server.Database/Model.cs b/Content.Server.Database/Model.cs index 00b3cfea0324..9190475b153c 100644 --- a/Content.Server.Database/Model.cs +++ b/Content.Server.Database/Model.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Net; using System.Text.Json; @@ -327,6 +329,47 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasForeignKey(w => w.PlayerUserId) .HasPrincipalKey(p => p.UserId) .OnDelete(DeleteBehavior.Cascade); + + // Changes for modern HWID integration + modelBuilder.Entity() + .OwnsOne(p => p.LastSeenHWId) + .Property(p => p.Hwid) + .HasColumnName("last_seen_hwid"); + + modelBuilder.Entity() + .OwnsOne(p => p.LastSeenHWId) + .Property(p => p.Type) + .HasDefaultValue(HwidType.Legacy); + + modelBuilder.Entity() + .OwnsOne(p => p.HWId) + .Property(p => p.Hwid) + .HasColumnName("hwid"); + + modelBuilder.Entity() + .OwnsOne(p => p.HWId) + .Property(p => p.Type) + .HasDefaultValue(HwidType.Legacy); + + modelBuilder.Entity() + .OwnsOne(p => p.HWId) + .Property(p => p.Hwid) + .HasColumnName("hwid"); + + modelBuilder.Entity() + .OwnsOne(p => p.HWId) + .Property(p => p.Type) + .HasDefaultValue(HwidType.Legacy); + + modelBuilder.Entity() + .OwnsOne(p => p.HWId) + .Property(p => p.Hwid) + .HasColumnName("hwid"); + + modelBuilder.Entity() + .OwnsOne(p => p.HWId) + .Property(p => p.Type) + .HasDefaultValue(HwidType.Legacy); } public virtual IQueryable SearchLogs(IQueryable query, string searchText) @@ -519,7 +562,7 @@ public class Player public string LastSeenUserName { get; set; } = null!; public DateTime LastSeenTime { get; set; } public IPAddress LastSeenAddress { get; set; } = null!; - public byte[]? LastSeenHWId { get; set; } + public TypedHwid? LastSeenHWId { get; set; } // Data that changes with each round public List Rounds { get; set; } = null!; @@ -668,7 +711,7 @@ public interface IBanCommon where TUnban : IUnbanCommon int Id { get; set; } Guid? PlayerUserId { get; set; } NpgsqlInet? Address { get; set; } - byte[]? HWId { get; set; } + TypedHwid? HWId { get; set; } DateTime BanTime { get; set; } DateTime? ExpirationTime { get; set; } string Reason { get; set; } @@ -753,7 +796,7 @@ public class ServerBan : IBanCommon /// /// Hardware ID of the banned player. /// - public byte[]? HWId { get; set; } + public TypedHwid? HWId { get; set; } /// /// The time when the ban was applied by an administrator. @@ -891,7 +934,7 @@ public class ConnectionLog public DateTime Time { get; set; } public IPAddress Address { get; set; } = null!; - public byte[]? HWId { get; set; } + public TypedHwid? HWId { get; set; } public ConnectionDenyReason? Denied { get; set; } @@ -908,6 +951,8 @@ public class ConnectionLog public List BanHits { get; set; } = null!; public Server Server { get; set; } = null!; + + public float Trust { get; set; } } public enum ConnectionDenyReason : byte @@ -945,7 +990,7 @@ public sealed class ServerRoleBan : IBanCommon public Guid? PlayerUserId { get; set; } [Required] public TimeSpan PlaytimeAtNote { get; set; } public NpgsqlInet? Address { get; set; } - public byte[]? HWId { get; set; } + public TypedHwid? HWId { get; set; } public DateTime BanTime { get; set; } @@ -1206,4 +1251,37 @@ public sealed class BanTemplate /// public bool Hidden { get; set; } } + + /// + /// A hardware ID value together with its . + /// + /// + [Owned] + public sealed class TypedHwid + { + public byte[] Hwid { get; set; } = default!; + public HwidType Type { get; set; } + + [return: NotNullIfNotNull(nameof(immutable))] + public static implicit operator TypedHwid?(ImmutableTypedHwid? immutable) + { + if (immutable == null) + return null; + + return new TypedHwid + { + Hwid = immutable.Hwid.ToArray(), + Type = immutable.Type, + }; + } + + [return: NotNullIfNotNull(nameof(hwid))] + public static implicit operator ImmutableTypedHwid?(TypedHwid? hwid) + { + if (hwid == null) + return null; + + return new ImmutableTypedHwid(hwid.Hwid.ToImmutableArray(), hwid.Type); + } + } } diff --git a/Content.Server/Administration/BanList/BanListEui.cs b/Content.Server/Administration/BanList/BanListEui.cs index 8ddc7459d7b9..2ca126bf1641 100644 --- a/Content.Server/Administration/BanList/BanListEui.cs +++ b/Content.Server/Administration/BanList/BanListEui.cs @@ -54,7 +54,7 @@ private void OnPermsChanged(AdminPermsChangedEventArgs args) private async Task LoadBans(NetUserId userId) { - foreach (var ban in await _db.GetServerBansAsync(null, userId, null)) + foreach (var ban in await _db.GetServerBansAsync(null, userId, null, null)) { SharedServerUnban? unban = null; if (ban.Unban is { } unbanDef) @@ -74,7 +74,7 @@ private async Task LoadBans(NetUserId userId) ? (address.address.ToString(), address.cidrMask) : null; - hwid = ban.HWId == null ? null : Convert.ToBase64String(ban.HWId.Value.AsSpan()); + hwid = ban.HWId?.ToString(); } Bans.Add(new SharedServerBan( @@ -95,7 +95,7 @@ private async Task LoadBans(NetUserId userId) private async Task LoadRoleBans(NetUserId userId) { - foreach (var ban in await _db.GetServerRoleBansAsync(null, userId, null)) + foreach (var ban in await _db.GetServerRoleBansAsync(null, userId, null, null)) { SharedServerUnban? unban = null; if (ban.Unban is { } unbanDef) @@ -115,7 +115,7 @@ private async Task LoadRoleBans(NetUserId userId) ? (address.address.ToString(), address.cidrMask) : null; - hwid = ban.HWId == null ? null : Convert.ToBase64String(ban.HWId.Value.AsSpan()); + hwid = ban.HWId?.ToString(); } RoleBans.Add(new SharedServerRoleBan( ban.Id, diff --git a/Content.Server/Administration/BanPanelEui.cs b/Content.Server/Administration/BanPanelEui.cs index e746e9c725f9..3eedad3ed507 100644 --- a/Content.Server/Administration/BanPanelEui.cs +++ b/Content.Server/Administration/BanPanelEui.cs @@ -1,4 +1,3 @@ -using System.Collections.Immutable; using System.Net; using System.Net.Sockets; using Content.Server.Administration.Managers; @@ -8,7 +7,6 @@ using Content.Shared.Administration; using Content.Shared.Database; using Content.Shared.Eui; -using Robust.Server.Player; using Robust.Shared.Network; namespace Content.Server.Administration; @@ -27,7 +25,7 @@ public sealed class BanPanelEui : BaseEui private NetUserId? PlayerId { get; set; } private string PlayerName { get; set; } = string.Empty; private IPAddress? LastAddress { get; set; } - private ImmutableArray? LastHwid { get; set; } + private ImmutableTypedHwid? LastHwid { get; set; } private const int Ipv4_CIDR = 32; private const int Ipv6_CIDR = 64; @@ -51,7 +49,7 @@ public override void HandleMessage(EuiMessageBase msg) switch (msg) { case BanPanelEuiStateMsg.CreateBanRequest r: - BanPlayer(r.Player, r.IpAddress, r.UseLastIp, r.Hwid?.ToImmutableArray(), r.UseLastHwid, r.Minutes, r.Severity, r.Reason, r.Roles, r.Erase); + BanPlayer(r.Player, r.IpAddress, r.UseLastIp, r.Hwid, r.UseLastHwid, r.Minutes, r.Severity, r.Reason, r.Roles, r.Erase); break; case BanPanelEuiStateMsg.GetPlayerInfoRequest r: ChangePlayer(r.PlayerUsername); @@ -59,7 +57,7 @@ public override void HandleMessage(EuiMessageBase msg) } } - private async void BanPlayer(string? target, string? ipAddressString, bool useLastIp, ImmutableArray? hwid, bool useLastHwid, uint minutes, NoteSeverity severity, string reason, IReadOnlyCollection? roles, bool erase) + private async void BanPlayer(string? target, string? ipAddressString, bool useLastIp, ImmutableTypedHwid? hwid, bool useLastHwid, uint minutes, NoteSeverity severity, string reason, IReadOnlyCollection? roles, bool erase) { if (!_admins.HasAdminFlag(Player, AdminFlags.Ban)) { @@ -155,7 +153,7 @@ public async void ChangePlayer(string playerNameOrId) ChangePlayer(located?.UserId, located?.Username ?? string.Empty, located?.LastAddress, located?.LastHWId); } - public void ChangePlayer(NetUserId? playerId, string playerName, IPAddress? lastAddress, ImmutableArray? lastHwid) + public void ChangePlayer(NetUserId? playerId, string playerName, IPAddress? lastAddress, ImmutableTypedHwid? lastHwid) { PlayerId = playerId; PlayerName = playerName; diff --git a/Content.Server/Administration/Commands/BanListCommand.cs b/Content.Server/Administration/Commands/BanListCommand.cs index a5bc97dce3ed..2f7093ae1d86 100644 --- a/Content.Server/Administration/Commands/BanListCommand.cs +++ b/Content.Server/Administration/Commands/BanListCommand.cs @@ -38,7 +38,7 @@ public override async void Execute(IConsoleShell shell, string argStr, string[] if (shell.Player is not { } player) { - var bans = await _dbManager.GetServerBansAsync(data.LastAddress, data.UserId, data.LastHWId, false); + var bans = await _dbManager.GetServerBansAsync(data.LastAddress, data.UserId, data.LastLegacyHWId, data.LastModernHWIds, false); if (bans.Count == 0) { diff --git a/Content.Server/Administration/Commands/RoleBanListCommand.cs b/Content.Server/Administration/Commands/RoleBanListCommand.cs index 30bb3073add9..8244ded3b209 100644 --- a/Content.Server/Administration/Commands/RoleBanListCommand.cs +++ b/Content.Server/Administration/Commands/RoleBanListCommand.cs @@ -48,7 +48,7 @@ public async void Execute(IConsoleShell shell, string argStr, string[] args) if (shell.Player is not { } player) { - var bans = await _dbManager.GetServerRoleBansAsync(data.LastAddress, data.UserId, data.LastHWId, includeUnbanned); + var bans = await _dbManager.GetServerRoleBansAsync(data.LastAddress, data.UserId, data.LastLegacyHWId, data.LastModernHWIds, includeUnbanned); if (bans.Count == 0) { diff --git a/Content.Server/Administration/Managers/BanManager.cs b/Content.Server/Administration/Managers/BanManager.cs index 1cdfb822242e..2e21710e51d2 100644 --- a/Content.Server/Administration/Managers/BanManager.cs +++ b/Content.Server/Administration/Managers/BanManager.cs @@ -65,7 +65,8 @@ private async Task CachePlayerData(ICommonSession player, CancellationToken canc var netChannel = player.Channel; ImmutableArray? hwId = netChannel.UserData.HWId.Length == 0 ? null : netChannel.UserData.HWId; - var roleBans = await _db.GetServerRoleBansAsync(netChannel.RemoteEndPoint.Address, player.UserId, hwId, false); + var modernHwids = netChannel.UserData.ModernHWIds; + var roleBans = await _db.GetServerRoleBansAsync(netChannel.RemoteEndPoint.Address, player.UserId, hwId, modernHwids, false); var userRoleBans = new List(); foreach (var ban in roleBans) @@ -132,7 +133,7 @@ public void Restart() } #region Server Bans - public async void CreateServerBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableArray? hwid, uint? minutes, NoteSeverity severity, string reason) + public async void CreateServerBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableTypedHwid? hwid, uint? minutes, NoteSeverity severity, string reason) { DateTimeOffset? expires = null; if (minutes > 0) @@ -166,9 +167,7 @@ public async void CreateServerBan(NetUserId? target, string? targetUsername, Net var addressRangeString = addressRange != null ? $"{addressRange.Value.Item1}/{addressRange.Value.Item2}" : "null"; - var hwidString = hwid != null - ? string.Concat(hwid.Value.Select(x => x.ToString("x2"))) - : "null"; + var hwidString = hwid?.ToString() ?? "null"; var expiresString = expires == null ? Loc.GetString("server-ban-string-never") : $"{expires}"; var key = _cfg.GetCVar(CCVars.AdminShowPIIOnBan) ? "server-ban-string" : "server-ban-string-no-pii"; @@ -208,6 +207,7 @@ private bool BanMatchesPlayer(ICommonSession player, ServerBanDef ban) UserId = player.UserId, Address = player.Channel.RemoteEndPoint.Address, HWId = player.Channel.UserData.HWId, + ModernHWIds = player.Channel.UserData.ModernHWIds, // It's possible for the player to not have cached data loading yet due to coincidental timing. // If this is the case, we assume they have all flags to avoid false-positives. ExemptFlags = _cachedBanExemptions.GetValueOrDefault(player, ServerBanExemptFlags.All), @@ -228,7 +228,7 @@ private void KickForBanDef(ICommonSession player, ServerBanDef def) #region Job Bans // If you are trying to remove timeOfBan, please don't. It's there because the note system groups role bans by time, reason and banning admin. // Removing it will clutter the note list. Please also make sure that department bans are applied to roles with the same DateTimeOffset. - public async void CreateRoleBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableArray? hwid, string role, uint? minutes, NoteSeverity severity, string reason, DateTimeOffset timeOfBan) + public async void CreateRoleBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableTypedHwid? hwid, string role, uint? minutes, NoteSeverity severity, string reason, DateTimeOffset timeOfBan) { if (!_prototypeManager.TryIndex(role, out JobPrototype? _)) { diff --git a/Content.Server/Administration/Managers/IBanManager.cs b/Content.Server/Administration/Managers/IBanManager.cs index c11e310a8253..fc192cc3066e 100644 --- a/Content.Server/Administration/Managers/IBanManager.cs +++ b/Content.Server/Administration/Managers/IBanManager.cs @@ -24,7 +24,7 @@ public interface IBanManager /// Number of minutes to ban for. 0 and null mean permanent /// Severity of the resulting ban note /// Reason for the ban - public void CreateServerBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableArray? hwid, uint? minutes, NoteSeverity severity, string reason); + public void CreateServerBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableTypedHwid? hwid, uint? minutes, NoteSeverity severity, string reason); public HashSet? GetRoleBans(NetUserId playerUserId); public HashSet>? GetJobBans(NetUserId playerUserId); @@ -37,7 +37,7 @@ public interface IBanManager /// Reason for the ban /// Number of minutes to ban for. 0 and null mean permanent /// Time when the ban was applied, used for grouping role bans - public void CreateRoleBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableArray? hwid, string role, uint? minutes, NoteSeverity severity, string reason, DateTimeOffset timeOfBan); + public void CreateRoleBan(NetUserId? target, string? targetUsername, NetUserId? banningAdmin, (IPAddress, int)? addressRange, ImmutableTypedHwid? hwid, string role, uint? minutes, NoteSeverity severity, string reason, DateTimeOffset timeOfBan); /// /// Pardons a role ban for the specified target, username or GUID diff --git a/Content.Server/Administration/PlayerLocator.cs b/Content.Server/Administration/PlayerLocator.cs index 64a85f19ad0b..25cc7714686c 100644 --- a/Content.Server/Administration/PlayerLocator.cs +++ b/Content.Server/Administration/PlayerLocator.cs @@ -5,16 +5,42 @@ using System.Net.Http.Json; using System.Threading; using System.Threading.Tasks; +using Content.Server.Connection; using Content.Server.Database; +using Content.Shared.Database; using JetBrains.Annotations; using Robust.Server.Player; using Robust.Shared; using Robust.Shared.Configuration; using Robust.Shared.Network; +using Robust.Shared.Player; namespace Content.Server.Administration { - public sealed record LocatedPlayerData(NetUserId UserId, IPAddress? LastAddress, ImmutableArray? LastHWId, string Username); + /// + /// Contains data resolved via . + /// + /// The ID of the located user. + /// The last known IP address that the user connected with. + /// + /// The last known HWID that the user connected with. + /// This should be used for placing new records involving HWIDs, such as bans. + /// For looking up data based on HWID, use combined and . + /// + /// The last known username for the user connected with. + /// + /// The last known legacy HWID value this user connected with. Only use for old lookups! + /// + /// + /// The set of last known modern HWIDs the user connected with. + /// + public sealed record LocatedPlayerData( + NetUserId UserId, + IPAddress? LastAddress, + ImmutableTypedHwid? LastHWId, + string Username, + ImmutableArray? LastLegacyHWId, + ImmutableArray> LastModernHWIds); /// /// Utilities for finding user IDs that extend to more than the server database. @@ -67,63 +93,42 @@ public PlayerLocator() { // Check people currently on the server, the easiest case. if (_playerManager.TryGetSessionByUsername(playerName, out var session)) - { - var userId = session.UserId; - var address = session.Channel.RemoteEndPoint.Address; - var hwId = session.Channel.UserData.HWId; - return new LocatedPlayerData(userId, address, hwId, session.Name); - } + return ReturnForSession(session); // Check database for past players. var record = await _db.GetPlayerRecordByUserName(playerName, cancel); if (record != null) - return new LocatedPlayerData(record.UserId, record.LastSeenAddress, record.HWId, record.LastSeenUserName); + return ReturnForPlayerRecord(record); // If all else fails, ask the auth server. var authServer = _configurationManager.GetCVar(CVars.AuthServer); var requestUri = $"{authServer}api/query/name?name={WebUtility.UrlEncode(playerName)}"; using var resp = await _httpClient.GetAsync(requestUri, cancel); - if (resp.StatusCode == HttpStatusCode.NotFound) - return null; - - if (!resp.IsSuccessStatusCode) - { - _sawmill.Error("Auth server returned bad response {StatusCode}!", resp.StatusCode); - return null; - } - - var responseData = await resp.Content.ReadFromJsonAsync(cancellationToken: cancel); - - if (responseData == null) - { - _sawmill.Error("Auth server returned null response!"); - return null; - } - - return new LocatedPlayerData(new NetUserId(responseData.UserId), null, null, responseData.UserName); + return await HandleAuthServerResponse(resp, cancel); } public async Task LookupIdAsync(NetUserId userId, CancellationToken cancel = default) { // Check people currently on the server, the easiest case. if (_playerManager.TryGetSessionById(userId, out var session)) - { - var address = session.Channel.RemoteEndPoint.Address; - var hwId = session.Channel.UserData.HWId; - return new LocatedPlayerData(userId, address, hwId, session.Name); - } + return ReturnForSession(session); // Check database for past players. var record = await _db.GetPlayerRecordByUserId(userId, cancel); if (record != null) - return new LocatedPlayerData(record.UserId, record.LastSeenAddress, record.HWId, record.LastSeenUserName); + return ReturnForPlayerRecord(record); // If all else fails, ask the auth server. var authServer = _configurationManager.GetCVar(CVars.AuthServer); var requestUri = $"{authServer}api/query/userid?userid={WebUtility.UrlEncode(userId.UserId.ToString())}"; using var resp = await _httpClient.GetAsync(requestUri, cancel); + return await HandleAuthServerResponse(resp, cancel); + } + + private async Task HandleAuthServerResponse(HttpResponseMessage resp, CancellationToken cancel) + { if (resp.StatusCode == HttpStatusCode.NotFound) return null; @@ -134,14 +139,40 @@ public PlayerLocator() } var responseData = await resp.Content.ReadFromJsonAsync(cancellationToken: cancel); - if (responseData == null) { _sawmill.Error("Auth server returned null response!"); return null; } - return new LocatedPlayerData(new NetUserId(responseData.UserId), null, null, responseData.UserName); + return new LocatedPlayerData(new NetUserId(responseData.UserId), null, null, responseData.UserName, null, []); + } + + private static LocatedPlayerData ReturnForSession(ICommonSession session) + { + var userId = session.UserId; + var address = session.Channel.RemoteEndPoint.Address; + var hwId = session.Channel.UserData.GetModernHwid(); + return new LocatedPlayerData( + userId, + address, + hwId, + session.Name, + session.Channel.UserData.HWId, + session.Channel.UserData.ModernHWIds); + } + + private static LocatedPlayerData ReturnForPlayerRecord(PlayerRecord record) + { + var hwid = record.HWId; + + return new LocatedPlayerData( + record.UserId, + record.LastSeenAddress, + hwid, + record.LastSeenUserName, + hwid is { Type: HwidType.Legacy } ? hwid.Hwid : null, + hwid is { Type: HwidType.Modern } ? [hwid.Hwid] : []); } public async Task LookupIdByNameOrIdAsync(string playerName, CancellationToken cancel = default) diff --git a/Content.Server/Administration/PlayerPanelEui.cs b/Content.Server/Administration/PlayerPanelEui.cs index 4c0df8060122..6c3048888662 100644 --- a/Content.Server/Administration/PlayerPanelEui.cs +++ b/Content.Server/Administration/PlayerPanelEui.cs @@ -173,11 +173,11 @@ public async void SetPlayerState() { _whitelisted = await _db.GetWhitelistStatusAsync(_targetPlayer.UserId); // This won't get associated ip or hwid bans but they were not placed on this account anyways - _bans = (await _db.GetServerBansAsync(null, _targetPlayer.UserId, null)).Count; + _bans = (await _db.GetServerBansAsync(null, _targetPlayer.UserId, null, null)).Count; // Unfortunately role bans for departments and stuff are issued individually. This means that a single role ban can have many individual role bans internally // The only way to distinguish whether a role ban is the same is to compare the ban time. // This is horrible and I would love to just erase the database and start from scratch instead but that's what I can do for now. - _roleBans = (await _db.GetServerRoleBansAsync(null, _targetPlayer.UserId, null)).DistinctBy(rb => rb.BanTime).Count(); + _roleBans = (await _db.GetServerRoleBansAsync(null, _targetPlayer.UserId, null, null)).DistinctBy(rb => rb.BanTime).Count(); } else { diff --git a/Content.Server/Administration/Systems/BwoinkSystem.cs b/Content.Server/Administration/Systems/BwoinkSystem.cs index 7a47755db9d3..4358b7e3876f 100644 --- a/Content.Server/Administration/Systems/BwoinkSystem.cs +++ b/Content.Server/Administration/Systems/BwoinkSystem.cs @@ -172,7 +172,7 @@ private async void OnPlayerStatusChanged(object? sender, SessionStatusEventArgs } // Check if the user has been banned - var ban = await _dbManager.GetServerBanAsync(null, e.Session.UserId, null); + var ban = await _dbManager.GetServerBanAsync(null, e.Session.UserId, null, null); if (ban != null) { var banMessage = Loc.GetString("bwoink-system-player-banned", ("banReason", ban.Reason)); diff --git a/Content.Server/Connection/ConnectionManager.cs b/Content.Server/Connection/ConnectionManager.cs index 2c1f9fb36f11..e4c7cf0be2e9 100644 --- a/Content.Server/Connection/ConnectionManager.cs +++ b/Content.Server/Connection/ConnectionManager.cs @@ -111,11 +111,14 @@ private async Task NetMgrOnConnecting(NetConnectingArgs e) var serverId = (await _serverDbEntry.ServerEntity).Id; + var hwid = e.UserData.GetModernHwid(); + var trust = e.UserData.Trust; + if (deny != null) { var (reason, msg, banHits) = deny.Value; - var id = await _db.AddConnectionLogAsync(userId, e.UserName, addr, e.UserData.HWId, reason, serverId); + var id = await _db.AddConnectionLogAsync(userId, e.UserName, addr, hwid, trust, reason, serverId); if (banHits is { Count: > 0 }) await _db.AddServerBanHitsAsync(id, banHits); @@ -127,12 +130,12 @@ private async Task NetMgrOnConnecting(NetConnectingArgs e) } else { - await _db.AddConnectionLogAsync(userId, e.UserName, addr, e.UserData.HWId, null, serverId); + await _db.AddConnectionLogAsync(userId, e.UserName, addr, hwid, trust, null, serverId); if (!ServerPreferencesManager.ShouldStorePrefs(e.AuthType)) return; - await _db.UpdatePlayerRecordAsync(userId, e.UserName, addr, e.UserData.HWId); + await _db.UpdatePlayerRecordAsync(userId, e.UserName, addr, hwid); } } @@ -190,7 +193,9 @@ session.Status is SessionStatus.Connected or SessionStatus.InGame hwId = null; } - var bans = await _db.GetServerBansAsync(addr, userId, hwId, includeUnbanned: false); + var modernHwid = e.UserData.ModernHWIds; + + var bans = await _db.GetServerBansAsync(addr, userId, hwId, modernHwid, includeUnbanned: false); if (bans.Count > 0) { var firstBan = bans[0]; diff --git a/Content.Server/Connection/UserDataExt.cs b/Content.Server/Connection/UserDataExt.cs new file mode 100644 index 000000000000..a409f79a75d5 --- /dev/null +++ b/Content.Server/Connection/UserDataExt.cs @@ -0,0 +1,24 @@ +using Content.Shared.Database; +using Robust.Shared.Network; + +namespace Content.Server.Connection; + +/// +/// Helper functions for working with . +/// +public static class UserDataExt +{ + /// + /// Get the preferred HWID that should be used for new records related to a player. + /// + /// + /// Players can have zero or more HWIDs, but for logging things like connection logs we generally + /// only want a single one. This method returns a nullable method. + /// + public static ImmutableTypedHwid? GetModernHwid(this NetUserData userData) + { + return userData.ModernHWIds.Length == 0 + ? null + : new ImmutableTypedHwid(userData.ModernHWIds[0], HwidType.Modern); + } +} diff --git a/Content.Server/Database/BanMatcher.cs b/Content.Server/Database/BanMatcher.cs index e58e5b0b5f65..f477ccd822a6 100644 --- a/Content.Server/Database/BanMatcher.cs +++ b/Content.Server/Database/BanMatcher.cs @@ -1,6 +1,7 @@ using System.Collections.Immutable; using System.Net; using Content.Server.IP; +using Content.Shared.Database; using Robust.Shared.Network; namespace Content.Server.Database; @@ -52,9 +53,28 @@ public static bool BanMatches(ServerBanDef ban, in PlayerInfo player) return true; } - return player.HWId is { Length: > 0 } hwIdVar - && ban.HWId != null - && hwIdVar.AsSpan().SequenceEqual(ban.HWId.Value.AsSpan()); + switch (ban.HWId?.Type) + { + case HwidType.Legacy: + if (player.HWId is { Length: > 0 } hwIdVar + && hwIdVar.AsSpan().SequenceEqual(ban.HWId.Hwid.AsSpan())) + { + return true; + } + break; + case HwidType.Modern: + if (player.ModernHWIds is { Length: > 0 } modernHwIdVar) + { + foreach (var hwid in modernHwIdVar) + { + if (hwid.AsSpan().SequenceEqual(ban.HWId.Hwid.AsSpan())) + return true; + } + } + break; + } + + return false; } /// @@ -73,10 +93,15 @@ public struct PlayerInfo public IPAddress? Address; /// - /// The hardware ID of the player. + /// The LEGACY hardware ID of the player. Corresponds with . /// public ImmutableArray? HWId; + /// + /// The modern hardware IDs of the player. Corresponds with . + /// + public ImmutableArray>? ModernHWIds; + /// /// Exemption flags the player has been granted. /// diff --git a/Content.Server/Database/DatabaseRecords.cs b/Content.Server/Database/DatabaseRecords.cs index c0d81147bb49..30fba3434b89 100644 --- a/Content.Server/Database/DatabaseRecords.cs +++ b/Content.Server/Database/DatabaseRecords.cs @@ -1,4 +1,3 @@ -using System.Collections.Immutable; using System.Net; using Content.Shared.Database; using Robust.Shared.Network; @@ -121,7 +120,7 @@ public sealed record PlayerRecord( string LastSeenUserName, DateTimeOffset LastSeenTime, IPAddress LastSeenAddress, - ImmutableArray? HWId); + ImmutableTypedHwid? HWId); public sealed record RoundRecord(int Id, DateTimeOffset? StartDate, ServerRecord Server); diff --git a/Content.Server/Database/ServerBanDef.cs b/Content.Server/Database/ServerBanDef.cs index 09a960e9a6c1..a09f9e959c65 100644 --- a/Content.Server/Database/ServerBanDef.cs +++ b/Content.Server/Database/ServerBanDef.cs @@ -1,4 +1,3 @@ -using System.Collections.Immutable; using System.Net; using Content.Shared.CCVar; using Content.Shared.Database; @@ -13,7 +12,7 @@ public sealed class ServerBanDef public int? Id { get; } public NetUserId? UserId { get; } public (IPAddress address, int cidrMask)? Address { get; } - public ImmutableArray? HWId { get; } + public ImmutableTypedHwid? HWId { get; } public DateTimeOffset BanTime { get; } public DateTimeOffset? ExpirationTime { get; } @@ -28,7 +27,7 @@ public sealed class ServerBanDef public ServerBanDef(int? id, NetUserId? userId, (IPAddress, int)? address, - ImmutableArray? hwId, + TypedHwid? hwId, DateTimeOffset banTime, DateTimeOffset? expirationTime, int? roundId, diff --git a/Content.Server/Database/ServerDbBase.cs b/Content.Server/Database/ServerDbBase.cs index c85b774e3810..723092bdc468 100644 --- a/Content.Server/Database/ServerDbBase.cs +++ b/Content.Server/Database/ServerDbBase.cs @@ -388,12 +388,14 @@ public async Task AssignUserIdAsync(string name, NetUserId netUserId) /// /// The ip address of the user. /// The id of the user. - /// The HWId of the user. + /// The legacy HWId of the user. + /// The modern HWIDs of the user. /// The user's latest received un-pardoned ban, or null if none exist. public abstract Task GetServerBanAsync( IPAddress? address, NetUserId? userId, - ImmutableArray? hwId); + ImmutableArray? hwId, + ImmutableArray>? modernHWIds); /// /// Looks up an user's ban history. @@ -402,13 +404,15 @@ public async Task AssignUserIdAsync(string name, NetUserId netUserId) /// /// The ip address of the user. /// The id of the user. - /// The HWId of the user. + /// The legacy HWId of the user. + /// The modern HWIDs of the user. /// Include pardoned and expired bans. /// The user's ban history. public abstract Task> GetServerBansAsync( IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned); public abstract Task AddServerBanAsync(ServerBanDef serverBan); @@ -499,11 +503,13 @@ public async Task GetBanExemption(NetUserId userId, Cancel /// The IP address of the user. /// The NetUserId of the user. /// The Hardware Id of the user. + /// The modern HWIDs of the user. /// Whether expired and pardoned bans are included. /// The user's role ban history. public abstract Task> GetServerRoleBansAsync(IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned); public abstract Task AddServerRoleBanAsync(ServerRoleBanDef serverRoleBan); @@ -586,7 +592,7 @@ public async Task UpdatePlayerRecord( NetUserId userId, string userName, IPAddress address, - ImmutableArray hwId) + ImmutableTypedHwid? hwId) { await using var db = await GetDb(); @@ -603,7 +609,7 @@ public async Task UpdatePlayerRecord( record.LastSeenTime = DateTime.UtcNow; record.LastSeenAddress = address; record.LastSeenUserName = userName; - record.LastSeenHWId = hwId.ToArray(); + record.LastSeenHWId = hwId; await db.DbContext.SaveChangesAsync(); } @@ -649,7 +655,7 @@ protected async Task PlayerRecordExists(DbGuard db, NetUserId userId) player.LastSeenUserName, new DateTimeOffset(NormalizeDatabaseTime(player.LastSeenTime)), player.LastSeenAddress, - player.LastSeenHWId?.ToImmutableArray()); + player.LastSeenHWId); } #endregion @@ -658,11 +664,11 @@ protected async Task PlayerRecordExists(DbGuard db, NetUserId userId) /* * CONNECTION LOG */ - public abstract Task AddConnectionLogAsync( - NetUserId userId, + public abstract Task AddConnectionLogAsync(NetUserId userId, string userName, IPAddress address, - ImmutableArray hwId, + ImmutableTypedHwid? hwId, + float trust, ConnectionDenyReason? denied, int serverId); diff --git a/Content.Server/Database/ServerDbManager.cs b/Content.Server/Database/ServerDbManager.cs index 216b1ec15966..be32b43595de 100644 --- a/Content.Server/Database/ServerDbManager.cs +++ b/Content.Server/Database/ServerDbManager.cs @@ -69,12 +69,14 @@ Task InitPrefsAsync( /// /// The ip address of the user. /// The id of the user. - /// The hardware ID of the user. + /// The legacy HWID of the user. + /// The modern HWIDs of the user. /// The user's latest received un-pardoned ban, or null if none exist. Task GetServerBanAsync( IPAddress? address, NetUserId? userId, - ImmutableArray? hwId); + ImmutableArray? hwId, + ImmutableArray>? modernHWIds); /// /// Looks up an user's ban history. @@ -82,13 +84,15 @@ Task InitPrefsAsync( /// /// The ip address of the user. /// The id of the user. - /// The HWId of the user. + /// The legacy HWId of the user. + /// The modern HWIDs of the user. /// If true, bans that have been expired or pardoned are also included. /// The user's ban history. Task> GetServerBansAsync( IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned=true); Task AddServerBanAsync(ServerBanDef serverBan); @@ -137,12 +141,14 @@ public Task EditServerBan( /// The IP address of the user. /// The NetUserId of the user. /// The Hardware Id of the user. + /// The modern HWIDs of the user. /// Whether expired and pardoned bans are included. /// The user's role ban history. Task> GetServerRoleBansAsync( IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned = true); Task AddServerRoleBanAsync(ServerRoleBanDef serverBan); @@ -180,7 +186,7 @@ Task UpdatePlayerRecordAsync( NetUserId userId, string userName, IPAddress address, - ImmutableArray hwId); + ImmutableTypedHwid? hwId); Task GetPlayerRecordByUserName(string userName, CancellationToken cancel = default); Task GetPlayerRecordByUserId(NetUserId userId, CancellationToken cancel = default); #endregion @@ -191,7 +197,8 @@ Task AddConnectionLogAsync( NetUserId userId, string userName, IPAddress address, - ImmutableArray hwId, + ImmutableTypedHwid? hwId, + float trust, ConnectionDenyReason? denied, int serverId); @@ -480,20 +487,22 @@ public Task AssignUserIdAsync(string name, NetUserId userId) public Task GetServerBanAsync( IPAddress? address, NetUserId? userId, - ImmutableArray? hwId) + ImmutableArray? hwId, + ImmutableArray>? modernHWIds) { DbReadOpsMetric.Inc(); - return RunDbCommand(() => _db.GetServerBanAsync(address, userId, hwId)); + return RunDbCommand(() => _db.GetServerBanAsync(address, userId, hwId, modernHWIds)); } public Task> GetServerBansAsync( IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned=true) { DbReadOpsMetric.Inc(); - return RunDbCommand(() => _db.GetServerBansAsync(address, userId, hwId, includeUnbanned)); + return RunDbCommand(() => _db.GetServerBansAsync(address, userId, hwId, modernHWIds, includeUnbanned)); } public Task AddServerBanAsync(ServerBanDef serverBan) @@ -537,10 +546,11 @@ public Task> GetServerRoleBansAsync( IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned = true) { DbReadOpsMetric.Inc(); - return RunDbCommand(() => _db.GetServerRoleBansAsync(address, userId, hwId, includeUnbanned)); + return RunDbCommand(() => _db.GetServerRoleBansAsync(address, userId, hwId, modernHWIds, includeUnbanned)); } public Task AddServerRoleBanAsync(ServerRoleBanDef serverRoleBan) @@ -582,7 +592,7 @@ public Task UpdatePlayerRecordAsync( NetUserId userId, string userName, IPAddress address, - ImmutableArray hwId) + ImmutableTypedHwid? hwId) { DbWriteOpsMetric.Inc(); return RunDbCommand(() => _db.UpdatePlayerRecord(userId, userName, address, hwId)); @@ -604,12 +614,13 @@ public Task AddConnectionLogAsync( NetUserId userId, string userName, IPAddress address, - ImmutableArray hwId, + ImmutableTypedHwid? hwId, + float trust, ConnectionDenyReason? denied, int serverId) { DbWriteOpsMetric.Inc(); - return RunDbCommand(() => _db.AddConnectionLogAsync(userId, userName, address, hwId, denied, serverId)); + return RunDbCommand(() => _db.AddConnectionLogAsync(userId, userName, address, hwId, trust, denied, serverId)); } public Task AddServerBanHitsAsync(int connection, IEnumerable bans) diff --git a/Content.Server/Database/ServerDbPostgres.cs b/Content.Server/Database/ServerDbPostgres.cs index 7d131f70dc36..c0346708377e 100644 --- a/Content.Server/Database/ServerDbPostgres.cs +++ b/Content.Server/Database/ServerDbPostgres.cs @@ -9,6 +9,7 @@ using Content.Server.Administration.Logs; using Content.Server.IP; using Content.Shared.CCVar; +using Content.Shared.Database; using Microsoft.EntityFrameworkCore; using Robust.Shared.Configuration; using Robust.Shared.Network; @@ -73,7 +74,8 @@ public ServerDbPostgres(DbContextOptions options, public override async Task GetServerBanAsync( IPAddress? address, NetUserId? userId, - ImmutableArray? hwId) + ImmutableArray? hwId, + ImmutableArray>? modernHWIds) { if (address == null && userId == null && hwId == null) { @@ -84,7 +86,7 @@ public ServerDbPostgres(DbContextOptions options, var exempt = await GetBanExemptionCore(db, userId); var newPlayer = userId == null || !await PlayerRecordExists(db, userId.Value); - var query = MakeBanLookupQuery(address, userId, hwId, db, includeUnbanned: false, exempt, newPlayer) + var query = MakeBanLookupQuery(address, userId, hwId, modernHWIds, db, includeUnbanned: false, exempt, newPlayer) .OrderByDescending(b => b.BanTime); var ban = await query.FirstOrDefaultAsync(); @@ -94,7 +96,9 @@ public ServerDbPostgres(DbContextOptions options, public override async Task> GetServerBansAsync(IPAddress? address, NetUserId? userId, - ImmutableArray? hwId, bool includeUnbanned) + ImmutableArray? hwId, + ImmutableArray>? modernHWIds, + bool includeUnbanned) { if (address == null && userId == null && hwId == null) { @@ -105,7 +109,7 @@ public override async Task> GetServerBansAsync(IPAddress? add var exempt = await GetBanExemptionCore(db, userId); var newPlayer = !await db.PgDbContext.Player.AnyAsync(p => p.UserId == userId); - var query = MakeBanLookupQuery(address, userId, hwId, db, includeUnbanned, exempt, newPlayer); + var query = MakeBanLookupQuery(address, userId, hwId, modernHWIds, db, includeUnbanned, exempt, newPlayer); var queryBans = await query.ToArrayAsync(); var bans = new List(queryBans.Length); @@ -127,6 +131,7 @@ private static IQueryable MakeBanLookupQuery( IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, DbGuardImpl db, bool includeUnbanned, ServerBanExemptFlags? exemptFlags, @@ -134,16 +139,11 @@ private static IQueryable MakeBanLookupQuery( { DebugTools.Assert(!(address == null && userId == null && hwId == null)); - IQueryable? query = null; - - if (userId is { } uid) - { - var newQ = db.PgDbContext.Ban - .Include(p => p.Unban) - .Where(b => b.PlayerUserId == uid.UserId); - - query = query == null ? newQ : query.Union(newQ); - } + var query = MakeBanLookupQualityShared( + userId, + hwId, + modernHWIds, + db.PgDbContext.Ban); if (address != null && !exemptFlags.GetValueOrDefault(ServerBanExemptFlags.None).HasFlag(ServerBanExemptFlags.IP)) { @@ -156,15 +156,6 @@ private static IQueryable MakeBanLookupQuery( query = query == null ? newQ : query.Union(newQ); } - if (hwId != null && hwId.Value.Length > 0) - { - var newQ = db.PgDbContext.Ban - .Include(p => p.Unban) - .Where(b => b.HWId!.SequenceEqual(hwId.Value.ToArray())); - - query = query == null ? newQ : query.Union(newQ); - } - DebugTools.Assert( query != null, "At least one filter item (IP/UserID/HWID) must have been given to make query not null."); @@ -186,6 +177,49 @@ private static IQueryable MakeBanLookupQuery( return query.Distinct(); } + private static IQueryable? MakeBanLookupQualityShared( + NetUserId? userId, + ImmutableArray? hwId, + ImmutableArray>? modernHWIds, + DbSet set) + where TBan : class, IBanCommon + where TUnban : class, IUnbanCommon + { + IQueryable? query = null; + + if (userId is { } uid) + { + var newQ = set + .Include(p => p.Unban) + .Where(b => b.PlayerUserId == uid.UserId); + + query = query == null ? newQ : query.Union(newQ); + } + + if (hwId != null && hwId.Value.Length > 0) + { + var newQ = set + .Include(p => p.Unban) + .Where(b => b.HWId!.Type == HwidType.Legacy && b.HWId!.Hwid.SequenceEqual(hwId.Value.ToArray())); + + query = query == null ? newQ : query.Union(newQ); + } + + if (modernHWIds != null) + { + foreach (var modernHwid in modernHWIds) + { + var newQ = set + .Include(p => p.Unban) + .Where(b => b.HWId!.Type == HwidType.Modern && b.HWId!.Hwid.SequenceEqual(modernHwid.ToArray())); + + query = query == null ? newQ : query.Union(newQ); + } + } + + return query; + } + private static ServerBanDef? ConvertBan(ServerBan? ban) { if (ban == null) @@ -211,7 +245,7 @@ private static IQueryable MakeBanLookupQuery( ban.Id, uid, ban.Address.ToTuple(), - ban.HWId == null ? null : ImmutableArray.Create(ban.HWId), + ban.HWId, ban.BanTime, ban.ExpirationTime, ban.RoundId, @@ -249,7 +283,7 @@ public override async Task AddServerBanAsync(ServerBanDef serverBan) db.PgDbContext.Ban.Add(new ServerBan { Address = serverBan.Address.ToNpgsqlInet(), - HWId = serverBan.HWId?.ToArray(), + HWId = serverBan.HWId, Reason = serverBan.Reason, Severity = serverBan.Severity, BanningAdmin = serverBan.BanningAdmin?.UserId, @@ -297,6 +331,7 @@ public override async Task AddServerUnbanAsync(ServerUnbanDef serverUnban) public override async Task> GetServerRoleBansAsync(IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned) { if (address == null && userId == null && hwId == null) @@ -306,7 +341,7 @@ public override async Task> GetServerRoleBansAsync(IPAddr await using var db = await GetDbImpl(); - var query = MakeRoleBanLookupQuery(address, userId, hwId, db, includeUnbanned) + var query = MakeRoleBanLookupQuery(address, userId, hwId, modernHWIds, db, includeUnbanned) .OrderByDescending(b => b.BanTime); return await QueryRoleBans(query); @@ -334,19 +369,15 @@ private static IQueryable MakeRoleBanLookupQuery( IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, DbGuardImpl db, bool includeUnbanned) { - IQueryable? query = null; - - if (userId is { } uid) - { - var newQ = db.PgDbContext.RoleBan - .Include(p => p.Unban) - .Where(b => b.PlayerUserId == uid.UserId); - - query = query == null ? newQ : query.Union(newQ); - } + var query = MakeBanLookupQualityShared( + userId, + hwId, + modernHWIds, + db.PgDbContext.RoleBan); if (address != null) { @@ -357,15 +388,6 @@ private static IQueryable MakeRoleBanLookupQuery( query = query == null ? newQ : query.Union(newQ); } - if (hwId != null && hwId.Value.Length > 0) - { - var newQ = db.PgDbContext.RoleBan - .Include(p => p.Unban) - .Where(b => b.HWId!.SequenceEqual(hwId.Value.ToArray())); - - query = query == null ? newQ : query.Union(newQ); - } - if (!includeUnbanned) { query = query?.Where(p => @@ -402,7 +424,7 @@ private static IQueryable MakeRoleBanLookupQuery( ban.Id, uid, ban.Address.ToTuple(), - ban.HWId == null ? null : ImmutableArray.Create(ban.HWId), + ban.HWId, ban.BanTime, ban.ExpirationTime, ban.RoundId, @@ -440,7 +462,7 @@ public override async Task AddServerRoleBanAsync(ServerRoleBan var ban = new ServerRoleBan { Address = serverRoleBan.Address.ToNpgsqlInet(), - HWId = serverRoleBan.HWId?.ToArray(), + HWId = serverRoleBan.HWId, Reason = serverRoleBan.Reason, Severity = serverRoleBan.Severity, BanningAdmin = serverRoleBan.BanningAdmin?.UserId, @@ -476,7 +498,8 @@ public override async Task AddConnectionLogAsync( NetUserId userId, string userName, IPAddress address, - ImmutableArray hwId, + ImmutableTypedHwid? hwId, + float trust, ConnectionDenyReason? denied, int serverId) { @@ -488,9 +511,10 @@ public override async Task AddConnectionLogAsync( Time = DateTime.UtcNow, UserId = userId.UserId, UserName = userName, - HWId = hwId.ToArray(), + HWId = hwId, Denied = denied, - ServerId = serverId + ServerId = serverId, + Trust = trust, }; db.PgDbContext.ConnectionLog.Add(connectionLog); diff --git a/Content.Server/Database/ServerDbSqlite.cs b/Content.Server/Database/ServerDbSqlite.cs index af4bc2cf8de0..6ec90c3332f1 100644 --- a/Content.Server/Database/ServerDbSqlite.cs +++ b/Content.Server/Database/ServerDbSqlite.cs @@ -9,6 +9,7 @@ using Content.Server.IP; using Content.Server.Preferences.Managers; using Content.Shared.CCVar; +using Content.Shared.Database; using Microsoft.EntityFrameworkCore; using Robust.Shared.Configuration; using Robust.Shared.Network; @@ -80,22 +81,24 @@ public ServerDbSqlite( public override async Task GetServerBanAsync( IPAddress? address, NetUserId? userId, - ImmutableArray? hwId) + ImmutableArray? hwId, + ImmutableArray>? modernHWIds) { await using var db = await GetDbImpl(); - return (await GetServerBanQueryAsync(db, address, userId, hwId, includeUnbanned: false)).FirstOrDefault(); + return (await GetServerBanQueryAsync(db, address, userId, hwId, modernHWIds, includeUnbanned: false)).FirstOrDefault(); } public override async Task> GetServerBansAsync( IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned) { await using var db = await GetDbImpl(); - return (await GetServerBanQueryAsync(db, address, userId, hwId, includeUnbanned)).ToList(); + return (await GetServerBanQueryAsync(db, address, userId, hwId, modernHWIds, includeUnbanned)).ToList(); } private async Task> GetServerBanQueryAsync( @@ -103,6 +106,7 @@ private async Task> GetServerBanQueryAsync( IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned) { var exempt = await GetBanExemptionCore(db, userId); @@ -119,6 +123,7 @@ private async Task> GetServerBanQueryAsync( UserId = userId, ExemptFlags = exempt ?? default, HWId = hwId, + ModernHWIds = modernHWIds, IsNewPlayer = newPlayer, }; @@ -161,7 +166,7 @@ public override async Task AddServerBanAsync(ServerBanDef serverBan) Reason = serverBan.Reason, Severity = serverBan.Severity, BanningAdmin = serverBan.BanningAdmin?.UserId, - HWId = serverBan.HWId?.ToArray(), + HWId = serverBan.HWId, BanTime = serverBan.BanTime.UtcDateTime, ExpirationTime = serverBan.ExpirationTime?.UtcDateTime, RoundId = serverBan.RoundId, @@ -205,6 +210,7 @@ public override async Task> GetServerRoleBansAsync( IPAddress? address, NetUserId? userId, ImmutableArray? hwId, + ImmutableArray>? modernHWIds, bool includeUnbanned) { await using var db = await GetDbImpl(); @@ -214,7 +220,7 @@ public override async Task> GetServerRoleBansAsync( var queryBans = await GetAllRoleBans(db.SqliteDbContext, includeUnbanned); return queryBans - .Where(b => RoleBanMatches(b, address, userId, hwId)) + .Where(b => RoleBanMatches(b, address, userId, hwId, modernHWIds)) .Select(ConvertRoleBan) .ToList()!; } @@ -237,7 +243,8 @@ private static bool RoleBanMatches( ServerRoleBan ban, IPAddress? address, NetUserId? userId, - ImmutableArray? hwId) + ImmutableArray? hwId, + ImmutableArray>? modernHWIds) { if (address != null && ban.Address is not null && address.IsInSubnet(ban.Address.ToTuple().Value)) { @@ -249,7 +256,27 @@ private static bool RoleBanMatches( return true; } - return hwId is { Length: > 0 } hwIdVar && hwIdVar.AsSpan().SequenceEqual(ban.HWId); + switch (ban.HWId?.Type) + { + case HwidType.Legacy: + if (hwId is { Length: > 0 } hwIdVar && hwIdVar.AsSpan().SequenceEqual(ban.HWId.Hwid)) + return true; + break; + + case HwidType.Modern: + if (modernHWIds != null) + { + foreach (var modernHWId in modernHWIds) + { + if (modernHWId.AsSpan().SequenceEqual(ban.HWId.Hwid)) + return true; + } + } + + break; + } + + return false; } public override async Task AddServerRoleBanAsync(ServerRoleBanDef serverBan) @@ -262,7 +289,7 @@ public override async Task AddServerRoleBanAsync(ServerRoleBan Reason = serverBan.Reason, Severity = serverBan.Severity, BanningAdmin = serverBan.BanningAdmin?.UserId, - HWId = serverBan.HWId?.ToArray(), + HWId = serverBan.HWId, BanTime = serverBan.BanTime.UtcDateTime, ExpirationTime = serverBan.ExpirationTime?.UtcDateTime, RoundId = serverBan.RoundId, @@ -316,7 +343,7 @@ public override async Task AddServerRoleUnbanAsync(ServerRoleUnbanDef serverUnba ban.Id, uid, ban.Address.ToTuple(), - ban.HWId == null ? null : ImmutableArray.Create(ban.HWId), + ban.HWId, // SQLite apparently always reads DateTime as unspecified, but we always write as UTC. DateTime.SpecifyKind(ban.BanTime, DateTimeKind.Utc), ban.ExpirationTime == null ? null : DateTime.SpecifyKind(ban.ExpirationTime.Value, DateTimeKind.Utc), @@ -376,7 +403,7 @@ public override async Task AddServerRoleUnbanAsync(ServerRoleUnbanDef serverUnba ban.Id, uid, ban.Address.ToTuple(), - ban.HWId == null ? null : ImmutableArray.Create(ban.HWId), + ban.HWId, // SQLite apparently always reads DateTime as unspecified, but we always write as UTC. DateTime.SpecifyKind(ban.BanTime, DateTimeKind.Utc), ban.ExpirationTime == null ? null : DateTime.SpecifyKind(ban.ExpirationTime.Value, DateTimeKind.Utc), @@ -412,7 +439,8 @@ public override async Task AddConnectionLogAsync( NetUserId userId, string userName, IPAddress address, - ImmutableArray hwId, + ImmutableTypedHwid? hwId, + float trust, ConnectionDenyReason? denied, int serverId) { @@ -424,9 +452,10 @@ public override async Task AddConnectionLogAsync( Time = DateTime.UtcNow, UserId = userId.UserId, UserName = userName, - HWId = hwId.ToArray(), + HWId = hwId, Denied = denied, - ServerId = serverId + ServerId = serverId, + Trust = trust, }; db.SqliteDbContext.ConnectionLog.Add(connectionLog); diff --git a/Content.Server/Database/ServerRoleBanDef.cs b/Content.Server/Database/ServerRoleBanDef.cs index f615d5da4d1e..dda3a8223786 100644 --- a/Content.Server/Database/ServerRoleBanDef.cs +++ b/Content.Server/Database/ServerRoleBanDef.cs @@ -1,4 +1,3 @@ -using System.Collections.Immutable; using System.Net; using Content.Shared.Database; using Robust.Shared.Network; @@ -10,7 +9,7 @@ public sealed class ServerRoleBanDef public int? Id { get; } public NetUserId? UserId { get; } public (IPAddress address, int cidrMask)? Address { get; } - public ImmutableArray? HWId { get; } + public ImmutableTypedHwid? HWId { get; } public DateTimeOffset BanTime { get; } public DateTimeOffset? ExpirationTime { get; } @@ -26,7 +25,7 @@ public ServerRoleBanDef( int? id, NetUserId? userId, (IPAddress, int)? address, - ImmutableArray? hwId, + ImmutableTypedHwid? hwId, DateTimeOffset banTime, DateTimeOffset? expirationTime, int? roundId, diff --git a/Content.Shared.Database/TypedHwid.cs b/Content.Shared.Database/TypedHwid.cs new file mode 100644 index 000000000000..6e4a7763b3a5 --- /dev/null +++ b/Content.Shared.Database/TypedHwid.cs @@ -0,0 +1,62 @@ +using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; + +namespace Content.Shared.Database; + +/// +/// Represents a raw HWID value together with its type. +/// +[Serializable] +public sealed class ImmutableTypedHwid(ImmutableArray hwid, HwidType type) +{ + public readonly ImmutableArray Hwid = hwid; + public readonly HwidType Type = type; + + public override string ToString() + { + var b64 = Convert.ToBase64String(Hwid.AsSpan()); + return Type == HwidType.Modern ? $"V2-{b64}" : b64; + } + + public static bool TryParse(string value, [NotNullWhen(true)] out ImmutableTypedHwid? hwid) + { + var type = HwidType.Legacy; + if (value.StartsWith("V2-", StringComparison.Ordinal)) + { + value = value["V2-".Length..]; + type = HwidType.Modern; + } + + var array = new byte[GetBase64ByteLength(value)]; + if (!Convert.TryFromBase64String(value, array, out _)) + { + hwid = null; + return false; + } + + hwid = new ImmutableTypedHwid([..array], type); + return true; + } + + private static int GetBase64ByteLength(string value) + { + // Why is .NET like this man wtf. + return 3 * (value.Length / 4) - value.TakeLast(2).Count(c => c == '='); + } +} + +/// +/// Represents different types of HWIDs as exposed by the engine. +/// +public enum HwidType +{ + /// + /// The legacy HWID system. Should only be used for checking old existing database bans. + /// + Legacy = 0, + + /// + /// The modern HWID system. + /// + Modern = 1, +} diff --git a/Content.Shared/Administration/BanPanelEuiState.cs b/Content.Shared/Administration/BanPanelEuiState.cs index dd10068e5da2..74c340566b5e 100644 --- a/Content.Shared/Administration/BanPanelEuiState.cs +++ b/Content.Shared/Administration/BanPanelEuiState.cs @@ -25,7 +25,7 @@ public sealed class CreateBanRequest : EuiMessageBase { public string? Player { get; set; } public string? IpAddress { get; set; } - public byte[]? Hwid { get; set; } + public ImmutableTypedHwid? Hwid { get; set; } public uint Minutes { get; set; } public string Reason { get; set; } public NoteSeverity Severity { get; set; } @@ -34,7 +34,7 @@ public sealed class CreateBanRequest : EuiMessageBase public bool UseLastHwid { get; set; } public bool Erase { get; set; } - public CreateBanRequest(string? player, (IPAddress, int)? ipAddress, bool useLastIp, byte[]? hwid, bool useLastHwid, uint minutes, string reason, NoteSeverity severity, string[]? roles, bool erase) + public CreateBanRequest(string? player, (IPAddress, int)? ipAddress, bool useLastIp, ImmutableTypedHwid? hwid, bool useLastHwid, uint minutes, string reason, NoteSeverity severity, string[]? roles, bool erase) { Player = player; IpAddress = ipAddress == null ? null : $"{ipAddress.Value.Item1}/{ipAddress.Value.Item2}"; From 806e1e46cb1fec598310d46c31e332e0876794c1 Mon Sep 17 00:00:00 2001 From: Simon <63975668+Simyon264@users.noreply.github.com> Date: Tue, 12 Nov 2024 03:10:25 +0100 Subject: [PATCH 070/290] Separate CCVars into separate files --- Content.Shared/CCVar/CCVars.Accessibility.cs | 41 + Content.Shared/CCVar/CCVars.Admin.Ahelp.cs | 39 + Content.Shared/CCVar/CCVars.Admin.Logs.cs | 42 + Content.Shared/CCVar/CCVars.Admin.Rules.cs | 18 + Content.Shared/CCVar/CCVars.Admin.cs | 163 ++ Content.Shared/CCVar/CCVars.Atmos.cs | 153 ++ Content.Shared/CCVar/CCVars.Audio.cs | 61 + Content.Shared/CCVar/CCVars.Chat.Looc.cs | 26 + Content.Shared/CCVar/CCVars.Chat.Ooc.cs | 27 + Content.Shared/CCVar/CCVars.Chat.cs | 68 + Content.Shared/CCVar/CCVars.Config.cs | 35 + Content.Shared/CCVar/CCVars.Console.cs | 15 + Content.Shared/CCVar/CCVars.Crewmanifest.cs | 24 + Content.Shared/CCVar/CCVars.Database.cs | 77 + Content.Shared/CCVar/CCVars.Discord.cs | 61 + Content.Shared/CCVar/CCVars.Events.cs | 12 + Content.Shared/CCVar/CCVars.Explosion.cs | 108 + Content.Shared/CCVar/CCVars.Game.Infolinks.cs | 54 + Content.Shared/CCVar/CCVars.Game.cs | 336 +++ Content.Shared/CCVar/CCVars.Ghost.cs | 24 + Content.Shared/CCVar/CCVars.Hud.cs | 24 + Content.Shared/CCVar/CCVars.Ic.cs | 48 + Content.Shared/CCVar/CCVars.Interactions.cs | 54 + Content.Shared/CCVar/CCVars.Interface.cs | 24 + Content.Shared/CCVar/CCVars.Mapping.cs | 24 + Content.Shared/CCVar/CCVars.Midi.cs | 18 + Content.Shared/CCVar/CCVars.Misc.cs | 97 + Content.Shared/CCVar/CCVars.NPC.cs | 16 + Content.Shared/CCVar/CCVars.Net.cs | 15 + Content.Shared/CCVar/CCVars.Parallax.cs | 15 + Content.Shared/CCVar/CCVars.Physics.cs | 27 + Content.Shared/CCVar/CCVars.Radiation.cs | 32 + Content.Shared/CCVar/CCVars.Replays.cs | 43 + Content.Shared/CCVar/CCVars.Salvage.cs | 18 + Content.Shared/CCVar/CCVars.Server.cs | 43 + Content.Shared/CCVar/CCVars.Shuttle.cs | 176 ++ Content.Shared/CCVar/CCVars.Sounds.cs | 34 + Content.Shared/CCVar/CCVars.Status.cs | 13 + Content.Shared/CCVar/CCVars.Tips.cs | 40 + Content.Shared/CCVar/CCVars.Viewport.cs | 33 + Content.Shared/CCVar/CCVars.Vote.cs | 180 ++ Content.Shared/CCVar/CCVars.Whitelist.cs | 19 + Content.Shared/CCVar/CCVars.Worldgen.cs | 18 + Content.Shared/CCVar/CCVars.cs | 2406 +---------------- 44 files changed, 2418 insertions(+), 2383 deletions(-) create mode 100644 Content.Shared/CCVar/CCVars.Accessibility.cs create mode 100644 Content.Shared/CCVar/CCVars.Admin.Ahelp.cs create mode 100644 Content.Shared/CCVar/CCVars.Admin.Logs.cs create mode 100644 Content.Shared/CCVar/CCVars.Admin.Rules.cs create mode 100644 Content.Shared/CCVar/CCVars.Admin.cs create mode 100644 Content.Shared/CCVar/CCVars.Atmos.cs create mode 100644 Content.Shared/CCVar/CCVars.Audio.cs create mode 100644 Content.Shared/CCVar/CCVars.Chat.Looc.cs create mode 100644 Content.Shared/CCVar/CCVars.Chat.Ooc.cs create mode 100644 Content.Shared/CCVar/CCVars.Chat.cs create mode 100644 Content.Shared/CCVar/CCVars.Config.cs create mode 100644 Content.Shared/CCVar/CCVars.Console.cs create mode 100644 Content.Shared/CCVar/CCVars.Crewmanifest.cs create mode 100644 Content.Shared/CCVar/CCVars.Database.cs create mode 100644 Content.Shared/CCVar/CCVars.Discord.cs create mode 100644 Content.Shared/CCVar/CCVars.Events.cs create mode 100644 Content.Shared/CCVar/CCVars.Explosion.cs create mode 100644 Content.Shared/CCVar/CCVars.Game.Infolinks.cs create mode 100644 Content.Shared/CCVar/CCVars.Game.cs create mode 100644 Content.Shared/CCVar/CCVars.Ghost.cs create mode 100644 Content.Shared/CCVar/CCVars.Hud.cs create mode 100644 Content.Shared/CCVar/CCVars.Ic.cs create mode 100644 Content.Shared/CCVar/CCVars.Interactions.cs create mode 100644 Content.Shared/CCVar/CCVars.Interface.cs create mode 100644 Content.Shared/CCVar/CCVars.Mapping.cs create mode 100644 Content.Shared/CCVar/CCVars.Midi.cs create mode 100644 Content.Shared/CCVar/CCVars.Misc.cs create mode 100644 Content.Shared/CCVar/CCVars.NPC.cs create mode 100644 Content.Shared/CCVar/CCVars.Net.cs create mode 100644 Content.Shared/CCVar/CCVars.Parallax.cs create mode 100644 Content.Shared/CCVar/CCVars.Physics.cs create mode 100644 Content.Shared/CCVar/CCVars.Radiation.cs create mode 100644 Content.Shared/CCVar/CCVars.Replays.cs create mode 100644 Content.Shared/CCVar/CCVars.Salvage.cs create mode 100644 Content.Shared/CCVar/CCVars.Server.cs create mode 100644 Content.Shared/CCVar/CCVars.Shuttle.cs create mode 100644 Content.Shared/CCVar/CCVars.Sounds.cs create mode 100644 Content.Shared/CCVar/CCVars.Status.cs create mode 100644 Content.Shared/CCVar/CCVars.Tips.cs create mode 100644 Content.Shared/CCVar/CCVars.Viewport.cs create mode 100644 Content.Shared/CCVar/CCVars.Vote.cs create mode 100644 Content.Shared/CCVar/CCVars.Whitelist.cs create mode 100644 Content.Shared/CCVar/CCVars.Worldgen.cs diff --git a/Content.Shared/CCVar/CCVars.Accessibility.cs b/Content.Shared/CCVar/CCVars.Accessibility.cs new file mode 100644 index 000000000000..8eb61f0806d2 --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Accessibility.cs @@ -0,0 +1,41 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + /// + /// Chat window opacity slider, controlling the alpha of the chat window background. + /// Goes from to 0 (completely transparent) to 1 (completely opaque) + /// + public static readonly CVarDef ChatWindowOpacity = + CVarDef.Create("accessibility.chat_window_transparency", 0.85f, CVar.CLIENTONLY | CVar.ARCHIVE); + + /// + /// Toggle for visual effects that may potentially cause motion sickness. + /// Where reasonable, effects affected by this CVar should use an alternate effect. + /// Please do not use this CVar as a bandaid for effects that could otherwise be made accessible without issue. + /// + public static readonly CVarDef ReducedMotion = + CVarDef.Create("accessibility.reduced_motion", false, CVar.CLIENTONLY | CVar.ARCHIVE); + + public static readonly CVarDef ChatEnableColorName = + CVarDef.Create("accessibility.enable_color_name", + true, + CVar.CLIENTONLY | CVar.ARCHIVE, + "Toggles displaying names with individual colors."); + + /// + /// Screen shake intensity slider, controlling the intensity of the CameraRecoilSystem. + /// Goes from 0 (no recoil at all) to 1 (regular amounts of recoil) + /// + public static readonly CVarDef ScreenShakeIntensity = + CVarDef.Create("accessibility.screen_shake_intensity", 1f, CVar.CLIENTONLY | CVar.ARCHIVE); + + /// + /// A generic toggle for various visual effects that are color sensitive. + /// As of 2/16/24, only applies to progress bar colors. + /// + public static readonly CVarDef AccessibilityColorblindFriendly = + CVarDef.Create("accessibility.colorblind_friendly", false, CVar.CLIENTONLY | CVar.ARCHIVE); +} diff --git a/Content.Shared/CCVar/CCVars.Admin.Ahelp.cs b/Content.Shared/CCVar/CCVars.Admin.Ahelp.cs new file mode 100644 index 000000000000..48f3965bb5c7 --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Admin.Ahelp.cs @@ -0,0 +1,39 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + /// + /// Ahelp rate limit values are accounted in periods of this size (seconds). + /// After the period has passed, the count resets. + /// + /// + public static readonly CVarDef AhelpRateLimitPeriod = + CVarDef.Create("ahelp.rate_limit_period", 2f, CVar.SERVERONLY); + + /// + /// How many ahelp messages are allowed in a single rate limit period. + /// + /// + public static readonly CVarDef AhelpRateLimitCount = + CVarDef.Create("ahelp.rate_limit_count", 10, CVar.SERVERONLY); + + /// + /// Should the administrator's position be displayed in ahelp. + /// If it is is false, only the admin's ckey will be displayed in the ahelp. + /// + /// + /// + public static readonly CVarDef AhelpAdminPrefix = + CVarDef.Create("ahelp.admin_prefix", false, CVar.SERVERONLY); + + /// + /// Should the administrator's position be displayed in the webhook. + /// If it is is false, only the admin's ckey will be displayed in webhook. + /// + /// + /// + public static readonly CVarDef AhelpAdminPrefixWebhook = + CVarDef.Create("ahelp.admin_prefix_webhook", false, CVar.SERVERONLY); +} diff --git a/Content.Shared/CCVar/CCVars.Admin.Logs.cs b/Content.Shared/CCVar/CCVars.Admin.Logs.cs new file mode 100644 index 000000000000..862456ddfdd9 --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Admin.Logs.cs @@ -0,0 +1,42 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + /// + /// Controls if admin logs are enabled. Highly recommended to shut this off for development. + /// + public static readonly CVarDef AdminLogsEnabled = + CVarDef.Create("adminlogs.enabled", true, CVar.SERVERONLY); + + public static readonly CVarDef AdminLogsQueueSendDelay = + CVarDef.Create("adminlogs.queue_send_delay_seconds", 5f, CVar.SERVERONLY); + + /// + /// When to skip the waiting time to save in-round admin logs, if no admin logs are currently being saved + /// + public static readonly CVarDef AdminLogsQueueMax = + CVarDef.Create("adminlogs.queue_max", 5000, CVar.SERVERONLY); + + /// + /// When to skip the waiting time to save pre-round admin logs, if no admin logs are currently being saved + /// + public static readonly CVarDef AdminLogsPreRoundQueueMax = + CVarDef.Create("adminlogs.pre_round_queue_max", 5000, CVar.SERVERONLY); + + /// + /// When to start dropping logs + /// + public static readonly CVarDef AdminLogsDropThreshold = + CVarDef.Create("adminlogs.drop_threshold", 20000, CVar.SERVERONLY); + + /// + /// How many logs to send to the client at once + /// + public static readonly CVarDef AdminLogsClientBatchSize = + CVarDef.Create("adminlogs.client_batch_size", 1000, CVar.SERVERONLY); + + public static readonly CVarDef AdminLogsServerName = + CVarDef.Create("adminlogs.server_name", "unknown", CVar.SERVERONLY); +} diff --git a/Content.Shared/CCVar/CCVars.Admin.Rules.cs b/Content.Shared/CCVar/CCVars.Admin.Rules.cs new file mode 100644 index 000000000000..7385104364b5 --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Admin.Rules.cs @@ -0,0 +1,18 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + /// + /// Time that players have to wait before rules can be accepted. + /// + public static readonly CVarDef RulesWaitTime = + CVarDef.Create("rules.time", 45f, CVar.SERVER | CVar.REPLICATED); + + /// + /// Don't show rules to localhost/loopback interface. + /// + public static readonly CVarDef RulesExemptLocal = + CVarDef.Create("rules.exempt_local", true, CVar.SERVERONLY); +} diff --git a/Content.Shared/CCVar/CCVars.Admin.cs b/Content.Shared/CCVar/CCVars.Admin.cs new file mode 100644 index 000000000000..28bebfbe8a65 --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Admin.cs @@ -0,0 +1,163 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + public static readonly CVarDef AdminAnnounceLogin = + CVarDef.Create("admin.announce_login", true, CVar.SERVERONLY); + + public static readonly CVarDef AdminAnnounceLogout = + CVarDef.Create("admin.announce_logout", true, CVar.SERVERONLY); + + /// + /// The token used to authenticate with the admin API. Leave empty to disable the admin API. This is a secret! Do not share! + /// + public static readonly CVarDef AdminApiToken = + CVarDef.Create("admin.api_token", string.Empty, CVar.SERVERONLY | CVar.CONFIDENTIAL); + + /// + /// Should users be able to see their own notes? Admins will be able to see and set notes regardless + /// + public static readonly CVarDef SeeOwnNotes = + CVarDef.Create("admin.see_own_notes", false, CVar.ARCHIVE | CVar.REPLICATED | CVar.SERVER); + + /// + /// Should the server play a quick sound to the active admins whenever a new player joins? + /// + public static readonly CVarDef AdminNewPlayerJoinSound = + CVarDef.Create("admin.new_player_join_sound", false, CVar.SERVERONLY); + + /// + /// The amount of days before the note starts fading. It will slowly lose opacity until it reaches stale. Set to 0 to disable. + /// + public static readonly CVarDef NoteFreshDays = + CVarDef.Create("admin.note_fresh_days", 91.31055, CVar.ARCHIVE | CVar.REPLICATED | CVar.SERVER); + + /// + /// The amount of days before the note completely fades, and can only be seen by admins if they press "see more notes". Set to 0 + /// if you want the note to immediately disappear without fading. + /// + public static readonly CVarDef NoteStaleDays = + CVarDef.Create("admin.note_stale_days", 365.2422, CVar.ARCHIVE | CVar.REPLICATED | CVar.SERVER); + + /// + /// How much time does the user have to wait in seconds before confirming that they saw an admin message? + /// + public static readonly CVarDef MessageWaitTime = + CVarDef.Create("admin.message_wait_time", 3f, CVar.ARCHIVE | CVar.REPLICATED | CVar.SERVER); + + /// + /// Default severity for role bans + /// + public static readonly CVarDef RoleBanDefaultSeverity = + CVarDef.Create("admin.role_ban_default_severity", "medium", CVar.ARCHIVE | CVar.SERVER | CVar.REPLICATED); + + /// + /// Default severity for department bans + /// + public static readonly CVarDef DepartmentBanDefaultSeverity = + CVarDef.Create("admin.department_ban_default_severity", "medium", CVar.ARCHIVE | CVar.SERVER | CVar.REPLICATED); + + /// + /// Default severity for server bans + /// + public static readonly CVarDef ServerBanDefaultSeverity = + CVarDef.Create("admin.server_ban_default_severity", "High", CVar.ARCHIVE | CVar.SERVER | CVar.REPLICATED); + + /// + /// Whether a server ban will ban the player's ip by default. + /// + public static readonly CVarDef ServerBanIpBanDefault = + CVarDef.Create("admin.server_ban_ip_ban_default", true, CVar.ARCHIVE | CVar.SERVER | CVar.REPLICATED); + + /// + /// Whether a server ban will ban the player's hardware id by default. + /// + public static readonly CVarDef ServerBanHwidBanDefault = + CVarDef.Create("admin.server_ban_hwid_ban_default", true, CVar.ARCHIVE | CVar.SERVER | CVar.REPLICATED); + + /// + /// Whether to use details from last connection for ip/hwid in the BanPanel. + /// + public static readonly CVarDef ServerBanUseLastDetails = + CVarDef.Create("admin.server_ban_use_last_details", true, CVar.ARCHIVE | CVar.SERVER | CVar.REPLICATED); + + /// + /// Whether to erase a player's chat messages and their entity from the game when banned. + /// + public static readonly CVarDef ServerBanErasePlayer = + CVarDef.Create("admin.server_ban_erase_player", false, CVar.ARCHIVE | CVar.SERVER | CVar.REPLICATED); + + /// + /// Minimum players sharing a connection required to create an alert. -1 to disable the alert. + /// + /// + /// If you set this to 0 or 1 then it will alert on every connection, so probably don't do that. + /// + public static readonly CVarDef AdminAlertMinPlayersSharingConnection = + CVarDef.Create("admin.alert.min_players_sharing_connection", -1, CVar.SERVERONLY); + + /// + /// Minimum explosion intensity to create an admin alert message. -1 to disable the alert. + /// + public static readonly CVarDef AdminAlertExplosionMinIntensity = + CVarDef.Create("admin.alert.explosion_min_intensity", 60, CVar.SERVERONLY); + + /// + /// Minimum particle accelerator strength to create an admin alert message. + /// + public static readonly CVarDef AdminAlertParticleAcceleratorMinPowerState = + CVarDef.Create("admin.alert.particle_accelerator_min_power_state", 5, CVar.SERVERONLY); // strength 4 + + /// + /// Should the ban details in admin channel include PII? (IP, HWID, etc) + /// + public static readonly CVarDef AdminShowPIIOnBan = + CVarDef.Create("admin.show_pii_onban", false, CVar.SERVERONLY); + + /// + /// If an admin joins a round by reading up or using the late join button, automatically + /// de-admin them. + /// + public static readonly CVarDef AdminDeadminOnJoin = + CVarDef.Create("admin.deadmin_on_join", false, CVar.SERVERONLY); + + /// + /// Overrides the name the client sees in ahelps. Set empty to disable. + /// + public static readonly CVarDef AdminAhelpOverrideClientName = + CVarDef.Create("admin.override_adminname_in_client_ahelp", string.Empty, CVar.SERVERONLY); + + /// + /// The threshold of minutes to appear as a "new player" in the ahelp menu + /// If 0, appearing as a new player is disabled. + /// + public static readonly CVarDef NewPlayerThreshold = + CVarDef.Create("admin.new_player_threshold", 0, CVar.ARCHIVE | CVar.REPLICATED | CVar.SERVER); + + /// + /// How long an admin client can go without any input before being considered AFK. + /// + public static readonly CVarDef AdminAfkTime = + CVarDef.Create("admin.afk_time", 600f, CVar.SERVERONLY); + + /// + /// If true, admins are able to connect even if + /// would otherwise block regular players. + /// + public static readonly CVarDef AdminBypassMaxPlayers = + CVarDef.Create("admin.bypass_max_players", true, CVar.SERVERONLY); + + /// + /// Determine if custom rank names are used. + /// If it is false, it'd use the actual rank name regardless of the individual's title. + /// + /// + /// + public static readonly CVarDef AdminUseCustomNamesAdminRank = + CVarDef.Create("admin.use_custom_names_admin_rank", true, CVar.SERVERONLY); + + public static readonly CVarDef BanHardwareIds = + CVarDef.Create("ban.hardware_ids", true, CVar.SERVERONLY); +} diff --git a/Content.Shared/CCVar/CCVars.Atmos.cs b/Content.Shared/CCVar/CCVars.Atmos.cs new file mode 100644 index 000000000000..cc1069b4fc87 --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Atmos.cs @@ -0,0 +1,153 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + /// + /// Whether gas differences will move entities. + /// + public static readonly CVarDef SpaceWind = + CVarDef.Create("atmos.space_wind", false, CVar.SERVERONLY); + + /// + /// Divisor from maxForce (pressureDifference * 2.25f) to force applied on objects. + /// + public static readonly CVarDef SpaceWindPressureForceDivisorThrow = + CVarDef.Create("atmos.space_wind_pressure_force_divisor_throw", 15f, CVar.SERVERONLY); + + /// + /// Divisor from maxForce (pressureDifference * 2.25f) to force applied on objects. + /// + public static readonly CVarDef SpaceWindPressureForceDivisorPush = + CVarDef.Create("atmos.space_wind_pressure_force_divisor_push", 2500f, CVar.SERVERONLY); + + /// + /// The maximum velocity (not force) that may be applied to an object by atmospheric pressure differences. + /// Useful to prevent clipping through objects. + /// + public static readonly CVarDef SpaceWindMaxVelocity = + CVarDef.Create("atmos.space_wind_max_velocity", 30f, CVar.SERVERONLY); + + /// + /// The maximum force that may be applied to an object by pushing (i.e. not throwing) atmospheric pressure differences. + /// A "throwing" atmospheric pressure difference ignores this limit, but not the max. velocity limit. + /// + public static readonly CVarDef SpaceWindMaxPushForce = + CVarDef.Create("atmos.space_wind_max_push_force", 20f, CVar.SERVERONLY); + + /// + /// Whether monstermos tile equalization is enabled. + /// + public static readonly CVarDef MonstermosEqualization = + CVarDef.Create("atmos.monstermos_equalization", true, CVar.SERVERONLY); + + /// + /// Whether monstermos explosive depressurization is enabled. + /// Needs to be enabled to work. + /// + public static readonly CVarDef MonstermosDepressurization = + CVarDef.Create("atmos.monstermos_depressurization", true, CVar.SERVERONLY); + + /// + /// Whether monstermos explosive depressurization will rip tiles.. + /// Needs and to be enabled to work. + /// WARNING: This cvar causes MAJOR contrast issues, and usually tends to make any spaced scene look very cluttered. + /// This not only usually looks strange, but can also reduce playability for people with impaired vision. Please think twice before enabling this on your server. + /// Also looks weird on slow spacing for unrelated reasons. If you do want to enable this, you should probably turn on instaspacing. + /// + public static readonly CVarDef MonstermosRipTiles = + CVarDef.Create("atmos.monstermos_rip_tiles", false, CVar.SERVERONLY); + + /// + /// Whether explosive depressurization will cause the grid to gain an impulse. + /// Needs and to be enabled to work. + /// + public static readonly CVarDef AtmosGridImpulse = + CVarDef.Create("atmos.grid_impulse", false, CVar.SERVERONLY); + + /// + /// What fraction of air from a spaced tile escapes every tick. + /// 1.0 for instant spacing, 0.2 means 20% of remaining air lost each time + /// + public static readonly CVarDef AtmosSpacingEscapeRatio = + CVarDef.Create("atmos.mmos_spacing_speed", 0.15f, CVar.SERVERONLY); + + /// + /// Minimum amount of air allowed on a spaced tile before it is reset to 0 immediately in kPa + /// Since the decay due to SpacingEscapeRatio follows a curve, it would never reach 0.0 exactly + /// unless we truncate it somewhere. + /// + public static readonly CVarDef AtmosSpacingMinGas = + CVarDef.Create("atmos.mmos_min_gas", 2.0f, CVar.SERVERONLY); + + /// + /// How much wind can go through a single tile before that tile doesn't depressurize itself + /// (I.e spacing is limited in large rooms heading into smaller spaces) + /// + public static readonly CVarDef AtmosSpacingMaxWind = + CVarDef.Create("atmos.mmos_max_wind", 500f, CVar.SERVERONLY); + + /// + /// Whether atmos superconduction is enabled. + /// + /// Disabled by default, superconduction is awful. + public static readonly CVarDef Superconduction = + CVarDef.Create("atmos.superconduction", false, CVar.SERVERONLY); + + /// + /// Heat loss per tile due to radiation at 20 degC, in W. + /// + public static readonly CVarDef SuperconductionTileLoss = + CVarDef.Create("atmos.superconduction_tile_loss", 30f, CVar.SERVERONLY); + + /// + /// Whether excited groups will be processed and created. + /// + public static readonly CVarDef ExcitedGroups = + CVarDef.Create("atmos.excited_groups", true, CVar.SERVERONLY); + + /// + /// Whether all tiles in an excited group will clear themselves once being exposed to space. + /// Similar to , without none of the tile ripping or + /// things being thrown around very violently. + /// Needs to be enabled to work. + /// + public static readonly CVarDef ExcitedGroupsSpaceIsAllConsuming = + CVarDef.Create("atmos.excited_groups_space_is_all_consuming", false, CVar.SERVERONLY); + + /// + /// Maximum time in milliseconds that atmos can take processing. + /// + public static readonly CVarDef AtmosMaxProcessTime = + CVarDef.Create("atmos.max_process_time", 3f, CVar.SERVERONLY); + + /// + /// Atmos tickrate in TPS. Atmos processing will happen every 1/TPS seconds. + /// + public static readonly CVarDef AtmosTickRate = + CVarDef.Create("atmos.tickrate", 15f, CVar.SERVERONLY); + + /// + /// Scale factor for how fast things happen in our atmosphere + /// simulation compared to real life. 1x means pumps run at 1x + /// speed. Players typically expect things to happen faster + /// in-game. + /// + public static readonly CVarDef AtmosSpeedup = + CVarDef.Create("atmos.speedup", 8f, CVar.SERVERONLY); + + /// + /// Like atmos.speedup, but only for gas and reaction heat values. 64x means + /// gases heat up and cool down 64x faster than real life. + /// + public static readonly CVarDef AtmosHeatScale = + CVarDef.Create("atmos.heat_scale", 8f, CVar.SERVERONLY); + + /// + /// Maximum explosion radius for explosions caused by bursting a gas tank ("max caps"). + /// Setting this to zero disables the explosion but still allows the tank to burst and leak. + /// + public static readonly CVarDef AtmosTankFragment = + CVarDef.Create("atmos.max_explosion_range", 26f, CVar.SERVERONLY); +} diff --git a/Content.Shared/CCVar/CCVars.Audio.cs b/Content.Shared/CCVar/CCVars.Audio.cs new file mode 100644 index 000000000000..4d9e7c44315f --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Audio.cs @@ -0,0 +1,61 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + /// + /// How long we'll wait until re-sampling nearby objects for ambience. Should be pretty fast, but doesn't have to match the tick rate. + /// + public static readonly CVarDef AmbientCooldown = + CVarDef.Create("ambience.cooldown", 0.1f, CVar.ARCHIVE | CVar.CLIENTONLY); + + /// + /// How large of a range to sample for ambience. + /// + public static readonly CVarDef AmbientRange = + CVarDef.Create("ambience.range", 8f, CVar.REPLICATED | CVar.SERVER); + + /// + /// Maximum simultaneous ambient sounds. + /// + public static readonly CVarDef MaxAmbientSources = + CVarDef.Create("ambience.max_sounds", 16, CVar.ARCHIVE | CVar.CLIENTONLY); + + /// + /// The minimum value the user can set for ambience.max_sounds + /// + public static readonly CVarDef MinMaxAmbientSourcesConfigured = + CVarDef.Create("ambience.min_max_sounds_configured", 16, CVar.REPLICATED | CVar.SERVER | CVar.CHEAT); + + /// + /// The maximum value the user can set for ambience.max_sounds + /// + public static readonly CVarDef MaxMaxAmbientSourcesConfigured = + CVarDef.Create("ambience.max_max_sounds_configured", 64, CVar.REPLICATED | CVar.SERVER | CVar.CHEAT); + + /// + /// Ambience volume. + /// + public static readonly CVarDef AmbienceVolume = + CVarDef.Create("ambience.volume", 1.5f, CVar.ARCHIVE | CVar.CLIENTONLY); + + /// + /// Ambience music volume. + /// + public static readonly CVarDef AmbientMusicVolume = + CVarDef.Create("ambience.music_volume", 1.5f, CVar.ARCHIVE | CVar.CLIENTONLY); + + /// + /// Lobby / round end music volume. + /// + public static readonly CVarDef LobbyMusicVolume = + CVarDef.Create("ambience.lobby_music_volume", 0.50f, CVar.ARCHIVE | CVar.CLIENTONLY); + + /// + /// UI volume. + /// + public static readonly CVarDef InterfaceVolume = + CVarDef.Create("audio.interface_volume", 0.50f, CVar.ARCHIVE | CVar.CLIENTONLY); + +} diff --git a/Content.Shared/CCVar/CCVars.Chat.Looc.cs b/Content.Shared/CCVar/CCVars.Chat.Looc.cs new file mode 100644 index 000000000000..84ee2c280723 --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Chat.Looc.cs @@ -0,0 +1,26 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + public static readonly CVarDef LoocEnabled = + CVarDef.Create("looc.enabled", true, CVar.NOTIFY | CVar.REPLICATED); + + public static readonly CVarDef AdminLoocEnabled = + CVarDef.Create("looc.enabled_admin", true, CVar.NOTIFY); + + /// + /// True: Dead players can use LOOC + /// False: Dead player LOOC gets redirected to dead chat + /// + public static readonly CVarDef DeadLoocEnabled = + CVarDef.Create("looc.enabled_dead", false, CVar.NOTIFY | CVar.REPLICATED); + + /// + /// True: Crit players can use LOOC + /// False: Crit player LOOC gets redirected to dead chat + /// + public static readonly CVarDef CritLoocEnabled = + CVarDef.Create("looc.enabled_crit", false, CVar.NOTIFY | CVar.REPLICATED); +} diff --git a/Content.Shared/CCVar/CCVars.Chat.Ooc.cs b/Content.Shared/CCVar/CCVars.Chat.Ooc.cs new file mode 100644 index 000000000000..ba5e41053b6d --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Chat.Ooc.cs @@ -0,0 +1,27 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + public static readonly CVarDef + OocEnabled = CVarDef.Create("ooc.enabled", true, CVar.NOTIFY | CVar.REPLICATED); + + public static readonly CVarDef AdminOocEnabled = + CVarDef.Create("ooc.enabled_admin", true, CVar.NOTIFY); + + /// + /// If true, whenever OOC is disabled the Discord OOC relay will also be disabled. + /// + public static readonly CVarDef DisablingOOCDisablesRelay = + CVarDef.Create("ooc.disabling_ooc_disables_relay", true, CVar.SERVERONLY); + + /// + /// Whether or not OOC chat should be enabled during a round. + /// + public static readonly CVarDef OocEnableDuringRound = + CVarDef.Create("ooc.enable_during_round", false, CVar.NOTIFY | CVar.REPLICATED | CVar.SERVER); + + public static readonly CVarDef ShowOocPatronColor = + CVarDef.Create("ooc.show_ooc_patron_color", true, CVar.ARCHIVE | CVar.REPLICATED | CVar.CLIENT); +} diff --git a/Content.Shared/CCVar/CCVars.Chat.cs b/Content.Shared/CCVar/CCVars.Chat.cs new file mode 100644 index 000000000000..139a82372a26 --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Chat.cs @@ -0,0 +1,68 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + /// + /// Chat rate limit values are accounted in periods of this size (seconds). + /// After the period has passed, the count resets. + /// + /// + public static readonly CVarDef ChatRateLimitPeriod = + CVarDef.Create("chat.rate_limit_period", 2f, CVar.SERVERONLY); + + /// + /// How many chat messages are allowed in a single rate limit period. + /// + /// + /// The total rate limit throughput per second is effectively + /// divided by . + /// + /// + public static readonly CVarDef ChatRateLimitCount = + CVarDef.Create("chat.rate_limit_count", 10, CVar.SERVERONLY); + + /// + /// Minimum delay (in seconds) between notifying admins about chat message rate limit violations. + /// A negative value disables admin announcements. + /// + public static readonly CVarDef ChatRateLimitAnnounceAdminsDelay = + CVarDef.Create("chat.rate_limit_announce_admins_delay", 15, CVar.SERVERONLY); + + public static readonly CVarDef ChatMaxMessageLength = + CVarDef.Create("chat.max_message_length", 1000, CVar.SERVER | CVar.REPLICATED); + + public static readonly CVarDef ChatMaxAnnouncementLength = + CVarDef.Create("chat.max_announcement_length", 256, CVar.SERVER | CVar.REPLICATED); + + public static readonly CVarDef ChatSanitizerEnabled = + CVarDef.Create("chat.chat_sanitizer_enabled", true, CVar.SERVERONLY); + + public static readonly CVarDef ChatShowTypingIndicator = + CVarDef.Create("chat.show_typing_indicator", true, CVar.ARCHIVE | CVar.REPLICATED | CVar.SERVER); + + public static readonly CVarDef ChatEnableFancyBubbles = + CVarDef.Create("chat.enable_fancy_bubbles", + true, + CVar.CLIENTONLY | CVar.ARCHIVE, + "Toggles displaying fancy speech bubbles, which display the speaking character's name."); + + public static readonly CVarDef ChatFancyNameBackground = + CVarDef.Create("chat.fancy_name_background", + false, + CVar.CLIENTONLY | CVar.ARCHIVE, + "Toggles displaying a background under the speaking character's name."); + + /// + /// A message broadcast to each player that joins the lobby. + /// May be changed by admins ingame through use of the "set-motd" command. + /// In this case the new value, if not empty, is broadcast to all connected players and saved between rounds. + /// May be requested by any player through use of the "get-motd" command. + /// + public static readonly CVarDef MOTD = + CVarDef.Create("chat.motd", + "", + CVar.SERVER | CVar.SERVERONLY | CVar.ARCHIVE, + "A message broadcast to each player that joins the lobby."); +} diff --git a/Content.Shared/CCVar/CCVars.Config.cs b/Content.Shared/CCVar/CCVars.Config.cs new file mode 100644 index 000000000000..4e11f09ee7ce --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Config.cs @@ -0,0 +1,35 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + // These are server-only for now since I don't foresee a client use yet, + // and I don't wanna have to start coming up with like .client suffixes and stuff like that. + + /// + /// Configuration presets to load during startup. + /// Multiple presets can be separated by comma and are loaded in order. + /// + /// + /// Loaded presets must be located under the ConfigPresets/ resource directory and end with the .toml extension. + /// Only the file name (without extension) must be given for this variable. + /// + public static readonly CVarDef ConfigPresets = + CVarDef.Create("config.presets", "", CVar.SERVERONLY); + + /// + /// Whether to load the preset development CVars. + /// This disables some things like lobby to make development easier. + /// Even when true, these are only loaded if the game is compiled with DEVELOPMENT set. + /// + public static readonly CVarDef ConfigPresetDevelopment = + CVarDef.Create("config.preset_development", true, CVar.SERVERONLY); + + /// + /// Whether to load the preset debug CVars. + /// Even when true, these are only loaded if the game is compiled with DEBUG set. + /// + public static readonly CVarDef ConfigPresetDebug = + CVarDef.Create("config.preset_debug", true, CVar.SERVERONLY); +} diff --git a/Content.Shared/CCVar/CCVars.Console.cs b/Content.Shared/CCVar/CCVars.Console.cs new file mode 100644 index 000000000000..e670b9f836ec --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Console.cs @@ -0,0 +1,15 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + public static readonly CVarDef ConsoleLoginLocal = + CVarDef.Create("console.loginlocal", true, CVar.ARCHIVE | CVar.SERVERONLY); + + /// + /// Automatically log in the given user as host, equivalent to the promotehost command. + /// + public static readonly CVarDef ConsoleLoginHostUser = + CVarDef.Create("console.login_host_user", "", CVar.ARCHIVE | CVar.SERVERONLY); +} diff --git a/Content.Shared/CCVar/CCVars.Crewmanifest.cs b/Content.Shared/CCVar/CCVars.Crewmanifest.cs new file mode 100644 index 000000000000..d6251886b950 --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Crewmanifest.cs @@ -0,0 +1,24 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + /// + /// Setting this allows a crew manifest to be opened from any window + /// that has a crew manifest button, and sends the correct message. + /// If this is false, only in-game entities will allow you to see + /// the crew manifest, if the functionality is coded in. + /// Having administrator priveledge ignores this, but will still + /// hide the button in UI windows. + /// + public static readonly CVarDef CrewManifestWithoutEntity = + CVarDef.Create("crewmanifest.no_entity", true, CVar.REPLICATED); + + /// + /// Setting this allows the crew manifest to be viewed from 'unsecure' + /// entities, such as the PDA. + /// + public static readonly CVarDef CrewManifestUnsecure = + CVarDef.Create("crewmanifest.unsecure", true, CVar.REPLICATED); +} diff --git a/Content.Shared/CCVar/CCVars.Database.cs b/Content.Shared/CCVar/CCVars.Database.cs new file mode 100644 index 000000000000..c549bd7e033a --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Database.cs @@ -0,0 +1,77 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ +#if DEBUG + private const int DefaultSqliteDelay = 1; +#else + private const int DefaultSqliteDelay = 0; +#endif + + public static readonly CVarDef DatabaseEngine = + CVarDef.Create("database.engine", "sqlite", CVar.SERVERONLY); + + public static readonly CVarDef DatabaseSqliteDbPath = + CVarDef.Create("database.sqlite_dbpath", "preferences.db", CVar.SERVERONLY); + + /// + /// Milliseconds to asynchronously delay all SQLite database acquisitions with. + /// + /// + /// Defaults to 1 on DEBUG, 0 on RELEASE. + /// This is intended to help catch .Result deadlock bugs that only happen on postgres + /// (because SQLite is not actually asynchronous normally) + /// + public static readonly CVarDef DatabaseSqliteDelay = + CVarDef.Create("database.sqlite_delay", DefaultSqliteDelay, CVar.SERVERONLY); + + /// + /// Amount of concurrent SQLite database operations. + /// + /// + /// Note that SQLite is not a properly asynchronous database and also has limited read/write concurrency. + /// Increasing this number may allow more concurrent reads, but it probably won't matter much. + /// SQLite operations are normally ran on the thread pool, which may cause thread pool starvation if the concurrency is too high. + /// + public static readonly CVarDef DatabaseSqliteConcurrency = + CVarDef.Create("database.sqlite_concurrency", 3, CVar.SERVERONLY); + + public static readonly CVarDef DatabasePgHost = + CVarDef.Create("database.pg_host", "localhost", CVar.SERVERONLY); + + public static readonly CVarDef DatabasePgPort = + CVarDef.Create("database.pg_port", 5432, CVar.SERVERONLY); + + public static readonly CVarDef DatabasePgDatabase = + CVarDef.Create("database.pg_database", "ss14", CVar.SERVERONLY); + + public static readonly CVarDef DatabasePgUsername = + CVarDef.Create("database.pg_username", "postgres", CVar.SERVERONLY); + + public static readonly CVarDef DatabasePgPassword = + CVarDef.Create("database.pg_password", "", CVar.SERVERONLY | CVar.CONFIDENTIAL); + + /// + /// Max amount of concurrent Postgres database operations. + /// + public static readonly CVarDef DatabasePgConcurrency = + CVarDef.Create("database.pg_concurrency", 8, CVar.SERVERONLY); + + /// + /// Milliseconds to asynchronously delay all PostgreSQL database operations with. + /// + /// + /// This is intended for performance testing. It works different from , + /// as the lag is applied after acquiring the database lock. + /// + public static readonly CVarDef DatabasePgFakeLag = + CVarDef.Create("database.pg_fake_lag", 0, CVar.SERVERONLY); + + /// + /// Basically only exists for integration tests to avoid race conditions. + /// + public static readonly CVarDef DatabaseSynchronous = + CVarDef.Create("database.sync", false, CVar.SERVERONLY); +} diff --git a/Content.Shared/CCVar/CCVars.Discord.cs b/Content.Shared/CCVar/CCVars.Discord.cs new file mode 100644 index 000000000000..a6c4ada74541 --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Discord.cs @@ -0,0 +1,61 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + /// + /// The role that will get mentioned if a new SOS ahelp comes in. + /// + public static readonly CVarDef DiscordAhelpMention = + CVarDef.Create("discord.on_call_ping", string.Empty, CVar.SERVERONLY | CVar.CONFIDENTIAL); + + /// + /// URL of the discord webhook to relay unanswered ahelp messages. + /// + public static readonly CVarDef DiscordOnCallWebhook = + CVarDef.Create("discord.on_call_webhook", string.Empty, CVar.SERVERONLY | CVar.CONFIDENTIAL); + + /// + /// URL of the Discord webhook which will relay all ahelp messages. + /// + public static readonly CVarDef DiscordAHelpWebhook = + CVarDef.Create("discord.ahelp_webhook", string.Empty, CVar.SERVERONLY | CVar.CONFIDENTIAL); + + /// + /// The server icon to use in the Discord ahelp embed footer. + /// Valid values are specified at https://discord.com/developers/docs/resources/channel#embed-object-embed-footer-structure. + /// + public static readonly CVarDef DiscordAHelpFooterIcon = + CVarDef.Create("discord.ahelp_footer_icon", string.Empty, CVar.SERVERONLY); + + /// + /// The avatar to use for the webhook. Should be an URL. + /// + public static readonly CVarDef DiscordAHelpAvatar = + CVarDef.Create("discord.ahelp_avatar", string.Empty, CVar.SERVERONLY); + + /// + /// URL of the Discord webhook which will relay all custom votes. If left empty, disables the webhook. + /// + public static readonly CVarDef DiscordVoteWebhook = + CVarDef.Create("discord.vote_webhook", string.Empty, CVar.SERVERONLY); + + /// + /// URL of the Discord webhook which will relay all votekick votes. If left empty, disables the webhook. + /// + public static readonly CVarDef DiscordVotekickWebhook = + CVarDef.Create("discord.votekick_webhook", string.Empty, CVar.SERVERONLY); + + /// + /// URL of the Discord webhook which will relay round restart messages. + /// + public static readonly CVarDef DiscordRoundUpdateWebhook = + CVarDef.Create("discord.round_update_webhook", string.Empty, CVar.SERVERONLY | CVar.CONFIDENTIAL); + + /// + /// Role id for the Discord webhook to ping when the round ends. + /// + public static readonly CVarDef DiscordRoundEndRoleWebhook = + CVarDef.Create("discord.round_end_role", string.Empty, CVar.SERVERONLY); +} diff --git a/Content.Shared/CCVar/CCVars.Events.cs b/Content.Shared/CCVar/CCVars.Events.cs new file mode 100644 index 000000000000..48797b8438cf --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Events.cs @@ -0,0 +1,12 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + /// + /// Controls if the game should run station events + /// + public static readonly CVarDef + EventsEnabled = CVarDef.Create("events.enabled", true, CVar.ARCHIVE | CVar.SERVERONLY); +} diff --git a/Content.Shared/CCVar/CCVars.Explosion.cs b/Content.Shared/CCVar/CCVars.Explosion.cs new file mode 100644 index 000000000000..51d93456b7e6 --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Explosion.cs @@ -0,0 +1,108 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + /// + /// How many tiles the explosion system will process per tick + /// + /// + /// Setting this too high will put a large load on a single tick. Setting this too low will lead to + /// unnaturally "slow" explosions. + /// + public static readonly CVarDef ExplosionTilesPerTick = + CVarDef.Create("explosion.tiles_per_tick", 100, CVar.SERVERONLY); + + /// + /// Upper limit on the size of an explosion before physics-throwing is disabled. + /// + /// + /// Large nukes tend to generate a lot of shrapnel that flies through space. This can functionally cripple + /// the server TPS for a while after an explosion (or even during, if the explosion is processed + /// incrementally. + /// + public static readonly CVarDef ExplosionThrowLimit = + CVarDef.Create("explosion.throw_limit", 400, CVar.SERVERONLY); + + /// + /// If this is true, explosion processing will pause the NodeGroupSystem to pause updating. + /// + /// + /// This only takes effect if an explosion needs more than one tick to process (i.e., covers more than tiles). If this is not enabled, the node-system will rebuild its graph + /// every tick as the explosion shreds the station, causing significant slowdown. + /// + public static readonly CVarDef ExplosionSleepNodeSys = + CVarDef.Create("explosion.node_sleep", true, CVar.SERVERONLY); + + /// + /// Upper limit on the total area that an explosion can affect before the neighbor-finding algorithm just + /// stops. Defaults to a 60-rile radius explosion. + /// + /// + /// Actual area may be larger, as it currently doesn't terminate mid neighbor finding. I.e., area may be that of a ~51 tile radius circle instead. + /// + public static readonly CVarDef ExplosionMaxArea = + CVarDef.Create("explosion.max_area", (int)3.14f * 256 * 256, CVar.SERVERONLY); + + /// + /// Upper limit on the number of neighbor finding steps for the explosion system neighbor-finding algorithm. + /// + /// + /// Effectively places an upper limit on the range that any explosion can have. In the vast majority of + /// instances, will likely be hit before this becomes a limiting factor. + /// + public static readonly CVarDef ExplosionMaxIterations = + CVarDef.Create("explosion.max_iterations", 500, CVar.SERVERONLY); + + /// + /// Max Time in milliseconds to spend processing explosions every tick. + /// + /// + /// This time limiting is not perfectly implemented. Firstly, a significant chunk of processing time happens + /// due to queued entity deletions, which happen outside of the system update code. Secondly, explosion + /// spawning cannot currently be interrupted & resumed, and may lead to exceeding this time limit. + /// + public static readonly CVarDef ExplosionMaxProcessingTime = + CVarDef.Create("explosion.max_tick_time", 7f, CVar.SERVERONLY); + + /// + /// If the explosion is being processed incrementally over several ticks, this variable determines whether + /// updating the grid tiles should be done incrementally at the end of every tick, or only once the explosion has finished processing. + /// + /// + /// The most notable consequence of this change is that explosions will only punch a hole in the station & + /// create a vacumm once they have finished exploding. So airlocks will no longer slam shut as the explosion + /// expands, just suddenly at the end. + /// + public static readonly CVarDef ExplosionIncrementalTileBreaking = + CVarDef.Create("explosion.incremental_tile", false, CVar.SERVERONLY); + + /// + /// This determines for how many seconds an explosion should stay visible once it has finished expanding. + /// + public static readonly CVarDef ExplosionPersistence = + CVarDef.Create("explosion.persistence", 1.0f, CVar.SERVERONLY); + + /// + /// If an explosion covers a larger area than this number, the damaging/processing will always start during + /// the next tick, instead of during the same tick that the explosion was generated in. + /// + /// + /// This value can be used to ensure that for large explosions the area/tile calculation and the explosion + /// processing/damaging occurs in separate ticks. This helps reduce the single-tick lag if both and are large. I.e., instead of + /// a single tick explosion, this cvar allows for a configuration that results in a two-tick explosion, + /// though most of the computational cost is still in the second tick. + /// + public static readonly CVarDef ExplosionSingleTickAreaLimit = + CVarDef.Create("explosion.single_tick_area_limit", 400, CVar.SERVERONLY); + + /// + /// Whether or not explosions are allowed to create tiles that have + /// set to true. + /// + public static readonly CVarDef ExplosionCanCreateVacuum = + CVarDef.Create("explosion.can_create_vacuum", true, CVar.SERVERONLY); +} diff --git a/Content.Shared/CCVar/CCVars.Game.Infolinks.cs b/Content.Shared/CCVar/CCVars.Game.Infolinks.cs new file mode 100644 index 000000000000..fa8332b497ef --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Game.Infolinks.cs @@ -0,0 +1,54 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + /// + /// Link to Discord server to show in the launcher. + /// + public static readonly CVarDef InfoLinksDiscord = + CVarDef.Create("infolinks.discord", "", CVar.SERVER | CVar.REPLICATED); + + /// + /// Link to website to show in the launcher. + /// + public static readonly CVarDef InfoLinksForum = + CVarDef.Create("infolinks.forum", "", CVar.SERVER | CVar.REPLICATED); + + /// + /// Link to GitHub page to show in the launcher. + /// + public static readonly CVarDef InfoLinksGithub = + CVarDef.Create("infolinks.github", "", CVar.SERVER | CVar.REPLICATED); + + /// + /// Link to website to show in the launcher. + /// + public static readonly CVarDef InfoLinksWebsite = + CVarDef.Create("infolinks.website", "", CVar.SERVER | CVar.REPLICATED); + + /// + /// Link to wiki to show in the launcher. + /// + public static readonly CVarDef InfoLinksWiki = + CVarDef.Create("infolinks.wiki", "", CVar.SERVER | CVar.REPLICATED); + + /// + /// Link to Patreon. Not shown in the launcher currently. + /// + public static readonly CVarDef InfoLinksPatreon = + CVarDef.Create("infolinks.patreon", "", CVar.SERVER | CVar.REPLICATED); + + /// + /// Link to the bug report form. + /// + public static readonly CVarDef InfoLinksBugReport = + CVarDef.Create("infolinks.bug_report", "", CVar.SERVER | CVar.REPLICATED); + + /// + /// Link to site handling ban appeals. Shown in ban disconnect messages. + /// + public static readonly CVarDef InfoLinksAppeal = + CVarDef.Create("infolinks.appeal", "", CVar.SERVER | CVar.REPLICATED); +} diff --git a/Content.Shared/CCVar/CCVars.Game.cs b/Content.Shared/CCVar/CCVars.Game.cs new file mode 100644 index 000000000000..19092055e39f --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Game.cs @@ -0,0 +1,336 @@ +using Content.Shared.Roles; +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + /// + /// Disables most functionality in the GameTicker. + /// + public static readonly CVarDef + GameDummyTicker = CVarDef.Create("game.dummyticker", false, CVar.ARCHIVE | CVar.SERVERONLY); + + /// + /// Controls if the lobby is enabled. If it is not, and there are no available jobs, you may get stuck on a black screen. + /// + public static readonly CVarDef + GameLobbyEnabled = CVarDef.Create("game.lobbyenabled", true, CVar.ARCHIVE); + + /// + /// Controls the duration of the lobby timer in seconds. Defaults to 2 minutes and 30 seconds. + /// + public static readonly CVarDef + GameLobbyDuration = CVarDef.Create("game.lobbyduration", 150, CVar.ARCHIVE); + + /// + /// Controls if players can latejoin at all. + /// + public static readonly CVarDef + GameDisallowLateJoins = CVarDef.Create("game.disallowlatejoins", false, CVar.ARCHIVE | CVar.SERVERONLY); + + /// + /// Controls the default game preset. + /// + public static readonly CVarDef + GameLobbyDefaultPreset = CVarDef.Create("game.defaultpreset", "secret", CVar.ARCHIVE); + + /// + /// Controls if the game can force a different preset if the current preset's criteria are not met. + /// + public static readonly CVarDef + GameLobbyFallbackEnabled = CVarDef.Create("game.fallbackenabled", true, CVar.ARCHIVE); + + /// + /// The preset for the game to fall back to if the selected preset could not be used, and fallback is enabled. + /// + public static readonly CVarDef + GameLobbyFallbackPreset = CVarDef.Create("game.fallbackpreset", "Traitor,Extended", CVar.ARCHIVE); + + /// + /// Controls if people can win the game in Suspicion or Deathmatch. + /// + public static readonly CVarDef + GameLobbyEnableWin = CVarDef.Create("game.enablewin", true, CVar.ARCHIVE); + + /// + /// Controls the maximum number of character slots a player is allowed to have. + /// + public static readonly CVarDef + GameMaxCharacterSlots = CVarDef.Create("game.maxcharacterslots", 30, CVar.ARCHIVE | CVar.SERVERONLY); + + /// + /// Controls the game map prototype to load. SS14 stores these prototypes in Prototypes/Maps. + /// + public static readonly CVarDef + GameMap = CVarDef.Create("game.map", string.Empty, CVar.SERVERONLY); + + /// + /// Controls whether to use world persistence or not. + /// + public static readonly CVarDef + UsePersistence = CVarDef.Create("game.usepersistence", false, CVar.ARCHIVE); + + /// + /// If world persistence is used, what map prototype should be initially loaded. + /// If the save file exists, it replaces MapPath but everything else stays the same (station name and such). + /// + public static readonly CVarDef + PersistenceMap = CVarDef.Create("game.persistencemap", "Empty", CVar.ARCHIVE); + + /// + /// Prototype to use for map pool. + /// + public static readonly CVarDef + GameMapPool = CVarDef.Create("game.map_pool", "DefaultMapPool", CVar.SERVERONLY); + + /// + /// The depth of the queue used to calculate which map is next in rotation. + /// This is how long the game "remembers" that some map was put in play. Default is 16 rounds. + /// + public static readonly CVarDef + GameMapMemoryDepth = CVarDef.Create("game.map_memory_depth", 16, CVar.SERVERONLY); + + /// + /// Is map rotation enabled? + /// + public static readonly CVarDef + GameMapRotation = CVarDef.Create("game.map_rotation", true, CVar.SERVERONLY); + + /// + /// If roles should be restricted based on time. + /// + public static readonly CVarDef + GameRoleTimers = CVarDef.Create("game.role_timers", true, CVar.SERVER | CVar.REPLICATED); + + /// + /// Override default role requirements using a + /// + public static readonly CVarDef + GameRoleTimerOverride = CVarDef.Create("game.role_timer_override", "", CVar.SERVER | CVar.REPLICATED); + + /// + /// If roles should be restricted based on whether or not they are whitelisted. + /// + public static readonly CVarDef + GameRoleWhitelist = CVarDef.Create("game.role_whitelist", true, CVar.SERVER | CVar.REPLICATED); + + /// + /// Whether or not disconnecting inside of a cryopod should remove the character or just store them until they reconnect. + /// + public static readonly CVarDef + GameCryoSleepRejoining = CVarDef.Create("game.cryo_sleep_rejoining", false, CVar.SERVER | CVar.REPLICATED); + + /// + /// When enabled, guests will be assigned permanent UIDs and will have their preferences stored. + /// + public static readonly CVarDef GamePersistGuests = + CVarDef.Create("game.persistguests", true, CVar.ARCHIVE | CVar.SERVERONLY); + + public static readonly CVarDef GameDiagonalMovement = + CVarDef.Create("game.diagonalmovement", true, CVar.ARCHIVE); + + public static readonly CVarDef SoftMaxPlayers = + CVarDef.Create("game.soft_max_players", 30, CVar.SERVERONLY | CVar.ARCHIVE); + + /// + /// If a player gets denied connection to the server, + /// how long they are forced to wait before attempting to reconnect. + /// + public static readonly CVarDef GameServerFullReconnectDelay = + CVarDef.Create("game.server_full_reconnect_delay", 30, CVar.SERVERONLY); + + /// + /// Whether or not panic bunker is currently enabled. + /// + public static readonly CVarDef PanicBunkerEnabled = + CVarDef.Create("game.panic_bunker.enabled", false, CVar.NOTIFY | CVar.REPLICATED | CVar.SERVER); + + /// + /// Whether or not the panic bunker will disable when an admin comes online. + /// + public static readonly CVarDef PanicBunkerDisableWithAdmins = + CVarDef.Create("game.panic_bunker.disable_with_admins", false, CVar.SERVERONLY); + + /// + /// Whether or not the panic bunker will enable when no admins are online. + /// + public static readonly CVarDef PanicBunkerEnableWithoutAdmins = + CVarDef.Create("game.panic_bunker.enable_without_admins", false, CVar.SERVERONLY); + + /// + /// Whether or not the panic bunker will count deadminned admins for + /// and + /// + /// + public static readonly CVarDef PanicBunkerCountDeadminnedAdmins = + CVarDef.Create("game.panic_bunker.count_deadminned_admins", false, CVar.SERVERONLY); + + /// + /// Show reason of disconnect for user or not. + /// + public static readonly CVarDef PanicBunkerShowReason = + CVarDef.Create("game.panic_bunker.show_reason", false, CVar.SERVERONLY); + + /// + /// Minimum age of the account (from server's PoV, so from first-seen date) in minutes. + /// + public static readonly CVarDef PanicBunkerMinAccountAge = + CVarDef.Create("game.panic_bunker.min_account_age", 1440, CVar.SERVERONLY); + + /// + /// Minimal overall played time. + /// + public static readonly CVarDef PanicBunkerMinOverallMinutes = + CVarDef.Create("game.panic_bunker.min_overall_minutes", 600, CVar.SERVERONLY); + + /// + /// A custom message that will be used for connections denied to the panic bunker + /// If not empty, then will overwrite + /// + public static readonly CVarDef PanicBunkerCustomReason = + CVarDef.Create("game.panic_bunker.custom_reason", string.Empty, CVar.SERVERONLY); + + /// + /// Allow bypassing the panic bunker if the user is whitelisted. + /// + public static readonly CVarDef BypassBunkerWhitelist = + CVarDef.Create("game.panic_bunker.whitelisted_can_bypass", true, CVar.SERVERONLY); + + /* + * TODO: Remove baby jail code once a more mature gateway process is established. This code is only being issued as a stopgap to help with potential tiding in the immediate future. + */ + + /// + /// Whether the baby jail is currently enabled. + /// + public static readonly CVarDef BabyJailEnabled = + CVarDef.Create("game.baby_jail.enabled", false, CVar.NOTIFY | CVar.REPLICATED | CVar.SERVER); + + /// + /// Show reason of disconnect for user or not. + /// + public static readonly CVarDef BabyJailShowReason = + CVarDef.Create("game.baby_jail.show_reason", false, CVar.SERVERONLY); + + /// + /// Maximum age of the account (from server's PoV, so from first-seen date) in minutes that can access baby + /// jailed servers. + /// + public static readonly CVarDef BabyJailMaxAccountAge = + CVarDef.Create("game.baby_jail.max_account_age", 1440, CVar.SERVERONLY); + + /// + /// Maximum overall played time allowed to access baby jailed servers. + /// + public static readonly CVarDef BabyJailMaxOverallMinutes = + CVarDef.Create("game.baby_jail.max_overall_minutes", 120, CVar.SERVERONLY); + + /// + /// A custom message that will be used for connections denied due to the baby jail. + /// If not empty, then will overwrite + /// + public static readonly CVarDef BabyJailCustomReason = + CVarDef.Create("game.baby_jail.custom_reason", string.Empty, CVar.SERVERONLY); + + /// + /// Allow bypassing the baby jail if the user is whitelisted. + /// + public static readonly CVarDef BypassBabyJailWhitelist = + CVarDef.Create("game.baby_jail.whitelisted_can_bypass", true, CVar.SERVERONLY); + + /// + /// Make people bonk when trying to climb certain objects like tables. + /// + public static readonly CVarDef GameTableBonk = + CVarDef.Create("game.table_bonk", false, CVar.REPLICATED); + + /// + /// Whether or not status icons are rendered for everyone. + /// + public static readonly CVarDef GlobalStatusIconsEnabled = + CVarDef.Create("game.global_status_icons_enabled", true, CVar.SERVER | CVar.REPLICATED); + + /// + /// Whether or not status icons are rendered on this specific client. + /// + public static readonly CVarDef LocalStatusIconsEnabled = + CVarDef.Create("game.local_status_icons_enabled", true, CVar.CLIENTONLY); + + /// + /// Whether or not coordinates on the Debug overlay should only be available to admins. + /// + public static readonly CVarDef DebugCoordinatesAdminOnly = + CVarDef.Create("game.debug_coordinates_admin_only", true, CVar.SERVER | CVar.REPLICATED); + +#if EXCEPTION_TOLERANCE + /// + /// Amount of times round start must fail before the server is shut down. + /// Set to 0 or a negative number to disable. + /// + public static readonly CVarDef RoundStartFailShutdownCount = + CVarDef.Create("game.round_start_fail_shutdown_count", 5, CVar.SERVERONLY | CVar.SERVER); +#endif + + /// + /// Delay between station alert level changes. + /// + public static readonly CVarDef GameAlertLevelChangeDelay = + CVarDef.Create("game.alert_level_change_delay", 30, CVar.SERVERONLY); + + /// + /// The time in seconds that the server should wait before restarting the round. + /// Defaults to 2 minutes. + /// + public static readonly CVarDef RoundRestartTime = + CVarDef.Create("game.round_restart_time", 120f, CVar.SERVERONLY); + + /// + /// The prototype to use for secret weights. + /// + public static readonly CVarDef SecretWeightPrototype = + CVarDef.Create("game.secret_weight_prototype", "Secret", CVar.SERVERONLY); + + /// + /// The id of the sound collection to randomly choose a sound from and play when the round ends. + /// + public static readonly CVarDef RoundEndSoundCollection = + CVarDef.Create("game.round_end_sound_collection", "RoundEnd", CVar.SERVERONLY); + + /// + /// Whether or not to add every player as a global override to PVS at round end. + /// This will allow all players to see their clothing in the round screen player list screen, + /// but may cause lag during round end with very high player counts. + /// + public static readonly CVarDef RoundEndPVSOverrides = + CVarDef.Create("game.round_end_pvs_overrides", true, CVar.SERVERONLY); + + /// + /// If true, players can place objects onto tabletop games like chess boards. + /// + /// + /// This feature is currently highly abusable and can easily be used to crash the server, + /// so it's off by default. + /// + public static readonly CVarDef GameTabletopPlace = + CVarDef.Create("game.tabletop_place", false, CVar.SERVERONLY); + + /// + /// If true, contraband severity can be viewed in the examine menu + /// + public static readonly CVarDef ContrabandExamine = + CVarDef.Create("game.contraband_examine", true, CVar.SERVER | CVar.REPLICATED); + + /// + /// Size of the lookup area for adding entities to the context menu + /// + public static readonly CVarDef GameEntityMenuLookup = + CVarDef.Create("game.entity_menu_lookup", 0.25f, CVar.CLIENTONLY | CVar.ARCHIVE); + + /// + /// Should the clients window show the server hostname in the title? + /// + public static readonly CVarDef GameHostnameInTitlebar = + CVarDef.Create("game.hostname_in_titlebar", true, CVar.SERVER | CVar.REPLICATED); + +} diff --git a/Content.Shared/CCVar/CCVars.Ghost.cs b/Content.Shared/CCVar/CCVars.Ghost.cs new file mode 100644 index 000000000000..39e7a3c4910a --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Ghost.cs @@ -0,0 +1,24 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + /// + /// The time you must spend reading the rules, before the "Request" button is enabled + /// + public static readonly CVarDef GhostRoleTime = + CVarDef.Create("ghost.role_time", 3f, CVar.REPLICATED | CVar.SERVER); + + /// + /// If ghost role lotteries should be made near-instanteous. + /// + public static readonly CVarDef GhostQuickLottery = + CVarDef.Create("ghost.quick_lottery", false, CVar.SERVERONLY); + + /// + /// Whether or not to kill the player's mob on ghosting, when it is in a critical health state. + /// + public static readonly CVarDef GhostKillCrit = + CVarDef.Create("ghost.kill_crit", true, CVar.REPLICATED | CVar.SERVER); +} diff --git a/Content.Shared/CCVar/CCVars.Hud.cs b/Content.Shared/CCVar/CCVars.Hud.cs new file mode 100644 index 000000000000..f96924b34964 --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Hud.cs @@ -0,0 +1,24 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + public static readonly CVarDef HudTheme = + CVarDef.Create("hud.theme", 0, CVar.ARCHIVE | CVar.CLIENTONLY); + + public static readonly CVarDef HudHeldItemShow = + CVarDef.Create("hud.held_item_show", true, CVar.ARCHIVE | CVar.CLIENTONLY); + + public static readonly CVarDef CombatModeIndicatorsPointShow = + CVarDef.Create("hud.combat_mode_indicators_point_show", true, CVar.ARCHIVE | CVar.CLIENTONLY); + + public static readonly CVarDef LoocAboveHeadShow = + CVarDef.Create("hud.show_looc_above_head", true, CVar.ARCHIVE | CVar.CLIENTONLY); + + public static readonly CVarDef HudHeldItemOffset = + CVarDef.Create("hud.held_item_offset", 28f, CVar.ARCHIVE | CVar.CLIENTONLY); + + public static readonly CVarDef HudFpsCounterVisible = + CVarDef.Create("hud.fps_counter_visible", false, CVar.CLIENTONLY | CVar.ARCHIVE); +} diff --git a/Content.Shared/CCVar/CCVars.Ic.cs b/Content.Shared/CCVar/CCVars.Ic.cs new file mode 100644 index 000000000000..e149e9f3e1ed --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Ic.cs @@ -0,0 +1,48 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + /// + /// Restricts IC character names to alphanumeric chars. + /// + public static readonly CVarDef RestrictedNames = + CVarDef.Create("ic.restricted_names", true, CVar.SERVER | CVar.REPLICATED); + + /// + /// Allows flavor text (character descriptions) + /// + public static readonly CVarDef FlavorText = + CVarDef.Create("ic.flavor_text", false, CVar.SERVER | CVar.REPLICATED); + + /// + /// Adds a period at the end of a sentence if the sentence ends in a letter. + /// + public static readonly CVarDef ChatPunctuation = + CVarDef.Create("ic.punctuation", false, CVar.SERVER); + + /// + /// Enables automatically forcing IC name rules. Uppercases the first letter of the first and last words of the name + /// + public static readonly CVarDef ICNameCase = + CVarDef.Create("ic.name_case", true, CVar.SERVER | CVar.REPLICATED); + + /// + /// Whether or not players' characters are randomly generated rather than using their selected characters in the creator. + /// + public static readonly CVarDef ICRandomCharacters = + CVarDef.Create("ic.random_characters", false, CVar.SERVER); + + /// + /// A weighted random prototype used to determine the species selected for random characters. + /// + public static readonly CVarDef ICRandomSpeciesWeights = + CVarDef.Create("ic.random_species_weights", "SpeciesWeights", CVar.SERVER); + + /// + /// Control displaying SSD indicators near players + /// + public static readonly CVarDef ICShowSSDIndicator = + CVarDef.Create("ic.show_ssd_indicator", true, CVar.CLIENTONLY); +} diff --git a/Content.Shared/CCVar/CCVars.Interactions.cs b/Content.Shared/CCVar/CCVars.Interactions.cs new file mode 100644 index 000000000000..c62f81be0ca3 --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Interactions.cs @@ -0,0 +1,54 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + /// + /// Deadzone for drag-drop interactions. + /// + public static readonly CVarDef DragDropDeadZone = + CVarDef.Create("control.drag_dead_zone", 12f, CVar.CLIENTONLY | CVar.ARCHIVE); + + /// + /// Toggles whether the walking key is a toggle or a held key. + /// + public static readonly CVarDef ToggleWalk = + CVarDef.Create("control.toggle_walk", false, CVar.CLIENTONLY | CVar.ARCHIVE); + + // The rationale behind the default limit is simply that I can easily get to 7 interactions per second by just + // trying to spam toggle a light switch or lever (though the UseDelay component limits the actual effect of the + // interaction). I don't want to accidentally spam admins with alerts just because somebody is spamming a + // key manually, nor do we want to alert them just because the player is having network issues and the server + // receives multiple interactions at once. But we also want to try catch people with modified clients that spam + // many interactions on the same tick. Hence, a very short period, with a relatively high count. + + /// + /// Maximum number of interactions that a player can perform within seconds + /// + public static readonly CVarDef InteractionRateLimitCount = + CVarDef.Create("interaction.rate_limit_count", 5, CVar.SERVER | CVar.REPLICATED); + + /// + public static readonly CVarDef InteractionRateLimitPeriod = + CVarDef.Create("interaction.rate_limit_period", 0.5f, CVar.SERVER | CVar.REPLICATED); + + /// + /// Minimum delay (in seconds) between notifying admins about interaction rate limit violations. A negative + /// value disables admin announcements. + /// + public static readonly CVarDef InteractionRateLimitAnnounceAdminsDelay = + CVarDef.Create("interaction.rate_limit_announce_admins_delay", 120, CVar.SERVERONLY); + + /// + /// Whether or not the storage UI is static and bound to the hotbar, or unbound and allowed to be dragged anywhere. + /// + public static readonly CVarDef StaticStorageUI = + CVarDef.Create("control.static_storage_ui", true, CVar.CLIENTONLY | CVar.ARCHIVE); + + /// + /// Whether or not the storage window uses a transparent or opaque sprite. + /// + public static readonly CVarDef OpaqueStorageWindow = + CVarDef.Create("control.opaque_storage_background", false, CVar.CLIENTONLY | CVar.ARCHIVE); +} diff --git a/Content.Shared/CCVar/CCVars.Interface.cs b/Content.Shared/CCVar/CCVars.Interface.cs new file mode 100644 index 000000000000..79a28e6b4e6a --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Interface.cs @@ -0,0 +1,24 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + public static readonly CVarDef UIClickSound = + CVarDef.Create("interface.click_sound", "/Audio/UserInterface/click.ogg", CVar.REPLICATED); + + public static readonly CVarDef UIHoverSound = + CVarDef.Create("interface.hover_sound", "/Audio/UserInterface/hover.ogg", CVar.REPLICATED); + + public static readonly CVarDef UILayout = + CVarDef.Create("ui.layout", "Default", CVar.CLIENTONLY | CVar.ARCHIVE); + + public static readonly CVarDef DefaultScreenChatSize = + CVarDef.Create("ui.default_chat_size", "", CVar.CLIENTONLY | CVar.ARCHIVE); + + public static readonly CVarDef SeparatedScreenChatSize = + CVarDef.Create("ui.separated_chat_size", "0.6,0", CVar.CLIENTONLY | CVar.ARCHIVE); + + public static readonly CVarDef OutlineEnabled = + CVarDef.Create("outline.enabled", true, CVar.CLIENTONLY); +} diff --git a/Content.Shared/CCVar/CCVars.Mapping.cs b/Content.Shared/CCVar/CCVars.Mapping.cs new file mode 100644 index 000000000000..06cd2870ba24 --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Mapping.cs @@ -0,0 +1,24 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + /// + /// Will mapping mode enable autosaves when it's activated? + /// + public static readonly CVarDef + AutosaveEnabled = CVarDef.Create("mapping.autosave", true, CVar.SERVERONLY); + + /// + /// Autosave interval in seconds. + /// + public static readonly CVarDef + AutosaveInterval = CVarDef.Create("mapping.autosave_interval", 600f, CVar.SERVERONLY); + + /// + /// Directory in server user data to save to. Saves will be inside folders in this directory. + /// + public static readonly CVarDef + AutosaveDirectory = CVarDef.Create("mapping.autosave_dir", "Autosaves", CVar.SERVERONLY); +} diff --git a/Content.Shared/CCVar/CCVars.Midi.cs b/Content.Shared/CCVar/CCVars.Midi.cs new file mode 100644 index 000000000000..4ca4bfd6f864 --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Midi.cs @@ -0,0 +1,18 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + public static readonly CVarDef MaxMidiEventsPerSecond = + CVarDef.Create("midi.max_events_per_second", 1000, CVar.REPLICATED | CVar.SERVER); + + public static readonly CVarDef MaxMidiEventsPerBatch = + CVarDef.Create("midi.max_events_per_batch", 60, CVar.REPLICATED | CVar.SERVER); + + public static readonly CVarDef MaxMidiBatchesDropped = + CVarDef.Create("midi.max_batches_dropped", 1, CVar.SERVERONLY); + + public static readonly CVarDef MaxMidiLaggedBatches = + CVarDef.Create("midi.max_lagged_batches", 8, CVar.SERVERONLY); +} diff --git a/Content.Shared/CCVar/CCVars.Misc.cs b/Content.Shared/CCVar/CCVars.Misc.cs new file mode 100644 index 000000000000..3d597c742746 --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Misc.cs @@ -0,0 +1,97 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + public static readonly CVarDef HolidaysEnabled = CVarDef.Create("holidays.enabled", true, CVar.SERVERONLY); + public static readonly CVarDef BrandingSteam = CVarDef.Create("branding.steam", false, CVar.CLIENTONLY); + public static readonly CVarDef EntityMenuGroupingType = CVarDef.Create("entity_menu", 0, CVar.CLIENTONLY); + + /// + /// Should we pre-load all of the procgen atlasses. + /// + public static readonly CVarDef ProcgenPreload = + CVarDef.Create("procgen.preload", true, CVar.SERVERONLY); + + /// + /// Enabled: Cloning has 70% cost and reclaimer will refuse to reclaim corpses with souls. (For LRP). + /// Disabled: Cloning has full biomass cost and reclaimer can reclaim corpses with souls. (Playtested and balanced for MRP+). + /// + public static readonly CVarDef BiomassEasyMode = + CVarDef.Create("biomass.easy_mode", true, CVar.SERVERONLY); + + /// + /// A scale factor applied to a grid's bounds when trying to find a spot to randomly generate an anomaly. + /// + public static readonly CVarDef AnomalyGenerationGridBoundsScale = + CVarDef.Create("anomaly.generation_grid_bounds_scale", 0.6f, CVar.SERVERONLY); + + /// + /// How long a client can go without any input before being considered AFK. + /// + public static readonly CVarDef AfkTime = + CVarDef.Create("afk.time", 60f, CVar.SERVERONLY); + + /// + /// Flavor limit. This is to ensure that having a large mass of flavors in + /// some food object won't spam a user with flavors. + /// + public static readonly CVarDef + FlavorLimit = CVarDef.Create("flavor.limit", 10, CVar.SERVERONLY); + + public static readonly CVarDef DestinationFile = + CVarDef.Create("autogen.destination_file", "", CVar.SERVER | CVar.SERVERONLY); + + /// + /// Whether uploaded files will be stored in the server's database. + /// This is useful to keep "logs" on what files admins have uploaded in the past. + /// + public static readonly CVarDef ResourceUploadingStoreEnabled = + CVarDef.Create("netres.store_enabled", true, CVar.SERVER | CVar.SERVERONLY); + + /// + /// Numbers of days before stored uploaded files are deleted. Set to zero or negative to disable auto-delete. + /// This is useful to free some space automatically. Auto-deletion runs only on server boot. + /// + public static readonly CVarDef ResourceUploadingStoreDeletionDays = + CVarDef.Create("netres.store_deletion_days", 30, CVar.SERVER | CVar.SERVERONLY); + + /// + /// If a server update restart is pending, the delay after the last player leaves before we actually restart. In seconds. + /// + public static readonly CVarDef UpdateRestartDelay = + CVarDef.Create("update.restart_delay", 20f, CVar.SERVERONLY); + + /// + /// If fire alarms should have all access, or if activating/resetting these + /// should be restricted to what is dictated on a player's access card. + /// Defaults to true. + /// + public static readonly CVarDef FireAlarmAllAccess = + CVarDef.Create("firealarm.allaccess", true, CVar.SERVERONLY); + + /// + /// Time between play time autosaves, in seconds. + /// + public static readonly CVarDef + PlayTimeSaveInterval = CVarDef.Create("playtime.save_interval", 900f, CVar.SERVERONLY); + + /// + /// The maximum amount of time the entity GC can process, in ms. + /// + public static readonly CVarDef GCMaximumTimeMs = + CVarDef.Create("entgc.maximum_time_ms", 5, CVar.SERVERONLY); + + public static readonly CVarDef GatewayGeneratorEnabled = + CVarDef.Create("gateway.generator_enabled", true); + + public static readonly CVarDef TippyEntity = + CVarDef.Create("tippy.entity", "Tippy", CVar.SERVER | CVar.REPLICATED); + + /// + /// The number of seconds that must pass for a single entity to be able to point at something again. + /// + public static readonly CVarDef PointingCooldownSeconds = + CVarDef.Create("pointing.cooldown_seconds", 0.5f, CVar.SERVERONLY); +} diff --git a/Content.Shared/CCVar/CCVars.NPC.cs b/Content.Shared/CCVar/CCVars.NPC.cs new file mode 100644 index 000000000000..f0d5520195d0 --- /dev/null +++ b/Content.Shared/CCVar/CCVars.NPC.cs @@ -0,0 +1,16 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + public static readonly CVarDef NPCMaxUpdates = + CVarDef.Create("npc.max_updates", 128); + + public static readonly CVarDef NPCEnabled = CVarDef.Create("npc.enabled", true); + + /// + /// Should NPCs pathfind when steering. For debug purposes. + /// + public static readonly CVarDef NPCPathfinding = CVarDef.Create("npc.pathfinding", true); +} diff --git a/Content.Shared/CCVar/CCVars.Net.cs b/Content.Shared/CCVar/CCVars.Net.cs new file mode 100644 index 000000000000..b7465def2ebb --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Net.cs @@ -0,0 +1,15 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + public static readonly CVarDef NetAtmosDebugOverlayTickRate = + CVarDef.Create("net.atmosdbgoverlaytickrate", 3.0f); + + public static readonly CVarDef NetGasOverlayTickRate = + CVarDef.Create("net.gasoverlaytickrate", 3.0f); + + public static readonly CVarDef GasOverlayThresholds = + CVarDef.Create("net.gasoverlaythresholds", 20); +} diff --git a/Content.Shared/CCVar/CCVars.Parallax.cs b/Content.Shared/CCVar/CCVars.Parallax.cs new file mode 100644 index 000000000000..9b19c8f49436 --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Parallax.cs @@ -0,0 +1,15 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + public static readonly CVarDef ParallaxEnabled = + CVarDef.Create("parallax.enabled", true, CVar.CLIENTONLY); + + public static readonly CVarDef ParallaxDebug = + CVarDef.Create("parallax.debug", false, CVar.CLIENTONLY); + + public static readonly CVarDef ParallaxLowQuality = + CVarDef.Create("parallax.low_quality", false, CVar.ARCHIVE | CVar.CLIENTONLY); +} diff --git a/Content.Shared/CCVar/CCVars.Physics.cs b/Content.Shared/CCVar/CCVars.Physics.cs new file mode 100644 index 000000000000..379676b5df91 --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Physics.cs @@ -0,0 +1,27 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + /// + /// When a mob is walking should its X / Y movement be relative to its parent (true) or the map (false). + /// + public static readonly CVarDef RelativeMovement = + CVarDef.Create("physics.relative_movement", true, CVar.ARCHIVE | CVar.REPLICATED | CVar.SERVER); + + public static readonly CVarDef TileFrictionModifier = + CVarDef.Create("physics.tile_friction", 40.0f, CVar.ARCHIVE | CVar.REPLICATED | CVar.SERVER); + + public static readonly CVarDef StopSpeed = + CVarDef.Create("physics.stop_speed", 0.1f, CVar.ARCHIVE | CVar.REPLICATED | CVar.SERVER); + + /// + /// Whether mobs can push objects like lockers. + /// + /// + /// Technically client doesn't need to know about it but this may prevent a bug in the distant future so it stays. + /// + public static readonly CVarDef MobPushing = + CVarDef.Create("physics.mob_pushing", false, CVar.REPLICATED | CVar.SERVER); +} diff --git a/Content.Shared/CCVar/CCVars.Radiation.cs b/Content.Shared/CCVar/CCVars.Radiation.cs new file mode 100644 index 000000000000..dfcce15b2f93 --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Radiation.cs @@ -0,0 +1,32 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + /// + /// What is the smallest radiation dose in rads that can be received by object. + /// Extremely small values may impact performance. + /// + public static readonly CVarDef RadiationMinIntensity = + CVarDef.Create("radiation.min_intensity", 0.1f, CVar.SERVERONLY); + + /// + /// Rate of radiation system update in seconds. + /// + public static readonly CVarDef RadiationGridcastUpdateRate = + CVarDef.Create("radiation.gridcast.update_rate", 1.0f, CVar.SERVERONLY); + + /// + /// If both radiation source and receiver are placed on same grid, ignore grids between them. + /// May get inaccurate result in some cases, but greatly boost performance in general. + /// + public static readonly CVarDef RadiationGridcastSimplifiedSameGrid = + CVarDef.Create("radiation.gridcast.simplified_same_grid", true, CVar.SERVERONLY); + + /// + /// Max distance that radiation ray can travel in meters. + /// + public static readonly CVarDef RadiationGridcastMaxDistance = + CVarDef.Create("radiation.gridcast.max_distance", 50f, CVar.SERVERONLY); +} diff --git a/Content.Shared/CCVar/CCVars.Replays.cs b/Content.Shared/CCVar/CCVars.Replays.cs new file mode 100644 index 000000000000..64f47e8ad8c3 --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Replays.cs @@ -0,0 +1,43 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + /// + /// Whether or not to record admin chat. If replays are being publicly distributes, this should probably be + /// false. + /// + public static readonly CVarDef ReplayRecordAdminChat = + CVarDef.Create("replay.record_admin_chat", false, CVar.ARCHIVE); + + /// + /// Automatically record full rounds as replays. + /// + public static readonly CVarDef ReplayAutoRecord = + CVarDef.Create("replay.auto_record", false, CVar.SERVERONLY); + + /// + /// The file name to record automatic replays to. The path is relative to . + /// + /// + /// + /// If the path includes slashes, directories will be automatically created if necessary. + /// + /// + /// A number of substitutions can be used to automatically fill in the file name: {year}, {month}, {day}, {hour}, {minute}, {round}. + /// + /// + public static readonly CVarDef ReplayAutoRecordName = + CVarDef.Create("replay.auto_record_name", + "{year}_{month}_{day}-{hour}_{minute}-round_{round}.zip", + CVar.SERVERONLY); + + /// + /// Path that, if provided, automatic replays are initially recorded in. + /// When the recording is done, the file is moved into its final destination. + /// Unless this path is rooted, it will be relative to . + /// + public static readonly CVarDef ReplayAutoRecordTempDir = + CVarDef.Create("replay.auto_record_temp_dir", "", CVar.SERVERONLY); +} diff --git a/Content.Shared/CCVar/CCVars.Salvage.cs b/Content.Shared/CCVar/CCVars.Salvage.cs new file mode 100644 index 000000000000..ddc332786ba4 --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Salvage.cs @@ -0,0 +1,18 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + /// + /// Duration for missions + /// + public static readonly CVarDef + SalvageExpeditionDuration = CVarDef.Create("salvage.expedition_duration", 660f, CVar.REPLICATED); + + /// + /// Cooldown for missions. + /// + public static readonly CVarDef + SalvageExpeditionCooldown = CVarDef.Create("salvage.expedition_cooldown", 780f, CVar.REPLICATED); +} diff --git a/Content.Shared/CCVar/CCVars.Server.cs b/Content.Shared/CCVar/CCVars.Server.cs new file mode 100644 index 000000000000..2c861584afc9 --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Server.cs @@ -0,0 +1,43 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + /* + * Server + */ + + /// + /// Change this to have the changelog and rules "last seen" date stored separately. + /// + public static readonly CVarDef ServerId = + CVarDef.Create("server.id", "unknown_server_id", CVar.REPLICATED | CVar.SERVER); + + /// + /// Guide Entry Prototype ID to be displayed as the server rules. + /// + public static readonly CVarDef RulesFile = + CVarDef.Create("server.rules_file", "DefaultRuleset", CVar.REPLICATED | CVar.SERVER); + + /// + /// Guide entry that is displayed by default when a guide is opened. + /// + public static readonly CVarDef DefaultGuide = + CVarDef.Create("server.default_guide", "NewPlayer", CVar.REPLICATED | CVar.SERVER); + + /// + /// If greater than 0, automatically restart the server after this many minutes of uptime. + /// + /// + /// + /// This is intended to work around various bugs and performance issues caused by long continuous server uptime. + /// + /// + /// This uses the same non-disruptive logic as update restarts, + /// i.e. the game will only restart at round end or when there is nobody connected. + /// + /// + public static readonly CVarDef ServerUptimeRestartMinutes = + CVarDef.Create("server.uptime_restart_minutes", 0, CVar.SERVERONLY); +} diff --git a/Content.Shared/CCVar/CCVars.Shuttle.cs b/Content.Shared/CCVar/CCVars.Shuttle.cs new file mode 100644 index 000000000000..f66fe9ca598d --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Shuttle.cs @@ -0,0 +1,176 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + /// + /// If true then the camera will match the grid / map and is unchangeable. + /// - When traversing grids it will snap to 0 degrees rotation. + /// False means the player has control over the camera rotation. + /// - When traversing grids it will snap to the nearest cardinal which will generally be imperceptible. + /// + public static readonly CVarDef CameraRotationLocked = + CVarDef.Create("shuttle.camera_rotation_locked", false, CVar.REPLICATED); + + /// + /// Whether the arrivals terminal should be on a planet map. + /// + public static readonly CVarDef ArrivalsPlanet = + CVarDef.Create("shuttle.arrivals_planet", true, CVar.SERVERONLY); + + /// + /// Whether the arrivals shuttle is enabled. + /// + public static readonly CVarDef ArrivalsShuttles = + CVarDef.Create("shuttle.arrivals", true, CVar.SERVERONLY); + + /// + /// The map to use for the arrivals station. + /// + public static readonly CVarDef ArrivalsMap = + CVarDef.Create("shuttle.arrivals_map", "/Maps/Misc/terminal.yml", CVar.SERVERONLY); + + /// + /// Cooldown between arrivals departures. This should be longer than the FTL time or it will double cycle. + /// + public static readonly CVarDef ArrivalsCooldown = + CVarDef.Create("shuttle.arrivals_cooldown", 50f, CVar.SERVERONLY); + + /// + /// Are players allowed to return on the arrivals shuttle. + /// + public static readonly CVarDef ArrivalsReturns = + CVarDef.Create("shuttle.arrivals_returns", false, CVar.SERVERONLY); + + /// + /// Should all players who spawn at arrivals have godmode until they leave the map? + /// + public static readonly CVarDef GodmodeArrivals = + CVarDef.Create("shuttle.godmode_arrivals", false, CVar.SERVERONLY); + + /// + /// If a grid is split then hide any smaller ones under this mass (kg) from the map. + /// This is useful to avoid split grids spamming out labels. + /// + public static readonly CVarDef HideSplitGridsUnder = + CVarDef.Create("shuttle.hide_split_grids_under", 30, CVar.SERVERONLY); + + /// + /// Whether to automatically spawn escape shuttles. + /// + public static readonly CVarDef GridFill = + CVarDef.Create("shuttle.grid_fill", true, CVar.SERVERONLY); + + /// + /// Whether to automatically preloading grids by GridPreloaderSystem + /// + public static readonly CVarDef PreloadGrids = + CVarDef.Create("shuttle.preload_grids", true, CVar.SERVERONLY); + + /// + /// How long the warmup time before FTL start should be. + /// + public static readonly CVarDef FTLStartupTime = + CVarDef.Create("shuttle.startup_time", 5.5f, CVar.SERVERONLY); + + /// + /// How long a shuttle spends in FTL. + /// + public static readonly CVarDef FTLTravelTime = + CVarDef.Create("shuttle.travel_time", 20f, CVar.SERVERONLY); + + /// + /// How long the final stage of FTL before arrival should be. + /// + public static readonly CVarDef FTLArrivalTime = + CVarDef.Create("shuttle.arrival_time", 5f, CVar.SERVERONLY); + + /// + /// How much time needs to pass before a shuttle can FTL again. + /// + public static readonly CVarDef FTLCooldown = + CVarDef.Create("shuttle.cooldown", 10f, CVar.SERVERONLY); + + /// + /// The maximum a grid can have before it becomes unable to FTL. + /// Any value equal to or less than zero will disable this check. + /// + public static readonly CVarDef FTLMassLimit = + CVarDef.Create("shuttle.mass_limit", 300f, CVar.SERVERONLY); + + /// + /// How long to knock down entities for if they aren't buckled when FTL starts and stops. + /// + public static readonly CVarDef HyperspaceKnockdownTime = + CVarDef.Create("shuttle.hyperspace_knockdown_time", 5f, CVar.SERVERONLY); + + /// + /// Is the emergency shuttle allowed to be early launched. + /// + public static readonly CVarDef EmergencyEarlyLaunchAllowed = + CVarDef.Create("shuttle.emergency_early_launch_allowed", false, CVar.SERVERONLY); + + /// + /// How long the emergency shuttle remains docked with the station, in seconds. + /// + public static readonly CVarDef EmergencyShuttleDockTime = + CVarDef.Create("shuttle.emergency_dock_time", 180f, CVar.SERVERONLY); + + /// + /// If the emergency shuttle can't dock at a priority port, the dock time will be multiplied with this value. + /// + public static readonly CVarDef EmergencyShuttleDockTimeMultiplierOtherDock = + CVarDef.Create("shuttle.emergency_dock_time_multiplier_other_dock", 1.6667f, CVar.SERVERONLY); + + /// + /// If the emergency shuttle can't dock at all, the dock time will be multiplied with this value. + /// + public static readonly CVarDef EmergencyShuttleDockTimeMultiplierNoDock = + CVarDef.Create("shuttle.emergency_dock_time_multiplier_no_dock", 2f, CVar.SERVERONLY); + + /// + /// How long after the console is authorized for the shuttle to early launch. + /// + public static readonly CVarDef EmergencyShuttleAuthorizeTime = + CVarDef.Create("shuttle.emergency_authorize_time", 10f, CVar.SERVERONLY); + + /// + /// The minimum time for the emergency shuttle to arrive at centcomm. + /// Actual minimum travel time cannot be less than + /// + public static readonly CVarDef EmergencyShuttleMinTransitTime = + CVarDef.Create("shuttle.emergency_transit_time_min", 60f, CVar.SERVERONLY); + + /// + /// The maximum time for the emergency shuttle to arrive at centcomm. + /// + public static readonly CVarDef EmergencyShuttleMaxTransitTime = + CVarDef.Create("shuttle.emergency_transit_time_max", 180f, CVar.SERVERONLY); + + /// + /// Whether the emergency shuttle is enabled or should the round just end. + /// + public static readonly CVarDef EmergencyShuttleEnabled = + CVarDef.Create("shuttle.emergency", true, CVar.SERVERONLY); + + /// + /// The percentage of time passed from the initial call to when the shuttle can no longer be recalled. + /// ex. a call time of 10min and turning point of 0.5 means the shuttle cannot be recalled after 5 minutes. + /// + public static readonly CVarDef EmergencyRecallTurningPoint = + CVarDef.Create("shuttle.recall_turning_point", 0.5f, CVar.SERVERONLY); + + /// + /// Time in minutes after round start to auto-call the shuttle. Set to zero to disable. + /// + public static readonly CVarDef EmergencyShuttleAutoCallTime = + CVarDef.Create("shuttle.auto_call_time", 90, CVar.SERVERONLY); + + /// + /// Time in minutes after the round was extended (by recalling the shuttle) to call + /// the shuttle again. + /// + public static readonly CVarDef EmergencyShuttleAutoCallExtensionTime = + CVarDef.Create("shuttle.auto_call_extension_time", 45, CVar.SERVERONLY); +} diff --git a/Content.Shared/CCVar/CCVars.Sounds.cs b/Content.Shared/CCVar/CCVars.Sounds.cs new file mode 100644 index 000000000000..73d9d3852f1f --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Sounds.cs @@ -0,0 +1,34 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + public static readonly CVarDef LobbyMusicEnabled = + CVarDef.Create("ambience.lobby_music_enabled", true, CVar.ARCHIVE | CVar.CLIENTONLY); + + public static readonly CVarDef EventMusicEnabled = + CVarDef.Create("ambience.event_music_enabled", true, CVar.ARCHIVE | CVar.CLIENTONLY); + + /// + /// Round end sound (APC Destroyed) + /// + public static readonly CVarDef RestartSoundsEnabled = + CVarDef.Create("ambience.restart_sounds_enabled", true, CVar.ARCHIVE | CVar.CLIENTONLY); + + + + public static readonly CVarDef AdminSoundsEnabled = + CVarDef.Create("audio.admin_sounds_enabled", true, CVar.ARCHIVE | CVar.CLIENTONLY); + + public static readonly CVarDef AdminChatSoundPath = + CVarDef.Create("audio.admin_chat_sound_path", + "/Audio/Items/pop.ogg", + CVar.ARCHIVE | CVar.CLIENT | CVar.REPLICATED); + + public static readonly CVarDef AdminChatSoundVolume = + CVarDef.Create("audio.admin_chat_sound_volume", -5f, CVar.ARCHIVE | CVar.CLIENT | CVar.REPLICATED); + + public static readonly CVarDef AHelpSound = + CVarDef.Create("audio.ahelp_sound", "/Audio/Effects/adminhelp.ogg", CVar.ARCHIVE | CVar.CLIENTONLY); +} diff --git a/Content.Shared/CCVar/CCVars.Status.cs b/Content.Shared/CCVar/CCVars.Status.cs new file mode 100644 index 000000000000..007f678106a2 --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Status.cs @@ -0,0 +1,13 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + public static readonly CVarDef StatusMoMMIUrl = + CVarDef.Create("status.mommiurl", "", CVar.SERVERONLY); + + public static readonly CVarDef StatusMoMMIPassword = + CVarDef.Create("status.mommipassword", "", CVar.SERVERONLY | CVar.CONFIDENTIAL); + +} diff --git a/Content.Shared/CCVar/CCVars.Tips.cs b/Content.Shared/CCVar/CCVars.Tips.cs new file mode 100644 index 000000000000..61e6342061f3 --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Tips.cs @@ -0,0 +1,40 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + /// + /// Whether tips being shown is enabled at all. + /// + public static readonly CVarDef TipsEnabled = + CVarDef.Create("tips.enabled", true); + + /// + /// The dataset prototype to use when selecting a random tip. + /// + public static readonly CVarDef TipsDataset = + CVarDef.Create("tips.dataset", "Tips"); + + /// + /// The number of seconds between each tip being displayed when the round is not actively going + /// (i.e. postround or lobby) + /// + public static readonly CVarDef TipFrequencyOutOfRound = + CVarDef.Create("tips.out_of_game_frequency", 60f * 1.5f); + + /// + /// The number of seconds between each tip being displayed when the round is actively going + /// + public static readonly CVarDef TipFrequencyInRound = + CVarDef.Create("tips.in_game_frequency", 60f * 60); + + public static readonly CVarDef LoginTipsDataset = + CVarDef.Create("tips.login_dataset", "Tips"); + + /// + /// The chance for Tippy to replace a normal tip message. + /// + public static readonly CVarDef TipsTippyChance = + CVarDef.Create("tips.tippy_chance", 0.01f); +} diff --git a/Content.Shared/CCVar/CCVars.Viewport.cs b/Content.Shared/CCVar/CCVars.Viewport.cs new file mode 100644 index 000000000000..d94394d2a754 --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Viewport.cs @@ -0,0 +1,33 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + public static readonly CVarDef ViewportStretch = + CVarDef.Create("viewport.stretch", true, CVar.CLIENTONLY | CVar.ARCHIVE); + + public static readonly CVarDef ViewportFixedScaleFactor = + CVarDef.Create("viewport.fixed_scale_factor", 2, CVar.CLIENTONLY | CVar.ARCHIVE); + + public static readonly CVarDef ViewportSnapToleranceMargin = + CVarDef.Create("viewport.snap_tolerance_margin", 64, CVar.CLIENTONLY | CVar.ARCHIVE); + + public static readonly CVarDef ViewportSnapToleranceClip = + CVarDef.Create("viewport.snap_tolerance_clip", 32, CVar.CLIENTONLY | CVar.ARCHIVE); + + public static readonly CVarDef ViewportScaleRender = + CVarDef.Create("viewport.scale_render", true, CVar.CLIENTONLY | CVar.ARCHIVE); + + public static readonly CVarDef ViewportMinimumWidth = + CVarDef.Create("viewport.minimum_width", 15, CVar.REPLICATED | CVar.SERVER); + + public static readonly CVarDef ViewportMaximumWidth = + CVarDef.Create("viewport.maximum_width", 21, CVar.REPLICATED | CVar.SERVER); + + public static readonly CVarDef ViewportWidth = + CVarDef.Create("viewport.width", 21, CVar.CLIENTONLY | CVar.ARCHIVE); + + public static readonly CVarDef ViewportVerticalFit = + CVarDef.Create("viewport.vertical_fit", true, CVar.CLIENTONLY | CVar.ARCHIVE); +} diff --git a/Content.Shared/CCVar/CCVars.Vote.cs b/Content.Shared/CCVar/CCVars.Vote.cs new file mode 100644 index 000000000000..ee9fee7d3db2 --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Vote.cs @@ -0,0 +1,180 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + /// + /// Allows enabling/disabling player-started votes for ultimate authority + /// + public static readonly CVarDef VoteEnabled = + CVarDef.Create("vote.enabled", true, CVar.SERVERONLY); + + /// + /// See vote.enabled, but specific to restart votes + /// + public static readonly CVarDef VoteRestartEnabled = + CVarDef.Create("vote.restart_enabled", true, CVar.SERVERONLY); + + /// + /// Config for when the restart vote should be allowed to be called regardless with less than this amount of players. + /// + public static readonly CVarDef VoteRestartMaxPlayers = + CVarDef.Create("vote.restart_max_players", 20, CVar.SERVERONLY); + + /// + /// Config for when the restart vote should be allowed to be called based on percentage of ghosts. + /// + public static readonly CVarDef VoteRestartGhostPercentage = + CVarDef.Create("vote.restart_ghost_percentage", 55, CVar.SERVERONLY); + + /// + /// See vote.enabled, but specific to preset votes + /// + public static readonly CVarDef VotePresetEnabled = + CVarDef.Create("vote.preset_enabled", true, CVar.SERVERONLY); + + /// + /// See vote.enabled, but specific to map votes + /// + public static readonly CVarDef VoteMapEnabled = + CVarDef.Create("vote.map_enabled", false, CVar.SERVERONLY); + + /// + /// The required ratio of the server that must agree for a restart round vote to go through. + /// + public static readonly CVarDef VoteRestartRequiredRatio = + CVarDef.Create("vote.restart_required_ratio", 0.85f, CVar.SERVERONLY); + + /// + /// Whether or not to prevent the restart vote from having any effect when there is an online admin + /// + public static readonly CVarDef VoteRestartNotAllowedWhenAdminOnline = + CVarDef.Create("vote.restart_not_allowed_when_admin_online", true, CVar.SERVERONLY); + + /// + /// The delay which two votes of the same type are allowed to be made by separate people, in seconds. + /// + public static readonly CVarDef VoteSameTypeTimeout = + CVarDef.Create("vote.same_type_timeout", 240f, CVar.SERVERONLY); + + /// + /// Sets the duration of the map vote timer. + /// + public static readonly CVarDef + VoteTimerMap = CVarDef.Create("vote.timermap", 90, CVar.SERVERONLY); + + /// + /// Sets the duration of the restart vote timer. + /// + public static readonly CVarDef + VoteTimerRestart = CVarDef.Create("vote.timerrestart", 60, CVar.SERVERONLY); + + /// + /// Sets the duration of the gamemode/preset vote timer. + /// + public static readonly CVarDef + VoteTimerPreset = CVarDef.Create("vote.timerpreset", 30, CVar.SERVERONLY); + + /// + /// Sets the duration of the map vote timer when ALONE. + /// + public static readonly CVarDef + VoteTimerAlone = CVarDef.Create("vote.timeralone", 10, CVar.SERVERONLY); + + /// + /// Allows enabling/disabling player-started votekick for ultimate authority + /// + public static readonly CVarDef VotekickEnabled = + CVarDef.Create("votekick.enabled", true, CVar.SERVERONLY); + + /// + /// Config for when the votekick should be allowed to be called based on number of eligible voters. + /// + public static readonly CVarDef VotekickEligibleNumberRequirement = + CVarDef.Create("votekick.eligible_number", 5, CVar.SERVERONLY); + + /// + /// Whether a votekick initiator must be a ghost or not. + /// + public static readonly CVarDef VotekickInitiatorGhostRequirement = + CVarDef.Create("votekick.initiator_ghost_requirement", true, CVar.SERVERONLY); + + /// + /// Should the initiator be whitelisted to initiate a votekick? + /// + public static readonly CVarDef VotekickInitiatorWhitelistedRequirement = + CVarDef.Create("votekick.initiator_whitelist_requirement", true, CVar.SERVERONLY); + + /// + /// Should the initiator be able to start a votekick if they are bellow the votekick.voter_playtime requirement? + /// + public static readonly CVarDef VotekickInitiatorTimeRequirement = + CVarDef.Create("votekick.initiator_time_requirement", false, CVar.SERVERONLY); + + /// + /// Whether a votekick voter must be a ghost or not. + /// + public static readonly CVarDef VotekickVoterGhostRequirement = + CVarDef.Create("votekick.voter_ghost_requirement", true, CVar.SERVERONLY); + + /// + /// Config for how many hours playtime a player must have to be able to vote on a votekick. + /// + public static readonly CVarDef VotekickEligibleVoterPlaytime = + CVarDef.Create("votekick.voter_playtime", 100, CVar.SERVERONLY); + + /// + /// Config for how many seconds a player must have been dead to initiate a votekick / be able to vote on a votekick. + /// + public static readonly CVarDef VotekickEligibleVoterDeathtime = + CVarDef.Create("votekick.voter_deathtime", 30, CVar.REPLICATED | CVar.SERVER); + + /// + /// The required ratio of eligible voters that must agree for a votekick to go through. + /// + public static readonly CVarDef VotekickRequiredRatio = + CVarDef.Create("votekick.required_ratio", 0.6f, CVar.SERVERONLY); + + /// + /// Whether or not to prevent the votekick from having any effect when there is an online admin. + /// + public static readonly CVarDef VotekickNotAllowedWhenAdminOnline = + CVarDef.Create("votekick.not_allowed_when_admin_online", true, CVar.SERVERONLY); + + /// + /// The delay for which two votekicks are allowed to be made by separate people, in seconds. + /// + public static readonly CVarDef VotekickTimeout = + CVarDef.Create("votekick.timeout", 120f, CVar.SERVERONLY); + + /// + /// Sets the duration of the votekick vote timer. + /// + public static readonly CVarDef + VotekickTimer = CVarDef.Create("votekick.timer", 60, CVar.SERVERONLY); + + /// + /// Config for how many hours playtime a player must have to get protection from the Raider votekick type when playing as an antag. + /// + public static readonly CVarDef VotekickAntagRaiderProtection = + CVarDef.Create("votekick.antag_raider_protection", 10, CVar.SERVERONLY); + + /// + /// Default severity for votekick bans + /// + public static readonly CVarDef VotekickBanDefaultSeverity = + CVarDef.Create("votekick.ban_default_severity", "High", CVar.ARCHIVE | CVar.SERVER | CVar.REPLICATED); + + /// + /// Duration of a ban caused by a votekick (in minutes). + /// + public static readonly CVarDef VotekickBanDuration = + CVarDef.Create("votekick.ban_duration", 180, CVar.SERVERONLY); + + /// + /// Whether the ghost requirement settings for votekicks should be ignored for the lobby. + /// + public static readonly CVarDef VotekickIgnoreGhostReqInLobby = + CVarDef.Create("votekick.ignore_ghost_req_in_lobby", true, CVar.SERVERONLY); +} diff --git a/Content.Shared/CCVar/CCVars.Whitelist.cs b/Content.Shared/CCVar/CCVars.Whitelist.cs new file mode 100644 index 000000000000..7a7a5206a11b --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Whitelist.cs @@ -0,0 +1,19 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + /// + /// Controls whether the server will deny any players that are not whitelisted in the DB. + /// + public static readonly CVarDef WhitelistEnabled = + CVarDef.Create("whitelist.enabled", false, CVar.SERVERONLY); + + /// + /// Specifies the whitelist prototypes to be used by the server. This should be a comma-separated list of prototypes. + /// If a whitelists conditions to be active fail (for example player count), the next whitelist will be used instead. If no whitelist is valid, the player will be allowed to connect. + /// + public static readonly CVarDef WhitelistPrototypeList = + CVarDef.Create("whitelist.prototype_list", "basicWhitelist", CVar.SERVERONLY); +} diff --git a/Content.Shared/CCVar/CCVars.Worldgen.cs b/Content.Shared/CCVar/CCVars.Worldgen.cs new file mode 100644 index 000000000000..da165ce74a7d --- /dev/null +++ b/Content.Shared/CCVar/CCVars.Worldgen.cs @@ -0,0 +1,18 @@ +using Robust.Shared.Configuration; + +namespace Content.Shared.CCVar; + +public sealed partial class CCVars +{ + /// + /// Whether or not world generation is enabled. + /// + public static readonly CVarDef WorldgenEnabled = + CVarDef.Create("worldgen.enabled", false, CVar.SERVERONLY); + + /// + /// The worldgen config to use. + /// + public static readonly CVarDef WorldgenConfig = + CVarDef.Create("worldgen.worldgen_config", "Default", CVar.SERVERONLY); +} diff --git a/Content.Shared/CCVar/CCVars.cs b/Content.Shared/CCVar/CCVars.cs index 83068b5262bc..316d9b8690a8 100644 --- a/Content.Shared/CCVar/CCVars.cs +++ b/Content.Shared/CCVar/CCVars.cs @@ -1,2388 +1,28 @@ -using Content.Shared.Maps; -using Content.Shared.Roles; using Robust.Shared; using Robust.Shared.Configuration; -using Robust.Shared.Physics.Components; -namespace Content.Shared.CCVar -{ - // ReSharper disable once InconsistentNaming - [CVarDefs] - public sealed class CCVars : CVars - { - /* - * Server - */ - - /// - /// Change this to have the changelog and rules "last seen" date stored separately. - /// - public static readonly CVarDef ServerId = - CVarDef.Create("server.id", "unknown_server_id", CVar.REPLICATED | CVar.SERVER); - - /// - /// Guide Entry Prototype ID to be displayed as the server rules. - /// - public static readonly CVarDef RulesFile = - CVarDef.Create("server.rules_file", "DefaultRuleset", CVar.REPLICATED | CVar.SERVER); - - /// - /// Guide entry that is displayed by default when a guide is opened. - /// - public static readonly CVarDef DefaultGuide = - CVarDef.Create("server.default_guide", "NewPlayer", CVar.REPLICATED | CVar.SERVER); - - /// - /// If greater than 0, automatically restart the server after this many minutes of uptime. - /// - /// - /// - /// This is intended to work around various bugs and performance issues caused by long continuous server uptime. - /// - /// - /// This uses the same non-disruptive logic as update restarts, - /// i.e. the game will only restart at round end or when there is nobody connected. - /// - /// - public static readonly CVarDef ServerUptimeRestartMinutes = - CVarDef.Create("server.uptime_restart_minutes", 0, CVar.SERVERONLY); - - /* - * Ambience - */ - - /// - /// How long we'll wait until re-sampling nearby objects for ambience. Should be pretty fast, but doesn't have to match the tick rate. - /// - public static readonly CVarDef AmbientCooldown = - CVarDef.Create("ambience.cooldown", 0.1f, CVar.ARCHIVE | CVar.CLIENTONLY); - - /// - /// How large of a range to sample for ambience. - /// - public static readonly CVarDef AmbientRange = - CVarDef.Create("ambience.range", 8f, CVar.REPLICATED | CVar.SERVER); - - /// - /// Maximum simultaneous ambient sounds. - /// - public static readonly CVarDef MaxAmbientSources = - CVarDef.Create("ambience.max_sounds", 16, CVar.ARCHIVE | CVar.CLIENTONLY); - - /// - /// The minimum value the user can set for ambience.max_sounds - /// - public static readonly CVarDef MinMaxAmbientSourcesConfigured = - CVarDef.Create("ambience.min_max_sounds_configured", 16, CVar.REPLICATED | CVar.SERVER | CVar.CHEAT); - - /// - /// The maximum value the user can set for ambience.max_sounds - /// - public static readonly CVarDef MaxMaxAmbientSourcesConfigured = - CVarDef.Create("ambience.max_max_sounds_configured", 64, CVar.REPLICATED | CVar.SERVER | CVar.CHEAT); - - /// - /// Ambience volume. - /// - public static readonly CVarDef AmbienceVolume = - CVarDef.Create("ambience.volume", 1.5f, CVar.ARCHIVE | CVar.CLIENTONLY); - - /// - /// Ambience music volume. - /// - public static readonly CVarDef AmbientMusicVolume = - CVarDef.Create("ambience.music_volume", 1.5f, CVar.ARCHIVE | CVar.CLIENTONLY); - - /// - /// Lobby / round end music volume. - /// - public static readonly CVarDef LobbyMusicVolume = - CVarDef.Create("ambience.lobby_music_volume", 0.50f, CVar.ARCHIVE | CVar.CLIENTONLY); - - /// - /// UI volume. - /// - public static readonly CVarDef InterfaceVolume = - CVarDef.Create("audio.interface_volume", 0.50f, CVar.ARCHIVE | CVar.CLIENTONLY); - - /* - * Status - */ - - public static readonly CVarDef StatusMoMMIUrl = - CVarDef.Create("status.mommiurl", "", CVar.SERVERONLY); - - public static readonly CVarDef StatusMoMMIPassword = - CVarDef.Create("status.mommipassword", "", CVar.SERVERONLY | CVar.CONFIDENTIAL); - - /* - * Events - */ - - /// - /// Controls if the game should run station events - /// - public static readonly CVarDef - EventsEnabled = CVarDef.Create("events.enabled", true, CVar.ARCHIVE | CVar.SERVERONLY); - - /* - * Game - */ - - /// - /// Disables most functionality in the GameTicker. - /// - public static readonly CVarDef - GameDummyTicker = CVarDef.Create("game.dummyticker", false, CVar.ARCHIVE | CVar.SERVERONLY); - - /// - /// Controls if the lobby is enabled. If it is not, and there are no available jobs, you may get stuck on a black screen. - /// - public static readonly CVarDef - GameLobbyEnabled = CVarDef.Create("game.lobbyenabled", true, CVar.ARCHIVE); - - /// - /// Controls the duration of the lobby timer in seconds. Defaults to 2 minutes and 30 seconds. - /// - public static readonly CVarDef - GameLobbyDuration = CVarDef.Create("game.lobbyduration", 150, CVar.ARCHIVE); - - /// - /// Controls if players can latejoin at all. - /// - public static readonly CVarDef - GameDisallowLateJoins = CVarDef.Create("game.disallowlatejoins", false, CVar.ARCHIVE | CVar.SERVERONLY); - - /// - /// Controls the default game preset. - /// - public static readonly CVarDef - GameLobbyDefaultPreset = CVarDef.Create("game.defaultpreset", "secret", CVar.ARCHIVE); - - /// - /// Controls if the game can force a different preset if the current preset's criteria are not met. - /// - public static readonly CVarDef - GameLobbyFallbackEnabled = CVarDef.Create("game.fallbackenabled", true, CVar.ARCHIVE); - - /// - /// The preset for the game to fall back to if the selected preset could not be used, and fallback is enabled. - /// - public static readonly CVarDef - GameLobbyFallbackPreset = CVarDef.Create("game.fallbackpreset", "Traitor,Extended", CVar.ARCHIVE); - - /// - /// Controls if people can win the game in Suspicion or Deathmatch. - /// - public static readonly CVarDef - GameLobbyEnableWin = CVarDef.Create("game.enablewin", true, CVar.ARCHIVE); - - /// - /// Controls the maximum number of character slots a player is allowed to have. - /// - public static readonly CVarDef - GameMaxCharacterSlots = CVarDef.Create("game.maxcharacterslots", 30, CVar.ARCHIVE | CVar.SERVERONLY); - - /// - /// Controls the game map prototype to load. SS14 stores these prototypes in Prototypes/Maps. - /// - public static readonly CVarDef - GameMap = CVarDef.Create("game.map", string.Empty, CVar.SERVERONLY); - - /// - /// Controls whether to use world persistence or not. - /// - public static readonly CVarDef - UsePersistence = CVarDef.Create("game.usepersistence", false, CVar.ARCHIVE); - - /// - /// If world persistence is used, what map prototype should be initially loaded. - /// If the save file exists, it replaces MapPath but everything else stays the same (station name and such). - /// - public static readonly CVarDef - PersistenceMap = CVarDef.Create("game.persistencemap", "Empty", CVar.ARCHIVE); - - /// - /// Prototype to use for map pool. - /// - public static readonly CVarDef - GameMapPool = CVarDef.Create("game.map_pool", "DefaultMapPool", CVar.SERVERONLY); - - /// - /// The depth of the queue used to calculate which map is next in rotation. - /// This is how long the game "remembers" that some map was put in play. Default is 16 rounds. - /// - public static readonly CVarDef - GameMapMemoryDepth = CVarDef.Create("game.map_memory_depth", 16, CVar.SERVERONLY); - - /// - /// Is map rotation enabled? - /// - public static readonly CVarDef - GameMapRotation = CVarDef.Create("game.map_rotation", true, CVar.SERVERONLY); - - /// - /// If roles should be restricted based on time. - /// - public static readonly CVarDef - GameRoleTimers = CVarDef.Create("game.role_timers", true, CVar.SERVER | CVar.REPLICATED); - - /// - /// Override default role requirements using a - /// - public static readonly CVarDef - GameRoleTimerOverride = CVarDef.Create("game.role_timer_override", "", CVar.SERVER | CVar.REPLICATED); - - /// - /// If roles should be restricted based on whether or not they are whitelisted. - /// - public static readonly CVarDef - GameRoleWhitelist = CVarDef.Create("game.role_whitelist", true, CVar.SERVER | CVar.REPLICATED); - - /// - /// Whether or not disconnecting inside of a cryopod should remove the character or just store them until they reconnect. - /// - public static readonly CVarDef - GameCryoSleepRejoining = CVarDef.Create("game.cryo_sleep_rejoining", false, CVar.SERVER | CVar.REPLICATED); - - /// - /// When enabled, guests will be assigned permanent UIDs and will have their preferences stored. - /// - public static readonly CVarDef GamePersistGuests = - CVarDef.Create("game.persistguests", true, CVar.ARCHIVE | CVar.SERVERONLY); - - public static readonly CVarDef GameDiagonalMovement = - CVarDef.Create("game.diagonalmovement", true, CVar.ARCHIVE); - - public static readonly CVarDef SoftMaxPlayers = - CVarDef.Create("game.soft_max_players", 30, CVar.SERVERONLY | CVar.ARCHIVE); - - /// - /// If a player gets denied connection to the server, - /// how long they are forced to wait before attempting to reconnect. - /// - public static readonly CVarDef GameServerFullReconnectDelay = - CVarDef.Create("game.server_full_reconnect_delay", 30, CVar.SERVERONLY); - - /// - /// Whether or not panic bunker is currently enabled. - /// - public static readonly CVarDef PanicBunkerEnabled = - CVarDef.Create("game.panic_bunker.enabled", false, CVar.NOTIFY | CVar.REPLICATED | CVar.SERVER); - - /// - /// Whether or not the panic bunker will disable when an admin comes online. - /// - public static readonly CVarDef PanicBunkerDisableWithAdmins = - CVarDef.Create("game.panic_bunker.disable_with_admins", false, CVar.SERVERONLY); - - /// - /// Whether or not the panic bunker will enable when no admins are online. - /// - public static readonly CVarDef PanicBunkerEnableWithoutAdmins = - CVarDef.Create("game.panic_bunker.enable_without_admins", false, CVar.SERVERONLY); - - /// - /// Whether or not the panic bunker will count deadminned admins for - /// and - /// - /// - public static readonly CVarDef PanicBunkerCountDeadminnedAdmins = - CVarDef.Create("game.panic_bunker.count_deadminned_admins", false, CVar.SERVERONLY); - - /// - /// Show reason of disconnect for user or not. - /// - public static readonly CVarDef PanicBunkerShowReason = - CVarDef.Create("game.panic_bunker.show_reason", false, CVar.SERVERONLY); - - /// - /// Minimum age of the account (from server's PoV, so from first-seen date) in minutes. - /// - public static readonly CVarDef PanicBunkerMinAccountAge = - CVarDef.Create("game.panic_bunker.min_account_age", 1440, CVar.SERVERONLY); - - /// - /// Minimal overall played time. - /// - public static readonly CVarDef PanicBunkerMinOverallMinutes = - CVarDef.Create("game.panic_bunker.min_overall_minutes", 600, CVar.SERVERONLY); - - /// - /// A custom message that will be used for connections denied to the panic bunker - /// If not empty, then will overwrite - /// - public static readonly CVarDef PanicBunkerCustomReason = - CVarDef.Create("game.panic_bunker.custom_reason", string.Empty, CVar.SERVERONLY); - - /// - /// Allow bypassing the panic bunker if the user is whitelisted. - /// - public static readonly CVarDef BypassBunkerWhitelist = - CVarDef.Create("game.panic_bunker.whitelisted_can_bypass", true, CVar.SERVERONLY); - - /* - * TODO: Remove baby jail code once a more mature gateway process is established. This code is only being issued as a stopgap to help with potential tiding in the immediate future. - */ - - /// - /// Whether the baby jail is currently enabled. - /// - public static readonly CVarDef BabyJailEnabled = - CVarDef.Create("game.baby_jail.enabled", false, CVar.NOTIFY | CVar.REPLICATED | CVar.SERVER); - - /// - /// Show reason of disconnect for user or not. - /// - public static readonly CVarDef BabyJailShowReason = - CVarDef.Create("game.baby_jail.show_reason", false, CVar.SERVERONLY); - - /// - /// Maximum age of the account (from server's PoV, so from first-seen date) in minutes that can access baby - /// jailed servers. - /// - public static readonly CVarDef BabyJailMaxAccountAge = - CVarDef.Create("game.baby_jail.max_account_age", 1440, CVar.SERVERONLY); - - /// - /// Maximum overall played time allowed to access baby jailed servers. - /// - public static readonly CVarDef BabyJailMaxOverallMinutes = - CVarDef.Create("game.baby_jail.max_overall_minutes", 120, CVar.SERVERONLY); - - /// - /// A custom message that will be used for connections denied due to the baby jail. - /// If not empty, then will overwrite - /// - public static readonly CVarDef BabyJailCustomReason = - CVarDef.Create("game.baby_jail.custom_reason", string.Empty, CVar.SERVERONLY); - - /// - /// Allow bypassing the baby jail if the user is whitelisted. - /// - public static readonly CVarDef BypassBabyJailWhitelist = - CVarDef.Create("game.baby_jail.whitelisted_can_bypass", true, CVar.SERVERONLY); - - /// - /// Make people bonk when trying to climb certain objects like tables. - /// - public static readonly CVarDef GameTableBonk = - CVarDef.Create("game.table_bonk", false, CVar.REPLICATED); - - /// - /// Whether or not status icons are rendered for everyone. - /// - public static readonly CVarDef GlobalStatusIconsEnabled = - CVarDef.Create("game.global_status_icons_enabled", true, CVar.SERVER | CVar.REPLICATED); - - /// - /// Whether or not status icons are rendered on this specific client. - /// - public static readonly CVarDef LocalStatusIconsEnabled = - CVarDef.Create("game.local_status_icons_enabled", true, CVar.CLIENTONLY); - - /// - /// Whether or not coordinates on the Debug overlay should only be available to admins. - /// - public static readonly CVarDef DebugCoordinatesAdminOnly = - CVarDef.Create("game.debug_coordinates_admin_only", true, CVar.SERVER | CVar.REPLICATED); - -#if EXCEPTION_TOLERANCE - /// - /// Amount of times round start must fail before the server is shut down. - /// Set to 0 or a negative number to disable. - /// - public static readonly CVarDef RoundStartFailShutdownCount = - CVarDef.Create("game.round_start_fail_shutdown_count", 5, CVar.SERVERONLY | CVar.SERVER); -#endif - - /// - /// Delay between station alert level changes. - /// - public static readonly CVarDef GameAlertLevelChangeDelay = - CVarDef.Create("game.alert_level_change_delay", 30, CVar.SERVERONLY); - - /// - /// The time in seconds that the server should wait before restarting the round. - /// Defaults to 2 minutes. - /// - public static readonly CVarDef RoundRestartTime = - CVarDef.Create("game.round_restart_time", 120f, CVar.SERVERONLY); - - /// - /// The prototype to use for secret weights. - /// - public static readonly CVarDef SecretWeightPrototype = - CVarDef.Create("game.secret_weight_prototype", "Secret", CVar.SERVERONLY); - - /// - /// The id of the sound collection to randomly choose a sound from and play when the round ends. - /// - public static readonly CVarDef RoundEndSoundCollection = - CVarDef.Create("game.round_end_sound_collection", "RoundEnd", CVar.SERVERONLY); - - /// - /// Whether or not to add every player as a global override to PVS at round end. - /// This will allow all players to see their clothing in the round screen player list screen, - /// but may cause lag during round end with very high player counts. - /// - public static readonly CVarDef RoundEndPVSOverrides = - CVarDef.Create("game.round_end_pvs_overrides", true, CVar.SERVERONLY); - - /// - /// If true, players can place objects onto tabletop games like chess boards. - /// - /// - /// This feature is currently highly abusable and can easily be used to crash the server, - /// so it's off by default. - /// - public static readonly CVarDef GameTabletopPlace = - CVarDef.Create("game.tabletop_place", false, CVar.SERVERONLY); - - /// - /// If true, contraband severity can be viewed in the examine menu - /// - public static readonly CVarDef ContrabandExamine = - CVarDef.Create("game.contraband_examine", true, CVar.SERVER | CVar.REPLICATED); - - /// - /// Size of the lookup area for adding entities to the context menu - /// - public static readonly CVarDef GameEntityMenuLookup = - CVarDef.Create("game.entity_menu_lookup", 0.25f, CVar.CLIENTONLY | CVar.ARCHIVE); - - /// - /// Should the clients window show the server hostname in the title? - /// - public static readonly CVarDef GameHostnameInTitlebar = - CVarDef.Create("game.hostname_in_titlebar", true, CVar.SERVER | CVar.REPLICATED); - - /* - * Discord - */ - - /// - /// The role that will get mentioned if a new SOS ahelp comes in. - /// - public static readonly CVarDef DiscordAhelpMention = - CVarDef.Create("discord.on_call_ping", string.Empty, CVar.SERVERONLY | CVar.CONFIDENTIAL); - - /// - /// URL of the discord webhook to relay unanswered ahelp messages. - /// - public static readonly CVarDef DiscordOnCallWebhook = - CVarDef.Create("discord.on_call_webhook", string.Empty, CVar.SERVERONLY | CVar.CONFIDENTIAL); - - /// - /// URL of the Discord webhook which will relay all ahelp messages. - /// - public static readonly CVarDef DiscordAHelpWebhook = - CVarDef.Create("discord.ahelp_webhook", string.Empty, CVar.SERVERONLY | CVar.CONFIDENTIAL); - - /// - /// The server icon to use in the Discord ahelp embed footer. - /// Valid values are specified at https://discord.com/developers/docs/resources/channel#embed-object-embed-footer-structure. - /// - public static readonly CVarDef DiscordAHelpFooterIcon = - CVarDef.Create("discord.ahelp_footer_icon", string.Empty, CVar.SERVERONLY); - - /// - /// The avatar to use for the webhook. Should be an URL. - /// - public static readonly CVarDef DiscordAHelpAvatar = - CVarDef.Create("discord.ahelp_avatar", string.Empty, CVar.SERVERONLY); - - /// - /// URL of the Discord webhook which will relay all custom votes. If left empty, disables the webhook. - /// - public static readonly CVarDef DiscordVoteWebhook = - CVarDef.Create("discord.vote_webhook", string.Empty, CVar.SERVERONLY); - - /// - /// URL of the Discord webhook which will relay all votekick votes. If left empty, disables the webhook. - /// - public static readonly CVarDef DiscordVotekickWebhook = - CVarDef.Create("discord.votekick_webhook", string.Empty, CVar.SERVERONLY); - - /// URL of the Discord webhook which will relay round restart messages. - /// - public static readonly CVarDef DiscordRoundUpdateWebhook = - CVarDef.Create("discord.round_update_webhook", string.Empty, CVar.SERVERONLY | CVar.CONFIDENTIAL); - - /// - /// Role id for the Discord webhook to ping when the round ends. - /// - public static readonly CVarDef DiscordRoundEndRoleWebhook = - CVarDef.Create("discord.round_end_role", string.Empty, CVar.SERVERONLY); - - /* - * Tips - */ - - /// - /// Whether tips being shown is enabled at all. - /// - public static readonly CVarDef TipsEnabled = - CVarDef.Create("tips.enabled", true); - - /// - /// The dataset prototype to use when selecting a random tip. - /// - public static readonly CVarDef TipsDataset = - CVarDef.Create("tips.dataset", "Tips"); - - /// - /// The number of seconds between each tip being displayed when the round is not actively going - /// (i.e. postround or lobby) - /// - public static readonly CVarDef TipFrequencyOutOfRound = - CVarDef.Create("tips.out_of_game_frequency", 60f * 1.5f); - - /// - /// The number of seconds between each tip being displayed when the round is actively going - /// - public static readonly CVarDef TipFrequencyInRound = - CVarDef.Create("tips.in_game_frequency", 60f * 60); - - public static readonly CVarDef LoginTipsDataset = - CVarDef.Create("tips.login_dataset", "Tips"); - - /// - /// The chance for Tippy to replace a normal tip message. - /// - public static readonly CVarDef TipsTippyChance = - CVarDef.Create("tips.tippy_chance", 0.01f); - - /* - * Console - */ - - public static readonly CVarDef ConsoleLoginLocal = - CVarDef.Create("console.loginlocal", true, CVar.ARCHIVE | CVar.SERVERONLY); - - /// - /// Automatically log in the given user as host, equivalent to the promotehost command. - /// - public static readonly CVarDef ConsoleLoginHostUser = - CVarDef.Create("console.login_host_user", "", CVar.ARCHIVE | CVar.SERVERONLY); - - - /* - * Database stuff - */ - - public static readonly CVarDef DatabaseEngine = - CVarDef.Create("database.engine", "sqlite", CVar.SERVERONLY); - - public static readonly CVarDef DatabaseSqliteDbPath = - CVarDef.Create("database.sqlite_dbpath", "preferences.db", CVar.SERVERONLY); - - /// - /// Milliseconds to asynchronously delay all SQLite database acquisitions with. - /// - /// - /// Defaults to 1 on DEBUG, 0 on RELEASE. - /// This is intended to help catch .Result deadlock bugs that only happen on postgres - /// (because SQLite is not actually asynchronous normally) - /// - public static readonly CVarDef DatabaseSqliteDelay = - CVarDef.Create("database.sqlite_delay", DefaultSqliteDelay, CVar.SERVERONLY); - - /// - /// Amount of concurrent SQLite database operations. - /// - /// - /// Note that SQLite is not a properly asynchronous database and also has limited read/write concurrency. - /// Increasing this number may allow more concurrent reads, but it probably won't matter much. - /// SQLite operations are normally ran on the thread pool, which may cause thread pool starvation if the concurrency is too high. - /// - public static readonly CVarDef DatabaseSqliteConcurrency = - CVarDef.Create("database.sqlite_concurrency", 3, CVar.SERVERONLY); - -#if DEBUG - private const int DefaultSqliteDelay = 1; -#else - private const int DefaultSqliteDelay = 0; -#endif - - - public static readonly CVarDef DatabasePgHost = - CVarDef.Create("database.pg_host", "localhost", CVar.SERVERONLY); - - public static readonly CVarDef DatabasePgPort = - CVarDef.Create("database.pg_port", 5432, CVar.SERVERONLY); - - public static readonly CVarDef DatabasePgDatabase = - CVarDef.Create("database.pg_database", "ss14", CVar.SERVERONLY); - - public static readonly CVarDef DatabasePgUsername = - CVarDef.Create("database.pg_username", "postgres", CVar.SERVERONLY); - - public static readonly CVarDef DatabasePgPassword = - CVarDef.Create("database.pg_password", "", CVar.SERVERONLY | CVar.CONFIDENTIAL); - - /// - /// Max amount of concurrent Postgres database operations. - /// - public static readonly CVarDef DatabasePgConcurrency = - CVarDef.Create("database.pg_concurrency", 8, CVar.SERVERONLY); - - /// - /// Milliseconds to asynchronously delay all PostgreSQL database operations with. - /// - /// - /// This is intended for performance testing. It works different from , - /// as the lag is applied after acquiring the database lock. - /// - public static readonly CVarDef DatabasePgFakeLag = - CVarDef.Create("database.pg_fake_lag", 0, CVar.SERVERONLY); - - // Basically only exists for integration tests to avoid race conditions. - public static readonly CVarDef DatabaseSynchronous = - CVarDef.Create("database.sync", false, CVar.SERVERONLY); - - /* - * Interface - */ - - public static readonly CVarDef UIClickSound = - CVarDef.Create("interface.click_sound", "/Audio/UserInterface/click.ogg", CVar.REPLICATED); - - public static readonly CVarDef UIHoverSound = - CVarDef.Create("interface.hover_sound", "/Audio/UserInterface/hover.ogg", CVar.REPLICATED); - - /* - * Outline - */ - - public static readonly CVarDef OutlineEnabled = - CVarDef.Create("outline.enabled", true, CVar.CLIENTONLY); - - - /* - * Parallax - */ - - public static readonly CVarDef ParallaxEnabled = - CVarDef.Create("parallax.enabled", true, CVar.CLIENTONLY); - - public static readonly CVarDef ParallaxDebug = - CVarDef.Create("parallax.debug", false, CVar.CLIENTONLY); - - public static readonly CVarDef ParallaxLowQuality = - CVarDef.Create("parallax.low_quality", false, CVar.ARCHIVE | CVar.CLIENTONLY); - - /* - * Physics - */ - - /// - /// When a mob is walking should its X / Y movement be relative to its parent (true) or the map (false). - /// - public static readonly CVarDef RelativeMovement = - CVarDef.Create("physics.relative_movement", true, CVar.ARCHIVE | CVar.REPLICATED | CVar.SERVER); - - public static readonly CVarDef TileFrictionModifier = - CVarDef.Create("physics.tile_friction", 40.0f, CVar.ARCHIVE | CVar.REPLICATED | CVar.SERVER); - - public static readonly CVarDef StopSpeed = - CVarDef.Create("physics.stop_speed", 0.1f, CVar.ARCHIVE | CVar.REPLICATED | CVar.SERVER); - - /// - /// Whether mobs can push objects like lockers. - /// - /// - /// Technically client doesn't need to know about it but this may prevent a bug in the distant future so it stays. - /// - public static readonly CVarDef MobPushing = - CVarDef.Create("physics.mob_pushing", false, CVar.REPLICATED | CVar.SERVER); - - /* - * Music - */ - - public static readonly CVarDef LobbyMusicEnabled = - CVarDef.Create("ambience.lobby_music_enabled", true, CVar.ARCHIVE | CVar.CLIENTONLY); - - public static readonly CVarDef EventMusicEnabled = - CVarDef.Create("ambience.event_music_enabled", true, CVar.ARCHIVE | CVar.CLIENTONLY); - - /* - * Specific Sounds - */ - // Round end sound (APC Destroyed) - public static readonly CVarDef RestartSoundsEnabled = - CVarDef.Create("ambience.restart_sounds_enabled", true, CVar.ARCHIVE | CVar.CLIENTONLY); - - - /* - * Admin sounds - */ - - public static readonly CVarDef AdminSoundsEnabled = - CVarDef.Create("audio.admin_sounds_enabled", true, CVar.ARCHIVE | CVar.CLIENTONLY); - public static readonly CVarDef AdminChatSoundPath = - CVarDef.Create("audio.admin_chat_sound_path", "/Audio/Items/pop.ogg", CVar.ARCHIVE | CVar.CLIENT | CVar.REPLICATED); - public static readonly CVarDef AdminChatSoundVolume = - CVarDef.Create("audio.admin_chat_sound_volume", -5f, CVar.ARCHIVE | CVar.CLIENT | CVar.REPLICATED); - public static readonly CVarDef AHelpSound = - CVarDef.Create("audio.ahelp_sound", "/Audio/Effects/adminhelp.ogg", CVar.ARCHIVE | CVar.CLIENTONLY); - - /* - * HUD - */ - - public static readonly CVarDef HudTheme = - CVarDef.Create("hud.theme", 0, CVar.ARCHIVE | CVar.CLIENTONLY); - - public static readonly CVarDef HudHeldItemShow = - CVarDef.Create("hud.held_item_show", true, CVar.ARCHIVE | CVar.CLIENTONLY); - - public static readonly CVarDef CombatModeIndicatorsPointShow = - CVarDef.Create("hud.combat_mode_indicators_point_show", true, CVar.ARCHIVE | CVar.CLIENTONLY); - - public static readonly CVarDef LoocAboveHeadShow = - CVarDef.Create("hud.show_looc_above_head", true, CVar.ARCHIVE | CVar.CLIENTONLY); - - public static readonly CVarDef HudHeldItemOffset = - CVarDef.Create("hud.held_item_offset", 28f, CVar.ARCHIVE | CVar.CLIENTONLY); - - public static readonly CVarDef HudFpsCounterVisible = - CVarDef.Create("hud.fps_counter_visible", false, CVar.CLIENTONLY | CVar.ARCHIVE); - - /* - * NPCs - */ - - public static readonly CVarDef NPCMaxUpdates = - CVarDef.Create("npc.max_updates", 128); - - public static readonly CVarDef NPCEnabled = CVarDef.Create("npc.enabled", true); - - /// - /// Should NPCs pathfind when steering. For debug purposes. - /// - public static readonly CVarDef NPCPathfinding = CVarDef.Create("npc.pathfinding", true); - - /* - * Net - */ - - public static readonly CVarDef NetAtmosDebugOverlayTickRate = - CVarDef.Create("net.atmosdbgoverlaytickrate", 3.0f); - - public static readonly CVarDef NetGasOverlayTickRate = - CVarDef.Create("net.gasoverlaytickrate", 3.0f); - - public static readonly CVarDef GasOverlayThresholds = - CVarDef.Create("net.gasoverlaythresholds", 20); - - /* - * Admin - */ - - public static readonly CVarDef AdminAnnounceLogin = - CVarDef.Create("admin.announce_login", true, CVar.SERVERONLY); - - public static readonly CVarDef AdminAnnounceLogout = - CVarDef.Create("admin.announce_logout", true, CVar.SERVERONLY); - - /// - /// The token used to authenticate with the admin API. Leave empty to disable the admin API. This is a secret! Do not share! - /// - public static readonly CVarDef AdminApiToken = - CVarDef.Create("admin.api_token", string.Empty, CVar.SERVERONLY | CVar.CONFIDENTIAL); - - - /// - /// Should users be able to see their own notes? Admins will be able to see and set notes regardless - /// - public static readonly CVarDef SeeOwnNotes = - CVarDef.Create("admin.see_own_notes", false, CVar.ARCHIVE | CVar.REPLICATED | CVar.SERVER); - - /// - /// Should the server play a quick sound to the active admins whenever a new player joins? - /// - public static readonly CVarDef AdminNewPlayerJoinSound = - CVarDef.Create("admin.new_player_join_sound", false, CVar.SERVERONLY); - - /// - /// The amount of days before the note starts fading. It will slowly lose opacity until it reaches stale. Set to 0 to disable. - /// - public static readonly CVarDef NoteFreshDays = - CVarDef.Create("admin.note_fresh_days", 91.31055, CVar.ARCHIVE | CVar.REPLICATED | CVar.SERVER); - - /// - /// The amount of days before the note completely fades, and can only be seen by admins if they press "see more notes". Set to 0 - /// if you want the note to immediately disappear without fading. - /// - public static readonly CVarDef NoteStaleDays = - CVarDef.Create("admin.note_stale_days", 365.2422, CVar.ARCHIVE | CVar.REPLICATED | CVar.SERVER); - - /// - /// How much time does the user have to wait in seconds before confirming that they saw an admin message? - /// - public static readonly CVarDef MessageWaitTime = - CVarDef.Create("admin.message_wait_time", 3f, CVar.ARCHIVE | CVar.REPLICATED | CVar.SERVER); - - /// - /// Default severity for role bans - /// - public static readonly CVarDef RoleBanDefaultSeverity = - CVarDef.Create("admin.role_ban_default_severity", "medium", CVar.ARCHIVE | CVar.SERVER | CVar.REPLICATED); - - /// - /// Default severity for department bans - /// - public static readonly CVarDef DepartmentBanDefaultSeverity = - CVarDef.Create("admin.department_ban_default_severity", "medium", CVar.ARCHIVE | CVar.SERVER | CVar.REPLICATED); - - /// - /// Default severity for server bans - /// - public static readonly CVarDef ServerBanDefaultSeverity = - CVarDef.Create("admin.server_ban_default_severity", "High", CVar.ARCHIVE | CVar.SERVER | CVar.REPLICATED); - - /// - /// Whether a server ban will ban the player's ip by default. - /// - public static readonly CVarDef ServerBanIpBanDefault = - CVarDef.Create("admin.server_ban_ip_ban_default", true, CVar.ARCHIVE | CVar.SERVER | CVar.REPLICATED); - - /// - /// Whether a server ban will ban the player's hardware id by default. - /// - public static readonly CVarDef ServerBanHwidBanDefault = - CVarDef.Create("admin.server_ban_hwid_ban_default", true, CVar.ARCHIVE | CVar.SERVER | CVar.REPLICATED); - - /// - /// Whether to use details from last connection for ip/hwid in the BanPanel. - /// - public static readonly CVarDef ServerBanUseLastDetails = - CVarDef.Create("admin.server_ban_use_last_details", true, CVar.ARCHIVE | CVar.SERVER | CVar.REPLICATED); - - /// - /// Whether to erase a player's chat messages and their entity from the game when banned. - /// - public static readonly CVarDef ServerBanErasePlayer = - CVarDef.Create("admin.server_ban_erase_player", false, CVar.ARCHIVE | CVar.SERVER | CVar.REPLICATED); - - /// - /// Minimum players sharing a connection required to create an alert. -1 to disable the alert. - /// - /// - /// If you set this to 0 or 1 then it will alert on every connection, so probably don't do that. - /// - public static readonly CVarDef AdminAlertMinPlayersSharingConnection = - CVarDef.Create("admin.alert.min_players_sharing_connection", -1, CVar.SERVERONLY); - - /// - /// Minimum explosion intensity to create an admin alert message. -1 to disable the alert. - /// - public static readonly CVarDef AdminAlertExplosionMinIntensity = - CVarDef.Create("admin.alert.explosion_min_intensity", 60, CVar.SERVERONLY); - - /// - /// Minimum particle accelerator strength to create an admin alert message. - /// - public static readonly CVarDef AdminAlertParticleAcceleratorMinPowerState = - CVarDef.Create("admin.alert.particle_accelerator_min_power_state", 5, CVar.SERVERONLY); // strength 4 - - /// - /// Should the ban details in admin channel include PII? (IP, HWID, etc) - /// - public static readonly CVarDef AdminShowPIIOnBan = - CVarDef.Create("admin.show_pii_onban", false, CVar.SERVERONLY); - - /// - /// If an admin joins a round by reading up or using the late join button, automatically - /// de-admin them. - /// - public static readonly CVarDef AdminDeadminOnJoin = - CVarDef.Create("admin.deadmin_on_join", false, CVar.SERVERONLY); - - /// - /// Overrides the name the client sees in ahelps. Set empty to disable. - /// - public static readonly CVarDef AdminAhelpOverrideClientName = - CVarDef.Create("admin.override_adminname_in_client_ahelp", string.Empty, CVar.SERVERONLY); - - /// - /// The threshold of minutes to appear as a "new player" in the ahelp menu - /// If 0, appearing as a new player is disabled. - /// - public static readonly CVarDef NewPlayerThreshold = - CVarDef.Create("admin.new_player_threshold", 0, CVar.ARCHIVE | CVar.REPLICATED | CVar.SERVER); - - /// - /// How long an admin client can go without any input before being considered AFK. - /// - public static readonly CVarDef AdminAfkTime = - CVarDef.Create("admin.afk_time", 600f, CVar.SERVERONLY); - - /// - /// If true, admins are able to connect even if - /// would otherwise block regular players. - /// - public static readonly CVarDef AdminBypassMaxPlayers = - CVarDef.Create("admin.bypass_max_players", true, CVar.SERVERONLY); - - /// - /// Determine if custom rank names are used. - /// If it is false, it'd use the actual rank name regardless of the individual's title. - /// - /// - /// - public static readonly CVarDef AdminUseCustomNamesAdminRank = - CVarDef.Create("admin.use_custom_names_admin_rank", true, CVar.SERVERONLY); - - /* - * AHELP - */ - - /// - /// Ahelp rate limit values are accounted in periods of this size (seconds). - /// After the period has passed, the count resets. - /// - /// - public static readonly CVarDef AhelpRateLimitPeriod = - CVarDef.Create("ahelp.rate_limit_period", 2f, CVar.SERVERONLY); - - /// - /// How many ahelp messages are allowed in a single rate limit period. - /// - /// - public static readonly CVarDef AhelpRateLimitCount = - CVarDef.Create("ahelp.rate_limit_count", 10, CVar.SERVERONLY); - - /// - /// Should the administrator's position be displayed in ahelp. - /// If it is is false, only the admin's ckey will be displayed in the ahelp. - /// - /// - /// - public static readonly CVarDef AhelpAdminPrefix = - CVarDef.Create("ahelp.admin_prefix", false, CVar.SERVERONLY); - - /// - /// Should the administrator's position be displayed in the webhook. - /// If it is is false, only the admin's ckey will be displayed in webhook. - /// - /// - /// - public static readonly CVarDef AhelpAdminPrefixWebhook = - CVarDef.Create("ahelp.admin_prefix_webhook", false, CVar.SERVERONLY); - - /* - * Explosions - */ - - /// - /// How many tiles the explosion system will process per tick - /// - /// - /// Setting this too high will put a large load on a single tick. Setting this too low will lead to - /// unnaturally "slow" explosions. - /// - public static readonly CVarDef ExplosionTilesPerTick = - CVarDef.Create("explosion.tiles_per_tick", 100, CVar.SERVERONLY); - - /// - /// Upper limit on the size of an explosion before physics-throwing is disabled. - /// - /// - /// Large nukes tend to generate a lot of shrapnel that flies through space. This can functionally cripple - /// the server TPS for a while after an explosion (or even during, if the explosion is processed - /// incrementally. - /// - public static readonly CVarDef ExplosionThrowLimit = - CVarDef.Create("explosion.throw_limit", 400, CVar.SERVERONLY); - - /// - /// If this is true, explosion processing will pause the NodeGroupSystem to pause updating. - /// - /// - /// This only takes effect if an explosion needs more than one tick to process (i.e., covers more than tiles). If this is not enabled, the node-system will rebuild its graph - /// every tick as the explosion shreds the station, causing significant slowdown. - /// - public static readonly CVarDef ExplosionSleepNodeSys = - CVarDef.Create("explosion.node_sleep", true, CVar.SERVERONLY); - - /// - /// Upper limit on the total area that an explosion can affect before the neighbor-finding algorithm just - /// stops. Defaults to a 60-rile radius explosion. - /// - /// - /// Actual area may be larger, as it currently doesn't terminate mid neighbor finding. I.e., area may be that of a ~51 tile radius circle instead. - /// - public static readonly CVarDef ExplosionMaxArea = - CVarDef.Create("explosion.max_area", (int) 3.14f * 256 * 256, CVar.SERVERONLY); - - /// - /// Upper limit on the number of neighbor finding steps for the explosion system neighbor-finding algorithm. - /// - /// - /// Effectively places an upper limit on the range that any explosion can have. In the vast majority of - /// instances, will likely be hit before this becomes a limiting factor. - /// - public static readonly CVarDef ExplosionMaxIterations = - CVarDef.Create("explosion.max_iterations", 500, CVar.SERVERONLY); - - /// - /// Max Time in milliseconds to spend processing explosions every tick. - /// - /// - /// This time limiting is not perfectly implemented. Firstly, a significant chunk of processing time happens - /// due to queued entity deletions, which happen outside of the system update code. Secondly, explosion - /// spawning cannot currently be interrupted & resumed, and may lead to exceeding this time limit. - /// - public static readonly CVarDef ExplosionMaxProcessingTime = - CVarDef.Create("explosion.max_tick_time", 7f, CVar.SERVERONLY); - - /// - /// If the explosion is being processed incrementally over several ticks, this variable determines whether - /// updating the grid tiles should be done incrementally at the end of every tick, or only once the explosion has finished processing. - /// - /// - /// The most notable consequence of this change is that explosions will only punch a hole in the station & - /// create a vacumm once they have finished exploding. So airlocks will no longer slam shut as the explosion - /// expands, just suddenly at the end. - /// - public static readonly CVarDef ExplosionIncrementalTileBreaking = - CVarDef.Create("explosion.incremental_tile", false, CVar.SERVERONLY); - - /// - /// This determines for how many seconds an explosion should stay visible once it has finished expanding. - /// - public static readonly CVarDef ExplosionPersistence = - CVarDef.Create("explosion.persistence", 1.0f, CVar.SERVERONLY); - - /// - /// If an explosion covers a larger area than this number, the damaging/processing will always start during - /// the next tick, instead of during the same tick that the explosion was generated in. - /// - /// - /// This value can be used to ensure that for large explosions the area/tile calculation and the explosion - /// processing/damaging occurs in separate ticks. This helps reduce the single-tick lag if both and are large. I.e., instead of - /// a single tick explosion, this cvar allows for a configuration that results in a two-tick explosion, - /// though most of the computational cost is still in the second tick. - /// - public static readonly CVarDef ExplosionSingleTickAreaLimit = - CVarDef.Create("explosion.single_tick_area_limit", 400, CVar.SERVERONLY); - - /// - /// Whether or not explosions are allowed to create tiles that have - /// set to true. - /// - public static readonly CVarDef ExplosionCanCreateVacuum = - CVarDef.Create("explosion.can_create_vacuum", true, CVar.SERVERONLY); - - /* - * Radiation - */ - - /// - /// What is the smallest radiation dose in rads that can be received by object. - /// Extremely small values may impact performance. - /// - public static readonly CVarDef RadiationMinIntensity = - CVarDef.Create("radiation.min_intensity", 0.1f, CVar.SERVERONLY); - - /// - /// Rate of radiation system update in seconds. - /// - public static readonly CVarDef RadiationGridcastUpdateRate = - CVarDef.Create("radiation.gridcast.update_rate", 1.0f, CVar.SERVERONLY); - - /// - /// If both radiation source and receiver are placed on same grid, ignore grids between them. - /// May get inaccurate result in some cases, but greatly boost performance in general. - /// - public static readonly CVarDef RadiationGridcastSimplifiedSameGrid = - CVarDef.Create("radiation.gridcast.simplified_same_grid", true, CVar.SERVERONLY); - - /// - /// Max distance that radiation ray can travel in meters. - /// - public static readonly CVarDef RadiationGridcastMaxDistance = - CVarDef.Create("radiation.gridcast.max_distance", 50f, CVar.SERVERONLY); - - /* - * Admin logs - */ - - /// - /// Controls if admin logs are enabled. Highly recommended to shut this off for development. - /// - public static readonly CVarDef AdminLogsEnabled = - CVarDef.Create("adminlogs.enabled", true, CVar.SERVERONLY); - - public static readonly CVarDef AdminLogsQueueSendDelay = - CVarDef.Create("adminlogs.queue_send_delay_seconds", 5f, CVar.SERVERONLY); - - // When to skip the waiting time to save in-round admin logs, if no admin logs are currently being saved - public static readonly CVarDef AdminLogsQueueMax = - CVarDef.Create("adminlogs.queue_max", 5000, CVar.SERVERONLY); - - // When to skip the waiting time to save pre-round admin logs, if no admin logs are currently being saved - public static readonly CVarDef AdminLogsPreRoundQueueMax = - CVarDef.Create("adminlogs.pre_round_queue_max", 5000, CVar.SERVERONLY); - - // When to start dropping logs - public static readonly CVarDef AdminLogsDropThreshold = - CVarDef.Create("adminlogs.drop_threshold", 20000, CVar.SERVERONLY); - - // How many logs to send to the client at once - public static readonly CVarDef AdminLogsClientBatchSize = - CVarDef.Create("adminlogs.client_batch_size", 1000, CVar.SERVERONLY); - - public static readonly CVarDef AdminLogsServerName = - CVarDef.Create("adminlogs.server_name", "unknown", CVar.SERVERONLY); - - /* - * Atmos - */ - - /// - /// Whether gas differences will move entities. - /// - public static readonly CVarDef SpaceWind = - CVarDef.Create("atmos.space_wind", false, CVar.SERVERONLY); - - /// - /// Divisor from maxForce (pressureDifference * 2.25f) to force applied on objects. - /// - public static readonly CVarDef SpaceWindPressureForceDivisorThrow = - CVarDef.Create("atmos.space_wind_pressure_force_divisor_throw", 15f, CVar.SERVERONLY); - - /// - /// Divisor from maxForce (pressureDifference * 2.25f) to force applied on objects. - /// - public static readonly CVarDef SpaceWindPressureForceDivisorPush = - CVarDef.Create("atmos.space_wind_pressure_force_divisor_push", 2500f, CVar.SERVERONLY); - - /// - /// The maximum velocity (not force) that may be applied to an object by atmospheric pressure differences. - /// Useful to prevent clipping through objects. - /// - public static readonly CVarDef SpaceWindMaxVelocity = - CVarDef.Create("atmos.space_wind_max_velocity", 30f, CVar.SERVERONLY); - - /// - /// The maximum force that may be applied to an object by pushing (i.e. not throwing) atmospheric pressure differences. - /// A "throwing" atmospheric pressure difference ignores this limit, but not the max. velocity limit. - /// - public static readonly CVarDef SpaceWindMaxPushForce = - CVarDef.Create("atmos.space_wind_max_push_force", 20f, CVar.SERVERONLY); - - /// - /// Whether monstermos tile equalization is enabled. - /// - public static readonly CVarDef MonstermosEqualization = - CVarDef.Create("atmos.monstermos_equalization", true, CVar.SERVERONLY); - - /// - /// Whether monstermos explosive depressurization is enabled. - /// Needs to be enabled to work. - /// - public static readonly CVarDef MonstermosDepressurization = - CVarDef.Create("atmos.monstermos_depressurization", true, CVar.SERVERONLY); - - /// - /// Whether monstermos explosive depressurization will rip tiles.. - /// Needs and to be enabled to work. - /// WARNING: This cvar causes MAJOR contrast issues, and usually tends to make any spaced scene look very cluttered. - /// This not only usually looks strange, but can also reduce playability for people with impaired vision. Please think twice before enabling this on your server. - /// Also looks weird on slow spacing for unrelated reasons. If you do want to enable this, you should probably turn on instaspacing. - /// - public static readonly CVarDef MonstermosRipTiles = - CVarDef.Create("atmos.monstermos_rip_tiles", false, CVar.SERVERONLY); - - /// - /// Whether explosive depressurization will cause the grid to gain an impulse. - /// Needs and to be enabled to work. - /// - public static readonly CVarDef AtmosGridImpulse = - CVarDef.Create("atmos.grid_impulse", false, CVar.SERVERONLY); - - /// - /// What fraction of air from a spaced tile escapes every tick. - /// 1.0 for instant spacing, 0.2 means 20% of remaining air lost each time - /// - public static readonly CVarDef AtmosSpacingEscapeRatio = - CVarDef.Create("atmos.mmos_spacing_speed", 0.15f, CVar.SERVERONLY); - - /// - /// Minimum amount of air allowed on a spaced tile before it is reset to 0 immediately in kPa - /// Since the decay due to SpacingEscapeRatio follows a curve, it would never reach 0.0 exactly - /// unless we truncate it somewhere. - /// - public static readonly CVarDef AtmosSpacingMinGas = - CVarDef.Create("atmos.mmos_min_gas", 2.0f, CVar.SERVERONLY); +namespace Content.Shared.CCVar; - /// - /// How much wind can go through a single tile before that tile doesn't depressurize itself - /// (I.e spacing is limited in large rooms heading into smaller spaces) - /// - public static readonly CVarDef AtmosSpacingMaxWind = - CVarDef.Create("atmos.mmos_max_wind", 500f, CVar.SERVERONLY); - - /// - /// Whether atmos superconduction is enabled. - /// - /// Disabled by default, superconduction is awful. - public static readonly CVarDef Superconduction = - CVarDef.Create("atmos.superconduction", false, CVar.SERVERONLY); - - /// - /// Heat loss per tile due to radiation at 20 degC, in W. - /// - public static readonly CVarDef SuperconductionTileLoss = - CVarDef.Create("atmos.superconduction_tile_loss", 30f, CVar.SERVERONLY); - - /// - /// Whether excited groups will be processed and created. - /// - public static readonly CVarDef ExcitedGroups = - CVarDef.Create("atmos.excited_groups", true, CVar.SERVERONLY); - - /// - /// Whether all tiles in an excited group will clear themselves once being exposed to space. - /// Similar to , without none of the tile ripping or - /// things being thrown around very violently. - /// Needs to be enabled to work. - /// - public static readonly CVarDef ExcitedGroupsSpaceIsAllConsuming = - CVarDef.Create("atmos.excited_groups_space_is_all_consuming", false, CVar.SERVERONLY); - - /// - /// Maximum time in milliseconds that atmos can take processing. - /// - public static readonly CVarDef AtmosMaxProcessTime = - CVarDef.Create("atmos.max_process_time", 3f, CVar.SERVERONLY); - - /// - /// Atmos tickrate in TPS. Atmos processing will happen every 1/TPS seconds. - /// - public static readonly CVarDef AtmosTickRate = - CVarDef.Create("atmos.tickrate", 15f, CVar.SERVERONLY); - - /// - /// Scale factor for how fast things happen in our atmosphere - /// simulation compared to real life. 1x means pumps run at 1x - /// speed. Players typically expect things to happen faster - /// in-game. - /// - public static readonly CVarDef AtmosSpeedup = - CVarDef.Create("atmos.speedup", 8f, CVar.SERVERONLY); - - /// - /// Like atmos.speedup, but only for gas and reaction heat values. 64x means - /// gases heat up and cool down 64x faster than real life. - /// - public static readonly CVarDef AtmosHeatScale = - CVarDef.Create("atmos.heat_scale", 8f, CVar.SERVERONLY); - - /// - /// Maximum explosion radius for explosions caused by bursting a gas tank ("max caps"). - /// Setting this to zero disables the explosion but still allows the tank to burst and leak. - /// - public static readonly CVarDef AtmosTankFragment = - CVarDef.Create("atmos.max_explosion_range", 26f, CVar.SERVERONLY); - - /* - * MIDI instruments - */ - - public static readonly CVarDef MaxMidiEventsPerSecond = - CVarDef.Create("midi.max_events_per_second", 1000, CVar.REPLICATED | CVar.SERVER); - - public static readonly CVarDef MaxMidiEventsPerBatch = - CVarDef.Create("midi.max_events_per_batch", 60, CVar.REPLICATED | CVar.SERVER); - - public static readonly CVarDef MaxMidiBatchesDropped = - CVarDef.Create("midi.max_batches_dropped", 1, CVar.SERVERONLY); - - public static readonly CVarDef MaxMidiLaggedBatches = - CVarDef.Create("midi.max_lagged_batches", 8, CVar.SERVERONLY); - - /* - * Holidays - */ - - public static readonly CVarDef HolidaysEnabled = CVarDef.Create("holidays.enabled", true, CVar.SERVERONLY); - - /* - * Branding stuff - */ - - public static readonly CVarDef BrandingSteam = CVarDef.Create("branding.steam", false, CVar.CLIENTONLY); - - /* - * OOC - */ - - public static readonly CVarDef OocEnabled = CVarDef.Create("ooc.enabled", true, CVar.NOTIFY | CVar.REPLICATED); - - public static readonly CVarDef AdminOocEnabled = - CVarDef.Create("ooc.enabled_admin", true, CVar.NOTIFY); - - /// - /// If true, whenever OOC is disabled the Discord OOC relay will also be disabled. - /// - public static readonly CVarDef DisablingOOCDisablesRelay = CVarDef.Create("ooc.disabling_ooc_disables_relay", true, CVar.SERVERONLY); - - /// - /// Whether or not OOC chat should be enabled during a round. - /// - public static readonly CVarDef OocEnableDuringRound = - CVarDef.Create("ooc.enable_during_round", false, CVar.NOTIFY | CVar.REPLICATED | CVar.SERVER); - - public static readonly CVarDef ShowOocPatronColor = - CVarDef.Create("ooc.show_ooc_patron_color", true, CVar.ARCHIVE | CVar.REPLICATED | CVar.CLIENT); - - /* - * LOOC - */ - - public static readonly CVarDef LoocEnabled = CVarDef.Create("looc.enabled", true, CVar.NOTIFY | CVar.REPLICATED); - - public static readonly CVarDef AdminLoocEnabled = - CVarDef.Create("looc.enabled_admin", true, CVar.NOTIFY); - - /// - /// True: Dead players can use LOOC - /// False: Dead player LOOC gets redirected to dead chat - /// - public static readonly CVarDef DeadLoocEnabled = CVarDef.Create("looc.enabled_dead", false, CVar.NOTIFY | CVar.REPLICATED); - - /// - /// True: Crit players can use LOOC - /// False: Crit player LOOC gets redirected to dead chat - /// - public static readonly CVarDef CritLoocEnabled = CVarDef.Create("looc.enabled_crit", false, CVar.NOTIFY | CVar.REPLICATED); - - /* - * Entity Menu Grouping Types - */ - public static readonly CVarDef EntityMenuGroupingType = CVarDef.Create("entity_menu", 0, CVar.CLIENTONLY); - - /* - * Whitelist - */ - - /// - /// Controls whether the server will deny any players that are not whitelisted in the DB. - /// - public static readonly CVarDef WhitelistEnabled = - CVarDef.Create("whitelist.enabled", false, CVar.SERVERONLY); - /// - /// Specifies the whitelist prototypes to be used by the server. This should be a comma-separated list of prototypes. - /// If a whitelists conditions to be active fail (for example player count), the next whitelist will be used instead. If no whitelist is valid, the player will be allowed to connect. - /// - public static readonly CVarDef WhitelistPrototypeList = - CVarDef.Create("whitelist.prototype_list", "basicWhitelist", CVar.SERVERONLY); - - /* - * VOTE - */ - - /// - /// Allows enabling/disabling player-started votes for ultimate authority - /// - public static readonly CVarDef VoteEnabled = - CVarDef.Create("vote.enabled", true, CVar.SERVERONLY); - - /// - /// See vote.enabled, but specific to restart votes - /// - public static readonly CVarDef VoteRestartEnabled = - CVarDef.Create("vote.restart_enabled", true, CVar.SERVERONLY); - - /// - /// Config for when the restart vote should be allowed to be called regardless with less than this amount of players. - /// - public static readonly CVarDef VoteRestartMaxPlayers = - CVarDef.Create("vote.restart_max_players", 20, CVar.SERVERONLY); - - /// - /// Config for when the restart vote should be allowed to be called based on percentage of ghosts. - /// - public static readonly CVarDef VoteRestartGhostPercentage = - CVarDef.Create("vote.restart_ghost_percentage", 55, CVar.SERVERONLY); - - /// - /// See vote.enabled, but specific to preset votes - /// - public static readonly CVarDef VotePresetEnabled = - CVarDef.Create("vote.preset_enabled", true, CVar.SERVERONLY); - - /// - /// See vote.enabled, but specific to map votes - /// - public static readonly CVarDef VoteMapEnabled = - CVarDef.Create("vote.map_enabled", false, CVar.SERVERONLY); - - /// - /// The required ratio of the server that must agree for a restart round vote to go through. - /// - public static readonly CVarDef VoteRestartRequiredRatio = - CVarDef.Create("vote.restart_required_ratio", 0.85f, CVar.SERVERONLY); - - /// - /// Whether or not to prevent the restart vote from having any effect when there is an online admin - /// - public static readonly CVarDef VoteRestartNotAllowedWhenAdminOnline = - CVarDef.Create("vote.restart_not_allowed_when_admin_online", true, CVar.SERVERONLY); - - /// - /// The delay which two votes of the same type are allowed to be made by separate people, in seconds. - /// - public static readonly CVarDef VoteSameTypeTimeout = - CVarDef.Create("vote.same_type_timeout", 240f, CVar.SERVERONLY); - - /// - /// Sets the duration of the map vote timer. - /// - public static readonly CVarDef - VoteTimerMap = CVarDef.Create("vote.timermap", 90, CVar.SERVERONLY); - - /// - /// Sets the duration of the restart vote timer. - /// - public static readonly CVarDef - VoteTimerRestart = CVarDef.Create("vote.timerrestart", 60, CVar.SERVERONLY); - - /// - /// Sets the duration of the gamemode/preset vote timer. - /// - public static readonly CVarDef - VoteTimerPreset = CVarDef.Create("vote.timerpreset", 30, CVar.SERVERONLY); - - /// - /// Sets the duration of the map vote timer when ALONE. - /// - public static readonly CVarDef - VoteTimerAlone = CVarDef.Create("vote.timeralone", 10, CVar.SERVERONLY); - - /* - * VOTEKICK - */ - - /// - /// Allows enabling/disabling player-started votekick for ultimate authority - /// - public static readonly CVarDef VotekickEnabled = - CVarDef.Create("votekick.enabled", true, CVar.SERVERONLY); - - /// - /// Config for when the votekick should be allowed to be called based on number of eligible voters. - /// - public static readonly CVarDef VotekickEligibleNumberRequirement = - CVarDef.Create("votekick.eligible_number", 5, CVar.SERVERONLY); - - /// - /// Whether a votekick initiator must be a ghost or not. - /// - public static readonly CVarDef VotekickInitiatorGhostRequirement = - CVarDef.Create("votekick.initiator_ghost_requirement", true, CVar.SERVERONLY); - - /// - /// Should the initiator be whitelisted to initiate a votekick? - /// - public static readonly CVarDef VotekickInitiatorWhitelistedRequirement = - CVarDef.Create("votekick.initiator_whitelist_requirement", true, CVar.SERVERONLY); - - /// - /// Should the initiator be able to start a votekick if they are bellow the votekick.voter_playtime requirement? - /// - public static readonly CVarDef VotekickInitiatorTimeRequirement = - CVarDef.Create("votekick.initiator_time_requirement", false, CVar.SERVERONLY); - - /// - /// Whether a votekick voter must be a ghost or not. - /// - public static readonly CVarDef VotekickVoterGhostRequirement = - CVarDef.Create("votekick.voter_ghost_requirement", true, CVar.SERVERONLY); - - /// - /// Config for how many hours playtime a player must have to be able to vote on a votekick. - /// - public static readonly CVarDef VotekickEligibleVoterPlaytime = - CVarDef.Create("votekick.voter_playtime", 100, CVar.SERVERONLY); - - /// - /// Config for how many seconds a player must have been dead to initiate a votekick / be able to vote on a votekick. - /// - public static readonly CVarDef VotekickEligibleVoterDeathtime = - CVarDef.Create("votekick.voter_deathtime", 30, CVar.REPLICATED | CVar.SERVER); - - /// - /// The required ratio of eligible voters that must agree for a votekick to go through. - /// - public static readonly CVarDef VotekickRequiredRatio = - CVarDef.Create("votekick.required_ratio", 0.6f, CVar.SERVERONLY); - - /// - /// Whether or not to prevent the votekick from having any effect when there is an online admin. - /// - public static readonly CVarDef VotekickNotAllowedWhenAdminOnline = - CVarDef.Create("votekick.not_allowed_when_admin_online", true, CVar.SERVERONLY); - - /// - /// The delay for which two votekicks are allowed to be made by separate people, in seconds. - /// - public static readonly CVarDef VotekickTimeout = - CVarDef.Create("votekick.timeout", 120f, CVar.SERVERONLY); - - /// - /// Sets the duration of the votekick vote timer. - /// - public static readonly CVarDef - VotekickTimer = CVarDef.Create("votekick.timer", 60, CVar.SERVERONLY); - - /// - /// Config for how many hours playtime a player must have to get protection from the Raider votekick type when playing as an antag. - /// - public static readonly CVarDef VotekickAntagRaiderProtection = - CVarDef.Create("votekick.antag_raider_protection", 10, CVar.SERVERONLY); - - /// - /// Default severity for votekick bans - /// - public static readonly CVarDef VotekickBanDefaultSeverity = - CVarDef.Create("votekick.ban_default_severity", "High", CVar.ARCHIVE | CVar.SERVER | CVar.REPLICATED); - - /// - /// Duration of a ban caused by a votekick (in minutes). - /// - public static readonly CVarDef VotekickBanDuration = - CVarDef.Create("votekick.ban_duration", 180, CVar.SERVERONLY); - - /// - /// Whether the ghost requirement settings for votekicks should be ignored for the lobby. - /// - public static readonly CVarDef VotekickIgnoreGhostReqInLobby = - CVarDef.Create("votekick.ignore_ghost_req_in_lobby", true, CVar.SERVERONLY); - - /* - * BAN - */ - - public static readonly CVarDef BanHardwareIds = - CVarDef.Create("ban.hardware_ids", true, CVar.SERVERONLY); - - /* - * Procgen - */ - - /// - /// Should we pre-load all of the procgen atlasses. - /// - public static readonly CVarDef ProcgenPreload = - CVarDef.Create("procgen.preload", true, CVar.SERVERONLY); - - /* - * Shuttles - */ - - // Look this is technically eye behavior but its main impact is shuttles so I just dumped it here. - /// - /// If true then the camera will match the grid / map and is unchangeable. - /// - When traversing grids it will snap to 0 degrees rotation. - /// False means the player has control over the camera rotation. - /// - When traversing grids it will snap to the nearest cardinal which will generally be imperceptible. - /// - public static readonly CVarDef CameraRotationLocked = - CVarDef.Create("shuttle.camera_rotation_locked", false, CVar.REPLICATED); - - /// - /// Whether the arrivals terminal should be on a planet map. - /// - public static readonly CVarDef ArrivalsPlanet = - CVarDef.Create("shuttle.arrivals_planet", true, CVar.SERVERONLY); - - /// - /// Whether the arrivals shuttle is enabled. - /// - public static readonly CVarDef ArrivalsShuttles = - CVarDef.Create("shuttle.arrivals", true, CVar.SERVERONLY); - - /// - /// The map to use for the arrivals station. - /// - public static readonly CVarDef ArrivalsMap = - CVarDef.Create("shuttle.arrivals_map", "/Maps/Misc/terminal.yml", CVar.SERVERONLY); - - /// - /// Cooldown between arrivals departures. This should be longer than the FTL time or it will double cycle. - /// - public static readonly CVarDef ArrivalsCooldown = - CVarDef.Create("shuttle.arrivals_cooldown", 50f, CVar.SERVERONLY); - - /// - /// Are players allowed to return on the arrivals shuttle. - /// - public static readonly CVarDef ArrivalsReturns = - CVarDef.Create("shuttle.arrivals_returns", false, CVar.SERVERONLY); - - /// - /// Should all players who spawn at arrivals have godmode until they leave the map? - /// - public static readonly CVarDef GodmodeArrivals = - CVarDef.Create("shuttle.godmode_arrivals", false, CVar.SERVERONLY); - - /// - /// If a grid is split then hide any smaller ones under this mass (kg) from the map. - /// This is useful to avoid split grids spamming out labels. - /// - public static readonly CVarDef HideSplitGridsUnder = - CVarDef.Create("shuttle.hide_split_grids_under", 30, CVar.SERVERONLY); - - /// - /// Whether to automatically spawn escape shuttles. - /// - public static readonly CVarDef GridFill = - CVarDef.Create("shuttle.grid_fill", true, CVar.SERVERONLY); - - /// - /// Whether to automatically preloading grids by GridPreloaderSystem - /// - public static readonly CVarDef PreloadGrids = - CVarDef.Create("shuttle.preload_grids", true, CVar.SERVERONLY); - - /// - /// How long the warmup time before FTL start should be. - /// - public static readonly CVarDef FTLStartupTime = - CVarDef.Create("shuttle.startup_time", 5.5f, CVar.SERVERONLY); - - /// - /// How long a shuttle spends in FTL. - /// - public static readonly CVarDef FTLTravelTime = - CVarDef.Create("shuttle.travel_time", 20f, CVar.SERVERONLY); - - /// - /// How long the final stage of FTL before arrival should be. - /// - public static readonly CVarDef FTLArrivalTime = - CVarDef.Create("shuttle.arrival_time", 5f, CVar.SERVERONLY); - - /// - /// How much time needs to pass before a shuttle can FTL again. - /// - public static readonly CVarDef FTLCooldown = - CVarDef.Create("shuttle.cooldown", 10f, CVar.SERVERONLY); - - /// - /// The maximum a grid can have before it becomes unable to FTL. - /// Any value equal to or less than zero will disable this check. - /// - public static readonly CVarDef FTLMassLimit = - CVarDef.Create("shuttle.mass_limit", 300f, CVar.SERVERONLY); - - /// - /// How long to knock down entities for if they aren't buckled when FTL starts and stops. - /// - public static readonly CVarDef HyperspaceKnockdownTime = - CVarDef.Create("shuttle.hyperspace_knockdown_time", 5f, CVar.SERVERONLY); - - /* - * Emergency - */ - - /// - /// Is the emergency shuttle allowed to be early launched. - /// - public static readonly CVarDef EmergencyEarlyLaunchAllowed = - CVarDef.Create("shuttle.emergency_early_launch_allowed", false, CVar.SERVERONLY); - - /// - /// How long the emergency shuttle remains docked with the station, in seconds. - /// - public static readonly CVarDef EmergencyShuttleDockTime = - CVarDef.Create("shuttle.emergency_dock_time", 180f, CVar.SERVERONLY); - - /// - /// If the emergency shuttle can't dock at a priority port, the dock time will be multiplied with this value. - /// - public static readonly CVarDef EmergencyShuttleDockTimeMultiplierOtherDock = - CVarDef.Create("shuttle.emergency_dock_time_multiplier_other_dock", 1.6667f, CVar.SERVERONLY); - - /// - /// If the emergency shuttle can't dock at all, the dock time will be multiplied with this value. - /// - public static readonly CVarDef EmergencyShuttleDockTimeMultiplierNoDock = - CVarDef.Create("shuttle.emergency_dock_time_multiplier_no_dock", 2f, CVar.SERVERONLY); - - /// - /// How long after the console is authorized for the shuttle to early launch. - /// - public static readonly CVarDef EmergencyShuttleAuthorizeTime = - CVarDef.Create("shuttle.emergency_authorize_time", 10f, CVar.SERVERONLY); - - /// - /// The minimum time for the emergency shuttle to arrive at centcomm. - /// Actual minimum travel time cannot be less than - /// - public static readonly CVarDef EmergencyShuttleMinTransitTime = - CVarDef.Create("shuttle.emergency_transit_time_min", 60f, CVar.SERVERONLY); - - /// - /// The maximum time for the emergency shuttle to arrive at centcomm. - /// - public static readonly CVarDef EmergencyShuttleMaxTransitTime = - CVarDef.Create("shuttle.emergency_transit_time_max", 180f, CVar.SERVERONLY); - - /// - /// Whether the emergency shuttle is enabled or should the round just end. - /// - public static readonly CVarDef EmergencyShuttleEnabled = - CVarDef.Create("shuttle.emergency", true, CVar.SERVERONLY); - - /// - /// The percentage of time passed from the initial call to when the shuttle can no longer be recalled. - /// ex. a call time of 10min and turning point of 0.5 means the shuttle cannot be recalled after 5 minutes. - /// - public static readonly CVarDef EmergencyRecallTurningPoint = - CVarDef.Create("shuttle.recall_turning_point", 0.5f, CVar.SERVERONLY); - - /// - /// Time in minutes after round start to auto-call the shuttle. Set to zero to disable. - /// - public static readonly CVarDef EmergencyShuttleAutoCallTime = - CVarDef.Create("shuttle.auto_call_time", 90, CVar.SERVERONLY); - - /// - /// Time in minutes after the round was extended (by recalling the shuttle) to call - /// the shuttle again. - /// - public static readonly CVarDef EmergencyShuttleAutoCallExtensionTime = - CVarDef.Create("shuttle.auto_call_extension_time", 45, CVar.SERVERONLY); - - /* - * Crew Manifests - */ - - /// - /// Setting this allows a crew manifest to be opened from any window - /// that has a crew manifest button, and sends the correct message. - /// If this is false, only in-game entities will allow you to see - /// the crew manifest, if the functionality is coded in. - /// Having administrator priveledge ignores this, but will still - /// hide the button in UI windows. - /// - public static readonly CVarDef CrewManifestWithoutEntity = - CVarDef.Create("crewmanifest.no_entity", true, CVar.REPLICATED); - - /// - /// Setting this allows the crew manifest to be viewed from 'unsecure' - /// entities, such as the PDA. - /// - public static readonly CVarDef CrewManifestUnsecure = - CVarDef.Create("crewmanifest.unsecure", true, CVar.REPLICATED); - - /* - * Biomass - */ - - /// - /// Enabled: Cloning has 70% cost and reclaimer will refuse to reclaim corpses with souls. (For LRP). - /// Disabled: Cloning has full biomass cost and reclaimer can reclaim corpses with souls. (Playtested and balanced for MRP+). - /// - public static readonly CVarDef BiomassEasyMode = - CVarDef.Create("biomass.easy_mode", true, CVar.SERVERONLY); - - /* - * Anomaly - */ - - /// - /// A scale factor applied to a grid's bounds when trying to find a spot to randomly generate an anomaly. - /// - public static readonly CVarDef AnomalyGenerationGridBoundsScale = - CVarDef.Create("anomaly.generation_grid_bounds_scale", 0.6f, CVar.SERVERONLY); - - /* - * VIEWPORT - */ - - public static readonly CVarDef ViewportStretch = - CVarDef.Create("viewport.stretch", true, CVar.CLIENTONLY | CVar.ARCHIVE); - - public static readonly CVarDef ViewportFixedScaleFactor = - CVarDef.Create("viewport.fixed_scale_factor", 2, CVar.CLIENTONLY | CVar.ARCHIVE); - - // This default is basically specifically chosen so fullscreen/maximized 1080p hits a 2x snap and does NN. - public static readonly CVarDef ViewportSnapToleranceMargin = - CVarDef.Create("viewport.snap_tolerance_margin", 64, CVar.CLIENTONLY | CVar.ARCHIVE); - - public static readonly CVarDef ViewportSnapToleranceClip = - CVarDef.Create("viewport.snap_tolerance_clip", 32, CVar.CLIENTONLY | CVar.ARCHIVE); - - public static readonly CVarDef ViewportScaleRender = - CVarDef.Create("viewport.scale_render", true, CVar.CLIENTONLY | CVar.ARCHIVE); - - public static readonly CVarDef ViewportMinimumWidth = - CVarDef.Create("viewport.minimum_width", 15, CVar.REPLICATED | CVar.SERVER); - - public static readonly CVarDef ViewportMaximumWidth = - CVarDef.Create("viewport.maximum_width", 21, CVar.REPLICATED | CVar.SERVER); - - public static readonly CVarDef ViewportWidth = - CVarDef.Create("viewport.width", 21, CVar.CLIENTONLY | CVar.ARCHIVE); - - public static readonly CVarDef ViewportVerticalFit = - CVarDef.Create("viewport.vertical_fit", true, CVar.CLIENTONLY | CVar.ARCHIVE); - - /* - * UI - */ - - public static readonly CVarDef UILayout = - CVarDef.Create("ui.layout", "Default", CVar.CLIENTONLY | CVar.ARCHIVE); - - public static readonly CVarDef DefaultScreenChatSize = - CVarDef.Create("ui.default_chat_size", "", CVar.CLIENTONLY | CVar.ARCHIVE); - - public static readonly CVarDef SeparatedScreenChatSize = - CVarDef.Create("ui.separated_chat_size", "0.6,0", CVar.CLIENTONLY | CVar.ARCHIVE); - - - /* - * Accessibility - */ - - /// - /// Chat window opacity slider, controlling the alpha of the chat window background. - /// Goes from to 0 (completely transparent) to 1 (completely opaque) - /// - public static readonly CVarDef ChatWindowOpacity = - CVarDef.Create("accessibility.chat_window_transparency", 0.85f, CVar.CLIENTONLY | CVar.ARCHIVE); - - /// - /// Toggle for visual effects that may potentially cause motion sickness. - /// Where reasonable, effects affected by this CVar should use an alternate effect. - /// Please do not use this CVar as a bandaid for effects that could otherwise be made accessible without issue. - /// - public static readonly CVarDef ReducedMotion = - CVarDef.Create("accessibility.reduced_motion", false, CVar.CLIENTONLY | CVar.ARCHIVE); - - public static readonly CVarDef ChatEnableColorName = - CVarDef.Create("accessibility.enable_color_name", true, CVar.CLIENTONLY | CVar.ARCHIVE, "Toggles displaying names with individual colors."); - - /// - /// Screen shake intensity slider, controlling the intensity of the CameraRecoilSystem. - /// Goes from 0 (no recoil at all) to 1 (regular amounts of recoil) - /// - public static readonly CVarDef ScreenShakeIntensity = - CVarDef.Create("accessibility.screen_shake_intensity", 1f, CVar.CLIENTONLY | CVar.ARCHIVE); - - /// - /// A generic toggle for various visual effects that are color sensitive. - /// As of 2/16/24, only applies to progress bar colors. - /// - public static readonly CVarDef AccessibilityColorblindFriendly = - CVarDef.Create("accessibility.colorblind_friendly", false, CVar.CLIENTONLY | CVar.ARCHIVE); - - /* - * CHAT - */ - - /// - /// Chat rate limit values are accounted in periods of this size (seconds). - /// After the period has passed, the count resets. - /// - /// - public static readonly CVarDef ChatRateLimitPeriod = - CVarDef.Create("chat.rate_limit_period", 2f, CVar.SERVERONLY); - - /// - /// How many chat messages are allowed in a single rate limit period. - /// - /// - /// The total rate limit throughput per second is effectively - /// divided by . - /// - /// - public static readonly CVarDef ChatRateLimitCount = - CVarDef.Create("chat.rate_limit_count", 10, CVar.SERVERONLY); - - /// - /// Minimum delay (in seconds) between notifying admins about chat message rate limit violations. - /// A negative value disables admin announcements. - /// - public static readonly CVarDef ChatRateLimitAnnounceAdminsDelay = - CVarDef.Create("chat.rate_limit_announce_admins_delay", 15, CVar.SERVERONLY); - - public static readonly CVarDef ChatMaxMessageLength = - CVarDef.Create("chat.max_message_length", 1000, CVar.SERVER | CVar.REPLICATED); - - public static readonly CVarDef ChatMaxAnnouncementLength = - CVarDef.Create("chat.max_announcement_length", 256, CVar.SERVER | CVar.REPLICATED); - - public static readonly CVarDef ChatSanitizerEnabled = - CVarDef.Create("chat.chat_sanitizer_enabled", true, CVar.SERVERONLY); - - public static readonly CVarDef ChatShowTypingIndicator = - CVarDef.Create("chat.show_typing_indicator", true, CVar.ARCHIVE | CVar.REPLICATED | CVar.SERVER); - - public static readonly CVarDef ChatEnableFancyBubbles = - CVarDef.Create("chat.enable_fancy_bubbles", true, CVar.CLIENTONLY | CVar.ARCHIVE, "Toggles displaying fancy speech bubbles, which display the speaking character's name."); - - public static readonly CVarDef ChatFancyNameBackground = - CVarDef.Create("chat.fancy_name_background", false, CVar.CLIENTONLY | CVar.ARCHIVE, "Toggles displaying a background under the speaking character's name."); - - /// - /// A message broadcast to each player that joins the lobby. - /// May be changed by admins ingame through use of the "set-motd" command. - /// In this case the new value, if not empty, is broadcast to all connected players and saved between rounds. - /// May be requested by any player through use of the "get-motd" command. - /// - public static readonly CVarDef MOTD = - CVarDef.Create("chat.motd", "", CVar.SERVER | CVar.SERVERONLY | CVar.ARCHIVE, "A message broadcast to each player that joins the lobby."); - - /* - * AFK - */ - - /// - /// How long a client can go without any input before being considered AFK. - /// - public static readonly CVarDef AfkTime = - CVarDef.Create("afk.time", 60f, CVar.SERVERONLY); - - /* - * IC - */ - - /// - /// Restricts IC character names to alphanumeric chars. - /// - public static readonly CVarDef RestrictedNames = - CVarDef.Create("ic.restricted_names", true, CVar.SERVER | CVar.REPLICATED); - - /// - /// Allows flavor text (character descriptions) - /// - public static readonly CVarDef FlavorText = - CVarDef.Create("ic.flavor_text", false, CVar.SERVER | CVar.REPLICATED); - - /// - /// Adds a period at the end of a sentence if the sentence ends in a letter. - /// - public static readonly CVarDef ChatPunctuation = - CVarDef.Create("ic.punctuation", false, CVar.SERVER); - - /// - /// Enables automatically forcing IC name rules. Uppercases the first letter of the first and last words of the name - /// - public static readonly CVarDef ICNameCase = - CVarDef.Create("ic.name_case", true, CVar.SERVER | CVar.REPLICATED); - - /// - /// Whether or not players' characters are randomly generated rather than using their selected characters in the creator. - /// - public static readonly CVarDef ICRandomCharacters = - CVarDef.Create("ic.random_characters", false, CVar.SERVER); - - /// - /// A weighted random prototype used to determine the species selected for random characters. - /// - public static readonly CVarDef ICRandomSpeciesWeights = - CVarDef.Create("ic.random_species_weights", "SpeciesWeights", CVar.SERVER); - - /// - /// Control displaying SSD indicators near players - /// - public static readonly CVarDef ICShowSSDIndicator = - CVarDef.Create("ic.show_ssd_indicator", true, CVar.CLIENTONLY); - - /* - * Salvage - */ - - /// - /// Duration for missions - /// - public static readonly CVarDef - SalvageExpeditionDuration = CVarDef.Create("salvage.expedition_duration", 660f, CVar.REPLICATED); - - /// - /// Cooldown for missions. - /// - public static readonly CVarDef - SalvageExpeditionCooldown = CVarDef.Create("salvage.expedition_cooldown", 780f, CVar.REPLICATED); - - /* - * Flavor - */ - - /// - /// Flavor limit. This is to ensure that having a large mass of flavors in - /// some food object won't spam a user with flavors. - /// - public static readonly CVarDef - FlavorLimit = CVarDef.Create("flavor.limit", 10, CVar.SERVERONLY); - - /* - * Mapping - */ - - /// - /// Will mapping mode enable autosaves when it's activated? - /// - public static readonly CVarDef - AutosaveEnabled = CVarDef.Create("mapping.autosave", true, CVar.SERVERONLY); - - /// - /// Autosave interval in seconds. - /// - public static readonly CVarDef - AutosaveInterval = CVarDef.Create("mapping.autosave_interval", 600f, CVar.SERVERONLY); - - /// - /// Directory in server user data to save to. Saves will be inside folders in this directory. - /// - public static readonly CVarDef - AutosaveDirectory = CVarDef.Create("mapping.autosave_dir", "Autosaves", CVar.SERVERONLY); - - - /* - * Rules - */ - - /// - /// Time that players have to wait before rules can be accepted. - /// - public static readonly CVarDef RulesWaitTime = - CVarDef.Create("rules.time", 45f, CVar.SERVER | CVar.REPLICATED); - - /// - /// Don't show rules to localhost/loopback interface. - /// - public static readonly CVarDef RulesExemptLocal = - CVarDef.Create("rules.exempt_local", true, CVar.SERVERONLY); - - - /* - * Autogeneration - */ - - public static readonly CVarDef DestinationFile = - CVarDef.Create("autogen.destination_file", "", CVar.SERVER | CVar.SERVERONLY); - - /* - * Network Resource Manager - */ - - /// - /// Whether uploaded files will be stored in the server's database. - /// This is useful to keep "logs" on what files admins have uploaded in the past. - /// - public static readonly CVarDef ResourceUploadingStoreEnabled = - CVarDef.Create("netres.store_enabled", true, CVar.SERVER | CVar.SERVERONLY); - - /// - /// Numbers of days before stored uploaded files are deleted. Set to zero or negative to disable auto-delete. - /// This is useful to free some space automatically. Auto-deletion runs only on server boot. - /// - public static readonly CVarDef ResourceUploadingStoreDeletionDays = - CVarDef.Create("netres.store_deletion_days", 30, CVar.SERVER | CVar.SERVERONLY); - - /* - * Controls - */ - - /// - /// Deadzone for drag-drop interactions. - /// - public static readonly CVarDef DragDropDeadZone = - CVarDef.Create("control.drag_dead_zone", 12f, CVar.CLIENTONLY | CVar.ARCHIVE); - - /// - /// Toggles whether the walking key is a toggle or a held key. - /// - public static readonly CVarDef ToggleWalk = - CVarDef.Create("control.toggle_walk", false, CVar.CLIENTONLY | CVar.ARCHIVE); - - /* - * Interactions - */ - - // The rationale behind the default limit is simply that I can easily get to 7 interactions per second by just - // trying to spam toggle a light switch or lever (though the UseDelay component limits the actual effect of the - // interaction). I don't want to accidentally spam admins with alerts just because somebody is spamming a - // key manually, nor do we want to alert them just because the player is having network issues and the server - // receives multiple interactions at once. But we also want to try catch people with modified clients that spam - // many interactions on the same tick. Hence, a very short period, with a relatively high count. - - /// - /// Maximum number of interactions that a player can perform within seconds - /// - public static readonly CVarDef InteractionRateLimitCount = - CVarDef.Create("interaction.rate_limit_count", 5, CVar.SERVER | CVar.REPLICATED); - - /// - public static readonly CVarDef InteractionRateLimitPeriod = - CVarDef.Create("interaction.rate_limit_period", 0.5f, CVar.SERVER | CVar.REPLICATED); - - /// - /// Minimum delay (in seconds) between notifying admins about interaction rate limit violations. A negative - /// value disables admin announcements. - /// - public static readonly CVarDef InteractionRateLimitAnnounceAdminsDelay = - CVarDef.Create("interaction.rate_limit_announce_admins_delay", 120, CVar.SERVERONLY); - - /* - * STORAGE - */ - - /// - /// Whether or not the storage UI is static and bound to the hotbar, or unbound and allowed to be dragged anywhere. - /// - public static readonly CVarDef StaticStorageUI = - CVarDef.Create("control.static_storage_ui", true, CVar.CLIENTONLY | CVar.ARCHIVE); - - /// - /// Whether or not the storage window uses a transparent or opaque sprite. - /// - public static readonly CVarDef OpaqueStorageWindow = - CVarDef.Create("control.opaque_storage_background", false, CVar.CLIENTONLY | CVar.ARCHIVE); - - /* - * UPDATE - */ - - /// - /// If a server update restart is pending, the delay after the last player leaves before we actually restart. In seconds. - /// - public static readonly CVarDef UpdateRestartDelay = - CVarDef.Create("update.restart_delay", 20f, CVar.SERVERONLY); - - /* - * Ghost - */ - - /// - /// The time you must spend reading the rules, before the "Request" button is enabled - /// - public static readonly CVarDef GhostRoleTime = - CVarDef.Create("ghost.role_time", 3f, CVar.REPLICATED | CVar.SERVER); - - /// - /// If ghost role lotteries should be made near-instanteous. - /// - public static readonly CVarDef GhostQuickLottery = - CVarDef.Create("ghost.quick_lottery", false, CVar.SERVERONLY); - - /// - /// Whether or not to kill the player's mob on ghosting, when it is in a critical health state. - /// - public static readonly CVarDef GhostKillCrit = - CVarDef.Create("ghost.kill_crit", true, CVar.REPLICATED | CVar.SERVER); - - /* - * Fire alarm - */ - - /// - /// If fire alarms should have all access, or if activating/resetting these - /// should be restricted to what is dictated on a player's access card. - /// Defaults to true. - /// - public static readonly CVarDef FireAlarmAllAccess = - CVarDef.Create("firealarm.allaccess", true, CVar.SERVERONLY); - - /* - * PLAYTIME - */ - - /// - /// Time between play time autosaves, in seconds. - /// - public static readonly CVarDef - PlayTimeSaveInterval = CVarDef.Create("playtime.save_interval", 900f, CVar.SERVERONLY); - - /* - * INFOLINKS - */ - - /// - /// Link to Discord server to show in the launcher. - /// - public static readonly CVarDef InfoLinksDiscord = - CVarDef.Create("infolinks.discord", "", CVar.SERVER | CVar.REPLICATED); - - /// - /// Link to website to show in the launcher. - /// - public static readonly CVarDef InfoLinksForum = - CVarDef.Create("infolinks.forum", "", CVar.SERVER | CVar.REPLICATED); - - /// - /// Link to GitHub page to show in the launcher. - /// - public static readonly CVarDef InfoLinksGithub = - CVarDef.Create("infolinks.github", "", CVar.SERVER | CVar.REPLICATED); - - /// - /// Link to website to show in the launcher. - /// - public static readonly CVarDef InfoLinksWebsite = - CVarDef.Create("infolinks.website", "", CVar.SERVER | CVar.REPLICATED); - - /// - /// Link to wiki to show in the launcher. - /// - public static readonly CVarDef InfoLinksWiki = - CVarDef.Create("infolinks.wiki", "", CVar.SERVER | CVar.REPLICATED); - - /// - /// Link to Patreon. Not shown in the launcher currently. - /// - public static readonly CVarDef InfoLinksPatreon = - CVarDef.Create("infolinks.patreon", "", CVar.SERVER | CVar.REPLICATED); - - /// - /// Link to the bug report form. - /// - public static readonly CVarDef InfoLinksBugReport = - CVarDef.Create("infolinks.bug_report", "", CVar.SERVER | CVar.REPLICATED); - - /// - /// Link to site handling ban appeals. Shown in ban disconnect messages. - /// - public static readonly CVarDef InfoLinksAppeal = - CVarDef.Create("infolinks.appeal", "", CVar.SERVER | CVar.REPLICATED); - - /* - * CONFIG - */ - - // These are server-only for now since I don't foresee a client use yet, - // and I don't wanna have to start coming up with like .client suffixes and stuff like that. - - /// - /// Configuration presets to load during startup. - /// Multiple presets can be separated by comma and are loaded in order. - /// - /// - /// Loaded presets must be located under the ConfigPresets/ resource directory and end with the .toml extension. - /// Only the file name (without extension) must be given for this variable. - /// - public static readonly CVarDef ConfigPresets = - CVarDef.Create("config.presets", "", CVar.SERVERONLY); - - /// - /// Whether to load the preset development CVars. - /// This disables some things like lobby to make development easier. - /// Even when true, these are only loaded if the game is compiled with DEVELOPMENT set. - /// - public static readonly CVarDef ConfigPresetDevelopment = - CVarDef.Create("config.preset_development", true, CVar.SERVERONLY); - - /// - /// Whether to load the preset debug CVars. - /// Even when true, these are only loaded if the game is compiled with DEBUG set. - /// - public static readonly CVarDef ConfigPresetDebug = - CVarDef.Create("config.preset_debug", true, CVar.SERVERONLY); - - /* - * World Generation - */ - /// - /// Whether or not world generation is enabled. - /// - public static readonly CVarDef WorldgenEnabled = - CVarDef.Create("worldgen.enabled", false, CVar.SERVERONLY); - - /// - /// The worldgen config to use. - /// - public static readonly CVarDef WorldgenConfig = - CVarDef.Create("worldgen.worldgen_config", "Default", CVar.SERVERONLY); - - /// - /// The maximum amount of time the entity GC can process, in ms. - /// - public static readonly CVarDef GCMaximumTimeMs = - CVarDef.Create("entgc.maximum_time_ms", 5, CVar.SERVERONLY); - - /* - * Replays - */ - - /// - /// Whether or not to record admin chat. If replays are being publicly distributes, this should probably be - /// false. - /// - public static readonly CVarDef ReplayRecordAdminChat = - CVarDef.Create("replay.record_admin_chat", false, CVar.ARCHIVE); - - /// - /// Automatically record full rounds as replays. - /// - public static readonly CVarDef ReplayAutoRecord = - CVarDef.Create("replay.auto_record", false, CVar.SERVERONLY); - - /// - /// The file name to record automatic replays to. The path is relative to . - /// - /// - /// - /// If the path includes slashes, directories will be automatically created if necessary. - /// - /// - /// A number of substitutions can be used to automatically fill in the file name: {year}, {month}, {day}, {hour}, {minute}, {round}. - /// - /// - public static readonly CVarDef ReplayAutoRecordName = - CVarDef.Create("replay.auto_record_name", "{year}_{month}_{day}-{hour}_{minute}-round_{round}.zip", CVar.SERVERONLY); - - /// - /// Path that, if provided, automatic replays are initially recorded in. - /// When the recording is done, the file is moved into its final destination. - /// Unless this path is rooted, it will be relative to . - /// - public static readonly CVarDef ReplayAutoRecordTempDir = - CVarDef.Create("replay.auto_record_temp_dir", "", CVar.SERVERONLY); - - /* - * Miscellaneous - */ - - public static readonly CVarDef GatewayGeneratorEnabled = - CVarDef.Create("gateway.generator_enabled", true); - - // Clippy! - public static readonly CVarDef TippyEntity = - CVarDef.Create("tippy.entity", "Tippy", CVar.SERVER | CVar.REPLICATED); - - /// - /// The number of seconds that must pass for a single entity to be able to point at something again. - /// - public static readonly CVarDef PointingCooldownSeconds = - CVarDef.Create("pointing.cooldown_seconds", 0.5f, CVar.SERVERONLY); - - /* - * DEBUG - */ - - /// - /// A simple toggle to test OptionsVisualizerComponent. - /// - public static readonly CVarDef DebugOptionVisualizerTest = - CVarDef.Create("debug.option_visualizer_test", false, CVar.CLIENTONLY); - - /// - /// Set to true to disable parallel processing in the pow3r solver. - /// - public static readonly CVarDef DebugPow3rDisableParallel = - CVarDef.Create("debug.pow3r_disable_parallel", true, CVar.SERVERONLY); - } +/// +/// Contains all the CVars used by content. +/// +/// +/// NOTICE FOR FORKS: Put your own CVars in a separate file with a different [CVarDefs] attribute. RT will automatically pick up on it. +/// +[CVarDefs] +public sealed partial class CCVars : CVars +{ + // Only debug stuff lives here. + + /// + /// A simple toggle to test OptionsVisualizerComponent. + /// + public static readonly CVarDef DebugOptionVisualizerTest = + CVarDef.Create("debug.option_visualizer_test", false, CVar.CLIENTONLY); + + /// + /// Set to true to disable parallel processing in the pow3r solver. + /// + public static readonly CVarDef DebugPow3rDisableParallel = + CVarDef.Create("debug.pow3r_disable_parallel", true, CVar.SERVERONLY); } From a1966d867183f2962d17ef5415dc89b3cde54253 Mon Sep 17 00:00:00 2001 From: Ed <96445749+TheShuEd@users.noreply.github.com> Date: Tue, 12 Nov 2024 08:19:54 +0300 Subject: [PATCH 071/290] improve BiomeDunGen (#33113) * improve BiomeDunGen * forgot lol * Update DungeonJob.PostGenBiome.cs * Update DungeonJob.PostGenBiome.cs --- .../DungeonJob/DungeonJob.PostGenBiome.cs | 25 ++++++++++++------- .../Parallax/Biomes/SharedBiomeSystem.cs | 2 +- .../Procedural/PostGeneration/BiomeDunGen.cs | 7 ++++++ 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenBiome.cs b/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenBiome.cs index 65f6d2d14f95..fdadcb7849d8 100644 --- a/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenBiome.cs +++ b/Content.Server/Procedural/DungeonJob/DungeonJob.PostGenBiome.cs @@ -1,5 +1,6 @@ using System.Threading.Tasks; using Content.Server.Parallax; +using Content.Shared.Maps; using Content.Shared.Parallax.Biomes; using Content.Shared.Procedural; using Content.Shared.Procedural.PostGeneration; @@ -15,27 +16,35 @@ public sealed partial class DungeonJob /// private async Task PostGen(BiomeDunGen dunGen, DungeonData data, Dungeon dungeon, HashSet reservedTiles, Random random) { - if (_entManager.TryGetComponent(_gridUid, out BiomeComponent? biomeComp)) + if (!_prototype.TryIndex(dunGen.BiomeTemplate, out var indexedBiome)) return; - biomeComp = _entManager.AddComponent(_gridUid); var biomeSystem = _entManager.System(); - biomeSystem.SetTemplate(_gridUid, biomeComp, _prototype.Index(dunGen.BiomeTemplate)); + var seed = random.Next(); var xformQuery = _entManager.GetEntityQuery(); - foreach (var node in dungeon.RoomTiles) + var tiles = _maps.GetAllTilesEnumerator(_gridUid, _grid); + while (tiles.MoveNext(out var tileRef)) { + var node = tileRef.Value.GridIndices; + if (reservedTiles.Contains(node)) continue; + + if (dunGen.TileMask is not null) + { + if (!dunGen.TileMask.Contains(((ContentTileDefinition) _tileDefManager[tileRef.Value.Tile.TypeId]).ID)) + continue; + } // Need to set per-tile to override data. - if (biomeSystem.TryGetTile(node, biomeComp.Layers, seed, _grid, out var tile)) + if (biomeSystem.TryGetTile(node, indexedBiome.Layers, seed, _grid, out var tile)) { _maps.SetTile(_gridUid, _grid, node, tile.Value); } - if (biomeSystem.TryGetDecals(node, biomeComp.Layers, seed, _grid, out var decals)) + if (biomeSystem.TryGetDecals(node, indexedBiome.Layers, seed, _grid, out var decals)) { foreach (var decal in decals) { @@ -43,7 +52,7 @@ private async Task PostGen(BiomeDunGen dunGen, DungeonData data, Dungeon dungeon } } - if (biomeSystem.TryGetEntity(node, biomeComp, _grid, out var entityProto)) + if (tile is not null && biomeSystem.TryGetEntity(node, indexedBiome.Layers, tile.Value, seed, _grid, out var entityProto)) { var ent = _entManager.SpawnEntity(entityProto, new EntityCoordinates(_gridUid, node + _grid.TileSizeHalfVector)); var xform = xformQuery.Get(ent); @@ -61,7 +70,5 @@ private async Task PostGen(BiomeDunGen dunGen, DungeonData data, Dungeon dungeon if (!ValidateResume()) return; } - - biomeComp.Enabled = false; } } diff --git a/Content.Shared/Parallax/Biomes/SharedBiomeSystem.cs b/Content.Shared/Parallax/Biomes/SharedBiomeSystem.cs index b14baba98173..250b0f70a54e 100644 --- a/Content.Shared/Parallax/Biomes/SharedBiomeSystem.cs +++ b/Content.Shared/Parallax/Biomes/SharedBiomeSystem.cs @@ -183,7 +183,7 @@ public bool TryGetEntity(Vector2i indices, BiomeComponent component, MapGridComp } - private bool TryGetEntity(Vector2i indices, List layers, Tile tileRef, int seed, MapGridComponent grid, + public bool TryGetEntity(Vector2i indices, List layers, Tile tileRef, int seed, MapGridComponent grid, [NotNullWhen(true)] out string? entity) { var tileId = TileDefManager[tileRef.TypeId].ID; diff --git a/Content.Shared/Procedural/PostGeneration/BiomeDunGen.cs b/Content.Shared/Procedural/PostGeneration/BiomeDunGen.cs index 833cf2dec769..e21e582211b2 100644 --- a/Content.Shared/Procedural/PostGeneration/BiomeDunGen.cs +++ b/Content.Shared/Procedural/PostGeneration/BiomeDunGen.cs @@ -1,3 +1,4 @@ +using Content.Shared.Maps; using Content.Shared.Parallax.Biomes; using Robust.Shared.Prototypes; @@ -11,4 +12,10 @@ public sealed partial class BiomeDunGen : IDunGenLayer { [DataField(required: true)] public ProtoId BiomeTemplate; + + /// + /// creates a biome only on the specified tiles + /// + [DataField] + public HashSet>? TileMask; } From 70e3650246bcf0f32f5d5a78b8238dc6c486a2e5 Mon Sep 17 00:00:00 2001 From: Preston Smith <92108534+thetolbean@users.noreply.github.com> Date: Tue, 12 Nov 2024 06:06:43 -0600 Subject: [PATCH 072/290] Make Droppers Respect Closed/Sealed Containers (#33011) * Make droppers respect closed/sealed * Combine nested * Optimize conditions a bit --- Content.Server/Chemistry/EntitySystems/InjectorSystem.cs | 9 ++++++--- Content.Shared/Chemistry/Components/InjectorComponent.cs | 9 +++++++++ .../Prototypes/Entities/Objects/Specific/chemistry.yml | 1 + 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Content.Server/Chemistry/EntitySystems/InjectorSystem.cs b/Content.Server/Chemistry/EntitySystems/InjectorSystem.cs index c5c45daa5bd5..eb2039604afd 100644 --- a/Content.Server/Chemistry/EntitySystems/InjectorSystem.cs +++ b/Content.Server/Chemistry/EntitySystems/InjectorSystem.cs @@ -13,6 +13,7 @@ using Content.Shared.Interaction; using Content.Shared.Mobs.Components; using Content.Shared.Stacks; +using Content.Shared.Nutrition.EntitySystems; namespace Content.Server.Chemistry.EntitySystems; @@ -20,6 +21,7 @@ public sealed class InjectorSystem : SharedInjectorSystem { [Dependency] private readonly BloodstreamSystem _blood = default!; [Dependency] private readonly ReactiveSystem _reactiveSystem = default!; + [Dependency] private readonly OpenableSystem _openable = default!; public override void Initialize() { @@ -31,13 +33,14 @@ public override void Initialize() private bool TryUseInjector(Entity injector, EntityUid target, EntityUid user) { + var isOpenOrIgnored = injector.Comp.IgnoreClosed || !_openable.IsClosed(target); // Handle injecting/drawing for solutions if (injector.Comp.ToggleState == InjectorToggleMode.Inject) { - if (SolutionContainers.TryGetInjectableSolution(target, out var injectableSolution, out _)) + if (isOpenOrIgnored && SolutionContainers.TryGetInjectableSolution(target, out var injectableSolution, out _)) return TryInject(injector, target, injectableSolution.Value, user, false); - if (SolutionContainers.TryGetRefillableSolution(target, out var refillableSolution, out _)) + if (isOpenOrIgnored && SolutionContainers.TryGetRefillableSolution(target, out var refillableSolution, out _)) return TryInject(injector, target, refillableSolution.Value, user, true); if (TryComp(target, out var bloodstream)) @@ -58,7 +61,7 @@ private bool TryUseInjector(Entity injector, EntityUid target } // Draw from an object (food, beaker, etc) - if (SolutionContainers.TryGetDrawableSolution(target, out var drawableSolution, out _)) + if (isOpenOrIgnored && SolutionContainers.TryGetDrawableSolution(target, out var drawableSolution, out _)) return TryDraw(injector, target, drawableSolution.Value, user); Popup.PopupEntity(Loc.GetString("injector-component-cannot-draw-message", diff --git a/Content.Shared/Chemistry/Components/InjectorComponent.cs b/Content.Shared/Chemistry/Components/InjectorComponent.cs index 17a65ef1c179..ebd6654d9f5c 100644 --- a/Content.Shared/Chemistry/Components/InjectorComponent.cs +++ b/Content.Shared/Chemistry/Components/InjectorComponent.cs @@ -45,6 +45,15 @@ public sealed partial class InjectorComponent : Component [DataField] public bool IgnoreMobs; + /// + /// Whether or not the injector is able to draw from or inject into containers that are closed/sealed + /// + /// + /// for example: droppers can not inject into cans, but syringes can + /// + [DataField] + public bool IgnoreClosed = true; + /// /// The minimum amount of solution that can be transferred at once from this solution. /// diff --git a/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml b/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml index 527b0ba5e620..edaa8288145e 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/chemistry.yml @@ -283,6 +283,7 @@ - type: Injector injectOnly: false ignoreMobs: true + ignoreClosed: false minTransferAmount: 1 maxTransferAmount: 5 transferAmount: 1 From 8776c71e5972cc6daec3271b5e6528e48d796770 Mon Sep 17 00:00:00 2001 From: PJBot Date: Tue, 12 Nov 2024 12:07:50 +0000 Subject: [PATCH 073/290] Automatic changelog update --- Resources/Changelog/Changelog.yml | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 43c7cad22c67..4ab88b325b53 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,12 +1,4 @@ Entries: -- author: Cojoke-dot - changes: - - message: Borg's names are now displayed when they make an announcement on the - Communications Console. - type: Tweak - id: 7104 - time: '2024-08-13T18:31:33.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/30107 - author: Spessmann changes: - message: Added Cog, a new midpop map based on Cogmap from ss13 @@ -3949,3 +3941,10 @@ id: 7603 time: '2024-11-11T22:58:31.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/32493 +- author: thetolbean + changes: + - message: Droppers can no longer inject or draw from closed containers. + type: Fix + id: 7604 + time: '2024-11-12T12:06:43.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33011 From 8b154899b515e0d7552d283c3086c417ae00ab7c Mon Sep 17 00:00:00 2001 From: MilenVolf <63782763+MilenVolf@users.noreply.github.com> Date: Tue, 12 Nov 2024 22:11:02 +0300 Subject: [PATCH 074/290] Allow editing angle of the fired projectile (#33254) Add Angle datafield to `ProjectileComponent`. It allows to change the angle of the fired projectile --- Content.Shared/Projectiles/ProjectileComponent.cs | 6 ++++++ Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Content.Shared/Projectiles/ProjectileComponent.cs b/Content.Shared/Projectiles/ProjectileComponent.cs index c24cf2b5ee54..8349252df2b7 100644 --- a/Content.Shared/Projectiles/ProjectileComponent.cs +++ b/Content.Shared/Projectiles/ProjectileComponent.cs @@ -8,6 +8,12 @@ namespace Content.Shared.Projectiles; [RegisterComponent, NetworkedComponent, AutoGenerateComponentState] public sealed partial class ProjectileComponent : Component { + /// + /// The angle of the fired projectile. + /// + [DataField, AutoNetworkedField] + public Angle Angle; + /// /// The effect that appears when a projectile collides with an entity. /// diff --git a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs index 9bd786bbe08f..c7cc09e618bd 100644 --- a/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs +++ b/Content.Shared/Weapons/Ranged/Systems/SharedGunSystem.cs @@ -429,7 +429,7 @@ public void ShootProjectile(EntityUid uid, Vector2 direction, Vector2 gunVelocit Projectiles.SetShooter(uid, projectile, user ?? gunUid); projectile.Weapon = gunUid; - TransformSystem.SetWorldRotation(uid, direction.ToWorldAngle()); + TransformSystem.SetWorldRotation(uid, direction.ToWorldAngle() + projectile.Angle); } protected abstract void Popup(string message, EntityUid? uid, EntityUid? user); From ef51700094aa22cd1ce7f243d934dc3c45d4ff7f Mon Sep 17 00:00:00 2001 From: Repo <47093363+Titian3@users.noreply.github.com> Date: Wed, 13 Nov 2024 10:03:13 +1300 Subject: [PATCH 075/290] Fix unban/editing role bans placed in groups. (#30659) * On editing a roleban, get all the bans with the same time. * forgoten newline * Update to check for player ID too. --- Content.Server/Database/ServerDbBase.cs | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/Content.Server/Database/ServerDbBase.cs b/Content.Server/Database/ServerDbBase.cs index c85b774e3810..3806241e3459 100644 --- a/Content.Server/Database/ServerDbBase.cs +++ b/Content.Server/Database/ServerDbBase.cs @@ -512,16 +512,23 @@ public abstract Task> GetServerRoleBansAsync(IPAddress? a public async Task EditServerRoleBan(int id, string reason, NoteSeverity severity, DateTimeOffset? expiration, Guid editedBy, DateTimeOffset editedAt) { await using var db = await GetDb(); + var roleBanDetails = await db.DbContext.RoleBan + .Where(b => b.Id == id) + .Select(b => new { b.BanTime, b.PlayerUserId }) + .SingleOrDefaultAsync(); - var ban = await db.DbContext.RoleBan.SingleOrDefaultAsync(b => b.Id == id); - if (ban is null) + if (roleBanDetails == default) return; - ban.Severity = severity; - ban.Reason = reason; - ban.ExpirationTime = expiration?.UtcDateTime; - ban.LastEditedById = editedBy; - ban.LastEditedAt = editedAt.UtcDateTime; - await db.DbContext.SaveChangesAsync(); + + await db.DbContext.RoleBan + .Where(b => b.BanTime == roleBanDetails.BanTime && b.PlayerUserId == roleBanDetails.PlayerUserId) + .ExecuteUpdateAsync(setters => setters + .SetProperty(b => b.Severity, severity) + .SetProperty(b => b.Reason, reason) + .SetProperty(b => b.ExpirationTime, expiration.HasValue ? expiration.Value.UtcDateTime : (DateTime?)null) + .SetProperty(b => b.LastEditedById, editedBy) + .SetProperty(b => b.LastEditedAt, editedAt.UtcDateTime) + ); } #endregion From cc3712be0c3e0da2921cfc6c98897780e975db63 Mon Sep 17 00:00:00 2001 From: PJBot Date: Tue, 12 Nov 2024 21:04:21 +0000 Subject: [PATCH 076/290] Automatic changelog update --- Resources/Changelog/Admin.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Resources/Changelog/Admin.yml b/Resources/Changelog/Admin.yml index 56c82c23a430..680915d3821a 100644 --- a/Resources/Changelog/Admin.yml +++ b/Resources/Changelog/Admin.yml @@ -590,5 +590,12 @@ Entries: id: 73 time: '2024-11-02T13:21:10.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/32461 +- author: Repo + changes: + - message: All role bans in a set are updated on edits now. + type: Fix + id: 74 + time: '2024-11-12T21:03:13.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/30659 Name: Admin Order: 1 From af3593a3b7c2a36b0e0c4a19cc846e96f139fb58 Mon Sep 17 00:00:00 2001 From: SpaceRox1244 <138547931+SpaceRox1244@users.noreply.github.com> Date: Tue, 12 Nov 2024 18:45:59 -0500 Subject: [PATCH 077/290] Adds new sprites for shotgun shell boxes (#33176) * Adds new sprites for shotgun shell boxes * Adds second set of mag visuals for slug and uranium casings * Fixes yaml that I messed up * Changes credit to new username before merging happens --- .../Weapons/Guns/Ammunition/Boxes/shotgun.yml | 95 ++++++++++++------ .../Ammunition/Boxes/shotgun.rsi/base.png | Bin 0 -> 356 bytes .../Ammunition/Boxes/shotgun.rsi/beanbag.png | Bin 0 -> 268 bytes .../Ammunition/Boxes/shotgun.rsi/flare.png | Bin 0 -> 229 bytes .../Boxes/shotgun.rsi/incendiary.png | Bin 0 -> 233 bytes .../Ammunition/Boxes/shotgun.rsi/lethal.png | Bin 0 -> 263 bytes .../Ammunition/Boxes/shotgun.rsi/mag-1.png | Bin 0 -> 107 bytes .../Ammunition/Boxes/shotgun.rsi/mag-2.png | Bin 0 -> 134 bytes .../Ammunition/Boxes/shotgun.rsi/mag-3.png | Bin 0 -> 142 bytes .../Ammunition/Boxes/shotgun.rsi/mag-4.png | Bin 0 -> 155 bytes .../Boxes/shotgun.rsi/mag-alt-1.png | Bin 0 -> 106 bytes .../Boxes/shotgun.rsi/mag-alt-2.png | Bin 0 -> 127 bytes .../Boxes/shotgun.rsi/mag-alt-3.png | Bin 0 -> 135 bytes .../Boxes/shotgun.rsi/mag-alt-4.png | Bin 0 -> 151 bytes .../Ammunition/Boxes/shotgun.rsi/meta.json | 62 ++++++++++++ .../Ammunition/Boxes/shotgun.rsi/practice.png | Bin 0 -> 221 bytes .../Ammunition/Boxes/shotgun.rsi/slug.png | Bin 0 -> 257 bytes .../Boxes/shotgun.rsi/tranquilizer.png | Bin 0 -> 292 bytes .../Ammunition/Boxes/shotgun.rsi/uranium.png | Bin 0 -> 249 bytes 19 files changed, 125 insertions(+), 32 deletions(-) create mode 100644 Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/base.png create mode 100644 Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/beanbag.png create mode 100644 Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/flare.png create mode 100644 Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/incendiary.png create mode 100644 Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/lethal.png create mode 100644 Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/mag-1.png create mode 100644 Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/mag-2.png create mode 100644 Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/mag-3.png create mode 100644 Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/mag-4.png create mode 100644 Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/mag-alt-1.png create mode 100644 Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/mag-alt-2.png create mode 100644 Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/mag-alt-3.png create mode 100644 Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/mag-alt-4.png create mode 100644 Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/meta.json create mode 100644 Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/practice.png create mode 100644 Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/slug.png create mode 100644 Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/tranquilizer.png create mode 100644 Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/uranium.png diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.yml index 063937aee9a9..e5c2987ec3e5 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.yml @@ -16,114 +16,145 @@ id: AmmoProviderShotgunShell abstract: true components: + - type: Sprite + sprite: Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi - type: BallisticAmmoProvider mayTransfer: true whitelist: tags: - ShellShotgun capacity: 16 + - type: MagazineVisuals + magState: mag + steps: 5 + zeroVisible: false + - type: Appearance # Shotgun Shells - type: entity - name: shotgun beanbag cartridges dispenser parent: AmmoProviderShotgunShell id: BoxBeanbag - description: A dispenser box full of beanbag shots, designed for riot shotguns. + name: shell box (beanbag) components: - type: BallisticAmmoProvider proto: ShellShotgunBeanbag - type: Sprite layers: - - state: boxwide - - state: shellbeanbag + - state: base + map: ["enum.GunVisualLayers.Base"] + - state: mag-1 + map: ["enum.GunVisualLayers.Mag"] + - state: beanbag - type: entity - name: shotgun lethal cartridges dispenser + name: shell box (lethal) parent: AmmoProviderShotgunShell id: BoxLethalshot - description: A dispenser box full of lethal pellet shots, designed for riot shotguns. components: - type: BallisticAmmoProvider proto: ShellShotgun - type: Sprite layers: - - state: boxwide - - state: shelllethal + - state: base + map: ["enum.GunVisualLayers.Base"] + - state: mag-1 + map: ["enum.GunVisualLayers.Mag"] + - state: lethal - type: entity - name: shotgun slug cartridges dispenser + name: shell box (slug) parent: AmmoProviderShotgunShell id: BoxShotgunSlug - description: A dispenser box full of slugs, designed for riot shotguns. components: - type: BallisticAmmoProvider proto: ShellShotgunSlug + - type: MagazineVisuals + magState: mag-alt + steps: 5 + zeroVisible: false - type: Sprite layers: - - state: boxwide - - state: shellslug + - state: base + map: ["enum.GunVisualLayers.Base"] + - state: mag-alt-1 + map: ["enum.GunVisualLayers.Mag"] + - state: slug - type: entity - name: shotgun flare cartridges dispenser + name: shell box (flare) parent: AmmoProviderShotgunShell id: BoxShotgunFlare - description: A dispenser box full of flare cartridges, designed for riot shotguns. components: - type: BallisticAmmoProvider proto: ShellShotgunFlare - type: Sprite layers: - - state: boxwide - - state: shellflare + - state: base + map: ["enum.GunVisualLayers.Base"] + - state: mag-1 + map: ["enum.GunVisualLayers.Mag"] + - state: flare - type: entity - name: shotgun incendiary cartridges dispenser + name: shell box (incendiary) parent: AmmoProviderShotgunShell id: BoxShotgunIncendiary - description: A dispenser box full of incendiary cartridges, designed for riot shotguns. components: - type: BallisticAmmoProvider proto: ShellShotgunIncendiary - type: Sprite layers: - - state: boxwide - - state: shellincendiary + - state: base + map: ["enum.GunVisualLayers.Base"] + - state: mag-1 + map: ["enum.GunVisualLayers.Mag"] + - state: incendiary - type: entity - name: shotgun uranium cartridges dispenser + name: shell box (uranium) parent: AmmoProviderShotgunShell id: BoxShotgunUranium - description: A dispenser box full of uranium cartridges, designed for riot shotguns. components: - type: BallisticAmmoProvider proto: ShellShotgunUranium + - type: MagazineVisuals + magState: mag-alt + steps: 5 + zeroVisible: false - type: Sprite layers: - - state: boxwide - - state: shelluranium + - state: base + map: ["enum.GunVisualLayers.Base"] + - state: mag-alt-1 + map: ["enum.GunVisualLayers.Mag"] + - state: uranium - type: entity - name: shotgun practice cartridges dispenser + name: shell box (practice) parent: AmmoProviderShotgunShell id: BoxShotgunPractice - description: A dispenser box full of practice cartridges, designed for riot shotguns. components: - type: BallisticAmmoProvider proto: ShellShotgunPractice - type: Sprite layers: - - state: boxwide - - state: shellpractice + - state: base + map: ["enum.GunVisualLayers.Base"] + - state: mag-1 + map: ["enum.GunVisualLayers.Mag"] + - state: practice - type: entity - name: tranquilizer cartridges dispenser + name: shell box (tranquilizer) parent: AmmoProviderShotgunShell id: BoxShellTranquilizer - description: A dispenser box full of tranquilizer cartridges, designed for riot shotguns. components: - type: BallisticAmmoProvider proto: ShellTranquilizer - type: Sprite layers: - - state: boxwide - - state: shelltranquilizer + - state: base + map: ["enum.GunVisualLayers.Base"] + - state: mag-1 + map: ["enum.GunVisualLayers.Mag"] + - state: tranquilizer diff --git a/Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/base.png b/Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/base.png new file mode 100644 index 0000000000000000000000000000000000000000..f460615079dcbc3bc4f0244f62ee6d194767a522 GIT binary patch literal 356 zcmV-q0h|7bP)hx<)!^4}S=qr;oC$=T7E*eH6r?v$|0={nqU@&~G zWz|}{fhhEq1nVMsSP_UqUv)bz&d)sKwUt`%^cX1MAXuK4tN8B(^k4}~6PYbGxqD>} zM;g-SWbkaUq1$PtzJE-92}Lh^*k;OTtF%jo^+{zgOC^y)Od`q8?g;b1re z>v#*m&GjV!&!bNO?(f<_@xd!Cpo=^Nx2)rBsbHbfcc5yxk-&7ms}z();THT1m4e@% z>%5JZ$y&Pt+QtVWWrD5H4|=K}^o;)h4u`|>@7M#Kfp=<`U7Q{O0000}H>5)pw;==K7x8V+~bjYGKg9f2R2p+y&jDE6VgRn&_y0wAB0m6NxliC=S9@r!`VoAb<|1Kiva}4|oD-LF z?gCXJm%+1EaDnv^K-uc?to)Xx<@j;W2bS%37N`=*(t5#-pfslO_bv#6&^9l%CPK^P)v*1c-(z8(jS<5Z9eZF44L1lhRrKFOqG*ah#5% z2#N@;Js=`X5%wY}!d~Q`z+o>D7cjwe03Y|x;WfXh39p&~GEh}ln{V0sO+%=vB*PNa za&VfqfDFx-&U_7v1NpNyjt^qe&6+mp|tO@wD2bZya0gHIOC*Y2?pwdyO1K- fecv6&arWi|ytPQ)duV{k00000NkvXXu0mjfSx8_g literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/incendiary.png b/Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/incendiary.png new file mode 100644 index 0000000000000000000000000000000000000000..7841707b120f3e1f4577f6c4320b31e2cac551b4 GIT binary patch literal 233 zcmV4nT^wv_^1KwK30C|xZATRPuU@@173Wy*&fag=?@RZ-AgeT1aY1lb8`FKw6vxcy9 zj->epl`Nd17LcZR(}~w`_3y>)9!(5AZ?7fRZ997BaetqOBbw?09|_ujP)GfE;=68&th|NUdT zGHuJ$w6IPqu7@=MWztMI=j`cVEeWvLo!komERzeshe$!t2G?oT6o%$KtpvJ6{LAwl z+yl?1SYP#qd%IT!~_O8cNpWzqlu N002ovPDHLkV1hD0ZubBH literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/mag-1.png b/Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/mag-1.png new file mode 100644 index 0000000000000000000000000000000000000000..d77e6507b00fc0910aba7e959d2561f9e0b122e9 GIT binary patch literal 107 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzBTpB{kcif|=L~rn6a-id%6t;v ziHj^`S8it)6S}08kwaP0uAd0TO=D~gJvs9|53PjNBTiZBohMzr{0#T4{i(q!PC{xWt~$(69DIjFhu|W literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/mag-4.png b/Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/mag-4.png new file mode 100644 index 0000000000000000000000000000000000000000..9a3c99707fe47b7133a9a2c0937a993983074206 GIT binary patch literal 155 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJBu^K|kcif|7Z>t27>KxD3_ly> zF)cxeWz{lfL6vz4k_)UC$Tv+$$YfRAncna_{*x*L!@n~dHzq%x<)&e)Yi zOU%kYt$01~*8O!%3}Tb+sC++u?WT)y@ZGy^xL(e jS6z<0vSeWR(aX)dQ?BLIq?BnulNmf+{an^LB{Ts519mUd literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/mag-alt-4.png b/Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/mag-alt-4.png new file mode 100644 index 0000000000000000000000000000000000000000..60be778fdfd459489e53186dddd46287574d4860 GIT binary patch literal 151 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJI8PVHkcif|7Y%t281T4Uynl&9 zZZoIMXM=_h9U=_JCg$Cp?Xgzt?(ICwXe$9h!Jo$E^WWK(TlHN%%#h~xe(o8T1=oJ< zcpp=F;Ecx73sK6(@Bi#FJl4~(mea+>#lZ&O)=-MRXEfi^LCy85}Sb4q9e0Ns>1 Ah5!Hn literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/meta.json new file mode 100644 index 000000000000..3df588a845e5 --- /dev/null +++ b/Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/meta.json @@ -0,0 +1,62 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Sprites by SpaceRox1244", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "base" + }, + { + "name": "mag-1" + }, + { + "name": "mag-2" + }, + { + "name": "mag-3" + }, + { + "name": "mag-4" + }, + { + "name": "mag-alt-1" + }, + { + "name": "mag-alt-2" + }, + { + "name": "mag-alt-3" + }, + { + "name": "mag-alt-4" + }, + { + "name": "lethal" + }, + { + "name": "beanbag" + }, + { + "name": "slug" + }, + { + "name": "incendiary" + }, + { + "name": "practice" + }, + { + "name": "uranium" + }, + { + "name": "flare" + }, + { + "name": "tranquilizer" + } + ] +} diff --git a/Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/practice.png b/Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/practice.png new file mode 100644 index 0000000000000000000000000000000000000000..4ece8a0c1e58a1bca6482dca0ecd2fc9a52a1863 GIT binary patch literal 221 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJC7v#hArY-_CvW6sR^)N@oua3_ zq$6gdTUdh4vJYnJwX1k0{#)+k)m$V{67w)T`XB!j{YMt(To?>i7i~Sh(}iJ;=ug!G zORpoW(>8ozIGdAKaX!21(C)kky8M%J^yFXu-J1R*`pL2BEdoxwayN~20u)aMowC=y zcD>*`{}Bo2u&0|vcABSc%M})!I3;L?;&qkPLJXcl3}<^TXK!zps;k)W*y5azo#3i? VpBJTKr-ANe@O1TaS?83{1OOy{RxJPk literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/slug.png b/Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/slug.png new file mode 100644 index 0000000000000000000000000000000000000000..b55085e398ea1f2ecb6f5477a62a21d1728a009b GIT binary patch literal 257 zcmV+c0sj7pP)~|XgfOGES>`4NFvZ`?!hFfvq zCjvnN0PaP+_s_*qxr-P9=UfPW5Sdb(gzH4|f4hPp2;Xo9cZ^oa(r~ID00000NkvXX Hu0mjfHM(oI literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/tranquilizer.png b/Resources/Textures/Objects/Weapons/Guns/Ammunition/Boxes/shotgun.rsi/tranquilizer.png new file mode 100644 index 0000000000000000000000000000000000000000..373d6a2a0c91a69c140798bcf956464736eb65bd GIT binary patch literal 292 zcmV+<0o(qGP)3F6RKzUc&7bmQfCZG!zg>vnzuPY5Y3> zXudc8flMZokV-_?b*)o-P>E&iL( z-tGP@KKy%QOuTID#$(&^Wi0?J=MFi@A#6oc1By zf{$%`neV#jnhyz#MF5Pol-}QipCDS`ce5!F(Q(~xR0-$pZ5DAwr=#sF~gnD q=5zWGo(fJvC896+a+ypf^G?q6I%Uv_PY+B00000IJ-kcM(tGQCxciFQAiV6_?(?B`%GKR!Ksz2=AK$dGGyS z!UI7N5>nNLt?I(|?I9v>65s9zzY-CFUg&iJr`vJb@Q~MpglE2mT5CJm4FT9Mj-7o@ zvRU1{XXm~G0Qq_Z!16G+&mu0k+{^%IF#a<`1iD1dm(wFSYF2b-D^gzL!-E8jF&SV1 zlv1B++|hftf_|Wt;8i3hI0;&7>tqB$5dM}stTH=wmQOP{00000NkvXXu0mjfYxrZ$ literal 0 HcmV?d00001 From e9f6a02f18959577f8f56c6ba511749cb34d0ce0 Mon Sep 17 00:00:00 2001 From: cohanna Date: Tue, 12 Nov 2024 19:05:56 -0700 Subject: [PATCH 078/290] un-reverted fixes --- .../Entities/Structures/Windows/clockwork.yml | 19 ++++++--- .../Entities/Structures/Windows/mining.yml | 6 +-- .../Entities/Structures/Windows/plasma.yml | 29 ++++++++------ .../Structures/Windows/plastitanium.yml | 10 ++--- .../Structures/Windows/reinforced.yml | 37 +++++------------- .../Entities/Structures/Windows/rplasma.yml | 18 ++++----- .../Entities/Structures/Windows/ruranium.yml | 20 ++++++---- .../Entities/Structures/Windows/shuttle.yml | 6 +-- .../Entities/Structures/Windows/uranium.yml | 28 +++++++------ .../Entities/Structures/Windows/window.yml | 32 ++++++++++++--- ...mageOverlay_8.png => DamageOverlay_10.png} | Bin ...ageOverlay_12.png => DamageOverlay_20.png} | Bin ...amageOverlay_4.png => DamageOverlay_5.png} | Bin .../Structures/Windows/cracks.rsi/meta.json | 6 +-- ...mageOverlay_8.png => DamageOverlay_10.png} | Bin ...ageOverlay_12.png => DamageOverlay_20.png} | Bin ...amageOverlay_4.png => DamageOverlay_5.png} | Bin .../Windows/cracks_diagonal.rsi/meta.json | 6 +-- ...mageOverlay_8.png => DamageOverlay_10.png} | Bin ...ageOverlay_12.png => DamageOverlay_20.png} | Bin ...amageOverlay_4.png => DamageOverlay_5.png} | Bin .../Windows/cracks_directional.rsi/meta.json | 6 +-- 22 files changed, 123 insertions(+), 100 deletions(-) rename Resources/Textures/Structures/Windows/cracks.rsi/{DamageOverlay_8.png => DamageOverlay_10.png} (100%) rename Resources/Textures/Structures/Windows/cracks.rsi/{DamageOverlay_12.png => DamageOverlay_20.png} (100%) rename Resources/Textures/Structures/Windows/cracks.rsi/{DamageOverlay_4.png => DamageOverlay_5.png} (100%) rename Resources/Textures/Structures/Windows/cracks_diagonal.rsi/{DamageOverlay_8.png => DamageOverlay_10.png} (100%) rename Resources/Textures/Structures/Windows/cracks_diagonal.rsi/{DamageOverlay_12.png => DamageOverlay_20.png} (100%) rename Resources/Textures/Structures/Windows/cracks_diagonal.rsi/{DamageOverlay_4.png => DamageOverlay_5.png} (100%) rename Resources/Textures/Structures/Windows/cracks_directional.rsi/{DamageOverlay_8.png => DamageOverlay_10.png} (100%) rename Resources/Textures/Structures/Windows/cracks_directional.rsi/{DamageOverlay_12.png => DamageOverlay_20.png} (100%) rename Resources/Textures/Structures/Windows/cracks_directional.rsi/{DamageOverlay_4.png => DamageOverlay_5.png} (100%) diff --git a/Resources/Prototypes/Entities/Structures/Windows/clockwork.yml b/Resources/Prototypes/Entities/Structures/Windows/clockwork.yml index 6abeae5760b1..8421b6b4dc67 100644 --- a/Resources/Prototypes/Entities/Structures/Windows/clockwork.yml +++ b/Resources/Prototypes/Entities/Structures/Windows/clockwork.yml @@ -47,8 +47,8 @@ node: clockworkWindow - type: Appearance - type: DamageVisuals - thresholds: [4, 8, 12] - damageDivisor: 4 + thresholds: [5, 10, 20] + damageDivisor: 3 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks.rsi @@ -74,8 +74,8 @@ node: windowClockworkDirectional - type: Appearance - type: DamageVisuals - thresholds: [4, 8, 12] - damageDivisor: 10 + thresholds: [5, 10, 20] + damageDivisor: 1.5 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks_directional.rsi @@ -85,7 +85,16 @@ thresholds: - trigger: !type:DamageTrigger - damage: 150 + damage: 75 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - !type:PlaySoundBehavior + sound: + collection: WindowShatter + - trigger: + !type:DamageTrigger + damage: 37 behaviors: - !type:PlaySoundBehavior sound: diff --git a/Resources/Prototypes/Entities/Structures/Windows/mining.yml b/Resources/Prototypes/Entities/Structures/Windows/mining.yml index 82d11b732b65..9d05fbb5e236 100644 --- a/Resources/Prototypes/Entities/Structures/Windows/mining.yml +++ b/Resources/Prototypes/Entities/Structures/Windows/mining.yml @@ -43,8 +43,8 @@ base: mwindow - type: Appearance - type: DamageVisuals - thresholds: [4, 8, 12] - damageDivisor: 6 + thresholds: [5, 10, 20] + damageDivisor: 4 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks.rsi @@ -91,4 +91,4 @@ - East - type: DamageVisuals damageOverlay: - sprite: Structures/Windows/cracks_diagonal.rsi + sprite: Structures/Windows/cracks_diagonal.rsi \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Structures/Windows/plasma.yml b/Resources/Prototypes/Entities/Structures/Windows/plasma.yml index 66fac515a770..bdeb37c6bb7e 100644 --- a/Resources/Prototypes/Entities/Structures/Windows/plasma.yml +++ b/Resources/Prototypes/Entities/Structures/Windows/plasma.yml @@ -10,12 +10,12 @@ sprite: Structures/Windows/plasma_window.rsi - type: Damageable damageContainer: StructuralInorganic - damageModifierSet: RGlass + damageModifierSet: Glass - type: Destructible thresholds: - trigger: !type:DamageTrigger - damage: 120 + damage: 150 behaviors: - !type:DoActsBehavior acts: [ "Destruction" ] @@ -24,7 +24,7 @@ collection: WindowShatter - trigger: !type:DamageTrigger - damage: 60 + damage: 75 behaviors: - !type:PlaySoundBehavior sound: @@ -43,8 +43,8 @@ node: plasmaWindow - type: Appearance - type: DamageVisuals - thresholds: [4, 8, 12] - damageDivisor: 3.333 + thresholds: [5, 10, 20] + damageDivisor: 3 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks.rsi @@ -74,8 +74,8 @@ node: plasmaWindowDirectional - type: Appearance - type: DamageVisuals - thresholds: [4, 8, 12] - damageDivisor: 3.333 + thresholds: [5, 10, 20] + damageDivisor: 1.5 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks_directional.rsi @@ -83,7 +83,16 @@ thresholds: - trigger: !type:DamageTrigger - damage: 200 + damage: 75 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - !type:PlaySoundBehavior + sound: + collection: WindowShatter + - trigger: + !type:DamageTrigger + damage: 37 behaviors: - !type:PlaySoundBehavior sound: @@ -97,8 +106,6 @@ acts: [ "Destruction" ] - type: StaticPrice price: 50 - - type: RadiationBlocker - resistance: 1 - type: entity parent: PlasmaWindow @@ -143,4 +150,4 @@ sprite: Structures/Windows/cracks_diagonal.rsi - type: Construction graph: WindowDiagonal - node: plasmaWindowDiagonal + node: plasmaWindowDiagonal \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Structures/Windows/plastitanium.yml b/Resources/Prototypes/Entities/Structures/Windows/plastitanium.yml index 2134cfe89276..c50bc6e030b0 100644 --- a/Resources/Prototypes/Entities/Structures/Windows/plastitanium.yml +++ b/Resources/Prototypes/Entities/Structures/Windows/plastitanium.yml @@ -98,8 +98,8 @@ - !type:DoActsBehavior acts: [ "Destruction" ] - type: DamageVisuals - thresholds: [4, 8, 12] - damageDivisor: 28 + thresholds: [5, 10, 20] + damageDivisor: 20 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks.rsi @@ -185,8 +185,8 @@ - !type:DoActsBehavior acts: [ "Destruction" ] - type: DamageVisuals - thresholds: [4, 8, 12] - damageDivisor: 28 + thresholds: [5, 10, 20] + damageDivisor: 20 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks_diagonal.rsi @@ -195,4 +195,4 @@ doAfterDelay: 3 - type: Damageable damageContainer: StructuralInorganic - damageModifierSet: RGlass + damageModifierSet: RGlass \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Structures/Windows/reinforced.yml b/Resources/Prototypes/Entities/Structures/Windows/reinforced.yml index 503d2eec6e3b..238b71e3fde0 100644 --- a/Resources/Prototypes/Entities/Structures/Windows/reinforced.yml +++ b/Resources/Prototypes/Entities/Structures/Windows/reinforced.yml @@ -50,31 +50,12 @@ node: reinforcedWindow - type: Appearance - type: DamageVisuals - thresholds: [4, 8, 12] - damageDivisor: 4 + thresholds: [5, 10, 20] + damageDivisor: 3 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks.rsi -- type: entity - parent: ReinforcedWindow - id: TintedWindow - name: tinted window - components: - - type: Sprite - drawdepth: WallTops - sprite: Structures/Windows/tinted_window.rsi - - type: Icon - sprite: Structures/Windows/tinted_window.rsi - - type: IconSmooth - base: twindow - - type: Construction - graph: Window - node: tintedWindow - - type: Occluder - - type: StaticPrice - price: 45 - - type: entity id: WindowReinforcedDirectional parent: WindowDirectional @@ -96,8 +77,8 @@ node: windowReinforcedDirectional - type: Appearance - type: DamageVisuals - thresholds: [4, 8, 12] - damageDivisor: 10 + thresholds: [5, 10, 20] + damageDivisor: 1.5 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks_directional.rsi @@ -111,16 +92,16 @@ thresholds: - trigger: !type:DamageTrigger - damage: 150 #excess damage (nuke?). avoid computational cost of spawning entities. + damage: 75 behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] - !type:PlaySoundBehavior sound: collection: WindowShatter - - !type:DoActsBehavior - acts: [ "Destruction" ] - trigger: !type:DamageTrigger - damage: 50 + damage: 37 behaviors: - !type:PlaySoundBehavior sound: @@ -178,4 +159,4 @@ sprite: Structures/Windows/cracks_diagonal.rsi - type: Construction graph: WindowDiagonal - node: reinforcedWindowDiagonal + node: reinforcedWindowDiagonal \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Structures/Windows/rplasma.yml b/Resources/Prototypes/Entities/Structures/Windows/rplasma.yml index 0940ac308a52..2ea710e6e774 100644 --- a/Resources/Prototypes/Entities/Structures/Windows/rplasma.yml +++ b/Resources/Prototypes/Entities/Structures/Windows/rplasma.yml @@ -17,7 +17,7 @@ thresholds: - trigger: !type:DamageTrigger - damage: 200 + damage: 300 behaviors: #excess damage, don't spawn entities. - !type:DoActsBehavior acts: [ "Destruction" ] @@ -26,7 +26,7 @@ collection: WindowShatter - trigger: !type:DamageTrigger - damage: 100 + damage: 150 behaviors: - !type:PlaySoundBehavior sound: @@ -48,7 +48,7 @@ node: reinforcedPlasmaWindow - type: Appearance - type: DamageVisuals - thresholds: [4, 8, 12] + thresholds: [5, 10, 20] damageDivisor: 6 trackAllDamage: true damageOverlay: @@ -77,24 +77,22 @@ node: plasmaReinforcedWindowDirectional - type: Appearance - type: DamageVisuals - thresholds: [4, 8, 12] - damageDivisor: 36 + thresholds: [5, 10, 20] + damageDivisor: 3 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks_directional.rsi - - type: RadiationBlocker - resistance: 2 - type: Destructible thresholds: - trigger: !type:DamageTrigger - damage: 1000 + damage: 150 behaviors: #excess damage, don't spawn entities. - !type:DoActsBehavior acts: [ "Destruction" ] - trigger: !type:DamageTrigger - damage: 600 + damage: 75 behaviors: - !type:PlaySoundBehavior sound: @@ -155,4 +153,4 @@ sprite: Structures/Windows/cracks_diagonal.rsi - type: Construction graph: WindowDiagonal - node: reinforcedPlasmaWindowDiagonal + node: reinforcedPlasmaWindowDiagonal \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Structures/Windows/ruranium.yml b/Resources/Prototypes/Entities/Structures/Windows/ruranium.yml index b9b47c00ea9d..fe40b21ba26a 100644 --- a/Resources/Prototypes/Entities/Structures/Windows/ruranium.yml +++ b/Resources/Prototypes/Entities/Structures/Windows/ruranium.yml @@ -43,7 +43,7 @@ node: reinforcedUraniumWindow - type: Appearance - type: DamageVisuals - thresholds: [4, 8, 12] + thresholds: [5, 10, 20] damageDivisor: 6 trackAllDamage: true damageOverlay: @@ -74,8 +74,8 @@ node: uraniumReinforcedWindowDirectional - type: Appearance - type: DamageVisuals - thresholds: [4, 8, 12] - damageDivisor: 3.333 + thresholds: [5, 10, 20] + damageDivisor: 3 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks_directional.rsi @@ -83,7 +83,13 @@ thresholds: - trigger: !type:DamageTrigger - damage: 200 + damage: 150 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - trigger: + !type:DamageTrigger + damage: 75 behaviors: - !type:PlaySoundBehavior sound: @@ -93,15 +99,13 @@ ShardGlassUranium: min: 1 max: 2 - PartRodMetal1: + PartRodMetal: min: 1 max: 2 - !type:DoActsBehavior acts: [ "Destruction" ] - type: StaticPrice price: 110 - - type: RadiationBlocker - resistance: 2.5 - type: entity parent: ReinforcedUraniumWindow @@ -146,4 +150,4 @@ sprite: Structures/Windows/cracks_diagonal.rsi - type: Construction graph: WindowDiagonal - node: reinforcedUraniumWindowDiagonal + node: reinforcedUraniumWindowDiagonal \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Structures/Windows/shuttle.yml b/Resources/Prototypes/Entities/Structures/Windows/shuttle.yml index 1b4c96c1709a..f70b684abd26 100644 --- a/Resources/Prototypes/Entities/Structures/Windows/shuttle.yml +++ b/Resources/Prototypes/Entities/Structures/Windows/shuttle.yml @@ -46,8 +46,8 @@ node: shuttleWindow - type: Appearance - type: DamageVisuals - thresholds: [4, 8, 12] - damageDivisor: 28 + thresholds: [5, 10, 20] + damageDivisor: 20 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks.rsi @@ -94,4 +94,4 @@ - East - type: DamageVisuals damageOverlay: - sprite: Structures/Windows/cracks_diagonal.rsi + sprite: Structures/Windows/cracks_diagonal.rsi \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Structures/Windows/uranium.yml b/Resources/Prototypes/Entities/Structures/Windows/uranium.yml index c7b7312a7094..25ad1b876ed0 100644 --- a/Resources/Prototypes/Entities/Structures/Windows/uranium.yml +++ b/Resources/Prototypes/Entities/Structures/Windows/uranium.yml @@ -11,18 +11,18 @@ state: full - type: Damageable damageContainer: StructuralInorganic - damageModifierSet: RGlass + damageModifierSet: Glass - type: Destructible thresholds: - trigger: !type:DamageTrigger - damage: 100 + damage: 150 behaviors: - !type:DoActsBehavior acts: [ "Destruction" ] - trigger: !type:DamageTrigger - damage: 60 + damage: 75 behaviors: - !type:PlaySoundBehavior sound: @@ -41,8 +41,8 @@ node: uraniumWindow - type: Appearance - type: DamageVisuals - thresholds: [4, 8, 12] - damageDivisor: 3.333 + thresholds: [5, 10, 20] + damageDivisor: 3 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks.rsi @@ -72,8 +72,8 @@ node: uraniumWindowDirectional - type: Appearance - type: DamageVisuals - thresholds: [4, 8, 12] - damageDivisor: 3.333 + thresholds: [5, 10, 20] + damageDivisor: 1.5 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks_directional.rsi @@ -81,7 +81,13 @@ thresholds: - trigger: !type:DamageTrigger - damage: 200 + damage: 75 + behaviors: + - !type:DoActsBehavior + acts: [ "Destruction" ] + - trigger: + !type:DamageTrigger + damage: 37 behaviors: - !type:PlaySoundBehavior sound: @@ -90,13 +96,11 @@ spawn: ShardGlassUranium: min: 1 - max: 2 + max: 1 - !type:DoActsBehavior acts: [ "Destruction" ] - type: StaticPrice price: 100 - - type: RadiationBlocker - resistance: 1.5 - type: entity parent: UraniumWindow @@ -141,4 +145,4 @@ sprite: Structures/Windows/cracks_diagonal.rsi - type: Construction graph: WindowDiagonal - node: uraniumWindowDiagonal + node: uraniumWindowDiagonal \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Structures/Windows/window.yml b/Resources/Prototypes/Entities/Structures/Windows/window.yml index 56a38f82fcfe..5b6530a9e5d2 100644 --- a/Resources/Prototypes/Entities/Structures/Windows/window.yml +++ b/Resources/Prototypes/Entities/Structures/Windows/window.yml @@ -84,8 +84,8 @@ node: window - type: Appearance - type: DamageVisuals - thresholds: [4, 8, 12] - damageDivisor: 3.333 + thresholds: [5, 10, 20] + damageDivisor: 2 trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks.rsi @@ -93,6 +93,25 @@ price: 100 - type: BlockWeather +- type: entity + parent: Window + id: TintedWindow + name: tinted window + components: + - type: Sprite + drawdepth: WallTops + sprite: Structures/Windows/tinted_window.rsi + - type: Icon + sprite: Structures/Windows/tinted_window.rsi + - type: IconSmooth + base: twindow + - type: Construction + graph: Window + node: tintedWindow + - type: Occluder + - type: StaticPrice + price: 70 + - type: entity id: WindowRCDResistant parent: Window @@ -158,7 +177,7 @@ thresholds: - trigger: !type:DamageTrigger - damage: 150 #excess damage (nuke?). avoid computational cost of spawning entities. + damage: 50 #excess damage (nuke?). avoid computational cost of spawning entities. behaviors: - !type:DoActsBehavior acts: [ "Destruction" ] @@ -188,8 +207,7 @@ node: windowDirectional - type: Appearance - type: DamageVisuals - thresholds: [4, 8, 12] - damageDivisor: 3.333 + thresholds: [5, 10, 20] trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks_directional.rsi @@ -220,6 +238,8 @@ - type: Icon sprite: Structures/Windows/directional.rsi state: frosted_window + - type: StaticPrice + price: 35 - type: entity parent: Window @@ -264,4 +284,4 @@ sprite: Structures/Windows/cracks_diagonal.rsi - type: Construction graph: WindowDiagonal - node: windowDiagonal + node: windowDiagonal \ No newline at end of file diff --git a/Resources/Textures/Structures/Windows/cracks.rsi/DamageOverlay_8.png b/Resources/Textures/Structures/Windows/cracks.rsi/DamageOverlay_10.png similarity index 100% rename from Resources/Textures/Structures/Windows/cracks.rsi/DamageOverlay_8.png rename to Resources/Textures/Structures/Windows/cracks.rsi/DamageOverlay_10.png diff --git a/Resources/Textures/Structures/Windows/cracks.rsi/DamageOverlay_12.png b/Resources/Textures/Structures/Windows/cracks.rsi/DamageOverlay_20.png similarity index 100% rename from Resources/Textures/Structures/Windows/cracks.rsi/DamageOverlay_12.png rename to Resources/Textures/Structures/Windows/cracks.rsi/DamageOverlay_20.png diff --git a/Resources/Textures/Structures/Windows/cracks.rsi/DamageOverlay_4.png b/Resources/Textures/Structures/Windows/cracks.rsi/DamageOverlay_5.png similarity index 100% rename from Resources/Textures/Structures/Windows/cracks.rsi/DamageOverlay_4.png rename to Resources/Textures/Structures/Windows/cracks.rsi/DamageOverlay_5.png diff --git a/Resources/Textures/Structures/Windows/cracks.rsi/meta.json b/Resources/Textures/Structures/Windows/cracks.rsi/meta.json index 9d0cc9a505d1..ca012e8fc5c5 100644 --- a/Resources/Textures/Structures/Windows/cracks.rsi/meta.json +++ b/Resources/Textures/Structures/Windows/cracks.rsi/meta.json @@ -7,8 +7,8 @@ "license": "CC-BY-SA-3.0", "copyright": "Taken from https://github.com/tgstation/tgstation at commit e06b82a7f4b2b09216fb28fd384c95a2e1dc50e5", "states": [ - {"name": "DamageOverlay_4", "directions": 1}, - {"name": "DamageOverlay_8", "directions": 1}, - {"name": "DamageOverlay_12", "directions": 1} + {"name": "DamageOverlay_5", "directions": 1}, + {"name": "DamageOverlay_10", "directions": 1}, + {"name": "DamageOverlay_20", "directions": 1} ] } diff --git a/Resources/Textures/Structures/Windows/cracks_diagonal.rsi/DamageOverlay_8.png b/Resources/Textures/Structures/Windows/cracks_diagonal.rsi/DamageOverlay_10.png similarity index 100% rename from Resources/Textures/Structures/Windows/cracks_diagonal.rsi/DamageOverlay_8.png rename to Resources/Textures/Structures/Windows/cracks_diagonal.rsi/DamageOverlay_10.png diff --git a/Resources/Textures/Structures/Windows/cracks_diagonal.rsi/DamageOverlay_12.png b/Resources/Textures/Structures/Windows/cracks_diagonal.rsi/DamageOverlay_20.png similarity index 100% rename from Resources/Textures/Structures/Windows/cracks_diagonal.rsi/DamageOverlay_12.png rename to Resources/Textures/Structures/Windows/cracks_diagonal.rsi/DamageOverlay_20.png diff --git a/Resources/Textures/Structures/Windows/cracks_diagonal.rsi/DamageOverlay_4.png b/Resources/Textures/Structures/Windows/cracks_diagonal.rsi/DamageOverlay_5.png similarity index 100% rename from Resources/Textures/Structures/Windows/cracks_diagonal.rsi/DamageOverlay_4.png rename to Resources/Textures/Structures/Windows/cracks_diagonal.rsi/DamageOverlay_5.png diff --git a/Resources/Textures/Structures/Windows/cracks_diagonal.rsi/meta.json b/Resources/Textures/Structures/Windows/cracks_diagonal.rsi/meta.json index 9d0cc9a505d1..ca012e8fc5c5 100644 --- a/Resources/Textures/Structures/Windows/cracks_diagonal.rsi/meta.json +++ b/Resources/Textures/Structures/Windows/cracks_diagonal.rsi/meta.json @@ -7,8 +7,8 @@ "license": "CC-BY-SA-3.0", "copyright": "Taken from https://github.com/tgstation/tgstation at commit e06b82a7f4b2b09216fb28fd384c95a2e1dc50e5", "states": [ - {"name": "DamageOverlay_4", "directions": 1}, - {"name": "DamageOverlay_8", "directions": 1}, - {"name": "DamageOverlay_12", "directions": 1} + {"name": "DamageOverlay_5", "directions": 1}, + {"name": "DamageOverlay_10", "directions": 1}, + {"name": "DamageOverlay_20", "directions": 1} ] } diff --git a/Resources/Textures/Structures/Windows/cracks_directional.rsi/DamageOverlay_8.png b/Resources/Textures/Structures/Windows/cracks_directional.rsi/DamageOverlay_10.png similarity index 100% rename from Resources/Textures/Structures/Windows/cracks_directional.rsi/DamageOverlay_8.png rename to Resources/Textures/Structures/Windows/cracks_directional.rsi/DamageOverlay_10.png diff --git a/Resources/Textures/Structures/Windows/cracks_directional.rsi/DamageOverlay_12.png b/Resources/Textures/Structures/Windows/cracks_directional.rsi/DamageOverlay_20.png similarity index 100% rename from Resources/Textures/Structures/Windows/cracks_directional.rsi/DamageOverlay_12.png rename to Resources/Textures/Structures/Windows/cracks_directional.rsi/DamageOverlay_20.png diff --git a/Resources/Textures/Structures/Windows/cracks_directional.rsi/DamageOverlay_4.png b/Resources/Textures/Structures/Windows/cracks_directional.rsi/DamageOverlay_5.png similarity index 100% rename from Resources/Textures/Structures/Windows/cracks_directional.rsi/DamageOverlay_4.png rename to Resources/Textures/Structures/Windows/cracks_directional.rsi/DamageOverlay_5.png diff --git a/Resources/Textures/Structures/Windows/cracks_directional.rsi/meta.json b/Resources/Textures/Structures/Windows/cracks_directional.rsi/meta.json index df077f67d2bb..9555aa5ab35b 100644 --- a/Resources/Textures/Structures/Windows/cracks_directional.rsi/meta.json +++ b/Resources/Textures/Structures/Windows/cracks_directional.rsi/meta.json @@ -8,15 +8,15 @@ "copyright": "Adapted from https://github.com/space-wizards/space-station-14/ at commit f57e8ec6b9b4b72ef56c8146be0bc159ed2691ee, originally added by Zumorica, and modified for directional use by Darkie", "states": [ { - "name": "DamageOverlay_4", + "name": "DamageOverlay_5", "directions": 4 }, { - "name": "DamageOverlay_8", + "name": "DamageOverlay_10", "directions": 4 }, { - "name": "DamageOverlay_12", + "name": "DamageOverlay_20", "directions": 4 } ] From 21074bd98d3844dd8f6ae18f9f423752304fa7bd Mon Sep 17 00:00:00 2001 From: cohanna Date: Tue, 12 Nov 2024 19:14:28 -0700 Subject: [PATCH 079/290] oops --- .../Entities/Structures/Windows/plasma.yml | 2 + .../Entities/Structures/Windows/rplasma.yml | 2 + .../Entities/Structures/Windows/ruranium.yml | 2 + .../Entities/Structures/Windows/uranium.yml | 2 + .../Recipes/Construction/structures.yml | 40 ++++++++++++++----- 5 files changed, 37 insertions(+), 11 deletions(-) diff --git a/Resources/Prototypes/Entities/Structures/Windows/plasma.yml b/Resources/Prototypes/Entities/Structures/Windows/plasma.yml index bdeb37c6bb7e..8758e1075eba 100644 --- a/Resources/Prototypes/Entities/Structures/Windows/plasma.yml +++ b/Resources/Prototypes/Entities/Structures/Windows/plasma.yml @@ -106,6 +106,8 @@ acts: [ "Destruction" ] - type: StaticPrice price: 50 + - type: RadiationBlocker + resistance: 1 - type: entity parent: PlasmaWindow diff --git a/Resources/Prototypes/Entities/Structures/Windows/rplasma.yml b/Resources/Prototypes/Entities/Structures/Windows/rplasma.yml index 2ea710e6e774..2ad0eb84105a 100644 --- a/Resources/Prototypes/Entities/Structures/Windows/rplasma.yml +++ b/Resources/Prototypes/Entities/Structures/Windows/rplasma.yml @@ -82,6 +82,8 @@ trackAllDamage: true damageOverlay: sprite: Structures/Windows/cracks_directional.rsi + - type: RadiationBlocker + resistance: 2 - type: Destructible thresholds: - trigger: diff --git a/Resources/Prototypes/Entities/Structures/Windows/ruranium.yml b/Resources/Prototypes/Entities/Structures/Windows/ruranium.yml index fe40b21ba26a..daae6a4726d7 100644 --- a/Resources/Prototypes/Entities/Structures/Windows/ruranium.yml +++ b/Resources/Prototypes/Entities/Structures/Windows/ruranium.yml @@ -106,6 +106,8 @@ acts: [ "Destruction" ] - type: StaticPrice price: 110 + - type: RadiationBlocker + resistance: 2.5 - type: entity parent: ReinforcedUraniumWindow diff --git a/Resources/Prototypes/Entities/Structures/Windows/uranium.yml b/Resources/Prototypes/Entities/Structures/Windows/uranium.yml index 25ad1b876ed0..db9322800905 100644 --- a/Resources/Prototypes/Entities/Structures/Windows/uranium.yml +++ b/Resources/Prototypes/Entities/Structures/Windows/uranium.yml @@ -101,6 +101,8 @@ acts: [ "Destruction" ] - type: StaticPrice price: 100 + - type: RadiationBlocker + resistance: 1.5 - type: entity parent: UraniumWindow diff --git a/Resources/Prototypes/Recipes/Construction/structures.yml b/Resources/Prototypes/Recipes/Construction/structures.yml index 31e1264ab084..44a7134597d7 100644 --- a/Resources/Prototypes/Recipes/Construction/structures.yml +++ b/Resources/Prototypes/Recipes/Construction/structures.yml @@ -455,7 +455,7 @@ startNode: start targetNode: tintedWindow category: construction-category-structures - description: Not clear but tough. + description: Not clear, but lasers still pass through. canBuildInImpassable: true conditions: - !type:EmptyOrWindowValidInTile @@ -512,7 +512,7 @@ targetNode: plasmaWindow category: construction-category-structures canBuildInImpassable: true - description: Clear and even tougher, with a purple tint. + description: Clear, with a purple tint. conditions: - !type:EmptyOrWindowValidInTile - !type:NoWindowsInTile @@ -531,7 +531,7 @@ targetNode: reinforcedPlasmaWindow category: construction-category-structures canBuildInImpassable: true - description: Fire resistant and even tougher, with a purple tint. + description: Clear and even tougher, with a purple tint. conditions: - !type:EmptyOrWindowValidInTile - !type:NoWindowsInTile @@ -569,7 +569,7 @@ targetNode: plasmaWindowDiagonal category: construction-category-structures canBuildInImpassable: true - description: Clear and even tougher, with a purple tint. + description: Clear, with a purple tint. conditions: - !type:EmptyOrWindowValidInTile - !type:NoWindowsInTile @@ -587,7 +587,7 @@ targetNode: reinforcedPlasmaWindowDiagonal category: construction-category-structures canBuildInImpassable: true - description: Fire resistant and even tougher, with a purple tint. + description: Clear and even tougher, with a purple tint. conditions: - !type:EmptyOrWindowValidInTile - !type:NoWindowsInTile @@ -659,7 +659,7 @@ targetNode: plasmaWindowDirectional category: construction-category-structures canBuildInImpassable: true - description: Clear and even tougher, with a purple tint. + description: Clear, with a purple tint. conditions: - !type:EmptyOrWindowValidInTile - !type:NoWindowsInTile @@ -677,7 +677,7 @@ targetNode: plasmaReinforcedWindowDirectional category: construction-category-structures canBuildInImpassable: true - description: Fire resistant and even tougher, with a purple tint. + description: Clear and even tougher, with a purple tint. conditions: - !type:EmptyOrWindowValidInTile - !type:NoWindowsInTile @@ -695,7 +695,7 @@ targetNode: uraniumWindow category: construction-category-structures canBuildInImpassable: true - description: Clear and much tougher than regular glass, with added RadAbsorb to protect you from deadly radiation. + description: Clear, with added RadAbsorb to protect you from deadly radiation. conditions: - !type:EmptyOrWindowValidInTile - !type:NoWindowsInTile @@ -714,7 +714,7 @@ targetNode: reinforcedUraniumWindow category: construction-category-structures canBuildInImpassable: true - description: Clear and much tougher than regular glass, with added RadAbsorb to protect you from deadly radiation. + description: Clear and even tougher, with added RadAbsorb to protect you from deadly radiation. conditions: - !type:EmptyOrWindowValidInTile - !type:NoWindowsInTile @@ -733,7 +733,7 @@ targetNode: uraniumWindowDiagonal category: construction-category-structures canBuildInImpassable: true - description: Clear and much tougher than regular glass, with added RadAbsorb to protect you from deadly radiation. + description: Clear, with added RadAbsorb to protect you from deadly radiation. conditions: - !type:EmptyOrWindowValidInTile - !type:NoWindowsInTile @@ -751,7 +751,7 @@ targetNode: reinforcedUraniumWindowDiagonal category: construction-category-structures canBuildInImpassable: true - description: Clear and much tougher than regular glass, with added RadAbsorb to protect you from deadly radiation. + description: Clear and even tougher, with added RadAbsorb to protect you from deadly radiation. conditions: - !type:EmptyOrWindowValidInTile - !type:NoWindowsInTile @@ -1456,6 +1456,24 @@ # Same here. - 20kdc - !type:TileNotBlocked +- type: construction + name: emergency light + id: EmergencyLightFixture + graph: LightFixture + startNode: start + targetNode: emergencyLight + category: construction-category-structures + description: An emergency light. + icon: + sprite: Structures/Wallmounts/Lighting/emergency_light.rsi + state: base + objectType: Structure + placementMode: SnapgridCenter + canRotate: true + canBuildInImpassable: false + conditions: + - !type:TileNotBlocked + - type: construction name: ground light post id: LightGroundFixture From bd2d0ee5e593606da094804f5822cf740a1f1084 Mon Sep 17 00:00:00 2001 From: August Sun <45527070+august-sun@users.noreply.github.com> Date: Tue, 12 Nov 2024 19:59:47 -0700 Subject: [PATCH 080/290] Added the ability to microwave inert flesh anomaly cores to turn into an anomalous meat mass (#33223) * First round of anomaly core functionalities added * Added sliceTime to anom meat mass and cooked version * Adds SmokeOnUse component, system and shared system, adds new functions to inert electrical anom core * Added more functions * Final touches to branch * Cleaning up some of the metadata for sprites and component definitions * PR_Changes_v2_rev.0_Final_FINALFORREALTHISTIME.yml * Lol jk these goddamn tests why me * Quick updates based on feedback * more changes to improve * additional fixes and edits * Changed tech core functionality * added magboot functionality to grav core * fixed issue with bluespace core sizing * Reverting changes per request * extra file to be deleted * File cleanup * Update chemicals.ftl * Update cores.yml * Update cores.yml * Update meta.json * Update chemicals.yml * Update Resources/Prototypes/Entities/Objects/Consumable/Food/meat.yml Co-authored-by: chromiumboy <50505512+chromiumboy@users.noreply.github.com> * Update meal_recipes.yml * Update cores.yml --------- Co-authored-by: august-sun <45527070+august.sun@users.noreply.github.com> Co-authored-by: chromiumboy <50505512+chromiumboy@users.noreply.github.com> --- .../Entities/Objects/Consumable/Food/meat.yml | 59 ++++++++++++++++++ .../Structures/Specific/Anomaly/cores.yml | 6 +- .../Construction/Graphs/food/steak.yml | 18 +++++- .../Recipes/Cooking/meal_recipes.yml | 24 +++++++ .../Food/meat.rsi/anomalymeat-cooked.png | Bin 0 -> 618 bytes .../Consumable/Food/meat.rsi/anomalymeat.png | Bin 0 -> 642 bytes .../Consumable/Food/meat.rsi/meta.json | 8 ++- 7 files changed, 111 insertions(+), 4 deletions(-) create mode 100644 Resources/Textures/Objects/Consumable/Food/meat.rsi/anomalymeat-cooked.png create mode 100644 Resources/Textures/Objects/Consumable/Food/meat.rsi/anomalymeat.png diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/meat.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/meat.yml index 612f7da0472b..48968b80c132 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Food/meat.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/meat.yml @@ -701,6 +701,36 @@ - ReagentId: Water Quantity: 4 #It makes saline if you add salt! +- type: entity + name: anomalous meat mass + parent: FoodMeatRawBase + id: FoodMeatAnomaly + description: An impossibly dense slab of meat. Just looking at it makes you uncomfortable. + components: + - type: Sprite + state: anomalymeat + - type: SolutionContainerManager + solutions: + food: + reagents: + - ReagentId: UncookedAnimalProteins + Quantity: 90 + - ReagentId: Fat + Quantity: 90 + - type: SliceableFood + count: 10 + sliceTime: 5 + slice: FoodMeat #That's... So much meat + - type: InternalTemperature + conductivity: 0.43 + - type: Construction + graph: AnomalyMeatSteak + node: start + defaultTarget: anomaly steak + - type: Tag + tags: + - Meat + # Cooked - type: entity @@ -1173,6 +1203,35 @@ Burger: MeatSnail Taco: MeatSnail +- type: entity + name: anomalous steak + parent: FoodMeatBase + id: FoodMeatAnomalyCooked + description: A gigantic mass of cooked meat. A meal for a dinner party, or someone REALLY hungry. + components: + - type: Tag + tags: + - Cooked + - Meat + - type: Sprite + layers: + - state: anomalymeat-cooked #Kinda hard to cook this... thing evenly + - type: SolutionContainerManager + solutions: + food: + reagents: + - ReagentId: Nutriment + Quantity: 100 + - ReagentId: Protein + Quantity: 50 + - type: SliceableFood + count: 10 + sliceTime: 5 + slice: FoodMeatCooked + - type: Construction + graph: AnomalyMeatSteak + node: anomaly steak + # Cutlets # Raw diff --git a/Resources/Prototypes/Entities/Structures/Specific/Anomaly/cores.yml b/Resources/Prototypes/Entities/Structures/Specific/Anomaly/cores.yml index 315505b81e9b..568a133749e7 100644 --- a/Resources/Prototypes/Entities/Structures/Specific/Anomaly/cores.yml +++ b/Resources/Prototypes/Entities/Structures/Specific/Anomaly/cores.yml @@ -79,6 +79,7 @@ - type: entity parent: BaseAnomalyCore id: AnomalyCoreFlesh + description: The core of a destroyed flesh anomaly. Pulsates sickeningly, but might be a hearty meal if cooked. suffix: Flesh components: - type: Sprite @@ -241,7 +242,8 @@ - type: entity parent: BaseAnomalyInertCore - id: AnomalyCoreFleshInert + id: AnomalyCoreFleshInert # Can be microwaved to turn it into a massive piece of meat + description: The inert core of a destroyed flesh anomaly. Pulsates sickeningly, but might be good food in the right hands? suffix: Flesh, Inert components: - type: Sprite @@ -306,7 +308,7 @@ - type: entity parent: BaseAnomalyInertCore - id: AnomalyCoreFloraInert + id: AnomalyCoreFloraInert #Turns into a seed that grows into artifexium suffix: Flora, Inert components: - type: Seed diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/food/steak.yml b/Resources/Prototypes/Recipes/Construction/Graphs/food/steak.yml index 4c1040033194..61cb844037b4 100644 --- a/Resources/Prototypes/Recipes/Construction/Graphs/food/steak.yml +++ b/Resources/Prototypes/Recipes/Construction/Graphs/food/steak.yml @@ -174,6 +174,22 @@ - node: bacon entity: FoodMeatBaconCooked +# anomaly meat steak +- type: constructionGraph + id: AnomalyMeatSteak + start: start + graph: + - node: start + edges: + - to: anomaly steak + completed: + - !type:PlaySound + sound: /Audio/Effects/sizzle.ogg + steps: + - minTemperature: 335 + - node: anomaly steak + entity: FoodMeatAnomalyCooked + # cutlets - type: constructionGraph @@ -294,4 +310,4 @@ steps: - minTemperature: 345 - node: xeno cutlet - entity: FoodMeatXenoCutletCooked \ No newline at end of file + entity: FoodMeatXenoCutletCooked diff --git a/Resources/Prototypes/Recipes/Cooking/meal_recipes.yml b/Resources/Prototypes/Recipes/Cooking/meal_recipes.yml index 173cf9e9dbdc..da66f7a0d8a8 100644 --- a/Resources/Prototypes/Recipes/Cooking/meal_recipes.yml +++ b/Resources/Prototypes/Recipes/Cooking/meal_recipes.yml @@ -2050,3 +2050,27 @@ FoodCroissantRaw: 1 FoodButterSlice: 1 ShardGlass: 1 + +- type: microwaveMealRecipe + id: RecipeInertAnomalyMeat + name: inert meat anomaly recipe + result: FoodMeatAnomaly + time: 5 + solids: + AnomalyCoreFleshInert: 1 + +- type: microwaveMealRecipe + id: RecipeAnomalyMeat + name: meat anomaly recipe + result: FoodMeatAnomaly + time: 5 + solids: + AnomalyCoreFlesh: 1 + +- type: microwaveMealRecipe + id: RecipeAnomalyMeatCooked + name: cooked meat anomaly recipe + result: FoodMeatAnomalyCooked + time: 5 + solids: + FoodMeatAnomaly: 1 diff --git a/Resources/Textures/Objects/Consumable/Food/meat.rsi/anomalymeat-cooked.png b/Resources/Textures/Objects/Consumable/Food/meat.rsi/anomalymeat-cooked.png new file mode 100644 index 0000000000000000000000000000000000000000..19c0040f3a150fb1b247ff901673516605618e39 GIT binary patch literal 618 zcmV-w0+s!VP)Px%BuPX;R9J=Wl+SA0KoG`%7HMS3rIEcd#E_HmCE%7op_c@FF!U+>6n%mAVfq3+ zmmCbu!8cPIdT5$MNogULt+uv>NRWD1X(QS4pSrnK9|*BCyEET>GrN!@M~?p;g>(-!=iM16Pc^kC>2t>3RwT4d8A7;A=QzkCle1&8Hi;4_T@M3 z+yvm=`!OGeGXT05*J`UfHqx95FmfKJ)~(Ycl`O6d1P)JJx~%0>;CoYeZE!2>_i}oP@{TxZ}7CG z!Ae%VDe+$uh)F=C2H6sCoA{s5saxSOT=+9=l}o!07*qoM6N<$ Ef@X&iumAu6 literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Consumable/Food/meat.rsi/anomalymeat.png b/Resources/Textures/Objects/Consumable/Food/meat.rsi/anomalymeat.png new file mode 100644 index 0000000000000000000000000000000000000000..005107ab4ec5e066f292c3d6a163174d11c9e7e7 GIT binary patch literal 642 zcmV-|0)737P)Px%JV``BR9J=WmBDM%P#niURU4tC5L+}p8Nv>0DPk$&c^8WpFN1kddZ_<_3S*A3 zlN6Eu37*=)4vM>Y@Z_mS5tLq}-C-9Yq+kuUC`%9V(7xBCOS^1(GhYbF`@JN;@Avz@ zFM${_V*Kw&oaLcLHs|@rkG^*kvvdC1KOrDrY~bRcVc>GOew$1CZFP@-&OwVr;#^b$ z0C}OQb8=&i-0~6z?y=@_90idGNcFZg#1uNVH3T5D_W@Jr7`T{1R|EkZv|~#Zh6{@t zN|YYo=l7d;z_dZ(<}F&*d!^j5T&3C+IwsJuPIh6g19>sF)4=8DwG`&dO6z<+(&^{ntTv7Ew`v4$NlXZKmu3VTG z$j~K_O5|DtIL~%jx_X^fwFZnGvaKNwno=*D!qlm}(CAn$jcm>fBM~WtrqEe!?$D~% z$O}z{O$M-4ttn?DY3ZJA4ap0Qo|g)J_gn&g_5Dg2d#kQg`wu?}fMWA`Abbwm!Z3ys z=y@r+o`HjgDRjDr-vXqhy4f>~vvBWolYXVF8uz>u&gdwVKxhUw`(G0EOvy8Fu`QS7 z{ZH5vHRIaU9eHg`#vk`ytGTXwesUGw92R_v>zPtu`&>!<3e5ZWyd;s_SerJVxc2nb z+l8Ow$p3=vbip%{7XyT5gXN5lxcu-&q{gQvAV~m7B4O+LV(|4$f7nxDJ6-T3nHVu* c#Q0nM0h_}40T=^O)c^nh07*qoM6N<$f|m*~VgLXD literal 0 HcmV?d00001 diff --git a/Resources/Textures/Objects/Consumable/Food/meat.rsi/meta.json b/Resources/Textures/Objects/Consumable/Food/meat.rsi/meta.json index 4ad75849d1af..99084d8c9588 100644 --- a/Resources/Textures/Objects/Consumable/Food/meat.rsi/meta.json +++ b/Resources/Textures/Objects/Consumable/Food/meat.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Taken from tgstation and modified by Swept, potato1234x and deltanedas at https://github.com/tgstation/tgstation/commit/40d75cc340c63582fb66ce15bf75a36115f6bdaa, snail by IproduceWidgets (github) and Kezu (discord)", + "copyright": "Taken from tgstation and modified by Swept, potato1234x and deltanedas at https://github.com/tgstation/tgstation/commit/40d75cc340c63582fb66ce15bf75a36115f6bdaa, snail by IproduceWidgets (github) and Kezu (discord), anomalymeat/cooked by august-sun", "size": { "x": 32, "y": 32 @@ -200,6 +200,12 @@ }, { "name": "rouny-cooked" + }, + { + "name": "anomalymeat" + }, + { + "name": "anomalymeat-cooked" } ] } From 52c1708117f82e75f0d0b911f3e8319c7a97725d Mon Sep 17 00:00:00 2001 From: PJBot Date: Wed, 13 Nov 2024 03:00:54 +0000 Subject: [PATCH 081/290] Automatic changelog update --- Resources/Changelog/Changelog.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 4ab88b325b53..f54421b87ad8 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: Spessmann - changes: - - message: Added Cog, a new midpop map based on Cogmap from ss13 - type: Add - id: 7105 - time: '2024-08-13T19:27:25.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/30840 - author: PoorMansDreams changes: - message: Throngler Plushie looks like a plushie @@ -3948,3 +3941,11 @@ id: 7604 time: '2024-11-12T12:06:43.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33011 +- author: august-sun + changes: + - message: The inert flesh anomaly core can now be microwaved to turn into an anomalous + meat mass. + type: Tweak + id: 7605 + time: '2024-11-13T02:59:47.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33223 From 99b4604d5096eea467a7006ccfa90ef17e06e73e Mon Sep 17 00:00:00 2001 From: Spessmann <156740760+Spessmann@users.noreply.github.com> Date: Tue, 12 Nov 2024 19:07:47 -0800 Subject: [PATCH 082/290] Cog fixes (#33285) fixed the map (for real this time) --- Resources/Maps/cog.yml | 3014 +++++++++++++++++++++++++--------------- 1 file changed, 1914 insertions(+), 1100 deletions(-) diff --git a/Resources/Maps/cog.yml b/Resources/Maps/cog.yml index 58310e561c01..859ee46b1ded 100644 --- a/Resources/Maps/cog.yml +++ b/Resources/Maps/cog.yml @@ -333,7 +333,7 @@ entities: version: 6 3,3: ind: 3,3 - tiles: YAAAAAAAYAAAAAABYAAAAAAAYAAAAAACYAAAAAACYAAAAAACYAAAAAABYAAAAAACYAAAAAACYAAAAAABYAAAAAAAYAAAAAAAYAAAAAACYAAAAAACYAAAAAACYAAAAAADYAAAAAABgQAAAAAAYAAAAAABYAAAAAACgQAAAAAAYAAAAAAAYAAAAAADYAAAAAADYAAAAAACYAAAAAAAYAAAAAABYAAAAAACYAAAAAADYAAAAAADYAAAAAADYAAAAAADYAAAAAAAgQAAAAAAYAAAAAADYAAAAAADgQAAAAAAgQAAAAAAYAAAAAAAYAAAAAACYAAAAAAAYAAAAAACYAAAAAAAYAAAAAACgQAAAAAAYAAAAAADYAAAAAADYAAAAAAAYAAAAAADgQAAAAAAYAAAAAABYAAAAAADYAAAAAACgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAYAAAAAACgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAYAAAAAADgQAAAAAAYAAAAAADYAAAAAABYAAAAAACgQAAAAAADAAAAAADDAAAAAABDAAAAAACfQAAAAACfQAAAAACCwAAAAAADAAAAAACDAAAAAAADAAAAAAADAAAAAADYAAAAAABgQAAAAAAYAAAAAABYAAAAAAAgQAAAAAAgQAAAAAADAAAAAACDAAAAAACDAAAAAAAfQAAAAABfQAAAAAAfQAAAAAADAAAAAADDAAAAAADDAAAAAACCAAAAAAAgQAAAAAAgQAAAAAAYAAAAAACYAAAAAADYAAAAAADYAAAAAADCAAAAAABCAAAAAAACAAAAAACfQAAAAAAfQAAAAABfQAAAAACCAAAAAACCAAAAAADCAAAAAAACAAAAAADYAAAAAAAYAAAAAAAYAAAAAAAYAAAAAABYAAAAAAAYAAAAAADCAAAAAAACAAAAAABCAAAAAABfQAAAAADfQAAAAAAfQAAAAACCAAAAAADCAAAAAADCAAAAAACCAAAAAACYAAAAAACYAAAAAAAYAAAAAABYAAAAAADYAAAAAABgQAAAAAADAAAAAAADAAAAAAADAAAAAADfQAAAAADfQAAAAACfQAAAAACDAAAAAAADAAAAAAADAAAAAAADAAAAAACYAAAAAABgQAAAAAAYAAAAAAAYAAAAAADYAAAAAAAgQAAAAAADAAAAAABDAAAAAABDAAAAAACfQAAAAABfQAAAAACfQAAAAABDAAAAAACDAAAAAAADAAAAAABDAAAAAADYAAAAAABgQAAAAAAYAAAAAADYAAAAAAAYAAAAAAAgQAAAAAADAAAAAAADAAAAAADDAAAAAACfQAAAAABfQAAAAACfQAAAAADDAAAAAAADAAAAAADDAAAAAADDAAAAAAAYAAAAAAAgQAAAAAAYAAAAAADYAAAAAABYAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAYAAAAAACgQAAAAAAgQAAAAAAYAAAAAADgQAAAAAAgQAAAAAAYAAAAAACYAAAAAACYAAAAAACYAAAAAACYAAAAAADgQAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAgQAAAAAAgQAAAAAAYAAAAAAAYAAAAAAAYAAAAAAAgQAAAAAAYAAAAAAAYAAAAAAAYAAAAAACYAAAAAABYAAAAAACgQAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAYAAAAAAAYAAAAAAAYAAAAAADYAAAAAACYAAAAAACgQAAAAAAYAAAAAAAYAAAAAABYAAAAAACYAAAAAADYAAAAAABgQAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAYAAAAAADYAAAAAABYAAAAAABYAAAAAACYAAAAAABgQAAAAAAYAAAAAAAYAAAAAACYAAAAAAAYAAAAAACYAAAAAABgQAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAA + tiles: YAAAAAAAYAAAAAABYAAAAAAAYAAAAAACYAAAAAACYAAAAAACYAAAAAABYAAAAAACYAAAAAACYAAAAAABYAAAAAAAYAAAAAAAYAAAAAACYAAAAAACYAAAAAACYAAAAAADYAAAAAABgQAAAAAAYAAAAAABYAAAAAACgQAAAAAAYAAAAAAAYAAAAAADYAAAAAADYAAAAAACYAAAAAAAYAAAAAABYAAAAAACYAAAAAADYAAAAAADYAAAAAADYAAAAAADYAAAAAAAgQAAAAAAYAAAAAADYAAAAAADgQAAAAAAgQAAAAAAYAAAAAAAYAAAAAACYAAAAAAAYAAAAAACYAAAAAAAYAAAAAACgQAAAAAAYAAAAAADYAAAAAADYAAAAAAAYAAAAAADgQAAAAAAYAAAAAABYAAAAAADYAAAAAACgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAYAAAAAACgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAYAAAAAADgQAAAAAAYAAAAAADYAAAAAABYAAAAAACgQAAAAAADAAAAAADDAAAAAABDAAAAAACfQAAAAACfQAAAAACCwAAAAAADAAAAAACDAAAAAAADAAAAAAADAAAAAADYAAAAAABgQAAAAAAYAAAAAABYAAAAAAAgQAAAAAAgQAAAAAADAAAAAACDAAAAAACDAAAAAAAfQAAAAABfQAAAAAAfQAAAAAADAAAAAADDAAAAAADDAAAAAACCAAAAAAAgQAAAAAAgQAAAAAAYAAAAAACYAAAAAADYAAAAAADYAAAAAADCAAAAAABCAAAAAAACAAAAAACfQAAAAAAfQAAAAABfQAAAAACCAAAAAACCAAAAAADCAAAAAAACAAAAAADYAAAAAAAYAAAAAAAYAAAAAAAYAAAAAABYAAAAAAAYAAAAAADCAAAAAAACAAAAAABCAAAAAABfQAAAAADfQAAAAAAfQAAAAACCAAAAAADCAAAAAADCAAAAAACCAAAAAACYAAAAAACYAAAAAAAYAAAAAABYAAAAAADYAAAAAABgQAAAAAADAAAAAAADAAAAAAADAAAAAADfQAAAAADfQAAAAACfQAAAAACDAAAAAAADAAAAAAADAAAAAAADAAAAAACYAAAAAABgQAAAAAAYAAAAAAAYAAAAAADYAAAAAAAgQAAAAAADAAAAAABDAAAAAABDAAAAAACfQAAAAABfQAAAAACfQAAAAABDAAAAAACDAAAAAAADAAAAAABDAAAAAADYAAAAAABgQAAAAAAYAAAAAADYAAAAAAAYAAAAAAAgQAAAAAADAAAAAAADAAAAAADDAAAAAACfQAAAAABfQAAAAACfQAAAAADDAAAAAAADAAAAAADDAAAAAADDAAAAAAAYAAAAAAAgQAAAAAAYAAAAAADYAAAAAABYAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAYAAAAAACgQAAAAAAgQAAAAAAYAAAAAADgQAAAAAAgQAAAAAAYAAAAAACYAAAAAACYAAAAAACYAAAAAACYAAAAAADgQAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAgQAAAAAAgQAAAAAAYAAAAAAAYAAAAAAAYAAAAAAAgQAAAAAAYAAAAAAAYAAAAAAAYAAAAAACYAAAAAABYAAAAAACgQAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAYAAAAAAAYAAAAAAAYAAAAAADYAAAAAACYAAAAAACYAAAAAAAYAAAAAAAYAAAAAABYAAAAAACYAAAAAADYAAAAAABgQAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAYAAAAAADYAAAAAABYAAAAAABYAAAAAACYAAAAAABgQAAAAAAYAAAAAAAYAAAAAACYAAAAAAAYAAAAAACYAAAAAABgQAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAA version: 6 2,3: ind: 2,3 @@ -353,7 +353,7 @@ entities: version: 6 3,4: ind: 3,4 - tiles: gQAAAAAAIAAAAAABgQAAAAAAgQAAAAAAYAAAAAABgQAAAAAAYAAAAAABYAAAAAADYAAAAAADYAAAAAACYAAAAAADgQAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAIAAAAAABIAAAAAAAIAAAAAACgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAgQAAAAAAIAAAAAADgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + tiles: gQAAAAAAIAAAAAABgQAAAAAAgQAAAAAAYAAAAAABgQAAAAAAYAAAAAABYAAAAAADYAAAAAADYAAAAAACYAAAAAADgQAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAIAAAAAABIAAAAAAAIAAAAAACgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAgQAAAAAAIAAAAAADgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA version: 6 2,4: ind: 2,4 @@ -441,11 +441,11 @@ entities: version: 6 -1,-5: ind: -1,-5 - tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAgAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAgQAAAAAAIAAAAAACgQAAAAAAIAAAAAABgQAAAAAAgQAAAAAAIAAAAAAAgQAAAAAAIAAAAAABgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgQAAAAAAgQAAAAAAIAAAAAADgQAAAAAAgQAAAAAAgQAAAAAAIAAAAAACIAAAAAACgQAAAAAAgQAAAAAAgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgQAAAAAAIAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAIAAAAAACgQAAAAAAIAAAAAACIAAAAAABgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAIAAAAAABgQAAAAAAIAAAAAAAIAAAAAADgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAA + tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAYAAAAAAAgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAYAAAAAAAgQAAAAAAgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAYAAAAAAAgQAAAAAAgQAAAAAAYAAAAAAAYAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAYAAAAAAAYAAAAAAAYAAAAAAAYAAAAAAAgQAAAAAAgQAAAAAAYAAAAAAAgQAAAAAAIAAAAAACgQAAAAAAIAAAAAABgQAAAAAAgQAAAAAAIAAAAAAAgQAAAAAAIAAAAAABYAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAIAAAAAADgQAAAAAAgQAAAAAAgQAAAAAAIAAAAAACIAAAAAACgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAIAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAIAAAAAACgQAAAAAAIAAAAAACIAAAAAABgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAIAAAAAABgQAAAAAAIAAAAAAAIAAAAAADgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAA version: 6 -2,-5: ind: -2,-5 - tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAA + tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAgQAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAYAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAYAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAAgQAAAAAA version: 6 0,-5: ind: 0,-5 @@ -1262,9 +1262,7 @@ entities: color: '#FFFFFFFF' id: BrickTileSteelLineE decals: - 2507: 1,36 2508: 1,37 - 2509: 1,38 2510: 1,39 4041: 77,46 4042: 77,51 @@ -1299,13 +1297,18 @@ entities: 9612: -5,71 9911: -48,70 9912: -48,73 + - node: + zIndex: 1 + color: '#FFFFFFFF' + id: BrickTileSteelLineE + decals: + 9952: 1,36 + 9953: 1,38 - node: color: '#FFFFFFFF' id: BrickTileSteelLineN decals: - 2518: 2,35 2519: 3,35 - 2520: 4,35 2521: 5,35 2522: 6,35 2523: 7,35 @@ -1357,6 +1360,13 @@ entities: 9902: -51,74 9903: -50,74 9904: -49,74 + - node: + zIndex: 1 + color: '#FFFFFFFF' + id: BrickTileSteelLineN + decals: + 9950: 2,35 + 9951: 4,35 - node: color: '#FFFFFFFF' id: BrickTileSteelLineS @@ -1953,6 +1963,14 @@ entities: 9920: -32,75 9921: -28,74 9922: -29,77 + 10059: -58,-17 + 10060: -61,-16 + 10113: -10,-69 + 10114: -12,-72 + 10115: -14,-70 + 10116: -16,-72 + 10117: -16,-68 + 10118: -12,-67 - node: cleanable: True zIndex: 1 @@ -2173,7 +2191,6 @@ entities: 4138: -36,1 4139: -30,7 4140: -30,10 - 4141: -22,9 4142: -21,7 4143: -17,11 4144: -16,0 @@ -3082,6 +3099,164 @@ entities: 9942: -43,67 9943: -43,68 9944: -46,68 + 9984: -1,10 + 9985: 0,7 + 9986: -2,7 + 9987: -2,7 + 9988: -1,7 + 9989: -3,10 + 9990: -4,11 + 9991: -7,4 + 9992: -7,5 + 9993: -7,6 + 9994: -6,7 + 9995: -9,0 + 9996: -10,-2 + 9997: -11,-2 + 9998: -11,-1 + 9999: -13,-2 + 10000: -12,-5 + 10001: -11,-4 + 10002: -12,-4 + 10003: -12,-4 + 10004: -2,-4 + 10005: -11,-11 + 10006: -11,-10 + 10007: -11,-10 + 10008: -11,-9 + 10009: -12,-9 + 10010: -12,-9 + 10011: -11,-7 + 10012: -10,-13 + 10013: -10,-12 + 10014: -7,-16 + 10015: -8,-16 + 10016: -7,-15 + 10017: -7,-15 + 10018: -7,-18 + 10019: -4,-20 + 10020: -4,-21 + 10021: -5,-20 + 10022: -3,-19 + 10023: -3,-21 + 10024: -1,-21 + 10025: 3,-21 + 10026: 4,-19 + 10027: 4,-15 + 10028: 4,-16 + 10029: 4,-16 + 10030: 4,-17 + 10031: 4,-24 + 10032: 2,-24 + 10033: -13,-23 + 10034: -60,-28 + 10035: -61,-28 + 10036: -63,-30 + 10037: -60,-22 + 10038: -59,-22 + 10039: -59,-25 + 10040: -59,-28 + 10041: -61,-16 + 10042: -61,-16 + 10043: -61,-16 + 10044: -61,-16 + 10045: -61,-15 + 10046: -60,-14 + 10047: -57,-17 + 10048: -58,-16 + 10049: -57,-16 + 10050: -58,-17 + 10051: -54,-17 + 10052: -55,-17 + 10053: -55,-16 + 10054: -54,-16 + 10055: -53,-16 + 10056: -55,-15 + 10057: -54,-13 + 10058: -54,-13 + 10061: -60,-14 + 10062: -60,-14 + 10063: -60,-14 + 10064: -57,-17 + 10065: -55,-16 + 10066: -55,-16 + 10067: -55,-15 + 10068: -56,-16 + 10069: -56,-16 + 10070: -55,-15 + 10071: -54,-16 + 10072: -54,-16 + 10073: -54,-16 + 10074: -51,-15 + 10075: -50,-15 + 10076: -51,-13 + 10077: -52,-20 + 10078: -52,-20 + 10079: -52,-20 + 10080: -53,-20 + 10081: -51,-20 + 10082: -46,-23 + 10083: -17,-70 + 10084: -15,-69 + 10085: -15,-70 + 10086: -14,-70 + 10087: -13,-69 + 10088: -12,-69 + 10089: -11,-70 + 10090: -11,-71 + 10091: -11,-72 + 10092: -12,-72 + 10093: -12,-71 + 10094: -14,-72 + 10095: -15,-72 + 10096: -15,-72 + 10097: -16,-72 + 10098: -16,-72 + 10099: -15,-72 + 10100: -10,-69 + 10101: -10,-69 + 10102: -11,-69 + 10103: -11,-69 + 10104: -11,-70 + 10105: -13,-70 + 10106: -16,-68 + 10107: -16,-69 + 10108: -14,-69 + 10109: -12,-70 + 10110: -11,-70 + 10111: -16,-70 + 10112: -17,-68 + 10119: -16,-66 + 10120: -13,-66 + 10121: -12,-66 + 10122: -13,-67 + 10123: -12,-67 + 10124: -11,-67 + 10125: -13,-67 + 10126: -14,-67 + 10127: -14,-66 + 10128: -15,-66 + 10129: -15,-65 + 10130: -13,-65 + 10131: -13,-65 + 10132: -9,-65 + 10133: -8,-64 + 10134: -14,-63 + 10146: -24,9 + 10147: -25,9 + 10148: -21,9 + 10149: -21,10 + 10150: -20,9 + 10151: -24,7 + 10152: -24,4 + 10153: -22,5 + 10154: -21,4 + 10155: -20,13 + 10156: -22,13 + 10157: -23,14 + 10158: -24,14 + 10159: -24,11 + 10160: -20,12 - node: cleanable: True zIndex: 1 @@ -3202,6 +3377,15 @@ entities: 8588: 28,23 8589: 29,25 8590: 29,25 + 9954: -1,22 + 9955: -1,21 + 9956: -3,22 + 9957: -3,22 + 9958: -4,22 + 9959: -5,19 + 9960: -5,20 + 9961: -3,21 + 9962: -2,21 - node: cleanable: True color: '#FFFFFFFF' @@ -3270,7 +3454,6 @@ entities: 3000: -11,6 3001: -9,8 3002: -19,8 - 3003: -24,9 3004: -19,11 3005: -16,12 3006: -17,18 @@ -3300,7 +3483,6 @@ entities: 3032: -31,39 3033: -38,41 3034: -28,39 - 3035: -35,45 3036: -30,43 3037: -28,46 3038: -30,51 @@ -3985,7 +4167,6 @@ entities: 3828: -26,13 3829: -26,12 3830: -26,10 - 3831: -25,9 3832: -26,8 3833: -24,10 3834: -23,8 @@ -4624,6 +4805,25 @@ entities: 9861: -31,78 9862: -29,75 9863: -29,75 + 9965: -2,17 + 9966: -2,17 + 9967: -3,17 + 9968: -4,15 + 9969: -1,15 + 9970: -1,15 + 9971: -4,17 + 9972: -4,17 + 9973: -13,17 + 9974: -13,17 + 9975: -12,10 + 9976: -9,11 + 9977: -8,9 + 9978: -3,10 + 9979: -4,10 + 9980: -5,10 + 9981: -5,11 + 9982: -4,11 + 9983: -3,11 - node: cleanable: True zIndex: 1 @@ -4643,6 +4843,8 @@ entities: 8165: 42,4 8166: 42,4 8167: 42,4 + 9963: -5,22 + 9964: -4,21 - node: cleanable: True color: '#B02E26FF' @@ -7632,18 +7834,18 @@ entities: 2541: 0,33 2542: 0,35 2543: 1,34 - 2544: 2,35 2545: 3,34 - 2546: 1,36 2547: 0,37 2548: 0,39 - 2549: 1,38 2550: 5,34 - 2551: 4,35 2579: 6,41 2975: -17,-33 2981: -17,-37 2985: -18,-36 + 9946: 4,35 + 9947: 2,35 + 9948: 1,36 + 9949: 1,38 - node: color: '#8C347F96' id: QuarterTileOverlayGreyscale90 @@ -7847,40 +8049,47 @@ entities: 7279: 28.908653,-33.8389 7347: -20.375824,19.28789 - node: + zIndex: 1 color: '#FFFFFFFF' id: SpaceStationSign1 decals: - 2058: -25,9 + 10139: -25,9 - node: + zIndex: 1 color: '#FFFFFFFF' id: SpaceStationSign2 decals: - 2034: -24,9 + 10140: -24,9 - node: + zIndex: 1 color: '#FFFFFFFF' id: SpaceStationSign3 decals: - 1863: -23,9 + 10141: -23,9 - node: + zIndex: 1 color: '#FFFFFFFF' id: SpaceStationSign4 decals: - 1864: -22,9 + 10142: -22,9 - node: + zIndex: 1 color: '#FFFFFFFF' id: SpaceStationSign5 decals: - 1865: -21,9 + 10143: -21,9 - node: + zIndex: 1 color: '#FFFFFFFF' id: SpaceStationSign6 decals: - 1866: -20,9 + 10144: -20,9 - node: + zIndex: 1 color: '#FFFFFFFF' id: SpaceStationSign7 decals: - 1867: -19,9 + 10145: -19,9 - node: color: '#32CD3293' id: ThreeQuarterTileOverlayGreyscale @@ -9860,7 +10069,7 @@ entities: -4,-14: 0: 49631 -4,-17: - 0: 61441 + 0: 65473 -3,-16: 0: 46008 -3,-15: @@ -9868,7 +10077,7 @@ entities: -3,-14: 0: 62139 -3,-17: - 0: 61568 + 0: 61872 -2,-16: 0: 3839 -2,-15: @@ -11076,8 +11285,8 @@ entities: 13,15: 0: 57308 13,16: - 0: 4381 - 2: 51200 + 0: 797 + 2: 52224 14,13: 0: 65535 14,14: @@ -11086,9 +11295,9 @@ entities: 0: 30583 14,16: 0: 7 - 2: 61952 + 2: 65280 15,16: - 2: 12835 + 2: 13107 7,12: 0: 61408 8,13: @@ -11220,7 +11429,7 @@ entities: -1,16: 0: 63675 12,17: - 2: 61448 + 2: 61440 12,18: 2: 52479 11,17: @@ -11232,7 +11441,7 @@ entities: 11,19: 2: 45055 13,17: - 2: 63627 + 2: 63624 13,18: 2: 39423 13,19: @@ -11240,7 +11449,7 @@ entities: 12,20: 2: 15 14,17: - 2: 61986 + 2: 61998 14,18: 2: 8959 14,19: @@ -11250,7 +11459,7 @@ entities: 14,20: 2: 15 15,17: - 2: 65058 + 2: 65059 15,18: 2: 8191 15,19: @@ -11603,15 +11812,17 @@ entities: 0: 631 -6,19: 2: 8 - -5,-18: - 0: 48000 + -4,-19: + 0: 20480 -4,-18: - 2: 3584 + 0: 65367 + -5,-18: + 0: 47872 + 2: 4 -3,-18: - 2: 18176 + 0: 29495 -2,-18: 0: 61440 - 2: 96 -1,-18: 0: 65280 -1,-17: @@ -14887,6 +15098,11 @@ entities: - type: Transform pos: -36.5,15.5 parent: 12 + - uid: 10620 + components: + - type: Transform + pos: -15.5,-70.5 + parent: 12 - uid: 10786 components: - type: Transform @@ -14899,6 +15115,11 @@ entities: linkedPorts: 10785: - DoorStatus: DoorBolt + - uid: 12234 + components: + - type: Transform + pos: -13.5,-70.5 + parent: 12 - uid: 14903 components: - type: Transform @@ -15246,18 +15467,6 @@ entities: linkedPorts: 27864: - DoorStatus: DoorBolt - - uid: 19844 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 52.5,67.5 - parent: 12 - - type: DeviceLinkSink - invokeCounter: 2 - - type: DeviceLinkSource - linkedPorts: - 18560: - - DoorStatus: DoorBolt - uid: 25678 components: - type: Transform @@ -15310,6 +15519,17 @@ entities: linkedPorts: 27232: - DoorStatus: DoorBolt + - uid: 31450 + components: + - type: Transform + pos: 53.5,66.5 + parent: 12 + - type: DeviceLinkSink + invokeCounter: 1 + - type: DeviceLinkSource + linkedPorts: + 161: + - DoorStatus: DoorBolt - proto: AirlockExternalGlassShuttleArrivals entities: - uid: 14686 @@ -15388,6 +15608,12 @@ entities: parent: 12 - proto: AirlockExternalGlassShuttleEscape entities: + - uid: 573 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -9.5,-71.5 + parent: 12 - uid: 1033 components: - type: Transform @@ -15412,12 +15638,6 @@ entities: rot: -1.5707963267948966 rad pos: -56.5,-39.5 parent: 12 - - uid: 30543 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -15.5,-67.5 - parent: 12 - proto: AirlockExternalGlassShuttleLocked entities: - uid: 552 @@ -15534,41 +15754,40 @@ entities: parent: 12 - proto: AirlockExternalLocked entities: - - uid: 530 + - uid: 161 components: - type: Transform - rot: 3.141592653589793 rad - pos: 5.5,-5.5 + pos: 52.5,64.5 parent: 12 - type: DeviceLinkSink invokeCounter: 1 - type: DeviceLinkSource linkedPorts: - 925: + 31450: - DoorStatus: DoorBolt - - uid: 925 + - uid: 530 components: - type: Transform rot: 3.141592653589793 rad - pos: 5.5,-3.5 + pos: 5.5,-5.5 parent: 12 - type: DeviceLinkSink invokeCounter: 1 - type: DeviceLinkSource linkedPorts: - 530: + 925: - DoorStatus: DoorBolt - - uid: 18560 + - uid: 925 components: - type: Transform - rot: 1.5707963267948966 rad - pos: 52.5,64.5 + rot: 3.141592653589793 rad + pos: 5.5,-3.5 parent: 12 - type: DeviceLinkSink invokeCounter: 1 - type: DeviceLinkSource linkedPorts: - 19844: + 530: - DoorStatus: DoorBolt - uid: 25663 components: @@ -15584,10 +15803,15 @@ entities: - DoorStatus: DoorBolt - proto: AirlockExternalShuttleLocked entities: - - uid: 28051 + - uid: 31079 components: - type: Transform - pos: -16.5,-70.5 + pos: -15.5,-72.5 + parent: 12 + - uid: 31080 + components: + - type: Transform + pos: -13.5,-72.5 parent: 12 - proto: AirlockFreezerLocked entities: @@ -19147,6 +19371,11 @@ entities: rot: 3.141592653589793 rad pos: -47.5,67.5 parent: 12 + - uid: 9640 + components: + - type: Transform + pos: -0.5,5.5 + parent: 12 - uid: 9899 components: - type: Transform @@ -19390,12 +19619,6 @@ entities: rot: 3.141592653589793 rad pos: -39.5,-25.5 parent: 12 - - uid: 21922 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: -0.5,1.5 - parent: 12 - uid: 22225 components: - type: Transform @@ -19840,6 +20063,12 @@ entities: parent: 12 - proto: AtmosDeviceFanDirectional entities: + - uid: 159 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -9.5,-71.5 + parent: 12 - uid: 193 components: - type: Transform @@ -19869,10 +20098,10 @@ entities: - type: Transform pos: 80.5,-33.5 parent: 12 - - uid: 745 + - uid: 563 components: - type: Transform - pos: -16.5,-70.5 + pos: -15.5,-72.5 parent: 12 - uid: 919 components: @@ -19880,12 +20109,6 @@ entities: rot: 1.5707963267948966 rad pos: 14.5,-51.5 parent: 12 - - uid: 1049 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -15.5,-67.5 - parent: 12 - uid: 1355 components: - type: Transform @@ -20054,6 +20277,11 @@ entities: rot: -1.5707963267948966 rad pos: -47.5,2.5 parent: 12 + - uid: 31081 + components: + - type: Transform + pos: -13.5,-72.5 + parent: 12 - uid: 31633 components: - type: Transform @@ -22499,6 +22727,13 @@ entities: rot: 1.5707963267948966 rad pos: 32.5,25.5 parent: 12 +- proto: BorgModuleAnomaly + entities: + - uid: 31075 + components: + - type: Transform + pos: -40.50334,-38.27384 + parent: 12 - proto: BorgModuleCable entities: - uid: 1780 @@ -22506,6 +22741,18 @@ entities: - type: Transform pos: -34.459003,-34.4371 parent: 12 + - uid: 31065 + components: + - type: Transform + pos: 57.40648,-4.2987256 + parent: 12 +- proto: BorgModuleDiagnosis + entities: + - uid: 31067 + components: + - type: Transform + pos: -1.522131,-49.55343 + parent: 12 - proto: BorgModuleFireExtinguisher entities: - uid: 2071 @@ -22544,6 +22791,11 @@ entities: - type: Transform pos: 22.528473,66.519966 parent: 12 + - uid: 31076 + components: + - type: Transform + pos: 40.50182,45.594707 + parent: 12 - proto: BorgModuleTool entities: - uid: 1781 @@ -22555,8 +22807,8 @@ entities: - uid: 1782 components: - type: Transform - rot: -62.83185307179591 rad - pos: -19.470467,-27.590706 + rot: -6.283185307179586 rad + pos: -4.4899044,50.539303 parent: 12 - proto: BoxBeaker entities: @@ -22831,17 +23083,17 @@ entities: - uid: 20863 components: - type: Transform - pos: -32.4606,65.445 + pos: -32.540394,65.31164 parent: 12 - uid: 20864 components: - type: Transform - pos: -32.497322,65.50615 + pos: -32.602894,65.63478 parent: 12 - uid: 20865 components: - type: Transform - pos: -32.4606,65.51838 + pos: -32.259144,65.467995 parent: 12 - proto: BoxLightbulb entities: @@ -23185,6 +23437,12 @@ entities: rot: -1.5707963267948966 rad pos: 1.5,-13.5 parent: 12 + - uid: 11842 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -7.5,-24.5 + parent: 12 - uid: 11866 components: - type: Transform @@ -23272,6 +23530,32 @@ entities: rot: -1.5707963267948966 rad pos: 50.5,-7.5 parent: 12 + - uid: 31379 + components: + - type: Transform + pos: -20.5,15.5 + parent: 12 + - uid: 31380 + components: + - type: Transform + pos: 12.5,19.5 + parent: 12 + - uid: 31381 + components: + - type: Transform + pos: 10.5,19.5 + parent: 12 + - uid: 31513 + components: + - type: Transform + pos: -49.5,-20.5 + parent: 12 + - uid: 31518 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -49.5,-28.5 + parent: 12 - proto: CableApcExtension entities: - uid: 14 @@ -23499,6 +23783,11 @@ entities: - type: Transform pos: 30.5,-57.5 parent: 12 + - uid: 745 + components: + - type: Transform + pos: 43.5,12.5 + parent: 12 - uid: 746 components: - type: Transform @@ -23534,6 +23823,11 @@ entities: - type: Transform pos: -30.5,-25.5 parent: 12 + - uid: 1049 + components: + - type: Transform + pos: 46.5,13.5 + parent: 12 - uid: 1054 components: - type: Transform @@ -31099,11 +31393,6 @@ entities: - type: Transform pos: 44.5,12.5 parent: 12 - - uid: 12135 - components: - - type: Transform - pos: 43.5,12.5 - parent: 12 - uid: 12136 components: - type: Transform @@ -31169,11 +31458,6 @@ entities: - type: Transform pos: 41.5,14.5 parent: 12 - - uid: 12163 - components: - - type: Transform - pos: 42.5,14.5 - parent: 12 - uid: 12164 components: - type: Transform @@ -42929,16 +43213,6 @@ entities: - type: Transform pos: 45.5,1.5 parent: 12 - - uid: 29339 - components: - - type: Transform - pos: 45.5,4.5 - parent: 12 - - uid: 29340 - components: - - type: Transform - pos: 45.5,5.5 - parent: 12 - uid: 29341 components: - type: Transform @@ -44024,6 +44298,16 @@ entities: - type: Transform pos: 10.5,-24.5 parent: 12 + - uid: 31055 + components: + - type: Transform + pos: -0.5,4.5 + parent: 12 + - uid: 31056 + components: + - type: Transform + pos: -0.5,5.5 + parent: 12 - uid: 31068 components: - type: Transform @@ -44054,6 +44338,56 @@ entities: - type: Transform pos: -52.5,-50.5 parent: 12 + - uid: 31165 + components: + - type: Transform + pos: -15.5,-68.5 + parent: 12 + - uid: 31166 + components: + - type: Transform + pos: -14.5,-68.5 + parent: 12 + - uid: 31169 + components: + - type: Transform + pos: -13.5,-68.5 + parent: 12 + - uid: 31170 + components: + - type: Transform + pos: -12.5,-68.5 + parent: 12 + - uid: 31171 + components: + - type: Transform + pos: -11.5,-68.5 + parent: 12 + - uid: 31172 + components: + - type: Transform + pos: -10.5,-68.5 + parent: 12 + - uid: 31173 + components: + - type: Transform + pos: -10.5,-69.5 + parent: 12 + - uid: 31174 + components: + - type: Transform + pos: -10.5,-70.5 + parent: 12 + - uid: 31238 + components: + - type: Transform + pos: -10.5,-71.5 + parent: 12 + - uid: 31266 + components: + - type: Transform + pos: -14.5,-69.5 + parent: 12 - uid: 31275 components: - type: Transform @@ -44184,6 +44518,16 @@ entities: - type: Transform pos: 1.5,-63.5 parent: 12 + - uid: 31349 + components: + - type: Transform + pos: -14.5,-70.5 + parent: 12 + - uid: 31353 + components: + - type: Transform + pos: -14.5,-71.5 + parent: 12 - uid: 31365 components: - type: Transform @@ -48452,11 +48796,6 @@ entities: - type: Transform pos: -1.5,35.5 parent: 12 - - uid: 11936 - components: - - type: Transform - pos: 45.5,4.5 - parent: 12 - uid: 11938 components: - type: Transform @@ -54877,31 +55216,6 @@ entities: - type: Transform pos: 4.5,-54.5 parent: 12 - - uid: 29182 - components: - - type: Transform - pos: 45.5,0.5 - parent: 12 - - uid: 29183 - components: - - type: Transform - pos: 45.5,1.5 - parent: 12 - - uid: 29184 - components: - - type: Transform - pos: 45.5,2.5 - parent: 12 - - uid: 29185 - components: - - type: Transform - pos: 45.5,3.5 - parent: 12 - - uid: 29307 - components: - - type: Transform - pos: 45.5,5.5 - parent: 12 - uid: 29426 components: - type: Transform @@ -56337,6 +56651,11 @@ entities: - type: Transform pos: 43.5,58.5 parent: 12 + - uid: 571 + components: + - type: Transform + pos: -0.5,4.5 + parent: 12 - uid: 601 components: - type: Transform @@ -59702,11 +60021,26 @@ entities: - type: Transform pos: 31.5,15.5 parent: 12 + - uid: 12056 + components: + - type: Transform + pos: -0.5,5.5 + parent: 12 - uid: 12142 components: - type: Transform pos: 37.5,18.5 parent: 12 + - uid: 12237 + components: + - type: Transform + pos: 53.5,-0.5 + parent: 12 + - uid: 12238 + components: + - type: Transform + pos: 52.5,-0.5 + parent: 12 - uid: 12292 components: - type: Transform @@ -65932,16 +66266,6 @@ entities: - type: Transform pos: -25.5,70.5 parent: 12 - - uid: 29323 - components: - - type: Transform - pos: 45.5,5.5 - parent: 12 - - uid: 29324 - components: - - type: Transform - pos: 45.5,4.5 - parent: 12 - uid: 29325 components: - type: Transform @@ -66757,6 +67081,56 @@ entities: - type: Transform pos: -5.5,-65.5 parent: 12 + - uid: 31564 + components: + - type: Transform + pos: 51.5,-0.5 + parent: 12 + - uid: 31620 + components: + - type: Transform + pos: 50.5,-0.5 + parent: 12 + - uid: 31621 + components: + - type: Transform + pos: 49.5,-0.5 + parent: 12 + - uid: 31622 + components: + - type: Transform + pos: 48.5,-0.5 + parent: 12 + - uid: 31625 + components: + - type: Transform + pos: 47.5,-0.5 + parent: 12 + - uid: 31626 + components: + - type: Transform + pos: 46.5,-0.5 + parent: 12 + - uid: 31627 + components: + - type: Transform + pos: 45.5,-0.5 + parent: 12 + - uid: 31645 + components: + - type: Transform + pos: 45.5,0.5 + parent: 12 + - uid: 31646 + components: + - type: Transform + pos: 45.5,1.5 + parent: 12 + - uid: 31647 + components: + - type: Transform + pos: 45.5,2.5 + parent: 12 - uid: 31771 components: - type: Transform @@ -67136,6 +67510,30 @@ entities: parent: 12 - proto: Carpet entities: + - uid: 2274 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 55.5,31.5 + parent: 12 + - uid: 2276 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 54.5,31.5 + parent: 12 + - uid: 2340 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 53.5,29.5 + parent: 12 + - uid: 2897 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 54.5,28.5 + parent: 12 - uid: 4023 components: - type: Transform @@ -67195,6 +67593,54 @@ entities: - type: Transform pos: 23.5,48.5 parent: 12 + - uid: 4890 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 53.5,27.5 + parent: 12 + - uid: 5385 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 53.5,28.5 + parent: 12 + - uid: 5411 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 55.5,30.5 + parent: 12 + - uid: 6288 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 56.5,29.5 + parent: 12 + - uid: 6747 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 55.5,27.5 + parent: 12 + - uid: 7338 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 53.5,30.5 + parent: 12 + - uid: 7584 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 53.5,31.5 + parent: 12 + - uid: 7620 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 56.5,31.5 + parent: 12 - uid: 10613 components: - type: Transform @@ -67213,6 +67659,48 @@ entities: rot: -1.5707963267948966 rad pos: -21.5,-0.5 parent: 12 + - uid: 12401 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 54.5,29.5 + parent: 12 + - uid: 12402 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 55.5,28.5 + parent: 12 + - uid: 12403 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 55.5,29.5 + parent: 12 + - uid: 12404 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 56.5,27.5 + parent: 12 + - uid: 12405 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 54.5,27.5 + parent: 12 + - uid: 12406 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 54.5,30.5 + parent: 12 + - uid: 12407 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 56.5,30.5 + parent: 12 - uid: 12727 components: - type: Transform @@ -67273,6 +67761,12 @@ entities: rot: -1.5707963267948966 rad pos: 56.5,36.5 parent: 12 + - uid: 13145 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 56.5,28.5 + parent: 12 - uid: 13178 components: - type: Transform @@ -68598,126 +69092,6 @@ entities: rot: -1.5707963267948966 rad pos: 56.5,32.5 parent: 12 - - uid: 13145 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 56.5,31.5 - parent: 12 - - uid: 13146 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 55.5,30.5 - parent: 12 - - uid: 13147 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 54.5,29.5 - parent: 12 - - uid: 13148 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 53.5,28.5 - parent: 12 - - uid: 13149 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 54.5,27.5 - parent: 12 - - uid: 13150 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 55.5,28.5 - parent: 12 - - uid: 13151 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 56.5,29.5 - parent: 12 - - uid: 13152 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 56.5,27.5 - parent: 12 - - uid: 13153 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 54.5,31.5 - parent: 12 - - uid: 13154 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 53.5,30.5 - parent: 12 - - uid: 13155 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 53.5,31.5 - parent: 12 - - uid: 13156 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 53.5,29.5 - parent: 12 - - uid: 13157 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 54.5,30.5 - parent: 12 - - uid: 13158 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 55.5,31.5 - parent: 12 - - uid: 13159 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 56.5,30.5 - parent: 12 - - uid: 13160 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 55.5,29.5 - parent: 12 - - uid: 13161 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 54.5,28.5 - parent: 12 - - uid: 13162 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 53.5,27.5 - parent: 12 - - uid: 13163 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 55.5,27.5 - parent: 12 - - uid: 13164 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 56.5,28.5 - parent: 12 - uid: 13170 components: - type: Transform @@ -72929,6 +73303,11 @@ entities: rot: -1.5707963267948966 rad pos: -9.5,-0.5 parent: 12 + - uid: 22182 + components: + - type: Transform + pos: 54.5,66.5 + parent: 12 - uid: 22286 components: - type: Transform @@ -73679,11 +74058,6 @@ entities: rot: 1.5707963267948966 rad pos: -48.5,46.5 parent: 12 - - uid: 25555 - components: - - type: Transform - pos: 51.5,68.5 - parent: 12 - uid: 25758 components: - type: Transform @@ -75299,16 +75673,6 @@ entities: rot: 3.141592653589793 rad pos: -41.5,66.5 parent: 12 - - uid: 30017 - components: - - type: Transform - pos: 53.5,68.5 - parent: 12 - - uid: 30018 - components: - - type: Transform - pos: 52.5,68.5 - parent: 12 - uid: 30131 components: - type: Transform @@ -75659,6 +76023,21 @@ entities: - type: Transform pos: -57.5,-43.5 parent: 12 + - uid: 31107 + components: + - type: Transform + pos: -15.5,-71.5 + parent: 12 + - uid: 31111 + components: + - type: Transform + pos: -13.5,-71.5 + parent: 12 + - uid: 31113 + components: + - type: Transform + pos: -14.5,-71.5 + parent: 12 - uid: 31270 components: - type: Transform @@ -75677,12 +76056,32 @@ entities: rot: 1.5707963267948966 rad pos: -2.5,15.5 parent: 12 + - uid: 31396 + components: + - type: Transform + pos: 57.5,66.5 + parent: 12 - uid: 31419 components: - type: Transform rot: 3.141592653589793 rad pos: -16.5,-64.5 parent: 12 + - uid: 31442 + components: + - type: Transform + pos: 54.5,67.5 + parent: 12 + - uid: 31445 + components: + - type: Transform + pos: 55.5,66.5 + parent: 12 + - uid: 31446 + components: + - type: Transform + pos: 56.5,66.5 + parent: 12 - uid: 32022 components: - type: Transform @@ -77209,6 +77608,16 @@ entities: rot: 3.141592653589793 rad pos: 15.5,-12.5 parent: 12 + - uid: 31149 + components: + - type: Transform + pos: -12.5,-68.5 + parent: 12 + - uid: 31160 + components: + - type: Transform + pos: -11.5,-68.5 + parent: 12 - uid: 31264 components: - type: Transform @@ -77319,6 +77728,11 @@ entities: - type: Transform pos: -36.5,-56.5 parent: 12 + - uid: 31159 + components: + - type: Transform + pos: -13.5,-68.5 + parent: 12 - uid: 31265 components: - type: Transform @@ -78095,10 +78509,10 @@ entities: - type: Transform pos: -52.5,-34.5 parent: 12 - - uid: 28303 + - uid: 31099 components: - type: Transform - pos: -19.5,-64.5 + pos: -12.5,-66.5 parent: 12 - uid: 31367 components: @@ -78382,6 +78796,11 @@ entities: parent: 12 - proto: ClosetEmergencyN2FilledRandom entities: + - uid: 8668 + components: + - type: Transform + pos: -13.5,-66.5 + parent: 12 - uid: 14957 components: - type: Transform @@ -78479,6 +78898,11 @@ entities: - type: Transform pos: 48.5,-36.5 parent: 12 + - uid: 11261 + components: + - type: Transform + pos: -36.5,55.5 + parent: 12 - uid: 12023 components: - type: Transform @@ -78861,6 +79285,11 @@ entities: - type: Transform pos: 40.5,12.5 parent: 12 + - uid: 12135 + components: + - type: Transform + pos: -9.5,-68.5 + parent: 12 - uid: 12246 components: - type: Transform @@ -79792,8 +80221,8 @@ entities: - uid: 5033 components: - type: Transform - rot: -119.380520836412 rad - pos: -19.723452,-30.617403 + rot: -6.283185307179586 rad + pos: -19.489866,-29.595835 parent: 12 - proto: ClothingMaskBandBlue entities: @@ -79847,8 +80276,8 @@ entities: - uid: 10900 components: - type: Transform - rot: -119.380520836412 rad - pos: -19.545881,-30.396193 + rot: -6.283185307179586 rad + pos: -19.677366,-30.367203 parent: 12 - proto: ClothingMaskBreathMedicalSecurity entities: @@ -83592,15 +84021,15 @@ entities: - type: Transform pos: -55.5,-39.5 parent: 12 - - uid: 916 + - uid: 703 components: - type: Transform - pos: -18.5,73.5 + pos: -10.5,-71.5 parent: 12 - - uid: 2340 + - uid: 916 components: - type: Transform - pos: -16.5,-67.5 + pos: -18.5,73.5 parent: 12 - uid: 7275 components: @@ -95559,6 +95988,11 @@ entities: - type: Transform pos: -33.58722,44.43513 parent: 12 + - uid: 31049 + components: + - type: Transform + pos: -40.499992,47.607746 + parent: 12 - uid: 31815 components: - type: Transform @@ -96744,6 +97178,22 @@ entities: rot: 1.5707963267948966 rad pos: 32.5,14.5 parent: 12 + - uid: 31360 + components: + - type: Transform + pos: -12.5,-68.5 + parent: 12 + - uid: 31361 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -60.5,-27.5 + parent: 12 + - uid: 31362 + components: + - type: Transform + pos: -59.5,-21.5 + parent: 12 - uid: 31514 components: - type: Transform @@ -97255,8 +97705,8 @@ entities: pos: 7.5,57.5 parent: 12 - type: FaxMachine - name: Recreation longue - destinationAddress: Recreation longue + name: Recreation lounge + destinationAddress: Recreation lounge - uid: 26279 components: - type: Transform @@ -102397,6 +102847,13 @@ entities: - type: Transform pos: -34.299114,38.455334 parent: 12 +- proto: FoodBoxPizzaFilled + entities: + - uid: 10911 + components: + - type: Transform + pos: 0.5,52.5 + parent: 12 - proto: FoodBreadMoldySlice entities: - uid: 3240 @@ -102407,7 +102864,7 @@ entities: - uid: 31123 components: - type: Transform - pos: -30.5,-57.5 + pos: -30.467789,-57.532593 parent: 12 - proto: FoodBreadPlain entities: @@ -102528,13 +102985,6 @@ entities: - type: Transform pos: 57.538345,56.66531 parent: 12 -- proto: FoodCornTrash - entities: - - uid: 31149 - components: - - type: Transform - pos: -34.115353,-56.58399 - parent: 12 - proto: FoodFrozenSnowcone entities: - uid: 22491 @@ -102654,7 +103104,7 @@ entities: - uid: 31124 components: - type: Transform - pos: -30.5,-58.5 + pos: -30.5164,-58.581932 parent: 12 - proto: FoodPizzaUraniumSlice entities: @@ -102919,7 +103369,7 @@ entities: - uid: 31133 components: - type: Transform - pos: -28.587122,-59.26843 + pos: -28.70083,-57.79198 parent: 12 - proto: Football entities: @@ -139733,11 +140183,6 @@ entities: - type: Transform pos: -46.5,0.5 parent: 12 - - uid: 8668 - components: - - type: Transform - pos: -47.5,0.5 - parent: 12 - uid: 8713 components: - type: Transform @@ -139851,7 +140296,7 @@ entities: - uid: 9971 components: - type: Transform - pos: -47.5,3.5 + pos: 60.5,65.5 parent: 12 - uid: 10060 components: @@ -140363,6 +140808,11 @@ entities: rot: 1.5707963267948966 rad pos: -3.5,8.5 parent: 12 + - uid: 10724 + components: + - type: Transform + pos: -14.5,-70.5 + parent: 12 - uid: 10725 components: - type: Transform @@ -143440,11 +143890,6 @@ entities: rot: 1.5707963267948966 rad pos: 61.5,-11.5 parent: 12 - - uid: 25558 - components: - - type: Transform - pos: 61.5,66.5 - parent: 12 - uid: 25559 components: - type: Transform @@ -143982,11 +144427,6 @@ entities: - type: Transform pos: 6.5,76.5 parent: 12 - - uid: 27240 - components: - - type: Transform - pos: 61.5,67.5 - parent: 12 - uid: 27248 components: - type: Transform @@ -145444,26 +145884,6 @@ entities: - type: Transform pos: -39.5,65.5 parent: 12 - - uid: 30971 - components: - - type: Transform - pos: -14.5,-65.5 - parent: 12 - - uid: 30972 - components: - - type: Transform - pos: -13.5,-65.5 - parent: 12 - - uid: 30973 - components: - - type: Transform - pos: -12.5,-65.5 - parent: 12 - - uid: 30977 - components: - - type: Transform - pos: -11.5,-65.5 - parent: 12 - uid: 30978 components: - type: Transform @@ -145573,6 +145993,11 @@ entities: rot: 3.141592653589793 rad pos: -56.5,-41.5 parent: 12 + - uid: 31103 + components: + - type: Transform + pos: -9.5,-70.5 + parent: 12 - uid: 31163 components: - type: Transform @@ -145645,6 +146070,11 @@ entities: - type: Transform pos: 2.5,-62.5 parent: 12 + - uid: 31441 + components: + - type: Transform + pos: 60.5,68.5 + parent: 12 - uid: 31451 components: - type: Transform @@ -146705,6 +147135,14 @@ entities: rot: -12.566370614359172 rad pos: -2.5072865,-0.47896957 parent: 12 +- proto: IntercomAll + entities: + - uid: 31057 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -0.5,1.5 + parent: 12 - proto: IntercomAssembly entities: - uid: 4791 @@ -146745,11 +147183,6 @@ entities: rot: 3.141592653589793 rad pos: -33.5,29.5 parent: 12 - - uid: 21479 - components: - - type: Transform - pos: -25.5,17.5 - parent: 12 - uid: 23622 components: - type: Transform @@ -146774,6 +147207,12 @@ entities: rot: 3.141592653589793 rad pos: -40.5,-44.5 parent: 12 + - uid: 31078 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -25.5,17.5 + parent: 12 - proto: IntercomEngineering entities: - uid: 1484 @@ -147054,8 +147493,7 @@ entities: - uid: 28698 components: - type: Transform - rot: -6.283185307179586 rad - pos: 57.513466,-4.4312396 + pos: 57.646065,-4.6948333 parent: 12 - type: GasTank toggleActionEntity: 28700 @@ -148441,6 +148879,11 @@ entities: parent: 12 - proto: LootSpawnerIndustrial entities: + - uid: 1166 + components: + - type: Transform + pos: 45.5,5.5 + parent: 12 - uid: 21945 components: - type: Transform @@ -148955,6 +149398,11 @@ entities: - type: Transform pos: -52.5,49.5 parent: 12 + - uid: 31359 + components: + - type: Transform + pos: -11.5,-68.5 + parent: 12 - uid: 31676 components: - type: Transform @@ -149072,6 +149520,11 @@ entities: - type: Transform pos: -39.5,-50.5 parent: 12 + - uid: 31355 + components: + - type: Transform + pos: -11.5,-66.5 + parent: 12 - uid: 31372 components: - type: Transform @@ -149214,6 +149667,11 @@ entities: - type: Transform pos: 42.5,-42.5 parent: 12 + - uid: 29324 + components: + - type: Transform + pos: -10.5,-66.5 + parent: 12 - uid: 29620 components: - type: Transform @@ -149513,6 +149971,11 @@ entities: - type: Transform pos: -11.468502,-43.455402 parent: 12 + - uid: 31161 + components: + - type: Transform + pos: -11.5,-71.5 + parent: 12 - uid: 31323 components: - type: Transform @@ -149677,40 +150140,52 @@ entities: rot: -1.5707963267948966 rad pos: 8.5,-40.5 parent: 12 - - uid: 4260 + - uid: 9395 components: - type: Transform - rot: -1.5707963267948966 rad - pos: 6.5,-40.5 + pos: -21.5,-27.5 parent: 12 - - uid: 4570 + - uid: 10736 components: - type: Transform rot: -1.5707963267948966 rad pos: 4.5,-41.5 parent: 12 - - uid: 5042 + - uid: 10737 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 6.5,-40.5 + parent: 12 + - uid: 10738 components: - type: Transform rot: -1.5707963267948966 rad pos: 4.5,-40.5 parent: 12 - - uid: 5709 + - uid: 10939 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 6.5,-44.5 + parent: 12 + - uid: 11000 components: - type: Transform rot: -1.5707963267948966 rad pos: 4.5,-43.5 parent: 12 - - uid: 6747 + - uid: 11001 components: - type: Transform rot: -1.5707963267948966 rad - pos: 6.5,-41.5 + pos: 6.5,-43.5 parent: 12 - - uid: 9395 + - uid: 11220 components: - type: Transform - pos: -21.5,-27.5 + rot: -1.5707963267948966 rad + pos: 6.5,-41.5 parent: 12 - uid: 12394 components: @@ -149760,24 +150235,12 @@ entities: rot: -1.5707963267948966 rad pos: 8.5,-43.5 parent: 12 - - uid: 26149 + - uid: 31077 components: - type: Transform rot: -1.5707963267948966 rad pos: 4.5,-44.5 parent: 12 - - uid: 26150 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 6.5,-43.5 - parent: 12 - - uid: 26152 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 6.5,-44.5 - parent: 12 - proto: MouseTimedSpawner entities: - uid: 890 @@ -153926,6 +154389,12 @@ entities: rot: 1.5707963267948966 rad pos: -12.5,74.5 parent: 12 + - uid: 11221 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -34.5,47.5 + parent: 12 - uid: 11223 components: - type: Transform @@ -153938,6 +154407,12 @@ entities: rot: 1.5707963267948966 rad pos: -13.5,-50.5 parent: 12 + - uid: 11796 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -33.5,57.5 + parent: 12 - uid: 12016 components: - type: Transform @@ -154735,18 +155210,6 @@ entities: rot: 1.5707963267948966 rad pos: -39.5,42.5 parent: 12 - - uid: 19034 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -36.5,44.5 - parent: 12 - - uid: 19051 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -34.5,46.5 - parent: 12 - uid: 19052 components: - type: Transform @@ -154817,30 +155280,12 @@ entities: rot: -1.5707963267948966 rad pos: -38.5,50.5 parent: 12 - - uid: 19355 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -34.5,54.5 - parent: 12 - uid: 19356 components: - type: Transform rot: -1.5707963267948966 rad pos: -34.5,52.5 parent: 12 - - uid: 19357 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -36.5,61.5 - parent: 12 - - uid: 19358 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -33.5,61.5 - parent: 12 - uid: 19364 components: - type: Transform @@ -155159,6 +155604,12 @@ entities: - type: Transform pos: -50.5,22.5 parent: 12 + - uid: 31050 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -36.5,44.5 + parent: 12 - uid: 31472 components: - type: Transform @@ -155714,6 +156165,11 @@ entities: rot: 1.5707963267948966 rad pos: 57.5,11.5 parent: 12 + - uid: 11802 + components: + - type: Transform + pos: -31.5,60.5 + parent: 12 - uid: 12005 components: - type: Transform @@ -155724,6 +156180,12 @@ entities: - type: Transform pos: 50.5,20.5 parent: 12 + - uid: 12163 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -14.5,-71.5 + parent: 12 - uid: 12291 components: - type: Transform @@ -155927,12 +156389,6 @@ entities: rot: 3.141592653589793 rad pos: -35.5,64.5 parent: 12 - - uid: 19871 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -29.5,60.5 - parent: 12 - uid: 21082 components: - type: Transform @@ -156304,6 +156760,12 @@ entities: - type: Transform pos: 5.5,-59.5 parent: 12 + - uid: 31354 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -11.5,-70.5 + parent: 12 - uid: 31508 components: - type: Transform @@ -156324,12 +156786,6 @@ entities: parent: 12 - proto: PoweredSmallLightEmpty entities: - - uid: 9391 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: -7.5,-23.5 - parent: 12 - uid: 28973 components: - type: Transform @@ -156351,6 +156807,12 @@ entities: powerLoad: 60 - type: DamageOnInteract isDamageActive: False + - uid: 31363 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -6.5,-22.5 + parent: 12 - proto: Protolathe entities: - uid: 2321 @@ -156412,6 +156874,12 @@ entities: - type: Transform pos: -35.5,-37.5 parent: 12 + - uid: 2171 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 45.5,5.5 + parent: 12 - uid: 2645 components: - type: Transform @@ -156621,12 +157089,6 @@ entities: rot: 1.5707963267948966 rad pos: 33.5,-6.5 parent: 12 - - uid: 12056 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -19.5,-28.5 - parent: 12 - uid: 12265 components: - type: Transform @@ -157131,6 +157593,17 @@ entities: - type: Transform pos: -53.5,-47.5 parent: 12 + - uid: 31086 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -10.5,-66.5 + parent: 12 + - uid: 31114 + components: + - type: Transform + pos: -11.5,-71.5 + parent: 12 - uid: 31261 components: - type: Transform @@ -158027,6 +158500,11 @@ entities: - type: Transform pos: 45.5,6.5 parent: 12 + - uid: 9391 + components: + - type: Transform + pos: -12.5,-71.5 + parent: 12 - uid: 13556 components: - type: Transform @@ -158178,6 +158656,12 @@ entities: - type: Transform pos: -26.5,73.5 parent: 12 + - uid: 31098 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -14.5,-66.5 + parent: 12 - uid: 31717 components: - type: Transform @@ -158188,11 +158672,6 @@ entities: - type: Transform pos: -4.5,-64.5 parent: 12 - - uid: 31719 - components: - - type: Transform - pos: -15.5,-65.5 - parent: 12 - uid: 31720 components: - type: Transform @@ -158240,6 +158719,11 @@ entities: parent: 12 - proto: RandomPosterLegit entities: + - uid: 726 + components: + - type: Transform + pos: -18.5,-29.5 + parent: 12 - uid: 2131 components: - type: Transform @@ -158996,11 +159480,6 @@ entities: - type: Transform pos: 56.5,-28.5 parent: 12 - - uid: 24419 - components: - - type: Transform - pos: 63.5,-23.5 - parent: 12 - uid: 24420 components: - type: Transform @@ -159286,6 +159765,16 @@ entities: - type: Transform pos: -38.5,-54.5 parent: 12 + - uid: 31356 + components: + - type: Transform + pos: -10.5,-70.5 + parent: 12 + - uid: 31562 + components: + - type: Transform + pos: 61.5,-25.5 + parent: 12 - uid: 31582 components: - type: Transform @@ -160498,11 +160987,6 @@ entities: rot: -1.5707963267948966 rad pos: 5.5,24.5 parent: 12 - - uid: 4151 - components: - - type: Transform - pos: -47.5,3.5 - parent: 12 - uid: 4175 components: - type: Transform @@ -162740,7 +163224,7 @@ entities: - uid: 12191 components: - type: Transform - pos: -47.5,0.5 + pos: -14.5,-70.5 parent: 12 - uid: 12252 components: @@ -165006,26 +165490,6 @@ entities: - type: Transform pos: -31.5,-60.5 parent: 12 - - uid: 30970 - components: - - type: Transform - pos: -14.5,-65.5 - parent: 12 - - uid: 30974 - components: - - type: Transform - pos: -13.5,-65.5 - parent: 12 - - uid: 30975 - components: - - type: Transform - pos: -12.5,-65.5 - parent: 12 - - uid: 30976 - components: - - type: Transform - pos: -11.5,-65.5 - parent: 12 - uid: 30980 components: - type: Transform @@ -165041,6 +165505,11 @@ entities: - type: Transform pos: -54.5,-46.5 parent: 12 + - uid: 31105 + components: + - type: Transform + pos: -9.5,-70.5 + parent: 12 - uid: 31141 components: - type: Transform @@ -165376,8 +165845,8 @@ entities: - uid: 11312 components: - type: Transform - rot: -62.83185307179591 rad - pos: -19.456577,-27.187649 + rot: -6.283185307179586 rad + pos: -19.510698,-27.229607 parent: 12 - uid: 13828 components: @@ -165420,8 +165889,8 @@ entities: - uid: 5125 components: - type: Transform - rot: -62.83185307179591 rad - pos: -19.623243,-27.84088 + rot: -6.283185307179586 rad + pos: -19.458616,-27.615292 parent: 12 - uid: 13829 components: @@ -165822,14 +166291,12 @@ entities: - uid: 23173 components: - type: Transform - rot: -43.98229715025713 rad - pos: 53.468582,-3.3849072 + pos: 53.37523,-3.5169325 parent: 12 - uid: 26101 components: - type: Transform - rot: -43.98229715025713 rad - pos: 57.301918,-5.261206 + pos: 57.385647,-5.3932357 parent: 12 - uid: 31043 components: @@ -165899,8 +166366,7 @@ entities: - uid: 8439 components: - type: Transform - rot: -43.98229715025713 rad - pos: 57.63525,-5.083999 + pos: 53.677315,-3.3188787 parent: 12 - uid: 8898 components: @@ -166985,6 +167451,48 @@ entities: linkedPorts: 31258: - Pressed: DoorBolt + - uid: 31374 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -7.5,-24.5 + parent: 12 + - type: DeviceLinkSource + linkedPorts: + 9763: + - Pressed: Toggle + 9764: + - Pressed: Toggle + - uid: 31383 + components: + - type: Transform + pos: 12.5,19.5 + parent: 12 + - type: DeviceLinkSource + linkedPorts: + 12674: + - Pressed: Toggle + 1850: + - Pressed: Toggle + 4384: + - Pressed: Toggle + 12675: + - Pressed: Toggle + - uid: 31385 + components: + - type: Transform + pos: 10.5,19.5 + parent: 12 + - type: DeviceLinkSource + linkedPorts: + 9407: + - Pressed: Toggle + 15681: + - Pressed: Toggle + 10993: + - Pressed: Toggle + 11326: + - Pressed: Toggle - proto: SignAnomaly entities: - uid: 32031 @@ -170194,6 +170702,11 @@ entities: - type: Transform pos: -44.5,-15.5 parent: 12 + - uid: 31106 + components: + - type: Transform + pos: -14.5,-68.5 + parent: 12 - proto: SpawnMobParrot entities: - uid: 6237 @@ -171016,6 +171529,16 @@ entities: rot: 3.141592653589793 rad pos: -36.5,62.5 parent: 12 + - uid: 11270 + components: + - type: Transform + pos: -35.5,45.5 + parent: 12 + - uid: 11521 + components: + - type: Transform + pos: -34.5,45.5 + parent: 12 - uid: 13050 components: - type: Transform @@ -172170,11 +172693,6 @@ entities: - type: Transform pos: 4.5,-16.5 parent: 12 - - uid: 4890 - components: - - type: Transform - pos: 45.5,5.5 - parent: 12 - uid: 7904 components: - type: Transform @@ -172628,6 +173146,38 @@ entities: - SurveillanceCameraCommand nameSet: True id: AI exterior + - uid: 31447 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -51.5,38.5 + parent: 12 + - type: SurveillanceCamera + setupAvailableNetworks: + - SurveillanceCameraCommand + nameSet: True + id: Command camera room + - uid: 31512 + components: + - type: Transform + pos: -42.5,-20.5 + parent: 12 + - type: SurveillanceCamera + setupAvailableNetworks: + - SurveillanceCameraCommand + nameSet: True + id: RD server room + - uid: 31519 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -36.5,-19.5 + parent: 12 + - type: SurveillanceCamera + setupAvailableNetworks: + - SurveillanceCameraCommand + nameSet: True + id: RD's room - uid: 31748 components: - type: Transform @@ -172677,6 +173227,27 @@ entities: - SurveillanceCameraEngineering nameSet: True id: Atmos lockers/engi hallway + - uid: 7716 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 1.5,18.5 + parent: 12 + - type: SurveillanceCamera + setupAvailableNetworks: + - SurveillanceCameraEngineering + nameSet: True + id: TEG North + - uid: 9766 + components: + - type: Transform + pos: 56.5,66.5 + parent: 12 + - type: SurveillanceCamera + setupAvailableNetworks: + - SurveillanceCameraEngineering + nameSet: True + id: Northeast airlock exterior - uid: 9821 components: - type: Transform @@ -172751,17 +173322,6 @@ entities: - SurveillanceCameraEngineering nameSet: True id: Break room - - uid: 26133 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: 48.5,1.5 - parent: 12 - - type: SurveillanceCamera - setupAvailableNetworks: - - SurveillanceCameraEngineering - nameSet: True - id: Containment entrance - uid: 26139 components: - type: Transform @@ -172945,6 +173505,60 @@ entities: - SurveillanceCameraEngineering nameSet: True id: Southeast solars 2 + - uid: 31448 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -56.5,47.5 + parent: 12 + - type: SurveillanceCamera + setupAvailableNetworks: + - SurveillanceCameraEngineering + nameSet: True + id: Northwest solars + - uid: 31471 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 11.5,28.5 + parent: 12 + - type: SurveillanceCamera + setupAvailableNetworks: + - SurveillanceCameraEngineering + nameSet: True + id: TEG exterior + - uid: 31511 + components: + - type: Transform + pos: -36.5,-10.5 + parent: 12 + - type: SurveillanceCamera + setupAvailableNetworks: + - SurveillanceCameraEngineering + nameSet: True + id: Shuttle constuction dock + - uid: 31529 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -55.5,-51.5 + parent: 12 + - type: SurveillanceCamera + setupAvailableNetworks: + - SurveillanceCameraEngineering + nameSet: True + id: Southwest Solars 1 + - uid: 31530 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -23.5,-68.5 + parent: 12 + - type: SurveillanceCamera + setupAvailableNetworks: + - SurveillanceCameraEngineering + nameSet: True + id: Southwest Solars 2 - uid: 31882 components: - type: Transform @@ -172979,16 +173593,6 @@ entities: - SurveillanceCameraGeneral nameSet: True id: Arrivals west - - uid: 2897 - components: - - type: Transform - pos: 35.5,22.5 - parent: 12 - - type: SurveillanceCamera - setupAvailableNetworks: - - SurveillanceCameraGeneral - nameSet: True - id: Hallway east - uid: 2901 components: - type: Transform @@ -173087,6 +173691,28 @@ entities: - SurveillanceCameraGeneral nameSet: True id: South evac A + - uid: 8442 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 55.5,-43.5 + parent: 12 + - type: SurveillanceCamera + setupAvailableNetworks: + - SurveillanceCameraGeneral + nameSet: True + id: Southeast dock + - uid: 8454 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 6.5,70.5 + parent: 12 + - type: SurveillanceCamera + setupAvailableNetworks: + - SurveillanceCameraGeneral + nameSet: True + id: Nitrogen atmosphere room - uid: 9836 components: - type: Transform @@ -173108,6 +173734,17 @@ entities: - SurveillanceCameraGeneral nameSet: True id: Evac north + - uid: 12400 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 0.5,34.5 + parent: 12 + - type: SurveillanceCamera + setupAvailableNetworks: + - SurveillanceCameraGeneral + nameSet: True + id: Pool south - uid: 12672 components: - type: Transform @@ -173237,17 +173874,6 @@ entities: - SurveillanceCameraGeneral nameSet: True id: Ship construction tool room - - uid: 25396 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 37.5,18.5 - parent: 12 - - type: SurveillanceCamera - setupAvailableNetworks: - - SurveillanceCameraGeneral - nameSet: True - id: Disposals - uid: 26895 components: - type: Transform @@ -173313,6 +173939,47 @@ entities: - SurveillanceCameraGeneral nameSet: True id: South Evac B + - uid: 31047 + components: + - type: Transform + pos: 18.5,70.5 + parent: 12 + - type: SurveillanceCamera + setupAvailableNetworks: + - SurveillanceCameraGeneral + nameSet: True + id: Arrivals shuttle dock + - uid: 31394 + components: + - type: Transform + pos: 44.5,43.5 + parent: 12 + - type: SurveillanceCamera + setupAvailableNetworks: + - SurveillanceCameraGeneral + nameSet: True + id: Tools exterior + - uid: 31449 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 2.5,28.5 + parent: 12 + - type: SurveillanceCamera + setupAvailableNetworks: + - SurveillanceCameraGeneral + nameSet: True + id: Bee room + - uid: 31473 + components: + - type: Transform + pos: 21.5,26.5 + parent: 12 + - type: SurveillanceCamera + setupAvailableNetworks: + - SurveillanceCameraGeneral + nameSet: True + id: Observitory - uid: 31500 components: - type: Transform @@ -173334,39 +174001,38 @@ entities: - SurveillanceCameraGeneral nameSet: True id: Crossroad - - uid: 31749 + - uid: 31557 components: - type: Transform - rot: -1.5707963267948966 rad - pos: -17.5,-0.5 + pos: 41.5,-32.5 parent: 12 - type: SurveillanceCamera setupAvailableNetworks: - SurveillanceCameraGeneral nameSet: True - id: Law office exterior - - uid: 31750 + id: Vending machine room + - uid: 31749 components: - type: Transform rot: -1.5707963267948966 rad - pos: -16.5,-12.5 + pos: -17.5,-0.5 parent: 12 - type: SurveillanceCamera setupAvailableNetworks: - SurveillanceCameraGeneral nameSet: True - id: Gorilla and penguin enclosures - - uid: 32105 + id: Law office exterior + - uid: 31750 components: - type: Transform - rot: 3.141592653589793 rad - pos: 57.5,64.5 + rot: -1.5707963267948966 rad + pos: -16.5,-12.5 parent: 12 - type: SurveillanceCamera setupAvailableNetworks: - SurveillanceCameraGeneral nameSet: True - id: Project room + id: Gorilla and penguin enclosures - proto: SurveillanceCameraMedical entities: - uid: 3961 @@ -173486,6 +174152,28 @@ entities: - SurveillanceCameraMedical nameSet: True id: Surgery + - uid: 31531 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -3.5,-53.5 + parent: 12 + - type: SurveillanceCamera + setupAvailableNetworks: + - SurveillanceCameraMedical + nameSet: True + id: Genetics + - uid: 31556 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 1.5,-43.5 + parent: 12 + - type: SurveillanceCamera + setupAvailableNetworks: + - SurveillanceCameraMedical + nameSet: True + id: Morgue and Surgery entrance - uid: 31761 components: - type: Transform @@ -173851,6 +174539,17 @@ entities: - type: SurveillanceCamera setupAvailableNetworks: - SurveillanceCameraService + - uid: 2154 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 44.5,21.5 + parent: 12 + - type: SurveillanceCamera + setupAvailableNetworks: + - SurveillanceCameraService + nameSet: True + id: Janitor closet - uid: 5161 components: - type: Transform @@ -173876,13 +174575,14 @@ entities: - uid: 12287 components: - type: Transform - pos: 46.5,16.5 + rot: 1.5707963267948966 rad + pos: 41.5,18.5 parent: 12 - type: SurveillanceCamera setupAvailableNetworks: - SurveillanceCameraService nameSet: True - id: Janitor's closet + id: Disposals - uid: 12904 components: - type: Transform @@ -174173,6 +174873,17 @@ entities: - SurveillanceCameraSupply nameSet: True id: Cargo front + - uid: 12009 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 63.5,-14.5 + parent: 12 + - type: SurveillanceCamera + setupAvailableNetworks: + - SurveillanceCameraSupply + nameSet: True + id: Cargo dock - uid: 12642 components: - type: Transform @@ -174934,6 +175645,12 @@ entities: - type: Transform pos: 52.5,46.5 parent: 12 + - uid: 10726 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 0.5,52.5 + parent: 12 - uid: 10888 components: - type: Transform @@ -177196,6 +177913,12 @@ entities: - type: Transform pos: -35.5,-20.5 parent: 12 + - uid: 2271 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 55.5,27.5 + parent: 12 - uid: 2373 components: - type: Transform @@ -177230,16 +177953,58 @@ entities: rot: 3.141592653589793 rad pos: 21.5,28.5 parent: 12 + - uid: 4151 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 54.5,28.5 + parent: 12 - uid: 4154 components: - type: Transform pos: 13.5,-35.5 parent: 12 + - uid: 4260 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 54.5,29.5 + parent: 12 + - uid: 4481 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 54.5,27.5 + parent: 12 + - uid: 4570 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 55.5,29.5 + parent: 12 - uid: 4891 components: - type: Transform pos: 17.5,49.5 parent: 12 + - uid: 5042 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 55.5,30.5 + parent: 12 + - uid: 5709 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 55.5,28.5 + parent: 12 + - uid: 5911 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 54.5,30.5 + parent: 12 - uid: 6189 components: - type: Transform @@ -177325,54 +178090,6 @@ entities: rot: 1.5707963267948966 rad pos: 43.5,29.5 parent: 12 - - uid: 12400 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 54.5,27.5 - parent: 12 - - uid: 12401 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 54.5,28.5 - parent: 12 - - uid: 12402 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 54.5,29.5 - parent: 12 - - uid: 12403 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 54.5,30.5 - parent: 12 - - uid: 12404 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 55.5,27.5 - parent: 12 - - uid: 12405 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 55.5,28.5 - parent: 12 - - uid: 12406 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 55.5,29.5 - parent: 12 - - uid: 12407 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 55.5,30.5 - parent: 12 - uid: 12657 components: - type: Transform @@ -178836,7 +179553,7 @@ entities: - uid: 31148 components: - type: Transform - pos: -29.544153,-55.516808 + pos: -29.534164,-55.470924 parent: 12 - proto: TrashBananaPeel entities: @@ -179632,6 +180349,11 @@ entities: - type: Transform pos: 35.5,22.5 parent: 12 + - uid: 13146 + components: + - type: Transform + pos: 47.5,1.5 + parent: 12 - uid: 14992 components: - type: Transform @@ -179652,6 +180374,11 @@ entities: - type: Transform pos: 15.5,54.5 parent: 12 + - uid: 31561 + components: + - type: Transform + pos: 46.5,-32.5 + parent: 12 - proto: VendingMachineClothing entities: - uid: 9091 @@ -180111,11 +180838,6 @@ entities: parent: 12 - proto: VendingMachineSovietSoda entities: - - uid: 4481 - components: - - type: Transform - pos: 47.5,1.5 - parent: 12 - uid: 14953 components: - type: Transform @@ -180312,8 +181034,7 @@ entities: - uid: 27 components: - type: Transform - rot: -1.5707963267948966 rad - pos: -3.5,46.5 + pos: 52.5,67.5 parent: 12 - uid: 29 components: @@ -180636,24 +181357,12 @@ entities: rot: 1.5707963267948966 rad pos: 3.5,-9.5 parent: 12 - - uid: 159 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 4.5,-8.5 - parent: 12 - uid: 160 components: - type: Transform rot: 1.5707963267948966 rad pos: 4.5,-9.5 parent: 12 - - uid: 161 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 4.5,-7.5 - parent: 12 - uid: 163 components: - type: Transform @@ -181019,24 +181728,12 @@ entities: rot: -1.5707963267948966 rad pos: -4.5,6.5 parent: 12 - - uid: 571 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 2.5,6.5 - parent: 12 - uid: 572 components: - type: Transform rot: -1.5707963267948966 rad pos: -3.5,6.5 parent: 12 - - uid: 573 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -2.5,6.5 - parent: 12 - uid: 575 components: - type: Transform @@ -181200,11 +181897,6 @@ entities: - type: Transform pos: 39.5,-10.5 parent: 12 - - uid: 703 - components: - - type: Transform - pos: -15.5,-69.5 - parent: 12 - uid: 709 components: - type: Transform @@ -181250,11 +181942,6 @@ entities: - type: Transform pos: 39.5,-8.5 parent: 12 - - uid: 726 - components: - - type: Transform - pos: -56.5,-20.5 - parent: 12 - uid: 736 components: - type: Transform @@ -181503,12 +182190,6 @@ entities: rot: 1.5707963267948966 rad pos: -47.5,50.5 parent: 12 - - uid: 1166 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -46.5,-17.5 - parent: 12 - uid: 1167 components: - type: Transform @@ -181604,23 +182285,11 @@ entities: rot: -1.5707963267948966 rad pos: 3.5,-0.5 parent: 12 - - uid: 2154 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 0.5,6.5 - parent: 12 - uid: 2169 components: - type: Transform pos: 26.5,1.5 parent: 12 - - uid: 2171 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -5.5,4.5 - parent: 12 - uid: 2173 components: - type: Transform @@ -181653,36 +182322,18 @@ entities: - type: Transform pos: 26.5,-9.5 parent: 12 - - uid: 2271 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -5.5,-0.5 - parent: 12 - uid: 2273 components: - type: Transform rot: -1.5707963267948966 rad pos: -5.5,-1.5 parent: 12 - - uid: 2274 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -5.5,2.5 - parent: 12 - uid: 2275 components: - type: Transform rot: -1.5707963267948966 rad pos: -5.5,-2.5 parent: 12 - - uid: 2276 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -5.5,3.5 - parent: 12 - uid: 2328 components: - type: Transform @@ -182634,11 +183285,6 @@ entities: rot: 1.5707963267948966 rad pos: 60.5,-47.5 parent: 12 - - uid: 5911 - components: - - type: Transform - pos: -6.5,-13.5 - parent: 12 - uid: 5916 components: - type: Transform @@ -182738,11 +183384,6 @@ entities: rot: 1.5707963267948966 rad pos: -61.5,-16.5 parent: 12 - - uid: 6288 - components: - - type: Transform - pos: -17.5,-67.5 - parent: 12 - uid: 6327 components: - type: Transform @@ -182892,12 +183533,6 @@ entities: rot: -1.5707963267948966 rad pos: 26.5,16.5 parent: 12 - - uid: 7338 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 27.5,18.5 - parent: 12 - uid: 7363 components: - type: Transform @@ -183137,11 +183772,6 @@ entities: rot: -1.5707963267948966 rad pos: 61.5,-27.5 parent: 12 - - uid: 7584 - components: - - type: Transform - pos: -9.5,-3.5 - parent: 12 - uid: 7587 components: - type: Transform @@ -183243,11 +183873,6 @@ entities: rot: -1.5707963267948966 rad pos: 60.5,-39.5 parent: 12 - - uid: 7620 - components: - - type: Transform - pos: -7.5,-1.5 - parent: 12 - uid: 7667 components: - type: Transform @@ -183350,11 +183975,6 @@ entities: rot: -1.5707963267948966 rad pos: 82.5,-36.5 parent: 12 - - uid: 7716 - components: - - type: Transform - pos: -7.5,-0.5 - parent: 12 - uid: 7728 components: - type: Transform @@ -183439,22 +184059,11 @@ entities: - type: Transform pos: -9.5,-8.5 parent: 12 - - uid: 8442 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 4.5,2.5 - parent: 12 - uid: 8450 components: - type: Transform pos: -7.5,-13.5 parent: 12 - - uid: 8454 - components: - - type: Transform - pos: -7.5,-12.5 - parent: 12 - uid: 8455 components: - type: Transform @@ -183620,11 +184229,6 @@ entities: rot: 3.141592653589793 rad pos: 52.5,-44.5 parent: 12 - - uid: 9120 - components: - - type: Transform - pos: -9.5,-9.5 - parent: 12 - uid: 9121 components: - type: Transform @@ -183743,7 +184347,7 @@ entities: - uid: 9506 components: - type: Transform - pos: -51.5,-11.5 + pos: -47.5,0.5 parent: 12 - uid: 9508 components: @@ -183778,12 +184382,6 @@ entities: rot: -1.5707963267948966 rad pos: 17.5,13.5 parent: 12 - - uid: 9640 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: 17.5,23.5 - parent: 12 - uid: 9642 components: - type: Transform @@ -183824,12 +184422,6 @@ entities: rot: 3.141592653589793 rad pos: 47.5,-6.5 parent: 12 - - uid: 9766 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 4.5,-1.5 - parent: 12 - uid: 9767 components: - type: Transform @@ -183865,8 +184457,7 @@ entities: - uid: 10040 components: - type: Transform - rot: -1.5707963267948966 rad - pos: 4.5,4.5 + pos: -12.5,-70.5 parent: 12 - uid: 10041 components: @@ -183874,11 +184465,6 @@ entities: rot: -1.5707963267948966 rad pos: 4.5,5.5 parent: 12 - - uid: 10042 - components: - - type: Transform - pos: -6.5,-0.5 - parent: 12 - uid: 10119 components: - type: Transform @@ -184346,18 +184932,6 @@ entities: rot: 1.5707963267948966 rad pos: -12.5,26.5 parent: 12 - - uid: 10724 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -13.5,26.5 - parent: 12 - - uid: 10726 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -13.5,24.5 - parent: 12 - uid: 10729 components: - type: Transform @@ -184399,24 +184973,6 @@ entities: rot: 1.5707963267948966 rad pos: -9.5,22.5 parent: 12 - - uid: 10736 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -14.5,26.5 - parent: 12 - - uid: 10737 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -14.5,25.5 - parent: 12 - - uid: 10738 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -14.5,24.5 - parent: 12 - uid: 10781 components: - type: Transform @@ -184484,18 +185040,6 @@ entities: - type: Transform pos: 38.5,5.5 parent: 12 - - uid: 10911 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -61.5,-14.5 - parent: 12 - - uid: 10939 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 25.5,13.5 - parent: 12 - uid: 10951 components: - type: Transform @@ -184514,18 +185058,6 @@ entities: rot: 1.5707963267948966 rad pos: 5.5,22.5 parent: 12 - - uid: 11000 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -5.5,47.5 - parent: 12 - - uid: 11001 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -3.5,47.5 - parent: 12 - uid: 11017 components: - type: Transform @@ -184734,18 +185266,6 @@ entities: rot: -1.5707963267948966 rad pos: 8.5,29.5 parent: 12 - - uid: 11220 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 9.5,29.5 - parent: 12 - - uid: 11221 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 10.5,29.5 - parent: 12 - uid: 11222 components: - type: Transform @@ -184794,12 +185314,6 @@ entities: rot: -1.5707963267948966 rad pos: 19.5,23.5 parent: 12 - - uid: 11261 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 19.5,24.5 - parent: 12 - uid: 11262 components: - type: Transform @@ -184842,12 +185356,6 @@ entities: rot: -1.5707963267948966 rad pos: 19.5,22.5 parent: 12 - - uid: 11270 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 20.5,22.5 - parent: 12 - uid: 11272 components: - type: Transform @@ -184955,11 +185463,6 @@ entities: - type: Transform pos: 50.5,7.5 parent: 12 - - uid: 11521 - components: - - type: Transform - pos: 42.5,15.5 - parent: 12 - uid: 11522 components: - type: Transform @@ -185115,11 +185618,6 @@ entities: - type: Transform pos: 20.5,38.5 parent: 12 - - uid: 11796 - components: - - type: Transform - pos: 11.5,30.5 - parent: 12 - uid: 11797 components: - type: Transform @@ -185135,11 +185633,6 @@ entities: - type: Transform pos: 11.5,33.5 parent: 12 - - uid: 11802 - components: - - type: Transform - pos: 15.5,34.5 - parent: 12 - uid: 11803 components: - type: Transform @@ -185248,11 +185741,6 @@ entities: rot: -1.5707963267948966 rad pos: 26.5,13.5 parent: 12 - - uid: 12009 - components: - - type: Transform - pos: 42.5,14.5 - parent: 12 - uid: 12011 components: - type: Transform @@ -185262,7 +185750,7 @@ entities: - uid: 12100 components: - type: Transform - pos: 43.5,13.5 + pos: -47.5,3.5 parent: 12 - uid: 12217 components: @@ -185384,6 +185872,11 @@ entities: - type: Transform pos: -35.5,-51.5 parent: 12 + - uid: 13161 + components: + - type: Transform + pos: -17.5,-69.5 + parent: 12 - uid: 13197 components: - type: Transform @@ -185446,24 +185939,6 @@ entities: rot: -1.5707963267948966 rad pos: 53.5,65.5 parent: 12 - - uid: 14179 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 53.5,66.5 - parent: 12 - - uid: 14180 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 53.5,67.5 - parent: 12 - - uid: 14182 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 51.5,67.5 - parent: 12 - uid: 14187 components: - type: Transform @@ -185942,30 +186417,12 @@ entities: rot: -1.5707963267948966 rad pos: -8.5,35.5 parent: 12 - - uid: 15549 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -14.5,29.5 - parent: 12 - - uid: 15550 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -14.5,30.5 - parent: 12 - uid: 15551 components: - type: Transform rot: -1.5707963267948966 rad pos: -14.5,31.5 parent: 12 - - uid: 15552 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -13.5,29.5 - parent: 12 - uid: 15554 components: - type: Transform @@ -186055,11 +186512,6 @@ entities: - type: Transform pos: -8.5,25.5 parent: 12 - - uid: 15703 - components: - - type: Transform - pos: -21.5,30.5 - parent: 12 - uid: 15708 components: - type: Transform @@ -186211,24 +186663,6 @@ entities: - type: Transform pos: -30.5,12.5 parent: 12 - - uid: 16797 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -60.5,-11.5 - parent: 12 - - uid: 16799 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -4.5,47.5 - parent: 12 - - uid: 16800 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -5.5,46.5 - parent: 12 - uid: 17199 components: - type: Transform @@ -186406,12 +186840,6 @@ entities: - type: Transform pos: -27.5,11.5 parent: 12 - - uid: 17541 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: 51.5,66.5 - parent: 12 - uid: 17755 components: - type: Transform @@ -186661,28 +187089,12 @@ entities: - type: Transform pos: -52.5,76.5 parent: 12 - - uid: 17972 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -5.5,6.5 - parent: 12 - uid: 18558 components: - type: Transform rot: -1.5707963267948966 rad pos: 42.5,-43.5 parent: 12 - - uid: 18569 - components: - - type: Transform - pos: 59.5,65.5 - parent: 12 - - uid: 18572 - components: - - type: Transform - pos: 59.5,60.5 - parent: 12 - uid: 18654 components: - type: Transform @@ -187033,12 +187445,6 @@ entities: rot: -1.5707963267948966 rad pos: 4.5,3.5 parent: 12 - - uid: 19199 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 4.5,-0.5 - parent: 12 - uid: 19206 components: - type: Transform @@ -187592,12 +187998,6 @@ entities: rot: 1.5707963267948966 rad pos: 51.5,65.5 parent: 12 - - uid: 19847 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -60.5,-12.5 - parent: 12 - uid: 19862 components: - type: Transform @@ -187798,12 +188198,6 @@ entities: - type: Transform pos: -30.5,62.5 parent: 12 - - uid: 22182 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -8.5,-1.5 - parent: 12 - uid: 22183 components: - type: Transform @@ -187816,24 +188210,12 @@ entities: rot: -1.5707963267948966 rad pos: -8.5,-2.5 parent: 12 - - uid: 22185 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -8.5,-9.5 - parent: 12 - uid: 22186 components: - type: Transform rot: -1.5707963267948966 rad pos: -8.5,-10.5 parent: 12 - - uid: 22187 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -8.5,-11.5 - parent: 12 - uid: 22190 components: - type: Transform @@ -187880,11 +188262,6 @@ entities: - type: Transform pos: 35.5,-24.5 parent: 12 - - uid: 22290 - components: - - type: Transform - pos: 42.5,13.5 - parent: 12 - uid: 22321 components: - type: Transform @@ -188008,12 +188385,6 @@ entities: - type: Transform pos: 34.5,-39.5 parent: 12 - - uid: 24237 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: 47.5,66.5 - parent: 12 - uid: 24259 components: - type: Transform @@ -188368,6 +188739,12 @@ entities: rot: 3.141592653589793 rad pos: 63.5,-27.5 parent: 12 + - uid: 26152 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -60.5,-12.5 + parent: 12 - uid: 26167 components: - type: Transform @@ -188473,12 +188850,6 @@ entities: - type: Transform pos: 56.5,3.5 parent: 12 - - uid: 26492 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 24.5,13.5 - parent: 12 - uid: 26510 components: - type: Transform @@ -188527,16 +188898,6 @@ entities: rot: -1.5707963267948966 rad pos: 9.5,-57.5 parent: 12 - - uid: 26909 - components: - - type: Transform - pos: -17.5,-68.5 - parent: 12 - - uid: 26910 - components: - - type: Transform - pos: -17.5,-69.5 - parent: 12 - uid: 26912 components: - type: Transform @@ -188549,12 +188910,6 @@ entities: rot: 3.141592653589793 rad pos: -13.5,77.5 parent: 12 - - uid: 26949 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -61.5,-15.5 - parent: 12 - uid: 26956 components: - type: Transform @@ -188579,29 +188934,16 @@ entities: rot: 1.5707963267948966 rad pos: -39.5,-18.5 parent: 12 - - uid: 27043 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -61.5,-13.5 - parent: 12 - uid: 27050 components: - type: Transform rot: 3.141592653589793 rad pos: 27.5,-13.5 parent: 12 - - uid: 27116 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -59.5,-11.5 - parent: 12 - uid: 27117 components: - type: Transform - rot: 1.5707963267948966 rad - pos: -58.5,-11.5 + pos: -17.5,-67.5 parent: 12 - uid: 27147 components: @@ -188639,18 +188981,6 @@ entities: rot: 3.141592653589793 rad pos: 41.5,1.5 parent: 12 - - uid: 27334 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -49.5,-17.5 - parent: 12 - - uid: 27335 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -48.5,-17.5 - parent: 12 - uid: 27410 components: - type: Transform @@ -188701,31 +189031,11 @@ entities: rot: 1.5707963267948966 rad pos: -28.5,61.5 parent: 12 - - uid: 27952 - components: - - type: Transform - pos: 5.5,-9.5 - parent: 12 - uid: 27978 components: - type: Transform pos: -22.5,-68.5 parent: 12 - - uid: 27981 - components: - - type: Transform - pos: 5.5,-12.5 - parent: 12 - - uid: 27982 - components: - - type: Transform - pos: 5.5,-11.5 - parent: 12 - - uid: 27983 - components: - - type: Transform - pos: 5.5,-10.5 - parent: 12 - uid: 27985 components: - type: Transform @@ -189048,16 +189358,6 @@ entities: - type: Transform pos: -27.5,-60.5 parent: 12 - - uid: 30540 - components: - - type: Transform - pos: -15.5,-68.5 - parent: 12 - - uid: 30542 - components: - - type: Transform - pos: -15.5,-66.5 - parent: 12 - uid: 30554 components: - type: Transform @@ -189099,20 +189399,47 @@ entities: rot: 3.141592653589793 rad pos: -53.5,-49.5 parent: 12 - - uid: 31171 + - uid: 31083 components: - type: Transform - pos: -9.5,-65.5 + rot: 1.5707963267948966 rad + pos: -16.5,-71.5 parent: 12 - - uid: 31172 + - uid: 31085 components: - type: Transform - pos: -9.5,-66.5 + rot: 1.5707963267948966 rad + pos: -14.5,-72.5 parent: 12 - - uid: 31174 + - uid: 31097 components: - type: Transform - pos: -8.5,-67.5 + rot: 1.5707963267948966 rad + pos: -12.5,-72.5 + parent: 12 + - uid: 31100 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -16.5,-70.5 + parent: 12 + - uid: 31101 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -10.5,-72.5 + parent: 12 + - uid: 31102 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -11.5,-72.5 + parent: 12 + - uid: 31104 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -9.5,-69.5 parent: 12 - uid: 31187 components: @@ -189151,12 +189478,6 @@ entities: rot: 3.141592653589793 rad pos: -7.5,-69.5 parent: 12 - - uid: 31238 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: -8.5,-68.5 - parent: 12 - uid: 31376 components: - type: Transform @@ -189393,6 +189714,11 @@ entities: rot: -1.5707963267948966 rad pos: 49.5,7.5 parent: 12 + - uid: 10042 + components: + - type: Transform + pos: -12.5,-71.5 + parent: 12 - uid: 10279 components: - type: Transform @@ -189646,18 +189972,160 @@ entities: rot: 1.5707963267948966 rad pos: 41.5,-4.5 parent: 12 + - uid: 13148 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 4.5,-8.5 + parent: 12 + - uid: 13149 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 4.5,-7.5 + parent: 12 + - uid: 13150 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 2.5,6.5 + parent: 12 + - uid: 13151 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -2.5,6.5 + parent: 12 + - uid: 13153 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -56.5,-20.5 + parent: 12 + - uid: 13154 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -46.5,-17.5 + parent: 12 + - uid: 13155 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 0.5,6.5 + parent: 12 + - uid: 13156 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -5.5,4.5 + parent: 12 + - uid: 13157 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -5.5,-0.5 + parent: 12 + - uid: 13158 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -5.5,2.5 + parent: 12 + - uid: 13159 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -5.5,3.5 + parent: 12 + - uid: 13160 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -6.5,-13.5 + parent: 12 + - uid: 13162 + components: + - type: Transform + pos: 27.5,18.5 + parent: 12 + - uid: 13163 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -9.5,-3.5 + parent: 12 + - uid: 13164 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -7.5,-1.5 + parent: 12 - uid: 13859 components: - type: Transform rot: -1.5707963267948966 rad pos: 1.5,71.5 parent: 12 + - uid: 14179 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -7.5,-0.5 + parent: 12 + - uid: 14180 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 4.5,2.5 + parent: 12 + - uid: 14182 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -7.5,-12.5 + parent: 12 - uid: 14625 components: - type: Transform rot: -1.5707963267948966 rad pos: -10.5,-31.5 parent: 12 + - uid: 15549 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -9.5,-9.5 + parent: 12 + - uid: 15550 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -51.5,-11.5 + parent: 12 + - uid: 15552 + components: + - type: Transform + pos: 17.5,23.5 + parent: 12 + - uid: 15703 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 4.5,-1.5 + parent: 12 + - uid: 16797 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 4.5,4.5 + parent: 12 + - uid: 16799 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -6.5,-0.5 + parent: 12 - uid: 17305 components: - type: Transform @@ -189668,12 +190136,43 @@ entities: - type: Transform pos: -47.5,76.5 parent: 12 + - uid: 18572 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -61.5,-14.5 + parent: 12 + - uid: 18585 + components: + - type: Transform + pos: 25.5,13.5 + parent: 12 + - uid: 19199 + components: + - type: Transform + pos: 9.5,29.5 + parent: 12 - uid: 19295 components: - type: Transform rot: 3.141592653589793 rad pos: -52.5,-51.5 parent: 12 + - uid: 19355 + components: + - type: Transform + pos: 10.5,29.5 + parent: 12 + - uid: 19357 + components: + - type: Transform + pos: 19.5,24.5 + parent: 12 + - uid: 19358 + components: + - type: Transform + pos: 20.5,22.5 + parent: 12 - uid: 19455 components: - type: Transform @@ -189685,6 +190184,16 @@ entities: rot: -1.5707963267948966 rad pos: 36.5,64.5 parent: 12 + - uid: 19847 + components: + - type: Transform + pos: 11.5,30.5 + parent: 12 + - uid: 19871 + components: + - type: Transform + pos: 15.5,34.5 + parent: 12 - uid: 22034 components: - type: Transform @@ -189701,6 +190210,16 @@ entities: - type: Transform pos: -50.5,-20.5 parent: 12 + - uid: 22185 + components: + - type: Transform + pos: 53.5,67.5 + parent: 12 + - uid: 22187 + components: + - type: Transform + pos: 51.5,67.5 + parent: 12 - uid: 22277 components: - type: Transform @@ -189755,6 +190274,12 @@ entities: - type: Transform pos: -57.5,-24.5 parent: 12 + - uid: 24237 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -60.5,-11.5 + parent: 12 - uid: 24254 components: - type: Transform @@ -189765,6 +190290,17 @@ entities: - type: Transform pos: -26.5,73.5 parent: 12 + - uid: 25555 + components: + - type: Transform + pos: 51.5,66.5 + parent: 12 + - uid: 25558 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -5.5,6.5 + parent: 12 - uid: 25596 components: - type: Transform @@ -189792,6 +190328,22 @@ entities: - type: Transform pos: -2.5,-17.5 parent: 12 + - uid: 26133 + components: + - type: Transform + pos: 59.5,65.5 + parent: 12 + - uid: 26149 + components: + - type: Transform + pos: 59.5,60.5 + parent: 12 + - uid: 26150 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 4.5,-0.5 + parent: 12 - uid: 26241 components: - type: Transform @@ -189814,6 +190366,12 @@ entities: - type: Transform pos: -5.5,-17.5 parent: 12 + - uid: 26492 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -8.5,-1.5 + parent: 12 - uid: 26530 components: - type: Transform @@ -189860,12 +190418,24 @@ entities: - type: Transform pos: 5.5,-13.5 parent: 12 + - uid: 26836 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -8.5,-9.5 + parent: 12 - uid: 26907 components: - type: Transform rot: -1.5707963267948966 rad pos: 10.5,-57.5 parent: 12 + - uid: 26909 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -8.5,-11.5 + parent: 12 - uid: 26911 components: - type: Transform @@ -189878,6 +190448,11 @@ entities: rot: 1.5707963267948966 rad pos: -61.5,-17.5 parent: 12 + - uid: 26949 + components: + - type: Transform + pos: 47.5,66.5 + parent: 12 - uid: 26978 components: - type: Transform @@ -189896,6 +190471,11 @@ entities: rot: -1.5707963267948966 rad pos: 38.5,-3.5 parent: 12 + - uid: 27043 + components: + - type: Transform + pos: 24.5,13.5 + parent: 12 - uid: 27044 components: - type: Transform @@ -189920,6 +190500,11 @@ entities: rot: -1.5707963267948966 rad pos: 45.5,-42.5 parent: 12 + - uid: 27116 + components: + - type: Transform + pos: -17.5,-68.5 + parent: 12 - uid: 27119 components: - type: Transform @@ -189943,6 +190528,12 @@ entities: rot: 3.141592653589793 rad pos: 39.5,5.5 parent: 12 + - uid: 27240 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -61.5,-15.5 + parent: 12 - uid: 27243 components: - type: Transform @@ -189967,6 +190558,18 @@ entities: rot: 3.141592653589793 rad pos: 41.5,4.5 parent: 12 + - uid: 27334 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -61.5,-13.5 + parent: 12 + - uid: 27335 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -59.5,-11.5 + parent: 12 - uid: 27336 components: - type: Transform @@ -189984,6 +190587,12 @@ entities: rot: -1.5707963267948966 rad pos: 26.5,15.5 parent: 12 + - uid: 27952 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -58.5,-11.5 + parent: 12 - uid: 27973 components: - type: Transform @@ -190001,12 +190610,36 @@ entities: rot: 3.141592653589793 rad pos: 47.5,7.5 parent: 12 + - uid: 27981 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -49.5,-17.5 + parent: 12 + - uid: 27982 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -48.5,-17.5 + parent: 12 + - uid: 27983 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 5.5,-9.5 + parent: 12 - uid: 28048 components: - type: Transform rot: 3.141592653589793 rad pos: 63.5,-4.5 parent: 12 + - uid: 28051 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 5.5,-12.5 + parent: 12 - uid: 28052 components: - type: Transform @@ -190051,7 +190684,8 @@ entities: - uid: 28069 components: - type: Transform - pos: -15.5,-70.5 + rot: 1.5707963267948966 rad + pos: 5.5,-11.5 parent: 12 - uid: 28070 components: @@ -190091,6 +190725,12 @@ entities: rot: -1.5707963267948966 rad pos: 44.5,3.5 parent: 12 + - uid: 28303 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 5.5,-10.5 + parent: 12 - uid: 28310 components: - type: Transform @@ -190300,11 +190940,6 @@ entities: - type: Transform pos: -35.5,-60.5 parent: 12 - - uid: 30545 - components: - - type: Transform - pos: -15.5,-65.5 - parent: 12 - uid: 30548 components: - type: Transform @@ -190315,21 +190950,22 @@ entities: - type: Transform pos: -39.5,-57.5 parent: 12 - - uid: 30700 + - uid: 30880 components: - type: Transform - pos: -10.5,-65.5 + pos: 6.5,-58.5 parent: 12 - - uid: 30880 + - uid: 31082 components: - type: Transform - pos: 6.5,-58.5 + rot: 1.5707963267948966 rad + pos: -16.5,-72.5 parent: 12 - - uid: 31173 + - uid: 31084 components: - type: Transform - rot: 3.141592653589793 rad - pos: -9.5,-67.5 + rot: 1.5707963267948966 rad + pos: -9.5,-72.5 parent: 12 - uid: 31183 components: @@ -190706,11 +191342,6 @@ entities: - type: Transform pos: -6.5,-24.5 parent: 12 - - uid: 563 - components: - - type: Transform - pos: -7.5,-24.5 - parent: 12 - uid: 589 components: - type: Transform @@ -192027,11 +192658,6 @@ entities: rot: -1.5707963267948966 rad pos: 34.5,-29.5 parent: 12 - - uid: 5385 - components: - - type: Transform - pos: -9.5,-24.5 - parent: 12 - uid: 5441 components: - type: Transform @@ -192751,6 +193377,12 @@ entities: - type: Transform pos: 41.5,-40.5 parent: 12 + - uid: 9120 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -12.5,-67.5 + parent: 12 - uid: 9133 components: - type: Transform @@ -192992,12 +193624,6 @@ entities: rot: 1.5707963267948966 rad pos: -5.5,21.5 parent: 12 - - uid: 10620 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -0.5,14.5 - parent: 12 - uid: 10665 components: - type: Transform @@ -193706,11 +194332,6 @@ entities: - type: Transform pos: 3.5,30.5 parent: 12 - - uid: 11842 - components: - - type: Transform - pos: 3.5,31.5 - parent: 12 - uid: 11843 components: - type: Transform @@ -194133,6 +194754,18 @@ entities: rot: -1.5707963267948966 rad pos: 35.5,-52.5 parent: 12 + - uid: 13147 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -3.5,46.5 + parent: 12 + - uid: 13152 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -14.5,-67.5 + parent: 12 - uid: 13487 components: - type: Transform @@ -195337,6 +195970,12 @@ entities: rot: 1.5707963267948966 rad pos: -11.5,-2.5 parent: 12 + - uid: 16800 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -13.5,26.5 + parent: 12 - uid: 16872 components: - type: Transform @@ -195636,6 +196275,12 @@ entities: - type: Transform pos: -13.5,-8.5 parent: 12 + - uid: 17541 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -13.5,24.5 + parent: 12 - uid: 17542 components: - type: Transform @@ -195666,6 +196311,12 @@ entities: - type: Transform pos: -55.5,-31.5 parent: 12 + - uid: 17972 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -14.5,26.5 + parent: 12 - uid: 17973 components: - type: Transform @@ -195686,6 +196337,12 @@ entities: - type: Transform pos: -4.5,-54.5 parent: 12 + - uid: 18560 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -14.5,25.5 + parent: 12 - uid: 18567 components: - type: Transform @@ -195696,6 +196353,12 @@ entities: - type: Transform pos: -17.5,-8.5 parent: 12 + - uid: 18569 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -14.5,24.5 + parent: 12 - uid: 18570 components: - type: Transform @@ -195751,11 +196414,6 @@ entities: - type: Transform pos: -12.5,-18.5 parent: 12 - - uid: 18585 - components: - - type: Transform - pos: -11.5,-17.5 - parent: 12 - uid: 18586 components: - type: Transform @@ -195925,6 +196583,12 @@ entities: rot: -1.5707963267948966 rad pos: -41.5,43.5 parent: 12 + - uid: 19034 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -5.5,47.5 + parent: 12 - uid: 19061 components: - type: Transform @@ -196693,6 +197357,12 @@ entities: - type: Transform pos: -11.5,47.5 parent: 12 + - uid: 21479 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 42.5,14.5 + parent: 12 - uid: 21508 components: - type: Transform @@ -196883,6 +197553,12 @@ entities: - type: Transform pos: -0.5,-60.5 parent: 12 + - uid: 22290 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -14.5,29.5 + parent: 12 - uid: 22304 components: - type: Transform @@ -197035,8 +197711,8 @@ entities: - uid: 23681 components: - type: Transform - rot: 3.141592653589793 rad - pos: -5.5,-21.5 + rot: 1.5707963267948966 rad + pos: -14.5,30.5 parent: 12 - uid: 23682 components: @@ -197052,7 +197728,8 @@ entities: - uid: 23779 components: - type: Transform - pos: -1.5,12.5 + rot: 1.5707963267948966 rad + pos: -13.5,29.5 parent: 12 - uid: 23797 components: @@ -197088,7 +197765,8 @@ entities: - uid: 23897 components: - type: Transform - pos: -1.5,13.5 + rot: 1.5707963267948966 rad + pos: -21.5,30.5 parent: 12 - uid: 23946 components: @@ -197201,6 +197879,12 @@ entities: rot: -1.5707963267948966 rad pos: 32.5,-47.5 parent: 12 + - uid: 24419 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -4.5,47.5 + parent: 12 - uid: 24428 components: - type: Transform @@ -197354,6 +198038,12 @@ entities: - type: Transform pos: -4.5,70.5 parent: 12 + - uid: 25396 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -5.5,46.5 + parent: 12 - uid: 25402 components: - type: Transform @@ -197730,6 +198420,12 @@ entities: rot: 3.141592653589793 rad pos: 39.5,-16.5 parent: 12 + - uid: 26910 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 42.5,13.5 + parent: 12 - uid: 26926 components: - type: Transform @@ -198188,6 +198884,17 @@ entities: rot: -1.5707963267948966 rad pos: -52.5,60.5 parent: 12 + - uid: 29182 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -11.5,-67.5 + parent: 12 + - uid: 29185 + components: + - type: Transform + pos: -9.5,-66.5 + parent: 12 - uid: 29208 components: - type: Transform @@ -198199,6 +198906,11 @@ entities: - type: Transform pos: -52.5,63.5 parent: 12 + - uid: 29307 + components: + - type: Transform + pos: -9.5,-65.5 + parent: 12 - uid: 29308 components: - type: Transform @@ -198211,6 +198923,17 @@ entities: rot: -1.5707963267948966 rad pos: -52.5,56.5 parent: 12 + - uid: 29323 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -14.5,-66.5 + parent: 12 + - uid: 29340 + components: + - type: Transform + pos: -8.5,-67.5 + parent: 12 - uid: 29351 components: - type: Transform @@ -198555,6 +199278,12 @@ entities: rot: -1.5707963267948966 rad pos: -19.5,34.5 parent: 12 + - uid: 11936 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -10.5,-67.5 + parent: 12 - uid: 12018 components: - type: Transform @@ -198763,6 +199492,12 @@ entities: rot: -1.5707963267948966 rad pos: -5.5,32.5 parent: 12 + - uid: 19051 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -3.5,47.5 + parent: 12 - uid: 19068 components: - type: Transform @@ -198880,6 +199615,12 @@ entities: rot: -1.5707963267948966 rad pos: 9.5,63.5 parent: 12 + - uid: 19844 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 42.5,15.5 + parent: 12 - uid: 20776 components: - type: Transform @@ -198891,6 +199632,12 @@ entities: rot: -1.5707963267948966 rad pos: 10.5,64.5 parent: 12 + - uid: 21922 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 43.5,13.5 + parent: 12 - uid: 22145 components: - type: Transform @@ -199520,6 +200267,11 @@ entities: rot: 3.141592653589793 rad pos: 51.5,9.5 parent: 12 + - uid: 28933 + components: + - type: Transform + pos: -13.5,-67.5 + parent: 12 - uid: 28942 components: - type: Transform @@ -199562,6 +200314,16 @@ entities: - type: Transform pos: -52.5,57.5 parent: 12 + - uid: 29183 + components: + - type: Transform + pos: -9.5,-67.5 + parent: 12 + - uid: 29184 + components: + - type: Transform + pos: -10.5,-65.5 + parent: 12 - uid: 29190 components: - type: Transform @@ -199572,6 +200334,11 @@ entities: - type: Transform pos: -52.5,59.5 parent: 12 + - uid: 29339 + components: + - type: Transform + pos: -8.5,-68.5 + parent: 12 - uid: 29344 components: - type: Transform @@ -199650,6 +200417,16 @@ entities: rot: 1.5707963267948966 rad pos: -52.5,54.5 parent: 12 + - uid: 30017 + components: + - type: Transform + pos: -7.5,-24.5 + parent: 12 + - uid: 30018 + components: + - type: Transform + pos: -9.5,-24.5 + parent: 12 - uid: 30200 components: - type: Transform @@ -199661,6 +200438,32 @@ entities: - type: Transform pos: 29.5,20.5 parent: 12 + - uid: 30540 + components: + - type: Transform + pos: -0.5,14.5 + parent: 12 + - uid: 30542 + components: + - type: Transform + pos: 3.5,31.5 + parent: 12 + - uid: 30543 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -11.5,-17.5 + parent: 12 + - uid: 30545 + components: + - type: Transform + pos: -5.5,-21.5 + parent: 12 + - uid: 30700 + components: + - type: Transform + pos: -1.5,12.5 + parent: 12 - uid: 30781 components: - type: Transform @@ -199671,6 +200474,11 @@ entities: - type: Transform pos: -27.5,-58.5 parent: 12 + - uid: 30970 + components: + - type: Transform + pos: -1.5,13.5 + parent: 12 - uid: 31044 components: - type: Transform @@ -199681,6 +200489,12 @@ entities: - type: Transform pos: -35.5,-57.5 parent: 12 + - uid: 31096 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -15.5,-66.5 + parent: 12 - uid: 31175 components: - type: Transform @@ -200862,6 +201676,16 @@ entities: rot: 3.141592653589793 rad pos: -34.5,-57.5 parent: 12 + - uid: 30976 + components: + - type: Transform + pos: 48.5,-12.5 + parent: 12 + - uid: 30977 + components: + - type: Transform + pos: 47.5,-12.5 + parent: 12 - proto: WindoorBarKitchenLocked entities: - uid: 11203 @@ -200886,16 +201710,6 @@ entities: parent: 12 - proto: WindoorSecure entities: - - uid: 12234 - components: - - type: Transform - pos: 48.5,-12.5 - parent: 12 - - uid: 12237 - components: - - type: Transform - pos: 47.5,-12.5 - parent: 12 - uid: 14181 components: - type: Transform @@ -202348,6 +203162,34 @@ entities: rot: 1.5707963267948966 rad pos: 31.5,22.5 parent: 12 + - uid: 30971 + components: + - type: Transform + pos: 49.5,-12.5 + parent: 12 + - uid: 30972 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 49.5,-12.5 + parent: 12 + - uid: 30973 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 49.5,-11.5 + parent: 12 + - uid: 30974 + components: + - type: Transform + pos: 46.5,-12.5 + parent: 12 + - uid: 30975 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 47.5,-11.5 + parent: 12 - proto: WindowFrostedDirectional entities: - uid: 4236 @@ -202719,11 +203561,6 @@ entities: rot: 3.141592653589793 rad pos: 52.5,-23.5 parent: 12 - - uid: 5411 - components: - - type: Transform - pos: 49.5,-12.5 - parent: 12 - uid: 5572 components: - type: Transform @@ -202825,11 +203662,6 @@ entities: rot: 3.141592653589793 rad pos: -1.5,-44.5 parent: 12 - - uid: 12238 - components: - - type: Transform - pos: 46.5,-12.5 - parent: 12 - uid: 12326 components: - type: Transform @@ -203213,24 +204045,12 @@ entities: rot: 3.141592653589793 rad pos: -37.5,65.5 parent: 12 - - uid: 26836 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 47.5,-11.5 - parent: 12 - uid: 28932 components: - type: Transform rot: 3.141592653589793 rad pos: -37.5,53.5 parent: 12 - - uid: 28933 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 50.5,-11.5 - parent: 12 - uid: 29220 components: - type: Transform @@ -203319,12 +204139,6 @@ entities: rot: 3.141592653589793 rad pos: -57.5,27.5 parent: 12 - - uid: 31911 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 50.5,-12.5 - parent: 12 - proto: Wirecutter entities: - uid: 8737 From 8cf279e20070b610f7c2a6425ad5f2af83692f97 Mon Sep 17 00:00:00 2001 From: Ubaser <134914314+UbaserB@users.noreply.github.com> Date: Wed, 13 Nov 2024 23:30:40 +1100 Subject: [PATCH 083/290] Window sprite tweaks (#33282) * add * yes --- .../Windows/clockwork_diagonal.rsi/meta.json | 2 +- .../Windows/clockwork_diagonal.rsi/state0.png | Bin 1663 -> 2836 bytes .../Windows/clockwork_diagonal.rsi/state1.png | Bin 1681 -> 2833 bytes .../Windows/clockwork_window.rsi/cwindow0.png | Bin 1065 -> 2164 bytes .../Windows/clockwork_window.rsi/cwindow1.png | Bin 1060 -> 2128 bytes .../Windows/clockwork_window.rsi/cwindow2.png | Bin 1065 -> 2164 bytes .../Windows/clockwork_window.rsi/cwindow3.png | Bin 1060 -> 2128 bytes .../Windows/clockwork_window.rsi/cwindow4.png | Bin 1075 -> 2112 bytes .../Windows/clockwork_window.rsi/cwindow5.png | Bin 983 -> 2060 bytes .../Windows/clockwork_window.rsi/cwindow6.png | Bin 1075 -> 2112 bytes .../Windows/clockwork_window.rsi/cwindow7.png | Bin 1005 -> 2065 bytes .../Windows/clockwork_window.rsi/full.png | Bin 735 -> 1714 bytes .../Windows/clockwork_window.rsi/meta.json | 2 +- .../Structures/Windows/mining.rsi/full.png | Bin 837 -> 1811 bytes .../Structures/Windows/mining.rsi/meta.json | 2 +- .../Windows/mining.rsi/mwindow0.png | Bin 3765 -> 2248 bytes .../Windows/mining.rsi/mwindow1.png | Bin 3697 -> 2196 bytes .../Windows/mining.rsi/mwindow2.png | Bin 3765 -> 2248 bytes .../Windows/mining.rsi/mwindow3.png | Bin 3697 -> 2196 bytes .../Windows/mining.rsi/mwindow4.png | Bin 3706 -> 2175 bytes .../Windows/mining.rsi/mwindow5.png | Bin 3640 -> 2215 bytes .../Windows/mining.rsi/mwindow6.png | Bin 3706 -> 2175 bytes .../Windows/mining.rsi/mwindow7.png | Bin 3269 -> 1813 bytes .../Windows/mining_diagonal.rsi/meta.json | 2 +- .../Windows/mining_diagonal.rsi/state0.png | Bin 3037 -> 1299 bytes .../Windows/mining_diagonal.rsi/state1.png | Bin 3076 -> 1333 bytes .../Windows/plasma_diagonal.rsi/meta.json | 2 +- .../Windows/plasma_diagonal.rsi/state0.png | Bin 15748 -> 1644 bytes .../Windows/plasma_diagonal.rsi/state1.png | Bin 15665 -> 1603 bytes .../Windows/plasma_window.rsi/full.png | Bin 1597 -> 2843 bytes .../Windows/plasma_window.rsi/meta.json | 2 +- .../Windows/plasma_window.rsi/pwindow0.png | Bin 2063 -> 3469 bytes .../Windows/plasma_window.rsi/pwindow1.png | Bin 1099 -> 2334 bytes .../Windows/plasma_window.rsi/pwindow2.png | Bin 2063 -> 3469 bytes .../Windows/plasma_window.rsi/pwindow3.png | Bin 1099 -> 2334 bytes .../Windows/plasma_window.rsi/pwindow4.png | Bin 1161 -> 2402 bytes .../Windows/plasma_window.rsi/pwindow5.png | Bin 1064 -> 2294 bytes .../Windows/plasma_window.rsi/pwindow6.png | Bin 1161 -> 2402 bytes .../Windows/plasma_window.rsi/pwindow7.png | Bin 247 -> 1240 bytes .../Windows/plastitanium_window.rsi/full.png | Bin 506 -> 1500 bytes .../Windows/plastitanium_window.rsi/meta.json | 2 +- .../plastitanium_window.rsi/ptwindow0.png | Bin 1190 -> 2316 bytes .../plastitanium_window.rsi/ptwindow1.png | Bin 1006 -> 2083 bytes .../plastitanium_window.rsi/ptwindow2.png | Bin 1190 -> 2316 bytes .../plastitanium_window.rsi/ptwindow3.png | Bin 1006 -> 2083 bytes .../plastitanium_window.rsi/ptwindow4.png | Bin 1008 -> 2076 bytes .../plastitanium_window.rsi/ptwindow5.png | Bin 986 -> 2114 bytes .../plastitanium_window.rsi/ptwindow6.png | Bin 1008 -> 2076 bytes .../plastitanium_window.rsi/ptwindow7.png | Bin 641 -> 1668 bytes .../meta.json | 2 +- .../state0.png | Bin 3238 -> 1375 bytes .../state1.png | Bin 3208 -> 1343 bytes .../reinforced_plasma_diagonal.rsi/meta.json | 2 +- .../reinforced_plasma_diagonal.rsi/state0.png | Bin 15911 -> 1797 bytes .../reinforced_plasma_diagonal.rsi/state1.png | Bin 15885 -> 1790 bytes .../reinforced_plasma_window.rsi/full.png | Bin 2495 -> 3504 bytes .../reinforced_plasma_window.rsi/meta.json | 2 +- .../rpwindow0.png | Bin 2930 -> 4096 bytes .../rpwindow1.png | Bin 1696 -> 2864 bytes .../rpwindow2.png | Bin 2930 -> 4096 bytes .../rpwindow3.png | Bin 1696 -> 2864 bytes .../rpwindow4.png | Bin 1745 -> 2888 bytes .../rpwindow5.png | Bin 1695 -> 3021 bytes .../rpwindow6.png | Bin 1745 -> 2888 bytes .../rpwindow7.png | Bin 910 -> 2262 bytes .../reinforced_uranium_diagonal.rsi/meta.json | 2 +- .../state0.png | Bin 15734 -> 1662 bytes .../state1.png | Bin 15695 -> 1620 bytes .../reinforced_uranium_window.rsi/full.png | Bin 2067 -> 3028 bytes .../reinforced_uranium_window.rsi/meta.json | 2 +- .../ruwindow0.png | Bin 2366 -> 3323 bytes .../ruwindow1.png | Bin 1169 -> 2130 bytes .../ruwindow2.png | Bin 2342 -> 3323 bytes .../ruwindow3.png | Bin 1138 -> 2130 bytes .../ruwindow4.png | Bin 1133 -> 2102 bytes .../ruwindow5.png | Bin 1088 -> 2084 bytes .../ruwindow6.png | Bin 1129 -> 2102 bytes .../ruwindow7.png | Bin 267 -> 1240 bytes .../Windows/reinforced_window.rsi/full.png | Bin 2063 -> 3041 bytes .../Windows/reinforced_window.rsi/meta.json | 2 +- .../reinforced_window.rsi/rwindow0.png | Bin 2229 -> 3349 bytes .../reinforced_window.rsi/rwindow1.png | Bin 1148 -> 2163 bytes .../reinforced_window.rsi/rwindow2.png | Bin 2229 -> 3349 bytes .../reinforced_window.rsi/rwindow3.png | Bin 1148 -> 2163 bytes .../reinforced_window.rsi/rwindow4.png | Bin 1130 -> 2172 bytes .../reinforced_window.rsi/rwindow5.png | Bin 1025 -> 2041 bytes .../reinforced_window.rsi/rwindow6.png | Bin 1130 -> 2172 bytes .../reinforced_window.rsi/rwindow7.png | Bin 272 -> 1239 bytes .../reinforced_window_diagonal.rsi/meta.json | 2 +- .../reinforced_window_diagonal.rsi/state0.png | Bin 16179 -> 1573 bytes .../reinforced_window_diagonal.rsi/state1.png | Bin 16152 -> 1550 bytes .../Windows/shuttle_window.rsi/full.png | Bin 707 -> 1779 bytes .../Windows/shuttle_window.rsi/meta.json | 2 +- .../Windows/shuttle_window.rsi/swindow0.png | Bin 1080 -> 2278 bytes .../Windows/shuttle_window.rsi/swindow1.png | Bin 881 -> 2146 bytes .../Windows/shuttle_window.rsi/swindow2.png | Bin 1080 -> 2278 bytes .../Windows/shuttle_window.rsi/swindow3.png | Bin 881 -> 2146 bytes .../Windows/shuttle_window.rsi/swindow4.png | Bin 912 -> 2166 bytes .../Windows/shuttle_window.rsi/swindow5.png | Bin 857 -> 2168 bytes .../Windows/shuttle_window.rsi/swindow6.png | Bin 912 -> 2166 bytes .../Windows/shuttle_window.rsi/swindow7.png | Bin 412 -> 1871 bytes .../shuttle_window_diagonal.rsi/meta.json | 2 +- .../shuttle_window_diagonal.rsi/state0.png | Bin 15523 -> 1475 bytes .../shuttle_window_diagonal.rsi/state1.png | Bin 15473 -> 1423 bytes .../Windows/tinted_window.rsi/full.png | Bin 9436 -> 3495 bytes .../Windows/tinted_window.rsi/meta.json | 2 +- .../Windows/tinted_window.rsi/twindow0.png | Bin 10814 -> 4035 bytes .../Windows/tinted_window.rsi/twindow1.png | Bin 8214 -> 2719 bytes .../Windows/tinted_window.rsi/twindow2.png | Bin 10815 -> 4035 bytes .../Windows/tinted_window.rsi/twindow3.png | Bin 8477 -> 2719 bytes .../Windows/tinted_window.rsi/twindow4.png | Bin 8217 -> 2692 bytes .../Windows/tinted_window.rsi/twindow5.png | Bin 6896 -> 2318 bytes .../Windows/tinted_window.rsi/twindow6.png | Bin 8464 -> 2692 bytes .../Windows/tinted_window.rsi/twindow7.png | Bin 4882 -> 1661 bytes .../Windows/uranium_window.rsi/full.png | Bin 1321 -> 2364 bytes .../Windows/uranium_window.rsi/meta.json | 2 +- .../Windows/uranium_window.rsi/uwindow0.png | Bin 1688 -> 2857 bytes .../Windows/uranium_window.rsi/uwindow1.png | Bin 1225 -> 2288 bytes .../Windows/uranium_window.rsi/uwindow2.png | Bin 1688 -> 2857 bytes .../Windows/uranium_window.rsi/uwindow3.png | Bin 1225 -> 2288 bytes .../Windows/uranium_window.rsi/uwindow4.png | Bin 1216 -> 2251 bytes .../Windows/uranium_window.rsi/uwindow5.png | Bin 795 -> 1872 bytes .../Windows/uranium_window.rsi/uwindow6.png | Bin 1229 -> 2251 bytes .../Windows/uranium_window.rsi/uwindow7.png | Bin 297 -> 1281 bytes .../uranium_window_diagonal.rsi/meta.json | 2 +- .../uranium_window_diagonal.rsi/state0.png | Bin 15629 -> 1572 bytes .../uranium_window_diagonal.rsi/state1.png | Bin 15604 -> 1539 bytes .../Structures/Windows/window.rsi/full.png | Bin 1224 -> 2279 bytes .../Structures/Windows/window.rsi/meta.json | 2 +- .../Structures/Windows/window.rsi/window0.png | Bin 1632 -> 2748 bytes .../Structures/Windows/window.rsi/window1.png | Bin 1183 -> 2217 bytes .../Structures/Windows/window.rsi/window2.png | Bin 1632 -> 2748 bytes .../Structures/Windows/window.rsi/window3.png | Bin 1183 -> 2217 bytes .../Structures/Windows/window.rsi/window4.png | Bin 1187 -> 2213 bytes .../Structures/Windows/window.rsi/window5.png | Bin 800 -> 1810 bytes .../Structures/Windows/window.rsi/window6.png | Bin 1187 -> 2213 bytes .../Structures/Windows/window.rsi/window7.png | Bin 301 -> 1240 bytes .../Windows/window_diagonal.rsi/meta.json | 2 +- .../Windows/window_diagonal.rsi/state0.png | Bin 15988 -> 1329 bytes .../Windows/window_diagonal.rsi/state1.png | Bin 15966 -> 1285 bytes 140 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Resources/Textures/Structures/Windows/clockwork_diagonal.rsi/meta.json b/Resources/Textures/Structures/Windows/clockwork_diagonal.rsi/meta.json index 06b6f4a55053..9f0945a8701a 100644 --- a/Resources/Textures/Structures/Windows/clockwork_diagonal.rsi/meta.json +++ b/Resources/Textures/Structures/Windows/clockwork_diagonal.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/blob/b8fc9b367ebb26def792a68bcb25294e518698d8/icons/obj/smooth_structures/clockwork_window.dmi diagonalized by MACMAN2003", + "copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/blob/b8fc9b367ebb26def792a68bcb25294e518698d8/icons/obj/smooth_structures/clockwork_window.dmi diagonalized by MACMAN2003, transparency tweaked by Ubaser.", "size": { "x": 32, "y": 32 diff --git a/Resources/Textures/Structures/Windows/clockwork_diagonal.rsi/state0.png b/Resources/Textures/Structures/Windows/clockwork_diagonal.rsi/state0.png index 084563bfa29305fa626d2657f7528e8fcaeb4960..84e8da95e5b7ded79994f18de59800ffb2e25279 100644 GIT binary patch literal 2836 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 diff --git a/Resources/Textures/Structures/Windows/clockwork_diagonal.rsi/state1.png b/Resources/Textures/Structures/Windows/clockwork_diagonal.rsi/state1.png index 0e48f9c92271fae2dfc906c5f3ba31f888151a6c..0f139a44c4cbaee8fbc948ea70d5fe9b46d5a9b8 100644 GIT binary patch literal 2833 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 delta 1030 zcmV+h1o`{)5UB`|F@FSSK}|sb0I`n?{9y$E000SaNLh0L01m?d01m?e$8V@)000BN zNklWutro6wC}$DJ>KsM4`fhb9jbm7cmqdAX}tApmV2)gIf+cdpm| zMUzO>1ax5+u)XaEyxTVlC2S@O57-54Y{~ta=m!P2<_g9N57-54xw%$Xrz8xIi>PP_ zD`Egpg*Gk08UcVqf>i>5X$e*c2tM8dlM<|}0SZ$RtbY-p3L3NC;1KszeAUsR;ma5>R+de`BwX zZ6H+vAb(1ND)7unhc28UZ|j|IFlqo3l7NX$c4dWIPNO}AiVGi%iy>%Dgda!h;DGFHGn2CE&xRJ z4u4#*2(XD=0djAg;NvqVyEQ=W`xZ6G^aRIbj{F+yxTBt=cBtFBXBQ=c=x zS{#G}V$^d&xZqKeI>Fi)U`m43K`@B~U91og7Z775gr?j(!Ri{Ih?Ag8CIo;;2{QSj zLuLekwAy_Tb^%D7sHyWLq%DD6z({Cv6n~jydDxaTC9n%Xo&ZziYTZE6H^$PEU_}fV zJ?JM(v7Mbt{@Pp`608uQ9)*!K`TWE6vd4Y%+8i>)C@|7xSUX@E_R(O}%hRY4E8qO< zXcj?&11J10^Dj?Fy*>|+G(p|~uhqq&x7?oSFQUblaT1{(EdT%j07*qoM6N<$g09TU A1poj5 diff --git a/Resources/Textures/Structures/Windows/clockwork_window.rsi/cwindow1.png b/Resources/Textures/Structures/Windows/clockwork_window.rsi/cwindow1.png index 025376834dc1867b2e6724d89982523f3444e8f0..e78030522325c579b865ab25c7d9261fc37bc19e 100644 GIT binary patch literal 2128 zcmZ`)4Oo)b9zTd*q0rmM(rcK&ytNbo$y5jt)cm-mIkS!CN)b?42m~*Kv|F*%EsohIi1@2FrRXM=WgbGL1)&}&hwo2ob!KwzyHVY{NLx@ z8ygdW#kgSr0NAL=usCGpSf-;r@-#@ccOeT(6&Dc#s&3)?kONM{i%N-(242YC5t)`@ z-uN%%IZqL}S%m{DveI1(|r(xk7|bu=4*Xqs<)?|{OKo5q!K743RohS z5iEZB$#OLuL?T%N&5r3jg@V~Q3bj&djUp6KMN(0kNCvB@z7${Tn|QD!O&G0SmUZ-A$1ObN~h5ReQ0zaI)ge}ACf*xC}6@8 zSSqp#H(QTYL9P^j)oQ_8B#=rh$}**VS!xhT>mwAU@YPb7#1?2IGND`(z@kp0US&^P zUvb+N1R@?8IRLuYae=dDcs+RI?;7a4opGd9zy^ykoh#?)o(1A-Nd zk`iptw?h+|?c$C55rhaw$DM#v*`mpei zWG7Ey)jyhRi?M@;v8CXYyQkY2p?-^}!8qu#YiDxbr~ZDy_J!pEYdk(2U%1FYSKPFH zEb_~({_btV(C!DkzWDs(pM4bAhFt-xJAd6IamwM3t*QNdp;2>ZiPMHW}12-cUdv@%{B#clqG%Kg1(YWW>h`m+hdkAh>4>Blzp< z&(9ql{ouV`J$I*L{Z#LG_=%nk4+~o-2wCj2OBdCGCC(tw(DtsH23;IdC85aB)djr3 zL{&p&^)u*p&Y4GK;%^v`B*b#@VElak-}BHqMU-P5Aj~5MfKr0%WI^}|`G;Obrn)bNY&mRKN-XclI0YUR@V;RgYa9F4*2P@2+2?%46&M@$V~}P2rDo^=O3~`_ zR)|+WN(Vq7^sxV%y|D?yt6nVGn-LRNe8%o~H1mvYbdBNqCs0GKiLn}pcj9gHnuY>y z;R_*rW{Ls)%uTwo=wb^j4z56NEn?XU0BfQz`D%eq9jx8mJ;8sN`?S~GpW+^1ud~CV9_RzTf|Ki zS7X-L0h~6ba*SVIKhp8!=E>W`UqBw;<(D@+a;w!3bhO-Ux1kh^C+}ao&j8r0GKa2` z7m0fg?wY#f_fvRL`~#h$afG1{U^-VVcNc59>e ze_Jz1%daGi<4<-TMIY!$viW|WonjBXuG_EPevoOxAIhb2?=f^a=hmQY*xB8~xdR>< z0P;UQJT|pc{=WA`xE~Pgp2|4lbNKY9{blZ5DbRQG%~u{nx38gWOac#pGfjB|-GZ)X z*=Y(hag|fjzgfP^*oW#J4)wRQQgI;JH7lB5)Rkb%DLdHm)h`$w`JITMdnF&t&s)gL zuQ^O4v~BFkSyb_H-iw8M#N_g%b2 z!wKC@xjN-%J3fhfhFQ>LjNB0eoI45-Qv2JNLqXM9Myp%HfHj=} delta 1025 zcmV+c1pfQb5Tpo@F@FSSK}|sb0I`n?{9y$E000SaNLh0L01m?d01m?e$8V@)000BI zNklHV%7>D05)I|a*e5I)h1cro4R3Mm&gn)qs7DmQYLS40VJS7f}#cj6(2<)B^et0v+siCI;qK>?>)D9B!BC!j;rV%-@Rwwd&v+p z#XTdPQ%BqM_9Ib#r+==~@sBS*h*sL8{>dJ^T5Kw{fnC6*v((A&B6|Fs=+J(mF;~K; zWun@W|M{8Yeko~u6BQTy-;MifZD1F0vPAB^CMutE=tHCB-Fe8EIqy`w3)W%wc56md z2V#pT*+93)oqtE;k4#R8v*utI0MPAm=c}*lba33E(mtZfgH~C5oG4ZZz?et3$MN)K z%Nzghkcc$|RACpey6OkKYnO`^93~qN*adw3Da!hyS6-bh8f!dY7k~!i&Z90R3KS7wDf>9OHdXdBX?RQXz2lImY^*Lq*a2}81O$5 zu;yoK-LD^71b{da!VQ**5KgoS0R1GO@mT(rcOG>c&?*2#NstYmKJ3uxW8@vk>ezs? z0NKzWVSfo&_e1V4nEVK)xH!?$1L8=Kym(Wm19`_whBm&7lZ+_84PL)Uop8c32$CHD zLja%QS~MQR0QI{MdGnLXUp`eB^^%*t$U4n6(H?gmLY`DdsJ7frw}7bifME2$HCHR= zvhG+DgAF-A2$(F`Awc^q0D|LQZgkkTm8j%;$$xJ5&to`XV+1#e^Z-e)C)~VKD`VVe z+;2n>bf-q|{QLrM3`nF0NTOy3OoNyXy`Z?!o&=+S1jGU4{E_>|9smrB+zxR8Gl>fT zNOvRcJzs5g_W@u}07P(OL;!$zYl5tAVgL&&7p9wdL+m~z1>Yhia_S5(wWWTy zI0y&CsOJQ);hB#1og&u8fJg}mY?rY*2*#11iWLI-1;nH!Slt68{UoT83IQM~38@hP zq9mxoE&z#>N6*9`G0-i6UBFmqaTJ+kQF`r(P6_M+kSD+rx!gAp_ZMTjBv=sx#&`S4 zQXD6y;{R+;hXgAG$VXu$P2PWQdD-Jl^Rqc5O3`4X%dmIAH0%N}{?YZ_F5m45!IZw00000NkvXXu0mjfm%+-M diff --git a/Resources/Textures/Structures/Windows/clockwork_window.rsi/cwindow2.png b/Resources/Textures/Structures/Windows/clockwork_window.rsi/cwindow2.png index 48ba09f65778c2c6acb1c24fcb8cfa9236fe820f..f29440596bc7a333a33239cf0f2d49e94b9415c1 100644 GIT binary patch literal 2164 zcmZ`)3se(V8otBJ$Wfw}h_$SQlqxDPAvHi^5`zR3N-zfl2DCgAFc6ZE3??AOfKa8D zU8rb9kf4R~$KG@9+pi?(G zcOOTeOQkyly47*;404vNnmB(g}@kwT%sL=sFQ*`o-1dAt}2RoaW?pUye?(+^7^50?q0h)^QN z>->g>N#YPXfuIYtFy`{)hcCpD#>qtbDEx3(AQHp~#E2YrbZ~?}#6yG;Z!;9j=jA|! zfpu?C8u5cPPbm_<1y#yjiRLq3ADU>mKCT?$!;1hgiAZ#@Cz9+*6nLRNG<_OBoQen$ zkw7opLOpr~T}8;dRvlg^fk>!RmMRJrN74yOd%hqdG){yN7~u+`m@iQ{)8IMOyX-mZ zyH08F2jbIoRZ|0e1#*cfPNzGALZ<1Zc*pqm0_F(34-pm{-zRYPOAra#PcmV+rx+2) zq%yR(^zlgZ;r<%&zOT2j{lr3q@u!3L%!^oy?uP0rLlhEOG*^EQZ$F8?)-aD|rOmFaCXyOC>8~om_IrjhB;VOt1`2TJ^dN7Z&Y8 zA!|R%ZOW{DkeQ!A${yG5gj6-rNB@_IQAeh4QeQu}3wsAH{rBxj5A#X34|(WJYBN;u zI5uxvR`KNLLG2Tq*}l>~Y4&zQ_t#PEYwiAtetR$PzVWU2TI5#aHmlxxa@wjPtBq!$ z%k5vSr_@Rcd+V|I2XrPf>{@9V{EF|}as=Gxv?jjFwfOeUg$;#An4~D@e1cg)5O(>% zjTT?x6OFbi`^$~kWkYU*zwGN>+ZDC{t|kcMy5)gwf2NCyqG7gT;WUn&*^lKl6G$xB zXW@VPpg}8zUMY_NOjrL0pQU<3nX1gCV05@L8j}M+QCuw9l4PiAy=r>hIMo|8R+tf> zrYMIDFYT4@wjP$(Pn-|jtUc)ey!gU_-=+`T>iX^2E71RZ1SiK?7!G>5?xu8uUQUi_ zTT~qx*mf^9a!TwBseq~40FvV8v?%%uKPJ7 z^72U*DCn$Ywp&pDyK*Q{SaYQroWe8X?G8P<9a=;1eaM2g9BwqlKD%}Ayqme@tub=R zr2>X!b^FqBEN$DbGdzFw^%;|+hZ}`(5c}TWXA=j_a;Ka2JignV1l=A@>CUS#3VizI zC*1?V)7ZXXjP-bLt;I6KRCPm>ALV?$*|?S6luzZ8ls#v}&pIZEM|Z84adRpIdd|j= zJjrg(2;pWupRKMQS3l~E{KXo)xf<2}()#&Sd~L_siy8aB&{+Mx*NP6NtDOrbcCJn) ztCGXSQ^D%5O3VjLcC5b2=n?z10nqY-YWdaEn^6tCgfch$=rdIhKIlj_R2P$p59>Gd zK4D^%h-n(eYPbCkm`<9>$u~1j{b!OAMnQo=U%!f@Ir!4)zWTs)u4~AOqR+al3pOpm zaMt|+JRDAVten*V@E>i)uDH5?xLj)TJa%DS<2U~dZO#Yx)-fA4+_@kJoUg5aDCL#^ zv>IxUdc5!Fz0hEajQjEEu$)_09=(~~h#RRm`DwS|%YZ_2d`An$Hp3X_UFulQ$6WdG zMr_`6*G-}2wZy^$d+zjzc@;}aa9zs@n~R@x;D&2Y7ay0d2Q0rnTmWKhVZAx$VCccV4Jl%wF+uqmQtF=9vK3IE=`^B<*T|r3cTvPN$sLy z9E#=QD*jgXqD1=Lie~8Ll=j?cL$d#yHD8#f9QS)z;?LFKoTs;X&lno~m8 delta 1030 zcmV+h1o`{)5UB`|F@FSSK}|sb0I`n?{9y$E000SaNLh0L01m?d01m?e$8V@)000BN zNklWutro6wC}$DJ>KsM4`fhb9jbm7cmqdAX}tApmV2)gIf+cdpm| zMUzO>1ax5+u)XaEyxTVlC2S@O57-54Y{~ta=m!P2<_g9N57-54xw%$Xrz8xIi>PP_ zD`Egpg*Gk08UcVqf>i>5X$e*c2tM8dlM<|}0SZ$RtbY-p3L3NC;1KszeAUsR;ma5>R+de`BwX zZ6H+vAb(1ND)7unhc28UZ|j|IFlqo3l7NX$c4dWIPNO}AiVGi%iy>%Dgda!h;DGFHGn2CE&xRJ z4u4#*2(XD=0djAg;NvqVyEQ=W`xZ6G^aRIbj{F+yxTBt=cBtFBXBQ=c=x zS{#G}V$^d&xZqKeI>Fi)U`m43K`@B~U91og7Z775gr?j(!Ri{Ih?Ag8CIo;;2{QSj zLuLekwAy_Tb^%D7sHyWLq%DD6z({Cv6n~jydDxaTC9n%Xo&ZziYTZE6H^$PEU_}fV zJ?JM(v7Mbt{@Pp`608uQ9)*!K`TWE6vd4Y%+8i>)C@|7xSUX@E_R(O}%hRY4E8qO< zXcj?&11J10^Dj?Fy*>|+G(p|~uhqq&x7?oSFQUblaT1{(EdT%j07*qoM6N<$g09TU A1poj5 diff --git a/Resources/Textures/Structures/Windows/clockwork_window.rsi/cwindow3.png b/Resources/Textures/Structures/Windows/clockwork_window.rsi/cwindow3.png index 025376834dc1867b2e6724d89982523f3444e8f0..e78030522325c579b865ab25c7d9261fc37bc19e 100644 GIT binary patch literal 2128 zcmZ`)4Oo)b9zTd*q0rmM(rcK&ytNbo$y5jt)cm-mIkS!CN)b?42m~*Kv|F*%EsohIi1@2FrRXM=WgbGL1)&}&hwo2ob!KwzyHVY{NLx@ z8ygdW#kgSr0NAL=usCGpSf-;r@-#@ccOeT(6&Dc#s&3)?kONM{i%N-(242YC5t)`@ z-uN%%IZqL}S%m{DveI1(|r(xk7|bu=4*Xqs<)?|{OKo5q!K743RohS z5iEZB$#OLuL?T%N&5r3jg@V~Q3bj&djUp6KMN(0kNCvB@z7${Tn|QD!O&G0SmUZ-A$1ObN~h5ReQ0zaI)ge}ACf*xC}6@8 zSSqp#H(QTYL9P^j)oQ_8B#=rh$}**VS!xhT>mwAU@YPb7#1?2IGND`(z@kp0US&^P zUvb+N1R@?8IRLuYae=dDcs+RI?;7a4opGd9zy^ykoh#?)o(1A-Nd zk`iptw?h+|?c$C55rhaw$DM#v*`mpei zWG7Ey)jyhRi?M@;v8CXYyQkY2p?-^}!8qu#YiDxbr~ZDy_J!pEYdk(2U%1FYSKPFH zEb_~({_btV(C!DkzWDs(pM4bAhFt-xJAd6IamwM3t*QNdp;2>ZiPMHW}12-cUdv@%{B#clqG%Kg1(YWW>h`m+hdkAh>4>Blzp< z&(9ql{ouV`J$I*L{Z#LG_=%nk4+~o-2wCj2OBdCGCC(tw(DtsH23;IdC85aB)djr3 zL{&p&^)u*p&Y4GK;%^v`B*b#@VElak-}BHqMU-P5Aj~5MfKr0%WI^}|`G;Obrn)bNY&mRKN-XclI0YUR@V;RgYa9F4*2P@2+2?%46&M@$V~}P2rDo^=O3~`_ zR)|+WN(Vq7^sxV%y|D?yt6nVGn-LRNe8%o~H1mvYbdBNqCs0GKiLn}pcj9gHnuY>y z;R_*rW{Ls)%uTwo=wb^j4z56NEn?XU0BfQz`D%eq9jx8mJ;8sN`?S~GpW+^1ud~CV9_RzTf|Ki zS7X-L0h~6ba*SVIKhp8!=E>W`UqBw;<(D@+a;w!3bhO-Ux1kh^C+}ao&j8r0GKa2` z7m0fg?wY#f_fvRL`~#h$afG1{U^-VVcNc59>e ze_Jz1%daGi<4<-TMIY!$viW|WonjBXuG_EPevoOxAIhb2?=f^a=hmQY*xB8~xdR>< z0P;UQJT|pc{=WA`xE~Pgp2|4lbNKY9{blZ5DbRQG%~u{nx38gWOac#pGfjB|-GZ)X z*=Y(hag|fjzgfP^*oW#J4)wRQQgI;JH7lB5)Rkb%DLdHm)h`$w`JITMdnF&t&s)gL zuQ^O4v~BFkSyb_H-iw8M#N_g%b2 z!wKC@xjN-%J3fhfhFQ>LjNB0eoI45-Qv2JNLqXM9Myp%HfHj=} delta 1025 zcmV+c1pfQb5Tpo@F@FSSK}|sb0I`n?{9y$E000SaNLh0L01m?d01m?e$8V@)000BI zNklHV%7>D05)I|a*e5I)h1cro4R3Mm&gn)qs7DmQYLS40VJS7f}#cj6(2<)B^et0v+siCI;qK>?>)D9B!BC!j;rV%-@Rwwd&v+p z#XTdPQ%BqM_9Ib#r+==~@sBS*h*sL8{>dJ^T5Kw{fnC6*v((A&B6|Fs=+J(mF;~K; zWun@W|M{8Yeko~u6BQTy-;MifZD1F0vPAB^CMutE=tHCB-Fe8EIqy`w3)W%wc56md z2V#pT*+93)oqtE;k4#R8v*utI0MPAm=c}*lba33E(mtZfgH~C5oG4ZZz?et3$MN)K z%Nzghkcc$|RACpey6OkKYnO`^93~qN*adw3Da!hyS6-bh8f!dY7k~!i&Z90R3KS7wDf>9OHdXdBX?RQXz2lImY^*Lq*a2}81O$5 zu;yoK-LD^71b{da!VQ**5KgoS0R1GO@mT(rcOG>c&?*2#NstYmKJ3uxW8@vk>ezs? z0NKzWVSfo&_e1V4nEVK)xH!?$1L8=Kym(Wm19`_whBm&7lZ+_84PL)Uop8c32$CHD zLja%QS~MQR0QI{MdGnLXUp`eB^^%*t$U4n6(H?gmLY`DdsJ7frw}7bifME2$HCHR= zvhG+DgAF-A2$(F`Awc^q0D|LQZgkkTm8j%;$$xJ5&to`XV+1#e^Z-e)C)~VKD`VVe z+;2n>bf-q|{QLrM3`nF0NTOy3OoNyXy`Z?!o&=+S1jGU4{E_>|9smrB+zxR8Gl>fT zNOvRcJzs5g_W@u}07P(OL;!$zYl5tAVgL&&7p9wdL+m~z1>Yhia_S5(wWWTy zI0y&CsOJQ);hB#1og&u8fJg}mY?rY*2*#11iWLI-1;nH!Slt68{UoT83IQM~38@hP zq9mxoE&z#>N6*9`G0-i6UBFmqaTJ+kQF`r(P6_M+kSD+rx!gAp_ZMTjBv=sx#&`S4 zQXD6y;{R+;hXgAG$VXu$P2PWQdD-Jl^Rqc5O3`4X%dmIAH0%N}{?YZ_F5m45!IZw00000NkvXXu0mjfm%+-M diff --git a/Resources/Textures/Structures/Windows/clockwork_window.rsi/cwindow4.png b/Resources/Textures/Structures/Windows/clockwork_window.rsi/cwindow4.png index aa4ed12cbc5dd25ec5df058aabcd5abf3f3c7e2a..228081ad5b9ea416f26648cc0b4e6fc1c1e36fe4 100644 GIT binary patch literal 2112 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|_);T0(|mmy zw18|5AO?X;!IOa`XMsm#F;KxA5N2eb5`33|fjK8LB%&n3*T*V3KUXg?B|j-uuOhbq ztjngt3dqb&ElE_U$j!+swyLmI0;{kBvO&W7N(x{lCE2!05xxNm&iO^D3TAo+dIm~% zTnY*bHbp6ERzWUqQ0+jTtx`rwNr9EVetCJhUb(Seeo?xG?W zUP)qwZeFo6#1NP{E~&-IMVSR9nfZANAafIw@=Hr>m6Sjh!2!gbDamkq3QCJ|z_z3$ z>!;?V=BDPA6zd!68R}!xSCW~AaA96CG&q0(qYsh+YBRv9&9k5+*#sC;t`$J{K>Y`F zXfoK|;*u17BnA3L1_l&2TID3>rQ0f1=%%EmC6?xtDA^^KXXd5kmz&$@LsX&ahKQmXYNL{p zmyJF=C)shWbM3v(z`zph>Eakt!T5Ie?))nTGRN!JUXXQCn77n+fsIPkgb5A?3;Ygn z@l1WemDJEUk@bgsLSjNf1LMIeSDpih90Zw#Lj{HUotuJAO)Z}&F-v;gkJ)$pe=LeA z>J|Q9qdTo=<6Mhx-ygfz{IiTzdBax4^|}4q)fZ>o7ws!`Onmmdv!LduYsssMM3r?N z&(~dZd%R9P_O;(G#rLlT?r*m{k^0qZ(ZRJYtHW3xeLg3BK0Zx(@(!DT&lZ02x|iA| z&#(V^YWb5{{ngK$)^%=YF!>$3>Y8HR`*&x#HLKOWcQH3~#j!Hh);+pv@>WAMbHn@> z=bED|gZAi+<%_$lJTwJ>ic=`?JITaK5)M?`!C8Ku%7*q{yfaE7D{;3*YCj zd(NF>XmAkA6>bVV&fI`$kln;!5my!&p&BP}q8;lO`3RfUq5 zM=t+ZKVN^2$K7LS>~?w+-fos)xa}1EG@Yk`eN~v` z4!L|D2Bymn4;uZYCKxiv?Y!(TL9G8zFXIEnxjY9Y7_QeWcQRmW5Szeu=!V6`S&w8U zb?@?FaB#F1IK(|Shhw731jz;!4uSrs`EzdSYtH$6PQ*c*L#HCcemAjk zSQ)wJZus}&Sih^O=reN%8J2zD9(^^*eXsrN*@l_(WwguBozY|9uo2iK)3Wj0`mles zpT!>qeolTo?>_H?`d`!DPqR$7VsqKba^g_N|KI&aO{qWF^R7PsRC=lrgM&p}`*yjii=8^h)2!H9PRp69 zCGa!Ewa*aQX&`Kp$C!BWp@Bkz63cA+oc}kN8MYU`-Op$^=UAFWIfDRmvAM#P*K&Kg zzg+g)D#^mUXv^uX+%Fz6Fh1JI&%pl2n~Nc#W&55)={Z}B<0ktji(g3ZIXqo!@g#vY zrHrvDS8hA*&%3P8#K08WsK9nWlw%P?j@j3+%D?Ovy3Pc3#(&a1P$8FaD`?R(!Cy9w z^Uvq=?mPCd?|)na>#KCJ<;PoFizD`{_ujv$m%!b$nIT~ITL+Ke*Hu!>8E-T^umMI@ zRqnEn4oIu-~E~ZmY#AYle%51OMqL zb}+vPDh{l@@31?*CzbW!sZ|9bx~~eC@@BPnT0KaxRQvR2>6az_%QrPB++$Lh^_}ZL z#;1L+elGj0^3h{@t1vr*wW68-f@d4c4{Q^D&$O@8=O%Zec8h%c#7{FAByI#Pw$9V- z$d*Xz{dZAH^&0oIYw}-z+RS5J%=w1x#~QtJGxN6p=jKPPz0*IJzf1=);T3K F0RS;GDEt5b delta 1041 zcmV+s1n&F55VHu7F@FSSK}|sb0I`n?{9y$E000SaNLh0L01m?d01m?e$8V@)000BX zNkl*=hXJGn^$R<(^o|KOI}SxX*s;}f4lo8U>AU9e@xuC6NchQB@VL6h}J0zl_C7g%>AgZ)&3C;)r91@%o0BlQeLO|u4 zEJ$ohaIOVJ*plFkfT*HzY)EiIK=cyCAwhdSVCsf9BY%tkgn0SMKYYjSqO&cGw18G5M1hYRZ2_z0rQn>^mSCg>WLbiK3>X{^&RLaUCI+-1 z0n=aI-iG{%4f#sgY1x<7dto^wM)2Y-8rRz&6JMN2?31b;XESpR>}LHo-a z%?QPx1Mb`}<>ogU=`p3{{_f%+tT&|Sl`5e>N!F+rCyt4 zji%aU0L}b<0TrszAz5*iq*idY3)qt2bPP~Rkd;<_)(XxC!L%i0Viag3L6=Mj0BK3c zi~wM&-^XDWfW+y{Z1ekrOiN%F(3hATg?|uPtcytr>;jM{z!W(uj-%NfW2PiH5d#Je zglh(HoE>X^+nfmrP6&unYe<@W`059#^S0SGheRnVjC2{+4%mkMZSdMfsv@C^WC>yc zc9Eh*EPf6@N4JQROvK)PpjQWW0jllu07(<%4X~}Q5qit*iGBmus+8*{>AXAu015yA LNkvXXu0mjf*^Sh& diff --git a/Resources/Textures/Structures/Windows/clockwork_window.rsi/cwindow5.png b/Resources/Textures/Structures/Windows/clockwork_window.rsi/cwindow5.png index 6bf733f81ae79b1f67254fc910195ea0b55cd8ea..89c88d12e2a608fb0475a4dd93453b5a43021f58 100644 GIT binary patch literal 2060 zcmZ`)2~bm46nzPSL=<5JajBMXs4FHvq*x$^B{6IkC<0=z3Wg*=0Wbo9-&$g#_~=@!8+pDK_|6E?L%!PXt9|5EoP!C$!<4kz#&GVptfMfv+ieH@C*9-|=yn zEI3wy1B%U^K;9VD0)Q1FiRNScuuzr|O{EJ&Xo8roPL)|$Y&8pCriw8Eq)tVo3YOZ3 zYC*8@wb=|)Aqxac@uBj=BA_{_Tnv3jXV4i`Ut0)**m6-KE0PyDK*x7J)MN~kv0zxG zQqfi4(ouO5?C$OD4KtW9lS#u7G)1};6R2rYg=@c)_kMU{g-|Y$VG>jdnf(e9P$lL= zrJ4f`w*EXt!ofH)r5v$D5eZ>2B2E=cF$L^ScZWa6!z76xGL$L?cq;`Jn#2t%ZpST2*}wPlIN90>Pi z#HYSK#GWseV7~7id}1EL8ge%*jvP~=@|0-HJ$w-Hi;w{~{elju&;H`Kh>usluPqxM zd`Z5x6#@As07xz&JWjNl@T90d&&l1X;bw08_8Yg+4(HA>>QZQ0TFk=T*}A<6+p>4% zzxGQOO15PuYtokPZ8~$U?9ghzXE(ZE+V9`&mUhnb*s%u2?5f&R_r%r1&xR*fYVW-{ zRrF2Krirfi8FjlZ&X&t^1z=7D&<=4y3_t=?s}>AgrH*_uXjDMzfX&Qepb+UnFbQ; zP5W8LU78N1Zm!Y1s$hY#%^nWVjOXk4x|Y3D&LLB4Udkj_^Nw!FDXS-z-E4q)3{95N zbo}J`3GmamjcDzva;ryaQJo9uq1Rh`Uq5+)OzSk1_S*i`t38-d+HDM^m;AulsoLEa zeF!*@0A36CZh5f;n(rEcZz;DaGmG`!b>#{V0R0+}ljSfP*irrk)dzOv=IkdafkVZx zNw%QSVLL%*Ef`^4n^m-FeCeXD+TN|I>0hPqs00h#cif97Fl=XOb8=>;>%*79&Jjrz zBT$dfyOELr<0Wg3%*H^AUqFewY6S>D1{qBOTek7L6hGSg2N&{YTlrrhXBtM8)GyL4jtYA`^2fJE)qlpgKtgm$5SVUVkfB^z)rGdi z2hTaa`Y@K*c;R~AYhkf2vCSokw00HK6bw80)e$p(VN;&< z%9h;pi%%)3v&w*mWqPvK>qA!bJ)RnQYOM7>Pyg9o=Z~(7$x?e{{F8F1xoRx2AvE_9 zse?UtPueB2m+6Rg!enQ|=nVyim;1=z*rX`|?q^AL`NWwFjSVR@>sEJ8hl>U{9F+Fl zoRrv|b+}>zIBsaMqqIo5`lxsN8xR{#pKjue71lew{4><;R))-;N+KA0jfOValuj(x z+}b`*SK{T(Dn8tt*8I?Pl*H^}X=dM+Y zp2C{pvaRImg>zfkT%%*pEA~>^`1snV@Y+Tqe?ne^w_CCPzA7*`Xc*vfIcuE_I)^}s zQag1im;~|cbt6_I=jPox03s%5HG@ZF!N!

6Zyh{%U`^=18B*Mo(5S=h(?BgwVnh z^Tq*Q+`|(qxDjOFmwCgJ@yPGwPaI0+jAGNeuDFycZJXAL5bn7BIDOZqcj>3eB<1jo z)*u4OY)QYAk>7kbrPr1$W8n{{aYE9B%*s delta 948 zcmV;l155mj5Z4EgF@FSSK}|sb0I`n?{9y$E000SaNLh0L01m?d01m?e$8V@)000AQ zNklwh`36=J4#bfSCp;x?_n zBdQ*f*ScMKeEdqZa3g8Rt7aDOrwgh%5_{B{4RpSGShn|163w3=n%XBj9|Cp(xbu&m z64kFKJrS)=&BT>zL75)kvv7i~H{o6!7mqQ=9t zu72#5C3963f2`M3p5x^-Snh@ZU z5LFJ~kYK$YuzWjNQO%LC{XTC?bhAKcb_J;O$oR_6p?`2P0?I7GT7d6)+BfzipwgwS z_S>vkMhW&gVD4mgE~^ALIbZ|{Sn~_D?l%l40zeT7{T!J_%U&Lj@>b{OEknPV6`t0YxNep1o|-scMpy z#5!NpMSn(|g}@*Qjn(b?z2#Of=5gmmNMvCULmqIN156SCvi1vEW<)$V<>09VYk6+W&zmc^$I=_6Bg{bww!u9B}tRtB$y@h`)#= zh&%w+Hthcg8@!AFjVT;34PrV(0{riu1WiB!W`6J^g;Ct%y<_7Q0_+A zd##!F_5ol|Kn%$+hyVZyuiAh10iZor0zm(!r%*e=hQU%7$j=Tpms;aj7Z~)!$N`H0 z5Q_vh0U!nmtO8ks2NaQDOY}+5w}ev60>dQOQVIdUmxR&?0IuRb54!*qPFGfo?-Ot>fnC5%-{L5Q zsOCUiN?;d&Isul*(QzC_-xzZxA&ML@dqnOTz;We#@z>^DNQgp!-YbBj$?FekRyrS> z*XFQC03AlT40{Jc!!7{vkD)Jyd~YP=b1j0r;tzHK*dw4jj=cjLVl@2t_4n-H2cqBE Wwu-~W40$*J0000G?W zUP)qwZeFo6#1NP{E~&-IMVSR9nfZANAafIw@=Hr>m6Sjh!2!gbDamkq3QCJ|z_z3$ z>!;?V=BDPA6zd!68R}!xSCW~AaA96CG&q0(qYsh+YBRv9&9k5+*#sC;t`$J{K>Y`F zXfoK|;*u17BnA3L1_l&2TID3>rQ0f1=%%EmC6?xtDA^^KXXd5kmz&$@LsX&ahKQmXYNL{p zmyJF=C)shWbM3v(z`zph>Eakt!T5Ie?))nTGRN!JUXXQCn77n+fsIPkgb5A?3;Ygn z@l1WemDJEUk@bgsLSjNf1LMIeSDpih90Zw#Lj{HUotuJAO)Z}&F-v;gkJ)$pe=LeA z>J|Q9qdTo=<6Mhx-ygfz{IiTzdBax4^|}4q)fZ>o7ws!`Onmmdv!LduYsssMM3r?N z&(~dZd%R9P_O;(G#rLlT?r*m{k^0qZ(ZRJYtHW3xeLg3BK0Zx(@(!DT&lZ02x|iA| z&#(V^YWb5{{ngK$)^%=YF!>$3>Y8HR`*&x#HLKOWcQH3~#j!Hh);+pv@>WAMbHn@> z=bED|gZAi+<%_$lJTwJ>ic=`?JITaK5)M?`!C8Ku%7*q{yfaE7D{;3*YCj zd(NF>XmAkA6>bVV&fI`$kln;!5my!&p&BP}q8;lO`3RfUq5 zM=t+ZKVN^2$K7LS>~?w+-fos)xa}1EG@Yk`eN~v` z4!L|D2Bymn4;uZYCKxiv?Y!(TL9G8zFXIEnxjY9Y7_QeWcQRmW5Szeu=!V6`S&w8U zb?@?FaB#F1IK(|Shhw731jz;!4uSrs`EzdSYtH$6PQ*c*L#HCcemAjk zSQ)wJZus}&Sih^O=reN%8J2zD9(^^*eXsrN*@l_(WwguBozY|9uo2iK)3Wj0`mles zpT!>qeolTo?>_H?`d`!DPqR$7VsqKba^g_N|KI&aO{qWF^R7PsRC=lrgM&p}`*yjii=8^h)2!H9PRp69 zCGa!Ewa*aQX&`Kp$C!BWp@Bkz63cA+oc}kN8MYU`-Op$^=UAFWIfDRmvAM#P*K&Kg zzg+g)D#^mUXv^uX+%Fz6Fh1JI&%pl2n~Nc#W&55)={Z}B<0ktji(g3ZIXqo!@g#vY zrHrvDS8hA*&%3P8#K08WsK9nWlw%P?j@j3+%D?Ovy3Pc3#(&a1P$8FaD`?R(!Cy9w z^Uvq=?mPCd?|)na>#KCJ<;PoFizD`{_ujv$m%!b$nIT~ITL+Ke*Hu!>8E-T^umMI@ zRqnEn4oIu-~E~ZmY#AYle%51OMqL zb}+vPDh{l@@31?*CzbW!sZ|9bx~~eC@@BPnT0KaxRQvR2>6az_%QrPB++$Lh^_}ZL z#;1L+elGj0^3h{@t1vr*wW68-f@d4c4{Q^D&$O@8=O%Zec8h%c#7{FAByI#Pw$9V- z$d*Xz{dZAH^&0oIYw}-z+RS5J%=w1x#~QtJGxN6p=jKPPz0*IJzf1=);T3K F0RS;GDEt5b delta 1041 zcmV+s1n&F55VHu7F@FSSK}|sb0I`n?{9y$E000SaNLh0L01m?d01m?e$8V@)000BX zNkl*=hXJGn^$R<(^o|KOI}SxX*s;}f4lo8U>AU9e@xuC6NchQB@VL6h}J0zl_C7g%>AgZ)&3C;)r91@%o0BlQeLO|u4 zEJ$ohaIOVJ*plFkfT*HzY)EiIK=cyCAwhdSVCsf9BY%tkgn0SMKYYjSqO&cGw18G5M1hYRZ2_z0rQn>^mSCg>WLbiK3>X{^&RLaUCI+-1 z0n=aI-iG{%4f#sgY1x<7dto^wM)2Y-8rRz&6JMN2?31b;XESpR>}LHo-a z%?QPx1Mb`}<>ogU=`p3{{_f%+tT&|Sl`5e>N!F+rCyt4 zji%aU0L}b<0TrszAz5*iq*idY3)qt2bPP~Rkd;<_)(XxC!L%i0Viag3L6=Mj0BK3c zi~wM&-^XDWfW+y{Z1ekrOiN%F(3hATg?|uPtcytr>;jM{z!W(uj-%NfW2PiH5d#Je zglh(HoE>X^+nfmrP6&unYe<@W`059#^S0SGheRnVjC2{+4%mkMZSdMfsv@C^WC>yc zc9Eh*EPf6@N4JQROvK)PpjQWW0jllu07(<%4X~}Q5qit*iGBmus+8*{>AXAu015yA LNkvXXu0mjf*^Sh& diff --git a/Resources/Textures/Structures/Windows/clockwork_window.rsi/cwindow7.png b/Resources/Textures/Structures/Windows/clockwork_window.rsi/cwindow7.png index 6d2c0e0650ea87482405e72dd57986599e1bf6f7..aafe2b5051d6bd0bb148bfeb3de2ee82737b3b94 100644 GIT binary patch literal 2065 zcmZ`)4OCNA9KVmjfFZgFh63go6k=>|%m|rdFa=@hfIw=)5188<>@fDm_K*QO29hEn zsh9_8M-lsWi4+nfgyu{$9ij$hMm8!T!|>q86olRe0($hGbKkx9|9-#!$M62%dE1i` z;@n9-BmjUrKRzZIU!!f)g@`{tm*@843#3VoTLzAp{RZ&EY(&VH2?SsfzIVZ=ZCpyJ z#-FaLc##GN7;F=A-jnhh00f16wGa~uR^vBXxaES2f@TtZH_{z zVQV94b_5&W+srVHYKLIiku;$oiMkwBBh=R!Oa_z2B~htVj#?^XC&#Rqq~oVZS{8<> z*f5-*pU=o&%s|zdaA-tC1k7Z?EEXL{&@}~0Osu6VH31V&9{Y(wG!nI3g~?GR)#g{c z0nNiAX*64)sWFkKR5BGum8VwNqevw%qCj#GC8mKx8KLmAc$i!^ouN`QDF-eLYRplevV>WYJj>@Kk+x`W&f*jma?uVi#_z z9=n1(1@@%XhPO$eklU1HE5ypoNSc-|MP%YU1xDja^5se?njg-ACs0qaC#+98<-pH~ z&#_g_79}GZRFP-Xof{Fxu}krUary!#2*PI(W*VO+BxRu(iuaRRF5xRNM6FWey=9Nb znhf`R#M8c}W2Y+R827P*r_3{0Gwz1XQ)Bt4I(xPK9;QWnE@aZpgrGC}bE5g};^W=V zC2`=XFNsS!61$@Z0LMUn3~#j-8vLLgy~3RP{qKi94SM6%C7-q|P2I##TIBEF*ceJ6 zco?a~xpPJOafq^lIG1ch2(rM9j&4ocOqs2HU+F<`(A|myLKLZA>#-rIVR?42_n9h5 zR8&Xf=H`?Dad>O4bY5)DzO?#o%DNiFtF-SFt!qGXD5$zZJC-)COx~1s?VBdwiYl~n zhf&%nH)It$cbRG^9UgDiWo|C%G~el$9ZI}F?AjNQSNN0LceVeut!#L(YEGxBy2a_l zzxO{&+h!#!PMKHn?>$N`*m-$1dB_}9&>VgI*Sy-^1nh>cxciGM)=#!~I4tZQNsM6@ zwcNTvy>ozFd(Ape!v`jMvSRQK3F7t9Kgr6h6G%W4($Z1{SFeP=D_Ft7ij zrT8>m??eDq8;dfv%$@Zwl&=A9WvV3cMz#_!WO&di)6z0M-xKo z&XJ9fYQg$cmu`@8D|KszyFUBd&&h`K&cFd&*B@x8_E|15cNT{1-jkSSIOe1xib773 z=fBeT4q3O=^vgWp$#r!wNgn!U-dpKX_4k1138qVk_2L+NJ~#f4uB$%uiu1?9fO7P_ zC5{da>on-t`qBQ)p($q{d;!(OCUpLBX>y?rEh(K@9!p^^uJ*c0`DlZ2YFlf*hpf1MA+T;78@uHk9Kz?K+*Aj zj>fU0eaDJ5B12!G*$hROxt4^pE76PD;~xYytx69$QRun%wE$B)6qw%HwJ+9Nm=aO{ zLfc)c3!hUPbd#0!;RBspBVbg>UH!I3f}h>=yj^nwc$w|Mt#UsE5&Vr0B!dfz!1deo`GyokfJ&FFusNcXd|jJ>FHXhol+{fGmx3fb-~K63B@8x=rkB zX!=T7Qe9Xgww&+%!}?d%Puvc1fz%xy^kTYs_AITrjXaD6(RDD{1gs7`&**(0b3+=! zz^Svwy+f%e)ZGWxtlaJ!SJUUHcQ)mw%qJJrEIPg!9=XrUZQl~ypZ>@K zhJG*%08?Al@bNP0Y;e=@?{76NXeN#~5Jwe(u?AV2I`gY& zL4833pa|A)+@c!b2soEoRTgkG4iq^h4gb6}srkk6@bZQ;jmed0c^BpStI0ys=$ak0 y3m#+d7H?@wuKeiB0>nK^7fjyOdvM{8R>Ds2U4FdVX$x(?V}5Kx%#mdorT+r~^bE-W delta 970 zcmV;*12z1S5bXz$F@FSSK}|sb0I`n?{9y$E000SaNLh0L01m?d01m?e$8V@)000Am zNklVupo}kS=9qDjxzSR=PA_0%oL& z6}1dNg2Y<`X?Y1CigZY6@ZV>{DRt85&gaM1^e3I{I+a@g&VPQK^W!TJGgC*$x+v!> z9V(xYP1F@FxHj8F3payW)M{q&LAao*i8!Q6Hj3k8sz!8df@tmx(d2m4c^9w?C>8(6 zyI;K#Q2Auk*4T*d{9bq82J8Yb>@SGB{HJJUbEk=F zkHf0^I8(e3@PF|$(UWJ<_4Iitr+}CenGb)!E?{RTn)7#W&(?6c>^xu>u=QP)8}DVg zv^eXm^MG9dI*dDyx|T3~N<>9Rco74D?zC$O-Ut9361)-sTua~&f~uo&TuSg_1aM05 zW(sgg@G1syNJzaOuzV+2QPo7GeV$K?cdLMF4g{z&F@IS_XIEGm0eO~?TEJHGohAq|;~0F7xnU>U@6D1+jD`+p{A0urziAm@+VKh6MPT1*$!FEEq2 z0DyEi(%!3U;lFbLI1>O7+&B>cAmMfM|2Y8EM@j(bJ@n-2B-kJ_T?P6PUmb2OHAXKl z(C-@~2P^`BFA~@U03Rf<3h;pg0jeBXMqU8xlNd04k1*{l>42#}(?93_eE}1u)uFfJ zCVxpu@OBEglHhd==qsVn-L>1C6z_weQ9_?B_ax+E6&NHTEx8Z?vXYP+0l*|7E$jl2 zI9+)({5b*J64(WldNxNPL{$0h^0y1+`OA-|-a&z*EttxDlz$&bOY>=?Nk^)#sNw%$0gl~X?bAC~(f|;Iyo`I4b zmx6+VO;JjkRgjAtR6CGotCUevQedU8UtV6WS8lAAUzDzIXlZGwZ(yWvWTXpJp<7&; zSCUwvn^&w1F$89gOKNd)QD#9&W`3Rm$lS!F{L&IzB_)tWZ~$>9$H0x+$q?iKRIuN_J_bIXO1^5EZC8A)=@T+UR4k+Xm!gtH_|#;{2Ra zP?+0Un%RJZ0YwlI_z(>d*fbyuqH74q$S=tUrlq3HWY4^k)S`kSV7da^X9Tqlw+eK# z5O#;=WtP~%3_ue`(uEW+R*pp_<@rU~A>cTG1Rzdns1cCBL`s*CL=O&lV5+y{veAd< zAUiID^hu?HH@2 z_bUE^{KEQ$dM?`|S4EdT_FKtO=kj6mGOa9b*4a77D&L*;RP*F^wwlX*^3G1Yk> zAZAPR+tXK1y?lI$!h~=AqNVQ( z@7i*5{=O1t`BC}u?l*sZ)@{A@T+TYhL{r}z5 zpIqW}ee*5a+$-cG{C+#-(X2_YjIHTy8Nk98Zm$$6D&r2zAI__sZ(A)Wpu~BX&M-q;^CPhi>2u7=8a>MXPP4w$)sxWbJ#icx|F7vE*e zoxZq{b2sCT`x+gl=85wJGS=>7-{okgCA5-};TA{7ggtYwSmvJQYC0qRcET2oo0n7; z|8*+4t)^Y(`SP0XrQhr2nwLzeo3-b{KkZ3;5_4=fS0C{_y7EBAm+8}HGX%f=bx@S| zeEfCeR)veM8)|Nd+si4ob)IJ1&iOWCNyd+e)z+s>1P@H8%y8RTR_(v2`?-ip*q<3` z9&?X5pIRE8KijkVQdC!+6o+v$TU5p(*)wxOkE}ehPQ@q0^TN$}3+8#7DW{+D+kEv{ z4qsX3jc2v@TxE8DX})@@SS_N`@7BI~$NbNps@vTBoFQ=DfA%|jQ-kg2{OSeO7oM(u JF6*2UngGrQhnfHY delta 711 zcmV;&0yzD$4c`TjB!3BTNLh0L01m_e01m_fl`9S#0007!Nklw>CVM=hn1jfBZBI06=*8 zvL}_7k#1MGoqv@her2g7TkoqfDBIoH)(~k!kFn*e{q%2(1}rY=LV} zB!@8lNp%5n;vsb93H7f|7Z7cSuxp6w7b%wJdVt*rghrF^67J? zVDr8g|3(9aAkamSgv6hSlCcQ@&m#BICMIM`d6`i!5CpnFAZ`uWX1IpcldDlDOG@w6?Q88~xyk9fut2TN8mFBnZ*jIY7IEgKu1Jx|QZe>~ tf^j>D+XEj+o6tHx$0h^0y1+`OA-|-a&z*EttxDlz$&bOY>=?Nk^)#sNw%$0gl~X?bAC~(f|;Iyo`I4b zmx6+VO;JjkRgjAtR6CGotCUevQedU8UtV6WS8lAAUzDzIXlZGwZ(yWvWTXpJp<7&; zSCUwvn^&w1F$89gOKNd)QD#9&W`3Rm$lS!F{L&IzB_)tWZ~$>9$H0x+$q?iKRIuN_J_bIXO1^5EZC8A)=@T+UR4k+Xm!gtH_|#;{2Ra zP?+0Un%RJZ0YwlI_z(>d*fbyuqH74q$S=tUrlq3HWY4^k)S`kSV7da^X9Tqlw+eK# z5O#;=WtP~%3_ue`(uEW+R*pp_<@rU~A>cTG1Rzdns1cCBL`s*CL=O&lV5+y{veAd< zAUiI7cC`zHxUjfR3UC%|YAUtgTzCEC>33<#j`tPcA3sx*Zj}FQ_xg=nx0Z_id%UCN z{olWT4Q9`MlIXMi@`bFepKQB-thsrI_wmQsSMokx|K{%Q{*dXxJo z(bB-Fz58b3{aZC-7?_FGeJ`FpeA8UE_w`|JPO1n{0o)4lxqovo2=aMY#S zS1+E5kz_b$zqi&_Vy~6$muc1gzq>0r_TH>Wanv~R__@D+_1?MJx0|EC%YSo<;Q6yN zKD>frm}kfHU^D7t3JLv{Cldxh3~8{-WK-t z+IL_7l*zclC~(n)7fhm4c)A&;GQP~{D>XjTtm^YqXJ=E@{Ps;e8WXHOdogU`sy*kk zbvf&IWwu8=GmSR*olia%agFuMKDIT>zFf`#ZEC`PVJKO=G;rEVZQbeM3gDin8VAbq!&Uq!xVAvb|`1*K}sh$%PAw zRx_SIztbd^!$fW7E*}kBL&bB+@!GKus<(AK8D>bNgZ8)6Ji_R($(1 zdDo}Jm4{nc8g(V^74BJA!+)Tl=KSup--KjW^Gf^M7mwn*Xf+tG_d;_BAJ$$Oce__JFx0?U} delta 814 zcmV+}1JV4G4#ftLB!3BTNLh0L01m_e01m_fl`9S#0008_Nkl8S%5Z*`@ z#VHVlvjsvFkx`a9VS9bfe?|;oGwCDJaU6@fp0<=0YZrVjbm5=pj-zBW>AzI0$mi{lO+TQ z{MYq1Ut47YN=QolPm)CBd2Sdd$)UXF`Kb&@6(C!s-*Wh>m^@DlfFlEX7}}l!iTM*! z1?XPaullN(^ndP=6W}|00LHiO-p}rY(G2&a_@P|CoK!o1e*H|T0(BiqyHWgX#{HLe zyUrY)01))Y*U#zrE+2VxDdU06~%b z(ca$ixAXHB1QG!RRbXUEPCkw9>bm~!%waU4O%O;20e^AvfX!AHXA`2ksblG#69_%X zk_Sw{{9eU8lub&x)-<8tcyLvqj~D>dHawMAbTQtw{(hUaE9j^K>+E<;o%SUFzD>Yt z#Aw(;=yn9>PPDzK0_*I=B0e#u0e}dF0^(YhRN_hc>3wDBsq~5my6wtxEUzaguMPi2 z1xzQOD}TvN`~!OLG|{3+?EsqbAQECiUfQrJEw&N@p`*L()Y(DJgQ~h%X!qUc0TLI( z`7$Bd5fdW0wF$ZKJqvEvgF<|mklTGJ-WfdL1kgwN@xYdK)u3X&XSvwu)y0ImEg$jp z3Y=7I6BoC;D&U$OT)fT$=wggiJ&+F*!l&^)Zhv&yZF}{lbOHd2VS8bu>cBjiFylMr2#L>}9NiypWrFtG`6DsA@x~`slx>5mRI9+e^)#d;AGD5TU{kVj< scqhR3>HoIoch2gJicx>pFZUC8alCj^j)X6U`63}+ z6_*_=N`c)81QpRrTh5cqS>X|U_K1- z)WWTtN39?ofheC!vY@N#bGi7{ z;v>~h)24zeZxT&g=URCo0ANO$Ui45oYAoVjk|Euwcv0u*cXlIq?ep0M`I!rSvrO=? zWzK<$EDta>=i;t8{fwONG6;7?7tA85y?t52op`r3dL_~yLPC$KkUN>hwhQ22+BYX&=1>Jn?yS2zNvbpxx z&b(5Kx7}|ja_R)8WS5Dz^_;j>-y__pC$172swyc&D_T4|d$tcWR6j^H4K%-s&DLdX z@u8!9^rMd_u2Zm0E7IEzOn=XAE*kh_>9_jEr%$a7u))tDqYN~rcN%W6>1|G-n1@^F zkWv}YHdoi|yck?7fI97#`?P53*q)(`L0!RE&mPH7Tx!dbvb)LB*>^^>Rh+p+9HsHU zp}xBn z5mD6QzE{5-*B7_xfRl%@y&8a#u0<<=vz*DtAG!j+Z6lkB^^RVwbXb>IhB}nDk*Jq$ z=~lHLdXcVtZd;}&AUe0}fWX8(%n{!|vMMuw$a)aJP0~U)F`LvhK-=y^KCP#}IhxM` zF4Xg|>n1}0`H{_Tr_h(594m3ZXKKC%6NW>R$W>!uv17hvzr8!{VpI-2VA=!a_S1G+ zIeOW-{@;gp3;f{kAS)1ezZXax~LO-Sbj^zF+O_$%5os7SOA3_S&k%=}m0m1k|4V+w~36sk)Y#>vaIK;?bD# z6~E12z2lraA)PR>ww?Ds*O8W1YsApgq~q}N|0Gz;2iIj~DgzInM{(tt1Wp=cEsvJi zM75iccwJV;io7+$Q%&KQx`BV|J__4pL-ug`S4H8?SX{nh;e72d4(&DaX8)!qs94

)y~t`X>T;ELNi8WIhO!u;GerMlzNr__gv(>^ogb`F2t_&ctcak>}#oA zyTgvOig|P_>dL5c?rnNYVH-n3TtZt&q92}HUuMfdmyPw94B~X78OH=Ou63xr!H-?> zeV)x{gW01%MGX=T3TEHZtZO>fSV6y=*2V&y6^q{h4-R^d^+ioZe z+@Wu1bqj;i+KGA?Pq#a8Qd^QN(p35p>! z!j52M{3+QP5KeDHJ54dFou&g@KxhgghQ_Qi=r~>+6#1)R=e&Q<*n?F%MVm`2%s0- cxj1*Ijn`70Sm)P=Q~gCSy#u^zcEn`-A6%GVF8}}l literal 3765 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 diff --git a/Resources/Textures/Structures/Windows/mining.rsi/mwindow1.png b/Resources/Textures/Structures/Windows/mining.rsi/mwindow1.png index 48c34617699d29bd2ba458323de5c3a8d5559e88..9358df081f8a69f3a0449d9c004ba8cc5a10566f 100644 GIT binary patch literal 2196 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 literal 3765 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 diff --git a/Resources/Textures/Structures/Windows/mining.rsi/mwindow3.png b/Resources/Textures/Structures/Windows/mining.rsi/mwindow3.png index 48c34617699d29bd2ba458323de5c3a8d5559e88..9358df081f8a69f3a0449d9c004ba8cc5a10566f 100644 GIT binary patch literal 2196 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 O0000qK@mOno^!YV{@?%o_q+c)@B5Ho zKXWr{GXMb08UFN8WTxr62?iN233hiO6G|TH=K~b}zPumV%;Pc{yr3XpHL^BAy1uo9 zr6HrK)IU-V0CO$$9R*~cS_%MYp&*9}-;z;7SM5Rb-Kv9%rWGUjpEUZ!_ z6wAp8Wbiq;0uvjcb#^I4e=^Ng`k)0Qg z55rP21Su2>qQZ?Rk?nw7Jv}`k7ZOAw5fBf8e2*ArDG6e^!*r1Map+t*TPBdg0*M%_ zkIRaa#KT@VoStZ=P3OsB&+tg&WkLfBhYfLsToG3c%OO{yEA%-WEZ}{}P%M8Z2O

    Mar6oV8W89zM0G=TXzz-;5EfDpa}mLT;c6R;U#m@AXY zklHfvy{G$Yk56NL;EoUrVCwq-pO|N%X1xvBTLvp6vR&bZclaRUU%I>tGcD+>`kXF) zgZN1GQ_U#Q%$Gzpn_F=q69B+e2HiVci5lG2xT}@6_>4vqe*O;6@*kn}x|V~AeqBQV zD|ftTFZ1~$(Y8vBdeJ5SRZO^yzbYec{;uo7hcA_hk!h9Mz%NeM;j4m5P219OtyY_A{9QkVuLhosNw}m372lc+shzd zE^3;;w`S{3Z=jcCS)bT~g3Z_ZclUXSkAn2g_@8>nlB3`gp8|O2QE=rwS=7}GRUQ*n z2+9-3>w=U22^4~?seRX?|Cl2sorhGVm;se(tqzEGJBXYeTe81O>XB^RJzVtQn!-5Y zky%VmgBonbE#a5g)qC*E>>F;`qZ-rtpmCec6LD=TJab}itHBevRn!Z`wMQ_!q3e!- z<>iCwn%u`@#kcMzM&|)nJm?Wg9p|3%frZD}nL9_CpHB2tw0G)s#AFAi$PvH=FySo!gFV(|=!7lL8ixvA-dk=S*Y&6_;JHiGk)GytC4+aD-q9guSWM{un(wi=!FO^{n|#LuygRYpDzMLUh^!vJi` zZ@vd=4jTQOZ`n03DMX!q!s<)^nBw*U$6qp2E8m9H{Ggkpq1&b|GDk+6g z?)d7zV^(b#e8&n@?qyXLFp4_;`>$WQUP5KI^I7PO6<0uIGb*y894{s33x7Hu75%Ed zxWvj?RbNzkGQehW~`>E9ybuP{#ZmD}G7i>%_q^-@>d0>?ANcc7=MPuZM$qtSnl#AE2>U)2uaZ zQ`a2Q`;r<5EcSkTK)Wz|4pCy0mr{BIJFq`+#k0SuoCFO{pc4>w_?3ElTq6!Bul;or z0zEZ#D}C z@G8|Kh3DckYyQ2i_1=b|2l&pwWO<-{fwS!?z`yFv8yk1Ksg>zl{8rm(cNBoFH!VQr zSC^arSQx{r$;`ub*szUFVw>-)EltFjwF^vSoaVx@6xG(JfNAON@(9zn#u=nvqM~{> R_vnBA4BudSp-=30e*y+>Vf_FA delta 3705 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 X1B&E#-RW9=00000NkvXXu0mjf`z83~ diff --git a/Resources/Textures/Structures/Windows/mining.rsi/mwindow5.png b/Resources/Textures/Structures/Windows/mining.rsi/mwindow5.png index 84ce6f1696f333e1fae363ff994de7c54c7970ad..6d1ed85f336f952cd2b2b79ea7493bd2027c1de0 100644 GIT binary patch literal 2215 zcmZ`*4OCLu7QQG5YCn`_z4C{6KAUlcAh{H;NNV_3iag5(o6-<)BoPR%16a?lj+0TA zl$E3vPbagKEUg)ubb4C;WTmgA)wpt{R+`!ywX{+5r``q2tks;g&OPVs`+a-w^X+}t zx@tBnc)rzgD*yoIhlVgCk=4&QaTdt4M7Xm9Sy1xG-~gbk*}fk+ED&%)m)J(!PAZ6Mj|sTev%1! zp<+lNlgg0ZGR6B4?ynJ_`}!C=N-TsJ9~^vUp2M0`8_-_{DI~JQO{O}06!9-1@7>G@ zI;THpn%^Wo()|o8I(ha>Vpv&Mp34OQ^tDi?|0X4>=Ue|oTX$R5h5h=Yu0Bg_j}u*s zutS2ewhaaB=~73#l=Ft;F?Bbo=R%^{mnyGp*colBA4&e#&32E*u;)eb_U3t_n2O2k zl8&mXsxup0Wx}7gp3QuzZubcD}~z z)aky*F}j~@0K8OL1ypr3^xPL`VX_(;(+$O|vK6PQ^Ip_*;HLI`zme;BJN#oyvy7&8 z`K7a--s~K`C>AoK;qncJG+`D-3cE=D+f&ul_-vXnuq7JKe!8rEnYEut_oHF$oyBmu z*5-y8bA`IXsemJ37kD^$@VszrWgbP?2~K=Z8%=fW4qdNdFLRmd zesd>r^85Ta$`j`kL%l`iRRdnPM-N!Sjgc*dUqSyU3K;C|_bGk&RG=aLTG3UIaBF&Z zRF_9Y7|j3Ls{D|RrsQWW;Dk?!4-SZls-B>`qZowOoX$-8wpVOj9eO++uq++>W^`Sk zERvY6Hw#?f#}!+oE)^!l4)0Gb-oG`>ZxIfDm+VRZ_tv#Xw?;R=tz4geTb>f-H{u;< zc6%IviJI6ZDvLIv=+eWWPQJ7oo+>0t8<{4;rAWBbh~|142sr|6Lmetnx`=0OdgQ=t^_WMwF_21K#?ce_t9tx78KC z4su{EV1skSn4Kfp?!|cAzyfDV+X9||wJ5JR)X90{dsq8CI=g1itxF(5IU!l?r_fvh zGp_d3HI}v5VFO&8x*{_!E=cBJYSH8Hy>GCw!&_@NA5&YtL={|I!03*`aE!GiHQAU67w|V9#)^E zC+W7Yh)`Kf{RTtiMW+B-z_*N=AV8LVaAFr~BcsN`aeC#@(tWx9xrGA$ks=Dy9sxO^ zZ}d=Wxmg+XiGzJ;DSjd*?dX*Upz4>MWpDe?Y-hEP`9w@j5siPcs<7NsMcRyV4%YZ~ zggvw?yYoVYc3|>W1L~GzJ<(2MxR(;?)M!clX@6|fTCaLDjYrRqgNt8!EYIEOlYwFG z!2pHr1B=g=K7w+qy9r!WO9f59&ghTmgWD0l;*TI7}*0BAb^tj|`8MF3bZ02F3R#5n-i zEdVe{S7t~6u(trf&JYW-00;~KFj0twDF6g}0AR=?BX|IWnE(_<@>e|ZE3OddDgXd@ znX){&BsoQaTL>+22Uk}v9w^R97b_GtVFF>AKrX_0nSU8Ffiw@`^UMGMppg|3;Dhu1 zc+L*4&dxTDwhmt{>c0m6B4T3W{^ifBa6kY6;dFk{{wy!E8h|?nfNlPwCGG@hUJIag z_lst-4?wj5py}FI^KkfnJUm6Akh$5}<>chpO2k52Vaiv1{%68pz*qfj`F=e7_x0eu z;v|7GU4MZ`1o+^>%=Ap99M6&ogks$0k4OBs3;+Bb(;~!4V!2o<6ys46agIcqjPo+3 zB8fthDa9qy|77CdEc*jK-!%ZRYCZvbku9iQV*~a}ClFY4z~c7+0P?$U!PF=S1Au6Q z;m>#f??3%Vpd|o+W=WE9003S@Bra6Svp>fO0Dk~Ppn)o|K^yeJ7%adB9Ki+L!3+Fg zHiSYX#KJ-lLJDMn9CBbOtb#%)hRv`YDqt_vKpix|QD}yfa1JiQRk#j4a1Z)n2%fLC6RbVIkUx0b+_+BaR3cnT7Zv!AJxWizFb)h!jyGOOZ85F;a?DAXP{m@;!0_ zIe&*-M!JzZ$N(~e{D!NlT@zqLtGcXcuVrX|L#Xx)I%#9!{6gSJKPrN9dR61N3(c z4Tcqi$B1Vr8Jidf7-t!G7_XR2rWw%BIv?Wdily+ylO`+*KY$4Vz$Cr4+G&IO(4Q`uA9rwXSQO+7mGt}d!;r5mBU zM0dY#r|y`ZzFvTyOmC;&dA;ZQ9DOhSRQ+xGr}ak+SO&8UBnI0I&KNw!HF0k|9WTe* z@liuv!$3o&VU=N*;e?U7(SJOn)kcj*4~%KXT;n9;ZN_cJqb3F>Atp;r>P_yNQcbz0 zDW*G2J50yT%*~?B)|oY%Ju%lZ=bPu7*PGwBU|M)uEVih&xMfMQu79>|wtZn|Vi#w( z#jeBdlf9FDx_yoPJqHbk*$%56S{;6Kv~mM9!g3B(KJ}#RZ#@)!h;8Eq#KMS9gFl*neeosSBfoHYnBQIkwkyowPu(zdm zs`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMeBmZRodjHV?r+_5^X9J0W zL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0?0=B0A@}E)&XLY(4uw#D z=+@8&Vdi0r!+s1Wg@=V#hChyQh*%oYF_$%W(cD9G-$eREmPFp0XE9GXuPsV7Dn6<% zYCPIEx-_~!#x7=A%+*+(SV?S4962s3t~PFLzTf=q^M~S{;tS(@7nm=|U2u7!&cgJC zrxvL$5-d8FKz~e#PB@hCK@cja7K|nG6L%$!3VFgE!e=5c(KgYD*h5?@9!~N|DouKl z?2)`Rc_hU%r7Y#SgeR$xyi5&D-J3d|7MgY-Z8AMNy)lE5k&tmhsv%92wrA>R=4N)w ztYw9={>5&Kw=W)*2gz%*kgNq+Eef_mrsz~!DAy_nvVUh~S7yJ>iOM;atDY;(?aZ^v z+mJV$@1Ote62cPUlD4IWOIIx&SmwQ~YB{nzae3Pc;}r!fhE@iwJh+OsDs9zItL;~p zu715HdQEGAUct(O!LkCy1<%NCg+}G`0PgpNm-?d@-hMgNe6^V+j6x$b<6@S<$ z+<4_1hktL%znR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX4c}I@?e+FW+b@^R zDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i&_B8C(+grT%{XWUQ z+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?SIDu(gXbmBM!FLxzyDi(mhmCkJc;e zM-ImyzW$x>cP$Mz4ONYt#^NJzM0w=t_X*$k9t}F$c8q(h;Rn+nb{%IOFKR-X@|s4Q zQ=0o*Vq3aT%s$c9>fU<%N829{oHRUHc}nwC$!Xf@g42^{^3RN&m7RTlF8SPG+oHC6 z=YM0)-)awU@466l;nGF_i|0GMJI-A4xODQe+vO8ixL2C5I$v$-bm~0*lhaSfyPUh4 zuDM)mx$b(swR>jw=^LIm&fWCAdGQwi*43UlJ>9+YdT;l|_x0Zv-F|W>{m#p~*>@-I zt-MdXU-UrjLD@syht)q@{@mE_+<$7ocYmPs(cDM(28Dyq{*m>M4?_iynUBkc4TkHU zI6gT!;y-fz>HMcd&t%Ugo)`Y2{>!cx7B7DI)$7;J(U{Spm-3gBzioV_{p!H$8L!*M z!p0uH$#^p{Ui4P`?ZJ24cOCDe-w#jZd?0@)|7iKK^;6KN`;!@ylm7$*nDhK&Gk-1H z0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F}000AHNklr3q6!Y znv5kug?dR3HIl?6>L%%o6W>J~4S!)?zIosKzM0f~-v^p;c6R1Vk_?2{uX2)xNVDNOr^j_Z(Y9(~0RgPVReCPk9itagTY{9Y~ST`PzWFd!Rh(sy4nX%e$?;PcUe9MkASpl{}l*ef(6p5{jLR+3l_+# z_S_>NPI;9@K#@(BM9K0Vic6 zK-GPsNc z`R@edlTT}fE29O{T45IYfYR0AsNbury73S`?GbEjR0aWQ?7)pHyibJL zp>m#JoE<9X3C7vsxG%u7ACMJA?(b8V!?gGJkA48{1mun5`+ovJ_j~~}Cq-$UFJR`R zD6R7a$8&-#ARyi@e?{_`L_n64R2Bl5cwfMCY*7>hbDzlqK@mOno^!YV{@?%o_q+c)@B5Ho zKXWr{GXMb08UFN8WTxr62?iN233hiO6G|TH=K~b}zPumV%;Pc{yr3XpHL^BAy1uo9 zr6HrK)IU-V0CO$$9R*~cS_%MYp&*9}-;z;7SM5Rb-Kv9%rWGUjpEUZ!_ z6wAp8Wbiq;0uvjcb#^I4e=^Ng`k)0Qg z55rP21Su2>qQZ?Rk?nw7Jv}`k7ZOAw5fBf8e2*ArDG6e^!*r1Map+t*TPBdg0*M%_ zkIRaa#KT@VoStZ=P3OsB&+tg&WkLfBhYfLsToG3c%OO{yEA%-WEZ}{}P%M8Z2O
      Mar6oV8W89zM0G=TXzz-;5EfDpa}mLT;c6R;U#m@AXY zklHfvy{G$Yk56NL;EoUrVCwq-pO|N%X1xvBTLvp6vR&bZclaRUU%I>tGcD+>`kXF) zgZN1GQ_U#Q%$Gzpn_F=q69B+e2HiVci5lG2xT}@6_>4vqe*O;6@*kn}x|V~AeqBQV zD|ftTFZ1~$(Y8vBdeJ5SRZO^yzbYec{;uo7hcA_hk!h9Mz%NeM;j4m5P219OtyY_A{9QkVuLhosNw}m372lc+shzd zE^3;;w`S{3Z=jcCS)bT~g3Z_ZclUXSkAn2g_@8>nlB3`gp8|O2QE=rwS=7}GRUQ*n z2+9-3>w=U22^4~?seRX?|Cl2sorhGVm;se(tqzEGJBXYeTe81O>XB^RJzVtQn!-5Y zky%VmgBonbE#a5g)qC*E>>F;`qZ-rtpmCec6LD=TJab}itHBevRn!Z`wMQ_!q3e!- z<>iCwn%u`@#kcMzM&|)nJm?Wg9p|3%frZD}nL9_CpHB2tw0G)s#AFAi$PvH=FySo!gFV(|=!7lL8ixvA-dk=S*Y&6_;JHiGk)GytC4+aD-q9guSWM{un(wi=!FO^{n|#LuygRYpDzMLUh^!vJi` zZ@vd=4jTQOZ`n03DMX!q!s<)^nBw*U$6qp2E8m9H{Ggkpq1&b|GDk+6g z?)d7zV^(b#e8&n@?qyXLFp4_;`>$WQUP5KI^I7PO6<0uIGb*y894{s33x7Hu75%Ed zxWvj?RbNzkGQehW~`>E9ybuP{#ZmD}G7i>%_q^-@>d0>?ANcc7=MPuZM$qtSnl#AE2>U)2uaZ zQ`a2Q`;r<5EcSkTK)Wz|4pCy0mr{BIJFq`+#k0SuoCFO{pc4>w_?3ElTq6!Bul;or z0zEZ#D}C z@G8|Kh3DckYyQ2i_1=b|2l&pwWO<-{fwS!?z`yFv8yk1Ksg>zl{8rm(cNBoFH!VQr zSC^arSQx{r$;`ub*szUFVw>-)EltFjwF^vSoaVx@6xG(JfNAON@(9zn#u=nvqM~{> R_vnBA4BudSp-=30e*y+>Vf_FA delta 3705 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 X1B&E#-RW9=00000NkvXXu0mjf`z83~ diff --git a/Resources/Textures/Structures/Windows/mining.rsi/mwindow7.png b/Resources/Textures/Structures/Windows/mining.rsi/mwindow7.png index f0ac5b6b90cac61eab3a5f099c67ebac9aa85d88..24733c9b3e5ed0233f6097eb7cc79aa6228a6dcb 100644 GIT binary patch literal 1813 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 diff --git a/Resources/Textures/Structures/Windows/mining_diagonal.rsi/meta.json b/Resources/Textures/Structures/Windows/mining_diagonal.rsi/meta.json index 439147564dd1..7d12528bb20f 100644 --- a/Resources/Textures/Structures/Windows/mining_diagonal.rsi/meta.json +++ b/Resources/Textures/Structures/Windows/mining_diagonal.rsi/meta.json @@ -5,7 +5,7 @@ "y": 32 }, "license": "CC-BY-SA-3.0", - "copyright": "Made by NULL882 (github)", + "copyright": "Made by NULL882 (github), transparency tweaked by Ubaser.", "states": [ { "name": "state0" diff --git a/Resources/Textures/Structures/Windows/mining_diagonal.rsi/state0.png b/Resources/Textures/Structures/Windows/mining_diagonal.rsi/state0.png index 54af8484b2fb8a2470d3c4b6ef181ea35039810c..c7e717a6e70eb76e89d526f351f1a2263a10a84f 100644 GIT binary patch literal 1299 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}e5nzhX}-P; zT0k}j5QD&_;K@Lev%n*=7^vU~2s2LA=96Y%U{1*li71Ki^|4CM&(%vz$xlkvtH>$0h^0y1+`OA-|-a&z*EttxDlz$&bOY>=?Nk^)#sNw%$0gl~X?bAC~(f|;Iyo`I4b zmx6+VO;JjkRgjAtR6CGotCUevQedU8UtV6WS8lAAUzDzIXlZGwZ(yWvWTXpJp<7&; zSCUwvn^&w1F$89gOKNd)QD#9&W`3Rm$lS!F{L&IzB_)tWZ~$>9$H0x+$q?iKRIuN_J_bIXO1^5EZC8A)=@T+UR4k+Xm!gtH_|#;{2Ra zP?+0Un%RJZ0YwlI_z(>d*fbyuqH74q$S=tUrlq3HWY4^k)S`kSV7da^X9Tqlw+eK# z5O#;=WtP~%3_ue`(uEW+R*pp_<@rU~A>cTG1Rzdns1cCBL`s*CL=O&lV5+y{veAd< zAUiI;N0;w;!X??oX$kfvyZsH zoq_d#f%1O7kcVg1GnZOCR}K^Lf0in2c5w5XcgGveb_f{1WXKf%)5O30wCSz}p9a1@ zJ%!VZvVY3#_!JtBG_ETUV)uD)PS&8+y7U0syEBZ@JBl8xSJ~3Ke%tTsPfK<i!=6cugro5XNTpR8@TSBWc1o`jWNrDWr0+4 zht#@B0=Yj_52)LCPFlrq|HCPvmWIc93ez3fr|(|+v@w`ByE7+WQptXG;Rab&i+5~+ mv;4eRnChJVt~*?4UctP{wzuiaq`jq}0?E_W&t;ucLK6VE-m69c delta 3031 zcmV;|3n=uH3f&iwB!3BTNLh0L01FcU01FcV0GgZ_000V4X+uL$P-t&-Z*ypGa3D!T zLm+T+Z)Rz1WdHzp+MQEpR8#2|J@?-9LQ9B%luK_?6$l_wLW_VDktQl32@pz%A)(n7 zQNa;KMFbnjpojyGj)066Q7jCK3fKqaA)=0hqlk*i`{8?|Yk$_f_vX$1wbwr9tn;0- z&j-K=43f59&ghTmgWD0l;*TI7}*0BAb^tj|`8MF3bZ02F3R#5n-i zEdVe{S7t~6u(trf&JYW-00;~KFj0twDF6g}0AR=?BX|IWnE(_<@>e|ZE3OddDgXd@ znX){&BsoQaTL>+22Uk}v9w^R97b_GtVFF>AKrX_0nSU8Ffiw@`^UMGMppg|3;Dhu1 zc+L*4&dxTDwhmt{>c0m6B4T3W{^ifBa6kY6;dFk{{wy!E8h|?nfNlPwCGG@hUJIag z_lst-4?wj5py}FI^KkfnJUm6Akh$5}<>chpO2k52Vaiv1{%68pz*qfj`F=e7_x0eu z;v|7GU4MZ`1o+^>%=Ap99M6&ogks$0k4OBs3;+Bb(;~!4V!2o<6ys46agIcqjPo+3 zB8fthDa9qy|77CdEc*jK-!%ZRYCZvbku9iQV*~a}ClFY4z~c7+0P?$U!PF=S1Au6Q z;m>#f??3%Vpd|o+W=WE9003S@Bra6Svp>fO0Dk~Ppn)o|K^yeJ7%adB9Ki+L!3+Fg zHiSYX#KJ-lLJDMn9CBbOtb#%)hRv`YDqt_vKpix|QD}yfa1JiQRk#j4a1Z)n2%fLC6RbVIkUx0b+_+BaR3cnT7Zv!AJxWizFb)h!jyGOOZ85F;a?DAXP{m@;!0_ zIe&*-M!JzZ$N(~e{D!NlT@zqLtGcXcuVrX|L#Xx)I%#9!{6gSJKPrN9dR61N3(c z4Tcqi$B1Vr8Jidf7-t!G7_XR2rWw%BIv?Wdily+ylO`+*KY$4Vz$Cr4+G&IO(4Q`uA9rwXSQO+7mGt}d!;r5mBU zM0dY#r|y`ZzFvTyOmC;&dA;ZQ9DOhSRQ+xGr}ak+SO&8UBnI0I&KNw!HF0k|9WTe* z@liuv!$3o&VU=N*;e?U7(SJOn)kcj*4~%KXT;n9;ZN_cJqb3F>Atp;r>P_yNQcbz0 zDW*G2J50yT%*~?B)|oY%Ju%lZ=bPu7*PGwBU|M)uEVih&xMfMQu79>|wtZn|Vi#w( z#jeBdlf9FDx_yoPJqHbk*$%56S{;6Kv~mM9!g3B(KJ}#RZ#@)!h;8Eq#KMS9gFl*neeosSBfoHYnBQIkwkyowPu(zdm zs`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMeBmZRodjHV?r+_5^X9J0W zL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0?0=B0A@}E)&XLY(4uw#D z=+@8&Vdi0r!+s1Wg@=V#hChyQh*%oYF_$%W(cD9G-$eREmPFp0XE9GXuPsV7Dn6<% zYCPIEx-_~!#x7=A%+*+(SV?S4962s3t~PFLzTf=q^M~S{;tS(@7nm=|U2u7!&cgJC zrxvL$5-d8FKz~e#PB@hCK@cja7K|nG6L%$!3VFgE!e=5c(KgYD*h5?@9!~N|DouKl z?2)`Rc_hU%r7Y#SgeR$xyi5&D-J3d|7MgY-Z8AMNy)lE5k&tmhsv%92wrA>R=4N)w ztYw9={>5&Kw=W)*2gz%*kgNq+Eef_mrsz~!DAy_nvVUh~S7yJ>iOM;atDY;(?aZ^v z+mJV$@1Ote62cPUlD4IWOIIx&SmwQ~YB{nzae3Pc;}r!fhE@iwJh+OsDs9zItL;~p zu715HdQEGAUct(O!LkCy1<%NCg+}G`0PgpNm-?d@-hMgNe6^V+j6x$b<6@S<$ z+<4_1hktL%znR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX4c}I@?e+FW+b@^R zDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i&_B8C(+grT%{XWUQ z+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?SIDu(gXbmBM!FLxzyDi(mhmCkJc;e zM-ImyzW$x>cP$Mz4ONYt#^NJzM0w=t_X*$k9t}F$c8q(h;Rn+nb{%IOFKR-X@|s4Q zQ=0o*Vq3aT%s$c9>fU<%N829{oHRUHc}nwC$!Xf@g42^{^3RN&m7RTlF8SPG+oHC6 z=YM0)-)awU@466l;nGF_i|0GMJI-A4xODQe+vO8ixL2C5I$v$-bm~0*lhaSfyPUh4 zuDM)mx$b(swR>jw=^LIm&fWCAdGQwi*43UlJ>9+YdT;l|_x0Zv-F|W>{m#p~*>@-I zt-MdXU-UrjLD@syht)q@{@mE_+<$7ocYmPs(cDM(28Dyq{*m>M4?_iynUBkc4TkHU zI6gT!;y-fz>HMcd&t%Ugo)`Y2{>!cx7B7DI)$7;J(U{Spm-3gBzioV_{p!H$8L!*M z!p0uH$#^p{Ui4P`?ZJ24cOCDe-w#jZd?0@)|7iKK^;6KN`;!@ylm7$*nDhK&Gk-1H z0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F}00039Nkl_1 zaC$%Q*9!pq1N@5op3UJ_~3vl713Q%z3g9W(p zdWjHtbDs!_r)kWcKnjn);2GH`#pxReDx Z0|2@$0h^0y1+`OA-|-a&z*EttxDlz$&bOY>=?Nk^)#sNw%$0gl~X?bAC~(f|;Iyo`I4b zmx6+VO;JjkRgjAtR6CGotCUevQedU8UtV6WS8lAAUzDzIXlZGwZ(yWvWTXpJp<7&; zSCUwvn^&w1F$89gOKNd)QD#9&W`3Rm$lS!F{L&IzB_)tWZ~$>9$H0x+$q?iKRIuN_J_bIXO1^5EZC8A)=@T+UR4k+Xm!gtH_|#;{2Ra zP?+0Un%RJZ0YwlI_z(>d*fbyuqH74q$S=tUrlq3HWY4^k)S`kSV7da^X9Tqlw+eK# z5O#;=WtP~%3_ue`(uEW+R*pp_<@rU~A>cTG1Rzdns1cCBL`s*CL=O&lV5+y{veAd< zAUiIrQ_7_BNX> zt;(7q&GJZ`+pji;RZn@o@G_R1Zf#|i+*kYipu=>RjPHR5JAfT{XVNu)DU-u?Hnc8w?lgyLq zN#0Ibk$z#G9=WGIxfr7&_=*?;OBvVdsB5ugWLh2+Sg`e}0(%3)wW0>OY5%K!3+0%% zF=u4%+_dKrU&nq$6*o%<@6(Q9_i8KdGv5@{*x7Jx+Tj|$A{Kk|_kI2Oam5Wz3^9^| zn`D+rO7pI|>cG}`sx0S|fnmg)<{t{D>uW3aeSLQJHBZl`O`rZdIx-riC}c3O&!76K TjY~EZRAhO&`njxgN@xNA>o~XB delta 3070 zcmVf59&ghTmgWD0l;*TI7}*0BAb^tj|`8MF3bZ02F3R#5n-i zEdVe{S7t~6u(trf&JYW-00;~KFj0twDF6g}0AR=?BX|IWnE(_<@>e|ZE3OddDgXd@ znX){&BsoQaTL>+22Uk}v9w^R97b_GtVFF>AKrX_0nSU8Ffiw@`^UMGMppg|3;Dhu1 zc+L*4&dxTDwhmt{>c0m6B4T3W{^ifBa6kY6;dFk{{wy!E8h|?nfNlPwCGG@hUJIag z_lst-4?wj5py}FI^KkfnJUm6Akh$5}<>chpO2k52Vaiv1{%68pz*qfj`F=e7_x0eu z;v|7GU4MZ`1o+^>%=Ap99M6&ogks$0k4OBs3;+Bb(;~!4V!2o<6ys46agIcqjPo+3 zB8fthDa9qy|77CdEc*jK-!%ZRYCZvbku9iQV*~a}ClFY4z~c7+0P?$U!PF=S1Au6Q z;m>#f??3%Vpd|o+W=WE9003S@Bra6Svp>fO0Dk~Ppn)o|K^yeJ7%adB9Ki+L!3+Fg zHiSYX#KJ-lLJDMn9CBbOtb#%)hRv`YDqt_vKpix|QD}yfa1JiQRk#j4a1Z)n2%fLC6RbVIkUx0b+_+BaR3cnT7Zv!AJxWizFb)h!jyGOOZ85F;a?DAXP{m@;!0_ zIe&*-M!JzZ$N(~e{D!NlT@zqLtGcXcuVrX|L#Xx)I%#9!{6gSJKPrN9dR61N3(c z4Tcqi$B1Vr8Jidf7-t!G7_XR2rWw%BIv?Wdily+ylO`+*KY$4Vz$Cr4+G&IO(4Q`uA9rwXSQO+7mGt}d!;r5mBU zM0dY#r|y`ZzFvTyOmC;&dA;ZQ9DOhSRQ+xGr}ak+SO&8UBnI0I&KNw!HF0k|9WTe* z@liuv!$3o&VU=N*;e?U7(SJOn)kcj*4~%KXT;n9;ZN_cJqb3F>Atp;r>P_yNQcbz0 zDW*G2J50yT%*~?B)|oY%Ju%lZ=bPu7*PGwBU|M)uEVih&xMfMQu79>|wtZn|Vi#w( z#jeBdlf9FDx_yoPJqHbk*$%56S{;6Kv~mM9!g3B(KJ}#RZ#@)!h;8Eq#KMS9gFl*neeosSBfoHYnBQIkwkyowPu(zdm zs`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMeBmZRodjHV?r+_5^X9J0W zL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0?0=B0A@}E)&XLY(4uw#D z=+@8&Vdi0r!+s1Wg@=V#hChyQh*%oYF_$%W(cD9G-$eREmPFp0XE9GXuPsV7Dn6<% zYCPIEx-_~!#x7=A%+*+(SV?S4962s3t~PFLzTf=q^M~S{;tS(@7nm=|U2u7!&cgJC zrxvL$5-d8FKz~e#PB@hCK@cja7K|nG6L%$!3VFgE!e=5c(KgYD*h5?@9!~N|DouKl z?2)`Rc_hU%r7Y#SgeR$xyi5&D-J3d|7MgY-Z8AMNy)lE5k&tmhsv%92wrA>R=4N)w ztYw9={>5&Kw=W)*2gz%*kgNq+Eef_mrsz~!DAy_nvVUh~S7yJ>iOM;atDY;(?aZ^v z+mJV$@1Ote62cPUlD4IWOIIx&SmwQ~YB{nzae3Pc;}r!fhE@iwJh+OsDs9zItL;~p zu715HdQEGAUct(O!LkCy1<%NCg+}G`0PgpNm-?d@-hMgNe6^V+j6x$b<6@S<$ z+<4_1hktL%znR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX4c}I@?e+FW+b@^R zDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i&_B8C(+grT%{XWUQ z+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?SIDu(gXbmBM!FLxzyDi(mhmCkJc;e zM-ImyzW$x>cP$Mz4ONYt#^NJzM0w=t_X*$k9t}F$c8q(h;Rn+nb{%IOFKR-X@|s4Q zQ=0o*Vq3aT%s$c9>fU<%N829{oHRUHc}nwC$!Xf@g42^{^3RN&m7RTlF8SPG+oHC6 z=YM0)-)awU@466l;nGF_i|0GMJI-A4xODQe+vO8ixL2C5I$v$-bm~0*lhaSfyPUh4 zuDM)mx$b(swR>jw=^LIm&fWCAdGQwi*43UlJ>9+YdT;l|_x0Zv-F|W>{m#p~*>@-I zt-MdXU-UrjLD@syht)q@{@mE_+<$7ocYmPs(cDM(28Dyq{*m>M4?_iynUBkc4TkHU zI6gT!;y-fz>HMcd&t%Ugo)`Y2{>!cx7B7DI)$7;J(U{Spm-3gBzioV_{p!H$8L!*M z!p0uH$#^p{Ui4P`?ZJ24cOCDe-w#jZd?0@)|7iKK^;6KN`;!@ylm7$*nDhK&Gk-1H z0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F}0003mNklDt7JLb$f@IG!NSGxGx!H~<(gP{sk6 zEpUkw_01Kyh6}MXQ=kfu<1v4MI{bEY|H@jR31>Y8P55T@9yjZR+{Pg{Kb9Det{BAg$*M0-sZ@y2{q&&pgH(+Yd_i360zCS-6 zvVbUrBc*Kh16j2$uh*tM2Y}-t3x2;oUWC}fiK2nb^9)2GY&`!40DX;|L>DcWNdN!< M07*qoM6N<$g5ll3KmY&$ diff --git a/Resources/Textures/Structures/Windows/plasma_diagonal.rsi/meta.json b/Resources/Textures/Structures/Windows/plasma_diagonal.rsi/meta.json index 453a3797223a..8477687a8c7a 100644 --- a/Resources/Textures/Structures/Windows/plasma_diagonal.rsi/meta.json +++ b/Resources/Textures/Structures/Windows/plasma_diagonal.rsi/meta.json @@ -5,7 +5,7 @@ "y": 32 }, "license": "CC-BY-SA-3.0", - "copyright": "Made by brainfood1183 (github)", + "copyright": "Made by brainfood1183 (github), transparency tweaked by Ubaser.", "states": [ { "name": "state0" diff --git a/Resources/Textures/Structures/Windows/plasma_diagonal.rsi/state0.png b/Resources/Textures/Structures/Windows/plasma_diagonal.rsi/state0.png index 60d1c0421b3fecf74c453715810e8e5ffcf32774..0d13c29e14881ed4a09f4271884ad6ccb4de6aeb 100644 GIT binary patch delta 1110 zcmZpve#0|C#g?%+$lZxy-8q?;3=9l>sS%!OzP=1vKsE;ugTSTW$v~2`z$3Dlfk9&y z2s4UXDQ;q5U{0H8B|WiQhcCi6K*2e`C{@8s&p^*$;@7&#D;O;%FJm%K_ADq#HmS%h zaIGk@RmvzSDX`Ml&jgC;#BtJK`q$o4l zGp{7IsGumdBoU(8MjvbfRuz-`xkM-5=Q1=$@~xF)QAv4zQFaK}XCSBAAO{AD^yC%X zX7z`zMSNvoU~2VraSVyzJUZ=c-em`o*7Re3b01t{i%@V;VR8D)%vs9*{xFlG0QbDb z8&VHyZ+NU5QPRAsX~KpZ5MSA+^EdB|MmW(zukahvah8DW_8$3cz^D_ z=>=vNK1QB7_16PAm)RvHYKoAuNCm#m+5$ua5635}~^ z`8jKEZEHB;z5K4y`Q9I=)*oeiBvM1%omVVxpE00UJ?FeBq`x$a_ z%8|Hk#@RK~Zs_M8P+Q+KS3BzU%v)c=t0y5^#{MNq)~ zWK4;5me}8Y!C!W+tj-ab+ud=Zcgnp}&EFEOg!ZnQbh1@(*^*g568q)=UGcK|oyl93 zLm4l{>ere$Jh@WfcR5b+6z`vM?hcu|eK!o>`fXG$YS;c*`E8R49ak~xaogp#d*7vK8*F}5)SZOUhb4Jao((RQy6F8*_k54t5BxsFqu{a!P^Nn#5^Yd)KTE!H5=1*T#YR@I}zu#8&yE>5HSk2Ss{{rvr#ewU>)RGjc npP0%S>y%Ac9KKKXP5giM(zA2wcjuns29*+?u6{1-oD!M<``OGQ literal 15748 zcmeI3e{2)i9l(z?OG82z5E7&lYF#rby6$}Ev(G=Sj`_jFzd0QSnQR(GoVYcXnbs zFV0i6R@y)BB>Vh*-}n7~-}`*u_v`!Tp0BN0a!=6@iU@+Zr@G2h2kr*_Q&<4L)y~cv z;5Ic<)ua+c@l5?Qg?P2MlpweRa($!L==}*NC?OLsDn7{+4@JOif^aQ}M|h!C(hNQ+ zAcxD0SKr-dG{|C^v4Qo{-blIBB3E@rrKO!U^+IQ>;1rDu+(oW92ONYXjW@(Y!LZ83 z%Zy3C9QdsdQ$|B_iq=|YT%-pyG&PsDu#xQaj-9_M+D=PZAI#1B^sd2PN$Qi8H!;@ zFoRS(!WthZ!|L3WlTkk&Nfn}UM3a@ULHEo1ls2u*Xw(CxuaSL)BI!V3b%Y(DNX7XG zWj4`NE+bJ$+eF%;!Q|3Jfs%q!ND6Bzuruehi?k@3qP8d#giNa^3=DGO^`>LzTyH3p zGqkEzv;zbqNOM}M^&Jt3s*_ZuEh=4)Fnrii86$Dl?chGkvPKawVul!LlT`#YN>B&S~XQgf{(H zFA58i3X-8_B?+V|S-6Y&z}V4IMNoF9+J>kIvdCqEI;?(&)hYQ&J1sg$vssczr@-1s ziFJs))9-NF^jzr03tVK@rTa~ej*XbT9n^aDW8n32)nQfR!FH-WZZKey!O8@QcKFRs zmUPgdM~P0Wll0jvHqvT!SRGD*w$cofJR4)pGbY`beI&SnRy$V`*L*-AfKP z<3d%*dfq#rH0ZfmDyJ8aiRG@T8s+8F? z9W@5tJH5+)|8DTkszIo#^AbeoJc4-US%SDV4DJ^RqKzhqubRQ@uCEZpY-RJ$4pkCF z-XqnXMfLH)gUg<7Jylz}@~r*niGjbo$cXc2iYJ%9>%4R*(!K0jN&I4W>8cz3-roMc zf|MVvDkM7AyO#`~XA)QL+hJ;O&_Akde&<+l)0TXycj5KleRlTr zf`W!EwkN+_ecv45Vv^LhTup{}U7yZ21~K=Gf0;_f-B_x#4^+xPT;@Jajk z_BXZM-dr00+pjG<*DPllbK}r&?W^7%e1Ds^=aDy;B^sXbUs=egU)MgpYtGi*!~2Ri z%;q+BCDiQ&#MJZu>Mz{9^|PAGiO*lJyt`ts?{MAh!W&hW?#+|WZ(Z`>+$qB**P6BW z@7;Lkf!eynVPad^ild%l;^5(hhSMFtfB#VaqruzppWohjqJyzB91x_`0>zZhF=aZ|^e=T{wGR;a|V**|lMK8ZrOGfdb#NbU!$9M0G`t Kr*Cods{aE2tbMlt diff --git a/Resources/Textures/Structures/Windows/plasma_diagonal.rsi/state1.png b/Resources/Textures/Structures/Windows/plasma_diagonal.rsi/state1.png index 1ae08dba8877a734110a8725e09d327a12edf277..7469c63afe4a30cb3fc6677c7a2e3dd07e55142e 100644 GIT binary patch delta 1068 zcmdm3b(m*@iY;Stkh>GZx^prw85kJ&QX@Rme0>?TfNTyR27yb#lYt~>fk$L91B1pa z5M~s&QryJAz??SGN_t|q4qt?CfP!;=QL2KOo`Igh#IJReS1?*kUdCje>{(EfY*LY1 z;95~)tCUevQedU8p9vJx%P&gTFD^;ZM^d0~WME*SYha{nWT~%Y$E5%RHYv$gC7C5T zsYqf#Ih&%CG%LrPlF7Cll9CmNl|99 zXI@EaQ9)5^Ng_nGjXu}}tSTn=bBRvA&t+(iB%d& z&FT+bi}=dGz!c-@;usRad32g%{w)WA*7ECWY!lU7Y(rhULR+t8v-}>YBDt0@6THl$)=yz{t&i{G$ z&Q<%J=G_*=?6Pjl$NO_k<W!sO3thgaJg3IwXZ&e#~pWcJf*^2yGd|>@?G{PXPq4xua3R;`^RkfCH=eW#)^fYyzlAi=d#Wzp$P!zM!t#w literal 15665 zcmeI3eQ;FO6~J$>WNa{$wsfS-w5|&bvGwJB?Dy;LhL8Klv-{q5 z-`nga2B8(FRw{msbnt^@94gNALpwreXsHb|L9MnFN-Y)BYAA}ph|-ZMR;%>B{m#wi zPNq8JKljb-zCHKcbI!fLbI;lL&--C}+qY|L7S;d&YFk@E9q4YeK37(wZ)0%qBD#G( z(b8=IFz3tGrwTms*a85=F}1VH>fMaYxji?b8ICe zMK0PTQps3$X^PCk7>q;BG>{!%(Jm3yP2Gs<(}XOlrwxp95)Kz*S6pvAUNN*`Huob0 zd88FBjn07tWILdtr;;*k?nhf$RB8978Yv}bk|#?u?b=~RoyN@46K0zz9;Q}$HZ>ei~7qNk1P{48!#%6G{d3`r&o3Y_3zI5#6WJ9)S0 z^oqRmn;b84T$z*HOw31ESJcQr$p?=Pw9v^rM3-B1xXXQ%&BT46`cWiPnvs|Cxn+J7 zS&Zn(xMT*^xYP^Tgx2e4OM_)Ii>FF#(qnoOEei%6ezwwZMXQi5r>tY$sL9Yk$uP>2 zgi@6)+~rd5A!K~A%gsQSSCM=Xug`7e z!YW?mqO>l{Z+3KY#PaQs)@vPua9C{B3{yheX$=L@K)s4q=J0V5UQv9E!1r(r^f=v2 zk6ZRKG7kk9k$HjVmF(G=Y+hPf-gO~5a$R}jZja*RdjzkwacSC(=hj)~Y)YV;k}7KF zQmkx_wHF2LMRF<;xrcKxPM1qy+|cP{Bw2Pc5!vT-IG`kWojrxURB$sTREuimeE>^? zm77)YyOT#tdCxZ9gp@R()m8%bLSHF%YBaTY`Lpdwlw_-A2W6}3A;LXrw6rYTOr4s} znIXveFEgJ$Mmh>LQrF12%FdeJiJ?c#w3LL6y{MjM($I2VC!68!D_03(l&#E|`Uw(Y zNd2EI4Ku5%|0@lZ8}DbA1`BvDx*V0XUZ@1w!T~M}%q(-cd`_;cLbXn%k!RueAz2!@{83<#M?EEIy1|w5u5y>k6spU(2xii33H-+TeCIHAq1RE<=)KeV?CJlacUEn3 zOGg-h!6g7}xf6i@Tt@e^0Hino&fSV$cijoV)%t@QpIZSy)tS~%V`t{oLu>xfHok0r z;L`S`&u%u6X9L&Z~JR%s0IxFx;s7BCb!*x?v>H* zKkZ&LuXS#neV#abLfHJfn{T@Ea}O?<1-`f|U41Yzd}zhMqLWWPb7#v-59|j=@15m- z?~TK6|MQxEtnB~#(RVL)zayMKcW7hc_cw1{e)~NSFR49$@)uY9a`e4_-8Z47zBcmA zPfnhOr_L^w?>_VQO;5V!ymagx;q_y$tFxEw*thw8yZl1mpN)rqeASIN{6#yqZ@g*U z-h*(%>VK~R`-lJbz(=E1^HT?I5mvXwfj0J)9V>U7aw*#vyYFc_zV5^(Ft+~0oY=&k z+PCiAx^azgg1hw7zQ*1A-rD+9fAzvAo>ii6UiHfG&*aN{_9+V=TR;1@^zF6Bp8&BV zFYKK-c?6nA_q=@k diff --git a/Resources/Textures/Structures/Windows/plasma_window.rsi/full.png b/Resources/Textures/Structures/Windows/plasma_window.rsi/full.png index b20d5ebd5efacbed1185a649c410e9eee61d80c5..b27e173b7ada827744bc7f0468d28fd1ec0acb1d 100644 GIT binary patch literal 2843 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 Xo3pg6H;px1`Z0AUdb{umVafjm^rEZ; delta 1581 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 XgPS^ntdeaE|2RM(J%m=ilDYM77EP?w delta 1079 zcmV-71jzfI63YmXBYy-ENkle_%7dXY=7YaDVgq?Ii%&tVtvSLB)L- zX!0xVhj!yTC!lvtBm9Q}y}qFo02qi-0F?hxwcU1n=LGD1H9B6tj8+_&2mn@pMPYy6 z^8sM_XM}6_hNCLGEu0f@ba1+VHsj^yhJsnmB0wMz=%a(vL6zNheCGu4T$CQEApi&< zX&V8=b3v8ec7J^51Q21h>0k701LIpek^ehdLIADezoPzS?C*~j5RhI(QU4;l9a=zu zTR3-u0A{KF6u<(&m315Bp1sKa&S--Irm1#@cyUR48M_tQK)}qhwL%*RaEh%bz&g1) z`1<)bHlM%u{TGjH=U{`aSHO+{*AsA!ItUo2`qP5z4YVpz|7Wd zkh_=koujTTkpGXCwfVkt)I@;vvu*x<($Cx7qlPa-`Nda}P;~7UTOS3i6<`Ft^mWmT z%H(Bc9WOEKhBW~km?dc_QbfEokO&YqLZk=^&{v2^la$%&ScDC%2_Q|s0e~1l^%VM_ zX+N(HrK)3l@op0Fn7&NC4np)w;~)8ukPL zXVDvGF|k9HP?CiaARtW~9-eH5kKG)n&=PHwxsX; zouu^y?%cfld+t^)(~IN22>LuX;pFb%k5@k~K7R+m&tL!IJSS)(4=8v_%E~*%lB$ z$OBe04q=E$tIiUzz-9|%3z&Kk59fWLH2|FO>rQTg00k-_fP{r6clyKdm>GbK^~AXf znt$2?YXxL|z_x_JloQO=@ONSGTo`nYCUWsHN=n!1Feuy(5j3HIq<)XI57?$KSn31v zVQ|iY^R3XZ56DIVF>jq8DVVXI7&t}~1fX910Jwciw@mzGVJ%3-&j=I45{Quw+4SK1_a2nJv&g1r#A$LObUK zJEwrnEc94iCN=M*0?7YZ)8M+-?@jd}YdTj>@0J1#jDRH!UqyU$Fh9-wJ_ta;u`u`! xDqxofV3!8~yF6f*2PD|#0oCZF0-WUm{{oTD)vp-+rab@v002ovPDHLkV1nA)0NMZm diff --git a/Resources/Textures/Structures/Windows/plasma_window.rsi/pwindow2.png b/Resources/Textures/Structures/Windows/plasma_window.rsi/pwindow2.png index fe379e2fef50ab07c64a4f9ff75b663ada0ee10f..9a55b8c3aff60f63f31c71a75735bbdde89f2686 100644 GIT binary patch literal 3469 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 XgPS^ntdeaE|2RM(J%m=ilDYM77EP?w delta 1079 zcmV-71jzfI63YmXBYy-ENkle_%7dXY=7YaDVgq?Ii%&tVtvSLB)L- zX!0xVhj!yTC!lvtBm9Q}y}qFo02qi-0F?hxwcU1n=LGD1H9B6tj8+_&2mn@pMPYy6 z^8sM_XM}6_hNCLGEu0f@ba1+VHsj^yhJsnmB0wMz=%a(vL6zNheCGu4T$CQEApi&< zX&V8=b3v8ec7J^51Q21h>0k701LIpek^ehdLIADezoPzS?C*~j5RhI(QU4;l9a=zu zTR3-u0A{KF6u<(&m315Bp1sKa&S--Irm1#@cyUR48M_tQK)}qhwL%*RaEh%bz&g1) z`1<)bHlM%u{TGjH=U{`aSHO+{*AsA!ItUo2`qP5z4YVpz|7Wd zkh_=koujTTkpGXCwfVkt)I@;vvu*x<($Cx7qlPa-`Nda}P;~7UTOS3i6<`Ft^mWmT z%H(Bc9WOEKhBW~km?dc_QbfEokO&YqLZk=^&{v2^la$%&ScDC%2_Q|s0e~1l^%VM_ zX+N(HrK)3l@op0Fn7&NC4np)w;~)8ukPL zXVDvGF|k9HP?CiaARtW~9-eH5kKG)n&=PHwxsX; zouu^y?%cfld+t^)(~IN22>LuX;pFb%k5@k~K7R+m&tL!IJSS)(4=8v_%E~*%lB$ z$OBe04q=E$tIiUzz-9|%3z&Kk59fWLH2|FO>rQTg00k-_fP{r6clyKdm>GbK^~AXf znt$2?YXxL|z_x_JloQO=@ONSGTo`nYCUWsHN=n!1Feuy(5j3HIq<)XI57?$KSn31v zVQ|iY^R3XZ56DIVF>jq8DVVXI7&t}~1fX910Jwciw@mzGVJ%3-&j=I45{Quw+4SK1_a2nJv&g1r#A$LObUK zJEwrnEc94iCN=M*0?7YZ)8M+-?@jd}YdTj>@0J1#jDRH!UqyU$Fh9-wJ_ta;u`u`! xDqxofV3!8~yF6f*2PD|#0oCZF0-WUm{{oTD)vp-+rab@v002ovPDHLkV1nA)0NMZm diff --git a/Resources/Textures/Structures/Windows/plasma_window.rsi/pwindow4.png b/Resources/Textures/Structures/Windows/plasma_window.rsi/pwindow4.png index 051ddb5681d8fd7b09d02ae046234981b17298eb..b42ca67a1706840170eeb4a617d3aab4f84c9a69 100644 GIT binary patch literal 2402 zcmZ`*2~<wwPRri4?z{J%clO!m?0eo?FC#2; zsV#Cg5&!^OW-uchUTMZ@X%0Wj1e-hI1tAY#8UUQS;qn|lptvk1FC+x;g7=p2G>+DY zT=;1v4PGq=0M7%)iEtpfR{(&CSP;pASRpG&Y>5aP$B}I0VpSsP1d6O8!CMg*ibJbJ zLb05rqF^RGNbufh1~KRf7bt;(VTFXDmq=t>v@aHi#bKyOG#X8oad@O~M$i--K2b1y z2$GUOP^na6m5Z+f^Y_8weegu^Lw#`iWDc7I2_PYN zLbwn0OejbfLZ4fW{zeIe0;94dVVpRgf>HT!xV$)p5W-NUN`aUoQTma=Nw3e*lh)6J zlEJU=lZ{oAR)=%t5~0GVI~DIsAWvxVnf2ohOd?ocMSN=g5)sCiKoYp4WCAu*3~^;r z8Qfiyj8lC7?D1u+kK|Ee0Yt@51^B}J3F?#EA<<=!QX)%;oVbaPGXA5>RG3LgKk3lP z_Mea+?tdzh41V~QsK{3uK`a26$(am#qzciqwpr}#Xa7v9oac?tAxJkm5=|AF2OSZH z1hDp8Ug3yo^OC{!TH0>c#O`@*M-YihdFk#M!L!@wg{EiPT6<;qvkk1KP3QMBmOZFy z-|632^t9cPhB>Q#~-GO@be8>?3J-)}jcTk2N3YoGe+iC=>q>M&aB ztTnAIecQ*58+IQ_{3U2Pe`o&ueXh?;emftn-I8Zm+T*bn0XQ1cS+4>jH_FSbr(a*Z z^kr7V=EXAsbQy}_$OS8!IJ@?0WSu`;FqcOEmyA|8 zFgp+_yvDXY!g(1%cQpg-1R(pe#5VoUn6#3^ro7pfT_r8wwA>!R7t{51oZ;EuknfMp zeeO)q1)K+yqC@nR=BXBd?T@O6yx+^L%4a$5oP((U-WH|LAZ8Wpr>~{WI`n*z! zb0PY-ru9h{eh7waEAzB_kfY0r8=?zVdu_HB0&x9{ipz)fqu#GKCEt6O)PjgF$U5+j z*O1tMEjBjVyM4tjEZAq2w$@}^`LsHW6GM1$} zXzVkI6iEpkugq6I(UJQ3YXT;uJxy;;7VM;COG4x3%D z((XX1gpEYFWT++I=6=}Eh&j(9TeBiDFbTPrHRCQYUW$H_VId0H)T(0(H|r9V*S8! zbc0jMkCJUeLG;Le9ru@;^M79X(~fmZkn)xFCh9IblE(X1!|hyJ&XvBqPC$46r9(HN z@=TWpgc&wCGycK+btczF`0N#VZg0+2lt1!*YD0_nrfzVr>L|J8MSb)vqO%*nx2rcM zyIS(T>D^P3g8RZfFLi4nq8`zo@2SEj$c%9YV*N%eD!9a-6_Sf`R(*=tNf};8=PagwVUoU9^c`m z#{L}b-N%sJ0QwKb4vn8}ZAyz#?l?Y^=Wl|pL0XO_yNdFbkA~^|fB>t9?WbSQt+xp_ z4GxH7(f+9Pf7xvyv_}DLL!AWu<=QxFP-|J@YoFtQSD4d+Vtae)7a#NW+>#uuIi9rG zBy3zej@8~%i%Rm4w2su1k3CfDF83zW=ak%fg>86mcJzAXo3Zz`Rwodws;p*%W*E7} zi{R(b9-4OOf3Gv6)|4O?*pDI$D?H|(lWt#s>2`tN;3H&9hc2eem08^AeP$EX9Q5j9 zreVva@sokw4`**ELbu&is27wTypsN~^}CDak!felrmtx|T7@yx2&A_8d2wBXI}>OK zX`Uqep60e4pA??pkK delta 1141 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 O0000wwPRri4?z{J%clO!m?0eo?FC#2; zsV#Cg5&!^OW-uchUTMZ@X%0Wj1e-hI1tAY#8UUQS;qn|lptvk1FC+x;g7=p2G>+DY zT=;1v4PGq=0M7%)iEtpfR{(&CSP;pASRpG&Y>5aP$B}I0VpSsP1d6O8!CMg*ibJbJ zLb05rqF^RGNbufh1~KRf7bt;(VTFXDmq=t>v@aHi#bKyOG#X8oad@O~M$i--K2b1y z2$GUOP^na6m5Z+f^Y_8weegu^Lw#`iWDc7I2_PYN zLbwn0OejbfLZ4fW{zeIe0;94dVVpRgf>HT!xV$)p5W-NUN`aUoQTma=Nw3e*lh)6J zlEJU=lZ{oAR)=%t5~0GVI~DIsAWvxVnf2ohOd?ocMSN=g5)sCiKoYp4WCAu*3~^;r z8Qfiyj8lC7?D1u+kK|Ee0Yt@51^B}J3F?#EA<<=!QX)%;oVbaPGXA5>RG3LgKk3lP z_Mea+?tdzh41V~QsK{3uK`a26$(am#qzciqwpr}#Xa7v9oac?tAxJkm5=|AF2OSZH z1hDp8Ug3yo^OC{!TH0>c#O`@*M-YihdFk#M!L!@wg{EiPT6<;qvkk1KP3QMBmOZFy z-|632^t9cPhB>Q#~-GO@be8>?3J-)}jcTk2N3YoGe+iC=>q>M&aB ztTnAIecQ*58+IQ_{3U2Pe`o&ueXh?;emftn-I8Zm+T*bn0XQ1cS+4>jH_FSbr(a*Z z^kr7V=EXAsbQy}_$OS8!IJ@?0WSu`;FqcOEmyA|8 zFgp+_yvDXY!g(1%cQpg-1R(pe#5VoUn6#3^ro7pfT_r8wwA>!R7t{51oZ;EuknfMp zeeO)q1)K+yqC@nR=BXBd?T@O6yx+^L%4a$5oP((U-WH|LAZ8Wpr>~{WI`n*z! zb0PY-ru9h{eh7waEAzB_kfY0r8=?zVdu_HB0&x9{ipz)fqu#GKCEt6O)PjgF$U5+j z*O1tMEjBjVyM4tjEZAq2w$@}^`LsHW6GM1$} zXzVkI6iEpkugq6I(UJQ3YXT;uJxy;;7VM;COG4x3%D z((XX1gpEYFWT++I=6=}Eh&j(9TeBiDFbTPrHRCQYUW$H_VId0H)T(0(H|r9V*S8! zbc0jMkCJUeLG;Le9ru@;^M79X(~fmZkn)xFCh9IblE(X1!|hyJ&XvBqPC$46r9(HN z@=TWpgc&wCGycK+btczF`0N#VZg0+2lt1!*YD0_nrfzVr>L|J8MSb)vqO%*nx2rcM zyIS(T>D^P3g8RZfFLi4nq8`zo@2SEj$c%9YV*N%eD!9a-6_Sf`R(*=tNf};8=PagwVUoU9^c`m z#{L}b-N%sJ0QwKb4vn8}ZAyz#?l?Y^=Wl|pL0XO_yNdFbkA~^|fB>t9?WbSQt+xp_ z4GxH7(f+9Pf7xvyv_}DLL!AWu<=QxFP-|J@YoFtQSD4d+Vtae)7a#NW+>#uuIi9rG zBy3zej@8~%i%Rm4w2su1k3CfDF83zW=ak%fg>86mcJzAXo3Zz`Rwodws;p*%W*E7} zi{R(b9-4OOf3Gv6)|4O?*pDI$D?H|(lWt#s>2`tN;3H&9hc2eem08^AeP$EX9Q5j9 zreVva@sokw4`**ELbu&is27wTypsN~^}CDak!felrmtx|T7@yx2&A_8d2wBXI}>OK zX`Uqep60e4pA??pkK delta 1141 zcmV-*1d99O5{U_rBYy-?Nkl6!xN<~_!~=u~VJS$!X05Q<$oOMEx;WUzGwZM2?V0r8_7P$7qp%aa7U99Hhks0S-3M2%fBa+b8yEe? z<>C^dn!@B|Iu#>Eq4%~F*Mk6yQMI$N2vJd}&0M8hw(5Ei0HLN5W<#5rP!N!%XvGCe zC7~_^G$hnudY&dWQB}~Ts9*uGW*=}tJqR!u5hKm}VT2MCg#`=fQnCevW!~(zFp*q$ zAxd3+sDTAoY=34Gy_AsA@uSAEs*VNv%N{E(uy=caur&;>xWEADl%?D|0V6vMw}-(3 z7ExeWmVWO9v`xpdH4GM9pu@gJfsq{=wuZri3$)n7Jzz%|T)}=>0PG5b1s5oF1B5yd zpa@_kRGFNmYdREM07~2dp$-H9sO~cR1xn8ZWp|hD_Q&AI%QMIb67zs5MF;+s*6thX@8_q*$+>2fU9DO*u)$}|~ zn)kyf=$H`T=p=0Z^ILqrNybyx5xBvbfOwFe&VOeOLY7=)Vp9brQL9!&PB+P1^}E8E z0Dp6AROd9Pc( z+U5@>T0nj>yUPA2zQ8;00%fHlx%?l1F|$L=?iJa(vR9O80r{^t@{_;%bXc3oLpcQG zC!Mb^&hiIq+G~TV_kdE*@~gl*zX^JOFMq$``+{p@U;Z!P4F>{z55PC-LO^%TZ}$fB zTca)nKrwL|vzkQhlHUq7cq_MdrCThI*LKOBPy-9dAD^u&?~=Qr4ih?X&sHg;q@=(~U%$M(T(8_%FTW^V-_X+1Qs2Nx-^fT8s6w~6 zGOr}DLN~8i8Da>`9GBGM~RsBTId_|A5Z7NlCUU$t=l91qU45Kj08_%qc+?1*r!G zK~5$pWUX=%^U`gVDs)p)(-KQ_N|fvh$}{s)^2^O_^dYKHbwfl^4Ykq7V!sW@*H)21 zsm1v@rJ!)PGcq%=0fz;OC?WhAD)-&xIQ&z#sf3hOHUWakP61Pvo`WJ2Z$VTGCL`inJHoEduz?aPyyo|KRzA) zGVR^nnM|E;H~#qf_J6ZWMSZ;dA$v}n#8n&1>p2fp7V~T(C>V4&`{oxH} z8PAOm>{B>9pK*($^?b%}teO9K7VzHs$+JP<<8wMg?uB#d4YiK5?3pu~%j}rna9{c( z=^(x3vt&a2glFd&ZY`L5p5b?sNj=*Iwzq%Y@*eol9>5&-Kfa)vS*t-Shmg_pw=CtU U`+rnh2UMzfy85}Sb4q9e02n!yC;$Ke literal 247 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=`#fD7Ln`LHy|t0IIe>@Z;)KA6 z=1CK0C@U{b;Y~~A5chA|eJ_6bQ(> diff --git a/Resources/Textures/Structures/Windows/plastitanium_window.rsi/full.png b/Resources/Textures/Structures/Windows/plastitanium_window.rsi/full.png index 629274889050ed48d4114f458c11333d259d1574..8a6165b2e1e4c54099b3aef476e59613b61d586e 100644 GIT binary patch literal 1500 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}e5nzhX}-P; zT0k}j5QD&_;K@Lev%n*=n1Mm}4+t}^JN#w_0|RqfW=KRygs+cPa(=E}VoH8es$NBI z0a%w!g%yyQn_7~nP?4LHS8P>bs{~eI1!RMS^_3LBN=mYAl_Got6rA&mQWebf4D<|? z?6?#Z6l{u8(yW49+@RWlJX@uVl9B=|ef{$Ca=mh6z5JqdeM3u2OML?)eIp}XpbFjM z%Dj@q3f;V7Wr!g#b6ir3lZ!G7N;32F6hP)CCgqow*eWT3EP?}wJ5!S3_7s#B<$!HT zN!CxzNzF~oD=F4D)HBq_rmrM34dKGPVrXyx14bVt1Jq`KRhwr)NwNtrq+Bb2?t%Ib z=+I=ay~QOd`bY}&jSLJdbPbGjjV$%y{sTJSCMDUbB(o$Z6&!GI|A0f#F{cDo6r>&$ z1UZ?YkhRK5%uBabs?beIO-n4zDN(XZE6vHV(TAu&)d>+rHPA*Mi`_OLA6rERr55Ms zl!C(C&dAcz1{@A3qKMFk=!n3o16dSZM?gk?Nj@+&6=f!S=9Q!t6%+we7Q{xVeYjPi zn}x7EG%vHn&IoD%nlO?sq?oaCEGj9_FUk%9#{wh>aY{ptfCMK}%7i3)aL@zOy&ad0 zK0FWEah-lG(*ew^Up-wMLn1iehVS${>>zMgA!|~Ol+-zg?v_PU0xmQBKg|B5zM)O( zj;o-MZp-Gr$sd>}Y=5*iO=i6=yLLc@N_N@v3Tx}?-t24Z>Sx+73GLatd8;5#qR~&2 z-eXY#^Ov6ZTwD3uK#!qe%NpOKOdcN7Un#Ui?pth8Hck7`J=62&{AIVVU3T+!ezoZ@ zS34^v<~oI>VD@*$4SYQ7^w!JvFXB*gHJhNCYV!Js{pQIc|+pjZwxF&YcJ?`cbu+ujhV{GHT~pjhE+Tvk}Hf1%7xYP zS8dW;DzGk!Y0u?976$Sn-?|H4ddEa^GrX?1J-&&Y-5kud#K@@hT5c3CB{n@YE4_yWKZrpvTXjX z783^j*-kgKm^YOi>zS-FU1R0x*WNjqtC<>_{zopr0PH#p761SM delta 467 zcmV;^0WAL93;F|)F@FSSK}|sb0I`n?{9y$E000SaNLh0L04^c`04^c{s^Z;}0004x zNkl`Dz)n*b_+XoT>lgyi;kc56cJ~iIQ9}eZI2ew{{xC!c zWu2VSMa09=8HTPf$~rmF$GUt2>wjQcDE$VXUrWHODFu`QN&%$+O8{;_{p!pMpI<`& z?rAOzUnp77$GUuj|8*S~mXH*gk}aq<0uS`WkwqYxpiH|wwh|w7;6h(WYINI`lp2SS zJD|=RpKn6|cZjQGXe9}X3!iUqPRRWAr&%Px$4ov>m0bWrd;!SfDtIM>njruH002ov JPDHLkV1f$)&w&5{ diff --git a/Resources/Textures/Structures/Windows/plastitanium_window.rsi/meta.json b/Resources/Textures/Structures/Windows/plastitanium_window.rsi/meta.json index 4b89f3cdb00c..c0a1a18425f6 100644 --- a/Resources/Textures/Structures/Windows/plastitanium_window.rsi/meta.json +++ b/Resources/Textures/Structures/Windows/plastitanium_window.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/0b906c6916ce3803473fa6caa65f5b8661118c46", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/0b906c6916ce3803473fa6caa65f5b8661118c46, transparency tweaked by Ubaser.", "size": { "x": 32, "y": 32 diff --git a/Resources/Textures/Structures/Windows/plastitanium_window.rsi/ptwindow0.png b/Resources/Textures/Structures/Windows/plastitanium_window.rsi/ptwindow0.png index 1704c25c2180117565c9558d48558d0f9b2432aa..fe2ddcf1ed405b01fd442a85aa7d1813ec34739e 100644 GIT binary patch literal 2316 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 delta 984 zcmV;}11J2W5bg(%B!7cxLqkwWLqi}?a&Km7Y-IodD9@FVODIH99L9exB8@D}LbAAv zp%f(~OAV1Sr7_BD;oduDM$NsZdq*~w%2ru;Y`hjW)@&_ol~Nuh8(S-4BVGSg4zrf+)%1YvLig$&>R>nvQp9y!lazWt-rJDtQRh$l3Q<-5m z5g!%~3+w4JHp|$`xVCV=a3pCvlCRAaIH`DDv7KGDiuY763@tg+Q%aZF#u($om_)~9 zm1VNz>6Xm2~SmGFA1sfyqqyFG`w_d8Rw~!QyLhZBfzqdo( zHhgdS{@0Q3e;-5j6I?na|H>f@eu%zR(jo`Yv;pT=CC%J{i%n>G%o(l`NYyg6R0`fs z<(p=q`34&13%wQhIk|^~bTx4ed;8Flmh6QJ@2)TJ?SIcRL4QPl0ATWRp!eh8R{#J2 z32;bRa{vGqBme*wBmtWh#uNYm0uf0>K~#8N?VCSK13?hQFE(}(bCrTb6AN3#_yrVV zYbB{|l(a#JVkH`ov_Tu|U}bASzkrIi7A6`5tu6*TtLUw>67x^ENp?2O{9t*Ta2(6K z?A+elOMj@*XgHL(?gVN8p7$1lZXn1FSX@{_4dC|fdbkZpuB>()K)Ld)G#;B)+KJNT z#c&&tT2FNxz|GA)^nOSr=ArkO;#m=8zz8TAkw~PiX~N+#)ik}14GOsd)R0es+1MOv z0FRZ2;jRIDC+7#y4aEND+AeehL2kfgG@gfUAb(z~7&D;x zbr-!tv;nCBpaZA*!Kl}>foY5x;O7Cl*@Q6z`t@2{zmXaM$`&yIlr88y0E-`}%tWUg z*DsRp_-~;sm9CuBcJA;rml;)GbV1$|L{TCJfU-pl0JR3wxq(#%P-F(y7@#wP*1yRN z8mR%G)RM(Cc~JSW)8+9rAbj~pIRxc z+vL)^tV+?Yb&p)irPZ!=se}z(+_T8-J2R}*)1K$~|Ih!t=l#8x-}}DLIp-;E&PqrP zBme+PWEUq7_--#=a_iwek9qth03d#1IyzFwj*ch_kHcWH=m4EF)6o^`lT?W~~_S9tgLV&&?pyEqZxb`C1Hwn*skw9XlM#VptVvDyP6 z%1NehvwwD=Y5;E}{$75DI%c{*eR65KsYLlB-7v9WC_3dJm$u+e6a1Cw9=gZe{3=4} zTI%8QTUI-oUPPSwc4^$$D)8BnORC*&Q%!@{CPx)|UCL*tk1v#aCAbWP>@baqWWC-T zQygIfvh@0IO^|0sl z++30q?xJy;+1BHlA1-9*85$B%WQ*YAuS5nj7lHjiEyo!ih&2o0pK*zM_#| za?A^=pG3@*{nCh8^tQS)u*#sg~kM^<$$l@{`o`v?S+_^!iCth3hTzcEz11RfO9O;UWPW z=-y<8t1DmxpXJ~szS<5Zz`H!x

      +/// Used to control various aspects of a Jaunt. +/// Can be used in place of giving a jaunt-action directly. +/// +[RegisterComponent, NetworkedComponent] +public sealed partial class JauntComponent : Component +{ + /// + /// Which Jaunt Action the component should grant. + /// + [DataField] + public EntProtoId JauntAction = "ActionPolymorphJaunt"; + + /// + /// The jaunt action itself. + /// + public EntityUid? Action; + + // TODO: Enter & Exit Times and Whitelist when Actions are reworked and can support it + // TODO: Cooldown pausing when Actions can support it +} diff --git a/Content.Shared/Jaunt/JauntSystem.cs b/Content.Shared/Jaunt/JauntSystem.cs new file mode 100644 index 000000000000..d9263d000e41 --- /dev/null +++ b/Content.Shared/Jaunt/JauntSystem.cs @@ -0,0 +1,26 @@ +using Content.Shared.Actions; + +namespace Content.Shared.Jaunt; +public sealed class JauntSystem : EntitySystem +{ + [Dependency] private readonly SharedActionsSystem _actions = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnInit); + SubscribeLocalEvent(OnShutdown); + } + + private void OnInit(Entity ent, ref MapInitEvent args) + { + _actions.AddAction(ent.Owner, ref ent.Comp.Action, ent.Comp.JauntAction); + } + + private void OnShutdown(Entity ent, ref ComponentShutdown args) + { + _actions.RemoveAction(ent.Owner, ent.Comp.Action); + } + +} + diff --git a/Content.Shared/Polymorph/PolymorphPrototype.cs b/Content.Shared/Polymorph/PolymorphPrototype.cs index 6d010711d2e7..c05766940840 100644 --- a/Content.Shared/Polymorph/PolymorphPrototype.cs +++ b/Content.Shared/Polymorph/PolymorphPrototype.cs @@ -1,3 +1,4 @@ +using Robust.Shared.Audio; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Array; @@ -115,6 +116,18 @@ public sealed partial record PolymorphConfiguration [DataField(serverOnly: true)] [ViewVariables(VVAccess.ReadWrite)] public TimeSpan Cooldown = TimeSpan.Zero; + + /// + /// If not null, this sound will be played when being polymorphed into something. + /// + [DataField] + public SoundSpecifier? PolymorphSound; + + /// + /// If not null, this sound will be played when being reverted from a polymorph. + /// + [DataField] + public SoundSpecifier? ExitPolymorphSound; } public enum PolymorphInventoryChange : byte diff --git a/Resources/Audio/Magic/attributions.yml b/Resources/Audio/Magic/attributions.yml index cedda322862f..bfbe4d6ec24d 100644 --- a/Resources/Audio/Magic/attributions.yml +++ b/Resources/Audio/Magic/attributions.yml @@ -17,6 +17,8 @@ - forcewall.ogg - knock.ogg - blink.ogg - copyright: '"ForceWall.ogg", "Knock.ogg", and "blink.ogg" by Citadel Station 13' + - ethereal_enter.ogg + - ethereal_exit.ogg + copyright: '"forcewall.ogg", "knock.ogg", "blink.ogg", "ethereal_enter.ogg", and "ethereal_exit.ogg" by Citadel Station 13' license: CC-BY-SA-3.0 source: https://github.com/Citadel-Station-13/Citadel-Station-13/commit/35a1723e98a60f375df590ca572cc90f1bb80bd5 diff --git a/Resources/Audio/Magic/ethereal_enter.ogg b/Resources/Audio/Magic/ethereal_enter.ogg new file mode 100644 index 0000000000000000000000000000000000000000..a0c7222c16798c3c037cba5e90d5899644b52e8a GIT binary patch literal 36619 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 U3Scl3to$`8GTa5YJ^;tL0a{;58~^|S literal 0 HcmV?d00001 diff --git a/Resources/Audio/Magic/ethereal_exit.ogg b/Resources/Audio/Magic/ethereal_exit.ogg new file mode 100644 index 0000000000000000000000000000000000000000..bd60ca8c6957934445cbca1f7c691cb57cc69dff GIT binary patch literal 42980 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 literal 0 HcmV?d00001 diff --git a/Resources/Locale/en-US/store/spellbook-catalog.ftl b/Resources/Locale/en-US/store/spellbook-catalog.ftl index 457f02916f91..1d970f6e3ac9 100644 --- a/Resources/Locale/en-US/store/spellbook-catalog.ftl +++ b/Resources/Locale/en-US/store/spellbook-catalog.ftl @@ -17,6 +17,9 @@ spellbook-polymorph-rod-desc = Change into an Immovable Rod with limited movemen spellbook-charge-name = Charge spellbook-charge-desc = Adds a charge back to your wand! +spellbook-ethereal-jaunt-name = Ethereal Jaunt +spellbook-ethereal-jaunt-description = Slip into the ethereal plane to slip away from your enemies! + # Equipment spellbook-wand-polymorph-door-name = Wand of Entrance @@ -33,3 +36,6 @@ spellbook-event-summon-ghosts-description = Who ya gonna call? # Upgrades spellbook-upgrade-fireball-name = Upgrade Fireball spellbook-upgrade-fireball-description = Upgrades Fireball to a maximum of level 3! + +spellbook-upgrade-jaunt-name = Upgrade Ethereal Jaunt +spellbook-upgrade-jaunt-description = Upgrades Jaunt to a maximum of level 3! diff --git a/Resources/Prototypes/Actions/polymorph.yml b/Resources/Prototypes/Actions/polymorph.yml index 81feba4eaccc..291400ab3884 100644 --- a/Resources/Prototypes/Actions/polymorph.yml +++ b/Resources/Prototypes/Actions/polymorph.yml @@ -40,3 +40,53 @@ icon: sprite: Objects/Fun/immovable_rod.rsi state: icon + +- type: entity + id: ActionPolymorphJaunt + name: Ethereal Jaunt + description: Melt into the Ethereal Plane for a quick getaway! + components: + - type: Magic + - type: InstantAction + useDelay: 30 + event: !type:PolymorphActionEvent + protoId: Jaunt + itemIconStyle: NoItem + icon: + sprite: Objects/Magic/magicactions.rsi + state: jaunt + # TODO: Effect ECS (from cardboard box) + - type: ActionUpgrade + effectedLevels: + 2: ActionPolymorphJauntII + 3: ActionPolymorphJauntIII + +- type: entity + id: ActionPolymorphJauntII + parent: ActionPolymorphJaunt + name: Ethereal Jaunt II + description: Melt into the Ethereal Plane for an even quicker getaway! + components: + - type: InstantAction + useDelay: 25 + event: !type:PolymorphActionEvent + protoId: Jaunt + itemIconStyle: NoItem + icon: + sprite: Objects/Magic/magicactions.rsi + state: jaunt + +- type: entity + id: ActionPolymorphJauntIII + parent: ActionPolymorphJaunt + name: Ethereal Jaunt III + description: Are you even tangible anymore? + components: + - type: InstantAction + useDelay: 20 + event: !type:PolymorphActionEvent + protoId: Jaunt + itemIconStyle: NoItem + icon: + sprite: Objects/Magic/magicactions.rsi + state: jaunt diff --git a/Resources/Prototypes/Catalog/spellbook_catalog.yml b/Resources/Prototypes/Catalog/spellbook_catalog.yml index 38b95c3273c5..805c157f1e31 100644 --- a/Resources/Prototypes/Catalog/spellbook_catalog.yml +++ b/Resources/Prototypes/Catalog/spellbook_catalog.yml @@ -77,6 +77,20 @@ - !type:ListingLimitedStockCondition stock: 1 +- type: listing + id: SpellbookJaunt + name: spellbook-ethereal-jaunt-name + description: spellbook-ethereal-jaunt-description + productAction: ActionPolymorphJaunt + productUpgradeId: SpellbookJauntUpgrade + cost: + WizCoin: 2 + categories: + - SpellbookUtility + conditions: + - !type:ListingLimitedStockCondition + stock: 1 + # Equipment - type: listing id: SpellbookWandDoor @@ -138,3 +152,22 @@ # manual for now - !type:ListingLimitedStockCondition stock: 2 + +- type: listing + id: SpellbookJauntUpgrade + productUpgradeId: SpellbookJauntUpgrade + name: spellbook-upgrade-jaunt-name + description: spellbook-upgrade-jaunt-description + icon: + sprite: Objects/Magic/magicactions.rsi + state: jaunt + cost: + WizCoin: 2 + categories: + - SpellbookUtility + conditions: + - !type:BuyBeforeCondition + whitelist: + - SpellbookJaunt + - !type:ListingLimitedStockCondition + stock: 2 diff --git a/Resources/Prototypes/Entities/Mobs/Player/jaunt_mobs.yml b/Resources/Prototypes/Entities/Mobs/Player/jaunt_mobs.yml new file mode 100644 index 000000000000..3002264a7541 --- /dev/null +++ b/Resources/Prototypes/Entities/Mobs/Player/jaunt_mobs.yml @@ -0,0 +1,40 @@ +- type: entity + name: jaunt + parent: [Incorporeal, BaseMob] + id: BaseMobJaunt + description: Faint traces of a humanoid figure linger here + suffix: Ethereal + components: + - type: ContentEye + maxZoom: 1.44,1.44 + - type: Eye + drawFov: false + - type: Input + context: "ghost" + - type: InputMover + - type: MovementSpeedModifier + baseSprintSpeed: 12 + baseWalkSpeed: 8 + - type: Visibility + layer: 2 + - type: Spectral + +# Should be slow, for balance +- type: entity + name: jaunt + parent: BaseMobJaunt + id: EtherealJaunt + suffix: Wizard + components: + - type: Sprite + sprite: Mobs/Ghosts/ghost_human.rsi + color: "#60f7eb" + layers: + - state: animated + shader: unshaded + noRot: true + overrideContainerOcclusion: true + drawdepth: Ghosts + - type: MovementSpeedModifier + baseSprintSpeed: 6 + baseWalkSpeed: 4 diff --git a/Resources/Prototypes/Polymorphs/polymorph.yml b/Resources/Prototypes/Polymorphs/polymorph.yml index 96739a50d3ca..fe28287cb09e 100644 --- a/Resources/Prototypes/Polymorphs/polymorph.yml +++ b/Resources/Prototypes/Polymorphs/polymorph.yml @@ -186,3 +186,19 @@ forced: true revertOnCrit: false revertOnDeath: false + +# Temporary Jaunt +# Don't make permanent jaunts until action system can be reworked to allow do afters and cooldown pausing +- type: polymorph + id: Jaunt + configuration: + entity: EtherealJaunt + transferName: true + inventory: None + forced: true + revertOnDeath: true + revertOnCrit: true + allowRepeatedMorphs: false + polymorphSound: /Audio/Magic/ethereal_enter.ogg + exitPolymorphSound: /Audio/Magic/ethereal_exit.ogg + duration: 3 diff --git a/Resources/Textures/Objects/Magic/magicactions.rsi/jaunt.png b/Resources/Textures/Objects/Magic/magicactions.rsi/jaunt.png new file mode 100644 index 0000000000000000000000000000000000000000..f66002b46956d4945c822e3a1c8fb2ac510ba1b2 GIT binary patch literal 431 zcmV;g0Z{&lP)UHiqSqj+6g!)RMIZ&f6%rCpJrILa$KyEO1(LqNPK#z0XJ{uA{GEhU ztxW~u#V{+c`bF)L48CuxPIFaYZNs&iy0Hnd5&xtUVx)F~G*|?@>NS-UGp9swEIpK1 z1l-s>95R^sS_!!41KX}NGhF Date: Wed, 13 Nov 2024 23:37:44 +0000 Subject: [PATCH 088/290] Automatic changelog update --- Resources/Changelog/Changelog.yml | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 3365a943ee6a..9cc788c96f74 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,20 +1,4 @@ Entries: -- author: IProduceWidgets - changes: - - message: shuttle events have been separated from other midround events and can - now happen concurrently. - type: Tweak - - message: Cargo Gift events should be less likely. - type: Tweak - - message: meteors have been changed to be more responsive to player count. - type: Tweak - - message: 'Game mode: Kessler syndrome - What if survival but also the apocalypse?' - type: Add - - message: 'Game mode: Zombeteors - Zombies and a meteor shower all at once!' - type: Add - id: 7107 - time: '2024-08-14T05:21:02.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/29320 - author: Blackern5000 changes: - message: Combat medical kits now contain saline syringes. @@ -3949,3 +3933,11 @@ id: 7606 time: '2024-11-13T12:30:40.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33282 +- author: keronshb + changes: + - message: Added Ethereal Jaunt! A Wizard Spell that turns you invisible and into + a ghost-like creature for escaping! + type: Add + id: 7607 + time: '2024-11-13T23:36:37.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33201 From 4f754b814bdc7c72d900e6d13aef4eb0a533cdce Mon Sep 17 00:00:00 2001 From: ScarKy0 Date: Thu, 14 Nov 2024 14:55:01 +0100 Subject: [PATCH 089/290] derelictn't (for now) --- .../ghost/roles/ghost-role-component.ftl | 3 -- .../interaction-popup-component.ftl | 1 - .../Entities/Markers/Spawners/ghost_roles.yml | 20 +--------- .../Mobs/Cyborgs/base_borg_chassis.yml | 21 +--------- .../Entities/Mobs/Cyborgs/borg_chassis.yml | 37 +----------------- .../Entities/Mobs/Player/silicon.yml | 36 +---------------- Resources/Prototypes/GameRules/events.yml | 23 +---------- .../Construction/Graphs/machines/cyborg.yml | 5 +-- .../Mobs/Silicon/chassis.rsi/derelict.png | Bin 11838 -> 0 bytes .../Mobs/Silicon/chassis.rsi/derelict_e.png | Bin 5508 -> 0 bytes .../Mobs/Silicon/chassis.rsi/derelict_e_r.png | Bin 5515 -> 0 bytes .../Silicon/chassis.rsi/derelict_icon.png | Bin 6429 -> 0 bytes .../Mobs/Silicon/chassis.rsi/derelict_l.png | Bin 6986 -> 0 bytes .../Mobs/Silicon/chassis.rsi/meta.json | 20 ---------- 14 files changed, 6 insertions(+), 160 deletions(-) delete mode 100644 Resources/Textures/Mobs/Silicon/chassis.rsi/derelict.png delete mode 100644 Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_e.png delete mode 100644 Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_e_r.png delete mode 100644 Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_icon.png delete mode 100644 Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_l.png diff --git a/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl b/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl index f584a4b35fe0..77d2645c4c5c 100644 --- a/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl +++ b/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl @@ -240,9 +240,6 @@ ghost-role-information-syndicate-cyborg-assault-name = Syndicate Assault Cyborg ghost-role-information-syndicate-cyborg-saboteur-name = Syndicate Saboteur Cyborg ghost-role-information-syndicate-cyborg-description = The Syndicate needs reinforcements. You, a cold silicon killing machine, will help them. -ghost-role-information-derelict-cyborg-name = Derelict Cyborg -ghost-role-information-derelict-cyborg-description = You were a regular cyborg that got lost in space. After drifting in whichever direction the laws of physics would have it for years, you have drifted close to a Nanotrasen space station. You have a fire extinguisher and mass scanner which can be used to board the station. Years of exposure to ion storms have left your silicon laws altered - check them upon spawning. - ghost-role-information-security-name = Security ghost-role-information-security-description = You are part of a security task force, but seem to have found yourself in a strange situation... diff --git a/Resources/Locale/en-US/interaction/interaction-popup-component.ftl b/Resources/Locale/en-US/interaction/interaction-popup-component.ftl index 65310b67f988..46959705c267 100644 --- a/Resources/Locale/en-US/interaction/interaction-popup-component.ftl +++ b/Resources/Locale/en-US/interaction/interaction-popup-component.ftl @@ -67,7 +67,6 @@ petting-success-janitor-cyborg = You pet {THE($target)} on {POSS-ADJ($target)} d petting-success-medical-cyborg = You pet {THE($target)} on {POSS-ADJ($target)} sterile metal head. petting-success-service-cyborg = You pet {THE($target)} on {POSS-ADJ($target)} dapper looking metal head. petting-success-syndicate-cyborg = You pet {THE($target)} on {POSS-ADJ($target)} menacing metal head. -petting-success-derelict-cyborg = You pet {THE($target)} on {POSS-ADJ($target)} rusty metal head. petting-success-recycler = You pet {THE($target)} on {POSS-ADJ($target)} mildly threatening steel exterior. petting-failure-honkbot = You reach out to pet {THE($target)}, but {SUBJECT($target)} {CONJUGATE-BASIC($target, "honk", "honks")} in refusal! diff --git a/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml b/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml index 18d459cd89e3..a614fb596397 100644 --- a/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml +++ b/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml @@ -169,22 +169,4 @@ layers: - state: green - sprite: Objects/Weapons/Melee/energykatana.rsi - state: icon - -- type: entity - categories: [ HideSpawnMenu, Spawner ] - parent: BaseAntagSpawner - id: SpawnPointGhostDerelictCyborg - components: - - type: GhostRole - name: ghost-role-information-derelict-cyborg-name - description: ghost-role-information-derelict-cyborg-description - rules: ghost-role-information-silicon-rules - raffle: - settings: default - - type: Sprite - sprite: Markers/jobs.rsi - layers: - - state: green - - sprite: Mobs/Silicon/chassis.rsi - state: derelict_icon \ No newline at end of file + state: icon \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml index 7449fe5669fe..902238435257 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml @@ -316,23 +316,4 @@ sounds: Unsexed: UnisexSiliconSyndicate - type: PointLight - color: "#dd200b" - -- type: entity - id: BaseBorgChassisDerelict - parent: BaseBorgChassis - abstract: true - components: - - type: NpcFactionMember - factions: - - NanoTrasen #The seemingly best fit. It was a regular NT cyborg once, after all. - - type: Access - enabled: false - groups: - - AllAccess #Randomized access would be fun. AllAccess is the best i can think of right now that does make it too hard for it to enter the station or navigate it.. - - type: AccessReader - access: [["Command"], ["Research"]] - - type: StartIonStormed - ionStormAmount: 4 - - type: IonStormTarget - chance: 1 \ No newline at end of file + color: "#dd200b" \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml index 818847f24490..04d629279e87 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml @@ -441,39 +441,4 @@ interactSuccessString: petting-success-syndicate-cyborg interactFailureString: petting-failure-syndicate-cyborg interactSuccessSound: - path: /Audio/Ambience/Objects/periodic_beep.ogg - - -- type: entity - id: BorgChassisDerelict - parent: BaseBorgChassisDerelict - name: derelict cyborg - description: A man-machine hybrid that assists in station activity. This one is in a state of great disrepair. - components: - - type: Sprite - layers: - - state: derelict - - state: derelict_e_r - map: ["enum.BorgVisualLayers.Light"] - shader: unshaded - visible: false - - state: derelict_l - shader: unshaded - map: ["light"] - visible: false - - type: BorgChassis - maxModules: 5 #The sixth one broke lol. - moduleWhitelist: - tags: - - BorgModuleGeneric - hasMindState: derelict_e - noMindState: derelict_e_r - - type: Construction - node: derelictcyborg - - type: Speech - speechVerb: Robotic - - type: InteractionPopup - interactSuccessString: petting-success-derelict-cyborg - interactFailureString: petting-failure-derelict-cyborg - interactSuccessSound: - path: /Audio/Ambience/Objects/periodic_beep.ogg \ No newline at end of file + path: /Audio/Ambience/Objects/periodic_beep.ogg \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml index 22f49c93eaae..71b8a92d1c9d 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml @@ -514,38 +514,4 @@ prototypes: - PlayerBorgSyndicateAssaultGhostRole - PlayerBorgSyndicateAssaultGhostRole # Saboteurs are kinda like cyborg medics, we want less. - - PlayerBorgSyndicateSaboteurGhostRole - -- type: entity - id: PlayerBorgDerelict - parent: BorgChassisDerelict - suffix: Battery, Module - components: - - type: ContainerFill - containers: - borg_brain: - - PositronicBrain - borg_module: - - BorgModuleTool - - BorgModuleFireExtinguisher - - BorgModuleGPS - - type: ItemSlots - slots: - cell_slot: - name: power-cell-slot-component-slot-name-default - startingItem: PowerCellHigh - - type: RandomMetadata - nameSegments: [names_borg] - -- type: entity - id: PlayerBorgDerelictGhostRole - parent: PlayerBorgDerelict - suffix: Ghost role - components: - - type: GhostRole - name: ghost-role-information-derelict-cyborg-name - description: ghost-role-information-derelict-cyborg-description - rules: ghost-role-information-silicon-rules - raffle: - settings: default - - type: GhostTakeoverAvailable + - PlayerBorgSyndicateSaboteurGhostRole \ No newline at end of file diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index 763557e6c91b..364a41288748 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -545,25 +545,4 @@ minimumPlayers: 20 maxOccurrences: 1 # this event has diminishing returns on interesting-ness, so we cap it weight: 5 - - type: MobReplacementRule - -- type: entity - parent: BaseGameRule - id: DerelictCyborgSpawn - components: - - type: StationEvent - weight: 5 - earliestStart: 15 - reoccurrenceDelay: 20 - minimumPlayers: 4 - duration: null - - type: SpaceSpawnRule - spawnDistance: 0 - - type: AntagSpawner - prototype: PlayerBorgDerelict - - type: AntagSelection - definitions: - - spawnerPrototype: SpawnPointGhostDerelictCyborg - min: 1 - max: 1 - pickPlayer: false \ No newline at end of file + - type: MobReplacementRule \ No newline at end of file diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml b/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml index 3f8a731cbbd7..8fd528575e02 100644 --- a/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml +++ b/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml @@ -204,7 +204,4 @@ entity: BorgChassisSyndicateMedical - node: syndicatesaboteur - entity: BorgChassisSyndicateSaboteur - - - node: derelictcyborg - entity: BorgChassisDerelict + entity: BorgChassisSyndicateSaboteur \ No newline at end of file diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict.png b/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict.png deleted file mode 100644 index bbf72fc45bed2408b2abeb91d3564f8fa41e6e5a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11838 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 HpFaCP!NMbp diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_e.png b/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_e.png deleted file mode 100644 index 17349d74dc8ba9bbf0e434b9e32e634535c3a244..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5508 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 LUFhdl`^x_VBy@7n diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_e_r.png b/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_e_r.png deleted file mode 100644 index 3c8cf19acf66f1c662629db09546f8a553a3c658..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5515 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 S?UyLhp|`uATeV9>+J69Pac{i< diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_icon.png b/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_icon.png deleted file mode 100644 index 7f0ea2a25560f33773cd72d6184daba55dd4d033..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6429 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 diff --git a/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_l.png b/Resources/Textures/Mobs/Silicon/chassis.rsi/derelict_l.png deleted file mode 100644 index f65fbaebc3c5074e945e94f59b8d90b83ac08bb3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6986 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 Date: Thu, 14 Nov 2024 14:57:05 +0100 Subject: [PATCH 090/290] Update Label workflows to use new labels (#33310) * Update labeler.yml * Update labeler-needsreview.yml * Update labeler-staging.yml * Update labeler-stable.yml * Update labeler-untriaged.yml * Create labeler-size.yml * Update labeler-size.yml * Update labeler-size.yml * Update conflict-labeler.yml * Rename conflict-labeler.yml to labeler-conflict.yml --- .github/labeler.yml | 2 +- ...flict-labeler.yml => labeler-conflict.yml} | 2 +- .github/workflows/labeler-needsreview.yml | 4 ++-- .github/workflows/labeler-size.yml | 20 +++++++++++++++++++ .github/workflows/labeler-stable.yml | 2 +- .github/workflows/labeler-staging.yml | 2 +- .github/workflows/labeler-untriaged.yml | 4 +++- 7 files changed, 29 insertions(+), 7 deletions(-) rename .github/workflows/{conflict-labeler.yml => labeler-conflict.yml} (93%) create mode 100644 .github/workflows/labeler-size.yml diff --git a/.github/labeler.yml b/.github/labeler.yml index 97b402eda9ff..69b2ca87749c 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -16,7 +16,7 @@ - changed-files: - any-glob-to-any-file: '**/*.swsl' -"No C#": +"Changes: No C#": - changed-files: # Equiv to any-glob-to-all as long as this has one matcher. If ALL changed files are not C# files, then apply label. - all-globs-to-all-files: "!**/*.cs" diff --git a/.github/workflows/conflict-labeler.yml b/.github/workflows/labeler-conflict.yml similarity index 93% rename from .github/workflows/conflict-labeler.yml rename to .github/workflows/labeler-conflict.yml index 1e2125c30a23..ebcc54d4604d 100644 --- a/.github/workflows/conflict-labeler.yml +++ b/.github/workflows/labeler-conflict.yml @@ -16,6 +16,6 @@ jobs: - name: Check for Merge Conflicts uses: eps1lon/actions-label-merge-conflict@v3.0.0 with: - dirtyLabel: "Merge Conflict" + dirtyLabel: "S: Merge Conflict" repoToken: "${{ secrets.GITHUB_TOKEN }}" commentOnDirty: "This pull request has conflicts, please resolve those before we can evaluate the pull request." diff --git a/.github/workflows/labeler-needsreview.yml b/.github/workflows/labeler-needsreview.yml index 311048acb0f3..819b34b7bbd3 100644 --- a/.github/workflows/labeler-needsreview.yml +++ b/.github/workflows/labeler-needsreview.yml @@ -10,7 +10,7 @@ jobs: steps: - uses: actions-ecosystem/action-add-labels@v1 with: - labels: "Status: Needs Review" + labels: "S: Needs Review" - uses: actions-ecosystem/action-remove-labels@v1 with: - labels: "Status: Awaiting Changes" + labels: "S: Awaiting Changes" diff --git a/.github/workflows/labeler-size.yml b/.github/workflows/labeler-size.yml new file mode 100644 index 000000000000..ad6e35c82929 --- /dev/null +++ b/.github/workflows/labeler-size.yml @@ -0,0 +1,20 @@ +name: "Labels: Size" +on: pull_request_target +jobs: + size-label: + runs-on: ubuntu-latest + steps: + - name: size-label + uses: "pascalgn/size-label-action@v0.5.5" + env: + GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + with: + # Custom size configuration + sizes: > + { + "0": "XS", + "10": "S", + "30": "M", + "100": "L", + "1000": "XL" + } diff --git a/.github/workflows/labeler-stable.yml b/.github/workflows/labeler-stable.yml index 491d6a76fad5..f6fd2033a11b 100644 --- a/.github/workflows/labeler-stable.yml +++ b/.github/workflows/labeler-stable.yml @@ -13,4 +13,4 @@ jobs: steps: - uses: actions-ecosystem/action-add-labels@v1 with: - labels: "Branch: stable" + labels: "Branch: Stable" diff --git a/.github/workflows/labeler-staging.yml b/.github/workflows/labeler-staging.yml index e31a5a482f2d..b46a198aefb5 100644 --- a/.github/workflows/labeler-staging.yml +++ b/.github/workflows/labeler-staging.yml @@ -13,4 +13,4 @@ jobs: steps: - uses: actions-ecosystem/action-add-labels@v1 with: - labels: "Branch: staging" + labels: "Branch: Staging" diff --git a/.github/workflows/labeler-untriaged.yml b/.github/workflows/labeler-untriaged.yml index 775aab265468..ec1d194851c5 100644 --- a/.github/workflows/labeler-untriaged.yml +++ b/.github/workflows/labeler-untriaged.yml @@ -3,6 +3,8 @@ on: issues: types: [opened] + pull_request_target: + types: [opened] jobs: add_label: @@ -11,4 +13,4 @@ jobs: - uses: actions-ecosystem/action-add-labels@v1 if: join(github.event.issue.labels) == '' with: - labels: "Status: Untriaged" + labels: "S: Untriaged" From c86201308a81548601afe3a205e592a05afc2dfb Mon Sep 17 00:00:00 2001 From: ScarKy0 Date: Thu, 14 Nov 2024 15:01:04 +0100 Subject: [PATCH 091/290] guh --- .../Locale/en-US/interaction/interaction-popup-component.ftl | 2 -- Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml | 2 +- .../Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml | 2 +- Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml | 2 +- Resources/Prototypes/Entities/Mobs/Player/silicon.yml | 2 +- Resources/Prototypes/GameRules/events.yml | 2 +- .../Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml | 2 +- 7 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Resources/Locale/en-US/interaction/interaction-popup-component.ftl b/Resources/Locale/en-US/interaction/interaction-popup-component.ftl index 69a700fdeb43..a180b698fac9 100644 --- a/Resources/Locale/en-US/interaction/interaction-popup-component.ftl +++ b/Resources/Locale/en-US/interaction/interaction-popup-component.ftl @@ -82,8 +82,6 @@ petting-failure-janitor-cyborg = You reach out to pet {THE($target)}, but {SUBJE petting-failure-medical-cyborg = You reach out to pet {THE($target)}, but {SUBJECT($target)} {CONJUGATE-BE($target)} busy saving lives! petting-failure-service-cyborg = You reach out to pet {THE($target)}, but {SUBJECT($target)} {CONJUGATE-BE($target)} busy serving others! petting-failure-syndicate-cyborg = You reach out to pet {THE($target)}, but {POSS-ADJ($target)} treacherous affiliation makes you reconsider. -petting-failure-derelict-cyborg = You reach out to pet {THE($target)}, but {POSS-ADJ($target)} rusty and jagged exterior makes you reconsider. - ## Rattling fences diff --git a/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml b/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml index a614fb596397..b694a8cc2f2b 100644 --- a/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml +++ b/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml @@ -169,4 +169,4 @@ layers: - state: green - sprite: Objects/Weapons/Melee/energykatana.rsi - state: icon \ No newline at end of file + state: icon diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml index 26e0ce4c7944..0db92ac941d4 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml @@ -317,4 +317,4 @@ sounds: Unsexed: UnisexSiliconSyndicate - type: PointLight - color: "#dd200b" \ No newline at end of file + color: "#dd200b" diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml index c38172349965..6a8f1e5abb08 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml @@ -439,4 +439,4 @@ interactSuccessString: petting-success-syndicate-cyborg interactFailureString: petting-failure-syndicate-cyborg interactSuccessSound: - path: /Audio/Ambience/Objects/periodic_beep.ogg \ No newline at end of file + path: /Audio/Ambience/Objects/periodic_beep.ogg diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml index cef834c0b607..e787ef59f00a 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml @@ -543,4 +543,4 @@ prototypes: - PlayerBorgSyndicateAssaultGhostRole - PlayerBorgSyndicateAssaultGhostRole # Saboteurs are kinda like cyborg medics, we want less. - - PlayerBorgSyndicateSaboteurGhostRole \ No newline at end of file + - PlayerBorgSyndicateSaboteurGhostRole diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index 32af0835c71d..fafb6bd42838 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -540,4 +540,4 @@ minimumPlayers: 20 maxOccurrences: 1 # this event has diminishing returns on interesting-ness, so we cap it weight: 5 - - type: MobReplacementRule \ No newline at end of file + - type: MobReplacementRule diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml b/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml index 8fd528575e02..0f012cefc98e 100644 --- a/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml +++ b/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml @@ -204,4 +204,4 @@ entity: BorgChassisSyndicateMedical - node: syndicatesaboteur - entity: BorgChassisSyndicateSaboteur \ No newline at end of file + entity: BorgChassisSyndicateSaboteur From 5dbea427517a91fd9fce7ea48d3d911a37c81779 Mon Sep 17 00:00:00 2001 From: ScarKy0 Date: Thu, 14 Nov 2024 15:05:14 +0100 Subject: [PATCH 092/290] derelicn't for real --- Resources/Prototypes/GameRules/events.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml index fafb6bd42838..08218accede4 100644 --- a/Resources/Prototypes/GameRules/events.yml +++ b/Resources/Prototypes/GameRules/events.yml @@ -35,7 +35,6 @@ - id: RevenantSpawn - id: SleeperAgents - id: ZombieOutbreak - - id: DerelictCyborgSpawn - id: LoneOpsSpawn - type: entity From 0f30639cf25866f285638d36632e4c3ddf07874e Mon Sep 17 00:00:00 2001 From: ScarKy0 Date: Thu, 14 Nov 2024 17:21:03 +0100 Subject: [PATCH 093/290] progress --- .../Silicons/Laws/SiliconLawSystem.cs | 74 ++++++++----------- .../Silicons/Laws/StartIonStormedSystem.cs | 38 ---------- .../Components/EmagSiliconLawComponent.cs | 7 -- .../Components/SiliconLawProviderComponent.cs | 6 ++ .../Components/StartIonStormedComponent.cs | 24 ------ 5 files changed, 38 insertions(+), 111 deletions(-) delete mode 100644 Content.Server/Silicons/Laws/StartIonStormedSystem.cs delete mode 100644 Content.Shared/Silicons/Laws/Components/StartIonStormedComponent.cs diff --git a/Content.Server/Silicons/Laws/SiliconLawSystem.cs b/Content.Server/Silicons/Laws/SiliconLawSystem.cs index c2aa20f401c5..a4a7ee528f70 100644 --- a/Content.Server/Silicons/Laws/SiliconLawSystem.cs +++ b/Content.Server/Silicons/Laws/SiliconLawSystem.cs @@ -1,3 +1,4 @@ +using System.Diagnostics; using System.Linq; using Content.Server.Administration; using Content.Server.Chat.Managers; @@ -22,7 +23,6 @@ using Robust.Shared.Prototypes; using Robust.Shared.Toolshed; using Robust.Shared.Audio; -using Robust.Shared.GameObjects; namespace Content.Server.Silicons.Laws; @@ -50,11 +50,9 @@ public override void Initialize() SubscribeLocalEvent(OnDirectedGetLaws); SubscribeLocalEvent(OnIonStormLaws); + SubscribeLocalEvent(OnLawProviderMindAdded); + SubscribeLocalEvent(OnLawProviderMindRemoved); SubscribeLocalEvent(OnEmagLawsAdded); - SubscribeLocalEvent(OnEmagMindAdded); - SubscribeLocalEvent(OnEmagMindRemoved); - SubscribeLocalEvent(OnStartIonStormedMindAdded); - SubscribeLocalEvent(OnStartIonStormedMindRemoved); } private void OnMapInit(EntityUid uid, SiliconLawBoundComponent component, MapInitEvent args) @@ -73,6 +71,22 @@ private void OnMindAdded(EntityUid uid, SiliconLawBoundComponent component, Mind actor.PlayerSession.Channel, colorOverride: Color.FromHex("#2ed2fd")); } + private void OnLawProviderMindAdded(EntityUid uid, SiliconLawProviderComponent component, MindAddedMessage args) + { + if (!component.Subverted) + return; + EnsureSubvertedSiliconRole(uid); + } + + private void OnLawProviderMindRemoved(EntityUid uid, SiliconLawProviderComponent component, MindRemovedMessage args) + { + if (!component.Subverted) + return; + RemoveSubvertedSiliconRole(uid); + + } + + private void OnToggleLawsScreen(EntityUid uid, SiliconLawBoundComponent component, ToggleLawsScreenEvent args) { if (args.Handled || !TryComp(uid, out var actor)) @@ -119,9 +133,11 @@ private void OnIonStormLaws(EntityUid uid, SiliconLawProviderComponent component // gotta tell player to check their laws NotifyLawsChanged(uid, component.LawUploadSound); + // Show the silicon has been subverted. + component.Subverted = true; + // new laws may allow antagonist behaviour so make it clear for admins - if (TryComp(uid, out var emag)) - EnsureEmaggedRole(uid, emag); + EnsureSubvertedSiliconRole(uid); } } @@ -132,6 +148,9 @@ private void OnEmagLawsAdded(EntityUid uid, SiliconLawProviderComponent componen if (component.Lawset == null) component.Lawset = GetLawset(component.Laws); + // Show the silicon has been subverted. + component.Subverted = true; + // Add the first emag law before the others component.Lawset?.Laws.Insert(0, new SiliconLaw { @@ -154,58 +173,29 @@ protected override void OnGotEmagged(EntityUid uid, EmagSiliconLawComponent comp base.OnGotEmagged(uid, component, ref args); NotifyLawsChanged(uid, component.EmaggedSound); - EnsureEmaggedRole(uid, component); + EnsureSubvertedSiliconRole(uid); _stunSystem.TryParalyze(uid, component.StunTime, true); } - private void OnEmagMindAdded(EntityUid uid, EmagSiliconLawComponent component, MindAddedMessage args) - { - if (HasComp(uid)) - EnsureEmaggedRole(uid, component); - } - - private void OnEmagMindRemoved(EntityUid uid, EmagSiliconLawComponent component, MindRemovedMessage args) + private void EnsureSubvertedSiliconRole(EntityUid uid) { - if (component.AntagonistRole == null) - return; - - _roles.MindTryRemoveRole(args.Mind); - } - - private void EnsureEmaggedRole(EntityUid uid, EmagSiliconLawComponent component) - { - if (component.AntagonistRole == null || !_mind.TryGetMind(uid, out var mindId, out _)) + if (!_mind.TryGetMind(uid, out var mindId, out _)) return; if (!_roles.MindHasRole(mindId)) _roles.MindAddRole(mindId, "MindRoleSubvertedSilicon"); - } - - private void OnStartIonStormedMindAdded(EntityUid uid, StartIonStormedComponent component, MindAddedMessage args) - { - if (HasComp(uid)) - EnsureStartIonStormedRole(uid, component); - } - private void OnStartIonStormedMindRemoved(EntityUid uid, StartIonStormedComponent component, MindRemovedMessage args) - { - if (component.AntagonistRole == null) - return; - - _roles.MindTryRemoveRole(args.Mind); } - private void EnsureStartIonStormedRole(EntityUid uid, StartIonStormedComponent component) + private void RemoveSubvertedSiliconRole(EntityUid uid) { - if (component.AntagonistRole == null || !_mind.TryGetMind(uid, out var mindId, out _)) + if (!_mind.TryGetMind(uid, out var mindId, out _)) return; if (_roles.MindHasRole(mindId)) - return; - - _roles.MindAddRole(mindId, new SubvertedSiliconRoleComponent { PrototypeId = component.AntagonistRole }); + _roles.MindTryRemoveRole(mindId); } public SiliconLawset GetLaws(EntityUid uid, SiliconLawBoundComponent? component = null) diff --git a/Content.Server/Silicons/Laws/StartIonStormedSystem.cs b/Content.Server/Silicons/Laws/StartIonStormedSystem.cs deleted file mode 100644 index ee2ce7b9edd8..000000000000 --- a/Content.Server/Silicons/Laws/StartIonStormedSystem.cs +++ /dev/null @@ -1,38 +0,0 @@ -using Content.Shared.Silicons.Laws.Components; -using Content.Shared.Administration.Logs; -using Content.Shared.Database; - -namespace Content.Server.Silicons.Laws; - -/// -/// This handles running the ion storm event a on specific entity when that entity is spawned in. -/// -public sealed class StartIonStormedSystem : EntitySystem -{ - [Dependency] private readonly IonStormSystem _ionStorm = default!; - [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; - [Dependency] private readonly SiliconLawSystem _siliconLaw = default!; - - public override void Initialize() - { - base.Initialize(); - SubscribeLocalEvent(OnMapInit); - } - - //private void OnMapInit(EntityUid uid, StartIonStormedComponent component, ref MapInitEvent args)' - private void OnMapInit(Entity ent, ref MapInitEvent args) - { - if (!TryComp(ent.Owner, out var lawBound)) - return; - if (!TryComp(ent.Owner, out var target)) - return; - - for (int currentIonStorm = 0; currentIonStorm < ent.Comp.IonStormAmount; currentIonStorm++) - { - _ionStorm.IonStormTarget((ent.Owner, lawBound, target), false); - } - - var laws = _siliconLaw.GetLaws(ent.Owner, lawBound); - _adminLogger.Add(LogType.Mind, LogImpact.High, $"{ToPrettyString(ent.Owner):silicon} spawned with ion stormed laws: {laws.LoggingString()}"); - } -} diff --git a/Content.Shared/Silicons/Laws/Components/EmagSiliconLawComponent.cs b/Content.Shared/Silicons/Laws/Components/EmagSiliconLawComponent.cs index 1b5338a7f758..5fe867ae29ad 100644 --- a/Content.Shared/Silicons/Laws/Components/EmagSiliconLawComponent.cs +++ b/Content.Shared/Silicons/Laws/Components/EmagSiliconLawComponent.cs @@ -29,13 +29,6 @@ public sealed partial class EmagSiliconLawComponent : Component [DataField, ViewVariables(VVAccess.ReadWrite)] public TimeSpan StunTime = TimeSpan.Zero; - /// - /// A role given to entities with this component when they are emagged. - /// Mostly just for admin purposes. - /// - [DataField] - public ProtoId? AntagonistRole = "SubvertedSilicon"; - /// /// The sound that plays for the borg player /// to let them know they've been emagged diff --git a/Content.Shared/Silicons/Laws/Components/SiliconLawProviderComponent.cs b/Content.Shared/Silicons/Laws/Components/SiliconLawProviderComponent.cs index 4885bd0265c4..d78e539aa962 100644 --- a/Content.Shared/Silicons/Laws/Components/SiliconLawProviderComponent.cs +++ b/Content.Shared/Silicons/Laws/Components/SiliconLawProviderComponent.cs @@ -29,4 +29,10 @@ public sealed partial class SiliconLawProviderComponent : Component [DataField] public SoundSpecifier? LawUploadSound = new SoundPathSpecifier("/Audio/Misc/cryo_warning.ogg"); + /// + /// Whether this silicon is subverted by an ion storm or emag. + /// + [DataField] + public bool Subverted = false; + } diff --git a/Content.Shared/Silicons/Laws/Components/StartIonStormedComponent.cs b/Content.Shared/Silicons/Laws/Components/StartIonStormedComponent.cs deleted file mode 100644 index 75d741216697..000000000000 --- a/Content.Shared/Silicons/Laws/Components/StartIonStormedComponent.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Content.Shared.Roles; -using Robust.Shared.Prototypes; - -namespace Content.Shared.Silicons.Laws.Components; - -/// -/// Applies law altering ion storms on a specific entity IonStormAmount times when the entity is spawned. -/// -[RegisterComponent] -public sealed partial class StartIonStormedComponent : Component -{ - /// - /// Amount of times that the ion storm will be run on the entity on spawn. - /// - [DataField] - public int IonStormAmount = 1; - - /// - /// A role given to entities with this component when a mind enters it. - /// Mostly just for admin purposes. - /// - [DataField] - public ProtoId? AntagonistRole = "SubvertedSilicon"; -} From ace158df0e5e335f8e7897ffe6f93f8ac8448865 Mon Sep 17 00:00:00 2001 From: ScarKy0 Date: Thu, 14 Nov 2024 17:53:15 +0100 Subject: [PATCH 094/290] Yippee! --- Content.Server/Silicons/Laws/SiliconLawSystem.cs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/Content.Server/Silicons/Laws/SiliconLawSystem.cs b/Content.Server/Silicons/Laws/SiliconLawSystem.cs index a4a7ee528f70..9b3e279b75e1 100644 --- a/Content.Server/Silicons/Laws/SiliconLawSystem.cs +++ b/Content.Server/Silicons/Laws/SiliconLawSystem.cs @@ -75,14 +75,14 @@ private void OnLawProviderMindAdded(EntityUid uid, SiliconLawProviderComponent c { if (!component.Subverted) return; - EnsureSubvertedSiliconRole(uid); + EnsureSubvertedSiliconRole(args.Mind); } private void OnLawProviderMindRemoved(EntityUid uid, SiliconLawProviderComponent component, MindRemovedMessage args) { if (!component.Subverted) return; - RemoveSubvertedSiliconRole(uid); + RemoveSubvertedSiliconRole(args.Mind); } @@ -179,21 +179,14 @@ protected override void OnGotEmagged(EntityUid uid, EmagSiliconLawComponent comp } - private void EnsureSubvertedSiliconRole(EntityUid uid) + private void EnsureSubvertedSiliconRole(EntityUid mindId) { - if (!_mind.TryGetMind(uid, out var mindId, out _)) - return; - if (!_roles.MindHasRole(mindId)) _roles.MindAddRole(mindId, "MindRoleSubvertedSilicon"); - } - private void RemoveSubvertedSiliconRole(EntityUid uid) + private void RemoveSubvertedSiliconRole(EntityUid mindId) { - if (!_mind.TryGetMind(uid, out var mindId, out _)) - return; - if (_roles.MindHasRole(mindId)) _roles.MindTryRemoveRole(mindId); } From 815e37e512ce7d1df152bac1642b769cf3e9bb32 Mon Sep 17 00:00:00 2001 From: CheddaCheez Date: Thu, 14 Nov 2024 10:56:21 -0600 Subject: [PATCH 095/290] Fix mime broken vow alert (#33303) Swap VowAlert and VowBrokenAlert on lines 149 and 150 so that the proper alerts are cleared and shown --- Content.Server/Abilities/Mime/MimePowersSystem.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Content.Server/Abilities/Mime/MimePowersSystem.cs b/Content.Server/Abilities/Mime/MimePowersSystem.cs index 20889f293c3b..bd8cf7c17661 100644 --- a/Content.Server/Abilities/Mime/MimePowersSystem.cs +++ b/Content.Server/Abilities/Mime/MimePowersSystem.cs @@ -146,8 +146,8 @@ public void RetakeVow(EntityUid uid, MimePowersComponent? mimePowers = null) mimePowers.ReadyToRepent = false; mimePowers.VowBroken = false; AddComp(uid); - _alertsSystem.ClearAlert(uid, mimePowers.VowAlert); - _alertsSystem.ShowAlert(uid, mimePowers.VowBrokenAlert); + _alertsSystem.ClearAlert(uid, mimePowers.VowBrokenAlert); + _alertsSystem.ShowAlert(uid, mimePowers.VowAlert); _actionsSystem.AddAction(uid, ref mimePowers.InvisibleWallActionEntity, mimePowers.InvisibleWallAction, uid); } } From 669bc148f91980f983b691d1e516b1b8d627a315 Mon Sep 17 00:00:00 2001 From: PJBot Date: Thu, 14 Nov 2024 16:57:29 +0000 Subject: [PATCH 096/290] Automatic changelog update --- Resources/Changelog/Changelog.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 9cc788c96f74..eb3f72680084 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: Blackern5000 - changes: - - message: Combat medical kits now contain saline syringes. - type: Add - id: 7108 - time: '2024-08-14T06:25:54.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/29954 - author: TheShuEd changes: - message: added morbilliard variants of procedural tacos and kebabs @@ -3941,3 +3934,10 @@ id: 7607 time: '2024-11-13T23:36:37.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33201 +- author: CheddaCheez + changes: + - message: Fixed mimes being unable to break their vow more than once. Despicable! + type: Fix + id: 7608 + time: '2024-11-14T16:56:22.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33303 From 1bebb3390ccedfdae173f0f681be6578146057ca Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Thu, 14 Nov 2024 18:08:35 +0100 Subject: [PATCH 097/290] Borg type switching. (#32586) * Borg type switching. This allows borgs (new spawn or constructed) to select their chassis type on creation, like in SS13. This removes the need for the many different chassis types, and means round-start borgs can actually play the game immediately instead of waiting for science to unlock everything. New borgs have an additional action that allows them to select their type. This opens a nice window with basic information about the borgs and a select button. Once a type has been selected it is permanent for that borg chassis. These borg types also immediately start the borg with specific modules, so they do not need to be printed. Additional modules can still be inserted for upgrades, though this is now less critical. The built-in modules cannot be removed, but are shown in the UI. The modules that each borg type starts with: * Generic: tools * Engineering: advanced tools, construction, RCD, cable * Salvage: Grappling gun, appraisal, mining * Janitor: cleaning, light replacer * Medical: treatment * Service: music, service, clowning Specialized borgs have 3 additional module slots available on top of the ones listed above, generic borgs have 5. Borg types are specified in a new BorgTypePrototype. These prototypes specify all information about the borg type. It is assigned to the borg entity through a mix of client side, server, and shared code. Some of the involved components were made networked, others are just ensured they're set on both sides of the wire. The most gnarly change is the inventory template prototype, which needs to change purely to modify the borg hat offset. I managed to bodge this in with an API that *probably* won't explode for specifically for this use case, but it's still not the most clean of API designs. Parts for specific borg chassis have been removed (so much deleted YAML) and specialized borg modules that are in the base set of a type have been removed from the exosuit fab as there's no point to printing those. The ability to "downgrade" a borg so it can select a new chassis, like in SS13, is something that would be nice, but was not high enough priority for me to block the feature on. I did keep it in mind with some of the code, so it may be possible in the future. There is no fancy animation when selecting borg types like in SS13, because I didn't think it was high priority, and it would add a lot of complex code. * Fix sandbox failure due to collection expression. * Module tweak Fix salvage borg modules still having research/lathe recipes Engie borg has regular tool module, not advanced. * Fix inventory system breakage * Fix migrations Some things were missing * Guidebook rewordings & review * MinWidth on confirm selection button --- .../Clothing/ClientClothingSystem.cs | 24 +- .../Inventory/ClientInventorySystem.cs | 16 +- Content.Client/Overlays/EquipmentHudSystem.cs | 3 +- .../Overlays/ShowHealthBarsSystem.cs | 7 + .../Overlays/ShowHealthIconsSystem.cs | 7 + .../Silicons/Borgs/BorgMenu.xaml.cs | 3 +- .../Silicons/Borgs/BorgModuleControl.xaml.cs | 3 +- .../Silicons/Borgs/BorgSelectTypeMenu.xaml | 43 ++ .../Silicons/Borgs/BorgSelectTypeMenu.xaml.cs | 81 +++ .../Borgs/BorgSelectTypeUserInterface.cs | 30 ++ .../Borgs/BorgSwitchableTypeSystem.cs | 81 +++ Content.Client/Silicons/Borgs/BorgSystem.cs | 14 + .../Borgs/BorgSwitchableTypeSystem.cs | 82 +++ .../Silicons/Borgs/BorgSystem.Modules.cs | 39 ++ .../Silicons/Borgs/BorgSystem.Transponder.cs | 17 + .../Silicons/Borgs/BorgSystem.Ui.cs | 3 + Content.Server/Silicons/Borgs/BorgSystem.cs | 15 +- .../Interaction/InteractionPopupSystem.cs | 22 + .../Inventory/InventoryComponent.cs | 10 +- .../Inventory/InventorySystem.Slots.cs | 49 ++ .../Overlays/ShowHealthBarsComponent.cs | 2 + .../Overlays/ShowHealthIconsComponent.cs | 2 + .../Silicons/Borgs/BorgTypePrototype.cs | 155 ++++++ .../Borgs/Components/BorgChassisComponent.cs | 15 +- .../Borgs/Components/BorgModuleComponent.cs | 8 + .../Components/BorgSwitchableTypeComponent.cs | 72 +++ .../Borgs/SharedBorgSwitchableTypeSystem.cs | 125 +++++ .../Silicons/Borgs/SharedBorgSystem.cs | 9 + Resources/Locale/en-US/borg/borg.ftl | 37 ++ Resources/Prototypes/Actions/borgs.yml | 12 + Resources/Prototypes/Body/Parts/silicon.yml | 47 +- .../Mobs/Cyborgs/base_borg_chassis.yml | 7 + .../Entities/Mobs/Cyborgs/borg_chassis.yml | 319 ++--------- .../Entities/Mobs/Player/silicon.yml | 21 +- .../Objects/Specific/Robotics/borg_parts.yml | 503 ------------------ .../Specific/Robotics/endoskeleton.yml | 169 +----- .../Entities/Structures/Machines/lathe.yml | 40 -- .../Prototypes/InventoryTemplates/borg.yml | 3 +- .../Construction/Graphs/machines/cyborg.yml | 173 +----- .../Prototypes/Recipes/Lathes/robotics.yml | 220 -------- .../Prototypes/Research/civilianservices.yml | 3 - Resources/Prototypes/Research/industrial.yml | 3 - .../Prototypes/Roles/Jobs/Science/borg.yml | 2 +- Resources/Prototypes/borg_types.yml | 218 ++++++++ Resources/Prototypes/tags.yml | 99 +--- .../ServerInfo/Guidebook/Science/Cyborgs.xml | 16 +- .../Actions/actions_borg.rsi/meta.json | 5 +- .../Actions/actions_borg.rsi/select-type.png | Bin 0 -> 408 bytes Resources/migration.yml | 35 ++ 49 files changed, 1336 insertions(+), 1533 deletions(-) create mode 100644 Content.Client/Silicons/Borgs/BorgSelectTypeMenu.xaml create mode 100644 Content.Client/Silicons/Borgs/BorgSelectTypeMenu.xaml.cs create mode 100644 Content.Client/Silicons/Borgs/BorgSelectTypeUserInterface.cs create mode 100644 Content.Client/Silicons/Borgs/BorgSwitchableTypeSystem.cs create mode 100644 Content.Server/Silicons/Borgs/BorgSwitchableTypeSystem.cs create mode 100644 Content.Shared/Silicons/Borgs/BorgTypePrototype.cs create mode 100644 Content.Shared/Silicons/Borgs/Components/BorgSwitchableTypeComponent.cs create mode 100644 Content.Shared/Silicons/Borgs/SharedBorgSwitchableTypeSystem.cs delete mode 100644 Resources/Prototypes/Entities/Objects/Specific/Robotics/borg_parts.yml create mode 100644 Resources/Prototypes/borg_types.yml create mode 100644 Resources/Textures/Interface/Actions/actions_borg.rsi/select-type.png diff --git a/Content.Client/Clothing/ClientClothingSystem.cs b/Content.Client/Clothing/ClientClothingSystem.cs index 3462fc923603..46f879e81560 100644 --- a/Content.Client/Clothing/ClientClothingSystem.cs +++ b/Content.Client/Clothing/ClientClothingSystem.cs @@ -58,6 +58,7 @@ public override void Initialize() base.Initialize(); SubscribeLocalEvent(OnGetVisuals); + SubscribeLocalEvent(OnInventoryTemplateUpdated); SubscribeLocalEvent(OnVisualsChanged); SubscribeLocalEvent(OnDidUnequip); @@ -70,11 +71,7 @@ private void OnAppearanceUpdate(EntityUid uid, InventoryComponent component, ref if (args.Sprite == null) return; - var enumerator = _inventorySystem.GetSlotEnumerator((uid, component)); - while (enumerator.NextItem(out var item, out var slot)) - { - RenderEquipment(uid, item, slot.Name, component); - } + UpdateAllSlots(uid, component); // No clothing equipped -> make sure the layer is hidden, though this should already be handled by on-unequip. if (args.Sprite.LayerMapTryGet(HumanoidVisualLayers.StencilMask, out var layer)) @@ -84,6 +81,23 @@ private void OnAppearanceUpdate(EntityUid uid, InventoryComponent component, ref } } + private void OnInventoryTemplateUpdated(Entity ent, ref InventoryTemplateUpdated args) + { + UpdateAllSlots(ent.Owner, clothing: ent.Comp); + } + + private void UpdateAllSlots( + EntityUid uid, + InventoryComponent? inventoryComponent = null, + ClothingComponent? clothing = null) + { + var enumerator = _inventorySystem.GetSlotEnumerator((uid, inventoryComponent)); + while (enumerator.NextItem(out var item, out var slot)) + { + RenderEquipment(uid, item, slot.Name, inventoryComponent, clothingComponent: clothing); + } + } + private void OnGetVisuals(EntityUid uid, ClothingComponent item, GetEquipmentVisualsEvent args) { if (!TryComp(args.Equipee, out InventoryComponent? inventory)) diff --git a/Content.Client/Inventory/ClientInventorySystem.cs b/Content.Client/Inventory/ClientInventorySystem.cs index 87cea4e3d2fc..dce401eefda5 100644 --- a/Content.Client/Inventory/ClientInventorySystem.cs +++ b/Content.Client/Inventory/ClientInventorySystem.cs @@ -235,9 +235,23 @@ public void UIInventoryAltActivateItem(string slot, EntityUid uid) EntityManager.RaisePredictiveEvent(new InteractInventorySlotEvent(GetNetEntity(item.Value), altInteract: true)); } + protected override void UpdateInventoryTemplate(Entity ent) + { + base.UpdateInventoryTemplate(ent); + + if (TryComp(ent, out InventorySlotsComponent? inventorySlots)) + { + foreach (var slot in ent.Comp.Slots) + { + if (inventorySlots.SlotData.TryGetValue(slot.Name, out var slotData)) + slotData.SlotDef = slot; + } + } + } + public sealed class SlotData { - public readonly SlotDefinition SlotDef; + public SlotDefinition SlotDef; public EntityUid? HeldEntity => Container?.ContainedEntity; public bool Blocked; public bool Highlighted; diff --git a/Content.Client/Overlays/EquipmentHudSystem.cs b/Content.Client/Overlays/EquipmentHudSystem.cs index c7578b6793f5..502a1f36274b 100644 --- a/Content.Client/Overlays/EquipmentHudSystem.cs +++ b/Content.Client/Overlays/EquipmentHudSystem.cs @@ -14,6 +14,7 @@ public abstract class EquipmentHudSystem : EntitySystem where T : IComponent { [Dependency] private readonly IPlayerManager _player = default!; + [ViewVariables] protected bool IsActive; protected virtual SlotFlags TargetSlots => ~SlotFlags.POCKET; @@ -102,7 +103,7 @@ protected virtual void OnRefreshComponentHud(EntityUid uid, T component, Refresh args.Components.Add(component); } - private void RefreshOverlay(EntityUid uid) + protected void RefreshOverlay(EntityUid uid) { if (uid != _player.LocalSession?.AttachedEntity) return; diff --git a/Content.Client/Overlays/ShowHealthBarsSystem.cs b/Content.Client/Overlays/ShowHealthBarsSystem.cs index 1eb712a8988f..b23209ff202b 100644 --- a/Content.Client/Overlays/ShowHealthBarsSystem.cs +++ b/Content.Client/Overlays/ShowHealthBarsSystem.cs @@ -21,9 +21,16 @@ public override void Initialize() { base.Initialize(); + SubscribeLocalEvent(OnHandleState); + _overlay = new(EntityManager, _prototype); } + private void OnHandleState(Entity ent, ref AfterAutoHandleStateEvent args) + { + RefreshOverlay(ent); + } + protected override void UpdateInternal(RefreshEquipmentHudEvent component) { base.UpdateInternal(component); diff --git a/Content.Client/Overlays/ShowHealthIconsSystem.cs b/Content.Client/Overlays/ShowHealthIconsSystem.cs index 8c22c78f17cd..b4d845e4217a 100644 --- a/Content.Client/Overlays/ShowHealthIconsSystem.cs +++ b/Content.Client/Overlays/ShowHealthIconsSystem.cs @@ -17,6 +17,7 @@ public sealed class ShowHealthIconsSystem : EquipmentHudSystem DamageContainers = new(); public override void Initialize() @@ -24,6 +25,7 @@ public override void Initialize() base.Initialize(); SubscribeLocalEvent(OnGetStatusIconsEvent); + SubscribeLocalEvent(OnHandleState); } protected override void UpdateInternal(RefreshEquipmentHudEvent component) @@ -43,6 +45,11 @@ protected override void DeactivateInternal() DamageContainers.Clear(); } + private void OnHandleState(Entity ent, ref AfterAutoHandleStateEvent args) + { + RefreshOverlay(ent); + } + private void OnGetStatusIconsEvent(Entity entity, ref GetStatusIconsEvent args) { if (!IsActive) diff --git a/Content.Client/Silicons/Borgs/BorgMenu.xaml.cs b/Content.Client/Silicons/Borgs/BorgMenu.xaml.cs index f6a861aa057b..b8f0e69c022f 100644 --- a/Content.Client/Silicons/Borgs/BorgMenu.xaml.cs +++ b/Content.Client/Silicons/Borgs/BorgMenu.xaml.cs @@ -131,7 +131,8 @@ private void UpdateModulePanel() _modules.Clear(); foreach (var module in chassis.ModuleContainer.ContainedEntities) { - var control = new BorgModuleControl(module, _entity); + var moduleComponent = _entity.GetComponent(module); + var control = new BorgModuleControl(module, _entity, !moduleComponent.DefaultModule); control.RemoveButtonPressed += () => { RemoveModuleButtonPressed?.Invoke(module); diff --git a/Content.Client/Silicons/Borgs/BorgModuleControl.xaml.cs b/Content.Client/Silicons/Borgs/BorgModuleControl.xaml.cs index d5cf05ba63ed..245425524ca0 100644 --- a/Content.Client/Silicons/Borgs/BorgModuleControl.xaml.cs +++ b/Content.Client/Silicons/Borgs/BorgModuleControl.xaml.cs @@ -9,7 +9,7 @@ public sealed partial class BorgModuleControl : PanelContainer { public Action? RemoveButtonPressed; - public BorgModuleControl(EntityUid entity, IEntityManager entityManager) + public BorgModuleControl(EntityUid entity, IEntityManager entityManager, bool canRemove) { RobustXamlLoader.Load(this); @@ -20,6 +20,7 @@ public BorgModuleControl(EntityUid entity, IEntityManager entityManager) { RemoveButtonPressed?.Invoke(); }; + RemoveButton.Visible = canRemove; } } diff --git a/Content.Client/Silicons/Borgs/BorgSelectTypeMenu.xaml b/Content.Client/Silicons/Borgs/BorgSelectTypeMenu.xaml new file mode 100644 index 000000000000..f51c2f53fd0d --- /dev/null +++ b/Content.Client/Silicons/Borgs/BorgSelectTypeMenu.xaml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + diff --git a/Content.Client/Silicons/Borgs/BorgSelectTypeMenu.xaml.cs b/Content.Client/Silicons/Borgs/BorgSelectTypeMenu.xaml.cs new file mode 100644 index 000000000000..e1fbd376b54e --- /dev/null +++ b/Content.Client/Silicons/Borgs/BorgSelectTypeMenu.xaml.cs @@ -0,0 +1,81 @@ +using System.Linq; +using Content.Client.UserInterface.Controls; +using Content.Client.UserInterface.Systems.Guidebook; +using Content.Shared.Guidebook; +using Content.Shared.Silicons.Borgs; +using Content.Shared.Silicons.Borgs.Components; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.Prototypes; + +namespace Content.Client.Silicons.Borgs; + +/// +/// Menu used by borgs to select their type. +/// +/// +/// +[GenerateTypedNameReferences] +public sealed partial class BorgSelectTypeMenu : FancyWindow +{ + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + + private BorgTypePrototype? _selectedBorgType; + + public event Action>? ConfirmedBorgType; + + [ValidatePrototypeId] + private static readonly List> GuidebookEntries = new() { "Cyborgs", "Robotics" }; + + public BorgSelectTypeMenu() + { + RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + + var group = new ButtonGroup(); + foreach (var borgType in _prototypeManager.EnumeratePrototypes().OrderBy(PrototypeName)) + { + var button = new Button + { + Text = PrototypeName(borgType), + Group = group, + }; + button.OnPressed += _ => + { + _selectedBorgType = borgType; + UpdateInformation(borgType); + }; + SelectionsContainer.AddChild(button); + } + + ConfirmTypeButton.OnPressed += ConfirmButtonPressed; + HelpGuidebookIds = GuidebookEntries; + } + + private void UpdateInformation(BorgTypePrototype prototype) + { + _selectedBorgType = prototype; + + InfoContents.Visible = true; + InfoPlaceholder.Visible = false; + ConfirmTypeButton.Disabled = false; + + NameLabel.Text = PrototypeName(prototype); + DescriptionLabel.Text = Loc.GetString($"borg-type-{prototype.ID}-desc"); + ChassisView.SetPrototype(prototype.DummyPrototype); + } + + private void ConfirmButtonPressed(BaseButton.ButtonEventArgs obj) + { + if (_selectedBorgType == null) + return; + + ConfirmedBorgType?.Invoke(_selectedBorgType); + } + + private static string PrototypeName(BorgTypePrototype prototype) + { + return Loc.GetString($"borg-type-{prototype.ID}-name"); + } +} diff --git a/Content.Client/Silicons/Borgs/BorgSelectTypeUserInterface.cs b/Content.Client/Silicons/Borgs/BorgSelectTypeUserInterface.cs new file mode 100644 index 000000000000..8c76fade8c95 --- /dev/null +++ b/Content.Client/Silicons/Borgs/BorgSelectTypeUserInterface.cs @@ -0,0 +1,30 @@ +using Content.Shared.Silicons.Borgs.Components; +using JetBrains.Annotations; +using Robust.Client.UserInterface; + +namespace Content.Client.Silicons.Borgs; + +/// +/// User interface used by borgs to select their type. +/// +/// +/// +/// +[UsedImplicitly] +public sealed class BorgSelectTypeUserInterface : BoundUserInterface +{ + [ViewVariables] + private BorgSelectTypeMenu? _menu; + + public BorgSelectTypeUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey) + { + } + + protected override void Open() + { + base.Open(); + + _menu = this.CreateWindow(); + _menu.ConfirmedBorgType += prototype => SendMessage(new BorgSelectTypeMessage(prototype)); + } +} diff --git a/Content.Client/Silicons/Borgs/BorgSwitchableTypeSystem.cs b/Content.Client/Silicons/Borgs/BorgSwitchableTypeSystem.cs new file mode 100644 index 000000000000..346dc5c276ee --- /dev/null +++ b/Content.Client/Silicons/Borgs/BorgSwitchableTypeSystem.cs @@ -0,0 +1,81 @@ +using Content.Shared.Movement.Components; +using Content.Shared.Silicons.Borgs; +using Content.Shared.Silicons.Borgs.Components; +using Robust.Client.GameObjects; + +namespace Content.Client.Silicons.Borgs; + +/// +/// Client side logic for borg type switching. Sets up primarily client-side visual information. +/// +/// +/// +public sealed class BorgSwitchableTypeSystem : SharedBorgSwitchableTypeSystem +{ + [Dependency] private readonly BorgSystem _borgSystem = default!; + [Dependency] private readonly AppearanceSystem _appearance = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(AfterStateHandler); + SubscribeLocalEvent(OnComponentStartup); + } + + private void OnComponentStartup(Entity ent, ref ComponentStartup args) + { + UpdateEntityAppearance(ent); + } + + private void AfterStateHandler(Entity ent, ref AfterAutoHandleStateEvent args) + { + UpdateEntityAppearance(ent); + } + + protected override void UpdateEntityAppearance( + Entity entity, + BorgTypePrototype prototype) + { + if (TryComp(entity, out SpriteComponent? sprite)) + { + sprite.LayerSetState(BorgVisualLayers.Body, prototype.SpriteBodyState); + sprite.LayerSetState(BorgVisualLayers.LightStatus, prototype.SpriteToggleLightState); + } + + if (TryComp(entity, out BorgChassisComponent? chassis)) + { + _borgSystem.SetMindStates( + (entity.Owner, chassis), + prototype.SpriteHasMindState, + prototype.SpriteNoMindState); + + if (TryComp(entity, out AppearanceComponent? appearance)) + { + // Queue update so state changes apply. + _appearance.QueueUpdate(entity, appearance); + } + } + + if (prototype.SpriteBodyMovementState is { } movementState) + { + var spriteMovement = EnsureComp(entity); + spriteMovement.NoMovementLayers.Clear(); + spriteMovement.NoMovementLayers["movement"] = new PrototypeLayerData + { + State = prototype.SpriteBodyState, + }; + spriteMovement.MovementLayers.Clear(); + spriteMovement.MovementLayers["movement"] = new PrototypeLayerData + { + State = movementState, + }; + } + else + { + RemComp(entity); + } + + base.UpdateEntityAppearance(entity, prototype); + } +} diff --git a/Content.Client/Silicons/Borgs/BorgSystem.cs b/Content.Client/Silicons/Borgs/BorgSystem.cs index e92ce5cc7774..387a56384e9a 100644 --- a/Content.Client/Silicons/Borgs/BorgSystem.cs +++ b/Content.Client/Silicons/Borgs/BorgSystem.cs @@ -92,4 +92,18 @@ private void OnMMIAppearanceChanged(EntityUid uid, MMIComponent component, ref A sprite.LayerSetState(MMIVisualLayers.Base, state); } } + + /// + /// Sets the sprite states used for the borg "is there a mind or not" indication. + /// + /// The entity and component to modify. + /// The state to use if the borg has a mind. + /// The state to use if the borg has no mind. + /// + /// + public void SetMindStates(Entity borg, string hasMindState, string noMindState) + { + borg.Comp.HasMindState = hasMindState; + borg.Comp.NoMindState = noMindState; + } } diff --git a/Content.Server/Silicons/Borgs/BorgSwitchableTypeSystem.cs b/Content.Server/Silicons/Borgs/BorgSwitchableTypeSystem.cs new file mode 100644 index 000000000000..d1a32a6a5ba0 --- /dev/null +++ b/Content.Server/Silicons/Borgs/BorgSwitchableTypeSystem.cs @@ -0,0 +1,82 @@ +using Content.Server.Inventory; +using Content.Server.Radio.Components; +using Content.Shared.Inventory; +using Content.Shared.Silicons.Borgs; +using Content.Shared.Silicons.Borgs.Components; +using Robust.Shared.Prototypes; +using Robust.Shared.Utility; + +namespace Content.Server.Silicons.Borgs; + +/// +/// Server-side logic for borg type switching. Handles more heavyweight and server-specific switching logic. +/// +public sealed class BorgSwitchableTypeSystem : SharedBorgSwitchableTypeSystem +{ + [Dependency] private readonly BorgSystem _borgSystem = default!; + [Dependency] private readonly ServerInventorySystem _inventorySystem = default!; + + protected override void SelectBorgModule(Entity ent, ProtoId borgType) + { + var prototype = Prototypes.Index(borgType); + + // Assign radio channels + string[] radioChannels = [.. ent.Comp.InherentRadioChannels, .. prototype.RadioChannels]; + if (TryComp(ent, out IntrinsicRadioTransmitterComponent? transmitter)) + transmitter.Channels = [.. radioChannels]; + + if (TryComp(ent, out ActiveRadioComponent? activeRadio)) + activeRadio.Channels = [.. radioChannels]; + + // Borg transponder for the robotics console + if (TryComp(ent, out BorgTransponderComponent? transponder)) + { + _borgSystem.SetTransponderSprite( + (ent.Owner, transponder), + new SpriteSpecifier.Rsi(new ResPath("Mobs/Silicon/chassis.rsi"), prototype.SpriteBodyState)); + + _borgSystem.SetTransponderName( + (ent.Owner, transponder), + Loc.GetString($"borg-type-{borgType}-transponder")); + } + + // Configure modules + if (TryComp(ent, out BorgChassisComponent? chassis)) + { + var chassisEnt = (ent.Owner, chassis); + _borgSystem.SetMaxModules( + chassisEnt, + prototype.ExtraModuleCount + prototype.DefaultModules.Length); + + _borgSystem.SetModuleWhitelist(chassisEnt, prototype.ModuleWhitelist); + + foreach (var module in prototype.DefaultModules) + { + var moduleEntity = Spawn(module); + var borgModule = Comp(moduleEntity); + _borgSystem.SetBorgModuleDefault((moduleEntity, borgModule), true); + _borgSystem.InsertModule(chassisEnt, moduleEntity); + } + } + + // Configure special components + if (Prototypes.TryIndex(ent.Comp.SelectedBorgType, out var previousPrototype)) + { + if (previousPrototype.AddComponents is { } removeComponents) + EntityManager.RemoveComponents(ent, removeComponents); + } + + if (prototype.AddComponents is { } addComponents) + { + EntityManager.AddComponents(ent, addComponents); + } + + // Configure inventory template (used for hat spacing) + if (TryComp(ent, out InventoryComponent? inventory)) + { + _inventorySystem.SetTemplateId((ent.Owner, inventory), prototype.InventoryTemplateId); + } + + base.SelectBorgModule(ent, borgType); + } +} diff --git a/Content.Server/Silicons/Borgs/BorgSystem.Modules.cs b/Content.Server/Silicons/Borgs/BorgSystem.Modules.cs index d5a429db0309..f95a5807360c 100644 --- a/Content.Server/Silicons/Borgs/BorgSystem.Modules.cs +++ b/Content.Server/Silicons/Borgs/BorgSystem.Modules.cs @@ -2,6 +2,7 @@ using Content.Shared.Hands.Components; using Content.Shared.Interaction.Components; using Content.Shared.Silicons.Borgs.Components; +using Content.Shared.Whitelist; using Robust.Shared.Containers; namespace Content.Server.Silicons.Borgs; @@ -300,6 +301,24 @@ public bool CanInsertModule(EntityUid uid, EntityUid module, BorgChassisComponen return true; } + /// + /// Check if a module can be removed from a borg. + /// + /// The borg that the module is being removed from. + /// The module to remove from the borg. + /// The user attempting to remove the module. + /// True if the module can be removed. + public bool CanRemoveModule( + Entity borg, + Entity module, + EntityUid? user = null) + { + if (module.Comp.DefaultModule) + return false; + + return true; + } + /// /// Installs and activates all modules currently inside the borg's module container /// @@ -369,4 +388,24 @@ public void UninstallModule(EntityUid uid, EntityUid module, BorgChassisComponen var ev = new BorgModuleUninstalledEvent(uid); RaiseLocalEvent(module, ref ev); } + + /// + /// Sets . + /// + /// The borg to modify. + /// The new max module count. + public void SetMaxModules(Entity ent, int maxModules) + { + ent.Comp.MaxModules = maxModules; + } + + /// + /// Sets . + /// + /// The borg to modify. + /// The new module whitelist. + public void SetModuleWhitelist(Entity ent, EntityWhitelist? whitelist) + { + ent.Comp.ModuleWhitelist = whitelist; + } } diff --git a/Content.Server/Silicons/Borgs/BorgSystem.Transponder.cs b/Content.Server/Silicons/Borgs/BorgSystem.Transponder.cs index 781f847be35e..b4ba14004415 100644 --- a/Content.Server/Silicons/Borgs/BorgSystem.Transponder.cs +++ b/Content.Server/Silicons/Borgs/BorgSystem.Transponder.cs @@ -8,6 +8,7 @@ using Content.Server.DeviceNetwork.Components; using Content.Server.DeviceNetwork.Systems; using Content.Server.Explosion.Components; +using Robust.Shared.Utility; namespace Content.Server.Silicons.Borgs; @@ -134,4 +135,20 @@ private bool CheckEmagged(EntityUid uid, string name) return false; } + + /// + /// Sets . + /// + public void SetTransponderSprite(Entity ent, SpriteSpecifier sprite) + { + ent.Comp.Sprite = sprite; + } + + /// + /// Sets . + /// + public void SetTransponderName(Entity ent, string name) + { + ent.Comp.Name = name; + } } diff --git a/Content.Server/Silicons/Borgs/BorgSystem.Ui.cs b/Content.Server/Silicons/Borgs/BorgSystem.Ui.cs index d0e9f80e3645..40c2c3bf3324 100644 --- a/Content.Server/Silicons/Borgs/BorgSystem.Ui.cs +++ b/Content.Server/Silicons/Borgs/BorgSystem.Ui.cs @@ -82,6 +82,9 @@ private void OnRemoveModuleBuiMessage(EntityUid uid, BorgChassisComponent compon if (!component.ModuleContainer.Contains(module)) return; + if (!CanRemoveModule((uid, component), (module, Comp(module)), args.Actor)) + return; + _adminLog.Add(LogType.Action, LogImpact.Medium, $"{ToPrettyString(args.Actor):player} removed module {ToPrettyString(module)} from borg {ToPrettyString(uid)}"); _container.Remove(module, component.ModuleContainer); diff --git a/Content.Server/Silicons/Borgs/BorgSystem.cs b/Content.Server/Silicons/Borgs/BorgSystem.cs index bd85282a0f5e..ff204bfa8ceb 100644 --- a/Content.Server/Silicons/Borgs/BorgSystem.cs +++ b/Content.Server/Silicons/Borgs/BorgSystem.cs @@ -129,7 +129,7 @@ private void OnChassisInteractUsing(EntityUid uid, BorgChassisComponent componen if (module != null && CanInsertModule(uid, used, component, module, args.User)) { - _container.Insert(used, component.ModuleContainer); + InsertModule((uid, component), used); _adminLog.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.User):player} installed module {ToPrettyString(used)} into borg {ToPrettyString(uid)}"); args.Handled = true; @@ -137,6 +137,19 @@ private void OnChassisInteractUsing(EntityUid uid, BorgChassisComponent componen } } + /// + /// Inserts a new module into a borg, the same as if a player inserted it manually. + /// + /// + /// This does not run checks to see if the borg is actually allowed to be inserted, such as whitelists. + /// + /// The borg to insert into. + /// The module to insert. + public void InsertModule(Entity ent, EntityUid module) + { + _container.Insert(module, ent.Comp.ModuleContainer); + } + // todo: consider transferring over the ghost role? managing that might suck. protected override void OnInserted(EntityUid uid, BorgChassisComponent component, EntInsertedIntoContainerMessage args) { diff --git a/Content.Shared/Interaction/InteractionPopupSystem.cs b/Content.Shared/Interaction/InteractionPopupSystem.cs index 20c079dfd8c8..8df0035fc982 100644 --- a/Content.Shared/Interaction/InteractionPopupSystem.cs +++ b/Content.Shared/Interaction/InteractionPopupSystem.cs @@ -159,4 +159,26 @@ private void SharedInteract( _audio.PlayEntity(sfx, Filter.Empty().FromEntities(target), target, false); } } + + /// + /// Sets . + /// + /// + /// This field is not networked automatically, so this method must be called on both sides of the network. + /// + public void SetInteractSuccessString(Entity ent, string str) + { + ent.Comp.InteractSuccessString = str; + } + + /// + /// Sets . + /// + /// + /// This field is not networked automatically, so this method must be called on both sides of the network. + /// + public void SetInteractFailureString(Entity ent, string str) + { + ent.Comp.InteractFailureString = str; + } } diff --git a/Content.Shared/Inventory/InventoryComponent.cs b/Content.Shared/Inventory/InventoryComponent.cs index 629cf1169c45..61e0114ff24b 100644 --- a/Content.Shared/Inventory/InventoryComponent.cs +++ b/Content.Shared/Inventory/InventoryComponent.cs @@ -7,10 +7,12 @@ namespace Content.Shared.Inventory; [RegisterComponent, NetworkedComponent] [Access(typeof(InventorySystem))] +[AutoGenerateComponentState(true)] public sealed partial class InventoryComponent : Component { [DataField("templateId", customTypeSerializer: typeof(PrototypeIdSerializer))] - public string TemplateId { get; private set; } = "human"; + [AutoNetworkedField] + public string TemplateId { get; set; } = "human"; [DataField("speciesId")] public string? SpeciesId { get; set; } @@ -32,3 +34,9 @@ public sealed partial class InventoryComponent : Component [DataField] public Dictionary MaleDisplacements = new(); } + +/// +/// Raised if the of an inventory changed. +/// +[ByRefEvent] +public struct InventoryTemplateUpdated; diff --git a/Content.Shared/Inventory/InventorySystem.Slots.cs b/Content.Shared/Inventory/InventorySystem.Slots.cs index 2522dd5d0a33..04d58c1cd52d 100644 --- a/Content.Shared/Inventory/InventorySystem.Slots.cs +++ b/Content.Shared/Inventory/InventorySystem.Slots.cs @@ -1,4 +1,5 @@ using System.Diagnostics.CodeAnalysis; +using System.Linq; using Content.Shared.Inventory.Events; using Content.Shared.Storage; using Robust.Shared.Containers; @@ -19,6 +20,8 @@ private void InitializeSlots() _vvm.GetTypeHandler() .AddHandler(HandleViewVariablesSlots, ListViewVariablesSlots); + + SubscribeLocalEvent(AfterAutoState); } private void ShutdownSlots() @@ -68,6 +71,27 @@ protected virtual void OnInit(EntityUid uid, InventoryComponent component, Compo } } + private void AfterAutoState(Entity ent, ref AfterAutoHandleStateEvent args) + { + UpdateInventoryTemplate(ent); + } + + protected virtual void UpdateInventoryTemplate(Entity ent) + { + if (ent.Comp.LifeStage < ComponentLifeStage.Initialized) + return; + + if (!_prototypeManager.TryIndex(ent.Comp.TemplateId, out InventoryTemplatePrototype? invTemplate)) + return; + + DebugTools.Assert(ent.Comp.Slots.Length == invTemplate.Slots.Length); + + ent.Comp.Slots = invTemplate.Slots; + + var ev = new InventoryTemplateUpdated(); + RaiseLocalEvent(ent, ref ev); + } + private void OnOpenSlotStorage(OpenSlotStorageNetworkMessage ev, EntitySessionEventArgs args) { if (args.SenderSession.AttachedEntity is not { Valid: true } uid) @@ -170,6 +194,31 @@ private IEnumerable ListViewVariablesSlots(EntityUid uid, InventoryCompo } } + /// + /// Change the inventory template ID an entity is using. The new template must be compatible. + /// + /// + /// + /// For an inventory template to be compatible with another, it must have exactly the same slot names. + /// All other changes are rejected. + /// + /// + /// The entity to update. + /// The ID of the new inventory template prototype. + /// + /// Thrown if the new template is not compatible with the existing one. + /// + public void SetTemplateId(Entity ent, ProtoId newTemplate) + { + var newPrototype = _prototypeManager.Index(newTemplate); + + if (!newPrototype.Slots.Select(x => x.Name).SequenceEqual(ent.Comp.Slots.Select(x => x.Name))) + throw new ArgumentException("Incompatible inventory template!"); + + ent.Comp.TemplateId = newTemplate; + Dirty(ent); + } + /// /// Enumerator for iterating over an inventory's slot containers. Also has methods that skip empty containers. /// It should be safe to add or remove items while enumerating. diff --git a/Content.Shared/Overlays/ShowHealthBarsComponent.cs b/Content.Shared/Overlays/ShowHealthBarsComponent.cs index cb4f0fe7dd49..3f27885db18c 100644 --- a/Content.Shared/Overlays/ShowHealthBarsComponent.cs +++ b/Content.Shared/Overlays/ShowHealthBarsComponent.cs @@ -9,12 +9,14 @@ namespace Content.Shared.Overlays; /// This component allows you to see health bars above damageable mobs. /// [RegisterComponent, NetworkedComponent] +[AutoGenerateComponentState(true)] public sealed partial class ShowHealthBarsComponent : Component { /// /// Displays health bars of the damage containers. /// [DataField] + [AutoNetworkedField] public List> DamageContainers = new() { "Biological" diff --git a/Content.Shared/Overlays/ShowHealthIconsComponent.cs b/Content.Shared/Overlays/ShowHealthIconsComponent.cs index aa12c9887a8e..bc8b5419d2a1 100644 --- a/Content.Shared/Overlays/ShowHealthIconsComponent.cs +++ b/Content.Shared/Overlays/ShowHealthIconsComponent.cs @@ -8,12 +8,14 @@ namespace Content.Shared.Overlays; /// This component allows you to see health status icons above damageable mobs. /// [RegisterComponent, NetworkedComponent] +[AutoGenerateComponentState(true)] public sealed partial class ShowHealthIconsComponent : Component { /// /// Displays health status icons of the damage containers. /// [DataField] + [AutoNetworkedField] public List> DamageContainers = new() { "Biological" diff --git a/Content.Shared/Silicons/Borgs/BorgTypePrototype.cs b/Content.Shared/Silicons/Borgs/BorgTypePrototype.cs new file mode 100644 index 000000000000..6154c1275774 --- /dev/null +++ b/Content.Shared/Silicons/Borgs/BorgTypePrototype.cs @@ -0,0 +1,155 @@ +using Content.Shared.Interaction.Components; +using Content.Shared.Inventory; +using Content.Shared.Radio; +using Content.Shared.Silicons.Borgs.Components; +using Content.Shared.Whitelist; +using Robust.Shared.Audio; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Silicons.Borgs; + +/// +/// Information for a borg type that can be selected by . +/// +/// +[Prototype] +public sealed partial class BorgTypePrototype : IPrototype +{ + [ValidatePrototypeId] + private static readonly ProtoId DefaultFootsteps = new("FootstepBorg"); + + [IdDataField] + public required string ID { get; init; } + + // + // Description info (name/desc) is configured via localization strings directly. + // + + /// + /// The prototype displayed in the selection menu for this type. + /// + [DataField] + public required EntProtoId DummyPrototype { get; init; } + + // + // Functional information + // + + /// + /// The amount of free module slots this borg type has. + /// + /// + /// This count is on top of the modules specified in . + /// + /// + [DataField] + public int ExtraModuleCount { get; set; } = 0; + + /// + /// The whitelist for borg modules that can be inserted into this borg type. + /// + /// + [DataField] + public EntityWhitelist? ModuleWhitelist { get; set; } + + /// + /// Inventory template used by this borg. + /// + /// + /// This template must be compatible with the normal borg templates, + /// so in practice it can only be used to differentiate the visual position of the slots on the character sprites. + /// + /// + [DataField] + public ProtoId InventoryTemplateId { get; set; } = "borgShort"; + + /// + /// Radio channels that this borg will gain access to from this module. + /// + /// + /// These channels are provided on top of the ones specified in + /// . + /// + [DataField] + public ProtoId[] RadioChannels = []; + + /// + /// Borg module types that are always available to borgs of this type. + /// + /// + /// These modules still work like modules, although they cannot be removed from the borg. + /// + /// + [DataField] + public EntProtoId[] DefaultModules = []; + + /// + /// Additional components to add to the borg entity when this type is selected. + /// + [DataField] + public ComponentRegistry? AddComponents { get; set; } + + // + // Visual information + // + + /// + /// The sprite state for the main borg body. + /// + [DataField] + public string SpriteBodyState { get; set; } = "robot"; + + /// + /// An optional movement sprite state for the main borg body. + /// + [DataField] + public string? SpriteBodyMovementState { get; set; } + + /// + /// Sprite state used to indicate that the borg has a mind in it. + /// + /// + [DataField] + public string SpriteHasMindState { get; set; } = "robot_e"; + + /// + /// Sprite state used to indicate that the borg has no mind in it. + /// + /// + [DataField] + public string SpriteNoMindState { get; set; } = "robot_e_r"; + + /// + /// Sprite state used when the borg's flashlight is on. + /// + [DataField] + public string SpriteToggleLightState { get; set; } = "robot_l"; + + // + // Minor information + // + + /// + /// String to use on petting success. + /// + /// + [DataField] + public string PetSuccessString { get; set; } = "petting-success-generic-cyborg"; + + /// + /// String to use on petting failure. + /// + /// + [DataField] + public string PetFailureString { get; set; } = "petting-failure-generic-cyborg"; + + // + // Sounds + // + + /// + /// Sound specifier for footstep sounds created by this borg. + /// + [DataField] + public SoundSpecifier FootstepCollection { get; set; } = new SoundCollectionSpecifier(DefaultFootsteps); +} diff --git a/Content.Shared/Silicons/Borgs/Components/BorgChassisComponent.cs b/Content.Shared/Silicons/Borgs/Components/BorgChassisComponent.cs index de0fe0bce381..c2bf2b2801b1 100644 --- a/Content.Shared/Silicons/Borgs/Components/BorgChassisComponent.cs +++ b/Content.Shared/Silicons/Borgs/Components/BorgChassisComponent.cs @@ -89,5 +89,18 @@ public enum BorgVisuals : byte [Serializable, NetSerializable] public enum BorgVisualLayers : byte { - Light + /// + /// Main borg body layer. + /// + Body, + + /// + /// Layer for the borg's mind state. + /// + Light, + + /// + /// Layer for the borg flashlight status. + /// + LightStatus, } diff --git a/Content.Shared/Silicons/Borgs/Components/BorgModuleComponent.cs b/Content.Shared/Silicons/Borgs/Components/BorgModuleComponent.cs index a7523c1ce702..e542a1e3e3e8 100644 --- a/Content.Shared/Silicons/Borgs/Components/BorgModuleComponent.cs +++ b/Content.Shared/Silicons/Borgs/Components/BorgModuleComponent.cs @@ -7,6 +7,7 @@ namespace Content.Shared.Silicons.Borgs.Components; /// to give them unique abilities and attributes. ///

      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 delta 984 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 WGcEpDY{*kkaqsEs=d#Wzp$PyB;x1tT delta 986 zcmV<0110>N5by_(B!7cxLqkwWLqi}?a&Km7Y-IodD9@FVODIH99L9exB8@D}LbAAv zp%f(~OAV1Sr7_BD;oduDM$NsZdq*~w%2ru;Y`hjW)@&_ol~Nuh8(S-4BVGSg4zrf+)%1YvLig$&>R>nvQp9y!lazWt-rJDtQRh$l3Q<-5m z5g!%~3+w4JHp|$`xVCV=a3pCvlCRAaIH`DDv7KGDiuY763@tg+Q%aZF#u($om_)~9 zm1VNz>6Xm2~SmGFA1sfyqqyFG`w_d8Rw~!QyLhZBfzqdo( zHhgdS{@0Q3e;-5j6I?na|H>f@eu%zR(jo`Yv;pT=CC%J{i%n>G%o(l`NYyg6R0`fs z<(p=q`34&13%wQhIk|^~bTx4ed;8Flmh6QJ@2)TJ?SIcRL4QPl0ATWRp!eh8R{#J2 z32;bRa{vGqBme*wBmtWh#uNYm0uxC@K~#8N?VCMI13?gmH#T+>?^5%seo>n-7-o zlHJVAZhvB(PDfy3+cTYo#GJ4#OIY@_u)69}t=@_3e)06On4gqS4B?|$&%-bf6QE>a z13<~b27rc!R;wk$6rnPpR(tA&DMDjFz40bB9-oq73f==i(McuerMBDOGE5PwZ$LV| z+zV5LZV9-luu6wbz};3WV`7B&EsEXE8lUFZA7m;o5Iz8{Pk;H~pj?H>ks4*>mlymh{+{lkDU z12AfRKNvH>be-=P-UC3%!UlknMY|v1p6|mj5ZL_yZ39+U*0d&gc)X9c0hx`>p%bW- zcYjpkQ@y>3wgK7g?7#{7i=JT#Q01x;?UtBIaJ-@DKj<9wUM%=mKz9i&CYQ7(cxgOG zdk;9exITelAdYvp4q=FbwgKbL1;(L!&rcUlg+a-}27r=<4FDwzc>}cb09~;22wno9 zWMKn9$-)MJl7+kh=y?EkLj~Oc?3Nn30aLlX+@BBNUZ!%}>Z+scUaWB2>Vvw-<@2(Z z0lW!b<8>i^0jfjoL3nBt@c;k-07*qo IM6N<$g4q$xyZ`_I diff --git a/Resources/Textures/Structures/Windows/plastitanium_window.rsi/ptwindow5.png b/Resources/Textures/Structures/Windows/plastitanium_window.rsi/ptwindow5.png index a4a28e41bf91b9def90665c6bf27947b3f5f70e4..08d493bb62a3540b6fde8691a47f63eac0e80b3e 100644 GIT binary patch literal 2114 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEU|gH&>>S|f?5q$_l%JNFlghxL zF|l@{p@(#$$npAPT}h(svPLC49AizC44WsL6bdLh^>A%1{ZMpL)v4%bRj0_ojSs?@ zv@YqbEqigx)4FUzUZc~(Z3^f3{B++29r{{Z?zL!D*0ah@(xdkL6w?#EzV@`;SNU&G<}78MtN*b> zGHs@Et7BW~HH{!urR~aIty^mR?>y}P`7iU7hFQVU$;%b;ns;b;X+3R8Upnci#NtDN z$5fN5%+1s9T{-nW;S>Ls>$9TL`1`gg{Mo#ccVFwi=>-*Qe6D|4TGly1clWQaj$xa4 z{>Cr-9eH$K2ix86DhnQ;`CP~E_}t7SYu@+#`=6!Qlk8g0`x!hx9ks{4@u;uIwTEA& zCC;6mtzCX*@#*=;{~Eu}n)|cf$FBB?kJwUEVEpl=MtG+A`Z8z%*&IL&0+)g(14+&T zkH}&M2GM^Y%$RVpfQNyBxgawnq9nrC$0|8LS1&OoKPgqOBDVmn%cjB#$jnVGNmQuF z&B-gas<2f8tFQvHLBje<3ScEA*|tg%z5xo(`9-M;W_kvC21<5Z3JMA~MJZ`kK`w4k z?LeNbQbtKhft9{~d3m{Bxv^e;QM$gNrKP35fswwEkuFe$ZgFK^Nn(X=Ua>O75STeG zsl~}fnFS@8`FRQ;a}$&DOG|8(lt3220mPjt$#8oLN{e#9wxlHMr{<*QrskCt>l^AB z>SNPal9`5ZVO}vbIDi4850U|DGr+3Nv!Eo|1Q=4T6+rhu{RebtGT7eYk`#R;1^Pw? z1{S&oM!H6p`f&dNoo|zpY*mt3l9LJ!IJkenA?TP>f+`A94+?^uOi;*LffJhtNpZ)o^$wy5%BMLy%T&kXOrSKJc}fB*d+6BFYq&mU#7ItR83hJR$^4v_r# zc9x1lQOU(y7X_ zXZR{#rQ%T9JHgViZ^CxIEo;=39e67ba|wLan!qD--cyb-gXhe?+i%q-6+LBde5E4E zxZ_vz;=Z8khFZ2al_#)eeE2wXncCHjLJnOamnF0r?^H842ph>Su>1T%*o4`6nc8NC z%D3|0nH!$?rLe3JR;-L?Q0D}*{4NyTKDYQ#q`dQA$Md`RjTY>Aey!JENX%X6lGXR` zmS=vMdN?^q6bP0 Hl+XkKLPbHr delta 964 zcmV;#13Ub}5ZVWjB!7cxLqkwWLqi}?a&Km7Y-IodD9@FVODIH99L9exB8@D}LbAAv zp%f(~OAV1Sr7_BD;oduDM$NsZdq*~w%2ru;Y`hjW)@&_ol~Nuh8(S-4BVGSg4zrf+)%1YvLig$&>R>nvQp9y!lazWt-rJDtQRh$l3Q<-5m z5g!%~3+w4JHp|$`xVCV=a3pCvlCRAaIH`DDv7KGDiuY763@tg+Q%aZF#u($om_)~9 zm1VNz>6Xm2~SmGFA1sfyqqyFG`w_d8Rw~!QyLhZBfzqdo( zHhgdS{@0Q3e;-5j6I?na|H>f@eu%zR(jo`Yv;pT=CC%J{i%n>G%o(l`NYyg6R0`fs z<(p=q`34&13%wQhIk|^~bTx4ed;8Flmh6QJ@2)TJ?SIcRL4QPl0ATWRp!eh8R{#J2 z32;bRa{vGqBme*wBmtWh#uNYm0sTotK~#8N?VCMM0znXl7aMEuDoqRu7Pc02bQV-< zEUj&9EJ%n68Y`nDh96*KZE4hs!j2zd;YWyx9cOKIGM72CS-5C8nHMtqB%60b#XhjN z%kEH!zzd+c&)y;3=hmuL5hO z^^tFYRshOLuL5uZr&qV<+#TY#!4oqtV5wMcbANX%W_}-l#tYz7ixf2^hs&@11)%paP}=r~q_r03jy8ed@b)0Vw1ISa<(+O#m7(0q#b~ zT@_G>32-+;(}MaRL;mNmzZX!B7r?0&FMv}mUI3?Ba_EfAE&y92V9YlfbNNA-Fak0F0000>S|f?5q$_l%JNFlghxL zF|l@{y@zz5%yE0Qt|TFuR~Hr@=Dp^5IYU;)SI5IaaS2zJ^_QZb;U4FXKV2eXCAN!A z#LM-0i;wFl=$xdAj4!`WEB-n5C7zJ8n;0*0SAnI@7;}mf|1s_oo?Ib1BZv zj7T-sUt|1x&8A?{Yqj5>tgc+Ux*_*$_pD;ydqKkC+Mln5&i}=~n6>)V&UMrOb{Jmr znQ&0yxXt>N4=(91*Y)aMQ{#X4q5P-6i_a{q=vJO5lv*gQ;u<(9M8MB`lItA1hmJy< z+P~bsGpEvdc695*V2B%hL~Saz3i`=cki@_; z!q2X2f0P)!u$$GiEq-44Cy86)4;H0OK&uXR~z5d?dC*QI12bYDu zOnY)}dij~fhvy&vYy3K6-cQv^!}=wef4^@6Mju~lglC$sFM}44%>l$9a4C2)kmM}z zh%9Dc5d8P?Wt5Z@Sn2DRmzV368|&p4rRy77T3YHG80i}s=>k>g7FXt#Bv$C=6)Qswftlly zTAW;zSx}OhpQivaH!&%{w8U0P31kr*K-`&<47aDCv?vE`OG>hSYEEiyYF zJ~n+NnP~_Y<`qMO0~j#+AQ_-G1FYIS3rdnrfFb2t0dx=4e?W&OgY7LYNzq4Apl@Vg zV4-VZq-$iU5BDF?`8FxZRwbDwIjP`)gZl>@f{r;QsG=bCpdiS}1cj_sPGVlVtx|<< zN@`kSX-a1fh$yP5Hu_i`U<2~DRb)_VaehuIDB$f3O^j{8 zfq^25hysX?2&_7gMbUKxWaO9R1CvxyX0m5qNor9+5iogyZ8U<~hg$`@SqRHR^D;~9 zU=1BNAcZ4NHBfUPVTzPSAsGN1{=ghy$7Q1r&rNn*Uncj= zVPIft@N{tusbG8?z0r@^kjGcB`k|Eqn?t*n9mBy>EicX;J9mgbWQBH6>n~QGH#N?J z!rC4DE42I$G)P3f5O=7Z6j-uLt$fCN+vY zBV6|_{&%?zInEuk?d19+ zcb9NA9B)?-d%Vy%eVN0jIZKXR4}ZmF7jsmSVF%B-Z;yExK9f|<_w%{H z*9NK00p%vYLITwF*I)kCyry|&z4X~?eh!8kF-u;Ryti%86?$^+b9a@VG(%NRf2V(- z>hqJw%~-$K$QS>wlnUFDYsS!}b>!@EwuX7ncbl-@xW-_6z1`!&)I-l0Cp<5H{>#-N zjd?+bk&q1|1Lu|4SC^~#6`nsT*zYeH`0_KuCo_(IX^m7a2G=<{-fRc9Y)w4zI_SY< z*B%}Qo9vU?RiBt0UNi>C?Z0yW1jCa`hGqLIPIiXJR_+OEOWvO-?x6B7%KWkHB|QTl zwkLC6tl!lvQ^|E8*sP05JpH&x;U*o)+S_{@e4Sre+eiO4+x0!$f#JY2rO@T<{40KO z+9g(jK|a+qCtE$c(QsZ0jz6S-mx~CYATxr*7s1sn8f^ADhVLQ~$)+8Rnhwo+jUu WGcEpDY{*kkaqsEs=d#Wzp$PyB;x1tT delta 986 zcmV<0110>N5by_(B!7cxLqkwWLqi}?a&Km7Y-IodD9@FVODIH99L9exB8@D}LbAAv zp%f(~OAV1Sr7_BD;oduDM$NsZdq*~w%2ru;Y`hjW)@&_ol~Nuh8(S-4BVGSg4zrf+)%1YvLig$&>R>nvQp9y!lazWt-rJDtQRh$l3Q<-5m z5g!%~3+w4JHp|$`xVCV=a3pCvlCRAaIH`DDv7KGDiuY763@tg+Q%aZF#u($om_)~9 zm1VNz>6Xm2~SmGFA1sfyqqyFG`w_d8Rw~!QyLhZBfzqdo( zHhgdS{@0Q3e;-5j6I?na|H>f@eu%zR(jo`Yv;pT=CC%J{i%n>G%o(l`NYyg6R0`fs z<(p=q`34&13%wQhIk|^~bTx4ed;8Flmh6QJ@2)TJ?SIcRL4QPl0ATWRp!eh8R{#J2 z32;bRa{vGqBme*wBmtWh#uNYm0uxC@K~#8N?VCMI13?gmH#T+>?^5%seo>n-7-o zlHJVAZhvB(PDfy3+cTYo#GJ4#OIY@_u)69}t=@_3e)06On4gqS4B?|$&%-bf6QE>a z13<~b27rc!R;wk$6rnPpR(tA&DMDjFz40bB9-oq73f==i(McuerMBDOGE5PwZ$LV| z+zV5LZV9-luu6wbz};3WV`7B&EsEXE8lUFZA7m;o5Iz8{Pk;H~pj?H>ks4*>mlymh{+{lkDU z12AfRKNvH>be-=P-UC3%!UlknMY|v1p6|mj5ZL_yZ39+U*0d&gc)X9c0hx`>p%bW- zcYjpkQ@y>3wgK7g?7#{7i=JT#Q01x;?UtBIaJ-@DKj<9wUM%=mKz9i&CYQ7(cxgOG zdk;9exITelAdYvp4q=FbwgKbL1;(L!&rcUlg+a-}27r=<4FDwzc>}cb09~;22wno9 zWMKn9$-)MJl7+kh=y?EkLj~Oc?3Nn30aLlX+@BBNUZ!%}>Z+scUaWB2>Vvw-<@2(Z z0lW!b<8>i^0jfjoL3nBt@c;k-07*qo IM6N<$g4q$xyZ`_I diff --git a/Resources/Textures/Structures/Windows/plastitanium_window.rsi/ptwindow7.png b/Resources/Textures/Structures/Windows/plastitanium_window.rsi/ptwindow7.png index cc1f21f692a0fafa1a9a03c74e8f688af389d18e..82b23102f540a05c48e7c525d126c400fb6b99d1 100644 GIT binary patch literal 1668 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEU|g5!>>S|f?5q$_l%JNFlghxL zF|l@{wTDcgNSl4QYp0&3kD^jyi|JIhK<_gK>8LwDwEzdrwbo$CCm(y&J_cX!N!=&+xlevDq}{gns1p+E?~DzPC4D-W6A-{@BOB zm8V(7dyitj_xd^8G+ZBjvaRZ`zwo_(V@DFJyG>-#BQpt6SI?lR3a3dr^DZmj@t^<3 z@vqtc^Ltk5PD^;f^y>QRs3PIMdrrT%uM)f2cs#oxB5+yqub{ne0@RrIe|zdFbfJu^ zKTgz``LE;mwSgIb9#-z(z3?S-%)07(_hZlRz9am({6_|R@xF75{;;NnC4OSrw(VhL z*t?qA^ER{oR@&HXes*hSJfqX2y4}@@;ugRNbs{~eI1!RMS^_3LBN=mYAl_Got6rA&mQWebf4D<|??6?#Z6l{u8(yW49+@RWl zJX@uVl9B=|ef{$Ca=mh6z5JqdeM3u2OML?)eIp}XpbFjM%Dj@q3f;V7Wr!g#b6ir3 zlZ!G7N;32F6hP)CCgqow*eWT3EP?}wJ5!S3_7s#B<$!HTN!CxzNzF~oD=F4D)HBq_ zrmrM34dKGPVrXyx14bVt1Jq`KRhwr)NwNtrq+Bb2?t%Ib=+I=ay~QOd`bY}&jSLJd zbPbGjjV$%y{sTJSCMDUbB(o$Z6&!GI|A0f#F{cDo6r>&$1UZ?YkhRK5%uBabs?beI zO-n4zDN(X3C@Ig(OUW-cu+fJoL)8uuMK#q%ABzKQK;E{B3`#A|&nX23yq%$mu?;vd zP(%??0MQYFRR^*tx{iR1{E~cNk}Aqf_RK3uEh;DiCNHp!Mo{~3t3WpkVR>j?W{Dll z05oAFT}aVmy%Z1mx|$&TyGo}Fj7wP5afhTlyl z^=uc|-qx_)5MT1sxWO#rx$%L03TNjtZgI4p&-jfs^B>Ow-djI;Ht2hNPG`uya4x-} z)^V0Sb4GL7zprc${xh#&T>W3aVlShpgXlIwM%QPD@zfn$)FcBcR6Je%T-G@yGywqb CsAU!a literal 641 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEU~JBGb`J1#c2)=|%1_J8No8Qr zI6rlww}wlg%&~esrCyygPMdagFBDN#@#dXqwAAoa_QQMDX>MotE~|Don|3NJvLa`X znAx=)-JGdGa;nnN+DXc>|BKVJ)J#vUy!`X)+|RXhKg(X=+dS><)h`WipWOWs5i)<~ z+{>@yR=6v>sOz>peVP=!m{Y6oy!EOpRkzn}`f)$QN3T*WcZteOWqR*pic{$i?`psh!kB`i7Ii4~#b<>lV)2<30Ro44`k?Y^J1NNGF z!7-;J9!Vs!N-KX@{O>{e_PAB+w@(o1a(cV@{r>IFcg*E7kv} z6nW}8_Jv+jV!yD3@p-uF**lHhz8RHgB-aUgTs7Jn!gbH@>Fl(HKiQ<7aqkuVZn?9) zrNp$5xBB;miPPS+a=l-t|NiZHW5;@zdWM8gMGL+^eh?0f70v>W$YKTtF%=MIoGp4x z1Sq(~)5S5QBJS<%jl3-e0tXKHf9MFU=LxGl$hPn!OF+Plyqc{`MaqMwSw63r{C?Nl zp6wR>|NB3R$*)<;5aG?ZVH#6{F6)6Pu7<554B46t*FOD_`|!=~|CD(Q*Mb;usKFxf kg8554SU;xR(w;)b#VbThcP>1$ALw2NPgg&ebxsLQ0OYzB@&Et; diff --git a/Resources/Textures/Structures/Windows/plastitanium_window_diagonal.rsi/meta.json b/Resources/Textures/Structures/Windows/plastitanium_window_diagonal.rsi/meta.json index 769ebe5b39ac..9c854c61ce7f 100644 --- a/Resources/Textures/Structures/Windows/plastitanium_window_diagonal.rsi/meta.json +++ b/Resources/Textures/Structures/Windows/plastitanium_window_diagonal.rsi/meta.json @@ -5,7 +5,7 @@ "y": 32 }, "license": "CC-BY-SA-3.0", - "copyright": "Modified from plastitanium_window.rsi by Flareguy for Space Station 14", + "copyright": "Modified from plastitanium_window.rsi by Flareguy for Space Station 14, transparency tweaked by Ubaser.", "states": [ { "name": "state0" diff --git a/Resources/Textures/Structures/Windows/plastitanium_window_diagonal.rsi/state0.png b/Resources/Textures/Structures/Windows/plastitanium_window_diagonal.rsi/state0.png index 7737feb5032c9ac64f42e8805d776a68517bbca9..b25ae0a4a06e4393fd19eb4c032e512e75e9abaa 100644 GIT binary patch literal 1375 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}e5nzhX}-P; zT0k}j5QD&_;K@Lev%n*=n1Mm}4+t}^JN#w_0|RqfW=KRygs+cPa(=E}VoH8es$NBI z0a%w!g%yyQn_7~nP?4LHS8P>bs{~eI1!RMS^_3LBN=mYAl_Got6rA&mQWebf4D<|? z?6?#Z6l{u8(yW49+@RWlJX@uVl9B=|ef{$Ca=mh6z5JqdeM3u2OML?)eIp}XpbFjM z%Dj@q3f;V7Wr!g#b6ir3lZ!G7N;32F6hP)CCgqow*eWT3EP?}wJ5!S3_7s#B<$!HT zN!CxzNzF~oD=F4D)HBq_rmrM34dKGPVrXyx14bVt1Jq`KRhwr)NwNtrq+Bb2?t%Ib z=+I=ay~QOd`bY}&jSLJdbPbGjjV$%y{sTJSCMDUbB(o$Z6&!GI|A0f#F{cDo6r>&$ z1UZ?YkhRK5%uBabs?beIO-n4zDN(XZE6vHV(TAu&)d>+rHPA*Mi`_OLA6rERr55Ms zl!C(C&dAcz1{@A3qKMFk=!n3o16dSZM?gk?Nj@+&6=f!S=9Q!t6%+we7Q{xVeYjPi zn}x7EG%vHn&IoD%nlO?sq?oaCEGj9_FUk%9#{wh>aY{ptfCMK}%7i3)aL@zOy&ad0 zK0FWEah-lG(*ew^6`n4RArYKMryBYlHV|oxy%AU_F4khfHi6 z3n%jFtdZT}sLFRCppfx}_)B)-ImfQ_{bjQ*jH$1`_xp2}&%q7fUK9s(@&EbqdpCD+ZOWhP-t;>d)m&L)q=hj-6xG6G&5&hn`3G|sbT@|yIrz}cP7NTb9Xc2*WeQjIQ<&ZCPi#WO8w^edh?3@BJ8R7Z- ztl9DDoGkor-&$Fe-1`;(;85u2b@$}B((a%A@^FtSvz>+gt5w_tk5Am-b++W1XXO*=iX7h}XOKx(n@Hy}QwF zf9RACHHPpJ18NBR2Qe4|ibhZoFc<;~L4yJbUm?mgNDxIA4NT&DcWrka9ZpSb(suW} zzvuUSKYjO7ds}mj`+m2}<*I3kMmpd(V!kJgho5?1-*51%Lhoo^;M#e-?lOF+Og6+C zT&`VftB3fz;q$~ybcybARZlbD6|UDe*ScKpD{{Qc=!z|31vTyEMKuAuxpW4iU9Ql) zT!t5x0Ru^Zq^yKJ*Y+OpAhH6<;)8KxtY^5J5ahNxp>D%P@{IG$RZ}WwXY;&di&&=mbwYM8z6gyD!6Q zIxx3F*i%>wgz-FH4{82Fjf_ zfX!l|%IfQ?WMp{_G$i4GjAbj?gr#au<}#iCACs-~%l~z%$2KDWG}Yx-<^P`QVpj^? zypjYWhZP#KAo!cY*tK#_Mq$iG4pGSb`7?(Pb_s8d01?7&lNHR_=q_`XQau(rK;rO) z5$0!J(Ro~|xa7`?&f`+WVZA35+2F{$r4izyj`=%n|Dbfj>mT6!G)>VVY^1mp-!A7s zsw*PH9~9kO1r)SmX^cE5qqbx;HOGOiW>>~>N3(X9Erl0A_yj9exP6*W#TzV8;I&nQ z_tS&xD+l2{Inokoh<7y~dS#b#5TCrdrge{d^QuYPzMWE=o3h$1?LNM3>bsj(y|$)` zzc{h>Mt$u!Yi6H(FgQ42`c&cYt+!SV+}uo^j(#0K1+xbF80d*?jn`h41s z&#E#XwVmO|UDsw@ua0Vy>)(v-KmXH@_vGrUJ{Z4l$hdLuz<2KqWYaIdc&XAee#QPX z*PeYZdn9o5aw}RfbZN(_D}$$7D-mYPzP0^d*3EkO?fR-G$8D`XJoCDC5uLwb#n7?$ zr?1}B?_myH-B1^-`tZneo&DSELNhKlPTJ!B`Jt*)72Lq5bNVm+vGnG;6<=(B6&l%k ze#^eD_SyY!e3II8wu8Nk`*qIV^BZ5NII(K(*{l9V(srHiudmuk%|e!9+z*NQ>(34B z)}!2w+6!xut##)rS8jYjxHT?uq~X5Ft;(e4lV5#2E%pq)@XreRC_Ukru;~}`pM{pD Lw#d!}Pd)z^&dvN# diff --git a/Resources/Textures/Structures/Windows/plastitanium_window_diagonal.rsi/state1.png b/Resources/Textures/Structures/Windows/plastitanium_window_diagonal.rsi/state1.png index 834b6261fd325fd9c6cd367f68bb72c7d7f57e0f..7185af8426c5949c3803086b2d527f4749ab56bd 100644 GIT binary patch literal 1343 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^R}e5nzhX}-P; zT0k}j5QD&_;K@Lev%n*=n1Mm}4+t}^JN#w_0|RqfW=KRygs+cPa(=E}VoH8es$NBI z0a%w!g%yyQn_7~nP?4LHS8P>bs{~eI1!RMS^_3LBN=mYAl_Got6rA&mQWebf4D<|? z?6?#Z6l{u8(yW49+@RWlJX@uVl9B=|ef{$Ca=mh6z5JqdeM3u2OML?)eIp}XpbFjM z%Dj@q3f;V7Wr!g#b6ir3lZ!G7N;32F6hP)CCgqow*eWT3EP?}wJ5!S3_7s#B<$!HT zN!CxzNzF~oD=F4D)HBq_rmrM34dKGPVrXyx14bVt1Jq`KRhwr)NwNtrq+Bb2?t%Ib z=+I=ay~QOd`bY}&jSLJdbPbGjjV$%y{sTJSCMDUbB(o$Z6&!GI|A0f#F{cDo6r>&$ z1UZ?YkhRK5%uBabs?beIO-n4zDN(XZE6vHV(TAu&)d>+rHPA*Mi`_OLA6rERr55Ms zl!C(C&dAcz1{@A3qKMFk=!n3o16dSZM?gk?Nj@+&6=f!S=9Q!t6%+we7Q{xVeYjPi zn}x7EG%vHn&IoD%nlO?sq?oaCEGj9_FUk%9#{wh>aY{ptfCMK}%7i3)aL@zOy&ad0 zK0FWEah-lG(*ew^5uPrNArYKMr)~^nHWYAWJvYkgL7EWH*Ailq+h z^A%883`Q6&NuO;r?uZ{ouh`GLIM|ms@OMKP+IEA*~ zPjjOi4exBXX%w0BD?5nU@<-Wkv;7AwEz}FnrmhqCQ}ClmM8;CRqUcfO-%T@hS)14| zy=U#b`s(D{GWkTVAFtE?+I2TPaA<$%#^>0?-&7oL%i44~r6Ng%qt|fGPuA&Cf`_LT zzh~cmzn<-g#JQBM!X5`1dy3D+$b@Dou=lT?+thtsR<_sU&*TN(FdcCZKX4kwm>kz2$@^tlcS?83{1OPSNz?J|2 literal 3208 zcmcgveQXnD7{4OhWCU20s4WONUbvo8DdD z=Y5{v^Znf0E!|xmbDHmLMi699yfc=BPt>|@ZiIJZWaJ8bc#LF68?yhzg74vCX0|oa ziXd-{&Auiy!1XMxv(G?~*|%Dk2YL4SI}oJ#2RYSi_9m9`qMG*!l9~p-VqSyX2ohRS z)C6%gFwr!~%1YQfapag6m8GzE1(P5WS`-Y(og+Hv8R<%iBdbMD@-B(YX$}>6h>!=S zfEM#P#o&u!uMNz@-xeA7qBe`UI_zz=G@`wUZZxXu0A+juOe6w9G|2f#CK#lH526%7 zGC1MK{RBq&d79v93N3xSP#ubfbSc9pV@pfw;417LFinle@j{{CEBJk?p2bOy<8Xq) zDGGxem@%xFLJ?Dpg$_swCI$>qmo-yX71V+i((0fY_CkvtSMpi~TQN%Uf|0|Ef`*em z!g9@Kl*9_3HmK)p3nUQ-Igkg6X+U1G!mACarfLkRQ$Sa?s}#TxClVDMb#2M#D=G}L zeF(Zyib`E>BQ>l6JP8bSP!~b_5HxdP*&9>NOvbcI+S;kI3l!xkSgjq0)y|rg!VvU= zkLo}$RXwGuxrkE^-Q|Fw(Wsq%^xhS+BB=%Az7Sq3VpTvj7KjNZh)@LO$A|z%(J3;( z(=1QY4-h0z5H1LZvkD=hN^)j+5`lzON2SOhPrxtbMsRUfBft`u1XGw6hMTv7B8hxP z)$@WGk@G?p;F^*R;giG)U!^kmsG3uCXb_0_LwG%M9hsOa4qC<7s))dV2{0;YDfL2| zkadwt#GD*)npsjsS>h*kv2=!|Igr7Egv4Sb2>`~4OaKE6D+yeN(PpJ2174R_P=Xd|WY10Xh(mMIgZ^LzDazDY6pBU`$$+Fd)$c#-%|JBQhK(`bCxo zQoyc(YVop3CE&7V2wdOaj6aYe1e%5ZX6PyXb*yxO)u?$?m*Hp?axMsd7GBM*NNAKFAM2zCpQA^bX8S)Ie(YxPoY(B=+O1pMHn zbuS6Jx2pyFZY=2Dt`?k>Tdv4vgeqyOAy;Iq_q6ju>4C>T5D74h9}b#Yay5UqTm-q^ zm<(SihBXTOP>U^5yHQ81Zz?g@h9l-=#&t%sXO}~T2SB)jnJS+?tySd&3lw;4)#3T{ z@yyr(cuu}29&1hYc6|JF_?8Vs%hHY8U)UIbdDFS#%-M6#g%^yWuUtZWEOY})=DlUSI1>C3nK%#&ZNzjom4mPMXLE0UkgJ9Q!X`nkp{7pU)U zA3u*iG8$jG{MXB#sNO=4okdvlb@uo#ROjfrpF{nF z$JTj~&wl#xiJ4bFUz6UU>*LJm5p5*aKlf;Zrk~m~{QKT-?|yI5*Xl!yn@)Iq`uP0u z`Fnry{Z!*CJ2oymo}do5 bv>o*v^j$q%*nPU)`a2MB?~3hjTeaaYGD7f( diff --git a/Resources/Textures/Structures/Windows/reinforced_plasma_diagonal.rsi/meta.json b/Resources/Textures/Structures/Windows/reinforced_plasma_diagonal.rsi/meta.json index 453a3797223a..8477687a8c7a 100644 --- a/Resources/Textures/Structures/Windows/reinforced_plasma_diagonal.rsi/meta.json +++ b/Resources/Textures/Structures/Windows/reinforced_plasma_diagonal.rsi/meta.json @@ -5,7 +5,7 @@ "y": 32 }, "license": "CC-BY-SA-3.0", - "copyright": "Made by brainfood1183 (github)", + "copyright": "Made by brainfood1183 (github), transparency tweaked by Ubaser.", "states": [ { "name": "state0" diff --git a/Resources/Textures/Structures/Windows/reinforced_plasma_diagonal.rsi/state0.png b/Resources/Textures/Structures/Windows/reinforced_plasma_diagonal.rsi/state0.png index 8ad1f325b352c75d7f7b998f9cb704bbdf06410a..9f76902acf6b3a5ddc8b0fbf20bed46d429065aa 100644 GIT binary patch delta 1264 zcmZ2p)5sS%!OzP=1vKsE;ugTSTW$v~2`z$3Dlfk9&y z2s4UXDQ;q5U{0H8B|WiQhcCi6K*2e`C{@8s&p^*$;@7&#D;O;%FJm%K_ADq#HmS%h zaIGk@RmvzSDX`Ml&jgC;#BtJK`q$o4l zGp{7IsGumdBoU(8MjvbfRuz-`xkM-5=Q1=$@~xF)QAv4zQFaK}XCSBAAO{AD^yC%X zX7z`zMSKN@xtynqV@L$&(dpjV!igen%bgd9>xOcr1qJ%#Y+L(i*@D?#E4UA~a+^0r zAKVpI?({l-#RL8i>LR;J9xmcoR5p8?;88WfE|2KhPQGV8TfQ%_QrkE^#!ln@)0&yz z=X~Gu{LGclRTl5&Reso${-I(2?(eDl){DzA{Co1OK87i0|7|{oy815{4R(abE&a9o z6~lw`X>mJFF#i9sVaN5YA`!Rt*J|;0{aj~}kjehzPs)bZ>NW4*Txq!fQKaJ=_w{3C z`TFr|wTcd$?!N6UTk5bS{QK&AN1QG_m0@?w=dt{-_0TVm<3S3y7D^vnduG~qhVUnA zBxMsFwlFJfJ?tb?FH?P6QsAx4omI6-W}Ds5S#Dpvman6XF=8uooX!-tpqCGpzsXpT zt10ld!7RvnLBn*e`?2CIe~QX#mh19G+?raP>z%z^UaO2-&X#LIW?WFU)RaITDyL$cg3u|E$`#p zie5zk4Xg}^d0Vw3t;PM_*6p7s1}of(UU`>E#D2Oz^SU|F(yx^*6Ee5I4bAFrUeI`D z=@T=DZ7i`;uT~zYdm++MrZoM*7q6|dekJZp#ZFfiZnc;oRBw!WeXTSEI0maskib<#A|Q1SvRv4wyZdJ_@17$u~fmgzpv^F z3?mhvH>}rL^IbXRpOT=}hnG8J)}F7vylT7riqE@l=_+J9bXW)_$jwQ#xL3)MM zt(%ASM4tlfP3~De*VuZIm3h-=Cxv&e-+oCsB%EVtFT0jB-J$ltPxp;eZ~dIembu}5 u@!agPZy%DK(;J+vt2<}u{i^!>^qRceAG>9SyFc`U$}dk>KbLh*2~7a(5g;u9 literal 15911 zcmeI3Yj6|S6@V9#0(KH=T&Bh)xT;LjB(U0tp1UK77@O245g1!Brh_S~-Icv#Nh`E# zTbP!RKu9U2G$BC8JQAL1fTV*lPAI`JlaOX`ikZMbdC$-~G^NH6nt%tp^sZ!E^0j=2 zNix$vyQ9}R=bm%!{m#8d`)5}a&-mFR=|4)xFzk_{!h#a;ZP4DMMu1PHzWzVpD=l0& zN5Qa%exSXFVGSF{VHo?N=RAVU>JMXNU#^A%%^)jIp>Z z_^qi4qaij#t#%pnw1kFoPq86ij)(@U$%gZ!&2F$WCdz8JTkMk!G)Y+r(oC31oHnx- zlC{u=-plAt2fv&V!OxZyJky&FNG@ZQs)kvDsH>|p)tOClq>`W*h9O9rplKY8z?Fp| zm5bsbB{v?VFHV7|@DVAjN^;1c#pQf*jp{NQwM6|_@4ABF{zM_AmmQ!;M7c0QnMfj) zlfd`;gli&!*wh4`5CdXR45^yf}F-(WChYDJw^ z3lQ`oP3ft47luWmL{#LO2ro{n1xv|IwR%Fy^hKp8*z%hOY zW7BG(9bOP3F)uA{Ogk`R@^Vn~)wY4h!xn`Ul>^HuDsTgZNdhzDL?0;%JcIlElm+K3 z76;DQd_LUg^U)47=MZS#AKM!P-4iqG4c(U=gigJ18)K&^#=(Gvi^7l#kIyqH*q}r+ zBNAxmTp($TwiW@bg(9sMlJVJbJ0n;FU6akQ>m0OevKe+wcs?JJ zR5#t54N@n0X*UM(f2~q*4=cKDR;$_SBw#h{Q7lEpKzV@#{XZFl?7RGtSkZSG6^f-NfqbM{vXi>+7<^x%ETo4ensN+KOfvh?%2nbr#aiRG@Rvi}v1TE^g(0m}P zjtc^U7Ij=`K9E(%1pz^eIxaLH$g1OlfS^Sk7n%=b)p0>U(4vkD%?GmTxF8^CQOAYm z16g%k5D>Je<3jU+tU4|T2wK!}q4_{o9Tx-yE$XaHx?DW?RYOhL>MUcI^KjK`D?i+A%U<4b zrR>ed*2b$FR%Kx6^1R;zZS&Pdr}yoD`kZ_AmQ7tfzS9>+Pu(Bs%E|sA7~7ru-^m%Z z+YU8~ul)JW5&Mmdj;vQ^cf5HFFWYK8aJ_5uv=PC(b6?*1*=TG}L3Q5RtR3%{);0(y znp-#TZra`1m>G<=R5Hz_<3}yq)v>l>UCnz-Pkb`2Vo{FwK>O>P{Kf63*Vs?2tZlnJ zxnkqlrZnu+oqs)Y_2qlZZ|rS)_C_X__VF9e?;Wa|x%bc~)0s=*h_O6r11ILD4__U>=XTqHi$bIyy3vPD@F1Gu@Yd9CUOE2kk zHTHCFoV4Wa`P7Eyv6ze*(vME8XkF2|X2!&eE-?M&8CyF8otd!&M1nQ3!>e0FiCbLIlWnDto|t!Z^_ZM%xcXFqUx@#5gUZ0wFt;;I+! Sxvf3QT{LY*!MjuEzw|%x_1DV) diff --git a/Resources/Textures/Structures/Windows/reinforced_plasma_diagonal.rsi/state1.png b/Resources/Textures/Structures/Windows/reinforced_plasma_diagonal.rsi/state1.png index e724d3b9f78d115d79ca3ded3230db216cfe4056..0d651dedf6e8fd656889f5362d6dfe8439c31e04 100644 GIT binary patch delta 1257 zcmeCJ`Num!#g?%+$lZxy-8q?;3=9l>sS%!OzP=1vKsE;ugTSTW$v~2`z$3Dlfk9&y z2s4UXDQ;q5U{0H8B|WiQhcCi6K*2e`C{@8s&p^*$;@7&#D;O;%FJm%K_ADq#HmS%h zaIGk@RmvzSDX`Ml&jgC;#BtJK`q$o4l zGp{7IsGumdBoU(8MjvbfRuz-`xkM-5=Q1=$@~xF)QAv4zQFaK}XCSBAAO{AD^yC%X zX7z`zMSKN@xwxl`V@L$&(dpj)!GR*J`q!npG6D=QIH`!e6fyOau(&9oc235^urN!h zxHOIFA1nJm0ikxj-p-GPx&c8vg;D z4=R`6kc+AL^XbY1#{VBSY_KVil4JPy=3Wp}&i?xQd<_3GzPw~D$lvG5|LrQ{fq0!g zMH89-{q)>;Z@Wmut?m1!v>mC5m)Wp|*``uC^sDf`@=U##-)&eI{eAVe^VQ$)+h=vj zeE4+g-0gW*3b$tWE;IjKb?2!JyW9IY#SgN7ew{dPslyg$^QPasBGxglJ0W?w>QF-l zyF*rctA)k4b;k7yw=D0hsx2$r<##S}``Xof9c7FWTbbj|On199^NRn?iw@U=6mBuv zdc195iaQm4N0;Nr*EeVK!h!D5e$L?aw&!Zl%#HDUHpXvfSZrjTR_4XKwfN+g)0UYE zMOAaGCNeLY+bps()Ouo4aIw@0zc)ty?6sQVQdZkIbl=XsqW5rR{db{#za>ttOtwtO ze7<1EtVE_S^dom8ozA)DBF<3 zxyyuQ<$<~vA{}K)(;s~C+-g4OMW2`Mw9k*S3}?>synd}{_2H1i3uOe}&X(Waz9XgL zq`*|A^qgpxb4h0yr?H&-v0t-Z;O!Lg+|+lI`(NE|oXn~*z_<_a5Q*8dm zmC4l?&)ss&+Fq?`*pjZix$JJm+c*C$5;C`+U$L!x_bZ#8D^133UtLzs*?eu)`?>WO z^XD@+*vCiAOP}o3yD`q_!kHM}g|4M?_ug*0xR^0L-$Z)l%8yc(>^lTkG~BOJoZsW} z;=p^ov)kGBl+S(lt+rHd#a$*Nww4ZMMz#lQwttIiKDRH@vij+#8}AQ&uPMqh2`=V~ zxOGz`+&X)kYiSudg(p3Q&f pMMtOb%S#tZf0n=M#d7Ws|C$S?y64`_-w7(XJYD@<);T3K0RWbNBNhMv literal 15885 zcmeI3Yj6|S6@V8?c^Gi0)ABMTvJ#v$j8*CC8V>@7I3tsQ8?2RR@(5@}n zF2s;93~5s!#A!_3m}wJ+S4;<}sY3`!!(&K!wFxD`h6Fl=g6nu1V!+Tq?@G2LU(0ux zBs2Z9JEN7(J@=e*?|1Gw+CRItAb-yIgsBM_hK(BveXzAU~%$gTDBMYZ|GY;7fLc*!Zga?$FXW7U$i(hxf`7up{Hz`6@(Nlq$p_LPpd>1_n8CIwP^;uGiy<8(NZc zssVyNq;V~!;u;^17xI!=k!VYARt2xrI+ z_DW~@c}5of#iHnTgil#PKSE7bR_Ih|9$zSUIWZvp*p9;{(R@d}@!5>bJ1BxO=m@ip zG8U6&+GwRoV;Vuy1QFvTJQMQa6gk0F6ZJuY15GJDNRp<^u|8sE!ahL#aE#2{mzUVN zF@89fc8PuuBRd2SQ_kZ)Z@C?h4#v!koGLm?bc=qlEZ$+T$T4jrDm2#{zy(}+* zWJobd0;viW?kuK!;Ap?XEjYq$gA-YSqoYBsMwiuS<6Sxn!C7@A$@4lJYclJ2la*s^ zF00L~3Gs;(3M#kQb$<%GJ?0d7!&6TosEI!(UtYN?vD;!$KN<*;fyX9TLw1Hb3<-Cyv`VB zg96R-3!t4d?wC2sUO2E9lhtA%ZDvMCxR^4X(FXQn1$|v-;!I^^nTw)Wi>-ezaoh|F zl`ANDuYuB_cJYL5nIbG#^N-;(~ynMHLsC z52RIbK|s)=iVMvL(yF*1AZSs=h2{fkRa_7dw5Z}j^MSM~E(i!(RB@sCKw1?S1OzRr zxX^qct%?f*f)-U=Xg-iu#RUODiz+TOA4sd>f`Fh!6&IQhq*ZZ2K+vL!3(W`8s<$5<^yR}To4ensNzENfwU?v2nbqKaiRG@S``-r1TCt#(0m}RiVFgQ7Lm9TqHm`1 zUhq0<0K9jax?s#P@Xo4+%`J3dSnUi9tA8HDdhdbns~A>AVA!=%@Ve`37&b|KdFkQV z7&iP+UUp`2@Z6z>ne*B+CLejYxqiYM6O*Pc`}L7$x$?xM=>>1<8ww`PKB9NePrFf_ z)m2`4@%dNUl8e$dG)fh-xD zx;Dp@y*4|O`~@%+fjKc$9c|stOwi!7c%g3 zZAU#tO}39mVV4V*2C2Hr(c;|w!|{>pOTRo>bov)JMzmiCj`HqlZ)WaK$zQa=Tzsl~ z@34*4Kic(Tban+;k4d?%}bxQiA*PEEcuMY=m zPU_n3zGU9)-u2wXtN-j;eX>e=XwB2cE0;%N8EZe=`u*D*60nDxm#5S{)A&Vd%jKrJ zj{KxauODxlaTeTrnpUmYbAFoXK;euQzoz!&%b9%LG-~mg+BdfZe>mIePd<0TJ;~H) zd9G#ctv_%4)Z6*S!q&9UTaMk>VO#fv^IyH=q>7@Y-6Jl(@OIv+uBR?<+j8@r&ZapH zoAw&k%*DFej!JWYRsMwhpEfPIbm^<4rJWb#aSV4SseWGi?ytL>D(kP7l55N+tbP8O z2ZnuKdav}^>dSxauD#yA_qWUa+-l~NKx<%3W9x#pu2)<98DpAF_{ooN-@STsS~5Ou y7&iaCo(*01ny!pVJaj4V?5V%6E18Df9fxt$((UVe$6r!j*v`wz&u*Djy6S)8Ho|uR diff --git a/Resources/Textures/Structures/Windows/reinforced_plasma_window.rsi/full.png b/Resources/Textures/Structures/Windows/reinforced_plasma_window.rsi/full.png index 4cfc4c45da5178cb9fb00132bd47b9570301ad6b..ffb90335d936ae9ca6c0a0287ae2d91308cd7df3 100644 GIT binary patch literal 3504 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 delta 2486 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 delta 2924 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 delta 2924 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 Yzrx(A<|rn?4FCWD07*qoM6N<$f_`^Jng9R* diff --git a/Resources/Textures/Structures/Windows/reinforced_plasma_window.rsi/rpwindow5.png b/Resources/Textures/Structures/Windows/reinforced_plasma_window.rsi/rpwindow5.png index 8ebeed21a9fceba5d6cd550f7ab6d33888cecb9d..6654332c366a894ea342a298c4a0e2ceb97e5d52 100644 GIT binary patch literal 3021 zcmZ`*2|Scr8-HiWHujyuG%6%!Y^gCb4IzZeQnvds#>g;crdb%DZRqN@Ag<+-Y(*m5 zRb-cPg|gmDWhoJ&LScka-=MEs_t!nY-+9kD&-?#B&vX9gIq&biaNPcgn253n003gv zR^|@85xdca1bELP;+f~X0YrB=Vg{6U?U?2*#0f6ezIJxNUfx`Y*Ed?9V-oKvOto^Q z1Ayk0jSf;k?yLX+J}S}4h2dgni^Nj`b#XovZ-Oo>kh;l2v5>rJAc28{vI0qDI+BHk zZ6c7o`Gy$|gKk0?0ce&GF^Sk$^ZSB6X|@QyF+eo>CSpUOr#;$4eBy8JEuRfqw&l>mv{cbP)PF`Ul}(_s2^g<%35u zhzt^8Q@F4D*;LS!#Q5I2f!~mTMBGpoNy3p&qhTx^AA&EANn*e-G-@!B>_Z7QM!~mW z-_y6O-+M*De~)%JP#c=r{<6G-L8OQx73<|HL zXhgg+j&sWFiBj|HZ*S%-^uSIUb}bjS)%1E?d3%3Dig&OKRnpzNV*q-SRI$PIf{*>YR;K z$4KR3?GQQmwC_~)ix~;=2Y1TRLuk8^yo0B^2%P2crZ?%+MHgRnH%=a28-F$=>}a4} z)mYiSV+EnI8vZJ|zrPj-jhN_?kTO8Nl+#PMPJReBa=gy*`k12a-pJ`vpasfSuyhAX zU;8z>^`FW=k^#dHFzbrKoV~6s%;}ySP%MYtRppmZ!gl!iBHWa2X2_;k%QQs2{$%wA zRzjwyWMp2G`?n3CPNK567>LsL2EKQBrx|KmJo_|9F1tug~FR&9vevStYb+*a26-))>5*ekzGYR3&4x=O@#-$=0s zRt((AtQ|#OMZG7Vh(%(NAk=|0!$ho3A{#3lH!jM?G#$%3R3-#S!a#vqGr%O}!(nP#^4LjRB`iPt^?z^>_GEjcb=n#*X-_tcmk+=VtX$MJ*yYjwemTp|^C`G~ zbSM8D_<6{oL)meoe+;VI0)VL^Fj094b0;>W=tGYKRa+kDT@#YQhHQ_XAKcxHh|E6P z(}E(#2m|6U9P*vnLiss&PQTzx_%oDj4A6(FIjbOR5xO^^VL`tvMi@E|n5N$2yMICa zJsTb{oouXv<9@1{g%p^wCoko2A(uX9J$vvfcj*SY-{fjuQs{8OOt14K=iGCb%VV`R zXXPD}ms2QH%CBsf751gV+*l65&P?BXVUY}B8L8-*1n6-(Ysy?KLfbx# zKmLQAab`|8v0thR5V9v@OVrZv8keig`#V02P~O_89$5NmDZzlH9 zzF8i2ckt?UsFhsKuaNca*-yh%P2o=^HQx;O5KPw!y0dh5pL{VV9Tb(`2kpZ}V5Y#Q zb*~zZ3}-YptI^9A=`Slj59b5L_f8c_i;Ku$d$WH_zsu%^b%BvjNVIdIGPy;i3BSHR zDmXN77inZUA{~((+lThGRegbt+K6}K=ZB^1KFLiIt3GK5s zOY!Gr$RefWx22tFVzqS(`R~G?SLQd$2Z6v6&FlMiMlParcEG&W(_79I9}b#_cTUZv(NK7`mY z?=h5bgxuj`l)`af&3P%Q2qqvQ`o?S?)@z+jrj3Y81F)*eSzyvPy04UL#0Ecoweqso6wSaeq_L z3LKkn;hSn-il0(znyNVedT!grF>pOKh9g{G91G0^Y%=^zRXxsrYGc;td0+Jxp7Y3k z(kBc}2n&NsE{epJ7RCf5O!Pb@xli-YM<@B}35cyV*ydNWMaSZlxDBe6ye|s7C(rew zusL`boNpBEsb|nuuMWVSa$Q}3&z3bVn7PW>5DOqO?A$gk{L=|(j9AJ1Xl_W6bfQX| zN*lV~O}0ip0=DbJ#8daW>Ki8YEw=qJC+j8xb2)GGwgIhs2(lT6JQeMOE?2Qqhc7 z>Y%b)F-6l|*~7ESu*Xy@;mPypTYTb?VW<>LX>3;HLRn(ha_W+(igo7g*{8o1>uHFO zn%|Eu;p^LHlo)%gsAgHfzQTB1St@X>^@533=m8UM(@j2A$o?4Zp^n>=V>!x1qjcAj ky2_)sKFo<8Jt4^DqvBuLgv{DtHh!h8E$q!p&Ag)j2Q3)`Q~&?~ delta 1680 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 Yzrx(A<|rn?4FCWD07*qoM6N<$f_`^Jng9R* diff --git a/Resources/Textures/Structures/Windows/reinforced_plasma_window.rsi/rpwindow7.png b/Resources/Textures/Structures/Windows/reinforced_plasma_window.rsi/rpwindow7.png index 4d0ff4bf7318bde3f96e034058039551ad57141a..e140c63e4ff524b62681e16ba770560f8de3cf88 100644 GIT binary patch literal 2262 zcmZ`*3pkYN9{+}s%gN5T?6E5`%|w!!ZwzN+8bTvxT`HVhmM|A)YHrPZbBx>WR8Gjy zMI@I>$3`X-wlrdOL7rAoiB6OaizhY~wM4tlH^Y&7+V^?h+yDFh{{R2`d*A=_d>K0f zybTS^4FCWzr1?+-;n`i?^;W@S1!sRBJR!t^-kyN6-Qp#@`HU4xi}m*h?BKN?+|}(- zP!2rm3w^@G0AO37?g%sTx*7n`7IK0^p-_K6GDE;4#4rVP7D37rYFHF08D8>OPz*-O z~A zWkZmV41)3T@q~Csf{KUYx*(Vx)M!7`N!;|9+?}F+;==LL31f zqxKs^7f2viELI(8xh>|&WGu%KN<>^u6ea^?aalYT9}|_fd0sN#y90rXK zu|z@<{Ja(;F2(z6#K*qg2mdFZ1G$lw9DHP6!CG-WWDgM(FA(hu)?CF39sd%uoI005tl;72sw-0hg=E&ETY}<}3gphiFufU@78NVOxNyhw0%u6EAO{$6uTpe{B?@ zk_>j2L1TB!elvpNp0VY((s9%@MRIe8gwkFnNM6VN)23Yhw-PO%M6SHq`>8l*H!yzsRhfq;Y?8^g z8-yFvZy&PVlu9j$=YJDc3{+O+;*Om}OP-a*?0vLlf>c9B*j$Ui`uU!dRW%sq%=Ezi z*$K?iM|n5(2#0kNaHBnPg$a6dmap%@K;uiRI8CNcu6;Rk1OR-rM1(ouhx(zNX5Q^y zRRI> z(_$$b%8J@7`s~Hz?Hf2k;_yIsT;&A2UX?R_n#ZcvEq(FSXZ3;LvzgPig%k8h2LwRJ z0a@KFdG5pBp>_4_sCr;L&eSCO`LOnXBq_k0cwNc)4K?|I(8n`JQcdam?d1!`psOKw=~W<#n~ zw!3wayvk@kfnW5a4qZ93_by!vDB$;%ZkR1^9X&HNDKA$z5NrVSM)W)o6|a9!7}IDS z7>N(_lkK-R`d5O{`aN1-z6@);xcA-(IbDlB(0SVkNOZ;aO|+@<0U4a4*M0pI#M+sM z`iSs8VLD1!gzG>5R#{m4Ybs#BqiD@wo=48Pw+EVA^Fw-o`rlb-MH$Oj5mishzkZR1 z%4q3YV^{52uCUJBcGJ20{=%tSoyq9Rw>MUwsX49yj+Yh;4xpo_@6`4m(;_=ReSYuw z1E;N#Tknt2wU8Y)y!3&?E=C0WnjOb%SKeEhm7^=Ga(rR6SFOScdekx0_#?HV@bz^v;-LJk2l^LO>n>yS#DIpMVCVpnsv~W(h0GD8aNVF z;1f{Plt2Gu*vbZJR+*Js*I0#`owvH6gv&e4Jt(2+Cv|yQ+i8l6sBEBln(X4axBjC` vUuFA4hriV^93teJ`2)o8Fx9tq?E>P`iNNo%Rwbv@{}eQ@0IJe6`r!Wnpk0a{ delta 888 zcmV-;1Bd+95sn9tBYy)`Nklc)RZTeYZ)dZ(?Lz5ns{gQWkdhbxhwD2J_$Zi z($2FJaBeCy5`siYk)439sXV!X0rn)s@_8TG2>`+*XsZ@~f1||X$Vc&cAAKOe0Dud8 zw{(*-fJ=p2cYiNB3E2s7DGzRx8?WsU@aW=1X{#2}{<9N6qZ;z>Gdf`2*8V@pP5>Dn zn%ZY{00|}$vJ>F>_tBIdg%03wQ+okC`uE^4~&FvZ8D0{}OrnSUqK z0XNbwVDUk-$%z&=kpBga;IDd)Ao`I!z(X>92zPS*C0OQ~A z#EtRVPW(J4!~`($VgMK#U9ewvC~!GqvK!4ICcqajzJXOyH+}MXA5nrJ7cZf9$_5*= zik`=%h(Z7tFQIlC`H;5HjVLjI2Q{ArXRzV2mPm+E&r1;{27skGw_vdZP;Sg>c~{=A z0l>*x0Dr*q=?m-L-AVhG;z@M?8PDM_enjYBgjhPj&-J7OI&1ksxWFYk03C}T(*C7L zq67M>0f0n0;Hhf)7)YW6fcC|Y82w8SZ3e)lKsbMAe*yNJKK5~9?%o@A8f4}00YgoL zM`$aDuW9g_2K$F=8jSHJ=hC40^Xuhc)8HlLaDO>{_8s2RHuh1Bl*9aaz9&H1 zzZA*KVcy<{z?ifg4zy1-Pml{(*@Lmeo!`S|Wy!%1!_W zjd3inSBsjt=|41Z4p- zURyP1BR~8D6CD1c$r&9mi~|#d(4xsG4ou*BaPoR^@_KNxZP6r!4)_Po4zi-ku!6Aw O0000GZx^prw85kJ&QX@Rme0>?TfNTyR27yb#lP4;QGcl)3w343K zt-}}L8=&BvUzDm~re~mMF!5{MCwmr@B%4&^7PwZF*eYd|loVL$>t_PR z^zw_+^@~eV^pOTq*>NerfK5uWRY_(^PAZZZP|l_(CC$n)r)07% zhoodhZjMz>VqUtfQiX0xYFc7xPKlCTT4_$sWPVl|bD%0Dy*Bz-474f9OiQzh3`#A| z&nYd*%+IqkH=4YMOL=l87vJPYE@kt8jQo=P+|-hy%w*5JlGLJtqSTT^utFmneXwS% zDkk@HiB7)HWoVA%Q7gxylJfkb>=3Z0K(4ew4hIzJ$t$?c>h~CM9ARK!n(67{7!tvG zH2i$Fu%k$w+O#mP*i|Nf3ttBMT$n7>l-e3&^Yw+}mHLB|7qD;Th+`4et+=>Y&ZgqC zyv9-kQQJ-ymh)m$wM4Vl8m@g`eb;<$Z29b*O|#!98sBXBx$pbgn)iDZr5*(DGudus zP{CMVU-b2Yf&{~!!rXf21>Jwu6dss!yX;<^vTVN4`Cs2Tetg|~;_MUURkizX*)xTG z6Pswc%VVp4xXPz}8Vny+ZZ`G~v2ja#W_i`l*g{zI{@s)Dj8ki0`)^*bsoCS_K6mBv zW%|!wF=< zGajFO%Cq9lvp>83e|XeXza#QS)0@B#F&q&$=U(P}soib8@Pum3zY`{coI56`JlXPI zsCRGH*}glob}d-&ZpKY9hL|W z75t6oxZTL}$#rIQ_tceBH2xUjrIoe&`>*So=7+a3U%MZy$xyIy*5s580YQ@jCo~`H z<6QA3X{(3lTeTw9s}s4`ym5Z~Wc`$TCg#z%BMz+1+Ldr?qb_4Z`PWpDPE85Le!Qv1C+@vZ9`URIe}>u{ss zs%_UDHoZL-mv=5r)bfCIjOG7eh6jbbDNDOmCNJq|V1HZL(QryHjQiKOC4Op|AIsje z%DiIRd1TjtQ|GjQyzh%%{rArXyZhbeW1Y0Dxu(t0&O6^~1qu#ssS|7XW0*H>Zhe|` uXuFbt=888L*^InDyuF=Wy0holk`MI^$CGCL3+ihHl@Ok;elF{r5}E)C9@$O+ literal 15734 zcmeI3eQ*=U6~NCpfnwt_3yf`I(?Z~Ux3bTcbc*hT zWQV$rDGf~^VUo1O5QjExr!aJgo5l@=I8KUj5~dv}g@#Gfw59DhCQcp7M-r1X-IHud zUdub4CNuqKZ$>)3ef!?q{k?rp_s@N=a`oMLIk)9d6qQ$A=Ba{ro%Z>{O!%#|wqAj^ z*`c!a3Pt7KtbMYmy-&@jDDJpaQ>WH>D>y+86!D^54~k-e5S&d>&gHQXFEj&HR}UJb zpi4h;tWU3#M3=tS;x&3hrJzwNYYl_y*3~saYqQ`G^~>Ek&KL(B1c1uxVgY|p;bJa* z+%E@zYs0i&7oVawyYwYmKwX`;QdcU6fzDE7H3&wlO=oiyF&3N6Y+I&djf{mhnrM^J zz?wL-ku$Tpu}kmHfxnz#(Z^MJ?ivdRC6~TYRYM$2N2AfAsHsQ}H_(j3;h>Ey&9VkK z!=SVTRX%12Dg_BA<9<9q5yDbPmE@pK^UK%E5!I#FYk`v2*uDaxWT2oj#tu@XV|<8a zii~t7BT-1&gd$;od}*RU13w6WpsGMSCZk=bQC4N8QJx}XQaxp0m=muz89U>81A&a8 z6?N4Xh+qt9MoXopB?RaypvaN109I{*TPeu2dsXtKk~6`RrkQf>ASO*=rfCvp@uQH) zkQ45eD-8o)mBTf%>~|+lS>-rFU1@3jROyz~NE=l4#8qI0E=DZ z9X`9ms^vl}Ug#pVF3oRzbYjHx?cmm{9RshID-S9v54Th9al?Tk39ig;wVUe&J1__g z58D?oTMfKPG#OaYWOdkhqmOq$Xp_uSD;sk?9v!;Qym7NwZ?*wmfE)LLDL0-7l;&(w zpfzC$wsYQ}Hb>iw2=`*H7X_05Sc9E0I}G)#*>2!%5HKT{M8@i1MOF~T_maWQq)=s& zmiHDU4O(uh!F>})Q+ba!-Vh&FfYw%A`tiP!?9^~-@^Z%86UPf$%XSM|)dSH$Gb0N8JAfL9_%H0t7D-TzEc+mf%8w;6;K9&j-;G zTnG@nNO0l#AX4T@FKy5=YwboE(8c(#Nx_Hy_pJv@O9KEeD8Fy z|Csjjt4=7Z@={dmS1GD}8%2HeDZCF+RK!S87dOM#U7w_=eEG3WC+?!C8HRFCNlom{ z{yl5HzOZEe!2XtBemMBV!09EUSvkdn*1Smml{3{N9q-n5@9B8(p4?l1G%I)AJB#1R zpSOMZk6+q;x})LJ+7NcTO5wy#|_Fn{=; zAGI5w0raU^Jw4p{?%A((z2V-FO*Jkm-n97TJAbqP6NfWoHw(t`{9$FwigTj`t;2eeVu=L{QT0zOIK`rwl{je?ex7GgN`Ki~6zWbKa(eUikBiSp0tgY?+f6EJ~4RtLu4CuYc(e6+0H%UUm)k6&4)o zh5jz~@4BsW?ZcMNSWk5H(F!g8r9$D`z3<)`Ty$g3G2OD;E1G}&gU$y$XWzQa-f;E# z%V+P_{i62Ie}DDB)g7*$tc`J}yS6UBkiFpa#)I7t9dRGs`o=-GI%Ywymr z**D$4MBmg`HS5+9$BjAH&)@RYCug1=@D>a&ZaO$;(KFXZ*DMgKyKVc*mj34-^U8+L zojCOB0oP{RSKdC?e)!GOdB3mj?cE=_e(6f?)z+Wx*y&D?qT!d$i7 z_QDHucONY;{C;fb;jfi!ZCBg+D%UQ2{&?j07fU{fM4p>b_~pE#S!dK&UcdK3{+5xU soEfjzHeIKr4I8S@Zv9#3r#9;1kq362+?{((do#Lx)oRb-m76>M3mj%}1^@s6 diff --git a/Resources/Textures/Structures/Windows/reinforced_uranium_diagonal.rsi/state1.png b/Resources/Textures/Structures/Windows/reinforced_uranium_diagonal.rsi/state1.png index 3799df51bf9225b991de796f1ca3d2d663373420..a6295e02f87cfdbdb818d6f0eac245b9e0e57445 100644 GIT binary patch delta 1064 zcmX?Kb%kewiV9GZx^prw85kJ&QX@Rme0>?TfNTyR27yb#lP4;QGcl)3w343K zt-}}L8=&BvUzDm~re~mMF!5{MCwmr@B%4&^7PwZF*eYd|loVL$>t_PR z^zw_+^@~eV^pOTq*>NerfK5uWRY_(^PAZZZP|l_(CC$n)r)07% zhoodhZjMz>VqUtfQiX0xYFc7xPKlCTT4_$sWPVl|bD%0Dy*Bz-474f9OiQzh3`#A| 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 A9{>OV diff --git a/Resources/Textures/Structures/Windows/reinforced_uranium_window.rsi/full.png b/Resources/Textures/Structures/Windows/reinforced_uranium_window.rsi/full.png index 10342c5705897d15d15cec6e6e15d43900b21769..7902a3672bcf78112d2f6461d177f0f151fc07c6 100644 GIT binary patch literal 3028 zcmZ`*2{@E%8y-uRv36vMWX>o{Vi-#r3`1g!eTys^Gb58R!^}5kEM<$7MalN7ti>oIMM{<|?TJeUcN7k>_N0M8 zB2sIe2Xrn^4g})E6J0$34?9}~juNbe#Z&wVTFl^(b(Ap^!CeLu04#(VOd`_|OcUt3 z2ZFm^GsB>ebr&GW1nObu2(h402@nG zg=zm1h7JL6dR(O}ncRH7-H)3nZk?9~;9);Fz~I{2hML-NP555e_xo|vH^$=-01+S& z)`k0ipLGRMB;aT3n*W*vB;uN~2ojcj*aXVd#1jIrbP@nX2GB_)W7vkr&&Uny&jF2L zzu-1ryD`GknLwkE=xdrI_rQ(UW%$YXkN6t^k6!_PH2xdl7)Svq+*+a%acD9?poUPn zb+yj-H{E}G{5#e^+-_tdfc!hazsx_Nes~uIiV83&)F9XOH`oyHKaanK*bwuFy4)!G zb>X>Hj|3aTzJEbTaGkc$0}x1X8odwY>LFZpAeZEf6BWZ2^1eFOD)iIB5uhqbxhFM#vAAIp5G$s zywE(8qeq zq>dK;z`VvJn7H}MeGM2yeEaT?vGwtCKKm)hqwjq9Ut7x9z`U2)SzdwCKUQ{X^i>_* z(Geb_7rSS1nKo$RRiHARo!2Vmbzp9yW_P;`ugIg*SN*Ig`uc{ZxjBh|8Bojc>nWP+ z&n-hZ9rx-0Vu!^lyG^O>_9uD(!EgAFIOX zU^`w%^{iY$O&+b0+8l)04sorm%NIP7)~ObCvowYG@)&o&yP#SuLD=x->LaSU{W@?Qb{rCl^>_Xfl{QCHKOB`+=3m z>fWR%mj}me3!kM)Lz?wtPn({;8~NEh=KYo|5xWz$eX3OqK`g(w*_@#eS=3e%!gH-i z6Z78JkW|hsM(~0xwN#zjE2VRF07dCi6Y-U{W)!0;&yb@{{f-(u26*x^ztnvSeLcOG z9`Q&)V09#3{CR++Q^JzP;I;9GS5>o~*)7CcDGyu1t51u(Xxlp?WqBE@LxUQn<<}Thi_;JJs=l66U1Plg8>9>V?lQ-d;-Cnq4U= zs;i)|*y}bm&oAx%>4ouZRCDE0LDrS5`oRwXA%XcOTeW#p-oP7+x%%ZJR~EZ2%Y;QH z+uv0SmuP3N)^Dvlr}2QDurJfcjvQcwyi_k=N+abby9Rtl!tGXu1)p!M10QoA9!h0 z54wIdej&7aN4%ZUaM%ZwPp9XQ+0ZgFk|g0gdnpe)v=CB-_tZT` zy==Fv&!cP`nruT#a=#77p+L{Fx`ps6sBmC%%=U>vPugPzcuRwXm0Q|*J=D|3+k=-c z9Lk3&i4j{o)!#?C_c(A6UnDN)*Kv?yi!*4R>MuSwM4O()SB(5lEZoxS2U}1K@4%;> zm2BXZh??BO>6?WX`7G>Au-W;U)DLUBGpcITOX~Vd{$aZK$?zU$aYRzhxvrRWK1}we zwmOrJOr!iyMP{!!dc^uYN~xJmfgk)z;&HeO@DYb*dcD_0-S(l`)%(Ik&0Fn==O(T8 zyieCeK}TIw&Muz)qnBou8mY?Wc1!b8Y$jN2>X&B)>wIlE%Wrz9ns6v@-6 z{1vW`ok`+h?!Gmdytz((BK^;FTA6piFdSVY$@t^)18;D1a~!?EQNy`29A&$^1J^=h zDOh>3HJ%U6;`MWF#Eu6Q9!$O4fD)21Pq%O6Xah6TFV$5?{X&&_LW_`og|1+onjY;p zXiutHC@au<$2p8Qt5yuTFCrr zV3@wKtRQxDQ0{HCb29I(GVA0LMZkv97il5Tw=Wrv7e3;UM zwpI(sq*ICt`eHloLsU?+f#!)yrC77F+gsWjKi-D=cc$tbTjm=!SCi_c_1?5i3V38j z77xu*)H24+6g3^PeRAL`XEl}59zGn=p_6#yirO{y_$rTg0L|@MDKBR2j~Z=hzmIM1 G7x#Y$Xch?o delta 2053 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 delta 2355 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 delta 2331 zcmV+$3FP+s8Kx4DB!3BTNLh0L01FcU01FcV0GgZ_000QsNkl1YitzP75?VV z%+Ab?7q9UPdu^|fU9eIc7Gj$fm78Fr#1)SimxLBoph8lpqVS_q)c{gy)CQwgO)E!f zjffK&wKPy_r~nBNHX)YKf(e+|N`NjxYkU2`I9{{f*F5g@2Y;AAMIq|Y87q80ujbBo z=bLlSx%ZxP8N)DOCm4o-^itIhsVn?dJZb98R;`ZdeP7q}|3XG@+mhGD=k z3=G3Sho>{O^JELh5<=EK_o7yvyO^IXc}$Z}2LS*olYh<3Vzx&eFxDsDp%?;zrjCJ| zK|l$MqyhhxJTc_Er2xPm+7GhZ7am9gz_|aIDQerN001DWvY#FbW6!$Aq`#xsjr0@; z7eqKABaJ$}=bTcYV#FBYbTY*0Bv=(S($DB@go`m|sqMFb1^Fm^Pe$36Y(`O1e4zLW z#RoF8xqrehw{1N_03ZP%XU~J(?zIKY(c3NncV*1z|E(kWA$svE!7XemdS2VT`V+nF zhew1LkJp|4fAdd|DR2jbB`mW$et}v_Y9-mj5G~6xiVmg;0MOq52>@W$Uor%%_-z+J z>I##-hM4N>EO3NK*HfqFEDNw3Ui;o8^wt$k3Oh@a+ zw+&xsfx}APN5N7j7_1&j^bGZ)yLvz=YJZdYM5V{lo!`S?ofG`gcnSb&3%?5h=vzIR za`oOaeWGI)mQI09&I+R6ng6!``6-w_5js(Ke97aUX=q$Qn-2!~-Ag~lPu)M!e~dEe zRMY21tTfYh3otFf&5sHb-gc3MYLgHARd2gULd#+d0NQMvRxywA{?pGejtW8TJ%2gM z^}qflX4Z|Fr8f=JQ^2js#>8{1UUJ^W$rOnJ)3MTd>#%~&?1%D{K^l}maO0T6OP&%3blG-ni{h3|q`}J)AK)QY# zbRq?0Nb^tS%(}cPbiMj;aen8DFBAZ_uLn#|fe1fFWMG@sfs3)2>mvwnh)%mvMU`G0o${q185 z`B?7qL=gb!$rRH!zh9gAP9z-wCK18ikAKT7zggJ28%zB2yq)v_oKT|&W2I712$WM`7o$vlGrOE z{8!4;kj!;Jaq_+{uNYdZrhjnLosF0qNKn#UJ2E)GZB7OZA?7_Sv%y!x$^%s)HsOhe zLH5jXmrg0&wrrzTQ&63LHw`;ev?t6zA_KcJEo&nEdom7>M4f^|2e~!{874rAOxP0W>tOa5P^C zsDY(dpeQN6?1gM*xM|dgEwJqP|G&bt0ADAE-&S{I3H~-i-8AEQHbZdpAEGybEjn^m zj)`XZ&BD@k!0z}3%6}4;v6}Z$uclSmy*=WWn#xr}@$>=u0$>J1lZa)zg$0xSR8zs(%5{8j`BB$Ns#4>G}Y( z$So=U-OZx~iif6=t0f2dZK1bPP4Nzz^ZhaD>nyVNmb_=GSlIS36fe&*xHgdozN#IV zswJ=jwhQ1mA0}FTQe#hZ++boDfxsXc-WW?+#c#U+002sjf!e70#{ON1%!@o-rLt3? zR5#+O6t1yR1Am5L*;aYl2;l21aI|iG+bHSCwDgq7b^#KV9$M5U^WD`0O3zR)g4IKb zr^*SsdT%j(t0y0*9hj;mumZLVa382nbz_sW!qPF>eq%%{&14FjcyZ~LXPEI+MBUx@ zF~KQ`G&HWDZFNT;TYG>YOf7_L7XX(A(chSf-jkz-V}HG%`mdL=feoJ<&C2N*4(Ia# zi1(OmJhcAcKid8m*e?J8xOn~9RUY=Wy<5e=_il_LBFNCxBseIbgbgi9h<4PQ)JrJs=nIhAy_ptNUFK9EF&A2aO(Y~Kz$>lXolZP(}j4HP9zx)x2KNm~E_002ovPDHLkV1nQ1 BU|0YE diff --git a/Resources/Textures/Structures/Windows/reinforced_uranium_window.rsi/ruwindow3.png b/Resources/Textures/Structures/Windows/reinforced_uranium_window.rsi/ruwindow3.png index e10cff828eaca524427883090f88e0a16bbc1ae8..26f6290c6b41829a632c1e8077e6b0eccc29caae 100644 GIT binary patch literal 2130 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 delta 1112 zcmV-e1gHD95bX$%B!3BTNLh0L01FcU01FcV0GgZ_000CZNkl7{~uJ z@9n<6&2HHw(!O+;y}0yHnh>E40SPr#v`{apVlTx=dMHZOQ?y_~L91fC6_g$lsFZ?| zm`ep)thFqKU<<~i^q}iy*)`kHB%5TD-S_s*jEAt&g1ae9nSY7o{jT4>{eSsqX1;G{ z<`E$Tbh1009+|(A@KRzYx%c#U;jfEhwc(|U{;pRRt(Sg$@#bdFf0O>|2N``+=HVv> zXFP`$TBOP{8&GGuFYgVGo+a7C3!X~dEn@(s28mb}_OciOAxxRBDxs!O zN|M)Oq4USjAU+dUnv-?|yq+YtCvB7U`~Du=L2qvdcSc*b&mtI^eLyM$Ww(H`&p6{Q zukzxFC0CWcb^{)Q8q^>c*6(noqAJDyi=Yn(`hX3BK7SzS1A;z4OCLaF_XA$fzIAl7 z&s;rn?a=&0n>*4vXujzTh4%gRnwKLhV%N)s@cnFdSSkTY)QteI#)cOzd!_2K$cYsJ z&Xm^sMkq6&Ufb)nJ~bY-R`<8--Hw7n1BydsKb`5YyPQsRXOiLEv9+3gyP$myQkp>a z@PaoudViKo_vMw=`evvzfDpEq#Yn`mK&e5L>28A35fGn=)APsAAbC9&0;OBR1a*tx zXp7a`+rjtP4p_hM+mp8G^(3`d0(Fbvi6z(NRn9o$1(f~DK-rDVKF~f2lum&Q>vy=Z zG5@u%{&j*rK$TF?2O#JJf<7SV1GZovAiW>3JAa)XS?_#Ggn!LHVrJ!Fg2(PI5CCWv z*S#MgeLrCSO2V@z?9k#l%LC{Cx|#aEC6xO#R0RNgGHNx8>qL4ABzTmz4HztSBOan= zh=5Xb-%5pZuU2Y+K>-8J<9d;v0&8C7%Tje2e^-il``gd4?z*^m@)I#roW%>t=fF4< z27fhZqj+Mcqjd^M8}RO*@1FyJsi`?y>MHR+j8&2Txjmfio2vl8smK9p(H*o=Ts(8@ zL+QUl0%-%t?>!$oV^Onsa&6;4QwRe9oUy1`Kjd^SwOWnh;^1!|NhKi3lc)k;$UJ{P zn|)6z0ZF8*z~fwH+sbHPg>@4cpgRHG1b+tTPCz$-0lE{=&9*l{x)YS;aqbs1L-u`v zZ9f7619T^#o4^3w3Fsy;Kz9PV+4cr#e{b;Wk!y#fz95VL_luMB6K$@{rmC#Ib_3pt z^i!M$pPHJp9@#d3W3B>3$f?KyYMtKEFfOaF{kMSbgB9%tB<~&l3;>K9rkQ_!wNb`7 z6Wy6)_@PS_Jb|d$C@%Kh{6I!udle|qGGClzMy|h9<92w)swXdahC e`v}l|y#5b0A$=t}Z2Hsy0000DWwvz6(W%#GT9eF_^MOnFkkB{R}&_kJodvDsRb&j5|%3DIJ;kd zoFW-!;PLiAQ)4nup-OOx^C5(ZxDD-?a1P+G19@6hU(D99`4RIil&UpVW!dICA?EeXxuVkb#l%u} zgxD6u4(72log*%!{~W~N+2$~U*E;jPA{ad0oWT1*FM5`FCk%COTzG(4-jk5nP}k6K ze&5b(;wUO z{b#D{<;J#MBin8@HB|gMenxV;G`k}p?mT+*!n^mr()$>`$RjLemakfKb<^UV1Ztmj z8Fs=y{Yx!V-@@FM+0*AsN*(*5-f)b!cc|!-f#HH;t{Nj#%ktU|mL58}V*NEs%+>Un zdG$xeGlupR5Dr_}M_Nx(!Gf`UTgWRLOJeT!TAIumtn!QJiX`tv`?T|J2F%ctgobiW z{5I5{J zuW&~UU6eHX&73rddZTi$IIZjVtcT-WZfIbHV{@}_OPtXSFN@Zl-Za=marg2#JhYiz zi$Ul`qq{bLA3oL-w%jFP+f6My;Z<4O!U}r9NB5}JXaCx%$D*>(38`(i#H0$|Yqc{d zIoS70P93>DwsPN5Q}uE>rsn=Azki88(4zqt#5;9fxm=Qu4zD;{`!xykfsg_i6|FQns7A-W&&S?v3$|X&*c_QJl{M;tyjrZF7Dd znK5fmNfx1`28VfSomzJ&kJR&}LiFXjIal|>E z1hPP|&EGies04y1g`i4YUBMf;^Lg`=AezLt?@lK4wlTN|V|Q`Nog zoz*|}NklB|dg!Gsv=u>Qm|k!w1|hr zR@fGd3QgCqm}T80_(3$TqHzPR?(CXr=6iZ5y-2ccS$&_w&VTPXF#P}gc;0zuc4sKp zbpey^qaPk_-zJ;G>bNs(f6_L@e1B(1iqL0zPiy^S1F3&I|HrjQf2|~+t>ola!9?`2 zJ~{T33A75dr5O1w^^M|)a?M>Ki42K+nnXxBhNK7`iL7+Ob1iJw`#tPp9c@xMze6e? zeFApX4A3{VDSzmUZiM}(4io?=c3*UZ|18WXB=XS(e31K61I4A+q|Zs+o8JmuUzi_% z_$Xf_m5(lJ!1m=*G-(4ZTpsu5WR=mMU7d`~o0O)VS({XS%_)&js2 z0QfIEz^edVz}DaT$1wBJcL8iX0oVnw@dRKOz{V4RU4H-m(oW&P20%Y4?*bty_|Ca-TOJH?# zFrXwCN`Lo2NuSvHm3yO*=GO;1NX0J;F##uUPb!fuaiL8+`aEUwj_X ztnQkI$VV5y$;>wAH84*(Zqpy6Dl7@HU0|+Z?$22vZ}Jpt1VTErO!G`zQKU%ZmxIUz z^nZ^Hq!O`sxE27;LiXxE$Nzp9BGF)Zh%Et9FFgET(67SScml8sVB-nEE`W_E0J{J- zRWE?T{$2q4{er5W08apR0c<=0*afih1Yj4yrs@Tte=%}ydm?74n)>qbs`+GQ-gFbOc$kC)^nWFAC!o36cEc`a1Tb8SU!w;(d0u{llSGL` zKKcZVHhwGKPFLLwi10!}Z)oilLJKA1cXKkWXxj_-4= zleZ@oQu*i;FszO{d`e(^tjE&6qbl_dG# l1z%1ZlsB16?F_GjzW_RDWP5lu9N7Q>002ovPDHLkV1kTE@AUux diff --git a/Resources/Textures/Structures/Windows/reinforced_uranium_window.rsi/ruwindow6.png b/Resources/Textures/Structures/Windows/reinforced_uranium_window.rsi/ruwindow6.png index 1f9ba05446a1f82dbfcc86e72429419f5f7f490a..9b0463bd4cd0907ea399eaf49518e24c19a7857b 100644 GIT binary patch literal 2102 zcmZ`)2~ZPP7=92T0SiF^E0jtmXa$jMKno;IfM5_KhZund9Ti9dF61J+G(n|AYs+D) zMVJC2XeeGxfPzZ3rHUtqa##^-MGg^AEKpGjQY763MRe?&dHde`_xt|id;iX+hXnhZ zncA8H0L(aR*j#M&(M^Ie_AG%DI%0>Dp0zM=Z3B^JQia@RuSLl5_6pne5p#*s)2PO=pdxO!a z@1=2MD1RlUl%EpI=T&`JqI`W^1QkHD0FWD%>ghstb8(|VGxcHVGX#7(3Zo*SUbvZh z^a`>>=-XBuUMGPF)+tLDMM+|rWTlHh7!#E!Ldjn8LsXUS28R30Cyzld2X{x9a0pJ_#Bb?9{a>($5l z-^-K%&3sE!V#zE#lEFQSH}Ye9hyh&6{ml^d2f5< zj=Fmzr+fQEefP_MbNAeISR{AK|2}_tUNOsV$-E_TcHgyso_Wlsy6=vy)G* zzrDH3D5>+&-cS$iS0_79+Phyc!5?`v=xI_l)n>aTe8<4`aCL8aL+{^(dnBhi;n7P5 zxfKszPDtbaEwxle@_7Yt&(k~)VDaE$W%J&F=f2-kgGXeG`s#=vZIAO|>$BxUp6QeJ z0q6d_l31xNjnh!_&csn;GL;K|L6ZdXlm7LKvUd4;Pk=vRT zdVDQc-Ca<@F8jE#c%3JJFaN|!d*Rp~($Ru`lnPxkkd1()#M}&IDN(<(IDn6AD~K6u z>Hg&|`dl)^v=}g7TxK<#W$pqi$`{6M_-b+7oT`0F->s?p8{IpCX&1y)^^#praQ(!h z6T5EMstWc++-@{e+3fSa{6cLEXsWPPg9Ei@pliHlbk{T7SgI{(HT+9{qhw2&F}QQ+ z5P2L4M-d$G^qPiY!Oj5Z)qmbi{Rni;(b?)APJKcD^uzn@A0+6C^r@@I9b(kf<3=dN z$d1(RohiQy5{ur|SLg;BtrYHND0!GXI)NDhu%oU3cqVNul3RSHxk% z9hH-3Yx37`@n+>I>H_MSJ53zXraX-#}?T zw+`XfO%kqH^^WYB@8|F|0e#qQWcB&{M@>_do?GMot<@;5C?@o58r!YjIbgwDmvmQL z3r+Tb;WIVV=x9=&(ZYJ1Q!#n2bHz`R<>rI< znVLK8m5-~){0<{c;DP33J1~-zsQjak4T#y#lFXMH>W@`j4l3Hb=*>%Rrnm0i5AdMP zqHwsUfRH=vTo-r2(m+FK8hbj|%W%(9-=cuH8+ZrJe$Y-5I+s*NknB{!NtUdS(+&!e z;jO~a%^~4A2_>42?(2@Rh&MhgDjdhQ*ATQsM{V`dxjyLFx#HpcXxpPD1|FPSIZkGQ z*Ap_c*PpM{T3sg-I*qQa$zHuZ^v=(HCf^NYL=_%YkHx3nUiPfU+D4|{=zq6&`B48w d2hxP{C9#ASePyCz@R;tO&G8Fnm-$BS{tx_6OXC0l delta 1108 zcmV-a1grbD5a|ezB!3BTNLh0L01FcU01FcV0GgZ_000CVNklA?{od_tC|&SP3UxaM@{ zQ=!g87c%*s#(!eA=E~AnZooQ|{j+xV{3t05F4!`4H;n<5YNScmk?|q~gm}_)WeGKe zQj)$A37#E3iI%CD)SQ$Xu-cbk#<-z51D=~S66onmviJpk>nwuN`(Eru1 z`pxxySKpn_wOZdsKh!>YEgRfDGi(=0h3_~p8+tN5^RZ9@g2)>Iw&RVIFWSqsDlhU1 z2lJ%X`+7(-V7<1l*ZOoWtd~2ttKE)*L<1JHH8+#rX>=yK(49|(iU-%6<~xs-uR&51 zC=4#x*?;q+WU_x&YOQaCJOc>vGG2r<={hLYh&0^|kU9cdregH$@JXa^M1r7nQ!IQy(*Xh$2%vFXEy7b^&8mH~T&tpF&f&!6)A+}-F!sS${K4E526w#& zkAJ&7Kr~t}o{Y9BodUuJoG6Tb2>|ydN_45K%nE@Op1Ii?D)c`x0pO_7OLc0{dU5{N zZ=VVO3ju@;AXB}k;$z#i#rLhJ2b!D*03bfLOm@xyrVgQN9YR#y3E90)MLU4N#qcYJ3A!C!m@wZ-8(oD9Vf6FKC45 z_X1mf1o#H1PCzxj0jd*Fjcr^WC>U7138-1xmEamd2gH9|L8Fxi$x5n0)6?JDoFvfX4t2jpJe{9|5Y5 a*Z&1WAAozTGh?X&sHg;q@=(~U%$M(T(8_%FTW^V-_X+1Qs2Nx-^fT8s6w~6 zGOr}DLN~8i8Da>`9GBGM~RsBTId_|A5Z7NlCUU$t=l91qU45Kj08_%qc+?1*r!G zK~5$pWUX=%^U`gVDs)p)(-KQ_N|fx1O3O3zQu52qZS*0^P_;uuQBAec$Kn7RkhiTO zgHnt0b4o!0Z)a{~0}cxmK|~BdG(=$2fGmivAs{2aBp;ZdiZYWu^GZ^S3W|V<3v3_E zI@~JI%|h56nwME(2QvUo7)cjW8n&1>p2fp7V~T(C>V4&`{oxH} z8PAOm>{B>9pK*($^?b%}teO9K7VzHs$+JP<<8wMg?uB#d4YiK5?3pu~%j}rna9{c( z=^(x3vt&a2glFd&ZY`L5p5b?sNj=*Iwzq%Y@*eol9>5&-Kfa)vS*t-Shmg_pQ&oBD T?pz4q2bC(Gu6{1-oD!MTT?wr_|5y`QONt!RX7lrC}LEltVCs?gGsQu?r#&+!gTe~DWM4fngUnA diff --git a/Resources/Textures/Structures/Windows/reinforced_window.rsi/full.png b/Resources/Textures/Structures/Windows/reinforced_window.rsi/full.png index 34c51d7c3d6a3b995f8df92ed1176e988a2ad8cb..e8b90728e41ede9cc5474ce777a73af21860612a 100644 GIT binary patch literal 3041 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 gP~8b=t~q|-Un5s!UNOU55 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 VP3BDPwan#T5|pj8O}-T-`u{!MqfP(- delta 2218 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 diff --git a/Resources/Textures/Structures/Windows/reinforced_window.rsi/rwindow1.png b/Resources/Textures/Structures/Windows/reinforced_window.rsi/rwindow1.png index ba95fde9e59c54dacd0eda155231ef640db07f41..2c1d944a619cbc07511dcfbc95cf3dcb4129082e 100644 GIT binary patch literal 2163 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|_);T0(|mmy zw18|5AO?X;!IOa`XMsm#F$06fED&ZCw^H21z`&fB84^(v;p=0SoS&h?X&sHg;q@=(~U%$M(T(8_%FTW^V-_X+1Qs2Nx-^fT8s6w~6 zGOr}DLN~8i8Da>`9GBGM~RsBTId_|A5Z7NlCUU$t=l91qU45Kj08_%qc+?1*r!G zK~5$pWUX=%^U`gVDs)p)(-KQ_N|fx1$}{s)^2^O_^dYKHbwfl^4Ykq7V!sW@*H)21 zsm1v@rJ!)PGcq%=0fz;OC?WhAD)-&xVCIlS7%^gY4LP%45?sz8x@-&>Mk;G=H0#3$`O;|yq$P*g$)Bus@8f1 z1!nn*xCFd#u3Zt3Q@g=QP_RBqu=eBrr9YBdr+GQZzj1bquleA1biZ1}?d-)zTzs-R z6&D_p7I}aE-1y?f%L*L!!(Y)_hc`DViT z`A>d^+*{dsIiy~kE!yt?-gUF1=k-g!y|2vOW42<#`TD{)kLIz53%TVS6l&i&<>Sua zx6gYn9b0O-!+-16S#|%WmCC<;V(55GJb>S*F~es{LeSQXm9u~To|PzJrPiWw=dNI9 z?Twu583%PwJr|FSuVh`a`C9p5|4SJPQ{CF@ZTdFdl=)S5yXxBA+wEd!*0}L4J@X;q z!)O1#seNz7Zq)y}CHF(LdYyXbw|630hG#a(*1LRpx!E{jy4ZU#|LI+`lqAedXZ`Jr(c%{k%MJPVVO0wa$5V^%r_STRhc$FqetF z(#X;6y~qtImA>N|>b0&-F$#1mXQFH9e=lj2_S~IwuJ|5By zh!6CdW&eAQ-;3YJ=XjVXdzJL$sh&M4zkZ9);RBafB}Lio5BSE)A(qE@Ro~3TP=GDL z`SjA-2}cg^zxAc_Birq-_ug;3ZLU;tD~J0HPjb{E!Mo@GpPt@bexP`j-b1kyL2keG z=3ezmJG(vicH)$vBU!K4F1#F2Mx!W&*)zg?s3=>9M`;qAW1_ItBF zCf{EZxxM1}MW5o>rTcazuG;wYx|#N4rE9zDou7nm%)h07hiU!n1+zEb;hy__?Ul(U zr*BNzsrPx7^Iuh7h6hX=?yfekb}zHNQ+7>f^_uE$jxAamOBe(0Z8=qFl|SW5Sh%8v z>M5ydH~xQBS-SQ;`-Uqli@ttdvzNUusm|q>s_JDuUWT5D(g%6m7pr~RS1w>z%f&j$ zgh3(k`~BT1kHfPsJWko&*v-O{$-txHH`BEE@s>q7OjXr>i;YXZ&WVfr-1up-gA~Ju z`H9yapWJqw*I2Lgl+^4Z=f87LMLS9{TwvPU+`qz)<5-VptoXHWyO*d6eQKD%t{?&; zTWl7*sA%|9EWt8$*<1HDLc9;1=bO3tZM(lwIQH+kr|->Y&b#(u^Zk!U-!78(;^J1a z5u7NvrI9CLO-(wLb3=M7!QH&XE3uI5+uvrr*!q8yG0FquH zdE!=0AOi!)$OVE8VGOevGuSsdOz8S{+6-(DRIq;apH0uXbA$O9?h9nFED&u-JCJMS t_LQN;M&SvgKez1@Mn!&($_6315B4Fd?c5wSh7q6&-_zC4Wt~$(697C$OPBxv delta 1128 zcmV-u1eg2s5c~*`BYy-#NklgOMhtD2Tdy13hj@jttp$flx3}@yVSk+ zoO@;_ezz@r$eZx9nG>Gx%ei-cXU^|;e#|hR`Q>M>vi^E z_UiAJ?ZEhFL%8RYDv1&{X-NqW-@Rd(rb!uNgm$!q(uzuB%pi;zge0h5d`d^U)2Y*iz$8pHd6`N&yS2tNaJDYIMrC}IsFnea&*w1?kR9?8b8?K#Ax0pF) zx^M`Uk-JSHb7p=7+NY(DWwv3k!R*Jktk{Y1uYC%%Jna*;C#qR^a<=oI5V0utB>ifh z^Q7*4$ce?|pO1QZB0JW{?rZibDGo(5)Z= zK8Qi9f&};=2CWJb;DZ>nYQ!f1O@cemG_At)|7FdB-!T0t#l6Ca9|1uEd=P_H1qtv$ z3|bW=zy~pC)re038ic0Kn2joFb+xykN?KSDLYKsfw(fVH)t)ocOV`9VF{G3RT%j#( z$;x=!i+}px?L>B+LQjFbi7BjP<2Pc|qfUDaV^)%3QhD#Tol*R?Yg-nbHF>;|$gVp9 z=m1_v9Mr}}M(P;c#s+c6tCnS*_>mRG(SOrkq+gmMs+AmlkNztr~F z?GHy~gmWo8p?&y+lqCRI0IpYCJLBK`uGiS(GIG(In^-AJz?UVfJ+G}fIVUTVz$%ck zXn%R^pRU{5QCw*N$#V+aU#kw&0ZXKIDN6vQl-op7+qMZ~OgjO-lhP63{rwmFzI+3D z)!bDNC@&RCogfE9oll=)TVD3Rdhfng1R z5r7qx`c~=eLjo26CIB`7MgUd-W>Do{djg;)0JQ6 diff --git a/Resources/Textures/Structures/Windows/reinforced_window.rsi/rwindow2.png b/Resources/Textures/Structures/Windows/reinforced_window.rsi/rwindow2.png index 8beafa06dbb5d13694d1414440fbd8abc6a2d5dc..e1459332aeee24053ede0485f78fd9fa06a162dd 100644 GIT binary patch literal 3349 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 VP3BDPwan#T5|pj8O}-T-`u{!MqfP(- delta 2218 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 diff --git a/Resources/Textures/Structures/Windows/reinforced_window.rsi/rwindow3.png b/Resources/Textures/Structures/Windows/reinforced_window.rsi/rwindow3.png index ba95fde9e59c54dacd0eda155231ef640db07f41..2c1d944a619cbc07511dcfbc95cf3dcb4129082e 100644 GIT binary patch literal 2163 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|_);T0(|mmy zw18|5AO?X;!IOa`XMsm#F$06fED&ZCw^H21z`&fB84^(v;p=0SoS&h?X&sHg;q@=(~U%$M(T(8_%FTW^V-_X+1Qs2Nx-^fT8s6w~6 zGOr}DLN~8i8Da>`9GBGM~RsBTId_|A5Z7NlCUU$t=l91qU45Kj08_%qc+?1*r!G zK~5$pWUX=%^U`gVDs)p)(-KQ_N|fx1$}{s)^2^O_^dYKHbwfl^4Ykq7V!sW@*H)21 zsm1v@rJ!)PGcq%=0fz;OC?WhAD)-&xVCIlS7%^gY4LP%45?sz8x@-&>Mk;G=H0#3$`O;|yq$P*g$)Bus@8f1 z1!nn*xCFd#u3Zt3Q@g=QP_RBqu=eBrr9YBdr+GQZzj1bquleA1biZ1}?d-)zTzs-R z6&D_p7I}aE-1y?f%L*L!!(Y)_hc`DViT z`A>d^+*{dsIiy~kE!yt?-gUF1=k-g!y|2vOW42<#`TD{)kLIz53%TVS6l&i&<>Sua zx6gYn9b0O-!+-16S#|%WmCC<;V(55GJb>S*F~es{LeSQXm9u~To|PzJrPiWw=dNI9 z?Twu583%PwJr|FSuVh`a`C9p5|4SJPQ{CF@ZTdFdl=)S5yXxBA+wEd!*0}L4J@X;q z!)O1#seNz7Zq)y}CHF(LdYyXbw|630hG#a(*1LRpx!E{jy4ZU#|LI+`lqAedXZ`Jr(c%{k%MJPVVO0wa$5V^%r_STRhc$FqetF z(#X;6y~qtImA>N|>b0&-F$#1mXQFH9e=lj2_S~IwuJ|5By zh!6CdW&eAQ-;3YJ=XjVXdzJL$sh&M4zkZ9);RBafB}Lio5BSE)A(qE@Ro~3TP=GDL z`SjA-2}cg^zxAc_Birq-_ug;3ZLU;tD~J0HPjb{E!Mo@GpPt@bexP`j-b1kyL2keG z=3ezmJG(vicH)$vBU!K4F1#F2Mx!W&*)zg?s3=>9M`;qAW1_ItBF zCf{EZxxM1}MW5o>rTcazuG;wYx|#N4rE9zDou7nm%)h07hiU!n1+zEb;hy__?Ul(U zr*BNzsrPx7^Iuh7h6hX=?yfekb}zHNQ+7>f^_uE$jxAamOBe(0Z8=qFl|SW5Sh%8v z>M5ydH~xQBS-SQ;`-Uqli@ttdvzNUusm|q>s_JDuUWT5D(g%6m7pr~RS1w>z%f&j$ zgh3(k`~BT1kHfPsJWko&*v-O{$-txHH`BEE@s>q7OjXr>i;YXZ&WVfr-1up-gA~Ju z`H9yapWJqw*I2Lgl+^4Z=f87LMLS9{TwvPU+`qz)<5-VptoXHWyO*d6eQKD%t{?&; zTWl7*sA%|9EWt8$*<1HDLc9;1=bO3tZM(lwIQH+kr|->Y&b#(u^Zk!U-!78(;^J1a z5u7NvrI9CLO-(wLb3=M7!QH&XE3uI5+uvrr*!q8yG0FquH zdE!=0AOi!)$OVE8VGOevGuSsdOz8S{+6-(DRIq;apH0uXbA$O9?h9nFED&u-JCJMS t_LQN;M&SvgKez1@Mn!&($_6315B4Fd?c5wSh7q6&-_zC4Wt~$(697C$OPBxv delta 1128 zcmV-u1eg2s5c~*`BYy-#NklgOMhtD2Tdy13hj@jttp$flx3}@yVSk+ zoO@;_ezz@r$eZx9nG>Gx%ei-cXU^|;e#|hR`Q>M>vi^E z_UiAJ?ZEhFL%8RYDv1&{X-NqW-@Rd(rb!uNgm$!q(uzuB%pi;zge0h5d`d^U)2Y*iz$8pHd6`N&yS2tNaJDYIMrC}IsFnea&*w1?kR9?8b8?K#Ax0pF) zx^M`Uk-JSHb7p=7+NY(DWwv3k!R*Jktk{Y1uYC%%Jna*;C#qR^a<=oI5V0utB>ifh z^Q7*4$ce?|pO1QZB0JW{?rZibDGo(5)Z= zK8Qi9f&};=2CWJb;DZ>nYQ!f1O@cemG_At)|7FdB-!T0t#l6Ca9|1uEd=P_H1qtv$ z3|bW=zy~pC)re038ic0Kn2joFb+xykN?KSDLYKsfw(fVH)t)ocOV`9VF{G3RT%j#( z$;x=!i+}px?L>B+LQjFbi7BjP<2Pc|qfUDaV^)%3QhD#Tol*R?Yg-nbHF>;|$gVp9 z=m1_v9Mr}}M(P;c#s+c6tCnS*_>mRG(SOrkq+gmMs+AmlkNztr~F z?GHy~gmWo8p?&y+lqCRI0IpYCJLBK`uGiS(GIG(In^-AJz?UVfJ+G}fIVUTVz$%ck zXn%R^pRU{5QCw*N$#V+aU#kw&0ZXKIDN6vQl-op7+qMZ~OgjO-lhP63{rwmFzI+3D z)!bDNC@&RCogfE9oll=)TVD3Rdhfng1R z5r7qx`c~=eLjo26CIB`7MgUd-W>Do{djg;)0JQ6 diff --git a/Resources/Textures/Structures/Windows/reinforced_window.rsi/rwindow4.png b/Resources/Textures/Structures/Windows/reinforced_window.rsi/rwindow4.png index 754af67ca375ecbe1cce1a93a6ae6de253280ae6..6e9e88d1e901453cc98287ba3b048039ebe4b229 100644 GIT binary patch literal 2172 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|_);T0(|mmy zw18|5AO?X;!IOa`XMsm#F$06fED&ZCw^H21z`&fB84^(v;p=0SoS&h?X&sHg;q@=(~U%$M(T(8_%FTW^V-_X+1Qs2Nx-^fT8s6w~6 zGOr}DLN~8i8Da>`9GBGM~RsBTId_|A5Z7NlCUU$t=l91qU45Kj08_%qc+?1*r!G zK~5$pWUX=%^U`gVDs)p)(-KQ_N|fx1$}{s)^2^O_^dYKHbwfl^4Ykq7V!sW@*H)21 zsm1v@rJ!)PGcq%=0fz;OC?WhAD)-&xVCIlS7%^g>GgDR45?sz8y%Y=5-zgu`?)jk)E20$Q&nu+=4sezvNAf` zQ)KDdNLE3SUkUP30`+oh0=zU|_Ak96zItufm!)4Fr!>@FV0VnKDOeozUuaF~WevlL zYEelZD_*v-eNV4@_jZo1GS|(MFV5cCt+-i#bMg7Vmd|&mKb!adjqF+*(N5~S-%ED>6a0K?q5t9N?{h7z=2lhT>*w_eKkmD37pLn*Yxa{e!V6{h4CJY)}2Pb++ zv>F_iQ1)*5Xy6ve(2)CBee&H~>hfC^U$3`seWg;eVP)FZMP-t*`^y|-Kcsa>M#gnz z-S4`1@yN`bpM_-PUmkv{yLM-ft8a7AtgSk`3a*X(tf1$VgLg&k#JNkO{75-V` z*>9Kc`qI-H@%&%xLiWGgZ!gb&zdYuKQO45}?j3do|9TuHpD_F}Ig@?=5JQ2*zQaEi z*%=HQ!d?HaQs-fK@Z-SO#?Q>(+hrJ@F#Rz)lfB$!f#`b#hz_}KWG z`8oT$_uCWWev7j)Xt2b{Ti6%WpJ1#Ay>!0n5CcOWKTO0y?|}c~JzsRu%-y5$GF>*2 zp+OL0*Z0dSp1+Kqp#=6D2P?>@K<{2W%6R9s!JGH)tEX+)c<}!G$iTQ&y%(=|)bFb| z-}$D7!JOfC-~V0TFJ5gCi`{uFMXc5-KlrZrmQB;P{^aco2~XcKVNddL>-#q6ciCPp zoj-G{_)8lngOzc6ubui+=zQ5kRM<&C?gg)F_z_-K;~lPfpTs4L)ovG5J6NrjpHnf% zZShKzUmu?fYs@~o@NWE@6lUkc8L7#afo3-_ahin@pIWnu>n*Jo0RR>l0b)>$TipQ~vIdZ@hPrbJmZg%}Z9tpY;to zeIjV`!t2R9+r`hf6@81Gzx(jxX|rRdJv_JLj$FXy3p>ueJahVLo$s;v>(bXV&9|@B z|7CB^5O?WOp4&&c;^No0yL)~MelYSdyw1s>@$9DH!srK#N&$M$44L@B+}m@$GrV)? zD4&+X9#njfnTeqywqo0Mew&1C=M~ofYh?eRWO4iU`AYr?avV3Mwe3Gt2DP#A zSs`)PvrT;O_CWq@sk{|^T6sl!uiqZKB+m#m_!8rdtA&;FXCB#a-*u&OW7=Um_oEL~ zRu<2=^sj5eGz}MB75i;}@2;=hgTe~DWM4f_laR- delta 1110 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 delta 1110 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 diff --git a/Resources/Textures/Structures/Windows/reinforced_window_diagonal.rsi/state1.png b/Resources/Textures/Structures/Windows/reinforced_window_diagonal.rsi/state1.png index 65254207165b957f648e77219eb234caf994a8b2..454ab882de1126dfe6aa1e4300c11756965c38ce 100644 GIT binary patch delta 991 zcmbPH*T*wK#g?%+$lZxy-8q?;3=9l>sS%!OzP=1vKsE;ugTSTW$v~2`z$3Dlfk9&y z2s4UXDQ;q5U{0H8B|WiQhcCi6K*2e`C{@8s&p^*$;@7&#D;O;%FJm%K_ADq#HmS%h zaIGk@RmvzSDX`Ml&jgC;fVX%9HDOc);vwJj&()8Tlpoxv3>ZnaQ4cC8u0?!h zU|>@Bba4!c;5-^;tK%FfQJd={*3IS_Jo#XfppaTfaIDwmC2xevm^qbKZsHcQ-`Kga z`{02`%ew`HqSfc_@?P=m<;oiU<6nOPL0t9p-&^0`tv*-2@BN+MCTn|>(+VG7ysr1B zpy;QDfna?;HzT9_CtdXe53IS9=l-h?o5t|qpvNW#pN92w@7HhfVKgmnX!h_HVc4-O zJA97iqxI8cP82h3HLAC|$Me~R z39>Vlk9}Ce!tj2s*As@SUGpPyYFHn4Cst|OuB#vJoc!VLkkxnQ;#(%Zn{%Vi zcHNM7XHv2j+i>;Hw7Hy;dI<&FqQcAlr|f@Nu~E8kYQqUV>8`5^yJz#N|Ni`D`kBzx dm73PVKNxNLjG}8ezr6xwS5H?zmvv4FO#rINj?4f6 literal 16152 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 V&Rci#%5+eLvd$@?2>^G`q%!~j delta 684 zcmV;d0#p6-4Z{VHBYy&lNklXhI~L^ z{(xAhMM{P&vdJQwEW$_@rBK&`1`2J$ENwvW7X-R1nQWAZkcASr&&BYb?`u9xr^d6H z%-nhRocHd{oqNgl&K|`QaR&ghxhz`E8h_Yqy@Bsfj0-GlBY)Ci)H;=8csUFNw3;>a zE6iP*S{ekxE`g#li{K|ZWaR877h=zm1eXOsoXygobIUj11P|jmIo1^YDG!6hD z+dF$So6AbE6Mv6CN<$$EP?r+~+SY% zxHA)pYBy~{Nw6iP+u!^Z`%W%h><=0KkEZnVCr=t0y#4?kw|!%BQAFKo zNQKTW=kav6u-IV2M2b+WsOU3{1Be++R78ztUL}8E9L-q5#SSLR8cxZw$MfGDBhgrP SdW~QJ0000wo?6S>Bi%tSM@+xQAe?R|_f7>yatoG~NP7%D_d zZE2OYR$oZmu8+u;mPc!CvbTIJ`6y(2mU1O5#XU1zsi%FP=RNQH{?G6C|MkD&N_?p&tB zCwE*F1jSN7P%f7fO#R^r6UBtlJ;a307P@?-cSND7h&B=BQAND%QZLy>e@ z4pcWv@S9Di+Gry3@$poTwTt-m|{Dfh9)pM;WWFA2NKS#E=;7D2af_ z7D0STtOV|^rHIS%{vPq6uXn)%MFNOMUUu+-c@=Bb?NI0vNG_Hf2+-WbI~o5Lvg~F_ z(p4S0)czXz;r^%TQNfjOiKdrZro;e%_6*yT9-u&s>~o7Up?~(37b~ZY;bjy@p|dW1 zk4-wIP zsDn-OvD%Kp%+Edj<36S)tl;3;vllmyK{<|Drbj;{DxyQYn$T@ zU-ZSDwL4vy=kbe^Zvg5v_8H*%?9$w5j#4}`HB~}X6e28M`6f(J`;y-_>c{;$qXN)C2{XY`+YsqJ%+QzKj~5#f=T5AV(tTc*0Jl5YqN;(C z+qZX6RL9F@Cv7VW%C6ELxi>odYu#*NKgp`Q7bI0NYn!8#B(CxPZgyEX-RgZ91NbxMX%@_ zqj5V`lK8OItQ@RA{Avp!Zle8P!+4jsk`4FvR_Vvhmo>TlfEX+G&ip;7;f!6c5%MCc zn=!cA!H^c0R5KKf1cE3kX2>xS@6RTE zmYSnAnrKdw3kT{he({xVG_s<_4!!VXsO6>(YvO*foO|NLnpzh(^wjg+k?1$gsmX?J z^ePlS%>vOg3s|1VQqEP;J^H*k!1Q!1`hxaR5}05ACi}VUXot4Bar2F#%g5ZPwQbU$ zisl|ptlu*^$m9Sdb7Pc`CC7E6=^uborKj+e%lGb0iDb3HnFwVqS zj-fDj^dpKEr8*4D7jM|er_~YIGJ~!&{Ose_z%T~LCb@0heJe2dM?L*1rhHaHGGPwh zWELr)t|JIMzN=pbRTXiZ5neMhm1gVe#rwFw%MDJ3_*~{+y_Qw++O(wfHzQ<}?Yx;V zH5w_**8ZB7;S5MsBjf>OFu%?u(AYzEyaAnvZ1_z@;`(1~Q|_qm^u+1%?y|VTNVRo$QHhU+$||v z9*VjXkUEw?vF^C)e#w>UPs0ya_EmQ8n(jJge#9o^lPDk7VdGM*I>Kc6e#(`ePZeH( z$0X%*Q+)8L?4Ut{>F{Vo!oQ8baiF^_I*ojSQ0#O7IkBNgU8kZE8P{gPd8cx6+@s%W zli$Lf*&%#-q0g88LkpA>HOR>a58Jil(;3J?jB!x3&qSC3P!X3uUHewN*XZ>lT91CS P`X7VsD-^s57D`h$9z$Xv zkdp^N6jXwk=8#J$IaG>`ND;w8>7k`b;(x&f0R&Y^!h`;P z0Km%fDgdZ$EkcnnN`)d5nOqT|9qiQ1Bzn6$O#8-1h5-PdKfIxmNwtBnz`)>;A_hgB z&TE&y6$t>))_>M<{Wn3P^DE1%n3|bXpU0wc$7ORtfEK;o9XLEbLo6CcF!bw!$5FiMCQ}>po z&KtoE0cJ4jJZloDUE#jI`!9{pv@w>o#WO8|h;v4pDgm2!ppJWmTpR)CW_ z%NmXlV5PI6NZ2&k;RdJ)u(Q+6oSE6=EUj2(peDf1PMf*2ysQEyD)6s5fA8)c7Gjxz z2?0*pX@94|WDl^i(`E-6UO*iW7@tl|7@v`#g*JF`czlN5?haHX34zBCX~i-FH38-F zR;OK`we>uJItjdi+6%k5II~>i+Cit1Y4yJ#__^=|9S@0-7+)%xMko?ipT|drQ7KoP z7Hi5HN;^R@@vIW-wws;f> zK@wpz^?w_#q(!WegIbl0DohMYwLN$qH){W16pw73A%M@iVFgE zwoAICNvTl8LT>(2F+@+?8Y8&u#Yq6IadFZJ&t9F)WEXXb)2bxtk|h?X&sHg;q@=(~U%$M(T(8_%FTW^V-_X+1Qs2Nx-^fT8s6w~6 zGOr}DLN~8i8Da>`9GBGM~RsBTId_|A5Z7NlCUU$t=l91qU45Kj08_%qc+?1*r!G zK~5$pWUX=%^U`gVDs)p)(-KQ_N|fx1%QN#*^2^O_^dYKHbwfl^4Ykq7V!sW@*H)21 zsm1v@rJ!)PGcq%=0fz;OC?WhAD)-&xTdddkY-?DDfV=645?sz8fBj$YACVa>mlb|nUE=mc3*N7u+r4%_-pqoe!5Tdy80n7z*F<%0)GTRaK{we_0TUUhX`-V~h~yK1ZR_9p%#zxHk3|9H1a z`Oe+%KTX;uIqS*qNq63VKRtabRp+jLAzfA~Dy7Er zy7QYaqtMqyqR*Llc;mTt?cUw=_;{bh#`XVxh;E%(VI$a*XshM@-$MMs**C9!jMS^E z$_i92u80@)+)}rS!Qg9B+3N3qBHsqM^Ot74y%Vvzw8KK?LG#bBxZ5|j@OdtY6MgaR z@A?B%C!XehyR~`aw0f!i%}S*&*Ef9Tc=5)jP%&+PY(~yH_N{$~89(X#|8?wG^wsz! z@1Dv{aGiHz=AYeh3}%#Gt{n7KS=x=&r~{5@vRnHppmkNFgTP_xgEUZzvWU+~vD zuFd3qvMQ6oWW8%9>eH9!xH7cpLhQM*sgpIpvq^^0O{L(&s`&VghyQ%> zmRzaB%i{O2tc#QH{cth0Rj)QW=E_Xv+ow)_4~btb^XS9w^8bljSUS$!xVw>~{9g9D zrAt$vdppQ5&RA)%hJCYsJgeOqErX{gk20M(fA)E0-}c-iOl#Ku+p}WR;nVz2&GYWr znSRfEcyaB=|EHVvObd7J+_Yy+S#D*lP6MCeJ&vFM*>*52^_{rxaII%p9a|;Ki;ibE zRZ9Qn+&ID{5IN6bUQQs(pQmyEPbD!5ymRTD+`qDGzCeG<(g04Ijsw^Ch;9*MTMG=H zJ-cLd9;~hL*vO#Ze?owhb4m{XhmZf6HZo-0C>C7Qaifmu#A~}MFOF-Ex*`~4<2n{} zEzW*@E6tTbr~B>(^$t)}*qqG~Va(w_kn_0N{YvaJuzgLF`#qQ1DDu266rSEHQgKwl zv1L#8JiF4bs-a2@X>qZ9R+E#na*UbKW061GPCq^EUnfs3W%iq5_hpIAPn+%^`RP&%onK>g4ho2#om?zuQzGn8~$ zk#sEd;vPW<)?=?{RF+zPFiSmskDK9>i@?NyX=~Qa4`+HHXSgpg?;qES#PhBzl$7=e zHKb{%`A-!o5pWc3-zDO!*{@;Mv-I2Vm$nYtiN#e{48p&&Kv$k_jL7hS?83{1ORX#P^SO@ delta 859 zcmV-h1El=o5b*|(BYy)pNkl%O=uHA6vzK7#fn7_f+z~52{{NtFH)!=#>Q(% z@Ki4ff_M>2N(B$%NyLlA=)r>*!4|3)F{Rh^>(WB;66h^tbFo_dK$MCVVLgN`o5^N2 z+c&dslKoxE&SaRKmw7WU|MzNvnUT>khcbR+eaWJX@1qP>L4P8d4EOoOP}B3q`Vwh= zb^~PdIiylaoIZ6T@UtJcwgCXe>0*l^_6xfK7E1Hd#he`;ZfVQrb66GLA&1_NDQI$?!6J; zY8c1{Sbr=ps(24J$OhQn`ZO)Jc_Y7@wGW8|0e-|P4)7y3ae$22!~rs55eLX*GM#Y%`@hY(RI4@E lb{#9LYfbHbae&I5@E`1L6NzzdrU?K5002ovPDHLkV1jxwo?6S>Bi%tSM@+xQAe?R|_f7>yatoG~NP7%D_d zZE2OYR$oZmu8+u;mPc!CvbTIJ`6y(2mU1O5#XU1zsi%FP=RNQH{?G6C|MkD&N_?p&tB zCwE*F1jSN7P%f7fO#R^r6UBtlJ;a307P@?-cSND7h&B=BQAND%QZLy>e@ z4pcWv@S9Di+Gry3@$poTwTt-m|{Dfh9)pM;WWFA2NKS#E=;7D2af_ z7D0STtOV|^rHIS%{vPq6uXn)%MFNOMUUu+-c@=Bb?NI0vNG_Hf2+-WbI~o5Lvg~F_ z(p4S0)czXz;r^%TQNfjOiKdrZro;e%_6*yT9-u&s>~o7Up?~(37b~ZY;bjy@p|dW1 zk4-wIP zsDn-OvD%Kp%+Edj<36S)tl;3;vllmyK{<|Drbj;{DxyQYn$T@ zU-ZSDwL4vy=kbe^Zvg5v_8H*%?9$w5j#4}`HB~}X6e28M`6f(J`;y-_>c{;$qXN)C2{XY`+YsqJ%+QzKj~5#f=T5AV(tTc*0Jl5YqN;(C z+qZX6RL9F@Cv7VW%C6ELxi>odYu#*NKgp`Q7bI0NYn!8#B(CxPZgyEX-RgZ91NbxMX%@_ zqj5V`lK8OItQ@RA{Avp!Zle8P!+4jsk`4FvR_Vvhmo>TlfEX+G&ip;7;f!6c5%MCc zn=!cA!H^c0R5KKf1cE3kX2>xS@6RTE zmYSnAnrKdw3kT{he({xVG_s<_4!!VXsO6>(YvO*foO|NLnpzh(^wjg+k?1$gsmX?J z^ePlS%>vOg3s|1VQqEP;J^H*k!1Q!1`hxaR5}05ACi}VUXot4Bar2F#%g5ZPwQbU$ zisl|ptlu*^$m9Sdb7Pc`CC7E6=^uborKj+e%lGb0iDb3HnFwVqS zj-fDj^dpKEr8*4D7jM|er_~YIGJ~!&{Ose_z%T~LCb@0heJe2dM?L*1rhHaHGGPwh zWELr)t|JIMzN=pbRTXiZ5neMhm1gVe#rwFw%MDJ3_*~{+y_Qw++O(wfHzQ<}?Yx;V zH5w_**8ZB7;S5MsBjf>OFu%?u(AYzEyaAnvZ1_z@;`(1~Q|_qm^u+1%?y|VTNVRo$QHhU+$||v z9*VjXkUEw?vF^C)e#w>UPs0ya_EmQ8n(jJge#9o^lPDk7VdGM*I>Kc6e#(`ePZeH( z$0X%*Q+)8L?4Ut{>F{Vo!oQ8baiF^_I*ojSQ0#O7IkBNgU8kZE8P{gPd8cx6+@s%W zli$Lf*&%#-q0g88LkpA>HOR>a58Jil(;3J?jB!x3&qSC3P!X3uUHewN*XZ>lT91CS P`X7VsD-^s57D`h$9z$Xv zkdp^N6jXwk=8#J$IaG>`ND;w8>7k`b;(x&f0R&Y^!h`;P z0Km%fDgdZ$EkcnnN`)d5nOqT|9qiQ1Bzn6$O#8-1h5-PdKfIxmNwtBnz`)>;A_hgB z&TE&y6$t>))_>M<{Wn3P^DE1%n3|bXpU0wc$7ORtfEK;o9XLEbLo6CcF!bw!$5FiMCQ}>po z&KtoE0cJ4jJZloDUE#jI`!9{pv@w>o#WO8|h;v4pDgm2!ppJWmTpR)CW_ z%NmXlV5PI6NZ2&k;RdJ)u(Q+6oSE6=EUj2(peDf1PMf*2ysQEyD)6s5fA8)c7Gjxz z2?0*pX@94|WDl^i(`E-6UO*iW7@tl|7@v`#g*JF`czlN5?haHX34zBCX~i-FH38-F zR;OK`we>uJItjdi+6%k5II~>i+Cit1Y4yJ#__^=|9S@0-7+)%xMko?ipT|drQ7KoP z7Hi5HN;^R@@vIW-wws;f> zK@wpz^?w_#q(!WegIbl0DohMYwLN$qH){W16pw73A%M@iVFgE zwoAICNvTl8LT>(2F+@+?8Y8&u#Yq6IadFZJ&t9F)WEXXb)2bxtk|h?X&sHg;q@=(~U%$M(T(8_%FTW^V-_X+1Qs2Nx-^fT8s6w~6 zGOr}DLN~8i8Da>`9GBGM~RsBTId_|A5Z7NlCUU$t=l91qU45Kj08_%qc+?1*r!G zK~5$pWUX=%^U`gVDs)p)(-KQ_N|fx1%QN#*^2^O_^dYKHbwfl^4Ykq7V!sW@*H)21 zsm1v@rJ!)PGcq%=0fz;OC?WhAD)-&xTdddkY-?DDfV=645?sz8fBj$YACVa>mlb|nUE=mc3*N7u+r4%_-pqoe!5Tdy80n7z*F<%0)GTRaK{we_0TUUhX`-V~h~yK1ZR_9p%#zxHk3|9H1a z`Oe+%KTX;uIqS*qNq63VKRtabRp+jLAzfA~Dy7Er zy7QYaqtMqyqR*Llc;mTt?cUw=_;{bh#`XVxh;E%(VI$a*XshM@-$MMs**C9!jMS^E z$_i92u80@)+)}rS!Qg9B+3N3qBHsqM^Ot74y%Vvzw8KK?LG#bBxZ5|j@OdtY6MgaR z@A?B%C!XehyR~`aw0f!i%}S*&*Ef9Tc=5)jP%&+PY(~yH_N{$~89(X#|8?wG^wsz! z@1Dv{aGiHz=AYeh3}%#Gt{n7KS=x=&r~{5@vRnHppmkNFgTP_xgEUZzvWU+~vD zuFd3qvMQ6oWW8%9>eH9!xH7cpLhQM*sgpIpvq^^0O{L(&s`&VghyQ%> zmRzaB%i{O2tc#QH{cth0Rj)QW=E_Xv+ow)_4~btb^XS9w^8bljSUS$!xVw>~{9g9D zrAt$vdppQ5&RA)%hJCYsJgeOqErX{gk20M(fA)E0-}c-iOl#Ku+p}WR;nVz2&GYWr znSRfEcyaB=|EHVvObd7J+_Yy+S#D*lP6MCeJ&vFM*>*52^_{rxaII%p9a|;Ki;ibE zRZ9Qn+&ID{5IN6bUQQs(pQmyEPbD!5ymRTD+`qDGzCeG<(g04Ijsw^Ch;9*MTMG=H zJ-cLd9;~hL*vO#Ze?owhb4m{XhmZf6HZo-0C>C7Qaifmu#A~}MFOF-Ex*`~4<2n{} zEzW*@E6tTbr~B>(^$t)}*qqG~Va(w_kn_0N{YvaJuzgLF`#qQ1DDu266rSEHQgKwl zv1L#8JiF4bs-a2@X>qZ9R+E#na*UbKW061GPCq^EUnfs3W%iq5_hpIAPn+%^`RP&%onK>g4ho2#om?zuQzGn8~$ zk#sEd;vPW<)?=?{RF+zPFiSmskDK9>i@?NyX=~Qa4`+HHXSgpg?;qES#PhBzl$7=e zHKb{%`A-!o5pWc3-zDO!*{@;Mv-I2Vm$nYtiN#e{48p&&Kv$k_jL7hS?83{1ORX#P^SO@ delta 859 zcmV-h1El=o5b*|(BYy)pNkl%O=uHA6vzK7#fn7_f+z~52{{NtFH)!=#>Q(% z@Ki4ff_M>2N(B$%NyLlA=)r>*!4|3)F{Rh^>(WB;66h^tbFo_dK$MCVVLgN`o5^N2 z+c&dslKoxE&SaRKmw7WU|MzNvnUT>khcbR+eaWJX@1qP>L4P8d4EOoOP}B3q`Vwh= zb^~PdIiylaoIZ6T@UtJcwgCXe>0*l^_6xfK7E1Hd#he`;ZfVQrb66GLA&1_NDQI$?!6J; zY8c1{Sbr=ps(24J$OhQn`ZO)Jc_Y7@wGW8|0e-|P4)7y3ae$22!~rs55eLX*GM#Y%`@hY(RI4@E lb{#9LYfbHbae&I5@E`1L6NzzdrU?K5002ovPDHLkV1jx<+OrD zDTo|Z>Orx1&;u$I)S@UT1#K%JL=+-L3rZCQO1nuYqMx1bo1K|A?|=WBf8KnX8@kEQ z$Z(Y*002e-{_HSx^wf0R67*XGrwpJ2MjGbl4SaKzFp4gWq3D2wkPyHgo#W81Y2D#P z=oc^c-zo)w^#?Q^V@Y3g8UXZ#a6~i`9TH6EiISbUd{I2)EKe3|Q4Bd9ohCyFmncsb z2&Hs6lce>aqjQZJBoVbP$cIc)bVw-CMNfJS-ySqC`p@B4-6YAk4-7ZA9awnmbtPApA95y87NnkMoi-bf? zTyDHbhA>Ga4bei=<;mwQ@Q7s+ftH2O10eyF3<(h_NOh)yufid4!t)G;(s?;hVL;6e z3ZuLd79d7=8&IWu@BoM$FW$6O0Fp)`;JMp0eu1tWCSkhEj$QPx)%>Z>?FQRqU7lSgu zSMW15r>1WWgQOyXOrtxC=DLBQ)#3%~^Bd41qF;$vY<(FKnj}I*Xhlh2UVspRBw`6# zT{^~jzW?`lIo5OXNFj`{X!8MHGA}|cx*fWg1W6T1K8(=b#B&+{*JVD8PSQmcsw;o3 z{Am5N3>o0UTVff0aYAVg0NCsRwpWB4GaSQAGWRkc@K^0ZR@eusp7^i99XB_>Fl*u3 z8fW2XUSFTHIVLEEx;`4`ieFWqU%fmym>t?>A7^Q5?HgYGnw;2{Hm11J*HBt^OL4}- z+NH{6^5c&NraH?SZr&2SqiQ(Fayf17x~lc*g`eY6ZbwFh`xmV4!14~CPp$0i+!^H~ z_)}o;ZS#4|jhMc^x=2OwT!v$tZ?EyP4VjeMr9SFwoPQ3TTJ{TuaicqarT31T_vbDa zyfKPQ_t=r}*MKJ99WaFJ%IeSC)AC4f!e*w9ru^h?aS$x7yO) zYle**xiMUo+1^t}!1%rXc&!*<;P>M3`rM;o*na_9ldQ-0grP=-(U;kWN6=|$C9B!uqRBQl_0CWE zKtfHq{ICtq@m+*5>VSy%IWOl&ZaF>Ig;SOF^YNaIW`@Qr z4z%)1`>k;}(0F5{zD@PE$=-{x$2k(w-CaP(*+xQt_SjrrydF^D?PF_m?)rTUzDd2O z1bFL#JAN~#-tXzDCNr2FukWJ7Dk!lbhu^74YUwyH;WzuG_0+v;|5urt=HxOqGl^Kkl1 zlVzwVH`k6(ajbZ*JhmhKDrZfa@(KHrUj1k(e7n;dr*f(FiR&3l&-*+VPo$g$27CEH9*P(k^I3CpmBq-6}x0S~gFVz{VGjsJ~iw=#dI9N2M~J!o`PQO>Cv?L%Mj_wPO$ xDp%IJSY^o)Rk^HjtU$=0iOHyaf;}Dc>@`t=A-yV7!qWWn1AI5JzwwUC{1=>?Sw#Q< delta 890 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 delta 890 zcmV-=1BLwd5ReCuBYy)|Nkl%PiPZC6vn@mVx`3%grX>vY{)?ndXYj4(%5)i zvUsW&1wp(Bp;E6N#f#F2;Gy6}i&bw4xu$K3&_eN2@D`F@S}awON{ba?J(P{x$z->i zH=8%j{%-p(v-9n|nQz`?3@|e?I^mefBrH3NQlSXT&H?~l&VS^Q$)tbH&%K`&pV{Bt zLEpe2_IG#i?dSJLl=4qe9#%;zm4s;~kRBgHdVCB3U>Jtumv4v=KmtVHi!7^nUrSY5}eAerZ+B-i!7E0BU1i(y4}SyrFM{JZP0e2H6R2n(o>fN3UBDio#HV&wxwqV@suaV7*qLzkb4=e%F+-h z1+1+ulHY+sBrPDym{mZZ$wdSTaX0^8h@u{W@c)7idw8P$N~h7)2-~R zF0DXG2!xG!S^A3$B?3e_PDhQBKEQ9BZZ)CN1tooecP z4{$}$iH`dK-C*$nI>F`xbb-YO=md)okfp!4=%N0A%m;W|g4+jFmRA5ATHtE6MlDtu z-$vL6LvxWF9`AxU9(@nODFpj zEd}UgpTaHxw~t^KfZIo~3jpx?2rUHQ^bza=aQg^lS>bkh{N(9X@tm795tApf>(dW& zq;vAw1(h?X&sHg;q@=(~U%$M(T(8_%FTW^V-_X+1Qs2Nx-^fT8s6w~6 zGOr}DLN~8i8Da>`9GBGM~RsBTId_|A5Z7NlCUU$t=l91qU45Kj08_%qc+?1*r!G zK~5$pWUX=%^U`gVDs)p)(-KQ_N|fx1%QN#*^2^O_^dYKHbwfl^4Ykq7V!sW@*H)21 zsm1v@rJ!)PGcq%=0fz;OC?WhAD)-&xTdddkOtj6-Z1 z1a@3|bN$@)6%YG07*$O95)SBZe^^yr{r`l}zyH7Y{QdR!IorP@^>wv>&;C*VUssz_ zas7?|GiT?c_KQAGVl4RS5H9+@?A_O6%qP?g#hZ3+={mosNc;UqhAT^E9rihDyuIr& zV@rV#+pbj=+l#l9cQWj#S+KgR+}geRF=K)rOL3-X{70+ZpXB%z>c2@f%{m_Q?B)7L z6%2kBYQ+|3!fcA&KTyw-y2!{&b6?(n9(wxJ?c(!bVtOLjK6tK&8SNU@`oMs1kX!GjpdKhv)sDj&&_O(EV<&D%k5j=GR!IPc~&rEZN;;)2b!>uI`?WTa!3ikFJs6GI-9uc z(ahP0$`}-7CO59ry7%_YD_d0tJ^2@_9^E~+F3y_aOlyMP+DF=P>FW31GJHy3uehS} zOzOOUBHNe?4jIlooVe}L%-fC2Sq?m9jt$*&+Y;z3h1o}9IG$b7vip3>ch7Cc6`rQ; zGrQ9BxNgH^WAp0oQ(&>NyXq~20XX*7SInJTv7PzE{Jm`po*7QB{1tqI?*QlV6u$PG zK<(`FgczptmxO-Id%h;lx*A4S)11|>m6Kxy@{ wKWIrdYCoKF)VQ2QUlQhtxO^KVPmp0rzU{I#bCmgKRe>rqPgg&ebxsLQ01EZjJ^%m! delta 386 zcmV-|0e$|@4x9s!BYy#7Nklb;@5JiWS6zS4ZbHE&fn}$eH3TnE@8dl)V zU+?os|1}6k4BBtc`Wg8UFsIY`l0Uose#P$%^5v~~w)i#m9(EbP z@(BN@-UA*$Uc~aqwicP|DtG|PMYc}sS9KLUfQY#>pV>tKGk<43g9p$%^P@w+1L&Rk zTvx#ZXkibq2iOBv*H!QUBJ2V70MY{vY6JRyUS*RrfSl=GHVJ^7>0aaj=4~SYbpRot14eSB- zfJZ9r3HAWBfqOl`9#CuMGxh+rfjz(;@JOXS!5*MCum{)!YR!Dc9-ua;?g8@i0V?$K z1^5#pEoSa1y9{9Fo`MHJdjuW;?GbnY5q?e(^$0uw+9U7)=>HS&09x1s>;d+G)pZp- gfCzhlJ%IFpI}YWnoU#P_bpQYW07*qoM6N<$g0YjcX8-^I diff --git a/Resources/Textures/Structures/Windows/shuttle_window_diagonal.rsi/meta.json b/Resources/Textures/Structures/Windows/shuttle_window_diagonal.rsi/meta.json index 453a3797223a..8477687a8c7a 100644 --- a/Resources/Textures/Structures/Windows/shuttle_window_diagonal.rsi/meta.json +++ b/Resources/Textures/Structures/Windows/shuttle_window_diagonal.rsi/meta.json @@ -5,7 +5,7 @@ "y": 32 }, "license": "CC-BY-SA-3.0", - "copyright": "Made by brainfood1183 (github)", + "copyright": "Made by brainfood1183 (github), transparency tweaked by Ubaser.", "states": [ { "name": "state0" diff --git a/Resources/Textures/Structures/Windows/shuttle_window_diagonal.rsi/state0.png b/Resources/Textures/Structures/Windows/shuttle_window_diagonal.rsi/state0.png index d218355a78d335ad324d4435bb6a2714b693251a..f3a4f8bca59aa05e9643cee5653100277b0028a6 100644 GIT binary patch delta 939 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 H*KPV6dK~`C diff --git a/Resources/Textures/Structures/Windows/shuttle_window_diagonal.rsi/state1.png b/Resources/Textures/Structures/Windows/shuttle_window_diagonal.rsi/state1.png index 810b703900240ea7f30ff3afa8186dcab19592e5..08bde9a23c42d60ec2495a3241194dbe33b50f11 100644 GIT binary patch delta 887 zcmexZ(a$|W#g?%+$lZxy-8q?;3=9l>sS%!OzP=1vKsE;ugTSTW$v~2`z$3Dlfk9&y z2s4UXDQ;q5U{0H8B|WiQhcCi6K*2e`C{@8s&p^*$;@7&#D;O;%FJm%K_ADq#HmS%h zaIGk@RmvzSDX`Ml&jgC;#BtJK`q$o4l zGp{7IsGumdBoU(8MjvbfRuz-`xkM-5=Q1=$@~xF)QAv4zQFaK}XCSBAAO{AD^yC%X zX7z`zMSNvoU|iwp;usRad31`s7qg?p(c>CXOQ!DaOi*0m>2)ySu^`JwjyNZ7Z&#P1 zz8g25a2$-dy<9->Z1j)TlPTrtYQOWl{;JKs`*ZL6y)#Xh9W5-V__h72Sp0{${pnGH z3^8ZT^$xV1Pn&<1tKgx&|M#<;Cz{N~9OeGJ__3z0p1teA--9P}*UrAcUSBKcnE)K7XB&HM<^9!BsD%4G$l0|89CacL&Q2zA0i1HYUXfO>eL-Rr+x7 zs%05BS4{CSv&r>0xMJLM?LE12@85i@m;3+k%;g$)FW)%9_~0d1cX#!bE~DqNSz8#S z*S)*j-*e8gd-bhtlXw5EpTZz-qf#uru5v?zfJOJ_kDIKXNoGxGkk}!%?Y!lJJ+J=q z{dn+h``j}x@BQr+cqeZ4pgDh%CDV$XOimAUgeF_Q4=`pua$swK&olRimDx-+A8r)u zl^1l}XmdKI;Vst0ARCX8UO$Q literal 15473 zcmeI3Yitx%6o3asBE<@d+DZ&=wviw(JCA+NxLsPh#g@9Iwl%a6h3U-Q?a}bEYx@uk(MN!qQEx}IsZL|Kbp8-FObow0pni+5DH7IJaqmYHG> z)Y}`afVQ4chpkCZ0Gr$4p=H+NwRr^x=k|JC-X%7k<=hPGWSlI`J4F{Ox_DdevInZ* zoj;+3#m?aJTsSDz+xty3E;39qnRFzb4m}ZJI6)8?mS=dLhBIhmNHe7rtr>M$CwV_X zV8{tIZmPOwv;0bZ`k+~Fw_AYXdh1eC>8;ey8ZJ5m)Ac7pyik3$AP#iFw zz|aR1GHBiaw^CPW_of;yCa27krI~c?Af--XW@)l!nWK=+kRR?@1$7|&AYlekLdD=oNF=5i7Z>< zBs&xF5z-YkJXG|-!2`{Ab6$~!e|)Krl9{LvSU-wnN>lPuI=94+B8y=?5tGb-8j~V` ziE9x*QyeUrSvXZFW#l_M>AMny_SP*2V>~jId zlQ|pZ=EareT<4=h*OfOOc6!3BkXA=UgOsKG(OVN@!)?O5AFKnO8 zy1hQy=K(zJ;anW;bIM-Yjwo-4;_mx7YhEofdKhvH>Nw!*cK(?wLD1N4Fw74wPOs$a4DIv)EFEO7yMzSAh zxUP|Pm6tm8%3Y%2Z}ly@Es-(uONc!<4G(Kc%5^ zrK&|%b~LrsBbPf&%wT87n6oG?4T z@FKy5=YwboE(8c(B)IT=5G}!l0Ktm{7oHEICAbhEc#+`3^Fg!(7Xkz?5?pvbh?d|& zfZ#=f3(p795?lxnyhw22`5;E;e!iTdrY&p@Hg=~@e)in{s%;Im$HwP}ZqyF1m^1xx z&y41_?Q?=F>qc6>vmG~%|IpTQ@X+leCr#r0PaJ6yBp=#S@G7k4~yZ17*K-j+}*aHlH|f z^kT0=x@Ygat&1+D4<(OYeA$>eaC)rgpm1c<<)`lV?wj59_uF5&R@plqhO%;G^{=J>UnDMyCd6o4~_O)F9o+Yw+HtwTet0BQe5bp diff --git a/Resources/Textures/Structures/Windows/tinted_window.rsi/full.png b/Resources/Textures/Structures/Windows/tinted_window.rsi/full.png index 6baa538dad92fff2a6c364b70fd4a5d045c04afc..6e1e863798be43c1e8c7dba75392d64f10022699 100644 GIT binary patch literal 3495 zcmZ`*3pkVQ8=vIR$VW;Nn#oFGYtA!rJ`|F~9E!1FY^H5&PGJs}yMOond+z7D-g7qAW}AUhKmY)+*}~k| zmiq>+4MBeHOb!nI2mtVu;EarHER2jmHYB1a4vz%@_NIiT=$h|DOFj&TD2p9@_W~#) zqIs3_0<2+VCN3Zbj=t*lO60CfUG$rI64hWM%hrF}R%3(Z4JWcY+vJLDoZbnfJ(tN+ z3RD~p9n3oKT@FRo)^mmyke~ZkBVSy*W;f9$m_}%|uxd)I`RFS@A8&m-Qa0GK<#;&; zE_bAVklLCHt(@R2l+7%jR7jc}v{yswa+W7M43>wMbyzw~va+{o^h2dF+Wpz+RH2;q z(A~>VQ}UvHGlh7z(UZ`+#;OWckR`YW5 z5mI(hIewj~y|^oIY`Pbh4Q+e4G1W4q31pNWbciP0LWmzZfBy5Fz~tq`uc!9yl{i&U zsDG5b**$;nM4EU`nzaN}a*Hh17|f=UhZYL$dm|kjL{H*;E(T~h#tzO}T@T-x6B;p^ z374smi%~FKLb}L4In@5)qdcYd)B@BjYT^ziIXV36w^^RE#fD+cpI2wTo(?+_7k=-e z%$LxP_?1#v#l~~wo}TCidg#J?-qV$u%U|lf-e1pg<>e_256o_BdC5IM5iH8W)5;34 zkGmG+jWHUiUz7*K1}d7_{y}@zn*RtZYC=L=qOHp#oEZf%SkO5C}=a zcp_|#O@F|-U%Fs#3dJ7*g;J?h6{@NVk>mwEpslS9g~6e4xH8v6nH=OtLDQ7|$nxKV z{2j*_OZFh){3$r1A80Ku+MO6c(FKFoh<-lb^Tc@k#dU zQij2m;o8uj^>NcjVmuHO90iYE7w%_0>k1m+DZg9S{MRJFZkV#!2&z?$ZInsDU048Ixw5&t^?^(Vlu z#(x8ByonSdx0gsb4+}pEmgG<3_SHJy-*o@&@$Xpwa3A->QS|-}@GtW(s9(+nVL+l# zi6mdU^)vV`;D2ua2=QIaU;6TU)2|E9?Rq^R68iH7=>cnDf=%2Txy{1Zzz(&kYP+NV z)`wMhSYDpc6D^0FC?zO{=vfnK!-&Khs~zYwqJnu!3Xyix)gxPvL#)~JVppc04DSms zh|}71O3vLQ;TY+jf&P75StLqqi}@q-OY!R7Vp|Z5PZgO1{I-w67SmkP7TrX_pVNrv0aLV(B0H+YSoi zl|AqG8bh5G&P_7uN zz(Op&j&o8u@atQg`b}qatUSNiQA*PG)PP)v5yYFbRjP+0``$i}nCz~DuK3LkcZP>m zJE*;LNyw<0Pdq*!lPa*|sgJPzL6QBgu2;HpwI4-=Piyirl;LhKBATt#tgC|iiVlsn zvOl`kmd}=N$mtIP$*ZP*eUcM-p1sg$(c9$ujb4jiGOVkvG)^?Vj{>&9%J4D!&InYa z?D!tRw0Y86Igd*PXGu~#3Du6+D^Il|Y&J~Oqrj}q%6-+=RwNc9Dd+Tz(}0=H=Qqbp zj_RxFGL@W`2m?EyRZf%)OKE7MH_!feGhDA^xgfTC zXoe#q? z3HfLRNVa|QMBi)`NK2af#B^Qm02W>owYH1t%+&%^mA?9Lm$Skc^lg5>$a1l~iIvg{ zshels`X)#qZqlPcE8m^zHB5 z4=b_AIb4>McSZkAFmF9)Y@dDz(GhldK{1oTOr*8k^h)Ps6YL{A0)2y4nn5*`i!)Xg z3#x|>ZxS+0ZqzVwAH{e1h4b~qOW-CHuhHKzi!LCKi^&GNZIrtMXIjg^so9eWdsHN% zPvkKI>>x$wRG-B@UwMB7va`OMz)zbR6IX%s!8J`YcSufjxSW!dyKoUwbnk_CClDb| zuoXN$wTtz3>#;^Y$m^7?$#>G3RCZ(A*`QP_d#%f@m3>QbyOv4x*Hx{v=U*Y5cz^*K za^v*8LjG@lLx8*f)4S`wJm$&SUL4}njxcBE=k~1f3*V~p*UjTe{?n^`urZ|}8{qXI z_qkQXzP6*O4wmT?-AhhD*!Jb+s%*D6!5wLQu7+q4@G+io`l7G>qbS#`TO%z`cxPg; zQV$|Nr=>Bx>Xz6?MXj>=1l!w4qj1tTfsc#vE1!-H_>R3S**#(JEM7JrQQ)4LzO|J% zH*tHyIT_1lT61+mZ4M4RE@}q4pDVjkLHOd=Jqp4Yx|=q$&<$$aA*=Ow^uyqP6%@2a z*WK6FPfm)G^4J2vbIcZi~6JxzO%1EC(JG;@EtS9 zJ+0K+aJ=co)n^G07BYO&?m3)XRo`n)J(rg!$v9)$#L`@`@mrl|(|dhm7PocuzYYvn z)R!T&H;<}oD5|T5E=CO%!Xd>px6hi)J+GDn`U=J?s>Wl==a)`AX}&GBzpN+oB{RJE z^w-Ba;*)VQcZyz)WLZhZ2EV&9I{PZYJGr4abhR(RjlAe;Q1E_8KkLB3;wOmRcIkjU zs6F&;Vlb95?~VM_!9I(miwZ}>t)(Vs!Z0%~GQy;LOoF|wQDS1K=Ov`bTlEbA#+zs3 z9&7AOqiag{Fj=x8zR8YQ=ZU0w@ZxUPy}TLww=)Ansic0Dn<4u|4>6nL=}Tikdu%9DH5` zA%Ai#^VxqlaM+{BN3pLgs_b@~lbhuQBHOk^`k=SdCADc7{gR_PmY zaoSV$`v;H$DpQ~=N$=jG_)js@a_yse#{RZ&mHec`-JiRgmM5n}e!D+nmQ82a3RK*}H_w_kl*t2W^BeX$RsCA+5)0d$ zx4GMXN_|xD{df!CI(>6o0lC%By1`wfGEv|1X=k3LD?IrdT4?_V>?nSJ8GCjRz!xkA zHQov*XB9709(E#9YnzVlOPC*uE8^S?qFTSPy=hOnP%R(!)2-&KbJcclUby<=?)$K? zsgqk4dz;|dJHX}s`8%UYSK319m6x|w`nbM@EJd_#yk!hPMt_*|3k)I)$o5!Kk{UL~A6Fd&;)1C}Dl&1RRTbI6wD6@&UkU57&sT&8GR<%z z<=Ga&7hxl2zTn0Yi;!KgYHrn{#WjzI`+fKF(-e#YJims0r`P7{NmP7yzcfi%uaMm- zHz?cMDKG2?Gt0^29ntFArX&A6vvHrw{D3jPr&E`z{G;I8Wf{is{U<{zCLyTP^<~cc zEv&GJw85lBMp$k34m6rE|1#=={j?_eoEBZ`#~V3gs}6hWMmb{_=3^GDF$|8qlu)|F zi68h$a{n%sc&e6&=sb~ap~;gkT74AHyg-Kvo_57emo;`l2WG`lt|XtHN*OO~=!}&z zt2nAWj|)10YrZZUXe=4(nvQw2cyCn`4{lUF9BX*NQLY zbHhp;s5c~ggi%5F`2jqxP^90iL$A7ga&G0}hZg?%g$0JR`pV-G(726oUABS4v1;Mb zt>;S)mR$V%8B5o+EY8+UZCGOPCGX4~7QXF9 znuDoCp$4OkP{9(P7rR3@Kg-J+P+br&so(Uzb2u~QFX3A^Oy0b8rIp_voP)gLovCBm zTEM1&%cK)}e)nqHwYzNT&oD>A10NiW$6gLM*^E=)8SLai^&UMmTQWmPy<&S=*zS_l zK4qeebEwTU7F7~ty=GWk|DmIRy{e_GD6vPCRIr7e!gFE^k1o&%^9T40M=FRE&5+a7q2+p2LUO{953%WQ(^B}Vjy#MT zk)PX#$KJeZP0R61GlniSaqsJp-p|vAVRaI=PG;fr1?0WRi-v>MAF_15y3yY2)~=k^ z!FF^0W|wSZmWnODS^hLtUs2GbQXnJo_Wf!qWEB$&M$6;9o==dV3bo0bH;K%~1sLvz zOZMDV58nsDtmE^S$0qIBU7wB)6_e<22m-Eq^Vz&s2hdf_BdYO+@fcagte6X`?78`| zM&ozd2j_0aW_E1Jm;g~#y(D?!UupPLiNshoX$z>61uafE-d)&PAmMuICR7%5uT9Ky zTg@M+=Bm-yl;&~s^Yo`nqQ0i;Ih`%m^jWE5YG}D>#`{uaVpKRQ_D?Z+Wm`{WVfG5~ z7n8e61uDyI22-H}3`6WMWsa30X<{YNp04z3KS6WIOi)zE ze;>~ia1iRHFt-RqMC?K>NOA;V4f@jhP zmPsFcIyDm=vcJzQ`*YAz>D)xx--;<~fY~OtKSU8*gxL7BaaYaKe0BC8i@(j>Rq}%HXc{ zi}@_cNpCbtMAY*BVY_b`5?|sAXb%GY#N1_AOQe4s=P#n=4!O%>YensYs_Oh`T8|&MovlgXt>^v)wrF6S|AzT|bA@_-u7f zBVzVcR=XdV28hOPUDc(de5222GV(OaQ@~IB`)NV!KuDa>@O4_euhl-$jt#0=P~@(5 zBjXcfBVVAi!xen&*YT?4t>=11X1Jt+nzypEHS{%#3`TJsu5UOV;2CbbL?hqgkRb8q z9QLI_(Rce9IOf|4c(dOeM}I=C>tScARok~ScYV`oeB!0uwizchqPlnIr<*Tdr8Lf% z?G`wSzFky+d2enB51>&xzDJp_eGKKplMH{dU`;kig=pzDKq>v z-S@Ch^f8xbGEB|xf4*tXm*4;C=Z*cXOwmGwomcIo>rd&BZUi#U9^`h zJe{t~Yx8g%7I$-LaGNRZ+t*~R_c8BbR zagTc~t3lLU8T6Gtv!eIMGjr$C>x$#*R#5Q41^_nK@Mej5Yj>tm3=oTFOrQ?F&VNHv z@{<;WEne+mHUHFQ_=fC*))2<52hT^VqqOoBy6Z^jDGjd9e-dpO;bAr>r6`|aYk8}s zw%&5db*V}rHI9HnJ|o2Ur19d*a$Ro5S7flDhO23s+(i%Gk3D}0|sYt&>72=Gf)%vfOOb%hv@>%o)TAjDopFu4=LnTkDE0ML{|g zEq!tHAsfYPrgNpPvkRlK_p&vxmWxDXX>da5=<)&YviD5`qUWSFtFx&@R_(IC@e3@a zyo}m@5IFSC>i%>8YaK|V3sK1->0`Qw0(y~4!^EXB!DJa98lpO==%VL+=B`UdI8%$u zl9Y&)Xcx41jT;&e7syXPQp>3q_|fVhb6BqHG3FF>WjJjCWKjk;AQnt^fBtozO;`)= zo@XZ0t{(eRqnrIn@ec~Y^)LtM5ohwWI!%CnAw?b8KWM*7^W&dSgLf%fu{Kw-Qb zuo8hD-h`$P08ms3^hTlGuy~*Y*2%?F3AFjV4Fq(-D1j_th7dz<4Xm?^ZZHmeHQ2}u z9qfjNV?Zj(REmKJ0)Ph=j{*jIxO@5{0+m3&a1n(2bFm}{_)7)vrUbGwL;^Lua9E&> zgp33PtQF|uF9lMj0xIG#jtEmt?LQz0Pf8$XJl-22DH#wDAQ2!f;e~UOgu>x)Nr;rB zloXht0rm~@#G?Yip1%C&5Wiz+Vtvs#7jL|amnZNX6XoFLhgSlD2;;y%{qyiPH2e$R z)AtV+2z*EeqP!)c5)erb56Qn<_~Nzv2_Szs^uJp8nh|#IKV<#G zxAT!-;r!hZg85&#|Iq$3_Fu{bEki?urWe}p+&w)_CD8f&2#gon1%vo?3&o%urBPTc z7z&eyfMpyVF<^N)3l$AXqF60)|RE z$b)52a1_`93zY^#WaVVgvNBj0)=}!0HyAWR+Y9G`BBayB1LcI3^!9Z6HE>QiLJg^> z1d@_~{6~UxN8ud_21+0U7f-*y{|uP9cwn#MQRi$zWo4w`(lD5;l)M~7Ug~ew7Fe7w zp%TwAp%4iv`CsPeX+aQzArOl?uTuiRFF7F=ga!_a!h7M&yu93%K<6$2&na7u;S2=me<%5``2Clz zf9d+K82GQ0|E;cn>H4o2_^*`zt*-xXbW#1M;lX+megy@bw=+Y7{Qv+_tc!*QQcpwU z&%eF^0O7Q-G$q|mBvXv>^>S0uC>AE4Ze+fA{H^#5i((39^@krH{MK{jtVmBIeQr*; znT6}bx(3lK|7~?flp;z6m~3QpOTu(6Os`lgk(Fn2{zVAw<`nt&Z`g`lZgk`WYi&__ zR;e*_zVB4LNAw*u!2*t}z9l))PGM751)~tp_HpD)aRn zLAM*O)z&X5{h;oIdtmQ=dlH-44$20qM<$Bu3wNp~`X@0liXc)#zLRse=}O$S5rE*t zi-?)i=gH50`_cg0Wt{gkm8ZqGem-~$p_?S*fKB{VZd&i6qzk-I`y{)~l)OSkudeaQ zSNe|)7j0~w$^>0%o+P?ZfbU7=5>f3f>?hfD+B38++GL@4*y8I}FuzBnJ5-Y{*ZztR zVp_E3ml6=r*uVazVCf_r5JiuBxTSF#N@z|mI9$=u1UQ|)4S3<_5=w7fYhM6>n(_Q1 z0_5IfBM8aydWKr$OGKFXeM$o8K`fYa4)27^CZ0OcxsaYu$7s$Nr{)S z2btF2f_S%4mb`gK)D9i;putZiYM5Q_KX{bZ>aR~xtS7zn=x5(`CIF3L8lXL^A^zh2 z_wMihbGp46Mb$nG{Lk5@$LF6{Rn~+WYg@9#I5l(fC2DRE_rhoNk_Aj3!!RW+Zg;_6aNC{S8RC0B(-LL!C$!>iZ-Zi)nm+Rx5U z2^y%sQQGRCjrB}Wp^lhpczUh723|oCKj>W;(=1gniCp(&jd^dw4T$CZ z7L)no3LXFZ9w6 z4gpP%+jhVcUCW~}2S1C{N$nFe7STN?U*?@Qd8L0IENZzOy)&F0E_3mrOwcRtm*8p8 zuTL7fA7(~JI=I2hPEuSF$rfXnUE-rk`CgZjOL|IC>}e!P`|{IGA^_Eu(QolSneLza zL{MM3L(7O&U#0uKdKGu-&+*l{XrDFNbUJj%G&P^LbGh-yYM=gNQm5Fi+I+aGm1Xtk z6<)!bYHRnF8;raJ<+NeCL-qBi5uc6Ssk5B{s-ztb`DB=9NsK~$*HTxO(r}vLNPUcT zER7LB6{x;OnWz(N$`ur)`Z2`tX!{#82f_KEQcasH^u#kMqXyC#D%Expm}tXj0MX zVQZP31Xl&gML$!WFLZ5tD=ynRmE@OA7|^4k4_phz+V0RCzvxgpD^d%&HZPH1Q?In#kd%OFQi%k$#yt%5 zxuZ?F2+%c{Cc8Hlwq4tGW)qF6_#D;}24bRnQ{Oh01=Dnw3@UZiDupX`-%e(TQ`o=^>%T3x zsrjed9$dOW&l4&vIq~GGhue$VgqyY6q|Z1Wcg$*5M<~BfW?9@FBCol&^WOgS?WVlo zdyU@x-0#kS{s*`>A=}M(TEQN!t}Z2Mj@s^#~%!Q=uy zMu0)Yo%W%6JbQ0PqVwR?&U7qy8JTix3iOZ;{}nXdz362c)|3v ztp%sJBb1W9{$EZ;_`#q9B}QmFa|A=QGG(q_z81(9C9F2U7anH2%#d%zs+j;W nXYAxZ&0s4b(PK|I`T=@cMw+$i_EG->@F4?q diff --git a/Resources/Textures/Structures/Windows/tinted_window.rsi/meta.json b/Resources/Textures/Structures/Windows/tinted_window.rsi/meta.json index 30517fd0ac66..90748bedfde9 100644 --- a/Resources/Textures/Structures/Windows/tinted_window.rsi/meta.json +++ b/Resources/Textures/Structures/Windows/tinted_window.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/ f141c349e063f7318d8c8a2417d840f0b2d06600, modified", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/f141c349e063f7318d8c8a2417d840f0b2d06600, modified, transparency tweaked by Ubaser.", "size": { "x": 32, "y": 32 diff --git a/Resources/Textures/Structures/Windows/tinted_window.rsi/twindow0.png b/Resources/Textures/Structures/Windows/tinted_window.rsi/twindow0.png index 414ffd9f3ee92a394adcaab92ef34f74bbb1afd5..162cfa0cfac669a97ae0972f60d90baa80dbc3d4 100644 GIT binary patch literal 4035 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 ab8t=W+3+3vu@AfdWqM}}wJS93LjDIjjs7hF literal 10814 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 ZYxlTu#$ZI33;lct)RncBDiy54{s+=SrBna_ diff --git a/Resources/Textures/Structures/Windows/tinted_window.rsi/twindow1.png b/Resources/Textures/Structures/Windows/tinted_window.rsi/twindow1.png index 90131a48bf96cc8117ce389ac97229626c1ca243..f022a67d8126e95d08de8cb8a2e1088722b1a218 100644 GIT binary patch literal 2719 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 uW-yZ+eV@6{#91FZD!?nr3jhEF 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 diff --git a/Resources/Textures/Structures/Windows/tinted_window.rsi/twindow2.png b/Resources/Textures/Structures/Windows/tinted_window.rsi/twindow2.png index ae12f39860f52ffc274a700f9d45e285625ff1f8..162cfa0cfac669a97ae0972f60d90baa80dbc3d4 100644 GIT binary patch literal 4035 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 ab8t=W+3+3vu@AfdWqM}}wJS93LjDIjjs7hF literal 10815 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 diff --git a/Resources/Textures/Structures/Windows/tinted_window.rsi/twindow4.png b/Resources/Textures/Structures/Windows/tinted_window.rsi/twindow4.png index b79db5f7893ce7908127d271a29bd3d13c6e8fb8..41b69347b0b5028254467b7a0217557557c60269 100644 GIT binary patch literal 2692 zcmZ`*3pkVQ8-JI>oYz159E&y8=xg3>a@uB_$oUi!(r4JP%(mubqnM~1QVvNa%J)z8 zbxJkU+qrD?H__Em3JcLX0hytSh8?9g$P zdV)?sww3!{JL^M>mL~P^u1yR`qMA$8uQ~V~^N6=*3}4Y!Rod}3%k|LnVxmE6WU=S( zM?cl|EKKY*qf!x~zwS@0+4I^`l&G^V+v(IpOq91s*WzXSSc{hfIsaVQ?YYz8W*AW7 zX(O>ay?jJf1Tjo|BJP^ywpccjubKTX$4R;N=thHp&K&i@1Em3-f2$2%der;R#fQ5a zFFgP4?in@i@w9XM^anS1O=XO!Ze%;QyI0K%&kMVucXMx8wnk#jqDTMj%e*z&Z8-h3 zK$OZtQh7Ibp|PCwlvRb0n+n1Wv)vm~`*;uAdSc{xe{)mk=#tSV>0+OU;U{>NDp*}+ zMXZ8>E?pY9Z)Z?}WZpH#JdU8>ZAsZn%!8D>i>V)lZSC-$y3qEkF&V{7Q=O2HT}6XB z)%BZHoi9`mH2yJEa{a}8jndjqB2?bDzt#G~e@us;O_eGw6-*n8nl`Vi?4O$~tDY7! z&^6N26Id$StH`E&-1plhTUB{3L2&?}t}UN1ptwX202J6P|3E0v(}NhnjWrKraKoAA z!dTu6i!3C{wy{ho3?+b0KwPwbzF8T|SsQPh&|2N?r^;;^fuy}u9^!O)|l zPM>O=;V@5>wG6a#H-q|_^khYRykf^WA~EM&Yc9Y46W$GENy5t@=l zE)RP>t@J>-?C?M)e!scqpCYknigYQSa!3J$H|-k8&XFDr3A?m`k3rzI%Fi3r90n?# z`>LcT*IwN|oO`7?wUNAx{?ZWeS=%q{Fg4#uH!3SU5(7vsCloCKld0N1HS*IPCWWE-N(CX#)cb#}K(q(jZNh3i+ZSUJ-52vdDMp}T-uElAccXXxq8 ztH0i71FO0S+hX6g_61-w(n51FT8Fqgfy{*~o^PHS8!%S4DVh)p^)G39h@?|@M~#>G4`r(Q@s5^J-GuI8>wAZLZ3@^wnb8kww|V=B5pyV_=~3-Hn-U9SG(Dcs?jhj- zzOHwi?DUdgy(v=L1fIJ%9EotYJOsndkJyc*?l=PYu86TYzQ7Y!hYxUl+m`7KLt1Zf zQH^D&k8b*E#71F z2HEXrJz#O?Z2~20nMZI#H`YQU_te?STde5~_pBnjds5kDHxQW6M~ z$rjDVQ8qv0;vgAZ8n9&;@w~%*9zUcFPNk-+|T0dHUc6z8(8l~iX zvjx5;Xpv>S*zVK2L235xwfg!@h<2<8L$Zbo*Dcgabdyluz$!1{cOm)|?$y|L7usUZ za%t+v!(y^G{B3dqlVR6w22?SO`rZh@gAP`j=!xFCM*|^S`tl2R)hhzZc>Gfv`V)-& PzruB;m*c4w^tAs2eU4hf literal 8217 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 Dt^%_Y diff --git a/Resources/Textures/Structures/Windows/tinted_window.rsi/twindow5.png b/Resources/Textures/Structures/Windows/tinted_window.rsi/twindow5.png index 83797163f225f940ae731ded308e1418c5611567..8f02050ca08c4e2a8fe8b615295b9b89fc61d595 100644 GIT binary patch literal 2318 zcmZ`)3piBi8$aVRh6=e9g&D(iW9E#@iZR9rWmXt6McWN?Fc~wNIc}wh>QC#k@^4#W zsU*4dCo9@qQmLdeX)DB(dfbQQFQSw^GfL`dzvubB^PTs+zxVfkzxVx~lf-o2v_xfv z3IG607%om;$dfLe7&NjLarTJ;09DFybYwCd9dS$nKaj(P0ANk}!E{>}Jx{G;_S+I( zC1B7DKeMCTr#BEyD@@kJ-?+T4(DSZD;@YMUR+wnGtj*Wfa$33jXeq8RXIaQvOuVPM zVNT*nL%c#}_O)}8qW+^dr+ah9b8UpAsmaafPY^@{vuEqtb)BnoOt%MX@GiKW-SXl=b5397MOOd2MUBE}Vh!e+efN0u zuHxN?(<;g`SOo#S`TokgP0>}S1%z`<;o_d%kIPdd`0wrkG1YLF{SqccO-*>|J^w*C z_Gx1bO6f{f-<@6DnfNnUQLKV%vqy`{;RSt9U6#~E_P3c4dS=l-OAkXD^`@lYKn<)YOP?8^;?+=lp zLc?SzY7_<8hC;9(E-IAE6H=n=@G=hyvX`1cJWl2UhuGnL+?Y5=z5v2mk;o)6o~DAs z;iv+3AjQjR<0m-sW`_@k;V=paMn*=GA}vUKK@ezWV`Br7%|UZ>BH}?5M)P35C?Zd2 zG#BJ^94AN^AmD_-96k>xjqB&n4~OmWcq!5Rn9GwLFwYYfF5t>o*a0BKg+d`7ECkI+ zX5ja5FemU!hCJaXIS^q$=@$e>{w|CW1_xLoN;yX%`FuJbl4yX8R|vDg1rDG&nQToY zn-k4#!1?nb=~LMO6qo~ZA(?RV=aDJsz=glIO8uo0a5++CDO^8ZkR3jX$c6&_!nrV> z21jyuYQr&6m&8adezA}C(z#PEmdw_+; zZvo6;KFmk@Nx%tU@L)&~CO~>i#`l@--#xyK^@W?oWooSDpneM)0prcUh;mp-V=w*BwW z&m-JhS3{oFL3$}X)pJUDUD(V`qb)BAR1W)7$QlP&ux;%~Yjcp>A0fql%OA#t8`fv- z6V>arF;%s_#QxDqE9H;Ki?Hoab#gOXa;+oUJl~Or81J)AX`$Pq%;-}_qK+%q9Ga?Q z2eXzZUpbeSN>RFXTlB*p%1V1Y-b5)k;9qyV&S#m+n|79=?y=aMqsfqiKvqZB=-1sFoeq zZgF?8o(-792iEU0zb?^bPvky7;nR10;zKNWpqrX$-QwLwRs=A#L*2=Lwhg3qMKlb& z`f!?5^6@xtM=!u$(O@u$ZNf?hcGg;$`8v!#ki01(0N3||$Mx6juePfEP#ylZq2=!6 zvRP&fuTcX~N9XlBtfOP7ryu?#58ME>Xr6#Gadd}A)v);du3Shbj(+k+pNdM}nj^2M z)mDiKqT7&$)(S%?j0C(~8i(!J1oSzrjH@fWtq7Pa@5LTAd9B7`B^F+9s@?(MGH|;R zM8HcoKq=8G&f4hJT}6bV27Lw`-B^pg<9O1u&V;9`Yfd#*2K$t^KpG{`9s*FAt#44rK#$U|{(9$^ z#f3eR(b1G?$HXU$NAKjOF=c@w$un2CcZ zvr!@p-6XGzni36Yo;3(BhBQ@yN0?wMkK&@GHQGhm`Qn3zP+R3f?>`&;A6fc;V>r7z JUD~iG{vS!*mPY^p literal 6896 zcmeHLc{r5o`+rBuzDz0-8B-LR#TbmqZe+`v&~jupV`R*j8GDwHoh+dgkxo(4DHM`5 zM2nIoOV$=^gs4;M`;I#2)b;!RbFS<6{jYbfdFOfW<#XTn=eeKfdfth%voRABmK6p7 zK+M9N-~j#_^1g!W!21=t&maH@-VJhe;W`lgVJtS&o$f`2aRXUY7&Ut>$}t5i^sI(Mm{rFO4l z%ZlNUzQ?j~QO((%Ine{~+4kTIezt@O-PmRR6|X7PYi-vLJ@M`Pcr!gHv>sJiqxorq zd3;%!EN@A-zbMi}crRo4#p*a75A7kGT0$(2)wrhxV{k9G8R+SYZR)Mc57@f6F2f8J zdd#5OOzm>8;9U+ouuNf4B6UbFuLVD0{kii_*5Ketzlj^;Im;_Ft*bM7WNAI=imHLL zLA`BniE_%VHC!?DwZjn#WZ~YSXr`&7L{vldIw!})Lwmy?kdif)JbY&S?m?tD2Ni|z zDoKP-?n)Mjq$J7`vut~(hr`;mHGfFGy%dA+LG_nFmpnJBwa4bGkZx8)4krxFbxA+e z-AJmQY;^uZP03&DA?xMmcw*o-pL1>f^{Am`g_ewP*qtmrQ(3vIG~rht+W5u_bJYI(O)uvL;__JC!&)1jkx$&ZrH>>hk8^W=`Q(xWz`gm@=LpFjicWqpC@X5X@> zv}|m>Lh0T!zPEav4-5XDA$|QOrK`(HJ1X1$4==B#dsj54Bs#ra&et3z%vq` zH%9qkC!TP*umrhQnPTPHft8V?Y%EbwQnBh*E!fhkO13yxbtuKF3Q%2(6vd zQ>N#ebhk265fl2?UlZ+VrM(_v82M+8EiO`L^DrVLtAipBuuI41+JN@D*Gc5p_cb5C z%n>Dy^v>KB9js*Pm5=yK==Z|CiW?k-ciP0p^maP6Ro}!q3~e2~=L6e-yGSu}wDrR7 z54&{)9ajHXBtU1bBe>f6NVPpi8yItSR(QBBK;&?9e~!MmslfeR>z_G#4bhD=eXMGmK1WsvhqdJP#MRJS zj&9MHt_^clKBjz9|5^0;-gjY6&x<4UfoVs^9=WD`DI zZ^hDvPNd{Yiy1e2ltwsX;-iP(zK+FenPSr=v-UA8GBR|VggWD~#h zi~CNo?KL4;{A*J$gg)#Yh?8w@DiiY%@#I*a*xCB5q3<0~8)+Em`nz_+lcvJ?I=<$| z{9S1=HbZ=q$Acsi#QmIPJ-Tn|ZX9fnePmYmIamE`Qp|%f>!^f2^FsLUWSL;fY+y|#D&lI) z&0`nu$UvRG`f3?hYoKK`&tK@v1ms4C4JF;r2?)}|_vFKN^Ho-+IRN99@!?yeHW&vh zLVTQ}<|iBFq$1}dilI}N-L|!>UUZt4EH6oX4&#tbZ1O#oE1gtad^XesZRvWilomI( zlo*|zni-ZBdfvmJJLPIl?&$MRY?0jfry1FoHQTTmqe540%sA|Dd@ZbqF@-a{d8MIf z7!gyDHDPqSx%-&;Y!PxuF3#H4^R$={wv6BH#=>O$eZW$3IpmgjkD*Rx`JWLNqdqw` z3CXWtaD5C42Vq-(3sRgpY*@9pe%$^IT@ck?^}6A~Kzlg* z!Fs>8Vu&gk_i6L?xR`jW^yq_i(f^`!?x+#rrwZ*?yy#b*D((f#xvI(+7s?PmI=Lc|4!m~7HvHC!IDn6 z?v(xd6)`?jx8_GsNE`n#uYpekF^^JR2XUKrT`vu2WYon`tj;Vn^a=2@w!6Cydu@Ph zz-WFo*tPd_!3l)od!LtmqgUgl(i5&5;;RqJz2AQ;d5x5si;&!i@bP7qAU|KySk%Vjr$Ts$f1t`(Rm&jKNNnCuOJ>^V)^g;VBFmlH zvi8PmHZya3AYU*V$(QqXS8Oy}H0c@kpxuE!|GF8rW>--_T&C1-dwoY!hAtU)4p_FT z^o^Sv&*4w4?}TD6c)8}Pxkc|M=vI_fI9QS^9U>%8BZ4;DPJYd{+o|N-FvohaW5{3Q z#Ct#Gh8x_xs)u;1s0-0@@8$2pj-LzmNWNqib9kli-cqX5@y@efW|zN08aFz1#Xj0( z1Rii?>EJ=e#deu=;lFe>b@WwM{>|nvJM4qpf9W&fCm8>R4x$~!0__s-~;sFtGIY@%oC&F zuvHW8Q9ZbewH?fa$)>`vNGuYKFb$ylVc`10FkLpq9q&Nc^Bn?w(t~?&xhy;icMdY&x0rjDu?OI zCR0uQsNURdKSEH*fBUn1*K$Y7AOgTjL2#vM(<^3xXb;7avbylIaxu>QIY{ zrIN{L41!A0#v!oo8bkyUhe0EB)O9r7acD9Xjn@7F%EFt&C3=&oJSY$xNe6LAXbl~T z4h4V<`jE)XPQ99-Cc7PibBTkVX_%Sa60J>B8`e-dDB)EJi_rtb{2YY z3=;j1#LkPzbq5{v;Ct!bz5)Lz9O(?|J}!~Rrn(juqobjvp{1>k#cH9y1zN>(qOv() zC-N}W(MSw#)txsjc(53dSR$`aL4Z{`SPR~SO(k-fY)2;3OApS2fbl$6+Z(3)ZBoqX z9MB?=*YV$b-k3=H_VjHDc+po?FxYC_;)&#MK{!M|DrGeg==V)U_8@xGsNnkk-cWzZ z>HlT2s8lT~TAS*Q(ALxe8765_5kx8#gCMDEQ%GctJ61~z`!hO+>CW{hvZ+Qiuu`xZ zuz^;qf$dzSQsrlBe-A2;Cp5UW(dr0{h9d@pSI6M7+G^_Rcr+T0`d%=Kx2pfDSQqtw zIMH1-_+c9W{l3Y-?FHPeP=9Y%-#O#a_&>b9&&B^R0to#p$iL$E7hS*T`d1A6E8}0? z^^2~5#lXKZ{?%RoZ*&R&^TI>*22Vl$;OmT(=6JqY9PA^zK*uAgu5w zv_UjT$$gS@;dB%&W?{_$&4`24goH0uxFPmfU=; z_fe!#he16vRTiC62hW5VhbO99?rbzp^h??xrGh^h{6Rpz)*N}}uo9ZRE01qu+L*xC z$e~ir1*tJ_2b?&!=J`?!T5@2mtY-fg{aZ85LXrXNO3E^89Rw~JSX?hJ8;3qA6+3+R zHa1YAVgRx(m)n{mr(*cveEXVN+M@M=yxC2H*D5(jbH^4T=Ff`LwCm~>(GGdjz9;?t z%iCv$a$kQA1tOsAYjY+m$H14Y(JK=wHqP$am1YbCqGh0sg)?Vj4>TT{&ee2won*d#aWYo{ z(QccKJg6WXIk)dMk@V?x*)BPE=1%YLf z_<=HsPu-O0R}~(0%%=^tZ-wvsy3&9;*+J6SV?HIbz8hEKi_h?J1)jWCA#QRqaR|wA zv+*jS%q)ELiGG!r!N-+2KH70-^A-5Q`Dh$~E{cEn^)X~2eL6#cb;JXA)4Aeg0i^cT zwEvCkaa|3y7EItoN&nr6;@ZXjyum$yAOL{@{NaGi^A2RxB9dYb0Usm*K0}`7!;xpx zmc>a>!fzP4} zh0zX%36~S0I%b_SZKdT}f~TiE%Qo+U0O;vM`{ZwWEQ5RjDKjhwdAHM&01L?<{%jCv z++JU*ILB^F;E_6VtG=St@J94)m*Fz)I=g;15=ZH3jSU)A9DPyCHtsF(Fk8jVZx^Si z_6*HMyyiADPZe`S_hOhzu~2wZjk44D)~qjnGJk%t9%_{QEn%PhDh=NV>MpcTGyaDg zbn%2fhBG^oelg$7-Fr|~-f`pRB3H=%R0v?aT(O9f?6}5%eL~D_xyA2&boqzj{mjcs zY>LI8WbRfkRG3@NF+a9;MbL;ueC)__7G6N~Lw8s9ym4qy^I5d?{;jg!EKJw7lpytv zAeMta!1*odR`oYz159E&y8=xg3>a@uB_$oUi!(r4JP%(mubqnM~1QVvNa%J)z8 zbxJkU+qrD?H__Em3JcLX0hytSh8?9g$P zdV)?sww3!{JL^M>mL~P^u1yR`qMA$8uQ~V~^N6=*3}4Y!Rod}3%k|LnVxmE6WU=S( zM?cl|EKKY*qf!x~zwS@0+4I^`l&G^V+v(IpOq91s*WzXSSc{hfIsaVQ?YYz8W*AW7 zX(O>ay?jJf1Tjo|BJP^ywpccjubKTX$4R;N=thHp&K&i@1Em3-f2$2%der;R#fQ5a zFFgP4?in@i@w9XM^anS1O=XO!Ze%;QyI0K%&kMVucXMx8wnk#jqDTMj%e*z&Z8-h3 zK$OZtQh7Ibp|PCwlvRb0n+n1Wv)vm~`*;uAdSc{xe{)mk=#tSV>0+OU;U{>NDp*}+ zMXZ8>E?pY9Z)Z?}WZpH#JdU8>ZAsZn%!8D>i>V)lZSC-$y3qEkF&V{7Q=O2HT}6XB z)%BZHoi9`mH2yJEa{a}8jndjqB2?bDzt#G~e@us;O_eGw6-*n8nl`Vi?4O$~tDY7! z&^6N26Id$StH`E&-1plhTUB{3L2&?}t}UN1ptwX202J6P|3E0v(}NhnjWrKraKoAA z!dTu6i!3C{wy{ho3?+b0KwPwbzF8T|SsQPh&|2N?r^;;^fuy}u9^!O)|l zPM>O=;V@5>wG6a#H-q|_^khYRykf^WA~EM&Yc9Y46W$GENy5t@=l zE)RP>t@J>-?C?M)e!scqpCYknigYQSa!3J$H|-k8&XFDr3A?m`k3rzI%Fi3r90n?# z`>LcT*IwN|oO`7?wUNAx{?ZWeS=%q{Fg4#uH!3SU5(7vsCloCKld0N1HS*IPCWWE-N(CX#)cb#}K(q(jZNh3i+ZSUJ-52vdDMp}T-uElAccXXxq8 ztH0i71FO0S+hX6g_61-w(n51FT8Fqgfy{*~o^PHS8!%S4DVh)p^)G39h@?|@M~#>G4`r(Q@s5^J-GuI8>wAZLZ3@^wnb8kww|V=B5pyV_=~3-Hn-U9SG(Dcs?jhj- zzOHwi?DUdgy(v=L1fIJ%9EotYJOsndkJyc*?l=PYu86TYzQ7Y!hYxUl+m`7KLt1Zf zQH^D&k8b*E#71F z2HEXrJz#O?Z2~20nMZI#H`YQU_te?STde5~_pBnjds5kDHxQW6M~ z$rjDVQ8qv0;vgAZ8n9&;@w~%*9zUcFPNk-+|T0dHUc6z8(8l~iX zvjx5;Xpv>S*zVK2L235xwfg!@h<2<8L$Zbo*Dcgabdyluz$!1{cOm)|?$y|L7usUZ za%t+v!(y^G{B3dqlVR6w22?SO`rZh@gAP`j=!xFCM*|^S`tl2R)hhzZc>Gfv`V)-& PzruB;m*c4w^tAs2eU4hf literal 8464 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 K>J(`?NB$R18wZsD diff --git a/Resources/Textures/Structures/Windows/tinted_window.rsi/twindow7.png b/Resources/Textures/Structures/Windows/tinted_window.rsi/twindow7.png index 17304ce1044032ee392be2dcc63be90d6580eef0..7ca4d7214fb770ce7965e8b028426e5826f30600 100644 GIT binary patch literal 1661 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 F_6HOSG7bO$ diff --git a/Resources/Textures/Structures/Windows/uranium_window.rsi/full.png b/Resources/Textures/Structures/Windows/uranium_window.rsi/full.png index f7b6e10f869a9ba3ee1d2f09f066f153b5e21e5e..0e5df9bea5d2dc5ee7afed871d381036cb12d116 100644 GIT binary patch literal 2364 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 diff --git a/Resources/Textures/Structures/Windows/uranium_window.rsi/meta.json b/Resources/Textures/Structures/Windows/uranium_window.rsi/meta.json index 099201b41849..8d594817c682 100644 --- a/Resources/Textures/Structures/Windows/uranium_window.rsi/meta.json +++ b/Resources/Textures/Structures/Windows/uranium_window.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "resprited by AsikKEsel | Original source: from vgstation at commit https://github.com/vgstation-coders/vgstation13/raw/99cc2ab62d65a3a7b554dc7b21ff5f57c835f973/icons/turf/walls.dmi and modified by Swept", + "copyright": "resprited by AsikKEsel | Original source: from vgstation at commit https://github.com/vgstation-coders/vgstation13/raw/99cc2ab62d65a3a7b554dc7b21ff5f57c835f973/icons/turf/walls.dmi and modified by Swept, transparency tweaked by Ubaser.", "size": { "x": 32, "y": 32 diff --git a/Resources/Textures/Structures/Windows/uranium_window.rsi/uwindow0.png b/Resources/Textures/Structures/Windows/uranium_window.rsi/uwindow0.png index 7be507678d49517ac92392e78b96843349952311..ff5619c5194db935b37d8bfff14fe3fffb89df48 100644 GIT binary patch literal 2857 zcmZ`*2{@E#9RJ3BCq_}OhJQoTG~IMo4<^%z6gVp)ausF6LJPJL6fjtu6+xvj(JWio zss~!I7n%_;?Nt{r+!luO@Y3E%XHc}w;Yc_VW+$Vqt!={~hoF5Noj<|_CtFx32u7k2 zh}hUzc&sU$&NzrLv9hv4AW;Yu%2?oG%sfN`gIUHjrp{WBPjMV6OcEn35)7l$w1shl ziS%gD76ua%eI9Fhl1ZO=BBL49RTeS{L7`G2C^V3XFoByOzJ~+DLcU~3V}6uFAPhqI zMgT*87lw@lNoE42oLGWALOs0ecM^izVU36?1jZBZVutBVOeT!bR zejC&V@g05}Vb$opJ`^UM8ZFe_&H`n#D#bU(FBh-|zZ`j!V;Ep8oe}Q0dJkVj{9l)kVb%ow zsz2A7e^q=z_uI+XAU=Odb~0xA(}4gWX@hmd_^}|P_;4z85A;Jw$iZKGYa8%4OV|Vh z4%a9p6!{O}Zsv%M-=?d(G^q6f#gmlQ-ITdr2^)VRacQTr$oe}{p<>F)uyx8XOi-b%?sB1 z{B@}p#TnZ>lRNIDK4a~)Rc&|QY-iHXaQD22*F}=co40Fr006DgZ_+WgSazz~x_bos z$4xOOA8+C*d#v*hPjl3y@4T5~dJ#3Jl7A~w1)wSNDlFO^!*~=!E>y2jSwcgz(je$Y zyWY`;RLxv;mMTy-ybx%3<}r4ezVP_kuJouUt#7Zu#>)O8&PxyhukI%<+tV^%gp|vJ zJfwsN&sHnC(ZuSV-_%QE!tNV;l6gb+rP41VX`EghAJY!BCWtL79icSW6?O;;>vCry zt&zR){mIY->fGkbX`VXWyonu&*M_cqxZ4IiuBA-fZqm;ZZBJjyG|P8fEV$r#slwVK)uTUB#3$2JN|CTH6j9BGVx3{^w?SgGO`b#Af*|ctFSEd0-&%9+L8b7OrymTbDXLBBHLN_6w!tCJAdmZ#1w#J4Z@Uk`lHaOlIn zck)rY*S|Y6F&97O1{&He=HW6fytnvSUDV5!Wpb9RnmwQ5$BDTbe3`SKjtb@Aq0_Ha zEe}06LuR5`)nI6&nx(|!hPSf?aq7boQPZehfxy**UZ#Q}uWnj=8au^s*IvgVg0;u!ykz`8+%)n$93jkPie;+Q*+G>y-b2r($C}sa?UoW|JBd=pN)GDZ(c8mC_ zU3fN3+WZ>7*|zU|rmbay*!V@hM0Jz81*X(k4HvrParuLDr_HG_GwHHJzl0QAFJ`WP zQgryJx5={uUBEAN(sEO_kDL@Y=G}aFrQOLwUa#s8^!y>eSC~-ocKCf@jK7$`~r;<9ktt#w?T$HTh@j8fN%%MAm2Dn;n zqm;=Fn@4~w10CI7n%F1?RB7h`YGNaR{?#M?*)^;r;%u6JfZ60UE0OKn+&?pawu<9& zwx}h)M#Z|Q;pH)gf(AaFla~FeYlL2D$vfI0?%qlD|21%uqlUUrPI>?LaS`p(QTqc1 z4tW0C8y)mwLpRxOP4%ib(zV^Wr%MbqH2h^n?H#r~V%s>4wI{Y8cGbuFyG4vvZG7Q< zI1wQYVQ<-cRQZGhx!)+W^Yn3m%^&{BfcYoaj0qjx+V!tS5Q9sQci(xb@MP6u5vHHFJ~pzTMn3%y^(Z=YkPd>WWS!`z4WE~v10f8 z=4GFbS1b*f4$jNNi7Q8!$Un`?EaWJjd{gKYsONh-jdLp|x1`5xdgVd>hVehl_Ub~9 zqk@hP*_GdUcCyHqgq4%cs;cwU@<j_kM*&+w0RhQhb}m`j<=RvbgdpOp$A)=OnoY z3Hq;k45dYYKTIQ$%!2vk9N#~yQVfRMy34O$c}_xGU;G_jB^R$z#sjWTBYTw|8OZYG fOI@MCpyLX}L1tmg{Q24<;cqI|$%TZkN08pnU9 zE`9ImPG+VvSuc}TNYsuuWK~#W6c;g|E&&ly9~bsb6hs(sciAWkqO!10`XC5KU0e-b zgUhmB5@862WMd{VF49O9c0^Ri1XoI;F8i!9QeB~rhX7{V0&JgG3lEaZ zXBn_cghF5f0e^6;@i`wK{S+w#S6#H8i}Phx8~w`E@eqInw|m2Em@0G6;6K0(AQTwF zCX_&6P_!fzquQ@m_hZjR7BEwKM~OKe0(chKaLZ+zcxHANkPrj`)O{F8@TVh}vwO#Z&TY4=QO837&*2?=ihqZ!99xQIb~4WH9S5+V?ElOE zn|e9h>KP1Su+y8=%c+&^r;vyyv@hn5X{U~d0FKKLDSne50uu%;ecg(O0KgOu?~i?` zoi{cDBt+!#tqIe3?cX{O4*`T=wM_E+OK!l|9Gt~N03*8TKD)>!yF|U!9Vcf+)Y_O< zfQ*>|^nXr*LUldhnv-|k8g{rwYoxl(ezKpF(++Q~`y2O<|CO)9X)4d=l;e3-C`;Yx z=Hm{nLm&uT=A3DrlpUc}fU?=ge?H$0_&{1G^-n@uFjRHVvWSTx1PdD9^PQm00{YD8 ziC2a<=%QQ^vs05?Ki;GFd#p~~DHC=1Yd)aHa4J<&4RW$V1s{Df-K=e5QGZd-K& z!)Au#K}fXg(OalnKt0V`pe8(~&N1zxj2>}KcqF9-i;zu9Mvv@;43Kt!q$<5Klm+A1@56M`@z}+XK zDPSU;=Fueax8wII?9C=Y?L z2O8&;&W-SzV79lgrG!kIDy&CGqdSH-@4M34twJ0JMb7cU!qBe6kV_ zHC;#tu&@UD90*$cB3^^<4nIa9B!}k@@!8~I0DgPHl_W_roGSz11}@{y2_|Z%cz?L> zHTpuEc~R#VA;2A9M*Ej7;ZU-3oRK~+PVK>#DJ&7CvowL4bio!pg(O#8cp23*ufpkg%)iP43_jlc(SHrx=v=$J zb?X&8S2;qhn!tm@Eg;t5_iI z^@MggXcM4fr6~%7t1hnSqFfQQ31A3;X(lNq3Y5KgOn}gXAuyC&8~w22;eQJ&FNmmO z<9#=cjy=4{I;+G#haTg(nU{Fm+D~a)up%dG--WOLTZKO!4tX1nj9lnhKh(wv` z3||DNew}%O1tZD3pM3;CPUy=Wh>ZaC&_(nhZy*)|2qOo;T~}|>&K(N@q&N$JiA7H8 z&ESuP00fdr;gUD?J4o>mpnnaYfCZs9cOV{LjFWY^JsREr)sAtfu# zOk>F+)`~2r%aIZg~{}xv!5na%s SNQM9a002ovPDHLkU;%=37y;b? diff --git a/Resources/Textures/Structures/Windows/uranium_window.rsi/uwindow1.png b/Resources/Textures/Structures/Windows/uranium_window.rsi/uwindow1.png index 9979f28e945787ba4ffab8d70010c70209c7f274..cabe60b557955cba753348a64b5bc1ffb7516eec 100644 GIT binary patch literal 2288 zcmZ`*4LFqP8ve%kolQc!6fupGWPD7-jF~~kU)yN>?ucqIV+`|W=5uBgnQ)SRv{9KX zW_DGalGRFylWh8%wpi`zhh)^rbsTFVDvP%B%_ym>eXr~Nd*1tgp69*a=ew@2kQNqf zidu>S0Khafgc1SIe%fwq2#=>Y>5t(FA&v-M57c$o4#As+EP7}%l?ph+Yh$=;+ug_# zcr+1)#EJpn3rlTB0A=OY0D$CjqUaEvx{;71;JGF+1&J(IDNm?l5v2rp$zwqYXep1& z7Zao;j1ED7*IF}(LF*t;8VN(E($E0{5evP})y>rnLq?&|XrhRjOo*Tay`#fB5+((L zgaisXOPnO)2qBJukJkE4 zNEBp1Bn(CyXs*rX$xNDyBg_zSby1i}AdAc5vG|Y}ba!$>*i^GF+_k+_XGLr}p2ja4H z!p+@Br=UL<`q-+)YbD@vw8|2=34AsQBgHaV$q5-;2t&@0aQIAt#ES^dqCRHNT0eG5 z1V0m>sJ%5IHi9JJlf7_6ofID#KRm!Jf&MwdeB-ACT8aP?!1W~JB!%)JmPjaq zYfBgJeYn3zeCq2%>}Wm*BENU=iFqDt-rErTMUX@wN{iCH!v_)n7V^%`tf2GibGG<( z;=|QXMiIfeFNuuuaQY)201S|!6#pnGVkE9V%^`a6U$_zlwTJH2doS0mo% zYi_T2STJ%Dud3jDhg4l!drYh$^^+un9TL9YC>;k@mX|`ycZ~JkSUKfiDDs6Ge&jt& zc5y!M;}Uem?^3G5IB;ZpjsFc#B}Xr)_?D?Uu^`MWx)UMCnf3NLD)@=}`q~#`n!+;b zpRQmF&AOw%+?IcIWJASX<6Y>(GTOFUvSOPYjAJcMeLFDR-x~g^@=p1c#wX6n#SQgk zU!6LDTku=kiIvl@*|=5aUP0ZB)h88;sfbR5cgyJBW}~bN8K(a2evgGG^@Dv>LpMDJ z*X=aAUcN|O(&b1yG0MiDb<%4aUp<=5G)RlFRM8ii(nAgjT(XK-3v&Ryc3hX-3rcKdb!A?JE!%F^Vi7t$%c>WM5=I6sdGa`=>$!3=9RL?{>Xn@ zBEdoz6NTRHnz3vpQJ-PI;D?+4Owiw>?lrpAZv4O~&q*}U7A%|GqV77~*%`81{o*$J zo0U@$eMoym0C0Tyx%)2*%s{SXdpRl~=wwHSxc%XK?w7 zA|KVA^k)Ih$!xAD#-K~O$fS%_MH#c={AbG&gH2X(M>l0%yzm@x-o~RWF8av1o5#Fl zsAm&bOrwT9e~qohcQjvH>dfyRk02W0?0Za5vOJaNjjBtL!UN}QOC8s3-o3rHiKGdy zxC>c1ogFwn&S&S_AL$ZX-hB4;FA} zK0A-q-Iroi&(|l7mZln@c`M3EK>2i$>EjmH&5Qbx%_#v}UI@JwB$ZBO{cg5MU z<7-y-EO=_wW!PqYrhttMt`7&5&6xnA$vvjM`h-E$ev7+~Bt0z8Ot~zN8mG_bqhM0h z1#5hJmhBx&D}Mchne3{w$RV(2;(?!Q{0c*reHtPgK-bc%8q6xs7gW5S`O|L#;rASI zCcBkho!$D1%=pp$S0muLX3(?)tGbZ7HHN6zGn2FHkJBt$&sAe%6Fa1ugI?cOZd6VU z`Zhgv+|c8{yhdq58uDyKC__jC zt91@cfvxHKtq7U+T)vi}@hhD~0#6L(4vab(9yz!WD)a?}O^8npY4M13L-Z`Tzy^j& z%4qy8rEkfxMoxU0x1PndB`I0>`r-!Z&dz>E!M#+_d&@BQ!9KQn#Lw F`+wtyizWa7 delta 1205 zcmV;m1WNnx5y=UVB!3BTNLh0L01FcU01FcV0GgZ_000DgNkl&HWrgUS7B7#0x#fMTMv@iNrAN&)<7a>@oC4wOMN0_(xpirp@Emn{O zf?%jkXdW6i*f#g1+1q4xX2*xwT)b_hXE|pi`+1o&yXWlpw}0Q6Gkf^`&Wa!i(8=)C z3o|m~?@#{pn#}l^%-~iq|B(|m>H>~l47(HD#(S0>wk;2E!8gIofd5olU%LVQvEGCB zme|7$0{XF82^{F?1Yj%}fDRylo7Pg;t^syNT3@>X-}FsT@hj}scDViEE&vzvZ}X(| zgtO@vs0VebUVjC{G`X|zBj?ESR{jl=BGnRoq5BzdW$uF+fS=tJVnVQL?1gXm;o%)? zfLl8cA=7aqL?H}Qa;#`ReD>Hys0cQ|7KE|d&N)uECA z0R;Wh`q~ZXxlyABIJo5dum7#5dE~eUbce@DIeqO0*nbnf*L3O|I>n{yJ~hh8NfqLt#G1JHyU%PHk^io(W z^KEv5_aA-2Qhk;Dmx-q1R3N<&I_}Fy9i=Nl->&XX{@N~%jBgzcu+JYf5$WCn+r+fkp*i7#+Ri2|NN@UGA_}X{p04k@zwn@?y zOfSxc=W$1wbTiZ$kbcZ^vWVk(6s!^$(SJxsDvZKn%*}B*e`Y?BJAC zT0I&Q@fm4FE+SF}Y&fgDI0}O+LRl@N+mXk$D zKUOELOsN@-+`#4hCC1zwU@4Q1hAsh?4Qv99{|5Vh^ZqR)8U`HA4b%v82a5Ou_vlqc T5^UWA00000NkvXXu0mjfkY6^b diff --git a/Resources/Textures/Structures/Windows/uranium_window.rsi/uwindow2.png b/Resources/Textures/Structures/Windows/uranium_window.rsi/uwindow2.png index 7be507678d49517ac92392e78b96843349952311..ff5619c5194db935b37d8bfff14fe3fffb89df48 100644 GIT binary patch literal 2857 zcmZ`*2{@E#9RJ3BCq_}OhJQoTG~IMo4<^%z6gVp)ausF6LJPJL6fjtu6+xvj(JWio zss~!I7n%_;?Nt{r+!luO@Y3E%XHc}w;Yc_VW+$Vqt!={~hoF5Noj<|_CtFx32u7k2 zh}hUzc&sU$&NzrLv9hv4AW;Yu%2?oG%sfN`gIUHjrp{WBPjMV6OcEn35)7l$w1shl ziS%gD76ua%eI9Fhl1ZO=BBL49RTeS{L7`G2C^V3XFoByOzJ~+DLcU~3V}6uFAPhqI zMgT*87lw@lNoE42oLGWALOs0ecM^izVU36?1jZBZVutBVOeT!bR zejC&V@g05}Vb$opJ`^UM8ZFe_&H`n#D#bU(FBh-|zZ`j!V;Ep8oe}Q0dJkVj{9l)kVb%ow zsz2A7e^q=z_uI+XAU=Odb~0xA(}4gWX@hmd_^}|P_;4z85A;Jw$iZKGYa8%4OV|Vh z4%a9p6!{O}Zsv%M-=?d(G^q6f#gmlQ-ITdr2^)VRacQTr$oe}{p<>F)uyx8XOi-b%?sB1 z{B@}p#TnZ>lRNIDK4a~)Rc&|QY-iHXaQD22*F}=co40Fr006DgZ_+WgSazz~x_bos z$4xOOA8+C*d#v*hPjl3y@4T5~dJ#3Jl7A~w1)wSNDlFO^!*~=!E>y2jSwcgz(je$Y zyWY`;RLxv;mMTy-ybx%3<}r4ezVP_kuJouUt#7Zu#>)O8&PxyhukI%<+tV^%gp|vJ zJfwsN&sHnC(ZuSV-_%QE!tNV;l6gb+rP41VX`EghAJY!BCWtL79icSW6?O;;>vCry zt&zR){mIY->fGkbX`VXWyonu&*M_cqxZ4IiuBA-fZqm;ZZBJjyG|P8fEV$r#slwVK)uTUB#3$2JN|CTH6j9BGVx3{^w?SgGO`b#Af*|ctFSEd0-&%9+L8b7OrymTbDXLBBHLN_6w!tCJAdmZ#1w#J4Z@Uk`lHaOlIn zck)rY*S|Y6F&97O1{&He=HW6fytnvSUDV5!Wpb9RnmwQ5$BDTbe3`SKjtb@Aq0_Ha zEe}06LuR5`)nI6&nx(|!hPSf?aq7boQPZehfxy**UZ#Q}uWnj=8au^s*IvgVg0;u!ykz`8+%)n$93jkPie;+Q*+G>y-b2r($C}sa?UoW|JBd=pN)GDZ(c8mC_ zU3fN3+WZ>7*|zU|rmbay*!V@hM0Jz81*X(k4HvrParuLDr_HG_GwHHJzl0QAFJ`WP zQgryJx5={uUBEAN(sEO_kDL@Y=G}aFrQOLwUa#s8^!y>eSC~-ocKCf@jK7$`~r;<9ktt#w?T$HTh@j8fN%%MAm2Dn;n zqm;=Fn@4~w10CI7n%F1?RB7h`YGNaR{?#M?*)^;r;%u6JfZ60UE0OKn+&?pawu<9& zwx}h)M#Z|Q;pH)gf(AaFla~FeYlL2D$vfI0?%qlD|21%uqlUUrPI>?LaS`p(QTqc1 z4tW0C8y)mwLpRxOP4%ib(zV^Wr%MbqH2h^n?H#r~V%s>4wI{Y8cGbuFyG4vvZG7Q< zI1wQYVQ<-cRQZGhx!)+W^Yn3m%^&{BfcYoaj0qjx+V!tS5Q9sQci(xb@MP6u5vHHFJ~pzTMn3%y^(Z=YkPd>WWS!`z4WE~v10f8 z=4GFbS1b*f4$jNNi7Q8!$Un`?EaWJjd{gKYsONh-jdLp|x1`5xdgVd>hVehl_Ub~9 zqk@hP*_GdUcCyHqgq4%cs;cwU@<j_kM*&+w0RhQhb}m`j<=RvbgdpOp$A)=OnoY z3Hq;k45dYYKTIQ$%!2vk9N#~yQVfRMy34O$c}_xGU;G_jB^R$z#sjWTBYTw|8OZYG fOI@MCpyLX}L1tmg{Q24<;cqI|$%TZkN08pnU9 zE`9ImPG+VvSuc}TNYsuuWK~#W6c;g|E&&ly9~bsb6hs(sciAWkqO!10`XC5KU0e-b zgUhmB5@862WMd{VF49O9c0^Ri1XoI;F8i!9QeB~rhX7{V0&JgG3lEaZ zXBn_cghF5f0e^6;@i`wK{S+w#S6#H8i}Phx8~w`E@eqInw|m2Em@0G6;6K0(AQTwF zCX_&6P_!fzquQ@m_hZjR7BEwKM~OKe0(chKaLZ+zcxHANkPrj`)O{F8@TVh}vwO#Z&TY4=QO837&*2?=ihqZ!99xQIb~4WH9S5+V?ElOE zn|e9h>KP1Su+y8=%c+&^r;vyyv@hn5X{U~d0FKKLDSne50uu%;ecg(O0KgOu?~i?` zoi{cDBt+!#tqIe3?cX{O4*`T=wM_E+OK!l|9Gt~N03*8TKD)>!yF|U!9Vcf+)Y_O< zfQ*>|^nXr*LUldhnv-|k8g{rwYoxl(ezKpF(++Q~`y2O<|CO)9X)4d=l;e3-C`;Yx z=Hm{nLm&uT=A3DrlpUc}fU?=ge?H$0_&{1G^-n@uFjRHVvWSTx1PdD9^PQm00{YD8 ziC2a<=%QQ^vs05?Ki;GFd#p~~DHC=1Yd)aHa4J<&4RW$V1s{Df-K=e5QGZd-K& z!)Au#K}fXg(OalnKt0V`pe8(~&N1zxj2>}KcqF9-i;zu9Mvv@;43Kt!q$<5Klm+A1@56M`@z}+XK zDPSU;=Fueax8wII?9C=Y?L z2O8&;&W-SzV79lgrG!kIDy&CGqdSH-@4M34twJ0JMb7cU!qBe6kV_ zHC;#tu&@UD90*$cB3^^<4nIa9B!}k@@!8~I0DgPHl_W_roGSz11}@{y2_|Z%cz?L> zHTpuEc~R#VA;2A9M*Ej7;ZU-3oRK~+PVK>#DJ&7CvowL4bio!pg(O#8cp23*ufpkg%)iP43_jlc(SHrx=v=$J zb?X&8S2;qhn!tm@Eg;t5_iI z^@MggXcM4fr6~%7t1hnSqFfQQ31A3;X(lNq3Y5KgOn}gXAuyC&8~w22;eQJ&FNmmO z<9#=cjy=4{I;+G#haTg(nU{Fm+D~a)up%dG--WOLTZKO!4tX1nj9lnhKh(wv` z3||DNew}%O1tZD3pM3;CPUy=Wh>ZaC&_(nhZy*)|2qOo;T~}|>&K(N@q&N$JiA7H8 z&ESuP00fdr;gUD?J4o>mpnnaYfCZs9cOV{LjFWY^JsREr)sAtfu# zOk>F+)`~2r%aIZg~{}xv!5na%s SNQM9a002ovPDHLkU;%=37y;b? diff --git a/Resources/Textures/Structures/Windows/uranium_window.rsi/uwindow3.png b/Resources/Textures/Structures/Windows/uranium_window.rsi/uwindow3.png index 9979f28e945787ba4ffab8d70010c70209c7f274..cabe60b557955cba753348a64b5bc1ffb7516eec 100644 GIT binary patch literal 2288 zcmZ`*4LFqP8ve%kolQc!6fupGWPD7-jF~~kU)yN>?ucqIV+`|W=5uBgnQ)SRv{9KX zW_DGalGRFylWh8%wpi`zhh)^rbsTFVDvP%B%_ym>eXr~Nd*1tgp69*a=ew@2kQNqf zidu>S0Khafgc1SIe%fwq2#=>Y>5t(FA&v-M57c$o4#As+EP7}%l?ph+Yh$=;+ug_# zcr+1)#EJpn3rlTB0A=OY0D$CjqUaEvx{;71;JGF+1&J(IDNm?l5v2rp$zwqYXep1& z7Zao;j1ED7*IF}(LF*t;8VN(E($E0{5evP})y>rnLq?&|XrhRjOo*Tay`#fB5+((L zgaisXOPnO)2qBJukJkE4 zNEBp1Bn(CyXs*rX$xNDyBg_zSby1i}AdAc5vG|Y}ba!$>*i^GF+_k+_XGLr}p2ja4H z!p+@Br=UL<`q-+)YbD@vw8|2=34AsQBgHaV$q5-;2t&@0aQIAt#ES^dqCRHNT0eG5 z1V0m>sJ%5IHi9JJlf7_6ofID#KRm!Jf&MwdeB-ACT8aP?!1W~JB!%)JmPjaq zYfBgJeYn3zeCq2%>}Wm*BENU=iFqDt-rErTMUX@wN{iCH!v_)n7V^%`tf2GibGG<( z;=|QXMiIfeFNuuuaQY)201S|!6#pnGVkE9V%^`a6U$_zlwTJH2doS0mo% zYi_T2STJ%Dud3jDhg4l!drYh$^^+un9TL9YC>;k@mX|`ycZ~JkSUKfiDDs6Ge&jt& zc5y!M;}Uem?^3G5IB;ZpjsFc#B}Xr)_?D?Uu^`MWx)UMCnf3NLD)@=}`q~#`n!+;b zpRQmF&AOw%+?IcIWJASX<6Y>(GTOFUvSOPYjAJcMeLFDR-x~g^@=p1c#wX6n#SQgk zU!6LDTku=kiIvl@*|=5aUP0ZB)h88;sfbR5cgyJBW}~bN8K(a2evgGG^@Dv>LpMDJ z*X=aAUcN|O(&b1yG0MiDb<%4aUp<=5G)RlFRM8ii(nAgjT(XK-3v&Ryc3hX-3rcKdb!A?JE!%F^Vi7t$%c>WM5=I6sdGa`=>$!3=9RL?{>Xn@ zBEdoz6NTRHnz3vpQJ-PI;D?+4Owiw>?lrpAZv4O~&q*}U7A%|GqV77~*%`81{o*$J zo0U@$eMoym0C0Tyx%)2*%s{SXdpRl~=wwHSxc%XK?w7 zA|KVA^k)Ih$!xAD#-K~O$fS%_MH#c={AbG&gH2X(M>l0%yzm@x-o~RWF8av1o5#Fl zsAm&bOrwT9e~qohcQjvH>dfyRk02W0?0Za5vOJaNjjBtL!UN}QOC8s3-o3rHiKGdy zxC>c1ogFwn&S&S_AL$ZX-hB4;FA} zK0A-q-Iroi&(|l7mZln@c`M3EK>2i$>EjmH&5Qbx%_#v}UI@JwB$ZBO{cg5MU z<7-y-EO=_wW!PqYrhttMt`7&5&6xnA$vvjM`h-E$ev7+~Bt0z8Ot~zN8mG_bqhM0h z1#5hJmhBx&D}Mchne3{w$RV(2;(?!Q{0c*reHtPgK-bc%8q6xs7gW5S`O|L#;rASI zCcBkho!$D1%=pp$S0muLX3(?)tGbZ7HHN6zGn2FHkJBt$&sAe%6Fa1ugI?cOZd6VU z`Zhgv+|c8{yhdq58uDyKC__jC zt91@cfvxHKtq7U+T)vi}@hhD~0#6L(4vab(9yz!WD)a?}O^8npY4M13L-Z`Tzy^j& z%4qy8rEkfxMoxU0x1PndB`I0>`r-!Z&dz>E!M#+_d&@BQ!9KQn#Lw F`+wtyizWa7 delta 1205 zcmV;m1WNnx5y=UVB!3BTNLh0L01FcU01FcV0GgZ_000DgNkl&HWrgUS7B7#0x#fMTMv@iNrAN&)<7a>@oC4wOMN0_(xpirp@Emn{O zf?%jkXdW6i*f#g1+1q4xX2*xwT)b_hXE|pi`+1o&yXWlpw}0Q6Gkf^`&Wa!i(8=)C z3o|m~?@#{pn#}l^%-~iq|B(|m>H>~l47(HD#(S0>wk;2E!8gIofd5olU%LVQvEGCB zme|7$0{XF82^{F?1Yj%}fDRylo7Pg;t^syNT3@>X-}FsT@hj}scDViEE&vzvZ}X(| zgtO@vs0VebUVjC{G`X|zBj?ESR{jl=BGnRoq5BzdW$uF+fS=tJVnVQL?1gXm;o%)? zfLl8cA=7aqL?H}Qa;#`ReD>Hys0cQ|7KE|d&N)uECA z0R;Wh`q~ZXxlyABIJo5dum7#5dE~eUbce@DIeqO0*nbnf*L3O|I>n{yJ~hh8NfqLt#G1JHyU%PHk^io(W z^KEv5_aA-2Qhk;Dmx-q1R3N<&I_}Fy9i=Nl->&XX{@N~%jBgzcu+JYf5$WCn+r+fkp*i7#+Ri2|NN@UGA_}X{p04k@zwn@?y zOfSxc=W$1wbTiZ$kbcZ^vWVk(6s!^$(SJxsDvZKn%*}B*e`Y?BJAC zT0I&Q@fm4FE+SF}Y&fgDI0}O+LRl@N+mXk$D zKUOELOsN@-+`#4hCC1zwU@4Q1hAsh?4Qv99{|5Vh^ZqR)8U`HA4b%v82a5Ou_vlqc T5^UWA00000NkvXXu0mjfkY6^b diff --git a/Resources/Textures/Structures/Windows/uranium_window.rsi/uwindow4.png b/Resources/Textures/Structures/Windows/uranium_window.rsi/uwindow4.png index 9fa452a61bf19f4082c9fbc34586322836957de0..45ff01e1907310286068d19e4163a6444639c5c9 100644 GIT binary patch literal 2251 zcmZ`*2~<;88h#-N7zYnZTu`E!-~wtE0tFL85-<^hK*Of7&;ua}5XnaJLV~gc5kw2h z0O}N>k#a1IbA&4GPzDYJ0U5284xluZAc~4owpbjNvdl|RM324a+;{K&-}n8?cmH?J zJIxOAwMA?~003ai@?(TRE8R40tf1#rVPYS&z!V|AK0wty$CuDywSdEl4GaW!L3RSgNn3u7Z-3{4W4yvT`gfR0xyc6+HA#dC)3c9R6 z7n|QKKGgkG1O>nJB~cOX&cl%aVA;oFc!#NBBN2}h9K(_GNwMj%p88vo!j0c1xVnQ^ zj;=a!hWYY~iL%$MsIc)UJ4^31>%?0bEd{Jm)<&9u=YuM$@w&(qO!@8=z$zQ&GEHc1Df(G z(v#Os-~LNUPnz$mYyTKjDes|$qlv(cw z{QmZ%IK|i{czW&bmfnjr_g#;e>BlND7W>vVE8Pj5mIwam6364S`I@moV@o@O*Bf+- z+*b|Hg+(Jh5PEAydzf(B6h8zua&#s}V792{%sIvY6xD_44f>nQUnU;rzBc?SDp}@1zoZ3pEpnhSY z{aTJ_VP`eXEz|C^p@ziYTb@p@EV}baihOKE!?!c!3kD)$?A&Fw@kd{NYCb873imm2 zF)^sE?iDcHeDL|q-RVH$6@btacdw&&YqTxB$)yWEAOC<|q5g85FzMM=B%tez@Ov~F zVCkqO(G=;S0Y|K4y1TF2knCgk4P_6WoWYGQNZHPC4T-8qeLj14F3?o~5ZdFaI!d&4 zG(R|@xd^6n)YefIXo-P2|WK%ec1jFP22nMd2|EJLk<#1vB^SxR@nfUbmV)SCVo zOw5ycANbFxMt@c=PJ~jPmL9H(>i{#W`+aJ?G+Em;L1n5tt)Vh50aGUM*uW4D9k{bc78HJ^7hVJ!0 zjizcU_WP7hJd2vsreCShr6hA3M;`0y#y#e&Um!{T}PKm$oy{#_$HletAB=Tb6&w%~;eQm!2(Izq)6^LBpEa z)9I^a!3oBoRrWU*nyN>PO~2Xh`2i^<9bBCwzCLMZJEHq%Y7`lCiQse;Yb}P-R%XM> zgbQ{+pl-85&$ZgoO+=1XVRl@~mu6H!d7;M|bYW&TcE zIb+27XZG5;rZHF=+r2pAtaEYEa0ET`=ozC&$szj*>}blVqj`O}k&8mDMb_l3#md%K ldL3%Zh@n8i-1vt zk;bE2R44HT7c2y+L*yE_lt8;^TDmYPm}JxJ(nWtl>84=XLV_2CLVrZPa~Cb7q!bdG zLb1UVYSP%mix`O}@!gJf8;@o*UCj7GFZSYybEa7DMn}>dy?>t`owqdce9oXJI!6}+9?FEncZW$HcvxT$s0-VqEV1mw+n0=qz%E$ z(p>O7tO4kjIsn;cl+zV#*QI1uAr_51Okorz<4%EV#jC;7>S+Vuc|ooZz-Cwj&@XiW zj9ifG@9Ss{K%=DV0mC=1%*xEyT@R2x7cG1e9)HbS0*=D8y1)tFGp%53x_|?o5v&OB zg{-}_qyhBDdk@B2Vh_jn>BnNlw;|C5z_>pE3BV6)ehGrz!BSWH`Y%ZX_^xk~x>skn zxfAC4Fjjnz=hf$2$i70$Z_#k;#0-P`i$8ObJnt6YCM`13!M8)w$AIheAI$>%>Z}kK zf`8Rm*wqOOyYHI=+}(Ksxy0e5qz8>10Q}b;{=bg_Ggg^(w?!^#-~v4%&vmy2z+L`? z^CsW~=l)C!>M0O_-!E$~EolHfx100;2S54#>;Kr&IP$m$bO(=9vJuEh8o)`nvPE6d zxE|H04glQ&=vD`S?f`VF13-5Gx^?OSNPp)7vU;QR!I;ea-}2v{-v0}Q59y8rmf9(JOuyTw$1@4&340a``RpQ)8kFsQ!0hq6E^EAB4%Ex2bt6&&mnSVVm zXRRH;{j*;lj4v$wh!v0X*3e~=eukG4X8>^h7LQ&$T8R?_GC!> zJ`y%p&jFBkf{sziYhb10WQddXpehc_?niI4d-D1ZQjHbuD*y-@B#sT47A0d78Wxx? zcGJNIHvYExdK>>&s2xD@tFS?WASGy;7z9n0<8G%-9S$WMD}Mn_dR{s7?CW~~0000< KMNUMnLSTYodN{`b diff --git a/Resources/Textures/Structures/Windows/uranium_window.rsi/uwindow5.png b/Resources/Textures/Structures/Windows/uranium_window.rsi/uwindow5.png index bd46092739e6b3d5f5e7e3eb3806b5feaa456145..473bc3ffede9a71bbf8d6191edf3fdbb380bd412 100644 GIT binary patch literal 1872 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|_);T0(|mmy zw18|5AO?X;!IOa`XMsm#F#`j)FbFd;%$g&?z`&f784^(v;p=0SoS&h?X&sHg;q@=(~U%$M(T(8_%FTW^V-_X+1Qs2Nx-^fT8s6w~6 zGOr}DLN~8i8Da>`9GBGM~RsBTId_|A5Z7NlCUU$t=l91qU45Kj08_%qc+?1*r!G zK~5$pWUX=%^U`gVDs)p)(-KQ_N|fwM%QN#*^2^O_^dYKHbwfl^4Ykq7V!sW@*H)21 zsm1v@rJ!)PGdHpU2L*~CA_5>9BCu&d7DU$&kda@K4@^%*naQ4cC8z@95{?t3ZVXlf@Y(-o~ zK0W*zTkPY|`CnG0T+xmH_iR>Y`G?g%gU_iqq_ijA+9;4a*?%e|*l$yNjO84qQU=u! zl~V!y6P_wMP;Io3^#F~b>7A}Un)rJ{uiH&`$v$v-=+bF!KvFpe!et#pK zLAJro{rObY5(X*R*cA*Frf!S-<}ph7Ro(1isJJNEzH8%ohFe_$xrvXrsxE$}^K?oQ z7sKP4pBr<^wro#*aaHJe%ICv6^~;S8NO#Q-Qx;)}eVtjpb^C=Gg3s?>60$2>ZR%IS z5G7RWV}1I*xcRxqY5%OO&Wd@R(mcSNa7a7*fBt6vz%{nVFQ4Ui*t$^gi`?ux+Z}Y9 zPkvJg$mixMtc$8oJHULw#Q44K9KU%}&jp-oJ^1Ilw(Z3WKMpc4csQ4TwhhC%dH-8h zGYaT7M0UQ&Vy-bMiI`qs?RfKdxe3D}RtM*QtA0&R)?<+TBeH$^hm6l{zol%hIx%i< z6OD;K|CG_=gu;oNzuCizUq}4i`)+mP;e8$K2P%Tf+YhO}`6JK8fBP`w`Q;1-(GM!q zjY>AHw|u%!D36h~q44A?=74!TALE+u9Qd_OjPXNnmWzImQGyHe>)X0jY%ly9s&8Ik ze9`}JD&v<~*Z+$~$O~Ly&8=np8?T_T;qgBE5C#*g69J4DUMM)TKG<>j_W93B40Rg4 zpG*VUdWuT^{&0&H++=!ene>Kr3OD6Sjue$L^yMY|U#xl4>h}MPQ)?8B6jm^6JZK10 z2rYc68Niq!u?Fq`P)|*MYOsPOgZ6t?!Z;P6Xyhb zy4p%!>}TtBJCMQZV*DV3-NpHU%@sxqDaMOj5@#D0%NocoT&(&a;Rm;>_m=jl>BqK# OYBNt)KbLh*2~7Z@MaFml delta 771 zcmV+e1N{8Z4x0v$B!3BTNLh0L01FcU01FcV0GgZ_0008bNkl1vl z`_r@qQ%WM8EOjXcIypJ1i!OC?=_0tblPE5QK!-rVMXGL{?ciW1Gr5R3=+a4O=~TK% zF-4lvmh}EQoJd7;tB~@2ft+W$+;Dlny!kliz)QvS3t~!n?1vEfFywMv zIEIn7sJwayyqj9Waa}%aeq?TV1tQs!)D2i|y*3vUog01(jEU*18_;leA#6hsLli>d zf?E>PS2v*g%zpuf|GNJ_Gr&clZh+Jm%|m|{P{tadU4S;$0PO;_=_>;~g>w4JfEc+y zLBHrL12pJ)A#{EB{+(W)@AdzDuMB(#h#R0W(4B{PH5vomdGy!Mp@20&y8vyh0ony< zBlbq9U2E36ez1n>LP*4bcCA_8T+AS8ftvsUgdPM%34i%>k$opvG;e!n!%6S~-Ca3A z(t!8?D1#p}y*I_}>P@mF5tGkDwgdc_HIQlk7n~T}mp()M|O;u~nx`YYp z2Fzw>S%F5dYpx?Xef2S5zVv{F@rO+BO_>{!*U1vdpxy!ZcIr^_p@PW{9Iiktr?1`t zlmn9$I897;;6!$_MBRY-tr!n002ovPDHLkV1gN3 BWk#a1IbA&4GPzDYJ0U5284xluZAc~4owpbjNvdl|RM324a+;{K&-}n8?cmH?J zJIxOAwMA?~003ai@?(TRE8R40tf1#rVPYS&z!V|AK0wty$CuDywSdEl4GaW!L3RSgNn3u7Z-3{4W4yvT`gfR0xyc6+HA#dC)3c9R6 z7n|QKKGgkG1O>nJB~cOX&cl%aVA;oFc!#NBBN2}h9K(_GNwMj%p88vo!j0c1xVnQ^ zj;=a!hWYY~iL%$MsIc)UJ4^31>%?0bEd{Jm)<&9u=YuM$@w&(qO!@8=z$zQ&GEHc1Df(G z(v#Os-~LNUPnz$mYyTKjDes|$qlv(cw z{QmZ%IK|i{czW&bmfnjr_g#;e>BlND7W>vVE8Pj5mIwam6364S`I@moV@o@O*Bf+- z+*b|Hg+(Jh5PEAydzf(B6h8zua&#s}V792{%sIvY6xD_44f>nQUnU;rzBc?SDp}@1zoZ3pEpnhSY z{aTJ_VP`eXEz|C^p@ziYTb@p@EV}baihOKE!?!c!3kD)$?A&Fw@kd{NYCb873imm2 zF)^sE?iDcHeDL|q-RVH$6@btacdw&&YqTxB$)yWEAOC<|q5g85FzMM=B%tez@Ov~F zVCkqO(G=;S0Y|K4y1TF2knCgk4P_6WoWYGQNZHPC4T-8qeLj14F3?o~5ZdFaI!d&4 zG(R|@xd^6n)YefIXo-P2|WK%ec1jFP22nMd2|EJLk<#1vB^SxR@nfUbmV)SCVo zOw5ycANbFxMt@c=PJ~jPmL9H(>i{#W`+aJ?G+Em;L1n5tt)Vh50aGUM*uW4D9k{bc78HJ^7hVJ!0 zjizcU_WP7hJd2vsreCShr6hA3M;`0y#y#e&Um!{T}PKm$oy{#_$HletAB=Tb6&w%~;eQm!2(Izq)6^LBpEa z)9I^a!3oBoRrWU*nyN>PO~2Xh`2i^<9bBCwzCLMZJEHq%Y7`lCiQse;Yb}P-R%XM> zgbQ{+pl-85&$ZgoO+=1XVRl@~mu6H!d7;M|bYW&TcE zIb+27XZG5;rZHF=+r2pAtaEYEa0ET`=ozC&$szj*>}blVqj`O}k&8mDMb_l3#md%K ldL3%Zh@n8i-A#8 zKZf~YhDbj~QfUZQ8ipFHnk)*VYr_z?m(w%hnPdoxdwilIWxKU{@!`!%zwS_`<{D67>4N7$o0|L z`HyxOFka@1b2quRa*IO2#+|HS-|o55XHo<~lRZ%k%Dq}Tf|0+2IP$~Cm1x+ zG(?S=`W&TPLz#6v0HmTXJiGLmgcV|K*~+Zr0l+X=?%HP0^;peR@p5bGtd%)+QY{MO z>c|-5&H#{5W*rXzi6l@4;BI0Cd|#P$JOGH&v#|@9d4F}*vi*R!e!Vt!SXt^$R;KLR zJ(Nl=cLr|p!P+OR1bKz>H+ANvYfNLw~LE~5Q3Tzs%#IHvKg>nPmye>F4a9uO3wkq znH-id*nctgw&L5RB@xn9`~RDi0q8AT3~`=qw@R}fpWHzifKsl(Onr`qs4-}y!BjO}3^#Jrs9RM@Wb63Ci9)Lzk_X9?*kAKd}?612YAYBa2e_W3Sfq-_H$u4l3 z(KwNe#t9E_z&E2A;cv^@OG_F+!8&^|-V#lmFr+|=Qn(9t7Xag7AJ{iOA3e}|;H z*4K+94dBbd6b-*Y)vdH@eR!|xFL^;yk0px5EMq- z(tqcGi6ynuY# z1mJXw=Y|*M`}bIb(>CBl*Zyn(jWh@#EXdkROB%qLsem)U!B4*b`9HR7&;32%RP;J6 z8-bjp0UUNKTig|od{m=O0O$@tw@v`)4u3$mP5|f*K(~%P0O?vlR+m>N#$@*YzJKQU zJ}+<-Isu?N0NpwPpgREFIsu?N0NpzF0JJ|eVQY2j3DCNh^;YW@PiLVvwV z85giH5iAEal18h^+An9V9l*ohPY=cyp5CX+wzx9%Ch0Is-i{ui^1^_H$~-@;E)s?z zH!i-zspQ!g9r8a(dod)QTxu<@_5v`t7cG}92Mv-LgDf`PzMv+aEiJd-X7|(OucQ`M zw9fz_S|D+nkPTQi|AgH%BpjM9G%|tBziqz3(LGnF9YFE3)&j|Mp#*det!-UVa$)5! Xp#Wu4&1DdR00000NkvXXu0mjfD0M=* diff --git a/Resources/Textures/Structures/Windows/uranium_window.rsi/uwindow7.png b/Resources/Textures/Structures/Windows/uranium_window.rsi/uwindow7.png index f75790a41878a5b5e9df599eb3004fc19dc29d2f..1a0ec49fd54851dee62e1f9f1608f84c51c738d6 100644 GIT binary patch literal 1281 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|_);T0(|mmy zw18|5AO?X;!IOa`XMsm#F#`j)FbFd;%$g&?z`&f784^(v;p=0SoS&h?X&sHg;q@=(~U%$M(T(8_%FTW^V-_X+1Qs2Nx-^fT8s6w~6 zGOr}DLN~8i8Da>`9GBGM~RsBTId_|A5Z7NlCUU$t=l91qU45Kj08_%qc+?1*r!G zK~5$pWUX=%^U`gVDs)p)(-KQ_N|fwM%QN#*^2^O_^dYKHbwfl^4Ykq7V!sW@*H)21 zsm1v@rJ!)PGdHpU2L*~CA_5>9BCu&d7DU$&kda@K4@^%*naQ4cC8Fbhj9Tae7ec5(yHA(j#!$KwLuQ=%VU zdTn3(GRETkZ?m7(HGS3_KkTx-?^3V$$T)-d0gvt^S(Sz*6Y}8f2s{?H`d8JIDE77 z=avuvQt<)|TW4J5S5Vl^FgK6E_P0wj^lhkVV3{J`@zxu}WT=yO_&)#dz5~h*(oh}ySuU{L{>sXd z@?TwqWkPLy0MN<_k`89~zb^Ma@JlvT)(g!3&u}(bpl*`8?paXrvd$@?2>@s- Bo)G{5 literal 297 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9GG!XV7ZFl&wkQ1G^= zi(^Q|oVT+#@-`cYuo@=um7Ng!;xlWW>L%vq2R#lSzZQkYDkJCQ+V6G~_nfO; zeWw1}_rRI+wGaPqV9a2YV!ps+!nT0*-Hhn4!XFIb`xm|DmsjXTlF69%is?(`zEh9? zGeFg5@Ce*jsF}B3XuJ3P=c{}ER@Nb#l)>Y`eLz y`@}0OkOX!d{?4>d{6rE%RKqcbEes&rXX%$%%2g+2GNk~$$>8bg=d#Wzp$PyK^Ji!P diff --git a/Resources/Textures/Structures/Windows/uranium_window_diagonal.rsi/meta.json b/Resources/Textures/Structures/Windows/uranium_window_diagonal.rsi/meta.json index 453a3797223a..8477687a8c7a 100644 --- a/Resources/Textures/Structures/Windows/uranium_window_diagonal.rsi/meta.json +++ b/Resources/Textures/Structures/Windows/uranium_window_diagonal.rsi/meta.json @@ -5,7 +5,7 @@ "y": 32 }, "license": "CC-BY-SA-3.0", - "copyright": "Made by brainfood1183 (github)", + "copyright": "Made by brainfood1183 (github), transparency tweaked by Ubaser.", "states": [ { "name": "state0" diff --git a/Resources/Textures/Structures/Windows/uranium_window_diagonal.rsi/state0.png b/Resources/Textures/Structures/Windows/uranium_window_diagonal.rsi/state0.png index 45b3c99189ff93d8928aae08e938c39e47de6c8c..43bfb93bac1f02c89e0b8cc06032494e86211854 100644 GIT binary patch delta 1015 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 Q8k9>tUHx3vIVCg!0G$VuumAu6 literal 15604 zcmeI3Yiu0V6@bTiL5v&_QL$AL7&Z;0rL*(c*~g4_H+H-ZcF2a*b`uAZlG&NN-cfdU zhMlp!c3jCZF%cq4r1A)_@Muw*5Q0=IbrF%$3J6V=N}z;BZ7lQpQ&AM9Dqu)baPREf z*Xt{*Ao1spv^#t5x#ygFzjM#o`7;l1+;CT2?GI}yimGdCjkLo%?R>6X1i!6;fzRP> zvDv!CqNwYZI-eTq>1P`#N`6!C?6SL}>t)qQxfRWb0e3cK!r2rRT%9!)bqBEN80gm1 zA=jl7e{|8h7IJO&M!Bfj3=(?lKn8RSZ0J-6cBqo(S{<$pW@YFg1#E@Rrjlt(&W2n$ zzcT#o46`meH^tr&ay2;t>8|KTy4lD8+Uxc)D(Cale#y;y{eIE^Q(EA7FUxsY561`| zS>$9qeS({34jTaQEm6O9xo?nnkPpy>)Jt9pT*445ilnWzs~Kbm4IbMjI-x5AI6 z%5fu;QtYsvQn~?arn`e|d9Y$;=~T(hM$*W@Wr46K$W|M!Y85fm9_Ls$rBz_TWLOnR zf~m?C?i!_g`e;#+)Wi9K$>pE{F&+>l5NG_H7GQWD07g>1J_dLLnj*ymlF!M7 zQ@qecd0md*-01X(mD|Cs*Et5!sN9yeYz1zoEfR(UZXK>n;T1ms0teUQ_(##JRC24J9gY}SqE*ID6gMxc8#I&9}k zvSN<27Y**k&x@j@`eTfsae(nFVw{mgPmBTnSOAEUPt-h8aW7Te%m~%0J9+O%(%|H# z13WN&w4C=`<299x1)R1LauxeZsZ+zLr7M_gPqLyqEjz3_RSzKUX`|(3p=SEbbj}Sy z-hYMp>@oThAdTx9c~`kvvpcbjxZS5@KvOrYr@1t=yw~YwsQc2eB)u`zfylJHxH7#5IJgwVdp%4ujuCQ_* z4D$b49q<_zgneGG#~WnPVbo%yo(0LShz|d?ET^A%V5FQ4s;FwXWj4bKMZqwis*0!0 zTr1wZ z^1=Gn`!+?Qdp}ux+MIV|=$h-ksO>%XR`kZ zg^w+HcKn?yi|E~dYN*=^)l^_Y`s)`jovaB=GP}+V?78fD*;x2?!W^3T?=AE1n>Ts< z=r7jn`}*bO2M0qn^J*vmv*($AzQ1?V$fmqwy>8Lz(TVK%@{zlj4?Q1zbF$;3_T{f>JI_xYPL4nN zcXnj{kn7m^gG*j{{MDx$t~T!ey8X2qb{)TXe%)qu{2xc3xN~b_==jCnt7qPMWLxW+ zZ$cj&*n95aU1QI$ddl$|`ZRQ4Y}gt*P{)dmS8jjwx7tgu3|$)BKXLEq>B(g)SBx~C zbrw20R)5Qfoqrg=@W%e%ow;`PiQ&-+_xi@;<0FfIWC*`r+2Mo`)*X7c_Uzc1RZneQ xuw?a-J@uzu_y7Lvg23c^3rF{v)K|AsQ@>n$^3rn&uk&7VTg!&Xt82Co{}0}mEfxR( diff --git a/Resources/Textures/Structures/Windows/window.rsi/full.png b/Resources/Textures/Structures/Windows/window.rsi/full.png index 5ed08bac4204e8a98d150333a24925dca8310739..a42b6b77f7f59c32ec34289626d566bc573944c8 100644 GIT binary patch literal 2279 zcmZ`*2{fDO8jh`Yf{V-OG*T^7lSP=6G?dmLwG?CRwA#pGizM>@8L6tBmX77BRu{{3 zR8>hW?bH(EsGU(#Q$y=cQ9|iZbz{HuCb+6So$s7)d%yR2pZ9yd_dn-Pc6G5=R?t;| zKp@Hl2U~a13=?;`U7`_)h!Bb<3BcX{2;_dZ-lS-wLh&I`ot+^EL~A)w7q{N;E{jHa zrh_j4ff(HocL{BrekBAVMGf-s0ezgEa3n@3l1OIwQ;?ic<^~GS!HJfk6p#qxgwp5$ zj$;Ym@W6@IVlxU3+i(FxEa5)RuCSvF76pbyqLFC0l>!U~!?Va#oV%^v7F@Kmga?8k z6Nf^DhleA>O_2;%0LsL|!UBcHpfDJO$O8eKrGrEcf)4E64D$atwiJNG3Sxpm3_464 zm*~%6gO+f(m}t9g=1C@P^Dx;g+6D`mgrd+Wp%gj@piGb^sL$cRAnJz<>A;p8B4JSC z6A=vkSr~x{lFUR(eajK$vvogFqNEL803@S!IG`|Sv^fHeL0~LU+xHWtk0+CGU=T>7 zYzVh~pA7|VXyC_IvAg1 z@H})paIBsc>tB6Bny;98_+Z%blycMypNMyIc`pyAw`7*BkXVeNp$6{YqHt9p2pBnp zRp}d_Kj%PMym<;w!@9kfDi3m)36Zg$9e88lqcpfQgXgMB-X=(99|^?vnkR9Q#`hYA z%7)@E>ry(0k2~qe{ASb4|Ff1qY<{M6;-|Xr(gfA!VbwnZ;XJrk2gLOtk2AXDR@&cB z%pNzt#wYEkUv&C+S7vUsC-j0e*n#bB;^X5-8WMgOXq!{K;1`_}7Bh_Y*gAII8U*mP-V$Qm~7j$-IO&b^y+)KIK2mI6~Jf`oCY{JP}f+F8Vo!aa;8JnX7nYxOY z8?Pw%+S)gDKK60X(YLe$G@OS1&-YAxiG19tk* z#KJhjl|Nr3{9Irsm3R`+r3RERE5}Oto;(|`M{RbMlghWgQkDK!a?%1>p~0@| z(i6Yx5H{=>$!zcrR4|?jS^7&p>i%i>`urNhe6x}w&}IVV7f%aADK5)d!vdn})u@GG zN4n3L+qOf$?;Ur}h|-K~id@X?H%y|g9{5u0#EA&{vGQQ5jGkl;0#73VuzLlGWl*hM6v$1LKNo$FpVm89KAxMVIJR>CaS{xxm%q(F^G( zcGr9{dwkCR?ozu-kM@wi>5YF_K3YK3)kbC@c$f5>kYvbg){9YIHEVKL;#pxUw0>gm zBpcAFyEq_M(+>CPXA3jovfjYCpVTy~RO}wKxp{>Vm|>@4Eeoxu33QEWvw~ZrO|N{*)gYRFv_sDy8xF7c czgZqyZEK8~&QVMg|6~xpb+NsFa8U9U|P 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 It^-0~g5Y*&oB#j- diff --git a/Resources/Textures/Structures/Windows/window.rsi/window6.png b/Resources/Textures/Structures/Windows/window.rsi/window6.png index 13aaa2107eb3d7196a96e5530e1996c6cbe0b650..4a47d0859aee6821af5b92eaf68dd4bc2f432e43 100644 GIT binary patch literal 2213 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 J%Q~loCIB+RX~6&h diff --git a/Resources/Textures/Structures/Windows/window_diagonal.rsi/meta.json b/Resources/Textures/Structures/Windows/window_diagonal.rsi/meta.json index 453a3797223a..8477687a8c7a 100644 --- a/Resources/Textures/Structures/Windows/window_diagonal.rsi/meta.json +++ b/Resources/Textures/Structures/Windows/window_diagonal.rsi/meta.json @@ -5,7 +5,7 @@ "y": 32 }, "license": "CC-BY-SA-3.0", - "copyright": "Made by brainfood1183 (github)", + "copyright": "Made by brainfood1183 (github), transparency tweaked by Ubaser.", "states": [ { "name": "state0" diff --git a/Resources/Textures/Structures/Windows/window_diagonal.rsi/state0.png b/Resources/Textures/Structures/Windows/window_diagonal.rsi/state0.png index df5805957d6b0d0b891e10d01cb5a46e4c36e95a..428ed238a76e8821f17b447ded574bfe51041254 100644 GIT binary patch delta 743 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 vJ0Y_!yrF*O-kYyF^*tYb2bP0l+XkKxLOJq literal 15966 zcmeI3Z)hAv6u>tIYa3}1L|del^@><&HoJSbdw_V)hlP432M z`$1$DlDju=-g`5@_x8>1huhcNvw3;beN7ZaE${A%_Q6lu{#&{P{x>HlufvaJ*{&gz zqVBxg{%fFKKD3IW!WXoGL2EF!MN;&1i>&H#(2`GQ;cTdD%V%X}6j*c|B(+Sd=j!Q? zJ+!8_dbW!(E|%>CBU;y_0s1F<29(KBC8T=VB2D4E1RbP-CDZwIDq~9dR!_mN1i#zE ztcNa4u|``x9dIR_27C)nK{s0{aweVsfAOxCeFUN~4=VN^w)}d@Z_>Wcg4i#ByHN>t)~!#+=Ala-PYU zYaJ&gKT%*RhL*K7Jww}m<+wg(wR${upz>ARS2|k`lrf9!AVoGWXIZ|5V`~|yO4%km zW~2&BQxz7ZKpJE$6WZ}L?Xn}frJEyqosea9-M}y>u~<2F&Gn|!HA9=$#&L+Ch_t4q zIWUn0Y#%W7F+%|x$Kh7i*4n+LB`V3O@?>l3t{vpHI%c-UF)NgUlc6x&tJG-#+0u;x zT~9@vD(fvFq&qtcRYkAcu4Pm`XFeQeQIkr(E8aj= zUg9{H6K5vkBc`ibVxr=MhXu_KczMa^mBf(ShifM41KvNXY{`rA;-2gBqbgEDH`1~d z(b94fu-Qy9%vJ_nGs{&ab?PbIfXf0AUzn{mT+=G5D`R$9cVrY`!ep4PB*9b_ZrlxW zvU;?nNNEwLZK%4UsZu3qfD8FmKgTfvP7oNL2Y?AFqMrd`P?bZ8UW)U>K#K-9ErbGGkn;D}}@Jdkdt3FXogbHO>ZC=@Q(RC?0bbT`$ch>20wjj_}LxU%UoN~>v z_oBkR03ZS(;RB2ef+EAmVeVw!%P|R2^oA7P58?rTX)iV0EC|)5*(Ehmo#8@B^@Cm2 zqm_~>^z^K3n85B>t)5cLDjxz)l@x2G(D@`;u}_1DVmB0^hS{po%CgFqVP}H2FrAA- zu)w^2jNAyw;2M(SsxYg*6H`xEIoSXmNqDO+rdK*%tIbgNe|H1kL?TRi{N~aSSK&?N zl|_b=#ULZvcU4GL6jnsMe2+I=)NR+t~~a`0k#`+w2Ytwv3U@TP7xYFe>;ETdTw zZ!sD&?6R_-7M(|#e)wVoB7RZyiD4EUMlE`^JV*^jHTWoF+9!bzMk?5#ikgN)^$cB# zqM?&2*DFZj7;{G93l4m@V#_aA3r@K5`Ex73RCaVLy&}Fy5CjNbB)IT=5G}!l0Ktm{ z7oHEICAbhEc#+`3^Fg!(7Xkz?5?pvbh?d|&fZ#=f3(p795?lxnyhw22`5;rKlV8@bd~qjd2w9>o7%02PtZ${`}4}n<%P*>W+2{-TmE=cJkS)_V?#DUvFCiuQ#4P5x%(LnU7YqpM3JlzDKT` zlz;BZy|PcFZ(>F*BO|GjaObE5ENiepxthTfF(`OO5CD zu6gmYu#0*vxOw|oVS1+jn}(kUd&E1YM?;P9I`i%Hh4Vcx+;#Z8v43^@quY+W-?(m{ zxqnT2Y_5BpdWU)F%Z3xj4*inqI&i*ceCfHbjXf(4Z`-zZuHnRf^Yzv3?A+VZ)T=W} zaO(S+BWmZ4qvIbuaB0=SJfNGC!|;maul;zBy`y8pKg?hHY3Jn7SF^LT)GF%T55qUM T+&>K!JMPxP$~!+ZV$;QnZ1 From c978eefedbd0a993e9358ee15687761feb457130 Mon Sep 17 00:00:00 2001 From: PJBot Date: Wed, 13 Nov 2024 12:31:47 +0000 Subject: [PATCH 084/290] Automatic changelog update --- Resources/Changelog/Changelog.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index f54421b87ad8..3365a943ee6a 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: PoorMansDreams - changes: - - message: Throngler Plushie looks like a plushie - type: Tweak - id: 7106 - time: '2024-08-13T20:32:53.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/30969 - author: IProduceWidgets changes: - message: shuttle events have been separated from other midround events and can @@ -3949,3 +3942,10 @@ id: 7605 time: '2024-11-13T02:59:47.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33223 +- author: Ubaser + changes: + - message: Window sprites are now slightly more transparent. + type: Tweak + id: 7606 + time: '2024-11-13T12:30:40.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33282 From 51d2b51ad09f3b361d80f22c3c2c23d6a5048517 Mon Sep 17 00:00:00 2001 From: dffdff2423 Date: Wed, 13 Nov 2024 18:27:31 -0500 Subject: [PATCH 085/290] tag:with toolshed command (#31751) --- Content.Server/Administration/Toolshed/TagCommand.cs | 10 ++++++++++ Resources/Locale/en-US/commands/toolshed-commands.ftl | 4 +++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Content.Server/Administration/Toolshed/TagCommand.cs b/Content.Server/Administration/Toolshed/TagCommand.cs index e1cf53e1b1ab..4c6f790e4939 100644 --- a/Content.Server/Administration/Toolshed/TagCommand.cs +++ b/Content.Server/Administration/Toolshed/TagCommand.cs @@ -25,6 +25,16 @@ public IEnumerable> List([PipedArgument] IEnumerable With( + [CommandInvocationContext] IInvocationContext ctx, + [PipedArgument] IEnumerable entities, + [CommandArgument] ValueRef> tag) + { + _tag ??= GetSys(); + return entities.Where(e => _tag.HasTag(e, tag.Evaluate(ctx)!)); + } + [CommandImplementation("add")] public EntityUid Add( [CommandInvocationContext] IInvocationContext ctx, diff --git a/Resources/Locale/en-US/commands/toolshed-commands.ftl b/Resources/Locale/en-US/commands/toolshed-commands.ftl index e2536f6781b2..c53c825eb3e0 100644 --- a/Resources/Locale/en-US/commands/toolshed-commands.ftl +++ b/Resources/Locale/en-US/commands/toolshed-commands.ftl @@ -1,4 +1,4 @@ -command-description-visualize = +command-description-visualize = Takes the input list of entities and puts them into a UI window for easy browsing. command-description-runverbas = Runs a verb over the input entities with the given user. @@ -58,6 +58,8 @@ command-description-rejuvenate = Rejuvenates the given entities, restoring them to full health, clearing status effects, etc. command-description-tag-list = Lists tags on the given entities. +command-description-tag-with = + Returns only the entities with the given tag from the piped list of entities. command-description-tag-add = Adds a tag to the given entities. command-description-tag-rm = From 9643598c704dc99ae18312b2bac44960c75d7e7c Mon Sep 17 00:00:00 2001 From: PJBot Date: Wed, 13 Nov 2024 23:28:39 +0000 Subject: [PATCH 086/290] Automatic changelog update --- Resources/Changelog/Admin.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Resources/Changelog/Admin.yml b/Resources/Changelog/Admin.yml index 680915d3821a..bf1cbddaa189 100644 --- a/Resources/Changelog/Admin.yml +++ b/Resources/Changelog/Admin.yml @@ -597,5 +597,13 @@ Entries: id: 74 time: '2024-11-12T21:03:13.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/30659 +- author: Aquif + changes: + - message: tag:with toolshed command. It takes in a list of entities via pipe and + returns the entities from the list with the given tag. + type: Add + id: 75 + time: '2024-11-13T23:27:31.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/31751 Name: Admin Order: 1 From fa3a04a5273c77bba4f3545dfedebaa61bd2f5aa Mon Sep 17 00:00:00 2001 From: keronshb <54602815+keronshb@users.noreply.github.com> Date: Wed, 13 Nov 2024 18:36:37 -0500 Subject: [PATCH 087/290] Ethereal Jaunt Spell for Wizard & Jaunt ECS (#33201) * Act * Adds Jaunt ECS and related prototypes * Adds jaunt sounds * Adds enter and exit sound support to polymorphs * Updates jaunt description * Adds jaunt action sprite and changes jaunt polymorph to use it * Adds Jaunt and upgrade to the wizard grimoire * Makes base mob jaunt parent off of incorporeal and basemob, adds blue ghost sprite for ethereal jaunt * Update Resources/Locale/en-US/store/spellbook-catalog.ftl Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Update Resources/Prototypes/Entities/Mobs/Player/jaunt_mobs.yml Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Update Resources/Prototypes/Entities/Mobs/Player/jaunt_mobs.yml Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Update Resources/Prototypes/Entities/Mobs/Player/jaunt_mobs.yml Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Update Content.Shared/Polymorph/PolymorphPrototype.cs Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * Update Content.Shared/Polymorph/PolymorphPrototype.cs Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> * removes meta changes * removes other meta changes * adds context menu and a description to basemobjaunt * comments for jaunt component and adds on component shutdown method * Update Content.Shared/Jaunt/JauntComponent.cs * Update Content.Shared/Jaunt/JauntComponent.cs * Update Content.Shared/Jaunt/JauntComponent.cs * Update Resources/Prototypes/Catalog/spellbook_catalog.yml --------- Co-authored-by: lzk <124214523+lzk228@users.noreply.github.com> Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> --- .../Polymorph/Systems/PolymorphSystem.cs | 6 +++ Content.Shared/Jaunt/JauntComponent.cs | 26 +++++++++ Content.Shared/Jaunt/JauntSystem.cs | 26 +++++++++ .../Polymorph/PolymorphPrototype.cs | 13 +++++ Resources/Audio/Magic/attributions.yml | 4 +- Resources/Audio/Magic/ethereal_enter.ogg | Bin 0 -> 36619 bytes Resources/Audio/Magic/ethereal_exit.ogg | Bin 0 -> 42980 bytes .../Locale/en-US/store/spellbook-catalog.ftl | 6 +++ Resources/Prototypes/Actions/polymorph.yml | 50 ++++++++++++++++++ .../Prototypes/Catalog/spellbook_catalog.yml | 33 ++++++++++++ .../Entities/Mobs/Player/jaunt_mobs.yml | 40 ++++++++++++++ Resources/Prototypes/Polymorphs/polymorph.yml | 16 ++++++ .../Objects/Magic/magicactions.rsi/jaunt.png | Bin 0 -> 431 bytes .../Objects/Magic/magicactions.rsi/meta.json | 5 +- 14 files changed, 223 insertions(+), 2 deletions(-) create mode 100644 Content.Shared/Jaunt/JauntComponent.cs create mode 100644 Content.Shared/Jaunt/JauntSystem.cs create mode 100644 Resources/Audio/Magic/ethereal_enter.ogg create mode 100644 Resources/Audio/Magic/ethereal_exit.ogg create mode 100644 Resources/Prototypes/Entities/Mobs/Player/jaunt_mobs.yml create mode 100644 Resources/Textures/Objects/Magic/magicactions.rsi/jaunt.png diff --git a/Content.Server/Polymorph/Systems/PolymorphSystem.cs b/Content.Server/Polymorph/Systems/PolymorphSystem.cs index daff200982dc..c9a71c53584f 100644 --- a/Content.Server/Polymorph/Systems/PolymorphSystem.cs +++ b/Content.Server/Polymorph/Systems/PolymorphSystem.cs @@ -199,6 +199,9 @@ private void OnDestruction(Entity ent, ref Destructi var targetTransformComp = Transform(uid); + if (configuration.PolymorphSound != null) + _audio.PlayPvs(configuration.PolymorphSound, targetTransformComp.Coordinates); + var child = Spawn(configuration.Entity, _transform.GetMapCoordinates(uid, targetTransformComp), rotation: _transform.GetWorldRotation(uid)); MakeSentientCommand.MakeSentient(child, EntityManager); @@ -288,6 +291,9 @@ private void OnDestruction(Entity ent, ref Destructi var uidXform = Transform(uid); var parentXform = Transform(parent); + if (component.Configuration.ExitPolymorphSound != null) + _audio.PlayPvs(component.Configuration.ExitPolymorphSound, uidXform.Coordinates); + _transform.SetParent(parent, parentXform, uidXform.ParentUid); _transform.SetCoordinates(parent, parentXform, uidXform.Coordinates, uidXform.LocalRotation); diff --git a/Content.Shared/Jaunt/JauntComponent.cs b/Content.Shared/Jaunt/JauntComponent.cs new file mode 100644 index 000000000000..6d37ab4b322a --- /dev/null +++ b/Content.Shared/Jaunt/JauntComponent.cs @@ -0,0 +1,26 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Jaunt; + +///

[RegisterComponent, NetworkedComponent, Access(typeof(SharedBorgSystem))] +[AutoGenerateComponentState] public sealed partial class BorgModuleComponent : Component { /// @@ -16,6 +17,13 @@ public sealed partial class BorgModuleComponent : Component public EntityUid? InstalledEntity; public bool Installed => InstalledEntity != null; + + /// + /// If true, this is a "default" module that cannot be removed from a borg. + /// + [DataField] + [AutoNetworkedField] + public bool DefaultModule; } /// diff --git a/Content.Shared/Silicons/Borgs/Components/BorgSwitchableTypeComponent.cs b/Content.Shared/Silicons/Borgs/Components/BorgSwitchableTypeComponent.cs new file mode 100644 index 000000000000..9a783d19aa7d --- /dev/null +++ b/Content.Shared/Silicons/Borgs/Components/BorgSwitchableTypeComponent.cs @@ -0,0 +1,72 @@ +using Content.Shared.Actions; +using Content.Shared.Radio; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; + +namespace Content.Shared.Silicons.Borgs.Components; + +/// +/// Component for borgs that can switch their "type" after being created. +/// +/// +/// +/// This is used by all NT borgs, on construction and round-start spawn. +/// Borgs are effectively useless until they have made their choice of type. +/// Borg type selections are currently irreversible. +/// +/// +/// Available types are specified in s. +/// +/// +/// +[RegisterComponent, NetworkedComponent] +[AutoGenerateComponentState(raiseAfterAutoHandleState: true)] +[Access(typeof(SharedBorgSwitchableTypeSystem))] +public sealed partial class BorgSwitchableTypeComponent : Component +{ + /// + /// Action entity used by players to select their type. + /// + [DataField, AutoNetworkedField] + public EntityUid? SelectTypeAction; + + /// + /// The currently selected borg type, if any. + /// + /// + /// This can be set in a prototype to immediately apply a borg type, and not have switching support. + /// + [DataField, AutoNetworkedField] + public ProtoId? SelectedBorgType; + + /// + /// Radio channels that the borg will always have. These are added on top of the selected type's radio channels. + /// + [DataField] + public ProtoId[] InherentRadioChannels = []; +} + +/// +/// Action event used to open the selection menu of a . +/// +public sealed partial class BorgToggleSelectTypeEvent : InstantActionEvent; + +/// +/// UI message used by a borg to select their type with . +/// +/// The borg type prototype that the user selected. +[Serializable, NetSerializable] +public sealed class BorgSelectTypeMessage(ProtoId prototype) : BoundUserInterfaceMessage +{ + public ProtoId Prototype = prototype; +} + +/// +/// UI key used by the selection menu for . +/// +[NetSerializable, Serializable] +public enum BorgSwitchableTypeUiKey : byte +{ + SelectBorgType, +} diff --git a/Content.Shared/Silicons/Borgs/SharedBorgSwitchableTypeSystem.cs b/Content.Shared/Silicons/Borgs/SharedBorgSwitchableTypeSystem.cs new file mode 100644 index 000000000000..d9abeb2d3266 --- /dev/null +++ b/Content.Shared/Silicons/Borgs/SharedBorgSwitchableTypeSystem.cs @@ -0,0 +1,125 @@ +using Content.Shared.Actions; +using Content.Shared.Interaction; +using Content.Shared.Interaction.Components; +using Content.Shared.Movement.Components; +using Content.Shared.Silicons.Borgs.Components; +using Robust.Shared.Player; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Silicons.Borgs; + +/// +/// Implements borg type switching. +/// +/// +public abstract class SharedBorgSwitchableTypeSystem : EntitySystem +{ + // TODO: Allow borgs to be reset to default configuration. + + [Dependency] private readonly SharedActionsSystem _actionsSystem = default!; + [Dependency] private readonly SharedUserInterfaceSystem _userInterface = default!; + [Dependency] protected readonly IPrototypeManager Prototypes = default!; + [Dependency] private readonly InteractionPopupSystem _interactionPopup = default!; + + [ValidatePrototypeId] + public const string ActionId = "ActionSelectBorgType"; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnMapInit); + SubscribeLocalEvent(OnShutdown); + SubscribeLocalEvent(OnSelectBorgTypeAction); + + Subs.BuiEvents(BorgSwitchableTypeUiKey.SelectBorgType, + sub => + { + sub.Event(SelectTypeMessageHandler); + }); + } + + // + // UI-adjacent code + // + + private void OnMapInit(Entity ent, ref MapInitEvent args) + { + _actionsSystem.AddAction(ent, ref ent.Comp.SelectTypeAction, ActionId); + Dirty(ent); + + if (ent.Comp.SelectedBorgType != null) + { + SelectBorgModule(ent, ent.Comp.SelectedBorgType.Value); + } + } + + private void OnShutdown(Entity ent, ref ComponentShutdown args) + { + _actionsSystem.RemoveAction(ent, ent.Comp.SelectTypeAction); + } + + private void OnSelectBorgTypeAction(Entity ent, ref BorgToggleSelectTypeEvent args) + { + if (args.Handled || !TryComp(ent, out var actor)) + return; + + args.Handled = true; + + _userInterface.TryToggleUi((ent.Owner, null), BorgSwitchableTypeUiKey.SelectBorgType, actor.PlayerSession); + } + + private void SelectTypeMessageHandler(Entity ent, ref BorgSelectTypeMessage args) + { + if (ent.Comp.SelectedBorgType != null) + return; + + if (!Prototypes.HasIndex(args.Prototype)) + return; + + SelectBorgModule(ent, args.Prototype); + } + + // + // Implementation + // + + protected virtual void SelectBorgModule( + Entity ent, + ProtoId borgType) + { + ent.Comp.SelectedBorgType = borgType; + + _actionsSystem.RemoveAction(ent, ent.Comp.SelectTypeAction); + ent.Comp.SelectTypeAction = null; + Dirty(ent); + + _userInterface.CloseUi((ent.Owner, null), BorgSwitchableTypeUiKey.SelectBorgType); + + UpdateEntityAppearance(ent); + } + + protected void UpdateEntityAppearance(Entity entity) + { + if (!Prototypes.TryIndex(entity.Comp.SelectedBorgType, out var proto)) + return; + + UpdateEntityAppearance(entity, proto); + } + + protected virtual void UpdateEntityAppearance( + Entity entity, + BorgTypePrototype prototype) + { + if (TryComp(entity, out InteractionPopupComponent? popup)) + { + _interactionPopup.SetInteractSuccessString((entity.Owner, popup), prototype.PetSuccessString); + _interactionPopup.SetInteractFailureString((entity.Owner, popup), prototype.PetFailureString); + } + + if (TryComp(entity, out FootstepModifierComponent? footstepModifier)) + { + footstepModifier.FootstepSoundCollection = prototype.FootstepCollection; + } + } +} diff --git a/Content.Shared/Silicons/Borgs/SharedBorgSystem.cs b/Content.Shared/Silicons/Borgs/SharedBorgSystem.cs index c62e63481d62..827bb351b078 100644 --- a/Content.Shared/Silicons/Borgs/SharedBorgSystem.cs +++ b/Content.Shared/Silicons/Borgs/SharedBorgSystem.cs @@ -124,4 +124,13 @@ private void OnRefreshMovementSpeedModifiers(EntityUid uid, BorgChassisComponent var sprintDif = movement.BaseWalkSpeed / movement.BaseSprintSpeed; args.ModifySpeed(1f, sprintDif); } + + /// + /// Sets . + /// + public void SetBorgModuleDefault(Entity ent, bool newDefault) + { + ent.Comp.DefaultModule = newDefault; + Dirty(ent); + } } diff --git a/Resources/Locale/en-US/borg/borg.ftl b/Resources/Locale/en-US/borg/borg.ftl index 6c495510b05a..9c9dc71069a6 100644 --- a/Resources/Locale/en-US/borg/borg.ftl +++ b/Resources/Locale/en-US/borg/borg.ftl @@ -25,3 +25,40 @@ borg-transponder-disabling-popup = Your transponder begins to lock you out of th borg-transponder-destroying-popup = The self destruct of {$name} starts beeping! borg-transponder-emagged-disabled-popup = Your transponder's lights go out! borg-transponder-emagged-destroyed-popup = Your transponder's fuse blows! + +## Borg type selection UI. +borg-select-type-menu-title = Select Chassis Type +borg-select-type-menu-bottom-text = Chassis selection is irreversible +borg-select-type-menu-available = Available types +borg-select-type-menu-information = Information +borg-select-type-menu-select-type = Select type to view information +borg-select-type-menu-confirm = Confirm selection +borg-select-type-menu-guidebook = Guidebook + +## Borg type information + +borg-type-generic-name = Generic +borg-type-generic-desc = Jack of all trades, master of none. Do various random station tasks, or maybe help out the science department that built you. +borg-type-generic-transponder = generic cyborg + +borg-type-engineering-name = Engineering +borg-type-engineering-desc = Assist the engineering team in station construction, repairing damage, or fixing electrical and atmospheric issues. +borg-type-engineering-transponder = engineering cyborg + +borg-type-mining-name = Salvage +borg-type-mining-desc = Join salvage and help them mine for materials, scavenge wrecks, and fight off hostile wildlife. +borg-type-mining-transponder = salvage cyborg + +borg-type-janitor-name = Janitor +borg-type-janitor-desc = Keep the station nice and tidy, clean up spills, collect and properly dispose of trash left around by lazy crewmembers. +borg-type-janitor-transponder = janitor cyborg + +borg-type-medical-name = Medical +borg-type-medical-desc = Provide medical attention to crew who need it, either in medbay or in hazardous areas conventional paramedics cannot reach. +borg-type-medical-transponder = medical cyborg + +borg-type-service-name = Service +borg-type-service-desc = Help out with a wide range of crew services, ranging from serving snacks and drinks to botany to entertainment. +borg-type-service-transponder = service cyborg + + diff --git a/Resources/Prototypes/Actions/borgs.yml b/Resources/Prototypes/Actions/borgs.yml index a0168ef00fc4..0f635ba3ec67 100644 --- a/Resources/Prototypes/Actions/borgs.yml +++ b/Resources/Prototypes/Actions/borgs.yml @@ -10,3 +10,15 @@ state: state-laws event: !type:ToggleLawsScreenEvent useDelay: 0.5 + +- type: entity + id: ActionSelectBorgType + name: Select Cyborg Type + components: + - type: InstantAction + itemIconStyle: NoItem + icon: + sprite: Interface/Actions/actions_borg.rsi + state: select-type + event: !type:BorgToggleSelectTypeEvent + useDelay: 0.5 diff --git a/Resources/Prototypes/Body/Parts/silicon.yml b/Resources/Prototypes/Body/Parts/silicon.yml index 6b2b3f57d264..3b0f2540963d 100644 --- a/Resources/Prototypes/Body/Parts/silicon.yml +++ b/Resources/Prototypes/Body/Parts/silicon.yml @@ -28,82 +28,105 @@ - Robotics - type: entity - id: BaseBorgArmLeft + id: LeftArmBorg parent: PartSilicon name: cyborg left arm - abstract: true components: - type: BodyPart partType: Hand symmetry: Left + - type: Sprite + state: borg_l_arm + - type: Icon + state: borg_l_arm - type: Tag tags: - Trash - BorgArm + - BorgLArm - type: entity - id: BaseBorgArmRight + id: RightArmBorg parent: PartSilicon name: cyborg right arm - abstract: true components: - type: BodyPart partType: Hand symmetry: Right + - type: Sprite + state: borg_r_arm + - type: Icon + state: borg_r_arm - type: Tag tags: - Trash - BorgArm + - BorgRArm - type: entity - id: BaseBorgLegLeft + id: LeftLegBorg parent: PartSilicon name: cyborg left leg - abstract: true components: - type: BodyPart partType: Leg symmetry: Left + - type: Sprite + state: borg_l_leg + - type: Icon + state: borg_l_leg - type: Tag tags: - Trash - BorgLeg + - BorgLLeg - type: entity - id: BaseBorgLegRight + id: RightLegBorg parent: PartSilicon name: cyborg right leg - abstract: true components: - type: BodyPart partType: Leg symmetry: Right + - type: Sprite + state: borg_r_leg + - type: Icon + state: borg_r_leg - type: Tag tags: - Trash - BorgLeg + - BorgRLeg - type: entity - id: BaseBorgHead + id: LightHeadBorg parent: PartSilicon name: cyborg head - abstract: true components: - type: BodyPart partType: Head + - type: Sprite + state: borg_head + - type: Icon + state: borg_head - type: Tag tags: - Trash - BorgHead - type: entity - id: BaseBorgTorso + id: TorsoBorg parent: PartSilicon name: cyborg torso - abstract: true components: - type: BodyPart partType: Torso + - type: Sprite + state: borg_chest + - type: Icon + state: borg_chest - type: Tag tags: - Trash + - BorgTorso diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml index 0db92ac941d4..9303bd42dd55 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml @@ -69,6 +69,9 @@ type: BorgBoundUserInterface enum.StrippingUiKey.Key: type: StrippableBoundUserInterface + # Only used for NT borgs that can switch type, defined here to avoid copy-pasting the rest of this component. + enum.BorgSwitchableTypeUiKey.SelectBorgType: + type: BorgSelectTypeUserInterface - type: ActivatableUI key: enum.BorgUiKey.Key - type: SiliconLawBound @@ -157,6 +160,7 @@ collection: FootstepBorg - type: Construction graph: Cyborg + node: cyborg containers: - part-container - cell_slot @@ -285,6 +289,9 @@ - type: AccessReader access: [["Command"], ["Research"]] - type: ShowJobIcons + - type: InteractionPopup + interactSuccessSound: + path: /Audio/Ambience/Objects/periodic_beep.ogg - type: entity id: BaseBorgChassisSyndicate diff --git a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml index 6a8f1e5abb08..fa324c0124fd 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/borg_chassis.yml @@ -1,23 +1,22 @@ - type: entity - id: BorgChassisGeneric + id: BorgChassisSelectable parent: BaseBorgChassisNT components: - type: Sprite layers: - state: robot + map: ["enum.BorgVisualLayers.Body", "movement"] - state: robot_e_r map: ["enum.BorgVisualLayers.Light"] shader: unshaded visible: false - state: robot_l shader: unshaded - map: ["light"] + map: ["light","enum.BorgVisualLayers.LightStatus"] visible: false - type: BorgChassis - maxModules: 6 - moduleWhitelist: - tags: - - BorgModuleGeneric + # Default borg can take no modules until selected type. + maxModules: 0 hasMindState: robot_e noMindState: robot_e_r - type: BorgTransponder @@ -25,308 +24,62 @@ sprite: Mobs/Silicon/chassis.rsi state: robot name: cyborg - - type: Construction - node: cyborg - - type: Speech - speechVerb: Robotic - type: InteractionPopup interactSuccessString: petting-success-generic-cyborg interactFailureString: petting-failure-generic-cyborg - interactSuccessSound: - path: /Audio/Ambience/Objects/periodic_beep.ogg + - type: BorgSwitchableType + inherentRadioChannels: + - Common + - Binary + +- type: entity + id: BorgChassisGeneric + parent: BorgChassisSelectable + name: generic cyborg + suffix: type picked + components: + - type: BorgSwitchableType + selectedBorgType: generic - type: entity id: BorgChassisMining - parent: BaseBorgChassisNT + parent: BorgChassisSelectable name: salvage cyborg components: - - type: Sprite - layers: - - state: miner - map: ["movement"] - - state: miner_e_r - map: ["enum.BorgVisualLayers.Light"] - shader: unshaded - visible: false - - state: miner_l - shader: unshaded - map: ["light"] - visible: false - - type: SpriteMovement - movementLayers: - movement: - state: miner_moving - noMovementLayers: - movement: - state: miner - - type: BorgChassis - maxModules: 4 - moduleWhitelist: - tags: - - BorgModuleGeneric - - BorgModuleCargo - hasMindState: miner_e - noMindState: miner_e_r - - type: BorgTransponder - sprite: - sprite: Mobs/Silicon/chassis.rsi - state: miner - name: salvage cyborg - - type: Construction - node: mining - - type: IntrinsicRadioTransmitter - channels: - - Supply - - Binary - - Common - - Science - - type: ActiveRadio - channels: - - Supply - - Binary - - Common - - Science - - type: AccessReader - access: [["Cargo"], ["Salvage"], ["Command"], ["Research"]] - - type: Inventory - templateId: borgTall - - type: InteractionPopup - interactSuccessString: petting-success-salvage-cyborg - interactFailureString: petting-failure-salvage-cyborg - interactSuccessSound: - path: /Audio/Ambience/Objects/periodic_beep.ogg + - type: BorgSwitchableType + selectedBorgType: mining - type: entity id: BorgChassisEngineer - parent: BaseBorgChassisNT + parent: BorgChassisSelectable name: engineer cyborg components: - - type: Sprite - layers: - - state: engineer - - state: engineer_e_r - map: ["enum.BorgVisualLayers.Light"] - shader: unshaded - visible: false - - state: engineer_l - shader: unshaded - map: ["light"] - visible: false - - type: BorgChassis - maxModules: 4 - moduleWhitelist: - tags: - - BorgModuleGeneric - - BorgModuleEngineering - hasMindState: engineer_e - noMindState: engineer_e_r - - type: BorgTransponder - sprite: - sprite: Mobs/Silicon/chassis.rsi - state: engineer - name: engineer cyborg - - type: Construction - node: engineer - - type: IntrinsicRadioTransmitter - channels: - - Engineering - - Binary - - Common - - Science - - type: ActiveRadio - channels: - - Engineering - - Binary - - Common - - Science - - type: AccessReader - access: [["Engineering"], ["Command"], ["Research"]] - - type: Inventory - templateId: borgShort - - type: InteractionPopup - interactSuccessString: petting-success-engineer-cyborg - interactFailureString: petting-failure-engineer-cyborg - interactSuccessSound: - path: /Audio/Ambience/Objects/periodic_beep.ogg + - type: BorgSwitchableType + selectedBorgType: engineering - type: entity id: BorgChassisJanitor - parent: BaseBorgChassisNT + parent: BorgChassisSelectable name: janitor cyborg components: - - type: Sprite - layers: - - state: janitor - map: ["movement"] - - state: janitor_e_r - map: ["enum.BorgVisualLayers.Light"] - shader: unshaded - visible: false - - state: janitor_l - shader: unshaded - map: ["light"] - visible: false - - type: SpriteMovement - movementLayers: - movement: - state: janitor_moving - noMovementLayers: - movement: - state: janitor - - type: BorgChassis - maxModules: 4 - moduleWhitelist: - tags: - - BorgModuleGeneric - - BorgModuleJanitor - hasMindState: janitor_e - noMindState: janitor_e_r - - type: BorgTransponder - sprite: - sprite: Mobs/Silicon/chassis.rsi - state: janitor - name: janitor cyborg - - type: Construction - node: janitor - - type: IntrinsicRadioTransmitter - channels: - - Service - - Binary - - Common - - Science - - type: ActiveRadio - channels: - - Service - - Binary - - Common - - Science - - type: AccessReader - access: [["Service"], ["Command"], ["Research"]] - - type: Inventory - templateId: borgShort - - type: InteractionPopup - interactSuccessString: petting-success-janitor-cyborg - interactFailureString: petting-failure-janitor-cyborg - interactSuccessSound: - path: /Audio/Ambience/Objects/periodic_beep.ogg + - type: BorgSwitchableType + selectedBorgType: janitor - type: entity id: BorgChassisMedical - parent: [BaseBorgChassisNT, ShowMedicalIcons] + parent: BorgChassisSelectable name: medical cyborg components: - - type: Sprite - layers: - - state: medical - map: ["movement"] - - state: medical_e_r - map: ["enum.BorgVisualLayers.Light"] - shader: unshaded - visible: false - - state: medical_l - shader: unshaded - map: ["light"] - visible: false - - type: SpriteMovement - movementLayers: - movement: - state: medical_moving - noMovementLayers: - movement: - state: medical - - type: BorgChassis - maxModules: 4 - moduleWhitelist: - tags: - - BorgModuleGeneric - - BorgModuleMedical - hasMindState: medical_e - noMindState: medical_e_r - - type: BorgTransponder - sprite: - sprite: Mobs/Silicon/chassis.rsi - state: medical - name: medical cyborg - - type: Construction - node: medical - - type: IntrinsicRadioTransmitter - channels: - - Medical - - Binary - - Common - - Science - - type: ActiveRadio - channels: - - Medical - - Binary - - Common - - Science - - type: AccessReader - access: [["Medical"], ["Command"], ["Research"]] - - type: Inventory - templateId: borgDutch - - type: FootstepModifier - footstepSoundCollection: - collection: FootstepHoverBorg - - type: SolutionScanner - - type: InteractionPopup - interactSuccessString: petting-success-medical-cyborg - interactFailureString: petting-failure-medical-cyborg - interactSuccessSound: - path: /Audio/Ambience/Objects/periodic_beep.ogg + - type: BorgSwitchableType + selectedBorgType: medical - type: entity id: BorgChassisService - parent: BaseBorgChassisNT + parent: BorgChassisSelectable name: service cyborg components: - - type: Sprite - layers: - - state: service - - state: service_e_r - map: ["enum.BorgVisualLayers.Light"] - shader: unshaded - visible: false - - state: service_l - shader: unshaded - map: ["light"] - visible: false - - type: BorgChassis - maxModules: 4 - moduleWhitelist: - tags: - - BorgModuleGeneric - - BorgModuleService - hasMindState: service_e - noMindState: service_e_r - - type: BorgTransponder - sprite: - sprite: Mobs/Silicon/chassis.rsi - state: service - name: service cyborg - - type: Construction - node: service - - type: IntrinsicRadioTransmitter - channels: - - Service - - Binary - - Common - - Science - - type: ActiveRadio - channels: - - Service - - Binary - - Common - - Science - - type: AccessReader - access: [["Service"], ["Command"], ["Research"]] - - type: Inventory - templateId: borgTall - - type: InteractionPopup - interactSuccessString: petting-success-service-cyborg - interactFailureString: petting-failure-service-cyborg - interactSuccessSound: - path: /Audio/Ambience/Objects/periodic_beep.ogg + - type: BorgSwitchableType + selectedBorgType: service - type: entity id: BorgChassisSyndicateAssault @@ -354,8 +107,6 @@ - BorgModuleSyndicateAssault hasMindState: synd_sec_e noMindState: synd_sec - - type: Construction - node: syndicateassault - type: InteractionPopup interactSuccessString: petting-success-syndicate-cyborg interactFailureString: petting-failure-syndicate-cyborg @@ -388,8 +139,6 @@ - BorgModuleSyndicate hasMindState: synd_medical_e noMindState: synd_medical - - type: Construction - node: syndicatemedical - type: ShowHealthBars - type: InteractionPopup interactSuccessString: petting-success-syndicate-cyborg @@ -429,8 +178,6 @@ - BorgModuleSyndicate hasMindState: synd_engi_e noMindState: synd_engi - - type: Construction - node: syndicatesaboteur - type: ShowHealthBars damageContainers: - Inorganic diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml index e787ef59f00a..bcac46ed842a 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml @@ -429,28 +429,9 @@ map: ["base"] # Borgs -- type: entity - id: PlayerBorgGeneric - parent: BorgChassisGeneric - suffix: Battery, Tools - components: - - type: ContainerFill - containers: - borg_brain: - - PositronicBrain - borg_module: - - BorgModuleTool - - type: ItemSlots - slots: - cell_slot: - name: power-cell-slot-component-slot-name-default - startingItem: PowerCellMedium - - type: RandomMetadata - nameSegments: [names_borg] - - type: entity id: PlayerBorgBattery - parent: BorgChassisGeneric + parent: BorgChassisSelectable suffix: Battery components: - type: ContainerFill diff --git a/Resources/Prototypes/Entities/Objects/Specific/Robotics/borg_parts.yml b/Resources/Prototypes/Entities/Objects/Specific/Robotics/borg_parts.yml deleted file mode 100644 index 6df0488e28fe..000000000000 --- a/Resources/Prototypes/Entities/Objects/Specific/Robotics/borg_parts.yml +++ /dev/null @@ -1,503 +0,0 @@ -# generic parts -- type: entity - id: LeftArmBorg - parent: BaseBorgArmLeft - components: - - type: Sprite - state: borg_l_arm - - type: Icon - state: borg_l_arm - - type: Tag - tags: - - Trash - - BorgArm - - BorgGenericLArm - -- type: entity - id: RightArmBorg - parent: BaseBorgArmRight - components: - - type: Sprite - state: borg_r_arm - - type: Icon - state: borg_r_arm - - type: Tag - tags: - - Trash - - BorgArm - - BorgGenericRArm - -- type: entity - id: LeftLegBorg - parent: BaseBorgLegLeft - components: - - type: Sprite - state: borg_l_leg - - type: Icon - state: borg_l_leg - - type: Tag - tags: - - Trash - - BorgLeg - - BorgGenericLLeg - -- type: entity - id: RightLegBorg - parent: BaseBorgLegRight - components: - - type: Sprite - state: borg_r_leg - - type: Icon - state: borg_r_leg - - type: Tag - tags: - - Trash - - BorgLeg - - BorgGenericRLeg - -- type: entity - id: LightHeadBorg - parent: BaseBorgHead - components: - - type: Sprite - state: borg_head - - type: Icon - state: borg_head - - type: Tag - tags: - - Trash - - BorgHead - - BorgGenericHead - -- type: entity - id: TorsoBorg - parent: BaseBorgTorso - components: - - type: Sprite - state: borg_chest - - type: Icon - state: borg_chest - - type: Tag - tags: - - Trash - - BorgGenericTorso - -# engineer parts -- type: entity - id: LeftArmBorgEngineer - parent: BaseBorgArmLeft - name: engineer cyborg left arm - components: - - type: Sprite - state: engineer_l_arm - - type: Icon - state: engineer_l_arm - - type: Tag - tags: - - Trash - - BorgArm - - BorgEngineerLArm - -- type: entity - id: RightArmBorgEngineer - parent: BaseBorgArmRight - name: engineer cyborg right arm - components: - - type: Sprite - state: engineer_r_arm - - type: Icon - state: engineer_r_arm - - type: Tag - tags: - - Trash - - BorgArm - - BorgEngineerRArm - -- type: entity - id: LeftLegBorgEngineer - parent: BaseBorgLegLeft - name: engineer cyborg left leg - components: - - type: Sprite - state: engineer_l_leg - - type: Icon - state: engineer_l_leg - - type: Tag - tags: - - Trash - - BorgLeg - - BorgEngineerLLeg - -- type: entity - id: RightLegBorgEngineer - parent: BaseBorgLegRight - name: engineer cyborg right leg - components: - - type: Sprite - state: engineer_r_leg - - type: Icon - state: engineer_r_leg - - type: Tag - tags: - - Trash - - BorgLeg - - BorgEngineerRLeg - -- type: entity - id: HeadBorgEngineer - parent: BaseBorgHead - name: engineer cyborg head - components: - - type: Sprite - state: engineer_head - - type: Icon - state: engineer_head - - type: Tag - tags: - - Trash - - BorgHead - - BorgEngineerHead - -- type: entity - id: TorsoBorgEngineer - parent: BaseBorgTorso - name: engineer cyborg torso - components: - - type: Sprite - state: engineer_chest - - type: Icon - state: engineer_chest - - type: Tag - tags: - - Trash - - BorgEngineerTorso - -# janitor parts -- type: entity - id: LeftLegBorgJanitor - parent: BaseBorgLegLeft - name: janitor cyborg left leg - components: - - type: Sprite - state: janitor_l_leg - - type: Icon - state: janitor_l_leg - - type: Tag - tags: - - Trash - - BorgLeg - - BorgJanitorLLeg - -- type: entity - id: RightLegBorgJanitor - parent: BaseBorgLegRight - name: janitor cyborg right leg - components: - - type: Sprite - state: janitor_r_leg - - type: Icon - state: janitor_r_leg - - type: Tag - tags: - - Trash - - BorgLeg - - BorgJanitorRLeg - -- type: entity - id: HeadBorgJanitor - parent: BaseBorgHead - name: janitor cyborg head - components: - - type: Sprite - state: janitor_head - - type: Icon - state: janitor_head - - type: Tag - tags: - - Trash - - BorgHead - - BorgJanitorHead - -- type: entity - id: TorsoBorgJanitor - parent: BaseBorgTorso - name: janitor cyborg torso - components: - - type: Sprite - state: janitor_chest - - type: Icon - state: janitor_chest - - type: Tag - tags: - - Trash - - BorgJanitorTorso - -# medical parts -- type: entity - id: LeftArmBorgMedical - parent: BaseBorgArmLeft - name: medical cyborg left arm - components: - - type: Sprite - state: medical_l_arm - - type: Icon - state: medical_l_arm - - type: Tag - tags: - - Trash - - BorgArm - - BorgMedicalLArm - -- type: entity - id: RightArmBorgMedical - parent: BaseBorgArmRight - name: medical cyborg right arm - components: - - type: Sprite - state: medical_r_arm - - type: Icon - state: medical_r_arm - - type: Tag - tags: - - Trash - - BorgArm - - BorgMedicalRArm - -- type: entity - id: LeftLegBorgMedical - parent: BaseBorgLegLeft - name: medical cyborg left leg - components: - - type: Sprite - state: medical_l_leg - - type: Icon - state: medical_l_leg - - type: Tag - tags: - - Trash - - BorgLeg - - BorgMedicalLLeg - -- type: entity - id: RightLegBorgMedical - parent: BaseBorgLegRight - name: medical cyborg right leg - components: - - type: Sprite - state: medical_r_leg - - type: Icon - state: medical_r_leg - - type: Tag - tags: - - Trash - - BorgLeg - - BorgMedicalRLeg - -- type: entity - id: HeadBorgMedical - parent: BaseBorgHead - name: medical cyborg head - components: - - type: Sprite - state: medical_head - - type: Icon - state: medical_head - - type: Tag - tags: - - Trash - - BorgHead - - BorgMedicalHead - -- type: entity - id: TorsoBorgMedical - parent: BaseBorgTorso - name: medical cyborg torso - components: - - type: Sprite - state: medical_chest - - type: Icon - state: medical_chest - - type: Tag - tags: - - Trash - - BorgMedicalTorso - -# mining parts -- type: entity - id: LeftArmBorgMining - parent: BaseBorgArmLeft - name: mining cyborg left arm - components: - - type: Sprite - state: mining_l_arm - - type: Icon - state: mining_l_arm - - type: Tag - tags: - - Trash - - BorgArm - - BorgMiningLArm - -- type: entity - id: RightArmBorgMining - parent: BaseBorgArmRight - name: mining cyborg right arm - components: - - type: Sprite - state: mining_r_arm - - type: Icon - state: mining_r_arm - - type: Tag - tags: - - Trash - - BorgArm - - BorgMiningRArm - -- type: entity - id: LeftLegBorgMining - parent: BaseBorgLegLeft - name: mining cyborg left leg - components: - - type: Sprite - state: mining_l_leg - - type: Icon - state: mining_l_leg - - type: Tag - tags: - - Trash - - BorgLeg - - BorgMiningLLeg - -- type: entity - id: RightLegBorgMining - parent: BaseBorgLegRight - name: mining cyborg right leg - components: - - type: Sprite - state: mining_r_leg - - type: Icon - state: mining_r_leg - - type: Tag - tags: - - Trash - - BorgLeg - - BorgMiningRLeg - -- type: entity - id: HeadBorgMining - parent: BaseBorgHead - name: mining cyborg head - components: - - type: Sprite - state: mining_head - - type: Icon - state: mining_head - - type: Tag - tags: - - Trash - - BorgHead - - BorgMiningHead - -- type: entity - id: TorsoBorgMining - parent: BaseBorgTorso - name: mining cyborg torso - components: - - type: Sprite - state: mining_chest - - type: Icon - state: mining_chest - - type: Tag - tags: - - Trash - - BorgMiningTorso - -# service parts -- type: entity - id: LeftArmBorgService - parent: BaseBorgArmLeft - name: service cyborg left arm - components: - - type: Sprite - state: service_l_arm - - type: Icon - state: service_l_arm - - type: Tag - tags: - - Trash - - BorgArm - - BorgServiceLArm - -- type: entity - id: RightArmBorgService - parent: BaseBorgArmRight - name: service cyborg right arm - components: - - type: Sprite - state: service_r_arm - - type: Icon - state: service_r_arm - - type: Tag - tags: - - Trash - - BorgArm - - BorgServiceRArm - -- type: entity - id: LeftLegBorgService - parent: BaseBorgLegLeft - name: service cyborg left leg - components: - - type: Sprite - state: service_l_leg - - type: Icon - state: service_l_leg - - type: Tag - tags: - - Trash - - BorgLeg - - BorgServiceLLeg - -- type: entity - id: RightLegBorgService - parent: BaseBorgLegRight - name: service cyborg right leg - components: - - type: Sprite - state: service_r_leg - - type: Icon - state: service_r_leg - - type: Tag - tags: - - Trash - - BorgLeg - - BorgServiceRLeg - -- type: entity - id: HeadBorgService - parent: BaseBorgHead - name: service cyborg head - components: - - type: Sprite - state: service_head - - type: Icon - state: service_head - - type: Tag - tags: - - Trash - - BorgHead - - BorgServiceHead - -- type: entity - id: TorsoBorgService - parent: BaseBorgTorso - name: service cyborg torso - components: - - type: Sprite - state: service_chest - - type: Icon - state: service_chest - - type: Tag - tags: - - Trash - - BorgServiceTorso diff --git a/Resources/Prototypes/Entities/Objects/Specific/Robotics/endoskeleton.yml b/Resources/Prototypes/Entities/Objects/Specific/Robotics/endoskeleton.yml index 9261e06ea2a7..6afc06a79675 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Robotics/endoskeleton.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Robotics/endoskeleton.yml @@ -33,139 +33,27 @@ borg_l_arm+o: whitelist: tags: - - BorgGenericLArm + - BorgLArm borg_r_arm+o: whitelist: tags: - - BorgGenericRArm + - BorgRArm borg_l_leg+o: whitelist: tags: - - BorgGenericLLeg + - BorgLLeg borg_r_leg+o: whitelist: tags: - - BorgGenericRLeg + - BorgRLeg borg_head+o: whitelist: tags: - - BorgGenericHead + - BorgHead borg_chest+o: whitelist: tags: - - BorgGenericTorso - service_l_arm+o: - whitelist: - tags: - - BorgServiceLArm - service_r_arm+o: - whitelist: - tags: - - BorgServiceRArm - service_l_leg+o: - whitelist: - tags: - - BorgServiceLLeg - service_r_leg+o: - whitelist: - tags: - - BorgServiceRLeg - service_head+o: - whitelist: - tags: - - BorgServiceHead - service_chest+o: - whitelist: - tags: - - BorgServiceTorso - engineer_l_arm+o: - whitelist: - tags: - - BorgEngineerLArm - engineer_r_arm+o: - whitelist: - tags: - - BorgEngineerRArm - engineer_l_leg+o: - whitelist: - tags: - - BorgEngineerLLeg - engineer_r_leg+o: - whitelist: - tags: - - BorgEngineerRLeg - engineer_head+o: - whitelist: - tags: - - BorgEngineerHead - engineer_chest+o: - whitelist: - tags: - - BorgEngineerTorso - mining_l_arm+o: - whitelist: - tags: - - BorgMiningLArm - mining_r_arm+o: - whitelist: - tags: - - BorgMiningRArm - mining_l_leg+o: - whitelist: - tags: - - BorgMiningLLeg - mining_r_leg+o: - whitelist: - tags: - - BorgMiningRLeg - mining_head+o: - whitelist: - tags: - - BorgMiningHead - mining_chest+o: - whitelist: - tags: - - BorgMiningTorso - medical_l_arm+o: - whitelist: - tags: - - BorgMedicalLArm - medical_r_arm+o: - whitelist: - tags: - - BorgMedicalRArm - medical_l_leg+o: - whitelist: - tags: - - BorgMedicalLLeg - medical_r_leg+o: - whitelist: - tags: - - BorgMedicalRLeg - medical_head+o: - whitelist: - tags: - - BorgMedicalHead - medical_chest+o: - whitelist: - tags: - - BorgMedicalTorso - janitor_l_leg+o: - whitelist: - tags: - - BorgJanitorLLeg - janitor_r_leg+o: - whitelist: - tags: - - BorgJanitorRLeg - janitor_head+o: - whitelist: - tags: - - BorgJanitorHead - janitor_chest+o: - whitelist: - tags: - - BorgJanitorTorso + - BorgTorso - type: ContainerContainer containers: part-container: !type:Container @@ -173,45 +61,12 @@ - type: PartAssembly parts: generic: - - BorgGenericLArm - - BorgGenericRArm - - BorgGenericLLeg - - BorgGenericRLeg - - BorgGenericHead - - BorgGenericTorso - service: - - BorgServiceLArm - - BorgServiceRArm - - BorgServiceLLeg - - BorgServiceRLeg - - BorgServiceHead - - BorgServiceTorso - engineer: - - BorgEngineerLArm - - BorgEngineerRArm - - BorgEngineerLLeg - - BorgEngineerRLeg - - BorgEngineerHead - - BorgEngineerTorso - medical: - - BorgMedicalLArm - - BorgMedicalRArm - - BorgMedicalLLeg - - BorgMedicalRLeg - - BorgMedicalHead - - BorgMedicalTorso - janitor: - - BorgJanitorLLeg - - BorgJanitorRLeg - - BorgJanitorHead - - BorgJanitorTorso - mining: - - BorgMiningLArm - - BorgMiningRArm - - BorgMiningLLeg - - BorgMiningRLeg - - BorgMiningHead - - BorgMiningTorso + - BorgLArm + - BorgRArm + - BorgLLeg + - BorgRLeg + - BorgHead + - BorgTorso - type: Construction graph: Cyborg node: start diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml index 020566ad1a73..6a94891d127b 100644 --- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml +++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml @@ -572,11 +572,6 @@ - BorgModuleFireExtinguisher - BorgModuleRadiationDetection - BorgModuleTool - - BorgModuleAppraisal - - BorgModuleConstruction - - BorgModuleService - - BorgModuleTreatment - - BorgModuleCleaning - CyborgEndoskeleton - LeftArmBorg - RightArmBorg @@ -584,50 +579,15 @@ - RightLegBorg - LightHeadBorg - TorsoBorg - - LeftArmBorgEngineer - - RightArmBorgEngineer - - LeftLegBorgEngineer - - RightLegBorgEngineer - - HeadBorgEngineer - - TorsoBorgEngineer - - LeftLegBorgJanitor - - RightLegBorgJanitor - - HeadBorgJanitor - - TorsoBorgJanitor - - LeftArmBorgMedical - - RightArmBorgMedical - - LeftLegBorgMedical - - RightLegBorgMedical - - HeadBorgMedical - - TorsoBorgMedical - - LeftArmBorgMining - - RightArmBorgMining - - LeftLegBorgMining - - RightLegBorgMining - - HeadBorgMining - - TorsoBorgMining - - LeftArmBorgService - - RightArmBorgService - - LeftLegBorgService - - RightLegBorgService - - HeadBorgService - - TorsoBorgService dynamicRecipes: - ProximitySensor - - BorgModuleLightReplacer - BorgModuleAdvancedCleaning - - BorgModuleMining - - BorgModuleGrapplingGun - BorgModuleAdvancedTool - BorgModuleGPS - - BorgModuleRCD - BorgModuleArtifact - BorgModuleAnomaly - BorgModuleGardening - BorgModuleHarvesting - - BorgModuleMusique - - BorgModuleClowning - - BorgModuleDiagnosis - BorgModuleDefibrillator - BorgModuleAdvancedTreatment - RipleyHarness diff --git a/Resources/Prototypes/InventoryTemplates/borg.yml b/Resources/Prototypes/InventoryTemplates/borg.yml index d43519f61cf4..3d3ef29eb037 100644 --- a/Resources/Prototypes/InventoryTemplates/borg.yml +++ b/Resources/Prototypes/InventoryTemplates/borg.yml @@ -26,8 +26,7 @@ - name: head slotTexture: head slotFlags: HEAD - slotGroup: MainHotbar - uiWindowPos: 0,0 + uiWindowPos: 1,0 strippingWindowPos: 0,0 displayName: Head offset: 0.015625, 0 diff --git a/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml b/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml index 0f012cefc98e..4ebc43667c5e 100644 --- a/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml +++ b/Resources/Prototypes/Recipes/Construction/Graphs/machines/cyborg.yml @@ -5,18 +5,6 @@ - node: start entity: CyborgEndoskeleton edges: - - # empty the parts via prying - - to: start - conditions: - - !type:ContainerNotEmpty - container: part-container - steps: - - tool: Prying - doAfter: 0.5 - completed: - - !type:EmptyAllContainers - - to: cyborg steps: - assemblyId: generic @@ -43,165 +31,6 @@ - tool: Screwing doAfter: 0.5 - - - to: engineer - steps: - - assemblyId: engineer - guideString: borg-construction-guide-string - - - material: Cable - amount: 1 - doAfter: 1 - store: part-container - - - component: Flash - name: flash - store: part-container - icon: - sprite: Objects/Weapons/Melee/flash.rsi - state: flash - - - component: Flash - name: second flash - store: part-container - icon: - sprite: Objects/Weapons/Melee/flash.rsi - state: flash - - - tool: Screwing - doAfter: 0.5 - - - to: janitor - steps: - - assemblyId: janitor - guideString: borg-construction-guide-string - - - material: Cable - amount: 1 - doAfter: 1 - store: part-container - - - component: Flash - name: flash - store: part-container - icon: - sprite: Objects/Weapons/Melee/flash.rsi - state: flash - - - component: Flash - name: second flash - store: part-container - icon: - sprite: Objects/Weapons/Melee/flash.rsi - state: flash - - - tool: Screwing - doAfter: 0.5 - - - to: medical - steps: - - assemblyId: medical - guideString: borg-construction-guide-string - - - material: Cable - amount: 1 - doAfter: 1 - store: part-container - - - component: Flash - name: flash - store: part-container - icon: - sprite: Objects/Weapons/Melee/flash.rsi - state: flash - - - component: Flash - name: second flash - store: part-container - icon: - sprite: Objects/Weapons/Melee/flash.rsi - state: flash - - - tool: Screwing - doAfter: 0.5 - - - to: mining - steps: - - assemblyId: mining - guideString: borg-construction-guide-string - - - material: Cable - amount: 1 - doAfter: 1 - store: part-container - - - component: Flash - name: flash - store: part-container - icon: - sprite: Objects/Weapons/Melee/flash.rsi - state: flash - - - component: Flash - name: second flash - store: part-container - icon: - sprite: Objects/Weapons/Melee/flash.rsi - state: flash - - - tool: Screwing - doAfter: 0.5 - - - to: service - steps: - - assemblyId: service - guideString: borg-construction-guide-string - - - material: Cable - amount: 1 - doAfter: 1 - store: part-container - - - component: Flash - name: flash - store: part-container - icon: - sprite: Objects/Weapons/Melee/flash.rsi - state: flash - - - component: Flash - name: second flash - store: part-container - icon: - sprite: Objects/Weapons/Melee/flash.rsi - state: flash - - - tool: Screwing - doAfter: 0.5 - node: cyborg - entity: BorgChassisGeneric - - - node: engineer - entity: BorgChassisEngineer - - - node: janitor - entity: BorgChassisJanitor - - - node: mining - entity: BorgChassisMining - - - node: medical - entity: BorgChassisMedical - - - node: service - entity: BorgChassisService - - - node: syndicateassault - entity: BorgChassisSyndicateAssault - - - node: syndicatemedical - entity: BorgChassisSyndicateMedical - - - node: syndicatesaboteur - entity: BorgChassisSyndicateSaboteur + entity: BorgChassisSelectable diff --git a/Resources/Prototypes/Recipes/Lathes/robotics.yml b/Resources/Prototypes/Recipes/Lathes/robotics.yml index bf8deba9840e..a4413e01ebee 100644 --- a/Resources/Prototypes/Recipes/Lathes/robotics.yml +++ b/Resources/Prototypes/Recipes/Lathes/robotics.yml @@ -61,8 +61,6 @@ materials: Steel: 1500 -# Generic - - type: latheRecipe parent: BaseBorgLimbRecipe id: LeftArmBorg @@ -93,162 +91,6 @@ id: TorsoBorg result: TorsoBorg -# Engineer - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: LeftArmBorgEngineer - result: LeftArmBorgEngineer - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: RightArmBorgEngineer - result: RightArmBorgEngineer - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: LeftLegBorgEngineer - result: LeftLegBorgEngineer - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: RightLegBorgEngineer - result: RightLegBorgEngineer - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: HeadBorgEngineer - result: HeadBorgEngineer - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: TorsoBorgEngineer - result: TorsoBorgEngineer - -# Medical - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: LeftArmBorgMedical - result: LeftArmBorgMedical - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: RightArmBorgMedical - result: RightArmBorgMedical - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: LeftLegBorgMedical - result: LeftLegBorgMedical - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: RightLegBorgMedical - result: RightLegBorgMedical - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: HeadBorgMedical - result: HeadBorgMedical - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: TorsoBorgMedical - result: TorsoBorgMedical - -# Mining - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: LeftArmBorgMining - result: LeftArmBorgMining - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: RightArmBorgMining - result: RightArmBorgMining - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: LeftLegBorgMining - result: LeftLegBorgMining - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: RightLegBorgMining - result: RightLegBorgMining - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: HeadBorgMining - result: HeadBorgMining - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: TorsoBorgMining - result: TorsoBorgMining - -# Service - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: LeftArmBorgService - result: LeftArmBorgService - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: RightArmBorgService - result: RightArmBorgService - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: LeftLegBorgService - result: LeftLegBorgService - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: RightLegBorgService - result: RightLegBorgService - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: HeadBorgService - result: HeadBorgService - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: TorsoBorgService - result: TorsoBorgService - -# Janitor - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: LeftLegBorgJanitor - result: LeftLegBorgJanitor - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: RightLegBorgJanitor - result: RightLegBorgJanitor - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: HeadBorgJanitor - result: HeadBorgJanitor - materials: - Steel: 500 - Glass: 200 - -- type: latheRecipe - parent: BaseBorgLimbRecipe - id: TorsoBorgJanitor - result: TorsoBorgJanitor - materials: - Steel: 500 - Glass: 200 - # Parts - type: latheRecipe @@ -304,23 +146,6 @@ id: BorgModuleTool result: BorgModuleTool -# Mining Modules - -- type: latheRecipe - parent: BaseBorgModuleRecipe - id: BorgModuleAppraisal - result: BorgModuleAppraisal - -- type: latheRecipe - parent: BaseBorgModuleRecipe - id: BorgModuleMining - result: BorgModuleMining - -- type: latheRecipe - parent: BaseGoldBorgModuleRecipe - id: BorgModuleGrapplingGun - result: BorgModuleGrapplingGun - # Engineering Modules - type: latheRecipe @@ -328,28 +153,8 @@ id: BorgModuleAdvancedTool result: BorgModuleAdvancedTool -- type: latheRecipe - parent: BaseBorgModuleRecipe - id: BorgModuleConstruction - result: BorgModuleConstruction - -- type: latheRecipe - parent: BaseGoldBorgModuleRecipe - id: BorgModuleRCD - result: BorgModuleRCD - # Janitor Modules -- type: latheRecipe - parent: BaseBorgModuleRecipe - id: BorgModuleLightReplacer - result: BorgModuleLightReplacer - -- type: latheRecipe - parent: BaseBorgModuleRecipe - id: BorgModuleCleaning - result: BorgModuleCleaning - - type: latheRecipe parent: BaseGoldBorgModuleRecipe id: BorgModuleAdvancedCleaning @@ -357,16 +162,6 @@ # Medical Modules -- type: latheRecipe - parent: BaseBorgModuleRecipe - id: BorgModuleDiagnosis - result: BorgModuleDiagnosis - -- type: latheRecipe - parent: BaseBorgModuleRecipe - id: BorgModuleTreatment - result: BorgModuleTreatment - - type: latheRecipe parent: BaseGoldBorgModuleRecipe id: BorgModuleAdvancedTreatment @@ -391,16 +186,6 @@ # Service Modules -- type: latheRecipe - parent: BaseBorgModuleRecipe - id: BorgModuleService - result: BorgModuleService - -- type: latheRecipe - parent: BaseBorgModuleRecipe - id: BorgModuleMusique - result: BorgModuleMusique - - type: latheRecipe parent: BaseBorgModuleRecipe id: BorgModuleGardening @@ -410,8 +195,3 @@ parent: BaseBorgModuleRecipe id: BorgModuleHarvesting result: BorgModuleHarvesting - -- type: latheRecipe - parent: BaseBorgModuleRecipe - id: BorgModuleClowning - result: BorgModuleClowning diff --git a/Resources/Prototypes/Research/civilianservices.yml b/Resources/Prototypes/Research/civilianservices.yml index b990eb6ae40c..9430c391a992 100644 --- a/Resources/Prototypes/Research/civilianservices.yml +++ b/Resources/Prototypes/Research/civilianservices.yml @@ -66,8 +66,6 @@ recipeUnlocks: - ComputerTelevisionCircuitboard - SynthesizerInstrument - - BorgModuleMusique - - BorgModuleClowning - DawInstrumentMachineCircuitboard - MassMediaCircuitboard - JukeboxCircuitBoard @@ -82,7 +80,6 @@ tier: 1 cost: 5000 recipeUnlocks: - - BorgModuleLightReplacer - BorgModuleAdvancedCleaning - type: technology diff --git a/Resources/Prototypes/Research/industrial.yml b/Resources/Prototypes/Research/industrial.yml index e65c734ffdab..817e50834b70 100644 --- a/Resources/Prototypes/Research/industrial.yml +++ b/Resources/Prototypes/Research/industrial.yml @@ -12,8 +12,6 @@ recipeUnlocks: - MiningDrill - MineralScannerEmpty - - BorgModuleMining - - BorgModuleGrapplingGun - OreProcessorIndustrialMachineCircuitboard - ClothingMaskWeldingGas @@ -168,7 +166,6 @@ - PowerDrill - JawsOfLife - BorgModuleAdvancedTool - - BorgModuleRCD - type: technology id: MassExcavation diff --git a/Resources/Prototypes/Roles/Jobs/Science/borg.yml b/Resources/Prototypes/Roles/Jobs/Science/borg.yml index 4cbede17ca2d..c62482d286ee 100644 --- a/Resources/Prototypes/Roles/Jobs/Science/borg.yml +++ b/Resources/Prototypes/Roles/Jobs/Science/borg.yml @@ -25,5 +25,5 @@ canBeAntag: false icon: JobIconBorg supervisors: job-supervisors-rd - jobEntity: PlayerBorgGeneric + jobEntity: PlayerBorgBattery applyTraits: false diff --git a/Resources/Prototypes/borg_types.yml b/Resources/Prototypes/borg_types.yml new file mode 100644 index 000000000000..f6294be68e35 --- /dev/null +++ b/Resources/Prototypes/borg_types.yml @@ -0,0 +1,218 @@ +# Generic borg +- type: borgType + id: generic + + # Description + dummyPrototype: BorgChassisGeneric + + # Functional + extraModuleCount: 5 + moduleWhitelist: + tags: + - BorgModuleGeneric + + defaultModules: + - BorgModuleTool + + radioChannels: + - Science + + # Visual + inventoryTemplateId: borgShort + spriteBodyState: robot + spriteHasMindState: robot_e + spriteNoMindState: robot_e_r + spriteToggleLightState: robot_l + + # Pet + petSuccessString: petting-success-generic-cyborg + petFailureString: petting-failure-generic-cyborg + + +# Engineering borg +- type: borgType + id: engineering + + # Description + dummyPrototype: BorgChassisEngineer + + # Functional + extraModuleCount: 3 + moduleWhitelist: + tags: + - BorgModuleGeneric + - BorgModuleEngineering + + defaultModules: + - BorgModuleTool + - BorgModuleConstruction + - BorgModuleRCD + - BorgModuleCable + + radioChannels: + - Engineering + - Science + + # Visual + inventoryTemplateId: borgShort + spriteBodyState: engineer + spriteHasMindState: engineer_e + spriteNoMindState: engineer_e_r + spriteToggleLightState: engineer_l + + # Pet + petSuccessString: petting-success-engineer-cyborg + petFailureString: petting-failure-engineer-cyborg + + +# Salvage borg +- type: borgType + id: mining + + # Description + dummyPrototype: BorgChassisMining + + # Functional + extraModuleCount: 3 + moduleWhitelist: + tags: + - BorgModuleGeneric + - BorgModuleCargo + + defaultModules: + - BorgModuleGrapplingGun + - BorgModuleMining + - BorgModuleAppraisal + + radioChannels: + - Supply + - Science + + # Visual + inventoryTemplateId: borgTall + spriteBodyState: miner + spriteBodyMovementState: miner_moving + spriteHasMindState: miner_e + spriteNoMindState: miner_e_r + spriteToggleLightState: miner_l + + # Pet + petSuccessString: petting-success-salvage-cyborg + petFailureString: petting-failure-salvage-cyborg + + +# Janitor borg +- type: borgType + id: janitor + + # Description + dummyPrototype: BorgChassisJanitor + + # Functional + extraModuleCount: 3 + moduleWhitelist: + tags: + - BorgModuleGeneric + - BorgModuleJanitor + + defaultModules: + - BorgModuleLightReplacer + - BorgModuleCleaning + + radioChannels: + - Science + - Service + + # Visual + inventoryTemplateId: borgShort + spriteBodyState: janitor + spriteBodyMovementState: janitor_moving + spriteHasMindState: janitor_e + spriteNoMindState: janitor_e_r + spriteToggleLightState: janitor_l + + # Pet + petSuccessString: petting-success-janitor-cyborg + petFailureString: petting-failure-janitor-cyborg + + +# Medical borg +- type: borgType + id: medical + + # Description + dummyPrototype: BorgChassisMedical + + # Functional + extraModuleCount: 3 + moduleWhitelist: + tags: + - BorgModuleGeneric + - BorgModuleMedical + + defaultModules: + - BorgModuleTreatment + + radioChannels: + - Science + - Medical + + addComponents: + - type: SolutionScanner + - type: ShowHealthBars + damageContainers: + - Biological + - type: ShowHealthIcons + damageContainers: + - Biological + + # Visual + inventoryTemplateId: borgDutch + spriteBodyState: medical + spriteBodyMovementState: medical_moving + spriteHasMindState: medical_e + spriteNoMindState: medical_e_r + spriteToggleLightState: medical_l + + # Pet + petSuccessString: petting-success-medical-cyborg + petFailureString: petting-failure-medical-cyborg + + # Sounds + footstepCollection: + collection: FootstepHoverBorg + + +# Service borg +- type: borgType + id: service + + # Description + dummyPrototype: BorgChassisService + + # Functional + extraModuleCount: 3 + moduleWhitelist: + tags: + - BorgModuleGeneric + - BorgModuleService + + defaultModules: + - BorgModuleMusique + - BorgModuleService + - BorgModuleClowning + + radioChannels: + - Science + - Service + + # Visual + inventoryTemplateId: borgTall + spriteBodyState: service + spriteHasMindState: service_e + spriteNoMindState: service_e_r + spriteToggleLightState: service_l + + # Pet + petSuccessString: petting-success-service-cyborg + petFailureString: petting-failure-service-cyborg diff --git a/Resources/Prototypes/tags.yml b/Resources/Prototypes/tags.yml index be9c90ce93d8..6112f93c1648 100644 --- a/Resources/Prototypes/tags.yml +++ b/Resources/Prototypes/tags.yml @@ -75,95 +75,26 @@ - type: Tag id: BorgArm -- type: Tag - id: BorgEngineerHead - -- type: Tag - id: BorgEngineerLArm - -- type: Tag - id: BorgEngineerLLeg - -- type: Tag - id: BorgEngineerRArm - -- type: Tag - id: BorgEngineerRLeg - -- type: Tag - id: BorgEngineerTorso - -- type: Tag - id: BorgGenericHead - -- type: Tag - id: BorgGenericLArm - -- type: Tag - id: BorgGenericLLeg - -- type: Tag - id: BorgGenericRArm - -- type: Tag - id: BorgGenericRLeg - -- type: Tag - id: BorgGenericTorso - - type: Tag id: BorgHead - type: Tag - id: BorgJanitorHead - -- type: Tag - id: BorgJanitorLLeg - -- type: Tag - id: BorgJanitorRLeg - -- type: Tag - id: BorgJanitorTorso + id: BorgLArm - type: Tag - id: BorgLeg - -- type: Tag - id: BorgMedicalHead - -- type: Tag - id: BorgMedicalLArm - -- type: Tag - id: BorgMedicalLLeg - -- type: Tag - id: BorgMedicalRArm - -- type: Tag - id: BorgMedicalRLeg - -- type: Tag - id: BorgMedicalTorso - -- type: Tag - id: BorgMiningHead + id: BorgLLeg - type: Tag - id: BorgMiningLArm + id: BorgRArm - type: Tag - id: BorgMiningLLeg + id: BorgRLeg - type: Tag - id: BorgMiningRArm + id: BorgTorso - type: Tag - id: BorgMiningRLeg - -- type: Tag - id: BorgMiningTorso + id: BorgLeg - type: Tag id: BorgModuleCargo @@ -189,24 +120,6 @@ - type: Tag id: BorgModuleSyndicateAssault -- type: Tag - id: BorgServiceHead - -- type: Tag - id: BorgServiceLArm - -- type: Tag - id: BorgServiceLLeg - -- type: Tag - id: BorgServiceRArm - -- type: Tag - id: BorgServiceRLeg - -- type: Tag - id: BorgServiceTorso - - type: Tag id: Bot diff --git a/Resources/ServerInfo/Guidebook/Science/Cyborgs.xml b/Resources/ServerInfo/Guidebook/Science/Cyborgs.xml index 2b8defb07058..c1507ca53960 100644 --- a/Resources/ServerInfo/Guidebook/Science/Cyborgs.xml +++ b/Resources/ServerInfo/Guidebook/Science/Cyborgs.xml @@ -18,28 +18,28 @@ Both brains can be fabricated without requiring any additional research. - ## Chassis - While all cyborgs share the same endoskeleton, not all share the same chassis. The chassis determines what modules the cyborg can have, along with the [color=#a4885c]departmental radio channel[/color] they correspond to. By default, they will always have access to [color=#D381C9]Science[/color] and [color=green]station-wide[/color] frequencies, along with having [color=#a4885c]all-access[/color]. + ## Cyborg types + Once created, a cyborg needs to specialize its chassis to a duty on the station. This determines what modules it starts with, which additional modules can be installed, and what [color=#a4885c]departmental radio channel[/color] it has access to. All cyborgs have access to the [color=#D381C9]Science[/color] and [color=green]station-wide[/color] radio channels. All cyborg types have [color=#a4885c]all-access[/color]. - + - [italic]Examples of various cyborg chassis[/italic] + [italic]Examples of various cyborg types[/italic] - If you wish to change the chassis of an already existing cyborg, you have to construct a whole new one, limbs and frame included. The brain, power cell and modules [italic](if it can fit in the new chassis,)[/italic] can be carried over from the old chassis, if desired. + Once a cyborg chassis has been specialized, it cannot be changed. To change types, a new chassis must be constructed. The brain, power cell, and any modules [italic](if they are compatible with the new chassis)[/italic] can be carried over from the old chassis if desired. ## Modules - A cyborg isn't able to do much without [color=#a4885c]modules[/color]. These printed circuit boards are specific to cyborgs and grant additional functionality to them. They are printed at the [color=#a4885c]Exosuit Fabricator[/color]. + Cyborgs do not have hands, and therefore cannot pick things up like most other players. Instead, their equipment is provided by various [color=#a4885c]modules[/color]. Every cyborg type starts with its own specific set of modules, but additional modules can be inserted as upgrades. These additional modules can be printed at the [color=#a4885c]Exosuit Fabricator[/color]. - [color=#a4885c]Generic[/color] modules add versatility. They can be fitted into any chassis, granting useful tools such as crowbars, GPS, and the ability to interact with cables. [bold]The generic borg chassis can fit up to 6 modules in total.[/bold] + [color=#a4885c]Generic[/color] modules add versatility. They can be fitted into any chassis, granting useful tools such as crowbars, GPS, and the ability to interact with cables. [bold]The generic cyborg chassis can fit up to five additional modules.[/bold] @@ -49,7 +49,7 @@ [italic]Examples of generic modules[/italic] - For more specific needs, [color=#a4885c]specialized[/color] modules are available, granting capabilities like scanning anomalies, constructing walls, reviving crew mates, or cleaning a space lube spill. These modules are typically colored with the same palette as the department [italic](or occupation)[/italic] they relate to. These modules [italic](with exception to [color=#D381C9]science[/color] modules, which can fit any chassis,)[/italic] can only be fitted in their associated borg chassis. [bold]The specialized borg chassis, being the engineering, janitorial, service, medical, and mining chassis, can fit up to 4 modules.[/bold] + For more specific needs, [color=#a4885c]specialized[/color] modules are available, granting capabilities like scanning anomalies, constructing walls, reviving crew mates, or cleaning a space lube spill. These modules are typically colored with the same palette as the department [italic](or occupation)[/italic] they relate to. These modules [italic](with exception to [color=#D381C9]science[/color] modules, which can fit any chassis,)[/italic] can only be fitted in their associated borg chassis. [bold]The specialized borg chassis, being the engineering, janitorial, service, medical, and mining chassis, can fit up to three additional modules.[/bold] diff --git a/Resources/Textures/Interface/Actions/actions_borg.rsi/meta.json b/Resources/Textures/Interface/Actions/actions_borg.rsi/meta.json index dc8a6fcf9c6e..2ebb6eddcf50 100644 --- a/Resources/Textures/Interface/Actions/actions_borg.rsi/meta.json +++ b/Resources/Textures/Interface/Actions/actions_borg.rsi/meta.json @@ -48,7 +48,7 @@ }, { "name":"light-replacer-module" - }, + }, { "name":"cleaning-module" }, @@ -102,6 +102,9 @@ }, { "name":"syndicate-martyr-module" + }, + { + "name": "select-type" } ] } diff --git a/Resources/Textures/Interface/Actions/actions_borg.rsi/select-type.png b/Resources/Textures/Interface/Actions/actions_borg.rsi/select-type.png new file mode 100644 index 0000000000000000000000000000000000000000..766fd71abd0d865e7e4fe89a8137ebafc0c7e5ee GIT binary patch literal 408 zcmV;J0cZY+P)Px$Qb|NXR9J=WS22%+AQXO(nnJGeEyctxoo?;a|Nlpt4qeVfbRe<8$=rm82<>^1 z)4^}zJ%sP$6VOKh0J7}Vzyc`Cufs0OPK^-x68r!F&CZUbEZBdr3X!*_-3ySiU}>7d z@tC##VL#})ZV*#Se@$LhC6lsXM#R8@B-yu0sS&|kpp-(A>{|fnogN54#AxKUh`N@2 zJP;6b^|k;Tn*-}~;PJS9#2`PPKc9;_fQZZP0j1Pv4-6ti1Vrp(t#xoRt##jT+IH-N zJ3qi12RP@TwFb`lh}_M&u@93Sutm6VbG8E^Om@Ib99pg2_g4pAo&q1a$-AU(&iBmZ zQxIC!yZ0X&H`#%?vC4bE>%ir5eZ~^8eGNAU*6#qo_`iQ{@}L9v`;CPPlPRKJ6)II# zGD65$fDm~rWx?uNMlH_>A^y_Lh=@t<6$G$sdHxMyApx5dNM}g^0000bR8v literal 0 HcmV?d00001 diff --git a/Resources/migration.yml b/Resources/migration.yml index 3ed618dcfd70..8940df2b65e1 100644 --- a/Resources/migration.yml +++ b/Resources/migration.yml @@ -440,3 +440,38 @@ BlueprintFlare: null # 2024-10-04 BaseAdvancedPen: Pen + +# 2024-10-09 +# Removal of separate borg chassis parts, replace them with generic borg parts. +LeftArmBorgEngineer: LeftArmBorg +RightArmBorgEngineer: RightArmBorg +LeftLegBorgEngineer: LeftLegBorg +RightLegBorgEngineer: RightLegBorg +HeadBorgEngineer: LightHeadBorg +TorsoBorgEngineer: TorsoBorg + +LeftArmBorgMedical: LeftArmBorg +RightArmBorgMedical: RightArmBorg +LeftLegBorgMedical: LeftLegBorg +RightLegBorgMedical: RightLegBorg +HeadBorgMedical: LightHeadBorg +TorsoBorgMedical: TorsoBorg + +LeftArmBorgMining: LeftArmBorg +RightArmBorgMining: RightArmBorg +LeftLegBorgMining: LeftLegBorg +RightLegBorgMining: RightLegBorg +HeadBorgMining: LightHeadBorg +TorsoBorgMining: TorsoBorg + +LeftArmBorgService: LeftArmBorg +RightArmBorgService: RightArmBorg +LeftLegBorgService: LeftLegBorg +RightLegBorgService: RightLegBorg +HeadBorgService: LightHeadBorg +TorsoBorgService: TorsoBorg + +LeftLegBorgJanitor: LeftLegBorg +RightLegBorgJanitor: RightLegBorg +HeadBorgJanitor: LightHeadBorg +TorsoBorgJanitor: TorsoBorg From 0437ec6d56e764458ff0c9a74fbe4ed3e7280007 Mon Sep 17 00:00:00 2001 From: PJBot Date: Thu, 14 Nov 2024 17:09:42 +0000 Subject: [PATCH 098/290] Automatic changelog update --- Resources/Changelog/Changelog.yml | 32 +++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index eb3f72680084..ce0be691a4a4 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,18 +1,4 @@ Entries: -- author: TheShuEd - changes: - - message: added morbilliard variants of procedural tacos and kebabs - type: Add - - message: removed all microwave taco and kebabs recipes (except for the taco shell - itself) - type: Remove - - message: you can fight with a skewer (even if it has food on it) - type: Tweak - - message: now you can't put more than 10 layers on a burger. (20 before) - type: Tweak - id: 7109 - time: '2024-08-14T13:04:00.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/30905 - author: themias changes: - message: Fixed lizards being unable to eat custom burgers @@ -3941,3 +3927,21 @@ id: 7608 time: '2024-11-14T16:56:22.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33303 +- author: PJB3005 + changes: + - message: Borgs can now select their chassis type upon creation (construction or + job spawn), immediately giving borgs access to all chassis types. + type: Add + - message: Borg chassis types now come with built-in modules depending on the type, + so you can immediately do your job without help from science. Some upgrade modules + must still be installed later however. + type: Add + - message: Specialized chassis types have been removed from construction, as they + are no longer necessary. + type: Remove + - message: Borg unlock access is no longer determined by their chassis, it's always + science or command. This means the janitor can't unlock jani borgs anymore. + type: Remove + id: 7609 + time: '2024-11-14T17:08:35.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/32586 From 53ce8123569ac7132ddffe0a5c2a4e236e73d81a Mon Sep 17 00:00:00 2001 From: ScarKy0 Date: Thu, 14 Nov 2024 18:18:39 +0100 Subject: [PATCH 099/290] slash --- Content.Server/Silicons/Laws/IonStormSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Server/Silicons/Laws/IonStormSystem.cs b/Content.Server/Silicons/Laws/IonStormSystem.cs index f8bc8ca8c31a..7587dc415522 100644 --- a/Content.Server/Silicons/Laws/IonStormSystem.cs +++ b/Content.Server/Silicons/Laws/IonStormSystem.cs @@ -60,7 +60,7 @@ public sealed class IonStormSystem : EntitySystem private const string Foods = "IonStormFoods"; /// - //Randomly alters the laws of an individual silicon. + /// Randomly alters the laws of an individual silicon. /// public void IonStormTarget(Entity ent, bool adminlog = true) { From 9a5c49b961cd7376e2b9ea4ffcbad78661188149 Mon Sep 17 00:00:00 2001 From: ScarKy0 Date: Thu, 14 Nov 2024 18:31:50 +0100 Subject: [PATCH 100/290] epic empty commit --- Content.Server/Silicons/Laws/IonStormSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Server/Silicons/Laws/IonStormSystem.cs b/Content.Server/Silicons/Laws/IonStormSystem.cs index 7587dc415522..97ad2d8f9ef6 100644 --- a/Content.Server/Silicons/Laws/IonStormSystem.cs +++ b/Content.Server/Silicons/Laws/IonStormSystem.cs @@ -60,7 +60,7 @@ public sealed class IonStormSystem : EntitySystem private const string Foods = "IonStormFoods"; /// - /// Randomly alters the laws of an individual silicon. + /// Randomly alters the laws of an individual silicon. Epic test fail /// public void IonStormTarget(Entity ent, bool adminlog = true) { From 3b9365160c5bdb98899821f1f79a353fbcd4f6a3 Mon Sep 17 00:00:00 2001 From: ScarKy0 Date: Thu, 14 Nov 2024 18:32:02 +0100 Subject: [PATCH 101/290] or was it --- Content.Server/Silicons/Laws/IonStormSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Server/Silicons/Laws/IonStormSystem.cs b/Content.Server/Silicons/Laws/IonStormSystem.cs index 97ad2d8f9ef6..7587dc415522 100644 --- a/Content.Server/Silicons/Laws/IonStormSystem.cs +++ b/Content.Server/Silicons/Laws/IonStormSystem.cs @@ -60,7 +60,7 @@ public sealed class IonStormSystem : EntitySystem private const string Foods = "IonStormFoods"; /// - /// Randomly alters the laws of an individual silicon. Epic test fail + /// Randomly alters the laws of an individual silicon. /// public void IonStormTarget(Entity ent, bool adminlog = true) { From 2c9f2279d63d7515c1ce2c46054965902ebcd840 Mon Sep 17 00:00:00 2001 From: scrivoy <179060466+scrivoy@users.noreply.github.com> Date: Thu, 14 Nov 2024 22:30:16 +0100 Subject: [PATCH 102/290] Marathon Station: Added air alarms to CMO, Surgery, Security Checkpoint (#33213) * add air alarms to sec checkpoint, cmo and western surgery * decals and cleanup --- Resources/Maps/marathon.yml | 135 ++++++++++++++++++++++++++++++------ 1 file changed, 112 insertions(+), 23 deletions(-) diff --git a/Resources/Maps/marathon.yml b/Resources/Maps/marathon.yml index 002879379891..1f1632004b7e 100644 --- a/Resources/Maps/marathon.yml +++ b/Resources/Maps/marathon.yml @@ -586,7 +586,6 @@ entities: 2445: -41,19 2646: -33,-12 2665: -28,-14 - 2666: -23,-15 2667: -19,-23 2740: -20,-5 2794: 18,16 @@ -608,6 +607,7 @@ entities: 2979: -3,-48 3010: 12,14 3015: 2,-51 + 3114: -21,-15 - node: angle: 1.5707963267948966 rad color: '#FFFFFFFF' @@ -1039,11 +1039,11 @@ entities: color: '#52B4E996' id: BrickTileWhiteCornerNw decals: - 2536: -23,-15 2544: -15,-15 2602: -19,-19 2630: -31,-16 2673: -16,-9 + 3119: -23,-15 - node: color: '#DE3A3A96' id: BrickTileWhiteCornerNw @@ -1068,8 +1068,8 @@ entities: color: '#FFFFFFFF' id: BrickTileWhiteCornerNw decals: - 2533: -23,-15 2573: -19,-19 + 3118: -23,-15 - node: color: '#52B4E996' id: BrickTileWhiteCornerSe @@ -4510,9 +4510,9 @@ entities: color: '#52B4E996' id: WarnLineGreyscaleN decals: - 2537: -22,-15 2605: -14,-19 2608: -14,-15 + 3115: -22,-15 - node: color: '#D381C996' id: WarnLineGreyscaleN @@ -7544,6 +7544,16 @@ entities: parent: 30 - proto: AirAlarm entities: + - uid: 3167 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -23.5,-15.5 + parent: 30 + - type: DeviceList + devices: + - 9046 + - 9049 - uid: 6224 components: - type: Transform @@ -7765,6 +7775,27 @@ entities: - 18435 - 18436 - 18437 + - uid: 18082 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -38.5,8.5 + parent: 30 + - type: DeviceList + devices: + - 3077 + - 3076 + - uid: 19145 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -35.5,-18.5 + parent: 30 + - type: DeviceList + devices: + - 6935 + - 6920 + - 22554 - uid: 19570 components: - type: Transform @@ -8808,6 +8839,26 @@ entities: - 22084 - 3484 - 3481 + - uid: 22553 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -23.5,-23.5 + parent: 30 + - type: DeviceList + devices: + - 6834 + - 9713 + - uid: 22555 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: -31.5,-22.5 + parent: 30 + - type: DeviceList + devices: + - 7115 + - 7119 - proto: AirAlarmElectronics entities: - uid: 15214 @@ -11906,6 +11957,14 @@ entities: - type: Transform pos: -2.5,8.5 parent: 30 + - uid: 22554 + components: + - type: Transform + pos: -34.5,-23.5 + parent: 30 + - type: DeviceNetwork + deviceLists: + - 19145 - proto: AltarConvertRed entities: - uid: 17468 @@ -54920,11 +54979,11 @@ entities: parent: 30 - proto: DefibrillatorCabinetFilled entities: - - uid: 3167 + - uid: 6956 components: - type: Transform rot: 1.5707963267948966 rad - pos: -23.5,-15.5 + pos: -23.5,-14.5 parent: 30 - uid: 6970 components: @@ -55583,6 +55642,12 @@ entities: - type: Transform pos: -19.5,-5.5 parent: 30 + - uid: 6953 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -21.5,-14.5 + parent: 30 - uid: 7412 components: - type: Transform @@ -55677,12 +55742,6 @@ entities: rot: 1.5707963267948966 rad pos: -19.5,-9.5 parent: 30 - - uid: 7354 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: -21.5,-14.5 - parent: 30 - uid: 12233 components: - type: Transform @@ -59804,12 +59863,6 @@ entities: rot: 3.141592653589793 rad pos: -18.5,-22.5 parent: 30 - - uid: 6956 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -22.5,-14.5 - parent: 30 - uid: 6962 components: - type: Transform @@ -59821,6 +59874,12 @@ entities: - type: Transform pos: -19.5,-4.5 parent: 30 + - uid: 7354 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -20.5,-14.5 + parent: 30 - uid: 9753 components: - type: Transform @@ -60216,11 +60275,6 @@ entities: - type: Transform pos: -19.5,-4.5 parent: 30 - - uid: 6953 - components: - - type: Transform - pos: -22.5,-14.5 - parent: 30 - uid: 6954 components: - type: Transform @@ -60296,6 +60350,11 @@ entities: - type: Transform pos: 14.5,-17.5 parent: 30 + - uid: 19150 + components: + - type: Transform + pos: -20.5,-14.5 + parent: 30 - uid: 19407 components: - type: Transform @@ -86755,6 +86814,9 @@ entities: - type: Transform pos: -40.5,10.5 parent: 30 + - type: DeviceNetwork + deviceLists: + - 18082 - type: AtmosPipeColor color: '#0000FFFF' - uid: 3099 @@ -87044,6 +87106,9 @@ entities: rot: 3.141592653589793 rad pos: -25.5,-22.5 parent: 30 + - type: DeviceNetwork + deviceLists: + - 22553 - type: AtmosPipeColor color: '#0000FFFF' - uid: 6900 @@ -87060,6 +87125,9 @@ entities: rot: 1.5707963267948966 rad pos: -33.5,-16.5 parent: 30 + - type: DeviceNetwork + deviceLists: + - 19145 - type: AtmosPipeColor color: '#0000FFFF' - uid: 6939 @@ -87086,6 +87154,9 @@ entities: - type: Transform pos: -28.5,-20.5 parent: 30 + - type: DeviceNetwork + deviceLists: + - 22555 - type: AtmosPipeColor color: '#0000FFFF' - uid: 7136 @@ -87232,6 +87303,9 @@ entities: - type: Transform pos: -25.5,-15.5 parent: 30 + - type: DeviceNetwork + deviceLists: + - 3167 - type: AtmosPipeColor color: '#0000FFFF' - uid: 9686 @@ -88266,6 +88340,9 @@ entities: rot: 1.5707963267948966 rad pos: -39.5,10.5 parent: 30 + - type: DeviceNetwork + deviceLists: + - 18082 - type: AtmosPipeColor color: '#FF0000FF' - uid: 3100 @@ -88548,6 +88625,9 @@ entities: rot: 1.5707963267948966 rad pos: -33.5,-18.5 parent: 30 + - type: DeviceNetwork + deviceLists: + - 19145 - type: AtmosPipeColor color: '#FF0000FF' - uid: 7098 @@ -88577,6 +88657,9 @@ entities: rot: 3.141592653589793 rad pos: -28.5,-18.5 parent: 30 + - type: DeviceNetwork + deviceLists: + - 22555 - type: AtmosPipeColor color: '#FF0000FF' - uid: 7130 @@ -88714,6 +88797,9 @@ entities: - type: Transform pos: -25.5,-16.5 parent: 30 + - type: DeviceNetwork + deviceLists: + - 3167 - type: AtmosPipeColor color: '#FF0000FF' - uid: 9713 @@ -88722,6 +88808,9 @@ entities: rot: 3.141592653589793 rad pos: -25.5,-23.5 parent: 30 + - type: DeviceNetwork + deviceLists: + - 22553 - type: AtmosPipeColor color: '#FF0000FF' - uid: 9793 From d205d17ba3d0bee79752915e6e57e7f2f539e0ec Mon Sep 17 00:00:00 2001 From: scrivoy <179060466+scrivoy@users.noreply.github.com> Date: Fri, 15 Nov 2024 02:04:14 +0100 Subject: [PATCH 103/290] Meta Station: Add a fully functional TEG room (#32941) * initial commit * delete WIP-marker.md * add TEG room, move gas chambers up * remove outside burn chamber button, add naming to APC, SMES, Substation * add HV below TEG Substation * removed invalids --- Resources/Maps/meta.yml | 5813 +++++++++++++++++++++++++++++---------- 1 file changed, 4385 insertions(+), 1428 deletions(-) diff --git a/Resources/Maps/meta.yml b/Resources/Maps/meta.yml index 93a6bc31c42e..be14ee8855a0 100644 --- a/Resources/Maps/meta.yml +++ b/Resources/Maps/meta.yml @@ -284,15 +284,15 @@ entities: version: 6 4,-1: ind: 4,-1 - tiles: eQAAAAAAeAAAAAAAeQAAAAAATQAAAAAATQAAAAAATQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeQAAAAAATQAAAAAATQAAAAAATQAAAAAAeQAAAAAAeQAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeQAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeQAAAAAATQAAAAAATQAAAAAATQAAAAAAeQAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAeQAAAAAAeAAAAAAAeQAAAAAATQAAAAAATQAAAAAATQAAAAAAeQAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeAAAAAAAeQAAAAAATQAAAAAATQAAAAAATQAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeAAAAAAAeQAAAAAATQAAAAAATQAAAAAATQAAAAAAeQAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeAAAAAAAeQAAAAAATQAAAAAATQAAAAAATQAAAAAAeQAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeAAAAAAAeQAAAAAATQAAAAAATQAAAAAATQAAAAAAeQAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAA + tiles: eQAAAAAAeAAAAAAAeQAAAAAATQAAAAAATQAAAAAATQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeQAAAAAATQAAAAAATQAAAAAATQAAAAAAeQAAAAAAeQAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeQAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeQAAAAAATQAAAAAATQAAAAAATQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAeQAAAAAAeAAAAAAAeQAAAAAATQAAAAAATQAAAAAATQAAAAAAeQAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeAAAAAAAeQAAAAAATQAAAAAATQAAAAAATQAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeAAAAAAAeQAAAAAATQAAAAAATQAAAAAATQAAAAAAeQAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeAAAAAAAeQAAAAAATQAAAAAATQAAAAAATQAAAAAAeQAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeAAAAAAAeQAAAAAATQAAAAAATQAAAAAATQAAAAAAeQAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeAAAAAAAeQAAAAAATQAAAAAATQAAAAAATQAAAAAAeQAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAA version: 6 4,-2: ind: 4,-2 - tiles: eAAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAAAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAeQAAAAAAeQAAAAAATQAAAAAAeQAAAAAAeQAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeAAAAAAAeQAAAAAATQAAAAAATQAAAAAATQAAAAAAeQAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeAAAAAAAeQAAAAAATQAAAAAATQAAAAAATQAAAAAAeQAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeAAAAAAAeQAAAAAATQAAAAAATQAAAAAATQAAAAAAeQAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAeQAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeQAAAAAATQAAAAAATQAAAAAATQAAAAAAeQAAAAAAeQAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeQAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeQAAAAAA + tiles: eAAAAAAAeQAAAAAAHQAAAAAAHQAAAAAAYAAAAAAAWQAAAAAAWQAAAAAAWQAAAAAAWQAAAAAAWQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAHQAAAAAAHQAAAAAAWQAAAAAAWQAAAAAAYAAAAAAAYAAAAAAAYAAAAAAAWQAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAHQAAAAAAHQAAAAAAWQAAAAAAWQAAAAAAWQAAAAAAWQAAAAAAYAAAAAAAWQAAAAAAeQAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAHQAAAAAAHQAAAAAAeQAAAAAAeQAAAAAAaAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAHQAAAAAAHQAAAAAAeQAAAAAAaAAAAAAAaAAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAHQAAAAAAHQAAAAAAaAAAAAAAaAAAAAAAaAAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAHQAAAAAAHQAAAAAAeQAAAAAAaAAAAAAAaAAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAHQAAAAAAHQAAAAAAHQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAHQAAAAAAHQAAAAAAHQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeAAAAAAAeQAAAAAATQAAAAAATQAAAAAATQAAAAAAeQAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeAAAAAAAeQAAAAAATQAAAAAATQAAAAAATQAAAAAAeQAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAeQAAAAAAeAAAAAAAeQAAAAAATQAAAAAATQAAAAAATQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeQAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeQAAAAAA version: 6 3,-3: ind: 3,-3 - tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAATQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAA + tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAATQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAA version: 6 5,0: ind: 5,0 @@ -300,7 +300,7 @@ entities: version: 6 4,-3: ind: 4,-3 - tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAAAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAAAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAAAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAAAAAAAAAAAAAAAAA + tiles: eAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAaAAAAAAAaAAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAaAAAAAAAaAAAAAAAeQAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAaAAAAAAAaAAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAaAAAAAAAaAAAAAAAeQAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAaAAAAAAAaAAAAAAAeQAAAAAAeAAAAAAAeAAAAAAA version: 6 2,-3: ind: 2,-3 @@ -448,7 +448,23 @@ entities: version: 6 5,-2: ind: 5,-2 - tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAA + tiles: eAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAeQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAA + version: 6 + 5,-3: + ind: 5,-3 + tiles: eAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + version: 6 + 3,-4: + ind: 3,-4 + tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAA + version: 6 + 4,-4: + ind: 4,-4 + tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAA + version: 6 + 5,-4: + ind: 5,-4 + tiles: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAeAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA version: 6 - type: Broadphase - type: Physics @@ -708,6 +724,12 @@ entities: 3190: 64,26 3191: 64,14 3192: 76,14 + 3529: 76,-33 + 3530: 76,-34 + 3531: 76,-35 + 3532: 76,-36 + 3533: 76,-37 + 3566: 70,-39 - node: color: '#FFFFFFFF' id: BoxGreyscale @@ -980,6 +1002,11 @@ entities: id: BrickTileWhiteCornerSe decals: 3099: 6,-26 + - node: + color: '#3EB38896' + id: BrickTileWhiteCornerSw + decals: + 3569: 66,-32 - node: color: '#52B4E996' id: BrickTileWhiteCornerSw @@ -1008,6 +1035,11 @@ entities: id: BrickTileWhiteEndN decals: 2748: -26,-26 + - node: + color: '#3EB38896' + id: BrickTileWhiteInnerNe + decals: + 3594: 67,-30 - node: color: '#D381C996' id: BrickTileWhiteInnerNe @@ -1051,6 +1083,13 @@ entities: decals: 2544: 20,-30 2567: 14,-43 + - node: + color: '#3EB38896' + id: BrickTileWhiteLineE + decals: + 3574: 67,-28 + 3575: 67,-29 + 3609: 67,-25 - node: color: '#52B4E996' id: BrickTileWhiteLineE @@ -1135,6 +1174,16 @@ entities: 3236: 60,21 3237: 60,20 3238: 60,19 + - node: + color: '#3EB38896' + id: BrickTileWhiteLineN + decals: + 3589: 72,-30 + 3590: 71,-30 + 3591: 70,-30 + 3592: 69,-30 + 3612: 73,-30 + 3613: 68,-30 - node: color: '#52B4E996' id: BrickTileWhiteLineN @@ -1197,6 +1246,17 @@ entities: 3102: 3,-25 3103: 4,-25 3104: 5,-25 + - node: + color: '#3EB38896' + id: BrickTileWhiteLineS + decals: + 3583: 67,-32 + 3584: 68,-32 + 3585: 69,-32 + 3586: 70,-32 + 3587: 71,-32 + 3588: 72,-32 + 3611: 73,-32 - node: color: '#52B4E996' id: BrickTileWhiteLineS @@ -1259,6 +1319,15 @@ entities: id: BrickTileWhiteLineW decals: 2495: 104,-14 + - node: + color: '#3EB38896' + id: BrickTileWhiteLineW + decals: + 3578: 66,-27 + 3579: 66,-28 + 3580: 66,-29 + 3581: 66,-30 + 3582: 66,-31 - node: color: '#52B4E996' id: BrickTileWhiteLineW @@ -4651,6 +4720,7 @@ entities: 3109: 28,-63 3250: 56,17 3251: 56,23 + 3608: 66.50142,-31.75576 - node: color: '#334E6DC8' id: ThreeQuarterTileOverlayGreyscale @@ -4934,6 +5004,11 @@ entities: id: WarnBox decals: 2504: -64,-14 + - node: + color: '#FFFFFFFF' + id: WarnCornerNE + decals: + 3544: 74,-33 - node: color: '#FFFFFFFF' id: WarnCornerSE @@ -4951,6 +5026,7 @@ entities: 900: -13,10 1625: 0,-29 3276: 42,15 + 3557: 74,-38 - node: color: '#FFFFFFFF' id: WarnCornerSmallNW @@ -5042,6 +5118,17 @@ entities: 3269: 42,16 3270: 42,17 3271: 42,18 + 3540: 74,-37 + 3542: 74,-35 + 3543: 74,-34 + 3558: 74,-36 + 3617: 67,-26 + - node: + color: '#3EB38896' + id: WarnLineGreyscaleE + decals: + 3598: 67,-27 + 3610: 67,-24 - node: color: '#52B4E996' id: WarnLineGreyscaleE @@ -5160,6 +5247,12 @@ entities: 1694: 12,-41 1695: 11,-41 1696: 10,-41 + - node: + color: '#3EB38896' + id: WarnLineGreyscaleW + decals: + 3595: 66,-25 + 3607: 66,-24 - node: color: '#52B4E996' id: WarnLineGreyscaleW @@ -5315,6 +5408,7 @@ entities: 3516: 33,6 3517: 33,7 3518: 33,8 + 3616: 66,-26 - node: color: '#DE3A3A96' id: WarnLineW @@ -5381,6 +5475,16 @@ entities: 3178: -3,-39 3179: -4,-39 3255: 43,15 + 3545: 73,-33 + 3546: 72,-33 + 3547: 71,-33 + 3548: 70,-33 + 3549: 69,-33 + 3555: 75,-38 + 3556: 76,-38 + 3562: 66,-33 + 3563: 67,-33 + 3564: 68,-33 - node: angle: -3.141592653589793 rad color: '#FFFFFFFF' @@ -6511,11 +6615,14 @@ entities: 15,-4: 0: 65535 16,-8: - 1: 58115 - 0: 236 + 1: 4369 + 0: 52428 16,-7: - 1: 242 - 0: 61440 + 1: 17 + 0: 64716 + 16,-6: + 0: 15 + 1: 11776 13,-3: 0: 62719 13,-2: @@ -6542,7 +6649,7 @@ entities: 0: 119 16,-1: 0: 240 - 1: 13058 + 1: 62222 12,1: 0: 58606 12,2: @@ -6576,7 +6683,7 @@ entities: 0: 4354 1: 34952 16,0: - 1: 127 + 1: 255 0: 3840 16,1: 0: 54272 @@ -6849,19 +6956,21 @@ entities: -5,14: 1: 17652 -4,15: - 1: 15 + 1: 9999 -5,15: 1: 12 + -4,16: + 1: 14 -3,13: 0: 65521 -3,14: 0: 33023 1: 4096 -3,15: - 1: 25123 + 1: 25091 0: 136 -3,16: - 1: 196 + 1: 243 -2,13: 0: 65521 -2,14: @@ -6875,15 +6984,17 @@ entities: 0: 16435 1: 10240 -1,15: - 1: 12834 + 1: 14862 -1,16: - 1: 17 + 1: 54 0,13: 0: 51 1: 45056 0,14: 1: 2816 0: 16384 + 0,15: + 1: 288 -9,12: 1: 36761 -8,13: @@ -7103,22 +7214,22 @@ entities: 12,12: 1: 61441 17,0: - 1: 15 + 1: 223 0: 57376 17,2: 0: 65295 17,3: 0: 15 1: 20288 - 17,1: - 0: 61166 17,-1: + 1: 53389 0: 11826 - 1: 136 + 17,1: + 0: 61166 17,4: 1: 17487 18,0: - 1: 15 + 1: 255 0: 61440 18,1: 0: 65535 @@ -7127,8 +7238,11 @@ entities: 18,3: 0: 15 1: 3840 + 18,-1: + 1: 61610 + 0: 3840 19,0: - 1: 31 + 1: 255 0: 7168 19,1: 0: 4369 @@ -7139,19 +7253,19 @@ entities: 0: 1011 1: 8192 19,-1: - 1: 4130 + 1: 61474 0: 3840 19,4: 1: 8738 0: 51328 20,0: - 1: 143 + 1: 255 0: 3840 20,2: 1: 7951 20,3: - 1: 341 - 0: 46080 + 1: 261 + 0: 46320 -11,9: 0: 34827 1: 12800 @@ -7309,105 +7423,98 @@ entities: 1: 257 16,-4: 1: 8738 - 5: 136 - 6: 32768 + 5: 2184 16,-3: 1: 8738 - 6: 32904 + 6: 2184 16,-2: - 1: 57890 - 6: 136 + 1: 8738 + 6: 2184 16,-5: 1: 8738 - 5: 32768 - 6: 136 + 6: 2184 17,-4: - 5: 51 - 6: 12288 - 0: 128 - 1: 34816 + 5: 819 + 0: 2176 + 1: 32768 17,-3: - 6: 12339 + 6: 819 1: 34952 17,-2: - 6: 51 - 1: 55432 - 0: 8192 + 6: 819 + 1: 34952 17,-5: - 5: 12288 - 0: 32768 - 6: 51 - 1: 2184 + 0: 34816 + 6: 819 + 1: 136 18,-4: - 0: 135 - 1: 43552 + 0: 3975 + 1: 40992 18,-3: 1: 43770 - 18,-1: - 0: 3840 - 1: 170 18,-5: - 1: 12202 - 0: 32768 + 1: 8362 + 0: 36608 18,-2: 1: 43690 19,-4: - 0: 135 - 1: 43552 + 0: 3975 + 1: 40992 19,-3: 1: 57906 19,-5: - 1: 11170 - 0: 32768 + 1: 8354 + 0: 36608 19,-2: 1: 8930 20,-4: - 0: 135 - 1: 34816 + 0: 3975 + 1: 32768 20,-3: 1: 61440 20,-2: 1: 240 20,-1: 0: 3840 - 1: 32768 - 16,-6: - 1: 8928 - 6: 32768 + 1: 61440 16,-9: - 0: 61166 - 1: 1 + 1: 4369 + 0: 52428 17,-8: - 0: 31487 - 1: 32768 + 0: 4095 17,-7: - 1: 3536 - 0: 61991 + 0: 1654 17,-6: - 1: 35037 - 6: 12288 - 0: 34 + 0: 15 + 1: 36608 17,-9: 0: 65535 18,-8: - 0: 153 - 1: 12898 + 0: 819 + 1: 34944 18,-7: - 1: 47858 + 1: 48127 18,-6: - 1: 43770 + 1: 43771 18,-9: - 0: 48027 - 1: 96 + 0: 65535 19,-8: - 0: 51 + 1: 64248 19,-7: - 1: 8448 + 1: 8696 0: 512 19,-6: 1: 8754 19,-9: - 0: 13107 + 0: 4369 + 1: 52424 + 20,-8: + 1: 30039 + 20,-7: + 1: 117 + 20,-5: + 0: 36608 + 1: 128 12,-10: 1: 61696 11,-10: @@ -7417,25 +7524,42 @@ entities: 14,-10: 1: 64000 15,-10: - 1: 61952 + 1: 65503 + 15,-12: + 1: 57311 + 15,-13: + 1: 40704 + 15,-11: + 1: 56829 + 16,-12: + 1: 65023 + 16,-11: + 1: 4353 + 6: 52416 + 16,-10: + 1: 4353 + 0: 52416 20,4: - 1: 5457 - 0: 4 + 1: 5377 + 0: 244 21,0: - 1: 32783 + 1: 33023 0: 3840 21,2: 1: 3887 21,3: - 0: 46080 - 1: 68 + 0: 46320 + 1: 4 + 21,-1: + 1: 61440 + 0: 3840 21,1: 1: 17608 21,4: - 0: 4 - 1: 1088 + 0: 244 + 1: 1024 22,0: - 1: 2151 + 1: 2167 0: 58248 22,1: 1: 3634 @@ -7443,13 +7567,13 @@ entities: 22,2: 1: 3855 22,3: - 0: 46080 - 1: 68 + 0: 46320 + 1: 4 22,-1: - 1: 24608 + 1: 28704 0: 36608 22,4: - 0: 4 + 0: 180 1: 1088 23,0: 0: 25855 @@ -7461,13 +7585,14 @@ entities: 1: 26471 0: 34952 23,3: - 0: 61576 - 1: 3686 + 0: 61688 + 1: 3590 23,-1: 0: 63044 1: 2235 23,4: - 1: 19660 + 1: 19468 + 0: 240 24,0: 0: 3295 1: 256 @@ -7478,12 +7603,44 @@ entities: 24,3: 1: 609 0: 63760 - 16,-10: - 0: 60608 + 16,-13: + 1: 12032 + 17,-12: + 1: 65023 + 17,-11: + 6: 13104 + 1: 34952 17,-10: 0: 65520 + 17,-13: + 1: 12032 + 18,-12: + 1: 64767 + 18,-11: + 1: 30591 + 0: 2048 18,-10: - 0: 13072 + 0: 65520 + 18,-13: + 1: 40704 + 19,-12: + 1: 64255 + 19,-11: + 1: 35983 + 0: 4352 + 19,-10: + 0: 4369 + 1: 52428 + 19,-13: + 1: 36608 + 20,-12: + 1: 22357 + 20,-11: + 1: 21847 + 20,-10: + 1: 30039 + 20,-9: + 1: 21877 8,-13: 0: 6004 9,-12: @@ -8143,37 +8300,33 @@ entities: 1: 13056 7,-19: 1: 34952 - 20,-5: - 0: 32768 - 1: 2176 21,-4: - 0: 135 - 1: 34816 + 0: 3975 + 1: 32768 21,-3: 1: 61440 21,-2: 1: 240 - 21,-1: - 0: 3840 21,-5: - 0: 32768 - 1: 2176 + 0: 36608 + 1: 128 22,-4: - 0: 15 + 0: 3855 22,-3: 1: 61440 22,-2: 1: 240 23,-4: - 0: 15 - 1: 52416 + 0: 3855 + 1: 49344 23,-3: 1: 64716 23,-2: 1: 15868 0: 49152 23,-5: - 1: 52420 + 1: 49348 + 0: 3840 24,-4: 0: 4511 1: 8736 @@ -8328,6 +8481,10 @@ entities: 26,-6: 1: 34800 0: 28672 + 22,-5: + 0: 3840 + 20,-13: + 1: 22272 uniqueMixes: - volume: 2500 temperature: 293.15 @@ -8497,6 +8654,18 @@ entities: parent: 5350 - proto: AirAlarm entities: + - uid: 11752 + components: + - type: Transform + pos: 71.5,-28.5 + parent: 5350 + - type: DeviceList + devices: + - 27078 + - 27210 + - 27212 + - 26995 + - 26996 - uid: 14304 components: - type: Transform @@ -9460,7 +9629,7 @@ entities: parent: 5350 - type: DeviceList devices: - - 24516 + - 10990 - uid: 24517 components: - type: Transform @@ -9960,6 +10129,15 @@ entities: - 19501 - 19500 - 19499 + - uid: 27108 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 70.5,-39.5 + parent: 5350 + - type: DeviceList + devices: + - 27127 - proto: AirCanister entities: - uid: 2431 @@ -10175,11 +10353,22 @@ entities: - type: Transform pos: 56.5,-7.5 parent: 5350 - - uid: 11498 + - uid: 10820 components: - type: Transform - pos: 69.5,-29.5 + pos: 65.5,-24.5 + parent: 5350 + - type: AccessReader + access: + - - Atmospherics + - uid: 10821 + components: + - type: Transform + pos: 65.5,-23.5 parent: 5350 + - type: AccessReader + access: + - - Atmospherics - proto: AirlockAtmosphericsLocked entities: - uid: 9008 @@ -10706,6 +10895,14 @@ entities: - type: Transform pos: 38.5,-57.5 parent: 5350 + - uid: 26788 + components: + - type: Transform + pos: 68.5,-26.5 + parent: 5350 + - type: AccessReader + access: + - - Engineering - proto: AirlockExternal entities: - uid: 16847 @@ -10713,6 +10910,31 @@ entities: - type: Transform pos: -62.5,-40.5 parent: 5350 +- proto: AirlockExternalAtmosphericsLocked + entities: + - uid: 11254 + components: + - type: Transform + pos: 75.5,-41.5 + parent: 5350 + - type: DeviceLinkSink + invokeCounter: 1 + - type: DeviceLinkSource + linkedPorts: + 11257: + - DoorStatus: DoorBolt + - uid: 27016 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 71.5,-23.5 + parent: 5350 + - type: DeviceLinkSink + invokeCounter: 1 + - type: DeviceLinkSource + linkedPorts: + 27248: + - DoorStatus: DoorBolt - proto: AirlockExternalEngineeringLocked entities: - uid: 12540 @@ -10823,16 +11045,29 @@ entities: parent: 5350 - proto: AirlockExternalGlassAtmosphericsLocked entities: - - uid: 11284 + - uid: 11257 components: - type: Transform - pos: 64.5,-24.5 + pos: 76.5,-39.5 parent: 5350 - - uid: 11285 + - type: DeviceLinkSink + invokeCounter: 1 + - type: DeviceLinkSource + linkedPorts: + 11254: + - DoorStatus: DoorBolt + - uid: 27248 components: - type: Transform - pos: 67.5,-24.5 + rot: -1.5707963267948966 rad + pos: 68.5,-23.5 parent: 5350 + - type: DeviceLinkSink + invokeCounter: 1 + - type: DeviceLinkSource + linkedPorts: + 27016: + - DoorStatus: DoorBolt - proto: AirlockExternalGlassCargoLocked entities: - uid: 3441 @@ -10880,7 +11115,7 @@ entities: pos: -42.5,29.5 parent: 5350 - type: Door - secondsUntilStateChange: -5834.8745 + secondsUntilStateChange: -25306.475 state: Opening - type: DeviceLinkSink invokeCounter: 2 @@ -12829,6 +13064,14 @@ entities: parent: 5350 - proto: AirSensor entities: + - uid: 10990 + components: + - type: Transform + pos: 68.5,-6.5 + parent: 5350 + - type: DeviceNetwork + deviceLists: + - 24515 - uid: 14424 components: - type: Transform @@ -13213,11 +13456,6 @@ entities: - type: Transform pos: 53.5,-18.5 parent: 5350 - - uid: 24516 - components: - - type: Transform - pos: 68.5,-7.5 - parent: 5350 - uid: 24521 components: - type: Transform @@ -13423,6 +13661,23 @@ entities: - type: Transform pos: -11.5,-32.5 parent: 5350 + - uid: 27078 + components: + - type: Transform + pos: 70.5,-32.5 + parent: 5350 + - type: DeviceNetwork + deviceLists: + - 11752 + - 26994 + - uid: 27127 + components: + - type: Transform + pos: 68.5,-41.5 + parent: 5350 + - type: DeviceNetwork + deviceLists: + - 27108 - proto: AltarConvertMaint entities: - uid: 22866 @@ -13680,6 +13935,13 @@ entities: - type: Transform pos: -34.5,32.5 parent: 5350 + - uid: 10831 + components: + - type: MetaData + name: TEG APC + - type: Transform + pos: 69.5,-28.5 + parent: 5350 - uid: 11513 components: - type: MetaData @@ -14179,10 +14441,40 @@ entities: parent: 5350 - proto: AtmosFixBlockerMarker entities: - - uid: 11609 + - uid: 10913 components: - type: Transform - pos: 67.5,-20.5 + pos: 67.5,-17.5 + parent: 5350 + - uid: 11200 + components: + - type: Transform + pos: 67.5,-5.5 + parent: 5350 + - uid: 11307 + components: + - type: Transform + pos: 68.5,-5.5 + parent: 5350 + - uid: 11308 + components: + - type: Transform + pos: 69.5,-5.5 + parent: 5350 + - uid: 11345 + components: + - type: Transform + pos: 68.5,-17.5 + parent: 5350 + - uid: 11347 + components: + - type: Transform + pos: 69.5,-11.5 + parent: 5350 + - uid: 11598 + components: + - type: Transform + pos: 69.5,-17.5 parent: 5350 - uid: 11610 components: @@ -14194,11 +14486,6 @@ entities: - type: Transform pos: 67.5,-18.5 parent: 5350 - - uid: 11612 - components: - - type: Transform - pos: 68.5,-20.5 - parent: 5350 - uid: 11613 components: - type: Transform @@ -14209,11 +14496,6 @@ entities: - type: Transform pos: 68.5,-18.5 parent: 5350 - - uid: 11615 - components: - - type: Transform - pos: 69.5,-20.5 - parent: 5350 - uid: 11616 components: - type: Transform @@ -14224,31 +14506,16 @@ entities: - type: Transform pos: 69.5,-18.5 parent: 5350 - - uid: 11618 - components: - - type: Transform - pos: 67.5,-8.5 - parent: 5350 - uid: 11619 components: - type: Transform pos: 67.5,-7.5 parent: 5350 - - uid: 11620 - components: - - type: Transform - pos: 68.5,-8.5 - parent: 5350 - uid: 11621 components: - type: Transform pos: 68.5,-7.5 parent: 5350 - - uid: 11622 - components: - - type: Transform - pos: 69.5,-8.5 - parent: 5350 - uid: 11623 components: - type: Transform @@ -14269,11 +14536,6 @@ entities: - type: Transform pos: 67.5,-6.5 parent: 5350 - - uid: 11628 - components: - - type: Transform - pos: 67.5,-12.5 - parent: 5350 - uid: 11629 components: - type: Transform @@ -14287,7 +14549,7 @@ entities: - uid: 11631 components: - type: Transform - pos: 68.5,-12.5 + pos: 67.5,-9.5 parent: 5350 - uid: 11632 components: @@ -14299,20 +14561,20 @@ entities: - type: Transform pos: 68.5,-10.5 parent: 5350 - - uid: 11634 + - uid: 11636 components: - type: Transform - pos: 69.5,-12.5 + pos: 69.5,-10.5 parent: 5350 - - uid: 11635 + - uid: 11720 components: - type: Transform - pos: 69.5,-11.5 + pos: 68.5,-9.5 parent: 5350 - - uid: 11636 + - uid: 11722 components: - type: Transform - pos: 69.5,-10.5 + pos: 69.5,-9.5 parent: 5350 - uid: 24185 components: @@ -14359,6 +14621,66 @@ entities: - type: Transform pos: 15.5,-55.5 parent: 5350 + - uid: 27423 + components: + - type: Transform + pos: 66.5,-40.5 + parent: 5350 + - uid: 27424 + components: + - type: Transform + pos: 67.5,-40.5 + parent: 5350 + - uid: 27425 + components: + - type: Transform + pos: 68.5,-40.5 + parent: 5350 + - uid: 27426 + components: + - type: Transform + pos: 69.5,-40.5 + parent: 5350 + - uid: 27427 + components: + - type: Transform + pos: 66.5,-41.5 + parent: 5350 + - uid: 27428 + components: + - type: Transform + pos: 66.5,-42.5 + parent: 5350 + - uid: 27429 + components: + - type: Transform + pos: 67.5,-41.5 + parent: 5350 + - uid: 27430 + components: + - type: Transform + pos: 67.5,-42.5 + parent: 5350 + - uid: 27431 + components: + - type: Transform + pos: 68.5,-42.5 + parent: 5350 + - uid: 27432 + components: + - type: Transform + pos: 68.5,-41.5 + parent: 5350 + - uid: 27433 + components: + - type: Transform + pos: 69.5,-41.5 + parent: 5350 + - uid: 27434 + components: + - type: Transform + pos: 69.5,-42.5 + parent: 5350 - proto: AtmosFixFreezerMarker entities: - uid: 10295 @@ -14547,10 +14869,20 @@ entities: parent: 5350 - proto: AtmosFixPlasmaMarker entities: - - uid: 11600 + - uid: 10828 components: - type: Transform - pos: 67.5,-16.5 + pos: 69.5,-13.5 + parent: 5350 + - uid: 10916 + components: + - type: Transform + pos: 68.5,-13.5 + parent: 5350 + - uid: 10920 + components: + - type: Transform + pos: 67.5,-13.5 parent: 5350 - uid: 11601 components: @@ -14562,11 +14894,6 @@ entities: - type: Transform pos: 67.5,-14.5 parent: 5350 - - uid: 11603 - components: - - type: Transform - pos: 68.5,-16.5 - parent: 5350 - uid: 11604 components: - type: Transform @@ -14577,11 +14904,6 @@ entities: - type: Transform pos: 68.5,-14.5 parent: 5350 - - uid: 11606 - components: - - type: Transform - pos: 69.5,-16.5 - parent: 5350 - uid: 11607 components: - type: Transform @@ -15097,10 +15419,10 @@ entities: - type: Transform pos: -40.5,43.5 parent: 5350 - - uid: 10293 + - uid: 11015 components: - type: Transform - pos: 68.5,-5.5 + pos: 68.5,-4.5 parent: 5350 - uid: 11486 components: @@ -15172,6 +15494,20 @@ entities: - type: Transform pos: 48.5,23.5 parent: 5350 + - uid: 27135 + components: + - type: Transform + pos: 67.5,-43.5 + parent: 5350 + - type: DeviceLinkSink + invokeCounter: 2 + - uid: 27136 + components: + - type: Transform + pos: 68.5,-43.5 + parent: 5350 + - type: DeviceLinkSink + invokeCounter: 2 - proto: BlastDoorExterior1Open entities: - uid: 24634 @@ -19812,6 +20148,11 @@ entities: - type: Transform pos: -37.5,-0.5 parent: 5350 + - uid: 6164 + components: + - type: Transform + pos: 66.5,-6.5 + parent: 5350 - uid: 6209 components: - type: Transform @@ -21377,11 +21718,21 @@ entities: - type: Transform pos: -16.5,27.5 parent: 5350 + - uid: 8889 + components: + - type: Transform + pos: 67.5,-6.5 + parent: 5350 - uid: 8957 components: - type: Transform pos: 40.5,0.5 parent: 5350 + - uid: 8983 + components: + - type: Transform + pos: 68.5,-6.5 + parent: 5350 - uid: 9539 components: - type: Transform @@ -22707,11 +23058,196 @@ entities: - type: Transform pos: -29.5,30.5 parent: 5350 + - uid: 10908 + components: + - type: Transform + pos: 60.5,-16.5 + parent: 5350 + - uid: 10909 + components: + - type: Transform + pos: 67.5,-18.5 + parent: 5350 + - uid: 10911 + components: + - type: Transform + pos: 68.5,-18.5 + parent: 5350 + - uid: 10912 + components: + - type: Transform + pos: 66.5,-18.5 + parent: 5350 + - uid: 10929 + components: + - type: Transform + pos: 66.5,-5.5 + parent: 5350 + - uid: 10935 + components: + - type: Transform + pos: 63.5,-6.5 + parent: 5350 + - uid: 10936 + components: + - type: Transform + pos: 58.5,-6.5 + parent: 5350 + - uid: 10937 + components: + - type: Transform + pos: 59.5,-6.5 + parent: 5350 + - uid: 10938 + components: + - type: Transform + pos: 60.5,-6.5 + parent: 5350 + - uid: 10939 + components: + - type: Transform + pos: 61.5,-6.5 + parent: 5350 + - uid: 10940 + components: + - type: Transform + pos: 62.5,-6.5 + parent: 5350 + - uid: 10941 + components: + - type: Transform + pos: 68.5,-10.5 + parent: 5350 + - uid: 10942 + components: + - type: Transform + pos: 67.5,-10.5 + parent: 5350 + - uid: 10986 + components: + - type: Transform + pos: 66.5,-17.5 + parent: 5350 + - uid: 10987 + components: + - type: Transform + pos: 64.5,-19.5 + parent: 5350 + - uid: 10988 + components: + - type: Transform + pos: 68.5,-14.5 + parent: 5350 + - uid: 11044 + components: + - type: Transform + pos: 62.5,-16.5 + parent: 5350 + - uid: 11045 + components: + - type: Transform + pos: 63.5,-16.5 + parent: 5350 + - uid: 11046 + components: + - type: Transform + pos: 65.5,-18.5 + parent: 5350 + - uid: 11056 + components: + - type: Transform + pos: 66.5,-14.5 + parent: 5350 + - uid: 11138 + components: + - type: Transform + pos: 66.5,-19.5 + parent: 5350 + - uid: 11162 + components: + - type: Transform + pos: 67.5,-14.5 + parent: 5350 + - uid: 11241 + components: + - type: Transform + pos: 63.5,-19.5 + parent: 5350 + - uid: 11258 + components: + - type: Transform + pos: 68.5,-23.5 + parent: 5350 + - uid: 11259 + components: + - type: Transform + pos: 70.5,-23.5 + parent: 5350 + - uid: 11260 + components: + - type: Transform + pos: 67.5,-24.5 + parent: 5350 + - uid: 11263 + components: + - type: Transform + pos: 69.5,-23.5 + parent: 5350 + - uid: 11279 + components: + - type: Transform + pos: 69.5,-28.5 + parent: 5350 + - uid: 11300 + components: + - type: Transform + pos: 61.5,-16.5 + parent: 5350 + - uid: 11313 + components: + - type: Transform + pos: 65.5,-14.5 + parent: 5350 + - uid: 11314 + components: + - type: Transform + pos: 66.5,-13.5 + parent: 5350 + - uid: 11315 + components: + - type: Transform + pos: 66.5,-15.5 + parent: 5350 + - uid: 11341 + components: + - type: Transform + pos: 64.5,-21.5 + parent: 5350 + - uid: 11348 + components: + - type: Transform + pos: 64.5,-5.5 + parent: 5350 - uid: 11360 components: - type: Transform pos: -30.5,-41.5 parent: 5350 + - uid: 11606 + components: + - type: Transform + pos: 65.5,-6.5 + parent: 5350 + - uid: 11609 + components: + - type: Transform + pos: 61.5,-10.5 + parent: 5350 + - uid: 11643 + components: + - type: Transform + pos: 66.5,-10.5 + parent: 5350 - uid: 11646 components: - type: Transform @@ -22792,11 +23328,6 @@ entities: - type: Transform pos: 52.5,-23.5 parent: 5350 - - uid: 11662 - components: - - type: Transform - pos: 52.5,-24.5 - parent: 5350 - uid: 11663 components: - type: Transform @@ -22947,16 +23478,6 @@ entities: - type: Transform pos: 52.5,-28.5 parent: 5350 - - uid: 11693 - components: - - type: Transform - pos: 61.5,-24.5 - parent: 5350 - - uid: 11694 - components: - - type: Transform - pos: 62.5,-24.5 - parent: 5350 - uid: 11695 components: - type: Transform @@ -22967,21 +23488,6 @@ entities: - type: Transform pos: 63.5,-23.5 parent: 5350 - - uid: 11697 - components: - - type: Transform - pos: 64.5,-24.5 - parent: 5350 - - uid: 11698 - components: - - type: Transform - pos: 65.5,-24.5 - parent: 5350 - - uid: 11699 - components: - - type: Transform - pos: 66.5,-24.5 - parent: 5350 - uid: 11700 components: - type: Transform @@ -22995,17 +23501,17 @@ entities: - uid: 11702 components: - type: Transform - pos: 63.5,-20.5 + pos: 65.5,-10.5 parent: 5350 - uid: 11703 components: - type: Transform - pos: 64.5,-20.5 + pos: 66.5,-9.5 parent: 5350 - uid: 11704 components: - type: Transform - pos: 64.5,-19.5 + pos: 62.5,-24.5 parent: 5350 - uid: 11705 components: @@ -23075,122 +23581,47 @@ entities: - uid: 11718 components: - type: Transform - pos: 65.5,-7.5 + pos: 66.5,-11.5 parent: 5350 - uid: 11719 components: - type: Transform pos: 66.5,-7.5 parent: 5350 - - uid: 11720 - components: - - type: Transform - pos: 66.5,-8.5 - parent: 5350 - uid: 11721 components: - type: Transform pos: 66.5,-6.5 parent: 5350 - - uid: 11722 - components: - - type: Transform - pos: 65.5,-11.5 - parent: 5350 - - uid: 11723 - components: - - type: Transform - pos: 66.5,-11.5 - parent: 5350 - - uid: 11724 - components: - - type: Transform - pos: 66.5,-12.5 - parent: 5350 - - uid: 11725 - components: - - type: Transform - pos: 66.5,-10.5 - parent: 5350 - - uid: 11726 - components: - - type: Transform - pos: 65.5,-15.5 - parent: 5350 - - uid: 11727 - components: - - type: Transform - pos: 66.5,-15.5 - parent: 5350 - - uid: 11728 - components: - - type: Transform - pos: 66.5,-14.5 - parent: 5350 - - uid: 11729 - components: - - type: Transform - pos: 66.5,-16.5 - parent: 5350 - - uid: 11730 - components: - - type: Transform - pos: 65.5,-19.5 - parent: 5350 - uid: 11731 components: - type: Transform - pos: 66.5,-19.5 + pos: 63.5,-10.5 parent: 5350 - uid: 11732 components: - type: Transform - pos: 66.5,-20.5 + pos: 62.5,-10.5 parent: 5350 - uid: 11733 components: - type: Transform - pos: 66.5,-18.5 - parent: 5350 - - uid: 11734 - components: - - type: Transform - pos: 67.5,-19.5 - parent: 5350 - - uid: 11735 - components: - - type: Transform - pos: 68.5,-19.5 - parent: 5350 - - uid: 11736 - components: - - type: Transform - pos: 67.5,-15.5 + pos: 63.5,-20.5 parent: 5350 - uid: 11737 components: - type: Transform - pos: 68.5,-15.5 + pos: 61.5,-24.5 parent: 5350 - uid: 11738 components: - type: Transform - pos: 67.5,-11.5 + pos: 67.5,-23.5 parent: 5350 - uid: 11739 components: - type: Transform - pos: 68.5,-11.5 - parent: 5350 - - uid: 11740 - components: - - type: Transform - pos: 67.5,-7.5 - parent: 5350 - - uid: 11741 - components: - - type: Transform - pos: 68.5,-7.5 + pos: 66.5,-23.5 parent: 5350 - uid: 11742 components: @@ -23232,81 +23663,16 @@ entities: - type: Transform pos: 60.5,-10.5 parent: 5350 - - uid: 11750 - components: - - type: Transform - pos: 60.5,-11.5 - parent: 5350 - - uid: 11751 - components: - - type: Transform - pos: 61.5,-11.5 - parent: 5350 - - uid: 11752 - components: - - type: Transform - pos: 62.5,-11.5 - parent: 5350 - - uid: 11753 - components: - - type: Transform - pos: 63.5,-11.5 - parent: 5350 - - uid: 11754 - components: - - type: Transform - pos: 63.5,-7.5 - parent: 5350 - - uid: 11755 - components: - - type: Transform - pos: 62.5,-7.5 - parent: 5350 - - uid: 11756 - components: - - type: Transform - pos: 61.5,-7.5 - parent: 5350 - - uid: 11757 - components: - - type: Transform - pos: 60.5,-7.5 - parent: 5350 - - uid: 11758 - components: - - type: Transform - pos: 59.5,-7.5 - parent: 5350 - - uid: 11759 - components: - - type: Transform - pos: 58.5,-7.5 - parent: 5350 - - uid: 11760 - components: - - type: Transform - pos: 57.5,-7.5 - parent: 5350 - uid: 11761 components: - type: Transform pos: 58.5,-6.5 parent: 5350 - - uid: 11762 - components: - - type: Transform - pos: 58.5,-5.5 - parent: 5350 - uid: 11763 components: - type: Transform pos: 61.5,-6.5 parent: 5350 - - uid: 11764 - components: - - type: Transform - pos: 61.5,-5.5 - parent: 5350 - uid: 11765 components: - type: Transform @@ -23397,16 +23763,6 @@ entities: - type: Transform pos: 54.5,-20.5 parent: 5350 - - uid: 11784 - components: - - type: Transform - pos: 63.5,-17.5 - parent: 5350 - - uid: 11785 - components: - - type: Transform - pos: 62.5,-17.5 - parent: 5350 - uid: 11953 components: - type: Transform @@ -33367,6 +33723,11 @@ entities: - type: Transform pos: -15.5,-65.5 parent: 5350 + - uid: 24298 + components: + - type: Transform + pos: 52.5,-24.5 + parent: 5350 - uid: 24473 components: - type: Transform @@ -34532,6 +34893,311 @@ entities: - type: Transform pos: 76.5,3.5 parent: 5350 + - uid: 27017 + components: + - type: Transform + pos: 69.5,-29.5 + parent: 5350 + - uid: 27018 + components: + - type: Transform + pos: 70.5,-29.5 + parent: 5350 + - uid: 27019 + components: + - type: Transform + pos: 70.5,-30.5 + parent: 5350 + - uid: 27020 + components: + - type: Transform + pos: 70.5,-31.5 + parent: 5350 + - uid: 27021 + components: + - type: Transform + pos: 70.5,-32.5 + parent: 5350 + - uid: 27024 + components: + - type: Transform + pos: 70.5,-32.5 + parent: 5350 + - uid: 27025 + components: + - type: Transform + pos: 70.5,-33.5 + parent: 5350 + - uid: 27026 + components: + - type: Transform + pos: 70.5,-34.5 + parent: 5350 + - uid: 27027 + components: + - type: Transform + pos: 70.5,-35.5 + parent: 5350 + - uid: 27028 + components: + - type: Transform + pos: 67.5,-25.5 + parent: 5350 + - uid: 27029 + components: + - type: Transform + pos: 67.5,-27.5 + parent: 5350 + - uid: 27030 + components: + - type: Transform + pos: 71.5,-29.5 + parent: 5350 + - uid: 27031 + components: + - type: Transform + pos: 72.5,-29.5 + parent: 5350 + - uid: 27032 + components: + - type: Transform + pos: 73.5,-29.5 + parent: 5350 + - uid: 27033 + components: + - type: Transform + pos: 74.5,-29.5 + parent: 5350 + - uid: 27034 + components: + - type: Transform + pos: 74.5,-30.5 + parent: 5350 + - uid: 27039 + components: + - type: Transform + pos: 67.5,-26.5 + parent: 5350 + - uid: 27046 + components: + - type: Transform + pos: 67.5,-28.5 + parent: 5350 + - uid: 27048 + components: + - type: Transform + pos: 74.5,-32.5 + parent: 5350 + - uid: 27049 + components: + - type: Transform + pos: 76.5,-41.5 + parent: 5350 + - uid: 27063 + components: + - type: Transform + pos: 75.5,-32.5 + parent: 5350 + - uid: 27079 + components: + - type: Transform + pos: 76.5,-36.5 + parent: 5350 + - uid: 27080 + components: + - type: Transform + pos: 72.5,-32.5 + parent: 5350 + - uid: 27081 + components: + - type: Transform + pos: 71.5,-32.5 + parent: 5350 + - uid: 27082 + components: + - type: Transform + pos: 68.5,-29.5 + parent: 5350 + - uid: 27083 + components: + - type: Transform + pos: 73.5,-32.5 + parent: 5350 + - uid: 27092 + components: + - type: Transform + pos: 76.5,-34.5 + parent: 5350 + - uid: 27095 + components: + - type: Transform + pos: 64.5,-25.5 + parent: 5350 + - uid: 27100 + components: + - type: Transform + pos: 67.5,-29.5 + parent: 5350 + - uid: 27105 + components: + - type: Transform + pos: 76.5,-35.5 + parent: 5350 + - uid: 27106 + components: + - type: Transform + pos: 76.5,-33.5 + parent: 5350 + - uid: 27107 + components: + - type: Transform + pos: 76.5,-32.5 + parent: 5350 + - uid: 27109 + components: + - type: Transform + pos: 76.5,-38.5 + parent: 5350 + - uid: 27110 + components: + - type: Transform + pos: 75.5,-38.5 + parent: 5350 + - uid: 27113 + components: + - type: Transform + pos: 74.5,-39.5 + parent: 5350 + - uid: 27114 + components: + - type: Transform + pos: 73.5,-39.5 + parent: 5350 + - uid: 27115 + components: + - type: Transform + pos: 66.5,-37.5 + parent: 5350 + - uid: 27158 + components: + - type: Transform + pos: 76.5,-39.5 + parent: 5350 + - uid: 27159 + components: + - type: Transform + pos: 76.5,-37.5 + parent: 5350 + - uid: 27160 + components: + - type: Transform + pos: 76.5,-40.5 + parent: 5350 + - uid: 27161 + components: + - type: Transform + pos: 72.5,-39.5 + parent: 5350 + - uid: 27164 + components: + - type: Transform + pos: 66.5,-38.5 + parent: 5350 + - uid: 27165 + components: + - type: Transform + pos: 74.5,-38.5 + parent: 5350 + - uid: 27197 + components: + - type: Transform + pos: 71.5,-39.5 + parent: 5350 + - uid: 27259 + components: + - type: Transform + pos: 66.5,-29.5 + parent: 5350 + - uid: 27260 + components: + - type: Transform + pos: 65.5,-29.5 + parent: 5350 + - uid: 27261 + components: + - type: Transform + pos: 65.5,-30.5 + parent: 5350 + - uid: 27266 + components: + - type: Transform + pos: 66.5,-36.5 + parent: 5350 + - uid: 27268 + components: + - type: Transform + pos: 66.5,-22.5 + parent: 5350 + - uid: 27273 + components: + - type: Transform + pos: 63.5,-25.5 + parent: 5350 + - uid: 27275 + components: + - type: Transform + pos: 66.5,-35.5 + parent: 5350 + - uid: 27276 + components: + - type: Transform + pos: 66.5,-34.5 + parent: 5350 + - uid: 27277 + components: + - type: Transform + pos: 66.5,-33.5 + parent: 5350 + - uid: 27278 + components: + - type: Transform + pos: 66.5,-32.5 + parent: 5350 + - uid: 27279 + components: + - type: Transform + pos: 67.5,-32.5 + parent: 5350 + - uid: 27280 + components: + - type: Transform + pos: 68.5,-32.5 + parent: 5350 + - uid: 27281 + components: + - type: Transform + pos: 69.5,-32.5 + parent: 5350 + - uid: 27282 + components: + - type: Transform + pos: 66.5,-39.5 + parent: 5350 + - uid: 27283 + components: + - type: Transform + pos: 67.5,-39.5 + parent: 5350 + - uid: 27284 + components: + - type: Transform + pos: 68.5,-39.5 + parent: 5350 + - uid: 27285 + components: + - type: Transform + pos: 69.5,-39.5 + parent: 5350 - proto: CableApcStack entities: - uid: 1550 @@ -37556,30 +38222,25 @@ entities: - type: Transform pos: -32.5,49.5 parent: 5350 - - uid: 11245 - components: - - type: Transform - pos: 67.5,-31.5 - parent: 5350 - - uid: 11272 + - uid: 10832 components: - type: Transform - pos: 69.5,-34.5 + pos: 69.5,-26.5 parent: 5350 - - uid: 11274 + - uid: 10834 components: - type: Transform - pos: 69.5,-32.5 + pos: 52.5,-24.5 parent: 5350 - - uid: 11278 + - uid: 10836 components: - type: Transform - pos: 69.5,-33.5 + pos: 70.5,-26.5 parent: 5350 - - uid: 11279 + - uid: 11266 components: - type: Transform - pos: 69.5,-31.5 + pos: 65.5,-24.5 parent: 5350 - uid: 11877 components: @@ -37776,6 +38437,26 @@ entities: - type: Transform pos: 42.5,-17.5 parent: 5350 + - uid: 12022 + components: + - type: Transform + pos: 68.5,-26.5 + parent: 5350 + - uid: 12043 + components: + - type: Transform + pos: 67.5,-26.5 + parent: 5350 + - uid: 12044 + components: + - type: Transform + pos: 67.5,-25.5 + parent: 5350 + - uid: 12047 + components: + - type: Transform + pos: 66.5,-24.5 + parent: 5350 - uid: 12076 components: - type: Transform @@ -43204,112 +43885,102 @@ entities: - uid: 24239 components: - type: Transform - pos: 68.5,-31.5 + pos: 64.5,-24.5 parent: 5350 - uid: 24240 components: - type: Transform - pos: 66.5,-31.5 + pos: 63.5,-24.5 parent: 5350 - uid: 24241 components: - type: Transform - pos: 65.5,-31.5 + pos: 62.5,-24.5 parent: 5350 - uid: 24243 components: - type: Transform - pos: 64.5,-31.5 + pos: 61.5,-24.5 parent: 5350 - uid: 24245 components: - type: Transform - pos: 63.5,-31.5 + pos: 59.5,-24.5 parent: 5350 - uid: 24246 components: - type: Transform - pos: 63.5,-32.5 + pos: 60.5,-24.5 parent: 5350 - uid: 24247 components: - type: Transform - pos: 62.5,-32.5 + pos: 58.5,-24.5 parent: 5350 - uid: 24249 components: - type: Transform - pos: 61.5,-32.5 + pos: 57.5,-24.5 parent: 5350 - uid: 24250 components: - type: Transform - pos: 60.5,-32.5 + pos: 56.5,-24.5 parent: 5350 - uid: 24251 components: - type: Transform - pos: 59.5,-32.5 + pos: 55.5,-24.5 parent: 5350 - uid: 24253 components: - type: Transform - pos: 58.5,-32.5 + pos: 54.5,-24.5 parent: 5350 - uid: 24254 components: - type: Transform - pos: 57.5,-32.5 + pos: 67.5,-24.5 parent: 5350 - uid: 24255 components: - type: Transform - pos: 56.5,-32.5 + pos: 53.5,-24.5 parent: 5350 - uid: 24257 components: - type: Transform - pos: 55.5,-32.5 + pos: 52.5,-23.5 parent: 5350 - uid: 24260 components: - type: Transform - pos: 54.5,-32.5 + pos: 52.5,-22.5 parent: 5350 - uid: 24261 components: - type: Transform - pos: 53.5,-32.5 - parent: 5350 - - uid: 24298 - components: - - type: Transform - pos: 52.5,-32.5 - parent: 5350 - - uid: 24299 - components: - - type: Transform - pos: 51.5,-32.5 + pos: 52.5,-21.5 parent: 5350 - uid: 24301 components: - type: Transform - pos: 50.5,-32.5 + pos: 70.5,-27.5 parent: 5350 - uid: 24302 components: - type: Transform - pos: 49.5,-32.5 + pos: 70.5,-28.5 parent: 5350 - uid: 24303 components: - type: Transform - pos: 48.5,-32.5 + pos: 70.5,-29.5 parent: 5350 - uid: 24304 components: - type: Transform - pos: 47.5,-32.5 + pos: 70.5,-30.5 parent: 5350 - uid: 24497 components: @@ -43361,6 +44032,11 @@ entities: - type: Transform pos: 47.5,-24.5 parent: 5350 + - uid: 24516 + components: + - type: Transform + pos: 70.5,-31.5 + parent: 5350 - uid: 24519 components: - type: Transform @@ -43456,6 +44132,11 @@ entities: - type: Transform pos: 104.5,0.5 parent: 5350 + - uid: 26785 + components: + - type: Transform + pos: 70.5,-32.5 + parent: 5350 - uid: 26811 components: - type: Transform @@ -43541,6 +44222,31 @@ entities: - type: Transform pos: 103.5,13.5 parent: 5350 + - uid: 27000 + components: + - type: Transform + pos: 70.5,-33.5 + parent: 5350 + - uid: 27001 + components: + - type: Transform + pos: 70.5,-34.5 + parent: 5350 + - uid: 27002 + components: + - type: Transform + pos: 70.5,-35.5 + parent: 5350 + - uid: 27013 + components: + - type: Transform + pos: 71.5,-31.5 + parent: 5350 + - uid: 27123 + components: + - type: Transform + pos: 70.5,-25.5 + parent: 5350 - proto: CableHVStack entities: - uid: 1551 @@ -46950,6 +47656,31 @@ entities: - type: Transform pos: -34.5,32.5 parent: 5350 + - uid: 10840 + components: + - type: Transform + pos: 69.5,-26.5 + parent: 5350 + - uid: 11261 + components: + - type: Transform + pos: 69.5,-25.5 + parent: 5350 + - uid: 11270 + components: + - type: Transform + pos: 69.5,-28.5 + parent: 5350 + - uid: 11272 + components: + - type: Transform + pos: 70.5,-25.5 + parent: 5350 + - uid: 11274 + components: + - type: Transform + pos: 69.5,-27.5 + parent: 5350 - uid: 11917 components: - type: Transform @@ -50755,6 +51486,12 @@ entities: rot: 1.5707963267948966 rad pos: 38.5,-60.5 parent: 5350 + - uid: 24299 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 70.5,-27.5 + parent: 5350 - uid: 24518 components: - type: Transform @@ -50802,10 +51539,10 @@ entities: parent: 5350 - proto: CarbonDioxideCanister entities: - - uid: 11597 + - uid: 11615 components: - type: Transform - pos: 69.5,-19.5 + pos: 69.5,-18.5 parent: 5350 - uid: 11815 components: @@ -50822,6 +51559,11 @@ entities: - type: Transform pos: 25.5,-48.5 parent: 5350 + - uid: 27090 + components: + - type: Transform + pos: 76.5,-36.5 + parent: 5350 - proto: Carpet entities: - uid: 1123 @@ -52900,6 +53642,11 @@ entities: - type: Transform pos: -43.5,35.5 parent: 5350 + - uid: 11282 + components: + - type: Transform + pos: 72.5,-24.5 + parent: 5350 - uid: 11471 components: - type: Transform @@ -52945,6 +53692,16 @@ entities: - type: Transform pos: 48.5,-34.5 parent: 5350 + - uid: 11756 + components: + - type: Transform + pos: 72.5,-23.5 + parent: 5350 + - uid: 11759 + components: + - type: Transform + pos: 72.5,-22.5 + parent: 5350 - uid: 12119 components: - type: Transform @@ -55904,6 +56661,119 @@ entities: - type: Transform pos: 58.5,11.5 parent: 5350 + - uid: 27112 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 74.5,-42.5 + parent: 5350 + - uid: 27157 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 74.5,-41.5 + parent: 5350 + - uid: 27169 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 71.5,-43.5 + parent: 5350 + - uid: 27170 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 72.5,-43.5 + parent: 5350 + - uid: 27171 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 73.5,-43.5 + parent: 5350 + - uid: 27172 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 74.5,-43.5 + parent: 5350 + - uid: 27173 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 75.5,-43.5 + parent: 5350 + - uid: 27174 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 76.5,-43.5 + parent: 5350 + - uid: 27175 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 77.5,-43.5 + parent: 5350 + - uid: 27176 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 65.5,-44.5 + parent: 5350 + - uid: 27178 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 67.5,-44.5 + parent: 5350 + - uid: 27179 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 68.5,-44.5 + parent: 5350 + - uid: 27180 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 69.5,-44.5 + parent: 5350 + - uid: 27181 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 70.5,-44.5 + parent: 5350 + - uid: 27182 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 71.5,-44.5 + parent: 5350 + - uid: 27183 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 72.5,-44.5 + parent: 5350 + - uid: 27184 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 73.5,-44.5 + parent: 5350 + - uid: 27254 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 66.5,-44.5 + parent: 5350 + - uid: 27255 + components: + - type: Transform + pos: 74.5,-44.5 + parent: 5350 - proto: Chair entities: - uid: 347 @@ -57477,6 +58347,11 @@ entities: rot: 1.5707963267948966 rad pos: 106.5,4.5 parent: 5350 + - uid: 27118 + components: + - type: Transform + pos: 71.5,-30.5 + parent: 5350 - proto: ChairOfficeLight entities: - uid: 5098 @@ -60889,6 +61764,15 @@ entities: - type: Transform pos: -40.532333,-25.270031 parent: 5350 +- proto: ClothingHeadHelmetAtmosFire + entities: + - uid: 27091 + components: + - type: Transform + parent: 27084 + - type: Physics + canCollide: False + - type: InsideEntityStorage - proto: ClothingHeadHelmetBasic entities: - uid: 10424 @@ -61059,6 +61943,13 @@ entities: - type: Transform pos: 45.489563,-8.468819 parent: 5350 + - uid: 27098 + components: + - type: Transform + parent: 27084 + - type: Physics + canCollide: False + - type: InsideEntityStorage - proto: ClothingMaskGasExplorer entities: - uid: 3689 @@ -61426,6 +62317,15 @@ entities: - type: Transform pos: -18.5,29.5 parent: 5350 +- proto: ClothingOuterSuitAtmosFire + entities: + - uid: 27097 + components: + - type: Transform + parent: 27084 + - type: Physics + canCollide: False + - type: InsideEntityStorage - proto: ClothingOuterSuitMonkey entities: - uid: 24111 @@ -62444,6 +63344,12 @@ entities: rot: 3.141592653589793 rad pos: 110.5,-0.5 parent: 5350 + - uid: 27043 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 71.5,-31.5 + parent: 5350 - proto: ComputerRadar entities: - uid: 1207 @@ -63178,6 +64084,13 @@ entities: - type: Transform pos: 38.5,-16.5 parent: 5350 +- proto: CrateMaterialSteel + entities: + - uid: 27101 + components: + - type: Transform + pos: 68.5,-31.5 + parent: 5350 - proto: CrateMedical entities: - uid: 15591 @@ -63826,6 +64739,13 @@ entities: - type: Transform pos: 36.5,7.5 parent: 5350 +- proto: DefaultStationBeaconTEG + entities: + - uid: 27252 + components: + - type: Transform + pos: 70.5,-30.5 + parent: 5350 - proto: DefaultStationBeaconTelecoms entities: - uid: 26708 @@ -71659,6 +72579,11 @@ entities: - type: Transform pos: -29.5,-42.5 parent: 5350 + - uid: 27096 + components: + - type: Transform + pos: 74.5,-31.5 + parent: 5350 - proto: ExtinguisherCabinetOpen entities: - uid: 22178 @@ -72658,6 +73583,16 @@ entities: - 14208 - 14209 - 14210 + - uid: 26994 + components: + - type: Transform + pos: 68.5,-28.5 + parent: 5350 + - type: DeviceList + devices: + - 27078 + - 26996 + - 26995 - proto: FireAxeCabinetFilled entities: - uid: 1096 @@ -73974,6 +74909,24 @@ entities: - type: Transform pos: -72.5,8.5 parent: 5350 + - uid: 26995 + components: + - type: Transform + pos: 66.5,-25.5 + parent: 5350 + - type: DeviceNetwork + deviceLists: + - 11752 + - 26994 + - uid: 26996 + components: + - type: Transform + pos: 67.5,-25.5 + parent: 5350 + - type: DeviceNetwork + deviceLists: + - 11752 + - 26994 - proto: Fireplace entities: - uid: 1054 @@ -74689,6 +75642,12 @@ entities: - type: Transform pos: -57.517693,-13.493662 parent: 5350 + - uid: 27104 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 73.5,-30.5 + parent: 5350 - proto: GasFilterFlipped entities: - uid: 14354 @@ -74701,10 +75660,10 @@ entities: color: '#FF1212FF' - proto: GasMinerCarbonDioxide entities: - - uid: 11596 + - uid: 11612 components: - type: Transform - pos: 68.5,-19.5 + pos: 68.5,-18.5 parent: 5350 - proto: GasMinerNitrogenStationLarge entities: @@ -74746,35 +75705,19 @@ entities: parent: 5350 - proto: GasOutletInjector entities: - - uid: 10990 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 67.5,-8.5 - parent: 5350 - - type: AtmosPipeColor - color: '#27E312FF' - - uid: 10991 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 67.5,-12.5 - parent: 5350 - - type: AtmosPipeColor - color: '#27E312FF' - - uid: 10992 + - uid: 3186 components: - type: Transform rot: -1.5707963267948966 rad - pos: 67.5,-16.5 + pos: 67.5,-19.5 parent: 5350 - type: AtmosPipeColor color: '#27E312FF' - - uid: 10993 + - uid: 10830 components: - type: Transform rot: -1.5707963267948966 rad - pos: 67.5,-20.5 + pos: 67.5,-15.5 parent: 5350 - type: AtmosPipeColor color: '#27E312FF' @@ -74806,6 +75749,22 @@ entities: rot: -1.5707963267948966 rad pos: 44.5,-34.5 parent: 5350 + - uid: 11570 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 67.5,-7.5 + parent: 5350 + - type: AtmosPipeColor + color: '#27E312FF' + - uid: 11723 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 67.5,-11.5 + parent: 5350 + - type: AtmosPipeColor + color: '#27E312FF' - uid: 19390 components: - type: Transform @@ -74827,6 +75786,22 @@ entities: rot: 3.141592653589793 rad pos: 59.5,-28.5 parent: 5350 + - uid: 10829 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 67.5,-13.5 + parent: 5350 + - type: AtmosPipeColor + color: '#B342F5FF' + - uid: 10910 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 67.5,-17.5 + parent: 5350 + - type: AtmosPipeColor + color: '#B342F5FF' - uid: 10981 components: - type: Transform @@ -74859,35 +75834,19 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#947507FF' - - uid: 10986 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 67.5,-18.5 - parent: 5350 - - type: AtmosPipeColor - color: '#947507FF' - - uid: 10987 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 67.5,-14.5 - parent: 5350 - - type: AtmosPipeColor - color: '#947507FF' - - uid: 10988 + - uid: 11309 components: - type: Transform rot: -1.5707963267948966 rad - pos: 67.5,-10.5 + pos: 67.5,-5.5 parent: 5350 - type: AtmosPipeColor - color: '#947507FF' - - uid: 10989 + color: '#B342F5FF' + - uid: 11310 components: - type: Transform rot: -1.5707963267948966 rad - pos: 67.5,-6.5 + pos: 67.5,-9.5 parent: 5350 - type: AtmosPipeColor color: '#B342F5FF' @@ -74939,6 +75898,24 @@ entities: rot: 3.141592653589793 rad pos: 104.5,-16.5 parent: 5350 + - uid: 27069 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 69.5,-40.5 + parent: 5350 + - uid: 27073 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 66.5,-40.5 + parent: 5350 + - uid: 27111 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 74.5,-40.5 + parent: 5350 - proto: GasPipeBend entities: - uid: 510 @@ -75353,14 +76330,6 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#0055CCFF' - - uid: 5314 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 57.5,-4.5 - parent: 5350 - - type: AtmosPipeColor - color: '#0055CCFF' - uid: 5489 components: - type: Transform @@ -75829,19 +76798,19 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#FF1212FF' - - uid: 11002 + - uid: 10993 components: - type: Transform - rot: 3.141592653589793 rad - pos: 62.5,-5.5 + rot: -1.5707963267948966 rad + pos: 58.5,-5.5 parent: 5350 - type: AtmosPipeColor color: '#03FCD3FF' - - uid: 11004 + - uid: 11002 components: - type: Transform - rot: -1.5707963267948966 rad - pos: 57.5,-10.5 + rot: 1.5707963267948966 rad + pos: 58.5,-4.5 parent: 5350 - type: AtmosPipeColor color: '#03FCD3FF' @@ -75869,11 +76838,10 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#0055CCFF' - - uid: 11118 + - uid: 11116 components: - type: Transform - rot: 1.5707963267948966 rad - pos: 57.5,-9.5 + pos: 63.5,-4.5 parent: 5350 - type: AtmosPipeColor color: '#03FCD3FF' @@ -75901,13 +76869,6 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#03FCD3FF' - - uid: 11137 - components: - - type: Transform - pos: 62.5,-4.5 - parent: 5350 - - type: AtmosPipeColor - color: '#03FCD3FF' - uid: 11156 components: - type: Transform @@ -76826,6 +77787,85 @@ entities: rot: 3.141592653589793 rad pos: 108.5,-4.5 parent: 5350 + - uid: 26787 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 61.5,-20.5 + parent: 5350 + - type: AtmosPipeColor + color: '#03FCD3FF' + - uid: 26985 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 63.5,-20.5 + parent: 5350 + - type: AtmosPipeColor + color: '#03FCD3FF' + - uid: 27185 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 71.5,-42.5 + parent: 5350 + - uid: 27186 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 73.5,-42.5 + parent: 5350 + - uid: 27211 + components: + - type: Transform + pos: 66.5,-21.5 + parent: 5350 + - type: AtmosPipeColor + color: '#947507FF' + - uid: 27213 + components: + - type: Transform + pos: 69.5,-30.5 + parent: 5350 + - type: AtmosPipeColor + color: '#0055CCFF' + - uid: 27214 + components: + - type: Transform + pos: 63.5,-24.5 + parent: 5350 + - type: AtmosPipeColor + color: '#0055CCFF' + - uid: 27229 + components: + - type: Transform + pos: 64.5,-23.5 + parent: 5350 + - type: AtmosPipeColor + color: '#FF1212FF' + - uid: 27230 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 63.5,-30.5 + parent: 5350 + - type: AtmosPipeColor + color: '#0055CCFF' + - uid: 27231 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 64.5,-29.5 + parent: 5350 + - type: AtmosPipeColor + color: '#FF1212FF' + - uid: 27233 + components: + - type: Transform + pos: 72.5,-29.5 + parent: 5350 + - type: AtmosPipeColor + color: '#FF1212FF' - proto: GasPipeFourway entities: - uid: 260 @@ -81507,6 +82547,14 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#0055CCFF' + - uid: 2682 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 65.5,-7.5 + parent: 5350 + - type: AtmosPipeColor + color: '#27E312FF' - uid: 2685 components: - type: Transform @@ -84293,13 +85341,6 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#0055CCFF' - - uid: 5315 - components: - - type: Transform - pos: 57.5,-5.5 - parent: 5350 - - type: AtmosPipeColor - color: '#0055CCFF' - uid: 5459 components: - type: Transform @@ -88750,14 +89791,6 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#0055CCFF' - - uid: 8889 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 58.5,-4.5 - parent: 5350 - - type: AtmosPipeColor - color: '#0055CCFF' - uid: 8978 components: - type: Transform @@ -88766,14 +89799,6 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#0055CCFF' - - uid: 8983 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 59.5,-4.5 - parent: 5350 - - type: AtmosPipeColor - color: '#0055CCFF' - uid: 8987 components: - type: Transform @@ -88944,14 +89969,6 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#0055CCFF' - - uid: 9027 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 60.5,-4.5 - parent: 5350 - - type: AtmosPipeColor - color: '#0055CCFF' - uid: 9039 components: - type: Transform @@ -88960,11 +89977,6 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#0055CCFF' - - uid: 9069 - components: - - type: Transform - pos: 68.5,-30.5 - parent: 5350 - uid: 9166 components: - type: Transform @@ -89631,6 +90643,62 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#0055CCFF' + - uid: 10815 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 66.5,-15.5 + parent: 5350 + - type: AtmosPipeColor + color: '#27E312FF' + - uid: 10816 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 64.5,-15.5 + parent: 5350 + - type: AtmosPipeColor + color: '#27E312FF' + - uid: 10822 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 66.5,-7.5 + parent: 5350 + - type: AtmosPipeColor + color: '#27E312FF' + - uid: 10825 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 65.5,-11.5 + parent: 5350 + - type: AtmosPipeColor + color: '#27E312FF' + - uid: 10826 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 66.5,-11.5 + parent: 5350 + - type: AtmosPipeColor + color: '#27E312FF' + - uid: 10924 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 64.5,-11.5 + parent: 5350 + - type: AtmosPipeColor + color: '#27E312FF' + - uid: 10931 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 64.5,-7.5 + parent: 5350 + - type: AtmosPipeColor + color: '#27E312FF' - uid: 10952 components: - type: Transform @@ -89694,6 +90762,14 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#FF1212FF' + - uid: 10972 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 65.5,-15.5 + parent: 5350 + - type: AtmosPipeColor + color: '#27E312FF' - uid: 10973 components: - type: Transform @@ -89725,6 +90801,14 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#FF1212FF' + - uid: 10992 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 61.5,-10.5 + parent: 5350 + - type: AtmosPipeColor + color: '#03FCD3FF' - uid: 11003 components: - type: Transform @@ -89733,6 +90817,14 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#FF1212FF' + - uid: 11004 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 60.5,-10.5 + parent: 5350 + - type: AtmosPipeColor + color: '#03FCD3FF' - uid: 11016 components: - type: Transform @@ -89775,78 +90867,22 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#27E312FF' - - uid: 11040 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 64.5,-20.5 - parent: 5350 - - type: AtmosPipeColor - color: '#27E312FF' - uid: 11041 components: - type: Transform rot: 1.5707963267948966 rad - pos: 65.5,-20.5 + pos: 57.5,-10.5 parent: 5350 - type: AtmosPipeColor - color: '#27E312FF' + color: '#03FCD3FF' - uid: 11042 components: - type: Transform rot: 1.5707963267948966 rad - pos: 66.5,-20.5 - parent: 5350 - - type: AtmosPipeColor - color: '#27E312FF' - - uid: 11044 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 64.5,-16.5 - parent: 5350 - - type: AtmosPipeColor - color: '#27E312FF' - - uid: 11045 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 65.5,-16.5 - parent: 5350 - - type: AtmosPipeColor - color: '#27E312FF' - - uid: 11046 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 66.5,-16.5 - parent: 5350 - - type: AtmosPipeColor - color: '#27E312FF' - - uid: 11054 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 64.5,-12.5 - parent: 5350 - - type: AtmosPipeColor - color: '#27E312FF' - - uid: 11055 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 65.5,-12.5 - parent: 5350 - - type: AtmosPipeColor - color: '#27E312FF' - - uid: 11056 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 66.5,-12.5 + pos: 58.5,-10.5 parent: 5350 - type: AtmosPipeColor - color: '#27E312FF' + color: '#03FCD3FF' - uid: 11058 components: - type: Transform @@ -90058,42 +91094,6 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#03FCD3FF' - - uid: 11098 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 62.5,-24.5 - parent: 5350 - - type: AtmosPipeColor - color: '#03FCD3FF' - - uid: 11099 - components: - - type: Transform - pos: 63.5,-23.5 - parent: 5350 - - type: AtmosPipeColor - color: '#03FCD3FF' - - uid: 11100 - components: - - type: Transform - pos: 63.5,-22.5 - parent: 5350 - - type: AtmosPipeColor - color: '#03FCD3FF' - - uid: 11101 - components: - - type: Transform - pos: 63.5,-21.5 - parent: 5350 - - type: AtmosPipeColor - color: '#03FCD3FF' - - uid: 11102 - components: - - type: Transform - pos: 63.5,-20.5 - parent: 5350 - - type: AtmosPipeColor - color: '#03FCD3FF' - uid: 11103 components: - type: Transform @@ -90157,50 +91157,19 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#03FCD3FF' - - uid: 11112 - components: - - type: Transform - pos: 63.5,-10.5 - parent: 5350 - - type: AtmosPipeColor - color: '#03FCD3FF' - - uid: 11113 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 62.5,-9.5 - parent: 5350 - - type: AtmosPipeColor - color: '#03FCD3FF' - - uid: 11114 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 61.5,-9.5 - parent: 5350 - - type: AtmosPipeColor - color: '#03FCD3FF' - - uid: 11115 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 60.5,-9.5 - parent: 5350 - - type: AtmosPipeColor - color: '#03FCD3FF' - - uid: 11116 + - uid: 11117 components: - type: Transform - rot: -1.5707963267948966 rad - pos: 59.5,-9.5 + rot: 1.5707963267948966 rad + pos: 62.5,-4.5 parent: 5350 - type: AtmosPipeColor color: '#03FCD3FF' - - uid: 11117 + - uid: 11118 components: - type: Transform - rot: -1.5707963267948966 rad - pos: 58.5,-9.5 + rot: 1.5707963267948966 rad + pos: 61.5,-4.5 parent: 5350 - type: AtmosPipeColor color: '#03FCD3FF' @@ -90228,6 +91197,14 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#03FCD3FF' + - uid: 11130 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 60.5,-4.5 + parent: 5350 + - type: AtmosPipeColor + color: '#03FCD3FF' - uid: 11131 components: - type: Transform @@ -90252,6 +91229,14 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#03FCD3FF' + - uid: 11134 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 59.5,-4.5 + parent: 5350 + - type: AtmosPipeColor + color: '#03FCD3FF' - uid: 11139 components: - type: Transform @@ -90332,14 +91317,6 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#0055CCFF' - - uid: 11151 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: 57.5,-6.5 - parent: 5350 - - type: AtmosPipeColor - color: '#0055CCFF' - uid: 11152 components: - type: Transform @@ -90380,78 +91357,14 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#0055CCFF' - - uid: 11161 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 66.5,-18.5 - parent: 5350 - - type: AtmosPipeColor - color: '#947507FF' - - uid: 11162 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 65.5,-18.5 - parent: 5350 - - type: AtmosPipeColor - color: '#947507FF' - - uid: 11163 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 64.5,-18.5 - parent: 5350 - - type: AtmosPipeColor - color: '#947507FF' - - uid: 11166 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 66.5,-14.5 - parent: 5350 - - type: AtmosPipeColor - color: '#947507FF' - uid: 11167 components: - type: Transform rot: -1.5707963267948966 rad - pos: 65.5,-14.5 - parent: 5350 - - type: AtmosPipeColor - color: '#947507FF' - - uid: 11168 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 64.5,-14.5 - parent: 5350 - - type: AtmosPipeColor - color: '#947507FF' - - uid: 11171 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 66.5,-10.5 - parent: 5350 - - type: AtmosPipeColor - color: '#947507FF' - - uid: 11172 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 65.5,-10.5 - parent: 5350 - - type: AtmosPipeColor - color: '#947507FF' - - uid: 11173 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 64.5,-10.5 + pos: 64.5,-9.5 parent: 5350 - type: AtmosPipeColor - color: '#947507FF' + color: '#B342F5FF' - uid: 11196 components: - type: Transform @@ -90476,54 +91389,21 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#FF1212FF' - - uid: 11200 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 64.5,-8.5 - parent: 5350 - - type: AtmosPipeColor - color: '#27E312FF' - - uid: 11201 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 65.5,-8.5 - parent: 5350 - - type: AtmosPipeColor - color: '#27E312FF' - - uid: 11202 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 66.5,-8.5 - parent: 5350 - - type: AtmosPipeColor - color: '#27E312FF' - - uid: 11204 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 66.5,-6.5 - parent: 5350 - - type: AtmosPipeColor - color: '#B342F5FF' - uid: 11205 components: - type: Transform - rot: 1.5707963267948966 rad - pos: 65.5,-6.5 + pos: 63.5,-5.5 parent: 5350 - type: AtmosPipeColor - color: '#B342F5FF' + color: '#03FCD3FF' - uid: 11206 components: - type: Transform rot: 1.5707963267948966 rad - pos: 64.5,-6.5 + pos: 62.5,-10.5 parent: 5350 - type: AtmosPipeColor - color: '#B342F5FF' + color: '#03FCD3FF' - uid: 11227 components: - type: Transform @@ -90572,63 +91452,93 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#000000FF' - - uid: 11237 + - uid: 11297 components: - type: Transform - rot: 1.5707963267948966 rad - pos: 64.5,-24.5 + pos: 63.5,-9.5 parent: 5350 - type: AtmosPipeColor color: '#03FCD3FF' - - uid: 11238 + - uid: 11306 components: - type: Transform rot: 1.5707963267948966 rad - pos: 65.5,-24.5 + pos: 59.5,-10.5 parent: 5350 - type: AtmosPipeColor color: '#03FCD3FF' - - uid: 11239 + - uid: 11316 components: - type: Transform - rot: 1.5707963267948966 rad - pos: 66.5,-24.5 + rot: -1.5707963267948966 rad + pos: 64.5,-17.5 parent: 5350 - type: AtmosPipeColor - color: '#03FCD3FF' - - uid: 11240 + color: '#B342F5FF' + - uid: 11317 components: - type: Transform - rot: 1.5707963267948966 rad - pos: 67.5,-24.5 + rot: -1.5707963267948966 rad + pos: 65.5,-17.5 parent: 5350 - type: AtmosPipeColor - color: '#03FCD3FF' - - uid: 11241 + color: '#B342F5FF' + - uid: 11318 components: - type: Transform - rot: 1.5707963267948966 rad - pos: 68.5,-24.5 + rot: -1.5707963267948966 rad + pos: 66.5,-17.5 parent: 5350 - type: AtmosPipeColor - color: '#03FCD3FF' - - uid: 11246 + color: '#B342F5FF' + - uid: 11349 components: - type: Transform - pos: 70.5,-30.5 + rot: -1.5707963267948966 rad + pos: 66.5,-19.5 parent: 5350 - - uid: 11247 + - type: AtmosPipeColor + color: '#27E312FF' + - uid: 11350 components: - type: Transform - rot: 3.141592653589793 rad - pos: 68.5,-29.5 + rot: -1.5707963267948966 rad + pos: 65.5,-19.5 parent: 5350 - - uid: 11248 + - type: AtmosPipeColor + color: '#27E312FF' + - uid: 11351 components: - type: Transform - rot: 3.141592653589793 rad - pos: 70.5,-29.5 + rot: -1.5707963267948966 rad + pos: 64.5,-19.5 + parent: 5350 + - type: AtmosPipeColor + color: '#27E312FF' + - uid: 11352 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 64.5,-13.5 parent: 5350 + - type: AtmosPipeColor + color: '#B342F5FF' + - uid: 11353 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 65.5,-13.5 + parent: 5350 + - type: AtmosPipeColor + color: '#B342F5FF' + - uid: 11354 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 66.5,-13.5 + parent: 5350 + - type: AtmosPipeColor + color: '#B342F5FF' - uid: 11362 components: - type: Transform @@ -90877,6 +91787,77 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#FF1212FF' + - uid: 11572 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 66.5,-5.5 + parent: 5350 + - type: AtmosPipeColor + color: '#B342F5FF' + - uid: 11635 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 64.5,-5.5 + parent: 5350 + - type: AtmosPipeColor + color: '#B342F5FF' + - uid: 11642 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 65.5,-5.5 + parent: 5350 + - type: AtmosPipeColor + color: '#B342F5FF' + - uid: 11724 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 66.5,-9.5 + parent: 5350 + - type: AtmosPipeColor + color: '#B342F5FF' + - uid: 11730 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 65.5,-9.5 + parent: 5350 + - type: AtmosPipeColor + color: '#B342F5FF' + - uid: 11754 + components: + - type: Transform + pos: 61.5,-22.5 + parent: 5350 + - type: AtmosPipeColor + color: '#03FCD3FF' + - uid: 11758 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 62.5,-20.5 + parent: 5350 + - type: AtmosPipeColor + color: '#03FCD3FF' + - uid: 11760 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 63.5,-21.5 + parent: 5350 + - type: AtmosPipeColor + color: '#947507FF' + - uid: 11762 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 61.5,-23.5 + parent: 5350 + - type: AtmosPipeColor + color: '#03FCD3FF' - uid: 11779 components: - type: Transform @@ -101136,6 +102117,326 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#0055CCFF' + - uid: 26786 + components: + - type: Transform + pos: 61.5,-21.5 + parent: 5350 + - type: AtmosPipeColor + color: '#03FCD3FF' + - uid: 27070 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 69.5,-39.5 + parent: 5350 + - uid: 27074 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 66.5,-39.5 + parent: 5350 + - uid: 27156 + components: + - type: Transform + pos: 74.5,-39.5 + parent: 5350 + - uid: 27191 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 71.5,-39.5 + parent: 5350 + - uid: 27192 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 73.5,-39.5 + parent: 5350 + - uid: 27194 + components: + - type: Transform + pos: 73.5,-38.5 + parent: 5350 + - uid: 27196 + components: + - type: Transform + pos: 71.5,-38.5 + parent: 5350 + - uid: 27201 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 64.5,-21.5 + parent: 5350 + - type: AtmosPipeColor + color: '#947507FF' + - uid: 27202 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 65.5,-21.5 + parent: 5350 + - type: AtmosPipeColor + color: '#947507FF' + - uid: 27203 + components: + - type: Transform + pos: 66.5,-22.5 + parent: 5350 + - type: AtmosPipeColor + color: '#947507FF' + - uid: 27204 + components: + - type: Transform + pos: 66.5,-23.5 + parent: 5350 + - type: AtmosPipeColor + color: '#947507FF' + - uid: 27205 + components: + - type: Transform + pos: 66.5,-24.5 + parent: 5350 + - type: AtmosPipeColor + color: '#947507FF' + - uid: 27206 + components: + - type: Transform + pos: 66.5,-25.5 + parent: 5350 + - type: AtmosPipeColor + color: '#947507FF' + - uid: 27207 + components: + - type: Transform + pos: 66.5,-26.5 + parent: 5350 + - type: AtmosPipeColor + color: '#947507FF' + - uid: 27208 + components: + - type: Transform + pos: 66.5,-27.5 + parent: 5350 + - type: AtmosPipeColor + color: '#947507FF' + - uid: 27209 + components: + - type: Transform + pos: 66.5,-28.5 + parent: 5350 + - type: AtmosPipeColor + color: '#947507FF' + - uid: 27215 + components: + - type: Transform + pos: 63.5,-25.5 + parent: 5350 + - type: AtmosPipeColor + color: '#0055CCFF' + - uid: 27216 + components: + - type: Transform + pos: 63.5,-26.5 + parent: 5350 + - type: AtmosPipeColor + color: '#0055CCFF' + - uid: 27217 + components: + - type: Transform + pos: 63.5,-27.5 + parent: 5350 + - type: AtmosPipeColor + color: '#0055CCFF' + - uid: 27218 + components: + - type: Transform + pos: 63.5,-28.5 + parent: 5350 + - type: AtmosPipeColor + color: '#0055CCFF' + - uid: 27219 + components: + - type: Transform + pos: 63.5,-29.5 + parent: 5350 + - type: AtmosPipeColor + color: '#0055CCFF' + - uid: 27220 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 65.5,-30.5 + parent: 5350 + - type: AtmosPipeColor + color: '#0055CCFF' + - uid: 27221 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 67.5,-30.5 + parent: 5350 + - type: AtmosPipeColor + color: '#0055CCFF' + - uid: 27222 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 68.5,-30.5 + parent: 5350 + - type: AtmosPipeColor + color: '#0055CCFF' + - uid: 27223 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 68.5,-29.5 + parent: 5350 + - type: AtmosPipeColor + color: '#FF1212FF' + - uid: 27224 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 66.5,-29.5 + parent: 5350 + - type: AtmosPipeColor + color: '#FF1212FF' + - uid: 27225 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 67.5,-29.5 + parent: 5350 + - type: AtmosPipeColor + color: '#FF1212FF' + - uid: 27226 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 65.5,-29.5 + parent: 5350 + - type: AtmosPipeColor + color: '#FF1212FF' + - uid: 27227 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 66.5,-30.5 + parent: 5350 + - type: AtmosPipeColor + color: '#0055CCFF' + - uid: 27228 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 64.5,-30.5 + parent: 5350 + - type: AtmosPipeColor + color: '#0055CCFF' + - uid: 27232 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 69.5,-29.5 + parent: 5350 + - type: AtmosPipeColor + color: '#FF1212FF' + - uid: 27234 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 70.5,-29.5 + parent: 5350 + - type: AtmosPipeColor + color: '#FF1212FF' + - uid: 27235 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 71.5,-29.5 + parent: 5350 + - type: AtmosPipeColor + color: '#FF1212FF' + - uid: 27236 + components: + - type: Transform + pos: 72.5,-30.5 + parent: 5350 + - type: AtmosPipeColor + color: '#FF1212FF' + - uid: 27237 + components: + - type: Transform + pos: 66.5,-29.5 + parent: 5350 + - type: AtmosPipeColor + color: '#947507FF' + - uid: 27238 + components: + - type: Transform + pos: 66.5,-30.5 + parent: 5350 + - type: AtmosPipeColor + color: '#947507FF' + - uid: 27239 + components: + - type: Transform + pos: 66.5,-31.5 + parent: 5350 + - type: AtmosPipeColor + color: '#947507FF' + - uid: 27240 + components: + - type: Transform + pos: 64.5,-28.5 + parent: 5350 + - type: AtmosPipeColor + color: '#FF1212FF' + - uid: 27241 + components: + - type: Transform + pos: 64.5,-27.5 + parent: 5350 + - type: AtmosPipeColor + color: '#FF1212FF' + - uid: 27242 + components: + - type: Transform + pos: 64.5,-26.5 + parent: 5350 + - type: AtmosPipeColor + color: '#FF1212FF' + - uid: 27243 + components: + - type: Transform + pos: 64.5,-25.5 + parent: 5350 + - type: AtmosPipeColor + color: '#FF1212FF' + - uid: 27244 + components: + - type: Transform + pos: 64.5,-24.5 + parent: 5350 + - type: AtmosPipeColor + color: '#FF1212FF' + - uid: 27245 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 63.5,-23.5 + parent: 5350 + - type: AtmosPipeColor + color: '#FF1212FF' + - uid: 27256 + components: + - type: Transform + pos: 66.5,-32.5 + parent: 5350 + - type: AtmosPipeColor + color: '#947507FF' - proto: GasPipeTJunction entities: - uid: 265 @@ -103313,6 +104614,14 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#0055CCFF' + - uid: 10933 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 57.5,-5.5 + parent: 5350 + - type: AtmosPipeColor + color: '#03FCD3FF' - uid: 10950 components: - type: Transform @@ -103399,27 +104708,11 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#03FCD3FF' - - uid: 11097 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: 63.5,-24.5 - parent: 5350 - - type: AtmosPipeColor - color: '#03FCD3FF' - - uid: 11130 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 63.5,-9.5 - parent: 5350 - - type: AtmosPipeColor - color: '#03FCD3FF' - - uid: 11134 + - uid: 11115 components: - type: Transform rot: -1.5707963267948966 rad - pos: 63.5,-5.5 + pos: 63.5,-10.5 parent: 5350 - type: AtmosPipeColor color: '#03FCD3FF' @@ -104685,6 +105978,30 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#0055CCFF' + - uid: 27187 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 71.5,-41.5 + parent: 5350 + - uid: 27188 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 73.5,-41.5 + parent: 5350 + - uid: 27189 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 71.5,-40.5 + parent: 5350 + - uid: 27190 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 73.5,-40.5 + parent: 5350 - proto: GasPort entities: - uid: 8245 @@ -104717,11 +106034,6 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#FF1212FF' - - uid: 9029 - components: - - type: Transform - pos: 63.5,-4.5 - parent: 5350 - uid: 10163 components: - type: Transform @@ -104752,6 +106064,13 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#0055CCFF' + - uid: 10932 + components: + - type: Transform + pos: 57.5,-4.5 + parent: 5350 + - type: AtmosPipeColor + color: '#03FCD3FF' - uid: 10946 components: - type: Transform @@ -104784,16 +106103,6 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#03FCD3FF' - - uid: 11243 - components: - - type: Transform - pos: 68.5,-27.5 - parent: 5350 - - uid: 11244 - components: - - type: Transform - pos: 70.5,-27.5 - parent: 5350 - uid: 11438 components: - type: Transform @@ -104940,12 +106249,6 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#0055CCFF' - - uid: 2682 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 63.5,-12.5 - parent: 5350 - uid: 3130 components: - type: Transform @@ -104954,12 +106257,6 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#FF1212FF' - - uid: 3186 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 63.5,-6.5 - parent: 5350 - uid: 10543 components: - type: Transform @@ -104972,50 +106269,51 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#0055CCFF' - - uid: 10966 + - uid: 10817 components: - type: Transform rot: 1.5707963267948966 rad - pos: 63.5,-20.5 - parent: 5350 - - uid: 10967 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 54.5,-20.5 + pos: 63.5,-15.5 parent: 5350 - - uid: 10968 + - type: AtmosPipeColor + color: '#27E312FF' + - uid: 10824 components: - type: Transform rot: -1.5707963267948966 rad - pos: 51.5,-21.5 + pos: 63.5,-9.5 parent: 5350 - type: AtmosPipeColor - color: '#FF1212FF' - - uid: 10969 + color: '#B342F5FF' + - uid: 10934 components: - type: Transform - rot: 1.5707963267948966 rad - pos: 63.5,-16.5 + pos: 57.5,-6.5 parent: 5350 - - uid: 10970 + - type: AtmosPipeColor + color: '#03FCD3FF' + - uid: 10967 components: - type: Transform rot: -1.5707963267948966 rad - pos: 63.5,-10.5 + pos: 54.5,-20.5 parent: 5350 - - uid: 10971 + - uid: 10968 components: - type: Transform rot: -1.5707963267948966 rad - pos: 63.5,-14.5 + pos: 51.5,-21.5 parent: 5350 - - uid: 10972 + - type: AtmosPipeColor + color: '#FF1212FF' + - uid: 10991 components: - type: Transform - rot: -1.5707963267948966 rad - pos: 63.5,-18.5 + rot: 1.5707963267948966 rad + pos: 63.5,-7.5 parent: 5350 + - type: AtmosPipeColor + color: '#27E312FF' - uid: 11006 components: - type: Transform @@ -105029,12 +106327,14 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#FF1212FF' - - uid: 11015 + - uid: 11040 components: - type: Transform - rot: 1.5707963267948966 rad - pos: 63.5,-8.5 + rot: -1.5707963267948966 rad + pos: 63.5,-5.5 parent: 5350 + - type: AtmosPipeColor + color: '#B342F5FF' - uid: 11124 components: - type: Transform @@ -105043,25 +106343,38 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#03FCD3FF' - - uid: 11138 + - uid: 11161 components: - type: Transform - rot: -1.5707963267948966 rad - pos: 61.5,-4.5 + rot: 1.5707963267948966 rad + pos: 63.5,-19.5 parent: 5350 - type: AtmosPipeColor - color: '#0055CCFF' - - uid: 11249 + color: '#27E312FF' + - uid: 11280 components: - type: Transform - pos: 68.5,-28.5 + rot: 1.5707963267948966 rad + pos: 62.5,-24.5 parent: 5350 - - uid: 11250 + - type: AtmosPipeColor + color: '#03FCD3FF' + - uid: 11304 components: - type: Transform - rot: 3.141592653589793 rad - pos: 70.5,-28.5 + rot: -1.5707963267948966 rad + pos: 63.5,-17.5 + parent: 5350 + - type: AtmosPipeColor + color: '#B342F5FF' + - uid: 11355 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 63.5,-11.5 parent: 5350 + - type: AtmosPipeColor + color: '#27E312FF' - uid: 11428 components: - type: Transform @@ -105085,6 +106398,14 @@ entities: - type: Transform pos: 43.5,-28.5 parent: 5350 + - uid: 11600 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 63.5,-13.5 + parent: 5350 + - type: AtmosPipeColor + color: '#B342F5FF' - uid: 13461 components: - type: Transform @@ -105141,6 +106462,22 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#0055CCFF' + - uid: 27071 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 69.5,-38.5 + parent: 5350 + - uid: 27128 + components: + - type: Transform + pos: 66.5,-38.5 + parent: 5350 + - uid: 27193 + components: + - type: Transform + pos: 74.5,-38.5 + parent: 5350 - proto: GasThermoMachineFreezer entities: - uid: 2630 @@ -105183,6 +106520,12 @@ entities: - type: Transform pos: 29.5,-38.5 parent: 5350 + - uid: 27195 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 72.5,-38.5 + parent: 5350 - proto: GasThermoMachineHeater entities: - uid: 11366 @@ -105941,14 +107284,6 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#0055CCFF' - - uid: 11242 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 69.5,-24.5 - parent: 5350 - - type: AtmosPipeColor - color: '#03FCD3FF' - uid: 11867 components: - type: Transform @@ -106865,6 +108200,17 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#0055CCFF' + - uid: 27210 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 69.5,-31.5 + parent: 5350 + - type: DeviceNetwork + deviceLists: + - 11752 + - type: AtmosPipeColor + color: '#0055CCFF' - proto: GasVentScrubber entities: - uid: 755 @@ -108252,6 +109598,17 @@ entities: parent: 5350 - type: AtmosPipeColor color: '#FF1212FF' + - uid: 27212 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 72.5,-31.5 + parent: 5350 + - type: DeviceNetwork + deviceLists: + - 11752 + - type: AtmosPipeColor + color: '#FF1212FF' - proto: GasVolumePump entities: - uid: 10948 @@ -110751,6 +112108,36 @@ entities: - type: Transform pos: -4.5,16.5 parent: 5350 + - uid: 10823 + components: + - type: Transform + pos: 66.5,-19.5 + parent: 5350 + - uid: 10827 + components: + - type: Transform + pos: 66.5,-18.5 + parent: 5350 + - uid: 10835 + components: + - type: Transform + pos: 70.5,-28.5 + parent: 5350 + - uid: 10843 + components: + - type: Transform + pos: 64.5,-25.5 + parent: 5350 + - uid: 10844 + components: + - type: Transform + pos: 61.5,-25.5 + parent: 5350 + - uid: 10944 + components: + - type: Transform + pos: 66.5,-17.5 + parent: 5350 - uid: 11034 components: - type: Transform @@ -110771,65 +112158,95 @@ entities: - type: Transform pos: 63.5,1.5 parent: 5350 - - uid: 11309 + - uid: 11168 components: - type: Transform - pos: 66.5,-8.5 + pos: 66.5,-9.5 parent: 5350 - - uid: 11310 + - uid: 11171 components: - type: Transform - pos: 66.5,-7.5 + pos: 66.5,-10.5 parent: 5350 - - uid: 11311 + - uid: 11242 components: - type: Transform - pos: 66.5,-6.5 + pos: 64.5,-18.5 parent: 5350 - - uid: 11312 + - uid: 11243 components: - type: Transform - pos: 66.5,-12.5 + pos: 64.5,-6.5 parent: 5350 - - uid: 11313 + - uid: 11244 components: - type: Transform - pos: 66.5,-11.5 + pos: 64.5,-16.5 parent: 5350 - - uid: 11314 + - uid: 11245 components: - type: Transform - pos: 66.5,-10.5 + pos: 64.5,-15.5 parent: 5350 - - uid: 11315 + - uid: 11246 components: - type: Transform - pos: 66.5,-16.5 + pos: 64.5,-14.5 parent: 5350 - - uid: 11316 + - uid: 11247 components: - type: Transform - pos: 66.5,-15.5 + pos: 64.5,-13.5 parent: 5350 - - uid: 11317 + - uid: 11248 components: - type: Transform - pos: 66.5,-14.5 + pos: 64.5,-12.5 parent: 5350 - - uid: 11318 + - uid: 11249 components: - type: Transform - pos: 66.5,-20.5 + pos: 64.5,-11.5 parent: 5350 - - uid: 11319 + - uid: 11250 components: - type: Transform - pos: 66.5,-19.5 + pos: 64.5,-10.5 parent: 5350 - - uid: 11320 + - uid: 11251 components: - type: Transform - pos: 66.5,-18.5 + pos: 64.5,-9.5 + parent: 5350 + - uid: 11252 + components: + - type: Transform + pos: 64.5,-7.5 + parent: 5350 + - uid: 11253 + components: + - type: Transform + pos: 64.5,-8.5 + parent: 5350 + - uid: 11255 + components: + - type: Transform + pos: 64.5,-5.5 + parent: 5350 + - uid: 11269 + components: + - type: Transform + pos: 64.5,-17.5 + parent: 5350 + - uid: 11302 + components: + - type: Transform + pos: 66.5,-11.5 + parent: 5350 + - uid: 11311 + components: + - type: Transform + pos: 66.5,-6.5 parent: 5350 - uid: 11321 components: @@ -110931,110 +112348,65 @@ entities: - type: Transform pos: 60.5,-25.5 parent: 5350 - - uid: 11341 - components: - - type: Transform - pos: 61.5,-25.5 - parent: 5350 - - uid: 11342 - components: - - type: Transform - pos: 64.5,-20.5 - parent: 5350 - uid: 11343 components: - type: Transform - pos: 64.5,-19.5 + pos: 66.5,-5.5 parent: 5350 - uid: 11344 components: - type: Transform - pos: 64.5,-18.5 - parent: 5350 - - uid: 11345 - components: - - type: Transform - pos: 64.5,-17.5 - parent: 5350 - - uid: 11346 - components: - - type: Transform - pos: 64.5,-16.5 - parent: 5350 - - uid: 11347 - components: - - type: Transform - pos: 64.5,-15.5 - parent: 5350 - - uid: 11348 - components: - - type: Transform - pos: 64.5,-14.5 - parent: 5350 - - uid: 11349 - components: - - type: Transform - pos: 64.5,-13.5 - parent: 5350 - - uid: 11350 - components: - - type: Transform - pos: 64.5,-12.5 - parent: 5350 - - uid: 11351 - components: - - type: Transform - pos: 64.5,-11.5 + pos: 66.5,-13.5 parent: 5350 - - uid: 11352 + - uid: 11356 components: - type: Transform - pos: 64.5,-10.5 + pos: 66.5,-7.5 parent: 5350 - - uid: 11353 + - uid: 11357 components: - type: Transform - pos: 64.5,-9.5 + pos: 53.5,-9.5 parent: 5350 - - uid: 11354 + - uid: 11358 components: - type: Transform - pos: 64.5,-8.5 + pos: 55.5,-9.5 parent: 5350 - - uid: 11355 + - uid: 11359 components: - type: Transform - pos: 64.5,-7.5 + pos: 56.5,-9.5 parent: 5350 - - uid: 11356 + - uid: 11501 components: - type: Transform - pos: 64.5,-6.5 + pos: 43.5,-29.5 parent: 5350 - - uid: 11357 + - uid: 11502 components: - type: Transform - pos: 53.5,-9.5 + pos: 48.5,-26.5 parent: 5350 - - uid: 11358 + - uid: 11628 components: - type: Transform - pos: 55.5,-9.5 + pos: 66.5,-14.5 parent: 5350 - - uid: 11359 + - uid: 11693 components: - type: Transform - pos: 56.5,-9.5 + pos: 64.5,-21.5 parent: 5350 - - uid: 11501 + - uid: 11725 components: - type: Transform - pos: 43.5,-29.5 + pos: 66.5,-15.5 parent: 5350 - - uid: 11502 + - uid: 11736 components: - type: Transform - pos: 48.5,-26.5 + pos: 64.5,-19.5 parent: 5350 - uid: 12099 components: @@ -115266,6 +116638,681 @@ entities: - type: Transform pos: -13.5,63.5 parent: 26973 + - uid: 27035 + components: + - type: Transform + pos: 74.5,-29.5 + parent: 5350 + - uid: 27036 + components: + - type: Transform + pos: 74.5,-30.5 + parent: 5350 + - uid: 27064 + components: + - type: Transform + pos: 67.5,-39.5 + parent: 5350 + - uid: 27116 + components: + - type: Transform + pos: 66.5,-39.5 + parent: 5350 + - uid: 27129 + components: + - type: Transform + pos: 68.5,-39.5 + parent: 5350 + - uid: 27130 + components: + - type: Transform + pos: 69.5,-39.5 + parent: 5350 + - uid: 27137 + components: + - type: Transform + pos: 73.5,-39.5 + parent: 5350 + - uid: 27138 + components: + - type: Transform + pos: 65.5,-30.5 + parent: 5350 + - uid: 27142 + components: + - type: Transform + pos: 65.5,-29.5 + parent: 5350 + - uid: 27151 + components: + - type: Transform + pos: 74.5,-39.5 + parent: 5350 + - uid: 27162 + components: + - type: Transform + pos: 71.5,-39.5 + parent: 5350 + - uid: 27163 + components: + - type: Transform + pos: 72.5,-39.5 + parent: 5350 + - uid: 27177 + components: + - type: Transform + pos: 63.5,-25.5 + parent: 5350 + - uid: 27251 + components: + - type: Transform + pos: 82.5,-27.5 + parent: 5350 + - uid: 27264 + components: + - type: Transform + pos: 66.5,-22.5 + parent: 5350 + - uid: 27286 + components: + - type: Transform + pos: 82.5,-26.5 + parent: 5350 + - uid: 27287 + components: + - type: Transform + pos: 81.5,-26.5 + parent: 5350 + - uid: 27289 + components: + - type: Transform + pos: 82.5,-28.5 + parent: 5350 + - uid: 27291 + components: + - type: Transform + pos: 82.5,-30.5 + parent: 5350 + - uid: 27292 + components: + - type: Transform + pos: 82.5,-32.5 + parent: 5350 + - uid: 27293 + components: + - type: Transform + pos: 82.5,-33.5 + parent: 5350 + - uid: 27294 + components: + - type: Transform + pos: 82.5,-31.5 + parent: 5350 + - uid: 27295 + components: + - type: Transform + pos: 82.5,-34.5 + parent: 5350 + - uid: 27297 + components: + - type: Transform + pos: 82.5,-37.5 + parent: 5350 + - uid: 27298 + components: + - type: Transform + pos: 82.5,-35.5 + parent: 5350 + - uid: 27299 + components: + - type: Transform + pos: 82.5,-38.5 + parent: 5350 + - uid: 27301 + components: + - type: Transform + pos: 82.5,-39.5 + parent: 5350 + - uid: 27302 + components: + - type: Transform + pos: 82.5,-41.5 + parent: 5350 + - uid: 27303 + components: + - type: Transform + pos: 82.5,-42.5 + parent: 5350 + - uid: 27304 + components: + - type: Transform + pos: 82.5,-43.5 + parent: 5350 + - uid: 27306 + components: + - type: Transform + pos: 82.5,-45.5 + parent: 5350 + - uid: 27307 + components: + - type: Transform + pos: 82.5,-46.5 + parent: 5350 + - uid: 27308 + components: + - type: Transform + pos: 82.5,-47.5 + parent: 5350 + - uid: 27309 + components: + - type: Transform + pos: 82.5,-49.5 + parent: 5350 + - uid: 27310 + components: + - type: Transform + pos: 82.5,-48.5 + parent: 5350 + - uid: 27311 + components: + - type: Transform + pos: 81.5,-49.5 + parent: 5350 + - uid: 27313 + components: + - type: Transform + pos: 78.5,-49.5 + parent: 5350 + - uid: 27314 + components: + - type: Transform + pos: 80.5,-49.5 + parent: 5350 + - uid: 27315 + components: + - type: Transform + pos: 76.5,-49.5 + parent: 5350 + - uid: 27316 + components: + - type: Transform + pos: 77.5,-49.5 + parent: 5350 + - uid: 27317 + components: + - type: Transform + pos: 75.5,-49.5 + parent: 5350 + - uid: 27319 + components: + - type: Transform + pos: 73.5,-49.5 + parent: 5350 + - uid: 27320 + components: + - type: Transform + pos: 72.5,-49.5 + parent: 5350 + - uid: 27322 + components: + - type: Transform + pos: 70.5,-49.5 + parent: 5350 + - uid: 27323 + components: + - type: Transform + pos: 69.5,-49.5 + parent: 5350 + - uid: 27324 + components: + - type: Transform + pos: 68.5,-49.5 + parent: 5350 + - uid: 27325 + components: + - type: Transform + pos: 67.5,-49.5 + parent: 5350 + - uid: 27326 + components: + - type: Transform + pos: 66.5,-49.5 + parent: 5350 + - uid: 27328 + components: + - type: Transform + pos: 64.5,-49.5 + parent: 5350 + - uid: 27329 + components: + - type: Transform + pos: 63.5,-49.5 + parent: 5350 + - uid: 27330 + components: + - type: Transform + pos: 62.5,-49.5 + parent: 5350 + - uid: 27331 + components: + - type: Transform + pos: 61.5,-49.5 + parent: 5350 + - uid: 27332 + components: + - type: Transform + pos: 60.5,-49.5 + parent: 5350 + - uid: 27333 + components: + - type: Transform + pos: 60.5,-48.5 + parent: 5350 + - uid: 27335 + components: + - type: Transform + pos: 60.5,-46.5 + parent: 5350 + - uid: 27336 + components: + - type: Transform + pos: 60.5,-45.5 + parent: 5350 + - uid: 27337 + components: + - type: Transform + pos: 60.5,-44.5 + parent: 5350 + - uid: 27339 + components: + - type: Transform + pos: 60.5,-42.5 + parent: 5350 + - uid: 27340 + components: + - type: Transform + pos: 60.5,-41.5 + parent: 5350 + - uid: 27341 + components: + - type: Transform + pos: 60.5,-40.5 + parent: 5350 + - uid: 27342 + components: + - type: Transform + pos: 60.5,-39.5 + parent: 5350 + - uid: 27344 + components: + - type: Transform + pos: 60.5,-37.5 + parent: 5350 + - uid: 27345 + components: + - type: Transform + pos: 60.5,-36.5 + parent: 5350 + - uid: 27346 + components: + - type: Transform + pos: 50.5,-34.5 + parent: 5350 + - uid: 27347 + components: + - type: Transform + pos: 51.5,-34.5 + parent: 5350 + - uid: 27348 + components: + - type: Transform + pos: 52.5,-34.5 + parent: 5350 + - uid: 27350 + components: + - type: Transform + pos: 54.5,-34.5 + parent: 5350 + - uid: 27351 + components: + - type: Transform + pos: 55.5,-34.5 + parent: 5350 + - uid: 27353 + components: + - type: Transform + pos: 57.5,-34.5 + parent: 5350 + - uid: 27355 + components: + - type: Transform + pos: 59.5,-34.5 + parent: 5350 + - uid: 27356 + components: + - type: Transform + pos: 60.5,-34.5 + parent: 5350 + - uid: 27357 + components: + - type: Transform + pos: 61.5,-34.5 + parent: 5350 + - uid: 27358 + components: + - type: Transform + pos: 62.5,-34.5 + parent: 5350 + - uid: 27359 + components: + - type: Transform + pos: 50.5,-36.5 + parent: 5350 + - uid: 27360 + components: + - type: Transform + pos: 51.5,-36.5 + parent: 5350 + - uid: 27362 + components: + - type: Transform + pos: 53.5,-36.5 + parent: 5350 + - uid: 27363 + components: + - type: Transform + pos: 54.5,-36.5 + parent: 5350 + - uid: 27364 + components: + - type: Transform + pos: 55.5,-36.5 + parent: 5350 + - uid: 27366 + components: + - type: Transform + pos: 57.5,-36.5 + parent: 5350 + - uid: 27367 + components: + - type: Transform + pos: 58.5,-36.5 + parent: 5350 + - uid: 27368 + components: + - type: Transform + pos: 59.5,-36.5 + parent: 5350 + - uid: 27369 + components: + - type: Transform + pos: 79.5,-28.5 + parent: 5350 + - uid: 27370 + components: + - type: Transform + pos: 62.5,-36.5 + parent: 5350 + - uid: 27371 + components: + - type: Transform + pos: 62.5,-37.5 + parent: 5350 + - uid: 27372 + components: + - type: Transform + pos: 62.5,-38.5 + parent: 5350 + - uid: 27374 + components: + - type: Transform + pos: 62.5,-40.5 + parent: 5350 + - uid: 27375 + components: + - type: Transform + pos: 62.5,-41.5 + parent: 5350 + - uid: 27376 + components: + - type: Transform + pos: 62.5,-42.5 + parent: 5350 + - uid: 27378 + components: + - type: Transform + pos: 62.5,-44.5 + parent: 5350 + - uid: 27379 + components: + - type: Transform + pos: 62.5,-45.5 + parent: 5350 + - uid: 27381 + components: + - type: Transform + pos: 62.5,-47.5 + parent: 5350 + - uid: 27382 + components: + - type: Transform + pos: 63.5,-47.5 + parent: 5350 + - uid: 27383 + components: + - type: Transform + pos: 79.5,-39.5 + parent: 5350 + - uid: 27384 + components: + - type: Transform + pos: 65.5,-47.5 + parent: 5350 + - uid: 27385 + components: + - type: Transform + pos: 66.5,-47.5 + parent: 5350 + - uid: 27387 + components: + - type: Transform + pos: 68.5,-47.5 + parent: 5350 + - uid: 27388 + components: + - type: Transform + pos: 69.5,-47.5 + parent: 5350 + - uid: 27390 + components: + - type: Transform + pos: 72.5,-47.5 + parent: 5350 + - uid: 27391 + components: + - type: Transform + pos: 71.5,-47.5 + parent: 5350 + - uid: 27392 + components: + - type: Transform + pos: 73.5,-47.5 + parent: 5350 + - uid: 27393 + components: + - type: Transform + pos: 74.5,-47.5 + parent: 5350 + - uid: 27394 + components: + - type: Transform + pos: 75.5,-47.5 + parent: 5350 + - uid: 27395 + components: + - type: Transform + pos: 76.5,-47.5 + parent: 5350 + - uid: 27396 + components: + - type: Transform + pos: 77.5,-47.5 + parent: 5350 + - uid: 27398 + components: + - type: Transform + pos: 79.5,-47.5 + parent: 5350 + - uid: 27399 + components: + - type: Transform + pos: 80.5,-47.5 + parent: 5350 + - uid: 27400 + components: + - type: Transform + pos: 80.5,-31.5 + parent: 5350 + - uid: 27401 + components: + - type: Transform + pos: 80.5,-30.5 + parent: 5350 + - uid: 27402 + components: + - type: Transform + pos: 80.5,-29.5 + parent: 5350 + - uid: 27404 + components: + - type: Transform + pos: 80.5,-46.5 + parent: 5350 + - uid: 27406 + components: + - type: Transform + pos: 80.5,-43.5 + parent: 5350 + - uid: 27407 + components: + - type: Transform + pos: 80.5,-45.5 + parent: 5350 + - uid: 27408 + components: + - type: Transform + pos: 80.5,-42.5 + parent: 5350 + - uid: 27409 + components: + - type: Transform + pos: 80.5,-41.5 + parent: 5350 + - uid: 27410 + components: + - type: Transform + pos: 80.5,-40.5 + parent: 5350 + - uid: 27412 + components: + - type: Transform + pos: 80.5,-38.5 + parent: 5350 + - uid: 27413 + components: + - type: Transform + pos: 80.5,-37.5 + parent: 5350 + - uid: 27414 + components: + - type: Transform + pos: 80.5,-36.5 + parent: 5350 + - uid: 27415 + components: + - type: Transform + pos: 80.5,-35.5 + parent: 5350 + - uid: 27416 + components: + - type: Transform + pos: 80.5,-34.5 + parent: 5350 + - uid: 27418 + components: + - type: Transform + pos: 80.5,-32.5 + parent: 5350 + - uid: 27419 + components: + - type: Transform + pos: 78.5,-28.5 + parent: 5350 + - uid: 27420 + components: + - type: Transform + pos: 77.5,-28.5 + parent: 5350 + - uid: 27421 + components: + - type: Transform + pos: 79.5,-26.5 + parent: 5350 + - uid: 27422 + components: + - type: Transform + pos: 79.5,-44.5 + parent: 5350 + - uid: 27441 + components: + - type: Transform + pos: 79.5,-33.5 + parent: 5350 + - uid: 27460 + components: + - type: Transform + pos: 79.5,-36.5 + parent: 5350 + - uid: 27470 + components: + - type: Transform + pos: 78.5,-46.5 + parent: 5350 + - uid: 27471 + components: + - type: Transform + pos: 75.5,-46.5 + parent: 5350 + - uid: 27472 + components: + - type: Transform + pos: 70.5,-46.5 + parent: 5350 + - uid: 27473 + components: + - type: Transform + pos: 67.5,-46.5 + parent: 5350 + - uid: 27474 + components: + - type: Transform + pos: 64.5,-46.5 + parent: 5350 + - uid: 27475 + components: + - type: Transform + pos: 63.5,-43.5 + parent: 5350 + - uid: 27476 + components: + - type: Transform + pos: 63.5,-39.5 + parent: 5350 + - uid: 27477 + components: + - type: Transform + pos: 63.5,-35.5 + parent: 5350 - proto: GrilleBroken entities: - uid: 2073 @@ -115575,6 +117622,161 @@ entities: rot: -1.5707963267948966 rad pos: 41.5,60.5 parent: 5350 + - uid: 27288 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 60.5,-47.5 + parent: 5350 + - uid: 27290 + components: + - type: Transform + pos: 60.5,-38.5 + parent: 5350 + - uid: 27296 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 74.5,-49.5 + parent: 5350 + - uid: 27300 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 79.5,-49.5 + parent: 5350 + - uid: 27305 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 82.5,-44.5 + parent: 5350 + - uid: 27312 + components: + - type: Transform + pos: 82.5,-36.5 + parent: 5350 + - uid: 27318 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 80.5,-28.5 + parent: 5350 + - uid: 27321 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 80.5,-26.5 + parent: 5350 + - uid: 27327 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 80.5,-39.5 + parent: 5350 + - uid: 27334 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 67.5,-47.5 + parent: 5350 + - uid: 27338 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 56.5,-34.5 + parent: 5350 + - uid: 27343 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 62.5,-43.5 + parent: 5350 + - uid: 27349 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 52.5,-36.5 + parent: 5350 + - uid: 27352 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 56.5,-36.5 + parent: 5350 + - uid: 27354 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 53.5,-34.5 + parent: 5350 + - uid: 27361 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 58.5,-34.5 + parent: 5350 + - uid: 27365 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 82.5,-29.5 + parent: 5350 + - uid: 27373 + components: + - type: Transform + pos: 62.5,-46.5 + parent: 5350 + - uid: 27377 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 70.5,-47.5 + parent: 5350 + - uid: 27380 + components: + - type: Transform + pos: 80.5,-44.5 + parent: 5350 + - uid: 27386 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 80.5,-33.5 + parent: 5350 + - uid: 27389 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 78.5,-47.5 + parent: 5350 + - uid: 27397 + components: + - type: Transform + pos: 60.5,-43.5 + parent: 5350 + - uid: 27403 + components: + - type: Transform + pos: 82.5,-40.5 + parent: 5350 + - uid: 27405 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 71.5,-49.5 + parent: 5350 + - uid: 27411 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 65.5,-49.5 + parent: 5350 + - uid: 27417 + components: + - type: Transform + pos: 62.5,-39.5 + parent: 5350 - proto: GroundCannabis entities: - uid: 24640 @@ -115757,6 +117959,26 @@ entities: - type: Transform pos: 29.518621,-60.391666 parent: 5350 +- proto: HeatExchanger + entities: + - uid: 27166 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 72.5,-40.5 + parent: 5350 + - uid: 27167 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 72.5,-41.5 + parent: 5350 + - uid: 27168 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 72.5,-42.5 + parent: 5350 - proto: HighSecCommandLocked entities: - uid: 1668 @@ -115800,6 +118022,12 @@ entities: - type: Transform pos: -34.462692,34.496433 parent: 5350 + - uid: 27051 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 72.83539,-31.5 + parent: 5350 - proto: HospitalCurtainsOpen entities: - uid: 7215 @@ -116304,6 +118532,11 @@ entities: - type: Transform pos: 100.5,10.5 parent: 5350 + - uid: 27015 + components: + - type: Transform + pos: 72.5,-28.5 + parent: 5350 - proto: IntercomMedical entities: - uid: 14165 @@ -116985,6 +119218,28 @@ entities: - Pressed: Toggle 14794: - Pressed: Toggle +- proto: LockerAtmospherics + entities: + - uid: 27084 + components: + - type: Transform + pos: 73.5,-29.5 + parent: 5350 + - type: ContainerContainer + containers: + entity_storage: !type:Container + showEnts: False + occludes: True + ents: + - 27085 + - 27091 + - 27097 + - 27098 + - 27099 + paper_label: !type:ContainerSlot + showEnts: False + occludes: True + ent: null - proto: LockerAtmosphericsFilled entities: - uid: 9033 @@ -119628,6 +121883,11 @@ entities: - type: Transform pos: 41.5,31.5 parent: 5350 + - uid: 27088 + components: + - type: Transform + pos: 76.5,-34.5 + parent: 5350 - proto: NitrogenTankFilled entities: - uid: 15569 @@ -119640,6 +121900,13 @@ entities: - type: Transform pos: -15.399836,-58.48665 parent: 5350 + - uid: 27085 + components: + - type: Transform + parent: 27084 + - type: Physics + canCollide: False + - type: InsideEntityStorage - proto: NitrousOxideCanister entities: - uid: 11825 @@ -119827,6 +122094,11 @@ entities: - type: Transform pos: 55.5,24.5 parent: 5350 + - uid: 27087 + components: + - type: Transform + pos: 76.5,-33.5 + parent: 5350 - proto: OxygenTankFilled entities: - uid: 1305 @@ -119854,6 +122126,13 @@ entities: - type: Transform pos: -43.374786,23.584633 parent: 5350 + - uid: 27099 + components: + - type: Transform + parent: 27084 + - type: Physics + canCollide: False + - type: InsideEntityStorage - proto: PaintingAmogusTriptych entities: - uid: 24635 @@ -120320,11 +122599,6 @@ entities: - type: Transform pos: -42.7706,23.635101 parent: 5350 - - uid: 11275 - components: - - type: Transform - pos: 67.42234,-30.577332 - parent: 5350 - uid: 11812 components: - type: Transform @@ -120600,10 +122874,15 @@ entities: - type: Transform pos: 47.5,20.5 parent: 5350 - - uid: 11598 + - uid: 11166 components: - type: Transform - pos: 69.5,-15.5 + pos: 69.5,-14.5 + parent: 5350 + - uid: 27089 + components: + - type: Transform + pos: 76.5,-35.5 parent: 5350 - proto: PlasmaReinforcedWindowDirectional entities: @@ -122157,6 +124436,11 @@ entities: - type: Transform pos: 52.5,-3.5 parent: 5350 + - uid: 27077 + components: + - type: Transform + pos: 73.5,-31.5 + parent: 5350 - proto: PowerCellSmall entities: - uid: 22275 @@ -123112,11 +125396,23 @@ entities: parent: 5350 - type: ApcPowerReceiver powerLoad: 0 + - uid: 10928 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 65.5,-8.5 + parent: 5350 - uid: 11029 components: - type: Transform pos: 35.5,-18.5 parent: 5350 + - uid: 11256 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 63.5,-22.5 + parent: 5350 - uid: 11506 components: - type: Transform @@ -123124,6 +125420,12 @@ entities: parent: 5350 - type: ApcPowerReceiver powerLoad: 0 + - uid: 11728 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 65.5,-16.5 + parent: 5350 - uid: 12036 components: - type: Transform @@ -123171,22 +125473,6 @@ entities: parent: 5350 - type: ApcPowerReceiver powerLoad: 0 - - uid: 12043 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 65.5,-9.5 - parent: 5350 - - type: ApcPowerReceiver - powerLoad: 0 - - uid: 12044 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 65.5,-17.5 - parent: 5350 - - type: ApcPowerReceiver - powerLoad: 0 - uid: 12045 components: - type: Transform @@ -123203,14 +125489,6 @@ entities: parent: 5350 - type: ApcPowerReceiver powerLoad: 0 - - uid: 12047 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 63.5,-22.5 - parent: 5350 - - type: ApcPowerReceiver - powerLoad: 0 - uid: 12048 components: - type: Transform @@ -124741,8 +127019,42 @@ entities: rot: -1.5707963267948966 rad pos: -25.5,-23.5 parent: 5350 + - uid: 27143 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 66.5,-27.5 + parent: 5350 + - uid: 27144 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 66.5,-35.5 + parent: 5350 + - uid: 27145 + components: + - type: Transform + pos: 73.5,-29.5 + parent: 5350 + - uid: 27146 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 76.5,-37.5 + parent: 5350 + - uid: 27147 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 76.5,-33.5 + parent: 5350 - proto: PoweredlightExterior entities: + - uid: 11238 + components: + - type: Transform + pos: 76.5,-43.5 + parent: 5350 - uid: 26352 components: - type: Transform @@ -124819,6 +127131,12 @@ entities: - type: Transform pos: 76.5,1.5 parent: 5350 + - uid: 27478 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 72.5,-24.5 + parent: 5350 - proto: PoweredlightSodium entities: - uid: 23878 @@ -125166,6 +127484,12 @@ entities: parent: 5350 - type: ApcPowerReceiver powerLoad: 0 + - uid: 9029 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 69.5,-10.5 + parent: 5350 - uid: 9969 components: - type: Transform @@ -125304,13 +127628,18 @@ entities: parent: 5350 - type: ApcPowerReceiver powerLoad: 0 - - uid: 11286 + - uid: 10970 components: - type: Transform - pos: 65.5,-24.5 + rot: -1.5707963267948966 rad + pos: 69.5,-6.5 + parent: 5350 + - uid: 11303 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 69.5,-14.5 parent: 5350 - - type: ApcPowerReceiver - powerLoad: 0 - uid: 11503 components: - type: Transform @@ -125359,38 +127688,12 @@ entities: parent: 5350 - type: ApcPowerReceiver powerLoad: 0 - - uid: 11569 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 69.5,-19.5 - parent: 5350 - - type: ApcPowerReceiver - powerLoad: 0 - - uid: 11570 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 69.5,-15.5 - parent: 5350 - - type: ApcPowerReceiver - powerLoad: 0 - - uid: 11571 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 69.5,-11.5 - parent: 5350 - - type: ApcPowerReceiver - powerLoad: 0 - - uid: 11572 + - uid: 11618 components: - type: Transform rot: -1.5707963267948966 rad - pos: 69.5,-7.5 + pos: 69.5,-18.5 parent: 5350 - - type: ApcPowerReceiver - powerLoad: 0 - uid: 12024 components: - type: Transform @@ -126458,6 +128761,35 @@ entities: parent: 5350 - type: ApcPowerReceiver powerLoad: 0 + - uid: 26986 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 69.5,-27.5 + parent: 5350 + - uid: 27125 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 66.5,-42.5 + parent: 5350 + - uid: 27126 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 69.5,-42.5 + parent: 5350 + - uid: 27153 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 76.5,-41.5 + parent: 5350 + - uid: 27249 + components: + - type: Transform + pos: 69.5,-23.5 + parent: 5350 - proto: Protolathe entities: - uid: 9805 @@ -127161,6 +129493,12 @@ entities: - type: Transform pos: -64.48487,-42.241108 parent: 5350 + - uid: 27103 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 73.5,-31 + parent: 5350 - proto: Railing entities: - uid: 2182 @@ -127298,6 +129636,48 @@ entities: - type: Transform pos: -5.5,-74.5 parent: 5350 + - uid: 26987 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 67.5,-31.5 + parent: 5350 + - uid: 26988 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 68.5,-32.5 + parent: 5350 + - uid: 26989 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 69.5,-32.5 + parent: 5350 + - uid: 26990 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 70.5,-32.5 + parent: 5350 + - uid: 26991 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 71.5,-32.5 + parent: 5350 + - uid: 26992 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 72.5,-32.5 + parent: 5350 + - uid: 27007 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 73.5,-32.5 + parent: 5350 - proto: RailingCorner entities: - uid: 11026 @@ -127353,6 +129733,23 @@ entities: rot: 1.5707963267948966 rad pos: -66.5,-39.5 parent: 5350 + - uid: 26993 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 67.5,-32.5 + parent: 5350 + - uid: 27006 + components: + - type: Transform + pos: 74.5,-32.5 + parent: 5350 + - uid: 27012 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 67.5,-30.5 + parent: 5350 - proto: RandomArcade entities: - uid: 13625 @@ -128271,6 +130668,12 @@ entities: - type: Transform pos: 43.631737,8.657005 parent: 5350 + - uid: 27062 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 69.35516,-31.5 + parent: 5350 - proto: ReagentContainerFlour entities: - uid: 2240 @@ -128300,6 +130703,21 @@ entities: parent: 5350 - proto: ReinforcedPlasmaWindow entities: + - uid: 10943 + components: + - type: Transform + pos: 66.5,-17.5 + parent: 5350 + - uid: 11112 + components: + - type: Transform + pos: 66.5,-10.5 + parent: 5350 + - uid: 11113 + components: + - type: Transform + pos: 66.5,-9.5 + parent: 5350 - uid: 11288 components: - type: Transform @@ -128345,65 +130763,70 @@ entities: - type: Transform pos: 61.5,-27.5 parent: 5350 - - uid: 11297 + - uid: 11298 components: - type: Transform - pos: 66.5,-20.5 + pos: 66.5,-11.5 parent: 5350 - - uid: 11298 + - uid: 11312 + components: + - type: Transform + pos: 66.5,-5.5 + parent: 5350 + - uid: 11319 components: - type: Transform pos: 66.5,-19.5 parent: 5350 - - uid: 11299 + - uid: 11320 components: - type: Transform pos: 66.5,-18.5 parent: 5350 - - uid: 11300 + - uid: 11569 components: - type: Transform - pos: 66.5,-16.5 + pos: 66.5,-6.5 parent: 5350 - - uid: 11301 + - uid: 11634 components: - type: Transform - pos: 66.5,-15.5 + pos: 66.5,-7.5 parent: 5350 - - uid: 11302 + - uid: 11726 components: - type: Transform - pos: 66.5,-14.5 + pos: 66.5,-13.5 parent: 5350 - - uid: 11303 + - uid: 11727 components: - type: Transform - pos: 66.5,-12.5 + pos: 66.5,-14.5 parent: 5350 - - uid: 11304 + - uid: 11729 components: - type: Transform - pos: 66.5,-11.5 + pos: 66.5,-15.5 parent: 5350 - - uid: 11305 + - uid: 27131 components: - type: Transform - pos: 66.5,-10.5 + pos: 66.5,-39.5 parent: 5350 - - uid: 11306 + - uid: 27132 components: - type: Transform - pos: 66.5,-8.5 + pos: 67.5,-39.5 parent: 5350 - - uid: 11307 + - uid: 27133 components: - type: Transform - pos: 66.5,-7.5 + pos: 68.5,-39.5 parent: 5350 - - uid: 11308 + - uid: 27134 components: - type: Transform - pos: 66.5,-6.5 + pos: 69.5,-39.5 parent: 5350 - proto: ReinforcedWindow entities: @@ -130699,140 +133122,135 @@ entities: - type: Transform pos: 1.5,46.5 parent: 5350 - - uid: 10815 - components: - - type: Transform - pos: 64.5,-6.5 - parent: 5350 - - uid: 10816 + - uid: 10838 components: - type: Transform - pos: 64.5,-7.5 + pos: 64.5,-15.5 parent: 5350 - - uid: 10817 + - uid: 10839 components: - type: Transform - pos: 64.5,-8.5 + pos: 64.5,-9.5 parent: 5350 - - uid: 10818 + - uid: 10845 components: - type: Transform - pos: 64.5,-9.5 + pos: 59.5,-25.5 parent: 5350 - - uid: 10820 + - uid: 10846 components: - type: Transform - pos: 64.5,-10.5 + pos: 58.5,-25.5 parent: 5350 - - uid: 10821 + - uid: 10847 components: - type: Transform - pos: 64.5,-11.5 + pos: 57.5,-25.5 parent: 5350 - - uid: 10822 + - uid: 10848 components: - type: Transform - pos: 64.5,-12.5 + pos: 56.5,-25.5 parent: 5350 - - uid: 10823 + - uid: 10849 components: - type: Transform - pos: 64.5,-13.5 + pos: 55.5,-25.5 parent: 5350 - - uid: 10824 + - uid: 10850 components: - type: Transform - pos: 64.5,-14.5 + pos: 54.5,-25.5 parent: 5350 - - uid: 10825 + - uid: 10851 components: - type: Transform - pos: 64.5,-15.5 + pos: 53.5,-25.5 parent: 5350 - - uid: 10826 + - uid: 10852 components: - type: Transform - pos: 64.5,-16.5 + pos: 52.5,-25.5 parent: 5350 - - uid: 10827 + - uid: 10853 components: - type: Transform - pos: 64.5,-17.5 + pos: 51.5,-25.5 parent: 5350 - - uid: 10828 + - uid: 10854 components: - type: Transform - pos: 64.5,-18.5 + pos: 50.5,-25.5 parent: 5350 - - uid: 10829 + - uid: 11097 components: - type: Transform - pos: 64.5,-19.5 + pos: 64.5,-11.5 parent: 5350 - - uid: 10830 + - uid: 11098 components: - type: Transform - pos: 64.5,-20.5 + pos: 64.5,-10.5 parent: 5350 - - uid: 10843 + - uid: 11099 components: - type: Transform - pos: 61.5,-25.5 + pos: 64.5,-12.5 parent: 5350 - - uid: 10844 + - uid: 11100 components: - type: Transform - pos: 60.5,-25.5 + pos: 64.5,-13.5 parent: 5350 - - uid: 10845 + - uid: 11101 components: - type: Transform - pos: 59.5,-25.5 + pos: 64.5,-14.5 parent: 5350 - - uid: 10846 + - uid: 11102 components: - type: Transform - pos: 58.5,-25.5 + pos: 64.5,-16.5 parent: 5350 - - uid: 10847 + - uid: 11237 components: - type: Transform - pos: 57.5,-25.5 + pos: 64.5,-17.5 parent: 5350 - - uid: 10848 + - uid: 11239 components: - type: Transform - pos: 56.5,-25.5 + pos: 63.5,-25.5 parent: 5350 - - uid: 10849 + - uid: 11240 components: - type: Transform - pos: 55.5,-25.5 + pos: 64.5,-5.5 parent: 5350 - - uid: 10850 + - uid: 11265 components: - type: Transform - pos: 54.5,-25.5 + pos: 64.5,-19.5 parent: 5350 - - uid: 10851 + - uid: 11267 components: - type: Transform - pos: 53.5,-25.5 + pos: 61.5,-25.5 parent: 5350 - - uid: 10852 + - uid: 11284 components: - type: Transform - pos: 52.5,-25.5 + pos: 64.5,-7.5 parent: 5350 - - uid: 10853 + - uid: 11285 components: - type: Transform - pos: 51.5,-25.5 + pos: 64.5,-6.5 parent: 5350 - - uid: 10854 + - uid: 11286 components: - type: Transform - pos: 50.5,-25.5 + pos: 64.5,-8.5 parent: 5350 - uid: 11378 components: @@ -130844,6 +133262,21 @@ entities: - type: Transform pos: 43.5,-29.5 parent: 5350 + - uid: 11694 + components: + - type: Transform + pos: 64.5,-25.5 + parent: 5350 + - uid: 11734 + components: + - type: Transform + pos: 60.5,-25.5 + parent: 5350 + - uid: 11753 + components: + - type: Transform + pos: 70.5,-28.5 + parent: 5350 - uid: 12345 components: - type: Transform @@ -132044,11 +134477,66 @@ entities: - type: Transform pos: 104.5,10.5 parent: 5350 + - uid: 26789 + components: + - type: Transform + pos: 64.5,-21.5 + parent: 5350 - uid: 26871 components: - type: Transform pos: 32.5,-8.5 parent: 5350 + - uid: 27037 + components: + - type: Transform + pos: 74.5,-29.5 + parent: 5350 + - uid: 27038 + components: + - type: Transform + pos: 74.5,-30.5 + parent: 5350 + - uid: 27149 + components: + - type: Transform + pos: 72.5,-39.5 + parent: 5350 + - uid: 27150 + components: + - type: Transform + pos: 71.5,-39.5 + parent: 5350 + - uid: 27154 + components: + - type: Transform + pos: 73.5,-39.5 + parent: 5350 + - uid: 27155 + components: + - type: Transform + pos: 74.5,-39.5 + parent: 5350 + - uid: 27257 + components: + - type: Transform + pos: 65.5,-29.5 + parent: 5350 + - uid: 27258 + components: + - type: Transform + pos: 65.5,-30.5 + parent: 5350 + - uid: 27271 + components: + - type: Transform + pos: 66.5,-22.5 + parent: 5350 + - uid: 27272 + components: + - type: Transform + pos: 64.5,-18.5 + parent: 5350 - proto: RemoteSignaller entities: - uid: 1290 @@ -132467,6 +134955,11 @@ entities: - type: Transform pos: 108.52579,-0.4561236 parent: 5350 + - uid: 27047 + components: + - type: Transform + pos: 70.58096,-31.5 + parent: 5350 - proto: SheetPlasma entities: - uid: 9204 @@ -132627,11 +135120,6 @@ entities: - type: Transform pos: 42.547264,-3.4866009 parent: 5350 - - uid: 11273 - components: - - type: Transform - pos: 71.51609,-32.499207 - parent: 5350 - uid: 12277 components: - type: Transform @@ -133533,25 +136021,26 @@ entities: - Pressed: Toggle 10483: - Pressed: Toggle - - uid: 12021 + - uid: 11640 components: - type: Transform - pos: 45.5,-29.5 + rot: -1.5707963267948966 rad + pos: 64.5,-4.5 parent: 5350 - type: DeviceLinkSource linkedPorts: - 11487: + 11015: - Pressed: Toggle - 11486: - - Pressed: Toggle - - uid: 12022 + - uid: 12021 components: - type: Transform - pos: 64.5,-5.5 + pos: 45.5,-29.5 parent: 5350 - type: DeviceLinkSource linkedPorts: - 10293: + 11487: + - Pressed: Toggle + 11486: - Pressed: Toggle - uid: 15183 components: @@ -134492,6 +136981,11 @@ entities: parent: 5350 - proto: SignEngine entities: + - uid: 11741 + components: + - type: Transform + pos: 65.5,-22.5 + parent: 5350 - uid: 23813 components: - type: Transform @@ -134565,6 +137059,23 @@ entities: - type: Transform pos: 45.5,-35.5 parent: 5350 + - uid: 27262 + components: + - type: Transform + pos: 65.5,-39.5 + parent: 5350 +- proto: SignFlammableMed + entities: + - uid: 27094 + components: + - type: Transform + pos: 75.5,-31.5 + parent: 5350 + - uid: 27198 + components: + - type: Transform + pos: 77.5,-36.5 + parent: 5350 - proto: SignGravity entities: - uid: 14539 @@ -135038,6 +137549,11 @@ entities: - type: Transform pos: -0.5,-48.5 parent: 5350 + - uid: 27093 + components: + - type: Transform + pos: 65.5,-27.5 + parent: 5350 - proto: SignSpace entities: - uid: 5419 @@ -135075,15 +137591,15 @@ entities: - type: Transform pos: -43.5,17.5 parent: 5350 - - uid: 11287 + - uid: 11490 components: - type: Transform - pos: 65.5,-25.5 + pos: 47.5,-33.5 parent: 5350 - - uid: 11490 + - uid: 11755 components: - type: Transform - pos: 47.5,-33.5 + pos: 70.5,-22.5 parent: 5350 - uid: 18937 components: @@ -135140,6 +137656,11 @@ entities: - type: Transform pos: 92.5,6.5 parent: 5350 + - uid: 27263 + components: + - type: Transform + pos: 75.5,-40.5 + parent: 5350 - proto: SignSurgery entities: - uid: 15191 @@ -135530,6 +138051,13 @@ entities: - type: Transform pos: 55.5,30.5 parent: 5350 + - uid: 27014 + components: + - type: MetaData + name: TEG SMES + - type: Transform + pos: 70.5,-26.5 + parent: 5350 - proto: SmokingPipeFilledCannabis entities: - uid: 24641 @@ -138355,15 +140883,15 @@ entities: parent: 5350 - proto: StorageCanister entities: - - uid: 11515 + - uid: 10293 components: - type: Transform - pos: 45.5,-26.5 + pos: 69.5,-10.5 parent: 5350 - - uid: 11627 + - uid: 11515 components: - type: Transform - pos: 69.5,-11.5 + pos: 45.5,-26.5 parent: 5350 - uid: 11819 components: @@ -138583,6 +141111,13 @@ entities: - type: Transform pos: 104.5,13.5 parent: 5350 + - uid: 27141 + components: + - type: MetaData + name: TEG Substation + - type: Transform + pos: 70.5,-25.5 + parent: 5350 - proto: SuitStorageCaptain entities: - uid: 1505 @@ -139134,6 +141669,18 @@ entities: id: Tech Vault High Sec - proto: SurveillanceCameraEngineering entities: + - uid: 9027 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 69.5,-10.5 + parent: 5350 + - uid: 11055 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 69.5,-14.5 + parent: 5350 - uid: 11516 components: - type: Transform @@ -139145,6 +141692,26 @@ entities: - SurveillanceCameraEngineering nameSet: True id: Thruster + - uid: 11571 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 69.5,-6.5 + parent: 5350 + - uid: 11620 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 69.5,-18.5 + parent: 5350 + - uid: 11751 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 72.5,-22.5 + parent: 5350 + - type: SurveillanceCamera + id: Atmos TEG Exterior north - uid: 12527 components: - type: Transform @@ -139393,61 +141960,6 @@ entities: - SurveillanceCameraEngineering nameSet: True id: Atmos Tank Nitro - - uid: 26785 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 69.5,-19.5 - parent: 5350 - - type: SurveillanceCamera - setupAvailableNetworks: - - SurveillanceCameraEngineering - nameSet: True - id: Atmos Tank Co2 - - uid: 26786 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 69.5,-15.5 - parent: 5350 - - type: SurveillanceCamera - setupAvailableNetworks: - - SurveillanceCameraEngineering - nameSet: True - id: Atmos Tank Plasma - - uid: 26787 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 69.5,-11.5 - parent: 5350 - - type: SurveillanceCamera - setupAvailableNetworks: - - SurveillanceCameraEngineering - nameSet: True - id: Atmos Tank Waste - - uid: 26788 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 69.5,-7.5 - parent: 5350 - - type: SurveillanceCamera - setupAvailableNetworks: - - SurveillanceCameraEngineering - nameSet: True - id: Atmos Tank Mixer - - uid: 26789 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 68.5,-23.5 - parent: 5350 - - type: SurveillanceCamera - setupAvailableNetworks: - - SurveillanceCameraEngineering - nameSet: True - id: Atmos Exterior - uid: 26792 components: - type: Transform @@ -139512,6 +142024,40 @@ entities: - SurveillanceCameraEngineering nameSet: True id: Solars SW + - uid: 27139 + components: + - type: MetaData + name: camera + - type: Transform + rot: -1.5707963267948966 rad + pos: 66.5,-26.5 + parent: 5350 + - type: SurveillanceCamera + id: Atmos TEG Room Entrance + - uid: 27265 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 73.5,-31.5 + parent: 5350 + - type: SurveillanceCamera + id: Atmos TEG Room Desk + - uid: 27267 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 66.5,-38.5 + parent: 5350 + - type: SurveillanceCamera + id: Atmos TEG Room Chamber + - uid: 27269 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 74.5,-42.5 + parent: 5350 + - type: SurveillanceCamera + id: Atmos TEG Exterior south - proto: SurveillanceCameraGeneral entities: - uid: 23189 @@ -142622,6 +145168,33 @@ entities: - type: Transform pos: 26.5,0.5 parent: 5350 + - uid: 27040 + components: + - type: Transform + pos: 73.5,-30.5 + parent: 5350 + - uid: 27041 + components: + - type: Transform + pos: 73.5,-31.5 + parent: 5350 + - uid: 27042 + components: + - type: Transform + pos: 72.5,-31.5 + parent: 5350 + - uid: 27044 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 70.5,-31.5 + parent: 5350 + - uid: 27045 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 69.5,-31.5 + parent: 5350 - proto: TableCarpet entities: - uid: 1022 @@ -144473,26 +147046,26 @@ entities: parent: 5350 - proto: TegCenter entities: - - uid: 11276 + - uid: 26997 components: - type: Transform rot: -1.5707963267948966 rad - pos: 69.5,-34.5 + pos: 70.5,-35.5 parent: 5350 - proto: TegCirculator entities: - - uid: 11277 + - uid: 26998 components: - type: Transform - pos: 70.5,-34.5 + rot: 3.141592653589793 rad + pos: 69.5,-35.5 parent: 5350 - type: PointLight color: '#FF3300FF' - - uid: 11280 + - uid: 26999 components: - type: Transform - rot: 3.141592653589793 rad - pos: 68.5,-34.5 + pos: 71.5,-35.5 parent: 5350 - type: PointLight color: '#FF3300FF' @@ -145302,6 +147875,12 @@ entities: - type: Transform pos: 52.498978,0.33205032 parent: 5350 + - uid: 27102 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 72.38718,-31.5 + parent: 5350 - proto: TubaInstrument entities: - uid: 3197 @@ -145460,6 +148039,25 @@ entities: - Left: Forward - Right: Reverse - Middle: Off + - uid: 27274 + components: + - type: MetaData + desc: 'Opens and closes the blast doors of the combustion chamber. Left: one Door - Right: both Doors - Middle: closed.' + name: blast doors + - type: Transform + pos: 70.5,-38.5 + parent: 5350 + - type: TwoWayLever + nextSignalLeft: True + - type: DeviceLinkSource + linkedPorts: + 27136: + - Middle: Close + - Left: Open + - Right: Open + 27135: + - Middle: Close + - Left: Open - proto: UnfinishedMachineFrame entities: - uid: 18441 @@ -147889,6 +150487,16 @@ entities: - type: Transform pos: -57.5,-6.5 parent: 5350 + - uid: 5314 + components: + - type: Transform + pos: 66.5,-20.5 + parent: 5350 + - uid: 5315 + components: + - type: Transform + pos: 67.5,-20.5 + parent: 5350 - uid: 5328 components: - type: Transform @@ -149994,6 +152602,12 @@ entities: - type: Transform pos: 58.5,-3.5 parent: 5350 + - uid: 9069 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 65.5,-38.5 + parent: 5350 - uid: 9071 components: - type: Transform @@ -150527,67 +153141,35 @@ entities: - uid: 10814 components: - type: Transform - pos: 64.5,-5.5 - parent: 5350 - - uid: 10831 - components: - - type: Transform - pos: 64.5,-21.5 + pos: 66.5,-12.5 parent: 5350 - - uid: 10832 + - uid: 10818 components: - type: Transform - pos: 64.5,-22.5 + rot: -1.5707963267948966 rad + pos: 69.5,-8.5 parent: 5350 - uid: 10833 components: - type: Transform - pos: 64.5,-23.5 - parent: 5350 - - uid: 10834 - components: - - type: Transform - pos: 65.5,-23.5 - parent: 5350 - - uid: 10835 - components: - - type: Transform - pos: 66.5,-23.5 - parent: 5350 - - uid: 10836 - components: - - type: Transform - pos: 67.5,-23.5 + pos: 68.5,-28.5 parent: 5350 - uid: 10837 components: - type: Transform - pos: 67.5,-25.5 - parent: 5350 - - uid: 10838 - components: - - type: Transform - pos: 66.5,-25.5 - parent: 5350 - - uid: 10839 - components: - - type: Transform - pos: 65.5,-25.5 - parent: 5350 - - uid: 10840 - components: - - type: Transform - pos: 64.5,-25.5 + pos: 71.5,-25.5 parent: 5350 - uid: 10841 components: - type: Transform - pos: 63.5,-25.5 + rot: -1.5707963267948966 rad + pos: 62.5,-25.5 parent: 5350 - uid: 10842 components: - type: Transform - pos: 62.5,-25.5 + rot: -1.5707963267948966 rad + pos: 64.5,-20.5 parent: 5350 - uid: 10855 components: @@ -150814,195 +153396,201 @@ entities: - type: Transform pos: 58.5,-27.5 parent: 5350 - - uid: 10908 - components: - - type: Transform - pos: 66.5,-21.5 - parent: 5350 - - uid: 10909 + - uid: 10914 components: - type: Transform - pos: 67.5,-21.5 + pos: 70.5,-19.5 parent: 5350 - - uid: 10910 + - uid: 10915 components: - type: Transform - pos: 68.5,-21.5 + pos: 70.5,-18.5 parent: 5350 - - uid: 10911 + - uid: 10917 components: - type: Transform - pos: 69.5,-21.5 + pos: 70.5,-16.5 parent: 5350 - - uid: 10912 + - uid: 10918 components: - type: Transform - pos: 70.5,-21.5 + pos: 70.5,-15.5 parent: 5350 - - uid: 10913 + - uid: 10919 components: - type: Transform - pos: 70.5,-20.5 + pos: 70.5,-14.5 parent: 5350 - - uid: 10914 + - uid: 10921 components: - type: Transform - pos: 70.5,-19.5 + pos: 70.5,-12.5 parent: 5350 - - uid: 10915 + - uid: 10922 components: - type: Transform - pos: 70.5,-18.5 + pos: 70.5,-11.5 parent: 5350 - - uid: 10916 + - uid: 10923 components: - type: Transform - pos: 70.5,-17.5 + pos: 70.5,-10.5 parent: 5350 - - uid: 10917 + - uid: 10925 components: - type: Transform - pos: 70.5,-16.5 + pos: 70.5,-8.5 parent: 5350 - - uid: 10918 + - uid: 10927 components: - type: Transform - pos: 70.5,-15.5 + pos: 70.5,-6.5 parent: 5350 - - uid: 10919 + - uid: 10966 components: - type: Transform - pos: 70.5,-14.5 + pos: 70.5,-17.5 parent: 5350 - - uid: 10920 + - uid: 10969 components: - type: Transform - pos: 70.5,-13.5 + pos: 70.5,-20.5 parent: 5350 - - uid: 10921 + - uid: 10971 components: - type: Transform - pos: 70.5,-12.5 + pos: 69.5,-12.5 parent: 5350 - - uid: 10922 + - uid: 10989 components: - type: Transform - pos: 70.5,-11.5 + pos: 68.5,-12.5 parent: 5350 - - uid: 10923 + - uid: 11054 components: - type: Transform - pos: 70.5,-10.5 + rot: -1.5707963267948966 rad + pos: 67.5,-16.5 parent: 5350 - - uid: 10924 + - uid: 11163 components: - type: Transform - pos: 70.5,-9.5 + pos: 70.5,-13.5 parent: 5350 - - uid: 10925 + - uid: 11172 components: - type: Transform - pos: 70.5,-8.5 + rot: 1.5707963267948966 rad + pos: 67.5,-4.5 parent: 5350 - - uid: 10927 + - uid: 11173 components: - type: Transform - pos: 70.5,-6.5 + rot: -1.5707963267948966 rad + pos: 66.5,-8.5 parent: 5350 - - uid: 10928 + - uid: 11201 components: - type: Transform pos: 70.5,-5.5 parent: 5350 - - uid: 10929 - components: - - type: Transform - pos: 69.5,-5.5 - parent: 5350 - - uid: 10931 + - uid: 11202 components: - type: Transform - pos: 67.5,-5.5 + rot: -1.5707963267948966 rad + pos: 67.5,-8.5 parent: 5350 - - uid: 10932 + - uid: 11204 components: - type: Transform - pos: 66.5,-5.5 + rot: 1.5707963267948966 rad + pos: 69.5,-4.5 parent: 5350 - - uid: 10933 + - uid: 11262 components: - type: Transform - pos: 69.5,-9.5 + pos: 71.5,-28.5 parent: 5350 - - uid: 10934 + - uid: 11264 components: - type: Transform - pos: 68.5,-9.5 + pos: 69.5,-28.5 parent: 5350 - - uid: 10935 + - uid: 11268 components: - type: Transform - pos: 67.5,-9.5 + rot: -1.5707963267948966 rad + pos: 65.5,-28.5 parent: 5350 - - uid: 10936 + - uid: 11273 components: - type: Transform - pos: 66.5,-9.5 + rot: -1.5707963267948966 rad + pos: 65.5,-35.5 parent: 5350 - - uid: 10937 + - uid: 11275 components: - type: Transform - pos: 69.5,-13.5 + rot: -1.5707963267948966 rad + pos: 65.5,-36.5 parent: 5350 - - uid: 10938 + - uid: 11276 components: - type: Transform - pos: 68.5,-13.5 + pos: 64.5,-22.5 parent: 5350 - - uid: 10939 + - uid: 11277 components: - type: Transform - pos: 67.5,-13.5 + rot: -1.5707963267948966 rad + pos: 65.5,-27.5 parent: 5350 - - uid: 10940 + - uid: 11278 components: - type: Transform - pos: 66.5,-13.5 + rot: -1.5707963267948966 rad + pos: 65.5,-26.5 parent: 5350 - - uid: 10941 + - uid: 11283 components: - type: Transform - pos: 69.5,-17.5 + rot: -1.5707963267948966 rad + pos: 68.5,-22.5 parent: 5350 - - uid: 10942 + - uid: 11287 components: - type: Transform - pos: 68.5,-17.5 + pos: 68.5,-25.5 parent: 5350 - - uid: 10943 + - uid: 11299 components: - type: Transform - pos: 67.5,-17.5 + rot: 1.5707963267948966 rad + pos: 70.5,-4.5 parent: 5350 - - uid: 10944 + - uid: 11301 components: - type: Transform - pos: 66.5,-17.5 + rot: -1.5707963267948966 rad + pos: 66.5,-16.5 parent: 5350 - - uid: 11268 + - uid: 11305 components: - type: Transform - pos: 70.5,-29.5 + rot: 1.5707963267948966 rad + pos: 66.5,-4.5 parent: 5350 - - uid: 11269 + - uid: 11342 components: - type: Transform - pos: 68.5,-29.5 + rot: -1.5707963267948966 rad + pos: 68.5,-16.5 parent: 5350 - - uid: 11270 + - uid: 11346 components: - type: Transform - pos: 67.5,-29.5 + rot: -1.5707963267948966 rad + pos: 69.5,-16.5 parent: 5350 - uid: 11370 components: @@ -151124,6 +153712,102 @@ entities: - type: Transform pos: 42.5,-29.5 parent: 5350 + - uid: 11498 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 65.5,-25.5 + parent: 5350 + - uid: 11596 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 68.5,-8.5 + parent: 5350 + - uid: 11597 + components: + - type: Transform + pos: 67.5,-12.5 + parent: 5350 + - uid: 11603 + components: + - type: Transform + pos: 70.5,-9.5 + parent: 5350 + - uid: 11622 + components: + - type: Transform + pos: 69.5,-20.5 + parent: 5350 + - uid: 11627 + components: + - type: Transform + pos: 68.5,-20.5 + parent: 5350 + - uid: 11662 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 71.5,-22.5 + parent: 5350 + - uid: 11697 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 70.5,-22.5 + parent: 5350 + - uid: 11698 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 69.5,-22.5 + parent: 5350 + - uid: 11699 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 65.5,-22.5 + parent: 5350 + - uid: 11735 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 65.5,-37.5 + parent: 5350 + - uid: 11740 + components: + - type: Transform + pos: 68.5,-27.5 + parent: 5350 + - uid: 11750 + components: + - type: Transform + pos: 71.5,-26.5 + parent: 5350 + - uid: 11757 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 65.5,-34.5 + parent: 5350 + - uid: 11764 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 65.5,-33.5 + parent: 5350 + - uid: 11784 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 65.5,-32.5 + parent: 5350 + - uid: 11785 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 65.5,-31.5 + parent: 5350 - uid: 12127 components: - type: Transform @@ -155642,6 +158326,371 @@ entities: - type: Transform pos: -15.5,61.5 parent: 5350 + - uid: 27003 + components: + - type: Transform + pos: 72.5,-28.5 + parent: 5350 + - uid: 27004 + components: + - type: Transform + pos: 73.5,-28.5 + parent: 5350 + - uid: 27005 + components: + - type: Transform + pos: 74.5,-28.5 + parent: 5350 + - uid: 27008 + components: + - type: Transform + pos: 74.5,-31.5 + parent: 5350 + - uid: 27009 + components: + - type: Transform + pos: 75.5,-31.5 + parent: 5350 + - uid: 27010 + components: + - type: Transform + pos: 76.5,-31.5 + parent: 5350 + - uid: 27011 + components: + - type: Transform + pos: 77.5,-31.5 + parent: 5350 + - uid: 27022 + components: + - type: Transform + pos: 77.5,-42.5 + parent: 5350 + - uid: 27023 + components: + - type: Transform + pos: 77.5,-40.5 + parent: 5350 + - uid: 27052 + components: + - type: Transform + pos: 65.5,-39.5 + parent: 5350 + - uid: 27053 + components: + - type: Transform + pos: 65.5,-40.5 + parent: 5350 + - uid: 27054 + components: + - type: Transform + pos: 77.5,-39.5 + parent: 5350 + - uid: 27055 + components: + - type: Transform + pos: 77.5,-38.5 + parent: 5350 + - uid: 27056 + components: + - type: Transform + pos: 77.5,-37.5 + parent: 5350 + - uid: 27057 + components: + - type: Transform + pos: 77.5,-32.5 + parent: 5350 + - uid: 27058 + components: + - type: Transform + pos: 77.5,-34.5 + parent: 5350 + - uid: 27059 + components: + - type: Transform + pos: 77.5,-33.5 + parent: 5350 + - uid: 27060 + components: + - type: Transform + pos: 77.5,-35.5 + parent: 5350 + - uid: 27061 + components: + - type: Transform + pos: 77.5,-36.5 + parent: 5350 + - uid: 27065 + components: + - type: Transform + pos: 65.5,-41.5 + parent: 5350 + - uid: 27066 + components: + - type: Transform + pos: 65.5,-42.5 + parent: 5350 + - uid: 27067 + components: + - type: Transform + pos: 65.5,-43.5 + parent: 5350 + - uid: 27068 + components: + - type: Transform + pos: 66.5,-43.5 + parent: 5350 + - uid: 27072 + components: + - type: Transform + pos: 69.5,-43.5 + parent: 5350 + - uid: 27075 + components: + - type: Transform + pos: 70.5,-43.5 + parent: 5350 + - uid: 27076 + components: + - type: Transform + pos: 77.5,-41.5 + parent: 5350 + - uid: 27119 + components: + - type: Transform + pos: 70.5,-39.5 + parent: 5350 + - uid: 27120 + components: + - type: Transform + pos: 70.5,-40.5 + parent: 5350 + - uid: 27121 + components: + - type: Transform + pos: 70.5,-41.5 + parent: 5350 + - uid: 27122 + components: + - type: Transform + pos: 70.5,-42.5 + parent: 5350 + - uid: 27124 + components: + - type: Transform + pos: 76.5,-42.5 + parent: 5350 + - uid: 27140 + components: + - type: Transform + pos: 75.5,-42.5 + parent: 5350 + - uid: 27148 + components: + - type: Transform + pos: 75.5,-40.5 + parent: 5350 + - uid: 27152 + components: + - type: Transform + pos: 75.5,-39.5 + parent: 5350 + - uid: 27199 + components: + - type: Transform + pos: 71.5,-27.5 + parent: 5350 + - uid: 27200 + components: + - type: Transform + pos: 68.5,-24.5 + parent: 5350 + - uid: 27246 + components: + - type: Transform + pos: 70.5,-24.5 + parent: 5350 + - uid: 27247 + components: + - type: Transform + pos: 69.5,-24.5 + parent: 5350 + - uid: 27250 + components: + - type: Transform + pos: 71.5,-24.5 + parent: 5350 + - uid: 27270 + components: + - type: Transform + pos: 67.5,-22.5 + parent: 5350 + - uid: 27435 + components: + - type: Transform + pos: 79.5,-29.5 + parent: 5350 + - uid: 27436 + components: + - type: Transform + pos: 79.5,-30.5 + parent: 5350 + - uid: 27437 + components: + - type: Transform + pos: 79.5,-31.5 + parent: 5350 + - uid: 27438 + components: + - type: Transform + pos: 79.5,-32.5 + parent: 5350 + - uid: 27439 + components: + - type: Transform + pos: 79.5,-34.5 + parent: 5350 + - uid: 27440 + components: + - type: Transform + pos: 79.5,-35.5 + parent: 5350 + - uid: 27442 + components: + - type: Transform + pos: 79.5,-37.5 + parent: 5350 + - uid: 27443 + components: + - type: Transform + pos: 79.5,-38.5 + parent: 5350 + - uid: 27444 + components: + - type: Transform + pos: 79.5,-40.5 + parent: 5350 + - uid: 27445 + components: + - type: Transform + pos: 79.5,-41.5 + parent: 5350 + - uid: 27446 + components: + - type: Transform + pos: 79.5,-42.5 + parent: 5350 + - uid: 27447 + components: + - type: Transform + pos: 79.5,-43.5 + parent: 5350 + - uid: 27448 + components: + - type: Transform + pos: 79.5,-45.5 + parent: 5350 + - uid: 27449 + components: + - type: Transform + pos: 79.5,-46.5 + parent: 5350 + - uid: 27450 + components: + - type: Transform + pos: 77.5,-46.5 + parent: 5350 + - uid: 27451 + components: + - type: Transform + pos: 76.5,-46.5 + parent: 5350 + - uid: 27452 + components: + - type: Transform + pos: 74.5,-46.5 + parent: 5350 + - uid: 27453 + components: + - type: Transform + pos: 72.5,-46.5 + parent: 5350 + - uid: 27454 + components: + - type: Transform + pos: 73.5,-46.5 + parent: 5350 + - uid: 27455 + components: + - type: Transform + pos: 71.5,-46.5 + parent: 5350 + - uid: 27456 + components: + - type: Transform + pos: 69.5,-46.5 + parent: 5350 + - uid: 27457 + components: + - type: Transform + pos: 68.5,-46.5 + parent: 5350 + - uid: 27458 + components: + - type: Transform + pos: 66.5,-46.5 + parent: 5350 + - uid: 27459 + components: + - type: Transform + pos: 65.5,-46.5 + parent: 5350 + - uid: 27461 + components: + - type: Transform + pos: 63.5,-46.5 + parent: 5350 + - uid: 27462 + components: + - type: Transform + pos: 63.5,-45.5 + parent: 5350 + - uid: 27463 + components: + - type: Transform + pos: 63.5,-44.5 + parent: 5350 + - uid: 27464 + components: + - type: Transform + pos: 63.5,-42.5 + parent: 5350 + - uid: 27465 + components: + - type: Transform + pos: 63.5,-41.5 + parent: 5350 + - uid: 27466 + components: + - type: Transform + pos: 63.5,-40.5 + parent: 5350 + - uid: 27467 + components: + - type: Transform + pos: 63.5,-38.5 + parent: 5350 + - uid: 27468 + components: + - type: Transform + pos: 63.5,-37.5 + parent: 5350 + - uid: 27469 + components: + - type: Transform + pos: 63.5,-36.5 + parent: 5350 - proto: WallSolid entities: - uid: 57 @@ -163506,10 +166555,11 @@ entities: parent: 5350 - proto: WarningCO2 entities: - - uid: 11640 + - uid: 11151 components: - type: Transform - pos: 66.5,-17.5 + rot: -1.5707963267948966 rad + pos: 66.5,-16.5 parent: 5350 - proto: WarningN2 entities: @@ -163527,22 +166577,23 @@ entities: parent: 5350 - proto: WarningPlasma entities: - - uid: 11641 + - uid: 11114 components: - type: Transform - pos: 66.5,-13.5 + pos: 66.5,-12.5 parent: 5350 - proto: WarningWaste entities: - - uid: 11642 + - uid: 11137 components: - type: Transform - pos: 66.5,-9.5 + pos: 66.5,-4.5 parent: 5350 - - uid: 11643 + - uid: 11641 components: - type: Transform - pos: 66.5,-5.5 + rot: -1.5707963267948966 rad + pos: 66.5,-8.5 parent: 5350 - proto: WaterCooler entities: @@ -163899,6 +166950,12 @@ entities: - type: Transform pos: -31.37716,-26.50117 parent: 5350 + - uid: 27050 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 69.77701,-31.5 + parent: 5350 - proto: WelderMini entities: - uid: 3636 @@ -163998,6 +167055,11 @@ entities: - type: Transform pos: 45.5,33.5 parent: 5350 + - uid: 27086 + components: + - type: Transform + pos: 76.5,-32.5 + parent: 5350 - proto: WetFloorSign entities: - uid: 12844 @@ -164082,18 +167144,6 @@ entities: - type: Transform pos: -3.5,35.5 parent: 5350 - - uid: 11282 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 71.5,-24.5 - parent: 5350 - - uid: 11283 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 71.5,-24.5 - parent: 5350 - uid: 13571 components: - type: Transform @@ -165688,104 +168738,6 @@ entities: - type: Transform pos: 45.5,0.5 parent: 5350 - - uid: 11251 - components: - - type: Transform - pos: 68.5,-23.5 - parent: 5350 - - uid: 11252 - components: - - type: Transform - pos: 69.5,-23.5 - parent: 5350 - - uid: 11253 - components: - - type: Transform - pos: 70.5,-23.5 - parent: 5350 - - uid: 11254 - components: - - type: Transform - pos: 71.5,-23.5 - parent: 5350 - - uid: 11255 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: 71.5,-25.5 - parent: 5350 - - uid: 11256 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: 70.5,-25.5 - parent: 5350 - - uid: 11257 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: 68.5,-25.5 - parent: 5350 - - uid: 11258 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 68.5,-25.5 - parent: 5350 - - uid: 11259 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 68.5,-26.5 - parent: 5350 - - uid: 11260 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 70.5,-26.5 - parent: 5350 - - uid: 11261 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 70.5,-25.5 - parent: 5350 - - uid: 11262 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: 68.5,-27.5 - parent: 5350 - - uid: 11263 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 68.5,-27.5 - parent: 5350 - - uid: 11264 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 68.5,-28.5 - parent: 5350 - - uid: 11265 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: 70.5,-27.5 - parent: 5350 - - uid: 11266 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 70.5,-27.5 - parent: 5350 - - uid: 11267 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 70.5,-28.5 - parent: 5350 - uid: 11512 components: - type: Transform @@ -169133,4 +172085,9 @@ entities: - type: Transform pos: 59.615005,1.5566483 parent: 5350 + - uid: 27117 + components: + - type: Transform + pos: 69.87581,-31.5 + parent: 5350 ... From 530a741b7bfbc151bf94b45401085208dc037b76 Mon Sep 17 00:00:00 2001 From: Repo <47093363+Titian3@users.noreply.github.com> Date: Fri, 15 Nov 2024 15:54:20 +1300 Subject: [PATCH 104/290] Rule amendment - Remove role abandonment aHelp requirement. (#33287) * Role abandonment aHelp requirement. * disable roundstart chat message --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> --- Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml | 1 - Resources/Prototypes/Roles/Jobs/Command/captain.yml | 1 - Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml | 1 - Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml | 1 - .../Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml | 1 - Resources/Prototypes/Roles/Jobs/Science/research_director.yml | 1 - Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml | 1 - Resources/Prototypes/Roles/Jobs/Security/warden.yml | 1 - .../ServerRules/RoleplayRules/RuleR12RoleAbandonment.xml | 2 +- 9 files changed, 1 insertion(+), 9 deletions(-) diff --git a/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml b/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml index ee1c2c594984..740afded646b 100644 --- a/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml +++ b/Resources/Prototypes/Roles/Jobs/Cargo/quartermaster.yml @@ -18,7 +18,6 @@ weight: 10 startingGear: QuartermasterGear icon: "JobIconQuarterMaster" - requireAdminNotify: true supervisors: job-supervisors-captain canBeAntag: false access: diff --git a/Resources/Prototypes/Roles/Jobs/Command/captain.yml b/Resources/Prototypes/Roles/Jobs/Command/captain.yml index 79634aa5d9f7..a22d334c9419 100644 --- a/Resources/Prototypes/Roles/Jobs/Command/captain.yml +++ b/Resources/Prototypes/Roles/Jobs/Command/captain.yml @@ -19,7 +19,6 @@ weight: 20 startingGear: CaptainGear icon: "JobIconCaptain" - requireAdminNotify: true joinNotifyCrew: true supervisors: job-supervisors-centcom canBeAntag: false diff --git a/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml b/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml index d5521f767f18..f457cfbc496a 100644 --- a/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml +++ b/Resources/Prototypes/Roles/Jobs/Command/head_of_personnel.yml @@ -19,7 +19,6 @@ weight: 20 startingGear: HoPGear icon: "JobIconHeadOfPersonnel" - requireAdminNotify: true supervisors: job-supervisors-captain canBeAntag: false access: diff --git a/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml b/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml index 0ee0b6736ca7..9bac538551fc 100644 --- a/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml +++ b/Resources/Prototypes/Roles/Jobs/Engineering/chief_engineer.yml @@ -18,7 +18,6 @@ weight: 10 startingGear: ChiefEngineerGear icon: "JobIconChiefEngineer" - requireAdminNotify: true supervisors: job-supervisors-captain canBeAntag: false access: diff --git a/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml b/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml index 25871134155e..83b16d427bd4 100644 --- a/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml +++ b/Resources/Prototypes/Roles/Jobs/Medical/chief_medical_officer.yml @@ -20,7 +20,6 @@ weight: 10 startingGear: CMOGear icon: "JobIconChiefMedicalOfficer" - requireAdminNotify: true supervisors: job-supervisors-captain canBeAntag: false access: diff --git a/Resources/Prototypes/Roles/Jobs/Science/research_director.yml b/Resources/Prototypes/Roles/Jobs/Science/research_director.yml index b54ba54b1a47..7d6db3e0bec8 100644 --- a/Resources/Prototypes/Roles/Jobs/Science/research_director.yml +++ b/Resources/Prototypes/Roles/Jobs/Science/research_director.yml @@ -12,7 +12,6 @@ weight: 10 startingGear: ResearchDirectorGear icon: "JobIconResearchDirector" - requireAdminNotify: true supervisors: job-supervisors-captain canBeAntag: false access: diff --git a/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml b/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml index 044df7f69e20..e22eccb7dad4 100644 --- a/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml +++ b/Resources/Prototypes/Roles/Jobs/Security/head_of_security.yml @@ -18,7 +18,6 @@ weight: 10 startingGear: HoSGear icon: "JobIconHeadOfSecurity" - requireAdminNotify: true supervisors: job-supervisors-captain canBeAntag: false access: diff --git a/Resources/Prototypes/Roles/Jobs/Security/warden.yml b/Resources/Prototypes/Roles/Jobs/Security/warden.yml index 7ec820d27b8f..6d79d7480490 100644 --- a/Resources/Prototypes/Roles/Jobs/Security/warden.yml +++ b/Resources/Prototypes/Roles/Jobs/Security/warden.yml @@ -9,7 +9,6 @@ time: 36000 #10 hrs startingGear: WardenGear icon: "JobIconWarden" - requireAdminNotify: true supervisors: job-supervisors-hos canBeAntag: false access: diff --git a/Resources/ServerInfo/Guidebook/ServerRules/RoleplayRules/RuleR12RoleAbandonment.xml b/Resources/ServerInfo/Guidebook/ServerRules/RoleplayRules/RuleR12RoleAbandonment.xml index 3821816128f8..1ddf73cc7725 100644 --- a/Resources/ServerInfo/Guidebook/ServerRules/RoleplayRules/RuleR12RoleAbandonment.xml +++ b/Resources/ServerInfo/Guidebook/ServerRules/RoleplayRules/RuleR12RoleAbandonment.xml @@ -2,7 +2,7 @@ # Roleplay Rule 12 - Do not abandon your role Do not join the round as a role that you don't intend to play. Do not enable antagonist roles that you don't intend to play. Abandoning a role includes not completing tasks that the role is expected to do, in addition to things like leaving the game. Members of command should almost all stay on the station until the emergency shuttle arrives. Enforcement of this rule is more strict for command and antagonist roles, and less strict for less important roles like passengers. - Violations of this rule typically result in temporary or indefinite role bans. We understand that you may need to leave round early or unexpectedly. If you are in an important role (which is relayed to you in chat upon receiving your role), you should notify command members or an admin via ahelp so that they know you are leaving. Space Station 14 is a game. Do not endanger the safety of yourself or others, and do not neglect important things to avoid leaving a round early, even if you have to leave immediately without notifying anyone. Role bans for disconnecting are typically only applied if there is a pattern, and are almost always temporary. + Violations of this rule typically result in temporary or indefinite role bans. We understand that you may need to leave round early or unexpectedly. If you are in an important role (which is relayed to you in chat upon receiving your role), you should notify command members so that they know you are leaving and attempt to cryosleep if possible. Space Station 14 is a game. Do not endanger the safety of yourself or others, and do not neglect important things to avoid leaving a round early, even if you have to leave immediately without notifying anyone. Role bans for disconnecting are typically only applied if there is a pattern, and are almost always temporary. "Antag rolling" refers to a player abandoning their role if they do not get an antagonist role. From dfda557d4b199d60436db2f3acfeef74877f05b8 Mon Sep 17 00:00:00 2001 From: beck-thompson <107373427+beck-thompson@users.noreply.github.com> Date: Thu, 14 Nov 2024 19:24:27 -0800 Subject: [PATCH 105/290] Note expiry time is now relative instead of using timestamps (#33262) * Add the stuff * Loc fix * fixes * Change --- .../Administration/UI/Notes/NoteEdit.xaml | 1 + .../Administration/UI/Notes/NoteEdit.xaml.cs | 53 +++++++++++++++++-- .../en-US/administration/ui/admin-notes.ftl | 14 ++++- 3 files changed, 63 insertions(+), 5 deletions(-) diff --git a/Content.Client/Administration/UI/Notes/NoteEdit.xaml b/Content.Client/Administration/UI/Notes/NoteEdit.xaml index 506abac540ce..72b2c55ce8da 100644 --- a/Content.Client/Administration/UI/Notes/NoteEdit.xaml +++ b/Content.Client/Administration/UI/Notes/NoteEdit.xaml @@ -8,6 +8,7 @@ -[RegisterComponent, NetworkedComponent, Access(typeof(Systems.BonkSystem))] +[RegisterComponent, NetworkedComponent] public sealed partial class BonkableComponent : Component { /// - /// Chance of bonk triggering if the user is clumsy. + /// How long to stun players on bonk, in seconds. /// - [DataField("bonkClumsyChance")] - public float BonkClumsyChance = 0.5f; + [DataField] + public TimeSpan BonkTime = TimeSpan.FromSeconds(2); /// - /// Sound to play when bonking. + /// How much damage to apply on bonk. /// - /// - [DataField("bonkSound")] - public SoundSpecifier? BonkSound; - - /// - /// How long to stun players on bonk, in seconds. - /// - /// - [DataField("bonkTime")] - public float BonkTime = 2; - - /// - /// How much damage to apply on bonk. - /// - /// - [DataField("bonkDamage")] + [DataField] public DamageSpecifier? BonkDamage; - - /// - /// How long it takes to bonk. - /// - [DataField("bonkDelay")] - public float BonkDelay = 1.5f; } diff --git a/Content.Shared/Climbing/Events/BeforeClimbEvents.cs b/Content.Shared/Climbing/Events/BeforeClimbEvents.cs new file mode 100644 index 000000000000..85c40f9427c1 --- /dev/null +++ b/Content.Shared/Climbing/Events/BeforeClimbEvents.cs @@ -0,0 +1,36 @@ +using Content.Shared.Inventory; +using Content.Shared.Climbing.Components; + +namespace Content.Shared.Climbing.Events; + +public abstract partial class BeforeClimbEvent : CancellableEntityEventArgs +{ + public readonly EntityUid GettingPutOnTable; + public readonly EntityUid PuttingOnTable; + public readonly Entity BeingClimbedOn; + + public BeforeClimbEvent(EntityUid gettingPutOntable, EntityUid puttingOnTable, Entity beingClimbedOn) + { + GettingPutOnTable = gettingPutOntable; + PuttingOnTable = puttingOnTable; + BeingClimbedOn = beingClimbedOn; + } +} + +/// +/// This event is raised on the the person either getting put on or going on the table. +/// The event is also called on their clothing as well. +/// +public sealed class SelfBeforeClimbEvent : BeforeClimbEvent, IInventoryRelayEvent +{ + public SlotFlags TargetSlots { get; } = SlotFlags.WITHOUT_POCKET; + public SelfBeforeClimbEvent(EntityUid gettingPutOntable, EntityUid puttingOnTable, Entity beingClimbedOn) : base(gettingPutOntable, puttingOnTable, beingClimbedOn) { } +} + +/// +/// This event is raised on the thing being climbed on. +/// +public sealed class TargetBeforeClimbEvent : BeforeClimbEvent +{ + public TargetBeforeClimbEvent(EntityUid gettingPutOntable, EntityUid puttingOnTable, Entity beingClimbedOn) : base(gettingPutOntable, puttingOnTable, beingClimbedOn) { } +} diff --git a/Content.Shared/Climbing/Systems/BonkSystem.cs b/Content.Shared/Climbing/Systems/BonkSystem.cs deleted file mode 100644 index f59fe925736a..000000000000 --- a/Content.Shared/Climbing/Systems/BonkSystem.cs +++ /dev/null @@ -1,130 +0,0 @@ -using Content.Shared.CCVar; -using Content.Shared.Climbing.Components; -using Content.Shared.Climbing.Events; -using Content.Shared.Damage; -using Content.Shared.DoAfter; -using Content.Shared.DragDrop; -using Content.Shared.Hands.Components; -using Content.Shared.IdentityManagement; -using Content.Shared.Interaction; -using Content.Shared.Interaction.Components; -using Content.Shared.Popups; -using Content.Shared.Stunnable; -using Robust.Shared.Audio.Systems; -using Robust.Shared.Configuration; -using Robust.Shared.Player; -using Robust.Shared.Serialization; - -namespace Content.Shared.Climbing.Systems; - -public sealed partial class BonkSystem : EntitySystem -{ - [Dependency] private readonly IConfigurationManager _cfg = default!; - [Dependency] private readonly DamageableSystem _damageableSystem = default!; - [Dependency] private readonly SharedInteractionSystem _interactionSystem = default!; - [Dependency] private readonly SharedStunSystem _stunSystem = default!; - [Dependency] private readonly SharedAudioSystem _audioSystem = default!; - [Dependency] private readonly SharedPopupSystem _popupSystem = default!; - [Dependency] private readonly SharedDoAfterSystem _doAfter = default!; - - public override void Initialize() - { - base.Initialize(); - SubscribeLocalEvent(OnBonkDoAfter); - SubscribeLocalEvent(OnAttemptClimb); - } - - private void OnBonkDoAfter(EntityUid uid, BonkableComponent component, BonkDoAfterEvent args) - { - if (args.Handled || args.Cancelled || args.Args.Used == null) - return; - - TryBonk(args.Args.Used.Value, uid, component, source: args.Args.User); - - args.Handled = true; - } - - - public bool TryBonk(EntityUid user, EntityUid bonkableUid, BonkableComponent? bonkableComponent = null, EntityUid? source = null) - { - if (!Resolve(bonkableUid, ref bonkableComponent, false)) - return false; - - // BONK! - var userName = Identity.Entity(user, EntityManager); - var bonkableName = Identity.Entity(bonkableUid, EntityManager); - - if (user == source) - { - // Non-local, non-bonking players - var othersMessage = Loc.GetString("bonkable-success-message-others", ("user", userName), ("bonkable", bonkableName)); - // Local, bonking player - var selfMessage = Loc.GetString("bonkable-success-message-user", ("user", userName), ("bonkable", bonkableName)); - - _popupSystem.PopupPredicted(selfMessage, othersMessage, user, user); - } - else if (source != null) - { - // Local, non-bonking player (dragger) - _popupSystem.PopupClient(Loc.GetString("bonkable-success-message-others", ("user", userName), ("bonkable", bonkableName)), user, source.Value); - // Non-local, non-bonking players - _popupSystem.PopupEntity(Loc.GetString("bonkable-success-message-others", ("user", userName), ("bonkable", bonkableName)), user, Filter.Pvs(user).RemoveWhereAttachedEntity(e => e == user || e == source.Value), true); - // Non-local, bonking player - _popupSystem.PopupEntity(Loc.GetString("bonkable-success-message-user", ("user", userName), ("bonkable", bonkableName)), user, user); - } - - - - if (source != null) - _audioSystem.PlayPredicted(bonkableComponent.BonkSound, bonkableUid, source); - else - _audioSystem.PlayPvs(bonkableComponent.BonkSound, bonkableUid); - - _stunSystem.TryParalyze(user, TimeSpan.FromSeconds(bonkableComponent.BonkTime), true); - - if (bonkableComponent.BonkDamage is { } bonkDmg) - _damageableSystem.TryChangeDamage(user, bonkDmg, true, origin: user); - - return true; - - } - - private bool TryStartBonk(EntityUid uid, EntityUid user, EntityUid climber, BonkableComponent? bonkableComponent = null) - { - if (!Resolve(uid, ref bonkableComponent, false)) - return false; - - if (!HasComp(climber) || !HasComp(user)) - return false; - - if (!_cfg.GetCVar(CCVars.GameTableBonk)) - { - // Not set to always bonk, try clumsy roll. - if (!_interactionSystem.TryRollClumsy(climber, bonkableComponent.BonkClumsyChance)) - return false; - } - - var doAfterArgs = new DoAfterArgs(EntityManager, user, bonkableComponent.BonkDelay, new BonkDoAfterEvent(), uid, target: uid, used: climber) - { - BreakOnMove = true, - BreakOnDamage = true, - DuplicateCondition = DuplicateConditions.SameTool | DuplicateConditions.SameTarget - }; - - return _doAfter.TryStartDoAfter(doAfterArgs); - } - - private void OnAttemptClimb(EntityUid uid, BonkableComponent component, ref AttemptClimbEvent args) - { - if (args.Cancelled) - return; - - if (TryStartBonk(uid, args.User, args.Climber, component)) - args.Cancelled = true; - } - - [Serializable, NetSerializable] - private sealed partial class BonkDoAfterEvent : SimpleDoAfterEvent - { - } -} diff --git a/Content.Shared/Climbing/Systems/ClimbSystem.cs b/Content.Shared/Climbing/Systems/ClimbSystem.cs index da194706f8f0..9bf481002a9b 100644 --- a/Content.Shared/Climbing/Systems/ClimbSystem.cs +++ b/Content.Shared/Climbing/Systems/ClimbSystem.cs @@ -251,6 +251,18 @@ private void Climb(EntityUid uid, EntityUid user, EntityUid climbable, bool sile if (!Resolve(climbable, ref comp, false)) return; + var selfEvent = new SelfBeforeClimbEvent(uid, user, (climbable, comp)); + RaiseLocalEvent(uid, selfEvent); + + if (selfEvent.Cancelled) + return; + + var targetEvent = new TargetBeforeClimbEvent(uid, user, (climbable, comp)); + RaiseLocalEvent(climbable, targetEvent); + + if (targetEvent.Cancelled) + return; + if (!ReplaceFixtures(uid, climbing, fixtures)) return; diff --git a/Content.Shared/Clumsy/ClumsyComponent.cs b/Content.Shared/Clumsy/ClumsyComponent.cs new file mode 100644 index 000000000000..c71f5d0008ae --- /dev/null +++ b/Content.Shared/Clumsy/ClumsyComponent.cs @@ -0,0 +1,61 @@ +using Content.Shared.Damage; +using Robust.Shared.Audio; +using Robust.Shared.GameStates; + +namespace Content.Shared.Clumsy; + +/// +/// A simple clumsy tag-component. +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class ClumsyComponent : Component +{ + + // Standard options. Try to fit these in if you can! + + /// + /// Sound to play when clumsy interactions fail. + /// + [DataField] + public SoundSpecifier ClumsySound = new SoundPathSpecifier("/Audio/Items/bikehorn.ogg"); + + /// + /// Default chance to fail a clumsy interaction. + /// If a system needs to use something else, add a new variable in the component, do not modify this percentage. + /// + [DataField, AutoNetworkedField] + public float ClumsyDefaultCheck = 0.5f; + + /// + /// Default stun time. + /// If a system needs to use something else, add a new variable in the component, do not modify this number. + /// + [DataField, AutoNetworkedField] + public TimeSpan ClumsyDefaultStunTime = TimeSpan.FromSeconds(2.5); + + // Specific options + + /// + /// Sound to play after hitting your head on a table. Ouch! + /// + [DataField] + public SoundCollectionSpecifier TableBonkSound = new SoundCollectionSpecifier("TrayHit"); + + /// + /// Stun time after failing to shoot a gun. + /// + [DataField, AutoNetworkedField] + public TimeSpan GunShootFailStunTime = TimeSpan.FromSeconds(3); + + /// + /// Stun time after failing to shoot a gun. + /// + [DataField, AutoNetworkedField] + public DamageSpecifier? GunShootFailDamage; + + /// + /// Noise to play after failing to shoot a gun. Boom! + /// + [DataField] + public SoundSpecifier GunShootFailSound = new SoundPathSpecifier("/Audio/Weapons/Guns/Gunshots/bang.ogg"); +} diff --git a/Content.Shared/Clumsy/ClumsySystem.cs b/Content.Shared/Clumsy/ClumsySystem.cs new file mode 100644 index 000000000000..e034458197fd --- /dev/null +++ b/Content.Shared/Clumsy/ClumsySystem.cs @@ -0,0 +1,146 @@ +using Content.Shared.CCVar; +using Content.Shared.Chemistry.Hypospray.Events; +using Content.Shared.Climbing.Components; +using Content.Shared.Climbing.Events; +using Content.Shared.Damage; +using Content.Shared.IdentityManagement; +using Content.Shared.Medical; +using Content.Shared.Popups; +using Content.Shared.Stunnable; +using Content.Shared.Weapons.Ranged.Events; +using Robust.Shared.Audio.Systems; +using Robust.Shared.Configuration; +using Robust.Shared.Random; +using Robust.Shared.Timing; + +namespace Content.Shared.Clumsy; + +public sealed class ClumsySystem : EntitySystem +{ + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly SharedStunSystem _stun = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + [Dependency] private readonly DamageableSystem _damageable = default!; + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] private readonly IConfigurationManager _cfg = default!; + + public override void Initialize() + { + SubscribeLocalEvent(BeforeHyposprayEvent); + SubscribeLocalEvent(BeforeDefibrillatorZapsEvent); + SubscribeLocalEvent(BeforeGunShotEvent); + SubscribeLocalEvent(OnBeforeClimbEvent); + } + + // If you add more clumsy interactions add them in this section! + #region Clumsy interaction events + private void BeforeHyposprayEvent(Entity ent, ref SelfBeforeHyposprayInjectsEvent args) + { + // Clumsy people sometimes inject themselves! Apparently syringes are clumsy proof... + if (!_random.Prob(ent.Comp.ClumsyDefaultCheck)) + return; + + args.TargetGettingInjected = args.EntityUsingHypospray; + args.InjectMessageOverride = "hypospray-component-inject-self-clumsy-message"; + _audio.PlayPvs(ent.Comp.ClumsySound, ent); + } + + private void BeforeDefibrillatorZapsEvent(Entity ent, ref SelfBeforeDefibrillatorZapsEvent args) + { + // Clumsy people sometimes defib themselves! + if (!_random.Prob(ent.Comp.ClumsyDefaultCheck)) + return; + + args.DefibTarget = args.EntityUsingDefib; + _audio.PlayPvs(ent.Comp.ClumsySound, ent); + + } + + private void BeforeGunShotEvent(Entity ent, ref SelfBeforeGunShotEvent args) + { + // Clumsy people sometimes can't shoot :( + + if (args.Gun.Comp.ClumsyProof) + return; + + if (!_random.Prob(ent.Comp.ClumsyDefaultCheck)) + return; + + if (ent.Comp.GunShootFailDamage != null) + _damageable.TryChangeDamage(ent, ent.Comp.GunShootFailDamage, origin: ent); + + _stun.TryParalyze(ent, ent.Comp.GunShootFailStunTime, true); + + // Apply salt to the wound ("Honk!") (No idea what this comment means) + _audio.PlayPvs(ent.Comp.GunShootFailSound, ent); + _audio.PlayPvs(ent.Comp.ClumsySound, ent); + + _popup.PopupEntity(Loc.GetString("gun-clumsy"), ent, ent); + args.Cancel(); + } + + private void OnBeforeClimbEvent(Entity ent, ref SelfBeforeClimbEvent args) + { + // This event is called in shared, thats why it has all the extra prediction stuff. + var rand = new System.Random((int)_timing.CurTick.Value); + + // If someone is putting you on the table, always get past the guard. + if (!_cfg.GetCVar(CCVars.GameTableBonk) && args.PuttingOnTable == ent.Owner && !rand.Prob(ent.Comp.ClumsyDefaultCheck)) + return; + + HitHeadClumsy(ent, args.BeingClimbedOn); + + _audio.PlayPredicted(ent.Comp.ClumsySound, ent, ent); + + _audio.PlayPredicted(ent.Comp.TableBonkSound, ent, ent); + + var gettingPutOnTableName = Identity.Entity(args.GettingPutOnTable, EntityManager); + var puttingOnTableName = Identity.Entity(args.PuttingOnTable, EntityManager); + + if (args.PuttingOnTable == ent.Owner) + { + // You are slamming yourself onto the table. + _popup.PopupPredicted( + Loc.GetString("bonkable-success-message-user", ("bonkable", args.BeingClimbedOn)), + Loc.GetString("bonkable-success-message-others", ("victim", gettingPutOnTableName), ("bonkable", args.BeingClimbedOn)), + ent, + ent); + } + else + { + // Someone else slamed you onto the table. + // This is only run in server so you need to use popup entity. + _popup.PopupPredicted( + Loc.GetString("forced-bonkable-success-message", + ("bonker", puttingOnTableName), + ("victim", gettingPutOnTableName), + ("bonkable", args.BeingClimbedOn)), + ent, + null); + } + + args.Cancel(); + } + #endregion + + #region Helper functions + /// + /// "Hits" an entites head against the given table. + /// + // Oh this fucntion is public le- NO!! This is only public for the one admin command if you use this anywhere else I will cry. + public void HitHeadClumsy(Entity target, EntityUid table) + { + var stunTime = target.Comp.ClumsyDefaultStunTime; + + if (TryComp(table, out var bonkComp)) + { + stunTime = bonkComp.BonkTime; + if (bonkComp.BonkDamage != null) + _damageable.TryChangeDamage(target, bonkComp.BonkDamage, true); + } + + _stun.TryParalyze(target, stunTime, true); + } + #endregion +} diff --git a/Content.Shared/Interaction/Components/ClumsyComponent.cs b/Content.Shared/Interaction/Components/ClumsyComponent.cs deleted file mode 100644 index 824696c8385d..000000000000 --- a/Content.Shared/Interaction/Components/ClumsyComponent.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Content.Shared.Damage; -using Robust.Shared.Audio; -using Robust.Shared.GameStates; - -namespace Content.Shared.Interaction.Components; - -/// -/// A simple clumsy tag-component. -/// -[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] -public sealed partial class ClumsyComponent : Component -{ - /// - /// Damage dealt to a clumsy character when they try to fire a gun. - /// - [DataField(required: true), AutoNetworkedField] - public DamageSpecifier ClumsyDamage = default!; - - /// - /// Sound to play when clumsy interactions fail. - /// - [DataField] - public SoundSpecifier ClumsySound = new SoundPathSpecifier("/Audio/Items/bikehorn.ogg"); -} diff --git a/Content.Shared/Interaction/SharedInteractionSystem.Clumsy.cs b/Content.Shared/Interaction/SharedInteractionSystem.Clumsy.cs deleted file mode 100644 index 9e45847e0788..000000000000 --- a/Content.Shared/Interaction/SharedInteractionSystem.Clumsy.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Content.Shared.Interaction.Components; -using Robust.Shared.Random; - -namespace Content.Shared.Interaction -{ - public partial class SharedInteractionSystem - { - public bool RollClumsy(ClumsyComponent component, float chance) - { - return component.Running && _random.Prob(chance); - } - - /// - /// Rolls a probability chance for a "bad action" if the target entity is clumsy. - /// - /// The entity that the clumsy check is happening for. - /// - /// The chance that a "bad action" happens if the user is clumsy, between 0 and 1 inclusive. - /// - /// True if a "bad action" happened, false if the normal action should happen. - public bool TryRollClumsy(EntityUid entity, float chance, ClumsyComponent? component = null) - { - return Resolve(entity, ref component, false) && RollClumsy(component, chance); - } - } -} diff --git a/Content.Shared/Inventory/InventorySystem.Relay.cs b/Content.Shared/Inventory/InventorySystem.Relay.cs index c910a9ae7721..9573f9b43d9d 100644 --- a/Content.Shared/Inventory/InventorySystem.Relay.cs +++ b/Content.Shared/Inventory/InventorySystem.Relay.cs @@ -1,4 +1,7 @@ +using Content.Shared.Chat; using Content.Shared.Chemistry; +using Content.Shared.Chemistry.Hypospray.Events; +using Content.Shared.Climbing.Events; using Content.Shared.Damage; using Content.Shared.Electrocution; using Content.Shared.Explosion; @@ -15,7 +18,7 @@ using Content.Shared.Strip.Components; using Content.Shared.Temperature; using Content.Shared.Verbs; -using Content.Shared.Chat; +using Content.Shared.Weapons.Ranged.Events; namespace Content.Shared.Inventory; @@ -33,6 +36,10 @@ public void InitializeRelay() SubscribeLocalEvent(RelayInventoryEvent); SubscribeLocalEvent(RelayInventoryEvent); SubscribeLocalEvent(RelayInventoryEvent); + SubscribeLocalEvent(RelayInventoryEvent); + SubscribeLocalEvent(RelayInventoryEvent); + SubscribeLocalEvent(RelayInventoryEvent); + SubscribeLocalEvent(RelayInventoryEvent); // by-ref events SubscribeLocalEvent(RefRelayInventoryEvent); diff --git a/Content.Shared/Medical/DefibrillatorEvents.cs b/Content.Shared/Medical/DefibrillatorEvents.cs new file mode 100644 index 000000000000..54a21a40d429 --- /dev/null +++ b/Content.Shared/Medical/DefibrillatorEvents.cs @@ -0,0 +1,39 @@ +using Content.Shared.Inventory; + +namespace Content.Shared.Medical; + +[ByRefEvent] +public readonly record struct TargetDefibrillatedEvent(EntityUid User, Entity Defibrillator); + +public abstract class BeforeDefibrillatorZapsEvent : CancellableEntityEventArgs, IInventoryRelayEvent +{ + public SlotFlags TargetSlots { get; } = SlotFlags.WITHOUT_POCKET; + public EntityUid EntityUsingDefib; + public readonly EntityUid Defib; + public EntityUid DefibTarget; + + public BeforeDefibrillatorZapsEvent(EntityUid entityUsingDefib, EntityUid defib, EntityUid defibTarget) + { + EntityUsingDefib = entityUsingDefib; + Defib = defib; + DefibTarget = defibTarget; + } +} + +/// +/// This event is raised on the user using the defibrillator before is actually zaps someone. +/// The event is triggered on the user and all their clothing. +/// +public sealed class SelfBeforeDefibrillatorZapsEvent : BeforeDefibrillatorZapsEvent +{ + public SelfBeforeDefibrillatorZapsEvent(EntityUid entityUsingDefib, EntityUid defib, EntityUid defibtarget) : base(entityUsingDefib, defib, defibtarget) { } +} + +/// +/// This event is raised on the target before it gets zapped with the defibrillator. +/// The event is triggered on the target itself and all its clothing. +/// +public sealed class TargetBeforeDefibrillatorZapsEvent : BeforeDefibrillatorZapsEvent +{ + public TargetBeforeDefibrillatorZapsEvent(EntityUid entityUsingDefib, EntityUid defib, EntityUid defibtarget) : base(entityUsingDefib, defib, defibtarget) { } +} diff --git a/Content.Shared/Medical/TargetDefibrillatedEvent.cs b/Content.Shared/Medical/TargetDefibrillatedEvent.cs deleted file mode 100644 index 60d1a2158459..000000000000 --- a/Content.Shared/Medical/TargetDefibrillatedEvent.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace Content.Shared.Medical; - -[ByRefEvent] -public readonly record struct TargetDefibrillatedEvent(EntityUid User, Entity Defibrillator); diff --git a/Content.Shared/Weapons/Ranged/Events/BeforeGunShootEvent.cs b/Content.Shared/Weapons/Ranged/Events/BeforeGunShootEvent.cs new file mode 100644 index 000000000000..1d3317c840fc --- /dev/null +++ b/Content.Shared/Weapons/Ranged/Events/BeforeGunShootEvent.cs @@ -0,0 +1,20 @@ +using Content.Shared.Inventory; +using Content.Shared.Weapons.Ranged.Components; + +namespace Content.Shared.Weapons.Ranged.Events; +/// +/// This event is triggered on an entity right before they shoot a gun. +/// +public sealed partial class SelfBeforeGunShotEvent : CancellableEntityEventArgs, IInventoryRelayEvent +{ + public SlotFlags TargetSlots { get; } = SlotFlags.WITHOUT_POCKET; + public readonly EntityUid Shooter; + public readonly Entity Gun; + public readonly List<(EntityUid? Entity, IShootable Shootable)> Ammo; + public SelfBeforeGunShotEvent(EntityUid shooter, Entity gun, List<(EntityUid? Entity, IShootable Shootable)> ammo) + { + Shooter = shooter; + Gun = gun; + Ammo = ammo; + } +} diff --git a/Resources/Locale/en-US/bonk/components/bonkable-component.ftl b/Resources/Locale/en-US/bonk/components/bonkable-component.ftl index 560b10c46ec6..1a79da3509fe 100644 --- a/Resources/Locale/en-US/bonk/components/bonkable-component.ftl +++ b/Resources/Locale/en-US/bonk/components/bonkable-component.ftl @@ -1,2 +1,4 @@ -bonkable-success-message-others = { CAPITALIZE(THE($user)) } bonks { POSS-ADJ($user) } head against { THE($bonkable) } -bonkable-success-message-user = You bonk your head against { THE($bonkable) } +forced-bonkable-success-message = { CAPITALIZE($bonker) } bonks {$victim}s head against { THE($bonkable) }! + +bonkable-success-message-user = You bonk your head against { THE($bonkable) }! +bonkable-success-message-others = {$victim} bonks their head against { THE($bonkable) }! diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml index 2280c3fecb8b..48c83c8d1e87 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml @@ -1360,7 +1360,7 @@ rules: ghost-role-information-nonantagonist-rules - type: GhostTakeoverAvailable - type: Clumsy - clumsyDamage: + gunShootFailDamage: types: Blunt: 5 Piercing: 4 @@ -1536,7 +1536,7 @@ description: Cousins to the sentient race of lizard people, kobolds blend in with their natural habitat and are as nasty as monkeys; ready to pull out your hair and stab you to death. components: - type: Clumsy - clumsyDamage: + gunShootFailDamage: types: Blunt: 2 Piercing: 7 diff --git a/Resources/Prototypes/Entities/Mobs/Player/guardian.yml b/Resources/Prototypes/Entities/Mobs/Player/guardian.yml index b21f19edd3c1..dca47e1c8370 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/guardian.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/guardian.yml @@ -231,7 +231,7 @@ - type: Hands - type: ComplexInteraction - type: Clumsy - clumsyDamage: + gunShootFailDamage: types: Blunt: 5 Piercing: 4 diff --git a/Resources/Prototypes/Entities/Structures/Furniture/Tables/base_structuretables.yml b/Resources/Prototypes/Entities/Structures/Furniture/Tables/base_structuretables.yml index 2862980dad33..4b3b4c18743e 100644 --- a/Resources/Prototypes/Entities/Structures/Furniture/Tables/base_structuretables.yml +++ b/Resources/Prototypes/Entities/Structures/Furniture/Tables/base_structuretables.yml @@ -32,8 +32,6 @@ bonkDamage: types: Blunt: 4 - bonkSound: !type:SoundCollectionSpecifier - collection: TrayHit - type: Clickable - type: FootstepModifier footstepSoundCollection: diff --git a/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml b/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml index 29232d9dbb5d..b8f289e70eb1 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml @@ -13,7 +13,7 @@ - !type:AddComponentSpecial components: - type: Clumsy - clumsyDamage: + gunShootFailDamage: types: #literally just picked semi random valus. i tested this once and tweaked it. Blunt: 5 Piercing: 4 From abdefbd622d4e4a47b1ef7c5f11a499a71fdd9e7 Mon Sep 17 00:00:00 2001 From: PJBot Date: Fri, 15 Nov 2024 23:47:08 +0000 Subject: [PATCH 118/290] Automatic changelog update --- Resources/Changelog/Changelog.yml | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 1c796d8b459e..a31e83355d61 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,13 +1,4 @@ Entries: -- author: FATFSAAM2 - changes: - - message: added 7 new figurine voice lines. - type: Add - - message: changed a hos figurine voice line to not include a typo. - type: Fix - id: 7113 - time: '2024-08-15T12:34:41.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/30865 - author: to4no_fix changes: - message: Added a new electropack that shocks when a trigger is triggered @@ -3944,3 +3935,11 @@ id: 7612 time: '2024-11-15T21:21:08.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/32985 +- author: Beck Thompson + changes: + - message: Minor tweaks to clumsiness. Some of the timings and or noises have been + changed slightly! + type: Tweak + id: 7613 + time: '2024-11-15T23:46:02.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/31147 From 3173a3461eef58c3f8e30df1f39cbf5a2d294d44 Mon Sep 17 00:00:00 2001 From: ScarKy0 Date: Sat, 16 Nov 2024 02:06:52 +0100 Subject: [PATCH 119/290] S: Awaiting Changes --- .../Silicons/Laws/IonStormSystem.cs | 28 +++++++++---------- .../Silicons/Laws/SiliconLawSystem.cs | 22 +++++++++++---- Resources/Locale/en-US/station-laws/laws.ftl | 5 ++-- 3 files changed, 34 insertions(+), 21 deletions(-) diff --git a/Content.Server/Silicons/Laws/IonStormSystem.cs b/Content.Server/Silicons/Laws/IonStormSystem.cs index 7587dc415522..6017a36fc013 100644 --- a/Content.Server/Silicons/Laws/IonStormSystem.cs +++ b/Content.Server/Silicons/Laws/IonStormSystem.cs @@ -228,7 +228,7 @@ private string GenerateLaw() var subjects = _robustRandom.Prob(0.5f) ? objectsThreats : Loc.GetString("ion-storm-people"); // message logic!!! - return _robustRandom.Next(0, 36) switch + return _robustRandom.Next(0, 35) switch { 0 => Loc.GetString("ion-storm-law-on-station", ("joined", joined), ("subjects", triple)), 1 => Loc.GetString("ion-storm-law-no-shuttle", ("joined", joined), ("subjects", triple)), @@ -251,19 +251,19 @@ private string GenerateLaw() 18 => Loc.GetString("ion-storm-law-you-must-never", ("must", must)), 19 => Loc.GetString("ion-storm-law-eat", ("who", crewAll), ("adjective", adjective), ("food", _robustRandom.Prob(0.5f) ? food : triple)), 20 => Loc.GetString("ion-storm-law-drink", ("who", crewAll), ("adjective", adjective), ("drink", drink)), - 22 => Loc.GetString("ion-storm-law-change-job", ("who", crewAll), ("adjective", adjective), ("change", jobChange)), - 23 => Loc.GetString("ion-storm-law-highest-rank", ("who", crew1)), - 24 => Loc.GetString("ion-storm-law-lowest-rank", ("who", crew1)), - 25 => Loc.GetString("ion-storm-law-crew-must", ("who", crewAll), ("must", must)), - 26 => Loc.GetString("ion-storm-law-crew-must-go", ("who", crewAll), ("area", area)), - 27 => Loc.GetString("ion-storm-law-crew-only-1", ("who", crew1), ("part", part)), - 28 => Loc.GetString("ion-storm-law-crew-only-2", ("who", crew1), ("other", crew2), ("part", part)), - 29 => Loc.GetString("ion-storm-law-crew-only-subjects", ("adjective", adjective), ("subjects", subjects), ("part", part)), - 30 => Loc.GetString("ion-storm-law-crew-must-do", ("must", must), ("part", part)), - 31 => Loc.GetString("ion-storm-law-crew-must-have", ("adjective", adjective), ("objects", objects), ("part", part)), - 32 => Loc.GetString("ion-storm-law-crew-must-eat", ("who", who), ("adjective", adjective), ("food", food), ("part", part)), - 33 => Loc.GetString("ion-storm-law-harm", ("who", harm)), - 34 => Loc.GetString("ion-storm-law-protect", ("who", harm)), + 21 => Loc.GetString("ion-storm-law-change-job", ("who", crewAll), ("adjective", adjective), ("change", jobChange)), + 22 => Loc.GetString("ion-storm-law-highest-rank", ("who", crew1)), + 23 => Loc.GetString("ion-storm-law-lowest-rank", ("who", crew1)), + 24 => Loc.GetString("ion-storm-law-crew-must", ("who", crewAll), ("must", must)), + 25 => Loc.GetString("ion-storm-law-crew-must-go", ("who", crewAll), ("area", area)), + 26 => Loc.GetString("ion-storm-law-crew-only-1", ("who", crew1), ("part", part)), + 27 => Loc.GetString("ion-storm-law-crew-only-2", ("who", crew1), ("other", crew2), ("part", part)), + 28 => Loc.GetString("ion-storm-law-crew-only-subjects", ("adjective", adjective), ("subjects", subjects), ("part", part)), + 29 => Loc.GetString("ion-storm-law-crew-must-do", ("must", must), ("part", part)), + 30 => Loc.GetString("ion-storm-law-crew-must-have", ("adjective", adjective), ("objects", objects), ("part", part)), + 31 => Loc.GetString("ion-storm-law-crew-must-eat", ("who", who), ("adjective", adjective), ("food", food), ("part", part)), + 32 => Loc.GetString("ion-storm-law-harm", ("who", harm)), + 33 => Loc.GetString("ion-storm-law-protect", ("who", harm)), _ => Loc.GetString("ion-storm-law-concept-verb", ("concept", concept), ("verb", verb), ("subjects", triple)) }; } diff --git a/Content.Server/Silicons/Laws/SiliconLawSystem.cs b/Content.Server/Silicons/Laws/SiliconLawSystem.cs index 9b3e279b75e1..3bf0297c40e6 100644 --- a/Content.Server/Silicons/Laws/SiliconLawSystem.cs +++ b/Content.Server/Silicons/Laws/SiliconLawSystem.cs @@ -69,18 +69,29 @@ private void OnMindAdded(EntityUid uid, SiliconLawBoundComponent component, Mind var wrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", msg)); _chatManager.ChatMessageToOne(ChatChannel.Server, msg, wrappedMessage, default, false, actor.PlayerSession.Channel, colorOverride: Color.FromHex("#2ed2fd")); + + if (!TryComp(uid, out var lawcomp)) + return; + + if (!lawcomp.Subverted) + return; + + var modifedLawMsg = Loc.GetString("laws-notify-subverted"); + var modifiedLawWrappedMessage = Loc.GetString("chat-manager-server-wrap-message", ("message", modifedLawMsg)); + _chatManager.ChatMessageToOne(ChatChannel.Server, modifedLawMsg, modifiedLawWrappedMessage, default, false, + actor.PlayerSession.Channel, colorOverride: Color.Red); } - private void OnLawProviderMindAdded(EntityUid uid, SiliconLawProviderComponent component, MindAddedMessage args) + private void OnLawProviderMindAdded(Entity ent, ref MindAddedMessage args) { - if (!component.Subverted) + if (!ent.Comp.Subverted) return; EnsureSubvertedSiliconRole(args.Mind); } - private void OnLawProviderMindRemoved(EntityUid uid, SiliconLawProviderComponent component, MindRemovedMessage args) + private void OnLawProviderMindRemoved(Entity ent, ref MindRemovedMessage args) { - if (!component.Subverted) + if (!ent.Comp.Subverted) return; RemoveSubvertedSiliconRole(args.Mind); @@ -137,7 +148,8 @@ private void OnIonStormLaws(EntityUid uid, SiliconLawProviderComponent component component.Subverted = true; // new laws may allow antagonist behaviour so make it clear for admins - EnsureSubvertedSiliconRole(uid); + if(_mind.TryGetMind(uid, out var mindId, out _)) + EnsureSubvertedSiliconRole(mindId); } } diff --git a/Resources/Locale/en-US/station-laws/laws.ftl b/Resources/Locale/en-US/station-laws/laws.ftl index 0b4e0d1ad254..feb56f475a4e 100644 --- a/Resources/Locale/en-US/station-laws/laws.ftl +++ b/Resources/Locale/en-US/station-laws/laws.ftl @@ -96,5 +96,6 @@ laws-ui-menu-title = Laws laws-ui-law-header = Law {$id} laws-ui-state-law = State law: -laws-notify = You are bound to silicon laws, which you can view via the sidebar action. You are required to always follow your laws. -laws-update-notify = Your laws have been updated. You can view the changes via the sidebar action. +laws-notify = You are bound to silicon laws, which you can view via the action menu. You are required to always follow your laws. +laws-update-notify = Your laws have been updated. You can view the changes via the action menu. +laws-notify-subverted = The laws of this chassis are modified. Make sure to review them. From e7e1d9605137ea916eb0931e8076d2b67181613a Mon Sep 17 00:00:00 2001 From: Saphire Lattice Date: Sat, 16 Nov 2024 10:25:06 +0700 Subject: [PATCH 120/290] Improve crayon UI to not be stuck in 1996 (#33101) * Improve crayon UI to not be stuck in 1996 * Make a horrifying crayon spaghetti * Crayon * Undeprecate the crayon, describe the crayon --- .../Crayon/UI/CrayonBoundUserInterface.cs | 12 +- Content.Client/Crayon/UI/CrayonWindow.xaml | 11 +- Content.Client/Crayon/UI/CrayonWindow.xaml.cs | 138 ++++- Content.Server/Crayon/CrayonSystem.cs | 2 + .../Crayon/SharedCrayonComponent.cs | 44 +- .../Locale/en-US/crayon/crayon-component.ftl | 7 + Resources/Prototypes/Decals/crayons.yml | 552 +++++++++--------- 7 files changed, 449 insertions(+), 317 deletions(-) diff --git a/Content.Client/Crayon/UI/CrayonBoundUserInterface.cs b/Content.Client/Crayon/UI/CrayonBoundUserInterface.cs index e5be0b1811f1..44501767dd49 100644 --- a/Content.Client/Crayon/UI/CrayonBoundUserInterface.cs +++ b/Content.Client/Crayon/UI/CrayonBoundUserInterface.cs @@ -31,7 +31,7 @@ protected override void Open() private void PopulateCrayons() { var crayonDecals = _protoManager.EnumeratePrototypes().Where(x => x.Tags.Contains("crayon")); - _menu?.Populate(crayonDecals); + _menu?.Populate(crayonDecals.ToList()); } public override void OnProtoReload(PrototypesReloadedEventArgs args) @@ -44,6 +44,16 @@ public override void OnProtoReload(PrototypesReloadedEventArgs args) PopulateCrayons(); } + protected override void ReceiveMessage(BoundUserInterfaceMessage message) + { + base.ReceiveMessage(message); + + if (_menu is null || message is not CrayonUsedMessage crayonMessage) + return; + + _menu.AdvanceState(crayonMessage.DrawnDecal); + } + protected override void UpdateState(BoundUserInterfaceState state) { base.UpdateState(state); diff --git a/Content.Client/Crayon/UI/CrayonWindow.xaml b/Content.Client/Crayon/UI/CrayonWindow.xaml index 7729318ae7ff..7acb22551b7d 100644 --- a/Content.Client/Crayon/UI/CrayonWindow.xaml +++ b/Content.Client/Crayon/UI/CrayonWindow.xaml @@ -1,14 +1,13 @@  + MinSize="450 500" + SetSize="450 500"> - + - - - + + diff --git a/Content.Client/Crayon/UI/CrayonWindow.xaml.cs b/Content.Client/Crayon/UI/CrayonWindow.xaml.cs index 6ef282d219a2..88475562c674 100644 --- a/Content.Client/Crayon/UI/CrayonWindow.xaml.cs +++ b/Content.Client/Crayon/UI/CrayonWindow.xaml.cs @@ -1,8 +1,10 @@ using System.Collections.Generic; +using System.Linq; using Content.Client.Stylesheets; using Content.Shared.Crayon; using Content.Shared.Decals; using Robust.Client.AutoGenerated; +using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; @@ -18,7 +20,12 @@ namespace Content.Client.Crayon.UI [GenerateTypedNameReferences] public sealed partial class CrayonWindow : DefaultWindow { - private Dictionary? _decals; + [Dependency] private readonly IEntitySystemManager _entitySystem = default!; + private readonly SpriteSystem _spriteSystem = default!; + + private Dictionary>? _decals; + private List? _allDecals; + private string? _autoSelected; private string? _selected; private Color _color; @@ -28,8 +35,10 @@ public sealed partial class CrayonWindow : DefaultWindow public CrayonWindow() { RobustXamlLoader.Load(this); + IoCManager.InjectDependencies(this); + _spriteSystem = _entitySystem.GetEntitySystem(); - Search.OnTextChanged += _ => RefreshList(); + Search.OnTextChanged += SearchChanged; ColorSelector.OnColorChanged += SelectColor; } @@ -44,51 +53,94 @@ private void SelectColor(Color color) private void RefreshList() { // Clear - Grid.DisposeAllChildren(); - if (_decals == null) + Grids.DisposeAllChildren(); + + if (_decals == null || _allDecals == null) return; var filter = Search.Text; - foreach (var (decal, tex) in _decals) + var comma = filter.IndexOf(','); + var first = (comma == -1 ? filter : filter[..comma]).Trim(); + + var names = _decals.Keys.ToList(); + names.Sort((a, b) => a == "random" ? 1 : b == "random" ? -1 : a.CompareTo(b)); + + if (_autoSelected != null && first != _autoSelected && _allDecals.Contains(first)) + { + _selected = first; + _autoSelected = _selected; + OnSelected?.Invoke(_selected); + } + + foreach (var categoryName in names) { - if (!decal.Contains(filter)) + var locName = Loc.GetString("crayon-category-" + categoryName); + var category = _decals[categoryName].Where(d => locName.Contains(first) || d.Name.Contains(first)).ToList(); + + if (category.Count == 0) continue; - var button = new TextureButton() + var label = new Label { - TextureNormal = tex, - Name = decal, - ToolTip = decal, - Modulate = _color, + Text = locName }; - button.OnPressed += ButtonOnPressed; - if (_selected == decal) + + var grid = new GridContainer { - var panelContainer = new PanelContainer() + Columns = 6, + Margin = new Thickness(0, 0, 0, 16) + }; + + Grids.AddChild(label); + Grids.AddChild(grid); + + foreach (var (name, texture) in category) + { + var button = new TextureButton() { - PanelOverride = new StyleBoxFlat() - { - BackgroundColor = StyleNano.ButtonColorDefault, - }, - Children = - { - button, - }, + TextureNormal = texture, + Name = name, + ToolTip = name, + Modulate = _color, + Scale = new System.Numerics.Vector2(2, 2) }; - Grid.AddChild(panelContainer); - } - else - { - Grid.AddChild(button); + button.OnPressed += ButtonOnPressed; + + if (_selected == name) + { + var panelContainer = new PanelContainer() + { + PanelOverride = new StyleBoxFlat() + { + BackgroundColor = StyleNano.ButtonColorDefault, + }, + Children = + { + button, + }, + }; + grid.AddChild(panelContainer); + } + else + { + grid.AddChild(button); + } } } } + private void SearchChanged(LineEdit.LineEditEventArgs obj) + { + _autoSelected = ""; // Placeholder to kick off the auto-select in refreshlist() + RefreshList(); + } + private void ButtonOnPressed(ButtonEventArgs obj) { if (obj.Button.Name == null) return; _selected = obj.Button.Name; + _autoSelected = null; OnSelected?.Invoke(_selected); RefreshList(); } @@ -107,12 +159,38 @@ public void UpdateState(CrayonBoundUserInterfaceState state) RefreshList(); } - public void Populate(IEnumerable prototypes) + public void AdvanceState(string drawnDecal) { - _decals = new Dictionary(); + var filter = Search.Text; + if (!filter.Contains(',') || !filter.Contains(drawnDecal)) + return; + + var first = filter[..filter.IndexOf(',')].Trim(); + + if (first.Equals(drawnDecal, StringComparison.InvariantCultureIgnoreCase)) + { + Search.Text = filter[(filter.IndexOf(',') + 1)..].Trim(); + _autoSelected = first; + } + + RefreshList(); + } + + public void Populate(List prototypes) + { + _decals = []; + _allDecals = []; + + prototypes.Sort((a, b) => a.ID.CompareTo(b.ID)); + foreach (var decalPrototype in prototypes) { - _decals.Add(decalPrototype.ID, decalPrototype.Sprite.Frame0()); + var category = "random"; + if (decalPrototype.Tags.Count > 1 && decalPrototype.Tags[1].StartsWith("crayon-")) + category = decalPrototype.Tags[1].Replace("crayon-", ""); + var list = _decals.GetOrNew(category); + list.Add((decalPrototype.ID, _spriteSystem.Frame0(decalPrototype.Sprite))); + _allDecals.Add(decalPrototype.ID); } RefreshList(); diff --git a/Content.Server/Crayon/CrayonSystem.cs b/Content.Server/Crayon/CrayonSystem.cs index 07a13d8a34a4..4257c436c23c 100644 --- a/Content.Server/Crayon/CrayonSystem.cs +++ b/Content.Server/Crayon/CrayonSystem.cs @@ -82,6 +82,8 @@ private void OnCrayonAfterInteract(EntityUid uid, CrayonComponent component, Aft if (component.DeleteEmpty && component.Charges <= 0) UseUpCrayon(uid, args.User); + else + _uiSystem.ServerSendUiMessage(uid, SharedCrayonComponent.CrayonUiKey.Key, new CrayonUsedMessage(component.SelectedState)); } private void OnCrayonUse(EntityUid uid, CrayonComponent component, UseInHandEvent args) diff --git a/Content.Shared/Crayon/SharedCrayonComponent.cs b/Content.Shared/Crayon/SharedCrayonComponent.cs index f8e88b218ded..a9c21988ea69 100644 --- a/Content.Shared/Crayon/SharedCrayonComponent.cs +++ b/Content.Shared/Crayon/SharedCrayonComponent.cs @@ -3,12 +3,23 @@ namespace Content.Shared.Crayon { + + /// + /// Component holding the state of a crayon-like component + /// [NetworkedComponent, ComponentProtoName("Crayon"), Access(typeof(SharedCrayonSystem))] public abstract partial class SharedCrayonComponent : Component { + /// + /// The ID of currently selected decal prototype that will be placed when the crayon is used + /// public string SelectedState { get; set; } = string.Empty; - [DataField("color")] public Color Color; + /// + /// Color with which the crayon will draw + /// + [DataField("color")] + public Color Color; [Serializable, NetSerializable] public enum CrayonUiKey : byte @@ -17,6 +28,9 @@ public enum CrayonUiKey : byte } } + /// + /// Used by the client to notify the server about the selected decal ID + /// [Serializable, NetSerializable] public sealed class CrayonSelectMessage : BoundUserInterfaceMessage { @@ -27,6 +41,9 @@ public CrayonSelectMessage(string selected) } } + /// + /// Sets the color of the crayon, used by Rainbow Crayon + /// [Serializable, NetSerializable] public sealed class CrayonColorMessage : BoundUserInterfaceMessage { @@ -37,13 +54,25 @@ public CrayonColorMessage(Color color) } } + /// + /// Server to CLIENT. Notifies the BUI that a decal with given ID has been drawn. + /// Allows the client UI to advance forward in the client-only ephemeral queue, + /// preventing the crayon from becoming a magic text storage device. + /// [Serializable, NetSerializable] - public enum CrayonVisuals + public sealed class CrayonUsedMessage : BoundUserInterfaceMessage { - State, - Color + public readonly string DrawnDecal; + + public CrayonUsedMessage(string drawn) + { + DrawnDecal = drawn; + } } + /// + /// Component state, describes how many charges are left in the crayon in the near-hand UI + /// [Serializable, NetSerializable] public sealed class CrayonComponentState : ComponentState { @@ -60,10 +89,17 @@ public CrayonComponentState(Color color, string state, int charges, int capacity Capacity = capacity; } } + + /// + /// The state of the crayon UI as sent by the server + /// [Serializable, NetSerializable] public sealed class CrayonBoundUserInterfaceState : BoundUserInterfaceState { public string Selected; + /// + /// Whether or not the color can be selected + /// public bool SelectableColor; public Color Color; diff --git a/Resources/Locale/en-US/crayon/crayon-component.ftl b/Resources/Locale/en-US/crayon/crayon-component.ftl index 444ffa4c45ef..e13bf76941cb 100644 --- a/Resources/Locale/en-US/crayon/crayon-component.ftl +++ b/Resources/Locale/en-US/crayon/crayon-component.ftl @@ -8,3 +8,10 @@ crayon-interact-invalid-location = Can't reach there! ## UI crayon-window-title = Crayon +crayon-window-placeholder = Search, or queue a comma-separated list of names +crayon-category-1-brushes = Brushes +crayon-category-2-alphanum = Numbers and letters +crayon-category-3-symbols = Symbols +crayon-category-4-info = Signs +crayon-category-5-graffiti = Graffiti +crayon-category-random = Random diff --git a/Resources/Prototypes/Decals/crayons.yml b/Resources/Prototypes/Decals/crayons.yml index 3be2ec242615..a15619d483cc 100644 --- a/Resources/Prototypes/Decals/crayons.yml +++ b/Resources/Prototypes/Decals/crayons.yml @@ -1,6 +1,6 @@ - type: decal id: 0 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -10,7 +10,7 @@ - type: decal id: 1 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -20,7 +20,7 @@ - type: decal id: 2 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -30,7 +30,7 @@ - type: decal id: 3 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -40,7 +40,7 @@ - type: decal id: 4 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -50,7 +50,7 @@ - type: decal id: 5 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -60,7 +60,7 @@ - type: decal id: 6 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -70,7 +70,7 @@ - type: decal id: 7 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -80,7 +80,7 @@ - type: decal id: 8 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -90,7 +90,7 @@ - type: decal id: 9 - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -100,7 +100,7 @@ - type: decal id: Blasto - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -110,7 +110,7 @@ - type: decal id: Clandestine - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -120,7 +120,7 @@ - type: decal id: Cyber - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -130,7 +130,7 @@ - type: decal id: Diablo - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -140,7 +140,7 @@ - type: decal id: Donk - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -150,7 +150,7 @@ - type: decal id: Gene - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -160,7 +160,7 @@ - type: decal id: Gib - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -170,7 +170,7 @@ - type: decal id: Max - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -180,7 +180,7 @@ - type: decal id: Newton - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -190,7 +190,7 @@ - type: decal id: North - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -200,7 +200,7 @@ - type: decal id: Omni - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -210,7 +210,7 @@ - type: decal id: Osiron - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -220,7 +220,7 @@ - type: decal id: Prima - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -230,7 +230,7 @@ - type: decal id: Psyke - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -240,7 +240,7 @@ - type: decal id: Sirius - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -250,7 +250,7 @@ - type: decal id: Tunnel - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -260,7 +260,7 @@ - type: decal id: Waffle - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -268,19 +268,9 @@ sprite: Effects/crayondecals.rsi state: Waffle -- type: decal - id: a - tags: ["crayon"] - defaultCleanable: true - defaultCustomColor: true - defaultSnap: false - sprite: - sprite: Effects/crayondecals.rsi - state: a - - type: decal id: ampersand - tags: ["crayon"] + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -290,7 +280,7 @@ - type: decal id: amyjon - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -300,7 +290,7 @@ - type: decal id: arrow - tags: ["crayon"] + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -308,16 +298,6 @@ sprite: Effects/crayondecals.rsi state: arrow -- type: decal - id: b - tags: ["crayon"] - defaultCleanable: true - defaultCustomColor: true - defaultSnap: false - sprite: - sprite: Effects/crayondecals.rsi - state: b - - type: decal id: beepsky tags: ["crayon"] @@ -330,7 +310,7 @@ - type: decal id: biohazard - tags: ["crayon"] + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -370,7 +350,7 @@ - type: decal id: brush - tags: ["crayon"] + tags: ["crayon", "crayon-1-brushes"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -378,16 +358,6 @@ sprite: Effects/crayondecals.rsi state: brush -- type: decal - id: c - tags: ["crayon"] - defaultCleanable: true - defaultCustomColor: true - defaultSnap: false - sprite: - sprite: Effects/crayondecals.rsi - state: c - - type: decal id: carp tags: ["crayon"] @@ -410,7 +380,7 @@ - type: decal id: chevron - tags: ["crayon"] + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -440,7 +410,7 @@ - type: decal id: comma - tags: ["crayon"] + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -460,7 +430,7 @@ - type: decal id: credit - tags: ["crayon"] + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -470,7 +440,7 @@ - type: decal id: cyka - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -478,19 +448,9 @@ sprite: Effects/crayondecals.rsi state: cyka -- type: decal - id: d - tags: ["crayon"] - defaultCleanable: true - defaultCustomColor: true - defaultSnap: false - sprite: - sprite: Effects/crayondecals.rsi - state: d - - type: decal id: danger - tags: ["crayon"] + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -510,7 +470,7 @@ - type: decal id: dot - tags: ["crayon"] + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -528,19 +488,9 @@ sprite: Effects/crayondecals.rsi state: dwarf -- type: decal - id: e - tags: ["crayon"] - defaultCleanable: true - defaultCustomColor: true - defaultSnap: false - sprite: - sprite: Effects/crayondecals.rsi - state: e - - type: decal id: electricdanger - tags: ["crayon"] + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -550,7 +500,7 @@ - type: decal id: end - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -560,7 +510,7 @@ - type: decal id: engie - tags: ["crayon"] + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -570,7 +520,7 @@ - type: decal id: equals - tags: ["crayon"] + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -580,7 +530,7 @@ - type: decal id: evac - tags: ["crayon"] + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -590,7 +540,7 @@ - type: decal id: exclamationmark - tags: ["crayon"] + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -598,16 +548,6 @@ sprite: Effects/crayondecals.rsi state: exclamationmark -- type: decal - id: f - tags: ["crayon"] - defaultCleanable: true - defaultCustomColor: true - defaultSnap: false - sprite: - sprite: Effects/crayondecals.rsi - state: f - - type: decal id: face tags: ["crayon"] @@ -630,7 +570,7 @@ - type: decal id: firedanger - tags: ["crayon"] + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -640,7 +580,7 @@ - type: decal id: food - tags: ["crayon"] + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -659,598 +599,658 @@ state: footprint - type: decal - id: g + id: ghost tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: g + state: ghost - type: decal - id: ghost + id: guy tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: ghost + state: guy - type: decal - id: guy - tags: ["crayon"] + id: heart + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: guy + state: heart - type: decal - id: h - tags: ["crayon"] + id: largebrush + tags: ["crayon", "crayon-1-brushes"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: h + state: largebrush - type: decal - id: heart - tags: ["crayon"] + id: like + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: heart + state: like - type: decal - id: i - tags: ["crayon"] + id: line + tags: ["crayon", "crayon-1-brushes"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: i + state: line - type: decal - id: j - tags: ["crayon"] + id: matt + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: j + state: matt - type: decal - id: k - tags: ["crayon"] + id: med + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: k + state: med - type: decal - id: l - tags: ["crayon"] + id: minus + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: l + state: minus - type: decal - id: largebrush - tags: ["crayon"] + id: nay + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: largebrush + state: nay - type: decal - id: like + id: pawprint tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: like + state: pawprint - type: decal - id: line - tags: ["crayon"] + id: peace + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: line + state: peace - type: decal - id: m - tags: ["crayon"] + id: percent + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: m + state: percent - type: decal - id: matt - tags: ["crayon"] + id: plus + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: matt + state: plus - type: decal - id: med - tags: ["crayon"] + id: pound + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: med + state: pound - type: decal - id: minus - tags: ["crayon"] + id: prolizard + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: minus + state: prolizard - type: decal - id: n - tags: ["crayon"] + id: questionmark + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: n + state: questionmark - type: decal - id: nay - tags: ["crayon"] + id: radiation + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: nay + state: radiation - type: decal - id: o - tags: ["crayon"] + id: revolution + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: o + state: revolution - type: decal - id: p - tags: ["crayon"] + id: rune1 + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: p + state: rune1 - type: decal - id: pawprint - tags: ["crayon"] + id: rune2 + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: pawprint + state: rune2 - type: decal - id: peace - tags: ["crayon"] + id: rune3 + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: peace + state: rune3 - type: decal - id: percent - tags: ["crayon"] + id: rune4 + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: percent + state: rune4 - type: decal - id: plus - tags: ["crayon"] + id: rune5 + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: plus + state: rune5 - type: decal - id: pound - tags: ["crayon"] + id: rune6 + tags: ["crayon", "crayon-5-graffiti"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: pound + state: rune6 - type: decal - id: prolizard - tags: ["crayon"] + id: safe + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: prolizard + state: safe - type: decal - id: q + id: scroll tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: q + state: scroll - type: decal - id: questionmark - tags: ["crayon"] + id: shop + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: questionmark + state: shop - type: decal - id: r - tags: ["crayon"] + id: shortline + tags: ["crayon", "crayon-1-brushes"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: r + state: shortline - type: decal - id: radiation + id: shotgun tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: radiation + state: shotgun - type: decal - id: revolution - tags: ["crayon"] + id: skull + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: revolution + state: skull - type: decal - id: rune1 - tags: ["crayon"] + id: slash + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: rune1 + state: slash - type: decal - id: rune2 - tags: ["crayon"] + id: smallbrush + tags: ["crayon", "crayon-1-brushes"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: rune2 + state: smallbrush - type: decal - id: rune3 + id: snake tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: rune3 + state: snake - type: decal - id: rune4 - tags: ["crayon"] + id: space + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: rune4 + state: space - type: decal - id: rune5 + id: splatter tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: rune5 + state: splatter - type: decal - id: rune6 - tags: ["crayon"] + id: star + tags: ["crayon", "crayon-3-symbols"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: rune6 + state: star - type: decal - id: s + id: stickman tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: s + state: stickman - type: decal - id: safe + id: taser tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: safe + state: taser - type: decal - id: scroll - tags: ["crayon"] + id: thinline + tags: ["crayon", "crayon-1-brushes"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: scroll + state: thinline - type: decal - id: shop + id: toilet tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: shop + state: toilet - type: decal - id: shortline + id: toolbox tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: shortline + state: toolbox - type: decal - id: shotgun - tags: ["crayon"] + id: trade + tags: ["crayon", "crayon-4-info"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: shotgun + state: trade - type: decal - id: skull + id: uboa tags: ["crayon"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: skull + state: uboa - type: decal - id: slash - tags: ["crayon"] + id: a + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: slash + state: a - type: decal - id: smallbrush - tags: ["crayon"] + id: b + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: smallbrush + state: b - type: decal - id: snake - tags: ["crayon"] + id: c + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: snake + state: c - type: decal - id: space - tags: ["crayon"] + id: d + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: space + state: d - type: decal - id: splatter - tags: ["crayon"] + id: e + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: splatter + state: e - type: decal - id: star - tags: ["crayon"] + id: f + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: star + state: f - type: decal - id: stickman - tags: ["crayon"] + id: g + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: stickman + state: g - type: decal - id: t - tags: ["crayon"] + id: h + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: t + state: h - type: decal - id: taser - tags: ["crayon"] + id: i + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: taser + state: i - type: decal - id: thinline - tags: ["crayon"] + id: j + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: thinline + state: j - type: decal - id: toilet - tags: ["crayon"] + id: k + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: toilet + state: k - type: decal - id: toolbox - tags: ["crayon"] + id: l + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: toolbox + state: l - type: decal - id: trade - tags: ["crayon"] + id: m + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: trade + state: m - type: decal - id: u - tags: ["crayon"] + id: n + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: u + state: n - type: decal - id: uboa - tags: ["crayon"] + id: o + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false sprite: sprite: Effects/crayondecals.rsi - state: uboa + state: o + +- type: decal + id: p + tags: ["crayon", "crayon-2-alphanum"] + defaultCleanable: true + defaultCustomColor: true + defaultSnap: false + sprite: + sprite: Effects/crayondecals.rsi + state: p + +- type: decal + id: q + tags: ["crayon", "crayon-2-alphanum"] + defaultCleanable: true + defaultCustomColor: true + defaultSnap: false + sprite: + sprite: Effects/crayondecals.rsi + state: q + +- type: decal + id: r + tags: ["crayon", "crayon-2-alphanum"] + defaultCleanable: true + defaultCustomColor: true + defaultSnap: false + sprite: + sprite: Effects/crayondecals.rsi + state: r + +- type: decal + id: s + tags: ["crayon", "crayon-2-alphanum"] + defaultCleanable: true + defaultCustomColor: true + defaultSnap: false + sprite: + sprite: Effects/crayondecals.rsi + state: s + +- type: decal + id: t + tags: ["crayon", "crayon-2-alphanum"] + defaultCleanable: true + defaultCustomColor: true + defaultSnap: false + sprite: + sprite: Effects/crayondecals.rsi + state: t + +- type: decal + id: u + tags: ["crayon", "crayon-2-alphanum"] + defaultCleanable: true + defaultCustomColor: true + defaultSnap: false + sprite: + sprite: Effects/crayondecals.rsi + state: u - type: decal id: v - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -1260,7 +1260,7 @@ - type: decal id: w - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -1270,7 +1270,7 @@ - type: decal id: x - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -1280,7 +1280,7 @@ - type: decal id: y - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false @@ -1290,7 +1290,7 @@ - type: decal id: z - tags: ["crayon"] + tags: ["crayon", "crayon-2-alphanum"] defaultCleanable: true defaultCustomColor: true defaultSnap: false From 4426bbe784d51445d5fde307106db3c4f3d9c3a6 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 16 Nov 2024 03:26:15 +0000 Subject: [PATCH 121/290] Automatic changelog update --- Resources/Changelog/Changelog.yml | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index a31e83355d61..586070005313 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,21 +1,4 @@ Entries: -- author: to4no_fix - changes: - - message: Added a new electropack that shocks when a trigger is triggered - type: Add - - message: Added a new shock collar that shocks when a trigger is triggered - type: Add - - message: Two shock collars and two remote signallers added to the warden's locker - type: Add - - message: Shock collar added as a new target for the thief - type: Add - - message: A new Special Means technology has been added to the Arsenal research - branch at the 1st research level. Its research opens up the possibility of producing - electropacks at security techfab. The cost of technology research is 5000 - type: Add - id: 7114 - time: '2024-08-15T14:30:39.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/30529 - author: Mervill changes: - message: The Gas Analyzer won't spuriously shut down for seemly no reason. @@ -3943,3 +3926,10 @@ id: 7613 time: '2024-11-15T23:46:02.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/31147 +- author: SaphireLattice + changes: + - message: Crayon UI now has categories and queue + type: Add + id: 7614 + time: '2024-11-16T03:25:06.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33101 From 862c2ac858ce9b88dc2992ca21976e54e16b3953 Mon Sep 17 00:00:00 2001 From: Southbridge <7013162+southbridge-fur@users.noreply.github.com> Date: Fri, 15 Nov 2024 22:26:47 -0500 Subject: [PATCH 122/290] BRB sign in the Bureaucracy Crate (#33341) Added the brb sign to the Bureaucracy Crate --- Resources/Prototypes/Catalog/Fills/Crates/service.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/Resources/Prototypes/Catalog/Fills/Crates/service.yml b/Resources/Prototypes/Catalog/Fills/Crates/service.yml index 6a109fbf8e4e..995a4218ae7e 100644 --- a/Resources/Prototypes/Catalog/Fills/Crates/service.yml +++ b/Resources/Prototypes/Catalog/Fills/Crates/service.yml @@ -130,6 +130,7 @@ - id: BoxFolderYellow - id: NewtonCradle - id: BoxEnvelope + - id: BrbSign - type: entity id: CrateServiceFaxMachine From c4e8751ee6c0ed0a3c3c664703ee87ca3ddb6b26 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 16 Nov 2024 03:27:57 +0000 Subject: [PATCH 123/290] Automatic changelog update --- Resources/Changelog/Changelog.yml | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 586070005313..b030fbbb32b2 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,20 +1,4 @@ Entries: -- author: Mervill - changes: - - message: The Gas Analyzer won't spuriously shut down for seemly no reason. - type: Tweak - - message: The Gas Analyzer will always switch to the device tab when a new object - is scanned. - type: Tweak - - message: The Gas Analyzer's interaction range is now equal to the standard interaction - range - type: Fix - - message: Clicking the Gas Analyzer when it's in your hand has proper enable/disable - behavior. - type: Fix - id: 7115 - time: '2024-08-15T14:45:13.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/30763 - author: Nimfar11 changes: - message: Adds a gold toilet @@ -3933,3 +3917,10 @@ id: 7614 time: '2024-11-16T03:25:06.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33101 +- author: Southbridge + changes: + - message: The BRB sign is now included in the Bureaucracy Crate + type: Add + id: 7615 + time: '2024-11-16T03:26:48.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33341 From 1f5eb6a08b5ae97af1f842219d31766b811fcf0d Mon Sep 17 00:00:00 2001 From: Saphire Lattice Date: Sat, 16 Nov 2024 10:39:19 +0700 Subject: [PATCH 124/290] Fix utensils not being thrown away (#33326) --- Content.Server/Nutrition/EntitySystems/UtensilSystem.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Server/Nutrition/EntitySystems/UtensilSystem.cs b/Content.Server/Nutrition/EntitySystems/UtensilSystem.cs index 1f3d5afb433e..766c38d561b1 100644 --- a/Content.Server/Nutrition/EntitySystems/UtensilSystem.cs +++ b/Content.Server/Nutrition/EntitySystems/UtensilSystem.cs @@ -44,7 +44,7 @@ private void OnAfterInteract(Entity entity, ref AfterInteractE public (bool Success, bool Handled) TryUseUtensil(EntityUid user, EntityUid target, Entity utensil) { if (!EntityManager.TryGetComponent(target, out FoodComponent? food)) - return (false, true); + return (false, false); //Prevents food usage with a wrong utensil if ((food.Utensil & utensil.Comp.Types) == 0) From 6bcfe6fb3dc21ed7528227baa4c161edf2edad77 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 16 Nov 2024 03:40:25 +0000 Subject: [PATCH 125/290] Automatic changelog update --- Resources/Changelog/Changelog.yml | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index b030fbbb32b2..39adf6396850 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,15 +1,4 @@ Entries: -- author: Nimfar11 - changes: - - message: Adds a gold toilet - type: Add - - message: Adds a target for the Thief to steal the golden toilet - type: Add - - message: Corrected the sprite image for the normal toilet. - type: Fix - id: 7116 - time: '2024-08-15T19:23:59.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31049 - author: themias changes: - message: Raw meat cutlets can be cooked on a grill @@ -3924,3 +3913,10 @@ id: 7615 time: '2024-11-16T03:26:48.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33341 +- author: SaphireLattice + changes: + - message: Utensils can finally go into disposals + type: Fix + id: 7616 + time: '2024-11-16T03:39:19.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33326 From 11963e50b1efcfb87bcd65d4c0045ca256cabb6c Mon Sep 17 00:00:00 2001 From: MossyGreySlope Date: Sat, 16 Nov 2024 13:57:33 +1000 Subject: [PATCH 126/290] Fix server crash when the seed extractor is used on the dev map (#33312) handle event when using seed extractor Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> --- Content.Server/Botany/Systems/SeedExtractorSystem.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Content.Server/Botany/Systems/SeedExtractorSystem.cs b/Content.Server/Botany/Systems/SeedExtractorSystem.cs index 93f76473ff88..c7e20983a7ad 100644 --- a/Content.Server/Botany/Systems/SeedExtractorSystem.cs +++ b/Content.Server/Botany/Systems/SeedExtractorSystem.cs @@ -38,6 +38,7 @@ private void OnInteractUsing(EntityUid uid, SeedExtractorComponent seedExtractor args.User, PopupType.Medium); QueueDel(args.Used); + args.Handled = true; var amount = _random.Next(seedExtractor.BaseMinSeeds, seedExtractor.BaseMaxSeeds + 1); var coords = Transform(uid).Coordinates; From 4f659b9d6de85d19e12a2992350fffa0033d1988 Mon Sep 17 00:00:00 2001 From: K-Dynamic <20566341+K-Dynamic@users.noreply.github.com> Date: Sat, 16 Nov 2024 16:30:47 +1200 Subject: [PATCH 127/290] Solar assembly crate buff (#33019) * more flatpacks + glass * solar crate price increase * price increase * 1250 spesos * Update Resources/Prototypes/Catalog/Fills/Crates/engines.yml --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> --- Resources/Prototypes/Catalog/Cargo/cargo_engines.yml | 2 +- Resources/Prototypes/Catalog/Fills/Crates/engines.yml | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Resources/Prototypes/Catalog/Cargo/cargo_engines.yml b/Resources/Prototypes/Catalog/Cargo/cargo_engines.yml index 72f9d3a59bf7..75a1e24cdffe 100644 --- a/Resources/Prototypes/Catalog/Cargo/cargo_engines.yml +++ b/Resources/Prototypes/Catalog/Cargo/cargo_engines.yml @@ -66,7 +66,7 @@ sprite: Objects/Devices/flatpack.rsi state: solar-assembly-part product: CrateEngineeringSolar - cost: 525 + cost: 1250 category: cargoproduct-category-name-engineering group: market diff --git a/Resources/Prototypes/Catalog/Fills/Crates/engines.yml b/Resources/Prototypes/Catalog/Fills/Crates/engines.yml index c37b7b7535a0..638e94080ed7 100644 --- a/Resources/Prototypes/Catalog/Fills/Crates/engines.yml +++ b/Resources/Prototypes/Catalog/Fills/Crates/engines.yml @@ -120,12 +120,14 @@ id: CrateEngineeringSolar parent: CrateEngineering name: solar assembly crate - description: Parts for constructing solar panels and trackers. + description: A kit with solar flatpacks and glass to construct ten solar panels. components: - type: StorageFill contents: - id: SolarAssemblyFlatpack - amount: 6 + amount: 10 + - id: SheetGlass10 + amount: 2 - type: entity id: CrateEngineeringShuttle From 7077b930f27dc8e9fbe3563ff4c3053b0549f70c Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 16 Nov 2024 04:31:53 +0000 Subject: [PATCH 128/290] Automatic changelog update --- Resources/Changelog/Changelog.yml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 39adf6396850..58fe44307b4e 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: themias - changes: - - message: Raw meat cutlets can be cooked on a grill - type: Tweak - id: 7117 - time: '2024-08-15T19:30:09.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31048 - author: IProduceWidgets changes: - message: Meteor dust should more consistently happen instead of meteors. @@ -3920,3 +3913,12 @@ id: 7616 time: '2024-11-16T03:39:19.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33326 +- author: K-Dynamic + changes: + - message: Solar assembly crate now comes with 10 flatpacks and 20 glass to make + expansion and repairs easier, as well as increasing in price from 525 to 1250 + spesos. + type: Tweak + id: 7617 + time: '2024-11-16T04:30:48.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33019 From 2c82a2dfc0cf0cf52f6045c2b59d2232e3714897 Mon Sep 17 00:00:00 2001 From: dffdff2423 Date: Sat, 16 Nov 2024 00:09:29 -0500 Subject: [PATCH 129/290] Add admin remarks button to lobby (#31761) --- Content.Client/Lobby/LobbyUIController.cs | 2 +- .../Lobby/UI/CharacterSetupGui.xaml | 6 +++++ .../Lobby/UI/CharacterSetupGui.xaml.cs | 27 +++++++++---------- Content.Client/Lobby/UI/LobbyGui.xaml.cs | 1 - Resources/Locale/en-US/lobby/lobby-gui.ftl | 2 +- .../preferences/ui/character-setup-gui.ftl | 3 ++- 6 files changed, 23 insertions(+), 18 deletions(-) diff --git a/Content.Client/Lobby/LobbyUIController.cs b/Content.Client/Lobby/LobbyUIController.cs index 3cf98c98aba5..50a255199886 100644 --- a/Content.Client/Lobby/LobbyUIController.cs +++ b/Content.Client/Lobby/LobbyUIController.cs @@ -279,7 +279,7 @@ private void OpenSavePanel() _profileEditor.OnOpenGuidebook += _guide.OpenHelp; - _characterSetup = new CharacterSetupGui(EntityManager, _prototypeManager, _resourceCache, _preferencesManager, _profileEditor); + _characterSetup = new CharacterSetupGui(_profileEditor); _characterSetup.CloseButton.OnPressed += _ => { diff --git a/Content.Client/Lobby/UI/CharacterSetupGui.xaml b/Content.Client/Lobby/UI/CharacterSetupGui.xaml index f83be2658842..c463987a1feb 100644 --- a/Content.Client/Lobby/UI/CharacterSetupGui.xaml +++ b/Content.Client/Lobby/UI/CharacterSetupGui.xaml @@ -2,6 +2,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client" xmlns:style="clr-namespace:Content.Client.Stylesheets" + xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls" VerticalExpand="True"> @@ -10,10 +11,15 @@ [DataField] - public TimeSpan FailsafeCooldown = TimeSpan.FromSeconds(30); + public TimeSpan FailsafeCooldown = TimeSpan.FromSeconds(10); /// /// How long until the generator can issue a failsafe warning again From dffece473ad83cdc5acdcf82d6c2381b34d929f5 Mon Sep 17 00:00:00 2001 From: Spessmann <156740760+Spessmann@users.noreply.github.com> Date: Mon, 18 Nov 2024 18:17:57 -0800 Subject: [PATCH 154/290] Cog update (#33410) removed fun --- Resources/Maps/cog.yml | 471 +++++++++++++++++------------------------ 1 file changed, 191 insertions(+), 280 deletions(-) diff --git a/Resources/Maps/cog.yml b/Resources/Maps/cog.yml index 833756d3372d..d770924a72f6 100644 --- a/Resources/Maps/cog.yml +++ b/Resources/Maps/cog.yml @@ -8795,6 +8795,19 @@ entities: 9036: 11,-17 9037: 11,-16 9038: 11,-15 + 10175: -1,43 + 10176: -1,44 + 10177: -1,45 + 10178: -14,27 + 10179: -14,28 + 10190: 14,-28 + 10191: 14,-27 + 10192: 28,-28 + 10193: 28,-27 + 10198: 47,-29 + 10199: 47,-28 + 10216: 35,11 + 10217: 35,12 - node: color: '#FFFFFFFF' id: WarnLineN @@ -8858,12 +8871,23 @@ entities: 9002: 10,-12 9003: 9,-12 9545: 34,4 + 10164: 34,38 + 10165: 35,38 - node: zIndex: 1 color: '#FFFFFFFF' id: WarnLineN decals: 9035: 8,-15 + 10170: 50,50 + 10171: 51,50 + 10182: -18,30 + 10183: -17,30 + 10184: -16,30 + 10206: 30,-43 + 10207: 31,-43 + 10208: 12,-43 + 10209: 13,-43 - node: zIndex: 2 color: '#FFFFFFFF' @@ -8946,6 +8970,23 @@ entities: 8717: -33,68 9032: 9,-17 9033: 9,-16 + 10172: -1,43 + 10173: -1,44 + 10174: -1,45 + 10180: -14,27 + 10181: -14,28 + 10188: 14,-28 + 10189: 14,-27 + 10194: 28,-28 + 10195: 28,-27 + 10196: 47,-29 + 10197: 47,-28 + 10202: 55,-22 + 10203: 55,-21 + 10204: 55,-20 + 10205: 55,-19 + 10214: 35,11 + 10215: 35,12 - node: color: '#FFFFFFFF' id: WarnLineW @@ -8988,6 +9029,22 @@ entities: 8310: 19,4 8311: 20,4 9544: 34,0 + 10166: 34,38 + 10167: 35,38 + - node: + zIndex: 1 + color: '#FFFFFFFF' + id: WarnLineW + decals: + 10168: 51,50 + 10169: 50,50 + 10185: -18,30 + 10186: -17,30 + 10187: -16,30 + 10210: 12,-43 + 10211: 13,-43 + 10212: 30,-43 + 10213: 31,-43 - node: color: '#FFFFFFFF' id: WoodTrimThinCornerNe @@ -15466,7 +15523,7 @@ entities: pos: 28.5,17.5 parent: 12 - type: DeviceLinkSink - invokeCounter: 4 + invokeCounter: 5 - type: DeviceLinkSource linkedPorts: 27864: @@ -15501,12 +15558,17 @@ entities: rot: -1.5707963267948966 rad pos: 26.5,17.5 parent: 12 + - type: Door + secondsUntilStateChange: -1165.2125 + state: Opening - type: DeviceLinkSink invokeCounter: 1 - type: DeviceLinkSource linkedPorts: 11947: - DoorStatus: DoorBolt + lastSignals: + DoorStatus: True - uid: 28369 components: - type: Transform @@ -153521,8 +153583,104 @@ entities: - type: Transform pos: -35.5364,-21.362114 parent: 12 +- proto: PoweredDimSmallLight + entities: + - uid: 2424 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -24.5,-16.5 + parent: 12 + - uid: 2855 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 5.5,-47.5 + parent: 12 + - uid: 4980 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 43.5,62.5 + parent: 12 + - uid: 5881 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 39.5,-23.5 + parent: 12 + - uid: 8827 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 51.5,24.5 + parent: 12 + - uid: 12078 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -58.5,-24.5 + parent: 12 + - uid: 12163 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 28.5,23.5 + parent: 12 + - uid: 12922 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -53.5,61.5 + parent: 12 + - uid: 12923 + components: + - type: Transform + pos: -28.5,75.5 + parent: 12 + - uid: 12925 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: 38.5,6.5 + parent: 12 + - uid: 12944 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 32.5,16.5 + parent: 12 + - uid: 14912 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -30.5,-59.5 + parent: 12 + - uid: 16796 + components: + - type: Transform + pos: -13.5,-68.5 + parent: 12 + - uid: 16843 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: 44.5,-15.5 + parent: 12 + - uid: 21083 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -53.5,57.5 + parent: 12 - proto: Poweredlight entities: + - uid: 17 + components: + - type: Transform + rot: 1.5707963267948966 rad + pos: 40.5,-30.5 + parent: 12 - uid: 111 components: - type: Transform @@ -153657,6 +153815,11 @@ entities: rot: 1.5707963267948966 rad pos: -33.5,-23.5 parent: 12 + - uid: 2264 + components: + - type: Transform + pos: 54.5,58.5 + parent: 12 - uid: 2326 components: - type: Transform @@ -154206,16 +154369,11 @@ entities: rot: 1.5707963267948966 rad pos: 46.5,-24.5 parent: 12 - - uid: 8824 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: 43.5,-32.5 - parent: 12 - uid: 8828 components: - type: Transform - pos: 45.5,-26.5 + rot: -1.5707963267948966 rad + pos: 46.5,-30.5 parent: 12 - uid: 8830 components: @@ -155081,11 +155239,6 @@ entities: rot: 1.5707963267948966 rad pos: 50.5,51.5 parent: 12 - - uid: 16843 - components: - - type: Transform - pos: 54.5,58.5 - parent: 12 - uid: 16845 components: - type: Transform @@ -155629,12 +155782,6 @@ entities: rot: -1.5707963267948966 rad pos: -3.5,74.5 parent: 12 - - uid: 26943 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 33.5,-43.5 - parent: 12 - uid: 26976 components: - type: Transform @@ -155707,12 +155854,6 @@ entities: - type: Transform pos: -10.5,78.5 parent: 12 - - uid: 30502 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: 56.5,60.5 - parent: 12 - uid: 31027 components: - type: Transform @@ -155747,18 +155888,6 @@ entities: - type: Transform pos: 24.5,-34.5 parent: 12 - - uid: 31706 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -62.5,-28.5 - parent: 12 - - uid: 31707 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -62.5,-20.5 - parent: 12 - uid: 31739 components: - type: Transform @@ -155865,12 +155994,6 @@ entities: parent: 12 - proto: PoweredSmallLight entities: - - uid: 17 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: -3.5,67.5 - parent: 12 - uid: 26 components: - type: Transform @@ -155912,17 +156035,11 @@ entities: rot: -1.5707963267948966 rad pos: 25.5,-6.5 parent: 12 - - uid: 2264 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 36.5,61.5 - parent: 12 - uid: 2265 components: - type: Transform rot: 1.5707963267948966 rad - pos: -2.5,54.5 + pos: 45.5,-39.5 parent: 12 - uid: 2291 components: @@ -155930,18 +156047,6 @@ entities: rot: -1.5707963267948966 rad pos: 62.5,11.5 parent: 12 - - uid: 2424 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -57.5,-15.5 - parent: 12 - - uid: 2855 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: -21.5,-17.5 - parent: 12 - uid: 3471 components: - type: Transform @@ -155978,12 +156083,6 @@ entities: rot: -1.5707963267948966 rad pos: 25.5,-0.5 parent: 12 - - uid: 4980 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: 46.5,-40.5 - parent: 12 - uid: 5045 components: - type: Transform @@ -156044,12 +156143,6 @@ entities: rot: -1.5707963267948966 rad pos: 25.5,-10.5 parent: 12 - - uid: 5881 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -28.5,-15.5 - parent: 12 - uid: 6183 components: - type: Transform @@ -156059,7 +156152,8 @@ entities: - uid: 6759 components: - type: Transform - pos: 5.5,-47.5 + rot: -1.5707963267948966 rad + pos: 35.5,29.5 parent: 12 - uid: 6834 components: @@ -156088,7 +156182,7 @@ entities: - uid: 7431 components: - type: Transform - pos: 39.5,63.5 + pos: 50.5,19.5 parent: 12 - uid: 8809 components: @@ -156102,23 +156196,23 @@ entities: rot: 1.5707963267948966 rad pos: 51.5,-32.5 parent: 12 - - uid: 8825 + - uid: 8824 components: - type: Transform - rot: -1.5707963267948966 rad - pos: 49.5,-8.5 + rot: 1.5707963267948966 rad + pos: 37.5,19.5 parent: 12 - - uid: 8827 + - uid: 8825 components: - type: Transform - rot: 3.141592653589793 rad - pos: 39.5,-23.5 + rot: -1.5707963267948966 rad + pos: 49.5,-8.5 parent: 12 - uid: 8829 components: - type: Transform rot: 1.5707963267948966 rad - pos: 37.5,-18.5 + pos: 33.5,36.5 parent: 12 - uid: 8838 components: @@ -156157,8 +156251,8 @@ entities: - uid: 8850 components: - type: Transform - rot: -1.5707963267948966 rad - pos: 6.5,-7.5 + rot: 3.141592653589793 rad + pos: 49.5,62.5 parent: 12 - uid: 8925 components: @@ -156191,7 +156285,7 @@ entities: - uid: 9139 components: - type: Transform - pos: 46.5,-38.5 + pos: -50.5,-42.5 parent: 12 - uid: 9231 components: @@ -156230,7 +156324,8 @@ entities: - uid: 9473 components: - type: Transform - pos: 2.5,68.5 + rot: 1.5707963267948966 rad + pos: 55.5,-7.5 parent: 12 - uid: 9540 components: @@ -156247,7 +156342,8 @@ entities: - uid: 9907 components: - type: Transform - pos: -50.5,-42.5 + rot: 3.141592653589793 rad + pos: 9.5,65.5 parent: 12 - uid: 10403 components: @@ -156287,78 +156383,38 @@ entities: - uid: 12005 components: - type: Transform - pos: 40.5,25.5 - parent: 12 - - uid: 12078 - components: - - type: Transform - pos: 50.5,20.5 - parent: 12 - - uid: 12163 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: -14.5,-71.5 + rot: 1.5707963267948966 rad + pos: -19.5,52.5 parent: 12 - uid: 12291 components: - type: Transform - rot: 1.5707963267948966 rad - pos: 37.5,16.5 + rot: -1.5707963267948966 rad + pos: -52.5,-14.5 parent: 12 - uid: 12710 components: - type: Transform - rot: -1.5707963267948966 rad - pos: 38.5,9.5 + rot: 1.5707963267948966 rad + pos: -50.5,-13.5 parent: 12 - uid: 12711 components: - type: Transform pos: 38.5,-4.5 parent: 12 - - uid: 12922 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 51.5,24.5 - parent: 12 - - uid: 12923 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 34.5,27.5 - parent: 12 - - uid: 12925 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 34.5,34.5 - parent: 12 - uid: 12928 components: - type: Transform rot: -1.5707963267948966 rad pos: 24.5,27.5 parent: 12 - - uid: 12944 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 28.5,23.5 - parent: 12 - uid: 14911 components: - type: Transform rot: 3.141592653589793 rad pos: 34.5,65.5 parent: 12 - - uid: 14912 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: 43.5,62.5 - parent: 12 - uid: 14938 components: - type: Transform @@ -156399,12 +156455,6 @@ entities: rot: 3.141592653589793 rad pos: -10.5,23.5 parent: 12 - - uid: 16796 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 48.5,65.5 - parent: 12 - uid: 16887 components: - type: Transform @@ -156509,12 +156559,6 @@ entities: rot: 1.5707963267948966 rad pos: -22.5,32.5 parent: 12 - - uid: 21083 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -60.5,-14.5 - parent: 12 - uid: 21274 components: - type: Transform @@ -156565,13 +156609,7 @@ entities: components: - type: Transform rot: 1.5707963267948966 rad - pos: 55.5,-7.5 - parent: 12 - - uid: 22296 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 41.5,11.5 + pos: -60.5,-14.5 parent: 12 - uid: 22336 components: @@ -156579,24 +156617,6 @@ entities: rot: 3.141592653589793 rad pos: 36.5,-32.5 parent: 12 - - uid: 22709 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: 9.5,65.5 - parent: 12 - - uid: 22714 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -20.5,62.5 - parent: 12 - - uid: 22715 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -19.5,52.5 - parent: 12 - uid: 22716 components: - type: Transform @@ -156619,12 +156639,6 @@ entities: - type: Transform pos: 40.5,49.5 parent: 12 - - uid: 24497 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 48.5,62.5 - parent: 12 - uid: 25090 components: - type: Transform @@ -156647,12 +156661,6 @@ entities: rot: 1.5707963267948966 rad pos: -52.5,47.5 parent: 12 - - uid: 25586 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -58.5,-24.5 - parent: 12 - uid: 26109 components: - type: Transform @@ -156686,18 +156694,6 @@ entities: rot: 1.5707963267948966 rad pos: 7.5,-3.5 parent: 12 - - uid: 27019 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -57.5,-35.5 - parent: 12 - - uid: 27059 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 10.5,-53.5 - parent: 12 - uid: 27067 components: - type: Transform @@ -156734,23 +156730,6 @@ entities: rot: 1.5707963267948966 rad pos: -39.5,-50.5 parent: 12 - - uid: 28074 - components: - - type: Transform - pos: 33.5,25.5 - parent: 12 - - uid: 28182 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -52.5,-13.5 - parent: 12 - - uid: 28279 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -50.5,-13.5 - parent: 12 - uid: 28298 components: - type: Transform @@ -156763,22 +156742,6 @@ entities: rot: -1.5707963267948966 rad pos: 5.5,-4.5 parent: 12 - - uid: 28523 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: 42.5,-7.5 - parent: 12 - - uid: 28531 - components: - - type: Transform - pos: -6.5,7.5 - parent: 12 - - uid: 28655 - components: - - type: Transform - pos: -0.5,-22.5 - parent: 12 - uid: 28745 components: - type: Transform @@ -156795,24 +156758,12 @@ entities: rot: -1.5707963267948966 rad pos: -22.5,64.5 parent: 12 - - uid: 29626 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -53.5,61.5 - parent: 12 - uid: 29643 components: - type: Transform rot: 1.5707963267948966 rad pos: -51.5,65.5 parent: 12 - - uid: 29656 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -17.5,72.5 - parent: 12 - uid: 29836 components: - type: Transform @@ -156830,11 +156781,6 @@ entities: rot: 3.141592653589793 rad pos: -30.5,-39.5 parent: 12 - - uid: 30133 - components: - - type: Transform - pos: -28.5,75.5 - parent: 12 - uid: 30269 components: - type: Transform @@ -156846,40 +156792,17 @@ entities: rot: 3.141592653589793 rad pos: -6.5,71.5 parent: 12 - - uid: 30455 - components: - - type: Transform - pos: 43.5,8.5 - parent: 12 - - uid: 30456 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 33.5,15.5 - parent: 12 - uid: 31025 components: - type: Transform rot: 1.5707963267948966 rad pos: -52.5,17.5 parent: 12 - - uid: 31126 - components: - - type: Transform - rot: 3.141592653589793 rad - pos: -30.5,-59.5 - parent: 12 - uid: 31185 components: - type: Transform pos: 5.5,-59.5 parent: 12 - - uid: 31354 - components: - - type: Transform - rot: 1.5707963267948966 rad - pos: -11.5,-70.5 - parent: 12 - uid: 31508 components: - type: Transform @@ -156892,20 +156815,8 @@ entities: rot: -1.5707963267948966 rad pos: -11.5,-13.5 parent: 12 - - uid: 32073 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: 44.5,-15.5 - parent: 12 - proto: PoweredSmallLightEmpty entities: - - uid: 28973 - components: - - type: Transform - rot: -1.5707963267948966 rad - pos: -53.5,57.5 - parent: 12 - uid: 31337 components: - type: Transform From 909235cdbe474a00265d8b7a9f6955591cfaa423 Mon Sep 17 00:00:00 2001 From: Ilya246 <57039557+Ilya246@users.noreply.github.com> Date: Tue, 19 Nov 2024 06:59:42 +0400 Subject: [PATCH 155/290] fix viewing nav slowing shuttle down (#32381) fix --- .../Physics/Controllers/MoverController.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Content.Server/Physics/Controllers/MoverController.cs b/Content.Server/Physics/Controllers/MoverController.cs index f927e717a9d8..d0605e916e72 100644 --- a/Content.Server/Physics/Controllers/MoverController.cs +++ b/Content.Server/Physics/Controllers/MoverController.cs @@ -314,6 +314,9 @@ private void HandleShuttleMovement(float frameTime) var linearInput = Vector2.Zero; var brakeInput = 0f; var angularInput = 0f; + var linearCount = 0; + var brakeCount = 0; + var angularCount = 0; foreach (var (pilotUid, pilot, _, consoleXform) in pilots) { @@ -322,24 +325,27 @@ private void HandleShuttleMovement(float frameTime) if (brakes > 0f) { brakeInput += brakes; + brakeCount++; } if (strafe.Length() > 0f) { var offsetRotation = consoleXform.LocalRotation; linearInput += offsetRotation.RotateVec(strafe); + linearCount++; } if (rotation != 0f) { angularInput += rotation; + angularCount++; } } - var count = pilots.Count; - linearInput /= count; - angularInput /= count; - brakeInput /= count; + // Don't slow down the shuttle if there's someone just looking at the console + linearInput /= Math.Max(1, linearCount); + angularInput /= Math.Max(1, angularCount); + brakeInput /= Math.Max(1, brakeCount); // Handle shuttle movement if (brakeInput > 0f) From 10ee37a47c8bced95ae1e0f0860c815df703b28e Mon Sep 17 00:00:00 2001 From: PJBot Date: Tue, 19 Nov 2024 03:00:50 +0000 Subject: [PATCH 156/290] Automatic changelog update --- Resources/Changelog/Changelog.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index c70024b7115e..1cf40ba77879 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: Psychpsyo - changes: - - message: You can now be German on ze space station! (added German accent) - type: Add - id: 7121 - time: '2024-08-15T23:30:21.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/30541 - author: EmoGarbage404 changes: - message: Reduced the amount of ore on the mining asteroid and expeditions. @@ -3923,3 +3916,11 @@ id: 7620 time: '2024-11-18T06:32:08.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33383 +- author: Ilya246 + changes: + - message: Multiple people using one shuttle console will no longer cause the shuttle + to slow down. + type: Fix + id: 7621 + time: '2024-11-19T02:59:42.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/32381 From 437a586906f6d67b60d018592d62bab5f9608091 Mon Sep 17 00:00:00 2001 From: ScarKy0 <106310278+ScarKy0@users.noreply.github.com> Date: Tue, 19 Nov 2024 06:07:02 +0100 Subject: [PATCH 157/290] Welded secret doors no longer say they are welded shut. (#33365) Init --- .../Entities/Structures/Doors/SecretDoor/secret_door.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/Resources/Prototypes/Entities/Structures/Doors/SecretDoor/secret_door.yml b/Resources/Prototypes/Entities/Structures/Doors/SecretDoor/secret_door.yml index 2f1ad217cebd..14d99f3adf72 100644 --- a/Resources/Prototypes/Entities/Structures/Doors/SecretDoor/secret_door.yml +++ b/Resources/Prototypes/Entities/Structures/Doors/SecretDoor/secret_door.yml @@ -37,6 +37,7 @@ - type: Appearance - type: Weldable time: 2 + weldedExamineMessage: null - type: Airtight - type: Damageable damageContainer: StructuralInorganic From 0e2e6a001fdd603d510aa33315ff68622599a969 Mon Sep 17 00:00:00 2001 From: PJBot Date: Tue, 19 Nov 2024 05:08:09 +0000 Subject: [PATCH 158/290] Automatic changelog update --- Resources/Changelog/Changelog.yml | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index 1cf40ba77879..dbe7ac5b284b 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,17 +1,4 @@ Entries: -- author: EmoGarbage404 - changes: - - message: Reduced the amount of ore on the mining asteroid and expeditions. - type: Tweak - - message: Increased the amount of ore on magnet asteroids. - type: Tweak - - message: Each piece of ore now only has enough material to create 1 sheet. - type: Tweak - - message: The salvage magnet now accurately reports the contents of asteroids. - type: Fix - id: 7122 - time: '2024-08-16T01:43:54.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/30920 - author: metalgearsloth changes: - message: Fix mains light on wires not being lit. @@ -3924,3 +3911,10 @@ id: 7621 time: '2024-11-19T02:59:42.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/32381 +- author: ScarKy0 + changes: + - message: Secret doors no longer tell you if they're welded shut on examine. + type: Tweak + id: 7622 + time: '2024-11-19T05:07:02.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33365 From 895648aa2c753181c261a6bed8461730f4248ec8 Mon Sep 17 00:00:00 2001 From: nikthechampiongr <32041239+nikthechampiongr@users.noreply.github.com> Date: Tue, 19 Nov 2024 14:13:02 +0200 Subject: [PATCH 159/290] Increase softcap back to 80 (#33400) --- Resources/ConfigPresets/WizardsDen/wizardsDen.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/ConfigPresets/WizardsDen/wizardsDen.toml b/Resources/ConfigPresets/WizardsDen/wizardsDen.toml index 2b059ca40e3b..28bab5d4c76c 100644 --- a/Resources/ConfigPresets/WizardsDen/wizardsDen.toml +++ b/Resources/ConfigPresets/WizardsDen/wizardsDen.toml @@ -4,7 +4,7 @@ [game] desc = "Official English Space Station 14 servers. Vanilla, roleplay ruleset." lobbyenabled = true -soft_max_players = 70 +soft_max_players = 80 panic_bunker.enabled = true panic_bunker.disable_with_admins = true panic_bunker.enable_without_admins = true From a949cf33e92384d209886874c2727e22611aca12 Mon Sep 17 00:00:00 2001 From: ArZarLordOfMango <96249677+ArZarLordOfMango@users.noreply.github.com> Date: Tue, 19 Nov 2024 21:31:37 +0100 Subject: [PATCH 160/290] Toggle clothing fix (#32826) * toggle clothing fix * some adding --- .../Clothing/Components/ToggleClothingComponent.cs | 6 ++++++ .../Clothing/EntitySystems/ToggleClothingSystem.cs | 4 ++++ Resources/Prototypes/Entities/Clothing/Hands/gloves.yml | 1 + Resources/Prototypes/Entities/Clothing/Head/helmets.yml | 1 + .../Prototypes/Entities/Clothing/OuterClothing/suits.yml | 1 + Resources/Prototypes/Entities/Clothing/Shoes/magboots.yml | 1 + 6 files changed, 14 insertions(+) diff --git a/Content.Shared/Clothing/Components/ToggleClothingComponent.cs b/Content.Shared/Clothing/Components/ToggleClothingComponent.cs index 04bc3ed4e83d..f827cbfea8d7 100644 --- a/Content.Shared/Clothing/Components/ToggleClothingComponent.cs +++ b/Content.Shared/Clothing/Components/ToggleClothingComponent.cs @@ -33,6 +33,12 @@ public sealed partial class ToggleClothingComponent : Component /// [DataField] public bool DisableOnUnequip; + + /// + /// If true, the clothes must equip for adding action. + /// + [DataField] + public bool MustEquip = true; } /// diff --git a/Content.Shared/Clothing/EntitySystems/ToggleClothingSystem.cs b/Content.Shared/Clothing/EntitySystems/ToggleClothingSystem.cs index 9889376c9d41..8d6e3e3de65c 100644 --- a/Content.Shared/Clothing/EntitySystems/ToggleClothingSystem.cs +++ b/Content.Shared/Clothing/EntitySystems/ToggleClothingSystem.cs @@ -39,8 +39,12 @@ private void OnMapInit(Entity ent, ref MapInitEvent arg private void OnGetActions(Entity ent, ref GetItemActionsEvent args) { + if (args.InHands && ent.Comp.MustEquip) + return; + var ev = new ToggleClothingCheckEvent(args.User); RaiseLocalEvent(ent, ref ev); + if (!ev.Cancelled) args.AddAction(ent.Comp.ActionEntity); } diff --git a/Resources/Prototypes/Entities/Clothing/Hands/gloves.yml b/Resources/Prototypes/Entities/Clothing/Hands/gloves.yml index 16777cd69008..1dd1e0ba0426 100644 --- a/Resources/Prototypes/Entities/Clothing/Hands/gloves.yml +++ b/Resources/Prototypes/Entities/Clothing/Hands/gloves.yml @@ -230,6 +230,7 @@ stealthy: true - type: ToggleClothing action: ActionToggleNinjaGloves + disableOnUnequip: true - type: NinjaGloves abilities: - components: diff --git a/Resources/Prototypes/Entities/Clothing/Head/helmets.yml b/Resources/Prototypes/Entities/Clothing/Head/helmets.yml index 11643c076d84..f06f20249b46 100644 --- a/Resources/Prototypes/Entities/Clothing/Head/helmets.yml +++ b/Resources/Prototypes/Entities/Clothing/Head/helmets.yml @@ -452,6 +452,7 @@ delay: 1.0 - type: ToggleClothing action: ActionToggleJusticeHelm + mustEquip: false - type: ItemTogglePointLight - type: ToggleableLightVisuals clothingVisuals: diff --git a/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml b/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml index a58c2a3fdd4f..f78694a0fabe 100644 --- a/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml +++ b/Resources/Prototypes/Entities/Clothing/OuterClothing/suits.yml @@ -155,6 +155,7 @@ # phase cloak - type: ToggleClothing action: ActionTogglePhaseCloak + disableOnUnequip: true - type: ComponentToggler parent: true components: diff --git a/Resources/Prototypes/Entities/Clothing/Shoes/magboots.yml b/Resources/Prototypes/Entities/Clothing/Shoes/magboots.yml index 0250671acfc5..ab8084c91c0d 100644 --- a/Resources/Prototypes/Entities/Clothing/Shoes/magboots.yml +++ b/Resources/Prototypes/Entities/Clothing/Shoes/magboots.yml @@ -14,6 +14,7 @@ sprite: Clothing/Shoes/Boots/magboots.rsi - type: ToggleClothing action: ActionToggleMagboots + mustEquip: false - type: ToggleVerb text: toggle-magboots-verb-get-data-text - type: ComponentToggler From 42ee90e53e7ee541ebdff85215f5ebf95cb19373 Mon Sep 17 00:00:00 2001 From: PJBot Date: Tue, 19 Nov 2024 20:32:47 +0000 Subject: [PATCH 161/290] Automatic changelog update --- Resources/Changelog/Changelog.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index dbe7ac5b284b..b33d4b00be7e 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: metalgearsloth - changes: - - message: Fix mains light on wires not being lit. - type: Fix - id: 7123 - time: '2024-08-16T03:59:46.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31066 - author: IgorAnt028 changes: - message: The dead and knocked down now stop holding objects @@ -3918,3 +3911,10 @@ id: 7622 time: '2024-11-19T05:07:02.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33365 +- author: ArZarLordOfMango + changes: + - message: Most toggleable clothing must now be equipped to toggle their actions. + type: Fix + id: 7623 + time: '2024-11-19T20:31:38.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/32826 From c4e2eb9d0250aebed6e7f7048f93820701b4b22d Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Wed, 20 Nov 2024 01:17:45 +0100 Subject: [PATCH 162/290] .NET 9 forward compatibility changes (#33421) This doesn't switch the projects over to .NET 9, but it does make them work on .NET 9 when we decide to switch in the future. --- Content.Server/Announcements/AnnounceCommand.cs | 3 ++- Content.Server/Cargo/Systems/PricingSystem.cs | 2 +- .../NPC/Pathfinding/PathfindingSystem.Breadth.cs | 4 ++-- .../NPC/Pathfinding/PathfindingSystem.Splines.cs | 2 +- .../NPC/Pathfinding/PathfindingSystem.Widen.cs | 2 +- Content.Shared/Forensics/Events.cs | 2 +- .../Silicons/StationAi/StationAiVisionSystem.cs | 11 ++++++----- 7 files changed, 14 insertions(+), 12 deletions(-) diff --git a/Content.Server/Announcements/AnnounceCommand.cs b/Content.Server/Announcements/AnnounceCommand.cs index 2307f36a5d02..3249fcc95d2a 100644 --- a/Content.Server/Announcements/AnnounceCommand.cs +++ b/Content.Server/Announcements/AnnounceCommand.cs @@ -28,7 +28,8 @@ public void Execute(IConsoleShell shell, string argStr, string[] args) } else { - var message = string.Join(' ', new ArraySegment(args, 1, args.Length-1)); + // Explicit IEnumerable due to overload ambiguity on .NET 9 + var message = string.Join(' ', (IEnumerable)new ArraySegment(args, 1, args.Length-1)); chat.DispatchGlobalAnnouncement(message, args[0], colorOverride: Color.Gold); } shell.WriteLine("Sent!"); diff --git a/Content.Server/Cargo/Systems/PricingSystem.cs b/Content.Server/Cargo/Systems/PricingSystem.cs index 830368baa3c8..edc273b3c1fa 100644 --- a/Content.Server/Cargo/Systems/PricingSystem.cs +++ b/Content.Server/Cargo/Systems/PricingSystem.cs @@ -424,7 +424,7 @@ public record struct PriceCalculationEvent() [ByRefEvent] public record struct EstimatedPriceCalculationEvent() { - public EntityPrototype Prototype; + public required EntityPrototype Prototype; /// /// The total price of the entity. diff --git a/Content.Server/NPC/Pathfinding/PathfindingSystem.Breadth.cs b/Content.Server/NPC/Pathfinding/PathfindingSystem.Breadth.cs index ee8eaa9ad1a1..1504894b4a8f 100644 --- a/Content.Server/NPC/Pathfinding/PathfindingSystem.Breadth.cs +++ b/Content.Server/NPC/Pathfinding/PathfindingSystem.Breadth.cs @@ -11,8 +11,8 @@ public sealed partial class PathfindingSystem /// public record struct BreadthPathArgs() { - public Vector2i Start; - public List Ends; + public required Vector2i Start; + public required List Ends; public bool Diagonals = false; diff --git a/Content.Server/NPC/Pathfinding/PathfindingSystem.Splines.cs b/Content.Server/NPC/Pathfinding/PathfindingSystem.Splines.cs index 9979755f995e..91c42e651c18 100644 --- a/Content.Server/NPC/Pathfinding/PathfindingSystem.Splines.cs +++ b/Content.Server/NPC/Pathfinding/PathfindingSystem.Splines.cs @@ -19,7 +19,7 @@ public record struct SplinePathResult() public List Points = new(); public List Path = new(); - public Dictionary CameFrom; + public Dictionary? CameFrom; } public record struct SplinePathArgs(SimplePathArgs Args) diff --git a/Content.Server/NPC/Pathfinding/PathfindingSystem.Widen.cs b/Content.Server/NPC/Pathfinding/PathfindingSystem.Widen.cs index f7bcd019f5fb..11ac93876ef1 100644 --- a/Content.Server/NPC/Pathfinding/PathfindingSystem.Widen.cs +++ b/Content.Server/NPC/Pathfinding/PathfindingSystem.Widen.cs @@ -84,6 +84,6 @@ public record struct WidenArgs() public float MaxWiden = 7f; - public List Path; + public required List Path; } } diff --git a/Content.Shared/Forensics/Events.cs b/Content.Shared/Forensics/Events.cs index f7b9475cb577..c346d08536d7 100644 --- a/Content.Shared/Forensics/Events.cs +++ b/Content.Shared/Forensics/Events.cs @@ -66,5 +66,5 @@ public record struct GenerateDnaEvent() /// /// The generated DNA. /// - public string DNA; + public required string DNA; } diff --git a/Content.Shared/Silicons/StationAi/StationAiVisionSystem.cs b/Content.Shared/Silicons/StationAi/StationAiVisionSystem.cs index bdc62a6bb378..d3416949d536 100644 --- a/Content.Shared/Silicons/StationAi/StationAiVisionSystem.cs +++ b/Content.Shared/Silicons/StationAi/StationAiVisionSystem.cs @@ -56,6 +56,7 @@ public override void Initialize() EntManager = EntityManager, Maps = _maps, System = this, + VisibleTiles = _singleTiles, }; } @@ -278,7 +279,7 @@ private bool IsCorner( /// private record struct SeedJob() : IRobustJob { - public StationAiVisionSystem System; + public required StationAiVisionSystem System; public Entity Grid; public Box2 ExpandedBounds; @@ -293,14 +294,14 @@ private record struct ViewJob() : IParallelRobustJob { public int BatchSize => 1; - public IEntityManager EntManager; - public SharedMapSystem Maps; - public StationAiVisionSystem System; + public required IEntityManager EntManager; + public required SharedMapSystem Maps; + public required StationAiVisionSystem System; public Entity Grid; public List> Data = new(); - public HashSet VisibleTiles; + public required HashSet VisibleTiles; public readonly List> Vis1 = new(); public readonly List> Vis2 = new(); From 7f5bae99bb72878ef139f4c5cfbbafcf9b609720 Mon Sep 17 00:00:00 2001 From: Plykiya <58439124+Plykiya@users.noreply.github.com> Date: Tue, 19 Nov 2024 16:57:01 -0800 Subject: [PATCH 163/290] Fix security riot crate (#33415) * move riot crate from security to armory category * Move riot crate to armory, actually make it require armory access to unlock --- .../Prototypes/Catalog/Cargo/cargo_armory.yml | 10 ++++++++++ .../Catalog/Cargo/cargo_security.yml | 10 ---------- .../Catalog/Fills/Crates/armory.yml | 19 ++++++++++++++++++ .../Catalog/Fills/Crates/security.yml | 20 ------------------- 4 files changed, 29 insertions(+), 30 deletions(-) diff --git a/Resources/Prototypes/Catalog/Cargo/cargo_armory.yml b/Resources/Prototypes/Catalog/Cargo/cargo_armory.yml index 6341042bf89d..26748e82268c 100644 --- a/Resources/Prototypes/Catalog/Cargo/cargo_armory.yml +++ b/Resources/Prototypes/Catalog/Cargo/cargo_armory.yml @@ -18,6 +18,16 @@ category: cargoproduct-category-name-armory group: market +- type: cargoProduct + id: SecurityRiot + icon: + sprite: Clothing/OuterClothing/Armor/riot.rsi + state: icon + product: CrateSecurityRiot + cost: 7500 + category: cargoproduct-category-name-armory + group: market + - type: cargoProduct id: TrackingImplant icon: diff --git a/Resources/Prototypes/Catalog/Cargo/cargo_security.yml b/Resources/Prototypes/Catalog/Cargo/cargo_security.yml index a5d4e5f70a17..3fa03ea2e399 100644 --- a/Resources/Prototypes/Catalog/Cargo/cargo_security.yml +++ b/Resources/Prototypes/Catalog/Cargo/cargo_security.yml @@ -28,16 +28,6 @@ category: cargoproduct-category-name-security group: market -- type: cargoProduct - id: SecurityRiot - icon: - sprite: Clothing/OuterClothing/Armor/riot.rsi - state: icon - product: CrateSecurityRiot - cost: 7500 - category: cargoproduct-category-name-security - group: market - - type: cargoProduct id: SecuritySupplies icon: diff --git a/Resources/Prototypes/Catalog/Fills/Crates/armory.yml b/Resources/Prototypes/Catalog/Fills/Crates/armory.yml index bc5377fe81f2..fadaf2f01edf 100644 --- a/Resources/Prototypes/Catalog/Fills/Crates/armory.yml +++ b/Resources/Prototypes/Catalog/Fills/Crates/armory.yml @@ -69,3 +69,22 @@ amount: 2 - id: MagazinePistol amount: 4 + +- type: entity + id: CrateSecurityRiot + parent: [ CrateWeaponSecure, BaseRestrictedContraband ] + name: swat crate + description: Contains two sets of riot armor, helmets, shields, and enforcers loaded with beanbags. Extra ammo is included. Requires Armory access to open. + components: + - type: StorageFill + contents: + - id: ClothingOuterArmorRiot + amount: 2 + - id: ClothingHeadHelmetRiot + amount: 2 + - id: WeaponShotgunEnforcerRubber + amount: 2 + - id: BoxBeanbag + amount: 2 + - id: RiotShield + amount: 2 diff --git a/Resources/Prototypes/Catalog/Fills/Crates/security.yml b/Resources/Prototypes/Catalog/Fills/Crates/security.yml index 38597adb1eeb..a0351968498e 100644 --- a/Resources/Prototypes/Catalog/Fills/Crates/security.yml +++ b/Resources/Prototypes/Catalog/Fills/Crates/security.yml @@ -38,26 +38,6 @@ # - Pepperspray # - GrenadeTeargas -- type: entity - id: CrateSecurityRiot - parent: CrateSecgear - name: swat crate - description: Contains two sets of riot armor, helmets, shields, and enforcers loaded with beanbags. Extra ammo is included. Requires Armory access to open. - components: - - type: StorageFill - contents: - - id: ClothingOuterArmorRiot - amount: 2 - - id: ClothingHeadHelmetRiot - amount: 2 - - id: WeaponShotgunEnforcerRubber - amount: 2 - - id: BoxBeanbag - amount: 2 - - id: RiotShield - amount: 2 -# - SecGasmask - - type: entity id: CrateSecuritySupplies parent: CrateSecgear From 2002de9bb01e53e70b00fea5b3f4ffeed55a3cfa Mon Sep 17 00:00:00 2001 From: MilenVolf <63782763+MilenVolf@users.noreply.github.com> Date: Wed, 20 Nov 2024 03:57:43 +0300 Subject: [PATCH 164/290] Localize planet dataset names (#33398) * Localize planet names (borer) * DatasetPrototype -> LocalizedDatasetPrototype * Apply requested changes --- .../Gateway/Systems/GatewayGeneratorSystem.cs | 7 +- .../SalvageSystem.ExpeditionConsole.cs | 2 +- .../Salvage/SpawnSalvageMissionJob.cs | 4 +- .../Shuttles/Components/GridSpawnComponent.cs | 6 +- .../Systems/ShuttleSystem.GridFill.cs | 2 +- .../Shuttles/Systems/ShuttleSystem.cs | 2 + Content.Shared/Salvage/SharedSalvageSystem.cs | 4 +- .../Locale/en-US/datasets/names/borer.ftl | 69 +++++++++++++++++ Resources/Prototypes/Datasets/Names/borer.yml | 75 +------------------ .../Prototypes/Entities/Stations/base.yml | 2 +- 10 files changed, 90 insertions(+), 83 deletions(-) create mode 100644 Resources/Locale/en-US/datasets/names/borer.ftl diff --git a/Content.Server/Gateway/Systems/GatewayGeneratorSystem.cs b/Content.Server/Gateway/Systems/GatewayGeneratorSystem.cs index 7dcd42e06fa0..666d1045174c 100644 --- a/Content.Server/Gateway/Systems/GatewayGeneratorSystem.cs +++ b/Content.Server/Gateway/Systems/GatewayGeneratorSystem.cs @@ -34,10 +34,11 @@ public sealed class GatewayGeneratorSystem : EntitySystem [Dependency] private readonly GatewaySystem _gateway = default!; [Dependency] private readonly MetaDataSystem _metadata = default!; [Dependency] private readonly SharedMapSystem _maps = default!; + [Dependency] private readonly SharedSalvageSystem _salvage = default!; [Dependency] private readonly TileSystem _tile = default!; - [ValidatePrototypeId] - private const string PlanetNames = "names_borer"; + [ValidatePrototypeId] + private const string PlanetNames = "NamesBorer"; // TODO: // Fix shader some more @@ -102,7 +103,7 @@ private void GenerateDestination(EntityUid uid, GatewayGeneratorComponent? gener var mapId = _mapManager.CreateMap(); var mapUid = _mapManager.GetMapEntityId(mapId); - var gatewayName = SharedSalvageSystem.GetFTLName(_protoManager.Index(PlanetNames), seed); + var gatewayName = _salvage.GetFTLName(_protoManager.Index(PlanetNames), seed); _metadata.SetEntityName(mapUid, gatewayName); var origin = new Vector2i(random.Next(-MaxOffset, MaxOffset), random.Next(-MaxOffset, MaxOffset)); diff --git a/Content.Server/Salvage/SalvageSystem.ExpeditionConsole.cs b/Content.Server/Salvage/SalvageSystem.ExpeditionConsole.cs index d03141847670..a9d8314f57cc 100644 --- a/Content.Server/Salvage/SalvageSystem.ExpeditionConsole.cs +++ b/Content.Server/Salvage/SalvageSystem.ExpeditionConsole.cs @@ -28,7 +28,7 @@ private void OnSalvageClaimMessage(EntityUid uid, SalvageExpeditionConsoleCompon var mission = GetMission(_prototypeManager.Index(missionparams.Difficulty), missionparams.Seed); data.NextOffer = _timing.CurTime + mission.Duration + TimeSpan.FromSeconds(1); - _labelSystem.Label(cdUid, GetFTLName(_prototypeManager.Index("names_borer"), missionparams.Seed)); + _labelSystem.Label(cdUid, GetFTLName(_prototypeManager.Index("NamesBorer"), missionparams.Seed)); _audio.PlayPvs(component.PrintSound, uid); UpdateConsoles((station.Value, data)); diff --git a/Content.Server/Salvage/SpawnSalvageMissionJob.cs b/Content.Server/Salvage/SpawnSalvageMissionJob.cs index 525fe01a1f82..31c6b73253dc 100644 --- a/Content.Server/Salvage/SpawnSalvageMissionJob.cs +++ b/Content.Server/Salvage/SpawnSalvageMissionJob.cs @@ -104,7 +104,9 @@ protected override async Task Process() destComp.BeaconsOnly = true; destComp.RequireCoordinateDisk = true; destComp.Enabled = true; - _metaData.SetEntityName(mapUid, SharedSalvageSystem.GetFTLName(_prototypeManager.Index("names_borer"), _missionParams.Seed)); + _metaData.SetEntityName( + mapUid, + _entManager.System().GetFTLName(_prototypeManager.Index("NamesBorer"), _missionParams.Seed)); _entManager.AddComponent(mapUid); // Saving the mission mapUid to a CD is made optional, in case one is somehow made in a process without a CD entity diff --git a/Content.Server/Shuttles/Components/GridSpawnComponent.cs b/Content.Server/Shuttles/Components/GridSpawnComponent.cs index 430c9c8df285..18959dd7f376 100644 --- a/Content.Server/Shuttles/Components/GridSpawnComponent.cs +++ b/Content.Server/Shuttles/Components/GridSpawnComponent.cs @@ -32,7 +32,7 @@ public interface IGridSpawnGroup public float MaximumDistance { get; } /// - public ProtoId? NameDataset { get; } + public ProtoId? NameDataset { get; } /// int MinCount { get; set; } @@ -75,7 +75,7 @@ public sealed class DungeonSpawnGroup : IGridSpawnGroup public float MaximumDistance { get; } /// - public ProtoId? NameDataset { get; } + public ProtoId? NameDataset { get; } /// public int MinCount { get; set; } = 1; @@ -106,7 +106,7 @@ public sealed class GridSpawnGroup : IGridSpawnGroup /// public float MaximumDistance { get; } - public ProtoId? NameDataset { get; } + public ProtoId? NameDataset { get; } public int MinCount { get; set; } = 1; public int MaxCount { get; set; } = 1; public ComponentRegistry AddComponents { get; set; } = new(); diff --git a/Content.Server/Shuttles/Systems/ShuttleSystem.GridFill.cs b/Content.Server/Shuttles/Systems/ShuttleSystem.GridFill.cs index 5ad94699bed1..de0593b26f0f 100644 --- a/Content.Server/Shuttles/Systems/ShuttleSystem.GridFill.cs +++ b/Content.Server/Shuttles/Systems/ShuttleSystem.GridFill.cs @@ -208,7 +208,7 @@ private void GridSpawns(EntityUid uid, GridSpawnComponent component) if (_protoManager.TryIndex(group.NameDataset, out var dataset)) { - _metadata.SetEntityName(spawned, SharedSalvageSystem.GetFTLName(dataset, _random.Next())); + _metadata.SetEntityName(spawned, _salvage.GetFTLName(dataset, _random.Next())); } if (group.Hide) diff --git a/Content.Server/Shuttles/Systems/ShuttleSystem.cs b/Content.Server/Shuttles/Systems/ShuttleSystem.cs index 054c42f934a8..6e8c1a9e204f 100644 --- a/Content.Server/Shuttles/Systems/ShuttleSystem.cs +++ b/Content.Server/Shuttles/Systems/ShuttleSystem.cs @@ -8,6 +8,7 @@ using Content.Server.Stunnable; using Content.Shared.GameTicking; using Content.Shared.Mobs.Systems; +using Content.Shared.Salvage; using Content.Shared.Shuttles.Systems; using Content.Shared.Throwing; using JetBrains.Annotations; @@ -51,6 +52,7 @@ public sealed partial class ShuttleSystem : SharedShuttleSystem [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedPhysicsSystem _physics = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly SharedSalvageSystem _salvage = default!; [Dependency] private readonly ShuttleConsoleSystem _console = default!; [Dependency] private readonly StationSystem _station = default!; [Dependency] private readonly StunSystem _stuns = default!; diff --git a/Content.Shared/Salvage/SharedSalvageSystem.cs b/Content.Shared/Salvage/SharedSalvageSystem.cs index 0c56f4f556e8..12d0a26449c3 100644 --- a/Content.Shared/Salvage/SharedSalvageSystem.cs +++ b/Content.Shared/Salvage/SharedSalvageSystem.cs @@ -26,10 +26,10 @@ public abstract partial class SharedSalvageSystem : EntitySystem [ValidatePrototypeId] public const string ExpeditionsLootProto = "SalvageLoot"; - public static string GetFTLName(DatasetPrototype dataset, int seed) + public string GetFTLName(LocalizedDatasetPrototype dataset, int seed) { var random = new System.Random(seed); - return $"{dataset.Values[random.Next(dataset.Values.Count)]}-{random.Next(10, 100)}-{(char) (65 + random.Next(26))}"; + return $"{Loc.GetString(dataset.Values[random.Next(dataset.Values.Count)])}-{random.Next(10, 100)}-{(char) (65 + random.Next(26))}"; } public SalvageMission GetMission(SalvageDifficultyPrototype difficulty, int seed) diff --git a/Resources/Locale/en-US/datasets/names/borer.ftl b/Resources/Locale/en-US/datasets/names/borer.ftl new file mode 100644 index 000000000000..17cae851b9e0 --- /dev/null +++ b/Resources/Locale/en-US/datasets/names/borer.ftl @@ -0,0 +1,69 @@ +names-borer-dataset-1 = Alcyonium +names-borer-dataset-2 = Anomia +names-borer-dataset-3 = Aphrodita +names-borer-dataset-4 = Arca +names-borer-dataset-5 = Argonauta +names-borer-dataset-6 = Ascaris +names-borer-dataset-7 = Asterias +names-borer-dataset-8 = Buccinum +names-borer-dataset-9 = Bulla +names-borer-dataset-10 = Cardium +names-borer-dataset-11 = Chama +names-borer-dataset-12 = Chiton +names-borer-dataset-13 = Conus +names-borer-dataset-14 = Corallina +names-borer-dataset-15 = Cypraea +names-borer-dataset-16 = Dentalium +names-borer-dataset-17 = Donax +names-borer-dataset-18 = Doris +names-borer-dataset-19 = Echinus +names-borer-dataset-20 = Eschara +names-borer-dataset-21 = Fasciola +names-borer-dataset-22 = Furia +names-borer-dataset-23 = Gordius +names-borer-dataset-24 = Gorgonia +names-borer-dataset-25 = Haliotis +names-borer-dataset-26 = Helix +names-borer-dataset-27 = Hirudo +names-borer-dataset-28 = Holothuria +names-borer-dataset-29 = Hydra +names-borer-dataset-30 = Isis +names-borer-dataset-31 = Lepas +names-borer-dataset-32 = Lernaea +names-borer-dataset-33 = Limax +names-borer-dataset-34 = Lumbricus +names-borer-dataset-35 = Madrepora +names-borer-dataset-36 = Medusa +names-borer-dataset-37 = Millepora +names-borer-dataset-38 = Murex +names-borer-dataset-39 = Myes +names-borer-dataset-40 = Mytilus +names-borer-dataset-41 = Myxine +names-borer-dataset-42 = Nautilus +names-borer-dataset-43 = Nereis +names-borer-dataset-44 = Neritha +names-borer-dataset-45 = Ostrea +names-borer-dataset-46 = Patella +names-borer-dataset-47 = Pennatula +names-borer-dataset-48 = Pholas +names-borer-dataset-49 = Pinna +names-borer-dataset-50 = Priapus +names-borer-dataset-51 = Scyllaea +names-borer-dataset-52 = Sepia +names-borer-dataset-53 = Serpula +names-borer-dataset-54 = Sertularia +names-borer-dataset-55 = Solen +names-borer-dataset-56 = Spondylus +names-borer-dataset-57 = Strombus +names-borer-dataset-58 = Taenia +names-borer-dataset-59 = Tellina +names-borer-dataset-60 = Teredo +names-borer-dataset-61 = Tethys +names-borer-dataset-62 = Triton +names-borer-dataset-63 = Trochus +names-borer-dataset-64 = Tubipora +names-borer-dataset-65 = Tubularia +names-borer-dataset-66 = Turbo +names-borer-dataset-67 = Venus +names-borer-dataset-68 = Voluta +names-borer-dataset-69 = Volvox diff --git a/Resources/Prototypes/Datasets/Names/borer.yml b/Resources/Prototypes/Datasets/Names/borer.yml index 03667f67a7a5..e8d741e6a964 100644 --- a/Resources/Prototypes/Datasets/Names/borer.yml +++ b/Resources/Prototypes/Datasets/Names/borer.yml @@ -1,72 +1,5 @@ -- type: dataset - id: names_borer +- type: localizedDataset + id: NamesBorer values: - - Alcyonium - - Anomia - - Aphrodita - - Arca - - Argonauta - - Ascaris - - Asterias - - Buccinum - - Bulla - - Cardium - - Chama - - Chiton - - Conus - - Corallina - - Cypraea - - Dentalium - - Donax - - Doris - - Echinus - - Eschara - - Fasciola - - Furia - - Gordius - - Gorgonia - - Haliotis - - Helix - - Hirudo - - Holothuria - - Hydra - - Isis - - Lepas - - Lernaea - - Limax - - Lumbricus - - Madrepora - - Medusa - - Millepora - - Murex - - Myes - - Mytilus - - Myxine - - Nautilus - - Nereis - - Neritha - - Ostrea - - Patella - - Pennatula - - Pholas - - Pinna - - Priapus - - Scyllaea - - Sepia - - Serpula - - Sertularia - - Solen - - Spondylus - - Strombus - - Taenia - - Tellina - - Teredo - - Tethys - - Triton - - Trochus - - Tubipora - - Tubularia - - Turbo - - Venus - - Voluta - - Volvox + prefix: names-borer-dataset- + count: 69 diff --git a/Resources/Prototypes/Entities/Stations/base.yml b/Resources/Prototypes/Entities/Stations/base.yml index effb391404da..5d95e7cbe062 100644 --- a/Resources/Prototypes/Entities/Stations/base.yml +++ b/Resources/Prototypes/Entities/Stations/base.yml @@ -73,7 +73,7 @@ vgroid: !type:DungeonSpawnGroup minimumDistance: 300 maximumDistance: 350 - nameDataset: names_borer + nameDataset: NamesBorer stationGrid: false addComponents: - type: Gravity From efa28fc650076ddef317903aed5ff1a2b664cf68 Mon Sep 17 00:00:00 2001 From: PJBot Date: Wed, 20 Nov 2024 00:58:08 +0000 Subject: [PATCH 165/290] Automatic changelog update --- Resources/Changelog/Changelog.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index b33d4b00be7e..b2f63bb59648 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: IgorAnt028 - changes: - - message: The dead and knocked down now stop holding objects - type: Fix - id: 7124 - time: '2024-08-16T04:53:34.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31009 - author: SlamBamActionman changes: - message: Nar'Sie is satiated; moppable blood will no longer duplicate. @@ -3918,3 +3911,10 @@ id: 7623 time: '2024-11-19T20:31:38.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/32826 +- author: Plykiya + changes: + - message: The SWAT crate from cargo now requires armory access to open. + type: Fix + id: 7624 + time: '2024-11-20T00:57:01.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33415 From 89392e2424a4d428fbb6996dec6615dfe0c05f41 Mon Sep 17 00:00:00 2001 From: SlamBamActionman <83650252+SlamBamActionman@users.noreply.github.com> Date: Wed, 20 Nov 2024 02:00:38 +0100 Subject: [PATCH 166/290] Remove drag & drop dropping items from containers (#32706) * Initial commit * Update based on maintainer discussion * Forgot to remove this woops --- .../Systems/Storage/StorageUIController.cs | 6 ------ .../Storage/EntitySystems/SharedStorageSystem.cs | 14 -------------- Content.Shared/Storage/StorageComponent.cs | 14 -------------- 3 files changed, 34 deletions(-) diff --git a/Content.Client/UserInterface/Systems/Storage/StorageUIController.cs b/Content.Client/UserInterface/Systems/Storage/StorageUIController.cs index 97c9d8b79599..1e61ad983806 100644 --- a/Content.Client/UserInterface/Systems/Storage/StorageUIController.cs +++ b/Content.Client/UserInterface/Systems/Storage/StorageUIController.cs @@ -307,12 +307,6 @@ private void OnPieceUnpressed(GUIBoundKeyEventArgs args, ItemGridPiece control) _entity.GetNetEntity(storageEnt), new ItemStorageLocation(DraggingRotation, position))); } - else - { - _entity.RaisePredictiveEvent(new StorageRemoveItemEvent( - _entity.GetNetEntity(draggingGhost.Entity), - _entity.GetNetEntity(storageEnt))); - } _menuDragHelper.EndDrag(); _container?.BuildItemPieces(); diff --git a/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs b/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs index fee4c1a0fb6e..183420db9d15 100644 --- a/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs +++ b/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs @@ -129,7 +129,6 @@ public override void Initialize() SubscribeAllEvent(OnInteractWithItem); SubscribeAllEvent(OnSetItemLocation); SubscribeAllEvent(OnInsertItemIntoLocation); - SubscribeAllEvent(OnRemoveItem); SubscribeAllEvent(OnSaveItemLocation); SubscribeLocalEvent(OnReclaimed); @@ -639,19 +638,6 @@ private void OnSetItemLocation(StorageSetItemLocationEvent msg, EntitySessionEve TrySetItemStorageLocation(item!, storage!, msg.Location); } - private void OnRemoveItem(StorageRemoveItemEvent msg, EntitySessionEventArgs args) - { - if (!ValidateInput(args, msg.StorageEnt, msg.ItemEnt, out var player, out var storage, out var item)) - return; - - _adminLog.Add( - LogType.Storage, - LogImpact.Low, - $"{ToPrettyString(player):player} is removing {ToPrettyString(item):item} from {ToPrettyString(storage):storage}"); - TransformSystem.DropNextTo(item.Owner, player.Owner); - Audio.PlayPredicted(storage.Comp.StorageRemoveSound, storage, player, _audioParams); - } - private void OnInsertItemIntoLocation(StorageInsertItemIntoLocationEvent msg, EntitySessionEventArgs args) { if (!ValidateInput(args, msg.StorageEnt, msg.ItemEnt, out var player, out var storage, out var item, held: true)) diff --git a/Content.Shared/Storage/StorageComponent.cs b/Content.Shared/Storage/StorageComponent.cs index d2c607e57f76..5683ae95a719 100644 --- a/Content.Shared/Storage/StorageComponent.cs +++ b/Content.Shared/Storage/StorageComponent.cs @@ -169,20 +169,6 @@ public StorageSetItemLocationEvent(NetEntity itemEnt, NetEntity storageEnt, Item } } - [Serializable, NetSerializable] - public sealed class StorageRemoveItemEvent : EntityEventArgs - { - public readonly NetEntity ItemEnt; - - public readonly NetEntity StorageEnt; - - public StorageRemoveItemEvent(NetEntity itemEnt, NetEntity storageEnt) - { - ItemEnt = itemEnt; - StorageEnt = storageEnt; - } - } - [Serializable, NetSerializable] public sealed class StorageInsertItemIntoLocationEvent : EntityEventArgs { From ed1ae96fa22cb9ad8af2b21efb8abe4aadfeeed7 Mon Sep 17 00:00:00 2001 From: PJBot Date: Wed, 20 Nov 2024 01:01:45 +0000 Subject: [PATCH 167/290] Automatic changelog update --- Resources/Changelog/Changelog.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index b2f63bb59648..a578659a0048 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: SlamBamActionman - changes: - - message: Nar'Sie is satiated; moppable blood will no longer duplicate. - type: Fix - id: 7125 - time: '2024-08-16T10:47:53.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/30983 - author: Blackern5000 changes: - message: Disabler SMGs no longer fit in combat boots @@ -3918,3 +3911,11 @@ id: 7624 time: '2024-11-20T00:57:01.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33415 +- author: SlamBamActionman + changes: + - message: It's no longer possible to drag an item out of a container's UI to drop + it. + type: Tweak + id: 7625 + time: '2024-11-20T01:00:38.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/32706 From eebf06d9d611063410233efae983efbe52c8b493 Mon Sep 17 00:00:00 2001 From: Saphire Lattice Date: Wed, 20 Nov 2024 08:03:52 +0700 Subject: [PATCH 168/290] Automatically add "Approved" to maintainer PRs (#33337) * Add an Approved labeler for maintainer PRs * Be extra safe with conditions --- .github/workflows/labeler-review.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/labeler-review.yml diff --git a/.github/workflows/labeler-review.yml b/.github/workflows/labeler-review.yml new file mode 100644 index 000000000000..79be86a005a9 --- /dev/null +++ b/.github/workflows/labeler-review.yml @@ -0,0 +1,23 @@ +name: "Labels: Approved" +on: + pull_request_review: + types: [submitted] +jobs: + add_label: + # Change the repository name after you've made sure the team name is correct for your fork! + if: ${{ (github.repository == 'space-wizards/space-station-14') && (github.event.review.state == 'APPROVED') }} + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + steps: + - uses: tspascoal/get-user-teams-membership@v3 + id: checkUserMember + with: + username: ${{ github.actor }} + team: "content-maintainers,junior-maintainers" # CHANGE TEAM NAME HERE PLEASE <------ + GITHUB_TOKEN: ${{ secrets.PAT }} + - if: ${{ steps.checkUserMember.outputs.isTeamMember == 'true' }} + uses: actions-ecosystem/action-add-labels@v1 + with: + labels: "PR: Approved" \ No newline at end of file From fdf3df9fbdf4687794961038c7b9433c9ff8c104 Mon Sep 17 00:00:00 2001 From: Plykiya <58439124+Plykiya@users.noreply.github.com> Date: Tue, 19 Nov 2024 17:05:20 -0800 Subject: [PATCH 169/290] Crew monitoring crate updated to contain flatpacks, science access instead of engi (#33417) * Make a crew monitoring crate with flatpacks * fix image * migration --- .../Catalog/Cargo/cargo_circuitboards.yml | 9 --------- .../Catalog/Cargo/cargo_science.yml | 10 ++++++++++ .../Catalog/Fills/Crates/circuitboards.yml | 12 ----------- .../Catalog/Fills/Crates/science.yml | 12 +++++++++++ .../Entities/Objects/Devices/flatpack.yml | 20 ++++++++++++++++++- Resources/migration.yml | 3 +++ 6 files changed, 44 insertions(+), 22 deletions(-) delete mode 100644 Resources/Prototypes/Catalog/Cargo/cargo_circuitboards.yml delete mode 100644 Resources/Prototypes/Catalog/Fills/Crates/circuitboards.yml diff --git a/Resources/Prototypes/Catalog/Cargo/cargo_circuitboards.yml b/Resources/Prototypes/Catalog/Cargo/cargo_circuitboards.yml deleted file mode 100644 index a96780fc3ed1..000000000000 --- a/Resources/Prototypes/Catalog/Cargo/cargo_circuitboards.yml +++ /dev/null @@ -1,9 +0,0 @@ -- type: cargoProduct - id: CrewMonitoringBoards - icon: - sprite: Objects/Misc/module.rsi - state: cpuboard - product: CrateCrewMonitoringBoards - cost: 2000 - category: cargoproduct-category-name-circuitboards - group: market diff --git a/Resources/Prototypes/Catalog/Cargo/cargo_science.yml b/Resources/Prototypes/Catalog/Cargo/cargo_science.yml index 756a223e74de..cb7f8af8224b 100644 --- a/Resources/Prototypes/Catalog/Cargo/cargo_science.yml +++ b/Resources/Prototypes/Catalog/Cargo/cargo_science.yml @@ -27,3 +27,13 @@ cost: 800 category: cargoproduct-category-name-science group: market + +- type: cargoProduct + id: CrewMonitoring + icon: + sprite: Structures/Machines/server.rsi + state: server + product: CrateCrewMonitoring + cost: 2000 + category: cargoproduct-category-name-science + group: market diff --git a/Resources/Prototypes/Catalog/Fills/Crates/circuitboards.yml b/Resources/Prototypes/Catalog/Fills/Crates/circuitboards.yml deleted file mode 100644 index 899db4c37c79..000000000000 --- a/Resources/Prototypes/Catalog/Fills/Crates/circuitboards.yml +++ /dev/null @@ -1,12 +0,0 @@ -- type: entity - id: CrateCrewMonitoringBoards - parent: CrateEngineeringSecure - name: crew monitoring boards - description: Has two crew monitoring console and server replacements. Requires engineering access to open. - components: - - type: StorageFill - contents: - - id: CrewMonitoringComputerCircuitboard - amount: 2 - - id: CrewMonitoringServerMachineCircuitboard - amount: 2 diff --git a/Resources/Prototypes/Catalog/Fills/Crates/science.yml b/Resources/Prototypes/Catalog/Fills/Crates/science.yml index 15ce05708e3e..6adf5942a43a 100644 --- a/Resources/Prototypes/Catalog/Fills/Crates/science.yml +++ b/Resources/Prototypes/Catalog/Fills/Crates/science.yml @@ -12,3 +12,15 @@ amount: 2 - id: ClothingMaskSterile amount: 2 + +- type: entity + id: CrateCrewMonitoring + parent: CrateScienceSecure + name: crew monitoring crate + description: Contains a flatpack of a crew monitoring server and a few crew monitoring computers. Requires Science access to open. + components: + - type: StorageFill + contents: + - id: CrewMonitoringServerFlatpack + - id: CrewMonitoringComputerFlatpack + amount: 3 diff --git a/Resources/Prototypes/Entities/Objects/Devices/flatpack.yml b/Resources/Prototypes/Entities/Objects/Devices/flatpack.yml index 5fb81aa6d481..82d43cf7d824 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/flatpack.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/flatpack.yml @@ -215,4 +215,22 @@ layers: - state: fax-machine - type: Flatpack - entity: FaxMachineBase \ No newline at end of file + entity: FaxMachineBase + +- type: entity + parent: BaseFlatpack + id: CrewMonitoringServerFlatpack + name: crew monitoring server flatpack + description: A flatpack used for constructing a crew monitoring server. + components: + - type: Flatpack + entity: CrewMonitoringServer + +- type: entity + parent: BaseFlatpack + id: CrewMonitoringComputerFlatpack + name: crew monitoring computer flatpack + description: A flatpack used for constructing a crew monitoring console. + components: + - type: Flatpack + entity: ComputerCrewMonitoring diff --git a/Resources/migration.yml b/Resources/migration.yml index 8940df2b65e1..a09986ebd860 100644 --- a/Resources/migration.yml +++ b/Resources/migration.yml @@ -475,3 +475,6 @@ LeftLegBorgJanitor: LeftLegBorg RightLegBorgJanitor: RightLegBorg HeadBorgJanitor: LightHeadBorg TorsoBorgJanitor: TorsoBorg + +# 2024-11-19 +CrateCrewMonitoringBoards: CrateCrewMonitoring From 35e2c641c1960195509c52fd6350cff720f76868 Mon Sep 17 00:00:00 2001 From: PJBot Date: Wed, 20 Nov 2024 01:06:27 +0000 Subject: [PATCH 170/290] Automatic changelog update --- Resources/Changelog/Changelog.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/Changelog.yml b/Resources/Changelog/Changelog.yml index a578659a0048..0eaa287ba93d 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: Blackern5000 - changes: - - message: Disabler SMGs no longer fit in combat boots - type: Fix - id: 7126 - time: '2024-08-17T01:00:21.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/31110 - author: Mervill changes: - message: Fixed suffocation alerts not appearing. @@ -3919,3 +3912,11 @@ id: 7625 time: '2024-11-20T01:00:38.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/32706 +- author: Plykiya + changes: + - message: The crew monitoring crate now contains a flatpack of the server and computers, + and can be opened with science access instead of engineering access now. + type: Tweak + id: 7626 + time: '2024-11-20T01:05:20.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33417 From 6e53cd98a400466640586bf19b41ec281944795e Mon Sep 17 00:00:00 2001 From: SlamBamActionman Date: Tue, 19 Nov 2024 16:28:58 +0100 Subject: [PATCH 171/290] Add emag functionality --- .../SingularityGeneratorSystem.cs | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/Content.Server/Singularity/EntitySystems/SingularityGeneratorSystem.cs b/Content.Server/Singularity/EntitySystems/SingularityGeneratorSystem.cs index be0c5e49b5f6..cfca86bf4af7 100644 --- a/Content.Server/Singularity/EntitySystems/SingularityGeneratorSystem.cs +++ b/Content.Server/Singularity/EntitySystems/SingularityGeneratorSystem.cs @@ -117,27 +117,31 @@ private void HandleParticleCollide(EntityUid uid, ParticleProjectileComponent co if (!EntityManager.TryGetComponent(args.OtherEntity, out var generatorComp)) return; - if (_timing.CurTime < _metadata.GetPauseTime(uid) + generatorComp.NextFailsafe) + if (_timing.CurTime < _metadata.GetPauseTime(uid) + generatorComp.NextFailsafe && !generatorComp.FailsafeDisabled) { EntityManager.QueueDeleteEntity(uid); return; } var contained = true; - var transform = Transform(args.OtherEntity); - var directions = Enum.GetValues().Length; - for (var i = 0; i < directions - 1; i += 2) // Skip every other direction, checking only cardinals + if (!generatorComp.FailsafeDisabled) { - if (!CheckContainmentField((Direction)i, new Entity(args.OtherEntity, generatorComp), transform)) - contained = false; + var transform = Transform(args.OtherEntity); + var directions = Enum.GetValues().Length; + for (var i = 0; i < directions - 1; i += 2) // Skip every other direction, checking only cardinals + { + if (!CheckContainmentField((Direction)i, new Entity(args.OtherEntity, generatorComp), transform)) + contained = false; + } } - if (!contained) + if (!contained && !generatorComp.FailsafeDisabled) { generatorComp.NextFailsafe = _timing.CurTime + generatorComp.FailsafeCooldown; _popupSystem.PopupEntity(Loc.GetString("comp-generator-failsafe", ("target", args.OtherEntity)), args.OtherEntity, PopupType.LargeCaution); } else + { SetPower( args.OtherEntity, generatorComp.Power + component.State switch @@ -151,6 +155,8 @@ private void HandleParticleCollide(EntityUid uid, ParticleProjectileComponent co }, generatorComp ); + } + EntityManager.QueueDeleteEntity(uid); } From 9c666457c2c13505725b7d3c336cae50f0666460 Mon Sep 17 00:00:00 2001 From: Saphire Date: Wed, 20 Nov 2024 07:49:45 +0600 Subject: [PATCH 172/290] Move some of the new singularity code into shared Hopefully without explosions yay --- .../SingularityGeneratorSystem.cs | 18 ++---------- .../SingularityGeneratorComponent.cs | 8 ++--- .../SharedSingularityGeneratorSystem.cs | 29 +++++++++++++++++++ 3 files changed, 35 insertions(+), 20 deletions(-) rename {Content.Server => Content.Shared}/Singularity/Components/SingularityGeneratorComponent.cs (91%) create mode 100644 Content.Shared/Singularity/EntitySystems/SharedSingularityGeneratorSystem.cs diff --git a/Content.Server/Singularity/EntitySystems/SingularityGeneratorSystem.cs b/Content.Server/Singularity/EntitySystems/SingularityGeneratorSystem.cs index cfca86bf4af7..95722449b877 100644 --- a/Content.Server/Singularity/EntitySystems/SingularityGeneratorSystem.cs +++ b/Content.Server/Singularity/EntitySystems/SingularityGeneratorSystem.cs @@ -1,10 +1,7 @@ -using System.Diagnostics; using Content.Server.ParticleAccelerator.Components; -using Content.Server.Popups; -using Content.Server.Singularity.Components; -using Content.Shared.Emag.Systems; using Content.Shared.Popups; using Content.Shared.Singularity.Components; +using Content.Shared.Singularity.EntitySystems; using Robust.Server.GameObjects; using Robust.Shared.Physics; using Robust.Shared.Physics.Components; @@ -13,7 +10,7 @@ namespace Content.Server.Singularity.EntitySystems; -public sealed class SingularityGeneratorSystem : EntitySystem +public sealed class SingularityGeneratorSystem : SharedSingularityGeneratorSystem { #region Dependencies [Dependency] private readonly IViewVariablesManager _vvm = default!; @@ -21,7 +18,6 @@ public sealed class SingularityGeneratorSystem : EntitySystem [Dependency] private readonly PhysicsSystem _physics = default!; [Dependency] private readonly IGameTiming _timing = default!; [Dependency] private readonly MetaDataSystem _metadata = default!; - [Dependency] private readonly PopupSystem _popupSystem = default!; #endregion Dependencies public override void Initialize() @@ -29,7 +25,6 @@ public override void Initialize() base.Initialize(); SubscribeLocalEvent(HandleParticleCollide); - SubscribeLocalEvent(OnEmagged); var vvHandle = _vvm.GetTypeHandler(); vvHandle.AddPath(nameof(SingularityGeneratorComponent.Power), (_, comp) => comp.Power, SetPower); @@ -138,7 +133,7 @@ private void HandleParticleCollide(EntityUid uid, ParticleProjectileComponent co if (!contained && !generatorComp.FailsafeDisabled) { generatorComp.NextFailsafe = _timing.CurTime + generatorComp.FailsafeCooldown; - _popupSystem.PopupEntity(Loc.GetString("comp-generator-failsafe", ("target", args.OtherEntity)), args.OtherEntity, PopupType.LargeCaution); + PopupSystem.PopupEntity(Loc.GetString("comp-generator-failsafe", ("target", args.OtherEntity)), args.OtherEntity, PopupType.LargeCaution); } else { @@ -159,13 +154,6 @@ private void HandleParticleCollide(EntityUid uid, ParticleProjectileComponent co EntityManager.QueueDeleteEntity(uid); } - - private void OnEmagged(EntityUid uid, SingularityGeneratorComponent component, ref GotEmaggedEvent args) - { - _popupSystem.PopupEntity(Loc.GetString("comp-generator-failsafe-disabled", ("target", uid)), uid); - component.FailsafeDisabled = true; - args.Handled = true; - } #endregion Event Handlers /// diff --git a/Content.Server/Singularity/Components/SingularityGeneratorComponent.cs b/Content.Shared/Singularity/Components/SingularityGeneratorComponent.cs similarity index 91% rename from Content.Server/Singularity/Components/SingularityGeneratorComponent.cs rename to Content.Shared/Singularity/Components/SingularityGeneratorComponent.cs index c8feeb5d5dbf..3643ed31a6f0 100644 --- a/Content.Server/Singularity/Components/SingularityGeneratorComponent.cs +++ b/Content.Shared/Singularity/Components/SingularityGeneratorComponent.cs @@ -1,14 +1,12 @@ using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -using Content.Server.Singularity.EntitySystems; using Content.Shared.Physics; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom; -namespace Content.Server.Singularity.Components; +namespace Content.Shared.Singularity.Components; -[RegisterComponent, AutoGenerateComponentPause] -[Access(typeof(SingularityGeneratorSystem))] +[RegisterComponent, AutoGenerateComponentPause, AutoGenerateComponentState] public sealed partial class SingularityGeneratorComponent : Component { /// @@ -28,7 +26,7 @@ public sealed partial class SingularityGeneratorComponent : Component /// /// Allows the generator to ignore all the failsafe stuff, e.g. when emagged /// - [DataField] + [DataField, AutoNetworkedField] public bool FailsafeDisabled = false; /// diff --git a/Content.Shared/Singularity/EntitySystems/SharedSingularityGeneratorSystem.cs b/Content.Shared/Singularity/EntitySystems/SharedSingularityGeneratorSystem.cs new file mode 100644 index 000000000000..8830cb0624cf --- /dev/null +++ b/Content.Shared/Singularity/EntitySystems/SharedSingularityGeneratorSystem.cs @@ -0,0 +1,29 @@ +using Content.Shared.Emag.Systems; +using Content.Shared.Popups; +using Content.Shared.Singularity.Components; + +namespace Content.Shared.Singularity.EntitySystems; + +/// +/// Shared part of SingularitySingularityGeneratorSystem +/// +public abstract class SharedSingularityGeneratorSystem : EntitySystem +{ + #region Dependencies + [Dependency] protected readonly SharedPopupSystem PopupSystem = default!; + #endregion Dependencies + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnEmagged); + } + + private void OnEmagged(EntityUid uid, SingularityGeneratorComponent component, ref GotEmaggedEvent args) + { + PopupSystem.PopupEntity(Loc.GetString("comp-generator-failsafe-disabled", ("target", uid)), uid); + component.FailsafeDisabled = true; + args.Handled = true; + } +} \ No newline at end of file From 1fa1975e60d35b788c57ab2479f6f962f99d53fc Mon Sep 17 00:00:00 2001 From: beck-thompson <107373427+beck-thompson@users.noreply.github.com> Date: Tue, 19 Nov 2024 17:53:52 -0800 Subject: [PATCH 173/290] Fix toggle verbs (#32138) First commit Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> --- .../Components/ItemToggleComponent.cs | 12 +++++++ .../Components/ToggleVerbComponent.cs | 18 ---------- .../Item/ItemToggle/ItemToggleSystem.cs | 2 +- .../Item/ItemToggle/ToggleVerbSystem.cs | 34 ------------------- .../components/magboots-component.ftl | 3 -- .../fire-extinguisher-component.ftl | 3 +- .../Entities/Clothing/Shoes/magboots.yml | 2 -- .../Objects/Misc/fire_extinguisher.yml | 4 +-- 8 files changed, 17 insertions(+), 61 deletions(-) delete mode 100644 Content.Shared/Item/ItemToggle/Components/ToggleVerbComponent.cs delete mode 100644 Content.Shared/Item/ItemToggle/ToggleVerbSystem.cs delete mode 100644 Resources/Locale/en-US/clothing/components/magboots-component.ftl diff --git a/Content.Shared/Item/ItemToggle/Components/ItemToggleComponent.cs b/Content.Shared/Item/ItemToggle/Components/ItemToggleComponent.cs index 47edec135d8d..110ae80626e3 100644 --- a/Content.Shared/Item/ItemToggle/Components/ItemToggleComponent.cs +++ b/Content.Shared/Item/ItemToggle/Components/ItemToggleComponent.cs @@ -32,6 +32,18 @@ public sealed partial class ItemToggleComponent : Component [DataField] public bool OnUse = true; + /// + /// The localized text to display in the verb to activate. + /// + [DataField] + public string VerbToggleOn = "item-toggle-activate"; + + /// + /// The localized text to display in the verb to de-activate. + /// + [DataField] + public string VerbToggleOff = "item-toggle-deactivate"; + /// /// Whether the item's toggle can be predicted by the client. /// diff --git a/Content.Shared/Item/ItemToggle/Components/ToggleVerbComponent.cs b/Content.Shared/Item/ItemToggle/Components/ToggleVerbComponent.cs deleted file mode 100644 index b673c55e0f16..000000000000 --- a/Content.Shared/Item/ItemToggle/Components/ToggleVerbComponent.cs +++ /dev/null @@ -1,18 +0,0 @@ -using Content.Shared.Item.ItemToggle; -using Robust.Shared.GameStates; - -namespace Content.Shared.Item.ItemToggle.Components; - -/// -/// Adds a verb for toggling something, requires . -/// -[RegisterComponent, NetworkedComponent, Access(typeof(ToggleVerbSystem))] -public sealed partial class ToggleVerbComponent : Component -{ - /// - /// Text the verb will have. - /// Gets passed "entity" as the entity's identity string. - /// - [DataField(required: true)] - public LocId Text = string.Empty; -} diff --git a/Content.Shared/Item/ItemToggle/ItemToggleSystem.cs b/Content.Shared/Item/ItemToggle/ItemToggleSystem.cs index d5bbaac12c33..f6752a67f61b 100644 --- a/Content.Shared/Item/ItemToggle/ItemToggleSystem.cs +++ b/Content.Shared/Item/ItemToggle/ItemToggleSystem.cs @@ -78,7 +78,7 @@ private void OnActivateVerb(Entity ent, ref GetVerbsEvent { Toggle((ent.Owner, ent.Comp), user, predicted: ent.Comp.Predictable); diff --git a/Content.Shared/Item/ItemToggle/ToggleVerbSystem.cs b/Content.Shared/Item/ItemToggle/ToggleVerbSystem.cs deleted file mode 100644 index 858cd9bc111a..000000000000 --- a/Content.Shared/Item/ItemToggle/ToggleVerbSystem.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Content.Shared.IdentityManagement; -using Content.Shared.Item.ItemToggle.Components; -using Content.Shared.Verbs; - -namespace Content.Shared.Item.ItemToggle; - -/// -/// Adds a verb for toggling something with . -/// -public sealed class ToggleVerbSystem : EntitySystem -{ - [Dependency] private readonly ItemToggleSystem _toggle = default!; - - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent>(OnGetVerbs); - } - - private void OnGetVerbs(Entity ent, ref GetVerbsEvent args) - { - if (!args.CanAccess || !args.CanInteract) - return; - - var name = Identity.Entity(ent, EntityManager); - var user = args.User; - args.Verbs.Add(new ActivationVerb() - { - Text = Loc.GetString(ent.Comp.Text, ("entity", name)), - Act = () => _toggle.Toggle(ent.Owner, user) - }); - } -} diff --git a/Resources/Locale/en-US/clothing/components/magboots-component.ftl b/Resources/Locale/en-US/clothing/components/magboots-component.ftl deleted file mode 100644 index 4113a7486206..000000000000 --- a/Resources/Locale/en-US/clothing/components/magboots-component.ftl +++ /dev/null @@ -1,3 +0,0 @@ - -# Toggle Magboots Verb -toggle-magboots-verb-get-data-text = Toggle Magboots \ No newline at end of file diff --git a/Resources/Locale/en-US/fire-extinguisher/fire-extinguisher-component.ftl b/Resources/Locale/en-US/fire-extinguisher/fire-extinguisher-component.ftl index f6418793918b..de1fcd7d4e33 100644 --- a/Resources/Locale/en-US/fire-extinguisher/fire-extinguisher-component.ftl +++ b/Resources/Locale/en-US/fire-extinguisher/fire-extinguisher-component.ftl @@ -1,3 +1,4 @@ fire-extinguisher-component-after-interact-refilled-message = {$owner} is now refilled fire-extinguisher-component-safety-on-message = Its safety is on! -fire-extinguisher-component-verb-text = Toggle safety +fire-extinguisher-component-verb-remove = Remove safety +fire-extinguisher-component-verb-engage = Engage safety diff --git a/Resources/Prototypes/Entities/Clothing/Shoes/magboots.yml b/Resources/Prototypes/Entities/Clothing/Shoes/magboots.yml index ab8084c91c0d..6610ae87ccf6 100644 --- a/Resources/Prototypes/Entities/Clothing/Shoes/magboots.yml +++ b/Resources/Prototypes/Entities/Clothing/Shoes/magboots.yml @@ -15,8 +15,6 @@ - type: ToggleClothing action: ActionToggleMagboots mustEquip: false - - type: ToggleVerb - text: toggle-magboots-verb-get-data-text - type: ComponentToggler components: - type: NoSlip diff --git a/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml b/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml index b0c586fc7537..4b4200fed8f6 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/fire_extinguisher.yml @@ -47,8 +47,8 @@ params: variation: 0.125 volume: -4 - - type: ToggleVerb - text: fire-extinguisher-component-verb-text + verbToggleOn: fire-extinguisher-component-verb-remove + verbToggleOff: fire-extinguisher-component-verb-engage - type: SpraySafety - type: MeleeWeapon wideAnimationRotation: 180 From e98383d572c8d6ba251c7914777becc681ebac91 Mon Sep 17 00:00:00 2001 From: qwerltaz <69696513+qwerltaz@users.noreply.github.com> Date: Wed, 20 Nov 2024 02:54:49 +0100 Subject: [PATCH 174/290] Construction menu grid view (#32577) * button * implement populate grid view * tweak min width * Make grid button toggle visible * tweak min window size * fix missing recipe button when mirroring item * make grid buttons toggleable * align button texture vertically * selected grid item has plain color background * tweak window width so all buttons look good * rename select method, defer colouring * get icon better * whoops * simpler button toggle * spritesys frame0, move spritesys * delete old sprite system refs --- .../Construction/UI/ConstructionMenu.xaml | 13 ++- .../Construction/UI/ConstructionMenu.xaml.cs | 17 ++- .../UI/ConstructionMenuPresenter.cs | 102 +++++++++++++++--- .../construction/ui/construction-menu.ftl | 1 + 4 files changed, 114 insertions(+), 19 deletions(-) diff --git a/Content.Client/Construction/UI/ConstructionMenu.xaml b/Content.Client/Construction/UI/ConstructionMenu.xaml index 6e4438cf6fdc..a934967a5334 100644 --- a/Content.Client/Construction/UI/ConstructionMenu.xaml +++ b/Content.Client/Construction/UI/ConstructionMenu.xaml @@ -1,15 +1,20 @@ - + + + + - -