diff --git a/Source/Game/Entities/Object/WorldObject.cs b/Source/Game/Entities/Object/WorldObject.cs index 6d3d4ccb7..89eeeeb8f 100644 --- a/Source/Game/Entities/Object/WorldObject.cs +++ b/Source/Game/Entities/Object/WorldObject.cs @@ -1776,6 +1776,9 @@ namespace Game.Entities public virtual float GetStationaryZ() { return GetPositionZ(); } public virtual float GetStationaryO() { return GetOrientation(); } + public virtual float GetCollisionHeight() { return 0.0f; } + public float GetMidsectionHeight() { return GetCollisionHeight() / 2.0f; } + public virtual bool IsNeverVisibleFor(WorldObject seer) { return !IsInWorld; } public virtual bool IsAlwaysVisibleFor(WorldObject seer) { return false; } public virtual bool IsInvisibleDueToDespawn() { return false; } @@ -1897,11 +1900,14 @@ namespace Game.Entities { float x, y, z; if (IsTypeId(TypeId.Player)) + { GetPosition(out x, out y, out z); + z += GetMidsectionHeight(); + } else GetHitSpherePointFor(new Position(ox, oy, oz), out x, out y, out z); - return GetMap().IsInLineOfSight(GetPhaseShift(), x, y, z + 2.0f, ox, oy, oz + 2.0f, checks, ignoreFlags); + return GetMap().IsInLineOfSight(GetPhaseShift(), x, y, z, ox, oy, oz, checks, ignoreFlags); } return true; @@ -1914,16 +1920,19 @@ namespace Game.Entities float x, y, z; if (obj.IsTypeId(TypeId.Player)) + { obj.GetPosition(out x, out y, out z); + z += GetMidsectionHeight(); + } else - obj.GetHitSpherePointFor(GetPosition(), out x, out y, out z); + obj.GetHitSpherePointFor(new (GetPositionX(), GetPositionY(), GetPositionZ() + GetMidsectionHeight()), out x, out y, out z); return IsWithinLOS(x, y, z, checks, ignoreFlags); } Position GetHitSpherePointFor(Position dest) { - Vector3 vThis = new Vector3(GetPositionX(), GetPositionY(), GetPositionZ()); + Vector3 vThis = new Vector3(GetPositionX(), GetPositionY(), GetPositionZ() + GetMidsectionHeight()); Vector3 vObj = new Vector3(dest.GetPositionX(), dest.GetPositionY(), dest.GetPositionZ()); Vector3 contactPoint = vThis + (vObj - vThis).directionOrZero() * Math.Min(dest.GetExactDist(GetPosition()), GetCombatReach()); diff --git a/Source/Game/Entities/Player/Player.cs b/Source/Game/Entities/Player/Player.cs index 518358973..266f7574c 100644 --- a/Source/Game/Entities/Player/Player.cs +++ b/Source/Game/Entities/Player/Player.cs @@ -4988,39 +4988,6 @@ namespace Game.Entities return true; } - public float GetCollisionHeight(bool mounted) - { - if (mounted) - { - var mountDisplayInfo = CliDB.CreatureDisplayInfoStorage.LookupByKey(GetMountDisplayId()); - if (mountDisplayInfo == null) - return GetCollisionHeight(false); - - var mountModelData = CliDB.CreatureModelDataStorage.LookupByKey(mountDisplayInfo.ModelID); - if (mountModelData == null) - return GetCollisionHeight(false); - - var displayInfo = CliDB.CreatureDisplayInfoStorage.LookupByKey(GetNativeDisplayId()); - Cypher.Assert(displayInfo != null); - var modelData = CliDB.CreatureModelDataStorage.LookupByKey(displayInfo.ModelID); - Cypher.Assert(modelData != null); - - float scaleMod = GetObjectScale(); // 99% sure about this - - return scaleMod * mountModelData.MountHeight + modelData.CollisionHeight * 0.5f; - } - else - { - //! Dismounting case - use basic default model data - var displayInfo = CliDB.CreatureDisplayInfoStorage.LookupByKey(GetNativeDisplayId()); - Cypher.Assert(displayInfo != null); - var modelData = CliDB.CreatureModelDataStorage.LookupByKey(displayInfo.ModelID); - Cypher.Assert(modelData != null); - - return modelData.CollisionHeight; - } - } - // Used in triggers for check "Only to targets that grant experience or honor" req public bool IsHonorOrXPTarget(Unit victim) { @@ -6388,7 +6355,7 @@ namespace Game.Entities SetBoundingRadius(scale * SharedConst.DefaultPlayerBoundingRadius); SetCombatReach(scale * SharedConst.DefaultPlayerCombatReach); if (IsInWorld) - SendMovementSetCollisionHeight(scale * GetCollisionHeight(IsMounted()), UpdateCollisionHeightReason.Scale); + SendMovementSetCollisionHeight(scale * GetCollisionHeight(), UpdateCollisionHeightReason.Scale); } public uint GetXP() { return m_activePlayerData.XP; } diff --git a/Source/Game/Entities/Unit/Unit.Movement.cs b/Source/Game/Entities/Unit/Unit.Movement.cs index 3bd891077..dda985d8c 100644 --- a/Source/Game/Entities/Unit/Unit.Movement.cs +++ b/Source/Game/Entities/Unit/Unit.Movement.cs @@ -1323,7 +1323,7 @@ namespace Game.Entities if (charm.GetTypeId() == TypeId.Unit) charm.AddUnitFlag(UnitFlags.Stunned); - player.SendMovementSetCollisionHeight(player.GetCollisionHeight(true), UpdateCollisionHeightReason.Mount); + player.SendMovementSetCollisionHeight(player.GetCollisionHeight(), UpdateCollisionHeightReason.Mount); } RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Mount); @@ -1339,7 +1339,7 @@ namespace Game.Entities Player thisPlayer = ToPlayer(); if (thisPlayer != null) - thisPlayer.SendMovementSetCollisionHeight(thisPlayer.GetCollisionHeight(false), UpdateCollisionHeightReason.Mount); + thisPlayer.SendMovementSetCollisionHeight(thisPlayer.GetCollisionHeight(), UpdateCollisionHeightReason.Mount); // dismount as a vehicle if (IsTypeId(TypeId.Player) && GetVehicleKit() != null) diff --git a/Source/Game/Entities/Unit/Unit.cs b/Source/Game/Entities/Unit/Unit.cs index 8e4b896f5..bd27c8fc1 100644 --- a/Source/Game/Entities/Unit/Unit.cs +++ b/Source/Game/Entities/Unit/Unit.cs @@ -782,6 +782,32 @@ namespace Game.Entities public void SetHoverHeight(float hoverHeight) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.HoverHeight), hoverHeight); } + public override float GetCollisionHeight() + { + float scaleMod = GetObjectScale(); // 99% sure about this + + if (IsMounted()) + { + var mountDisplayInfo = CliDB.CreatureDisplayInfoStorage.LookupByKey(GetMountDisplayId()); + if (mountDisplayInfo != null) + { + var mountModelData = CliDB.CreatureModelDataStorage.LookupByKey(mountDisplayInfo.ModelID); + if (mountModelData != null) + { + var displayInfo = CliDB.CreatureDisplayInfoStorage.LookupByKey(GetNativeDisplayId()); + var modelData = CliDB.CreatureModelDataStorage.LookupByKey(displayInfo.ModelID); + return scaleMod * (mountModelData.MountHeight + modelData.CollisionHeight * 0.5f); + } + } + } + + //! Dismounting case - use basic default model data + var defaultDisplayInfo = CliDB.CreatureDisplayInfoStorage.LookupByKey(GetNativeDisplayId()); + var defaultModelData = CliDB.CreatureModelDataStorage.LookupByKey(defaultDisplayInfo.ModelID); + + return scaleMod * defaultModelData.CollisionHeight; + } + public Guardian GetGuardianPet() { ObjectGuid pet_guid = GetPetGUID(); diff --git a/Source/Game/Movement/MotionMaster.cs b/Source/Game/Movement/MotionMaster.cs index 05e48b8a3..36a67aa9e 100644 --- a/Source/Game/Movement/MotionMaster.cs +++ b/Source/Game/Movement/MotionMaster.cs @@ -379,11 +379,11 @@ namespace Game.Movement if (_owner.IsTypeId(TypeId.Player)) return; - float x, y, z; - float moveTimeHalf = (float)(speedZ / gravity); float dist = 2 * moveTimeHalf * speedXY; - _owner.GetClosePoint(out x, out y, out z, _owner.GetCombatReach(), dist, angle); + _owner.GetNearPoint2D(out float x, out float y, dist, _owner.GetOrientation() + angle); + float z = _owner.GetPositionZ() + _owner.GetMidsectionHeight(); + _owner.UpdateAllowedPositionZ(x, y, ref z); MoveJump(x, y, z, 0.0f, speedXY, speedZ); } diff --git a/Source/Game/Spells/Auras/AuraEffect.cs b/Source/Game/Spells/Auras/AuraEffect.cs index 38702cb75..1fbcc685e 100644 --- a/Source/Game/Spells/Auras/AuraEffect.cs +++ b/Source/Game/Spells/Auras/AuraEffect.cs @@ -1394,7 +1394,7 @@ namespace Game.Spells Player playerTarget = target.ToPlayer(); if (playerTarget != null) { - playerTarget.SendMovementSetCollisionHeight(playerTarget.GetCollisionHeight(false), UpdateCollisionHeightReason.Force); + playerTarget.SendMovementSetCollisionHeight(playerTarget.GetCollisionHeight(), UpdateCollisionHeightReason.Force); playerTarget.InitDataForForm(); } else