Пример #1
0
        public bool CanPerkBeUpgraded(Data.Entities.Perk perk, PCPerk pcPerk, PlayerCharacter player)
        {
            int rank    = pcPerk?.PerkLevel ?? 0;
            int maxRank = perk.PerkLevels.Count;

            if (rank + 1 > maxRank)
            {
                return(false);
            }

            PerkLevel level = FindPerkLevel(perk.PerkLevels, rank + 1);

            if (level == null)
            {
                return(false);
            }

            if (player.UnallocatedSP < level.Price)
            {
                return(false);
            }

            foreach (PerkLevelSkillRequirement req in level.PerkLevelSkillRequirements)
            {
                PCSkill pcSkill = _db.PCSkills.Single(x => x.PlayerID == player.PlayerID && x.SkillID == req.SkillID);
                if (pcSkill.Rank < req.RequiredRank)
                {
                    return(false);
                }
            }

            return(true);
        }
Пример #2
0
        public void OnHitCastSpell(NWPlayer oPC)
        {
            NWObject oTarget             = NWObject.Wrap(_.GetSpellTargetObject());
            int      activeWeaponSkillID = oPC.GetLocalInt("ACTIVE_WEAPON_SKILL");

            if (activeWeaponSkillID <= 0)
            {
                return;
            }

            Data.Entities.Perk entity = _db.Perks.Single(x => x.PerkID == activeWeaponSkillID);

            IPerk perk = App.ResolveByInterface <IPerk>("Perk." + entity.JavaScriptName);

            if (perk.CanCastSpell(oPC, oTarget))
            {
                perk.OnImpact(oPC, oTarget);

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

            oPC.DeleteLocalString("ACTIVE_WEAPON_SKILL_UUID");
            oPC.DeleteLocalInt("ACTIVE_WEAPON_SKILL");
        }
Пример #3
0
        public string OnModuleExamine(string existingDescription, NWPlayer examiner, NWObject examinedObject)
        {
            if (!examiner.IsPlayer && !examiner.IsDM)
            {
                return(existingDescription);
            }
            if (examinedObject.ObjectType != OBJECT_TYPE_ITEM)
            {
                return(existingDescription);
            }
            int perkID = examinedObject.GetLocalInt("ACTIVATION_PERK_ID");

            if (perkID <= 0)
            {
                return(existingDescription);
            }

            Data.Entities.Perk perk        = _db.Perks.Single(x => x.PerkID == perkID);
            string             description = existingDescription;

            description += _color.Orange("Name: ") + perk.Name + "\n" +
                           _color.Orange("Description: ") + perk.Description + "\n";

            switch ((PerkExecutionType)perk.PerkExecutionType.PerkExecutionTypeID)
            {
            case PerkExecutionType.CombatAbility:
                description += _color.Orange("Type: ") + "Combat Ability\n";
                break;

            case PerkExecutionType.Spell:
                description += _color.Orange("Type: ") + "Spell\n";
                break;

            case PerkExecutionType.ShieldOnHit:
                description += _color.Orange("Type: ") + "Reactive\n";
                break;

            case PerkExecutionType.QueuedWeaponSkill:
                description += _color.Orange("Type: ") + "Queued Attack\n";
                break;
            }

            if (perk.BaseManaCost > 0)
            {
                description += _color.Orange("Base Mana Cost: ") + perk.BaseManaCost + "\n";
            }
            if (perk.CooldownCategory.BaseCooldownTime > 0.0f)
            {
                description += _color.Orange("Cooldown: ") + perk.CooldownCategory.BaseCooldownTime + "s\n";
            }
            if (perk.BaseCastingTime > 0.0f)
            {
                description += _color.Orange("Base Casting Time: ") + perk.BaseCastingTime + "s\n";
            }


            return(description);
        }
Пример #4
0
        public void OnHitCastSpell(NWPlayer oPC)
        {
            NWObject oTarget             = NWObject.Wrap(_.GetSpellTargetObject());
            int      activeWeaponSkillID = oPC.GetLocalInt("ACTIVE_WEAPON_SKILL");

            if (activeWeaponSkillID <= 0)
            {
                return;
            }

            Data.Entities.Perk entity = _db.Perks.Single(x => x.PerkID == activeWeaponSkillID);

            IPerk perk = App.ResolveByInterface <IPerk>("Perk." + entity.JavaScriptName);

            perk?.OnImpact(oPC, oTarget);

            oPC.DeleteLocalString("ACTIVE_WEAPON_SKILL_UUID");
            oPC.DeleteLocalInt("ACTIVE_WEAPON_SKILL");
        }
Пример #5
0
        private void HandleQueueWeaponSkill(NWPlayer pc, Data.Entities.Perk entity, IPerk ability)
        {
            string queueUUID = Guid.NewGuid().ToString();

            pc.SetLocalInt("ACTIVE_WEAPON_SKILL", entity.PerkID);
            pc.SetLocalString("ACTIVE_WEAPON_SKILL_UUID", queueUUID);
            pc.SendMessage("Weapon skill '" + entity.Name + "' queued for next attack.");

            ApplyCooldown(pc, entity.CooldownCategory, ability);

            // Player must attack within 30 seconds after queueing or else it wears off.
            pc.DelayCommand(() =>
            {
                if (pc.GetLocalString("ACTIVE_WEAPON_SKILL_UUID") == queueUUID)
                {
                    pc.DeleteLocalInt("ACTIVE_WEAPON_SKILL");
                    pc.DeleteLocalString("ACTIVE_WEAPON_SKILL_UUID");
                    pc.SendMessage("Your weapon skill '" + entity.Name + "' is no longer queued.");
                }
            }, 30.0f);
        }
Пример #6
0
        private void ApplyEnmity(NWPlayer pc, NWCreature target, Data.Entities.Perk perk)
        {
            switch ((EnmityAdjustmentRuleType)perk.EnmityAdjustmentRuleID)
            {
            case EnmityAdjustmentRuleType.AllTaggedTargets:
                _enmity.AdjustEnmityOnAllTaggedCreatures(pc, perk.Enmity);
                break;

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

            case EnmityAdjustmentRuleType.Custom:
                IPerk perkAction = App.ResolveByInterface <IPerk>("Perk." + perk.JavaScriptName);
                perkAction?.OnCustomEnmityRule(pc, perk.Enmity);
                break;
            }
        }
Пример #7
0
        private void BuildPerkDetails()
        {
            Model vm = GetDialogCustomData <Model>();

            Data.Entities.Perk perk   = _perk.GetPerkByID(vm.SelectedPerkID);
            PCPerk             pcPerk = _perk.GetPCPerkByID(GetPC().GlobalID, perk.PerkID);
            PlayerCharacter    player = _player.GetPlayerEntity(GetPC().GlobalID);

            int       rank             = pcPerk?.PerkLevel ?? 0;
            int       maxRank          = perk.PerkLevels.Count;
            string    currentBonus     = "N/A";
            string    nextBonus        = "N/A";
            string    price            = "N/A";
            PerkLevel currentPerkLevel = _perk.FindPerkLevel(perk.PerkLevels, rank);
            PerkLevel nextPerkLevel    = _perk.FindPerkLevel(perk.PerkLevels, rank + 1);

            SetResponseVisible("PerkDetailsPage", 1, _perk.CanPerkBeUpgraded(perk, pcPerk, player));

            if (rank > 0)
            {
                if (currentPerkLevel != null)
                {
                    currentBonus = currentPerkLevel.Description;
                }
            }
            if (rank + 1 <= maxRank)
            {
                if (nextPerkLevel != null)
                {
                    nextBonus = nextPerkLevel.Description;
                    price     = nextPerkLevel.Price + " SP (Available: " + player.UnallocatedSP + " SP)";
                }
            }

            string header = _color.Green("Name: ") + perk.Name + "\n" +
                            _color.Green("Category: ") + perk.PerkCategory.Name + "\n" +
                            _color.Green("Rank: ") + rank + " / " + maxRank + "\n" +
                            _color.Green("Price: ") + price + "\n" +
                            (perk.BaseManaCost > 0 ? _color.Green("Mana: ") + perk.BaseManaCost : "") + "\n" +
                            (perk.CooldownCategory != null && perk.CooldownCategory.BaseCooldownTime > 0 ? _color.Green("Cooldown: ") + perk.CooldownCategory.BaseCooldownTime + "s" : "") + "\n" +
                            _color.Green("Description: ") + perk.Description + "\n" +
                            _color.Green("Current Bonus: ") + currentBonus + "\n" +
                            _color.Green("Next Bonus: ") + nextBonus + "\n";

            if (nextPerkLevel != null)
            {
                List <PerkLevelSkillRequirement> requirements = nextPerkLevel.PerkLevelSkillRequirements.ToList();
                if (requirements.Count > 0)
                {
                    header += "\n" + _color.Green("Next Upgrade Skill Requirements:\n\n");

                    bool hasRequirement = false;
                    foreach (PerkLevelSkillRequirement req in requirements)
                    {
                        if (req.RequiredRank > 0)
                        {
                            string detailLine = req.Skill.Name + " Rank " + req.RequiredRank;

                            PCSkill skill = _skill.GetPCSkillByID(GetPC().GlobalID, req.SkillID);
                            if (skill.Rank >= req.RequiredRank)
                            {
                                header += _color.Green(detailLine) + "\n";
                            }
                            else
                            {
                                header += _color.Red(detailLine) + "\n";
                            }

                            hasRequirement = true;
                        }
                    }

                    if (requirements.Count <= 0 || !hasRequirement)
                    {
                        header += "None\n";
                    }
                }
            }

            SetPageHeader("PerkDetailsPage", header);
        }
Пример #8
0
        public void OnModuleItemActivated()
        {
            NWPlayer pc     = NWPlayer.Wrap(_.GetItemActivator());
            NWItem   item   = NWItem.Wrap(_.GetItemActivated());
            NWPlayer target = NWPlayer.Wrap(_.GetItemActivatedTarget());
            int      perkID = item.GetLocalInt("ACTIVATION_PERK_ID");

            if (perkID <= 0)
            {
                return;
            }

            Data.Entities.Perk perk = _db.Perks.SingleOrDefault(x => x.PerkID == perkID);

            if (perk == null)
            {
                return;
            }

            IPerk perkAction = App.ResolveByInterface <IPerk>("Perk." + perk.JavaScriptName);

            if (perkAction == null)
            {
                return;
            }

            PlayerCharacter playerEntity = _db.PlayerCharacters.Single(x => x.PlayerID == pc.GlobalID);

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

            if (perkAction.IsHostile() && target.IsPlayer)
            {
                if (!_pvpSanctuary.IsPVPAttackAllowed(pc, target))
                {
                    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() ?? "That ability cannot be used at this time.");
                return;
            }

            int manaCost = perkAction.ManaCost(pc, perkAction.ManaCost(pc, perk.BaseManaCost));

            if (playerEntity.CurrentMana < manaCost)
            {
                pc.SendMessage("You do not have enough mana. (Required: " + manaCost + ". You have: " + playerEntity.CurrentMana + ")");
                return;
            }

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

            // Check cooldown
            PCCooldown pcCooldown = _db.PCCooldowns.SingleOrDefault(x => x.PlayerID == pc.GlobalID && x.CooldownCategoryID == perk.CooldownCategoryID);

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

                _db.PCCooldowns.Add(pcCooldown);
                _db.SaveChanges();
            }

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

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

            // Spells w/ casting time
            if (perk.PerkExecutionType.PerkExecutionTypeID == (int)PerkExecutionType.Spell)
            {
                CastSpell(pc, target, perk, perkAction, perk.CooldownCategory);
            }
            // Combat Abilities w/o casting time
            else if (perk.PerkExecutionType.PerkExecutionTypeID == (int)PerkExecutionType.CombatAbility)
            {
                perkAction.OnImpact(pc, target);

                if (manaCost > 0)
                {
                    playerEntity.CurrentMana = playerEntity.CurrentMana - manaCost;
                    _db.SaveChanges();
                }
                ApplyCooldown(pc, perk.CooldownCategory, perkAction);
            }
            // Queued Weapon Skills
            else if (perk.PerkExecutionType.PerkExecutionTypeID == (int)PerkExecutionType.QueuedWeaponSkill)
            {
                HandleQueueWeaponSkill(pc, perk, perkAction);
            }
        }
