Ejemplo n.º 1
0
        protected override void triggerInternal(GameStateData previousGameState, GameStateData currentGameState)
        {
            audioPlayer.queueClip(new QueuedMessage(folderTest, 0, this));
            testDriverNames();

            /*audioPlayer.queueClip(new QueuedMessage("conditionsAirAndTrackIncreasing1", MessageContents
                               (ConditionsMonitor.folderAirAndTrackTempIncreasing,
                               ConditionsMonitor.folderAirTempIsNow, QueuedMessage.folderNameNumbersStub + 26,
                               ConditionsMonitor.folderTrackTempIsNow, QueuedMessage.folderNameNumbersStub + 32, ConditionsMonitor.folderCelsius), 0, this));
            audioPlayer.queueClip(new QueuedMessage("Fuel/estimate", MessageContents(
                                        Fuel.folderWeEstimate, QueuedMessage.folderNameNumbersStub + 12, Fuel.folderMinutesRemaining), 0, this));
            audioPlayer.queueClip(new QueuedMessage("laptime", MessageContents(LapTimes.folderLapTimeIntro,
                TimeSpan.FromSeconds(60 + (random.NextDouble() * 60))), 0, this));
            audioPlayer.queueClip(new QueuedMessage("yesBoxAfter", MessageContents(MandatoryPitStops.folderMandatoryPitStopsYesStopAfter,
                QueuedMessage.folderNameNumbersStub + 10, MandatoryPitStops.folderMandatoryPitStopsMinutes), 0, null));
            audioPlayer.queueClip(new QueuedMessage("laps_on_current_tyres", MessageContents(TyreMonitor.folderLapsOnCurrentTyresIntro,
                QueuedMessage.folderNameNumbersStub + 5, TyreMonitor.folderLapsOnCurrentTyresOutro), 0, this));*/
        }
Ejemplo n.º 2
0
 public override bool isMessageStillValid(string eventSubType, GameStateData currentGameState, Dictionary<String, Object> validationData)
 {
     if (validationData != null && validationData.ContainsKey(validationDriverAheadKey)) {
         String expectedOpponentName = (String)validationData[validationDriverAheadKey];
         OpponentData opponentInFront = currentGameState.SessionData.Position > 1 ? currentGameState.getOpponentAtPosition(currentGameState.SessionData.Position - 1, false) : null;
         String actualOpponentName = opponentInFront == null ? null : opponentInFront.DriverRawName;
         if (actualOpponentName != expectedOpponentName)
         {
             if (actualOpponentName != null && expectedOpponentName != null)
             {
                 Console.WriteLine("new car in front message for opponent " + expectedOpponentName +
                     " no longer valid - driver in front is now " + actualOpponentName);
             }
             return false;
         }
     }
     return true;
 }
Ejemplo n.º 3
0
 protected override void triggerInternal(GameStateData previousGameState, GameStateData currentGameState)
 {
     if (currentGameState.SessionData.Flag == FlagEnum.BLACK)
     {
         if (currentGameState.Now > lastBlackFlagTime.Add(timeBetweenBlackFlagMessages))
         {
             lastBlackFlagTime = currentGameState.Now;
             audioPlayer.queueClip(new QueuedMessage(folderBlackFlag, 0, this));
         }
     }
     else if (!currentGameState.PitData.InPitlane && currentGameState.SessionData.Flag == FlagEnum.BLUE)
     {
         if (currentGameState.Now > lastBlueFlagTime.Add(timeBetweenBlueFlagMessages))
         {
             lastBlueFlagTime = currentGameState.Now;
             audioPlayer.queueClip(new QueuedMessage(folderBlueFlag, 0, this));
         }
     }
     else if (!currentGameState.PitData.InPitlane && currentGameState.SessionData.Flag == FlagEnum.YELLOW)
     {
         if (currentGameState.Now > lastYellowFlagTime.Add(timeBetweenYellowFlagMessages))
         {
             lastYellowFlagTime = currentGameState.Now;
             audioPlayer.queueClip(new QueuedMessage(folderYellowFlag, 0, this));
         }
     }
     else if (currentGameState.SessionData.Flag == FlagEnum.WHITE)
     {
         if (currentGameState.Now > lastWhiteFlagTime.Add(timeBetweenWhiteFlagMessages))
         {
             lastWhiteFlagTime = currentGameState.Now;
             audioPlayer.queueClip(new QueuedMessage(folderWhiteFlag, 0, this));
         }
     }
     else if (!currentGameState.PitData.InPitlane && currentGameState.SessionData.Flag == FlagEnum.DOUBLE_YELLOW)
     {
         if (currentGameState.Now > lastYellowFlagTime.Add(timeBetweenYellowFlagMessages))
         {
             lastYellowFlagTime = currentGameState.Now;
             audioPlayer.queueClip(new QueuedMessage(folderDoubleYellowFlag, 0, this));
         }
     }
 }
Ejemplo n.º 4
0
 public override bool isMessageStillValid(String eventSubType, GameStateData currentGameState, Dictionary<String, Object> validationData)
 {
     // when a new penalty is given we queue a 'three laps left to serve' message for 20 seconds in the future.
     // If, 20 seconds later, the player has started a new lap, this message is no longer valid so shouldn't be played
     if (eventSubType == folderThreeLapsToServe)
     {
         Console.WriteLine("checking penalty validity, pen lap = " + penaltyLap + ", completed =" + lapsCompleted);
         return hasOutstandingPenalty && lapsCompleted == penaltyLap && currentGameState.SessionData.SessionPhase != SessionPhase.Finished;
     }
     else if (eventSubType == folderCutTrackInRace)
     {
         return !hasOutstandingPenalty && currentGameState.SessionData.SessionPhase != SessionPhase.Finished;
     }
     else if(eventSubType == folderCutTrackPracticeOrQual || eventSubType == folderLapDeleted)
     {
         return currentGameState.SessionData.SessionPhase != SessionPhase.Finished;
     }
     else
     {
         return hasOutstandingPenalty && currentGameState.SessionData.SessionPhase != SessionPhase.Finished;
     }
 }
Ejemplo n.º 5
0
 protected override void triggerInternal(GameStateData previousGameState, GameStateData currentGameState)
 {
     Boolean checkPushToGain = currentGameState.SessionData.SessionRunningTime - currentGameState.SessionData.GameTimeAtLastPositionFrontChange < minTimeToBeInThisPosition;
     Boolean checkPushToHold = currentGameState.SessionData.SessionRunningTime - currentGameState.SessionData.GameTimeAtLastPositionBehindChange < minTimeToBeInThisPosition;
     if (currentGameState.SessionData.SessionType == SessionType.Race)
     {
         if ((checkPushToGain || checkPushToHold) && !playedNearEndTimePush && currentGameState.SessionData.SessionNumberOfLaps <= 0 &&
                 currentGameState.SessionData.SessionTimeRemaining < 4 * 60 && currentGameState.SessionData.SessionTimeRemaining > 2 * 60)
         {
             // estimate the number of remaining laps - be optimistic...
             int numLapsLeft = (int)Math.Ceiling((double)currentGameState.SessionData.SessionTimeRemaining / (double)currentGameState.SessionData.PlayerLapTimeSessionBest);
             if (currentGameState.carClass.carClassEnum == CarData.CarClassEnum.DTM_2015)
             {
                 numLapsLeft = numLapsLeft + 1;
             }
             playedNearEndTimePush = checkGaps(currentGameState, numLapsLeft, checkPushToGain, checkPushToHold);
         }
         else if ((checkPushToGain || checkPushToHold) && !playedNearEndLapsPush && currentGameState.SessionData.SessionNumberOfLaps > 0 &&
             currentGameState.SessionData.SessionNumberOfLaps - currentGameState.SessionData.CompletedLaps <= 4)
         {
             playedNearEndLapsPush = checkGaps(currentGameState, currentGameState.SessionData.SessionNumberOfLaps - currentGameState.SessionData.CompletedLaps, checkPushToGain, checkPushToHold);
         }
     }
     if (currentGameState.PitData.IsAtPitExit && currentGameState.PositionAndMotionData.CarSpeed > 5)
     {
         // we've just been handed control back after a pitstop
         if (isOpponentApproachingPitExit(currentGameState))
         {
             // we've exited into clean air
             audioPlayer.queueClip(new QueuedMessage(folderTrafficBehindExitingPits, 0, this));
         }
         else
         {
             audioPlayer.queueClip(new QueuedMessage(folderPushExitingPits, 0, this));
         }
     }
 }
Ejemplo n.º 6
0
 public Boolean isMessageStillValid(String eventSubType, GameStateData currentGameState)
 {
     return this.abstractEvent == null ||
         this.abstractEvent.isMessageStillValid(eventSubType, currentGameState, validationData);
 }
Ejemplo n.º 7
0
 private LastLapRating getLastLapRating(GameStateData currentGameState, float[] bestLapDataForOpponents)
 {
     if (currentGameState.SessionData.PreviousLapWasValid && currentGameState.SessionData.LapTimePrevious > 0)
     {
         float closeThreshold = currentGameState.SessionData.LapTimePrevious * goodLapPercent / 100;
         float matchingRacePaceThreshold = currentGameState.SessionData.LapTimePrevious * matchingRacePacePercent / 100;
         if (currentGameState.SessionData.OverallSessionBestLapTime == currentGameState.SessionData.LapTimePrevious)
         {
             return LastLapRating.BEST_OVERALL;
         }
         else if (currentGameState.SessionData.PlayerClassSessionBestLapTime == currentGameState.SessionData.LapTimePrevious)
         {
             return LastLapRating.BEST_IN_CLASS;
         }
         else if (currentGameState.SessionData.SessionType == SessionType.Race && bestLapDataForOpponents[0] > 0 && bestLapDataForOpponents[0] >= currentGameState.SessionData.LapTimePrevious)
         {
             return LastLapRating.SETTING_CURRENT_PACE;
         }
         else if (currentGameState.SessionData.SessionType == SessionType.Race && bestLapDataForOpponents[0] > 0 && bestLapDataForOpponents[0] > currentGameState.SessionData.LapTimePrevious - closeThreshold)
         {
             return LastLapRating.CLOSE_TO_CURRENT_PACE;
         }
         else if (currentGameState.SessionData.LapTimePrevious == currentGameState.SessionData.PlayerLapTimeSessionBest)
         {
             if (currentGameState.SessionData.OpponentsLapTimeSessionBestOverall > currentGameState.SessionData.LapTimePrevious - closeThreshold)
             {
                 return LastLapRating.PERSONAL_BEST_CLOSE_TO_OVERALL_LEADER;
             }
             else if (currentGameState.SessionData.OpponentsLapTimeSessionBestPlayerClass > currentGameState.SessionData.LapTimePrevious - closeThreshold)
             {
                 return LastLapRating.PERSONAL_BEST_CLOSE_TO_CLASS_LEADER;
             }
             else if (currentGameState.SessionData.OpponentsLapTimeSessionBestPlayerClass > 0 || currentGameState.SessionData.OpponentsLapTimeSessionBestOverall > 0)
             {
                 return LastLapRating.PERSONAL_BEST_STILL_SLOW;
             }
         }
         else if (currentGameState.SessionData.OpponentsLapTimeSessionBestOverall >= currentGameState.SessionData.LapTimePrevious - closeThreshold)
         {
             return LastLapRating.CLOSE_TO_OVERALL_LEADER;
         }
         else if (currentGameState.SessionData.OpponentsLapTimeSessionBestPlayerClass >= currentGameState.SessionData.LapTimePrevious - closeThreshold)
         {
             return LastLapRating.CLOSE_TO_CLASS_LEADER;
         }
         else if (currentGameState.SessionData.PlayerLapTimeSessionBest >= currentGameState.SessionData.LapTimePrevious - closeThreshold)
         {
             return LastLapRating.CLOSE_TO_PERSONAL_BEST;
         }
         else if (currentGameState.SessionData.PlayerLapTimeSessionBest > 0)
         {
             return LastLapRating.MEH;
         }
     }
     return LastLapRating.NO_DATA;
 }
Ejemplo n.º 8
0
 private void displayNewSessionInfo(GameStateData currentGameState)
 {
     Console.WriteLine("New session details...");
     Console.WriteLine("SessionType " + currentGameState.SessionData.SessionType);
     Console.WriteLine("EventIndex " + currentGameState.SessionData.EventIndex);
     Console.WriteLine("SessionIteration " + currentGameState.SessionData.SessionIteration);
     String trackName = currentGameState.SessionData.TrackDefinition == null ? "unknown" : currentGameState.SessionData.TrackDefinition.name;
     Console.WriteLine("TrackName " + trackName);
 }
Ejemplo n.º 9
0
 public override bool isMessageStillValid(string eventSubType, GameStateData currentGameState, Dictionary<String, Object> validationData)
 {
     return true;
 }
Ejemplo n.º 10
0
 private void playPreLightsMessage(GameStateData currentGameState, int maxNumberToPlay)
 {
     playedPreLightsMessage = true;
     CrewChiefV3.GameState.Conditions.ConditionsSample currentConditions = currentGameState.Conditions.getMostRecentConditions();
     List<QueuedMessage> possibleMessages = new List<QueuedMessage>();
     if (currentConditions != null)
     {
         possibleMessages.Add(new QueuedMessage("trackTemp", MessageContents(ConditionsMonitor.folderTrackTempIs,
             QueuedMessage.folderNameNumbersStub + Math.Round(currentConditions.TrackTemperature), ConditionsMonitor.folderCelsius,
             ConditionsMonitor.folderAirTempIs, QueuedMessage.folderNameNumbersStub + Math.Round(currentConditions.AmbientTemperature),
             ConditionsMonitor.folderCelsius), 0, null));
     }
     if (currentGameState.PitData.HasMandatoryPitStop)
     {
         if (currentGameState.SessionData.SessionHasFixedTime)
         {
             possibleMessages.Add(new QueuedMessage("pit_window_time", MessageContents(MandatoryPitStops.folderMandatoryPitStopsPitWindowOpensAfter,
                 QueuedMessage.folderNameNumbersStub + currentGameState.PitData.PitWindowStart, MandatoryPitStops.folderMandatoryPitStopsMinutes), 0, this));
         }
         else
         {
             possibleMessages.Add(new QueuedMessage("pit_window_lap", MessageContents(MandatoryPitStops.folderMandatoryPitStopsPitWindowOpensOnLap,
                 QueuedMessage.folderNameNumbersStub + currentGameState.PitData.PitWindowStart), 0, this));
         }
     }
     if (currentGameState.SessionData.Position == 1)
     {
         possibleMessages.Add(new QueuedMessage(Position.folderPole, 0, this));
     }
     else
     {
         Console.WriteLine("pre-start message for P " + currentGameState.SessionData.Position);
         possibleMessages.Add(new QueuedMessage(Position.folderStub + currentGameState.SessionData.Position, 0, this));
     }
     // now pick a random selection
     if (possibleMessages.Count > 0)
     {
         int played = 0;
         var shuffled = possibleMessages.OrderBy(item => rand.Next());
         foreach (var message in shuffled)
         {
             played++;
             if (played > maxNumberToPlay)
             {
                 break;
             }
             audioPlayer.queueClip(message);
         }
     }
     // TODO: in the countdown / pre-lights phase, we don't know how long the race is going to be so we can't use the 'get on with it' messages :(
 }
Ejemplo n.º 11
0
        protected override void triggerInternal(GameStateData previousGameState, GameStateData currentGameState)
        {
            if (!playedPreLightsMessage && currentGameState.SessionData.SessionType == SessionType.Race && currentGameState.SessionData.SessionPhase == SessionPhase.Gridwalk &&
                (playPreLightsInRaceroom || CrewChief.gameDefinition.gameEnum != GameEnum.RACE_ROOM))
            {
                playPreLightsMessage(currentGameState, 3);
                playedPreLightsMessage = true;
                purgePreLightsMessages = true;
            }
            // TODO: in R3E online there's a GridWalk phase before the Countdown. In PCars they're combined. Add some messages to this phase.

            // R3E's gridWalk phase isn't useable here - the data during this phase are bollocks
            if (!playedGetReady && currentGameState.SessionData.SessionType == SessionType.Race && (currentGameState.SessionData.SessionPhase == SessionPhase.Countdown ||
                (currentGameState.SessionData.SessionPhase == SessionPhase.Formation && CrewChief.gameDefinition.gameEnum == GameEnum.RACE_ROOM)))
            {
                // If we've not yet played the pre-lights messages, just play one of them here, but not for RaceRoom as the lights will already have started
                if (!playedPreLightsMessage && CrewChief.gameDefinition.gameEnum != GameEnum.RACE_ROOM)
                {
                    playedPreLightsMessage = true;
                    playPreLightsMessage(currentGameState, 2);
                    purgePreLightsMessages = false;
                }
                if (purgePreLightsMessages)
                {
                    audioPlayer.purgeQueues();
                }
                audioPlayer.queueClip(new QueuedMessage(folderGetReady, 0, this));
                playedGetReady = true;
            }
            /*if (!playedGreenGreenGreen && previousGameState != null && currentGameState.SessionData.SessionType == SessionType.Race &&
                (currentGameState.SessionData.SessionPhase == SessionPhase.Green &&
                    (previousGameState.SessionData.SessionPhase == SessionPhase.Formation ||
                     previousGameState.SessionData.SessionPhase == SessionPhase.Countdown)))
            {*/
            if (previousGameState != null && enableGreenLightMessages &&
                currentGameState.SessionData.SessionType == SessionType.Race &&
                currentGameState.SessionData.SessionPhase == SessionPhase.Green &&
                (previousGameState.SessionData.SessionPhase == SessionPhase.Formation ||
                 previousGameState.SessionData.SessionPhase == SessionPhase.Countdown))
            {
                audioPlayer.removeQueuedClip(folderGetReady);
                audioPlayer.playClipImmediately(new QueuedMessage(folderGreenGreenGreen, 0, this), false);
                audioPlayer.closeChannel();
                audioPlayer.disablePearlsOfWisdom = false;
            }
            if (currentGameState.SessionData.SessionType == SessionType.Race && currentGameState.SessionData.IsNewLap && currentGameState.SessionData.CompletedLaps > 0)
            {
                // a new lap has been started in race mode
                int position = currentGameState.SessionData.Position;
                if (currentGameState.SessionData.CompletedLaps == currentGameState.SessionData.SessionNumberOfLaps - 1)
                {
                    if (position == 1)
                    {
                        audioPlayer.queueClip(new QueuedMessage(folderLastLapLeading, 0, this));
                    }
                    else if (position < 4)
                    {
                        audioPlayer.queueClip(new QueuedMessage(folderLastLapTopThree, 0, this));
                    }
                    else if (position >= 4)
                    {
                        audioPlayer.queueClip(new QueuedMessage(folderLastLap, 0, this), PearlsOfWisdom.PearlType.NEUTRAL, 0.5);
                    }
                    else if (position >= 10)
                    {
                        audioPlayer.queueClip(new QueuedMessage(folderLastLap, 0, this), PearlsOfWisdom.PearlType.BAD, 0.5);
                    }
                    else
                    {
                        Console.WriteLine("1 lap left but position is < 1");
                    }
                }
                else if (currentGameState.SessionData.CompletedLaps == currentGameState.SessionData.SessionNumberOfLaps - 2)
                {
                    if (position == 1)
                    {
                        audioPlayer.queueClip(new QueuedMessage(folderTwoLeftLeading, 0, this));
                    }
                    else if (position < 4)
                    {
                        audioPlayer.queueClip(new QueuedMessage(folderTwoLeftTopThree, 0, this));
                    }
                    else if (position >= 4)
                    {
                        audioPlayer.queueClip(new QueuedMessage(folderTwoLeft, 0, this), PearlsOfWisdom.PearlType.NEUTRAL, 0.5);
                    }
                    else if (position >= 10)
                    {
                        audioPlayer.queueClip(new QueuedMessage(folderTwoLeft, 0, this), PearlsOfWisdom.PearlType.BAD, 0.5);
                    }
                    else
                    {
                        Console.WriteLine("2 laps left but position is < 1");
                    }
                    // 2 laps left, so prevent any further pearls of wisdom being added

                }
            }
        }
        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;
        }
