Example #1
0
        public static int CalculateChanceForComponentBonus(NWPlayer player, int tier, ResourceQuality quality, bool scavenging = false)
        {
            int rank       = (scavenging ? SkillService.GetPCSkillRank(player, SkillType.Scavenging) : SkillService.GetPCSkillRank(player, SkillType.Harvesting));
            int difficulty = (tier - 1) * 10 + GetDifficultyAdjustment(quality);
            int delta      = difficulty - rank;

            if (delta >= 7)
            {
                return(0);
            }
            if (delta <= -7)
            {
                return(45);
            }

            int chance = 0;

            switch (delta)
            {
            case 6: chance = 1; break;

            case 5: chance = 2; break;

            case 4: chance = 3; break;

            case 3: chance = 6; break;

            case 2: chance = 9; break;

            case 1: chance = 12; break;

            case 0: chance = 15; break;

            case -1: chance = 18; break;

            case -2: chance = 20; break;

            case -3: chance = 21; break;

            case -4: chance = 23; break;

            case -5: chance = 25; break;

            case -6: chance = 27; break;
            }

            var effectiveStats = PlayerStatService.GetPlayerItemEffectiveStats(player);
            int itemBonus      = (scavenging ? effectiveStats.Scavenging : effectiveStats.Harvesting) / 2;

            if (itemBonus > 30)
            {
                itemBonus = 30;
            }
            chance += itemBonus;

            return(chance);
        }
Example #2
0
        private static void HandleApplySneakAttackDamage()
        {
            DamageEventData data = NWNXDamage.GetDamageEventData();

            if (data.Total <= 0)
            {
                return;
            }
            NWObject damager         = data.Damager;
            int      sneakAttackType = damager.GetLocalInt("SNEAK_ATTACK_ACTIVE");

            if (damager.IsPlayer && sneakAttackType > 0)
            {
                NWPlayer   player    = damager.Object;
                NWCreature target    = _.OBJECT_SELF;
                var        pcPerk    = PerkService.GetPCPerkByID(damager.GlobalID, (int)PerkType.SneakAttack);
                int        perkRank  = pcPerk?.PerkLevel ?? 0;
                int        perkBonus = 1;

                // Rank 4 increases damage bonus by 2x (total: 3x)
                if (perkRank == 4)
                {
                    perkBonus = 2;
                }

                float perkRate;
                if (sneakAttackType == 1) // Player is behind target.
                {
                    perkRate = 1.0f * perkBonus;
                }
                else // Player is anywhere else.
                {
                    perkRate = 0.5f * perkBonus;
                }

                var   effectiveStats = PlayerStatService.GetPlayerItemEffectiveStats(player);
                float damageRate     = 1.0f + perkRate + effectiveStats.SneakAttack * 0.05f;
                data.Base = (int)(data.Base * damageRate);

                if (target.IsNPC)
                {
                    EnmityService.AdjustEnmity(target, player, 5 * data.Base);
                }

                NWNXDamage.SetDamageEventData(data);
            }

            damager.DeleteLocalInt("SNEAK_ATTACK_ACTIVE");
        }
Example #3
0
        public static void AdjustEnmity(NWCreature npc, NWCreature attacker, int volatileAdjust, int cumulativeAdjust = 0)
        {
            if (!npc.IsNPC)
            {
                return;
            }
            if (attacker == null || attacker.Area != npc.Area || LineOfSightObject(npc, attacker) == false)
            {
                return;
            }

            bool adjustVolatile   = volatileAdjust != 0;
            bool adjustCumulative = cumulativeAdjust != 0;

            float effectiveEnmityRate = 1.0f;

            if (attacker.IsPlayer)
            {
                NWPlayer player         = (attacker.Object);
                var      effectiveStats = PlayerStatService.GetPlayerItemEffectiveStats(player);
                effectiveEnmityRate = effectiveStats.EnmityRate;
            }

            volatileAdjust   = (int)(effectiveEnmityRate * volatileAdjust);
            cumulativeAdjust = (int)(effectiveEnmityRate * cumulativeAdjust);

            var table = GetEnmityTable(npc);

            // If this is the first creature to go on the enmity table, immediately attack them so they aren't
            // waiting around to do something the next time their AI runs.
            if (table.Count <= 0)
            {
                npc.AssignCommand(() =>
                {
                    _.ActionAttack(attacker);
                });
            }

            var enmity = GetEnmity(npc, attacker);

            if (adjustVolatile)
            {
                enmity.VolatileAmount += volatileAdjust;
            }
            if (adjustCumulative)
            {
                enmity.CumulativeAmount += cumulativeAdjust;
            }
        }
