diff options
author | Jeremy <Golrag@users.noreply.github.com> | 2019-04-07 20:15:40 +0200 |
---|---|---|
committer | Giacomo Pozzoni <giacomopoz@gmail.com> | 2019-04-07 20:15:40 +0200 |
commit | 9fcbd8f15d249070aabc25d48df86681e8ec3d11 (patch) | |
tree | 33b077329695d07b6592e47b0d8aeb3a5c58a72d | |
parent | 73e3fdc8b4545cca52b66032a5f2465183d14c71 (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.cpp | 35 | ||||
-rw-r--r-- | src/server/game/Entities/Object/Object.h | 2 | ||||
-rw-r--r-- | src/server/game/Maps/Map.cpp | 25 | ||||
-rw-r--r-- | src/server/game/Maps/Map.h | 1 | ||||
-rwxr-xr-x | src/server/game/Movement/MovementGenerators/ConfusedMovementGenerator.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Movement/MovementGenerators/FleeingMovementGenerator.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Movement/MovementGenerators/RandomMovementGenerator.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Movement/PathGenerator.cpp | 4 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 3 |
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: |