return msg;
}
- protected string ExtractSpeechSubstring(ChatMessage message, string tag)
- {
- var rawmsg = message.WrappedMessage;
- var tagStart = rawmsg.IndexOf($"[{tag}]");
- var tagEnd = rawmsg.IndexOf($"[/{tag}]");
- if (tagStart < 0 || tagEnd < 0) //the above return -1 if the tag's not found, which in turn will cause the below to throw an exception. a blank speech bubble is far more noticeably broken than the bubble not appearing at all -bhijn
- return "";
- tagStart += tag.Length + 2;
- return rawmsg.Substring(tagStart, tagEnd - tagStart);
- }
-
protected FormattedMessage ExtractAndFormatSpeechSubstring(ChatMessage message, string tag, Color? fontColor = null)
{
- return FormatSpeech(ExtractSpeechSubstring(message, tag), fontColor);
+ return FormatSpeech(SharedChatSystem.GetStringInsideTag(message, tag), fontColor);
}
}
FontColorOverride="{xNamespace:Static s:StyleNano.NanoGold}"
StyleClasses="LabelKeyText"/>
<CheckBox Name="ReducedMotionCheckBox" Text="{Loc 'ui-options-reduced-motion'}" />
+ <CheckBox Name="EnableColorNameCheckBox" Text="{Loc 'ui-options-enable-color-name'}" />
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc 'ui-options-screen-shake-intensity'}" Margin="8 0" />
<Slider Name="ScreenShakeIntensitySlider"
OpaqueStorageWindowCheckBox.OnToggled += OnCheckBoxToggled;
FancySpeechBubblesCheckBox.OnToggled += OnCheckBoxToggled;
FancyNameBackgroundsCheckBox.OnToggled += OnCheckBoxToggled;
+ EnableColorNameCheckBox.OnToggled += OnCheckBoxToggled;
ReducedMotionCheckBox.OnToggled += OnCheckBoxToggled;
ScreenShakeIntensitySlider.OnValueChanged += OnScreenShakeIntensitySliderChanged;
// ToggleWalk.OnToggled += OnCheckBoxToggled;
OpaqueStorageWindowCheckBox.Pressed = _cfg.GetCVar(CCVars.OpaqueStorageWindow);
FancySpeechBubblesCheckBox.Pressed = _cfg.GetCVar(CCVars.ChatEnableFancyBubbles);
FancyNameBackgroundsCheckBox.Pressed = _cfg.GetCVar(CCVars.ChatFancyNameBackground);
+ EnableColorNameCheckBox.Pressed = _cfg.GetCVar(CCVars.ChatEnableColorName);
ReducedMotionCheckBox.Pressed = _cfg.GetCVar(CCVars.ReducedMotion);
ScreenShakeIntensitySlider.Value = _cfg.GetCVar(CCVars.ScreenShakeIntensity) * 100f;
// ToggleWalk.Pressed = _cfg.GetCVar(CCVars.ToggleWalk);
_cfg.SetCVar(CCVars.LoocAboveHeadShow, ShowLoocAboveHeadCheckBox.Pressed);
_cfg.SetCVar(CCVars.ChatEnableFancyBubbles, FancySpeechBubblesCheckBox.Pressed);
_cfg.SetCVar(CCVars.ChatFancyNameBackground, FancyNameBackgroundsCheckBox.Pressed);
+ _cfg.SetCVar(CCVars.ChatEnableColorName, EnableColorNameCheckBox.Pressed);
_cfg.SetCVar(CCVars.ReducedMotion, ReducedMotionCheckBox.Pressed);
_cfg.SetCVar(CCVars.ScreenShakeIntensity, ScreenShakeIntensitySlider.Value / 100f);
// _cfg.SetCVar(CCVars.ToggleWalk, ToggleWalk.Pressed);
var isLoocShowSame = ShowLoocAboveHeadCheckBox.Pressed == _cfg.GetCVar(CCVars.LoocAboveHeadShow);
var isFancyChatSame = FancySpeechBubblesCheckBox.Pressed == _cfg.GetCVar(CCVars.ChatEnableFancyBubbles);
var isFancyBackgroundSame = FancyNameBackgroundsCheckBox.Pressed == _cfg.GetCVar(CCVars.ChatFancyNameBackground);
+ var isEnableColorNameSame = EnableColorNameCheckBox.Pressed == _cfg.GetCVar(CCVars.ChatEnableColorName);
var isReducedMotionSame = ReducedMotionCheckBox.Pressed == _cfg.GetCVar(CCVars.ReducedMotion);
var isScreenShakeIntensitySame = Math.Abs(ScreenShakeIntensitySlider.Value / 100f - _cfg.GetCVar(CCVars.ScreenShakeIntensity)) < 0.01f;
// var isToggleWalkSame = ToggleWalk.Pressed == _cfg.GetCVar(CCVars.ToggleWalk);
isLoocShowSame &&
isFancyChatSame &&
isFancyBackgroundSame &&
+ isEnableColorNameSame &&
isReducedMotionSame &&
isScreenShakeIntensitySame &&
// isToggleWalkSame &&
using Content.Shared.Administration;
using Content.Shared.CCVar;
using Content.Shared.Chat;
+using Content.Shared.Decals;
using Content.Shared.Damage.ForceSay;
using Content.Shared.Examine;
using Content.Shared.Input;
using Content.Shared.Radio;
+using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.Input;
using Robust.Client.Player;
using Robust.Client.UserInterface.Controllers;
using Robust.Client.UserInterface.Controls;
using Robust.Shared.Configuration;
+using Robust.Shared.GameObjects.Components.Localization;
using Robust.Shared.Input.Binding;
using Robust.Shared.Map;
using Robust.Shared.Network;
+using Robust.Shared.Prototypes;
using Robust.Shared.Replays;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
[Dependency] private readonly IChatManager _manager = default!;
[Dependency] private readonly IConfigurationManager _config = default!;
[Dependency] private readonly IEyeManager _eye = default!;
+ [Dependency] private readonly IEntityManager _ent = default!;
[Dependency] private readonly IInputManager _input = default!;
[Dependency] private readonly IClientNetManager _net = default!;
[Dependency] private readonly IPlayerManager _player = default!;
+ [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IStateManager _state = default!;
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IReplayRecordingManager _replayRecording = default!;
[UISystemDependency] private readonly TypingIndicatorSystem? _typingIndicator = default;
[UISystemDependency] private readonly ChatSystem? _chatSys = default;
+ [ValidatePrototypeId<ColorPalettePrototype>]
+ private const string ChatNamePalette = "ChatNames";
+ private string[] _chatNameColors = default!;
+ private bool _chatNameColorsEnabled;
+
private ISawmill _sawmill = default!;
public static readonly Dictionary<char, ChatSelectChannel> PrefixToChannel = new()
_net.RegisterNetMessage<MsgChatMessage>(OnChatMessage);
_net.RegisterNetMessage<MsgDeleteChatMessagesBy>(OnDeleteChatMessagesBy);
SubscribeNetworkEvent<DamageForceSayEvent>(OnDamageForceSay);
+ _cfg.OnValueChanged(CCVars.ChatEnableColorName, (value) => { _chatNameColorsEnabled = value; });
+ _chatNameColorsEnabled = _cfg.GetCVar(CCVars.ChatEnableColorName);
_speechBubbleRoot = new LayoutContainer();
var gameplayStateLoad = UIManager.GetUIController<GameplayStateLoadController>();
gameplayStateLoad.OnScreenLoad += OnScreenLoad;
gameplayStateLoad.OnScreenUnload += OnScreenUnload;
+
+ var nameColors = _prototypeManager.Index<ColorPalettePrototype>(ChatNamePalette).Colors.Values.ToArray();
+ _chatNameColors = new string[nameColors.Length];
+ for (var i = 0; i < nameColors.Length; i++)
+ {
+ _chatNameColors[i] = nameColors[i].ToHex();
+ }
}
public void OnScreenLoad()
public void ProcessChatMessage(ChatMessage msg, bool speechBubble = true)
{
+ // color the name unless it's something like "the old man"
+ if ((msg.Channel == ChatChannel.Local || msg.Channel == ChatChannel.Whisper) && _chatNameColorsEnabled)
+ {
+ var grammar = _ent.GetComponentOrNull<GrammarComponent>(_ent.GetEntity(msg.SenderEntity));
+ if (grammar != null && grammar.ProperNoun == true)
+ msg.WrappedMessage = SharedChatSystem.InjectTagInsideTag(msg, "Name", "color", GetNameColor(SharedChatSystem.GetStringInsideTag(msg, "Name")));
+ }
+
// Log all incoming chat to repopulate when filter is un-toggled
if (!msg.HideChat)
{
}
}
+ /// <summary>
+ /// Returns the chat name color for a mob
+ /// </summary>
+ /// <param name="name">Name of the mob</param>
+ /// <returns>Hex value of the color</returns>
+ public string GetNameColor(string name)
+ {
+ var colorIdx = Math.Abs(name.GetHashCode() % _chatNameColors.Length);
+ return _chatNameColors[colorIdx];
+ }
+
private readonly record struct SpeechBubbleData(ChatMessage Message, SpeechBubble.SpeechType Type);
private sealed class SpeechBubbleQueueData
using Content.Shared.CCVar;
using Content.Shared.Chat;
using Content.Shared.Database;
-using Content.Shared.Decals;
using Content.Shared.Ghost;
using Content.Shared.Humanoid;
using Content.Shared.IdentityManagement;
using Robust.Shared.Audio.Systems;
using Robust.Shared.Configuration;
using Robust.Shared.Console;
-using Robust.Shared.GameObjects.Components.Localization;
using Robust.Shared.Network;
using Robust.Shared.Player;
using Robust.Shared.Prototypes;
private bool _critLoocEnabled;
private readonly bool _adminLoocEnabled = true;
- [ValidatePrototypeId<ColorPalettePrototype>]
- private const string ChatNamePalette = "ChatNames";
- private string[] _chatNameColors = default!;
-
public override void Initialize()
{
base.Initialize();
_configurationManager.OnValueChanged(CCVars.CritLoocEnabled, OnCritLoocEnabledChanged, true);
SubscribeLocalEvent<GameRunLevelChangedEvent>(OnGameChange);
-
- var nameColors = _prototypeManager.Index<ColorPalettePrototype>(ChatNamePalette).Colors.Values.ToArray();
- _chatNameColors = new string[nameColors.Length];
- for (var i = 0; i < nameColors.Length; i++)
- {
- _chatNameColors[i] = nameColors[i].ToHex();
- }
}
public override void Shutdown()
name = FormattedMessage.EscapeText(name);
- // color the name unless it's something like "the old man"
- string coloredName = name;
- if (!TryComp<GrammarComponent>(source, out var grammar) || grammar.ProperNoun == true)
- coloredName = $"[color={GetNameColor(name)}]{name}[/color]";
-
var wrappedMessage = Loc.GetString(speech.Bold ? "chat-manager-entity-say-bold-wrap-message" : "chat-manager-entity-say-wrap-message",
- ("entityName", coloredName),
+ ("entityName", name),
("verb", Loc.GetString(_random.Pick(speech.SpeechVerbStrings))),
("fontType", speech.FontId),
("fontSize", speech.FontSize),
}
name = FormattedMessage.EscapeText(name);
- // color the name unless it's something like "the old man"
- if (!TryComp<GrammarComponent>(source, out var grammar) || grammar.ProperNoun == true)
- name = $"[color={GetNameColor(name)}]{name}[/color]";
-
var wrappedMessage = Loc.GetString("chat-manager-entity-whisper-wrap-message",
("entityName", name), ("message", FormattedMessage.EscapeText(message)));
#region Utility
- /// <summary>
- /// Returns the chat name color for a mob
- /// </summary>
- /// <param name="name">Name of the mob</param>
- /// <returns>Hex value of the color</returns>
- public string GetNameColor(string name)
- {
- var colorIdx = Math.Abs(name.GetHashCode() % _chatNameColors.Length);
- return _chatNameColors[colorIdx];
- }
-
private enum MessageRangeCheckResult
{
Disallowed,
public static readonly CVarDef<bool> ReducedMotion =
CVarDef.Create("accessibility.reduced_motion", false, CVar.CLIENTONLY | CVar.ARCHIVE);
+ public static readonly CVarDef<bool> ChatEnableColorName =
+ CVarDef.Create("accessibility.enable_color_name", true, CVar.CLIENTONLY | CVar.ARCHIVE, "Toggles displaying names with individual colors.");
+
/// <summary>
/// Screen shake intensity slider, controlling the intensity of the CameraRecoilSystem.
/// Goes from 0 (no recoil at all) to 1 (regular amounts of recoil)
return trimmed;
}
+
+ public static string InjectTagInsideTag(ChatMessage message, string outerTag, string innerTag, string? tagParameter)
+ {
+ var rawmsg = message.WrappedMessage;
+ var tagStart = rawmsg.IndexOf($"[{outerTag}]");
+ var tagEnd = rawmsg.IndexOf($"[/{outerTag}]");
+ if (tagStart < 0 || tagEnd < 0) //If the outer tag is not found, the injection is not performed
+ return rawmsg;
+ tagStart += outerTag.Length + 2;
+
+ string innerTagProcessed = tagParameter != null ? $"[{innerTag}={tagParameter}]" : $"[{innerTag}]";
+
+ rawmsg = rawmsg.Insert(tagEnd, $"[/{innerTag}]");
+ rawmsg = rawmsg.Insert(tagStart, innerTagProcessed);
+
+ return rawmsg;
+ }
+ public static string GetStringInsideTag(ChatMessage message, string tag)
+ {
+ var rawmsg = message.WrappedMessage;
+ var tagStart = rawmsg.IndexOf($"[{tag}]");
+ var tagEnd = rawmsg.IndexOf($"[/{tag}]");
+ if (tagStart < 0 || tagEnd < 0)
+ return "";
+ tagStart += tag.Length + 2;
+ return rawmsg.Substring(tagStart, tagEnd - tagStart);
+ }
}
chat-manager-server-wrap-message = [bold]{$message}[/bold]
chat-manager-sender-announcement-wrap-message = [font size=14][bold]{$sender} Announcement:[/font][font size=12]
{$message}[/bold][/font]
-chat-manager-entity-say-wrap-message = [BubbleHeader][bold]{$entityName}[/bold][/BubbleHeader] {$verb}, [font={$fontType} size={$fontSize}]"[BubbleContent]{$message}[/BubbleContent]"[/font]
-chat-manager-entity-say-bold-wrap-message = [BubbleHeader][bold]{$entityName}[/bold][/BubbleHeader] {$verb}, [font={$fontType} size={$fontSize}]"[BubbleContent][bold]{$message}[/bold][/BubbleContent]"[/font]
+chat-manager-entity-say-wrap-message = [BubbleHeader][bold][Name]{$entityName}[/Name][/bold][/BubbleHeader] {$verb}, [font={$fontType} size={$fontSize}]"[BubbleContent]{$message}[/BubbleContent]"[/font]
+chat-manager-entity-say-bold-wrap-message = [BubbleHeader][bold][Name]{$entityName}[/Name][/bold][/BubbleHeader] {$verb}, [font={$fontType} size={$fontSize}]"[BubbleContent][bold]{$message}[/bold][/BubbleContent]"[/font]
-chat-manager-entity-whisper-wrap-message = [font size=11][italic][BubbleHeader]{$entityName}[/BubbleHeader] whispers,"[BubbleContent]{$message}[/BubbleContent]"[/italic][/font]
+chat-manager-entity-whisper-wrap-message = [font size=11][italic][BubbleHeader][Name]{$entityName}[/Name][/BubbleHeader] whispers,"[BubbleContent]{$message}[/BubbleContent]"[/italic][/font]
chat-manager-entity-whisper-unknown-wrap-message = [font size=11][italic][BubbleHeader]Someone[/BubbleHeader] whispers, "[BubbleContent]{$message}[/BubbleContent]"[/italic][/font]
# THE() is not used here because the entity and its name can technically be disconnected if a nameOverride is passed...
ui-options-show-looc-on-head = Show LOOC chat above characters head
ui-options-fancy-speech = Show names in speech bubbles
ui-options-fancy-name-background = Add background to speech bubble names
+ui-options-enable-color-name = Add colors to character names
ui-options-reduced-motion = Reduce motion of visual effects
ui-options-screen-shake-intensity = Screen shake intensity
ui-options-screen-shake-percent = { TOSTRING($intensity, "P0") }