add background loading of sound sequences

- fix bug with preFunction
- remove most of the old preloading code
This commit is contained in:
minenice55 2023-01-11 17:18:04 -05:00
parent d50c15035d
commit af5eaf9689
22 changed files with 194 additions and 134 deletions

View file

@ -22477,7 +22477,7 @@ MonoBehaviour:
- name: arisa_hai - name: arisa_hai
sequence: sequence:
game: 1 game: 1
force: 0 force: 1
clips: clips:
- clip: fanClub/arisa_hai_1_jp - clip: fanClub/arisa_hai_1_jp
beat: 0 beat: 0
@ -22485,18 +22485,21 @@ MonoBehaviour:
volume: 1 volume: 1
looping: 0 looping: 0
offset: 0 offset: 0
parameters: []
- clip: fanClub/arisa_hai_2_jp - clip: fanClub/arisa_hai_2_jp
beat: 1 beat: 1
pitch: 1 pitch: 1
volume: 1 volume: 1
looping: 0 looping: 0
offset: 0 offset: 0
parameters: []
- clip: fanClub/arisa_hai_3_jp - clip: fanClub/arisa_hai_3_jp
beat: 2 beat: 2
pitch: 1 pitch: 1
volume: 1 volume: 1
looping: 0 looping: 0
offset: 0 offset: 0
parameters: []
- name: crowd_hai - name: crowd_hai
sequence: sequence:
game: 1 game: 1
@ -22508,28 +22511,32 @@ MonoBehaviour:
volume: 1 volume: 1
looping: 0 looping: 0
offset: 0 offset: 0
parameters: []
- clip: fanClub/crowd_hai_jp - clip: fanClub/crowd_hai_jp
beat: 1 beat: 1
pitch: 1 pitch: 1
volume: 1 volume: 1
looping: 0 looping: 0
offset: 0 offset: 0
parameters: []
- clip: fanClub/crowd_hai_jp - clip: fanClub/crowd_hai_jp
beat: 2 beat: 2
pitch: 1 pitch: 1
volume: 1 volume: 1
looping: 0 looping: 0
offset: 0 offset: 0
parameters: []
- clip: fanClub/crowd_hai_jp - clip: fanClub/crowd_hai_jp
beat: 3 beat: 3
pitch: 1 pitch: 1
volume: 1 volume: 1
looping: 0 looping: 0
offset: 0 offset: 0
parameters: []
- name: arisa_kamone - name: arisa_kamone
sequence: sequence:
game: 1 game: 1
force: 0 force: 1
clips: clips:
- clip: fanClub/arisa_ka_jp - clip: fanClub/arisa_ka_jp
beat: 0 beat: 0
@ -22537,22 +22544,25 @@ MonoBehaviour:
volume: 1 volume: 1
looping: 0 looping: 0
offset: 0 offset: 0
parameters: []
- clip: fanClub/arisa_mo_jp - clip: fanClub/arisa_mo_jp
beat: 0.5 beat: 0.5
pitch: 1 pitch: 1
volume: 1 volume: 1
looping: 0 looping: 0
offset: 0.07407407 offset: 0.07407407
parameters: []
- clip: fanClub/arisa_ne_jp - clip: fanClub/arisa_ne_jp
beat: 1 beat: 1
pitch: 1 pitch: 1
volume: 1 volume: 1
looping: 0 looping: 0
offset: 0.07407407 offset: 0.07407407
parameters: []
- name: arisa_kamone_fast - name: arisa_kamone_fast
sequence: sequence:
game: 1 game: 1
force: 0 force: 1
clips: clips:
- clip: fanClub/arisa_ka_fast_jp - clip: fanClub/arisa_ka_fast_jp
beat: 0 beat: 0
@ -22560,18 +22570,21 @@ MonoBehaviour:
volume: 1 volume: 1
looping: 0 looping: 0
offset: 0 offset: 0
parameters: []
- clip: fanClub/arisa_mo_fast_jp - clip: fanClub/arisa_mo_fast_jp
beat: 0.25 beat: 0.25
pitch: 1 pitch: 1
volume: 1 volume: 1
looping: 0 looping: 0
offset: 0 offset: 0
parameters: []
- clip: fanClub/arisa_ne_fast_jp - clip: fanClub/arisa_ne_fast_jp
beat: 0.5 beat: 0.5
pitch: 1 pitch: 1
volume: 1 volume: 1
looping: 0 looping: 0
offset: 0 offset: 0
parameters: []
- name: crowd_kamone - name: crowd_kamone
sequence: sequence:
game: 1 game: 1
@ -22583,28 +22596,32 @@ MonoBehaviour:
volume: 1 volume: 1
looping: 0 looping: 0
offset: 0 offset: 0
parameters: []
- clip: fanClub/crowd_mo_jp - clip: fanClub/crowd_mo_jp
beat: 1.5 beat: 1.5
pitch: 1 pitch: 1
volume: 1 volume: 1
looping: 0 looping: 0
offset: 0 offset: 0
parameters: []
- clip: fanClub/crowd_ne_jp - clip: fanClub/crowd_ne_jp
beat: 2 beat: 2
pitch: 1 pitch: 1
volume: 1 volume: 1
looping: 0 looping: 0
offset: 0 offset: 0
parameters: []
- clip: fanClub/crowd_hey_jp - clip: fanClub/crowd_hey_jp
beat: 3 beat: 3
pitch: 1 pitch: 1
volume: 1 volume: 1
looping: 0 looping: 0
offset: 0 offset: 0
parameters: []
- name: crowd_big_ready - name: crowd_big_ready
sequence: sequence:
game: 1 game: 1
force: 0 force: 1
clips: clips:
- clip: fanClub/crowd_big_ready - clip: fanClub/crowd_big_ready
beat: 0 beat: 0
@ -22612,6 +22629,7 @@ MonoBehaviour:
volume: 1 volume: 1
looping: 0 looping: 0
offset: 0 offset: 0
parameters: []
EligibleHits: [] EligibleHits: []
scheduledInputs: [] scheduledInputs: []
firstEnable: 0 firstEnable: 0

