mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2026-01-23 21:56:22 +00:00
fix(Core/Pathfinding): Creatures regen health, spells LOD (#4509)
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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()); }
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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 <ace/RW_Thread_Mutex.h>
|
||||
#include <ace/Thread_Mutex.h>
|
||||
@@ -27,7 +22,6 @@
|
||||
#include "GameObjectModel.h"
|
||||
#include "PathGenerator.h"
|
||||
#include "ObjectDefines.h"
|
||||
#include "Log.h"
|
||||
#include "DataMap.h"
|
||||
#include <bitset>
|
||||
#include <list>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -126,6 +126,7 @@ bool ChaseMovementGenerator<T>::DoUpdate(T* owner, uint32 time_diff)
|
||||
{
|
||||
cOwner->SetCannotReachTarget(true);
|
||||
cOwner->StopMoving();
|
||||
i_path = nullptr;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ class ChaseMovementGenerator : public MovementGeneratorMedium<T, ChaseMovementGe
|
||||
{
|
||||
public:
|
||||
ChaseMovementGenerator(Unit* target, std::optional<ChaseRange> range = {}, std::optional<ChaseAngle> 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<ChaseAngle> 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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
#
|
||||
###################################################################################################
|
||||
|
||||
|
||||
Reference in New Issue
Block a user