Example #1
0
        /// <summary>
        /// Gives GP to a player for a given guild.
        /// If the baseAmount is less than 1, nothing will happen.
        /// If the baseAmount is greater than 1000, the baseAmount will be set to 1000.
        /// If the player ranks up, a message will be sent to him/her and an OnPlayerGuildRankUp event will be published.
        /// </summary>
        /// <param name="player">The player to give GP.</param>
        /// <param name="guild">The guild this GP will apply to.</param>
        /// <param name="baseAmount">The baseAmount of GP to grant.</param>
        public static void GiveGuildPoints(NWPlayer player, GuildType guild, int baseAmount)
        {
            if (baseAmount <= 0)
            {
                return;
            }

            // Clamp max GP baseAmount
            if (baseAmount > 1000)
            {
                baseAmount = 1000;
            }

            // Grant a bonus based on the player's guild relations perk rank. Always offset by 1 so we don't end up with multiplication by zero.
            int perkBonus = PerkService.GetCreaturePerkLevel(player, PerkType.GuildRelations) + 1;

            baseAmount *= perkBonus;

            var dbGuild = DataService.Get <Guild>((int)guild);
            var pcGP    = DataService.Single <PCGuildPoint>(x => x.GuildID == (int)guild && x.PlayerID == player.GlobalID);

            pcGP.Points += baseAmount;

            // Clamp player GP to the highest rank.
            int maxRank = RankProgression.Keys.Max();
            int maxGP   = RankProgression[maxRank];

            if (pcGP.Points >= maxGP)
            {
                pcGP.Points = maxGP - 1;
            }

            // Notify player how much GP they earned.
            player.SendMessage("You earned " + baseAmount + " " + dbGuild.Name + " guild points.");

            // Are we able to rank up?
            bool didRankUp = false;

            if (pcGP.Rank < maxRank)
            {
                // Is it time for a rank up?
                int nextRank = RankProgression[pcGP.Rank];
                if (pcGP.Points >= nextRank)
                {
                    // Let's do a rank up.
                    pcGP.Rank++;
                    player.SendMessage(ColorTokenService.Green("You've reached rank " + pcGP.Rank + " in the " + dbGuild.Name + "!"));
                    didRankUp = true;
                }
            }

            // Submit changes to the DB/cache.
            DataService.SubmitDataChange(pcGP, DatabaseActionType.Update);

            // If the player ranked up, publish an event saying so.
            if (didRankUp)
            {
                MessageHub.Instance.Publish(new OnPlayerGuildRankUp(player.GlobalID, pcGP.Rank));
            }
        }
Example #2
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;
            }
        }
Example #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;
            }
        }
Example #4
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;
            }
        }
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 OnHitCastSpell()
        {
            NWPlayer oPC = Object.OBJECT_SELF;

            if (!oPC.IsValid)
            {
                return;
            }

            NWObject oTarget = _.GetSpellTargetObject();
            NWItem   oItem   = _.GetSpellCastItem();

            // If this method was triggered by our own armor (from getting hit), return.
            if (oItem.BaseItemType == BASE_ITEM_ARMOR)
            {
                return;
            }

            // Flag this attack as physical so that the damage scripts treat it properly.
            LoggingService.Trace(TraceComponent.LastAttack, "Setting attack type from " + oPC.GlobalID + " against " + _.GetName(oTarget) + " to physical (" + ATTACK_PHYSICAL.ToString() + ")");
            oTarget.SetLocalInt(LAST_ATTACK + oPC.GlobalID, ATTACK_PHYSICAL);

            HandleGrenadeProficiency(oPC, oTarget);
            HandlePlasmaCellPerk(oPC, oTarget);
            int activeWeaponSkillID = oPC.GetLocalInt("ACTIVE_WEAPON_SKILL");

            if (activeWeaponSkillID <= 0)
            {
                return;
            }
            int activeWeaponSkillFeatID = oPC.GetLocalInt("ACTIVE_WEAPON_SKILL_FEAT_ID");

            if (activeWeaponSkillFeatID < 0)
            {
                activeWeaponSkillFeatID = -1;
            }

            PCPerk entity  = DataService.GetAll <PCPerk>().Single(x => x.PlayerID == oPC.GlobalID && x.PerkID == activeWeaponSkillID);
            var    perk    = DataService.Get <Data.Entity.Perk>(entity.PerkID);
            var    handler = PerkService.GetPerkHandler(activeWeaponSkillID);

            if (handler.CanCastSpell(oPC, oTarget))
            {
                handler.OnImpact(oPC, oTarget, entity.PerkLevel, activeWeaponSkillFeatID);

                if (oTarget.IsNPC)
                {
                    ApplyEnmity(oPC, oTarget.Object, perk);
                }
            }
            else
            {
                oPC.SendMessage(handler.CannotCastSpellMessage(oPC, oTarget) ?? "That ability cannot be used at this time.");
            }

            oPC.DeleteLocalString("ACTIVE_WEAPON_SKILL_UUID");
            oPC.DeleteLocalInt("ACTIVE_WEAPON_SKILL");
            oPC.DeleteLocalInt("ACTIVE_WEAPON_SKILL_FEAT_ID");
        }
Example #7
0
        /// <summary>
        /// Processes all feats which are linked to perks.
        /// </summary>
        private static void OnModuleUseFeat()
        {
            // Activator is the creature who used the feat.
            // Target is who the activator selected to use this feat on.
            NWCreature activator = _.OBJECT_SELF;
            NWCreature target    = NWNXObject.StringToObject(NWNXEvents.GetEventData("TARGET_OBJECT_ID"));
            var        featID    = (Feat)Convert.ToInt32(NWNXEvents.GetEventData("FEAT_ID"));

            // Ensure this perk feat can be activated.
            if (!CanUsePerkFeat(activator, target, featID))
            {
                return;
            }

            // Retrieve information necessary for activation of perk feat.
            var perkFeat = DataService.PerkFeat.GetByFeatID((int)featID);

            Data.Entity.Perk perk = DataService.Perk.GetByID(perkFeat.PerkID);
            int creaturePerkLevel = PerkService.GetCreaturePerkLevel(activator, perk.ID);
            var handler           = PerkService.GetPerkHandler(perkFeat.PerkID);

            SendAOEMessage(activator, activator.Name + " readies " + perk.Name + ".");

            // Force Abilities (aka Spells)
            if (perk.ExecutionTypeID == PerkExecutionType.ForceAbility)
            {
                target.SetLocalInt(LAST_ATTACK + activator.GlobalID, ATTACK_FORCE);
                ActivateAbility(activator, target, perk, handler, creaturePerkLevel, PerkExecutionType.ForceAbility, perkFeat.PerkLevelUnlocked);
            }
            // Combat Abilities
            else if (perk.ExecutionTypeID == PerkExecutionType.CombatAbility)
            {
                target.SetLocalInt(LAST_ATTACK + activator.GlobalID, ATTACK_PHYSICAL);
                ActivateAbility(activator, target, perk, handler, creaturePerkLevel, PerkExecutionType.CombatAbility, perkFeat.PerkLevelUnlocked);
            }
            // Queued Weapon Skills
            else if (perk.ExecutionTypeID == PerkExecutionType.QueuedWeaponSkill)
            {
                target.SetLocalInt(LAST_ATTACK + activator.GlobalID, ATTACK_PHYSICAL);
                HandleQueueWeaponSkill(activator, perk, handler, featID);
            }
            // Stances
            else if (perk.ExecutionTypeID == PerkExecutionType.Stance)
            {
                target.SetLocalInt(LAST_ATTACK + activator.GlobalID, ATTACK_COMBATABILITY);
                ActivateAbility(activator, target, perk, handler, creaturePerkLevel, PerkExecutionType.Stance, perkFeat.PerkLevelUnlocked);
            }
            // Concentration Abilities
            else if (perk.ExecutionTypeID == PerkExecutionType.ConcentrationAbility)
            {
                target.SetLocalInt(LAST_ATTACK + activator.GlobalID, ATTACK_FORCE);
                ActivateAbility(activator, target, perk, handler, creaturePerkLevel, PerkExecutionType.ConcentrationAbility, perkFeat.PerkLevelUnlocked);
            }
        }
