public override void clearState() { timeOfLastLimiterWarning = DateTime.MinValue; timeOfDisengageCheck = DateTime.MaxValue; pitWindowOpenLap = 0; pitWindowClosedLap = 0; pitWindowOpenTime = 0; pitWindowClosedTime = 0; pitDataInitialised = false; playBoxNowMessage = false; play2minOpenWarning = false; play2minCloseWarning = false; play1minOpenWarning = false; play1minCloseWarning = false; playClosedNow = false; playOpenNow = false; playPitThisLap = false; mandatoryStopCompleted = false; mandatoryStopBoxThisLap = false; mandatoryStopMissed = false; mandatoryTyreChangeTyreType = TyreType.Unknown_Race; hasMandatoryPitStop = false; hasMandatoryTyreChange = false; minDistanceOnCurrentTyre = -1; maxDistanceOnCurrentTyre = -1; enableWindowWarnings = true; }
/// <summary> /// Creates a new instance of the stint class specifically for use in strateiges /// </summary> /// <param name="_driver">The driver to link to the stint</param> /// <param name="passStartLap">The lap on which the stint starts</param> /// <param name="passTyreType">The tyre type used for the stint</param> /// <param name="_stintLength">The number of laps in the stint</param> public Stint(int passStartLap, TyreType passTyreType, int _stintLength) { session = 5; startLap = passStartLap; lapTimes = new List <float>(); tyreType = passTyreType; stintLength = _stintLength; modified = false; }
public void ChangeStintTyreType(int stintToChange, TyreType newTyreType) { listOfStints[stintToChange].tyreType = newTyreType; int lapsThroughRace = listOfStints[stintToChange].startLap; listOfStints[stintToChange] = PopulateSingleStint(Stints[stintToChange], ref lapsThroughRace); UpdateStrategyParameters(); MyEvents.OnStrategyModified(Data.Drivers[driverIndex], this, false); }
public CarClass(CarClassEnum carClassEnum, String[] pCarsClassNames, int[] raceroomClassIds, BrakeType brakeType, TyreType defaultTyreType, float maxSafeWaterTemp, float maxSafeOilTemp) { this.carClassEnum = carClassEnum; this.pCarsClassNames = pCarsClassNames; this.raceroomClassIds = raceroomClassIds; this.brakeType = brakeType; this.defaultTyreType = defaultTyreType; this.maxSafeOilTemp = maxSafeOilTemp; this.maxSafeWaterTemp = maxSafeWaterTemp; this.minTyreCircumference = carMinTyreCircumference; this.maxTyreCircumference = carMaxTyreCircumference; }
public override void clearState() { pitWindowOpenLap = 0; pitWindowClosedLap = 0; pitWindowOpenTime = 0; pitWindowClosedTime = 0; pitDataInitialised = false; playBoxNowMessage = false; play2minOpenWarning = false; play2minCloseWarning = false; play1minOpenWarning = false; play1minCloseWarning = false; playClosedNow = false; playOpenNow = false; playPitThisLap = false; mandatoryStopCompleted = false; mandatoryStopBoxThisLap = false; mandatoryStopMissed = false; mandatoryTyreChangeTyreType = TyreType.Unknown_Race; hasMandatoryPitStop = false; hasMandatoryTyreChange = false; minDistanceOnCurrentTyre = -1; maxDistanceOnCurrentTyre = -1; }
override protected void triggerInternal(GameStateData previousGameState, GameStateData currentGameState) { // AMS (RF1) uses the pit window calculations to make 'box now' calls for scheduled stops, but we don't want // the pit window opening / closing warnings. // Try also applying the same approach to rF2. if (CrewChief.gameDefinition.gameEnum == GameEnum.RF1 || CrewChief.gameDefinition.gameEnum == GameEnum.RF2_64BIT) { enableWindowWarnings = false; } if (currentGameState.PitData.limiterStatus != -1 && currentGameState.Now > timeOfLastLimiterWarning + TimeSpan.FromSeconds(30)) { if (currentGameState.SessionData.SectorNumber == 1 && currentGameState.Now > timeOfDisengageCheck && !currentGameState.PitData.InPitlane && currentGameState.PitData.limiterStatus == 1) { // in S1 but have exited pits, and we're expecting the limit to have been turned off timeOfDisengageCheck = DateTime.MaxValue; timeOfLastLimiterWarning = currentGameState.Now; audioPlayer.playMessage(new QueuedMessage(folderDisengageLimiter, 0, this)); } else if (previousGameState != null) { if (currentGameState.SessionData.SectorNumber == 3 && !previousGameState.PitData.InPitlane && currentGameState.PitData.InPitlane && currentGameState.PitData.limiterStatus == 0) { // just entered the pit lane with no limiter active audioPlayer.playMessage(new QueuedMessage(folderEngageLimiter, 0, this)); timeOfLastLimiterWarning = currentGameState.Now; } else if (currentGameState.SessionData.SectorNumber == 1 && previousGameState.PitData.InPitlane && !currentGameState.PitData.InPitlane && currentGameState.PitData.limiterStatus == 1) { // just left the pitlane with the limiter active - wait 2 seconds then warn timeOfDisengageCheck = currentGameState.Now + TimeSpan.FromSeconds(2); } } } if (currentGameState.SessionData.SessionType == SessionType.Race && currentGameState.PitData.HasMandatoryPitStop && (currentGameState.SessionData.SessionPhase == SessionPhase.Green || currentGameState.SessionData.SessionPhase == SessionPhase.FullCourseYellow)) { // allow this data to be reinitialised during a race (hack for AMS) if (!pitDataInitialised || currentGameState.PitData.ResetEvents) { mandatoryStopCompleted = false; mandatoryStopBoxThisLap = false; mandatoryStopMissed = false; Console.WriteLine("pit start = " + currentGameState.PitData.PitWindowStart + ", pit end = " + currentGameState.PitData.PitWindowEnd); hasMandatoryPitStop = currentGameState.PitData.HasMandatoryPitStop; hasMandatoryTyreChange = currentGameState.PitData.HasMandatoryTyreChange; mandatoryTyreChangeTyreType = currentGameState.PitData.MandatoryTyreChangeRequiredTyreType; maxDistanceOnCurrentTyre = currentGameState.PitData.MaxPermittedDistanceOnCurrentTyre; minDistanceOnCurrentTyre = currentGameState.PitData.MinPermittedDistanceOnCurrentTyre; if (currentGameState.SessionData.SessionNumberOfLaps > 0) { pitWindowOpenLap = currentGameState.PitData.PitWindowStart; pitWindowClosedLap = currentGameState.PitData.PitWindowEnd; playPitThisLap = true; } else if (currentGameState.SessionData.SessionTimeRemaining > 0) { pitWindowOpenTime = currentGameState.PitData.PitWindowStart; pitWindowClosedTime = currentGameState.PitData.PitWindowEnd; if (pitWindowOpenTime > 0) { play2minOpenWarning = pitWindowOpenTime > 2; play1minOpenWarning = pitWindowOpenTime > 1; playOpenNow = true; } if (pitWindowClosedTime > 0) { play2minCloseWarning = pitWindowClosedTime > 2; play1minCloseWarning = pitWindowClosedTime > 1; playClosedNow = true; playPitThisLap = true; } } else { Console.WriteLine("Error getting pit data"); } pitDataInitialised = true; } else if (currentGameState.PitData.IsMakingMandatoryPitStop) { playPitThisLap = false; playBoxNowMessage = false; mandatoryStopCompleted = true; mandatoryStopBoxThisLap = false; mandatoryStopMissed = false; } else { if (currentGameState.SessionData.IsNewLap && currentGameState.SessionData.CompletedLaps > 0 && currentGameState.SessionData.SessionNumberOfLaps > 0) { if (currentGameState.PitData.PitWindow != PitWindow.StopInProgress && currentGameState.PitData.PitWindow != PitWindow.Completed) { if (maxDistanceOnCurrentTyre > 0 && currentGameState.SessionData.CompletedLaps == maxDistanceOnCurrentTyre && playPitThisLap) { playBoxNowMessage = true; playPitThisLap = false; mandatoryStopBoxThisLap = true; if (mandatoryTyreChangeTyreType == TyreType.R3E_NEW_Prime) { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsFitPrimesThisLap, random.Next(0, 10), this)); } else if (mandatoryTyreChangeTyreType == TyreType.R3E_NEW_Option) { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsFitOptionsThisLap, random.Next(0, 20), this)); } else { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitThisLap, random.Next(0, 20), this)); } } else if (minDistanceOnCurrentTyre > 0 && currentGameState.SessionData.CompletedLaps == minDistanceOnCurrentTyre) { if (mandatoryTyreChangeTyreType == TyreType.R3E_NEW_Prime) { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsCanNowFitPrimes, random.Next(0, 20), this)); } else if (mandatoryTyreChangeTyreType == TyreType.R3E_NEW_Option) { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsCanNowFitOptions, random.Next(0, 20), this)); } } } if (pitWindowOpenLap > 0 && currentGameState.SessionData.CompletedLaps == pitWindowOpenLap - 1) { // note this is a 'pit window opens at the end of this lap' message, // so we play it 1 lap before the window opens if (enableWindowWarnings) { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitWindowOpening, random.Next(0, 20), this)); } } else if (pitWindowOpenLap > 0 && currentGameState.SessionData.CompletedLaps == pitWindowOpenLap) { if (enableWindowWarnings) { audioPlayer.setBackgroundSound(AudioPlayer.dtmPitWindowOpenBackground); audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitWindowOpen, 0, this)); } } else if (pitWindowClosedLap > 0 && currentGameState.SessionData.CompletedLaps == pitWindowClosedLap - 1) { if (enableWindowWarnings) { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitWindowClosing, random.Next(0, 20), this)); } if (currentGameState.PitData.PitWindow != PitWindow.Completed && currentGameState.PitData.PitWindow != PitWindow.StopInProgress) { playBoxNowMessage = true; if (mandatoryTyreChangeTyreType == TyreType.R3E_NEW_Prime) { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsFitPrimesThisLap, random.Next(0, 10), this)); } else if (mandatoryTyreChangeTyreType == TyreType.R3E_NEW_Option) { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsFitOptionsThisLap, random.Next(0, 10), this)); } else { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitThisLap, random.Next(0, 10), this)); } } } else if (pitWindowClosedLap > 0 && currentGameState.SessionData.CompletedLaps == pitWindowClosedLap) { mandatoryStopBoxThisLap = false; if (currentGameState.PitData.PitWindow != PitWindow.Completed) { mandatoryStopMissed = true; } if (enableWindowWarnings) { audioPlayer.setBackgroundSound(AudioPlayer.dtmPitWindowClosedBackground); audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitWindowClosed, 0, this)); } } } else if (currentGameState.SessionData.IsNewLap && currentGameState.SessionData.CompletedLaps > 0 && currentGameState.SessionData.SessionTimeRemaining > 0) { if (pitWindowClosedTime > 0 && currentGameState.PitData.PitWindow != PitWindow.StopInProgress && currentGameState.PitData.PitWindow != PitWindow.Completed && currentGameState.SessionData.SessionTotalRunTime - currentGameState.SessionData.SessionTimeRemaining > pitWindowOpenTime * 60 && currentGameState.SessionData.SessionTotalRunTime - currentGameState.SessionData.SessionTimeRemaining < pitWindowClosedTime * 60) { double timeLeftToPit = pitWindowClosedTime * 60 - (currentGameState.SessionData.SessionTotalRunTime - currentGameState.SessionData.SessionTimeRemaining); if (playPitThisLap && currentGameState.SessionData.PlayerLapTimeSessionBest + 10 > timeLeftToPit) { // oh dear, we might have missed the pit window. playBoxNowMessage = true; playPitThisLap = false; mandatoryStopBoxThisLap = true; if (enableWindowWarnings) { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitThisLapTooLate, 0, this)); } } else if (playPitThisLap && currentGameState.SessionData.PlayerLapTimeSessionBest + 10 < timeLeftToPit && (currentGameState.SessionData.PlayerLapTimeSessionBest * 2) + 10 > timeLeftToPit) { // we probably won't make it round twice - pit at the end of this lap playBoxNowMessage = true; playPitThisLap = false; mandatoryStopBoxThisLap = true; if (mandatoryTyreChangeTyreType == TyreType.R3E_NEW_Prime) { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsFitPrimesThisLap, random.Next(0, 20), this)); } else if (mandatoryTyreChangeTyreType == TyreType.R3E_NEW_Option) { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsFitOptionsThisLap, random.Next(0, 20), this)); } else { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitThisLap, random.Next(0, 20), this)); } } } } if (playOpenNow && currentGameState.SessionData.SessionTimeRemaining > 0 && (currentGameState.SessionData.SessionTotalRunTime - currentGameState.SessionData.SessionTimeRemaining > (pitWindowOpenTime * 60) || currentGameState.PitData.PitWindow == PitWindow.Open)) { playOpenNow = false; play1minOpenWarning = false; play2minOpenWarning = false; if (enableWindowWarnings) { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitWindowOpen, 0, this)); } } else if (play1minOpenWarning && currentGameState.SessionData.SessionTimeRemaining > 0 && currentGameState.SessionData.SessionTotalRunTime - currentGameState.SessionData.SessionTimeRemaining > ((pitWindowOpenTime - 1) * 60)) { play1minOpenWarning = false; play2minOpenWarning = false; if (enableWindowWarnings) { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitWindowOpen1Min, 0, this)); } } else if (play2minOpenWarning && currentGameState.SessionData.SessionTimeRemaining > 0 && currentGameState.SessionData.SessionTotalRunTime - currentGameState.SessionData.SessionTimeRemaining > ((pitWindowOpenTime - 2) * 60)) { play2minOpenWarning = false; if (enableWindowWarnings) { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitWindowOpen2Min, 0, this)); } } else if (pitWindowClosedTime > 0 && playClosedNow && currentGameState.SessionData.SessionTimeRemaining > 0 && currentGameState.SessionData.SessionTotalRunTime - currentGameState.SessionData.SessionTimeRemaining > (pitWindowClosedTime * 60)) { playClosedNow = false; playBoxNowMessage = false; play1minCloseWarning = false; play2minCloseWarning = false; playPitThisLap = false; mandatoryStopBoxThisLap = false; if (currentGameState.PitData.PitWindow != PitWindow.Completed) { mandatoryStopMissed = true; } if (enableWindowWarnings) { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitWindowClosed, 0, this)); } } else if (pitWindowClosedTime > 0 && play1minCloseWarning && currentGameState.SessionData.SessionTimeRemaining > 0 && currentGameState.SessionData.SessionTotalRunTime - currentGameState.SessionData.SessionTimeRemaining > ((pitWindowClosedTime - 1) * 60)) { play1minCloseWarning = false; play2minCloseWarning = false; if (enableWindowWarnings) { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitWindowCloses1min, 0, this)); } } else if (pitWindowClosedTime > 0 && play2minCloseWarning && currentGameState.SessionData.SessionTimeRemaining > 0 && currentGameState.SessionData.SessionTotalRunTime - currentGameState.SessionData.SessionTimeRemaining > ((pitWindowClosedTime - 2) * 60)) { play2minCloseWarning = false; if (enableWindowWarnings) { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitWindowCloses2min, 0, this)); } } // for Automobilista, sector update lag time means sometimes we miss the pit entrance before this message plays // TODO: Verify for rF2. if (playBoxNowMessage && currentGameState.SessionData.SectorNumber == 2 && CrewChief.gameDefinition.gameEnum == GameEnum.RF1) { playBoxNowMessage = false; // pit entry is right at sector 3 timing line, play message part way through sector 2 to give us time to pit int messageDelay = currentGameState.SessionData.PlayerBestSector2Time > 0 ? (int)(currentGameState.SessionData.PlayerBestSector2Time * 0.7) : 15; audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitNow, messageDelay, this)); } if (playBoxNowMessage && currentGameState.SessionData.SectorNumber == 3) { playBoxNowMessage = false; if (mandatoryTyreChangeTyreType == TyreType.R3E_NEW_Prime) { audioPlayer.playMessage(new QueuedMessage("box_now_for_primes", MessageContents(folderMandatoryPitStopsPitNow, folderMandatoryPitStopsPrimeTyres), 3, this)); } else if (mandatoryTyreChangeTyreType == TyreType.R3E_NEW_Option) { audioPlayer.playMessage(new QueuedMessage("box_now_for_options", MessageContents(folderMandatoryPitStopsPitNow, folderMandatoryPitStopsOptionTyres), 3, this)); } else { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitNow, 3, this)); } } } } }
public GameStateData mapToGameStateData(Object memoryMappedFileStruct, GameStateData previousGameState) { pCarsAPIStruct shared = ((CrewChiefV3.PCars.PCarsSharedMemoryReader.PCarsStructWrapper)memoryMappedFileStruct).data; long ticks = ((CrewChiefV3.PCars.PCarsSharedMemoryReader.PCarsStructWrapper)memoryMappedFileStruct).ticksWhenRead; // game state is 3 for paused, 5 for replay. No idea what 4 is... if (shared.mGameState == (uint)eGameState.GAME_FRONT_END || (shared.mGameState == (uint)eGameState.GAME_INGAME_PAUSED && !System.Diagnostics.Debugger.IsAttached) || (shared.mGameState == (uint)eGameState.GAME_INGAME_PAUSED) || shared.mGameState == (uint)eGameState.GAME_VIEWING_REPLAY || shared.mGameState == (uint)eGameState.GAME_EXITED) { // don't ignore the paused game updates if we're in debug mode return previousGameState; } GameStateData currentGameState = new GameStateData(ticks); if (shared.mNumParticipants < 1 || shared.mTrackLength <= 0) { // Unusable data in the block // TODO: is this check sufficient? return null; } Tuple<int, pCarsAPIParticipantStruct> playerData = getPlayerDataStruct(shared.mParticipantData, shared.mViewedParticipantIndex); if (getPlayerByName && playerSteamId != shared.mParticipantData[shared.mViewedParticipantIndex].mName) { return null; } int playerDataIndex = playerData.Item1; pCarsAPIParticipantStruct viewedParticipant = playerData.Item2; NameValidator.validateName(viewedParticipant.mName); currentGameState.SessionData.CompletedLaps = (int)viewedParticipant.mLapsCompleted; currentGameState.SessionData.SectorNumber = (int)viewedParticipant.mCurrentSector; currentGameState.SessionData.Position = (int)viewedParticipant.mRacePosition; currentGameState.SessionData.UnFilteredPosition = (int)viewedParticipant.mRacePosition; currentGameState.SessionData.IsNewSector = previousGameState == null || viewedParticipant.mCurrentSector != previousGameState.SessionData.SectorNumber; // When in the pit lane, mCurrentLapDistance gets set to 0 when crossing the start line and *remains at 0* until some distance into the lap (about 300 metres) currentGameState.PositionAndMotionData.DistanceRoundTrack = viewedParticipant.mCurrentLapDistance; // previous session data to check if we've started an new session SessionPhase lastSessionPhase = SessionPhase.Unavailable; SessionType lastSessionType = SessionType.Unavailable; float lastSessionRunningTime = 0; int lastSessionLapsCompleted = 0; TrackDefinition lastSessionTrack = null; Boolean lastSessionHasFixedTime = false; int lastSessionNumberOfLaps = 0; float lastSessionRunTime = 0; float lastSessionTimeRemaining = 0; if (previousGameState != null) { lastSessionPhase = previousGameState.SessionData.SessionPhase; lastSessionType = previousGameState.SessionData.SessionType; lastSessionRunningTime = previousGameState.SessionData.SessionRunningTime; lastSessionHasFixedTime = previousGameState.SessionData.SessionHasFixedTime; lastSessionTrack = previousGameState.SessionData.TrackDefinition; lastSessionLapsCompleted = previousGameState.SessionData.CompletedLaps; lastSessionNumberOfLaps = previousGameState.SessionData.SessionNumberOfLaps; lastSessionRunTime = previousGameState.SessionData.SessionRunTime; lastSessionTimeRemaining = previousGameState.SessionData.SessionTimeRemaining; currentGameState.carClass = previousGameState.carClass; } if (currentGameState.carClass.carClassEnum == CarData.CarClassEnum.UNKNOWN_RACE) { CarData.CarClass newClass = CarData.getCarClassForPCarsClassName(shared.mCarClassName); if (newClass.carClassEnum != currentGameState.carClass.carClassEnum) { currentGameState.carClass = newClass; Console.WriteLine("Player is using car class " + currentGameState.carClass.carClassEnum + " (class name " + shared.mCarClassName + ")"); brakeTempThresholdsForPlayersCar = CarData.getBrakeTempThresholds(currentGameState.carClass, shared.mCarName); // no tyre data in the block so get the default tyre types for this car defaultTyreTypeForPlayersCar = CarData.getDefaultTyreType(currentGameState.carClass, shared.mCarName); } } // current session data currentGameState.SessionData.SessionType = mapToSessionType(shared); Boolean leaderHasFinished = previousGameState != null && previousGameState.SessionData.LeaderHasFinishedRace; currentGameState.SessionData.LeaderHasFinishedRace = leaderHasFinished; currentGameState.SessionData.IsDisqualified = shared.mRaceState == (int)eRaceState.RACESTATE_DISQUALIFIED; currentGameState.SessionData.SessionPhase = mapToSessionPhase(currentGameState.SessionData.SessionType, shared.mSessionState, shared.mRaceState, shared.mNumParticipants, leaderHasFinished, lastSessionPhase, lastSessionTimeRemaining, lastSessionRunTime); float sessionTimeRemaining = -1; int numberOfLapsInSession = (int)shared.mLapsInEvent; if (shared.mEventTimeRemaining > 0) { currentGameState.SessionData.SessionHasFixedTime = true; sessionTimeRemaining = shared.mEventTimeRemaining; } currentGameState.SessionData.TrackDefinition = TrackData.getTrackDefinition(shared.mTrackLocation + ":" + shared.mTrackVariation, shared.mTrackLength); // Console.WriteLine(lastSessionPhase + ", " + currentGameState.SessionData.SessionPhase + "; " + lastSessionType + ", " + currentGameState.SessionData.SessionType); // now check if this is a new session... Boolean raceRestarted = currentGameState.SessionData.SessionType == SessionType.Race && lastSessionPhase == SessionPhase.Green && currentGameState.SessionData.SessionPhase == SessionPhase.Countdown; if (raceRestarted || (currentGameState.SessionData.SessionType != SessionType.Unavailable && (lastSessionType != currentGameState.SessionData.SessionType || lastSessionHasFixedTime != currentGameState.SessionData.SessionHasFixedTime || lastSessionTrack == null || lastSessionTrack.name != currentGameState.SessionData.TrackDefinition.name || lastSessionLapsCompleted > currentGameState.SessionData.CompletedLaps || (numberOfLapsInSession > 0 && lastSessionNumberOfLaps > 0 && lastSessionNumberOfLaps != numberOfLapsInSession) || (sessionTimeRemaining > 0 && sessionTimeRemaining > lastSessionRunTime)))) { Console.WriteLine("New session, trigger..."); if (raceRestarted) { Console.WriteLine("Race restarted (green -> countdown)"); } if (lastSessionType != currentGameState.SessionData.SessionType) { Console.WriteLine("lastSessionType = " + lastSessionType + " currentGameState.SessionData.SessionType = " + currentGameState.SessionData.SessionType); } else if (lastSessionHasFixedTime != currentGameState.SessionData.SessionHasFixedTime) { Console.WriteLine("lastSessionHasFixedTime = " + lastSessionHasFixedTime + " currentGameState.SessionData.SessionHasFixedTime = " + currentGameState.SessionData.SessionHasFixedTime); } else if (lastSessionTrack != currentGameState.SessionData.TrackDefinition) { String lastTrackName = lastSessionTrack == null ? "unknown" : lastSessionTrack.name; String currentTrackName = currentGameState.SessionData.TrackDefinition == null ? "unknown" : currentGameState.SessionData.TrackDefinition.name; Console.WriteLine("lastSessionTrack = " + lastTrackName + " currentGameState.SessionData.Track = " + currentTrackName); } else if (lastSessionLapsCompleted > currentGameState.SessionData.CompletedLaps) { Console.WriteLine("lastSessionLapsCompleted = " + lastSessionLapsCompleted + " currentGameState.SessionData.CompletedLaps = " + currentGameState.SessionData.CompletedLaps); } else if (lastSessionNumberOfLaps != numberOfLapsInSession) { Console.WriteLine("lastSessionNumberOfLaps = " + lastSessionNumberOfLaps + " numberOfLapsInSession = "+ numberOfLapsInSession); } else if (sessionTimeRemaining > 0 && sessionTimeRemaining > lastSessionRunTime) { Console.WriteLine("sessionTimeRemaining = " + sessionTimeRemaining + " lastSessionRunTime = " + lastSessionRunTime); } currentGameState.SessionData.IsNewSession = true; currentGameState.SessionData.SessionNumberOfLaps = numberOfLapsInSession; currentGameState.SessionData.LeaderHasFinishedRace = false; currentGameState.SessionData.SessionStartTime = currentGameState.Now; currentGameState.SessionData.SessionStartPosition = (int)viewedParticipant.mRacePosition; if (currentGameState.SessionData.SessionHasFixedTime) { currentGameState.SessionData.SessionRunTime = sessionTimeRemaining; currentGameState.SessionData.SessionTimeRemaining = sessionTimeRemaining; if (currentGameState.SessionData.SessionRunTime == 0) { Console.WriteLine("Setting session run time to 0"); } Console.WriteLine("Time in this new session = " + sessionTimeRemaining); } currentGameState.SessionData.DriverRawName = viewedParticipant.mName; currentGameState.PitData.IsRefuellingAllowed = true; for (int i=0; i < shared.mParticipantData.Length; i++) { pCarsAPIParticipantStruct participantStruct = shared.mParticipantData[i]; if (i != playerDataIndex && participantStruct.mIsActive && participantStruct.mName != null && participantStruct.mName.Length > 0) { if (!currentGameState.OpponentData.ContainsKey(participantStruct.mName)) { currentGameState.OpponentData.Add(participantStruct.mName, createOpponentData(participantStruct, false)); } } } currentGameState.carClass = CarData.getCarClassForPCarsClassName(shared.mCarClassName); Console.WriteLine("Player is using car class " + currentGameState.carClass.carClassEnum + " (class name " + shared.mCarClassName + ")"); brakeTempThresholdsForPlayersCar = CarData.getBrakeTempThresholds(currentGameState.carClass, shared.mCarName); // no tyre data in the block so get the default tyre types for this car defaultTyreTypeForPlayersCar = CarData.getDefaultTyreType(currentGameState.carClass, shared.mCarName); } else { Boolean justGoneGreen = false; if (lastSessionPhase != currentGameState.SessionData.SessionPhase) { if (currentGameState.SessionData.SessionPhase == SessionPhase.Green) { justGoneGreen = true; // just gone green, so get the session data if (currentGameState.SessionData.SessionType == SessionType.Race) { if (currentGameState.SessionData.SessionHasFixedTime) { currentGameState.SessionData.SessionRunTime = sessionTimeRemaining; currentGameState.SessionData.SessionTimeRemaining = sessionTimeRemaining; if (currentGameState.SessionData.SessionRunTime == 0) { Console.WriteLine("Setting session run time to 0"); } } currentGameState.SessionData.SessionStartTime = currentGameState.Now; currentGameState.SessionData.SessionNumberOfLaps = numberOfLapsInSession; currentGameState.SessionData.SessionStartPosition = (int)viewedParticipant.mRacePosition; } currentGameState.SessionData.LeaderHasFinishedRace = false; currentGameState.SessionData.NumCarsAtStartOfSession = shared.mNumParticipants; currentGameState.SessionData.TrackDefinition = TrackData.getTrackDefinition(shared.mTrackLocation + ":" + shared.mTrackVariation, shared.mTrackLength); currentGameState.carClass = CarData.getCarClassForPCarsClassName(shared.mCarClassName); Console.WriteLine("Player is using car class " + currentGameState.carClass.carClassEnum + " (class name " + shared.mCarClassName + ")"); brakeTempThresholdsForPlayersCar = CarData.getBrakeTempThresholds(currentGameState.carClass, shared.mCarName); // no tyre data in the block so get the default tyre types for this car defaultTyreTypeForPlayersCar = CarData.getDefaultTyreType(currentGameState.carClass, shared.mCarName); if (previousGameState != null) { currentGameState.OpponentData = previousGameState.OpponentData; currentGameState.PitData.IsRefuellingAllowed = previousGameState.PitData.IsRefuellingAllowed; if (currentGameState.SessionData.SessionType != SessionType.Race) { currentGameState.SessionData.SessionStartTime = previousGameState.SessionData.SessionStartTime; currentGameState.SessionData.SessionRunTime = previousGameState.SessionData.SessionRunTime; currentGameState.SessionData.SessionTimeRemaining = previousGameState.SessionData.SessionTimeRemaining; currentGameState.SessionData.SessionNumberOfLaps = previousGameState.SessionData.SessionNumberOfLaps; } } Console.WriteLine("Just gone green, session details..."); Console.WriteLine("SessionType " + currentGameState.SessionData.SessionType); Console.WriteLine("SessionPhase " + currentGameState.SessionData.SessionPhase); if (previousGameState != null) { Console.WriteLine("previous SessionPhase " + previousGameState.SessionData.SessionPhase); } Console.WriteLine("EventIndex " + currentGameState.SessionData.EventIndex); Console.WriteLine("SessionIteration " + currentGameState.SessionData.SessionIteration); Console.WriteLine("HasMandatoryPitStop " + currentGameState.PitData.HasMandatoryPitStop); Console.WriteLine("PitWindowStart " + currentGameState.PitData.PitWindowStart); Console.WriteLine("PitWindowEnd " + currentGameState.PitData.PitWindowEnd); Console.WriteLine("NumCarsAtStartOfSession " + currentGameState.SessionData.NumCarsAtStartOfSession); Console.WriteLine("SessionNumberOfLaps " + currentGameState.SessionData.SessionNumberOfLaps); Console.WriteLine("SessionRunTime " + currentGameState.SessionData.SessionRunTime); Console.WriteLine("SessionStartPosition " + currentGameState.SessionData.SessionStartPosition); Console.WriteLine("SessionStartTime " + currentGameState.SessionData.SessionStartTime); String trackName = currentGameState.SessionData.TrackDefinition == null ? "unknown" : currentGameState.SessionData.TrackDefinition.name; Console.WriteLine("TrackName " + trackName); } } // copy persistent data from the previous game state // if (!justGoneGreen && previousGameState != null) { currentGameState.SessionData.SessionStartTime = previousGameState.SessionData.SessionStartTime; currentGameState.SessionData.SessionRunTime = previousGameState.SessionData.SessionRunTime; currentGameState.SessionData.SessionNumberOfLaps = previousGameState.SessionData.SessionNumberOfLaps; currentGameState.SessionData.SessionStartPosition = previousGameState.SessionData.SessionStartPosition; currentGameState.SessionData.NumCarsAtStartOfSession = previousGameState.SessionData.NumCarsAtStartOfSession; currentGameState.SessionData.TrackDefinition = previousGameState.SessionData.TrackDefinition; currentGameState.SessionData.EventIndex = previousGameState.SessionData.EventIndex; currentGameState.SessionData.SessionIteration = previousGameState.SessionData.SessionIteration; currentGameState.OpponentData = previousGameState.OpponentData; currentGameState.PitData.PitWindowStart = previousGameState.PitData.PitWindowStart; currentGameState.PitData.PitWindowEnd = previousGameState.PitData.PitWindowEnd; currentGameState.PitData.HasMandatoryPitStop = previousGameState.PitData.HasMandatoryPitStop; currentGameState.PitData.HasMandatoryDriverChange = previousGameState.PitData.HasMandatoryDriverChange; currentGameState.PitData.HasMandatoryTyreChange = previousGameState.PitData.HasMandatoryTyreChange; currentGameState.PitData.MandatoryTyreChangeRequiredTyreType = previousGameState.PitData.MandatoryTyreChangeRequiredTyreType; currentGameState.PitData.IsRefuellingAllowed = previousGameState.PitData.IsRefuellingAllowed; currentGameState.PitData.MaxPermittedDistanceOnCurrentTyre = previousGameState.PitData.MaxPermittedDistanceOnCurrentTyre; currentGameState.PitData.MinPermittedDistanceOnCurrentTyre = previousGameState.PitData.MinPermittedDistanceOnCurrentTyre; currentGameState.PitData.OnInLap = previousGameState.PitData.OnInLap; currentGameState.PitData.OnOutLap = previousGameState.PitData.OnOutLap; // the other properties of PitData are updated each tick, and shouldn't be copied over here. Nasty... currentGameState.SessionData.SessionTimesAtEndOfSectors = previousGameState.SessionData.SessionTimesAtEndOfSectors; currentGameState.PenaltiesData.CutTrackWarnings = previousGameState.PenaltiesData.CutTrackWarnings; currentGameState.SessionData.formattedPlayerLapTimes = previousGameState.SessionData.formattedPlayerLapTimes; currentGameState.SessionData.PlayerLapTimeSessionBest = previousGameState.SessionData.PlayerLapTimeSessionBest; currentGameState.SessionData.OpponentsLapTimeSessionBestOverall = previousGameState.SessionData.OpponentsLapTimeSessionBestOverall; currentGameState.SessionData.OpponentsLapTimeSessionBestPlayerClass = previousGameState.SessionData.OpponentsLapTimeSessionBestPlayerClass; currentGameState.SessionData.OverallSessionBestLapTime = previousGameState.SessionData.OverallSessionBestLapTime; currentGameState.SessionData.PlayerClassSessionBestLapTime = previousGameState.SessionData.PlayerClassSessionBestLapTime; currentGameState.SessionData.GameTimeAtLastPositionFrontChange = previousGameState.SessionData.GameTimeAtLastPositionFrontChange; currentGameState.SessionData.GameTimeAtLastPositionBehindChange = previousGameState.SessionData.GameTimeAtLastPositionBehindChange; currentGameState.SessionData.LastSector1Time = previousGameState.SessionData.LastSector1Time; currentGameState.SessionData.LastSector2Time = previousGameState.SessionData.LastSector2Time; currentGameState.SessionData.LastSector3Time = previousGameState.SessionData.LastSector3Time; currentGameState.SessionData.PlayerBestSector1Time = previousGameState.SessionData.PlayerBestSector1Time; currentGameState.SessionData.PlayerBestSector2Time = previousGameState.SessionData.PlayerBestSector2Time; currentGameState.SessionData.PlayerBestSector3Time = previousGameState.SessionData.PlayerBestSector3Time; currentGameState.SessionData.PlayerBestLapSector1Time = previousGameState.SessionData.PlayerBestLapSector1Time; currentGameState.SessionData.PlayerBestLapSector2Time = previousGameState.SessionData.PlayerBestLapSector2Time; currentGameState.SessionData.PlayerBestLapSector3Time = previousGameState.SessionData.PlayerBestLapSector3Time; currentGameState.Conditions = previousGameState.Conditions; } } //------------------- Variable session data --------------------------- if (currentGameState.SessionData.SessionHasFixedTime) { currentGameState.SessionData.SessionRunningTime = currentGameState.SessionData.SessionRunTime - shared.mEventTimeRemaining; currentGameState.SessionData.SessionTimeRemaining = shared.mEventTimeRemaining; } else { currentGameState.SessionData.SessionRunningTime = (float)(currentGameState.Now - currentGameState.SessionData.SessionStartTime).TotalSeconds; } if (currentGameState.SessionData.IsNewSector) { if (currentGameState.SessionData.SectorNumber == 1) { currentGameState.SessionData.LapTimePreviousEstimateForInvalidLap = currentGameState.SessionData.SessionRunningTime - currentGameState.SessionData.SessionTimesAtEndOfSectors[3]; currentGameState.SessionData.SessionTimesAtEndOfSectors[3] = currentGameState.SessionData.SessionRunningTime; currentGameState.SessionData.LastSector3Time = shared.mCurrentSector3Time; if (currentGameState.SessionData.LastSector3Time > 0 && (currentGameState.SessionData.PlayerBestSector3Time == -1 || currentGameState.SessionData.LastSector3Time < currentGameState.SessionData.PlayerBestSector3Time)) { currentGameState.SessionData.PlayerBestSector3Time = currentGameState.SessionData.LastSector3Time; } if (shared.mLastLapTime > 0 && (currentGameState.SessionData.PlayerLapTimeSessionBest == -1 || shared.mLastLapTime <= currentGameState.SessionData.PlayerLapTimeSessionBest)) { currentGameState.SessionData.PlayerBestLapSector1Time = currentGameState.SessionData.LastSector1Time; currentGameState.SessionData.PlayerBestLapSector2Time = currentGameState.SessionData.LastSector2Time; currentGameState.SessionData.PlayerBestLapSector3Time = currentGameState.SessionData.LastSector3Time; } } else if (currentGameState.SessionData.SectorNumber == 2) { currentGameState.SessionData.SessionTimesAtEndOfSectors[1] = currentGameState.SessionData.SessionRunningTime; currentGameState.SessionData.LastSector1Time = shared.mCurrentSector1Time; if (currentGameState.SessionData.LastSector1Time > 0 && (currentGameState.SessionData.PlayerBestSector1Time == -1 || currentGameState.SessionData.LastSector1Time < currentGameState.SessionData.PlayerBestSector1Time)) { currentGameState.SessionData.PlayerBestSector1Time = currentGameState.SessionData.LastSector1Time; } } if (currentGameState.SessionData.SectorNumber == 3) { currentGameState.SessionData.SessionTimesAtEndOfSectors[2] = currentGameState.SessionData.SessionRunningTime; currentGameState.SessionData.LastSector2Time = shared.mCurrentSector2Time; if (currentGameState.SessionData.LastSector2Time > 0 && (currentGameState.SessionData.PlayerBestSector2Time == -1 || currentGameState.SessionData.LastSector2Time < currentGameState.SessionData.PlayerBestSector2Time)) { currentGameState.SessionData.PlayerBestSector2Time = currentGameState.SessionData.LastSector2Time; } } } currentGameState.SessionData.Flag = mapToFlagEnum(shared.mHighestFlagColour); currentGameState.SessionData.NumCars = shared.mNumParticipants; currentGameState.SessionData.CurrentLapIsValid = !shared.mLapInvalidated; currentGameState.SessionData.IsNewLap = previousGameState == null || currentGameState.SessionData.CompletedLaps == previousGameState.SessionData.CompletedLaps + 1 || ((shared.mSessionState == (int)eSessionState.SESSION_PRACTICE || shared.mSessionState == (int)eSessionState.SESSION_QUALIFY || shared.mSessionState == (int)eSessionState.SESSION_TEST || shared.mSessionState == (int)eSessionState.SESSION_TIME_ATTACK) && previousGameState.SessionData.LapTimeCurrent == -1 && shared.mCurrentTime > 0); currentGameState.SessionData.IsRacingSameCarBehind = previousGameState != null && previousGameState.getOpponentKeyBehind(false) == currentGameState.getOpponentKeyBehind(false); currentGameState.SessionData.IsRacingSameCarInFront = previousGameState != null && previousGameState.getOpponentKeyInFront(false) == currentGameState.getOpponentKeyInFront(false); if (!currentGameState.SessionData.IsRacingSameCarInFront) { currentGameState.SessionData.GameTimeAtLastPositionFrontChange = currentGameState.SessionData.SessionRunningTime; } if (!currentGameState.SessionData.IsRacingSameCarBehind) { currentGameState.SessionData.GameTimeAtLastPositionBehindChange = currentGameState.SessionData.SessionRunningTime; } currentGameState.SessionData.LapTimeCurrent = shared.mCurrentTime; currentGameState.SessionData.TimeDeltaBehind = shared.mSplitTimeBehind; currentGameState.SessionData.TimeDeltaFront = shared.mSplitTimeAhead; // NOTE: the shared.mSessionFastestLapTime is JUST FOR THE PLAYER so the code below is not going to work: // currentGameState.SessionData.SessionFastestLapTimeFromGame = shared.mSessionFastestLapTime; // currentGameState.SessionData.SessionFastestLapTimeFromGamePlayerClass = shared.mSessionFastestLapTime; for (int i = 0; i < shared.mParticipantData.Length; i++) { if (i != playerDataIndex) { pCarsAPIParticipantStruct participantStruct = shared.mParticipantData[i]; if (participantStruct.mName != null && currentGameState.OpponentData.ContainsKey(participantStruct.mName)) { OpponentData currentOpponentData = currentGameState.OpponentData[participantStruct.mName]; if (currentOpponentData.IsActive && participantStruct.mIsActive) { if (previousGameState != null) { int previousOpponentSectorNumber = 1; int previousOpponentCompletedLaps = 0; int previousOpponentPosition = 0; Boolean previousOpponentIsEnteringPits = false; Boolean previousOpponentIsExitingPits = false; float[] previousOpponentWorldPosition = new float[] { 0, 0, 0 }; float previousOpponentSpeed = 0; OpponentData previousOpponentData = null; if (previousGameState.OpponentData.ContainsKey(participantStruct.mName)) { previousOpponentData = previousGameState.OpponentData[participantStruct.mName]; previousOpponentSectorNumber = previousOpponentData.CurrentSectorNumber; previousOpponentCompletedLaps = previousOpponentData.CompletedLaps; previousOpponentPosition = previousOpponentData.Position; previousOpponentIsEnteringPits = previousOpponentData.isEnteringPits(); previousOpponentIsExitingPits = previousOpponentData.isExitingPits(); previousOpponentWorldPosition = previousOpponentData.WorldPosition; previousOpponentSpeed = previousOpponentData.Speed; } int currentOpponentRacePosition = (int)participantStruct.mRacePosition; int currentOpponentLapsCompleted = (int)participantStruct.mLapsCompleted; int currentOpponentSector = (int)participantStruct.mCurrentSector; if (currentOpponentSector == 0) { currentOpponentSector = previousOpponentSectorNumber; } float currentOpponentLapDistance = participantStruct.mCurrentLapDistance; if (currentOpponentRacePosition == 1 && (currentGameState.SessionData.SessionNumberOfLaps > 0 && currentGameState.SessionData.SessionNumberOfLaps == currentOpponentLapsCompleted) || (currentGameState.SessionData.SessionRunTime > 0 && currentGameState.SessionData.SessionTimeRemaining < 1 && previousOpponentCompletedLaps < currentOpponentLapsCompleted)) { currentGameState.SessionData.LeaderHasFinishedRace = true; } if (currentOpponentRacePosition == 1 && previousOpponentPosition > 1) { currentGameState.SessionData.HasLeadChanged = true; } int opponentPositionAtSector3 = previousOpponentPosition; Boolean isEnteringPits = false; Boolean isLeavingPits = false; if (attemptPitDetection) { if (previousOpponentData != null && currentGameState.SessionData.SessionRunningTime > 30) { if (currentOpponentSector == 3) { if (previousOpponentSectorNumber == 2) { opponentPositionAtSector3 = currentOpponentRacePosition; } else if (!previousOpponentIsEnteringPits) { isEnteringPits = currentGameState.SessionData.TrackDefinition != null && currentGameState.SessionData.TrackDefinition.isAtPitEntry(participantStruct.mWorldPosition[0], participantStruct.mWorldPosition[2]); } else { isEnteringPits = previousOpponentIsEnteringPits; } } else if (currentOpponentSector == 1 && !previousOpponentIsExitingPits) { isLeavingPits = currentGameState.SessionData.TrackDefinition != null && currentGameState.SessionData.TrackDefinition.isAtPitExit(participantStruct.mWorldPosition[0], participantStruct.mWorldPosition[2]); } } if (isEnteringPits && !previousOpponentIsEnteringPits) { if (opponentPositionAtSector3 == 1) { Console.WriteLine("leader pitting, pos at sector 3 = " + opponentPositionAtSector3 + " current pos = " + currentOpponentRacePosition); currentGameState.PitData.LeaderIsPitting = true; currentGameState.PitData.OpponentForLeaderPitting = currentOpponentData; } if (currentGameState.SessionData.Position > 2 && opponentPositionAtSector3 == currentGameState.SessionData.Position - 1) { Console.WriteLine("car in front pitting, pos at sector 3 = " + opponentPositionAtSector3 + " current pos = " + currentOpponentRacePosition); currentGameState.PitData.CarInFrontIsPitting = true; currentGameState.PitData.OpponentForCarAheadPitting = currentOpponentData; } if (!currentGameState.isLast() && opponentPositionAtSector3 == currentGameState.SessionData.Position + 1) { Console.WriteLine("car behind pitting, pos at sector 3 = " + opponentPositionAtSector3 + " current pos = " + currentOpponentRacePosition); currentGameState.PitData.CarBehindIsPitting = true; currentGameState.PitData.OpponentForCarBehindPitting = currentOpponentData; } } } float secondsSinceLastUpdate = (float)new TimeSpan(currentGameState.Ticks - previousGameState.Ticks).TotalSeconds; upateOpponentData(currentOpponentData, currentOpponentRacePosition, currentOpponentLapsCompleted, currentOpponentSector, isEnteringPits || isLeavingPits, currentGameState.SessionData.SessionRunningTime, secondsSinceLastUpdate, new float[] { participantStruct.mWorldPosition[0], participantStruct.mWorldPosition[2] }, previousOpponentWorldPosition, previousOpponentSpeed, shared.mWorldFastestLapTime, participantStruct.mCurrentLapDistance, shared.mRainDensity == 1, shared.mAmbientTemperature, shared.mTrackTemperature); if (currentOpponentData.IsNewLap && currentOpponentData.CurrentBestLapTime > 0) { // the car class is always Unknown for PCars - it's not in the opponent data if (currentGameState.SessionData.OpponentsLapTimeSessionBestOverall == -1 || currentOpponentData.CurrentBestLapTime < currentGameState.SessionData.OpponentsLapTimeSessionBestOverall) { currentGameState.SessionData.OpponentsLapTimeSessionBestOverall = currentOpponentData.CurrentBestLapTime; currentGameState.SessionData.OpponentsLapTimeSessionBestPlayerClass = currentOpponentData.CurrentBestLapTime; if (currentGameState.SessionData.OverallSessionBestLapTime == -1 || currentGameState.SessionData.OverallSessionBestLapTime > currentOpponentData.CurrentBestLapTime) { currentGameState.SessionData.OverallSessionBestLapTime = currentOpponentData.CurrentBestLapTime; currentGameState.SessionData.PlayerClassSessionBestLapTime = currentOpponentData.CurrentBestLapTime; } } } } } else { currentOpponentData.IsActive = false; } } else { if (participantStruct.mIsActive && participantStruct.mName != null && participantStruct.mName.Length > 0) { Console.WriteLine("Creating opponent for name " + participantStruct.mName); currentGameState.OpponentData.Add(participantStruct.mName, createOpponentData(participantStruct, true)); } } } } currentGameState.SessionData.LapTimePrevious = shared.mLastLapTime; if (currentGameState.SessionData.IsNewLap) { currentGameState.SessionData.PreviousLapWasValid = previousGameState != null && previousGameState.SessionData.CurrentLapIsValid; currentGameState.SessionData.formattedPlayerLapTimes.Add(TimeSpan.FromSeconds(shared.mLastLapTime).ToString(@"mm\:ss\.fff")); } else if (previousGameState != null) { currentGameState.SessionData.PreviousLapWasValid = previousGameState.SessionData.PreviousLapWasValid; } if (currentGameState.SessionData.IsNewLap && currentGameState.SessionData.PreviousLapWasValid && currentGameState.SessionData.LapTimePrevious > 0) { if (currentGameState.SessionData.PlayerLapTimeSessionBest == -1 || currentGameState.SessionData.LapTimePrevious < currentGameState.SessionData.PlayerLapTimeSessionBest) { currentGameState.SessionData.PlayerLapTimeSessionBest = currentGameState.SessionData.LapTimePrevious; if (currentGameState.SessionData.OverallSessionBestLapTime == -1 || currentGameState.SessionData.LapTimePrevious < currentGameState.SessionData.OverallSessionBestLapTime) { currentGameState.SessionData.OverallSessionBestLapTime = currentGameState.SessionData.LapTimePrevious; } if (currentGameState.SessionData.PlayerClassSessionBestLapTime == -1 || currentGameState.SessionData.LapTimePrevious < currentGameState.SessionData.PlayerClassSessionBestLapTime) { currentGameState.SessionData.PlayerClassSessionBestLapTime = currentGameState.SessionData.LapTimePrevious; } } } currentGameState.PitData.InPitlane = shared.mPitMode == (int)ePitMode.PIT_MODE_DRIVING_INTO_PITS || shared.mPitMode == (int)ePitMode.PIT_MODE_IN_PIT || shared.mPitMode == (int)ePitMode.PIT_MODE_DRIVING_OUT_OF_PITS || shared.mPitMode == (int)ePitMode.PIT_MODE_IN_GARAGE; if (currentGameState.PitData.InPitlane) { // should we just use the sector number to check this? if (shared.mPitMode == (int)ePitMode.PIT_MODE_DRIVING_INTO_PITS) { currentGameState.PitData.OnInLap = true; currentGameState.PitData.OnOutLap = false; } else if (shared.mPitMode == (int)ePitMode.PIT_MODE_DRIVING_OUT_OF_PITS || shared.mPitMode == (int)ePitMode.PIT_MODE_IN_GARAGE) { currentGameState.PitData.OnInLap = false; currentGameState.PitData.OnOutLap = true; } } else if (currentGameState.SessionData.IsNewLap) { currentGameState.PitData.OnInLap = false; currentGameState.PitData.OnOutLap = false; } currentGameState.PitData.IsAtPitExit = previousGameState != null && currentGameState.PitData.OnOutLap && previousGameState.PitData.InPitlane && !currentGameState.PitData.InPitlane; currentGameState.PitData.HasRequestedPitStop = shared.mPitSchedule == (int)ePitSchedule.PIT_SCHEDULE_STANDARD; if (previousGameState != null && previousGameState.PitData.HasRequestedPitStop) { Console.WriteLine("Has requested pitstop"); } if (currentGameState.SessionData.SessionType == SessionType.Race && shared.mEnforcedPitStopLap > 0) { currentGameState.PitData.HasMandatoryPitStop = true; currentGameState.PitData.PitWindowStart = (int) shared.mEnforcedPitStopLap; currentGameState.PitData.PitWindow = mapToPitWindow(currentGameState, shared.mPitSchedule, shared.mPitMode); currentGameState.PitData.IsMakingMandatoryPitStop = (currentGameState.PitData.PitWindow == PitWindow.Open || currentGameState.PitData.PitWindow == PitWindow.StopInProgress) && (currentGameState.PitData.OnInLap || currentGameState.PitData.OnOutLap); } currentGameState.CarDamageData.DamageEnabled = true; // no way to tell if it's disabled from the shared memory currentGameState.CarDamageData.OverallAeroDamage = mapToAeroDamageLevel(shared.mAeroDamage); currentGameState.CarDamageData.OverallEngineDamage = mapToEngineDamageLevel(shared.mEngineDamage); currentGameState.CarDamageData.OverallTransmissionDamage = DamageLevel.NONE; currentGameState.CarDamageData.SuspensionDamageStatus = CornerData.getCornerData(suspensionDamageThresholds, shared.mSuspensionDamage[0], shared.mSuspensionDamage[1], shared.mSuspensionDamage[2], shared.mSuspensionDamage[3]); currentGameState.CarDamageData.BrakeDamageStatus = CornerData.getCornerData(brakeDamageThresholds, shared.mBrakeDamage[0], shared.mBrakeDamage[1], shared.mBrakeDamage[2], shared.mBrakeDamage[3]); currentGameState.EngineData.EngineOilPressure = shared.mOilPressureKPa; // todo: units conversion currentGameState.EngineData.EngineOilTemp = shared.mOilTempCelsius; currentGameState.EngineData.EngineWaterTemp = shared.mWaterTempCelsius; currentGameState.EngineData.EngineRpm = shared.mRPM; currentGameState.EngineData.MaxEngineRpm = shared.mMaxRPM; currentGameState.EngineData.MinutesIntoSessionBeforeMonitoring = 2; currentGameState.FuelData.FuelCapacity = shared.mFuelCapacity; currentGameState.FuelData.FuelLeft = currentGameState.FuelData.FuelCapacity * shared.mFuelLevel; currentGameState.FuelData.FuelPressure = shared.mFuelPressureKPa; currentGameState.FuelData.FuelUseActive = true; // no way to tell if it's disabled currentGameState.PenaltiesData.HasDriveThrough = shared.mPitSchedule == (int)ePitSchedule.PIT_SCHEDULE_DRIVE_THROUGH; currentGameState.PenaltiesData.HasStopAndGo = shared.mPitSchedule == (int)ePitSchedule.PIT_SCHEDULE_STOP_GO; currentGameState.PositionAndMotionData.CarSpeed = shared.mSpeed; //------------------------ Tyre data ----------------------- currentGameState.TyreData.HasMatchedTyreTypes = true; currentGameState.TyreData.TireWearActive = true; currentGameState.TyreData.LeftFrontAttached = (shared.mTyreFlags[0] & 1) == 1; currentGameState.TyreData.RightFrontAttached = (shared.mTyreFlags[1] & 1) == 1; currentGameState.TyreData.LeftRearAttached = (shared.mTyreFlags[2] & 1) == 1; currentGameState.TyreData.RightRearAttached = (shared.mTyreFlags[3] & 1) == 1; currentGameState.TyreData.FrontLeft_CenterTemp = shared.mTyreTreadTemp[0] - 273; currentGameState.TyreData.FrontLeft_LeftTemp = shared.mTyreTreadTemp[0] - 273; currentGameState.TyreData.FrontLeft_RightTemp = shared.mTyreTreadTemp[0] - 273; currentGameState.TyreData.FrontLeftTyreType = defaultTyreTypeForPlayersCar; currentGameState.TyreData.FrontLeftPressure = -1; // not in the block currentGameState.TyreData.FrontLeftPercentWear = Math.Min(100, shared.mTyreWear[0] * 100 / wornOutTyreWearLevel); if (currentGameState.SessionData.IsNewLap) { currentGameState.TyreData.PeakFrontLeftTemperatureForLap = currentGameState.TyreData.FrontLeft_CenterTemp; } else if (previousGameState == null || currentGameState.TyreData.FrontLeft_CenterTemp > previousGameState.TyreData.PeakFrontLeftTemperatureForLap) { currentGameState.TyreData.PeakFrontLeftTemperatureForLap = currentGameState.TyreData.FrontLeft_CenterTemp; } currentGameState.TyreData.FrontRight_CenterTemp = shared.mTyreTreadTemp[1] - 273; currentGameState.TyreData.FrontRight_LeftTemp = shared.mTyreTreadTemp[1] - 273; currentGameState.TyreData.FrontRight_RightTemp = shared.mTyreTreadTemp[1] - 273; currentGameState.TyreData.FrontRightTyreType = defaultTyreTypeForPlayersCar; currentGameState.TyreData.FrontRightPressure = -1; // not in the block currentGameState.TyreData.FrontRightPercentWear = Math.Min(100, shared.mTyreWear[1] * 100 / wornOutTyreWearLevel); if (currentGameState.SessionData.IsNewLap) { currentGameState.TyreData.PeakFrontRightTemperatureForLap = currentGameState.TyreData.FrontRight_CenterTemp; } else if (previousGameState == null || currentGameState.TyreData.FrontRight_CenterTemp > previousGameState.TyreData.PeakFrontRightTemperatureForLap) { currentGameState.TyreData.PeakFrontRightTemperatureForLap = currentGameState.TyreData.FrontRight_CenterTemp; } currentGameState.TyreData.RearLeft_CenterTemp = shared.mTyreTreadTemp[2] - 273; currentGameState.TyreData.RearLeft_LeftTemp = shared.mTyreTreadTemp[2] - 273; currentGameState.TyreData.RearLeft_RightTemp = shared.mTyreTreadTemp[2] - 273; currentGameState.TyreData.RearLeftTyreType = defaultTyreTypeForPlayersCar; currentGameState.TyreData.RearLeftPressure = -1; // not in the block currentGameState.TyreData.RearLeftPercentWear = Math.Min(100, shared.mTyreWear[2] * 100 / wornOutTyreWearLevel); if (currentGameState.SessionData.IsNewLap) { currentGameState.TyreData.PeakRearLeftTemperatureForLap = currentGameState.TyreData.RearLeft_CenterTemp; } else if (previousGameState == null || currentGameState.TyreData.RearLeft_CenterTemp > previousGameState.TyreData.PeakRearLeftTemperatureForLap) { currentGameState.TyreData.PeakRearLeftTemperatureForLap = currentGameState.TyreData.RearLeft_CenterTemp; } currentGameState.TyreData.RearRight_CenterTemp = shared.mTyreTreadTemp[3] - 273; currentGameState.TyreData.RearRight_LeftTemp = shared.mTyreTreadTemp[3] - 273; currentGameState.TyreData.RearRight_RightTemp = shared.mTyreTreadTemp[3] - 273; currentGameState.TyreData.RearRightTyreType = defaultTyreTypeForPlayersCar; currentGameState.TyreData.RearRightPressure = -1; // not in the block currentGameState.TyreData.RearRightPercentWear = Math.Min(100, shared.mTyreWear[3] * 100 / wornOutTyreWearLevel); if (currentGameState.SessionData.IsNewLap) { currentGameState.TyreData.PeakRearRightTemperatureForLap = currentGameState.TyreData.RearRight_CenterTemp; } else if (previousGameState == null || currentGameState.TyreData.RearRight_CenterTemp > previousGameState.TyreData.PeakRearRightTemperatureForLap) { currentGameState.TyreData.PeakRearRightTemperatureForLap = currentGameState.TyreData.RearRight_CenterTemp; } currentGameState.TyreData.TyreConditionStatus = CornerData.getCornerData(tyreWearThresholds, currentGameState.TyreData.FrontLeftPercentWear, currentGameState.TyreData.FrontRightPercentWear, currentGameState.TyreData.RearLeftPercentWear, currentGameState.TyreData.RearRightPercentWear); currentGameState.TyreData.TyreTempStatus = CornerData.getCornerData(CarData.tyreTempThresholds[defaultTyreTypeForPlayersCar], currentGameState.TyreData.PeakFrontLeftTemperatureForLap, currentGameState.TyreData.PeakFrontRightTemperatureForLap, currentGameState.TyreData.PeakRearLeftTemperatureForLap, currentGameState.TyreData.PeakRearRightTemperatureForLap); currentGameState.TyreData.BrakeTempStatus = CornerData.getCornerData(brakeTempThresholdsForPlayersCar, shared.mBrakeTempCelsius[0], shared.mBrakeTempCelsius[1], shared.mBrakeTempCelsius[2], shared.mBrakeTempCelsius[3]); currentGameState.TyreData.LeftFrontBrakeTemp = shared.mBrakeTempCelsius[0]; currentGameState.TyreData.RightFrontBrakeTemp = shared.mBrakeTempCelsius[1]; currentGameState.TyreData.LeftRearBrakeTemp = shared.mBrakeTempCelsius[2]; currentGameState.TyreData.RightRearBrakeTemp = shared.mBrakeTempCelsius[0]; // improvised cut track warnings... if (incrementCutTrackCountWhenLeavingRacingSurface) { currentGameState.PenaltiesData.IsOffRacingSurface = !racingSurfaces.Contains(shared.mTerrain[0]) && !racingSurfaces.Contains(shared.mTerrain[1]) && !racingSurfaces.Contains(shared.mTerrain[2]) && !racingSurfaces.Contains(shared.mTerrain[3]); if (previousGameState != null && previousGameState.PenaltiesData.IsOffRacingSurface && currentGameState.PenaltiesData.IsOffRacingSurface) { currentGameState.PenaltiesData.CutTrackWarnings = previousGameState.PenaltiesData.CutTrackWarnings + 1; } } if (!currentGameState.PitData.OnOutLap && previousGameState != null && previousGameState.SessionData.CurrentLapIsValid && !currentGameState.SessionData.CurrentLapIsValid && !(shared.mSessionState == (int)eSessionState.SESSION_RACE && shared.mRaceState == (int)eRaceState.RACESTATE_NOT_STARTED)) { currentGameState.PenaltiesData.CutTrackWarnings = previousGameState.PenaltiesData.CutTrackWarnings + 1; } // Tyre slip speed seems to peak at about 30 with big lock or wheelspin (in Sauber Merc). It's noisy as hell and is frequently bouncing around // in single figures, with the noise varying between cars. // tyreRPS is much cleaner but we don't know the diameter of the tyre so can't compare it (accurately) to the car's speed if (shared.mSpeed > 7) { float minRotatingSpeed = 2 * (float)Math.PI * shared.mSpeed / currentGameState.carClass.maxTyreCircumference; // I think the tyreRPS is actually radians per second... currentGameState.TyreData.LeftFrontIsLocked = Math.Abs(shared.mTyreRPS[0]) < minRotatingSpeed; currentGameState.TyreData.RightFrontIsLocked = Math.Abs(shared.mTyreRPS[1]) < minRotatingSpeed; currentGameState.TyreData.LeftRearIsLocked = Math.Abs(shared.mTyreRPS[2]) < minRotatingSpeed; currentGameState.TyreData.RightRearIsLocked = Math.Abs(shared.mTyreRPS[3]) < minRotatingSpeed; float maxRotatingSpeed = 2 * (float)Math.PI * shared.mSpeed / currentGameState.carClass.minTyreCircumference; currentGameState.TyreData.LeftFrontIsSpinning = Math.Abs(shared.mTyreRPS[0]) > maxRotatingSpeed; currentGameState.TyreData.RightFrontIsSpinning = Math.Abs(shared.mTyreRPS[1]) > maxRotatingSpeed; currentGameState.TyreData.LeftRearIsSpinning = Math.Abs(shared.mTyreRPS[2]) > maxRotatingSpeed; currentGameState.TyreData.RightRearIsSpinning = Math.Abs(shared.mTyreRPS[3]) > maxRotatingSpeed; } if (currentGameState.Conditions.timeOfMostRecentSample.Add(ConditionsMonitor.ConditionsSampleFrequency) < currentGameState.Now) { currentGameState.Conditions.addSample(currentGameState.Now, currentGameState.SessionData.CompletedLaps, currentGameState.SessionData.SectorNumber, shared.mAmbientTemperature, shared.mTrackTemperature, shared.mRainDensity, shared.mWindSpeed, shared.mWindDirectionX, shared.mWindDirectionY, shared.mCloudBrightness); } return currentGameState; }
override protected void triggerInternal(GameStateData previousGameState, GameStateData currentGameState) { if (currentGameState.SessionData.SessionType == SessionType.Race && currentGameState.PitData.HasMandatoryPitStop && currentGameState.SessionData.SessionPhase == SessionPhase.Green) { if (!pitDataInitialised) { mandatoryStopCompleted = false; mandatoryStopBoxThisLap = false; mandatoryStopMissed = false; Console.WriteLine("pit start = " + currentGameState.PitData.PitWindowStart + ", pit end = " + currentGameState.PitData.PitWindowEnd); hasMandatoryPitStop = currentGameState.PitData.HasMandatoryPitStop; hasMandatoryTyreChange = currentGameState.PitData.HasMandatoryTyreChange; mandatoryTyreChangeTyreType = currentGameState.PitData.MandatoryTyreChangeRequiredTyreType; maxDistanceOnCurrentTyre = currentGameState.PitData.MaxPermittedDistanceOnCurrentTyre; minDistanceOnCurrentTyre = currentGameState.PitData.MinPermittedDistanceOnCurrentTyre; if (currentGameState.SessionData.SessionNumberOfLaps > 0) { pitWindowOpenLap = currentGameState.PitData.PitWindowStart; pitWindowClosedLap = currentGameState.PitData.PitWindowEnd; playPitThisLap = true; } else if (currentGameState.SessionData.SessionTimeRemaining > 0) { pitWindowOpenTime = currentGameState.PitData.PitWindowStart; pitWindowClosedTime = currentGameState.PitData.PitWindowEnd; if (pitWindowOpenTime > 0) { play2minOpenWarning = pitWindowOpenTime > 2; play1minOpenWarning = pitWindowOpenTime > 1; playOpenNow = true; } if (pitWindowClosedTime > 0) { play2minCloseWarning = pitWindowClosedTime > 2; play1minCloseWarning = pitWindowClosedTime > 1; playClosedNow = true; playPitThisLap = true; } } else { Console.WriteLine("Error getting pit data"); } pitDataInitialised = true; } else if (currentGameState.PitData.IsMakingMandatoryPitStop) { playPitThisLap = false; playBoxNowMessage = false; mandatoryStopCompleted = true; mandatoryStopBoxThisLap = false; mandatoryStopMissed = false; } else { if (currentGameState.SessionData.IsNewLap && currentGameState.SessionData.CompletedLaps > 0 && currentGameState.SessionData.SessionNumberOfLaps > 0) { if (currentGameState.PitData.PitWindow != PitWindow.StopInProgress && currentGameState.PitData.PitWindow != PitWindow.Completed) { if (maxDistanceOnCurrentTyre > 0 && currentGameState.SessionData.CompletedLaps == maxDistanceOnCurrentTyre && playPitThisLap) { playBoxNowMessage = true; playPitThisLap = false; mandatoryStopBoxThisLap = true; if (mandatoryTyreChangeTyreType == TyreType.Prime) { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsFitPrimesThisLap, random.Next(0, 10), this)); } else if (mandatoryTyreChangeTyreType == TyreType.Option) { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsFitOptionsThisLap, random.Next(0, 20), this)); } else { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitThisLap, random.Next(0, 20), this)); } } else if (minDistanceOnCurrentTyre > 0 && currentGameState.SessionData.CompletedLaps == minDistanceOnCurrentTyre) { if (mandatoryTyreChangeTyreType == TyreType.Prime) { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsCanNowFitPrimes, random.Next(0, 20), this)); } else if (mandatoryTyreChangeTyreType == TyreType.Option) { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsCanNowFitOptions, random.Next(0, 20), this)); } } } if (pitWindowOpenLap > 0 && currentGameState.SessionData.CompletedLaps == pitWindowOpenLap - 1) { // note this is a 'pit window opens at the end of this lap' message, // so we play it 1 lap before the window opens audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitWindowOpening, random.Next(0, 20), this)); } else if (pitWindowOpenLap > 0 && currentGameState.SessionData.CompletedLaps == pitWindowOpenLap) { audioPlayer.setBackgroundSound(AudioPlayer.dtmPitWindowOpenBackground); audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitWindowOpen, 0, this)); } else if (pitWindowClosedLap > 0 && currentGameState.SessionData.CompletedLaps == pitWindowClosedLap - 1) { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitWindowClosing, random.Next(0, 20), this)); if (currentGameState.PitData.PitWindow != PitWindow.Completed && currentGameState.PitData.PitWindow != PitWindow.StopInProgress) { playBoxNowMessage = true; if (mandatoryTyreChangeTyreType == TyreType.Prime) { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsFitPrimesThisLap, random.Next(0, 10), this)); } else if (mandatoryTyreChangeTyreType == TyreType.Option) { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsFitOptionsThisLap, random.Next(0, 10), this)); } else { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitThisLap, random.Next(0, 10), this)); } } } else if (pitWindowClosedLap > 0 && currentGameState.SessionData.CompletedLaps == pitWindowClosedLap) { mandatoryStopBoxThisLap = false; if (currentGameState.PitData.PitWindow != PitWindow.Completed) { mandatoryStopMissed = true; } audioPlayer.setBackgroundSound(AudioPlayer.dtmPitWindowClosedBackground); audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitWindowClosed, 0, this)); } } else if (currentGameState.SessionData.IsNewLap && currentGameState.SessionData.CompletedLaps > 0 && currentGameState.SessionData.SessionTimeRemaining > 0) { if (pitWindowClosedTime > 0 && currentGameState.PitData.PitWindow != PitWindow.StopInProgress && currentGameState.PitData.PitWindow != PitWindow.Completed && currentGameState.SessionData.SessionTotalRunTime - currentGameState.SessionData.SessionTimeRemaining > pitWindowOpenTime * 60 && currentGameState.SessionData.SessionTotalRunTime - currentGameState.SessionData.SessionTimeRemaining < pitWindowClosedTime * 60) { double timeLeftToPit = pitWindowClosedTime * 60 - (currentGameState.SessionData.SessionTotalRunTime - currentGameState.SessionData.SessionTimeRemaining); if (playPitThisLap && currentGameState.SessionData.PlayerLapTimeSessionBest + 10 > timeLeftToPit) { // oh dear, we might have missed the pit window. playBoxNowMessage = true; playPitThisLap = false; mandatoryStopBoxThisLap = true; audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitThisLapTooLate, 0, this)); } else if (playPitThisLap && currentGameState.SessionData.PlayerLapTimeSessionBest + 10 < timeLeftToPit && (currentGameState.SessionData.PlayerLapTimeSessionBest * 2) + 10 > timeLeftToPit) { // we probably won't make it round twice - pit at the end of this lap playBoxNowMessage = true; playPitThisLap = false; mandatoryStopBoxThisLap = true; if (mandatoryTyreChangeTyreType == TyreType.Prime) { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsFitPrimesThisLap, random.Next(0, 20), this)); } else if (mandatoryTyreChangeTyreType == TyreType.Option) { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsFitOptionsThisLap, random.Next(0, 20), this)); } else { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitThisLap, random.Next(0, 20), this)); } } } } if (playOpenNow && currentGameState.SessionData.SessionTimeRemaining > 0 && (currentGameState.SessionData.SessionTotalRunTime - currentGameState.SessionData.SessionTimeRemaining > (pitWindowOpenTime * 60) || currentGameState.PitData.PitWindow == PitWindow.Open)) { playOpenNow = false; play1minOpenWarning = false; play2minOpenWarning = false; audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitWindowOpen, 0, this)); } else if (play1minOpenWarning && currentGameState.SessionData.SessionTimeRemaining > 0 && currentGameState.SessionData.SessionTotalRunTime - currentGameState.SessionData.SessionTimeRemaining > ((pitWindowOpenTime - 1) * 60)) { play1minOpenWarning = false; play2minOpenWarning = false; audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitWindowOpen1Min, 0, this)); } else if (play2minOpenWarning && currentGameState.SessionData.SessionTimeRemaining > 0 && currentGameState.SessionData.SessionTotalRunTime - currentGameState.SessionData.SessionTimeRemaining > ((pitWindowOpenTime - 2) * 60)) { play2minOpenWarning = false; audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitWindowOpen2Min, 0, this)); } else if (pitWindowClosedTime > 0 && playClosedNow && currentGameState.SessionData.SessionTimeRemaining > 0 && currentGameState.SessionData.SessionTotalRunTime - currentGameState.SessionData.SessionTimeRemaining > (pitWindowClosedTime * 60)) { playClosedNow = false; playBoxNowMessage = false; play1minCloseWarning = false; play2minCloseWarning = false; playPitThisLap = false; mandatoryStopBoxThisLap = false; if (currentGameState.PitData.PitWindow != PitWindow.Completed) { mandatoryStopMissed = true; } audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitWindowClosed, 0, this)); } else if (pitWindowClosedTime > 0 && play1minCloseWarning && currentGameState.SessionData.SessionTimeRemaining > 0 && currentGameState.SessionData.SessionTotalRunTime - currentGameState.SessionData.SessionTimeRemaining > ((pitWindowClosedTime - 1) * 60)) { play1minCloseWarning = false; play2minCloseWarning = false; audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitWindowCloses1min, 0, this)); } else if (pitWindowClosedTime > 0 && play2minCloseWarning && currentGameState.SessionData.SessionTimeRemaining > 0 && currentGameState.SessionData.SessionTotalRunTime - currentGameState.SessionData.SessionTimeRemaining > ((pitWindowClosedTime - 2) * 60)) { play2minCloseWarning = false; audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitWindowCloses2min, 0, this)); } // for Automobilista, sector update lag time means sometimes we miss the pit entrance before this message plays if (playBoxNowMessage && currentGameState.SessionData.SectorNumber == 2 && CrewChief.gameDefinition.gameEnum == GameEnum.RF1) { playBoxNowMessage = false; // pit entry is right at sector 3 timing line, play message part way through sector 2 to give us time to pit int messageDelay = currentGameState.SessionData.PlayerBestSector2Time > 0 ? (int)(currentGameState.SessionData.PlayerBestSector2Time * 0.7) : 15; audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitNow, messageDelay, this)); } if (playBoxNowMessage && currentGameState.SessionData.SectorNumber == 3) { playBoxNowMessage = false; if (mandatoryTyreChangeTyreType == TyreType.Prime) { audioPlayer.playMessage(new QueuedMessage("box_now_for_primes", MessageContents(folderMandatoryPitStopsPitNow, folderMandatoryPitStopsPrimeTyres), 3, this)); } else if (mandatoryTyreChangeTyreType == TyreType.Option) { audioPlayer.playMessage(new QueuedMessage("box_now_for_options", MessageContents(folderMandatoryPitStopsPitNow, folderMandatoryPitStopsOptionTyres), 3, this)); } else { audioPlayer.playMessage(new QueuedMessage(folderMandatoryPitStopsPitNow, 3, this)); } } } } }
public override void clearState() { pitWindowOpenLap = 0; pitWindowClosedLap = 0; pitWindowOpenTime = 0; pitWindowClosedTime = 0; pitDataInitialised = false; playBoxNowMessage = false; play2minOpenWarning = false; play2minCloseWarning = false; play1minOpenWarning = false; play1minCloseWarning = false; playClosedNow = false; playOpenNow = false; playPitThisLap = false; mandatoryStopCompleted = false; mandatoryStopBoxThisLap = false; mandatoryStopMissed = false; mandatoryTyreChangeTyreType = TyreType.Unknown_Race; hasMandatoryPitStop = false; hasMandatoryTyreChange = false; hasMandatoryDriverChange = false; minDistanceOnCurrentTyre = -1; maxDistanceOnCurrentTyre = -1; }
protected override void triggerInternal(GameStateData previousGameState, GameStateData currentGameState) { if (currentGameState.SessionData.SessionType == SessionType.Race && currentGameState.PitData.HasMandatoryPitStop) { if (!pitDataInitialised) { mandatoryStopCompleted = false; mandatoryStopBoxThisLap = false; mandatoryStopMissed = false; Console.WriteLine("pit start = " + currentGameState.PitData.PitWindowStart + ", pit end = " + currentGameState.PitData.PitWindowEnd); hasMandatoryPitStop = currentGameState.PitData.HasMandatoryPitStop; hasMandatoryTyreChange = currentGameState.PitData.HasMandatoryTyreChange; hasMandatoryDriverChange = currentGameState.PitData.HasMandatoryDriverChange; mandatoryTyreChangeTyreType = currentGameState.PitData.MandatoryTyreChangeRequiredTyreType; maxDistanceOnCurrentTyre = currentGameState.PitData.MaxPermittedDistanceOnCurrentTyre; minDistanceOnCurrentTyre = currentGameState.PitData.MinPermittedDistanceOnCurrentTyre; if (currentGameState.SessionData.SessionNumberOfLaps > 0) { pitWindowOpenLap = currentGameState.PitData.PitWindowStart; pitWindowClosedLap = currentGameState.PitData.PitWindowEnd; playPitThisLap = true; } else if (currentGameState.SessionData.SessionTimeRemaining > 0) { pitWindowOpenTime = currentGameState.PitData.PitWindowStart; pitWindowClosedTime = currentGameState.PitData.PitWindowEnd; play2minOpenWarning = true; play1minOpenWarning = true; playOpenNow = true; play2minCloseWarning = true; play1minCloseWarning = true; playClosedNow = true; playPitThisLap = true; } else { Console.WriteLine("Error getting pit data"); } pitDataInitialised = true; } else if (currentGameState.PitData.IsMakingMandatoryPitStop) { playPitThisLap = false; playBoxNowMessage = false; mandatoryStopCompleted = true; mandatoryStopBoxThisLap = false; mandatoryStopMissed = false; } else { if (currentGameState.SessionData.IsNewLap && currentGameState.SessionData.CompletedLaps > 0 && currentGameState.SessionData.SessionNumberOfLaps > 0) { if (currentGameState.PitData.PitWindow != PitWindow.StopInProgress && currentGameState.PitData.PitWindow != PitWindow.Completed) { if (maxDistanceOnCurrentTyre > 0 && currentGameState.SessionData.CompletedLaps == maxDistanceOnCurrentTyre && playPitThisLap) { playBoxNowMessage = true; playPitThisLap = false; mandatoryStopBoxThisLap = true; if (mandatoryTyreChangeTyreType == TyreType.Prime) { audioPlayer.queueClip(new QueuedMessage(folderMandatoryPitStopsFitPrimesThisLap, random.Next(0, 10), this)); } else if (mandatoryTyreChangeTyreType == TyreType.Option) { audioPlayer.queueClip(new QueuedMessage(folderMandatoryPitStopsFitOptionsThisLap, random.Next(0, 20), this)); } else { audioPlayer.queueClip(new QueuedMessage(folderMandatoryPitStopsPitThisLap, random.Next(0, 20), this)); } } else if (minDistanceOnCurrentTyre > 0 && currentGameState.SessionData.CompletedLaps == minDistanceOnCurrentTyre) { if (mandatoryTyreChangeTyreType == TyreType.Prime) { audioPlayer.queueClip(new QueuedMessage(folderMandatoryPitStopsCanNowFitPrimes, random.Next(0, 20), this)); } else if (mandatoryTyreChangeTyreType == TyreType.Option) { audioPlayer.queueClip(new QueuedMessage(folderMandatoryPitStopsCanNowFitOptions, random.Next(0, 20), this)); } } } if (pitWindowOpenLap > 0 && currentGameState.SessionData.CompletedLaps == pitWindowOpenLap - 1) { // note this is a 'pit window opens at the end of this lap' message, // so we play it 1 lap before the window opens audioPlayer.queueClip(new QueuedMessage(folderMandatoryPitStopsPitWindowOpening, random.Next(0, 20), this)); } else if (pitWindowOpenLap > 0 && currentGameState.SessionData.CompletedLaps == pitWindowOpenLap) { audioPlayer.setBackgroundSound(AudioPlayer.dtmPitWindowOpenBackground); audioPlayer.queueClip(new QueuedMessage(folderMandatoryPitStopsPitWindowOpen, 0, this)); } else if (pitWindowClosedLap > 0 && currentGameState.SessionData.CompletedLaps == pitWindowClosedLap - 1) { audioPlayer.queueClip(new QueuedMessage(folderMandatoryPitStopsPitWindowClosing, random.Next(0, 20), this)); if (currentGameState.PitData.PitWindow != PitWindow.Completed && currentGameState.PitData.PitWindow != PitWindow.StopInProgress) { playBoxNowMessage = true; if (mandatoryTyreChangeTyreType == TyreType.Prime) { audioPlayer.queueClip(new QueuedMessage(folderMandatoryPitStopsFitPrimesThisLap, random.Next(0, 10), this)); } else if (mandatoryTyreChangeTyreType == TyreType.Option) { audioPlayer.queueClip(new QueuedMessage(folderMandatoryPitStopsFitOptionsThisLap, random.Next(0, 10), this)); } else { audioPlayer.queueClip(new QueuedMessage(folderMandatoryPitStopsPitThisLap, random.Next(0, 10), this)); } } } else if (pitWindowClosedLap > 0 && currentGameState.SessionData.CompletedLaps == pitWindowClosedLap) { mandatoryStopBoxThisLap = false; if (currentGameState.PitData.PitWindow != PitWindow.Completed) { mandatoryStopMissed = true; } audioPlayer.setBackgroundSound(AudioPlayer.dtmPitWindowClosedBackground); audioPlayer.queueClip(new QueuedMessage(folderMandatoryPitStopsPitWindowClosed, 0, this)); } } else if (currentGameState.SessionData.IsNewLap && currentGameState.SessionData.CompletedLaps > 0 && currentGameState.SessionData.SessionTimeRemaining > 0) { if (pitWindowClosedTime > 0 && currentGameState.PitData.PitWindow != PitWindow.StopInProgress && currentGameState.PitData.PitWindow != PitWindow.Completed && currentGameState.SessionData.SessionRunTime - currentGameState.SessionData.SessionTimeRemaining > pitWindowOpenTime * 60 && currentGameState.SessionData.SessionRunTime - currentGameState.SessionData.SessionTimeRemaining < pitWindowClosedTime * 60) { double timeLeftToPit = pitWindowClosedTime * 60 - (currentGameState.SessionData.SessionRunTime - currentGameState.SessionData.SessionTimeRemaining); if (playPitThisLap && currentGameState.SessionData.PlayerLapTimeSessionBest + 10 > timeLeftToPit) { // oh dear, we might have missed the pit window. playBoxNowMessage = true; playPitThisLap = false; mandatoryStopBoxThisLap = true; audioPlayer.queueClip(new QueuedMessage(folderMandatoryPitStopsPitThisLapTooLate, 0, this)); } else if (playPitThisLap && currentGameState.SessionData.PlayerLapTimeSessionBest + 10 < timeLeftToPit && (currentGameState.SessionData.PlayerLapTimeSessionBest * 2) + 10 > timeLeftToPit) { // we probably won't make it round twice - pit at the end of this lap playBoxNowMessage = true; playPitThisLap = false; mandatoryStopBoxThisLap = true; if (mandatoryTyreChangeTyreType == TyreType.Prime) { audioPlayer.queueClip(new QueuedMessage(folderMandatoryPitStopsFitPrimesThisLap, random.Next(0, 20), this)); } else if (mandatoryTyreChangeTyreType == TyreType.Option) { audioPlayer.queueClip(new QueuedMessage(folderMandatoryPitStopsFitOptionsThisLap, random.Next(0, 20), this)); } else { audioPlayer.queueClip(new QueuedMessage(folderMandatoryPitStopsPitThisLap, random.Next(0, 20), this)); } } } } if (playOpenNow && currentGameState.SessionData.SessionTimeRemaining > 0 && (currentGameState.SessionData.SessionRunTime - currentGameState.SessionData.SessionTimeRemaining > (pitWindowOpenTime * 60) || currentGameState.PitData.PitWindow == PitWindow.Open)) { playOpenNow = false; play1minOpenWarning = false; play2minOpenWarning = false; audioPlayer.queueClip(new QueuedMessage(folderMandatoryPitStopsPitWindowOpen, 0, this)); } else if (play1minOpenWarning && currentGameState.SessionData.SessionTimeRemaining > 0 && currentGameState.SessionData.SessionRunTime - currentGameState.SessionData.SessionTimeRemaining > ((pitWindowOpenTime - 1) * 60)) { play1minOpenWarning = false; play2minOpenWarning = false; audioPlayer.queueClip(new QueuedMessage(folderMandatoryPitStopsPitWindowOpen1Min, 0, this)); } else if (play2minOpenWarning && currentGameState.SessionData.SessionTimeRemaining > 0 && currentGameState.SessionData.SessionRunTime - currentGameState.SessionData.SessionTimeRemaining > ((pitWindowOpenTime - 2) * 60)) { play2minOpenWarning = false; audioPlayer.queueClip(new QueuedMessage(folderMandatoryPitStopsPitWindowOpen2Min, 0, this)); } else if (pitWindowClosedTime > 0 && playClosedNow && currentGameState.SessionData.SessionTimeRemaining > 0 && currentGameState.SessionData.SessionRunTime - currentGameState.SessionData.SessionTimeRemaining > (pitWindowClosedTime * 60)) { playClosedNow = false; playBoxNowMessage = false; play1minCloseWarning = false; play2minCloseWarning = false; playPitThisLap = false; mandatoryStopBoxThisLap = false; if (currentGameState.PitData.PitWindow != PitWindow.Completed) { mandatoryStopMissed = true; } audioPlayer.queueClip(new QueuedMessage(folderMandatoryPitStopsPitWindowClosed, 0, this)); } else if (pitWindowClosedTime > 0 && play1minCloseWarning && currentGameState.SessionData.SessionTimeRemaining > 0 && currentGameState.SessionData.SessionRunTime - currentGameState.SessionData.SessionTimeRemaining > ((pitWindowClosedTime - 1) * 60)) { play1minCloseWarning = false; play2minCloseWarning = false; audioPlayer.queueClip(new QueuedMessage(folderMandatoryPitStopsPitWindowCloses1min, 0, this)); } else if (pitWindowClosedTime > 0 && play2minCloseWarning && currentGameState.SessionData.SessionTimeRemaining > 0 && currentGameState.SessionData.SessionRunTime - currentGameState.SessionData.SessionTimeRemaining > ((pitWindowClosedTime - 2) * 60)) { play2minCloseWarning = false; audioPlayer.queueClip(new QueuedMessage(folderMandatoryPitStopsPitWindowCloses2min, 0, this)); } if (playBoxNowMessage && currentGameState.SessionData.SectorNumber == 3) { playBoxNowMessage = false; if (mandatoryTyreChangeTyreType == TyreType.Prime) { audioPlayer.queueClip(new QueuedMessage("box_now_for_primes", MessageContents(folderMandatoryPitStopsPitNow, folderMandatoryPitStopsPrimeTyres), 3, this)); } else if (mandatoryTyreChangeTyreType == TyreType.Option) { audioPlayer.queueClip(new QueuedMessage("box_now_for_options", MessageContents(folderMandatoryPitStopsPitNow, folderMandatoryPitStopsPrimeTyres), 3, this)); } else { audioPlayer.queueClip(new QueuedMessage(folderMandatoryPitStopsPitNow, 3, this)); } } } } }