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