public static SpellCheckCastResult PrepareSpell(this Unit u, SpellCast spell)
        {
            spell.Initialize();
            SpellCheckCastResult reason = u.CanCast(spell, true);

            if (u.SpellCast.ContainsKey(spell.SpellType) && !u.SpellCast[spell.SpellType].IsFinished)
            {
                reason = SpellCheckCastResult.SPELL_FAILED_SPELL_IN_PROGRESS;
            }

            if (reason != SpellCheckCastResult.SPELL_CAST_OK)
            {
                u.SendCastResult(reason, spell.Spell.Id);
                return(reason);
            }

            spell.SendSpellStart();

            if (spell.Caster.IsTypeOf(ObjectTypes.TYPE_UNIT) && !spell.Caster.IsTypeOf(ObjectTypes.TYPE_PLAYER))
            {
                Creature unit = ((Creature)spell.Caster);
                if (spell.Targets.Target != null)
                {
                    unit.TurnTo(spell.Targets.Target.Location);
                }
                else if (spell.Targets.TargetMask.HasFlag((uint)SpellTargetType.TARGET_TYPE_LOCATION))
                {
                    unit.TurnTo(spell.Targets.TargetLocation);
                }
            }

            spell.State = SpellState.SPELL_STATE_CASTING;
            u.SpellCast[spell.SpellType] = spell;

            if (spell.Duration > 0)
            {
                u.ChannelSpell  = spell.Spell.Id;
                u.ChannelObject = spell.Targets.Target.Guid;
                GridManager.Instance.SendSurrounding(u.BuildUpdate(), u);

                if (u.IsTypeOf(ObjectTypes.TYPE_PLAYER))
                {
                    PacketWriter channel = new PacketWriter(Opcodes.MSG_CHANNEL_START);
                    channel.WriteUInt32(spell.Spell.Id);
                    channel.WriteInt32(spell.Duration * 1000);
                    ((Player)u).Client.Send(channel);
                }
            }
            return(SpellCheckCastResult.SPELL_CAST_OK);
        }
        public static void SendCastResult(this Unit u, SpellCheckCastResult result, uint spellid)
        {
            if (u.IsTypeOf(ObjectTypes.TYPE_PLAYER))
            {
                PacketWriter pkt = new PacketWriter(Opcodes.SMSG_CAST_RESULT);
                pkt.WriteUInt32(spellid);

                if (result == SpellCheckCastResult.SPELL_CAST_OK)
                {
                    pkt.WriteUInt8(0);
                }
                else
                {
                    pkt.WriteUInt8(2);
                    pkt.WriteUInt8((byte)result);
                }

                GridManager.Instance.SendSurrounding(pkt, u);
                //((Player)u).Client.Send(pkt);
            }
        }
