示例#1
0
        static int ResetRuleNav(int selectedRule)
        {
            if (selectedRule != -1)
            {
                InputSim.Press(Keys.Up, Wait.Short, selectedRule + 1);
            }

            return(-1);
        }
示例#2
0
        static int RuleNav(int selectedRule, int toRule)
        {
            if (selectedRule == -1)
            {
                InputSim.Press(Keys.Down, Wait.Long);
                InputSim.Press(Keys.Left, Wait.Long);
                selectedRule = 0;
            }

            if (selectedRule < toRule)
            {
                InputSim.Press(Keys.Down, Wait.Short, toRule - selectedRule);
            }
            else if (selectedRule > toRule)
            {
                InputSim.Press(Keys.Up, Wait.Short, selectedRule - toRule);
            }

            return(toRule);
        }
示例#3
0
        static void Script(string parseFile)
        {
            string text       = File.ReadAllText(parseFile);
            string scriptName = Path.GetFileName(parseFile);

            string compiledDirectory = Path.Combine(Constants.WorkingDirectory, "compiled");

            string compiledName = scriptName + Constants.COMPILED_FILETYPE;

            Rule[] generatedRules = null;
#if DEBUG == false
            try
            {
#endif
            generatedRules = Parser.ParseText(text);
            for (int i = 0; i < generatedRules.Length; i++)
            {
                Console.WriteLine($"Rule \"{generatedRules[i].Name}\":");
                generatedRules[i].Print();
            }
#if DEBUG == false
        }
        catch (SyntaxErrorException ex)
        {
            Log.Write(ex.Message, ConsoleColor.DarkRed);
            return;
        }
#endif
            Workshop workshop = new Workshop(generatedRules);

            Section();
            if (!Directory.Exists(compiledDirectory))
            {
                Directory.CreateDirectory(compiledDirectory);
            }
            Workshop prev = null;
            if (File.Exists(Path.Combine(compiledDirectory, compiledName)))
            {
                try
                {
                    Stream stream = File.Open(Path.Combine(compiledDirectory, compiledName), FileMode.Open);

                    var formatter = new BinaryFormatter();
                    prev = formatter.Deserialize(stream) as Workshop;

                    stream.Close();

                    Log.Write($"A previously compiled version of \"{scriptName}\" was found.");
                    Log.Write("Rules:");

                    int maxlength = prev.Rules.Length.ToString().Length;
                    for (int i = 0; i < prev.Rules.Length; i++)
                    {
                        Log.Colors(new ColorMod($"{i}{new string(' ', maxlength - i.ToString().Length)}", ConsoleColor.Gray), new ColorMod(": " + prev.Rules[i].Name));
                    }

                    Log.Write("Press [Y] to update the current workshop ruleset based off the changes since the last compilation. The workshop code must be the same as the rules above.");
                    Log.Write("Press [N] to regenerate the script. This requires the workshop's ruleset to be empty.");
                    if (!YorN())
                    {
                        prev = null;
                    }
                }
                catch (Exception ex)
                {
                    Log.Write($"Found previous compiled version of \"{scriptName}\", but failed to load it:", ConsoleColor.Black, ConsoleColor.Yellow);
                    Log.Write(ex.ToString());
                }
            }

            List <Rule> previousRules = prev?.Rules.ToList();

            List <int> deleteRules        = new List <int>();
            List <RuleAction> ruleActions = new List <RuleAction>();

            // Remove old rules
            if (previousRules != null)
            {
                for (int i = previousRules.Count - 1; i >= 0; i--)
                {
                    if (!generatedRules.Contains(previousRules[i]))
                    {
                        InputLog.Write($"Deleting rule \"{previousRules[i].Name}\"");
                        deleteRules.Add(i);
                        previousRules.RemoveAt(i);
                    }
                }
            }

            int numberOfRules = 0;

            for (int i = 0; i < generatedRules.Length; i++)
            {
                if (previousRules != null && generatedRules[i] == previousRules.ElementAtOrDefault(i))
                {
                    return;
                }

                var previousIndex = previousRules?.IndexOf(generatedRules[i]) ?? -1;

                if (previousIndex == -1)
                {
                    // Create new rule

                    InputLog.Write($"Creating rule \"{generatedRules[i].Name}\"");
                    ruleActions.Add(new RuleAction(generatedRules[i], i, true));
                }
                else if (previousIndex != i)
                {
                    // Move existing rule
                    InputLog.Write($"Moving rule \"{generatedRules[i].Name}\" from #{previousIndex} to #{i}.");
                    ruleActions.Add(new RuleAction(generatedRules[i], previousIndex, i));
                    numberOfRules++;
                }
                else
                {
                    InputLog.Write($"Doing nothing to rule \"{generatedRules[i].Name}\"");
                    ruleActions.Add(new RuleAction(generatedRules[i], i, false));
                    numberOfRules++;
                }
            }

            Log.Write("To setup the input for the generation, leave then re-enter the Settings/Workshop menu in Overwatch.", ConsoleColor.Black, ConsoleColor.Cyan);
            if (prev == null)
            {
                Log.Write("No previous workshop state loaded, make sure that there are no rules in the workshop.");
            }
            Log.Write("It is recommended to save a backup preset before starting the input.", ConsoleColor.Black, ConsoleColor.Yellow);
            Log.Write("If input is incorrect or fails, increase the step wait times in the config.");
            Log.Write("During generation, you can press ctrl+c to cancel.");
            if (Config.StopInput)
            {
                Log.Write("The stopinput option in the config is set to true. During generation any user input sent to the Overwatch window will be ignored." +
                          " After generation if you can't interact with the Overwatch window, start the executable directly then type \"fixinput\".", ConsoleColor.Black, ConsoleColor.Gray);
            }
            Log.Write("Press Enter to start input.");

            List <int> breakAt = null;

            var parameters = Regex.Matches(Console.ReadLine(), @"-([a-z]+)(=(.*))?");
            foreach (Match match in parameters)
            {
                string paramName = match.Groups[1].Value;
                string value     = match.Groups.Count == 4 ? match.Groups[3].Value : null;

                List <int> targetRules = null;

                if (value != null)
                {
                    targetRules = new List <int>();
                    string[] rulesToDo = value.Split(',');

                    foreach (string ruleToDo in rulesToDo)
                    {
                        if (int.TryParse(ruleToDo, out int set))
                        {
                            targetRules.Add(set);
                        }
                    }
                }

                else if (paramName == "break")
                {
                    breakAt = targetRules;
                }
                else
                {
                    Log.Write($"Unknown parameter {paramName}");
                }
            }

            while ((InputSim.OverwatchProcess = Process.GetProcessesByName("Overwatch").FirstOrDefault()) == null)
            {
                Log.Write("No Overwatch window found, press enter to recheck.");
                Console.ReadLine();
            }

            // Generate rules
            try
            {
                Console.CancelKeyPress += Console_CancelKeyPress;
                InputSim.CancelToken    = CancelSource.Token;

                if (Config.StopInput)
                {
                    InputSim.EnableWindow(false);
                }

                InputSim.Press(Keys.Tab, Wait.Short);

                // Delete rules
                int selectedRule = -1;
                foreach (var remove in deleteRules)
                {
                    selectedRule = RuleNav(selectedRule, remove);

                    InputSim.Press(Keys.Space, Wait.Short);
                    InputSim.Press(Keys.Tab, Wait.Short);
                    InputSim.Press(Keys.Right, Wait.Short);
                    InputSim.Press(Keys.Space, Wait.Long);

                    selectedRule = -1;
                }

                // Move and add rules.
                int index = 0;
                foreach (var action in ruleActions)
                {
                    if (breakAt != null && breakAt.Contains(index))
                    {
                        Debugger.Break();
                    }

                    if (action.RuleActionType == RuleActionType.Add)
                    {
                        selectedRule = ResetRuleNav(selectedRule);

                        action.Rule.Input(numberOfRules, action.RuleIndex);
                        numberOfRules++;
                        action.Exists = true;

                        var conflicting = ruleActions.Where(v => v != null &&
                                                            v.Exists &&
                                                            action.NewIndex <= v.RuleIndex &&
                                                            !ReferenceEquals(action, v));
                        foreach (var conflict in conflicting)
                        {
                            conflict.RuleIndex += 1;
                        }
                    }
                    if (action.RuleIndex != action.NewIndex)
                    {
                        selectedRule = RuleNav(selectedRule, action.RuleIndex);

                        InputSim.Press(Keys.Left, Wait.Short, 2);
                        if (index < action.RuleIndex)
                        {
                            InputSim.Press(Keys.Space, Wait.Short, selectedRule - action.NewIndex);
                        }

                        InputSim.Press(Keys.Right, Wait.Short, 2);

                        selectedRule = index;

                        var conflicting = ruleActions.Where(v => v != null &&
                                                            v.Exists &&
                                                            action.NewIndex <= v.RuleIndex && v.RuleIndex <= action.RuleIndex &&
                                                            !ReferenceEquals(action, v));
                        foreach (var conflict in conflicting)
                        {
                            conflict.RuleIndex += 1;
                        }

                        action.RuleIndex = action.NewIndex;
                    }

                    index++;
                }

                selectedRule = ResetRuleNav(selectedRule);

                InputSim.EnableWindow(true);

                Log.Write("Input completed.");
                Log.Write("Press [Y] to save the current workshop state. Only do this if the input was sucessful.");
                Log.Write("Press [N] to discard the saved workshop state. The next generation will requre the workshop state to be the same as before the last input.");
                if (YorN())
                {
                    Stream saveStream = File.Open(Path.Combine(compiledDirectory, compiledName), FileMode.Create);

                    var saveFormatter = new BinaryFormatter();
                    saveFormatter.Serialize(saveStream, workshop);

                    saveStream.Close();
                }
            }
            catch (OperationCanceledException)
            {
                Log.Write("Generation canceled.");
            }
            finally
            {
                InputSim.EnableWindow(true);
            }
        }