Beispiel #1
0
        private void DamageTarget(GameLiving target, GameLiving caster)
        {
            double modifier   = 0.5 + (caster.GetModifiedSpecLevel("Soulrending") * 0.01);
            int    basedamage = (int)(250 * modifier);
            int    resist     = basedamage * target.GetResist(eDamageType.Spirit) / -100;
            int    damage     = basedamage + resist;
            int    heal       = (int)(damage * 0.75);
            int    modheal    = caster.MaxHealth - caster.Health;

            if (modheal > heal)
            {
                modheal = heal;
            }

            caster.Health += modheal;

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

            if (caster is GamePlayer gamePlayer && modheal > 0)
            {
                gamePlayer.Out.SendMessage($"Your Soul Quench returns {modheal} lifepoints to you", eChatType.CT_Spell, 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(caster, target, 1145, 0, false, 1);
                p.Out.SendCombatAnimation(caster, target, 0, 0, 0, 0, 0x14, target.HealthPercent);
            }

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

            target.OnAttackedByEnemy(ad);
            caster.DealDamage(ad);
        }
        private void DamageTarget(GameLiving target, GameLiving caster, double counter)
        {
            int level = caster.GetModifiedSpecLevel("Stormcalling");

            if (level > 50)
            {
                level = 50;
            }
            modifier   = 0.5 + (level * 0.01) * Math.Pow(0.75, counter);
            basedamage = (int)(450 * modifier);
            resist     = basedamage * target.GetResist(eDamageType.Energy) / -100;
            damage     = basedamage + resist;

            GamePlayer player = caster 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(caster, target, 3505, 0, false, 1);
                p.Out.SendCombatAnimation(caster, target, 0, 0, 0, 0, 0x14, target.HealthPercent);
            }

            //target.TakeDamage(caster, eDamageType.Spirit, damage, 0);
            AttackData ad = new AttackData();

            ad.AttackResult = GameLiving.eAttackResult.HitUnstyled;
            ad.Attacker     = caster;
            ad.Target       = target;
            ad.DamageType   = eDamageType.Energy;
            ad.Damage       = damage;
            target.OnAttackedByEnemy(ad);
            caster.DealDamage(ad);
        }
Beispiel #3
0
        private void DamageTarget(GameLiving target, GameLiving caster, double counter)
        {
            int level = caster.GetModifiedSpecLevel("Stormcalling");

            if (level > 50)
            {
                level = 50;
            }

            _modifier   = 0.5 + (level * 0.01) * Math.Pow(0.75, counter);
            _basedamage = (int)(450 * _modifier);
            _resist     = _basedamage * target.GetResist(eDamageType.Energy) / -100;
            _damage     = _basedamage + _resist;

            if (caster 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(caster, target, 3505, 0, false, 1);
                p.Out.SendCombatAnimation(caster, target, 0, 0, 0, 0, 0x14, target.HealthPercent);
            }

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

            target.OnAttackedByEnemy(ad);
            caster.DealDamage(ad);
        }
Beispiel #4
0
        private void DamageTarget(GameLiving target, GameLiving caster)
        {
            double modifier = 0.5 + (caster.GetModifiedSpecLevel("Soulrending") * 0.01);
            int basedamage = (int)(250 * modifier);
            int resist = basedamage * target.GetResist(eDamageType.Spirit) / -100;
            int damage = basedamage + resist;
            int heal = (int)(damage * 0.75);
            int modheal = caster.MaxHealth - caster.Health;
            if (modheal > heal)
                modheal = heal;
            caster.Health += modheal;

            GamePlayer player = caster as GamePlayer;
            if (player != null)
                player.Out.SendMessage("You hit " + target.Name + " for " + damage + "(" + resist + ") points of damage!", eChatType.CT_YouHit, eChatLoc.CL_SystemWindow);
            if (caster is GamePlayer && modheal > 0)
                ((GamePlayer)caster).Out.SendMessage("Your Soul Quench returns " + modheal + " lifepoints to you", eChatType.CT_Spell, 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(caster, target, 1145, 0, false, 1);
                p.Out.SendCombatAnimation(caster, target, 0, 0, 0, 0, 0x14, target.HealthPercent);
            }

            //target.TakeDamage(caster, eDamageType.Spirit, damage, 0);
            AttackData ad = new AttackData();
            ad.AttackResult = GameLiving.eAttackResult.HitUnstyled;
            ad.Attacker = caster;
            ad.Target = target;
            ad.DamageType = eDamageType.Spirit;
            ad.Damage = damage;
            target.OnAttackedByEnemy(ad);
            caster.DealDamage(ad);
        }
