diff --git a/Source/Framework/Constants/SharedConst.cs b/Source/Framework/Constants/SharedConst.cs index e0e966bbb..126032366 100644 --- a/Source/Framework/Constants/SharedConst.cs +++ b/Source/Framework/Constants/SharedConst.cs @@ -245,6 +245,8 @@ namespace Framework.Constants public const int WorldTrigger = 12999; + public const uint DisplayIdHiddenMount = 73200; + public static float[] baseMoveSpeed = { 2.5f, // MOVE_WALK diff --git a/Source/Game/Entities/Player/Player.Map.cs b/Source/Game/Entities/Player/Player.Map.cs index 3a6d69344..98da9ec14 100644 --- a/Source/Game/Entities/Player/Player.Map.cs +++ b/Source/Game/Entities/Player/Player.Map.cs @@ -148,6 +148,8 @@ namespace Game.Entities PushQuests(); UpdateCriteria(CriteriaType.EnterTopLevelArea, newArea); + + UpdateMountCapability(); } public void UpdateZone(uint newZone, uint newArea) diff --git a/Source/Game/Entities/Player/Player.Spells.cs b/Source/Game/Entities/Player/Player.Spells.cs index a40056538..406b70209 100644 --- a/Source/Game/Entities/Player/Player.Spells.cs +++ b/Source/Game/Entities/Player/Player.Spells.cs @@ -1069,7 +1069,11 @@ namespace Game.Entities LearnSkillRewardedSpells(id, newVal); // if skill value is going up, update enchantments after setting the new value if (newVal > currVal) + { UpdateSkillEnchantments(id, currVal, (ushort)newVal); + if (id == (uint)SkillType.Riding) + UpdateMountCapability(); + } UpdateCriteria(CriteriaType.SkillRaised, id); UpdateCriteria(CriteriaType.AchieveSkillStep, id); diff --git a/Source/Game/Entities/Unit/Unit.Movement.cs b/Source/Game/Entities/Unit/Unit.Movement.cs index 279842583..4c8af14c6 100644 --- a/Source/Game/Entities/Unit/Unit.Movement.cs +++ b/Source/Game/Entities/Unit/Unit.Movement.cs @@ -742,7 +742,8 @@ namespace Game.Entities if (!mountCapability.Flags.HasAnyFlag(MountCapabilityFlags.Ground)) continue; } - else if (!mountCapability.Flags.HasAnyFlag(MountCapabilityFlags.Underwater)) + // player is on water surface + else if (!mountCapability.Flags.HasAnyFlag(MountCapabilityFlags.Float)) continue; } else if (isInWater) @@ -783,7 +784,25 @@ namespace Game.Entities return null; } - public override void ProcessPositionDataChanged(PositionFullTerrainStatus data) + public void UpdateMountCapability() + { + var mounts = GetAuraEffectsByType(AuraType.Mounted); + foreach (AuraEffect aurEff in mounts) + { + aurEff.RecalculateAmount(); + if (aurEff.GetAmount() == 0) + aurEff.GetBase().Remove(); + else + { + var capability = CliDB.MountCapabilityStorage.LookupByKey(aurEff.GetAmount()); + if (capability != null) // aura may get removed by interrupt flag, reapply + if (!HasAura(capability.ModSpellAuraID)) + CastSpell(this, capability.ModSpellAuraID, new CastSpellExtraArgs(aurEff)); + } + } + } + + public override void ProcessPositionDataChanged(PositionFullTerrainStatus data) { base.ProcessPositionDataChanged(data); ProcessTerrainStatusUpdate(data.LiquidStatus, data.LiquidInfo); @@ -800,7 +819,7 @@ namespace Game.Entities public virtual void ProcessTerrainStatusUpdate(ZLiquidStatus status, Optional liquidData) { - if (IsFlying() || !IsControlledByPlayer()) + if (!IsControlledByPlayer()) return; SetInWater(status.HasAnyFlag(ZLiquidStatus.Swimming)); @@ -817,6 +836,9 @@ namespace Game.Entities if (curLiquid != null && curLiquid.SpellID != 0 && (!player || !player.IsGameMaster())) CastSpell(this, curLiquid.SpellID, true); _lastLiquid = curLiquid; + + // mount capability depends on liquid state change + UpdateMountCapability(); } } diff --git a/Source/Game/Spells/Auras/AuraEffect.cs b/Source/Game/Spells/Auras/AuraEffect.cs index 1dea1e956..fd5b0094e 100644 --- a/Source/Game/Spells/Auras/AuraEffect.cs +++ b/Source/Game/Spells/Auras/AuraEffect.cs @@ -107,10 +107,7 @@ namespace Game.Spells var mountCapability = GetBase().GetUnitOwner().GetMountCapability(mountType); if (mountCapability != null) - { amount = (int)mountCapability.Id; - m_canBeRecalculated = false; - } break; case AuraType.ShowConfirmationPromptWithDifficulty: if (caster) @@ -843,7 +840,7 @@ namespace Game.Spells public int GetPeriodicTimer() { return _periodicTimer; } public void SetPeriodicTimer(int periodicTimer) { _periodicTimer = periodicTimer; } - void RecalculateAmount(AuraEffect triggeredBy = null) + public void RecalculateAmount(AuraEffect triggeredBy = null) { if (!CanBeRecalculated()) return; @@ -2053,73 +2050,76 @@ namespace Game.Spells [AuraEffectHandler(AuraType.Mounted)] void HandleAuraMounted(AuraApplication aurApp, AuraEffectHandleModes mode, bool apply) { - if (!mode.HasAnyFlag(AuraEffectHandleModes.SendForClientMask)) + if (!mode.HasAnyFlag(AuraEffectHandleModes.ChangeAmountSendForClientMask)) return; Unit target = aurApp.GetTarget(); if (apply) { - uint creatureEntry = (uint)GetMiscValue(); - uint displayId = 0; - uint vehicleId = 0; - - MountRecord mountEntry = Global.DB2Mgr.GetMount(GetId()); - if (mountEntry != null) + if (mode.HasAnyFlag(AuraEffectHandleModes.SendForClientMask)) { - var mountDisplays = Global.DB2Mgr.GetMountDisplays(mountEntry.Id); - if (mountDisplays != null) + uint creatureEntry = (uint)GetMiscValue(); + uint displayId = 0; + uint vehicleId = 0; + + var mountEntry = Global.DB2Mgr.GetMount(GetId()); + if (mountEntry != null) { - if (mountEntry.IsSelfMount()) + var mountDisplays = Global.DB2Mgr.GetMountDisplays(mountEntry.Id); + if (mountDisplays != null) { - displayId = 73200; //DisplayId: HiddenMount - } - else - { - List usableDisplays = mountDisplays.Where(mountDisplay => + if (mountEntry.IsSelfMount()) { - Player playerTarget = target.ToPlayer(); - if (playerTarget) + displayId = SharedConst.DisplayIdHiddenMount; + } + else + { + var usableDisplays = mountDisplays.Where(mountDisplay => { - PlayerConditionRecord playerCondition = CliDB.PlayerConditionStorage.LookupByKey(mountDisplay.PlayerConditionID); - if (playerCondition != null) - return ConditionManager.IsPlayerMeetingCondition(playerTarget, playerCondition); - } + Player playerTarget = target.ToPlayer(); + if (playerTarget != null) + { + var playerCondition = CliDB.PlayerConditionStorage.LookupByKey(mountDisplay.PlayerConditionID); + if (playerCondition != null) + return ConditionManager.IsPlayerMeetingCondition(playerTarget, playerCondition); + } - return true; - }).ToList(); + return true; + }).ToList(); - if (!usableDisplays.Empty()) - displayId = usableDisplays.SelectRandom().CreatureDisplayInfoID; + if (!usableDisplays.Empty()) + displayId = usableDisplays.SelectRandom().CreatureDisplayInfoID; + } } + // TODO: CREATE TABLE mount_vehicle (mountId, vehicleCreatureId) for future mounts that are vehicles (new mounts no longer have proper data in MiscValue) + //if (MountVehicle const* mountVehicle = sObjectMgr->GetMountVehicle(mountEntry->Id)) + // creatureEntry = mountVehicle->VehicleCreatureId; } - // TODO: CREATE TABLE mount_vehicle (mountId, vehicleCreatureId) for future mounts that are vehicles (new mounts no longer have proper data in MiscValue) - //if (MountVehicle const* mountVehicle = sObjectMgr.GetMountVehicle(mountEntry.Id)) - // creatureEntry = mountVehicle.VehicleCreatureId; - } - CreatureTemplate creatureInfo = Global.ObjectMgr.GetCreatureTemplate(creatureEntry); - if (creatureInfo != null) - { - vehicleId = creatureInfo.VehicleId; - - if (displayId == 0) + CreatureTemplate creatureInfo = Global.ObjectMgr.GetCreatureTemplate(creatureEntry); + if (creatureInfo != null) { - CreatureModel model = ObjectManager.ChooseDisplayId(creatureInfo); - Global.ObjectMgr.GetCreatureModelRandomGender(ref model, creatureInfo); - displayId = model.CreatureDisplayID; + vehicleId = creatureInfo.VehicleId; + + if (displayId == 0) + { + CreatureModel model = ObjectManager.ChooseDisplayId(creatureInfo); + Global.ObjectMgr.GetCreatureModelRandomGender(ref model, creatureInfo); + displayId = model.CreatureDisplayID; + } + + //some spell has one aura of mount and one of vehicle + foreach (SpellEffectInfo effect in GetSpellInfo().GetEffects()) + if (effect.IsEffect(SpellEffectName.Summon) && effect.MiscValue == GetMiscValue()) + displayId = 0; } - //some spell has one aura of mount and one of vehicle - foreach (var spellEffectInfo in GetSpellInfo().GetEffects()) - if (spellEffectInfo.IsEffect(SpellEffectName.Summon) && spellEffectInfo.MiscValue == GetMiscValue()) - displayId = 0; + target.Mount(displayId, vehicleId, creatureEntry); } - target.Mount(displayId, vehicleId, creatureEntry); - // cast speed aura - if (mode.HasAnyFlag(AuraEffectHandleModes.Real)) + if (mode.HasAnyFlag(AuraEffectHandleModes.ChangeAmountMask)) { var mountCapability = CliDB.MountCapabilityStorage.LookupByKey(GetAmount()); if (mountCapability != null) @@ -2128,14 +2128,17 @@ namespace Game.Spells } else { - target.Dismount(); + if (mode.HasAnyFlag(AuraEffectHandleModes.SendForClientMask)) + target.Dismount(); + //some mounts like Headless Horseman's Mount or broom stick are skill based spell // need to remove ALL arura related to mounts, this will stop client crash with broom stick // and never endless flying after using Headless Horseman's Mount if (mode.HasAnyFlag(AuraEffectHandleModes.Real)) - { target.RemoveAurasByType(AuraType.Mounted); + if (mode.HasAnyFlag(AuraEffectHandleModes.ChangeAmountMask)) + { // remove speed aura var mountCapability = CliDB.MountCapabilityStorage.LookupByKey(GetAmount()); if (mountCapability != null) @@ -5759,6 +5762,15 @@ namespace Game.Spells playerTarget.RemoveStoredAuraTeleportLocation(GetSpellInfo().Id); } + [AuraEffectHandler(AuraType.MountRestrictions)] + void HandleMountRestrictions(AuraApplication aurApp, AuraEffectHandleModes mode, bool apply) + { + if (!mode.HasAnyFlag(AuraEffectHandleModes.Real)) + return; + + aurApp.GetTarget().UpdateMountCapability(); + } + [AuraEffectHandler(AuraType.CosmeticMounted)] void HandleCosmeticMounted(AuraApplication aurApp, AuraEffectHandleModes mode, bool apply) { diff --git a/Source/Scripts/Spells/Generic.cs b/Source/Scripts/Spells/Generic.cs index 094053dd9..768933269 100644 --- a/Source/Scripts/Spells/Generic.cs +++ b/Source/Scripts/Spells/Generic.cs @@ -330,8 +330,6 @@ namespace Scripts.Spells.Generic //ServiceUniform public const uint GoblinMale = 31002; public const uint GoblinFemale = 31003; - - public const uint HiddenMount = 73200; } struct TextIds @@ -2586,7 +2584,7 @@ namespace Scripts.Spells.Generic { public override bool Validate(SpellInfo spellInfo) { - if (!CliDB.CreatureDisplayInfoStorage.ContainsKey(ModelIds.HiddenMount)) + if (!CliDB.CreatureDisplayInfoStorage.ContainsKey(SharedConst.DisplayIdHiddenMount)) return false; return true; } @@ -2596,7 +2594,7 @@ namespace Scripts.Spells.Generic Unit target = GetTarget(); PreventDefaultAction(); - target.Mount(ModelIds.HiddenMount, 0, 0); + target.Mount(SharedConst.DisplayIdHiddenMount, 0, 0); // cast speed aura MountCapabilityRecord mountCapability = CliDB.MountCapabilityStorage.LookupByKey(aurEff.GetAmount());