private IEnumerator Setup()
    {
        // Find the Mystery Module Service and obtain the list of compatibilities
        var mmService = FindObjectOfType <MysteryModuleService>();

        if (mmService == null)
        {
            Debug.LogFormat(@"[Mystery Module #{0}] Catastrophic problem: Mystery Module Service is not present.", moduleId);
            goto mustAutoSolve;
        }

        yield return(new WaitUntil(() => mmService.SettingsLoaded));

        var offendingModule = Bomb.GetSolvableModuleIDs().FirstOrDefault(n => mmService.MustAutoSolve(n));

        if (offendingModule != null)
        {
            Debug.LogFormat(@"[Mystery Module #{0}] The module {1} ruins the mood! Green button can be pressed to solve this module.", moduleId, offendingModule);
            goto mustAutoSolve;
        }

        var serialNumber = Bomb.GetSerialNumber();
        remainingCandidatesInfo inf;
        List <object>           organizationModules = new List <object>();

        if (!_infos.ContainsKey(serialNumber))
        {
            inf = new remainingCandidatesInfo();
            _infos[serialNumber] = inf;

            for (int i = 0; i < transform.parent.childCount; i++)
            {
                var module = transform.parent.GetChild(i).gameObject.GetComponent <KMBombModule>();
                if (module == null)
                {
                    continue;
                }

                if (!mmService.MustNotBeHidden(module.ModuleType))
                {
                    inf.RemainingCandidateMystifiables.Add(module);
                }
                if (!mmService.MustNotBeKey(module.ModuleType))
                {
                    inf.RemainingCandidateKeys.Add(module);
                }

                object orgMod;
                if (module.ModuleType == "organizationModule" && (orgMod = module.GetComponent("OrganizationScript")) != null)
                {
                    organizationModules.Add(orgMod);
                }
            }
        }
        else
        {
            inf = _infos[serialNumber];
        }

        var mystifiableCandidates = inf.RemainingCandidateMystifiables.Where(m =>
        {
            // We need to make sure that Mystery Modules do not hide themselves in a cycle.
            // This code relies on the fact that we haven’t chosen a mystified module yet (mystsifiedModule for us is null).
            MysteryModuleScript scr;
            var my = m;
            while ((scr = my.GetComponent <MysteryModuleScript>()) != null && scr.mystifiedModule != null)
            {
                my = scr.mystifiedModule;
            }

            return(my != Module);
        }).ToArray();

        if (mystifiableCandidates.Length == 0)
        {
            Debug.LogFormat(@"[Mystery Module #{0}] No possible candidate found to mystify - Green button can be pressed to solve this module.", moduleId);
            goto mustAutoSolve;
        }

        mystifiedModule = mystifiableCandidates[Random.Range(0, mystifiableCandidates.Length)];
        inf.RemainingCandidateMystifiables.Remove(mystifiedModule);
        inf.RemainingCandidateKeys.Remove(mystifiedModule); // A mystified module cannot be a key anymore (for this or any other Mystery Module)

        if (inf.RemainingCandidateKeys.Count == 0)
        {
            Debug.LogFormat(@"[Mystery Module #{0}] No possible candidates for using as a key found - Green button can be pressed to solve this module.", moduleId);
            goto mustAutoSolve;
        }

        // Select a number of key modules
        keyModules = inf.RemainingCandidateKeys.ToList().Shuffle()
                     .Take(Random.Range(1, Mathf.Max(2, inf.RemainingCandidateKeys.Count / (Bomb.GetSolvableModuleIDs().Count(m => m == Module.ModuleType) + 1))))
                     .ToList();

        // These key modules can no longer be mystified by any other Mystery Module
        foreach (var km in keyModules)
        {
            inf.RemainingCandidateMystifiables.Remove(km);
        }

        Debug.LogFormat(@"[Mystery Module #{0}] Keys are: {1}, mystified module is: {2}", moduleId, keyModules.Select(km => km.ModuleDisplayName).Join(", "), mystifiedModule.ModuleDisplayName);

        Cover.SetActive(true);
        var mysPos = mystifiedModule.transform.localPosition;

        Cover.transform.parent = mystifiedModule.transform.parent;

        var scale = new Vector3(.95f, .95f, .95f);

        Cover.transform.localScale = scale;
        Cover.transform.rotation   = mystifiedModule.transform.rotation;
        if (Cover.transform.rotation == new Quaternion(0f, 0f, 1f, 0f))
        {
            Cover.transform.localPosition = new Vector3(mysPos.x, mysPos.y - 0.02f, mysPos.z);
        }
        else
        {
            Cover.transform.localPosition = new Vector3(mysPos.x, mysPos.y + 0.02f, mysPos.z);
        }
        Debug.LogFormat(@"[Mystery Module #{0}] Rotation: {1}", moduleId, Cover.transform.rotation);
        yield return(null);

        Cover.transform.parent = transform.parent;

        SetKey();
        StartCoroutine(checkSolves());

        mystifyScale = mystifiedModule.transform.localScale;
        mystifiedModule.transform.localScale = new Vector3(0, 0, 0);

        foreach (var org in organizationModules)
        {
            var mth = org.GetType().GetMethod("MysteryModuleNotification", BindingFlags.Public | BindingFlags.Instance);
            Debug.LogFormat(@"<Mystery Module #{0}> Notifying Organization: {1}", moduleId, mth != null);
            if (mth != null && mth.GetParameters().Select(p => p.ParameterType).SequenceEqual(new[] { typeof(List <string>), typeof(string) }))
            {
                Debug.LogFormat(@"[Mystery Module #{0}] Notifying Organization", moduleId);
                mth.Invoke(org, new object[] { keyModules.Select(k => k.ModuleDisplayName).ToList(), mystifiedModule.ModuleDisplayName });
            }
        }
        yield break;

mustAutoSolve:
        nextStage = true;
        SetLED(0, 255, 0);
        setScreen("Free solve :D", 0, 255, 0);
        failsolve = true;
        StopAllCoroutines();
    }
