]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Make parrots talk like parrots (#26340)
authorTayrtahn <tayrtahn@gmail.com>
Mon, 25 Mar 2024 01:26:41 +0000 (21:26 -0400)
committerGitHub <noreply@github.com>
Mon, 25 Mar 2024 01:26:41 +0000 (18:26 -0700)
Content.Server/Speech/Components/ParrotAccentComponent.cs [new file with mode: 0644]
Content.Server/Speech/EntitySystems/ParrotAccentSystem.cs [new file with mode: 0644]
Resources/Locale/en-US/accent/parrot.ftl [new file with mode: 0644]
Resources/Locale/en-US/chat/managers/chat-manager.ftl
Resources/Prototypes/Entities/Mobs/NPCs/animals.yml
Resources/Prototypes/Voice/speech_emote_sounds.yml
Resources/Prototypes/Voice/speech_sounds.yml
Resources/Prototypes/Voice/speech_verbs.yml

diff --git a/Content.Server/Speech/Components/ParrotAccentComponent.cs b/Content.Server/Speech/Components/ParrotAccentComponent.cs
new file mode 100644 (file)
index 0000000..5c4e015
--- /dev/null
@@ -0,0 +1,47 @@
+namespace Content.Server.Speech.Components;
+
+/// <summary>
+/// Makes this entity speak like a parrot in all chat messages it sends.
+/// </summary>
+[RegisterComponent]
+public sealed partial class ParrotAccentComponent : Component
+{
+    /// <summary>
+    /// Chance that a message will have a squawk sound added before the first character.
+    /// If it fails, the message with have a squawk as a postfix instead.
+    /// If the longest word is repeated, no pre- or postfix will be added.
+    /// </summary>
+    [DataField]
+    public float SquawkPrefixChance = 0.5f;
+
+    /// <summary>
+    /// Chance that the longest word in the message will be repeated as an
+    /// exclamation at the end of the final message.
+    /// </summary>
+    [DataField]
+    public float LongestWordRepeatChance = 0.5f;
+
+    /// <summary>
+    /// The longest word must be at least this many characters long to be
+    /// repeated. This prevents repeating short words, which can sound weird.
+    /// ex: "How are you? AWWK! How!" - bad
+    /// ex: "Look out, it's the captain! RAWWK! Captain!" - good
+    /// </summary>
+    [DataField]
+    public float LongestWordMinLength = 5;
+
+    /// <summary>
+    /// Strings to use as squawking noises.
+    /// </summary>
+    public readonly string[] Squawks = [
+        "accent-parrot-squawk-1",
+        "accent-parrot-squawk-2",
+        "accent-parrot-squawk-3",
+        "accent-parrot-squawk-4",
+        "accent-parrot-squawk-5",
+        "accent-parrot-squawk-6",
+        "accent-parrot-squawk-7",
+        "accent-parrot-squawk-8"
+    ];
+
+}
diff --git a/Content.Server/Speech/EntitySystems/ParrotAccentSystem.cs b/Content.Server/Speech/EntitySystems/ParrotAccentSystem.cs
new file mode 100644 (file)
index 0000000..10437c2
--- /dev/null
@@ -0,0 +1,79 @@
+using System.Linq;
+using System.Text.RegularExpressions;
+using Content.Server.Speech.Components;
+using Robust.Shared.Random;
+
+namespace Content.Server.Speech.EntitySystems;
+
+public sealed partial class ParrotAccentSystem : EntitySystem
+{
+    [Dependency] private readonly IRobustRandom _random = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        SubscribeLocalEvent<ParrotAccentComponent, AccentGetEvent>(OnAccentGet);
+    }
+
+    private void OnAccentGet(Entity<ParrotAccentComponent> entity, ref AccentGetEvent args)
+    {
+        args.Message = Accentuate(entity, args.Message);
+    }
+
+    public string Accentuate(Entity<ParrotAccentComponent> entity, string message)
+    {
+        // Sometimes repeat the longest word at the end of the message, after a squawk! SQUAWK! Sometimes!
+        if (_random.Prob(entity.Comp.LongestWordRepeatChance))
+        {
+            // Don't count non-alphanumeric characters as parts of words
+            var cleaned = Regex.Replace(message, "[^A-Za-z0-9 -]", string.Empty);
+            // Split on whitespace and favor words towards the end of the message
+            var words = cleaned.Split(null).Reverse();
+            // Find longest word
+            var longest = words.MaxBy(word => word.Length);
+            if (longest?.Length >= entity.Comp.LongestWordMinLength)
+            {
+                message = EnsurePunctuation(message);
+
+                // Capitalize the first letter of the repeated word
+                longest = string.Concat(longest[0].ToString().ToUpper(), longest.AsSpan(1));
+
+                message = string.Format("{0} {1} {2}!", message, GetRandomSquawk(entity), longest);
+                return message; // No more changes, or it's too much
+            }
+        }
+
+        if (_random.Prob(entity.Comp.SquawkPrefixChance))
+        {
+            // AWWK! Sometimes add a squawk at the begining of the message
+            message = string.Format("{0} {1}", GetRandomSquawk(entity), message);
+        }
+        else
+        {
+            // Otherwise add a squawk at the end of the message! RAWWK!
+            message = EnsurePunctuation(message);
+            message = string.Format("{0} {1}", message, GetRandomSquawk(entity));
+        }
+
+        return message;
+    }
+
+    /// <summary>
+    /// Adds a "!" to the end of the string, if there isn't already a sentence-ending punctuation mark.
+    /// </summary>
+    private string EnsurePunctuation(string message)
+    {
+        if (!message.EndsWith('!') && !message.EndsWith('?') && !message.EndsWith('.'))
+            return message + '!';
+        return message;
+    }
+
+    /// <summary>
+    /// Returns a random, localized squawk sound.
+    /// </summary>
+    private string GetRandomSquawk(Entity<ParrotAccentComponent> entity)
+    {
+        return Loc.GetString(_random.Pick(entity.Comp.Squawks));
+    }
+}
diff --git a/Resources/Locale/en-US/accent/parrot.ftl b/Resources/Locale/en-US/accent/parrot.ftl
new file mode 100644 (file)
index 0000000..4d4e0dc
--- /dev/null
@@ -0,0 +1,8 @@
+accent-parrot-squawk-1 = SQUAWK!
+accent-parrot-squawk-2 = SQUAAAWK!
+accent-parrot-squawk-3 = AWWK!
+accent-parrot-squawk-4 = AAWK!
+accent-parrot-squawk-5 = RAWWK!
+accent-parrot-squawk-6 = RAAAWK!
+accent-parrot-squawk-7 = BRAAWK!
+accent-parrot-squawk-8 = BRAWWK!
index e5ef61701a8285c76dcd6818fee9054a7cb0aebf..cf8c384dee28b7f537494bffd8ed0568c0018b78 100644 (file)
@@ -109,6 +109,10 @@ chat-speech-verb-large-mob-2 = growls
 chat-speech-verb-monkey-1 = chimpers
 chat-speech-verb-monkey-2 = screeches
 
