示例#1
0
def create_energy_cell(
    cell_index: int,
    resource_database: ResourceDatabase,
) -> PickupEntry:
    ENERGY_CELL_CATEGORY = ItemCategory(name="energy_cell",
                                        long_name="",
                                        hint_details=("an ", "energy cell"),
                                        is_major=False,
                                        is_key=True)

    return PickupEntry(
        name=f"Energy Cell {cell_index + 1}",
        progression=((resource_database.get_item(
            corruption_items.ENERGY_CELL_ITEMS[cell_index]), 1), ),
        extra_resources=(
            (resource_database.get_item(
                corruption_items.ENERGY_CELL_TOTAL_ITEM), 1),
            (resource_database.item_percentage, 1),
        ),
        model=PickupModel(
            game=resource_database.game_enum,
            name=corruption_items.ENERGY_CELL_MODEL,
        ),
        item_category=ENERGY_CELL_CATEGORY,
        broad_category=GENERIC_KEY_CATEGORY,
        probability_offset=0.25,
    )
示例#2
0
def create_stk_hints(
    all_patches: Dict[int, GamePatches],
    players_config: PlayersConfiguration,
    resource_database: ResourceDatabase,
    namer: HintNamer,
    hide_area: bool,
) -> list:
    """
    Creates the string patches entries that changes the Sky Temple Gateway hint scans with hints for where
    the STK actually are.
    :param all_patches:
    :param players_config:
    :param resource_database:
    :param namer:
    :param hide_area: Should the hint include only the world?
    :return:
    """
    resulting_hints = guaranteed_item_hint.create_guaranteed_hints_for_resources(
        all_patches,
        players_config,
        namer,
        hide_area,
        [
            resource_database.get_item(index)
            for index in echoes_items.SKY_TEMPLE_KEY_ITEMS
        ],
        True,
    )
    return [
        create_simple_logbook_hint(
            _SKY_TEMPLE_KEY_SCAN_ASSETS[key_number],
            resulting_hints[resource_database.get_item(key_index)],
        ) for key_number, key_index in enumerate(
            echoes_items.SKY_TEMPLE_KEY_ITEMS)
    ]
示例#3
0
 def create_resource_lock(self, resource_database: ResourceDatabase) -> Optional[ResourceLock]:
     if self.unlocked_by is not None:
         return ResourceLock(
             locked_by=resource_database.get_item(self.unlocked_by),
             item_to_lock=resource_database.get_item(self.items[0]),
             temporary_item=resource_database.get_item(self.temporary),
         )
     return None
示例#4
0
 def create_game_specific(self, resource_database: ResourceDatabase) -> EchoesBeamConfiguration:
     return EchoesBeamConfiguration(
         item=resource_database.get_item(self.item_index),
         ammo_a=resource_database.get_item(self.ammo_a) if self.ammo_a >= 0 else None,
         ammo_b=resource_database.get_item(self.ammo_b) if self.ammo_b >= 0 else None,
         uncharged_cost=self.uncharged_cost,
         charged_cost=self.charged_cost,
         combo_missile_cost=self.combo_missile_cost,
         combo_ammo_cost=self.combo_ammo_cost,
     )
示例#5
0
def read_beam_configuration(data: Dict, resource_database: ResourceDatabase,
                            ) -> EchoesBeamConfiguration:
    return EchoesBeamConfiguration(
        item=resource_database.get_item(data["item_index"]),
        ammo_a=resource_database.get_item(data["ammo_a"]) if data["ammo_a"] is not None else None,
        ammo_b=resource_database.get_item(data["ammo_b"]) if data["ammo_b"] is not None else None,
        uncharged_cost=data["uncharged_cost"],
        charged_cost=data["charged_cost"],
        combo_missile_cost=data["combo_missile_cost"],
        combo_ammo_cost=data["combo_ammo_cost"],
    )
def wrap(db: ResourceDatabase, data):
    if isinstance(data, dict):
        return {
            db.get_item(key): value
            for key, value in data.items()
        }
    else:
        return [
            (db.get_item(key), value)
            for key, value in data
        ]
