Example #1
0
        static bool Prefix(BombGenerator __instance, BombFace selectedFace, BombComponent bombComponentPrefab, GeneratorSetting settings)
        {
            var bomb = __instance.GetValue <Bomb>("bomb");
            var type = bombComponentPrefab.ComponentType;

            // Let the timer component spawn normally and record the bomb's information.
            if (type == ComponentTypeEnum.Timer)
            {
                allBombInfo.Add(bomb, new BombInfo(settings, selectedFace, __instance.GetValue <Random>("rand")));

                void logCallback(string condition, string _, LogType __)
                {
                    if (!condition.StartsWith("[BombGenerator] Bomb component list: "))
                    {
                        return;
                    }

                    // Replace the Random object with a fake one, so that we can make the consistent RNG calls later.
                    __instance.SetValue("rand", new FakeRandom());

                    Application.logMessageReceived -= logCallback;
                }

                Application.logMessageReceived += logCallback;

                return(true);
            }

            // If we don't have information about a bomb, just let it go through.
            if (!allBombInfo.TryGetValue(bomb, out BombInfo bombInfo))
            {
                return(true);
            }

            // Once we're ready to instantiate the components, this allows us to call the original method again.
            if (bombInfo.EnableOriginal)
            {
                return(true);
            }

            // If the generator is trying to fill the bomb with empty components, clear the valid faces to skip over it.
            if (type == ComponentTypeEnum.Empty)
            {
                __instance.GetValue <List <BombFace> >("validBombFaces").Clear();
                return(false);
            }

            // Start loading any fake modules.
            if (bombComponentPrefab.GetComponent <FakeModule>() != null)
            {
                __instance.StartCoroutine(LoadModule(bombComponentPrefab, bombInfo));
            }
            else
            {
                bombInfo.Components.Add(bombComponentPrefab);
            }

            return(false);
        }
Example #2
0
    public void GeneratorThrowsExceptionWhenMapIsTooSmallForAllBombs(int bombsAmount, int width, int height)
    {
        BombGenerator bombGenerator = new BombGenerator();
        Map           map           = GenerateEmptyMap(width, height, bombsAmount);

        Exception ex = Assert.Throws <Exception>(() => bombGenerator.GenerateBombs(map));

        Assert.NotNull(ex);
    }
Example #3
0
    public void GeneratorGeneratesExaclyAsManyBombsAsRequested(int bombsAmount, int width, int height)
    {
        BombGenerator bombGenerator = new BombGenerator();
        Map           map           = GenerateEmptyMap(width, height, bombsAmount);

        Map generatedMap = bombGenerator.GenerateBombs(map);

        Assert.Equal(bombsAmount, HowManyBombsDoesMapHave(generatedMap));
    }
Example #4
0
    public void GeneratorDoesNotGenerateBombsWhichAreSurroundedByOtherBombs()
    {
        int           bombsAmount = 8, width = 3, height = 3;
        BombGenerator bombGenerator = new BombGenerator();
        Map           map           = GenerateEmptyMap(width, height, bombsAmount);

        for (int i = 0; i < 2; i++)
        {
            Map generatedMap = bombGenerator.GenerateBombs(map);
            Assert.False(IsAnyBombSurroundedByOtherBombs(generatedMap));
        }
    }
Example #5
0
        private MineField(int zoneSize, int numberOfBombs)
        {
            if (numberOfBombs <= 0)
            {
                throw new NoBombException();
            }

            if (numberOfBombs >= zoneSize * zoneSize)
            {
                throw new TooManyBombsException();
            }

            BombCount = numberOfBombs;
            ZoneSize  = zoneSize;

            _cells = new ICell[zoneSize, zoneSize];

            GenerateGameCells();
            PutBombs();
            ScanNumberOfBombsAroundEmptyCells();

            void GenerateGameCells()
            {
                for (var row = 0; row < zoneSize; row++)
                {
                    for (var column = 0; column < zoneSize; column++)
                    {
                        _cells[row, column] = new UndiscoveredCell(row, column);
                    }
                }
            }

            void PutBombs()
            {
                var generator = new BombGenerator(numberOfBombs);

                do
                {
                    _cells.OfType <UndiscoveredCell>()
                    .Where(a => !a.HasBomb)
                    .ForEach(a => a.HasBomb = generator.Put());
                } while (generator.BombNumber > 0);
            }

            void ScanNumberOfBombsAroundEmptyCells()
            {
                _cells.OfType <UndiscoveredCell>()
                .Where(a => a.HasBomb)
                .SelectMany(CellsAround)
                .ForEach(u => ((UndiscoveredCell)u).NumberOfBombsAround++);
            }
        }
