public static void CheckIntersections(Client ThisClient) { Vehicle ThisVehicle = ThisClient.Vehicle; if (ThisVehicle == Vehicles.NoVehicle) { return; } for (int j = 0; j < World.Objects.PathList.Count; j++) { World.Objects.Path ThisPath = World.Objects.PathList[j]; for (int k = ThisPath.Points.Count - 1; k >= 0; k--) { #region Segment Testings Maths... World.Objects.Path._Point ThisPoint = ThisPath.Points[k]; if (!ActiveCheckPoints.Select(x => x.CheckPoint).Contains(ThisPath.Points[0]) & ThisPoint != ThisPath.Points[0]) { continue; } Math3D.Point3 Previous = new Math3D.Point3(ThisVehicle.Prev_PosX, ThisVehicle.Prev_PosY, ThisVehicle.Prev_PosZ); Math3D.Point3 Current = new Math3D.Point3(ThisVehicle.PosX, ThisVehicle.PosY, ThisVehicle.PosZ); Math3D.Segment3 Segment = new Math3D.Segment3(Previous, Current); Math3D.Point3 Point = new Math3D.Point3(ThisPoint.X, ThisPoint.Y, ThisPoint.Z); double Tolerance = Math3D.Distance(Previous, Current); Tolerance /= (ThisVehicle.TimeStamp - ThisVehicle.Prev_TimeStamp); float HitRadius = (float)ThisVehicle.CachedAircraft.HTRADIUS; if (Tolerance < HitRadius * 5) { Tolerance = HitRadius * 5; } #endregion if (Math3D.DoesSegmentPassNearPoint(Segment, Point, Tolerance)) { lock (ActiveCheckPoints) { List <World.Objects.Path._Point> Intersection = ActiveCheckPoints.Select(x => x.CheckPoint).Intersect(ThisPath.Points).ToList(); if (ThisPath.Points.Count > Intersection.Count) { if (ThisPath.Points[Intersection.Count] == ThisPoint) //Allow to go forwards or backwards on the track! { #region Add the new point. ActiveCheckPoints.Add(new CheckPointDescriptor(ThisVehicle, ThisPoint)); #endregion #region Update the data-set intersection Intersection = ActiveCheckPoints.Select(x => x.CheckPoint).Intersect(ThisPath.Points).ToList(); #endregion #region GET SPLIT TIME string SplitTimeResult = "<ERROR>"; try { float starttime = 0; float endtime = 0; if (ActiveCheckPoints.Count > 0) { starttime = ActiveCheckPoints.Where(x => x.Vehicle == ThisVehicle).Where(y => y.CheckPoint == Intersection[0]).ToArray()[0].TimeStamp; endtime = ActiveCheckPoints.Where(x => x.Vehicle == ThisVehicle).Where(y => y.CheckPoint == ThisPoint).ToArray()[0].TimeStamp; } else { starttime = ThisVehicle.TimeStamp; endtime = ThisVehicle.TimeStamp; } TimeSpan StartTimeSpan = new TimeSpan(0, 0, 0, 0, (int)(starttime * 1000)); TimeSpan EndTimeSpan = new TimeSpan(0, 0, 0, 0, (int)(endtime * 1000)); TimeSpan LapTime = EndTimeSpan - StartTimeSpan; string Hours = LapTime.Hours.ToString(); while (Hours.Length < 2) { Hours = "0" + Hours; } if (Hours.Length > 2) { Hours = "99"; } string Minutes = LapTime.Minutes.ToString(); while (Minutes.Length < 2) { Minutes = "0" + Minutes; } if (Minutes.Length > 2) { Minutes = "99"; } string Seconds = LapTime.Seconds.ToString(); while (Seconds.Length < 2) { Seconds = "0" + Seconds; } if (Seconds.Length > 2) { Seconds = "99"; } string Milliseconds = LapTime.Milliseconds.ToString(); while (Milliseconds.Length < 3) { Milliseconds = "0" + Milliseconds; } if (Milliseconds.Length > 3) { Milliseconds = "999"; } SplitTimeResult = Hours + ":" + Minutes + ":" + Seconds + "." + Milliseconds; } catch { } #endregion if (SplitTimeResult == "00:00:00.000") { continue; //ThisClient.SendMessage(ThisPath.Identify + " Split " + (k - 1) + " - " + SplitTimeResult); } else { if (ThisPoint == ThisPath.Points[ThisPath.Points.Count - 1] & Intersection.Count == ThisPath.Points.Count) //Finish Line! { ThisClient.SendMessage("[" + ThisPath.Identify + "]" + " Lap - " + SplitTimeResult); } else { ThisClient.SendMessage("[" + ThisPath.Identify + "]" + " Split " + k + " - " + SplitTimeResult); } } } } if (ThisPoint == ThisPath.Points[ThisPath.Points.Count - 1] & Intersection.Count == ThisPath.Points.Count) { ActiveCheckPoints.OrderBy(x => x.TimeStamp); foreach (World.Objects.Path._Point ThisUnionPoint in Intersection) { CheckPointDescriptor CheckPointToRemove = ActiveCheckPoints.Where(x => x.CheckPoint == ThisUnionPoint).Where(y => y.Vehicle == ThisVehicle).ToArray()[0]; ActiveCheckPoints.Remove(CheckPointToRemove); } Intersection = ActiveCheckPoints.Select(x => x.CheckPoint).Intersect(ThisPath.Points).ToList(); //need to update this! } if (ThisPoint == ThisPath.Points[0] & Intersection.Count == 1) { //ThisClient.SendMessage("START LAP" + ActiveCheckPoints.Count.ToString()); //ActiveCheckPoints.Add(new CheckPointDescriptor(ThisVehicle, ThisPoint)); //continue; //k = 0; //Restart the check, we may have passed another checkpoint a second ago! } } } } } }
public void CheckIntersections(_Racer ThisRacer) { List <Client> NONRACING = Clients.AllClients.Except(ThisRacer.Race.Racers.Select(x => x.Client)).ToList(); List <Client> RACING = ThisRacer.Race.Racers.Select(x => x.Client).ToList(); if (RaceEnds <= DateTime.Now & Status.IsInProgress() & RaceEnds > RaceStarted) { //The session has timed out! lock (Threads.GenericThreadSafeLock) { if (!Status.IsFinished()) { Status.SetFinished(); } foreach (_Racer DNFRacer in Racers.Where(x => x.CurrentCheckpoint / (Path.Points.Count) < TotalLapCount)) { DNFRacer.Client.SendMessage("RACE OVER ##" + " P" + GetPositionOfRacer(DNFRacer) + " ## RACE OVER"); } } } if (ThisRacer.CurrentLap > TotalLapCount && TotalLapCount > 0) { //stop counting for this racer, they finished the race! return; } Client ThisClient = ThisRacer.Client; Vehicle ThisVehicle = ThisRacer.Client.Vehicle; if (ThisVehicle == Vehicles.NoVehicle) { return; } World.Objects.Path ThisPath = Path; World.Objects.Path._Point ThisPoint; try { ThisPoint = ThisPath.Points[(ThisRacer.CurrentCheckpoint + 1) % ThisPath.Points.Count]; } catch { return; } //Target point will be the next checkpoint the vehicle has to pass! #region Set up the 3D Maths required. //if (!ActiveCheckPoints.Select(x => x.CheckPoint).Contains(ThisPath.Points[0]) & ThisPoint != ThisPath.Points[0]) continue; Math3D.Point3 Previous = new Math3D.Point3(ThisVehicle.Prev_PosX, ThisVehicle.Prev_PosY, ThisVehicle.Prev_PosZ); Math3D.Point3 Current = new Math3D.Point3(ThisVehicle.PosX, ThisVehicle.PosY, ThisVehicle.PosZ); Math3D.Segment3 Segment = new Math3D.Segment3(Previous, Current); Math3D.Point3 Point = new Math3D.Point3(ThisPoint.X, ThisPoint.Y, ThisPoint.Z); double Tolerance = Math3D.Distance(Previous, Current); Tolerance /= (ThisVehicle.TimeStamp - ThisVehicle.Prev_TimeStamp); float HitRadius = (float)ThisVehicle.CachedAircraft.HTRADIUS; if (Tolerance < HitRadius * 5) { Tolerance = HitRadius * 5; } #endregion if (Math3D.DoesSegmentPassNearPoint(Segment, Point, Tolerance)) { int ModulatedCheckPointCount = (ThisRacer.CurrentCheckpoint + 1) % ThisPath.Points.Count; //increment point count! ThisRacer.CurrentCheckpoint++; string CurrentLapTime = "<ERROR>"; string CurrentSplitTime = "<ERROR>"; #region GET SPLIT/LAP TIME //float starttime = ThisRacer.TimeStamp_LastCheckpoint; float endtime = ThisRacer.TimeStamp_LastCheckpoint; float laptime = 0; float splittime = 0; try { double Distance = Math3D.GetPointSegmentDistanceIfIntersecting(Point, Segment); if (Distance == Double.PositiveInfinity | Distance == Double.NegativeInfinity) { //no intersection??? return; } double FractionOfTime = Distance / Segment.Length(); endtime = (float)(FractionOfTime * (ThisVehicle.TimeStamp - ThisVehicle.Prev_TimeStamp)) + ThisVehicle.Prev_TimeStamp; TimeSpan StartLapTimeSpan = new TimeSpan(0, 0, 0, 0, (int)(ThisRacer.TimeStamp_LapStarted * 1000)); TimeSpan StartSplitTimeSpan = new TimeSpan(0, 0, 0, 0, (int)(ThisRacer.TimeStamp_LastCheckpoint * 1000)); TimeSpan EndTimeSpan = new TimeSpan(0, 0, 0, 0, (int)(endtime * 1000)); CurrentLapTime = StartLapTimeSpan.GetTimeDifference(EndTimeSpan); laptime = (float)((EndTimeSpan - StartLapTimeSpan).TotalSeconds); splittime = (float)((EndTimeSpan - StartSplitTimeSpan).TotalSeconds); CurrentSplitTime = StartSplitTimeSpan.GetTimeDifference(EndTimeSpan); } catch { } #endregion if (ThisRacer.CumulativeSectorTimeStamps.Count > 0) { ThisRacer.CumulativeSectorTimeStamps.Add(splittime + ThisRacer.CumulativeSectorTimeStamps.Last()); } else { ThisRacer.CumulativeSectorTimeStamps.Add(splittime); } ThisRacer.SectorTimeStamps.Add(splittime); if (ModulatedCheckPointCount == 0) { //just passed the start/finish line! bool YellowLap = false; bool RedLap = false; if (CurrentLapTime == "00:00:00.000") { return; } float ThisLapTime = laptime; float LapTimeDifference = ThisLapTime - FastestLap; if (ThisRacer.FastestLap == 0) { ThisRacer.FastestLap = ThisLapTime; if (FastestLap == 0) { LapTimeDifference = 0; } else { LapTimeDifference = ThisLapTime - FastestLap; } } string PositionDifference = "<ERROR>"; string LapCountString = "<ERROR>"; if (FastestLap == 0) { //No fastest lap set yet! FastestLap = ThisLapTime; LapTimeDifference = 0; RedLap = true; } if (LapTimeDifference < 0) { //New Circuit Record! FastestLap = ThisLapTime; RedLap = true; NONRACING.SendMessage("&a" + ThisRacer.Client.Username + " Just set a new lap record on " + Path.Identify); NONRACING.SendMessage("&a Using a &3" + ThisRacer.Client.Vehicle.Identify); NONRACING.SendMessage("&a LapTime: &e" + ThisLapTime.AsFormattedTimeDifference().Substring(1) + "&c!"); RACING.Exclude(ThisRacer.Client).SendMessage("&a" + ThisRacer.Client.Username + " New lap record: &e" + ThisLapTime.AsFormattedTimeDifference().Substring(1) + "&c!"); } if (ThisRacer.FastestLap > ThisLapTime) { //New Personal Best! ThisRacer.FastestLap = ThisLapTime; YellowLap = true; } string LapBonusMarker = ""; if (YellowLap) { LapBonusMarker = "[&e+&f]"; } if (RedLap) { LapBonusMarker = "[&c#&f]"; } if (RaceTypeIsTimeTrial()) { LapCountString = "L" + ThisRacer.CurrentLap.ToString() + " P" + GetPositionOfRacer(ThisRacer); PositionDifference = LapTimeDifference.AsFormattedTimeDifference(); ThisClient.SendMessage(LapCountString + " - " + CurrentLapTime + " (" + PositionDifference + ")" + LapBonusMarker); } if (RaceTypeIsRace()) { string LapsRemaining = (TotalLapCount - ThisRacer.CurrentLap).ToString(); if (ThisRacer.CurrentLap < TotalLapCount) { LapCountString = "L" + LapsRemaining + " P" + GetPositionOfRacer(ThisRacer); } else { LapCountString = "P" + GetPositionOfRacer(ThisRacer); } int CurrentPosition = GetPositionOfRacer(ThisRacer); string PosAhead = ""; string PosBehind = ""; if (CurrentPosition != Racers.Count()) //Not Last { PosAhead = ThisRacer.RaceTimeGetTimeAheadString(); } if (CurrentPosition != 1) //Not First { PosBehind = ThisRacer.RaceTimeGetTimeBehindString(); } if (ThisRacer.CurrentLap < TotalLapCount) { ThisClient.SendMessage(LapCountString + " - " + CurrentLapTime + LapBonusMarker); } else { if (GetPositionOfRacer(ThisRacer) == 1) { ThisClient.SendMessage("RACE OVER ## " + LapCountString + " - " + ThisRacer.RaceTimeGetTotalTime() + LapBonusMarker + " ## RACE OVER"); } else { float Time = RacersSortedByPosition[0].RaceTimeGetTotalTime(); float Difference = ThisRacer.RaceTimeGetTotalTime() - Time; string StrDiff = Difference.AsFormattedTimeDifference(); ThisClient.SendMessage("RACE OVER ## " + LapCountString + " - " + ThisRacer.RaceTimeGetTotalTime() + LapBonusMarker + "(" + StrDiff + ")" + " ## RACE OVER"); } } if (PosAhead != "") { ThisClient.SendMessage(" " + PosAhead); } if (PosBehind != "") { ThisClient.SendMessage(" " + PosBehind); } } ThisRacer.TimeStamp_LapStarted = endtime; ThisRacer.TimeStamp_LastCheckpoint = endtime; if (GetPositionOfRacer(ThisRacer) == 1 & ThisRacer.CurrentLap == TotalLapCount & TotalLapCount != 0) { //coming first //completed the last lap //not a 0 lap race... //... Means this racer WON the race! RaceEnds = DateTime.Now + new TimeSpan(0, 0, 0, 0, (int)(FastestLap * 1000 * 2)); //double the fastest lap time of the race should be plenty of time for the stragglers to catch up! } ThisRacer.CurrentLap++; } else { //normal checkpoint. bool YellowSector = false; bool RedSector = false; #region FastestSectors if (FastestSectors[ModulatedCheckPointCount] == 0) { //no time set for this sector, set it now! FastestSectors[ModulatedCheckPointCount] = splittime; } if (splittime < FastestSectors[ModulatedCheckPointCount]) { //New circuit record sector! FastestSectors[ModulatedCheckPointCount] = splittime; } if (splittime < ThisRacer.FastestSectors[ModulatedCheckPointCount]) { //New personal best sector! ThisRacer.FastestSectors[ModulatedCheckPointCount] = splittime; } #endregion #region CumulativeSectors float Difference = laptime - CumulativeSectors[ModulatedCheckPointCount]; if (CumulativeSectors[ModulatedCheckPointCount] == 0) { //no time set for this sector, set it now! CumulativeSectors[ModulatedCheckPointCount] = laptime; RedSector = true; Difference = 0; } if (laptime < CumulativeSectors[ModulatedCheckPointCount]) { //New circuit record sector! CumulativeSectors[ModulatedCheckPointCount] = laptime; RedSector = true; } if (laptime < ThisRacer.CumulativeSectors[ModulatedCheckPointCount]) { //New personal best sector! ThisRacer.CumulativeSectors[ModulatedCheckPointCount] = laptime; YellowSector = true; } #endregion string StrDiff = Difference.AsFormattedTimeDifference(); string SectorBonusMarker = ""; if (YellowSector) { SectorBonusMarker = "[&e+&f]"; } if (RedSector) { SectorBonusMarker = "[&c#&f]"; } ThisClient.SendMessage("Split " + ModulatedCheckPointCount + " - " + CurrentSplitTime + "(" + StrDiff + ")" + SectorBonusMarker); ThisRacer.TimeStamp_LastCheckpoint = endtime; } } }