Add text highlighting (#31442)

Heavy DeltaV modications by Vanessa

Co-authored-by: ScarKy0 <106310278+ScarKy0@users.noreply.github.com>
Co-authored-by: Hans Larsson <hanandlia@gmail.com>
Co-authored-by: Tobias Berger <toby@tobot.dev>
Co-authored-by: Vanessa <vanessalouwagie@gmail.com>
This commit is contained in:
vitopigno 2025-06-04 12:12:37 +02:00 committed by Vanessa
parent a779990dfc
commit d9bb797d32
26 changed files with 486 additions and 889 deletions

View File

@ -1,7 +1,8 @@
using Content.Client.Options.UI;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
namespace Content.Client._DV.Options.UI;
namespace Content.Client.Options.UI;
/// <summary>
/// Standard UI control used for color sliders in the options menu. Intended for use with <see cref="OptionsTabControlRow"/>.

View File

@ -121,6 +121,19 @@ public sealed partial class OptionsTabControlRow : Control
return AddOption(new OptionSliderFloatCVar(this, _cfg, cVar, slider, min, max, scale, FormatPercent));
}
/// <summary>
/// Add a color slider option, backed by a simple string CVar.
/// </summary>
/// <param name="cVar">The CVar represented by the slider.</param>
/// <param name="slider">The UI control for the option.</param>
/// <returns>The option instance backing the added option.</returns>
public OptionColorSliderCVar AddOptionColorSlider(
CVarDef<string> cVar,
OptionColorSlider slider)
{
return AddOption(new OptionColorSliderCVar(this, _cfg, cVar, slider));
}
/// <summary>
/// Add a slider option, backed by a simple integer CVar.
/// </summary>
@ -518,6 +531,58 @@ public sealed class OptionSliderFloatCVar : BaseOptionCVar<float>
}
}
/// <summary>
/// Implementation of a CVar option that simply corresponds with a string <see cref="OptionColorSlider"/>.
/// </summary>
/// <seealso cref="OptionsTabControlRow"/>
public sealed class OptionColorSliderCVar : BaseOptionCVar<string>
{
private readonly OptionColorSlider _slider;
protected override string Value
{
get => _slider.Slider.Color.ToHex();
set
{
_slider.Slider.Color = Color.FromHex(value);
UpdateLabelColor();
}
}
/// <summary>
/// Creates a new instance of this type.
/// </summary>
/// <remarks>
/// <para>
/// It is generally more convenient to call overloads on <see cref="OptionsTabControlRow"/>
/// such as <see cref="OptionsTabControlRow.AddOptionPercentSlider"/> instead of instantiating this type directly.
/// </para>
/// </remarks>
/// <param name="controller">The control row that owns this option.</param>
/// <param name="cfg">The configuration manager to get and set values from.</param>
/// <param name="cVar">The CVar that is being controlled by this option.</param>
/// <param name="slider">The UI control for the option.</param>
public OptionColorSliderCVar(
OptionsTabControlRow controller,
IConfigurationManager cfg,
CVarDef<string> cVar,
OptionColorSlider slider) : base(controller, cfg, cVar)
{
_slider = slider;
slider.Slider.OnColorChanged += _ =>
{
ValueChanged();
UpdateLabelColor();
};
}
private void UpdateLabelColor()
{
_slider.ExampleLabel.FontColorOverride = Color.FromHex(Value);
}
}
/// <summary>
/// Implementation of a CVar option that simply corresponds with an integer <see cref="OptionSlider"/>.
/// </summary>

View File

@ -14,6 +14,10 @@
<ui:OptionSlider Name="SpeechBubbleTextOpacitySlider" Title="{Loc 'ui-options-speech-bubble-text-opacity'}" />
<ui:OptionSlider Name="SpeechBubbleSpeakerOpacitySlider" Title="{Loc 'ui-options-speech-bubble-speaker-opacity'}" />
<ui:OptionSlider Name="SpeechBubbleBackgroundOpacitySlider" Title="{Loc 'ui-options-speech-bubble-background-opacity'}" />
<CheckBox Name="AutoFillHighlightsCheckBox" Text="{Loc 'ui-options-auto-fill-highlights'}" />
<ui:OptionColorSlider Name="HighlightsColorSlider"
Title="{Loc 'ui-options-highlights-color'}"
Example="{Loc 'ui-options-highlights-color-example'}"/>
<Label Text="{Loc 'ui-options-accessability-header-content'}"
StyleClasses="LabelKeyText"/>
<CheckBox Name="CensorNudityCheckBox" Text="{Loc 'ui-options-censor-nudity'}" />

View File

@ -20,6 +20,8 @@ public sealed partial class AccessibilityTab : Control
Control.AddOptionPercentSlider(CCVars.SpeechBubbleTextOpacity, SpeechBubbleTextOpacitySlider);
Control.AddOptionPercentSlider(CCVars.SpeechBubbleSpeakerOpacity, SpeechBubbleSpeakerOpacitySlider);
Control.AddOptionPercentSlider(CCVars.SpeechBubbleBackgroundOpacity, SpeechBubbleBackgroundOpacitySlider);
Control.AddOptionCheckBox(CCVars.ChatAutoFillHighlights, AutoFillHighlightsCheckBox);
Control.AddOptionColorSlider(CCVars.ChatHighlightsColor, HighlightsColorSlider);
Control.AddOptionCheckBox(CCVars.AccessibilityClientCensorNudity, CensorNudityCheckBox);

View File

