protected void DrawSectionMissionEntry(Rect rect, int index, bool isActive, bool isFocused)
        {
            var missionIDProperty = List.serializedProperty.GetArrayElementAtIndex(index);

            KMMission mission = KMMissionTableOfContentsEditor.GetMission(missionIDProperty.stringValue);

            string sectionLabel = String.Format("{0}.{1}",
                                                sectionNum,
                                                index + 1);

            EditorGUI.PrefixLabel(new Rect(rect.x, rect.y, 30, EditorGUIUtility.singleLineHeight), new GUIContent(sectionLabel));
            EditorGUI.LabelField(
                new Rect(rect.x + 30, rect.y, 200, EditorGUIUtility.singleLineHeight),
                missionIDProperty.stringValue);

            if (!IsValidMission(missionIDProperty.stringValue))
            {
                EditorGUI.HelpBox(new Rect(rect.x + 30 + 200, rect.y, 200, EditorGUIUtility.singleLineHeight), "Mission not found!", MessageType.Error);
            }
            else if (!IsMissionUnique(missionIDProperty.stringValue))
            {
                EditorGUI.HelpBox(new Rect(rect.x + 30 + 200, rect.y, 100, EditorGUIUtility.singleLineHeight), "Duplicate!", MessageType.Warning);
            }
            else if (mission != null)
            {
                float x = 30 + 200;

                //Display Name
                EditorGUI.LabelField(new Rect(rect.x + x, rect.y, 300, EditorGUIUtility.singleLineHeight),
                                     mission.DisplayName);
                x += 300;
            }
        }
    /// <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;
        }
    }
Example #3
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);
    }
Example #4
0
 /// <summary>
 /// Launches a custom KMMission with the mission id set to 'custom'
 /// </summary>
 /// <param name="mission"></param>
 /// <param name="seed"></param>
 public void StartMission(KMMission mission, string seed)
 {
     if (OnStartCustomMission != null)
     {
         OnStartCustomMission(mission, seed);
     }
 }
 public void RunMission(KMMission mission)
 {
     if (CurrentState == KMGameInfo.State.Setup)
     {
         GetComponent <KMGameCommands>().StartMission(mission, "-1");
         OtherModes.RefreshModes(KMGameInfo.State.Transitioning);
     }
 }
    public static int CalculateTotalComponents(KMMission mission)
    {
        int numComponents = 0;

        if ((mission.GeneratorSetting != null) && (mission.GeneratorSetting.ComponentPools != null))
        {
            foreach (KMComponentPool pool in mission.GeneratorSetting.ComponentPools)
            {
                numComponents += pool.Count;
            }
        }

        return(numComponents);
    }
    public static void CreateNewMission()
    {
        if (!AssetDatabase.IsValidFolder("Assets/" + MISSION_FOLDER))
        {
            AssetDatabase.CreateFolder("Assets", MISSION_FOLDER);
        }

        KMMission mission = ScriptableObject.CreateInstance <KMMission>();
        string    path    = AssetDatabase.GenerateUniqueAssetPath("Assets/" + MISSION_FOLDER + "/mission.asset");

        AssetDatabase.CreateAsset(mission, path);
        AssetImporter.GetAtPath(path).assetBundleName = AssetBundler.BUNDLE_FILENAME;

        EditorGUIUtility.PingObject(mission);
    }
    /// <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>
    /// Search the AssetDatabase for all missions.
    /// </summary>
    /// <param name="missionID"></param>
    /// <returns></returns>
    public static List <KMMission> GetAllMissions()
    {
        string[]         guids    = AssetDatabase.FindAssets("t:KMMission");
        List <KMMission> missions = new List <KMMission>();

        foreach (string guid in guids)
        {
            KMMission mission = AssetDatabase.LoadAssetAtPath <KMMission>(AssetDatabase.GUIDToAssetPath(guid));

            if (mission != null)
            {
                missions.Add(mission);
            }
        }

        return(missions);
    }
        protected void OnSelect(ReorderableList list)
        {
            //Deselect all other section lists, because otherwise each section will have
            //an active selection
            int oldIndex = list.index;

            editor.ClearTableOfContentsSectionSelections();
            list.index = oldIndex;

            SerializedProperty missionIDProperty = list.serializedProperty.GetArrayElementAtIndex(list.index);

            KMMission mission = KMMissionTableOfContentsEditor.GetMission(missionIDProperty.stringValue);

            if (mission != null)
            {
                EditorGUIUtility.PingObject(mission);
            }
        }
