Пример #1
0
        public Pet CreateTamedPetFrom(uint creatureEntry, uint spell_id = 0)
        {
            if (!IsTypeId(TypeId.Player))
            {
                return(null);
            }

            CreatureTemplate creatureInfo = Global.ObjectMgr.GetCreatureTemplate(creatureEntry);

            if (creatureInfo == null)
            {
                return(null);
            }

            Pet pet = new Pet(ToPlayer(), PetType.Hunter);

            if (!pet.CreateBaseAtCreatureInfo(creatureInfo, this) || !InitTamedPet(pet, getLevel(), spell_id))
            {
                return(null);
            }

            return(pet);
        }
Пример #2
0
        // @todo Move stat mods code to pet passive auras
        public bool InitStatsForLevel(uint petlevel)
        {
            CreatureTemplate cinfo = GetCreatureTemplate();

            Cypher.Assert(cinfo != null);

            SetLevel(petlevel);

            //Determine pet type
            PetType petType = PetType.Max;

            if (IsPet() && GetOwner().IsTypeId(TypeId.Player))
            {
                if (GetOwner().GetClass() == Class.Warlock ||
                    GetOwner().GetClass() == Class.Shaman ||           // Fire Elemental
                    GetOwner().GetClass() == Class.Deathknight)        // Risen Ghoul
                {
                    petType = PetType.Summon;
                }
                else if (GetOwner().GetClass() == Class.Hunter)
                {
                    petType       = PetType.Hunter;
                    UnitTypeMask |= UnitTypeMask.HunterPet;
                }
                else
                {
                    Log.outError(LogFilter.Unit, "Unknown type pet {0} is summoned by player class {1}", GetEntry(), GetOwner().GetClass());
                }
            }

            uint creature_ID = (petType == PetType.Hunter) ? 1 : cinfo.Entry;

            SetMeleeDamageSchool((SpellSchools)cinfo.DmgSchool);

            SetStatFlatModifier(UnitMods.Armor, UnitModifierFlatType.Base, (float)petlevel * 50);

            SetBaseAttackTime(WeaponAttackType.BaseAttack, SharedConst.BaseAttackTime);
            SetBaseAttackTime(WeaponAttackType.OffAttack, SharedConst.BaseAttackTime);
            SetBaseAttackTime(WeaponAttackType.RangedAttack, SharedConst.BaseAttackTime);

            //scale
            var cFamily = CliDB.CreatureFamilyStorage.LookupByKey(cinfo.Family);

            if (cFamily != null && cFamily.MinScale > 0.0f && petType == PetType.Hunter)
            {
                float scale;
                if (GetLevel() >= cFamily.MaxScaleLevel)
                {
                    scale = cFamily.MaxScale;
                }
                else if (GetLevel() <= cFamily.MinScaleLevel)
                {
                    scale = cFamily.MinScale;
                }
                else
                {
                    scale = cFamily.MinScale + (float)(GetLevel() - cFamily.MinScaleLevel) / cFamily.MaxScaleLevel * (cFamily.MaxScale - cFamily.MinScale);
                }

                SetObjectScale(scale);
            }

            // Resistance
            // Hunters pet should not inherit resistances from creature_template, they have separate auras for that
            if (!IsHunterPet())
            {
                for (int i = (int)SpellSchools.Holy; i < (int)SpellSchools.Max; ++i)
                {
                    SetStatFlatModifier(UnitMods.ResistanceStart + i, UnitModifierFlatType.Base, cinfo.Resistance[i]);
                }
            }

            // Health, Mana or Power, Armor
            PetLevelInfo pInfo = Global.ObjectMgr.GetPetLevelInfo(creature_ID, petlevel);

            if (pInfo != null)                                      // exist in DB
            {
                SetCreateHealth(pInfo.health);
                SetCreateMana(pInfo.mana);

                if (pInfo.armor > 0)
                {
                    SetStatFlatModifier(UnitMods.Armor, UnitModifierFlatType.Base, pInfo.armor);
                }

                for (byte stat = 0; stat < (int)Stats.Max; ++stat)
                {
                    SetCreateStat((Stats)stat, pInfo.stats[stat]);
                }
            }
            else                                            // not exist in DB, use some default fake data
            {
                // remove elite bonuses included in DB values
                CreatureBaseStats    stats   = Global.ObjectMgr.GetCreatureBaseStats(petlevel, cinfo.UnitClass);
                CreatureLevelScaling scaling = cinfo.GetLevelScaling(GetMap().GetDifficultyID());

                SetCreateHealth((uint)(Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.CreatureHealth, petlevel, cinfo.GetHealthScalingExpansion(), scaling.ContentTuningID, (Class)cinfo.UnitClass) * cinfo.ModHealth * cinfo.ModHealthExtra));

                SetCreateMana(stats.BaseMana);

                SetCreateStat(Stats.Strength, 22);
                SetCreateStat(Stats.Agility, 22);
                SetCreateStat(Stats.Stamina, 25);
                SetCreateStat(Stats.Intellect, 28);
            }

            // Power
            if (petType == PetType.Hunter) // Hunter pets have focus
            {
                SetPowerType(PowerType.Focus);
            }
            else if (IsPetGhoul() || IsPetAbomination()) // DK pets have energy
            {
                SetPowerType(PowerType.Energy);
            }
            else if (IsPetImp() || IsPetFelhunter() || IsPetVoidwalker() || IsPetSuccubus() || IsPetDoomguard() || IsPetFelguard()) // Warlock pets have energy (since 5.x)
            {
                SetPowerType(PowerType.Energy);
            }
            else
            {
                SetPowerType(PowerType.Mana);
            }

            // Damage
            SetBonusDamage(0);
            switch (petType)
            {
            case PetType.Summon:
            {
                // the damage bonus used for pets is either fire or shadow damage, whatever is higher
                int fire   = GetOwner().ToPlayer().m_activePlayerData.ModDamageDonePos[(int)SpellSchools.Fire];
                int shadow = GetOwner().ToPlayer().m_activePlayerData.ModDamageDonePos[(int)SpellSchools.Shadow];
                int val    = (fire > shadow) ? fire : shadow;
                if (val < 0)
                {
                    val = 0;
                }

                SetBonusDamage((int)(val * 0.15f));

                SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MinDamage, petlevel - (petlevel / 4));
                SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MaxDamage, petlevel + (petlevel / 4));
                break;
            }

            case PetType.Hunter:
            {
                ToPet().SetPetNextLevelExperience((uint)(Global.ObjectMgr.GetXPForLevel(petlevel) * 0.05f));
                //these formula may not be correct; however, it is designed to be close to what it should be
                //this makes dps 0.5 of pets level
                SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MinDamage, petlevel - (petlevel / 4));
                //damage range is then petlevel / 2
                SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MaxDamage, petlevel + (petlevel / 4));
                //damage is increased afterwards as strength and pet scaling modify attack power
                break;
            }

            default:
            {
                switch (GetEntry())
                {
                case 510:             // mage Water Elemental
                {
                    SetBonusDamage((int)(GetOwner().SpellBaseDamageBonusDone(SpellSchoolMask.Frost) * 0.33f));
                    break;
                }

                case 1964:             //force of nature
                {
                    if (pInfo == null)
                    {
                        SetCreateHealth(30 + 30 * petlevel);
                    }
                    float bonusDmg = GetOwner().SpellBaseDamageBonusDone(SpellSchoolMask.Nature) * 0.15f;
                    SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MinDamage, petlevel * 2.5f - ((float)petlevel / 2) + bonusDmg);
                    SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MaxDamage, petlevel * 2.5f + ((float)petlevel / 2) + bonusDmg);
                    break;
                }

                case 15352:             //earth elemental 36213
                {
                    if (pInfo == null)
                    {
                        SetCreateHealth(100 + 120 * petlevel);
                    }
                    SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MinDamage, petlevel - (petlevel / 4));
                    SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MaxDamage, petlevel + (petlevel / 4));
                    break;
                }

                case 15438:             //fire elemental
                {
                    if (pInfo == null)
                    {
                        SetCreateHealth(40 * petlevel);
                        SetCreateMana(28 + 10 * petlevel);
                    }
                    SetBonusDamage((int)(GetOwner().SpellBaseDamageBonusDone(SpellSchoolMask.Fire) * 0.5f));
                    SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MinDamage, petlevel * 4 - petlevel);
                    SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MaxDamage, petlevel * 4 + petlevel);
                    break;
                }

                case 19668:             // Shadowfiend
                {
                    if (pInfo == null)
                    {
                        SetCreateMana(28 + 10 * petlevel);
                        SetCreateHealth(28 + 30 * petlevel);
                    }
                    int bonus_dmg = (int)(GetOwner().SpellBaseDamageBonusDone(SpellSchoolMask.Shadow) * 0.3f);
                    SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MinDamage, (petlevel * 4 - petlevel) + bonus_dmg);
                    SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MaxDamage, (petlevel * 4 + petlevel) + bonus_dmg);
                    break;
                }

                case 19833:             //Snake Trap - Venomous Snake
                {
                    SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MinDamage, (petlevel / 2) - 25);
                    SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MaxDamage, (petlevel / 2) - 18);
                    break;
                }

                case 19921:             //Snake Trap - Viper
                {
                    SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MinDamage, petlevel / 2 - 10);
                    SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MaxDamage, petlevel / 2);
                    break;
                }

                case 29264:             // Feral Spirit
                {
                    if (pInfo == null)
                    {
                        SetCreateHealth(30 * petlevel);
                    }

                    // wolf attack speed is 1.5s
                    SetBaseAttackTime(WeaponAttackType.BaseAttack, cinfo.BaseAttackTime);

                    SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MinDamage, (petlevel * 4 - petlevel));
                    SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MaxDamage, (petlevel * 4 + petlevel));

                    SetStatFlatModifier(UnitMods.Armor, UnitModifierFlatType.Base, GetOwner().GetArmor() * 0.35f);                  // Bonus Armor (35% of player armor)
                    SetStatFlatModifier(UnitMods.StatStamina, UnitModifierFlatType.Base, GetOwner().GetStat(Stats.Stamina) * 0.3f); // Bonus Stamina (30% of player stamina)
                    if (!HasAura(58877))                                                                                            //prevent apply twice for the 2 wolves
                    {
                        AddAura(58877, this);                                                                                       //Spirit Hunt, passive, Spirit Wolves' attacks heal them and their master for 150% of damage done.
                    }
                    break;
                }

                case 31216:             // Mirror Image
                {
                    SetBonusDamage((int)(GetOwner().SpellBaseDamageBonusDone(SpellSchoolMask.Frost) * 0.33f));
                    SetDisplayId(GetOwner().GetDisplayId());
                    if (pInfo == null)
                    {
                        SetCreateMana(28 + 30 * petlevel);
                        SetCreateHealth(28 + 10 * petlevel);
                    }
                    break;
                }

                case 27829:             // Ebon Gargoyle
                {
                    if (pInfo == null)
                    {
                        SetCreateMana(28 + 10 * petlevel);
                        SetCreateHealth(28 + 30 * petlevel);
                    }
                    SetBonusDamage((int)(GetOwner().GetTotalAttackPowerValue(WeaponAttackType.BaseAttack) * 0.5f));
                    SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MinDamage, petlevel - (petlevel / 4));
                    SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MaxDamage, petlevel + (petlevel / 4));
                    break;
                }

                case 28017:             // Bloodworms
                {
                    SetCreateHealth(4 * petlevel);
                    SetBonusDamage((int)(GetOwner().GetTotalAttackPowerValue(WeaponAttackType.BaseAttack) * 0.006f));
                    SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MinDamage, petlevel - 30 - (petlevel / 4));
                    SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MaxDamage, petlevel - 30 + (petlevel / 4));
                }
                break;
                }
                break;
            }
            }

            UpdateAllStats();

            SetFullHealth();
            SetFullPower(PowerType.Mana);
            return(true);
        }
