예제 #1
0
    private object CreateMission(CustomMission mission)
    {
        KMMission template = (KMMission)ScriptableObject.CreateInstance(typeof(KMMission));

        template.name                = mission.ID;
        template.DisplayName         = mission.Name;
        template.PacingEventsEnabled = mission.PacingEvents;

        KMGeneratorSetting generator = new KMGeneratorSetting();

        generator.FrontFaceOnly             = mission.FrontFaceOnly;
        generator.NumStrikes                = mission.Strikes;
        generator.TimeLimit                 = mission.TimeLimit;
        generator.TimeBeforeNeedyActivation = mission.TimeBeforeNeedyActivation;

        foreach (var pool in mission.ComponentPools)
        {
            KMComponentPool componentpool = ConvertPool(mission, pool);

            generator.ComponentPools.Add(componentpool);
        }

        template.GeneratorSetting = generator;

        var type     = FindType("ModMission");
        var instance = ScriptableObject.CreateInstance(type);
        var InstType = instance.GetType();

        InstType.GetMethod("ConfigureFrom", @public).Invoke(instance, new object[] { template, "MissionMaker" });
        InstType.GetProperty("name", @public).SetValue(instance, mission.ID, null);

        //InstType.GetProperty("INVALID_MISSION_ID", BindingFlags.Public | BindingFlags.Static).SetValue(instance, mission.ID, null); // This should block out any kind of records being set for these custom missions.

        return(instance);
    }
예제 #2
0
 /// <summary>
 /// Creates and returns a new bomb with
 /// </summary>
 /// <param name="missionId">The mission id to spawn the bomb based on</param>
 /// <param name="generatorSettings">Generator seetings that will be used if missionId is empty or null </param>
 /// <param name="spawnPoint">A gameobject whose transform will determine where the bomb spawns </param>
 /// <param name="seed">The seed used to generate the bomb, currently this must parse to an int </param>
 public KMBomb CreateBomb(string missionId, KMGeneratorSetting generatorSettings, GameObject spawnPoint, string seed)
 {
     if (OnCreateBomb != null)
     {
         return(OnCreateBomb(missionId, generatorSettings, spawnPoint, seed));
     }
     return(null);
 }
예제 #3
0
 public static bool SameMission(this KMGeneratorSetting a, KMGeneratorSetting b)
 {
     return(Mathf.RoundToInt(a.TimeLimit) == Mathf.RoundToInt(b.TimeLimit) &&
            a.NumStrikes == b.NumStrikes &&
            a.TimeBeforeNeedyActivation == b.TimeBeforeNeedyActivation &&
            a.FrontFaceOnly == b.FrontFaceOnly &&
            a.OptionalWidgetCount == b.OptionalWidgetCount &&
            a.ComponentPools.FilterPools().SamePools(b.ComponentPools.FilterPools()));
 }
예제 #4
0
    bool StartMission()
    {
        KMGeneratorSetting generatorSettings = new KMGeneratorSetting();

        generatorSettings.NumStrikes = 3;
        generatorSettings.TimeLimit  = time;

        generatorSettings.ComponentPools      = BuildComponentPools();
        generatorSettings.OptionalWidgetCount = widgets;

        KMMission mission = ScriptableObject.CreateInstance <KMMission>() as KMMission;

        mission.DisplayName      = "Custom Freeplay";
        mission.GeneratorSetting = generatorSettings;

        GetComponent <KMGameCommands>().StartMission(mission, "" + UnityEngine.Random.Range(0, int.MaxValue));
        return(false);
    }
예제 #5
0
    private void addGeneratorSetting(int bombIndex)
    {
        KMGeneratorSetting newGeneratorSetting = new KMGeneratorSetting();

        newGeneratorSetting.ComponentPools = new List <KMComponentPool>()
        {
            new KMComponentPool()
            {
                Count = 1, ModTypes = new List <string>()
            }
        };
        int componentPoolIndex           = addComponentPool(serializedObject.FindProperty("GeneratorSetting"));
        SerializedProperty componentPool = serializedObject.FindProperty("GeneratorSetting.ComponentPools").GetArrayElementAtIndex(componentPoolIndex);
        SerializedProperty modTypes      = componentPool.FindPropertyRelative("ModTypes");

        modTypes.arraySize = 1;
        modTypes.GetArrayElementAtIndex(0).stringValue = MULTIPLE_BOMBS_COMPONENT_POOL_ID + ":" + bombIndex + ":" + JsonConvert.SerializeObject(newGeneratorSetting);
        multipleBombsGeneratorSettings.Add(bombIndex, new KeyValuePair <KMGeneratorSetting, int>(newGeneratorSetting, componentPoolIndex));
    }
