// Connect according to MPQ data public Spot AddAndConnectSpot(Spot s) { s = AddSpot(s); List<Spot> close = FindAllSpots(s.location, MaxStepLength); if (!s.GetFlag(Spot.FLAG_MPQ_MAPPED)) { foreach (Spot cs in close) { if (cs.HasPathTo(this, s) && s.HasPathTo(this, cs) || cs.IsBlocked()) { } else if (!triangleWorld.IsStepBlocked(s.X, s.Y, s.Z, cs.X, cs.Y, cs.Z, toonHeight, toonSize, null)) { float mid_x = (s.X + cs.X) / 2; float mid_y = (s.Y + cs.Y) / 2; float mid_z = (s.Z + cs.Z) / 2; float stand_z; int flags; if (triangleWorld.FindStandableAt(mid_x, mid_y, mid_z - WantedStepLength * .75f, mid_z + WantedStepLength * .75f, out stand_z, out flags, toonHeight, toonSize)) { s.AddPathTo(cs); cs.AddPathTo(s); } } } } return s; }
// return old spot at conflicting poision // or the same as passed the function if all was ok public Spot AddSpot(Spot s) { Spot old = GetSpot(s.X, s.Y, s.Z); if (old != null) return old; int x, y; s.chunk = this; LocalCoords(s.X, s.Y, out x, out y); s.next = spots[x, y]; spots[x, y] = s; modified = true; return s; }
public Path CreatePath(Spot from, Spot to, Location realDst, float minHowClose, bool AllowInvented, ILocationHeuristics locationHeuristics) { Spot newTo = search(from, to, realDst, minHowClose, AllowInvented, locationHeuristics); if (newTo != null) { if (newTo.GetDistanceTo(to) <= minHowClose) { List <Spot> path = FollowTraceBack(from, newTo); return(new Path(path)); } } return(null); }
public List <Spot> FindAllSpots(Location l, float max_d) { List <Spot> sl = new List <Spot>(); int d = 0; while ((float)d <= max_d + 0.1f) { for (int i = -d; i <= d; i++) { float x_up = l.X + (float)d; float x_dn = l.X - (float)d; float y_up = l.Y + (float)d; float y_dn = l.Y - (float)d; Spot s0 = GetSpot2D(x_up, l.Y + i); Spot s2 = GetSpot2D(x_dn, l.Y + i); Spot s1 = GetSpot2D(l.X + i, y_dn); Spot s3 = GetSpot2D(l.X + i, y_up); Spot[] sv = { s0, s1, s2, s3 }; foreach (Spot s in sv) { Spot ss = s; while (ss != null) { float di = ss.GetDistanceTo(l); if (di < max_d) { sl.Add(ss); } ss = ss.next; if (Cancel) { goto loop_end; } } } } d++; } loop_end: return(sl); }
public List <Spot> GetAllSpots() { List <Spot> l = new List <Spot>(); for (int x = 0; x < CHUNK_SIZE; x++) { for (int y = 0; y < CHUNK_SIZE; y++) { Spot s = spots[x, y]; while (s != null) { l.Add(s); s = s.next; } } } return(l); }
// return old spot at conflicting poision // or the same as passed the function if all was ok public Spot AddSpot(Spot s) { Spot old = GetSpot(s.X, s.Y, s.Z); if (old != null) { return(old); } int x, y; s.chunk = this; LocalCoords(s.X, s.Y, out x, out y); s.next = spots[x, y]; spots[x, y] = s; modified = true; return(s); }
public void MarkBlockedAt(Location loc) { Spot s = new Spot(loc); s = AddSpot(s); s.SetFlag(Spot.FLAG_BLOCKED, true); // Find all paths leading though this one List <Spot> sl = FindAllSpots(loc, 5.0f); foreach (Spot sp in sl) { List <Location> paths = sp.GetPaths(); foreach (Location to in paths) { if (LineCrosses(sp.location, to, loc)) { sp.RemovePathTo(to); } } } }
public void AddPathTo(Spot s) { AddPathTo(s.X, s.Y, s.Z); }
public Spot AddSpot(Spot s) { LoadChunk(s.X, s.Y); GraphChunk gc = GetChunkAt(s.X, s.Y); return gc.AddSpot(s); }
////////////////////////////////////////////////////// // Searching ////////////////////////////////////////////////////// float TurnCost(Spot from, Spot to) { Spot prev = from.traceBack; if (prev == null) return 0.0f; return TurnCost(prev.X, prev.Y, prev.Z, from.X, from.Y, from.Z, to.X, to.Y, to.Z); }
private Spot search(Spot src, Spot dst, Location realDst, float minHowClose, bool AllowInvented, ILocationHeuristics locationHeuristics) { searchID++; int count = 0; Cancel = false; int prevCount = 0; int currentSearchID = searchID; float heuristicsFactor = 1.3f; System.DateTime pre = System.DateTime.Now; System.DateTime lastSpam = pre; // lowest first queue PriorityQueue<Spot, float> q = new PriorityQueue<Spot, float>(); // (new SpotSearchComparer(dst, score)); ; q.Enqueue(src, -src.GetDistanceTo(dst) * heuristicsFactor); Spot BestSpot = null; //Set<Spot> closed = new Set<Spot>(); //SpotData<float> score = new SpotData<float>(); src.SearchScoreSet(currentSearchID, 0.0f); src.traceBack = null; // A* -ish algorithm while ((q.Count != 0) && !Cancel) // && count < 100000) { float prio; Spot spot = q.Dequeue(out prio); // .Value; //q.Remove(spot); if (spot.SearchIsClosed(currentSearchID)) continue; spot.SearchClose(currentSearchID); if (count % 100 == 0) { System.TimeSpan span = System.DateTime.Now.Subtract(lastSpam); if (span.Seconds != 0 && BestSpot != null) { Thread.Sleep(50); // give glider a chance to stop us int t = span.Seconds * 1000 + span.Milliseconds; if (t == 0) Log("searching.... " + (count + 1) + " d: " + BestSpot.location.GetDistanceTo(realDst)); else Log("searching.... " + (count + 1) + " d: " + BestSpot.location.GetDistanceTo(realDst) + " " + (count - prevCount) * 1000 / t + " steps/s"); lastSpam = System.DateTime.Now; prevCount = count; } } count++; if (spot.Equals(dst) || spot.location.GetDistanceTo(realDst) <= minHowClose) { System.TimeSpan ts = System.DateTime.Now.Subtract(pre); int t = ts.Seconds * 1000 + ts.Milliseconds; /*if(t == 0) Log(" search found the way there. " + count); else Log(" search found the way there. " + count + " " + (count * 1000) / t + " steps/s"); */ return spot; // got there } if (BestSpot == null || spot.location.GetDistanceTo(realDst) < BestSpot.location.GetDistanceTo(realDst)) { BestSpot = spot; } { System.TimeSpan ts = System.DateTime.Now.Subtract(pre); if (ts.Seconds > 120) { Log("too long search, aborting"); break; } } float src_score = spot.SearchScoreGet(currentSearchID); //Console.WriteLine("inspect: " + c + " score " + s); int new_found = 0; List<Spot> ll = spot.GetPathsToSpots(this); foreach (Spot to in ll) { //Spot to = GetSpot(l); if (to != null && !to.IsBlocked() && !to.SearchIsClosed(currentSearchID)) { float old_score = 1E30f; float new_score = src_score + spot.GetDistanceTo(to) + TurnCost(spot, to); if (locationHeuristics != null) new_score += locationHeuristics.Score(spot.X, spot.Y, spot.Z); if (to.GetFlag(Spot.FLAG_WATER)) new_score += 30; if (to.SearchScoreIsSet(currentSearchID)) { old_score = to.SearchScoreGet(currentSearchID); } if (new_score < old_score) { // shorter path to here found to.traceBack = spot; //if (q.Contains(to)) // q.Remove(to); // very sloppy to not dequeue it to.SearchScoreSet(currentSearchID, new_score); q.Enqueue(to, -(new_score + to.GetDistanceTo(dst) * heuristicsFactor)); new_found++; } } if (Cancel) break; } //hmm search the triangles :p if (!spot.GetFlag(Spot.FLAG_MPQ_MAPPED)) { float PI = (float)Math.PI; spot.SetFlag(Spot.FLAG_MPQ_MAPPED, true); for (float a = 0; a < PI * 2; a += PI / 8) { float nx = spot.X + (float)Math.Sin(a) * WantedStepLength;// *0.8f; float ny = spot.Y + (float)Math.Cos(a) * WantedStepLength;// *0.8f; Spot s = GetSpot(nx, ny, spot.Z); if (s == null) s = FindClosestSpot(new Location(nx, ny, spot.Z), MinStepLength); // TODO: this is slow if (s != null) { // hmm, they should already be connected } else { float new_z; int flags; // gogo find a new one //Console.WriteLine("gogo brave new world"); if (!triangleWorld.FindStandableAt(nx, ny, spot.Z - WantedStepLength * .75f, spot.Z + WantedStepLength * .75f, out new_z, out flags, toonHeight, toonSize)) { //Spot blocked = new Spot(nx, ny, spot.Z); //blocked.SetFlag(Spot.FLAG_BLOCKED, true); //AddSpot(blocked); } else { s = FindClosestSpot(new Location(nx, ny, new_z), MinStepLength); if (s == null) { if (!triangleWorld.IsStepBlocked(spot.X, spot.Y, spot.Z, nx, ny, new_z, toonHeight, toonSize, null)) { Spot n = new Spot(nx, ny, new_z); Spot to = AddAndConnectSpot(n); if ((flags & ChunkedTriangleCollection.TriangleFlagDeepWater) != 0) { to.SetFlag(Spot.FLAG_WATER, true); } if (((flags & ChunkedTriangleCollection.TriangleFlagModel) != 0) || ((flags & ChunkedTriangleCollection.TriangleFlagObject) != 0)) { to.SetFlag(Spot.FLAG_INDOORS, true); } if (to != n || to.SearchIsClosed(currentSearchID)) { // Console.WriteLine("/sigh"); } else { // There should be a path from source to this one now if (spot.HasPathTo(to.location)) { float old_score = 1E30f; float new_score = src_score + spot.GetDistanceTo(to) + TurnCost(spot, to); if (locationHeuristics != null) new_score += locationHeuristics.Score(spot.X, spot.Y, spot.Z); if (to.GetFlag(Spot.FLAG_WATER)) new_score += 30; if (to.SearchScoreIsSet(currentSearchID)) { old_score = to.SearchScoreGet(currentSearchID); } if (new_score < old_score) { // shorter path to here found to.traceBack = spot; //if (q.Contains(to)) // q.Remove(to); to.SearchScoreSet(currentSearchID, new_score); q.Enqueue(to, -(new_score + to.GetDistanceTo(dst) * heuristicsFactor)); new_found++; } } else { // woot! I added a new one and it is not connected!?!? //Console.WriteLine("/cry"); } } } } } } if (Cancel) break; } } } { System.TimeSpan ts = System.DateTime.Now.Subtract(pre); int t = ts.Seconds * 1000 + ts.Milliseconds; if (t == 0) t = 1; Log(" search failed. " + (count * 1000) / t + " steps/s"); } return BestSpot; // :( }
// Per spot: // uint32 magic // uint32 reserved; // uint32 flags; // float x; // float y; // float z; // uint32 no_paths // for each path // float x; // float y; // float z; public bool Load(string baseDir) { string fileName = FileName(); string filenamebin = baseDir + fileName; System.IO.Stream stream = null; System.IO.BinaryReader file = null; int n_spots = 0; int n_steps = 0; try { stream = System.IO.File.OpenRead(filenamebin); if (stream != null) { file = new System.IO.BinaryReader(stream); if (file != null) { uint magic = file.ReadUInt32(); if (magic == FILE_MAGIC) { uint type; while ((type = file.ReadUInt32()) != FILE_ENDMAGIC) { n_spots++; uint reserved = file.ReadUInt32(); uint flags = file.ReadUInt32(); float x = file.ReadSingle(); float y = file.ReadSingle(); float z = file.ReadSingle(); uint n_paths = file.ReadUInt32(); if (x != 0 && y != 0) { Spot s = new Spot(x, y, z); s.flags = flags; for (uint i = 0; i < n_paths; i++) { n_steps++; float sx = file.ReadSingle(); float sy = file.ReadSingle(); float sz = file.ReadSingle(); s.AddPathTo(sx, sy, sz); } AddSpot(s); } } } } } } catch (System.IO.FileNotFoundException e) { Console.WriteLine(e.Message); } catch (System.IO.DirectoryNotFoundException e) { Console.WriteLine(e.Message); } catch (Exception e) { Console.WriteLine(e.Message); } if (file != null) { file.Close(); } if (stream != null) { stream.Close(); } Log("Loaded " + fileName + " " + n_spots + " spots " + n_steps + " steps"); modified = false; return false; }
public void UpdateMyPos() { BoogieCore.Log(LogType.System, "[Update] 1"); //radar.Update(); if (world != null) { Coordinate loc = BoogieCore.world.getPlayerObject().GetCoordinates(); Location isAt = new Location(loc.X, loc.Y, loc.Z); BoogieCore.Log(LogType.System, "[Update] 2"); //if(WasAt != null) Context.Log("was " + WasAt.location); //Context.Log("isAt " + isAt); if (WasAt != null) { BoogieCore.Log(LogType.System, "[Update] 3"); if (WasAt.GetLocation().GetDistanceTo(isAt) > 20) WasAt = null; } BoogieCore.Log(LogType.System, "[Update] 4"); WasAt = world.TryAddSpot(WasAt, isAt); BoogieCore.Log(LogType.System, "[Update] 5"); } }
public void MarkBlockedAt(Location loc) { Spot s = new Spot(loc); s = AddSpot(s); s.SetFlag(Spot.FLAG_BLOCKED, true); // Find all paths leading though this one List<Spot> sl = FindAllSpots(loc, 5.0f); foreach (Spot sp in sl) { List<Location> paths = sp.GetPaths(); foreach (Location to in paths) { if (LineCrosses(sp.location, to, loc)) { sp.RemovePathTo(to); } } } }
public Path CreatePath(Spot from, Spot to, Location realDst, float minHowClose, bool AllowInvented, ILocationHeuristics locationHeuristics) { Spot newTo = search(from, to, realDst, minHowClose, AllowInvented, locationHeuristics); if (newTo != null) { if (newTo.GetDistanceTo(to) <= minHowClose) { List<Spot> path = FollowTraceBack(from, newTo); return new Path(path); } } return null; }
public bool HasPathTo(PathGraph pg, Spot s) { for (int i = 0; i < n_paths; i++) { Spot to = GetToSpot(pg, i); if (to == s) return true; } return false; }
public float GetDistanceTo(Spot s) { float dx = s.X - X; float dy = s.Y - Y; float dz = s.Z - Z; return (float)Math.Sqrt(dx * dx + dy * dy + dz * dz); }
public void ResetMyPos() { WasAt = null; }
private Spot search(Spot src, Spot dst, Location realDst, float minHowClose, bool AllowInvented, ILocationHeuristics locationHeuristics) { searchID++; int count = 0; int prevCount = 0; int currentSearchID = searchID; float heuristicsFactor = 1.3f; System.DateTime pre = System.DateTime.Now; System.DateTime lastSpam = pre; // lowest first queue PriorityQueue <Spot, float> q = new PriorityQueue <Spot, float>(); // (new SpotSearchComparer(dst, score)); ; q.Enqueue(src, -src.GetDistanceTo(dst) * heuristicsFactor); Spot BestSpot = null; //Set<Spot> closed = new Set<Spot>(); //SpotData<float> score = new SpotData<float>(); src.SearchScoreSet(currentSearchID, 0.0f); src.traceBack = null; // A* -ish algorithm while (q.Count != 0) // && count < 100000) { float prio; Spot spot = q.Dequeue(out prio); // .Value; //q.Remove(spot); if (spot.SearchIsClosed(currentSearchID)) { continue; } spot.SearchClose(currentSearchID); if (count % 100 == 0) { System.TimeSpan span = System.DateTime.Now.Subtract(lastSpam); if (span.Seconds != 0 && BestSpot != null) { Thread.Sleep(50); // give glider a chance to stop us int t = span.Seconds * 1000 + span.Milliseconds; if (t == 0) { Log("searching.... " + (count + 1) + " d: " + BestSpot.location.GetDistanceTo(realDst)); } else { Log("searching.... " + (count + 1) + " d: " + BestSpot.location.GetDistanceTo(realDst) + " " + (count - prevCount) * 1000 / t + " steps/s"); } lastSpam = System.DateTime.Now; prevCount = count; } } count++; if (spot.Equals(dst) || spot.location.GetDistanceTo(realDst) <= minHowClose) { System.TimeSpan ts = System.DateTime.Now.Subtract(pre); int t = ts.Seconds * 1000 + ts.Milliseconds; /*if(t == 0) * Log(" search found the way there. " + count); * else * Log(" search found the way there. " + count + " " + (count * 1000) / t + " steps/s"); */ return(spot); // got there } if (BestSpot == null || spot.location.GetDistanceTo(realDst) < BestSpot.location.GetDistanceTo(realDst)) { BestSpot = spot; } { System.TimeSpan ts = System.DateTime.Now.Subtract(pre); if (ts.Seconds > 15) { Log("too long search, aborting"); break; } } float src_score = spot.SearchScoreGet(currentSearchID); //PPather.WriteLine("inspect: " + c + " score " + s); int new_found = 0; List <Spot> ll = spot.GetPathsToSpots(this); foreach (Spot to in ll) { //Spot to = GetSpot(l); if (to != null && !to.IsBlocked() && !to.SearchIsClosed(currentSearchID)) { float old_score = 1E30f; float new_score = src_score + spot.GetDistanceTo(to) + TurnCost(spot, to); if (locationHeuristics != null) { new_score += locationHeuristics.Score(spot.X, spot.Y, spot.Z); } if (to.GetFlag(Spot.FLAG_WATER)) { new_score += 30; } if (to.SearchScoreIsSet(currentSearchID)) { old_score = to.SearchScoreGet(currentSearchID); } if (new_score < old_score) { // shorter path to here found to.traceBack = spot; //if (q.Contains(to)) // q.Remove(to); // very sloppy to not dequeue it to.SearchScoreSet(currentSearchID, new_score); q.Enqueue(to, -(new_score + to.GetDistanceTo(dst) * heuristicsFactor)); new_found++; } } } //hmm search the triangles :p if (!spot.GetFlag(Spot.FLAG_MPQ_MAPPED)) { float PI = (float)Math.PI; spot.SetFlag(Spot.FLAG_MPQ_MAPPED, true); for (float a = 0; a < PI * 2; a += PI / 8) { float nx = spot.X + (float)Math.Sin(a) * WantedStepLength; // *0.8f; float ny = spot.Y + (float)Math.Cos(a) * WantedStepLength; // *0.8f; Spot s = GetSpot(nx, ny, spot.Z); if (s == null) { s = FindClosestSpot(new Location(nx, ny, spot.Z), MinStepLength); // TODO: this is slow } if (s != null) { // hmm, they should already be connected } else { float new_z; int flags; // gogo find a new one //PPather.WriteLine("gogo brave new world"); if (!triangleWorld.FindStandableAt(nx, ny, spot.Z - WantedStepLength * .75f, spot.Z + WantedStepLength * .75f, out new_z, out flags, toonHeight, toonSize)) { //Spot blocked = new Spot(nx, ny, spot.Z); //blocked.SetFlag(Spot.FLAG_BLOCKED, true); //AddSpot(blocked); } else { s = FindClosestSpot(new Location(nx, ny, new_z), MinStepLength); if (s == null) { if (!triangleWorld.IsStepBlocked(spot.X, spot.Y, spot.Z, nx, ny, new_z, toonHeight, toonSize, null)) { Spot n = new Spot(nx, ny, new_z); Spot to = AddAndConnectSpot(n); if ((flags & ChunkedTriangleCollection.TriangleFlagDeepWater) != 0) { to.SetFlag(Spot.FLAG_WATER, true); } if (((flags & ChunkedTriangleCollection.TriangleFlagModel) != 0) || ((flags & ChunkedTriangleCollection.TriangleFlagObject) != 0)) { to.SetFlag(Spot.FLAG_INDOORS, true); } if (to != n || to.SearchIsClosed(currentSearchID)) { // PPather.WriteLine("/sigh"); } else { // There should be a path from source to this one now if (spot.HasPathTo(to.location)) { float old_score = 1E30f; float new_score = src_score + spot.GetDistanceTo(to) + TurnCost(spot, to); if (locationHeuristics != null) { new_score += locationHeuristics.Score(spot.X, spot.Y, spot.Z); } if (to.GetFlag(Spot.FLAG_WATER)) { new_score += 30; } if (to.SearchScoreIsSet(currentSearchID)) { old_score = to.SearchScoreGet(currentSearchID); } if (new_score < old_score) { // shorter path to here found to.traceBack = spot; //if (q.Contains(to)) // q.Remove(to); to.SearchScoreSet(currentSearchID, new_score); q.Enqueue(to, -(new_score + to.GetDistanceTo(dst) * heuristicsFactor)); new_found++; } } else { // woot! I added a new one and it is not connected!?!? //PPather.WriteLine("/cry"); } } } } } } } } } { System.TimeSpan ts = System.DateTime.Now.Subtract(pre); int t = ts.Seconds * 1000 + ts.Milliseconds; if (t == 0) { t = 1; } Log(" search failed. " + (count * 1000) / t + " steps/s"); } return(BestSpot); // :( }
private List<Spot> FollowTraceBack(Spot from, Spot to) { List<Spot> path = new List<Spot>(); int count = 0; Spot r = to; path.Insert(0, to); // add last while (r != null) { Spot s = r.traceBack; if (s != null) { path.Insert(0, s); // add first r = s; if (r == from) r = null; // fount source } else r = null; count++; } path.Insert(0, from); // add first return path; }
public bool IsSet(Spot s) { return(data.ContainsKey(s)); }
private void Startup() { RunState = RunState_e.Paused; WantedState = RunState_e.Running; BoogieCore.Log(LogType.System, "TotalMemory before " + System.GC.GetTotalMemory(true) / (1024 * 1024) + " MB"); WasAt = null; string zone = FigureOutZone(); MPQTriangleSupplier mpq = new MPQTriangleSupplier(); CurrentContinent = mpq.SetZone(zone); BoogieCore.Log(LogType.System, "Zone is : " + zone); BoogieCore.Log(LogType.System, "Continent is : " + CurrentContinent); string myFaction = "Unknown"; ChunkedTriangleCollection triangleWorld = new ChunkedTriangleCollection(512); triangleWorld.SetMaxCached(9); triangleWorld.AddSupplier(mpq); world = new PathGraph(CurrentContinent, triangleWorld, null); mover = new Mover(); radar = new UnitRadar(); BoogieCore.Log(LogType.System, "Pather loaded!"); while (ShouldRun) { Thread.Sleep(100); } }
public Spot TryAddSpot(Spot wasAt, Location isAt) { Spot isAtSpot = FindClosestSpot(isAt, WantedStepLength); if (isAtSpot == null) { isAtSpot = GetSpot(isAt); if (isAtSpot == null) { Spot s = new Spot(isAt); s = AddSpot(s); isAtSpot = s; } if (isAtSpot.GetFlag(Spot.FLAG_BLOCKED)) { isAtSpot.SetFlag(Spot.FLAG_BLOCKED, false); Log("Cleared blocked flag"); } if (wasAt != null) { wasAt.AddPathTo(isAtSpot); isAtSpot.AddPathTo(wasAt); } List<Spot> sl = FindAllSpots(isAtSpot.location, MaxStepLength); int connected = 0; foreach (Spot other in sl) { if (other != isAtSpot) { other.AddPathTo(isAtSpot); isAtSpot.AddPathTo(other); connected++; // Log(" connect to " + other.location); } } Log("Learned a new spot at " + isAtSpot.location + " connected to " + connected + " other spots"); wasAt = isAtSpot; } else { if (wasAt != null && wasAt != isAtSpot) { // moved to an old spot, make sure they are connected wasAt.AddPathTo(isAtSpot); isAtSpot.AddPathTo(wasAt); } wasAt = isAtSpot; } return wasAt; }
// Per spot: // uint32 magic // uint32 reserved; // uint32 flags; // float x; // float y; // float z; // uint32 no_paths // for each path // float x; // float y; // float z; public bool Load(string baseDir) { string fileName = FileName(); string filenamebin = baseDir + fileName; System.IO.Stream stream = null; System.IO.BinaryReader file = null; int n_spots = 0; int n_steps = 0; try { stream = System.IO.File.OpenRead(filenamebin); if (stream != null) { file = new System.IO.BinaryReader(stream); if (file != null) { uint magic = file.ReadUInt32(); if (magic == FILE_MAGIC) { uint type; while ((type = file.ReadUInt32()) != FILE_ENDMAGIC) { n_spots++; uint reserved = file.ReadUInt32(); uint flags = file.ReadUInt32(); float x = file.ReadSingle(); float y = file.ReadSingle(); float z = file.ReadSingle(); uint n_paths = file.ReadUInt32(); Spot s = new Spot(x, y, z); s.flags = flags; for (uint i = 0; i < n_paths; i++) { n_steps++; float sx = file.ReadSingle(); float sy = file.ReadSingle(); float sz = file.ReadSingle(); s.AddPathTo(sx, sy, sz); } AddSpot(s); } } } } } catch (System.IO.FileNotFoundException e) { PPather.WriteLine(e.Message); } catch (System.IO.DirectoryNotFoundException e) { PPather.WriteLine(e.Message); } if (file != null) { file.Close(); } if (stream != null) { stream.Close(); } Log("Loaded " + fileName + " " + n_spots + " spots " + n_steps + " steps"); modified = false; return(false); }