public AudioPlayer(CrewChief crewChief) { this.crewChief = crewChief; String soundPackLocationOverride = UserSettings.GetUserSettings().getString("override_default_sound_pack_location"); if (soundPackLocationOverride != null && soundPackLocationOverride.Length > 0) { soundFilesPath = soundPackLocationOverride; } else { soundFilesPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\CrewChiefV4\sounds"; } DirectoryInfo soundDirectory = new DirectoryInfo(soundFilesPath); if (soundDirectory.Exists) { soundPackVersion = getSoundPackVersion(soundDirectory); driverNamesVersion = getDriverNamesVersion(soundDirectory); soundPackLanguage = getSoundPackLanguage(soundDirectory); } else { soundDirectory.Create(); } }
override protected 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 && !currentGameState.PitData.InPitlane) { 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.playMessage(new QueuedMessage(folderTrafficBehindExitingPits, 0, this)); } else { audioPlayer.playMessage(new QueuedMessage(folderPushExitingPits, 0, this)); } // now try and report the current brake and tyre temp status try { if (brakeTempWarningOnPitExit) { ((TyreMonitor)CrewChief.getEvent("TyreMonitor")).reportBrakeTempStatus(false, false); } if (tyreTempWarningOnPitExit) { ((TyreMonitor)CrewChief.getEvent("TyreMonitor")).reportCurrentTyreTempStatus(false); } } catch (Exception e) { Console.WriteLine("Failed to report brake temp status on pit exit"); } } }
override protected void triggerInternal(GameStateData previousGameState, GameStateData currentGameState) { if (GameStateData.onManualFormationLap) { return; } if (currentGameState.SessionData.IsNewLap && currentGameState.PositionAndMotionData.CarSpeed > maxSpeedWhenCrossingLine) { maxSpeedWhenCrossingLine = currentGameState.PositionAndMotionData.CarSpeed; // the distance at which we check if there's a car exiting the pits will be speed dependent. // The faster we are over the line, the more notice we'll need. * 3 is a number I pulled out of my arse, // it may be shit. distanceBeforeStartLineToWarnOfPitExit = maxSpeedWhenCrossingLine * 3; } Boolean checkPushToGain = currentGameState.SessionData.SessionRunningTime - currentGameState.SessionData.GameTimeAtLastPositionFrontChange < minTimeToBeInThisPosition; Boolean checkPushToHold = currentGameState.SessionData.SessionRunningTime - currentGameState.SessionData.GameTimeAtLastPositionBehindChange < minTimeToBeInThisPosition; if (currentGameState.SessionData.SessionType == SessionType.Race && !currentGameState.PitData.InPitlane) { if ((checkPushToGain || checkPushToHold) && !playedNearEndTimePush && currentGameState.SessionData.SessionHasFixedTime && 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.SessionData.HasExtraLap) { numLapsLeft = numLapsLeft + 1; } playedNearEndTimePush = checkGaps(currentGameState, numLapsLeft, checkPushToGain, checkPushToHold); } else if ((checkPushToGain || checkPushToHold) && !playedNearEndLapsPush && !currentGameState.SessionData.SessionHasFixedTime && ((currentGameState.SessionData.SessionLapsRemaining <= 4 && currentGameState.SessionData.TrackDefinition.trackLengthClass <= TrackData.TrackLengthClass.MEDIUM) || (currentGameState.SessionData.SessionLapsRemaining <= 2 && currentGameState.SessionData.TrackDefinition.trackLengthClass <= TrackData.TrackLengthClass.LONG) || (currentGameState.SessionData.SessionLapsRemaining == 1 && currentGameState.SessionData.TrackDefinition.trackLengthClass <= TrackData.TrackLengthClass.VERY_LONG))) { playedNearEndLapsPush = checkGaps(currentGameState, currentGameState.SessionData.SessionLapsRemaining, checkPushToGain, checkPushToHold); } } if (currentGameState.PitData.IsAtPitExit && currentGameState.PositionAndMotionData.CarSpeed > 5) { // we've just been handed control back after a pitstop if (currentGameState.SessionData.SessionRunningTime > 30 && isOpponentApproachingPitExit(currentGameState)) { // we've exited into clean air audioPlayer.playMessageImmediately(new QueuedMessage(folderTrafficBehindExitingPits, 3, abstractEvent: this, type: SoundType.IMPORTANT_MESSAGE, priority: 0)); } else { audioPlayer.playMessageImmediately(new QueuedMessage(folderPushExitingPits, 3, abstractEvent: this, type: SoundType.IMPORTANT_MESSAGE, priority: 0)); } // now try and report the current brake and tyre temp status try { if (brakeTempWarningOnPitExit) { ((TyreMonitor)CrewChief.getEvent("TyreMonitor")).reportBrakeTempStatus(false, false); } if (tyreTempWarningOnPitExit) { ((TyreMonitor)CrewChief.getEvent("TyreMonitor")).reportCurrentTyreTempStatus(false); } } catch (Exception) { Console.WriteLine("Failed to report brake temp status on pit exit"); } if (!playedQualExitMessage && currentGameState.SessionData.SessionType == SessionType.Qualify) { playedQualExitMessage = true; if (currentGameState.SessionData.SessionNumberOfLaps > 0) { // special case for iracing - AFAIK no other games have number-of-laps in qual sessions audioPlayer.playMessageImmediately(new QueuedMessage("qual_pit_exit", 5, messageFragments: MessageContents(folderQualExitIntro, currentGameState.SessionData.SessionNumberOfLaps, folderQualExitOutroLaps), abstractEvent: this, type: SoundType.IMPORTANT_MESSAGE, priority: 0)); } else if (currentGameState.SessionData.SessionHasFixedTime) { int minutesLeft = (int)Math.Floor(currentGameState.SessionData.SessionTimeRemaining / 60f); if (minutesLeft > 1) { audioPlayer.playMessageImmediately(new QueuedMessage("qual_pit_exit", 5, messageFragments: MessageContents(folderQualExitIntro, minutesLeft, folderQualExitOutroMinutes), abstractEvent: this, type: SoundType.IMPORTANT_MESSAGE, priority: 0)); } } } } if (previousGameState != null && currentGameState.SessionData.SectorNumber == 3 && currentGameState.PositionAndMotionData.CarSpeed > 5 && !currentGameState.PitData.InPitlane && isApproachingStartLine(currentGameState.SessionData.TrackDefinition, previousGameState.PositionAndMotionData.DistanceRoundTrack, currentGameState.PositionAndMotionData.DistanceRoundTrack) && isOpponentLeavingPits(currentGameState)) { audioPlayer.playMessageImmediately(new QueuedMessage(folderOpponentExitingPits, 2, abstractEvent: this, type: SoundType.IMPORTANT_MESSAGE, priority: 0)); } }
public void execute(String recognitionResult, Boolean supressConfirmationMessage) { // blocking... Boolean isR3e = CrewChief.gameDefinition == GameDefinition.raceRoom; int multiplePressCountFromVoiceCommand = 0; if (macro.integerVariableVoiceTrigger != null && macro.integerVariableVoiceTrigger.Length > 0) { multiplePressCountFromVoiceCommand = macro.extractInt(recognitionResult, macro.startPhrase, macro.endPhrase); } foreach (CommandSet commandSet in macro.commandSets) { // only execute for the requested game - is this check sensible? if (CrewChief.gameDefinition.gameEnum.ToString().Equals(commandSet.gameDefinition) && assignmentsByGame.ContainsKey(commandSet.gameDefinition)) { Boolean isValid = checkValidAndPlayConfirmation(commandSet, supressConfirmationMessage); if (isValid) { ThreadManager.UnregisterTemporaryThread(executableCommandMacroThread); executableCommandMacroThread = new Thread(() => { // only allow macros to excute one at a time lock (ExecutableCommandMacro.mutex) { IntPtr currentForgroundWindow = GetForegroundWindow(); bool hasChangedForgroundWindow = BringGameWindowToFront(CrewChief.gameDefinition.processName, CrewChief.gameDefinition.alternativeProcessNames, currentForgroundWindow); foreach (ActionItem actionItem in commandSet.getActionItems()) { if (MacroManager.stopped) { break; } if (MacroManager.WAIT_IDENTIFIER.Equals(actionItem.extendedType)) { Thread.Sleep(actionItem.extendedTypeNumericParam); } else { int count; if (MacroManager.MULTIPLE_PRESS_IDENTIFIER.Equals(actionItem.extendedType)) { if (actionItem.extendedTypeTextParam != null) { if (MacroManager.MULTIPLE_PRESS_FROM_VOICE_TRIGGER_IDENTIFIER.Equals(actionItem.extendedTypeTextParam)) { count = multiplePressCountFromVoiceCommand; } else { count = CrewChief.getEvent(actionItem.extendedTypeTextParam).resolveMacroKeyPressCount(macro.name); } // hack for R3E: fuel menu needs 3 presses to get it from the start to 0 if (isR3e && macro.name.Contains("fuel")) { count = count + 3; } } else { count = actionItem.extendedTypeNumericParam; } } else { count = 1; } sendKeys(count, actionItem, commandSet.keyPressTime, commandSet.waitBetweenEachCommand); } } if (hasChangedForgroundWindow) { SetForegroundWindow(currentForgroundWindow); } } }); executableCommandMacroThread.Name = "CommandMacro.executableCommandMacroThread"; ThreadManager.RegisterTemporaryThread(executableCommandMacroThread); executableCommandMacroThread.Start(); } break; } } }
public static void SetCrewChief(CrewChief cc) { PlaybackModerator.crewChief = cc; }
} } }
override protected void triggerInternal(GameStateData previousGameState, GameStateData currentGameState) { if (CrewChief.gameDefinition.gameEnum != GameEnum.IRACING) { return; } lastColdFLPressure = (int)currentGameState.TyreData.FrontLeftPressure; lastColdFRPressure = (int)currentGameState.TyreData.FrontRightPressure; lastColdRLPressure = (int)currentGameState.TyreData.RearLeftPressure; lastColdRRPressure = (int)currentGameState.TyreData.RearRightPressure; maxIncidentCount = currentGameState.SessionData.MaxIncidentCount; incidentsCount = currentGameState.SessionData.CurrentIncidentCount; hasLimitedIncidents = currentGameState.SessionData.HasLimitedIncidents; licenseLevel = currentGameState.SessionData.LicenseLevel; iRating = currentGameState.SessionData.iRating; strenghtOfField = currentGameState.SessionData.StrengthOfField; fuelCapacity = currentGameState.FuelData.FuelCapacity; currentFuel = currentGameState.FuelData.FuelLeft; if (autoFuelToEnd) { if (previousGameState != null && !previousGameState.PitData.InPitlane && currentGameState.PitData.InPitlane && currentGameState.SessionData.SessionType == SessionType.Race && currentGameState.SessionData.SessionRunningTime > 15 && !previousGameState.PitData.IsInGarage && !currentGameState.PitData.JumpedToPits) { Fuel fuelEvent = (Fuel)CrewChief.getEvent("Fuel"); float litresNeeded = fuelEvent.getLitresToEndOfRace(true); if (litresNeeded == float.MaxValue) { audioPlayer.playMessage(new QueuedMessage(AudioPlayer.folderNoData, 0)); } else if (litresNeeded <= 0) { audioPlayer.playMessage(new QueuedMessage(Fuel.folderPlentyOfFuel, 0)); } else if (litresNeeded > 0) { int roundedLitresNeeded = (int)Math.Ceiling(litresNeeded); AddFuel(roundedLitresNeeded); Console.WriteLine("Auto refuel to the end of the race, adding " + roundedLitresNeeded + " liters of fuel"); if (roundedLitresNeeded > fuelCapacity - currentFuel) { // if we have a known fuel capacity and this is less than the calculated amount of fuel we need, warn about it. audioPlayer.playMessage(new QueuedMessage(Fuel.folderWillNeedToStopAgain, 0, secondsDelay: 4, abstractEvent: this)); } else { audioPlayer.playMessage(new QueuedMessage(AudioPlayer.folderFuelToEnd, 0)); } } } } /* * if (hasLimitedIncidents) * { * //play < 5 incident left warning. * if (incidentsCount >= maxIncidentCount - 5 && !playedIncidentsWarning) * { * playedIncidentsWarning = true; * audioPlayer.playMessageImmediately(new QueuedMessage("Incidents/limit", MessageContents(folderYouHave, incidentsCount, folderincidentPoints, * Pause(200), folderincidentPointslimit, maxIncidentCount), 0)); * * } * else if (incidentsCount >= maxIncidentCount - 1 && !playedLastIncidentsLeftWarning) * { * playedLastIncidentsLeftWarning = true; * //play 1 incident left warning. * } * } */ }
public override void respond(String voiceMessage) { if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.PIT_STOP_ADD)) { int amount = 0; foreach (KeyValuePair <String[], int> entry in SpeechRecogniser.numberToNumber) { foreach (String numberStr in entry.Key) { if (voiceMessage.Contains(" " + numberStr + " ")) { amount = entry.Value; break; } } } if (amount == 0) { audioPlayer.playMessageImmediately(new QueuedMessage(AudioPlayer.folderDidntUnderstand, 0)); return; } if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.LITERS)) { AddFuel(amount); audioPlayer.playMessageImmediately(new QueuedMessage("iracing_add_fuel", 0, messageFragments: MessageContents(AudioPlayer.folderAcknowlegeOK, amount, amount == 1 ? Fuel.folderLitre : Fuel.folderLitres))); } else if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.GALLONS)) { AddFuel(convertGallonsToLitres(amount)); audioPlayer.playMessageImmediately(new QueuedMessage("iracing_add_fuel", 0, messageFragments: MessageContents(AudioPlayer.folderAcknowlegeOK, amount, amount == 1 ? Fuel.folderGallon : Fuel.folderGallons))); } else { Console.WriteLine("Got fuel request with no unit, assuming " + (Fuel.fuelReportsInGallon ? " gallons" : "litres")); if (!Fuel.fuelReportsInGallon) { AddFuel(amount); audioPlayer.playMessageImmediately(new QueuedMessage("iracing_add_fuel", 0, messageFragments: MessageContents(AudioPlayer.folderAcknowlegeOK, amount, amount == 1 ? Fuel.folderLitre : Fuel.folderLitres))); } else { AddFuel(convertGallonsToLitres(amount)); audioPlayer.playMessageImmediately(new QueuedMessage("iracing_add_fuel", 0, messageFragments: MessageContents(AudioPlayer.folderAcknowlegeOK, amount, amount == 1 ? Fuel.folderGallon : Fuel.folderGallons))); } } return; } else if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.PIT_STOP_FUEL_TO_THE_END)) { Fuel fuelEvent = (Fuel)CrewChief.getEvent("Fuel"); float litresNeeded = fuelEvent.getLitresToEndOfRace(true); if (litresNeeded == float.MaxValue) { audioPlayer.playMessageImmediately(new QueuedMessage(AudioPlayer.folderNoData, 0)); } else if (litresNeeded <= 0) { audioPlayer.playMessageImmediately(new QueuedMessage(Fuel.folderPlentyOfFuel, 0)); } else if (litresNeeded > 0) { int roundedLitresNeeded = (int)Math.Ceiling(litresNeeded); AddFuel(roundedLitresNeeded); if (roundedLitresNeeded > fuelCapacity - currentFuel) { // if we have a known fuel capacity and this is less than the calculated amount of fuel we need, warn about it. audioPlayer.playMessage(new QueuedMessage(Fuel.folderWillNeedToStopAgain, 0, secondsDelay: 4, abstractEvent: this)); } else { audioPlayer.playMessageImmediately(new QueuedMessage(AudioPlayer.folderFuelToEnd, 0)); } return; } } else if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.PIT_STOP_TEAROFF)) { Tearoff(); audioPlayer.playMessageImmediately(new QueuedMessage(AudioPlayer.folderAcknowlegeOK, 0)); return; } else if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.PIT_STOP_FAST_REPAIR)) { FastRepair(); audioPlayer.playMessageImmediately(new QueuedMessage(AudioPlayer.folderAcknowlegeOK, 0)); return; } else if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.PIT_STOP_CLEAR_ALL)) { ClearAll(); audioPlayer.playMessageImmediately(new QueuedMessage(AudioPlayer.folderAcknowlegeOK, 0)); return; } else if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.PIT_STOP_CLEAR_TYRES)) { ClearTires(); audioPlayer.playMessageImmediately(new QueuedMessage(AudioPlayer.folderAcknowlegeOK, 0)); return; } else if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.PIT_STOP_CLEAR_WIND_SCREEN)) { ClearTearoff(); audioPlayer.playMessageImmediately(new QueuedMessage(AudioPlayer.folderAcknowlegeOK, 0)); return; } else if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.PIT_STOP_CLEAR_FAST_REPAIR)) { ClearFastRepair(); audioPlayer.playMessageImmediately(new QueuedMessage(AudioPlayer.folderAcknowlegeOK, 0)); return; } else if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.PIT_STOP_CLEAR_FUEL)) { ClearFuel(); audioPlayer.playMessageImmediately(new QueuedMessage(AudioPlayer.folderAcknowlegeOK, 0)); return; } else if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.PIT_STOP_CHANGE_TYRE_PRESSURE) || SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.PIT_STOP_CHANGE_FRONT_LEFT_TYRE_PRESSURE) || SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.PIT_STOP_CHANGE_FRONT_RIGHT_TYRE_PRESSURE) || SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.PIT_STOP_CHANGE_REAR_LEFT_TYRE_PRESSURE) || SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.PIT_STOP_CHANGE_REAR_RIGHT_TYRE_PRESSURE)) { int amount = 0; foreach (KeyValuePair <String[], int> entry in SpeechRecogniser.numberToNumber) { foreach (String numberStr in entry.Key) { if (voiceMessage.Contains(" " + numberStr)) { amount = entry.Value; break; } } } if (amount == 0) { audioPlayer.playMessageImmediately(new QueuedMessage(AudioPlayer.folderDidntUnderstand, 0)); return; } else { if (pressureUnit == PressureUnit.PSI) { amount = convertPSItoKPA(amount); } if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.PIT_STOP_CHANGE_TYRE_PRESSURE)) { ChangeTire(PitCommandModeTypes.LF, amount); ChangeTire(PitCommandModeTypes.RF, amount); ChangeTire(PitCommandModeTypes.LR, amount); ChangeTire(PitCommandModeTypes.RR, amount); audioPlayer.playMessageImmediately(new QueuedMessage(AudioPlayer.folderAcknowlegeOK, 0)); return; } else if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.PIT_STOP_CHANGE_FRONT_LEFT_TYRE_PRESSURE)) { ChangeTire(PitCommandModeTypes.LF, amount); audioPlayer.playMessageImmediately(new QueuedMessage(AudioPlayer.folderAcknowlegeOK, 0)); return; } else if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.PIT_STOP_CHANGE_FRONT_RIGHT_TYRE_PRESSURE)) { ChangeTire(PitCommandModeTypes.RF, amount); audioPlayer.playMessageImmediately(new QueuedMessage(AudioPlayer.folderAcknowlegeOK, 0)); return; } else if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.PIT_STOP_CHANGE_REAR_LEFT_TYRE_PRESSURE)) { ChangeTire(PitCommandModeTypes.LR, amount); audioPlayer.playMessageImmediately(new QueuedMessage(AudioPlayer.folderAcknowlegeOK, 0)); return; } else if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.PIT_STOP_CHANGE_REAR_RIGHT_TYRE_PRESSURE)) { ChangeTire(PitCommandModeTypes.RR, amount); audioPlayer.playMessageImmediately(new QueuedMessage(AudioPlayer.folderAcknowlegeOK, 0)); return; } } } else if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.PIT_STOP_CHANGE_ALL_TYRES)) { ChangeTire(PitCommandModeTypes.LF, lastColdFLPressure); ChangeTire(PitCommandModeTypes.RF, lastColdFRPressure); ChangeTire(PitCommandModeTypes.LR, lastColdRLPressure); ChangeTire(PitCommandModeTypes.RR, lastColdRRPressure); audioPlayer.playMessageImmediately(new QueuedMessage(AudioPlayer.folderAcknowlegeOK, 0)); return; } else if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.PIT_STOP_CHANGE_FRONT_LEFT_TYRE)) { ChangeTire(PitCommandModeTypes.LF, lastColdFLPressure); audioPlayer.playMessageImmediately(new QueuedMessage(AudioPlayer.folderAcknowlegeOK, 0)); return; } else if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.PIT_STOP_CHANGE_FRONT_RIGHT_TYRE)) { ChangeTire(PitCommandModeTypes.RF, lastColdFRPressure); audioPlayer.playMessageImmediately(new QueuedMessage(AudioPlayer.folderAcknowlegeOK, 0)); return; } else if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.PIT_STOP_CHANGE_REAR_LEFT_TYRE)) { ChangeTire(PitCommandModeTypes.LR, lastColdRLPressure); audioPlayer.playMessageImmediately(new QueuedMessage(AudioPlayer.folderAcknowlegeOK, 0)); return; } else if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.PIT_STOP_CHANGE_REAR_RIGHT_TYRE)) { ChangeTire(PitCommandModeTypes.RR, lastColdRRPressure); audioPlayer.playMessageImmediately(new QueuedMessage(AudioPlayer.folderAcknowlegeOK, 0)); return; } else if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.PIT_STOP_CHANGE_LEFT_SIDE_TYRES)) { ClearTires(); ChangeTire(PitCommandModeTypes.LF, lastColdFLPressure); ChangeTire(PitCommandModeTypes.LR, lastColdRLPressure); audioPlayer.playMessageImmediately(new QueuedMessage(AudioPlayer.folderAcknowlegeOK, 0)); return; } else if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.PIT_STOP_CHANGE_RIGHT_SIDE_TYRES)) { ClearTires(); ChangeTire(PitCommandModeTypes.RF, lastColdFRPressure); ChangeTire(PitCommandModeTypes.RR, lastColdRRPressure); audioPlayer.playMessageImmediately(new QueuedMessage(AudioPlayer.folderAcknowlegeOK, 0)); return; } else if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.HOW_MANY_INCIDENT_POINTS)) { audioPlayer.playMessageImmediately(new QueuedMessage("Incidents/incidents", 0, messageFragments: MessageContents(folderYouHave, incidentsCount, folderincidents))); return; } else if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.WHATS_THE_INCIDENT_LIMIT)) { if (hasLimitedIncidents) { audioPlayer.playMessageImmediately(new QueuedMessage("Incidents/limit", 0, messageFragments: MessageContents(folderincidentlimit, maxIncidentCount))); } else { audioPlayer.playMessageImmediately(new QueuedMessage("Incidents/limit", 0, messageFragments: MessageContents(folderUnlimited))); } return; } else if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.WHATS_MY_IRATING)) { if (iRating != -1) { audioPlayer.playMessageImmediately(new QueuedMessage("license/irating", 0, messageFragments: MessageContents(iRating))); return; } else { audioPlayer.playMessageImmediately(new QueuedMessage(AudioPlayer.folderNoData, 0)); return; } } else if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.WHATS_MY_LICENSE_CLASS)) { if (licenseLevel.Item2 == -1) { audioPlayer.playMessageImmediately(new QueuedMessage(AudioPlayer.folderNoData, 0)); return; } if (licenseLevel.Item2 != -1) { Tuple <int, int> wholeandfractional = Utilities.WholeAndFractionalPart(licenseLevel.Item2, 2); List <MessageFragment> messageFragments = new List <MessageFragment>(); if (licenseLevel.Item1.ToLower() == "a") { messageFragments.Add(MessageFragment.Text(folderLicenseA)); } else if (licenseLevel.Item1.ToLower() == "b") { messageFragments.Add(MessageFragment.Text(folderLicenseB)); } else if (licenseLevel.Item1.ToLower() == "c") { messageFragments.Add(MessageFragment.Text(folderLicenseC)); } else if (licenseLevel.Item1.ToLower() == "d") { messageFragments.Add(MessageFragment.Text(folderLicenseD)); } else if (licenseLevel.Item1.ToLower() == "r") { messageFragments.Add(MessageFragment.Text(folderLicenseR)); } else if (licenseLevel.Item1.ToLower() == "wc") { messageFragments.Add(MessageFragment.Text(folderLicensePro)); } else { audioPlayer.playMessageImmediately(new QueuedMessage(AudioPlayer.folderNoData, 0)); return; } messageFragments.AddRange(MessageContents(wholeandfractional.Item1, NumberReader.folderPoint, wholeandfractional.Item2)); QueuedMessage licenceLevelMessage = new QueuedMessage("License/license", 0, messageFragments: messageFragments); audioPlayer.playDelayedImmediateMessage(licenceLevelMessage); } return; } else if (SpeechRecogniser.ResultContains(voiceMessage, SpeechRecogniser.WHATS_THE_SOF)) { if (strenghtOfField != -1) { audioPlayer.playMessageImmediately(new QueuedMessage("license/irating", 0, messageFragments: MessageContents(strenghtOfField))); return; } else { audioPlayer.playMessageImmediately(new QueuedMessage(AudioPlayer.folderNoData, 0)); return; } } }
public AudioPlayer(CrewChief crewChief) { this.crewChief = crewChief; String soundPackLocationOverride = UserSettings.GetUserSettings().getString("override_default_sound_pack_location"); String defaultSoundFilesPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + @"\CrewChiefV4\sounds"; DirectoryInfo defaultSoundDirectory = new DirectoryInfo(defaultSoundFilesPath); DirectoryInfo overrideSoundDirectory = null; DirectoryInfo soundDirectory = null; Boolean useOverride = false; if (soundPackLocationOverride != null && soundPackLocationOverride.Length > 0) { try { overrideSoundDirectory = new DirectoryInfo(soundPackLocationOverride); if (overrideSoundDirectory.Exists) { useOverride = true; } else { Console.WriteLine("Specified sound pack override folder " + soundPackLocationOverride + " doesn't exist, using default"); } } catch (Exception e) { Console.WriteLine("Unable to set override sound folder ", e.Message); } } if (useOverride && overrideSoundDirectory != null) { soundFilesPath = soundPackLocationOverride; soundDirectory = overrideSoundDirectory; } else { soundFilesPath = defaultSoundFilesPath; soundDirectory = defaultSoundDirectory; } if (soundDirectory.Exists) { soundPackVersion = getSoundPackVersion(soundDirectory); driverNamesVersion = getDriverNamesVersion(soundDirectory); soundPackLanguage = getSoundPackLanguage(soundDirectory); personalisationsVersion = getPersonalisationsVersion(soundDirectory); } else { soundDirectory.Create(); } // populate the personalisations list DirectoryInfo personalisationsDirectory = new DirectoryInfo(soundFilesPath + @"\personalisations"); if (personalisationsDirectory.Exists) { List <String> personalisationsList = new List <string>(); personalisationsList.Add(NO_PERSONALISATION_SELECTED); foreach (DirectoryInfo folderInPersonalisationsDirectory in personalisationsDirectory.GetDirectories()) { personalisationsList.Add(folderInPersonalisationsDirectory.Name); } personalisationsArray = personalisationsList.ToArray(); } String savedPersonalisation = UserSettings.GetUserSettings().getString("PERSONALISATION_NAME"); if (savedPersonalisation != null && savedPersonalisation.Length > 0) { selectedPersonalisation = savedPersonalisation; } }
override protected void triggerInternal(GameStateData previousGameState, GameStateData currentGameState) { currentConditions = currentGameState.Conditions.getMostRecentConditions(); if (currentGameState.SessionData.IsNewLap) { conditionsAtStartOfThisLap = currentConditions; } if (currentConditions != null) { // for pcars track temp, we're only interested in changes at the start line (a single point on the track) because the track // temp is localised. The air temp is (probably) localised too, but will be less variable float trackTempToUse = CrewChief.isPCars() && conditionsAtStartOfThisLap != null ? conditionsAtStartOfThisLap.TrackTemperature : currentConditions.TrackTemperature; if (airTempAtLastReport == float.MinValue) { airTempAtLastReport = currentConditions.AmbientTemperature; trackTempAtLastReport = trackTempToUse; rainAtLastReport = currentConditions.RainDensity; lastRainReport = currentGameState.Now; lastTrackTempReport = currentGameState.Now; lastAirTempReport = currentGameState.Now; } else { Boolean canReportAirChange = enableTrackAndAirTempReports && currentGameState.Now > lastAirTempReport.Add(AirTemperatureReportMaxFrequency); Boolean canReportTrackChange = enableTrackAndAirTempReports && currentGameState.Now > lastTrackTempReport.Add(TrackTemperatureReportMaxFrequency); Boolean reportedCombinedTemps = false; TimeSpan rainReportFrequency = CrewChief.gameDefinition.gameEnum == GameEnum.RF2_64BIT ? RainReportMaxFrequencyRF2 : RainReportMaxFrequencyPCars; if (canReportAirChange || canReportTrackChange) { if (trackTempToUse > trackTempAtLastReport + minTrackTempDeltaToReport && currentConditions.AmbientTemperature > airTempAtLastReport + minAirTempDeltaToReport) { airTempAtLastReport = currentConditions.AmbientTemperature; trackTempAtLastReport = trackTempToUse; lastAirTempReport = currentGameState.Now; lastTrackTempReport = currentGameState.Now; // do the reporting audioPlayer.playMessage(new QueuedMessage("airAndTrackTemp", 10, messageFragments: MessageContents (folderAirAndTrackTempIncreasing, folderAirTempIsNow, convertTemp(currentConditions.AmbientTemperature), folderTrackTempIsNow, convertTemp(trackTempToUse), getTempUnit()), abstractEvent: this, priority: 0)); reportedCombinedTemps = true; } else if (trackTempToUse < trackTempAtLastReport - minTrackTempDeltaToReport && currentConditions.AmbientTemperature < airTempAtLastReport - minAirTempDeltaToReport) { airTempAtLastReport = currentConditions.AmbientTemperature; trackTempAtLastReport = trackTempToUse; lastAirTempReport = currentGameState.Now; lastTrackTempReport = currentGameState.Now; // do the reporting audioPlayer.playMessage(new QueuedMessage("airAndTrackTemp", 10, messageFragments: MessageContents (folderAirAndTrackTempDecreasing, folderAirTempIsNow, convertTemp(currentConditions.AmbientTemperature), folderTrackTempIsNow, convertTemp(trackTempToUse), getTempUnit()), abstractEvent: this, priority: 0)); reportedCombinedTemps = true; } } if (!reportedCombinedTemps && canReportAirChange) { if (currentConditions.AmbientTemperature > airTempAtLastReport + minAirTempDeltaToReport) { airTempAtLastReport = currentConditions.AmbientTemperature; lastAirTempReport = currentGameState.Now; // do the reporting audioPlayer.playMessage(new QueuedMessage("airTemp", 10, messageFragments: MessageContents (folderAirTempIncreasing, convertTemp(currentConditions.AmbientTemperature), getTempUnit()), abstractEvent: this, priority: 0)); } else if (currentConditions.AmbientTemperature < airTempAtLastReport - minAirTempDeltaToReport) { airTempAtLastReport = currentConditions.AmbientTemperature; lastAirTempReport = currentGameState.Now; // do the reporting audioPlayer.playMessage(new QueuedMessage("airTemp", 10, messageFragments: MessageContents (folderAirTempDecreasing, convertTemp(currentConditions.AmbientTemperature), getTempUnit()), abstractEvent: this, priority: 0)); } } if (!reportedCombinedTemps && canReportTrackChange) { if (trackTempToUse > trackTempAtLastReport + minTrackTempDeltaToReport) { trackTempAtLastReport = trackTempToUse; lastTrackTempReport = currentGameState.Now; // do the reporting audioPlayer.playMessage(new QueuedMessage("trackTemp", 10, messageFragments: MessageContents (folderTrackTempIncreasing, convertTemp(trackTempToUse), getTempUnit()), abstractEvent: this, priority: 0)); } else if (trackTempToUse < trackTempAtLastReport - minTrackTempDeltaToReport) { trackTempAtLastReport = trackTempToUse; lastTrackTempReport = currentGameState.Now; // do the reporting audioPlayer.playMessage(new QueuedMessage("trackTemp", 10, messageFragments: MessageContents (folderTrackTempDecreasing, convertTemp(trackTempToUse), getTempUnit()), abstractEvent: this, priority: 0)); } } //pcars2 test warning if (enablePCarsRainPrediction && CrewChief.isPCars()) { if (previousGameState != null && currentGameState.SessionData.SessionRunningTime > 10) { if (currentGameState.RainDensity == 0) { // not raining so see if we can guess when it might start if (!waitingForRainEstimate) { if (previousGameState.CloudBrightness == 2 && currentGameState.CloudBrightness < 2) { timeWhenCloudIncreased = previousGameState.Now; waitingForRainEstimate = true; } } else if (currentGameState.CloudBrightness < 1.98) { // big enough change to calculate expected rain time TimeSpan timeDelta = currentGameState.Now - timeWhenCloudIncreased; // assume rain just after it hits 1.9 float millisTillRain = (float)timeDelta.TotalMilliseconds * 6f; // this is usually really inaccurate and can go either way timeWhenRainExpected = timeWhenCloudIncreased.AddMilliseconds(millisTillRain); waitingForRainEstimate = false; timeWhenCloudIncreased = DateTime.MinValue; DateTime when = currentGameState.Now.AddMilliseconds(millisTillRain); Console.WriteLine("It is now " + currentGameState.Now + ", we expect rain at game time " + when); int minutes = (int)Math.Round(millisTillRain / 60000); if (minutes > 2) { audioPlayer.playMessage(new QueuedMessage("expecting_rain", 10, messageFragments: MessageContents(folderExpectRain, new TimeSpanWrapper(TimeSpan.FromMinutes(minutes), Precision.MINUTES)), abstractEvent: this)); } } } else { // cancel waiting for rain waitingForRainEstimate = false; timeWhenCloudIncreased = DateTime.MinValue; } } } if (currentGameState.Now > lastRainReport.Add(rainReportFrequency)) { // for PCars mRainDensity value is 0 or 1 if (CrewChief.gameDefinition.gameEnum == GameEnum.PCARS_32BIT || CrewChief.gameDefinition.gameEnum == GameEnum.PCARS_64BIT || CrewChief.gameDefinition.gameEnum == GameEnum.PCARS_NETWORK) { if (currentGameState.RainDensity == 0 && rainAtLastReport == 1) { rainAtLastReport = currentGameState.RainDensity; lastRainReport = currentGameState.Now; audioPlayer.playMessage(new QueuedMessage(folderStoppedRaining, 10, abstractEvent: this, priority: 2)); } else if (currentConditions.RainDensity == 1 && rainAtLastReport == 0) { rainAtLastReport = currentGameState.RainDensity; lastRainReport = currentGameState.Now; audioPlayer.playMessage(new QueuedMessage(folderSeeingSomeRain, 10, abstractEvent: this, priority: 5)); } } else if (CrewChief.gameDefinition.gameEnum == GameEnum.RF2_64BIT || CrewChief.gameDefinition.gameEnum == GameEnum.PCARS2) { if (rainDensityAtLastCheck != -1 && rainDensityAtLastCheck != currentConditions.RainDensity) { float rainChangeRate = (float)(Math.Abs(rainDensityAtLastCheck - currentConditions.RainDensity) / rainReportFrequency.TotalSeconds); if (rainChangeRate > ConditionsMonitor.maxRainChangeRate) { ConditionsMonitor.maxRainChangeRate = rainChangeRate; } } rainDensityAtLastCheck = currentConditions.RainDensity; RainLevel currentRainLevel = getRainLevel(currentConditions.RainDensity); RainLevel lastReportedRainLevel = getRainLevel(rainAtLastReport); if (currentRainLevel != lastReportedRainLevel) { Boolean increasing = currentConditions.RainDensity > rainAtLastReport; switch (currentRainLevel) { case RainLevel.DRIZZLE: audioPlayer.playMessageImmediately(new QueuedMessage(increasing ? folderDrizzleIncreasing : folderDrizzleDecreasing, 0, type: SoundType.IMPORTANT_MESSAGE, priority: 0)); break; case RainLevel.LIGHT: audioPlayer.playMessageImmediately(new QueuedMessage(increasing ? folderRainLightIncreasing : folderRainLightDecreasing, 0, type: SoundType.IMPORTANT_MESSAGE, priority: 0)); break; case RainLevel.MID: audioPlayer.playMessageImmediately(new QueuedMessage(increasing ? folderRainMidIncreasing : folderRainMidDecreasing, 0, type: SoundType.IMPORTANT_MESSAGE, priority: 0)); break; case RainLevel.HEAVY: audioPlayer.playMessageImmediately(new QueuedMessage(increasing ? folderRainHeavyIncreasing : folderRainHeavyDecreasing, 0, type: SoundType.IMPORTANT_MESSAGE, priority: 0)); break; case RainLevel.STORM: audioPlayer.playMessageImmediately(new QueuedMessage(folderRainMax, 0, type: SoundType.IMPORTANT_MESSAGE, priority: 0)); break; case RainLevel.NONE: audioPlayer.playMessage(new QueuedMessage(folderStoppedRaining, 10, abstractEvent: this, priority: 3)); break; } lastRainReport = currentGameState.Now; rainAtLastReport = currentConditions.RainDensity; } } } } } }