Example #8
0
        public static int CalculateGPReward(NWPlayer player, GuildType guild, int baseAmount)
        {
            var   pcGP      = DataService.PCGuildPoint.GetByPlayerIDAndGuildID(player.GlobalID, (int)guild);
            float rankBonus = 0.25f * pcGP.Rank;

            // Grant a bonus based on the player's guild relations perk rank.
            int perkBonus = PerkService.GetCreaturePerkLevel(player, PerkType.GuildRelations);

            baseAmount = baseAmount + (perkBonus * baseAmount);

            return(baseAmount + (int)(baseAmount * rankBonus));
        }
Example #9
0
        public static float CalculateCraftingDelay(NWPlayer oPC, int skillID)
        {
            int      atmosphere = CalculateAreaAtmosphereBonus(oPC.Area);
            PerkType perkType;
            float    adjustedSpeed = 1.0f;

            perkType = PerkType.SpeedyCrafting;

            int perkLevel = PerkService.GetCreaturePerkLevel(oPC, perkType);

            // Each perk level reduces crafting speed by 10%.
            switch (perkLevel)
            {
            case 1: adjustedSpeed = 0.9f; break;

            case 2: adjustedSpeed = 0.8f; break;

            case 3: adjustedSpeed = 0.7f; break;

            case 4: adjustedSpeed = 0.6f; break;

            case 5: adjustedSpeed = 0.5f; break;

            case 6: adjustedSpeed = 0.4f; break;

            case 7: adjustedSpeed = 0.3f; break;

            case 8: adjustedSpeed = 0.2f; break;

            case 9: adjustedSpeed = 0.1f; break;

            case 10: adjustedSpeed = 0.01f; break;
            }

            // Workshops with an atmosphere bonus decrease crafting time.
            if (atmosphere >= 45)
            {
                adjustedSpeed -= 0.2f;
            }
            else if (atmosphere >= 5)
            {
                adjustedSpeed -= 0.1f;
            }

            // Never fall below 1% of overall crafting time.
            if (adjustedSpeed <= 0.01f)
            {
                adjustedSpeed = 0.01f;
            }

            return(BaseCraftDelay * adjustedSpeed);
        }
Example #10
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 #11
0
        private static int EffectiveMaxFP(NWPlayer player, EffectiveItemStats stats)
        {
            int fp = 20;

            fp += (player.IntelligenceModifier + player.WisdomModifier + player.CharismaModifier) * 5;
            fp += PerkService.GetPCPerkLevel(player, PerkType.FP) * 5;
            fp += stats.FP;

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

            return(fp);
        }
Example #12
0
        private static int EffectiveMaxHitPoints(NWPlayer player, EffectiveItemStats stats)
        {
            int   hp = 25 + player.ConstitutionModifier * 5;
            float effectPercentBonus = CustomEffectService.CalculateEffectHPBonusPercent(player);

            hp += PerkService.GetPCPerkLevel(player, PerkType.Health) * 5;
            hp += stats.HP;
            hp  = hp + (int)(hp * effectPercentBonus);

            if (hp > 1275)
            {
                hp = 1275;
            }
            if (hp < 20)
            {
                hp = 20;
            }

            return(hp);
        }
Example #13
0
        public static void ApplyEnmity(NWCreature attacker, NWCreature target, Data.Entity.Perk perk)
        {
            switch ((EnmityAdjustmentRuleType)perk.EnmityAdjustmentRuleID)
            {
            case EnmityAdjustmentRuleType.AllTaggedTargets:
                EnmityService.AdjustEnmityOnAllTaggedCreatures(attacker, perk.Enmity);
                break;

            case EnmityAdjustmentRuleType.TargetOnly:
                if (target.IsValid)
                {
                    EnmityService.AdjustEnmity(target, attacker, perk.Enmity);
                }
                break;

            case EnmityAdjustmentRuleType.Custom:
                var handler = PerkService.GetPerkHandler(perk.ID);
                handler.OnCustomEnmityRule(attacker, perk.Enmity);
                break;
            }
        }
Example #14
0
        private static void HandleGrenadeProficiency(NWPlayer oPC, NWObject target)
        {
            NWItem weapon = _.GetSpellCastItem();

            if (weapon.BaseItemType != BaseItem.Grenade)
            {
                return;
            }

            int   perkLevel = PerkService.GetCreaturePerkLevel(oPC, PerkType.GrenadeProficiency);
            int   chance    = 10 * perkLevel;
            float duration;

            switch (perkLevel)
            {
            case 1:
            case 2:
            case 3:
            case 4:
                duration = 6;
                break;

            case 5:
            case 6:
            case 7:
            case 8:
            case 9:
                duration = 9;
                break;

            default: return;
            }


            if (RandomService.D100(1) <= chance)
            {
                _.ApplyEffectToObject(DurationType.Temporary, AbilityService.EffectKnockdown(target, duration), target, duration);
            }
        }
Example #15
0
        private static void HandleGrenadeProficiency(NWPlayer oPC, NWObject target)
        {
            NWItem weapon = _.GetSpellCastItem();

            if (weapon.BaseItemType != BASE_ITEM_GRENADE)
            {
                return;
            }

            int   perkLevel = PerkService.GetPCPerkLevel(oPC, PerkType.GrenadeProficiency);
            int   chance    = 10 * perkLevel;
            float duration;

            switch (perkLevel)
            {
            case 1:
            case 2:
            case 3:
            case 4:
                duration = 6;
                break;

            case 5:
            case 6:
            case 7:
            case 8:
            case 9:
                duration = 9;
                break;

            default: return;
            }


            if (RandomService.D100(1) <= chance)
            {
                _.ApplyEffectToObject(DURATION_TYPE_TEMPORARY, _.EffectKnockdown(), target, duration);
            }
        }
