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:
110
Content.Server/Wagging/WaggingSystem.cs
Normal file
110
Content.Server/Wagging/WaggingSystem.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
33
Content.Shared/Wagging/WaggingComponent.cs
Normal file
33
Content.Shared/Wagging/WaggingComponent.cs
Normal 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;
|
||||
}
|
||||
5
Resources/Locale/en-US/actions/actions/wagging.ftl
Normal file
5
Resources/Locale/en-US/actions/actions/wagging.ftl
Normal 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.
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
heatDamage:
|
||||
types:
|
||||
Heat : 1.5 #per second, scales with temperature & other constants
|
||||
- type: Wagging
|
||||
|
||||
- type: entity
|
||||
parent: BaseSpeciesDummy
|
||||
|
||||
14
Resources/Prototypes/Voice/tail_emotes.yml
Normal file
14
Resources/Prototypes/Voice/tail_emotes.yml
Normal 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.
|
||||
@@ -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 |
Reference in New Issue
Block a user