Exemple #1
0
    def ShowConfiguration(self) -> None:
        mod_button = OptionBoxButton("Mod", f"Currently: '{self.ModName}'")
        input_button = OptionBoxButton("Input", f"Currently: '{self.Input}'")
        custom_button = OptionBoxButton("- Custom Mod Name -")
        mod_buttons = [
            OptionBoxButton(mod.Name) for mod in GetOrderedModList()
        ] + [custom_button]

        main_box = OptionBox(
            Title="Configure SDK Mod Input",
            Caption="Select which part you want to configure.",
            Buttons=(mod_button, input_button))

        mod_box = OptionBox(Title="Select SDK Mod",
                            Caption="Select which mod to send inputs to.",
                            Buttons=mod_buttons)

        custom_box = TextInputBox("Custom Mod Name", self.ModName)

        input_box = TrainingBox("Set Input", "Press any key to set the input.")

        def OnMainPress(button: OptionBoxButton) -> None:
            if button == mod_button:
                mod_box.Show()
            elif button == input_button:
                input_box.Show()

        def OnModPick(button: OptionBoxButton) -> None:
            if button == custom_button:
                custom_box.Show()
            else:
                self.ModName = button.Name
                mod_button.Tip = f"Currently: '{self.ModName}'"
                main_box.Show(mod_button)

        def OnCustomSubmit(msg: str) -> None:
            if len(msg) != 0:
                self.ModName = msg
                mod_button.Tip = f"Currently: '{self.ModName}'"
                main_box.Show(mod_button)
            else:
                mod_box.Show(custom_button)

        def OnInput(key: str, event: int) -> None:
            if event != 1:
                return
            self.Input = key
            input_button.Tip = f"Currently: '{self.Input}''"
            if input_box.IsShowing():
                input_box.Hide()
            main_box.Show(input_button)

        main_box.OnPress = OnMainPress  # type: ignore
        main_box.OnCancel = self.OnFinishConfiguration  # type: ignore
        mod_box.OnPress = OnModPick  # type:ignore
        mod_box.OnCancel = lambda: mod_button.Show()  # type: ignore
        custom_box.OnSubmit = OnCustomSubmit  # type: ignore
        input_box.OnInput = OnInput  # type: ignore

        main_box.Show()
    def ShowConfiguration(self) -> None:
        custom_button = OptionBoxButton("- Custom Mod Name -")
        mod_buttons = [OptionBoxButton(mod.Name) for mod in GetOrderedModList()] + [custom_button]

        mod_box = OptionBox(
            Title="Select SDK Mod",
            Caption="Select the mod to enable.",
            Buttons=mod_buttons
        )

        custom_box = TextInputBox("Custom Mod Name", self.ModName)

        def OnModPick(button: OptionBoxButton) -> None:
            if button == custom_button:
                custom_box.Show()
            else:
                self.ModName = button.Name
                self.OnFinishConfiguration()

        def OnCustomSubmit(msg: str) -> None:
            if len(msg) != 0:
                self.ModName = msg
                self.OnFinishConfiguration()
            else:
                mod_box.Show(custom_button)

        mod_box.OnPress = OnModPick  # type:ignore
        mod_box.OnCancel = self.OnFinishConfiguration  # type: ignore
        custom_box.OnSubmit = OnCustomSubmit  # type: ignore

        mod_box.Show()
Exemple #3
0
    def ShowConfiguration(self) -> None:
        inputBox = TextInputBox("Configure Console Command", self.Command)

        def OnSubmit(msg: str) -> None:
            if len(msg) != 0:
                self.Command = msg
            self.OnFinishConfiguration()

        inputBox.OnSubmit = OnSubmit  # type: ignore
        inputBox.Show()