Пример #9
0
        private void CastSpell(NWPlayer pc,
                               NWObject target,
                               Data.Entities.Perk entity,
                               IPerk perk,
                               CooldownCategory cooldown)
        {
            string spellUUID       = Guid.NewGuid().ToString();
            int    itemBonus       = pc.CastingSpeed;
            float  baseCastingTime = perk.CastingTime(pc, (float)entity.BaseCastingTime);
            float  castingTime     = baseCastingTime;

            // Casting Bonus % - Shorten casting time.
            if (itemBonus < 0)
            {
                float castingPercentageBonus = Math.Abs(itemBonus) * 0.01f;
                castingTime = castingTime - (castingTime * castingPercentageBonus);
            }
            // Casting Penalty % - Increase casting time.
            else if (itemBonus > 0)
            {
                float castingPercentageBonus = Math.Abs(itemBonus) * 0.01f;
                castingTime = castingTime + (castingTime * castingPercentageBonus);
            }

            if (castingTime < 0.5f)
            {
                castingTime = 0.5f;
            }

            // Heavy armor increases casting time by 2x the base casting time
            if (pc.Chest.CustomItemType == CustomItemType.HeavyArmor)
            {
                castingTime = baseCastingTime * 2;
            }

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

            _.ClearAllActions();
            _biowarePosition.TurnToFaceObject(target, pc);
            _.ApplyEffectToObject(DURATION_TYPE_TEMPORARY,
                                  _.EffectVisualEffect(VFX_DUR_ELEMENTAL_SHIELD),
                                  pc.Object,
                                  castingTime + 0.2f);

            float animationTime = castingTime;

            pc.AssignCommand(() => _.ActionPlayAnimation(ANIMATION_LOOPING_CONJURE1, 1.0f, animationTime - 0.1f));

            pc.IsBusy = true;
            CheckForSpellInterruption(pc, spellUUID, pc.Position);
            pc.SetLocalInt(spellUUID, SPELL_STATUS_STARTED);

            _nwnxPlayer.StartGuiTimingBar(pc, (int)castingTime, "");

            pc.DelayCommand(() =>
            {
                if (pc.GetLocalInt(spellUUID) == SPELL_STATUS_INTERRUPTED || // Moved during casting
                    pc.CurrentHP < 0 || pc.IsDead)                           // Or is dead/dying
                {
                    pc.DeleteLocalInt(spellUUID);
                    pc.SendMessage("Your spell has been interrupted.");
                    return;
                }

                pc.DeleteLocalInt(spellUUID);

                if ((PerkExecutionType)entity.ExecutionTypeID == PerkExecutionType.Spell ||
                    (PerkExecutionType)entity.ExecutionTypeID == PerkExecutionType.CombatAbility)
                {
                    perk.OnImpact(pc, target);
                }
                else
                {
                    HandleQueueWeaponSkill(pc, entity, perk);
                }


                // Adjust mana only if spell cost > 0
                PlayerCharacter pcEntity = _db.PlayerCharacters.Single(x => x.PlayerID == pc.GlobalID);
                if (perk.ManaCost(pc, entity.BaseManaCost) > 0)
                {
                    pcEntity.CurrentMana = pcEntity.CurrentMana - perk.ManaCost(pc, entity.BaseManaCost);
                    _db.SaveChanges();
                    pc.SendMessage(_color.Custom("Mana: " + pcEntity.CurrentMana + " / " + pcEntity.MaxMana, 32, 223, 219));
                }

                if (_random.Random(100) + 1 <= 3)
                {
                    _food.DecreaseHungerLevel(pc, 1);
                }
                // Mark cooldown on category
                ApplyCooldown(pc, cooldown, perk);
                pc.IsBusy = false;
            }, castingTime + 0.5f);
        }