Beispiel #5
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;
				}
			}
		}
Beispiel #6
0
        public virtual bool CheckAbilityToUseItem(GameLiving living, ItemTemplate item)
        {
            if (living == null || item == null)
                return false;

            GamePlayer player = living as GamePlayer;

            // GMs can equip everything
            if (player != null  && player.Client.Account.PrivLevel > (uint) ePrivLevel.Player)
                return true;

            // allow usage of all house items
            if ((item.Object_Type == 0 || item.Object_Type >= (int)eObjectType._FirstHouse) && item.Object_Type <= (int)eObjectType._LastHouse)
                return true;

            // on some servers we may wish for dropped items to be used by all realms regardless of what is set in the db
            if (!ServerProperties.Properties.ALLOW_CROSS_REALM_ITEMS)
            {
                if (item.Realm != 0 && item.Realm != (int)living.Realm)
                    return false;
            }

            // classes restriction. 0 means every class
            if (player != null && !Util.IsEmpty(item.AllowedClasses, true))
            {
                if (!item.AllowedClasses.SplitCSV(true).Contains(player.CharacterClass.ID.ToString()))
                    return false;
            }

            //armor
            if (item.Object_Type >= (int)eObjectType._FirstArmor && item.Object_Type <= (int)eObjectType._LastArmor)
            {
                int armorAbility = -1;
                switch ((eRealm)item.Realm)
                {
                        case eRealm.Albion: armorAbility = living.GetAbilityLevel(Abilities.AlbArmor); break;
                        case eRealm.Hibernia: armorAbility = living.GetAbilityLevel(Abilities.HibArmor); break;
                        case eRealm.Midgard: armorAbility = living.GetAbilityLevel(Abilities.MidArmor); break;
                    default: // use old system
                        armorAbility = Math.Max(armorAbility, living.GetAbilityLevel(Abilities.AlbArmor));
                        armorAbility = Math.Max(armorAbility, living.GetAbilityLevel(Abilities.HibArmor));
                        armorAbility = Math.Max(armorAbility, living.GetAbilityLevel(Abilities.MidArmor));
                        break;
                }
                switch ((eObjectType)item.Object_Type)
                {
                        case eObjectType.GenericArmor: return armorAbility >= ArmorLevel.GenericArmor;
                        case eObjectType.Cloth: return armorAbility >= ArmorLevel.Cloth;
                        case eObjectType.Leather: return armorAbility >= ArmorLevel.Leather;
                    case eObjectType.Reinforced:
                        case eObjectType.Studded: return armorAbility >= ArmorLevel.Studded;
                    case eObjectType.Scale:
                        case eObjectType.Chain: return armorAbility >= ArmorLevel.Chain;
                        case eObjectType.Plate: return armorAbility >= ArmorLevel.Plate;
                        default: return false;
                }
            }

            // non-armors
            string abilityCheck = null;
            string[] otherCheck = new string[0];

            //http://dol.kitchenhost.de/files/dol/Info/itemtable.txt
            switch ((eObjectType)item.Object_Type)
            {
                    case eObjectType.GenericItem: return true;
                    case eObjectType.GenericArmor: return true;
                    case eObjectType.GenericWeapon: return true;
                    case eObjectType.Staff: abilityCheck = Abilities.Weapon_Staves; break;
                    case eObjectType.Fired: abilityCheck = Abilities.Weapon_Shortbows; break;
                    case eObjectType.FistWraps: abilityCheck = Abilities.Weapon_FistWraps; break;
                    case eObjectType.MaulerStaff: abilityCheck = Abilities.Weapon_MaulerStaff; break;

                    //alb
                    case eObjectType.CrushingWeapon: abilityCheck = Abilities.Weapon_Crushing; break;
                    case eObjectType.SlashingWeapon: abilityCheck = Abilities.Weapon_Slashing; break;
                    case eObjectType.ThrustWeapon: abilityCheck = Abilities.Weapon_Thrusting; break;
                    case eObjectType.TwoHandedWeapon: abilityCheck = Abilities.Weapon_TwoHanded; break;
                    case eObjectType.PolearmWeapon: abilityCheck = Abilities.Weapon_Polearms; break;
                case eObjectType.Longbow:
                    otherCheck = new string[] { Abilities.Weapon_Longbows, Abilities.Weapon_Archery };
                    break;
                    case eObjectType.Crossbow: abilityCheck = Abilities.Weapon_Crossbow; break;
                    case eObjectType.Flexible: abilityCheck = Abilities.Weapon_Flexible; break;
                    //TODO: case 5: abilityCheck = Abilities.Weapon_Thrown; break;

                    //mid
                    case eObjectType.Sword: abilityCheck = Abilities.Weapon_Swords; break;
                    case eObjectType.Hammer: abilityCheck = Abilities.Weapon_Hammers; break;
                case eObjectType.LeftAxe:
                    case eObjectType.Axe: abilityCheck = Abilities.Weapon_Axes; break;
                    case eObjectType.Spear: abilityCheck = Abilities.Weapon_Spears; break;
                case eObjectType.CompositeBow:
                    otherCheck = new string[] { Abilities.Weapon_CompositeBows, Abilities.Weapon_Archery };
                    break;
                    case eObjectType.Thrown: abilityCheck = Abilities.Weapon_Thrown; break;
                    case eObjectType.HandToHand: abilityCheck = Abilities.Weapon_HandToHand; break;

                    //hib
                case eObjectType.RecurvedBow:
                    otherCheck = new string[] { Abilities.Weapon_RecurvedBows, Abilities.Weapon_Archery };
                    break;
                    case eObjectType.Blades: abilityCheck = Abilities.Weapon_Blades; break;
                    case eObjectType.Blunt: abilityCheck = Abilities.Weapon_Blunt; break;
                    case eObjectType.Piercing: abilityCheck = Abilities.Weapon_Piercing; break;
                    case eObjectType.LargeWeapons: abilityCheck = Abilities.Weapon_LargeWeapons; break;
                    case eObjectType.CelticSpear: abilityCheck = Abilities.Weapon_CelticSpear; break;
                    case eObjectType.Scythe: abilityCheck = Abilities.Weapon_Scythe; break;

                    //misc
                    case eObjectType.Magical: return true;
                    case eObjectType.Shield: return living.GetAbilityLevel(Abilities.Shield) >= item.Type_Damage;
                    case eObjectType.Bolt: abilityCheck = Abilities.Weapon_Crossbow; break;
                    case eObjectType.Arrow: otherCheck = new string[] { Abilities.Weapon_CompositeBows, Abilities.Weapon_Longbows, Abilities.Weapon_RecurvedBows, Abilities.Weapon_Shortbows }; break;
                    case eObjectType.Poison: return living.GetModifiedSpecLevel(Specs.Envenom) > 0;
                    case eObjectType.Instrument: return living.HasAbility(Abilities.Weapon_Instruments);
                    //TODO: different shield sizes
            }

            if(abilityCheck != null && living.HasAbility(abilityCheck))
                return true;

            foreach (string str in otherCheck)
                if (living.HasAbility(str))
                    return true;

            return false;
        }
        private void DamageTarget(GameLiving target, GameLiving caster, double counter)
        {
            int level = caster.GetModifiedSpecLevel("Stormcalling");
            if (level > 50)
                level = 50;
            modifier = 0.5 + (level * 0.01) * Math.Pow(0.75, counter);
            basedamage = (int)(450 * modifier);
            resist = basedamage * target.GetResist(eDamageType.Energy) / -100;
            damage = basedamage + resist;

            GamePlayer player = caster 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(caster, target, 3505, 0, false, 1);
                p.Out.SendCombatAnimation(caster, target, 0, 0, 0, 0, 0x14, target.HealthPercent);
            }

            //target.TakeDamage(caster, eDamageType.Spirit, damage, 0);
            AttackData ad = new AttackData();
            ad.AttackResult = GameLiving.eAttackResult.HitUnstyled;
            ad.Attacker = caster;
            ad.Target = target;
            ad.DamageType = eDamageType.Energy;
            ad.Damage = damage;
            target.OnAttackedByEnemy(ad);
            caster.DealDamage(ad);
        }
Beispiel #8
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;
                }
            }
        }