Exemple #4
0
    def ShowConfiguration(self) -> None:
        plus_one = OptionBoxButton("+1")
        plus_tenth = OptionBoxButton("+0.1")
        minus_tenth = OptionBoxButton("-0.1")
        minus_one = OptionBoxButton("-1")
        direct_edit = OptionBoxButton("Direct Edit")

        main_box = OptionBox(
            Title="Configure Delay",
            Caption=f"Current Delay: {self.Delay:.02f}s",
            Tooltip=OptionBox.CreateTooltipString(EscMessage="Back"),
            Buttons=(plus_one, plus_tenth, minus_tenth, minus_one,
                     direct_edit))
        direct_box = TextInputBox("Configure Delay", f"{self.Delay:.02f}")

        def OnMainBoxPress(button: OptionBoxButton) -> None:
            if button == direct_edit:
                direct_box.Show()
                return

            if button == plus_one:
                self.Delay += 1
            elif button == plus_tenth:
                self.Delay += 0.1
            elif button == minus_tenth:
                self.Delay = max(self.Delay - 0.1, 0)
            elif button == minus_one:
                self.Delay = max(self.Delay - 1, 0)
            direct_box.DefaultMessage = f"{self.Delay:.02f}"
            main_box.Caption = f"Current Delay: {self.Delay:.02f}s"
            main_box.Update()
            main_box.Show(button)

        main_box.OnPress = OnMainBoxPress  # type: ignore
        main_box.OnCancel = self.OnFinishConfiguration  # type: ignore

        def WriteFloatFilter(char: str, message: str, pos: int) -> bool:
            if char in "0123456789":
                return True
            if char == ".":
                return "." not in message
            return False

        def OnDirectBoxSubmit(msg: str) -> None:
            if msg != "":
                self.Delay = round(float(msg), 2)
                main_box.Caption = f"Current Delay: {self.Delay:.02f}s"
            main_box.Update()
            main_box.Show()

        direct_box.IsAllowedToWrite = WriteFloatFilter  # type: ignore
        direct_box.OnSubmit = OnDirectBoxSubmit  # type: ignore

        main_box.Show()
Exemple #5
0
    def __init__(self, Option: Options.Hidden, CheatList: List[ABCCheat]):
        self.Option = Option
        self.CheatList = CheatList

        # Move legacy presets into the option
        legacy_path = os.path.join(os.path.dirname(__file__), "Presets.json")
        try:
            loaded_data = []
            with open(legacy_path) as file:
                loaded_data = json.load(file)
            os.remove(legacy_path)
            self.Option.CurrentValue = loaded_data
        except (FileNotFoundError, json.JSONDecodeError):
            pass

        self.LoadPresets()

        self._ConfigureBox = OptionBox(
            Title="Configure Presets",
            Caption="Select the preset you want to configure",
            Tooltip=OptionBox.CreateTooltipString(EscMessage="Exit"),
            Buttons=(
                self._NewPreset,
                self._OpenPresetFile,
            ),
        )
        self._ConfigureBox.OnPress = self._SelectSpecificPreset  # type: ignore
        self._UpdateConfigureBox()

        self._CurrentPreset = None

        # These two dialog boxes are mostly the constant, we'll just update their title as needed
        self._PresetActionBox = OptionBox(
            Title="Selected 'PRESET NAME'",
            Caption="Select the action to perform on this preset",
            Tooltip=OptionBox.CreateTooltipString(EscMessage="Back"),
            Buttons=(self._EditPreset, self._RenamePreset, self._DeletePreset),
        )
        self._PresetActionBox.OnPress = self._SelectPresetAction  # type: ignore
        self._PresetActionBox.OnCancel = self.StartConfiguring  # type: ignore

        self._ConfirmDeleteBox = OptionBox(
            Title="Delete 'PRESET NAME'",
            Caption="Are you sure you want to delete this preset?",
            Tooltip=OptionBox.CreateTooltipString(EscMessage="Back"),
            Buttons=(self._No, self._Yes),
        )
        self._ConfirmDeleteBox.OnPress = self._OnConfirmDelete  # type: ignore
        self._ConfirmDeleteBox.OnCancel = lambda: self._OnConfirmDelete(
            None)  # type: ignore

        self._RenameBox = TextInputBox("Rename 'PRESET NAME'")
        self._RenameBox.OnSubmit = self._OnPresetRename  # type: ignore
