Beispiel #1
0
        void ClearCharmInfoFlags()
        {
            // Quick access to set all flags to FALSE

            CharmInfo ci = me.GetCharmInfo();

            if (ci != null)
            {
                ci.SetIsAtStay(false);
                ci.SetIsCommandAttack(false);
                ci.SetIsCommandFollow(false);
                ci.SetIsFollowing(false);
                ci.SetIsReturning(false);
            }
        }
Beispiel #2
0
        void HandlePetActionHelper(Unit pet, ObjectGuid guid1, uint spellid, ActiveStates flag, ObjectGuid guid2, float x, float y, float z)
        {
            CharmInfo charmInfo = pet.GetCharmInfo();

            if (charmInfo == null)
            {
                Log.outError(LogFilter.Network, "WorldSession.HandlePetAction(petGuid: {0}, tagGuid: {1}, spellId: {2}, flag: {3}): object (GUID: {4} Entry: {5} TypeId: {6}) is considered pet-like but doesn't have a charminfo!",
                             guid1, guid2, spellid, flag, pet.GetGUID().ToString(), pet.GetEntry(), pet.GetTypeId());
                return;
            }

            switch (flag)
            {
            case ActiveStates.Command:                                       //0x07
                switch ((CommandStates)spellid)
                {
                case CommandStates.Stay:                                  //flat=1792  //STAY
                    pet.StopMoving();
                    pet.GetMotionMaster().Clear(false);
                    pet.GetMotionMaster().MoveIdle();
                    charmInfo.SetCommandState(CommandStates.Stay);

                    charmInfo.SetIsCommandAttack(false);
                    charmInfo.SetIsAtStay(true);
                    charmInfo.SetIsCommandFollow(false);
                    charmInfo.SetIsFollowing(false);
                    charmInfo.SetIsReturning(false);
                    charmInfo.SaveStayPosition();
                    break;

                case CommandStates.Follow:                                //spellid=1792  //FOLLOW
                    pet.AttackStop();
                    pet.InterruptNonMeleeSpells(false);
                    pet.GetMotionMaster().MoveFollow(GetPlayer(), SharedConst.PetFollowDist, pet.GetFollowAngle());
                    charmInfo.SetCommandState(CommandStates.Follow);

                    charmInfo.SetIsCommandAttack(false);
                    charmInfo.SetIsAtStay(false);
                    charmInfo.SetIsReturning(true);
                    charmInfo.SetIsCommandFollow(true);
                    charmInfo.SetIsFollowing(false);
                    break;

                case CommandStates.Attack:                                //spellid=1792  //ATTACK
                {
                    // Can't attack if owner is pacified
                    if (GetPlayer().HasAuraType(AuraType.ModPacify))
                    {
                        // @todo Send proper error message to client
                        return;
                    }

                    // only place where pet can be player
                    Unit TargetUnit = Global.ObjAccessor.GetUnit(GetPlayer(), guid2);
                    if (!TargetUnit)
                    {
                        return;
                    }

                    Unit owner = pet.GetOwner();
                    if (owner)
                    {
                        if (!owner.IsValidAttackTarget(TargetUnit))
                        {
                            return;
                        }
                    }

                    pet.ClearUnitState(UnitState.Follow);
                    // This is true if pet has no target or has target but targets differs.
                    if (pet.GetVictim() != TargetUnit || (pet.GetVictim() == TargetUnit && !pet.GetCharmInfo().IsCommandAttack()))
                    {
                        if (pet.GetVictim())
                        {
                            pet.AttackStop();
                        }

                        if (!pet.IsTypeId(TypeId.Player) && pet.ToCreature().IsAIEnabled)
                        {
                            charmInfo.SetIsCommandAttack(true);
                            charmInfo.SetIsAtStay(false);
                            charmInfo.SetIsFollowing(false);
                            charmInfo.SetIsCommandFollow(false);
                            charmInfo.SetIsReturning(false);

                            pet.ToCreature().GetAI().AttackStart(TargetUnit);

                            //10% chance to play special pet attack talk, else growl
                            if (pet.IsPet() && pet.ToPet().getPetType() == PetType.Summon && pet != TargetUnit && RandomHelper.IRand(0, 100) < 10)
                            {
                                pet.SendPetTalk(PetTalk.Attack);
                            }
                            else
                            {
                                // 90% chance for pet and 100% chance for charmed creature
                                pet.SendPetAIReaction(guid1);
                            }
                        }
                        else                                            // charmed player
                        {
                            if (pet.GetVictim() && pet.GetVictim() != TargetUnit)
                            {
                                pet.AttackStop();
                            }

                            charmInfo.SetIsCommandAttack(true);
                            charmInfo.SetIsAtStay(false);
                            charmInfo.SetIsFollowing(false);
                            charmInfo.SetIsCommandFollow(false);
                            charmInfo.SetIsReturning(false);

                            pet.Attack(TargetUnit, true);
                            pet.SendPetAIReaction(guid1);
                        }
                    }
                    break;
                }

                case CommandStates.Abandon:                               // abandon (hunter pet) or dismiss (summoned pet)
                    if (pet.GetCharmerGUID() == GetPlayer().GetGUID())
                    {
                        GetPlayer().StopCastingCharm();
                    }
                    else if (pet.GetOwnerGUID() == GetPlayer().GetGUID())
                    {
                        Cypher.Assert(pet.IsTypeId(TypeId.Unit));
                        if (pet.IsPet())
                        {
                            if (pet.ToPet().getPetType() == PetType.Hunter)
                            {
                                GetPlayer().RemovePet(pet.ToPet(), PetSaveMode.AsDeleted);
                            }
                            else
                            {
                                //dismissing a summoned pet is like killing them (this prevents returning a soulshard...)
                                pet.setDeathState(DeathState.Corpse);
                            }
                        }
                        else if (pet.HasUnitTypeMask(UnitTypeMask.Minion))
                        {
                            ((Minion)pet).UnSummon();
                        }
                    }
                    break;

                case CommandStates.MoveTo:
                    pet.StopMoving();
                    pet.GetMotionMaster().Clear(false);
                    pet.GetMotionMaster().MovePoint(0, x, y, z);
                    charmInfo.SetCommandState(CommandStates.MoveTo);

                    charmInfo.SetIsCommandAttack(false);
                    charmInfo.SetIsAtStay(true);
                    charmInfo.SetIsFollowing(false);
                    charmInfo.SetIsReturning(false);
                    charmInfo.SaveStayPosition();
                    break;

                default:
                    Log.outError(LogFilter.Network, "WORLD: unknown PET flag Action {0} and spellid {1}.", flag, spellid);
                    break;
                }
                break;

            case ActiveStates.Reaction:                                      // 0x6
                switch ((ReactStates)spellid)
                {
                case ReactStates.Passive:                                 //passive
                    pet.AttackStop();
                    goto case ReactStates.Defensive;

                case ReactStates.Defensive:                               //recovery
                case ReactStates.Aggressive:                              //activete
                    if (pet.IsTypeId(TypeId.Unit))
                    {
                        pet.ToCreature().SetReactState((ReactStates)spellid);
                    }
                    break;
                }
                break;

            case ActiveStates.Disabled:                                      // 0x81    spell (disabled), ignore
            case ActiveStates.Passive:                                       // 0x01
            case ActiveStates.Enabled:                                       // 0xC1    spell
            {
                Unit unit_target = null;

                if (!guid2.IsEmpty())
                {
                    unit_target = Global.ObjAccessor.GetUnit(GetPlayer(), guid2);
                }

                // do not cast unknown spells
                SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(spellid);
                if (spellInfo == null)
                {
                    Log.outError(LogFilter.Network, "WORLD: unknown PET spell id {0}", spellid);
                    return;
                }

                foreach (SpellEffectInfo effect in spellInfo.GetEffectsForDifficulty(Difficulty.None))
                {
                    if (effect != null && (effect.TargetA.GetTarget() == Targets.UnitSrcAreaEnemy || effect.TargetA.GetTarget() == Targets.UnitDestAreaEnemy || effect.TargetA.GetTarget() == Targets.DestDynobjEnemy))
                    {
                        return;
                    }
                }

                // do not cast not learned spells
                if (!pet.HasSpell(spellid) || spellInfo.IsPassive())
                {
                    return;
                }

                //  Clear the flags as if owner clicked 'attack'. AI will reset them
                //  after AttackStart, even if spell failed
                if (pet.GetCharmInfo() != null)
                {
                    pet.GetCharmInfo().SetIsAtStay(false);
                    pet.GetCharmInfo().SetIsCommandAttack(true);
                    pet.GetCharmInfo().SetIsReturning(false);
                    pet.GetCharmInfo().SetIsFollowing(false);
                }

                Spell spell = new Spell(pet, spellInfo, TriggerCastFlags.None);

                SpellCastResult result = spell.CheckPetCast(unit_target);

                //auto turn to target unless possessed
                if (result == SpellCastResult.UnitNotInfront && !pet.isPossessed() && !pet.IsVehicle())
                {
                    Unit unit_target2 = spell.m_targets.GetUnitTarget();
                    if (unit_target)
                    {
                        pet.SetInFront(unit_target);
                        Player player = unit_target.ToPlayer();
                        if (player)
                        {
                            pet.SendUpdateToPlayer(player);
                        }
                    }
                    else if (unit_target2)
                    {
                        pet.SetInFront(unit_target2);
                        Player player = unit_target2.ToPlayer();
                        if (player)
                        {
                            pet.SendUpdateToPlayer(player);
                        }
                    }
                    Unit powner = pet.GetCharmerOrOwner();
                    if (powner)
                    {
                        Player player = powner.ToPlayer();
                        if (player)
                        {
                            pet.SendUpdateToPlayer(player);
                        }
                    }

                    result = SpellCastResult.SpellCastOk;
                }

                if (result == SpellCastResult.SpellCastOk)
                {
                    unit_target = spell.m_targets.GetUnitTarget();

                    //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.IsPet() && (pet.ToPet().getPetType() == PetType.Summon) && (pet != unit_target) && (RandomHelper.IRand(0, 100) < 10))
                    {
                        pet.SendPetTalk(PetTalk.SpecialSpell);
                    }
                    else
                    {
                        pet.SendPetAIReaction(guid1);
                    }

                    if (unit_target && !GetPlayer().IsFriendlyTo(unit_target) && !pet.isPossessed() && !pet.IsVehicle())
                    {
                        // This is true if pet has no target or has target but targets differs.
                        if (pet.GetVictim() != unit_target)
                        {
                            if (pet.GetVictim())
                            {
                                pet.AttackStop();
                            }
                            pet.GetMotionMaster().Clear();
                            if (pet.ToCreature().IsAIEnabled)
                            {
                                pet.ToCreature().GetAI().AttackStart(unit_target);
                            }
                        }
                    }

                    spell.prepare(spell.m_targets);
                }
                else
                {
                    if (pet.isPossessed() || pet.IsVehicle())         // @todo: confirm this check
                    {
                        Spell.SendCastResult(GetPlayer(), spellInfo, spell.m_SpellVisual, spell.m_castId, result);
                    }
                    else
                    {
                        spell.SendPetCastResult(result);
                    }

                    if (!pet.GetSpellHistory().HasCooldown(spellid))
                    {
                        pet.GetSpellHistory().ResetCooldown(spellid, true);
                    }

                    spell.finish(false);
                    spell.Dispose();

                    // reset specific flags in case of spell fail. AI will reset other flags
                    if (pet.GetCharmInfo() != null)
                    {
                        pet.GetCharmInfo().SetIsCommandAttack(false);
                    }
                }
                break;
            }

            default:
                Log.outError(LogFilter.Network, "WORLD: unknown PET flag Action {0} and spellid {1}.", flag, spellid);
                break;
            }
        }