Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mirror: Make parrots talk like parrots #381

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions Content.Server/Speech/Components/ParrotAccentComponent.cs
Original file line number Diff line number Diff line change
@@ -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"
];

}
79 changes: 79 additions & 0 deletions Content.Server/Speech/EntitySystems/ParrotAccentSystem.cs
Original file line number Diff line number Diff line change
@@ -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));
}
}
8 changes: 8 additions & 0 deletions Resources/Locale/en-US/accent/parrot.ftl
Original file line number Diff line number Diff line change
@@ -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!
4 changes: 4 additions & 0 deletions Resources/Locale/en-US/chat/managers/chat-manager.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions Resources/Prototypes/Entities/Mobs/NPCs/animals.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1866,6 +1866,13 @@
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
Expand Down
7 changes: 7 additions & 0 deletions Resources/Prototypes/Voice/speech_emote_sounds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -380,3 +380,10 @@
sounds:
Chirp:
path: /Audio/Animals/nymph_chirp.ogg

- type: emoteSounds
id: Parrot
sound:
path: /Audio/Animals/parrot_raught.ogg
params:
variation: 0.125
9 changes: 9 additions & 0 deletions Resources/Prototypes/Voice/speech_sounds.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@
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:
Expand Down
7 changes: 7 additions & 0 deletions Resources/Prototypes/Voice/speech_verbs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,13 @@
- 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:
Expand Down
Loading