aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy <Golrag@users.noreply.github.com>2019-04-07 20:15:40 +0200
committerGiacomo Pozzoni <giacomopoz@gmail.com>2019-04-07 20:15:40 +0200
commit9fcbd8f15d249070aabc25d48df86681e8ec3d11 (patch)
tree33b077329695d07b6592e47b0d8aeb3a5c58a72d
parent73e3fdc8b4545cca52b66032a5f2465183d14c71 (diff)
Core/Movement: Fix some undermap issues with random movement/fear/blink (#22937)
* Core/Movement: - Only move to point if there is a path that is not a shortcut (which will make the unit move through terrain) - Added new function to check if there is a vmap floor without search distance - Units that can fly, are underground but far above the vmap floor will stay underground (bronze drakes in tanaris) - Don't remove PATHFIND_SHORTCUT from path type in some cases * Core/Object: Ignore UpdateAllowedPositionZ for flying units. - This will make flying units go through mountains instead of going to the top and back to the bottom to reach you. * Core/Object: Revert some changes and let MovePositionToFirstCollision deal with a position without ground * Missing groundZ change for objects on transport * use CanFly instead of IsFlying
-rw-r--r--src/server/game/Entities/Object/Object.cpp35
-rw-r--r--src/server/game/Entities/Object/Object.h2
-rw-r--r--src/server/game/Maps/Map.cpp25
-rw-r--r--src/server/game/Maps/Map.h1
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp2
-rw-r--r--src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp2
-rw-r--r--src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp2
-rw-r--r--src/server/game/Movement/PathGenerator.cpp4
-rw-r--r--src/server/game/Spells/Spell.cpp3
9 files changed, 56 insertions, 20 deletions
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 4d605a6afd3..bd3d20f9ff2 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -1414,11 +1414,16 @@ void WorldObject::UpdateGroundPositionZ(float x, float y, float &z) const
z = new_z + (isType(TYPEMASK_UNIT) ? static_cast<Unit const*>(this)->GetHoverOffset() : 0.0f);
}
-void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
+void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z, float* groundZ) const
{
// TODO: Allow transports to be part of dynamic vmap tree
if (GetTransport())
+ {
+ if (groundZ)
+ *groundZ = z;
+
return;
+ }
if (Unit const* unit = ToUnit())
{
@@ -1444,12 +1449,18 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
else if (z < ground_z)
z = ground_z;
}
+
+ if (groundZ)
+ *groundZ = ground_z;
}
else
{
float ground_z = GetMapHeight(x, y, z) + unit->GetHoverOffset();
if (z < ground_z)
z = ground_z;
+
+ if (groundZ)
+ *groundZ = ground_z;
}
}
else
@@ -1457,6 +1468,9 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
float ground_z = GetMapHeight(x, y, z);
if (ground_z > INVALID_HEIGHT)
z = ground_z;
+
+ if (groundZ)
+ *groundZ = ground_z;
}
}
@@ -3283,10 +3297,27 @@ void WorldObject::MovePositionToFirstCollision(Position &pos, float dist, float
}
}
+ float groundZ = VMAP_INVALID_HEIGHT_VALUE;
Trinity::NormalizeMapCoord(pos.m_positionX);
Trinity::NormalizeMapCoord(pos.m_positionY);
- UpdateAllowedPositionZ(destx, desty, pos.m_positionZ);
+ UpdateAllowedPositionZ(destx, desty, pos.m_positionZ, &groundZ);
pos.SetOrientation(GetOrientation());
+
+ // position has no ground under it (or is too far away)
+ if (groundZ <= INVALID_HEIGHT)
+ {
+ if (Unit const* unit = ToUnit())
+ {
+ // unit can fly, ignore.
+ if (unit->CanFly())
+ return;
+
+ // fall back to gridHeight if any
+ float gridHeight = GetMap()->GetGridHeight(pos.m_positionX, pos.m_positionY);
+ if (gridHeight > INVALID_HEIGHT)
+ pos.m_positionZ = gridHeight + unit->GetHoverOffset();
+ }
+ }
}
void WorldObject::SetPhaseMask(uint32 newPhaseMask, bool update)
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index 7b13276a7f8..f8981999f9f 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -288,7 +288,7 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation
virtual float GetCombatReach() const { return 0.0f; } // overridden (only) in Unit
void UpdateGroundPositionZ(float x, float y, float &z) const;
- void UpdateAllowedPositionZ(float x, float y, float &z) const;
+ void UpdateAllowedPositionZ(float x, float y, float &z, float* groundZ = nullptr) const;
void GetRandomPoint(Position const& srcPos, float distance, float& rand_x, float& rand_y, float& rand_z) const;
Position GetRandomPoint(Position const& srcPos, float distance) const;
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index f847fca56e2..2cefeb63532 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -2443,12 +2443,9 @@ float Map::GetHeight(float x, float y, float z, bool checkVMap /*= true*/, float
{
// find raw .map surface under Z coordinates
float mapHeight = VMAP_INVALID_HEIGHT_VALUE;
- if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
- {
- float gridHeight = gmap->getHeight(x, y);
- if (G3D::fuzzyGe(z, gridHeight - GROUND_HEIGHT_TOLERANCE))
- mapHeight = gridHeight;
- }
+ float gridHeight = GetGridHeight(x, y);
+ if (G3D::fuzzyGe(z, gridHeight - GROUND_HEIGHT_TOLERANCE))
+ mapHeight = gridHeight;
float vmapHeight = VMAP_INVALID_HEIGHT_VALUE;
if (checkVMap)
@@ -2470,16 +2467,24 @@ float Map::GetHeight(float x, float y, float z, bool checkVMap /*= true*/, float
// or if the distance of the vmap height is less the land height distance
if (vmapHeight > mapHeight || std::fabs(mapHeight - z) > std::fabs(vmapHeight - z))
return vmapHeight;
- else
- return mapHeight; // better use .map surface height
+
+ return mapHeight; // better use .map surface height
}
- else
- return vmapHeight; // we have only vmapHeight (if have)
+
+ return vmapHeight; // we have only vmapHeight (if have)
}
return mapHeight; // explicitly use map data
}
+float Map::GetGridHeight(float x, float y) const
+{
+ if (GridMap* gmap = const_cast<Map*>(this)->GetGrid(x, y))
+ return gmap->getHeight(x, y);
+
+ return VMAP_INVALID_HEIGHT_VALUE;
+}
+
float Map::GetMinHeight(float x, float y) const
{
if (GridMap const* grid = const_cast<Map*>(this)->GetGrid(x, y))
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index 9fa357db44c..ecc13fca277 100644
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -543,6 +543,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
float GetWaterOrGroundLevel(uint32 phasemask, float x, float y, float z, float* ground = nullptr, bool swim = false, float collisionHeight = 2.03128f) const; // DEFAULT_COLLISION_HEIGHT in Object.h
float GetMinHeight(float x, float y) const;
float GetHeight(float x, float y, float z, bool checkVMap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const;
+ float GetGridHeight(float x, float y) const;
float GetHeight(Position const& pos, bool vmap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const { return GetHeight(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), vmap, maxSearchDist); }
float GetHeight(uint32 phasemask, float x, float y, float z, bool vmap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const { return std::max<float>(GetHeight(x, y, z, vmap, maxSearchDist), GetGameObjectFloor(phasemask, x, y, z, maxSearchDist)); }
float GetHeight(uint32 phasemask, Position const& pos, bool vmap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) const { return GetHeight(phasemask, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), vmap, maxSearchDist); }
diff --git a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp
index 06d48f9a022..421ca1b8d69 100755
--- a/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp
@@ -100,7 +100,7 @@ bool ConfusedMovementGenerator<T>::DoUpdate(T* owner, uint32 diff)
}
bool result = _path->CalculatePath(destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ());
- if (!result || (_path->GetPathType() & PATHFIND_NOPATH))
+ if (!result || (_path->GetPathType() & PATHFIND_NOPATH) || (_path->GetPathType() & PATHFIND_SHORTCUT))
{
_timer.Reset(100);
return true;
diff --git a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp
index 82efaab6001..7c72c50ec10 100644
--- a/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp
@@ -165,7 +165,7 @@ void FleeingMovementGenerator<T>::SetTargetLocation(T* owner)
}
bool result = _path->CalculatePath(destination.GetPositionX(), destination.GetPositionY(), destination.GetPositionZ());
- if (!result || (_path->GetPathType() & PATHFIND_NOPATH))
+ if (!result || (_path->GetPathType() & PATHFIND_NOPATH) || (_path->GetPathType() & PATHFIND_SHORTCUT))
{
_timer.Reset(100);
return;
diff --git a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp
index a5b410fc60a..c97c7b389ca 100644
--- a/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp
@@ -108,7 +108,7 @@ void RandomMovementGenerator<Creature>::SetRandomLocation(Creature* owner)
}
bool result = _path->CalculatePath(position.GetPositionX(), position.GetPositionY(), position.GetPositionZ());
- if (!result || (_path->GetPathType() & PATHFIND_NOPATH))
+ if (!result || (_path->GetPathType() & PATHFIND_NOPATH) || (_path->GetPathType() & PATHFIND_SHORTCUT))
{
_timer.Reset(100);
return;
diff --git a/src/server/game/Movement/PathGenerator.cpp b/src/server/game/Movement/PathGenerator.cpp
index febdae30015..69844b2c15b 100644
--- a/src/server/game/Movement/PathGenerator.cpp
+++ b/src/server/game/Movement/PathGenerator.cpp
@@ -536,14 +536,14 @@ void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoin
/// @todo check the exact cases
TC_LOG_DEBUG("maps.mmaps", "++ PathGenerator::BuildPointPath FAILED! path sized %d returned\n", pointCount);
BuildShortcut();
- _type = PATHFIND_NOPATH;
+ _type = PathType(_type | PATHFIND_NOPATH);
return;
}
else if (pointCount == _pointPathLimit)
{
TC_LOG_DEBUG("maps.mmaps", "++ PathGenerator::BuildPointPath FAILED! path sized %d returned, lower than limit set to %d", pointCount, _pointPathLimit);
BuildShortcut();
- _type = PATHFIND_SHORT;
+ _type = PathType(_type | PATHFIND_SHORT);
return;
}
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 3e0a5e0d988..a0f35b48b29 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -1370,9 +1370,8 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplici
pos.m_positionX = m_preGeneratedPath->GetActualEndPosition().x;
pos.m_positionY = m_preGeneratedPath->GetActualEndPosition().y;
pos.m_positionZ = m_preGeneratedPath->GetActualEndPosition().z;
+ dest.Relocate(pos);
}
-
- dest.Relocate(pos);
break;
}
default: