void PathInfo::BuildPolyPath(PathNode startPos, PathNode endPos) { // *** 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}; dtPolyRef startPoly = getPolyByLocation(startPoint, &distToStartPoly); dtPolyRef endPoly = getPolyByLocation(endPoint, &distToEndPoly); // we have a hole in our mesh // make shortcut path and mark it as NOPATH ( with flying exception ) // its up to caller how he will use this info if (startPoly == INVALID_POLYREF || endPoly == INVALID_POLYREF) { DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: (startPoly == 0 || endPoly == 0)\n"); BuildShortcut(); m_type = (m_sourceUnit->GetTypeId() == TYPEID_UNIT && ((Creature*)m_sourceUnit)->CanFly()) ? PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH) : PATHFIND_NOPATH; return; } // we may need a better number here bool farFromPoly = (distToStartPoly > 7.0f || distToEndPoly > 7.0f); if (farFromPoly) { DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: farFromPoly distToStartPoly=%.3f distToEndPoly=%.3f\n", distToStartPoly, distToEndPoly); bool buildShotrcut = false; if (m_sourceUnit->GetTypeId() == TYPEID_UNIT) { Creature* owner = (Creature*)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 :: underWater case\n"); if (owner->CanSwim() || owner->IsPet()) buildShotrcut = true; } else { DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: flying case\n"); if (owner->CanFly()) buildShotrcut = true; } } if (buildShotrcut) { BuildShortcut(); m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); return; } else { float closestPoint[VERTEX_SIZE]; // we may want to use closestPointOnPolyBoundary instead if (DT_SUCCESS == m_navMeshQuery->closestPointOnPoly(endPoly, endPoint, closestPoint)) { dtVcopy(endPoint, closestPoint); setActualEndPosition(PathNode(endPoint[2],endPoint[0],endPoint[1])); } m_type = PATHFIND_INCOMPLETE; } } // *** poly path generating logic *** // start and end are on same polygon // just need to move in straight line if (startPoly == endPoly) { DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: (startPoly == endPoly)\n"); BuildShortcut(); m_pathPolyRefs[0] = startPoly; m_polyLength = 1; m_type = farFromPoly ? PATHFIND_INCOMPLETE : PATHFIND_NORMAL; DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: path type %d\n", m_type); return; } // look for startPoly/endPoly in current path // TODO: we can merge it with getPathPolyByPosition() loop bool startPolyFound = false; bool endPolyFound = false; uint32 pathStartIndex, pathEndIndex; if (m_polyLength) { for (pathStartIndex = 0; pathStartIndex < m_polyLength; ++pathStartIndex) { // here to carch few bugs MANGOS_ASSERT(m_pathPolyRefs[pathStartIndex] != INVALID_POLYREF); if (m_pathPolyRefs[pathStartIndex] == startPoly) { startPolyFound = true; break; } } for (pathEndIndex = m_polyLength-1; pathEndIndex > pathStartIndex; --pathEndIndex) if (m_pathPolyRefs[pathEndIndex] == endPoly) { endPolyFound = true; break; } } if (startPolyFound && endPolyFound) { DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: (startPolyFound && endPolyFound)\n"); // we moved along the path and the target did not move out of our old poly-path // our path is a simple subpath case, we have all the data we need // just "cut" it out m_polyLength = pathEndIndex - pathStartIndex + 1; memmove(m_pathPolyRefs, m_pathPolyRefs+pathStartIndex, m_polyLength*sizeof(dtPolyRef)); } else if (startPolyFound && !endPolyFound) { DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: (startPolyFound && !endPolyFound)\n"); // we are moving on the old path but target moved out // so we have atleast part of poly-path ready m_polyLength -= pathStartIndex; // try to adjust the suffix of the path instead of recalculating entire length // at given interval the target cannot get too far from its last location // thus we have less poly to cover // sub-path of optimal path is optimal // take ~80% of the original length // TODO : play with the values here uint32 prefixPolyLength = uint32(m_polyLength*0.8f + 0.5f); memmove(m_pathPolyRefs, m_pathPolyRefs+pathStartIndex, prefixPolyLength*sizeof(dtPolyRef)); dtPolyRef suffixStartPoly = m_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]; 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->GetGUID()); BuildShortcut(); m_type = PATHFIND_NOPATH; return; } // generate suffix uint32 suffixPolyLength = 0; dtStatus dtResult = m_navMeshQuery->findPath( suffixStartPoly, // start polygon endPoly, // end polygon suffixEndPoint, // start position endPoint, // end position &m_filter, // polygon search filter m_pathPolyRefs + prefixPolyLength - 1, // [out] path (int*)&suffixPolyLength, MAX_PATH_LENGTH-prefixPolyLength); // max number of polygons in output path if (!suffixPolyLength || dtResult != DT_SUCCESS) { // 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->GetGUID()); } DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ m_polyLength=%u prefixPolyLength=%u suffixPolyLength=%u \n",m_polyLength, prefixPolyLength, suffixPolyLength); // new path = prefix + suffix - overlap m_polyLength = prefixPolyLength + suffixPolyLength - 1; } else { DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ BuildPolyPath :: (!startPolyFound && !endPolyFound)\n"); // either we have no path at all -> first run // or something went really wrong -> we aren't moving along the path to the target // just generate new path // free and invalidate old path data clear(); dtStatus dtResult = m_navMeshQuery->findPath( startPoly, // start polygon endPoly, // end polygon startPoint, // start position endPoint, // end position &m_filter, // polygon search filter m_pathPolyRefs, // [out] path (int*)&m_polyLength, MAX_PATH_LENGTH); // max number of polygons in output path 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->GetGUID()); BuildShortcut(); m_type = PATHFIND_NOPATH; return; } } // by now we know what type of path we can get if (m_pathPolyRefs[m_polyLength - 1] == endPoly && !(m_type & PATHFIND_INCOMPLETE)) m_type = PATHFIND_NORMAL; else m_type = PATHFIND_INCOMPLETE; // generate the point-path out of our up-to-date poly-path BuildPointPath(startPoint, endPoint); }
void VehicleInstance::setDestinationV(Mission *m, int x, int y, int z, int ox, int oy, int new_speed) { std::set < PathNode > open, closed; std::map < PathNode, PathNode > parent; m->adjXYZ(x, y, z); z = tile_z_; dest_path_.clear(); setSpeed(0); if (map_ == -1 || health_ <= 0 || !(walkable(x, y, z))) return; if (!walkable(tile_x_, tile_y_, tile_z_)) { float dBest = 100000, dCur; int xBest,yBest; // we got somewhere we shouldn't, we need to find somewhere that is walkable for (int j = 0; j < 5; j++) for (int i = 0; i < 5; i++) if (walkable(tile_x_ + i, tile_y_ + j, tile_z_)) { dCur = sqrt((float)(i*i + j*j)); if(dCur < dBest) { xBest = tile_x_ + i; yBest = tile_y_ + j; dBest = dCur; } } for (int j = 0; j < 5; j++) for (int i = 0; i > -5; --i) if (walkable(tile_x_ + i, tile_y_ + j, tile_z_)) { dCur = sqrt((float)(i*i + j*j)); if(dCur < dBest) { xBest = tile_x_ + i; yBest = tile_y_ + j; dBest = dCur; } } for (int j = 0; j > -5; --j) for (int i = 0; i > -5; --i) if (walkable(tile_x_ + i, tile_y_ + j, tile_z_)) { dCur = sqrt((float)(i*i + j*j)); if(dCur < dBest) { xBest = tile_x_ + i; yBest = tile_y_ + j; } } for (int j = 0; j > -5; --j) for (int i = 0; i < 5; i++) if (walkable(tile_x_ + i, tile_y_ + j, tile_z_)) { dCur = sqrt((float)(i*i + j*j)); if(dCur < dBest) { xBest = tile_x_ + i; yBest = tile_y_ + j; dBest = dCur; } } if(dBest == 100000) return; else { tile_x_ = xBest; tile_y_ = yBest; } } PathNode closest; float closest_dist = 100000; open.insert(PathNode(tile_x_, tile_y_, tile_z_, off_x_, off_y_)); int watchDog = 1000; while (!open.empty()) { watchDog--; float dist = 100000; PathNode p; std::set < PathNode >::iterator pit; for (std::set < PathNode >::iterator it = open.begin(); it != open.end(); it++) { float d = sqrt((float) (x - it->tileX()) * (x - it->tileX()) + (y - it->tileY()) * (y - it->tileY())); if (d < dist) { dist = d; p = *it; pit = it; // it cannot be const_iterator because of this assign } } if (dist < closest_dist) { closest = p; closest_dist = dist; } //printf("found best dist %f in %i nodes\n", dist, open.size()); open.erase(pit); closed.insert(p); if ((p.tileX() == x && p.tileY() == y && p.tileZ() == z) || watchDog < 0) { if (watchDog < 0) { p = closest; dest_path_. push_front(PathNode (p.tileX(), p.tileY(), p.tileZ(), ox, oy)); } else dest_path_.push_front(PathNode(x, y, z, ox, oy)); while (parent.find(p) != parent.end()) { p = parent[p]; if (p.tileX() == tile_x_ && p.tileY() == tile_y_ && p.tileZ() == tile_z_) break; dest_path_.push_front(p); } break; } std::list < PathNode > neighbours; uint32 goodDir = tileDir(p.tileX(), p.tileY(), p.tileZ()); if (p.tileX() > 0) { if (dirWalkable(&p,p.tileX() - 1, p.tileY(), p.tileZ()) && ((goodDir & 0xFF000000) == 0x06000000 || goodDir == 0xFFFFFFFF)) neighbours. push_back(PathNode(p.tileX() - 1, p.tileY(), p.tileZ())); } if (p.tileX() < g_App.maps().map(map())->maxX()) { if (dirWalkable(&p,p.tileX() + 1, p.tileY(), p.tileZ()) && ((goodDir & 0x0000FF00) == 0x00000200 || goodDir == 0xFFFFFFFF)) neighbours. push_back(PathNode(p.tileX() + 1, p.tileY(), p.tileZ())); } if (p.tileY() > 0) if (dirWalkable(&p,p.tileX(), p.tileY() - 1, p.tileZ()) && ((goodDir & 0x00FF0000) == 0x00040000 || goodDir == 0xFFFFFFFF)) neighbours. push_back(PathNode(p.tileX(), p.tileY() - 1, p.tileZ())); if (p.tileY() < g_App.maps().map(map())->maxY()) if (dirWalkable(&p,p.tileX(), p.tileY() + 1, p.tileZ()) && ((goodDir & 0x000000FF) == 0x0 || goodDir == 0xFFFFFFFF)) neighbours. push_back(PathNode(p.tileX(), p.tileY() + 1, p.tileZ())); for (std::list < PathNode >::iterator it = neighbours.begin(); it != neighbours.end(); it++) if (dirWalkable(&p,it->tileX(), it->tileY(), it->tileZ()) && open.find(*it) == open.end() && closed.find(*it) == closed.end()) { parent[*it] = p; open.insert(*it); } } if(!dest_path_.empty()) { // Adjusting offsets for correct positioning speed_ = new_speed; for(std::list < PathNode >::iterator it = dest_path_.begin(); it != dest_path_.end(); it++) { // TODO : requires testing for correct offsets per // every direction, because in some part of game // vehicle position on start of game can create incorrect // visual representation // maybe offsets depend on type or tileZ? switch(tileDir(it->tileX(), it->tileY(), it->tileZ())) { case 0xFFFFFF00: case 0xFFFF0200: it->setOffX(200); it->setOffY(32); break; case 0xFF04FFFF: it->setOffX(32); it->setOffY(200); break; case 0xFFFF02FF: case 0xFF0402FF: it->setOffX(32); it->setOffY(32); break; case 0x06FFFFFF: case 0x0604FFFF: it->setOffX(32); it->setOffY(200); break; case 0x06FFFF00: it->setOffX(200); it->setOffY(200); break; default: printf("hmm tileDir %X\n", (unsigned int)tileDir(it->tileX(), it->tileY(), it->tileZ())); break; } } } }
void PathInfo::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 || dtResult != DT_SUCCESS) { // 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, "++ PathInfo::BuildPointPath FAILED! path sized %d returned\n", pointCount); BuildShortcut(); m_type = PATHFIND_NOPATH; return; } 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])); // 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))) { // we may want to keep partial subpath if (dist3DSqr(getActualEndPosition(), getEndPosition()) < 0.3f * dist3DSqr(getStartPosition(), getEndPosition())) { setActualEndPosition(getEndPosition()); m_pathPoints.set(m_pathPoints.size()-1, getEndPosition()); } else { setActualEndPosition(getEndPosition()); BuildShortcut(); } m_type = PathType(PATHFIND_NORMAL | PATHFIND_NOT_USING_PATH); } //DEBUG_FILTER_LOG(LOG_FILTER_PATHFINDING, "++ PathInfo::BuildPointPath path type %d size %d poly-size %d\n", m_type, pointCount, m_polyLength); }
// ---------------------------------------------------------------------------------- // Actual A* algorithm: return number of steps in the creation of the path or -1 ---- // ---------------------------------------------------------------------------------- int j1PathFinding::CreatePath(const iPoint& origin, const iPoint& destination) { if (IsWalkable(origin) && IsWalkable(destination)) { // TODO 2: Create three lists: open, close ,adjacent PathList open; PathList closed; PathList adjacent; // Add the origin tile to open open.list.add(PathNode(0, 0, origin, NULL)); // Iterate while we have tile in the open list do { // TODO 3: Move the lowest score cell from open list to the closed list p2List_item<PathNode>* lowest_score = open.GetNodeLowestScore(); p2List_item<PathNode>* node = closed.list.add(lowest_score->data); // delete de lowest score from the open list open.list.del(lowest_score); // TODO 4: If we just added the destination, we are done! if (node->data.pos == destination) { //clean the path we used before last_path.Clear(); // Backtrack to create the final path const PathNode* path_node = &node->data; while (path_node) { // Use the Pathnode::parent and Flip() the path when you are finish last_path.PushBack(path_node->pos); path_node = path_node->parent; } last_path.Flip(); return last_path.Count(); } // TODO 5: Fill a list of all adjancent nodes node->data.FindWalkableAdjacents(adjacent); p2List_item<PathNode>* adjacent_items = adjacent.list.start; // TODO 6: Iterate adjancent nodes: for (; adjacent_items; adjacent_items = adjacent_items->next) { // ignore nodes in the closed list if (closed.Find(adjacent_items->data.pos) != NULL) { continue; } p2List_item<PathNode>* adjacent_open = open.Find(adjacent_items->data.pos); // If it is NOT found, calculate its F and add it to the open list if (adjacent_open == NULL) { adjacent_items->data.CalculateF(destination); open.list.add(adjacent_items->data); } else // If it is already in the open list, check if it is a better path (compare G) { if (adjacent_open->data.g > adjacent_items->data.g) { // If it is a better path, Update the parent adjacent_open->data.parent = adjacent_items->data.parent; adjacent_open->data.CalculateF(destination); } } } } while (open.list.count()>0); } return -1; }
bool NGMainWnd::onnet_authsuccess(const NETAUTHEX &auth) { EnableMenuItem(this->hmenu, 1, MF_BYPOSITION | MF_ENABLED); EnableMenuItem(this->hmenu, 2, MF_BYPOSITION | MF_ENABLED); DrawMenuBar(this->hwnd); if (this->client->hasaccess(NGWINAMPUSER_ACCESS_READ)) { if (this->client->hasaccess(NGWINAMPUSER_ACCESS_WRITE)) { this->toolbox_select(TOOLBOX_ADMIN); if (this->client->hasaccess(NGWINAMPUSER_ACCESS_PL_ADD)) { } else { } if (this->client->hasaccess(NGWINAMPUSER_ACCESS_PL_SET)) { } else { } if (this->client->hasaccess(NGWINAMPUSER_ACCESS_PL_DEL)) { } else { } if (this->client->hasaccess(NGWINAMPUSER_ACCESS_PL_CTRL)) { EnableWindow(GetDlgItem(this->htoolboxwnd[this->curtoolbox], IDC_SHUFFLE), TRUE); EnableWindow(GetDlgItem(this->htoolboxwnd[this->curtoolbox], IDC_REPEAT), TRUE); EnableMenuItem(GetSubMenu(this->hmenu, 2), IDM_REPEAT, MF_BYCOMMAND | MF_ENABLED); EnableMenuItem(GetSubMenu(this->hmenu, 2), IDM_SHUFFLE, MF_BYCOMMAND | MF_ENABLED); EnableMenuItem(GetSubMenu(this->hmenu, 2), IDM_CLEAR, MF_BYCOMMAND | MF_ENABLED); EnableMenuItem(GetSubMenu(this->hmenu, 2), IDM_REMOVE_DEAD, MF_BYCOMMAND | MF_ENABLED); EnableMenuItem(GetSubMenu(this->hmenu, 2), IDM_SORTBYNAME, MF_BYCOMMAND | MF_ENABLED); EnableMenuItem(GetSubMenu(this->hmenu, 2), IDM_SORTBYPATH, MF_BYCOMMAND | MF_ENABLED); EnableMenuItem(GetSubMenu(this->hmenu, 2), IDM_RANDOMIZE, MF_BYCOMMAND | MF_ENABLED); EnableMenuItem(GetSubMenu(this->hmenu, 2), IDM_REFRESH, MF_BYCOMMAND | MF_ENABLED); } else { EnableWindow(GetDlgItem(this->htoolboxwnd[this->curtoolbox], IDC_SHUFFLE), FALSE); EnableWindow(GetDlgItem(this->htoolboxwnd[this->curtoolbox], IDC_REPEAT), FALSE); EnableMenuItem(GetSubMenu(this->hmenu, 2), IDM_REPEAT, MF_BYCOMMAND | MF_GRAYED); EnableMenuItem(GetSubMenu(this->hmenu, 2), IDM_SHUFFLE, MF_BYCOMMAND | MF_GRAYED); EnableMenuItem(GetSubMenu(this->hmenu, 2), IDM_CLEAR, MF_BYCOMMAND | MF_GRAYED); EnableMenuItem(GetSubMenu(this->hmenu, 2), IDM_REMOVE_DEAD, MF_BYCOMMAND | MF_GRAYED); EnableMenuItem(GetSubMenu(this->hmenu, 2), IDM_SORTBYNAME, MF_BYCOMMAND | MF_GRAYED); EnableMenuItem(GetSubMenu(this->hmenu, 2), IDM_SORTBYPATH, MF_BYCOMMAND | MF_GRAYED); EnableMenuItem(GetSubMenu(this->hmenu, 2), IDM_RANDOMIZE, MF_BYCOMMAND | MF_GRAYED); EnableMenuItem(GetSubMenu(this->hmenu, 2), IDM_REFRESH, MF_BYCOMMAND | MF_GRAYED); } if (this->client->hasaccess(NGWINAMPUSER_ACCESS_SN_BACK)) { EnableWindow(GetDlgItem(this->htoolboxwnd[this->curtoolbox], IDC_BACK), TRUE); EnableMenuItem(GetSubMenu(this->hmenu, 1), IDM_BACK, MF_BYCOMMAND | MF_ENABLED); } else { EnableWindow(GetDlgItem(this->htoolboxwnd[this->curtoolbox], IDC_BACK), FALSE); EnableMenuItem(GetSubMenu(this->hmenu, 1), IDM_BACK, MF_BYCOMMAND | MF_GRAYED); } if (this->client->hasaccess(NGWINAMPUSER_ACCESS_SN_PLAY)) { EnableWindow(GetDlgItem(this->htoolboxwnd[this->curtoolbox], IDC_PLAY), TRUE); EnableMenuItem(GetSubMenu(this->hmenu, 1), IDM_PLAY, MF_BYCOMMAND | MF_ENABLED); } else { EnableWindow(GetDlgItem(this->htoolboxwnd[this->curtoolbox], IDC_PLAY), FALSE); EnableMenuItem(GetSubMenu(this->hmenu, 1), IDM_PLAY, MF_BYCOMMAND | MF_GRAYED); } if (this->client->hasaccess(NGWINAMPUSER_ACCESS_SN_PAUSE)) { EnableWindow(GetDlgItem(this->htoolboxwnd[this->curtoolbox], IDC_PAUSE), TRUE); EnableMenuItem(GetSubMenu(this->hmenu, 1), IDM_PAUSE, MF_BYCOMMAND | MF_ENABLED); } else { EnableWindow(GetDlgItem(this->htoolboxwnd[this->curtoolbox], IDC_PAUSE), FALSE); EnableMenuItem(GetSubMenu(this->hmenu, 1), IDM_PAUSE, MF_BYCOMMAND | MF_GRAYED); } if (this->client->hasaccess(NGWINAMPUSER_ACCESS_SN_STOP)) { EnableWindow(GetDlgItem(this->htoolboxwnd[this->curtoolbox], IDC_STOP), TRUE); EnableMenuItem(GetSubMenu(this->hmenu, 1), IDM_STOP, MF_BYCOMMAND | MF_ENABLED); } else { EnableWindow(GetDlgItem(this->htoolboxwnd[this->curtoolbox], IDC_STOP), FALSE); EnableMenuItem(GetSubMenu(this->hmenu, 1), IDM_STOP, MF_BYCOMMAND | MF_GRAYED); } if (this->client->hasaccess(NGWINAMPUSER_ACCESS_SN_NEXT)) { EnableWindow(GetDlgItem(this->htoolboxwnd[this->curtoolbox], IDC_NEXT), TRUE); EnableMenuItem(GetSubMenu(this->hmenu, 1), IDM_NEXT, MF_BYCOMMAND | MF_ENABLED); } else { EnableWindow(GetDlgItem(this->htoolboxwnd[this->curtoolbox], IDC_NEXT), FALSE); EnableMenuItem(GetSubMenu(this->hmenu, 1), IDM_NEXT, MF_BYCOMMAND | MF_GRAYED); } if (this->client->hasaccess(NGWINAMPUSER_ACCESS_SN_VOLUME)) { EnableWindow(GetDlgItem(this->htoolboxwnd[this->curtoolbox], IDC_VOLUME), TRUE); EnableWindow(GetDlgItem(this->htoolboxwnd[this->curtoolbox], IDC_VOLUME_VALUE), TRUE); } else { EnableWindow(GetDlgItem(this->htoolboxwnd[this->curtoolbox], IDC_VOLUME), FALSE); EnableWindow(GetDlgItem(this->htoolboxwnd[this->curtoolbox], IDC_VOLUME_VALUE), FALSE); } if (this->client->hasaccess(NGWINAMPUSER_ACCESS_SN_PAN)) { EnableWindow(GetDlgItem(this->htoolboxwnd[this->curtoolbox], IDC_PAN), TRUE); EnableWindow(GetDlgItem(this->htoolboxwnd[this->curtoolbox], IDC_PAN_VALUE), TRUE); } else { EnableWindow(GetDlgItem(this->htoolboxwnd[this->curtoolbox], IDC_PAN), FALSE); EnableWindow(GetDlgItem(this->htoolboxwnd[this->curtoolbox], IDC_PAN_VALUE), FALSE); } if (this->client->hasaccess(NGWINAMPUSER_ACCESS_SN_POS)) { EnableWindow(GetDlgItem(this->htoolboxwnd[this->curtoolbox], IDC_SONG_PROGRESS), TRUE); } else { EnableWindow(GetDlgItem(this->htoolboxwnd[this->curtoolbox], IDC_SONG_PROGRESS), FALSE); } } else { this->toolbox_select(TOOLBOX_USER); } if (this->client->hasaccess(NGWINAMPUSER_ACCESS_ADMIN)) { } else { } // setup playlist if (!this->client->request_pl_getnames()) { return false; } if (!this->client->request_pl_getfiles()) { return false; } // setup initial values if (!this->client->request_snapshot(NGWINAMP_SNAPSHOT_REFRESH)) { return false; } // setup share tree TVINSERTSTRUCT tvi; memset(&tvi, 0, sizeof(TVINSERTSTRUCT)); tvi.hParent = TVI_ROOT; tvi.hInsertAfter = TVI_ROOT; tvi.itemex.mask = TVIF_CHILDREN | TVIF_IMAGE | TVIF_TEXT; tvi.itemex.cChildren = 1; tvi.itemex.pszText = NGWINAMP_BROWSER_ROOT; tvi.itemex.iImage = ICON_MAIN; this->browsenodes.push_back(PathNode(NULL, TreeView_InsertItem(this->hbrowsewnd, &tvi), "/", 0)); if (!this->client->request_bw_getdirectories("/")) { return false; } if (!this->client->request_bw_getfiles("/")) { return false; } } return true; }
// ---------------------------------------------------------------------------------- // Actual A* algorithm: return number of steps in the creation of the path or -1 ---- // ---------------------------------------------------------------------------------- int j1PathFinding::CreatePath(const iPoint& origin, const iPoint& destination) { int ret = -1; int iterations = 0; if(IsWalkable(origin) && IsWalkable(destination)) { PathList open; PathList closed; PathList adjacent; // Start pushing the origin in the open list open.list.add(PathNode(0, 0, origin, NULL)); // Iterate while we have open destinations to visit do { // Move the lowest score cell from open list to the closed list p2List_item<PathNode>* lowest = open.GetNodeLowestScore(); p2List_item<PathNode>* node = closed.list.add(lowest->data); open.list.del(lowest); // If destination was added, we are done! if(node->data.pos == destination) { last_path.Clear(); // Backtrack to create the final path const PathNode* path_node = &node->data; while(path_node) { last_path.PushBack(path_node->pos); path_node = path_node->parent; } last_path.Flip(); ret = last_path.Count(); LOG("Created path of %d steps in %d iterations", ret, iterations); break; } // Fill a list with all adjacent nodes adjacent.list.clear(); node->data.FindWalkableAdjacents(adjacent); p2List_item<PathNode>* item = adjacent.list.start; for(; item; item = item->next) { if(closed.Find(item->data.pos) != NULL) continue; p2List_item<PathNode>* adjacent_in_open = open.Find(item->data.pos); if(adjacent_in_open == NULL) { item->data.CalculateF(destination); open.list.add(item->data); } else { if(adjacent_in_open->data.g > item->data.g + 1) { adjacent_in_open->data.parent = item->data.parent; adjacent_in_open->data.CalculateF(destination); } } } ++iterations; } while(open.list.count() > 0); } return ret; }