Beispiel #1
0
        private static void RemoveWeaponPenalties(NWItem oItem)
        {
            SkillType skillType = ItemService.GetSkillTypeForItem(oItem);

            if (skillType == SkillType.Unknown ||
                skillType == SkillType.HeavyArmor ||
                skillType == SkillType.LightArmor ||
                skillType == SkillType.ForceArmor ||
                skillType == SkillType.Shields)
            {
                return;
            }

            foreach (ItemProperty ip in oItem.ItemProperties)
            {
                string tag = _.GetItemPropertyTag(ip);
                if (tag == IPWeaponPenaltyTag)
                {
                    _.RemoveItemProperty(oItem.Object, ip);
                }
            }
        }
Beispiel #2
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));
        }
        public static void ApplyComponentBonus(NWItem product, ItemProperty sourceIP)
        {
            ComponentBonusType bonusType = (ComponentBonusType)_.GetItemPropertySubType(sourceIP);
            int          amount          = _.GetItemPropertyCostTableValue(sourceIP);
            ItemProperty prop            = null;
            string       sourceTag       = string.Empty;
            int          attackBonus     = 0;

            // A note about the sourceTags:
            // It's not currently possible to create custom item properties on items. To get around this,
            // we look in an inaccessible container which holds the custom item properties. Then, we get the
            // item that has the item property we want. From there we take that item property and copy it to
            // the crafted item.
            // This is a really roundabout way to do it, but it's the only option for now. Hopefully a feature to
            // directly add the item properties comes in to NWNX in the future.
            // 2019-06-12: Directly modifying item properties is possible now but I'm not going to do a refactor until later.
            //             Anyone interested in working on this let me know and I can point you in the right direction. - Z
            for (int x = 1; x <= amount; x++)
            {
                switch (bonusType)
                {
                case ComponentBonusType.ModSocketRed:
                    sourceTag = "rslot_red";
                    break;

                case ComponentBonusType.ModSocketBlue:
                    sourceTag = "rslot_blue";
                    break;

                case ComponentBonusType.ModSocketGreen:
                    sourceTag = "rslot_green";
                    break;

                case ComponentBonusType.ModSocketYellow:
                    sourceTag = "rslot_yellow";
                    break;

                case ComponentBonusType.ModSocketPrismatic:
                    sourceTag = "rslot_prismatic";
                    break;

                case ComponentBonusType.DurabilityUp:
                    var maxDur = DurabilityService.GetMaxDurability(product) + amount;
                    DurabilityService.SetMaxDurability(product, maxDur);
                    DurabilityService.SetDurability(product, maxDur);
                    break;

                case ComponentBonusType.ChargesUp:
                    product.Charges += amount;
                    break;

                case ComponentBonusType.ACUp:
                    product.CustomAC += amount;
                    break;

                case ComponentBonusType.HarvestingUp:
                    product.HarvestingBonus += amount;
                    break;

                case ComponentBonusType.CooldownRecoveryUp:
                    product.CooldownRecovery += amount;
                    break;

                case ComponentBonusType.ArmorsmithUp:
                    product.CraftBonusArmorsmith += amount;
                    break;

                case ComponentBonusType.WeaponsmithUp:
                    product.CraftBonusWeaponsmith += amount;
                    break;

                case ComponentBonusType.CookingUp:
                    product.CraftBonusCooking += amount;
                    break;

                case ComponentBonusType.EngineeringUp:
                    product.CraftBonusEngineering += amount;
                    break;

                case ComponentBonusType.FabricationUp:
                    product.CraftBonusFabrication += amount;
                    break;

                case ComponentBonusType.HPUp:
                    product.HPBonus += amount;
                    break;

                case ComponentBonusType.FPUp:
                    product.FPBonus += amount;
                    break;

                case ComponentBonusType.EnmityUp:
                    product.EnmityRate += amount;
                    break;

                case ComponentBonusType.EnmityDown:
                    product.EnmityRate -= amount;
                    break;

                case ComponentBonusType.LuckUp:
                    product.LuckBonus += amount;
                    break;

                case ComponentBonusType.MeditateUp:
                    product.MeditateBonus += amount;
                    break;

                case ComponentBonusType.RestUp:
                    product.RestBonus += amount;
                    break;

                case ComponentBonusType.MedicineUp:
                    product.MedicineBonus += amount;
                    break;

                case ComponentBonusType.HPRegenUp:
                    product.HPRegenBonus += amount;
                    break;

                case ComponentBonusType.FPRegenUp:
                    product.FPRegenBonus += amount;
                    break;

                case ComponentBonusType.BaseAttackBonusUp:
                    product.BaseAttackBonus += amount;
                    break;

                case ComponentBonusType.SneakAttackUp:
                    product.SneakAttackBonus += amount;
                    break;

                case ComponentBonusType.DamageUp:
                    product.DamageBonus += amount;
                    break;

                case ComponentBonusType.StructureBonusUp:
                    product.StructureBonus += amount;
                    break;

                case ComponentBonusType.StrengthUp:
                    product.StrengthBonus += amount;
                    break;

                case ComponentBonusType.DexterityUp:
                    product.DexterityBonus += amount;
                    break;

                case ComponentBonusType.ConstitutionUp:
                    product.ConstitutionBonus += amount;
                    break;

                case ComponentBonusType.WisdomUp:
                    product.WisdomBonus += amount;
                    break;

                case ComponentBonusType.IntelligenceUp:
                    product.IntelligenceBonus += amount;
                    break;

                case ComponentBonusType.CharismaUp:
                    product.CharismaBonus += amount;
                    break;

                case ComponentBonusType.AttackBonusUp:
                    attackBonus += amount;
                    break;

                case ComponentBonusType.DurationUp:
                    product.DurationBonus += amount;
                    break;

                case ComponentBonusType.ScanningUp:
                    product.ScanningBonus += amount;
                    break;

                case ComponentBonusType.ScavengingUp:
                    product.ScavengingBonus += amount;
                    break;

                case ComponentBonusType.PilotingUp:
                    product.PilotingBonus += amount;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                if (!string.IsNullOrWhiteSpace(sourceTag))
                {
                    prop = ItemService.GetCustomItemPropertyByItemTag(sourceTag);
                }

                if (prop == null)
                {
                    return;
                }

                BiowareXP2.IPSafeAddItemProperty(product, prop, 0.0f, AddItemPropertyPolicy.IgnoreExisting, true, true);
            }

            // Attack bonus is aggregated into one item property, ensuring that the amount doesn't go over 20.
            if (attackBonus > 0)
            {
                // Look for existing properties, get the value and add it. Then remove that item property.
                foreach (var ip in product.ItemProperties)
                {
                    if (_.GetItemPropertyType(ip) == _.ITEM_PROPERTY_ATTACK_BONUS)
                    {
                        amount       = _.GetItemPropertyCostTableValue(ip);
                        attackBonus += amount;

                        _.RemoveItemProperty(product, ip);
                    }
                }

                // Clamp bonus to 20.
                if (attackBonus > 20)
                {
                    attackBonus = 20;
                }

                // Time to add the new item property.
                prop = _.ItemPropertyAttackBonus(attackBonus);
                BiowareXP2.IPSafeAddItemProperty(product, prop, 0.0f, AddItemPropertyPolicy.ReplaceExisting, false, false);
            }
        }
Beispiel #4
0
        public static Tuple <ItemProperty, int> GetRandomComponentBonusIP(ResourceQuality quality)
        {
            string[] normalIP =
            {
                "compbon_arm1",         // Armorsmith 1
                "compbon_cspd1",        // Cooldown Recovery 1
                "compbon_charges1",     // Charges 1
                //"compbon_cooking1",     // Cooking 1
                "compbon_dmg1",         // Damage 1
                "compbon_eng1",         // Engineering 1
                "compbon_enmdown1",     // Enmity Down 1
                "compbon_harv1",        // Harvesting 1
                "compbon_wpn1",         // Weaponsmith 1
                "compbon_hp2",          // Hit Points 2
                "compbon_fp2",          // Force Points 2
                "compbon_enmup1",       // Enmity Up 1
                "compbon_med1",         // Meditate 1
                "compbon_faid1",        // Medicine 1
                "compbon_fab1",         // Fabrication 1
                "compbon_scanup1",      // Scanning 1
                "compbon_rest1",        // Rest 1
                "compbon_ab1"           // Attack Bonus 1
            };

            string[] highIP =
            {
                "compbon_arm2",         // Armorsmith 2
                "compbon_cspd2",        // Cooldown Recovery 2
                "compbon_charges2",     // Charges 2
                //"compbon_cooking2",     // Cooking 2
                "compbon_dmg2",         // Damage 2
                "compbon_eng2",         // Engineering 2
                "compbon_enmdown2",     // Enmity Down 2
                "compbon_harv2",        // Harvesting 2
                "compbon_wpn2",         // Weaponsmith 2
                "compbon_hp4",          // Hit Points 4
                "compbon_fp4",          // Force Points 4
                "compbon_enmup2",       // Enmity Up 2
                "compbon_luck1",        // Luck 1
                "compbon_med2",         // Meditate 2
                "compbon_faid2",        // Medicine 2
                "compbon_hpregen1",     // HP Regen 1
                "compbon_fpregen1",     // FP Regen 1
                "compbon_snkatk1",      // Sneak Attack 1
                "compbon_fab2",         // Fabrication 2
                "compbon_scanup2",      // Scanning 2
                "compbon_rest2",        // Rest 2
                "compbon_str1",         // Strength 1
                "compbon_dex1",         // Dexterity 1
                "compbon_con1",         // Constitution 1
                "compbon_wis1",         // Wisdom 1
                "compbon_int1",         // Intelligence 1
                "compbon_cha1",         // Charisma 1
                "compbon_ab2",          // Attack Bonus 2
                "compbon_scavup1"       // Scavenging 1
            };

            string[] veryHighIP =
            {
                "compbon_arm3",         // Armorsmith 3
                "compbon_cspd3",        // Cooldown Recovery 3
                //"compbon_cooking3",     // Cooking 3
                "compbon_charges3",     // Charges 3
                "compbon_dmg3",         // Damage 3
                "compbon_eng3",         // Engineering 3
                "compbon_enmdown3",     // Enmity Down 3
                "compbon_harv3",        // Harvesting 3
                "compbon_wpn3",         // Weaponsmith 3
                "compbon_hp6",          // Hit Points 6
                "compbon_fp6",          // Force Points 6
                "compbon_enmup3",       // Enmity Up 3
                "compbon_luck2",        // Luck 2
                "compbon_med3",         // Meditate 3
                "compbon_faid3",        // Medicine 3
                "compbon_hpregen2",     // HP Regen 2
                "compbon_fpregen2",     // FP Regen 2
                "compbon_snkatk2",      // Sneak Attack 2
                "compbon_fab3",         // Fabrication 3
                "compbon_scanup3",      // Scanning 3
                "compbon_rest3",        // Rest 3
                "compbon_str2",         // Strength 2
                "compbon_dex2",         // Dexterity 2
                "compbon_con2",         // Constitution 2
                "compbon_wis2",         // Wisdom 2
                "compbon_int2",         // Intelligence 2
                "compbon_cha2",         // Charisma 2
                "compbon_ab3",          // Attack Bonus 3
                "compbon_scavup2"       // Scavenging 2
            };

            string[] setToUse;

            switch (quality)
            {
            case ResourceQuality.Low:
            case ResourceQuality.Normal:
                setToUse = normalIP;
                break;

            case ResourceQuality.High:
                setToUse = highIP;
                break;

            case ResourceQuality.VeryHigh:
                setToUse = veryHighIP;
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(quality), quality, null);
            }

            int    index   = RandomService.Random(0, setToUse.Length - 1);
            string itemTag = setToUse[index];

            return(new Tuple <ItemProperty, int>(ItemService.GetCustomItemPropertyByItemTag(itemTag), Colorize(itemTag)));
        }
