diff --git a/Content.Client/Examine/ExamineSystem.cs b/Content.Client/Examine/ExamineSystem.cs index 1c1f1984de..6870f81d9e 100644 --- a/Content.Client/Examine/ExamineSystem.cs +++ b/Content.Client/Examine/ExamineSystem.cs @@ -361,7 +361,6 @@ namespace Content.Client.Examine // If we get it wrong, server will correct us later anyway. // This will usually be correct (barring server-only components, which generally only adds, not replaces text) message = GetExamineText(entity, playerEnt); - UpdateTooltipInfo(playerEnt.Value, entity, message); if (!IsClientSide(entity)) { diff --git a/Content.Server/AlertLevel/AlertLevelSystem.cs b/Content.Server/AlertLevel/AlertLevelSystem.cs index 0b49d7e4bf..86d2a23463 100644 --- a/Content.Server/AlertLevel/AlertLevelSystem.cs +++ b/Content.Server/AlertLevel/AlertLevelSystem.cs @@ -1,5 +1,6 @@ using System.Linq; using Content.Server.Chat.Systems; +using Content.Server.Speech.EntitySystems; using Content.Server.Station.Systems; using Content.Shared.CCVar; using Robust.Shared.Audio; @@ -188,6 +189,7 @@ public sealed class AlertLevelSystem : EntitySystem if (announce) { + announcementFull = RandomAccentuator.MaybeAccentuate(announcementFull); _chatSystem.DispatchStationAnnouncement(station, announcementFull, playDefaultSound: playDefault, colorOverride: detail.Color, sender: stationName); } diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index 50d5a778f3..789717ea89 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -381,6 +381,9 @@ public sealed partial class ChatSystem : SharedChatSystem { sender ??= Loc.GetString("chat-manager-sender-announcement"); + if (!sender.Equals(Loc.GetString("comms-console-announcement-title-station"), StringComparison.OrdinalIgnoreCase)) + message = RandomAccentuator.MaybeAccentuate(message); + var wrappedMessage = Loc.GetString("chat-manager-sender-announcement-wrap-message", ("sender", sender), ("message", FormattedMessage.EscapeText(message))); var station = _stationSystem.GetOwningStation(source); diff --git a/Content.Server/CrewManifest/CrewManifestSystem.cs b/Content.Server/CrewManifest/CrewManifestSystem.cs index e742456015..b194180cd2 100644 --- a/Content.Server/CrewManifest/CrewManifestSystem.cs +++ b/Content.Server/CrewManifest/CrewManifestSystem.cs @@ -1,6 +1,7 @@ using System.Linq; using Content.Server.Administration; using Content.Server.EUI; +using Content.Server.Speech.EntitySystems; using Content.Server.Station.Components; using Content.Server.Station.Systems; using Content.Server.StationRecords; @@ -230,7 +231,7 @@ public sealed class CrewManifestSystem : EntitySystem foreach (var recordObject in iter) { var record = recordObject.Item2; - var entry = new CrewManifestEntry(record.Name, record.JobTitle, record.JobIcon, record.JobPrototype); + var entry = new CrewManifestEntry(RandomAccentuator.MaybeAccentuate(record.Name, reaccentuationChance: 0.03f), RandomAccentuator.MaybeAccentuate(record.JobTitle, reaccentuationChance: 0.2f), record.JobIcon, record.JobPrototype); _prototypeManager.TryIndex(record.JobPrototype, out JobPrototype? job); entriesSort.Add((job, entry)); diff --git a/Content.Server/Examine/ExamineSystem.cs b/Content.Server/Examine/ExamineSystem.cs index d7546e2eb0..08d6896b5e 100644 --- a/Content.Server/Examine/ExamineSystem.cs +++ b/Content.Server/Examine/ExamineSystem.cs @@ -1,4 +1,5 @@ using System.Linq; +using Content.Server.Speech.EntitySystems; using Content.Server.Verbs; using Content.Shared.Examine; using Content.Shared.Verbs; @@ -36,6 +37,8 @@ namespace Content.Server.Examine if (getVerbs) verbs = _verbSystem.GetLocalVerbs(target, player, typeof(ExamineVerb)); + message = RandomAccentuator.MaybeAccentuate(message, 0.1f); + var ev = new ExamineSystemMessages.ExamineInfoResponseMessage( GetNetEntity(target), 0, message, verbs?.ToList(), centerAtCursor ); @@ -70,6 +73,8 @@ namespace Content.Server.Examine verbs = _verbSystem.GetLocalVerbs(entity, playerEnt, typeof(ExamineVerb)); var text = GetExamineText(entity, player.AttachedEntity); + text = RandomAccentuator.MaybeAccentuate(text, 0.05f); + RaiseNetworkEvent(new ExamineSystemMessages.ExamineInfoResponseMessage( request.NetEntity, request.Id, text, verbs?.ToList()), channel); } diff --git a/Content.Server/Nuke/NukeSystem.cs b/Content.Server/Nuke/NukeSystem.cs index 96eeb35d0c..02e100b5b5 100644 --- a/Content.Server/Nuke/NukeSystem.cs +++ b/Content.Server/Nuke/NukeSystem.cs @@ -4,6 +4,7 @@ using Content.Server.Chat.Systems; using Content.Server.Explosion.EntitySystems; using Content.Server.Pinpointer; using Content.Server.Popups; +using Content.Server.Speech.EntitySystems; using Content.Server.Station.Systems; using Content.Shared.Audio; using Content.Shared.Containers.ItemSlots; @@ -478,6 +479,7 @@ public sealed class NukeSystem : EntitySystem ("time", (int) component.RemainingTime), ("location", FormattedMessage.RemoveMarkupOrThrow(_navMap.GetNearestBeaconString((uid, nukeXform))))); var sender = Loc.GetString("nuke-component-announcement-sender"); + announcement = RandomAccentuator.MaybeAccentuate(announcement); _chatSystem.DispatchStationAnnouncement(stationUid ?? uid, announcement, sender, false, null, Color.Red); _sound.PlayGlobalOnStation(uid, _audio.ResolveSound(component.ArmSound)); @@ -518,6 +520,7 @@ public sealed class NukeSystem : EntitySystem // warn a crew var announcement = Loc.GetString("nuke-component-announcement-unarmed"); var sender = Loc.GetString("nuke-component-announcement-sender"); + announcement = RandomAccentuator.MaybeAccentuate(announcement); _chatSystem.DispatchStationAnnouncement(uid, announcement, sender, false); component.PlayedNukeSong = false; diff --git a/Content.Server/Speech/EntitySystems/FrenchAccentSystem.cs b/Content.Server/Speech/EntitySystems/FrenchAccentSystem.cs index d71655569c..0f567e8818 100644 --- a/Content.Server/Speech/EntitySystems/FrenchAccentSystem.cs +++ b/Content.Server/Speech/EntitySystems/FrenchAccentSystem.cs @@ -21,7 +21,12 @@ public sealed class FrenchAccentSystem : EntitySystem SubscribeLocalEvent(OnAccentGet); } - public string Accentuate(string message, FrenchAccentComponent component) + public string Accentuate(string message, FrenchAccentComponent _) + { + return Accentuate(message); + } + + public string Accentuate(string message) { var msg = message; diff --git a/Content.Server/Speech/EntitySystems/MobsterAccentSystem.cs b/Content.Server/Speech/EntitySystems/MobsterAccentSystem.cs index 0e9b0a34ef..e218b60412 100644 --- a/Content.Server/Speech/EntitySystems/MobsterAccentSystem.cs +++ b/Content.Server/Speech/EntitySystems/MobsterAccentSystem.cs @@ -25,7 +25,12 @@ public sealed class MobsterAccentSystem : EntitySystem SubscribeLocalEvent(OnAccentGet); } - public string Accentuate(string message, MobsterAccentComponent component) + private string Accentuate(string message, MobsterAccentComponent component) + { + return Accentuate(message, component.IsBoss); + } + + public string Accentuate(string message, bool isBoss = true) { // Order: // Do text manipulations first @@ -72,7 +77,7 @@ public sealed class MobsterAccentSystem : EntitySystem //So the suffix can be allcapped var lastWordAllCaps = !RegexLastWord.Match(msg).Value.Any(char.IsLower); var suffix = ""; - if (component.IsBoss) + if (isBoss) { var pick = _random.Next(1, 4); suffix = Loc.GetString($"accent-mobster-suffix-boss-{pick}"); @@ -90,6 +95,7 @@ public sealed class MobsterAccentSystem : EntitySystem return msg; } + private void OnAccentGet(EntityUid uid, MobsterAccentComponent component, AccentGetEvent args) { args.Message = Accentuate(args.Message, component); diff --git a/Content.Server/Speech/EntitySystems/MumbleAccentSystem.cs b/Content.Server/Speech/EntitySystems/MumbleAccentSystem.cs index 757f31ad9e..c7de7cf198 100644 --- a/Content.Server/Speech/EntitySystems/MumbleAccentSystem.cs +++ b/Content.Server/Speech/EntitySystems/MumbleAccentSystem.cs @@ -13,7 +13,12 @@ public sealed class MumbleAccentSystem : EntitySystem SubscribeLocalEvent(OnAccentGet); } - public string Accentuate(string message, MumbleAccentComponent component) + private string Accentuate(string message, MumbleAccentComponent _) + { + return Accentuate(message); + } + + public string Accentuate(string message) { return _replacement.ApplyReplacements(message, "mumble"); } diff --git a/Content.Server/Speech/EntitySystems/OwOAccentSystem.cs b/Content.Server/Speech/EntitySystems/OwOAccentSystem.cs index 2b3d5aa3d4..fad7037cf2 100644 --- a/Content.Server/Speech/EntitySystems/OwOAccentSystem.cs +++ b/Content.Server/Speech/EntitySystems/OwOAccentSystem.cs @@ -1,5 +1,6 @@ using Content.Server.Speech.Components; using Robust.Shared.Random; +using Robust.Shared.Utility; namespace Content.Server.Speech.EntitySystems { diff --git a/Content.Server/Speech/EntitySystems/PirateAccentSystem.cs b/Content.Server/Speech/EntitySystems/PirateAccentSystem.cs index 84298cbf01..bdcfd5f50b 100644 --- a/Content.Server/Speech/EntitySystems/PirateAccentSystem.cs +++ b/Content.Server/Speech/EntitySystems/PirateAccentSystem.cs @@ -42,6 +42,11 @@ public sealed class PirateAccentSystem : EntitySystem return msg; } + public string Accentuate(string message) + { + return Accentuate(message, new PirateAccentComponent { YarrChance = 0.3f }); + } + private void OnAccentGet(EntityUid uid, PirateAccentComponent component, AccentGetEvent args) { args.Message = Accentuate(args.Message, component); diff --git a/Content.Server/Speech/EntitySystems/RandomAccentuator.cs b/Content.Server/Speech/EntitySystems/RandomAccentuator.cs new file mode 100644 index 0000000000..3c583de862 --- /dev/null +++ b/Content.Server/Speech/EntitySystems/RandomAccentuator.cs @@ -0,0 +1,66 @@ +using Robust.Shared.Random; +using Robust.Shared.Utility; + +namespace Content.Server.Speech.EntitySystems; + +public static class RandomAccentuator +{ + private const float DefaultAccentuationChance = 0.25f; + + private const float DefaultReaccentuationChance = 0.15f; + + private const float MaxReaccentuations = 4; + + public static string MaybeAccentuate(string message, + float chance = DefaultAccentuationChance, + float reaccentuationChance = DefaultReaccentuationChance) + { + var random = IoCManager.Resolve(); + var singleAccentuator = new SingleAccentuator(); + return random.Prob(chance) + ? MaybeAccentuateDirect(message, singleAccentuator, random, reaccentuationChance) + : message; + } + + public static FormattedMessage MaybeAccentuate(FormattedMessage message, + float chance = DefaultAccentuationChance, + float reaccentuationChance = DefaultReaccentuationChance) + { + var random = IoCManager.Resolve(); + var singleAccentuator = new SingleAccentuator(); + var newMessage = new FormattedMessage(); + + foreach (var node in message) + { + if (random.Prob(chance) && node.Name is null && node.Value.TryGetString(out var text) && + !string.IsNullOrWhiteSpace(text)) + { + var accentedText = MaybeAccentuateDirect(text, singleAccentuator, random, reaccentuationChance); + newMessage.PushTag(new MarkupNode(accentedText)); + } + else + { + newMessage.PushTag(node); + } + } + + return newMessage; + } + + private static string MaybeAccentuateDirect(string message, + SingleAccentuator singleAccentuator, + IRobustRandom random, + float reaccentuationChance) + { + for (var i = 0; i < MaxReaccentuations; i++) + { + if (i > 0 && !random.Prob(reaccentuationChance)) + continue; + + singleAccentuator.NextSystem(); + message = singleAccentuator.Accentuate(message); + } + + return message; + } +} diff --git a/Content.Server/Speech/EntitySystems/SingleAccentuator.cs b/Content.Server/Speech/EntitySystems/SingleAccentuator.cs new file mode 100644 index 0000000000..972b795a5b --- /dev/null +++ b/Content.Server/Speech/EntitySystems/SingleAccentuator.cs @@ -0,0 +1,59 @@ +using Robust.Shared.Random; + +namespace Content.Server.Speech.EntitySystems; + +public sealed class SingleAccentuator +{ + private EntitySystem? _accentSystem; + + private readonly IReadOnlyList _accentSystems; + + public SingleAccentuator() + { + var entMan = IoCManager.Resolve(); + _accentSystems = new List + { + entMan.EntitySysManager.GetEntitySystem(), + entMan.EntitySysManager.GetEntitySystem(), + entMan.EntitySysManager.GetEntitySystem(), + entMan.EntitySysManager.GetEntitySystem(), + entMan.EntitySysManager.GetEntitySystem(), + entMan.EntitySysManager.GetEntitySystem(), + entMan.EntitySysManager.GetEntitySystem(), + entMan.EntitySysManager.GetEntitySystem(), + entMan.EntitySysManager.GetEntitySystem(), + entMan.EntitySysManager.GetEntitySystem(), + }; + NextSystem(); + } + + public void NextSystem() + { + _accentSystem = GetRandomAccentSystem(); + } + + private EntitySystem GetRandomAccentSystem() + { + var random = IoCManager.Resolve(); + + return random.Pick(_accentSystems); + } + + public string Accentuate(string message) + { + return _accentSystem switch + { + OwOAccentSystem owoAccentSystem => owoAccentSystem.Accentuate(message), + GermanAccentSystem germanAccentSystem => germanAccentSystem.Accentuate(message), + RussianAccentSystem russianAccentSystem => russianAccentSystem.Accentuate(message), + FrenchAccentSystem frenchAccentSystem => frenchAccentSystem.Accentuate(message), + MumbleAccentSystem mumbleAccentSystem => mumbleAccentSystem.Accentuate(message), + SlurredSystem slurredSystem => slurredSystem.Accentuate(message), + MobsterAccentSystem mobsterAccentSystem => mobsterAccentSystem.Accentuate(message), + PirateAccentSystem pirateAccentSystem => pirateAccentSystem.Accentuate(message), + MonkeyAccentSystem monkeyAccentSystem => monkeyAccentSystem.Accentuate(message), + StutteringSystem stutteringSystem => stutteringSystem.Accentuate(message), + _ => message + }; + } +} diff --git a/Content.Server/Speech/EntitySystems/SlurredSystem.cs b/Content.Server/Speech/EntitySystems/SlurredSystem.cs index e396cd0b18..a0ce69c638 100644 --- a/Content.Server/Speech/EntitySystems/SlurredSystem.cs +++ b/Content.Server/Speech/EntitySystems/SlurredSystem.cs @@ -54,7 +54,7 @@ public sealed class SlurredSystem : SharedSlurredSystem args.Message = Accentuate(args.Message, scale); } - private string Accentuate(string message, float scale) + public string Accentuate(string message, float scale = 0.3f) { var sb = new StringBuilder(); diff --git a/Content.Server/Speech/EntitySystems/StutteringSystem.cs b/Content.Server/Speech/EntitySystems/StutteringSystem.cs index d6e3c0b749..1dcfd40c3d 100644 --- a/Content.Server/Speech/EntitySystems/StutteringSystem.cs +++ b/Content.Server/Speech/EntitySystems/StutteringSystem.cs @@ -70,5 +70,10 @@ namespace Content.Server.Speech.EntitySystems return finalMessage.ToString(); } + + public string Accentuate(string message) + { + return Accentuate(message, new StutteringAccentComponent()); + } } } diff --git a/Content.Server/StationEvents/Events/StationEventSystem.cs b/Content.Server/StationEvents/Events/StationEventSystem.cs index aaa48a482e..3e1c6e82fd 100644 --- a/Content.Server/StationEvents/Events/StationEventSystem.cs +++ b/Content.Server/StationEvents/Events/StationEventSystem.cs @@ -2,6 +2,7 @@ using Content.Server.Administration.Logs; using Content.Server.Chat.Systems; using Content.Server.GameTicking; using Content.Server.GameTicking.Rules; +using Content.Server.Speech.EntitySystems; using Content.Server.Station.Systems; using Content.Server.StationEvents.Components; using Content.Shared.Database; @@ -46,7 +47,11 @@ public abstract class StationEventSystem : GameRuleSystem where T : ICompo Filter allPlayersInGame = Filter.Empty().AddWhere(GameTicker.UserHasJoinedGame); if (stationEvent.StartAnnouncement != null) - ChatSystem.DispatchFilteredAnnouncement(allPlayersInGame, Loc.GetString(stationEvent.StartAnnouncement), playSound: false, colorOverride: stationEvent.StartAnnouncementColor); + { + var announcement = Loc.GetString(stationEvent.StartAnnouncement); + announcement = RandomAccentuator.MaybeAccentuate(announcement); + ChatSystem.DispatchFilteredAnnouncement(allPlayersInGame, announcement, playSound: false, colorOverride: stationEvent.StartAnnouncementColor); + } Audio.PlayGlobal(stationEvent.StartAudio, allPlayersInGame, true); }