Ejemplo n.º 13
0
        protected override void triggerInternal(GameStateData previousGameState, GameStateData currentGameState)
        {
            addExtraLapForDTM2015 = currentGameState.carClass.carClassEnum == CarData.CarClassEnum.DTM_2015;
            leaderHasFinishedRace = currentGameState.SessionData.LeaderHasFinishedRace;
            timeLeft = currentGameState.SessionData.SessionTimeRemaining;
            if (currentGameState.SessionData.SessionNumberOfLaps > 0)
            {
                lapsLeft = currentGameState.SessionData.SessionNumberOfLaps - currentGameState.SessionData.CompletedLaps;
                sessionLengthIsTime = false;
            }
            else
            {
                sessionLengthIsTime = true;
            }
            if (sessionLengthIsTime)
            {
                if (addExtraLapForDTM2015 && gotHalfTime && timeLeft <= 0 && currentGameState.SessionData.IsNewLap)
                {
                    startedDTM2015ExtraLap = true;
                }
                if (!gotHalfTime)
                {
                    Console.WriteLine("Session time remaining = " + timeLeft);
                    halfTime = timeLeft / 2;
                    gotHalfTime = true;
                    if (currentGameState.FuelData.FuelUseActive)
                    {
                        // don't allow the half way message to play if fuel use is active - there's already one in there
                        playedHalfWayHome = true;
                    }
                }
                PearlsOfWisdom.PearlType pearlType = PearlsOfWisdom.PearlType.NONE;
                if (currentGameState.SessionData.SessionType == SessionType.Race && currentGameState.SessionData.CompletedLaps > 1)
                {
                    pearlType = PearlsOfWisdom.PearlType.NEUTRAL;
                    if (currentGameState.SessionData.Position < 4)
                    {
                        pearlType = PearlsOfWisdom.PearlType.GOOD;
                    }
                    else if (currentGameState.SessionData.Position > 10)
                    {
                        pearlType = PearlsOfWisdom.PearlType.BAD;
                    }
                }

                // this event only works if we're leading because we don't know when the leader
                // crosses the line :(

                // TODO: the above is no longer true - rework this
                if (currentGameState.SessionData.SessionType == SessionType.Race && currentGameState.SessionData.IsNewLap &&
                    currentGameState.SessionData.SessionRunningTime > 60 && !playedLastLap &&
                    currentGameState.SessionData.Position == 1 &&
                    ((!addExtraLapForDTM2015 && timeLeft > 0 && timeLeft < currentGameState.SessionData.PlayerLapTimeSessionBest) ||
                    (addExtraLapForDTM2015 && timeLeft <= 0)))
                {
                    playedLastLap = true;
                    played2mins = true;
                    played5mins = true;
                    played10mins = true;
                    played15mins = true;
                    played20mins = true;
                    playedHalfWayHome = true;
                    if (currentGameState.SessionData.Position == 1)
                    {
                        // don't add a pearl here - the audio clip already contains encouragement
                        audioPlayer.queueClip(new QueuedMessage(folderLastLapLeading, 0, this), pearlType, 0);
                    }
                    else if (currentGameState.SessionData.Position < 4)
                    {
                        // don't add a pearl here - the audio clip already contains encouragement
                        audioPlayer.queueClip(new QueuedMessage(folderLastLapPodium, 0, this), pearlType, 0);
                    }
                    else
                    {
                        audioPlayer.queueClip(new QueuedMessage(folderLastLap, 0, this), pearlType, 0.7);
                    }
                }
                if (currentGameState.SessionData.SessionRunningTime > 60 && timeLeft / 60 < 3 && timeLeft / 60 > 2.9)
                {
                    // disable pearls for the last part of the race
                    audioPlayer.disablePearlsOfWisdom = true;
                }
                if (currentGameState.SessionData.SessionRunningTime > 60 && !played2mins && timeLeft / 60 < 2 && timeLeft / 60 > 1.9)
                {
                    played2mins = true;
                    played5mins = true;
                    played10mins = true;
                    played15mins = true;
                    played20mins = true;
                    playedHalfWayHome = true;
                    audioPlayer.suspendPearlsOfWisdom();
                    audioPlayer.queueClip(new QueuedMessage(folder2mins, 0, this));
                } if (currentGameState.SessionData.SessionRunningTime > 60 && !played5mins && timeLeft / 60 < 5 && timeLeft / 60 > 4.9)
                {
                    played5mins = true;
                    played10mins = true;
                    played15mins = true;
                    played20mins = true;
                    playedHalfWayHome = true;
                    if (currentGameState.SessionData.SessionType == SessionType.Race && currentGameState.SessionData.Position == 1)
                    {
                        // don't add a pearl here - the audio clip already contains encouragement
                        audioPlayer.queueClip(new QueuedMessage(folder5minsLeading, 0, this), pearlType, 0);
                    }
                    else if (currentGameState.SessionData.SessionType == SessionType.Race && currentGameState.SessionData.Position < 4)
                    {
                        // don't add a pearl here - the audio clip already contains encouragement
                        audioPlayer.queueClip(new QueuedMessage(folder5minsPodium, 0, this), pearlType, 0);
                    }
                    else
                    {
                        audioPlayer.queueClip(new QueuedMessage(folder5mins, 0, this), pearlType, 0.7);
                    }
                }
                if (currentGameState.SessionData.SessionRunningTime > 60 && !played10mins && timeLeft / 60 < 10 && timeLeft / 60 > 9.9)
                {
                    played10mins = true;
                    played15mins = true;
                    played20mins = true;
                    audioPlayer.queueClip(new QueuedMessage(folder10mins, 0, this), pearlType, 0.7);
                }
                if (currentGameState.SessionData.SessionRunningTime > 60 && !played15mins && timeLeft / 60 < 15 && timeLeft / 60 > 14.9)
                {
                    played15mins = true;
                    played20mins = true;
                    audioPlayer.queueClip(new QueuedMessage(folder15mins, 0, this), pearlType, 0.7);
                }
                if (currentGameState.SessionData.SessionRunningTime > 60 && !played20mins && timeLeft / 60 < 20 && timeLeft / 60 > 19.9)
                {
                    played20mins = true;
                    audioPlayer.queueClip(new QueuedMessage(folder20mins, 0, this), pearlType, 0.7);
                }
                else if (currentGameState.SessionData.SessionType == SessionType.Race &&
                    currentGameState.SessionData.SessionRunningTime > 60 && !playedHalfWayHome && timeLeft > 0 && timeLeft < halfTime)
                {
                    // this one sounds weird in practice and qual sessions, so skip it
                    playedHalfWayHome = true;
                    audioPlayer.queueClip(new QueuedMessage(folderHalfWayHome, 0, this), pearlType, 0.7);
                }
            }
        }
Ejemplo n.º 14
0
 // this is called on each 'tick' - the event subtype should
 // place its logic in here including calls to audioPlayer.queueClip
 protected abstract void triggerInternal(GameStateData previousGameState, GameStateData currentGameState);
 private PitWindow mapToPitWindow(GameStateData currentGameState, uint pitSchedule, uint pitMode)
 {
     if (currentGameState.PitData.PitWindowStart > 0)
     {
         if ((currentGameState.SessionData.SessionNumberOfLaps > 0 && currentGameState.SessionData.CompletedLaps < currentGameState.PitData.PitWindowStart - 1) ||
             (currentGameState.SessionData.SessionRunTime > 0 && currentGameState.SessionData.SessionRunningTime < currentGameState.PitData.PitWindowStart))
         {
             return PitWindow.Closed;
         }
         else if ((currentGameState.SessionData.SessionNumberOfLaps > 0 && currentGameState.SessionData.CompletedLaps >= currentGameState.PitData.PitWindowStart - 1) ||
             (currentGameState.SessionData.SessionRunTime > 0 && currentGameState.SessionData.SessionRunningTime >= currentGameState.PitData.PitWindowStart))
         {
             if (currentGameState.PitData.PitWindow == PitWindow.Completed ||
                 (currentGameState.PitData.PitWindow == PitWindow.StopInProgress && pitMode == (uint)ePitMode.PIT_MODE_DRIVING_OUT_OF_PITS))
             {
                 return PitWindow.Completed;
             }
             else
             if (pitSchedule == (uint)ePitSchedule.PIT_SCHEDULE_STANDARD &&
                 (pitMode == (uint)ePitMode.PIT_MODE_DRIVING_INTO_PITS || pitMode == (uint)ePitMode.PIT_MODE_IN_PIT))
             {
                 return PitWindow.StopInProgress;
             }
             else
             {
                 return PitWindow.Open;
             }
         }
     }
     return PitWindow.Unavailable;
 }
Ejemplo n.º 16
0
 public void trigger(GameStateData previousGameState, GameStateData currentGameState)
 {
     // common checks here?
     triggerInternal(previousGameState, currentGameState);
 }
Ejemplo n.º 17
0
 // generally the event subclass can just return true for this, but when a clip is played with
 // a non-zero delay it may be necessary to re-check that the clip is still valid against the current
 // state
 public virtual Boolean isMessageStillValid(String eventSubType, GameStateData currentGameState, Dictionary<String, Object> validationData)
 {
     return currentGameState != null && isApplicableForCurrentSessionAndPhase(currentGameState.SessionData.SessionType, currentGameState.SessionData.SessionPhase);
 }
Ejemplo n.º 18
0
        protected override void triggerInternal(GameStateData previousGameState, GameStateData currentGameState)
        {
            if (engineData == null)
            {
                clearState();
            }
            if (maxSafeWaterTemp == 0) {
                maxSafeWaterTemp = currentGameState.carClass.maxSafeWaterTemp;
            }
            if (maxSafeOilTemp == 0) {
                maxSafeOilTemp = currentGameState.carClass.maxSafeOilTemp;
            }
            if (currentGameState.SessionData.SessionRunningTime > 60 * currentGameState.EngineData.MinutesIntoSessionBeforeMonitoring)
            {
                engineData.addSample(currentGameState.EngineData.EngineOilTemp, currentGameState.EngineData.EngineWaterTemp,
                    currentGameState.EngineData.EngineOilPressure);

                if (currentGameState.SessionData.SessionRunningTime > gameTimeAtLastStatusCheck + statusMonitorWindowLength)
                {
                    EngineStatus currentEngineStatus = engineData.getEngineStatusFromAverage(maxSafeWaterTemp, maxSafeOilTemp);
                    if (currentEngineStatus != lastStatusMessage)
                    {
                        switch (currentEngineStatus)
                        {
                            case EngineStatus.ALL_CLEAR:
                                lastStatusMessage = currentEngineStatus;
                                audioPlayer.queueClip(new QueuedMessage(folderAllClear, 0, this));
                                break;
                            case EngineStatus.HOT_OIL:
                                // don't play this if the last message was about hot oil *and* water - wait for 'all clear'
                                if (lastStatusMessage != EngineStatus.HOT_OIL_AND_WATER)
                                {
                                    lastStatusMessage = currentEngineStatus;
                                    audioPlayer.queueClip(new QueuedMessage(folderHotOil, 0, this));
                                }
                                break;
                            case EngineStatus.HOT_WATER:
                                // don't play this if the last message was about hot oil *and* water - wait for 'all clear'
                                if (lastStatusMessage != EngineStatus.HOT_OIL_AND_WATER)
                                {
                                    lastStatusMessage = currentEngineStatus;
                                    audioPlayer.queueClip(new QueuedMessage(folderHotWater, 0, this));
                                }
                                break;
                            case EngineStatus.HOT_OIL_AND_WATER:
                                lastStatusMessage = currentEngineStatus;
                                audioPlayer.queueClip(new QueuedMessage(folderHotOilAndWater, 0, this));
                                break;
                        }
                    }
                    gameTimeAtLastStatusCheck = currentGameState.SessionData.SessionRunningTime;
                    engineData = new EngineData();
                }
            }
        }
Ejemplo n.º 19
0
 public override void clearState()
 {
     lapTimesWindow = new List<float>(lapTimesWindowSize);
     lastConsistencyUpdate = 0;
     lastConsistencyMessage = ConsistencyResult.NOT_APPLICABLE;
     lapIsValid = true;
     lastLapRating = LastLapRating.NO_DATA;
     deltaPlayerBestToSessionBestInClass = TimeSpan.MaxValue;
     deltaPlayerBestToSessionBestOverall = TimeSpan.MaxValue;
     deltaPlayerLastToSessionBestInClass = TimeSpan.MaxValue;
     deltaPlayerLastToSessionBestOverall = TimeSpan.MaxValue;
     lastLapTime = 0;
     bestLapTime = 0;
     currentPosition = -1;
     currentGameState = null;
     isHotLapping = false;
     lastGapToSecondWhenLeadingPracOrQual = TimeSpan.Zero;
 }
Ejemplo n.º 20
0
 private float getOpponentBestLap(int opponentPosition, int lapsToCheck, GameStateData gameState)
 {
     OpponentData opponent = gameState.getOpponentAtPosition(opponentPosition, false);
     if (opponent == null || opponent.OpponentLapData.Count < lapsToCheck)
     {
         return -1;
     }
     float bestLap = -1;
     for (int i = opponent.OpponentLapData.Count - 1; i >= opponent.OpponentLapData.Count - lapsToCheck; i--)
     {
         if (bestLap == -1 || bestLap > opponent.OpponentLapData[i].LapTime)
         {
             bestLap = opponent.OpponentLapData[i].LapTime;
         }
     }
     return bestLap;
 }
