Пример #1
0
    def _add_persist_option(self, check: QtWidgets.QCheckBox,
                            attribute_name: str):
        def persist(value: bool):
            with self._editor as editor:
                editor.set_configuration_field(attribute_name, value)

        signal_handling.on_checked(check, persist)
Пример #2
0
    def __init__(self, editor: PresetEditor):
        super().__init__(editor)
        self.setupUi(self)

        self.energy_tank_capacity_spin_box.valueChanged.connect(
            self._persist_tank_capacity)
        signal_handling.on_checked(self.immediate_energy_parts_check,
                                   self._persist_immediate_energy_parts)
Пример #3
0
    def _create_check_for_source_elevator(self, location: Teleporter):
        area = self.game_description.world_list.area_by_area_location(location.area_location)
        name = randovania.games.prime.echoes_teleporters.CUSTOM_NAMES_FOR_ELEVATORS.get(area.area_asset_id)
        if name is None:
            name = self.game_description.world_list.area_name(area)

        check = QtWidgets.QCheckBox(self.elevators_source_group)
        check.setText(name)
        check.area_location = location
        signal_handling.on_checked(check, functools.partial(self._on_elevator_source_check_changed, location))
        return check
Пример #4
0
    def __init__(self, editor: PresetEditor,
                 game_description: GameDescription) -> None:
        super().__init__(editor)
        self.setupUi(self)

        # Game-specific Settings
        game_settings = self.game_specific_widgets
        if game_settings is not None:
            for w in game_settings:
                self.game_specific_layout.addWidget(w)
        else:
            self.game_specific_group.setVisible(False)

        # Item Placement
        signal_handling.on_checked(self.multi_pickup_placement_check,
                                   self._persist_multi_pickup_placement)
        signal_handling.on_checked(self.multi_pickup_new_weighting_check,
                                   self._persist_multi_pickup_new_weighting)
        signal_handling.on_checked(self.check_major_minor,
                                   self._persist_major_minor)
        signal_handling.on_checked(self.local_first_progression_check,
                                   self._persist_local_first_progression)

        # Logic Settings
        self.dangerous_combo.setItemData(0,
                                         LayoutLogicalResourceAction.RANDOMLY)
        self.dangerous_combo.setItemData(
            1, LayoutLogicalResourceAction.LAST_RESORT)
        signal_handling.on_combo(self.dangerous_combo,
                                 self._on_dangerous_changed)

        signal_handling.on_checked(self.trick_level_minimal_logic_check,
                                   self._on_trick_level_minimal_logic_check)
        for w in [
                self.trick_level_minimal_logic_check,
                self.trick_level_minimal_logic_label, self.minimal_logic_line
        ]:
            w.setVisible(game_description.minimal_logic is not None)
        if game_description.minimal_logic is not None:
            self.trick_level_minimal_logic_label.setText(
                self.trick_level_minimal_logic_label.text().format(
                    game_specific_text=game_description.minimal_logic.
                    description))

        # Damage strictness
        self.damage_strictness_combo.setItemData(0,
                                                 LayoutDamageStrictness.STRICT)
        self.damage_strictness_combo.setItemData(1,
                                                 LayoutDamageStrictness.MEDIUM)
        self.damage_strictness_combo.setItemData(
            2, LayoutDamageStrictness.LENIENT)
        self.damage_strictness_combo.currentIndexChanged.connect(
            self._on_update_damage_strictness)
Пример #5
0
    def _create_check_for_source_elevator(self, location: NodeIdentifier):
        name = elevators.get_elevator_or_area_name(
            self.game_enum, self.game_description.world_list,
            location.area_location, True)

        check = QtWidgets.QCheckBox(self.elevators_source_group)
        check.setText(name)
        check.area_location = location
        signal_handling.on_checked(
            check,
            functools.partial(self._on_elevator_source_check_changed,
                              location))
        return check
