diff --git a/Content.Client/Chat/TypingIndicator/TypingIndicatorSystem.cs b/Content.Client/Chat/TypingIndicator/TypingIndicatorSystem.cs new file mode 100644 index 0000000000..a6a1c93b07 --- /dev/null +++ b/Content.Client/Chat/TypingIndicator/TypingIndicatorSystem.cs @@ -0,0 +1,86 @@ +using Content.Shared.CCVar; +using Content.Shared.Chat.TypingIndicator; +using Robust.Client.Player; +using Robust.Shared.Configuration; +using Robust.Shared.Timing; + +namespace Content.Client.Chat.TypingIndicator; + +// Client-side typing system tracks user input in chat box +public sealed class TypingIndicatorSystem : SharedTypingIndicatorSystem +{ + [Dependency] private readonly IGameTiming _time = default!; + [Dependency] private readonly IPlayerManager _playerManager = default!; + [Dependency] private readonly IConfigurationManager _cfg = default!; + + private readonly TimeSpan _typingTimeout = TimeSpan.FromSeconds(2); + private TimeSpan _lastTextChange; + private bool _isClientTyping; + + public override void Initialize() + { + base.Initialize(); + _cfg.OnValueChanged(CCVars.ChatShowTypingIndicator, OnShowTypingChanged); + } + + public void ClientChangedChatText() + { + // don't update it if player don't want to show typing indicator + if (!_cfg.GetCVar(CCVars.ChatShowTypingIndicator)) + return; + + // client typed something - show typing indicator + ClientUpdateTyping(true); + _lastTextChange = _time.CurTime; + } + + public void ClientSubmittedChatText() + { + // don't update it if player don't want to show typing + if (!_cfg.GetCVar(CCVars.ChatShowTypingIndicator)) + return; + + // client submitted text - hide typing indicator + ClientUpdateTyping(false); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + // check if client didn't changed chat text box for a long time + if (_isClientTyping) + { + var dif = _time.CurTime - _lastTextChange; + if (dif > _typingTimeout) + { + // client didn't typed anything for a long time - hide indicator + ClientUpdateTyping(false); + } + } + } + + private void ClientUpdateTyping(bool isClientTyping) + { + if (_isClientTyping == isClientTyping) + return; + _isClientTyping = isClientTyping; + + // check if player controls any pawn + var playerPawn = _playerManager.LocalPlayer?.ControlledEntity; + if (playerPawn == null) + return; + + // send a networked event to server + RaiseNetworkEvent(new TypingChangedEvent(playerPawn.Value, isClientTyping)); + } + + private void OnShowTypingChanged(bool showTyping) + { + // hide typing indicator immediately if player don't want to show it anymore + if (!showTyping) + { + ClientUpdateTyping(false); + } + } +} diff --git a/Content.Client/Chat/TypingIndicator/TypingIndicatorVisualizerSystem.cs b/Content.Client/Chat/TypingIndicator/TypingIndicatorVisualizerSystem.cs new file mode 100644 index 0000000000..0f261b69ef --- /dev/null +++ b/Content.Client/Chat/TypingIndicator/TypingIndicatorVisualizerSystem.cs @@ -0,0 +1,50 @@ +using Content.Shared.Chat.TypingIndicator; +using Robust.Client.GameObjects; +using Robust.Client.Graphics; +using Robust.Shared.Prototypes; + +namespace Content.Client.Chat.TypingIndicator; + +public sealed class TypingIndicatorVisualizerSystem : VisualizerSystem +{ + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnInit); + } + + private void OnInit(EntityUid uid, TypingIndicatorComponent component, ComponentInit args) + { + if (!TryComp(uid, out SpriteComponent? sprite)) + return; + + if (!_prototypeManager.TryIndex(component.Prototype, out var proto)) + { + Logger.Error($"Unknown typing indicator id: {component.Prototype}"); + return; + } + + var layer = sprite.LayerMapReserveBlank(TypingIndicatorLayers.Base); + sprite.LayerSetRSI(layer, proto.SpritePath); + sprite.LayerSetState(layer, proto.TypingState); + sprite.LayerSetShader(layer, proto.Shader); + sprite.LayerSetOffset(layer, proto.Offset); + sprite.LayerSetVisible(layer, false); + } + + protected override void OnAppearanceChange(EntityUid uid, TypingIndicatorComponent component, ref AppearanceChangeEvent args) + { + base.OnAppearanceChange(uid, component, ref args); + + if (!TryComp(uid, out SpriteComponent? sprite)) + return; + + args.Component.TryGetData(TypingIndicatorVisuals.IsTyping, out bool isTyping); + if (sprite.LayerMapTryGet(TypingIndicatorLayers.Base, out var layer)) + { + sprite.LayerSetVisible(layer, isTyping); + } + } +} diff --git a/Content.Client/Chat/UI/ChatBox.xaml.cs b/Content.Client/Chat/UI/ChatBox.xaml.cs index 5b31ca0526..d6ac16ee04 100644 --- a/Content.Client/Chat/UI/ChatBox.xaml.cs +++ b/Content.Client/Chat/UI/ChatBox.xaml.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using Content.Client.Alerts.UI; using Content.Client.Chat.Managers; +using Content.Client.Chat.TypingIndicator; using Content.Client.Resources; using Content.Client.Stylesheets; using Content.Shared.Chat; @@ -475,6 +476,9 @@ namespace Content.Client.Chat.UI { // Update channel select button to correct channel if we have a prefix. UpdateChannelSelectButton(); + + // Warn typing indicator about change + EntitySystem.Get().ClientChangedChatText(); } private static ChatSelectChannel GetChannelFromPrefix(char prefix) @@ -518,6 +522,9 @@ namespace Content.Client.Chat.UI private void Input_OnTextEntered(LineEdit.LineEditEventArgs args) { + // Warn typing indicator about entered text + EntitySystem.Get().ClientSubmittedChatText(); + if (!string.IsNullOrWhiteSpace(args.Text)) { var (prefixChannel, text) = SplitInputContents(); diff --git a/Content.Server/Chat/TypingIndicator/TypingIndicatorSystem.cs b/Content.Server/Chat/TypingIndicator/TypingIndicatorSystem.cs new file mode 100644 index 0000000000..1c919b7ecf --- /dev/null +++ b/Content.Server/Chat/TypingIndicator/TypingIndicatorSystem.cs @@ -0,0 +1,63 @@ +using Content.Shared.ActionBlocker; +using Content.Shared.Chat.TypingIndicator; +using Robust.Server.GameObjects; + +namespace Content.Server.Chat.TypingIndicator; + +// Server-side typing system +// It receives networked typing events from clients +// And sync typing indicator using appearance component +public sealed class TypingIndicatorSystem : SharedTypingIndicatorSystem +{ + [Dependency] private readonly ActionBlockerSystem _actionBlocker = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnPlayerAttached); + SubscribeLocalEvent(OnPlayerDetached); + SubscribeNetworkEvent(OnClientTypingChanged); + } + + private void OnPlayerAttached(PlayerAttachedEvent ev) + { + // when player poses entity we want to make sure that there is typing indicator + EnsureComp(ev.Entity); + // we also need appearance component to sync visual state + EnsureComp(ev.Entity); + } + + private void OnPlayerDetached(EntityUid uid, TypingIndicatorComponent component, PlayerDetachedEvent args) + { + // player left entity body - hide typing indicator + SetTypingIndicatorEnabled(uid, false); + } + + private void OnClientTypingChanged(TypingChangedEvent ev) + { + // make sure that this entity still exist + if (!Exists(ev.Uid)) + { + Logger.Warning($"Client attached entity {ev.Uid} from TypingChangedEvent doesn't exist on server."); + return; + } + + // check if this entity can speak or emote + if (!_actionBlocker.CanSpeak(ev.Uid) && !_actionBlocker.CanEmote(ev.Uid)) + { + // nah, make sure that typing indicator is disabled + SetTypingIndicatorEnabled(ev.Uid, false); + return; + } + + SetTypingIndicatorEnabled(ev.Uid, ev.IsTyping); + } + + private void SetTypingIndicatorEnabled(EntityUid uid, bool isEnabled, AppearanceComponent? appearance = null) + { + if (!Resolve(uid, ref appearance, false)) + return; + + appearance.SetData(TypingIndicatorVisuals.IsTyping, isEnabled); + } +} diff --git a/Content.Shared/CCVar/CCVars.cs b/Content.Shared/CCVar/CCVars.cs index 2457d997ed..dd747870f1 100644 --- a/Content.Shared/CCVar/CCVars.cs +++ b/Content.Shared/CCVar/CCVars.cs @@ -820,6 +820,9 @@ namespace Content.Shared.CCVar public static readonly CVarDef ChatSanitizerEnabled = CVarDef.Create("chat.chat_sanitizer_enabled", true, CVar.SERVERONLY); + public static readonly CVarDef ChatShowTypingIndicator = + CVarDef.Create("chat.show_typing_indicator", true, CVar.CLIENTONLY); + /* * AFK */ diff --git a/Content.Shared/Chat/TypingIndicator/SharedTypingIndicatorSystem.cs b/Content.Shared/Chat/TypingIndicator/SharedTypingIndicatorSystem.cs new file mode 100644 index 0000000000..4c5ac2ca80 --- /dev/null +++ b/Content.Shared/Chat/TypingIndicator/SharedTypingIndicatorSystem.cs @@ -0,0 +1,9 @@ +namespace Content.Shared.Chat.TypingIndicator; + +/// +/// Sync typing indicator icon between client and server. +/// +public abstract class SharedTypingIndicatorSystem : EntitySystem +{ + +} diff --git a/Content.Shared/Chat/TypingIndicator/TypingChangedEvent.cs b/Content.Shared/Chat/TypingIndicator/TypingChangedEvent.cs new file mode 100644 index 0000000000..5e364d395a --- /dev/null +++ b/Content.Shared/Chat/TypingIndicator/TypingChangedEvent.cs @@ -0,0 +1,20 @@ +using Robust.Shared.Serialization; + +namespace Content.Shared.Chat.TypingIndicator; + +/// +/// Networked event from client. +/// Send to server when client started/stopped typing in chat input field. +/// +[Serializable, NetSerializable] +public sealed class TypingChangedEvent : EntityEventArgs +{ + public readonly EntityUid Uid; + public readonly bool IsTyping; + + public TypingChangedEvent(EntityUid uid, bool isTyping) + { + Uid = uid; + IsTyping = isTyping; + } +} diff --git a/Content.Shared/Chat/TypingIndicator/TypingIndicatorComponent.cs b/Content.Shared/Chat/TypingIndicator/TypingIndicatorComponent.cs new file mode 100644 index 0000000000..9878628ef0 --- /dev/null +++ b/Content.Shared/Chat/TypingIndicator/TypingIndicatorComponent.cs @@ -0,0 +1,20 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + +namespace Content.Shared.Chat.TypingIndicator; + +/// +/// Show typing indicator icon when player typing text in chat box. +/// Added automatically when player poses entity. +/// +[RegisterComponent, NetworkedComponent] +[Friend(typeof(SharedTypingIndicatorSystem))] +public sealed class TypingIndicatorComponent : Component +{ + /// + /// Prototype id that store all visual info about typing indicator. + /// + [ViewVariables(VVAccess.ReadOnly)] + [DataField("proto", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string Prototype = "default"; +} diff --git a/Content.Shared/Chat/TypingIndicator/TypingIndicatorPrototype.cs b/Content.Shared/Chat/TypingIndicator/TypingIndicatorPrototype.cs new file mode 100644 index 0000000000..e693b9099d --- /dev/null +++ b/Content.Shared/Chat/TypingIndicator/TypingIndicatorPrototype.cs @@ -0,0 +1,27 @@ +using Robust.Shared.Prototypes; +using Robust.Shared.Utility; + +namespace Content.Shared.Chat.TypingIndicator; + +/// +/// Prototype to store chat typing indicator visuals. +/// +[Prototype("typingIndicator")] +public sealed class TypingIndicatorPrototype : IPrototype +{ + [IdDataFieldAttribute] + public string ID { get; } = default!; + + [DataField("spritePath")] + public ResourcePath SpritePath = new("/Textures/Effects/speech.rsi"); + + [DataField("typingState", required: true)] + public string TypingState = default!; + + [DataField("offset")] + public Vector2 Offset = new(0.5f, 0.5f); + + [DataField("shader")] + public string Shader = "unshaded"; + +} diff --git a/Content.Shared/Chat/TypingIndicator/TypingIndicatorVisuals.cs b/Content.Shared/Chat/TypingIndicator/TypingIndicatorVisuals.cs new file mode 100644 index 0000000000..0368819eff --- /dev/null +++ b/Content.Shared/Chat/TypingIndicator/TypingIndicatorVisuals.cs @@ -0,0 +1,15 @@ +using Robust.Shared.Serialization; + +namespace Content.Shared.Chat.TypingIndicator; + +[Serializable, NetSerializable] +public enum TypingIndicatorVisuals : byte +{ + IsTyping +} + +[Serializable] +public enum TypingIndicatorLayers : byte +{ + Base +} diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml b/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml index 4ade2dc49f..dd183bc2af 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml @@ -68,6 +68,8 @@ Otherwise, wreak havoc on the station! - type: ReplacementAccent accent: genericAggressive + - type: TypingIndicator + proto: alien - type: NoSlip - type: entity @@ -84,6 +86,8 @@ sprite: Mobs/Aliens/Carps/magic.rsi - type: GhostTakeoverAvailable name: magicarp + - type: TypingIndicator + proto: guardian - type: entity name: holocarp @@ -110,6 +114,8 @@ - Opaque - type: GhostTakeoverAvailable name: holocarp + - type: TypingIndicator + proto: robot - type: entity id: MobCarpSalvage diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml b/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml index d5ed41c9af..8c355b9442 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml @@ -79,6 +79,8 @@ rules: You are an antagonist, smack, slash, and wack! - type: ReplacementAccent accent: xeno + - type: TypingIndicator + proto: alien - type: Temperature heatDamageThreshold: 360 coldDamageThreshold: -150 diff --git a/Resources/Prototypes/Entities/Mobs/Player/guardian.yml b/Resources/Prototypes/Entities/Mobs/Player/guardian.yml index ed944f8e51..7597e72c68 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/guardian.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/guardian.yml @@ -56,6 +56,8 @@ - type: Internals - type: Examiner - type: Speech + - type: TypingIndicator + proto: guardian - type: Pullable - type: UnarmedCombat range: 2 @@ -89,6 +91,8 @@ description: Listen to your owner. Don't tank damage. Punch people hard. - type: NameIdentifier group: Holoparasite + - type: TypingIndicator + proto: holo - type: Sprite layers: - state: tech_base diff --git a/Resources/Prototypes/Entities/Objects/Fun/pai.yml b/Resources/Prototypes/Entities/Objects/Fun/pai.yml index 4721e1d6ac..3265295dfd 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/pai.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/pai.yml @@ -36,6 +36,8 @@ - type: GhostRadio - type: DoAfter - type: Actions + - type: TypingIndicator + proto: robot - type: Speech speechSounds: Pai # This has to be installed because otherwise they're not "alive", diff --git a/Resources/Prototypes/typing_indicator.yml b/Resources/Prototypes/typing_indicator.yml new file mode 100644 index 0000000000..bc6f32e31e --- /dev/null +++ b/Resources/Prototypes/typing_indicator.yml @@ -0,0 +1,19 @@ +- type: typingIndicator + id: default + typingState: default0 + +- type: typingIndicator + id: robot + typingState: robot0 + +- type: typingIndicator + id: alien + typingState: alien0 + +- type: typingIndicator + id: guardian + typingState: guardian0 + +- type: typingIndicator + id: holo + typingState: holo0 diff --git a/Resources/Textures/Effects/speech.rsi/alien0.png b/Resources/Textures/Effects/speech.rsi/alien0.png new file mode 100644 index 0000000000..e8b08e8c3b Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/alien0.png differ diff --git a/Resources/Textures/Effects/speech.rsi/alien1.png b/Resources/Textures/Effects/speech.rsi/alien1.png new file mode 100644 index 0000000000..03703c2858 Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/alien1.png differ diff --git a/Resources/Textures/Effects/speech.rsi/alien2.png b/Resources/Textures/Effects/speech.rsi/alien2.png new file mode 100644 index 0000000000..0362e4bc29 Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/alien2.png differ diff --git a/Resources/Textures/Effects/speech.rsi/alienroyal0.png b/Resources/Textures/Effects/speech.rsi/alienroyal0.png new file mode 100644 index 0000000000..daa2836f39 Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/alienroyal0.png differ diff --git a/Resources/Textures/Effects/speech.rsi/alienroyal1.png b/Resources/Textures/Effects/speech.rsi/alienroyal1.png new file mode 100644 index 0000000000..e557acaa4b Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/alienroyal1.png differ diff --git a/Resources/Textures/Effects/speech.rsi/alienroyal2.png b/Resources/Textures/Effects/speech.rsi/alienroyal2.png new file mode 100644 index 0000000000..76b4be2ca4 Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/alienroyal2.png differ diff --git a/Resources/Textures/Effects/speech.rsi/blob0.png b/Resources/Textures/Effects/speech.rsi/blob0.png new file mode 100644 index 0000000000..41dc2180d0 Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/blob0.png differ diff --git a/Resources/Textures/Effects/speech.rsi/blob1.png b/Resources/Textures/Effects/speech.rsi/blob1.png new file mode 100644 index 0000000000..a7f6f38ee4 Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/blob1.png differ diff --git a/Resources/Textures/Effects/speech.rsi/blob2.png b/Resources/Textures/Effects/speech.rsi/blob2.png new file mode 100644 index 0000000000..a7a83d2317 Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/blob2.png differ diff --git a/Resources/Textures/Effects/speech.rsi/clock0.png b/Resources/Textures/Effects/speech.rsi/clock0.png new file mode 100644 index 0000000000..30722223b7 Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/clock0.png differ diff --git a/Resources/Textures/Effects/speech.rsi/clock1.png b/Resources/Textures/Effects/speech.rsi/clock1.png new file mode 100644 index 0000000000..dc4a80a73b Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/clock1.png differ diff --git a/Resources/Textures/Effects/speech.rsi/clock2.png b/Resources/Textures/Effects/speech.rsi/clock2.png new file mode 100644 index 0000000000..48b4f806ec Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/clock2.png differ diff --git a/Resources/Textures/Effects/speech.rsi/default0.png b/Resources/Textures/Effects/speech.rsi/default0.png new file mode 100644 index 0000000000..029892d264 Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/default0.png differ diff --git a/Resources/Textures/Effects/speech.rsi/default1.png b/Resources/Textures/Effects/speech.rsi/default1.png new file mode 100644 index 0000000000..b4bd545633 Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/default1.png differ diff --git a/Resources/Textures/Effects/speech.rsi/default2.png b/Resources/Textures/Effects/speech.rsi/default2.png new file mode 100644 index 0000000000..43c4aaaea9 Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/default2.png differ diff --git a/Resources/Textures/Effects/speech.rsi/guardian0.png b/Resources/Textures/Effects/speech.rsi/guardian0.png new file mode 100644 index 0000000000..859c4936bd Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/guardian0.png differ diff --git a/Resources/Textures/Effects/speech.rsi/guardian1.png b/Resources/Textures/Effects/speech.rsi/guardian1.png new file mode 100644 index 0000000000..d35ecff026 Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/guardian1.png differ diff --git a/Resources/Textures/Effects/speech.rsi/guardian2.png b/Resources/Textures/Effects/speech.rsi/guardian2.png new file mode 100644 index 0000000000..fb64f26e52 Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/guardian2.png differ diff --git a/Resources/Textures/Effects/speech.rsi/holo0.png b/Resources/Textures/Effects/speech.rsi/holo0.png new file mode 100644 index 0000000000..002e0c835f Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/holo0.png differ diff --git a/Resources/Textures/Effects/speech.rsi/holo1.png b/Resources/Textures/Effects/speech.rsi/holo1.png new file mode 100644 index 0000000000..3850d981da Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/holo1.png differ diff --git a/Resources/Textures/Effects/speech.rsi/holo2.png b/Resources/Textures/Effects/speech.rsi/holo2.png new file mode 100644 index 0000000000..636d3ea31a Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/holo2.png differ diff --git a/Resources/Textures/Effects/speech.rsi/lawyer0.png b/Resources/Textures/Effects/speech.rsi/lawyer0.png new file mode 100644 index 0000000000..6b804ab734 Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/lawyer0.png differ diff --git a/Resources/Textures/Effects/speech.rsi/lawyer1.png b/Resources/Textures/Effects/speech.rsi/lawyer1.png new file mode 100644 index 0000000000..7a8a817dd1 Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/lawyer1.png differ diff --git a/Resources/Textures/Effects/speech.rsi/lawyer2.png b/Resources/Textures/Effects/speech.rsi/lawyer2.png new file mode 100644 index 0000000000..2a36a4cd52 Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/lawyer2.png differ diff --git a/Resources/Textures/Effects/speech.rsi/machine0.png b/Resources/Textures/Effects/speech.rsi/machine0.png new file mode 100644 index 0000000000..3d039ad4d9 Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/machine0.png differ diff --git a/Resources/Textures/Effects/speech.rsi/machine1.png b/Resources/Textures/Effects/speech.rsi/machine1.png new file mode 100644 index 0000000000..5e5930bf2b Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/machine1.png differ diff --git a/Resources/Textures/Effects/speech.rsi/machine2.png b/Resources/Textures/Effects/speech.rsi/machine2.png new file mode 100644 index 0000000000..a7f223a8e3 Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/machine2.png differ diff --git a/Resources/Textures/Effects/speech.rsi/meta.json b/Resources/Textures/Effects/speech.rsi/meta.json new file mode 100644 index 0000000000..5a42d7ecfd --- /dev/null +++ b/Resources/Textures/Effects/speech.rsi/meta.json @@ -0,0 +1,345 @@ +{ + "version": 1, + "size": { + "x": 64, + "y": 64 + }, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation at commit https://github.com/tgstation/tgstation/commit/c6e3401f2e7e1e55c57060cdf956a98ef1fefc24", + "states": [ + { + "name": "alien0", + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2, + 0.2, + 0.4 + ] + ] + }, + { + "name": "alien1" + }, + { + "name": "alien2" + }, + { + "name": "alienroyal0", + + "delays": [ + [ + 0.2, + 0.3, + 0.3, + 0.3, + 0.3, + 0.5 + ] + ] + }, + { + "name": "alienroyal1", + }, + { + "name": "alienroyal2" + }, + { + "name": "blob0", + "delays": [ + [ + 0.2, + 0.4, + 0.4, + 0.4, + 0.4, + 0.4 + ] + ] + }, + { + "name": "blob1" + }, + { + "name": "blob2" + }, + { + "name": "clock0", + "delays": [ + [ + 0.2, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.3 + ] + ] + }, + { + "name": "clock1", + "delays": [ + [ + 0.6, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "clock2", + "delays": [ + [ + 0.6, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "default0", + "delays": [ + [ + 0.2, + 0.3, + 0.3, + 0.5 + ] + ] + }, + { + "name": "default1" + }, + { + "name": "default2" + }, + { + "name": "guardian0", + "delays": [ + [ + 0.4, + 0.4, + 0.4, + 0.6 + ] + ] + }, + { + "name": "guardian1" + }, + { + "name": "guardian2" + }, + { + "name": "holo0", + "delays": [ + [ + 0.2, + 0.1, + 0.1, + 0.1, + 0.1, + 0.2 + ] + ] + }, + { + "name": "holo1" + }, + { + "name": "holo2" + }, + { + "name": "lawyer0", + "delays": [ + [ + 0.3, + 0.3, + 0.3, + 0.4 + ] + ] + }, + { + "name": "lawyer1", + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "lawyer2", + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "machine0", + "delays": [ + [ + 0.4, + 0.4, + 0.4, + 0.4 + ] + ] + }, + { + "name": "machine1" + }, + { + "name": "machine2" + }, + { + "name": "robot0", + "delays": [ + [ + 0.4, + 0.4, + 0.4, + 0.4 + ] + ] + }, + { + "name": "robot1" + }, + { + "name": "robot2" + }, + { + "name": "slime0", + "delays": [ + [ + 0.1, + 0.1, + 0.2, + 0.1, + 0.1, + 0.1, + 0.1, + 0.5 + ] + ] + }, + { + "name": "slime1", + "delays": [ + [ + 0.1, + 0.3, + 0.1, + 0.1, + 0.1, + 0.6 + ] + ] + }, + { + "name": "slime2", + "delays": [ + [ + 0.1, + 0.3, + 0.1, + 0.1, + 0.1, + 0.6 + ] + ] + }, + { + "name": "swarmer0", + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "swarmer1", + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "swarmer2", + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "syndibot0", + "delays": [ + [ + 0.2, + 0.2, + 0.2, + 0.2 + ] + ] + }, + { + "name": "syndibot1" + }, + { + "name": "syndibot2" + } + ] +} \ No newline at end of file diff --git a/Resources/Textures/Effects/speech.rsi/robot0.png b/Resources/Textures/Effects/speech.rsi/robot0.png new file mode 100644 index 0000000000..557b641cea Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/robot0.png differ diff --git a/Resources/Textures/Effects/speech.rsi/robot1.png b/Resources/Textures/Effects/speech.rsi/robot1.png new file mode 100644 index 0000000000..66320382bd Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/robot1.png differ diff --git a/Resources/Textures/Effects/speech.rsi/robot2.png b/Resources/Textures/Effects/speech.rsi/robot2.png new file mode 100644 index 0000000000..1dd1755ff5 Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/robot2.png differ diff --git a/Resources/Textures/Effects/speech.rsi/slime0.png b/Resources/Textures/Effects/speech.rsi/slime0.png new file mode 100644 index 0000000000..28a374ec12 Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/slime0.png differ diff --git a/Resources/Textures/Effects/speech.rsi/slime1.png b/Resources/Textures/Effects/speech.rsi/slime1.png new file mode 100644 index 0000000000..87010aa307 Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/slime1.png differ diff --git a/Resources/Textures/Effects/speech.rsi/slime2.png b/Resources/Textures/Effects/speech.rsi/slime2.png new file mode 100644 index 0000000000..0cd03b9dd4 Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/slime2.png differ diff --git a/Resources/Textures/Effects/speech.rsi/swarmer0.png b/Resources/Textures/Effects/speech.rsi/swarmer0.png new file mode 100644 index 0000000000..baa18dbe79 Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/swarmer0.png differ diff --git a/Resources/Textures/Effects/speech.rsi/swarmer1.png b/Resources/Textures/Effects/speech.rsi/swarmer1.png new file mode 100644 index 0000000000..0f9d266b79 Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/swarmer1.png differ diff --git a/Resources/Textures/Effects/speech.rsi/swarmer2.png b/Resources/Textures/Effects/speech.rsi/swarmer2.png new file mode 100644 index 0000000000..493cf3743d Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/swarmer2.png differ diff --git a/Resources/Textures/Effects/speech.rsi/syndibot0.png b/Resources/Textures/Effects/speech.rsi/syndibot0.png new file mode 100644 index 0000000000..31160c3708 Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/syndibot0.png differ diff --git a/Resources/Textures/Effects/speech.rsi/syndibot1.png b/Resources/Textures/Effects/speech.rsi/syndibot1.png new file mode 100644 index 0000000000..3cc5779af6 Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/syndibot1.png differ diff --git a/Resources/Textures/Effects/speech.rsi/syndibot2.png b/Resources/Textures/Effects/speech.rsi/syndibot2.png new file mode 100644 index 0000000000..2155de92fc Binary files /dev/null and b/Resources/Textures/Effects/speech.rsi/syndibot2.png differ