Пример #3
0
        public bool SetCharmedBy(Unit charmer, CharmType type, AuraApplication aurApp = null)
        {
            if (!charmer)
            {
                return(false);
            }

            // dismount players when charmed
            if (IsTypeId(TypeId.Player))
            {
                RemoveAurasByType(AuraType.Mounted);
            }

            if (charmer.IsTypeId(TypeId.Player))
            {
                charmer.RemoveAurasByType(AuraType.Mounted);
            }

            Contract.Assert(type != CharmType.Possess || charmer.IsTypeId(TypeId.Player));
            Contract.Assert((type == CharmType.Vehicle) == IsVehicle());

            Log.outDebug(LogFilter.Unit, "SetCharmedBy: charmer {0} (GUID {1}), charmed {2} (GUID {3}), type {4}.", charmer.GetEntry(), charmer.GetGUID().ToString(), GetEntry(), GetGUID().ToString(), type);

            if (this == charmer)
            {
                Log.outFatal(LogFilter.Unit, "Unit:SetCharmedBy: Unit {0} (GUID {1}) is trying to charm itself!", GetEntry(), GetGUID().ToString());
                return(false);
            }

            if (IsTypeId(TypeId.Player) && ToPlayer().GetTransport())
            {
                Log.outFatal(LogFilter.Unit, "Unit:SetCharmedBy: Player on transport is trying to charm {0} (GUID {1})", GetEntry(), GetGUID().ToString());
                return(false);
            }

            // Already charmed
            if (!GetCharmerGUID().IsEmpty())
            {
                Log.outFatal(LogFilter.Unit, "Unit:SetCharmedBy: {0} (GUID {1}) has already been charmed but {2} (GUID {3}) is trying to charm it!", GetEntry(), GetGUID().ToString(), charmer.GetEntry(), charmer.GetGUID().ToString());
                return(false);
            }

            CastStop();
            CombatStop(); // @todo CombatStop(true) may cause crash (interrupt spells)
            DeleteThreatList();

            Player playerCharmer = charmer.ToPlayer();

            // Charmer stop charming
            if (playerCharmer)
            {
                playerCharmer.StopCastingCharm();
                playerCharmer.StopCastingBindSight();
            }

            // Charmed stop charming
            if (IsTypeId(TypeId.Player))
            {
                ToPlayer().StopCastingCharm();
                ToPlayer().StopCastingBindSight();
            }

            // StopCastingCharm may remove a possessed pet?
            if (!IsInWorld)
            {
                Log.outFatal(LogFilter.Unit, "Unit:SetCharmedBy: {0} (GUID {1}) is not in world but {2} (GUID {3}) is trying to charm it!", GetEntry(), GetGUID().ToString(), charmer.GetEntry(), charmer.GetGUID().ToString());
                return(false);
            }

            // charm is set by aura, and aura effect remove handler was called during apply handler execution
            // prevent undefined behaviour
            if (aurApp != null && aurApp.GetRemoveMode() != 0)
            {
                return(false);
            }

            _oldFactionId = getFaction();
            SetFaction(charmer.getFaction());

            // Set charmed
            charmer.SetCharm(this, true);

            Player player;

            if (IsTypeId(TypeId.Unit))
            {
                ToCreature().GetAI().OnCharmed(true);
                GetMotionMaster().MoveIdle();
            }
            else if (player = ToPlayer())
            {
                if (player.isAFK())
                {
                    player.ToggleAFK();
                }

                Creature creatureCharmer = charmer.ToCreature();
                if (charmer.IsTypeId(TypeId.Unit)) // we are charmed by a creature
                {
                    // change AI to charmed AI on next Update tick
                    NeedChangeAI = true;
                    if (IsAIEnabled)
                    {
                        IsAIEnabled = false;
                        player.GetAI().OnCharmed(true);
                    }
                }

                player.SetClientControl(this, false);
            }

            // charm is set by aura, and aura effect remove handler was called during apply handler execution
            // prevent undefined behaviour
            if (aurApp != null && aurApp.GetRemoveMode() != 0)
            {
                return(false);
            }

            // Pets already have a properly initialized CharmInfo, don't overwrite it.
            if (type != CharmType.Vehicle && GetCharmInfo() == null)
            {
                InitCharmInfo();
                if (type == CharmType.Possess)
                {
                    GetCharmInfo().InitPossessCreateSpells();
                }
                else
                {
                    GetCharmInfo().InitCharmCreateSpells();
                }
            }

            if (playerCharmer)
            {
                switch (type)
                {
                case CharmType.Vehicle:
                    SetFlag(UnitFields.Flags, UnitFlags.PlayerControlled);
                    playerCharmer.SetClientControl(this, true);
                    playerCharmer.VehicleSpellInitialize();
                    break;

                case CharmType.Possess:
                    AddUnitState(UnitState.Possessed);
                    SetFlag(UnitFields.Flags, UnitFlags.PlayerControlled);
                    charmer.SetFlag(UnitFields.Flags, UnitFlags.RemoveClientControl);
                    playerCharmer.SetClientControl(this, true);
                    playerCharmer.PossessSpellInitialize();
                    break;

                case CharmType.Charm:
                    if (IsTypeId(TypeId.Unit) && charmer.GetClass() == Class.Warlock)
                    {
                        CreatureTemplate cinfo = ToCreature().GetCreatureTemplate();
                        if (cinfo != null && cinfo.CreatureType == CreatureType.Demon)
                        {
                            // to prevent client crash
                            SetByteValue(UnitFields.Bytes0, 1, (byte)Class.Mage);

                            // just to enable stat window
                            if (GetCharmInfo() != null)
                            {
                                GetCharmInfo().SetPetNumber(Global.ObjectMgr.GeneratePetNumber(), true);
                            }

                            // if charmed two demons the same session, the 2nd gets the 1st one's name
                            SetUInt32Value(UnitFields.PetNameTimestamp, (uint)Time.UnixTime);     // cast can't be helped
                        }
                    }
                    playerCharmer.CharmSpellInitialize();
                    break;

                default:
                case CharmType.Convert:
                    break;
                }
            }
            return(true);
        }
