예제 #1
0
        private void ScanArea(NWCreature user, Location targetLocation)
        {
            NWArea area   = (_.GetAreaFromLocation(targetLocation));
            var    spawns = SpawnService.GetAreaPlaceableSpawns(area);
            var    spawn  = spawns
                            .Where(x => !string.IsNullOrWhiteSpace(x.SpawnPlaceable.GetLocalString("RESOURCE_RESREF")) &&
                                   x.SpawnPlaceable.IsValid)
                            .OrderBy(o => _.GetDistanceBetweenLocations(targetLocation, o.Spawn.Location))
                            .FirstOrDefault();
            const float BaseScanningRange = 20.0f;

            if (spawn == null || _.GetDistanceBetweenLocations(targetLocation, spawn.SpawnLocation) > BaseScanningRange)
            {
                user.FloatingText("Couldn't locate any nearby resources...");
            }
            else
            {
                var position = _.GetPositionFromLocation(spawn.SpawnLocation);
                int cellX    = (int)(position.m_X / 10);
                int cellY    = (int)(position.m_Y / 10);

                BiowarePosition.TurnToFaceLocation(spawn.SpawnLocation, user);

                user.FloatingText("Nearest resource is located at coordinates (" + cellX + ", " + cellY + ")");
            }
        }
예제 #2
0
        private void StartSmelt(NWPlaceable forge, NWPlayer pc, NWItem item)
        {
            int charges = forge.GetLocalInt("FORGE_CHARGES");

            if (item.Resref == "power_core")
            {
                item.Destroy();
                charges += 10 + CalculatePerkCoalBonusCharges(pc) + GetPowerCoreDurability(item) * 2;
                forge.SetLocalInt("FORGE_CHARGES", charges);

                NWPlaceable flames = (forge.GetLocalObject("FORGE_FLAMES"));
                if (!flames.IsValid)
                {
                    Vector   flamePosition = BiowarePosition.GetChangedPosition(forge.Position, 0.36f, forge.Facing);
                    Location flameLocation = _.Location(forge.Area.Object, flamePosition, 0.0f);
                    flames = (_.CreateObject(_.OBJECT_TYPE_PLACEABLE, "forge_flame", flameLocation));
                    forge.SetLocalObject("FORGE_FLAMES", flames.Object);
                }

                return;
            }
            else if (charges <= 0)
            {
                ReturnItemToPC(pc, item, "You must power the refinery with a power unit before refining.");
                return;
            }

            // Ready to smelt
            float baseCraftDelay = 18.0f - (18.0f * PerkService.GetCreaturePerkLevel(pc, PerkType.SpeedyRefining) * 0.1f);

            pc.IsBusy = true;
            NWNXPlayer.StartGuiTimingBar(pc, baseCraftDelay, string.Empty);

            // Any component bonuses on the ore get applied to the end product.
            var itemProperties = item.ItemProperties.Where(x =>
                                                           _.GetItemPropertyType(x) == (int)CustomItemPropertyType.ComponentBonus ||
                                                           _.GetItemPropertyType(x) == (int)CustomItemPropertyType.RecommendedLevel).ToList();

            string itemResref = item.Resref;

            var @event = new OnCompleteSmelt(pc, itemResref, itemProperties);

            pc.DelayEvent(baseCraftDelay, @event);

            _.ApplyEffectToObject(_.DURATION_TYPE_TEMPORARY, _.EffectCutsceneImmobilize(), pc.Object, baseCraftDelay);
            pc.AssignCommand(() => _.ActionPlayAnimation(_.ANIMATION_LOOPING_GET_MID, 1.0f, baseCraftDelay));
            item.Destroy();
        }
