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); }
// @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); }
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); }
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(); } }
public float GenerateBaseDamage(CreatureTemplate info) { return(BaseDamage[info.HealthScalingExpansion]); }
public float GenerateArmor(CreatureTemplate info) { return((float)Math.Ceiling(BaseArmor * info.ModArmor)); }
// Helpers public uint GenerateHealth(CreatureTemplate info) { return((uint)Math.Ceiling(BaseHealth[info.HealthScalingExpansion] * info.ModHealth * info.ModHealthExtra)); }
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(); } } }
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); }