From ab7a8f0502518fc0601829386744d2f8c601c6bf Mon Sep 17 00:00:00 2001 From: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com> Date: Wed, 4 Dec 2024 22:10:37 -0600 Subject: [PATCH 001/359] Adds sprite to superweapon spawner (#2368) Co-authored-by: Velcroboy --- .../DeltaV/Entities/Markers/Spawners/Random/security.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Resources/Prototypes/DeltaV/Entities/Markers/Spawners/Random/security.yml b/Resources/Prototypes/DeltaV/Entities/Markers/Spawners/Random/security.yml index 2fda11f0e54..c0ea5c8e621 100644 --- a/Resources/Prototypes/DeltaV/Entities/Markers/Spawners/Random/security.yml +++ b/Resources/Prototypes/DeltaV/Entities/Markers/Spawners/Random/security.yml @@ -4,6 +4,11 @@ suffix: superweapon parent: MarkerBase components: + - type: Sprite + layers: + - state: red + - sprite: DeltaV/Objects/Weapons/Guns/Battery/beam_cannon.rsi + state: base - type: EntityTableSpawner table: !type:NestedSelector tableId: RandomSuperweaponTable @@ -18,4 +23,4 @@ - id: WeaponLauncherRocket - id: CartridgeRocket prob: 0.2 - - id: WeaponBeamDevastator \ No newline at end of file + - id: WeaponBeamDevastator From 95ea9e24684158c28f70e797c85bc25dcb3d44ff Mon Sep 17 00:00:00 2001 From: deltanedas <39013340+deltanedas@users.noreply.github.com> Date: Thu, 5 Dec 2024 04:17:26 +0000 Subject: [PATCH 002/359] fix notary stamp objective never happening (#2358) Co-authored-by: deltanedas <@deltanedas:kde.org> --- Resources/Prototypes/Objectives/objectiveGroups.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Prototypes/Objectives/objectiveGroups.yml b/Resources/Prototypes/Objectives/objectiveGroups.yml index bfc7122c6d6..19e8b908762 100644 --- a/Resources/Prototypes/Objectives/objectiveGroups.yml +++ b/Resources/Prototypes/Objectives/objectiveGroups.yml @@ -22,7 +22,7 @@ CaptainJetpackStealObjective: 0.5 HandTeleporterStealObjective: 0.5 #EnergyShotgunStealObjective: 0.5 # DeltaV - replaced by X-01 objective - SecretDocumentsStealObjective: 0.5 + ClerkNotaryStealObjective: 0.5 # DeltaV LOLuckyBillStealObjective: 0.5 # DeltaV - LO steal objective, see Resources/Prototypes/DeltaV/Objectives/traitor.yml HoPBookIanDossierStealObjective: 1 # DeltaV - HoP steal objective, see Resources/Prototypes/DeltaV/Objectives/traitor.yml HoSGunStealObjective: 0.5 # DeltaV From 7c74034746bb1295581d2531232eaf0884805503 Mon Sep 17 00:00:00 2001 From: Delta-V bot <135767721+DeltaV-Bot@users.noreply.github.com> Date: Thu, 5 Dec 2024 05:17:45 +0100 Subject: [PATCH 003/359] Automatic changelog update --- Resources/Changelog/DeltaVChangelog.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/DeltaVChangelog.yml b/Resources/Changelog/DeltaVChangelog.yml index 5690634a707..ff8c31a35c9 100644 --- a/Resources/Changelog/DeltaVChangelog.yml +++ b/Resources/Changelog/DeltaVChangelog.yml @@ -1,11 +1,4 @@ Entries: -- author: Guess-My-Name - changes: - - message: Some budget cuts were made in HR department, expect more bureaucratic - errors in near future. - type: Add - id: 239 - time: '2024-02-12T21:01:44.0000000+00:00' - author: Adrian16199 changes: - message: Felinid's thieving gloves have been removed for Soft paws mechanic. @@ -3805,3 +3798,10 @@ id: 738 time: '2024-12-04T23:20:55.0000000+00:00' url: https://github.com/DeltaV-Station/Delta-v/pull/2363 +- author: deltanedas + changes: + - message: Fixed traitors never getting the notary stamp steal objective. + type: Fix + id: 739 + time: '2024-12-05T04:17:26.0000000+00:00' + url: https://github.com/DeltaV-Station/Delta-v/pull/2358 From 958808c3854f34def9e7e8ef689dc9de80e6d88c Mon Sep 17 00:00:00 2001 From: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com> Date: Thu, 5 Dec 2024 04:29:36 -0600 Subject: [PATCH 004/359] Updates Logi and Epi dept signs for server consistency (#2366) * Updates Logi and Epi dept signs * oops --------- Co-authored-by: Velcroboy --- .../Structures/Wallmounts/Signs/signs.yml | 6 ++++-- .../Wallmounts/signs.rsi/epistemics.png | Bin 0 -> 597 bytes .../Structures/Wallmounts/signs.rsi/logistics.png | Bin 0 -> 445 bytes .../Structures/Wallmounts/signs.rsi/meta.json | 8 +++++++- 4 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 Resources/Textures/DeltaV/Structures/Wallmounts/signs.rsi/epistemics.png create mode 100644 Resources/Textures/DeltaV/Structures/Wallmounts/signs.rsi/logistics.png diff --git a/Resources/Prototypes/Entities/Structures/Wallmounts/Signs/signs.yml b/Resources/Prototypes/Entities/Structures/Wallmounts/Signs/signs.yml index 2eda24a90be..21533c5f3eb 100644 --- a/Resources/Prototypes/Entities/Structures/Wallmounts/Signs/signs.yml +++ b/Resources/Prototypes/Entities/Structures/Wallmounts/Signs/signs.yml @@ -403,7 +403,8 @@ description: A sign indicating the logistics area. # DeltaV - Logistics Department replacing Cargo components: - type: Sprite - state: cargo + sprite: DeltaV/Structures/Wallmounts/signs.rsi # DeltaV - Logistics Department replacing Cargo + state: logistics # DeltaV - Logistics Department replacing Cargo - type: entity parent: BaseSign @@ -740,7 +741,8 @@ description: A sign indicating the epistemics area. # DeltaV - Epistemics Department replacing Science components: - type: Sprite - state: sci + sprite: DeltaV/Structures/Wallmounts/signs.rsi # DeltaV - Epistemics Department replacing Science + state: epistemics # DeltaV - Epistemics Department replacing Science - type: entity parent: BaseSign diff --git a/Resources/Textures/DeltaV/Structures/Wallmounts/signs.rsi/epistemics.png b/Resources/Textures/DeltaV/Structures/Wallmounts/signs.rsi/epistemics.png new file mode 100644 index 0000000000000000000000000000000000000000..7851be8b4823a1255f8ab1edc959c8740443c90b GIT binary patch literal 597 zcmV-b0;>IqP)Px$^+`lQR9J=Wmp@L!Fc`%jhyjGu(gh(T*mHn163X6VBy*W^l5CmVW3Xqja)9ns zLWl(t3Bg1e=rbRwo!U(YBzRNfx_-a!k6j1&>pJNAG9FD<`!Xt@?~GnnfOs@n4Nry` z3k-38K!9WM{2_FQ>1^OWq8^En`&dD=yB1XU_+cpJ?z zz8UM?!uh=bWL?`}Y()0J>SJY{zcWA=m~2GXZMQc7Lij}68$g}~y35xxJ-f*3KENFz z7dL%&HTMPpzG^NbZT}JZ%DV^J(fLGcl2-&qDoU28sT<>*-}z!9A$q&7WqURI*C(d~LdH+wWN!cf01jnX jNoGw=04e|g00;m8000000Mb*F00000NkvXXu0mjfnz;C8 literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Structures/Wallmounts/signs.rsi/logistics.png b/Resources/Textures/DeltaV/Structures/Wallmounts/signs.rsi/logistics.png new file mode 100644 index 0000000000000000000000000000000000000000..256afbacaa89d60352bcc32d8476483d5d22451a GIT binary patch literal 445 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz#^NA%Cx&(BWL^T?`IxWg-97Y*LoG&X#lzyHGlyR?R56MriG-eybeptrt!ChrQip6W5$CUSQhCzD zt_q}P09h{9O)oSud^?j2II|VK-p&j)b!nG67qdV`|Ac~`R+plCUdf)Czq20RJN#W@ zXTu5&hix|J?~ATJykVs(n}96qk|WxhFI$(yIILOUv2{)cdxEjZG=;*>;Jb`1GA?=x zB0V#Nt~rIwTG+`9lx}Qn(NIv$%M22^%*9iY>oJA-!sq?FXA6N{^e)d!qvpvcrkVa5 znJ+NvOgwmrwTHi3t7O(Iz5}ctYgepz$56x&$k%Z7y@C9p9~&+S%=P!W>sVCX5aUo( z{ow8I?>vtdElN46Z3Xg7#qWQ%VLK1rG;}OuIl9f6aoxI`8Vn3whI4p-UJ3sW40XQL e2+uTMUj{88n*)eJ;8O5p5asFW=d#Wzp$P!A&$R3S literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Structures/Wallmounts/signs.rsi/meta.json b/Resources/Textures/DeltaV/Structures/Wallmounts/signs.rsi/meta.json index 08393f464a3..f0a3e110740 100644 --- a/Resources/Textures/DeltaV/Structures/Wallmounts/signs.rsi/meta.json +++ b/Resources/Textures/DeltaV/Structures/Wallmounts/signs.rsi/meta.json @@ -1,7 +1,7 @@ { "version": 1, "license": "CC-BY-SA-3.0", - "copyright": "directional sprites taken from https://github.com/space-wizards/space-station-14/commit/c1556214de46d66fe4057500e269b17438dc96ca | direction_mail modified by Hyenh, direction_logi modified by Floofers | direction_court, direction_justice by leonardo_dabepis (Discord) | chapel modified from upstream sprite by Lyndomen (github)", + "copyright": "directional sprites taken from https://github.com/space-wizards/space-station-14/commit/c1556214de46d66fe4057500e269b17438dc96ca | direction_mail modified by Hyenh, direction_logi modified by Floofers | direction_court, direction_justice by leonardo_dabepis (Discord) | chapel modified from upstream sprite by Lyndomen (github) | Logistics and Epistemics modified by JustAnOrange", "size": { "x": 32, "y": 32 @@ -29,6 +29,12 @@ }, { "name": "chapel" + }, + { + "name": "epistemics" + }, + { + "name": "logistics" } ] } From c138f8d75bf1ed5f3ff8babdaa488dc440c89cff Mon Sep 17 00:00:00 2001 From: Delta-V bot <135767721+DeltaV-Bot@users.noreply.github.com> Date: Thu, 5 Dec 2024 11:29:56 +0100 Subject: [PATCH 005/359] Automatic changelog update --- Resources/Changelog/DeltaVChangelog.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Resources/Changelog/DeltaVChangelog.yml b/Resources/Changelog/DeltaVChangelog.yml index ff8c31a35c9..111f518a8dc 100644 --- a/Resources/Changelog/DeltaVChangelog.yml +++ b/Resources/Changelog/DeltaVChangelog.yml @@ -1,10 +1,4 @@ Entries: -- author: Adrian16199 - changes: - - message: Felinid's thieving gloves have been removed for Soft paws mechanic. - type: Tweak - id: 240 - time: '2024-02-12T21:10:44.0000000+00:00' - author: Adrian16199 changes: - message: Felinids now scream in agony from water. @@ -3805,3 +3799,10 @@ id: 739 time: '2024-12-05T04:17:26.0000000+00:00' url: https://github.com/DeltaV-Station/Delta-v/pull/2358 +- author: JustAnOrange + changes: + - message: Fixed Logi and Epi departmental sign sprites. + type: Fix + id: 740 + time: '2024-12-05T10:29:37.0000000+00:00' + url: https://github.com/DeltaV-Station/Delta-v/pull/2366 From 26201a19b383b9820d71190434032f2be0fac96e Mon Sep 17 00:00:00 2001 From: Velcroboy <107660393+IamVelcroboy@users.noreply.github.com> Date: Thu, 5 Dec 2024 04:47:39 -0600 Subject: [PATCH 006/359] Map Edits: Tortuga (#2365) Co-authored-by: Velcroboy --- Resources/Maps/tortuga.yml | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/Resources/Maps/tortuga.yml b/Resources/Maps/tortuga.yml index 7da9f5c667d..1d6a77d3512 100644 --- a/Resources/Maps/tortuga.yml +++ b/Resources/Maps/tortuga.yml @@ -158239,11 +158239,6 @@ entities: parent: 33 - proto: PlayerStationAi entities: - - uid: 31784 - components: - - type: Transform - pos: -49.5,-70.5 - parent: 33 - uid: 31785 components: - type: Transform @@ -162356,6 +162351,12 @@ entities: rot: 3.141592653589793 rad pos: 31.5,-8.5 parent: 33 + - uid: 31784 + components: + - type: Transform + rot: -1.5707963267948966 rad + pos: -57.5,-43.5 + parent: 33 - uid: 32304 components: - type: Transform @@ -163780,6 +163781,12 @@ entities: rot: 3.141592653589793 rad pos: -83.5,12.5 parent: 33 + - uid: 32430 + components: + - type: Transform + rot: 3.141592653589793 rad + pos: -60.5,-39.5 + parent: 33 - proto: PoweredSmallLightMaintenanceRed entities: - uid: 1132 From fbdc55e1c24f42b0d2a6211f6a8596578605c3f2 Mon Sep 17 00:00:00 2001 From: Emily <182209267+Emily9031@users.noreply.github.com> Date: Thu, 5 Dec 2024 18:22:26 -0700 Subject: [PATCH 007/359] Make medical borgs able to fly in space (#2339) * Makes Medborgs fly Just adds the JetpackUser component. * I forgot to comment it * I'm bad at commenting sorry * Applies flight to all borgs instead of just mediborg * Forgot to update the comment, oopsie --- 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 3c7dd74e22a..e5f7ec82756 100644 --- a/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml +++ b/Resources/Prototypes/Entities/Mobs/Cyborgs/base_borg_chassis.yml @@ -248,6 +248,7 @@ visMask: - PsionicInvisibility - Normal + - type: JetpackUser # DeltaV: Lets cyborgs fly in space - type: entity abstract: true From 60f3949d1fdddfb03880234744eeab2794584e95 Mon Sep 17 00:00:00 2001 From: Delta-V bot <135767721+DeltaV-Bot@users.noreply.github.com> Date: Fri, 6 Dec 2024 02:22:45 +0100 Subject: [PATCH 008/359] Automatic changelog update --- Resources/Changelog/DeltaVChangelog.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Resources/Changelog/DeltaVChangelog.yml b/Resources/Changelog/DeltaVChangelog.yml index 111f518a8dc..ff1433e014f 100644 --- a/Resources/Changelog/DeltaVChangelog.yml +++ b/Resources/Changelog/DeltaVChangelog.yml @@ -1,10 +1,4 @@ Entries: -- author: Adrian16199 - changes: - - message: Felinids now scream in agony from water. - type: Add - id: 241 - time: '2024-02-12T21:11:44.0000000+00:00' - author: VMSolidus changes: - message: 'Harpies have received a full visual rework. Featuring clothing sprites, @@ -3806,3 +3800,10 @@ id: 740 time: '2024-12-05T10:29:37.0000000+00:00' url: https://github.com/DeltaV-Station/Delta-v/pull/2366 +- author: Emily9031 + changes: + - message: Cyborgs are now able to slowly fly through space. + type: Add + id: 741 + time: '2024-12-06T01:22:26.0000000+00:00' + url: https://github.com/DeltaV-Station/Delta-v/pull/2339 From 868297b5af274650723d4f551572992044e8bc81 Mon Sep 17 00:00:00 2001 From: Monotheonist <182929384+Monotheonist@users.noreply.github.com> Date: Fri, 6 Dec 2024 01:32:57 -0400 Subject: [PATCH 009/359] mail carrier hood. AAAAAAAAAAAAH!! (#2113) * Sprite the actual hood, tell me what I'm missing. * Does the yaml thing, because me two weeks ago was a tired * moving the comment * Build and test will you ever be satisfied? * THE LINTER * Mono breaks robusttoolbox with his shitcode * Revert "Mono breaks robusttoolbox with his shitcode" This reverts commit 392b3eecfb10448b842758bca84ef7c4ec9be7c4. * Revert "THE LINTER" This reverts commit 3331e4d18a60e950ff6384290cc244515ced20e1. * Okay let's try this again * Mono, you press Tab too much. --- .../Entities/Clothing/Head/hoods.yml | 13 +++++++++++++ .../Clothing/OuterClothing/wintercoats.yml | 12 ++++++++++++ .../Coat/hoodmail.rsi/equipped-HELMET.png | Bin 0 -> 504 bytes .../Head/Hoods/Coat/hoodmail.rsi/icon.png | Bin 0 -> 363 bytes .../Head/Hoods/Coat/hoodmail.rsi/meta.json | 18 ++++++++++++++++++ 5 files changed, 43 insertions(+) create mode 100644 Resources/Prototypes/Nyanotrasen/Entities/Clothing/Head/hoods.yml create mode 100644 Resources/Textures/DeltaV/Clothing/Head/Hoods/Coat/hoodmail.rsi/equipped-HELMET.png create mode 100644 Resources/Textures/DeltaV/Clothing/Head/Hoods/Coat/hoodmail.rsi/icon.png create mode 100644 Resources/Textures/DeltaV/Clothing/Head/Hoods/Coat/hoodmail.rsi/meta.json diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Head/hoods.yml b/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Head/hoods.yml new file mode 100644 index 00000000000..405ed6e4a94 --- /dev/null +++ b/Resources/Prototypes/Nyanotrasen/Entities/Clothing/Head/hoods.yml @@ -0,0 +1,13 @@ +#Be sure to link back to the appropriate winter coats here (mostly in the nyanotrasen folder.) If this is a non-winter coat hood, then do whatever. + +- type: entity + parent: ClothingHeadHatHoodWinterBase + id: ClothingHeadHatHoodWinterMailCarrier + categories: [ HideSpawnMenu ] + name: mail carrier's winter coat hood + description: A hood for keeping the humble mailman's head warm while making all those deliveries. + components: + - type: Sprite + sprite: DeltaV/Clothing/Head/Hoods/Coat/hoodmail.rsi + - type: Clothing + sprite: DeltaV/Clothing/Head/Hoods/Coat/hoodmail.rsi diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Clothing/OuterClothing/wintercoats.yml b/Resources/Prototypes/Nyanotrasen/Entities/Clothing/OuterClothing/wintercoats.yml index 8b8e83507a2..0284c26a99e 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Clothing/OuterClothing/wintercoats.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Clothing/OuterClothing/wintercoats.yml @@ -39,6 +39,18 @@ name: mail carrier's winter coat description: It'll keep away the cold but not the dogs. components: + - type: ToggleableClothing #DeltaV - fixing the fact that it has no hood + clothingPrototype: ClothingHeadHatHoodWinterMailCarrier + - type: ContainerContainer + containers: + storagebase: !type:Container + showEnts: False + occludes: True + ents: [] + toggleable-clothing: !type:ContainerSlot + showEnts: False + occludes: True + ent: null - type: Sprite sprite: Nyanotrasen/Clothing/OuterClothing/WinterCoats/mail_winter_coat.rsi - type: Clothing diff --git a/Resources/Textures/DeltaV/Clothing/Head/Hoods/Coat/hoodmail.rsi/equipped-HELMET.png b/Resources/Textures/DeltaV/Clothing/Head/Hoods/Coat/hoodmail.rsi/equipped-HELMET.png new file mode 100644 index 0000000000000000000000000000000000000000..6062386142f4b9dce150b358886c086ba7a5885a GIT binary patch literal 504 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!7>k44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O`1E2l#}zK7Rh@`kf~-Y8k@P;qr!A$`<8H)?G42MdC`?mcGYy-RDYah5^;? zKln`^Nb!~g`33(+0t~hanMpyiI9E{-7)?r*0ZEIO>f z1+lkeyM_iw$zk|!$c&g9>_VP?-!j{T7=$rI)3L)bkc>&>dJYrJ=##?PrK{^Hv6 zy9%kR&Ui0vX!zcFkHdXV(ORi1Rw_$sl+`lca=6bBjy|Fp{bcIpQ%V9g_pE=g=}ct4 zw~e<&$TC7FN{M|5i`K+ub%k{YcQ#jDe-Ova&fvkB#GbO-;GVn10kc!T8<`bfeEuTi zkUd@g{9gxQ1I9(1GZ-$i^f0XL-PNSEJ?-K`xeG2k6mNWR^?1P|{q7aRueBG7gi@eEeM1MG8=`$J50z#KQmW1aH2>3Oua2Jb5dmZ+$uZw?9fmdKDSix(ovij@dB_8OAU3F_HS+A@K85(QFH*Z?>s9 z9cPpdSyu9PJ}=V$;}O@)739LYzHwUR-Xz8KiWAIiHrGD4NUB&{@qfV{b30qpo`NHq eCjUgU{xU_*^KV@+X^$MxT@0SCelF{r5}E*RnSkK{ literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/Head/Hoods/Coat/hoodmail.rsi/meta.json b/Resources/Textures/DeltaV/Clothing/Head/Hoods/Coat/hoodmail.rsi/meta.json new file mode 100644 index 00000000000..86fc1cfea61 --- /dev/null +++ b/Resources/Textures/DeltaV/Clothing/Head/Hoods/Coat/hoodmail.rsi/meta.json @@ -0,0 +1,18 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "By Monotheonist for SS14", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "equipped-HELMET", + "directions": 4 + } + ] +} \ No newline at end of file From 6780806cc05c4c6d0ffff94959682ca23871aaac Mon Sep 17 00:00:00 2001 From: Avalon Date: Fri, 6 Dec 2024 13:15:21 -0500 Subject: [PATCH 010/359] Observation Bundle Modifications (#2288) * Itbegins * Webeditcommentfixpt1 Signed-off-by: Avalon * Commentfixopspt2 Signed-off-by: Avalon * Comment fixes Pt 3 wooo Signed-off-by: Avalon * disount bump * untouchednow untouch? --------- Signed-off-by: Avalon Co-authored-by: Milon Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com> --- Resources/Prototypes/Catalog/Fills/Boxes/syndicate.yml | 4 ++-- Resources/Prototypes/DeltaV/Catalog/uplink_catalog.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Resources/Prototypes/Catalog/Fills/Boxes/syndicate.yml b/Resources/Prototypes/Catalog/Fills/Boxes/syndicate.yml index 179af783162..62464b9ca70 100644 --- a/Resources/Prototypes/Catalog/Fills/Boxes/syndicate.yml +++ b/Resources/Prototypes/Catalog/Fills/Boxes/syndicate.yml @@ -42,11 +42,11 @@ contents: - id: SyndiCrewMonitorEmpty amount: 1 - - id: PowerCellHigh + - id: PowerCellMicroreactor # DeltaV - No more charging amount: 1 - id: ClothingEyesGlassesHiddenSecurity amount: 1 - - id: SurveillanceCameraMonitorCircuitboard + - id: CameraBug # DeltaV - Way better than that board amount: 1 diff --git a/Resources/Prototypes/DeltaV/Catalog/uplink_catalog.yml b/Resources/Prototypes/DeltaV/Catalog/uplink_catalog.yml index 2e428c8f8d9..f8c317772ae 100644 --- a/Resources/Prototypes/DeltaV/Catalog/uplink_catalog.yml +++ b/Resources/Prototypes/DeltaV/Catalog/uplink_catalog.yml @@ -41,9 +41,9 @@ productEntity: Observationskit discountCategory: usualDiscounts discountDownTo: - Telecrystal: 2 + Telecrystal: 3 cost: - Telecrystal: 4 + Telecrystal: 6 # DeltaV - Price Goes up, but the goods are better! categories: - UplinkDeception From bdc0a52988df6f31d7ddf43633f501643856ad99 Mon Sep 17 00:00:00 2001 From: Delta-V bot <135767721+DeltaV-Bot@users.noreply.github.com> Date: Fri, 6 Dec 2024 19:15:41 +0100 Subject: [PATCH 011/359] Automatic changelog update --- Resources/Changelog/DeltaVChangelog.yml | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/Resources/Changelog/DeltaVChangelog.yml b/Resources/Changelog/DeltaVChangelog.yml index ff1433e014f..878a7a86ab5 100644 --- a/Resources/Changelog/DeltaVChangelog.yml +++ b/Resources/Changelog/DeltaVChangelog.yml @@ -1,18 +1,4 @@ Entries: -- author: VMSolidus - changes: - - message: 'Harpies have received a full visual rework. Featuring clothing sprites, - new markings, a complete overhaul of their layering, as well as visual systems. ' - type: Add - - message: Harpies now have bird related speech verbs - type: Add - - message: 'Two new traits have been added related to birds. Harpies now start by - default with the new Ultraviolet Vision trait, letting them see a whole new - spectrum of colors. This trait can be taken by other curious people. Harpies - that wish to see in RGB colors can instead take the new Normal Vision trait. ' - type: Add - id: 242 - time: '2024-02-12T22:25:02.0000000+00:00' - author: DebugOk changes: - message: Glimmer probers now react violently to being hit by gorilla gauntlets @@ -3807,3 +3793,11 @@ id: 741 time: '2024-12-06T01:22:26.0000000+00:00' url: https://github.com/DeltaV-Station/Delta-v/pull/2339 +- author: Avalon-Proto + changes: + - message: Syndicate Observation Kits have been adjusted, granting it a Camera bug + and a better cell for the monitor! + type: Tweak + id: 742 + time: '2024-12-06T18:15:22.0000000+00:00' + url: https://github.com/DeltaV-Station/Delta-v/pull/2288 From 2698e8922bb441136aa91cc475cf4fd4c8245efe Mon Sep 17 00:00:00 2001 From: Radezolid Date: Fri, 6 Dec 2024 16:33:55 -0300 Subject: [PATCH 012/359] Add a foam sabre (#2310) * Added sabre + sheath * Can't forget the filled sheath * Fix comment + fun StaminaDamageOnHit * Add the sabre to the maints loot pool * Add the sword to the mime loadout * Let's add a sharp version! * Why not add it to the syndicate catalog? * Conventions! * Grammar! * Fix indent * Fix indent on the sabre * Now in mail! * Indent! --------- Co-authored-by: Milon Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com> --- .../en-US/deltav/store/uplink-catalog.ftl | 3 ++ .../Catalog/Fills/Items/Belts/belts.yml | 20 ++++++++++++ .../DeltaV/Catalog/uplink_catalog.yml | 15 +++++++++ .../DeltaV/Entities/Clothing/Belt/belts.yml | 11 +++++++ .../DeltaV/Entities/Objects/Fun/toys.yml | 30 ++++++++++++++++++ .../Entities/Objects/Specific/Mail/mail.yml | 9 ++++++ .../Objects/Weapons/Melee/foam_blade.yml | 15 +++++++++ .../DeltaV/Loadouts/Jobs/Civilian/mime.yml | 5 +++ .../Prototypes/DeltaV/Mail/mailDeliveries.yml | 3 +- .../Markers/Spawners/Random/maintenance.yml | 1 + .../Prototypes/Loadouts/loadout_groups.yml | 1 + .../Belt/foamsheath.rsi/equipped-BELT.png | Bin 0 -> 444 bytes .../Clothing/Belt/foamsheath.rsi/meta.json | 25 +++++++++++++++ .../sheath-sabre-equipped-BELT.png | Bin 0 -> 537 bytes .../Belt/foamsheath.rsi/sheath-sabre.png | Bin 0 -> 424 bytes .../Clothing/Belt/foamsheath.rsi/sheath.png | Bin 0 -> 219 bytes .../Objects/Fun/Toys/foam_sabre.rsi/icon.png | Bin 0 -> 408 bytes .../Fun/Toys/foam_sabre.rsi/inhand-left.png | Bin 0 -> 362 bytes .../Fun/Toys/foam_sabre.rsi/inhand-right.png | Bin 0 -> 363 bytes .../Objects/Fun/Toys/foam_sabre.rsi/meta.json | 22 +++++++++++++ 20 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 Resources/Prototypes/DeltaV/Entities/Objects/Weapons/Melee/foam_blade.yml create mode 100644 Resources/Prototypes/DeltaV/Loadouts/Jobs/Civilian/mime.yml create mode 100644 Resources/Textures/DeltaV/Clothing/Belt/foamsheath.rsi/equipped-BELT.png create mode 100644 Resources/Textures/DeltaV/Clothing/Belt/foamsheath.rsi/meta.json create mode 100644 Resources/Textures/DeltaV/Clothing/Belt/foamsheath.rsi/sheath-sabre-equipped-BELT.png create mode 100644 Resources/Textures/DeltaV/Clothing/Belt/foamsheath.rsi/sheath-sabre.png create mode 100644 Resources/Textures/DeltaV/Clothing/Belt/foamsheath.rsi/sheath.png create mode 100644 Resources/Textures/DeltaV/Objects/Fun/Toys/foam_sabre.rsi/icon.png create mode 100644 Resources/Textures/DeltaV/Objects/Fun/Toys/foam_sabre.rsi/inhand-left.png create mode 100644 Resources/Textures/DeltaV/Objects/Fun/Toys/foam_sabre.rsi/inhand-right.png create mode 100644 Resources/Textures/DeltaV/Objects/Fun/Toys/foam_sabre.rsi/meta.json diff --git a/Resources/Locale/en-US/deltav/store/uplink-catalog.ftl b/Resources/Locale/en-US/deltav/store/uplink-catalog.ftl index 4b860e6efdd..4cf03df5f92 100644 --- a/Resources/Locale/en-US/deltav/store/uplink-catalog.ftl +++ b/Resources/Locale/en-US/deltav/store/uplink-catalog.ftl @@ -20,3 +20,6 @@ uplink-doorjack-desc = A specialized cryptographic sequencer, designed solely to uplink-home-run-bat-name = Home Run Bat uplink-home-run-bat-desc = Rigged bat pre-coated in blood for Syndicate tee-ball practice. Launch your foes! + +uplink-foam-sabre-name = Sharp Foam Sabre +uplink-foam-sabre-desc = A blade disguised as a toy foam sabre. Perfect for assassins that pretend playing around. diff --git a/Resources/Prototypes/DeltaV/Catalog/Fills/Items/Belts/belts.yml b/Resources/Prototypes/DeltaV/Catalog/Fills/Items/Belts/belts.yml index b563757acb5..cbdee1d05fa 100644 --- a/Resources/Prototypes/DeltaV/Catalog/Fills/Items/Belts/belts.yml +++ b/Resources/Prototypes/DeltaV/Catalog/Fills/Items/Belts/belts.yml @@ -22,3 +22,23 @@ - id: Bloodpack - id: SyringeEphedrine - id: EmergencyMedipen + +- type: entity + id: ClothingBeltFoamSheathFilled + parent: ClothingBeltFoamSheath + suffix: Filled + components: + - type: ContainerFill + containers: + item: + - FoamSabre + +- type: entity + id: ClothingBeltRealFoamSheathFilled + parent: ClothingBeltFoamSheath + suffix: Filled, Real + components: + - type: ContainerFill + containers: + item: + - RealFoamSabre diff --git a/Resources/Prototypes/DeltaV/Catalog/uplink_catalog.yml b/Resources/Prototypes/DeltaV/Catalog/uplink_catalog.yml index f8c317772ae..f03c88af6b5 100644 --- a/Resources/Prototypes/DeltaV/Catalog/uplink_catalog.yml +++ b/Resources/Prototypes/DeltaV/Catalog/uplink_catalog.yml @@ -102,3 +102,18 @@ Telecrystal: 16 categories: - UplinkWeaponry + +- type: listing + id: UplinkRealFoamSabre + name: uplink-foam-sabre-name + description: uplink-foam-sabre-desc + productEntity: ClothingBeltRealFoamSheathFilled + icon: + entity: RealFoamSabre + discountCategory: usualDiscounts + discountDownTo: + Telecrystal: 4 + cost: + Telecrystal: 6 + categories: + - UplinkWeaponry diff --git a/Resources/Prototypes/DeltaV/Entities/Clothing/Belt/belts.yml b/Resources/Prototypes/DeltaV/Entities/Clothing/Belt/belts.yml index cef0cf394c1..a609238d9be 100644 --- a/Resources/Prototypes/DeltaV/Entities/Clothing/Belt/belts.yml +++ b/Resources/Prototypes/DeltaV/Entities/Clothing/Belt/belts.yml @@ -73,3 +73,14 @@ ents: [] medkit: !type:ContainerSlot {} - type: Appearance + +- type: entity + parent: ClothingBeltSheath + id: ClothingBeltFoamSheath + name: foam sheath + description: A foam sheath to cosplay as the captain! It seems to be able to fit a real sabre in it. + components: + - type: Sprite + sprite: DeltaV/Clothing/Belt/foamsheath.rsi + - type: Clothing + sprite: DeltaV/Clothing/Belt/foamsheath.rsi diff --git a/Resources/Prototypes/DeltaV/Entities/Objects/Fun/toys.yml b/Resources/Prototypes/DeltaV/Entities/Objects/Fun/toys.yml index 2a22e6fd938..39593702130 100644 --- a/Resources/Prototypes/DeltaV/Entities/Objects/Fun/toys.yml +++ b/Resources/Prototypes/DeltaV/Entities/Objects/Fun/toys.yml @@ -45,3 +45,33 @@ - type: Sprite sprite: DeltaV/Objects/Fun/Toys/zerotoy.rsi state: icon + +- type: entity + parent: BaseItem + id: FoamSabre + name: foam sabre + description: Cosplay as a captain and command your group of friends! + components: + - type: Sprite + sprite: DeltaV/Objects/Fun/Toys/foam_sabre.rsi + state: icon + - type: MeleeWeapon + wideAnimationRotation: -135 + attackRate: 1.5 + range: 2.0 + damage: + types: + Blunt: 0 + - type: Reflect # Imitation of captain's sword, 1% chance of reflecting a projectile for the fun chance of it happening. + reflectProb: .01 + spread: 90 + - type: Item + size: Normal + sprite: DeltaV/Objects/Fun/Toys/foam_sabre.rsi + - type: Tag + tags: + - CaptainSabre # To be able to store it a captain's sheath if you get your hands on one. + - type: StaminaDamageOnHit + damage: 5 + - type: Execution + doAfterDuration: 3.0 diff --git a/Resources/Prototypes/DeltaV/Entities/Objects/Specific/Mail/mail.yml b/Resources/Prototypes/DeltaV/Entities/Objects/Specific/Mail/mail.yml index 2fa02ebc002..9bb228637a3 100644 --- a/Resources/Prototypes/DeltaV/Entities/Objects/Specific/Mail/mail.yml +++ b/Resources/Prototypes/DeltaV/Entities/Objects/Specific/Mail/mail.yml @@ -1732,3 +1732,12 @@ amount: 1 - id: PaperMailHydroCoTrial amount: 1 + +- type: entity + parent: BaseMailLarge + id: MailFoamSabre + suffix: Foam sabre + components: + - type: Mail + contents: + - id: ClothingBeltFoamSheathFilled diff --git a/Resources/Prototypes/DeltaV/Entities/Objects/Weapons/Melee/foam_blade.yml b/Resources/Prototypes/DeltaV/Entities/Objects/Weapons/Melee/foam_blade.yml new file mode 100644 index 00000000000..ac47fed7992 --- /dev/null +++ b/Resources/Prototypes/DeltaV/Entities/Objects/Weapons/Melee/foam_blade.yml @@ -0,0 +1,15 @@ +- type: entity + parent: FoamSabre + id: RealFoamSabre + name: foam sabre + suffix: Real + components: + - type: MeleeWeapon + attackRate: 1.5 + damage: + types: + Slash: 14 + soundHit: + path: /Audio/Weapons/bladeslice.ogg + - type: StaminaDamageOnHit + damage: 0 diff --git a/Resources/Prototypes/DeltaV/Loadouts/Jobs/Civilian/mime.yml b/Resources/Prototypes/DeltaV/Loadouts/Jobs/Civilian/mime.yml new file mode 100644 index 00000000000..43740a3097a --- /dev/null +++ b/Resources/Prototypes/DeltaV/Loadouts/Jobs/Civilian/mime.yml @@ -0,0 +1,5 @@ +# Belt +- type: loadout + id: FoamSabre + equipment: + belt: ClothingBeltFoamSheathFilled diff --git a/Resources/Prototypes/DeltaV/Mail/mailDeliveries.yml b/Resources/Prototypes/DeltaV/Mail/mailDeliveries.yml index c951d09986e..d7cd57d75bf 100644 --- a/Resources/Prototypes/DeltaV/Mail/mailDeliveries.yml +++ b/Resources/Prototypes/DeltaV/Mail/mailDeliveries.yml @@ -51,7 +51,7 @@ MailNFSodaSpaceUp: 0.2 #End Soda MailNFSmoke: 0.4 - MailSpaceVillainDIY: 0.5 + MailSpaceVillainDIY: 0.4 # Lowered to accommodate the foam sabre MailSignallerKit: 0.5 MailSunglasses: 1 MailNFSoaps: 0.5 @@ -63,6 +63,7 @@ MailNFUnusualFood: 1.09 # DeltaV: increased to offset throngler toy MailNFUnusualProduce: 1 MailNFVagueThreat: 0.5 + MailFoamSabre: 0.1 # Mainly for Glacier MailWinterCoat: 1.5 diff --git a/Resources/Prototypes/Entities/Markers/Spawners/Random/maintenance.yml b/Resources/Prototypes/Entities/Markers/Spawners/Random/maintenance.yml index 2ef16c6ec18..93194945ee3 100644 --- a/Resources/Prototypes/Entities/Markers/Spawners/Random/maintenance.yml +++ b/Resources/Prototypes/Entities/Markers/Spawners/Random/maintenance.yml @@ -165,6 +165,7 @@ - id: CigarGold - id: ClothingUniformJumpsuitFamilyGuy - id: WristwatchGold + - id: ClothingBeltFoamSheathFilled # DeltaV - Add small chance of it spawning in maints locker. #- id: RubberStampGreytide # Delta-V: prevent greytide stamp from spawning - type: entity diff --git a/Resources/Prototypes/Loadouts/loadout_groups.yml b/Resources/Prototypes/Loadouts/loadout_groups.yml index 0a167aca0c7..d801a9fce93 100644 --- a/Resources/Prototypes/Loadouts/loadout_groups.yml +++ b/Resources/Prototypes/Loadouts/loadout_groups.yml @@ -634,6 +634,7 @@ loadouts: - MimeSuspendersRed - MimeSuspendersBlack + - FoamSabre # DeltaV - Add foam sabre to the mime's loadout. - type: loadoutGroup id: SurvivalMime diff --git a/Resources/Textures/DeltaV/Clothing/Belt/foamsheath.rsi/equipped-BELT.png b/Resources/Textures/DeltaV/Clothing/Belt/foamsheath.rsi/equipped-BELT.png new file mode 100644 index 0000000000000000000000000000000000000000..d404e4143e0137ca1a7d523153d7af2fd8068f7d GIT binary patch literal 444 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7T#lEU~KkuaSW-L^Y)gZ-(dp@)(7cF z4jgDva-Aw=RlqPo!XkFrJw^5t4*G|Jmhi|l9AsLlps2>S?YIEbN{tok>Zh~aQ%}v* zK3=);Ki_^vK^V9x^87*mdBrPrC;Gc>lo@1X<#cN6imTs8G-mLme`~%x`Q!8j^W)hg@y*SuHhry(b)vz?tl$Rlb@1V<}?ffbn3-q@s zEYn&MZMgdNi>|X=bFO|Za29|$Qc#fj+TVkYiJVpMGp`!ns?)y7;4Prc@Z2GX-)M*N zmAQfpx9n=mMJtc}D_<#6d2I7(!?3OQ!{$o=xE#^6#%}u|HT{GM(F^p;tXc9K>mKb^ z*rqBk!k{hCeIa^@xbUG{jBj2YE;r*%T+6WMyFCB=R|}e2MbtwWwzQ^s)c$&RKk)*) iPEw@I1%aRJ_ZV0l)~POH<~#?C6$VdNKbLh*2~7Y8daefm literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/Belt/foamsheath.rsi/meta.json b/Resources/Textures/DeltaV/Clothing/Belt/foamsheath.rsi/meta.json new file mode 100644 index 00000000000..6383a3c4561 --- /dev/null +++ b/Resources/Textures/DeltaV/Clothing/Belt/foamsheath.rsi/meta.json @@ -0,0 +1,25 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/555fa0ed9f380509156d94131bd8a3f1c1fee1cf , edited by Skarletto (github), modified by Radezolid for foam sheath", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "equipped-BELT", + "directions": 4 + }, + { + "name": "sheath-sabre-equipped-BELT", + "directions": 4 + }, + { + "name": "sheath-sabre" + }, + { + "name": "sheath" + } + ] +} diff --git a/Resources/Textures/DeltaV/Clothing/Belt/foamsheath.rsi/sheath-sabre-equipped-BELT.png b/Resources/Textures/DeltaV/Clothing/Belt/foamsheath.rsi/sheath-sabre-equipped-BELT.png new file mode 100644 index 0000000000000000000000000000000000000000..94674c9adb2be33ff61b40abf76bb0d5bc4fbdff GIT binary patch literal 537 zcmV+!0_OdRP)&&Q|{~rh{I=lX7#)bVpfQX2Qh=^zhsW>0bXVL-y$A;r0ArOJ({A{jW^~h&d*MM z1^xc<2>^J0eT#K`?UNnUA-DIz^M}VQdXpg>$1xs)bRd`q&sE!8$l6<=)`hB+g00Y- z3~~D6m^iNma%XRA8J#Ip)dz9GB;~BXCE*e0I(Q> z5hK9X>;o18i1K}3YxZ=%zfpb96KUx!U+F;lo|oJZh=_=Yh=_=Yh=_F9s6-pTEk3Bj zT9w#FCE9oZZZ(HW$@Hj!S{Lg2W*Fy`dNPat8ZZK*4Zv2tzadDucMQ*ti(4s>XzhVZ-Hpy z+d#J@A1i=po60uP31R5~w)Mw{Rt;gP0DRxK(x7CTjSdw6!5>YM>h$5&A<+#Mx=b`^ b5bc0(<_p3`BgGBa00000NkvXXu0mjfe{%Eo literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Clothing/Belt/foamsheath.rsi/sheath-sabre.png b/Resources/Textures/DeltaV/Clothing/Belt/foamsheath.rsi/sheath-sabre.png new file mode 100644 index 0000000000000000000000000000000000000000..22f7868918888cea5d95ee0a60815baa75cf92e4 GIT binary patch literal 424 zcmV;Z0ayNsP)N4{ zB}>N+LYHt3H6^qa3#O?<4&HEq8QUQEwh$sH$|A>+o%K+4wKa*bf)4=p zw&CQC*g)eQI6E&;uP|=8>S`+-M_Byoz7|*A>F``+*r`br;goEtSCF?>L57{0crJ_G zi6|mG(cIKgfvFoSQ;W6M~X-hDI!Ir zh!pV`gi=c2hYQJ~5aFe!cWMC8S|xNY^I S6XRY00000B>ArY-_uWjT!Y#`A3&_2>t zxuW~bMAIH)*JC^Hxw-`uItthv^-f%JOVO>Yke@}1<@?KZ6BL9xUFtg0On6_+c%*zu zIMXd{oAjeyPXl&;Wv_7b>a-P{ZN%%LT=ae0uKvSkQqqdPoAo&hNL|m9XtkYzf7@cJ&){ur(5Kaj3L7*WJxMkPaQh#KA96h*;f9+#ITdL%O-f4%MY~aL~m< z6@-*RH^IS09v5>awQjvDNNx%Vq`RP67OQGU;1j)vk%7lyp2E5RV8tJvDd~U>9?A3gDob6%jJ< zUuQy+bV_+FFJ-_?4qju3up40ez(lK}&HOl>2#Dh^ub+5)%i!T%hu0X+(wrVJ4R7}c zX!i#IfUq0L3-}AyG)Njfrd0Qdsx88+zf&~R=5000015QgDN4iO0J!Y4=}Fa(0i+{2&)_)4mE1y?S80~ab%2n0HTyKxZ)goA%1jkHL4 zpGpRMcfU`nJQ4u_000000Du9COw_K+Jm|geKBK)xdu=bT-U}vakRlT;^PsEG??ENB z*C;a4Bn_TN9Z#7DJ)gE()s5~C$KD0(4@a%)M$f0MdOS^&vb)x|1PedL*(TSughhon z&z7*r@a9noiwOLHeF~i$!)|#Y2zCM1Y-ukZ?gUr5n-<`)qxU2SFW4u4m$#S2j>7GSTSauZ>;8 zEJkT#l`xC&#=C@Bg*RR$%rd<3dSA%%Op~kXrdNo*zXO0rE;V!=`+1ylC;$Ke07*qo IM6N<$f_Ax^)&Kwi literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Objects/Fun/Toys/foam_sabre.rsi/inhand-right.png b/Resources/Textures/DeltaV/Objects/Fun/Toys/foam_sabre.rsi/inhand-right.png new file mode 100644 index 0000000000000000000000000000000000000000..44f5e32a29136e504512ac8e7e8a465598e1d5ca GIT binary patch literal 363 zcmV-x0hIoUP)2OX0RR9100000PhC2-E}gD_{-iFQR)uJmyD4Uz zRhB!c3Q>Rd;D;TKCvDnJFXx?(dQfC_>GX2mY14LkIG)1hw(!>G#4|<{RDy+{X{P8N zDq(5i&0QrdHM|)tVd>#bZwc=b-uNY~Ecp8CbM@S@;(DhK4gdfE0001Bg#C7-DQt=F zHMkw_^ZWfTS?*-N-9#_pWp=K%hyKGr*LstVDnka7F>2fXyE ze(n;ISli82LK5N4)FmVp-b__OlHtwR5|R#YnzjoH5qckhU{`RvA+N;zR8If^002ov JPDHLkV1g)pq?!N# literal 0 HcmV?d00001 diff --git a/Resources/Textures/DeltaV/Objects/Fun/Toys/foam_sabre.rsi/meta.json b/Resources/Textures/DeltaV/Objects/Fun/Toys/foam_sabre.rsi/meta.json new file mode 100644 index 00000000000..e9322bc4d34 --- /dev/null +++ b/Resources/Textures/DeltaV/Objects/Fun/Toys/foam_sabre.rsi/meta.json @@ -0,0 +1,22 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/555fa0ed9f380509156d94131bd8a3f1c1fee1cf, modified by Radezolid for foam sabre", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "inhand-left", + "directions": 4 + }, + { + "name": "inhand-right", + "directions": 4 + } + ] +} From a2c5a83e7a1c2ed3424580d367670e3a01d4c86b Mon Sep 17 00:00:00 2001 From: Delta-V bot <135767721+DeltaV-Bot@users.noreply.github.com> Date: Fri, 6 Dec 2024 20:34:14 +0100 Subject: [PATCH 013/359] Automatic changelog update --- Resources/Changelog/DeltaVChangelog.yml | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/Resources/Changelog/DeltaVChangelog.yml b/Resources/Changelog/DeltaVChangelog.yml index 878a7a86ab5..b8c61d42577 100644 --- a/Resources/Changelog/DeltaVChangelog.yml +++ b/Resources/Changelog/DeltaVChangelog.yml @@ -1,11 +1,4 @@ Entries: -- author: DebugOk - changes: - - message: Glimmer probers now react violently to being hit by gorilla gauntlets - if glimmer is above 500 - type: Tweak - id: 243 - time: '2024-02-13T00:59:01.0000000+00:00' - author: VMSolidus changes: - message: Removed the ability of Harpies to destroy people's ears. @@ -3801,3 +3794,14 @@ id: 742 time: '2024-12-06T18:15:22.0000000+00:00' url: https://github.com/DeltaV-Station/Delta-v/pull/2288 +- author: Radezolid + changes: + - message: Added foam sabres! They may appear in maintenance lockers and mimes can + select to spawn with it in the loadout selection. + type: Add + - message: Added a sharp version of the foam sabre toy, purchasable from the syndicate + uplink at 6 TC with a possible discount to 4 TC. + type: Add + id: 743 + time: '2024-12-06T19:33:56.0000000+00:00' + url: https://github.com/DeltaV-Station/Delta-v/pull/2310 From cc23335f7eb23aa4ee0da6734367fb966a12744d Mon Sep 17 00:00:00 2001 From: Milon Date: Sat, 7 Dec 2024 14:28:45 +0100 Subject: [PATCH 014/359] remove unnecessary migrations (#2386) whoopsie! --- Resources/Migrations/deltaMigrations.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Resources/Migrations/deltaMigrations.yml b/Resources/Migrations/deltaMigrations.yml index 9624e6c01e9..bab6685466a 100644 --- a/Resources/Migrations/deltaMigrations.yml +++ b/Resources/Migrations/deltaMigrations.yml @@ -111,11 +111,6 @@ SpawnPointMailCarrier: SpawnPointCourier # 2024-07-01 shuttle_manipulator: ShuttleManipulator -# 2024-07-25 Remove when these are added -MagazinePistolSubMachineGunEmpty: null -MagazinePistolSubMachineGunTopMountedEmpty: null -MagazineShotgunEmpty: null - # 2024-08-16 ShockCollar: ClothingNeckShockCollar FoodMealSoftTaco: FoodTacoShell From 2b227b5a4e38700c95aee56256da6af284238587 Mon Sep 17 00:00:00 2001 From: RedBookcase Date: Fri, 15 Nov 2024 12:52:19 -0800 Subject: [PATCH 015/359] Edited Snow White reaction to output proper amount of drink. (#33331) Co-authored-by: RedBookcase --- Resources/Prototypes/Recipes/Reactions/drinks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Prototypes/Recipes/Reactions/drinks.yml b/Resources/Prototypes/Recipes/Reactions/drinks.yml index 2353099df56..64668b10895 100644 --- a/Resources/Prototypes/Recipes/Reactions/drinks.yml +++ b/Resources/Prototypes/Recipes/Reactions/drinks.yml @@ -953,7 +953,7 @@ LemonLime: amount: 1 products: - SnowWhite: 3 + SnowWhite: 2 - type: reaction id: SodaWater From f88cd33137c2df0269d2f5c46b23f95581ac2b56 Mon Sep 17 00:00:00 2001 From: PJBot Date: Fri, 15 Nov 2024 20:53:26 +0000 Subject: [PATCH 016/359] 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 82896471192..4bf34d35bc4 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,12 +1,4 @@ Entries: -- author: Erisfiregamer1 - changes: - - message: New chemical, Sedin. It restores seeds on plants 20% of the time with - other adverse effects included. - type: Add - id: 7111 - time: '2024-08-15T00:38:24.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/27110 - author: PoorMansDreams changes: - message: Added Star sticker in loadouts for Secoffs @@ -3913,3 +3905,10 @@ id: 7610 time: '2024-11-15T06:54:53.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33315 +- author: RedBookcase + changes: + - message: Mixing up a Snow White no longer creates extra liquid out of thin air. + type: Fix + id: 7611 + time: '2024-11-15T20:52:19.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/33331 From 22984f6adfb3b6d3728f0b5d080b7392264f241d Mon Sep 17 00:00:00 2001 From: lzk <124214523+lzk228@users.noreply.github.com> Date: Fri, 15 Nov 2024 22:21:08 +0100 Subject: [PATCH 017/359] Add succumb action 10 sec delay (#32985) * Add succumb action 10 sec delay * add somthing * add delay to last words as well --------- Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> --- Resources/Prototypes/Actions/crit.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Resources/Prototypes/Actions/crit.yml b/Resources/Prototypes/Actions/crit.yml index c5712844bf4..aaad27d2b7d 100644 --- a/Resources/Prototypes/Actions/crit.yml +++ b/Resources/Prototypes/Actions/crit.yml @@ -12,6 +12,8 @@ sprite: Mobs/Ghosts/ghost_human.rsi state: icon event: !type:CritSuccumbEvent + startDelay: true + useDelay: 10 - type: entity id: ActionCritFakeDeath @@ -41,3 +43,5 @@ sprite: Interface/Actions/actions_crit.rsi state: lastwords event: !type:CritLastWordsEvent + startDelay: true + useDelay: 10 From 86edb198b40fdd608603b90e30f7b483e100e2c4 Mon Sep 17 00:00:00 2001 From: PJBot Date: Fri, 15 Nov 2024 21:22:14 +0000 Subject: [PATCH 018/359] 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 4bf34d35bc4..6955fb76968 100644 --- a/Resources/Changelog/Changelog.yml +++ b/Resources/Changelog/Changelog.yml @@ -1,11 +1,4 @@ Entries: -- author: PoorMansDreams - changes: - - message: Added Star sticker in loadouts for Secoffs - type: Add - id: 7112 - time: '2024-08-15T01:50:55.0000000+00:00' - url: https://github.com/space-wizards/space-station-14/pull/29767 - author: FATFSAAM2 changes: - message: added 7 new figurine voice lines. @@ -3912,3 +3905,10 @@ id: 7611 time: '2024-11-15T20:52:19.0000000+00:00' url: https://github.com/space-wizards/space-station-14/pull/33331 +- author: lzk228 + changes: + - message: Added 10 seconds delay to Succumb action + type: Add + id: 7612 + time: '2024-11-15T21:21:08.0000000+00:00' + url: https://github.com/space-wizards/space-station-14/pull/32985 From 05fe5b701f138bfd1bcd1351c47a668310055e52 Mon Sep 17 00:00:00 2001 From: SpaceRox1244 <138547931+SpaceRox1244@users.noreply.github.com> Date: Fri, 15 Nov 2024 17:48:28 -0500 Subject: [PATCH 019/359] Adds gorilla gauntlet storage sprite and updates hit sound (#33167) * Adds storage sprite for gorilla gauntlet * Specifies a heavier hitsound for gorilla gauntlet * Modifies gauntlet icon and storage sprite * Updates credit to my new username --- .../Objects/Specific/Research/anomaly.yml | 5 +++++ .../Objects/Weapons/Melee/gorilla.rsi/icon.png | Bin 753 -> 775 bytes .../Objects/Weapons/Melee/gorilla.rsi/meta.json | 7 +++++-- .../Weapons/Melee/gorilla.rsi/storage.png | Bin 0 -> 624 bytes 4 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 Resources/Textures/Objects/Weapons/Melee/gorilla.rsi/storage.png diff --git a/Resources/Prototypes/Entities/Objects/Specific/Research/anomaly.yml b/Resources/Prototypes/Entities/Objects/Specific/Research/anomaly.yml index ff53218e222..6525cb44cfd 100644 --- a/Resources/Prototypes/Entities/Objects/Specific/Research/anomaly.yml +++ b/Resources/Prototypes/Entities/Objects/Specific/Research/anomaly.yml @@ -125,6 +125,9 @@ state: icon - type: Item size: Large + storedSprite: + state: storage + sprite: Objects/Weapons/Melee/gorilla.rsi - type: MeleeWeapon attackRate: 0.5 angle: 0 @@ -133,6 +136,8 @@ damage: types: Blunt: 20 + soundHit: + path: "/Audio/Weapons/Guns/Gunshots/kinetic_accel.ogg" - type: CorePoweredThrower - type: MeleeThrowOnHit unanchorOnHit: true diff --git a/Resources/Textures/Objects/Weapons/Melee/gorilla.rsi/icon.png b/Resources/Textures/Objects/Weapons/Melee/gorilla.rsi/icon.png index a57ce53cc4633590e7be46bbe293c5bd7cace1f4..9ce8603d2a68d0c78a8f09a9f95844ea5ca986b7 100644 GIT binary patch delta 752 zcmV3vclDCr!X4)Ld}VS9q4K56`pgeC<}|o zk!ZGGSy%+f_Nh5humg_`ZwQsupwsDyeGM^7h=vQbT%QSp4Ll1Dz^WRj=p1-AKE>=z zh=#^m%;qYrHh&8MFFspote#U{U$6rf%OULcx7Un*EB$-U5k0Tbt;jpvubDa-FxIKDn$0W?#0iWA1mh01P zgW&)GwRKLW-oFLF;jj}9M_7n15sSrCVFlEEq-U|#9_2rJ>}*5DJc;c zjTR!|d6LOgmi$TJu4*yLxf1%^ezELMx38>i0Pygj9<5dnKs>G>%LzsU0f3yya~9z3 z=oB|gD*<@rs!NNgNE7!b6|`DC@wmeCXRq-MbmvvxRVQywxXjL<9<>2*aXwva`YTJB zoS4p=Tz^$ShCGvOuyyCDJ73asb9{XM#9x!p<#LHfBlk2GOHG%_WTK*?9IaN*_^QH@ z=r>NrQ@mVDFs4k?_25Rquj;l7Jsyu39v;q)ZFVAa-uvz+(qjegJcBKzSdt{+bUN{P zJlRLYH_)w_oR~(I6U5^R0LyOh6DWpzdjT1=wrRF*5iuGFAj^sDb<6dtrw1{9Z_?w8`z>XG5k|dg&n*kUc9AtB1{wwVG81?n_ iX#fH23i%%P0PqW$ha}q5Nokw_0000Px%t4TybR9J=WmETKKVI0Ok{$M6f-a>Sz4B_v)*sMC9P2_D6q%tZMA~d@7dvPo ztg|0EmGyS9&ajy7mvqyft8-r7@AEwG^ZoL^P)8mAI~q=tY=3%SM%W}906ulJEbhiy zMFZZT2zZ0S_#b`PQ7}_ZeRD11(*rZ&-t8Qc%LxQULQkN_;w1DWj~-veCIv;QB&tqe zdSFJ3-26dO+eVMY3+qX38=$aODv7EScquIsX}*ZXVj=Y{!Uhrg?sW5HJqk`3(cD01 zNuHW#;KR}?8-ME&`ue+(Wjmct2LPeXPWn5-CF`qBz~MNL%XOLkgF|HdS!CHxG#bNV zvC!#+7x6bFHm;TAX{tutH#RA5^j-%*wmS%a`AjyupKnJhh1=~S_w$fX#CSIU^u!^o zIDvpSD0X}E-;&e@KzGkARzJQ6!0mPsjmFU8JET&nl7D;^CEy#I6w+Wj!>eI-u3W%u zwqi21(AX%j*&M{8U&&_o3*xWT=Or(rvJC{hK_Lyc1F+d{=l=IBYbG$6TK+Jx_-=`V zgM+ffq0AQe#wNvXFAT4SdF$x`z)yyWGgkcRBxbV}fR*L7vV{$l+C<3o?+r#2mWmS diff --git a/Resources/Textures/Objects/Weapons/Melee/gorilla.rsi/meta.json b/Resources/Textures/Objects/Weapons/Melee/gorilla.rsi/meta.json index 97a5fdbd2e2..55417c2e716 100644 --- a/Resources/Textures/Objects/Weapons/Melee/gorilla.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Melee/gorilla.rsi/meta.json @@ -1,14 +1,17 @@ { "version": 1, "license": "CC0-1.0", - "copyright": "Design and inhands by ricemar (discord) and icon by EmoGarbage404 (github)", + "copyright": "Design, inhands, and storage sprite by SpaceRox1244 (github) and icon by EmoGarbage404 (github)", "size": { "x": 32, "y": 32 }, "states": [ { - "name": "icon" + "name": "icon" + }, + { + "name": "storage" }, { "name": "inhand-left", diff --git a/Resources/Textures/Objects/Weapons/Melee/gorilla.rsi/storage.png b/Resources/Textures/Objects/Weapons/Melee/gorilla.rsi/storage.png new file mode 100644 index 0000000000000000000000000000000000000000..e21fc82b971ece07b67423bb0e0603cb217392c6 GIT binary patch literal 624 zcmV-$0+0QPP)U0K2E}v08zbeqOF0w zXqu?Co26QN#MN4Bf{jdu;gMm}`doI2EAL)&`}hb@GUA4TR4Qd!AVdXKHUGy>@hJ-H z>uFO=k|f3pV?13n&+WJZLR0`K6PSr5u#!wuTz|j=>YehluXxfUthP=6X$jRU_ZI6%G~Hl4&9h;GVxap0GvH{Sr24~ zn3{AMvAsqb>Dq4tj~?8y0Y4s`U-Mgsuv2O!j_QpMj)jHAf6I6B;@<@Dy8w0o0000< KMNUMnLSTZDXB*xC literal 0 HcmV?d00001 From 8abdafc353458b0410ff99945c7b5680b38c6143 Mon Sep 17 00:00:00 2001 From: beck-thompson <107373427+beck-thompson@users.noreply.github.com> Date: Fri, 15 Nov 2024 15:46:01 -0800 Subject: [PATCH 020/359] Clumsy system refactor (#31147) * First commit * Fixes * Added the noise * Renames * Timespan * Fixed space * entity -> ent * This shouldn't work * opps.... * Datafield name change * Better comments * small comment * Personal skill issue * Event renames and stuff * Couple fixes * Defib ref fixes (Silly me) * Added clumsy back! * no hard code clumsy! * Identity fix * Event name change * Comment change * Function name change * opp * Update names * Damage stuff! * Fixes! * Fixes * opps * This was hidden away!! * negative diff feeds me --- .../Systems/AdminVerbSystem.Smites.cs | 1 + .../Administration/Systems/SuperBonkSystem.cs | 22 +-- .../EntitySystems/HypospraySystem.cs | 41 ++++- Content.Server/Cluwne/CluwneSystem.cs | 1 + Content.Server/Medical/DefibrillatorSystem.cs | 70 +++++++-- .../Weapons/Ranged/Systems/GunSystem.cs | 30 +--- .../Components/HyposprayComponent.cs | 5 - .../Chemistry/Events/HyposprayEvents.cs | 38 +++++ .../Climbing/Components/BonkableComponent.cs | 34 +--- .../Climbing/Events/BeforeClimbEvents.cs | 36 +++++ Content.Shared/Climbing/Systems/BonkSystem.cs | 130 ---------------- .../Climbing/Systems/ClimbSystem.cs | 12 ++ Content.Shared/Clumsy/ClumsyComponent.cs | 61 ++++++++ Content.Shared/Clumsy/ClumsySystem.cs | 146 ++++++++++++++++++ .../Interaction/Components/ClumsyComponent.cs | 24 --- .../SharedInteractionSystem.Clumsy.cs | 26 ---- .../Inventory/InventorySystem.Relay.cs | 9 +- Content.Shared/Medical/DefibrillatorEvents.cs | 39 +++++ .../Medical/TargetDefibrillatedEvent.cs | 4 - .../Ranged/Events/BeforeGunShootEvent.cs | 20 +++ .../bonk/components/bonkable-component.ftl | 6 +- .../Prototypes/Entities/Mobs/NPCs/animals.yml | 4 +- .../Entities/Mobs/Player/guardian.yml | 2 +- .../Furniture/Tables/base_structuretables.yml | 2 - .../Prototypes/Roles/Jobs/Civilian/clown.yml | 2 +- 25 files changed, 484 insertions(+), 281 deletions(-) create mode 100644 Content.Shared/Chemistry/Events/HyposprayEvents.cs create mode 100644 Content.Shared/Climbing/Events/BeforeClimbEvents.cs delete mode 100644 Content.Shared/Climbing/Systems/BonkSystem.cs create mode 100644 Content.Shared/Clumsy/ClumsyComponent.cs create mode 100644 Content.Shared/Clumsy/ClumsySystem.cs delete mode 100644 Content.Shared/Interaction/Components/ClumsyComponent.cs delete mode 100644 Content.Shared/Interaction/SharedInteractionSystem.Clumsy.cs create mode 100644 Content.Shared/Medical/DefibrillatorEvents.cs delete mode 100644 Content.Shared/Medical/TargetDefibrillatedEvent.cs create mode 100644 Content.Shared/Weapons/Ranged/Events/BeforeGunShootEvent.cs diff --git a/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs b/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs index d57898d9d98..5e002198056 100644 --- a/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs +++ b/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs @@ -23,6 +23,7 @@ using Content.Shared.Administration.Components; using Content.Shared.Body.Components; using Content.Shared.Body.Part; +using Content.Shared.Clumsy; using Content.Shared.Clothing.Components; using Content.Shared.Cluwne; using Content.Shared.Damage; diff --git a/Content.Server/Administration/Systems/SuperBonkSystem.cs b/Content.Server/Administration/Systems/SuperBonkSystem.cs index 5488a8d6f46..5cd62d83572 100644 --- a/Content.Server/Administration/Systems/SuperBonkSystem.cs +++ b/Content.Server/Administration/Systems/SuperBonkSystem.cs @@ -1,27 +1,27 @@ using Content.Server.Administration.Components; using Content.Shared.Climbing.Components; -using Content.Shared.Climbing.Events; -using Content.Shared.Climbing.Systems; -using Content.Shared.Interaction.Components; +using Content.Shared.Clumsy; using Content.Shared.Mobs; using Content.Shared.Mobs.Components; +using Robust.Shared.Audio.Systems; namespace Content.Server.Administration.Systems; -public sealed class SuperBonkSystem: EntitySystem +public sealed class SuperBonkSystem : EntitySystem { [Dependency] private readonly SharedTransformSystem _transformSystem = default!; - [Dependency] private readonly BonkSystem _bonkSystem = default!; + [Dependency] private readonly ClumsySystem _clumsySystem = default!; + [Dependency] private readonly SharedAudioSystem _audioSystem = default!; public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnBonkShutdown); SubscribeLocalEvent(OnMobStateChanged); + SubscribeLocalEvent(OnBonkShutdown); } - public void StartSuperBonk(EntityUid target, float delay = 0.1f, bool stopWhenDead = false ) + public void StartSuperBonk(EntityUid target, float delay = 0.1f, bool stopWhenDead = false) { //The other check in the code to stop when the target dies does not work if the target is already dead. @@ -31,7 +31,6 @@ public void StartSuperBonk(EntityUid target, float delay = 0.1f, bool stopWhenDe return; } - var hadClumsy = EnsureComp(target, out _); var tables = EntityQueryEnumerator(); @@ -79,16 +78,17 @@ public override void Update(float frameTime) private void Bonk(SuperBonkComponent comp) { var uid = comp.Tables.Current.Key; - var bonkComp = comp.Tables.Current.Value; // It would be very weird for something without a transform component to have a bonk component // but just in case because I don't want to crash the server. - if (!HasComp(uid)) + if (!HasComp(uid) || !TryComp(comp.Target, out var clumsyComp)) return; _transformSystem.SetCoordinates(comp.Target, Transform(uid).Coordinates); - _bonkSystem.TryBonk(comp.Target, uid, bonkComp); + _clumsySystem.HitHeadClumsy((comp.Target, clumsyComp), uid); + + _audioSystem.PlayPvs(clumsyComp.TableBonkSound, comp.Target); } private void OnMobStateChanged(EntityUid uid, SuperBonkComponent comp, MobStateChangedEvent args) diff --git a/Content.Server/Chemistry/EntitySystems/HypospraySystem.cs b/Content.Server/Chemistry/EntitySystems/HypospraySystem.cs index 9b78e81aa00..8345aa3c3dd 100644 --- a/Content.Server/Chemistry/EntitySystems/HypospraySystem.cs +++ b/Content.Server/Chemistry/EntitySystems/HypospraySystem.cs @@ -1,6 +1,7 @@ using Content.Shared.Chemistry.EntitySystems; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Components.SolutionManager; +using Content.Shared.Chemistry.Hypospray.Events; using Content.Shared.Chemistry; using Content.Shared.Database; using Content.Shared.FixedPoint; @@ -85,14 +86,44 @@ public bool TryDoInject(Entity entity, EntityUid target, Ent string? msgFormat = null; - if (target == user) - msgFormat = "hypospray-component-inject-self-message"; - else if (EligibleEntity(user, EntityManager, component) && _interaction.TryRollClumsy(user, component.ClumsyFailChance)) + // Self event + var selfEvent = new SelfBeforeHyposprayInjectsEvent(user, entity.Owner, target); + RaiseLocalEvent(user, selfEvent); + + if (selfEvent.Cancelled) + { + _popup.PopupEntity(Loc.GetString(selfEvent.InjectMessageOverride ?? "hypospray-cant-inject", ("owner", Identity.Entity(target, EntityManager))), target, user); + return false; + } + + target = selfEvent.TargetGettingInjected; + + if (!EligibleEntity(target, EntityManager, component)) + return false; + + // Target event + var targetEvent = new TargetBeforeHyposprayInjectsEvent(user, entity.Owner, target); + RaiseLocalEvent(target, targetEvent); + + if (targetEvent.Cancelled) { - msgFormat = "hypospray-component-inject-self-clumsy-message"; - target = user; + _popup.PopupEntity(Loc.GetString(targetEvent.InjectMessageOverride ?? "hypospray-cant-inject", ("owner", Identity.Entity(target, EntityManager))), target, user); + return false; } + target = targetEvent.TargetGettingInjected; + + if (!EligibleEntity(target, EntityManager, component)) + return false; + + // The target event gets priority for the overriden message. + if (targetEvent.InjectMessageOverride != null) + msgFormat = targetEvent.InjectMessageOverride; + else if (selfEvent.InjectMessageOverride != null) + msgFormat = selfEvent.InjectMessageOverride; + else if (target == user) + msgFormat = "hypospray-component-inject-self-message"; + if (!_solutionContainers.TryGetSolution(uid, component.SolutionName, out var hypoSpraySoln, out var hypoSpraySolution) || hypoSpraySolution.Volume == 0) { _popup.PopupEntity(Loc.GetString("hypospray-component-empty-message"), target, user); diff --git a/Content.Server/Cluwne/CluwneSystem.cs b/Content.Server/Cluwne/CluwneSystem.cs index f24f0143f31..1fbb0c72690 100644 --- a/Content.Server/Cluwne/CluwneSystem.cs +++ b/Content.Server/Cluwne/CluwneSystem.cs @@ -16,6 +16,7 @@ using Content.Shared.Interaction.Components; using Robust.Shared.Audio.Systems; using Content.Shared.NameModifier.EntitySystems; +using Content.Shared.Clumsy; namespace Content.Server.Cluwne; diff --git a/Content.Server/Medical/DefibrillatorSystem.cs b/Content.Server/Medical/DefibrillatorSystem.cs index c9cb6cc58dc..fa0ea26385d 100644 --- a/Content.Server/Medical/DefibrillatorSystem.cs +++ b/Content.Server/Medical/DefibrillatorSystem.cs @@ -77,7 +77,20 @@ private void OnDoAfter(EntityUid uid, DefibrillatorComponent component, Defibril Zap(uid, target, args.User, component); } - public bool CanZap(EntityUid uid, EntityUid target, EntityUid? user = null, DefibrillatorComponent? component = null) + /// + /// Checks if you can actually defib a target. + /// + /// Uid of the defib + /// Uid of the target getting defibbed + /// Uid of the entity using the defibrillator + /// Defib component + /// + /// If true, the target can be alive. If false, the function will check if the target is alive and will return false if they are. + /// + /// + /// Returns true if the target is valid to be defibed, false otherwise. + /// + public bool CanZap(EntityUid uid, EntityUid target, EntityUid? user = null, DefibrillatorComponent? component = null, bool targetCanBeAlive = false) { if (!Resolve(uid, ref component)) return false; @@ -98,15 +111,25 @@ public bool CanZap(EntityUid uid, EntityUid target, EntityUid? user = null, Defi if (!_powerCell.HasActivatableCharge(uid, user: user)) return false; - if (_mobState.IsAlive(target, mobState)) + if (!targetCanBeAlive && _mobState.IsAlive(target, mobState)) return false; - if (!component.CanDefibCrit && _mobState.IsCritical(target, mobState)) + if (!targetCanBeAlive && !component.CanDefibCrit && _mobState.IsCritical(target, mobState)) return false; return true; } + /// + /// Tries to start defibrillating the target. If the target is valid, will start the defib do-after. + /// + /// Uid of the defib + /// Uid of the target getting defibbed + /// Uid of the entity using the defibrillator + /// Defib component + /// + /// Returns true if the defibrillation do-after started, otherwise false. + /// public bool TryStartZap(EntityUid uid, EntityUid target, EntityUid user, DefibrillatorComponent? component = null) { if (!Resolve(uid, ref component)) @@ -118,25 +141,42 @@ public bool TryStartZap(EntityUid uid, EntityUid target, EntityUid user, Defibri _audio.PlayPvs(component.ChargeSound, uid); return _doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager, user, component.DoAfterDuration, new DefibrillatorZapDoAfterEvent(), uid, target, uid) - { - NeedHand = true, - BreakOnMove = !component.AllowDoAfterMovement - }); + { + NeedHand = true, + BreakOnMove = !component.AllowDoAfterMovement + }); } - public void Zap(EntityUid uid, EntityUid target, EntityUid user, DefibrillatorComponent? component = null, MobStateComponent? mob = null, MobThresholdsComponent? thresholds = null) + /// + /// Tries to defibrillate the target with the given defibrillator. + /// + public void Zap(EntityUid uid, EntityUid target, EntityUid user, DefibrillatorComponent? component = null) { - if (!Resolve(uid, ref component) || !Resolve(target, ref mob, ref thresholds, false)) + if (!Resolve(uid, ref component)) return; - // clowns zap themselves - if (HasComp(user) && user != target) - { - Zap(uid, user, user, component); + if (!_powerCell.TryUseActivatableCharge(uid, user: user)) return; - } - if (!_powerCell.TryUseActivatableCharge(uid, user: user)) + var selfEvent = new SelfBeforeDefibrillatorZapsEvent(user, uid, target); + RaiseLocalEvent(user, selfEvent); + + target = selfEvent.DefibTarget; + + // Ensure thet new target is still valid. + if (selfEvent.Cancelled || !CanZap(uid, target, user, component, true)) + return; + + var targetEvent = new TargetBeforeDefibrillatorZapsEvent(user, uid, target); + RaiseLocalEvent(target, targetEvent); + + target = targetEvent.DefibTarget; + + if (targetEvent.Cancelled || !CanZap(uid, target, user, component, true)) + return; + + if (!TryComp(target, out var mob) || + !TryComp(target, out var thresholds)) return; _audio.PlayPvs(component.ZapSound, uid); diff --git a/Content.Server/Weapons/Ranged/Systems/GunSystem.cs b/Content.Server/Weapons/Ranged/Systems/GunSystem.cs index 29504d5a76d..03e529c4398 100644 --- a/Content.Server/Weapons/Ranged/Systems/GunSystem.cs +++ b/Content.Server/Weapons/Ranged/Systems/GunSystem.cs @@ -1,15 +1,12 @@ using System.Linq; using System.Numerics; using Content.Server.Cargo.Systems; -using Content.Server.Interaction; using Content.Server.Power.EntitySystems; -using Content.Server.Stunnable; using Content.Server.Weapons.Ranged.Components; using Content.Shared.Damage; using Content.Shared.Damage.Systems; using Content.Shared.Database; using Content.Shared.Effects; -using Content.Shared.Interaction.Components; using Content.Shared.Projectiles; using Content.Shared.Weapons.Melee; using Content.Shared.Weapons.Ranged; @@ -36,16 +33,13 @@ public sealed partial class GunSystem : SharedGunSystem [Dependency] private readonly IComponentFactory _factory = default!; [Dependency] private readonly BatterySystem _battery = default!; [Dependency] private readonly DamageExamineSystem _damageExamine = default!; - [Dependency] private readonly InteractionSystem _interaction = default!; [Dependency] private readonly PricingSystem _pricing = default!; [Dependency] private readonly SharedColorFlashEffectSystem _color = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; [Dependency] private readonly StaminaSystem _stamina = default!; - [Dependency] private readonly StunSystem _stun = default!; [Dependency] private readonly SharedContainerSystem _container = default!; private const float DamagePitchVariation = 0.05f; - public const float GunClumsyChance = 0.5f; public override void Initialize() { @@ -80,26 +74,14 @@ public override void Shoot(EntityUid gunUid, GunComponent gun, List<(EntityUid? { userImpulse = true; - // Try a clumsy roll - // TODO: Who put this here - if (TryComp(user, out var clumsy) && gun.ClumsyProof == false) + if (user != null) { - for (var i = 0; i < ammo.Count; i++) + var selfEvent = new SelfBeforeGunShotEvent(user.Value, (gunUid, gun), ammo); + RaiseLocalEvent(user.Value, selfEvent); + if (selfEvent.Cancelled) { - if (_interaction.TryRollClumsy(user.Value, GunClumsyChance, clumsy)) - { - // Wound them - Damageable.TryChangeDamage(user, clumsy.ClumsyDamage, origin: user); - _stun.TryParalyze(user.Value, TimeSpan.FromSeconds(3f), true); - - // Apply salt to the wound ("Honk!") - Audio.PlayPvs(new SoundPathSpecifier("/Audio/Weapons/Guns/Gunshots/bang.ogg"), gunUid); - Audio.PlayPvs(clumsy.ClumsySound, gunUid); - - PopupSystem.PopupEntity(Loc.GetString("gun-clumsy"), user.Value); - userImpulse = false; - return; - } + userImpulse = false; + return; } } diff --git a/Content.Shared/Chemistry/Components/HyposprayComponent.cs b/Content.Shared/Chemistry/Components/HyposprayComponent.cs index 05ef84bbaf7..17d52f0ad93 100644 --- a/Content.Shared/Chemistry/Components/HyposprayComponent.cs +++ b/Content.Shared/Chemistry/Components/HyposprayComponent.cs @@ -11,11 +11,6 @@ public sealed partial class HyposprayComponent : Component [DataField] public string SolutionName = "hypospray"; - // TODO: This should be on clumsycomponent. - [DataField] - [ViewVariables(VVAccess.ReadWrite)] - public float ClumsyFailChance = 0.5f; - [DataField] [ViewVariables(VVAccess.ReadWrite)] public FixedPoint2 TransferAmount = FixedPoint2.New(5); diff --git a/Content.Shared/Chemistry/Events/HyposprayEvents.cs b/Content.Shared/Chemistry/Events/HyposprayEvents.cs new file mode 100644 index 00000000000..e8ed081a577 --- /dev/null +++ b/Content.Shared/Chemistry/Events/HyposprayEvents.cs @@ -0,0 +1,38 @@ +using Content.Shared.Inventory; + +namespace Content.Shared.Chemistry.Hypospray.Events; + +public abstract partial class BeforeHyposprayInjectsTargetEvent : CancellableEntityEventArgs, IInventoryRelayEvent +{ + public SlotFlags TargetSlots { get; } = SlotFlags.WITHOUT_POCKET; + public EntityUid EntityUsingHypospray; + public readonly EntityUid Hypospray; + public EntityUid TargetGettingInjected; + public string? InjectMessageOverride; + + public BeforeHyposprayInjectsTargetEvent(EntityUid user, EntityUid hypospray, EntityUid target) + { + EntityUsingHypospray = user; + Hypospray = hypospray; + TargetGettingInjected = target; + InjectMessageOverride = null; + } +} + +/// +/// This event is raised on the user using the hypospray before the hypospray is injected. +/// The event is triggered on the user and all their clothing. +/// +public sealed class SelfBeforeHyposprayInjectsEvent : BeforeHyposprayInjectsTargetEvent +{ + public SelfBeforeHyposprayInjectsEvent(EntityUid user, EntityUid hypospray, EntityUid target) : base(user, hypospray, target) { } +} + +/// +/// This event is raised on the target before the hypospray is injected. +/// The event is triggered on the target itself and all its clothing. +/// +public sealed class TargetBeforeHyposprayInjectsEvent : BeforeHyposprayInjectsTargetEvent +{ + public TargetBeforeHyposprayInjectsEvent (EntityUid user, EntityUid hypospray, EntityUid target) : base(user, hypospray, target) { } +} diff --git a/Content.Shared/Climbing/Components/BonkableComponent.cs b/Content.Shared/Climbing/Components/BonkableComponent.cs index 5e97396fbad..cb4839cae71 100644 --- a/Content.Shared/Climbing/Components/BonkableComponent.cs +++ b/Content.Shared/Climbing/Components/BonkableComponent.cs @@ -1,5 +1,4 @@ using Content.Shared.Damage; -using Robust.Shared.Audio; using Robust.Shared.GameStates; namespace Content.Shared.Climbing.Components; @@ -8,39 +7,18 @@ namespace Content.Shared.Climbing.Components; /// Makes entity do damage and stun entities with ClumsyComponent /// upon DragDrop or Climb interactions. /// -[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 00000000000..85c40f9427c --- /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 f59fe925736..00000000000 --- 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 da194706f8f..9bf481002a9 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 00000000000..c71f5d0008a --- /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 00000000000..e034458197f --- /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 824696c8385..00000000000 --- 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 9e45847e078..00000000000 --- 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 c910a9ae772..9573f9b43d9 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 00000000000..54a21a40d42 --- /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 60d1a215845..00000000000 --- 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 00000000000..1d3317c840f --- /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 560b10c46ec..1a79da3509f 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 98159d4562f..97b11aa7569 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml @@ -1347,7 +1347,7 @@ rules: ghost-role-information-nonantagonist-rules - type: GhostTakeoverAvailable - type: Clumsy - clumsyDamage: + gunShootFailDamage: types: Blunt: 5 Piercing: 4 @@ -1523,7 +1523,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 b21f19edd3c..dca47e1c837 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 2862980dad3..4b3b4c18743 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 6c53530b185..d2416920d5a 100644 --- a/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml +++ b/Resources/Prototypes/Roles/Jobs/Civilian/clown.yml @@ -17,7 +17,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 321361c1a1a82cd0267268cfc09227499956ad88 Mon Sep 17 00:00:00 2001 From: PJBot Date: Fri, 15 Nov 2024 23:47:08 +0000 Subject: [PATCH 021/359] 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 6955fb76968..edc4b52be69 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 @@ -3912,3 +3903,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 c86c20355cf67b2019b7b565cb058e48d3fbfdb9 Mon Sep 17 00:00:00 2001 From: ScarKy0 Date: Sat, 16 Nov 2024 02:06:52 +0100 Subject: [PATCH 022/359] S: Awaiting Changes --- .../Silicons/Laws/SiliconLawSystem.cs | 31 +++++++++++++++++-- Resources/Locale/en-US/station-laws/laws.ftl | 5 +-- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/Content.Server/Silicons/Laws/SiliconLawSystem.cs b/Content.Server/Silicons/Laws/SiliconLawSystem.cs index 1dc8ae1c219..fa15efda561 100644 --- a/Content.Server/Silicons/Laws/SiliconLawSystem.cs +++ b/Content.Server/Silicons/Laws/SiliconLawSystem.cs @@ -69,8 +69,35 @@ 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(Entity ent, ref MindAddedMessage args) + { + if (!ent.Comp.Subverted) + return; + EnsureSubvertedSiliconRole(args.Mind); + } + + private void OnLawProviderMindRemoved(Entity ent, ref MindRemovedMessage args) + { + if (!ent.Comp.Subverted) + return; + RemoveSubvertedSiliconRole(args.Mind); + + } + + private void OnToggleLawsScreen(EntityUid uid, SiliconLawBoundComponent component, ToggleLawsScreenEvent args) { if (args.Handled || !TryComp(uid, out var actor)) @@ -118,8 +145,8 @@ private void OnIonStormLaws(EntityUid uid, SiliconLawProviderComponent component NotifyLawsChanged(uid, component.LawUploadSound); // new laws may allow antagonist behaviour so make it clear for admins - if (TryComp(uid, out var emag)) - EnsureEmaggedRole(uid, emag); + 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 00662be926b..d1b4a61f0cb 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 c65ab513931f25f43bc1c8a5992ba69351f8abec Mon Sep 17 00:00:00 2001 From: Saphire Lattice Date: Sat, 16 Nov 2024 10:25:06 +0700 Subject: [PATCH 023/359] 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 e5be0b1811f..44501767dd4 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 7729318ae7f..7acb22551b7 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 6ef282d219a..88475562c67 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 07a13d8a34a..4257c436c23 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 f8e88b218de..a9c21988ea6 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 444ffa4c45e..e13bf76941c 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 3be2ec24261..a15619d483c 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 3fd50809a7feba414c304245a44c6c2980e752f4 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 16 Nov 2024 03:26:15 +0000 Subject: [PATCH 024/359] 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 edc4b52be69..d456bd83a98 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. @@ -3911,3 +3894,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 da4e63f832d0b003439f27ed3ffa5bdc4e55b1b4 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 025/359] 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 86623eee60b..8af7b17245d 100644 --- a/Resources/Prototypes/Catalog/Fills/Crates/service.yml +++ b/Resources/Prototypes/Catalog/Fills/Crates/service.yml @@ -135,6 +135,7 @@ - id: BoxFolderYellow - id: NewtonCradle - id: BoxEnvelope + - id: BrbSign - type: entity id: CrateServiceFaxMachine From 968ea7b89352d6147718fbe6071a221c4a3b6e80 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 16 Nov 2024 03:27:57 +0000 Subject: [PATCH 026/359] 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 d456bd83a98..be145b98107 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 @@ -3901,3 +3885,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 8e0b24b38a59576676722c73395c6a27bf024206 Mon Sep 17 00:00:00 2001 From: Saphire Lattice Date: Sat, 16 Nov 2024 10:39:19 +0700 Subject: [PATCH 027/359] 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 1f3d5afb433..766c38d561b 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 fda37fe8ba7f3a8cab7dc6a58905dc1724c438cb Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 16 Nov 2024 03:40:25 +0000 Subject: [PATCH 028/359] 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 be145b98107..927da179073 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 @@ -3892,3 +3881,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 875ab71002fb8ac7ad5a80f2f214039053a9ac62 Mon Sep 17 00:00:00 2001 From: MossyGreySlope Date: Sat, 16 Nov 2024 13:57:33 +1000 Subject: [PATCH 029/359] 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 93f76473ff8..c7e20983a7a 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 818342f39856dab0d2a1bb61209da05c5fa94fc1 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 030/359] 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 72f9d3a59bf..75a1e24cdff 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 c37b7b7535a..638e94080ed 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 a8c6df7c60f064be9afe9cfe9411c9367a2f77b1 Mon Sep 17 00:00:00 2001 From: PJBot Date: Sat, 16 Nov 2024 04:31:53 +0000 Subject: [PATCH 031/359] 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 927da179073..ec2ae015a8a 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. @@ -3888,3 +3881,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 d13b2403b0b7730386012d3baf2027dddc8027c3 Mon Sep 17 00:00:00 2001 From: dffdff2423 Date: Sat, 16 Nov 2024 00:09:29 -0500 Subject: [PATCH 032/359] 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 3cf98c98aba..50a25519988 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 f83be265884..c463987a1fe 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 @@ + + + diff --git a/Content.Client/DeltaV/CartridgeLoader/Cartridges/NanoChatUiFragment.xaml.cs b/Content.Client/DeltaV/CartridgeLoader/Cartridges/NanoChatUiFragment.xaml.cs new file mode 100644 index 00000000000..159d6b1a93a --- /dev/null +++ b/Content.Client/DeltaV/CartridgeLoader/Cartridges/NanoChatUiFragment.xaml.cs @@ -0,0 +1,254 @@ +using System.Linq; +using System.Numerics; +using Content.Shared.DeltaV.CartridgeLoader.Cartridges; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; +using Robust.Client.UserInterface; +using Robust.Shared.Timing; + +namespace Content.Client.DeltaV.CartridgeLoader.Cartridges; + +[GenerateTypedNameReferences] +public sealed partial class NanoChatUiFragment : BoxContainer +{ + [Dependency] private readonly IGameTiming _timing = default!; + + private const int MaxMessageLength = 256; + + private readonly NewChatPopup _newChatPopup; + private uint? _currentChat; + private uint? _pendingChat; + private uint _ownNumber; + private bool _notificationsMuted; + private Dictionary _recipients = new(); + private Dictionary> _messages = new(); + + public event Action? OnMessageSent; + + public NanoChatUiFragment() + { + IoCManager.InjectDependencies(this); + RobustXamlLoader.Load(this); + + _newChatPopup = new NewChatPopup(); + SetupEventHandlers(); + } + + private void SetupEventHandlers() + { + _newChatPopup.OnChatCreated += (number, name, job) => + { + OnMessageSent?.Invoke(NanoChatUiMessageType.NewChat, number, name, job); + }; + + NewChatButton.OnPressed += _ => + { + _newChatPopup.ClearInputs(); + _newChatPopup.OpenCentered(); + }; + + MuteButton.OnPressed += _ => + { + _notificationsMuted = !_notificationsMuted; + UpdateMuteButton(); + OnMessageSent?.Invoke(NanoChatUiMessageType.ToggleMute, null, null, null); + }; + + MessageInput.OnTextChanged += args => + { + var length = args.Text.Length; + var isValid = !string.IsNullOrWhiteSpace(args.Text) && + length <= MaxMessageLength && + (_currentChat != null || _pendingChat != null); + + SendButton.Disabled = !isValid; + + // Show character count when over limit + CharacterCount.Visible = length > MaxMessageLength; + if (length > MaxMessageLength) + { + CharacterCount.Text = Loc.GetString("nano-chat-message-too-long", + ("current", length), + ("max", MaxMessageLength)); + CharacterCount.StyleClasses.Add("LabelDanger"); + } + }; + + SendButton.OnPressed += _ => SendMessage(); + DeleteChatButton.OnPressed += _ => DeleteCurrentChat(); + } + + private void SendMessage() + { + var activeChat = _pendingChat ?? _currentChat; + if (activeChat == null || string.IsNullOrWhiteSpace(MessageInput.Text)) + return; + + var messageContent = MessageInput.Text; + + // Add predicted message + var predictedMessage = new NanoChatMessage( + _timing.CurTime, + messageContent, + _ownNumber + ); + + if (!_messages.TryGetValue(activeChat.Value, out var value)) + { + value = new List(); + _messages[activeChat.Value] = value; + } + + value.Add(predictedMessage); + + // Update UI with predicted message + UpdateMessages(_messages); + + // Send message event + OnMessageSent?.Invoke(NanoChatUiMessageType.SendMessage, activeChat, messageContent, null); + + // Clear input + MessageInput.Text = string.Empty; + SendButton.Disabled = true; + } + + private void SelectChat(uint number) + { + // Don't reselect the same chat + if (_currentChat == number && _pendingChat == null) + return; + + _pendingChat = number; + + // Predict marking messages as read + if (_recipients.TryGetValue(number, out var recipient)) + { + recipient.HasUnread = false; + _recipients[number] = recipient; + UpdateChatList(_recipients); + } + + OnMessageSent?.Invoke(NanoChatUiMessageType.SelectChat, number, null, null); + UpdateCurrentChat(); + } + + private void DeleteCurrentChat() + { + var activeChat = _pendingChat ?? _currentChat; + if (activeChat == null) + return; + + OnMessageSent?.Invoke(NanoChatUiMessageType.DeleteChat, activeChat, null, null); + } + + private void UpdateChatList(Dictionary recipients) + { + ChatList.RemoveAllChildren(); + _recipients = recipients; + + NoChatsLabel.Visible = recipients.Count == 0; + if (NoChatsLabel.Parent != ChatList) + { + NoChatsLabel.Parent?.RemoveChild(NoChatsLabel); + ChatList.AddChild(NoChatsLabel); + } + + foreach (var (number, recipient) in recipients.OrderBy(r => r.Value.Name)) + { + var entry = new NanoChatEntry(); + // For pending chat selection, always show it as selected even if unconfirmed + var isSelected = (_pendingChat == number) || (_pendingChat == null && _currentChat == number); + entry.SetRecipient(recipient, number, isSelected); + entry.OnPressed += SelectChat; + ChatList.AddChild(entry); + } + } + + private void UpdateCurrentChat() + { + var activeChat = _pendingChat ?? _currentChat; + var hasActiveChat = activeChat != null; + + // Update UI state + MessagesScroll.Visible = hasActiveChat; + CurrentChatName.Visible = !hasActiveChat; + MessageInputContainer.Visible = hasActiveChat; + DeleteChatButton.Visible = hasActiveChat; + DeleteChatButton.Disabled = !hasActiveChat; + + if (activeChat != null && _recipients.TryGetValue(activeChat.Value, out var recipient)) + { + CurrentChatName.Text = recipient.Name + (string.IsNullOrEmpty(recipient.JobTitle) ? "" : $" ({recipient.JobTitle})"); + } + else + { + CurrentChatName.Text = Loc.GetString("nano-chat-select-chat"); + } + } + + private void UpdateMessages(Dictionary> messages) + { + _messages = messages; + MessageList.RemoveAllChildren(); + + var activeChat = _pendingChat ?? _currentChat; + if (activeChat == null || !messages.TryGetValue(activeChat.Value, out var chatMessages)) + return; + + foreach (var message in chatMessages) + { + var messageBubble = new NanoChatMessageBubble(); + messageBubble.SetMessage(message, message.SenderId == _ownNumber); + MessageList.AddChild(messageBubble); + + // Add spacing between messages + MessageList.AddChild(new Control { MinSize = new Vector2(0, 4) }); + } + + MessageList.InvalidateMeasure(); + MessagesScroll.InvalidateMeasure(); + + // Scroll to bottom after messages are added + if (MessageList.Parent is ScrollContainer scroll) + scroll.SetScrollValue(new Vector2(0, float.MaxValue)); + } + + private void UpdateMuteButton() + { + if (BellMutedIcon != null) + BellMutedIcon.Visible = _notificationsMuted; + } + + public void UpdateState(NanoChatUiState state) + { + _ownNumber = state.OwnNumber; + _notificationsMuted = state.NotificationsMuted; + OwnNumberLabel.Text = $"#{state.OwnNumber:D4}"; + UpdateMuteButton(); + + // Update new chat button state based on recipient limit + var atLimit = state.Recipients.Count >= state.MaxRecipients; + NewChatButton.Disabled = atLimit; + NewChatButton.ToolTip = atLimit + ? Loc.GetString("nano-chat-max-recipients") + : Loc.GetString("nano-chat-new-chat"); + + // First handle pending chat resolution if we have one + if (_pendingChat != null) + { + if (_pendingChat == state.CurrentChat) + _currentChat = _pendingChat; // Server confirmed our selection + + _pendingChat = null; // Clear pending either way + } + + // No pending chat or it was just cleared, update current directly + if (_pendingChat == null) + _currentChat = state.CurrentChat; + + UpdateCurrentChat(); + UpdateChatList(state.Recipients); + UpdateMessages(state.Messages); + } +} diff --git a/Content.Client/DeltaV/CartridgeLoader/Cartridges/NewChatPopup.xaml b/Content.Client/DeltaV/CartridgeLoader/Cartridges/NewChatPopup.xaml new file mode 100644 index 00000000000..20095c4fce9 --- /dev/null +++ b/Content.Client/DeltaV/CartridgeLoader/Cartridges/NewChatPopup.xaml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + +