def from_json(cls, value: dict,
                  game: RandovaniaGame) -> "MajorItemsConfiguration":
        item_database = default_database.item_database_for_game(game)

        items_state = {}
        for name, item in item_database.major_items.items():
            if name in value["items_state"]:
                state = MajorItemState.from_json(value["items_state"][name])
            else:
                state = MajorItemState()
            items_state[item] = state

        default_items = {}
        for category, options in item_database.default_items.items():
            default_items[category] = item_database.major_items[
                value["default_items"][category.value]]
            if default_items[category] not in options:
                raise ValueError(
                    f"Category {category} has {default_items[category]} as default item, "
                    f"but that's not a valid option.")

        return cls(
            items_state=items_state,
            default_items=default_items,
            minimum_random_starting_items=value[
                "minimum_random_starting_items"],
            maximum_random_starting_items=value[
                "maximum_random_starting_items"],
        )
Exemple #2
0
 def from_json(cls, value: dict,
               game: RandovaniaGame) -> "AmmoConfiguration":
     item_database = default_database.item_database_for_game(game)
     return cls(items_state={
         item_database.ammo[name]: AmmoState.from_json(state)
         for name, state in value["items_state"].items()
     }, )
    def from_json(cls, value: dict,
                  game: RandovaniaGame) -> "MajorItemsConfiguration":
        item_database = default_database.item_database_for_game(game)

        items_state = {}
        for name, item in item_database.major_items.items():
            if name in value["items_state"]:
                state = MajorItemState.from_json(value["items_state"][name])
            else:
                state = MajorItemState()
            items_state[item] = state

        default_items = {
            category:
            item_database.major_items[value["default_items"][category.name]]
            for category, _ in item_database.default_items.items()
        }

        return cls(
            game=game,
            items_state=items_state,
            default_items=default_items,
            minimum_random_starting_items=value[
                "minimum_random_starting_items"],
            maximum_random_starting_items=value[
                "maximum_random_starting_items"],
        )
Exemple #4
0
    def __init__(self, editor: PresetEditor):
        super().__init__()
        self.setupUi(self)

        self._editor = editor
        size_policy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed)
        self.item_pool_layout.setAlignment(Qt.AlignTop)

        # Relevant Items
        self.game = editor.game
        self.game_description = default_database.game_description_for(
            self.game)
        item_database = default_database.item_database_for_game(self.game)

        self._energy_tank_item = item_database.major_items["Energy Tank"]

        self._register_random_starting_events()
        self._create_categories_boxes(item_database, size_policy)
        self._create_customizable_default_items(item_database)
        self._create_progressive_widgets(item_database)
        self._create_major_item_boxes(item_database,
                                      self.game_description.resource_database)
        self._create_energy_tank_box()
        self._create_split_ammo_widgets(item_database)
        self._create_ammo_pickup_boxes(size_policy, item_database)
    def from_json(cls, json_dict: dict) -> "BaseConfiguration":
        game = cls.game_enum()
        item_database = default_database.item_database_for_game(game)

        kwargs = {}
        for field in dataclasses.fields(cls):
            try:
                arg = json_dict[field.name]
            except KeyError as e:
                raise KeyError(f"Missing field {e}") from e

            try:
                if issubclass(field.type, Enum):
                    arg = field.type(arg)
                elif hasattr(field.type, "from_json"):
                    extra_args = []
                    if field.name in ("trick_level", "starting_location"):
                        extra_args.append(game)
                    if field.name in ("major_items_configuration",
                                      "ammo_configuration"):
                        extra_args.append(item_database)
                    arg = field.type.from_json(arg, *extra_args)
            except ValueError as e:
                raise ValueError(f"Error in field {field.name}: {e}") from e

            kwargs[field.name] = arg

        return cls(**kwargs)
Exemple #6
0
    def _add_minimal_logic_initial_resources(
        self,
        resources: CurrentResources,
        game: GameDescription,
        major_items: MajorItemsConfiguration,
    ) -> None:
        resource_database = game.resource_database

        if game.minimal_logic is None:
            raise ValueError(
                f"Minimal logic enabled, but {game.game} doesn't have support for it."
            )

        item_db = default_database.item_database_for_game(game.game)

        items_to_skip = set()
        for it in game.minimal_logic.items_to_exclude:
            if it.reason is None or major_items.items_state[
                    item_db.major_items[it.reason]].num_shuffled_pickups != 0:
                items_to_skip.add(it.name)

        custom_item_count = game.minimal_logic.custom_item_amount
        events_to_skip = {
            it.name
            for it in game.minimal_logic.events_to_exclude
        }

        for event in resource_database.event:
            if event.short_name not in events_to_skip:
                resources[event] = 1

        for item in resource_database.item:
            if item.short_name not in items_to_skip:
                resources[item] = custom_item_count.get(item.short_name, 1)
Exemple #7
0
def _add_minimal_logic_initial_resources(
    resources: CurrentResources,
    resource_database: ResourceDatabase,
    major_items: MajorItemsConfiguration,
) -> None:
    # TODO: this function assumes we're talking about Echoes
    for event in resource_database.event:
        # Ignoring these events:
        # Dark Samus 3 and 4 (93), otherwise we're done automatically (TODO: get this from database)
        # Chykka (28), otherwise we can't collect Dark Visor
        if event.index not in {28, 93}:
            resources[event] = 1

    item_db = default_database.item_database_for_game(RandovaniaGame.PRIME2)

    items_to_skip = copy.copy(_items_to_not_add_in_minimal_logic)
    if major_items.items_state[item_db.major_items[
            "Progressive Grapple"]].num_shuffled_pickups == 0:
        items_to_skip.remove(23)
    if major_items.items_state[
            item_db.major_items["Progressive Suit"]].num_shuffled_pickups == 0:
        items_to_skip.remove(13)

    for item in resource_database.item:
        if item.index not in items_to_skip:
            resources[item] = _minimal_logic_custom_item_count.get(
                item.index, 1)
Exemple #8
0
def _create_config_for(game: RandovaniaGame, replace: dict):
    with get_data_path().joinpath("item_database", game.value, "default_state",
                                  "major-items.json").open() as open_file:
        default_data = json.load(open_file)

    default_data["minimum_random_starting_items"] = 0
    default_data["maximum_random_starting_items"] = 0

    data = copy.deepcopy(default_data)
    for field, value in replace.items():
        for key, inner_value in value.items():
            data[field][key] = inner_value

    return (
        MajorItemsConfiguration.from_json(
            default_data, default_database.item_database_for_game(game)),
        MajorItemsConfiguration.from_json(
            data, default_database.item_database_for_game(game)),
    )
Exemple #9
0
def _config_with_data(request):
    game: RandovaniaGame = request.param["game"]

    with get_data_path().joinpath("item_database", game.value, "default_state",
                                  "ammo.json").open() as open_file:
        default_data = json.load(open_file)

    default = AmmoConfiguration.from_json(
        default_data, default_database.item_database_for_game(game))
    data = copy.deepcopy(default_data)

    for key, value in request.param.get("items_state", {}).items():
        data["items_state"][key] = value

    for key, value in request.param.get("maximum_ammo", {}).items():
        data["maximum_ammo"][key] = value

    config = AmmoConfiguration.from_json(
        data, default_database.item_database_for_game(game))
    return request.param["encoded"], config, default
    def __init__(self, editor: PresetEditor):
        super().__init__(editor)
        item_database = default_database.item_database_for_game(self.game)
        game_description = default_database.game_description_for(self.game)

        size_policy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred,
                                            QtWidgets.QSizePolicy.Fixed)

        self._energy_tank_item = item_database.major_items["Energy Tank"]
        self._create_energy_tank_box(
            game_description.resource_database.energy_tank)
        self._create_pickup_style_box(size_policy)
    def __init__(self, editor: PresetEditor):
        super().__init__(editor)
        item_database = default_database.item_database_for_game(self.game)

        size_policy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Fixed)

        self._energy_item_to_starting_spinbox = {}
        self._energy_item_to_shuffled_spinbox = {}
        self._energy_tank_item = item_database.major_items["Energy Tank"]
        self._energy_part_item = item_database.major_items["Energy Part"]
        self._create_energy_box()
        self._create_pickup_style_box(size_policy)
Exemple #12
0
def update_hints_text(
    game: RandovaniaGame,
    hint_item_names_tree_widget: QtWidgets.QTableWidget,
):
    item_database = default_database.item_database_for_game(game)

    rows = []

    for item in item_database.major_items.values():
        rows.append((
            item.name,
            item.item_category.hint_details[1],
            item.item_category.general_details[1],
            item.broad_category.hint_details[1],
        ))

    if game == RandovaniaGame.PRIME2:
        for dark_temple_key in DARK_TEMPLE_KEY_NAMES:
            rows.append((
                dark_temple_key.format("").strip(),
                ItemCategory.TEMPLE_KEY.hint_details[1],
                ItemCategory.TEMPLE_KEY.general_details[1],
                ItemCategory.KEY.hint_details[1],
            ))

        rows.append((
            "Sky Temple Key",
            ItemCategory.SKY_TEMPLE_KEY.hint_details[1],
            ItemCategory.SKY_TEMPLE_KEY.general_details[1],
            ItemCategory.KEY.hint_details[1],
        ))

    for item in item_database.ammo.values():
        rows.append((
            item.name,
            ItemCategory.EXPANSION.hint_details[1],
            ItemCategory.EXPANSION.general_details[1],
            item.broad_category.hint_details[1],
        ))

    hint_item_names_tree_widget.setRowCount(len(rows))
    for i, elements in enumerate(rows):
        for j, element in enumerate(elements):
            hint_item_names_tree_widget.setItem(
                i, j, QtWidgets.QTableWidgetItem(element))

    for i in range(4):
        hint_item_names_tree_widget.resizeColumnToContents(i)
Exemple #13
0
    def __init__(self, description: LayoutDescription,
                 players_config: PlayersConfiguration,
                 cosmetic_patches: BaseCosmeticPatches):
        self.description = description
        self.players_config = players_config
        self.cosmetic_patches = cosmetic_patches

        self.item_db = default_database.item_database_for_game(
            self.game_enum())

        self.patches = description.all_patches[players_config.player_index]
        self.configuration = description.get_preset(
            players_config.player_index).configuration
        self.rng = Random(
            description.get_seed_for_player(players_config.player_index))
        self.game = filtered_database.game_description_for_layout(
            self.configuration)
Exemple #14
0
def update_hints_text(
    game: RandovaniaGame,
    hint_item_names_tree_widget: QtWidgets.QTableWidget,
):
    item_database = default_database.item_database_for_game(game)

    rows = []

    for item in item_database.major_items.values():
        rows.append((
            item.name,
            item.item_category.hint_details[1],
            item.item_category.general_details[1],
            item.broad_category.hint_details[1],
        ))

    for name, item_category, broad_category in _GAME_SPECIFIC.get(
            game, lambda: [])():
        rows.append((
            name,
            item_category.hint_details[1],
            item_category.general_details[1],
            broad_category.hint_details[1],
        ))

    for ammo in item_database.ammo.values():
        rows.append((
            ammo.name,
            ammo.item_category.hint_details[1],
            ammo.item_category.general_details[1],
            ammo.broad_category.hint_details[1],
        ))

    hint_item_names_tree_widget.setSortingEnabled(False)
    hint_item_names_tree_widget.setRowCount(len(rows))
    for i, elements in enumerate(rows):
        for j, element in enumerate(elements):
            hint_item_names_tree_widget.setItem(
                i, j, QtWidgets.QTableWidgetItem(element))

    for i in range(4):
        hint_item_names_tree_widget.resizeColumnToContents(i)

    hint_item_names_tree_widget.setSortingEnabled(True)
    def __post_init__(self):
        item_database = default_database.item_database_for_game(self.game)

        _check_matching_items(self.items_state.keys(),
                              item_database.major_items.values())
        _check_matching_items(self.default_items.keys(),
                              item_database.default_items.keys())

        for item, state in self.items_state.items():
            state.check_consistency(item)

        for category, options in item_database.default_items.items():
            if category not in self.default_items:
                raise ValueError(f"Category {category} is missing an item.")

            if self.default_items[category] not in options:
                raise ValueError(
                    f"Category {category} has {self.default_items[category]} as default item, "
                    f"but that's not a valid option.")
Exemple #16
0
def refresh_all_logic(args):
    from randovania.game_description import pretty_print
    from randovania.game_description import data_reader, data_writer
    from randovania.game_description import integrity_check

    gd_per_game = {}
    path_per_game = {}
    idb_per_game = {}

    for game in iterate_enum(RandovaniaGame):
        logging.info("Reading %s", game.long_name)
        path, data = default_data.read_json_then_binary(game)
        path_per_game[game] = path
        gd = data_reader.decode_data(data)
        gd_per_game[game] = gd

        idb = default_database.item_database_for_game(game)
        idb_per_game[game] = idb

    should_stop = False
    if args.integrity_check:
        for game, gd in gd_per_game.items():
            errors = integrity_check.find_database_errors(gd)
            if errors:
                logging.warning("Integrity errors for %s:\n%s", game.long_name,
                                "\n".join(errors))
                if game.data.development_state.is_stable:
                    should_stop = True

    if should_stop:
        return

    for game, gd in gd_per_game.items():
        path = path_per_game[game]
        logging.info("Writing %s", game.long_name)
        new_data = data_writer.write_game_description(gd)
        data_writer.write_as_split_files(new_data, path)
        path.with_suffix("").mkdir(parents=True, exist_ok=True)
        pretty_print.write_human_readable_game(gd, path.with_suffix(""))

        default_database.write_item_database_for_game(idb_per_game[game], game)
    def __init__(self, editor: PresetEditor):
        super().__init__(editor)
        item_database = default_database.item_database_for_game(self.game)

        self._create_split_ammo_widgets(item_database)
Exemple #18
0
def _echoes_format_params(
        configuration: EchoesConfiguration
) -> Tuple[Dict[str, List[str]], dict]:
    major_items = configuration.major_items_configuration
    item_database = default_database.item_database_for_game(configuration.game)
    template_strings = copy.deepcopy(_ECHOES_TEMPLATE_STRINGS)

    format_params = {}

    # Items
    inventory_changes = []
    if has_shuffled_item(major_items, "Progressive Suit"):
        inventory_changes.append("Progressive Suit")
    if has_shuffled_item(major_items, "Progressive Grapple"):
        inventory_changes.append("Progressive Grapple")

    unified_ammo = configuration.ammo_configuration.items_state[
        item_database.ammo["Beam Ammo Expansion"]]
    if unified_ammo.pickup_count == 0:
        inventory_changes.append("Split beam ammo")

    if inventory_changes:
        template_strings["Items"].append(", ".join(inventory_changes))

    # Difficulty
    if (configuration.varia_suit_damage,
            configuration.dark_suit_damage) != (6, 1.2):
        template_strings["Difficulty"].append(
            "Dark Aether: {:.2f} dmg/s Varia, {:.2f} dmg/s Dark".format(
                configuration.varia_suit_damage,
                configuration.dark_suit_damage))

    if configuration.energy_per_tank != 100:
        template_strings["Difficulty"].append(
            f"Energy Tank: {configuration.energy_per_tank} energy")

    if configuration.safe_zone.heal_per_second != 1:
        template_strings["Difficulty"].append(
            f"Safe Zone: {configuration.safe_zone.heal_per_second:.2f} energy/s"
        )

    if configuration.dangerous_energy_tank:
        template_strings["Difficulty"].append("1-HP Mode")

    # Gameplay
    translator_gates = "Custom"
    translator_configurations = [
        (configuration.translator_configuration.with_vanilla_actual(),
         "Vanilla (Actual)"),
        (configuration.translator_configuration.with_vanilla_colors(),
         "Vanilla (Colors)"),
        (configuration.translator_configuration.with_full_random(), "Random"),
    ]
    for translator_config, name in translator_configurations:
        if translator_config == configuration.translator_configuration:
            translator_gates = name
            break

    format_params["translator_gates"] = translator_gates
    format_params["hints"] = "Yes"

    if configuration.elevators != LayoutElevators.VANILLA:
        template_strings["Gameplay"].append(
            f"Elevators: {configuration.elevators.long_name}")

    # Game Changes
    missile_launcher_required = True
    main_pb_required = True
    for ammo, state in configuration.ammo_configuration.items_state.items():
        if ammo.name == "Missile Expansion":
            missile_launcher_required = state.requires_major_item
        elif ammo.name == "Power Bomb Expansion":
            main_pb_required = state.requires_major_item

    required_messages = []
    if missile_launcher_required:
        required_messages.append("Missiles needs Launcher")
    if main_pb_required:
        required_messages.append("Power Bomb needs Main")

    if required_messages:
        template_strings["Game Changes"].append(", ".join(required_messages))

    qol_changes = []
    if configuration.warp_to_start:
        qol_changes.append("Can warp to start")
    if configuration.menu_mod:
        qol_changes.append("Menu Mod included")
    if configuration.skip_final_bosses:
        qol_changes.append("Final bosses removed")

    if qol_changes:
        template_strings["Game Changes"].append(", ".join(qol_changes))

    if not template_strings["Game Changes"]:
        template_strings.pop("Game Changes")

    # Sky Temple Keys
    if configuration.sky_temple_keys.num_keys == LayoutSkyTempleKeyMode.ALL_BOSSES:
        template_strings["Items"].append("Sky Temple Keys at all bosses")
    elif configuration.sky_temple_keys.num_keys == LayoutSkyTempleKeyMode.ALL_GUARDIANS:
        template_strings["Items"].append("Sky Temple Keys at all guardians")
    else:
        template_strings["Items"].append(
            f"{configuration.sky_temple_keys.num_keys} Sky Temple Keys shuffled"
        )

    # Item Model
    if configuration.pickup_model_style != PickupModelStyle.ALL_VISIBLE:
        template_strings["Difficulty"].append(
            f"Pickup: {configuration.pickup_model_style.long_name} "
            f"({configuration.pickup_model_data_source.long_name})")

    return template_strings, format_params
Exemple #19
0
def _echoes_format_params(configuration: EchoesConfiguration) -> dict:
    major_items = configuration.major_items_configuration
    item_database = default_database.item_database_for_game(configuration.game)

    format_params = {}

    # Items
    unified_ammo = configuration.ammo_configuration.items_state[
        item_database.ammo["Beam Ammo Expansion"]]

    format_params["progressive_suit"] = _bool_to_str(
        has_shuffled_item(major_items, "Progressive Suit"))
    format_params["progressive_grapple"] = _bool_to_str(
        has_shuffled_item(major_items, "Progressive Grapple"))
    format_params["split_beam_ammo"] = _bool_to_str(
        unified_ammo.pickup_count == 0)

    # Difficulty
    if configuration.varia_suit_damage == 6 and configuration.dark_suit_damage == 1.2:
        dark_aether_suit_damage = "Normal"
    else:
        dark_aether_suit_damage = "Custom"

    format_params["energy_tank"] = f"{configuration.energy_per_tank} energy"
    format_params["dangerous_energy_tank"] = _bool_to_str(
        configuration.dangerous_energy_tank)
    format_params[
        "safe_zone"] = f"{configuration.safe_zone.heal_per_second} energy/s"
    format_params["dark_aether_suit_damage"] = dark_aether_suit_damage

    # Gameplay
    translator_gates = "Custom"
    translator_configurations = [
        (configuration.translator_configuration.with_vanilla_actual(),
         "Vanilla (Actual)"),
        (configuration.translator_configuration.with_vanilla_colors(),
         "Vanilla (Colors)"),
        (configuration.translator_configuration.with_full_random(), "Random"),
    ]
    for translator_config, name in translator_configurations:
        if translator_config == configuration.translator_configuration:
            translator_gates = name
            break

    format_params["translator_gates"] = translator_gates
    format_params["elevators"] = configuration.elevators.value
    format_params["hints"] = "Yes"

    # Game Changes
    missile_launcher_required = True
    main_pb_required = True
    for ammo, state in configuration.ammo_configuration.items_state.items():
        if ammo.name == "Missile Expansion":
            missile_launcher_required = state.requires_major_item
        elif ammo.name == "Power Bomb Expansion":
            main_pb_required = state.requires_major_item

    format_params["missile_launcher_required"] = _bool_to_str(
        missile_launcher_required)
    format_params["main_pb_required"] = _bool_to_str(main_pb_required)
    format_params["warp_to_start"] = _bool_to_str(configuration.warp_to_start)
    format_params["generic_patches"] = "Some"
    format_params["menu_mod"] = _bool_to_str(configuration.menu_mod)
    format_params["include_final_bosses"] = _bool_to_str(
        not configuration.skip_final_bosses)

    # Sky Temple Keys
    if configuration.sky_temple_keys.num_keys == LayoutSkyTempleKeyMode.ALL_BOSSES:
        stk_location = "Bosses"
    elif configuration.sky_temple_keys.num_keys == LayoutSkyTempleKeyMode.ALL_GUARDIANS:
        stk_location = "Guardians"
    else:
        stk_location = "Random"

    format_params["target"] = "{0} of {0}".format(
        configuration.sky_temple_keys.num_keys)
    format_params["location"] = stk_location

    return format_params
    def format_params(
            self, configuration: BaseConfiguration) -> dict[str, list[str]]:
        assert isinstance(configuration, EchoesConfiguration)
        major_items = configuration.major_items_configuration
        item_database = default_database.item_database_for_game(
            configuration.game)

        template_strings = super().format_params(configuration)
        unified_ammo = configuration.ammo_configuration.items_state[
            item_database.ammo["Beam Ammo Expansion"]]

        # Difficulty
        if (configuration.varia_suit_damage,
                configuration.dark_suit_damage) != (6, 1.2):
            template_strings["Difficulty"].append(
                "Dark Aether: {:.2f} dmg/s Varia, {:.2f} dmg/s Dark".format(
                    configuration.varia_suit_damage,
                    configuration.dark_suit_damage))

        if configuration.energy_per_tank != 100:
            template_strings["Difficulty"].append(
                f"Energy Tank: {configuration.energy_per_tank} energy")

        if configuration.safe_zone.heal_per_second != 1:
            template_strings["Difficulty"].append(
                f"Safe Zone: {configuration.safe_zone.heal_per_second:.2f} energy/s"
            )

        extra_message_tree = {
            "Item Pool": [{
                "Progressive Suit":
                has_shuffled_item(major_items, "Progressive Suit"),
                "Progressive Grapple":
                has_shuffled_item(major_items, "Progressive Grapple"),
                "Split beam ammo":
                unified_ammo.pickup_count == 0,
            }],
            "Difficulty": [
                {
                    "1-HP Mode": configuration.dangerous_energy_tank
                },
            ],
            "Gameplay": [
                {
                    f"Translator Gates: {configuration.translator_configuration.description()}":
                    True
                },
                {
                    f"Elevators: {configuration.elevators.description()}":
                    not configuration.elevators.is_vanilla
                },
            ],
            "Game Changes": [
                message_for_required_mains(
                    configuration.ammo_configuration, {
                        "Missiles needs Launcher": "Missile Expansion",
                        "Power Bomb needs Main": "Power Bomb Expansion",
                    }),
                {
                    "Warp to start":
                    configuration.warp_to_start,
                    "Menu Mod":
                    configuration.menu_mod,
                    "Final bosses removed":
                    configuration.elevators.skip_final_bosses
                },
                *create_beam_configuration_description(
                    configuration.beam_configuration),
            ]
        }
        fill_template_strings_from_tree(template_strings, extra_message_tree)

        # Sky Temple Keys
        if configuration.sky_temple_keys == LayoutSkyTempleKeyMode.ALL_BOSSES:
            template_strings["Item Pool"].append(
                "Sky Temple Keys at all bosses")
        elif configuration.sky_temple_keys == LayoutSkyTempleKeyMode.ALL_GUARDIANS:
            template_strings["Item Pool"].append(
                "Sky Temple Keys at all guardians")
        else:
            template_strings["Item Pool"].append(
                f"{configuration.sky_temple_keys.num_keys} Sky Temple Keys")

        return template_strings
Exemple #21
0
def echoes_item_database() -> ItemDatabase:
    return default_database.item_database_for_game(RandovaniaGame.METROID_PRIME_ECHOES)
Exemple #22
0
def _prime_format_params(
        configuration: PrimeConfiguration
) -> Tuple[Dict[str, List[str]], dict]:
    major_items = configuration.major_items_configuration
    item_database = default_database.item_database_for_game(configuration.game)
    template_strings = copy.deepcopy(_BASE_TEMPLATE_STRINGS)

    format_params = {}

    # Difficulty
    if configuration.heat_damage != 10.0:
        template_strings["Difficulty"].append(
            "Heat Damage: {:.2f} dmg/s".format(configuration.heat_damage))

    if configuration.energy_per_tank != 100:
        template_strings["Difficulty"].append(
            f"Energy Tank: {configuration.energy_per_tank} energy")

    # Gameplay

    if not configuration.elevators.is_vanilla:
        template_strings["Gameplay"].append(
            f"Elevators: {configuration.elevators.description()}")

    # Game Changes
    missile_launcher_required = True
    main_pb_required = True
    for ammo, state in configuration.ammo_configuration.items_state.items():
        if ammo.name == "Missile Expansion":
            missile_launcher_required = state.requires_major_item
        elif ammo.name == "Power Bomb Expansion":
            main_pb_required = state.requires_major_item

    required_messages = []
    if missile_launcher_required:
        required_messages.append("Missiles needs Launcher")
    if main_pb_required:
        required_messages.append("Power Bomb needs Main")
    if configuration.heat_protection_only_varia:
        required_messages.append("Varia-only heat protection")
    if configuration.progressive_damage_reduction:
        required_messages.append("Progressive suit damage reduction")

    if required_messages:
        template_strings["Game Changes"].append(", ".join(required_messages))

    qol_changes = []
    for flag, message in (
        (configuration.qol_logical, "Logical QOL"),
        (configuration.qol_game_breaking, "Game Breaking QOL"),
        (configuration.qol_minor_cutscenes, "Minor Cutscenes QOL"),
        (configuration.qol_major_cutscenes, "Major Cutscenes QOL"),
        (configuration.elevators.skip_final_bosses, "Final bosses removed"),
    ):
        if flag:
            qol_changes.append(message)

    if qol_changes:
        template_strings["Game Changes"].append(", ".join(qol_changes))

    if not template_strings["Game Changes"]:
        template_strings.pop("Game Changes")

    # Artifacts
    template_strings["Items"].append(
        f"{configuration.artifacts.num_artifacts} Artifacts shuffled")

    # Item Model
    if configuration.pickup_model_style != PickupModelStyle.ALL_VISIBLE:
        template_strings["Difficulty"].append(
            f"Pickup: {configuration.pickup_model_style.long_name} "
            f"({configuration.pickup_model_data_source.long_name})")

    return template_strings, format_params