Пример #10
0
        public void DoPerkUpgrade(NWPlayer oPC, int perkID)
        {
            Data.Entities.Perk perk   = _db.Perks.Single(x => x.PerkID == perkID);
            PCPerk             pcPerk = _db.PCPerks.SingleOrDefault(x => x.PlayerID == oPC.GlobalID && x.PerkID == perkID);
            PlayerCharacter    player = _db.PlayerCharacters.Single(x => x.PlayerID == oPC.GlobalID);

            if (CanPerkBeUpgraded(perk, pcPerk, player))
            {
                if (pcPerk == null)
                {
                    pcPerk = new PCPerk();
                    DateTime dt = DateTime.UtcNow;
                    pcPerk.AcquiredDate = dt;
                    pcPerk.PerkID       = perk.PerkID;
                    pcPerk.PlayerID     = oPC.GlobalID;
                    pcPerk.PerkLevel    = 0;

                    _db.PCPerks.Add(pcPerk);
                }

                PerkLevel nextPerkLevel = FindPerkLevel(perk.PerkLevels, pcPerk.PerkLevel + 1);
                if (nextPerkLevel == null)
                {
                    return;
                }

                pcPerk.PerkLevel++;
                player.UnallocatedSP -= nextPerkLevel.Price;

                _db.SaveChanges();

                // If a perk is activatable, create the item on the PC.
                // Remove any existing cast spell unique power properties and add the correct one based on the DB flag.
                if (!string.IsNullOrWhiteSpace(perk.ItemResref))
                {
                    if (_.GetIsObjectValid(_.GetItemPossessedBy(oPC.Object, perk.ItemResref)) == FALSE)
                    {
                        NWItem spellItem = NWItem.Wrap(_.CreateItemOnObject(perk.ItemResref, oPC.Object));
                        spellItem.IsCursed = true;
                        spellItem.SetLocalInt("ACTIVATION_PERK_ID", perk.PerkID);

                        foreach (ItemProperty ipCur in spellItem.ItemProperties)
                        {
                            int ipType    = _.GetItemPropertyType(ipCur);
                            int ipSubType = _.GetItemPropertySubType(ipCur);
                            if (ipType == ITEM_PROPERTY_CAST_SPELL &&
                                (ipSubType == IP_CONST_CASTSPELL_UNIQUE_POWER ||
                                 ipSubType == IP_CONST_CASTSPELL_UNIQUE_POWER_SELF_ONLY ||
                                 ipSubType == IP_CONST_CASTSPELL_ACTIVATE_ITEM))
                            {
                                _.RemoveItemProperty(spellItem.Object, ipCur);
                            }
                        }

                        ItemProperty ip;
                        if (perk.IsTargetSelfOnly)
                        {
                            ip = _.ItemPropertyCastSpell(IP_CONST_CASTSPELL_UNIQUE_POWER_SELF_ONLY, IP_CONST_CASTSPELL_NUMUSES_UNLIMITED_USE);
                        }
                        else
                        {
                            ip = _.ItemPropertyCastSpell(IP_CONST_CASTSPELL_UNIQUE_POWER, IP_CONST_CASTSPELL_NUMUSES_UNLIMITED_USE);
                        }

                        _biowareXP2.IPSafeAddItemProperty(spellItem, ip, 0.0f, AddItemPropertyPolicy.ReplaceExisting, false, false);
                    }

                    _.SetName(_.GetItemPossessedBy(oPC.Object, perk.ItemResref), perk.Name + " (Lvl. " + pcPerk.PerkLevel + ")");
                }

                oPC.SendMessage(_color.Green("Perk Purchased: " + perk.Name + " (Lvl. " + pcPerk.PerkLevel + ")"));

                IPerk perkScript = App.ResolveByInterface <IPerk>("Perk." + perk.JavaScriptName);

                if (perkScript == null)
                {
                    return;
                }
                perkScript.OnPurchased(oPC, pcPerk.PerkLevel);
            }
            else
            {
                oPC.FloatingText(_color.Red("You cannot purchase the perk at this time."));
            }
        }