示例#7
0
def create_artifact(artifact_index: int,
                    minimum_progression: int,
                    resource_database: ResourceDatabase,
                    ) -> PickupEntry:
    ARTIFACT_CATEGORY = ItemCategory(
        name="artifact",
        long_name="",
        hint_details=("an ", "artifact"),
        is_major=False,
        is_key=True
    )

    return PickupEntry(
        name=prime_items.ARTIFACT_NAMES[artifact_index],
        progression=(
            (resource_database.get_item(prime_items.ARTIFACT_ITEMS[artifact_index]), 1),
        ),
        model=PickupModel(
            game=resource_database.game_enum,
            name=prime_items.ARTIFACT_MODEL[artifact_index],
        ),
        item_category=ARTIFACT_CATEGORY,
        broad_category=GENERIC_KEY_CATEGORY,
        probability_offset=0.25,
        required_progression=minimum_progression,
    )
示例#8
0
def create_dark_temple_key(
    key_number: int,
    temple_index: int,
    resource_database: ResourceDatabase,
) -> PickupEntry:
    """
    Creates a Dark Temple Key
    :param key_number:
    :param temple_index: The index of the temple: Dark Agon, Dark Torvus, Hive Temple
    :param resource_database:
    :return:
    """
    TEMPLE_KEY_CATEGORY = ItemCategory(name="temple_key",
                                       long_name="",
                                       hint_details=("a ", "red Temple Key"),
                                       is_major=False,
                                       is_key=True)

    return PickupEntry(
        name=echoes_items.DARK_TEMPLE_KEY_NAMES[temple_index].format(
            key_number + 1),
        progression=((resource_database.get_item(
            echoes_items.DARK_TEMPLE_KEY_ITEMS[temple_index][key_number]),
                      1), ),
        model=PickupModel(
            game=resource_database.game_enum,
            name=echoes_items.DARK_TEMPLE_KEY_MODEL,
        ),
        item_category=TEMPLE_KEY_CATEGORY,
        broad_category=GENERIC_KEY_CATEGORY,
        probability_offset=3,
    )
示例#9
0
def create_sky_temple_key(
    key_number: int,
    resource_database: ResourceDatabase,
) -> PickupEntry:
    """

    :param key_number:
    :param resource_database:
    :return:
    """
    SKY_TEMPLE_KEY_CATEGORY = ItemCategory(name="sky_temple_key",
                                           long_name="",
                                           hint_details=("a ",
                                                         "Sky Temple Key"),
                                           is_major=False,
                                           is_key=True)

    return PickupEntry(
        name="Sky Temple Key {}".format(key_number + 1),
        progression=((resource_database.get_item(
            echoes_items.SKY_TEMPLE_KEY_ITEMS[key_number]), 1), ),
        model=PickupModel(
            game=resource_database.game_enum,
            name=echoes_items.SKY_TEMPLE_KEY_MODEL,
        ),
        item_category=SKY_TEMPLE_KEY_CATEGORY,
        broad_category=GENERIC_KEY_CATEGORY,
        probability_offset=3,
    )
示例#10
0
def create_ammo_expansion(
    ammo: Ammo,
    ammo_count: Sequence[int],
    requires_major_item: bool,
    resource_database: ResourceDatabase,
) -> PickupEntry:
    """
    Creates a Pickup for an expansion of the given ammo.
    :param ammo:
    :param ammo_count:
    :param requires_major_item:
    :param resource_database:
    :return:
    """
    resources = [(resource_database.get_item(item), count)
                 for item, count in zip(ammo.items, ammo_count)]

    if resource_database.item_percentage is not None:
        resources.append((resource_database.item_percentage, 1))

    return PickupEntry(
        name=ammo.name,
        progression=(),
        extra_resources=tuple(resources),
        model=PickupModel(
            game=resource_database.game_enum,
            name=ammo.model_name,
        ),
        item_category=ammo.item_category,
        broad_category=ammo.broad_category,
        respects_lock=requires_major_item,
        resource_lock=ammo.create_resource_lock(resource_database),
        probability_multiplier=2,
    )
