Skip to content

Commit

Permalink
[PORT] animated emoting (#224)
Browse files Browse the repository at this point in the history
* flipflap

* jump
  • Loading branch information
Vonsant authored Jan 5, 2025
1 parent cbdc77b commit f4eb95f
Show file tree
Hide file tree
Showing 9 changed files with 281 additions and 1 deletion.
124 changes: 124 additions & 0 deletions Content.Client/_CorvaxNext/Emoting/AnimatedEmotesSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
using Robust.Client.Animations;
using Robust.Shared.Animations;
using Robust.Shared.GameStates;
using Robust.Client.GameObjects;
using Content.Shared.Emoting;
using Content.Shared._CorvaxNext.Emoting;
using System.Numerics;
using Robust.Shared.Prototypes;
using Content.Shared.Chat.Prototypes;

namespace Content.Client._CorvaxNext.Emoting;

public sealed partial class AnimatedEmotesSystem : SharedAnimatedEmotesSystem
{
[Dependency] private readonly AnimationPlayerSystem _anim = 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 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.Zero, 0f),
new AnimationTrackProperty.KeyFrame(Angle.FromDegrees(180), 0.25f),
new AnimationTrackProperty.KeyFrame(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);
}
}
2 changes: 1 addition & 1 deletion Content.Server/Chat/Systems/ChatSystem.Emote.cs
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ private bool AllowedToUseEmote(EntityUid source, EmotePrototype emote)
private void InvokeEmoteEvent(EntityUid uid, EmotePrototype proto)
{
var ev = new EmoteEvent(proto);
RaiseLocalEvent(uid, ref ev);
RaiseLocalEvent(uid, ref ev, true); // Corvax-Next-AnimateEmote
}
}

Expand Down
29 changes: 29 additions & 0 deletions Content.Server/_CorvaxNext/Emoting/AnimatedEmotesSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Robust.Shared.GameStates;
using Content.Server.Chat.Systems;
using Content.Shared.Chat.Prototypes;
using Content.Shared.Emoting;
using Content.Shared._CorvaxNext.Emoting;
using Robust.Shared.Prototypes;

namespace Content.Server._CorvaxNext.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);
}
}
5 changes: 5 additions & 0 deletions Content.Shared/Chat/Prototypes/EmotePrototype.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ public sealed partial class EmotePrototype : IPrototype
/// </summary>
[DataField]
public HashSet<string> ChatTriggers = new();

// Corvax-Next-AnimateEmote-Start
[DataField]
public object? Event = null;
// Corvax-Next-AnimateEmote-End
}

/// <summary>
Expand Down
28 changes: 28 additions & 0 deletions Content.Shared/_CorvaxNext/Emoting/AnimatedEmotesComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using Content.Shared.Chat.Prototypes;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;

namespace Content.Shared._CorvaxNext.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;
}
}
18 changes: 18 additions & 0 deletions Content.Shared/_CorvaxNext/Emoting/SharedAnimatedEmotesSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Robust.Shared.GameStates;

namespace Content.Shared._CorvaxNext.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);
}
}
7 changes: 7 additions & 0 deletions Resources/Locale/ru-RU/_corvaxnext/emotes.ftl
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
chat-emote-name-flip = Сделать сальто
chat-emote-name-spin = Покрутиться
chat-emote-name-jump = Прыгнуть
chat-emote-msg-flip = делает сальто!
chat-emote-msg-spin = вращается!
chat-emote-msg-jump = прыгает!
1 change: 1 addition & 0 deletions Resources/Prototypes/Entities/Mobs/base.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
- type: TTS # Corvax-TTS
- type: RequireProjectileTarget
active: False
- type: AnimatedEmotes # Corvax-Next-AutoAnimate

- type: entity
save: false
Expand Down
68 changes: 68 additions & 0 deletions Resources/Prototypes/_CorvaxNext/Actions/emotes.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
- type: emote
id: Flip
name: chat-emote-name-flip
chatMessages: ["chat-emote-msg-flip"]
chatTriggers:
- flip
- flips
- flipping
- does a flip
- do a flip
- backflip
- frontflip
- somersault
- cartwheel
- прыжок с переворотом
- кувырок
- сальто
- делает сальто
- сделал сальто
- делает сальтуху
- прыгает с переворотом
event: !type:AnimationFlipEmoteEvent

- type: emote
id: Spin
name: chat-emote-name-spin
chatMessages: ["chat-emote-msg-spin"]
chatTriggers:
- spin
- spins
- spinning
- twirl
- twirls
- twirling
- rotates
- rotating
- вращается
- вращается на месте
- кружится
- кружится на месте
- вертится
- закручивается
- разворот
event: !type:AnimationSpinEmoteEvent

- type: emote
id: Jump
name: chat-emote-name-jump
chatMessages: ["chat-emote-msg-jump"]
chatTriggers:
- jump
- jumps
- jumping
- hops
- hopping
- leaps
- leaping
- bounce
- bounces
- bouncing
- прыгает
- прыгнул
- подпрыгнул
- прыгает вверх
- подскакивает
- скачет
- прыжок
event: !type:AnimationJumpEmoteEvent

0 comments on commit f4eb95f

Please sign in to comment.