Beispiel #5
0
        private static int CalculateBAB(NWPlayer oPC, NWItem ignoreItem, EffectiveItemStats stats)
        {
            NWItem weapon = oPC.RightHand;

            // The unequip event fires before the item is actually unequipped, so we need
            // to have additional checks to make sure we're not getting the weapon that's about to be
            // unequipped.
            if (weapon.Equals(ignoreItem))
            {
                weapon = null;
                NWItem offHand = oPC.LeftHand;

                if (offHand.CustomItemType == CustomItemType.Vibroblade ||
                    offHand.CustomItemType == CustomItemType.FinesseVibroblade ||
                    offHand.CustomItemType == CustomItemType.Baton ||
                    offHand.CustomItemType == CustomItemType.HeavyVibroblade ||
                    offHand.CustomItemType == CustomItemType.Saberstaff ||
                    offHand.CustomItemType == CustomItemType.Polearm ||
                    offHand.CustomItemType == CustomItemType.TwinBlade ||
                    offHand.CustomItemType == CustomItemType.MartialArtWeapon ||
                    offHand.CustomItemType == CustomItemType.BlasterPistol ||
                    offHand.CustomItemType == CustomItemType.BlasterRifle ||
                    offHand.CustomItemType == CustomItemType.Throwing)
                {
                    weapon = offHand;
                }
            }

            if (weapon == null || !weapon.IsValid)
            {
                weapon = oPC.Arms;
            }
            if (!weapon.IsValid)
            {
                return(0);
            }

            SkillType itemSkill = ItemService.GetSkillTypeForItem(weapon);

            if (itemSkill == SkillType.Unknown ||
                itemSkill == SkillType.LightArmor ||
                itemSkill == SkillType.HeavyArmor ||
                itemSkill == SkillType.ForceArmor ||
                itemSkill == SkillType.Shields)
            {
                return(0);
            }

            int     weaponSkillID = (int)itemSkill;
            PCSkill skill         = DataService.Single <PCSkill>(x => x.PlayerID == oPC.GlobalID && x.SkillID == weaponSkillID);

            if (skill == null)
            {
                return(0);
            }
            int            skillBAB                = skill.Rank / 10;
            int            perkBAB                 = 0;
            int            backgroundBAB           = 0;
            BackgroundType background              = (BackgroundType)oPC.Class1;
            bool           receivesBackgroundBonus = false;

            // Apply increased BAB if player is using a weapon for which they have a proficiency.
            PerkType  proficiencyPerk  = PerkType.Unknown;
            SkillType proficiencySkill = SkillType.Unknown;

            switch (weapon.CustomItemType)
            {
            case CustomItemType.Vibroblade:
                proficiencyPerk  = PerkType.VibrobladeProficiency;
                proficiencySkill = SkillType.OneHanded;
                break;

            case CustomItemType.FinesseVibroblade:
                proficiencyPerk         = PerkType.FinesseVibrobladeProficiency;
                proficiencySkill        = SkillType.OneHanded;
                receivesBackgroundBonus = background == BackgroundType.Duelist;
                break;

            case CustomItemType.Baton:
                proficiencyPerk         = PerkType.BatonProficiency;
                proficiencySkill        = SkillType.OneHanded;
                receivesBackgroundBonus = background == BackgroundType.SecurityOfficer;
                break;

            case CustomItemType.HeavyVibroblade:
                proficiencyPerk         = PerkType.HeavyVibrobladeProficiency;
                proficiencySkill        = SkillType.TwoHanded;
                receivesBackgroundBonus = background == BackgroundType.Soldier;
                break;

            case CustomItemType.Saberstaff:
                proficiencyPerk  = PerkType.SaberstaffProficiency;
                proficiencySkill = SkillType.Lightsaber;
                break;

            case CustomItemType.Polearm:
                proficiencyPerk  = PerkType.PolearmProficiency;
                proficiencySkill = SkillType.TwoHanded;
                break;

            case CustomItemType.TwinBlade:
                proficiencyPerk         = PerkType.TwinVibrobladeProficiency;
                proficiencySkill        = SkillType.TwinBlades;
                receivesBackgroundBonus = background == BackgroundType.Berserker;
                break;

            case CustomItemType.MartialArtWeapon:
                proficiencyPerk         = PerkType.MartialArtsProficiency;
                proficiencySkill        = SkillType.MartialArts;
                receivesBackgroundBonus = background == BackgroundType.TerasKasi;
                break;

            case CustomItemType.BlasterPistol:
                proficiencyPerk         = PerkType.BlasterPistolProficiency;
                proficiencySkill        = SkillType.Firearms;
                receivesBackgroundBonus = background == BackgroundType.Smuggler;
                break;

            case CustomItemType.BlasterRifle:
                proficiencyPerk         = PerkType.BlasterRifleProficiency;
                proficiencySkill        = SkillType.Firearms;
                receivesBackgroundBonus = background == BackgroundType.Sharpshooter || background == BackgroundType.Mandalorian;
                break;

            case CustomItemType.Throwing:
                proficiencyPerk  = PerkType.ThrowingProficiency;
                proficiencySkill = SkillType.Throwing;
                break;

            case CustomItemType.Lightsaber:
                proficiencyPerk  = PerkType.LightsaberProficiency;
                proficiencySkill = SkillType.Lightsaber;
                break;
            }

            if (weapon.GetLocalInt("LIGHTSABER") == TRUE)
            {
                proficiencyPerk  = PerkType.LightsaberProficiency;
                proficiencySkill = SkillType.Lightsaber;
            }

            if (proficiencyPerk != PerkType.Unknown &&
                proficiencySkill != SkillType.Unknown)
            {
                perkBAB += PerkService.GetPCPerkLevel(oPC, proficiencyPerk);
            }

            if (receivesBackgroundBonus)
            {
                backgroundBAB = background == BackgroundType.Mandalorian ? 1 : 2;
            }

            return(1 + skillBAB + perkBAB + stats.BAB + backgroundBAB); // Note: Always add 1 to BAB. 0 will cause a crash in NWNX.
        }