示例#11
0
def _starting_items_value_for(resource_database: ResourceDatabase,
                              starting_items: CurrentResources, index: str) -> Union[bool, int]:
    item = resource_database.get_item(index)
    value = starting_items.get(item, 0)
    if item.max_capacity > 1:
        return value
    else:
        return value > 0
示例#12
0
    def __init__(self, parent: QWidget, item: MajorItem, starting_state: MajorItemState,
                 resources_database: ResourceDatabase):
        super().__init__(parent)
        self.setupUi(self)
        set_default_window_icon(self)
        self._item = item

        self.setWindowTitle(f"Item: {item.name}")
        self.item_name_label.setText(item.name)

        # connect
        self.excluded_radio.toggled.connect(self._on_select_excluded)
        self.vanilla_radio.toggled.connect(self._on_select_vanilla)
        self.starting_radio.toggled.connect(self._on_select_starting)
        self.shuffled_radio.toggled.connect(self._on_select_shuffled)
        self.shuffled_spinbox.valueChanged.connect(self._on_shuffled_value)
        self.provided_ammo_spinbox.valueChanged.connect(self._on_shuffled_value)

        # Update
        self.vanilla_radio.setEnabled(item.original_index is not None)
        self.shuffled_radio.setEnabled(item.model_index is not None)

        if not self.vanilla_radio.isEnabled():
            self.vanilla_radio.setToolTip(
                "This item does not exist in the original game, so there's no vanilla location.")

        if not self.shuffled_radio.isEnabled():
            self.shuffled_radio.setToolTip(
                "There's currently no available model and/or logic for this item to be shuffled.")

        # At least one radio should be selected
        for radio in (self.shuffled_radio, self.starting_radio, self.vanilla_radio):
            if radio.isEnabled():
                radio.setChecked(True)
                break

        if item.ammo_index:
            self.provided_ammo_label.setText(
                "<html><head/><body><p>Provided Ammo ({})</p></body></html>".format(
                    " and ".join(
                        resources_database.get_item(ammo_index).long_name
                        for ammo_index in item.ammo_index
                    )
                )
            )
        else:
            self.provided_ammo_label.hide()
            self.provided_ammo_spinbox.hide()

        if self._item.required:
            self.item_name_label.setToolTip(
                "This item is necessary for the game to function properly and can't be removed.")
            self.setEnabled(False)
            self.state = self._create_state(num_included_in_starting_items=1)
        else:
            if self._item.warning is not None:
                self.item_name_label.setToolTip(self._item.warning)
            self.state = starting_state
示例#13
0
def _starting_items_value_for(resource_database: ResourceDatabase,
                              starting_items: ResourceCollection,
                              index: str) -> Union[bool, int]:
    item = resource_database.get_item(index)
    value = starting_items[item]
    if item.max_capacity > 1:
        return value
    else:
        return value > 0
示例#14
0
def create_ammo_expansion(
    ammo: Ammo,
    ammo_count: List[int],
    requires_major_item: bool,
    resource_database: ResourceDatabase,
) -> PickupEntry:
    """
    Creates a Pickup for an expansion of the given ammo.
    :param ammo:
    :param ammo_count:
    :param requires_major_item:
    :param resource_database:
    :return:
    """
    resources = [(resource_database.get_item(item), count)
                 for item, count in zip(ammo.items, ammo_count)]
    resources.append((resource_database.item_percentage, 1))

    if ammo.unlocked_by is not None and requires_major_item:
        temporary_resources = [
            (resource_database.get_item(item), count)
            for item, count in zip(ammo.temporaries, ammo_count)
        ]
        temporary_resources.append((resource_database.item_percentage, 1))

        conditional_resources = (
            ConditionalResources(temporary_resources[0][0].long_name, None,
                                 tuple(temporary_resources)),
            ConditionalResources(ammo.name,
                                 resource_database.get_item(ammo.unlocked_by),
                                 tuple(resources)),
        )
    else:
        conditional_resources = (ConditionalResources(None, None,
                                                      tuple(resources)), )

    return PickupEntry(
        name=ammo.name,
        resources=conditional_resources,
        model_index=ammo.models[0],  # TODO: use a random model
        item_category=ItemCategory.EXPANSION,
        broad_category=ammo.broad_category,
    )
