Animated Emotes from Impstation (#2746)

* when the emotes are animated

* hopefully untouched

* INCORRECT

* can this work.

* flipping out
This commit is contained in:
hivehum 2025-01-18 18:50:21 -05:00 committed by GitHub
parent 604e2b1e60
commit 01a9e61ce9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 255 additions and 0 deletions

View File

@ -0,0 +1,137 @@
using Robust.Client.Animations;
using Robust.Shared.Animations;
using Robust.Shared.GameStates;
using Robust.Client.GameObjects;
using Content.Shared.Emoting;
using System.Numerics;
using Robust.Shared.Prototypes;
using Content.Shared.Chat.Prototypes;
using Content.Shared.Rotation;
namespace Content.Client.Emoting;
public sealed partial class AnimatedEmotesSystem : SharedAnimatedEmotesSystem
{
[Dependency] private readonly AnimationPlayerSystem _anim = default!;
[Dependency] private readonly AppearanceSystem _appearance = default!;
[Dependency] private readonly IPrototypeManager _prot = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<AnimatedEmotesComponent, ComponentHandleState>(OnHandleState);
SubscribeLocalEvent<AnimatedEmotesComponent, AnimationFlipEmoteEvent>(OnFlip);
SubscribeLocalEvent<AnimatedEmotesComponent, AnimationSpinEmoteEvent>(OnSpin);
SubscribeLocalEvent<AnimatedEmotesComponent, AnimationJumpEmoteEvent>(OnJump);
}
public void PlayEmote(EntityUid uid, Animation anim, string animationKey = "emoteAnimKeyId")
{
if (_anim.HasRunningAnimation(uid, animationKey))
return;
_anim.Play(uid, anim, animationKey);
}
private void OnHandleState(EntityUid uid, AnimatedEmotesComponent component, ref ComponentHandleState args)
{
if (args.Current is not AnimatedEmotesComponentState state
|| !_prot.TryIndex<EmotePrototype>(state.Emote, out var emote))
return;
if (emote.Event != null)
RaiseLocalEvent(uid, emote.Event);
}
private void OnFlip(Entity<AnimatedEmotesComponent> ent, ref AnimationFlipEmoteEvent args)
{
var angle = Angle.Zero;
if (TryComp<RotationVisualsComponent>(ent, out var rotation))
{
_appearance.TryGetData<RotationState>(ent, RotationVisuals.RotationState, out var state);
angle = state switch
{
RotationState.Vertical => rotation.VerticalRotation,
RotationState.Horizontal => rotation.HorizontalRotation,
_ => Angle.Zero
};
}
var a = new Animation
{
Length = TimeSpan.FromMilliseconds(500),
AnimationTracks =
{
new AnimationTrackComponentProperty
{
ComponentType = typeof(SpriteComponent),
Property = nameof(SpriteComponent.Rotation),
InterpolationMode = AnimationInterpolationMode.Linear,
KeyFrames =
{
new AnimationTrackProperty.KeyFrame(angle, 0f),
new AnimationTrackProperty.KeyFrame(angle + Angle.FromDegrees(180), 0.25f),
new AnimationTrackProperty.KeyFrame(angle + Angle.FromDegrees(360), 0.25f),
}
}
}
};
PlayEmote(ent, a);
}
private void OnSpin(Entity<AnimatedEmotesComponent> ent, ref AnimationSpinEmoteEvent args)
{
var a = new Animation
{
Length = TimeSpan.FromMilliseconds(600),
AnimationTracks =
{
new AnimationTrackComponentProperty
{
ComponentType = typeof(TransformComponent),
Property = nameof(TransformComponent.LocalRotation),
InterpolationMode = AnimationInterpolationMode.Linear,
KeyFrames =
{
new AnimationTrackProperty.KeyFrame(Angle.FromDegrees(0), 0f),
new AnimationTrackProperty.KeyFrame(Angle.FromDegrees(90), 0.075f),
new AnimationTrackProperty.KeyFrame(Angle.FromDegrees(180), 0.075f),
new AnimationTrackProperty.KeyFrame(Angle.FromDegrees(270), 0.075f),
new AnimationTrackProperty.KeyFrame(Angle.Zero, 0.075f),
new AnimationTrackProperty.KeyFrame(Angle.FromDegrees(90), 0.075f),
new AnimationTrackProperty.KeyFrame(Angle.FromDegrees(180), 0.075f),
new AnimationTrackProperty.KeyFrame(Angle.FromDegrees(270), 0.075f),
new AnimationTrackProperty.KeyFrame(Angle.Zero, 0.075f),
}
}
}
};
PlayEmote(ent, a, "emoteAnimSpin");
}
private void OnJump(Entity<AnimatedEmotesComponent> ent, ref AnimationJumpEmoteEvent args)
{
var a = new Animation
{
Length = TimeSpan.FromMilliseconds(250),
AnimationTracks =
{
new AnimationTrackComponentProperty
{
ComponentType = typeof(SpriteComponent),
Property = nameof(SpriteComponent.Offset),
InterpolationMode = AnimationInterpolationMode.Cubic,
KeyFrames =
{
new AnimationTrackProperty.KeyFrame(Vector2.Zero, 0f),
new AnimationTrackProperty.KeyFrame(new Vector2(0, .35f), 0.125f),
new AnimationTrackProperty.KeyFrame(Vector2.Zero, 0.125f),
}
}
}
};
PlayEmote(ent, a);
}
}

