Example #1
0
        public static void InitializePlayer(NWPlayer player)
        {
            if (player == null)
            {
                throw new ArgumentNullException(nameof(player));
            }
            if (!player.IsPlayer)
            {
                return;
            }

            // Player is initialized but not in the DB. Wipe the tag and rerun them through initialization - something went wrong before.
            if (player.IsInitializedAsPlayer)
            {
                if (!DataService.Player.ExistsByID(player.GlobalID))
                {
                    SetTag(player, string.Empty);
                }
            }

            if (!player.IsInitializedAsPlayer)
            {
                player.DestroyAllInventoryItems();
                player.InitializePlayer();
                AssignCommand(player, () => _.TakeGoldFromCreature(GetGold(player), player, true));

                DelayCommand(0.5f, () =>
                {
                    GiveGoldToCreature(player, 100);
                });

                // Capture original stats before we level up the player.
                int str  = NWNXCreature.GetRawAbilityScore(player, AbilityType.Strength);
                int con  = NWNXCreature.GetRawAbilityScore(player, AbilityType.Constitution);
                int dex  = NWNXCreature.GetRawAbilityScore(player, AbilityType.Dexterity);
                int @int = NWNXCreature.GetRawAbilityScore(player, AbilityType.Intelligence);
                int wis  = NWNXCreature.GetRawAbilityScore(player, AbilityType.Wisdom);
                int cha  = NWNXCreature.GetRawAbilityScore(player, AbilityType.Charisma);

                // Take player to level 5 in NWN levels so that we have access to more HP slots
                GiveXPToCreature(player, 10000);

                for (int level = 1; level <= 5; level++)
                {
                    LevelUpHenchman(player, player.Class1);
                }

                // Set stats back to how they were on entry.
                NWNXCreature.SetRawAbilityScore(player, AbilityType.Strength, str);
                NWNXCreature.SetRawAbilityScore(player, AbilityType.Constitution, con);
                NWNXCreature.SetRawAbilityScore(player, AbilityType.Dexterity, dex);
                NWNXCreature.SetRawAbilityScore(player, AbilityType.Intelligence, @int);
                NWNXCreature.SetRawAbilityScore(player, AbilityType.Wisdom, wis);
                NWNXCreature.SetRawAbilityScore(player, AbilityType.Charisma, cha);

                NWItem knife = (CreateItemOnObject("survival_knife", player));
                knife.Name     = player.Name + "'s Survival Knife";
                knife.IsCursed = true;
                DurabilityService.SetMaxDurability(knife, 5);
                DurabilityService.SetDurability(knife, 5);

                NWItem book = (CreateItemOnObject("player_guide", player));
                book.Name     = player.Name + "'s Player Guide";
                book.IsCursed = true;

                NWItem dyeKit = (CreateItemOnObject("tk_omnidye", player));
                dyeKit.IsCursed = true;

                int numberOfFeats = NWNXCreature.GetFeatCount(player);
                for (int currentFeat = numberOfFeats; currentFeat >= 0; currentFeat--)
                {
                    NWNXCreature.RemoveFeat(player, NWNXCreature.GetFeatByIndex(player, currentFeat - 1));
                }

                NWNXCreature.AddFeatByLevel(player, Feat.ArmorProficiencyLight, 1);
                NWNXCreature.AddFeatByLevel(player, Feat.ArmorProficiencyMedium, 1);
                NWNXCreature.AddFeatByLevel(player, Feat.ArmorProficiencyHeavy, 1);
                NWNXCreature.AddFeatByLevel(player, Feat.ShieldProficiency, 1);
                NWNXCreature.AddFeatByLevel(player, Feat.WeaponProficiencyExotic, 1);
                NWNXCreature.AddFeatByLevel(player, Feat.WeaponProficiencyMartial, 1);
                NWNXCreature.AddFeatByLevel(player, Feat.WeaponProficiencySimple, 1);
                NWNXCreature.AddFeatByLevel(player, Feat.UncannyDodge1, 1);
                NWNXCreature.AddFeatByLevel(player, Feat.StructureManagementTool, 1);
                NWNXCreature.AddFeatByLevel(player, Feat.OpenRestMenu, 1);
                NWNXCreature.AddFeatByLevel(player, Feat.RenameCraftedItem, 1);
                NWNXCreature.AddFeatByLevel(player, Feat.ChatCommandTargeter, 1);

                foreach (var skillType in Enum.GetValues(typeof(Skill)))
                {
                    var skill = (Skill)skillType;
                    if (skill == Skill.Invalid || skill == Skill.AllSkills)
                    {
                        continue;
                    }

                    NWNXCreature.SetSkillRank(player, skill, 0);
                }
                SetFortitudeSavingThrow(player, 0);
                SetReflexSavingThrow(player, 0);
                SetWillSavingThrow(player, 0);

                var classType = GetClassByPosition(1, player);

                for (int index = 0; index <= 255; index++)
                {
                    NWNXCreature.RemoveKnownSpell(player, classType, 0, index);
                }

                Player entity = CreateDBPCEntity(player);
                DataService.SubmitDataChange(entity, DatabaseActionType.Insert);

                var skills = DataService.Skill.GetAll();
                foreach (var skill in skills)
                {
                    var pcSkill = new PCSkill
                    {
                        IsLocked = false,
                        SkillID  = skill.ID,
                        PlayerID = entity.ID,
                        Rank     = 0,
                        XP       = 0
                    };

                    DataService.SubmitDataChange(pcSkill, DatabaseActionType.Insert);
                }

                RaceService.ApplyDefaultAppearance(player);
                NWNXCreature.SetAlignmentLawChaos(player, 50);
                NWNXCreature.SetAlignmentGoodEvil(player, 50);
                BackgroundService.ApplyBackgroundBonuses(player);

                PlayerStatService.ApplyStatChanges(player, null, true);
                LanguageService.InitializePlayerLanguages(player);

                DelayCommand(1.0f, () => ApplyEffectToObject(DurationType.Instant, EffectHeal(999), player));

                InitializeHotBar(player);
            }
        }
