/// <summary> /// Draws and responds to a toggle box for a component type. Clears Special types, if set. /// </summary> private void DrawToggle(int poolIndex, KMComponentPool.ComponentTypeEnum typeToToggle) { KMMission mission = (KMMission)serializedObject.targetObject; KMComponentPool componentPool = mission.GeneratorSetting.ComponentPools[poolIndex]; bool previousValue = componentPool.ComponentTypes.Contains(typeToToggle); if (EditorGUILayout.ToggleLeft( typeToToggle.ToString(), previousValue)) { if (!componentPool.ComponentTypes.Contains(typeToToggle)) { componentPool.ComponentTypes.Add(typeToToggle); } } else { componentPool.ComponentTypes.RemoveAll(x => x == typeToToggle); } //If we just toggled something, clear any special flags too bool currentValue = componentPool.ComponentTypes.Contains(typeToToggle); if (previousValue != currentValue) { componentPool.SpecialComponentType = KMComponentPool.SpecialComponentTypeEnum.None; } }
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); }
private static bool SamePool(this KMComponentPool a, KMComponentPool b) { return(a.Count == b.Count && a.AllowedSources == b.AllowedSources && a.SpecialComponentType == b.SpecialComponentType && a.ComponentTypes.ListEquals(b.ComponentTypes) && a.ModTypes.ListEquals(b.ModTypes)); }
/// <summary> /// Draw the array of mod module names to be selected from. /// </summary> /// <param name="poolIndex"></param> protected void DrawModTypesList(int poolIndex) { KMMission mission = (KMMission)serializedObject.targetObject; KMComponentPool componentPool = mission.GeneratorSetting.ComponentPools[poolIndex]; SerializedProperty componentPools = serializedObject.FindProperty("GeneratorSetting.ComponentPools"); var element = componentPools.GetArrayElementAtIndex(poolIndex); EditorGUILayout.PropertyField(element.FindPropertyRelative("ModTypes"), true); //Clear any special flags if needed if (componentPool.ModTypes != null && componentPool.ModTypes.Count > 0) { componentPool.SpecialComponentType = KMComponentPool.SpecialComponentTypeEnum.None; } }
/// <summary> /// Draws and responds to an enum picker for a special component type. Clears regular and special types, if set. /// </summary> private void DrawSpecialPicker(int poolIndex) { KMMission mission = (KMMission)serializedObject.targetObject; KMComponentPool componentPool = mission.GeneratorSetting.ComponentPools[poolIndex]; KMComponentPool.SpecialComponentTypeEnum previousValue = componentPool.SpecialComponentType; componentPool.SpecialComponentType = (KMComponentPool.SpecialComponentTypeEnum)EditorGUILayout.EnumPopup( "Type:", componentPool.SpecialComponentType, GUILayout.MinWidth(400)); //If we just changed the special type, clear any component types too KMComponentPool.SpecialComponentTypeEnum currentValue = componentPool.SpecialComponentType; if (previousValue != currentValue) { componentPool.ComponentTypes.Clear(); componentPool.ModTypes.Clear(); } }
/// <summary> /// Draws and responds to a picker for a component sources. /// </summary> private void DrawComponentSourcePicker(int poolIndex) { string[] options = new string[] { "Base", "Mods", "Base and Mods" }; KMMission mission = (KMMission)serializedObject.targetObject; KMComponentPool componentPool = mission.GeneratorSetting.ComponentPools[poolIndex]; KMComponentPool.ComponentSource previousValue = componentPool.AllowedSources; bool allowBase = (previousValue & KMComponentPool.ComponentSource.Base) == KMComponentPool.ComponentSource.Base; bool allowMods = (previousValue & KMComponentPool.ComponentSource.Mods) == KMComponentPool.ComponentSource.Mods; int index = 0; if (allowBase) { if (allowMods) { index = 2; } else { index = 0; } } else { index = 1; } index = EditorGUILayout.Popup("Source:", index, options, GUILayout.MinWidth(400)); switch (index) { case 0: { componentPool.AllowedSources = KMComponentPool.ComponentSource.Base; } break; case 1: { componentPool.AllowedSources = KMComponentPool.ComponentSource.Mods; } break; case 2: { componentPool.AllowedSources = KMComponentPool.ComponentSource.Base | KMComponentPool.ComponentSource.Mods; } break; } }
/// <summary> /// Draw the array of mod module names to be selected from. /// </summary> /// <param name="poolIndex"></param> protected void DrawModTypesList(int poolIndex) { KMMission mission = (KMMission)serializedObject.targetObject; KMComponentPool componentPool = mission.GeneratorSetting.ComponentPools[poolIndex]; SerializedProperty componentPools = serializedObject.FindProperty("GeneratorSetting.ComponentPools"); var modTypesElement = componentPools.GetArrayElementAtIndex(poolIndex).FindPropertyRelative("ModTypes"); EditorGUILayout.PropertyField(modTypesElement, true); // Trim whitespace from mod types for (int i = 0; i < modTypesElement.arraySize; i++) { modTypesElement.GetArrayElementAtIndex(i).stringValue = modTypesElement.GetArrayElementAtIndex(i).stringValue.Trim(); } //Clear any special flags if needed if (componentPool.ModTypes != null && componentPool.ModTypes.Count > 0) { componentPool.SpecialComponentType = KMComponentPool.SpecialComponentTypeEnum.None; } }
List <KMComponentPool> BuildComponentPools() { List <KMComponentPool> pools = new List <KMComponentPool>(); KMComponentPool solvablePool = new KMComponentPool(); solvablePool.ComponentTypes = new List <KMComponentPool.ComponentTypeEnum>(); solvablePool.ModTypes = new List <string>(); KMComponentPool needyPool = new KMComponentPool(); needyPool.ComponentTypes = new List <KMComponentPool.ComponentTypeEnum>(); needyPool.ModTypes = new List <string>(); foreach (KMGameInfo.KMModuleInfo moduleInfo in availableModules) { if (!disabledModuleIds.Contains(moduleInfo.ModuleId)) { KMComponentPool pool = moduleInfo.IsNeedy ? needyPool : solvablePool; if (moduleInfo.IsMod) { pool.ModTypes.Add(moduleInfo.ModuleId); } else { pool.ComponentTypes.Add(moduleInfo.ModuleType); } } } solvablePool.Count = needyPool.ComponentTypes.Count + needyPool.ModTypes.Count > 0 ? modules - 1 : modules; needyPool.Count = needyPool.ComponentTypes.Count + needyPool.ModTypes.Count > 0 ? 1 : 0; pools.Add(solvablePool); pools.Add(needyPool); return(pools); }
/// <summary> /// Draws a label summarizing the component types selected, or a warning if none are. /// </summary> /// <param name="componentFlags"></param> private void DrawComponentPoolSummaryLabel(int poolIndex) { KMMission mission = (KMMission)serializedObject.targetObject; KMComponentPool pool = mission.GeneratorSetting.ComponentPools[poolIndex]; string[] nonEmptyModNames = pool.ModTypes.Where(t => !string.IsNullOrEmpty(t)).ToArray(); if (pool.SpecialComponentType != KMComponentPool.SpecialComponentTypeEnum.None) { string specialSummary = string.Format("{0} ({1})", pool.SpecialComponentType.ToString(), pool.AllowedSources.ToString()); EditorGUILayout.LabelField(specialSummary); } else if (pool.ComponentTypes.Count > 0 || nonEmptyModNames.Length > 0) { EditorStyles.label.wordWrap = true; string componentTypeNames = String.Join(", ", pool.ComponentTypes.Select(x => x.ToString()).ToArray()); if (nonEmptyModNames.Length > 0) { if (componentTypeNames.Length > 0) { componentTypeNames += ", "; } componentTypeNames += String.Join(", ", nonEmptyModNames); } EditorGUILayout.LabelField(componentTypeNames); } else { EditorGUILayout.HelpBox("No component type selected!", MessageType.Error); } }
private static string GetPoolDmgString(KMComponentPool pool) { string source; // Handle special pools switch (pool.SpecialComponentType) { // Normal pool case KMComponentPool.SpecialComponentTypeEnum.None: var modules = new List <string>(pool.ModTypes); if (pool.ComponentTypes != null) { modules.AddRange(pool.ComponentTypes.Select(vanillaModule => vanillaModule.ToString())); } source = modules.Select(s => s.IndexOfAny(new[] { ',', ' ', '+' }) != -1 ? '"' + s + '"' : s).Join(","); break; // Needy pool case KMComponentPool.SpecialComponentTypeEnum.ALL_NEEDY: if ((pool.AllowedSources & KMComponentPool.ComponentSource.Base & KMComponentPool.ComponentSource.Mods) != 0) { source = "ALL_NEEDY"; } else if ((pool.AllowedSources & KMComponentPool.ComponentSource.Mods) != 0 && (pool.AllowedSources & KMComponentPool.ComponentSource.Base) == 0) { source = "ALL_MODS_NEEDY"; } else { source = "ALL_VANILLA_NEEDY"; } break; // Solvable pool case KMComponentPool.SpecialComponentTypeEnum.ALL_SOLVABLE: if ((pool.AllowedSources & KMComponentPool.ComponentSource.Base & KMComponentPool.ComponentSource.Mods) != 0) { source = "ALL_SOLVABLE"; } else if ((pool.AllowedSources & KMComponentPool.ComponentSource.Mods) != 0 && (pool.AllowedSources & KMComponentPool.ComponentSource.Base) == 0) { source = "ALL_MODS"; } else { source = "ALL_VANILLA"; } break; default: return(null); } // Create pool string return(pool.Count == 1 ? source : string.Format("{0}*{1}", pool.Count, source)); }
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); }
private KMComponentPool ConvertPool(CustomMission mission, CustomPool pool) { KMComponentPool componentpool = new KMComponentPool(); string Source = pool.Source; // If no source is specified try to figure out what the user wanted. if (Source == null) { if (pool.Modules != null) { Source = "none"; } else if (pool.Group != null) { Source = "group"; } else if (pool.Pools != null) { Source = "pools"; } else { Log("No source was able to be determined for a pool in the mission located at {0}.", mission.Path); return(null); } } else { Source = Source.ToLowerInvariant(); } if (Source == "group") { if (pool.Group == null) { Log("Source was set to Group but no Group parameter found in mission located at {0}.", mission.Path); return(null); } if (Groups.ContainsKey(pool.Group)) { CustomGroup group = Groups[pool.Group]; pool.Group = null; pool.Source = group.Source; pool.Mods = group.Mods; pool.Base = group.Base; if (pool.Blacklist != null) { pool.Modules = group.Modules.Except(pool.Blacklist).ToList(); } else { pool.Modules = group.Modules; } Source = pool.Source != null?pool.Source.ToLowerInvariant() : "none"; } else { Log("Unable to find group {0} for the mission located at {2}.", pool.Group, mission.Path); } } if (Source == "pools") { if (pool.Pools == null) { Log("Source was set to Pools but no Pools parameter found in mission located at {0}.", mission.Path); return(null); } componentpool.Count = pool.Count; HashSet <string> Modules = new HashSet <string>(); HashSet <KMComponentPool.ComponentTypeEnum> ComponentTypes = new HashSet <KMComponentPool.ComponentTypeEnum>(); foreach (CustomPool pool2 in pool.Pools) { KMComponentPool componentpool2 = ConvertPool(mission, pool2); foreach (string module in componentpool2.ModTypes) { Modules.Add(module); } foreach (KMComponentPool.ComponentTypeEnum module in componentpool2.ComponentTypes) { ComponentTypes.Add(module); } } componentpool.ModTypes = Modules.ToList(); componentpool.ComponentTypes = ComponentTypes.ToList(); if (ComponentTypes.Count > 0 && !(Modules.Count > 0)) { componentpool.AllowedSources = KMComponentPool.ComponentSource.Base; } else if (!(ComponentTypes.Count > 0) && Modules.Count > 0) { componentpool.AllowedSources = KMComponentPool.ComponentSource.Mods; } else { componentpool.AllowedSources = KMComponentPool.ComponentSource.Base | KMComponentPool.ComponentSource.Mods; } componentpool.SpecialComponentType = KMComponentPool.SpecialComponentTypeEnum.None; } if (Source == "none") { if (pool.Modules == null) { Log("Source was set to None but no Modules parameter found in the mission located at {0}.", mission.Path); return(null); } List <string> modded = new List <string>(); List <KMComponentPool.ComponentTypeEnum> vanilla = new List <KMComponentPool.ComponentTypeEnum>(); foreach (string module in pool.Modules) { if (Enum.IsDefined(typeof(KMComponentPool.ComponentTypeEnum), module)) { if (module != "Empty" && module != "Timer") { vanilla.Add((KMComponentPool.ComponentTypeEnum)Enum.Parse(typeof(KMComponentPool.ComponentTypeEnum), module)); } } else { modded.Add(module); } } bool hasModded = modded.Count > 0; if (hasModded) { componentpool.ModTypes = modded; } bool hasVanilla = vanilla.Count > 0; componentpool.ComponentTypes = hasVanilla ? vanilla : new List <KMComponentPool.ComponentTypeEnum>(); if (hasVanilla && !hasModded) { componentpool.AllowedSources = KMComponentPool.ComponentSource.Base; } else if (!hasVanilla && hasModded) { componentpool.AllowedSources = KMComponentPool.ComponentSource.Mods; } else { componentpool.AllowedSources = KMComponentPool.ComponentSource.Base | KMComponentPool.ComponentSource.Mods; } componentpool.SpecialComponentType = KMComponentPool.SpecialComponentTypeEnum.None; } else { if (!pool.Base && !pool.Mods) { Log("A source besides None was used but has both base and mods disabled in the mission located at {0}. Skipping pool.", mission.Path); return(null); } if (pool.Base && !pool.Mods) { componentpool.AllowedSources = KMComponentPool.ComponentSource.Base; } else if (!pool.Base && pool.Mods) { componentpool.AllowedSources = KMComponentPool.ComponentSource.Mods; } else { componentpool.AllowedSources = KMComponentPool.ComponentSource.Base | KMComponentPool.ComponentSource.Mods; } componentpool.ComponentTypes = new List <KMComponentPool.ComponentTypeEnum>(); if (Source == "solvable") { if (pool.Mods) { componentpool.ModTypes = new List <string>(); foreach (KMBombModule module in GetAllModObjects <KMBombModule>()) { if (pool.Blacklist == null || !pool.Blacklist.Contains(module.ModuleType)) { componentpool.ModTypes.Add(module.ModuleType); } } } if (pool.Base) { componentpool.ComponentTypes = new List <KMComponentPool.ComponentTypeEnum>(); foreach (string name in Enum.GetNames(typeof(KMComponentPool.ComponentTypeEnum))) { if (!name.StartsWith("Needy") && name != "Empty" && name != "Timer" && (pool.Blacklist == null || !pool.Blacklist.Contains(name))) { componentpool.ComponentTypes.Add((KMComponentPool.ComponentTypeEnum)Enum.Parse(typeof(KMComponentPool.ComponentTypeEnum), name)); } } } } else if (Source == "needy") { if (pool.Mods) { componentpool.ModTypes = new List <string>(); foreach (KMNeedyModule module in GetAllModObjects <KMNeedyModule>()) { if (pool.Blacklist == null || !pool.Blacklist.Contains(module.ModuleType)) { componentpool.ModTypes.Add(module.ModuleType); } } } if (pool.Base) { componentpool.ComponentTypes = new List <KMComponentPool.ComponentTypeEnum>(); foreach (string name in Enum.GetNames(typeof(KMComponentPool.ComponentTypeEnum))) { if (name.StartsWith("Needy") && (pool.Blacklist == null || !pool.Blacklist.Contains(name))) { componentpool.ComponentTypes.Add((KMComponentPool.ComponentTypeEnum)Enum.Parse(typeof(KMComponentPool.ComponentTypeEnum), name)); } } } } else { Log("Unkown source format of {0} was found in the mission located at {1}.", pool.Source, mission.Path); return(null); } } componentpool.Count = pool.Count; return(componentpool); }
private bool ParseTextToMission(string text, out KMMission mission, out List <string> messages) { messages = new List <string>(); var matches = tokenRegex.Matches(text); if (matches.Count == 0 || (matches.Count == 1 && !matches[0].Value.Any(c => !char.IsWhiteSpace(c))) || matches[matches.Count - 1].Index + matches[matches.Count - 1].Length < text.Length) { messages.Add("Syntax error"); mission = null; return(false); } bool timeSpecified = false, strikesSpecified = false, anySolvableModules = false; mission = ScriptableObject.CreateInstance <KMMission>(); mission.PacingEventsEnabled = true; mission.GeneratorSetting = new KMGeneratorSetting(); List <KMComponentPool> pools = new List <KMComponentPool>(); foreach (Match match in matches) { if (match.Groups["Min"].Success) { if (timeSpecified) { messages.Add("Time specified multiple times"); } else { timeSpecified = true; mission.GeneratorSetting.TimeLimit = (match.Groups["Hr"].Success ? int.Parse(match.Groups["Hr"].Value) * 3600 : 0) + int.Parse(match.Groups["Min"].Value) * 60 + int.Parse(match.Groups["Sec"].Value); if (mission.GeneratorSetting.TimeLimit <= 0) { messages.Add("Invalid time limit"); } } } else if (match.Groups["Strikes"].Success) { if (strikesSpecified) { messages.Add("Strike limit specified multiple times"); } else { strikesSpecified = true; mission.GeneratorSetting.NumStrikes = int.Parse(match.Groups["Strikes"].Value); if (mission.GeneratorSetting.NumStrikes <= 0) { messages.Add("Invalid strike limit"); } } } else if (match.Groups["Setting"].Success) { switch (match.Groups["Setting"].Value.ToLowerInvariant()) { case "strikes": if (match.Groups["Value"].Success) { if (strikesSpecified) { messages.Add("Strike limit specified multiple times"); } else { strikesSpecified = true; mission.GeneratorSetting.NumStrikes = int.Parse(match.Groups["Value"].Value); if (mission.GeneratorSetting.NumStrikes <= 0) { messages.Add("Invalid strike limit"); } } } break; case "needyactivationtime": if (match.Groups["Value"].Success) { mission.GeneratorSetting.TimeBeforeNeedyActivation = int.Parse(match.Groups["Value"].Value); } break; case "widgets": if (match.Groups["Value"].Success) { mission.GeneratorSetting.OptionalWidgetCount = int.Parse(match.Groups["Value"].Value); } break; case "nopacing": mission.PacingEventsEnabled = false; break; case "frontonly": mission.GeneratorSetting.FrontFaceOnly = true; break; } } else if (match.Groups["ID"].Success) { KMComponentPool 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) { messages.Add("Invalid module pool count"); } bool allSolvable = true; string list = match.Groups["ID"].Value.Replace("\"", "").Trim(); switch (list) { case "ALL_SOLVABLE": anySolvableModules = true; 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": anySolvableModules = true; pool.AllowedSources = KMComponentPool.ComponentSource.Base; pool.SpecialComponentType = KMComponentPool.SpecialComponentTypeEnum.ALL_SOLVABLE; break; case "ALL_MODS": anySolvableModules = true; 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; default: foreach (string id in list.Split(',', '+').Select(s => s.Trim())) { switch (id) { 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": allSolvable = false; pool.ComponentTypes.Add(KMComponentPool.ComponentTypeEnum.NeedyCapacitor); break; case "NeedyVentGas": allSolvable = false; pool.ComponentTypes.Add(KMComponentPool.ComponentTypeEnum.NeedyVentGas); break; case "NeedyKnob": allSolvable = false; pool.ComponentTypes.Add(KMComponentPool.ComponentTypeEnum.NeedyKnob); break; default: if (!((IEnumerable <string>)DynamicMissionGenerator.ModSelectorApi["AllSolvableModules"]).Contains(id) && !((IEnumerable <string>)DynamicMissionGenerator.ModSelectorApi["AllNeedyModules"]).Contains(id)) { messages.Add($"'{id}' is an unknown module ID."); } else if (((IEnumerable <string>)DynamicMissionGenerator.ModSelectorApi["DisabledSolvableModules"]).Contains(id) || ((IEnumerable <string>)DynamicMissionGenerator.ModSelectorApi["DisabledNeedyModules"]).Contains(id)) { messages.Add($"'{id}' is disabled."); } else { if (((IEnumerable <string>)DynamicMissionGenerator.ModSelectorApi["AllNeedyModules"]).Contains(id)) { allSolvable = false; } pool.ModTypes.Add(id); } break; } } break; } if (allSolvable) { anySolvableModules = true; } if (pool.ModTypes.Count == 0) { pool.ModTypes = null; } if (pool.ComponentTypes.Count == 0) { pool.ComponentTypes = null; } pools.Add(pool); } } if (!anySolvableModules) { messages.Add("No regular modules"); } mission.GeneratorSetting.ComponentPools = pools; if (mission.GeneratorSetting.GetComponentCount() > GetMaxModules()) { messages.Add($"Too many modules for any available bomb casing ({mission.GeneratorSetting.GetComponentCount()} specified; {GetMaxModules()} possible)."); } if (messages.Count > 0) { Destroy(mission); mission = null; return(false); } messages = null; mission.DisplayName = "Custom Freeplay"; if (!timeSpecified) { mission.GeneratorSetting.TimeLimit = mission.GeneratorSetting.GetComponentCount() * 120; } if (!strikesSpecified) { mission.GeneratorSetting.NumStrikes = Math.Max(3, mission.GeneratorSetting.GetComponentCount() / 12); } return(true); }