public static void DrawUpcomingEvents() { if (!PlayerManager.Car) { return; } var trackInfoSettings = Main.settings.trackInfoSettings; var bogie = PlayerManager.Car.Bogies[1]; var track = bogie.track; if (track == null) { return; } var startSpan = bogie.traveller.Span; var locoDirection = PlayerManager.LastLoco == null || PlayerManager.LastLoco.GetComponent <LocoControllerBase>()?.reverser >= 0f; var direction = !locoDirection ^ (bogie.trackDirection > 0); var currentGrade = TrackIndexer.Grade(bogie.point1) * (direction ? 1 : -1); var events = TrackFollower.FollowTrack( track, startSpan, direction ? trackInfoSettings.maxEventSpan : -trackInfoSettings.maxEventSpan); var eventDescriptions = events .ExceptUnnamedTracks() .ResolveJunctionSpeedLimits() .FilterRedundantSpeedLimits() .FilterGradeEvents(currentGrade) .Take(trackInfoSettings.maxEventCount) .TakeWhile(ev => ev.span < trackInfoSettings.maxEventSpan) .Select(ev => ev switch { TrackChangeEvent e => (e.span, e.ID.ToString()), JunctionEvent e => (e.span, GetJunctionEventDescription(e)), DualSpeedLimitEvent e => (e.span, $"{e.limit} / {e.rightLimit} km/h"), SpeedLimitEvent e => (e.span, GetSpeedLimitEventDescription(e)), GradeEvent e => (e.span, $"{e.grade:F1} %"), _ => (0.0, $"Unknown event: {ev}"), })
public static IEnumerable <TrackEvent> FollowTrack(RailTrack track, double startSpan, double distance) { const int MAX_ITERATIONS = 100; double distanceFromStart = 0f; for (int i = 0; i < MAX_ITERATIONS; i++) { yield return(new TrackChangeEvent(distanceFromStart, track.logicTrack.ID)); bool travelDirection = distance > 0; var trackEvents = TrackIndexer .GetTrackEvents(track, travelDirection, startSpan) .Offset(distanceFromStart); foreach (var trackEvent in trackEvents) { yield return(trackEvent); } double newSpan = startSpan + distance; Junction nextJunction; Junction.Branch nextBranch; if (newSpan < 0) { nextBranch = track.GetInBranch(); if (nextBranch == null) { yield break; } distance += startSpan; distanceFromStart += startSpan; if (nextBranch.first) { distance *= -1; } nextJunction = track.inJunction; } else { double trackSpan = track.GetPointSet().span; if (newSpan >= trackSpan) { nextBranch = track.GetOutBranch(); if (nextBranch == null) { yield break; } distance -= trackSpan - startSpan; distanceFromStart += trackSpan - startSpan; if (!nextBranch.first) { distance *= -1; } nextJunction = track.outJunction; } else { yield break; } } if (nextBranch == null) { yield break; } if (nextJunction != null && nextJunction.inBranch.track == track) { yield return(new JunctionEvent(distanceFromStart, true, nextJunction)); } track = nextBranch.track; startSpan = nextBranch.first ? 0.0 : nextBranch.track.GetPointSet().span; } }
public static void Register() { Register("hud.dumpTrack", _ => { if (PlayerManager.Car == null) { return; } var bogie = PlayerManager.Car.Bogies[0]; var track = bogie.track; if (track == null) { return; } var direction = bogie.trackDirection; var span = bogie.traveller.Span; var segments = SignPlacer.GetSegmentInfos(track.curve, 0.4f, 200f, false); var output = $"direction = {direction}, span = {span}\n"; output += string.Join("\n", segments.Select(seg => $"{seg.bezierStartT} -> {seg.bezierEndT}, {seg.segmentLength}, {seg.GetSpeed()}")); Terminal.Log(output); Main.DebugLog(output); }); Register("hud.raycast", _ => { var transform = PlayerManager.PlayerTransform; Terminal.Log($"casting from {transform.position} @ {transform.forward}"); var hits = Physics.RaycastAll( new Ray(transform.position, transform.forward), 1000f, 1 << TrackIndexer.SIGN_COLLIDER_LAYER); foreach (var hit in hits) { Terminal.Log($"hit {hit.collider} at {hit.transform.position}: dp = {Vector3.Dot(transform.forward, hit.transform.forward)}, layer = {hit.collider.gameObject.layer}"); } }); Register("hud.trackevents", _ => { var transform = PlayerManager.PlayerTransform; (RailTrack startTrack, EquiPointSet.Point? point) = RailTrack.GetClosest(transform.position); if (startTrack == null) { return; } var events = TrackIndexer.GetTrackEvents(startTrack); Terminal.Log($"All on track {startTrack.logicTrack.ID}"); foreach (var trackEvent in events) { Terminal.Log(trackEvent.ToString()); Main.DebugLog(trackEvent.ToString()); } var pointForward = point?.forward ?? Vector3.zero; var pointSpan = point?.span ?? 0; var trackDirection = Vector3.Dot(transform.forward, pointForward) > 0f; Terminal.Log($"From {pointSpan} {trackDirection}:"); foreach (var trackEvent in TrackIndexer.GetTrackEvents(startTrack, trackDirection, pointSpan)) { Terminal.Log(trackEvent.ToString()); Main.DebugLog(trackEvent.ToString()); } }); Register("hud.followTrack", _ => { var transform = PlayerManager.PlayerTransform; (RailTrack startTrack, EquiPointSet.Point? point) = RailTrack.GetClosest(transform.position); if (startTrack == null) { return; } var pointForward = point?.forward ?? Vector3.zero; var pointSpan = point?.span ?? 0; var trackDirection = Vector3.Dot(transform.forward, pointForward) > 0f ? 1 : -1; var trackEvents = TrackFollower.FollowTrack(startTrack, pointSpan, trackDirection * 1000f); foreach (var trackEvent in trackEvents) { Terminal.Log(trackEvent.ToString()); Main.DebugLog(trackEvent.ToString()); } }); Register("hud.findCarOnJunction", _ => { var transform = PlayerManager.PlayerTransform; (RailTrack startTrack, EquiPointSet.Point? point) = RailTrack.GetClosest(transform.position); if (startTrack == null) { return; } var pointForward = point?.forward ?? Vector3.zero; var pointSpan = point?.span ?? 0; var trackDirection = Vector3.Dot(transform.forward, pointForward) > 0f ? 1 : -1; var trackEvents = TrackFollower.FollowTrack(startTrack, pointSpan, trackDirection * 1000f); var junction = trackEvents.OfType <JunctionEvent>().FirstOrDefault(); if (junction == null) { Terminal.Log("no junction"); return; } Terminal.Log(Overlay.GetCarOnJunction(junction.junction)?.ID ?? "no car on junction"); }); Register("hud.dumpInterior", _ => { if (PlayerManager.Car == null) { return; } if (PlayerManager.Car.loadedInterior != null) { Terminal.Log(DumpHierarchy(PlayerManager.Car.loadedInterior)); } }); Register("hud.getSpeedLimit", _ => { var transform = PlayerManager.PlayerTransform; (RailTrack startTrack, EquiPointSet.Point? point) = RailTrack.GetClosest(transform.position); if (startTrack == null) { return; } var pointForward = point?.forward ?? Vector3.zero; var pointSpan = point?.span ?? 0; var trackDirection = Vector3.Dot(transform.forward, pointForward) > 0f; Terminal.Log($"{TrackFollower.GetSpeedLimit(startTrack, pointSpan, trackDirection)}"); }); }