예제 #2
0
    private IEnumerator Setup()
    {
        yield return(null);

        // Find the Mystery Module Service and obtain the list of compatibilities
        var mmService = FindObjectOfType <MysteryModuleService>();

        if (mmService == null)
        {
            Debug.LogFormat(@"[Mystery Module #{0}] Catastrophic problem: Mystery Module Service is not present.");
            goto mustAutoSolve;
        }

        var offendingModule = Bomb.GetSolvableModuleIDs().FirstOrDefault(n => mmService.MustAutoSolve(n));

        if (offendingModule != null)
        {
            Debug.LogFormat(@"[Mystery Module #{0}] The module {1} ruins the mood! Green button can be pressed to solve this module.", moduleId, offendingModule);
            goto mustAutoSolve;
        }

        var serialNumber = Bomb.GetSerialNumber();
        remainingCandidatesInfo inf;

        if (!_infos.ContainsKey(serialNumber))
        {
            inf = new remainingCandidatesInfo();
            _infos[serialNumber] = inf;

            for (int i = 0; i < transform.parent.childCount; i++)
            {
                var module = transform.parent.GetChild(i).gameObject.GetComponent <KMBombModule>();
                if (module == null)
                {
                    continue;
                }

                if (!mmService.MustNotBeHidden(module.ModuleType) || !mmService.ShouldNotBeHidden(module.ModuleType))
                {
                    inf.RemainingCandidateMystifiables.Add(module);
                }
                if (!mmService.MustNotBeKey(module.ModuleType))
                {
                    inf.RemainingCandidateKeys.Add(module);
                }
            }
        }
        else
        {
            inf = _infos[serialNumber];
        }

        var mystifiableCandidates = inf.RemainingCandidateMystifiables.Where(m =>
        {
            // We need to make sure that Mystery Modules do not hide themselves in a cycle.
            // This code relies on the fact that we haven’t chosen a mystified module yet (mystsifiedModule for us is null).
            MysteryModuleScript scr;
            var my = m;
            while ((scr = my.GetComponent <MysteryModuleScript>()) != null && scr.mystifiedModule != null)
            {
                my = scr.mystifiedModule;
            }

            return(my != Module);
        }).ToArray();

        if (mystifiableCandidates.Length == 0)
        {
            Debug.LogFormat(@"[Mystery Module #{0}] No possible candidate found to mystify - Green button can be pressed to solve this module.", moduleId);
            goto mustAutoSolve;
        }

        mystifiedModule = mystifiableCandidates[Random.Range(0, mystifiableCandidates.Length)];
        inf.RemainingCandidateMystifiables.Remove(mystifiedModule);
        inf.RemainingCandidateKeys.Remove(mystifiedModule); // A mystified module cannot be a key anymore (for this or any other Mystery Module)

        if (inf.RemainingCandidateKeys.Count == 0)
        {
            Debug.LogFormat(@"[Mystery Module #{0}] No possible candidates for using as a key found - Green button can be pressed to solve this module.", moduleId);
            goto mustAutoSolve;
        }

        // Select a number of key modules
        keyModules = inf.RemainingCandidateKeys.ToList().Shuffle()
                     .Take(Random.Range(1, Mathf.Max(2, inf.RemainingCandidateKeys.Count / (Bomb.GetSolvableModuleIDs().Count(m => m == Module.ModuleType) + 1))))
                     .ToList();

        // These key modules can no longer be mystified by any other Mystery Module
        foreach (var km in keyModules)
        {
            inf.RemainingCandidateMystifiables.Remove(km);
        }

        Debug.LogFormat(@"[Mystery Module #{0}] Keys are: {1}, mystified module is: {2}", moduleId, keyModules.Select(km => km.ModuleDisplayName).Join(", "), mystifiedModule.ModuleDisplayName);

        var maxBounds   = GetMaxBounds(mystifiedModule.gameObject);
        var coverBounds = GetMaxBounds(Cover);

        Cover.SetActive(true);

        Cover.transform.position = maxBounds.center;
        Cover.transform.parent   = mystifiedModule.gameObject.transform;

        var scale = new Vector3(coverBounds.size.x / maxBounds.size.x, coverBounds.size.y / maxBounds.size.y, coverBounds.size.z / maxBounds.size.z);

        Cover.transform.localScale = scale;
        Cover.transform.rotation   = mystifiedModule.transform.rotation;
        yield return(null);

        Cover.transform.parent = transform.parent;

        SetKey();
        StartCoroutine(checkSolves());

        mystifyScale = mystifiedModule.transform.localScale;
        mystifiedModule.transform.localScale = new Vector3(0, 0, 0);
        yield break;

mustAutoSolve:
        nextStage = true;
        SetLED(0, 255, 0);
        setScreen("Free solve :D", 0, 255, 0);
        failsolve = true;
        StopAllCoroutines();
    }