diff --git a/Content.Shared/Traits/Assorted/ImpairedMobilityComponent.cs b/Content.Shared/Traits/Assorted/ImpairedMobilityComponent.cs
new file mode 100644
index 0000000000..50f7281ff8
--- /dev/null
+++ b/Content.Shared/Traits/Assorted/ImpairedMobilityComponent.cs
@@ -0,0 +1,25 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Traits.Assorted;
+
+///
+/// Used for the Impaired Mobility disability trait.
+/// Applies a base movement speed reduction as determined by the SpeedModifier field.
+/// Also increases the time it takes to stand up after falling, as determined by the StandUpTimeModifier field.
+/// When an entity holds an item with the MobilityAidComponent, the speed penalty is nullified.
+///
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+public sealed partial class ImpairedMobilityComponent : Component
+{
+ ///
+ /// The movement speed modifier applied to the player (0.4 is 40% slower)
+ ///
+ [DataField, AutoNetworkedField]
+ public float SpeedModifier = 0.4f;
+
+ ///
+ /// The doAfter modifier when getting up after falling (1.4 is 40% slower)
+ ///
+ [DataField, AutoNetworkedField]
+ public float StandUpTimeModifier = 1.4f;
+}
diff --git a/Content.Shared/Traits/Assorted/ImpairedMobilitySystem.cs b/Content.Shared/Traits/Assorted/ImpairedMobilitySystem.cs
new file mode 100644
index 0000000000..678fc85344
--- /dev/null
+++ b/Content.Shared/Traits/Assorted/ImpairedMobilitySystem.cs
@@ -0,0 +1,70 @@
+using Content.Shared.Movement.Systems;
+using Content.Shared.Stunnable;
+using Content.Shared.Hands.EntitySystems;
+using Content.Shared.Hands.Components;
+using Content.Shared.Wieldable.Components;
+
+namespace Content.Shared.Traits.Assorted;
+
+///
+/// Handles
+///
+public sealed class ImpairedMobilitySystem : EntitySystem
+{
+ [Dependency] private readonly SharedHandsSystem _hands = default!;
+ [Dependency] private readonly MovementSpeedModifierSystem _speedModifier = default!;
+ public override void Initialize()
+ {
+ SubscribeLocalEvent(OnInit);
+ SubscribeLocalEvent(OnShutdown);
+ SubscribeLocalEvent(OnRefreshMovementSpeed);
+ SubscribeLocalEvent(OnGetStandUpTime);
+ }
+
+ private void OnInit(Entity ent, ref ComponentInit args)
+ {
+ _speedModifier.RefreshMovementSpeedModifiers(ent);
+ }
+
+ private void OnShutdown(Entity ent, ref ComponentShutdown args)
+ {
+ _speedModifier.RefreshMovementSpeedModifiers(ent);
+ }
+
+ // Handles movement speed for entities with impaired mobility.
+ // Applies a speed penalty, but counteracts it if the entity is holding a non-wielded mobility aid.
+ private void OnRefreshMovementSpeed(Entity ent, ref RefreshMovementSpeedModifiersEvent args)
+ {
+ if (HasMobilityAid(ent.Owner))
+ return;
+
+ args.ModifySpeed(ent.Comp.SpeedModifier);
+ }
+
+ // Increases the time it takes for entities to stand up from being knocked down.
+ private void OnGetStandUpTime(Entity ent, ref GetStandUpTimeEvent args)
+ {
+ args.DoAfterTime *= ent.Comp.StandUpTimeModifier;
+ }
+
+ // Checks if the entity is holding any non-wielded mobility aids.
+ private bool HasMobilityAid(Entity entity)
+ {
+ if (!Resolve(entity, ref entity.Comp, false))
+ return false;
+
+ foreach (var held in _hands.EnumerateHeld(entity))
+ {
+ if (!HasComp(held))
+ continue;
+
+ // Makes sure it's not wielded yet
+ if (TryComp(held, out var wieldable) && wieldable.Wielded)
+ continue;
+
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/Content.Shared/Traits/Assorted/MobilityAidComponent.cs b/Content.Shared/Traits/Assorted/MobilityAidComponent.cs
new file mode 100644
index 0000000000..6623c8217a
--- /dev/null
+++ b/Content.Shared/Traits/Assorted/MobilityAidComponent.cs
@@ -0,0 +1,11 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Traits.Assorted;
+
+///
+/// Component to mark items that restore normal movement speed when held in-hand for entities with the impaired mobility trait.
+/// The speed is automatically calculated to nullify the entity's speed penalty.
+/// Should be used on items that act as mobility aids, such as canes.
+///
+[RegisterComponent, NetworkedComponent]
+public sealed partial class MobilityAidComponent : Component;
diff --git a/Content.Shared/Traits/Assorted/MobilityAidSystem.cs b/Content.Shared/Traits/Assorted/MobilityAidSystem.cs
new file mode 100644
index 0000000000..7df47ca750
--- /dev/null
+++ b/Content.Shared/Traits/Assorted/MobilityAidSystem.cs
@@ -0,0 +1,42 @@
+using Content.Shared.Hands;
+using Content.Shared.Movement.Systems;
+using Content.Shared.Wieldable;
+
+namespace Content.Shared.Traits.Assorted;
+
+///
+/// Handles
+///
+public sealed class MobilityAidSystem : EntitySystem
+{
+ [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!;
+
+ ///
+ public override void Initialize()
+ {
+ SubscribeLocalEvent(OnGotEquippedHand);
+ SubscribeLocalEvent(OnGotUnequippedHand);
+ SubscribeLocalEvent(OnMobilityAidWielded);
+ SubscribeLocalEvent(OnMobilityAidUnwielded);
+ }
+
+ private void OnGotEquippedHand(Entity ent, ref GotEquippedHandEvent args)
+ {
+ _movementSpeedModifier.RefreshMovementSpeedModifiers(args.User);
+ }
+
+ private void OnGotUnequippedHand(Entity ent, ref GotUnequippedHandEvent args)
+ {
+ _movementSpeedModifier.RefreshMovementSpeedModifiers(args.User);
+ }
+
+ private void OnMobilityAidWielded(Entity ent, ref ItemWieldedEvent args)
+ {
+ _movementSpeedModifier.RefreshMovementSpeedModifiers(args.User);
+ }
+
+ private void OnMobilityAidUnwielded(Entity ent, ref ItemUnwieldedEvent args)
+ {
+ _movementSpeedModifier.RefreshMovementSpeedModifiers(args.User);
+ }
+}
diff --git a/Resources/Locale/en-US/traits/traits.ftl b/Resources/Locale/en-US/traits/traits.ftl
index d7ab6ca76a..f4c51d863e 100644
--- a/Resources/Locale/en-US/traits/traits.ftl
+++ b/Resources/Locale/en-US/traits/traits.ftl
@@ -65,3 +65,6 @@ trait-spanish-desc = Hola seƱor, donde esta la biblioteca.
trait-painnumbness-name = Numb
trait-painnumbness-desc = You lack any sense of feeling pain, being unaware of how hurt you may be.
+
+trait-impaired-mobility-name = Impaired Mobility
+trait-impaired-mobility-desc = You have difficulty moving without a mobility aid.
diff --git a/Resources/Prototypes/Entities/Mobs/Player/clone.yml b/Resources/Prototypes/Entities/Mobs/Player/clone.yml
index 43174cfffe..98d99d7321 100644
--- a/Resources/Prototypes/Entities/Mobs/Player/clone.yml
+++ b/Resources/Prototypes/Entities/Mobs/Player/clone.yml
@@ -16,6 +16,7 @@
# traits
- BlackAndWhiteOverlay
- Clumsy
+ - ImpairedMobility
# - LegsParalyzed (you get healed)
- LightweightDrunk
- Muted
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/cane.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/cane.yml
index 29ce5fa8c8..96ad8b233d 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/cane.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/cane.yml
@@ -11,6 +11,7 @@
size: Normal
sprite: Objects/Weapons/Melee/cane.rsi
- type: Appearance
+ - type: MobilityAid
- type: MeleeWeapon
wideAnimationRotation: 45
damage:
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/offset_cane.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/offset_cane.yml
index 1d2081fe93..12e2e9ae70 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/offset_cane.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/offset_cane.yml
@@ -10,6 +10,7 @@
- type: Item
size: Normal
sprite: Objects/Weapons/Melee/offset_canes/standard.rsi
+ - type: MobilityAid
# - type: RandomSprite # Ideally I'd rather these be their own selectable item instead of randomly picked.
# available:
# - color: "#91949C" # standard gray
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/white_cane.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/white_cane.yml
index 997c3771d5..bba4085295 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/white_cane.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/white_cane.yml
@@ -24,4 +24,3 @@
Blunt: 3
- type: UseDelay
delay: 1
-
diff --git a/Resources/Prototypes/Traits/disabilities.yml b/Resources/Prototypes/Traits/disabilities.yml
index a5c1f54d6b..0bb6f0da3c 100644
--- a/Resources/Prototypes/Traits/disabilities.yml
+++ b/Resources/Prototypes/Traits/disabilities.yml
@@ -83,3 +83,12 @@
category: Disabilities
components:
- type: PainNumbness
+
+- type: trait
+ id: ImpairedMobility
+ name: trait-impaired-mobility-name
+ description: trait-impaired-mobility-desc
+ traitGear: OffsetCane
+ category: Disabilities
+ components:
+ - type: ImpairedMobility