View file

@ -26,13 +26,55 @@ namespace HeavenStudio.Util
this.clips = new List<SequenceClip>(clips); this.clips = new List<SequenceClip>(clips);
} }
public MultiSound Play(float startBeat) public MultiSound Play(float startBeat, params SequenceParams[] args)
{ {
List<MultiSound.Sound> sounds = new List<MultiSound.Sound>(); List<MultiSound.Sound> sounds = new List<MultiSound.Sound>();
Dictionary<string, string> paramMaps = new Dictionary<string, string>();
foreach (SequenceClip clip in clips) foreach (SequenceClip clipdat in clips)
{ {
sounds.Add(new MultiSound.Sound(clip.clip, startBeat + clip.beat, clip.pitch, clip.volume, clip.looping, clip.offset)); string clip = clipdat.clip;
float beat = clipdat.beat;
float pitch = clipdat.pitch;
float volume = clipdat.volume;
bool looping = clipdat.looping;
float offset = clipdat.offset;
if (args != null && clipdat.parameters != null && clipdat.parameters.Length > 0)
{
paramMaps.Clear();
// map param names to overrides
foreach (SequenceParams prm in clipdat.parameters)
{
if (!paramMaps.ContainsKey(prm.name))
paramMaps.Add(prm.name, prm.map);
}
// apply overrides
foreach (SequenceParams prm in args)
{
if (paramMaps.ContainsKey(prm.name))
{
string map = paramMaps[prm.name];
switch (map)
{
case "beat":
beat = prm.value;
break;
case "pitch":
pitch = prm.value;
break;
case "volume":
volume = prm.value;
break;
case "offset":
offset = prm.value;
break;
default:
break;
}
}
}
}
sounds.Add(new MultiSound.Sound(clip, startBeat + beat, pitch, volume, looping, offset));
} }
return MultiSound.Play(sounds.ToArray(), game, force); return MultiSound.Play(sounds.ToArray(), game, force);
@ -41,16 +83,6 @@ namespace HeavenStudio.Util
[Serializable] [Serializable]
public struct SequenceClip 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)")] [Tooltip("Filename of clip to use (will look in assetbundles before resources)")]
public string clip; public string clip;
[Tooltip("Beat to play clip at relative to start of sequence")] [Tooltip("Beat to play clip at relative to start of sequence")]
@ -65,6 +97,9 @@ namespace HeavenStudio.Util
public bool looping; public bool looping;
[Tooltip("Offset to start playing clip")] [Tooltip("Offset to start playing clip")]
public float offset; public float offset;
[Tooltip("Set of possible value overrides for clip data")]
public SequenceParams[] parameters;
} }
[Serializable] [Serializable]
@ -75,5 +110,26 @@ namespace HeavenStudio.Util
[Tooltip("Sequence to play")] [Tooltip("Sequence to play")]
public SoundSequence sequence; public SoundSequence sequence;
} }
[Serializable]
public struct SequenceParams
{
//SequenceParams used in minigame code
public SequenceParams(string name, float value)
{
this.map = "";
this.name = name;
this.value = value;
}
[Tooltip("Inspector use only; Sequence Clip value to override")]
public string map;
[Tooltip("Name of parameter")]
public string name;
[NonSerialized]
public float value;
}
} }
} }

View file

