public void playMessage(QueuedMessage queuedMessage, PearlsOfWisdom.PearlType pearlType, double pearlMessageProbability) { if (queuedMessage.canBePlayed) { lock (queuedClips) { if (queuedClips.Contains(queuedMessage.messageName)) { Console.WriteLine("Clip for event " + queuedMessage.messageName + " is already queued, ignoring"); return; } else { PearlsOfWisdom.PearlMessagePosition pearlPosition = PearlsOfWisdom.PearlMessagePosition.NONE; if (pearlType != PearlsOfWisdom.PearlType.NONE && checkPearlOfWisdomValid(pearlType)) { pearlPosition = pearlsOfWisdom.getMessagePosition(pearlMessageProbability); } if (pearlPosition == PearlsOfWisdom.PearlMessagePosition.BEFORE) { QueuedMessage pearlQueuedMessage = new QueuedMessage(queuedMessage.abstractEvent); pearlQueuedMessage.dueTime = queuedMessage.dueTime; queuedClips.Add(PearlsOfWisdom.getMessageFolder(pearlType), pearlQueuedMessage); } queuedClips.Add(queuedMessage.messageName, queuedMessage); if (pearlPosition == PearlsOfWisdom.PearlMessagePosition.AFTER) { QueuedMessage pearlQueuedMessage = new QueuedMessage(queuedMessage.abstractEvent); pearlQueuedMessage.dueTime = queuedMessage.dueTime; queuedClips.Add(PearlsOfWisdom.getMessageFolder(pearlType), pearlQueuedMessage); } } } } }
// checks that another pearl isn't already queued. If one of the same type is already // in the queue this method just returns false. If a conflicting pearl is in the queue // this method removes it and returns false, so we don't end up with, for example, // a 'keep it up' message in a block that contains a 'your lap times are worsening' message private Boolean checkPearlOfWisdomValid(PearlsOfWisdom.PearlType newPearlType) { Boolean isValid = true; if (queuedClips != null && queuedClips.Count > 0) { List <String> pearlsToPurge = new List <string>(); foreach (String eventName in queuedClips.Keys) { if (clipIsPearlOfWisdom(eventName)) { Console.WriteLine("There's already a pearl in the queue, can't add another"); isValid = false; if (eventName != PearlsOfWisdom.getMessageFolder(newPearlType)) { pearlsToPurge.Add(eventName); } } } foreach (String pearlToPurge in pearlsToPurge) { queuedClips.Remove(pearlToPurge); Console.WriteLine("Queue contains a pearl " + pearlToPurge + " which conflicts with " + newPearlType); } } return(isValid); }
// read the position message. This is may be part of a long message queue so it can be a few seconds before it triggers. // Because of this, we use a delayed message event - when the message reaches the top of the queue it uses the latest // position, rather than the position when it was inserted into the queue. // For RF2 use a non-zero delay here because the position data isn't always updated in a timely fashion at the start of a new lap. private void playCurrentPositionMessage(PearlsOfWisdom.PearlType pearlType, float pearlLikelihood) { int delaySeconds = CrewChief.gameDefinition.gameEnum == GameEnum.RF2_64BIT || CrewChief.gameDefinition.gameEnum == GameEnum.ASSETTO_32BIT || CrewChief.gameDefinition.gameEnum == GameEnum.ASSETTO_64BIT ? 1 : 0; DelayedMessageEvent delayedMessageEvent = new DelayedMessageEvent("getPositionMessages", new Object[] { currentPosition }, this); audioPlayer.playMessage(new QueuedMessage("position", 10, delayedMessageEvent: delayedMessageEvent, secondsDelay: delaySeconds, priority: 10), pearlType, pearlLikelihood); }
protected override void triggerInternal(GameStateData previousGameState, GameStateData currentGameState) { if (opponentKeyForCarThatJustPassedUs == null && opponentKeyForCarWeJustPassed == null) { checkForNewOvertakes(currentGameState, previousGameState); } checkCompletedOvertake(currentGameState); currentPosition = currentGameState.SessionData.Position; isLast = currentGameState.isLast(); if (previousPosition == 0) { previousPosition = currentPosition; } if (currentGameState.SessionData.SessionPhase == SessionPhase.Green) { if (currentGameState.SessionData.SessionType == SessionType.Race && enableRaceStartMessages && !playedRaceStartMessage && currentGameState.SessionData.CompletedLaps == 0 && currentGameState.SessionData.LapTimeCurrent > startMessageTime) { playedRaceStartMessage = true; Console.WriteLine("Race start message... isLast = " + isLast + " session start pos = " + currentGameState.SessionData.SessionStartPosition + " current pos = " + currentGameState.SessionData.Position); if (currentGameState.SessionData.SessionStartPosition > 0) { if (currentGameState.SessionData.SessionStartPosition + 1 < currentGameState.SessionData.Position) { audioPlayer.playMessage(new QueuedMessage(folderBadStart, 0, this)); } else if (!isLast && (currentGameState.SessionData.Position == 1 || currentGameState.SessionData.SessionStartPosition > currentGameState.SessionData.Position + 2) && !currentGameState.PenaltiesData.HasDriveThrough && !currentGameState.PenaltiesData.HasStopAndGo) { audioPlayer.playMessage(new QueuedMessage(folderGoodStart, 0, this)); } else if (currentGameState.SessionData.SessionStartPosition + 5 < currentGameState.SessionData.Position) { audioPlayer.playMessage(new QueuedMessage(folderTerribleStart, 0, this)); } else if (!isLast && rand.NextDouble() > 0.6 && !currentGameState.PenaltiesData.HasDriveThrough && !currentGameState.PenaltiesData.HasStopAndGo) { // only play the OK start message sometimes audioPlayer.playMessage(new QueuedMessage(folderOKStart, 0, this)); } } } } if (enablePositionMessages && currentGameState.SessionData.IsNewLap) { if (currentGameState.SessionData.CompletedLaps > 0) { playedRaceStartMessage = true; } if (isLast) { numberOfLapsInLastPlace++; } else { numberOfLapsInLastPlace = 0; } if (previousPosition == 0 && currentGameState.SessionData.Position > 0) { previousPosition = currentGameState.SessionData.Position; } else { if (currentGameState.SessionData.CompletedLaps > lapNumberAtLastMessage + 3 || previousPosition != currentGameState.SessionData.Position) { Dictionary <String, Object> validationData = new Dictionary <String, Object>(); validationData.Add(positionValidationKey, currentGameState.SessionData.Position); PearlsOfWisdom.PearlType pearlType = PearlsOfWisdom.PearlType.NONE; float pearlLikelihood = 0.2f; if (currentGameState.SessionData.SessionType == SessionType.Race) { if (!isLast && (previousPosition > currentGameState.SessionData.Position + 5 || (previousPosition > currentGameState.SessionData.Position && currentGameState.SessionData.Position <= 5))) { pearlType = PearlsOfWisdom.PearlType.GOOD; pearlLikelihood = 0.8f; } else if (!isLast && previousPosition < currentGameState.SessionData.Position && currentGameState.SessionData.Position > 5 && !previousGameState.PitData.OnOutLap && !currentGameState.PitData.OnOutLap && !currentGameState.PitData.InPitlane) { // don't play bad-pearl if the lap just completed was an out lap or are in the pit // note that we don't play a pearl for being last - there's a special set of // insults reserved for this pearlType = PearlsOfWisdom.PearlType.BAD; pearlLikelihood = 0.5f; } else if (!isLast) { pearlType = PearlsOfWisdom.PearlType.NEUTRAL; } } if (currentGameState.SessionData.Position == 1) { if (currentGameState.SessionData.SessionType == SessionType.Race) { audioPlayer.playMessage(new QueuedMessage(folderLeading, 0, this, validationData), pearlType, pearlLikelihood); } else if (currentGameState.SessionData.SessionType == SessionType.Practice) { audioPlayer.playMessage(new QueuedMessage(folderStub + 1, 0, this, validationData), pearlType, pearlLikelihood); } // no p1 for pole - this is in the laptime tracker (yuk) } else if (!isLast) { audioPlayer.playMessage(new QueuedMessage(folderStub + currentGameState.SessionData.Position, 0, this), pearlType, pearlLikelihood); } else if (isLast) { if (numberOfLapsInLastPlace > 3) { audioPlayer.suspendPearlsOfWisdom(); audioPlayer.playMessage(new QueuedMessage(folderConsistentlyLast, 0, this, validationData)); } else { audioPlayer.suspendPearlsOfWisdom(); audioPlayer.playMessage(new QueuedMessage(folderLast, 0, this, validationData)); } } previousPosition = currentGameState.SessionData.Position; lapNumberAtLastMessage = currentGameState.SessionData.CompletedLaps; } } } }
override protected 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 > currentGameState.SessionData.SessionStartPosition + 5 && !currentGameState.PitData.OnOutLap && !currentGameState.PitData.InPitlane) { // don't play bad-pearl if we're on an out lap or are pitting pearlType = PearlsOfWisdom.PearlType.BAD; } } if (currentGameState.SessionData.SessionType == SessionType.Race && currentGameState.SessionData.IsNewLap && currentGameState.SessionData.SessionRunningTime > 60 && !playedLastLap) { Boolean timeWillBeZeroAtEndOfLeadersLap = false; if (currentGameState.SessionData.Position == 1) { timeWillBeZeroAtEndOfLeadersLap = timeLeft > 0 && currentGameState.SessionData.PlayerLapTimeSessionBest > 0 && timeLeft < currentGameState.SessionData.PlayerLapTimeSessionBest - 5; } else { OpponentData leader = currentGameState.getOpponentAtPosition(1, true); timeWillBeZeroAtEndOfLeadersLap = leader != null && leader.isProbablyLastLap; } if ((addExtraLapForDTM2015 && timeLeft <= 0) || (!addExtraLapForDTM2015 && timeWillBeZeroAtEndOfLeadersLap)) { 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.playMessage(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.playMessage(new QueuedMessage(folderLastLapPodium, 0, this), pearlType, 0); } else { audioPlayer.playMessage(new QueuedMessage(folderLastLap, 0, this)); } } } 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.playMessage(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.playMessage(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.playMessage(new QueuedMessage(folder5minsPodium, 0, this), pearlType, 0); } else { audioPlayer.playMessage(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.playMessage(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.playMessage(new QueuedMessage(folder15mins, 0, this), pearlType, 0.7); } if (currentGameState.SessionData.SessionRunningTime > 60 && !played20mins && timeLeft / 60 < 20 && timeLeft / 60 > 19.9) { played20mins = true; audioPlayer.playMessage(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.playMessage(new QueuedMessage(folderHalfWayHome, 0, this), pearlType, 0.7); } } }
protected override void triggerInternal(GameStateData previousGameState, GameStateData currentGameState) { if (GameStateData.onManualFormationLap) { return; } // edge case here - if we're the only can in the session, don't bother with this event if (currentGameState.OpponentData.Count == 0) { currentPosition = 1; return; } if (!GlobalBehaviourSettings.useOvalLogic && opponentKeyForCarThatJustPassedUs == null && opponentKeyForCarWeJustPassed == null) { checkForNewOvertakes(currentGameState, previousGameState); } checkCompletedOvertake(currentGameState); currentPosition = currentGameState.SessionData.ClassPosition; sessionType = currentGameState.SessionData.SessionType; isLast = currentGameState.isLast(); if (previousPosition == 0) { previousPosition = currentPosition; } if (currentGameState.SessionData.SessionPhase == SessionPhase.Green || currentGameState.SessionData.SessionPhase == SessionPhase.FullCourseYellow) { if (currentGameState.SessionData.SessionType == SessionType.Race && enableRaceStartMessages && !playedRaceStartMessage && currentGameState.SessionData.CompletedLaps == 0 && (currentGameState.SessionData.JustGoneGreenTime != DateTime.MaxValue && currentGameState.Now > currentGameState.SessionData.JustGoneGreenTime.AddSeconds(startMessageTime)) && !currentGameState.FlagData.isLocalYellow) { playedRaceStartMessage = true; Console.WriteLine("Race start message... isLast = " + isLast + " session start pos = " + currentGameState.SessionData.SessionStartClassPosition + " current pos = " + currentGameState.SessionData.ClassPosition); bool hasrFactorPenaltyPending = (CrewChief.gameDefinition.gameEnum == GameEnum.RF1 || CrewChief.gameDefinition.gameEnum == GameEnum.RF2_64BIT) && currentGameState.PenaltiesData.NumPenalties > 0; if (currentGameState.SessionData.SessionStartClassPosition > 0 && !currentGameState.PenaltiesData.HasDriveThrough && !currentGameState.PenaltiesData.HasStopAndGo && !hasrFactorPenaltyPending) { if (currentGameState.SessionData.ClassPosition > currentGameState.SessionData.SessionStartClassPosition + 5) { audioPlayer.playMessage(new QueuedMessage(folderTerribleStart, 10, abstractEvent: this, priority: 5)); } else if (currentGameState.SessionData.ClassPosition > currentGameState.SessionData.SessionStartClassPosition + 3) { audioPlayer.playMessage(new QueuedMessage(folderBadStart, 10, abstractEvent: this, priority: 5)); } else if (!isLast && (currentGameState.SessionData.ClassPosition == 1 || currentGameState.SessionData.ClassPosition < currentGameState.SessionData.SessionStartClassPosition - 1)) { audioPlayer.playMessage(new QueuedMessage(folderGoodStart, 10, abstractEvent: this, priority: 5)); } else if (!isLast && Utilities.random.NextDouble() > 0.6) { // only play the OK start message sometimes audioPlayer.playMessage(new QueuedMessage(folderOKStart, 10, abstractEvent: this, priority: 5)); } } } } if (enablePositionMessages && currentGameState.SessionData.SessionPhase != SessionPhase.Countdown && !currentGameState.PitData.InPitlane) { if (canPlayPositionReminder && currentGameState.SessionData.IsNewSector && currentGameState.SessionData.CompletedLaps == lapForPositionReminder && currentGameState.SessionData.SectorNumber == sectorForPositionReminder) { playCurrentPositionMessage(PearlsOfWisdom.PearlType.NONE, 0f); canPlayPositionReminder = false; } if (currentGameState.SessionData.IsNewLap) { if (currentGameState.SessionData.CompletedLaps > 0) { playedRaceStartMessage = true; } if (isLast) { numberOfLapsInLastPlace++; } else { numberOfLapsInLastPlace = 0; } if (previousPosition == 0 && currentGameState.SessionData.ClassPosition > 0) { previousPosition = currentGameState.SessionData.ClassPosition; } else { if (previousPosition != currentGameState.SessionData.ClassPosition) { if (currentGameState.SessionData.CompletedLaps > 1) { canPlayPositionReminder = true; lapForPositionReminder = currentGameState.SessionData.CompletedLaps + Utilities.random.Next(3, 6); sectorForPositionReminder = Utilities.random.Next(1, 4); } PearlsOfWisdom.PearlType pearlType = PearlsOfWisdom.PearlType.NONE; float pearlLikelihood = 0.2f; if (currentGameState.SessionData.SessionType == SessionType.Race && currentGameState.SessionData.ClassPosition > 0) { if (!isLast && (previousPosition > currentGameState.SessionData.ClassPosition + 5 || (previousPosition > currentGameState.SessionData.ClassPosition && currentGameState.SessionData.ClassPosition <= 5))) { pearlType = PearlsOfWisdom.PearlType.GOOD; pearlLikelihood = 0.8f; } else if (!isLast && previousPosition < currentGameState.SessionData.ClassPosition && currentGameState.SessionData.ClassPosition > 5 && !previousGameState.PitData.OnOutLap && !currentGameState.PitData.OnOutLap && !currentGameState.PitData.InPitlane && currentGameState.SessionData.LapTimePrevious > currentGameState.SessionData.PlayerLapTimeSessionBest) { // don't play bad-pearl if the lap just completed was an out lap or are in the pit // note that we don't play a pearl for being last - there's a special set of // insults reserved for this pearlType = PearlsOfWisdom.PearlType.BAD; pearlLikelihood = 0.5f; } else if (!isLast) { pearlType = PearlsOfWisdom.PearlType.NEUTRAL; } } playCurrentPositionMessage(pearlType, pearlLikelihood); } } } } }
override protected void triggerInternal(GameStateData previousGameState, GameStateData currentGameState) { // store this in a local var so it's available for vocie command responses addExtraLap = currentGameState.SessionData.HasExtraLap; 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 (addExtraLap && gotHalfTime && timeLeft <= 0 && currentGameState.SessionData.IsNewLap) { startedExtraLap = 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 > currentGameState.SessionData.SessionStartPosition + 5 && !currentGameState.PitData.OnOutLap && !currentGameState.PitData.InPitlane && // yuk... AC SessionStartPosition is suspect so don't allow "you're shit" messages based on it. CrewChief.gameDefinition.gameEnum != GameEnum.ASSETTO_32BIT && CrewChief.gameDefinition.gameEnum != GameEnum.ASSETTO_64BIT) { // don't play bad-pearl if we're on an out lap or are pitting pearlType = PearlsOfWisdom.PearlType.BAD; } } if (currentGameState.SessionData.SessionType == SessionType.Race && currentGameState.SessionData.IsNewLap && currentGameState.SessionData.SessionRunningTime > 60 && !playedLastLap) { Boolean timeWillBeZeroAtEndOfLeadersLap = false; if (currentGameState.SessionData.Position == 1) { timeWillBeZeroAtEndOfLeadersLap = timeLeft > 0 && currentGameState.SessionData.PlayerLapTimeSessionBest > 0 && timeLeft < currentGameState.SessionData.PlayerLapTimeSessionBest - 5; } else { OpponentData leader = currentGameState.getOpponentAtPosition(1, true); timeWillBeZeroAtEndOfLeadersLap = leader != null && leader.isProbablyLastLap; } if ((addExtraLap && timeLeft <= 0) || (!addExtraLap && timeWillBeZeroAtEndOfLeadersLap)) { 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.playMessage(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.playMessage(new QueuedMessage(folderLastLapPodium, 0, this), pearlType, 0); } else { audioPlayer.playMessage(new QueuedMessage(folderLastLap, 0, this)); } } } if (currentGameState.SessionData.SessionRunningTime > 60 && timeLeft / 60 < 3 && timeLeft / 60 > 2.9) { // disable pearls for the last part of the race audioPlayer.disablePearlsOfWisdom = true; } // Console.WriteLine("Session time left = " + timeLeft + " SessionRunningTime = " + currentGameState.SessionData.SessionRunningTime); if (!currentGameState.SessionData.HasExtraLap && currentGameState.SessionData.SessionRunningTime >= 0 && !played0mins && timeLeft <= 0.2) { played0mins = true; played2mins = true; played5mins = true; played10mins = true; played15mins = true; played20mins = true; playedHalfWayHome = true; audioPlayer.suspendPearlsOfWisdom(); // PCars hack - don't play this if it's an unlimited session - no lap limit and no time limit if (!currentGameState.SessionData.SessionHasFixedTime && currentGameState.SessionData.SessionNumberOfLaps <= 0) { Console.WriteLine("Skipping session end messages for unlimited session"); } else if (currentGameState.SessionData.SessionType != SessionType.Race) { // don't play the chequered flag message in race sessions audioPlayer.playMessage(new QueuedMessage("session_complete", MessageContents(folder0mins, Position.folderStub + currentGameState.SessionData.Position), 0, this)); } } 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.playMessage(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.playMessage(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.playMessage(new QueuedMessage(folder5minsPodium, 0, this), pearlType, 0); } else { audioPlayer.playMessage(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.playMessage(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.playMessage(new QueuedMessage(folder15mins, 0, this), pearlType, 0.7); } if (currentGameState.SessionData.SessionRunningTime > 60 && !played20mins && timeLeft / 60 < 20 && timeLeft / 60 > 19.9) { played20mins = true; audioPlayer.playMessage(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.playMessage(new QueuedMessage(folderHalfWayHome, 0, this), pearlType, 0.7); } } }
protected override void triggerInternal(GameStateData previousGameState, GameStateData currentGameState) { if (opponentKeyForCarThatJustPassedUs == null && opponentKeyForCarWeJustPassed == null) { checkForNewOvertakes(currentGameState, previousGameState); } checkCompletedOvertake(currentGameState); currentPosition = currentGameState.SessionData.Position; sessionType = currentGameState.SessionData.SessionType; isLast = currentGameState.isLast(); if (previousPosition == 0) { previousPosition = currentPosition; } if (currentGameState.SessionData.SessionPhase == SessionPhase.Green || currentGameState.SessionData.SessionPhase == SessionPhase.FullCourseYellow) { if (currentGameState.SessionData.SessionType == SessionType.Race && enableRaceStartMessages && !playedRaceStartMessage && currentGameState.SessionData.CompletedLaps == 0 && currentGameState.SessionData.LapTimeCurrent > startMessageTime && !currentGameState.FlagData.isLocalYellow) { playedRaceStartMessage = true; Console.WriteLine("Race start message... isLast = " + isLast + " session start pos = " + currentGameState.SessionData.SessionStartPosition + " current pos = " + currentGameState.SessionData.Position); if (currentGameState.SessionData.SessionStartPosition > 0) { if (currentGameState.SessionData.SessionStartPosition + 1 < currentGameState.SessionData.Position) { audioPlayer.playMessage(new QueuedMessage(folderBadStart, 0, this)); } else if (!isLast && (currentGameState.SessionData.Position == 1 || currentGameState.SessionData.SessionStartPosition > currentGameState.SessionData.Position + 2) && !currentGameState.PenaltiesData.HasDriveThrough && !currentGameState.PenaltiesData.HasStopAndGo) { audioPlayer.playMessage(new QueuedMessage(folderGoodStart, 0, this)); } else if (currentGameState.SessionData.SessionStartPosition + 5 < currentGameState.SessionData.Position) { audioPlayer.playMessage(new QueuedMessage(folderTerribleStart, 0, this)); } else if (!isLast && rand.NextDouble() > 0.6 && !currentGameState.PenaltiesData.HasDriveThrough && !currentGameState.PenaltiesData.HasStopAndGo) { // only play the OK start message sometimes audioPlayer.playMessage(new QueuedMessage(folderOKStart, 0, this)); } } } } if (enablePositionMessages && currentGameState.SessionData.IsNewLap) { if (currentGameState.SessionData.CompletedLaps > 0) { playedRaceStartMessage = true; } if (isLast) { numberOfLapsInLastPlace++; } else { numberOfLapsInLastPlace = 0; } if (previousPosition == 0 && currentGameState.SessionData.Position > 0) { previousPosition = currentGameState.SessionData.Position; } else { if (currentGameState.SessionData.CompletedLaps > lapNumberAtLastMessage + 3 || previousPosition != currentGameState.SessionData.Position) { PearlsOfWisdom.PearlType pearlType = PearlsOfWisdom.PearlType.NONE; float pearlLikelihood = 0.2f; if (currentGameState.SessionData.SessionType == SessionType.Race && currentGameState.SessionData.Position > 0) { if (!isLast && (previousPosition > currentGameState.SessionData.Position + 5 || (previousPosition > currentGameState.SessionData.Position && currentGameState.SessionData.Position <= 5))) { pearlType = PearlsOfWisdom.PearlType.GOOD; pearlLikelihood = 0.8f; } else if (!isLast && previousPosition < currentGameState.SessionData.Position && currentGameState.SessionData.Position > 5 && !previousGameState.PitData.OnOutLap && !currentGameState.PitData.OnOutLap && !currentGameState.PitData.InPitlane) { // don't play bad-pearl if the lap just completed was an out lap or are in the pit // note that we don't play a pearl for being last - there's a special set of // insults reserved for this pearlType = PearlsOfWisdom.PearlType.BAD; pearlLikelihood = 0.5f; } else if (!isLast) { pearlType = PearlsOfWisdom.PearlType.NEUTRAL; } } // read the position message. This is may be part of a long message queue so it can be a few seconds before it triggers. // Because of this, we use a delayed message event - when the message reaches the top of the queue it uses the latest // position, rather than the position when it was inserted into the queue. // For RF2 use a non-zero delay here because the position data isn't always updated in a timely fashion at the start of a new lap. int delaySeconds = CrewChief.gameDefinition.gameEnum == GameEnum.RF2_64BIT || CrewChief.gameDefinition.gameEnum == GameEnum.ASSETTO_32BIT || CrewChief.gameDefinition.gameEnum == GameEnum.ASSETTO_64BIT ? 1 : 0; DelayedMessageEvent delayedMessageEvent = new DelayedMessageEvent("getPositionMessages", new Object[] { currentPosition }, this); audioPlayer.playMessage(new QueuedMessage("position", delayedMessageEvent, delaySeconds, null), pearlType, pearlLikelihood); lapNumberAtLastMessage = currentGameState.SessionData.CompletedLaps; } } } }