@ -0,0 +1,164 @@
using System.Linq;
using System.Text.RegularExpressions;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controllers;
using Content.Shared._DV.CCVars; // DeltaV
using Content.Shared.CCVar;
using Content.Client.CharacterInfo;
using static Content.Client.CharacterInfo.CharacterInfoSystem;
using System.Collections;
using Content.Shared.Mobs;
namespace Content.Client.UserInterface.Systems.Chat;
/// <summary>
/// A partial class of ChatUIController that handles the saving and loading of highlights for the chatbox.
/// It also makes use of the CharacterInfoSystem to optionally generate highlights based on the character's info.
/// </summary>
public sealed partial class ChatUIController : IOnSystemChanged<CharacterInfoSystem>
{
[UISystemDependency] private readonly CharacterInfoSystem _characterInfo = default!;
/// <summary>
/// The list of words to be highlighted in the chatbox.
/// </summary>
private List<string> _highlights = new();
/// <summary>
/// The string holding the hex color used to highlight words.
/// </summary>
private string? _highlightsColor;
private bool _autoFillHighlightsEnabled;
/// <summary>
/// The boolean that keeps track of the 'OnCharacterUpdated' event, whenever it's a player attaching or opening the character info panel.
/// </summary>
private bool _charInfoIsAttach = false;
public event Action<string>? HighlightsUpdated;
private void InitializeHighlights()
{
MigrateDVHighlightSettings(); // TODO: SUM - Remove (DeltaV)
_config.OnValueChanged(CCVars.ChatAutoFillHighlights, (value) => { _autoFillHighlightsEnabled = value; }, true);
_config.OnValueChanged(CCVars.ChatHighlightsColor, (value) => { _highlightsColor = value; }, true);
// Load highlights if any were saved.
string highlights = _config.GetCVar(DCCVars.ChatHighlights); // DeltaV - Switched to use our CVar
if (!string.IsNullOrEmpty(highlights) || AutoHighlightsEnabled) // DeltaV - Message auto-highlighting
{
UpdateHighlights(highlights, true);
}
}
public void OnSystemLoaded(CharacterInfoSystem system)
{
system.OnCharacterUpdate += OnCharacterUpdated;
}
public void OnSystemUnloaded(CharacterInfoSystem system)
{
system.OnCharacterUpdate -= OnCharacterUpdated;
}
private void UpdateAutoFillHighlights()
{
if (!_autoFillHighlightsEnabled)
return;
// If auto highlights are enabled generate a request for new character info
// that will be used to determine the highlights.
_charInfoIsAttach = true;
_characterInfo.RequestCharacterInfo();
}
public void UpdateHighlights(string newHighlights, bool firstLoad = false)
{
// DeltaV - Heavily modified to split out the auto-generated highlights from the user-defined ones.
if (!firstLoad && !_config.GetCVar(DCCVars.ChatHighlights).Equals(newHighlights, StringComparison.CurrentCultureIgnoreCase))
{
_config.SetCVar(DCCVars.ChatHighlights, newHighlights); // DV - Moved inside this if because the comparison
_config.SaveToFile();
}
_highlights.Clear();
// We first subdivide the highlights based on newlines to prevent replacing
// a valid "\n" tag and adding it to the final regex.
var allHighlights = $"{newHighlights}\n{AutoHighlights}"; // Even if AutoHighlights is empty, the split below will remove it.
string[] splittedHighlights = allHighlights.Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
// END DeltaV
for (int i = 0; i < splittedHighlights.Length; i++)
{
// Replace every "\" character with a "\\" to prevent "\n", "\0", etc...
string keyword = splittedHighlights[i].Replace(@"\", @"\\");
// Escape the keyword to prevent special characters like "(" and ")" to be considered valid regex.
keyword = Regex.Escape(keyword);
// 1. Since the "["s in WrappedMessage are already sanitized, add 2 extra "\"s
// to make sure it matches the literal "\" before the square bracket.
keyword = keyword.Replace(@"\[", @"\\\[");
// If present, replace the double quotes at the edges with tags
// that make sure the words to match are separated by spaces or punctuation.
// NOTE: The reason why we don't use \b tags is that \b doesn't match reverse slash characters "\" so
// a pre-sanitized (see 1.) string like "\[test]" wouldn't get picked up by the \b.
if (keyword.Count(c => (c == '"')) > 0)
{
// Matches the last double quote character.
keyword = Regex.Replace(keyword, "\"$", "(?!\\w)");
// When matching for the first double quote character we also consider the possibility
// of the double quote being preceded by a @ character.
keyword = Regex.Replace(keyword, "^\"|(?<=^@)\"", "(?<!\\w)");
}
// Make sure any name tagged as ours gets highlighted only when others say it.
keyword = Regex.Replace(keyword, "^@", "(?<=(?<=/name.*)|(?<=,.*\"\".*))");
_highlights.Add(keyword);
}
// Arrange the list of highlights in descending order so that when highlighting,
// the full word (eg. "Security") gets picked before the abbreviation (eg. "Sec").
_highlights.Sort((x, y) => y.Length.CompareTo(x.Length));
}
// DeltaV - Modified and moved to Content.Client/_DV/UserInterfaces/Systems/Chat/ChatUIController.cs
// Commented out so that if you get a conflict, you actually put that change in the updated method.
/*private void OnCharacterUpdated(CharacterData data)
{
// If _charInfoIsAttach is false then the opening of the character panel was the one
// to generate the event, dismiss it.
if (!_charInfoIsAttach)
return;
var (_, job, _, _, entityName) = data;
// Mark this entity's name as our character name for the "UpdateHighlights" function.
string newHighlights = "@" + entityName;
// Subdivide the character's name based on spaces or hyphens so that every word gets highlighted.
if (newHighlights.Count(c => (c == ' ' || c == '-')) == 1)
newHighlights = newHighlights.Replace("-", "\n@").Replace(" ", "\n@");
// If the character has a name with more than one hyphen assume it is a lizard name and extract the first and
// last name eg. "Eats-The-Food" -> "@Eats" "@Food"
if (newHighlights.Count(c => c == '-') > 1)
newHighlights = newHighlights.Split('-')[0] + "\n@" + newHighlights.Split('-')[^1];
// Convert the job title to kebab-case and use it as a key for the loc file.
string jobKey = job.Replace(' ', '-').ToLower();
if (Loc.TryGetString($"highlights-{jobKey}", out var jobMatches))
newHighlights += '\n' + jobMatches.Replace(", ", "\n");
UpdateHighlights(newHighlights);
HighlightsUpdated?.Invoke(newHighlights);
_charInfoIsAttach = false;
}*/
}

View File

@ -42,9 +42,9 @@ using Robust.Shared.Timing;
using Robust.Shared.Utility;
using Content.Client.Nyanotrasen.Chat; //Nyano - Summary: chat namespace.
namespace Content.Client.UserInterface.Systems.Chat;
// DeltaV - Make partial to implement message highlighting
public sealed partial class ChatUIController : UIController
{
[Dependency] private readonly IClientAdminManager _admin = default!;
@ -245,7 +245,7 @@ public sealed partial class ChatUIController : UIController
_config.OnValueChanged(CCVars.ChatWindowOpacity, OnChatWindowOpacityChanged);
InitializeChatHighlights(); // DeltaV - Message highlighting
InitializeHighlights();
}
public void OnScreenLoad()
@ -432,6 +432,8 @@ public sealed partial class ChatUIController : UIController
private void OnAttachedChanged(EntityUid uid)
{
UpdateChannelPermissions();
UpdateAutoFillHighlights();
}
private void AddSpeechBubble(ChatMessage msg, SpeechBubble.SpeechType speechType)
@ -840,13 +842,11 @@ public sealed partial class ChatUIController : UIController
msg.WrappedMessage = SharedChatSystem.InjectTagInsideTag(msg, "Name", "color", GetNameColor(SharedChatSystem.GetStringInsideTag(msg, "Name")));
}
// DeltaV - Message highlighting start
// Color any words choosen by the client.
// Color any words chosen by the client.
foreach (var highlight in _highlights)
{
msg.WrappedMessage = SharedChatSystem.InjectTagAroundString(msg, highlight, "color", _highlightsColor);
}
// DeltaV - Message highlighting end
// Color any codewords for minds that have roles that use them
if (_player.LocalUser != null && _mindSystem != null && _roleCodewordSystem != null)

View File

@ -3,22 +3,19 @@
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
xmlns:controls="clr-namespace:Content.Client.UserInterface.Systems.Chat.Controls">
<PanelContainer Name="FilterPopupPanel" StyleClasses="BorderedWindowPanel">
<!-- DeltaV - Additional outer BoxContainer for changed layout including message highlighting -->
<BoxContainer Orientation="Horizontal" SeparationOverride="8" Margin="10 0">
<BoxContainer Orientation="Vertical" Margin="0 10">
<Label Text="{Loc 'hud-chatbox-select-channels'}"/>
<BoxContainer Name="FilterVBox" MinWidth="105" Orientation="Vertical" SeparationOverride="4"/>
</BoxContainer>
<!-- DeltaV - Message highlighting start -->
<BoxContainer Name="FilterVBox" MinWidth="105" Margin="0 10" Orientation="Vertical" SeparationOverride="4"/>
<BoxContainer Name="HighlightsVBox" MinWidth="120" Margin="0 10" Orientation="Vertical" SeparationOverride="4">
<Label Text="{Loc 'hud-chatbox-highlights'}"/>
<!-- Custom background for the TextEdit -->
<PanelContainer>
<!-- Begin custom background for TextEdit -->
<PanelContainer.PanelOverride>
<gfx:StyleBoxFlat BackgroundColor="#323446"/>
</PanelContainer.PanelOverride>
<!-- End custom background -->
<TextEdit Name="HighlightEdit" MinHeight="150" Margin="5 5"/>
</PanelContainer>
<!-- DeltaV - Message Auto-highlighting -->
<Label Name="AutoHighlightLabel" Text="{Loc 'hud-chatbox-auto-highlights'}"/>
<PanelContainer>
<PanelContainer.PanelOverride>
@ -26,9 +23,9 @@
</PanelContainer.PanelOverride>
<TextEdit Name="AutoHighlightEdit" MinHeight="150" Margin="5 5" Editable="false" />
</PanelContainer>
<!-- END DeltaV -->
<Button Name="HighlightButton" Text="{Loc 'hud-chatbox-highlights-button'}" ToolTip="{Loc 'hud-chatbox-highlights-tooltip'}"/>
</BoxContainer>
<!-- DeltaV - Message highlighting end -->
</BoxContainer>
</PanelContainer>
</controls:ChannelFilterPopup>