Example #11
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);
    }
    /// <summary>
    /// Search the AssetDatabase for a mission with this ID and return it if it exists.
    /// </summary>
    /// <param name="missionID"></param>
    /// <returns></returns>
    public static KMMission GetMission(string missionID)
    {
        string[] guids = AssetDatabase.FindAssets(string.Format("t:KMMission {0}", missionID));

        if (guids.Length > 0)
        {
            foreach (string guid in guids)
            {
                KMMission mission = AssetDatabase.LoadAssetAtPath <KMMission>(AssetDatabase.GUIDToAssetPath(guid));
                if (mission.ID.Equals(missionID))
                {
                    return(mission);
                }
            }
        }

        return(null);
    }
    /// <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();
        }
    }
    protected bool IsMissionInTableOfContents(KMMission mission)
    {
        bool isInToC = false;

        KMMissionTableOfContents tableOfContents = (KMMissionTableOfContents)serializedObject.targetObject;

        foreach (var section in tableOfContents.Sections)
        {
            foreach (var missionID in section.MissionIDs)
            {
                if (missionID.Equals(mission.ID))
                {
                    isInToC = true;
                    break;
                }
            }
        }

        return(isInToC);
    }
    /// <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;
        }
    }
    /// <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);
        }
    }
Example #18
0
        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);
        }
