예제 #1
0
        private static void OnModuleApplyDamage()
        {
            var data = NWNXDamage.GetDamageEventData();

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

            NWObject damager = data.Damager;

            if (!damager.IsPlayer)
            {
                return;
            }
            NWCreature target = NWGameObject.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));
            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);
        }
예제 #2
0
        private static void OnHitCastSpell()
        {
            NWPlayer oPC = Object.OBJECT_SELF;

            if (!oPC.IsValid || !oPC.IsPlayer)
            {
                return;
            }
            NWItem     oSpellOrigin = (_.GetSpellCastItem());
            NWCreature oTarget      = (_.GetSpellTargetObject());

            SkillType skillType = ItemService.GetSkillTypeForItem(oSpellOrigin);

            if (skillType == SkillType.Unknown ||
                skillType == SkillType.LightArmor ||
                skillType == SkillType.HeavyArmor ||
                skillType == SkillType.ForceArmor ||
                skillType == SkillType.Shields)
            {
                return;
            }
            if (oTarget.IsPlayer || oTarget.IsDM)
            {
                return;
            }
            if (oTarget.ObjectType != OBJECT_TYPE_CREATURE)
            {
                return;
            }

            int skillID = (int)skillType;
            CreatureSkillRegistration reg = GetCreatureSkillRegistration(oTarget.GlobalID);
            int rank = GetPCSkillRank(oPC, skillID);

            reg.AddSkillRegistrationPoint(oPC, skillID, oSpellOrigin.RecommendedLevel, rank);

            // Add a registration point if a shield is equipped. This is to prevent players from swapping out a weapon for a shield
            // just before they kill an enemy.
            NWItem oShield = oPC.LeftHand;

            if (oShield.BaseItemType == BASE_ITEM_SMALLSHIELD ||
                oShield.BaseItemType == BASE_ITEM_LARGESHIELD ||
                oShield.BaseItemType == BASE_ITEM_TOWERSHIELD)
            {
                rank = GetPCSkillRank(oPC, SkillType.Shields);
                reg.AddSkillRegistrationPoint(oPC, (int)SkillType.Shields, oShield.RecommendedLevel, rank);
            }
        }
예제 #3
0
        private 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 = 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));
            }
        }
예제 #4
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);
                }
            }
        }
예제 #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.
        }
예제 #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);
                }
            }
        }
예제 #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.
        }
예제 #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);
        }
예제 #9
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);
            }
        }
예제 #10
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.");
        }
예제 #11
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);
        }