Пример #1
0
        public static int CalculateItemPotencyBonus(NWCreature caster, ForceAbilityType abilityType)
        {
            if (!caster.IsPlayer)
            {
                return(0);
            }
            EffectiveItemStats itemStats = PlayerStatService.GetPlayerItemEffectiveStats(caster.Object);

            int itemBonus = itemStats.ForcePotency;

            switch (abilityType)
            {
            case ForceAbilityType.Electrical:
                itemBonus += itemStats.ElectricalPotency;
                break;

            case ForceAbilityType.Mind:
                itemBonus += itemStats.MindPotency;
                break;

            case ForceAbilityType.Light:
                itemBonus += itemStats.LightPotency;
                break;

            case ForceAbilityType.Dark:
                itemBonus += itemStats.DarkPotency;
                break;

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

            return(itemBonus);
        }
Пример #2
0
        private static void HandleRegenerationTick(NWPlayer oPC, Player entity)
        {
            entity.RegenerationTick = entity.RegenerationTick - 1;
            int rate   = 5;
            int amount = entity.HPRegenerationAmount;


            if (entity.RegenerationTick <= 0)
            {
                if (oPC.CurrentHP < oPC.MaxHP)
                {
                    var effectiveStats = PlayerStatService.GetPlayerItemEffectiveStats(oPC);
                    // CON bonus
                    int con = (oPC.ConstitutionModifier / 2);
                    if (con > 0)
                    {
                        amount += con;
                    }
                    amount += effectiveStats.HPRegen;

                    if (oPC.Chest.CustomItemType == CustomItemType.HeavyArmor)
                    {
                        int sturdinessLevel = PerkService.GetCreaturePerkLevel(oPC, PerkType.Sturdiness);
                        if (sturdinessLevel > 0)
                        {
                            amount += sturdinessLevel + 1;
                        }
                    }
                    ApplyEffectToObject(DurationType.Instant, EffectHeal(amount), oPC.Object);
                }

                entity.RegenerationTick = rate;
            }
        }
Пример #3
0
        private static void HandleFPRegenerationTick(NWPlayer oPC, Player entity)
        {
            entity.CurrentFPTick = entity.CurrentFPTick - 1;
            int rate   = 5;
            int amount = 1;

            if (entity.CurrentFPTick <= 0)
            {
                if (entity.CurrentFP < entity.MaxFP)
                {
                    var effectiveStats = PlayerStatService.GetPlayerItemEffectiveStats(oPC);
                    // CHA bonus
                    int cha = oPC.CharismaModifier;
                    if (cha > 0)
                    {
                        amount += cha;
                    }
                    amount += effectiveStats.FPRegen;

                    if (oPC.Chest.CustomItemType == CustomItemType.ForceArmor)
                    {
                        int clarityLevel = PerkService.GetCreaturePerkLevel(oPC, PerkType.Clarity);
                        if (clarityLevel > 0)
                        {
                            amount += clarityLevel + 1;
                        }
                    }

                    entity = AbilityService.RestorePlayerFP(oPC, amount, entity);
                }

                entity.CurrentFPTick = rate;
            }
        }
Пример #4
0
        private static void HandleRegenerationTick(NWPlayer oPC, Data.Entity.Player entity)
        {
            entity.RegenerationTick = entity.RegenerationTick - 1;
            int rate   = 20;
            int amount = entity.HPRegenerationAmount;

            if (entity.RegenerationTick <= 0)
            {
                if (oPC.CurrentHP < oPC.MaxHP)
                {
                    var effectiveStats = PlayerStatService.GetPlayerItemEffectiveStats(oPC);
                    // CON bonus
                    int con = oPC.ConstitutionModifier;
                    if (con > 0)
                    {
                        amount += con;
                    }
                    amount += effectiveStats.HPRegen;

                    if (oPC.Chest.CustomItemType == CustomItemType.HeavyArmor)
                    {
                        int sturdinessLevel = PerkService.GetPCPerkLevel(oPC, PerkType.Sturdiness);
                        if (sturdinessLevel > 0)
                        {
                            amount += sturdinessLevel + 1;
                        }
                    }
                    _.ApplyEffectToObject(_.DURATION_TYPE_INSTANT, _.EffectHeal(amount), oPC.Object);
                }

                entity.RegenerationTick = rate;
            }
        }
Пример #5
0
        private static void LoadCharacter()
        {
            NWPlayer player = GetEnteringObject();

            if (!player.IsPlayer)
            {
                return;
            }

            Player entity = GetPlayerEntity(player.GlobalID);

            if (entity == null)
            {
                return;
            }

            int hp = player.CurrentHP;
            int damage;

            if (entity.HitPoints < 0)
            {
                damage = hp + Math.Abs(entity.HitPoints);
            }
            else
            {
                damage = hp - entity.HitPoints;
            }

            if (damage != 0)
            {
                ApplyEffectToObject(DurationType.Instant, EffectDamage(damage), player);
            }

            // Handle item stats
            for (int itemSlot = 0; itemSlot < NumberOfInventorySlots; itemSlot++)
            {
                NWItem item = _.GetItemInSlot((InventorySlot)itemSlot, player);
                PlayerStatService.CalculateEffectiveStats(player, item);
            }
            PlayerStatService.ApplyStatChanges(player, null);


            player.IsBusy = false; // Just in case player logged out in the middle of an action.

            // Cleanup code in case people log out as spaceships.
            var appearance = (AppearanceType)player.Chest.GetLocalInt("APPEARANCE");

            if (appearance > 0 && appearance != GetAppearanceType(player))
            {
                SetCreatureAppearanceType(player, appearance);
                SetObjectVisualTransform(player, ObjectVisualTransform.Scale, 1.0f);
            }
        }
Пример #6
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");
        }
