Fix/add light flickering with animator controllers
This commit is contained in:
		
							parent
							
								
									3a2eaad493
								
							
						
					
					
						commit
						9062f386de
					
				|  | @ -8,6 +8,7 @@ | |||
| - Fixed visual glitch at the last beat of a loop. | ||||
| - Fixed timings of one of the tracks. | ||||
| - Removed unnecessary "Enable Color Animations" config option. | ||||
| - Fixed missing flickering behaviours for some animators controllers. | ||||
| 
 | ||||
| ## MuzikaGromche 13.37.911 - Sri Lanka Bus hotfix | ||||
| 
 | ||||
|  |  | |||
|  | @ -55,6 +55,7 @@ | |||
|             <PackagedResources Include="$(SolutionDir)icon.png" /> | ||||
|             <PackagedResources Include="$(SolutionDir)manifest.json" /> | ||||
|             <PackagedResources Include="$(ProjectDir)UnityAssets\muzikagromche_discoball" /> | ||||
|             <PackagedResources Include="$(ProjectDir)UnityAssets\muzikagromche_poweredlightsanimators" /> | ||||
|             <PackagedResources Include="$(TargetDir)MuzikaGromche.dll" /> | ||||
|         </ItemGroup> | ||||
| 
 | ||||
|  |  | |||
|  | @ -536,9 +536,11 @@ namespace MuzikaGromche | |||
|                 } | ||||
|                 Config = new Config(base.Config); | ||||
|                 DiscoBallManager.Initialize(); | ||||
|                 PoweredLightsAnimators.Load(); | ||||
|                 var harmony = new Harmony(PluginInfo.PLUGIN_NAME); | ||||
|                 harmony.PatchAll(typeof(JesterPatch)); | ||||
|                 harmony.PatchAll(typeof(EnemyAIPatch)); | ||||
|                 harmony.PatchAll(typeof(PoweredLightsAnimatorsPatch)); | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|  |  | |||
|  | @ -0,0 +1,143 @@ | |||
| using DunGen; | ||||
| using HarmonyLib; | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Reflection; | ||||
| using UnityEngine; | ||||
| 
 | ||||
