Beispiel #1
0
        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;
        }
Beispiel #3
0
        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;
        }
Beispiel #5
0
        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;
        }
Beispiel #6
0
        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;
        }
Beispiel #7
0
        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);
 }
Beispiel #9
0
 public override SkillResults Use(MabiCreature creature, MabiSkill skill, MabiPacket packet)
 {
     return UseCombat(creature, packet.GetLong(), skill);
 }