Exemple #6
0
    def __init__(self, FileName: str, CheatList: List[ABCCheat]):
        self.FileName = FileName
        self.CheatList = CheatList

        self._ConfigureBox = OptionBox(
            Title="Configure Presets",
            Caption="Select the preset you want to configure",
            Tooltip=OptionBox.CreateTooltipString(EscMessage="Exit"),
            Buttons=(
                self._NewPreset,
                self._OpenPresetFile,
            ),
        )
        self._ConfigureBox.OnPress = self._SelectSpecificPreset  # type: ignore
        self.LoadPresets()
        self._UpdateConfigureBox()

        self._CurrentPreset = None

        # These two dialog boxes are mostly the constant, we'll just update their title as needed
        self._PresetActionBox = OptionBox(
            Title="Selected 'PRESET NAME'",
            Caption="Select the action to perform on this preset",
            Tooltip=OptionBox.CreateTooltipString(EscMessage="Back"),
            Buttons=(self._EditPreset, self._RenamePreset, self._DeletePreset),
        )
        self._PresetActionBox.OnPress = self._SelectPresetAction  # type: ignore
        self._PresetActionBox.OnCancel = self.StartConfiguring  # type: ignore

        self._ConfirmDeleteBox = OptionBox(
            Title="Delete 'PRESET NAME'",
            Caption="Are you sure you want to delete this preset?",
            Tooltip=OptionBox.CreateTooltipString(EscMessage="Back"),
            Buttons=(self._No, self._Yes),
        )
        self._ConfirmDeleteBox.OnPress = self._OnConfirmDelete  # type: ignore
        self._ConfirmDeleteBox.OnCancel = lambda: self._OnConfirmDelete(
            None)  # type: ignore

        self._RenameBox = TextInputBox("Rename 'PRESET NAME'")
        self._RenameBox.OnSubmit = self._OnPresetRename  # type: ignore