Пример #6
0
    def __init__(self, editor: PresetEditor, game: GameDescription):
        super().__init__(editor)
        self.setupUi(self)
        self.game_description = game

        self.elevator_layout.setAlignment(QtCore.Qt.AlignTop)

        for value in enum_lib.iterate_enum(TeleporterShuffleMode):
            self.elevators_combo.addItem(value.long_name, value)
        self.elevators_combo.currentIndexChanged.connect(
            self._update_elevator_mode)
        signal_handling.on_checked(self.skip_final_bosses_check,
                                   self._update_require_final_bosses)
        signal_handling.on_checked(self.elevators_allow_unvisited_names_check,
                                   self._update_allow_unvisited_names)

        # Elevator Source
        self._create_source_elevators()

        # Elevator Target
        self._elevator_target_for_world, self._elevator_target_for_area = self.create_area_list_selection(
            self.elevators_target_group,
            self.elevators_target_layout,
            TeleporterTargetList.areas_list(self.game_enum),
            self._on_elevator_target_check_changed,
        )

        if self.game_enum != RandovaniaGame.METROID_PRIME_ECHOES:
            self.elevators_help_sound_bug_label.setVisible(False)
            self.elevators_allow_unvisited_names_check.setVisible(False)
            self.elevators_line_3.setVisible(False)
            self.elevators_help_list_label.setVisible(False)

        if self.game_enum == RandovaniaGame.METROID_PRIME:
            self.skip_final_bosses_check.setText(
                "Go directly to credits from Artifact Temple")
            self.skip_final_bosses_label.setText("""<html><head/><body>
            <p>Change the teleport in Artifact Temple to go directly to the credits, skipping the final bosses.</p>
            <p>This changes the requirements to <span style=" font-weight:600;">not need the final bosses</span>,
            turning certain items optional such as Plasma Beam.</p></body></html>
            """)
        elif self.game_enum != RandovaniaGame.METROID_PRIME_ECHOES:
            self.skip_final_bosses_check.setVisible(False)
            self.skip_final_bosses_label.setVisible(False)

        elif self.game_enum == RandovaniaGame.METROID_PRIME_CORRUPTION:
            self.elevators_description_label.setText(
                self.elevators_description_label.text().replace(
                    "elevator", "teleporter"))
Пример #7
0
    def _setup_general_widgets(self):
        # Item Data
        for i, value in enumerate(PickupModelStyle):
            self.pickup_model_combo.setItemData(i, value)
        for i, value in enumerate(PickupModelDataSource):
            self.pickup_data_source_combo.setItemData(i, value)

        # TODO: implement the LOCATION data source
        self.pickup_data_source_combo.removeItem(self.pickup_data_source_combo.findData(PickupModelDataSource.LOCATION))
        self.pickup_model_combo.currentIndexChanged.connect(
            self._persist_enum(self.pickup_model_combo, "pickup_model_style"))
        self.pickup_data_source_combo.currentIndexChanged.connect(
            self._persist_enum(self.pickup_data_source_combo, "pickup_model_data_source"))

        signal_handling.on_checked(self.multi_pickup_placement_check, self._persist_multi_pickup_placement)
