private static IEnumerator InstantiateComponents(Bomb bomb) { yield return(new WaitUntil(() => modsLoading == 0 && bombQueue.Count != 0 && bombQueue.Peek() == bomb)); var bombGenerator = SceneManager.Instance.GameplayState.GetValue <BombGenerator>("bombGenerator"); bombGenerator.SetValue("bomb", bomb); var logger = bombGenerator.GetValue <ILog>("logger"); // Enable logging again ((log4net.Repository.Hierarchy.Logger)logger.Logger).Level = null; var validBombFaces = new List <BombFace>(bomb.Faces.Where(face => face.ComponentSpawnPoints.Count != 0)); bombGenerator.SetValue("validBombFaces", validBombFaces); List <KMBombInfo> knownBombInfos = new List <KMBombInfo>(); foreach (KMBombInfo item in UnityEngine.Object.FindObjectsOfType <KMBombInfo>()) { knownBombInfos.Add(item); } var bombInfo = allBombInfo[bomb]; var timerFace = bombInfo.TimerFace; var setting = bombInfo.Settings; bombInfo.EnableOriginal = true; bombGenerator.SetValue("rand", bombInfo.Rand); // Bring back the real Random object. UnityEngine.Random.InitState(bomb.Seed); // Loading AudioClips triggers RNG calls so we need to reset the RNG to before that happened. // Emulate logging messages logger.InfoFormat("Generating bomb with seed {0}", bomb.Seed); logger.InfoFormat("Generator settings: {0}", setting.ToString()); foreach (var component in bombInfo.Components) { logger.InfoFormat("Selected {0} ({1})", Modes.GetModuleID(component), component); } var requiresTimer = bombInfo.Components.Where(component => component.RequiresTimerVisibility).Select(Modes.GetModuleID).ToArray(); var anyFace = bombInfo.Components.Where(component => !component.RequiresTimerVisibility).Select(Modes.GetModuleID).ToArray(); logger.DebugFormat("Bomb component list: RequiresTimerVisibility [{0}], AnyFace: [{1}]", string.Join(", ", requiresTimer), string.Join(", ", anyFace)); logger.DebugFormat("Instantiating RequiresTimerVisibility components on {0}", timerFace); // Spawn components bool loggedRemaining = false; foreach (var bombComponent in bombInfo.Components.OrderByDescending(component => component.RequiresTimerVisibility)) { BombFace face = null; if (bombComponent.RequiresTimerVisibility && timerFace.ComponentSpawnPoints.Count != 0) { face = timerFace; } else if (!loggedRemaining) { logger.Debug("Instantiating remaining components on any valid face."); loggedRemaining = true; } if (face == null && validBombFaces.Count != 0) { face = validBombFaces[bombInfo.Rand.Next(0, validBombFaces.Count)]; } if (face == null) { Tweaks.Log("No valid faces remain to instantiate:", bombComponent.name); continue; } bombGenerator.CallMethod("InstantiateComponent", face, bombComponent, setting); } logger.Debug("Filling remaining spaces with empty components."); while (validBombFaces.Count > 0) { bombGenerator.CallMethod("InstantiateComponent", validBombFaces[0], bombGenerator.emptyComponentPrefab, setting); } // We need to re-Init() the bomb face selectables so that the components get their correct X and Y positions for Gamepad support. foreach (Selectable selectable in bomb.Faces.Select(face => face.GetComponent <Selectable>())) { selectable.Init(); } logger.Debug("Generating Widgets"); // To ensure that the widgets get placed in the right position, we need to temporarily revert the bomb's size. bomb.visualTransform.localScale = Vector3.one; WidgetGenerator generator = bombGenerator.GetComponent <WidgetGenerator>(); generator.SetValue("zones", bombInfo.WidgetZones); generator.GenerateWidgets(bomb.WidgetManager, setting.OptionalWidgetCount); bomb.visualTransform.localScale = new Vector3(bomb.Scale, bomb.Scale, bomb.Scale); bombInfo.Loaded = true; HookUpMultipleBombs(bomb, knownBombInfos); bombQueue.Dequeue(); if (BombsLoaded) { SceneManager.Instance.GameplayState.Bombs.AddRange(allBombInfo.Keys); allBombInfo.Clear(); // This fixes the bomb not getting picked up correctly if clicked on before loading is finished. var holdable = KTInputManager.Instance.SelectableManager.GetCurrentFloatingHoldable(); if (holdable) { holdable.Defocus(false, false); } } // Solve any fake modules foreach (BombComponent component in bomb.BombComponents) { if (component.GetComponent <FakeModule>() != null) { component.IsSolved = true; component.Bomb.OnPass(component); } } }
private static IEnumerator InstantiateComponents(Bomb bomb) { yield return(new WaitUntil(() => modsLoading == 0)); var bombGenerator = SceneManager.Instance.GameplayState.GetValue <BombGenerator>("bombGenerator"); bombGenerator.SetValue("bomb", bomb); var validBombFaces = new List <BombFace>(bomb.Faces.Where(face => face.ComponentSpawnPoints.Count != 0)); bombGenerator.SetValue("validBombFaces", validBombFaces); List <KMBombInfo> knownBombInfos = new List <KMBombInfo>(); foreach (KMBombInfo item in UnityEngine.Object.FindObjectsOfType <KMBombInfo>()) { knownBombInfos.Add(item); } var bombInfo = allBombInfo[bomb]; var timerFace = bombInfo.TimerFace; var setting = bombInfo.Settings; bombInfo.EnableOriginal = true; bombGenerator.SetValue("rand", bombInfo.Rand); // Bring back the real Random object. UnityEngine.Random.InitState(bomb.Seed); // Loading AudioClips triggers RNG calls so we need to reset the RNG to before that happened. foreach (var bombComponent in bombInfo.Components.OrderByDescending(component => component.RequiresTimerVisibility)) { BombFace face = null; if (bombComponent.RequiresTimerVisibility && timerFace.ComponentSpawnPoints.Count != 0) { face = timerFace; } if (face == null && validBombFaces.Count != 0) { face = validBombFaces[bombInfo.Rand.Next(0, validBombFaces.Count)]; } if (face == null) { Tweaks.Log("No valid faces remain to instantiate:", bombComponent.name); continue; } bombGenerator.CallMethod("InstantiateComponent", face, bombComponent, setting); } while (validBombFaces.Count > 0) { bombGenerator.CallMethod("InstantiateComponent", validBombFaces[0], bombGenerator.emptyComponentPrefab, setting); } // To ensure that the widgets get placed in the right position, we need to temporarily revert the bomb's size. bomb.visualTransform.localScale = Vector3.one; WidgetGenerator generator = bombGenerator.GetComponent <WidgetGenerator>(); generator.SetValue("zones", bombInfo.WidgetZones); generator.GenerateWidgets(bomb.WidgetManager, setting.OptionalWidgetCount); bomb.visualTransform.localScale = new Vector3(bomb.Scale, bomb.Scale, bomb.Scale); bombInfo.Loaded = true; HookUpMultipleBombs(bomb, knownBombInfos); if (BombsLoaded) { SceneManager.Instance.GameplayState.Bombs.AddRange(allBombInfo.Keys); allBombInfo.Clear(); // This fixes the bomb not getting picked up correctly if clicked on before loading is finished. var holdable = KTInputManager.Instance.SelectableManager.GetCurrentFloatingHoldable(); if (holdable) { holdable.Defocus(false, false); } } // Solve any fake modules foreach (BombComponent component in bomb.BombComponents) { if (component.GetComponent <FakeModule>() != null) { component.IsSolved = true; component.Bomb.OnPass(component); } } }