예제 #6
0
    private static string GetBombSettingsString(KMGeneratorSetting bomb, KMGeneratorSetting compare = null)
    {
        var result = "";

        // Time limit
        if (compare == null || Math.Abs(bomb.TimeLimit - compare.TimeLimit) > 0.1f)
        {
            var t = TimeSpan.FromSeconds(bomb.TimeLimit);
            result += string.Format("{0:D2}:{1:D2}:{2:D2}\n",
                                    t.Hours,
                                    t.Minutes,
                                    t.Seconds);
        }

        // Strike count
        if (compare == null || bomb.NumStrikes != compare.NumStrikes)
        {
            result += bomb.NumStrikes + "X\n";
        }

        // Needy activation
        if (compare == null || bomb.TimeBeforeNeedyActivation != compare.TimeBeforeNeedyActivation)
        {
            result += string.Format("needyactivationtime:{0}\n", bomb.TimeBeforeNeedyActivation);
        }

        // Widget count
        if (compare == null || bomb.OptionalWidgetCount != compare.OptionalWidgetCount)
        {
            result += string.Format("widgets:{0}\n", bomb.OptionalWidgetCount);
        }

        // Front only
        if (bomb.FrontFaceOnly && (compare == null || bomb.FrontFaceOnly != compare.FrontFaceOnly))
        {
            result += "frontonly\n";
        }

        return(result.TrimEnd());
    }