Beispiel #6
0
        public static EffectiveItemStats GetPlayerItemEffectiveStats(NWPlayer player, NWItem ignoreItem = null)
        {
            using (new Profiler("PlayerStatService::ApplyStatChanges::GetPlayerItemEffectiveStats"))
            {
                var pcSkills = DataService.Where <PCSkill>(x => x.PlayerID == player.GlobalID);

                int heavyRank   = pcSkills.Single(x => x.SkillID == (int)SkillType.HeavyArmor).Rank;
                int lightRank   = pcSkills.Single(x => x.SkillID == (int)SkillType.LightArmor).Rank;
                int forceRank   = pcSkills.Single(x => x.SkillID == (int)SkillType.ForceArmor).Rank;
                int martialRank = pcSkills.Single(x => x.SkillID == (int)SkillType.MartialArts).Rank;

                EffectiveItemStats stats = new EffectiveItemStats();
                stats.EnmityRate = 1.0f;

                using (new Profiler("PlayerStatService::ApplyStatChanges::GetPlayerItemEffectiveStats::ItemLoop"))
                {
                    HashSet <NWItem> processed = new HashSet <NWItem>();
                    for (int itemSlot = 0; itemSlot < NUM_INVENTORY_SLOTS; itemSlot++)
                    {
                        NWItem item = _.GetItemInSlot(itemSlot, player);

                        if (!item.IsValid || item.Equals(ignoreItem))
                        {
                            continue;
                        }
                        SkillType skill = ItemService.GetSkillTypeForItem(item);
                        int       rank;

                        // Have we already processed this particular item? Skip over it.
                        // NWN likes to include the same weapon in multiple slots for some reasons, so this works around that.
                        // If someone has a better solution to this please feel free to change it.
                        if (processed.Contains(item))
                        {
                            continue;
                        }
                        processed.Add(item);

                        using (new Profiler("PlayerStatService::ApplyStatChanges::GetPlayerItemEffectiveStats::ItemLoop::GetRank"))
                        {
                            rank = pcSkills.Single(x => x.SkillID == (int)skill).Rank;
                        }

                        using (new Profiler("PlayerStatService::ApplyStatChanges::GetPlayerItemEffectiveStats::ItemLoop::StatAdjustments"))
                        {
                            // Only scale casting speed if it's a bonus. Penalties remain regardless of skill level difference.
                            if (item.CastingSpeed > 0)
                            {
                                stats.CastingSpeed += CalculateAdjustedValue(item.CastingSpeed, item.RecommendedLevel, rank, 1);
                            }
                            else
                            {
                                stats.CastingSpeed += item.CastingSpeed;
                            }

                            stats.EnmityRate += CalculateAdjustedValue(0.01f * item.EnmityRate, item.RecommendedLevel, rank, 0.00f);

                            stats.ForcePotency  += CalculateAdjustedValue(item.ForcePotencyBonus, item.RecommendedLevel, rank, 0);
                            stats.ForceDefense  += CalculateAdjustedValue(item.ForceDefenseBonus, item.RecommendedLevel, rank, 0);
                            stats.ForceAccuracy += CalculateAdjustedValue(item.ForceAccuracyBonus, item.RecommendedLevel, rank, 0);

                            stats.ElectricalPotency += CalculateAdjustedValue(item.ElectricalPotencyBonus, item.RecommendedLevel, rank, 0);
                            stats.MindPotency       += CalculateAdjustedValue(item.MindPotencyBonus, item.RecommendedLevel, rank, 0);
                            stats.LightPotency      += CalculateAdjustedValue(item.LightPotencyBonus, item.RecommendedLevel, rank, 0);
                            stats.DarkPotency       += CalculateAdjustedValue(item.DarkPotencyBonus, item.RecommendedLevel, rank, 0);

                            stats.ElectricalDefense += CalculateAdjustedValue(item.ElectricalDefenseBonus, item.RecommendedLevel, rank, 0);
                            stats.MindDefense       += CalculateAdjustedValue(item.MindDefenseBonus, item.RecommendedLevel, rank, 0);
                            stats.LightDefense      += CalculateAdjustedValue(item.LightDefenseBonus, item.RecommendedLevel, rank, 0);
                            stats.DarkDefense       += CalculateAdjustedValue(item.DarkDefenseBonus, item.RecommendedLevel, rank, 0);

                            stats.Luck        += CalculateAdjustedValue(item.LuckBonus, item.RecommendedLevel, rank, 0);
                            stats.Meditate    += CalculateAdjustedValue(item.MeditateBonus, item.RecommendedLevel, rank, 0);
                            stats.Rest        += CalculateAdjustedValue(item.RestBonus, item.RecommendedLevel, rank, 0);
                            stats.Medicine    += CalculateAdjustedValue(item.MedicineBonus, item.RecommendedLevel, rank, 0);
                            stats.HPRegen     += CalculateAdjustedValue(item.HPRegenBonus, item.RecommendedLevel, rank, 0);
                            stats.FPRegen     += CalculateAdjustedValue(item.FPRegenBonus, item.RecommendedLevel, rank, 0);
                            stats.Weaponsmith += CalculateAdjustedValue(item.CraftBonusWeaponsmith, item.RecommendedLevel, rank, 0);
                            stats.Cooking     += CalculateAdjustedValue(item.CraftBonusCooking, item.RecommendedLevel, rank, 0);
                            stats.Engineering += CalculateAdjustedValue(item.CraftBonusEngineering, item.RecommendedLevel, rank, 0);
                            stats.Fabrication += CalculateAdjustedValue(item.CraftBonusFabrication, item.RecommendedLevel, rank, 0);
                            stats.Armorsmith  += CalculateAdjustedValue(item.CraftBonusArmorsmith, item.RecommendedLevel, rank, 0);
                            stats.Harvesting  += CalculateAdjustedValue(item.HarvestingBonus, item.RecommendedLevel, rank, 0);
                            stats.Piloting    += CalculateAdjustedValue(item.PilotingBonus, item.RecommendedLevel, rank, 0);
                            stats.Scavenging  += CalculateAdjustedValue(item.ScavengingBonus, item.RecommendedLevel, rank, 0);
                            stats.SneakAttack += CalculateAdjustedValue(item.SneakAttackBonus, item.RecommendedLevel, rank, 0);

                            stats.Strength     += CalculateAdjustedValue(item.StrengthBonus, item.RecommendedLevel, rank, 0);
                            stats.Dexterity    += CalculateAdjustedValue(item.DexterityBonus, item.RecommendedLevel, rank, 0);
                            stats.Constitution += CalculateAdjustedValue(item.ConstitutionBonus, item.RecommendedLevel, rank, 0);
                            stats.Wisdom       += CalculateAdjustedValue(item.WisdomBonus, item.RecommendedLevel, rank, 0);
                            stats.Intelligence += CalculateAdjustedValue(item.IntelligenceBonus, item.RecommendedLevel, rank, 0);
                            stats.Charisma     += CalculateAdjustedValue(item.CharismaBonus, item.RecommendedLevel, rank, 0);
                            stats.HP           += CalculateAdjustedValue(item.HPBonus, item.RecommendedLevel, rank, 0);
                            stats.FP           += CalculateAdjustedValue(item.FPBonus, item.RecommendedLevel, rank, 0);
                        }


                        using (new Profiler("PlayerStatService::ApplyStatChanges::GetPlayerItemEffectiveStats::ItemLoop::CalcBAB"))
                        {
                            // Calculate base attack bonus
                            int itemLevel = item.RecommendedLevel;
                            int delta     = itemLevel - rank;
                            int itemBAB   = item.BaseAttackBonus;
                            if (delta >= 1)
                            {
                                itemBAB--;
                            }
                            if (delta > 0)
                            {
                                itemBAB = itemBAB - delta / 5;
                            }

                            if (itemBAB <= 0)
                            {
                                itemBAB = 0;
                            }
                            stats.BAB += itemBAB;
                        }

                        using (new Profiler("PlayerStatService::ApplyStatChanges::GetPlayerItemEffectiveStats::ItemLoop::CalcAC"))
                        {
                            // Calculate AC
                            if (ACBaseItemTypes.Contains(item.BaseItemType))
                            {
                                int skillRankToUse;
                                if (item.CustomItemType == CustomItemType.HeavyArmor)
                                {
                                    skillRankToUse = heavyRank;
                                }
                                else if (item.CustomItemType == CustomItemType.LightArmor)
                                {
                                    skillRankToUse = lightRank;
                                }
                                else if (item.CustomItemType == CustomItemType.ForceArmor)
                                {
                                    skillRankToUse = forceRank;
                                }
                                else if (item.CustomItemType == CustomItemType.MartialArtWeapon)
                                {
                                    skillRankToUse = martialRank;
                                }
                                else
                                {
                                    continue;
                                }

                                int itemAC = item.CustomAC;
                                itemAC    = CalculateAdjustedValue(itemAC, item.RecommendedLevel, skillRankToUse, 0);
                                stats.AC += itemAC;
                            }
                        }
                    }
                }

                using (new Profiler("PlayerStatService::ApplyStatChanges::GetPlayerItemEffectiveStats::FinalAdjustments"))
                {
                    // Final casting speed adjustments
                    if (stats.CastingSpeed < -99)
                    {
                        stats.CastingSpeed = -99;
                    }
                    else if (stats.CastingSpeed > 99)
                    {
                        stats.CastingSpeed = 99;
                    }

                    // Final enmity adjustments
                    if (stats.EnmityRate < 0.5f)
                    {
                        stats.EnmityRate = 0.5f;
                    }
                    else if (stats.EnmityRate > 1.5f)
                    {
                        stats.EnmityRate = 1.5f;
                    }

                    var stance = CustomEffectService.GetCurrentStanceType(player);
                    if (stance == CustomEffectType.ShieldOath)
                    {
                        stats.EnmityRate = stats.EnmityRate + 0.2f;
                    }

                    return(stats);
                }
            }
        }