Example #6
0
 public bool NewBomb(int modules)
 {
     if (BombInProgress)
     {
         return(false);
     }
     else
     {
         CurrentBomb = BombGenerator.Generate(modules);
         Debug.LogFormat("[Game] Starting new bomb with {0} modules...", modules);
         BombInProgress = true;
         return(true);
     }
 }
Example #7
0
        static bool Prefix(BombGenerator __instance, BombFace selectedFace, BombComponent bombComponentPrefab, GeneratorSetting settings)
        {
            var bomb = __instance.GetValue <Bomb>("bomb");
            var type = bombComponentPrefab.ComponentType;

            // Let the timer component spawn normally and record the bomb's information.
            if (type == ComponentTypeEnum.Timer)
            {
                allBombInfo.Add(bomb, new BombInfo(settings, selectedFace, __instance.GetValue <Random>("rand")));

                return(true);
            }

            // If we don't have information about a bomb, just let it go through.
            if (!allBombInfo.TryGetValue(bomb, out BombInfo bombInfo))
            {
                return(true);
            }

            // Once we're ready to instantiate the components, this allows us to call the original method again.
            if (bombInfo.EnableOriginal)
            {
                return(true);
            }

            // If the generator is trying to fill the bomb with empty components, clear the valid faces to skip over it.
            if (type == ComponentTypeEnum.Empty)
            {
                __instance.GetValue <List <BombFace> >("validBombFaces").Clear();
                return(false);
            }

            // Start loading any fake modules.
            if (bombComponentPrefab.GetComponent <FakeModule>() != null)
            {
                __instance.StartCoroutine(LoadModule(bombComponentPrefab, bombInfo));
            }
            else
            {
                bombInfo.Components.Add(bombComponentPrefab);
            }

            return(false);
        }
Example #8
0
    void Start()
    {
        if (instance == null)
        {
            instance = this;
        }
        else if (instance != this)
        {
            Destroy(gameObject);
        }

        restartPoint  = new Vector3(0f, -1.688f, 0f);
        bombGenerator = GameObject.Find("Generator").GetComponent <BombGenerator> ();
        scoreText     = GameObject.Find("Score Text");
        scoreText.SetActive(false);
        finalScore = GameObject.Find("Final Score");
        finalScore.SetActive(false);
        gameOver    = false;
        gamesPlayed = PlayerPrefs.GetInt("GamesPlayed");
        totalScore  = PlayerPrefs.GetInt("TotalScore");
        bestScore   = PlayerPrefs.GetInt("BestScore");
        CheckUnlockedCharacters();
    }
    static void HandleCaseGeneration()
    {
        Tweaks.FixRNGSeed();

        BombGenerator bombGenerator = Object.FindObjectOfType <BombGenerator>();

        if (bombGenerator.BombPrefabOverride == null)         // No point in doing anything if they aren't even going to use the ObjectPool.
        {
            ObjectPool prefabPool = bombGenerator.BombPrefabPool;

            // Generate a case parent
            if (CaseParent != null)
            {
                Object.Destroy(CaseParent);
            }

            // We have to parent the case to a GameObject that isn't active so it doesn't appear in the scene but itself is still active.
            CaseParent = new GameObject();
            CaseParent.SetActive(false);

            // Override any KMGameCommands
            foreach (KMGameCommands gameCommands in Object.FindObjectsOfType <KMGameCommands>())
            {
                var previousDelegate = gameCommands.OnCreateBomb;

                gameCommands.OnCreateBomb = (string missionId, KMGeneratorSetting generatorSettings, GameObject spawnTarget, string seed) =>
                {
                    HandleGeneratorSetting(ModMission.CreateGeneratorSettingsFromMod(generatorSettings), prefabPool);
                    return(previousDelegate(missionId, generatorSettings, spawnTarget, seed));
                };
            }

            // This must happen regardless of even BetterCasePicker is enabled so that the game can't try to spawn the fake case.
            prefabPool.Objects = prefabPool.Objects.Where(gameobject => gameobject.name != "TweaksCaseGenerator").ToList();

            if (!Tweaks.settings.BetterCasePicker && !Tweaks.CaseGeneratorSettingCache)
            {
                return;
            }

            // Try to figure out what mission we are going into
            Mission mission = null;
            if (!string.IsNullOrEmpty(GameplayState.MissionToLoad))
            {
                if (GameplayState.MissionToLoad.Equals(FreeplayMissionGenerator.FREEPLAY_MISSION_ID))
                {
                    mission = FreeplayMissionGenerator.Generate(GameplayState.FreeplaySettings);
                }
                else if (GameplayState.MissionToLoad.Equals(ModMission.CUSTOM_MISSION_ID))
                {
                    mission = GameplayState.CustomMission;
                }
                else
                {
                    mission = MissionManager.Instance.GetMission(GameplayState.MissionToLoad);
                }
            }

            if (mission == null)
            {
                Debug.LogError("[BetterCasePicker] Unable to find the current mission");
                return;
            }

            HandleGeneratorSetting(mission.GeneratorSetting, prefabPool);
        }
    }
