Tail wagging (#19573)

* MVP

* Uncomment animated prototypes

* Disable wagging on death

* Move component to server

* Looped tail animation

* Apply front tail template

* Disable animated markings globally

* Add emote sending

* Update documentation

* Move locale

* Use static instantAction & remove action on comp del

* Use fluent POSS-ADJ

* Update docs

* Add copyright

* Update copyright

* Update license & copyright

* Move to main directory & format meta.json

* Fix path

* Change namespace

* Remove empty meta.json

* Update

* REMOVE unnecessary IsNullOrWhiteSpace check

Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com>

* Move animated markings to main file

* Use emotes

* new

* fix

* fix

* Tests, pls

* fix dixel

* Remove networked from wagging comp

* Remove unused import

* Remove unused imports

* Move wagging comp to shared

* Revert the emotes

If we're getting it the action is better.

---------

Co-authored-by: DrSmugleaf <DrSmugleaf@users.noreply.github.com>
Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
This commit is contained in:
Morb
2024-01-14 10:52:07 +03:00
committed by GitHub
parent 88db476d27
commit 9063cfe454
13 changed files with 527 additions and 3 deletions

View File

@@ -0,0 +1,110 @@
using Content.Server.Actions;
using Content.Server.Chat.Systems;
using Content.Server.Humanoid;
using Content.Shared.Humanoid;
using Content.Shared.Humanoid.Markings;
using Content.Shared.Mobs;
using Content.Shared.Toggleable;
using Content.Shared.Wagging;
using Robust.Shared.Prototypes;
namespace Content.Server.Wagging;
/// <summary>
/// Adds an action to toggle wagging animation for tails markings that supporting this
/// </summary>
public sealed class WaggingSystem : EntitySystem
{
[Dependency] private readonly ActionsSystem _actions = default!;
[Dependency] private readonly ChatSystem _chat = default!;
[Dependency] private readonly HumanoidAppearanceSystem _humanoidAppearance = default!;
[Dependency] private readonly IPrototypeManager _prototype = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<WaggingComponent, MapInitEvent>(OnWaggingMapInit);
SubscribeLocalEvent<WaggingComponent, ComponentShutdown>(OnWaggingShutdown);
SubscribeLocalEvent<WaggingComponent, ToggleActionEvent>(OnWaggingToggle);
SubscribeLocalEvent<WaggingComponent, MobStateChangedEvent>(OnMobStateChanged);
}
private void OnWaggingMapInit(EntityUid uid, WaggingComponent component, MapInitEvent args)
{
_actions.AddAction(uid, ref component.ActionEntity, component.Action, uid);
}
private void OnWaggingShutdown(EntityUid uid, WaggingComponent component, ComponentShutdown args)
{
_actions.RemoveAction(uid, component.ActionEntity);
}
private void OnWaggingToggle(EntityUid uid, WaggingComponent component, ref ToggleActionEvent args)
{
if (args.Handled)
return;
TryToggleWagging(uid, wagging: component);
}
private void OnMobStateChanged(EntityUid uid, WaggingComponent component, MobStateChangedEvent args)
{
if (args.NewMobState != MobState.Dead)
return;
if (component.Wagging)
TryToggleWagging(uid, wagging: component);
}
public bool TryToggleWagging(EntityUid uid, WaggingComponent? wagging = null, HumanoidAppearanceComponent? humanoid = null)
{
if (!Resolve(uid, ref wagging, ref humanoid))
return false;
if (!humanoid.MarkingSet.Markings.TryGetValue(MarkingCategories.Tail, out var markings))
return false;
if (markings.Count == 0)
return false;
wagging.Wagging = !wagging.Wagging;
for (var idx = 0; idx < markings.Count; idx++) // Animate all possible tails
{
var currentMarkingId = markings[idx].MarkingId;
string newMarkingId;
if (wagging.Wagging)
{
newMarkingId = $"{currentMarkingId}{wagging.Suffix}";
}
else
{
if (currentMarkingId.EndsWith(wagging.Suffix))
{
newMarkingId = currentMarkingId[..^wagging.Suffix.Length];
}
else
{
newMarkingId = currentMarkingId;
Log.Warning($"Unable to revert wagging for {currentMarkingId}");
}
}
if (!_prototype.HasIndex<MarkingPrototype>(newMarkingId))
{
Log.Warning($"{ToPrettyString(uid)} tried toggling wagging but {newMarkingId} marking doesn't exist");
continue;
}
_humanoidAppearance.SetMarkingId(uid, MarkingCategories.Tail, idx, newMarkingId,
humanoid: humanoid);
}
var emoteText = Loc.GetString(wagging.Wagging ? "wagging-emote-start" : "wagging-emote-stop", ("ent", uid));
_chat.TrySendInGameICMessage(uid, emoteText, InGameICChatType.Emote, ChatTransmitRange.Normal); // Ok while emotes dont have radial menu
return true;
}
}

View File