예제 #3
0
        public void OnImpact(NWCreature player, NWObject target, int perkLevel, int spellTier)
        {
            NWItem weapon = player.RightHand;
            int    iDamage;
            int    iRange = 15;
            int    iCount = 1;
            float  fDelay = 0;

            int saberDamage = player.RightHand.DamageBonus;

            if (saberDamage > 40)
            {
                saberDamage = 40;
            }

            if (weapon.CustomItemType == CustomItemType.Lightsaber ||
                weapon.CustomItemType == CustomItemType.Saberstaff)
            {
                iDamage = saberDamage + RandomService.D6(2) + player.StrengthModifier;
            }
            else
            {
                iDamage = (int)weapon.Weight + player.StrengthModifier + (saberDamage / 2);
            }

            NWObject oObject;

            // If player is in stealth mode, force them out of stealth mode.
            if (_.GetActionMode(player.Object, ActionMode.Stealth) == true)
            {
                _.SetActionMode(player.Object, ActionMode.Stealth, false);
            }

            // Make the player face their target.
            _.ClearAllActions();
            BiowarePosition.TurnToFaceObject(target, player);

            player.AssignCommand(() => _.ActionPlayAnimation(Animation.LoopingCustom10, 2));

            var   result = CombatService.CalculateAbilityResistance(player, target.Object, SkillType.ForceAlter, ForceBalanceType.Universal);
            float delta  = 0.01f * result.Delta;

            /*
             * // reset phenotype
             *  player.DelayAssignCommand(() =>
             *  {
             *      _.SetPhenoType(4, player);
             *  }, 2.0f);
             *
             *  player.DelayAssignCommand(() =>
             *  {
             *      _.SetPhenoType(iPheno, player);
             *  }, 2.5f);
             */

            // Handle effects for differing spellTier values
            switch (spellTier)
            {
            case 1:
                iDamage = (int)(iDamage * 1.0);
                iDamage = iDamage + (int)(iDamage * delta);

                fDelay = _.GetDistanceBetween(player, target) / 10.0f;

                player.DelayAssignCommand(() =>
                {
                    _.ApplyEffectToObject(DurationType.Instant, _.EffectLinkEffects(_.EffectVisualEffect(VisualEffect.Vfx_Imp_Sonic), _.EffectDamage(iDamage, DamageType.BaseWeapon)), target);
                }, fDelay);

                if (player.IsPlayer)
                {
                    SkillService.RegisterPCToNPCForSkill(player.Object, target, SkillType.ForceAlter);
                }

                break;

            case 2:
                iDamage = (int)(iDamage * 1.25);
                iDamage = iDamage + (int)(iDamage * delta);

                fDelay = _.GetDistanceBetween(player, target) / 10.0f;

                player.DelayAssignCommand(() =>
                {
                    _.ApplyEffectToObject(DurationType.Instant, _.EffectLinkEffects(_.EffectVisualEffect(VisualEffect.Vfx_Imp_Sonic), _.EffectDamage(iDamage, DamageType.BaseWeapon)), target);
                }, fDelay);

                if (player.IsPlayer)
                {
                    SkillService.RegisterPCToNPCForSkill(player.Object, target, SkillType.ForceAlter);
                }

                break;

            case 3:
                iDamage = (int)(iDamage * 1.5);
                iDamage = iDamage + (int)(iDamage * delta);

                fDelay = _.GetDistanceBetween(player, target) / 10.0f;

                player.DelayAssignCommand(() =>
                {
                    _.ApplyEffectToObject(DurationType.Instant, _.EffectLinkEffects(_.EffectVisualEffect(VisualEffect.Vfx_Imp_Sonic), _.EffectDamage(iDamage, DamageType.BaseWeapon)), target);
                }, fDelay);

                if (player.IsPlayer)
                {
                    SkillService.RegisterPCToNPCForSkill(player.Object, target, SkillType.ForceAlter);
                }

                break;

            case 4:
                iDamage = (int)(iDamage * 1.6);
                iDamage = iDamage + (int)(iDamage * delta);

                // apply to target
                fDelay = _.GetDistanceBetween(player, target) / 10.0f;

                player.DelayAssignCommand(() =>
                {
                    _.ApplyEffectToObject(DurationType.Instant, _.EffectLinkEffects(_.EffectVisualEffect(VisualEffect.Vfx_Imp_Sonic), _.EffectDamage(iDamage, DamageType.BaseWeapon)), target);
                }, fDelay);

                if (player.IsPlayer)
                {
                    SkillService.RegisterPCToNPCForSkill(player.Object, target, SkillType.ForceAlter);
                }

                iCount += 1;

                // apply to next nearest creature in the spellcylinder
                oObject = _.GetFirstObjectInShape(Shape.SpellCone, iRange, target.Location, true, ObjectType.Creature, _.GetPosition(player));
                while (oObject.IsValid && iCount < 3)
                {
                    if (oObject != target && oObject != player)
                    {
                        fDelay = _.GetDistanceBetween(player, oObject) / 10.0f;
                        var creature = oObject;
                        player.DelayAssignCommand(() =>
                        {
                            _.ApplyEffectToObject(DurationType.Instant, _.EffectLinkEffects(_.EffectVisualEffect(VisualEffect.Vfx_Imp_Sonic), _.EffectDamage(iDamage, DamageType.BaseWeapon)), creature);
                        }, fDelay);

                        if (player.IsPlayer)
                        {
                            SkillService.RegisterPCToNPCForSkill(player.Object, oObject, SkillType.ForceAlter);
                        }
                        iCount += 1;
                    }
                    oObject = _.GetNextObjectInShape(Shape.SpellCone, iRange, target.Location, true, ObjectType.Creature, _.GetPosition(player));
                }
                break;

            case 5:
                iDamage = (int)(iDamage * 1.75);
                iDamage = iDamage + (int)(iDamage * delta);

                // apply to target
                fDelay = _.GetDistanceBetween(player, target) / 10.0f;

                player.DelayAssignCommand(() =>
                {
                    _.ApplyEffectToObject(DurationType.Instant, _.EffectLinkEffects(_.EffectVisualEffect(VisualEffect.Vfx_Imp_Sonic), _.EffectDamage(iDamage, DamageType.BaseWeapon)), target);
                }, fDelay);

                if (player.IsPlayer)
                {
                    SkillService.RegisterPCToNPCForSkill(player.Object, target, SkillType.ForceAlter);
                }
                iCount += 1;

                // apply to next nearest creature in the spellcylinder
                oObject = _.GetFirstObjectInShape(Shape.SpellCylinder, iRange, target.Location, true, ObjectType.Creature, _.GetPosition(player));
                while (oObject.IsValid && iCount < 4)
                {
                    if (oObject != target && oObject != player)
                    {
                        fDelay = _.GetDistanceBetween(player, oObject) / 10.0f;
                        var creature = oObject;
                        player.DelayAssignCommand(() =>
                        {
                            _.ApplyEffectToObject(DurationType.Instant, _.EffectLinkEffects(_.EffectVisualEffect(VisualEffect.Vfx_Imp_Sonic), _.EffectDamage(iDamage, DamageType.BaseWeapon)), creature);
                        }, fDelay);

                        if (player.IsPlayer)
                        {
                            SkillService.RegisterPCToNPCForSkill(player.Object, oObject, SkillType.ForceAlter);
                        }
                        iCount += 1;
                    }
                    oObject = _.GetNextObjectInShape(Shape.SpellCylinder, iRange, target.Location, true, ObjectType.Creature, _.GetPosition(player));
                }
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(spellTier));
            }
        }
