Пример #1
0
        private static void HandleQueueWeaponSkill(NWCreature activator, Data.Entity.Perk entity, IPerkHandler ability, Feat spellFeatID)
        {
            var    perkFeat           = DataService.PerkFeat.GetByFeatID((int)spellFeatID);
            int?   cooldownCategoryID = ability.CooldownCategoryID(activator, entity.CooldownCategoryID, perkFeat.PerkLevelUnlocked);
            var    cooldownCategory   = DataService.CooldownCategory.GetByID(Convert.ToInt32(cooldownCategoryID));
            string queueUUID          = Guid.NewGuid().ToString();

            activator.SetLocalInt("ACTIVE_WEAPON_SKILL", entity.ID);
            activator.SetLocalString("ACTIVE_WEAPON_SKILL_UUID", queueUUID);
            activator.SetLocalInt("ACTIVE_WEAPON_SKILL_FEAT_ID", (int)spellFeatID);
            activator.SendMessage("Weapon skill '" + entity.Name + "' queued for next attack.");
            SendAOEMessage(activator, activator.Name + " readies weapon skill '" + entity.Name + "'.");

            ApplyCooldown(activator, cooldownCategory, ability, perkFeat.PerkLevelUnlocked, 0.0f);

            // Player must attack within 30 seconds after queueing or else it wears off.
            _.DelayCommand(30f, () =>
            {
                if (activator.GetLocalString("ACTIVE_WEAPON_SKILL_UUID") == queueUUID)
                {
                    activator.DeleteLocalInt("ACTIVE_WEAPON_SKILL");
                    activator.DeleteLocalString("ACTIVE_WEAPON_SKILL_UUID");
                    activator.DeleteLocalInt("ACTIVE_WEAPON_SKILL_FEAT_ID");
                    activator.SendMessage("Your weapon skill '" + entity.Name + "' is no longer queued.");
                    SendAOEMessage(activator, activator.Name + " no longer has weapon skill '" + entity.Name + "' readied.");
                }
            });
        }
Пример #2
0
        public static void ApplyCooldown(NWCreature creature, CooldownCategory cooldown, IPerkHandler handler, int spellTier, float armorPenalty)
        {
            if (armorPenalty <= 0.0f)
            {
                armorPenalty = 1.0f;
            }

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

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

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

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

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

            if (creature.IsPlayer)
            {
                PCCooldown pcCooldown = DataService.Single <PCCooldown>(x => x.PlayerID == creature.GlobalID && x.CooldownCategoryID == cooldown.ID);
                pcCooldown.DateUnlocked = unlockDate;
                DataService.SubmitDataChange(pcCooldown, DatabaseActionType.Update);
            }
            else
            {
                string unlockDateString = unlockDate.ToString("yyyy-MM-dd hh:mm:ss");
                creature.SetLocalString("ABILITY_COOLDOWN_ID_" + (int)handler.PerkType, unlockDateString);
            }
        }
Пример #3
0
        public static void AddTemporaryForceDefense(NWCreature target, ForceAbilityType forceAbility, int amount = 5, int length = 5)
        {
            if (amount <= 0)
            {
                amount = 1;
            }
            string   variable        = "TEMP_FORCE_DEFENSE_" + (int)forceAbility;
            int      tempDefense     = target.GetLocalInt(variable) + amount;
            string   tempDateExpires = target.GetLocalString(variable);
            DateTime expirationDate  = DateTime.UtcNow;

            if (!string.IsNullOrWhiteSpace(tempDateExpires))
            {
                expirationDate = DateTime.Parse(tempDateExpires);
            }

            expirationDate = expirationDate.AddSeconds(length);
            target.SetLocalString(variable, expirationDate.ToString(CultureInfo.InvariantCulture));
            target.SetLocalInt(variable, tempDefense);
        }
