diff --git a/.gitignore b/.gitignore index ac934d6b4..5ba18d8a5 100644 --- a/.gitignore +++ b/.gitignore @@ -110,3 +110,5 @@ dep/ACE_wrappers/ace/config.h !dep/ACE_wrappers/lib/.empty !dep/tbb/src/Makefile +# recastnavigation directory needs exception +!dep/recastnavigation/RecastDemo/Build/ diff --git a/dep/lib/x64_Debug/ADEd.pdb b/dep/lib/x64_Debug/ADEd.pdb deleted file mode 100644 index 80eb10214..000000000 Binary files a/dep/lib/x64_Debug/ADEd.pdb and /dev/null differ diff --git a/src/game/Level2.cpp b/src/game/Level2.cpp index a541d2919..0c7947c76 100644 --- a/src/game/Level2.cpp +++ b/src/game/Level2.cpp @@ -5398,19 +5398,19 @@ bool ChatHandler::HandleMmapPathCommand(char* args) player->GetPosition(x, y, z); // path - PathInfo path(target, x, y, z, useStraightPath); - PointPath pointPath = path.getFullPath(); + PathInfo path(target); + path.calculate(x, y, z, useStraightPath); + + PointsArray pointPath = path.getPath(); PSendSysMessage("%s's path to %s:", target->GetName(), player->GetName()); PSendSysMessage("Building %s", useStraightPath ? "StraightPath" : "SmoothPath"); PSendSysMessage("length %i type %u", pointPath.size(), path.getPathType()); - PathNode start = path.getStartPosition(); - PathNode next = path.getNextPosition(); - PathNode end = path.getEndPosition(); - PathNode actualEnd = path.getActualEndPosition(); + Vector3 start = path.getStartPosition(); + Vector3 end = path.getEndPosition(); + Vector3 actualEnd = path.getActualEndPosition(); PSendSysMessage("start (%.3f, %.3f, %.3f)", start.x, start.y, start.z); - PSendSysMessage("next (%.3f, %.3f, %.3f)", next.x, next.y, next.z); PSendSysMessage("end (%.3f, %.3f, %.3f)", end.x, end.y, end.z); PSendSysMessage("actual end (%.3f, %.3f, %.3f)", actualEnd.x, actualEnd.y, actualEnd.z); @@ -5456,7 +5456,7 @@ bool ChatHandler::HandleMmapLocCommand(char* /*args*/) float x, y, z; player->GetPosition(x, y, z); float location[VERTEX_SIZE] = {y, z, x}; - float extents[VERTEX_SIZE] = {2.f,4.f,2.f}; + float extents[VERTEX_SIZE] = {3.0f, 5.0f, 3.0f}; int32 tilex = int32((y - min[0]) / SIZE_OF_GRIDS); int32 tiley = int32((x - min[2]) / SIZE_OF_GRIDS); diff --git a/src/game/Level3.cpp b/src/game/Level3.cpp index 0b53161c7..e1f78de92 100644 --- a/src/game/Level3.cpp +++ b/src/game/Level3.cpp @@ -41,6 +41,7 @@ #include "CellImpl.h" #include "Weather.h" #include "PointMovementGenerator.h" +#include "PathFinder.h" #include "TargetedMovementGenerator.h" #include "SkillDiscovery.h" #include "SkillExtraItems.h" @@ -7746,7 +7747,8 @@ bool ChatHandler::HandleMmapTestArea(char* args) m_session->GetPlayer()->GetPosition(gx,gy,gz); for (std::list::iterator itr = creatureList.begin(); itr != creatureList.end(); ++itr) { - PathInfo((*itr), gx, gy, gz); + PathInfo path(*itr); + path.calculate(gx, gy, gz); ++paths; } diff --git a/src/game/MotionMaster.cpp b/src/game/MotionMaster.cpp index efe3de2ed..694de5347 100644 --- a/src/game/MotionMaster.cpp +++ b/src/game/MotionMaster.cpp @@ -306,14 +306,14 @@ void MotionMaster::MoveFollow(Unit* target, float dist, float angle) Mutate(new FollowMovementGenerator(*target,dist,angle)); } -void MotionMaster::MovePoint(uint32 id, float x, float y, float z, bool usePathfinding) +void MotionMaster::MovePoint(uint32 id, float x, float y, float z, bool generatePath) { DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "%s targeted point (Id: %u X: %f Y: %f Z: %f)", m_owner->GetGuidStr().c_str(), id, x, y, z ); if (m_owner->GetTypeId() == TYPEID_PLAYER) - Mutate(new PointMovementGenerator(id,x,y,z,usePathfinding)); + Mutate(new PointMovementGenerator(id,x,y,z,generatePath)); else - Mutate(new PointMovementGenerator(id,x,y,z,usePathfinding)); + Mutate(new PointMovementGenerator(id,x,y,z,generatePath)); } void MotionMaster::MoveSeekAssistance(float x, float y, float z) diff --git a/src/game/MotionMaster.h b/src/game/MotionMaster.h index 106b8be07..bf10cf100 100644 --- a/src/game/MotionMaster.h +++ b/src/game/MotionMaster.h @@ -101,7 +101,7 @@ class MANGOS_DLL_SPEC MotionMaster : private std::stack void MoveChase(Unit* target, float dist = 0.0f, float angle = 0.0f); void MoveConfused(); void MoveFleeing(Unit* enemy, uint32 timeLimit = 0); - void MovePoint(uint32 id, float x, float y, float z, bool usePathfinding = true); + void MovePoint(uint32 id, float x,float y,float z, bool generatePath = true); void MoveSeekAssistance(float x,float y,float z); void MoveSeekAssistanceDistract(uint32 timer); void MoveWaypoint(); diff --git a/src/game/MovementGenerator.h b/src/game/MovementGenerator.h index 1c8dbdeb2..8018b2212 100644 --- a/src/game/MovementGenerator.h +++ b/src/game/MovementGenerator.h @@ -53,12 +53,12 @@ class MANGOS_DLL_SPEC MovementGenerator virtual bool GetDestination(float& /*x*/, float& /*y*/, float& /*z*/) const { return false; } - // given destination unreachable? due to pathfinsing or other - virtual bool IsReachable() const { return true; } - // used by Evade code for select point to evade with expected restart default movement virtual bool GetResetPosition(Unit &, float& /*x*/, float& /*y*/, float& /*z*/) { return false; } + // given destination unreachable? due to pathfinsing or other + virtual bool IsReachable() const { return true; } + // used for check from Update call is movegen still be active (top movement generator) // after some not safe for this calls bool IsActive(Unit& u); diff --git a/src/game/Object.cpp b/src/game/Object.cpp index 201fe4659..210ed9a28 100644 --- a/src/game/Object.cpp +++ b/src/game/Object.cpp @@ -1061,16 +1061,6 @@ float WorldObject::GetDistance(const WorldObject* obj) const return ( dist > 0 ? dist : 0); } -float WorldObject::GetDistanceSqr(float x, float y, float z) const -{ - float dx = GetPositionX() - x; - float dy = GetPositionY() - y; - float dz = GetPositionZ() - z; - float sizefactor = GetObjectBoundingRadius(); - float dist = dx*dx+dy*dy+dz*dz-sizefactor; - return (dist > 0 ? dist : 0); -} - float WorldObject::GetDistance2d(float x, float y) const { float dx = GetPositionX() - x; @@ -1080,16 +1070,6 @@ float WorldObject::GetDistance2d(float x, float y) const return ( dist > 0 ? dist : 0); } -float WorldObject::GetDistance(float x, float y, float z) const -{ - float dx = GetPositionX() - x; - float dy = GetPositionY() - y; - float dz = GetPositionZ() - z; - float sizefactor = GetObjectBoundingRadius(); - float dist = sqrt((dx*dx) + (dy*dy) + (dz*dz)) - sizefactor; - return ( dist > 0 ? dist : 0); -} - float WorldObject::GetDistance2d(const WorldObject* obj) const { float dx = GetPositionX() - obj->GetPositionX(); @@ -1286,34 +1266,6 @@ float WorldObject::GetAngle( const float x, const float y ) const return ang; } -bool WorldObject::HasInArc(const float arcangle, const float x, const float y) const -{ - // always have self in arc - if(x == GetPositionX() && y == GetPositionY()) - return true; - - float arc = arcangle; - - // move arc to range 0.. 2*pi - while( arc >= 2.0f * M_PI_F ) - arc -= 2.0f * M_PI_F; - while( arc < 0 ) - arc += 2.0f * M_PI_F; - - float angle = GetAngle( x, y ); - angle -= GetOrientation(); - - // move angle to range -pi ... +pi - while( angle > M_PI_F) - angle -= 2.0f * M_PI_F; - while(angle < -M_PI_F) - angle += 2.0f * M_PI_F; - - float lborder = -1 * (arc/2.0f); // in range -pi..0 - float rborder = (arc/2.0f); // in range 0..pi - return (( angle >= lborder ) && ( angle <= rborder )); -} - bool WorldObject::HasInArc(const float arcangle, const WorldObject* obj) const { // always have self in arc diff --git a/src/game/Object.h b/src/game/Object.h index ae84dac87..ade4b6175 100644 --- a/src/game/Object.h +++ b/src/game/Object.h @@ -499,7 +499,6 @@ class MANGOS_DLL_SPEC WorldObject : public Object virtual const char* GetNameForLocaleIdx(int32 /*locale_idx*/) const { return GetName(); } float GetDistance( const WorldObject* obj ) const; - float GetDistanceSqr(float x, float y, float z) const; float GetDistance(float x, float y, float z) const; float GetDistance2d(const WorldObject* obj) const; float GetDistance2d(float x, float y) const; @@ -539,7 +538,6 @@ class MANGOS_DLL_SPEC WorldObject : public Object float GetAngle( const WorldObject* obj ) const; float GetAngle( const float x, const float y ) const; - bool HasInArc( const float arcangle, const float x, const float y) const; bool HasInArc( const float arcangle, const WorldObject* obj ) const; bool isInFrontInMap(WorldObject const* target,float distance, float arc = M_PI) const; bool isInBackInMap(WorldObject const* target, float distance, float arc = M_PI) const; diff --git a/src/game/PathFinder.cpp b/src/game/PathFinder.cpp index b3155ecbb..727e51983 100644 --- a/src/game/PathFinder.cpp +++ b/src/game/PathFinder.cpp @@ -19,28 +19,18 @@ #include "MoveMap.h" #include "GridMap.h" #include "Creature.h" -#include "Player.h" #include "PathFinder.h" #include "Log.h" #include "../recastnavigation/Detour/Include/DetourCommon.h" ////////////////// PathInfo ////////////////// -PathInfo::PathInfo(const Unit* owner, const float destX, const float destY, const float destZ, - bool useStraightPath, bool forceDest) : +PathInfo::PathInfo(const Unit* owner) : m_polyLength(0), m_type(PATHFIND_BLANK), - m_useStraightPath(useStraightPath), m_forceDestination(forceDest), + m_useStraightPath(false), m_forceDestination(false), m_sourceUnit(owner), m_navMesh(NULL), m_navMeshQuery(NULL) { - PathNode endPoint(destX, destY, destZ); - setEndPosition(endPoint); - - float x,y,z; - m_sourceUnit->GetPosition(x, y, z); - PathNode startPoint(x, y, z); - setStartPosition(startPoint); - - DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathInfo::PathInfo for %u \n", m_sourceUnit->GetObjectGuid()); + DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathInfo::PathInfo for %u \n", m_sourceUnit->GetGUIDLow()); uint32 mapId = m_sourceUnit->GetMapId(); if (MMAP::MMapFactory::IsPathfindingEnabled(mapId)) @@ -52,43 +42,33 @@ PathInfo::PathInfo(const Unit* owner, const float destX, const float destY, cons createFilter(); - if (m_navMesh && m_navMeshQuery && HaveTiles(endPoint) && - !m_sourceUnit->hasUnitState(UNIT_STAT_IGNORE_PATHFINDING)) - { - BuildPolyPath(startPoint, endPoint); - } - else - { - BuildShortcut(); - m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); - } + m_pathPoints.clear(); } PathInfo::~PathInfo() { - DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathInfo::~PathInfo() for %u \n", m_sourceUnit->GetObjectGuid()); + DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathInfo::~PathInfo() for %u \n", m_sourceUnit->GetGUIDLow()); } -bool PathInfo::Update(const float destX, const float destY, const float destZ, - bool useStraightPath, bool forceDest) +bool PathInfo::calculate(float destX, float destY, float destZ, + bool useStraightPath, bool forceDest) { - PathNode newDest(destX, destY, destZ); - PathNode oldDest = getEndPosition(); - setEndPosition(newDest); + Vector3 oldDest = getEndPosition(); + Vector3 dest(destX, destY, destZ); + setEndPosition(dest); float x, y, z; m_sourceUnit->GetPosition(x, y, z); - PathNode newStart(x, y, z); - PathNode oldStart = getStartPosition(); - setStartPosition(newStart); + Vector3 start(x, y, z); + setStartPosition(start); m_useStraightPath = useStraightPath; m_forceDestination = forceDest; - DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathInfo::Update() for %u \n", m_sourceUnit->GetObjectGuid()); + DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathInfo::calculate() for %u \n", m_sourceUnit->GetGUIDLow()); // make sure navMesh works - we can run on map w/o mmap - if (!m_navMesh || !m_navMeshQuery || !HaveTiles(newDest) || + if (!m_navMesh || !m_navMeshQuery || !HaveTiles(dest) || m_sourceUnit->hasUnitState(UNIT_STAT_IGNORE_PATHFINDING)) { BuildShortcut(); @@ -101,26 +81,24 @@ bool PathInfo::Update(const float destX, const float destY, const float destZ, // check if destination moved - if not we can optimize something here // we are following old, precalculated path? float dist = m_sourceUnit->GetObjectBoundingRadius(); - if (inRange(oldDest, newDest, dist, dist) && m_pathPoints.size() > 2) + if (inRange(oldDest, dest, dist, dist) && m_pathPoints.size() > 2) { // our target is not moving - we just coming closer // we are moving on precalculated path - enjoy the ride - DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathInfo::Update:: precalculated path\n"); - - m_pathPoints.crop(1, 0); - setNextPosition(m_pathPoints[1]); + DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathInfo::calculate:: precalculated path\n"); + m_pathPoints.erase(m_pathPoints.begin()); return false; } else { // target moved, so we need to update the poly path - BuildPolyPath(newStart, newDest); + BuildPolyPath(start, dest); return true; } } -dtPolyRef PathInfo::getPathPolyByPosition(dtPolyRef *polyPath, uint32 polyPathSize, const float* point, float *distance) +dtPolyRef PathInfo::getPathPolyByPosition(const dtPolyRef *polyPath, uint32 polyPathSize, const float* point, float *distance) { if (!polyPath || !polyPathSize) return INVALID_POLYREF; @@ -189,7 +167,7 @@ dtPolyRef PathInfo::getPolyByLocation(const float* point, float *distance) return INVALID_POLYREF; } -void PathInfo::BuildPolyPath(PathNode startPos, PathNode endPos) +void PathInfo::BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos) { // *** getting start/end poly logic *** @@ -207,8 +185,7 @@ void PathInfo::BuildPolyPath(PathNode startPos, PathNode endPos) { DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: (startPoly == 0 || endPoly == 0)\n"); BuildShortcut(); - m_type = ((m_sourceUnit->GetTypeId() == TYPEID_UNIT && ((Creature*)m_sourceUnit)->CanFly()) || - (m_sourceUnit->GetTypeId() == TYPEID_PLAYER && ((Player*)m_sourceUnit)->IsBot() && ((Player*)m_sourceUnit)->IsFlying())) + m_type = (m_sourceUnit->GetTypeId() == TYPEID_UNIT && ((Creature*)m_sourceUnit)->CanFly()) ? PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH) : PATHFIND_NOPATH; return; } @@ -224,7 +201,7 @@ void PathInfo::BuildPolyPath(PathNode startPos, PathNode endPos) { Creature* owner = (Creature*)m_sourceUnit; - PathNode p = (distToStartPoly > 7.0f) ? startPos : endPos; + Vector3 p = (distToStartPoly > 7.0f) ? startPos : endPos; if (m_sourceUnit->GetTerrain()->IsUnderWater(p.x, p.y, p.z)) { DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: underWater case\n"); @@ -238,18 +215,6 @@ void PathInfo::BuildPolyPath(PathNode startPos, PathNode endPos) buildShotrcut = true; } } - else if (m_sourceUnit->GetTypeId() == TYPEID_PLAYER) - { - Player* owner = (Player*)m_sourceUnit; - - PathNode p = (distToStartPoly > 7.0f) ? startPos : endPos; - if (!m_sourceUnit->GetTerrain()->IsUnderWater(p.x, p.y, p.z)) - { - DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: flying case\n"); - if (owner->IsFlying()) - buildShotrcut = true; - } - } if (buildShotrcut) { @@ -264,7 +229,7 @@ void PathInfo::BuildPolyPath(PathNode startPos, PathNode endPos) if (DT_SUCCESS == m_navMeshQuery->closestPointOnPoly(endPoly, endPoint, closestPoint)) { dtVcopy(endPoint, closestPoint); - setActualEndPosition(PathNode(endPoint[2],endPoint[0],endPoint[1])); + setActualEndPosition(Vector3(endPoint[2],endPoint[0],endPoint[1])); } m_type = PATHFIND_INCOMPLETE; @@ -301,7 +266,7 @@ void PathInfo::BuildPolyPath(PathNode startPos, PathNode endPos) { // here to carch few bugs MANGOS_ASSERT(m_pathPolyRefs[pathStartIndex] != INVALID_POLYREF); - + if (m_pathPolyRefs[pathStartIndex] == startPoly) { startPolyFound = true; @@ -354,7 +319,7 @@ void PathInfo::BuildPolyPath(PathNode startPos, PathNode endPos) if (DT_SUCCESS != m_navMeshQuery->closestPointOnPoly(suffixStartPoly, endPoint, suffixEndPoint)) { // suffixStartPoly is invalid somehow, or the navmesh is broken => error state - sLog.outError("%u's Path Build failed: invalid polyRef in path", m_sourceUnit->GetObjectGuid()); + sLog.outError("%u's Path Build failed: invalid polyRef in path", m_sourceUnit->GetGUIDLow()); BuildShortcut(); m_type = PATHFIND_NOPATH; @@ -378,7 +343,7 @@ void PathInfo::BuildPolyPath(PathNode startPos, PathNode endPos) // this is probably an error state, but we'll leave it // and hopefully recover on the next Update // we still need to copy our preffix - sLog.outError("%u's Path Build failed: 0 length path", m_sourceUnit->GetObjectGuid()); + sLog.outError("%u's Path Build failed: 0 length path", m_sourceUnit->GetGUIDLow()); } DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ m_polyLength=%u prefixPolyLength=%u suffixPolyLength=%u \n",m_polyLength, prefixPolyLength, suffixPolyLength); @@ -410,7 +375,7 @@ void PathInfo::BuildPolyPath(PathNode startPos, PathNode endPos) if (!m_polyLength || dtResult != DT_SUCCESS) { // only happens if we passed bad data to findPath(), or navmesh is messed up - sLog.outError("%u's Path Build failed: 0 length path", m_sourceUnit->GetObjectGuid()); + sLog.outError("%u's Path Build failed: 0 length path", m_sourceUnit->GetGUIDLow()); BuildShortcut(); m_type = PATHFIND_NOPATH; return; @@ -427,7 +392,7 @@ void PathInfo::BuildPolyPath(PathNode startPos, PathNode endPos) BuildPointPath(startPoint, endPoint); } -void PathInfo::BuildPointPath(float *startPoint, float *endPoint) +void PathInfo::BuildPointPath(const float *startPoint, const float *endPoint) { float pathPoints[MAX_POINT_PATH_LENGTH*VERTEX_SIZE]; uint32 pointCount = 0; @@ -477,20 +442,29 @@ void PathInfo::BuildPointPath(float *startPoint, float *endPoint) m_pathPoints.resize(pointCount); for (uint32 i = 0; i < pointCount; ++i) - m_pathPoints.set(i, PathNode(pathPoints[i*VERTEX_SIZE+2], pathPoints[i*VERTEX_SIZE], pathPoints[i*VERTEX_SIZE+1])); + m_pathPoints[i] = Vector3(pathPoints[i*VERTEX_SIZE+2], pathPoints[i*VERTEX_SIZE], pathPoints[i*VERTEX_SIZE+1]); // first point is always our current location - we need the next one - setNextPosition(m_pathPoints[1]); setActualEndPosition(m_pathPoints[pointCount-1]); // force the given destination, if needed if(m_forceDestination && (!(m_type & PATHFIND_NORMAL) || !inRange(getEndPosition(), getActualEndPosition(), 1.0f, 1.0f))) { - setActualEndPosition(getEndPosition()); - BuildShortcut(); + // we may want to keep partial subpath + if(dist3DSqr(getActualEndPosition(), getEndPosition()) < + 0.3f * dist3DSqr(getStartPosition(), getEndPosition())) + { + setActualEndPosition(getEndPosition()); + m_pathPoints[m_pathPoints.size()-1] = getEndPosition(); + } + else + { + setActualEndPosition(getEndPosition()); + BuildShortcut(); + } + m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); - return; } DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathInfo::BuildPointPath path type %d size %d poly-size %d\n", m_type, pointCount, m_polyLength); @@ -506,17 +480,16 @@ void PathInfo::BuildShortcut() m_pathPoints.resize(2); // set start and a default next position - m_pathPoints.set(0, getStartPosition()); - m_pathPoints.set(1, getActualEndPosition()); + m_pathPoints[0] = getStartPosition(); + m_pathPoints[1] = getActualEndPosition(); - setNextPosition(getActualEndPosition()); m_type = PATHFIND_SHORTCUT; } void PathInfo::createFilter() { - unsigned short includeFlags = 0; - unsigned short excludeFlags = 0; + uint16 includeFlags = 0; + uint16 excludeFlags = 0; if (m_sourceUnit->GetTypeId() == TYPEID_UNIT) { @@ -546,7 +519,7 @@ void PathInfo::updateFilter() // forcefully into terrain they can't normally move in if (m_sourceUnit->IsInWater() || m_sourceUnit->IsUnderWater()) { - unsigned short includedFlags = m_filter.getIncludeFlags(); + uint16 includedFlags = m_filter.getIncludeFlags(); includedFlags |= getNavTerrain(m_sourceUnit->GetPositionX(), m_sourceUnit->GetPositionY(), m_sourceUnit->GetPositionZ()); @@ -574,7 +547,7 @@ NavTerrain PathInfo::getNavTerrain(float x, float y, float z) } } -bool PathInfo::HaveTiles(const PathNode p) const +bool PathInfo::HaveTiles(const Vector3 &p) const { int tx, ty; float point[VERTEX_SIZE] = {p.y, p.z, p.x}; @@ -584,8 +557,8 @@ bool PathInfo::HaveTiles(const PathNode p) const return (m_navMesh->getTileAt(tx, ty) != NULL); } -uint32 PathInfo::fixupCorridor(dtPolyRef* path, const uint32 npath, const uint32 maxPath, - const dtPolyRef* visited, const uint32 nvisited) +uint32 PathInfo::fixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath, + const dtPolyRef* visited, uint32 nvisited) { int32 furthestPath = -1; int32 furthestVisited = -1; @@ -631,7 +604,7 @@ uint32 PathInfo::fixupCorridor(dtPolyRef* path, const uint32 npath, const uint32 } bool PathInfo::getSteerTarget(const float* startPos, const float* endPos, - const float minTargetDist, const dtPolyRef* path, const uint32 pathSize, + float minTargetDist, const dtPolyRef* path, uint32 pathSize, float* steerPos, unsigned char& steerPosFlag, dtPolyRef& steerPosRef) { // Find steer target. @@ -668,8 +641,9 @@ bool PathInfo::getSteerTarget(const float* startPos, const float* endPos, } dtStatus PathInfo::findSmoothPath(const float* startPos, const float* endPos, - const dtPolyRef* polyPath, const uint32 polyPathSize, - float* smoothPath, int* smoothPathSize, bool &usedOffmesh, const uint32 maxSmoothPathSize) + const dtPolyRef* polyPath, uint32 polyPathSize, + float* smoothPath, int* smoothPathSize, + bool &usedOffmesh, uint32 maxSmoothPathSize) { MANGOS_ASSERT(polyPathSize <= MAX_PATH_LENGTH); *smoothPathSize = 0; @@ -791,3 +765,22 @@ dtStatus PathInfo::findSmoothPath(const float* startPos, const float* endPos, // this is most likely loop return nsmoothPath < maxSmoothPathSize ? DT_SUCCESS : DT_FAILURE; } + +bool PathInfo::inRangeYZX(const float* v1, const float* v2, float r, float h) const +{ + const float dx = v2[0] - v1[0]; + const float dy = v2[1] - v1[1]; // elevation + const float dz = v2[2] - v1[2]; + return (dx*dx + dz*dz) < r*r && fabsf(dy) < h; +} + +bool PathInfo::inRange(const Vector3 &p1, const Vector3 &p2, float r, float h) const +{ + Vector3 d = p1-p2; + return (d.x*d.x + d.y*d.y) < r*r && fabsf(d.z) < h; +} + +float PathInfo::dist3DSqr(const Vector3 &p1, const Vector3 &p2) const +{ + return (p1-p2).squaredLength(); +} diff --git a/src/game/PathFinder.h b/src/game/PathFinder.h index ebb931a49..eade62017 100644 --- a/src/game/PathFinder.h +++ b/src/game/PathFinder.h @@ -19,11 +19,15 @@ #ifndef MANGOS_PATH_FINDER_H #define MANGOS_PATH_FINDER_H -#include "Path.h" #include "MoveMapSharedDefines.h" #include "../recastnavigation/Detour/Include/DetourNavMesh.h" #include "../recastnavigation/Detour/Include/DetourNavMeshQuery.h" +#include "movement/MoveSplineInitArgs.h" + +using Movement::Vector3; +using Movement::PointsArray; + class Unit; // 64*6.0f=384y number_of_points*interval = max_path_len @@ -51,42 +55,35 @@ enum PathType class PathInfo { public: - PathInfo(Unit const* owner, const float destX, const float destY, const float destZ, - bool useStraightPath = false, bool forceDest = false); + PathInfo(Unit const* owner); ~PathInfo(); - // return value : true if new path was calculated - bool Update(const float destX, const float destY, const float destZ, - bool useStraightPath = false, bool forceDest = false); + // return: true if new path was calculated + // false otherwise (no change needed) + bool calculate(float destX, float destY, float destZ, + bool useStraightPath = false, bool forceDest = false); - inline void getStartPosition(float &x, float &y, float &z) { x = m_startPosition.x; y = m_startPosition.y; z = m_startPosition.z; } - inline void getNextPosition(float &x, float &y, float &z) { x = m_nextPosition.x; y = m_nextPosition.y; z = m_nextPosition.z; } - inline void getEndPosition(float &x, float &y, float &z) { x = m_endPosition.x; y = m_endPosition.y; z = m_endPosition.z; } - inline void getActualEndPosition(float &x, float &y, float &z) { x = m_actualEndPosition.x; y = m_actualEndPosition.y; z = m_actualEndPosition.z; } + Vector3 getStartPosition() const { return m_startPosition; } + Vector3 getEndPosition() const { return m_endPosition; } + Vector3 getActualEndPosition() const { return m_actualEndPosition; } - inline PathNode getStartPosition() const { return m_startPosition; } - inline PathNode getNextPosition() const { return m_nextPosition; } - inline PathNode getEndPosition() const { return m_endPosition; } - inline PathNode getActualEndPosition() const { return m_actualEndPosition; } - - inline PointPath& getFullPath() { return m_pathPoints; } - inline PathType getPathType() const { return m_type; } + PointsArray& getPath() { return m_pathPoints; } + PathType getPathType() const { return m_type; } private: - dtPolyRef m_pathPolyRefs[MAX_PATH_LENGTH]; // array of detour polygon references - uint32 m_polyLength; // number of polygons in the path + dtPolyRef m_pathPolyRefs[MAX_PATH_LENGTH]; // array of detour polygon references + uint32 m_polyLength; // number of polygons in the path - PointPath m_pathPoints; // our actual (x,y,z) path to the target - PathType m_type; // tells what kind of path this is + PointsArray m_pathPoints; // our actual (x,y,z) path to the target + PathType m_type; // tells what kind of path this is - bool m_useStraightPath; // type of path will be generated - bool m_forceDestination; // when set, we will always arrive at given point + bool m_useStraightPath; // type of path will be generated + bool m_forceDestination; // when set, we will always arrive at given point - PathNode m_startPosition; // {x, y, z} of current location - PathNode m_nextPosition; // {x, y, z} of next location on the path - PathNode m_endPosition; // {x, y, z} of the destination - PathNode m_actualEndPosition; // {x, y, z} of the closest possible point to given destination + Vector3 m_startPosition; // {x, y, z} of current location + Vector3 m_endPosition; // {x, y, z} of the destination + Vector3 m_actualEndPosition;// {x, y, z} of the closest possible point to given destination const Unit* const m_sourceUnit; // the unit that is moving const dtNavMesh* m_navMesh; // the nav mesh @@ -94,23 +91,26 @@ class PathInfo dtQueryFilter m_filter; // use single filter for all movements, update it when needed - inline void setNextPosition(PathNode point) { m_nextPosition = point; } - inline void setStartPosition(PathNode point) { m_startPosition = point; } - inline void setEndPosition(PathNode point) { m_actualEndPosition = point; m_endPosition = point; } - inline void setActualEndPosition(PathNode point) { m_actualEndPosition = point; } + void setStartPosition(Vector3 point) { m_startPosition = point; } + void setEndPosition(Vector3 point) { m_actualEndPosition = point; m_endPosition = point; } + void setActualEndPosition(Vector3 point) { m_actualEndPosition = point; } - inline void clear() + void clear() { m_polyLength = 0; m_pathPoints.clear(); } - dtPolyRef getPathPolyByPosition(dtPolyRef *polyPath, uint32 polyPathSize, const float* point, float *distance = NULL); + bool inRange(const Vector3 &p1, const Vector3 &p2, float r, float h) const; + float dist3DSqr(const Vector3 &p1, const Vector3 &p2) const; + bool inRangeYZX(const float* v1, const float* v2, float r, float h) const; + + dtPolyRef getPathPolyByPosition(const dtPolyRef *polyPath, uint32 polyPathSize, const float* point, float *distance = NULL); dtPolyRef getPolyByLocation(const float* point, float *distance); - bool HaveTiles(const PathNode p) const; + bool HaveTiles(const Vector3 &p) const; - void BuildPolyPath(PathNode startPos, PathNode endPos); - void BuildPointPath(float *startPoint, float *endPoint); + void BuildPolyPath(const Vector3 &startPos, const Vector3 &endPos); + void BuildPointPath(const float *startPoint, const float *endPoint); void BuildShortcut(); NavTerrain getNavTerrain(float x, float y, float z); @@ -118,32 +118,15 @@ class PathInfo void updateFilter(); // smooth path functions - uint32 fixupCorridor(dtPolyRef* path, const uint32 npath, const uint32 maxPath, - const dtPolyRef* visited, const uint32 nvisited); - bool getSteerTarget(const float* startPos, const float* endPos, const float minTargetDist, - const dtPolyRef* path, const uint32 pathSize, float* steerPos, + uint32 fixupCorridor(dtPolyRef* path, uint32 npath, uint32 maxPath, + const dtPolyRef* visited, uint32 nvisited); + bool getSteerTarget(const float* startPos, const float* endPos, float minTargetDist, + const dtPolyRef* path, uint32 pathSize, float* steerPos, unsigned char& steerPosFlag, dtPolyRef& steerPosRef); dtStatus findSmoothPath(const float* startPos, const float* endPos, - const dtPolyRef* polyPath, const uint32 polyPathSize, + const dtPolyRef* polyPath, uint32 polyPathSize, float* smoothPath, int* smoothPathSize, bool &usedOffmesh, - const uint32 smoothPathMaxSize); + uint32 smoothPathMaxSize); }; -inline bool inRangeYZX(const float* v1, const float* v2, const float r, const float h) -{ - const float dx = v2[0] - v1[0]; - const float dy = v2[1] - v1[1]; // elevation - const float dz = v2[2] - v1[2]; - return (dx*dx + dz*dz) < r*r && fabsf(dy) < h; -} - -inline bool inRange(const PathNode p1, const PathNode p2, - const float r, const float h) -{ - const float dx = p2.x - p1.x; - const float dy = p2.y - p1.y; - const float dz = p2.z - p1.z; - return (dx*dx + dy*dy) < r*r && fabsf(dz) < h; -} - #endif diff --git a/src/game/QueryHandler.cpp b/src/game/QueryHandler.cpp index 686e9182c..7244e6f13 100644 --- a/src/game/QueryHandler.cpp +++ b/src/game/QueryHandler.cpp @@ -126,23 +126,6 @@ void WorldSession::SendNameQueryOpcodeFromDBCallBack(QueryResult *result, uint32 delete result; } -// Added By AHBot -// Fake name for AHBot Guid -void WorldSession::SendFakeNameForAHBotQueryOPcode() -{ - // guess size - WorldPacket data( SMSG_NAME_QUERY_RESPONSE, (8+1+1+1+1+1+10) ); - data.appendPackGUID(auctionbot.GetAHBObjectGuid().GetRawValue()); - data << uint8(0); // added in 3.1; if > 1, then end of packet - data << auctionbot.GetAHBotName(); // played name - data << uint8(0); // realm name for cross realm BG usage - data << uint8(0); // race - data << uint8(0); // gender - data << uint8(0); // class - data << uint8(0); // is not declined - SendPacket(&data); -} - void WorldSession::HandleNameQueryOpcode( WorldPacket & recv_data ) { ObjectGuid guid; @@ -150,13 +133,11 @@ void WorldSession::HandleNameQueryOpcode( WorldPacket & recv_data ) recv_data >> guid; Player *pChar = sObjectMgr.GetPlayer(guid); + if (pChar) SendNameQueryOpcode(pChar); else - if (guid!=auctionbot.GetAHBObjectGuid()) - SendNameQueryOpcodeFromDB(guid); - else - SendFakeNameForAHBotQueryOPcode(); + SendNameQueryOpcodeFromDB(guid); } void WorldSession::HandleQueryTimeOpcode( WorldPacket & /*recv_data*/ ) diff --git a/src/game/RandomMovementGenerator.cpp b/src/game/RandomMovementGenerator.cpp index 0d0b04f49..1eecde1e6 100644 --- a/src/game/RandomMovementGenerator.cpp +++ b/src/game/RandomMovementGenerator.cpp @@ -25,84 +25,30 @@ #include "movement/MoveSpline.h" template<> -void -RandomMovementGenerator::_setRandomLocation(Creature &creature) +void RandomMovementGenerator::_setRandomLocation(Creature &creature) { - float respX, respY, respZ, respO, currZ, destX, destY, destZ, wander_distance, travelDistZ; - + float respX, respY, respZ, respO, wander_distance; creature.GetRespawnCoord(respX, respY, respZ, &respO, &wander_distance); - currZ = creature.GetPositionZ(); - TerrainInfo const* map = creature.GetTerrain(); - - // For 2D/3D system selection - //bool is_land_ok = creature.CanWalk(); // not used? - //bool is_water_ok = creature.CanSwim(); // not used? - bool is_air_ok = creature.CanFly(); - const float angle = rand_norm_f() * (M_PI_F*2.0f); const float range = rand_norm_f() * wander_distance; - const float distanceX = range * cos(angle); - const float distanceY = range * sin(angle); - - destX = respX + distanceX; - destY = respY + distanceY; - - // prevent invalid coordinates generation - MaNGOS::NormalizeMapCoord(destX); - MaNGOS::NormalizeMapCoord(destY); - - travelDistZ = distanceX*distanceX + distanceY*distanceY; - - if (is_air_ok) // 3D system above ground and above water (flying mode) - { - // Limit height change - const float distanceZ = rand_norm_f() * sqrtf(travelDistZ)/2.0f; - destZ = respZ + distanceZ; - float levelZ = map->GetWaterOrGroundLevel(destX, destY, destZ-2.0f); - - // Problem here, we must fly above the ground and water, not under. Let's try on next tick - if (levelZ >= destZ) - return; - } - //else if (is_water_ok) // 3D system under water and above ground (swimming mode) - else // 2D only - { - // 10.0 is the max that vmap high can check (MAX_CAN_FALL_DISTANCE) - travelDistZ = travelDistZ >= 100.0f ? 10.0f : sqrtf(travelDistZ); - - // The fastest way to get an accurate result 90% of the time. - // Better result can be obtained like 99% accuracy with a ray light, but the cost is too high and the code is too long. - destZ = map->GetHeight(destX, destY, respZ+travelDistZ-2.0f, false); - - if (fabs(destZ - respZ) > travelDistZ) // Map check - { - // Vmap Horizontal or above - destZ = map->GetHeight(destX, destY, respZ - 2.0f, true); - - if (fabs(destZ - respZ) > travelDistZ) - { - // Vmap Higher - destZ = map->GetHeight(destX, destY, respZ+travelDistZ-2.0f, true); - - // let's forget this bad coords where a z cannot be find and retry at next tick - if (fabs(destZ - respZ) > travelDistZ) - return; - } - } - } - if (is_air_ok) - i_nextMoveTime.Reset(0); - else - i_nextMoveTime.Reset(urand(500, 10000)); + float destX = respX + range * cos(angle); + float destY = respY + range * sin(angle); + float destZ = creature.GetPositionZ(); + creature.UpdateAllowedPositionZ(destX, destY, destZ); creature.addUnitState(UNIT_STAT_ROAMING_MOVE); Movement::MoveSplineInit init(creature); - init.MoveTo(destX, destY, destZ); + init.MoveTo(destX, destY, destZ, true); init.SetWalk(true); init.Launch(); + + if (creature.CanFly()) + i_nextMoveTime.Reset(0); + else + i_nextMoveTime.Reset(urand(500, 10000)); } template<> diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index 381485ae6..91bfc0fa4 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -10058,7 +10058,7 @@ void Spell::EffectCharge(SpellEffectIndex /*eff_idx*/) ((Creature *)unitTarget)->StopMoving(); // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags - m_caster->MonsterMoveWithSpeed(x, y, z, 24.f); + m_caster->MonsterMoveWithSpeed(x, y, z, 24.f, true, true); // not all charge effects used in negative spells if (unitTarget != m_caster && !IsPositiveSpell(m_spellInfo->Id)) @@ -10086,11 +10086,8 @@ void Spell::EffectCharge2(SpellEffectIndex /*eff_idx*/) else return; - // Try to normalize Z coord cuz GetContactPoint do nothing with Z axis - unitTarget->UpdateGroundPositionZ(x, y, z); - // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags - m_caster->MonsterMoveWithSpeed(x, y, z, 24.f); + m_caster->MonsterMoveWithSpeed(x, y, z, 24.f, true, true); // not all charge effects used in negative spells if (unitTarget && unitTarget != m_caster && !IsPositiveSpell(m_spellInfo->Id)) diff --git a/src/game/TargetedMovementGenerator.h b/src/game/TargetedMovementGenerator.h index 4ffe241c4..11f91f729 100644 --- a/src/game/TargetedMovementGenerator.h +++ b/src/game/TargetedMovementGenerator.h @@ -41,8 +41,8 @@ class MANGOS_DLL_SPEC TargetedMovementGeneratorMedium TargetedMovementGeneratorMedium(Unit &target, float offset, float angle) : TargetedMovementGeneratorBase(target), i_offset(offset), i_angle(angle), i_recalculateTravel(false), i_targetReached(false), i_recheckDistance(0), - i_path(NULL), i_x(target.GetPositionX()), i_y(target.GetPositionY()), - i_z(target.GetPositionZ()) + i_path(NULL), i_x(target.GetPositionX()), i_y(target.GetPositionY()), + i_z(target.GetPositionZ()) { } ~TargetedMovementGeneratorMedium() { delete i_path; } @@ -52,7 +52,10 @@ class MANGOS_DLL_SPEC TargetedMovementGeneratorMedium bool GetDestination(float &x, float &y, float &z) const { - if(!i_destinationHolder.HasDestination()) return false; + //if(!i_destinationHolder.HasDestination()) + if (owner.movespline->Finalized()) + return false; + i_destinationHolder.GetDestination(x,y,z); return true; } diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 2f4fe3bef..5da0cf34f 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -46,8 +46,6 @@ #include "MapPersistentStateMgr.h" #include "GridNotifiersImpl.h" #include "CellImpl.h" -#include "Vehicle.h" -#include "Transports.h" #include "VMapFactory.h" #include "MovementGenerator.h" #include "movement/MoveSplineInit.h" @@ -9271,8 +9269,33 @@ bool Unit::SelectHostileTarget() if (!hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_DIED)) { SetInFront(target); - if (oldTarget != target) - ((Creature*)this)->AI()->AttackStart(target); + ((Creature*)this)->AI()->AttackStart(target); + + // check if currently selected target is reachable + // NOTE: path alrteady generated from AttackStart() + if(!GetMotionMaster()->operator->()->IsReachable()) + { + // remove all taunts + RemoveSpellsCausingAura(SPELL_AURA_MOD_TAUNT); + + if(m_ThreatManager.getThreatList().size() < 2) + { + // only one target in list, we have to evade after timer + // TODO: make timer - inside Creature class + ((Creature*)this)->AI()->EnterEvadeMode(); + } + else + { + // remove unreachable target from our threat list + // next iteration we will select next possible target + m_HostileRefManager.deleteReference(target); + m_ThreatManager.modifyThreatPercent(target, -101); + + _removeAttacker(target); + } + + return false; + } } return true; } @@ -11678,93 +11701,14 @@ void Unit::NearTeleportTo( float x, float y, float z, float orientation, bool ca } } -void Unit::MonsterMoveWithSpeed(float x, float y, float z, float speed) +void Unit::MonsterMoveWithSpeed(float x, float y, float z, float speed, bool generatePath, bool forceDestination) { Movement::MoveSplineInit init(*this); - init.MoveTo(x,y,z); + init.MoveTo(x,y,z, generatePath, forceDestination); init.SetVelocity(speed); init.Launch(); } -template -void Unit::MonsterMoveByPath(Path const& path, uint32 start, uint32 end, uint32 transitTime) -{ - SplineFlags flags = SPLINEFLAG_NONE; - if (GetTypeId() == TYPEID_UNIT) - flags = ((Creature*)this)->GetSplineFlags(); - else if (((Player*)this)->IsBot() && ((Player*)this)->IsFlying()) - flags = SPLINEFLAG_FLYING; - else - flags = SPLINEFLAG_WALKMODE; - - SendMonsterMoveByPath(path, start, end, flags, transitTime); - - if (GetTypeId() != TYPEID_PLAYER) - { - Creature* c = (Creature*)this; - // Creature relocation acts like instant movement generator, so current generator expects interrupt/reset calls to react properly - if (!c->GetMotionMaster()->empty()) - if (MovementGenerator *movgen = c->GetMotionMaster()->top()) - movgen->Interrupt(*c); - - GetMap()->CreatureRelocation((Creature*)this, path[end-1].x, path[end-1].y, path[end-1].z, 0.0f); - - // finished relocation, movegen can different from top before creature relocation, - // but apply Reset expected to be safe in any case - if (!c->GetMotionMaster()->empty()) - if (MovementGenerator *movgen = c->GetMotionMaster()->top()) - movgen->Reset(*c); - } - else - { - Player* p = (Player*)this; - if (!p || !p->IsBot()) - return; - - // Creature relocation acts like instant movement generator, so current generator expects interrupt/reset calls to react properly - if (!p->GetMotionMaster()->empty()) - if (MovementGenerator *movgen = p->GetMotionMaster()->top()) - movgen->Interrupt(*p); - - GetMap()->PlayerRelocation((Player*)this, path[end-1].x, path[end-1].y, path[end-1].z, 0.0f); - - // finished relocation, movegen can different from top before creature relocation, - // but apply Reset expected to be safe in any case - if (!p->GetMotionMaster()->empty()) - if (MovementGenerator *movgen = p->GetMotionMaster()->top()) - movgen->Reset(*p); - } -} - -template void Unit::MonsterMoveByPath(const Path &, uint32, uint32, uint32); - -void Unit::MonsterJump(float x, float y, float z, float o, uint32 transitTime, uint32 verticalSpeed) -{ -// SendMonsterMove(x, y, z, SPLINETYPE_NORMAL, SplineFlags(SPLINEFLAG_TRAJECTORY | SPLINEFLAG_WALKMODE), transitTime, NULL, double(verticalSpeed)); - MonsterMoveWithSpeed(x, y, z, 28); -/* - if (GetTypeId() != TYPEID_PLAYER) - { - // Interrupt spells cause of movement - InterruptNonMeleeSpells(false); - - Creature* c = (Creature*)this; - // Creature relocation acts like instant movement generator, so current generator expects interrupt/reset calls to react properly - if (!c->GetMotionMaster()->empty()) - if (MovementGenerator *movgen = c->GetMotionMaster()->top()) - movgen->Interrupt(*c); - - GetMap()->CreatureRelocation((Creature*)this, x, y, z, o); - - // finished relocation, movegen can different from top before creature relocation, - // but apply Reset expected to be safe in any case - if (!c->GetMotionMaster()->empty()) - if (MovementGenerator *movgen = c->GetMotionMaster()->top()) - movgen->Reset(*c); - } -*/ -} - struct SetPvPHelper { explicit SetPvPHelper(bool _state) : state(_state) {} @@ -12152,103 +12096,6 @@ SpellAuraHolder* Unit::GetSpellAuraHolder (uint32 spellid, ObjectGuid casterGuid return NULL; } -void Unit::RemoveUnitFromHostileRefManager(Unit* pUnit) -{ - getHostileRefManager().deleteReference(pUnit); -} - -void Unit::_AddAura(uint32 spellID, uint32 duration) -{ - SpellEntry const *spellInfo = sSpellStore.LookupEntry( spellID ); - - if(spellInfo) - { - if (IsSpellAppliesAura(spellInfo, (1 << EFFECT_INDEX_0) | (1 << EFFECT_INDEX_1) | (1 << EFFECT_INDEX_2)) || IsSpellHaveEffect(spellInfo, SPELL_EFFECT_PERSISTENT_AREA_AURA)) - { - SpellAuraHolder* holder = CreateSpellAuraHolder(spellInfo, this, this); - - for(uint8 i = 0; i < MAX_EFFECT_INDEX; ++i) - { - if (spellInfo->Effect[i] >= TOTAL_SPELL_EFFECTS) - continue; - if( IsAreaAuraEffect(spellInfo->Effect[i]) || - spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA || - spellInfo->Effect[i] == SPELL_EFFECT_PERSISTENT_AREA_AURA ) - { - Aura *aura = CreateAura(spellInfo, SpellEffectIndex(i), NULL, holder, this); - holder->AddAura(aura, SpellEffectIndex(i)); - holder->SetAuraDuration(duration); - DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Manually adding aura of spell %u, index %u, duration %u ms", spellID, i, duration); - } - } - AddSpellAuraHolder(holder); - } - } -} - -template -void Unit::SendMonsterMoveByPath(Path const& path, uint32 start, uint32 end, SplineFlags flags, uint32 traveltime) -{ - uint32 pathSize = end - start; - - if (pathSize < 1) - { - SendMonsterMove(GetPositionX(), GetPositionY(), GetPositionZ(), SPLINETYPE_STOP, flags, 0); - return; - } - - if (pathSize == 1) - { - SendMonsterMove(path[start].x, path[start].y, path[start].z, SPLINETYPE_NORMAL, flags, traveltime); - return; - } - - uint32 packSize = (flags & SplineFlags(SPLINEFLAG_FLYING | SPLINEFLAG_CATMULLROM)) ? pathSize*4*3 : 4*3 + (pathSize-1)*4; - WorldPacket data( SMSG_MONSTER_MOVE, (GetPackGUID().size()+1+4+4+4+4+1+4+4+4+packSize) ); - data << GetPackGUID(); - data << uint8(0); - data << GetPositionX(); - data << GetPositionY(); - data << GetPositionZ(); - data << uint32(WorldTimer::getMSTime()); - data << uint8(SPLINETYPE_NORMAL); - data << uint32(flags); - data << uint32(traveltime); - data << uint32(pathSize); - - if (flags & SplineFlags(SPLINEFLAG_FLYING | SPLINEFLAG_CATMULLROM)) - { - // sending a taxi flight path - for (uint32 i = start; i < end; ++i) - { - data << float(path[i].x); - data << float(path[i].y); - data << float(path[i].z); - } - } - else - { - // sending a series of points - - // destination - data << path[end-1].x; - data << path[end-1].y; - data << path[end-1].z; - - // all other points are relative to the center of the path - float mid_X = (GetPositionX() + path[end-1].x) * 0.5f; - float mid_Y = (GetPositionY() + path[end-1].y) * 0.5f; - float mid_Z = (GetPositionZ() + path[end-1].z) * 0.5f; - - for (uint32 i = start; i < end - 1; ++i) - data.appendPackXYZ(mid_X - path[i].x, mid_Y - path[i].y, mid_Z - path[i].z); - } - - SendMessageToSet(&data, true); -} - -template void Unit::SendMonsterMoveByPath(const Path &, uint32, uint32, SplineFlags, uint32); - bool Unit::IsAllowedDamageInArea(Unit* pVictim) const { // can damage self anywhere diff --git a/src/game/Unit.h b/src/game/Unit.h index b66bc092a..c739377e3 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -412,9 +412,7 @@ enum UnitState UNIT_STAT_FLEEING = 0x00020000, // FleeMovementGenerator/TimedFleeingMovementGenerator active/onstack UNIT_STAT_FLEEING_MOVE = 0x00040000, UNIT_STAT_ON_VEHICLE = 0x00080000, // Unit is on vehicle - - UNIT_STAT_IGNORE_PATHFINDING = 0x00080000, // do not use pathfinding in any MovementGenerator - + UNIT_STAT_IGNORE_PATHFINDING = 0x00100000, // do not use pathfinding in any MovementGenerator // masks (only for check) // can't move currently @@ -1489,14 +1487,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject void SendSpellMiss(Unit *target, uint32 spellID, SpellMissInfo missInfo); void NearTeleportTo(float x, float y, float z, float orientation, bool casting = false); - void MonsterJump(float x, float y, float z, float o, uint32 transitTime, uint32 verticalSpeed); - // recommend use MonsterMove/MonsterMoveWithSpeed for most case that correctly work with movegens - // if used additional args in ... part then floats must explicitly casted to double - void SendMonsterMoveJump(float NewPosX, float NewPosY, float NewPosZ, float vert_speed, uint32 flags, uint32 Time, Player* player = NULL); - void SendMonsterMoveTransport(WorldObject *transport, SplineType type, SplineFlags flags, uint32 moveTime, ...); - virtual bool SetPosition(float x, float y, float z, float orientation, bool teleport = false); - - void MonsterMoveWithSpeed(float x, float y, float z, float speed); + void MonsterMoveWithSpeed(float x, float y, float z, float speed, bool generatePath = false, bool forceDestination = false); // recommend use MonsterMove/MonsterMoveWithSpeed for most case that correctly work with movegens // if used additional args in ... part then floats must explicitly casted to double void SendHeartBeat(); diff --git a/src/game/WorldSession.h b/src/game/WorldSession.h index 4f2c2bca5..073bee09c 100644 --- a/src/game/WorldSession.h +++ b/src/game/WorldSession.h @@ -257,7 +257,6 @@ class MANGOS_DLL_SPEC WorldSession void SendNameQueryOpcode(Player* p); void SendNameQueryOpcodeFromDB(ObjectGuid guid); static void SendNameQueryOpcodeFromDBCallBack(QueryResult *result, uint32 accountId); - void SendFakeNameForAHBotQueryOPcode(); void SendTrainerList(ObjectGuid guid); void SendTrainerList(ObjectGuid guid, const std::string& strTitle ); diff --git a/src/game/movement/MoveSpline.h b/src/game/movement/MoveSpline.h index 3ee5b49ad..459010be7 100644 --- a/src/game/movement/MoveSpline.h +++ b/src/game/movement/MoveSpline.h @@ -77,7 +77,6 @@ namespace Movement UpdateResult _updateState(int32& ms_time_diff); int32 next_timestamp() const { return spline.length(point_Idx+1);} int32 segment_time_elapsed() const { return next_timestamp()-time_passed;} - int32 Duration() const { return spline.length();} int32 timeElapsed() const { return Duration() - time_passed;} int32 timePassed() const { return time_passed;} @@ -120,6 +119,8 @@ namespace Movement const Vector3 CurrentDestination() const { return Initialized() ? spline.getPoint(point_Idx+1) : Vector3();} int32 currentPathIdx() const; + int32 Duration() const { return spline.length();} + std::string ToString() const; }; } diff --git a/src/game/movement/MoveSplineInit.cpp b/src/game/movement/MoveSplineInit.cpp index fb823fb25..380e1a7fc 100644 --- a/src/game/movement/MoveSplineInit.cpp +++ b/src/game/movement/MoveSplineInit.cpp @@ -50,7 +50,7 @@ namespace Movement return MOVE_RUN; } - void MoveSplineInit::Launch() + int32 MoveSplineInit::Launch() { MoveSpline& move_spline = *unit.movespline; @@ -80,7 +80,7 @@ namespace Movement args.velocity = unit.GetSpeed(SelectSpeedType(moveFlags)); if (!args.Validate()) - return; + return 0; unit.m_movementInfo.SetMovementFlags((MovementFlags)moveFlags); move_spline.Initialize(args); @@ -89,6 +89,8 @@ namespace Movement data << unit.GetPackGUID(); PacketBuilder::WriteMonsterMove(move_spline, data); unit.SendMessageToSet(&data,true); + + return move_spline.Duration(); } MoveSplineInit::MoveSplineInit(Unit& m) : unit(m) diff --git a/src/game/movement/MoveSplineInit.h b/src/game/movement/MoveSplineInit.h index ed7ddc6d4..bd57d098d 100644 --- a/src/game/movement/MoveSplineInit.h +++ b/src/game/movement/MoveSplineInit.h @@ -20,6 +20,7 @@ #define MANGOSSERVER_MOVESPLINEINIT_H #include "MoveSplineInitArgs.h" +#include "../PathFinder.h" class Unit; @@ -33,9 +34,10 @@ namespace Movement explicit MoveSplineInit(Unit& m); - /* Final pass of initialization that launches spline movement. + /* Final pass of initialization that launches spline movement. + * @return duration - estimated travel time */ - void Launch(); + int32 Launch(); /* Adds movement by parabolic trajectory * @param amplitude - the maximum height of parabola, value could be negative and positive @@ -60,8 +62,8 @@ namespace Movement /* Initializes simple A to B mition, A is current unit's position, B is destination */ - void MoveTo(const Vector3& destination); - void MoveTo(float x, float y, float z); + void MoveTo(const Vector3& destination, bool generatePath = false, bool forceDestination = false); + void MoveTo(float x, float y, float z, bool generatePath = false, bool forceDestination = false); /* Sets Id of fisrt point of the path. When N-th path point will be done ILisener will notify that pointId + N done * Needed for waypoint movement where path splitten into parts @@ -126,17 +128,26 @@ namespace Movement args.path.assign(controls.begin(),controls.end()); } - inline void MoveSplineInit::MoveTo(float x, float y, float z) + inline void MoveSplineInit::MoveTo(float x, float y, float z, bool generatePath, bool forceDestination) { Vector3 v(x,y,z); - MoveTo(v); + MoveTo(v, generatePath, forceDestination); } - inline void MoveSplineInit::MoveTo(const Vector3& dest) + inline void MoveSplineInit::MoveTo(const Vector3& dest, bool generatePath, bool forceDestination) { - args.path_Idx_offset = 0; - args.path.resize(2); - args.path[1] = dest; + if(generatePath) + { + PathInfo path(&unit); + path.calculate(dest.x, dest.y, dest.z, false, forceDestination); + MovebyPath(path.getPath()); + } + else + { + args.path_Idx_offset = 0; + args.path.resize(2); + args.path[1] = dest; + } } inline void MoveSplineInit::SetParabolic(float amplitude, float time_shift, bool is_knockback) diff --git a/src/game/playerbot/PlayerbotAI.cpp b/src/game/playerbot/PlayerbotAI.cpp index 21dd7d77b..d1d40c63e 100644 --- a/src/game/playerbot/PlayerbotAI.cpp +++ b/src/game/playerbot/PlayerbotAI.cpp @@ -1105,7 +1105,7 @@ bool PlayerbotAI::SetInFront(const Unit* obj) y = m_bot->m_movementInfo.GetPos()->y; z = m_bot->m_movementInfo.GetPos()->z; m_bot->m_movementInfo.ChangePosition(x,y,z,ori); - m_bot->SendHeartBeat(false); + m_bot->SendHeartBeat(); return true; } diff --git a/win/VC100/shared.vcxproj.filters b/win/VC100/shared.vcxproj.filters index 6b2321425..27c042c23 100644 --- a/win/VC100/shared.vcxproj.filters +++ b/win/VC100/shared.vcxproj.filters @@ -75,10 +75,6 @@ - - - - Database @@ -174,10 +170,6 @@ - - - - Database