Пример #4
0
        public void RemoveCharmedBy(Unit charmer)
        {
            if (!IsCharmed())
            {
                return;
            }

            if (!charmer)
            {
                charmer = GetCharmer();
            }
            if (charmer != GetCharmer()) // one aura overrides another?
            {
                return;
            }

            CharmType type;

            if (HasUnitState(UnitState.Possessed))
            {
                type = CharmType.Possess;
            }
            else if (charmer && charmer.IsOnVehicle(this))
            {
                type = CharmType.Vehicle;
            }
            else
            {
                type = CharmType.Charm;
            }

            CastStop();
            CombatStop(); // @todo CombatStop(true) may cause crash (interrupt spells)
            getHostileRefManager().deleteReferences();
            DeleteThreatList();

            if (_oldFactionId != 0)
            {
                SetFaction(_oldFactionId);
                _oldFactionId = 0;
            }
            else
            {
                RestoreFaction();
            }

            GetMotionMaster().InitDefault();

            Creature creature = ToCreature();

            if (creature)
            {
                // Creature will restore its old AI on next update
                if (creature.GetAI() != null)
                {
                    creature.GetAI().OnCharmed(false);
                }

                // Vehicle should not attack its passenger after he exists the seat
                if (type != CharmType.Vehicle)
                {
                    LastCharmerGUID = charmer ? charmer.GetGUID() : ObjectGuid.Empty;
                }
            }

            // If charmer still exists
            if (!charmer)
            {
                return;
            }

            Contract.Assert(type != CharmType.Possess || charmer.IsTypeId(TypeId.Player));
            Contract.Assert(type != CharmType.Vehicle || (IsTypeId(TypeId.Unit) && IsVehicle()));

            charmer.SetCharm(this, false);

            Player playerCharmer = charmer.ToPlayer();

            if (playerCharmer)
            {
                switch (type)
                {
                case CharmType.Vehicle:
                    playerCharmer.SetClientControl(this, false);
                    playerCharmer.SetClientControl(charmer, true);
                    RemoveFlag(UnitFields.Flags, UnitFlags.PlayerControlled);
                    break;

                case CharmType.Possess:
                    playerCharmer.SetClientControl(this, false);
                    playerCharmer.SetClientControl(charmer, true);
                    charmer.RemoveFlag(UnitFields.Flags, UnitFlags.RemoveClientControl);
                    RemoveFlag(UnitFields.Flags, UnitFlags.PlayerControlled);
                    ClearUnitState(UnitState.Possessed);
                    break;

                case CharmType.Charm:
                    if (IsTypeId(TypeId.Unit) && charmer.GetClass() == Class.Warlock)
                    {
                        CreatureTemplate cinfo = ToCreature().GetCreatureTemplate();
                        if (cinfo != null && cinfo.CreatureType == CreatureType.Demon)
                        {
                            SetByteValue(UnitFields.Bytes0, 1, (byte)cinfo.UnitClass);
                            if (GetCharmInfo() != null)
                            {
                                GetCharmInfo().SetPetNumber(0, true);
                            }
                            else
                            {
                                Log.outError(LogFilter.Unit, "Aura:HandleModCharm: target={0} with typeid={1} has a charm aura but no charm info!", GetGUID(), GetTypeId());
                            }
                        }
                    }
                    break;

                case CharmType.Convert:
                    break;
                }
            }

            Player player = ToPlayer();

            if (player)
            {
                if (charmer.IsTypeId(TypeId.Unit)) // charmed by a creature, this means we had PlayerAI
                {
                    NeedChangeAI = true;
                    IsAIEnabled  = false;
                }
                player.SetClientControl(this, true);
            }

            // a guardian should always have charminfo
            if (playerCharmer && this != charmer.GetFirstControlled())
            {
                playerCharmer.SendRemoveControlBar();
            }
            else if (IsTypeId(TypeId.Player) || (IsTypeId(TypeId.Unit) && !IsGuardian()))
            {
                DeleteCharmInfo();
            }
        }
