/// <param name="random">IMPORTANT: This may be part of the game state</param> /// <param name="cueStates">IMPORTANT: This may be part of the game state</param> /// <param name="playLocally"> /// True if this sound should be played, false if the sound is for a remote player (not for us). /// Allows for local-only UI sounds. /// </param> public void PlayCue(IAudioDefinitions definitions, Cue cue, Position?worldPosition, FadePitchPan fpp, PlayCueParameters parameters, bool playsLocally) { if (parameters.soundIndex == PlayCueParameters.MISSING_CUE) { if (!doingPrediction ) // <- poor man's "first time simulated" (Missing music doesn't get rollback-aware sound handling) { MissingAudio.TriedToPlayMissingCue(fpp); } return; } PlayCueSkipMissingCheck(definitions, cue, worldPosition, fpp, parameters, playsLocally); }
public static void PlayCue(IAudioDefinitions definitions, Cue cue, PlayCueParameters parameters, FadePitchPan fpp, bool loop = false) { if (parameters.soundIndex == PlayCueParameters.MISSING_CUE) { MissingAudio.TriedToPlayMissingCue(fpp); return; } if (parameters.soundIndex < 0) { return; } PlayCueSkipMissingCheck(definitions, cue, parameters, fpp, loop); }
public void PlayCueSkipMissingCheck(IAudioDefinitions definitions, Cue cue, Position?worldPosition, FadePitchPan fpp, PlayCueParameters parameters, bool playsLocally) { if (parameters.soundIndex < 0) { return; } if (!playsLocally || !AudioDevice.Available) { return; // <- nothing to do! } if (doingPrediction) // Re-prediction following rollback { if (activeFrame >= liveFrame - DontCareLimit) // <- new enough that we could still be tracking it { if (!TryKillCueExact(cue, activeFrame, worldPosition)) { if (activeFrame >= liveFrame - MaximumSoundShift) // <- new enough that we may play it { PendingCue pending; pending.cue = cue; pending.parameters = parameters; pending.frame = activeFrame; pending.position = worldPosition; pending.fpp = fpp; pendingCues.Add(pending); } } } } else // Standard playback { Debug.Assert(activeFrame == liveFrame); if (!rollbackAware || !TryKillCueFuzzy(cue, activeFrame, worldPosition)) { if (!doingStartupPrediction) { SoundEffectManager.PlayCueSkipMissingCheck(definitions, cue, parameters, fpp); } AddLiveCueNow(cue, worldPosition); } } }
/// <summary>Call this only when PlayCueParameters have been validated</summary> public static void PlayCueSkipMissingCheck(IAudioDefinitions definitions, Cue cue, PlayCueParameters parameters, FadePitchPan fpp, bool loop = false) { fpp.fade = MathHelper.Clamp(fpp.fade * cue.volume, 0, 1); fpp.pitch = MathHelper.Clamp(fpp.pitch + parameters.cuePitch, -1, 1); fpp.pan = MathHelper.Clamp(fpp.pan + cue.pan, -1, 1); if (fpp.fade < 0.01f) { return; // too quiet to care about } if (cue.SoundCount == 0) { return; // <- nothing to play } lock (lockObject) { switch (cue.type) { case CueType.Parallel: { for (int i = 0; i < cue.SoundCount; i++) { AddAndStartPlaying(definitions.GetSound(cue, i), fpp, loop); } } break; case CueType.Serial: { // Build the queue for the cue: int queueHead = -1; for (int i = cue.SoundCount - 1; i >= 1; i--) { int q = AllocateQueuedSound(); queuedSounds[q].sound = definitions.GetSound(cue, i); queuedSounds[q].next = queueHead; queueHead = q; } AddAndStartPlaying(definitions.GetSound(cue, 0), fpp, loop, queueHead); } break; default: { AddAndStartPlaying(definitions.GetSound(cue, parameters.soundIndex), fpp, loop); } break; } } }