Beispiel #7
0
        private static int CalculateBAB(NWPlayer oPC, NWItem ignoreItem, EffectiveItemStats stats)
        {
            NWItem weapon = oPC.RightHand;

            // The unequip event fires before the item is actually unequipped, so we need
            // to have additional checks to make sure we're not getting the weapon that's about to be
            // unequipped.
            if (weapon.Equals(ignoreItem))
            {
                weapon = null;
                NWItem offHand = oPC.LeftHand;

                if (offHand.CustomItemType == CustomItemType.Vibroblade ||
                    offHand.CustomItemType == CustomItemType.FinesseVibroblade ||
                    offHand.CustomItemType == CustomItemType.Baton ||
                    offHand.CustomItemType == CustomItemType.HeavyVibroblade ||
                    offHand.CustomItemType == CustomItemType.Saberstaff ||
                    offHand.CustomItemType == CustomItemType.Polearm ||
                    offHand.CustomItemType == CustomItemType.TwinBlade ||
                    offHand.CustomItemType == CustomItemType.MartialArtWeapon ||
                    offHand.CustomItemType == CustomItemType.BlasterPistol ||
                    offHand.CustomItemType == CustomItemType.BlasterRifle ||
                    offHand.CustomItemType == CustomItemType.Throwing)
                {
                    weapon = offHand;
                }
            }

            if (weapon == null || !weapon.IsValid)
            {
                weapon = oPC.Arms;
            }
            if (!weapon.IsValid)
            {
                return(0);
            }

            SkillType itemSkill = ItemService.GetSkillTypeForItem(weapon);

            if (itemSkill == SkillType.Unknown ||
                itemSkill == SkillType.LightArmor ||
                itemSkill == SkillType.HeavyArmor ||
                itemSkill == SkillType.ForceArmor ||
                itemSkill == SkillType.Shields)
            {
                return(0);
            }

            int     weaponSkillID = (int)itemSkill;
            PCSkill skill         = DataService.PCSkill.GetByPlayerIDAndSkillID(oPC.GlobalID, weaponSkillID);

            if (skill == null)
            {
                return(0);
            }
            int            skillBAB                = skill.Rank / 10;
            int            perkBAB                 = 0;
            int            backgroundBAB           = 0;
            BackgroundType background              = (BackgroundType)oPC.Class1;
            bool           receivesBackgroundBonus = false;

            switch (weapon.CustomItemType)
            {
            case CustomItemType.FinesseVibroblade:
                receivesBackgroundBonus = background == BackgroundType.Duelist;
                break;

            case CustomItemType.Baton:
                receivesBackgroundBonus = background == BackgroundType.SecurityOfficer;
                break;

            case CustomItemType.HeavyVibroblade:
                receivesBackgroundBonus = background == BackgroundType.Soldier;
                break;

            case CustomItemType.TwinBlade:
                receivesBackgroundBonus = background == BackgroundType.Berserker;
                break;

            case CustomItemType.MartialArtWeapon:
                receivesBackgroundBonus = background == BackgroundType.TerasKasi;
                break;

            case CustomItemType.BlasterPistol:
                receivesBackgroundBonus = background == BackgroundType.Smuggler;
                break;

            case CustomItemType.BlasterRifle:
                receivesBackgroundBonus = background == BackgroundType.Sharpshooter || background == BackgroundType.Mandalorian;
                break;
            }

            if (receivesBackgroundBonus)
            {
                backgroundBAB = background == BackgroundType.Mandalorian ? 1 : 2;
            }

            return(1 + skillBAB + perkBAB + stats.BAB + backgroundBAB); // Note: Always add 1 to BAB. 0 will cause a crash in NWNX.
        }
Beispiel #8
0
        public static EffectiveItemStats GetPlayerItemEffectiveStats(NWPlayer player, NWItem ignoreItem = null)
        {
            int heavyRank   = DataService.PCSkill.GetByPlayerIDAndSkillID(player.GlobalID, (int)SkillType.HeavyArmor).Rank;
            int lightRank   = DataService.PCSkill.GetByPlayerIDAndSkillID(player.GlobalID, (int)SkillType.LightArmor).Rank;
            int forceRank   = DataService.PCSkill.GetByPlayerIDAndSkillID(player.GlobalID, (int)SkillType.ForceArmor).Rank;
            int martialRank = DataService.PCSkill.GetByPlayerIDAndSkillID(player.GlobalID, (int)SkillType.MartialArts).Rank;

            EffectiveItemStats stats = new EffectiveItemStats();

            stats.EnmityRate = 1.0f;

            HashSet <NWItem> processed = new HashSet <NWItem>();

            for (int itemSlot = 0; itemSlot < NumberOfInventorySlots; itemSlot++)
            {
                NWItem item = _.GetItemInSlot((InventorySlot)itemSlot, player);

                if (!item.IsValid || item.Equals(ignoreItem))
                {
                    continue;
                }

                // Have we already processed this particular item? Skip over it.
                // NWN likes to include the same weapon in multiple slots for some reasons, so this works around that.
                // If someone has a better solution to this please feel free to change it.
                if (processed.Contains(item))
                {
                    continue;
                }
                processed.Add(item);

                SkillType skill = ItemService.GetSkillTypeForItem(item);
                var       rank  = DataService.PCSkill.GetByPlayerIDAndSkillID(player.GlobalID, (int)skill).Rank;
                stats.CooldownRecovery += item.GetLocalInt("STAT_EFFECTIVE_LEVEL_COOLDOWN_RECOVERY");
                stats.EnmityRate       += item.GetLocalFloat("STAT_EFFECTIVE_LEVEL_ENMITY_RATE");
                stats.Luck             += item.GetLocalInt("STAT_EFFECTIVE_LEVEL_LUCK_BONUS");
                stats.Meditate         += item.GetLocalInt("STAT_EFFECTIVE_LEVEL_MEDITATE_BONUS");
                stats.Rest             += item.GetLocalInt("STAT_EFFECTIVE_LEVEL_REST_BONUS");
                stats.Medicine         += item.GetLocalInt("STAT_EFFECTIVE_LEVEL_MEDICINE_BONUS");
                stats.HPRegen          += item.GetLocalInt("STAT_EFFECTIVE_LEVEL_HP_REGEN_BONUS");
                stats.FPRegen          += item.GetLocalInt("STAT_EFFECTIVE_LEVEL_FP_REGEN_BONUS");
                stats.Weaponsmith      += item.GetLocalInt("STAT_EFFECTIVE_LEVEL_WEAPONSMITH_BONUS");
                stats.Cooking          += item.GetLocalInt("STAT_EFFECTIVE_LEVEL_COOKING_BONUS");
                stats.Engineering      += item.GetLocalInt("STAT_EFFECTIVE_LEVEL_ENGINEERING_BONUS");
                stats.Fabrication      += item.GetLocalInt("STAT_EFFECTIVE_LEVEL_FABRICATION_BONUS");
                stats.Armorsmith       += item.GetLocalInt("STAT_EFFECTIVE_LEVEL_ARMORSMITH_BONUS");
                stats.Harvesting       += item.GetLocalInt("STAT_EFFECTIVE_LEVEL_HARVESTING_BONUS");
                stats.Piloting         += item.GetLocalInt("STAT_EFFECTIVE_LEVEL_PILOTING_BONUS");
                stats.Scavenging       += item.GetLocalInt("STAT_EFFECTIVE_LEVEL_SCAVENGING_BONUS");
                stats.SneakAttack      += item.GetLocalInt("STAT_EFFECTIVE_LEVEL_SNEAK_ATTACK_BONUS");
                stats.Strength         += item.GetLocalInt("STAT_EFFECTIVE_LEVEL_STRENGTH_BONUS");
                stats.Dexterity        += item.GetLocalInt("STAT_EFFECTIVE_LEVEL_DEXTERITY_BONUS");
                stats.Constitution     += item.GetLocalInt("STAT_EFFECTIVE_LEVEL_CONSTITUTION_BONUS");
                stats.Wisdom           += item.GetLocalInt("STAT_EFFECTIVE_LEVEL_WISDOM_BONUS");
                stats.Intelligence     += item.GetLocalInt("STAT_EFFECTIVE_LEVEL_INTELLIGENCE_BONUS");
                stats.Charisma         += item.GetLocalInt("STAT_EFFECTIVE_LEVEL_CHARISMA_BONUS");
                stats.HP += item.GetLocalInt("STAT_EFFECTIVE_LEVEL_HP_BONUS");
                stats.FP += item.GetLocalInt("STAT_EFFECTIVE_LEVEL_FP_BONUS");

                // Calculate base attack bonus
                if (ItemService.WeaponBaseItemTypes.Contains(item.BaseItemType))
                {
                    int itemLevel = item.RecommendedLevel;
                    int delta     = itemLevel - rank;
                    int itemBAB   = item.BaseAttackBonus;
                    if (delta >= 1)
                    {
                        itemBAB--;
                    }
                    if (delta > 0)
                    {
                        itemBAB = itemBAB - delta / 5;
                    }

                    if (itemBAB <= 0)
                    {
                        itemBAB = 0;
                    }
                    stats.BAB += itemBAB;
                }


                // Calculate AC
                if (ItemService.ArmorBaseItemTypes.Contains(item.BaseItemType))
                {
                    int skillRankToUse;
                    int maxAC = 0;

                    if (item.CustomItemType == CustomItemType.HeavyArmor)
                    {
                        skillRankToUse = heavyRank;
                        maxAC          = 10;
                    }
                    else if (item.CustomItemType == CustomItemType.LightArmor)
                    {
                        skillRankToUse = lightRank;
                        maxAC          = 13;
                    }
                    else if (item.CustomItemType == CustomItemType.ForceArmor)
                    {
                        skillRankToUse = forceRank;
                        maxAC          = 11;
                    }
                    else if (item.CustomItemType == CustomItemType.MartialArtWeapon)
                    {
                        skillRankToUse = martialRank;
                    }
                    else
                    {
                        continue;
                    }

                    int itemAC = item.CustomAC;
                    itemAC = CalculateAdjustedValue(itemAC, item.RecommendedLevel, skillRankToUse, 0);
                    if (itemAC > maxAC)
                    {
                        item.CustomAC = maxAC;
                    }
                    stats.AC += itemAC;
                }
            }

            // Final casting speed adjustments
            if (stats.CooldownRecovery < -99)
            {
                stats.CooldownRecovery = -99;
            }
            else if (stats.CooldownRecovery > 99)
            {
                stats.CooldownRecovery = 99;
            }

            // Final enmity adjustments
            if (stats.EnmityRate < 0.5f)
            {
                stats.EnmityRate = 0.5f;
            }
            else if (stats.EnmityRate > 1.5f)
            {
                stats.EnmityRate = 1.5f;
            }

            var stance = CustomEffectService.GetCurrentStanceType(player);

            if (stance == CustomEffectType.ShieldOath)
            {
                stats.EnmityRate = stats.EnmityRate + 0.2f;
            }

            return(stats);
        }