Ejemplo n.º 21
0
        protected override void triggerInternal(GameStateData previousGameState, GameStateData currentGameState)
        {
            sessionType = currentGameState.SessionData.SessionType;
            this.currentGameState = currentGameState;
            if (currentGameState.SessionData.IsNewLap)
            {
                if (currentGameState.SessionData.LapTimePrevious > 0)
                {
                    if (currentGameState.OpponentData.Count > 0)
                    {
                        if (currentGameState.SessionData.OpponentsLapTimeSessionBestPlayerClass > 0)
                        {
                            deltaPlayerLastToSessionBestInClass = TimeSpan.FromSeconds(
                                currentGameState.SessionData.LapTimePrevious - currentGameState.SessionData.OpponentsLapTimeSessionBestPlayerClass);
                        }
                        if (currentGameState.SessionData.OpponentsLapTimeSessionBestOverall > 0)
                        {
                            deltaPlayerLastToSessionBestOverall = TimeSpan.FromSeconds(
                                currentGameState.SessionData.LapTimePrevious - currentGameState.SessionData.OpponentsLapTimeSessionBestOverall);
                        }
                    }
                    else if (currentGameState.SessionData.PlayerLapTimeSessionBest > 0)
                    {
                        deltaPlayerLastToSessionBestOverall = TimeSpan.FromSeconds(currentGameState.SessionData.LapTimePrevious - currentGameState.SessionData.PlayerLapTimeSessionBest);
                        deltaPlayerLastToSessionBestInClass = deltaPlayerLastToSessionBestOverall;
                    }
                    if (currentGameState.SessionData.LapTimePrevious <= currentGameState.SessionData.PlayerLapTimeSessionBest)
                    {
                        deltaPlayerBestToSessionBestInClass = deltaPlayerLastToSessionBestInClass;
                        deltaPlayerBestToSessionBestOverall = deltaPlayerLastToSessionBestOverall;
                    }
                }
                else
                {
                    // the last lap was invalid so the delta is undefined
                    deltaPlayerLastToSessionBestInClass = TimeSpan.MaxValue;
                    deltaPlayerLastToSessionBestOverall = TimeSpan.MaxValue;
                }
            }
            currentPosition = currentGameState.SessionData.Position;

            // check the current lap is still valid
            if (lapIsValid && currentGameState.SessionData.CompletedLaps > 0 &&
                !currentGameState.SessionData.IsNewLap && !currentGameState.SessionData.CurrentLapIsValid)
            {
                lapIsValid = false;
            }
            if (currentGameState.SessionData.IsNewLap)
            {
                lastLapTime = currentGameState.SessionData.LapTimePrevious;
                if (lastLapTime > 0 && lapIsValid) {
                    if (bestLapTime == 0 || lastLapTime < bestLapTime) {
                        bestLapTime = lastLapTime;
                    }
                }
            }

            float[] lapAndSectorsComparisonData = new float[] { -1, -1, -1, -1 };
            if (currentGameState.SessionData.IsNewSector)
            {
                isHotLapping = currentGameState.SessionData.SessionType == SessionType.HotLap || (currentGameState.OpponentData.Count == 0 || (
                    currentGameState.OpponentData.Count == 1 && currentGameState.OpponentData.First().Value.DriverRawName == currentGameState.SessionData.DriverRawName));
                if (isHotLapping)
                {
                    lapAndSectorsComparisonData[1] = currentGameState.SessionData.PlayerBestLapSector1Time;
                    lapAndSectorsComparisonData[2] = currentGameState.SessionData.PlayerBestLapSector2Time;
                    lapAndSectorsComparisonData[3] = currentGameState.SessionData.PlayerBestLapSector3Time;
                }
                else
                {
                    if (currentGameState.SessionData.SessionType == SessionType.Race)
                    {
                        lapAndSectorsComparisonData = currentGameState.getTimeAndSectorsForBestOpponentLapInWindow(paceCheckLapsWindowForRace, currentGameState.carClass.carClassEnum);
                    }
                    else if (currentGameState.SessionData.SessionType == SessionType.Qualify || currentGameState.SessionData.SessionType == SessionType.Practice)
                    {
                        lapAndSectorsComparisonData = currentGameState.getTimeAndSectorsForBestOpponentLapInWindow(-1, currentGameState.carClass.carClassEnum);
                    }
                }
            }

            if (!currentGameState.PitData.OnInLap && !currentGameState.PitData.OnOutLap)
            {
                Boolean sectorsReportedForLap = false;
                if (currentGameState.SessionData.IsNewLap &&
                    ((currentGameState.SessionData.SessionType == SessionType.HotLap && currentGameState.SessionData.CompletedLaps > 0) || currentGameState.SessionData.CompletedLaps > 1))
                {
                    if (lapTimesWindow == null)
                    {
                        lapTimesWindow = new List<float>(lapTimesWindowSize);
                    }
                    lastLapRating = getLastLapRating(currentGameState, lapAndSectorsComparisonData);

                    if (currentGameState.SessionData.PreviousLapWasValid)
                    {
                        lapTimesWindow.Insert(0, currentGameState.SessionData.LapTimePrevious);
                        if (lapIsValid)
                        {
                            Boolean playedLapTime = false;
                            if (isHotLapping)
                            {
                                // always play the laptime in hotlap mode
                                audioPlayer.queueClip(new QueuedMessage("laptime",
                                        MessageContents(folderLapTimeIntro, TimeSpan.FromSeconds(currentGameState.SessionData.LapTimePrevious)), 0, this));
                                playedLapTime = true;
                            }
                            else if (((currentGameState.SessionData.SessionType == SessionType.Qualify || currentGameState.SessionData.SessionType == SessionType.Practice) && frequencyOfPlayerQualAndPracLapTimeReports > random.NextDouble() * 10)
                                || (currentGameState.SessionData.SessionType == SessionType.Race && frequencyOfPlayerRaceLapTimeReports > random.NextDouble() * 10))
                            {
                                // usually play it in practice / qual mode, occasionally play it in race mode
                                QueuedMessage gapFillerLapTime = new QueuedMessage("laptime",
                                    MessageContents(folderLapTimeIntro, TimeSpan.FromSeconds(currentGameState.SessionData.LapTimePrevious)), 0, this);
                                if (currentGameState.SessionData.SessionType == SessionType.Race)
                                {
                                    gapFillerLapTime.maxPermittedQueueLengthForMessage = maxQueueLengthForRaceLapTimeReports;
                                }
                                audioPlayer.queueClip(gapFillerLapTime);
                                playedLapTime = true;
                            }

                            if (currentGameState.SessionData.SessionType == SessionType.Qualify || currentGameState.SessionData.SessionType == SessionType.Practice ||
                                currentGameState.SessionData.SessionType == SessionType.HotLap)
                            {
                                if (currentGameState.SessionData.SessionType == SessionType.HotLap || currentGameState.OpponentData.Count == 0)
                                {
                                    if (lastLapRating == LastLapRating.BEST_IN_CLASS || deltaPlayerLastToSessionBestOverall <= TimeSpan.Zero)
                                    {
                                        audioPlayer.queueClip(new QueuedMessage(folderPersonalBest, 0, this));
                                    }
                                    else if (deltaPlayerLastToSessionBestOverall < TimeSpan.FromMilliseconds(50))
                                    {
                                        audioPlayer.queueClip(new QueuedMessage(folderLessThanATenthOffThePace, 0, this));
                                    }
                                    else if (deltaPlayerLastToSessionBestOverall < TimeSpan.MaxValue)
                                    {
                                        audioPlayer.queueClip(new QueuedMessage("lapTimeNotRaceGap",
                                            MessageContents(folderGapIntro, deltaPlayerLastToSessionBestOverall, folderGapOutroOffPace), 0, this));
                                    }
                                    if (practiceAndQualSectorReportsLapEnd && frequencyOfPracticeAndQualSectorDeltaReports > random.NextDouble() * 10)
                                    {
                                        List<MessageFragment> sectorMessageFragments = getSectorDeltaMessages(SectorReportOption.COMBINED, currentGameState.SessionData.LastSector1Time, lapAndSectorsComparisonData[1],
                                            currentGameState.SessionData.LastSector2Time, lapAndSectorsComparisonData[2], currentGameState.SessionData.LastSector3Time, lapAndSectorsComparisonData[3], true);
                                        if (sectorMessageFragments.Count > 0)
                                        {
                                            audioPlayer.queueClip(new QueuedMessage("sectorsHotLap", sectorMessageFragments, 0, this));
                                            sectorsReportedForLap = true;
                                        }
                                    }
                                }
                                    // need to be careful with the rating here as it's based on the known opponent laps, and we may have joined the session part way through
                                else if (currentGameState.SessionData.Position == 1)
                                {
                                    Boolean newGapToSecond = false;
                                    if (previousGameState != null && previousGameState.SessionData.Position > 1)
                                    {
                                        newGapToSecond = true;
                                        if (currentGameState.SessionData.SessionType == SessionType.Qualify)
                                        {
                                            audioPlayer.queueClip(new QueuedMessage(Position.folderPole, 0, this));
                                        }
                                        else if (currentGameState.SessionData.SessionType == SessionType.Practice)
                                        {
                                            audioPlayer.queueClip(new QueuedMessage(Position.folderStub + 1, 0, this));
                                        }
                                    }
                                    else if (deltaPlayerLastToSessionBestOverall < lastGapToSecondWhenLeadingPracOrQual)
                                    {
                                        newGapToSecond = true;
                                        lastGapToSecondWhenLeadingPracOrQual = deltaPlayerLastToSessionBestOverall;
                                    }
                                    if (newGapToSecond)
                                    {
                                        lastGapToSecondWhenLeadingPracOrQual = deltaPlayerLastToSessionBestOverall;
                                        TimeSpan gapBehind = deltaPlayerLastToSessionBestOverall.Negate();
                                        // only play qual / prac deltas for Raceroom as the PCars data is inaccurate for sessions joined part way through
                                        if ((!disablePCarspracAndQualPoleDeltaReports ||
                                            CrewChief.gameDefinition.gameEnum == GameDefinition.raceRoom.gameEnum) &&
                                            ((gapBehind.Seconds > 0 || gapBehind.Milliseconds > 50) &&
                                            gapBehind.Seconds < 60))
                                        {
                                            // delay this a bit...
                                            audioPlayer.queueClip(new QueuedMessage("lapTimeNotRaceGap",
                                                MessageContents(folderGapIntro, gapBehind, folderQuickerThanSecondPlace), random.Next(0, 20), this));
                                        }
                                    }
                                }
                                else
                                {
                                    if (lastLapRating == LastLapRating.PERSONAL_BEST_STILL_SLOW || lastLapRating == LastLapRating.PERSONAL_BEST_CLOSE_TO_CLASS_LEADER ||
                                        lastLapRating == LastLapRating.PERSONAL_BEST_CLOSE_TO_OVERALL_LEADER)
                                    {
                                        audioPlayer.queueClip(new QueuedMessage(folderPersonalBest, 0, this));
                                    }
                                    // don't read this message if the rounded time gap is 0.0 seconds or it's more than 59 seconds
                                    // only play qual / prac deltas for Raceroom as the PCars data is inaccurate for sessions joined part way through
                                    if ((!disablePCarspracAndQualPoleDeltaReports || CrewChief.gameDefinition.gameEnum == GameDefinition.raceRoom.gameEnum) &&
                                        (deltaPlayerLastToSessionBestInClass.Seconds > 0 || deltaPlayerLastToSessionBestInClass.Milliseconds > 50) &&
                                        deltaPlayerLastToSessionBestInClass.Seconds < 60)
                                    {
                                        // delay this a bit...
                                        audioPlayer.queueClip(new QueuedMessage("lapTimeNotRaceGap",
                                            MessageContents(folderGapIntro, deltaPlayerLastToSessionBestInClass, folderGapOutroOffPace), random.Next(0, 20), this));
                                    }
                                    if (practiceAndQualSectorReportsLapEnd && frequencyOfPracticeAndQualSectorDeltaReports > random.NextDouble() * 10)
                                    {
                                        List<MessageFragment> sectorMessageFragments = getSectorDeltaMessages(SectorReportOption.COMBINED, currentGameState.SessionData.LastSector1Time, lapAndSectorsComparisonData[1],
                                            currentGameState.SessionData.LastSector2Time, lapAndSectorsComparisonData[2], currentGameState.SessionData.LastSector3Time, lapAndSectorsComparisonData[3], true);
                                        if (sectorMessageFragments.Count > 0)
                                        {
                                            audioPlayer.queueClip(new QueuedMessage("sectorsQual", sectorMessageFragments, 0, this));
                                            sectorsReportedForLap = true;
                                        }
                                    }
                                }
                            }
                            else if (currentGameState.SessionData.SessionType == SessionType.Race)
                            {
                                Boolean playedLapMessage = false;
                                if (frequencyOfPlayerRaceLapTimeReports > random.NextDouble() * 10)
                                {
                                    float pearlLikelihood = 0.8f;
                                    switch (lastLapRating)
                                    {
                                        case LastLapRating.BEST_OVERALL:
                                            playedLapMessage = true;
                                            audioPlayer.queueClip(new QueuedMessage(folderBestLapInRace, 0, this), PearlsOfWisdom.PearlType.GOOD, pearlLikelihood);
                                            break;
                                        case LastLapRating.BEST_IN_CLASS:
                                            playedLapMessage = true;
                                            audioPlayer.queueClip(new QueuedMessage(folderBestLapInRaceForClass, 0, this), PearlsOfWisdom.PearlType.GOOD, pearlLikelihood);
                                            break;
                                        case LastLapRating.SETTING_CURRENT_PACE:
                                            playedLapMessage = true;
                                            audioPlayer.queueClip(new QueuedMessage(folderSettingCurrentRacePace, 0, this), PearlsOfWisdom.PearlType.GOOD, pearlLikelihood);
                                            break;
                                        case LastLapRating.CLOSE_TO_CURRENT_PACE:
                                            // don't keep playing this one
                                            if (random.NextDouble() < 0.5)
                                            {
                                                playedLapMessage = true;
                                                audioPlayer.queueClip(new QueuedMessage(folderMatchingCurrentRacePace, 0, this), PearlsOfWisdom.PearlType.GOOD, pearlLikelihood);
                                            }
                                            break;
                                        case LastLapRating.PERSONAL_BEST_CLOSE_TO_OVERALL_LEADER:
                                        case LastLapRating.PERSONAL_BEST_CLOSE_TO_CLASS_LEADER:
                                            playedLapMessage = true;
                                            audioPlayer.queueClip(new QueuedMessage(folderGoodLap, 0, this), PearlsOfWisdom.PearlType.GOOD, pearlLikelihood);
                                            break;
                                        case LastLapRating.PERSONAL_BEST_STILL_SLOW:
                                            playedLapMessage = true;
                                            audioPlayer.queueClip(new QueuedMessage(folderPersonalBest, 0, this), PearlsOfWisdom.PearlType.NEUTRAL, pearlLikelihood);
                                            break;
                                        case LastLapRating.CLOSE_TO_OVERALL_LEADER:
                                        case LastLapRating.CLOSE_TO_CLASS_LEADER:
                                            // this is an OK lap but not a PB. We only want to say "decent lap" occasionally here
                                            if (random.NextDouble() < 0.2)
                                            {
                                                playedLapMessage = true;
                                                audioPlayer.queueClip(new QueuedMessage(folderGoodLap, 0, this), PearlsOfWisdom.PearlType.NEUTRAL, pearlLikelihood);
                                            }
                                            break;
                                        default:
                                            break;
                                    }
                                }

                                if (raceSectorReportsAtLapEnd && frequencyOfRaceSectorDeltaReports > random.NextDouble() * 10)
                                {
                                    double r = random.NextDouble();
                                    SectorReportOption reportOption = SectorReportOption.COMBINED;
                                    if (playedLapTime && playedLapMessage)
                                    {
                                        // if we've already played a laptime and lap rating, use the short sector message.
                                        reportOption = SectorReportOption.WORST_ONLY;
                                    }
                                    else if (r > 0.6 || ((playedLapTime || playedLapMessage) && r > 0.3))
                                    {
                                        // if we've played one of these, usually use the abbrieviated version. If we've played neither, sometimes use the abbrieviated version
                                        reportOption = SectorReportOption.BEST_AND_WORST;
                                    }

                                    List<MessageFragment> sectorMessageFragments = getSectorDeltaMessages(reportOption, currentGameState.SessionData.LastSector1Time, lapAndSectorsComparisonData[1],
                                            currentGameState.SessionData.LastSector2Time, lapAndSectorsComparisonData[2], currentGameState.SessionData.LastSector3Time, lapAndSectorsComparisonData[3], false);
                                    if (sectorMessageFragments.Count > 0)
                                    {
                                        QueuedMessage message = new QueuedMessage("sectorsRace", sectorMessageFragments, 0, this);
                                        message.maxPermittedQueueLengthForMessage = maxQueueLengthForRaceSectorDeltaReports;
                                        audioPlayer.queueClip(message);
                                        sectorsReportedForLap = true;
                                    }
                                }

                                // play the consistency message if we've not played the good lap message, or sometimes
                                // play them both
                                Boolean playConsistencyMessage = !playedLapMessage || random.NextDouble() < 0.25;
                                if (playConsistencyMessage && currentGameState.SessionData.CompletedLaps >= lastConsistencyUpdate + lapTimesWindowSize &&
                                    lapTimesWindow.Count >= lapTimesWindowSize)
                                {
                                    ConsistencyResult consistency = checkAgainstPreviousLaps();
                                    if (consistency == ConsistencyResult.CONSISTENT)
                                    {
                                        lastConsistencyUpdate = currentGameState.SessionData.CompletedLaps;
                                        audioPlayer.queueClip(new QueuedMessage(folderConsistentTimes, random.Next(0, 20), this));
                                    }
                                    else if (consistency == ConsistencyResult.IMPROVING)
                                    {
                                        lastConsistencyUpdate = currentGameState.SessionData.CompletedLaps;
                                        audioPlayer.queueClip(new QueuedMessage(folderImprovingTimes, random.Next(0, 20), this));
                                    }
                                    else if (consistency == ConsistencyResult.WORSENING)
                                    {
                                        // don't play the worsening message if the lap rating is good
                                        if (lastLapRating == LastLapRating.BEST_IN_CLASS || lastLapRating == LastLapRating.BEST_OVERALL ||
                                            lastLapRating == LastLapRating.SETTING_CURRENT_PACE || lastLapRating == LastLapRating.CLOSE_TO_CURRENT_PACE)
                                        {
                                            Console.WriteLine("Skipping 'worsening' laptimes message - inconsistent with lap rating");
                                        }
                                        else
                                        {
                                            lastConsistencyUpdate = currentGameState.SessionData.CompletedLaps;
                                            audioPlayer.queueClip(new QueuedMessage(folderWorseningTimes, random.Next(0, 20), this));
                                        }
                                    }
                                }
                            }
                        }
                    }
                    lapIsValid = true;
                }
                // report sector delta at the completion of a sector?
                if (!sectorsReportedForLap && currentGameState.SessionData.IsNewSector &&
                    ((currentGameState.SessionData.SessionType == SessionType.Race && raceSectorReportsAtEachSector) ||
                     (currentGameState.SessionData.SessionType != SessionType.Race && practiceAndQualSectorReportsAtEachSector)))
                {
                    double r = random.NextDouble() * 10;
                    Boolean canPlayForRace = frequencyOfRaceSectorDeltaReports > r;
                    Boolean canPlayForPracAndQual = frequencyOfPracticeAndQualSectorDeltaReports > r;
                    if ((currentGameState.SessionData.SessionType == SessionType.Race && canPlayForRace) ||
                        ((currentGameState.SessionData.SessionType == SessionType.Practice || currentGameState.SessionData.SessionType == SessionType.Qualify ||
                        currentGameState.SessionData.SessionType == SessionType.HotLap) && canPlayForPracAndQual))
                    {
                        float playerSector = -1;
                        float comparisonSector = -1;
                        SectorSet sectorEnum = SectorSet.NONE;
                        switch (currentGameState.SessionData.SectorNumber)
                        {
                            case 1:
                                playerSector = currentGameState.SessionData.LastSector3Time;
                                comparisonSector = lapAndSectorsComparisonData[3];
                                sectorEnum = SectorSet.THREE;
                                break;
                            case 2:
                                playerSector = currentGameState.SessionData.LastSector1Time;
                                comparisonSector = lapAndSectorsComparisonData[1];
                                sectorEnum = SectorSet.ONE;
                                break;
                            case 3:
                                playerSector = currentGameState.SessionData.LastSector2Time;
                                comparisonSector = lapAndSectorsComparisonData[2];
                                sectorEnum = SectorSet.TWO;
                                break;
                        }
                        if (playerSector > 0 && comparisonSector > 0)
                        {
                            String folder = getFolderForSectorCombination(getEnumForSectorDelta(playerSector - comparisonSector, currentGameState.SessionData.SessionType != SessionType.Race), sectorEnum);
                            if (folder != null)
                            {
                                audioPlayer.queueClip(new QueuedMessage(folder, random.Next(2, 4), this));
                            }
                        }
                    }
                }
            }
        }
