public bool Run(params object[] args)
        {
            NWCreature oPC = NWCreature.Wrap(_.GetEnteringObject());

            if (!oPC.IsPlayer)
            {
                return(false);
            }

            string triggerID = _.GetLocalString(Object.OBJECT_SELF, "TRIGGER_ID");

            if (string.IsNullOrWhiteSpace(triggerID))
            {
                triggerID = Guid.NewGuid().ToString();
                _.SetLocalString(Object.OBJECT_SELF, "TRIGGER_ID", triggerID);
            }

            if (_.GetLocalInt(oPC.Object, triggerID) == 1)
            {
                return(false);
            }

            string message = _.GetLocalString(Object.OBJECT_SELF, "DISPLAY_TEXT");

            _.SendMessageToPC(oPC.Object, _colorToken.Cyan(message));
            _.SetLocalInt(oPC.Object, triggerID, 1);

            _.AssignCommand(oPC.Object, () => _.PlaySound("gui_prompt"));

            return(true);
        }
        public void OnNPCPhysicallyAttacked()
        {
            NWCreature self     = NWCreature.Wrap(Object.OBJECT_SELF);
            NWCreature attacker = NWCreature.Wrap(_.GetLastAttacker(Object.OBJECT_SELF));

            AdjustEnmity(self, attacker, 0, 1);
        }
        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");
        }
Exemple #4
0
        public bool Run(params object[] args)
        {
            NWPlayer pc = NWPlayer.Wrap(_.GetLastUsedBy());

            if (!pc.IsValid)
            {
                pc = NWPlayer.Wrap(_.GetPCSpeaker());
            }

            string conversation = _.GetLocalString(Object.OBJECT_SELF, "CONVERSATION");

            if (!string.IsNullOrWhiteSpace(conversation))
            {
                int objectType = _.GetObjectType(Object.OBJECT_SELF);
                if (objectType == OBJECT_TYPE_PLACEABLE)
                {
                    NWPlaceable talkTo = NWPlaceable.Wrap(Object.OBJECT_SELF);
                    _dialog.StartConversation(pc, talkTo, conversation);
                }
                else
                {
                    NWCreature talkTo = NWCreature.Wrap(Object.OBJECT_SELF);
                    _dialog.StartConversation(pc, talkTo, conversation);
                }
            }
            else
            {
                _.ActionStartConversation(pc.Object, "", TRUE, FALSE);
            }

            return(true);
        }
Exemple #5
0
        public void OnImpact(NWPlayer oPC, NWObject oTarget)
        {
            int level = _perk.GetPCPerkLevel(oPC, PerkType.HolyShot);
            int damage;
            int alterationBonus = oPC.EffectiveAlterationBonus;

            switch (level)
            {
            case 1:
                damage = _random.Random(8 + alterationBonus) + 1;
                break;

            case 2:
                damage  = _random.Random(6 + alterationBonus) + 1;
                damage += _random.Random(6 + alterationBonus) + 1;
                break;

            case 3:
                damage  = _random.Random(6 + alterationBonus) + 1;
                damage += _random.Random(6 + alterationBonus) + 1;
                break;

            case 4:
                damage  = _random.Random(4 + alterationBonus) + 1;
                damage += _random.Random(4 + alterationBonus) + 1;
                damage += _random.Random(4 + alterationBonus) + 1;
                damage += _random.Random(4 + alterationBonus) + 1;
                break;

            case 5:
                damage  = _random.Random(4 + alterationBonus) + 1;
                damage += _random.Random(4 + alterationBonus) + 1;
                damage += _random.Random(4 + alterationBonus) + 1;
                damage += _random.Random(4 + alterationBonus) + 1;
                damage += _random.Random(4 + alterationBonus) + 1;
                break;

            default:
                return;
            }

            int wisdom       = oPC.WisdomModifier;
            int intelligence = oPC.IntelligenceModifier;

            float damageMultiplier = 1.0f + (intelligence * 0.4f) + (wisdom * 0.2f);

            damage = (int)(damage * damageMultiplier);

            Effect vfx = _.EffectBeam(VFX_BEAM_SILENT_HOLY, oPC.Object, BODY_NODE_CHEST);

            _.ApplyEffectToObject(DURATION_TYPE_TEMPORARY, vfx, oTarget.Object, 1.5f);

            _skill.RegisterPCToNPCForSkill(oPC, NWCreature.Wrap(oTarget.Object), SkillType.AlterationMagic);

            oPC.AssignCommand(() =>
            {
                _.ApplyEffectToObject(DURATION_TYPE_INSTANT, _.EffectDamage(damage), oTarget.Object);
            });
        }