View File

@ -0,0 +1,28 @@
using Robust.Shared.GameStates;
using Content.Server.Chat.Systems;
using Content.Shared.Chat.Prototypes;
using Content.Shared.Emoting;
using Robust.Shared.Prototypes;
namespace Content.Server.Emoting;
public sealed partial class AnimatedEmotesSystem : SharedAnimatedEmotesSystem
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<AnimatedEmotesComponent, EmoteEvent>(OnEmote);
}
private void OnEmote(EntityUid uid, AnimatedEmotesComponent component, ref EmoteEvent args)
{
PlayEmoteAnimation(uid, component, args.Emote.ID);
}
public void PlayEmoteAnimation(EntityUid uid, AnimatedEmotesComponent component, ProtoId<EmotePrototype> prot)
{
component.Emote = prot;
Dirty(uid, component);
}
}

View File

@ -68,6 +68,10 @@ public sealed partial class EmotePrototype : IPrototype
/// </summary>
[DataField]
public HashSet<string> ChatTriggers = new();
// goob edit - animations
[DataField]
public object? Event = null;
}
/// <summary>

View File

@ -0,0 +1,28 @@
using Content.Shared.Chat.Prototypes;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
namespace Content.Shared.Emoting;
// use as a template
//[Serializable, NetSerializable, DataDefinition] public sealed partial class AnimationNameEmoteEvent : EntityEventArgs { }
[Serializable, NetSerializable, DataDefinition] public sealed partial class AnimationFlipEmoteEvent : EntityEventArgs { }
[Serializable, NetSerializable, DataDefinition] public sealed partial class AnimationSpinEmoteEvent : EntityEventArgs { }
[Serializable, NetSerializable, DataDefinition] public sealed partial class AnimationJumpEmoteEvent : EntityEventArgs { }
[RegisterComponent, NetworkedComponent] public sealed partial class AnimatedEmotesComponent : Component
{
[DataField] public ProtoId<EmotePrototype>? Emote;
}
[Serializable, NetSerializable] public sealed partial class AnimatedEmotesComponentState : ComponentState
{
public ProtoId<EmotePrototype>? Emote;
public AnimatedEmotesComponentState(ProtoId<EmotePrototype>? emote)
{
Emote = emote;
}
}

View File

@ -0,0 +1,18 @@
using Robust.Shared.GameStates;
namespace Content.Shared.Emoting;
public abstract class SharedAnimatedEmotesSystem : EntitySystem
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<AnimatedEmotesComponent, ComponentGetState>(OnGetState);
}
private void OnGetState(Entity<AnimatedEmotesComponent> ent, ref ComponentGetState args)
{
args.State = new AnimatedEmotesComponentState(ent.Comp.Emote);
}
}

View File

@ -0,0 +1,5 @@
chat-emote-name-spin = Spin
chat-emote-name-jump = Jump
chat-emote-msg-spin = spins!
chat-emote-msg-jump = jumps!

View File

@ -111,6 +111,7 @@
- type: Tag
tags:
- CannotSuicide
- type: AnimatedEmotes # goob edit - animated emotes
# From the uplink injector
- type: entity

View File

@ -43,6 +43,7 @@
- type: MovementSpeedModifier
- type: RequireProjectileTarget
active: False
- type: AnimatedEmotes # goob edit - animated emotes
- type: entity
save: false

View File

@ -0,0 +1,27 @@
- type: emote
id: Spin
name: chat-emote-name-spin
chatMessages: ["chat-emote-msg-spin"]
icon: _Impstation/Interface/Emotes/spin.png #imp
chatTriggers:
- spin
- spins
- spins.
- spins!
event: !type:AnimationSpinEmoteEvent
- type: emote
id: Jump
name: chat-emote-name-jump
chatMessages: ["chat-emote-msg-jump"]
icon: _Impstation/Interface/Emotes/jump.png #imp
chatTriggers:
- jump
- jumps
- jumps.
- jumps!
- bounce
- bounces
- bounces.
- bounces!
event: !type:AnimationJumpEmoteEvent

View File

@ -0,0 +1,6 @@
- files:
- jump.png
- spin.png
license: "CC-BY-SA-4.0"
copyright: "Created by Carousel for Impstation"
source: "https://github.com/impstation/imp-station-14"

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB