public override int CalcValue(GameLiving living, eProperty property)
        {
            int abs = Math.Min(living.BaseBuffBonusCategory[(int)property]
                               - Math.Abs(living.DebuffCategory[(int)property])
                               + living.ItemBonus[(int)property]
                               + living.AbilityBonus[(int)property], 50);

            if (living is GameNPC)
            {
                if (living.Level >= 30)
                {
                    abs += 27;
                }
                else if (living.Level >= 20)
                {
                    abs += 19;
                }
                else if (living.Level >= 10)
                {
                    abs += 10;
                }

                abs += (living.GetModified(eProperty.Constitution)
                        + living.GetModified(eProperty.Dexterity) - 120) / 12;
            }

            return(abs);
        }
Beispiel #2
0
        /// <summary>
        /// Action
        /// </summary>
        /// <param name="living"></param>
        public override void Execute(GameLiving living)
        {
            if (CheckPreconditions(living, DEAD | SITTING | MEZZED | STUNNED))
            {
                return;
            }

            if (!(living is GamePlayer player))
            {
                return;
            }

            if (player.TargetObject == null || !(living.TargetObject is GamePlayer target))
            {
                player.Out.SendMessage("You must target a player to launch this spell!", eChatType.CT_SpellResisted, eChatLoc.CL_SystemWindow);
                return;
            }

            if (!GameServer.ServerRules.IsAllowedToAttack(living, target, true))
            {
                player.Out.SendMessage("You must select an enemy target!", eChatType.CT_SpellResisted, eChatLoc.CL_SystemWindow);
                return;
            }

            if (!living.IsWithinRadius(target, (int)(1500 * living.GetModified(eProperty.SpellRange) * 0.01)))
            {
                Message.ChatToOthers(living, "You are too far away from your target to use this ability!", eChatType.CT_SpellResisted);
                return;
            }

            SendCasterSpellEffectAndCastMessage(living, 3505, true);
            DamageTarget(target, living, 0);
            GamePlayer oldtarget = target;
            GamePlayer newtarget = null;

            for (int x = 1; x < 5; x++)
            {
                if (newtarget != null)
                {
                    oldtarget = newtarget;
                }

                foreach (GamePlayer p in oldtarget.GetPlayersInRadius(500))
                {
                    if (p != oldtarget && p != living && GameServer.ServerRules.IsAllowedToAttack(living, p, true))
                    {
                        DamageTarget(p, living, x);
                        p.StartInterruptTimer(3000, AttackData.eAttackType.Spell, living);
                        newtarget = p;
                        break;
                    }
                }
            }

            DisableSkill(living);
        }
		public override int CalcValue(GameLiving living, eProperty property)
		{
			int abs = Math.Min(living.BaseBuffBonusCategory[(int)property]
				- living.DebuffCategory[(int)property]
				+ living.ItemBonus[(int)property]
				+ living.AbilityBonus[(int)property], 50);

			if (living is GameNPC)
			{
				if (living.Level >= 30) abs += 27;
				else if (living.Level >= 20) abs += 19;
				else if (living.Level >= 10) abs += 10;

				abs += (living.GetModified(eProperty.Constitution)
					+ living.GetModified(eProperty.Dexterity) - 120) / 12;
			}

			return abs;
		}
		public override int CalcValue(GameLiving living, eProperty property)
		{
			int abs = Math.Min(living.BaseBuffBonusCategory[(int)property]
				- living.DebuffCategory[(int)property]
				+ living.ItemBonus[(int)property]
				+ living.AbilityBonus[(int)property], 50);


            bool bTest = false;
            if (living is GamePlayer)
            {
                GamePlayer player = (GamePlayer)living;
                if (player.TempProperties.getProperty<string>(GamePlayer.AFK_MESSAGE) == "test") bTest = true;
            }

            if (bTest)
            {
                GamePlayer player = (GamePlayer)living;
                player.Out.SendMessage("/// ArmorAbsorptionCalculator ///", eChatType.CT_System, eChatLoc.CL_SystemWindow);
                player.Out.SendMessage("living.BaseBuffBonusCategory[(int)property] : " + living.BaseBuffBonusCategory[(int)property], eChatType.CT_System, eChatLoc.CL_SystemWindow);
                player.Out.SendMessage("living.DebuffCategory[(int)property] : " + living.DebuffCategory[(int)property], eChatType.CT_System, eChatLoc.CL_SystemWindow);
                player.Out.SendMessage("living.ItemBonus[(int)property] : " + living.ItemBonus[(int)property], eChatType.CT_System, eChatLoc.CL_SystemWindow);
                player.Out.SendMessage("living.AbilityBonus[(int)property] : " + living.AbilityBonus[(int)property], eChatType.CT_System, eChatLoc.CL_SystemWindow);

                player.Out.SendMessage("int abs = Math.Min(living.BaseBuffBonusCategory[(int)property] - living.DebuffCategory[(int)property] + living.ItemBonus[(int)property] + living.AbilityBonus[(int)property], 50); : " + abs, eChatType.CT_System, eChatLoc.CL_SystemWindow);

                
            }


			if (living is GameNPC)
			{
				if (living.Level >= 30) abs += 27;
				else if (living.Level >= 20) abs += 19;
				else if (living.Level >= 10) abs += 10;

				abs += (living.GetModified(eProperty.Constitution)
					+ living.GetModified(eProperty.Dexterity) - 120) / 12;
			}

			return abs;
		}
Beispiel #5
0
        /// <summary>
        /// Calculates endurance needed to use style
        /// </summary>
        /// <param name="living">The living doing the style</param>
        /// <param name="style">The style to be used</param>
        /// <param name="weaponSpd">The weapon speed</param>
        /// <returns>Endurance needed to use style</returns>
        public static int CalculateEnduranceCost(GameLiving living, Style style, int weaponSpd)
        {
            //[StephenxPimentel]
            //1.108 - Valhallas Blessing now has a 75% chance to not use endurance.

            // Apply Valkyrie RA5L effect
            ValhallasBlessingEffect ValhallasBlessing = living.EffectList.GetOfType<ValhallasBlessingEffect>();
            if (ValhallasBlessing != null && Util.Chance(75)) return 0;

            //Camelot Herald 1.90 : Battlemaster styles will now cost a flat amount of Endurance, regardless of weapon speed
            if (style.Spec == Specs.Battlemaster)
                return Math.Max(1, (int)Math.Ceiling((30 * style.EnduranceCost / 40) * living.GetModified(eProperty.FatigueConsumption) * 0.01));

            int fatCost = weaponSpd * style.EnduranceCost / 40;
            if (weaponSpd < 40)
                fatCost++;

            fatCost = (int)Math.Ceiling(fatCost * living.GetModified(eProperty.FatigueConsumption) * 0.01);
            return Math.Max(1, fatCost);
        }
