public override SkillResults UseCombat(MabiCreature attacker, ulong targetId, MabiSkill skill) { var target = WorldManager.Instance.GetCreatureById(targetId); if (target == null) return SkillResults.InvalidTarget; if (attacker.Magazine == null || attacker.Magazine.Count < 1) return SkillResults.Failure; var rnd = RandomProvider.Get(); attacker.StopMove(); var factory = new CombatFactory(); factory.SetAttackerAction(attacker, CombatActionType.RangeHit, skill.Id, targetId); factory.SetAttackerOptions(AttackerOptions.Result); factory.SetAttackerStun(AfterUseStun); bool hit = false; if (attacker.GetAimPercent(1) > rnd.NextDouble()) { target.StopMove(); factory.AddTargetAction(target, CombatActionType.TakeHit); factory.SetTargetOptions(TargetOptions.Result); factory.SetTargetStun(StunTime); hit = true; } else { factory.AddTargetAction(target, CombatActionType.None); } Send.SkillUse(attacker.Client, attacker, skill.Id, AfterUseStun, 1); SkillHelper.ClearStack(attacker, skill); attacker.Client.Send(new MabiPacket(Op.CombatTargetSet, attacker.Id).PutLong(0)); factory.ExecuteDamage(new System.Func<MabiCreature, MabiCreature, float>((a, t) => { var damage = attacker.GetRndRangeDamage(); damage *= skill.RankInfo.Var1 / 100f; return damage; })); factory.ExecuteStun(); factory.ExecuteKnockback(CombatHelper.MaxKnockBack); WorldManager.Instance.HandleCombatActionPack(factory.GetCap()); if (hit) CombatHelper.SetAggro(attacker, target); SkillHelper.GiveSkillExp(attacker, skill, 20); return SkillResults.Okay; }
public override SkillResults Prepare(MabiCreature creature, MabiSkill skill, MabiPacket packet, uint castTime) { creature.StopMove(); WorldManager.Instance.Broadcast(new MabiPacket(Op.Effect, creature.Id).PutInt(Effect.SkillInit).PutString("thunder").PutShort((ushort)skill.Id), SendTargets.Range, creature); Send.SkillPrepare(creature.Client, creature, skill.Id, castTime); return SkillResults.Okay; }
public override SkillResults Prepare(MabiCreature creature, MabiSkill skill, MabiPacket packet, uint castTime) { Send.SkillInitEffect(creature); creature.StopMove(); Send.SkillPrepare(creature.Client, creature, skill.Id, castTime); return SkillResults.Okay; }
public override SkillResults Prepare(MabiCreature creature, MabiSkill skill, MabiPacket packet, uint castTime) { creature.StopMove(); // Casting motion? WorldManager.Instance.Broadcast(new MabiPacket(Op.Effect, creature.Id).PutInt(Effect.Casting).PutShort(skill.Info.Id).PutBytes(0, 1).PutShort(0), SendTargets.Range, creature); Send.SkillPrepare(creature.Client, creature, skill.Id, castTime); return SkillResults.Okay; }
public override SkillResults Start(MabiCreature creature, MabiSkill skill) { creature.Activate(CreatureConditionB.Demigod); creature.StopMove(); // Spawn eruption { var pos = creature.GetPosition(); var targets = WorldManager.Instance.GetAttackableCreaturesInRange(creature, EruptionRadius); var cap = new CombatActionPack(creature, skill.Id); var aAction = new AttackerAction(CombatActionType.SpecialHit, creature, skill.Id, SkillHelper.GetAreaTargetID(creature.Region, pos.X, pos.Y)); aAction.Options |= AttackerOptions.KnockBackHit1 | AttackerOptions.UseEffect; cap.Add(aAction); foreach (var target in targets) { target.StopMove(); // Officials use CM skill id. var tAction = new TargetAction(CombatActionType.TakeHit, target, creature, skill.Id); tAction.StunTime = EruptionStun; tAction.Delay = 1000; // Supposedly it's magic damage tAction.Damage = creature.GetMagicDamage(null, EruptionDamage); target.TakeDamage(tAction.Damage); tAction.OldPosition = CombatHelper.KnockBack(target, creature, EruptionKnockBack); if (target.IsDead) tAction.Options |= TargetOptions.FinishingKnockDown; cap.Add(tAction); } WorldManager.Instance.HandleCombatActionPack(cap); } Send.EffectDelayed(Effect.AwakeningOfLight1, 800, creature); Send.EffectDelayed(Effect.AwakeningOfLight2, 800, creature); Send.UseMotion(creature, 67, 3, false, false); creature.StatRegens.Add(creature.Temp.DemiHpRegen = new MabiStatRegen(Stat.Life, skill.RankInfo.Var3, creature.LifeMax)); creature.StatRegens.Add(creature.Temp.DemiMpRegen = new MabiStatRegen(Stat.Mana, skill.RankInfo.Var4, creature.ManaMax)); creature.StatRegens.Add(creature.Temp.DemiStmRegen = new MabiStatRegen(Stat.Stamina, skill.RankInfo.Var5, creature.StaminaMax)); WorldManager.Instance.CreatureStatsUpdate(creature); return SkillResults.Okay; }
public override SkillResults UseCombat(MabiCreature attacker, ulong targetId, MabiSkill skill) { // if rank > x then // for splash targets 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; attacker.StopMove(); target.StopMove(); var factory = new CombatFactory(); factory.SetAttackerAction(attacker, CombatActionType.HardHit, skill.Id, targetId); factory.SetAttackerOptions(AttackerOptions.Result | AttackerOptions.KnockBackHit2); factory.SetAttackerStun(AfterUseStun); factory.AddTargetAction(target, CombatActionType.TakeHit, skillId: SkillConst.MeleeCombatMastery); factory.SetTargetOptions(TargetOptions.Result | TargetOptions.Smash); factory.SetTargetStun(StunTime); var critChance = attacker.CriticalChanceAgainst(target); var critOpts = CombatFactory.CriticalOptions.NoCritical; // +5% crit for 2H if (attacker.RightHand != null && attacker.RightHand.IsTwoHandWeapon) critChance *= 1.05f; // Crit if (CombatHelper.TryCritical(critChance)) critOpts = CombatFactory.CriticalOptions.Critical; factory.ExecuteDamage(calculateSmashDamage, critOpts); factory.ExecuteStun(); factory.ExecuteKnockback(CombatHelper.MaxKnockBack); WorldManager.Instance.HandleCombatActionPack(factory.GetCap()); Send.SkillUse(attacker.Client, attacker, skill.Id, AfterUseStun, 1); CombatHelper.SetAggro(attacker, target); SkillHelper.GiveSkillExp(attacker, skill, 20); return SkillResults.Okay; }
public override SkillResults Prepare(MabiCreature creature, MabiSkill skill, MabiPacket packet, uint castTime) { // Is this check done client sided in every client by now? if (WorldConf.BunshinSouls && creature is MabiPC && creature.SoulCount < skill.RankInfo.Var1) { Send.Notice(creature.Client, "You need {0} more souls\nto be able to use Shadow Bunshin.", (skill.RankInfo.Var1 - creature.SoulCount)); return SkillResults.Failure; } creature.StopMove(); WorldManager.Instance.Broadcast(new MabiPacket(Op.Effect, creature.Id).PutInt(Effect.ShadowBunshin).PutByte(1), SendTargets.Range, creature); Send.SkillPrepare(creature.Client, creature, skill.Id, castTime); return SkillResults.Okay; }
public override SkillResults Use(MabiCreature attacker, MabiSkill skill, MabiPacket packet) { //Logger.Debug(packet); var targetId = packet.GetLong(); var unk1 = packet.GetInt(); var unk2 = packet.GetInt(); // Determine range, doesn't seem to be included in rank info. var range = this.GetRange(skill); // Add attack range from race, range must increase depending on "size". range += (uint)attacker.RaceInfo.AttackRange; var enemies = WorldManager.Instance.GetAttackableCreaturesInRange(attacker, range); if (enemies.Count < 1) { Send.Notice(attacker.Client, Localization.Get("skills.wm_no_target")); // Unable to use when there is no target. Send.SkillSilentCancel(attacker.Client, attacker); return SkillResults.OutOfRange | SkillResults.Failure; } var rnd = RandomProvider.Get(); attacker.StopMove(); // Spin motion Send.UseMotion(attacker, 8, 4); var cap = new CombatActionPack(attacker, skill.Id); // One source action, target actions are added for every target // and then we send the pack on its way. var sAction = new AttackerAction(CombatActionType.Hit, attacker, skill.Id, targetId); sAction.Options |= AttackerOptions.Result | AttackerOptions.KnockBackHit1; cap.Add(sAction); attacker.Stun = sAction.StunTime = 2500; // For aggro selection, only one enemy gets it. MabiCreature aggroTarget = null; var survived = new List<MabiCreature>(); foreach (var target in enemies) { target.StopMove(); var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Id); cap.Add(tAction); var damage = attacker.GetRndTotalDamage(); damage *= skill.RankInfo.Var1 / 100; if (CombatHelper.TryAddCritical(attacker, ref damage, attacker.CriticalChance)) tAction.Options |= TargetOptions.Critical; target.TakeDamage(tAction.Damage = damage); if (target.IsDead) tAction.Options |= TargetOptions.FinishingKnockDown; tAction.Options |= TargetOptions.KnockDown; target.Stun = tAction.StunTime = CombatHelper.GetStunTarget(CombatHelper.GetAverageAttackSpeed(attacker), true); tAction.OldPosition = CombatHelper.KnockBack(target, attacker, 375); tAction.Delay = (uint)rnd.Next(300, 351); if (target.Target == attacker) aggroTarget = target; if (!target.IsDead) survived.Add(target); } // No aggro yet, random target. if (aggroTarget == null && survived.Count > 0) aggroTarget = survived[rnd.Next(0, survived.Count)]; if (aggroTarget != null) CombatHelper.SetAggro(attacker, aggroTarget); WorldManager.Instance.HandleCombatActionPack(cap); Send.SkillUse(attacker.Client, attacker, skill.Id, targetId, unk1, unk2); //attacker.Client.SendSkillStackUpdate(attacker, skill.Id, 0); SkillHelper.DecStack(attacker, skill); SkillHelper.GiveSkillExp(attacker, skill, 20); return SkillResults.Okay; }
public override SkillResults UseCombat(MabiCreature attacker, ulong targetId, MabiSkill skill) { var target = WorldManager.Instance.GetCreatureById(targetId); if (target == null) return SkillResults.InvalidTarget; if (attacker.Inventory.Magazine == null || attacker.Inventory.Magazine.Count < 1) return SkillResults.Failure; var rnd = RandomProvider.Get(); attacker.StopMove(); var factory = new CombatFactory(); factory.SetAttackerAction(attacker, CombatActionType.RangeHit, skill.Id, targetId); factory.SetAttackerOptions(AttackerOptions.Result); factory.SetAttackerStun(AfterUseStun); bool hit = false; if (attacker.GetAimPercent(attacker.Skills.Get(SkillConst.RangedCombatMastery).RankInfo.Var3, attacker.ActiveSkillStacks == 5 ? skill.RankInfo.Var3 : 0) > rnd.NextDouble()) { target.StopMove(); factory.AddTargetAction(target, CombatActionType.TakeHit); factory.SetTargetOptions(TargetOptions.Result); factory.SetTargetStun(StunTime); hit = true; } else { factory.AddTargetAction(target, CombatActionType.None); } Send.SkillUse(attacker.Client, attacker, skill.Id, AfterUseStun, 1); SkillHelper.DecStack(attacker, skill); attacker.Client.Send(new MabiPacket(Op.CombatTargetSet, attacker.Id).PutLong(0)); factory.ExecuteDamage(new System.Func<MabiCreature, MabiCreature, float>((a, t) => { var dmg = attacker.GetRndRangeDamage(); switch (5 - a.ActiveSkillStacks) { case 1: dmg *= (95 + skill.RankInfo.Var1) / 100f; break; case 2: dmg *= (105 + skill.RankInfo.Var1) / 100f; break; case 3: dmg *= (110 + skill.RankInfo.Var1) / 100f; break; case 4: dmg *= (130 + skill.RankInfo.Var1) / 100f; break; default: dmg *= (160 + skill.RankInfo.Var2) / 100f; break; } return dmg; })); factory.ExecuteStun(); factory.ExecuteKnockback(40f); WorldManager.Instance.HandleCombatActionPack(factory.GetCap()); if (hit) CombatHelper.SetAggro(attacker, target); SkillHelper.GiveSkillExp(attacker, skill, 20); return SkillResults.Okay; }
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, 1200)) return SkillResults.OutOfRange; attacker.StopMove(); WorldManager.Instance.Broadcast(new MabiPacket(Op.Effect, attacker.Id).PutInt(Effect.UseMagic).PutString(this.Name), SendTargets.Range, attacker); Send.SkillUse(attacker.Client, attacker, skill.Id, UseStun, 1); var sAction = new AttackerAction(CombatActionType.RangeHit, attacker, skill.Id, targetId); sAction.Options |= AttackerOptions.Result; var cap = new CombatActionPack(attacker, skill.Id); cap.Add(sAction); var rnd = RandomProvider.Get(); var damage = attacker.GetMagicDamage(attacker.RightHand, rnd.Next((int)skill.RankInfo.Var1, (int)skill.RankInfo.Var2 + 1)); attacker.Stun = sAction.StunTime = UseStun; var targets = WorldManager.Instance.GetCreaturesInRange(target, 500).Where(c => !c.IsDead && c.IsAttackableBy(attacker)).ToList(); targets.Insert(0, target); for (byte i = 0; i < attacker.ActiveSkillStacks && i < targets.Count; i++) { targets[i].StopMove(); var splashAction = new TargetAction(CombatActionType.TakeHit, targets[i], attacker, skill.Id); splashAction.Options |= TargetOptions.Result; cap.Add(splashAction); splashAction.Damage = damage * ((100 - (i * 10)) / 100f); if (CombatHelper.TryAddCritical(targets[i], ref damage, attacker.CriticalChanceAgainst(targets[i]))) splashAction.Options |= TargetOptions.Critical; targets[i].TakeDamage(splashAction.Damage); targets[i].Stun = splashAction.StunTime = TargetStun; // Knock down if dead if (targets[i].IsDead) { splashAction.OldPosition = CombatHelper.KnockBack(targets[i], (i == 0 ? attacker : targets[i - 1])); splashAction.Options |= TargetOptions.FinishingKnockDown; } else { if (targets[i].KnockBack >= CombatHelper.LimitKnockBack) { splashAction.Options |= TargetOptions.KnockDown; } else { targets[i].KnockBack += KnockBack; if (targets[i].KnockBack >= CombatHelper.LimitKnockBack) { splashAction.OldPosition = CombatHelper.KnockBack(targets[i], (i == 0 ? attacker : targets[i - 1])); splashAction.Options |= TargetOptions.KnockBack; } } targets[i].Stun = splashAction.StunTime = TargetStun; CombatHelper.SetAggro(attacker, targets[i]); } } SkillHelper.ClearStack(attacker, skill); WorldManager.Instance.HandleCombatActionPack(cap); SkillHelper.GiveSkillExp(attacker, skill, 20); return SkillResults.Okay; }
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, 1200)) return SkillResults.OutOfRange; attacker.StopMove(); target.StopMove(); WorldManager.Instance.Broadcast(new MabiPacket(Op.Effect, attacker.Id).PutInt(Effect.UseMagic).PutString(this.Name), SendTargets.Range, attacker); Send.SkillUse(attacker.Client, attacker, skill.Id, UseStun, 1); SkillHelper.DecStack(attacker, skill); var sAction = new AttackerAction(CombatActionType.RangeHit, attacker, skill.Id, targetId); sAction.Options |= AttackerOptions.Result; var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Id); tAction.Options |= TargetOptions.Result; var cap = new CombatActionPack(attacker, skill.Id); cap.Add(sAction, tAction); var rnd = RandomProvider.Get(); var damage = attacker.GetMagicDamage(attacker.RightHand, rnd.Next((int)skill.RankInfo.Var1, (int)skill.RankInfo.Var2 + 1)); if (CombatHelper.TryAddCritical(target, ref damage, attacker.CriticalChanceAgainst(target))) tAction.Options |= TargetOptions.Critical; target.TakeDamage(tAction.Damage = damage); attacker.Stun = sAction.StunTime = UseStun; // Knock down if dead if (target.IsDead) { tAction.OldPosition = CombatHelper.KnockBack(target, attacker); tAction.Options |= TargetOptions.FinishingKnockDown; } else { if (target.KnockBack >= CombatHelper.LimitKnockBack) { tAction.Options |= TargetOptions.KnockDown; } else { target.KnockBack += KnockBack; if (target.KnockBack >= CombatHelper.LimitKnockBack) { tAction.OldPosition = CombatHelper.KnockBack(target, attacker); tAction.Options |= TargetOptions.KnockBack; } } target.Stun = tAction.StunTime = TargetStun; CombatHelper.SetAggro(attacker, target); } WorldManager.Instance.HandleCombatActionPack(cap); SkillHelper.GiveSkillExp(attacker, skill, 20); return SkillResults.Okay; }
public override SkillResults UseCombat(MabiCreature attacker, ulong targetId, MabiSkill skill) { var target = WorldManager.Instance.GetCreatureById(targetId); if (target == null) return SkillResults.InvalidTarget; if (attacker.Magazine == null || attacker.Magazine.Count < 1) return SkillResults.Failure; var rnd = RandomProvider.Get(); attacker.StopMove(); var factory = new CombatFactory(); factory.SetAttackerAction(attacker, CombatActionType.RangeHit, skill.Id, targetId); factory.SetAttackerOptions(AttackerOptions.Result); factory.SetAttackerStun(AfterUseStun); bool hit = false; if (attacker.GetAimPercent(attacker.Skills.Get(SkillConst.RangedCombatMastery).RankInfo.Var3) > rnd.NextDouble()) { target.StopMove(); factory.AddTargetAction(target, CombatActionType.TakeHit); factory.SetTargetOptions(TargetOptions.Result); factory.SetTargetStun(StunTime); hit = true; } else { factory.AddTargetAction(target, CombatActionType.None); } Send.SkillUse(attacker.Client, attacker, skill.Id, AfterUseStun, 1); SkillHelper.ClearStack(attacker, skill); attacker.Client.Send(new MabiPacket(Op.CombatTargetSet, attacker.Id).PutLong(0)); factory.ExecuteDamage(new System.Func<MabiCreature, MabiCreature, float>((a, t) => { var damage = attacker.GetRndRangeDamage(); return damage * .8f; })); factory.ExecuteStun(); factory.ExecuteKnockback(0f); WorldManager.Instance.HandleCombatActionPack(factory.GetCap()); if (!target.IsDead && hit) { // TODO: debuff WorldManager.Instance.Broadcast(new MabiPacket(Op.Effect, target.Id).PutInt(Effect.SupportShot).PutByte(1), SendTargets.Range, target); System.Threading.Thread t = new System.Threading.Thread(() => { System.Threading.Thread.Sleep(3000); WorldManager.Instance.Broadcast(new MabiPacket(Op.Effect, target.Id).PutInt(Effect.SupportShot).PutByte(0), SendTargets.Range, target); }); t.Start(); CombatHelper.SetAggro(attacker, target); } SkillHelper.GiveSkillExp(attacker, skill, 20); return SkillResults.Okay; }
public override SkillResults UseCombat(MabiCreature attacker, ulong targetId, MabiSkill skill) { var itarget = WorldManager.Instance.GetCreatureById(targetId); if (itarget == null) return SkillResults.InvalidTarget; if (!WorldManager.InRange(attacker, itarget, 2000)) return SkillResults.OutOfRange; attacker.StopMove(); WorldManager.Instance.Broadcast(new MabiPacket(Op.Effect, attacker.Id).PutInt(Effect.UseMagic).PutString("thunder").PutByte(0).PutLong(targetId).PutShort((ushort)skill.Id), SendTargets.Range, attacker); var charges = attacker.ActiveSkillStacks; List<MabiCreature> targets = new List<MabiCreature>() { itarget }; this.GetThunderChain(attacker, itarget, targets, ((byte)skill.Rank >= (byte)SkillRank.R1 ? 4 : 1) + (charges - 1) * 2); var pos = itarget.GetPosition(); var cloud = new MabiProp(280, itarget.Region, pos.X, pos.Y, 0); WorldManager.Instance.AddProp(cloud); var lbPacket = new MabiPacket(Op.Effect, Id.Broadcast).PutInt(Effect.Lightningbolt).PutLong(attacker.Id).PutInt((uint)targets.Count); foreach (var target in targets) { lbPacket.PutLong(target.Id); } WorldManager.Instance.Broadcast(lbPacket, SendTargets.Range, attacker); Send.SkillUse(attacker.Client, attacker, skill.Id, UseStun, 1); SkillHelper.ClearStack(attacker, skill); // End the lightning balls WorldManager.Instance.Broadcast(new MabiPacket(Op.Effect, attacker.Id).PutInt(Effect.StackUpdate).PutString("lightningbolt").PutBytes(0, 0), SendTargets.Range, attacker); var sAction = new AttackerAction(CombatActionType.RangeHit, attacker, skill.Id, targetId); sAction.Options |= AttackerOptions.Result; attacker.Stun = sAction.StunTime = UseStun; var cap = new CombatActionPack(attacker, skill.Id); cap.Add(sAction); var rnd = RandomProvider.Get(); foreach (var target in targets) { var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Id); tAction.Options |= TargetOptions.Result; cap.Add(tAction); var damage = attacker.GetMagicDamage(attacker.RightHand, rnd.Next((int)skill.RankInfo.Var4, (int)skill.RankInfo.Var5 + 1)); if (CombatHelper.TryAddCritical(target, ref damage, attacker.CriticalChanceAgainst(target))) tAction.Options |= TargetOptions.Critical; target.TakeDamage(tAction.Damage = damage); // Knock down if dead if (target.IsDead) { tAction.OldPosition = CombatHelper.KnockBack(target, attacker); tAction.Options |= TargetOptions.FinishingKnockDown; } else { if (target.KnockBack >= CombatHelper.LimitKnockBack) { tAction.Options |= TargetOptions.KnockDown; } else { target.KnockBack += KnockBack; if (target.KnockBack >= CombatHelper.LimitKnockBack) { tAction.OldPosition = CombatHelper.KnockBack(target, attacker); tAction.Options |= TargetOptions.KnockBack; } } target.Stun = tAction.StunTime = (ushort)skill.RankInfo.Var3; CombatHelper.SetAggro(attacker, target); } } WorldManager.Instance.HandleCombatActionPack(cap); SkillHelper.GiveSkillExp(attacker, skill, 20); System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(() => { this.ThunderProcessing(attacker, skill, targets, cloud, DateTime.Now.AddMilliseconds(skill.RankInfo.Var3), charges); })); t.Start(); return SkillResults.Okay; }
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; }
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, 2000)) return SkillResults.OutOfRange; if (attacker.ActiveSkillStacks != 5) return SkillResults.Failure; attacker.StopMove(); WorldManager.Instance.Broadcast(new MabiPacket(Op.Effect, attacker.Id).PutInt(Effect.UseMagic).PutString("fireball").PutByte(1).PutLong(targetId).PutShort((ushort)skill.Id), SendTargets.Range, attacker); WorldManager.Instance.Broadcast(PacketCreator.TurnTo(attacker, target).PutByte(1), SendTargets.Range, attacker); var pos = target.GetPosition(); var bomb = new MabiProp(280, target.Region, pos.X, pos.Y, 1f); WorldManager.Instance.AddProp(bomb); var frompos = attacker.GetPosition(); WorldManager.Instance.Broadcast(new MabiPacket(Op.Effect, bomb.Id).PutInts(Effect.FireballFly, bomb.Region).PutFloats(frompos.X, frompos.Y, pos.X, pos.Y).PutInt(4000).PutByte(0).PutInt((uint)skill.Id), SendTargets.Range, attacker); Send.SkillUse(attacker.Client, attacker, skill.Id, UseStun, 1); SkillHelper.ClearStack(attacker, skill); // End the fire bolts WorldManager.Instance.Broadcast(new MabiPacket(Op.Effect, attacker.Id).PutInt(Effect.StackUpdate).PutString("firebolt").PutBytes(0, 0), SendTargets.Range, attacker); SkillHelper.GiveSkillExp(attacker, skill, 20); var t = new Thread(new System.Threading.ThreadStart(() => { this.FireballProcessing(attacker, skill, bomb, targetId); })); t.Start(); return SkillResults.Okay; }