Example #19
0
    public override void OnInspectorGUI()
    {
        if (target != null)
        {
            serializedObject.Update();

            //Basic mission meta-data
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PrefixLabel("ID");
            EditorGUILayout.SelectableLabel(serializedObject.targetObject.name);
            EditorGUILayout.EndHorizontal();

            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PrefixLabel("ID In-Game");
            EditorGUILayout.SelectableLabel(string.Format("mod_{0}_{1}", ModConfig.ID, serializedObject.targetObject.name));
            EditorGUILayout.EndHorizontal();

            SerializedProperty displayNameProperty = serializedObject.FindProperty("DisplayName");
            EditorGUILayout.PropertyField(displayNameProperty);
            displayNameProperty.stringValue = displayNameProperty.stringValue.Trim();
            EditorGUILayout.PropertyField(serializedObject.FindProperty("Description"));
            EditorGUILayout.PropertyField(serializedObject.FindProperty("PacingEventsEnabled"));

            SerializedProperty componentPools = serializedObject.FindProperty("GeneratorSetting.ComponentPools");

            if (factoryMode <= FactoryMode.FiniteSequenceGlobalTimeStrikes)
            {
                int newTotalBombCount = EditorGUILayout.IntField("Bomb Count", totalBombCount);
                setTotalBombCount(newTotalBombCount);
            }
            else
            {
                bool wasEnabled = GUI.enabled;
                GUI.enabled = false;
                EditorGUILayout.TextField("Bomb Count", "Infinite");
                GUI.enabled = wasEnabled;
            }

            FactoryMode newFactoryMode = (FactoryMode)EditorGUILayout.Popup("Factory Mode", (int)factoryMode, FactoryModeFriendlyNames);
            if (newFactoryMode != factoryMode)
            {
                if (newFactoryMode == FactoryMode.Static)
                {
                    if (factoryModeComponentPool != -1)
                    {
                        componentPools.DeleteArrayElementAtIndex(factoryModeComponentPool);
                        readCurrentMission();
                    }
                }
                else if (factoryModeComponentPool == -1)
                {
                    int index = addComponentPool(serializedObject.FindProperty("GeneratorSetting"));
                    SerializedProperty componentPool = componentPools.GetArrayElementAtIndex(index);
                    componentPool.FindPropertyRelative("Count").intValue     = (int)newFactoryMode;
                    componentPool.FindPropertyRelative("ModTypes").arraySize = 1;
                    componentPool.FindPropertyRelative("ModTypes").GetArrayElementAtIndex(0).stringValue = FACTORY_MODE_COMPONENT_POOL_ID;
                    factoryModeComponentPool = index;
                }
                else
                {
                    componentPools.GetArrayElementAtIndex(factoryModeComponentPool).FindPropertyRelative("Count").intValue = (int)newFactoryMode;
                }
                if (newFactoryMode >= FactoryMode.InfiniteSequence)
                {
                    setTotalBombCount(1);
                }
                factoryMode = newFactoryMode;
            }

            //Generator Settings
            EditorGUILayout.Separator();
            EditorGUILayout.LabelField("Generator Settings");

            List <string> unusedGeneratorSettings     = new List <string>();
            List <KeyValuePair <int, string> > tabMap = new List <KeyValuePair <int, string> >();
            tabMap.Add(new KeyValuePair <int, string>(0, "Bomb 0"));
            foreach (KeyValuePair <int, KeyValuePair <KMGeneratorSetting, int> > kv in multipleBombsGeneratorSettings)
            {
                if (kv.Key < totalBombCount || factoryMode >= FactoryMode.InfiniteSequence)
                {
                    tabMap.Add(new KeyValuePair <int, string>(kv.Key, "Bomb " + kv.Key));
                }
                else
                {
                    unusedGeneratorSettings.Add(kv.Key.ToString());
                }
            }
            tabMap.Sort((x, y) => x.Key.CompareTo(y.Key));

            if (unusedGeneratorSettings.Count > 0)
            {
                string unusedGeneratorSettingsWarningMessage = "The mission contains unused generator settings (for " + (unusedGeneratorSettings.Count > 1 ? "bombs " + string.Join(", ", unusedGeneratorSettings.ToArray()) : "bomb " + unusedGeneratorSettings[0]) + ").";
                EditorGUILayout.HelpBox(unusedGeneratorSettingsWarningMessage, MessageType.Warning);
            }

            EditorGUILayout.BeginVertical("box");
            int currentTab = activeGeneratorSetting != -1 ? tabMap.FindIndex((x) => x.Key == activeGeneratorSetting) : tabMap.Count;
            if (currentTab == -1)
            {
                activeGeneratorSetting = 0;
                currentTab             = 0;
            }
            List <string> tabs = new List <string>();
            tabs.Add(tabMap[0].Value);
            float minWidth = new GUIStyle("ButtonLeft").CalcSize(new GUIContent(tabMap[0].Value)).x;
            for (int i = 1; i < tabMap.Count; i++)
            {
                tabs.Add(tabMap[i].Value);
                float width = new GUIStyle("Button").CalcSize(new GUIContent(tabMap[i].Value)).x;
                if (width > minWidth)
                {
                    minWidth = width;
                }
            }
            tabs.Add("+");
            bool fits = Screen.width / tabs.Count > minWidth; //Screen.width is not an accurate measure of the available width but having the bar space always visible was too ugly
            if (!fits)
            {
                scrollPosition = EditorGUILayout.BeginScrollView(scrollPosition, GUILayout.Height(40));
            }
            int newTab = GUILayout.Toolbar(currentTab, tabs.ToArray());
            if (!fits)
            {
                EditorGUILayout.EndScrollView();
            }
            if (newTab != currentTab)
            {
                if (newTab == tabs.Count - 1)
                {
                    activeGeneratorSetting = -1;
                }
                else
                {
                    activeGeneratorSetting     = tabMap[newTab].Key;
                    activeComponentPool        = -1;
                    GUIUtility.keyboardControl = 0;
                }
            }

            if (activeGeneratorSetting == -1)
            {
                if (factoryMode <= FactoryMode.FiniteSequenceGlobalTimeStrikes)
                {
                    List <int> vaildBombs = new List <int>();
                    for (int i = 1; i < totalBombCount; i++)
                    {
                        if (!multipleBombsGeneratorSettings.ContainsKey(i))
                        {
                            vaildBombs.Add(i);
                        }
                    }
                    if (vaildBombs.Count == 0)
                    {
                        EditorGUILayout.HelpBox("All of the bombs have a Generator Setting.", MessageType.None);
                    }
                    else
                    {
                        if (!vaildBombs.Contains(currentAddGeneratorSettingIndex))
                        {
                            currentAddGeneratorSettingIndex = vaildBombs[0];
                        }
                        EditorGUILayout.BeginHorizontal();
                        EditorGUILayout.LabelField("Add Generator Setting for bomb");
                        currentAddGeneratorSettingIndex = vaildBombs[EditorGUILayout.Popup(vaildBombs.IndexOf(currentAddGeneratorSettingIndex), vaildBombs.Select((x) => x.ToString()).ToArray(), GUILayout.Width(60))];
                        EditorGUILayout.EndHorizontal();
                    }
                    bool wasEnabled = GUI.enabled;
                    GUI.enabled = vaildBombs.Count != 0;
                    if (GUILayout.Button("Add Generator Setting"))
                    {
                        addGeneratorSetting(currentAddGeneratorSettingIndex);
                    }
                    GUI.enabled = wasEnabled;
                }
                else
                {
                    EditorGUILayout.BeginHorizontal();
                    EditorGUILayout.LabelField("Add Generator Setting for bomb");
                    currentAddGeneratorSettingIndex = EditorGUILayout.IntField(currentAddGeneratorSettingIndex, GUILayout.Width(60));
                    EditorGUILayout.EndHorizontal();
                    bool isVaildBomb = currentAddGeneratorSettingIndex != 0 && !multipleBombsGeneratorSettings.ContainsKey(currentAddGeneratorSettingIndex);
                    if (!isVaildBomb)
                    {
                        EditorGUILayout.HelpBox("Bomb " + currentAddGeneratorSettingIndex + " already has a Generator Setting.", MessageType.None);
                    }
                    bool wasEnabled = GUI.enabled;
                    GUI.enabled = isVaildBomb;
                    if (GUILayout.Button("Add Generator Setting"))
                    {
                        addGeneratorSetting(currentAddGeneratorSettingIndex);
                    }
                    GUI.enabled = wasEnabled;
                }
            }
            else if (activeGeneratorSetting == 0)
            {
                bool wasEnabled = GUI.enabled;
                GUI.enabled = false;
                EditorGUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                GUILayout.Button("Delete");
                EditorGUILayout.EndHorizontal();
                GUI.enabled = wasEnabled;
                drawGeneratorSetting(serializedObject.FindProperty("GeneratorSetting"), true);
            }
            else
            {
                EditorGUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                bool delete = GUILayout.Button("Delete");
                EditorGUILayout.EndHorizontal();
                if (delete)
                {
                    removeGeneratorSetting(activeGeneratorSetting);
                }
                else
                {
                    KeyValuePair <KMGeneratorSetting, int> activeKV = multipleBombsGeneratorSettings[activeGeneratorSetting];
                    KMMission dummyMission = CreateInstance <KMMission>();
                    dummyMission.GeneratorSetting = activeKV.Key;
                    SerializedObject dummyMissionObject = new SerializedObject(dummyMission);
                    drawGeneratorSetting(dummyMissionObject.FindProperty("GeneratorSetting"), false);
                    if (dummyMissionObject.ApplyModifiedProperties())
                    {
                        serializedObject.FindProperty("GeneratorSetting").FindPropertyRelative("ComponentPools").GetArrayElementAtIndex(activeKV.Value).FindPropertyRelative("ModTypes").GetArrayElementAtIndex(0).stringValue = "Multiple Bombs:" + activeGeneratorSetting + ":" + JsonConvert.SerializeObject(activeKV.Key);
                    }
                }
            }
            EditorGUILayout.EndVertical();
        }
        serializedObject.ApplyModifiedProperties();
    }