Example #10
0
    public static void HandleCaseGeneration()
    {
        // The game sets the seed to 33 for some reason, so we have to set the seed so it doesn't pick the same values every time.
        Random.InitState((int)System.DateTime.Now.Ticks);

        BombGenerator bombGenerator = Object.FindObjectOfType <BombGenerator>();

        if (bombGenerator.BombPrefabOverride == null)         // No point in doing anything if they aren't even going to use the ObjectPool.
        {
            ObjectPool prefabPool = bombGenerator.BombPrefabPool;

            // This must happen regardless of even BetterCasePicker is enabled so that the game can't try to spawn the fake case.
            prefabPool.Objects = prefabPool.Objects.Where(gameobject => gameobject.name != "TweaksCaseGenerator").ToList();

            if (!Tweaks.settings.BetterCasePicker && !Tweaks.CaseGeneratorSettingCache)
            {
                return;
            }

            // Try to figure out what mission we are going into
            Mission mission = null;
            if (!string.IsNullOrEmpty(GameplayState.MissionToLoad))
            {
                if (GameplayState.MissionToLoad.Equals(FreeplayMissionGenerator.FREEPLAY_MISSION_ID))
                {
                    mission = FreeplayMissionGenerator.Generate(GameplayState.FreeplaySettings);
                }
                else if (GameplayState.MissionToLoad.Equals(ModMission.CUSTOM_MISSION_ID))
                {
                    mission = GameplayState.CustomMission;
                }
                else
                {
                    mission = MissionManager.Instance.GetMission(GameplayState.MissionToLoad);
                }
            }

            if (mission == null)
            {
                Debug.LogError("[BetterCasePicker] Unable to find the current mission");
                return;
            }

            bool frontFaceOnly  = mission.GeneratorSetting.FrontFaceOnly;
            int  componentCount = mission.GeneratorSetting.ComponentPools.Where(pool => pool.ModTypes == null || pool.ModTypes.Count == 0 || !(pool.ModTypes.Contains("Factory Mode") || pool.ModTypes[0].StartsWith("Multiple Bombs"))).Sum(pool => pool.Count) + 1;

            Dictionary <GameObject, int> bombcases = prefabPool.Objects
                                                     .Where(gameobject => gameobject.GetComponent <KMBomb>() != null)
                                                     .ToDictionary(gameobject => gameobject, gameobject =>
            {
                if (!frontFaceOnly)
                {
                    return(gameobject.GetComponent <KMBomb>().Faces.Select(face => face.Anchors.Count).Sum());
                }
                else
                {
                    return(gameobject.GetComponent <KMBomb>().Faces[0].Anchors.Count);
                }
            });

            bombcases.Add(prefabPool.Default, !frontFaceOnly ? 12 : 6);

            // Generate a case using Case Generator
            if (Tweaks.CaseGeneratorSettingCache)
            {
                List <Vector2> caseSizes = new List <Vector2>();
                for (int x = 1; x <= componentCount; x++)
                {
                    for (int y = 1; y <= componentCount; y++)
                    {
                        if (x >= y)
                        {
                            caseSizes.Add(new Vector2(x, y));
                        }
                    }
                }

                var caseSize = caseSizes
                               .Where(size => size.y / size.x >= 0.5f && size.x * size.y * (frontFaceOnly ? 1 : 2) >= componentCount)
                               .OrderBy(size => System.Math.Abs(size.x * size.y * (frontFaceOnly ? 1 : 2) - componentCount))
                               .ThenByDescending(size => size.y / size.x)
                               .FirstOrDefault();

                if (caseSize != default(Vector2))
                {
                    if (CaseParent != null)
                    {
                        Object.Destroy(CaseParent);
                    }

                    // We have to parent the case to a GameObject that isn't active so it doesn't appear in the scene but itself is still active.
                    CaseParent = new GameObject();
                    CaseParent.SetActive(false);

                    var caseGameObject = BombCaseGenerator.GenerateCase(caseSize);
                    caseGameObject.transform.parent = CaseParent.transform;

                    bombcases.Add(caseGameObject, (int)(caseSize.x * caseSize.y * (frontFaceOnly ? 1 : 2)));
                }
            }

            if (bombcases.Count == 0)
            {
                Debug.LogError("[BetterCasePicker] Unable to find any bomb cases to use");
                return;
            }

            var validBombCases = bombcases.Where(pair => pair.Value >= componentCount);
            var minBombCases   = !validBombCases.Any() ?
                                 bombcases.Where(pair => pair.Value == bombcases.Max(pair2 => pair2.Value)) :
                                 validBombCases.Where(pair => pair.Value == validBombCases.Min(pair2 => pair2.Value));

            prefabPool.Objects = minBombCases.Select(x => x.Key).ToList();
        }
    }
