public override SkillResults UseCombat(MabiCreature attacker, ulong targetId, MabiSkill skill) { var target = WorldManager.Instance.GetCreatureById(targetId); if (target == null) return SkillResults.InvalidTarget; if (!WorldManager.InRange(attacker, target, (uint)(attacker.RaceInfo.AttackRange + 50))) return SkillResults.OutOfRange; if (attacker.IsStunned) return SkillResults.AttackStunned; attacker.StopMove(); target.StopMove(); // Check counter var counter = CombatHelper.TryCounter(target, attacker); if (counter != SkillResults.None) return SkillResults.Okay; uint prevCombatActionId = 0; var rnd = RandomProvider.Get(); var rightHand = attacker.RightHand; var leftHand = attacker.LeftHand; if (leftHand != null && !leftHand.IsOneHandWeapon) leftHand = null; var sAction = new AttackerAction(CombatActionType.Hit, attacker, skill.Id, targetId); sAction.Options |= AttackerOptions.Result; if (rightHand != null && leftHand != null) sAction.Options |= AttackerOptions.DualWield; // Do this for two weapons, break if there is no second hit. for (byte i = 1; i <= 2; ++i) { var weapon = (i == 1 ? rightHand : leftHand); var atkSpeed = CombatHelper.GetAverageAttackSpeed(attacker); var cap = new CombatActionPack(attacker, skill.Id); cap.PrevCombatActionId = prevCombatActionId; cap.Hit = i; cap.HitsMax = (byte)(sAction.Has(AttackerOptions.DualWield) ? 2 : 1); var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Id); cap.Add(sAction, tAction); // Damage { var damage = attacker.GetRndDamage(weapon); var protection = target.Protection; // Crit if (CombatHelper.TryAddCritical(attacker, ref damage, attacker.CriticalChanceAgainst(target))) tAction.Options |= TargetOptions.Critical; // Def/Prot CombatHelper.ReduceDamage(ref damage, target.DefenseTotal, protection); // Mana Shield tAction.ManaDamage = CombatHelper.DealManaDamage(target, ref damage); // Deal Life Damage if (damage > 0) target.TakeDamage(tAction.Damage = damage); } // Killed? if (target.IsDead) { tAction.Options |= TargetOptions.FinishingKnockDown; attacker.Stun = sAction.StunTime = CombatHelper.GetStunSource(atkSpeed, tAction.IsKnock); } else { // Defense if (target.HasSkillLoaded(SkillConst.Defense)) { tAction.Type = CombatActionType.Defended; tAction.SkillId = SkillConst.Defense; target.Stun = tAction.StunTime = 1000; attacker.Stun = sAction.StunTime = 2500; } // Normal hit else { // Knock back if (target.RaceInfo.Is(RaceStands.KnockBackable)) { target.KnockBack += CombatHelper.GetKnockDown(weapon) / cap.HitsMax; if (target.KnockBack >= CombatHelper.LimitKnockBack) { // Knock down if critical tAction.Options |= (tAction.Has(TargetOptions.Critical) ? TargetOptions.KnockDown : TargetOptions.KnockBack); } } attacker.Stun = sAction.StunTime = CombatHelper.GetStunSource(atkSpeed, tAction.IsKnock); target.Stun = tAction.StunTime = CombatHelper.GetStunTarget(atkSpeed, tAction.IsKnock); } } // Stop on knock back if (tAction.IsKnock && target.RaceInfo.Is(RaceStands.KnockBackable)) { tAction.OldPosition = CombatHelper.KnockBack(target, attacker); sAction.Options |= AttackerOptions.KnockBackHit2; cap.HitsMax = cap.Hit; } // Weapon Exp if (weapon != null) SkillHelper.GiveItemExp(attacker, weapon); // Aggro CombatHelper.SetAggro(attacker, target); // Submit WorldManager.Instance.HandleCombatActionPack(cap); // Stop when all hits are done if (cap.Hit >= cap.HitsMax) break; prevCombatActionId = cap.CombatActionId; } SkillHelper.GiveSkillExp(attacker, skill, 20); return SkillResults.Okay; }