示例#15
0
def create_energy_cell(cell_index: int,
                       resource_database: ResourceDatabase,
                       ) -> PickupEntry:
    return PickupEntry(
        name=f"Energy Cell {cell_index + 1}",
        progression=(
            (resource_database.get_item(corruption_items.ENERGY_CELL_ITEMS[cell_index]), 1),
        ),
        extra_resources=(
            (resource_database.get_item(corruption_items.ENERGY_CELL_TOTAL_ITEM), 1),
            (resource_database.item_percentage, 1),
        ),
        model=PickupModel(
            game=resource_database.game_enum,
            name=corruption_items.ENERGY_CELL_MODEL,
        ),
        item_category=ItemCategory.TEMPLE_KEY,
        broad_category=ItemCategory.KEY,
        probability_offset=0.25,
    )
示例#16
0
def create_energy_cell(
    cell_index: int,
    resource_database: ResourceDatabase,
) -> PickupEntry:
    return PickupEntry(
        name=f"Energy Cell {cell_index + 1}",
        resources=(ConditionalResources(
            None, None,
            tuple([
                (resource_database.get_item(
                    corruption_items.ENERGY_CELL_ITEMS[cell_index]), 1),
                (resource_database.get_item(
                    corruption_items.ENERGY_CELL_TOTAL_ITEM), 1),
                (resource_database.item_percentage, 1),
            ])), ),
        model_index=corruption_items.ENERGY_CELL_MODEL,
        item_category=ItemCategory.TEMPLE_KEY,
        broad_category=ItemCategory.KEY,
        probability_offset=0.25,
    )
示例#17
0
def create_major_item(
    item: MajorItem,
    state: MajorItemState,
    include_percentage: bool,
    resource_database: ResourceDatabase,
    ammo: Optional[Ammo],
    ammo_requires_major_item: bool,
) -> PickupEntry:
    """
    Creates a Pickup for the given MajorItem
    :param include_percentage:
    :param state:
    :param item:
    :param resource_database:
    :param ammo:
    :param ammo_requires_major_item:
    :return:
    """

    extra_resources = [
        (resource_database.get_item(ammo_index), ammo_count)
        for ammo_index, ammo_count in zip(item.ammo_index, state.included_ammo)
    ]
    if include_percentage and resource_database.item_percentage is not None:
        extra_resources.append((resource_database.item_percentage, 1))

    def _create_resources(base_resource: Optional[str]) -> ResourceQuantity:
        # FIXME: hacky quantity for Hazard Shield
        quantity = 5 if item.name == "Hazard Shield" else 1
        return resource_database.get_item(base_resource), quantity

    return PickupEntry(
        name=item.name,
        progression=tuple(
            _create_resources(progression)
            for progression in item.progression),
        extra_resources=tuple(extra_resources),
        model=PickupModel(
            game=resource_database.game_enum,
            name=item.model_name,
        ),
        item_category=item.item_category,
        broad_category=item.broad_category,
        probability_offset=item.probability_offset,
        probability_multiplier=item.probability_multiplier * state.priority,
        unlocks_resource=item.unlocks_ammo,
        respects_lock=ammo_requires_major_item,
        resource_lock=ammo.create_resource_lock(resource_database)
        if ammo is not None else None,
    )
示例#18
0
def create_useless_pickup(resource_database: ResourceDatabase) -> PickupEntry:
    """
    Creates an Energy Transfer Module pickup.
    :param resource_database:
    :return:
    """
    return PickupEntry(
        name="Energy Transfer Module",
        resources=(ConditionalResources(
            None, None,
            tuple([(resource_database.get_item(USELESS_PICKUP_ITEM), 1)])), ),
        model_index=USELESS_PICKUP_MODEL,
        item_category=ItemCategory.ETM,
        broad_category=ItemCategory.ETM,
    )