예제 #4
0
        /// <summary>
        /// Handles casting abilities. These can be combat-related or casting-related and may or may not have a casting delay.
        /// Requirement reductions (MP, STM, etc) are applied after the casting has completed.
        /// In the event there is no casting delay, the reductions are applied immediately.
        /// </summary>
        /// <param name="activator">The creature activating the ability.</param>
        /// <param name="target">The target of the ability</param>
        /// <param name="ability">The ability details</param>
        /// <param name="effectivePerkLevel">The activator's effective perk level</param>
        private static void ActivateAbility(uint activator, uint target, AbilityDetail ability, int effectivePerkLevel)
        {
            // Activation delay is increased if player is equipped with heavy or light armor.
            float CalculateActivationDelay()
            {
                const float HeavyArmorPenalty = 2.0f;
                const float LightArmorPenalty = 1.5f;

                var armorPenalty   = 1.0f;
                var penaltyMessage = string.Empty;

                for (var slot = 0; slot < NumberOfInventorySlots; slot++)
                {
                    var item = GetItemInSlot((InventorySlot)slot, activator);

                    for (var ip = GetFirstItemProperty(item); GetIsItemPropertyValid(ip); ip = GetNextItemProperty(item))
                    {
                        if (GetItemPropertyType(ip) != ItemPropertyType.ArmorType)
                        {
                            continue;
                        }

                        var armorType = (ArmorType)GetItemPropertySubType(ip);
                        if (armorType == ArmorType.Heavy)
                        {
                            armorPenalty   = HeavyArmorPenalty;
                            penaltyMessage = "Heavy armor slows your casting speed by 100%.";
                            break;
                        }
                        else if (armorType == ArmorType.Light)
                        {
                            armorPenalty   = LightArmorPenalty;
                            penaltyMessage = "Light armor slows your casting speed by 50%.";
                        }
                    }

                    // If we found heavy armor, we can exit early. Anything else requires us to iterate over the rest of the items.
                    if (armorPenalty >= HeavyArmorPenalty)
                    {
                        break;
                    }
                }

                // Notify player if needed.
                if (!string.IsNullOrWhiteSpace(penaltyMessage))
                {
                    SendMessageToPC(activator, penaltyMessage);
                }

                var abilityDelay = ability.ActivationDelay?.Invoke(activator, target, effectivePerkLevel) ?? 0.0f;

                return(abilityDelay * armorPenalty);
            }

            // Handles displaying animation and visual effects.
            void ProcessAnimationAndVisualEffects(float delay)
            {
                // Force out of stealth
                if (GetActionMode(activator, ActionMode.Stealth))
                {
                    SetActionMode(activator, ActionMode.Stealth, false);
                }

                AssignCommand(activator, () => ClearAllActions());
                BiowarePosition.TurnToFaceObject(target, activator);

                // Display a casting visual effect if one has been specified.
                if (ability.ActivationVisualEffect != VisualEffect.None)
                {
                    var vfx = TagEffect(EffectVisualEffect(ability.ActivationVisualEffect), "ACTIVATION_VFX");
                    ApplyEffectToObject(DurationType.Temporary, vfx, activator, delay + 0.2f);
                }

                // Casted types play an animation of casting.
                if (ability.ActivationType == AbilityActivationType.Casted &&
                    ability.AnimationType != Animation.Invalid)
                {
                    AssignCommand(activator, () => ActionPlayAnimation(ability.AnimationType, 1.0f, delay - 0.2f));
                }
            }

            // Recursive function which checks if player has moved since starting the casting.
            void CheckForActivationInterruption(string activationId, Vector3 originalPosition)
            {
                if (!GetIsPC(activator))
                {
                    return;
                }

                // Completed abilities should no longer run.
                var status = GetLocalInt(activator, activationId);

                if (status == (int)ActivationStatus.Completed || status == (int)ActivationStatus.Invalid)
                {
                    return;
                }

                var currentPosition = GetPosition(activator);

                if (currentPosition.X != originalPosition.X ||
                    currentPosition.Y != originalPosition.Y ||
                    currentPosition.Z != originalPosition.Z)
                {
                    RemoveEffectByTag(activator, "ACTIVATION_VFX");

                    Player.StopGuiTimingBar(activator, string.Empty);
                    SendMessageToPC(activator, "Your ability has been interrupted.");
                    return;
                }

                DelayCommand(0.5f, () => CheckForActivationInterruption(activationId, originalPosition));
            }

            // This method is called after the delay of the ability has finished.
            void CompleteActivation(string id, float abilityRecastDelay)
            {
                DeleteLocalInt(activator, id);

                // Moved during casting or activator died. Cancel the activation.
                if (GetLocalInt(activator, id) == (int)ActivationStatus.Interrupted || GetCurrentHitPoints(activator) <= 0)
                {
                    return;
                }

                ApplyRequirementEffects(activator, ability);
                ability.ImpactAction?.Invoke(activator, target, effectivePerkLevel);
                ApplyRecastDelay(activator, ability.RecastGroup, abilityRecastDelay);
            }

            // Begin the main process
            var activationId    = Guid.NewGuid().ToString();
            var activationDelay = CalculateActivationDelay();
            var recastDelay     = ability.RecastDelay(activator);
            var position        = GetPosition(activator);

            ProcessAnimationAndVisualEffects(activationDelay);
            CheckForActivationInterruption(activationId, position);
            SetLocalInt(activator, activationId, (int)ActivationStatus.Started);

            if (GetIsPC(activator))
            {
                if (activationDelay > 0.0f)
                {
                    Player.StartGuiTimingBar(activator, activationDelay, string.Empty);
                }
            }

            DelayCommand(activationDelay, () => CompleteActivation(activationId, recastDelay));
        }