View File

@ -1,4 +1,8 @@
using Content.Shared._DV.CCVars; // DeltaV
using Content.Shared.Chat;
using Content.Shared.CCVar;
using Robust.Shared.Utility;
using Robust.Shared.Configuration;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
@ -30,11 +34,25 @@ public sealed partial class ChannelFilterPopup : Popup
private readonly Dictionary<ChatChannel, ChannelFilterCheckbox> _filterStates = new();
public event Action<ChatChannel, bool>? OnChannelFilter;
public event Action<string>? OnNewHighlights;
public ChannelFilterPopup()
{
RobustXamlLoader.Load(this);
InitializeChatHighlights(); // DeltaV - Message highlighting
HighlightButton.OnPressed += HighlightsEntered;
// Add a placeholder text to the highlights TextEdit.
HighlightEdit.Placeholder = new Rope.Leaf(Loc.GetString("hud-chatbox-highlights-placeholder"));
// Load highlights if any were saved.
var cfg = IoCManager.Resolve<IConfigurationManager>();
string highlights = cfg.GetCVar(DCCVars.ChatHighlights); // DeltaV - Use our own CVar
var autoHighlightsEnabled = cfg.GetCVar(CCVars.ChatAutoFillHighlights); // DeltaV - Auto-highlighting
if (!string.IsNullOrEmpty(highlights) || autoHighlightsEnabled) // DeltaV - Auto-highlighting
{
UpdateHighlights(highlights);
}
}
public bool IsActive(ChatChannel channel)
@ -94,12 +112,22 @@ public sealed partial class ChannelFilterPopup : Popup
}
}
public void UpdateHighlights(string highlights)
{
HighlightEdit.TextRope = new Rope.Leaf(highlights);
}
private void CheckboxPressed(ButtonEventArgs args)
{
var checkbox = (ChannelFilterCheckbox) args.Button;
OnChannelFilter?.Invoke(checkbox.Channel, checkbox.Pressed);
}
private void HighlightsEntered(ButtonEventArgs _args)
{
OnNewHighlights?.Invoke(Rope.Collapse(HighlightEdit.TextRope));
}
public void UpdateUnread(ChatChannel channel, int? unread)
{
if (_filterStates.TryGetValue(channel, out var checkbox))

View File

@ -51,10 +51,11 @@ public partial class ChatBox : UIWidget
ChatInput.Input.OnFocusExit += OnFocusExit;
ChatInput.ChannelSelector.OnChannelSelect += OnChannelSelect;
ChatInput.FilterButton.Popup.OnChannelFilter += OnChannelFilter;
ChatInput.FilterButton.Popup.OnNewHighlights += OnNewHighlights; // DeltaV - Message highlighting
ChatInput.FilterButton.Popup.OnNewHighlights += OnNewHighlights;
_controller = UserInterfaceManager.GetUIController<ChatUIController>();
_controller.OnAutoHighlightsUpdated += ChatInput.FilterButton.Popup.SetAutoHighlights; // DeltaV - Message highlighting
_controller.MessageAdded += OnMessageAdded;
_controller.HighlightsUpdated += OnHighlightsUpdated;
_controller.RegisterChat(this);
// EE - Chat stacking
@ -140,6 +141,11 @@ public partial class ChatBox : UIWidget
_chatStackList.Insert(0, new ChatStackData(wrappedMessage, colorOverride));
}
private void OnHighlightsUpdated(string highlights)
{
ChatInput.FilterButton.Popup.UpdateHighlights(highlights);
}
private void OnChannelSelect(ChatSelectChannel channel)
{
_controller.UpdateSelectedChannel(this);
@ -170,7 +176,12 @@ public partial class ChatBox : UIWidget
}
}
public void AddLine(string message, Color color, int repeat = 0) // EE - Chat stacking - repeat
private void OnNewHighlights(string highlighs)
{
_controller.UpdateHighlights(highlighs);
}
public void AddLine(string message, Color color, int repeat = 0) // EE - Chat stacking - repea
{
var formatted = new FormattedMessage(4); // EE - Chat stacking - up from 3
formatted.PushColor(color);

View File

@ -1,20 +0,0 @@
using Content.Client._DV.Options.UI;
using Robust.Shared.Configuration;
namespace Content.Client.Options.UI;
public sealed partial class OptionsTabControlRow
{
/// <summary>
/// Add a color slider option, backed by a simple string CVar.
/// </summary>
/// <param name="cVar">The CVar represented by the slider.</param>
/// <param name="slider">The UI control for the option.</param>
/// <returns>The option instance backing the added option.</returns>
public OptionColorSliderCVar AddOptionColorSlider(
CVarDef<string> cVar,
OptionColorSlider slider)
{
return AddOption(new OptionColorSliderCVar(this, _cfg, cVar, slider));
}
}

View File

@ -1,56 +0,0 @@
using Content.Client.Options.UI;
using Robust.Shared.Configuration;
namespace Content.Client._DV.Options.UI;
/// <summary>
/// Implementation of a CVar option that simply corresponds with a string <see cref="OptionColorSlider"/>.
/// </summary>
/// <seealso cref="OptionsTabControlRow"/>
public sealed class OptionColorSliderCVar : BaseOptionCVar<string>
{
private readonly OptionColorSlider _slider;
protected override string Value
{
get => _slider.Slider.Color.ToHex();
set
{
_slider.Slider.Color = Color.FromHex(value);
UpdateLabelColor();
}
}
/// <summary>
/// Creates a new instance of this type.
/// </summary>
/// <remarks>
/// <para>
/// It is generally more convenient to call overloads on <see cref="OptionsTabControlRow"/>
/// such as <see cref="OptionsTabControlRow.AddOptionPercentSlider"/> instead of instantiating this type directly.
/// </para>
/// </remarks>
/// <param name="controller">The control row that owns this option.</param>
/// <param name="cfg">The configuration manager to get and set values from.</param>
/// <param name="cVar">The CVar that is being controlled by this option.</param>
/// <param name="slider">The UI control for the option.</param>
public OptionColorSliderCVar(
OptionsTabControlRow controller,
IConfigurationManager cfg,
CVarDef<string> cVar,
OptionColorSlider slider) : base(controller, cfg, cVar)
{
_slider = slider;
slider.Slider.OnColorChanged += _ =>
{
ValueChanged();
UpdateLabelColor();
};
}
private void UpdateLabelColor()
{
_slider.ExampleLabel.FontColorOverride = Color.FromHex(Value);
}
}

View File

@ -2,6 +2,7 @@
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
xmlns:tabs="clr-namespace:Content.Client._DV.Options.UI.Tabs"
xmlns:xNamespace="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:optionsUI="clr-namespace:Content.Client.Options.UI"
xmlns:s="clr-namespace:Content.Client.Stylesheets"
xmlns:ui="clr-namespace:Content.Client.Options.UI"
xmlns:dvui="clr-namespace:Content.Client._DV.Options.UI">
@ -15,10 +16,6 @@
StyleClasses="LabelKeyText"/>
<CheckBox Name="DisableFiltersCheckBox" Text="{Loc 'ui-options-no-filters'}" />
<CheckBox Name="DisableGlimmerEffectCheckBox" Text="{Loc 'ui-options-disable-glimmer-effect'}" />
<CheckBox Name="AutoFillHighlightsCheckBox" Text="{Loc 'ui-options-auto-fill-highlights'}" />
<dvui:OptionColorSlider Name="HighlightsColorSlider"
Title="{Loc 'ui-options-highlights-color'}"
Example="{Loc 'ui-options-highlights-color-example'}"/>
</BoxContainer>
<ui:OptionsTabControlRow Name="Control" Access="Public" />
</BoxContainer>

View File

@ -1,4 +1,5 @@
using Content.Shared._DV.CCVars;
using Content.Client.Options.UI;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.XAML;
@ -15,8 +16,8 @@ public sealed partial class DeltaTab : Control
Control.AddOptionCheckBox(DCCVars.NoVisionFilters, DisableFiltersCheckBox);
Control.AddOptionCheckBox(DCCVars.DisableGlimmerShader, DisableGlimmerEffectCheckBox);
Control.AddOptionCheckBox(DCCVars.ChatAutoFillHighlights, AutoFillHighlightsCheckBox);
Control.AddOptionColorSlider(DCCVars.ChatHighlightsColor, HighlightsColorSlider);
//Control.AddOptionCheckBox(DCCVars.ChatAutoFillHighlights, AutoFillHighlightsCheckBox); // Migrating to the new system
//Control.AddOptionColorSlider(DCCVars.ChatHighlightsColor, HighlightsColorSlider); // Migrating to the new system
Control.Initialize();
}

