diff --git a/Content.Client/Clothing/MagbootsSystem.cs b/Content.Client/Clothing/MagbootsSystem.cs new file mode 100644 index 0000000000..040df94a50 --- /dev/null +++ b/Content.Client/Clothing/MagbootsSystem.cs @@ -0,0 +1,21 @@ +using Content.Shared.Clothing; +using Content.Shared.Movement.EntitySystems; +using Robust.Shared.GameObjects; + +namespace Content.Client.Clothing +{ + public class MagbootsSystem : EntitySystem + { + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnRefreshMovespeed); + } + + private void OnRefreshMovespeed(EntityUid uid, MagbootsComponent component, RefreshMovementSpeedModifiersEvent args) + { + args.ModifySpeed(component.WalkSpeedModifier, component.SprintSpeedModifier); + } + } +} diff --git a/Content.Client/Inventory/ClientInventoryComponent.cs b/Content.Client/Inventory/ClientInventoryComponent.cs index 3a653a67f7..56062b5255 100644 --- a/Content.Client/Inventory/ClientInventoryComponent.cs +++ b/Content.Client/Inventory/ClientInventoryComponent.cs @@ -3,8 +3,10 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using Content.Client.Clothing; using Content.Shared.CharacterAppearance; +using Content.Shared.Chemistry; using Content.Shared.Inventory; using Content.Shared.Movement.Components; +using Content.Shared.Movement.EntitySystems; using Robust.Client.GameObjects; using Robust.Shared.GameObjects; using Robust.Shared.IoC; @@ -81,46 +83,6 @@ namespace Content.Client.Inventory return item != null && _slots.Values.Any(e => e == item); } - public override float WalkSpeedModifier - { - get - { - var mod = 1f; - foreach (var slot in _slots.Values) - { - if (slot != null) - { - foreach (var modifier in slot.GetAllComponents()) - { - mod *= modifier.WalkSpeedModifier; - } - } - } - - return mod; - } - } - - public override float SprintSpeedModifier - { - get - { - var mod = 1f; - foreach (var slot in _slots.Values) - { - if (slot != null) - { - foreach (var modifier in slot.GetAllComponents()) - { - mod *= modifier.SprintSpeedModifier; - } - } - } - - return mod; - } - } - public override void HandleComponentState(ComponentState? curState, ComponentState? nextState) { base.HandleComponentState(curState, nextState); @@ -161,10 +123,7 @@ namespace Content.Client.Inventory } } - if (Owner.TryGetComponent(out MovementSpeedModifierComponent? mod)) - { - mod.RefreshMovementSpeedModifiers(); - } + EntitySystem.Get().RefreshMovementSpeedModifiers(OwnerUid); } private void _setSlot(Slots slot, IEntity entity) diff --git a/Content.Client/Inventory/ClientInventorySystem.cs b/Content.Client/Inventory/ClientInventorySystem.cs index 0d826ccf29..d01c5d32eb 100644 --- a/Content.Client/Inventory/ClientInventorySystem.cs +++ b/Content.Client/Inventory/ClientInventorySystem.cs @@ -2,6 +2,7 @@ using Content.Client.HUD; using Content.Client.Items.Components; using Content.Shared.Input; using Content.Shared.Inventory; +using Content.Shared.Movement.EntitySystems; using Content.Shared.Slippery; using JetBrains.Annotations; using Robust.Client.GameObjects; @@ -29,6 +30,7 @@ namespace Content.Client.Inventory SubscribeLocalEvent((_, component, _) => component.PlayerDetached()); SubscribeLocalEvent(OnSlipAttemptEvent); + SubscribeLocalEvent(OnRefreshMovespeed); } // jesus christ, this is duplicated to server/client, should really just be shared.. @@ -40,6 +42,17 @@ namespace Content.Client.Inventory } } + private void OnRefreshMovespeed(EntityUid uid, ClientInventoryComponent component, RefreshMovementSpeedModifiersEvent args) + { + foreach (var (_, ent) in component.AllSlots) + { + if (ent != null) + { + RaiseLocalEvent(ent.Uid, args, false); + } + } + } + public override void Shutdown() { CommandBinds.Unregister(); diff --git a/Content.Client/Nutrition/Components/HungerComponent.cs b/Content.Client/Nutrition/Components/HungerComponent.cs index 58af57803c..3c24528499 100644 --- a/Content.Client/Nutrition/Components/HungerComponent.cs +++ b/Content.Client/Nutrition/Components/HungerComponent.cs @@ -1,4 +1,5 @@ using Content.Shared.Movement.Components; +using Content.Shared.Movement.EntitySystems; using Content.Shared.Nutrition.Components; using Robust.Shared.GameObjects; @@ -21,10 +22,7 @@ namespace Content.Client.Nutrition.Components _currentHungerThreshold = hunger.CurrentThreshold; - if (Owner.TryGetComponent(out MovementSpeedModifierComponent? movement)) - { - movement.RefreshMovementSpeedModifiers(); - } + EntitySystem.Get().RefreshMovementSpeedModifiers(OwnerUid); } } } diff --git a/Content.Client/Nutrition/Components/ThirstComponent.cs b/Content.Client/Nutrition/Components/ThirstComponent.cs index 4394ef6517..0b1700dc3c 100644 --- a/Content.Client/Nutrition/Components/ThirstComponent.cs +++ b/Content.Client/Nutrition/Components/ThirstComponent.cs @@ -1,4 +1,5 @@ using Content.Shared.Movement.Components; +using Content.Shared.Movement.EntitySystems; using Content.Shared.Nutrition.Components; using Robust.Shared.GameObjects; @@ -21,10 +22,7 @@ namespace Content.Client.Nutrition.Components _currentThirstThreshold = thirst.CurrentThreshold; - if (Owner.TryGetComponent(out MovementSpeedModifierComponent? movement)) - { - movement.RefreshMovementSpeedModifiers(); - } + EntitySystem.Get().RefreshMovementSpeedModifiers(OwnerUid); } } } diff --git a/Content.Server/Chemistry/ReagentEffects/MovespeedModifier.cs b/Content.Server/Chemistry/ReagentEffects/MovespeedModifier.cs index d77446b9e6..519d599a3a 100644 --- a/Content.Server/Chemistry/ReagentEffects/MovespeedModifier.cs +++ b/Content.Server/Chemistry/ReagentEffects/MovespeedModifier.cs @@ -2,6 +2,7 @@ using System; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reagent; using Content.Shared.Movement.Components; +using Content.Shared.Movement.EntitySystems; using Robust.Shared.GameObjects; using Robust.Shared.IoC; using Robust.Shared.Serialization.Manager.Attributes; @@ -38,8 +39,6 @@ namespace Content.Server.Chemistry.ReagentEffects /// public override void Metabolize(IEntity solutionEntity, Solution.ReagentQuantity amount) { - if (!solutionEntity.TryGetComponent(out MovementSpeedModifierComponent? movement)) return; - solutionEntity.EnsureComponent(out MovespeedModifierMetabolismComponent status); // Only refresh movement if we need to. @@ -52,7 +51,7 @@ namespace Content.Server.Chemistry.ReagentEffects IncreaseTimer(status, StatusLifetime * amount.Quantity.Float()); if (modified) - movement.RefreshMovementSpeedModifiers(); + EntitySystem.Get().RefreshMovementSpeedModifiers(solutionEntity.Uid); } public void IncreaseTimer(MovespeedModifierMetabolismComponent status, float time) diff --git a/Content.Server/Clothing/MagbootsSystem.cs b/Content.Server/Clothing/MagbootsSystem.cs index b46fec5e25..89d795852d 100644 --- a/Content.Server/Clothing/MagbootsSystem.cs +++ b/Content.Server/Clothing/MagbootsSystem.cs @@ -1,4 +1,5 @@ using Content.Server.Clothing.Components; +using Content.Shared.Movement.EntitySystems; using Content.Shared.Slippery; using Content.Shared.Verbs; using Robust.Shared.GameObjects; @@ -14,6 +15,12 @@ namespace Content.Server.Clothing SubscribeLocalEvent(AddToggleVerb); SubscribeLocalEvent(OnSlipAttempt); + SubscribeLocalEvent(OnRefreshMovespeed); + } + + private void OnRefreshMovespeed(EntityUid uid, MagbootsComponent component, RefreshMovementSpeedModifiersEvent args) + { + args.ModifySpeed(component.WalkSpeedModifier, component.SprintSpeedModifier); } private void AddToggleVerb(EntityUid uid, MagbootsComponent component, GetActivationVerbsEvent args) diff --git a/Content.Server/Inventory/Components/InventoryComponent.cs b/Content.Server/Inventory/Components/InventoryComponent.cs index cb2d4d6056..37c8a90ef6 100644 --- a/Content.Server/Inventory/Components/InventoryComponent.cs +++ b/Content.Server/Inventory/Components/InventoryComponent.cs @@ -12,6 +12,7 @@ using Content.Shared.ActionBlocker; using Content.Shared.Acts; using Content.Shared.Inventory; using Content.Shared.Movement.Components; +using Content.Shared.Movement.EntitySystems; using Content.Shared.Popups; using Content.Shared.Verbs; using Robust.Server.Console; @@ -60,46 +61,6 @@ namespace Content.Server.Inventory.Components } } - public override float WalkSpeedModifier - { - get - { - var mod = 1f; - foreach (var slot in _slotContainers.Values) - { - if (slot.ContainedEntity != null) - { - foreach (var modifier in slot.ContainedEntity.GetAllComponents()) - { - mod *= modifier.WalkSpeedModifier; - } - } - } - - return mod; - } - } - - public override float SprintSpeedModifier - { - get - { - var mod = 1f; - foreach (var slot in _slotContainers.Values) - { - if (slot.ContainedEntity != null) - { - foreach (var modifier in slot.ContainedEntity.GetAllComponents()) - { - mod *= modifier.SprintSpeedModifier; - } - } - } - - return mod; - } - } - protected override void OnRemove() { var slots = _slotContainers.Keys.ToList(); @@ -333,10 +294,7 @@ namespace Content.Server.Inventory.Components private void UpdateMovementSpeed() { - if (Owner.TryGetComponent(out MovementSpeedModifierComponent? mod)) - { - mod.RefreshMovementSpeedModifiers(); - } + EntitySystem.Get().RefreshMovementSpeedModifiers(OwnerUid); } public void ForceUnequip(Slots slot) diff --git a/Content.Server/Inventory/InventorySystem.cs b/Content.Server/Inventory/InventorySystem.cs index 23211e1564..418f89a583 100644 --- a/Content.Server/Inventory/InventorySystem.cs +++ b/Content.Server/Inventory/InventorySystem.cs @@ -5,6 +5,7 @@ using Content.Shared.Inventory; using Content.Shared.Slippery; using Content.Shared.Damage; using Content.Shared.Electrocution; +using Content.Shared.Movement.EntitySystems; using Robust.Shared.Containers; using Robust.Shared.GameObjects; @@ -23,6 +24,7 @@ namespace Content.Server.Inventory SubscribeLocalEvent(OnDamageModify); SubscribeLocalEvent(OnElectrocutionAttempt); SubscribeLocalEvent(OnSlipAttemptEvent); + SubscribeLocalEvent(OnRefreshMovespeed); } private void OnSlipAttemptEvent(EntityUid uid, InventoryComponent component, SlipAttemptEvent args) @@ -33,6 +35,11 @@ namespace Content.Server.Inventory } } + private void OnRefreshMovespeed(EntityUid uid, InventoryComponent component, RefreshMovementSpeedModifiersEvent args) + { + RelayInventoryEvent(component, args); + } + private static void HandleInvRemovedFromContainer(EntityUid uid, InventoryComponent component, EntRemovedFromContainerMessage args) { component.ForceUnequip(args.Container, args.Entity); @@ -45,31 +52,25 @@ namespace Content.Server.Inventory private void OnHighPressureEvent(EntityUid uid, InventoryComponent component, HighPressureEvent args) { - RelayPressureEvent(component, args); + RelayInventoryEvent(component, args); } private void OnLowPressureEvent(EntityUid uid, InventoryComponent component, LowPressureEvent args) { - RelayPressureEvent(component, args); + RelayInventoryEvent(component, args); } private void OnElectrocutionAttempt(EntityUid uid, InventoryComponent component, ElectrocutionAttemptEvent args) { - foreach (var equipped in component.GetAllHeldItems()) - { - RaiseLocalEvent(equipped.Uid, args, false); - } + RelayInventoryEvent(component, args); } private void OnDamageModify(EntityUid uid, InventoryComponent component, DamageModifyEvent args) { - foreach (var equipped in component.GetAllHeldItems()) - { - RaiseLocalEvent(equipped.Uid, args, false); - } + RelayInventoryEvent(component, args); } - private void RelayPressureEvent(InventoryComponent component, T args) where T : PressureEvent + private void RelayInventoryEvent(InventoryComponent component, T args) where T : EntityEventArgs { foreach (var equipped in component.GetAllHeldItems()) { diff --git a/Content.Server/Nutrition/Components/HungerComponent.cs b/Content.Server/Nutrition/Components/HungerComponent.cs index 2eb83f55d4..be68ed3df5 100644 --- a/Content.Server/Nutrition/Components/HungerComponent.cs +++ b/Content.Server/Nutrition/Components/HungerComponent.cs @@ -5,6 +5,7 @@ using Content.Shared.Alert; using Content.Shared.Damage; using Content.Shared.MobState; using Content.Shared.Movement.Components; +using Content.Shared.Movement.EntitySystems; using Content.Shared.Nutrition.Components; using Robust.Shared.GameObjects; using Robust.Shared.IoC; @@ -86,7 +87,7 @@ namespace Content.Server.Nutrition.Components if (_lastHungerThreshold == HungerThreshold.Starving && _currentHungerThreshold != HungerThreshold.Dead && Owner.TryGetComponent(out MovementSpeedModifierComponent? movementSlowdownComponent)) { - movementSlowdownComponent.RefreshMovementSpeedModifiers(); + EntitySystem.Get().RefreshMovementSpeedModifiers(OwnerUid); } // Update UI @@ -122,10 +123,7 @@ namespace Content.Server.Nutrition.Components case HungerThreshold.Starving: // TODO: If something else bumps this could cause mega-speed. // If some form of speed update system if multiple things are touching it use that. - if (Owner.TryGetComponent(out MovementSpeedModifierComponent? movementSlowdownComponent1)) - { - movementSlowdownComponent1.RefreshMovementSpeedModifiers(); - } + EntitySystem.Get().RefreshMovementSpeedModifiers(OwnerUid); _lastHungerThreshold = _currentHungerThreshold; _actualDecayRate = _baseDecayRate * 0.6f; return; diff --git a/Content.Server/Nutrition/Components/ThirstComponent.cs b/Content.Server/Nutrition/Components/ThirstComponent.cs index 314bc2c007..39207a1955 100644 --- a/Content.Server/Nutrition/Components/ThirstComponent.cs +++ b/Content.Server/Nutrition/Components/ThirstComponent.cs @@ -5,6 +5,7 @@ using Content.Shared.Alert; using Content.Shared.Damage; using Content.Shared.MobState; using Content.Shared.Movement.Components; +using Content.Shared.Movement.EntitySystems; using Content.Shared.Nutrition.Components; using Robust.Shared.GameObjects; using Robust.Shared.IoC; @@ -85,7 +86,7 @@ namespace Content.Server.Nutrition.Components if (_lastThirstThreshold == ThirstThreshold.Parched && _currentThirstThreshold != ThirstThreshold.Dead && Owner.TryGetComponent(out MovementSpeedModifierComponent? movementSlowdownComponent)) { - movementSlowdownComponent.RefreshMovementSpeedModifiers(); + EntitySystem.Get().RefreshMovementSpeedModifiers(OwnerUid); } // Update UI @@ -119,10 +120,7 @@ namespace Content.Server.Nutrition.Components return; case ThirstThreshold.Parched: - if (Owner.TryGetComponent(out MovementSpeedModifierComponent? movementSlowdownComponent1)) - { - movementSlowdownComponent1.RefreshMovementSpeedModifiers(); - } + EntitySystem.Get().RefreshMovementSpeedModifiers(OwnerUid); _lastThirstThreshold = _currentThirstThreshold; _actualDecayRate = _baseDecayRate * 0.6f; return; diff --git a/Content.Server/Stunnable/StunOnCollideSystem.cs b/Content.Server/Stunnable/StunOnCollideSystem.cs index 4f2f85b046..4360464dbf 100644 --- a/Content.Server/Stunnable/StunOnCollideSystem.cs +++ b/Content.Server/Stunnable/StunOnCollideSystem.cs @@ -34,10 +34,9 @@ namespace Content.Server.Stunnable ServerAlertsComponent? alerts = null; StandingStateComponent? standingState = null; AppearanceComponent? appearance = null; - MovementSpeedModifierComponent? speedModifier = null; // Let the actual methods log errors for these. - Resolve(otherUid, ref alerts, ref standingState, ref appearance, ref speedModifier, false); + Resolve(otherUid, ref alerts, ref standingState, ref appearance, false); _stunSystem.TryStun(otherUid, TimeSpan.FromSeconds(component.StunAmount), status, alerts); @@ -45,7 +44,7 @@ namespace Content.Server.Stunnable status, alerts); _stunSystem.TrySlowdown(otherUid, TimeSpan.FromSeconds(component.SlowdownAmount), - component.WalkSpeedMultiplier, component.RunSpeedMultiplier, status, speedModifier, alerts); + component.WalkSpeedMultiplier, component.RunSpeedMultiplier, status, alerts); } } } diff --git a/Content.Shared/Chemistry/Components/MovespeedModifierMetabolismComponent.cs b/Content.Shared/Chemistry/Components/MovespeedModifierMetabolismComponent.cs index afcd0f3f42..e4c5a9dd9b 100644 --- a/Content.Shared/Chemistry/Components/MovespeedModifierMetabolismComponent.cs +++ b/Content.Shared/Chemistry/Components/MovespeedModifierMetabolismComponent.cs @@ -4,6 +4,7 @@ using Robust.Shared.Players; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; using System; +using Robust.Shared.Analyzers; using Robust.Shared.GameStates; using Robust.Shared.Timing; using Robust.Shared.IoC; @@ -13,7 +14,7 @@ namespace Content.Shared.Chemistry.Components //TODO: refactor movement modifier component because this is a pretty poor solution [RegisterComponent] [NetworkedComponent] - public sealed class MovespeedModifierMetabolismComponent : Component, IMoveSpeedModifier + public sealed class MovespeedModifierMetabolismComponent : Component { [ViewVariables] public override string Name => "MovespeedModifierMetabolism"; diff --git a/Content.Shared/Chemistry/MetabolismMovespeedModifierSystem.cs b/Content.Shared/Chemistry/MetabolismMovespeedModifierSystem.cs index 62499006a8..a365d65208 100644 --- a/Content.Shared/Chemistry/MetabolismMovespeedModifierSystem.cs +++ b/Content.Shared/Chemistry/MetabolismMovespeedModifierSystem.cs @@ -6,13 +6,16 @@ using Robust.Shared.Timing; using System.Collections.Generic; using System.Linq; using Content.Shared.Movement.Components; +using Content.Shared.Movement.EntitySystems; using static Content.Shared.Chemistry.Components.MovespeedModifierMetabolismComponent; namespace Content.Shared.Chemistry { + // TODO CONVERT THIS TO A STATUS EFFECT!!!!!!!!!!!!!!!!!!!!!!!! public class MetabolismMovespeedModifierSystem : EntitySystem { [Dependency] private readonly IGameTiming _gameTiming = default!; + [Dependency] private readonly MovementSpeedModifierSystem _movespeed = default!; private readonly List _components = new(); @@ -22,6 +25,7 @@ namespace Content.Shared.Chemistry SubscribeLocalEvent(OnMovespeedHandleState); SubscribeLocalEvent(AddComponent); + SubscribeLocalEvent(OnRefreshMovespeed); } private void OnMovespeedHandleState(EntityUid uid, MovespeedModifierMetabolismComponent component, ref ComponentHandleState args) @@ -33,7 +37,7 @@ namespace Content.Shared.Chemistry (!component.WalkSpeedModifier.Equals(cast.WalkSpeedModifier) || !component.SprintSpeedModifier.Equals(cast.SprintSpeedModifier))) { - modifier.RefreshMovementSpeedModifiers(); + _movespeed.RefreshMovementSpeedModifiers(uid); } component.WalkSpeedModifier = cast.WalkSpeedModifier; @@ -41,6 +45,12 @@ namespace Content.Shared.Chemistry component.ModifierTimer = cast.ModifierTimer; } + + private void OnRefreshMovespeed(EntityUid uid, MovespeedModifierMetabolismComponent component, RefreshMovementSpeedModifiersEvent args) + { + args.ModifySpeed(component.WalkSpeedModifier, component.SprintSpeedModifier); + } + private void AddComponent(EntityUid uid, MovespeedModifierMetabolismComponent component, ComponentStartup args) { _components.Add(component); @@ -65,12 +75,9 @@ namespace Content.Shared.Chemistry if (component.ModifierTimer > currentTime) continue; _components.RemoveAt(i); - EntityManager.RemoveComponent(component.Owner.Uid); + EntityManager.RemoveComponent(component.OwnerUid); - if (component.Owner.TryGetComponent(out MovementSpeedModifierComponent? modifier)) - { - modifier.RefreshMovementSpeedModifiers(); - } + _movespeed.RefreshMovementSpeedModifiers(component.OwnerUid); } } } diff --git a/Content.Shared/Clothing/SharedMagbootsComponent.cs b/Content.Shared/Clothing/SharedMagbootsComponent.cs index 4740f6cdf1..3d65e295a7 100644 --- a/Content.Shared/Clothing/SharedMagbootsComponent.cs +++ b/Content.Shared/Clothing/SharedMagbootsComponent.cs @@ -1,5 +1,7 @@ using System; using Content.Shared.Movement.Components; +using Content.Shared.Movement.EntitySystems; +using Robust.Shared.Containers; using Robust.Shared.GameObjects; using Robust.Shared.GameStates; using Robust.Shared.Serialization; @@ -7,16 +9,19 @@ using Robust.Shared.Serialization; namespace Content.Shared.Clothing { [NetworkedComponent()] - public abstract class SharedMagbootsComponent : Component, IMoveSpeedModifier + public abstract class SharedMagbootsComponent : Component { public sealed override string Name => "Magboots"; public abstract bool On { get; set; } - protected void OnChanged() { - MovementSpeedModifierComponent.RefreshItemModifiers(Owner); + // inventory system will automatically hook into the event raised by this and update accordingly + if (Owner.TryGetContainer(out var container)) + { + EntitySystem.Get().RefreshMovementSpeedModifiers(container.Owner.Uid); + } } public float WalkSpeedModifier => On ? 0.85f : 1; diff --git a/Content.Shared/Inventory/SharedInventoryComponent.cs b/Content.Shared/Inventory/SharedInventoryComponent.cs index 5b1fd6eb51..27733bb097 100644 --- a/Content.Shared/Inventory/SharedInventoryComponent.cs +++ b/Content.Shared/Inventory/SharedInventoryComponent.cs @@ -14,7 +14,7 @@ using static Content.Shared.Inventory.EquipmentSlotDefines; namespace Content.Shared.Inventory { [NetworkedComponent()] - public abstract class SharedInventoryComponent : Component, IMoveSpeedModifier + public abstract class SharedInventoryComponent : Component { [Dependency] protected readonly IReflectionManager ReflectionManager = default!; [Dependency] protected readonly IDynamicTypeFactory DynamicTypeFactory = default!; @@ -98,8 +98,5 @@ namespace Content.Shared.Inventory Slot = slot; } } - - public abstract float WalkSpeedModifier { get; } - public abstract float SprintSpeedModifier { get; } } } diff --git a/Content.Shared/Movement/Components/MovementSpeedModifierComponent.cs b/Content.Shared/Movement/Components/MovementSpeedModifierComponent.cs index ee8137abd7..331b71bdc9 100644 --- a/Content.Shared/Movement/Components/MovementSpeedModifierComponent.cs +++ b/Content.Shared/Movement/Components/MovementSpeedModifierComponent.cs @@ -1,3 +1,5 @@ +using Content.Shared.Movement.EntitySystems; +using Robust.Shared.Analyzers; using Robust.Shared.Containers; using Robust.Shared.GameObjects; using Robust.Shared.GameStates; @@ -7,7 +9,7 @@ using Robust.Shared.ViewVariables; namespace Content.Shared.Movement.Components { [RegisterComponent] - [NetworkedComponent] + [NetworkedComponent, Friend(typeof(MovementSpeedModifierSystem))] public sealed class MovementSpeedModifierComponent : Component { public const float DefaultBaseWalkSpeed = 4.0f; @@ -15,26 +17,11 @@ namespace Content.Shared.Movement.Components public override string Name => "MovementSpeedModifier"; - private float _cachedWalkSpeedModifier = 1.0f; [ViewVariables] - public float WalkSpeedModifier - { - get - { - RecalculateMovementSpeedModifiers(); - return _cachedWalkSpeedModifier; - } - } - private float _cachedSprintSpeedModifier; + public float WalkSpeedModifier = 1.0f; + [ViewVariables] - public float SprintSpeedModifier - { - get - { - RecalculateMovementSpeedModifiers(); - return _cachedSprintSpeedModifier; - } - } + public float SprintSpeedModifier = 1.0f; [ViewVariables(VVAccess.ReadWrite)] public float BaseWalkSpeedVV @@ -68,52 +55,5 @@ namespace Content.Shared.Movement.Components public float CurrentWalkSpeed => WalkSpeedModifier * BaseWalkSpeed; [ViewVariables] public float CurrentSprintSpeed => SprintSpeedModifier * BaseSprintSpeed; - - /// - /// set to warn us that a component's movespeed modifier has changed - /// - private bool _movespeedModifiersNeedRefresh = true; - - public void RefreshMovementSpeedModifiers() - { - _movespeedModifiersNeedRefresh = true; - } - - public static void RefreshItemModifiers(IEntity item) - { - if (item.TryGetContainer(out var container) && - container.Owner.TryGetComponent(out MovementSpeedModifierComponent? mod)) - { - mod.RefreshMovementSpeedModifiers(); - } - } - - /// - /// Recalculate movement speed with current modifiers, or return early if no change - /// - private void RecalculateMovementSpeedModifiers() - { - { - if (!_movespeedModifiersNeedRefresh) - return; - var movespeedModifiers = Owner.GetAllComponents(); - float walkSpeedModifier = 1.0f; - float sprintSpeedModifier = 1.0f; - foreach (var component in movespeedModifiers) - { - walkSpeedModifier *= component.WalkSpeedModifier; - sprintSpeedModifier *= component.SprintSpeedModifier; - } - _cachedWalkSpeedModifier = walkSpeedModifier; - _cachedSprintSpeedModifier = sprintSpeedModifier; - } - _movespeedModifiersNeedRefresh = false; - } - } - - public interface IMoveSpeedModifier - { - float WalkSpeedModifier { get; } - float SprintSpeedModifier { get; } } } diff --git a/Content.Shared/Movement/EntitySystems/MovementSpeedModifierSystem.cs b/Content.Shared/Movement/EntitySystems/MovementSpeedModifierSystem.cs index 90cdea07d3..9a70c31530 100644 --- a/Content.Shared/Movement/EntitySystems/MovementSpeedModifierSystem.cs +++ b/Content.Shared/Movement/EntitySystems/MovementSpeedModifierSystem.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Linq; using Content.Shared.Movement.Components; using Robust.Shared.GameObjects; using Robust.Shared.GameStates; @@ -8,6 +10,18 @@ namespace Content.Shared.Movement.EntitySystems { public sealed class MovementSpeedModifierSystem : EntitySystem { + private readonly HashSet _needsRefresh = new(); + + public override void Update(float frameTime) + { + foreach (var uid in _needsRefresh) + { + RecalculateMovementSpeedModifiers(uid); + } + + _needsRefresh.Clear(); + } + public override void Initialize() { base.Initialize(); @@ -31,6 +45,25 @@ namespace Content.Shared.Movement.EntitySystems component.BaseSprintSpeed = state.BaseSprintSpeed; } + public void RefreshMovementSpeedModifiers(EntityUid uid) + { + _needsRefresh.Add(uid); + } + + private void RecalculateMovementSpeedModifiers(EntityUid uid, MovementSpeedModifierComponent? move = null) + { + if (!Resolve(uid, ref move, false)) + return; + + var ev = new RefreshMovementSpeedModifiersEvent(); + RaiseLocalEvent(uid, ev, false); + + move.WalkSpeedModifier = ev.WalkSpeedModifier; + move.SprintSpeedModifier = ev.SprintSpeedModifier; + + move.Dirty(); + } + [Serializable, NetSerializable] private sealed class MovementSpeedModifierComponentState : ComponentState { @@ -38,4 +71,21 @@ namespace Content.Shared.Movement.EntitySystems public float BaseSprintSpeed; } } + + /// + /// Raised on an entity to determine its new movement speed. Any system that wishes to change movement speed + /// should hook into this event and set it then. If you want this event to be raised, + /// call . + /// + public class RefreshMovementSpeedModifiersEvent : EntityEventArgs + { + public float WalkSpeedModifier { get; private set; } = 1.0f; + public float SprintSpeedModifier { get; private set; } = 1.0f; + + public void ModifySpeed(float walk, float sprint) + { + WalkSpeedModifier *= walk; + SprintSpeedModifier *= sprint; + } + } } diff --git a/Content.Shared/Nutrition/Components/SharedHungerComponent.cs b/Content.Shared/Nutrition/Components/SharedHungerComponent.cs index 009aeaa45a..3f6cd68bbe 100644 --- a/Content.Shared/Nutrition/Components/SharedHungerComponent.cs +++ b/Content.Shared/Nutrition/Components/SharedHungerComponent.cs @@ -8,37 +8,13 @@ using Robust.Shared.ViewVariables; namespace Content.Shared.Nutrition.Components { [NetworkedComponent()] - public abstract class SharedHungerComponent : Component, IMoveSpeedModifier + public abstract class SharedHungerComponent : Component { public sealed override string Name => "Hunger"; [ViewVariables] public abstract HungerThreshold CurrentHungerThreshold { get; } - - float IMoveSpeedModifier.WalkSpeedModifier - { - get - { - if (CurrentHungerThreshold == HungerThreshold.Starving) - { - return 0.75f; - } - return 1.0f; - } - } - float IMoveSpeedModifier.SprintSpeedModifier - { - get - { - if (CurrentHungerThreshold == HungerThreshold.Starving) - { - return 0.75f; - } - return 1.0f; - } - } - [Serializable, NetSerializable] protected sealed class HungerComponentState : ComponentState { diff --git a/Content.Shared/Nutrition/Components/SharedThirstComponent.cs b/Content.Shared/Nutrition/Components/SharedThirstComponent.cs index e7a7cba426..2a8fe5ccc2 100644 --- a/Content.Shared/Nutrition/Components/SharedThirstComponent.cs +++ b/Content.Shared/Nutrition/Components/SharedThirstComponent.cs @@ -8,36 +8,13 @@ using Robust.Shared.ViewVariables; namespace Content.Shared.Nutrition.Components { [NetworkedComponent()] - public abstract class SharedThirstComponent : Component, IMoveSpeedModifier + public abstract class SharedThirstComponent : Component { public sealed override string Name => "Thirst"; [ViewVariables] public abstract ThirstThreshold CurrentThirstThreshold { get; } - float IMoveSpeedModifier.SprintSpeedModifier - { - get - { - if (CurrentThirstThreshold == ThirstThreshold.Parched) - { - return 0.75f; - } - return 1.0f; - } - } - float IMoveSpeedModifier.WalkSpeedModifier - { - get - { - if (CurrentThirstThreshold == ThirstThreshold.Parched) - { - return 0.75f; - } - return 1.0f; - } - } - [Serializable, NetSerializable] protected sealed class ThirstComponentState : ComponentState { diff --git a/Content.Shared/Nutrition/EntitySystems/SharedHungerSystem.cs b/Content.Shared/Nutrition/EntitySystems/SharedHungerSystem.cs new file mode 100644 index 0000000000..0bb7897661 --- /dev/null +++ b/Content.Shared/Nutrition/EntitySystems/SharedHungerSystem.cs @@ -0,0 +1,22 @@ +using Content.Shared.Movement.EntitySystems; +using Content.Shared.Nutrition.Components; +using Robust.Shared.GameObjects; + +namespace Content.Shared.Nutrition.EntitySystems +{ + public class SharedHungerSystem : EntitySystem + { + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnRefreshMovespeed); + } + + private void OnRefreshMovespeed(EntityUid uid, SharedHungerComponent component, RefreshMovementSpeedModifiersEvent args) + { + float mod = component.CurrentHungerThreshold == HungerThreshold.Starving ? 0.75f : 1.0f; + args.ModifySpeed(mod, mod); + } + } +} diff --git a/Content.Shared/Nutrition/EntitySystems/SharedThirstSystem.cs b/Content.Shared/Nutrition/EntitySystems/SharedThirstSystem.cs new file mode 100644 index 0000000000..311867b2f1 --- /dev/null +++ b/Content.Shared/Nutrition/EntitySystems/SharedThirstSystem.cs @@ -0,0 +1,22 @@ +using Content.Shared.Movement.EntitySystems; +using Content.Shared.Nutrition.Components; +using Robust.Shared.GameObjects; + +namespace Content.Shared.Nutrition.EntitySystems +{ + public class SharedThirstSystem : EntitySystem + { + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnRefreshMovespeed); + } + + private void OnRefreshMovespeed(EntityUid uid, SharedThirstComponent component, RefreshMovementSpeedModifiersEvent args) + { + float mod = component.CurrentThirstThreshold == ThirstThreshold.Parched ? 0.75f : 1.0f; + args.ModifySpeed(mod, mod); + } + } +} diff --git a/Content.Shared/Pulling/Components/SharedPullerComponent.cs b/Content.Shared/Pulling/Components/SharedPullerComponent.cs index 89398b0665..ca89c3d6da 100644 --- a/Content.Shared/Pulling/Components/SharedPullerComponent.cs +++ b/Content.Shared/Pulling/Components/SharedPullerComponent.cs @@ -10,7 +10,7 @@ namespace Content.Shared.Pulling.Components { [RegisterComponent] [Friend(typeof(SharedPullingStateManagementSystem))] - public class SharedPullerComponent : Component, IMoveSpeedModifier + public class SharedPullerComponent : Component { public override string Name => "Puller"; diff --git a/Content.Shared/Pulling/Systems/SharedPullerSystem.cs b/Content.Shared/Pulling/Systems/SharedPullerSystem.cs index 207e83174f..e09c2e6add 100644 --- a/Content.Shared/Pulling/Systems/SharedPullerSystem.cs +++ b/Content.Shared/Pulling/Systems/SharedPullerSystem.cs @@ -1,6 +1,7 @@ using Content.Shared.Alert; using Content.Shared.Hands; using Content.Shared.Movement.Components; +using Content.Shared.Movement.EntitySystems; using Content.Shared.Physics.Pull; using Content.Shared.Pulling.Components; using JetBrains.Annotations; @@ -13,6 +14,7 @@ namespace Content.Shared.Pulling.Systems public sealed class SharedPullerSystem : EntitySystem { [Dependency] private readonly SharedPullingSystem _pullSystem = default!; + [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifierSystem = default!; public override void Initialize() { @@ -21,6 +23,7 @@ namespace Content.Shared.Pulling.Systems SubscribeLocalEvent(PullerHandlePullStarted); SubscribeLocalEvent(PullerHandlePullStopped); SubscribeLocalEvent(OnVirtualItemDeleted); + SubscribeLocalEvent(OnRefreshMovespeed); } private void OnVirtualItemDeleted(EntityUid uid, SharedPullerComponent component, VirtualItemDeletedEvent args) @@ -37,7 +40,7 @@ namespace Content.Shared.Pulling.Systems } } - private static void PullerHandlePullStarted( + private void PullerHandlePullStarted( EntityUid uid, SharedPullerComponent component, PullStartedMessage args) @@ -51,7 +54,7 @@ namespace Content.Shared.Pulling.Systems RefreshMovementSpeed(component); } - private static void PullerHandlePullStopped( + private void PullerHandlePullStopped( EntityUid uid, SharedPullerComponent component, PullStoppedMessage args) @@ -65,13 +68,14 @@ namespace Content.Shared.Pulling.Systems RefreshMovementSpeed(component); } - private static void RefreshMovementSpeed(SharedPullerComponent component) + private void OnRefreshMovespeed(EntityUid uid, SharedPullerComponent component, RefreshMovementSpeedModifiersEvent args) { - // Before changing how this is updated, please see SharedPullerComponent - if (component.Owner.TryGetComponent(out var speed)) - { - speed.RefreshMovementSpeedModifiers(); - } + args.ModifySpeed(component.WalkSpeedModifier, component.SprintSpeedModifier); + } + + private void RefreshMovementSpeed(SharedPullerComponent component) + { + _movementSpeedModifierSystem.RefreshMovementSpeedModifiers(component.OwnerUid); } } } diff --git a/Content.Shared/Stunnable/SharedStunSystem.cs b/Content.Shared/Stunnable/SharedStunSystem.cs index 6054f101c8..9b5570f72c 100644 --- a/Content.Shared/Stunnable/SharedStunSystem.cs +++ b/Content.Shared/Stunnable/SharedStunSystem.cs @@ -8,6 +8,7 @@ using Content.Shared.Inventory.Events; using Content.Shared.Item; using Content.Shared.Movement; using Content.Shared.Movement.Components; +using Content.Shared.Movement.EntitySystems; using Content.Shared.Speech; using Content.Shared.Standing; using Content.Shared.StatusEffect; @@ -27,6 +28,7 @@ namespace Content.Shared.Stunnable { [Dependency] private readonly StandingStateSystem _standingStateSystem = default!; [Dependency] private readonly StatusEffectsSystem _statusEffectSystem = default!; + [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifierSystem = default!; public override void Initialize() { @@ -44,6 +46,7 @@ namespace Content.Shared.Stunnable // helping people up if they're knocked down SubscribeLocalEvent(OnInteractHand); + SubscribeLocalEvent(OnRefreshMovespeed); // Attempt event subscriptions. SubscribeLocalEvent(OnMoveAttempt); @@ -97,22 +100,17 @@ namespace Content.Shared.Stunnable private void OnSlowInit(EntityUid uid, SlowedDownComponent component, ComponentInit args) { - // needs to be done so the client can also refresh when the addition is replicated, - // if the initial status effect addition wasn't predicted - if (EntityManager.TryGetComponent(uid, out var move)) - { - move.RefreshMovementSpeedModifiers(); - } + _movementSpeedModifierSystem.RefreshMovementSpeedModifiers(uid); } private void OnSlowRemove(EntityUid uid, SlowedDownComponent component, ComponentRemove args) { - if (EntityManager.TryGetComponent(uid, out var move)) - { - component.SprintSpeedModifier = 1.0f; - component.WalkSpeedModifier = 1.0f; - move.RefreshMovementSpeedModifiers(); - } + _movementSpeedModifierSystem.RefreshMovementSpeedModifiers(uid); + } + + private void OnRefreshMovespeed(EntityUid uid, SlowedDownComponent component, RefreshMovementSpeedModifiersEvent args) + { + args.ModifySpeed(component.WalkSpeedModifier, component.SprintSpeedModifier); } // TODO STUN: Make events for different things. (Getting modifiers, attempt events, informative events...) @@ -127,6 +125,9 @@ namespace Content.Shared.Stunnable if (time <= TimeSpan.Zero) return false; + if (!Resolve(uid, ref status, false)) + return false; + Resolve(uid, ref alerts, false); return _statusEffectSystem.TryAddStatusEffect(uid, "Stun", time, alerts: alerts); @@ -142,6 +143,9 @@ namespace Content.Shared.Stunnable if (time <= TimeSpan.Zero) return false; + if (!Resolve(uid, ref status, false)) + return false; + Resolve(uid, ref alerts, false); return _statusEffectSystem.TryAddStatusEffect(uid, "KnockedDown", time, alerts: alerts); @@ -154,6 +158,9 @@ namespace Content.Shared.Stunnable StatusEffectsComponent? status = null, SharedAlertsComponent? alerts = null) { + if (!Resolve(uid, ref status)) + return false; + // Optional component. Resolve(uid, ref alerts, false); @@ -166,11 +173,13 @@ namespace Content.Shared.Stunnable public bool TrySlowdown(EntityUid uid, TimeSpan time, float walkSpeedMultiplier = 1f, float runSpeedMultiplier = 1f, StatusEffectsComponent? status = null, - MovementSpeedModifierComponent? speedModifier = null, SharedAlertsComponent? alerts = null) { + if (!Resolve(uid, ref status)) + return false; + // "Optional" component. - Resolve(uid, ref speedModifier, false); + Resolve(uid, ref alerts, false); if (time <= TimeSpan.Zero) return false; @@ -185,7 +194,7 @@ namespace Content.Shared.Stunnable slowed.WalkSpeedModifier *= walkSpeedMultiplier; slowed.SprintSpeedModifier *= runSpeedMultiplier; - speedModifier?.RefreshMovementSpeedModifiers(); + _movementSpeedModifierSystem.RefreshMovementSpeedModifiers(uid); return true; } diff --git a/Content.Shared/Stunnable/SlowedDownComponent.cs b/Content.Shared/Stunnable/SlowedDownComponent.cs index 9aecedf718..3b0d24e264 100644 --- a/Content.Shared/Stunnable/SlowedDownComponent.cs +++ b/Content.Shared/Stunnable/SlowedDownComponent.cs @@ -10,7 +10,7 @@ namespace Content.Shared.Stunnable [RegisterComponent] [NetworkedComponent] [Friend(typeof(SharedStunSystem))] - public class SlowedDownComponent : Component, IMoveSpeedModifier + public class SlowedDownComponent : Component { public override string Name => "SlowedDown";