diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 4a6cc4539..d74c71841 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -641,7 +641,7 @@ void Creature::Update(uint32 diff) // regenerate health if not in combat or if polymorphed) if (!IsInCombat() || IsPolymorphed()) RegenerateHealth(); - else if (CanNotReachTarget()) + else if (IsNotReachableAndNeedRegen()) { // regenerate health if cannot reach the target and the setting is set to do so. // this allows to disable the health regen of raid bosses if pathfinding has issues for whatever reason @@ -666,7 +666,7 @@ void Creature::Update(uint32 diff) if (CanNotReachTarget() && !IsInEvadeMode() && !GetMap()->IsRaid()) { m_cannotReachTimer += diff; - if (m_cannotReachTimer >= (sWorld->getIntConfig(CONFIG_NPC_EVADE_IF_NOT_REACHABLE)*IN_MILLISECONDS) && IsAIEnabled) + if (IsNotReachable() && IsAIEnabled) { AI()->EnterEvadeMode(); } diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h index 5e9b95bf4..d87a30385 100644 --- a/src/server/game/Entities/Creature/Creature.h +++ b/src/server/game/Entities/Creature/Creature.h @@ -688,6 +688,8 @@ public: void SetCannotReachTarget(bool cannotReach); [[nodiscard]] bool CanNotReachTarget() const { return m_cannotReachTarget; } + [[nodiscard]] bool IsNotReachable() const { return (m_cannotReachTimer >= (sWorld->getIntConfig(CONFIG_NPC_EVADE_IF_NOT_REACHABLE) * IN_MILLISECONDS)) && m_cannotReachTarget; } + [[nodiscard]] bool IsNotReachableAndNeedRegen() const { return (m_cannotReachTimer >= (sWorld->getIntConfig(CONFIG_NPC_REGEN_TIME_IF_NOT_REACHABLE_IN_RAID) * IN_MILLISECONDS)) && m_cannotReachTarget; } void SetPosition(float x, float y, float z, float o); void SetPosition(const Position& pos) { SetPosition(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation()); } diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index d5d7e88bb..e0f5d2557 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -553,7 +553,7 @@ void Unit::UpdateSplinePosition() void Unit::DisableSpline() { - m_movementInfo.RemoveMovementFlag(MovementFlags(MOVEMENTFLAG_SPLINE_ENABLED | MOVEMENTFLAG_FORWARD)); + m_movementInfo.RemoveMovementFlag(MovementFlags(MOVEMENTFLAG_SPLINE_ENABLED | MOVEMENTFLAG_FORWARD | MOVEMENTFLAG_BACKWARD)); movespline->_Interrupt(); } @@ -13685,6 +13685,7 @@ void Unit::setDeathState(DeathState s, bool despawn) // remove aurastates allowing special moves ClearAllReactives(); ClearDiminishings(); + GetMotionMaster()->Clear(false); GetMotionMaster()->MoveIdle(); @@ -15894,6 +15895,10 @@ void Unit::StopMoving() if (movespline->Finalized()) return; + // Update position now since Stop does not start a new movement that can be updated later + if (movespline->HasStarted()) + UpdateSplinePosition(); + Movement::MoveSplineInit init(this); init.Stop(); } diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 4adb249c5..6d55c7949 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -15,7 +15,6 @@ #include "Group.h" #include "InstanceScript.h" #include "MapInstanced.h" -#include "MapManager.h" #include "ObjectAccessor.h" #include "ObjectMgr.h" #include "Pet.h" @@ -3577,8 +3576,6 @@ bool Map::CheckCollisionAndGetValidCoords(const WorldObject* source, float start // collision check bool collided = false; - float angle = getAngle(destX, destY, startX, startY); - // check static LOS float halfHeight = source->GetCollisionHeight() * 0.5f; @@ -3588,15 +3585,13 @@ bool Map::CheckCollisionAndGetValidCoords(const WorldObject* source, float start bool col = VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(source->GetMapId(), startX, startY, startZ + halfHeight, destX, destY, destZ + halfHeight, - destX, destY, destZ, -0.5f); + destX, destY, destZ, -CONTACT_DISTANCE); destZ -= halfHeight; // Collided with static LOS object, move back to collision point if (col) { - destX -= CONTACT_DISTANCE * std::cos(angle); - destY -= CONTACT_DISTANCE * std::sin(angle); collided = true; } } @@ -3605,15 +3600,13 @@ bool Map::CheckCollisionAndGetValidCoords(const WorldObject* source, float start bool col = source->GetMap()->getObjectHitPos(source->GetPhaseMask(), startX, startY, startZ + halfHeight, destX, destY, destZ + halfHeight, - destX, destY, destZ, -0.5f); + destX, destY, destZ, -CONTACT_DISTANCE); destZ -= halfHeight; // Collided with a gameobject, move back to collision point if (col) { - destX -= CONTACT_DISTANCE * std::cos(angle); - destY -= CONTACT_DISTANCE * std::sin(angle); collided = true; } diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h index b07c29ac5..8d6c68606 100644 --- a/src/server/game/Maps/Map.h +++ b/src/server/game/Maps/Map.h @@ -7,11 +7,6 @@ #ifndef ACORE_MAP_H #define ACORE_MAP_H -// Pathfinding -#include "DetourAlloc.h" -#include "DetourNavMesh.h" -#include "DetourNavMeshQuery.h" - #include "Define.h" #include #include @@ -27,7 +22,6 @@ #include "GameObjectModel.h" #include "PathGenerator.h" #include "ObjectDefines.h" -#include "Log.h" #include "DataMap.h" #include #include diff --git a/src/server/game/Movement/MovementGenerators/PathGenerator.cpp b/src/server/game/Movement/MovementGenerators/PathGenerator.cpp index 24dbe138d..84ea32beb 100644 --- a/src/server/game/Movement/MovementGenerators/PathGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/PathGenerator.cpp @@ -12,10 +12,9 @@ #include "Log.h" #include "DisableMgr.h" #include "DetourCommon.h" -#include "DetourExtended.h" #include "Geometry.h" -////////////////// PathGenerator ////////////////// + ////////////////// PathGenerator ////////////////// PathGenerator::PathGenerator(WorldObject const* owner) : _polyLength(0), _type(PATHFIND_BLANK), _useStraightPath(false), _forceDestination(false), _slopeCheck(false), _pointPathLimit(MAX_POINT_PATH_LENGTH), _useRaycast(false), @@ -124,8 +123,8 @@ dtPolyRef PathGenerator::GetPolyByLocation(float const* point, float* distance) // we don't have it in our old path // try to get it by findNearestPoly() // first try with low search box - float extents[VERTEX_SIZE] = {3.0f, 5.0f, 3.0f}; // bounds of poly search area - float closestPoint[VERTEX_SIZE] = {0.0f, 0.0f, 0.0f}; + float extents[VERTEX_SIZE] = { 3.0f, 5.0f, 3.0f }; // bounds of poly search area + float closestPoint[VERTEX_SIZE] = { 0.0f, 0.0f, 0.0f }; if (dtStatusSucceed(_navMeshQuery->findNearestPoly(point, extents, &_filter, &polyRef, closestPoint)) && polyRef != INVALID_POLYREF) { *distance = dtVdist(closestPoint, point); @@ -152,8 +151,8 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con // *** getting start/end poly logic *** float distToStartPoly, distToEndPoly; - float startPoint[VERTEX_SIZE] = {startPos.y, startPos.z, startPos.x}; - float endPoint[VERTEX_SIZE] = {endPos.y, endPos.z, endPos.x}; + float startPoint[VERTEX_SIZE] = { startPos.y, startPos.z, startPos.x }; + float endPoint[VERTEX_SIZE] = { endPos.y, endPos.z, endPos.x }; dtPolyRef startPoly = GetPolyByLocation(startPoint, &distToStartPoly); dtPolyRef endPoly = GetPolyByLocation(endPoint, &distToEndPoly); @@ -189,22 +188,30 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con // we may need a better number here bool startFarFromPoly = distToStartPoly > 7.0f; bool endFarFromPoly = distToEndPoly > 7.0f; + // create a shortcut if the path begins or end too far // away from the desired path points. // swimming creatures should not use a shortcut // because exiting the water must be done following a proper path // we just need to remove/normalize paths between 2 adjacent points - if ((!creature || !creature->CanSwim() || !creature->IsInWater() || _useRaycast) - && (startFarFromPoly || endFarFromPoly)) + if (startFarFromPoly || endFarFromPoly) { bool buildShotrcut = false; + bool isUnderWaterStart = _source->GetMap()->IsUnderWater(startPos.x, startPos.y, startPos.z); + bool isUnderWaterEnd = _source->GetMap()->IsUnderWater(endPos.x, endPos.y, endPos.z); + bool isFarUnderWater = startFarFromPoly ? isUnderWaterStart : isUnderWaterEnd; + Unit const* _sourceUnit = _source->ToUnit(); - if (_useRaycast || - (_sourceUnit && (_sourceUnit->CanFly() || (_sourceUnit->IsFalling() && endPos.z < startPos.z))) - ) + + if (_sourceUnit) { - buildShotrcut = true; + bool isUnderWater = (_sourceUnit->CanSwim() && isUnderWaterStart && isUnderWaterEnd) || (isFarUnderWater && _useRaycast); + + if (isUnderWater || _sourceUnit->CanFly() || (_sourceUnit->IsFalling() && endPos.z < startPos.z)) + { + buildShotrcut = true; + } } if (buildShotrcut) @@ -216,7 +223,8 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con return; } - else + + if (!isFarUnderWater) { float closestPoint[VERTEX_SIZE]; // we may want to use closestPointOnPolyBoundary instead @@ -248,7 +256,7 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con AddFarFromPolyFlags(startFarFromPoly, endFarFromPoly); } else - _type = PATHFIND_NORMAL; + _type = PATHFIND_NORMAL; BuildPointPath(startPoint, endPoint); return; @@ -278,7 +286,7 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con } } - for (pathEndIndex = _polyLength-1; pathEndIndex > pathStartIndex; --pathEndIndex) + for (pathEndIndex = _polyLength - 1; pathEndIndex > pathStartIndex; --pathEndIndex) { if (_pathPolyRefs[pathEndIndex] == endPoly) { @@ -309,12 +317,12 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con // thus we have less poly to cover // sub-path of optimal path is optimal - // take ~80% of the original length + // take ~80% of the original length /// @todo play with the values here uint32 prefixPolyLength = uint32(_polyLength * 0.8f + 0.5f); - memmove(_pathPolyRefs, _pathPolyRefs+pathStartIndex, prefixPolyLength * sizeof(dtPolyRef)); + memmove(_pathPolyRefs, _pathPolyRefs + pathStartIndex, prefixPolyLength * sizeof(dtPolyRef)); - dtPolyRef suffixStartPoly = _pathPolyRefs[prefixPolyLength-1]; + dtPolyRef suffixStartPoly = _pathPolyRefs[prefixPolyLength - 1]; // we need any point on our suffix start poly to generate poly-path, so we need last poly in prefix data float suffixEndPoint[VERTEX_SIZE]; @@ -323,7 +331,7 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con // we can hit offmesh connection as last poly - closestPointOnPoly() don't like that // try to recover by using prev polyref --prefixPolyLength; - suffixStartPoly = _pathPolyRefs[prefixPolyLength-1]; + suffixStartPoly = _pathPolyRefs[prefixPolyLength - 1]; if (dtStatusFailed(_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint, nullptr))) { // suffixStartPoly is still invalid, error state @@ -346,14 +354,14 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con else { dtResult = _navMeshQuery->findPath( - suffixStartPoly, // start polygon - endPoly, // end polygon - suffixEndPoint, // start position - endPoint, // end position - &_filter, // polygon search filter - _pathPolyRefs + prefixPolyLength - 1, // [out] path - (int*)&suffixPolyLength, - MAX_PATH_LENGTH - prefixPolyLength); // max number of polygons in output path + suffixStartPoly, // start polygon + endPoly, // end polygon + suffixEndPoint, // start position + endPoint, // end position + &_filter, // polygon search filter + _pathPolyRefs + prefixPolyLength - 1, // [out] path + (int*)&suffixPolyLength, + MAX_PATH_LENGTH - prefixPolyLength); // max number of polygons in output path } if (!suffixPolyLength || dtStatusFailed(dtResult)) @@ -384,15 +392,15 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con memset(hitNormal, 0, sizeof(hitNormal)); dtResult = _navMeshQuery->raycast( - startPoly, - startPoint, - endPoint, - &_filter, - &hit, - hitNormal, - _pathPolyRefs, - (int*)&_polyLength, - MAX_PATH_LENGTH); + startPoly, + startPoint, + endPoint, + &_filter, + &hit, + hitNormal, + _pathPolyRefs, + (int*)&_polyLength, + MAX_PATH_LENGTH); if (!_polyLength || dtStatusFailed(dtResult)) { @@ -449,14 +457,14 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con else { dtResult = _navMeshQuery->findPath( - startPoly, // start polygon - endPoly, // end polygon - startPoint, // start position - endPoint, // end position - &_filter, // polygon search filter - _pathPolyRefs, // [out] path - (int*)&_polyLength, - MAX_PATH_LENGTH); // max number of polygons in output path + startPoly, // start polygon + endPoly, // end polygon + startPoint, // start position + endPoint, // end position + &_filter, // polygon search filter + _pathPolyRefs, // [out] path + (int*)&_polyLength, + MAX_PATH_LENGTH); // max number of polygons in output path } if (!_polyLength || dtStatusFailed(dtResult)) @@ -493,9 +501,9 @@ void PathGenerator::BuildPolyPath(G3D::Vector3 const& startPos, G3D::Vector3 con BuildPointPath(startPoint, endPoint); } -void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoint) +void PathGenerator::BuildPointPath(const float* startPoint, const float* endPoint) { - float pathPoints[MAX_POINT_PATH_LENGTH*VERTEX_SIZE]; + float pathPoints[MAX_POINT_PATH_LENGTH * VERTEX_SIZE]; uint32 pointCount = 0; dtStatus dtResult = DT_FAILURE; if (_useRaycast) @@ -509,26 +517,26 @@ void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoin else if (_useStraightPath) { dtResult = _navMeshQuery->findStraightPath( - startPoint, // start position - endPoint, // end position - _pathPolyRefs, // current path - _polyLength, // lenth of current path - pathPoints, // [out] path corner points - nullptr, // [out] flags - nullptr, // [out] shortened path - (int*)&pointCount, - _pointPathLimit); // maximum number of points/polygons to use + startPoint, // start position + endPoint, // end position + _pathPolyRefs, // current path + _polyLength, // lenth of current path + pathPoints, // [out] path corner points + nullptr, // [out] flags + nullptr, // [out] shortened path + (int*)&pointCount, + _pointPathLimit); // maximum number of points/polygons to use } else { dtResult = FindSmoothPath( - startPoint, // start position - endPoint, // end position - _pathPolyRefs, // current path - _polyLength, // length of current path - pathPoints, // [out] path corner points - (int*)&pointCount, - _pointPathLimit); // maximum number of points + startPoint, // start position + endPoint, // end position + _pathPolyRefs, // current path + _polyLength, // length of current path + pathPoints, // [out] path corner points + (int*)&pointCount, + _pointPathLimit); // maximum number of points } // Special case with start and end positions very close to each other @@ -538,7 +546,7 @@ void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoin dtVcopy(&pathPoints[1 * VERTEX_SIZE], endPoint); pointCount++; } - else if ( pointCount < 2 || dtStatusFailed(dtResult)) + else if (pointCount < 2 || dtStatusFailed(dtResult)) { // only happens if pass bad data to findStraightPath or navmesh is broken // single point paths can be generated here @@ -557,7 +565,7 @@ void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoin _pathPoints.resize(pointCount); uint32 newPointCount = 0; for (uint32 i = 0; i < pointCount; ++i) { - G3D::Vector3 vector = G3D::Vector3(pathPoints[i*VERTEX_SIZE+2], pathPoints[i*VERTEX_SIZE], pathPoints[i*VERTEX_SIZE+1]); + G3D::Vector3 vector = G3D::Vector3(pathPoints[i * VERTEX_SIZE + 2], pathPoints[i * VERTEX_SIZE], pathPoints[i * VERTEX_SIZE + 1]); ZLiquidStatus status = _source->GetMap()->getLiquidStatus(vector.x, vector.y, vector.z, MAP_ALL_LIQUIDS, nullptr); // One of the points is not in the water if (status == LIQUID_MAP_UNDER_WATER) @@ -571,7 +579,7 @@ void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoin } // if the last point is under water // then set the desired end position instead - else if (i == pointCount - 1 ) + else if (i == pointCount - 1) { _pathPoints[newPointCount] = GetActualEndPosition(); } @@ -594,7 +602,7 @@ void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoin NormalizePath(); // first point is always our current location - we need the next one - SetActualEndPosition(_pathPoints[newPointCount-1]); + SetActualEndPosition(_pathPoints[newPointCount - 1]); // force the given destination, if needed if (_forceDestination && @@ -604,7 +612,7 @@ void PathGenerator::BuildPointPath(const float *startPoint, const float *endPoin if (Dist3DSqr(GetActualEndPosition(), GetEndPosition()) < 0.3f * Dist3DSqr(GetStartPosition(), GetEndPosition())) { SetActualEndPosition(GetEndPosition()); - _pathPoints[_pathPoints.size()-1] = GetEndPosition(); + _pathPoints[_pathPoints.size() - 1] = GetEndPosition(); } else { @@ -677,8 +685,8 @@ void PathGenerator::UpdateFilter() { uint16 includedFlags = _filter.getIncludeFlags(); includedFlags |= GetNavTerrain(_source->GetPositionX(), - _source->GetPositionY(), - _source->GetPositionZ()); + _source->GetPositionY(), + _source->GetPositionZ()); _filter.setIncludeFlags(includedFlags); } @@ -712,7 +720,7 @@ NavTerrain PathGenerator::GetNavTerrain(float x, float y, float z) const bool PathGenerator::HaveTile(const G3D::Vector3& p) const { int tx = -1, ty = -1; - float point[VERTEX_SIZE] = {p.y, p.z, p.x}; + float point[VERTEX_SIZE] = { p.y, p.z, p.x }; _navMesh->calcTileLoc(point, &tx, &ty); @@ -731,10 +739,10 @@ uint32 PathGenerator::FixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPat int32 furthestVisited = -1; // Find furthest common polygon. - for (int32 i = npath-1; i >= 0; --i) + for (int32 i = npath - 1; i >= 0; --i) { bool found = false; - for (int32 j = nvisited-1; j >= 0; --j) + for (int32 j = nvisited - 1; j >= 0; --j) { if (path[i] == visited[j]) { @@ -758,7 +766,7 @@ uint32 PathGenerator::FixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPat uint32 orig = uint32(furthestPath + 1) < npath ? furthestPath + 1 : npath; uint32 size = npath > orig ? npath - orig : 0; if (req + size > maxPath) - size = maxPath-req; + size = maxPath - req; if (size) memmove(path + req, path + orig, size * sizeof(dtPolyRef)); @@ -767,21 +775,21 @@ uint32 PathGenerator::FixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPat for (uint32 i = 0; i < req; ++i) path[i] = visited[(nvisited - 1) - i]; - return req+size; + return req + size; } bool PathGenerator::GetSteerTarget(float const* startPos, float const* endPos, - float minTargetDist, dtPolyRef const* path, uint32 pathSize, - float* steerPos, unsigned char& steerPosFlag, dtPolyRef& steerPosRef) + float minTargetDist, dtPolyRef const* path, uint32 pathSize, + float* steerPos, unsigned char& steerPosFlag, dtPolyRef& steerPosRef) { // Find steer target. static const uint32 MAX_STEER_POINTS = 3; - float steerPath[MAX_STEER_POINTS*VERTEX_SIZE]; + float steerPath[MAX_STEER_POINTS * VERTEX_SIZE]; unsigned char steerPathFlags[MAX_STEER_POINTS]; dtPolyRef steerPathPolys[MAX_STEER_POINTS]; uint32 nsteerPath = 0; dtStatus dtResult = _navMeshQuery->findStraightPath(startPos, endPos, path, pathSize, - steerPath, steerPathFlags, steerPathPolys, (int*)&nsteerPath, MAX_STEER_POINTS); + steerPath, steerPathFlags, steerPathPolys, (int*)&nsteerPath, MAX_STEER_POINTS); if (!nsteerPath || dtStatusFailed(dtResult)) return false; @@ -791,7 +799,7 @@ bool PathGenerator::GetSteerTarget(float const* startPos, float const* endPos, { // Stop at Off-Mesh link or when point is further than slop away. if ((steerPathFlags[ns] & DT_STRAIGHTPATH_OFFMESH_CONNECTION) || - !InRangeYZX(&steerPath[ns*VERTEX_SIZE], startPos, minTargetDist, 1000.0f)) + !InRangeYZX(&steerPath[ns * VERTEX_SIZE], startPos, minTargetDist, 1000.0f)) break; ns++; @@ -800,7 +808,7 @@ bool PathGenerator::GetSteerTarget(float const* startPos, float const* endPos, if (ns >= nsteerPath) return false; - dtVcopy(steerPos, &steerPath[ns*VERTEX_SIZE]); + dtVcopy(steerPos, &steerPath[ns * VERTEX_SIZE]); steerPos[1] = startPos[1]; // keep Z value steerPosFlag = steerPathFlags[ns]; steerPosRef = steerPathPolys[ns]; @@ -809,14 +817,14 @@ bool PathGenerator::GetSteerTarget(float const* startPos, float const* endPos, } dtStatus PathGenerator::FindSmoothPath(float const* startPos, float const* endPos, - dtPolyRef const* polyPath, uint32 polyPathSize, - float* smoothPath, int* smoothPathSize, uint32 maxSmoothPathSize) + dtPolyRef const* polyPath, uint32 polyPathSize, + float* smoothPath, int* smoothPathSize, uint32 maxSmoothPathSize) { *smoothPathSize = 0; uint32 nsmoothPath = 0; dtPolyRef polys[MAX_PATH_LENGTH]; - memcpy(polys, polyPath, sizeof(dtPolyRef)*polyPathSize); + memcpy(polys, polyPath, sizeof(dtPolyRef) * polyPathSize); uint32 npolys = polyPathSize; float iterPos[VERTEX_SIZE], targetPos[VERTEX_SIZE]; @@ -841,7 +849,7 @@ dtStatus PathGenerator::FindSmoothPath(float const* startPos, float const* endPo dtVcopy(targetPos, endPos); } - dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos); + dtVcopy(&smoothPath[nsmoothPath * VERTEX_SIZE], iterPos); nsmoothPath++; // Move towards target a small advancement at a time until target reached or @@ -903,7 +911,7 @@ dtStatus PathGenerator::FindSmoothPath(float const* startPos, float const* endPo dtVcopy(iterPos, targetPos); if (nsmoothPath < maxSmoothPathSize) { - dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos); + dtVcopy(&smoothPath[nsmoothPath * VERTEX_SIZE], iterPos); nsmoothPath++; } break; @@ -922,7 +930,7 @@ dtStatus PathGenerator::FindSmoothPath(float const* startPos, float const* endPo } for (uint32 i = npos; i < npolys; ++i) - polys[i-npos] = polys[i]; + polys[i - npos] = polys[i]; npolys -= npos; @@ -932,7 +940,7 @@ dtStatus PathGenerator::FindSmoothPath(float const* startPos, float const* endPo { if (nsmoothPath < maxSmoothPathSize) { - dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], connectionStartPos); + dtVcopy(&smoothPath[nsmoothPath * VERTEX_SIZE], connectionStartPos); nsmoothPath++; } // Move position at the other side of the off-mesh link. @@ -946,7 +954,7 @@ dtStatus PathGenerator::FindSmoothPath(float const* startPos, float const* endPo // Store results. if (nsmoothPath < maxSmoothPathSize) { - dtVcopy(&smoothPath[nsmoothPath*VERTEX_SIZE], iterPos); + dtVcopy(&smoothPath[nsmoothPath * VERTEX_SIZE], iterPos); nsmoothPath++; } } @@ -1047,7 +1055,7 @@ void PathGenerator::ShortenPathUntilDist(G3D::Vector3 const& target, float dist) if ((*_pathPoints.rbegin() - target).squaredLength() >= distSq) return; - size_t i = _pathPoints.size()-1; + size_t i = _pathPoints.size() - 1; float x, y, z, collisionHeight = _source->GetCollisionHeight(); // find the first i s.t.: // - _pathPoints[i] is still too close @@ -1056,7 +1064,7 @@ void PathGenerator::ShortenPathUntilDist(G3D::Vector3 const& target, float dist) while (1) { // we know that pathPoints[i] is too close already (from the previous iteration) - if ((_pathPoints[i-1] - target).squaredLength() >= distSq) + if ((_pathPoints[i - 1] - target).squaredLength() >= distSq) break; // bingo! bool canCheckSlope = _slopeCheck && (GetPathType() & ~(PATHFIND_NOT_USING_PATH)); @@ -1068,7 +1076,7 @@ void PathGenerator::ShortenPathUntilDist(G3D::Vector3 const& target, float dist) && !IsSwimmableSegment(_source->GetPositionX(), _source->GetPositionY(), _source->GetPositionZ(), _pathPoints[i - 1].x, _pathPoints[i - 1].y, _pathPoints[i - 1].z) && !IsWalkableClimb(_source->GetPositionX(), _source->GetPositionY(), _source->GetPositionZ(), _pathPoints[i - 1].x, _pathPoints[i - 1].y, _pathPoints[i - 1].z) ) - ) + ) { // whenver we find a point that is not valid anymore, simply use last valid path _pathPoints.resize(i + 1); @@ -1088,7 +1096,7 @@ void PathGenerator::ShortenPathUntilDist(G3D::Vector3 const& target, float dist) // ... settle for a guesstimate since i'm not confident in doing trig on every chase motion tick... // (@todo review this) _pathPoints[i] += (_pathPoints[i - 1] - _pathPoints[i]).direction() * (dist - (_pathPoints[i] - target).length()); - _pathPoints.resize(i+1); + _pathPoints.resize(i + 1); } bool PathGenerator::IsInvalidDestinationZ(Unit const* target) const @@ -1143,8 +1151,8 @@ bool PathGenerator::IsSwimmableSegment(float x, float y, float z, float destX, f { Creature const* _sourceCreature = _source->ToCreature(); return _source->GetMap()->IsInWater(x, y, z) && - _source->GetMap()->IsInWater(destX, destY, destZ) && - (!checkSwim || !_sourceCreature || _sourceCreature->CanSwim()); + _source->GetMap()->IsInWater(destX, destY, destZ) && + (!checkSwim || !_sourceCreature || _sourceCreature->CanSwim()); } bool PathGenerator::IsWaterPath(Movement::PointsArray _pathPoints) const diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp index 45e86e7a3..54da580d7 100644 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp @@ -126,6 +126,7 @@ bool ChaseMovementGenerator::DoUpdate(T* owner, uint32 time_diff) { cOwner->SetCannotReachTarget(true); cOwner->StopMoving(); + i_path = nullptr; return true; } } diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h index 15e61ecb7..fa928165c 100644 --- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h +++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.h @@ -29,7 +29,7 @@ class ChaseMovementGenerator : public MovementGeneratorMedium range = {}, std::optional angle = {}) - : TargetedMovementGeneratorBase(target), i_path(nullptr), i_recheckDistance(0), i_recalculateTravel(true), _range(range), _angle(angle) {} + : TargetedMovementGeneratorBase(target), i_path(nullptr), i_recheckDistance(0), i_recalculateTravel(true), _range(range), _angle(angle) {} ~ChaseMovementGenerator() {} MovementGeneratorType GetMovementGeneratorType() { return CHASE_MOTION_TYPE; } @@ -45,7 +45,7 @@ public: void unitSpeedChanged() { _lastTargetPosition.reset(); } Unit* GetTarget() const { return i_target.getTarget(); } - bool EnableWalking() const { return false;} + bool EnableWalking() const { return false; } bool HasLostTarget(Unit* unit) const { return unit->GetVictim() != this->GetTarget(); } private: @@ -83,7 +83,7 @@ public: bool PositionOkay(T* owner, Unit* target, float range, std::optional angle = {}); static void _clearUnitStateMove(T* u) { u->ClearUnitState(UNIT_STATE_FOLLOW_MOVE); } - static void _addUnitStateMove(T* u) { u->AddUnitState(UNIT_STATE_FOLLOW_MOVE); } + static void _addUnitStateMove(T* u) { u->AddUnitState(UNIT_STATE_FOLLOW_MOVE); } void _updateSpeed(T* owner); diff --git a/src/server/game/Movement/Spline/MoveSpline.h b/src/server/game/Movement/Spline/MoveSpline.h index 03b66923e..c344d649d 100644 --- a/src/server/game/Movement/Spline/MoveSpline.h +++ b/src/server/game/Movement/Spline/MoveSpline.h @@ -112,6 +112,10 @@ namespace Movement bool onTransport; [[nodiscard]] std::string ToString() const; + [[nodiscard]] bool HasStarted() const + { + return time_passed > 0; + } }; } #endif // TRINITYSERVER_MOVEPLINE_H diff --git a/src/server/game/World/IWorld.h b/src/server/game/World/IWorld.h index 9b371f143..16ccf23f1 100644 --- a/src/server/game/World/IWorld.h +++ b/src/server/game/World/IWorld.h @@ -373,6 +373,7 @@ enum WorldIntConfigs CONFIG_GM_LEVEL_CHANNEL_MODERATION, CONFIG_TOGGLE_XP_COST, CONFIG_NPC_EVADE_IF_NOT_REACHABLE, + CONFIG_NPC_REGEN_TIME_IF_NOT_REACHABLE_IN_RAID, INT_CONFIG_VALUE_COUNT }; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 248cb9b27..db21814dd 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1404,6 +1404,7 @@ void World::LoadConfigSettings(bool reload) m_int_configs[CONFIG_WAYPOINT_MOVEMENT_STOP_TIME_FOR_PLAYER] = sConfigMgr->GetIntDefault("WaypointMovementStopTimeForPlayer", 120); m_int_configs[CONFIG_NPC_EVADE_IF_NOT_REACHABLE] = sConfigMgr->GetIntDefault("NpcEvadeIfTargetIsUnreachable", 5); + m_int_configs[CONFIG_NPC_REGEN_TIME_IF_NOT_REACHABLE_IN_RAID] = sConfigMgr->GetIntDefault("NpcRegenHPTimeIfTargetIsUnreachable", 10); m_bool_configs[CONFIG_REGEN_HP_CANNOT_REACH_TARGET_IN_RAID] = sConfigMgr->GetBoolDefault("NpcRegenHPIfTargetIsUnreachable", true); //Debug diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 7080dd378..1f9c78f43 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -1967,6 +1967,14 @@ NpcEvadeIfTargetIsUnreachable = 5 NpcRegenHPIfTargetIsUnreachable = 1 + +# NpcRegenHPTimeIfTargetIsUnreachable +# Description: Specifies the time (in seconds) that a creature whom target +# is unreachable in raid to end up regenerate health. +# Default: 10 + +NpcRegenHPTimeIfTargetIsUnreachable = 10 + # ###################################################################################################