Exemple #6
0
 public OnCreatureEvent(ISkillService skill,
                        ILootService loot,
                        IBehaviourService behaviour)
 {
     Self       = NWCreature.Wrap(Object.OBJECT_SELF);
     _skill     = skill;
     _loot      = loot;
     _behaviour = behaviour;
 }
        public void OnNPCDamaged()
        {
            NWCreature self         = NWCreature.Wrap(Object.OBJECT_SELF);
            NWCreature damager      = NWCreature.Wrap(_.GetLastDamager(Object.OBJECT_SELF));
            int        enmityAmount = _.GetTotalDamageDealt();

            if (enmityAmount <= 0)
            {
                enmityAmount = 1;
            }

            AdjustEnmity(self, damager, 0, enmityAmount);
        }
        public void OnPlayerDamaged()
        {
            NWPlayer   player = NWPlayer.Wrap(Object.OBJECT_SELF);
            NWCreature npc    = NWCreature.Wrap(_.GetLastDamager(Object.OBJECT_SELF));

            if (!player.IsPlayer || !npc.IsNPC)
            {
                return;
            }

            int    damage = _.GetTotalDamageDealt();
            Enmity enmity = GetEnmity(npc, player);

            enmity.CumulativeAmount -= damage;
        }
        public NWCreature DeserializeCreature(string base64String, Location location)
        {
            if (location == null)
            {
                throw new ArgumentException("Invalid target location during creature deserialization.");
            }

            NWCreature creature = NWCreature.Wrap(_nwnxObject.Deserialize(base64String));

            if (creature.Object == null)
            {
                throw new NullReferenceException("Unable to deserialize creature.");
            }
            creature.Location = location;

            return(creature);
        }
Exemple #10
0
        public void RegisterPCToAllCombatTargetsForSkill(NWPlayer player, SkillType skillType)
        {
            int skillID = (int)skillType;

            if (!player.IsPlayer)
            {
                return;
            }
            if (skillID <= 0)
            {
                return;
            }

            List <NWPlayer> members = new List <NWPlayer>();
            NWPlayer        member  = NWPlayer.Wrap(_.GetFirstFactionMember(player.Object));

            while (member.IsValid)
            {
                members.Add(member);
                member = NWPlayer.Wrap(_.GetNextFactionMember(player.Object));
            }

            int        nth      = 1;
            NWCreature creature = NWCreature.Wrap(_.GetNearestCreature(CREATURE_TYPE_IS_ALIVE, 1, player.Object, nth, CREATURE_TYPE_PLAYER_CHAR, 0));

            while (creature.IsValid)
            {
                if (_.GetDistanceBetween(player.Object, creature.Object) > 20.0f)
                {
                    break;
                }

                NWObject target = NWObject.Wrap(_.GetAttackTarget(creature.Object));
                if (target.IsValid && members.Contains(target))
                {
                    if (target.IsValid && target.Area.Equals(player.Area))
                    {
                        RegisterPCToNPCForSkill(player, creature, skillID);
                    }
                }

                nth++;
                creature = NWCreature.Wrap(_.GetNearestCreature(CREATURE_TYPE_IS_ALIVE, 1, player.Object, nth, CREATURE_TYPE_PLAYER_CHAR, 0));
            }
        }
Exemple #11
0
        public void OnHitCastSpell(NWPlayer oPC)
        {
            if (!oPC.IsPlayer)
            {
                return;
            }
            NWItem     oSpellOrigin = NWItem.Wrap(_.GetSpellCastItem());
            NWCreature oTarget      = NWCreature.Wrap(_.GetSpellTargetObject());

            int skillID = GetWeaponSkillID(oSpellOrigin);

            if (skillID <= -1)
            {
                return;
            }
            if (oTarget.IsPlayer || oTarget.IsDM)
            {
                return;
            }
            if (oTarget.ObjectType != OBJECT_TYPE_CREATURE)
            {
                return;
            }

            CreatureSkillRegistration reg = GetCreatureSkillRegistration(oTarget.GlobalID);

            reg.AddSkillRegistrationPoint(oPC, skillID, oSpellOrigin.RecommendedLevel);

            // Add a registration point if a shield is equipped. This is to prevent players from swapping out a weapon for a shield
            // just before they kill an enemy.
            NWItem oShield = oPC.LeftHand;

            if (oShield.BaseItemType == BASE_ITEM_SMALLSHIELD ||
                oShield.BaseItemType == BASE_ITEM_LARGESHIELD ||
                oShield.BaseItemType == BASE_ITEM_TOWERSHIELD)
            {
                reg.AddSkillRegistrationPoint(oPC, (int)SkillType.Shields, oShield.RecommendedLevel);
            }

            if (_random.Random(100) + 1 <= 3)
            {
                _food.DecreaseHungerLevel(oPC, 1);
            }
        }
        private void HandleApplySneakAttackDamage(DamageData data)
        {
            NWObject damager         = data.Damager;
            int      sneakAttackType = damager.GetLocalInt("SNEAK_ATTACK_ACTIVE");

            if (damager.IsPlayer && sneakAttackType > 0)
            {
                NWPlayer   player    = NWPlayer.Wrap(damager.Object);
                NWCreature target    = NWCreature.Wrap(Object.OBJECT_SELF);
                int        perkRank  = _perk.GetPCPerkByID(damager.GlobalID, (int)PerkType.SneakAttack).PerkLevel;
                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;
                }

                float damageRate = 1.0f + perkRate + (player.EffectiveSneakAttackBonus * 0.05f);
                data.Base = (int)(data.Base * damageRate);

                if (target.IsNPC)
                {
                    _enmity.AdjustEnmity(target, player, 5 * data.Base);
                }

                _nwnxDamage.SetDamageEventData(data);
            }

            damager.DeleteLocalInt("SNEAK_ATTACK_ACTIVE");
        }
