/// <summary> /// Do not use this message directly. If you need to do work with the chat system use /// the Chat API (the only exception to this rule is if you just need to send 1 msg to 1 client from the server /// i.e syndi special roles) /// </summary> public static UpdateChatMessage Send(GameObject recipient, ChatChannel channels, ChatModifier chatMods, string chatMessage, string othersMsg = "", GameObject originator = null, string speaker = "", bool stripTags = true) { uint origin = NetId.Empty; if (originator != null) { origin = originator.GetComponent <NetworkIdentity>().netId; } UpdateChatMessage msg = new UpdateChatMessage { Recipient = recipient.GetComponent <NetworkIdentity>().netId, Channels = channels, ChatModifiers = chatMods, Message = chatMessage, OthersMessage = othersMsg, Originator = origin, Speaker = speaker, StripTags = stripTags }; msg.SendTo(recipient); return(msg); }
/// <summary> /// Turns on the talk icon and picks a suitable icon for the chat modifier. /// Starts a coroutine to continue display the icon for a while. /// </summary> /// <param name="chatModifier">The player's chat modifier.</param> public void TurnOnTalkIcon(ChatModifier chatModifier) { switch (chatModifier) { case ChatModifier.Yell: case ChatModifier.Exclaim: spriteHandler.ChangeSprite(ExclaimSprite); break; case ChatModifier.Question: spriteHandler.ChangeSprite(QuestionSprite); break; default: spriteHandler.ChangeSprite(TalkSprite); break; } spriteHandler.gameObject.SetActive(true); if (coWaitToTurnOff != null) { StopCoroutine(coWaitToTurnOff); coWaitToTurnOff = null; } coWaitToTurnOff = StartCoroutine(WaitToTurnOff(IconTimeout)); }
public ChatModifier GetCurrentChatModifiers() { ChatModifier modifiers = ChatModifier.None; if (IsGhost) { return(ChatModifier.None); } if (playerHealth.IsCrit) { return(ChatModifier.Mute); } if (playerHealth.IsSoftCrit) { modifiers |= ChatModifier.Whisper; } //TODO add missing modifiers //TODO add if for being drunk //ChatModifier modifiers = ChatModifier.Drunk; if (mind.jobType == JobType.CLOWN) { modifiers |= ChatModifier.Clown; } return(modifiers); }
/// <summary> /// Turns on the talk icon and picks a suitable icon for the chat modifier. /// Starts a coroutine to continue display the icon for a while. /// </summary> /// <param name="chatModifier">The player's chat modifier.</param> public void TurnOnTalkIcon(ChatModifier chatModifier) { switch (chatModifier) { case ChatModifier.Yell: goto case ChatModifier.Exclaim; case ChatModifier.Exclaim: spriteRend.sprite = exclaimSprite; break; case ChatModifier.Question: spriteRend.sprite = questionSprite; break; default: spriteRend.sprite = talkSprite; break; } spriteRend.enabled = true; if (coWaitToTurnOff != null) { StopCoroutine(coWaitToTurnOff); coWaitToTurnOff = null; } coWaitToTurnOff = StartCoroutine(WaitToTurnOff()); }
public void UpdateClientChat(string message, ChatChannel channels, bool isOriginator, GameObject recipient, Loudness loudness, ChatModifier modifiers) { if (string.IsNullOrEmpty(message)) { return; } trySendingTTS(message); if (PlayerManager.LocalPlayerScript == null) { channels = ChatChannel.OOC; } if (channels != ChatChannel.None) { // replace action messages with chat bubble if (channels.HasFlag(ChatChannel.Combat) || channels.HasFlag(ChatChannel.Action) || channels.HasFlag(ChatChannel.Examine) || modifiers.HasFlag(ChatModifier.Emote)) { if (isOriginator) { ChatBubbleManager.Instance.ShowAction(Regex.Replace(message, "<.*?>", string.Empty), recipient); } } ChatUI.Instance.AddChatEntry(message); } }
/// <summary> /// Do not use this message directly. If you need to do work with the chat system use /// the Chat API (the only exception to this rule is if you just need to send 1 msg to 1 client from the server /// i.e syndi special roles) /// </summary> public static NetMessage Send(GameObject recipient, ChatChannel channels, ChatModifier chatMods, string chatMessage, Loudness loudness = Loudness.NORMAL, string othersMsg = "", GameObject originator = null, string speaker = "", bool stripTags = true) { uint origin = NetId.Empty; if (originator != null) { origin = originator.GetComponent <NetworkIdentity>().netId; } NetMessage msg = new NetMessage { Recipient = recipient.GetComponent <NetworkIdentity>().netId, Channels = channels, ChatModifiers = chatMods, Message = chatMessage, OthersMessage = othersMsg, Originator = origin, Speaker = speaker, StripTags = stripTags, Loudness = loudness }; SendTo(recipient, msg, Category.Chat, 2); return(msg); }
public ChatEvent(string message, string speaker, ChatChannel channels, ChatModifier modifiers) { timestamp = (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds; this.channels = channels; this.modifiers = modifiers; this.speaker = speaker; this.message = ProcessMessage(message, speaker, this.channels, this.modifiers); }
private void AddChatBubbleMsg(string msg, ChatChannel channel, ChatModifier chatModifier) { // Cancel right away if the player cannot speak. if ((chatModifier & ChatModifier.Mute) == ChatModifier.Mute) { return; } if (msg.Length > maxMessageLength) { while (msg.Length > maxMessageLength) { int ws = -1; //Searching for the nearest whitespace for (int i = maxMessageLength; i >= 0; i--) { if (char.IsWhiteSpace(msg[i])) { ws = i; break; } } //Player is spamming with no whitespace. Cut it up if (ws == -1 || ws == 0) { ws = maxMessageLength + 2; } var split = msg.Substring(0, ws); msgQueue.Enqueue(new BubbleMsg { maxTime = TimeToShow(split.Length), msg = split, modifier = chatModifier }); msg = msg.Substring(ws + 1); if (msg.Length <= maxMessageLength) { msgQueue.Enqueue(new BubbleMsg { maxTime = TimeToShow(msg.Length), msg = msg, modifier = chatModifier }); } } } else { msgQueue.Enqueue(new BubbleMsg { maxTime = TimeToShow(msg.Length), msg = msg, modifier = chatModifier }); } // Progress quickly through the queue if there is a lot of text left. displayTimeMultiplier = 1 + TimeToShow(msgQueue) * displayTimeMultiplierPerSecond; if (!showingDialogue) { StartCoroutine(ShowDialogue()); } }
public ChatEvent(string message, GameObject speaker, ChatChannel channels) { var player = speaker.Player(); this.channels = channels; this.modifiers = player.Script.GetCurrentChatModifiers(); this.speaker = player?.Name; this.position = ( Vector2 )player?.GameObject.transform.position; this.message = ProcessMessage(message, this.speaker, this.channels, modifiers); }
public ChatEvent(string message, ConnectedPlayer speaker, ChatChannel channels) { var player = speaker.Script; this.channels = channels; this.modifiers = (player == null) ? ChatModifier.None : player.GetCurrentChatModifiers(); this.speaker = ((channels & ChatChannel.OOC) == ChatChannel.OOC) ? speaker.Username : player.name; this.position = ((player == null) ? Vector2.zero : (Vector2)player.gameObject.transform.position); this.message = ProcessMessage(message, this.speaker, this.channels, modifiers); }
private string ApplyModifiers(string input, ChatModifier modifiers) { string output = input; //Clowns say a random number (1-3) HONK!'s after every message if ((modifiers & ChatModifier.Clown) == ChatModifier.Clown) { int intensity = Random.Range(1, 4); for (int i = 0; i < intensity; i++) { if (i == 0) { output = output + " HONK!"; } else { output = output + "HONK!"; } } } //Sneks say extra S's if ((modifiers & ChatModifier.Hiss) == ChatModifier.Hiss) { //Regex - find 1 or more "s" Regex rx = new Regex("s+|S+"); output = rx.Replace(output, Hiss); } //Stuttering people randomly repeat beginnings of words if ((modifiers & ChatModifier.Stutter) == ChatModifier.Stutter) { //Regex - find word boundary followed by non digit, non special symbol, non end of word letter. Basically find the start of words. Regex rx = new Regex(@"(\b)+([^\d\W])\B"); output = rx.Replace(output, Stutter); } //Drunk people slur all "s" into "sh", randomly ...hic!... between words and have high % to ...hic!... after a sentance if ((modifiers & ChatModifier.Drunk) == ChatModifier.Drunk) { //Regex - find 1 or more "s" Regex rx = new Regex("s+|S+"); output = rx.Replace(output, Slur); //Regex - find 1 or more whitespace rx = new Regex(@"\s+"); output = rx.Replace(output, Hic); //50% chance to ...hic!... at end of sentance if (Random.Range(1, 3) == 1) { output = output + " ...hic!..."; } } return(output); }
private string ProcessMessage(string message, string speaker, ChatChannel channels, ChatModifier modifiers) { message = StripTags(message); //Skip everything if system message if ((channels & ChatChannel.System) == ChatChannel.System) { this.channels = ChatChannel.System; this.modifiers = ChatModifier.None; return(message = "<b><i>" + message + "</i></b>"); } //Skip everything if examining something if ((channels & ChatChannel.Examine) == ChatChannel.Examine) { this.channels = ChatChannel.Examine; this.modifiers = ChatModifier.None; return(message = "<b><i>" + message + "</i></b>"); } //Check for emote. If found skip chat modifiers, make sure emote is only in Local channel Regex rx = new Regex("^(/me )"); if (rx.IsMatch(message)) { // /me message this.channels = ChatChannel.Local; message = rx.Replace(message, " "); message = "<i><b>" + speaker + "</b> " + message + "</i>"; return(message); } //Check for OOC. If selected, remove all other channels and modifiers (could happen if UI f***s up or someone tampers with it) if ((channels & ChatChannel.OOC) == ChatChannel.OOC) { this.channels = ChatChannel.OOC; this.modifiers = ChatModifier.None; message = "<b>" + speaker + ": " + message + "</b>"; return(message); } //Ghosts don't get modifiers if ((channels & ChatChannel.Ghost) == ChatChannel.Ghost) { this.channels = ChatChannel.Ghost; this.modifiers = ChatModifier.None; return(message = "<b>" + speaker + ": " + message + "</b>"); } message = ApplyModifiers(message, modifiers); message = "<b>" + speaker + "</b> says: \"" + message + "\""; return(message); }
public void ToggleChatIcon(bool toggle, ChatModifier chatModifier) { if (toggle) { TurnOnTalkIcon(chatModifier); } else { TurnOffTalkIcon(); } }
public string ApplyMod(ChatModifier modifiers, string message) { foreach (var kvp in speechModifier) { if (modifiers.HasFlag(kvp.Key)) { message = kvp.Value.ProcessMessage(message); } } return(message); }
public override IEnumerator Process() { yield return(WaitFor(SentBy)); GameObject player = NetworkObject; if (ValidRequest(player)) { ChatModifier modifiers = player.GetComponent <PlayerScript>().GetCurrentChatModifiers(); ChatEvent chatEvent = new ChatEvent(ChatMessageText, player.name, Channels, modifiers); ChatRelay.Instance.AddToChatLogServer(chatEvent); } }
public static ShowChatBubbleMessage SendToNearby(GameObject followTransform, string message, bool isPlayerChatBubble = false, ChatModifier chatModifier = ChatModifier.None) { ShowChatBubbleMessage msg = new ShowChatBubbleMessage { ChatModifiers = chatModifier, Message = message, FollowTransform = followTransform.GetComponent <NetworkIdentity>().netId, IsPlayerChatBubble = isPlayerChatBubble }; msg.SendToVisiblePlayers(followTransform.transform.position); return(msg); }
private void QueueMessages(string msg, ChatModifier chatModifier = ChatModifier.None) { if (msg.Length > maxMessageLength) { while (msg.Length > maxMessageLength) { int ws = -1; //Searching for the nearest whitespace for (int i = maxMessageLength; i >= 0; i--) { if (char.IsWhiteSpace(msg[i])) { ws = i; break; } } //Player is spamming with no whitespace. Cut it up if (ws == -1 || ws == 0) { ws = maxMessageLength + 2; } var split = msg.Substring(0, ws); msgQueue.Enqueue(new BubbleMsg { maxTime = TimeToShow(split.Length), msg = split, modifier = chatModifier }); msg = msg.Substring(ws + 1); if (msg.Length <= maxMessageLength) { msgQueue.Enqueue(new BubbleMsg { maxTime = TimeToShow(msg.Length), msg = msg, modifier = chatModifier }); } } } else { msgQueue.Enqueue(new BubbleMsg { maxTime = TimeToShow(msg.Length), msg = msg, modifier = chatModifier }); } // Progress quickly through the queue if there is a lot of text left. displayTimeMultiplier = 1 + TimeToShow(msgQueue) * displayTimeMultiplierPerSecond; }
public ChatEvent(string message, ChatChannel channels, bool skipProcessing = false) { timestamp = (DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalMilliseconds; this.channels = channels; modifiers = ChatModifier.None; speaker = ""; if (skipProcessing) { this.message = message; } else { this.message = ProcessMessage(message, speaker, this.channels, modifiers); } }
/// <summary> /// Display a chat bubble and make it follow a transform target /// </summary> /// <param name="msg">Text to show in the chat bubble</param> /// <param name="followTarget">The transform in the world for the bubble to follow</param> /// <param name="chatModifier">Any chat modifiers that need to be applied</param> public static void ShowAChatBubble(Transform followTarget, string msg, ChatModifier chatModifier = ChatModifier.None) { var index = Instance.chatBubblePool.FindIndex(x => x.Target == followTarget); if (index != -1) { if (Instance.chatBubblePool[index].gameObject.activeInHierarchy) { Instance.chatBubblePool[index].AppendToBubble(msg, chatModifier); return; } } Instance.GetChatBubbleFromPool().SetupBubble(followTarget, msg, chatModifier); }
public ChatModifier GetCurrentChatModifiers() { if (playerMove.isGhost) { return(ChatModifier.None); } //TODO add missing modifiers ChatModifier modifiers = ChatModifier.Drunk; if (JobType == JobType.CLOWN) { modifiers |= ChatModifier.Clown; } return(modifiers); }
public string ApplyMod(ChatModifier modifiers, string message) { // Prevents accents from modifying emotes if (modifiers.HasFlag(ChatModifier.Emote)) { return(message); } foreach (var kvp in speechModifier) { if (modifiers.HasFlag(kvp.Key)) { message = kvp.Value.ProcessMessage(message); } } return(message); }
/// <summary> /// Sets the text, style and size of the bubble to match the message's modifier. /// </summary> /// <param name="msg"> Player's chat message </param> private void SetBubbleParameters(string msg, ChatModifier modifiers) { // Set default chat bubble values. Are overwritten by modifiers. var screenHeightMultiplier = (float)camera.scaledPixelHeight / 720f; //720 is the reference height bubbleSize = bubbleSizeNormal * screenHeightMultiplier; bubbleText.fontStyle = FontStyles.Normal; bubbleText.font = fontDefault; // Determine type if ((modifiers & ChatModifier.Emote) == ChatModifier.Emote) { bubbleText.fontStyle = FontStyles.Italic; // TODO Differentiate emoting from whispering (e.g. rectangular box instead of speech bubble) } else if ((modifiers & ChatModifier.Whisper) == ChatModifier.Whisper) { bubbleSize = bubbleSizeWhisper * screenHeightMultiplier; bubbleText.fontStyle = FontStyles.Italic; // TODO Differentiate emoting from whispering (e.g. dotted line around text) } else if ((modifiers & ChatModifier.Sing) == ChatModifier.Sing) { bubbleSize = bubbleSizeCaps * screenHeightMultiplier; bubbleText.fontStyle = FontStyles.Italic; } else if ((modifiers & ChatModifier.Yell) == ChatModifier.Yell) { bubbleSize = bubbleSizeCaps * screenHeightMultiplier; bubbleText.fontStyle = FontStyles.Bold; } if ((modifiers & ChatModifier.Clown) == ChatModifier.Clown) { bubbleText.font = fontClown; bubbleText.UpdateFontAsset(); } // Apply values UpdateChatBubbleSize(); chatBubble.SetActive(true); bubbleText.text = msg; }
/// <summary> /// Set and enable this ChatBubble /// </summary> public void SetupBubble(Transform _target, string msg, ChatModifier chatModifier = ChatModifier.None) { if (cam == null) { cam = Camera.main; } Vector3 viewPos = cam.WorldToScreenPoint(_target.position); transform.position = viewPos; gameObject.SetActive(true); target = _target; QueueMessages(msg, chatModifier); cancelSource = new CancellationTokenSource(); if (!showingDialogue) { StartCoroutine(ShowDialogue(cancelSource.Token)); } }
/// <summary> /// Broadcast a comm. message to chat, by machine. Useful for e.g. AutomatedAnnouncer. /// </summary> /// <param name="sentByMachine">Machine broadcasting the message</param> /// <param name="message">The message to broadcast.</param> /// <param name="channels">The channels to broadcast on.</param> /// <param name="chatModifiers">Chat modifiers to use e.g. ChatModifier.ColdlyState.</param> /// <param name="broadcasterName">Optional name for the broadcaster. Pulls name from GameObject if not used.</param> public static void AddCommMsgByMachineToChat( GameObject sentByMachine, string message, ChatChannel channels, ChatModifier chatModifiers = ChatModifier.None, string broadcasterName = default) { if (string.IsNullOrWhiteSpace(message)) { return; } var chatEvent = new ChatEvent { message = message, modifiers = chatModifiers, speaker = broadcasterName != default ? broadcasterName : sentByMachine.ExpensiveName(), position = sentByMachine.WorldPosServer(), channels = channels, originator = sentByMachine }; InvokeChatEvent(chatEvent); }
/// <summary> /// Sets the text, style and size of the bubble to match the message's modifier. /// </summary> /// <param name="msg"> Player's chat message </param> private void SetBubbleParameters(string msg, ChatModifier modifiers) { bubbleSize = PlayerPrefs.GetFloat(PlayerPrefKeys.ChatBubbleSize); bubbleText.fontStyle = FontStyles.Normal; bubbleText.font = fontDefault; // Determine type if ((modifiers & ChatModifier.Emote) == ChatModifier.Emote) { bubbleText.fontStyle = FontStyles.Italic; // TODO Differentiate emoting from whispering (e.g. rectangular box instead of speech bubble) } else if ((modifiers & ChatModifier.Whisper) == ChatModifier.Whisper) { bubbleSize = bubbleSize * bubbleSizeWhisper; bubbleText.fontStyle = FontStyles.Italic; // TODO Differentiate emoting from whispering (e.g. dotted line around text) } else if ((modifiers & ChatModifier.Sing) == ChatModifier.Sing) { bubbleSize = bubbleSize * bubbleSizeCaps; bubbleText.fontStyle = FontStyles.Italic; } else if ((modifiers & ChatModifier.Yell) == ChatModifier.Yell) { bubbleSize = bubbleSize * bubbleSizeCaps; bubbleText.fontStyle = FontStyles.Bold; } if ((modifiers & ChatModifier.Clown) == ChatModifier.Clown) { bubbleText.font = fontClown; bubbleText.UpdateFontAsset(); } // Apply values UpdateChatBubbleSize(); chatBubble.SetActive(true); bubbleText.text = msg; }
/// <summary> /// Display a chat bubble and make it follow a transform target /// </summary> /// <param name="msg">Text to show in the chat bubble</param> /// <param name="followTarget">The transform in the world for the bubble to follow</param> /// <param name="chatModifier">Any chat modifiers that need to be applied</param> public static void ShowAChatBubble(Transform followTarget, string msg, ChatModifier chatModifier = ChatModifier.None) { //TODO this will prevent emotes from appearing as speech. We should streamline it and simply don't use // the chat api when the message is an emote, instead generate an action message. if ((chatModifier & ChatModifier.Emote) == ChatModifier.Emote) { return; } var index = Instance.chatBubblePool.FindIndex(x => x.Target == followTarget); if (index != -1) { if (Instance.chatBubblePool[index].gameObject.activeInHierarchy) { Instance.chatBubblePool[index].AppendToBubble(msg, chatModifier); return; } } Instance.GetChatBubbleFromPool().SetupBubble(followTarget, msg, chatModifier); }
public ChatModifier GetCurrentChatModifiers() { ChatModifier modifiers = ChatModifier.None; if (playerMove.isGhost) { return(ChatModifier.None); } if (playerHealth.IsCrit) { return(ChatModifier.Crit); } //TODO add missing modifiers //TODO add if for being drunk //ChatModifier modifiers = ChatModifier.Drunk; if (JobType == JobType.CLOWN) { modifiers |= ChatModifier.Clown; } return(modifiers); }
/// <summary> /// Processes a message to be used in the chat log and chat bubbles. /// 1. Detects which modifiers should be present in the messages. /// - Some of the modifiers will come from the player being unconcious, being a clown, etc. /// - Other modifiers are voluntary, such as shouting. They normally cannot override involuntary modifiers. /// - Certain emotes override each other and will never be present at the same time. /// - Emote overrides whispering, and whispering overrides yelling. /// 2. Modifies the message to match the previously detected modifiers. /// - Stutters, honks, drunkenness, etc. are directly applied to the message. /// - The chat log and chat bubble may add minor changes to the text, such as narration ("Player says, ..."). /// </summary> /// <param name="sendByPlayer">The player sending the message. Used for detecting conciousness and occupation.</param> /// <param name="message">The chat message to process.</param> /// <returns>A tuple of the processed chat message and the detected modifiers.</returns> private static (string, ChatModifier) ProcessMessage(ConnectedPlayer sentByPlayer, string message) { ChatModifier chatModifiers = ChatModifier.None; // Modifier that will be returned in the end. ConsciousState playerConsciousState = ConsciousState.DEAD; if (sentByPlayer.Script == null) { return(message, chatModifiers); } if (sentByPlayer.Script.playerHealth != null) { playerConsciousState = sentByPlayer.Script.playerHealth.ConsciousState; } if (playerConsciousState == ConsciousState.UNCONSCIOUS || playerConsciousState == ConsciousState.DEAD) { // Only the Mute modifier matters if the player cannot speak. We can skip everything else. return(message, ChatModifier.Mute); } // Emote if (message.StartsWith("*") || message.StartsWith("/me ", true, CultureInfo.CurrentCulture)) { message = message.Replace("/me", ""); // note that there is no space here as compared to the above if message = message.Substring(1); // so that this substring can properly cut off both * and the space chatModifiers |= ChatModifier.Emote; } // Whisper else if (message.StartsWith("#") || message.StartsWith("/w ", true, CultureInfo.CurrentCulture)) { message = message.Replace("/w", ""); message = message.Substring(1); chatModifiers |= ChatModifier.Whisper; } // Sing else if (message.StartsWith("%") || message.StartsWith("/s ", true, CultureInfo.CurrentCulture)) { message = message.Replace("/s", ""); message = message.Substring(1); message = Sing(message); chatModifiers |= ChatModifier.Sing; } // Involuntaly whisper due to not being fully concious else if (playerConsciousState == ConsciousState.BARELY_CONSCIOUS) { chatModifiers |= ChatModifier.Whisper; } // Yell else if ((message == message.ToUpper(CultureInfo.InvariantCulture) && // Is it all caps? message.Any(char.IsLetter))) // AND does it contain at least one letter? { chatModifiers |= ChatModifier.Yell; } // Question else if (message.EndsWith("?")) { chatModifiers |= ChatModifier.Question; } // Exclaim else if (message.EndsWith("!")) { chatModifiers |= ChatModifier.Exclaim; } // Assign character trait speech mods //TODO Assigning from character creation for now, they exclude each others chatModifiers |= Instance.CharacterSpeech[sentByPlayer.Script.characterSettings.Speech]; //TODO Assign racial speech mods // Assign inventory speech mods chatModifiers |= sentByPlayer.Script.mind.inventorySpeechModifiers; /////// Process Speech mutations message = SpeechModManager.Instance.ApplyMod(chatModifiers, message); return(message, chatModifiers); }
/// <summary> /// This should only be called via UpdateChatMessage /// on the client. Do not use for anything else! /// </summary> public static void ProcessUpdateChatMessage(uint recipient, uint originator, string message, string messageOthers, ChatChannel channels, ChatModifier modifiers, string speaker) { //If there is a message in MessageOthers then determine //if it should be the main message or not. if (!string.IsNullOrEmpty(messageOthers)) { //This is not the originator so use the messageOthers if (recipient != originator) { message = messageOthers; } } if (GhostValidationRejection(originator, channels)) { return; } var msg = ProcessMessageFurther(message, speaker, channels, modifiers); Instance.addChatLogClient.Invoke(msg, channels); }
/// <summary> /// Processes message further for the chat log. /// Adds text styling, color and channel prefixes depending on the message and its modifiers. /// </summary> /// <returns>The chat message, formatted to suit the chat log.</returns> public static string ProcessMessageFurther(string message, string speaker, ChatChannel channels, ChatModifier modifiers) { //Skip everything if system message if (channels.HasFlag(ChatChannel.System)) { return(message); } //Skip everything in case of combat channel if (channels.HasFlag(ChatChannel.Combat)) { return(AddMsgColor(channels, $"<i>{message}</i>")); //POC } //Skip everything if it is an action or examine message or if it is a local message //without a speaker (which is used by machines) if (channels.HasFlag(ChatChannel.Examine) || channels.HasFlag(ChatChannel.Action) || channels.HasFlag(ChatChannel.Local) && string.IsNullOrEmpty(speaker)) { return(AddMsgColor(channels, $"<i>{message}</i>")); } // Skip everything if the message is a local warning if (channels.HasFlag(ChatChannel.Warning)) { return(AddMsgColor(channels, $"<i>{message}</i>")); } message = StripTags(message); //Check for emote. If found skip chat modifiers, make sure emote is only in Local channel if ((modifiers & ChatModifier.Emote) == ChatModifier.Emote) { // /me message channels = ChatChannel.Local; message = AddMsgColor(channels, $"<i><b>{speaker}</b> {message}</i>"); return(message); } //Check for OOC. If selected, remove all other channels and modifiers (could happen if UI f***s up or someone tampers with it) if (channels.HasFlag(ChatChannel.OOC)) { //ooc name quick fix var name = Regex.Replace(speaker, @"\t\n\r", ""); if (string.IsNullOrWhiteSpace(name)) { name = "nerd"; } message = AddMsgColor(channels, $"[ooc] <b>{speaker}: {message}</b>"); return(message); } //Ghosts don't get modifiers if (channels.HasFlag(ChatChannel.Ghost)) { string[] _ghostVerbs = { "cries", "moans" }; return(AddMsgColor(channels, $"[dead] <b>{speaker}</b> {_ghostVerbs.PickRandom()}: {message}")); } string verb = "says,"; if ((modifiers & ChatModifier.Mute) == ChatModifier.Mute) { return(""); } if ((modifiers & ChatModifier.Whisper) == ChatModifier.Whisper) { verb = "whispers,"; message = $"<i>{message}</i>"; } else if ((modifiers & ChatModifier.Sing) == ChatModifier.Sing) { verb = "sings,"; message += " ♫"; } else if ((modifiers & ChatModifier.Yell) == ChatModifier.Yell) { verb = "yells,"; message = $"<b>{message}</b>"; } else if ((modifiers & ChatModifier.State) == ChatModifier.State) { verb = "states,"; } else if ((modifiers & ChatModifier.ColdlyState) == ChatModifier.ColdlyState) { verb = "coldly states,"; } else if (message.EndsWith("!")) { verb = "exclaims,"; } else if (message.EndsWith("?")) { verb = "asks,"; } var chan = $"[{channels.ToString().ToLower().Substring(0, 3)}] "; if (channels.HasFlag(ChatChannel.Command)) { chan = "[cmd] "; } if (channels.HasFlag(ChatChannel.Local)) { chan = ""; } return(AddMsgColor(channels, $"{chan}<b>{speaker}</b> {verb}" // [cmd] Username says, + " " // Two hair spaces. This triggers Text-to-Speech. + "\"" + message + "\"")); // "This text will be spoken by TTS!" }