Example #16
0
        public static float CalculateCraftingDelay(NWPlayer oPC, int skillID)
        {
            int       atmosphere = CalculateAreaAtmosphereBonus(oPC.Area);
            PerkType  perkType;
            float     adjustedSpeed = 1.0f;
            SkillType skillType     = (SkillType)skillID;

            // Identify which perk to use for this skill.
            if (skillType == SkillType.Weaponsmith)
            {
                perkType = PerkType.SpeedyWeaponsmith;
            }
            else if (skillType == SkillType.Armorsmith)
            {
                perkType = PerkType.SpeedyArmorsmith;
            }
            else if (skillType == SkillType.Cooking)
            {
                perkType = PerkType.SpeedyCooking;
            }
            else if (skillType == SkillType.Engineering)
            {
                perkType = PerkType.SpeedyEngineering;
            }
            else if (skillType == SkillType.Fabrication)
            {
                perkType = PerkType.SpeedyFabrication;
            }
            else if (skillType == SkillType.Medicine)
            {
                perkType = PerkType.SpeedyMedicine;
            }
            else if (skillType == SkillType.Harvesting)
            {
                perkType = PerkType.SpeedyReassembly;
            }
            else
            {
                return(BaseCraftDelay);
            }

            int perkLevel = PerkService.GetPCPerkLevel(oPC, perkType);

            // Each perk level reduces crafting speed by 10%.
            switch (perkLevel)
            {
            case 1: adjustedSpeed = 0.9f; break;

            case 2: adjustedSpeed = 0.8f; break;

            case 3: adjustedSpeed = 0.7f; break;

            case 4: adjustedSpeed = 0.6f; break;

            case 5: adjustedSpeed = 0.5f; break;

            case 6: adjustedSpeed = 0.4f; break;

            case 7: adjustedSpeed = 0.3f; break;

            case 8: adjustedSpeed = 0.2f; break;

            case 9: adjustedSpeed = 0.1f; break;

            case 10: adjustedSpeed = 0.01f; break;
            }

            // Workshops with an atmosphere bonus decrease crafting time.
            if (atmosphere >= 45)
            {
                adjustedSpeed -= 0.2f;
            }
            else if (atmosphere >= 5)
            {
                adjustedSpeed -= 0.1f;
            }

            // Never fall below 1% of overall crafting time.
            if (adjustedSpeed <= 0.01f)
            {
                adjustedSpeed = 0.01f;
            }

            return(BaseCraftDelay * adjustedSpeed);
        }
        private static void OnModuleEnter()
        {
            NWPlayer player = _.GetEnteringObject();

            if (!player.IsPlayer)
            {
                return;
            }

            var dbPlayer = DataService.Player.GetByID(player.GlobalID);

            // VERSION 2: Background items are no longer plot because item level no longer dictates your skill XP gain.
            if (dbPlayer.VersionNumber < 2)
            {
                string[] resrefs =
                {
                    "blaster_s",
                    "rifle_s",
                    "powerglove_t",
                    "baton_s",
                    "doubleaxe_z",
                    "kukri_d",
                    "greatsword_s",
                    "scanner_r_h",
                    "harvest_r_h",
                    "man_armor"
                };

                foreach (var resref in resrefs)
                {
                    NWItem item = _.GetItemPossessedBy(player, resref);
                    if (item.IsValid)
                    {
                        item.IsPlot = false;
                    }
                }

                dbPlayer.VersionNumber = 2;
            }

            // VERSION 3: Force feats need to be removed since force powers were reworked.
            if (dbPlayer.VersionNumber < 3)
            {
                // These IDs come from the Feat.2da file.
                NWNXCreature.RemoveFeat(player, Feat.DeprecatedForceBreach);    // Force Breach
                NWNXCreature.RemoveFeat(player, Feat.DeprecatedForceLightning); // Force Lightning
                NWNXCreature.RemoveFeat(player, Feat.DeprecatedForceHeal1);     // Force Heal
                NWNXCreature.RemoveFeat(player, Feat.DeprecatedDarkHeal);       // Dark Heal
                NWNXCreature.RemoveFeat(player, Feat.DeprecatedForceSpread);    // Force Spread
                NWNXCreature.RemoveFeat(player, Feat.DeprecatedDarkSpread);     // Dark Spread
                NWNXCreature.RemoveFeat(player, Feat.DeprecatedForcePush);      // Force Push
                NWNXCreature.RemoveFeat(player, Feat.DeprecatedForceAura);      // Force Aura
                NWNXCreature.RemoveFeat(player, Feat.DeprecatedDrainLife);      // Drain Life
                NWNXCreature.RemoveFeat(player, Feat.DeprecatedChainspell);     // Chainspell

                dbPlayer.VersionNumber = 3;
            }

            // VERSION 4: Give the Uncanny Dodge 1 feat to all characters.
            if (dbPlayer.VersionNumber < 4)
            {
                NWNXCreature.AddFeatByLevel(player, Feat.UncannyDodge1, 1);
                dbPlayer.VersionNumber = 4;
            }

            // VERSION 5: We're doing another Force rework, so remove any force feats the player may have acquired.
            if (dbPlayer.VersionNumber < 5)
            {
                NWNXCreature.RemoveFeat(player, Feat.DeprecatedForceBreach);     // Force Breach
                NWNXCreature.RemoveFeat(player, Feat.DeprecatedForceLightning);  // Force Lightning
                NWNXCreature.RemoveFeat(player, Feat.DeprecatedForceHeal1);      // Force Heal I
                NWNXCreature.RemoveFeat(player, Feat.DeprecatedAbsorptionField); // Absorption Field
                NWNXCreature.RemoveFeat(player, Feat.DeprecatedForceSpread);     // Force Spread
                NWNXCreature.RemoveFeat(player, Feat.DeprecatedForcePush);       // Force Push
                NWNXCreature.RemoveFeat(player, Feat.DeprecatedForceAura);       // Force Aura
                NWNXCreature.RemoveFeat(player, Feat.DeprecatedDrainLife);       // Drain Life
                NWNXCreature.RemoveFeat(player, Feat.DeprecatedChainspell);      // Chainspell
                NWNXCreature.RemoveFeat(player, Feat.DeprecatedForceHeal2);      // Force Heal II
                NWNXCreature.RemoveFeat(player, Feat.DeprecatedForceHeal3);      // Force Heal III
                NWNXCreature.RemoveFeat(player, Feat.DeprecatedForceHeal4);      // Force Heal IV

                dbPlayer.VersionNumber = 5;
            }

            // VERSION 6: Remove AC from all items the player is carrying. If possible,
            // grant +1 durability and +1 max durability for every 2 AC the item has.
            if (dbPlayer.VersionNumber < 6)
            {
                ProcessVersion6ItemChanges(player);
                dbPlayer.VersionNumber = 6;
            }

            // VERSION 7: Give 40 language ranks to players, for their distribution.
            if (dbPlayer.VersionNumber < 7)
            {
                var ranks = new PCSkillPool
                {
                    PlayerID        = dbPlayer.ID,
                    SkillCategoryID = 8, // 8 = Languages
                    Levels          = 40
                };
                DataService.SubmitDataChange(ranks, DatabaseActionType.Insert);
                dbPlayer.VersionNumber = 7;
            }

            // VERSION 8: Remove armor restrictions for a number of perks. Ensure player has the feat if they have the perk purchased.
            if (dbPlayer.VersionNumber < 8)
            {
                // Point Blank Shot
                if (PerkService.GetPCPerkByID(player.GlobalID, (int)PerkType.PointBlankShot) != null)
                {
                    NWNXCreature.AddFeat(player, Feat.PointBlankShot);
                }

                // Rapid Reload
                if (PerkService.GetPCPerkByID(player.GlobalID, (int)PerkType.RapidReload) != null)
                {
                    NWNXCreature.AddFeat(player, Feat.RapidReload);
                }

                dbPlayer.VersionNumber = 8;
            }

            // VERSION 9: Remove Weapon Finesse if player currently has it.
            if (dbPlayer.VersionNumber < 9)
            {
                if (GetHasFeat(Feat.WeaponFinesse, player))
                {
                    NWNXCreature.RemoveFeat(player, Feat.WeaponFinesse);
                }

                dbPlayer.VersionNumber = 9;
            }

            DataService.SubmitDataChange(dbPlayer, DatabaseActionType.Update);
        }