Beispiel #9
0
        public static void CalculateEffectiveStats(NWPlayer player, NWItem item)
        {
            if (item == null || !item.IsValid || !player.IsPlayer || player.IsDMPossessed || player.IsDM || !player.IsInitializedAsPlayer)
            {
                return;
            }

            // Calculating effective stats can be expensive, so we cache it on the item.
            SkillType skill;

            if (item.BaseItemType == BaseItem.Amulet || item.BaseItemType == BaseItem.Ring)
            {
                var forceArmor = SkillService.GetPCSkill(player, (int)SkillType.ForceArmor);
                var lightArmor = SkillService.GetPCSkill(player, (int)SkillType.LightArmor);
                var heavyArmor = SkillService.GetPCSkill(player, (int)SkillType.HeavyArmor);
                var highest    = forceArmor.Rank;
                skill = SkillType.ForceArmor;

                if (lightArmor.Rank > highest)
                {
                    highest = lightArmor.Rank;
                    skill   = SkillType.LightArmor;
                }
                if (heavyArmor.Rank > highest)
                {
                    skill = SkillType.HeavyArmor;
                }
            }
            else
            {
                skill = ItemService.GetSkillTypeForItem(item);
            }

            var rank = DataService.PCSkill.GetByPlayerIDAndSkillID(player.GlobalID, (int)skill).Rank;

            using (new Profiler("PlayerStatService::ApplyStatChanges::GetPlayerItemEffectiveStats::ItemLoop::CalculateEffectiveStats"))
            {
                // Only scale cooldown recovery if it's a bonus. Penalties remain regardless of skill level difference.
                item.SetLocalInt("STAT_EFFECTIVE_LEVEL_COOLDOWN_RECOVERY", item.CooldownRecovery > 0
                    ? CalculateAdjustedValue(item.CooldownRecovery, item.RecommendedLevel, rank, 1)
                    : item.CooldownRecovery);

                item.SetLocalFloat("STAT_EFFECTIVE_LEVEL_ENMITY_RATE", CalculateAdjustedValue(0.01f * item.EnmityRate, item.RecommendedLevel, rank, 0.00f));

                item.SetLocalInt("STAT_EFFECTIVE_LEVEL_LUCK_BONUS", CalculateAdjustedValue(item.LuckBonus, item.RecommendedLevel, rank, 0));
                item.SetLocalInt("STAT_EFFECTIVE_LEVEL_MEDITATE_BONUS", CalculateAdjustedValue(item.MeditateBonus, item.RecommendedLevel, rank, 0));
                item.SetLocalInt("STAT_EFFECTIVE_LEVEL_REST_BONUS", CalculateAdjustedValue(item.RestBonus, item.RecommendedLevel, rank, 0));
                item.SetLocalInt("STAT_EFFECTIVE_LEVEL_MEDICINE_BONUS", CalculateAdjustedValue(item.MedicineBonus, item.RecommendedLevel, rank, 0));
                item.SetLocalInt("STAT_EFFECTIVE_LEVEL_HP_REGEN_BONUS", CalculateAdjustedValue(item.HPRegenBonus, item.RecommendedLevel, rank, 0));
                item.SetLocalInt("STAT_EFFECTIVE_LEVEL_FP_REGEN_BONUS", CalculateAdjustedValue(item.FPRegenBonus, item.RecommendedLevel, rank, 0));
                item.SetLocalInt("STAT_EFFECTIVE_LEVEL_WEAPONSMITH_BONUS", CalculateAdjustedValue(item.CraftBonusWeaponsmith, item.RecommendedLevel, rank, 0));
                item.SetLocalInt("STAT_EFFECTIVE_LEVEL_COOKING_BONUS", CalculateAdjustedValue(item.CraftBonusCooking, item.RecommendedLevel, rank, 0));
                item.SetLocalInt("STAT_EFFECTIVE_LEVEL_ENGINEERING_BONUS", CalculateAdjustedValue(item.CraftBonusEngineering, item.RecommendedLevel, rank, 0));
                item.SetLocalInt("STAT_EFFECTIVE_LEVEL_FABRICATION_BONUS", CalculateAdjustedValue(item.CraftBonusFabrication, item.RecommendedLevel, rank, 0));
                item.SetLocalInt("STAT_EFFECTIVE_LEVEL_ARMORSMITH_BONUS", CalculateAdjustedValue(item.CraftBonusArmorsmith, item.RecommendedLevel, rank, 0));
                item.SetLocalInt("STAT_EFFECTIVE_LEVEL_HARVESTING_BONUS", CalculateAdjustedValue(item.HarvestingBonus, item.RecommendedLevel, rank, 0));
                item.SetLocalInt("STAT_EFFECTIVE_LEVEL_PILOTING_BONUS", CalculateAdjustedValue(item.PilotingBonus, item.RecommendedLevel, rank, 0));
                item.SetLocalInt("STAT_EFFECTIVE_LEVEL_SCAVENGING_BONUS", CalculateAdjustedValue(item.ScavengingBonus, item.RecommendedLevel, rank, 0));
                item.SetLocalInt("STAT_EFFECTIVE_LEVEL_SNEAK_ATTACK_BONUS", CalculateAdjustedValue(item.SneakAttackBonus, item.RecommendedLevel, rank, 0));

                item.SetLocalInt("STAT_EFFECTIVE_LEVEL_STRENGTH_BONUS", CalculateAdjustedValue(item.StrengthBonus, item.RecommendedLevel, rank, 0));
                item.SetLocalInt("STAT_EFFECTIVE_LEVEL_DEXTERITY_BONUS", CalculateAdjustedValue(item.DexterityBonus, item.RecommendedLevel, rank, 0));
                item.SetLocalInt("STAT_EFFECTIVE_LEVEL_CONSTITUTION_BONUS", CalculateAdjustedValue(item.ConstitutionBonus, item.RecommendedLevel, rank, 0));
                item.SetLocalInt("STAT_EFFECTIVE_LEVEL_WISDOM_BONUS", CalculateAdjustedValue(item.WisdomBonus, item.RecommendedLevel, rank, 0));
                item.SetLocalInt("STAT_EFFECTIVE_LEVEL_INTELLIGENCE_BONUS", CalculateAdjustedValue(item.IntelligenceBonus, item.RecommendedLevel, rank, 0));
                item.SetLocalInt("STAT_EFFECTIVE_LEVEL_CHARISMA_BONUS", CalculateAdjustedValue(item.CharismaBonus, item.RecommendedLevel, rank, 0));
                item.SetLocalInt("STAT_EFFECTIVE_LEVEL_HP_BONUS", CalculateAdjustedValue(item.HPBonus, item.RecommendedLevel, rank, 0));
                item.SetLocalInt("STAT_EFFECTIVE_LEVEL_FP_BONUS", CalculateAdjustedValue(item.FPBonus, item.RecommendedLevel, rank, 0));
            }
        }
        public static Tuple <ItemProperty, int> GetRandomComponentBonusIP(ResourceQuality quality)
        {
            string[] commonIP =
            {
                "compbon_ac1",
                "compbon_arm1",
                "compbon_cspd1",
                "compbon_charges1",
                "compbon_charges2",
                "compbon_cooking1",
                "compbon_dmg1",
                "compbon_dur1",
                "compbon_dur2",
                "compbon_eng1",
                "compbon_enmdown1",
                "compbon_epup1",
                "compbon_epdown1",
                "compbon_edup1",
                "compbon_eddown1",
                "compbon_dpdown1",
                "compbon_dpup1",
                "compbon_dddown1",
                "compbon_ddup1",
                "compbon_lpdown1",
                "compbon_lpup1",
                "compbon_lddown1",
                "compbon_ldup1",
                "compbon_mpdown1",
                "compbon_mpup1",
                "compbon_mddown1",
                "compbon_mdup1",
                "compbon_harv1",
                "compbon_wpn1",
                "compbon_hp2",
                "compbon_fp2",
                "compbon_enmup1",
                "compbon_med1",
                "compbon_faid1",
                "compbon_fab1",
                "compbon_scanup1",
                "compbon_rest1",
                "compbon_ab1"
            };

            string[] uncommonIP =
            {
                "compbon_ac2",
                "compbon_arm2",
                "compbon_cspd2",
                "compbon_charges3",
                "compbon_cooking2",
                "compbon_dmg2",
                "compbon_dur3",
                "compbon_eng2",
                "compbon_enmdown2",
                "compbon_epup2",
                "compbon_epdown2",
                "compbon_edup2",
                "compbon_eddown2",
                "compbon_dpdown2",
                "compbon_dpup2",
                "compbon_dddown2",
                "compbon_ddup2",
                "compbon_lpdown2",
                "compbon_lpup2",
                "compbon_lddown2",
                "compbon_ldup2",
                "compbon_mpdown2",
                "compbon_mpup2",
                "compbon_mddown2",
                "compbon_mdup2",
                "compbon_harv2",
                "compbon_wpn2",
                "compbon_hp4",
                "compbon_fp4",
                "compbon_enmup2",
                "compbon_luck1",
                "compbon_med2",
                "compbon_faid2",
                "compbon_hpregen1",
                "compbon_fpregen1",
                "compbon_snkatk1",
                "compbon_fab2",
                "compbon_scanup2",
                "compbon_rest2",
                "compbon_str1",
                "compbon_dex1",
                "compbon_con1",
                "compbon_wis1",
                "compbon_int1",
                "compbon_cha1",
                "compbon_ab2",
                "compbon_scavup1"
            };

            string[] rareIP =
            {
                "compbon_ac3",
                "compbon_arm3",
                "compbon_cspd3",
                "compbon_cooking3",
                "compbon_dmg3",
                "compbon_eng3",
                "compbon_enmdown3",
                "compbon_epup3",
                "compbon_epdown3",
                "compbon_edup3",
                "compbon_eddown3",
                "compbon_dpdown3",
                "compbon_dpup3",
                "compbon_dddown3",
                "compbon_ddup3",
                "compbon_lpdown3",
                "compbon_lpup3",
                "compbon_lddown3",
                "compbon_ldup3",
                "compbon_mpdown3",
                "compbon_mpup3",
                "compbon_mddown3",
                "compbon_mdup3",
                "compbon_harv3",
                "compbon_wpn3",
                "compbon_hp6",
                "compbon_fp6",
                "compbon_enmup3",
                "compbon_luck2",
                "compbon_med3",
                "compbon_faid3",
                "compbon_hpregen2",
                "compbon_fpregen2",
                "compbon_snkatk2",
                "compbon_fab3",
                "compbon_scanup3",
                "compbon_rest3",
                "compbon_str2",
                "compbon_dex2",
                "compbon_con2",
                "compbon_wis2",
                "compbon_int2",
                "compbon_cha2",
                "compbon_ab3",
                "compbon_scavup2"
            };

            string[] ultraRareIP =
            {
                "compbon_luck3",
                "compbon_hpregen3",
                "compbon_fpregen3",
                "compbon_snkatk3",
                "compbon_str3",
                "compbon_dex3",
                "compbon_con3",
                "compbon_wis3",
                "compbon_int3",
                "compbon_cha3",
                "compbon_fpup1",
                "compbon_faup1",
                "compbon_fdup1",
                "compbon_scavup3"
            };

            // Order: Common, Uncommon, Rare, Ultra Rare
            int[] chance;

            switch (quality)
            {
            case ResourceQuality.Low:
                chance = new[] { 100, 0, 0, 0 };
                break;

            case ResourceQuality.Normal:
                chance = new[] { 80, 20, 0, 0 };
                break;

            case ResourceQuality.High:
                chance = new[] { 20, 40, 40, 0 };
                break;

            case ResourceQuality.VeryHigh:
                chance = new[] { 0, 0, 70, 30 };
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(quality));
            }

            string[] setToUse = null;

            int index = RandomService.GetRandomWeightedIndex(chance);

            switch (index)
            {
            case 0: setToUse = commonIP; break;

            case 1: setToUse = uncommonIP; break;

            case 2: setToUse = rareIP; break;

            case 3: setToUse = ultraRareIP; break;
            }

            if (setToUse == null)
            {
                throw new NullReferenceException(nameof(setToUse));
            }

            index = RandomService.Random(0, setToUse.Length - 1);

            string itemTag = setToUse[index];

            return(new Tuple <ItemProperty, int>(ItemService.GetCustomItemPropertyByItemTag(itemTag), index));
        }