예제 #5
0
        public void OnImpact(NWCreature player, NWObject target, int perkLevel, int spellTier)
        {
            NWItem weapon = player.RightHand;
            int    iDamage;
            int    iRange = 15;
            int    iCount = 1;
            float  fDelay = 0;

            if (weapon.CustomItemType == CustomItemType.Lightsaber ||
                weapon.CustomItemType == CustomItemType.Saberstaff)
            {
                iDamage = player.RightHand.DamageBonus + RandomService.D6(2) + player.IntelligenceModifier + player.StrengthModifier;
            }
            else
            {
                iDamage = (int)weapon.Weight + player.StrengthModifier;
            }

            NWObject oObject;

            // If player is in stealth mode, force them out of stealth mode.
            if (_.GetActionMode(player.Object, ACTION_MODE_STEALTH) == 1)
            {
                _.SetActionMode(player.Object, ACTION_MODE_STEALTH, 0);
            }

            // Make the player face their target.
            _.ClearAllActions();
            BiowarePosition.TurnToFaceObject(target, player);

            player.AssignCommand(() => _.ActionPlayAnimation(30, 2));

            _.SendMessageToPC(player, "Level " + spellTier);

            // Handle effects for differing spellTier values
            switch (spellTier)
            {
            case 1:
                iDamage = (int)(iDamage * 1.6);

                fDelay = _.GetDistanceBetween(player, target) / 10.0f;

                player.DelayAssignCommand(() =>
                {
                    _.ApplyEffectToObject(_.DURATION_TYPE_INSTANT, _.EffectLinkEffects(_.EffectVisualEffect(VFX_IMP_SONIC), _.EffectDamage(iDamage, _.DAMAGE_TYPE_BASE_WEAPON)), target);
                }, fDelay);

                if (player.IsPlayer)
                {
                    SkillService.RegisterPCToNPCForSkill(player.Object, target, SkillType.ForceAlter);
                }

                break;

            case 2:
                iDamage = (int)(iDamage * 1.25);

                fDelay = _.GetDistanceBetween(player, target) / 10.0f;

                player.DelayAssignCommand(() =>
                {
                    _.ApplyEffectToObject(_.DURATION_TYPE_INSTANT, _.EffectLinkEffects(_.EffectVisualEffect(VFX_IMP_SONIC), _.EffectDamage(iDamage, _.DAMAGE_TYPE_BASE_WEAPON)), target);
                }, fDelay);

                if (player.IsPlayer)
                {
                    SkillService.RegisterPCToNPCForSkill(player.Object, target, SkillType.ForceAlter);
                }

                break;

            case 3:
                iDamage = (int)(iDamage * 1.6);

                fDelay = _.GetDistanceBetween(player, target) / 10.0f;

                player.DelayAssignCommand(() =>
                {
                    _.ApplyEffectToObject(_.DURATION_TYPE_INSTANT, _.EffectLinkEffects(_.EffectVisualEffect(VFX_IMP_SONIC), _.EffectDamage(iDamage, _.DAMAGE_TYPE_BASE_WEAPON)), target);
                }, fDelay);

                if (player.IsPlayer)
                {
                    SkillService.RegisterPCToNPCForSkill(player.Object, target, SkillType.ForceAlter);
                }

                break;

            case 4:
                iDamage = (int)(iDamage * 2.0);

                // apply to target
                fDelay = _.GetDistanceBetween(player, target) / 10.0f;

                player.DelayAssignCommand(() =>
                {
                    _.ApplyEffectToObject(_.DURATION_TYPE_INSTANT, _.EffectLinkEffects(_.EffectVisualEffect(VFX_IMP_SONIC), _.EffectDamage(iDamage, _.DAMAGE_TYPE_BASE_WEAPON)), target);
                }, fDelay);

                if (player.IsPlayer)
                {
                    SkillService.RegisterPCToNPCForSkill(player.Object, target, SkillType.ForceAlter);
                }

                iCount += 1;

                // apply to next nearest creature in the spellcylinder
                oObject = _.GetFirstObjectInShape(_.SHAPE_SPELLCONE, iRange, target.Location, 1, _.OBJECT_TYPE_CREATURE, _.GetPosition(player));
                while (oObject.IsValid && iCount < 3)
                {
                    if (oObject != target && oObject != player)
                    {
                        fDelay = _.GetDistanceBetween(player, oObject) / 10.0f;
                        var creature = oObject;
                        player.DelayAssignCommand(() =>
                        {
                            _.ApplyEffectToObject(_.DURATION_TYPE_INSTANT, _.EffectLinkEffects(_.EffectVisualEffect(VFX_IMP_SONIC), _.EffectDamage(iDamage, _.DAMAGE_TYPE_BASE_WEAPON)), creature);
                        }, fDelay);

                        if (player.IsPlayer)
                        {
                            SkillService.RegisterPCToNPCForSkill(player.Object, oObject, SkillType.ForceAlter);
                        }
                        iCount += 1;
                    }
                    oObject = _.GetNextObjectInShape(_.SHAPE_SPELLCONE, iRange, target.Location, 1, _.OBJECT_TYPE_CREATURE, _.GetPosition(player));
                }
                break;

            case 5:
                iDamage = (int)(iDamage * 2.5);

                // apply to target
                fDelay = _.GetDistanceBetween(player, target) / 10.0f;

                player.DelayAssignCommand(() =>
                {
                    _.ApplyEffectToObject(_.DURATION_TYPE_INSTANT, _.EffectLinkEffects(_.EffectVisualEffect(VFX_IMP_SONIC), _.EffectDamage(iDamage, _.DAMAGE_TYPE_BASE_WEAPON)), target);
                }, fDelay);

                if (player.IsPlayer)
                {
                    SkillService.RegisterPCToNPCForSkill(player.Object, target, SkillType.ForceAlter);
                }
                iCount += 1;

                // apply to next nearest creature in the spellcylinder
                oObject = _.GetFirstObjectInShape(_.SHAPE_SPELLCYLINDER, iRange, target.Location, 1, _.OBJECT_TYPE_CREATURE, _.GetPosition(player));
                while (oObject.IsValid && iCount < 4)
                {
                    if (oObject != target && oObject != player)
                    {
                        fDelay = _.GetDistanceBetween(player, oObject) / 10.0f;
                        var creature = oObject;
                        player.DelayAssignCommand(() =>
                        {
                            _.ApplyEffectToObject(_.DURATION_TYPE_INSTANT, _.EffectLinkEffects(_.EffectVisualEffect(VFX_IMP_SONIC), _.EffectDamage(iDamage, _.DAMAGE_TYPE_BASE_WEAPON)), creature);
                        }, fDelay);

                        if (player.IsPlayer)
                        {
                            SkillService.RegisterPCToNPCForSkill(player.Object, oObject, SkillType.ForceAlter);
                        }
                        iCount += 1;
                    }
                    oObject = _.GetNextObjectInShape(_.SHAPE_SPELLCYLINDER, iRange, target.Location, 1, _.OBJECT_TYPE_CREATURE, _.GetPosition(player));
                }
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(spellTier));
            }
        }