Пример #7
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;
            }
        }
Пример #8
0
        private static void OnModuleUnequipItem()
        {
            NWPlayer oPC = _.GetPCItemLastUnequippedBy();

            if (oPC.GetLocalInt("IS_CUSTOMIZING_ITEM") == _.TRUE)
            {
                return;                                                   // Don't run heavy code when customizing equipment.
            }
            NWItem oItem = _.GetPCItemLastUnequipped();

            HandleGlovesUnequipEvent();
            PlayerStatService.ApplyStatChanges(oPC, oItem);
            RemoveWeaponPenalties(oItem);
            RemoveEquipmentPenalties(oItem);
        }
Пример #9
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);
            }
        }
Пример #10
0
        private static void OnModuleEquipItem()
        {
            NWPlayer oPC = _.GetPCItemLastEquippedBy();

            if (oPC.GetLocalInt("IS_CUSTOMIZING_ITEM") == _.TRUE)
            {
                return;                                                   // Don't run heavy code when customizing equipment.
            }
            if (!oPC.IsInitializedAsPlayer)
            {
                return;                             // Players who log in for the first time don't have an ID yet.
            }
            if (oPC.GetLocalInt("LOGGED_IN_ONCE") <= 0)
            {
                return;                                         // Don't fire heavy calculations if this is the player's first log in after a restart.
            }
            NWItem oItem = _.GetPCItemLastEquipped();

            PlayerStatService.ApplyStatChanges(oPC, null);
            ApplyWeaponPenalties(oPC, oItem);
            ApplyEquipmentPenalties(oPC, oItem);
        }