Exemple #7
0
    def Configure(self) -> None:
        toggleEnabledButton = OptionBoxButton("Toggle Enabled")
        editTriggerButton = OptionBoxButton(
            "Edit Trigger",
            "Edits what redemption title triggers this effect. Not case sensitive, but must match exactly otherwise."
        )
        extraConfigurationButton = OptionBoxButton(
            "Extra Options", "Adjust extra, effect specific options.")

        def GetCaptionStr(trig: CrowdControl._Trigger) -> str:
            caption = ""
            if trig.IsEnabled:
                caption = f"Enabled: '{trig.Trigger}'"
            else:
                caption = "Disabled"
            caption += "\n" + trig.Effect.Description
            return caption

        class _EffectButton(OptionBoxButton):
            TrigObj: CrowdControl._Trigger

            def __init__(self, trig: CrowdControl._Trigger) -> None:
                self.TrigObj = trig

            @property
            def Name(self) -> str:  # type: ignore
                return f"{self.TrigObj.Effect.Name}   -   {GetCaptionStr(self.TrigObj)}"

        effectButtons = [_EffectButton(trig) for trig in self.Triggers]
        currentButton = effectButtons[0]

        selectBox = OptionBox(Title="Configure Effects",
                              Caption="Select the effect to configure.",
                              Buttons=effectButtons,
                              Tooltip=OptionBox.CreateTooltipString() +
                              "     " + "[R] Reset All")
        editBox = OptionBox(Title="Configure <effect>",
                            Caption="Enabled\n<description>",
                            Buttons=(toggleEnabledButton, editTriggerButton,
                                     extraConfigurationButton))
        renameBox = TextInputBox(Title="Configure <effect>")

        def UpdateEditBox() -> None:
            editBox.Title = f"Configure {currentButton.TrigObj.Effect.Name}"
            if currentButton.TrigObj.IsEnabled:
                editBox.Caption = f"Enabled: '{currentButton.TrigObj.Trigger}'"
            else:
                editBox.Caption = "Disabled"
            editBox.Caption += "\n" + currentButton.TrigObj.Effect.Description

            if currentButton.TrigObj.Effect.HasConfigMenu:
                editBox.Buttons = [
                    toggleEnabledButton, editTriggerButton,
                    extraConfigurationButton
                ]
            else:
                editBox.Buttons = [toggleEnabledButton, editTriggerButton]

            editBox.Update()

        def OnSelect(button: _EffectButton) -> None:
            nonlocal currentButton
            currentButton = button
            UpdateEditBox()
            editBox.Show()

        def OnEdit(button: OptionBoxButton) -> None:
            if button == toggleEnabledButton:
                currentButton.TrigObj.IsEnabled = not currentButton.TrigObj.IsEnabled
                for option in currentButton.TrigObj.Effect.Options:
                    option.IsHidden = not currentButton.TrigObj.IsEnabled
                UpdateEditBox()
                editBox.Show()
            elif button == editTriggerButton:
                renameBox.Title = editBox.Title
                renameBox.DefaultMessage = currentButton.TrigObj.Trigger
                renameBox.Show()
            elif button == extraConfigurationButton:
                currentButton.TrigObj.Effect.FinishConfiguration = editBox.Show  # type: ignore
                currentButton.TrigObj.Effect.ShowConfiguration()

        def OnRename(msg: str) -> None:
            if len(msg) > 0:
                currentButton.TrigObj.Trigger = msg
            UpdateEditBox()
            editBox.Show()

        oldSelectInput = selectBox.OnInput

        def OnSelectInput(key: str, event: int) -> None:
            if key == "R" and event == 1:
                for trig in self.Triggers:
                    trig.IsEnabled = True
                    trig.Trigger = trig.Effect.Name
                    for option in trig.Effect.Options:
                        option.IsHidden = False
                UpdateEditBox()
                selectBox.Hide()
                selectBox.Show()
            else:
                oldSelectInput(key, event)

        selectBox.OnPress = OnSelect  # type: ignore
        selectBox.OnCancel = self.SaveTriggers  # type: ignore
        selectBox.OnInput = OnSelectInput  # type:ignore
        editBox.OnPress = OnEdit  # type: ignore
        editBox.OnCancel = lambda: selectBox.ShowButton(currentButton
                                                        )  # type: ignore
        renameBox.OnSubmit = OnRename  # type: ignore
        selectBox.Show()