@ -38,6 +38,10 @@ namespace HeavenStudio
private double dspStartTime; private double dspStartTime;
public double dspStartTimeAsDouble => dspStartTime; public double dspStartTimeAsDouble => dspStartTime;
//the beat we started at
private double startBeat;
public double startBeatAsDouble => startBeat;
// an AudioSource attached to this GameObject that will play the music. // an AudioSource attached to this GameObject that will play the music.
public AudioSource musicSource; public AudioSource musicSource;
@ -150,6 +154,7 @@ namespace HeavenStudio
} }
lastAbsTime = Time.realtimeSinceStartupAsDouble; lastAbsTime = Time.realtimeSinceStartupAsDouble;
dspStartTime = AudioSettings.dspTime; dspStartTime = AudioSettings.dspTime;
startBeat = beat;
// GameManager.instance.SetCurrentEventToClosest(songPositionInBeats); // GameManager.instance.SetCurrentEventToClosest(songPositionInBeats);
} }
@ -193,7 +198,7 @@ namespace HeavenStudio
public void LateUpdate() public void LateUpdate()
{ {
if (metronome) if (metronome && isPlaying)
{ {
if (ReportBeat(ref lastReportedBeat)) if (ReportBeat(ref lastReportedBeat))
{ {
@ -260,7 +265,7 @@ namespace HeavenStudio
return GameManager.instance.Beatmap.tempoChanges; return GameManager.instance.Beatmap.tempoChanges;
} }
public double GetSongPosFromBeat(float beat) public double GetSongPosFromBeat(double beat)
{ {
var chart = GameManager.instance.Beatmap; var chart = GameManager.instance.Beatmap;
SetBpm(chart.bpm); SetBpm(chart.bpm);

View file

@ -190,7 +190,7 @@ namespace HeavenStudio
var inf = GetGameInfo(gameName); var inf = GetGameInfo(gameName);
if (inf.usesAssetBundle && !inf.AssetsLoaded) if (inf.usesAssetBundle && !inf.AssetsLoaded)
{ {
Debug.Log("ASYNC loading assetbundle for game " + gameName); Debug.Log($"ASYNC loading assetbundles for game {gameName}");
StartCoroutine(inf.LoadCommonAssetBundleAsync()); StartCoroutine(inf.LoadCommonAssetBundleAsync());
StartCoroutine(inf.LoadLocalizedAssetBundleAsync()); StartCoroutine(inf.LoadLocalizedAssetBundleAsync());
} }
@ -204,23 +204,23 @@ namespace HeavenStudio
if (start + seekTime >= entities[currentPreEvent]) if (start + seekTime >= entities[currentPreEvent])
{ {
var entitiesAtSameBeat = Beatmap.entities.FindAll(c => c.beat == Beatmap.entities[currentPreEvent].beat && !EventCaller.FXOnlyGames().Contains(EventCaller.instance.GetMinigame(c.datamodel.Split('/')[0]))); var entitiesAtSameBeat = Beatmap.entities.FindAll(c => c.beat == Beatmap.entities[currentPreEvent].beat && !EventCaller.FXOnlyGames().Contains(EventCaller.instance.GetMinigame(c.datamodel.Split('/')[0])));
for (int i = 0; i < entitiesAtSameBeat.Count; i++) foreach (DynamicBeatmap.DynamicEntity entity in entitiesAtSameBeat)
{ {
string gameName = entitiesAtSameBeat[i].datamodel.Split('/')[0]; string gameName = entity.datamodel.Split('/')[0];
var inf = GetGameInfo(gameName); var inf = GetGameInfo(gameName);
if (inf.usesAssetBundle && !inf.AssetsLoaded) if (inf.usesAssetBundle && !inf.AssetsLoaded)
{ {
Debug.Log("ASYNC loading assetbundle for game " + gameName); Debug.Log($"ASYNC loading assetbundles for game {gameName}");
StartCoroutine(inf.LoadCommonAssetBundleAsync()); StartCoroutine(inf.LoadCommonAssetBundleAsync());
StartCoroutine(inf.LoadLocalizedAssetBundleAsync()); StartCoroutine(inf.LoadLocalizedAssetBundleAsync());
} }
currentPreEvent++;
} }
currentPreEvent++;
} }
} }
} }
public void SeekAheadAndDoPreEvent(float start, float seekTime = 1f) public void SeekAheadAndDoPreEvent(float start, float seekTime = 2f)
{ {
List<float> entities = Beatmap.entities.Select(c => c.beat).ToList(); List<float> entities = Beatmap.entities.Select(c => c.beat).ToList();
if (currentPreSequence < Beatmap.entities.Count && currentPreSequence >= 0) if (currentPreSequence < Beatmap.entities.Count && currentPreSequence >= 0)
@ -231,9 +231,16 @@ namespace HeavenStudio
var entitiesAtSameBeat = Beatmap.entities.FindAll(c => c.beat == Beatmap.entities[currentPreSequence].beat); var entitiesAtSameBeat = Beatmap.entities.FindAll(c => c.beat == Beatmap.entities[currentPreSequence].beat);
foreach (DynamicBeatmap.DynamicEntity entity in entitiesAtSameBeat) foreach (DynamicBeatmap.DynamicEntity entity in entitiesAtSameBeat)
{ {
string gameName = entity.datamodel.Split('/')[0];
var inf = GetGameInfo(gameName);
if (inf.usesAssetBundle && inf.AssetsLoaded && !inf.SequencesPreloaded)
{
Debug.Log($"Preloading game {gameName}");
PreloadGameSequences(gameName);
}
eventCaller.CallPreEvent(entity); eventCaller.CallPreEvent(entity);
currentPreSequence++;
} }
currentPreSequence++;
} }
} }
} }
@ -291,14 +298,14 @@ namespace HeavenStudio
//seek ahead to preload games that have assetbundles //seek ahead to preload games that have assetbundles
SeekAheadAndPreload(Conductor.instance.songPositionInBeats, seekTime); SeekAheadAndPreload(Conductor.instance.songPositionInBeats, seekTime);
SeekAheadAndDoPreEvent(Conductor.instance.songPositionInBeats, 1f); SeekAheadAndDoPreEvent(Conductor.instance.songPositionInBeats, 2f);
if (currentEvent < Beatmap.entities.Count && currentEvent >= 0) if (currentEvent < Beatmap.entities.Count && currentEvent >= 0)
{ {
if (Conductor.instance.songPositionInBeats >= entities[currentEvent] /*&& SongPosLessThanClipLength(Conductor.instance.songPositionInBeats)*/) if (Conductor.instance.songPositionInBeats >= entities[currentEvent] /*&& SongPosLessThanClipLength(Conductor.instance.songPositionInBeats)*/)
{ {
// allows for multiple events on the same beat to be executed on the same frame, so no more 1-frame delay // allows for multiple events on the same beat to be executed on the same frame, so no more 1-frame delay
var entitiesAtSameBeat = Beatmap.entities.FindAll(c => c.beat == Beatmap.entities[currentEvent].beat && !EventCaller.FXOnlyGames().Contains(EventCaller.instance.GetMinigame(c.datamodel.Split('/')[0]))); var entitiesAtSameBeat = Beatmap.entities.FindAll(c => c.beat == Beatmap.entities[currentEvent].beat && !EventCaller.FXOnlyGames().Contains(EventCaller.instance.GetMinigame(c.datamodel.Split('/')[0])));
var fxEntities = Beatmap.entities.FindAll(c => c.beat == Beatmap.entities[currentEvent].beat && EventCaller.FXOnlyGames().Contains(EventCaller.instance.GetMinigame(c.datamodel.Split('/')[0]))); var fxEntities = Beatmap.entities.FindAll(c => c.beat == Beatmap.entities[currentEvent].beat && EventCaller.FXOnlyGames().Contains(EventCaller.instance.GetMinigame(c.datamodel.Split('/')[0])));
// FX entities should ALWAYS execute before gameplay entities // FX entities should ALWAYS execute before gameplay entities
@ -308,17 +315,16 @@ namespace HeavenStudio
currentEvent++; currentEvent++;
} }
for (int i = 0; i < entitiesAtSameBeat.Count; i++) foreach (DynamicBeatmap.DynamicEntity entity in entitiesAtSameBeat)
{ {
var entity = entitiesAtSameBeat[i];
// if game isn't loaded, preload game so whatever event that would be called will still run outside if needed // if game isn't loaded, preload game so whatever event that would be called will still run outside if needed
if (entitiesAtSameBeat[i].datamodel.Split('/')[0] != currentGame && !preloadedGames.Contains(preloadedGames.Find(c => c.name == entitiesAtSameBeat[i].datamodel.Split('/')[0]))) if (entity.datamodel.Split('/')[0] != currentGame)
{ {
eventCaller.CallEvent(entitiesAtSameBeat[i], false); eventCaller.CallEvent(entity, false);
} }
else else
{ {
eventCaller.CallEvent(entitiesAtSameBeat[i], true); eventCaller.CallEvent(entity, true);
} }
// Thank you to @shshwdr for bring this to my attention // Thank you to @shshwdr for bring this to my attention
@ -328,8 +334,6 @@ namespace HeavenStudio
// currentEvent += gameManagerEntities.Count; // currentEvent += gameManagerEntities.Count;
} }
} }
} }
public void ToggleInputs(bool inputs) public void ToggleInputs(bool inputs)
@ -549,47 +553,21 @@ namespace HeavenStudio
{ {
Destroy(currentGameO); Destroy(currentGameO);
var instantiate = true; currentGameO = Instantiate(GetGame(game));
currentGameO.transform.parent = eventCaller.GamesHolder.transform;
if (preloadedGames.Count > 0) currentGameO.name = game;
{
for (int i = 0; i < preloadedGames.Count; i++)
{
if (preloadedGames[i].gameObject != null)
{
if (preloadedGames[i].gameObject.name == game)
{
preloadedGames[i].SetActive(true);
currentGameO = preloadedGames[i];
preloadedGames.Remove(preloadedGames[i]);
instantiate = false;
}
}
}
}
if (instantiate)
{
currentGameO = Instantiate(GetGame(game));
currentGameO.transform.parent = eventCaller.GamesHolder.transform;
currentGameO.name = game;
}
SetCurrentGame(game); SetCurrentGame(game);
ResetCamera(); ResetCamera();
} }
private void PreloadGame(string game) public void PreloadGameSequences(string game)
{ {
if (preloadedGames.Contains(preloadedGames.Find(c => c.name == game))) var gameInfo = GetGameInfo(game);
return; //load the games' sound sequences
if (gameInfo != null && gameInfo.LoadedSoundSequences == null)
var g = Instantiate(GetGame(game)); gameInfo.LoadedSoundSequences = GetGame(game).GetComponent<Minigame>().SoundSequences;
g.transform.parent = eventCaller.GamesHolder.transform;
g.SetActive(false);
g.name = game;
preloadedGames.Add(g);
} }
public GameObject GetGame(string name) public GameObject GetGame(string name)

