mirror of
https://github.com/RHeavenStudio/HeavenStudio.git
synced 2025-06-12 08:47:37 +02:00
* update icons * add background loading of sound sequences - fix bug with preFunction - remove most of the old preloading code * update spritesheets for karate man, marching orders * file explorer chart loading * update icon for trick on the class
This commit is contained in:
@ -2,8 +2,8 @@ using System;
|
||||
|
||||
public static class AppInfo {
|
||||
//--- AutoGenerated.begin
|
||||
public const string Version = "0.0.961";
|
||||
public static readonly DateTime Date = new DateTime(2022, 10, 13, 16, 09, 43, 581, DateTimeKind.Utc);
|
||||
public const string Version = "0.0.963";
|
||||
public static readonly DateTime Date = new DateTime(2023, 01, 12, 00, 27, 14, 138, DateTimeKind.Utc);
|
||||
//--- AutoGenerated.end
|
||||
}
|
||||
|
||||
|
@ -353,7 +353,8 @@ namespace HeavenStudio
|
||||
Debug.LogWarning($"Unknown game {gameName} found in remix.json! Adding game...");
|
||||
game = new Minigames.Minigame(gameName, DisplayName(gameName) + " \n<color=#eb5454>[inferred from remix.json]</color>", "", false, true, new List<Minigames.GameAction>());
|
||||
EventCaller.instance.minigames.Add(game);
|
||||
Editor.Editor.instance.AddIcon(game);
|
||||
if (Editor.Editor.instance != null)
|
||||
Editor.Editor.instance.AddIcon(game);
|
||||
}
|
||||
action = EventCaller.instance.GetGameAction(game, actionName);
|
||||
if (action == null)
|
||||
|
@ -26,13 +26,55 @@ namespace HeavenStudio.Util
|
||||
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>();
|
||||
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);
|
||||
@ -41,16 +83,6 @@ namespace HeavenStudio.Util
|
||||
[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")]
|
||||
@ -65,6 +97,9 @@ namespace HeavenStudio.Util
|
||||
public bool looping;
|
||||
[Tooltip("Offset to start playing clip")]
|
||||
public float offset;
|
||||
|
||||
[Tooltip("Set of possible value overrides for clip data")]
|
||||
public SequenceParams[] parameters;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
@ -75,5 +110,26 @@ namespace HeavenStudio.Util
|
||||
[Tooltip("Sequence to play")]
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
@ -38,6 +38,10 @@ namespace HeavenStudio
|
||||
private double 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.
|
||||
public AudioSource musicSource;
|
||||
|
||||
@ -150,6 +154,7 @@ namespace HeavenStudio
|
||||
}
|
||||
lastAbsTime = Time.realtimeSinceStartupAsDouble;
|
||||
dspStartTime = AudioSettings.dspTime;
|
||||
startBeat = beat;
|
||||
|
||||
// GameManager.instance.SetCurrentEventToClosest(songPositionInBeats);
|
||||
}
|
||||
@ -193,7 +198,7 @@ namespace HeavenStudio
|
||||
|
||||
public void LateUpdate()
|
||||
{
|
||||
if (metronome)
|
||||
if (metronome && isPlaying)
|
||||
{
|
||||
if (ReportBeat(ref lastReportedBeat))
|
||||
{
|
||||
@ -260,7 +265,7 @@ namespace HeavenStudio
|
||||
return GameManager.instance.Beatmap.tempoChanges;
|
||||
}
|
||||
|
||||
public double GetSongPosFromBeat(float beat)
|
||||
public double GetSongPosFromBeat(double beat)
|
||||
{
|
||||
var chart = GameManager.instance.Beatmap;
|
||||
SetBpm(chart.bpm);
|
||||
|
@ -31,7 +31,7 @@ namespace HeavenStudio
|
||||
|
||||
private void Start()
|
||||
{
|
||||
CreateDebugUI(out Title); SetText(Title, "Rhythm Heaven Mania v1.0 BRAEDON DEBUG PLAYTEST");
|
||||
CreateDebugUI(out Title); SetText(Title, $"Heaven Studio {GlobalGameManager.buildTime}");
|
||||
CreateDebugUI(out SongPosBeats);
|
||||
CreateDebugUI(out SongPos);
|
||||
CreateDebugUI(out SecPerBeat);
|
||||
|
@ -19,7 +19,8 @@ namespace HeavenStudio
|
||||
public List<GameObject> SoundObjects = new List<GameObject>();
|
||||
|
||||
[Header("Components")]
|
||||
public TextAsset txt;
|
||||
public string txt;
|
||||
public string ext;
|
||||
public Camera GameCamera, CursorCam, OverlayCamera;
|
||||
public GameObject GameLetterbox;
|
||||
public CircleCursor CircleCursor;
|
||||
@ -83,17 +84,6 @@ namespace HeavenStudio
|
||||
GameObject fade = new GameObject();
|
||||
this.fade = fade.AddComponent<Games.Global.Flash>();
|
||||
|
||||
if (txt != null)
|
||||
{
|
||||
string json = txt.text;
|
||||
Beatmap = JsonConvert.DeserializeObject<DynamicBeatmap>(json);
|
||||
}
|
||||
else
|
||||
{
|
||||
NewRemix();
|
||||
}
|
||||
|
||||
SortEventsList();
|
||||
|
||||
GlobalGameManager.Init();
|
||||
|
||||
@ -106,13 +96,16 @@ namespace HeavenStudio
|
||||
|
||||
GameObject textbox = Instantiate(Resources.Load<GameObject>("Prefabs/Common/Textbox"));
|
||||
textbox.name = "Textbox";
|
||||
|
||||
if (playOnStart)
|
||||
if (txt != null && ext != null)
|
||||
{
|
||||
Play(startBeat);
|
||||
LoadRemix(txt, ext);
|
||||
}
|
||||
else
|
||||
{
|
||||
NewRemix();
|
||||
}
|
||||
|
||||
// SetCurrentGame(eventCaller.GamesHolder.transform.GetComponentsInChildren<Transform>()[1].name);
|
||||
SortEventsList();
|
||||
|
||||
if (Beatmap.entities.Count >= 1)
|
||||
{
|
||||
@ -123,6 +116,11 @@ namespace HeavenStudio
|
||||
{
|
||||
SetGame("noGame");
|
||||
}
|
||||
|
||||
if (playOnStart)
|
||||
{
|
||||
Play(startBeat);
|
||||
}
|
||||
}
|
||||
|
||||
public void NewRemix()
|
||||
@ -190,7 +188,7 @@ namespace HeavenStudio
|
||||
var inf = GetGameInfo(gameName);
|
||||
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.LoadLocalizedAssetBundleAsync());
|
||||
}
|
||||
@ -204,23 +202,23 @@ namespace HeavenStudio
|
||||
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])));
|
||||
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);
|
||||
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.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();
|
||||
if (currentPreSequence < Beatmap.entities.Count && currentPreSequence >= 0)
|
||||
@ -231,9 +229,16 @@ namespace HeavenStudio
|
||||
var entitiesAtSameBeat = Beatmap.entities.FindAll(c => c.beat == Beatmap.entities[currentPreSequence].beat);
|
||||
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);
|
||||
currentPreSequence++;
|
||||
}
|
||||
currentPreSequence++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -291,14 +296,14 @@ namespace HeavenStudio
|
||||
//seek ahead to preload games that have assetbundles
|
||||
SeekAheadAndPreload(Conductor.instance.songPositionInBeats, seekTime);
|
||||
|
||||
SeekAheadAndDoPreEvent(Conductor.instance.songPositionInBeats, 1f);
|
||||
SeekAheadAndDoPreEvent(Conductor.instance.songPositionInBeats, 2f);
|
||||
|
||||
if (currentEvent < Beatmap.entities.Count && currentEvent >= 0)
|
||||
{
|
||||
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
|
||||
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])));
|
||||
|
||||
// FX entities should ALWAYS execute before gameplay entities
|
||||
@ -308,17 +313,16 @@ namespace HeavenStudio
|
||||
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 (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
|
||||
{
|
||||
eventCaller.CallEvent(entitiesAtSameBeat[i], true);
|
||||
eventCaller.CallEvent(entity, true);
|
||||
}
|
||||
|
||||
// Thank you to @shshwdr for bring this to my attention
|
||||
@ -328,8 +332,6 @@ namespace HeavenStudio
|
||||
// currentEvent += gameManagerEntities.Count;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public void ToggleInputs(bool inputs)
|
||||
@ -380,6 +382,11 @@ namespace HeavenStudio
|
||||
SetCurrentEventToClosest(beat);
|
||||
onBeatChanged?.Invoke(beat);
|
||||
KillAllSounds();
|
||||
|
||||
if (playOnStart)
|
||||
{
|
||||
Play(0);
|
||||
}
|
||||
}
|
||||
|
||||
public void KillAllSounds()
|
||||
@ -549,47 +556,21 @@ namespace HeavenStudio
|
||||
{
|
||||
Destroy(currentGameO);
|
||||
|
||||
var instantiate = true;
|
||||
|
||||
if (preloadedGames.Count > 0)
|
||||
{
|
||||
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;
|
||||
}
|
||||
currentGameO = Instantiate(GetGame(game));
|
||||
currentGameO.transform.parent = eventCaller.GamesHolder.transform;
|
||||
currentGameO.name = game;
|
||||
|
||||
SetCurrentGame(game);
|
||||
|
||||
ResetCamera();
|
||||
}
|
||||
|
||||
private void PreloadGame(string game)
|
||||
public void PreloadGameSequences(string game)
|
||||
{
|
||||
if (preloadedGames.Contains(preloadedGames.Find(c => c.name == game)))
|
||||
return;
|
||||
|
||||
var g = Instantiate(GetGame(game));
|
||||
g.transform.parent = eventCaller.GamesHolder.transform;
|
||||
g.SetActive(false);
|
||||
g.name = game;
|
||||
preloadedGames.Add(g);
|
||||
var gameInfo = GetGameInfo(game);
|
||||
//load the games' sound sequences
|
||||
if (gameInfo != null && gameInfo.LoadedSoundSequences == null)
|
||||
gameInfo.LoadedSoundSequences = GetGame(game).GetComponent<Minigame>().SoundSequences;
|
||||
}
|
||||
|
||||
public GameObject GetGame(string name)
|
||||
|
@ -31,7 +31,8 @@ namespace HeavenStudio.Games.Loaders
|
||||
{
|
||||
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!")
|
||||
{
|
||||
@ -42,7 +43,8 @@ namespace HeavenStudio.Games.Loaders
|
||||
new Param("type", FanClub.KamoneResponseType.Through, "Response type", "Type of response to use"),
|
||||
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")
|
||||
{
|
||||
@ -52,7 +54,8 @@ namespace HeavenStudio.Games.Loaders
|
||||
{
|
||||
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")
|
||||
{
|
||||
@ -526,8 +529,6 @@ namespace HeavenStudio.Games
|
||||
const float HAIS_LENGTH = 4.5f;
|
||||
public void CallHai(float beat, bool noSound = false, int type = 0)
|
||||
{
|
||||
if (!noSound)
|
||||
PlaySoundSequence("arisa_hai", beat);
|
||||
responseToggle = false;
|
||||
DisableBop(beat, 8f);
|
||||
|
||||
@ -550,20 +551,21 @@ namespace HeavenStudio.Games
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
CallHai(beat, true, type);
|
||||
@ -575,13 +577,6 @@ 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 (!noSound)
|
||||
{
|
||||
if (isBig)
|
||||
PlaySoundSequence("arisa_kamone_fast", beat);
|
||||
else
|
||||
PlaySoundSequence("arisa_kamone", beat);
|
||||
}
|
||||
|
||||
responseToggle = true;
|
||||
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)
|
||||
{
|
||||
wantKamone = beat;
|
||||
wantKamoneType = responseType;
|
||||
}
|
||||
|
||||
public static void KamoneSound(float beat, bool noSound = false, int type = 0, int responseType = (int) KamoneResponseType.Through)
|
||||
{
|
||||
if (noSound) return;
|
||||
if (responseType == (int) KamoneResponseType.ThroughFast || responseType == (int) KamoneResponseType.JumpFast)
|
||||
{
|
||||
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),
|
||||
}, forcePlay:true);
|
||||
PlaySoundSequence("fanClub", "arisa_kamone_fast", beat);
|
||||
}
|
||||
else
|
||||
{
|
||||
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),
|
||||
}, forcePlay:true);
|
||||
PlaySoundSequence("fanClub", "arisa_kamone", beat);
|
||||
}
|
||||
}
|
||||
|
||||
@ -648,9 +639,6 @@ 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);
|
||||
|
||||
@ -669,8 +657,12 @@ namespace HeavenStudio.Games
|
||||
public static void WarnBigReady(float beat, bool noSound = false)
|
||||
{
|
||||
wantBigReady = beat;
|
||||
}
|
||||
|
||||
public static void BigReadySound(float beat, bool noSound = false)
|
||||
{
|
||||
if (noSound) return;
|
||||
Jukebox.PlayOneShotGame("fanClub/crowd_big_ready", beat);
|
||||
PlaySoundSequence("fanClub", "crowd_big_ready", beat);
|
||||
}
|
||||
|
||||
public void ContinueBigReady(float beat)
|
||||
|
@ -216,16 +216,18 @@ namespace HeavenStudio.Games
|
||||
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)
|
||||
{
|
||||
// Debug.Log($"Playing sound sequence {name} at beat {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;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,11 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
using System.IO.Compression;
|
||||
using System.Text;
|
||||
|
||||
using UnityEngine;
|
||||
using UnityEngine.Audio;
|
||||
|
||||
@ -9,13 +15,37 @@ namespace HeavenStudio
|
||||
{
|
||||
public TextAsset level;
|
||||
public AudioClip music;
|
||||
public GameObject canvas;
|
||||
public bool debugUI;
|
||||
|
||||
public bool playOnStart = false;
|
||||
public bool editor = false;
|
||||
|
||||
string json = "";
|
||||
string ext = "";
|
||||
|
||||
private void Start()
|
||||
{
|
||||
string[] args = System.Environment.GetCommandLineArgs();
|
||||
string input = "";
|
||||
for (int i = 1; i < args.Length; i++) {
|
||||
// first arg is always this executable
|
||||
Debug.Log(args[i]);
|
||||
if (args[i].IndexOfAny(Path.GetInvalidPathChars()) == -1)
|
||||
{
|
||||
if (File.Exists(args[i]))
|
||||
{
|
||||
input = args[i];
|
||||
editor = false;
|
||||
playOnStart = true;
|
||||
}
|
||||
}
|
||||
else if (args[i] == "-debug")
|
||||
{
|
||||
debugUI = true;
|
||||
}
|
||||
}
|
||||
|
||||
GameObject Cameras = Instantiate(Resources.Load<GameObject>("Prefabs/Cameras")); Cameras.name = "Cameras";
|
||||
GameObject MainCamera = Cameras.transform.GetChild(0).gameObject;
|
||||
GameObject CursorCamera = Cameras.transform.GetChild(1).gameObject;
|
||||
@ -33,7 +63,6 @@ namespace HeavenStudio
|
||||
GameManager gameManager = GameManager.AddComponent<GameManager>();
|
||||
gameManager.playOnStart = playOnStart;
|
||||
|
||||
gameManager.txt = level;
|
||||
gameManager.GamesHolder = Games;
|
||||
gameManager.CircleCursor = Cursor.transform.GetChild(0).GetComponent<CircleCursor>();
|
||||
gameManager.GameCamera = MainCamera.GetComponent<Camera>();
|
||||
@ -64,8 +93,58 @@ namespace HeavenStudio
|
||||
}
|
||||
else
|
||||
{
|
||||
this.GetComponent<HeavenStudio.Editor.Editor>().enabled = false;
|
||||
this.GetComponent<HeavenStudio.Editor.EditorTheme>().enabled = false;
|
||||
this.GetComponent<HeavenStudio.Editor.BoxSelection>().enabled = false;
|
||||
canvas.SetActive(false);
|
||||
|
||||
OpenCmdRemix(input);
|
||||
Debug.Log(json);
|
||||
gameManager.txt = json;
|
||||
gameManager.ext = ext;
|
||||
gameManager.Init();
|
||||
}
|
||||
}
|
||||
|
||||
public void OpenCmdRemix(string path)
|
||||
{
|
||||
if (path == string.Empty) return;
|
||||
if (!File.Exists(path)) return;
|
||||
byte[] MusicBytes;
|
||||
bool loadedMusic = false;
|
||||
string extension = path.GetExtension();
|
||||
|
||||
using var zipFile = File.Open(path, FileMode.Open);
|
||||
using var archive = new ZipArchive(zipFile, ZipArchiveMode.Read);
|
||||
|
||||
foreach (var entry in archive.Entries)
|
||||
switch (entry.Name)
|
||||
{
|
||||
case "remix.json":
|
||||
{
|
||||
using var stream = entry.Open();
|
||||
using var reader = new StreamReader(stream);
|
||||
json = reader.ReadToEnd();
|
||||
ext = extension;
|
||||
break;
|
||||
}
|
||||
case "song.ogg":
|
||||
{
|
||||
using var stream = entry.Open();
|
||||
using var memoryStream = new MemoryStream();
|
||||
stream.CopyTo(memoryStream);
|
||||
MusicBytes = memoryStream.ToArray();
|
||||
Conductor.instance.musicSource.clip = OggVorbis.VorbisPlugin.ToAudioClip(MusicBytes, "music");
|
||||
loadedMusic = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!loadedMusic)
|
||||
{
|
||||
Conductor.instance.musicSource.clip = null;
|
||||
MusicBytes = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -48,6 +48,7 @@ namespace HeavenStudio.Editor
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Editor.instance == null) return;
|
||||
float deltaTimelineX = timelineContent.transform.localPosition.x - timelineLastX;
|
||||
|
||||
Camera camera = Editor.instance.EditorCamera;
|
||||
|
@ -31,6 +31,7 @@ namespace HeavenStudio.Editor
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (Editor.instance == null) return;
|
||||
specialLayers.GetComponent<Image>().color = theme.properties.SpecialLayersCol.Hex2RGB();
|
||||
tempoLayer.GetComponent<Image>().color = theme.properties.TempoLayerCol.Hex2RGB();
|
||||
musicLayer.GetComponent<Image>().color = theme.properties.MusicLayerCol.Hex2RGB();
|
||||
|
@ -37,6 +37,7 @@ namespace HeavenStudio
|
||||
public bool usesAssetBundle => (wantAssetBundle != "");
|
||||
public bool hasLocales => (supportedLocales.Count > 0);
|
||||
public bool AssetsLoaded => (((hasLocales && localeLoaded && currentLoadedLocale == defaultLocale) || (!hasLocales)) && commonLoaded);
|
||||
public bool SequencesPreloaded => soundSequences != null;
|
||||
|
||||
private AssetBundle bundleCommon = null;
|
||||
private bool commonLoaded = false;
|
||||
@ -46,6 +47,14 @@ namespace HeavenStudio
|
||||
private bool localeLoaded = 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)
|
||||
{
|
||||
this.name = name;
|
||||
|
@ -38,27 +38,28 @@ namespace HeavenStudio.Util
|
||||
audioSource.pitch = pitch;
|
||||
audioSource.volume = volume;
|
||||
audioSource.loop = looping;
|
||||
Conductor cnd = Conductor.instance;
|
||||
|
||||
if (beat == -1 && !scheduled)
|
||||
{
|
||||
audioSource.PlayScheduled(AudioSettings.dspTime);
|
||||
playInstant = true;
|
||||
played = true;
|
||||
startTime = Conductor.instance.songPositionAsDouble;
|
||||
startTime = cnd.songPositionAsDouble;
|
||||
StartCoroutine(NotRelyOnBeatSound());
|
||||
}
|
||||
else
|
||||
{
|
||||
playInstant = false;
|
||||
scheduledPitch = Conductor.instance.musicSource.pitch;
|
||||
startTime = (AudioSettings.dspTime + (Conductor.instance.GetSongPosFromBeat(beat) - Conductor.instance.songPositionAsDouble)/(double)scheduledPitch);
|
||||
scheduledPitch = cnd.musicSource.pitch;
|
||||
startTime = cnd.dspStartTimeAsDouble + ((cnd.GetSongPosFromBeat(beat - cnd.startBeatAsDouble))/(double)scheduledPitch);
|
||||
audioSource.PlayScheduled(startTime);
|
||||
Debug.Log($"Scheduling future sound {clip.name} for beat {beat} (scheduled: {startTime}, current time: {AudioSettings.dspTime})");
|
||||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
Conductor cnd = Conductor.instance;
|
||||
if (!played)
|
||||
{
|
||||
if (scheduled)
|
||||
@ -78,12 +79,11 @@ namespace HeavenStudio.Util
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!played && scheduledPitch != Conductor.instance.musicSource.pitch)
|
||||
if (!played && scheduledPitch != cnd.musicSource.pitch)
|
||||
{
|
||||
scheduledPitch = Conductor.instance.musicSource.pitch;
|
||||
startTime = (AudioSettings.dspTime + (Conductor.instance.GetSongPosFromBeat(beat) - Conductor.instance.songPositionAsDouble)/(double)scheduledPitch);
|
||||
scheduledPitch = cnd.musicSource.pitch;
|
||||
startTime = (AudioSettings.dspTime + (cnd.GetSongPosFromBeat(beat) - cnd.songPositionAsDouble)/(double)scheduledPitch);
|
||||
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 (Conductor.instance.songPositionInBeats > loopEndBeat)
|
||||
if (cnd.songPositionInBeats > loopEndBeat)
|
||||
{
|
||||
KillLoop(fadeTime);
|
||||
loopIndex++;
|
||||
|
Reference in New Issue
Block a user