Example #4
0
        public static void ApplyCooldown(NWCreature creature, CooldownCategory cooldown, IPerkHandler handler, int spellTier, float armorPenalty)
        {
            if (armorPenalty <= 0.0f)
            {
                armorPenalty = 1.0f;
            }

            // If player has a a cooldown recovery bonus on their equipment, apply that change now.

            if (creature.IsPlayer)
            {
                var effectiveStats = PlayerStatService.GetPlayerItemEffectiveStats(creature.Object);
                if (effectiveStats.CooldownRecovery > 0)
                {
                    armorPenalty -= (effectiveStats.CooldownRecovery * 0.01f);
                }
            }

            // There's a cap of 50% cooldown reduction from equipment.
            if (armorPenalty < 0.5f)
            {
                armorPenalty = 0.5f;
            }

            Console.WriteLine("armorPenalty final = " + armorPenalty);

            float    finalCooldown   = handler.CooldownTime(creature, (float)cooldown.BaseCooldownTime, spellTier) * armorPenalty;
            int      cooldownSeconds = (int)finalCooldown;
            int      cooldownMillis  = (int)((finalCooldown - cooldownSeconds) * 100);
            DateTime unlockDate      = DateTime.UtcNow.AddSeconds(cooldownSeconds).AddMilliseconds(cooldownMillis);

            if (creature.IsPlayer)
            {
                PCCooldown pcCooldown = DataService.Single <PCCooldown>(x => x.PlayerID == creature.GlobalID && x.CooldownCategoryID == cooldown.ID);
                pcCooldown.DateUnlocked = unlockDate;
                DataService.SubmitDataChange(pcCooldown, DatabaseActionType.Update);
            }
            else
            {
                string unlockDateString = unlockDate.ToString("yyyy-MM-dd hh:mm:ss");
                creature.SetLocalString("ABILITY_COOLDOWN_ID_" + (int)handler.PerkType, unlockDateString);
            }
        }
Example #5
0
        public static int CalculateReassemblyChance(NWPlayer player, int penalty)
        {
            const int BaseChance = 70;
            int harvesting = SkillService.GetPCSkillRank(player, SkillType.Harvesting);
            var itemBonuses = PlayerStatService.GetPlayerItemEffectiveStats(player);
            int perkLevel = PerkService.GetCreaturePerkLevel(player, PerkType.MolecularReassemblyProficiency);

            // Calculate the base chance after factoring in skills, perks, and items.
            int categoryChance = (int)(BaseChance + (harvesting / 2.5f) + perkLevel * 10 + itemBonuses.Harvesting / 3f);

            // Reduce the chance by the penalty. This penalty is generally determined by how many properties were already
            // applied during this batch.
            categoryChance -= penalty;

            // Keep bounds between 0 and 100
            if (categoryChance < 0) return 0;
            else if (categoryChance > 100) return 100;
            else return categoryChance;
        }
Example #6
0
        private static void ActivateAbility(NWPlayer pc,
                                            NWObject target,
                                            Data.Entity.Perk entity,
                                            IPerkHandler perkHandler,
                                            int pcPerkLevel,
                                            PerkExecutionType executionType,
                                            int spellFeatID)
        {
            string uuid               = Guid.NewGuid().ToString();
            var    effectiveStats     = PlayerStatService.GetPlayerItemEffectiveStats(pc);
            int    itemBonus          = effectiveStats.CastingSpeed;
            float  baseActivationTime = perkHandler.CastingTime(pc, (float)entity.BaseCastingTime, spellFeatID);
            float  activationTime     = baseActivationTime;
            int    vfxID              = -1;
            int    animationID        = -1;

            // Activation Bonus % - Shorten activation time.
            if (itemBonus > 0)
            {
                float activationBonus = Math.Abs(itemBonus) * 0.01f;
                activationTime = activationTime - activationTime * activationBonus;
            }
            // Activation Penalty % - Increase activation time.
            else if (itemBonus < 0)
            {
                float activationPenalty = Math.Abs(itemBonus) * 0.01f;
                activationTime = activationTime + activationTime * activationPenalty;
            }

            if (baseActivationTime > 0f && activationTime < 1.0f)
            {
                activationTime = 1.0f;
            }

            // Force ability armor penalties
            if (executionType == PerkExecutionType.ForceAbility)
            {
                float  armorPenalty   = 0.0f;
                string penaltyMessage = string.Empty;
                foreach (var item in pc.EquippedItems)
                {
                    if (item.CustomItemType == CustomItemType.HeavyArmor)
                    {
                        armorPenalty   = 2;
                        penaltyMessage = "Heavy armor slows your force activation speed by 100%.";
                        break;
                    }
                    else if (item.CustomItemType == CustomItemType.LightArmor)
                    {
                        armorPenalty   = 1.25f;
                        penaltyMessage = "Light armor slows your force activation speed by 25%.";
                    }
                }

                if (armorPenalty > 0.0f)
                {
                    activationTime = baseActivationTime * armorPenalty;
                    pc.SendMessage(penaltyMessage);
                }
            }

            if (_.GetActionMode(pc.Object, ACTION_MODE_STEALTH) == 1)
            {
                _.SetActionMode(pc.Object, ACTION_MODE_STEALTH, 0);
            }

            _.ClearAllActions();
            BiowarePosition.TurnToFaceObject(target, pc);

            if (executionType == PerkExecutionType.ForceAbility)
            {
                vfxID       = VFX_DUR_IOUNSTONE_YELLOW;
                animationID = ANIMATION_LOOPING_CONJURE1;
            }

            if (vfxID > -1)
            {
                var vfx = _.EffectVisualEffect(vfxID);
                vfx = _.TagEffect(vfx, "ACTIVATION_VFX");
                _.ApplyEffectToObject(DURATION_TYPE_TEMPORARY, vfx, pc.Object, activationTime + 0.2f);
            }

            if (animationID > -1)
            {
                pc.AssignCommand(() => _.ActionPlayAnimation(animationID, 1.0f, activationTime - 0.1f));
            }

            pc.IsBusy = true;
            CheckForSpellInterruption(pc, uuid, pc.Position);
            pc.SetLocalInt(uuid, (int)SpellStatusType.Started);

            NWNXPlayer.StartGuiTimingBar(pc, (int)activationTime, "");

            int perkID = entity.ID;

            pc.DelayEvent <FinishAbilityUse>(activationTime + 0.2f,
                                             pc,
                                             uuid,
                                             perkID,
                                             target,
                                             pcPerkLevel,
                                             spellFeatID);
        }