Beispiel #11
0
        private static void ApplyEquipmentPenalties(NWPlayer oPC, NWItem oItem)
        {
            SkillType skill = ItemService.GetSkillTypeForItem(oItem);

            if (skill == SkillType.Unknown)
            {
                return;
            }

            int rank  = GetPCSkillRank(oPC, skill);
            int delta = oItem.RecommendedLevel - rank;

            if (delta <= 0)
            {
                return;
            }

            int str  = 0;
            int dex  = 0;
            int con  = 0;
            int wis  = 0;
            int @int = 0;
            int cha  = 0;
            int ab   = 0;
            int eb   = 0;

            foreach (var ip in oItem.ItemProperties)
            {
                int type  = _.GetItemPropertyType(ip);
                int value = _.GetItemPropertyCostTableValue(ip);
                if (type == ITEM_PROPERTY_ABILITY_BONUS)
                {
                    int abilityType = _.GetItemPropertySubType(ip);
                    switch (abilityType)
                    {
                    case ABILITY_STRENGTH: str += value; break;

                    case ABILITY_CONSTITUTION: con += value; break;

                    case ABILITY_DEXTERITY: dex += value; break;

                    case ABILITY_WISDOM: wis += value; break;

                    case ABILITY_INTELLIGENCE: @int += value; break;

                    case ABILITY_CHARISMA: cha += value; break;
                    }
                }
                else if (type == ITEM_PROPERTY_DECREASED_ABILITY_SCORE)
                {
                    int abilityType = _.GetItemPropertySubType(ip);
                    switch (abilityType)
                    {
                    case ABILITY_STRENGTH: str -= value; break;

                    case ABILITY_CONSTITUTION: con -= value; break;

                    case ABILITY_DEXTERITY: dex -= value; break;

                    case ABILITY_WISDOM: wis -= value; break;

                    case ABILITY_INTELLIGENCE: @int -= value; break;

                    case ABILITY_CHARISMA: cha -= value; break;
                    }
                }
                else if (type == ITEM_PROPERTY_ATTACK_BONUS)
                {
                    ab += value;
                }
                else if (type == ITEM_PROPERTY_DECREASED_ATTACK_MODIFIER)
                {
                    ab -= value;
                }
                else if (type == ITEM_PROPERTY_ENHANCEMENT_BONUS)
                {
                    eb += value;
                }
                else if (type == ITEM_PROPERTY_DECREASED_ENHANCEMENT_MODIFIER)
                {
                    eb -= value;
                }
            }

            // Apply penalties only if total value is greater than 0. Penalties don't scale.
            if (str > 0)
            {
                int newStr = 1 + delta / 5;
                if (newStr > str)
                {
                    newStr = str;
                }

                ItemProperty ip = _.ItemPropertyDecreaseAbility(ABILITY_STRENGTH, newStr);
                ip = _.TagItemProperty(ip, IPEquipmentPenaltyTag);
                BiowareXP2.IPSafeAddItemProperty(oItem, ip, 0.0f, AddItemPropertyPolicy.IgnoreExisting, false, false);
            }
            if (dex > 0)
            {
                int newDex = 1 + delta / 5;
                if (newDex > dex)
                {
                    newDex = dex;
                }

                ItemProperty ip = _.ItemPropertyDecreaseAbility(ABILITY_DEXTERITY, newDex);
                ip = _.TagItemProperty(ip, IPEquipmentPenaltyTag);
                BiowareXP2.IPSafeAddItemProperty(oItem, ip, 0.0f, AddItemPropertyPolicy.IgnoreExisting, false, false);
            }
            if (con > 0)
            {
                int newCon = 1 + delta / 5;
                if (newCon > con)
                {
                    newCon = con;
                }

                ItemProperty ip = _.ItemPropertyDecreaseAbility(ABILITY_CONSTITUTION, newCon);
                ip = _.TagItemProperty(ip, IPEquipmentPenaltyTag);
                BiowareXP2.IPSafeAddItemProperty(oItem, ip, 0.0f, AddItemPropertyPolicy.IgnoreExisting, false, false);
            }
            if (@int > 0)
            {
                int newInt = 1 + delta / 5;
                if (newInt > @int)
                {
                    newInt = @int;
                }

                ItemProperty ip = _.ItemPropertyDecreaseAbility(ABILITY_INTELLIGENCE, newInt);
                ip = _.TagItemProperty(ip, IPEquipmentPenaltyTag);
                BiowareXP2.IPSafeAddItemProperty(oItem, ip, 0.0f, AddItemPropertyPolicy.IgnoreExisting, false, false);
            }
            if (wis > 0)
            {
                int newWis = 1 + delta / 5;
                if (newWis > wis)
                {
                    newWis = wis;
                }

                ItemProperty ip = _.ItemPropertyDecreaseAbility(ABILITY_WISDOM, newWis);
                ip = _.TagItemProperty(ip, IPEquipmentPenaltyTag);
                BiowareXP2.IPSafeAddItemProperty(oItem, ip, 0.0f, AddItemPropertyPolicy.IgnoreExisting, false, false);
            }
            if (cha > 0)
            {
                int newCha = 1 + delta / 5;
                if (newCha > cha)
                {
                    newCha = cha;
                }

                ItemProperty ip = _.ItemPropertyDecreaseAbility(ABILITY_CHARISMA, newCha);
                ip = _.TagItemProperty(ip, IPEquipmentPenaltyTag);
                BiowareXP2.IPSafeAddItemProperty(oItem, ip, 0.0f, AddItemPropertyPolicy.IgnoreExisting, false, false);
            }
            if (ab > 0)
            {
                int newAB = 1 + delta / 5;
                if (newAB > ab)
                {
                    newAB = ab;
                }

                ItemProperty ip = _.ItemPropertyAttackPenalty(newAB);
                ip = _.TagItemProperty(ip, IPEquipmentPenaltyTag);
                BiowareXP2.IPSafeAddItemProperty(oItem, ip, 0.0f, AddItemPropertyPolicy.IgnoreExisting, false, false);
            }
            if (eb > 0)
            {
                int newEB = 1 + delta / 5;
                if (newEB > eb)
                {
                    newEB = eb;
                }

                ItemProperty ip = _.ItemPropertyEnhancementPenalty(newEB);
                ip = _.TagItemProperty(ip, IPEquipmentPenaltyTag);
                BiowareXP2.IPSafeAddItemProperty(oItem, ip, 0.0f, AddItemPropertyPolicy.IgnoreExisting, false, false);
            }
        }