Ejemplo n.º 22
0
        private Boolean isOpponentApproachingPitExit(GameStateData currentGameState)
        {
            float distanceStartCheckPoint;
            float distanceEndCheckPoint;

            // hack for PCars - the distanceRoundTrack will be zero until we enter turn one after leaving the pits. Stupid...
            if (currentGameState.PositionAndMotionData.DistanceRoundTrack == 0)
            {
                distanceStartCheckPoint = 0;
                distanceEndCheckPoint = maxSeparationForPitExitWarning - minSeparationForPitExitWarning;
            }
            else
            {
                distanceStartCheckPoint = currentGameState.PositionAndMotionData.DistanceRoundTrack - maxSeparationForPitExitWarning;
                distanceEndCheckPoint = currentGameState.PositionAndMotionData.DistanceRoundTrack - minSeparationForPitExitWarning;
            }
            Boolean startCheckPointIsInSector1 = true;
            // here we assume the end check point will be in sector 1 (after the s/f line)
            if (distanceStartCheckPoint < 0)
            {
                startCheckPointIsInSector1 = false;
                distanceStartCheckPoint = currentGameState.SessionData.TrackDefinition.trackLength + distanceStartCheckPoint;
            }

            foreach (KeyValuePair<Object, OpponentData> opponent in currentGameState.OpponentData)
            {
                if (opponent.Value.OpponentLapData.Count > 0 && !opponent.Value.isEnteringPits() && !opponent.Value.isExitingPits() &&
                    ((startCheckPointIsInSector1 && opponent.Value.DistanceRoundTrack > distanceStartCheckPoint && opponent.Value.DistanceRoundTrack < distanceEndCheckPoint) ||
                     (!startCheckPointIsInSector1 && (opponent.Value.DistanceRoundTrack > distanceStartCheckPoint || opponent.Value.DistanceRoundTrack < distanceEndCheckPoint))))
                {
                    return true;
                }
            }
            return false;
        }
