Esempio n. 1
0
        void HandleCastSpell(CastSpell cast)
        {
            // ignore for remote control state (for player case)
            Unit mover = GetPlayer().GetUnitBeingMoved();

            if (mover != GetPlayer() && mover.IsTypeId(TypeId.Player))
            {
                return;
            }

            SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(cast.Cast.SpellID, mover.GetMap().GetDifficultyID());

            if (spellInfo == null)
            {
                Log.outError(LogFilter.Network, "WORLD: unknown spell id {0}", cast.Cast.SpellID);
                return;
            }

            if (spellInfo.IsPassive())
            {
                return;
            }

            Unit caster = mover;

            if (caster.IsTypeId(TypeId.Unit) && !caster.ToCreature().HasSpell(spellInfo.Id))
            {
                // If the vehicle creature does not have the spell but it allows the passenger to cast own spells
                // change caster to player and let him cast
                if (!GetPlayer().IsOnVehicle(caster) || spellInfo.CheckVehicle(GetPlayer()) != SpellCastResult.SpellCastOk)
                {
                    return;
                }

                caster = GetPlayer();
            }

            TriggerCastFlags triggerFlag = TriggerCastFlags.None;

            // client provided targets
            SpellCastTargets targets = new(caster, cast.Cast);

            // check known spell or raid marker spell (which not requires player to know it)
            if (caster.IsTypeId(TypeId.Player) && !caster.ToPlayer().HasActiveSpell(spellInfo.Id) && !spellInfo.HasEffect(SpellEffectName.ChangeRaidMarker) && !spellInfo.HasAttribute(SpellAttr8.RaidMarker))
            {
                bool allow = false;


                // allow casting of unknown spells for special lock cases
                GameObject go = targets.GetGOTarget();
                if (go != null)
                {
                    if (go.GetSpellForLock(caster.ToPlayer()) == spellInfo)
                    {
                        allow = true;
                    }
                }

                // allow casting of spells triggered by clientside periodic trigger auras
                if (caster.HasAuraTypeWithTriggerSpell(AuraType.PeriodicTriggerSpellFromClient, spellInfo.Id))
                {
                    allow       = true;
                    triggerFlag = TriggerCastFlags.FullMask;
                }

                if (!allow)
                {
                    return;
                }
            }

            // Check possible spell cast overrides
            spellInfo = caster.GetCastSpellInfo(spellInfo);

            // can't use our own spells when we're in possession of another unit,
            if (GetPlayer().IsPossessing())
            {
                return;
            }

            // Client is resending autoshot cast opcode when other spell is cast during shoot rotation
            // Skip it to prevent "interrupt" message
            // Also check targets! target may have changed and we need to interrupt current spell
            if (spellInfo.IsAutoRepeatRangedSpell())
            {
                Spell autoRepeatSpell = caster.GetCurrentSpell(CurrentSpellTypes.AutoRepeat);
                if (autoRepeatSpell != null)
                {
                    if (autoRepeatSpell.m_spellInfo == spellInfo && autoRepeatSpell.m_targets.GetUnitTargetGUID() == targets.GetUnitTargetGUID())
                    {
                        return;
                    }
                }
            }

            // auto-selection buff level base at target level (in spellInfo)
            if (targets.GetUnitTarget() != null)
            {
                SpellInfo actualSpellInfo = spellInfo.GetAuraRankForLevel(targets.GetUnitTarget().GetLevelForTarget(caster));

                // if rank not found then function return NULL but in explicit cast case original spell can be casted and later failed with appropriate error message
                if (actualSpellInfo != null)
                {
                    spellInfo = actualSpellInfo;
                }
            }

            if (cast.Cast.MoveUpdate.HasValue)
            {
                HandleMovementOpcode(ClientOpcodes.MoveStop, cast.Cast.MoveUpdate.Value);
            }

            Spell spell = new(caster, spellInfo, triggerFlag);

            SpellPrepare spellPrepare = new();

            spellPrepare.ClientCastID = cast.Cast.CastID;
            spellPrepare.ServerCastID = spell.m_castId;
            SendPacket(spellPrepare);

            spell.m_fromClient = true;
            spell.m_misc.Data0 = cast.Cast.Misc[0];
            spell.m_misc.Data1 = cast.Cast.Misc[1];
            spell.Prepare(targets);
        }
