diff --git a/Assets/Resources/Games/fanClub.prefab b/Assets/Resources/Games/fanClub.prefab index 9ee33e2fe..8bef962bd 100644 --- a/Assets/Resources/Games/fanClub.prefab +++ b/Assets/Resources/Games/fanClub.prefab @@ -22473,6 +22473,145 @@ MonoBehaviour: m_Script: {fileID: 11500000, guid: c8bf5d56f80c8814489e7b35cc9421ff, type: 3} m_Name: m_EditorClassIdentifier: + SoundSequences: + - name: arisa_hai + sequence: + game: 1 + force: 0 + clips: + - clip: fanClub/arisa_hai_1_jp + beat: 0 + pitch: 1 + volume: 1 + looping: 0 + offset: 0 + - clip: fanClub/arisa_hai_2_jp + beat: 1 + pitch: 1 + volume: 1 + looping: 0 + offset: 0 + - clip: fanClub/arisa_hai_3_jp + beat: 2 + pitch: 1 + volume: 1 + looping: 0 + offset: 0 + - name: crowd_hai + sequence: + game: 1 + force: 0 + clips: + - clip: fanClub/crowd_hai_jp + beat: 0 + pitch: 1 + volume: 1 + looping: 0 + offset: 0 + - clip: fanClub/crowd_hai_jp + beat: 1 + pitch: 1 + volume: 1 + looping: 0 + offset: 0 + - clip: fanClub/crowd_hai_jp + beat: 2 + pitch: 1 + volume: 1 + looping: 0 + offset: 0 + - clip: fanClub/crowd_hai_jp + beat: 3 + pitch: 1 + volume: 1 + looping: 0 + offset: 0 + - name: arisa_kamone + sequence: + game: 1 + force: 0 + clips: + - clip: fanClub/arisa_ka_jp + beat: 0 + pitch: 1 + volume: 1 + looping: 0 + offset: 0 + - clip: fanClub/arisa_mo_jp + beat: 0.5 + pitch: 1 + volume: 1 + looping: 0 + offset: 0.07407407 + - clip: fanClub/arisa_ne_jp + beat: 1 + pitch: 1 + volume: 1 + looping: 0 + offset: 0.07407407 + - name: arisa_kamone_fast + sequence: + game: 1 + force: 0 + clips: + - clip: fanClub/arisa_ka_fast_jp + beat: 0 + pitch: 1 + volume: 1 + looping: 0 + offset: 0 + - clip: fanClub/arisa_mo_fast_jp + beat: 0.25 + pitch: 1 + volume: 1 + looping: 0 + offset: 0 + - clip: fanClub/arisa_ne_fast_jp + beat: 0.5 + pitch: 1 + volume: 1 + looping: 0 + offset: 0 + - name: crowd_kamone + sequence: + game: 1 + force: 0 + clips: + - clip: fanClub/crowd_ka_jp + beat: 0 + pitch: 1 + volume: 1 + looping: 0 + offset: 0 + - clip: fanClub/crowd_mo_jp + beat: 1.5 + pitch: 1 + volume: 1 + looping: 0 + offset: 0 + - clip: fanClub/crowd_ne_jp + beat: 2 + pitch: 1 + volume: 1 + looping: 0 + offset: 0 + - clip: fanClub/crowd_hey_jp + beat: 3 + pitch: 1 + volume: 1 + looping: 0 + offset: 0 + - name: crowd_big_ready + sequence: + game: 1 + force: 0 + clips: + - clip: fanClub/crowd_big_ready + beat: 0 + pitch: 1 + volume: 1 + looping: 0 + offset: 0 EligibleHits: [] scheduledInputs: [] firstEnable: 0 diff --git a/Assets/Scripts/Common/SoundSequence.cs b/Assets/Scripts/Common/SoundSequence.cs new file mode 100644 index 000000000..07a7db882 --- /dev/null +++ b/Assets/Scripts/Common/SoundSequence.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.ComponentModel; +using UnityEngine; + +namespace HeavenStudio.Util +{ + /// + /// MultiSound that is serializable in the inspector, etc. + /// + [Serializable] + public class SoundSequence + { + [Tooltip("Should sequence use game specific-sounds?")] + [SerializeField] bool game; + [Tooltip("Should sequence force playback even if corresponding game is not loaded?")] + [SerializeField] bool force; + [Tooltip("Clips to play in the sequence")] + [SerializeField] private List clips = new List(); + + public SoundSequence(bool game, bool force, params SequenceClip[] clips) + { + this.game = game; + this.force = force; + this.clips = new List(clips); + } + + public MultiSound Play(float startBeat) + { + List sounds = new List(); + + foreach (SequenceClip clip in clips) + { + sounds.Add(new MultiSound.Sound(clip.clip, startBeat + clip.beat, clip.pitch, clip.volume, clip.looping, clip.offset)); + } + + return MultiSound.Play(sounds.ToArray(), game, force); + } + + [Serializable] + public struct SequenceClip + { + public SequenceClip(string clip, float beat, float pitch = 1f, float volume = 1f, bool looping = false, float offset = 0f) + { + this.clip = clip; + this.beat = beat; + this.pitch = pitch; + this.volume = volume; + this.looping = looping; + this.offset = offset; + } + + [Tooltip("Filename of clip to use (will look in assetbundles before resources)")] + public string clip; + [Tooltip("Beat to play clip at relative to start of sequence")] + public float beat; + [Tooltip("Pitch to play clip at")] + [DefaultValue(1f)] + public float pitch; + [Tooltip("Volume to play clip at")] + [DefaultValue(1f)] + public float volume; + [Tooltip("Whether to loop the clip")] + public bool looping; + [Tooltip("Offset to start playing clip")] + public float offset; + } + + [Serializable] + public struct SequenceKeyValue + { + [Tooltip("Name of sequence (game scripts will call sequences to play using this name")] + public string name; + [Tooltip("Sequence to play")] + public SoundSequence sequence; + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Common/SoundSequence.cs.meta b/Assets/Scripts/Common/SoundSequence.cs.meta new file mode 100644 index 000000000..49732e379 --- /dev/null +++ b/Assets/Scripts/Common/SoundSequence.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 643b435927934b34599a4250da088992 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Conductor.cs b/Assets/Scripts/Conductor.cs index 79cb58efb..f494d7b53 100644 --- a/Assets/Scripts/Conductor.cs +++ b/Assets/Scripts/Conductor.cs @@ -22,16 +22,22 @@ namespace HeavenStudio // Current song position, in seconds private double songPos; // for Conductor use only public float songPosition => (float) songPos; + public double songPositionAsDouble => songPos; // Current song position, in beats private double songPosBeat; // for Conductor use only public float songPositionInBeats => (float) songPosBeat; + public double songPositionInBeatsAsDouble => songPosBeat; // Current time of the song private double time; double lastAbsTime; + // the dspTime we started at + private double dspStartTime; + public double dspStartTimeAsDouble => dspStartTime; + // an AudioSource attached to this GameObject that will play the music. public AudioSource musicSource; @@ -52,6 +58,7 @@ namespace HeavenStudio // Metronome tick sound enabled public bool metronome = false; + Util.Sound metronomeSound; public float timeSinceLastTempoChange = Single.MinValue; @@ -142,6 +149,7 @@ namespace HeavenStudio } } lastAbsTime = Time.realtimeSinceStartupAsDouble; + dspStartTime = AudioSettings.dspTime; // GameManager.instance.SetCurrentEventToClosest(songPositionInBeats); } @@ -189,13 +197,21 @@ namespace HeavenStudio { if (ReportBeat(ref lastReportedBeat)) { - Util.Jukebox.PlayOneShot("metronome"); + metronomeSound = Util.Jukebox.PlayOneShot("metronome", lastReportedBeat + 1f); } else if (songPositionInBeats < lastReportedBeat) { lastReportedBeat = Mathf.Round(songPositionInBeats); } } + else + { + if (metronomeSound != null) + { + metronomeSound.Delete(); + metronomeSound = null; + } + } } public bool ReportBeat(ref float lastReportedBeat, float offset = 0, bool shiftBeatToOffset = true) diff --git a/Assets/Scripts/EventCaller.cs b/Assets/Scripts/EventCaller.cs index 7d687e1dc..6247214fd 100644 --- a/Assets/Scripts/EventCaller.cs +++ b/Assets/Scripts/EventCaller.cs @@ -89,6 +89,23 @@ namespace HeavenStudio } } + public void CallPreEvent(DynamicBeatmap.DynamicEntity entity) + { + string[] details = entity.datamodel.Split('/'); + Minigames.Minigame game = minigames.Find(c => c.name == details[0]); + try + { + currentEntity = entity; + + Minigames.GameAction action = game.actions.Find(c => c.actionName == details[1]); + action.preFunction.Invoke(); + } + catch (Exception ex) + { + Debug.LogWarning("Event not found! May be spelled wrong or it is not implemented.\n" + ex); + } + } + public static List GetAllInGameManagerList(string gameName, string[] include) { List temp1 = GameManager.instance.Beatmap.entities.FindAll(c => c.datamodel.Split('/')[0] == gameName); diff --git a/Assets/Scripts/GameManager.cs b/Assets/Scripts/GameManager.cs index 35d028c2f..876bf42a3 100644 --- a/Assets/Scripts/GameManager.cs +++ b/Assets/Scripts/GameManager.cs @@ -33,7 +33,7 @@ namespace HeavenStudio [Header("Properties")] public int currentEvent, currentTempoEvent, currentVolumeEvent, currentSectionEvent, - currentPreEvent, currentPreSwitch; + currentPreEvent, currentPreSwitch, currentPreSequence; public float endBeat; public float startOffset; public bool playOnStart; @@ -48,7 +48,7 @@ namespace HeavenStudio return (Conductor.instance.songPositionInBeats - currentSection.beat) / (nextSection.beat - currentSection.beat); }} - public event Action onBeatChanged; + public event Action onBeatChanged; public event Action onSectionChange; public int BeatmapEntities() @@ -69,6 +69,7 @@ namespace HeavenStudio { currentPreEvent= 0; currentPreSwitch = 0; + currentPreSequence = 0; this.transform.localScale = new Vector3(30000000, 30000000); @@ -219,6 +220,24 @@ namespace HeavenStudio } } + public void SeekAheadAndDoPreEvent(float start, float seekTime = 1f) + { + List entities = Beatmap.entities.Select(c => c.beat).ToList(); + if (currentPreSequence < Beatmap.entities.Count && currentPreSequence >= 0) + { + if (start + seekTime >= entities[currentPreSequence]) + { + float beat = Beatmap.entities[currentPreSequence].beat; + var entitiesAtSameBeat = Beatmap.entities.FindAll(c => c.beat == Beatmap.entities[currentPreSequence].beat); + foreach (DynamicBeatmap.DynamicEntity entity in entitiesAtSameBeat) + { + eventCaller.CallPreEvent(entity); + } + currentPreSequence++; + } + } + } + // LateUpdate works a bit better(?) but causes some bugs (like issues with bop animations). private void Update() { @@ -272,6 +291,8 @@ namespace HeavenStudio //seek ahead to preload games that have assetbundles SeekAheadAndPreload(Conductor.instance.songPositionInBeats, seekTime); + SeekAheadAndDoPreEvent(Conductor.instance.songPositionInBeats, 1f); + if (currentEvent < Beatmap.entities.Count && currentEvent >= 0) { if (Conductor.instance.songPositionInBeats >= entities[currentEvent] /*&& SongPosLessThanClipLength(Conductor.instance.songPositionInBeats)*/) @@ -390,6 +411,7 @@ namespace HeavenStudio currentEvent = entities.IndexOf(Mathp.GetClosestInList(entities, beat)); currentPreEvent = entities.IndexOf(Mathp.GetClosestInList(entities, beat)); + currentPreSequence = entities.IndexOf(Mathp.GetClosestInList(entities, beat)); var gameSwitchs = Beatmap.entities.FindAll(c => c.datamodel.Split(1) == "switchGame"); diff --git a/Assets/Scripts/Games/DJSchool/Student.cs b/Assets/Scripts/Games/DJSchool/Student.cs index ef7958794..a2c1f2009 100644 --- a/Assets/Scripts/Games/DJSchool/Student.cs +++ b/Assets/Scripts/Games/DJSchool/Student.cs @@ -160,7 +160,7 @@ namespace HeavenStudio.Games.Scripts_DJSchool tableAnim.speed = 1; tableAnim.Play("Student_Turntable_Swipe", 0, 0); - Instantiate(slamFX).SetActive(true); + Instantiate(slamFX, this.transform.parent).SetActive(true); mixer.audioMixer.FindSnapshot("Main").TransitionTo(.01f); } else @@ -177,7 +177,7 @@ namespace HeavenStudio.Games.Scripts_DJSchool tableAnim.speed = 1; tableAnim.Play("Student_Turntable_Swipe", 0, 0); - Instantiate(slamFX).SetActive(true); + Instantiate(slamFX, this.transform.parent).SetActive(true); mixer.audioMixer.FindSnapshot("Main").TransitionTo(.01f); } diff --git a/Assets/Scripts/Games/FanClub/FanClub.cs b/Assets/Scripts/Games/FanClub/FanClub.cs index 5594d2fcc..571134539 100644 --- a/Assets/Scripts/Games/FanClub/FanClub.cs +++ b/Assets/Scripts/Games/FanClub/FanClub.cs @@ -182,7 +182,6 @@ namespace HeavenStudio.Games private void Awake() { instance = this; - Spectators = new List(); idolAnimator = Arisa.GetComponent(); @@ -528,12 +527,7 @@ namespace HeavenStudio.Games public void CallHai(float beat, bool noSound = false, int type = 0) { if (!noSound) - MultiSound.Play(new MultiSound.Sound[] { - new MultiSound.Sound("fanClub/arisa_hai_1_jp", beat), - new MultiSound.Sound("fanClub/arisa_hai_2_jp", beat + 1f), - new MultiSound.Sound("fanClub/arisa_hai_3_jp", beat + 2f), - }); - + PlaySoundSequence("arisa_hai", beat); responseToggle = false; DisableBop(beat, 8f); @@ -556,12 +550,7 @@ namespace HeavenStudio.Games new BeatAction.Action(beat + 7f, delegate { PlayOneClap(beat + 7f); DoIdolClaps();}), }); - MultiSound.Play(new MultiSound.Sound[] { - new MultiSound.Sound("fanClub/crowd_hai_jp", beat + 4f), - new MultiSound.Sound("fanClub/crowd_hai_jp", beat + 5f), - new MultiSound.Sound("fanClub/crowd_hai_jp", beat + 6f), - new MultiSound.Sound("fanClub/crowd_hai_jp", beat + 7f), - }); + PlaySoundSequence("crowd_hai", beat + 4f); } public static void WarnHai(float beat, bool noSound = false, int type = 0) @@ -586,27 +575,12 @@ namespace HeavenStudio.Games bool doJump = (responseType == (int) KamoneResponseType.Jump || responseType == (int) KamoneResponseType.JumpFast); bool isBig = (responseType == (int) KamoneResponseType.ThroughFast || responseType == (int) KamoneResponseType.JumpFast); DisableResponse(beat, 2f); - if (isBig) + if (!noSound) { - if (!noSound) - { - MultiSound.Play(new MultiSound.Sound[] { - new MultiSound.Sound("fanClub/arisa_ka_fast_jp", beat), - new MultiSound.Sound("fanClub/arisa_mo_fast_jp", beat + 0.25f), - new MultiSound.Sound("fanClub/arisa_ne_fast_jp", beat + 0.5f), - }); - } - } - else - { - if (!noSound) - { - MultiSound.Play(new MultiSound.Sound[] { - new MultiSound.Sound("fanClub/arisa_ka_jp", beat), - new MultiSound.Sound("fanClub/arisa_mo_jp", beat + 0.5f, offset: 0.07407407f), - new MultiSound.Sound("fanClub/arisa_ne_jp", beat + 1f, offset: 0.07407407f), - }); - } + if (isBig) + PlaySoundSequence("arisa_kamone_fast", beat); + else + PlaySoundSequence("arisa_kamone", beat); } responseToggle = true; @@ -640,12 +614,7 @@ namespace HeavenStudio.Games }), }); - MultiSound.Play(new MultiSound.Sound[] { - new MultiSound.Sound("fanClub/crowd_ka_jp", beat + 2f), - new MultiSound.Sound("fanClub/crowd_mo_jp", beat + 3.5f), - new MultiSound.Sound("fanClub/crowd_ne_jp", beat + 4f), - new MultiSound.Sound("fanClub/crowd_hey_jp", beat + 5f), - }); + PlaySoundSequence("crowd_kamone", beat + 2f); } public static void WarnKamone(float beat, bool noSound = false, int type = 0, int responseType = (int) KamoneResponseType.Through) @@ -679,11 +648,11 @@ namespace HeavenStudio.Games const float BIGCALL_LENGTH = 2.75f; public void CallBigReady(float beat, bool noSound = false) { + if (!noSound) + PlaySoundSequence("crowd_big_ready", beat); + Prepare(beat + 1.5f); Prepare(beat + 2f); - - if (!noSound) - Jukebox.PlayOneShotGame("fanClub/crowd_big_ready"); DisableSpecBop(beat, 3.75f); @@ -701,7 +670,7 @@ namespace HeavenStudio.Games { wantBigReady = beat; if (noSound) return; - Jukebox.PlayOneShotGame("fanClub/crowd_big_ready"); + Jukebox.PlayOneShotGame("fanClub/crowd_big_ready", beat); } public void ContinueBigReady(float beat) diff --git a/Assets/Scripts/Games/Minigame.cs b/Assets/Scripts/Games/Minigame.cs index 558bd1aac..a3703b7eb 100644 --- a/Assets/Scripts/Games/Minigame.cs +++ b/Assets/Scripts/Games/Minigame.cs @@ -2,11 +2,15 @@ using System.Collections; using System.Collections.Generic; using UnityEngine; +using HeavenStudio.Util; + namespace HeavenStudio.Games { public class Minigame : MonoBehaviour { public static float earlyTime = 0.1f, perfectTime = 0.08f, aceEarlyTime = 0.025f, aceLateTime = 0.025f, lateTime = 0.08f, endTime = 0.1f; + [SerializeField] public SoundSequence.SequenceKeyValue[] SoundSequences; + public List EligibleHits = new List(); [System.Serializable] @@ -211,5 +215,18 @@ namespace HeavenStudio.Games return sameTime; } + + public MultiSound PlaySoundSequence(string name, float startBeat) + { + foreach (SoundSequence.SequenceKeyValue pair in SoundSequences) + { + if (pair.name == name) + { + return pair.sequence.Play(startBeat); + } + } + Debug.LogWarning($"Sound sequence {name} not found in game {this.name} (did you build AssetBundles?)"); + return null; + } } } diff --git a/Assets/Scripts/Games/PajamaParty/PajamaParty.cs b/Assets/Scripts/Games/PajamaParty/PajamaParty.cs index 1e6e82c8f..ed4b383a0 100644 --- a/Assets/Scripts/Games/PajamaParty/PajamaParty.cs +++ b/Assets/Scripts/Games/PajamaParty/PajamaParty.cs @@ -37,7 +37,7 @@ namespace HeavenStudio.Games.Loaders new Param("type", PajamaParty.SleepType.Normal, "Sleep Type", "Type of sleep action to use"), new Param("toggle", false, "Alt. Animation", "Use an alternate animation for Mako") }, - inactiveFunction = delegate {var e = eventCaller.currentEntity; PajamaParty.WarnSleepSequence(e.beat, e["toggle"]);} + inactiveFunction = delegate {var e = eventCaller.currentEntity; PajamaParty.WarnSleepSequence(e.beat, e["toggle"], e["type"]);} }, new GameAction("throw", "Throw Pillows") { @@ -280,7 +280,7 @@ namespace HeavenStudio.Games }); } - public static void WarnSleepSequence(float beat, bool alt = false) + public static void WarnSleepSequence(float beat, bool alt = false, int action = (int) PajamaParty.SleepType.Normal) { MultiSound.Play(new MultiSound.Sound[] { new MultiSound.Sound("pajamaParty/siesta1", beat), @@ -291,6 +291,7 @@ namespace HeavenStudio.Games }, forcePlay: true); WantSleepSequence = beat; WantSleepType = alt; + WantSleepAction = action; } public void DoBedImpact() diff --git a/Assets/Scripts/Minigames.cs b/Assets/Scripts/Minigames.cs index 3691f9402..4f4df7d9a 100644 --- a/Assets/Scripts/Minigames.cs +++ b/Assets/Scripts/Minigames.cs @@ -20,6 +20,7 @@ namespace HeavenStudio { public class Minigame { + public string name; public string displayName; public string color; diff --git a/Assets/Scripts/Util/Jukebox.cs b/Assets/Scripts/Util/Jukebox.cs index 404848dc2..6f26cbe39 100644 --- a/Assets/Scripts/Util/Jukebox.cs +++ b/Assets/Scripts/Util/Jukebox.cs @@ -151,8 +151,6 @@ namespace HeavenStudio.Util return null; } - //TODO: playing sounds from assetbundles - public static void KillLoop(Sound source, float fadeTime) { // Safeguard against previously-destroyed sounds. diff --git a/Assets/Scripts/Util/MultiSound.cs b/Assets/Scripts/Util/MultiSound.cs index 3b1b6cda6..9aae9e3a2 100644 --- a/Assets/Scripts/Util/MultiSound.cs +++ b/Assets/Scripts/Util/MultiSound.cs @@ -8,10 +8,10 @@ namespace HeavenStudio.Util public class MultiSound : MonoBehaviour { private float startBeat; - private int index; private bool game; private bool forcePlay; public List sounds = new List(); + public List playingSounds = new List(); public class Sound { @@ -37,39 +37,35 @@ namespace HeavenStudio.Util public static MultiSound Play(Sound[] snds, bool game = true, bool forcePlay = false) { List sounds = snds.ToList(); - GameObject gameObj = new GameObject(); - MultiSound ms = gameObj.AddComponent(); + GameObject go = new GameObject("MultiSound"); + MultiSound ms = go.AddComponent(); ms.sounds = sounds; ms.startBeat = sounds[0].beat; ms.game = game; ms.forcePlay = forcePlay; - gameObj.name = "MultiSound"; - GameManager.instance.SoundObjects.Add(gameObj); + for (int i = 0; i < sounds.Count; i++) + { + Util.Sound s; + if (game) + s = Jukebox.PlayOneShotGame(sounds[i].name, sounds[i].beat - Conductor.instance.GetRestFromRealTime(sounds[i].offset), sounds[i].pitch, sounds[i].volume, sounds[i].looping, forcePlay); + else + s = Jukebox.PlayOneShot(sounds[i].name, sounds[i].beat - Conductor.instance.GetRestFromRealTime(sounds[i].offset), sounds[i].pitch, sounds[i].volume, sounds[i].looping); + ms.playingSounds.Add(s); + } + + GameManager.instance.SoundObjects.Add(go); return ms; } private void Update() { - float songPositionInBeats = Conductor.instance.songPositionInBeats; - - for (int i = 0; i < sounds.Count; i++) + foreach (Util.Sound sound in playingSounds) { - if (songPositionInBeats >= sounds[i].beat - Conductor.instance.GetRestFromRealTime(sounds[i].offset) && index == i) - { - if (game) - Jukebox.PlayOneShotGame(sounds[i].name, sounds[i].beat - Conductor.instance.GetRestFromRealTime(sounds[i].offset), sounds[i].pitch, sounds[i].volume, sounds[i].looping, forcePlay); - else - Jukebox.PlayOneShot(sounds[i].name, sounds[i].beat - Conductor.instance.GetRestFromRealTime(sounds[i].offset), sounds[i].pitch, sounds[i].volume, sounds[i].looping); - - index++; - } - } - - if (songPositionInBeats >= (sounds[sounds.Count - 1].beat - Conductor.instance.GetRestFromRealTime(sounds[sounds.Count - 1].offset))) - { - Delete(); + if (sound != null) + return; } + Delete(); } public void Delete() diff --git a/Assets/Scripts/Util/Sound.cs b/Assets/Scripts/Util/Sound.cs index 8384bee1e..e0f11f88d 100644 --- a/Assets/Scripts/Util/Sound.cs +++ b/Assets/Scripts/Util/Sound.cs @@ -23,12 +23,13 @@ namespace HeavenStudio.Util private int pauseTimes = 0; - private float startTime; + private double startTime; public float beat; + public float scheduledPitch = 1f; bool playInstant = false; - int playIndex = 0; + bool played = false; private void Start() { @@ -40,39 +41,50 @@ namespace HeavenStudio.Util if (beat == -1 && !scheduled) { - audioSource.PlayScheduled(Time.time); + audioSource.PlayScheduled(AudioSettings.dspTime); playInstant = true; - playIndex++; + played = true; + startTime = Conductor.instance.songPositionAsDouble; + StartCoroutine(NotRelyOnBeatSound()); } else { playInstant = false; + scheduledPitch = Conductor.instance.musicSource.pitch; + startTime = (AudioSettings.dspTime + (Conductor.instance.GetSongPosFromBeat(beat) - Conductor.instance.songPositionAsDouble)/(double)scheduledPitch); + audioSource.PlayScheduled(startTime); + Debug.Log($"Scheduling future sound {clip.name} for beat {beat} (scheduled: {startTime}, current time: {AudioSettings.dspTime})"); } - - startTime = Conductor.instance.songPosition; - - if (!scheduled && !looping) - StartCoroutine(NotRelyOnBeatSound()); } private void Update() { - if (playIndex < 1) + if (!played) { if (scheduled) { if (AudioSettings.dspTime > scheduledTime) { StartCoroutine(NotRelyOnBeatSound()); - playIndex++; + played = true; } } else if (!playInstant) { - if (Conductor.instance.songPositionInBeats > beat) + if (AudioSettings.dspTime > startTime) { - audioSource.PlayScheduled(Time.time); - playIndex++; + played = true; + StartCoroutine(NotRelyOnBeatSound()); + } + else + { + if (!played && scheduledPitch != Conductor.instance.musicSource.pitch) + { + scheduledPitch = Conductor.instance.musicSource.pitch; + startTime = (AudioSettings.dspTime + (Conductor.instance.GetSongPosFromBeat(beat) - Conductor.instance.songPositionAsDouble)/(double)scheduledPitch); + audioSource.SetScheduledStartTime(startTime); + Debug.Log($"Rescheduling future sound {clip.name} for beat {beat} (scheduled: {startTime}, current time: {AudioSettings.dspTime})"); + } } } } @@ -94,7 +106,7 @@ namespace HeavenStudio.Util { if (!looping) // Looping sounds are destroyed manually. { - yield return new WaitForSeconds(clip.length); + yield return new WaitForSeconds(clip.length / pitch); Delete(); } } diff --git a/Assets/StreamingAssets/StreamingAssets b/Assets/StreamingAssets/StreamingAssets index 024b9ab46..9b421b65a 100644 Binary files a/Assets/StreamingAssets/StreamingAssets and b/Assets/StreamingAssets/StreamingAssets differ diff --git a/Assets/StreamingAssets/StreamingAssets.manifest b/Assets/StreamingAssets/StreamingAssets.manifest index 02a1e402e..e07331984 100644 --- a/Assets/StreamingAssets/StreamingAssets.manifest +++ b/Assets/StreamingAssets/StreamingAssets.manifest @@ -1,5 +1,5 @@ ManifestFileVersion: 0 -CRC: 2362860034 +CRC: 1243838037 AssetBundleManifest: AssetBundleInfos: Info_0: diff --git a/Assets/StreamingAssets/ctrpillow/common b/Assets/StreamingAssets/ctrpillow/common index a043eee05..8e82b1ac0 100644 Binary files a/Assets/StreamingAssets/ctrpillow/common and b/Assets/StreamingAssets/ctrpillow/common differ diff --git a/Assets/StreamingAssets/ctrpillow/common.manifest b/Assets/StreamingAssets/ctrpillow/common.manifest index 73c92e38e..2977095b2 100644 --- a/Assets/StreamingAssets/ctrpillow/common.manifest +++ b/Assets/StreamingAssets/ctrpillow/common.manifest @@ -1,12 +1,12 @@ ManifestFileVersion: 0 -CRC: 4200721013 +CRC: 1167382196 Hashes: AssetFileHash: serializedVersion: 2 - Hash: 996e27defaede200a0288a246ceb7785 + Hash: 91ca0253f29ae5f7a1df107a25dc7c75 TypeTreeHash: serializedVersion: 2 - Hash: 77ce82dcd01e7c9c803f77daf119d967 + Hash: 222d3ac4260743916f7d5e044ddd31d4 HashAppended: 0 ClassTypes: - Class: 1 diff --git a/Assets/StreamingAssets/karate/common b/Assets/StreamingAssets/karate/common index a2eb531f1..bcf93c612 100644 Binary files a/Assets/StreamingAssets/karate/common and b/Assets/StreamingAssets/karate/common differ diff --git a/Assets/StreamingAssets/karate/common.manifest b/Assets/StreamingAssets/karate/common.manifest index 5077cc2ca..e78f21c1a 100644 --- a/Assets/StreamingAssets/karate/common.manifest +++ b/Assets/StreamingAssets/karate/common.manifest @@ -1,12 +1,12 @@ ManifestFileVersion: 0 -CRC: 1499416464 +CRC: 149759227 Hashes: AssetFileHash: serializedVersion: 2 - Hash: 7dbbb737179d1cc7db1edb0a31c7e1ab + Hash: 462778359784eea47ee51c3c63402505 TypeTreeHash: serializedVersion: 2 - Hash: 2b92e6f111bbb24dabe3a2c56ea02b28 + Hash: fc2a2e95963d1b3faf439c84ecb440b4 HashAppended: 0 ClassTypes: - Class: 1 diff --git a/Assets/StreamingAssets/ntrcoin/common b/Assets/StreamingAssets/ntrcoin/common index be4dab67d..3d5672f67 100644 Binary files a/Assets/StreamingAssets/ntrcoin/common and b/Assets/StreamingAssets/ntrcoin/common differ diff --git a/Assets/StreamingAssets/ntrcoin/common.manifest b/Assets/StreamingAssets/ntrcoin/common.manifest index 92af2b011..5276f8bcc 100644 --- a/Assets/StreamingAssets/ntrcoin/common.manifest +++ b/Assets/StreamingAssets/ntrcoin/common.manifest @@ -1,12 +1,12 @@ ManifestFileVersion: 0 -CRC: 3719062968 +CRC: 1663830856 Hashes: AssetFileHash: serializedVersion: 2 - Hash: eee37f302cb3e8cbe079bb5500cb45ed + Hash: 688c0aa50fbd25fe17346b36c6bf2176 TypeTreeHash: serializedVersion: 2 - Hash: 1341d321cd8444a4f78a51a8a0c6daff + Hash: 51d10f004f46f35e758498b711eedb2f HashAppended: 0 ClassTypes: - Class: 1 diff --git a/Assets/StreamingAssets/ntrdj/common b/Assets/StreamingAssets/ntrdj/common index 09658cf4a..1020ed61a 100644 Binary files a/Assets/StreamingAssets/ntrdj/common and b/Assets/StreamingAssets/ntrdj/common differ diff --git a/Assets/StreamingAssets/ntrdj/common.manifest b/Assets/StreamingAssets/ntrdj/common.manifest index 8b5667ac7..2c1a4bfe1 100644 --- a/Assets/StreamingAssets/ntrdj/common.manifest +++ b/Assets/StreamingAssets/ntrdj/common.manifest @@ -1,12 +1,12 @@ ManifestFileVersion: 0 -CRC: 1942609421 +CRC: 3480558300 Hashes: AssetFileHash: serializedVersion: 2 - Hash: 82fbc7ccb21aa83d8663117da7a24cbc + Hash: cfaae0e9f9c81b2d255e8da0db667aae TypeTreeHash: serializedVersion: 2 - Hash: 558e305ab690efbcd3eff9455cc9f4dc + Hash: a669441aae6ee39a06c1090efd6d25bc HashAppended: 0 ClassTypes: - Class: 1 diff --git a/Assets/StreamingAssets/ntridol/common b/Assets/StreamingAssets/ntridol/common index 1c115535a..fb986e9c5 100644 Binary files a/Assets/StreamingAssets/ntridol/common and b/Assets/StreamingAssets/ntridol/common differ diff --git a/Assets/StreamingAssets/ntridol/common.manifest b/Assets/StreamingAssets/ntridol/common.manifest index 53c576154..9211fc380 100644 --- a/Assets/StreamingAssets/ntridol/common.manifest +++ b/Assets/StreamingAssets/ntridol/common.manifest @@ -1,12 +1,12 @@ ManifestFileVersion: 0 -CRC: 2386252366 +CRC: 1706991399 Hashes: AssetFileHash: serializedVersion: 2 - Hash: 6f57f7727dc4903488ea4956307caac1 + Hash: ae519aaff83042895009b1d4dbae0a79 TypeTreeHash: serializedVersion: 2 - Hash: 6f0c5ebd30d7d3be8aad1c86837b5cc9 + Hash: 994ea96351ef9c039cf2db2caf2c1169 HashAppended: 0 ClassTypes: - Class: 1 @@ -50,6 +50,12 @@ ClassTypes: SerializeReferenceClassIdentifiers: - AssemblyName: Assembly-CSharp ClassName: HeavenStudio.Games.Minigame/Eligible +- AssemblyName: Assembly-CSharp + ClassName: HeavenStudio.Util.SoundSequence +- AssemblyName: Assembly-CSharp + ClassName: HeavenStudio.Util.SoundSequence/SequenceClip +- AssemblyName: Assembly-CSharp + ClassName: HeavenStudio.Util.SoundSequence/SequenceKeyValue Assets: - Assets/Resources/Sprites/Games/FanClub/Animations/Arisa/Arrange/IdolBigCall1Arrange.anim - Assets/Resources/Sprites/Games/FanClub/Animations/Fan/Head/FanHead.controller diff --git a/Assets/StreamingAssets/ntrsamurai/common b/Assets/StreamingAssets/ntrsamurai/common index f4e9f1e13..b863692fc 100644 Binary files a/Assets/StreamingAssets/ntrsamurai/common and b/Assets/StreamingAssets/ntrsamurai/common differ diff --git a/Assets/StreamingAssets/ntrsamurai/common.manifest b/Assets/StreamingAssets/ntrsamurai/common.manifest index 5491e2369..3763f619f 100644 --- a/Assets/StreamingAssets/ntrsamurai/common.manifest +++ b/Assets/StreamingAssets/ntrsamurai/common.manifest @@ -1,12 +1,12 @@ ManifestFileVersion: 0 -CRC: 1695511499 +CRC: 3961443211 Hashes: AssetFileHash: serializedVersion: 2 - Hash: 24892cdb3bebaf86064204efdc197727 + Hash: c56eae7afab3c51aa0d877ecb5fa6484 TypeTreeHash: serializedVersion: 2 - Hash: 788d5843115df613774b9a4b273d2334 + Hash: 9a9bdfe5fc84d62897a4e311b61519be HashAppended: 0 ClassTypes: - Class: 1