public override SkillResults Use(MabiCreature creature, MabiSkill skill, MabiPacket packet) { var targetId = packet.GetLong(); var target = WorldManager.Instance.GetCreatureById(targetId); if (target == null) return SkillResults.InvalidTarget; if (creature != target && !WorldManager.InRange(creature, target, 1000)) return SkillResults.OutOfRange; // Reduce Stamina equal to healing amount if a player // is using the skill on himself. if (creature == target && creature is MabiPC) { var amount = Math.Min(skill.RankInfo.Var1, creature.LifeInjured - creature.Life); if (creature.Stamina < amount) return SkillResults.InsufficientStamina; creature.Stamina -= amount; } target.Life += skill.RankInfo.Var1; WorldManager.Instance.CreatureStatsUpdate(target); SkillHelper.DecStack(creature, skill); WorldManager.Instance.Broadcast(new MabiPacket(Op.Effect, creature.Id).PutInt(Effect.UseMagic).PutString("healing").PutLong(target.Id), SendTargets.Range, creature); WorldManager.Instance.Broadcast(new MabiPacket(Op.Effect, creature.Id).PutInt(Effect.StackUpdate).PutString("healing_stack").PutBytes(creature.ActiveSkillStacks, 0), SendTargets.Range, creature); SkillHelper.GiveSkillExp(creature, skill, 20); Send.SkillUse(creature.Client, creature, skill.Id, targetId); return SkillResults.Okay; }
public override SkillResults Use(MabiCreature creature, MabiSkill skill, MabiPacket packet) { var targetId = packet.GetLong(); var target = WorldManager.Instance.GetCreatureById(targetId); if (target == null || !target.IsDead || (target.RevivalOptions & DeadMenuOptions.WaitForRescue) == 0 || !target.WaitingForRes) return SkillResults.InvalidTarget; WorldManager.Instance.Broadcast(new MabiPacket(Op.Effect, creature.Id).PutInt(Effect.UseMagic).PutString("healing_phoenix").PutLong(target.Id), SendTargets.Range, creature); Send.SkillUse(creature.Client, creature, skill.Id, targetId); return SkillResults.Okay; }
public override SkillResults Prepare(MabiCreature creature, MabiSkill skill, MabiPacket packet, uint castTime) { var itemId = packet.GetLong(); var title = packet.GetString(); var author = packet.GetString(); var mml = packet.GetString(); var singing = packet.GetString(); // [180300, NA166 (18.09.2013)] Singing var hidden = packet.GetByte(); var item = creature.GetItem(itemId); if (item == null) return SkillResults.Failure; var mmlParts = mml.Split(','); // Check total score length if (mml.Length > MMLMaxLength) return SkillResults.Failure; // Melody length if (mmlParts[0].Length > skill.RankInfo.Var1) return SkillResults.Failure; // Harmony 1 length if (mmlParts.Length > 1 && mmlParts[1].Length > skill.RankInfo.Var2) return SkillResults.Failure; // Harmony 2 length if (mmlParts.Length > 2 && mmlParts[2].Length > skill.RankInfo.Var3) return SkillResults.Failure; creature.Temp.SkillItem1 = item; var level = SkillRank.Novice; // Score level = Musical Knowledge rank var knowledge = creature.Skills.Get(SkillConst.MusicalKnowledge); if (knowledge != null) level = knowledge.Rank; item.Tags.SetString("TITLE", title); item.Tags.SetString("AUTHOR", author); item.Tags.SetString("SCORE", MabiZip.Compress(mml)); item.Tags.SetString("SCSING", ""); // [180300, NA166 (18.09.2013)] Singing item.Tags.SetByte("HIDDEN", hidden); item.Tags.SetShort("LEVEL", (ushort)level); Send.SkillUse(creature.Client, creature, skill.Id, itemId); return SkillResults.Okay; }
public override SkillResults Complete(MabiCreature creature, MabiSkill skill, MabiPacket packet) { var targetId = packet.GetLong(); // 2 unk ints in older logs //var unk1 = packet.GetInt(); //var unk2 = packet.GetInt(); var target = WorldManager.Instance.GetCreatureById(targetId); if (target == null || !target.IsDead) return SkillResults.InvalidTarget; if (creature.Temp.SkillItem1 == null || creature.Temp.SkillItem1.Info.Class != 63000 || creature.Temp.SkillItem1.Info.Amount < 1) return SkillResults.Failure; creature.Inventory.Decrement(creature.Temp.SkillItem1); // TODO: stats creature.Revive(); Send.SkillComplete(creature.Client, creature, skill.Id, targetId); 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 Use(MabiCreature attacker, MabiSkill skill, MabiPacket packet) { var targetId = packet.GetLong(); var unk1 = packet.GetInt(); var unk2 = packet.GetInt(); var target = WorldManager.Instance.GetCreatureById(targetId); if (target == null) return SkillResults.InvalidTarget; //if (!WorldManager.InRange(creature, target, Range)) // return SkillResults.OutOfRange; // X% of Stamina var staminaCost = attacker.Stamina * (skill.RankInfo.Var2 / 100f); if (attacker is MabiPC) attacker.Stamina -= staminaCost; target.StopMove(); var clones = (uint)skill.RankInfo.Var1; attacker.SoulCount = 0; // Spawn clones var pos = target.GetPosition(); WorldManager.Instance.Broadcast( new MabiPacket(Op.Effect, attacker.Id) .PutInt(Effect.ShadowBunshin) .PutByte(3) .PutString("appear") .PutLong(target.Id) .PutInt(clones) .PutInt(Radius) .PutInt(450) // no changes? .PutFloat(pos.X) .PutFloat(pos.Y) , SendTargets.Range, target); // Change char look direction. WorldManager.Instance.Broadcast(PacketCreator.TurnTo(attacker, target), SendTargets.Range, attacker); // Jump to clone circle var toPos = WorldManager.CalculatePosOnLine(attacker, target, -(int)Radius); attacker.SetPosition(toPos.X, toPos.Y); WorldManager.Instance.Broadcast( new MabiPacket(Op.SetLocation, attacker.Id) .PutByte(0) .PutInt(toPos.X) .PutInt(toPos.Y) , SendTargets.Range, attacker); bool alreadyDead = false; uint i = 0; Timer timer = null; timer = new Timer(_ => { if (timer == null || i > clones) return; // Move WorldManager.Instance.Broadcast( new MabiPacket(Op.Effect, attacker.Id) .PutInt(Effect.ShadowBunshin) .PutByte(3) .PutString("move") .PutLong(target.Id) .PutInt(i) // clone nr .PutInt(i) // clone nr .PutInt(450) .PutInt(clones) // ? (4) .PutInt(120) // disappear time? , SendTargets.Range, attacker); // Attack WorldManager.Instance.Broadcast( new MabiPacket(Op.EffectDelayed, attacker.Id) .PutInt(120) // delay? .PutInt(Effect.ShadowBunshin) .PutByte(3) .PutString("attack") .PutInt(i) // clone nr , SendTargets.Range, attacker); var sAction = new AttackerAction(CombatActionType.SpecialHit, attacker, skill.Id, targetId); sAction.Options |= AttackerOptions.Result; var tAction = new TargetAction(CombatActionType.TakeHit, target, attacker, skill.Id); tAction.Delay = 100; var cap = new CombatActionPack(attacker, skill.Id); cap.Add(sAction); target.Stun = tAction.StunTime = 2000; CombatHelper.SetAggro(attacker, target); var rnd = RandomProvider.Get(); float damage = rnd.Next((int)skill.RankInfo.Var5, (int)skill.RankInfo.Var6 + 1); damage += skill.RankInfo.Var7 * staminaCost; // Crit if (CombatHelper.TryAddCritical(attacker, ref damage, attacker.CriticalChanceAgainst(target))) tAction.Options |= TargetOptions.Critical; // Def/Prot CombatHelper.ReduceDamage(ref damage, target.DefenseTotal, target.Protection); // Mana Shield tAction.ManaDamage = CombatHelper.DealManaDamage(target, ref damage); // Deal Life Damage if (damage > 0) target.TakeDamage(tAction.Damage = damage); // Save if target was already dead, to not send // finish action twice. if (!alreadyDead) { target.TakeDamage(tAction.Damage); // Only send damage taking part if target isn't dead yet. cap.Add(tAction); } alreadyDead = target.IsDead; if (target.IsDead) { tAction.OldPosition = pos; if (!alreadyDead) tAction.Options |= TargetOptions.FinishingKnockDown; else tAction.Options |= TargetOptions.KnockDown; } else if (i == clones) { // Knock back if not dead after last attack. tAction.Options |= TargetOptions.KnockDown; tAction.OldPosition = CombatHelper.KnockBack(target, attacker, 400); } WorldManager.Instance.HandleCombatActionPack(cap); if (i >= clones) { // Cancel timer after last attack. timer.Dispose(); timer = null; } i++; GC.KeepAlive(timer); }, null, 900, 450); // Something's messed up here, if the skill isn't explicitly // canceled the client gets confused. //WorldManager.Instance.CreatureSkillCancel(attacker); SkillHelper.GiveSkillExp(attacker, skill, 20); Send.SkillUse(attacker.Client, attacker, skill.Id, targetId, unk1, unk2); return SkillResults.Okay; }
public override SkillResults Prepare(World.MabiCreature creature, MabiSkill skill, MabiPacket packet, uint castTime) { var itemId = packet.GetLong(); var dyeId = packet.GetLong(); var item = creature.GetItem(itemId); var dye = creature.GetItem(dyeId); if (item == null || dye == null) return SkillResults.Failure; creature.Temp.SkillItem1 = item; creature.Temp.SkillItem2 = dye; Send.SkillReady(creature.Client, creature, skill.Id, itemId, dyeId); return SkillResults.Okay; }
public override SkillResults Use(MabiCreature creature, MabiSkill skill, MabiPacket packet) { var targetId = packet.GetLong(); return this.Use(creature, targetId); }
public override SkillResults Use(MabiCreature creature, MabiSkill skill, MabiPacket packet) { return UseCombat(creature, packet.GetLong(), skill); }