Example #7
0
        private static int CalculateForceAccuracy(
            NWCreature caster,
            NWCreature target,
            ForceAbilityType abilityType)
        {
            EffectiveItemStats casterItemStats = caster.IsPlayer ?
                                                 PlayerStatService.GetPlayerItemEffectiveStats(caster.Object) :
                                                 null;
            float casterPrimary;
            float casterSecondary;
            float casterItemAccuracy = casterItemStats?.ForceAccuracy ?? 0;

            EffectiveItemStats targetItemStats = target.IsPlayer ?
                                                 PlayerStatService.GetPlayerItemEffectiveStats(target.Object) :
                                                 null;
            float targetPrimary;
            float targetSecondary;
            float targetItemDefense = targetItemStats?.ForceDefense ?? 0;

            switch (abilityType)
            {
            case ForceAbilityType.Electrical:
                casterPrimary     = caster.Intelligence;
                casterSecondary   = caster.Wisdom;
                targetPrimary     = target.Intelligence;
                targetSecondary   = target.Wisdom;
                targetItemDefense = targetItemDefense + targetItemStats?.ElectricalDefense ?? 0;
                break;

            case ForceAbilityType.Dark:
                casterPrimary     = caster.Intelligence;
                casterSecondary   = caster.Wisdom;
                targetPrimary     = target.Wisdom;
                targetSecondary   = target.Intelligence;
                targetItemDefense = targetItemDefense + targetItemStats?.DarkDefense ?? 0;
                break;

            case ForceAbilityType.Mind:
                casterPrimary     = caster.Wisdom;
                casterSecondary   = caster.Intelligence;
                targetPrimary     = target.Wisdom;
                targetSecondary   = target.Intelligence;
                targetItemDefense = targetItemDefense + targetItemStats?.MindDefense ?? 0;
                break;

            case ForceAbilityType.Light:
                casterPrimary     = caster.Wisdom;
                casterSecondary   = caster.Intelligence;
                targetPrimary     = target.Intelligence;
                targetSecondary   = target.Wisdom;
                targetItemDefense = targetItemDefense + targetItemStats?.ElectricalDefense ?? 0;
                break;

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

            // Calculate accuracy based on the caster's primary and secondary stats. Add modifiers for overall item accuracy.
            float baseAccuracy = caster.Charisma * 0.25f + casterPrimary * 0.75f + casterSecondary * 0.5f + casterItemAccuracy * 0.15f;

            // Calculate defense based on target's primary and secondary stats. Add modifiers for specific defense types.
            float baseDefense = target.Charisma * 0.25f + targetPrimary * 0.75f + targetSecondary * 0.5f + targetItemDefense * 0.15f;

            // Temp defense increases whenever a hostile force ability is used. This is primarily a deterrant towards spamming the same ability over and over.
            string expiration = target.GetLocalString("TEMP_FORCE_DEFENSE_" + (int)abilityType);

            if (DateTime.TryParse(expiration, out var unused))
            {
                int tempDefense = target.GetLocalInt("TEMP_FORCE_DEFENSE_" + (int)abilityType);
                baseDefense += tempDefense;
            }


            float delta         = baseAccuracy - baseDefense;
            float finalAccuracy = delta < 0 ?
                                  75 + (float)Math.Floor(delta / 2.0f) :
                                  75 + delta;

            // Accuracy cannot go above 95% or below 0%
            if (finalAccuracy > 95)
            {
                finalAccuracy = 95;
            }
            else if (finalAccuracy < 0)
            {
                finalAccuracy = 0;
            }

            return((int)finalAccuracy);
        }