Пример #8
0
    def __init__(self, editor: PresetEditor, game_enum: RandovaniaGame):
        super().__init__(editor)
        self.setupUi(self)
        self.game_enum = game_enum

        self.energy_tank_capacity_spin_box.valueChanged.connect(
            self._persist_tank_capacity)
        signal_handling.on_checked(self.dangerous_tank_check,
                                   self._persist_dangerous_tank)

        if self.game_enum == RandovaniaGame.METROID_PRIME_ECHOES:
            config_fields = {
                field.name: field
                for field in dataclasses.fields(EchoesConfiguration)
            }
            self.varia_suit_spin_box.setMinimum(
                config_fields["varia_suit_damage"].metadata["min"])
            self.varia_suit_spin_box.setMaximum(
                config_fields["varia_suit_damage"].metadata["max"])
            self.dark_suit_spin_box.setMinimum(
                config_fields["dark_suit_damage"].metadata["min"])
            self.dark_suit_spin_box.setMaximum(
                config_fields["dark_suit_damage"].metadata["max"])

            signal_handling.on_checked(self.safe_zone_logic_heal_check,
                                       self._persist_safe_zone_logic_heal)
            self.safe_zone_regen_spin.valueChanged.connect(
                self._persist_safe_zone_regen)
            self.varia_suit_spin_box.valueChanged.connect(
                self._persist_float("varia_suit_damage"))
            self.dark_suit_spin_box.valueChanged.connect(
                self._persist_float("dark_suit_damage"))
        else:
            self.dark_aether_box.setVisible(False)
            self.safe_zone_box.setVisible(False)
            self.dangerous_tank_check.setVisible(False)

        if self.game_enum == RandovaniaGame.METROID_PRIME:
            config_fields = {
                field.name: field
                for field in dataclasses.fields(PrimeConfiguration)
            }
            self.heated_damage_spin.setMinimum(
                config_fields["heat_damage"].metadata["min"])
            self.heated_damage_spin.setMaximum(
                config_fields["heat_damage"].metadata["max"])

            signal_handling.on_checked(self.progressive_damage_reduction_check,
                                       self._persist_progressive_damage)
            signal_handling.on_checked(
                self.heated_damage_varia_check,
                self._persist_heat_protection_only_varia)
            self.heated_damage_spin.valueChanged.connect(
                self._persist_float("heat_damage"))

        else:
            self.progressive_damage_reduction_check.setVisible(False)
            self.heated_damage_box.setVisible(False)
Пример #9
0
    def setup_damage_elements(self):
        self.damage_strictness_combo.setItemData(0, LayoutDamageStrictness.STRICT)
        self.damage_strictness_combo.setItemData(1, LayoutDamageStrictness.MEDIUM)
        self.damage_strictness_combo.setItemData(2, LayoutDamageStrictness.LENIENT)

        self.damage_strictness_combo.options_field_name = "layout_configuration_damage_strictness"
        self.damage_strictness_combo.currentIndexChanged.connect(functools.partial(_update_options_by_value,
                                                                                   self._editor,
                                                                                   self.damage_strictness_combo))

        def _persist_float(attribute_name: str):
            def persist(value: float):
                with self._editor as options:
                    options.set_configuration_field(attribute_name, value)

            return persist

        self.energy_tank_capacity_spin_box.valueChanged.connect(self._persist_tank_capacity)
        signal_handling.on_checked(self.dangerous_tank_check, self._persist_dangerous_tank)

        if self.game_enum == RandovaniaGame.PRIME2:
            config_fields = {
                field.name: field
                for field in dataclasses.fields(EchoesConfiguration)
            }
            self.varia_suit_spin_box.setMinimum(config_fields["varia_suit_damage"].metadata["min"])
            self.varia_suit_spin_box.setMaximum(config_fields["varia_suit_damage"].metadata["max"])
            self.dark_suit_spin_box.setMinimum(config_fields["dark_suit_damage"].metadata["min"])
            self.dark_suit_spin_box.setMaximum(config_fields["dark_suit_damage"].metadata["max"])

            signal_handling.on_checked(self.safe_zone_logic_heal_check, self._persist_safe_zone_logic_heal)
            self.safe_zone_regen_spin.valueChanged.connect(self._persist_safe_zone_regen)
            self.varia_suit_spin_box.valueChanged.connect(_persist_float("varia_suit_damage"))
            self.dark_suit_spin_box.valueChanged.connect(_persist_float("dark_suit_damage"))
        else:
            self.dark_aether_box.setVisible(False)
            self.safe_zone_box.setVisible(False)

        if self.game_enum == RandovaniaGame.PRIME1:
            config_fields = {
                field.name: field
                for field in dataclasses.fields(PrimeConfiguration)
            }
            self.heated_damage_spin.setMinimum(config_fields["heat_damage"].metadata["min"])
            self.heated_damage_spin.setMaximum(config_fields["heat_damage"].metadata["max"])

            signal_handling.on_checked(self.progressive_damage_reduction_check, self._persist_progressive_damage)
            signal_handling.on_checked(self.heated_damage_varia_check, self._persist_heat_protection_only_varia)
            self.heated_damage_spin.valueChanged.connect(_persist_float("heat_damage"))

        else:
            self.progressive_damage_reduction_check.setVisible(False)
            self.heated_damage_box.setVisible(False)
