From 4b2675944b228a92b00b4da5dedc2cbea72b95e3 Mon Sep 17 00:00:00 2001 From: hondacrx Date: Wed, 13 Dec 2017 14:34:37 -0500 Subject: [PATCH] Core/Auras: Updated mount capability check and implemented SPELL_AURA_MOUNT_RESTRICTIONS --- Source/Framework/Constants/CliDBConst.cs | 17 +++-- .../Constants/Spells/SpellAuraConst.cs | 2 +- Source/Game/DataStorage/DB2Manager.cs | 17 +++++ Source/Game/Entities/Player/Player.cs | 7 -- Source/Game/Entities/Unit/Unit.Movement.cs | 69 +++++++++++++++---- Source/Game/Spells/Auras/AuraEffect.cs | 2 +- Source/Game/Spells/SpellInfo.cs | 13 ++-- 7 files changed, 93 insertions(+), 34 deletions(-) diff --git a/Source/Framework/Constants/CliDBConst.cs b/Source/Framework/Constants/CliDBConst.cs index 80d883f65..2ae75dc30 100644 --- a/Source/Framework/Constants/CliDBConst.cs +++ b/Source/Framework/Constants/CliDBConst.cs @@ -1333,12 +1333,21 @@ namespace Framework.Constants CannotExtend = 0x10 } + public enum AreaMountFlags + { + GroundAllowed = 0x1, + FlyingAllowed = 0x2, + FloatAllowed = 0x4, + UnderwaterAllowed = 0x8 + } + public enum MountCapabilityFlags : byte { - Unk1 = 0x1, - Unk2 = 0x2, - CanPitch = 0x4, // client checks MOVEMENTFLAG2_FULL_SPEED_PITCHING - CanSwim = 0x8, // client checks MOVEMENTFLAG_SWIMMING + Ground = 0x1, + Flying = 0x2, + Float = 0x4, + Underwater = 0x8, + IgnoreRestrictions = 0x20 } public enum MountFlags diff --git a/Source/Framework/Constants/Spells/SpellAuraConst.cs b/Source/Framework/Constants/Spells/SpellAuraConst.cs index 6b1eab93e..694fbccd0 100644 --- a/Source/Framework/Constants/Spells/SpellAuraConst.cs +++ b/Source/Framework/Constants/Spells/SpellAuraConst.cs @@ -357,7 +357,7 @@ namespace Framework.Constants OverrideActionbarSpellsTriggered = 333, // Spells cast with this override have no cast time or power cost ModBlind = 334, // Nyi Unk335 = 335, - ModFlyingRestrictions = 336, // Nyi + MountRestrictions = 336, ModVendorItemsPrices = 337, ModDurabilityLoss = 338, IncreaseSkillGainChance = 339, // Nyi diff --git a/Source/Game/DataStorage/DB2Manager.cs b/Source/Game/DataStorage/DB2Manager.cs index ed85bbf6d..bed63dbf4 100644 --- a/Source/Game/DataStorage/DB2Manager.cs +++ b/Source/Game/DataStorage/DB2Manager.cs @@ -485,6 +485,23 @@ namespace Game.DataStorage return _areaGroupMembers.LookupByKey(areaGroupId); } + public bool IsInArea(uint objectAreaId, uint areaId) + { + do + { + if (objectAreaId == areaId) + return true; + + AreaTableRecord objectArea = CliDB.AreaTableStorage.LookupByKey(objectAreaId); + if (objectArea == null) + break; + + objectAreaId = objectArea.ParentAreaID; + } while (objectAreaId != 0); + + return false; + } + public List GetArtifactPowers(byte artifactId) { return _artifactPowers.LookupByKey(artifactId); diff --git a/Source/Game/Entities/Player/Player.cs b/Source/Game/Entities/Player/Player.cs index 90846cc96..7c54b3aae 100644 --- a/Source/Game/Entities/Player/Player.cs +++ b/Source/Game/Entities/Player/Player.cs @@ -7215,13 +7215,6 @@ namespace Game.Entities public bool CanTameExoticPets() { return IsGameMaster() || HasAuraType(AuraType.AllowTamePetType); } - public bool CanFlyInZone(uint mapid, uint zone) - { - // continent checked in SpellInfo.CheckLocation at cast and area update - uint v_map = Global.DB2Mgr.GetVirtualMapForMapAndZone(mapid, zone); - return v_map != 571 || HasSpell(54197); // 54197 = Cold Weather Flying - } - void SendAttackSwingDeadTarget() { SendPacket(new AttackSwingError(AttackSwingErr.DeadTarget)); } void SendAttackSwingCantAttack() { SendPacket(new AttackSwingError(AttackSwingErr.CantAttack)); } public void SendAttackSwingNotInRange() { SendPacket(new AttackSwingError(AttackSwingErr.NotInRange)); } diff --git a/Source/Game/Entities/Unit/Unit.Movement.cs b/Source/Game/Entities/Unit/Unit.Movement.cs index c143174ed..47f46312f 100644 --- a/Source/Game/Entities/Unit/Unit.Movement.cs +++ b/Source/Game/Entities/Unit/Unit.Movement.cs @@ -24,6 +24,7 @@ using Game.Movement; using Game.Network.Packets; using System; using System.Collections.Generic; +using Game.Spells; namespace Game.Entities { @@ -650,12 +651,32 @@ namespace Game.Entities if (capabilities == null) return null; - uint zoneId, areaId; - GetZoneAndAreaId(out zoneId, out areaId); + uint areaId = GetAreaId(); uint ridingSkill = 5000; + AreaMountFlags mountFlags = 0; + bool isSubmerged = false; + bool isInWater = false; + if (IsTypeId(TypeId.Player)) ridingSkill = ToPlayer().GetSkillValue(SkillType.Riding); + if (HasAuraType(AuraType.MountRestrictions)) + { + foreach (AuraEffect auraEffect in GetAuraEffectsByType(AuraType.MountRestrictions)) + mountFlags |= (AreaMountFlags)auraEffect.GetMiscValue(); + } + else + { + AreaTableRecord areaTable = CliDB.AreaTableStorage.LookupByKey(areaId); + if (areaTable != null) + mountFlags = (AreaMountFlags)areaTable.MountFlags; + } + + LiquidData liquid; + ZLiquidStatus liquidStatus = GetMap().getLiquidStatus(GetPositionX(), GetPositionY(), GetPositionZ(), MapConst.MapAllLiquidTypes, out liquid); + isSubmerged = liquidStatus.HasAnyFlag(ZLiquidStatus.UnderWater) || HasUnitMovementFlag(MovementFlag.Swimming); + isInWater = liquidStatus.HasAnyFlag(ZLiquidStatus.InWater | ZLiquidStatus.UnderWater); + foreach (var mountTypeXCapability in capabilities) { MountCapabilityRecord mountCapability = CliDB.MountCapabilityStorage.LookupByKey(mountTypeXCapability.MountCapabilityID); @@ -665,32 +686,50 @@ namespace Game.Entities if (ridingSkill < mountCapability.RequiredRidingSkill) continue; - if (HasUnitMovementFlag2(MovementFlag2.FullSpeedPitching)) + if (!mountCapability.Flags.HasAnyFlag(MountCapabilityFlags.IgnoreRestrictions)) { - if (!mountCapability.Flags.HasAnyFlag(MountCapabilityFlags.CanPitch)) + if (mountCapability.Flags.HasAnyFlag(MountCapabilityFlags.Ground) && !mountFlags.HasAnyFlag(AreaMountFlags.GroundAllowed)) continue; - } - else if (HasUnitMovementFlag(MovementFlag.Swimming)) - { - if (!mountCapability.Flags.HasAnyFlag(MountCapabilityFlags.CanSwim)) + if (mountCapability.Flags.HasAnyFlag(MountCapabilityFlags.Flying) && !mountFlags.HasAnyFlag(AreaMountFlags.FlyingAllowed)) continue; - } - else if (!mountCapability.Flags.HasAnyFlag(MountCapabilityFlags.Unk1)) // unknown flags, checked in 4.2.2 14545 client - { - if (!mountCapability.Flags.HasAnyFlag(MountCapabilityFlags.Unk2)) + if (mountCapability.Flags.HasAnyFlag(MountCapabilityFlags.Float) && !mountFlags.HasAnyFlag(AreaMountFlags.FloatAllowed)) + continue; + if (mountCapability.Flags.HasAnyFlag(MountCapabilityFlags.Underwater) && !mountFlags.HasAnyFlag(AreaMountFlags.UnderwaterAllowed)) continue; } - if (mountCapability.RequiredMap != -1 && (GetMapId()) != mountCapability.RequiredMap) + if (!isSubmerged) + { + if (!isInWater) + { + // player is completely out of water + if (!mountCapability.Flags.HasAnyFlag(MountCapabilityFlags.Ground)) + continue; + } + else if (!mountCapability.Flags.HasAnyFlag(MountCapabilityFlags.Underwater)) + continue; + } + else if (isInWater) + { + if (!mountCapability.Flags.HasAnyFlag(MountCapabilityFlags.Underwater)) + continue; + } + else if (!mountCapability.Flags.HasAnyFlag(MountCapabilityFlags.Float)) continue; - if (mountCapability.RequiredArea != 0 && (mountCapability.RequiredArea != zoneId && mountCapability.RequiredArea != areaId)) + if (mountCapability.RequiredMap != -1 && + GetMapId() != mountCapability.RequiredMap && + GetMap().GetEntry().CosmeticParentMapID != mountCapability.RequiredMap && + GetMap().GetEntry().ParentMapID != mountCapability.RequiredMap) + continue; + + if (mountCapability.RequiredArea != 0 && !Global.DB2Mgr.IsInArea(areaId, mountCapability.RequiredArea)) continue; if (mountCapability.RequiredAura != 0 && !HasAura(mountCapability.RequiredAura)) continue; - if (mountCapability.RequiredSpell != 0 && (!IsTypeId(TypeId.Player) || !ToPlayer().HasSpell(mountCapability.RequiredSpell))) + if (mountCapability.RequiredSpell != 0 && !HasSpell(mountCapability.RequiredSpell)) continue; return mountCapability; diff --git a/Source/Game/Spells/Auras/AuraEffect.cs b/Source/Game/Spells/Auras/AuraEffect.cs index cf0f100de..83759ff5b 100644 --- a/Source/Game/Spells/Auras/AuraEffect.cs +++ b/Source/Game/Spells/Auras/AuraEffect.cs @@ -1025,7 +1025,7 @@ namespace Game.Spells [AuraEffectHandler(AuraType.Unk324)] [AuraEffectHandler(AuraType.ModBlind)] [AuraEffectHandler(AuraType.Unk335)] - [AuraEffectHandler(AuraType.ModFlyingRestrictions)] + [AuraEffectHandler(AuraType.MountRestrictions)] [AuraEffectHandler(AuraType.IncreaseSkillGainChance)] [AuraEffectHandler(AuraType.ModResurrectedHealthByGuildMember)] [AuraEffectHandler(AuraType.ModAutoattackDamage)] diff --git a/Source/Game/Spells/SpellInfo.cs b/Source/Game/Spells/SpellInfo.cs index a4e8986ec..83c832be9 100644 --- a/Source/Game/Spells/SpellInfo.cs +++ b/Source/Game/Spells/SpellInfo.cs @@ -896,14 +896,15 @@ namespace Game.Spells switch (effect.ApplyAuraName) { - case AuraType.Fly: + case AuraType.ModShapeshift: { - var bounds = Global.SpellMgr.GetSkillLineAbilityMapBounds(Id); - foreach (var skillRecord in bounds) + SpellShapeshiftFormRecord spellShapeshiftForm = CliDB.SpellShapeshiftFormStorage.LookupByKey(effect.MiscValue); + if (spellShapeshiftForm != null) { - if (skillRecord.SkillLine == (int)SkillType.Mounts) - if (!player.CanFlyInZone(map_id, zone_id)) - return SpellCastResult.IncorrectArea; + uint mountType = spellShapeshiftForm.MountTypeID; + if (mountType != 0) + if (player.GetMountCapability(mountType) == null) + return SpellCastResult.NotHere; } break; }