@@ -562,7 +562,7 @@ public abstract class SharedActionsSystem : EntitySystem
/// <param name="actionId">Action entity to add</param>
/// <param name="component">The <see cref="performer"/>'s action component of </param>
/// <param name="actionPrototypeId">The action entity prototype id to use if <see cref="actionId"/> is invalid.</param>
/// <param name="container">The entity that contains/enables this action (e.g., flashlight)..</param>
/// <param name="container">The entity that contains/enables this action (e.g., flashlight).</param>
public bool AddAction(EntityUid performer,
[NotNullWhen(true)] ref EntityUid? actionId,
string? actionPrototypeId,

View File

@@ -0,0 +1,33 @@
using Content.Shared.Chat.Prototypes;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Shared.Wagging;
/// <summary>
/// An emoting wag for markings.
/// </summary>
[RegisterComponent, NetworkedComponent]
public sealed partial class WaggingComponent : Component
{
[DataField]
public EntProtoId Action = "ActionToggleWagging";
[DataField]
public EntityUid? ActionEntity;
[DataField]
public ProtoId<EmotePrototype> EmoteId = "WagTail";
/// <summary>
/// Suffix to add to get the animated marking.
/// </summary>
public string Suffix = "Animated";
/// <summary>
/// Is the entity currently wagging.
/// </summary>
[DataField]
public bool Wagging = false;
}

View File

@@ -0,0 +1,5 @@
action-name-toggle-wagging = Wagging Tail
action-description-toggle-wagging = Start or stop wagging tail.
wagging-emote-start = starts wagging {POSS-ADJ($ent)} tail.
wagging-emote-stop = stops wagging {POSS-ADJ($ent)} tail.

View File

@@ -315,3 +315,15 @@
event: !type:ToggleEyesActionEvent
useDelay: 1 # so u cant give yourself and observers eyestrain by rapidly spamming the action
- type: entity
id: ActionToggleWagging
name: action-name-toggle-wagging
description: action-description-toggle-wagging
noSpawn: true
components:
- type: InstantAction
icon: { sprite: Mobs/Customization/reptilian_parts.rsi, state: tail_smooth_behind }
iconOn: { sprite: Mobs/Customization/reptilian_parts.rsi, state: tail_smooth_behind }
itemIconStyle: NoItem
useDelay: 1 # emote spam
event: !type:ToggleActionEvent

View File

@@ -280,7 +280,7 @@
sprites:
- sprite: Mobs/Customization/reptilian_parts.rsi
state: horns_kobold_ears
- type: marking
id: LizardHornsFloppyKoboldEars
bodyPart: HeadSide
@@ -307,3 +307,40 @@
sprites:
- sprite: Mobs/Customization/reptilian_parts.rsi
state: body_backspikes
# Animated
- type: marking
id: LizardTailSmoothAnimated
bodyPart: Tail
markingCategory: Tail
speciesRestriction: []
sprites:
- sprite: Mobs/Customization/reptilian_parts.rsi
state: tail_smooth_wagging
- type: marking
id: LizardTailSpikesAnimated
bodyPart: Tail
markingCategory: Tail
speciesRestriction: []
sprites:
- sprite: Mobs/Customization/reptilian_parts.rsi
state: tail_spikes_wagging
- type: marking
id: LizardTailLTigerAnimated
bodyPart: Tail
markingCategory: Tail
speciesRestriction: []
sprites:
- sprite: Mobs/Customization/reptilian_parts.rsi
state: tail_ltiger_wagging
- type: marking
id: LizardTailDTigerAnimated
bodyPart: Tail
markingCategory: Tail
speciesRestriction: []
sprites:
- sprite: Mobs/Customization/reptilian_parts.rsi
state: tail_dtiger_wagging

View File

@@ -59,6 +59,7 @@
heatDamage:
types:
Heat : 1.5 #per second, scales with temperature & other constants
- type: Wagging
- type: entity
parent: BaseSpeciesDummy

View File

@@ -0,0 +1,14 @@
- type: emote
id: WagTail
chatMessages: [wags tail]
chatTriggers:
- wag
- wag.
- wags
- wags.
- wagging
- wagging.
- wag tail
- wag tail.
- wags tail
- wags tail.

View File

@@ -1,7 +1,7 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "https://github.com/Skyrat-SS13/Skyrat-tg/tree/40e3cdbb15b8bc0d5ef2fb46133adf805bda5297, while Argali, Ayrshire, Myrsore and Bighorn are drawn by Ubaser, and Kobold Ears are drawn by Pigeonpeas. Body_underbelly made by Nairod(github) for SS14. Large is drawn by Ubaser.",
"copyright": "https://github.com/Skyrat-SS13/Skyrat-tg/tree/40e3cdbb15b8bc0d5ef2fb46133adf805bda5297, while Argali, Ayrshire, Myrsore and Bighorn are drawn by Ubaser, and Kobold Ears are drawn by Pigeonpeas. Body_underbelly made by Nairod(github) for SS14. Large drawn by Ubaser. Wagging tail by SonicDC.",
"size": {
"x": 32,
"y": 32
@@ -67,6 +67,318 @@
"name": "tail_ltiger",
"directions": 4
},
{
"name": "tail_smooth_wagging",
"directions": 4,
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
],
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
],
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
],
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "tail_dtiger_wagging",
"directions": 4,
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
],
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
],
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
],
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "tail_ltiger_wagging",
"directions": 4,
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
],
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
],
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
],
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "tail_spikes_wagging",
"directions": 4,
"delays": [
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
],
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
],
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
],
[
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1,
0.1
]
]
},
{
"name": "snout_round",
"directions": 4

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB