diff --git a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs index 8521e4c93c..9e1620bd17 100644 --- a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs +++ b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs @@ -116,7 +116,7 @@ public override void Update(float frameTime) // Unarmed will try to disarm // Melee weapons will wideswing // Ranged weapons will do a light attack. - if (altDown == BoundKeyState.Down) + if (altDown == BoundKeyState.Down && weapon.CanHeavyAttack) // WD EDIT { // Get the target that was clicked on EntityUid? target = null; diff --git a/Content.Server/Explosion/EntitySystems/TriggerSystem.cs b/Content.Server/Explosion/EntitySystems/TriggerSystem.cs index 8e0a75ea24..098d5a3603 100644 --- a/Content.Server/Explosion/EntitySystems/TriggerSystem.cs +++ b/Content.Server/Explosion/EntitySystems/TriggerSystem.cs @@ -154,7 +154,7 @@ private void HandleExplodeTrigger(EntityUid uid, ExplodeOnTriggerComponent compo private void HandleFlashTrigger(EntityUid uid, FlashOnTriggerComponent component, TriggerEvent args) { // TODO Make flash durations sane ffs. - _flashSystem.FlashArea(uid, args.User, component.Range, component.Duration * 1000f, probability: component.Probability); + _flashSystem.FlashArea(uid, args.User, component.Range, component.Duration * 1000f, probability: component.Probability, stunTime: component.StunTime, knockdownTime: component.KnockdownTime); // WD EDIT args.Handled = true; } diff --git a/Content.Server/Flash/FlashSystem.cs b/Content.Server/Flash/FlashSystem.cs index bc91a307b0..81c071fec9 100644 --- a/Content.Server/Flash/FlashSystem.cs +++ b/Content.Server/Flash/FlashSystem.cs @@ -1,4 +1,5 @@ using System.Linq; +using Content.Server._White.Flash; using Content.Server.Flash.Components; using Content.Shared.Flash.Components; using Content.Server.Light.EntitySystems; @@ -24,6 +25,8 @@ using Content.Shared.Traits.Assorted.Components; using Robust.Shared.Random; using Content.Shared.Eye.Blinding.Systems; +using Content.Shared.Standing; + namespace Content.Server.Flash { @@ -167,7 +170,39 @@ public void Flash(EntityUid target, } } - public void FlashArea(Entity source, EntityUid? user, float range, float duration, float slowTo = 0.8f, bool displayPopup = false, float probability = 1f, SoundSpecifier? sound = null) + // WD EDIT START + private void FlashStun(EntityUid target, float stunDuration, float knockdownDuration, float distance, float range) + { + if (stunDuration <= 0 && knockdownDuration <= 0) + return; + + if (TryComp(target, out var suppression)) + range = MathF.Min(range, suppression.MaxRange); + + var ev = new FlashbangedEvent(range); + RaiseLocalEvent(target, ev); + + range = MathF.Min(range, ev.MaxRange); + if (range <= 0f) + return; + + if (distance < 0f) + distance = 0f; + + if (distance > range) + return; + + var knockdownTime = float.Lerp(knockdownDuration, 0f, distance / range); + if (knockdownTime > 0f) + _stun.TryKnockdown(target, TimeSpan.FromSeconds(knockdownTime), true, DropHeldItemsBehavior.DropIfStanding); + + var stunTime = float.Lerp(stunDuration, 0f, distance / range); + if (stunTime > 0f) + _stun.TryStun(target, TimeSpan.FromSeconds(stunTime), true); + } + // WD EDIT END + + public void FlashArea(Entity source, EntityUid? user, float range, float duration, float slowTo = 0.8f, bool displayPopup = false, float probability = 1f, SoundSpecifier? sound = null, float stunTime = 0f, float knockdownTime = 0f) // WD EDIT { var transform = Transform(source); var mapPosition = _transform.GetMapCoordinates(transform); @@ -187,6 +222,11 @@ public void FlashArea(Entity source, EntityUid? user, float ran // They shouldn't have flash removed in between right? Flash(entity, user, source, duration, slowTo, displayPopup, flashableQuery.GetComponent(entity)); + + // WD EDIT START + var distance = (mapPosition.Position - _transform.GetMapCoordinates(entity).Position).Length(); + FlashStun(entity, stunTime, knockdownTime, distance, range); + // WD EDIT END } _audio.PlayPvs(sound, source, AudioParams.Default.WithVolume(1f).WithMaxDistance(3f)); @@ -251,6 +291,4 @@ public AfterFlashedEvent(EntityUid target, EntityUid? user, EntityUid? used) Used = used; } } - - } diff --git a/Content.Server/Speech/EntitySystems/StutteringSystem.cs b/Content.Server/Speech/EntitySystems/StutteringSystem.cs index d6e3c0b749..71090511d5 100644 --- a/Content.Server/Speech/EntitySystems/StutteringSystem.cs +++ b/Content.Server/Speech/EntitySystems/StutteringSystem.cs @@ -13,7 +13,7 @@ public sealed class StutteringSystem : SharedStutteringSystem [Dependency] private readonly IRobustRandom _random = default!; // Regex of characters to stutter. - private static readonly Regex Stutter = new(@"[b-df-hj-np-tv-wxyz]", + private static readonly Regex Stutter = new(@"[b-df-hj-np-tv-wxyz-б-вд-к-лмн-прст]", // WD EDIT RegexOptions.Compiled | RegexOptions.IgnoreCase); public override void Initialize() diff --git a/Content.Server/Stunnable/Components/KnockdownOnHitComponent.cs b/Content.Server/Stunnable/Components/KnockdownOnHitComponent.cs deleted file mode 100644 index b89e674ece..0000000000 --- a/Content.Server/Stunnable/Components/KnockdownOnHitComponent.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Content.Shared.Standing; - -namespace Content.Server.Stunnable.Components; - -[RegisterComponent] -public sealed partial class KnockdownOnHitComponent : Component -{ - [DataField] - public TimeSpan Duration = TimeSpan.FromSeconds(1); - - [DataField] - public DropHeldItemsBehavior DropHeldItemsBehavior = DropHeldItemsBehavior.NoDrop; - - [DataField] - public bool RefreshDuration = true; -} diff --git a/Content.Server/Stunnable/Systems/KnockdownOnHitSystem.cs b/Content.Server/Stunnable/Systems/KnockdownOnHitSystem.cs deleted file mode 100644 index d1300c54f0..0000000000 --- a/Content.Server/Stunnable/Systems/KnockdownOnHitSystem.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System.Linq; -using Content.Server.Stunnable.Components; -using Content.Shared.StatusEffect; -using Content.Shared.Stunnable.Events; -using Content.Shared.Weapons.Melee.Events; - -namespace Content.Server.Stunnable.Systems; - -public sealed class KnockdownOnHitSystem : EntitySystem -{ - [Dependency] private readonly StunSystem _stun = default!; - - public override void Initialize() - { - SubscribeLocalEvent(OnMeleeHit); - } - - private void OnMeleeHit(Entity entity, ref MeleeHitEvent args) - { - if (args.Direction.HasValue || !args.IsHit || !args.HitEntities.Any() || entity.Comp.Duration <= TimeSpan.Zero) - return; - - var ev = new KnockdownOnHitAttemptEvent(); - RaiseLocalEvent(entity, ref ev); - if (ev.Cancelled) - return; - - foreach (var target in args.HitEntities) - { - if (!TryComp(target, out StatusEffectsComponent? statusEffects)) - continue; - - _stun.TryKnockdown(target, - entity.Comp.Duration, - entity.Comp.RefreshDuration, - entity.Comp.DropHeldItemsBehavior, - statusEffects); - } - } -} diff --git a/Content.Server/Stunnable/Systems/StunbatonSystem.cs b/Content.Server/Stunnable/Systems/StunbatonSystem.cs index 4b52bf1fb6..2b10aa3cc1 100644 --- a/Content.Server/Stunnable/Systems/StunbatonSystem.cs +++ b/Content.Server/Stunnable/Systems/StunbatonSystem.cs @@ -11,6 +11,8 @@ using Content.Shared.Popups; using Content.Shared.PowerCell.Components; using Content.Shared.Stunnable; +using Content.Shared.Stunnable.Events; + namespace Content.Server.Stunnable.Systems { @@ -32,18 +34,25 @@ public override void Initialize() SubscribeLocalEvent(ToggleDone); SubscribeLocalEvent(OnChargeChanged); SubscribeLocalEvent(OnPowerCellChanged); // WD EDIT + SubscribeLocalEvent(OnKnockdownHitAttempt); // WD EDIT } private void OnStaminaHitAttempt(Entity entity, ref StaminaDamageOnHitAttemptEvent args) { // WD EDIT START - if (!_itemToggle.IsActivated(entity.Owner) - || !_battery.TryGetBatteryComponent(entity, out var battery, out var batteryUid) - || !_battery.TryUseCharge(batteryUid.Value, entity.Comp.EnergyPerUse, battery)) + if (!_itemToggle.IsActivated(entity.Owner) || TryUseCharge(entity)) args.Cancelled = true; // WD EDIT END } + // WD EDIT START + private void OnKnockdownHitAttempt(Entity entity, ref KnockdownOnHitAttemptEvent args) + { + if (!_itemToggle.IsActivated(entity.Owner) || TryUseCharge(entity)) + args.Cancelled = true; + } + // WD EDIT END + private void OnExamined(Entity entity, ref ExaminedEvent args) { var onMsg = _itemToggle.IsActivated(entity.Owner) @@ -126,6 +135,13 @@ private void CheckCharge(Entity entity) || battery.CurrentCharge < entity.Comp.EnergyPerUse) _itemToggle.TryDeactivate(entity.Owner, predicted: false); } + + private bool TryUseCharge(Entity entity) + { + return _battery.TryGetBatteryComponent(entity, out var battery, out var batteryUid) + && battery.CurrentCharge >= entity.Comp.EnergyPerUse + && _battery.TryUseCharge(batteryUid.Value, entity.Comp.EnergyPerUse / 2, battery); + } // WD EDIT END } } diff --git a/Content.Server/_White/Flash/FlashSoundSuppressionComponent.cs b/Content.Server/_White/Flash/FlashSoundSuppressionComponent.cs new file mode 100644 index 0000000000..4c57f939c5 --- /dev/null +++ b/Content.Server/_White/Flash/FlashSoundSuppressionComponent.cs @@ -0,0 +1,8 @@ +namespace Content.Server._White.Flash; + +[RegisterComponent] +public sealed partial class FlashSoundSuppressionComponent : Component +{ + [DataField] + public float MaxRange = 2f; +} diff --git a/Content.Server/_White/Flash/FlashSoundSuppressionSystem.cs b/Content.Server/_White/Flash/FlashSoundSuppressionSystem.cs new file mode 100644 index 0000000000..747a3080ad --- /dev/null +++ b/Content.Server/_White/Flash/FlashSoundSuppressionSystem.cs @@ -0,0 +1,19 @@ +using Content.Shared.Flash; +using Content.Shared.Inventory; + +namespace Content.Server._White.Flash; + +public sealed class FlashSoundSuppressionSystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent>(OnFlashbanged); + } + + private void OnFlashbanged(Entity ent, ref InventoryRelayedEvent args) + { + args.Args.MaxRange = MathF.Min(args.Args.MaxRange, ent.Comp.MaxRange); + } +} diff --git a/Content.Server/_White/Knockdown/BaseKnockdownOnComponent.cs b/Content.Server/_White/Knockdown/BaseKnockdownOnComponent.cs new file mode 100644 index 0000000000..ff4186f183 --- /dev/null +++ b/Content.Server/_White/Knockdown/BaseKnockdownOnComponent.cs @@ -0,0 +1,22 @@ +using Content.Shared.Standing; + + +namespace Content.Server._White.Knockdown; + +public abstract partial class BaseKnockdownOnComponent : Component +{ + [DataField] + public TimeSpan Delay = TimeSpan.FromSeconds(2); + + [DataField] + public TimeSpan KnockdownTime = TimeSpan.FromSeconds(5); + + [DataField] + public DropHeldItemsBehavior DropHeldItemsBehavior = DropHeldItemsBehavior.DropIfStanding; + + [DataField] + public TimeSpan JitterTime = TimeSpan.FromSeconds(15); + + [DataField] + public TimeSpan StutterTime = TimeSpan.FromSeconds(15); +} diff --git a/Content.Server/_White/Knockdown/KnockComponent.cs b/Content.Server/_White/Knockdown/KnockComponent.cs new file mode 100644 index 0000000000..cc8ce45c81 --- /dev/null +++ b/Content.Server/_White/Knockdown/KnockComponent.cs @@ -0,0 +1,17 @@ +using Content.Shared.Standing; + + +namespace Content.Server._White.Knockdown; + +[RegisterComponent] +public sealed partial class KnockComponent : Component +{ + [DataField] + public TimeSpan Delay = TimeSpan.FromSeconds(2); + + [DataField] + public TimeSpan KnockdownTime = TimeSpan.FromSeconds(5); + + [DataField] + public DropHeldItemsBehavior DropHeldItemsBehavior = DropHeldItemsBehavior.DropIfStanding; +} diff --git a/Content.Server/_White/Knockdown/KnockdownOnCollideComponent.cs b/Content.Server/_White/Knockdown/KnockdownOnCollideComponent.cs new file mode 100644 index 0000000000..65f2f7a3a9 --- /dev/null +++ b/Content.Server/_White/Knockdown/KnockdownOnCollideComponent.cs @@ -0,0 +1,4 @@ +namespace Content.Server._White.Knockdown; + +[RegisterComponent] +public sealed partial class KnockdownOnCollideComponent : BaseKnockdownOnComponent; diff --git a/Content.Server/_White/Knockdown/KnockdownOnHitComponent.cs b/Content.Server/_White/Knockdown/KnockdownOnHitComponent.cs new file mode 100644 index 0000000000..11bdb75e28 --- /dev/null +++ b/Content.Server/_White/Knockdown/KnockdownOnHitComponent.cs @@ -0,0 +1,4 @@ +namespace Content.Server._White.Knockdown; + +[RegisterComponent] +public sealed partial class KnockdownOnHitComponent : BaseKnockdownOnComponent; diff --git a/Content.Server/_White/Knockdown/KnockdownSystem.cs b/Content.Server/_White/Knockdown/KnockdownSystem.cs new file mode 100644 index 0000000000..b5222ebac3 --- /dev/null +++ b/Content.Server/_White/Knockdown/KnockdownSystem.cs @@ -0,0 +1,79 @@ +using Content.Server.Jittering; +using Content.Server.Speech.EntitySystems; +using Content.Server.Stunnable; +using Content.Shared.Projectiles; +using Content.Shared.StatusEffect; +using Content.Shared.Stunnable.Events; +using Content.Shared.Throwing; +using Content.Shared.Weapons.Melee.Events; +using Robust.Shared.Timing; + +namespace Content.Server._White.Knockdown; + +public sealed class KnockdownSystem : EntitySystem +{ + [Dependency] private readonly StunSystem _sharedStun = default!; + [Dependency] private readonly JitteringSystem _jitter = default!; + [Dependency] private readonly StutteringSystem _stutter = default!; + [Dependency] private readonly IGameTiming _timing = default!; + + public override void Initialize() + { + SubscribeLocalEvent(OnMeleeHit); + SubscribeLocalEvent(OnProjectileHit); + SubscribeLocalEvent(OnThrowDoHit); + } + + private void OnMeleeHit(EntityUid uid, KnockdownOnHitComponent component, MeleeHitEvent args) + { + var ev = new KnockdownOnHitAttemptEvent(); + RaiseLocalEvent(uid, ref ev); + if (ev.Cancelled) + return; + + foreach (var hitEntity in args.HitEntities) + Knockdown(hitEntity, component); + } + + private void OnProjectileHit(EntityUid uid, KnockdownOnCollideComponent component, ProjectileHitEvent args) => Knockdown(args.Target, component); + + private void OnThrowDoHit(EntityUid uid, KnockdownOnCollideComponent component, ThrowDoHitEvent args) => Knockdown(args.Target, component); + + private void Knockdown(EntityUid target, BaseKnockdownOnComponent component) + { + if (!TryComp(target, out var statusEffects)) + return; + + if (component.JitterTime > TimeSpan.Zero) + _jitter.DoJitter(target, component.JitterTime, true, status: statusEffects); + + if (component.StutterTime > TimeSpan.Zero) + _stutter.DoStutter(target, component.StutterTime, true, statusEffects); + + if (component.Delay == TimeSpan.Zero) + { + _sharedStun.TryKnockdown(target, component.KnockdownTime, true, statusEffects); + return; + } + + var knockdown = EnsureComp(target); + knockdown.Delay = _timing.CurTime + component.Delay; + knockdown.KnockdownTime = component.KnockdownTime; + knockdown.DropHeldItemsBehavior = component.DropHeldItemsBehavior; + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var delayedKnockdown)) + { + if (delayedKnockdown.Delay > _timing.CurTime) + continue; + + _sharedStun.TryKnockdown(uid, delayedKnockdown.KnockdownTime, true, delayedKnockdown.DropHeldItemsBehavior); + RemCompDeferred(uid); + } + } +} diff --git a/Content.Shared/Flash/Components/FlashOnTriggerComponent.cs b/Content.Shared/Flash/Components/FlashOnTriggerComponent.cs index 7658ca0ae5..2c830cdda1 100644 --- a/Content.Shared/Flash/Components/FlashOnTriggerComponent.cs +++ b/Content.Shared/Flash/Components/FlashOnTriggerComponent.cs @@ -10,4 +10,12 @@ public sealed partial class FlashOnTriggerComponent : Component [DataField] public float Range = 1.0f; [DataField] public float Duration = 8.0f; [DataField] public float Probability = 1.0f; + + // WD EDIT START + [DataField] + public float StunTime; + + [DataField] + public float KnockdownTime; + // WD EDIT END } diff --git a/Content.Shared/Flash/SharedFlashSystem.cs b/Content.Shared/Flash/SharedFlashSystem.cs index 2646ae5e69..6e0a6abf6c 100644 --- a/Content.Shared/Flash/SharedFlashSystem.cs +++ b/Content.Shared/Flash/SharedFlashSystem.cs @@ -1,3 +1,4 @@ +using Content.Shared.Inventory; using Robust.Shared.GameStates; namespace Content.Shared.Flash @@ -16,4 +17,18 @@ private static void OnFlashableGetState(EntityUid uid, FlashableComponent compon args.State = new FlashableComponentState(component.Duration, component.LastFlash, component.EyeDamageChance, component.EyeDamage, component.DurationMultiplier); } } + + // WD EDIT START + public sealed class FlashbangedEvent : EntityEventArgs, IInventoryRelayEvent + { + public float MaxRange; + + public SlotFlags TargetSlots => SlotFlags.EARS | SlotFlags.HEAD; + + public FlashbangedEvent(float maxRange) + { + MaxRange = maxRange; + } + } + // WD EDIT END } diff --git a/Content.Shared/Inventory/InventorySystem.Relay.cs b/Content.Shared/Inventory/InventorySystem.Relay.cs index 39e10415f8..4b92ce82b7 100644 --- a/Content.Shared/Inventory/InventorySystem.Relay.cs +++ b/Content.Shared/Inventory/InventorySystem.Relay.cs @@ -4,6 +4,7 @@ using Content.Shared.Electrocution; using Content.Shared.Explosion; using Content.Shared.Eye.Blinding.Systems; +using Content.Shared.Flash; using Content.Shared.IdentityManagement.Components; using Content.Shared.Inventory.Events; using Content.Shared.Movement.Systems; @@ -30,6 +31,7 @@ public void InitializeRelay() SubscribeLocalEvent(RelayInventoryEvent); SubscribeLocalEvent(RelayInventoryEvent); SubscribeLocalEvent(RelayInventoryEvent); + SubscribeLocalEvent(RelayInventoryEvent); // WD EDIT SubscribeLocalEvent(RelayInventoryEvent); // by-ref events diff --git a/Content.Shared/SimpleStation14/Clothing/Systems/ClothingGrantingSystem.cs b/Content.Shared/SimpleStation14/Clothing/Systems/ClothingGrantingSystem.cs index 5fbc83a4b0..c5fa8ea4eb 100644 --- a/Content.Shared/SimpleStation14/Clothing/Systems/ClothingGrantingSystem.cs +++ b/Content.Shared/SimpleStation14/Clothing/Systems/ClothingGrantingSystem.cs @@ -28,9 +28,9 @@ private void OnCompEquip(EntityUid uid, ClothingGrantComponentComponent componen if (!clothing.Slots.HasFlag(args.SlotFlags)) return; - if (component.Components.Count > 1) + if (component.Components.Count > 8) // WD EDIT { - Logger.Error("Although a component registry supports multiple components, we cannot bookkeep more than 1 component for ClothingGrantComponent at this time."); + Logger.Error("Although a component registry supports multiple components, we cannot bookkeep more than 8 component for ClothingGrantComponent at this time."); // WD EDIT return; } @@ -46,9 +46,9 @@ private void OnCompEquip(EntityUid uid, ClothingGrantComponentComponent componen var temp = (object) newComp; _serializationManager.CopyTo(data.Component, ref temp); EntityManager.AddComponent(args.Equipee, (Component)temp!); - - component.IsActive = true; } + + component.IsActive = true; // WD EDIT } private void OnCompUnequip(EntityUid uid, ClothingGrantComponentComponent component, GotUnequippedEvent args) diff --git a/Content.Shared/Stunnable/KnockedDownComponent.cs b/Content.Shared/Stunnable/KnockedDownComponent.cs index 865c69bf6e..0a6c634890 100644 --- a/Content.Shared/Stunnable/KnockedDownComponent.cs +++ b/Content.Shared/Stunnable/KnockedDownComponent.cs @@ -14,7 +14,7 @@ public sealed partial class KnockedDownComponent : Component public SoundSpecifier StunAttemptSound = new SoundPathSpecifier("/Audio/Effects/thudswoosh.ogg"); [DataField] - public DropHeldItemsBehavior DropHeldItemsBehavior = DropHeldItemsBehavior.DropIfStanding; + public DropHeldItemsBehavior DropHeldItemsBehavior = DropHeldItemsBehavior.AlwaysDrop; [ViewVariables, AutoNetworkedField] public float HelpTimer = 0f; diff --git a/Content.Shared/Stunnable/SharedStunSystem.cs b/Content.Shared/Stunnable/SharedStunSystem.cs index ad36ba9329..0d2700084c 100644 --- a/Content.Shared/Stunnable/SharedStunSystem.cs +++ b/Content.Shared/Stunnable/SharedStunSystem.cs @@ -84,15 +84,15 @@ private void OnMobStateChanged(EntityUid uid, MobStateComponent component, MobSt case MobState.Alive: break; case MobState.Critical: - { - _statusEffect.TryRemoveStatusEffect(uid, "Stun"); - break; - } + { + _statusEffect.TryRemoveStatusEffect(uid, "Stun"); + break; + } case MobState.Dead: - { - _statusEffect.TryRemoveStatusEffect(uid, "Stun"); - break; - } + { + _statusEffect.TryRemoveStatusEffect(uid, "Stun"); + break; + } case MobState.Invalid: default: return; @@ -108,7 +108,7 @@ private void UpdateCanMove(EntityUid uid, StunnedComponent component, EntityEven private void OnKnockInit(EntityUid uid, KnockedDownComponent component, ComponentInit args) { RaiseNetworkEvent(new CheckAutoGetUpEvent(GetNetEntity(uid))); - _layingDown.TryLieDown(uid, null, null, component.DropHeldItemsBehavior); + _layingDown.TryLieDown(uid, null, null, component.DropHeldItemsBehavior); // WD EDIT } private void OnKnockShutdown(EntityUid uid, KnockedDownComponent component, ComponentShutdown args) diff --git a/Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs b/Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs index a60e921559..4157f56a1f 100644 --- a/Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs +++ b/Content.Shared/Weapons/Melee/MeleeWeaponComponent.cs @@ -133,6 +133,9 @@ public sealed partial class MeleeWeaponComponent : Component // WD EDIT START [ViewVariables(VVAccess.ReadWrite), DataField, AutoNetworkedField] public EntProtoId DisarmAnimation = "WeaponArcDisarm"; + + [DataField, AutoNetworkedField] + public bool CanHeavyAttack = true; // WD EDIT END /// diff --git a/Content.Shared/_White/Collision/Knockdown/KnockdownOnCollideSystem.cs b/Content.Shared/_White/Collision/Knockdown/KnockdownOnCollideSystem.cs deleted file mode 100644 index dcc6b38377..0000000000 --- a/Content.Shared/_White/Collision/Knockdown/KnockdownOnCollideSystem.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Content.Shared.Projectiles; -using Content.Shared.Standing; -using Content.Shared.Throwing; - -namespace Content.Shared._White.Collision.Knockdown; - -public sealed class KnockdownOnCollideSystem : EntitySystem -{ - [Dependency] private readonly SharedLayingDownSystem _layingDown = default!; - - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(OnProjectileHit); - SubscribeLocalEvent(OnEntityHit); - } - - private void OnEntityHit(Entity ent, ref ThrowDoHitEvent args) - { - ApplyEffects(args.Target, ent.Comp); - } - - private void OnProjectileHit(Entity ent, ref ProjectileHitEvent args) - { - ApplyEffects(args.Target, ent.Comp); - } - - private void ApplyEffects(EntityUid target, KnockdownOnCollideComponent component) - { - _layingDown.TryLieDown(target, null, null, component.Behavior); - } -} diff --git a/Content.Shared/_White/Collision/Knockdown/KnockdownOnCollideComponent.cs b/Content.Shared/_White/Collision/LayDown/LayDownOnCollideComponent.cs similarity index 54% rename from Content.Shared/_White/Collision/Knockdown/KnockdownOnCollideComponent.cs rename to Content.Shared/_White/Collision/LayDown/LayDownOnCollideComponent.cs index 078f01b952..215def75b4 100644 --- a/Content.Shared/_White/Collision/Knockdown/KnockdownOnCollideComponent.cs +++ b/Content.Shared/_White/Collision/LayDown/LayDownOnCollideComponent.cs @@ -1,9 +1,9 @@ using Content.Shared.Standing; -namespace Content.Shared._White.Collision.Knockdown; +namespace Content.Shared._White.Collision.LayDown; [RegisterComponent] -public sealed partial class KnockdownOnCollideComponent : Component +public sealed partial class LayDownOnCollideComponent : Component { [DataField] public DropHeldItemsBehavior Behavior = DropHeldItemsBehavior.NoDrop; diff --git a/Content.Shared/_White/Collision/LayDown/LayDownOnCollideSystem.cs b/Content.Shared/_White/Collision/LayDown/LayDownOnCollideSystem.cs new file mode 100644 index 0000000000..53678ac922 --- /dev/null +++ b/Content.Shared/_White/Collision/LayDown/LayDownOnCollideSystem.cs @@ -0,0 +1,36 @@ +using Content.Shared.Projectiles; +using Content.Shared.Standing; +using Content.Shared.Throwing; + +namespace Content.Shared._White.Collision.LayDown; + +public sealed class LayDownOnCollideSystem : EntitySystem +{ + [Dependency] private readonly SharedLayingDownSystem _layingDown = default!; + + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnProjectileHit); + SubscribeLocalEvent(OnEntityHit); + } + + private void OnEntityHit(Entity ent, ref ThrowDoHitEvent args) + { + ApplyEffects(args.Target, ent.Comp); + } + + private void OnProjectileHit(Entity ent, ref ProjectileHitEvent args) + { + ApplyEffects(args.Target, ent.Comp); + } + + private void ApplyEffects(EntityUid target, LayDownOnCollideComponent component) + { + if (!Exists(target)) + return; + + _layingDown.TryLieDown(target, null, null, component.Behavior); + } +} diff --git a/Resources/Locale/en-US/_white/alerts/alerts.ftl b/Resources/Locale/en-US/_white/alerts/alerts.ftl index d64317cb0a..ffb066dae0 100644 --- a/Resources/Locale/en-US/_white/alerts/alerts.ftl +++ b/Resources/Locale/en-US/_white/alerts/alerts.ftl @@ -1,2 +1,5 @@ alerts-blocked-name = Recently blocked -alerts-blocked-desc = I can't block for a while! \ No newline at end of file +alerts-blocked-desc = I can't block for a while! + +alerts-knockdown-name = [color=yellow]Knocked down[/color] +alerts-knockdown-desc = You're [color=yellow]knocked down[/color]! Something is impairing your ability to get up. diff --git a/Resources/Locale/ru-RU/_white/alerts/alerts.ftl b/Resources/Locale/ru-RU/_white/alerts/alerts.ftl index b622781c1d..82184c0a0d 100644 --- a/Resources/Locale/ru-RU/_white/alerts/alerts.ftl +++ b/Resources/Locale/ru-RU/_white/alerts/alerts.ftl @@ -1,2 +1,5 @@ alerts-blocked-name = Атака заблокирована -alerts-blocked-desc = Невозможно блокировать некоторое время. \ No newline at end of file +alerts-blocked-desc = Невозможно блокировать некоторое время. + +alerts-knockdown-name = [color=yellow]Сбиты с ног[/color] +alerts-knockdown-desc = Вы [color=yellow]сбиты с ног[/color]! Что-то мешает вам встать. diff --git a/Resources/Locale/ru-RU/prototypes/entities/objects/weapons/throwable/bola.ftl b/Resources/Locale/ru-RU/prototypes/entities/objects/weapons/throwable/bola.ftl index f9af55ba4a..6aeca0d9a5 100644 --- a/Resources/Locale/ru-RU/prototypes/entities/objects/weapons/throwable/bola.ftl +++ b/Resources/Locale/ru-RU/prototypes/entities/objects/weapons/throwable/bola.ftl @@ -1,2 +1,4 @@ ent-Bola = бола - .desc = Скрепленные с металлом кабельные стяжки. \ No newline at end of file + .desc = Скрепленные с металлом кабельные стяжки. +ent-BolaEnergy = энергобола + .desc = Совершенное слияние технологии и справедливости для отлова преступников. diff --git a/Resources/Prototypes/Alerts/alerts.yml b/Resources/Prototypes/Alerts/alerts.yml index 0dee8c4089..fc3725fd4b 100644 --- a/Resources/Prototypes/Alerts/alerts.yml +++ b/Resources/Prototypes/Alerts/alerts.yml @@ -18,6 +18,7 @@ - category: Piloting - alertType: Corporeal - alertType: Stun + - alertType: KnockedDown # WD EDIT - category: Breathing # Vox gang not calling this oxygen - category: Pressure - alertType: Bleed @@ -454,13 +455,6 @@ minSeverity: 0 maxSeverity: 1 -# WD EDIT -- type: alert - id: RecentlyBlocked - icons: [ /Textures/Objects/Weapons/Melee/shields.rsi/buckler-icon.png ] - name: alerts-blocked-name - description: alerts-blocked-desc - - type: alert id: Debug1 icons: @@ -627,3 +621,21 @@ state: deflecting0 name: alerts-deflecting-name description: alerts-deflecting-desc + +# WD EDIT START +- type: alert + id: KnockedDown + icons: + - sprite: /Textures/_White/Interface/Alerts/knockdown.rsi + state: knockdown + name: alerts-knockdown-name + description: alerts-knockdown-desc + +- type: alert + id: RecentlyBlocked + icons: + - sprite: /Textures/Objects/Weapons/Melee/shields.rsi + state: buckler-icon + name: alerts-blocked-name + description: alerts-blocked-desc +# WD EDIT END diff --git a/Resources/Prototypes/Entities/Clothing/Ears/headsets_alt.yml b/Resources/Prototypes/Entities/Clothing/Ears/headsets_alt.yml index 5dfa1df150..9cfb20ffc0 100644 --- a/Resources/Prototypes/Entities/Clothing/Ears/headsets_alt.yml +++ b/Resources/Prototypes/Entities/Clothing/Ears/headsets_alt.yml @@ -9,6 +9,7 @@ state: icon_alt - type: Clothing equippedPrefix: alt + - type: FlashSoundSuppression # WD EDIT - type: entity parent: ClothingHeadsetAlt diff --git a/Resources/Prototypes/Entities/Clothing/Head/hardsuit-helmets.yml b/Resources/Prototypes/Entities/Clothing/Head/hardsuit-helmets.yml index c685165de6..c8afe65812 100644 --- a/Resources/Prototypes/Entities/Clothing/Head/hardsuit-helmets.yml +++ b/Resources/Prototypes/Entities/Clothing/Head/hardsuit-helmets.yml @@ -199,6 +199,9 @@ Slash: 0.9 Piercing: 0.9 Heat: 0.9 + - type: FlashImmunity # WD EDIT + - type: FlashSoundSuppression # WD EDIT + #Brigmedic Hardsuit - type: entity @@ -226,6 +229,8 @@ - type: PressureProtection highPressureMultiplier: 0.6 lowPressureMultiplier: 1000 + - type: FlashImmunity # WD EDIT + - type: FlashSoundSuppression # WD EDIT #Warden's Hardsuit - type: entity @@ -251,6 +256,8 @@ Slash: 0.9 Piercing: 0.9 Heat: 0.9 + - type: FlashImmunity # WD EDIT + - type: FlashSoundSuppression # WD EDIT #Captain's Hardsuit - type: entity @@ -269,6 +276,8 @@ lowPressureMultiplier: 1000 - type: PointLight color: "#9CF4FF" + - type: FlashImmunity # WD EDIT + - type: FlashSoundSuppression # WD EDIT #Chief Engineer's Hardsuit - type: entity @@ -348,6 +357,8 @@ Slash: 0.9 Piercing: 0.9 Heat: 0.9 + - type: FlashImmunity # WD EDIT + - type: FlashSoundSuppression # WD EDIT #Luxury Mining Hardsuit - type: entity @@ -393,6 +404,9 @@ Slash: 0.9 Piercing: 0.9 Heat: 0.9 + - type: EyeProtection # WD EDIT + - type: FlashImmunity # WD EDIT + - type: FlashSoundSuppression # WD EDIT #Blood-red Medic Hardsuit - type: entity @@ -418,6 +432,9 @@ Slash: 0.9 Piercing: 0.9 Heat: 0.9 + - type: EyeProtection # WD EDIT + - type: FlashImmunity # WD EDIT + - type: FlashSoundSuppression # WD EDIT #Syndicate Elite Hardsuit - type: entity @@ -447,6 +464,9 @@ Slash: 0.9 Piercing: 0.9 Heat: 0.9 + - type: EyeProtection # WD EDIT + - type: FlashImmunity # WD EDIT + - type: FlashSoundSuppression # WD EDIT #Syndicate Commander Hardsuit - type: entity @@ -472,6 +492,9 @@ Slash: 0.9 Piercing: 0.9 Heat: 0.9 + - type: EyeProtection # WD EDIT + - type: FlashImmunity # WD EDIT + - type: FlashSoundSuppression # WD EDIT #Cybersun Juggernaut Hardsuit - type: entity @@ -495,6 +518,9 @@ Slash: 0.9 Piercing: 0.9 Heat: 0.9 + - type: EyeProtection # WD EDIT + - type: FlashImmunity # WD EDIT + - type: FlashSoundSuppression # WD EDIT #Wizard Hardsuit - type: entity @@ -593,6 +619,9 @@ Slash: 0.9 Piercing: 0.9 Heat: 0.9 + - type: EyeProtection # WD EDIT + - type: FlashImmunity # WD EDIT + - type: FlashSoundSuppression # WD EDIT #ERT Chaplain Hardsuit - type: entity @@ -608,6 +637,9 @@ sprite: Clothing/Head/Hardsuits/ERThelmets/ertchaplain.rsi - type: PointLight color: "#ffffff" + - type: EyeProtection # WD EDIT + - type: FlashImmunity # WD EDIT + - type: FlashSoundSuppression # WD EDIT #ERT Engineer Hardsuit - type: entity @@ -630,6 +662,9 @@ Slash: 0.9 Piercing: 0.9 Heat: 0.9 + - type: EyeProtection # WD EDIT + - type: FlashImmunity # WD EDIT + - type: FlashSoundSuppression # WD EDIT #ERT Medical Hardsuit - type: entity @@ -645,6 +680,9 @@ sprite: Clothing/Head/Hardsuits/ERThelmets/ertmedical.rsi - type: PointLight color: "#adffec" + - type: EyeProtection # WD EDIT + - type: FlashImmunity # WD EDIT + - type: FlashSoundSuppression # WD EDIT #ERT Security Hardsuit - type: entity @@ -667,6 +705,9 @@ Slash: 0.9 Piercing: 0.9 Heat: 0.9 + - type: EyeProtection # WD EDIT + - type: FlashImmunity # WD EDIT + - type: FlashSoundSuppression # WD EDIT #ERT Janitor Hardsuit - type: entity @@ -682,6 +723,9 @@ sprite: Clothing/Head/Hardsuits/ERThelmets/ertjanitor.rsi - type: PointLight color: "#cbadff" + - type: EyeProtection # WD EDIT + - type: FlashImmunity # WD EDIT + - type: FlashSoundSuppression # WD EDIT #CBURN Hardsuit - type: entity @@ -721,6 +765,9 @@ Slash: 0.9 Piercing: 0.9 Heat: 0.9 + - type: EyeProtection # WD EDIT + - type: FlashImmunity # WD EDIT + - type: FlashSoundSuppression # WD EDIT #Deathsquad Hardsuit - type: entity @@ -751,6 +798,10 @@ component: - type: ThermalVision - type: NightVision + - type: EyeProtection + - type: FlashImmunity + - type: FlashSoundSuppression + maxRange: 0 # WD EDIT END #MISC. HARDSUITS diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml index acf2253223..1f0f6c7728 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml @@ -211,9 +211,7 @@ soundHit: path: "/Audio/Weapons/Guns/Hits/taser_hit.ogg" forceSound: true - - type: StunOnCollide - stunAmount: 5 - knockdownAmount: 5 + - type: KnockdownOnCollide # WD EDIT - type: entity name : disabler bolt @@ -745,6 +743,8 @@ - state: grenade - type: FlashOnTrigger range: 7 + stunTime: 2 # WD EDIT + knockdownTime: 10 # WD EDIT - type: SpawnOnTrigger proto: GrenadeFlashEffect - type: ActiveTimerTrigger diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/stunprod.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/stunprod.yml index 772379cc42..3b034b4fbd 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/stunprod.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/stunprod.yml @@ -25,21 +25,15 @@ - type: Stunbaton energyPerUse: 120 - type: MeleeWeapon - wideAnimationRotation: -135 - attackRate: 0.8 + attackRate: 0.4 # WD EDIT range: 1.4 damage: types: Blunt: 7.5 bluntStaminaDamageFactor: 2.0 - heavyRateModifier: 0.8 - heavyDamageBaseModifier: 1.2 - heavyStaminaCost: 5 - maxTargets: 3 - angle: 60 - animation: WeaponArcThrust + canHeavyAttack: false # WD EDIT - type: StaminaDamageOnHit - damage: 22 + damage: 35 # WD EDIT sound: /Audio/Weapons/egloves.ogg - type: StaminaDamageOnCollide damage: 22 @@ -65,6 +59,8 @@ - type: ContainerContainer containers: cell_slot: !type:ContainerSlot {} + - type: KnockdownOnHit # WD EDIT + knockdownTime: 3 - type: entity name: stun prod diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Melee/telescopic_baton.yml b/Resources/Prototypes/Entities/Objects/Weapons/Melee/telescopic_baton.yml index 5e797c8536..5f3901e706 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Melee/telescopic_baton.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Melee/telescopic_baton.yml @@ -31,16 +31,16 @@ - type: UseDelay delay: 2 - type: TelescopicBaton - - type: KnockdownOnHit - duration: 1.5 - dropHeldItemsBehavior: NoDrop + - type: KnockdownOnHit # WD EDIT + jitterTime: 0 + stutterTime: 0 + delay: 0 + knockdownTime: 1 - type: MeleeWeapon attackRate: 0.8 bluntStaminaDamageFactor: 1.5 - heavyDamageBaseModifier: 1.2 - heavyStaminaCost: 5 maxTargets: 1 - angle: 40 + canHeavyAttack: false damage: types: Blunt: 1 @@ -62,7 +62,7 @@ - type: TelescopicBaton attackTimeframe: 300 # one minute after activation - type: KnockdownOnHit - duration: 60 # + knockdownTime: 60 # WD EDIT - type: MeleeWeapon attackRate: 1.2 - type: ItemToggleMeleeWeapon diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Throwable/bola.yml b/Resources/Prototypes/Entities/Objects/Weapons/Throwable/bola.yml index 7bbd0fe893..2bcc49b79f 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Throwable/bola.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Throwable/bola.yml @@ -14,18 +14,15 @@ sound: /Audio/Weapons/bolathrow.ogg - type: EmitSoundOnLand sound: /Audio/Effects/snap.ogg - - type: DamageOnLand - damage: - types: - Blunt: 5 - type: Ensnaring freeTime: 2.0 breakoutTime: 3.5 walkSpeed: 0.7 sprintSpeed: 0.7 - staminaDamage: 55 + staminaDamage: 20 # WD EDIT canThrowTrigger: true canMoveBreakout: true + - type: LayDownOnCollide # WD EDIT - type: entity name: bola @@ -55,6 +52,12 @@ collection: MetalBreak - !type:DoActsBehavior acts: [ "Destruction" ] + # WD EDIT START + - type: DamageOnLand + damage: + types: + Blunt: 5 + # WD EDIT END - type: entity name: energy bola @@ -62,11 +65,21 @@ parent: BaseBola description: An advanced hardlight criminal entangling tool. Otherwise known as an expensive piece of string. components: + # WD EDIT START + - type: Item + size: Small + # WD EDIT END - type: Sprite sprite: Objects/Weapons/Throwable/energy_bola.rsi - - type: DamageOnLand - damage: - types: - Heat: 5 - - type: Ensnaring - destroyOnRemove: true + # WD EDIT START + - type: EmitSoundOnLand + sound: + collection: sparks + - type: KnockdownOnCollide + knockdownTime: 1 + jitterTime: 7 + stutterTime: 7 + - type: Tag + tags: + - SecBeltEquip + # WD EDIT END \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Throwable/grenades.yml b/Resources/Prototypes/Entities/Objects/Weapons/Throwable/grenades.yml index b39303d9ed..e72cbfe3ec 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/Throwable/grenades.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/Throwable/grenades.yml @@ -67,6 +67,8 @@ sprite: Objects/Weapons/Grenades/flashbang.rsi - type: FlashOnTrigger range: 7 + stunTime: 2 # WD EDIT + knockdownTime: 10 # WD EDIT - type: SoundOnTrigger sound: path: "/Audio/Effects/flash_bang.ogg" diff --git a/Resources/Prototypes/Entities/Objects/Weapons/security.yml b/Resources/Prototypes/Entities/Objects/Weapons/security.yml index 10124f2601..31cf704632 100644 --- a/Resources/Prototypes/Entities/Objects/Weapons/security.yml +++ b/Resources/Prototypes/Entities/Objects/Weapons/security.yml @@ -10,7 +10,7 @@ - state: stunbaton_off map: [ "enum.ToggleVisuals.Layer" ] - type: Stunbaton - energyPerUse: 50 + energyPerUse: 100 # WD EDIT - type: ItemToggle predictable: false soundActivate: @@ -30,17 +30,15 @@ types: Blunt: 0 - type: MeleeWeapon - wideAnimationRotation: -135 damage: types: Blunt: 7 bluntStaminaDamageFactor: 2.0 - heavyRateModifier: 0.75 - maxTargets: 3 + canHeavyAttack: false # WD EDIT + attackRate: 0.4 # WD EDIT angle: 60 - animation: WeaponArcSlash - type: StaminaDamageOnHit - damage: 35 + damage: 55 # WD EDIT sound: /Audio/Weapons/egloves.ogg - type: StaminaDamageOnCollide damage: 35 @@ -87,6 +85,7 @@ - type: GuideHelp guides: - Security + - type: KnockdownOnHit # WD EDIT - type: entity name: truncheon diff --git a/Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Projectiles/bolts..yml b/Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Projectiles/bolts..yml index 4468ff1cd7..b90d5622d1 100644 --- a/Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Projectiles/bolts..yml +++ b/Resources/Prototypes/_White/Entities/Objects/Weapons/Guns/Projectiles/bolts..yml @@ -26,6 +26,6 @@ hard: false mask: - Opaque - - type: KnockdownOnCollide + - type: LayDownOnCollide behavior: AlwaysDrop - type: BlurOnCollide \ No newline at end of file diff --git a/Resources/Prototypes/status_effects.yml b/Resources/Prototypes/status_effects.yml index 0c29d79d5c..1e454d25ef 100644 --- a/Resources/Prototypes/status_effects.yml +++ b/Resources/Prototypes/status_effects.yml @@ -7,7 +7,7 @@ - type: statusEffect id: KnockedDown - alert: Stun + alert: KnockedDown # WD EDIT - type: statusEffect id: SlowedDown diff --git a/Resources/Textures/_White/Interface/Alerts/knockdown.rsi/knockdown.png b/Resources/Textures/_White/Interface/Alerts/knockdown.rsi/knockdown.png new file mode 100644 index 0000000000..dcefa1f58d Binary files /dev/null and b/Resources/Textures/_White/Interface/Alerts/knockdown.rsi/knockdown.png differ diff --git a/Resources/Textures/_White/Interface/Alerts/knockdown.rsi/meta.json b/Resources/Textures/_White/Interface/Alerts/knockdown.rsi/meta.json new file mode 100644 index 0000000000..ccfa26f5c9 --- /dev/null +++ b/Resources/Textures/_White/Interface/Alerts/knockdown.rsi/meta.json @@ -0,0 +1,14 @@ +{ + "version": 1, + "license": "CC-BY-SA-4.0", + "copyright": "Made by WWDP Team", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "knockdown" + } + ] +} \ No newline at end of file