Beispiel #12
0
        private static void ApplyWeaponPenalties(NWPlayer oPC, NWItem oItem)
        {
            SkillType skillType = ItemService.GetSkillTypeForItem(oItem);

            if (skillType == SkillType.Unknown ||
                skillType == SkillType.HeavyArmor ||
                skillType == SkillType.LightArmor ||
                skillType == SkillType.ForceArmor ||
                skillType == SkillType.Shields)
            {
                return;
            }

            int skillID         = (int)skillType;
            int rank            = GetPCSkillRank(oPC, skillID);
            int recommendedRank = oItem.RecommendedLevel;

            if (rank >= recommendedRank)
            {
                return;
            }

            int delta = rank - recommendedRank;
            int penalty;

            if (delta <= -20)
            {
                penalty = 99;
            }
            else if (delta <= -16)
            {
                penalty = 5;
            }
            else if (delta <= -12)
            {
                penalty = 4;
            }
            else if (delta <= -8)
            {
                penalty = 3;
            }
            else if (delta <= -4)
            {
                penalty = 2;
            }
            else if (delta <= 0)
            {
                penalty = 1;
            }
            else
            {
                penalty = 99;
            }

            // No combat damage penalty
            if (penalty == 99)
            {
                ItemProperty noDamage = _.ItemPropertyNoDamage();
                noDamage = _.TagItemProperty(noDamage, IPWeaponPenaltyTag);
                BiowareXP2.IPSafeAddItemProperty(oItem, noDamage, 0.0f, AddItemPropertyPolicy.ReplaceExisting, false, false);
                penalty = 5; // Reset to 5 so that the following penalties apply.
            }

            // Decreased attack penalty
            ItemProperty ipPenalty = _.ItemPropertyAttackPenalty(penalty);

            ipPenalty = _.TagItemProperty(ipPenalty, IPWeaponPenaltyTag);
            BiowareXP2.IPSafeAddItemProperty(oItem, ipPenalty, 0.0f, AddItemPropertyPolicy.ReplaceExisting, false, false);

            // Decreased damage penalty
            ipPenalty = _.ItemPropertyDamagePenalty(penalty);
            ipPenalty = _.TagItemProperty(ipPenalty, IPWeaponPenaltyTag);
            BiowareXP2.IPSafeAddItemProperty(oItem, ipPenalty, 0.0f, AddItemPropertyPolicy.ReplaceExisting, false, false);

            // Decreased enhancement bonus penalty
            ipPenalty = _.ItemPropertyEnhancementPenalty(penalty);
            ipPenalty = _.TagItemProperty(ipPenalty, IPWeaponPenaltyTag);
            BiowareXP2.IPSafeAddItemProperty(oItem, ipPenalty, 0.0f, AddItemPropertyPolicy.ReplaceExisting, false, false);

            oPC.SendMessage("A penalty has been applied to your weapon '" + oItem.Name + "' due to your skill being under the recommended level.");
        }
