From fffce0a625d7015ce7650283f9817a58f4af30bb Mon Sep 17 00:00:00 2001 From: harryhulse12-alt Date: Sun, 7 Dec 2025 21:42:40 +0000 Subject: [PATCH 01/16] removes guerilla gloves from uplink --- .../_Goobstation/Catalog/uplink_catalog.yml | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Resources/Prototypes/_Goobstation/Catalog/uplink_catalog.yml b/Resources/Prototypes/_Goobstation/Catalog/uplink_catalog.yml index 5e2b56cc040..1c53019cac5 100644 --- a/Resources/Prototypes/_Goobstation/Catalog/uplink_catalog.yml +++ b/Resources/Prototypes/_Goobstation/Catalog/uplink_catalog.yml @@ -602,16 +602,17 @@ # categories: # - UplinkWearables -- type: listing - id: UplinkClothingHandsGlovesGuerrilla - name: uplink-guerrilla-gloves-name - description: uplink-guerrilla-gloves-desc - icon: { sprite: /Textures/_Goobstation/Clothing/Hands/Gloves/guerrilla.rsi, state: icon } - productEntity: ClothingHandsGlovesGuerrilla - cost: - Telecrystal: 20 - categories: - - UplinkWearables +# Omu change - just plain unfun and unbalanced +#- type: listing +# id: UplinkClothingHandsGlovesGuerrilla +# name: uplink-guerrilla-gloves-name +# description: uplink-guerrilla-gloves-desc +# icon: { sprite: /Textures/_Goobstation/Clothing/Hands/Gloves/guerrilla.rsi, state: icon } +# productEntity: ClothingHandsGlovesGuerrilla +# cost: +# Telecrystal: 20 +# categories: +# - UplinkWearables # Job specific - type: listing From 4b7fc746938a4cd2eec549a4e7e40a9e0251be43 Mon Sep 17 00:00:00 2001 From: harryhulse12-alt Date: Sun, 7 Dec 2025 21:44:07 +0000 Subject: [PATCH 02/16] oops --- .../_Goobstation/Catalog/uplink_catalog.yml | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/Resources/Prototypes/_Goobstation/Catalog/uplink_catalog.yml b/Resources/Prototypes/_Goobstation/Catalog/uplink_catalog.yml index 1c53019cac5..5e2b56cc040 100644 --- a/Resources/Prototypes/_Goobstation/Catalog/uplink_catalog.yml +++ b/Resources/Prototypes/_Goobstation/Catalog/uplink_catalog.yml @@ -602,17 +602,16 @@ # categories: # - UplinkWearables -# Omu change - just plain unfun and unbalanced -#- type: listing -# id: UplinkClothingHandsGlovesGuerrilla -# name: uplink-guerrilla-gloves-name -# description: uplink-guerrilla-gloves-desc -# icon: { sprite: /Textures/_Goobstation/Clothing/Hands/Gloves/guerrilla.rsi, state: icon } -# productEntity: ClothingHandsGlovesGuerrilla -# cost: -# Telecrystal: 20 -# categories: -# - UplinkWearables +- type: listing + id: UplinkClothingHandsGlovesGuerrilla + name: uplink-guerrilla-gloves-name + description: uplink-guerrilla-gloves-desc + icon: { sprite: /Textures/_Goobstation/Clothing/Hands/Gloves/guerrilla.rsi, state: icon } + productEntity: ClothingHandsGlovesGuerrilla + cost: + Telecrystal: 20 + categories: + - UplinkWearables # Job specific - type: listing From b4ced3a1cf8f550db32510e41b001ec4ee8d28d9 Mon Sep 17 00:00:00 2001 From: harryhulse12-alt Date: Sun, 11 Jan 2026 20:06:57 +0000 Subject: [PATCH 03/16] Medbounty --- .../VendingMachines/Inventories/medical.yml | 2 + .../VendingMachines/Inventories/sec.yml | 4 +- .../Objects/Specific/Medical/hypospray.yml | 42 +++++++++++++++++++ .../Recipes/Lathes/Packs/medical.yml | 2 + .../Recipes/Lathes/Packs/security.yml | 2 + .../_Goobstation/Recipes/Lathes/security.yml | 16 +++++++ 6 files changed, 67 insertions(+), 1 deletion(-) diff --git a/Resources/Prototypes/Catalog/VendingMachines/Inventories/medical.yml b/Resources/Prototypes/Catalog/VendingMachines/Inventories/medical.yml index d4d256b8537..1c9e33391cd 100644 --- a/Resources/Prototypes/Catalog/VendingMachines/Inventories/medical.yml +++ b/Resources/Prototypes/Catalog/VendingMachines/Inventories/medical.yml @@ -120,6 +120,8 @@ CartridgeBicaridine: 4 CartridgeDermaline: 4 CartridgeAtropine: 4 + CartridgeArith: 4 + CartridgeDylo: 4 VehicleWheelchairFolded: 3 FoodSnackLollypopWrappedMystery: 10 FoodSnackLollypopWrappedTricordrazine: 8 diff --git a/Resources/Prototypes/Catalog/VendingMachines/Inventories/sec.yml b/Resources/Prototypes/Catalog/VendingMachines/Inventories/sec.yml index 94b8efd03cc..ba29fe3e437 100644 --- a/Resources/Prototypes/Catalog/VendingMachines/Inventories/sec.yml +++ b/Resources/Prototypes/Catalog/VendingMachines/Inventories/sec.yml @@ -72,7 +72,9 @@ CartridgeSaline: 2 CartridgeBicaridine: 2 CartridgeDermaline: 2 # Goobstation - end - PanicButton: 2 # Omu + PanicButton: 2 # Omu start + CartridgeArith: 4 + CartridgeDylo: 4 # Omu end # security officers need to follow a diet regimen! contrabandInventory: WeaponMeleeNeedle: 2 diff --git a/Resources/Prototypes/_Goobstation/Entities/Objects/Specific/Medical/hypospray.yml b/Resources/Prototypes/_Goobstation/Entities/Objects/Specific/Medical/hypospray.yml index 817075bba48..d84890a3dd7 100644 --- a/Resources/Prototypes/_Goobstation/Entities/Objects/Specific/Medical/hypospray.yml +++ b/Resources/Prototypes/_Goobstation/Entities/Objects/Specific/Medical/hypospray.yml @@ -262,6 +262,48 @@ - ReagentId: Atropine Quantity: 10 +#OMU start + +- type: entity + name: radiation autoinjector cartridge + parent: [ BaseSecurityMedicalContraband , BaseAutoinjectorCartridge ] + description: Contains 10u of arithrazine, used in a cartridge autoinjector. + id: CartridgeArith + components: + - type: Sprite + layers: + - state: base + - state: filling + color: "#572757" + - type: SolutionCartridge + targetSolution: hypospray + solution: + maxVol: 10 + reagents: + - ReagentId: Arithrazine + Quantity: 10 + +- type: entity + name: poison autoinjector cartridge + parent: [ BaseSecurityMedicalContraband , BaseAutoinjectorCartridge ] + description: Contains 10u of dylovene, used in a cartridge autoinjector. + id: CartridgeDylo + components: + - type: Sprite + layers: + - state: base + - state: filling + color: "#572757" + - type: SolutionCartridge + targetSolution: hypospray + solution: + maxVol: 10 + reagents: + - ReagentId: Dylovene + Quantity: 10 + +# OMU end + - type: entity name: piercing autoinjector cartridge parent: [ BaseSyndicateContraband , BaseAutoinjectorCartridge ] diff --git a/Resources/Prototypes/_Goobstation/Recipes/Lathes/Packs/medical.yml b/Resources/Prototypes/_Goobstation/Recipes/Lathes/Packs/medical.yml index 376ab6e55e3..c190b00c999 100644 --- a/Resources/Prototypes/_Goobstation/Recipes/Lathes/Packs/medical.yml +++ b/Resources/Prototypes/_Goobstation/Recipes/Lathes/Packs/medical.yml @@ -24,6 +24,8 @@ - CartridgeBicaridine - CartridgeDermaline - CartridgeSaline + - CartridgeArith + - CartridgeDylo - ParamedHypo - type: latheRecipePack diff --git a/Resources/Prototypes/_Goobstation/Recipes/Lathes/Packs/security.yml b/Resources/Prototypes/_Goobstation/Recipes/Lathes/Packs/security.yml index f76260ea6fd..41c188463fc 100644 --- a/Resources/Prototypes/_Goobstation/Recipes/Lathes/Packs/security.yml +++ b/Resources/Prototypes/_Goobstation/Recipes/Lathes/Packs/security.yml @@ -33,6 +33,8 @@ - CartridgeDermaline - CartridgeAtropine - CartridgeSaline + - CartridgeArith + - CartridgeDylo - SecHypo - type: latheRecipePack diff --git a/Resources/Prototypes/_Goobstation/Recipes/Lathes/security.yml b/Resources/Prototypes/_Goobstation/Recipes/Lathes/security.yml index efc51a353bc..c771ef86811 100644 --- a/Resources/Prototypes/_Goobstation/Recipes/Lathes/security.yml +++ b/Resources/Prototypes/_Goobstation/Recipes/Lathes/security.yml @@ -90,6 +90,22 @@ Glass: 100 Plasma: 50 +- type: latheRecipe + id: CartridgeArith + result: CartridgeArith + completetime: 1 + materials: + Glass: 100 + Plasma: 100 + +- type: latheRecipe + id: CartridgeDylo + result: CartridgeDylo + completetime: 1 + materials: + Glass: 100 + Plasma: 100 + - type: latheRecipe id: CartridgeEphedrine result: CartridgeEphedrine From 1f42e590d189ef11cbaff567e258d94c8c2d256c Mon Sep 17 00:00:00 2001 From: harryhulse12-alt Date: Mon, 12 Jan 2026 17:56:19 +0000 Subject: [PATCH 04/16] Update Resources/Prototypes/_Goobstation/Recipes/Lathes/Packs/medical.yml Co-authored-by: John Willis <143434770+CerberusWolfie@users.noreply.github.com> --- .../Prototypes/_Goobstation/Recipes/Lathes/Packs/medical.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Resources/Prototypes/_Goobstation/Recipes/Lathes/Packs/medical.yml b/Resources/Prototypes/_Goobstation/Recipes/Lathes/Packs/medical.yml index c190b00c999..a0e30f4e913 100644 --- a/Resources/Prototypes/_Goobstation/Recipes/Lathes/Packs/medical.yml +++ b/Resources/Prototypes/_Goobstation/Recipes/Lathes/Packs/medical.yml @@ -24,8 +24,8 @@ - CartridgeBicaridine - CartridgeDermaline - CartridgeSaline - - CartridgeArith - - CartridgeDylo + - CartridgeArith # Omu + - CartridgeDylo # Omu - ParamedHypo - type: latheRecipePack From 6ae69847c7bb43953f32e249aa80b5795685dceb Mon Sep 17 00:00:00 2001 From: harryhulse12-alt Date: Mon, 12 Jan 2026 17:56:43 +0000 Subject: [PATCH 05/16] Update Resources/Prototypes/Catalog/VendingMachines/Inventories/medical.yml Co-authored-by: John Willis <143434770+CerberusWolfie@users.noreply.github.com> --- .../Catalog/VendingMachines/Inventories/medical.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Resources/Prototypes/Catalog/VendingMachines/Inventories/medical.yml b/Resources/Prototypes/Catalog/VendingMachines/Inventories/medical.yml index 1c9e33391cd..f356f45e8c8 100644 --- a/Resources/Prototypes/Catalog/VendingMachines/Inventories/medical.yml +++ b/Resources/Prototypes/Catalog/VendingMachines/Inventories/medical.yml @@ -120,8 +120,8 @@ CartridgeBicaridine: 4 CartridgeDermaline: 4 CartridgeAtropine: 4 - CartridgeArith: 4 - CartridgeDylo: 4 + CartridgeArith: 2 # Omu + CartridgeDylo: 2 # Omu VehicleWheelchairFolded: 3 FoodSnackLollypopWrappedMystery: 10 FoodSnackLollypopWrappedTricordrazine: 8 From c59c7a70b9b8c5a0aff0272c0073d902fa0d6be9 Mon Sep 17 00:00:00 2001 From: harryhulse12-alt Date: Mon, 12 Jan 2026 17:56:50 +0000 Subject: [PATCH 06/16] Update Resources/Prototypes/_Goobstation/Recipes/Lathes/Packs/security.yml Co-authored-by: John Willis <143434770+CerberusWolfie@users.noreply.github.com> --- .../Prototypes/_Goobstation/Recipes/Lathes/Packs/security.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/Resources/Prototypes/_Goobstation/Recipes/Lathes/Packs/security.yml b/Resources/Prototypes/_Goobstation/Recipes/Lathes/Packs/security.yml index 41c188463fc..f76260ea6fd 100644 --- a/Resources/Prototypes/_Goobstation/Recipes/Lathes/Packs/security.yml +++ b/Resources/Prototypes/_Goobstation/Recipes/Lathes/Packs/security.yml @@ -33,8 +33,6 @@ - CartridgeDermaline - CartridgeAtropine - CartridgeSaline - - CartridgeArith - - CartridgeDylo - SecHypo - type: latheRecipePack From ccfb9d406e2dd285cabb2da2aaf6ff02cd325c45 Mon Sep 17 00:00:00 2001 From: harryhulse12-alt Date: Mon, 12 Jan 2026 17:57:06 +0000 Subject: [PATCH 07/16] Update Resources/Prototypes/Catalog/VendingMachines/Inventories/sec.yml Co-authored-by: John Willis <143434770+CerberusWolfie@users.noreply.github.com> --- .../Prototypes/Catalog/VendingMachines/Inventories/sec.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Resources/Prototypes/Catalog/VendingMachines/Inventories/sec.yml b/Resources/Prototypes/Catalog/VendingMachines/Inventories/sec.yml index ba29fe3e437..94b8efd03cc 100644 --- a/Resources/Prototypes/Catalog/VendingMachines/Inventories/sec.yml +++ b/Resources/Prototypes/Catalog/VendingMachines/Inventories/sec.yml @@ -72,9 +72,7 @@ CartridgeSaline: 2 CartridgeBicaridine: 2 CartridgeDermaline: 2 # Goobstation - end - PanicButton: 2 # Omu start - CartridgeArith: 4 - CartridgeDylo: 4 # Omu end + PanicButton: 2 # Omu # security officers need to follow a diet regimen! contrabandInventory: WeaponMeleeNeedle: 2 From 88fc732c14bb5a95014caa288c6402fd310719cf Mon Sep 17 00:00:00 2001 From: harryhulse12-alt Date: Mon, 12 Jan 2026 18:36:07 +0000 Subject: [PATCH 08/16] Okai Fen --- .../Objects/Specific/Medical/hypospray.yml | 42 ------------------- .../_Goobstation/Recipes/Lathes/security.yml | 16 ------- .../Objects/Specific/Medical/hypospray.yml | 37 ++++++++++++++++ .../_Omu/Recipes/Lathes/security.yml | 16 +++++++ 4 files changed, 53 insertions(+), 58 deletions(-) create mode 100644 Resources/Prototypes/_Omu/Entities/Objects/Specific/Medical/hypospray.yml diff --git a/Resources/Prototypes/_Goobstation/Entities/Objects/Specific/Medical/hypospray.yml b/Resources/Prototypes/_Goobstation/Entities/Objects/Specific/Medical/hypospray.yml index d84890a3dd7..817075bba48 100644 --- a/Resources/Prototypes/_Goobstation/Entities/Objects/Specific/Medical/hypospray.yml +++ b/Resources/Prototypes/_Goobstation/Entities/Objects/Specific/Medical/hypospray.yml @@ -262,48 +262,6 @@ - ReagentId: Atropine Quantity: 10 -#OMU start - -- type: entity - name: radiation autoinjector cartridge - parent: [ BaseSecurityMedicalContraband , BaseAutoinjectorCartridge ] - description: Contains 10u of arithrazine, used in a cartridge autoinjector. - id: CartridgeArith - components: - - type: Sprite - layers: - - state: base - - state: filling - color: "#572757" - - type: SolutionCartridge - targetSolution: hypospray - solution: - maxVol: 10 - reagents: - - ReagentId: Arithrazine - Quantity: 10 - -- type: entity - name: poison autoinjector cartridge - parent: [ BaseSecurityMedicalContraband , BaseAutoinjectorCartridge ] - description: Contains 10u of dylovene, used in a cartridge autoinjector. - id: CartridgeDylo - components: - - type: Sprite - layers: - - state: base - - state: filling - color: "#572757" - - type: SolutionCartridge - targetSolution: hypospray - solution: - maxVol: 10 - reagents: - - ReagentId: Dylovene - Quantity: 10 - -# OMU end - - type: entity name: piercing autoinjector cartridge parent: [ BaseSyndicateContraband , BaseAutoinjectorCartridge ] diff --git a/Resources/Prototypes/_Goobstation/Recipes/Lathes/security.yml b/Resources/Prototypes/_Goobstation/Recipes/Lathes/security.yml index ed216359c4e..26b1d75f64c 100644 --- a/Resources/Prototypes/_Goobstation/Recipes/Lathes/security.yml +++ b/Resources/Prototypes/_Goobstation/Recipes/Lathes/security.yml @@ -90,22 +90,6 @@ Glass: 100 Plasma: 50 -- type: latheRecipe - id: CartridgeArith - result: CartridgeArith - completetime: 1 - materials: - Glass: 100 - Plasma: 100 - -- type: latheRecipe - id: CartridgeDylo - result: CartridgeDylo - completetime: 1 - materials: - Glass: 100 - Plasma: 100 - - type: latheRecipe id: CartridgeEphedrine result: CartridgeEphedrine diff --git a/Resources/Prototypes/_Omu/Entities/Objects/Specific/Medical/hypospray.yml b/Resources/Prototypes/_Omu/Entities/Objects/Specific/Medical/hypospray.yml new file mode 100644 index 00000000000..7a0ff37eadd --- /dev/null +++ b/Resources/Prototypes/_Omu/Entities/Objects/Specific/Medical/hypospray.yml @@ -0,0 +1,37 @@ +- type: entity + name: radiation autoinjector cartridge + parent: [ BaseSecurityMedicalContraband , BaseAutoinjectorCartridge ] + description: Contains 10u of arithrazine, used in a cartridge autoinjector. + id: CartridgeArith + components: + - type: Sprite + layers: + - state: base + - state: filling + color: "#572757" + - type: SolutionCartridge + targetSolution: hypospray + solution: + maxVol: 10 + reagents: + - ReagentId: Arithrazine + Quantity: 10 + +- type: entity + name: poison autoinjector cartridge + parent: [ BaseSecurityMedicalContraband , BaseAutoinjectorCartridge ] + description: Contains 10u of dylovene, used in a cartridge autoinjector. + id: CartridgeDylo + components: + - type: Sprite + layers: + - state: base + - state: filling + color: "#572757" + - type: SolutionCartridge + targetSolution: hypospray + solution: + maxVol: 10 + reagents: + - ReagentId: Dylovene + Quantity: 10 diff --git a/Resources/Prototypes/_Omu/Recipes/Lathes/security.yml b/Resources/Prototypes/_Omu/Recipes/Lathes/security.yml index 243c9680524..b3dce894932 100644 --- a/Resources/Prototypes/_Omu/Recipes/Lathes/security.yml +++ b/Resources/Prototypes/_Omu/Recipes/Lathes/security.yml @@ -75,3 +75,19 @@ result: MagazineBoxCaselessRifleUranium materials: Uranium: 720 + +- type: latheRecipe + id: CartridgeArith + result: CartridgeArith + completetime: 1 + materials: + Glass: 100 + Plasma: 100 + +- type: latheRecipe + id: CartridgeDylo + result: CartridgeDylo + completetime: 1 + materials: + Glass: 100 + Plasma: 100 From 4de0451c263b52470773f125bda8d32e10e95441 Mon Sep 17 00:00:00 2001 From: MaiaArai <158123176+YaraaraY@users.noreply.github.com> Date: Sun, 21 Dec 2025 21:53:49 -0300 Subject: [PATCH 09/16] Soft Critical Port & Implementation (#2359) Co-authored-by: funkystationbot --- .../UI/HealthAnalyzerWindow.xaml.cs | 4 +- .../Overlays/EntityHealthBarOverlay.cs | 25 ++++---- .../Overlays/ShowHealthIconsSystem.cs | 27 +++++++- .../DamageOverlayUiController.cs | 7 +++ .../DamageOverlays/Overlays/DamageOverlay.cs | 9 ++- Content.Server/Chat/Systems/ChatSystem.cs | 30 ++++++++- .../Damage/ForceSay/DamageForceSaySystem.cs | 6 +- .../EffectConditions/MobStateCondition.cs | 8 +++ .../Explosion/EntitySystems/TriggerSystem.cs | 5 +- Content.Server/Ghost/Roles/GhostRoleSystem.cs | 8 +++ Content.Server/Guardian/GuardianSystem.cs | 6 +- .../KillTracking/KillTrackerComponent.cs | 10 ++- .../KillTracking/KillTrackingSystem.cs | 4 +- Content.Server/Mobs/DeathgaspSystem.cs | 6 +- Content.Server/NPC/Systems/NPCSystem.cs | 6 +- .../Revenant/EntitySystems/EssenceSystem.cs | 6 +- .../Systems/VocalizationSystem.cs | 10 ++- Content.Server/_DV/Harpy/HarpySingerSystem.cs | 5 +- .../ActionBlocker/ActionBlockerSystem.cs | 7 ++- .../SharedTypingIndicatorSystem.cs | 62 ++++++++++++++++++- Content.Shared/Cuffs/SharedCuffableSystem.cs | 21 ++++++- .../Damage/Components/DamageableComponent.cs | 6 ++ .../Mobs/Components/MobStateComponent.cs | 6 +- .../Mobs/Components/MobThresholdsComponent.cs | 4 ++ Content.Shared/Mobs/MobState.cs | 8 ++- .../Systems/MobStateSystem.StateMachine.cs | 31 +++++++++- .../Systems/MobStateSystem.Subscribers.cs | 35 ++++++++++- Content.Shared/Mobs/Systems/MobStateSystem.cs | 18 +++++- .../Mobs/Systems/MobThresholdSystem.cs | 23 +++++-- .../Movement/Pulling/Systems/PullingSystem.cs | 2 +- .../Movement/Systems/SharedMoverController.cs | 6 +- Content.Shared/Silicons/Bots/MedibotSystem.cs | 3 +- Content.Shared/Speech/SpeakAttemptEvent.cs | 1 + Content.Shared/Stunnable/SharedStunSystem.cs | 6 +- .../Prototypes/Entities/Mobs/Species/base.yml | 12 ++++ 35 files changed, 374 insertions(+), 59 deletions(-) diff --git a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs index 7147c1684e0..f109c8bc290 100644 --- a/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs +++ b/Content.Client/HealthAnalyzer/UI/HealthAnalyzerWindow.xaml.cs @@ -64,6 +64,8 @@ // SPDX-FileCopyrightText: 2025 gluesniffler // SPDX-FileCopyrightText: 2025 gus // SPDX-FileCopyrightText: 2025 kurokoTurbo <92106367+kurokoTurbo@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 taydeo // // SPDX-License-Identifier: AGPL-3.0-or-later @@ -482,7 +484,7 @@ private static string GetStatus(MobState mobState) return mobState switch { MobState.Alive => Loc.GetString("health-analyzer-window-entity-alive-text"), - MobState.Critical => Loc.GetString("health-analyzer-window-entity-critical-text"), + MobState.Critical or MobState.SoftCritical or MobState.HardCritical => Loc.GetString("health-analyzer-window-entity-critical-text"), MobState.Dead => Loc.GetString("health-analyzer-window-entity-dead-text"), _ => Loc.GetString("health-analyzer-window-entity-unknown-text"), }; diff --git a/Content.Client/Overlays/EntityHealthBarOverlay.cs b/Content.Client/Overlays/EntityHealthBarOverlay.cs index a3bdfc9e6dc..c4a5d8f2d90 100644 --- a/Content.Client/Overlays/EntityHealthBarOverlay.cs +++ b/Content.Client/Overlays/EntityHealthBarOverlay.cs @@ -83,6 +83,10 @@ // SPDX-FileCopyrightText: 2025 gluesniffler // SPDX-FileCopyrightText: 2025 gus // SPDX-FileCopyrightText: 2025 kurokoTurbo <92106367+kurokoTurbo@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 Tayrtahn +// SPDX-FileCopyrightText: 2025 Toastermeister <215405651+Toastermeister@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 taydeo // // SPDX-License-Identifier: AGPL-3.0-or-later @@ -108,7 +112,7 @@ namespace Content.Client.Overlays; /// /// Overlay that shows a health bar on mobs. /// -public sealed class EntityHealthBarOverlay : Overlay +public sealed partial class EntityHealthBarOverlay : Overlay { private readonly IEntityManager _entManager; private readonly IPrototypeManager _prototype; @@ -173,7 +177,6 @@ protected override void Draw(in OverlayDrawArgs args) if (!bounds.Translated(worldPos).Intersects(args.WorldAABB)) continue; - // we are all progressing towards death every day if (CalcProgress(uid, mobStateComponent, damageableComponent, mobThresholdsComponent) is not { } deathProgress) continue; @@ -224,34 +227,30 @@ protected override void Draw(in OverlayDrawArgs args) if (dmg.HealthBarThreshold != null && totalDamage < dmg.HealthBarThreshold) // GoobStation return null; - if (!_mobThresholdSystem.TryGetThresholdForState(uid, MobState.Critical, out var threshold, thresholds) && - !_mobThresholdSystem.TryGetThresholdForState(uid, MobState.Dead, out threshold, thresholds)) - return (1, false); + if (firstCritThreshold == 0) + return (1f, false); var ratio = 1 - ((FixedPoint2)(totalDamage / threshold)).Float(); // GoobStation return (ratio, false); } - if (_mobStateSystem.IsCritical(uid, component)) + if (_mobStateSystem.IsIncapacitated(uid, component) && !_mobStateSystem.IsDead(uid, component)) { - if (!_mobThresholdSystem.TryGetThresholdForState(uid, MobState.Critical, out var critThreshold, thresholds) || - !_mobThresholdSystem.TryGetThresholdForState(uid, MobState.Dead, out var deadThreshold, thresholds)) - { - return (1, true); - } + if (deadThreshold <= firstCritThreshold) + return (0f, true); var ratio = 1 - ((totalDamage - critThreshold) / (deadThreshold - critThreshold)).Value.Float(); // GoobStation return (ratio, true); } - return (0, true); + return (0f, true); } public Color GetProgressColor(float progress, bool crit) { if (crit) - progress = 0; + return Red; return _progressColor.GetProgressColor(progress); } diff --git a/Content.Client/Overlays/ShowHealthIconsSystem.cs b/Content.Client/Overlays/ShowHealthIconsSystem.cs index d2bb9ba296a..4ae70c7e614 100644 --- a/Content.Client/Overlays/ShowHealthIconsSystem.cs +++ b/Content.Client/Overlays/ShowHealthIconsSystem.cs @@ -75,12 +75,18 @@ // SPDX-FileCopyrightText: 2024 voidnull000 <18663194+voidnull000@users.noreply.github.com> // SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com> // SPDX-FileCopyrightText: 2025 Milon +// SPDX-FileCopyrightText: 2024 Tadeo +// SPDX-FileCopyrightText: 2025 Tay +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 slarticodefast <161409025+slarticodefast@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 taydeo // // SPDX-License-Identifier: AGPL-3.0-or-later using Content.Shared.Atmos.Rotting; using Content.Shared.Damage; using Content.Shared.Inventory.Events; +using Content.Shared.Mobs; using Content.Shared.Mobs.Components; using Content.Shared.Overlays; using Content.Shared.StatusIcon; @@ -91,6 +97,7 @@ namespace Content.Client.Overlays; + /// /// Shows a healthy icon on mobs. /// @@ -162,9 +169,25 @@ private IReadOnlyList DecideHealthIcons(Entity(entity) && _prototypeMan.TryIndex(damageableComponent.RottingIcon, out var rottingIcon)) + { result.Add(rottingIcon); - else if (damageableComponent.HealthIcons.TryGetValue(state.CurrentState, out var value) && _prototypeMan.TryIndex(value, out var icon)) - result.Add(icon); + } + else + { + // Try to get the specific state icon + if (damageableComponent.HealthIcons.TryGetValue(state.CurrentState, out var value)) + { + if (_prototypeMan.TryIndex(value, out var icon)) + result.Add(icon); + } + // Fallback: If in SoftCrit or HardCrit but no icon found, use the standard Critical icon + else if ((state.CurrentState == MobState.SoftCritical || state.CurrentState == MobState.HardCritical) && + damageableComponent.HealthIcons.TryGetValue(MobState.Critical, out var critValue)) + { + if (_prototypeMan.TryIndex(critValue, out var critIcon)) + result.Add(critIcon); + } + } } } diff --git a/Content.Client/UserInterface/Systems/DamageOverlays/DamageOverlayUiController.cs b/Content.Client/UserInterface/Systems/DamageOverlays/DamageOverlayUiController.cs index 34649772f57..40076862a22 100644 --- a/Content.Client/UserInterface/Systems/DamageOverlays/DamageOverlayUiController.cs +++ b/Content.Client/UserInterface/Systems/DamageOverlays/DamageOverlayUiController.cs @@ -17,6 +17,11 @@ // SPDX-FileCopyrightText: 2025 gluesniffler // SPDX-FileCopyrightText: 2025 gus // SPDX-FileCopyrightText: 2025 kurokoTurbo <92106367+kurokoTurbo@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 Tay +// SPDX-FileCopyrightText: 2025 Tojo <32783144+Alecksohs@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 slarticodefast <161409025+slarticodefast@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 taydeo // // SPDX-License-Identifier: AGPL-3.0-or-later @@ -199,6 +204,8 @@ private void UpdateOverlays(EntityUid entity, break; } + case MobState.SoftCritical: + case MobState.HardCritical: case MobState.Critical: { _overlay.CritLevel = FixedPoint2.Min(1f, diff --git a/Content.Client/UserInterface/Systems/DamageOverlays/Overlays/DamageOverlay.cs b/Content.Client/UserInterface/Systems/DamageOverlays/Overlays/DamageOverlay.cs index b02c6647a23..b673ade2f89 100644 --- a/Content.Client/UserInterface/Systems/DamageOverlays/Overlays/DamageOverlay.cs +++ b/Content.Client/UserInterface/Systems/DamageOverlays/Overlays/DamageOverlay.cs @@ -14,6 +14,13 @@ // SPDX-FileCopyrightText: 2025 gluesniffler // SPDX-FileCopyrightText: 2025 kurokoTurbo <92106367+kurokoTurbo@users.noreply.github.com> // SPDX-FileCopyrightText: 2025 RichardBlonski <48651647+RichardBlonski@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 Pieter-Jan Briers +// SPDX-FileCopyrightText: 2025 Steve +// SPDX-FileCopyrightText: 2025 Tay +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 marc-pelletier <113944176+marc-pelletier@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 taydeo // // SPDX-License-Identifier: MIT @@ -192,7 +199,7 @@ protected override void Draw(in OverlayDrawArgs args) } // Goobstation end - level = State != MobState.Critical ? _oldOxygenLevel : 1f; + level = State != MobState.Critical && State != MobState.HardCritical ? _oldOxygenLevel : 1f; if (level > 0f) { diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index 4e193316e65..a52c33da4bb 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -106,6 +106,12 @@ // SPDX-FileCopyrightText: 2025 ash lea // SPDX-FileCopyrightText: 2025 gluesniffler <159397573+gluesniffler@users.noreply.github.com> // SPDX-FileCopyrightText: 2025 pathetic meowmeow +// SPDX-FileCopyrightText: 2024 kbarkevich <24629810+kbarkevich@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 Tay +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 duston <66768086+dch-GH@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 slarticodefast <161409025+slarticodefast@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 taydeo // // SPDX-License-Identifier: AGPL-3.0-or-later @@ -348,6 +354,16 @@ public void TrySendInGameICMessage( // and i dont feel like vibe checking 50 code paths // so we set this here // todo free me from chat code + + // check if the entity is forced to whisper and convert to local whisper if yes + if (!ignoreActionBlocker && _actionBlocker.CanSpeak(source, out var onlyWhisper)) + { + if (desiredType == InGameICChatType.Speak && onlyWhisper) + { + desiredType = InGameICChatType.Whisper; + } + } + if (player != null) { _chatManager.EnsurePlayer(player.UserId).AddEntity(GetNetEntity(source)); @@ -672,7 +688,10 @@ private void SendEntitySpeak( Color? colorOverride = null // Goobstation ) { - if (!_actionBlocker.CanSpeak(source) && !ignoreActionBlocker) + if (!_actionBlocker.CanSpeak(source, out var onlyWhisper) && !ignoreActionBlocker) + return; + + if (onlyWhisper) return; // The Original Message [-] Einstein Engines - Language @@ -780,7 +799,7 @@ private void SendEntityWhisper( Color? colorOverride = null // Goobstation ) { - if (!_actionBlocker.CanSpeak(source) && !ignoreActionBlocker) + if (!_actionBlocker.CanSpeak(source, out var onlyWhisper) && !ignoreActionBlocker) return; // Goob edit start @@ -788,8 +807,15 @@ private void SendEntityWhisper( message = FormattedMessage.EscapeText(message); message = TransformSpeech(source, message, language); // Einstein Engines - Language // Goob edit end + + //Funky port start - if a channel is present but the user must whisper, force it to be a local whisper + if (channel != null && onlyWhisper) + channel = null; + + var message = TransformSpeech(source, FormattedMessage.RemoveMarkupOrThrow(originalMessage)); if (message.Length == 0) return; + //Funky port end // get the entity's name by visual identity (if no override provided). string nameIdentity = FormattedMessage.EscapeText(nameOverride ?? Identity.Name(source, EntityManager)); diff --git a/Content.Server/Damage/ForceSay/DamageForceSaySystem.cs b/Content.Server/Damage/ForceSay/DamageForceSaySystem.cs index ce453ec9453..558d5fc9fe0 100644 --- a/Content.Server/Damage/ForceSay/DamageForceSaySystem.cs +++ b/Content.Server/Damage/ForceSay/DamageForceSaySystem.cs @@ -5,6 +5,10 @@ // SPDX-FileCopyrightText: 2024 Tayrtahn // SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com> // SPDX-FileCopyrightText: 2025 Coolsurf6 +// SPDX-FileCopyrightText: 2025 Tay +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 slarticodefast <161409025+slarticodefast@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 taydeo // // SPDX-License-Identifier: AGPL-3.0-or-later @@ -131,7 +135,7 @@ private void OnDamageChanged(EntityUid uid, DamageForceSayComponent component, D private void OnMobStateChanged(EntityUid uid, DamageForceSayComponent component, MobStateChangedEvent args) { - if (args is not { OldMobState: MobState.Alive, NewMobState: MobState.Critical or MobState.Dead }) + if (args is not { OldMobState: MobState.Alive, NewMobState: MobState.Critical or MobState.SoftCritical or MobState.HardCritical or MobState.Dead }) return; // no suffix for the drama diff --git a/Content.Server/EntityEffects/EffectConditions/MobStateCondition.cs b/Content.Server/EntityEffects/EffectConditions/MobStateCondition.cs index 2195d00d89d..c3f6298ea42 100644 --- a/Content.Server/EntityEffects/EffectConditions/MobStateCondition.cs +++ b/Content.Server/EntityEffects/EffectConditions/MobStateCondition.cs @@ -1,5 +1,7 @@ // SPDX-FileCopyrightText: 2024 SlamBamActionman <83650252+SlamBamActionman@users.noreply.github.com> // SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 taydeo // // SPDX-License-Identifier: AGPL-3.0-or-later @@ -21,6 +23,12 @@ public override bool Condition(EntityEffectBaseArgs args) { if (mobState.CurrentState == Mobstate) return true; + + if (Mobstate == MobState.Critical && + (mobState.CurrentState == MobState.SoftCritical || mobState.CurrentState == MobState.HardCritical)) + { + return true; + } } return false; diff --git a/Content.Server/Explosion/EntitySystems/TriggerSystem.cs b/Content.Server/Explosion/EntitySystems/TriggerSystem.cs index f657bf87591..18f71c7ac2e 100644 --- a/Content.Server/Explosion/EntitySystems/TriggerSystem.cs +++ b/Content.Server/Explosion/EntitySystems/TriggerSystem.cs @@ -66,6 +66,9 @@ // SPDX-FileCopyrightText: 2025 TemporalOroboros // SPDX-FileCopyrightText: 2025 TheBorzoiMustConsume <197824988+TheBorzoiMustConsume@users.noreply.github.com> // SPDX-FileCopyrightText: 2025 metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 JoulesBerg <104539820+JoulesBerg@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 Tay +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> // SPDX-FileCopyrightText: 2025 slarticodefast <161409025+slarticodefast@users.noreply.github.com> // // SPDX-License-Identifier: AGPL-3.0-or-later @@ -354,7 +357,7 @@ private void HandleRattleTrigger(EntityUid uid, RattleComponent component, Trigg return; // Sends a message to the radio channel specified by the implant - if (mobstate.CurrentState == MobState.Critical) + if (mobstate.CurrentState == MobState.Critical || mobstate.CurrentState == MobState.SoftCritical) _radioSystem.SendRadioMessage(uid, critMessage, _prototypeManager.Index(component.RadioChannel), uid); if (mobstate.CurrentState == MobState.Dead) _radioSystem.SendRadioMessage(uid, deathMessage, _prototypeManager.Index(component.RadioChannel), uid); diff --git a/Content.Server/Ghost/Roles/GhostRoleSystem.cs b/Content.Server/Ghost/Roles/GhostRoleSystem.cs index d41ccc3b964..bbd43b72a1c 100644 --- a/Content.Server/Ghost/Roles/GhostRoleSystem.cs +++ b/Content.Server/Ghost/Roles/GhostRoleSystem.cs @@ -38,6 +38,12 @@ // SPDX-FileCopyrightText: 2025 Aviu00 <93730715+Aviu00@users.noreply.github.com> // SPDX-FileCopyrightText: 2025 Errant <35878406+Errant-4@users.noreply.github.com> // SPDX-FileCopyrightText: 2025 gluesniffler <159397573+gluesniffler@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 Josh Hilsberg +// SPDX-FileCopyrightText: 2025 JoulesBerg <104539820+JoulesBerg@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 Tay +// SPDX-FileCopyrightText: 2025 V <97265903+formlessnameless@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 corresp0nd <46357632+corresp0nd@users.noreply.github.com> // SPDX-FileCopyrightText: 2025 slarticodefast <161409025+slarticodefast@users.noreply.github.com> // // SPDX-License-Identifier: AGPL-3.0-or-later @@ -149,6 +155,8 @@ private void OnMobStateChanged(Entity component break; } case MobState.Critical: + case MobState.SoftCritical: + case MobState.HardCritical: case MobState.Dead: UnregisterGhostRole((component, ghostRole)); break; diff --git a/Content.Server/Guardian/GuardianSystem.cs b/Content.Server/Guardian/GuardianSystem.cs index aa96e4100e5..a8b38eba626 100644 --- a/Content.Server/Guardian/GuardianSystem.cs +++ b/Content.Server/Guardian/GuardianSystem.cs @@ -34,6 +34,10 @@ // SPDX-FileCopyrightText: 2025 No Elka <125199100+NoElkaTheGod@users.noreply.github.com> // SPDX-FileCopyrightText: 2025 Tayrtahn // SPDX-FileCopyrightText: 2025 YoungThug +// SPDX-FileCopyrightText: 2025 Tay +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 pa.pecherskij +// SPDX-FileCopyrightText: 2025 taydeo // // SPDX-License-Identifier: AGPL-3.0-or-later @@ -312,7 +316,7 @@ private void OnHostStateChange(EntityUid uid, GuardianHostComponent component, M TryComp(component.HostedGuardian, out var guardianComp); - if (args.NewMobState == MobState.Critical) + if (args.NewMobState == MobState.Critical || args.NewMobState == MobState.SoftCritical) //Funky port - checks for soft crit { _popupSystem.PopupEntity(Loc.GetString("guardian-host-critical-warn"), component.HostedGuardian.Value, component.HostedGuardian.Value); if (guardianComp != null) diff --git a/Content.Server/KillTracking/KillTrackerComponent.cs b/Content.Server/KillTracking/KillTrackerComponent.cs index 9f41c60e8fe..747279de713 100644 --- a/Content.Server/KillTracking/KillTrackerComponent.cs +++ b/Content.Server/KillTracking/KillTrackerComponent.cs @@ -1,12 +1,15 @@ // SPDX-FileCopyrightText: 2023 Kara // SPDX-FileCopyrightText: 2023 Nemanja <98561806+EmoGarbage404@users.noreply.github.com> // SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 taydeo // // SPDX-License-Identifier: MIT using Content.Goobstation.Maths.FixedPoint; using Content.Shared.Mobs; using Robust.Shared.Network; +using Content.Shared.FixedPoint; namespace Content.Server.KillTracking; @@ -20,7 +23,12 @@ public sealed partial class KillTrackerComponent : Component /// The mobstate that registers as a "kill" /// [DataField("killState")] - public MobState KillState = MobState.Critical; + public List KillState = new() + { + MobState.Critical, + MobState.HardCritical, + MobState.Dead + }; /// /// A dictionary of sources and how much damage they've done to this entity over time. diff --git a/Content.Server/KillTracking/KillTrackingSystem.cs b/Content.Server/KillTracking/KillTrackingSystem.cs index 237dd779e0b..e2c701fd80c 100644 --- a/Content.Server/KillTracking/KillTrackingSystem.cs +++ b/Content.Server/KillTracking/KillTrackingSystem.cs @@ -3,6 +3,8 @@ // SPDX-FileCopyrightText: 2024 Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> // SPDX-FileCopyrightText: 2024 LordCarve <27449516+LordCarve@users.noreply.github.com> // SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 taydeo // // SPDX-License-Identifier: AGPL-3.0-or-later @@ -50,7 +52,7 @@ private void OnDamageChanged(EntityUid uid, KillTrackerComponent component, Dama private void OnMobStateChanged(EntityUid uid, KillTrackerComponent component, MobStateChangedEvent args) { - if (args.NewMobState != component.KillState || args.OldMobState >= args.NewMobState) + if (component.KillState.Contains(args.NewMobState)) return; // impulse is the entity that did the finishing blow. diff --git a/Content.Server/Mobs/DeathgaspSystem.cs b/Content.Server/Mobs/DeathgaspSystem.cs index 49991367315..55f159d26d0 100644 --- a/Content.Server/Mobs/DeathgaspSystem.cs +++ b/Content.Server/Mobs/DeathgaspSystem.cs @@ -5,6 +5,8 @@ // SPDX-FileCopyrightText: 2024 gluesniffler <159397573+gluesniffler@users.noreply.github.com> // SPDX-FileCopyrightText: 2024 keronshb <54602815+keronshb@users.noreply.github.com> // SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 taydeo // // SPDX-License-Identifier: AGPL-3.0-or-later @@ -30,7 +32,7 @@ private void OnMobStateChanged(EntityUid uid, DeathgaspComponent component, MobS { // don't deathgasp if they arent going straight from crit to dead if (component.NeedsCritical // Goobstation - && args.OldMobState != MobState.Critical + && args.OldMobState != MobState.HardCritical || args.NewMobState != MobState.Dead) return; @@ -52,4 +54,4 @@ public bool Deathgasp(EntityUid uid, DeathgaspComponent? component = null) return true; } -} \ No newline at end of file +} diff --git a/Content.Server/NPC/Systems/NPCSystem.cs b/Content.Server/NPC/Systems/NPCSystem.cs index c570b0a188c..33d464c773f 100644 --- a/Content.Server/NPC/Systems/NPCSystem.cs +++ b/Content.Server/NPC/Systems/NPCSystem.cs @@ -18,6 +18,8 @@ // SPDX-FileCopyrightText: 2024 faint <46868845+ficcialfaint@users.noreply.github.com> // SPDX-FileCopyrightText: 2024 metalgearsloth // SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 taydeo // // SPDX-License-Identifier: AGPL-3.0-or-later @@ -168,13 +170,15 @@ public void OnMobStateChange(EntityUid uid, HTNComponent component, MobStateChan switch (args.NewMobState) { case MobState.Alive: + case MobState.SoftCritical: WakeNPC(uid, component); break; case MobState.Critical: + case MobState.HardCritical: case MobState.Dead: SleepNPC(uid, component); break; } } } -} \ No newline at end of file +} diff --git a/Content.Server/Revenant/EntitySystems/EssenceSystem.cs b/Content.Server/Revenant/EntitySystems/EssenceSystem.cs index c285fca5516..61fc3914fb4 100644 --- a/Content.Server/Revenant/EntitySystems/EssenceSystem.cs +++ b/Content.Server/Revenant/EntitySystems/EssenceSystem.cs @@ -5,6 +5,8 @@ // SPDX-FileCopyrightText: 2023 Leon Friedrich <60421075+ElectroJr@users.noreply.github.com> // SPDX-FileCopyrightText: 2023 ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> // SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 taydeo // // SPDX-License-Identifier: MIT @@ -83,6 +85,8 @@ private void UpdateEssenceAmount(EntityUid uid, EssenceComponent component) component.EssenceAmount = _random.NextFloat(45f, 70f); break; case MobState.Critical: + case MobState.SoftCritical: + case MobState.HardCritical: component.EssenceAmount = _random.NextFloat(35f, 50f); break; case MobState.Dead: @@ -90,4 +94,4 @@ private void UpdateEssenceAmount(EntityUid uid, EssenceComponent component) break; } } -} \ No newline at end of file +} diff --git a/Content.Server/Vocalization/Systems/VocalizationSystem.cs b/Content.Server/Vocalization/Systems/VocalizationSystem.cs index 8801e057b7e..243cc80e315 100644 --- a/Content.Server/Vocalization/Systems/VocalizationSystem.cs +++ b/Content.Server/Vocalization/Systems/VocalizationSystem.cs @@ -1,3 +1,11 @@ +// SPDX-FileCopyrightText: 2025 88tv <131759102+88tv@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 8tv +// SPDX-FileCopyrightText: 2025 Crude Oil <124208219+CroilBird@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 Errant <35878406+Errant-4@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> +// +// SPDX-License-Identifier: MIT + using Content.Server.Chat.Systems; using Content.Server.Power.Components; using Content.Server.Vocalization.Components; @@ -83,7 +91,7 @@ private void Speak(Entity entity, string message) // default to local chat if no other system handles the event // first check if the entity can speak - if (!_actionBlocker.CanSpeak(entity)) + if (!_actionBlocker.CanSpeak(entity, out _)) return; // send the message diff --git a/Content.Server/_DV/Harpy/HarpySingerSystem.cs b/Content.Server/_DV/Harpy/HarpySingerSystem.cs index 4ed418b5e4c..ac82c8a7673 100644 --- a/Content.Server/_DV/Harpy/HarpySingerSystem.cs +++ b/Content.Server/_DV/Harpy/HarpySingerSystem.cs @@ -5,6 +5,9 @@ // SPDX-FileCopyrightText: 2025 Piras314 // SPDX-FileCopyrightText: 2025 deltanedas <39013340+deltanedas@users.noreply.github.com> // SPDX-FileCopyrightText: 2025 deltanedas <@deltanedas:kde.org> +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 corresp0nd <46357632+corresp0nd@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 taydeo // // SPDX-License-Identifier: AGPL-3.0-or-later @@ -147,7 +150,7 @@ private void OnInstrumentOpen(EntityUid uid, HarpySingerComponent component, Ope { // CanSpeak covers all reasons you can't talk, including being incapacitated // (crit/dead), asleep, or for any reason mute inclding glimmer or a mime's vow. - var canNotSpeak = !_blocker.CanSpeak(uid); + var canNotSpeak = !_blocker.CanSpeak(uid, out _); var zombified = TryComp(uid, out var _); var muzzled = _inventorySystem.TryGetSlotEntity(uid, "mask", out var maskUid) && TryComp(maskUid, out var accent) && diff --git a/Content.Shared/ActionBlocker/ActionBlockerSystem.cs b/Content.Shared/ActionBlocker/ActionBlockerSystem.cs index d3680456bbc..485f24e0d5c 100644 --- a/Content.Shared/ActionBlocker/ActionBlockerSystem.cs +++ b/Content.Shared/ActionBlocker/ActionBlockerSystem.cs @@ -62,6 +62,8 @@ // SPDX-FileCopyrightText: 2025 Piras314 // SPDX-FileCopyrightText: 2025 ScarKy0 <106310278+ScarKy0@users.noreply.github.com> // SPDX-FileCopyrightText: 2025 gluesniffler <159397573+gluesniffler@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 Tay +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> // SPDX-FileCopyrightText: 2025 slarticodefast <161409025+slarticodefast@users.noreply.github.com> // SPDX-FileCopyrightText: 2025 themias <89101928+themias@users.noreply.github.com> // @@ -228,12 +230,13 @@ public bool CanThrow(EntityUid user, EntityUid itemUid) return !itemEv.Cancelled; } - public bool CanSpeak(EntityUid uid) + public bool CanSpeak(EntityUid uid, out bool onlyWhisper) { // This one is used as broadcast var ev = new SpeakAttemptEvent(uid); RaiseLocalEvent(uid, ev, true); + onlyWhisper = ev.OnlyWhisper; return !ev.Cancelled; } @@ -337,4 +340,4 @@ public bool CanInstrumentInteract(EntityUid user, EntityUid used, EntityUid? tar } // Shitmed Change End - Starlight Abductors } -} \ No newline at end of file +} diff --git a/Content.Shared/Chat/TypingIndicator/SharedTypingIndicatorSystem.cs b/Content.Shared/Chat/TypingIndicator/SharedTypingIndicatorSystem.cs index 6393043f690..dcaa217f582 100644 --- a/Content.Shared/Chat/TypingIndicator/SharedTypingIndicatorSystem.cs +++ b/Content.Shared/Chat/TypingIndicator/SharedTypingIndicatorSystem.cs @@ -5,6 +5,14 @@ // SPDX-FileCopyrightText: 2024 beck-thompson <107373427+beck-thompson@users.noreply.github.com> // SPDX-FileCopyrightText: 2024 metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> // SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 88tv <131759102+88tv@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 Amethyst <52829582+jackel234@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 Tojo <32783144+Alecksohs@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 TrixxedHeart <46364955+TrixxedBit@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 lzk <124214523+lzk228@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 maelines +// SPDX-FileCopyrightText: 2025 taydeo // // SPDX-License-Identifier: AGPL-3.0-or-later @@ -83,7 +91,7 @@ private void OnTypingChanged(TypingChangedEvent ev, EntitySessionEventArgs args) } // check if this entity can speak or emote - if (!_actionBlocker.CanEmote(uid.Value) && !_actionBlocker.CanSpeak(uid.Value)) + if (!_actionBlocker.CanEmote(uid.Value) && !_actionBlocker.CanSpeak(uid.Value, out _)) { // nah, make sure that typing indicator is disabled SetTypingIndicatorState(uid.Value, TypingIndicatorState.None); @@ -100,4 +108,54 @@ private void SetTypingIndicatorState(EntityUid uid, TypingIndicatorState state, _appearance.SetData(uid, TypingIndicatorVisuals.State, state, appearance); } -} \ No newline at end of file + // FUNKYSTATION EDIT START + private void OnTypingTypeChanged(TypingChangedTypeEvent ev, EntitySessionEventArgs args) + { + var uid = args.SenderSession.AttachedEntity; + if (!Exists(uid)) + { + Log.Warning($"Client {args.SenderSession} sent TypingChangedTypeEvent without an attached entity."); + return; + } + + // check if this entity can speak or emote + if (!_actionBlocker.CanEmote(uid.Value) && !_actionBlocker.CanSpeak(uid.Value, out _)) + { + SetTypingIndicatorType(uid.Value, ChatSelectChannel.None, "default"); + return; + } + + string? overrideProto = ev.ChatType switch + { + ChatSelectChannel.LOOC => "outofcharacter", + ChatSelectChannel.Emotes => "emote", + _ => null, + }; + + if (overrideProto != null) + { + SetTypingIndicatorType(uid.Value, ev.ChatType, overrideProto); + } + else + { + // For normal chat, clear any existing overrides + SetTypingIndicatorType(uid.Value, ev.ChatType, null); + } + } + private void SetTypingIndicatorType(EntityUid uid, ChatSelectChannel chatType, string? overrideProto, AppearanceComponent? appearance = null) + { + if (!Resolve(uid, ref appearance, false)) + return; + + if (overrideProto != null) + { + _appearance.SetData(uid, TypingIndicatorVisuals.OverrideIndicatorPrototype, overrideProto, appearance); + } + else + { + _appearance.RemoveData(uid, TypingIndicatorVisuals.OverrideIndicatorPrototype, appearance); + } + _appearance.SetData(uid, TypingIndicatorVisuals.ChatType, chatType, appearance); + } + // FUNKYSTATION EDIT END +} diff --git a/Content.Shared/Cuffs/SharedCuffableSystem.cs b/Content.Shared/Cuffs/SharedCuffableSystem.cs index efa66e6bf42..b9bbd99e09d 100644 --- a/Content.Shared/Cuffs/SharedCuffableSystem.cs +++ b/Content.Shared/Cuffs/SharedCuffableSystem.cs @@ -104,6 +104,13 @@ // SPDX-FileCopyrightText: 2025 Piras314 // SPDX-FileCopyrightText: 2025 gluesniffler <159397573+gluesniffler@users.noreply.github.com> // SPDX-FileCopyrightText: 2025 gus +// SPDX-FileCopyrightText: 2025 JoulesBerg <104539820+JoulesBerg@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 Tay +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 ferynn <117872973+ferynn@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 ferynn +// SPDX-FileCopyrightText: 2025 pa.pecherskij +// SPDX-FileCopyrightText: 2025 taydeo // // SPDX-License-Identifier: AGPL-3.0-or-later @@ -130,6 +137,7 @@ using Content.Shared.Inventory.Events; using Content.Shared.Inventory.VirtualItem; using Content.Shared.Item; +using Content.Shared.Mobs.Systems; // Required for MobStateSystem using Content.Shared.Movement.Events; using Content.Shared.Movement.Pulling.Components; using Content.Shared.Movement.Pulling.Events; @@ -169,6 +177,7 @@ public abstract partial class SharedCuffableSystem : EntitySystem [Dependency] private readonly UseDelaySystem _delay = default!; [Dependency] private readonly SharedHulkSystem _hulk = default!; [Dependency] private readonly SharedCombatModeSystem _combatMode = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; // Added dependency public override void Initialize() { @@ -363,8 +372,14 @@ private void HandleStopPull(EntityUid uid, CuffableComponent component, AttemptS if (args.User == null || !Exists(args.User.Value)) return; - if (args.User.Value == uid && !component.CanStillInteract) - args.Cancelled = true; + if (args.User.Value == uid) + { + // If they are cuffed or in soft/hard critical, they cannot stop the pull + if (!component.CanStillInteract || _mobState.IsCritical(uid)) + { + args.Cancelled = true; + } + } } private void OnRemoveCuffsAlert(Entity ent, ref RemoveCuffsAlertEvent args) @@ -597,7 +612,7 @@ public bool TryAddNewCuffs(EntityUid target, EntityUid user, EntityUid handcuff, EnsureComp(handcuff, out var handcuffsComp); handcuffsComp.Used = true; Dirty(handcuff, handcuffsComp); - + var ev = new TargetHandcuffedEvent(); RaiseLocalEvent(target, ref ev); diff --git a/Content.Shared/Damage/Components/DamageableComponent.cs b/Content.Shared/Damage/Components/DamageableComponent.cs index 9cd8f39026d..0d3dab12f27 100644 --- a/Content.Shared/Damage/Components/DamageableComponent.cs +++ b/Content.Shared/Damage/Components/DamageableComponent.cs @@ -89,6 +89,10 @@ // SPDX-FileCopyrightText: 2025 gluesniffler // SPDX-FileCopyrightText: 2025 gus // SPDX-FileCopyrightText: 2025 keronshb <54602815+keronshb@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 Tay +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 slarticodefast <161409025+slarticodefast@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 taydeo // // SPDX-License-Identifier: AGPL-3.0-or-later @@ -171,6 +175,8 @@ public sealed partial class DamageableComponent : Component { { MobState.Alive, "HealthIconFine" }, { MobState.Critical, "HealthIconCritical" }, + { MobState.SoftCritical, "HealthIconCritical" }, + { MobState.HardCritical, "HealthIconCritical" }, { MobState.Dead, "HealthIconDead" }, }; diff --git a/Content.Shared/Mobs/Components/MobStateComponent.cs b/Content.Shared/Mobs/Components/MobStateComponent.cs index a78a5a5e69c..86877896aa1 100644 --- a/Content.Shared/Mobs/Components/MobStateComponent.cs +++ b/Content.Shared/Mobs/Components/MobStateComponent.cs @@ -6,6 +6,8 @@ // SPDX-FileCopyrightText: 2024 Piras314 // SPDX-FileCopyrightText: 2024 metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> // SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 taydeo // // SPDX-License-Identifier: AGPL-3.0-or-later @@ -36,8 +38,8 @@ public sealed partial class MobStateComponent : Component public HashSet AllowedStates = new() { MobState.Alive, - MobState.Critical, + MobState.HardCritical, MobState.Dead }; } -} \ No newline at end of file +} diff --git a/Content.Shared/Mobs/Components/MobThresholdsComponent.cs b/Content.Shared/Mobs/Components/MobThresholdsComponent.cs index 10aefaf1562..5fcd5baf3c1 100644 --- a/Content.Shared/Mobs/Components/MobThresholdsComponent.cs +++ b/Content.Shared/Mobs/Components/MobThresholdsComponent.cs @@ -9,6 +9,8 @@ // SPDX-FileCopyrightText: 2025 GoobBot // SPDX-FileCopyrightText: 2025 Roudenn // SPDX-FileCopyrightText: 2025 gus +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 taydeo // // SPDX-License-Identifier: AGPL-3.0-or-later @@ -43,6 +45,8 @@ public sealed partial class MobThresholdsComponent : Component { {MobState.Alive, "HumanHealth"}, {MobState.Critical, "HumanCrit"}, + {MobState.SoftCritical, "HumanCrit"}, + {MobState.HardCritical, "HumanCrit"}, {MobState.Dead, "HumanDead"}, }; diff --git a/Content.Shared/Mobs/MobState.cs b/Content.Shared/Mobs/MobState.cs index 354257cc5ce..48d276e188f 100644 --- a/Content.Shared/Mobs/MobState.cs +++ b/Content.Shared/Mobs/MobState.cs @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: 2023 DrSmugleaf // SPDX-FileCopyrightText: 2023 Jezithyr // SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 taydeo // // SPDX-License-Identifier: MIT @@ -22,7 +24,9 @@ public enum MobState : byte Invalid = 0, Alive = 1, Critical = 2, - Dead = 3 + SoftCritical = 3, + HardCritical = 4, + Dead = 5 } /// @@ -46,4 +50,4 @@ public static class A public enum MobStateVisuals : byte { State -} \ No newline at end of file +} diff --git a/Content.Shared/Mobs/Systems/MobStateSystem.StateMachine.cs b/Content.Shared/Mobs/Systems/MobStateSystem.StateMachine.cs index 4c2268e8f73..e3837f71fde 100644 --- a/Content.Shared/Mobs/Systems/MobStateSystem.StateMachine.cs +++ b/Content.Shared/Mobs/Systems/MobStateSystem.StateMachine.cs @@ -13,6 +13,11 @@ // SPDX-FileCopyrightText: 2025 Trest <144359854+trest100@users.noreply.github.com> // SPDX-FileCopyrightText: 2025 Roudenn // SPDX-FileCopyrightText: 2025 Kayzel <43700376+KayzelW@users.noreply.github.com> +// SPDX-FileCopyrightText: 2024 Tadeo +// SPDX-FileCopyrightText: 2025 Tay +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 pa.pecherskij +// SPDX-FileCopyrightText: 2025 taydeo // // SPDX-License-Identifier: AGPL-3.0-or-later @@ -121,11 +126,31 @@ private void ChangeState(EntityUid target, MobStateComponent component, MobState { var oldState = component.CurrentState; //make sure we are allowed to enter the new state - if (oldState == newState || !component.AllowedStates.Contains(newState)) + if (oldState == newState) return; - if (oldState == MobState.Dead && HasComp(target)) // Shitmed Change - return; + if (!component.AllowedStates.Contains(newState)) + { + if (newState != MobState.Critical) + return; + + if (!component.AllowedStates.Contains(MobState.SoftCritical) || !component.AllowedStates.Contains(MobState.HardCritical)) + return; + + switch (oldState) + { + case MobState.Alive: + { + newState = MobState.SoftCritical; + break; + } + case MobState.Dead: + { + newState = MobState.HardCritical; + break; + } + } + } OnExitState(target, component, oldState); component.CurrentState = newState; diff --git a/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs b/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs index abf0b9cb4b7..ac814291322 100644 --- a/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs +++ b/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs @@ -83,6 +83,13 @@ // SPDX-FileCopyrightText: 2024 voidnull000 <18663194+voidnull000@users.noreply.github.com> // SPDX-FileCopyrightText: 2024 Арт <123451459+JustArt1m@users.noreply.github.com> // SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 Ilya Mikheev +// SPDX-FileCopyrightText: 2025 Tay +// SPDX-FileCopyrightText: 2025 Tyranex +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 ilyamikcoder +// SPDX-FileCopyrightText: 2025 pa.pecherskij +// SPDX-FileCopyrightText: 2025 taydeo // // SPDX-License-Identifier: AGPL-3.0-or-later @@ -99,6 +106,7 @@ using Content.Shared.Item; using Content.Shared.Mobs.Components; using Content.Shared.Movement.Events; +using Content.Shared.Movement.Systems; using Content.Shared.Pointing; using Content.Shared.Pulling.Events; using Content.Shared.Speech; @@ -133,6 +141,7 @@ private void SubscribeEvents() SubscribeLocalEvent(OnCombatModeShouldHandInteract); SubscribeLocalEvent(OnAttemptPacifiedAttack); SubscribeLocalEvent(OnDamageModify); + SubscribeLocalEvent(OnRefreshMovespeed); SubscribeLocalEvent(OnUnbuckleAttempt); } @@ -151,6 +160,8 @@ private void CheckConcious(Entity ent, ref ConsciousAttemptEv { case MobState.Dead: case MobState.Critical: + case MobState.SoftCritical: + case MobState.HardCritical: args.Cancelled = true; break; } @@ -165,10 +176,17 @@ private void OnStateExitSubscribers(EntityUid target, MobStateComponent componen break; case MobState.Critical: _standing.Stand(target); + case MobState.SoftCritical: //Funky port + var forceStand = false; + if (TryComp(target, out var tag)) + forceStand = _tag.HasTag(tag, ForceStandOnReviveTag); + + _standing.Stand(target, force: forceStand); break; + case MobState.HardCritical: + break; //Funky port End case MobState.Dead: RemComp(target); - _standing.Stand(target); break; case MobState.Invalid: //unused @@ -194,6 +212,8 @@ private void OnStateEnteredSubscribers(EntityUid target, MobStateComponent compo _appearance.SetData(target, MobStateVisuals.State, MobState.Alive); break; case MobState.Critical: + case MobState.SoftCritical: + case MobState.HardCritical: _standing.Down(target); RaiseLocalEvent(target, ref ev); // Goobstation _appearance.SetData(target, MobStateVisuals.State, MobState.Critical); @@ -214,6 +234,15 @@ private void OnStateEnteredSubscribers(EntityUid target, MobStateComponent compo #region Event Subscribers + private void OnRefreshMovespeed(EntityUid uid, MobStateComponent component, RefreshMovementSpeedModifiersEvent args) + { + if (component.CurrentState == MobState.SoftCritical) + { + // apply a 0.4x multiplier (60% slowdown) when in soft crit + args.ModifySpeed(0.4f, 0.4f); + } + } + private void OnSleepAttempt(EntityUid target, MobStateComponent component, ref TryingToSleepEvent args) { if (IsDead(target, component)) @@ -237,6 +266,9 @@ private void OnSpeakAttempt(EntityUid uid, MobStateComponent component, SpeakAtt return; } + if (component.CurrentState == MobState.SoftCritical) + args.OnlyWhisper = true; + CheckAct(uid, component, args); } @@ -246,6 +278,7 @@ private void CheckAct(EntityUid target, MobStateComponent component, Cancellable { case MobState.Dead: case MobState.Critical: + case MobState.HardCritical: args.Cancel(); break; } diff --git a/Content.Shared/Mobs/Systems/MobStateSystem.cs b/Content.Shared/Mobs/Systems/MobStateSystem.cs index f767bac87c6..6441444d561 100644 --- a/Content.Shared/Mobs/Systems/MobStateSystem.cs +++ b/Content.Shared/Mobs/Systems/MobStateSystem.cs @@ -14,6 +14,11 @@ // SPDX-FileCopyrightText: 2025 Trest <144359854+trest100@users.noreply.github.com> // SPDX-FileCopyrightText: 2025 Roudenn // SPDX-FileCopyrightText: 2025 Kayzel <43700376+KayzelW@users.noreply.github.com> +// SPDX-FileCopyrightText: 2024 Tadeo +// SPDX-FileCopyrightText: 2025 Tay +// SPDX-FileCopyrightText: 2025 YaraaraY <158123176+YaraaraY@users.noreply.github.com> +// SPDX-FileCopyrightText: 2025 pa.pecherskij +// SPDX-FileCopyrightText: 2025 taydeo // // SPDX-License-Identifier: AGPL-3.0-or-later @@ -75,7 +80,7 @@ public bool IsCritical(EntityUid target, MobStateComponent? component = null) { if (!_mobStateQuery.Resolve(target, ref component, false)) return false; - return component.CurrentState == MobState.Critical; + return component.CurrentState == MobState.Critical || component.CurrentState == MobState.SoftCritical || component.CurrentState == MobState.HardCritical; } /// @@ -101,7 +106,14 @@ public bool IsIncapacitated(EntityUid target, MobStateComponent? component = nul { if (!_mobStateQuery.Resolve(target, ref component, false)) return false; - return component.CurrentState is MobState.Critical or MobState.Dead; + return component.CurrentState is MobState.Critical or MobState.SoftCritical or MobState.HardCritical or MobState.Dead; + } + + public bool IsImmobile(EntityUid target, MobStateComponent? component = null) + { + if (!_mobStateQuery.Resolve(target, ref component, false)) + return false; + return component.CurrentState is MobState.Critical or MobState.HardCritical or MobState.Dead; } /// @@ -118,4 +130,4 @@ public bool IsInvalidState(EntityUid target, MobStateComponent? component = null } #endregion -} \ No newline at end of file +} diff --git a/Content.Shared/Mobs/Systems/MobThresholdSystem.cs b/Content.Shared/Mobs/Systems/MobThresholdSystem.cs index 0db4aeaa177..c54da16cd86 100644 --- a/Content.Shared/Mobs/Systems/MobThresholdSystem.cs +++ b/Content.Shared/Mobs/Systems/MobThresholdSystem.cs @@ -164,12 +164,27 @@ public bool TryGetThresholdForState(EntityUid target, MobState mobState, if (!Resolve(target, ref thresholdComponent, false)) // Goobstation return false; - foreach (var pair in thresholdComponent.Thresholds) + if (mobState == MobState.Critical && !thresholdComponent.Thresholds.ContainsValue(mobState) && + thresholdComponent.Thresholds.ContainsValue(MobState.SoftCritical) && thresholdComponent.Thresholds.ContainsValue(MobState.HardCritical)) { - if (pair.Value == mobState) + threshold = 0; + foreach (var pair in thresholdComponent.Thresholds) { - threshold = pair.Key; - return true; + if (pair.Value == MobState.SoftCritical || pair.Value == MobState.HardCritical) + threshold = threshold + pair.Key; + } + + return true; + } + else + { + foreach (var pair in thresholdComponent.Thresholds) + { + if (pair.Value == mobState) + { + threshold = pair.Key; + return true; + } } } diff --git a/Content.Shared/Movement/Pulling/Systems/PullingSystem.cs b/Content.Shared/Movement/Pulling/Systems/PullingSystem.cs index 0e25cad393b..f1f7bc146f1 100644 --- a/Content.Shared/Movement/Pulling/Systems/PullingSystem.cs +++ b/Content.Shared/Movement/Pulling/Systems/PullingSystem.cs @@ -318,7 +318,7 @@ private void OnStateChanged(EntityUid uid, PullerComponent component, ref Update if (component.Pulling == null) return; - if (TryComp(component.Pulling, out var comp) && (args.State == MobState.Critical || args.State == MobState.Dead)) + if (TryComp(component.Pulling, out var comp) && (args.State == MobState.Critical || args.State == MobState.HardCritical || args.State == MobState.Dead)) { TryStopPull(component.Pulling.Value, comp); } diff --git a/Content.Shared/Movement/Systems/SharedMoverController.cs b/Content.Shared/Movement/Systems/SharedMoverController.cs index 38198185fe7..c19f2ef753e 100644 --- a/Content.Shared/Movement/Systems/SharedMoverController.cs +++ b/Content.Shared/Movement/Systems/SharedMoverController.cs @@ -259,8 +259,12 @@ protected void HandleMobMovement( LerpRotation(uid, mover, frameTime); var dirtied = false; + if (_mobState.IsImmobile(relayTarget.Source) || //Funky port + TryComp(relayTarget.Source, out _) || + !MoverQuery.TryGetComponent(relayTarget.Source, out var relayedMover)) + { //Funky port end + if (relayTargetMover.RelativeEntity != mover.RelativeEntity) - { relayTargetMover.RelativeEntity = mover.RelativeEntity; dirtied = true; } diff --git a/Content.Shared/Silicons/Bots/MedibotSystem.cs b/Content.Shared/Silicons/Bots/MedibotSystem.cs index 3bbfd02c8d0..77d04684632 100644 --- a/Content.Shared/Silicons/Bots/MedibotSystem.cs +++ b/Content.Shared/Silicons/Bots/MedibotSystem.cs @@ -112,7 +112,8 @@ public bool CheckInjectable(Entity medibot, EntityUid target, if (!TryComp(target, out var damageable)) return false; if (!_solutionContainer.TryGetInjectableSolution(target, out _, out _)) return false; - if (mobState.CurrentState != MobState.Alive && mobState.CurrentState != MobState.Critical) + if (mobState.CurrentState != MobState.Alive && + (mobState.CurrentState != MobState.Critical || mobState.CurrentState != MobState.SoftCritical || mobState.CurrentState != MobState.HardCritical)) { _popup.PopupClient(Loc.GetString("medibot-target-dead"), medibot, medibot); return false; diff --git a/Content.Shared/Speech/SpeakAttemptEvent.cs b/Content.Shared/Speech/SpeakAttemptEvent.cs index 332f5dacaab..4605c7187bf 100644 --- a/Content.Shared/Speech/SpeakAttemptEvent.cs +++ b/Content.Shared/Speech/SpeakAttemptEvent.cs @@ -16,5 +16,6 @@ public SpeakAttemptEvent(EntityUid uid) } public EntityUid Uid { get; } + public bool OnlyWhisper = false; } } \ No newline at end of file diff --git a/Content.Shared/Stunnable/SharedStunSystem.cs b/Content.Shared/Stunnable/SharedStunSystem.cs index 576531f8edc..ce5a37fa624 100644 --- a/Content.Shared/Stunnable/SharedStunSystem.cs +++ b/Content.Shared/Stunnable/SharedStunSystem.cs @@ -169,14 +169,12 @@ private void OnMobStateChanged(EntityUid uid, MobStateComponent component, MobSt switch (args.NewMobState) { case MobState.Alive: + case MobState.SoftCritical: { break; } case MobState.Critical: - { - _statusEffect.TryRemoveStatusEffect(uid, "Stun"); - break; - } + case MobState.HardCritical: case MobState.Dead: { _statusEffect.TryRemoveStatusEffect(uid, "Stun"); diff --git a/Resources/Prototypes/Entities/Mobs/Species/base.yml b/Resources/Prototypes/Entities/Mobs/Species/base.yml index 14912a43aca..9c95c62208a 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/base.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/base.yml @@ -486,6 +486,18 @@ - type: MobPrice price: 1500 # Kidnapping a living person and selling them for cred is a good move. deathPenalty: 0.01 # However they really ought to be living and intact, otherwise they're worth 100x less. + - type: MobThresholds + thresholds: + 0: Alive + 100: SoftCritical + 150: HardCritical + 200: Dead + - type: MobState + allowedStates: + - Alive + - SoftCritical + - HardCritical + - Dead - type: Tag tags: - CanPilot From 3f435df52e31da0caac8cd2a7cf642e25ec93b69 Mon Sep 17 00:00:00 2001 From: harryhulse12-alt Date: Sat, 24 Jan 2026 11:52:03 +0000 Subject: [PATCH 10/16] Devoursystemchange --- Content.Shared/Devour/DevourSystem.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Content.Shared/Devour/DevourSystem.cs b/Content.Shared/Devour/DevourSystem.cs index f43320d7126..a634f5194c2 100644 --- a/Content.Shared/Devour/DevourSystem.cs +++ b/Content.Shared/Devour/DevourSystem.cs @@ -73,6 +73,8 @@ private void OnDevourAction(Entity ent, ref DevourActionEvent switch (targetState.CurrentState) { case MobState.Critical: + case MobState.SoftCritical: + case MobState.HardCritical: case MobState.Dead: _doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, ent.Owner, ent.Comp.DevourTime, new DevourDoAfterEvent(), ent.Owner, target: target, used: ent.Owner) From 7526018af524c6a877cdc3058f15d7ed0838c660 Mon Sep 17 00:00:00 2001 From: harryhulse12-alt Date: Sat, 24 Jan 2026 11:56:43 +0000 Subject: [PATCH 11/16] removedtypingtypechanged --- .../SharedTypingIndicatorSystem.cs | 33 ------------------- 1 file changed, 33 deletions(-) diff --git a/Content.Shared/Chat/TypingIndicator/SharedTypingIndicatorSystem.cs b/Content.Shared/Chat/TypingIndicator/SharedTypingIndicatorSystem.cs index dcaa217f582..562c988d37b 100644 --- a/Content.Shared/Chat/TypingIndicator/SharedTypingIndicatorSystem.cs +++ b/Content.Shared/Chat/TypingIndicator/SharedTypingIndicatorSystem.cs @@ -109,39 +109,6 @@ private void SetTypingIndicatorState(EntityUid uid, TypingIndicatorState state, _appearance.SetData(uid, TypingIndicatorVisuals.State, state, appearance); } // FUNKYSTATION EDIT START - private void OnTypingTypeChanged(TypingChangedTypeEvent ev, EntitySessionEventArgs args) - { - var uid = args.SenderSession.AttachedEntity; - if (!Exists(uid)) - { - Log.Warning($"Client {args.SenderSession} sent TypingChangedTypeEvent without an attached entity."); - return; - } - - // check if this entity can speak or emote - if (!_actionBlocker.CanEmote(uid.Value) && !_actionBlocker.CanSpeak(uid.Value, out _)) - { - SetTypingIndicatorType(uid.Value, ChatSelectChannel.None, "default"); - return; - } - - string? overrideProto = ev.ChatType switch - { - ChatSelectChannel.LOOC => "outofcharacter", - ChatSelectChannel.Emotes => "emote", - _ => null, - }; - - if (overrideProto != null) - { - SetTypingIndicatorType(uid.Value, ev.ChatType, overrideProto); - } - else - { - // For normal chat, clear any existing overrides - SetTypingIndicatorType(uid.Value, ev.ChatType, null); - } - } private void SetTypingIndicatorType(EntityUid uid, ChatSelectChannel chatType, string? overrideProto, AppearanceComponent? appearance = null) { if (!Resolve(uid, ref appearance, false)) From b7a5ae5d8437a8807e815321bf601e13b58cef38 Mon Sep 17 00:00:00 2001 From: harryhulse12-alt Date: Sat, 24 Jan 2026 12:04:06 +0000 Subject: [PATCH 12/16] movercontroller and mobstatesystem --- .../Mobs/Systems/MobStateSystem.Subscribers.cs | 9 +++++---- Content.Shared/Movement/Systems/SharedMoverController.cs | 7 ++++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs b/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs index ac814291322..f38db6fe497 100644 --- a/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs +++ b/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs @@ -176,12 +176,13 @@ private void OnStateExitSubscribers(EntityUid target, MobStateComponent componen break; case MobState.Critical: _standing.Stand(target); + break; case MobState.SoftCritical: //Funky port - var forceStand = false; - if (TryComp(target, out var tag)) - forceStand = _tag.HasTag(tag, ForceStandOnReviveTag); + // var forceStand = false; + // if (TryComp(target, out var tag)) + // forceStand = _tag.HasTag(tag, ForceStandOnReviveTag); - _standing.Stand(target, force: forceStand); + // _standing.Stand(target, force: forceStand); break; case MobState.HardCritical: break; //Funky port End diff --git a/Content.Shared/Movement/Systems/SharedMoverController.cs b/Content.Shared/Movement/Systems/SharedMoverController.cs index c19f2ef753e..e8312c65290 100644 --- a/Content.Shared/Movement/Systems/SharedMoverController.cs +++ b/Content.Shared/Movement/Systems/SharedMoverController.cs @@ -138,6 +138,7 @@ using Content.Shared._vg.TileMovement; using Content.Shared.Standing; // Goobstation - kil mofs using PullableComponent = Content.Shared.Movement.Pulling.Components.PullableComponent; +using Content.Shared.Bed.Sleep;; namespace Content.Shared.Movement.Systems; @@ -259,9 +260,9 @@ protected void HandleMobMovement( LerpRotation(uid, mover, frameTime); var dirtied = false; - if (_mobState.IsImmobile(relayTarget.Source) || //Funky port - TryComp(relayTarget.Source, out _) || - !MoverQuery.TryGetComponent(relayTarget.Source, out var relayedMover)) + if (_mobState.IsImmobile(mover.Source) || //Funky port + TryComp(mover.Source, out _) || + !MoverQuery.TryGetComponent(mover.Source, out var relayedMover)) { //Funky port end if (relayTargetMover.RelativeEntity != mover.RelativeEntity) From dd07a9eea3d34871944ff5d0b8ea31cae8fb56ea Mon Sep 17 00:00:00 2001 From: harryhulse12-alt Date: Sat, 24 Jan 2026 20:31:28 +0000 Subject: [PATCH 13/16] sharedtyping+mover --- .../SharedTypingIndicatorSystem.cs | 17 ----------------- .../Movement/Systems/SharedMoverController.cs | 8 ++------ 2 files changed, 2 insertions(+), 23 deletions(-) diff --git a/Content.Shared/Chat/TypingIndicator/SharedTypingIndicatorSystem.cs b/Content.Shared/Chat/TypingIndicator/SharedTypingIndicatorSystem.cs index 562c988d37b..d225770dee7 100644 --- a/Content.Shared/Chat/TypingIndicator/SharedTypingIndicatorSystem.cs +++ b/Content.Shared/Chat/TypingIndicator/SharedTypingIndicatorSystem.cs @@ -108,21 +108,4 @@ private void SetTypingIndicatorState(EntityUid uid, TypingIndicatorState state, _appearance.SetData(uid, TypingIndicatorVisuals.State, state, appearance); } - // FUNKYSTATION EDIT START - private void SetTypingIndicatorType(EntityUid uid, ChatSelectChannel chatType, string? overrideProto, AppearanceComponent? appearance = null) - { - if (!Resolve(uid, ref appearance, false)) - return; - - if (overrideProto != null) - { - _appearance.SetData(uid, TypingIndicatorVisuals.OverrideIndicatorPrototype, overrideProto, appearance); - } - else - { - _appearance.RemoveData(uid, TypingIndicatorVisuals.OverrideIndicatorPrototype, appearance); - } - _appearance.SetData(uid, TypingIndicatorVisuals.ChatType, chatType, appearance); - } - // FUNKYSTATION EDIT END } diff --git a/Content.Shared/Movement/Systems/SharedMoverController.cs b/Content.Shared/Movement/Systems/SharedMoverController.cs index e8312c65290..82ad73e53e7 100644 --- a/Content.Shared/Movement/Systems/SharedMoverController.cs +++ b/Content.Shared/Movement/Systems/SharedMoverController.cs @@ -138,7 +138,7 @@ using Content.Shared._vg.TileMovement; using Content.Shared.Standing; // Goobstation - kil mofs using PullableComponent = Content.Shared.Movement.Pulling.Components.PullableComponent; -using Content.Shared.Bed.Sleep;; +using Content.Shared.Bed.Sleep; namespace Content.Shared.Movement.Systems; @@ -260,12 +260,8 @@ protected void HandleMobMovement( LerpRotation(uid, mover, frameTime); var dirtied = false; - if (_mobState.IsImmobile(mover.Source) || //Funky port - TryComp(mover.Source, out _) || - !MoverQuery.TryGetComponent(mover.Source, out var relayedMover)) - { //Funky port end - if (relayTargetMover.RelativeEntity != mover.RelativeEntity) + { relayTargetMover.RelativeEntity = mover.RelativeEntity; dirtied = true; } From 11d50fd28526f0bfb02602c6e6419b8846c63e46 Mon Sep 17 00:00:00 2001 From: harryhulse12-alt Date: Sat, 24 Jan 2026 21:06:12 +0000 Subject: [PATCH 14/16] it works --- .../Overlays/EntityHealthBarOverlay.cs | 18 +++++++++++------- Content.Server/Chat/Systems/ChatSystem.cs | 2 +- .../KillTracking/KillTrackerComponent.cs | 1 - .../Actions/ChatMessageAction.cs | 2 +- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Content.Client/Overlays/EntityHealthBarOverlay.cs b/Content.Client/Overlays/EntityHealthBarOverlay.cs index c4a5d8f2d90..10e69d1c5cf 100644 --- a/Content.Client/Overlays/EntityHealthBarOverlay.cs +++ b/Content.Client/Overlays/EntityHealthBarOverlay.cs @@ -220,31 +220,35 @@ protected override void Draw(in OverlayDrawArgs args) /// Returns a ratio between 0 and 1, and whether the entity is in crit. /// private (float ratio, bool inCrit)? CalcProgress(EntityUid uid, MobStateComponent component, DamageableComponent dmg, MobThresholdsComponent thresholds) - { +{ var totalDamage = _mobThresholdSystem.CheckVitalDamage(uid, dmg); // GoobStation if (_mobStateSystem.IsAlive(uid, component)) { if (dmg.HealthBarThreshold != null && totalDamage < dmg.HealthBarThreshold) // GoobStation return null; - if (firstCritThreshold == 0) - return (1f, false); + if (!_mobThresholdSystem.TryGetThresholdForState(uid, MobState.Critical, out var threshold, thresholds) && + !_mobThresholdSystem.TryGetThresholdForState(uid, MobState.Dead, out threshold, thresholds)) + return (1, false); var ratio = 1 - ((FixedPoint2)(totalDamage / threshold)).Float(); // GoobStation return (ratio, false); } - if (_mobStateSystem.IsIncapacitated(uid, component) && !_mobStateSystem.IsDead(uid, component)) + if (_mobStateSystem.IsCritical(uid, component)) { - if (deadThreshold <= firstCritThreshold) - return (0f, true); + if (!_mobThresholdSystem.TryGetThresholdForState(uid, MobState.Critical, out var critThreshold, thresholds) || + !_mobThresholdSystem.TryGetThresholdForState(uid, MobState.Dead, out var deadThreshold, thresholds)) + { + return (1, true); + } var ratio = 1 - ((totalDamage - critThreshold) / (deadThreshold - critThreshold)).Value.Float(); // GoobStation return (ratio, true); } - return (0f, true); + return (0, true); } public Color GetProgressColor(float progress, bool crit) diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index a52c33da4bb..25d1aca88bf 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -812,7 +812,7 @@ private void SendEntityWhisper( if (channel != null && onlyWhisper) channel = null; - var message = TransformSpeech(source, FormattedMessage.RemoveMarkupOrThrow(originalMessage)); + message = TransformSpeech(source, FormattedMessage.RemoveMarkupOrThrow(originalMessage), language); if (message.Length == 0) return; //Funky port end diff --git a/Content.Server/KillTracking/KillTrackerComponent.cs b/Content.Server/KillTracking/KillTrackerComponent.cs index 747279de713..1209df4dfbb 100644 --- a/Content.Server/KillTracking/KillTrackerComponent.cs +++ b/Content.Server/KillTracking/KillTrackerComponent.cs @@ -9,7 +9,6 @@ using Content.Goobstation.Maths.FixedPoint; using Content.Shared.Mobs; using Robust.Shared.Network; -using Content.Shared.FixedPoint; namespace Content.Server.KillTracking; diff --git a/Content.Shared/_EinsteinEngines/InteractionVerbs/Actions/ChatMessageAction.cs b/Content.Shared/_EinsteinEngines/InteractionVerbs/Actions/ChatMessageAction.cs index 467a19675e1..881d56ad06c 100644 --- a/Content.Shared/_EinsteinEngines/InteractionVerbs/Actions/ChatMessageAction.cs +++ b/Content.Shared/_EinsteinEngines/InteractionVerbs/Actions/ChatMessageAction.cs @@ -44,7 +44,7 @@ public sealed partial class ChatMessageAction : InteractionAction public override bool CanPerform(InteractionArgs args, InteractionVerbPrototype proto, bool beforeDelay, VerbDependencies deps) { - return deps.EntMan.System().CanSpeak(GetSpeaker(args)); + return deps.EntMan.System().CanSpeak(GetSpeaker(args), out _); } public override bool Perform(InteractionArgs args, InteractionVerbPrototype proto, VerbDependencies deps) From 3e6bc3497ce4c885eb02138319db1db8dcefbdb7 Mon Sep 17 00:00:00 2001 From: harryhulse12-alt Date: Sat, 31 Jan 2026 14:20:30 +0000 Subject: [PATCH 15/16] maybefix? --- Content.Client/Overlays/EntityHealthBarOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Client/Overlays/EntityHealthBarOverlay.cs b/Content.Client/Overlays/EntityHealthBarOverlay.cs index 10e69d1c5cf..624c7176097 100644 --- a/Content.Client/Overlays/EntityHealthBarOverlay.cs +++ b/Content.Client/Overlays/EntityHealthBarOverlay.cs @@ -254,7 +254,7 @@ protected override void Draw(in OverlayDrawArgs args) public Color GetProgressColor(float progress, bool crit) { if (crit) - return Red; + progress = 0; return _progressColor.GetProgressColor(progress); } From 63c2270e0aa65de52d4201e71394d41670374147 Mon Sep 17 00:00:00 2001 From: harryhulse12-alt Date: Sat, 31 Jan 2026 14:53:04 +0000 Subject: [PATCH 16/16] try2 --- Content.Client/Overlays/EntityHealthBarOverlay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content.Client/Overlays/EntityHealthBarOverlay.cs b/Content.Client/Overlays/EntityHealthBarOverlay.cs index 624c7176097..02c9408d701 100644 --- a/Content.Client/Overlays/EntityHealthBarOverlay.cs +++ b/Content.Client/Overlays/EntityHealthBarOverlay.cs @@ -237,7 +237,7 @@ protected override void Draw(in OverlayDrawArgs args) if (_mobStateSystem.IsCritical(uid, component)) { - if (!_mobThresholdSystem.TryGetThresholdForState(uid, MobState.Critical, out var critThreshold, thresholds) || + if (!_mobThresholdSystem.TryGetThresholdForState(uid, MobState.SoftCritical, out var critThreshold, thresholds) || !_mobThresholdSystem.TryGetThresholdForState(uid, MobState.Dead, out var deadThreshold, thresholds)) { return (1, true);