コード例 #1
0
    def pretty_description(self) -> str:
        if self.minimal_logic:
            return "Minimal Logic"

        count_at_difficulties = collections.defaultdict(list)
        for trick in _all_tricks(
                default_database.resource_database_for(self.game)):
            count_at_difficulties[self.level_for_trick(trick)].append(
                trick.long_name)

        if len(count_at_difficulties) == 1:
            for level in count_at_difficulties.keys():
                if level == LayoutTrickLevel.DISABLED:
                    return "All tricks disabled"
                return f"All tricks enabled at {level.long_name}"

        def tricks_at_level(tricks: List[str]) -> str:
            if len(tricks) != 1:
                return f"{len(tricks)}"
            else:
                return tricks[0]

        descriptions = [
            f"{tricks_at_level(count_at_difficulties[level])} at {level.long_name}"
            for level in iterate_enum(LayoutTrickLevel)
            if count_at_difficulties[level]
        ]
        return "Enabled tricks: {}".format(", ".join(descriptions))
コード例 #2
0
    def create_tracker(self):
        self.delete_tracker()
        game_enum = RandovaniaGame.PRIME2

        resource_database = default_database.resource_database_for(game_enum)
        with get_data_path().joinpath(f"gui_assets/tracker/{game_enum.value}.json").open("r") as tracker_details_file:
            tracker_details = json.load(tracker_details_file)

        for element in tracker_details["elements"]:
            text_template = ""

            if "image_path" in element:
                image_path = get_data_path().joinpath(element["image_path"])
                pixmap = QPixmap(str(image_path))

                label = ClickableLabel(self.inventory_group, paint_with_opacity(pixmap, 0.3),
                                       paint_with_opacity(pixmap, 1.0))
                label.set_checked(False)
                label.set_ignore_mouse_events(True)

            elif "label" in element:
                label = QLabel(self.inventory_group)
                label.setAlignment(Qt.AlignCenter)
                text_template = element["label"]

            else:
                raise ValueError(f"Invalid element: {element}")

            resources = [
                find_resource_info_with_long_name(resource_database.item, resource_name)
                for resource_name in element["resources"]
            ]
            self._tracker_elements.append(Element(label, resources, text_template))
            self.inventory_layout.addWidget(label, element["row"], element["column"])
コード例 #3
0
ファイル: ammo_state.py プロジェクト: randovania/randovania
    def bit_pack_unpack(cls, decoder: BitPackDecoder, metadata) -> "AmmoState":
        ammo: Ammo = metadata["ammo"]
        db = default_database.resource_database_for(ammo.game)

        # Ammo Count
        ammo_count = []
        for ammo_index in ammo.items:
            ammo_item = db.get_item(ammo_index)
            ammo_count.append(
                bitpacking.decode_int_with_limits(
                    decoder,
                    (ammo_item.max_capacity // 2, ammo_item.max_capacity + 1),
                ))

        # Pickup Count
        pickup_count = bitpacking.decode_big_int(decoder)

        # Require Major Item
        requires_major_item = True
        if ammo.unlocked_by is not None:
            requires_major_item = bitpacking.decode_bool(decoder)

        return cls(
            ammo_count=tuple(ammo_count),
            pickup_count=pickup_count,
            requires_major_item=requires_major_item,
        )
コード例 #4
0
    def bit_pack_unpack(cls, decoder: BitPackDecoder, item: MajorItem,
                        reference: "MajorItemState") -> "MajorItemState":
        db = default_database.resource_database_for(item.game)
        if item.progression:
            main_index = item.progression[0]
        else:
            main_index = item.ammo_index[0]
        main_item = db.get_item(main_index)

        # original location
        original = False
        if item.original_index is not None:
            original = bitpacking.decode_bool(decoder)

        # num shuffled
        shuffled = bitpacking.decode_int_with_limits(decoder,
                                                     DEFAULT_MAXIMUM_SHUFFLED)

        # starting item
        if main_item.max_capacity > 1:
            starting = bitpacking.decode_int_with_limits(
                decoder, (2, main_item.max_capacity + 1))
        else:
            starting = decoder.decode_single(main_item.max_capacity + 1)

        # priority
        priority = bitpacking.BitPackFloat.bit_pack_unpack(
            decoder, PRIORITY_LIMITS)

        # ammo index
        if item.ammo_index:
            custom_ammo = bitpacking.decode_bool(decoder)
            if custom_ammo:
                all_equal = len(
                    item.ammo_index) <= 1 or bitpacking.decode_bool(decoder)
                if all_equal:
                    ammo = decoder.decode_single(
                        db.get_item(item.ammo_index[0]).max_capacity + 1)
                    included_ammo = [ammo] * len(item.ammo_index)
                else:
                    included_ammo = [
                        decoder.decode_single(
                            db.get_item(item).max_capacity + 1)
                        for item in item.ammo_index
                    ]
            else:
                included_ammo = reference.included_ammo
        else:
            included_ammo = []

        return cls(
            include_copy_in_original_location=original,
            num_shuffled_pickups=shuffled,
            num_included_in_starting_items=starting,
            priority=priority,
            included_ammo=tuple(included_ammo),
        )
コード例 #5
0
ファイル: game_session.py プロジェクト: randovania/randovania
    def admin_session(user, session_id):
        session: GameSession = GameSession.get_by_id(session_id)

        rows = []
        presets = session.all_presets

        for player in session.players:
            player = typing.cast(GameSessionMembership, player)
            if player.is_observer:
                rows.append([
                    player.effective_name,
                    "Observer",
                    "",
                ])
            else:
                preset = presets[player.row]
                db = default_database.resource_database_for(preset.game)

                inventory = []
                if player.inventory is not None:
                    try:
                        parsed_inventory: list[dict] = BinaryInventory.parse(
                            player.inventory)
                    except construct.ConstructError:
                        # Handle old format in an adhoc way
                        # TODO 4.3: remove this code and purge all old inventory from the server db
                        items_by_id: dict[int, ItemResourceInfo] = {
                            item.extra["item_id"]: item
                            for item in db.item
                        }
                        parsed_inventory = [{
                            "name":
                            items_by_id[item["index"]].short_name,
                            **item,
                        } for item in OldBinaryInventory.parse(
                            player.inventory)]

                    for item in parsed_inventory:
                        if item["amount"] + item["capacity"] > 0:
                            inventory.append("{} x{}/{}".format(
                                db.get_item(item["name"]).long_name,
                                item["amount"], item["capacity"]))

                rows.append([
                    player.effective_name,
                    preset.name,
                    ", ".join(inventory),
                ])

        header = ["Name", "Preset", "Inventory"]

        return "<table border='1'><tr>{}</tr>{}</table>".format(
            "".join(f"<th>{h}</th>" for h in header),
            "".join("<tr>{}</tr>".format("".join(f"<td>{h}</td>" for h in r))
                    for r in rows),
        )
コード例 #6
0
def prime1_hint_text():
    db = default_database.resource_database_for(RandovaniaGame.METROID_PRIME)
    artifact = pickup_creator.create_artifact(0, 0, db)

    result = [(
        "Artifact",
        artifact.item_category,
        artifact.broad_category,
    )]
    return result
コード例 #7
0
def prime3_hint_text():
    db = default_database.resource_database_for(RandovaniaGame.METROID_PRIME_CORRUPTION)
    cell = pickup_creator.create_energy_cell(0, db)

    result = [(
        "Energy Cell",
        cell.item_category,
        cell.broad_category,
    )]
    return result
コード例 #8
0
    def create_tracker(self, game_enum: RandovaniaGame):
        effective_theme = self.theme
        if not path_for(game_enum, effective_theme).is_file():
            effective_theme = TrackerTheme.CLASSIC

        if (game_enum, effective_theme) == self._last_tracker_config:
            return
        self.delete_tracker()

        resource_database = default_database.resource_database_for(game_enum)

        with path_for(game_enum,
                      effective_theme).open("r") as tracker_details_file:
            tracker_details = json.load(tracker_details_file)

        for element in tracker_details["elements"]:
            text_template = ""

            if "image_path" in element:
                image_path = get_data_path().joinpath(element["image_path"])
                pixmap = QPixmap(str(image_path))

                label = ClickableLabel(self.inventory_group,
                                       paint_with_opacity(pixmap, 0.3),
                                       paint_with_opacity(pixmap, 1.0))
                label.set_checked(False)
                label.set_ignore_mouse_events(True)

            elif "label" in element:
                label = QLabel(self.inventory_group)
                label.setAlignment(Qt.AlignCenter)
                text_template = element["label"]

            else:
                raise ValueError(f"Invalid element: {element}")

            resources = [
                find_resource_info_with_long_name(resource_database.item,
                                                  resource_name)
                for resource_name in element["resources"]
            ]
            self._tracker_elements.append(
                Element(label, resources, text_template))
            self.inventory_layout.addWidget(label, element["row"],
                                            element["column"])

        self.inventory_spacer = QSpacerItem(5, 5, QSizePolicy.Expanding,
                                            QSizePolicy.Expanding)
        self.inventory_layout.addItem(self.inventory_spacer,
                                      self.inventory_layout.rowCount(),
                                      self.inventory_layout.columnCount())
        self._update_tracker_from_hook({})

        self._last_tracker_config = (game_enum, effective_theme)
コード例 #9
0
    async def refresh_received_pickups(self):
        self.logger.debug(f"start")
        async with self._pickups_lock:
            game, result = await self.network_client.game_session_request_pickups(
            )
            resource_database = default_database.resource_database_for(game)

            self.logger.info(f"received {len(result)} items")
            self._received_pickups = [(provider_name,
                                       _decode_pickup(data, resource_database))
                                      for provider_name, data in result]
コード例 #10
0
    async def _on_game_session_pickups_update_raw(self, data):
        game = RandovaniaGame(data["game"])
        resource_database = default_database.resource_database_for(game)

        await self.on_game_session_pickups_update(
            GameSessionPickups(
                game=game,
                pickups=tuple(
                    (item["provider_name"],
                     _decode_pickup(item["pickup"], resource_database))
                    for item in data["pickups"]),
            ))
コード例 #11
0
ファイル: ammo_state.py プロジェクト: randovania/randovania
    def bit_pack_encode(self, metadata) -> Iterator[Tuple[int, int]]:
        ammo: Ammo = metadata["ammo"]
        db = default_database.resource_database_for(ammo.game)

        for count, ammo_index in zip(self.ammo_count, ammo.items):
            ammo_item = db.get_item(ammo_index)
            yield from bitpacking.encode_int_with_limits(
                count,
                (ammo_item.max_capacity // 2, ammo_item.max_capacity + 1),
            )

        yield from bitpacking.encode_big_int(self.pickup_count)
        if ammo.unlocked_by is not None:
            yield from bitpacking.encode_bool(self.requires_major_item)
コード例 #12
0
    def check_consistency(self, item: MajorItem):
        db = default_database.resource_database_for(item.game)

        if self.num_shuffled_pickups < 0 or self.num_shuffled_pickups > DEFAULT_MAXIMUM_SHUFFLED[
                -1]:
            raise ValueError(
                f"Can only shuffle between 0 and {DEFAULT_MAXIMUM_SHUFFLED[-1]} copies,"
                f" got {self.num_shuffled_pickups}. ({item.name})")

        if item.must_be_starting:
            if not self.num_included_in_starting_items:
                raise ValueError(
                    f"Required items must be included in starting items. ({item.name})"
                )

        if self.num_included_in_starting_items > 0:
            if len(item.progression) > 1:
                raise ValueError(
                    f"Progressive items cannot be starting item. ({item.name})"
                )

            for progression in item.progression:
                if self.num_included_in_starting_items > db.get_item(
                        progression).max_capacity:
                    raise ValueError(
                        f"More starting copies than the item's max copy. ({item.name})"
                    )

        if self.include_copy_in_original_location and item.original_index is None:
            raise ValueError(f"Custom item cannot be vanilla. ({item.name})")

        if not (PRIORITY_LIMITS["min"] <= self.priority <=
                PRIORITY_LIMITS["max"]):
            raise ValueError(
                "Priority must be between {min} and {max}, got {priority}".
                format(
                    priority=self.priority,
                    **PRIORITY_LIMITS,
                ))

        if len(self.included_ammo) != len(item.ammo_index):
            raise ValueError(
                f"Mismatched included_ammo array size. ({item.name})")

        for ammo_index, ammo in zip(item.ammo_index, self.included_ammo):
            if ammo > db.get_item(ammo_index).max_capacity:
                raise ValueError(
                    f"Including more than maximum capacity for ammo {ammo_index}. Included: {ammo}; Max: {db.get_item(ammo_index).max_capacity}"
                )
コード例 #13
0
    def bit_pack_encode(self, metadata) -> Iterator[Tuple[int, int]]:
        resource_database = default_database.resource_database_for(self.game)

        yield from bitpacking.encode_bool(self.minimal_logic)
        if self.minimal_logic:
            return

        encodable_levels = list(LayoutTrickLevel)
        encodable_levels.remove(LayoutTrickLevel.DISABLED)

        for trick in sorted(_all_tricks(resource_database)):
            has_trick = self.has_specific_level_for_trick(trick)
            yield from bitpacking.encode_bool(has_trick)
            if has_trick:
                yield from bitpacking.pack_array_element(
                    self.level_for_trick(trick), encodable_levels)
コード例 #14
0
    def bit_pack_encode(
            self, item: MajorItem,
            reference: "MajorItemState") -> Iterator[Tuple[int, int]]:
        db = default_database.resource_database_for(item.game)
        if item.progression:
            main_index = item.progression[0]
        else:
            main_index = item.ammo_index[0]
        main_item = db.get_item(main_index)

        # original location
        if item.original_index is not None:
            yield from bitpacking.encode_bool(
                self.include_copy_in_original_location)

        # num shuffled
        yield from bitpacking.encode_int_with_limits(self.num_shuffled_pickups,
                                                     DEFAULT_MAXIMUM_SHUFFLED)

        # starting item
        if main_item.max_capacity > 1:
            yield from bitpacking.encode_int_with_limits(
                self.num_included_in_starting_items,
                (2, main_item.max_capacity + 1))
        else:
            yield self.num_included_in_starting_items, main_item.max_capacity + 1

        # priority
        yield from bitpacking.BitPackFloat(
            self.priority).bit_pack_encode(PRIORITY_LIMITS)

        # ammo index
        assert len(self.included_ammo) == len(item.ammo_index)
        if self.included_ammo:
            custom_ammo = self.included_ammo != reference.included_ammo
            yield from bitpacking.encode_bool(custom_ammo)
            if custom_ammo:
                all_equal = len(set(self.included_ammo)) == 1
                if len(item.ammo_index) > 1:
                    yield from bitpacking.encode_bool(all_equal)

                for ammo_index, ammo in zip(item.ammo_index,
                                            self.included_ammo):
                    yield ammo, db.get_item(ammo_index).max_capacity + 1
                    if all_equal:
                        break
コード例 #15
0
    def bit_pack_unpack(cls, decoder: BitPackDecoder, metadata):
        game = metadata["reference"].game
        resource_database = default_database.resource_database_for(game)

        minimal_logic = bitpacking.decode_bool(decoder)
        specific_levels = {}

        if not minimal_logic:
            encodable_levels = list(LayoutTrickLevel)
            encodable_levels.remove(LayoutTrickLevel.DISABLED)

            for trick in sorted(_all_tricks(resource_database)):
                if bitpacking.decode_bool(decoder):
                    specific_levels[trick.short_name] = decoder.decode_element(
                        encodable_levels)

        return cls(minimal_logic, specific_levels, game)
コード例 #16
0
ファイル: item_pool_tab.py プロジェクト: gollop/randovania
    def show_item_popup(self, item: MajorItem):
        """
        Shows the ItemConfigurationPopup for the given MajorItem
        :param item:
        :return:
        """
        major_items_configuration = self._editor.major_items_configuration

        popup = ItemConfigurationPopup(
            self, item, major_items_configuration.items_state[item],
            default_database.resource_database_for(self.game))
        result = popup.exec_()

        if result == QDialog.Accepted:
            with self._editor:
                self._editor.major_items_configuration = major_items_configuration.replace_state_for_item(
                    item, popup.state)
コード例 #17
0
ファイル: ammo_state.py プロジェクト: randovania/randovania
    def check_consistency(self, ammo: Ammo):
        db = default_database.resource_database_for(ammo.game)

        if len(self.ammo_count) != len(ammo.items):
            raise ValueError(
                f"Ammo state has {len(self.ammo_count)} ammo counts, expected {len(ammo.items)}"
            )

        for count, ammo_index in zip(self.ammo_count, ammo.items):
            ammo_item = db.get_item(ammo_index)
            if not (0 <= count <= ammo_item.max_capacity):
                raise ValueError(
                    f"Ammo count for item {ammo_index} of value {count} is not "
                    f"in range [0, {ammo_item.max_capacity}].")

        if self.pickup_count < 0:
            raise ValueError(
                f"Pickup count must be at least 0, got {self.pickup_count}")
コード例 #18
0
    def pretty_description(self) -> str:
        if self.minimal_logic:
            return "Minimal Logic"

        difficulties = collections.defaultdict(int)
        for trick in _all_tricks(
                default_database.resource_database_for(self.game)):
            difficulties[self.level_for_trick(trick)] += 1

        if len(difficulties) == 1:
            for level in difficulties.keys():
                return f"All at {level.long_name}"

        descriptions = [
            f"{difficulties[level]} at {level.long_name}"
            for level in iterate_enum(LayoutTrickLevel)
            if difficulties[level] > 0
        ]
        return ", ".join(descriptions)
コード例 #19
0
def create_temple_key_hint(all_patches: Dict[int, GamePatches],
                           player_index: int,
                           temple: HintDarkTemple,
                           namer: HintNamer,
                           with_color: bool,
                           ) -> str:
    """
    Creates the text for .
    :param all_patches:
    :param player_index:
    :param temple:
    :param namer:
    :param with_color:
    :return:
    """
    all_world_names = {}

    _TEMPLE_NAMES = ["Dark Agon Temple", "Dark Torvus Temple", "Hive Temple"]
    temple_index = [HintDarkTemple.AGON_WASTES, HintDarkTemple.TORVUS_BOG,
                    HintDarkTemple.SANCTUARY_FORTRESS].index(temple)

    db = default_database.resource_database_for(RandovaniaGame.METROID_PRIME_ECHOES)
    items = [db.get_item(index) for index in echoes_items.DARK_TEMPLE_KEY_ITEMS[temple_index]]

    locations_for_items = guaranteed_item_hint.find_locations_that_gives_items(items, all_patches, player_index)

    for options in locations_for_items.values():
        for player, location in options:
            all_world_names[namer.format_world(location, with_color=False)] = (player, location)
            break

    temple_name = namer.format_temple_name(_TEMPLE_NAMES[temple_index], with_color=with_color)
    names_sorted = [namer.format_world(location, with_color=with_color)
                    for name, (_, location) in sorted(all_world_names.items(), key=lambda it: it[0])]
    if len(names_sorted) == 0:
        return f"The keys to {temple_name} are nowhere to be found."
    elif len(names_sorted) == 1:
        return f"The keys to {temple_name} can all be found in {names_sorted[0]}."
    else:
        last = names_sorted.pop()
        front = ", ".join(names_sorted)
        return f"The keys to {temple_name} can be found in {front} and {last}."
コード例 #20
0
def prime2_hint_text():
    db = default_database.resource_database_for(RandovaniaGame.METROID_PRIME_ECHOES)

    result = []

    for temple in range(3):
        key = pickup_creator.create_dark_temple_key(0, temple, db)
        result.append((
            key.name.replace(" 1", "").strip(),
            key.item_category,
            key.broad_category,
        ))

    key = pickup_creator.create_sky_temple_key(0, db)
    result.append((
        "Sky Temple Key",
        key.item_category,
        key.broad_category,
    ))

    return result
コード例 #21
0
def apply_fixes(version: EchoesDolVersion, dol_file: DolFile):
    resource_database = default_database.resource_database_for(
        RandovaniaGame.METROID_PRIME_ECHOES)

    dol_file.symbols[
        "CMapWorldInfo::IsAnythingSet"] = version.anything_set_address

    dol_file.write_instructions("CMapWorldInfo::IsAnythingSet", [
        li(r3, 1),
        blr(),
    ])

    dol_file.write_instructions(version.rs_debugger_printf_loop_address, [
        nop(),
    ])

    from randovania.games.prime2.exporter.patch_data_factory import item_id_for_item_resource

    for item in ["Double Damage", "Unlimited Missiles", "Unlimited Beam Ammo"]:
        index = item_id_for_item_resource(
            resource_database.get_item_by_name(item))
        dol_file.write(version.powerup_should_persist + index, b"\x01")
コード例 #22
0
    def admin_session(user, session_id):
        session: GameSession = GameSession.get_by_id(session_id)

        rows = []
        presets = session.all_presets

        for player in session.players:
            player = typing.cast(GameSessionMembership, player)
            if player.is_observer:
                rows.append([
                    player.effective_name,
                    "Observer",
                    "",
                ])
            else:
                preset = presets[player.row]
                db = default_database.resource_database_for(preset.game)

                inventory = []
                for item in json.loads(player.inventory):
                    if item["amount"] + item["capacity"] > 0:
                        inventory.append("{} x{}/{}".format(
                            db.get_item(item["index"]).long_name,
                            item["amount"], item["capacity"]))

                rows.append([
                    player.effective_name,
                    preset.name,
                    ", ".join(inventory),
                ])

        header = ["Name", "Preset", "Inventory"]

        return "<table border='1'><tr>{}</tr>{}</table>".format(
            "".join(f"<th>{h}</th>" for h in header),
            "".join("<tr>{}</tr>".format("".join(f"<td>{h}</td>" for h in r))
                    for r in rows),
        )
コード例 #23
0
ファイル: conftest.py プロジェクト: 00mjk/randovania
def echoes_resource_database() -> ResourceDatabase:
    return default_database.resource_database_for(RandovaniaGame.PRIME2)
コード例 #24
0
    def create_tracker(self):
        tracker_name = self.selected_tracker
        if tracker_name == self._current_tracker_name or tracker_name is None:
            return

        self.delete_tracker()

        with path_for(
                self.trackers[tracker_name]).open("r") as tracker_details_file:
            tracker_details = json.load(tracker_details_file)

        game_enum = RandovaniaGame(tracker_details["game"])
        resource_database = default_database.resource_database_for(game_enum)

        for element in tracker_details["elements"]:
            text_template = ""
            minimum_to_check = element.get("minimum_to_check", 1)
            field_to_check = FieldToCheck(
                element.get("field_to_check", FieldToCheck.CAPACITY.value))

            labels = []
            if "image_path" in element:
                paths = element["image_path"]
                if not isinstance(paths, list):
                    paths = [paths]

                visible = True
                for path in paths:
                    image_path = get_data_path().joinpath(path)
                    if not image_path.exists():
                        logging.error("Tracker asset not found: %s",
                                      image_path)
                    pixmap = QtGui.QPixmap(str(image_path))

                    label = ClickableLabel(self.inventory_group,
                                           paint_with_opacity(pixmap, 0.3),
                                           paint_with_opacity(pixmap, 1.0))
                    label.set_checked(False)
                    label.set_ignore_mouse_events(True)
                    label.setVisible(visible)
                    visible = False
                    labels.append(label)

            elif "label" in element:
                label = QtWidgets.QLabel(self.inventory_group)
                label.setAlignment(QtCore.Qt.AlignCenter)
                text_template = element["label"]
                labels.append(label)

            else:
                raise ValueError(f"Invalid element: {element}")

            resources = [
                find_resource_info_with_long_name(resource_database.item,
                                                  resource_name)
                for resource_name in element["resources"]
            ]
            for resource, label in zip(resources, labels):
                label.setToolTip(resource.long_name)

            self._tracker_elements.append(
                Element(labels, resources, text_template, minimum_to_check,
                        field_to_check))
            for label in labels:
                self.inventory_layout.addWidget(label, element["row"],
                                                element["column"])

        self.inventory_spacer = QtWidgets.QSpacerItem(
            5, 5, QtWidgets.QSizePolicy.Expanding,
            QtWidgets.QSizePolicy.Expanding)
        self.inventory_layout.addItem(self.inventory_spacer,
                                      self.inventory_layout.rowCount(),
                                      self.inventory_layout.columnCount())

        self._current_tracker_game = game_enum
        self._update_tracker_from_hook({})

        self._current_tracker_name = tracker_name
コード例 #25
0
    def _create_ammo_pickup_boxes(self, size_policy, item_database: ItemDatabase):
        """
        Creates the GroupBox with SpinBoxes for selecting the pickup count of all the ammo
        :param item_database:
        :return:
        """

        self._ammo_item_count_spinboxes = collections.defaultdict(list)
        self._ammo_pickup_widgets = {}

        resource_database = default_database.resource_database_for(self.game)
        broad_to_category = {
            "beam_related": "beam",
            "morph_ball_related": "morph_ball",
            "missile_related": "missile",
        }

        layouts_with_lines: set[tuple[Foldable, QtWidgets.QGridLayout]] = {
            self._boxes_for_category[broad_to_category.get(ammo.broad_category.name, ammo.broad_category.name)][:2]
            for ammo in item_database.ammo.values()
        }

        for box, layout in layouts_with_lines:
            layout.addWidget(_create_separator(box), layout.rowCount(), 0, 1, -1)

        for ammo in item_database.ammo.values():
            category_box, category_layout, _ = self._boxes_for_category[broad_to_category.get(ammo.broad_category.name,
                                                                                              ammo.broad_category.name)]

            pickup_box = QtWidgets.QGroupBox(category_box)
            pickup_box.setSizePolicy(size_policy)
            pickup_box.setTitle(ammo.name + "s")
            layout = QtWidgets.QGridLayout(pickup_box)
            layout.setObjectName(f"{ammo.name} Box Layout")

            current_row = 0

            def add_row(widget_a: QtWidgets.QWidget, widget_b: QtWidgets.QWidget):
                nonlocal current_row
                layout.addWidget(widget_a, current_row, 0)
                layout.addWidget(widget_b, current_row, 1)
                current_row += 1

            for ammo_index, ammo_item in enumerate(ammo.items):
                item = resource_database.get_by_type_and_index(ResourceType.ITEM, ammo_item)

                item_count_label = QtWidgets.QLabel(pickup_box)
                item_count_label.setText(item.long_name if len(ammo.items) > 1 else "Contains")

                item_count_spinbox = ScrollProtectedSpinBox(pickup_box)
                item_count_spinbox.setMaximum(item.max_capacity)
                item_count_spinbox.valueChanged.connect(partial(self._on_update_ammo_pickup_item_count_spinbox,
                                                                ammo, ammo_index))
                self._ammo_item_count_spinboxes[ammo.name].append(item_count_spinbox)
                add_row(item_count_label, item_count_spinbox)

            # Pickup Count
            count_label = QtWidgets.QLabel(pickup_box)
            count_label.setText("Pickup Count")
            count_label.setToolTip("How many instances of this expansion should be placed.")

            pickup_spinbox = ScrollProtectedSpinBox(pickup_box)
            pickup_spinbox.setMaximum(999)
            pickup_spinbox.valueChanged.connect(partial(self._on_update_ammo_pickup_num_count_spinbox, ammo))

            add_row(count_label, pickup_spinbox)

            # FIXME: hardcoded check to hide required mains for Prime 1
            if ammo.temporary:
                require_major_item_check = QtWidgets.QCheckBox(pickup_box)
                require_major_item_check.setText("Requires the major item to work?")
                require_major_item_check.stateChanged.connect(partial(self._on_update_ammo_require_major_item, ammo))
                if self.game == RandovaniaGame.METROID_PRIME:
                    require_major_item_check.setVisible(False)
                layout.addWidget(require_major_item_check, current_row, 0, 1, 2)
                current_row += 1
            else:
                require_major_item_check = None

            expected_count = QtWidgets.QLabel(pickup_box)
            expected_count.setWordWrap(True)
            expected_count.setText("<TODO>")
            layout.addWidget(expected_count, current_row, 0, 1, 2)
            current_row += 1

            self._ammo_pickup_widgets[ammo] = AmmoPickupWidgets(pickup_spinbox, expected_count,
                                                                pickup_box, require_major_item_check)
            category_layout.addWidget(pickup_box)
コード例 #26
0
def prime1_resource_database() -> ResourceDatabase:
    return default_database.resource_database_for(RandovaniaGame.METROID_PRIME)
コード例 #27
0
ファイル: game_session.py プロジェクト: randovania/randovania
def _get_resource_database(description: LayoutDescription,
                           player: int) -> ResourceDatabase:
    return default_database.resource_database_for(
        description.get_preset(player).game)
コード例 #28
0
    def _create_ammo_pickup_boxes(self, size_policy,
                                  item_database: ItemDatabase):
        """
        Creates the GroupBox with SpinBoxes for selecting the pickup count of all the ammo
        :param item_database:
        :return:
        """

        self._ammo_maximum_spinboxes = collections.defaultdict(list)
        self._ammo_pickup_widgets = {}

        resource_database = default_database.resource_database_for(self.game)
        broad_to_category = {
            ItemCategory.BEAM_RELATED: ItemCategory.BEAM,
            ItemCategory.MORPH_BALL_RELATED: ItemCategory.MORPH_BALL,
            ItemCategory.MISSILE_RELATED: ItemCategory.MISSILE,
        }

        for ammo in item_database.ammo.values():
            category_box, category_layout, _ = self._boxes_for_category[
                broad_to_category[ammo.broad_category]]

            pickup_box = QGroupBox(category_box)
            pickup_box.setSizePolicy(size_policy)
            pickup_box.setTitle(ammo.name + "s")
            layout = QGridLayout(pickup_box)
            layout.setObjectName(f"{ammo.name} Box Layout")
            current_row = 0

            for ammo_item in ammo.items:
                item = resource_database.get_by_type_and_index(
                    ResourceType.ITEM, ammo_item)

                target_count_label = QLabel(pickup_box)
                target_count_label.setText(f"{item.long_name} Target" if len(
                    ammo.items) > 1 else "Target count")

                maximum_spinbox = QSpinBox(pickup_box)
                maximum_spinbox.setMaximum(ammo.maximum)
                maximum_spinbox.valueChanged.connect(
                    partial(self._on_update_ammo_maximum_spinbox, ammo_item))
                self._ammo_maximum_spinboxes[ammo_item].append(maximum_spinbox)

                layout.addWidget(target_count_label, current_row, 0)
                layout.addWidget(maximum_spinbox, current_row, 1)
                current_row += 1

            count_label = QLabel(pickup_box)
            count_label.setText("Pickup Count")
            count_label.setToolTip(
                "How many instances of this expansion should be placed.")

            pickup_spinbox = QSpinBox(pickup_box)
            pickup_spinbox.setMaximum(AmmoState.maximum_pickup_count())
            pickup_spinbox.valueChanged.connect(
                partial(self._on_update_ammo_pickup_spinbox, ammo))

            layout.addWidget(count_label, current_row, 0)
            layout.addWidget(pickup_spinbox, current_row, 1)
            current_row += 1

            if ammo.temporaries:
                require_major_item_check = QCheckBox(pickup_box)
                require_major_item_check.setText(
                    "Requires the major item to work?")
                require_major_item_check.stateChanged.connect(
                    partial(self._on_update_ammo_require_major_item, ammo))
                layout.addWidget(require_major_item_check, current_row, 0, 1,
                                 2)
                current_row += 1
            else:
                require_major_item_check = None

            expected_count = QLabel(pickup_box)
            expected_count.setWordWrap(True)
            expected_count.setText(_EXPECTED_COUNT_TEXT_TEMPLATE)
            expected_count.setToolTip(
                "Some expansions may provide 1 extra, even with no variance, if the total count "
                "is not divisible by the pickup count.")
            layout.addWidget(expected_count, current_row, 0, 1, 2)
            current_row += 1

            self._ammo_pickup_widgets[ammo] = AmmoPickupWidgets(
                pickup_spinbox, expected_count, pickup_box,
                require_major_item_check)
            category_layout.addWidget(pickup_box)
コード例 #29
0
def echoes_resource_database() -> ResourceDatabase:
    return default_database.resource_database_for(RandovaniaGame.METROID_PRIME_ECHOES)
コード例 #30
0
ファイル: item_pool_tab.py プロジェクト: gollop/randovania
    def _create_ammo_pickup_boxes(self, size_policy,
                                  item_database: ItemDatabase):
        """
        Creates the GroupBox with SpinBoxes for selecting the pickup count of all the ammo
        :param item_database:
        :return:
        """

        self._ammo_maximum_spinboxes = collections.defaultdict(list)
        self._ammo_pickup_widgets = {}

        resource_database = default_database.resource_database_for(self.game)

        for ammo in item_database.ammo.values():
            title_layout = QHBoxLayout()
            title_layout.setObjectName(f"{ammo.name} Title Horizontal Layout")

            expand_ammo_button = QToolButton(self.ammo_box)
            expand_ammo_button.setGeometry(QRect(20, 30, 24, 21))
            expand_ammo_button.setText("+")
            title_layout.addWidget(expand_ammo_button)

            category_label = QLabel(self.ammo_box)
            category_label.setSizePolicy(size_policy)
            category_label.setText(ammo.name + "s")
            title_layout.addWidget(category_label)

            pickup_box = QGroupBox(self.ammo_box)
            pickup_box.setSizePolicy(size_policy)
            layout = QGridLayout(pickup_box)
            layout.setObjectName(f"{ammo.name} Box Layout")
            current_row = 0

            for ammo_item in ammo.items:
                item = resource_database.get_by_type_and_index(
                    ResourceType.ITEM, ammo_item)

                target_count_label = QLabel(pickup_box)
                target_count_label.setText(f"{item.long_name} Target" if len(
                    ammo.items) > 1 else "Target count")

                maximum_spinbox = QSpinBox(pickup_box)
                maximum_spinbox.setMaximum(ammo.maximum)
                maximum_spinbox.valueChanged.connect(
                    partial(self._on_update_ammo_maximum_spinbox, ammo_item))
                self._ammo_maximum_spinboxes[ammo_item].append(maximum_spinbox)

                layout.addWidget(target_count_label, current_row, 0)
                layout.addWidget(maximum_spinbox, current_row, 1)
                current_row += 1

            count_label = QLabel(pickup_box)
            count_label.setText("Pickup Count")
            count_label.setToolTip(
                "How many instances of this expansion should be placed.")

            pickup_spinbox = QSpinBox(pickup_box)
            pickup_spinbox.setMaximum(AmmoState.maximum_pickup_count())
            pickup_spinbox.valueChanged.connect(
                partial(self._on_update_ammo_pickup_spinbox, ammo))

            layout.addWidget(count_label, current_row, 0)
            layout.addWidget(pickup_spinbox, current_row, 1)
            current_row += 1

            if ammo.temporaries:
                require_major_item_check = QCheckBox(pickup_box)
                require_major_item_check.setText(
                    "Requires the major item to work?")
                require_major_item_check.stateChanged.connect(
                    partial(self._on_update_ammo_require_major_item, ammo))
                layout.addWidget(require_major_item_check, current_row, 0, 1,
                                 2)
                current_row += 1
            else:
                require_major_item_check = None

            expected_count = QLabel(pickup_box)
            expected_count.setWordWrap(True)
            expected_count.setText(_EXPECTED_COUNT_TEXT_TEMPLATE)
            expected_count.setToolTip(
                "Some expansions may provide 1 extra, even with no variance, if the total count "
                "is not divisible by the pickup count.")
            layout.addWidget(expected_count, current_row, 0, 1, 2)
            current_row += 1

            self._ammo_pickup_widgets[ammo] = (pickup_spinbox, expected_count,
                                               expand_ammo_button,
                                               category_label, pickup_box,
                                               require_major_item_check)

            expand_ammo_button.clicked.connect(
                partial(_toggle_box_visibility, expand_ammo_button,
                        pickup_box))
            pickup_box.setVisible(False)

            self.ammo_layout.addLayout(title_layout)
            self.ammo_layout.addWidget(pickup_box)