Beispiel #13
0
        private static void OnModuleApplyDamage()
        {
            var data = NWNXDamage.GetDamageEventData();

            if (data.Base <= 0)
            {
                return;
            }

            NWObject damager = data.Damager;

            if (!damager.IsPlayer)
            {
                return;
            }
            NWCreature target = _.OBJECT_SELF;

            // Check that this was a normal attack, and not (say) a damage over time effect.
            if (target.GetLocalInt(AbilityService.LAST_ATTACK + damager.GlobalID) != AbilityService.ATTACK_PHYSICAL)
            {
                return;
            }

            NWItem weapon = (_.GetLastWeaponUsed(damager.Object));

            if (!weapon.IsValid)
            {
                // Double weapons don't show up correctly when their offhand makes an attack.
                // So check for that case here.
                if (_.GetObjectType(damager) == ObjectType.Creature)
                {
                    NWCreature attacker = data.Damager.Object;

                    if (attacker.RightHand.BaseItemType == BaseItem.Saberstaff ||
                        attacker.RightHand.BaseItemType == BaseItem.TwoBladedSword ||
                        attacker.RightHand.BaseItemType == BaseItem.DoubleAxe ||
                        attacker.RightHand.BaseItemType == BaseItem.DireMace)
                    {
                        weapon = attacker.RightHand;
                    }
                }
            }

            int damageBonus = weapon.DamageBonus;

            NWPlayer  player    = (damager.Object);
            int       itemLevel = weapon.RecommendedLevel;
            SkillType skill     = ItemService.GetSkillTypeForItem(weapon);

            if (skill == SkillType.Unknown)
            {
                return;
            }

            int rank  = SkillService.GetPCSkillRank(player, skill);
            int delta = itemLevel - rank;

            if (delta >= 1)
            {
                damageBonus--;
            }
            damageBonus = damageBonus - delta / 5;

            if (damageBonus <= 0)
            {
                damageBonus = 0;
            }

            data.Base += damageBonus;
            NWNXDamage.SetDamageEventData(data);
        }
        public static void ApplyComponentBonus(NWItem product, ItemProperty sourceIP)
        {
            ComponentBonusType bonusType = (ComponentBonusType)_.GetItemPropertySubType(sourceIP);
            int          amount          = _.GetItemPropertyCostTableValue(sourceIP);
            ItemProperty prop            = null;
            string       sourceTag       = string.Empty;

            // A note about the sourceTags:
            // It's not currently possible to create custom item properties on items. To get around this,
            // we look in an inaccessible container which holds the custom item properties. Then, we get the
            // item that has the item property we want. From there we take that item property and copy it to
            // the crafted item.
            // This is a really roundabout way to do it, but it's the only option for now. Hopefully a feature to
            // directly add the item properties comes in to NWNX in the future.
            for (int x = 1; x <= amount; x++)
            {
                switch (bonusType)
                {
                case ComponentBonusType.ModSocketRed:
                    sourceTag = "rslot_red";
                    break;

                case ComponentBonusType.ModSocketBlue:
                    sourceTag = "rslot_blue";
                    break;

                case ComponentBonusType.ModSocketGreen:
                    sourceTag = "rslot_green";
                    break;

                case ComponentBonusType.ModSocketYellow:
                    sourceTag = "rslot_yellow";
                    break;

                case ComponentBonusType.ModSocketPrismatic:
                    sourceTag = "rslot_prismatic";
                    break;

                case ComponentBonusType.DurabilityUp:
                    var maxDur = DurabilityService.GetMaxDurability(product) + amount;
                    DurabilityService.SetMaxDurability(product, maxDur);
                    DurabilityService.SetDurability(product, maxDur);
                    break;

                case ComponentBonusType.ChargesUp:
                    product.Charges += amount;
                    break;

                case ComponentBonusType.ACUp:
                    product.CustomAC += amount;
                    break;

                case ComponentBonusType.HarvestingUp:
                    product.HarvestingBonus += amount;
                    break;

                case ComponentBonusType.CastingSpeedUp:
                    product.CastingSpeed += amount;
                    break;

                case ComponentBonusType.ArmorsmithUp:
                    product.CraftBonusArmorsmith += amount;
                    break;

                case ComponentBonusType.WeaponsmithUp:
                    product.CraftBonusWeaponsmith += amount;
                    break;

                case ComponentBonusType.CookingUp:
                    product.CraftBonusCooking += amount;
                    break;

                case ComponentBonusType.EngineeringUp:
                    product.CraftBonusEngineering += amount;
                    break;

                case ComponentBonusType.FabricationUp:
                    product.CraftBonusFabrication += amount;
                    break;

                case ComponentBonusType.HPUp:
                    product.HPBonus += amount;
                    break;

                case ComponentBonusType.FPUp:
                    product.FPBonus += amount;
                    break;

                case ComponentBonusType.EnmityUp:
                    product.EnmityRate += amount;
                    break;

                case ComponentBonusType.EnmityDown:
                    product.EnmityRate -= amount;
                    break;

                case ComponentBonusType.DarkPotencyUp:
                    product.DarkPotencyBonus += amount;
                    break;

                case ComponentBonusType.LightPotencyUp:
                    product.LightPotencyBonus += amount;
                    break;

                case ComponentBonusType.MindPotencyUp:
                    product.MindPotencyBonus += amount;
                    break;

                case ComponentBonusType.LuckUp:
                    product.LuckBonus += amount;
                    break;

                case ComponentBonusType.MeditateUp:
                    product.MeditateBonus += amount;
                    break;

                case ComponentBonusType.RestUp:
                    product.RestBonus += amount;
                    break;

                case ComponentBonusType.MedicineUp:
                    product.MedicineBonus += amount;
                    break;

                case ComponentBonusType.HPRegenUp:
                    product.HPRegenBonus += amount;
                    break;

                case ComponentBonusType.FPRegenUp:
                    product.FPRegenBonus += amount;
                    break;

                case ComponentBonusType.BaseAttackBonusUp:
                    product.BaseAttackBonus += amount;
                    break;

                case ComponentBonusType.SneakAttackUp:
                    product.SneakAttackBonus += amount;
                    break;

                case ComponentBonusType.DamageUp:
                    product.DamageBonus += amount;
                    break;

                case ComponentBonusType.DarkPotencyDown:
                    product.DarkPotencyBonus -= amount;
                    break;

                case ComponentBonusType.LightPotencyDown:
                    product.LightPotencyBonus -= amount;
                    break;

                case ComponentBonusType.StructureBonusUp:
                    product.StructureBonus += amount;
                    break;

                case ComponentBonusType.StrengthUp:
                    product.StrengthBonus += amount;
                    break;

                case ComponentBonusType.DexterityUp:
                    product.DexterityBonus += amount;
                    break;

                case ComponentBonusType.ConstitutionUp:
                    product.ConstitutionBonus += amount;
                    break;

                case ComponentBonusType.WisdomUp:
                    product.WisdomBonus += amount;
                    break;

                case ComponentBonusType.IntelligenceUp:
                    product.IntelligenceBonus += amount;
                    break;

                case ComponentBonusType.CharismaUp:
                    product.CharismaBonus += amount;
                    break;

                case ComponentBonusType.AttackBonusUp:
                    prop = _.ItemPropertyAttackBonus(amount);
                    break;

                case ComponentBonusType.DurationUp:
                    product.DurationBonus += amount;
                    break;

                case ComponentBonusType.ScanningUp:
                    product.ScanningBonus += amount;
                    break;

                case ComponentBonusType.ScavengingUp:
                    product.ScavengingBonus += amount;
                    break;

                case ComponentBonusType.MindPotencyDown:
                    product.MindPotencyBonus -= amount;
                    break;

                case ComponentBonusType.ElectricalPotencyUp:
                    product.ElectricalPotencyBonus += amount;
                    break;

                case ComponentBonusType.ElectricalPotencyDown:
                    product.ElectricalPotencyBonus -= amount;
                    break;

                case ComponentBonusType.ForcePotencyUp:
                    product.ForcePotencyBonus += amount;
                    break;

                case ComponentBonusType.ForcePotencyDown:
                    product.ForcePotencyBonus -= amount;
                    break;

                case ComponentBonusType.ForceAccuracyUp:
                    product.ForceAccuracyBonus += amount;
                    break;

                case ComponentBonusType.ForceAccuracyDown:
                    product.ForceAccuracyBonus -= amount;
                    break;

                case ComponentBonusType.ForceDefenseUp:
                    product.ForceDefenseBonus += amount;
                    break;

                case ComponentBonusType.ForceDefenseDown:
                    product.ForceDefenseBonus -= amount;
                    break;

                case ComponentBonusType.ElectricalDefenseUp:
                    product.ElectricalDefenseBonus += amount;
                    break;

                case ComponentBonusType.ElectricalDefenseDown:
                    product.ElectricalDefenseBonus -= amount;
                    break;

                case ComponentBonusType.MindDefenseUp:
                    product.MindDefenseBonus += amount;
                    break;

                case ComponentBonusType.MindDefenseDown:
                    product.MindDefenseBonus -= amount;
                    break;

                case ComponentBonusType.LightDefenseUp:
                    product.LightDefenseBonus += amount;
                    break;

                case ComponentBonusType.LightDefenseDown:
                    product.LightDefenseBonus -= amount;
                    break;

                case ComponentBonusType.DarkDefenseUp:
                    product.DarkDefenseBonus += amount;
                    break;

                case ComponentBonusType.DarkDefenseDown:
                    product.DarkDefenseBonus -= amount;
                    break;

                case ComponentBonusType.PilotingUp:
                    product.PilotingBonus += amount;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                if (!string.IsNullOrWhiteSpace(sourceTag))
                {
                    prop = ItemService.GetCustomItemPropertyByItemTag(sourceTag);
                }

                if (prop == null)
                {
                    return;
                }

                BiowareXP2.IPSafeAddItemProperty(product, prop, 0.0f, AddItemPropertyPolicy.IgnoreExisting, true, true);
            }
        }