static bool HandleMmapPathCommand(ChatHandler* handler, char const* args) { if (!MMAP::MMapFactory::createOrGetMMapManager()->GetNavMesh(handler->GetSession()->GetPlayer()->GetMapId())) { handler->PSendSysMessage("NavMesh not loaded for current map."); return true; } handler->PSendSysMessage("mmap path:"); // units Player* player = handler->GetSession()->GetPlayer(); Unit* target = handler->getSelectedUnit(); if (!player || !target) { handler->PSendSysMessage("Invalid target/source selection."); return true; } char* para = strtok((char*)args, " "); bool useStraightPath = false; if (para && strcmp(para, "true") == 0) useStraightPath = true; // unit locations float x, y, z; player->GetPosition(x, y, z); // path PathGenerator path(target); path.SetUseStraightPath(useStraightPath); bool result = path.CalculatePath(x, y, z); PointsArray pointPath = path.GetPath(); handler->PSendSysMessage("%s's path to %s:", target->GetName(), player->GetName()); handler->PSendSysMessage("Building: %s", useStraightPath ? "StraightPath" : "SmoothPath"); handler->PSendSysMessage("Result: %s - Length: %i - Type: %u", (result ? "true" : "false"), pointPath.size(), path.GetPathType()); Vector3 start = path.GetStartPosition(); Vector3 end = path.GetEndPosition(); Vector3 actualEnd = path.GetActualEndPosition(); handler->PSendSysMessage("StartPosition (%.3f, %.3f, %.3f)", start.x, start.y, start.z); handler->PSendSysMessage("EndPosition (%.3f, %.3f, %.3f)", end.x, end.y, end.z); handler->PSendSysMessage("ActualEndPosition (%.3f, %.3f, %.3f)", actualEnd.x, actualEnd.y, actualEnd.z); if (!player->isGameMaster()) handler->PSendSysMessage("Enable GM mode to see the path points."); for (uint32 i = 0; i < pointPath.size(); ++i) player->SummonCreature(VISUAL_WAYPOINT, pointPath[i].x, pointPath[i].y, pointPath[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 9000); return true; }
void WalkerDebugInfo::showPath( WalkerPtr walker, gfx::Engine& engine, gfx::Camera* camera, NColor color ) { Point camOffset = camera->offset(); const Pathway& pathway = walker->pathway(); const TilesArray& tiles = pathway.allTiles(); NColor pathColor = color; if( color == 0) { if( walker->agressive() > 0 ) { pathColor = DefaultColors::red; } else { pathColor = pathway.isReverse() ? DefaultColors::blue : DefaultColors::green; } } Point pos = walker->mappos(); Point xOffset( tilemap::cellSize().width(), 0 ); PointsArray points; if( pathway.isReverse() ) { int rStart = pathway.length() - pathway.curStep(); for( int step=rStart-1; step >= 0; step-- ) { pos = tiles[ step ]->mappos() + camOffset + xOffset; points.push_back( pos ); } } else { for( unsigned int step=pathway.curStep()+1; step < tiles.size(); step++ ) { pos = tiles[ step ]->mappos() + camOffset + xOffset; points.push_back( pos ); } } engine.drawLines( pathColor, points ); }
void set( Senate::Status status, Picture pic, const Point& offset ) { if( status >= pics.size() ) { pics.resize( status+1 ); offsets.resize( status+1 ); } offsets[ status ] = offset; pics[ status ] = pic; }
Point getOffset( Senate::Status st ) const { return offsets.valueOrEmpty( st ); }
void PathFinder::BuildPointPath(const float* startPoint, const float* endPoint) { float pathPoints[MAX_POINT_PATH_LENGTH * VERTEX_SIZE]; uint32 pointCount = 0; dtStatus dtResult = DT_FAILURE; if (m_useStraightPath) { dtResult = m_navMeshQuery->findStraightPath( startPoint, // start position endPoint, // end position m_pathPolyRefs, // current path m_polyLength, // lenth of current path pathPoints, // [out] path corner points NULL, // [out] flags NULL, // [out] shortened path (int*)&pointCount, m_pointPathLimit); // maximum number of points/polygons to use } else { dtResult = findSmoothPath( startPoint, // start position endPoint, // end position m_pathPolyRefs, // current path m_polyLength, // length of current path pathPoints, // [out] path corner points (int*)&pointCount, m_pointPathLimit); // maximum number of points } if (pointCount < 2 || dtStatusFailed(dtResult)) { // only happens if pass bad data to findStraightPath or navmesh is broken // single point paths can be generated here // TODO : check the exact cases DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathFinder::BuildPointPath FAILED! path sized %d returned\n", pointCount); BuildShortcut(); m_type = PATHFIND_NOPATH; return; } uint32 tempPointCounter = 2; uint8 cutLimit = 0; PointsArray tempPathPoints; tempPathPoints.resize(pointCount); for (uint32 i = 0; i < pointCount; ++i) tempPathPoints[i] = Vector3(pathPoints[i*VERTEX_SIZE+2], pathPoints[i*VERTEX_SIZE], pathPoints[i*VERTEX_SIZE+1]); // Optimize points for (uint32 i = 1; i < pointCount - 1; ++i) { G3D::Vector3 p = tempPathPoints[i]; // Point G3D::Vector3 p1 = tempPathPoints[i - 1]; // PrevPoint G3D::Vector3 p2 = tempPathPoints[i + 1]; // NextPoint float line = (p1.y - p2.y) * p.x + (p2.x - p1.x) * p.y + (p1.x * p2.y - p2.x * p1.y); if (fabs(line) < LINE_FAULT && cutLimit < SKIP_POINT_LIMIT) { tempPathPoints[i] = Vector3(0, 0, 0); ++cutLimit; } else { ++tempPointCounter; cutLimit = 0; } } m_pathPoints.resize(tempPointCounter); uint32 b = 0; for (uint32 i = 0; i < pointCount; ++i) { if (tempPathPoints[i] != Vector3(0, 0, 0)) { m_pathPoints[b] = tempPathPoints[i]; ++b; } } pointCount = tempPointCounter; // first point is always our current location - we need the next one 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))) { // 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); } DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathFinder::BuildPointPath path type %d size %d poly-size %d\n", m_type, pointCount, m_polyLength); }
bool Transport::GenerateWaypoints(uint32 pathid, uint32 moveSpeed, uint32 accelRate, std::set<uint32> &mapids) { if (pathid >= sTaxiPathNodesByPath.size()) return false; TaxiPathNodeList const& path = sTaxiPathNodesByPath[pathid]; PointsArray splinepath; float velocity = moveSpeed; uint32 time_step = 500; mapids.clear(); bool never_teleport = true; //if never teleported is cyclic path uint32 t = 0; uint32 start = 0; for (size_t i = 0; i < path.size(); ++i) { TaxiPathNodeEntry const& node_i = path[i]; splinepath.push_back(G3D::Vector3(node_i.x, node_i.y, node_i.z)); //split path in segments bool teleport = node_i.mapid != path[(i+1)%path.size()].mapid || (path[i].actionFlag == 1); //teleport on next node? if (teleport || i == path.size() - 1) { never_teleport &= !teleport; mapids.insert(node_i.mapid); //re-add first node for cyclic path if never teleported if(i == path.size() - 1 && never_teleport) splinepath.push_back(G3D::Vector3(path[0].x, path[0].y, path[0].z)); //generate spline for seg Spline<int32> spline; spline.init_spline(&splinepath[0], splinepath.size(), SplineBase::ModeCatmullrom); CommonInitializer init(velocity); spline.initLengths(init); sLog->outDebug(LOG_FILTER_TRANSPORTS, "[%d] Generate spline for seg: %d-%d (%d-%d)", pathid, start+spline.first()-1, start+spline.last()-1, spline.first(), spline.last()); //add first point of seg to waypoints m_WayPoints[t] = WayPoint(path[start].mapid, path[start].x, path[start].y, path[start].z, false, path[start].index, path[start].arrivalEventID, path[start].departureEventID); t += path[start].delay; sLog->outDebug(LOG_FILTER_TRANSPORTS, "[%d] %d T: %d, x: %f, y: %f, z: %f, t:%d", pathid, path[start].index, t, path[start].x, path[start].y, path[start].z, false); //sample the segment for (int32 point_Idx = spline.first(); point_Idx < spline.last(); ++point_Idx) { uint32 node_Idx = (start + point_Idx) % path.size(); float u = 1.0f; int32 seg_time = spline.length(point_Idx, point_Idx + 1); uint32 time_passed = time_step; do { if (seg_time > 0) u = time_passed / (float)seg_time; if (u >= 1) break; Location c; spline.evaluate_percent(point_Idx, u, c); if (path[node_Idx].actionFlag == 2) t += time_step / accelRate; //deceleration else if (node_Idx > 1 && path[node_Idx-1].actionFlag == 2) t += time_step / accelRate; //acceleration //add sample to waypoints m_WayPoints[t + time_passed] = WayPoint(node_i.mapid, c.x, c.y, c.z, false, 0); sLog->outDebug(LOG_FILTER_TRANSPORTS, "[%d] T: %d, x: %f, y: %f, z: %f, t:%d", pathid, t + time_passed, c.x, c.y, c.z, false); time_passed += time_step; } while (u < 1.0f); t += seg_time; //add point to waypoints (if isn't first) if (node_Idx > 0) { bool teleport_on_this_node = (point_Idx == spline.last() - 1 ? teleport : false); //if is the last node of segment -> teleport teleport_on_this_node |= (node_Idx == path.size() -1 ? !never_teleport : false); //if is the last node of path, teleport if teleported at least one time m_WayPoints[t] = WayPoint(path[node_Idx].mapid, path[node_Idx].x, path[node_Idx].y, path[node_Idx].z, teleport_on_this_node, path[node_Idx].index, path[node_Idx].arrivalEventID, path[node_Idx].departureEventID); sLog->outDebug(LOG_FILTER_TRANSPORTS, "[%d] %d T: %d, x: %f, y: %f, z: %f, t:%d", pathid, path[node_Idx].index, t, path[node_Idx].x, path[node_Idx].y, path[node_Idx].z, teleport_on_this_node); //if (path[node_Idx].actionFlag == 2) //add delay - always or only on actionFlag == 2? t += path[node_Idx].delay * 1000; } } splinepath.clear(); start = i + 1; } } m_curr = m_WayPoints.begin(); m_next = GetNextWayPoint(); m_pathTime = t; return true; }
void MoveSplineInit::MovebyPath(PointsArray const& controls, int32 path_offset) { args.path_Idx_offset = path_offset; args.path.resize(controls.size()); std::transform(controls.begin(), controls.end(), args.path.begin(), TransportPathTransform(unit, args.TransformForTransport)); }