Ejemplo n.º 23
0
        protected override void triggerInternal(GameStateData previousGameState, GameStateData currentGameState)
        {
            if (currentGameState.CarDamageData.DamageEnabled)
            {
                aeroDamage = currentGameState.CarDamageData.OverallAeroDamage;
                trannyDamage = currentGameState.CarDamageData.OverallTransmissionDamage;
                engineDamage = currentGameState.CarDamageData.OverallEngineDamage;
                if (enableBrakeDamageMessages)
                {
                    if (currentGameState.CarDamageData.BrakeDamageStatus.hasValueAtLevel(DamageLevel.DESTROYED))
                    {
                        maxBrakeDamage = DamageLevel.DESTROYED;
                    }
                    else if (currentGameState.CarDamageData.BrakeDamageStatus.hasValueAtLevel(DamageLevel.MAJOR))
                    {
                        maxBrakeDamage = DamageLevel.MAJOR;
                    }
                    else if (currentGameState.CarDamageData.BrakeDamageStatus.hasValueAtLevel(DamageLevel.MINOR))
                    {
                        maxBrakeDamage = DamageLevel.MINOR;
                    }
                    else if (currentGameState.CarDamageData.BrakeDamageStatus.hasValueAtLevel(DamageLevel.TRIVIAL))
                    {
                        maxBrakeDamage = DamageLevel.TRIVIAL;
                    }
                }

                if (enableSuspensionDamageMessages)
                {
                    if (currentGameState.CarDamageData.SuspensionDamageStatus.hasValueAtLevel(DamageLevel.DESTROYED))
                    {
                        maxSuspensionDamage = DamageLevel.DESTROYED;
                    }
                    else if (currentGameState.CarDamageData.SuspensionDamageStatus.hasValueAtLevel(DamageLevel.MAJOR))
                    {
                        maxSuspensionDamage = DamageLevel.MAJOR;
                    }
                    else if (currentGameState.CarDamageData.SuspensionDamageStatus.hasValueAtLevel(DamageLevel.MINOR))
                    {
                        maxSuspensionDamage = DamageLevel.MINOR;
                    }
                    else if (currentGameState.CarDamageData.SuspensionDamageStatus.hasValueAtLevel(DamageLevel.TRIVIAL))
                    {
                        maxSuspensionDamage = DamageLevel.TRIVIAL;
                    }
                    isMissingWheel = !currentGameState.PitData.InPitlane && (!currentGameState.TyreData.LeftFrontAttached || !currentGameState.TyreData.RightFrontAttached ||
                            !currentGameState.TyreData.LeftRearAttached || !currentGameState.TyreData.RightRearAttached);
                }

                if (engineDamage < getLastReportedDamageLevel(Component.ENGINE))
                {
                    resetReportedDamage(Component.ENGINE, engineDamage);
                }
                if (trannyDamage < getLastReportedDamageLevel(Component.TRANNY))
                {
                    resetReportedDamage(Component.TRANNY, trannyDamage);
                }
                if (maxSuspensionDamage < getLastReportedDamageLevel(Component.SUSPENSION))
                {
                    resetReportedDamage(Component.SUSPENSION, maxSuspensionDamage);
                }
                if (maxBrakeDamage < getLastReportedDamageLevel(Component.BRAKES))
                {
                    resetReportedDamage(Component.BRAKES, maxBrakeDamage);
                }
                if (aeroDamage < getLastReportedDamageLevel(Component.AERO))
                {
                    resetReportedDamage(Component.AERO, aeroDamage);
                }

                minDamageToReport = (DamageLevel)Math.Max((int)engineDamage, Math.Max((int)trannyDamage, Math.Max((int)maxSuspensionDamage, Math.Max((int)maxBrakeDamage, (int) aeroDamage))));

                Tuple<Component, DamageLevel> worstUnreportedDamage = getWorstUnreportedDamage();
                if (worstUnreportedDamage != null && worstUnreportedDamage.Item2 >= minDamageToReport)
                {
                    if (damageToReportNext == null || worstUnreportedDamage.Item1 != damageToReportNext.Item1 || worstUnreportedDamage.Item2 != damageToReportNext.Item2)
                    {
                        timeWhenDamageLastChanged = currentGameState.Now;
                        damageToReportNext = worstUnreportedDamage;
                    }
                    else if (timeWhenDamageLastChanged.Add(timeToWaitForDamageToSettle) < currentGameState.Now)
                    {
                        Console.WriteLine("reporting ...");
                        Console.WriteLine(damageToReportNext.Item1 + ", " + damageToReportNext.Item2);
                        if (reportedDamagesLevels.ContainsKey(damageToReportNext.Item1))
                        {
                            reportedDamagesLevels[damageToReportNext.Item1] = damageToReportNext.Item2;
                        }
                        else
                        {
                            reportedDamagesLevels.Add(damageToReportNext.Item1, damageToReportNext.Item2);
                        }
                        if (enableDamageMessages)
                        {
                            playDamageToReport();
                        }
                    }
                }
            }
        }
Ejemplo n.º 24
0
        protected override void triggerInternal(GameStateData previousGameState, GameStateData currentGameState)
        {
            if (currentGameState.SessionData.IsNewLap)
            {
                timeLeftFrontIsLockedForLap = 0;
                timeRightFrontIsLockedForLap = 0;
                timeLeftRearIsLockedForLap = 0;
                timeRightRearIsLockedForLap = 0;
                timeLeftFrontIsSpinningForLap = 0;
                timeRightFrontIsSpinningForLap = 0;
                timeLeftRearIsSpinningForLap = 0;
                timeRightRearIsSpinningForLap = 0;
                if (warnedOnLockingForLap)
                {
                    totalLockupThresholdForNextLap = totalLockupThresholdForNextLap + 1;
                }
                else
                {
                    totalLockupThresholdForNextLap = initialTotalLapLockupThreshold;
                }
                if (warnedOnWheelspinForLap)
                {
                    totalWheelspinThresholdForNextLap = totalWheelspinThresholdForNextLap + 1;
                }
                else
                {
                    totalWheelspinThresholdForNextLap = initialTotalWheelspinThreshold;
                }
                warnedOnLockingForLap = false;
                warnedOnWheelspinForLap = false;
            }
            if (previousGameState != null && currentGameState.Ticks > previousGameState.Ticks)
            {
                addLockingAndSpinningData(currentGameState.TyreData, previousGameState.Ticks, currentGameState.Ticks);
            }

            if (currentGameState.Now > nextLockingAndSpinningCheck)
            {
                if (enableBrakeLockWarnings)
                {
                    checkLocking();
                }
                if (enableWheelSpinWarnings)
                {
                    checkWheelSpinning();
                }
                nextLockingAndSpinningCheck = currentGameState.Now.Add(lockingAndSpinningCheckInterval);
            }

            if (currentGameState.TyreData.TireWearActive)
            {
                leftFrontWearPercent = currentGameState.TyreData.FrontLeftPercentWear;
                leftRearWearPercent = currentGameState.TyreData.RearLeftPercentWear;
                rightFrontWearPercent = currentGameState.TyreData.FrontRightPercentWear;
                rightRearWearPercent = currentGameState.TyreData.RearRightPercentWear;

                currentTyreConditionStatus = currentGameState.TyreData.TyreConditionStatus;
                currentTyreTempStatus = currentGameState.TyreData.TyreTempStatus;
                if (isBrakeTempPeakForLap(currentGameState.TyreData.LeftFrontBrakeTemp,
                    currentGameState.TyreData.RightFrontBrakeTemp, currentGameState.TyreData.LeftRearBrakeTemp,
                    currentGameState.TyreData.RightRearBrakeTemp))
                {
                    currentBrakeTempStatus = currentGameState.TyreData.BrakeTempStatus;
                }

                completedLaps = currentGameState.SessionData.CompletedLaps;
                lapsInSession = currentGameState.SessionData.SessionNumberOfLaps;
                timeInSession = currentGameState.SessionData.SessionRunTime;
                timeElapsed = currentGameState.SessionData.SessionRunningTime;

                if (currentGameState.PitData.InPitlane && !currentGameState.SessionData.LeaderHasFinishedRace)
                {
                    if (currentGameState.SessionData.SessionType == SessionType.Race && enableTyreWearWarnings && !reportedTyreWearForCurrentPitEntry)
                    {
                        //reportCurrentTyreConditionStatus(false, true);
                        // sounds shit...
                        reportedTyreWearForCurrentPitEntry = true;
                    }
                }
                else
                {
                    reportedTyreWearForCurrentPitEntry = false;
                }
                if (currentGameState.SessionData.IsNewLap && !currentGameState.PitData.InPitlane && enableTyreWearWarnings && !currentGameState.SessionData.LeaderHasFinishedRace)
                {
                    reportCurrentTyreConditionStatus(false, false);
                }
                if (!currentGameState.PitData.InPitlane && !reportedEstimatedTimeLeft && enableTyreWearWarnings && !currentGameState.SessionData.LeaderHasFinishedRace)
                {
                    reportEstimatedTyreLife(33, false);
                }
                // if the tyre wear has actually decreased, reset the 'reportdEstimatedTyreWear flag - assume this means the tyres have been changed
                if (previousGameState != null && (currentGameState.TyreData.FrontLeftPercentWear < previousGameState.TyreData.FrontLeftPercentWear ||
                    currentGameState.TyreData.FrontRightPercentWear < previousGameState.TyreData.FrontRightPercentWear ||
                    currentGameState.TyreData.RearRightPercentWear < previousGameState.TyreData.RearRightPercentWear ||
                    currentGameState.TyreData.RearLeftPercentWear < previousGameState.TyreData.RearLeftPercentWear))
                {
                    reportedEstimatedTimeLeft = true;
                }

                if (enableTyreTempWarnings && !currentGameState.SessionData.LeaderHasFinishedRace &&
                    !currentGameState.PitData.InPitlane &&
                    currentGameState.SessionData.CompletedLaps >= lapsIntoSessionBeforeTempMessage && currentGameState.SessionData.IsNewLap)
                {
                    reportCurrentTyreTempStatus(false);
                }
                if (!currentGameState.SessionData.LeaderHasFinishedRace &&
                     ((checkBrakesAtSector == 1 && currentGameState.SessionData.IsNewLap) ||
                     ((currentGameState.SessionData.IsNewSector && currentGameState.SessionData.SectorNumber == checkBrakesAtSector))))
                {
                    if (!currentGameState.PitData.InPitlane && currentGameState.SessionData.CompletedLaps >= lapsIntoSessionBeforeTempMessage)
                    {
                        if (enableBrakeTempWarnings)
                        {
                            reportCurrentBrakeTempStatus(false);
                        }
                    }
                    peakBrakeTempForLap = 0;
                }
            }
        }
Ejemplo n.º 25
0
 public override bool isMessageStillValid(String eventSubType, GameStateData currentGameState, Dictionary<String, Object> validationData)
 {
     return applicableSessionPhases.Contains(currentGameState.SessionData.SessionPhase);
 }
