From 927af5a681d80fa4ffa572adfbf17469abade938 Mon Sep 17 00:00:00 2001 From: DocNITE Date: Fri, 5 May 2023 18:31:39 +0300 Subject: [PATCH] added emote animations --- .../White/Animations/EmoteAnimationSystem.cs | 146 ++++++++++++++++++ .../White/Animations/EmoteAnimationSystem.cs | 84 ++++++++++ .../Animations/EmoteAnimationComponent.cs | 41 +++++ .../Animations/SharedEmoteAnimationSystem.cs | 19 +++ .../Prototypes/Entities/Mobs/Species/base.yml | 1 + Resources/Prototypes/White/Actions/emotes.yml | 66 ++++++++ 6 files changed, 357 insertions(+) create mode 100644 Content.Client/White/Animations/EmoteAnimationSystem.cs create mode 100644 Content.Server/White/Animations/EmoteAnimationSystem.cs create mode 100644 Content.Shared/White/Animations/EmoteAnimationComponent.cs create mode 100644 Content.Shared/White/Animations/SharedEmoteAnimationSystem.cs create mode 100644 Resources/Prototypes/White/Actions/emotes.yml diff --git a/Content.Client/White/Animations/EmoteAnimationSystem.cs b/Content.Client/White/Animations/EmoteAnimationSystem.cs new file mode 100644 index 0000000000..37ed1b9e9b --- /dev/null +++ b/Content.Client/White/Animations/EmoteAnimationSystem.cs @@ -0,0 +1,146 @@ +using Content.Shared.Animations; +using Robust.Client.Animations; +using Robust.Shared.Animations; +using Robust.Shared.GameStates; +using Robust.Client.GameObjects; +using static Content.Shared.Animations.EmoteAnimationComponent; +using Content.Shared.Interaction; + +namespace Content.Client.Animations; + +public class EmoteAnimationSystem : SharedEmoteAnimationSystem +{ + [Dependency] private readonly AnimationPlayerSystem AnimationSystem = default!; + + public override void Initialize() + { + SubscribeLocalEvent(OnHandleState); + } + + private void OnHandleState(EntityUid uid, EmoteAnimationComponent component, ref ComponentHandleState args) + { + if (args.Current is not EmoteAnimationComponentState state) + return; + + component.AnimationId = state.AnimationId; + + switch(component.AnimationId) + { + case EmoteFlipActionPrototype: + PlayEmoteFlip(uid); + break; + case EmoteJumpActionPrototype: + PlayEmoteJump(uid); + break; + case EmoteTurnActionPrototype: + PlayEmoteTurn(uid); + break; + default: + break; + } + } + + public void PlayEmoteFlip(EntityUid uid) + { + var animationKey = "emoteAnimationKeyId"; + + if (AnimationSystem.HasRunningAnimation(uid, animationKey)) + return; + + var baseAngle = Angle.Zero; + if (EntityManager.TryGetComponent(uid, out SpriteComponent? sprite)) + { + if (sprite != null) + baseAngle = sprite.Rotation; + } + + var animation = new Animation + { + Length = TimeSpan.FromMilliseconds(500), + AnimationTracks = + { + new AnimationTrackComponentProperty + { + ComponentType = typeof(SpriteComponent), + Property = nameof(SpriteComponent.Rotation), + InterpolationMode = AnimationInterpolationMode.Linear, + KeyFrames = + { + new AnimationTrackProperty.KeyFrame(Angle.FromDegrees(baseAngle.Degrees), 0f), + new AnimationTrackProperty.KeyFrame(Angle.FromDegrees(baseAngle.Degrees + 180), 0.25f), + new AnimationTrackProperty.KeyFrame(Angle.FromDegrees(baseAngle.Degrees + 360), 0.25f), + new AnimationTrackProperty.KeyFrame(Angle.FromDegrees(baseAngle.Degrees), 0f), + } + } + } + }; + + AnimationSystem.Play(uid, animation, animationKey); + } + + public void PlayEmoteJump(EntityUid uid) + { + var animationKey = "emoteAnimationKeyId"; + + if (AnimationSystem.HasRunningAnimation(uid, animationKey)) + return; + + var animation = 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, 1), 0.125f), + new AnimationTrackProperty.KeyFrame(Vector2.Zero, 0.125f), + } + } + } + }; + + AnimationSystem.Play(uid, animation, animationKey); + } + + public void PlayEmoteTurn(EntityUid uid) + { + var animationKey = "emoteAnimationKeyId_rotate"; // it needs for only rotate anim + + if (AnimationSystem.HasRunningAnimation(uid, animationKey)) + return; + + var animation = new Animation + { + Length = TimeSpan.FromMilliseconds(600), // Пока пусть на 0.6 секунд. В идеале бы до 0.9 на 3 поворота + 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), + } + } + } + }; + + AnimationSystem.Play(uid, animation, animationKey); + } +} diff --git a/Content.Server/White/Animations/EmoteAnimationSystem.cs b/Content.Server/White/Animations/EmoteAnimationSystem.cs new file mode 100644 index 0000000000..ff29c92615 --- /dev/null +++ b/Content.Server/White/Animations/EmoteAnimationSystem.cs @@ -0,0 +1,84 @@ +using Robust.Shared.GameStates; +using Content.Server.Actions; +using Content.Shared.Actions.ActionTypes; +using Content.Shared.Animations; +using static Content.Shared.Animations.EmoteAnimationComponent; +using Content.Server.Chat.Systems; +using Content.Shared.Chat.Prototypes; + +namespace Content.Server.Animations; + +public class EmoteAnimationSystem : SharedEmoteAnimationSystem +{ + [Dependency] private readonly ActionsSystem _action = default!; + public override void Initialize() + { + SubscribeLocalEvent(OnGetState); + + SubscribeLocalEvent(OnMapInint); + SubscribeLocalEvent(OnShutdown); + SubscribeLocalEvent(OnEmote); + SubscribeLocalEvent(OnEmoteFlip); + SubscribeLocalEvent(OnEmoteJump); + SubscribeLocalEvent(OnEmoteTurn); + } + + private void OnGetState(EntityUid uid, EmoteAnimationComponent component, ref ComponentGetState args) + { + args.State = new EmoteAnimationComponentState(component.AnimationId); + } + + private void OnMapInint(EntityUid uid, EmoteAnimationComponent component, MapInitEvent args) + { + /* + var actionFlip = new InstantAction(_proto.Index(EmoteFlipActionPrototype)); + var actionJump = new InstantAction(_proto.Index(EmoteJumpActionPrototype)); + var actionTurn = new InstantAction(_proto.Index(EmoteTurnActionPrototype)); + component.FlipAction = actionFlip; + component.JumpAction = actionJump; + component.TurnAction = actionTurn; + _action.AddAction(uid, actionFlip, null); + _action.AddAction(uid, actionJump, null); + _action.AddAction(uid, actionTurn, null); + */ + // shity-dirty-fucking code. There is need to refactor in future, if you wanna add more animations - Doc + } + + private void OnShutdown(EntityUid uid, EmoteAnimationComponent component, ComponentShutdown args) + { + if (component.FlipAction != null) + _action.RemoveAction(uid, component.FlipAction); + if (component.JumpAction != null) + _action.RemoveAction(uid, component.JumpAction); + if (component.TurnAction != null) + _action.RemoveAction(uid, component.TurnAction); + // shity-dirty-fucking code. There is need to refactor in future, if you wanna add more animations - Doc + } + + private void OnEmote(EntityUid uid, EmoteAnimationComponent component, ref EmoteEvent args) + { + if (args.Handled || !args.Emote.Category.HasFlag(EmoteCategory.Gesture)) + return; + + PlayEmoteAnimation(uid, component, args.Emote.ID); + } + + private void OnEmoteFlip(EntityUid uid, EmoteAnimationComponent component, EmoteFlipActionEvent args) + { + PlayEmoteAnimation(uid, component, EmoteFlipActionPrototype); + } + private void OnEmoteJump(EntityUid uid, EmoteAnimationComponent component, EmoteJumpActionEvent args) + { + PlayEmoteAnimation(uid, component, EmoteJumpActionPrototype); + } + private void OnEmoteTurn(EntityUid uid, EmoteAnimationComponent component, EmoteTurnActionEvent args) + { + PlayEmoteAnimation(uid, component, EmoteTurnActionPrototype); + } + + public void PlayEmoteAnimation(EntityUid uid, EmoteAnimationComponent component, string emoteId) + { + component.AnimationId = emoteId; + Dirty(component); + } +} diff --git a/Content.Shared/White/Animations/EmoteAnimationComponent.cs b/Content.Shared/White/Animations/EmoteAnimationComponent.cs new file mode 100644 index 0000000000..35a4ff2337 --- /dev/null +++ b/Content.Shared/White/Animations/EmoteAnimationComponent.cs @@ -0,0 +1,41 @@ +using Content.Shared.Actions; +using Content.Shared.Actions.ActionTypes; +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; + +namespace Content.Shared.Animations; + +/// +/// +public class EmoteFlipActionEvent : InstantActionEvent { }; + +/// +/// +public class EmoteJumpActionEvent : InstantActionEvent { }; + +/// +/// +public class EmoteTurnActionEvent : InstantActionEvent { }; + +[RegisterComponent] +[NetworkedComponent] +public class EmoteAnimationComponent : Component +{ + [ViewVariables(VVAccess.ReadWrite)] + public string AnimationId = "none"; + + public InstantAction? FlipAction; + public InstantAction? JumpAction; + public InstantAction? TurnAction; + + [Serializable, NetSerializable] + public class EmoteAnimationComponentState : ComponentState + { + public string AnimationId { get; init; } + + public EmoteAnimationComponentState(string animationId) + { + AnimationId = animationId; + } + } +} diff --git a/Content.Shared/White/Animations/SharedEmoteAnimationSystem.cs b/Content.Shared/White/Animations/SharedEmoteAnimationSystem.cs new file mode 100644 index 0000000000..78934d83dc --- /dev/null +++ b/Content.Shared/White/Animations/SharedEmoteAnimationSystem.cs @@ -0,0 +1,19 @@ +using Robust.Shared.GameStates; +using static Content.Shared.Animations.EmoteAnimationComponent; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Animations; + +public class SharedEmoteAnimationSystem : EntitySystem +{ + public const string EmoteFlipActionPrototype = "EmoteFlip"; + public const string EmoteJumpActionPrototype = "EmoteJump"; + public const string EmoteTurnActionPrototype = "EmoteTurn"; + + [Dependency] public readonly SharedAppearanceSystem _appearance = default!; + [Dependency] public readonly IPrototypeManager _proto = default!; + + public override void Initialize() + { + } +} diff --git a/Resources/Prototypes/Entities/Mobs/Species/base.yml b/Resources/Prototypes/Entities/Mobs/Species/base.yml index 032aab346d..bccf40c76b 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/base.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/base.yml @@ -215,6 +215,7 @@ Female: FemaleHuman Unsexed: MaleHuman - type: Emoting + - type: EmoteAnimation - type: BodyEmotes soundsId: GeneralBodyEmotes - type: Grammar diff --git a/Resources/Prototypes/White/Actions/emotes.yml b/Resources/Prototypes/White/Actions/emotes.yml new file mode 100644 index 0000000000..ccbe31159e --- /dev/null +++ b/Resources/Prototypes/White/Actions/emotes.yml @@ -0,0 +1,66 @@ +# flip animation +- type: instantAction + id: EmoteFlip + name: emote-flip-action-name + description: emote-flip-action-description + icon: Interface/Actions/blight.png + event: !type:EmoteFlipActionEvent + +# jump animation +- type: instantAction + id: EmoteJump + name: emote-jump-action-name + description: emote-jump-action-description + icon: Interface/Actions/blight.png + event: !type:EmoteJumpActionEvent + + # turn around in 4 directions animation +- type: instantAction + id: EmoteTurn + name: emote-turn-action-name + description: emote-turn-action-description + icon: Interface/Actions/blight.png + event: !type:EmoteTurnActionEvent + + +# Using EmoteAnimation from IC action chat +- type: emote + id: EmoteFlip + category: Gesture + buttonText: Сальто + chatMessages: [делает сальто] + chatTriggers: + - сделал сальто + - сделала сальто + - делает сальто + - устроила сальто + - устроил сальто + - ебанул сальтуху + - ебанула сальтуху + - ебашит сальтуху + +- type: emote + id: EmoteJump + category: Gesture + buttonText: Прыгнуть + chatMessages: [прыгает] + chatTriggers: + - прыгает + - прыгнула + - прыгнул + - подпрыгнул + - подпрыгнула + - подскакивает + +- type: emote + id: EmoteTurn + category: Gesture + buttonText: Танцевать + chatMessages: [танцует] + chatTriggers: + - танцует + - кружится + - оборачивается + - танцует + - покружилась + - покружился