Stealthier whispers (#17898)

* Stealth whisper take 2

* weh

* fix whisper maxrange

* make variables more distinct
This commit is contained in:
Errant
2023-08-01 14:43:02 +00:00
committed by GitHub
parent 5fc7f21853
commit 9b10f7f557
3 changed files with 28 additions and 11 deletions

View File

@@ -13,6 +13,8 @@ using Content.Shared.CCVar;
using Content.Shared.Chat; using Content.Shared.Chat;
using Content.Shared.Database; using Content.Shared.Database;
using Content.Shared.IdentityManagement; using Content.Shared.IdentityManagement;
using Content.Shared.Interaction;
using Content.Shared.Inventory;
using Content.Shared.Mobs.Systems; using Content.Shared.Mobs.Systems;
using Content.Shared.Radio; using Content.Shared.Radio;
using Robust.Server.GameObjects; using Robust.Server.GameObjects;
@@ -49,9 +51,11 @@ public sealed partial class ChatSystem : SharedChatSystem
[Dependency] private readonly StationSystem _stationSystem = default!; [Dependency] private readonly StationSystem _stationSystem = default!;
[Dependency] private readonly MobStateSystem _mobStateSystem = default!; [Dependency] private readonly MobStateSystem _mobStateSystem = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
public const int VoiceRange = 10; // how far voice goes in world units public const int VoiceRange = 10; // how far voice goes in world units
public const int WhisperRange = 2; // how far whisper goes in world units public const int WhisperClearRange = 2; // how far whisper goes while still being understandable, in world units
public const int WhisperMuffledRange = 5; // how far whisper goes at all, in world units
public const string DefaultAnnouncementSound = "/Audio/Announcements/announce.ogg"; public const string DefaultAnnouncementSound = "/Audio/Announcements/announce.ogg";
private bool _loocEnabled = true; private bool _loocEnabled = true;
@@ -373,7 +377,9 @@ public sealed partial class ChatSystem : SharedChatSystem
var obfuscatedMessage = ObfuscateMessageReadability(message, 0.2f); var obfuscatedMessage = ObfuscateMessageReadability(message, 0.2f);
// get the entity's apparent name (if no override provided). // get the entity's name by visual identity (if no override provided).
string nameIdentity = FormattedMessage.EscapeText(nameOverride ?? Identity.Name(source, EntityManager));
// get the entity's name by voice (if no override provided).
string name; string name;
if (nameOverride != null) if (nameOverride != null)
{ {
@@ -391,23 +397,33 @@ public sealed partial class ChatSystem : SharedChatSystem
var wrappedMessage = Loc.GetString("chat-manager-entity-whisper-wrap-message", var wrappedMessage = Loc.GetString("chat-manager-entity-whisper-wrap-message",
("entityName", name), ("message", FormattedMessage.EscapeText(message))); ("entityName", name), ("message", FormattedMessage.EscapeText(message)));
var wrappedobfuscatedMessage = Loc.GetString("chat-manager-entity-whisper-wrap-message", var wrappedobfuscatedMessage = Loc.GetString("chat-manager-entity-whisper-wrap-message",
("entityName", name), ("message", FormattedMessage.EscapeText(obfuscatedMessage))); ("entityName", nameIdentity), ("message", FormattedMessage.EscapeText(obfuscatedMessage)));
var wrappedUnknownMessage = Loc.GetString("chat-manager-entity-whisper-unknown-wrap-message",
("message", FormattedMessage.EscapeText(obfuscatedMessage)));
foreach (var (session, data) in GetRecipients(source, VoiceRange)) foreach (var (session, data) in GetRecipients(source, WhisperMuffledRange))
{ {
EntityUid listener;
if (session.AttachedEntity is not { Valid: true } playerEntity) if (session.AttachedEntity is not { Valid: true } playerEntity)
continue; continue;
listener = session.AttachedEntity.Value;
if (MessageRangeCheck(session, data, range) != MessageRangeCheckResult.Full) 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 <= WhisperClearRange)
_chatManager.ChatMessageToOne(ChatChannel.Whisper, message, wrappedMessage, source, false, session.ConnectedClient); _chatManager.ChatMessageToOne(ChatChannel.Whisper, message, wrappedMessage, source, false, session.ConnectedClient);
else //If listener is too far, they only hear fragments of the message
//Collisiongroup.Opaque is not ideal for this use. Preferably, there should be a check specifically with "Can Ent1 see Ent2" in mind
else if (_interactionSystem.InRangeUnobstructed(source, listener, WhisperMuffledRange, Shared.Physics.CollisionGroup.Opaque)) //Shared.Physics.CollisionGroup.Opaque
_chatManager.ChatMessageToOne(ChatChannel.Whisper, obfuscatedMessage, wrappedobfuscatedMessage, source, false, session.ConnectedClient); _chatManager.ChatMessageToOne(ChatChannel.Whisper, obfuscatedMessage, wrappedobfuscatedMessage, source, false, session.ConnectedClient);
//If listener is too far and has no line of sight, they can't identify the whisperer's identity
else
_chatManager.ChatMessageToOne(ChatChannel.Whisper, obfuscatedMessage, wrappedUnknownMessage, source, false, session.ConnectedClient);
} }
_replay.RecordServerMessage(new ChatMessage(ChatChannel.Whisper, message, wrappedMessage, source, MessageRangeHideChatForReplay(range))); _replay.RecordServerMessage(new ChatMessage(ChatChannel.Whisper, message, wrappedMessage, source, MessageRangeHideChatForReplay(range)));
@@ -647,7 +663,7 @@ public sealed partial class ChatSystem : SharedChatSystem
/// <summary> /// <summary>
/// Returns list of players and ranges for all players withing some range. Also returns observers with a range of -1. /// Returns list of players and ranges for all players withing some range. Also returns observers with a range of -1.
/// </summary> /// </summary>
private Dictionary<ICommonSession, ICChatRecipientData> GetRecipients(EntityUid source, float voiceRange) private Dictionary<ICommonSession, ICChatRecipientData> GetRecipients(EntityUid source, float voiceGetRange)
{ {
// TODO proper speech occlusion // TODO proper speech occlusion
@@ -672,7 +688,7 @@ public sealed partial class ChatSystem : SharedChatSystem
var observer = ghosts.HasComponent(playerEntity); var observer = ghosts.HasComponent(playerEntity);
// even if they are an observer, in some situations we still need the range // even if they are an observer, in some situations we still need the range
if (sourceCoords.TryDistance(EntityManager, transformEntity.Coordinates, out var distance) && distance < voiceRange) if (sourceCoords.TryDistance(EntityManager, transformEntity.Coordinates, out var distance) && distance < voiceGetRange)
{ {
recipients.Add(player, new ICChatRecipientData(distance, observer)); recipients.Add(player, new ICChatRecipientData(distance, observer));
continue; continue;
@@ -682,7 +698,7 @@ public sealed partial class ChatSystem : SharedChatSystem
recipients.Add(player, new ICChatRecipientData(-1, true)); recipients.Add(player, new ICChatRecipientData(-1, true));
} }
RaiseLocalEvent(new ExpandICChatRecipientstEvent(source, voiceRange, recipients)); RaiseLocalEvent(new ExpandICChatRecipientstEvent(source, voiceGetRange, recipients));
return recipients; return recipients;
} }

View File

@@ -53,7 +53,7 @@ public sealed class ListeningSystem : EntitySystem
continue; continue;
} }
if (obfuscatedEv != null && distance > ChatSystem.WhisperRange) if (obfuscatedEv != null && distance > ChatSystem.WhisperClearRange)
RaiseLocalEvent(listenerUid, obfuscatedEv); RaiseLocalEvent(listenerUid, obfuscatedEv);
else else
RaiseLocalEvent(listenerUid, ev); RaiseLocalEvent(listenerUid, ev);

View File

@@ -21,6 +21,7 @@ chat-manager-sender-announcement-wrap-message = {$sender} Announcement:
{$message} {$message}
chat-manager-entity-say-wrap-message = {$entityName} says, "{$message}" chat-manager-entity-say-wrap-message = {$entityName} says, "{$message}"
chat-manager-entity-whisper-wrap-message = {$entityName} whispers, "{$message}" chat-manager-entity-whisper-wrap-message = {$entityName} whispers, "{$message}"
chat-manager-entity-whisper-unknown-wrap-message = Someone whispers, "{$message}"
chat-manager-entity-me-wrap-message = {$entityName} {$message} chat-manager-entity-me-wrap-message = {$entityName} {$message}
chat-manager-entity-looc-wrap-message = LOOC: {$entityName}: {$message} chat-manager-entity-looc-wrap-message = LOOC: {$entityName}: {$message}
chat-manager-send-ooc-wrap-message = OOC: {$playerName}: {$message} chat-manager-send-ooc-wrap-message = OOC: {$playerName}: {$message}