Ejemplo n.º 26
0
 private Boolean checkGaps(GameStateData currentGameState, int numLapsLeft, Boolean checkPushToGain, Boolean checkPushToHold)
 {
     if (checkPushToGain && currentGameState.SessionData.Position > 1)
     {
         float opponentInFrontBestLap = getOpponentBestLap(currentGameState.SessionData.Position - 1, lapsToCountBackForOpponentBest, currentGameState);
         if (opponentInFrontBestLap > 0 &&
             (opponentInFrontBestLap - currentGameState.SessionData.PlayerLapTimeSessionBest) * numLapsLeft > currentGameState.SessionData.TimeDeltaFront)
         {
             // going flat out, we're going to catch the guy ahead us before the end
             if (currentGameState.SessionData.Position == 2)
             {
                 audioPlayer.queueClip(new QueuedMessage(folderPushToGetWin, 0, this));
             }
             else if (currentGameState.SessionData.Position == 3)
             {
                 audioPlayer.queueClip(new QueuedMessage(folderPushToGetSecond, 0, this));
             }
             else if (currentGameState.SessionData.Position == 4)
             {
                 audioPlayer.queueClip(new QueuedMessage(folderPushToGetThird, 0, this));
             }
             else
             {
                 audioPlayer.queueClip(new QueuedMessage(folderPushToImprove, 0, this));
             }
             return true;
         }
     }
     if (checkPushToHold && !currentGameState.isLast())
     {
         float opponentBehindBestLap = getOpponentBestLap(currentGameState.SessionData.Position + 1, lapsToCountBackForOpponentBest, currentGameState);
         if (opponentBehindBestLap > 0 &&
             (currentGameState.SessionData.PlayerLapTimeSessionBest - opponentBehindBestLap) * numLapsLeft > currentGameState.SessionData.TimeDeltaBehind)
         {
             // even with us going flat out, the guy behind is going to catch us before the end
             Console.WriteLine("might lose this position. Player best lap = " + currentGameState.SessionData.PlayerLapTimeSessionBest + " laps left = " + numLapsLeft +
                 " opponent best lap = " + opponentBehindBestLap + " time delta = " + currentGameState.SessionData.TimeDeltaBehind);
             audioPlayer.queueClip(new QueuedMessage(folderPushToHoldPosition, 0, this));
             return true;
         }
     }
     return false;
 }
Ejemplo n.º 27
0
        public Boolean Run(String filenameToRun, int interval, Boolean dumpToFile)
        {
            loadDataFromFile = false;
            audioPlayer.mute = false;
            if (filenameToRun != null && System.Diagnostics.Debugger.IsAttached)
            {
                loadDataFromFile = true;
                spotterEnabled = false;
                if (interval > 0)
                {
                    _timeInterval = TimeSpan.FromMilliseconds(interval);
                    audioPlayer.mute = false;
                }
                else
                {
                    _timeInterval = TimeSpan.Zero;
                    audioPlayer.mute = true;
                }
                dumpToFile = false;
            }

            gameStateMapper = GameStateReaderFactory.getInstance().getGameStateMapper(gameDefinition);
            gameStateMapper.setSpeechRecogniser(speechRecogniser);
            gameDataReader = GameStateReaderFactory.getInstance().getGameStateReader(gameDefinition);
            gameDataReader.dumpToFile = System.Diagnostics.Debugger.IsAttached && dumpToFile;
            if (gameDefinition.spotterName != null)
            {
                spotter = (Spotter)Activator.CreateInstance(Type.GetType(gameDefinition.spotterName),
                    audioPlayer, spotterEnabled);
            }
            else
            {
                Console.WriteLine("No spotter defined for game " + gameDefinition.friendlyName);
                spotter = null;
            }
            running = true;
            DateTime nextRunTime = DateTime.Now;
            if (!audioPlayer.initialised)
            {
                Console.WriteLine("Failed to initialise audio player");
                return false;
            }
            audioPlayer.startMonitor();
            Boolean attemptedToRunGame = false;

            int threadSleepTime = ((int)_timeInterval.Milliseconds / 10) + 1;
            Console.WriteLine("Polling for shared data every " + _timeInterval.Milliseconds + "ms, pausing " + threadSleepTime + "ms between invocations");
            Boolean sessionFinished = false;

            while (running)
            {
                DateTime now = DateTime.Now;
                if (now > nextRunTime)
                {
                    nextRunTime = DateTime.Now.Add(_timeInterval);
                    if (!loadDataFromFile)
                    {
                        if (gameDefinition.processName == null || Utilities.IsGameRunning(gameDefinition.processName))
                        {
                            if (!mapped)
                            {
                                mapped = gameDataReader.Initialise();
                            }
                        }
                        else if (UserSettings.GetUserSettings().getBoolean(gameDefinition.gameStartEnabledProperty) && !attemptedToRunGame)
                        {
                            Utilities.runGame(UserSettings.GetUserSettings().getString(gameDefinition.gameStartCommandProperty),
                                UserSettings.GetUserSettings().getString(gameDefinition.gameStartCommandOptionsProperty));
                            attemptedToRunGame = true;
                        }
                    }

                    if (loadDataFromFile || mapped)
                    {
                        stateCleared = false;
                        Object rawGameData;
                        if (loadDataFromFile)
                        {
                            rawGameData = gameDataReader.ReadGameDataFromFile(filenameToRun);
                            if (rawGameData == null)
                            {
                                Console.WriteLine("Reached the end of the data file, sleeping to clear queued messages");
                                Thread.Sleep(5000);
                                audioPlayer.purgeQueues();
                                running = false;
                                continue;
                            }
                        }
                        else
                        {
                            rawGameData = gameDataReader.ReadGameData(false);
                        }
                        gameStateMapper.versionCheck(rawGameData);

                        GameStateData nextGameState = null;
                        try
                        {
                            nextGameState = gameStateMapper.mapToGameStateData(rawGameData, currentGameState);
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine("Error mapping game data: " + e.StackTrace);
                        }

                        if (nextGameState != null)
                        {
                            previousGameState = currentGameState;
                            currentGameState = nextGameState;
                            if (!sessionFinished && currentGameState.SessionData.SessionPhase == SessionPhase.Finished
                                && previousGameState != null)
                            {
                                audioPlayer.purgeQueues();
                                if (displaySessionLapTimes)
                                {
                                    Console.WriteLine("Session lap times:");
                                    Console.WriteLine(String.Join(";", currentGameState.SessionData.formattedPlayerLapTimes));
                                }
                                sessionEndMessages.trigger(previousGameState.SessionData.SessionRunningTime, previousGameState.SessionData.SessionType, currentGameState.SessionData.SessionPhase,
                                    previousGameState.SessionData.Position, previousGameState.SessionData.NumCarsAtStartOfSession, previousGameState.SessionData.CompletedLaps,
                                    previousGameState.SessionData.IsDisqualified);
                                audioPlayer.closeChannel();
                                sessionFinished = true;
                                audioPlayer.disablePearlsOfWisdom = false;
                                if (loadDataFromFile)
                                {
                                    Thread.Sleep(2000);
                                }
                            }
                            float prevTime = previousGameState == null ? 0 : previousGameState.SessionData.SessionRunningTime;
                            if (currentGameState.SessionData.IsNewSession)
                            {
                                audioPlayer.disablePearlsOfWisdom = false;
                                displayNewSessionInfo(currentGameState);
                                sessionFinished = false;
                                if (!stateCleared)
                                {
                                    Console.WriteLine("Clearing game state...");
                                    audioPlayer.purgeQueues();
                                    audioPlayer.closeChannel();
                                    foreach (KeyValuePair<String, AbstractEvent> entry in eventsList)
                                    {
                                        entry.Value.clearState();
                                    }
                                    faultingEvents.Clear();
                                    faultingEventsCount.Clear();
                                    stateCleared = true;
                                }
                                if (enableDriverNames)
                                {
                                    List<String> rawDriverNames = currentGameState.getRawDriverNames();
                                    if (currentGameState.SessionData.DriverRawName != null && currentGameState.SessionData.DriverRawName.Length > 0 &&
                                        !rawDriverNames.Contains(currentGameState.SessionData.DriverRawName))
                                    {
                                        rawDriverNames.Add(currentGameState.SessionData.DriverRawName);
                                    }
                                    if (rawDriverNames.Count > 0)
                                    {
                                        List<String> usableDriverNames = DriverNameHelper.getUsableDriverNames(rawDriverNames, audioPlayer.soundFilesPath);
                                        if (speechRecogniser != null && speechRecogniser.initialised)
                                        {
                                            speechRecogniser.addOpponentSpeechRecognition(usableDriverNames, enableDriverNames);
                                        }
                                        audioPlayer.cacheDriverNames(usableDriverNames);
                                    }
                                }
                            }
                            else if (!sessionFinished && previousGameState != null &&
                                        (currentGameState.SessionData.SessionRunningTime > previousGameState.SessionData.SessionRunningTime ||
                                        (previousGameState != null && previousGameState.SessionData.SessionPhase != currentGameState.SessionData.SessionPhase)))
                            {
                                if (spotter != null)
                                {
                                    spotter.unpause();
                                }
                                if (currentGameState.SessionData.IsNewLap)
                                {
                                    currentGameState.display();
                                }
                                stateCleared = false;
                                foreach (KeyValuePair<String, AbstractEvent> entry in eventsList)
                                {
                                    if (entry.Value.isApplicableForCurrentSessionAndPhase(currentGameState.SessionData.SessionType, currentGameState.SessionData.SessionPhase))
                                    {
                                        triggerEvent(entry.Key, entry.Value, previousGameState, currentGameState);
                                    }
                                }
                                if (spotter != null && spotterEnabled && !spotterIsRunning && !loadDataFromFile)
                                {
                                    Console.WriteLine("********** starting spotter***********");
                                    spotter.clearState();
                                    startSpotterThread();
                                }
                                else if (spotterIsRunning && !spotterEnabled)
                                {
                                    runSpotterThread = false;
                                }
                            }
                            else if (spotter != null)
                            {
                                spotter.pause();
                            }
                        }
                    }
                }
                else
                {
                    Thread.Sleep(threadSleepTime);
                    continue;
                }
            }
            foreach (KeyValuePair<String, AbstractEvent> entry in eventsList)
            {
                entry.Value.clearState();
            }
            if (spotter != null)
            {
                spotter.clearState();
            }
            stateCleared = true;
            currentGameState = null;
            previousGameState = null;
            sessionFinished = false;
            audioPlayer.stopMonitor();
            audioPlayer.disablePearlsOfWisdom = false;
            if (gameDataReader != null && gameDataReader.dumpToFile)
            {
                gameDataReader.DumpRawGameData();
            }
            gameDataReader.stop();
            return true;
        }
        protected override void triggerInternal(GameStateData previousGameState, GameStateData currentGameState)
        {
            // DRS:
            if (drsMessagesEnabled && currentGameState.OvertakingAids.DrsEnabled)
            {
                if (trackDistanceToCheckDRSGapFrontAt == -1 && currentGameState.SessionData.TrackDefinition != null)
                {
                    trackDistanceToCheckDRSGapFrontAt = currentGameState.SessionData.TrackDefinition.trackLength / 2;
                }
                if (currentGameState.SessionData.IsNewLap)
                {
                    if (drsAvailableOnThisLap && !hasUsedDrsOnThisLap)
                    {
                        audioPlayer.queueClip(new QueuedMessage("missed_available_drs", MessageContents(folderDontForgetDRS), 0, this));
                    }
                    drsAvailableOnThisLap = currentGameState.OvertakingAids.DrsAvailable;
                    hasUsedDrsOnThisLap = false;
                    playedGetCloserForDRSOnThisLap = false;
                    playedOpponentHasDRSOnThisLap = false;
                }
                if (currentGameState.OvertakingAids.DrsEngaged)
                {
                    hasUsedDrsOnThisLap = true;
                }
                if (!hasUsedDrsOnThisLap && !drsAvailableOnThisLap && !playedGetCloserForDRSOnThisLap &&
                    currentGameState.PositionAndMotionData.DistanceRoundTrack > trackDistanceToCheckDRSGapFrontAt)
                {
                    if (currentGameState.SessionData.TimeDeltaFront < 1.3 + currentGameState.OvertakingAids.DrsRange &&
                        currentGameState.SessionData.TimeDeltaFront >= 0.6 + currentGameState.OvertakingAids.DrsRange)
                    {
                        audioPlayer.queueClip(new QueuedMessage("drs_a_second_out_of_range", MessageContents(folderASecondOffDRSRange), 0, this));
                        playedGetCloserForDRSOnThisLap = true;
                    }
                    else if (currentGameState.SessionData.TimeDeltaFront < 0.6 + currentGameState.OvertakingAids.DrsRange &&
                        currentGameState.SessionData.TimeDeltaFront >= 0.1 + currentGameState.OvertakingAids.DrsRange)
                    {
                        audioPlayer.queueClip(new QueuedMessage("drs_a_few_tenths_out_of_range", MessageContents(folderAFewTenthsOffDRSRange), 0, this));
                        playedGetCloserForDRSOnThisLap = true;
                    }
                }
                if (!playedOpponentHasDRSOnThisLap && currentGameState.SessionData.TimeDeltaBehind <= currentGameState.OvertakingAids.DrsRange &&
                    currentGameState.SessionData.LapTimeCurrent > currentGameState.SessionData.TimeDeltaBehind &&
                    currentGameState.SessionData.LapTimeCurrent < currentGameState.SessionData.TimeDeltaBehind + 1)
                {
                    audioPlayer.queueClip(new QueuedMessage("opponent_has_drs", MessageContents(folderGuyBehindHasDRS), 0, this));
                    playedOpponentHasDRSOnThisLap = true;
                }
            }

            // push to pass
            if (ptpMessagesEnabled && previousGameState != null)
            {
                if (previousGameState.OvertakingAids.PushToPassEngaged && !currentGameState.OvertakingAids.PushToPassEngaged &&
                    currentGameState.OvertakingAids.PushToPassActivationsRemaining == 0)
                {
                    audioPlayer.queueClip(new QueuedMessage("no_push_to_pass_remaining", MessageContents(folderNoActivationsRemaining), 0, this));
                    pushToPassActivationsRemaining = 0;
                }
                else if (previousGameState.OvertakingAids.PushToPassWaitTimeLeft > 0 && currentGameState.OvertakingAids.PushToPassWaitTimeLeft == 0)
                {
                    if (currentGameState.OvertakingAids.PushToPassActivationsRemaining == 1)
                    {
                        audioPlayer.queueClip(new QueuedMessage("one_push_to_pass_remaining", MessageContents(
                            folderPushToPassNowAvailable, folderOneActivationRemaining), 0, this));
                        pushToPassActivationsRemaining = 1;
                    }
                    else
                    {
                        audioPlayer.queueClip(new QueuedMessage("one_push_to_pass_remaining", MessageContents(folderPushToPassNowAvailable,
                            QueuedMessage.folderNameNumbersStub + currentGameState.OvertakingAids.PushToPassActivationsRemaining, folderActivationsRemaining), 0, this));
                        pushToPassActivationsRemaining = currentGameState.OvertakingAids.PushToPassActivationsRemaining;
                    }
                }
            }
        }