Exemple #8
0
class PresetManager:
    Option: Options.Hidden
    PresetList: List[Preset]
    CheatList: List[ABCCheat]

    _NewPreset: ClassVar[OptionBoxButton] = OptionBoxButton(
        "Create New Preset")
    _OpenPresetFile: ClassVar[OptionBoxButton] = OptionBoxButton(
        "Open Settings File",
        ("Useful for reordering or sharing presets."
         " The game will have to be restarted for changes to apply."))
    _EditPreset: ClassVar[OptionBoxButton] = OptionBoxButton("Configure")
    _RenamePreset: ClassVar[OptionBoxButton] = OptionBoxButton("Rename")
    _DeletePreset: ClassVar[OptionBoxButton] = OptionBoxButton("Delete")
    _Yes: ClassVar[OptionBoxButton] = OptionBoxButton("Yes")
    _No: ClassVar[OptionBoxButton] = OptionBoxButton("No")

    _ConfigureBox: OptionBox
    _ButtonPresetMap: Dict[str, Preset]

    _CurrentPreset: Optional[Preset]
    _PresetActionBox: OptionBox
    _ConfirmDeleteBox: OptionBox

    _RenameBox: TextInputBox

    def __init__(self, Option: Options.Hidden, CheatList: List[ABCCheat]):
        self.Option = Option
        self.CheatList = CheatList

        # Move legacy presets into the option
        legacy_path = os.path.join(os.path.dirname(__file__), "Presets.json")
        try:
            loaded_data = []
            with open(legacy_path) as file:
                loaded_data = json.load(file)
            os.remove(legacy_path)
            self.Option.CurrentValue = loaded_data
        except (FileNotFoundError, json.JSONDecodeError):
            pass

        self.LoadPresets()

        self._ConfigureBox = OptionBox(
            Title="Configure Presets",
            Caption="Select the preset you want to configure",
            Tooltip=OptionBox.CreateTooltipString(EscMessage="Exit"),
            Buttons=(
                self._NewPreset,
                self._OpenPresetFile,
            ),
        )
        self._ConfigureBox.OnPress = self._SelectSpecificPreset  # type: ignore
        self._UpdateConfigureBox()

        self._CurrentPreset = None

        # These two dialog boxes are mostly the constant, we'll just update their title as needed
        self._PresetActionBox = OptionBox(
            Title="Selected 'PRESET NAME'",
            Caption="Select the action to perform on this preset",
            Tooltip=OptionBox.CreateTooltipString(EscMessage="Back"),
            Buttons=(self._EditPreset, self._RenamePreset, self._DeletePreset),
        )
        self._PresetActionBox.OnPress = self._SelectPresetAction  # type: ignore
        self._PresetActionBox.OnCancel = self.StartConfiguring  # type: ignore

        self._ConfirmDeleteBox = OptionBox(
            Title="Delete 'PRESET NAME'",
            Caption="Are you sure you want to delete this preset?",
            Tooltip=OptionBox.CreateTooltipString(EscMessage="Back"),
            Buttons=(self._No, self._Yes),
        )
        self._ConfirmDeleteBox.OnPress = self._OnConfirmDelete  # type: ignore
        self._ConfirmDeleteBox.OnCancel = lambda: self._OnConfirmDelete(
            None)  # type: ignore

        self._RenameBox = TextInputBox("Rename 'PRESET NAME'")
        self._RenameBox.OnSubmit = self._OnPresetRename  # type: ignore

    def LoadPresets(self) -> None:
        self.PresetList = []
        for idx, current_dict in enumerate(self.Option.CurrentValue):
            name: str = f"Preset {idx}"
            settings: Dict[str, str] = {}

            if "Name" in current_dict:
                name = html.escape(str(current_dict["Name"]))

            if "Settings" in current_dict and isinstance(
                    current_dict["Settings"], dict):
                settings = current_dict["Settings"]
                # Sanity-check the data
                for cheat in self.CheatList:
                    if cheat.Name in settings:
                        value = settings[cheat.Name]
                        # We don't really care what this value is for regular cheats, but better to
                        #  keep it consistent
                        if not isinstance(cheat, ABCCycleableCheat):
                            value = "Run"
                        settings[cheat.Name] = value

            current_preset = Preset(name, settings, self.CheatList)
            current_preset.OnFinishConfiguring = self._OnFinishConfiguringPreset  # type: ignore
            self.PresetList.append(current_preset)

        # If there are no valid presets then still add the first one
        if len(self.PresetList) == 0:
            new_preset = Preset("Preset 1", {}, self.CheatList)
            new_preset.OnFinishConfiguring = self._OnFinishConfiguringPreset  # type: ignore
            self.PresetList.append(new_preset)

    def SavePresets(self) -> None:
        data = []
        for preset in self.PresetList:
            data.append({
                "Name": html.unescape(preset.Name),
                "Settings": preset.GetSettings()
            })

        self.Option.CurrentValue = data
        self.SaveOptions()

    def StartConfiguring(self) -> None:
        self._UpdateConfigureBox()
        self._ConfigureBox.Show()

    # The next four functions should be overwritten by the main mod
    def AddKeybind(self, Name: str) -> None:
        raise NotImplementedError

    def RenameKeybind(self, OldName: str, NewName: str) -> None:
        raise NotImplementedError

    def RemoveKeybind(self, Name: str) -> None:
        raise NotImplementedError

    def SaveOptions(self) -> None:
        raise NotImplementedError

    def _OnFinishConfiguringPreset(self) -> None:
        self.SavePresets()
        self.StartConfiguring()

    def _UpdateConfigureBox(self) -> None:
        button_list = []
        self._ButtonPresetMap = {}
        for preset in self.PresetList:
            button = OptionBoxButton(html.unescape(preset.Name))
            button_list.append(button)
            self._ButtonPresetMap[button.Name] = preset

        button_list += [
            self._NewPreset,
            self._OpenPresetFile,
        ]

        self._ConfigureBox.Buttons = button_list
        self._ConfigureBox.Update()

    def _SelectSpecificPreset(self, button: OptionBoxButton) -> None:
        if button == self._NewPreset:
            # Get a new default name that's at least the size of the list + 1, or the largest
            #  existing default name + 1
            # This makes renaming or deleting cheats still add a somewhat logical name
            max_val = len(self.PresetList)
            for preset in self.PresetList:
                val: int
                try:
                    val = int(preset.Name.split(" ")[-1])
                except ValueError:
                    continue
                if val > max_val:
                    max_val = val
            name = f"Preset {max_val + 1}"

            new_preset = Preset(name, {}, self.CheatList)
            new_preset.OnFinishConfiguring = self._OnFinishConfiguringPreset  # type: ignore
            self.PresetList.append(new_preset)

            self.AddKeybind(name)

            self.SavePresets()
        elif button == self._OpenPresetFile:
            settings_path = os.path.join(os.path.dirname(__file__),
                                         "settings.json")
            os.startfile(settings_path)

        if button.Name in self._ButtonPresetMap:
            self._CurrentPreset = self._ButtonPresetMap[button.Name]
            self._PresetActionBox.Title = f"Selected '{self._CurrentPreset.Name}'"
            self._PresetActionBox.Update()
            self._PresetActionBox.Show()
            return

        self.StartConfiguring()

    def _SelectPresetAction(self, button: OptionBoxButton) -> None:
        if self._CurrentPreset is None:
            raise RuntimeError("Current Preset is None")
        if button == self._EditPreset:
            self._CurrentPreset.StartConfiguring()
            self._CurrentPreset = None
        elif button == self._RenamePreset:
            self._RenameBox.Title = f"Rename '{self._CurrentPreset.Name}'"
            self._RenameBox.DefaultMessage = self._CurrentPreset.Name
            self._RenameBox.Show()
        elif button == self._DeletePreset:
            self._ConfirmDeleteBox.Title = f"Delete '{self._CurrentPreset.Name}'"
            self._ConfirmDeleteBox.Update()
            self._ConfirmDeleteBox.Show()

    def _OnPresetRename(self, msg: str) -> None:
        if self._CurrentPreset is None:
            raise RuntimeError("Current Preset is None")

        if len(msg) > 0:
            self.RenameKeybind(self._CurrentPreset.Name, msg)

            self._ButtonPresetMap[msg] = self._ButtonPresetMap[
                self._CurrentPreset.Name]
            del self._ButtonPresetMap[self._CurrentPreset.Name]

            self._CurrentPreset.UpdateName(msg)
            self.SavePresets()
            self._UpdateConfigureBox()

        self._PresetActionBox.Title = f"Selected '{self._CurrentPreset.Name}'"
        self._PresetActionBox.Update()
        self._PresetActionBox.Show(self._RenamePreset)

    def _OnConfirmDelete(self, button: Optional[OptionBoxButton]) -> None:
        if self._CurrentPreset is None:
            raise RuntimeError("Current Preset is None")
        if button == self._Yes:
            self.PresetList.remove(self._CurrentPreset)
            self.RemoveKeybind(self._CurrentPreset.Name)
            self._CurrentPreset = None
            self.SavePresets()
            self.StartConfiguring()
        else:
            self._PresetActionBox.Show()