Пример #11
0
        public static void GiveSkillXP(NWPlayer oPC, int skillID, int xp, bool enableResidencyBonus = true)
        {
            if (skillID <= 0 || xp <= 0 || !oPC.IsPlayer)
            {
                return;
            }

            if (enableResidencyBonus)
            {
                xp = (int)(xp + xp * PlayerStatService.EffectiveResidencyBonus(oPC));
            }
            Player player = DataService.Get <Player>(oPC.GlobalID);
            Skill  skill  = GetSkill(skillID);

            // Check if the player has any undistributed skill ranks for this skill category.
            // If they haven't been distributed yet, the player CANNOT gain XP for this skill.
            var pool = DataService.SingleOrDefault <PCSkillPool>(x => x.PlayerID == oPC.GlobalID &&
                                                                 x.SkillCategoryID == skill.SkillCategoryID &&
                                                                 x.Levels > 0);

            if (pool != null)
            {
                oPC.FloatingText("You must distribute all pooled skill ranks before you can gain any new XP in the '" + skill.Name + "' skill. Access this menu from the 'View Skills' section of your rest menu.");
                return;
            }


            PCSkill            pcSkill = GetPCSkill(oPC, skillID);
            SkillXPRequirement req     = DataService.Single <SkillXPRequirement>(x => x.SkillID == skillID && x.Rank == pcSkill.Rank);
            int   maxRank         = skill.MaxRank;
            int   originalRank    = pcSkill.Rank;
            float xpBonusModifier = player.XPBonus * 0.01f;

            // Guard against XP bonuses being too high.
            if (xpBonusModifier > 0.25)
            {
                xpBonusModifier = 0.25f;
            }

            xp = CalculateTotalSkillPointsPenalty(player.TotalSPAcquired, xp);
            xp = xp + (int)(xp * xpBonusModifier);

            // Run the skill decay rules.
            // If the method returns false, that means all skills are locked.
            // So we can't give the player any XP.
            if (!ApplySkillDecay(oPC, pcSkill, xp))
            {
                return;
            }


            pcSkill.XP = pcSkill.XP + xp;
            oPC.SendMessage("You earned " + skill.Name + " skill experience. (" + xp + ")");

            // Skill is at cap and player would level up.
            // Reduce XP to required amount minus 1 XP
            if (pcSkill.Rank >= maxRank && pcSkill.XP > req.XP)
            {
                pcSkill.XP = req.XP - 1;
            }

            while (pcSkill.XP >= req.XP)
            {
                pcSkill.XP = pcSkill.XP - req.XP;

                if (player.TotalSPAcquired < SkillCap && skill.ContributesToSkillCap)
                {
                    player.UnallocatedSP++;
                    player.TotalSPAcquired++;
                }

                pcSkill.Rank++;
                oPC.FloatingText("Your " + skill.Name + " skill level increased to rank " + pcSkill.Rank + "!");
                req = DataService.Single <SkillXPRequirement>(x => x.SkillID == skillID && x.Rank == pcSkill.Rank);

                // Reapply skill penalties on a skill level up.
                for (int slot = 0; slot < NUM_INVENTORY_SLOTS; slot++)
                {
                    NWItem item = _.GetItemInSlot(slot, oPC.Object);
                    RemoveWeaponPenalties(item);
                    ApplyWeaponPenalties(oPC, item);
                    RemoveEquipmentPenalties(item);
                    ApplyEquipmentPenalties(oPC, item);
                }

                MessageHub.Instance.Publish(new SkillGainedMessage(oPC, skillID));
            }

            DataService.SubmitDataChange(pcSkill, DatabaseActionType.Update);

            // Update player and apply stat changes only if a level up occurred.
            if (originalRank != pcSkill.Rank)
            {
                PlayerStatService.ApplyStatChanges(oPC, null);
            }
        }