Example #11
0
    void Start()
    {
        GetComponent <KMGameInfo>().OnStateChange += delegate(KMGameInfo.State state)
        {
            if (state == KMGameInfo.State.Gameplay)
            {
                BombGenerator bombGenerator = FindObjectOfType <BombGenerator>();

                if (bombGenerator.BombPrefabOverride == null)                 // No point in doing anything if they aren't even going to use the ObjectPool.
                {
                    GameplayState gameplayState = SceneManager.Instance.GameplayState;
                    Mission       mission       = null;
                    if (!string.IsNullOrEmpty(GameplayState.MissionToLoad))
                    {
                        if (GameplayState.MissionToLoad.Equals(FreeplayMissionGenerator.FREEPLAY_MISSION_ID))
                        {
                            mission = FreeplayMissionGenerator.Generate(GameplayState.FreeplaySettings);
                        }
                        else if (GameplayState.MissionToLoad.Equals(ModMission.CUSTOM_MISSION_ID))
                        {
                            mission = GameplayState.CustomMission;
                        }
                        else
                        {
                            mission = MissionManager.Instance.GetMission(GameplayState.MissionToLoad);
                        }
                    }

                    if (mission == null)
                    {
                        LogError("Unable to find mission.");
                        return;
                    }

                    bool frontFaceOnly  = mission.GeneratorSetting.FrontFaceOnly;
                    int  componentCount = mission.GeneratorSetting.ComponentPools.Where(pool => pool.ModTypes == null || !(pool.ModTypes.Contains("Factory Mode") || pool.ModTypes.Contains("Multiple Bombs"))).Sum(pool => pool.Count) + 1;

                    ObjectPool prefabPool = bombGenerator.BombPrefabPool;

                    Dictionary <GameObject, int> bombcases = prefabPool.Objects
                                                             .Where(gameobject => gameobject.GetComponent <KMBomb>() != null)
                                                             .ToDictionary(gameobject => gameobject, gameobject =>
                    {
                        if (!frontFaceOnly)
                        {
                            return(gameobject.GetComponent <KMBomb>().Faces.Select(face => face.Anchors.Count).Sum());
                        }
                        else
                        {
                            return(gameobject.GetComponent <KMBomb>().Faces[0].Anchors.Count);
                        }
                    });

                    bombcases.Add(prefabPool.Default, !frontFaceOnly ? 12 : 6);

                    if (bombcases.Count == 0)
                    {
                        LogError("Unable to find any bomb cases to use.");
                        return;
                    }

                    var validBombCases = bombcases.Where(pair => pair.Value >= componentCount);
                    var minBombCases   = validBombCases.Count() == 0 ?
                                         bombcases.Where(pair => pair.Value == bombcases.Max(pair2 => pair2.Value)) :
                                         validBombCases.Where(pair => pair.Value == validBombCases.Min(pair2 => pair2.Value));

                    prefabPool.Objects = minBombCases.Select(x => x.Key).ToList();
                }
            }
        };
    }
Example #12
0
 // attach bomb generator, call from bomb generator.
 public void setBombGenerator(BombGenerator bg)
 {
     this.bg = bg;
 }