diff --git a/MuzikaGromche/DiscoBallManager.cs b/MuzikaGromche/DiscoBallManager.cs new file mode 100644 index 0000000..a002a82 --- /dev/null +++ b/MuzikaGromche/DiscoBallManager.cs @@ -0,0 +1,90 @@ +using DunGen; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using UnityEngine; + +namespace MuzikaGromche +{ + public class DiscoBallManager : MonoBehaviour + { + // A struct holding a disco ball container object and the name of a tile for which it was designed. + public readonly record struct Data(string TileName, GameObject DiscoBallContainer) + { + // We are specifically looking for cloned tiles, not the original prototypes. + public readonly string TileCloneName = $"{TileName}(Clone)"; + } + + public static readonly List Containers = []; + private static readonly List InstantiatedContainers = []; + + public static void Initialize() + { + string assetdir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "muzikagromche"); + var bundle = AssetBundle.LoadFromFile(assetdir); + + foreach ((string prefabPath, string tileName) in new[] { + ("Assets/LethalCompany/Mods/MuzikaGromche/DiscoBallContainerManor.prefab", "ManorStartRoomSmall"), + ("Assets/LethalCompany/Mods/MuzikaGromche/DiscoBallContainerFactory.prefab", "StartRoom"), + ("Assets/LethalCompany/Mods/MuzikaGromche/DiscoBallContainerMineShaft.prefab", "MineshaftStartTile"), + ("Assets/LethalCompany/Mods/MuzikaGromche/DiscoBallContainerLargeForkTileB.prefab", "LargeForkTileB"), + ("Assets/LethalCompany/Mods/MuzikaGromche/DiscoBallContainerBirthdayRoomTile.prefab", "BirthdayRoomTile"), + }) + { + var container = bundle.LoadAsset(prefabPath); + Containers.Add(new(tileName, container)); + } + } + + public static void Enable() + { + // Just in case + Disable(); + + var query = from tile in Resources.FindObjectsOfTypeAll() + join container in Containers + on tile.gameObject.name equals container.TileCloneName + select (tile, container); + + foreach (var (tile, container) in query) + { + Enable(tile, container); + } + } + + private static readonly string[] animatorNames = [ + "DiscoBallProp/AnimContainer", + "DiscoBallProp1/AnimContainer", + "DiscoBallProp2/AnimContainer", + "DiscoBallProp3/AnimContainer", + "DiscoBallProp4/AnimContainer", + "DiscoBallProp5/AnimContainer", + ]; + + private static void Enable(Tile tile, Data container) + { + Debug.Log($"{nameof(MuzikaGromche)} {nameof(DiscoBallManager)} Enabling at '{tile.gameObject.name}'"); + var discoBall = Instantiate(container.DiscoBallContainer, tile.transform); + InstantiatedContainers.Add(discoBall); + + foreach (var animatorName in animatorNames) + { + if (discoBall.transform.Find(animatorName)?.gameObject is GameObject animator) + { + animator.GetComponent().SetBool("on", true); + } + } + } + + public static void Disable() + { + foreach (var discoBall in InstantiatedContainers) + { + Debug.Log($"{nameof(MuzikaGromche)} {nameof(DiscoBallManager)}: Disabling {discoBall.name}"); + Destroy(discoBall); + } + InstantiatedContainers.Clear(); + } + } +} diff --git a/MuzikaGromche/MuzikaGromche.csproj b/MuzikaGromche/MuzikaGromche.csproj index d2541eb..97286f4 100644 --- a/MuzikaGromche/MuzikaGromche.csproj +++ b/MuzikaGromche/MuzikaGromche.csproj @@ -49,6 +49,7 @@ + diff --git a/MuzikaGromche/Plugin.cs b/MuzikaGromche/Plugin.cs index 6e8af62..558a322 100644 --- a/MuzikaGromche/Plugin.cs +++ b/MuzikaGromche/Plugin.cs @@ -524,6 +524,7 @@ namespace MuzikaGromche track.LoadedLoop = DownloadHandlerAudioClip.GetContent(requests[i * 2 + 1]); } Config = new Config(base.Config); + DiscoBallManager.Initialize(); new Harmony(PluginInfo.PLUGIN_NAME).PatchAll(typeof(JesterPatch)); } else @@ -968,6 +969,8 @@ namespace MuzikaGromche // The time span after Zero state (when the Start audio has advanced from 0.0f) but before the WindUpTimer+LoopOffset+Loop/2. private bool loopOffsetIsLooping = false; + private bool windUpZeroBeatEventTriggered = false; + private readonly Track track; private float loopOffsetBeat = float.NegativeInfinity; @@ -1082,6 +1085,12 @@ namespace MuzikaGromche { List events = []; + if (windUpOffsetTimestamp.Beat >= 0f && !windUpZeroBeatEventTriggered) + { + events.Add(new WindUpZeroBeatEvent()); + windUpZeroBeatEventTriggered = true; + } + { var colorEvent = GetColorEvent(loopOffsetSpan, windUpOffsetTimestamp); if (colorEvent != null) @@ -1250,6 +1259,11 @@ namespace MuzikaGromche } } + public class WindUpZeroBeatEvent : BaseEvent + { + public override string ToString() => "WindUp"; + } + // Default C#/.NET remainder operator % returns negative result for negative input // which is unsuitable as an index for an array. public static class Mod @@ -1794,6 +1808,7 @@ namespace MuzikaGromche if (__instance.previousState != 2 && __state.previousState == 2) { Plugin.ResetLightColor(); + DiscoBallManager.Disable(); } if (__instance.previousState == 2 && __state.previousState != 2) @@ -1822,6 +1837,10 @@ namespace MuzikaGromche { switch (ev) { + case WindUpZeroBeatEvent: + DiscoBallManager.Enable(); + break; + case SetLightsColorEvent e: Plugin.SetLightColor(e.Color); break; diff --git a/MuzikaGromche/UnityAssets/muzikagromche b/MuzikaGromche/UnityAssets/muzikagromche new file mode 100644 index 0000000..de42bb1 Binary files /dev/null and b/MuzikaGromche/UnityAssets/muzikagromche differ