Refactor: Chat transmission ranges (+ a little preparation for downstream fork functionality) (#16026)
This commit is contained in:
@@ -38,7 +38,7 @@ namespace Content.Server.Chat.Commands
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<ChatSystem>()
|
IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<ChatSystem>()
|
||||||
.TrySendInGameICMessage(playerEntity, message, InGameICChatType.Emote, false, false, shell, player);
|
.TrySendInGameICMessage(playerEntity, message, InGameICChatType.Emote, ChatTransmitRange.Normal, shell, player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ namespace Content.Server.Chat.Commands
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<ChatSystem>()
|
IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<ChatSystem>()
|
||||||
.TrySendInGameICMessage(playerEntity, message, InGameICChatType.Speak, false, false, shell, player);
|
.TrySendInGameICMessage(playerEntity, message, InGameICChatType.Speak, ChatTransmitRange.Normal, shell, player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ namespace Content.Server.Chat.Commands
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<ChatSystem>()
|
IoCManager.Resolve<IEntitySystemManager>().GetEntitySystem<ChatSystem>()
|
||||||
.TrySendInGameICMessage(playerEntity, message, InGameICChatType.Whisper, false, false, shell, player);
|
.TrySendInGameICMessage(playerEntity, message, InGameICChatType.Whisper, ChatTransmitRange.Normal, shell, player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ public sealed class AutoEmoteSystem : EntitySystem
|
|||||||
|
|
||||||
if (autoEmotePrototype.WithChat)
|
if (autoEmotePrototype.WithChat)
|
||||||
{
|
{
|
||||||
_chatSystem.TryEmoteWithChat(uid, autoEmotePrototype.EmoteId, autoEmotePrototype.HiddenFromChatWindow);
|
_chatSystem.TryEmoteWithChat(uid, autoEmotePrototype.EmoteId, autoEmotePrototype.HiddenFromChatWindow ? ChatTransmitRange.HideChat : ChatTransmitRange.Normal);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -52,15 +52,13 @@ public partial class ChatSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="source">The entity that is speaking</param>
|
/// <param name="source">The entity that is speaking</param>
|
||||||
/// <param name="emoteId">The id of emote prototype. Should has valid <see cref="EmotePrototype.ChatMessages"/></param>
|
/// <param name="emoteId">The id of emote prototype. Should has valid <see cref="EmotePrototype.ChatMessages"/></param>
|
||||||
/// <param name="hideChat">Whether or not this message should appear in the chat window</param>
|
/// <param name="range">Conceptual range of transmission, if it shows in the chat window, if it shows to far-away ghosts or ghosts at all...</param>
|
||||||
/// <param name="hideGlobalGhostChat">Whether or not this message should appear in the chat window for out-of-range ghosts (which otherwise ignore range restrictions)</param>
|
|
||||||
/// <param name="nameOverride">The name to use for the speaking entity. Usually this should just be modified via <see cref="TransformSpeakerNameEvent"/>. If this is set, the event will not get raised.</param>
|
/// <param name="nameOverride">The name to use for the speaking entity. Usually this should just be modified via <see cref="TransformSpeakerNameEvent"/>. If this is set, the event will not get raised.</param>
|
||||||
public void TryEmoteWithChat(EntityUid source, string emoteId, bool hideChat = false,
|
public void TryEmoteWithChat(EntityUid source, string emoteId, ChatTransmitRange range = ChatTransmitRange.Normal, string? nameOverride = null)
|
||||||
bool hideGlobalGhostChat = false, string? nameOverride = null)
|
|
||||||
{
|
{
|
||||||
if (!_prototypeManager.TryIndex<EmotePrototype>(emoteId, out var proto))
|
if (!_prototypeManager.TryIndex<EmotePrototype>(emoteId, out var proto))
|
||||||
return;
|
return;
|
||||||
TryEmoteWithChat(source, proto, hideChat, hideGlobalGhostChat, nameOverride);
|
TryEmoteWithChat(source, proto, range, nameOverride);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -68,17 +66,15 @@ public partial class ChatSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="source">The entity that is speaking</param>
|
/// <param name="source">The entity that is speaking</param>
|
||||||
/// <param name="emote">The emote prototype. Should has valid <see cref="EmotePrototype.ChatMessages"/></param>
|
/// <param name="emote">The emote prototype. Should has valid <see cref="EmotePrototype.ChatMessages"/></param>
|
||||||
/// <param name="hideChat">Whether or not this message should appear in the chat window</param>
|
/// <param name="range">Conceptual range of transmission, if it shows in the chat window, if it shows to far-away ghosts or ghosts at all...</param>
|
||||||
/// <param name="hideGlobalGhostChat">Whether or not this message should appear in the chat window for out-of-range ghosts (which otherwise ignore range restrictions)</param>
|
|
||||||
/// <param name="nameOverride">The name to use for the speaking entity. Usually this should just be modified via <see cref="TransformSpeakerNameEvent"/>. If this is set, the event will not get raised.</param>
|
/// <param name="nameOverride">The name to use for the speaking entity. Usually this should just be modified via <see cref="TransformSpeakerNameEvent"/>. If this is set, the event will not get raised.</param>
|
||||||
public void TryEmoteWithChat(EntityUid source, EmotePrototype emote, bool hideChat = false,
|
public void TryEmoteWithChat(EntityUid source, EmotePrototype emote, ChatTransmitRange range = ChatTransmitRange.Normal, string? nameOverride = null)
|
||||||
bool hideGlobalGhostChat = false, string? nameOverride = null)
|
|
||||||
{
|
{
|
||||||
// check if proto has valid message for chat
|
// check if proto has valid message for chat
|
||||||
if (emote.ChatMessages.Count != 0)
|
if (emote.ChatMessages.Count != 0)
|
||||||
{
|
{
|
||||||
var action = _random.Pick(emote.ChatMessages);
|
var action = _random.Pick(emote.ChatMessages);
|
||||||
SendEntityEmote(source, action, hideChat, hideGlobalGhostChat, nameOverride, false);
|
SendEntityEmote(source, action, range, nameOverride, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// do the rest of emote event logic here
|
// do the rest of emote event logic here
|
||||||
|
|||||||
@@ -120,17 +120,32 @@ public sealed partial class ChatSystem : SharedChatSystem
|
|||||||
/// <param name="message">The message being spoken or emoted</param>
|
/// <param name="message">The message being spoken or emoted</param>
|
||||||
/// <param name="desiredType">The chat type</param>
|
/// <param name="desiredType">The chat type</param>
|
||||||
/// <param name="hideChat">Whether or not this message should appear in the chat window</param>
|
/// <param name="hideChat">Whether or not this message should appear in the chat window</param>
|
||||||
/// <param name="hideGlobalGhostChat">Whether or not this message should appear in the chat window for out-of-range ghosts (which otherwise ignore range restrictions)</param>
|
|
||||||
/// <param name="shell"></param>
|
/// <param name="shell"></param>
|
||||||
/// <param name="player">The player doing the speaking</param>
|
/// <param name="player">The player doing the speaking</param>
|
||||||
/// <param name="nameOverride">The name to use for the speaking entity. Usually this should just be modified via <see cref="TransformSpeakerNameEvent"/>. If this is set, the event will not get raised.</param>
|
/// <param name="nameOverride">The name to use for the speaking entity. Usually this should just be modified via <see cref="TransformSpeakerNameEvent"/>. If this is set, the event will not get raised.</param>
|
||||||
public void TrySendInGameICMessage(EntityUid source, string message, InGameICChatType desiredType, bool hideChat, bool hideGlobalGhostChat = false,
|
public void TrySendInGameICMessage(EntityUid source, string message, InGameICChatType desiredType, bool hideChat,
|
||||||
|
IConsoleShell? shell = null, IPlayerSession? player = null, string? nameOverride = null, bool checkRadioPrefix = true)
|
||||||
|
{
|
||||||
|
TrySendInGameICMessage(source, message, desiredType, hideChat ? ChatTransmitRange.HideChat : ChatTransmitRange.Normal, shell, player, nameOverride, checkRadioPrefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends an in-character chat message to relevant clients.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source">The entity that is speaking</param>
|
||||||
|
/// <param name="message">The message being spoken or emoted</param>
|
||||||
|
/// <param name="desiredType">The chat type</param>
|
||||||
|
/// <param name="range">Conceptual range of transmission, if it shows in the chat window, if it shows to far-away ghosts or ghosts at all...</param>
|
||||||
|
/// <param name="shell"></param>
|
||||||
|
/// <param name="player">The player doing the speaking</param>
|
||||||
|
/// <param name="nameOverride">The name to use for the speaking entity. Usually this should just be modified via <see cref="TransformSpeakerNameEvent"/>. If this is set, the event will not get raised.</param>
|
||||||
|
public void TrySendInGameICMessage(EntityUid source, string message, InGameICChatType desiredType, ChatTransmitRange range,
|
||||||
IConsoleShell? shell = null, IPlayerSession? player = null, string? nameOverride = null, bool checkRadioPrefix = true)
|
IConsoleShell? shell = null, IPlayerSession? player = null, string? nameOverride = null, bool checkRadioPrefix = true)
|
||||||
{
|
{
|
||||||
if (HasComp<GhostComponent>(source))
|
if (HasComp<GhostComponent>(source))
|
||||||
{
|
{
|
||||||
// Ghosts can only send dead chat messages, so we'll forward it to InGame OOC.
|
// Ghosts can only send dead chat messages, so we'll forward it to InGame OOC.
|
||||||
TrySendInGameOOCMessage(source, message, InGameOOCChatType.Dead, hideChat, shell, player);
|
TrySendInGameOOCMessage(source, message, InGameOOCChatType.Dead, range == ChatTransmitRange.HideChat, shell, player);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,7 +165,6 @@ public sealed partial class ChatSystem : SharedChatSystem
|
|||||||
message = message[1..];
|
message = message[1..];
|
||||||
}
|
}
|
||||||
|
|
||||||
hideGlobalGhostChat |= hideChat;
|
|
||||||
bool shouldCapitalize = (desiredType != InGameICChatType.Emote);
|
bool shouldCapitalize = (desiredType != InGameICChatType.Emote);
|
||||||
bool shouldPunctuate = _configurationManager.GetCVar(CCVars.ChatPunctuation);
|
bool shouldPunctuate = _configurationManager.GetCVar(CCVars.ChatPunctuation);
|
||||||
|
|
||||||
@@ -159,7 +173,7 @@ public sealed partial class ChatSystem : SharedChatSystem
|
|||||||
// Was there an emote in the message? If so, send it.
|
// Was there an emote in the message? If so, send it.
|
||||||
if (player != null && emoteStr != message && emoteStr != null)
|
if (player != null && emoteStr != message && emoteStr != null)
|
||||||
{
|
{
|
||||||
SendEntityEmote(source, emoteStr, hideChat, hideGlobalGhostChat, nameOverride);
|
SendEntityEmote(source, emoteStr, range, nameOverride);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This can happen if the entire string is sanitized out.
|
// This can happen if the entire string is sanitized out.
|
||||||
@@ -171,7 +185,7 @@ public sealed partial class ChatSystem : SharedChatSystem
|
|||||||
{
|
{
|
||||||
if (TryProccessRadioMessage(source, message, out var modMessage, out var channel))
|
if (TryProccessRadioMessage(source, message, out var modMessage, out var channel))
|
||||||
{
|
{
|
||||||
SendEntityWhisper(source, modMessage, hideChat, hideGlobalGhostChat, channel, nameOverride);
|
SendEntityWhisper(source, modMessage, range, channel, nameOverride);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -180,13 +194,13 @@ public sealed partial class ChatSystem : SharedChatSystem
|
|||||||
switch (desiredType)
|
switch (desiredType)
|
||||||
{
|
{
|
||||||
case InGameICChatType.Speak:
|
case InGameICChatType.Speak:
|
||||||
SendEntitySpeak(source, message, hideChat, hideGlobalGhostChat, nameOverride);
|
SendEntitySpeak(source, message, range, nameOverride);
|
||||||
break;
|
break;
|
||||||
case InGameICChatType.Whisper:
|
case InGameICChatType.Whisper:
|
||||||
SendEntityWhisper(source, message, hideChat, hideGlobalGhostChat, null, nameOverride);
|
SendEntityWhisper(source, message, range, null, nameOverride);
|
||||||
break;
|
break;
|
||||||
case InGameICChatType.Emote:
|
case InGameICChatType.Emote:
|
||||||
SendEntityEmote(source, message, hideChat, hideGlobalGhostChat, nameOverride);
|
SendEntityEmote(source, message, range, nameOverride);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -280,7 +294,7 @@ public sealed partial class ChatSystem : SharedChatSystem
|
|||||||
|
|
||||||
#region Private API
|
#region Private API
|
||||||
|
|
||||||
private void SendEntitySpeak(EntityUid source, string originalMessage, bool hideChat, bool hideGlobalGhostChat, string? nameOverride)
|
private void SendEntitySpeak(EntityUid source, string originalMessage, ChatTransmitRange range, string? nameOverride)
|
||||||
{
|
{
|
||||||
if (!_actionBlocker.CanSpeak(source))
|
if (!_actionBlocker.CanSpeak(source))
|
||||||
return;
|
return;
|
||||||
@@ -306,7 +320,7 @@ public sealed partial class ChatSystem : SharedChatSystem
|
|||||||
var wrappedMessage = Loc.GetString("chat-manager-entity-say-wrap-message",
|
var wrappedMessage = Loc.GetString("chat-manager-entity-say-wrap-message",
|
||||||
("entityName", name), ("message", FormattedMessage.EscapeText(message)));
|
("entityName", name), ("message", FormattedMessage.EscapeText(message)));
|
||||||
|
|
||||||
SendInVoiceRange(ChatChannel.Local, message, wrappedMessage, source, hideChat, hideGlobalGhostChat);
|
SendInVoiceRange(ChatChannel.Local, message, wrappedMessage, source, range);
|
||||||
|
|
||||||
var ev = new EntitySpokeEvent(source, message, null, null);
|
var ev = new EntitySpokeEvent(source, message, null, null);
|
||||||
RaiseLocalEvent(source, ev, true);
|
RaiseLocalEvent(source, ev, true);
|
||||||
@@ -333,7 +347,7 @@ public sealed partial class ChatSystem : SharedChatSystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendEntityWhisper(EntityUid source, string originalMessage, bool hideChat, bool hideGlobalGhostChat, RadioChannelPrototype? channel, string? nameOverride)
|
private void SendEntityWhisper(EntityUid source, string originalMessage, ChatTransmitRange range, RadioChannelPrototype? channel, string? nameOverride)
|
||||||
{
|
{
|
||||||
if (!_actionBlocker.CanSpeak(source))
|
if (!_actionBlocker.CanSpeak(source))
|
||||||
return;
|
return;
|
||||||
@@ -372,16 +386,16 @@ public sealed partial class ChatSystem : SharedChatSystem
|
|||||||
if (session.AttachedEntity is not { Valid: true } playerEntity)
|
if (session.AttachedEntity is not { Valid: true } playerEntity)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (hideGlobalGhostChat && data.Observer && data.Range < 0)
|
if (MessageRangeCheck(session, data, range) != MessageRangeCheckResult.Full)
|
||||||
continue; // Won't get logged to chat, and ghosts are too far away to see the pop-up, so we just won't send it to them.
|
continue; // Won't get logged to chat, and ghosts are too far away to see the pop-up, so we just won't send it to them.
|
||||||
|
|
||||||
if (data.Range <= WhisperRange)
|
if (data.Range <= WhisperRange)
|
||||||
_chatManager.ChatMessageToOne(ChatChannel.Whisper, message, wrappedMessage, source, data.HideChatOverride ?? hideChat, session.ConnectedClient);
|
_chatManager.ChatMessageToOne(ChatChannel.Whisper, message, wrappedMessage, source, false, session.ConnectedClient);
|
||||||
else
|
else
|
||||||
_chatManager.ChatMessageToOne(ChatChannel.Whisper, obfuscatedMessage, wrappedobfuscatedMessage, source, data.HideChatOverride ?? hideChat, session.ConnectedClient);
|
_chatManager.ChatMessageToOne(ChatChannel.Whisper, obfuscatedMessage, wrappedobfuscatedMessage, source, false, session.ConnectedClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
_replay.QueueReplayMessage(new ChatMessage(ChatChannel.Whisper, message, wrappedMessage, source, hideChat));
|
_replay.QueueReplayMessage(new ChatMessage(ChatChannel.Whisper, message, wrappedMessage, source, MessageRangeHideChatForReplay(range)));
|
||||||
|
|
||||||
var ev = new EntitySpokeEvent(source, message, channel, obfuscatedMessage);
|
var ev = new EntitySpokeEvent(source, message, channel, obfuscatedMessage);
|
||||||
RaiseLocalEvent(source, ev, true);
|
RaiseLocalEvent(source, ev, true);
|
||||||
@@ -404,8 +418,7 @@ public sealed partial class ChatSystem : SharedChatSystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SendEntityEmote(EntityUid source, string action, bool hideChat,
|
private void SendEntityEmote(EntityUid source, string action, ChatTransmitRange range, string? nameOverride, bool checkEmote = true)
|
||||||
bool hideGlobalGhostChat, string? nameOverride, bool checkEmote = true)
|
|
||||||
{
|
{
|
||||||
if (!_actionBlocker.CanEmote(source)) return;
|
if (!_actionBlocker.CanEmote(source)) return;
|
||||||
|
|
||||||
@@ -419,7 +432,7 @@ public sealed partial class ChatSystem : SharedChatSystem
|
|||||||
|
|
||||||
if (checkEmote)
|
if (checkEmote)
|
||||||
TryEmoteChatInput(source, action);
|
TryEmoteChatInput(source, action);
|
||||||
SendInVoiceRange(ChatChannel.Emotes, action, wrappedMessage, source, hideChat, hideGlobalGhostChat);
|
SendInVoiceRange(ChatChannel.Emotes, action, wrappedMessage, source, range);
|
||||||
|
|
||||||
if (name != Name(source))
|
if (name != Name(source))
|
||||||
_adminLogger.Add(LogType.Chat, LogImpact.Low, $"Emote from {ToPrettyString(source):user} as {name}: {action}");
|
_adminLogger.Add(LogType.Chat, LogImpact.Low, $"Emote from {ToPrettyString(source):user} as {name}: {action}");
|
||||||
@@ -441,7 +454,7 @@ public sealed partial class ChatSystem : SharedChatSystem
|
|||||||
("entityName", name),
|
("entityName", name),
|
||||||
("message", FormattedMessage.EscapeText(message)));
|
("message", FormattedMessage.EscapeText(message)));
|
||||||
|
|
||||||
SendInVoiceRange(ChatChannel.LOOC, message, wrappedMessage, source, hideChat, false);
|
SendInVoiceRange(ChatChannel.LOOC, message, wrappedMessage, source, hideChat ? ChatTransmitRange.HideChat : ChatTransmitRange.Normal);
|
||||||
_adminLogger.Add(LogType.Chat, LogImpact.Low, $"LOOC from {player:Player}: {message}");
|
_adminLogger.Add(LogType.Chat, LogImpact.Low, $"LOOC from {player:Player}: {message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -474,18 +487,66 @@ public sealed partial class ChatSystem : SharedChatSystem
|
|||||||
|
|
||||||
#region Utility
|
#region Utility
|
||||||
|
|
||||||
|
private enum MessageRangeCheckResult {
|
||||||
|
Disallowed,
|
||||||
|
HideChat,
|
||||||
|
Full
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If hideChat should be set as far as replays are concerned.
|
||||||
|
/// </summary>
|
||||||
|
private bool MessageRangeHideChatForReplay(ChatTransmitRange range)
|
||||||
|
{
|
||||||
|
return range == ChatTransmitRange.HideChat;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a target as returned from GetRecipients should receive the message.
|
||||||
|
/// Keep in mind data.Range is -1 for out of range observers.
|
||||||
|
/// </summary>
|
||||||
|
private MessageRangeCheckResult MessageRangeCheck(ICommonSession session, ICChatRecipientData data, ChatTransmitRange range)
|
||||||
|
{
|
||||||
|
var initialResult = MessageRangeCheckResult.Full;
|
||||||
|
switch (range)
|
||||||
|
{
|
||||||
|
case ChatTransmitRange.Normal:
|
||||||
|
initialResult = MessageRangeCheckResult.Full;
|
||||||
|
break;
|
||||||
|
case ChatTransmitRange.GhostRangeLimit:
|
||||||
|
initialResult = (data.Observer && data.Range < 0 && !_adminManager.IsAdmin((IPlayerSession) session)) ? MessageRangeCheckResult.HideChat : MessageRangeCheckResult.Full;
|
||||||
|
break;
|
||||||
|
case ChatTransmitRange.HideChat:
|
||||||
|
initialResult = MessageRangeCheckResult.HideChat;
|
||||||
|
break;
|
||||||
|
case ChatTransmitRange.NoGhosts:
|
||||||
|
initialResult = (data.Observer && !_adminManager.IsAdmin((IPlayerSession) session)) ? MessageRangeCheckResult.Disallowed : MessageRangeCheckResult.Full;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
var insistHideChat = data.HideChatOverride ?? false;
|
||||||
|
var insistNoHideChat = !(data.HideChatOverride ?? true);
|
||||||
|
if (insistHideChat && initialResult == MessageRangeCheckResult.Full)
|
||||||
|
return MessageRangeCheckResult.HideChat;
|
||||||
|
if (insistNoHideChat && initialResult == MessageRangeCheckResult.HideChat)
|
||||||
|
return MessageRangeCheckResult.Full;
|
||||||
|
return initialResult;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sends a chat message to the given players in range of the source entity.
|
/// Sends a chat message to the given players in range of the source entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void SendInVoiceRange(ChatChannel channel, string message, string wrappedMessage, EntityUid source, bool hideChat, bool hideGlobalGhostChat)
|
private void SendInVoiceRange(ChatChannel channel, string message, string wrappedMessage, EntityUid source, ChatTransmitRange range)
|
||||||
{
|
{
|
||||||
foreach (var (session, data) in GetRecipients(source, VoiceRange))
|
foreach (var (session, data) in GetRecipients(source, VoiceRange))
|
||||||
{
|
{
|
||||||
var entHideChat = data.HideChatOverride ?? (hideChat || hideGlobalGhostChat && data.Observer && data.Range < 0);
|
var entRange = MessageRangeCheck(session, data, range);
|
||||||
|
if (entRange == MessageRangeCheckResult.Disallowed)
|
||||||
|
continue;
|
||||||
|
var entHideChat = entRange == MessageRangeCheckResult.HideChat;
|
||||||
_chatManager.ChatMessageToOne(channel, message, wrappedMessage, source, entHideChat, session.ConnectedClient);
|
_chatManager.ChatMessageToOne(channel, message, wrappedMessage, source, entHideChat, session.ConnectedClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
_replay.QueueReplayMessage(new ChatMessage(channel, message, wrappedMessage, source, hideChat));
|
_replay.QueueReplayMessage(new ChatMessage(channel, message, wrappedMessage, source, MessageRangeHideChatForReplay(range)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -710,3 +771,19 @@ public enum InGameOOCChatType : byte
|
|||||||
Looc,
|
Looc,
|
||||||
Dead
|
Dead
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Controls transmission of chat.
|
||||||
|
/// </summary>
|
||||||
|
public enum ChatTransmitRange : byte
|
||||||
|
{
|
||||||
|
/// Acts normal, ghosts can hear across the map, etc.
|
||||||
|
Normal,
|
||||||
|
/// Normal but ghosts are still range-limited.
|
||||||
|
GhostRangeLimit,
|
||||||
|
/// Hidden from the chat window.
|
||||||
|
HideChat,
|
||||||
|
/// Ghosts can't hear or see it at all. Regular players can if in-range.
|
||||||
|
NoGhosts
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public sealed class EmoteOnDamageSystem : EntitySystem
|
|||||||
var emote = _random.Pick(emoteOnDamage.Emotes);
|
var emote = _random.Pick(emoteOnDamage.Emotes);
|
||||||
if (emoteOnDamage.WithChat)
|
if (emoteOnDamage.WithChat)
|
||||||
{
|
{
|
||||||
_chatSystem.TryEmoteWithChat(uid, emote, emoteOnDamage.HiddenFromChatWindow);
|
_chatSystem.TryEmoteWithChat(uid, emote, emoteOnDamage.HiddenFromChatWindow ? ChatTransmitRange.HideChat : ChatTransmitRange.Normal);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public sealed class Emote : ReagentEffect
|
|||||||
|
|
||||||
var chatSys = args.EntityManager.System<ChatSystem>();
|
var chatSys = args.EntityManager.System<ChatSystem>();
|
||||||
if (ShowInChat)
|
if (ShowInChat)
|
||||||
chatSys.TryEmoteWithChat(args.SolutionEntity, EmoteId, hideGlobalGhostChat: true);
|
chatSys.TryEmoteWithChat(args.SolutionEntity, EmoteId, ChatTransmitRange.GhostRangeLimit);
|
||||||
else
|
else
|
||||||
chatSys.TryEmoteWithoutChat(args.SolutionEntity, EmoteId);
|
chatSys.TryEmoteWithoutChat(args.SolutionEntity, EmoteId);
|
||||||
|
|
||||||
|
|||||||
@@ -91,14 +91,14 @@ public sealed class CluwneSystem : EntitySystem
|
|||||||
if (_robustRandom.Prob(component.GiggleRandomChance))
|
if (_robustRandom.Prob(component.GiggleRandomChance))
|
||||||
{
|
{
|
||||||
_audio.PlayPvs(component.SpawnSound, uid);
|
_audio.PlayPvs(component.SpawnSound, uid);
|
||||||
_chat.TrySendInGameICMessage(uid, "honks", InGameICChatType.Emote, false, false);
|
_chat.TrySendInGameICMessage(uid, "honks", InGameICChatType.Emote, ChatTransmitRange.Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (_robustRandom.Prob(component.KnockChance))
|
else if (_robustRandom.Prob(component.KnockChance))
|
||||||
{
|
{
|
||||||
_audio.PlayPvs(component.KnockSound, uid);
|
_audio.PlayPvs(component.KnockSound, uid);
|
||||||
_stunSystem.TryParalyze(uid, TimeSpan.FromSeconds(component.ParalyzeTime), true);
|
_stunSystem.TryParalyze(uid, TimeSpan.FromSeconds(component.ParalyzeTime), true);
|
||||||
_chat.TrySendInGameICMessage(uid, "spasms", InGameICChatType.Emote, false, false);
|
_chat.TrySendInGameICMessage(uid, "spasms", InGameICChatType.Emote, ChatTransmitRange.Normal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ public sealed class MedibotInjectOperator : HTNOperator
|
|||||||
_solution.TryAddReagent(target, injectable, botComp.EmergencyMed, botComp.EmergencyMedAmount, out var accepted);
|
_solution.TryAddReagent(target, injectable, botComp.EmergencyMed, botComp.EmergencyMedAmount, out var accepted);
|
||||||
_popup.PopupEntity(Loc.GetString("hypospray-component-feel-prick-message"), target, target);
|
_popup.PopupEntity(Loc.GetString("hypospray-component-feel-prick-message"), target, target);
|
||||||
_audio.PlayPvs(botComp.InjectSound, target);
|
_audio.PlayPvs(botComp.InjectSound, target);
|
||||||
_chat.TrySendInGameICMessage(owner, Loc.GetString("medibot-finish-inject"), InGameICChatType.Speak, hideChat: false, hideGlobalGhostChat: true);
|
_chat.TrySendInGameICMessage(owner, Loc.GetString("medibot-finish-inject"), InGameICChatType.Speak, ChatTransmitRange.GhostRangeLimit);
|
||||||
return HTNOperatorStatus.Finished;
|
return HTNOperatorStatus.Finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,7 +89,7 @@ public sealed class MedibotInjectOperator : HTNOperator
|
|||||||
_solution.TryAddReagent(target, injectable, botComp.StandardMed, botComp.StandardMedAmount, out var accepted);
|
_solution.TryAddReagent(target, injectable, botComp.StandardMed, botComp.StandardMedAmount, out var accepted);
|
||||||
_popup.PopupEntity(Loc.GetString("hypospray-component-feel-prick-message"), target, target);
|
_popup.PopupEntity(Loc.GetString("hypospray-component-feel-prick-message"), target, target);
|
||||||
_audio.PlayPvs(botComp.InjectSound, target);
|
_audio.PlayPvs(botComp.InjectSound, target);
|
||||||
_chat.TrySendInGameICMessage(owner, Loc.GetString("medibot-finish-inject"), InGameICChatType.Speak, hideChat: false, hideGlobalGhostChat: true);
|
_chat.TrySendInGameICMessage(owner, Loc.GetString("medibot-finish-inject"), InGameICChatType.Speak, ChatTransmitRange.GhostRangeLimit);
|
||||||
return HTNOperatorStatus.Finished;
|
return HTNOperatorStatus.Finished;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ public sealed class RadioDeviceSystem : EntitySystem
|
|||||||
var name = Loc.GetString("speech-name-relay", ("speaker", Name(uid)),
|
var name = Loc.GetString("speech-name-relay", ("speaker", Name(uid)),
|
||||||
("originalName", nameEv.Name));
|
("originalName", nameEv.Name));
|
||||||
|
|
||||||
var hideGlobalGhostChat = true; // log to chat so people can identity the speaker/source, but avoid clogging ghost chat if there are many radios
|
// log to chat so people can identity the speaker/source, but avoid clogging ghost chat if there are many radios
|
||||||
_chat.TrySendInGameICMessage(uid, args.Message, InGameICChatType.Speak, false, nameOverride: name, hideGlobalGhostChat:hideGlobalGhostChat, checkRadioPrefix: false);
|
_chat.TrySendInGameICMessage(uid, args.Message, InGameICChatType.Speak, ChatTransmitRange.GhostRangeLimit, nameOverride: name, checkRadioPrefix: false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ public sealed class SurveillanceCameraSpeakerSystem : EntitySystem
|
|||||||
var name = Loc.GetString("speech-name-relay", ("speaker", Name(uid)),
|
var name = Loc.GetString("speech-name-relay", ("speaker", Name(uid)),
|
||||||
("originalName", nameEv.Name));
|
("originalName", nameEv.Name));
|
||||||
|
|
||||||
var hideGlobalGhostChat = true; // log to chat so people can identity the speaker/source, but avoid clogging ghost chat if there are many radios
|
// log to chat so people can identity the speaker/source, but avoid clogging ghost chat if there are many radios
|
||||||
_chatSystem.TrySendInGameICMessage(uid, args.Message, InGameICChatType.Speak, false, hideGlobalGhostChat, nameOverride: name);
|
_chatSystem.TrySendInGameICMessage(uid, args.Message, InGameICChatType.Speak, ChatTransmitRange.GhostRangeLimit, nameOverride: name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user