Exemple #23
0
def echoes_item_database() -> ItemDatabase:
    return default_database.item_database_for_game(RandovaniaGame.PRIME2)
Exemple #24
0
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        common_qt_lib.set_default_window_icon(self)

        self.game_description = default_database.game_description_for(RandovaniaGame.METROID_PRIME_CORRUPTION)
        item_database = default_database.item_database_for_game(RandovaniaGame.METROID_PRIME_CORRUPTION)
        world_list = self.game_description.world_list
        self._index_to_combo = {}

        columns = []
        for i in range(2):
            columns.append(QtWidgets.QVBoxLayout(self.scroll_area_contents))
            self.scroll_area_layout.addLayout(columns[-1])

        ids_to_merge = [5406397194789083955,  # Phaaze
                        16039522250714156185,
                        10717625015048596485,
                        14806081023590793725,
                        ]
        nodes_to_merge = []

        world_count = 0
        for i, world in enumerate(world_list.worlds):
            if world.extra['asset_id'] in ids_to_merge:
                nodes_to_merge.extend(
                    node
                    for area in world.areas
                    for node in area.nodes
                    if isinstance(node, PickupNode)
                )
                continue

            group = QtWidgets.QGroupBox(self.scroll_area_contents)
            group.setTitle(world.name)

            layout = QtWidgets.QGridLayout(group)

            area_count = 0
            for area in world.areas:
                for node in area.nodes:
                    if not isinstance(node, PickupNode):
                        continue

                    node_label = QtWidgets.QLabel(world_list.node_name(node), group)
                    layout.addWidget(node_label, area_count, 0)

                    node_combo = QtWidgets.QComboBox(group)
                    _fill_combo(item_database, node_combo)
                    node_combo.currentIndexChanged.connect(self.update_layout_string)
                    layout.addWidget(node_combo, area_count, 1)

                    self._index_to_combo[node.pickup_index] = node_combo
                    area_count += 1

            columns[world_count % len(columns)].addWidget(group)
            world_count += 1

        group = QtWidgets.QGroupBox(self.scroll_area_contents)
        group.setTitle("Seeds")

        layout = QtWidgets.QGridLayout(group)
        area_count = 0
        for node in nodes_to_merge:
            if not isinstance(node, PickupNode):
                continue

            node_label = QtWidgets.QLabel(world_list.node_name(node), group)
            layout.addWidget(node_label, area_count, 0)

            node_combo = QtWidgets.QComboBox(group)
            _fill_combo(item_database, node_combo)
            node_combo.currentIndexChanged.connect(self.update_layout_string)
            layout.addWidget(node_combo, area_count, 1)

            self._index_to_combo[node.pickup_index] = node_combo
            area_count += 1

        columns[0].addWidget(group)
        # world_count += 1
        self.update_layout_string()