View File

@ -1,6 +1,7 @@
using System.Linq;
using System.Text.RegularExpressions;
using Content.Client.CharacterInfo;
using Content.Shared.CCVar;
using Content.Shared._DV.CCVars;
using Content.Shared.Dataset;
using Robust.Client.UserInterface;
@ -17,116 +18,84 @@ public sealed partial class ChatUIController : IOnSystemChanged<CharacterInfoSys
/// </summary>
public event Action<string>? OnAutoHighlightsUpdated;
[UISystemDependency] private readonly CharacterInfoSystem _characterInfo = default!;
/// <summary>
/// A list of words to be highlighted in the chatbox.
/// User-specified.
/// </summary>
private readonly List<string> _highlights = [];
/// <summary>
/// A list of words to be highlighted in the chatbox.
/// Auto-generated from users's character information.
/// </summary>
private readonly List<string> _autoHighlights = [];
private string _autoHighlights = String.Empty;
/// <summary>
/// The color (hex) in witch the words will be highlighted as.
/// Returns the list of auto-generated highlights based on the character's info (job, name, etc). Returns an empty list if the option is disabled.
/// </summary>
private string? _highlightsColor;
internal string AutoHighlights => _autoFillHighlightsEnabled ? _autoHighlights : String.Empty;
private bool _autoFillHighlightsEnabled;
internal string CurrentUserHighlights => _config.GetCVar(DCCVars.ChatHighlights);
private void InitializeChatHighlights()
/// <summary>
/// Gets whether the player has auto-generated highlights enabled or not.
/// </summary>
internal bool AutoHighlightsEnabled => _autoFillHighlightsEnabled;
internal void OnCharacterUpdated(CharacterData data)
{
// If _charInfoIsAttach is false then the opening of the character panel was the one
// to generate the event, dismiss it.
if (!_charInfoIsAttach)
return;
_player.LocalPlayerAttached += _ => _characterInfo.RequestCharacterInfo();
_player.LocalPlayerDetached += _ => _characterInfo.RequestCharacterInfo();
_config.OnValueChanged(DCCVars.ChatAutoFillHighlights, value => { _autoFillHighlightsEnabled = value; UpdateHighlights(); });
_autoFillHighlightsEnabled = _config.GetCVar(DCCVars.ChatAutoFillHighlights);
_config.OnValueChanged(DCCVars.ChatHighlightsColor, value => _highlightsColor = value);
_highlightsColor = _config.GetCVar(DCCVars.ChatHighlightsColor);
_config.OnValueChanged(DCCVars.ChatHighlights, UpdateHighlights);
UpdateHighlights(_config.GetCVar(DCCVars.ChatHighlights));
}
public void OnSystemLoaded(CharacterInfoSystem system)
{
system.OnCharacterUpdate += UpdateAutoHighlights;
}
public void OnSystemUnloaded(CharacterInfoSystem system)
{
system.OnCharacterUpdate -= UpdateAutoHighlights;
}
private void UpdateAutoHighlights(CharacterData data)
{
var (_, job, _, _, entityName) = data;
_autoHighlights.Clear();
// Mark this entity's name as our character name for the "UpdateHighlights" function.
string newHighlights = "@" + entityName;
// If the character has a normal name (eg. "Name Surname" and not "Name Initial Surname" or a particular species name)
// subdivide it so that the name and surname individually get highlighted.
if (entityName.Count(c => c == ' ') == 1)
_autoHighlights.AddRange(entityName.Split(' '));
_autoHighlights.Add(entityName);
// Subdivide the character's name based on spaces or hyphens so that every word gets highlighted.
if (newHighlights.Count(c => (c == ' ' || c == '-')) == 1)
newHighlights = newHighlights.Replace("-", "\n@").Replace(" ", "\n@");
var jobKey = "ChatHighlight" + job.Replace(" ", "");
if (_prototypeManager.TryIndex<LocalizedDatasetPrototype>(jobKey, out var jobMatches))
_autoHighlights.AddRange(jobMatches.Values.Select(Loc.GetString));
else
_sawmill.Debug("Missing LocalizedDataset for Job: " + jobKey);
UpdateHighlights();
// If the character has a name with more than one hyphen assume it is a lizard name and extract the first and
// last name eg. "Eats-The-Food" -> "@Eats" "@Food"
if (newHighlights.Count(c => c == '-') > 1)
newHighlights = newHighlights.Split('-')[0] + "\n@" + newHighlights.Split('-')[^1];
// Convert the job title to kebab-case and use it as a key for the loc file.
string jobKey = job.Replace(' ', '-').ToLower();
if (Loc.TryGetString($"highlights-{jobKey}", out var jobMatches))
newHighlights += '\n' + jobMatches.Replace(", ", "\n");
_autoHighlights = newHighlights; // DeltaV
UpdateHighlights(CurrentUserHighlights); // DeltaV
OnAutoHighlightsUpdated?.Invoke($"{AutoHighlights}"); // DeltaV
_charInfoIsAttach = false;
}
public void UpdateHighlights(string? newHighlights = null)
/// <summary>
/// This is ugly but it's only going to be around until the next upstream merge.
/// We'll still use DCCVars.ChatHighlights.
/// </summary>
private void MigrateDVHighlightSettings()
{
var configuredHighlights = _config.GetCVar(DCCVars.ChatHighlights);
var highlights = newHighlights ?? configuredHighlights;
// Save the newly provided list of highlights if different.
if (newHighlights is not null && !string.Equals(configuredHighlights, highlights, StringComparison.CurrentCultureIgnoreCase))
// AutoHightligt Checkbox
bool shouldSave = false;
var oldDCCAutofillFlag = _config.GetCVar(DCCVars.ChatAutoFillHighlights);
if (oldDCCAutofillFlag)
{
_config.SetCVar(DCCVars.ChatHighlights, highlights);
_config.SetCVar(CCVars.ChatAutoFillHighlights, oldDCCAutofillFlag);
_config.SetCVar(DCCVars.ChatAutoFillHighlights, false); // Next time this runs, it won't migrate this value again since CCVars.ChatAutoFillHighlights defaults to false.
shouldSave = true;
}
// Chat Color
var oldDCCVarColor = _config.GetCVar(DCCVars.ChatHighlightsColor);
var defaultColor = "#17FFC1FF";
if (!oldDCCVarColor.Equals(defaultColor)) // Default value
{
_config.SetCVar(CCVars.ChatHighlightsColor, oldDCCVarColor); // Next time, it should equal those words
_config.SetCVar(DCCVars.ChatHighlightsColor, defaultColor); // Prevents it from running again
shouldSave = true;
}
if (shouldSave)
_config.SaveToFile();
}
var effectiveAutoHighlights = _autoFillHighlightsEnabled
? string.Join("\n", _autoHighlights)
: string.Empty;
OnAutoHighlightsUpdated?.Invoke(effectiveAutoHighlights);
// If `highlights` is an empty string, this gives a single empty string, which breaks stuff, so check for that separately when adding it to `_highlights`
var allHighlights = _autoFillHighlightsEnabled
? highlights.Split("\n").Concat(_autoHighlights)
: highlights.Split("\n");
_highlights.Clear();
void AddHighlights(IEnumerable<string> highlights)
{
foreach (var highlight in highlights)
{
if (string.IsNullOrWhiteSpace(highlight))
continue;
// Use `"` as layman symbol for Regex `\b`, ignore all other special sequences
// (Without that escape, a name like `Robert'); DROP TABLE users; --` breaks all messsages)
// Turn `\` into `\\` or else it'll escape the tags inside the actual chat message for reasons I can barely intuit but not explain.
_highlights.Add(Regex.Escape(highlight.Replace(@"\", @"\\")).Replace("\"", "\\b"));
}
}
AddHighlights(highlights.Split("\n"));
if (_autoFillHighlightsEnabled)
AddHighlights(_autoHighlights);
// Arrange the list in descending order so that when highlighting,
// the full word (eg. "Security") appears before the abbreviation (eg. "Sec").
_highlights.Sort((x, y) => y.Length.CompareTo(x.Length));
}
}