Пример #12
0
        private static bool ApplySkillDecay(NWPlayer oPC, PCSkill levelingSkill, int xp)
        {
            int totalSkillRanks = GetPCTotalSkillCount(oPC);

            if (totalSkillRanks < SkillCap)
            {
                return(true);
            }

            // Find out if we have enough XP to remove. If we don't, make no changes and return false signifying no XP could be removed.
            var pcSkills = DataService.Where <PCSkill>(x => x.PlayerID == oPC.GlobalID && x.SkillID != levelingSkill.SkillID);
            var totalXPs = pcSkills.Select(s =>
            {
                var reqXP   = DataService.Where <SkillXPRequirement>(x => x.SkillID == s.SkillID && (x.Rank < s.Rank || x.Rank == 0 && s.XP > 0));
                var totalXP = reqXP.Sum(x => x.XP);
                return(new { s.SkillID, TotalSkillXP = totalXP });
            }).ToList();

            int aggregateXP = 0;

            foreach (var p in totalXPs)
            {
                aggregateXP += p.TotalSkillXP;
            }
            if (aggregateXP < xp)
            {
                return(false);
            }

            // We have enough XP to remove. Reduce XP, picking random skills each time we reduce.
            var skillsPossibleToDecay = GetAllPCSkills(oPC)
                                        .Where(x =>
            {
                var skill = DataService.Get <Skill>(x.SkillID);
                return(!x.IsLocked &&
                       skill.ContributesToSkillCap &&
                       x.SkillID != levelingSkill.SkillID &&
                       (x.XP > 0 || x.Rank > 0));
            }).ToList();

            // There's an edge case where players can be at the cap, but we're unable to find a skill to decay.
            // In this scenario we can't go any further. Return false which will cause the GiveSkillXP method to
            // bail out with no changes to XP or decayed skills.
            if (skillsPossibleToDecay.Count <= 0)
            {
                return(false);
            }

            while (xp > 0)
            {
                int     skillIndex        = RandomService.Random(skillsPossibleToDecay.Count);
                PCSkill decaySkill        = skillsPossibleToDecay[skillIndex];
                int     totalDecaySkillXP = totalXPs.Find(x => x.SkillID == decaySkill.SkillID).TotalSkillXP;
                int     oldRank           = decaySkill.Rank;

                if (totalDecaySkillXP >= xp)
                {
                    totalDecaySkillXP = totalDecaySkillXP - xp;
                    xp = 0;
                }
                else if (totalDecaySkillXP < xp)
                {
                    totalDecaySkillXP = 0;
                    xp = xp - totalDecaySkillXP;
                }

                // If skill drops to 0 total XP, remove it from the possible list of skills
                if (totalDecaySkillXP <= 0)
                {
                    skillsPossibleToDecay.Remove(decaySkill);
                    decaySkill.XP   = 0;
                    decaySkill.Rank = 0;
                }
                // Otherwise calculate what rank and XP value the skill should now be.
                else
                {
                    // Get the XP amounts required per level, in ascending order, so we can see how many levels we're now meant to have.
                    List <SkillXPRequirement> reqs = DataService.Where <SkillXPRequirement>(x => x.SkillID == decaySkill.SkillID && x.Rank <= decaySkill.Rank).OrderBy(o => o.Rank).ToList();


                    // The first entry in the database is for rank 0, and if passed, will raise us to 1.  So start our count at 0.
                    int newDecaySkillRank = 0;
                    foreach (SkillXPRequirement req in reqs)
                    {
                        if (totalDecaySkillXP >= req.XP)
                        {
                            totalDecaySkillXP = totalDecaySkillXP - req.XP;
                            newDecaySkillRank++;
                        }
                        else if (totalDecaySkillXP < req.XP)
                        {
                            break;
                        }
                    }

                    decaySkill.Rank = newDecaySkillRank;
                    decaySkill.XP   = totalDecaySkillXP;
                }

                PCSkill dbDecaySkill = new PCSkill
                {
                    SkillID  = decaySkill.SkillID,
                    IsLocked = decaySkill.IsLocked,
                    ID       = decaySkill.ID,
                    PlayerID = decaySkill.PlayerID,
                    Rank     = decaySkill.Rank,
                    XP       = decaySkill.XP
                };
                DataService.SubmitDataChange(dbDecaySkill, DatabaseActionType.Update);
                MessageHub.Instance.Publish(new SkillDecayedMessage(oPC, decaySkill.SkillID, oldRank, decaySkill.Rank));
            }

            PlayerStatService.ApplyStatChanges(oPC, null);
            return(true);
        }
Пример #13
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);
        }
Пример #14
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);
        }
Пример #15
0
        public static void InitializePlayer(NWPlayer player)
        {
            if (player == null)
            {
                throw new ArgumentNullException(nameof(player));
            }
            if (!player.IsPlayer)
            {
                return;
            }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                var classType = GetClassByPosition(1, player);

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

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

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

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

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

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

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

                InitializeHotBar(player);
            }
        }
Пример #16
0
        public static void InitializePlayer(NWPlayer player)
        {
            if (player == null)
            {
                throw new ArgumentNullException(nameof(player));
            }
            if (player.Object == null)
            {
                throw new ArgumentNullException(nameof(player.Object));
            }
            if (!player.IsPlayer)
            {
                return;
            }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                InitializeHotBar(player);
            }
        }