Example #18
0
        public static void HandlePlasmaCellPerk(NWPlayer player, NWObject target)
        {
            if (!player.IsPlayer)
            {
                return;
            }
            if (!_.GetHasFeat(Feat.PlasmaCell, player))
            {
                return;                                          // Check if player has the perk
            }
            if (player.RightHand.CustomItemType != CustomItemType.BlasterPistol &&
                player.RightHand.CustomItemType != CustomItemType.BlasterRifle)
            {
                return;                                                                 // Check if player has the right weapons
            }
            if (GetLocalBool(target, "TRANQUILIZER_EFFECT_FIRST_RUN") == true)
            {
                return;                                                                  // Check if Tranquilizer is on to avoid conflict
            }
            if (GetLocalBool(player, "PLASMA_CELL_TOGGLE_OFF") == true)
            {
                return;                                                          // Check if Plasma Cell toggle is on or off
            }
            if (GetLocalBool(target, "TRANQUILIZER_EFFECT_FIRST_RUN") == true)
            {
                return;
            }

            int perkLevel = PerkService.GetCreaturePerkLevel(player, PerkType.PlasmaCell);
            int chance;

            CustomEffectType[] damageTypes;
            switch (perkLevel)
            {
            case 1:
                chance      = 10;
                damageTypes = new[] { CustomEffectType.FireCell };
                break;

            case 2:
                chance      = 10;
                damageTypes = new[] { CustomEffectType.FireCell, CustomEffectType.ElectricCell };
                break;

            case 3:
                chance      = 20;
                damageTypes = new[] { CustomEffectType.FireCell, CustomEffectType.ElectricCell };
                break;

            case 4:
                chance      = 20;
                damageTypes = new[] { CustomEffectType.FireCell, CustomEffectType.ElectricCell, CustomEffectType.SonicCell };
                break;

            case 5:
                chance      = 30;
                damageTypes = new[] { CustomEffectType.FireCell, CustomEffectType.ElectricCell, CustomEffectType.SonicCell };
                break;

            case 6:
                chance      = 30;
                damageTypes = new[] { CustomEffectType.FireCell, CustomEffectType.ElectricCell, CustomEffectType.SonicCell, CustomEffectType.AcidCell };
                break;

            case 7:
                chance      = 40;
                damageTypes = new[] { CustomEffectType.FireCell, CustomEffectType.ElectricCell, CustomEffectType.SonicCell, CustomEffectType.AcidCell };
                break;

            case 8:
                chance      = 40;
                damageTypes = new[] { CustomEffectType.FireCell, CustomEffectType.ElectricCell, CustomEffectType.SonicCell, CustomEffectType.AcidCell, CustomEffectType.IceCell };
                break;

            case 9:
                chance      = 50;
                damageTypes = new[] { CustomEffectType.FireCell, CustomEffectType.ElectricCell, CustomEffectType.SonicCell, CustomEffectType.AcidCell, CustomEffectType.IceCell };
                break;

            case 10:
                chance      = 50;
                damageTypes = new[] { CustomEffectType.FireCell, CustomEffectType.ElectricCell, CustomEffectType.SonicCell, CustomEffectType.AcidCell, CustomEffectType.IceCell, CustomEffectType.DivineCell };
                break;

            default: return;
            }

            foreach (var effect in damageTypes)
            {
                if (RandomService.D100(1) <= chance)
                {
                    CustomEffectService.ApplyCustomEffect(player, target.Object, effect, RandomService.D6(1), perkLevel, null);
                }
            }
        }
