예제 #1
0
        public void AfterRollbackAwareFrame(IAudioDefinitions definitions)
        {
            Debug.Assert(rollbackAware);

            if (doingPrediction)
            {
                if (activeFrame == liveFrame)                 // Completed re-simulation of rollback frames
                {
                    doingPrediction = false;

                    foreach (var pending in pendingCues)
                    {
                        if (!TryKillCueFuzzy(pending.cue, activeFrame, pending.position))
                        {
                            if (!doingStartupPrediction)
                            {
                                SoundEffectManager.PlayCueSkipMissingCheck(definitions, pending.cue, pending.parameters,
                                                                           pending.fpp);
                            }
                            AddLiveCueNow(pending.cue, pending.position);
                        }
                    }

                    pendingCues.Clear();
                }
            }
        }
예제 #2
0
        /// <summary>Potentially gameplay-mutating logic for cue playback (modifies `random` and `cueStates`)</summary>
        public static PlayCueParameters GetParameters(IAudioDefinitions definitions, Cue cue, XorShift random, ushort[] cueStates)
        {
            if (cue == null)
            {
                return new PlayCueParameters {
                           soundIndex = PlayCueParameters.NO_SOUND
                }
            }
            ;
            if (ReferenceEquals(cue, Cue.missingCue))
            {
                return new PlayCueParameters {
                           soundIndex = PlayCueParameters.MISSING_CUE
                }
            }
            ;
            if (cue.SoundCount == 0)
            {
                return new PlayCueParameters {
                           soundIndex = PlayCueParameters.NO_SOUND
                }
            }
            ;

            PlayCueParameters result;

            result.cuePitch   = cue.SelectPitch(random);
            result.soundIndex = cue.SelectSound(random, cueStates);

            Debug.Assert(result.soundIndex >= 0);

            return(result);
        }
    }
}
예제 #3
0
        /// <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  = AudioMath.Clamp(fpp.fade * cue.volume, 0, 1);
            fpp.pitch = AudioMath.Clamp(fpp.pitch + parameters.cuePitch, -1, 1);
            fpp.pan   = AudioMath.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 (var i = 0; i < cue.SoundCount; i++)
                    {
                        AddAndStartPlaying(definitions.GetSound(cue, i), fpp, loop);
                    }
                }
                break;

                case CueType.Serial:
                {
                    // Build the queue for the cue:
                    var queueHead = -1;
                    for (var i = cue.SoundCount - 1; i >= 1; i--)
                    {
                        var 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;
                }
            }
        }
예제 #4
0
        /// <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);
        }
예제 #5
0
        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);
        }
예제 #6
0
        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);
                }
            }
        }