示例#19
0
def create_artifact(
    artifact_index: int,
    resource_database: ResourceDatabase,
) -> PickupEntry:
    return PickupEntry(
        name=prime_items.ARTIFACT_NAMES[artifact_index],
        resources=(ConditionalResources(
            None, None,
            tuple([(resource_database.get_item(
                prime_items.ARTIFACT_ITEMS[artifact_index]), 1),
                   (resource_database.item_percentage, 1)])), ),
        model_index=prime_items.ARTIFACT_MODEL[artifact_index],
        item_category=ItemCategory.TEMPLE_KEY,
        broad_category=ItemCategory.KEY,
        probability_offset=0.25,
    )
示例#20
0
def create_artifact(artifact_index: int,
                    resource_database: ResourceDatabase,
                    ) -> PickupEntry:
    return PickupEntry(
        name=prime_items.ARTIFACT_NAMES[artifact_index],
        progression=(
            (resource_database.get_item(prime_items.ARTIFACT_ITEMS[artifact_index]), 1),
        ),
        model=PickupModel(
            game=resource_database.game_enum,
            name=prime_items.ARTIFACT_MODEL[artifact_index],
        ),
        item_category=ItemCategory.TEMPLE_KEY,
        broad_category=ItemCategory.KEY,
        probability_offset=0.25,
    )
示例#21
0
def create_echoes_useless_pickup(
        resource_database: ResourceDatabase) -> PickupEntry:
    """
    Creates an Energy Transfer Module pickup.
    :param resource_database:
    :return:
    """
    return PickupEntry(
        name="Energy Transfer Module",
        progression=((resource_database.get_item(
            echoes_items.USELESS_PICKUP_ITEM), 1), ),
        model=PickupModel(
            game=resource_database.game_enum,
            name=echoes_items.USELESS_PICKUP_MODEL,
        ),
        item_category=USELESS_ITEM_CATEGORY,
        broad_category=USELESS_ITEM_CATEGORY,
    )
示例#22
0
def create_sky_temple_key(key_number: int,
                          resource_database: ResourceDatabase,
                          ) -> PickupEntry:
    """

    :param key_number:
    :param resource_database:
    :return:
    """

    return PickupEntry(
        name="Sky Temple Key {}".format(key_number + 1),
        progression=((resource_database.get_item(echoes_items.SKY_TEMPLE_KEY_ITEMS[key_number]), 1),),
        model=PickupModel(
            game=resource_database.game_enum,
            name=echoes_items.SKY_TEMPLE_KEY_MODEL,
        ),
        item_category=ItemCategory.SKY_TEMPLE_KEY,
        broad_category=ItemCategory.KEY,
        probability_offset=3,
    )
示例#23
0
def create_dark_temple_key(key_number: int,
                           temple_index: int,
                           resource_database: ResourceDatabase,
                           ) -> PickupEntry:
    """
    Creates a Dark Temple Key
    :param key_number:
    :param temple_index: The index of the temple: Dark Agon, Dark Torvus, Hive Temple
    :param resource_database:
    :return:
    """

    return PickupEntry(
        name=echoes_items.DARK_TEMPLE_KEY_NAMES[temple_index].format(key_number + 1),
        progression=((resource_database.get_item(echoes_items.DARK_TEMPLE_KEY_ITEMS[temple_index][key_number]), 1),),
        model=PickupModel(
            game=resource_database.game_enum,
            name=echoes_items.DARK_TEMPLE_KEY_MODEL,
        ),
        item_category=ItemCategory.TEMPLE_KEY,
        broad_category=ItemCategory.KEY,
        probability_offset=3,
    )
示例#24
0
def create_dark_temple_key(
    key_number: int,
    temple_index: int,
    resource_database: ResourceDatabase,
) -> PickupEntry:
    """
    Creates a Dark Temple Key
    :param key_number:
    :param temple_index: The index of the temple: Dark Agon, Dark Torvus, Hive Temple
    :param resource_database:
    :return:
    """

    return PickupEntry(
        name=DARK_TEMPLE_KEY_NAMES[temple_index].format(key_number + 1),
        resources=(ConditionalResources(
            None, None,
            tuple([(resource_database.get_item(
                DARK_TEMPLE_KEY_ITEMS[temple_index][key_number]), 1)])), ),
        model_index=DARK_TEMPLE_KEY_MODEL,
        item_category=ItemCategory.TEMPLE_KEY,
        broad_category=ItemCategory.KEY,
        probability_offset=3,
    )