Пример #5
0
 public float GenerateBaseDamage(CreatureTemplate info)
 {
     return(BaseDamage[info.HealthScalingExpansion]);
 }
Пример #6
0
 public float GenerateArmor(CreatureTemplate info)
 {
     return((float)Math.Ceiling(BaseArmor * info.ModArmor));
 }
Пример #7
0
 // Helpers
 public uint GenerateHealth(CreatureTemplate info)
 {
     return((uint)Math.Ceiling(BaseHealth[info.HealthScalingExpansion] * info.ModHealth * info.ModHealthExtra));
 }
Пример #8
0
        public void RemoveCharmedBy(Unit charmer)
        {
            if (!IsCharmed())
            {
                return;
            }

            if (charmer)
            {
                Cypher.Assert(charmer == GetCharmer());
            }
            else
            {
                charmer = GetCharmer();
            }

            Cypher.Assert(charmer);

            CharmType type;

            if (HasUnitState(UnitState.Possessed))
            {
                type = CharmType.Possess;
            }
            else if (charmer && charmer.IsOnVehicle(this))
            {
                type = CharmType.Vehicle;
            }
            else
            {
                type = CharmType.Charm;
            }

            CastStop();
            CombatStop(); // @todo CombatStop(true) may cause crash (interrupt spells)

            if (_oldFactionId != 0)
            {
                SetFaction(_oldFactionId);
                _oldFactionId = 0;
            }
            else
            {
                RestoreFaction();
            }

            ///@todo Handle SLOT_IDLE motion resume
            GetMotionMaster().InitializeDefault();

            // Vehicle should not attack its passenger after he exists the seat
            if (type != CharmType.Vehicle)
            {
                LastCharmerGUID = charmer.GetGUID();
            }

            Cypher.Assert(type != CharmType.Possess || charmer.IsTypeId(TypeId.Player));
            Cypher.Assert(type != CharmType.Vehicle || (IsTypeId(TypeId.Unit) && IsVehicle()));

            charmer.SetCharm(this, false);

            Player playerCharmer = charmer.ToPlayer();

            if (playerCharmer)
            {
                switch (type)
                {
                case CharmType.Vehicle:
                    playerCharmer.SetClientControl(this, false);
                    playerCharmer.SetClientControl(charmer, true);
                    RemoveUnitFlag(UnitFlags.Possessed);
                    break;

                case CharmType.Possess:
                    ClearUnitState(UnitState.Possessed);
                    playerCharmer.SetClientControl(this, false);
                    playerCharmer.SetClientControl(charmer, true);
                    charmer.RemoveUnitFlag(UnitFlags.RemoveClientControl);
                    RemoveUnitFlag(UnitFlags.Possessed);
                    break;

                case CharmType.Charm:
                    if (IsTypeId(TypeId.Unit) && charmer.GetClass() == Class.Warlock)
                    {
                        CreatureTemplate cinfo = ToCreature().GetCreatureTemplate();
                        if (cinfo != null && cinfo.CreatureType == CreatureType.Demon)
                        {
                            SetClass((Class)cinfo.UnitClass);
                            if (GetCharmInfo() != null)
                            {
                                GetCharmInfo().SetPetNumber(0, true);
                            }
                            else
                            {
                                Log.outError(LogFilter.Unit, "Aura:HandleModCharm: target={0} with typeid={1} has a charm aura but no charm info!", GetGUID(), GetTypeId());
                            }
                        }
                    }
                    break;

                case CharmType.Convert:
                    break;
                }
            }

            Player player = ToPlayer();

            if (player != null)
            {
                player.SetClientControl(this, true);
            }

            if (playerCharmer && this != charmer.GetFirstControlled())
            {
                playerCharmer.SendRemoveControlBar();
            }

            // a guardian should always have charminfo
            if (!IsGuardian())
            {
                DeleteCharmInfo();
            }

            // reset confused movement for example
            ApplyControlStatesIfNeeded();

            if (!IsPlayer() || charmer.IsCreature())
            {
                UnitAI charmedAI = GetAI();
                if (charmedAI != null)
                {
                    charmedAI.OnCharmed(false); // AI will potentially schedule a charm ai update
                }
                else
                {
                    ScheduleAIChange();
                }
            }
        }