Example #19
0
        /// <summary>
        /// Runs validation checks to ensure activator can use a perk feat.
        /// Activation will fail if any of the following are true:
        ///     - Target is invalid
        ///     - Activator is a ship
        ///     - Feat is not a perk feat
        ///     - Cooldown has not passed
        /// </summary>
        /// <param name="activator">The creature activating a perk feat.</param>
        /// <param name="target">The target of the perk feat.</param>
        /// <param name="featID">The ID number of the feat being used.</param>
        /// <returns>true if able to use perk feat on target, false otherwise.</returns>
        public static bool CanUsePerkFeat(NWCreature activator, NWObject target, Feat featID)
        {
            var perkFeat = DataService.PerkFeat.GetByFeatIDOrDefault((int)featID);

            // There's no matching feat in the DB for this ability. Exit early.
            if (perkFeat == null)
            {
                return(false);
            }

            // Retrieve the perk information.
            Data.Entity.Perk perk = DataService.Perk.GetByIDOrDefault(perkFeat.PerkID);

            // No perk could be found. Exit early.
            if (perk == null)
            {
                return(false);
            }

            // Check to see if we are a spaceship.  Spaceships can't use abilities...
            if (activator.GetLocalInt("IS_SHIP") > 0 || activator.GetLocalInt("IS_GUNNER") > 0)
            {
                activator.SendMessage("You cannot use that ability while piloting a ship.");
                return(false);
            }

            // Retrieve the perk-specific handler logic.
            var handler = PerkService.GetPerkHandler(perkFeat.PerkID);

            // Get the creature's perk level.
            int creaturePerkLevel = PerkService.GetCreaturePerkLevel(activator, perk.ID);

            // If player is disabling an existing stance, remove that effect.
            if (perk.ExecutionTypeID == PerkExecutionType.Stance)
            {
                // Can't process NPC stances at the moment. Need to do some more refactoring before this is possible.
                // todo: handle NPC stances.
                if (!activator.IsPlayer)
                {
                    return(false);
                }

                PCCustomEffect stanceEffect = DataService.PCCustomEffect.GetByStancePerkOrDefault(activator.GlobalID, perk.ID);

                if (stanceEffect != null)
                {
                    if (CustomEffectService.RemoveStance(activator))
                    {
                        return(false);
                    }
                }
            }

            // Check for a valid perk level.
            if (creaturePerkLevel <= 0)
            {
                activator.SendMessage("You do not meet the prerequisites to use this ability.");
                return(false);
            }

            // Verify that this hostile action meets PVP sanctuary restriction rules.
            if (handler.IsHostile() && target.IsPlayer)
            {
                if (!PVPSanctuaryService.IsPVPAttackAllowed(activator.Object, target.Object))
                {
                    return(false);
                }
            }

            // Activator and target must be in the same area and within line of sight.
            if (activator.Area.Resref != target.Area.Resref ||
                _.LineOfSightObject(activator.Object, target.Object) == false)
            {
                activator.SendMessage("You cannot see your target.");
                return(false);
            }

            // Run this perk's specific checks on whether the activator may use this perk on the target.
            string canCast = handler.CanCastSpell(activator, target, perkFeat.PerkLevelUnlocked);

            if (!string.IsNullOrWhiteSpace(canCast))
            {
                activator.SendMessage(canCast);
                return(false);
            }

            // Calculate the FP cost to use this ability. Verify activator has sufficient FP.
            int fpCost    = handler.FPCost(activator, handler.FPCost(activator, perkFeat.BaseFPCost, perkFeat.PerkLevelUnlocked), perkFeat.PerkLevelUnlocked);
            int currentFP = GetCurrentFP(activator);

            if (currentFP < fpCost)
            {
                activator.SendMessage("You do not have enough FP. (Required: " + fpCost + ". You have: " + currentFP + ")");
                return(false);
            }

            // Verify activator isn't busy or dead.
            if (activator.IsBusy || activator.CurrentHP <= 0)
            {
                activator.SendMessage("You are too busy to activate that ability.");
                return(false);
            }

            // verify activator is commandable. https://github.com/zunath/SWLOR_NWN/issues/940#issue-467175951
            if (!activator.IsCommandable)
            {
                activator.SendMessage("You cannot take actions currently.");
                return(false);
            }

            // If we're executing a concentration ability, check and see if the activator currently has this ability
            // active. If it's active, then we immediately remove its effect and bail out.
            // Any other ability (including other concentration abilities) execute as normal.
            if (perk.ExecutionTypeID == PerkExecutionType.ConcentrationAbility)
            {
                // Retrieve the concentration effect for this creature.
                var concentrationEffect = GetActiveConcentrationEffect(activator);
                if ((int)concentrationEffect.Type == perk.ID)
                {
                    // It's active. Time to disable it.
                    EndConcentrationEffect(activator);
                    activator.SendMessage("Concentration ability '" + perk.Name + "' deactivated.");
                    SendAOEMessage(activator, activator.Name + " deactivates concentration ability '" + perk.Name + "'.");
                    return(false);
                }
            }

            // Retrieve the cooldown information and determine the unlock time.
            int?     cooldownCategoryID = handler.CooldownCategoryID(activator, perk.CooldownCategoryID, perkFeat.PerkLevelUnlocked);
            DateTime now            = DateTime.UtcNow;
            DateTime unlockDateTime = cooldownCategoryID == null ? now : GetAbilityCooldownUnlocked(activator, (int)cooldownCategoryID);

            // Check if we've passed the unlock date. Exit early if we have not.
            if (unlockDateTime > now)
            {
                string timeToWait = TimeService.GetTimeToWaitLongIntervals(now, unlockDateTime, false);
                activator.SendMessage("That ability can be used in " + timeToWait + ".");
                return(false);
            }

            // Passed all checks. Return true.
            return(true);
        }
Example #20
0
        private static void OnHitCastSpell()
        {
            NWPlayer oPC = _.OBJECT_SELF;

            if (!oPC.IsValid)
            {
                return;
            }

            NWObject oTarget = _.GetSpellTargetObject();
            NWItem   oItem   = _.GetSpellCastItem();

            // If this method was triggered by our own armor (from getting hit), return.
            if (oItem.BaseItemType == BaseItem.Armor)
            {
                return;
            }

            // Flag this attack as physical so that the damage scripts treat it properly.
            LoggingService.Trace(TraceComponent.LastAttack, "Setting attack type from " + oPC.GlobalID + " against " + _.GetName(oTarget) + " to physical (" + ATTACK_PHYSICAL.ToString() + ")");
            oTarget.SetLocalInt(LAST_ATTACK + oPC.GlobalID, ATTACK_PHYSICAL);

            HandleGrenadeProficiency(oPC, oTarget);
            HandlePlasmaCellPerk(oPC, oTarget);
            int activeWeaponSkillID = oPC.GetLocalInt("ACTIVE_WEAPON_SKILL");

            if (activeWeaponSkillID <= 0)
            {
                return;
            }
            int activeWeaponSkillFeatID = oPC.GetLocalInt("ACTIVE_WEAPON_SKILL_FEAT_ID");

            if (activeWeaponSkillFeatID < 0)
            {
                activeWeaponSkillFeatID = -1;
            }

            PCPerk entity   = DataService.PCPerk.GetByPlayerAndPerkID(oPC.GlobalID, activeWeaponSkillID);
            var    perk     = DataService.Perk.GetByID(entity.PerkID);
            var    perkFeat = DataService.PerkFeat.GetByFeatID(activeWeaponSkillFeatID);
            var    handler  = PerkService.GetPerkHandler(activeWeaponSkillID);

            string canCast = handler.CanCastSpell(oPC, oTarget, perkFeat.PerkLevelUnlocked);

            if (string.IsNullOrWhiteSpace(canCast))
            {
                handler.OnImpact(oPC, oTarget, entity.PerkLevel, perkFeat.PerkLevelUnlocked);

                if (oTarget.IsNPC)
                {
                    ApplyEnmity(oPC, oTarget.Object, perk);
                }
            }
            else
            {
                oPC.SendMessage(canCast);
            }

            oPC.DeleteLocalString("ACTIVE_WEAPON_SKILL_UUID");
            oPC.DeleteLocalInt("ACTIVE_WEAPON_SKILL");
            oPC.DeleteLocalInt("ACTIVE_WEAPON_SKILL_FEAT_ID");
        }
