// Possible interpretation (as found on internet, by krausyao) // TrPathNode ( AAAABBBB mainIdx passingIdx pdpIdx ) // AAAA wait time seconds in hexidecimal // BBBB (Also hexidecimal, so 16 bits) // Bit 0 - connected pdp-entry references a reversal-point (1/x1) // Bit 1 - waiting point (2/x2) // Bit 2 - intermediate point between switches (4/x4) // Bit 3 - 'other exit' is used (8/x8) // Bit 4 - 'optional Route' active (16/x10) // // But the interpretation below is a bit more complicated. // TODO. Since this interpretation belongs to the PATfile itself, // in principle it would be more logical to have it in PATfile.cs. But this leads to too much code duplication private void InterpretPathNodeFlags(TrPathNode tpn, TrackPDP pdp, bool isTimetableMode) { if ((tpn.pathFlags & 03) == 0) { return; } // bit 0 and/or bit 1 is set. if ((tpn.pathFlags & 01) != 0) { // if bit 0 is set: reversal Type = AIPathNodeType.Reverse; } else { // bit 0 is not set, but bit 1 is set:waiting point Type = AIPathNodeType.Stop; //<CSComment> tests showed me that value 9 in pdp is generated when the waiting point (or also //a path start or end point) are dragged within the path editor of the MSTS activity editor; the points are still valid; // however, as a contradictory case of the past has been reported, the check is skipped only when the enhanced compatibility flag is on; if (pdp.IsInvalid && isTimetableMode) // not a valid point { Type = AIPathNodeType.Invalid; } } WaitTimeS = (int)((tpn.pathFlags >> 16) & 0xffff); // get the AAAA part. // computations for absolute wait times are made within AITrain.cs /* if (WaitTimeS >= 30000 && WaitTimeS < 40000) * { * // real wait time. * // waitTimeS (in decimal notation) = 3HHMM (hours and minuts) * int hour = (WaitTimeS / 100) % 100; * int minute = WaitTimeS % 100; * WaitUntil = 60 * (minute + 60 * hour); * WaitTimeS = 0; * }*/ // computations are made within AITrain.cs /* else if (WaitTimeS >= 40000 && WaitTimeS < 60000) * { * // Uncouple if a wait=stop point * // waitTimeS (in decimal notation) = 4NNSS (uncouple NN cars, wait SS seconds) * // or 5NNSS (uncouple NN cars, keep rear, wait SS seconds) * NCars = (WaitTimeS / 100) % 100; * if (WaitTimeS >= 50000) * NCars = -NCars; * WaitTimeS %= 100; * if (Type == AIPathNodeType.Stop) * Type = AIPathNodeType.Uncouple; * } * else if (WaitTimeS >= 60000) // this is old and should be removed/reused * { * // waitTimes = 6xSSS with waitTime SSS seconds. * WaitTimeS %= 1000; * } */ }
/// <summary> /// Creates a single trainpathNode and initializes everything that do not depend on other nodes. /// The trainpath constructor will initialize the rest. /// </summary> protected TrainpathNode(TrackPDP pdp, TrackDB trackDB, TrackSectionsFile tsectionDat) : this(trackDB, tsectionDat) { Location = new WorldLocation(pdp.TileX, pdp.TileZ, pdp.X, pdp.Y, pdp.Z); if (pdp.IsInvalid) // not a valid point { this.SetBroken(NodeStatus.SetAsInvalid); } }
public bool IsVisited; // true if the train has visited this node /// <summary> /// Creates a single AIPathNode and initializes everything that do not depend on other nodes. /// The AIPath constructor will initialize the rest. /// </summary> public AIPathNode(TrPathNode tpn, TrackPDP pdp, TrackDB trackDB, bool isTimetableMode) { ID = (int)tpn.fromPDP; InterpretPathNodeFlags(tpn, pdp, isTimetableMode); Location = new WorldLocation(pdp.TileX, pdp.TileZ, pdp.X, pdp.Y, pdp.Z); if (pdp.IsJunction) { JunctionIndex = FindJunctionOrEndIndex(Location, trackDB, true); } }
/// <summary> /// Sort of constructor. But it creates the right sub-class /// </summary> /// <returns>A sub-class object properly initialized</returns> public static TrainpathNode CreatePathNode(TrPathNode tpn, TrackPDP pdp, TrackDB trackDB, TrackSectionsFile tsectionDat) { if (pdp.IsJunction) { // we do not use tpn: this means we do not interpret the flags return(new TrainpathJunctionNode(pdp, trackDB, tsectionDat)); } else { return(new TrainpathVectorNode(tpn, pdp, trackDB, tsectionDat)); } }
/// <summary> /// Add information of the basic MSTS PATfile /// </summary> /// <param name="trackViewer"></param> private void AddPATfileStatus(TrackViewer trackViewer) { if (Properties.Settings.Default.statusShowPATfile && (trackViewer.DrawPATfile != null)) { TrPathNode curNode = trackViewer.DrawPATfile.CurrentNode; TrackPDP curPDP = trackViewer.DrawPATfile.CurrentPdp; statusAdditional.Text += string.Format(System.Globalization.CultureInfo.CurrentCulture, " {7}: {3}, {4} [{1} {2}] [{5} {6}] <{0}>", curNode.pathFlags, (int)curNode.nextMainNode, (int)curNode.nextSidingNode, curPDP.X, curPDP.Z, curPDP.junctionFlag, curPDP.invalidFlag, trackViewer.DrawPATfile.FileName); } }
public TrackPDP SearchNextPathNode(TrackPDP endPoint) { TrItem trItem = null; TrackPDP newNode = null; trItem = searchTraveller.MoveToNextItem(AllItems, (int)endPoint.TileX, (int)endPoint.TileZ, endPoint.X, endPoint.Z); if (trItem != null) { //newNode = new TrackPDP(trItem); } return(newNode); }
/// <summary> /// Constructor based on PAT file information. /// </summary> /// <param name="tpn">TrPathNode from .pat file</param> /// <param name="pdp">TrackPDP from .pat file</param> /// <param name="trackDB"></param> /// <param name="tsectionDat"></param> public TrainpathVectorNode(TrPathNode tpn, TrackPDP pdp, TrackDB trackDB, TrackSectionsFile tsectionDat) : base(pdp, trackDB, tsectionDat) { try { Traveller traveller = new Traveller(tsectionDat, trackDB.TrackNodes, this.Location); CopyDataFromTraveller(traveller); } catch { SetBroken(NodeStatus.NotOnTrack); } ForwardOriented = true; // only initial setting InterpretPathNodeFlags(tpn); }
public void StartSearchPath(TrackPDP startPoint) { searchTraveller = new AETraveller(this.traveller); searchTraveller.place((int)startPoint.TileX, (int)startPoint.TileZ, startPoint.X, startPoint.Z); }
/// <summary> /// Convert a PDP with raw coordinates numbers to a world location /// </summary> /// <param name="pdp">The trackPDP</param> /// <returns>The corresponding world location</returns> private static WorldLocation GetPdpLocation(TrackPDP pdp) { return(new WorldLocation(pdp.TileX, pdp.TileZ, pdp.X, pdp.Y, pdp.Z)); }
/// <summary> /// Constructor based on the data given in the .pat file /// </summary> /// <param name="pdp">Corresponding PDP in the .patfile</param> /// <param name="trackDB"></param> /// <param name="tsectionDat"></param> public TrainpathJunctionNode(TrackPDP pdp, TrackDB trackDB, TrackSectionsFile tsectionDat) : base(pdp, trackDB, tsectionDat) { JunctionIndex = FindJunctionOrEndIndex(true); }