Пример #9
0
        public bool SetCharmedBy(Unit charmer, CharmType type, AuraApplication aurApp = null)
        {
            if (!charmer)
            {
                return(false);
            }

            // dismount players when charmed
            if (IsTypeId(TypeId.Player))
            {
                RemoveAurasByType(AuraType.Mounted);
            }

            if (charmer.IsTypeId(TypeId.Player))
            {
                charmer.RemoveAurasByType(AuraType.Mounted);
            }

            Cypher.Assert(type != CharmType.Possess || charmer.IsTypeId(TypeId.Player));
            Cypher.Assert((type == CharmType.Vehicle) == (GetVehicleKit() && GetVehicleKit().IsControllableVehicle()));

            Log.outDebug(LogFilter.Unit, "SetCharmedBy: charmer {0} (GUID {1}), charmed {2} (GUID {3}), type {4}.", charmer.GetEntry(), charmer.GetGUID().ToString(), GetEntry(), GetGUID().ToString(), type);

            if (this == charmer)
            {
                Log.outFatal(LogFilter.Unit, "Unit:SetCharmedBy: Unit {0} (GUID {1}) is trying to charm itself!", GetEntry(), GetGUID().ToString());
                return(false);
            }

            if (IsTypeId(TypeId.Player) && ToPlayer().GetTransport())
            {
                Log.outFatal(LogFilter.Unit, "Unit:SetCharmedBy: Player on transport is trying to charm {0} (GUID {1})", GetEntry(), GetGUID().ToString());
                return(false);
            }

            // Already charmed
            if (!GetCharmerGUID().IsEmpty())
            {
                Log.outFatal(LogFilter.Unit, "Unit:SetCharmedBy: {0} (GUID {1}) has already been charmed but {2} (GUID {3}) is trying to charm it!", GetEntry(), GetGUID().ToString(), charmer.GetEntry(), charmer.GetGUID().ToString());
                return(false);
            }

            CastStop();
            CombatStop(); // @todo CombatStop(true) may cause crash (interrupt spells)

            Player playerCharmer = charmer.ToPlayer();

            // Charmer stop charming
            if (playerCharmer)
            {
                playerCharmer.StopCastingCharm();
                playerCharmer.StopCastingBindSight();
            }

            // Charmed stop charming
            if (IsTypeId(TypeId.Player))
            {
                ToPlayer().StopCastingCharm();
                ToPlayer().StopCastingBindSight();
            }

            // StopCastingCharm may remove a possessed pet?
            if (!IsInWorld)
            {
                Log.outFatal(LogFilter.Unit, "Unit:SetCharmedBy: {0} (GUID {1}) is not in world but {2} (GUID {3}) is trying to charm it!", GetEntry(), GetGUID().ToString(), charmer.GetEntry(), charmer.GetGUID().ToString());
                return(false);
            }

            // charm is set by aura, and aura effect remove handler was called during apply handler execution
            // prevent undefined behaviour
            if (aurApp != null && aurApp.GetRemoveMode() != 0)
            {
                return(false);
            }

            _oldFactionId = GetFaction();
            SetFaction(charmer.GetFaction());

            // Pause any Idle movement
            PauseMovement(0, 0, false);

            // Remove any active voluntary movement
            GetMotionMaster().Clear(MovementGeneratorPriority.Normal);

            // Stop any remaining spline, if no involuntary movement is found
            Func <MovementGenerator, bool> criteria = movement => movement.Priority == MovementGeneratorPriority.Highest;

            if (!GetMotionMaster().HasMovementGenerator(criteria))
            {
                StopMoving();
            }

            // Set charmed
            charmer.SetCharm(this, true);

            Player player = ToPlayer();

            if (player)
            {
                if (player.IsAFK())
                {
                    player.ToggleAFK();
                }

                player.SetClientControl(this, false);
            }

            // charm is set by aura, and aura effect remove handler was called during apply handler execution
            // prevent undefined behaviour
            if (aurApp != null && aurApp.GetRemoveMode() != 0)
            {
                return(false);
            }

            // Pets already have a properly initialized CharmInfo, don't overwrite it.
            if (type != CharmType.Vehicle && GetCharmInfo() == null)
            {
                InitCharmInfo();
                if (type == CharmType.Possess)
                {
                    GetCharmInfo().InitPossessCreateSpells();
                }
                else
                {
                    GetCharmInfo().InitCharmCreateSpells();
                }
            }

            if (playerCharmer)
            {
                switch (type)
                {
                case CharmType.Vehicle:
                    AddUnitFlag(UnitFlags.Possessed);
                    playerCharmer.SetClientControl(this, true);
                    playerCharmer.VehicleSpellInitialize();
                    break;

                case CharmType.Possess:
                    AddUnitFlag(UnitFlags.Possessed);
                    charmer.AddUnitFlag(UnitFlags.RemoveClientControl);
                    playerCharmer.SetClientControl(this, true);
                    playerCharmer.PossessSpellInitialize();
                    AddUnitState(UnitState.Possessed);
                    break;

                case CharmType.Charm:
                    if (IsTypeId(TypeId.Unit) && charmer.GetClass() == Class.Warlock)
                    {
                        CreatureTemplate cinfo = ToCreature().GetCreatureTemplate();
                        if (cinfo != null && cinfo.CreatureType == CreatureType.Demon)
                        {
                            // to prevent client crash
                            SetClass(Class.Mage);

                            // just to enable stat window
                            if (GetCharmInfo() != null)
                            {
                                GetCharmInfo().SetPetNumber(Global.ObjectMgr.GeneratePetNumber(), true);
                            }

                            // if charmed two demons the same session, the 2nd gets the 1st one's name
                            SetPetNameTimestamp((uint)GameTime.GetGameTime());     // cast can't be helped
                        }
                    }
                    playerCharmer.CharmSpellInitialize();
                    break;

                default:
                case CharmType.Convert:
                    break;
                }
            }

            AddUnitState(UnitState.Charmed);

            if (!IsPlayer() || !charmer.IsPlayer())
            {
                // AI will schedule its own change if appropriate
                UnitAI ai = GetAI();
                if (ai != null)
                {
                    ai.OnCharmed(false);
                }
                else
                {
                    ScheduleAIChange();
                }
            }
            return(true);
        }