예제 #7
0
    public static KMMission CreateMissionFromDmgString(string dmgString)
    {
        string errorMessage = null;

        // Parse the DMG string
        var matches = TokenRegex.Matches(ContinuationRegex.Replace(dmgString, ""));

        if (matches.Count == 0)
        {
            throw new ParseException("invalid DMG string provided");
        }

        // Bomb settings
        KMGeneratorSetting        currentBomb = null;
        List <KMGeneratorSetting> bombs       = null;

        // Flags
        var bombRepeatCount               = 0;
        int?defaultTime                   = null,
           defaultStrikes                 = null,
           defaultNeedyActivationTime     = null,
           defaultWidgetCount             = null;
        var  defaultFrontOnly             = false;
        bool timeSpecified                = false,
             strikesSpecified             = false,
             needyActivationTimeSpecified = false,
             widgetCountSpecified         = false,
             missionNameSpecified         = false;
        int?factoryMode                   = null;

        // Mission setup
        var mission = ScriptableObject.CreateInstance <KMMission>();

        mission.PacingEventsEnabled = true;
        var pools = new List <KMComponentPool>();
        var missionDescription = "";

        // New bomb handler
        NewBombDelegate newBomb = delegate
        {
            currentBomb = new KMGeneratorSetting {
                FrontFaceOnly = defaultFrontOnly
            };
            timeSpecified            = strikesSpecified = needyActivationTimeSpecified =
                widgetCountSpecified = false;
            pools = new List <KMComponentPool>();
        };

        // Bomb validation handler
        ValidateBombDelegate validateBomb = delegate
        {
            // Load the pools and setup default generator settings
            currentBomb.ComponentPools = pools;
            if (!timeSpecified)
            {
                currentBomb.TimeLimit = defaultTime ?? currentBomb.GetComponentCount() * 120;
            }
            if (!strikesSpecified)
            {
                currentBomb.NumStrikes = defaultStrikes ?? Math.Max(3, currentBomb.GetComponentCount() / 12);
            }
            if (!needyActivationTimeSpecified && defaultNeedyActivationTime.HasValue)
            {
                currentBomb.TimeBeforeNeedyActivation = defaultNeedyActivationTime.Value;
            }
            if (!widgetCountSpecified && defaultWidgetCount.HasValue)
            {
                currentBomb.OptionalWidgetCount = defaultWidgetCount.Value;
            }
        };

        // Deal with each token
        foreach (Match match in matches)
        {
            // Inline mission name
            if (match.Groups["MissionName"].Success)
            {
                if (missionNameSpecified)
                {
                    errorMessage = "mission name specified multiple times";
                    goto error;
                }

                missionNameSpecified = true;

                mission.DisplayName = match.Groups["MissionName"].Value.Trim();
            }
            // Inline description
            else if (match.Groups["DescriptionLine"].Success)
            {
                missionDescription += match.Groups["DescriptionLine"].Value.Trim() + "\n";

                mission.Description = missionDescription.Trim();
            }
            // Multiline name + description
            else if (match.Groups["MissionName2"].Success && match.Groups["Description"].Success)
            {
                if (missionNameSpecified)
                {
                    errorMessage = "mission name specified multiple times";
                    goto error;
                }

                missionNameSpecified = true;

                mission.DisplayName = match.Groups["MissionName2"].Value.Trim();
                mission.Description =
                    match.Groups["Description"].Value.Split('\n').Select(line => line.Trim()).Join("\n");
            }
            // Timer
            else if (match.Groups["Time1"].Success)
            {
                if (timeSpecified)
                {
                    errorMessage = "time specified multiple times";
                    goto error;
                }

                timeSpecified = true;

                // Parse time
                var time = match.Groups["Time3"].Success
                    ? int.Parse(match.Groups["Time1"].Value) * 3600 + int.Parse(match.Groups["Time2"].Value) * 60 +
                           int.Parse(match.Groups["Time3"].Value)
                    : int.Parse(match.Groups["Time1"].Value) * 60 + int.Parse(match.Groups["Time2"].Value);
                if (time <= 0)
                {
                    errorMessage = "invalid time limit";
                    goto error;
                }

                if (currentBomb != null)
                {
                    currentBomb.TimeLimit = time;
                }
                else
                {
                    defaultTime = time;
                }
            }
            // Strike count
            else if (match.Groups["Strikes"].Success || match.Groups["Setting"].Value
                     .Equals("strikes", StringComparison.InvariantCultureIgnoreCase))
            {
                if (strikesSpecified)
                {
                    errorMessage = ("strikes specified multiple times");
                    goto error;
                }

                strikesSpecified = true;

                var strikes = int.Parse(match.Groups["Strikes"].Success
                    ? match.Groups["Strikes"].Value
                    : match.Groups["Value"].Value);
                if (strikes <= 0)
                {
                    errorMessage = "invalid strike limit";
                    goto error;
                }

                if (currentBomb != null)
                {
                    currentBomb.NumStrikes = strikes;
                }
                else
                {
                    defaultStrikes = strikes;
                }
            }
            // Various settings
            else if (match.Groups["Setting"].Success)
            {
                switch (match.Groups["Setting"].Value.ToLowerInvariant())
                {
                // Needy timer
                case "needyactivationtime":
                    if (needyActivationTimeSpecified)
                    {
                        errorMessage = "needy activation time specified multiple times";
                        goto error;
                    }

                    needyActivationTimeSpecified = true;

                    var needyActivationTime = int.Parse(match.Groups["Value"].Value);
                    if (needyActivationTime < 0)
                    {
                        errorMessage = "invalid needy activation time";
                        goto error;
                    }

                    if (currentBomb != null)
                    {
                        currentBomb.TimeBeforeNeedyActivation = needyActivationTime;
                    }
                    else
                    {
                        defaultNeedyActivationTime = needyActivationTime;
                    }
                    break;

                // Widgets
                case "widgets":
                    if (widgetCountSpecified)
                    {
                        errorMessage = "widget count specified multiple times";
                        goto error;
                    }

                    widgetCountSpecified = true;
                    int widgetCount;
                    if (!int.TryParse(match.Groups["Value"].Value, out widgetCount))
                    {
                        errorMessage = "invalid widget count";
                        goto error;
                    }

                    if (widgetCount < 0)
                    {
                        errorMessage = "invalid widget count";
                        goto error;
                    }

                    if (currentBomb != null)
                    {
                        currentBomb.OptionalWidgetCount = widgetCount;
                    }
                    else
                    {
                        defaultWidgetCount = widgetCount;
                    }
                    break;

                // Front only
                case "frontonly":
                    if (currentBomb != null)
                    {
                        currentBomb.FrontFaceOnly = true;
                    }
                    else
                    {
                        defaultFrontOnly = true;
                    }
                    break;

                // No pacing
                case "nopacing":
                    if (bombs != null && currentBomb != null)
                    {
                        errorMessage = "nopacing cannot be a bomb-level setting";
                        goto error;
                    }
                    else
                    {
                        mission.PacingEventsEnabled = false;
                    }

                    break;

                // Factory mode
                case "factory":
                    if (bombs != null && currentBomb != null)
                    {
                        errorMessage = "Factory mode cannot be a bomb-level setting";
                        goto error;
                    }
                    else if (factoryMode.HasValue)
                    {
                        errorMessage = "factory mode specified multiple times";
                        goto error;
                    }
                    else
                    {
                        int i;
                        for (i = 0; i < FactoryModes.Length; ++i)
                        {
                            if (FactoryModes[i].Equals(match.Groups["Value"].Value,
                                                       StringComparison.InvariantCultureIgnoreCase))
                            {
                                break;
                            }
                        }

                        if (i >= FactoryModes.Length)
                        {
                            errorMessage = "invalid factory mode";
                            goto error;
                        }

                        factoryMode = i;
                    }

                    break;
                }
            }
            // Module pools
            else if (match.Groups["ID"].Success)
            {
                // Break on unmatched quote
                if (match.Groups["Error"].Success)
                {
                    errorMessage = "unclosed quote";
                    goto error;
                }

                // Create a new bomb
                if (bombs == null)
                {
                    if (currentBomb == null)
                    {
                        newBomb();

                        // Setup the bomb
                        if (defaultTime.HasValue)
                        {
                            timeSpecified         = true;
                            currentBomb.TimeLimit = defaultTime.Value;
                        }

                        if (defaultStrikes.HasValue)
                        {
                            strikesSpecified       = true;
                            currentBomb.NumStrikes = defaultStrikes.Value;
                        }

                        if (defaultNeedyActivationTime.HasValue)
                        {
                            needyActivationTimeSpecified          = true;
                            currentBomb.TimeBeforeNeedyActivation = defaultNeedyActivationTime.Value;
                        }

                        if (defaultWidgetCount.HasValue)
                        {
                            widgetCountSpecified            = true;
                            currentBomb.OptionalWidgetCount = defaultWidgetCount.Value;
                        }
                    }
                }
                else
                {
                    if (currentBomb == null)
                    {
                        errorMessage = "Unexpected module pool";
                        goto error;
                    }
                }

                // Create the module pool
                var pool = new KMComponentPool
                {
                    Count          = match.Groups["Count"].Success ? int.Parse(match.Groups["Count"].Value) : 1,
                    ComponentTypes = new List <KMComponentPool.ComponentTypeEnum>(),
                    ModTypes       = new List <string>()
                };
                if (pool.Count <= 0)
                {
                    errorMessage = "Invalid module pool count";
                    goto error;
                }

                // Parse module IDs
                var list = match.Groups["ID"].Value.Replace("\"", "").Replace("'", "").Trim();
                if (list.StartsWith("mode:"))
                {
                    continue;
                }
                switch (list)
                {
                // Module groups
                case "ALL_SOLVABLE":
                    pool.AllowedSources =
                        KMComponentPool.ComponentSource.Base | KMComponentPool.ComponentSource.Mods;
                    pool.SpecialComponentType = KMComponentPool.SpecialComponentTypeEnum.ALL_SOLVABLE;
                    break;

                case "ALL_NEEDY":
                    pool.AllowedSources =
                        KMComponentPool.ComponentSource.Base | KMComponentPool.ComponentSource.Mods;
                    pool.SpecialComponentType = KMComponentPool.SpecialComponentTypeEnum.ALL_NEEDY;
                    break;

                case "ALL_VANILLA":
                    pool.AllowedSources       = KMComponentPool.ComponentSource.Base;
                    pool.SpecialComponentType = KMComponentPool.SpecialComponentTypeEnum.ALL_SOLVABLE;
                    break;

                case "ALL_MODS":
                    pool.AllowedSources       = KMComponentPool.ComponentSource.Mods;
                    pool.SpecialComponentType = KMComponentPool.SpecialComponentTypeEnum.ALL_SOLVABLE;
                    break;

                case "ALL_VANILLA_NEEDY":
                    pool.AllowedSources       = KMComponentPool.ComponentSource.Base;
                    pool.SpecialComponentType = KMComponentPool.SpecialComponentTypeEnum.ALL_NEEDY;
                    break;

                case "ALL_MODS_NEEDY":
                    pool.AllowedSources       = KMComponentPool.ComponentSource.Mods;
                    pool.SpecialComponentType = KMComponentPool.SpecialComponentTypeEnum.ALL_NEEDY;
                    break;

                // Individual module IDs
                default:
                    foreach (var id in list.Split(',', '+').Select(s => s.Trim()))
                    {
                        switch (id)
                        {
                        // Vanilla modules
                        case "WireSequence":
                            pool.ComponentTypes.Add(KMComponentPool.ComponentTypeEnum.WireSequence);
                            break;

                        case "Wires":
                            pool.ComponentTypes.Add(KMComponentPool.ComponentTypeEnum.Wires);
                            break;

                        case "WhosOnFirst":
                            pool.ComponentTypes.Add(KMComponentPool.ComponentTypeEnum.WhosOnFirst);
                            break;

                        case "Simon":
                            pool.ComponentTypes.Add(KMComponentPool.ComponentTypeEnum.Simon);
                            break;

                        case "Password":
                            pool.ComponentTypes.Add(KMComponentPool.ComponentTypeEnum.Password);
                            break;

                        case "Morse":
                            pool.ComponentTypes.Add(KMComponentPool.ComponentTypeEnum.Morse);
                            break;

                        case "Memory":
                            pool.ComponentTypes.Add(KMComponentPool.ComponentTypeEnum.Memory);
                            break;

                        case "Maze":
                            pool.ComponentTypes.Add(KMComponentPool.ComponentTypeEnum.Maze);
                            break;

                        case "Keypad":
                            pool.ComponentTypes.Add(KMComponentPool.ComponentTypeEnum.Keypad);
                            break;

                        case "Venn":
                            pool.ComponentTypes.Add(KMComponentPool.ComponentTypeEnum.Venn);
                            break;

                        case "BigButton":
                            pool.ComponentTypes.Add(KMComponentPool.ComponentTypeEnum.BigButton);
                            break;

                        case "NeedyCapacitor":
                            pool.ComponentTypes.Add(KMComponentPool.ComponentTypeEnum.NeedyCapacitor);
                            break;

                        case "NeedyVentGas":
                            pool.ComponentTypes.Add(KMComponentPool.ComponentTypeEnum.NeedyVentGas);
                            break;

                        case "NeedyKnob":
                            pool.ComponentTypes.Add(KMComponentPool.ComponentTypeEnum.NeedyKnob);
                            break;

                        // Modded modules
                        default:
                            pool.ModTypes.Add(id);
                            break;
                        }
                    }

                    break;
                }

                pools.Add(pool);
            }
            // Multiple Bombs starting point
            else if (match.Groups["Open"].Success)
            {
                if (currentBomb != null)
                {
                    errorMessage = "Unexpected '('";
                    goto error;
                }

                bombRepeatCount = match.Groups["Count"].Success ? int.Parse(match.Groups["Count"].Value) : 1;
                if (bombRepeatCount <= 0)
                {
                    errorMessage = "Invalid bomb repeat count";
                    goto error;
                }

                if (bombs == null)
                {
                    bombs = new List <KMGeneratorSetting>();
                }
                newBomb();
            }
            // Multiple Bombs ending point
            else if (match.Groups["Close"].Success)
            {
                if (currentBomb == null)
                {
                    errorMessage = "Unexpected ')'";
                    goto error;
                }

                validateBomb();
                for (; bombRepeatCount > 0; --bombRepeatCount)
                {
                    bombs.Add(currentBomb);
                }
                currentBomb = null;
            }
        }

        // Check if no modules were provided
        if (bombs == null)
        {
            if (currentBomb == null)
            {
                errorMessage = "No solvable modules";
                goto error;
            }

            validateBomb();
            mission.GeneratorSetting = currentBomb;
        }
        else if (bombs.Count == 0)
        {
            errorMessage = "No solvable modules";
        }

        // Handle parsing error
error:
        if (errorMessage != null)
        {
            Debug.LogErrorFormat("[DMG] Error: {0}", errorMessage);
            throw new ParseException(errorMessage);
        }

        // Convert bombs to JSON for Multiple Bombs
        if (bombs != null)
        {
            mission.GeneratorSetting = bombs[0];
            if (bombs.Count > 1)
            {
                mission.GeneratorSetting.ComponentPools.Add(new KMComponentPool
                {
                    Count    = bombs.Count - 1, ComponentTypes = new List <KMComponentPool.ComponentTypeEnum>(),
                    ModTypes = new List <string> {
                        "Multiple Bombs"
                    }
                });
                for (int i = 1; i < bombs.Count; ++i)
                {
                    // if (bombs[i] != mission.GeneratorSetting)
                    mission.GeneratorSetting.ComponentPools.Add(new KMComponentPool
                    {
                        Count    = 1, ComponentTypes = new List <KMComponentPool.ComponentTypeEnum>(),
                        ModTypes = new List <string>
                        {
                            string.Format("Multiple Bombs:{0}:{1}", i, JsonConvert.SerializeObject(bombs[i]))
                        }
                    });
                }
            }
        }

        // Apply factory mode
        if (factoryMode.HasValue)
        {
            mission.GeneratorSetting.ComponentPools.Add(new KMComponentPool
            {
                Count    = factoryMode.Value, ComponentTypes = new List <KMComponentPool.ComponentTypeEnum>(),
                ModTypes = new List <string> {
                    "Factory Mode"
                }
            });
        }

        return(mission);
    }