Example #21
0
        private static void HandleEvadeOrDeflectBlasterFire()
        {
            DamageEventData data = NWNXDamage.GetDamageEventData();

            if (data.Total <= 0)
            {
                return;
            }
            NWCreature damager = data.Damager.Object;
            NWCreature target  = NWGameObject.OBJECT_SELF;

            NWItem damagerWeapon = _.GetLastWeaponUsed(damager);
            NWItem targetWeapon  = target.RightHand;

            int perkLevel;

            // Attacker isn't using a pistol or rifle. Return.
            if (damagerWeapon.CustomItemType != CustomItemType.BlasterPistol &&
                damagerWeapon.CustomItemType != CustomItemType.BlasterRifle)
            {
                return;
            }

            int    modifier;
            string action;

            // Check target's equipped weapon, armor and perk.
            if (target.Chest.CustomItemType == CustomItemType.LightArmor &&
                (targetWeapon.CustomItemType == CustomItemType.MartialArtWeapon ||
                 !target.RightHand.IsValid && !target.LeftHand.IsValid))
            {
                // Martial Arts (weapon or unarmed) uses the Evade Blaster Fire perk which is primarily DEX based.
                perkLevel = PerkService.GetCreaturePerkLevel(target.Object, PerkType.EvadeBlasterFire);
                modifier  = target.DexterityModifier;
                action    = "evade";
            }
            else if (target.Chest.CustomItemType == CustomItemType.ForceArmor &&
                     (targetWeapon.CustomItemType == CustomItemType.Lightsaber ||
                      targetWeapon.CustomItemType == CustomItemType.Saberstaff ||
                      targetWeapon.GetLocalInt("LIGHTSABER") == TRUE))
            {
                // Lightsabers (lightsaber or saberstaff) uses the Deflect Blaster Fire perk which is primarily CHA based.
                perkLevel = PerkService.GetCreaturePerkLevel(target.Object, PerkType.DeflectBlasterFire);
                modifier  = target.CharismaModifier;
                action    = "deflect";
            }
            else
            {
                return;
            }

            // Don't have the perk. Return.
            if (perkLevel <= 0)
            {
                return;
            }

            // Check attacker's DEX against the primary stat of the perk.
            int delta = modifier - damager.DexterityModifier;

            if (delta <= 0)
            {
                return;
            }

            // Has the delay between block/evade attempts past?
            DateTime cooldown       = DateTime.UtcNow;
            string   lastAttemptVar = target.GetLocalString("EVADE_OR_DEFLECT_BLASTER_FIRE_COOLDOWN");

            if (!string.IsNullOrWhiteSpace(lastAttemptVar))
            {
                cooldown = DateTime.Parse(lastAttemptVar);
            }

            // Cooldown hasn't expired yet. Not ready to attempt a deflect.
            if (cooldown >= DateTime.UtcNow)
            {
                return;
            }

            // Ready to attempt a deflect. Adjust chance based on the delta of attacker DEX versus primary stat of defender.
            int chanceToDeflect = 5 * delta;

            if (chanceToDeflect > 80)
            {
                chanceToDeflect = 80;
            }

            int delay; // Seconds delay between deflect attempts.

            switch (perkLevel)
            {
            case 1:
                delay = 18;
                break;

            case 2:
                delay = 12;
                break;

            case 3:
                delay = 6;
                break;

            default: throw new Exception("HandleEvadeOrDeflectBlasterFire -> Perk Level " + perkLevel + " unsupported.");
            }

            cooldown = DateTime.UtcNow.AddSeconds(delay);
            target.SetLocalString("EVADE_OR_DEFLECT_BLASTER_FIRE_COOLDOWN", cooldown.ToString(CultureInfo.InvariantCulture));

            int roll = RandomService.D100(1);

            if (roll <= chanceToDeflect)
            {
                target.SendMessage(ColorTokenService.Gray("You " + action + " a blaster shot."));
                data.AdjustAllByPercent(-1);
                NWNXDamage.SetDamageEventData(data);
            }
            else
            {
                target.SendMessage(ColorTokenService.Gray("You fail to " + action + " a blaster shot. (" + roll + " vs " + chanceToDeflect + ")"));
            }
        }
Example #22
0
        private static void HandleBattlemagePerk()
        {
            DamageEventData data = NWNXDamage.GetDamageEventData();

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

            NWObject target = Object.OBJECT_SELF;

            if (!data.Damager.IsPlayer || !target.IsNPC)
            {
                return;
            }
            if (_.GetHasFeat((int)CustomFeatType.Battlemage, data.Damager.Object) == FALSE)
            {
                return;
            }

            NWPlayer player = data.Damager.Object;
            NWItem   weapon = _.GetLastWeaponUsed(player.Object);

            if (weapon.CustomItemType != CustomItemType.Baton)
            {
                return;
            }
            if (player.Chest.CustomItemType != CustomItemType.ForceArmor)
            {
                return;
            }

            int perkRank = PerkService.GetPCPerkLevel(player, PerkType.Battlemage);

            int  restoreAmount = 0;
            bool metRoll       = RandomService.Random(100) + 1 <= 50;

            switch (perkRank)
            {
            case 1 when metRoll:
                restoreAmount = 1;
                break;

            case 2:
                restoreAmount = 1;
                break;

            case 3:
                restoreAmount = 1;
                if (metRoll)
                {
                    restoreAmount++;
                }
                break;

            case 4:
                restoreAmount = 2;
                break;

            case 5:
                restoreAmount = 2;
                if (metRoll)
                {
                    restoreAmount++;
                }
                break;

            case 6:
                restoreAmount = 3;
                break;
            }

            if (restoreAmount > 0)
            {
                AbilityService.RestoreFP(player, restoreAmount);
            }
        }
