From bcc5a9e829745ae87bc06877d892cb7571e42fc5 Mon Sep 17 00:00:00 2001 From: hivehum Date: Wed, 15 Jan 2025 16:11:31 -0500 Subject: [PATCH] when the emotes are animated --- .../Emoting/AnimatedEmotesSystem.cs | 137 ++++++++++++++++++ .../Emoting/AnimatedEmotesSystem.cs | 28 ++++ .../Chat/Prototypes/EmotePrototype.cs | 4 + .../Emoting/AnimatedEmotesComponent.cs | 28 ++++ .../Emoting/SharedAnimatedEmotesSystem.cs | 18 +++ .../Locale/en-US/_Goobstation/emotes.ftl | 7 + .../Entities/Mobs/Player/guardian.yml | 1 + Resources/Prototypes/Entities/Mobs/base.yml | 3 +- .../_Goobstation/Actions/emotes.yml | 42 ++++++ .../Interface/Emotes/attributions.yml | 7 + .../_Impstation/Interface/Emotes/backflip.png | Bin 0 -> 1068 bytes .../_Impstation/Interface/Emotes/jump.png | Bin 0 -> 1197 bytes .../_Impstation/Interface/Emotes/spin.png | Bin 0 -> 1083 bytes 13 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 Content.Client/_Goobstation/Emoting/AnimatedEmotesSystem.cs create mode 100644 Content.Server/_Goobstation/Emoting/AnimatedEmotesSystem.cs create mode 100644 Content.Shared/_Goobstation/Emoting/AnimatedEmotesComponent.cs create mode 100644 Content.Shared/_Goobstation/Emoting/SharedAnimatedEmotesSystem.cs create mode 100644 Resources/Locale/en-US/_Goobstation/emotes.ftl create mode 100644 Resources/Prototypes/_Goobstation/Actions/emotes.yml create mode 100644 Resources/Textures/_Impstation/Interface/Emotes/attributions.yml create mode 100644 Resources/Textures/_Impstation/Interface/Emotes/backflip.png create mode 100644 Resources/Textures/_Impstation/Interface/Emotes/jump.png create mode 100644 Resources/Textures/_Impstation/Interface/Emotes/spin.png diff --git a/Content.Client/_Goobstation/Emoting/AnimatedEmotesSystem.cs b/Content.Client/_Goobstation/Emoting/AnimatedEmotesSystem.cs new file mode 100644 index 00000000000..33b89fbed10 --- /dev/null +++ b/Content.Client/_Goobstation/Emoting/AnimatedEmotesSystem.cs @@ -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(OnHandleState); + + SubscribeLocalEvent(OnFlip); + SubscribeLocalEvent(OnSpin); + SubscribeLocalEvent(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(state.Emote, out var emote)) + return; + + if (emote.Event != null) + RaiseLocalEvent(uid, emote.Event); + } + + private void OnFlip(Entity ent, ref AnimationFlipEmoteEvent args) + { + var angle = Angle.Zero; + + if (TryComp(ent, out var rotation)) + { + _appearance.TryGetData(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 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 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); + } +} diff --git a/Content.Server/_Goobstation/Emoting/AnimatedEmotesSystem.cs b/Content.Server/_Goobstation/Emoting/AnimatedEmotesSystem.cs new file mode 100644 index 00000000000..cc4863d31f7 --- /dev/null +++ b/Content.Server/_Goobstation/Emoting/AnimatedEmotesSystem.cs @@ -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(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 prot) + { + component.Emote = prot; + Dirty(uid, component); + } +} diff --git a/Content.Shared/Chat/Prototypes/EmotePrototype.cs b/Content.Shared/Chat/Prototypes/EmotePrototype.cs index 7ee958ee6a7..34d54bc3600 100644 --- a/Content.Shared/Chat/Prototypes/EmotePrototype.cs +++ b/Content.Shared/Chat/Prototypes/EmotePrototype.cs @@ -68,6 +68,10 @@ public sealed partial class EmotePrototype : IPrototype /// [DataField] public HashSet ChatTriggers = new(); + + // goob edit - animations + [DataField] + public object? Event = null; } /// diff --git a/Content.Shared/_Goobstation/Emoting/AnimatedEmotesComponent.cs b/Content.Shared/_Goobstation/Emoting/AnimatedEmotesComponent.cs new file mode 100644 index 00000000000..fc8121bbe5a --- /dev/null +++ b/Content.Shared/_Goobstation/Emoting/AnimatedEmotesComponent.cs @@ -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? Emote; +} + +[Serializable, NetSerializable] public sealed partial class AnimatedEmotesComponentState : ComponentState +{ + public ProtoId? Emote; + + public AnimatedEmotesComponentState(ProtoId? emote) + { + Emote = emote; + } +} diff --git a/Content.Shared/_Goobstation/Emoting/SharedAnimatedEmotesSystem.cs b/Content.Shared/_Goobstation/Emoting/SharedAnimatedEmotesSystem.cs new file mode 100644 index 00000000000..b19e8c26a1e --- /dev/null +++ b/Content.Shared/_Goobstation/Emoting/SharedAnimatedEmotesSystem.cs @@ -0,0 +1,18 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Emoting; + +public abstract class SharedAnimatedEmotesSystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnGetState); + } + + private void OnGetState(Entity ent, ref ComponentGetState args) + { + args.State = new AnimatedEmotesComponentState(ent.Comp.Emote); + } +} diff --git a/Resources/Locale/en-US/_Goobstation/emotes.ftl b/Resources/Locale/en-US/_Goobstation/emotes.ftl new file mode 100644 index 00000000000..9f51be946c3 --- /dev/null +++ b/Resources/Locale/en-US/_Goobstation/emotes.ftl @@ -0,0 +1,7 @@ + +chat-emote-name-flip = Do a flip +chat-emote-name-spin = Spin +chat-emote-name-jump = Jump +chat-emote-msg-flip = does a flip! +chat-emote-msg-spin = spins! +chat-emote-msg-jump = jumps! diff --git a/Resources/Prototypes/Entities/Mobs/Player/guardian.yml b/Resources/Prototypes/Entities/Mobs/Player/guardian.yml index dca47e1c837..e81859421d9 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/guardian.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/guardian.yml @@ -109,6 +109,7 @@ - type: Tag tags: - CannotSuicide + - type: AnimatedEmotes # goob edit - animated emotes # From the uplink injector - type: entity diff --git a/Resources/Prototypes/Entities/Mobs/base.yml b/Resources/Prototypes/Entities/Mobs/base.yml index 90f3e8380f3..6f289a9185f 100644 --- a/Resources/Prototypes/Entities/Mobs/base.yml +++ b/Resources/Prototypes/Entities/Mobs/base.yml @@ -43,6 +43,7 @@ - type: MovementSpeedModifier - type: RequireProjectileTarget active: False + - type: AnimatedEmotes # goob edit - animated emotes - type: entity save: false @@ -67,7 +68,7 @@ damage: 400 behaviors: - !type:GibBehavior { } -# - trigger: # DeltaV- We don't like round removing people for being in the same room as a plasma trapped crate. +# - trigger: # DeltaV- We don't like round removing people for being in the same room as a plasma trapped crate. # !type:DamageTypeTrigger # damageType: Heat # damage: 1500 diff --git a/Resources/Prototypes/_Goobstation/Actions/emotes.yml b/Resources/Prototypes/_Goobstation/Actions/emotes.yml new file mode 100644 index 00000000000..3dcdf2ce49d --- /dev/null +++ b/Resources/Prototypes/_Goobstation/Actions/emotes.yml @@ -0,0 +1,42 @@ +- type: emote + id: Flip + name: chat-emote-name-flip + chatMessages: ["chat-emote-msg-flip"] + icon: _Impstation/Interface/Emotes/backflip.png #imp + chatTriggers: + - flip + - flips + - flips. + - flips! + - does a flip + - does a flip. + - does a flip! + event: !type:AnimationFlipEmoteEvent + +- 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 diff --git a/Resources/Textures/_Impstation/Interface/Emotes/attributions.yml b/Resources/Textures/_Impstation/Interface/Emotes/attributions.yml new file mode 100644 index 00000000000..a44bce9d523 --- /dev/null +++ b/Resources/Textures/_Impstation/Interface/Emotes/attributions.yml @@ -0,0 +1,7 @@ +- files: + - backflip.png + - jump.png + - spin.png + license: "CC-BY-SA-4.0" + copyright: "Created by Carousel for Impstation" + source: "https://github.com/impstation/imp-station-14" diff --git a/Resources/Textures/_Impstation/Interface/Emotes/backflip.png b/Resources/Textures/_Impstation/Interface/Emotes/backflip.png new file mode 100644 index 0000000000000000000000000000000000000000..f5d9ecb848f7ac0c1cdd4526059b7d6b65329e3f GIT binary patch literal 1068 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 LNkvXXu0mjfmjNXQ literal 0 HcmV?d00001 diff --git a/Resources/Textures/_Impstation/Interface/Emotes/spin.png b/Resources/Textures/_Impstation/Interface/Emotes/spin.png new file mode 100644 index 0000000000000000000000000000000000000000..c5de318e63b2564a6cf8e603226c95d0c0ff74fb GIT binary patch literal 1083 zcmV-B1jPG^P)EX>4Tx04R}tkv&MmP!xqvQ>7v;4(%W!lA$`;MMWG-6^me@v=v%)FnQ@8G-*gu zTpR`0f`dPcRRUL0ade% zOfn(n3#($_6+VOz#u)q(Gxbz%?)$SsO3`G1Pb7{r-LQx^h-Wt~ zo%23%gjFPk_?&pspbHW|a$R=$jdR&yfoDdHTxOm)LM)bhSngp~F;wCi;;5o(lrQ96 zRyc2QR%;E`xhH>Nu&AwMxlU^oNh~3SG(^Z~po$tS#Aw$@F_EG3gol5`@u$fpldB3w zjs?`ALUR1zfAD*@W@&oLO$sJ}{ukT+7zYBoK)Y$%-^aGyJ^}pCz?IhZ*IU5cC+W?u z7Ci!nwtZNBE*rk!3AX?M02y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00I+9L_t(&-tAaBO9Md=-i?QaBEc#MDQuI*D#CRsBQf|V zu1lZ7N9Ciix67Z9D5ktF5UVt~)*>LOB#0KG#A=AnG3?#$%w2*`bKKpsyWjWC&SRDO zx4&&#YT|l*Jf2MEbNoFFtJQK@YuE8hYXGEFDi#}!_!9$7JD%G-Zs1Ym`$3@8>&MAw z>png%ihMt4+K=b<2u~XL*7~K_Yntc5<6s_mN)e%@fmbSnLAQ$(4dU}r<4p6q5>enj zQzqb8*M5QpA|DLvDo-m6uH$hO_MY9|u3YpW*1PcDtk0`%CAoy=D%MYy?Ot zCk5P^0En{tdxwul&+#;rw7{{=CfIC&XC4H(3;@YTom{1rkfou<08~^ zU4W|1p#YLH5QGva^E62H1XQ!cZMH;+#Q-406wULB{zd{QCaL@Ttb-TVy4rQYv@VD1 z2b1zif!f9ZEv1BMLuv2#xddP*AS>5i)