SS14-26964 Clown Waddling Replicates, etc (#26983)

This commit is contained in:
Hannah Giovanna Dawson
2024-06-04 14:23:09 +01:00
committed by GitHub
parent 58647e7036
commit d4fe7eda51
6 changed files with 213 additions and 122 deletions

View File

@@ -2,94 +2,115 @@
using Content.Client.Buckle;
using Content.Client.Gravity;
using Content.Shared.ActionBlocker;
using Content.Shared.Buckle.Components;
using Content.Shared.Mobs.Systems;
using Content.Shared.Movement.Components;
using Content.Shared.Movement.Events;
using Content.Shared.StatusEffect;
using Content.Shared.Stunnable;
using Content.Shared.Movement.Systems;
using Robust.Client.Animations;
using Robust.Client.GameObjects;
using Robust.Shared.Animations;
using Robust.Shared.Timing;
namespace Content.Client.Movement.Systems;
public sealed class WaddleAnimationSystem : EntitySystem
public sealed class WaddleAnimationSystem : SharedWaddleAnimationSystem
{
[Dependency] private readonly AnimationPlayerSystem _animation = default!;
[Dependency] private readonly GravitySystem _gravity = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;
[Dependency] private readonly BuckleSystem _buckle = default!;
[Dependency] private readonly MobStateSystem _mobState = default!;
public override void Initialize()
{
SubscribeLocalEvent<WaddleAnimationComponent, MoveInputEvent>(OnMovementInput);
SubscribeLocalEvent<WaddleAnimationComponent, StartedWaddlingEvent>(OnStartedWalking);
SubscribeLocalEvent<WaddleAnimationComponent, StoppedWaddlingEvent>(OnStoppedWalking);
base.Initialize();
SubscribeAllEvent<StartedWaddlingEvent>(OnStartWaddling);
SubscribeLocalEvent<WaddleAnimationComponent, AnimationCompletedEvent>(OnAnimationCompleted);
SubscribeLocalEvent<WaddleAnimationComponent, StunnedEvent>(OnStunned);
SubscribeLocalEvent<WaddleAnimationComponent, KnockedDownEvent>(OnKnockedDown);
SubscribeLocalEvent<WaddleAnimationComponent, BuckleChangeEvent>(OnBuckleChange);
SubscribeAllEvent<StoppedWaddlingEvent>(OnStopWaddling);
}
private void OnMovementInput(EntityUid entity, WaddleAnimationComponent component, MoveInputEvent args)
private void OnStartWaddling(StartedWaddlingEvent msg, EntitySessionEventArgs args)
{
// Prediction mitigation. Prediction means that MoveInputEvents are spammed repeatedly, even though you'd assume
// they're once-only for the user actually doing something. As such do nothing if we're just repeating this FoR.
if (!_timing.IsFirstTimePredicted)
{
return;
}
if (!args.HasDirectionalMovement && component.IsCurrentlyWaddling)
{
var stopped = new StoppedWaddlingEvent(entity);
RaiseLocalEvent(entity, ref stopped);
return;
}
// Only start waddling if we're not currently AND we're actually moving.
if (component.IsCurrentlyWaddling || !args.HasDirectionalMovement)
return;
var started = new StartedWaddlingEvent(entity);
RaiseLocalEvent(entity, ref started);
if (TryComp<WaddleAnimationComponent>(GetEntity(msg.Entity), out var comp))
StartWaddling((GetEntity(msg.Entity), comp));
}
private void OnStartedWalking(EntityUid uid, WaddleAnimationComponent component, StartedWaddlingEvent args)
private void OnStopWaddling(StoppedWaddlingEvent msg, EntitySessionEventArgs args)
{
if (_animation.HasRunningAnimation(uid, component.KeyName))
if (TryComp<WaddleAnimationComponent>(GetEntity(msg.Entity), out var comp))
StopWaddling((GetEntity(msg.Entity), comp));
}
private void StartWaddling(Entity<WaddleAnimationComponent> entity)
{
if (_animation.HasRunningAnimation(entity.Owner, entity.Comp.KeyName))
return;
if (!TryComp<InputMoverComponent>(uid, out var mover))
if (!TryComp<InputMoverComponent>(entity.Owner, out var mover))
return;
if (_gravity.IsWeightless(uid))
if (_gravity.IsWeightless(entity.Owner))
return;
if (!_actionBlocker.CanMove(uid, mover))
if (!_actionBlocker.CanMove(entity.Owner, mover))
return;
// Do nothing if buckled in
if (_buckle.IsBuckled(uid))
if (_buckle.IsBuckled(entity.Owner))
return;
// Do nothing if crit or dead (for obvious reasons)
if (_mobState.IsIncapacitated(uid))
if (_mobState.IsIncapacitated(entity.Owner))
return;
var tumbleIntensity = component.LastStep ? 360 - component.TumbleIntensity : component.TumbleIntensity;
var len = mover.Sprinting ? component.AnimationLength * component.RunAnimationLengthMultiplier : component.AnimationLength;
PlayWaddleAnimationUsing(
(entity.Owner, entity.Comp),
CalculateAnimationLength(entity.Comp, mover),
CalculateTumbleIntensity(entity.Comp)
);
}
component.LastStep = !component.LastStep;
component.IsCurrentlyWaddling = true;
private static float CalculateTumbleIntensity(WaddleAnimationComponent component)
{
return component.LastStep ? 360 - component.TumbleIntensity : component.TumbleIntensity;
}
private static float CalculateAnimationLength(WaddleAnimationComponent component, InputMoverComponent mover)
{
return mover.Sprinting ? component.AnimationLength * component.RunAnimationLengthMultiplier : component.AnimationLength;
}
private void OnAnimationCompleted(Entity<WaddleAnimationComponent> entity, ref AnimationCompletedEvent args)
{
if (args.Key != entity.Comp.KeyName)
return;
if (!TryComp<InputMoverComponent>(entity.Owner, out var mover))
return;
PlayWaddleAnimationUsing(
(entity.Owner, entity.Comp),
CalculateAnimationLength(entity.Comp, mover),
CalculateTumbleIntensity(entity.Comp)
);
}
private void StopWaddling(Entity<WaddleAnimationComponent> entity)
{
if (!_animation.HasRunningAnimation(entity.Owner, entity.Comp.KeyName))
return;
_animation.Stop(entity.Owner, entity.Comp.KeyName);
if (!TryComp<SpriteComponent>(entity.Owner, out var sprite))
return;
sprite.Offset = new Vector2();
sprite.Rotation = Angle.FromDegrees(0);
}
private void PlayWaddleAnimationUsing(Entity<WaddleAnimationComponent> entity, float len, float tumbleIntensity)
{
entity.Comp.LastStep = !entity.Comp.LastStep;
var anim = new Animation()
{
@@ -116,58 +137,13 @@ public sealed class WaddleAnimationSystem : EntitySystem
KeyFrames =
{
new AnimationTrackProperty.KeyFrame(new Vector2(), 0),
new AnimationTrackProperty.KeyFrame(component.HopIntensity, len/2),
new AnimationTrackProperty.KeyFrame(entity.Comp.HopIntensity, len/2),
new AnimationTrackProperty.KeyFrame(new Vector2(), len/2),
}
}
}
};
_animation.Play(uid, anim, component.KeyName);
}
private void OnStoppedWalking(EntityUid uid, WaddleAnimationComponent component, StoppedWaddlingEvent args)
{
StopWaddling(uid, component);
}
private void OnAnimationCompleted(EntityUid uid, WaddleAnimationComponent component, AnimationCompletedEvent args)
{
var started = new StartedWaddlingEvent(uid);
RaiseLocalEvent(uid, ref started);
}
private void OnStunned(EntityUid uid, WaddleAnimationComponent component, StunnedEvent args)
{
StopWaddling(uid, component);
}
private void OnKnockedDown(EntityUid uid, WaddleAnimationComponent component, KnockedDownEvent args)
{
StopWaddling(uid, component);
}
private void OnBuckleChange(EntityUid uid, WaddleAnimationComponent component, BuckleChangeEvent args)
{
StopWaddling(uid, component);
}
private void StopWaddling(EntityUid uid, WaddleAnimationComponent component)
{
if (!component.IsCurrentlyWaddling)
return;
_animation.Stop(uid, component.KeyName);
if (!TryComp<SpriteComponent>(uid, out var sprite))
{
return;
}
sprite.Offset = new Vector2();
sprite.Rotation = Angle.FromDegrees(0);
component.IsCurrentlyWaddling = false;
_animation.Play(entity.Owner, anim, entity.Comp.KeyName);
}
}