View file

@ -31,7 +31,8 @@ namespace HeavenStudio.Games.Loaders
{ {
new Param("toggle", false, "Disable call", "Disable the idol's call") new Param("toggle", false, "Disable call", "Disable the idol's call")
}, },
inactiveFunction = delegate { var e = eventCaller.currentEntity; FanClub.WarnHai(e.beat, e["toggle"]);} inactiveFunction = delegate { var e = eventCaller.currentEntity; FanClub.WarnHai(e.beat, e["toggle"]);},
preFunction = delegate { var e = eventCaller.currentEntity; FanClub.HaiSound(e.beat, e["toggle"]); }
}, },
new GameAction("I suppose", "I Suppose!") new GameAction("I suppose", "I Suppose!")
{ {
@ -42,7 +43,8 @@ namespace HeavenStudio.Games.Loaders
new Param("type", FanClub.KamoneResponseType.Through, "Response type", "Type of response to use"), new Param("type", FanClub.KamoneResponseType.Through, "Response type", "Type of response to use"),
new Param("toggle", false, "Disable call", "Disable the idol's call") new Param("toggle", false, "Disable call", "Disable the idol's call")
}, },
inactiveFunction = delegate { var e = eventCaller.currentEntity; FanClub.WarnKamone(e.beat, e["toggle"], 0, e["type"]);} inactiveFunction = delegate { var e = eventCaller.currentEntity; FanClub.WarnKamone(e.beat, e["toggle"], 0, e["type"]);},
preFunction = delegate { var e = eventCaller.currentEntity; FanClub.KamoneSound(e.beat, e["toggle"], 0, e["type"]); }
}, },
new GameAction("double clap", "Double Clap") new GameAction("double clap", "Double Clap")
{ {
@ -52,7 +54,8 @@ namespace HeavenStudio.Games.Loaders
{ {
new Param("toggle", false, "Disable call", "Disable the call") new Param("toggle", false, "Disable call", "Disable the call")
}, },
inactiveFunction = delegate { var e = eventCaller.currentEntity; FanClub.WarnBigReady(e.beat, e["toggle"]); } inactiveFunction = delegate { var e = eventCaller.currentEntity; FanClub.WarnBigReady(e.beat, e["toggle"]); },
preFunction = delegate { var e = eventCaller.currentEntity; FanClub.BigReadySound(e.beat, e["toggle"]); }
}, },
new GameAction("play idol animation", "Idol Coreography") new GameAction("play idol animation", "Idol Coreography")
{ {
@ -526,8 +529,6 @@ namespace HeavenStudio.Games
const float HAIS_LENGTH = 4.5f; const float HAIS_LENGTH = 4.5f;
public void CallHai(float beat, bool noSound = false, int type = 0) public void CallHai(float beat, bool noSound = false, int type = 0)
{ {
if (!noSound)
PlaySoundSequence("arisa_hai", beat);
responseToggle = false; responseToggle = false;
DisableBop(beat, 8f); DisableBop(beat, 8f);
@ -550,20 +551,21 @@ namespace HeavenStudio.Games
new BeatAction.Action(beat + 7f, delegate { PlayOneClap(beat + 7f); DoIdolClaps();}), new BeatAction.Action(beat + 7f, delegate { PlayOneClap(beat + 7f); DoIdolClaps();}),
}); });
PlaySoundSequence("crowd_hai", beat + 4f); PlaySoundSequence("fanClub", "crowd_hai", beat + 4f);
} }
public static void WarnHai(float beat, bool noSound = false, int type = 0) public static void WarnHai(float beat, bool noSound = false, int type = 0)
{ {
wantHais = beat; wantHais = beat;
if (noSound) return;
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),
}, forcePlay:true);
} }
public static void HaiSound(float beat, bool noSound = false, int type = 0)
{
if (noSound) return;
PlaySoundSequence("fanClub", "arisa_hai", beat);
}
public void ContinueHais(float beat, int type = 0) public void ContinueHais(float beat, int type = 0)
{ {
CallHai(beat, true, type); CallHai(beat, true, type);
@ -575,13 +577,6 @@ namespace HeavenStudio.Games
bool doJump = (responseType == (int) KamoneResponseType.Jump || responseType == (int) KamoneResponseType.JumpFast); bool doJump = (responseType == (int) KamoneResponseType.Jump || responseType == (int) KamoneResponseType.JumpFast);
bool isBig = (responseType == (int) KamoneResponseType.ThroughFast || responseType == (int) KamoneResponseType.JumpFast); bool isBig = (responseType == (int) KamoneResponseType.ThroughFast || responseType == (int) KamoneResponseType.JumpFast);
DisableResponse(beat, 2f); DisableResponse(beat, 2f);
if (!noSound)
{
if (isBig)
PlaySoundSequence("arisa_kamone_fast", beat);
else
PlaySoundSequence("arisa_kamone", beat);
}
responseToggle = true; responseToggle = true;
DisableBop(beat, (doJump) ? 6.25f : 5.25f); DisableBop(beat, (doJump) ? 6.25f : 5.25f);
@ -614,29 +609,25 @@ namespace HeavenStudio.Games
}), }),
}); });
PlaySoundSequence("crowd_kamone", beat + 2f); PlaySoundSequence("fanClub", "crowd_kamone", beat + 2f);
} }
public static void WarnKamone(float beat, bool noSound = false, int type = 0, int responseType = (int) KamoneResponseType.Through) public static void WarnKamone(float beat, bool noSound = false, int type = 0, int responseType = (int) KamoneResponseType.Through)
{ {
wantKamone = beat; wantKamone = beat;
wantKamoneType = responseType; wantKamoneType = responseType;
}
public static void KamoneSound(float beat, bool noSound = false, int type = 0, int responseType = (int) KamoneResponseType.Through)
{
if (noSound) return; if (noSound) return;
if (responseType == (int) KamoneResponseType.ThroughFast || responseType == (int) KamoneResponseType.JumpFast) if (responseType == (int) KamoneResponseType.ThroughFast || responseType == (int) KamoneResponseType.JumpFast)
{ {
MultiSound.Play(new MultiSound.Sound[] { PlaySoundSequence("fanClub", "arisa_kamone_fast", beat);
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),
}, forcePlay:true);
} }
else else
{ {
MultiSound.Play(new MultiSound.Sound[] { PlaySoundSequence("fanClub", "arisa_kamone", beat);
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),
}, forcePlay:true);
} }
} }
@ -648,9 +639,6 @@ namespace HeavenStudio.Games
const float BIGCALL_LENGTH = 2.75f; const float BIGCALL_LENGTH = 2.75f;
public void CallBigReady(float beat, bool noSound = false) public void CallBigReady(float beat, bool noSound = false)
{ {
if (!noSound)
PlaySoundSequence("crowd_big_ready", beat);
Prepare(beat + 1.5f); Prepare(beat + 1.5f);
Prepare(beat + 2f); Prepare(beat + 2f);
@ -669,8 +657,12 @@ namespace HeavenStudio.Games
public static void WarnBigReady(float beat, bool noSound = false) public static void WarnBigReady(float beat, bool noSound = false)
{ {
wantBigReady = beat; wantBigReady = beat;
}
public static void BigReadySound(float beat, bool noSound = false)
{
if (noSound) return; if (noSound) return;
Jukebox.PlayOneShotGame("fanClub/crowd_big_ready", beat); PlaySoundSequence("fanClub", "crowd_big_ready", beat);
} }
public void ContinueBigReady(float beat) public void ContinueBigReady(float beat)

View file

@ -216,16 +216,18 @@ namespace HeavenStudio.Games
return sameTime; return sameTime;
} }
public MultiSound PlaySoundSequence(string name, float startBeat) public static MultiSound PlaySoundSequence(string game, string name, float startBeat, params SoundSequence.SequenceParams[] args)
{ {
foreach (SoundSequence.SequenceKeyValue pair in SoundSequences) Minigames.Minigame gameInfo = GameManager.instance.GetGameInfo(game);
foreach (SoundSequence.SequenceKeyValue pair in gameInfo.LoadedSoundSequences)
{ {
if (pair.name == name) if (pair.name == name)
{ {
// Debug.Log($"Playing sound sequence {name} at beat {startBeat}");
return pair.sequence.Play(startBeat); return pair.sequence.Play(startBeat);
} }
} }
Debug.LogWarning($"Sound sequence {name} not found in game {this.name} (did you build AssetBundles?)"); Debug.LogWarning($"Sound sequence {name} not found in game {game} (did you build AssetBundles?)");
return null; return null;
} }
} }