Example #23
0
        private static void HandleDamageImmunity()
        {
            DamageEventData data = NWNXDamage.GetDamageEventData();

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

            NWCreature target = NWGameObject.OBJECT_SELF;
            NWItem     shield = target.LeftHand;
            var        concentrationEffect = AbilityService.GetActiveConcentrationEffect(target);
            double     reduction           = 0.0f;

            // Shield damage reduction and absorb energy are calculated here. They don't stack, so the one
            // with the highest reduction will take precedence.

            // Calculate shield damage reduction.
            if (ItemService.ShieldBaseItemTypes.Contains(shield.BaseItemType))
            {
                // Apply damage scaling based on shield presence
                int   perkLevel = PerkService.GetCreaturePerkLevel(target.Object, PerkType.ShieldProficiency);
                float perkBonus = 0.02f * perkLevel;

                // DI = 10% + 1% / 3 AC bonuses on the shield + 2% per perk bonus.
                reduction = (0.1 + 0.01 * shield.AC / 3) + perkBonus;
            }
            // Calculate Absorb Energy concentration effect reduction.
            if (concentrationEffect.Type == PerkType.AbsorbEnergy)
            {
                double perkReduction = concentrationEffect.Tier * 0.1;
                if (perkReduction > reduction)
                {
                    reduction = perkReduction;
                    // Calculate and award force XP based on total damage reduced.
                    int xp = (int)(data.Total * reduction * 3);
                    if (xp < 5)
                    {
                        xp = 5;
                    }

                    SkillService.GiveSkillXP(target.Object, SkillType.ForceControl, xp);
                    // Play a visual effect signifying the ability was activated.
                    _.ApplyEffectToObject(DURATION_TYPE_TEMPORARY, EffectVisualEffect(VFX_DUR_BLUR), target, 0.5f);
                }
            }

            // No reduction found. Bail out early.
            if (reduction <= 0.0f)
            {
                return;
            }

            target.SendMessage("Damage reduced by " + (int)(reduction * 100) + "%");
            reduction = 1.0f - reduction;

            data.Bludgeoning = (int)(data.Bludgeoning * reduction);
            data.Pierce      = (int)(data.Pierce * reduction);
            data.Slash       = (int)(data.Slash * reduction);
            data.Magical     = (int)(data.Magical * reduction);
            data.Acid        = (int)(data.Acid * reduction);
            data.Cold        = (int)(data.Cold * reduction);
            data.Divine      = (int)(data.Divine * reduction);
            data.Electrical  = (int)(data.Electrical * reduction);
            data.Fire        = (int)(data.Fire * reduction);
            data.Negative    = (int)(data.Negative * reduction);
            data.Positive    = (int)(data.Positive * reduction);
            data.Sonic       = (int)(data.Sonic * reduction);
            data.Base        = (int)(data.Base * reduction);

            NWNXDamage.SetDamageEventData(data);
        }
Example #24
0
        public static void ApplyBackgroundBonuses(NWPlayer oPC)
        {
            var    dbPlayer = DataService.Single <Player>(x => x.ID == oPC.GlobalID);
            string pcName   = oPC.Name;
            int    classID  = oPC.Class1;

            string item1Resref   = "";
            int    item1Quantity = 1;
            string item2Resref   = "";
            int    item2Quantity = 1;

            switch ((BackgroundType)classID)
            {
            case BackgroundType.Freelancer:
                dbPlayer.UnallocatedSP = dbPlayer.UnallocatedSP + 3;
                DataService.SubmitDataChange(dbPlayer, DatabaseActionType.Update);
                break;

            case BackgroundType.Smuggler:
                item1Resref = "blaster_s";
                break;

            case BackgroundType.Sharpshooter:
                item1Resref = "rifle_s";
                break;

            case BackgroundType.TerasKasi:
                item1Resref = "powerglove_t";
                break;

            case BackgroundType.SecurityOfficer:
                item1Resref = "club_s";
                break;

            case BackgroundType.Berserker:
                item1Resref = "doubleaxe_z";
                break;

            case BackgroundType.Duelist:
                item1Resref = "kukri_d";
                break;

            case BackgroundType.Soldier:
                item1Resref = "greatsword_s";
                break;

            case BackgroundType.Armorsmith:
                PerkService.DoPerkUpgrade(oPC, PerkType.ArmorBlueprints, true);
                break;

            case BackgroundType.Weaponsmith:
                PerkService.DoPerkUpgrade(oPC, PerkType.WeaponBlueprints, true);
                break;

            case BackgroundType.Chef:
                PerkService.DoPerkUpgrade(oPC, PerkType.FoodRecipes, true);
                break;

            case BackgroundType.Engineer:
                PerkService.DoPerkUpgrade(oPC, PerkType.EngineeringBlueprints, true);
                break;

            case BackgroundType.Fabricator:
                PerkService.DoPerkUpgrade(oPC, PerkType.FabricationBlueprints, true);
                break;

            case BackgroundType.Harvester:
                item1Resref = "scanner_r_h";
                item2Resref = "harvest_r_h";
                break;

            case BackgroundType.Scavenger:
                PerkService.DoPerkUpgrade(oPC, PerkType.ScavengingExpert, true);
                break;

            case BackgroundType.Medic:
                PerkService.DoPerkUpgrade(oPC, PerkType.ImmediateImprovement, true);
                break;

            case BackgroundType.Mandalorian:
                item1Resref = "man_armor";
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            if (!string.IsNullOrWhiteSpace(item1Resref))
            {
                NWItem oItem1 = (_.CreateItemOnObject(item1Resref, oPC.Object, item1Quantity));
                oItem1.IsCursed = true;
                oItem1.Name     = pcName + "'s " + oItem1.Name;
            }
            if (!string.IsNullOrWhiteSpace(item2Resref))
            {
                NWItem oItem2 = (_.CreateItemOnObject(item2Resref, oPC.Object, item2Quantity, ""));
                oItem2.IsCursed = true;
                oItem2.Name     = pcName + "'s " + oItem2.Name;
            }
        }
Example #25
0
        private static void ProcessConcentrationEffects()
        {
            // Loop through each creature. If they have a concentration ability active,
            // process it using that perk's OnConcentrationTick() method.
            for (int index = ConcentratingCreatures.Count - 1; index >= 0; index--)
            {
                var  creature      = ConcentratingCreatures.ElementAt(index);
                var  activeAbility = GetActiveConcentrationEffect(creature);
                int  perkID        = (int)activeAbility.Type;
                int  tier          = activeAbility.Tier;
                bool ended         = false;

                // If we have an invalid creature for any reason, remove it and move to the next one.
                if (!creature.IsValid || creature.CurrentHP <= 0 || activeAbility.Type == PerkType.Unknown)
                {
                    ConcentratingCreatures.RemoveAt(index);
                    continue;
                }

                // Track the current tick.
                int tick = creature.GetLocalInt("ACTIVE_CONCENTRATION_ABILITY_TICK") + 1;
                creature.SetLocalInt("ACTIVE_CONCENTRATION_ABILITY_TICK", tick);

                PerkFeat perkFeat = DataService.PerkFeat.GetByPerkIDAndLevelUnlocked(perkID, tier);

                // Are we ready to continue processing this concentration effect?
                if (tick % perkFeat.ConcentrationTickInterval != 0)
                {
                    continue;
                }

                // Get the perk handler, FP cost, and the target.
                var      handler   = PerkService.GetPerkHandler(perkID);
                int      fpCost    = handler.FPCost(creature, perkFeat.ConcentrationFPCost, tier);
                NWObject target    = creature.GetLocalObject("CONCENTRATION_TARGET");
                int      currentFP = GetCurrentFP(creature);
                int      maxFP     = GetMaxFP(creature);

                // Is the target still valid?
                if (!target.IsValid || target.CurrentHP <= 0)
                {
                    creature.SendMessage("Concentration effect has ended because your target is no longer valid.");
                    EndConcentrationEffect(creature);
                    ended = true;
                }
                // Does player have enough FP to maintain this concentration?
                else if (currentFP < fpCost)
                {
                    creature.SendMessage("Concentration effect has ended because you ran out of FP.");
                    EndConcentrationEffect(creature);
                    ended = true;
                }
                // Is the target still within range and in the same area?
                else if (creature.Area.Object != target.Area.Object ||
                         _.GetDistanceBetween(creature, target) > 50.0f)
                {
                    creature.SendMessage("Concentration effect has ended because your target has gone out of range.");
                    EndConcentrationEffect(creature);
                    ended = true;
                }
                // Otherwise deduct the required FP.
                else
                {
                    currentFP -= fpCost;
                }

                SetCurrentFP(creature, currentFP);

                // Send a FP status message if the effect ended or it's been six seconds since the last one.
                if (ended || tick % 6 == 0)
                {
                    creature.SendMessage(ColorTokenService.Custom("FP: " + currentFP + " / " + maxFP, 32, 223, 219));
                }

                // Run this individual perk's concentration tick method if it didn't end this tick.
                if (!ended && target.IsValid)
                {
                    handler.OnConcentrationTick(creature, target, tier, tick);
                }
            }
        }
Example #26
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.
        }