Example #20
0
    public static string GetDmgString(KMMission mission)
    {
        string result = "";

        // Mission doc comments
        result += string.Format("//// {0}\n{1}\n\n",
                                mission.DisplayName,
                                mission.Description.Trim().Split('\n').Select(line => "/// " + line.Trim())
                                .Join("\n"));

        // No pacing events
        if (!mission.PacingEventsEnabled)
        {
            result += "nopacing\n";
        }

        // Bomb settings
        result += GetBombSettingsString(mission.GeneratorSetting) + "\n";

        // Pools
        string pools = "";
        List <KMGeneratorSetting> otherBombs = new List <KMGeneratorSetting>();

        mission.GeneratorSetting.ComponentPools.ForEach(pool =>
        {
            // Factory mode
            if (pool.ModTypes.Contains("Factory Mode"))
            {
                string factoryMode;
                if (pool.Count < 0 || pool.Count >= FactoryModes.Length)
                {
                    Debug.LogError("Invalid factory mode");
                    return;
                }

                factoryMode = FactoryModes[pool.Count];

                result += string.Format("factory:{0}\n", factoryMode);
            }
            // Multiple Bombs bomb count
            else if (pool.ModTypes.Contains("Multiple Bombs"))
            {
                // ignore
            }
            // Multiple Bombs bomb JSON
            else if (pool.ModTypes.Count == 1 && pool.ModTypes[0].StartsWith("Multiple Bombs"))
            {
                otherBombs.Add(
                    JsonConvert.DeserializeObject <KMGeneratorSetting>(pool.ModTypes[0].Split(new[] { ':' }, 3)[2]));
            }
            // Normal pool
            else
            {
                pools += GetPoolDmgString(pool) + "\n";
            }
        });

        // Determine whether to output as Multiple Bombs or as a single bomb
        if (otherBombs.Count != 0)
        {
            // Create bomb sets
            var bombSets = new List <Pair <int, KMGeneratorSetting> >
            {
                new Pair <int, KMGeneratorSetting> {
                    First = 1, Second = mission.GeneratorSetting
                }
            };

            // Group equal bombs
            foreach (var bomb in otherBombs)
            {
                if (bomb.SameMission(bombSets.Last().Second))
                {
                    bombSets.Last().First++;
                }
                else
                {
                    bombSets.Add(new Pair <int, KMGeneratorSetting> {
                        First = 1, Second = bomb
                    });
                }
            }

            result = result.TrimEnd();

            // Output each bomb
            result = bombSets.Aggregate(result, (current, bomb) =>
                                        current + ("\n\n" + (bomb.First != 1 ? bomb.First + "*" : "")
                                                   + "(\n" + Indent((GetBombSettingsString(bomb.Second, mission.GeneratorSetting)
                                                                     + "\n\n" + bomb.Second.ComponentPools.FilterPools()
                                                                     .Select(GetPoolDmgString).Join("\n")).Trim()) + "\n)"));
        }
        else
        {
            result += "\n" + pools.TrimEnd();
        }

        return(result);
    }