Example #2
0
        private static void OnModuleNWNXChat()
        {
            ChatChannel channel = (ChatChannel)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 == ChatChannel.PlayerTalk ||
                channel == ChatChannel.PlayerWhisper ||
                channel == ChatChannel.PlayerParty ||
                channel == ChatChannel.PlayerShout;

            bool messageToDm = channel == ChatChannel.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 == ChatChannel.PlayerDM)
            {
                // Simply echo the message back to the player.
                NWNXChat.SendMessage((int)ChatChannel.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 == ChatChannel.PlayerShout && sender.IsPC &&
                GetLocalBool(sender, "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 == ChatChannel.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 == ChatChannel.PlayerShout)
            {
                recipients.AddRange(NWModule.Get().Players.Where(player => GetLocalBool(player, "DISPLAY_HOLONET") == true));
                recipients.AddRange(AppCache.ConnectedDMs);
            }
            // This is the normal party chat, plus everyone within 20 units of the sender.
            else if (channel == ChatChannel.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 == ChatChannel.PlayerTalk)
            {
                needsAreaCheck = true;
                distanceCheck  = 20.0f;
            }
            // Whisper - 4 units.
            else if (channel == ChatChannel.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 == ChatChannel.PlayerShout)
                {
                    finalMessage.Append("[Holonet] ");
                }
                else if (channel == ChatChannel.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(" } ");
                    }
                }

                var originalSender = sender;
                // temp set sender to hologram owner for holocoms
                if (GetIsObjectValid(HoloComService.GetHoloGramOwner(sender)) == true)
                {
                    sender = HoloComService.GetHoloGramOwner(sender);
                }

                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.
                RacialType race = (RacialType)_.GetRacialType(sender);
                if (race == RacialType.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.

                ChatChannel finalChannel = channel;

                if (channel == ChatChannel.PlayerShout || channel == ChatChannel.PlayerParty)
                {
                    finalChannel = ChatChannel.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 == ChatChannel.PlayerShout)
                {
                    finalMessageColoured = ColorTokenService.Custom(finalMessageColoured, 0, 180, 255);
                }
                else if (channel == ChatChannel.PlayerParty)
                {
                    finalMessageColoured = ColorTokenService.Orange(finalMessageColoured);
                }

                // set back to original sender, if it was changed by holocom connection
                sender = originalSender;

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

            MessageHub.Instance.Publish(new OnChatProcessed(sender, channel, isOOC));
        }
Example #3
0
        public static void InitializePlayer(NWPlayer player)
        {
            if (player == null)
            {
                throw new ArgumentNullException(nameof(player));
            }
            if (player.Object == null)
            {
                throw new ArgumentNullException(nameof(player.Object));
            }
            if (!player.IsPlayer)
            {
                return;
            }

            // Player is initialized but not in the DB. Wipe the tag and rerun them through initialization - something went wrong before.
            if (player.IsInitializedAsPlayer)
            {
                if (DataService.GetAll <Player>().SingleOrDefault(x => x.ID == player.GlobalID) == null)
                {
                    _.SetTag(player, string.Empty);
                }
            }

            if (!player.IsInitializedAsPlayer)
            {
                player.DestroyAllInventoryItems();
                player.InitializePlayer();
                _.AssignCommand(player, () => _.TakeGoldFromCreature(_.GetGold(player), player, 1));

                _.DelayCommand(0.5f, () =>
                {
                    _.GiveGoldToCreature(player, 100);
                });

                // Capture original stats before we level up the player.
                int str  = NWNXCreature.GetRawAbilityScore(player, ABILITY_STRENGTH);
                int con  = NWNXCreature.GetRawAbilityScore(player, ABILITY_CONSTITUTION);
                int dex  = NWNXCreature.GetRawAbilityScore(player, ABILITY_DEXTERITY);
                int @int = NWNXCreature.GetRawAbilityScore(player, ABILITY_INTELLIGENCE);
                int wis  = NWNXCreature.GetRawAbilityScore(player, ABILITY_WISDOM);
                int cha  = NWNXCreature.GetRawAbilityScore(player, ABILITY_CHARISMA);

                // Take player to level 5 in NWN levels so that we have access to more HP slots
                _.GiveXPToCreature(player, 10000);

                for (int level = 1; level <= 5; level++)
                {
                    _.LevelUpHenchman(player, player.Class1);
                }

                // Set stats back to how they were on entry.
                NWNXCreature.SetRawAbilityScore(player, ABILITY_STRENGTH, str);
                NWNXCreature.SetRawAbilityScore(player, ABILITY_CONSTITUTION, con);
                NWNXCreature.SetRawAbilityScore(player, ABILITY_DEXTERITY, dex);
                NWNXCreature.SetRawAbilityScore(player, ABILITY_INTELLIGENCE, @int);
                NWNXCreature.SetRawAbilityScore(player, ABILITY_WISDOM, wis);
                NWNXCreature.SetRawAbilityScore(player, ABILITY_CHARISMA, cha);

                NWItem knife = (_.CreateItemOnObject("survival_knife", player));
                knife.Name     = player.Name + "'s Survival Knife";
                knife.IsCursed = true;
                DurabilityService.SetMaxDurability(knife, 5);
                DurabilityService.SetDurability(knife, 5);

                NWItem book = (_.CreateItemOnObject("player_guide", player));
                book.Name     = player.Name + "'s Player Guide";
                book.IsCursed = true;

                NWItem dyeKit = (_.CreateItemOnObject("tk_omnidye", player));
                dyeKit.IsCursed = true;

                int numberOfFeats = NWNXCreature.GetFeatCount(player);
                for (int currentFeat = numberOfFeats; currentFeat >= 0; currentFeat--)
                {
                    NWNXCreature.RemoveFeat(player, NWNXCreature.GetFeatByIndex(player, currentFeat - 1));
                }

                NWNXCreature.AddFeatByLevel(player, FEAT_ARMOR_PROFICIENCY_LIGHT, 1);
                NWNXCreature.AddFeatByLevel(player, FEAT_ARMOR_PROFICIENCY_MEDIUM, 1);
                NWNXCreature.AddFeatByLevel(player, FEAT_ARMOR_PROFICIENCY_HEAVY, 1);
                NWNXCreature.AddFeatByLevel(player, FEAT_SHIELD_PROFICIENCY, 1);
                NWNXCreature.AddFeatByLevel(player, FEAT_WEAPON_PROFICIENCY_EXOTIC, 1);
                NWNXCreature.AddFeatByLevel(player, FEAT_WEAPON_PROFICIENCY_MARTIAL, 1);
                NWNXCreature.AddFeatByLevel(player, FEAT_WEAPON_PROFICIENCY_SIMPLE, 1);
                NWNXCreature.AddFeatByLevel(player, FEAT_UNCANNY_DODGE_1, 1);
                NWNXCreature.AddFeatByLevel(player, (int)CustomFeatType.StructureManagementTool, 1);
                NWNXCreature.AddFeatByLevel(player, (int)CustomFeatType.OpenRestMenu, 1);
                NWNXCreature.AddFeatByLevel(player, (int)CustomFeatType.RenameCraftedItem, 1);
                NWNXCreature.AddFeatByLevel(player, (int)CustomFeatType.ChatCommandTargeter, 1);

                for (int iCurSkill = 1; iCurSkill <= 27; iCurSkill++)
                {
                    NWNXCreature.SetSkillRank(player, iCurSkill - 1, 0);
                }
                _.SetFortitudeSavingThrow(player, 0);
                _.SetReflexSavingThrow(player, 0);
                _.SetWillSavingThrow(player, 0);

                int classID = _.GetClassByPosition(1, player);

                for (int index = 0; index <= 255; index++)
                {
                    NWNXCreature.RemoveKnownSpell(player, classID, 0, index);
                }

                Player entity = CreateDBPCEntity(player);
                DataService.SubmitDataChange(entity, DatabaseActionType.Insert);

                var skills = DataService.GetAll <Skill>();
                foreach (var skill in skills)
                {
                    var pcSkill = new PCSkill
                    {
                        IsLocked = false,
                        SkillID  = skill.ID,
                        PlayerID = entity.ID,
                        Rank     = 0,
                        XP       = 0
                    };

                    DataService.SubmitDataChange(pcSkill, DatabaseActionType.Insert);
                }

                RaceService.ApplyDefaultAppearance(player);
                NWNXCreature.SetAlignmentLawChaos(player, 50);
                NWNXCreature.SetAlignmentGoodEvil(player, 50);
                BackgroundService.ApplyBackgroundBonuses(player);

                PlayerStatService.ApplyStatChanges(player, null, true);
                LanguageService.InitializePlayerLanguages(player);

                _.DelayCommand(1.0f, () => _.ApplyEffectToObject(DURATION_TYPE_INSTANT, _.EffectHeal(999), player));

                InitializeHotBar(player);
            }
        }