| namespace MuzikaGromche | ||||
| { | ||||
|     internal class PoweredLightsAnimators | ||||
|     { | ||||
|         private readonly record struct AnimatorPatch(string AnimatorContainerPath, RuntimeAnimatorController AnimatorController); | ||||
| 
 | ||||
|         private readonly record struct TilePatch(string TileName, AnimatorPatch[] Patches) | ||||
|         { | ||||
|             // We are specifically looking for cloned tiles, not the original prototypes. | ||||
|             public readonly string TileCloneName = $"{TileName}(Clone)"; | ||||
|         } | ||||
| 
 | ||||
|         private readonly record struct AnimatorPatchDescriptor(string AnimatorContainerPath, string AnimatorControllerAssetPath) | ||||
|         { | ||||
|             public AnimatorPatch Load(AssetBundle assetBundle) | ||||
|             { | ||||
|                 var animationController = assetBundle.LoadAsset<RuntimeAnimatorController>(AnimatorControllerAssetPath) | ||||
|                     ?? throw new FileNotFoundException($"RuntimeAnimatorController not found: {AnimatorControllerAssetPath}", AnimatorControllerAssetPath); | ||||
|                 return new(AnimatorContainerPath, animationController); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private readonly record struct TilePatchDescriptor(string[] TileNames, AnimatorPatchDescriptor[] Descriptors) | ||||
|         { | ||||
|             public TilePatchDescriptor(string TileName, AnimatorPatchDescriptor[] Descriptors) | ||||
|                 : this([TileName], Descriptors) | ||||
|             { | ||||
|             } | ||||
| 
 | ||||
|             public TilePatch[] Load(AssetBundle assetBundle) | ||||
|             { | ||||
|                 var patches = Descriptors.Select(d => d.Load(assetBundle)).ToArray(); | ||||
|                 return [.. TileNames.Select(tileName => new TilePatch(tileName, patches))]; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         private static IDictionary<string, TilePatch> Patches = new Dictionary<string, TilePatch>(); | ||||
| 
 | ||||
|         public static void Load() | ||||
|         { | ||||
|             const string BundleFileName = "muzikagromche_poweredlightsanimators"; | ||||
|             string bundlePath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), BundleFileName); | ||||
|             var assetBundle = AssetBundle.LoadFromFile(bundlePath) | ||||
|                 ?? throw new NullReferenceException("Failed to load bundle"); | ||||
| 
 | ||||
|             const string BasePath = "Assets/LethalCompany/Mods/MuzikaGromche/AnimatorControllers/"; | ||||
| 
 | ||||
|             const string PointLight4 = $"{BasePath}Point Light (4) (Patched).controller"; | ||||
|             const string MineshaftSpotlight = $"{BasePath}MineshaftSpotlight (Patched).controller"; | ||||
|             const string LightbulbsLine = $"{BasePath}lightbulbsLineMesh (Patched).controller"; | ||||
|             const string CeilingFan = $"{BasePath}CeilingFan (originally GameObject) (Patched).controller"; | ||||
| 
 | ||||
| 
 | ||||
|             TilePatchDescriptor[] descriptors = | ||||
|             [ | ||||
|                 // < v70 | ||||
|                 new("ManorStartRoom", [ | ||||
|                     new("ManorStartRoom/Chandelier/PoweredLightTypeB (1)", PointLight4), | ||||
|                     new("ManorStartRoom/Chandelier2/PoweredLightTypeB", PointLight4), | ||||
|                 ]), | ||||
|                 // v70+ | ||||
|                 new("ManorStartRoomSmall", [ | ||||
|                     new("ManorStartRoomMesh/Chandelier/PoweredLightTypeB (1)", PointLight4), | ||||
|                     new("ManorStartRoomMesh/Chandelier2/PoweredLightTypeB", PointLight4), | ||||
|                 ]), | ||||
|                 new("BirthdayRoomTile", [ | ||||
|                     new("Lights/MineshaftSpotlight", MineshaftSpotlight), | ||||
|                 ]), | ||||
|                 new("BathroomTileContainer", [ | ||||
|                     new("MineshaftSpotlight", MineshaftSpotlight), | ||||
|                     new("LightbulbLine/lightbulbsLineMesh", LightbulbsLine), | ||||
|                 ]), | ||||
|                 new(["BedroomTile", "BedroomTileB"], [ | ||||
|                     new("CeilingFanAnimContainer", CeilingFan), | ||||
|                     new("MineshaftSpotlight (1)", MineshaftSpotlight), | ||||
|                 ]), | ||||
|             ]; | ||||
| 
 | ||||
|             Patches = descriptors | ||||
|                 .SelectMany(d => d.Load(assetBundle)) | ||||
|                 .ToDictionary(d => d.TileCloneName, d => d); | ||||
|         } | ||||
| 
 | ||||
|         public static void Patch(Tile tile) | ||||
|         { | ||||
|             if (tile == null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(tile)); | ||||
|             } | ||||
| 
 | ||||
|             if (Patches.TryGetValue(tile.gameObject.name, out var tilePatch)) | ||||
|             { | ||||
|                 foreach (var patch in tilePatch.Patches) | ||||
|                 { | ||||
|                     Transform animationContainerTransform = tile.gameObject.transform.Find(patch.AnimatorContainerPath); | ||||
|                     if (animationContainerTransform == null) | ||||
|                     { | ||||
| #if DEBUG | ||||
|                         throw new NullReferenceException($"{tilePatch.TileName}/{patch.AnimatorContainerPath} Animation Container not found"); | ||||
| #endif | ||||
| #pragma warning disable CS0162 // Unreachable code detected | ||||
|                         continue; | ||||
| #pragma warning restore CS0162 // Unreachable code detected | ||||
|                     } | ||||
| 
 | ||||
|                     var animator = animationContainerTransform.gameObject.GetComponent<Animator>(); | ||||
|                     if (animator == null) | ||||
|                     { | ||||
| #if DEBUG | ||||
|                         throw new NullReferenceException($"{tilePatch.TileName}/{patch.AnimatorContainerPath} Animation Component not found"); | ||||
| #endif | ||||
| #pragma warning disable CS0162 // Unreachable code detected | ||||
|                         continue; | ||||
| #pragma warning restore CS0162 // Unreachable code detected | ||||
|                     } | ||||
| 
 | ||||
|                     animator.runtimeAnimatorController = patch.AnimatorController; | ||||
|                     Debug.Log($"{nameof(MuzikaGromche)} {nameof(PoweredLightsAnimatorsPatch)} {tilePatch.TileName}/{patch.AnimatorContainerPath}: Replaced animator controller"); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     [HarmonyPatch(typeof(Tile))] | ||||
|     internal class PoweredLightsAnimatorsPatch | ||||
|     { | ||||
|         [HarmonyPatch("AddTriggerVolume")] | ||||
|         [HarmonyPostfix] | ||||
|         public static void OnAddTriggerVolume(Tile __instance) | ||||
|         { | ||||
|             PoweredLightsAnimators.Patch(__instance); | ||||
|         } | ||||
|     } | ||||
| } | ||||
										
											Binary file not shown.
										
									
								
							
		Loading…
	
		Reference in New Issue