Example #27
0
        private static void OnModuleUseFeat()
        {
            NWPlayer   pc       = Object.OBJECT_SELF;
            NWCreature target   = NWNXEvents.OnFeatUsed_GetTarget().Object;
            int        featID   = NWNXEvents.OnFeatUsed_GetFeatID();
            var        perkFeat = DataService.SingleOrDefault <PerkFeat>(x => x.FeatID == featID);

            if (perkFeat == null)
            {
                return;
            }
            Data.Entity.Perk perk = DataService.GetAll <Data.Entity.Perk>().SingleOrDefault(x => x.ID == perkFeat.PerkID);
            if (perk == null)
            {
                return;
            }

            // Check to see if we are a spaceship.  Spaceships can't use abilities...
            if (pc.GetLocalInt("IS_SHIP") > 0 || pc.GetLocalInt("IS_GUNNER") > 0)
            {
                pc.SendMessage("You cannot use that ability while piloting a ship.");
                return;
            }

            var perkAction = PerkService.GetPerkHandler(perkFeat.PerkID);

            Player playerEntity = DataService.Get <Player>(pc.GlobalID);
            int    pcPerkLevel  = PerkService.GetPCPerkLevel(pc, perk.ID);

            // If player is disabling an existing stance, remove that effect.
            if (perk.ExecutionTypeID == (int)PerkExecutionType.Stance)
            {
                PCCustomEffect stanceEffect = DataService.SingleOrDefault <PCCustomEffect>(x => x.StancePerkID == perk.ID &&
                                                                                           x.PlayerID == pc.GlobalID);

                if (stanceEffect != null)
                {
                    if (CustomEffectService.RemoveStance(pc))
                    {
                        return;
                    }
                }
            }

            if (pcPerkLevel <= 0)
            {
                pc.SendMessage("You do not meet the prerequisites to use this ability.");
                return;
            }

            if (perkAction.IsHostile() && target.IsPlayer)
            {
                if (!PVPSanctuaryService.IsPVPAttackAllowed(pc, target.Object))
                {
                    return;
                }
            }

            if (pc.Area.Resref != target.Area.Resref ||
                _.LineOfSightObject(pc.Object, target.Object) == 0)
            {
                pc.SendMessage("You cannot see your target.");
                return;
            }

            if (!perkAction.CanCastSpell(pc, target))
            {
                pc.SendMessage(perkAction.CannotCastSpellMessage(pc, target) ?? "That ability cannot be used at this time.");
                return;
            }

            int fpCost = perkAction.FPCost(pc, perkAction.FPCost(pc, perk.BaseFPCost, featID), featID);

            if (playerEntity.CurrentFP < fpCost)
            {
                pc.SendMessage("You do not have enough FP. (Required: " + fpCost + ". You have: " + playerEntity.CurrentFP + ")");
                return;
            }

            if (pc.IsBusy || pc.CurrentHP <= 0)
            {
                pc.SendMessage("You are too busy to activate that ability.");
                return;
            }

            // Check cooldown
            int?       cooldownCategoryID = perkAction.CooldownCategoryID(pc, perk.CooldownCategoryID, featID);
            PCCooldown pcCooldown         = DataService.GetAll <PCCooldown>().SingleOrDefault(x => x.PlayerID == pc.GlobalID &&
                                                                                              x.CooldownCategoryID == cooldownCategoryID);

            if (pcCooldown == null)
            {
                pcCooldown = new PCCooldown
                {
                    CooldownCategoryID = Convert.ToInt32(cooldownCategoryID),
                    DateUnlocked       = DateTime.UtcNow.AddSeconds(-1),
                    PlayerID           = pc.GlobalID
                };

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

            DateTime unlockDateTime = pcCooldown.DateUnlocked;
            DateTime now            = DateTime.UtcNow;

            if (unlockDateTime > now)
            {
                string timeToWait = TimeService.GetTimeToWaitLongIntervals(now, unlockDateTime, false);
                pc.SendMessage("That ability can be used in " + timeToWait + ".");
                return;
            }

            // Force Abilities (aka Spells)
            if (perk.ExecutionTypeID == (int)PerkExecutionType.ForceAbility)
            {
                target.SetLocalInt(LAST_ATTACK + pc.GlobalID, ATTACK_FORCE);
                ActivateAbility(pc, target, perk, perkAction, pcPerkLevel, PerkExecutionType.ForceAbility, featID);
            }
            // Combat Abilities
            else if (perk.ExecutionTypeID == (int)PerkExecutionType.CombatAbility)
            {
                target.SetLocalInt(LAST_ATTACK + pc.GlobalID, ATTACK_PHYSICAL);
                ActivateAbility(pc, target, perk, perkAction, pcPerkLevel, PerkExecutionType.CombatAbility, featID);
            }
            // Queued Weapon Skills
            else if (perk.ExecutionTypeID == (int)PerkExecutionType.QueuedWeaponSkill)
            {
                target.SetLocalInt(LAST_ATTACK + pc.GlobalID, ATTACK_PHYSICAL);
                HandleQueueWeaponSkill(pc, perk, perkAction, featID);
            }
            // Stances
            else if (perk.ExecutionTypeID == (int)PerkExecutionType.Stance)
            {
                target.SetLocalInt(LAST_ATTACK + pc.GlobalID, ATTACK_COMBATABILITY);
                ActivateAbility(pc, target, perk, perkAction, pcPerkLevel, PerkExecutionType.Stance, featID);
            }
        }