Ejemplo n.º 1
0
        /// <summary>
        /// Call this on the NWNX OnChat event (not the OnPlayerChat event provided by base NWN).
        /// If a player is currently setting a "Seller Note", look for the text and apply it to their
        /// temporary market data object.
        /// </summary>
        private static void OnModuleNWNXChat()
        {
            NWPlayer player = NWNXChat.GetSender();

            if (!CanHandleChat(player))
            {
                return;
            }

            var model = GetPlayerMarketData(player);

            // Is the player specifying a seller note?
            if (!model.IsSettingSellerNote)
            {
                return;
            }
            model.IsSettingSellerNote = false;

            var message = NWNXChat.GetMessage();

            message          = message.Truncate(1024);
            model.SellerNote = message;

            player.FloatingText("Seller note set! Please click 'Refresh' to see the changes.");
            NWNXChat.SkipMessage();
        }
Ejemplo n.º 2
0
        private static void OnModuleNWNXChat()
        {
            NWPlayer pc      = NWNXChat.GetSender();
            string   newName = NWNXChat.GetMessage();

            if (!CanHandleChat(pc))
            {
                return;
            }

            NWNXChat.SkipMessage();
            NWItem renameItem = pc.GetLocalObject("CRAFT_RENAMING_ITEM_OBJECT");

            pc.DeleteLocalInt("CRAFT_RENAMING_ITEM");
            pc.DeleteLocalObject("CRAFT_RENAMING_ITEM_OBJECT");

            if (!renameItem.IsValid)
            {
                pc.SendMessage("Cannot find the item you were renaming.");
                return;
            }

            if (newName.Length < 3 || newName.Length > 64)
            {
                pc.SendMessage("Item names must be between 3 and 64 characters long.");
                return;
            }

            renameItem.Name = newName;

            pc.FloatingText("New name set!");
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Registers all of the NWNX event scripts.
        /// </summary>
        private static void RegisterNWNXEvents()
        {
            NWNXEvents.SubscribeEvent(NWNXEventType.StartCombatRoundBefore, "mod_on_attack");
            NWNXEvents.SubscribeEvent(NWNXEventType.ExamineObjectBefore, "mod_on_examine");
            NWNXEvents.SubscribeEvent(NWNXEventType.UseFeatBefore, "mod_on_usefeat");
            NWNXEvents.SubscribeEvent(NWNXEventType.UseItemBefore, "mod_on_useitem");
            NWNXEvents.SubscribeEvent(NWNXEventType.ItemEquipBefore, "mod_nwnx_equip");
            NWNXEvents.SubscribeEvent(NWNXEventType.ItemUnequipBefore, "mod_nwnx_unequip");

            NWNXChat.RegisterChatScript("mod_on_nwnxchat");
        }
Ejemplo n.º 4
0
        private static string BuildRegularLog()
        {
            var sender    = NWNXChat.GetSender();
            var channel   = NWNXChat.GetChannel();
            var message   = NWNXChat.GetMessage();
            var ipAddress = GetPCIPAddress(sender);
            var cdKey     = GetPCPublicCDKey(sender);
            var account   = GetPCPlayerName(sender);
            var pcName    = GetName(sender);

            var log = $"{pcName} - {account} - {cdKey} - {ipAddress} - {channel}: {message}";

            return(log);
        }
Ejemplo n.º 5
0
        private static void OnModuleNWNXChat()
        {
            NWPlayer player = NWNXChat.GetSender().Object;

            if (!CanHandleChat(player))
            {
                return;
            }
            string message = NWNXChat.GetMessage();

            NWNXChat.SkipMessage();

            player.SetLocalString("MESSAGE_BOARD_TEXT", message);
            player.SendMessage("Please click the 'Set Title' or 'Set Message' option in the menu.");
        }
Ejemplo n.º 6
0
        private static void OnModuleNWNXChat()
        {
            NWPlayer player = NWNXChat.GetSender().Object;

            if (!CanHandleChat(player))
            {
                return;
            }
            string message = NWNXChat.GetMessage();

            NWNXChat.SkipMessage();

            message = message.Truncate(50);
            player.SetLocalString("RENAMED_ITEM_NEW_NAME", message);
            player.SendMessage("Please click 'Refresh' to see changes, then select 'Change Name' to confirm the changes.");
        }
Ejemplo n.º 7
0
        private static string BuildTellLog()
        {
            var sender            = NWNXChat.GetSender();
            var receiver          = NWNXChat.GetTarget();
            var channel           = NWNXChat.GetChannel();
            var message           = NWNXChat.GetMessage();
            var senderIPAddress   = GetPCIPAddress(sender);
            var senderCDKey       = GetPCPublicCDKey(sender);
            var senderAccount     = GetPCPlayerName(sender);
            var senderPCName      = GetName(sender);
            var receiverIPAddress = GetPCIPAddress(receiver);
            var receiverCDKey     = GetPCPublicCDKey(receiver);
            var receiverAccount   = GetPCPlayerName(receiver);
            var receiverPCName    = GetName(receiver);

            var log = $"{senderPCName} - {senderAccount} - {senderCDKey} - {senderIPAddress} - {channel} (SENT TO {receiverPCName} - {receiverAccount} - {receiverCDKey} - {receiverIPAddress}): {message}";

            return(log);
        }
Ejemplo n.º 8
0
        // ReSharper disable once UnusedMember.Local
        public static void Main()
        {
            string nowString = DateTime.UtcNow.ToString("yyyy-MM-dd hh:mm:ss");

            Console.WriteLine(nowString + ": Module OnLoad executing...");

            using (new Profiler(nameof(mod_on_load) + ":DatabaseMigrator"))
            {
                DatabaseMigrationRunner.Start();
            }

            using (new Profiler(nameof(mod_on_load) + ":DBBackgroundThread"))
            {
                Console.WriteLine("Starting background thread manager...");
                BackgroundThreadManager.Start();
            }

            using (new Profiler(nameof(mod_on_load) + ":SetEventScripts"))
            {
                NWNXChat.RegisterChatScript("mod_on_nwnxchat");
                SetModuleEventScripts();
                SetAreaEventScripts();
                SetWeaponSettings();
            }
            // Bioware default
            _.ExecuteScript("x2_mod_def_load", _.OBJECT_SELF);

            using (new Profiler(nameof(mod_on_load) + ":RegisterSubscribeEvents"))
            {
                RegisterServiceSubscribeEvents();
            }

            ScriptService.Initialize();
            MessageHub.Instance.Publish(new OnModuleLoad());

            nowString = DateTime.UtcNow.ToString("yyyy-MM-dd hh:mm:ss");
            Console.WriteLine(nowString + ": Module OnLoad finished!");
        }
Ejemplo n.º 9
0
        public static void Main()
        {
            var    channel = NWNXChat.GetChannel();
            string log;

            // We don't log server messages because there isn't a good way to filter them.
            if (channel == NWNXChatChannel.ServerMessage)
            {
                return;
            }

            if (channel == NWNXChatChannel.DMTell ||
                channel == NWNXChatChannel.PlayerTell)
            {
                log = BuildTellLog();
            }
            else
            {
                log = BuildRegularLog();
            }

            Audit.Write(AuditGroup.Chat, log);
        }
Ejemplo n.º 10
0
        private static void OnModuleNWNXChat()
        {
            ChatChannelType channel = (ChatChannelType)NWNXChat.GetChannel();

            // So we're going to play with a couple of channels here.

            // - PlayerTalk, PlayerWhisper, PlayerParty, and PlayerShout are all IC channels. These channels
            //   are subject to emote colouring and language translation. (see below for more info).
            // - PlayerParty is an IC channel with special behaviour. Those outside of the party but within
            //   range may listen in to the party chat. (see below for more information).
            // - PlayerShout sends a holocom message server-wide through the DMTell channel.
            // - PlayerDM echoes back the message received to the sender.

            bool inCharacterChat =
                channel == ChatChannelType.PlayerTalk ||
                channel == ChatChannelType.PlayerWhisper ||
                channel == ChatChannelType.PlayerParty ||
                channel == ChatChannelType.PlayerShout;

            bool messageToDm = channel == ChatChannelType.PlayerDM;

            if (!inCharacterChat && !messageToDm)
            {
                // We don't much care about traffic on the other channels.
                return;
            }

            NWObject sender  = NWNXChat.GetSender();
            string   message = NWNXChat.GetMessage().Trim();

            if (string.IsNullOrWhiteSpace(message))
            {
                // We can't handle empty messages, so skip it.
                return;
            }

            if (ChatCommandService.CanHandleChat(sender, message) ||
                BaseService.CanHandleChat(sender) ||
                CraftService.CanHandleChat(sender) ||
                MarketService.CanHandleChat(sender.Object) ||
                MessageBoardService.CanHandleChat(sender) ||
                ItemService.CanHandleChat(sender))
            {
                // This will be handled by other services, so just bail.
                return;
            }

            if (channel == ChatChannelType.PlayerDM)
            {
                // Simply echo the message back to the player.
                NWNXChat.SendMessage((int)ChatChannelType.ServerMessage, "(Sent to DM) " + message, sender, sender);
                return;
            }

            // At this point, every channel left is one we want to manually handle.
            NWNXChat.SkipMessage();

            // If this is a shout message, and the holonet is disabled, we disallow it.
            if (channel == ChatChannelType.PlayerShout && sender.IsPC &&
                sender.GetLocalInt("DISPLAY_HOLONET") == FALSE)
            {
                NWPlayer player = sender.Object;
                player.SendMessage("You have disabled the holonet and cannot send this message.");
                return;
            }

            List <ChatComponent> chatComponents;

            // Quick early out - if we start with "//" or "((", this is an OOC message.
            bool isOOC = false;

            if (message.Length >= 2 && (message.Substring(0, 2) == "//" || message.Substring(0, 2) == "(("))
            {
                ChatComponent component = new ChatComponent
                {
                    m_Text         = message,
                    m_CustomColour = true,
                    m_ColourRed    = 64,
                    m_ColourGreen  = 64,
                    m_ColourBlue   = 64,
                    m_Translatable = false
                };

                chatComponents = new List <ChatComponent> {
                    component
                };

                if (channel == ChatChannelType.PlayerShout)
                {
                    _.SendMessageToPC(sender, "Out-of-character messages cannot be sent on the Holonet.");
                    return;
                }

                isOOC = true;
            }
            else
            {
                if (EmoteStyleService.GetEmoteStyle(sender) == EmoteStyle.Regular)
                {
                    chatComponents = SplitMessageIntoComponents_Regular(message);
                }
                else
                {
                    chatComponents = SplitMessageIntoComponents_Novel(message);
                }

                // For any components with colour, set the emote colour.
                foreach (ChatComponent component in chatComponents)
                {
                    if (component.m_CustomColour)
                    {
                        component.m_ColourRed   = 0;
                        component.m_ColourGreen = 255;
                        component.m_ColourBlue  = 0;
                    }
                }
            }

            // Now, depending on the chat channel, we need to build a list of recipients.
            bool  needsAreaCheck = false;
            float distanceCheck  = 0.0f;

            // The sender always wants to see their own message.
            List <NWObject> recipients = new List <NWObject> {
                sender
            };

            // This is a server-wide holonet message (that receivers can toggle on or off).
            if (channel == ChatChannelType.PlayerShout)
            {
                recipients.AddRange(NWModule.Get().Players.Where(player => player.GetLocalInt("DISPLAY_HOLONET") == TRUE));
                recipients.AddRange(AppCache.ConnectedDMs);
            }
            // This is the normal party chat, plus everyone within 20 units of the sender.
            else if (channel == ChatChannelType.PlayerParty)
            {
                // Can an NPC use the playerparty channel? I feel this is safe ...
                NWPlayer player = sender.Object;
                recipients.AddRange(player.PartyMembers.Cast <NWObject>().Where(x => x != sender));
                recipients.AddRange(AppCache.ConnectedDMs);

                needsAreaCheck = true;
                distanceCheck  = 20.0f;
            }
            // Normal talk - 20 units.
            else if (channel == ChatChannelType.PlayerTalk)
            {
                needsAreaCheck = true;
                distanceCheck  = 20.0f;
            }
            // Whisper - 4 units.
            else if (channel == ChatChannelType.PlayerWhisper)
            {
                needsAreaCheck = true;
                distanceCheck  = 4.0f;
            }

            if (needsAreaCheck)
            {
                recipients.AddRange(sender.Area.Objects.Where(obj => obj.IsPC && _.GetDistanceBetween(sender, obj) <= distanceCheck));
                recipients.AddRange(AppCache.ConnectedDMs.Where(dm => dm.Area == sender.Area && _.GetDistanceBetween(sender, dm) <= distanceCheck));
            }

            // Now we have a list of who is going to actually receive a message, we need to modify
            // the message for each recipient then dispatch them.

            foreach (NWObject obj in recipients.Distinct())
            {
                // Generate the final message as perceived by obj.

                StringBuilder finalMessage = new StringBuilder();

                if (channel == ChatChannelType.PlayerShout)
                {
                    finalMessage.Append("[Holonet] ");
                }
                else if (channel == ChatChannelType.PlayerParty)
                {
                    finalMessage.Append("[Comms] ");

                    if (obj.IsDM)
                    {
                        // Convenience for DMs - append the party members.
                        finalMessage.Append("{ ");

                        int               count        = 0;
                        NWPlayer          player       = sender.Object;
                        List <NWCreature> partyMembers = player.PartyMembers.ToList();

                        foreach (NWCreature otherPlayer in partyMembers)
                        {
                            string name = otherPlayer.Name;
                            finalMessage.Append(name.Substring(0, Math.Min(name.Length, 10)));

                            ++count;

                            if (count >= 3)
                            {
                                finalMessage.Append(", ...");
                                break;
                            }
                            else if (count != partyMembers.Count)
                            {
                                finalMessage.Append(",");
                            }
                        }

                        finalMessage.Append(" } ");
                    }
                }

                SkillType language = LanguageService.GetActiveLanguage(sender);

                // Wookiees cannot speak any other language (but they can understand them).
                // Swap their language if they attempt to speak in any other language.
                CustomRaceType race = (CustomRaceType)_.GetRacialType(sender);
                if (race == CustomRaceType.Wookiee && language != SkillType.Shyriiwook)
                {
                    LanguageService.SetActiveLanguage(sender, SkillType.Shyriiwook);
                    language = SkillType.Shyriiwook;
                }

                int  colour = LanguageService.GetColour(language);
                byte r      = (byte)(colour >> 24 & 0xFF);
                byte g      = (byte)(colour >> 16 & 0xFF);
                byte b      = (byte)(colour >> 8 & 0xFF);

                if (language != SkillType.Basic)
                {
                    string languageName = LanguageService.GetName(language);
                    finalMessage.Append(ColorTokenService.Custom($"[{languageName}] ", r, g, b));
                }

                foreach (ChatComponent component in chatComponents)
                {
                    string text = component.m_Text;

                    if (component.m_Translatable && language != SkillType.Basic)
                    {
                        text = LanguageService.TranslateSnippetForListener(sender, obj.Object, language, component.m_Text);

                        if (colour != 0)
                        {
                            text = ColorTokenService.Custom(text, r, g, b);
                        }
                    }

                    if (component.m_CustomColour)
                    {
                        text = ColorTokenService.Custom(text, component.m_ColourRed, component.m_ColourGreen, component.m_ColourBlue);
                    }

                    finalMessage.Append(text);
                }

                // Dispatch the final message - method depends on the original chat channel.
                // - Shout and party is sent as DMTalk. We do this to get around the restriction that
                //   the PC needs to be in the same area for the normal talk channel.
                //   We could use the native channels for these but the [shout] or [party chat] labels look silly.
                // - Talk and whisper are sent as-is.

                ChatChannelType finalChannel = channel;

                if (channel == ChatChannelType.PlayerShout || channel == ChatChannelType.PlayerParty)
                {
                    finalChannel = ChatChannelType.DMTalk;
                }

                // There are a couple of colour overrides we want to use here.
                // - One for holonet (shout).
                // - One for comms (party chat).

                string finalMessageColoured = finalMessage.ToString();

                if (channel == ChatChannelType.PlayerShout)
                {
                    finalMessageColoured = ColorTokenService.Custom(finalMessageColoured, 0, 180, 255);
                }
                else if (channel == ChatChannelType.PlayerParty)
                {
                    finalMessageColoured = ColorTokenService.Orange(finalMessageColoured);
                }

                NWNXChat.SendMessage((int)finalChannel, finalMessageColoured, sender, obj);
            }

            MessageHub.Instance.Publish(new OnChatProcessed(sender, channel, isOOC));
        }
Ejemplo n.º 11
0
        private static void OnModuleNWNXChat()
        {
            NWPlayer sender = OBJECT_SELF;

            if (!sender.IsPlayer && !sender.IsDM)
            {
                return;
            }
            string text = NWNXChat.GetMessage();

            if (string.IsNullOrWhiteSpace(text))
            {
                return;
            }

            var      mode          = NWNXChat.GetChannel();
            int      channel       = ConvertNWNXChatChannelIDToDatabaseID(mode);
            NWObject recipient     = NWNXChat.GetTarget();
            var      channelEntity = DataService.ChatChannel.GetByID(channel);

            // Sender - should always have this data.
            string senderCDKey       = GetPCPublicCDKey(sender.Object);
            string senderAccountName = sender.Name;
            Guid?  senderPlayerID    = null;
            string senderDMName      = null;

            // DMs do not have PlayerIDs so store their name in another field.
            if (sender.IsDM)
            {
                senderDMName = "[DM: " + sender.Name + " (" + senderCDKey + ")]";
            }
            else
            {
                senderPlayerID = sender.GlobalID;
            }

            // Receiver - may or may not have the data.

            string receiverCDKey       = null;
            string receiverAccountName = null;
            Guid?  receiverPlayerID    = null;
            string receiverDMName      = null;

            if (recipient.IsValid)
            {
                receiverCDKey       = GetPCPublicCDKey(recipient.Object);
                receiverAccountName = recipient.Name;

                // DMs do not have PlayerIDs so store their name in another field.
                if (recipient.IsDM)
                {
                    receiverDMName = "[DM: " + recipient.Name + " (" + senderCDKey + ")]";
                }
                else
                {
                    receiverPlayerID = recipient.GlobalID;
                }
            }

            ChatLog entity = new ChatLog
            {
                Message             = text,
                SenderCDKey         = senderCDKey,
                SenderAccountName   = senderAccountName,
                SenderPlayerID      = senderPlayerID,
                SenderDMName        = senderDMName,
                ReceiverCDKey       = receiverCDKey,
                ReceiverAccountName = receiverAccountName,
                ReceiverPlayerID    = receiverPlayerID,
                ReceiverDMName      = receiverDMName,
                ChatChannelID       = channelEntity.ID,
                DateSent            = DateTime.UtcNow
            };

            // Bypass the caching logic
            DataService.DataQueue.Enqueue(new DatabaseAction(entity, DatabaseActionType.Insert));
        }
Ejemplo n.º 12
0
        private static void OnModuleNWNXChat()
        {
            NWPlayer sender          = Object.OBJECT_SELF;
            string   originalMessage = NWNXChat.GetMessage().Trim();

            if (!CanHandleChat(sender, originalMessage))
            {
                return;
            }

            var split = originalMessage.Split(' ').ToList();

            // Commands with no arguments won't be split, so if we didn't split anything then add the command to the split list manually.
            if (split.Count <= 0)
            {
                split.Add(originalMessage);
            }

            split[0] = split[0].ToLower();
            string command = split[0].Substring(1, split[0].Length - 1);

            split.RemoveAt(0);

            NWNXChat.SkipMessage();

            if (!IsChatCommandRegistered(command))
            {
                sender.SendMessage(ColorTokenService.Red("Invalid chat command. Use '/help' to get a list of available commands."));
                return;
            }

            IChatCommand chatCommand = GetChatCommandHandler(command);
            string       args        = string.Join(" ", split);

            if (!chatCommand.RequiresTarget)
            {
                ProcessChatCommand(chatCommand, sender, null, null, args);
            }
            else
            {
                string error = chatCommand.ValidateArguments(sender, split.ToArray());
                if (!string.IsNullOrWhiteSpace(error))
                {
                    sender.SendMessage(error);
                    return;
                }

                sender.SetLocalString("CHAT_COMMAND", command);
                sender.SetLocalString("CHAT_COMMAND_ARGS", args);
                sender.SendMessage("Please use your 'Chat Command Targeter' feat to select the target of this chat command.");

                if (_.GetHasFeat((int)CustomFeatType.ChatCommandTargeter, sender) == FALSE || sender.IsDM)
                {
                    NWNXCreature.AddFeatByLevel(sender, (int)CustomFeatType.ChatCommandTargeter, 1);

                    if (sender.IsDM)
                    {
                        var qbs = NWNXPlayer.GetQuickBarSlot(sender, 11);
                        if (qbs.ObjectType == QuickBarSlotType.Empty)
                        {
                            NWNXPlayer.SetQuickBarSlot(sender, 11, NWNXPlayerQuickBarSlot.UseFeat((int)CustomFeatType.ChatCommandTargeter));
                        }
                    }
                }
            }
        }