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); }
/// <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); }
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())); }
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); }
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)); }
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()); }
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); }