예제 #6
0
        private static void ActivateAbility(
            NWCreature activator,
            NWObject target,
            Data.Entity.Perk entity,
            IPerkHandler perkHandler,
            int pcPerkLevel,
            PerkExecutionType executionType,
            int spellTier)
        {
            string uuid = Guid.NewGuid().ToString();
            float  baseActivationTime = perkHandler.CastingTime(activator, (float)entity.BaseCastingTime, spellTier);
            float  activationTime     = baseActivationTime;
            var    vfxID       = VisualEffect.Invalid;
            var    animationID = Animation.Invalid;

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

            // Force ability armor penalties
            float armorPenalty = 0.0f;

            if (executionType == PerkExecutionType.ForceAbility ||
                executionType == PerkExecutionType.ConcentrationAbility)
            {
                string penaltyMessage = string.Empty;
                foreach (var item in activator.EquippedItems)
                {
                    if (item.CustomItemType == CustomItemType.HeavyArmor)
                    {
                        armorPenalty   = 2;
                        penaltyMessage = "Heavy armor slows your force cooldown by 100%.";
                        break;
                    }
                    else if (item.CustomItemType == CustomItemType.LightArmor)
                    {
                        armorPenalty   = 1.25f;
                        penaltyMessage = "Light armor slows your force cooldown by 25%.";
                    }
                }

                // If there's an armor penalty, send a message to the player.
                if (armorPenalty > 0.0f)
                {
                    activator.SendMessage(penaltyMessage);
                }
            }

            // If player is in stealth mode, force them out of stealth mode.
            if (_.GetActionMode(activator.Object, ActionMode.Stealth))
            {
                _.SetActionMode(activator.Object, ActionMode.Stealth, false);
            }

            // Make the player face their target.
            _.ClearAllActions();
            BiowarePosition.TurnToFaceObject(target, activator);

            // Force and Concentration Abilities will display a visual effect during the casting process.
            if (executionType == PerkExecutionType.ForceAbility ||
                executionType == PerkExecutionType.ConcentrationAbility)
            {
                vfxID       = VisualEffect.Vfx_Dur_Iounstone_Yellow;
                animationID = Animation.LoopingConjure1;
            }

            if (executionType == PerkExecutionType.ConcentrationAbility)
            {
                activator.SetLocalObject("CONCENTRATION_TARGET", target);
            }

            // If a VFX ID has been specified, play that effect instead of the default one.
            if (vfxID != VisualEffect.Invalid)
            {
                var vfx = _.EffectVisualEffect(vfxID);
                vfx = _.TagEffect(vfx, "ACTIVATION_VFX");
                _.ApplyEffectToObject(DurationType.Temporary, vfx, activator.Object, activationTime + 0.2f);
            }

            // If an animation has been specified, make the player play that animation now.
            // bypassing if perk is throw saber due to couldn't get the animation to work via db table edit
            if (animationID != Animation.Invalid && entity.ID != (int)PerkType.ThrowSaber)
            {
                activator.AssignCommand(() => _.ActionPlayAnimation(animationID, 1.0f, activationTime - 0.1f));
            }

            // Mark player as busy. Busy players can't take other actions (crafting, harvesting, etc.)
            activator.IsBusy = true;

            // Non-players can't be interrupted via movement.
            if (!activator.IsPlayer)
            {
                // Begin the check for spell interruption. If the activator moves, the spell will be canceled.
                CheckForSpellInterruption(activator, uuid, activator.Position);
            }

            activator.SetLocalInt(uuid, (int)SpellStatusType.Started);

            // If there's a casting delay, display a timing bar on-screen.
            if (activationTime > 0)
            {
                NWNXPlayer.StartGuiTimingBar(activator, (int)activationTime, string.Empty);
            }

            // Run the FinishAbilityUse event at the end of the activation time.
            int perkID = entity.ID;

            var @event = new OnFinishAbilityUse(activator, uuid, perkID, target, pcPerkLevel, spellTier, armorPenalty);

            activator.DelayEvent(activationTime + 0.2f, @event);
        }
예제 #7
0
        private static void ActivateAbility(NWPlayer pc,
                                            NWObject target,
                                            Data.Entity.Perk entity,
                                            IPerkHandler perkHandler,
                                            int pcPerkLevel,
                                            PerkExecutionType executionType,
                                            int spellFeatID)
        {
            string uuid               = Guid.NewGuid().ToString();
            var    effectiveStats     = PlayerStatService.GetPlayerItemEffectiveStats(pc);
            int    itemBonus          = effectiveStats.CastingSpeed;
            float  baseActivationTime = perkHandler.CastingTime(pc, (float)entity.BaseCastingTime, spellFeatID);
            float  activationTime     = baseActivationTime;
            int    vfxID              = -1;
            int    animationID        = -1;

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

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

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

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

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

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

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

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

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

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

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

            int perkID = entity.ID;

            pc.DelayEvent <FinishAbilityUse>(activationTime + 0.2f,
                                             pc,
                                             uuid,
                                             perkID,
                                             target,
                                             pcPerkLevel,
                                             spellFeatID);
        }