Crawling Part 1: The Knockdownening (#36881)
Co-authored-by: slarticodefast <161409025+slarticodefast@users.noreply.github.com> Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com> Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> Co-authored-by: Princess Cheeseballs <66055347+Pronana@users.noreply.github.com> Co-authored-by: ScarKy0 <scarky0@onet.eu>
This commit is contained in:
committed by
GitHub
parent
cfb0a95035
commit
dec2d42a1d
@@ -1,12 +1,13 @@
|
||||
using Content.Shared.ActionBlocker;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Inventory.Events;
|
||||
using Content.Shared.Item;
|
||||
using Content.Shared.Bed.Sleep;
|
||||
using Content.Shared.Damage.Components;
|
||||
using Content.Shared.Damage.Systems;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Hands;
|
||||
using Content.Shared.Mobs;
|
||||
using Content.Shared.Mobs.Components;
|
||||
@@ -17,9 +18,7 @@ using Content.Shared.StatusEffect;
|
||||
using Content.Shared.Throwing;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Physics.Events;
|
||||
using Robust.Shared.Physics.Systems;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Shared.Stunnable;
|
||||
@@ -27,40 +26,28 @@ namespace Content.Shared.Stunnable;
|
||||
public abstract partial class SharedStunSystem : EntitySystem
|
||||
{
|
||||
[Dependency] protected readonly ActionBlockerSystem Blocker = default!;
|
||||
[Dependency] protected readonly AlertsSystem Alerts = default!;
|
||||
[Dependency] protected readonly IGameTiming GameTiming = default!;
|
||||
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
||||
[Dependency] private readonly EntityWhitelistSystem _entityWhitelist = default!;
|
||||
[Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifier = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] protected readonly SharedAppearanceSystem Appearance = default!;
|
||||
[Dependency] private readonly EntityWhitelistSystem _entityWhitelist = default!;
|
||||
[Dependency] private readonly StandingStateSystem _standingState = default!;
|
||||
[Dependency] protected readonly SharedDoAfterSystem DoAfter = default!;
|
||||
[Dependency] protected readonly SharedStaminaSystem Stamina = default!;
|
||||
[Dependency] private readonly StatusEffectsSystem _statusEffect = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Friction modifier for knocked down players.
|
||||
/// Doesn't make them faster but makes them slow down... slower.
|
||||
/// </summary>
|
||||
public const float KnockDownModifier = 0.2f;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
SubscribeLocalEvent<KnockedDownComponent, ComponentInit>(OnKnockInit);
|
||||
SubscribeLocalEvent<KnockedDownComponent, ComponentShutdown>(OnKnockShutdown);
|
||||
SubscribeLocalEvent<KnockedDownComponent, StandAttemptEvent>(OnStandAttempt);
|
||||
|
||||
SubscribeLocalEvent<SlowedDownComponent, ComponentInit>(OnSlowInit);
|
||||
SubscribeLocalEvent<SlowedDownComponent, ComponentShutdown>(OnSlowRemove);
|
||||
SubscribeLocalEvent<SlowedDownComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshMovespeed);
|
||||
|
||||
SubscribeLocalEvent<StunnedComponent, ComponentStartup>(UpdateCanMove);
|
||||
SubscribeLocalEvent<StunnedComponent, ComponentShutdown>(OnStunShutdown);
|
||||
|
||||
SubscribeLocalEvent<StunOnContactComponent, StartCollideEvent>(OnStunOnContactCollide);
|
||||
|
||||
// helping people up if they're knocked down
|
||||
SubscribeLocalEvent<KnockedDownComponent, InteractHandEvent>(OnInteractHand);
|
||||
SubscribeLocalEvent<SlowedDownComponent, RefreshMovementSpeedModifiersEvent>(OnRefreshMovespeed);
|
||||
|
||||
SubscribeLocalEvent<KnockedDownComponent, TileFrictionEvent>(OnKnockedTileFriction);
|
||||
|
||||
// Attempt event subscriptions.
|
||||
SubscribeLocalEvent<StunnedComponent, ChangeDirectionAttemptEvent>(OnAttempt);
|
||||
SubscribeLocalEvent<StunnedComponent, UpdateCanMoveEvent>(OnMoveAttempt);
|
||||
@@ -74,7 +61,7 @@ public abstract partial class SharedStunSystem : EntitySystem
|
||||
SubscribeLocalEvent<StunnedComponent, IsUnequippingAttemptEvent>(OnUnequipAttempt);
|
||||
SubscribeLocalEvent<MobStateComponent, MobStateChangedEvent>(OnMobStateChanged);
|
||||
|
||||
// Stun Appearance Data
|
||||
InitializeKnockdown();
|
||||
InitializeAppearance();
|
||||
}
|
||||
|
||||
@@ -136,23 +123,7 @@ public abstract partial class SharedStunSystem : EntitySystem
|
||||
return;
|
||||
|
||||
TryStun(args.OtherEntity, ent.Comp.Duration, true, status);
|
||||
TryKnockdown(args.OtherEntity, ent.Comp.Duration, true, status);
|
||||
}
|
||||
|
||||
private void OnKnockInit(EntityUid uid, KnockedDownComponent component, ComponentInit args)
|
||||
{
|
||||
_standingState.Down(uid);
|
||||
}
|
||||
|
||||
private void OnKnockShutdown(EntityUid uid, KnockedDownComponent component, ComponentShutdown args)
|
||||
{
|
||||
_standingState.Stand(uid);
|
||||
}
|
||||
|
||||
private void OnStandAttempt(EntityUid uid, KnockedDownComponent component, StandAttemptEvent args)
|
||||
{
|
||||
if (component.LifeStage <= ComponentLifeStage.Running)
|
||||
args.Cancel();
|
||||
TryKnockdown(args.OtherEntity, ent.Comp.Duration, ent.Comp.Refresh, ent.Comp.AutoStand);
|
||||
}
|
||||
|
||||
private void OnSlowInit(EntityUid uid, SlowedDownComponent component, ComponentInit args)
|
||||
@@ -167,18 +138,12 @@ public abstract partial class SharedStunSystem : EntitySystem
|
||||
_movementSpeedModifier.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...)
|
||||
|
||||
/// <summary>
|
||||
/// Stuns the entity, disallowing it from doing many interactions temporarily.
|
||||
/// </summary>
|
||||
public bool TryStun(EntityUid uid, TimeSpan time, bool refresh,
|
||||
StatusEffectsComponent? status = null)
|
||||
public bool TryStun(EntityUid uid, TimeSpan time, bool refresh, StatusEffectsComponent? status = null)
|
||||
{
|
||||
if (time <= TimeSpan.Zero)
|
||||
return false;
|
||||
@@ -199,20 +164,48 @@ public abstract partial class SharedStunSystem : EntitySystem
|
||||
/// <summary>
|
||||
/// Knocks down the entity, making it fall to the ground.
|
||||
/// </summary>
|
||||
public bool TryKnockdown(EntityUid uid, TimeSpan time, bool refresh,
|
||||
StatusEffectsComponent? status = null)
|
||||
public bool TryKnockdown(EntityUid uid, TimeSpan time, bool refresh, bool autoStand = true, bool drop = true)
|
||||
{
|
||||
if (time <= TimeSpan.Zero)
|
||||
return false;
|
||||
|
||||
if (!Resolve(uid, ref status, false))
|
||||
// Can't fall down if you can't actually be downed.
|
||||
if (!HasComp<StandingStateComponent>(uid))
|
||||
return false;
|
||||
|
||||
if (!_statusEffect.TryAddStatusEffect<KnockedDownComponent>(uid, "KnockedDown", time, refresh))
|
||||
var evAttempt = new KnockDownAttemptEvent(autoStand, drop);
|
||||
RaiseLocalEvent(uid, ref evAttempt);
|
||||
|
||||
if (evAttempt.Cancelled)
|
||||
return false;
|
||||
|
||||
var ev = new KnockedDownEvent();
|
||||
RaiseLocalEvent(uid, ref ev);
|
||||
// Initialize our component with the relevant data we need if we don't have it
|
||||
if (EnsureComp<KnockedDownComponent>(uid, out var component))
|
||||
{
|
||||
RefreshKnockedMovement((uid, component));
|
||||
CancelKnockdownDoAfter((uid, component));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Only drop items the first time we want to fall...
|
||||
if (drop)
|
||||
{
|
||||
var ev = new DropHandItemsEvent();
|
||||
RaiseLocalEvent(uid, ref ev);
|
||||
}
|
||||
|
||||
// Only update Autostand value if it's our first time being knocked down...
|
||||
SetAutoStand((uid, component), evAttempt.AutoStand);
|
||||
}
|
||||
|
||||
var knockedEv = new KnockedDownEvent(time);
|
||||
RaiseLocalEvent(uid, ref knockedEv);
|
||||
|
||||
UpdateKnockdownTime((uid, component), knockedEv.Time, refresh);
|
||||
|
||||
Alerts.ShowAlert(uid, KnockdownAlert, null, (GameTiming.CurTime, component.NextUpdate));
|
||||
|
||||
_adminLogger.Add(LogType.Stamina, LogImpact.Medium, $"{ToPrettyString(uid):user} knocked down for {time.Seconds} seconds");
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -226,14 +219,14 @@ public abstract partial class SharedStunSystem : EntitySystem
|
||||
if (!Resolve(uid, ref status, false))
|
||||
return false;
|
||||
|
||||
return TryKnockdown(uid, time, refresh, status) && TryStun(uid, time, refresh, status);
|
||||
return TryKnockdown(uid, time, refresh) && TryStun(uid, time, refresh, status);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Slows down the mob's walking/running speed temporarily
|
||||
/// </summary>
|
||||
public bool TrySlowdown(EntityUid uid, TimeSpan time, bool refresh,
|
||||
float walkSpeedMultiplier = 1f, float runSpeedMultiplier = 1f,
|
||||
float walkSpeedMod = 1f, float sprintSpeedMod = 1f,
|
||||
StatusEffectsComponent? status = null)
|
||||
{
|
||||
if (!Resolve(uid, ref status, false))
|
||||
@@ -246,11 +239,11 @@ public abstract partial class SharedStunSystem : EntitySystem
|
||||
{
|
||||
var slowed = Comp<SlowedDownComponent>(uid);
|
||||
// Doesn't make much sense to have the "TrySlowdown" method speed up entities now does it?
|
||||
walkSpeedMultiplier = Math.Clamp(walkSpeedMultiplier, 0f, 1f);
|
||||
runSpeedMultiplier = Math.Clamp(runSpeedMultiplier, 0f, 1f);
|
||||
walkSpeedMod = Math.Clamp(walkSpeedMod, 0f, 1f);
|
||||
sprintSpeedMod = Math.Clamp(sprintSpeedMod, 0f, 1f);
|
||||
|
||||
slowed.WalkSpeedModifier *= walkSpeedMultiplier;
|
||||
slowed.SprintSpeedModifier *= runSpeedMultiplier;
|
||||
slowed.WalkSpeedModifier *= walkSpeedMod;
|
||||
slowed.SprintSpeedModifier *= sprintSpeedMod;
|
||||
|
||||
_movementSpeedModifier.RefreshMovementSpeedModifiers(uid);
|
||||
return true;
|
||||
@@ -310,29 +303,14 @@ public abstract partial class SharedStunSystem : EntitySystem
|
||||
UpdateStunModifiers(ent, speedModifier, speedModifier);
|
||||
}
|
||||
|
||||
private void OnInteractHand(EntityUid uid, KnockedDownComponent knocked, InteractHandEvent args)
|
||||
#region friction and movement listeners
|
||||
|
||||
private void OnRefreshMovespeed(EntityUid ent, SlowedDownComponent comp, RefreshMovementSpeedModifiersEvent args)
|
||||
{
|
||||
if (args.Handled || knocked.HelpTimer > 0f)
|
||||
return;
|
||||
|
||||
// TODO: This should be an event.
|
||||
if (HasComp<SleepingComponent>(uid))
|
||||
return;
|
||||
|
||||
// Set it to half the help interval so helping is actually useful...
|
||||
knocked.HelpTimer = knocked.HelpInterval / 2f;
|
||||
|
||||
_statusEffect.TryRemoveTime(uid, "KnockedDown", TimeSpan.FromSeconds(knocked.HelpInterval));
|
||||
_audio.PlayPredicted(knocked.StunAttemptSound, uid, args.User);
|
||||
Dirty(uid, knocked);
|
||||
|
||||
args.Handled = true;
|
||||
args.ModifySpeed(comp.WalkSpeedModifier, comp.SprintSpeedModifier);
|
||||
}
|
||||
|
||||
private void OnKnockedTileFriction(EntityUid uid, KnockedDownComponent component, ref TileFrictionEvent args)
|
||||
{
|
||||
args.Modifier *= KnockDownModifier;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Attempt Event Handling
|
||||
|
||||
@@ -365,15 +343,3 @@ public abstract partial class SharedStunSystem : EntitySystem
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised directed on an entity when it is stunned.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public record struct StunnedEvent;
|
||||
|
||||
/// <summary>
|
||||
/// Raised directed on an entity when it is knocked down.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public record struct KnockedDownEvent;
|
||||
|
||||
Reference in New Issue
Block a user