Esempio n. 2
0
        void HandlePetCastSpell(PetCastSpell petCastSpell)
        {
            Unit caster = Global.ObjAccessor.GetUnit(GetPlayer(), petCastSpell.PetGUID);

            if (!caster)
            {
                Log.outError(LogFilter.Network, "WorldSession.HandlePetCastSpell: Caster {0} not found.", petCastSpell.PetGUID.ToString());
                return;
            }

            SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(petCastSpell.Cast.SpellID, caster.GetMap().GetDifficultyID());

            if (spellInfo == null)
            {
                Log.outError(LogFilter.Network, "WorldSession.HandlePetCastSpell: unknown spell id {0} tried to cast by {1}", petCastSpell.Cast.SpellID, petCastSpell.PetGUID.ToString());
                return;
            }

            // This opcode is also sent from charmed and possessed units (players and creatures)
            if (caster != GetPlayer().GetGuardianPet() && caster != GetPlayer().GetCharmed())
            {
                Log.outError(LogFilter.Network, "WorldSession.HandlePetCastSpell: {0} isn't pet of player {1} ({2}).", petCastSpell.PetGUID.ToString(), GetPlayer().GetName(), GetPlayer().GetGUID().ToString());
                return;
            }

            SpellCastTargets targets = new(caster, petCastSpell.Cast);

            TriggerCastFlags triggerCastFlags = TriggerCastFlags.None;

            if (spellInfo.IsPassive())
            {
                return;
            }

            // cast only learned spells
            if (!caster.HasSpell(spellInfo.Id))
            {
                bool allow = false;

                // allow casting of spells triggered by clientside periodic trigger auras
                if (caster.HasAuraTypeWithTriggerSpell(AuraType.PeriodicTriggerSpellFromClient, spellInfo.Id))
                {
                    allow            = true;
                    triggerCastFlags = TriggerCastFlags.FullMask;
                }

                if (!allow)
                {
                    return;
                }
            }

            Spell spell = new(caster, spellInfo, triggerCastFlags);

            spell.m_fromClient = true;
            spell.m_misc.Data0 = petCastSpell.Cast.Misc[0];
            spell.m_misc.Data1 = petCastSpell.Cast.Misc[1];
            spell.m_targets    = targets;

            SpellCastResult result = spell.CheckPetCast(null);

            if (result == SpellCastResult.SpellCastOk)
            {
                Creature creature = caster.ToCreature();
                if (creature)
                {
                    Pet pet = creature.ToPet();
                    if (pet)
                    {
                        // 10% chance to play special pet attack talk, else growl
                        // actually this only seems to happen on special spells, fire shield for imp, torment for voidwalker, but it's stupid to check every spell
                        if (pet.GetPetType() == PetType.Summon && (RandomHelper.IRand(0, 100) < 10))
                        {
                            pet.SendPetTalk(PetTalk.SpecialSpell);
                        }
                        else
                        {
                            pet.SendPetAIReaction(petCastSpell.PetGUID);
                        }
                    }
                }

                SpellPrepare spellPrepare = new();
                spellPrepare.ClientCastID = petCastSpell.Cast.CastID;
                spellPrepare.ServerCastID = spell.m_castId;
                SendPacket(spellPrepare);

                spell.Prepare(targets);
            }
            else
            {
                spell.SendPetCastResult(result);

                if (!caster.GetSpellHistory().HasCooldown(spellInfo.Id))
                {
                    caster.GetSpellHistory().ResetCooldown(spellInfo.Id, true);
                }

                spell.Finish(false);
                spell.Dispose();
            }
        }