View File

@ -7,24 +7,6 @@ namespace Content.Client.UserInterface.Systems.Chat.Controls;
public sealed partial class ChannelFilterPopup
{
public event Action<string>? OnNewHighlights;
private void InitializeChatHighlights()
{
HighlightButton.OnPressed += HighlightsEntered;
HighlightEdit.Placeholder = new Rope.Leaf(Loc.GetString("hud-chatbox-highlights-placeholder"));
// Load highlights if any were saved.
var cfg = IoCManager.Resolve<IConfigurationManager>();
var highlights = cfg.GetCVar(DCCVars.ChatHighlights);
if (!string.IsNullOrEmpty(highlights))
{
HighlightEdit.TextRope = new Rope.Leaf(highlights);
}
}
public void SetAutoHighlights(string autoHighlights)
{
var anyAutohighlights = !string.IsNullOrWhiteSpace(autoHighlights);
@ -32,9 +14,4 @@ public sealed partial class ChannelFilterPopup
AutoHighlightLabel.Visible = anyAutohighlights;
AutoHighlightEdit.TextRope = new Rope.Leaf(autoHighlights);
}
private void HighlightsEntered(ButtonEventArgs args)
{
OnNewHighlights?.Invoke(Rope.Collapse(HighlightEdit.TextRope));
}
}

View File

@ -1,9 +0,0 @@
namespace Content.Client.UserInterface.Systems.Chat.Widgets;
public partial class ChatBox
{
private void OnNewHighlights(string highlights)
{
_controller.UpdateHighlights(highlights);
}
}

View File

@ -65,4 +65,23 @@ public sealed partial class CCVars
"",
CVar.SERVER | CVar.SERVERONLY | CVar.ARCHIVE,
"A message broadcast to each player that joins the lobby.");
/// <summary>
/// A string containing a list of newline-separated words to be highlighted in the chat.
/// </summary>
[Obsolete("Use DCCVar.ChatHighlights instead. Trust me.")]
public static readonly CVarDef<string> ChatHighlights =
CVarDef.Create("chat.highlights", "", CVar.CLIENTONLY | CVar.ARCHIVE, "A list of newline-separated words to be highlighted in the chat.");
/// <summary>
/// An option to toggle the automatic filling of the highlights with the character's info, if available.
/// </summary>
public static readonly CVarDef<bool> ChatAutoFillHighlights =
CVarDef.Create("chat.auto_fill_highlights", false, CVar.CLIENTONLY | CVar.ARCHIVE, "Toggles automatically filling the highlights with the character's information.");
/// <summary>
/// The color in which the highlights will be displayed.
/// </summary>
public static readonly CVarDef<string> ChatHighlightsColor =
CVarDef.Create("chat.highlights_color", "#17FFC1FF", CVar.CLIENTONLY | CVar.ARCHIVE, "The color in which the highlights will be displayed.");
}

View File