View file

@ -37,6 +37,7 @@ namespace HeavenStudio
public bool usesAssetBundle => (wantAssetBundle != ""); public bool usesAssetBundle => (wantAssetBundle != "");
public bool hasLocales => (supportedLocales.Count > 0); public bool hasLocales => (supportedLocales.Count > 0);
public bool AssetsLoaded => (((hasLocales && localeLoaded && currentLoadedLocale == defaultLocale) || (!hasLocales)) && commonLoaded); public bool AssetsLoaded => (((hasLocales && localeLoaded && currentLoadedLocale == defaultLocale) || (!hasLocales)) && commonLoaded);
public bool SequencesPreloaded => soundSequences != null;
private AssetBundle bundleCommon = null; private AssetBundle bundleCommon = null;
private bool commonLoaded = false; private bool commonLoaded = false;
@ -46,6 +47,14 @@ namespace HeavenStudio
private bool localeLoaded = false; private bool localeLoaded = false;
private bool localePreloaded = false; private bool localePreloaded = false;
private SoundSequence.SequenceKeyValue[] soundSequences = null;
public SoundSequence.SequenceKeyValue[] LoadedSoundSequences
{
get => soundSequences;
set => soundSequences = value;
}
public Minigame(string name, string displayName, string color, bool threeD, bool fxOnly, List<GameAction> actions, List<string> tags = null, string assetBundle = "", string defaultLocale = "en", List<string> supportedLocales = null) public Minigame(string name, string displayName, string color, bool threeD, bool fxOnly, List<GameAction> actions, List<string> tags = null, string assetBundle = "", string defaultLocale = "en", List<string> supportedLocales = null)
{ {
this.name = name; this.name = name;

View file

@ -38,27 +38,28 @@ namespace HeavenStudio.Util
audioSource.pitch = pitch; audioSource.pitch = pitch;
audioSource.volume = volume; audioSource.volume = volume;
audioSource.loop = looping; audioSource.loop = looping;
Conductor cnd = Conductor.instance;
if (beat == -1 && !scheduled) if (beat == -1 && !scheduled)
{ {
audioSource.PlayScheduled(AudioSettings.dspTime); audioSource.PlayScheduled(AudioSettings.dspTime);
playInstant = true; playInstant = true;
played = true; played = true;
startTime = Conductor.instance.songPositionAsDouble; startTime = cnd.songPositionAsDouble;
StartCoroutine(NotRelyOnBeatSound()); StartCoroutine(NotRelyOnBeatSound());
} }
else else
{ {
playInstant = false; playInstant = false;
scheduledPitch = Conductor.instance.musicSource.pitch; scheduledPitch = cnd.musicSource.pitch;
startTime = (AudioSettings.dspTime + (Conductor.instance.GetSongPosFromBeat(beat) - Conductor.instance.songPositionAsDouble)/(double)scheduledPitch); startTime = cnd.dspStartTimeAsDouble + ((cnd.GetSongPosFromBeat(beat - cnd.startBeatAsDouble))/(double)scheduledPitch);
audioSource.PlayScheduled(startTime); audioSource.PlayScheduled(startTime);
Debug.Log($"Scheduling future sound {clip.name} for beat {beat} (scheduled: {startTime}, current time: {AudioSettings.dspTime})");
} }
} }
private void Update() private void Update()
{ {
Conductor cnd = Conductor.instance;
if (!played) if (!played)
{ {
if (scheduled) if (scheduled)
@ -78,12 +79,11 @@ namespace HeavenStudio.Util
} }
else else
{ {
if (!played && scheduledPitch != Conductor.instance.musicSource.pitch) if (!played && scheduledPitch != cnd.musicSource.pitch)
{ {
scheduledPitch = Conductor.instance.musicSource.pitch; scheduledPitch = cnd.musicSource.pitch;
startTime = (AudioSettings.dspTime + (Conductor.instance.GetSongPosFromBeat(beat) - Conductor.instance.songPositionAsDouble)/(double)scheduledPitch); startTime = (AudioSettings.dspTime + (cnd.GetSongPosFromBeat(beat) - cnd.songPositionAsDouble)/(double)scheduledPitch);
audioSource.SetScheduledStartTime(startTime); audioSource.SetScheduledStartTime(startTime);
Debug.Log($"Rescheduling future sound {clip.name} for beat {beat} (scheduled: {startTime}, current time: {AudioSettings.dspTime})");
} }
} }
} }
@ -93,7 +93,7 @@ namespace HeavenStudio.Util
{ {
if (looping && loopEndBeat != -1) // Looping sounds play forever unless params are set. if (looping && loopEndBeat != -1) // Looping sounds play forever unless params are set.
{ {
if (Conductor.instance.songPositionInBeats > loopEndBeat) if (cnd.songPositionInBeats > loopEndBeat)
{ {
KillLoop(fadeTime); KillLoop(fadeTime);
loopIndex++; loopIndex++;

View file

@ -1,5 +1,5 @@
ManifestFileVersion: 0 ManifestFileVersion: 0
CRC: 1243838037 CRC: 81299322
AssetBundleManifest: AssetBundleManifest:
AssetBundleInfos: AssetBundleInfos:
Info_0: Info_0:

View file

@ -1,12 +1,12 @@
ManifestFileVersion: 0 ManifestFileVersion: 0
CRC: 1167382196 CRC: 3465358365
Hashes: Hashes:
AssetFileHash: AssetFileHash:
serializedVersion: 2 serializedVersion: 2
Hash: 91ca0253f29ae5f7a1df107a25dc7c75 Hash: 3a4fb33b5553c823eef6c8ecb04520e1
TypeTreeHash: TypeTreeHash:
serializedVersion: 2 serializedVersion: 2
Hash: 222d3ac4260743916f7d5e044ddd31d4 Hash: f7c97b63c72a16f96d1364bd2603929e
HashAppended: 0 HashAppended: 0
ClassTypes: ClassTypes:
- Class: 1 - Class: 1

Binary file not shown.

View file

@ -1,12 +1,12 @@
ManifestFileVersion: 0 ManifestFileVersion: 0
CRC: 149759227 CRC: 2153920215
Hashes: Hashes:
AssetFileHash: AssetFileHash:
serializedVersion: 2 serializedVersion: 2
Hash: 462778359784eea47ee51c3c63402505 Hash: a7518e4203f5e5898721ae561bb7a311
TypeTreeHash: TypeTreeHash:
serializedVersion: 2 serializedVersion: 2
Hash: fc2a2e95963d1b3faf439c84ecb440b4 Hash: 98a6d4eb4172ec02b55d5f14afb2d5a8
HashAppended: 0 HashAppended: 0
ClassTypes: ClassTypes:
- Class: 1 - Class: 1

View file

@ -1,12 +1,12 @@
ManifestFileVersion: 0 ManifestFileVersion: 0
CRC: 1663830856 CRC: 3127587906
Hashes: Hashes:
AssetFileHash: AssetFileHash:
serializedVersion: 2 serializedVersion: 2
Hash: 688c0aa50fbd25fe17346b36c6bf2176 Hash: e10341a51d15d8d18350e495d447c162
TypeTreeHash: TypeTreeHash:
serializedVersion: 2 serializedVersion: 2
Hash: 51d10f004f46f35e758498b711eedb2f Hash: 139f759006457bf43e15a8517f8ee5c0
HashAppended: 0 HashAppended: 0
ClassTypes: ClassTypes:
- Class: 1 - Class: 1

Binary file not shown.

View file

@ -1,12 +1,12 @@
ManifestFileVersion: 0 ManifestFileVersion: 0
CRC: 3480558300 CRC: 3201955903
Hashes: Hashes:
AssetFileHash: AssetFileHash:
serializedVersion: 2 serializedVersion: 2
Hash: cfaae0e9f9c81b2d255e8da0db667aae Hash: 6dd02a8fda5fdb63afe693b00d6c8509
TypeTreeHash: TypeTreeHash:
serializedVersion: 2 serializedVersion: 2
Hash: a669441aae6ee39a06c1090efd6d25bc Hash: b0396ee8cf677796daf23b65e38d1ad2
HashAppended: 0 HashAppended: 0
ClassTypes: ClassTypes:
- Class: 1 - Class: 1

View file

@ -1,12 +1,12 @@
ManifestFileVersion: 0 ManifestFileVersion: 0
CRC: 1706991399 CRC: 2160738779
Hashes: Hashes:
AssetFileHash: AssetFileHash:
serializedVersion: 2 serializedVersion: 2
Hash: ae519aaff83042895009b1d4dbae0a79 Hash: ad07dd4676edfbe5572d0236124a4350
TypeTreeHash: TypeTreeHash:
serializedVersion: 2 serializedVersion: 2
Hash: 994ea96351ef9c039cf2db2caf2c1169 Hash: 6c542f6873f7e3067be67f888d87c947
HashAppended: 0 HashAppended: 0
ClassTypes: ClassTypes:
- Class: 1 - Class: 1

View file

@ -1,12 +1,12 @@
ManifestFileVersion: 0 ManifestFileVersion: 0
CRC: 3961443211 CRC: 1283939881
Hashes: Hashes:
AssetFileHash: AssetFileHash:
serializedVersion: 2 serializedVersion: 2
Hash: c56eae7afab3c51aa0d877ecb5fa6484 Hash: d166274169e80ae349c4e66b396c95a6
TypeTreeHash: TypeTreeHash:
serializedVersion: 2 serializedVersion: 2
Hash: 9a9bdfe5fc84d62897a4e311b61519be Hash: 36c1544bd987dbffd607c6771ff240cf
HashAppended: 0 HashAppended: 0
ClassTypes: ClassTypes:
- Class: 1 - Class: 1