Exemple #13
0
        private void DoPeekOutside()
        {
            const float MaxDistance = 2.5f;
            NWPlaceable door        = (NWPlaceable)GetDialogTarget();
            Location    location    = door.GetLocalLocation("PLAYER_HOME_EXIT_LOCATION");

            int        numberFound = 0;
            int        nth         = 1;
            NWCreature nearest     = NWCreature.Wrap(_.GetNearestObjectToLocation(OBJECT_TYPE_CREATURE, location, nth));

            while (nearest.IsValid)
            {
                if (_.GetDistanceBetweenLocations(location, nearest.Location) > MaxDistance)
                {
                    break;
                }

                if (nearest.IsPlayer)
                {
                    numberFound++;
                }

                nth++;
                nearest = NWCreature.Wrap(_.GetNearestObjectToLocation(OBJECT_TYPE_CREATURE, location, nth));
            }

            if (numberFound <= 0)
            {
                _.FloatingTextStringOnCreature("You don't see anyone outside.", GetPC().Object, FALSE);
            }
            else if (numberFound == 1)
            {
                _.FloatingTextStringOnCreature("You see one person outside.", GetPC().Object, FALSE);
            }
            else
            {
                _.FloatingTextStringOnCreature("You see " + numberFound + " people outside.", GetPC().Object, FALSE);
            }
        }
Exemple #14
0
        public void RegisterPCToAllCombatTargetsForSkill(NWPlayer pc, int skillID)
        {
            if (!pc.IsPlayer || skillID <= 0)
            {
                return;
            }

            List <NWCreature> members = new List <NWCreature>();

            NWN.Object member = _.GetFirstFactionMember(pc.Object);
            while (_.GetIsObjectValid(member) == TRUE)
            {
                members.Add(NWCreature.Wrap(member));
                member = _.GetNextFactionMember(pc.Object);
            }

            int        nth      = 1;
            NWCreature creature = NWCreature.Wrap(_.GetNearestCreature(CREATURE_TYPE_IS_ALIVE, 1, pc.Object, nth, CREATURE_TYPE_PLAYER_CHAR, 0));

            while (creature.IsValid)
            {
                if (_.GetDistanceBetween(pc.Object, creature.Object) > 20.0f)
                {
                    break;
                }

                NWCreature target = NWCreature.Wrap(_.GetAttackTarget(creature.Object));
                if (target.IsValid && members.Contains(target))
                {
                    if (target.IsValid && target.Area.Equals(pc.Area))
                    {
                        RegisterPCToNPCForSkill(pc, creature, skillID);
                    }
                }

                nth++;
                creature = NWCreature.Wrap(_.GetNearestCreature(CREATURE_TYPE_IS_ALIVE, 1, pc.Object, nth, CREATURE_TYPE_PLAYER_CHAR, 0));
            }
        }
        public BehaviourTreeBuilder Build(BehaviourTreeBuilder builder, params object[] args)
        {
            return(builder.Do("AggroTargetBySound", t =>
            {
                NWCreature self = (NWCreature)args[0];

                if (self.IsInCombat)
                {
                    return BehaviourTreeStatus.Failure;
                }

                float aggroRange = self.GetLocalFloat("AGGRO_RANGE");
                if (aggroRange <= 0.0f)
                {
                    aggroRange = 5.0f;
                }

                int nth = 1;
                NWCreature creature = NWCreature.Wrap(_.GetNearestObject(NWScript.OBJECT_TYPE_CREATURE, self.Object, nth));
                while (creature.IsValid)
                {
                    if (_.GetIsEnemy(creature.Object, self.Object) == NWScript.TRUE &&
                        !_enmity.IsOnEnmityTable(self, creature) &&
                        !creature.HasAnyEffect(NWScript.EFFECT_TYPE_SANCTUARY) &&
                        _.GetDistanceBetween(self.Object, creature.Object) <= aggroRange &&
                        _.LineOfSightObject(self.Object, creature.Object) == NWScript.TRUE)
                    {
                        _enmity.AdjustEnmity(self, creature, 0, 1);
                    }

                    nth++;
                    creature = NWCreature.Wrap(_.GetNearestObject(NWScript.OBJECT_TYPE_CREATURE, self.Object, nth));
                }


                return BehaviourTreeStatus.Running;
            }));
        }
Exemple #16
0
        public BehaviourTreeBuilder Build(BehaviourTreeBuilder builder, params object[] args)
        {
            return(builder.Do("AggroTargetBySight", t =>
            {
                NWCreature self = (NWCreature)args[0];

                if (self.IsInCombat)
                {
                    return BehaviourTreeStatus.Failure;
                }

                float aggroRange = self.GetLocalFloat("AGGRO_RANGE");
                if (aggroRange <= 0.0f)
                {
                    aggroRange = 10.0f;
                }
                Location targetLocation = _.Location(
                    self.Area.Object,
                    _biowarePos.GetChangedPosition(self.Position, aggroRange, self.Facing),
                    self.Facing + 180.0f);

                NWCreature creature = NWCreature.Wrap(_.GetFirstObjectInShape(NWScript.SHAPE_SPELLCYLINDER, aggroRange, targetLocation, NWScript.TRUE, NWScript.OBJECT_TYPE_CREATURE, self.Position));
                while (creature.IsValid)
                {
                    if (_.GetIsEnemy(creature.Object, self.Object) == NWScript.TRUE &&
                        !_enmity.IsOnEnmityTable(self, creature) &&
                        _.GetDistanceBetween(self.Object, creature.Object) <= aggroRange &&
                        !creature.HasAnyEffect(NWScript.EFFECT_TYPE_INVISIBILITY, NWScript.EFFECT_TYPE_SANCTUARY))
                    {
                        _enmity.AdjustEnmity(self, creature, 0, 1);
                    }

                    creature = NWCreature.Wrap(_.GetNextObjectInShape(NWScript.SHAPE_SPELLCYLINDER, aggroRange, targetLocation, NWScript.TRUE, NWScript.OBJECT_TYPE_CREATURE, self.Position));
                }

                return BehaviourTreeStatus.Running;
            }));
        }
Exemple #17
0
        public void OnImpact(NWPlayer oPC, NWObject oTarget)
        {
            NWCreature npc = NWCreature.Wrap(oTarget.Object);
            Effect     vfx = _.EffectVisualEffect(VFX_IMP_CHARM);

            _.ApplyEffectToObject(DURATION_TYPE_INSTANT, vfx, oTarget.Object);

            oPC.AssignCommand(() =>
            {
                _.ActionPlayAnimation(ANIMATION_FIREFORGET_TAUNT, 1f, 1f);
            });

            _enmity.AdjustEnmity(npc, oPC, 120);

            // todo debugging
            EnmityTable table = _enmity.GetEnmityTable(npc);

            foreach (var x in table.Values)
            {
                Console.WriteLine(npc.Name + ", " + x.TargetObject.Name + ": Volatile = " + x.VolatileAmount + ", Cumulative: " + x.CumulativeAmount);
            }
            // todo end debugging
        }
Exemple #18
0
 protected CreatureBase()
 {
     Self = NWCreature.Wrap(Object.OBJECT_SELF);
 }
        public void OnModuleUseFeat()
        {
            NWPlayer   pc     = NWPlayer.Wrap(Object.OBJECT_SELF);
            NWCreature target = NWCreature.Wrap(_nwnxEvents.OnFeatUsed_GetTarget().Object);
            int        featID = _nwnxEvents.OnFeatUsed_GetFeatID();

            Data.Entities.Perk perk = _db.Perks.SingleOrDefault(x => x.FeatID == featID);
            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, NWPlayer.Wrap(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 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);
                ApplyEnmity(pc, target, perk);

                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);
            }
        }
        private void CastSpell(NWPlayer pc,
                               NWObject target,
                               Data.Entities.Perk entity,
                               IPerk perk,
                               CooldownCategory cooldown)
        {
            string spellUUID       = Guid.NewGuid().ToString("N");
            int    itemBonus       = pc.EffectiveCastingSpeed;
            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);
                    if (target.IsNPC)
                    {
                        ApplyEnmity(pc, NWCreature.Wrap(target.Object), entity);
                    }
                }
                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);
                }

                if (!_customEffect.DoesPCHaveCustomEffect(pc, CustomEffectType.Chainspell))
                {
                    // Mark cooldown on category
                    ApplyCooldown(pc, cooldown, perk);
                }
                pc.IsBusy = false;
            }, castingTime + 0.5f);
        }
 protected BehaviourBase()
 {
     Self = NWCreature.Wrap(Object.OBJECT_SELF);
 }