Пример #10
0
        def add_group(name: str, desc: str, weaknesses: dict[DockWeakness,
                                                             bool]):
            group = QtWidgets.QGroupBox()
            group.setObjectName(f"{name}_group {dock_type.short_name}")
            group.setTitle(desc)
            layout = QtWidgets.QVBoxLayout()
            group.setLayout(layout)

            for weakness, enabled in weaknesses.items():
                check = QtWidgets.QCheckBox()
                check.setObjectName(
                    f"{name}_check {dock_type.short_name} {weakness.name}")
                check.setText(weakness.long_name)
                check.setEnabled(enabled)
                signal_handling.on_checked(
                    check,
                    self._persist_weakness_setting(name, dock_type, weakness))
                layout.addWidget(check)
                self.type_checks[dock_type][weakness][name] = check

            type_layout.addWidget(group)
Пример #11
0
    def setup_elevator_elements(self):
        for value in iterate_enum(TeleporterShuffleMode):
            self.elevators_combo.addItem(value.long_name, value)
        self.elevators_combo.currentIndexChanged.connect(self._update_elevator_mode)
        signal_handling.on_checked(self.skip_final_bosses_check, self._update_require_final_bosses)
        signal_handling.on_checked(self.elevators_allow_unvisited_names_check, self._update_allow_unvisited_names)

        # Elevator Source
        self._create_source_elevators()

        # Elevator Target
        self._elevator_target_for_world, self._elevator_target_for_area = self._create_area_list_selection(
            self.elevators_target_group,
            self.elevators_target_layout,
            TeleporterTargetList.areas_list(self.game_enum),
            self._on_elevator_target_check_changed,
        )

        if self.game_enum == RandovaniaGame.PRIME3:
            self.patches_tab_widget.setTabText(self.patches_tab_widget.indexOf(self.elevator_tab),
                                               "Teleporters")
            self.elevators_description_label.setText(
                self.elevators_description_label.text().replace("elevator", "teleporter")
            )
Пример #12
0
    def __init__(self, editor: PresetEditor):
        super().__init__(editor)
        self.setupUi(self)

        self.description_label.setText(self.description_label.text().replace("color:#0000ff;", ""))

        # Signals
        self.cutscene_combo.setItemData(0, LayoutCutsceneMode.ORIGINAL)
        self.cutscene_combo.setItemData(1, LayoutCutsceneMode.COMPETITIVE)
        self.cutscene_combo.setItemData(2, LayoutCutsceneMode.MINOR)
        self.cutscene_combo.setItemData(3, LayoutCutsceneMode.MAJOR)
        signal_handling.on_combo(self.cutscene_combo, self._on_cutscene_changed)
        self.room_rando_combo.setItemData(0, RoomRandoMode.NONE)
        self.room_rando_combo.setItemData(1, RoomRandoMode.ONE_WAY)
        self.room_rando_combo.setItemData(2, RoomRandoMode.TWO_WAY)
        signal_handling.on_combo(self.room_rando_combo, self._on_room_rando_changed)
        for f in _FIELDS:
            self._add_persist_option(getattr(self, f"{f}_check"), f)

        signal_handling.on_checked(self.small_samus_check, self._on_small_samus_changed)
        signal_handling.on_checked(self.large_samus_check, self._on_large_samus_changed)

        self.superheated_slider.valueChanged.connect(self._on_slider_changed)
        self.submerged_slider.valueChanged.connect(self._on_slider_changed)
    def connect_signals(self):
        super().connect_signals()

        self.music_type_combo.currentIndexChanged.connect(self._on_music_type_changed)
        self.mychar_left_button.clicked.connect(self._mychar_left)
        self.mychar_right_button.clicked.connect(self._mychar_right)

        signal_handling.on_checked(self.song_cs_check, self._cs_songs)
        signal_handling.on_checked(self.song_beta_check, self._beta_songs)
        signal_handling.on_checked(self.song_kero_check, self._kero_songs)