+chat-speech-verb-parrot-1 = squawks
+chat-speech-verb-parrot-2 = tweets
+chat-speech-verb-parrot-3 = chirps
+
 chat-speech-verb-cluwne-1 = giggles
 chat-speech-verb-cluwne-2 = guffaws
 chat-speech-verb-cluwne-3 = laughs
index 170e4fc57aeb45e264b163b676ccdb1fb04c95b4..de9a3db19e2144e5c8a68b13a63ba08e85047de0 100644 (file)
     spawned:
     - id: FoodMeat
       amount: 1
+  - type: Speech
+    speechSounds: Parrot
+    speechVerb: Parrot
+  - type: Vocal
+    sounds:
+      Unsexed: Parrot
+  - type: ParrotAccent
   - type: InteractionPopup
     successChance: 0.6
     interactSuccessString: petting-success-bird
index ee76fa33d2c92e2285dbd07e73d18fb40f0402c9..01fabbadf30cc3b548566fde1cdcd270dc935e5f 100644 (file)
   sounds:
     Chirp:
       path: /Audio/Animals/nymph_chirp.ogg
+
+- type: emoteSounds
+  id: Parrot
+  sound:
+    path: /Audio/Animals/parrot_raught.ogg
+    params:
+      variation: 0.125
index eb47b5363b6936ec7f51013681881614b66bb049..2e7e7bf989a50d404f1cf15996cf196390c3f762 100644 (file)
   exclaimSound:
     path: /Audio/Animals/monkey_scream.ogg
 
+- type: speechSounds
+  id: Parrot
+  saySound:
+    path: /Audio/Animals/parrot_raught.ogg
+  askSound:
+    path: /Audio/Animals/parrot_raught.ogg
+  exclaimSound:
+    path: /Audio/Animals/parrot_raught.ogg
+
 - type: speechSounds
   id: Lizard
   saySound:
index 1cdda32ece19c4fb53f41edcf838bff10d6cbf36..26e9370c017143015f80c16166dc573316669d0b 100644 (file)
   - chat-speech-verb-monkey-1
   - chat-speech-verb-monkey-2
 
+- type: speechVerb
+  id: Parrot
+  speechVerbStrings:
+  - chat-speech-verb-parrot-1
+  - chat-speech-verb-parrot-2
+  - chat-speech-verb-parrot-3
+
 - type: speechVerb
   id: Cluwne
   speechVerbStrings: