/// <summary>
        /// called when spell effect has to be started and applied to targets
        /// </summary>
        public override bool StartSpell(GameLiving target)
        {
            if (target == null)
            {
                return(false);
            }

            if (m_maxTick >= 0)
            {
                m_maxTick       = (Spell.Pulse > 1)?Spell.Pulse:1;
                m_currentTick   = 1;
                m_currentSource = target;
            }

            int ticksToTarget = m_currentSource.GetDistanceTo(target) * 100 / 85; // 85 units per 1/10s
            int delay         = 1 + ticksToTarget / 100;

            foreach (GamePlayer player in target.GetPlayersInRadius(WorldMgr.VISIBILITY_DISTANCE))
            {
                player.Out.SendSpellEffectAnimation(m_currentSource, target, m_spell.ClientEffect, (ushort)(delay), false, 1);
            }
            BoltOnTargetAction bolt = new BoltOnTargetAction(Caster, target, this);

            bolt.Start(1 + ticksToTarget);
            m_currentSource = target;
            m_currentTick++;

            return(true);
        }
Exemple #2
0
        /// <summary>
        /// Begins the callback between this gameliving source and target (commences a bolt flying between them)
        /// </summary>
        /// <param name="source"></param>
        /// <param name="target"></param>
        public void DealLightning()
        {
            int ticksToTarget = currentSource.GetDistanceTo(currentTarget) * 100 / 85; // 85 units per 1/10s
            int delay         = 1 + ticksToTarget / 100;

            foreach (GamePlayer player in currentTarget.GetPlayersInRadius(WorldMgr.VISIBILITY_DISTANCE))
            {
                player.Out.SendSpellEffectAnimation(currentSource, currentTarget, m_spell.ClientEffect, (ushort)(delay), false, 1);
            }
            BoltAction bolt = new BoltAction(this);

            bolt.Start(1 + ticksToTarget);
        }
Exemple #3
0
            /// <summary>
            /// Called on every timer tick
            /// </summary>
            protected override void OnTick()
            {
                GameLiving target = m_boltTarget;
                GameLiving caster = (GameLiving)m_actionSource;

                if (target == null)
                {
                    return;
                }
                if (target.CurrentRegionID != caster.CurrentRegionID)
                {
                    return;
                }
                if (target.ObjectState != GameObject.eObjectState.Active)
                {
                    return;
                }
                if (!target.IsAlive)
                {
                    return;
                }

                // Related to PvP hitchance
                // http://www.camelotherald.com/news/news_article.php?storyid=2444
                // No information on bolt hitchance against npc's
                // Bolts are treated as physical attacks for the purpose of ABS only
                // Based on this I am normalizing the miss rate for npc's to be that of a standard spell

                int missrate = 0;

                if (caster is GamePlayer && target is GamePlayer)
                {
                    if (target.InCombat)
                    {
                        foreach (GameLiving attacker in target.Attackers)
                        {
                            if (attacker != caster && target.GetDistanceTo(attacker) <= 200)
                            {
                                // each attacker within 200 units adds a 20% chance to miss
                                missrate += 20;
                            }
                        }
                    }
                }

                if (target is GameNPC || caster is GameNPC)
                {
                    missrate += (int)(ServerProperties.Properties.PVE_SPELL_CONHITPERCENT * caster.GetConLevel(target));
                }

                // add defence bonus from last executed style if any
                AttackData targetAD = (AttackData)target.TempProperties.getProperty <object>(GameLiving.LAST_ATTACK_DATA, null);

                if (targetAD != null &&
                    targetAD.AttackResult == GameLiving.eAttackResult.HitStyle &&
                    targetAD.Style != null)
                {
                    missrate += targetAD.Style.BonusToDefense;
                }

                AttackData ad = m_handler.CalculateDamageToTarget(target, 0.5 - (caster.GetModified(eProperty.SpellDamage) * 0.01));

                if (Util.Chance(missrate))
                {
                    ad.AttackResult = GameLiving.eAttackResult.Missed;
                    m_handler.MessageToCaster("You miss!", eChatType.CT_YouHit);
                    m_handler.MessageToLiving(target, caster.GetName(0, false) + " missed!", eChatType.CT_Missed);
                    target.OnAttackedByEnemy(ad);
                    target.StartInterruptTimer(target.SpellInterruptDuration, ad.AttackType, caster);
                    if (target is GameNPC)
                    {
                        IOldAggressiveBrain aggroBrain = ((GameNPC)target).Brain as IOldAggressiveBrain;
                        if (aggroBrain != null)
                        {
                            aggroBrain.AddToAggroList(caster, 1);
                        }
                    }
                    return;
                }

                ad.Damage = (int)((double)ad.Damage * (1.0 + caster.GetModified(eProperty.SpellDamage) * 0.01));

                // Block
                bool blocked = false;

                if (target is GamePlayer)
                {                 // mobs left out yet
                    GamePlayer    player   = (GamePlayer)target;
                    InventoryItem lefthand = player.Inventory.GetItem(eInventorySlot.LeftHandWeapon);
                    if (lefthand != null && (player.AttackWeapon == null || player.AttackWeapon.Item_Type == Slot.RIGHTHAND || player.AttackWeapon.Item_Type == Slot.LEFTHAND))
                    {
                        if (target.IsObjectInFront(caster, 180) && lefthand.Object_Type == (int)eObjectType.Shield)
                        {
                            double shield      = 0.5 * player.GetModifiedSpecLevel(Specs.Shields);
                            double blockchance = ((player.Dexterity * 2) - 100) / 40.0 + shield + 5;
                            // Removed 30% increased chance to block, can find no clear evidence this is correct - tolakram
                            blockchance -= target.GetConLevel(caster) * 5;
                            if (blockchance >= 100)
                            {
                                blockchance = 99;
                            }
                            if (blockchance <= 0)
                            {
                                blockchance = 1;
                            }

                            if (target.IsEngaging)
                            {
                                EngageEffect engage = target.EffectList.GetOfType <EngageEffect>();
                                if (engage != null && target.AttackState && engage.EngageTarget == caster)
                                {
                                    // Engage raised block change to 85% if attacker is engageTarget and player is in attackstate
                                    // You cannot engage a mob that was attacked within the last X seconds...
                                    if (engage.EngageTarget.LastAttackedByEnemyTick > engage.EngageTarget.CurrentRegion.Time - EngageAbilityHandler.ENGAGE_ATTACK_DELAY_TICK)
                                    {
                                        if (engage.Owner is GamePlayer)
                                        {
                                            (engage.Owner as GamePlayer).Out.SendMessage(engage.EngageTarget.GetName(0, true) + " has been attacked recently and you are unable to engage.", eChatType.CT_System, eChatLoc.CL_SystemWindow);
                                        }
                                    }                                      // Check if player has enough endurance left to engage
                                    else if (engage.Owner.Endurance < EngageAbilityHandler.ENGAGE_DURATION_LOST)
                                    {
                                        engage.Cancel(false);                                         // if player ran out of endurance cancel engage effect
                                    }
                                    else
                                    {
                                        engage.Owner.Endurance -= EngageAbilityHandler.ENGAGE_DURATION_LOST;
                                        if (engage.Owner is GamePlayer)
                                        {
                                            (engage.Owner as GamePlayer).Out.SendMessage("You concentrate on blocking the blow!", eChatType.CT_Skill, eChatLoc.CL_SystemWindow);
                                        }

                                        if (blockchance < 85)
                                        {
                                            blockchance = 85;
                                        }
                                    }
                                }
                            }

                            if (blockchance >= Util.Random(1, 100))
                            {
                                m_handler.MessageToLiving(player, "You partially block " + caster.GetName(0, false) + "'s spell!", eChatType.CT_Missed);
                                m_handler.MessageToCaster(player.GetName(0, true) + " blocks!", eChatType.CT_YouHit);
                                blocked = true;
                            }
                        }
                    }
                }

                double effectiveness = 1.0 + (caster.GetModified(eProperty.SpellDamage) * 0.01);

                // simplified melee damage calculation
                if (blocked == false)
                {
                    // TODO: armor resists to damage type

                    double damage = m_handler.Spell.Damage / 2;                     // another half is physical damage
                    if (target is GamePlayer)
                    {
                        ad.ArmorHitLocation = ((GamePlayer)target).CalculateArmorHitLocation(ad);
                    }

                    InventoryItem armor = null;
                    if (target.Inventory != null)
                    {
                        armor = target.Inventory.GetItem((eInventorySlot)ad.ArmorHitLocation);
                    }

                    double ws = (caster.Level * 8 * (1.0 + (caster.GetModified(eProperty.Dexterity) - 50) / 200.0));

                    damage     *= ((ws + 90.68) / (target.GetArmorAF(ad.ArmorHitLocation) + 20 * 4.67));
                    damage     *= 1.0 - Math.Min(0.85, ad.Target.GetArmorAbsorb(ad.ArmorHitLocation));
                    ad.Modifier = (int)(damage * (ad.Target.GetResist(ad.DamageType) + SkillBase.GetArmorResist(armor, ad.DamageType)) / -100.0);
                    damage     += ad.Modifier;

                    damage  = damage * effectiveness;
                    damage *= (1.0 + RelicMgr.GetRelicBonusModifier(caster.Realm, eRelicType.Magic));

                    if (damage < 0)
                    {
                        damage = 0;
                    }
                    ad.Damage += (int)damage;
                }

                if (m_handler is SiegeArrow == false)
                {
                    ad.UncappedDamage = ad.Damage;
                    ad.Damage         = (int)Math.Min(ad.Damage, m_handler.DamageCap(effectiveness));
                }

                ad.Damage = (int)(ad.Damage * caster.Effectiveness);

                if (blocked == false && ad.CriticalDamage > 0)
                {
                    int critMax = (target is GamePlayer) ? ad.Damage / 2 : ad.Damage;
                    ad.CriticalDamage = Util.Random(critMax / 10, critMax);
                }

                m_handler.SendDamageMessages(ad);
                m_handler.DamageTarget(ad, false, (blocked ? 0x02 : 0x14));
                target.StartInterruptTimer(target.SpellInterruptDuration, ad.AttackType, caster);
            }
        private void DamageTarget(GameLiving target)
        {
            if (!GameServer.ServerRules.IsAllowedToAttack(_owner, target, true))
            {
                return;
            }

            if (!target.IsAlive)
            {
                return;
            }

            if (_ticktimer.IsAlive)
            {
                _ticktimer.Stop();
                removeHandlers();
            }

            int    dist = target.GetDistanceTo(new Point3D(_traparea.X, _traparea.Y, _traparea.Z));
            double mod  = 1;

            if (dist > 0)
            {
                mod = 1 - ((double)dist / 350);
            }

            int basedamage = (int)(_effectiveness * mod);
            int resist     = (int)(basedamage * target.GetModified(eProperty.Resist_Energy) * -0.01);
            int damage     = basedamage + resist;

            if (_owner is GamePlayer player)
            {
                player.Out.SendMessage($"You hit {target.Name} for {damage}({resist}) points of damage!", eChatType.CT_YouHit, eChatLoc.CL_SystemWindow);
            }

            if (target is GamePlayer targetPlayer)
            {
                if (targetPlayer.IsStealthed)
                {
                    targetPlayer.Stealth(false);
                }
            }

            foreach (GamePlayer p in target.GetPlayersInRadius(false, WorldMgr.VISIBILITY_DISTANCE))
            {
                p.Out.SendSpellEffectAnimation(_owner, target, 7026, 0, false, 1);
                p.Out.SendCombatAnimation(_owner, target, 0, 0, 0, 0, 0x14, target.HealthPercent);
            }

            // target.TakeDamage(owner, eDamageType.Energy, damage, 0);
            AttackData ad = new AttackData
            {
                AttackResult = GameLiving.eAttackResult.HitUnstyled,
                Attacker     = _owner,
                Target       = target,
                DamageType   = eDamageType.Energy,
                Damage       = damage
            };

            target.OnAttackedByEnemy(ad);
            _owner.DealDamage(ad);
        }
		private void DamageTarget(GameLiving target)
		{
			if (!GameServer.ServerRules.IsAllowedToAttack(owner, target, true))
				return;
			if (!target.IsAlive)
				return;
			if (ticktimer.IsAlive)
			{
				ticktimer.Stop();
				removeHandlers();
			}
			int dist = target.GetDistanceTo( new Point3D( traparea.X, traparea.Y, traparea.Z ) );
			double mod = 1;
			if (dist > 0)
				mod = 1 - ((double)dist / 350);

			int basedamage = (int)(effectiveness * mod);
			int resist = (int)(basedamage * target.GetModified(eProperty.Resist_Energy) * -0.01);
			int damage = basedamage + resist;


			GamePlayer player = owner as GamePlayer;
			if (player != null)
			{
				player.Out.SendMessage("You hit " + target.Name + " for " + damage + "(" + resist + ") points of damage!", eChatType.CT_YouHit, eChatLoc.CL_SystemWindow);
			}

			GamePlayer targetPlayer = target as GamePlayer;
			if (targetPlayer != null)
			{
				if (targetPlayer.IsStealthed)
					targetPlayer.Stealth(false);
			}

			foreach (GamePlayer p in target.GetPlayersInRadius(false, WorldMgr.VISIBILITY_DISTANCE))
			{
				p.Out.SendSpellEffectAnimation(owner, target, 7026, 0, false, 1);
				p.Out.SendCombatAnimation(owner, target, 0, 0, 0, 0, 0x14, target.HealthPercent);
			}

			//target.TakeDamage(owner, eDamageType.Energy, damage, 0);
			AttackData ad = new AttackData();
			ad.AttackResult = GameLiving.eAttackResult.HitUnstyled;
			ad.Attacker = owner;
			ad.Target = target;
			ad.DamageType = eDamageType.Energy;
			ad.Damage = damage;
			target.OnAttackedByEnemy(ad);
			owner.DealDamage(ad);
		}