mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
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
(cherry picked from commit 9fcbd8f15d)
This commit is contained in:
@@ -1250,11 +1250,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())
|
||||
{
|
||||
@@ -1280,12 +1285,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
|
||||
@@ -1293,6 +1304,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3102,10 +3116,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(GetPhaseShift(), pos.m_positionX, pos.m_positionY);
|
||||
if (gridHeight > INVALID_HEIGHT)
|
||||
pos.m_positionZ = gridHeight + unit->GetHoverOffset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WorldObject::PlayDistanceSound(uint32 soundId, Player* target /*= nullptr*/)
|
||||
|
||||
@@ -433,7 +433,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;
|
||||
|
||||
@@ -2537,12 +2537,9 @@ float Map::GetStaticHeight(PhaseShift const& phaseShift, float x, float y, float
|
||||
// find raw .map surface under Z coordinates
|
||||
float mapHeight = VMAP_INVALID_HEIGHT_VALUE;
|
||||
uint32 terrainMapId = PhasingHandler::GetTerrainMapId(phaseShift, this, x, y);
|
||||
if (GridMap* gmap = GetGrid(terrainMapId, x, y))
|
||||
{
|
||||
float gridHeight = gmap->getHeight(x, y);
|
||||
if (G3D::fuzzyGe(z, gridHeight - GROUND_HEIGHT_TOLERANCE))
|
||||
mapHeight = gridHeight;
|
||||
}
|
||||
float gridHeight = GetGridHeight(phaseShift, x, y);
|
||||
if (G3D::fuzzyGe(z, gridHeight - GROUND_HEIGHT_TOLERANCE))
|
||||
mapHeight = gridHeight;
|
||||
|
||||
float vmapHeight = VMAP_INVALID_HEIGHT_VALUE;
|
||||
if (checkVMap)
|
||||
@@ -2564,16 +2561,24 @@ float Map::GetStaticHeight(PhaseShift const& phaseShift, float x, float y, 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(PhaseShift const& phaseShift, float x, float y)
|
||||
{
|
||||
if (GridMap* gmap = GetGrid(PhasingHandler::GetTerrainMapId(phaseShift, this, x, y), x, y))
|
||||
return gmap->getHeight(x, y);
|
||||
|
||||
return VMAP_INVALID_HEIGHT_VALUE;
|
||||
}
|
||||
|
||||
float Map::GetMinHeight(PhaseShift const& phaseShift, float x, float y)
|
||||
{
|
||||
if (GridMap const* grid = GetGrid(PhasingHandler::GetTerrainMapId(phaseShift, this, x, y), x, y))
|
||||
|
||||
@@ -495,6 +495,7 @@ class TC_GAME_API Map : public GridRefManager<NGridType>
|
||||
|
||||
float GetWaterOrGroundLevel(PhaseShift const& phaseShift, float x, float y, float z, float* ground = nullptr, bool swim = false, float collisionHeight = 2.03128f); // DEFAULT_COLLISION_HEIGHT in Object.h
|
||||
float GetMinHeight(PhaseShift const& phaseShift, float x, float y);
|
||||
float GetGridHeight(PhaseShift const& phaseShift, float x, float y);
|
||||
float GetStaticHeight(PhaseShift const& phaseShift, float x, float y, float z, bool checkVMap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH);
|
||||
float GetStaticHeight(PhaseShift const& phaseShift, Position const& pos, bool checkVMap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) { return GetStaticHeight(phaseShift, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), checkVMap, maxSearchDist); }
|
||||
float GetHeight(PhaseShift const& phaseShift, float x, float y, float z, bool vmap = true, float maxSearchDist = DEFAULT_HEIGHT_SEARCH) { return std::max<float>(GetStaticHeight(phaseShift, x, y, z, vmap, maxSearchDist), GetGameObjectFloor(phaseShift, x, y, z, maxSearchDist)); }
|
||||
|
||||
@@ -99,7 +99,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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -107,7 +107,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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1374,9 +1374,8 @@ void Spell::SelectImplicitCasterDestTargets(SpellEffectInfo const& spellEffectIn
|
||||
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;
|
||||
}
|
||||
case TARGET_DEST_CASTER_GROUND:
|
||||
|
||||
Reference in New Issue
Block a user