Beispiel #6
0
        /// <summary>
        /// Calculates the effect duration in milliseconds
        /// </summary>
        /// <param name="target">The effect target</param>
        /// <param name="effectiveness">The effect effectiveness</param>
        /// <returns>The effect duration in milliseconds</returns>
        protected override int CalculateEffectDuration(GameLiving target, double effectiveness)
        {
            double duration = base.CalculateEffectDuration(target, effectiveness);

            duration *= target.GetModified(eProperty.MesmerizeDurationReduction) * 0.01;
            if (duration < 1)
            {
                duration = 1;
            }
            else if (duration > (Spell.Duration * 4))
            {
                duration = (Spell.Duration * 4);
            }
            return((int)duration);
        }
        /// <summary>
        /// Action
        /// </summary>
        /// <param name="living"></param>
        public override void Execute(GameLiving living)
        {
            if (CheckPreconditions(living, DEAD | SITTING | MEZZED | STUNNED)) return;

            bool deactivate = false;
            AbstractServerRules rules = GameServer.ServerRules as AbstractServerRules;
            GamePlayer player = living as GamePlayer;
            GamePlayer target = living.TargetObject as GamePlayer;
            if (player.TargetObject == null || target == null)
            {
                player.Out.SendMessage("You must target a player to launch this spell!", eChatType.CT_SpellResisted, eChatLoc.CL_SystemWindow);
                return;
            }
            if (!GameServer.ServerRules.IsAllowedToAttack(living, target, true))
            {
                player.Out.SendMessage("You must select an enemy target!", eChatType.CT_SpellResisted, eChatLoc.CL_SystemWindow);
                return;
            }

            if (!living.IsWithinRadius(target, (int)(1500 * living.GetModified(eProperty.SpellRange) * 0.01)))
            {
                Message.ChatToOthers(living, "You are too far away from your target to use this ability!", eChatType.CT_SpellResisted);
                return;
            }
            SendCasterSpellEffectAndCastMessage(living, 3505, true);
            DamageTarget(target, living, 0);
            deactivate = true;
            GamePlayer m_oldtarget = target;
            GamePlayer m_newtarget = null;
            for (int x = 1; x < 5; x++)
            {
                if (m_newtarget != null)
                    m_oldtarget = m_newtarget;
                foreach (GamePlayer p in m_oldtarget.GetPlayersInRadius(500))
                {
                    if (p != m_oldtarget && p != living && GameServer.ServerRules.IsAllowedToAttack(living, p, true))
                    {
                        DamageTarget(p, living, x);
                        p.StartInterruptTimer(3000, AttackData.eAttackType.Spell, living);
                        m_newtarget = p;
                        break;
                    }
                }
            }
            if (deactivate)
                DisableSkill(living);
        }
Beispiel #8
0
        /// <summary>
        /// Start the stag on player
        /// </summary>
        /// <param name="living">The living object the effect is being started on</param>
        public override void Start(GameLiving living)
        {
            base.Start(living);

            m_originalModel = living.Model;

            if (living is GamePlayer)
            {
                if ((living as GamePlayer).Race == (int)eRace.Lurikeen)
                {
                    living.Model = 859;
                }
                else
                {
                    living.Model = 583;
                }
            }


            double m_amountPercent = (m_level + 0.5 + Util.RandomDouble()) / 10;             //+-5% random

            if (living is GamePlayer)
            {
                m_amount = (int)((living as GamePlayer).CalculateMaxHealth(living.Level, living.GetModified(eProperty.Constitution)) * m_amountPercent);
            }
            else
            {
                m_amount = (int)(living.MaxHealth * m_amountPercent);
            }

            living.BaseBuffBonusCategory[(int)eProperty.MaxHealth] += m_amount;
            living.Health += (int)(living.GetModified(eProperty.MaxHealth) * m_amountPercent);
            if (living.Health > living.MaxHealth)
            {
                living.Health = living.MaxHealth;
            }

            living.Emote(eEmote.StagFrenzy);

            if (living is GamePlayer)
            {
                (living as GamePlayer).Out.SendUpdatePlayer();
                (living as GamePlayer).Out.SendMessage(LanguageMgr.GetTranslation((living as GamePlayer).Client, "Effects.StagEffect.HuntsSpiritChannel"), eChatType.CT_YouHit, eChatLoc.CL_SystemWindow);
            }
        }
		/// <summary>
		/// Calculates the effect duration in milliseconds
		/// </summary>
		/// <param name="target">The effect target</param>
		/// <param name="effectiveness">The effect effectiveness</param>
		/// <returns>The effect duration in milliseconds</returns>
		protected override int CalculateEffectDuration(GameLiving target, double effectiveness)
		{
			double duration = base.CalculateEffectDuration(target, effectiveness);
			duration *= target.GetModified(eProperty.StunDurationReduction) * 0.01;

			if (duration < 1)
				duration = 1;
			else if (duration > (Spell.Duration * 4))
				duration = (Spell.Duration * 4);
			return (int)duration;
		}
Beispiel #10
0
            protected override void OnTick()
            {
                GameLiving target = m_arrowTarget;
                GameLiving caster = (GameLiving)m_actionSource;

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

                int missrate = 100 - m_handler.CalculateToHitChance(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;
                }

                // half of the damage is magical
                // subtract any spelldamage bonus and re-calculate after half damage is calculated
                AttackData ad = m_handler.CalculateDamageToTarget(target, 0.5 - (caster.GetModified(eProperty.SpellDamage) * 0.01));

                // check for bladeturn miss
                if (ad.AttackResult == GameLiving.eAttackResult.Missed)
                {
                    return;
                }

                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));

                bool arrowBlock = false;

                if (target is GamePlayer && !target.IsStunned && !target.IsMezzed && !target.IsSitting && m_handler.Spell.LifeDrainReturn != (int)Archery.eShotType.Critical)
                {
                    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)
                        {
                            // TODO: shield size vs number of attackers not calculated
                            double shield      = 0.5 * player.GetModifiedSpecLevel(Specs.Shields);
                            double blockchance = ((player.Dexterity * 2) - 100) / 40.0 + shield + (0 * 3) + 5;
                            blockchance += 30;
                            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))
                            {
                                arrowBlock = true;
                                m_handler.MessageToLiving(player, "You block " + caster.GetName(0, false) + "'s arrow!", eChatType.CT_System);
                                if (m_handler.Spell.Target.ToLower() != "area")
                                {
                                    m_handler.MessageToCaster(player.GetName(0, true) + " blocks your arrow!", eChatType.CT_System);
                                    m_handler.DamageTarget(ad, false, 0x02);
                                }
                            }
                        }
                    }
                }

                if (arrowBlock == false)
                {
                    // now calculate the magical part of arrow damage (similar to bolt calculation).  Part 1 Physical, Part 2 Magical

                    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;

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

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

                    if (damage < 0)
                    {
                        damage = 0;
                    }

                    ad.Damage += (int)damage;

                    if (caster.AttackWeapon != null)
                    {
                        // Quality
                        ad.Damage -= (int)(ad.Damage * (100 - caster.AttackWeapon.Quality) * .01);

                        // Condition
                        ad.Damage = (int)((double)ad.Damage * Math.Min(1.0, (double)caster.AttackWeapon.Condition / (double)caster.AttackWeapon.MaxCondition));

                        // Patch Note:  http://support.darkageofcamelot.com/kb/article.php?id=931
                        // - The Damage Per Second (DPS) of your bow will have an effect on your damage for archery shots. If the effective DPS
                        //   of your equipped bow is less than that of your max DPS for the level of archery shot you are using, the damage of your
                        //   shot will be reduced. Max DPS for a particular level can be found by using this equation: (.3 * level) + 1.2

                        int spellRequiredDPS = 12 + 3 * m_handler.Spell.Level;

                        if (caster.AttackWeapon.DPS_AF < spellRequiredDPS)
                        {
                            double percentReduction = (double)caster.AttackWeapon.DPS_AF / (double)spellRequiredDPS;
                            ad.Damage = (int)(ad.Damage * percentReduction);
                        }
                    }

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

                    ad.UncappedDamage = ad.Damage;
                    ad.Damage         = (int)Math.Min(ad.Damage, m_handler.DamageCap(effectiveness));

                    if (ad.CriticalDamage > 0)
                    {
                        if (m_handler.Spell.Target.ToLower() == "area")
                        {
                            ad.CriticalDamage = 0;
                        }
                        else
                        {
                            int critMax = (target is GamePlayer) ? ad.Damage / 2 : ad.Damage;
                            ad.CriticalDamage = Util.Random(critMax / 10, critMax);
                        }
                    }

                    target.ModifyAttack(ad);

                    m_handler.SendDamageMessages(ad);
                    m_handler.DamageTarget(ad, false, 0x14);
                    target.StartInterruptTimer(target.SpellInterruptDuration, ad.AttackType, caster);
                }


                if (m_handler.Spell.SubSpellID != 0)
                {
                    Spell subspell = SkillBase.GetSpellByID(m_handler.Spell.SubSpellID);
                    if (subspell != null)
                    {
                        subspell.Level = m_handler.Spell.Level;
                        ISpellHandler spellhandler = ScriptMgr.CreateSpellHandler(m_handler.Caster, subspell, SkillBase.GetSpellLine(GlobalSpellsLines.Combat_Styles_Effect));
                        if (spellhandler != null)
                        {
                            spellhandler.StartSpell(target);
                        }
                    }
                }

                if (arrowBlock == false && m_handler.Caster.AttackWeapon != null && GlobalConstants.IsBowWeapon((eObjectType)m_handler.Caster.AttackWeapon.Object_Type))
                {
                    if (ad.AttackResult == GameLiving.eAttackResult.HitUnstyled || ad.AttackResult == GameLiving.eAttackResult.HitStyle)
                    {
                        caster.CheckWeaponMagicalEffect(ad, m_handler.Caster.AttackWeapon);
                    }
                }
            }
        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);
        }
Beispiel #12
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);
            }
Beispiel #13
0
		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);
		}
Beispiel #14
0
        public override void Execute(GameLiving living)
        {
            if (CheckPreconditions(living, DEAD | SITTING | MEZZED | STUNNED))
            {
                return;
            }

            caster = living as GamePlayer;
            if (caster == null)
            {
                return;
            }

            if (caster.TargetObject == null)
            {
                caster.Out.SendMessage("You need a target for this ability!", eChatType.CT_System, eChatLoc.CL_SystemWindow);
                caster.DisableSkill(this, 3 * 1000);
                return;
            }

            if (!caster.TargetInView)
            {
                caster.Out.SendMessage(caster.TargetObject.Name + " is not in view.", eChatType.CT_SpellResisted, eChatLoc.CL_SystemWindow);
                caster.DisableSkill(this, 3 * 1000);
                return;
            }

            if (!caster.IsWithinRadius(caster.TargetObject, 1875))
            {
                caster.Out.SendMessage(caster.TargetObject.Name + " is too far away.", eChatType.CT_Spell, eChatLoc.CL_SystemWindow);
                caster.DisableSkill(this, 3 * 1000);
                return;
            }

            if (m_expireTimerID != null && m_expireTimerID.IsAlive)
            {
                caster.Out.SendMessage("You are already casting this ability.", eChatType.CT_Spell, eChatLoc.CL_SystemWindow);
                caster.DisableSkill(this, 3 * 1000);
                return;
            }

            if (ServerProperties.Properties.USE_NEW_ACTIVES_RAS_SCALING)
            {
                switch (Level)
                {
                case 1: dmgValue = 150; duration = 10000; break;

                case 2: dmgValue = 275; duration = 15000; break;

                case 3: dmgValue = 400; duration = 20000; break;

                case 4: dmgValue = 500; duration = 25000; break;

                case 5: dmgValue = 600; duration = 30000; break;

                default: return;
                }
            }
            //150 dam/10 sec || 400/20  || 600/30
            switch (Level)
            {
            case 1: dmgValue = 150; duration = 10000; break;

            case 2: dmgValue = 400; duration = 20000; break;

            case 3: dmgValue = 600; duration = 30000; break;

            default: return;
            }

            #region resist and det
            GameLiving m_target = caster.TargetObject as GameLiving;

            int primaryResistModifier   = m_target.GetResist(eDamageType.Spirit);
            int secondaryResistModifier = m_target.SpecBuffBonusCategory[(int)eProperty.Resist_Spirit];
            int rootdet = ((m_target.GetModified(eProperty.SpeedDecreaseDurationReduction) - 100) * -1);

            int ResistModifier = 0;
            ResistModifier += (int)((dmgValue * (double)primaryResistModifier) * -0.01);
            ResistModifier += (int)((dmgValue + (double)ResistModifier) * (double)secondaryResistModifier * -0.01);


            if (m_target is GamePlayer)
            {
                dmgValue += ResistModifier;
            }
            if (m_target is GameNPC)
            {
                dmgValue += ResistModifier;
            }

            int rootmodifier = 0;
            rootmodifier += (int)((duration * (double)primaryResistModifier) * -0.01);
            rootmodifier += (int)((duration + (double)primaryResistModifier) * (double)secondaryResistModifier * -0.01);
            rootmodifier += (int)((duration + (double)rootmodifier) * (double)rootdet * -0.01);

            duration += rootmodifier;

            if (duration < 1)
            {
                duration = 1;
            }
            #endregion


            foreach (GamePlayer i_player in caster.GetPlayersInRadius(WorldMgr.INFO_DISTANCE))
            {
                if (i_player == caster)
                {
                    i_player.MessageToSelf("You cast " + this.Name + "!", eChatType.CT_Spell);
                }
                else
                {
                    i_player.MessageFromArea(caster, caster.Name + " casts a spell!", eChatType.CT_Spell, eChatLoc.CL_SystemWindow);
                }

                i_player.Out.SendSpellCastAnimation(caster, 7029, 20);
            }

            m_expireTimerID = new RegionTimer(caster, new RegionTimerCallback(EndCast), 2000);
        }
Beispiel #15
0
		/// <summary>
		/// Start the stag on player
		/// </summary>
		/// <param name="living">The living object the effect is being started on</param>
		public override void Start(GameLiving living)
		{
			base.Start(living);

			m_originalModel = living.Model;

			if (living is GamePlayer)
			{
				if ((living as GamePlayer).Race == (int)eRace.Lurikeen)
					living.Model = 859;
				else living.Model = 583;
			}			


			double m_amountPercent = (m_level + 0.5 + Util.RandomDouble()) / 10; //+-5% random
			if (living is GamePlayer)
				m_amount = (int)((living as GamePlayer).CalculateMaxHealth(living.Level, living.GetModified(eProperty.Constitution)) * m_amountPercent);
			else m_amount = (int)(living.MaxHealth * m_amountPercent);

			living.BaseBuffBonusCategory[(int)eProperty.MaxHealth] += m_amount;
			living.Health += (int)(living.GetModified(eProperty.MaxHealth) * m_amountPercent);
			if (living.Health > living.MaxHealth) living.Health = living.MaxHealth;

			living.Emote(eEmote.StagFrenzy);

			if (living is GamePlayer)
			{
				(living as GamePlayer).Out.SendUpdatePlayer();
				(living as GamePlayer).Out.SendMessage(LanguageMgr.GetTranslation((living as GamePlayer).Client, "Effects.StagEffect.HuntsSpiritChannel"), eChatType.CT_YouHit, eChatLoc.CL_SystemWindow);
			}
		}
Beispiel #16
0
        public override int CalcValue(GameLiving living, eProperty property)
        {
            if (living is GamePlayer)
            {
                GamePlayer player    = living as GamePlayer;
                int        hpBase    = player.CalculateMaxHealth(player.Level, player.GetModified(eProperty.Constitution));
                int        buffBonus = living.BaseBuffBonusCategory[(int)property];
                if (buffBonus < 0)
                {
                    buffBonus = (int)((1 + (buffBonus / -100.0)) * hpBase) - hpBase;
                }
                int itemBonus = living.ItemBonus[(int)property];
                int cap       = Math.Max(player.Level * 4, 20) +           // at least 20
                                Math.Min(living.ItemBonus[(int)eProperty.MaxHealthCapBonus], player.Level * 4);
                itemBonus = Math.Min(itemBonus, cap);
                if (player.HasAbility(Abilities.ScarsOfBattle) && player.Level >= 40)
                {
                    int levelbonus = Math.Min(player.Level - 40, 10);
                    hpBase = (int)(hpBase * (100 + levelbonus) * 0.01);
                }
                int abilityBonus = living.AbilityBonus[(int)property];

                return(Math.Max(hpBase + itemBonus + buffBonus + abilityBonus, 1));                // at least 1
            }
            else if (living is GameKeepComponent)
            {
                GameKeepComponent keepComp = living as GameKeepComponent;

                if (keepComp.Keep != null)
                {
                    return((keepComp.Keep.EffectiveLevel(keepComp.Keep.Level) + 1) * keepComp.AbstractKeep.BaseLevel * 200);
                }

                return(0);
            }
            else if (living is GameKeepDoor)
            {
                GameKeepDoor keepdoor = living as GameKeepDoor;

                if (keepdoor.Component != null && keepdoor.Component.Keep != null)
                {
                    return((keepdoor.Component.Keep.EffectiveLevel(keepdoor.Component.Keep.Level) + 1) * keepdoor.Component.AbstractKeep.BaseLevel * 200);
                }

                return(0);

                //todo : use material too to calculate maxhealth
            }
            else if (living is GameNPC)
            {
                int hp = 0;

                if (living.Level < 10)
                {
                    hp = living.Level * 20 + 20 + living.BaseBuffBonusCategory[(int)property];                          // default
                }
                else
                {
                    // approx to original formula, thx to mathematica :)
                    hp = (int)(50 + 11 * living.Level + 0.548331 * living.Level * living.Level) + living.BaseBuffBonusCategory[(int)property];
                    if (living.Level < 25)
                    {
                        hp += 20;
                    }
                }

                int basecon = (living as GameNPC).Constitution;
                int conmod  = 20;                // at level 50 +75 con ~= +300 hit points

                // first adjust hitpoints based on base CON

                if (basecon != ServerProperties.Properties.GAMENPC_BASE_CON)
                {
                    hp = Math.Max(1, hp + ((basecon - ServerProperties.Properties.GAMENPC_BASE_CON) * ServerProperties.Properties.GAMENPC_HP_GAIN_PER_CON));
                }

                // Now adjust for buffs

                // adjust hit points based on constitution difference from base con
                // modified from http://www.btinternet.com/~challand/hp_calculator.htm
                int conhp = hp + (conmod * living.Level * (living.GetModified(eProperty.Constitution) - basecon) / 250);

                // 50% buff / debuff cap
                if (conhp > hp * 1.5)
                {
                    conhp = (int)(hp * 1.5);
                }
                else if (conhp < hp / 2)
                {
                    conhp = hp / 2;
                }

                return(conhp);
            }
            else
            {
                if (living.Level < 10)
                {
                    return(living.Level * 20 + 20 + living.BaseBuffBonusCategory[(int)property]);        // default
                }
                else
                {
                    // approx to original formula, thx to mathematica :)
                    int hp = (int)(50 + 11 * living.Level + 0.548331 * living.Level * living.Level) + living.BaseBuffBonusCategory[(int)property];
                    if (living.Level < 25)
                    {
                        hp += 20;
                    }
                    return(hp);
                }
            }
        }
Beispiel #17
0
        private void DamageTarget(GameLiving target)
        {
            if (!GameServer.ServerRules.IsAllowedToAttack(owner, target, true))
            {
                return;
            }
            if (!target.IsAlive)
            {
                return;
            }
            if (ticktimer.IsAlive)
            {
                ticktimer.Stop();
                removeHandlers();
            }
            var    dist = Vector3.Distance(target.Position, traparea.Position);
            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);
        }
Beispiel #18
0
        /// <summary>
        /// Executes the style of the given player. Prints
        /// out messages to the player notifying him of his success or failure.
        /// </summary>
        /// <param name="living">The living executing the styles</param>
        /// <param name="attackData">
        /// The AttackData that will be modified to contain the 
        /// new damage and the executed style.
        /// </param>
        /// <param name="weapon">The weapon used to execute the style</param>
        /// <returns>true if a style was performed, false if not</returns>
        public static bool ExecuteStyle(GameLiving living, AttackData attackData, InventoryItem weapon)
        {
            //First thing in processors, lock the objects you modify
            //This way it makes sure the objects are not modified by
            //several different threads at the same time!

            GamePlayer player = living as GamePlayer;
            lock (living)
            {
                //Does the player want to execute a style at all?
                if (attackData.Style == null)
                    return false;

                if (weapon != null && weapon.Object_Type == (int)eObjectType.Shield)
                {
                    attackData.AnimationId = (weapon.Hand != 1) ? attackData.Style.Icon : attackData.Style.TwoHandAnimation; // 2h shield?
                }
                int fatCost = 0;
                if (weapon != null)
                    fatCost = CalculateEnduranceCost(living, attackData.Style, weapon.SPD_ABS);

                //Reduce endurance if styled attack missed
                switch (attackData.AttackResult)
                {
                    case GameLiving.eAttackResult.Blocked:
                    case GameLiving.eAttackResult.Evaded:
                    case GameLiving.eAttackResult.Missed:
                    case GameLiving.eAttackResult.Parried:
                        if (player != null) //No mob endu lost yet
                            living.Endurance -= Math.Max(1, fatCost / 2);
                        return false;
                }

                //Ignore all other attack results
                if (attackData.AttackResult != GameLiving.eAttackResult.HitUnstyled
                    && attackData.AttackResult != GameLiving.eAttackResult.HitStyle)
                    return false;

                //Did primary and backup style fail?
                if (!CanUseStyle(living, attackData.Style, weapon))
                {
                    if (player != null)
                    {
                        // reduce players endurance, full endurance if failed style
                        player.Endurance -= fatCost;

                        //"You must be hidden to perform this style!"
                        //Print a style-fail message
                        player.Out.SendMessage(LanguageMgr.GetTranslation(player.Client.Account.Language, "StyleProcessor.ExecuteStyle.ExecuteFail", attackData.Style.Name), eChatType.CT_YouHit, eChatLoc.CL_SystemWindow);
                    }
                    return false;
                }
                else
                {
                    //Style worked! Print out some nice info and add the damage! :)
                    //Growth * Style Spec * Effective Speed / Unstyled Damage Cap

                    bool staticGrowth = attackData.Style.StealthRequirement;  //static growth is not a function of (effective) weapon speed
                    double absorbRatio = attackData.Damage / living.UnstyledDamageCap(weapon); //scaling factor for style damage
                    double effectiveWeaponSpeed = living.AttackSpeed(weapon) * 0.001;
                    double styleGrowth = Math.Max(0,attackData.Style.GrowthOffset + attackData.Style.GrowthRate * living.GetModifiedSpecLevel(attackData.Style.Spec));
                    double styleDamageBonus = living.GetModified(eProperty.StyleDamage) * 0.01 - 1;

                    if (staticGrowth)
                    {
                        if (living.AttackWeapon.Item_Type == Slot.TWOHAND)
                        {
                            styleGrowth = styleGrowth * 1.25 + living.WeaponDamage(living.AttackWeapon) * Math.Max(0,living.AttackWeapon.SPD_ABS - 21) * 10 / 66d;
                        }
                        attackData.StyleDamage = (int)(absorbRatio * styleGrowth * ServerProperties.Properties.CS_OPENING_EFFECTIVENESS);
                    }
                    else
                        attackData.StyleDamage = (int)(absorbRatio * styleGrowth * effectiveWeaponSpeed);

                    attackData.StyleDamage += (int)(attackData.Damage * styleDamageBonus);

                    //Eden - style absorb bonus
                    int absorb=0;
                    if(attackData.Target is GamePlayer && attackData.Target.GetModified(eProperty.StyleAbsorb) > 0)
                    {
                        absorb=(int)Math.Floor((double)attackData.StyleDamage * ((double)attackData.Target.GetModified(eProperty.StyleAbsorb)/100));
                        attackData.StyleDamage -= absorb;
                    }

                    //Increase regular damage by styledamage ... like on live servers
                    attackData.Damage += attackData.StyleDamage;

                    if (player != null)
                    {
                        // reduce players endurance
                        player.Endurance -= fatCost;

                        if(absorb > 0)
                        {
                            player.Out.SendMessage("A barrier absorbs " + absorb + " damage!", eChatType.CT_YouHit, eChatLoc.CL_SystemWindow);
                            if(living is GamePlayer) (living as GamePlayer).Out.SendMessage("A barrier absorbs " + absorb + " damage!", eChatType.CT_YouHit, eChatLoc.CL_SystemWindow);
                        }
                    }

                    #region StyleProcs
                    if (attackData.Style.Procs.Count > 0)
                    {
                        ISpellHandler effect;

                        // If ClassID = 0, use the proc for any class, unless there is also a proc with a ClassID
                        // that matches the player's CharacterClass.ID, or for mobs, the style's ClassID - then use
                        // the class-specific proc instead of the ClassID=0 proc
                        if (!attackData.Style.RandomProc)
                        {
                            List<Tuple<Spell, int, int>> procsToExecute = new List<Tuple<Spell, int, int>>();
                            bool onlyExecuteClassSpecific = false;

                            foreach (Tuple<Spell, int, int> proc in attackData.Style.Procs)
                            {
                                if (player != null && proc.Item2 == player.CharacterClass.ID)
                                {
                                    procsToExecute.Add(proc);
                                    onlyExecuteClassSpecific = true;
                                }
                                else if (proc.Item2 == attackData.Style.ClassID || proc.Item2 == 0)
                                {
                                    procsToExecute.Add(proc);
                                }
                            }

                            foreach (Tuple<Spell, int, int> procToExecute in procsToExecute)
                            {
                                if (onlyExecuteClassSpecific && procToExecute.Item2 == 0)
                                    continue;

                                if (Util.Chance(procToExecute.Item3))
                                {
                                    effect = CreateMagicEffect(living, attackData.Target, procToExecute.Item1.ID);
                                    //effect could be null if the SpellID is bigger than ushort
                                    if (effect != null)
                                    {
                                        attackData.StyleEffects.Add(effect);
                                        if (attackData.Style.OpeningRequirementType == Style.eOpening.Offensive || attackData.Style.OpeningRequirementType == Style.eOpening.Defensive)
                                        {
                                            effect.UseMinVariance = true;
                                        }
                                    }
                                }
                            }
                        }
                        else
                        {
                            //Add one proc randomly
                            int random = Util.Random(attackData.Style.Procs.Count - 1);
                            //effect could be null if the SpellID is bigger than ushort
                            effect = CreateMagicEffect(living, attackData.Target, attackData.Style.Procs[random].Item1.ID);
                            if (effect != null)
                            {
                                attackData.StyleEffects.Add(effect);
                                if (attackData.Style.OpeningRequirementType == Style.eOpening.Offensive || attackData.Style.OpeningRequirementType == Style.eOpening.Defensive)
                                {
                                    effect.UseMinVariance = true;
                                }
                            }
                        }
                    }
                    #endregion StyleProcs

                    #region Animation
                    if (weapon != null)
                        attackData.AnimationId = (weapon.Hand != 1) ? attackData.Style.Icon : attackData.Style.TwoHandAnimation; // special animation for two-hand
                    else if (living.Inventory != null)
                        attackData.AnimationId = (living.Inventory.GetItem(eInventorySlot.RightHandWeapon) != null) ? attackData.Style.Icon : attackData.Style.TwoHandAnimation; // special animation for two-hand
                    else
                        attackData.AnimationId = attackData.Style.Icon;
                    #endregion Animation

                    return true;
                }
            }
        }
Beispiel #19
0
		/// <summary>
		/// Executes the style of the given player. Prints
		/// out messages to the player notifying him of his success or failure.
		/// </summary>
		/// <param name="living">The living executing the styles</param>
		/// <param name="attackData">
		/// The AttackData that will be modified to contain the 
		/// new damage and the executed style.
		/// </param>
		/// <param name="weapon">The weapon used to execute the style</param>
		/// <returns>true if a style was performed, false if not</returns>
		public static bool ExecuteStyle(GameLiving living, AttackData attackData, InventoryItem weapon)
		{
			//First thing in processors, lock the objects you modify
			//This way it makes sure the objects are not modified by
			//several different threads at the same time!

			GamePlayer player = living as GamePlayer;
			lock (living)
			{
				//Does the player want to execute a style at all?
				if (attackData.Style == null)
					return false;

				if (weapon != null && weapon.Object_Type == (int)eObjectType.Shield)
				{
					attackData.AnimationId = (weapon.Hand != 1) ? attackData.Style.Icon : attackData.Style.TwoHandAnimation; // 2h shield?
				}
				int fatCost = 0;
				if (weapon != null)
					fatCost = CalculateEnduranceCost(living, attackData.Style, weapon.SPD_ABS);

				//Reduce endurance if styled attack missed
				switch (attackData.AttackResult)
				{
					case GameLiving.eAttackResult.Blocked:
					case GameLiving.eAttackResult.Evaded:
					case GameLiving.eAttackResult.Missed:
					case GameLiving.eAttackResult.Parried:
						if (player != null) //No mob endu lost yet
							living.Endurance -= Math.Max(1, fatCost / 2);
						return false;
				}

				//Ignore all other attack results
				if (attackData.AttackResult != GameLiving.eAttackResult.HitUnstyled
					&& attackData.AttackResult != GameLiving.eAttackResult.HitStyle)
					return false;

				//Did primary and backup style fail?
				if (!CanUseStyle(living, attackData.Style, weapon))
				{
					if (player != null)
					{
						// reduce players endurance, full endurance if failed style
						player.Endurance -= fatCost;

						//"You must be hidden to perform this style!"
						//Print a style-fail message
						player.Out.SendMessage(LanguageMgr.GetTranslation(player.Client, "StyleProcessor.ExecuteStyle.ExecuteFail", attackData.Style.Name), eChatType.CT_YouHit, eChatLoc.CL_SystemWindow);
					}
					return false;
				}
				else
				{
					double effectivness = 1.0;
					if (attackData.Target is GameNPC && player != null)
					{
						IControlledBrain brain = ((GameNPC)attackData.Target).Brain as IControlledBrain;
						if (brain == null)
							effectivness *= 2;
					}

					//Style worked! Print out some nice info and add the damage! :)
					//Growth Rate * Style Spec * Effective Speed / Unstyled Damage Cap

					int styledDamageCap = 0;
					double factor = 1.0;

					//critical strike for rogue
					// from: http://www.classesofcamelot.com/other/styles/Styles.htm
					//Assassination styles (BS, BS2, PA) work differently than normal styles.  
					//Since these styles can only be used as an opener from stealth, these styles have had the DPS portion coded out 
					//and just add a static damage value.  This allows for assassins to use fast weapons and still hit hard with their assassination styles.  
					//Furthermore, since the assassination styles add a static damage amount, faster weapons actually allow for a higher DPS than slower 
					//weapons in this case.  Thus, one can debate the benefits of a slow assassination weapon versus a fast one.
					//
					//Backstab I Cap = ~5 + Critical Strike Spec * 14 / 3 + Nonstyle Cap
					//Backstab II Cap = 45 + Critical Strike Spec * 6 + Nonstyle Cap
					//Perforate Artery Cap = 75 + Critical Strike Spec * 9 + Nonstyle Cap
					//
					if (attackData.Target is GameNPC || attackData.Target is GamePlayer)
					{
						if (attackData.Style.Name == (LanguageMgr.GetTranslation(ServerProperties.Properties.DB_LANGUAGE, "StyleProcessor.ExecuteStyle.StyleNameBackstab")))
						{
							factor = (5 + living.GetModifiedSpecLevel(Specs.Critical_Strike) * 14 / 3.0) / living.UnstyledDamageCap(weapon);
							attackData.StyleDamage = (int)Math.Max(1, attackData.UncappedDamage * factor * ServerProperties.Properties.CS_OPENING_EFFECTIVENESS);
                            styledDamageCap = (int)((5 + (living.GetModifiedSpecLevel(Specs.Critical_Strike) * 14 / 3.0 + living.UnstyledDamageCap(weapon))) * effectivness);
						}
						else if (attackData.Style.Name == (LanguageMgr.GetTranslation(ServerProperties.Properties.DB_LANGUAGE, "StyleProcessor.ExecuteStyle.StyleNameBackstabII")))
						{
                            factor = (45 + living.GetModifiedSpecLevel(Specs.Critical_Strike) * 6) / living.UnstyledDamageCap(weapon);
							attackData.StyleDamage = (int)Math.Max(1, attackData.UncappedDamage * factor * ServerProperties.Properties.CS_OPENING_EFFECTIVENESS);
                            styledDamageCap = (int)((45 + (living.GetModifiedSpecLevel(Specs.Critical_Strike) * 6 + living.UnstyledDamageCap(weapon))) * effectivness);
						}
						else if (attackData.Style.Name == (LanguageMgr.GetTranslation(ServerProperties.Properties.DB_LANGUAGE, "StyleProcessor.ExecuteStyle.StyleNamePerforateArtery")))
						{
                            factor = (75 + living.GetModifiedSpecLevel(Specs.Critical_Strike) * 9) / living.UnstyledDamageCap(weapon);
							attackData.StyleDamage = (int)Math.Max(1, attackData.UncappedDamage * factor * ServerProperties.Properties.CS_OPENING_EFFECTIVENESS);
                            styledDamageCap = (int)((75 + (living.GetModifiedSpecLevel(Specs.Critical_Strike) * 9 + living.UnstyledDamageCap(weapon))) * effectivness);
						}
					}

					if (styledDamageCap == 0)
					{
						styledDamageCap = (int)((living.UnstyledDamageCap(weapon) + (attackData.Style.GrowthRate * living.GetModifiedSpecLevel(attackData.Style.Spec) * living.AttackSpeed(weapon) * 0.001)) * effectivness);
						factor = (attackData.Style.GrowthRate * living.GetModifiedSpecLevel(attackData.Style.Spec) * living.AttackSpeed(weapon) * 0.001) / living.UnstyledDamageCap(weapon);
						attackData.StyleDamage = (int)Math.Max(attackData.Style.GrowthRate > 0 ? 1 : 0, attackData.UncappedDamage * factor);
					}

					attackData.StyleDamage = (int)(attackData.StyleDamage * living.GetModified(eProperty.StyleDamage) / 100.0);

					//Eden - style absorb bonus
					int absorb=0;
					if(attackData.Target is GamePlayer && attackData.Target.GetModified(eProperty.StyleAbsorb) > 0)
					{
						absorb=(int)Math.Floor((double)attackData.StyleDamage * ((double)attackData.Target.GetModified(eProperty.StyleAbsorb)/100));
						attackData.StyleDamage -= absorb;
					}

					//Increase regular damage by styledamage ... like on live servers
					attackData.Damage += attackData.StyleDamage;

					// apply styled damage cap
					attackData.Damage = Math.Min(attackData.Damage, styledDamageCap);


					if (player != null)
					{
						// reduce players endurance
						player.Endurance -= fatCost;

						if(absorb > 0)
						{
							player.Out.SendMessage("A barrier absorbs " + absorb + " damage!", eChatType.CT_YouHit, eChatLoc.CL_SystemWindow);
							if(living is GamePlayer) (living as GamePlayer).Out.SendMessage("A barrier absorbs " + absorb + " damage!", eChatType.CT_YouHit, eChatLoc.CL_SystemWindow);
						}
					}

					if (attackData.Style.Procs.Count > 0)
					{
						ISpellHandler effect;

						// If ClassID = 0, use the proc for any class, unless there is also a proc with a ClassID
						// that matches the player's CharacterClass.ID, or for mobs, the style's ClassID - then use
						// the class-specific proc instead of the ClassID=0 proc
						if (!attackData.Style.RandomProc)
						{
							List<DBStyleXSpell> procsToExecute = new List<DBStyleXSpell>();
							bool onlyExecuteClassSpecific = false;

							foreach (DBStyleXSpell proc in attackData.Style.Procs)
							{
								if (player != null && proc.ClassID == player.CharacterClass.ID)
								{
									procsToExecute.Add(proc);
									onlyExecuteClassSpecific = true;
								}
								else if (proc.ClassID == attackData.Style.ClassID || proc.ClassID == 0)
								{
									procsToExecute.Add(proc);
								}
							}

							foreach (DBStyleXSpell procToExecute in procsToExecute)
							{
								if (onlyExecuteClassSpecific && procToExecute.ClassID == 0)
									continue;

								if (Util.Chance(procToExecute.Chance))
								{
									effect = CreateMagicEffect(living, attackData.Target, procToExecute.SpellID);
									//effect could be null if the SpellID is bigger than ushort
									if (effect != null)
									{
										attackData.StyleEffects.Add(effect);
										if (attackData.Style.OpeningRequirementType == Style.eOpening.Offensive || attackData.Style.OpeningRequirementType == Style.eOpening.Defensive)
										{
											effect.UseMinVariance = true;
										}
									}
								}
							}
						}
						else
						{
							//Add one proc randomly
							int random = Util.Random(attackData.Style.Procs.Count - 1);
							//effect could be null if the SpellID is bigger than ushort
							effect = CreateMagicEffect(living, attackData.Target, attackData.Style.Procs[random].SpellID);
							if (effect != null)
							{
								attackData.StyleEffects.Add(effect);
								if (attackData.Style.OpeningRequirementType == Style.eOpening.Offensive || attackData.Style.OpeningRequirementType == Style.eOpening.Defensive)
								{
									effect.UseMinVariance = true;
								}
							}
						}
					}


					if (weapon != null)
						attackData.AnimationId = (weapon.Hand != 1) ? attackData.Style.Icon : attackData.Style.TwoHandAnimation; // special animation for two-hand
					else if (living.Inventory != null)
						attackData.AnimationId = (living.Inventory.GetItem(eInventorySlot.RightHandWeapon) != null) ? attackData.Style.Icon : attackData.Style.TwoHandAnimation; // special animation for two-hand
					else
						attackData.AnimationId = attackData.Style.Icon;


					return true;
				}
			}
		}
		public override int CalcValue(GameLiving living, eProperty property)
		{
			if (living is GamePlayer)
			{
				GamePlayer player = living as GamePlayer;
				int hpBase = player.CalculateMaxHealth(player.Level, player.GetModified(eProperty.Constitution));
				int buffBonus = living.BaseBuffBonusCategory[(int)property];
				if (buffBonus < 0) buffBonus = (int)((1 + (buffBonus / -100.0)) * hpBase)-hpBase;
				int itemBonus = living.ItemBonus[(int)property];
				int cap = Math.Max(player.Level * 4, 20) + // at least 20
						  Math.Min(living.ItemBonus[(int)eProperty.MaxHealthCapBonus], player.Level * 4);	
				itemBonus = Math.Min(itemBonus, cap);
                if (player.HasAbility(Abilities.ScarsOfBattle) && player.Level >= 40)
                {
                    int levelbonus = Math.Min(player.Level - 40, 10);
                    hpBase = (int)(hpBase * (100 + levelbonus) * 0.01);
                }
				int abilityBonus = living.AbilityBonus[(int)property];

				return Math.Max(hpBase + itemBonus + buffBonus + abilityBonus, 1); // at least 1
			}
			else if ( living is GameKeepComponent )
			{
				GameKeepComponent keepComp = living as GameKeepComponent;

				if (keepComp.Keep != null)
					return (keepComp.Keep.EffectiveLevel(keepComp.Keep.Level) + 1) * keepComp.Keep.BaseLevel * 200;

				return 0;
			}
			else if ( living is GameKeepDoor )
			{
				GameKeepDoor keepdoor = living as GameKeepDoor;

				if (keepdoor.Component != null && keepdoor.Component.Keep != null)
				{
					return (keepdoor.Component.Keep.EffectiveLevel(keepdoor.Component.Keep.Level) + 1) * keepdoor.Component.Keep.BaseLevel * 200;
				}

				return 0;

				//todo : use material too to calculate maxhealth
			}
			else if (living is GameNPC)
			{
				int hp = 0;

				if (living.Level<10)
				{
					hp = living.Level * 20 + 20 + living.BaseBuffBonusCategory[(int)property];	// default
				}
				else
				{
					// approx to original formula, thx to mathematica :)
					hp = (int)(50 + 11*living.Level + 0.548331 * living.Level * living.Level) + living.BaseBuffBonusCategory[(int)property];
					if (living.Level < 25)
						hp += 20;
				}

				int basecon = (living as GameNPC).Constitution;
				int conmod = 20; // at level 50 +75 con ~= +300 hit points

				// first adjust hitpoints based on base CON

				if (basecon != ServerProperties.Properties.GAMENPC_BASE_CON)
				{
					hp = Math.Max(1, hp + ((basecon - ServerProperties.Properties.GAMENPC_BASE_CON) * ServerProperties.Properties.GAMENPC_HP_GAIN_PER_CON));
				}

				// Now adjust for buffs

				// adjust hit points based on constitution difference from base con
				// modified from http://www.btinternet.com/~challand/hp_calculator.htm
				int conhp = hp + (conmod * living.Level * (living.GetModified(eProperty.Constitution) - basecon) / 250);

				// 50% buff / debuff cap
				if (conhp > hp * 1.5)
					conhp = (int)(hp * 1.5);
				else if (conhp < hp / 2)
					conhp = hp / 2;

				return conhp;
			}
            else
            {
                if (living.Level < 10)
                {
                    return living.Level * 20 + 20 + living.BaseBuffBonusCategory[(int)property];	// default
                }
                else
                {
                    // approx to original formula, thx to mathematica :)
                    int hp = (int)(50 + 11 * living.Level + 0.548331 * living.Level * living.Level) + living.BaseBuffBonusCategory[(int)property];
                    if (living.Level < 25)
                    {
                        hp += 20;
                    }
                    return hp;
                }
            }
		}