Exemple #3
0
        void DoSpellsListCasts(long diff)
        {
            bool bDontCast = false;

            foreach (CreatureSpellsEntry spell in spellsList.spells)
            {
                if (spell.cooldown <= diff)
                {
                    // Cooldown has expired.
                    spell.cooldown = 0;

                    // Prevent casting multiple spells in the same update. Only update timers.
                    if ((spell.data.castFlags & ((byte)CastFlags.CF_TRIGGERED | (byte)CastFlags.CF_INTERRUPT_PREVIOUS)) == 0)
                    {
                        if (bDontCast || IsNonMeleeSpellCasted())
                        {
                            continue;
                        }
                    }

                    if (!DBC.Spell.ContainsKey(spell.data.spellId))
                    {
                        continue;
                    }

                    Unit target = ScriptMgr.GetTargetByType(this, this, spell.data.castTarget, spell.data.targetParam1 != 0 ? spell.data.targetParam1 : (uint)DBC.Spell[spell.data.spellId].GetMaxCastRange(), spell.data.targetParam2)?.ToUnit();
                    SpellCheckCastResult result = ForceCastSpell(spell.data.spellId, target);
                    Console.WriteLine("[Creature " + this.Entry.ToString() + "][Spell " + spell.data.spellId.ToString() + "] Cast Result is " + result.ToString());

                    switch (result)
                    {
                    case SpellCheckCastResult.SPELL_CAST_OK:
                    {
                        bDontCast      = (spell.data.castFlags & (byte)CastFlags.CF_TRIGGERED) == 0;
                        spell.cooldown = (long)(new Random().Next((int)spell.data.delayRepeatMin, (int)spell.data.delayRepeatMax));

                        if ((spell.data.castFlags & (byte)CastFlags.CF_MAIN_RANGED_SPELL) != 0)
                        {
                            //if (IsMoving())
                            //    StopMoving();

                            SetCombatMovement(false);
                            SetMeleeAttack(false);
                        }

                        // If there is a script for this spell, run it.
                        // if (spell.data.scriptId != 0)
                        //     m_creature->GetMap()->ScriptsStart(sCreatureSpellScripts, spell.data.scriptId, this, pTarget);
                        break;
                    }

                    //case SpellCheckCastResult.SPELL_FAILED_FLEEING:
                    case SpellCheckCastResult.SPELL_FAILED_SPELL_IN_PROGRESS:
                    {
                        // Do nothing so it will try again on next update.
                        break;
                    }

                    case SpellCheckCastResult.SPELL_FAILED_TRY_AGAIN:
                    {
                        // Chance roll failed, so we reset cooldown.
                        spell.cooldown = (long)(new Random().Next((int)spell.data.delayRepeatMin, (int)spell.data.delayRepeatMax));
                        if ((spell.data.castFlags & (byte)CastFlags.CF_MAIN_RANGED_SPELL) != 0)
                        {
                            SetCombatMovement(true);
                            SetMeleeAttack(true);
                        }
                        break;
                    }

                    default:
                    {
                        // other error
                        if ((spell.data.castFlags & (byte)CastFlags.CF_MAIN_RANGED_SPELL) != 0)
                        {
                            SetCombatMovement(true);
                            SetMeleeAttack(true);
                        }
                        break;
                    }
                    }
                }
                else
                {
                    spell.cooldown -= diff;
                }
            }
        }
        public static SpellCheckCastResult Cast(this Unit u, SpellCast spell)
        {
            if (u.SpellCast[spell.SpellType] != spell) //Check it is the right spell
            {
                u.SendCastResult(SpellCheckCastResult.SPELL_FAILED_NOT_KNOWN, spell.Spell.Id);
                return(SpellCheckCastResult.SPELL_FAILED_NOT_KNOWN);
            }

            SpellCheckCastResult reason = u.CanCast(spell, false);

            if (reason != SpellCheckCastResult.SPELL_CAST_OK) //Final check we can cast this
            {
                u.SendCastResult(reason, spell.Spell.Id);
                return(reason);
            }

            int SpellTime = 0;

            if (spell.Spell.speed > 0)
            {
                float SpellDistance = 0;
                if (spell.Targets.Target != null)
                {
                    SpellDistance = u.Location.Distance(spell.Targets.Target.Location);
                }
                else if (spell.Targets.TargetLocation != null)
                {
                    SpellDistance = u.Location.Distance(spell.Targets.TargetLocation);
                }

                if (SpellDistance > 0)
                {
                    SpellTime = (int)Math.Floor(SpellDistance / spell.Spell.speed * 1000);
                }
            }

            Dictionary <WorldObject, SpellMissInfo>[] TargetsInfected = new Dictionary <WorldObject, SpellMissInfo> [3];
            TargetsInfected[0] = spell.GetTargets(0);
            TargetsInfected[1] = spell.GetTargets(1);
            TargetsInfected[2] = spell.GetTargets(2);

            if (spell.Spell.Attributes.HasFlag((uint)SpellAttributes.SPELL_ATTR_ON_NEXT_SWING_1) || spell.Spell.Attributes.HasFlag((uint)SpellAttributes.SPELL_ATTR_ON_NEXT_SWING_2))
            {
                //TODO combat spell
            }

            if (spell.Caster.IsTypeOf(ObjectTypes.TYPE_PLAYER))
            {
                spell.SendCooldown();
                Player p = (Player)u;

                //Reagents
                for (uint i = 0; i < 7; i++)
                {
                    if (spell.Spell.Reagent[i] > 0 && spell.Spell.ReagentCount[i] > 0)
                    {
                        p.RemoveItem(spell.Spell.Reagent[i], spell.Spell.ReagentCount[i]);
                    }
                }

                //TODO ammo

                switch ((PowerTypes)spell.Spell.powerType)
                {
                case PowerTypes.TYPE_MANA:
                    if (spell.Spell.Attributes.HasFlag((uint)SpellAttributesEx.SPELL_ATTR_EX_DRAIN_ALL_POWER))
                    {
                        p.Mana.Current = 0;
                    }
                    else
                    {
                        p.Mana.Current -= spell.GetManaCost(p.Mana.Current);
                    }
                    break;

                case PowerTypes.TYPE_RAGE:
                    if (spell.Spell.Attributes.HasFlag((uint)SpellAttributesEx.SPELL_ATTR_EX_DRAIN_ALL_POWER))
                    {
                        p.Rage.Current = 0;
                    }
                    else
                    {
                        p.Rage.Current = (p.Rage.Current - spell.GetManaCost(p.Rage.Current)) / 10;
                    }
                    break;

                case PowerTypes.POWER_HEALTH:
                    if (spell.Spell.Attributes.HasFlag((uint)SpellAttributesEx.SPELL_ATTR_EX_DRAIN_ALL_POWER))
                    {
                        p.Health.Current = 1;
                    }
                    else
                    {
                        p.Health.Current -= spell.GetManaCost(p.Health.Current);
                    }
                    break;

                case PowerTypes.TYPE_FOCUS:
                    if (spell.Spell.Attributes.HasFlag((uint)SpellAttributesEx.SPELL_ATTR_EX_DRAIN_ALL_POWER))
                    {
                        p.Focus.Current = 0;
                    }
                    else
                    {
                        p.Focus.Current -= spell.GetManaCost(p.Focus.Current);
                    }
                    break;

                case PowerTypes.TYPE_ENERGY:
                    if (spell.Spell.Attributes.HasFlag((uint)SpellAttributesEx.SPELL_ATTR_EX_DRAIN_ALL_POWER))
                    {
                        p.Energy.Current = 0;
                    }
                    else
                    {
                        p.Energy.Current -= spell.GetManaCost(p.Energy.Current);
                    }
                    break;
                }
            }
            else if (spell.Caster.IsTypeOf(ObjectTypes.TYPE_UNIT))
            {
                switch ((PowerTypes)spell.Spell.powerType)
                {
                case PowerTypes.TYPE_MANA:
                    u.Mana.Current -= spell.GetManaCost(u.Mana.Current);
                    break;

                case PowerTypes.POWER_HEALTH:
                    u.Health.Current -= spell.GetManaCost(u.Health.Current);
                    break;
                }
            }

            u.SpellCast[spell.SpellType].State = SpellState.SPELL_STATE_FINISHED;
            Dictionary <WorldObject, SpellMissInfo> TrueTargets = TargetsInfected[0].Concat(TargetsInfected[1]).Concat(TargetsInfected[2])
                                                                  .Where(w => w.Value == SpellMissInfo.MISS_NONE).GroupBy(d => d.Key)
                                                                  .ToDictionary(d => d.Key, d => d.First().Value);

            for (int i = 0; i < 3; i++)
            {
                List <WorldObject> targets = TargetsInfected[i].Where(x => x.Value == SpellMissInfo.MISS_NONE).Select(x => x.Key).ToList();
                reason = SpellEffect.InvokeHandler((SpellEffects)spell.Spell.Effect[i], spell, targets, i, null);

                if (reason != SpellCheckCastResult.SPELL_CAST_OK)
                {
                    break;
                }
            }

            if (reason == SpellCheckCastResult.SPELL_CAST_OK)
            {
                spell.SendSpellGo();
                spell.SendChannelUpdate(0);
                u.SendCastResult(SpellCheckCastResult.SPELL_CAST_OK, spell.Spell.Id);
            }
            else
            {
                u.SendCastResult(reason, spell.Spell.Id);
            }

            spell.State = SpellState.SPELL_STATE_FINISHED;
            GridManager.Instance.SendSurrounding(u.BuildUpdate(), u);
            return(reason);
        }