diff --git a/Source/Game/Entities/Creature/Creature.Fields.cs b/Source/Game/Entities/Creature/Creature.Fields.cs index 5efcb7ac9..7dea8c978 100644 --- a/Source/Game/Entities/Creature/Creature.Fields.cs +++ b/Source/Game/Entities/Creature/Creature.Fields.cs @@ -22,7 +22,7 @@ namespace Game.Entities long _lastDamagedTime; // Part of Evade mechanics MultiMap m_textRepeat = new(); - CreatureStaticFlagsHolder _staticFlags; + protected CreatureStaticFlagsHolder _staticFlags; // Regenerate health bool _regenerateHealth; // Set on creation diff --git a/Source/Game/Entities/Player/Player.Fields.cs b/Source/Game/Entities/Player/Player.Fields.cs index e1ca08ad1..b4e2b893f 100644 --- a/Source/Game/Entities/Player/Player.Fields.cs +++ b/Source/Game/Entities/Player/Player.Fields.cs @@ -109,6 +109,7 @@ namespace Game.Entities MultiMap m_overrideSpells = new(); public Spell m_spellModTakingSpell; uint m_oldpetspell; + ObjectGuid m_temporaryUnsummonedBattlePet; Dictionary m_storedAuraTeleportLocations = new(); SpellCastRequest _pendingSpellCastRequest; diff --git a/Source/Game/Entities/Player/Player.cs b/Source/Game/Entities/Player/Player.cs index ec91dd358..a647a3ca9 100644 --- a/Source/Game/Entities/Player/Player.cs +++ b/Source/Game/Entities/Player/Player.cs @@ -667,6 +667,7 @@ namespace Game.Entities StopCastingCharm(); StopCastingBindSight(); UnsummonPetTemporaryIfAny(); + UnsummonBattlePetTemporaryIfAny(); SetPower(PowerType.ComboPoints, 0); GetSession().DoLootReleaseAll(); m_lootRolls.Clear(); @@ -1079,6 +1080,35 @@ namespace Game.Entities m_temporaryUnsummonedPetNumber = 0; } + public void UnsummonBattlePetTemporaryIfAny(bool onFlyingMount = false) + { + Creature battlepet = GetSummonedBattlePet(); + if (battlepet == null || !battlepet.IsSummon()) + return; + + if (onFlyingMount && !battlepet.ToTempSummon().IsDismissedOnFlyingMount()) + return; + + if (battlepet.ToTempSummon().IsAutoResummoned()) + m_temporaryUnsummonedBattlePet = battlepet.GetBattlePetCompanionGUID(); + + GetSession().GetBattlePetMgr().DismissPet(); + } + + public void ResummonBattlePetTemporaryUnSummonedIfAny() + { + if (m_temporaryUnsummonedBattlePet.IsEmpty()) + return; + + // not resummon in not appropriate state + if (IsPetNeedBeTemporaryUnsummoned()) + return; + + GetSession().GetBattlePetMgr().SummonPet(m_temporaryUnsummonedBattlePet); + + m_temporaryUnsummonedBattlePet.Clear(); + } + public bool IsPetNeedBeTemporaryUnsummoned() { return !IsInWorld || !IsAlive() || HasUnitMovementFlag(MovementFlag.Flying) || HasExtraUnitMovementFlag2(MovementFlags3.AdvFlying); diff --git a/Source/Game/Entities/TemporarySummon.cs b/Source/Game/Entities/TemporarySummon.cs index d4665a585..5d0478eb7 100644 --- a/Source/Game/Entities/TemporarySummon.cs +++ b/Source/Game/Entities/TemporarySummon.cs @@ -181,7 +181,7 @@ namespace Game.Entities { if (IsTrigger() && m_spells[0] != 0) m_ControlledByPlayer = true; - + CreatureSummonedData summonedData = Global.ObjectMgr.GetCreatureSummonedData(GetEntry()); if (summonedData != null) { @@ -410,12 +410,12 @@ namespace Game.Entities return false; } - + public override string GetDebugInfo() { return $"{base.GetDebugInfo()}\nTempSummonType : {GetSummonType()} Summoner: {GetSummonerGUID()} Timer: {GetTimer()}"; } - + public override void SaveToDB(uint mapid, List spawnDifficulties) { } public ObjectGuid GetSummonerGUID() { return m_summonerGUID; } @@ -435,11 +435,31 @@ namespace Game.Entities public uint? GetCreatureIdVisibleToSummoner() { return m_creatureIdVisibleToSummoner; } public uint? GetDisplayIdVisibleToSummoner() { return m_displayIdVisibleToSummoner; } - + public bool CanFollowOwner() { return m_canFollowOwner; } public void SetCanFollowOwner(bool can) { m_canFollowOwner = can; } + public bool IsDismissedOnFlyingMount() + { + return !HasFlag(CreatureStaticFlags5.DontDismissOnFlyingMount); + } + + public void SetDontDismissOnFlyingMount(bool dontDismissOnFlyingMount) + { + _staticFlags.ApplyFlag(CreatureStaticFlags5.DontDismissOnFlyingMount, dontDismissOnFlyingMount); + } + + public bool IsAutoResummoned() + { + return !HasFlag(CreatureStaticFlags6.DoNotAutoResummon); + } + + public void SetDontAutoResummon(bool dontAutoResummon) + { + _staticFlags.ApplyFlag(CreatureStaticFlags6.DoNotAutoResummon, dontAutoResummon); + } + public SummonPropertiesRecord m_Properties; TempSummonType m_type; TimeSpan m_timer; diff --git a/Source/Game/Entities/Unit/Unit.Movement.cs b/Source/Game/Entities/Unit/Unit.Movement.cs index 673805074..5a9e7b9d8 100644 --- a/Source/Game/Entities/Unit/Unit.Movement.cs +++ b/Source/Game/Entities/Unit/Unit.Movement.cs @@ -1533,6 +1533,7 @@ namespace Game.Entities { player.EnablePetControlsOnDismount(); player.ResummonPetTemporaryUnSummonedIfAny(); + player.ResummonBattlePetTemporaryUnSummonedIfAny(); } } diff --git a/Source/Game/Handlers/MovementHandler.cs b/Source/Game/Handlers/MovementHandler.cs index 8d018e34c..3a858842d 100644 --- a/Source/Game/Handlers/MovementHandler.cs +++ b/Source/Game/Handlers/MovementHandler.cs @@ -139,7 +139,10 @@ namespace Game mover.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.LandingOrFlight); // Parachutes if (opcode == ClientOpcodes.MoveSetFly || opcode == ClientOpcodes.MoveSetAdvFly) + { _player.UnsummonPetTemporaryIfAny(); // always do the pet removal on current client activeplayer only + _player.UnsummonBattlePetTemporaryIfAny(true); + } movementInfo.Guid = mover.GetGUID(); movementInfo.Time = AdjustClientMovementTime(movementInfo.Time); @@ -408,6 +411,7 @@ namespace Game // resummon pet player.ResummonPetTemporaryUnSummonedIfAny(); + player.ResummonBattlePetTemporaryUnSummonedIfAny(); //lets process all delayed operations on successful teleport player.ProcessDelayedOperations();