Пример #4
0
        private void HandleEvadeOrDeflectBlasterFire()
        {
            DamageData data = _nwnxDamage.GetDamageEventData();

            if (data.Total <= 0)
            {
                return;
            }
            NWCreature damager = data.Damager.Object;
            NWCreature target  = Object.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 = _perk.GetPCPerkLevel(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 = _perk.GetPCPerkLevel(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 = _random.D100(1);

            if (roll <= chanceToDeflect)
            {
                target.SendMessage(_color.Gray("You " + action + " a blaster shot."));
                data.AdjustAllByPercent(-1);
                _nwnxDamage.SetDamageEventData(data);
            }
            else
            {
                target.SendMessage(_color.Gray("You fail to " + action + " a blaster shot. (" + roll + " vs " + chanceToDeflect + ")"));
            }
        }
Пример #5
0
 /// <summary>
 /// Sets the current script names as local variables on the creature and then disables all events.
 /// </summary>
 /// <param name="creature">The creatures whose events we're disabling.</param>
 private static void DisableCreatureEvents(NWCreature creature)
 {
     creature.SetLocalString("SPAWN_CREATURE_EVENT_ON_HEARTBEAT", GetEventScript(creature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT));
     creature.SetLocalString("SPAWN_CREATURE_EVENT_ON_NOTICE", GetEventScript(creature, EVENT_SCRIPT_CREATURE_ON_NOTICE));
     creature.SetLocalString("SPAWN_CREATURE_EVENT_ON_SPELLCASTAT", GetEventScript(creature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT));
     creature.SetLocalString("SPAWN_CREATURE_EVENT_ON_MELEE_ATTACKED", GetEventScript(creature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED));
     creature.SetLocalString("SPAWN_CREATURE_EVENT_ON_DAMAGED", GetEventScript(creature, EVENT_SCRIPT_CREATURE_ON_DAMAGED));
     creature.SetLocalString("SPAWN_CREATURE_EVENT_ON_DISTURBED", GetEventScript(creature, EVENT_SCRIPT_CREATURE_ON_DISTURBED));
     creature.SetLocalString("SPAWN_CREATURE_EVENT_ON_END_COMBATROUND", GetEventScript(creature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND));
     creature.SetLocalString("SPAWN_CREATURE_EVENT_ON_DIALOGUE", GetEventScript(creature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE));
     creature.SetLocalString("SPAWN_CREATURE_EVENT_ON_RESTED", GetEventScript(creature, EVENT_SCRIPT_CREATURE_ON_RESTED));
     creature.SetLocalString("SPAWN_CREATURE_EVENT_ON_DEATH", GetEventScript(creature, EVENT_SCRIPT_CREATURE_ON_DEATH));
     creature.SetLocalString("SPAWN_CREATURE_EVENT_ON_USER_DEFINED_EVENT", GetEventScript(creature, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT));
     creature.SetLocalString("SPAWN_CREATURE_EVENT_ON_BLOCKED_BY_DOOR", GetEventScript(creature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR));
     SetEventScript(creature, EVENT_SCRIPT_CREATURE_ON_HEARTBEAT, string.Empty);
     SetEventScript(creature, EVENT_SCRIPT_CREATURE_ON_NOTICE, string.Empty);
     SetEventScript(creature, EVENT_SCRIPT_CREATURE_ON_SPELLCASTAT, string.Empty);
     SetEventScript(creature, EVENT_SCRIPT_CREATURE_ON_MELEE_ATTACKED, string.Empty);
     SetEventScript(creature, EVENT_SCRIPT_CREATURE_ON_DAMAGED, string.Empty);
     SetEventScript(creature, EVENT_SCRIPT_CREATURE_ON_DISTURBED, string.Empty);
     SetEventScript(creature, EVENT_SCRIPT_CREATURE_ON_END_COMBATROUND, string.Empty);
     SetEventScript(creature, EVENT_SCRIPT_CREATURE_ON_DIALOGUE, string.Empty);
     SetEventScript(creature, EVENT_SCRIPT_CREATURE_ON_RESTED, string.Empty);
     SetEventScript(creature, EVENT_SCRIPT_CREATURE_ON_DEATH, string.Empty);
     SetEventScript(creature, EVENT_SCRIPT_CREATURE_ON_USER_DEFINED_EVENT, string.Empty);
     SetEventScript(creature, EVENT_SCRIPT_CREATURE_ON_BLOCKED_BY_DOOR, string.Empty);
 }
Пример #6
0
 /// <summary>
 /// Sets the current script names as local variables on the creature and then disables all events.
 /// </summary>
 /// <param name="creature">The creatures whose events we're disabling.</param>
 private static void DisableCreatureEvents(NWCreature creature)
 {
     creature.SetLocalString("SPAWN_CREATURE_EVENT_ON_HEARTBEAT", GetEventScript(creature, EventScript.Creature_OnHeartbeat));
     creature.SetLocalString("SPAWN_CREATURE_EVENT_ON_NOTICE", GetEventScript(creature, EventScript.Creature_OnNotice));
     creature.SetLocalString("SPAWN_CREATURE_EVENT_ON_SPELLCASTAT", GetEventScript(creature, EventScript.Creature_OnSpellCastAt));
     creature.SetLocalString("SPAWN_CREATURE_EVENT_ON_MELEE_ATTACKED", GetEventScript(creature, EventScript.Creature_OnMeleeAttacked));
     creature.SetLocalString("SPAWN_CREATURE_EVENT_ON_DAMAGED", GetEventScript(creature, EventScript.Creature_OnDamaged));
     creature.SetLocalString("SPAWN_CREATURE_EVENT_ON_DISTURBED", GetEventScript(creature, EventScript.Creature_OnDisturbed));
     creature.SetLocalString("SPAWN_CREATURE_EVENT_ON_END_COMBATROUND", GetEventScript(creature, EventScript.Creature_OnEndCombatRound));
     creature.SetLocalString("SPAWN_CREATURE_EVENT_ON_DIALOGUE", GetEventScript(creature, EventScript.Creature_OnDialogue));
     creature.SetLocalString("SPAWN_CREATURE_EVENT_ON_RESTED", GetEventScript(creature, EventScript.Creature_OnRested));
     creature.SetLocalString("SPAWN_CREATURE_EVENT_ON_DEATH", GetEventScript(creature, EventScript.Creature_OnDeath));
     creature.SetLocalString("SPAWN_CREATURE_EVENT_ON_USER_DEFINED_EVENT", GetEventScript(creature, EventScript.Creature_OnUserDefined));
     creature.SetLocalString("SPAWN_CREATURE_EVENT_ON_BLOCKED_BY_DOOR", GetEventScript(creature, EventScript.Creature_OnBlockedByDoor));
     SetEventScript(creature, EventScript.Creature_OnHeartbeat, string.Empty);
     SetEventScript(creature, EventScript.Creature_OnNotice, string.Empty);
     SetEventScript(creature, EventScript.Creature_OnSpellCastAt, string.Empty);
     SetEventScript(creature, EventScript.Creature_OnMeleeAttacked, string.Empty);
     SetEventScript(creature, EventScript.Creature_OnDamaged, string.Empty);
     SetEventScript(creature, EventScript.Creature_OnDisturbed, string.Empty);
     SetEventScript(creature, EventScript.Creature_OnEndCombatRound, string.Empty);
     SetEventScript(creature, EventScript.Creature_OnDialogue, string.Empty);
     SetEventScript(creature, EventScript.Creature_OnRested, string.Empty);
     SetEventScript(creature, EventScript.Creature_OnDeath, string.Empty);
     SetEventScript(creature, EventScript.Creature_OnUserDefined, string.Empty);
     SetEventScript(creature, EventScript.Creature_OnBlockedByDoor, string.Empty);
 }
Пример #7
0
        private bool UseFeat(int featID, string featName, NWCreature caster, NWCreature target)
        {
            // Note - this code is loosely based on code from AbilityService.  However, the perk interface
            // is written assuming players will always be using perks.  To allow NPCs to use them requires some hackery.
            int perkLevel = (int)caster.ChallengeRating / 5;

            if (perkLevel < 1)
            {
                perkLevel = 1;
            }

            if (caster.Area.Resref != target.Area.Resref ||
                _.LineOfSightObject(caster.Object, target.Object) == 0)
            {
                return(false);
            }

            // Give NPCs a bit longer range than most PCs.
            if (_.GetDistanceBetween(caster, target) > 20.0f)
            {
                return(false);
            }

            // Note - NPCs are assumed to have infinite FPs.
            if (_.GetIsDead(caster) == 1)
            {
                return(false);
            }

            // Cooldown of 1 round.
            string   timeout    = caster.GetLocalString("TIMEOUT_" + featName);
            DateTime unlockTime = DateTime.UtcNow;

            if (!string.IsNullOrWhiteSpace(timeout))
            {
                unlockTime = DateTime.Parse(timeout);
            }
            DateTime now = DateTime.UtcNow;

            if (unlockTime > now)
            {
                return(false);
            }
            else
            {
                unlockTime = now.AddSeconds(6);
                caster.SetLocalString("TIMEOUT_" + featName, unlockTime.ToString());
            }

            // Do the actual force attack.  Code taken from perks.
            if (featID == (int)CustomFeatType.ForceLightning)
            {
                int length;
                int dotAmount;

                int         basePotency;
                const float Tier1Modifier = 1.0f;
                const float Tier2Modifier = 1.6f;
                const float Tier3Modifier = 2.2f;
                const float Tier4Modifier = 0;

                switch (perkLevel)
                {
                case 1:
                    basePotency = 15;
                    length      = 0;
                    dotAmount   = 0;
                    break;

                case 2:
                    basePotency = 20;
                    length      = 6;
                    dotAmount   = 4;
                    break;

                case 3:
                    basePotency = 25;
                    length      = 6;
                    dotAmount   = 6;
                    break;

                case 4:
                    basePotency = 40;
                    length      = 12;
                    dotAmount   = 6;
                    break;

                case 5:
                    basePotency = 50;
                    length      = 12;
                    dotAmount   = 6;
                    break;

                case 6:
                    basePotency = 60;
                    length      = 12;
                    dotAmount   = 6;
                    break;

                case 7:
                    basePotency = 70;
                    length      = 12;
                    dotAmount   = 6;
                    break;

                case 8:
                    basePotency = 80;
                    length      = 12;
                    dotAmount   = 8;
                    break;

                case 9:
                    basePotency = 90;
                    length      = 12;
                    dotAmount   = 8;
                    break;

                default:
                    basePotency = 100;
                    length      = 12;
                    dotAmount   = 10;
                    break;
                }

                var calc = CombatService.CalculateForceDamage(
                    caster,
                    target.Object,
                    ForceAbilityType.Electrical,
                    basePotency,
                    Tier1Modifier,
                    Tier2Modifier,
                    Tier3Modifier,
                    Tier4Modifier);

                caster.AssignCommand(() => {
                    _.SetFacingPoint(target.Location.Position);
                    _.ActionPlayAnimation(ANIMATION_LOOPING_CONJURE1, 1.0f, 1.0f);
                });

                caster.SetLocalInt("CASTING", 1);

                _.DelayCommand(1.0f, () =>
                {
                    caster.AssignCommand(() =>
                    {
                        Effect damage = _.EffectDamage(calc.Damage, DAMAGE_TYPE_ELECTRICAL);
                        _.ApplyEffectToObject(DURATION_TYPE_INSTANT, damage, target);
                    });

                    if (length > 0.0f && dotAmount > 0)
                    {
                        CustomEffectService.ApplyCustomEffect(caster, target.Object, CustomEffectType.ForceShock, length, perkLevel, dotAmount.ToString());
                    }

                    caster.AssignCommand(() =>
                    {
                        _.ApplyEffectToObject(DURATION_TYPE_TEMPORARY, _.EffectVisualEffect(VFX_BEAM_LIGHTNING), target, 1.0f);
                        caster.DeleteLocalInt("CASTING");
                    });

                    CombatService.AddTemporaryForceDefense(target.Object, ForceAbilityType.Electrical);
                });
            }
            else if (featID == (int)CustomFeatType.DrainLife)
            {
                float       recoveryPercent;
                int         basePotency;
                const float Tier1Modifier = 1;
                const float Tier2Modifier = 2;
                const float Tier3Modifier = 0;
                const float Tier4Modifier = 0;

                switch (perkLevel)
                {
                case 1:
                    basePotency     = 10;
                    recoveryPercent = 0.2f;
                    break;

                case 2:
                    basePotency     = 15;
                    recoveryPercent = 0.2f;
                    break;

                case 3:
                    basePotency     = 20;
                    recoveryPercent = 0.4f;
                    break;

                case 4:
                    basePotency     = 25;
                    recoveryPercent = 0.4f;
                    break;

                default:
                    basePotency     = 30;
                    recoveryPercent = 0.5f;
                    break;
                }

                var calc = CombatService.CalculateForceDamage(
                    caster,
                    target.Object,
                    ForceAbilityType.Dark,
                    basePotency,
                    Tier1Modifier,
                    Tier2Modifier,
                    Tier3Modifier,
                    Tier4Modifier);

                caster.AssignCommand(() => {
                    _.SetFacingPoint(target.Location.Position);
                    _.ActionPlayAnimation(ANIMATION_LOOPING_CONJURE1, 1.0f, 1.0f);
                });
                caster.SetLocalInt("CASTING", 1);

                _.DelayCommand(1.0f, () =>
                {
                    _.AssignCommand(caster, () =>
                    {
                        int heal = (int)(calc.Damage * recoveryPercent);
                        if (heal > target.CurrentHP)
                        {
                            heal = target.CurrentHP;
                        }

                        _.ApplyEffectToObject(DURATION_TYPE_INSTANT, _.EffectDamage(calc.Damage), target);
                        _.ApplyEffectToObject(DURATION_TYPE_INSTANT, _.EffectHeal(heal), caster);
                        _.ApplyEffectToObject(DURATION_TYPE_TEMPORARY, _.EffectVisualEffect(VFX_BEAM_MIND), target, 1.0f);
                        caster.DeleteLocalInt("CASTING");
                    });
                });


                CombatService.AddTemporaryForceDefense(target.Object, ForceAbilityType.Dark);
            }

            return(true);
        }