示例#25
0
def create_sky_temple_key(
    key_number: int,
    resource_database: ResourceDatabase,
) -> PickupEntry:
    """

    :param key_number:
    :param resource_database:
    :return:
    """

    return PickupEntry(
        name="Sky Temple Key {}".format(key_number + 1),
        resources=(ConditionalResources(
            None, None,
            tuple([
                (resource_database.get_item(SKY_TEMPLE_KEY_ITEMS[key_number]),
                 1)
            ])), ),
        model_index=SKY_TEMPLE_KEY_MODEL,
        item_category=ItemCategory.SKY_TEMPLE_KEY,
        broad_category=ItemCategory.KEY,
        probability_offset=3,
    )
示例#26
0
def create_major_item(
    item: MajorItem,
    state: MajorItemState,
    include_percentage: bool,
    resource_database: ResourceDatabase,
    ammo: Optional[Ammo],
    ammo_requires_major_item: bool,
) -> PickupEntry:
    """
    Creates a Pickup for the given MajorItem
    :param include_percentage:
    :param state:
    :param item:
    :param resource_database:
    :param ammo:
    :param ammo_requires_major_item:
    :return:
    """
    def _create_resources(
            base_resource: Optional[int],
            temporary_ammo: bool = False) -> Tuple[ResourceQuantity, ...]:
        resources = []

        if base_resource is not None:
            resources.append((resource_database.get_item(base_resource), 1))

        for ammo_index, ammo_count in zip(
                ammo.temporaries if temporary_ammo else item.ammo_index,
                state.included_ammo):
            resources.append(
                (resource_database.get_item(ammo_index), ammo_count))

        if include_percentage:
            resources.append((resource_database.item_percentage, 1))

        return tuple(resources)

    if item.progression:
        if ammo_requires_major_item and ammo.unlocked_by != item.progression[
                0] and ammo.unlocked_by is not None:
            if len(item.progression) != 1:
                raise InvalidConfiguration((
                    "Item {item.name} uses ammo {ammo.name} that is locked behind {ammo.unlocked_by},"
                    "but it also has progression. This is unsupported."
                ).format(
                    ammo=ammo,
                    item=item,
                ))

            name = resource_database.get_item(item.progression[0]).long_name
            conditional_resources = (ConditionalResources(
                name=name,
                item=None,
                resources=_create_resources(item.progression[0], True)),
                                     ConditionalResources(
                                         name=name,
                                         item=resource_database.get_item(
                                             ammo.unlocked_by),
                                         resources=_create_resources(
                                             item.progression[0])))
        else:
            conditional_resources = tuple(
                ConditionalResources(
                    name=resource_database.get_item(
                        item.progression[i]).long_name,
                    item=resource_database.get_item(item.progression[i - 1]
                                                    ) if i > 0 else None,
                    resources=_create_resources(progression))
                for i, progression in enumerate(item.progression))
    else:
        conditional_resources = (ConditionalResources(
            name=item.name, item=None, resources=_create_resources(None)), )

    if item.converts_indices:
        assert len(item.converts_indices) == len(item.ammo_index)
        convert_resources = tuple(
            ResourceConversion(
                source=resource_database.get_item(source),
                target=resource_database.get_item(target),
            )
            for source, target in zip(item.converts_indices, item.ammo_index))
    else:
        convert_resources = tuple()

    return PickupEntry(
        name=item.name,
        resources=conditional_resources,
        model_index=item.model_index,
        item_category=item.item_category,
        broad_category=item.broad_category,
        probability_offset=item.probability_offset,
        probability_multiplier=item.probability_multiplier,
        convert_resources=convert_resources,
    )