Пример #14
0
    def __init__(self, parent: QtWidgets.QWidget, game: GameDescription):
        super().__init__(parent)
        set_default_window_icon(self)
        self.setWindowTitle("Layers")

        self.root_widget = QtWidgets.QScrollArea()
        self.root_layout = QtWidgets.QVBoxLayout(self.root_widget)
        self.root_widget.setWidgetResizable(True)
        self.setWidget(self.root_widget)

        self.contents_widget = QtWidgets.QWidget()
        self.contents_layout = QtWidgets.QVBoxLayout(self.contents_widget)
        self.root_widget.setWidget(self.contents_widget)

        self.title_label = QtWidgets.QLabel(self.contents_widget)
        self.title_label.setText("Select visible layers")
        self.contents_layout.addWidget(self.title_label)

        self.layer_checks = []
        for layer in game.layers:
            self.layer_checks.append(
                layer_check := QtWidgets.QCheckBox(self.contents_widget))
            layer_check.setText(layer)
            layer_check.setChecked(True)
            signal_handling.on_checked(layer_check,
                                       lambda it: self._notify_change())
            self.contents_layout.addWidget(layer_check)

        self.add_layer_button = QtWidgets.QPushButton(self.contents_widget)
        self.add_layer_button.setText("Add new layer")
        self.add_layer_button.setEnabled(False)
        self.add_layer_button.setToolTip("Not implemented")
        self.contents_layout.addWidget(self.add_layer_button)

        self.tricks_box = QtWidgets.QGroupBox(self.contents_widget)
        self.tricks_box.setTitle("Simplify connections with:")
        self.contents_layout.addWidget(self.tricks_box)
        self.tricks_layout = QtWidgets.QVBoxLayout(self.tricks_box)

        self.tricks = {}
        for trick in sorted(game.resource_database.trick,
                            key=lambda it: it.long_name):
            trick_layout = QtWidgets.QHBoxLayout()
            self.tricks_layout.addLayout(trick_layout)

            trick_check = QtWidgets.QCheckBox(self.tricks_box)
            trick_check.setText(trick.long_name)
            trick_layout.addWidget(trick_check)

            trick_combo = ScrollProtectedComboBox(self.tricks_box)
            trick_layout.addWidget(trick_combo)
            for trick_level in enum_lib.iterate_enum(LayoutTrickLevel):
                trick_combo.addItem(trick_level.long_name,
                                    userData=trick_level.as_number)
            signal_handling.on_combo(trick_combo,
                                     lambda it: self._notify_change())
            trick_combo.setEnabled(False)

            signal_handling.on_checked(trick_check, trick_combo.setEnabled)
            signal_handling.on_checked(trick_check,
                                       lambda it: self._notify_change())

            self.tricks[(trick, trick_check)] = trick_combo

        self.load_preset_button = QtWidgets.QPushButton(self.contents_widget)
        self.load_preset_button.setText("Configure with preset")
        self.load_preset_button.clicked.connect(self._on_load_preset_slot)
        self.contents_layout.addWidget(self.load_preset_button)

        self.vertical_spacer = QtWidgets.QSpacerItem(
            20, 30, QtWidgets.QSizePolicy.Minimum,
            QtWidgets.QSizePolicy.Expanding)
        self.contents_layout.addItem(self.vertical_spacer)