@ -168,7 +168,7 @@ public sealed partial class DCCVars
CVarDef.Create("game.disable_preset_test", false, CVar.SERVERONLY);
/// <summary>
/// A string containing a list of newline-separated strings to be highlighted in the chat.
/// A string containing a list of newline-separated strings to be highlighted in the chat. Use this instead of Wizden's CVar.
/// </summary>
public static readonly CVarDef<string> ChatHighlights =
CVarDef.Create("deltav.chat.highlights",
@ -179,6 +179,7 @@ public sealed partial class DCCVars
/// <summary>
/// An option to toggle the automatic filling of the highlights with the character's info, if available.
/// </summary>
[Obsolete("Use CCVar.ChatAutoFillHighlights instead.")]
public static readonly CVarDef<bool> ChatAutoFillHighlights =
CVarDef.Create("deltav.chat.auto_fill_highlights",
false,
@ -188,6 +189,7 @@ public sealed partial class DCCVars
/// <summary>
/// The color in which the highlights will be displayed.
/// </summary>
[Obsolete("Use CCVar.ChatHighlightsColor instead.")]
public static readonly CVarDef<string> ChatHighlightsColor =
CVarDef.Create("deltav.chat.highlights_color",
"#17FFC1FF",

View File

@ -1,337 +1,54 @@
# These IDs are generated from job IDs
# The corresponding prototypes are located in Resources/Prototypes/Catalog/_DV/Chat/highlights.yml
# if you add or remove a string here, update the protoype
###### Centcomm
highlight-centcomm-agent-1 = Centcomm
highlight-centcomm-agent-2 = Central Command
highlight-centcomm-agent-3 = Death Squad
highlight-centcomm-agent-4 = DeathSquad
# DeltaV-Specific Jobs
# Follows format of Resources/Locale/en-US/chat/highlights.ftl
highlight-centcomm-official-1 = Centcomm
highlight-centcomm-official-2 = Central Command
highlight-centcomm-quarantine-officer-1 = Centcomm
highlight-centcomm-quarantine-officer-2 = Central Command
highlight-centcomm-quarantine-officer-3 = "CBURN"
###### ERT
highlight-ert-leader-1 = "ERT Leader
highlight-ert-leader-2 = Leader
highlight-ert-leader-3 = "ERT"
highlight-ert-chaplain-1 = Chaplain
highlight-ert-chaplain-2 = "Chap"
highlight-ert-chaplain-3 = Chapel
highlight-ert-chaplain-4 = "ERT"
highlight-ert-engineer-1 = Station Engineer
highlight-ert-engineer-2 = Engineering
highlight-ert-engineer-3 = Engineer
highlight-ert-engineer-4 = "Engi"
highlight-ert-engineer-5 = "ERT"
highlight-ert-janitor-1 = Janitorial
highlight-ert-janitor-2 = Janitor
highlight-ert-janitor-3 = "Jani"
highlight-ert-janitor-4 = "ERT"
highlight-ert-medic-1 = Medical Doctor
highlight-ert-medic-2 = Doctor
highlight-ert-medic-3 = "Doc"
highlight-ert-medic-4 = MedBay
highlight-ert-medic-5 = "Med"
highlight-ert-medic-6 = Medic
highlight-ert-medic-7 = "ERT"
highlight-ert-security-1 = Security Officer
highlight-ert-security-2 = Secoff
highlight-ert-security-3 = Officer
highlight-ert-security-4 = Security
highlight-ert-security-5 = "Sec"
highlight-ert-security-6 = "ERT"
###### Command
highlight-captain-1 = Captain
highlight-captain-2 = "Cap"
highlight-captain-3 = Command
highlight-chief-justice-1 = Chief justice
highlight-chief-justice-2 = "CJ"
highlight-chief-justice-3 = Justice
highlight-chief-justice-4 = Command
highlight-chief-engineer-1 = Chief Engineer
highlight-chief-engineer-2 = "CE"
highlight-chief-engineer-3 = Engineering
highlight-chief-engineer-4 = Engineer
highlight-chief-engineer-5 = "Engi"
highlight-chief-engineer-6 = Command
highlight-chief-medical-officer-1 = Chief Medical Officer
highlight-chief-medical-officer-2 = "CMO"
highlight-chief-medical-officer-3 = MedBay
highlight-chief-medical-officer-4 = "Med"
highlight-chief-medical-officer-5 = Command
highlight-head-of-personnel-1 = Head Of Personnel
highlight-head-of-personnel-2 = "HoP"
highlight-head-of-personnel-3 = Service
highlight-head-of-personnel-4 = Command
highlight-head-of-security-1 = Head of Security
highlight-head-of-security-2 = "HoS"
highlight-head-of-security-3 = Security
highlight-head-of-security-4 = "Sec"
highlight-head-of-security-5 = Command
highlight-logistics-officer-1 = Logistics Officer
highlight-logistics-officer-2 = "LO"
highlight-logistics-officer-3 = Logistics
highlight-logistics-officer-4 = Logi
highlight-logistics-officer-5 = Command
highlight-mystagogue-1 = Mystagogue
highlight-mystagogue-2 = Mysta
highlight-mystagogue-3 = "MG"
highlight-mystagogue-4 = Epistemics
highlight-mystagogue-5 = "Epi"
highlight-mystagogue-6 = Command
###### Security
highlight-detective-1 = Detective
highlight-detective-2 = "Det"
highlight-detective-3 = Security
highlight-detective-4 = "Sec"
highlight-security-cadet-1 = Security Cadet
highlight-security-cadet-2 = Cadet
highlight-security-cadet-3 = Security
highlight-security-cadet-4 = "Sec"
highlight-security-officer-1 = Security Officer
highlight-security-officer-2 = Secoff
highlight-security-officer-3 = Officer
highlight-security-officer-4 = Security
highlight-security-officer-5 = "Sec"
highlight-warden-1 = Warden
highlight-warden-2 = "Ward"
highlight-warden-3 = Security
highlight-warden-4 = "Sec"
highlight-warden-5 = Brig
highlight-prison-guard-1 = Prison Guard
highlight-prison-guard-2 = Prison
highlight-prison-guard-3 = Guard
highlight-prison-guard-4 = Security
highlight-prison-guard-5 = "Sec"
highlight-prison-guard-6 = Brig
highlight-corpsman-1 = Corpsman
highlight-corpsman-2 = "Corps"
highlight-corpsman-3 = Brigmed
highlight-corpsman-4 = "Sec"
highlight-corpsman-5 = Security
# Command
highlights-chief-justice = Chief Justice, "CJ", Justice, Command, Warrant, "Law"
highlights-mystagogue = Mystagogue, Mysta, "MG", Epistemics, "Epi", Command, Science
# Security
highlights-prison-guard = Prison Guard, Prison, Guard, Security, "Sec", Security
highlights-corpsman = Corpsman, "Corps", Brigmed, "Sec", Security, "Med", Medical
###### Station-specific
highlight-boxer-1 = Boxer
highlights-gladiator = Gladiator
highlights-martial-artist = Martial Artist, Martial
highlight-prisoner = Prisoner
highlight-gladiator-1 = Gladiator
# Epistemics
highlight-roboticist = Roboticist, Epistemics, "Epi"
highlight-psionic-mantis = "Mantis", Psionic Mantis, Epistemics, "Epi", "Psionic"
highlight-martial-artist-1 = Martial Artist
highlight-martial-artist-2 = Martial
# Justice
highlight-clerk = Clerk, "Justice", Warrant, "Law"
highlight-attorney = Lawyer, Attorney, Defense, Warrant, "Law", "Shitsec", Justice
highlight-prosecutor = Lawyer, Prosecutor, Prosecution, Warrant, "Law", Justice
highlight-prisoner-1 = Prisoner
# Logistics
highlights-cargo-assistant = Cargo Assistant, "Cargo", "Logi", Logistics
highlight-courier = Courier, Mailman, "Mail", Logistics, "Logi"
highlight-psychologist-1 = Psychologist
highlight-psychologist-2 = Psychology
highlight-psychologist-3 = Psychodoc
highlight-psychologist-4 = "Psych"
# Medical
highlight-surgeon = Surgeon, "Med", Medbay, Medical, "Doc"
highlight-reporter-1 = Reporter
highlight-reporter-2 = Journalist
# Civilian
highlight-visitor = Visitor
highlight-service-worker = Service Worker
highlight-passenger = Passenger, "Assistant", "tider"
highlight-zookeeper-1 = Zookeeper
highlight-zookeeper-2 = Zookeep
# Silicon
highlight-security-cyborg = Cyborg, Borg, Security, Secborg, Justice
highlight-medical-cyborg = Cyborg, Borg, Medical, Medborg, Justice
# Centcomm
highlight-centcomm-agent = Centcomm, Central Command, Death Squad, DeathSquad
highlight-centcomm-official = Centcomm, Central Command, "CC"
highlight-centcomm-quarantine-officer = Centcomm, Central Command, "CBURN"
###### Engineering
highlight-atmospheric-technician-1 = Atmospheric Technician
highlight-atmospheric-technician-2 = Atmos
highlight-atmospheric-technician-3 = Atmospheric
highlight-atmospheric-technician-4 = Atmosian
highlight-station-engineer-1 = Station Engineer
highlight-station-engineer-2 = Engineering
highlight-station-engineer-3 = Engineer
highlight-station-engineer-4 = "Engi"
highlight-technical-assistant-1 = Technical Assistant
highlight-technical-assistant-2 = Tech Assistant
highlight-technical-assistant-3 = Engineering
highlight-technical-assistant-4 = Engineer
highlight-technical-assistant-5 = "Engi"
###### Epistemics
highlight-scientist-1 = Scientist
highlight-scientist-2 = Epistemics
highlight-scientist-3 = "Epi"
highlight-roboticist-1 = Roboticist
highlight-roboticist-2 = Epistemics
highlight-roboticist-3 = "Epi"
highlight-research-assistant-1 = Research Assistant
highlight-research-assistant-2 = Epistemics
highlight-research-assistant-3 = "Epi"
highlight-psionic-mantis-1 = "Mantis"
highlight-psionic-mantis-2 = Psionic Mantis
###### Justice
highlight-clerk-1 = Clerk
highlight-attorney-1 = Lawyer
highlight-attorney-2 = Attorney
highlight-attorney-3 = Defense
highlight-prosecutor-1 = Lawyer
highlight-prosecutor-2 = Prosecutor
highlight-prosecutor-3 = Prosecution
highlight-prosecutor-4 = "Prosec"
###### Logistics
highlight-cargo-technician-1 = Cargo Technician
highlight-cargo-technician-2 = Cargo Tech
highlight-cargo-technician-3 = Cargo
highlight-cargo-technician-4 = "CT"
highlight-cargo-technician-5 = "Logi"
highlight-cargo-technician-6 = Logistics
highlight-cargo-assistant-1 = Cargo Assistant
highlight-cargo-assistant-2 = "CA"
highlight-cargo-assistant-3 = "Logi"
highlight-cargo-assistant-4 = Logistics
highlight-salvage-specialist-1 = Salvage Specialist
highlight-salvage-specialist-2 = Salvager
highlight-salvage-specialist-3 = Salvage
highlight-salvage-specialist-4 = "Salv"
highlight-salvage-specialist-5 = Miner
highlight-salvage-specialist-6 = "Logi"
highlight-salvage-specialist-7 = Logistics
highlight-courier-1 = Courier
highlight-courier-2 = Mailman
highlight-courier-3 = Logistics
highlight-courier-4 = "Logi"
###### Medical
highlight-chemist-1 = Chemist
highlight-chemist-2 = Chemistry
highlight-chemist-3 = MedBay
highlight-chemist-4 = "Chem"
highlight-chemist-5 = "Medical"
highlight-medical-doctor-1 = Medical Doctor
highlight-medical-doctor-2 = Doctor
highlight-medical-doctor-3 = "Doc"
highlight-medical-doctor-4 = MedBay
highlight-medical-doctor-5 = "Med"
highlight-medical-doctor-6 = "Medical"
highlight-medical-intern-1 = Medical Intern
highlight-medical-intern-2 = Intern
highlight-medical-intern-3 = MedBay
highlight-medical-intern-4 = "Med"
highlight-medical-intern-5 = "Medical"
highlight-paramedic-1 = Paramedic
highlight-paramedic-2 = "Para"
highlight-paramedic-3 = MedBay
highlight-paramedic-4 = "Med"
highlight-paramedic-5 = "Medical"
highlight-surgeon-1 = Surgeon
highlight-surgeon-2 = "Med"
highlight-surgeon-3 = MedBay
highlight-surgeon-4 = Medical
###### Civilian
highlight-bartender-1 = Bartender
highlight-bartender-2 = Barkeeper
highlight-bartender-3 = Barkeep
highlight-bartender-4 = "Bar"
highlight-bartender-5 = Tender
highlight-botanist-1 = Botanist
highlight-botanist-2 = Botany
highlight-botanist-3 = Hydroponics
highlight-chaplain-1 = Chaplain
highlight-chaplain-2 = "Chap"
highlight-chaplain-3 = Chapel
highlight-chef-1 = Chef
highlight-chef-2 = "Cook"
highlight-chef-3 = Kitchen
highlight-clown-1 = Clown
highlight-clown-2 = Jester
highlight-janitor-1 = Janitorial
highlight-janitor-2 = Janitor
highlight-janitor-3 = "Jani"
highlight-lawyer-1 = Lawyer
highlight-lawyer-2 = Attorney
highlight-librarian-1 = Librarian
highlight-librarian-2 = Library
highlight-mime-1 = Mime
highlight-musician-1 = Musician
highlight-musician-2 = Music
highlight-passenger-1 = Passenger
highlight-visitor-1 = Visitor
highlight-service-worker-1 = Service Worker
###### Silicon
highlight-personal-ai-1 = Personal AI
highlight-personal-ai-2 = "pAI"
highlight-cyborg-1 = Cyborg
highlight-cyborg-2 = Borgie
highlight-cyborg-3 = Borg
highlight-medical-cyborg-1 = Cyborg
highlight-medical-cyborg-2 = Borgie
highlight-medical-cyborg-3 = Borg
highlight-medical-cyborg-4 = Medical
highlight-medical-cyborg-5 = Medborg
highlight-medical-cyborg-6 = Medical Cyborg
highlight-security-cyborg-1 = Cyborg
highlight-security-cyborg-2 = Borgie
highlight-security-cyborg-3 = Borg
highlight-security-cyborg-4 = Security
highlight-security-cyborg-5 = Secborg
highlight-security-cyborg-6 = Security Cyborg
highlight-station-ai-1 = Station AI
highlight-station-ai-2 = "AI"
# ERT
highlight-ert-leader = "ERT", Leader, CentComm
highlight-ert-chaplain = Chaplain, "Chap", "ERT"
highlight-ert-engineer = Engineer, "Engi", "ERT"
highlight-ert-janitor = Janitorial, Janitor, "Jani", "ERT", "mess"
highlight-ert-medic = Doctor, "Doc", "Med", "Medic", Medical, "ERT"
highlight-ert-security-1 = Security, Officer, Secoff, "Sec", "ERT"

View File

@ -1,11 +1,3 @@
hud-chatbox-select-channels = Channels:
hud-chatbox-auto-highlights = Automatic Highlights:
hud-chatbox-highlights = Highlights:
hud-chatbox-highlights-button = Submit
hud-chatbox-highlights-tooltip = The words need to be separated by a newline,
if wrapped around " they will be highlighted
only if separated by spaces.
hud-chatbox-highlights-placeholder = Urist
"Para"
Bridge

View File

@ -11,10 +11,5 @@ ui-options-function-nano-chat-navigate-down = Navigate down
ui-options-function-nano-chat-navigate-up-unread = Navigate up to next unread
ui-options-function-nano-chat-navigate-down-unread = Navigate down to next unread
## DeltaV implementation of message highlights
ui-options-auto-fill-highlights = Auto-fill the highlights with the character's information
ui-options-highlights-color = Highlights color:
ui-options-highlights-color-example = This is an highlighted text.
## DeltaV Curator Chat
ui-options-function-open-c-help = Open curator help

View File

@ -0,0 +1,58 @@
# Command
highlights-captain = Captain, "Cap", Bridge, Command
highlights-head-of-personnel = Head Of Personnel, "HoP", Service, Bridge, Command
highlights-chief-engineer = Chief Engineer, "CE", Engineering, Engineer, "Engi", Bridge, Command
highlights-chief-medical-officer = Chief Medical Officer, "CMO", MedBay, "Med", Bridge, Command
highlights-head-of-security = Head of Security, "HoS", Security, "Sec", Bridge, Command
highlights-quartermaster = Quartermaster, "QM", Cargo, "Logi", Logistics, Bridge, Command
highlights-research-director = Research Director, "RD", Science, "Sci", Bridge, Command
# Security
highlights-detective = Detective, "Det", Security, "Sec"
highlights-security-cadet = Security Cadet, Secoff, Cadet, Security, "Sec"
highlights-security-officer = Security Officer, Secoff, Officer, Security, "Sec"
highlights-warden = Warden, "Ward", Security, "Sec"
# Cargo
highlights-cargo-technician = Cargo Technician, Cargo Tech, "Cargo", "Logi", Logistics
highlights-salvage-specialist = Salvage Specialist, Salvager, Salvage, "Salv", "Cargo", Miner, "Logi", Logistics
# Engineering
highlights-atmospheric-technician = Atmospheric Technician, Atmos tech, Atmospheric, Engineering, "Atmos", "Engi"
highlights-station-engineer = Station Engineer, Engineering, Engineer, "Engi"
highlights-technical-assistant = Technical Assistant, Tech Assistant, Engineering, Engineer, "Engi"
# Medical
highlights-chemist = Chemist, Chemistry, "Chem", MedBay, "Med"
highlights-medical-doctor = Medical Doctor, Doctor, "Doc", MedBay, "Med"
highlights-medical-intern = Medical Intern, "Doc", Intern, MedBay, "Med"
highlights-paramedic = Paramedic, "Para", MedBay, "Med"
# Science
highlights-scientist = Scientist, Science, "Sci", Epistemics, "Epi"
highlights-research-assistant = Research Assistant, Science, "Sci", Epistemics, "Epi"
# Civilian
highlights-bartender = Bartender, Barkeeper, Barkeep, "Bar"
highlights-botanist = Botanist, Botany, Hydroponics
highlights-chaplain = Chaplain, "Chap", Chapel, Science, "Sci", Epistemics, "Epi"
highlights-chef = Chef, "Cook", Kitchen
highlights-clown = Clown, Jester
highlights-janitor = Janitor, "Jani"
highlights-lawyer = Lawyer, Attorney
highlights-librarian = Librarian, Library
highlights-mime = Mime
highlights-passenger = Passenger, Greytider, "Tider"
highlights-service-worker = Service Worker
# Station-specific
highlights-boxer = Boxer
highlights-reporter = Reporter, Journalist
highlights-zookeeper = Zookeeper
highlights-psychologist = Psychologist, Psychology, "Psych"
# Silicon
highlights-personal-ai = Personal AI, "pAI"
highlights-cyborg = Cyborg, Silicon, Borg
highlights-station-ai = Station AI, Silicon, "AI", "sAI"

View File

@ -31,3 +31,12 @@ hud-chatbox-channel-Server = Server
hud-chatbox-channel-Visual = Actions
hud-chatbox-channel-Damage = Damage
hud-chatbox-channel-Unspecified = Unspecified
hud-chatbox-highlights = Highlights:
hud-chatbox-highlights-button = Submit
hud-chatbox-highlights-tooltip = The words need to be separated by a newline,
if wrapped around " they will be highlighted
only if separated by spaces or punctuation.
hud-chatbox-highlights-placeholder = McHands
"Judge"
Medical

View File

@ -49,6 +49,9 @@ ui-options-misc-label = Misc
ui-options-interface-label = Interface
ui-options-auto-fill-highlights = Auto-fill the highlights with the character's information
ui-options-highlights-color = Highlighs color:
ui-options-highlights-color-example = This is an highlighted text!
ui-options-show-held-item = Show held item next to cursor
ui-options-show-combat-mode-indicators = Show combat mode indicators with cursor
ui-options-opaque-storage-window = Opaque storage window

View File

@ -1,329 +0,0 @@
# The IDs are generated from job names
# the Prefixes are generated job IDs
# The corresponding strings are located in Resources/Locale/en-US/_DV/chat/highlights.ftl
- type: localizedDataset
id: ChatHighlightAtmosphericTechnician
values:
prefix: highlight-atmospheric-technician-
count: 4
- type: localizedDataset
id: ChatHighlightBartender
values:
prefix: highlight-bartender-
count: 5
- type: localizedDataset
id: ChatHighlightBorg
values:
prefix: highlight-cyborg-
count: 3
- type: localizedDataset
id: ChatHighlightBotanist
values:
prefix: highlight-botanist-
count: 3
- type: localizedDataset
id: ChatHighlightBoxer
values:
prefix: highlight-boxer-
count: 1
- type: localizedDataset
id: ChatHighlightBrigmedic
values:
prefix: highlight-corpsman-
count: 5
- type: localizedDataset
id: ChatHighlightCaptain
values:
prefix: highlight-captain-
count: 3
- type: localizedDataset
id: ChatHighlightCargoAssistant
values:
prefix: highlight-cargo-assistant-
count: 4
- type: localizedDataset
id: ChatHighlightCargoTechnician
values:
prefix: highlight-cargo-technician-
count: 6
- type: localizedDataset
id: ChatHighlightCBURN
values:
prefix: highlight-centcomm-quarantine-officer-
count: 3
- type: localizedDataset
id: ChatHighlightCentralCommandOfficial
values:
prefix: highlight-centcomm-official-
count: 2
- type: localizedDataset
id: ChatHighlightChaplain
values:
prefix: highlight-chaplain-
count: 3
- type: localizedDataset
id: ChatHighlightChef
values:
prefix: highlight-chef-
count: 3
- type: localizedDataset
id: ChatHighlightChemist
values:
prefix: highlight-chemist-
count: 5
- type: localizedDataset
id: ChatHighlightChiefEngineer
values:
prefix: highlight-chief-engineer-
count: 6
- type: localizedDataset
id: ChatHighlightChiefJustice
values:
prefix: highlight-chief-justice-
count: 4
- type: localizedDataset
id: ChatHighlightChiefMedicalOfficer
values:
prefix: highlight-chief-medical-officer-
count: 5
- type: localizedDataset
id: ChatHighlightClerk
values:
prefix: highlight-clerk-
count: 1
- type: localizedDataset
id: ChatHighlightClown
values:
prefix: highlight-clown-
count: 2
- type: localizedDataset
id: ChatHighlightCourier
values:
prefix: highlight-courier-
count: 4
- type: localizedDataset
id: ChatHighlightDeathSquad
values:
prefix: highlight-centcomm-agent-
count: 4
- type: localizedDataset
id: ChatHighlightDetective
values:
prefix: highlight-detective-
count: 4
- type: localizedDataset
id: ChatHighlightERTChaplain
values:
prefix: highlight-ert-chaplain-
count: 4
- type: localizedDataset
id: ChatHighlightERTEngineer
values:
prefix: highlight-ert-engineer-
count: 5
- type: localizedDataset
id: ChatHighlightERTJanitor
values:
prefix: highlight-ert-janitor-
count: 4
- type: localizedDataset
id: ChatHighlightERTLeader
values:
prefix: highlight-ert-leader-
count: 3
- type: localizedDataset
id: ChatHighlightERTMedical
values:
prefix: highlight-ert-medic-
count: 7
- type: localizedDataset
id: ChatHighlightERTSecurity
values:
prefix: highlight-ert-security-
count: 6
- type: localizedDataset
id: ChatHighlightForensicMantis
values:
prefix: highlight-psionic-mantis-
count: 2
- type: localizedDataset
id: ChatHighlightGladiator
values:
prefix: highlight-gladiator-
count: 1
- type: localizedDataset
id: ChatHighlightHeadOfPersonnel
values:
prefix: highlight-head-of-personnel-
count: 4
- type: localizedDataset
id: ChatHighlightHeadOfSecurity
values:
prefix: highlight-head-of-security-
count: 5
- type: localizedDataset
id: ChatHighlightJanitor
values:
prefix: highlight-janitor-
count: 3
- type: localizedDataset
id: ChatHighlightLawyer
values:
prefix: highlight-attorney-
count: 3
- type: localizedDataset
id: ChatHighlightLibrarian
values:
prefix: highlight-librarian-
count: 2
- type: localizedDataset
id: ChatHighlightMartialArtist
values:
prefix: highlight-martial-artist-
count: 2
- type: localizedDataset
id: ChatHighlightMedicalBorg
values:
prefix: highlight-medical-cyborg-
count: 6
- type: localizedDataset
id: ChatHighlightMedicalDoctor
values:
prefix: highlight-medical-doctor-
count: 6
- type: localizedDataset
id: ChatHighlightMedicalIntern
values:
prefix: highlight-medical-intern-
count: 5
- type: localizedDataset
id: ChatHighlightMime
values:
prefix: highlight-mime-
count: 1
- type: localizedDataset
id: ChatHighlightMusician
values:
prefix: highlight-musician-
count: 2
- type: localizedDataset
id: ChatHighlightParamedic
values:
prefix: highlight-paramedic-
count: 5
- type: localizedDataset
id: ChatHighlightPassenger
values:
prefix: highlight-passenger-
count: 1
- type: localizedDataset
id: ChatHighlightPrisoner
values:
prefix: highlight-prisoner-
count: 1
- type: localizedDataset
id: ChatHighlightPrisonGuard
values:
prefix: highlight-prison-guard-
count: 6
- type: localizedDataset
id: ChatHighlightProsecutor
values:
prefix: highlight-prosecutor-
count: 4
- type: localizedDataset
id: ChatHighlightPsychologist
values:
prefix: highlight-psychologist-
count: 4
- type: localizedDataset
id: ChatHighlightQuartermaster
values:
prefix: highlight-logistics-officer-
count: 5
- type: localizedDataset
id: ChatHighlightReporter
values:
prefix: highlight-reporter-
count: 2
- type: localizedDataset
id: ChatHighlightResearchAssistant
values:
prefix: highlight-research-assistant-
count: 3
- type: localizedDataset
id: ChatHighlightResearchDirector
values:
prefix: highlight-mystagogue-
count: 6
- type: localizedDataset
id: ChatHighlightRoboticist
values:
prefix: highlight-roboticist-
count: 3
- type: localizedDataset
id: ChatHighlightSalvageSpecialist
values:
prefix: highlight-salvage-specialist-
count: 7
- type: localizedDataset
id: ChatHighlightScientist
values:
prefix: highlight-scientist-
count: 3
- type: localizedDataset
id: ChatHighlightSecurityBorg
values:
prefix: highlight-security-cyborg-
count: 6
- type: localizedDataset
id: ChatHighlightSecurityCadet
values:
prefix: highlight-security-cadet-
count: 4
- type: localizedDataset
id: ChatHighlightSecurityOfficer
values:
prefix: highlight-security-officer-
count: 5
- type: localizedDataset
id: ChatHighlightServiceWorker
values:
prefix: highlight-service-worker-
count: 1
- type: localizedDataset
id: ChatHighlightStationAi
values:
prefix: highlight-station-ai-
count: 2
- type: localizedDataset
id: ChatHighlightStationEngineer
values:
prefix: highlight-station-engineer-
count: 4
- type: localizedDataset
id: ChatHighlightSurgeon
values:
prefix: highlight-surgeon-
count: 4
- type: localizedDataset
id: ChatHighlightTechnicalAssistant
values:
prefix: highlight-technical-assistant-
count: 5
- type: localizedDataset
id: ChatHighlightVisitor
values:
prefix: highlight-visitor-
count: 1
- type: localizedDataset
id: ChatHighlightWarden
values:
prefix: highlight-warden-
count: 5
- type: localizedDataset
id: ChatHighlightZookeeper
values:
prefix: highlight-zookeeper-
count: 2