Ejemplo n.º 29
0
 private void triggerEvent(String eventName, AbstractEvent abstractEvent, GameStateData previousGameState, GameStateData currentGameState)
 {
     try
     {
         abstractEvent.trigger(previousGameState, currentGameState);
     }
     catch (Exception e)
     {
         if (faultingEventsCount.ContainsKey(eventName))
         {
             faultingEventsCount[eventName]++;
             if (faultingEventsCount[eventName] > 5)
             {
                 Console.WriteLine("Event " + eventName +
                     " has failed > 5 times in this session");
             }
         }
         if (!faultingEvents.ContainsKey(eventName))
         {
             Console.WriteLine("Event " + eventName + " threw exception " + e.Message);
             Console.WriteLine("This is the first time this event has failed in this session");
             faultingEvents.Add(eventName, e.Message);
             faultingEventsCount.Add(eventName, 1);
         }
         else if (faultingEvents[eventName] != e.Message)
         {
             Console.WriteLine("Event " + eventName + " threw a different exception: " + e.Message);
             faultingEvents[eventName] = e.Message;
         }
     }
 }
Ejemplo n.º 30
0
        protected override void triggerInternal(GameStateData previousGameState, GameStateData currentGameState)
        {
            if (currentGameState.SessionData.SessionType == SessionType.Race && previousGameState != null &&
                currentGameState.PenaltiesData.HasDriveThrough || currentGameState.PenaltiesData.HasStopAndGo || currentGameState.PenaltiesData.HasTimeDeduction)
            {
                if (currentGameState.PenaltiesData.HasDriveThrough && !previousGameState.PenaltiesData.HasDriveThrough)
                {
                    lapsCompleted = currentGameState.SessionData.CompletedLaps;
                    // this is a new penalty
                    audioPlayer.queueClip(new QueuedMessage(folderNewPenaltyDriveThrough, 0, this));
                    // queue a '3 laps to serve penalty' message - this might not get played
                    audioPlayer.queueClip(new QueuedMessage(folderThreeLapsToServe, 20, this));
                    // we don't already have a penalty
                    if (penaltyLap == -1 || !hasOutstandingPenalty)
                    {
                        penaltyLap = currentGameState.SessionData.CompletedLaps;
                    }
                    hasOutstandingPenalty = true;
                    hasHadAPenalty = true;
                }
                else if (currentGameState.PenaltiesData.HasStopAndGo && !previousGameState.PenaltiesData.HasStopAndGo)
                {
                    lapsCompleted = currentGameState.SessionData.CompletedLaps;
                    // this is a new penalty
                    audioPlayer.queueClip(new QueuedMessage(folderNewPenaltyStopGo, 0, this));
                    // queue a '3 laps to serve penalty' message - this might not get played
                    audioPlayer.queueClip(new QueuedMessage(folderThreeLapsToServe, 20, this));
                    // we don't already have a penalty
                    if (penaltyLap == -1 || !hasOutstandingPenalty)
                    {
                        penaltyLap = currentGameState.SessionData.CompletedLaps;
                    }
                    hasOutstandingPenalty = true;
                    hasHadAPenalty = true;
                }
                else if (currentGameState.PitData.InPitlane && currentGameState.PitData.OnOutLap && !playedNotServedPenalty &&
                    (currentGameState.PenaltiesData.HasStopAndGo || currentGameState.PenaltiesData.HasDriveThrough))
                {
                    // we've exited the pits but there's still an outstanding penalty
                    audioPlayer.queueClip(new QueuedMessage(folderPenaltyNotServed, 3, this));
                    playedNotServedPenalty = true;
                }
                else if (currentGameState.SessionData.IsNewLap && (currentGameState.PenaltiesData.HasStopAndGo || currentGameState.PenaltiesData.HasDriveThrough))
                {
                    // TODO: variable number of laps to serve penalty...

                    lapsCompleted = currentGameState.SessionData.CompletedLaps;
                    if (lapsCompleted - penaltyLap == 3 && !currentGameState.PitData.InPitlane)
                    {
                        // run out of laps, an not in the pitlane
                        audioPlayer.queueClip(new QueuedMessage(folderDisqualified, 5, this));
                    }
                    else if (lapsCompleted - penaltyLap == 2 && currentGameState.PenaltiesData.HasDriveThrough)
                    {
                        audioPlayer.queueClip(new QueuedMessage(folderOneLapToServeDriveThrough, pitstopDelay, this));
                    }
                    else if (lapsCompleted - penaltyLap == 2 && currentGameState.PenaltiesData.HasStopAndGo)
                    {
                        audioPlayer.queueClip(new QueuedMessage(folderOneLapToServeStopGo, pitstopDelay, this));
                    }
                    else if (lapsCompleted - penaltyLap == 1)
                    {
                        audioPlayer.queueClip(new QueuedMessage(folderTwoLapsToServe, pitstopDelay, this));
                    }
                }
                else if (!playedPitNow && currentGameState.SessionData.SectorNumber == 3 && currentGameState.PenaltiesData.HasStopAndGo && lapsCompleted - penaltyLap == 2)
                {
                    playedPitNow = true;
                    audioPlayer.queueClip(new QueuedMessage(folderPitNowStopGo, 6, this));
                }
                else if (!playedPitNow && currentGameState.SessionData.SectorNumber == 3 && currentGameState.PenaltiesData.HasDriveThrough && lapsCompleted - penaltyLap == 2)
                {
                    playedPitNow = true;
                    audioPlayer.queueClip(new QueuedMessage(folderPitNowDriveThrough, 6, this));
                }
                else if (!playedTimePenaltyMessage && currentGameState.PenaltiesData.HasTimeDeduction)
                {
                    playedTimePenaltyMessage = true;
                    audioPlayer.queueClip(new QueuedMessage(folderTimePenalty, 0, this));
                }
            }
            else if (currentGameState.PositionAndMotionData.CarSpeed > 1 && playCutTrackWarnings && currentGameState.SessionData.SessionType != SessionType.Race &&
              !currentGameState.SessionData.CurrentLapIsValid && previousGameState != null && previousGameState.SessionData.CurrentLapIsValid)
            {
                cutTrackWarningsCount = currentGameState.PenaltiesData.CutTrackWarnings;
                // don't warn about cut track if the AI is driving
                if (currentGameState.ControlData.ControlType != ControlType.AI &&
                    lastCutTrackWarningTime.Add(cutTrackWarningFrequency) < currentGameState.Now)
                {
                    lastCutTrackWarningTime = currentGameState.Now;
                    audioPlayer.queueClip(new QueuedMessage(folderLapDeleted, 2, this));
                    clearPenaltyState();
                }
            }
            else if (currentGameState.PositionAndMotionData.CarSpeed > 1 && playCutTrackWarnings &&
                currentGameState.PenaltiesData.CutTrackWarnings > cutTrackWarningsCount)
            {
                cutTrackWarningsCount = currentGameState.PenaltiesData.CutTrackWarnings;
                if (currentGameState.ControlData.ControlType != ControlType.AI &&
                    lastCutTrackWarningTime.Add(cutTrackWarningFrequency) < currentGameState.Now)
                {
                    lastCutTrackWarningTime = currentGameState.Now;
                    if (currentGameState.SessionData.SessionType == SessionType.Race)
                    {
                        audioPlayer.queueClip(new QueuedMessage(folderCutTrackInRace, 2, this));
                    }
                    else
                    {
                        audioPlayer.queueClip(new QueuedMessage(folderCutTrackPracticeOrQual, 2, this));
                    }
                    clearPenaltyState();
                }
            }
            else
            {
                clearPenaltyState();
            }
            if (currentGameState.SessionData.SessionType == SessionType.Race && previousGameState != null &&
                ((previousGameState.PenaltiesData.HasStopAndGo && !currentGameState.PenaltiesData.HasStopAndGo) ||
                (previousGameState.PenaltiesData.HasDriveThrough && !currentGameState.PenaltiesData.HasDriveThrough)))
            {
                audioPlayer.queueClip(new QueuedMessage(folderPenaltyServed, 0, null));
            }
        }