diff --git a/Content.Client/Options/UI/OptionsTabControlRow.xaml.cs b/Content.Client/Options/UI/OptionsTabControlRow.xaml.cs
index 31dd9897f4e..00b191cc60c 100644
--- a/Content.Client/Options/UI/OptionsTabControlRow.xaml.cs
+++ b/Content.Client/Options/UI/OptionsTabControlRow.xaml.cs
@@ -1,4 +1,5 @@
using System.Linq;
+using Content.Client._CorvaxNext.Options.UI;
using Content.Client.Stylesheets;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
@@ -120,6 +121,21 @@ public OptionSliderFloatCVar AddOptionPercentSlider(
{
return AddOption(new OptionSliderFloatCVar(this, _cfg, cVar, slider, min, max, scale, FormatPercent));
}
+
+ // Corvax-Highlights-Start
+ ///
+ /// Add a color slider option, backed by a simple string CVar.
+ ///
+ /// The CVar represented by the slider.
+ /// The UI control for the option.
+ /// The option instance backing the added option.
+ public OptionColorSliderCVar AddOptionColorSlider(
+ CVarDef cVar,
+ OptionColorSlider slider)
+ {
+ return AddOption(new OptionColorSliderCVar(this, _cfg, cVar, slider));
+ }
+ // Corvax-Highlights-End
///
/// Add a slider option, backed by a simple integer CVar.
@@ -518,6 +534,60 @@ private void UpdateLabelValue()
}
}
+///
+/// Implementation of a CVar option that simply corresponds with a string .
+///
+///
+public sealed class OptionColorSliderCVar : BaseOptionCVar
+{
+ private readonly OptionColorSlider _slider;
+
+ protected override string Value
+ {
+ get => _slider.Slider.Color.ToHex();
+ set
+ {
+ _slider.Slider.Color = Color.FromHex(value);
+ UpdateLabelColor();
+ }
+ }
+
+ // Corvax-Highlights-Start
+ ///
+ /// Creates a new instance of this type.
+ ///
+ ///
+ ///
+ /// It is generally more convenient to call overloads on
+ /// such as instead of instantiating this type directly.
+ ///
+ ///
+ /// The control row that owns this option.
+ /// The configuration manager to get and set values from.
+ /// The CVar that is being controlled by this option.
+ /// The UI control for the option.
+ public OptionColorSliderCVar(
+ OptionsTabControlRow controller,
+ IConfigurationManager cfg,
+ CVarDef cVar,
+ OptionColorSlider slider) : base(controller, cfg, cVar)
+ {
+ _slider = slider;
+
+ slider.Slider.OnColorChanged += _ =>
+ {
+ ValueChanged();
+ UpdateLabelColor();
+ };
+ }
+ // Corvax-Highlights-End
+
+ private void UpdateLabelColor()
+ {
+ _slider.ExampleLabel.FontColorOverride = Color.FromHex(Value);
+ }
+}
+
///
/// Implementation of a CVar option that simply corresponds with an integer .
///
diff --git a/Content.Client/Options/UI/Tabs/AccessibilityTab.xaml b/Content.Client/Options/UI/Tabs/AccessibilityTab.xaml
index 54d92b2b11c..9edb23d0a80 100644
--- a/Content.Client/Options/UI/Tabs/AccessibilityTab.xaml
+++ b/Content.Client/Options/UI/Tabs/AccessibilityTab.xaml
@@ -1,6 +1,7 @@
+ xmlns:ui="clr-namespace:Content.Client.Options.UI"
+ xmlns:cnui="clr-namespace:Content.Client._CorvaxNext.Options.UI">
@@ -9,6 +10,12 @@
+
+
+
+
diff --git a/Content.Client/Options/UI/Tabs/AccessibilityTab.xaml.cs b/Content.Client/Options/UI/Tabs/AccessibilityTab.xaml.cs
index 15182fbf126..5ab3d38b77e 100644
--- a/Content.Client/Options/UI/Tabs/AccessibilityTab.xaml.cs
+++ b/Content.Client/Options/UI/Tabs/AccessibilityTab.xaml.cs
@@ -2,6 +2,9 @@
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.XAML;
+// Corvax-Highlights-Start
+using Content.Shared.Corvax.CCCVars;
+// Corvax-Highlights-End
namespace Content.Client.Options.UI.Tabs;
@@ -17,6 +20,10 @@ public AccessibilityTab()
Control.AddOptionCheckBox(CCVars.ReducedMotion, ReducedMotionCheckBox);
Control.AddOptionPercentSlider(CCVars.ChatWindowOpacity, ChatWindowOpacitySlider);
Control.AddOptionPercentSlider(CCVars.ScreenShakeIntensity, ScreenShakeIntensitySlider);
+ // Corvax-Highlights-Start
+ Control.AddOptionCheckBox(CCCVars.ChatAutoFillHighlights, AutoFillHighlightsCheckBox);
+ Control.AddOptionColorSlider(CCCVars.ChatHighlightsColor, HighlightsColorSlider);
+ // Corvax-Highlights-End
Control.Initialize();
}
diff --git a/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs b/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs
index 005a9d1a2ec..6af9a77e148 100644
--- a/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs
+++ b/Content.Client/UserInterface/Systems/Chat/ChatUIController.cs
@@ -41,9 +41,16 @@
using Robust.Shared.Timing;
using Robust.Shared.Utility;
+// Corvax-Highlights-Start
+using Content.Client.CharacterInfo;
+using static Content.Client.CharacterInfo.CharacterInfoSystem;
+using Content.Shared.Corvax.CCCVars;
+// Corvax-Highlights-End
+
namespace Content.Client.UserInterface.Systems.Chat;
-public sealed class ChatUIController : UIController
+// Corvax-Highlights
+public sealed class ChatUIController : UIController, IOnSystemChanged
{
[Dependency] private readonly IClientAdminManager _admin = default!;
[Dependency] private readonly IChatManager _manager = default!;
@@ -65,6 +72,9 @@ public sealed class ChatUIController : UIController
[UISystemDependency] private readonly TransformSystem? _transform = default;
[UISystemDependency] private readonly MindSystem? _mindSystem = default!;
[UISystemDependency] private readonly RoleCodewordSystem? _roleCodewordSystem = default!;
+ // Corvax-Highlights-Start
+ [UISystemDependency] private readonly CharacterInfoSystem _characterInfo = default!;
+ // Corvax-Highlights-End
[ValidatePrototypeId]
private const string ChatNamePalette = "ChatNames";
@@ -149,6 +159,25 @@ private readonly Dictionary _queuedSpeechBubbl
///
private readonly Dictionary _unreadMessages = new();
+ // Corvax-Highlights-Start
+ ///
+ /// A list of words to be highlighted in the chatbox.
+ ///
+ private List _highlights = [];
+
+ ///
+ /// The color (hex) in witch the words will be highlighted as.
+ ///
+ private string? _highlightsColor;
+
+ private bool _autoFillHighlightsEnabled;
+
+ ///
+ /// A bool to keep track if the 'CharacterUpdated' event is a new player attaching or the opening of the character info panel.
+ ///
+ private bool _charInfoIsAttach = false;
+ // Corvax-Highlights-End
+
// TODO add a cap for this for non-replays
public readonly List<(GameTick Tick, ChatMessage Msg)> History = new();
@@ -172,6 +201,9 @@ private readonly Dictionary _queuedSpeechBubbl
public event Action? SelectableChannelsChanged;
public event Action? UnreadMessageCountsUpdated;
public event Action? MessageAdded;
+ // Corvax-Highlights-Start
+ public event Action? HighlightsUpdated;
+ // Corvax-Highlights-End
public override void Initialize()
{
@@ -240,6 +272,21 @@ public override void Initialize()
_config.OnValueChanged(CCVars.ChatWindowOpacity, OnChatWindowOpacityChanged);
+ // Corvax-Highlights-Start
+ _config.OnValueChanged(CCCVars.ChatAutoFillHighlights, (value) => { _autoFillHighlightsEnabled = value; });
+ _autoFillHighlightsEnabled = _config.GetCVar(CCCVars.ChatAutoFillHighlights);
+
+ _config.OnValueChanged(CCCVars.ChatHighlightsColor, (value) => { _highlightsColor = value; });
+ _highlightsColor = _config.GetCVar(CCCVars.ChatHighlightsColor);
+
+ // Load highlights if any were saved.
+ string highlights = _config.GetCVar(CCCVars.ChatHighlights);
+
+ if (!string.IsNullOrEmpty(highlights))
+ {
+ UpdateHighlights(highlights);
+ }
+ // Corvax-Highlights-End
}
public void OnScreenLoad()
@@ -257,6 +304,69 @@ public void OnScreenUnload()
SetMainChat(false);
}
+ // Corvax-Highlights-Start
+ public void OnSystemLoaded(CharacterInfoSystem system)
+ {
+ system.OnCharacterUpdate += CharacterUpdated;
+ }
+
+ public void OnSystemUnloaded(CharacterInfoSystem system)
+ {
+ system.OnCharacterUpdate -= CharacterUpdated;
+ }
+
+ private void CharacterUpdated(CharacterData data)
+ {
+ // If the _charInfoIsAttach is false then the character panel created the event, dismiss.
+ if (!_charInfoIsAttach)
+ return;
+
+ var (_, job, _, _, entityName) = data;
+
+ // 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)
+ entityName = entityName.Replace(' ', '\n');
+
+ string newHighlights = entityName;
+
+ // 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;
+ }
+
+ public void UpdateHighlights(string highlights)
+ {
+ // Save the newly provided list of highlighs if different.
+ if (!_config.GetCVar(CCCVars.ChatHighlights).Equals(highlights, StringComparison.CurrentCultureIgnoreCase))
+ {
+ _config.SetCVar(CCCVars.ChatHighlights, highlights);
+ _config.SaveToFile();
+ }
+
+ // If the word is surrounded by "" we replace them with a whole-word regex tag.
+ highlights = highlights.Replace("\"", "\\b");
+
+ // Fill the array with the highlights separated by newlines, disregarding empty entries.
+ string[] arrHighlights = highlights.Split('\n', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
+ _highlights.Clear();
+ foreach (var keyword in arrHighlights)
+ {
+ _highlights.Add(keyword);
+ }
+
+ // 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));
+ }
+ // Corvax-Highlights-End
+
private void OnChatWindowOpacityChanged(float opacity)
{
SetChatWindowOpacity(opacity);
@@ -426,6 +536,14 @@ public void SetSpeechBubbleRoot(LayoutContainer root)
private void OnAttachedChanged(EntityUid uid)
{
UpdateChannelPermissions();
+
+ // Corvax-Highlights-Start
+ if (_autoFillHighlightsEnabled)
+ {
+ _charInfoIsAttach = true;
+ _characterInfo.RequestCharacterInfo();
+ }
+ // Corvax-Highlights-End
}
private void AddSpeechBubble(ChatMessage msg, SpeechBubble.SpeechType speechType)
@@ -824,6 +942,14 @@ public void ProcessChatMessage(ChatMessage msg, bool speechBubble = true)
msg.WrappedMessage = SharedChatSystem.InjectTagInsideTag(msg, "Name", "color", GetNameColor(SharedChatSystem.GetStringInsideTag(msg, "Name")));
}
+ // Corvax-Highlights-Start
+ // Color any words choosen by the client.
+ foreach (var highlight in _highlights)
+ {
+ msg.WrappedMessage = SharedChatSystem.InjectTagAroundString(msg, highlight, "color", _highlightsColor);
+ }
+ // Corvax-Highlights-End
+
// Color any codewords for minds that have roles that use them
if (_player.LocalUser != null && _mindSystem != null && _roleCodewordSystem != null)
{
diff --git a/Content.Client/UserInterface/Systems/Chat/Controls/ChannelFilterPopup.xaml b/Content.Client/UserInterface/Systems/Chat/Controls/ChannelFilterPopup.xaml
index 459c44eee26..69cfc4218b7 100644
--- a/Content.Client/UserInterface/Systems/Chat/Controls/ChannelFilterPopup.xaml
+++ b/Content.Client/UserInterface/Systems/Chat/Controls/ChannelFilterPopup.xaml
@@ -1,10 +1,23 @@
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Content.Client/UserInterface/Systems/Chat/Controls/ChannelFilterPopup.xaml.cs b/Content.Client/UserInterface/Systems/Chat/Controls/ChannelFilterPopup.xaml.cs
index df4f56cb27c..baca946fcee 100644
--- a/Content.Client/UserInterface/Systems/Chat/Controls/ChannelFilterPopup.xaml.cs
+++ b/Content.Client/UserInterface/Systems/Chat/Controls/ChannelFilterPopup.xaml.cs
@@ -1,9 +1,15 @@
-using Content.Shared.Chat;
+using Content.Shared.Chat;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using static Robust.Client.UserInterface.Controls.BaseButton;
-
+// Corvax-Highlights-Start
+using Content.Shared.CCVar;
+using Robust.Shared.Utility;
+using Robust.Shared.Configuration;
+using static Robust.Client.UserInterface.Controls.TextEdit;
+using Content.Shared.Corvax.CCCVars;
+// Corvax-Highlights-End
namespace Content.Client.UserInterface.Systems.Chat.Controls;
[GenerateTypedNameReferences]
@@ -29,10 +35,28 @@ public sealed partial class ChannelFilterPopup : Popup
private readonly Dictionary _filterStates = new();
public event Action? OnChannelFilter;
+ // Corvax-Highlights-Start
+ public event Action? OnNewHighlights;
+ // Corvax-Highlights-End
public ChannelFilterPopup()
{
RobustXamlLoader.Load(this);
+
+ // Corvax-Highlights-Start
+ HighlightButton.OnPressed += HighlightsEntered;
+
+ HighlightEdit.Placeholder = new Rope.Leaf(Loc.GetString("hud-chatbox-highlights-placeholder"));
+
+ // Load highlights if any were saved.
+ var cfg = IoCManager.Resolve();
+ string highlights = cfg.GetCVar(CCCVars.ChatHighlights);
+
+ if (!string.IsNullOrEmpty(highlights))
+ {
+ SetHighlights(highlights);
+ }
+ // Corvax-Highlights-End
}
public bool IsActive(ChatChannel channel)
@@ -83,6 +107,18 @@ public void SetChannels(ChatChannel channels)
}
}
+ // Corvax-Highlights-Start
+ public void SetHighlights(string highlights)
+ {
+ HighlightEdit.TextRope = new Rope.Leaf(highlights);
+ }
+
+ private void HighlightsEntered(ButtonEventArgs _args)
+ {
+ OnNewHighlights?.Invoke(Rope.Collapse(HighlightEdit.TextRope));
+ }
+ // Corvax-Highlights-End
+
private void CheckboxPressed(ButtonEventArgs args)
{
var checkbox = (ChannelFilterCheckbox) args.Button;
diff --git a/Content.Client/UserInterface/Systems/Chat/Widgets/ChatBox.xaml.cs b/Content.Client/UserInterface/Systems/Chat/Widgets/ChatBox.xaml.cs
index d32922a00ac..26f6950f2ca 100644
--- a/Content.Client/UserInterface/Systems/Chat/Widgets/ChatBox.xaml.cs
+++ b/Content.Client/UserInterface/Systems/Chat/Widgets/ChatBox.xaml.cs
@@ -13,6 +13,12 @@
using Robust.Shared.Utility;
using static Robust.Client.UserInterface.Controls.LineEdit;
+// Corvax-Highlights-Start
+using Content.Shared.CCVar;
+using Robust.Shared.Configuration;
+using Content.Shared.Corvax.CCCVars;
+// Corvax-Highlights-End
+
namespace Content.Client.UserInterface.Systems.Chat.Widgets;
[GenerateTypedNameReferences]
@@ -23,6 +29,11 @@ public partial class ChatBox : UIWidget
private readonly ChatUIController _controller;
private readonly IEntityManager _entManager;
+ // Corvax-Highlights-Start
+ private static readonly Color HighlightColor = Color.FromHex("#e5ffcc");
+ private List _highlights = [];
+ // Corvax-Highlights-End
+
public bool Main { get; set; }
public ChatSelectChannel SelectedChannel => ChatInput.ChannelSelector.SelectedChannel;
@@ -39,9 +50,14 @@ public ChatBox()
ChatInput.Input.OnFocusExit += OnFocusExit; // Corvax-TypingIndicator
ChatInput.ChannelSelector.OnChannelSelect += OnChannelSelect;
ChatInput.FilterButton.Popup.OnChannelFilter += OnChannelFilter;
-
+ // Corvax-Highlights-Start
+ ChatInput.FilterButton.Popup.OnNewHighlights += OnNewHighlights;
+ // Corvax-Highlights-End
_controller = UserInterfaceManager.GetUIController();
_controller.MessageAdded += OnMessageAdded;
+ // Corvax-Highlights-Start
+ _controller.HighlightsUpdated += OnHighlightsReceived;
+ // Corvax-Highlights-End
_controller.RegisterChat(this);
}
@@ -65,6 +81,14 @@ private void OnMessageAdded(ChatMessage msg)
var color = msg.MessageColorOverride ?? msg.Channel.TextColor();
+ // Corvax-Highlights-Start
+ // Highlight any words choosen by the client.
+ foreach (var highlight in _highlights)
+ {
+ msg.WrappedMessage = SharedChatSystem.InjectTagAroundString(msg, highlight, "color", HighlightColor.ToHex());
+ }
+ // Corvax-Highlights-End
+
AddLine(msg.WrappedMessage, color);
}
@@ -98,6 +122,32 @@ private void OnChannelFilter(ChatChannel channel, bool active)
}
}
+ // Corvax-Highlights-Start
+ private void OnNewHighlights(string highlighs)
+ {
+ _controller.UpdateHighlights(highlighs);
+ }
+
+ private void OnHighlightsReceived(string highlights)
+ {
+ // Save the newly provided list of highlighs if different.
+ var cfg = IoCManager.Resolve();
+ if (!cfg.GetCVar(CCCVars.ChatHighlights).Equals(highlights, StringComparison.CurrentCultureIgnoreCase))
+ {
+ cfg.SetCVar(CCCVars.ChatHighlights, highlights);
+ cfg.SaveToFile();
+ }
+
+ // Fill the array with the highlights separated by commas, disregarding empty entries.
+ string[] arr_highlights = highlights.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
+ _highlights.Clear();
+ foreach (var keyword in arr_highlights)
+ {
+ _highlights.Add(keyword);
+ }
+ }
+ // Corvax-Highlights-Start
+
public void AddLine(string message, Color color)
{
var formatted = new FormattedMessage(3);
diff --git a/Content.Client/_CorvaxNext/Options/UI/OptionColorSlider.xaml b/Content.Client/_CorvaxNext/Options/UI/OptionColorSlider.xaml
new file mode 100644
index 00000000000..4f5f0823506
--- /dev/null
+++ b/Content.Client/_CorvaxNext/Options/UI/OptionColorSlider.xaml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/Content.Client/_CorvaxNext/Options/UI/OptionColorSlider.xaml.cs b/Content.Client/_CorvaxNext/Options/UI/OptionColorSlider.xaml.cs
new file mode 100644
index 00000000000..86356565377
--- /dev/null
+++ b/Content.Client/_CorvaxNext/Options/UI/OptionColorSlider.xaml.cs
@@ -0,0 +1,30 @@
+using Robust.Client.AutoGenerated;
+using Robust.Client.UserInterface;
+
+namespace Content.Client._CorvaxNext.Options.UI;
+
+///
+/// Standard UI control used for color sliders in the options menu. Intended for use with .
+///
+///
+[GenerateTypedNameReferences]
+public sealed partial class OptionColorSlider : Control
+{
+ ///
+ /// The text describing what this slider affects.
+ ///
+ public string? Title
+ {
+ get => TitleLabel.Text;
+ set => TitleLabel.Text = value;
+ }
+
+ ///
+ /// The example text showing the current color of the slider.
+ ///
+ public string? Example
+ {
+ get => ExampleLabel.Text;
+ set => ExampleLabel.Text = value;
+ }
+}
diff --git a/Content.Shared/Corvax/CCCVars/CCCVars.cs b/Content.Shared/Corvax/CCCVars/CCCVars.cs
index f9f281d55bd..6a9ab3b0840 100644
--- a/Content.Shared/Corvax/CCCVars/CCCVars.cs
+++ b/Content.Shared/Corvax/CCCVars/CCCVars.cs
@@ -1,4 +1,4 @@
-using Robust.Shared.Configuration;
+using Robust.Shared.Configuration;
namespace Content.Shared.Corvax.CCCVars;
@@ -78,6 +78,27 @@ public sealed class CCCVars
public static readonly CVarDef PeacefulRoundEnd =
CVarDef.Create("game.peaceful_end", true, CVar.SERVERONLY);
+ /*
+ * CHAT
+ */
+
+ ///
+ /// A string containing a list of newline-separated words to be highlighted in the chat.
+ ///
+ public static readonly CVarDef ChatHighlights =
+ CVarDef.Create("chat.highlights", "", CVar.CLIENTONLY | CVar.ARCHIVE, "A list of newline-separated words to be highlighted in the chat.");
+
+ ///
+ /// An option to toggle the automatic filling of the highlights with the character's info, if available.
+ ///
+ public static readonly CVarDef ChatAutoFillHighlights =
+ CVarDef.Create("chat.auto_fill_highlights", false, CVar.CLIENTONLY | CVar.ARCHIVE, "Toggles automatically filling the highlights with the character's information.");
+
+ ///
+ /// The color in which the highlights will be displayed.
+ ///
+ public static readonly CVarDef ChatHighlightsColor =
+ CVarDef.Create("chat.highlights_color", "#17FFC1FF", CVar.CLIENTONLY | CVar.ARCHIVE, "The color in which the highlights will be displayed.");
/*
* Station Goal
*/
diff --git a/Resources/Locale/en-US/_CorvaxNext/chat/highlights.ftl b/Resources/Locale/en-US/_CorvaxNext/chat/highlights.ftl
new file mode 100644
index 00000000000..f3fddfe7288
--- /dev/null
+++ b/Resources/Locale/en-US/_CorvaxNext/chat/highlights.ftl
@@ -0,0 +1,57 @@
+# Command
+highlights-captain = Captain, "Cap", Command
+highlights-head-of-personnel = Head Of Personnel, "HoP", Service, Command
+highlights-chief-engineer = Chief Engineer, "CE", Engineering, Engineer, "Engi", Command
+highlights-chief-medical-officer = Chief Medical Officer, "CMO", MedBay, "Med", Command
+highlights-head-of-security = Head of Security, "HoS", Security, "Sec", Command
+highlights-quartermaster = Quartermaster, "QM", Cargo, Command
+highlights-research-director = Research Director, "RD", Science, "Sci", Command
+
+# Security
+highlights-detective = Detective, "Det", Security, "Sec"
+highlights-security-cadet = Security Cadet, 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
+highlights-salvage-specialist = Salvage Specialist, Salvager, Salvage, "Salv", Miner
+
+# Engineering
+highlights-atmospheric-technician = Atmospheric Technician, Atmos tech, Atmospheric, Atmos
+highlights-station-engineer = Station Engineer, Engineering, Engineer, "Engi"
+highlights-technical-assistant = Technical Assistant, Tech Assistant, Engineering, Engineer, "Engi"
+
+# Medical
+highlights-chemist = Chemist, Chemistry, MedBay
+highlights-medical-doctor = Medical Doctor, Doctor, "Doc", MedBay, "Med"
+highlights-medical-intern = Medical Intern, Intern, MedBay, "Med"
+highlights-paramedic = Paramedic, "Para", MedBay, "Med"
+
+# Science
+highlights-scientist = Scientist, Science, "Sci"
+highlights-research-assistant = Research Assistant, Science, "Sci"
+
+# Civilian
+highlights-bartender = Bartender, Barkeeper, Barkeep, "Bar"
+highlights-botanist = Botanist, Botany, Hydroponics
+highlights-chaplain = Chaplain, "Chap", Chapel
+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
+highlights-service-worker = Service Worker
+
+# Station-specific
+highlights-boxer = Boxer
+highlights-reporter = Reporter, Journalist
+highlights-zookeeper = Zookeeper
+highlights-psychologist = Psychologist, Psychology
+
+# Silicon
+highlights-personal-ai = Personal AI, "pAI"
+highlights-cyborg = Cyborg, Borg
+highlights-station-ai = Station AI, "AI"
\ No newline at end of file
diff --git a/Resources/Locale/en-US/chat/ui/chat-box.ftl b/Resources/Locale/en-US/chat/ui/chat-box.ftl
index 720f0d15ab4..fa710bb58c2 100644
--- a/Resources/Locale/en-US/chat/ui/chat-box.ftl
+++ b/Resources/Locale/en-US/chat/ui/chat-box.ftl
@@ -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.
+hud-chatbox-highlights-placeholder = Urist
+ "Para"
+ Bridge
\ No newline at end of file
diff --git a/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl b/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl
index bcc5a994b8b..c5ac721e589 100644
--- a/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl
+++ b/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl
@@ -47,6 +47,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
diff --git a/Resources/Locale/ru-RU/_CorvaxNext/chat/highlights.ftl b/Resources/Locale/ru-RU/_CorvaxNext/chat/highlights.ftl
new file mode 100644
index 00000000000..61119deccb8
--- /dev/null
+++ b/Resources/Locale/ru-RU/_CorvaxNext/chat/highlights.ftl
@@ -0,0 +1,57 @@
+# Командование
+highlights-captain = Капитан, "Кэп", Командование
+highlights-head-of-personnel = Глава персонала, "ГП", Сервис, Командование
+highlights-chief-engineer = Старший инженер, "СИ", Инженер, "Инж", Командование
+highlights-chief-medical-officer = Главный врач, "ГВ", Медицинский, "Мед", Командование
+highlights-head-of-security = Глава Службы Безопасности, "ГСБ", Безопасности, "СБ", Командование
+highlights-quartermaster = Квартирмейстер, "КМ", Карго, Командование
+highlights-research-director = Научный Руководитель, "НР", Наука, Учёный, "НИО", Командование
+
+# Безопасность
+highlights-detective = Детектив, "Дек", Безопасности, "СБ"
+highlights-security-cadet = Кадет Службы Безопасности, Кадет, "СБ"
+highlights-security-officer = Офицер Службы Безопасности, Офицер, "СБ"
+highlights-warden = Смотритель, Безопасности, "СБ"
+
+# Карго
+highlights-cargo-technician = Грузчик, Снабжение, Карго
+highlights-salvage-specialist = Утилизатор, Снабжение, "Утиль", Шахтер
+
+# Инженерия
+highlights-atmospheric-technician = Атмосферный техник, Атмосферный, Атмос
+highlights-station-engineer = Инженер, Инженерия, Инженер, "Инж"
+highlights-technical-assistant = Технический ассистент, Инженерия, Инженер, "Инж"
+
+# Медицина
+highlights-chemist = Химик, Химия, "Мед", Медик, Врач
+highlights-medical-doctor = Врач, Доктор, "Мед", Медик, Врач
+highlights-medical-intern = Интерн, "Мед", Медик, Врач
+highlights-paramedic = Парамедик, "Парамед", "Мед", Медик, Врач
+
+# Наука
+highlights-scientist = Ученый, Наука, "НИО"
+highlights-research-assistant = Научный Ассистент, Наука, "НИО"
+
+# Гражданские
+highlights-bartender = Бармен, "Бар", "Сервис"
+highlights-botanist = Ботаник, Ботаника, Гидропоника
+highlights-chaplain = Священник, "Церковь", Святой Отец
+highlights-chef = Повар, Кухня
+highlights-clown = Клоун, Шут
+highlights-janitor = Уборщик, "Уборка"
+highlights-lawyer = Юрист, Адвокат
+highlights-librarian = Библиотекарь, Библиотека
+highlights-mime = Мим
+highlights-passenger = Пассажир
+highlights-service-worker = Сервисный Работник
+
+# Станционные роли
+highlights-boxer = Боксер
+highlights-reporter = Репортер, Журналист
+highlights-zookeeper = Смотритель зоопарка
+highlights-psychologist = Психолог, Психология
+
+# ИИ
+highlights-personal-ai = ПИИ, "ИИ"
+highlights-cyborg = Киборг, Борг, Робот
+highlights-station-ai = Станционный ИИ, "ИИ", Искусственный Интеллект
diff --git a/Resources/Locale/ru-RU/chat/ui/chat-box.ftl b/Resources/Locale/ru-RU/chat/ui/chat-box.ftl
index dda8ff1aec2..967068fc1d3 100644
--- a/Resources/Locale/ru-RU/chat/ui/chat-box.ftl
+++ b/Resources/Locale/ru-RU/chat/ui/chat-box.ftl
@@ -29,3 +29,11 @@ hud-chatbox-channel-Server = Сервер
hud-chatbox-channel-Visual = Визуальный
hud-chatbox-channel-Damage = Повреждения
hud-chatbox-channel-Unspecified = Неопределённый
+hud-chatbox-highlights = Подсветка:
+hud-chatbox-highlights-button = Отправить
+hud-chatbox-highlights-tooltip = Слова должны быть разделены новой строкой,
+ если обернуты в " ", они будут подсвечены
+ только если отделены пробелами.
+hud-chatbox-highlights-placeholder = Урист
+ "Пара"
+ Мост
diff --git a/Resources/Locale/ru-RU/escape-menu/ui/options-menu.ftl b/Resources/Locale/ru-RU/escape-menu/ui/options-menu.ftl
index 30417ce5613..33a779e7cc1 100644
--- a/Resources/Locale/ru-RU/escape-menu/ui/options-menu.ftl
+++ b/Resources/Locale/ru-RU/escape-menu/ui/options-menu.ftl
@@ -43,6 +43,9 @@ ui-options-interface-label = Интерфейс
## Graphics menu
+ui-options-auto-fill-highlights = Автоматически заполнять подсветкой информацию о персонаже
+ui-options-highlights-color = Цвет подсветки:
+ui-options-highlights-color-example = Это подсвеченный текст
ui-options-show-held-item = Показать удерживаемый элемент рядом с курсором
ui-options-show-combat-mode-indicators = Показать индикатор боевого режима рядом с курсором
ui-options-opaque-storage-window = Непрозрачность окна хранилища