Пример #15
0
    def __init__(self, editor: PresetEditor, game_description: GameDescription,
                 window_manager: WindowManager):
        super().__init__(editor)
        self.setupUi(self)

        self.game_description = game_description
        self._window_manager = window_manager

        self.trick_level_layout.setAlignment(QtCore.Qt.AlignTop)
        signal_handling.on_checked(self.underwater_abuse_check,
                                   self._on_underwater_abuse_check)
        self.underwater_abuse_label.linkActivated.connect(
            self._on_click_link_underwater_details)

        self.trick_difficulties_layout = QtWidgets.QGridLayout()
        self._slider_for_trick = {}

        tricks_in_use = trick_lib.used_tricks(self.game_description)
        size_policy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed,
                                            QtWidgets.QSizePolicy.Preferred)

        self.trick_level_line_1.setVisible(
            self.game_enum != RandovaniaGame.METROID_PRIME_CORRUPTION)
        self.underwater_abuse_label.setText(
            self.underwater_abuse_label.text().replace("color:#0000ff;", ""))

        if self.game_enum != RandovaniaGame.METROID_PRIME:
            for w in [
                    self.underwater_abuse_check, self.underwater_abuse_label
            ]:
                w.setVisible(False)

        self._create_difficulty_details_row()

        row = 2
        for trick in sorted(self.game_description.resource_database.trick,
                            key=lambda _trick: _trick.long_name):
            if trick not in tricks_in_use:
                continue

            if row > 1:
                self.trick_difficulties_layout.addItem(
                    QtWidgets.QSpacerItem(20, 40,
                                          QtWidgets.QSizePolicy.Minimum,
                                          QtWidgets.QSizePolicy.Expanding))

            trick_label = QtWidgets.QLabel(self.trick_level_scroll_contents)
            trick_label.setSizePolicy(size_policy)
            trick_label.setWordWrap(True)
            trick_label.setFixedWidth(100)
            trick_label.setText(trick.long_name)
            self.trick_difficulties_layout.addWidget(trick_label, row, 1, 1, 1)

            slider_layout = QtWidgets.QGridLayout()
            slider_layout.setHorizontalSpacing(0)
            for i in range(12):
                slider_layout.setColumnStretch(i, 1)

            horizontal_slider = QtWidgets.QSlider(
                self.trick_level_scroll_contents)
            horizontal_slider.setMaximum(5)
            horizontal_slider.setPageStep(2)
            horizontal_slider.setOrientation(QtCore.Qt.Horizontal)
            horizontal_slider.setTickPosition(QtWidgets.QSlider.TicksBelow)
            horizontal_slider.setEnabled(False)
            horizontal_slider.valueChanged.connect(
                functools.partial(self._on_slide_trick_slider, trick))
            self._slider_for_trick[trick] = horizontal_slider
            slider_layout.addWidget(horizontal_slider, 0, 1, 1, 10)

            used_difficulties = trick_lib.difficulties_for_trick(
                self.game_description, trick)
            for i, trick_level in enumerate(
                    enum_lib.iterate_enum(LayoutTrickLevel)):
                if trick_level == LayoutTrickLevel.DISABLED or trick_level in used_difficulties:
                    difficulty_label = QtWidgets.QLabel(
                        self.trick_level_scroll_contents)
                    difficulty_label.setAlignment(QtCore.Qt.AlignHCenter)
                    difficulty_label.setText(trick_level.long_name)

                    slider_layout.addWidget(difficulty_label, 1, 2 * i, 1, 2)

            self.trick_difficulties_layout.addLayout(slider_layout, row, 2, 1,
                                                     1)

            if self._window_manager is not None:
                tool_button = QtWidgets.QToolButton(
                    self.trick_level_scroll_contents)
                tool_button.setText("?")
                tool_button.clicked.connect(
                    functools.partial(self._open_trick_details_popup, trick))
                self.trick_difficulties_layout.addWidget(
                    tool_button, row, 3, 1, 1)

            row += 1

        self.trick_level_layout.addLayout(self.trick_difficulties_layout)