コード例 #1
0
    /// <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);
    }
コード例 #2
0
    /// <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));
    }
コード例 #3
0
    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);
    }
コード例 #4
0
ファイル: ChatIcon.cs プロジェクト: ynot01/unitystation
    /// <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());
    }
コード例 #5
0
    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);
        }
    }
コード例 #6
0
        /// <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);
        }
コード例 #7
0
 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);
 }
コード例 #8
0
    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());
        }
    }
コード例 #9
0
ファイル: ChatEvent.cs プロジェクト: svensis/unitystation
    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);
    }
コード例 #10
0
    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);
    }
コード例 #11
0
    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);
    }
コード例 #12
0
    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);
    }
コード例 #13
0
 public void ToggleChatIcon(bool toggle, ChatModifier chatModifier)
 {
     if (toggle)
     {
         TurnOnTalkIcon(chatModifier);
     }
     else
     {
         TurnOffTalkIcon();
     }
 }
コード例 #14
0
    public string ApplyMod(ChatModifier modifiers, string message)
    {
        foreach (var kvp in speechModifier)
        {
            if (modifiers.HasFlag(kvp.Key))
            {
                message = kvp.Value.ProcessMessage(message);
            }
        }

        return(message);
    }
コード例 #15
0
    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);
        }
    }
コード例 #16
0
    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);
    }
コード例 #17
0
    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;
    }
コード例 #18
0
 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);
     }
 }
コード例 #19
0
    /// <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);
    }
コード例 #20
0
        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);
        }
コード例 #21
0
        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);
        }
コード例 #22
0
    /// <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;
    }
コード例 #23
0
    /// <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));
        }
    }
コード例 #24
0
ファイル: Chat.cs プロジェクト: Wrackbang/unitystation
    /// <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);
    }
コード例 #25
0
    /// <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;
    }
コード例 #26
0
    /// <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);
    }
コード例 #27
0
    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);
    }
コード例 #28
0
    /// <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);
    }
コード例 #29
0
    /// <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);
    }
コード例 #30
0
    /// <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!"
    }