Exemplo n.º 1
0
    def bit_pack_unpack(cls, decoder: BitPackDecoder, name: str,
                        database: ResourceDatabase) -> PickupEntry:
        model_index = decoder.decode_single(255)
        probability_offset = BitPackFloat.bit_pack_unpack(
            decoder, _PROBABILITY_OFFSET_META)
        probability_multiplier = BitPackFloat.bit_pack_unpack(
            decoder, _PROBABILITY_MULTIPLIER_META)
        item_category = ItemCategory.bit_pack_unpack(decoder, {})
        broad_category = ItemCategory.bit_pack_unpack(decoder, {})
        has_name = bitpacking.decode_bool(decoder)
        num_conditional = decoder.decode_single(
            MAXIMUM_PICKUP_CONDITIONAL_RESOURCES) + 1

        conditional_resources = []
        for i in range(num_conditional):
            item_name = None  # TODO: get the first resource name
            if i > 0:
                item_dependency = decoder.decode_element(database.item)
            else:
                item_dependency = None

            resources = []
            for _ in range(decoder.decode_single(MAXIMUM_PICKUP_RESOURCES +
                                                 1)):
                resource = decoder.decode_element(database.item)
                quantity = decoder.decode_single(255)
                resources.append((resource, quantity))

            if has_name:
                if bitpacking.decode_bool(decoder):
                    item_name = name
                else:
                    item_name = resources[0][0].long_name

            conditional_resources.append(
                ConditionalResources(
                    name=item_name,
                    item=item_dependency,
                    resources=tuple(resources),
                ))

        num_convert = decoder.decode_single(MAXIMUM_PICKUP_CONVERSION + 1)
        convert_resources = []
        for i in range(num_convert):
            source = decoder.decode_element(database.item)
            target = decoder.decode_element(database.item)
            convert_resources.append(ResourceConversion(source, target))

        return PickupEntry(
            name=name,
            model_index=model_index,
            item_category=item_category,
            broad_category=broad_category,
            resources=tuple(conditional_resources),
            convert_resources=tuple(convert_resources),
            probability_offset=probability_offset,
            probability_multiplier=probability_multiplier,
        )
def test_bit_pack_pickup_entry(has_convert: bool, echoes_resource_database):
    # Setup
    name = "Some Random Name"
    if has_convert:
        convert_resources = (ResourceConversion(
            find_resource_info_with_long_name(echoes_resource_database.item,
                                              "Morph Ball"),
            find_resource_info_with_long_name(echoes_resource_database.item,
                                              "Item Percentage")), )
    else:
        convert_resources = ()

    pickup = PickupEntry(
        name=name,
        model_index=26,
        item_category=ItemCategory.TEMPLE_KEY,
        broad_category=ItemCategory.KEY,
        resources=(ConditionalResources(
            "Morph Ball",
            None,
            (
                (find_resource_info_with_long_name(
                    echoes_resource_database.item, "Morph Ball"), 2),
                (find_resource_info_with_long_name(
                    echoes_resource_database.item, "Item Percentage"), 5),
            ),
        ),
                   ConditionalResources(
                       "Grapple Beam",
                       find_resource_info_with_long_name(
                           echoes_resource_database.item, "Morph Ball"),
                       ((find_resource_info_with_long_name(
                           echoes_resource_database.item,
                           "Grapple Beam"), 3), ),
                   )),
        convert_resources=convert_resources)

    # Run
    encoded = bitpacking.pack_value(
        BitPackPickupEntry(pickup, echoes_resource_database))
    decoder = BitPackDecoder(encoded)
    decoded = BitPackPickupEntry.bit_pack_unpack(decoder, name,
                                                 echoes_resource_database)

    # Assert
    assert pickup == decoded
Exemplo n.º 3
0
def test_add_resource_gain_to_current_resources_convert():
    # Setup
    resource_a = SimpleResourceInfo(1, "A", "A", ResourceType.ITEM)
    resource_b = SimpleResourceInfo(2, "B", "B", ResourceType.ITEM)

    pickup = PickupEntry(name="P1",
                         model_index=1,
                         item_category=ItemCategory.SUIT,
                         resources=(ConditionalResources(None, None, ()), ),
                         convert_resources=(ResourceConversion(
                             resource_a, resource_b), ))
    current_resources = {resource_a: 5}

    # Run
    add_resource_gain_to_current_resources(
        pickup.resource_gain(current_resources), current_resources)

    # Assert
    assert current_resources == {resource_a: 0, resource_b: 5}
def test_create_missile_launcher(ammo_quantity: int, echoes_item_database,
                                 echoes_resource_database):
    # Setup
    missile = echoes_resource_database.get_by_type_and_index(
        ResourceType.ITEM, 44)
    missile_launcher = echoes_resource_database.get_by_type_and_index(
        ResourceType.ITEM, 73)
    temporary = echoes_resource_database.get_by_type_and_index(
        ResourceType.ITEM, 71)

    state = MajorItemState(
        include_copy_in_original_location=False,
        num_shuffled_pickups=0,
        num_included_in_starting_items=0,
        included_ammo=(ammo_quantity, ),
    )

    # Run
    result = randovania.generator.item_pool.pickup_creator.create_major_item(
        echoes_item_database.major_items["Missile Launcher"], state, True,
        echoes_resource_database,
        echoes_item_database.ammo["Missile Expansion"], True)

    # Assert
    assert result == PickupEntry(
        name="Missile Launcher",
        resources=(ConditionalResources(
            "Missile Launcher",
            None,
            resources=(
                (missile_launcher, 1),
                (missile, ammo_quantity),
                (echoes_resource_database.item_percentage, 1),
            )), ),
        convert_resources=(ResourceConversion(source=temporary,
                                              target=missile), ),
        model_index=24,
        item_category=ItemCategory.MISSILE,
    )
Exemplo n.º 5
0
def test_assign_pickup_to_starting_items(empty_patches, database):
    # Setup

    starting = state.State({}, (), 99, None, empty_patches, None, database)

    resource_a = SimpleResourceInfo(1, "A", "A", ResourceType.ITEM)
    resource_b = SimpleResourceInfo(2, "B", "B", ResourceType.ITEM)
    p = PickupEntry("A",
                    2,
                    ItemCategory.SUIT,
                    resources=(ConditionalResources(None, None, (
                        (resource_a, 5),
                        (database.item_percentage, 1),
                    )), ),
                    convert_resources=(ResourceConversion(
                        resource_b, resource_a), ))

    # Run
    final = starting.assign_pickup_to_starting_items(p)

    # Assert
    assert final.patches.starting_items == {resource_a: 5, resource_b: 0}
    assert final.resources == {resource_a: 5, resource_b: 0}
def test_create_pickup_for(percentage: bool, has_convert: bool,
                           echoes_resource_database):
    # Setup
    item_a = echoes_resource_database.get_by_type_and_index(
        ResourceType.ITEM, 10)
    item_b = echoes_resource_database.get_by_type_and_index(
        ResourceType.ITEM, 15)
    item_c = echoes_resource_database.get_by_type_and_index(
        ResourceType.ITEM, 18)
    ammo_a = echoes_resource_database.get_by_type_and_index(
        ResourceType.ITEM, 40)
    ammo_b = echoes_resource_database.get_by_type_and_index(
        ResourceType.ITEM, 42)
    temporary_a = echoes_resource_database.get_by_type_and_index(
        ResourceType.ITEM, 71)
    temporary_b = echoes_resource_database.get_by_type_and_index(
        ResourceType.ITEM, 72)

    major_item = MajorItem(
        name="The Item",
        item_category=ItemCategory.MORPH_BALL,
        model_index=1337,
        progression=(10, 15, 18),
        ammo_index=(40, 42),
        converts_indices=(71, 72) if has_convert else (),
        required=False,
        original_index=None,
        probability_offset=5,
    )
    state = MajorItemState(
        include_copy_in_original_location=False,
        num_shuffled_pickups=0,
        num_included_in_starting_items=0,
        included_ammo=(10, 20),
    )

    def _create_resources(item):
        if percentage:
            return (
                (item, 1),
                (ammo_a, 10),
                (ammo_b, 20),
                (echoes_resource_database.item_percentage, 1),
            )
        else:
            return (
                (item, 1),
                (ammo_a, 10),
                (ammo_b, 20),
            )

    # Run
    result = randovania.generator.item_pool.pickup_creator.create_major_item(
        major_item, state, percentage, echoes_resource_database, None, False)

    # Assert
    assert result == PickupEntry(
        name="The Item",
        model_index=1337,
        resources=(
            ConditionalResources(
                name="Dark Visor",
                item=None,
                resources=_create_resources(item_a),
            ),
            ConditionalResources(
                name="Morph Ball",
                item=item_a,
                resources=_create_resources(item_b),
            ),
            ConditionalResources(
                name="Morph Ball Bomb",
                item=item_b,
                resources=_create_resources(item_c),
            ),
        ),
        convert_resources=(
            ResourceConversion(source=temporary_a, target=ammo_a),
            ResourceConversion(source=temporary_b, target=ammo_b),
        ) if has_convert else (),
        item_category=ItemCategory.MORPH_BALL,
        probability_offset=5,
    )
Exemplo n.º 7
0
def test_create_pickup_list(model_style: PickupModelStyle, empty_patches):
    # Setup
    has_scan_text = model_style in {PickupModelStyle.ALL_VISIBLE, PickupModelStyle.HIDE_MODEL}
    rng = Random(5000)

    useless_resource = SimpleResourceInfo(0, "Useless", "Useless", ResourceType.ITEM)
    resource_a = SimpleResourceInfo(1, "A", "A", ResourceType.ITEM)
    resource_b = SimpleResourceInfo(2, "B", "B", ResourceType.ITEM)
    pickup_a = PickupEntry("A", 1, ItemCategory.TEMPLE_KEY,
                           (
                               ConditionalResources(None, None, ((resource_a, 1),)),
                           ))
    pickup_b = PickupEntry("B", 2, ItemCategory.SUIT,
                           (
                               ConditionalResources(None, None, ((resource_b, 1), (resource_a, 1))),
                               ConditionalResources(None, resource_b, ((resource_a, 5),))
                           ))
    pickup_c = PickupEntry("C", 2, ItemCategory.EXPANSION,
                           resources=(
                               ConditionalResources(None, None, ((resource_b, 2), (resource_a, 1))),
                           ),
                           convert_resources=(
                               ResourceConversion(useless_resource, resource_a),
                           ))

    useless_pickup = PickupEntry("Useless", 0, ItemCategory.ETM,
                                 (
                                     ConditionalResources(None, None, ((useless_resource, 1),)),
                                 ))
    patches = empty_patches.assign_pickup_assignment({
        PickupIndex(0): pickup_a,
        PickupIndex(2): pickup_b,
        PickupIndex(3): pickup_a,
        PickupIndex(4): pickup_c,
    })

    # Run
    result = patcher_file._create_pickup_list(patches, useless_pickup, 5,
                                              rng,
                                              model_style,
                                              PickupModelDataSource.ETM,
                                              None,
                                              )

    # Assert
    assert len(result) == 5
    assert result[0] == {
        "pickup_index": 0,
        "model_index": 1 if model_style == PickupModelStyle.ALL_VISIBLE else 30,
        "scan": "A" if has_scan_text else "Unknown item",
        "hud_text": ["A acquired!"] if model_style != PickupModelStyle.HIDE_ALL else ['Unknown item acquired!'],
        "sound_index": 1 if model_style == PickupModelStyle.ALL_VISIBLE else 0,
        "jingle_index": 2 if model_style == PickupModelStyle.ALL_VISIBLE else 0,
        "resources": [
            {
                "index": 1,
                "amount": 1
            }
        ],
        "conditional_resources": [],
        "convert": [],
    }
    assert result[1] == {
        "pickup_index": 1,
        "scan": "Useless" if has_scan_text else "Unknown item",
        "model_index": 0 if model_style == PickupModelStyle.ALL_VISIBLE else 30,
        "hud_text": ["Useless acquired!"] if model_style != PickupModelStyle.HIDE_ALL else ['Unknown item acquired!'],
        "sound_index": 0,
        "jingle_index": 0,
        "resources": [
            {
                "index": 0,
                "amount": 1
            }
        ],
        "conditional_resources": [],
        "convert": [],
    }
    assert result[2] == {
        "pickup_index": 2,
        "scan": "B" if has_scan_text else "Unknown item",
        "model_index": 2 if model_style == PickupModelStyle.ALL_VISIBLE else 30,
        "hud_text": ["B acquired!", "B acquired!"] if model_style != PickupModelStyle.HIDE_ALL else [
            'Unknown item acquired!', 'Unknown item acquired!'],
        "sound_index": 0,
        "jingle_index": 1 if model_style == PickupModelStyle.ALL_VISIBLE else 0,
        "resources": [
            {
                "index": 2,
                "amount": 1
            },
            {
                "index": 1,
                "amount": 1
            }
        ],
        "conditional_resources": [{
            "item": 2,
            "resources": [
                {
                    "index": 1,
                    "amount": 5
                }
            ]
        }],
        "convert": [],
    }
    assert result[3] == {
        "pickup_index": 3,
        "scan": "A" if has_scan_text else "Unknown item",
        "model_index": 1 if model_style == PickupModelStyle.ALL_VISIBLE else 30,
        "hud_text": ["A acquired!"] if model_style != PickupModelStyle.HIDE_ALL else ['Unknown item acquired!'],
        "sound_index": 1 if model_style == PickupModelStyle.ALL_VISIBLE else 0,
        "jingle_index": 2 if model_style == PickupModelStyle.ALL_VISIBLE else 0,
        "resources": [
            {
                "index": 1,
                "amount": 1
            }
        ],
        "conditional_resources": [],
        "convert": [],
    }
    assert result[4] == {
        "pickup_index": 4,
        "scan": "C that provides 2 B and 1 A" if has_scan_text else "Unknown item",
        "model_index": 2 if model_style == PickupModelStyle.ALL_VISIBLE else 30,
        "hud_text": ["C acquired!"] if model_style != PickupModelStyle.HIDE_ALL else ['Unknown item acquired!'],
        "sound_index": 0,
        "jingle_index": 0,
        "resources": [
            {
                "index": 2,
                "amount": 2
            },
            {
                "index": 1,
                "amount": 1
            }
        ],
        "conditional_resources": [],
        "convert": [
            {
                "from_item": 0,
                "to_item": 1,
                "clear_source": True,
                "overwrite_target": False,
            }
        ],
    }
Exemplo n.º 8
0
def test_create_pickup_list(model_style: PickupModelStyle, empty_patches):
    # Setup
    has_scan_text = model_style in {
        PickupModelStyle.ALL_VISIBLE, PickupModelStyle.HIDE_MODEL
    }
    rng = Random(5000)

    model_0 = MagicMock(spec=PickupModel)
    model_1 = MagicMock(spec=PickupModel)
    model_2 = MagicMock(spec=PickupModel)
    useless_model = PickupModel(
        game=RandovaniaGame.PRIME2,
        name="EnergyTransferModule",
    )

    useless_resource = ItemResourceInfo(0, "Useless", "Useless", 10, None)
    resource_a = ItemResourceInfo(1, "A", "A", 10, None)
    resource_b = ItemResourceInfo(2, "B", "B", 10, None)
    pickup_a = PickupEntry(
        "P-A",
        model_1,
        ItemCategory.TEMPLE_KEY,
        ItemCategory.KEY,
        progression=((resource_a, 1), ),
    )
    pickup_b = PickupEntry(
        "P-B",
        model_2,
        ItemCategory.SUIT,
        ItemCategory.LIFE_SUPPORT,
        progression=((resource_b, 1), (resource_a, 5)),
    )
    pickup_c = PickupEntry("P-C",
                           model_2,
                           ItemCategory.EXPANSION,
                           ItemCategory.MISSILE_RELATED,
                           progression=tuple(),
                           extra_resources=((resource_b, 2), (resource_a, 1)),
                           unlocks_resource=True,
                           resource_lock=ResourceLock(resource_a, resource_a,
                                                      useless_resource))

    useless_pickup = PickupEntry("P-Useless",
                                 model_0,
                                 ItemCategory.ETM,
                                 ItemCategory.ETM,
                                 progression=((useless_resource, 1), ))
    patches = empty_patches.assign_pickup_assignment({
        PickupIndex(0):
        PickupTarget(pickup_a, 0),
        PickupIndex(2):
        PickupTarget(pickup_b, 0),
        PickupIndex(3):
        PickupTarget(pickup_a, 0),
        PickupIndex(4):
        PickupTarget(pickup_c, 0),
    })
    creator = pickup_exporter.PickupExporterSolo(
        pickup_exporter.GenericAcquiredMemo())

    # Run
    result = pickup_exporter.export_all_indices(
        patches,
        PickupTarget(useless_pickup, 0),
        5,
        rng,
        model_style,
        PickupModelDataSource.ETM,
        creator,
        pickup_creator.create_visual_etm(),
    )

    # Assert
    assert len(result) == 5
    assert result[0] == pickup_exporter.ExportedPickupDetails(
        index=PickupIndex(0),
        scan_text="P-A" if has_scan_text else "Unknown item",
        hud_text=["A acquired!"] if model_style != PickupModelStyle.HIDE_ALL
        else ['Unknown item acquired!'],
        conditional_resources=[
            ConditionalResources("A", None, ((resource_a, 1), ))
        ],
        conversion=[],
        model=model_1
        if model_style == PickupModelStyle.ALL_VISIBLE else useless_model,
    )
    assert result[1] == pickup_exporter.ExportedPickupDetails(
        index=PickupIndex(1),
        scan_text="P-Useless" if has_scan_text else "Unknown item",
        hud_text=["Useless acquired!"]
        if model_style != PickupModelStyle.HIDE_ALL else
        ['Unknown item acquired!'],
        conditional_resources=[
            ConditionalResources("Useless", None, ((useless_resource, 1), ))
        ],
        conversion=[],
        model=model_0
        if model_style == PickupModelStyle.ALL_VISIBLE else useless_model,
    )
    assert result[2] == pickup_exporter.ExportedPickupDetails(
        index=PickupIndex(2),
        scan_text="P-B. Provides the following in order: B, A"
        if has_scan_text else "Unknown item",
        hud_text=["B acquired!", "A acquired!"]
        if model_style != PickupModelStyle.HIDE_ALL else
        ['Unknown item acquired!', 'Unknown item acquired!'],
        conditional_resources=[
            ConditionalResources("B", None, ((resource_b, 1), )),
            ConditionalResources("A", resource_b, ((resource_a, 5), )),
        ],
        conversion=[],
        model=model_2
        if model_style == PickupModelStyle.ALL_VISIBLE else useless_model,
    )
    assert result[3] == pickup_exporter.ExportedPickupDetails(
        index=PickupIndex(3),
        scan_text="P-A" if has_scan_text else "Unknown item",
        hud_text=["A acquired!"] if model_style != PickupModelStyle.HIDE_ALL
        else ['Unknown item acquired!'],
        conditional_resources=[
            ConditionalResources("A", None, ((resource_a, 1), ))
        ],
        conversion=[],
        model=model_1
        if model_style == PickupModelStyle.ALL_VISIBLE else useless_model,
    )
    assert result[4] == pickup_exporter.ExportedPickupDetails(
        index=PickupIndex(4),
        scan_text="P-C. Provides 2 B and 1 A"
        if has_scan_text else "Unknown item",
        hud_text=["P-C acquired!"] if model_style != PickupModelStyle.HIDE_ALL
        else ['Unknown item acquired!'],
        conditional_resources=[
            ConditionalResources("P-C", None, (
                (resource_b, 2),
                (resource_a, 1),
            ))
        ],
        conversion=[
            ResourceConversion(source=useless_resource, target=resource_a)
        ],
        model=model_2
        if model_style == PickupModelStyle.ALL_VISIBLE else useless_model,
    )
Exemplo n.º 9
0
 def decode_resource_conversion(self, decoder: BitPackDecoder) -> ResourceConversion:
     return ResourceConversion(
         source=self._decode_item(decoder),
         target=self._decode_item(decoder),
     )
Exemplo n.º 10
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,
    )
Exemplo n.º 11
0
def test_create_pickup_list(model_style: PickupModelStyle, empty_patches, generic_item_category,
                            blank_resource_db):
    # Setup
    has_scan_text = model_style in {PickupModelStyle.ALL_VISIBLE, PickupModelStyle.HIDE_MODEL}
    rng = Random(5000)

    model_0 = MagicMock(spec=PickupModel)
    model_1 = MagicMock(spec=PickupModel)
    model_2 = MagicMock(spec=PickupModel)
    useless_model = PickupModel(
        game=RandovaniaGame.METROID_PRIME_ECHOES,
        name="EnergyTransferModule",
    )

    useless_resource =  ItemResourceInfo(0, "Useless", "Useless", 10)
    resource_a = ItemResourceInfo(1, "A", "A", 10)
    resource_b = ItemResourceInfo(2, "B", "B", 10)
    pickup_a = PickupEntry("P-A", model_1, generic_item_category, generic_item_category,
                           progression=((resource_a, 1),),
                           )
    pickup_b = PickupEntry("P-B", model_2, generic_item_category, generic_item_category,
                           progression=((resource_b, 1),
                                        (resource_a, 5)), )
    pickup_c = PickupEntry("P-C", model_2, AMMO_ITEM_CATEGORY, generic_item_category,
                           progression=tuple(),
                           extra_resources=((resource_b, 2), (resource_a, 1)),
                           unlocks_resource=True,
                           resource_lock=ResourceLock(resource_a, resource_a, useless_resource))

    useless_pickup = PickupEntry("P-Useless", model_0, USELESS_ITEM_CATEGORY, USELESS_ITEM_CATEGORY,
                                 progression=((useless_resource, 1),))
    patches = empty_patches.assign_new_pickups([
        (PickupIndex(0), PickupTarget(pickup_a, 0)),
        (PickupIndex(2), PickupTarget(pickup_b, 0)),
        (PickupIndex(3), PickupTarget(pickup_a, 0)),
        (PickupIndex(4), PickupTarget(pickup_c, 0)),
    ])
    creator = pickup_exporter.PickupExporterSolo(pickup_exporter.GenericAcquiredMemo())

    world_list = MagicMock()
    world_list.iterate_nodes.return_value = [
        PickupNode(NodeIdentifier.create("World", "Area", f"Name {i}"),
                   i, False, None, "", ("default",), {}, PickupIndex(i), False)
        for i in range(5)
    ]

    # Run
    result = pickup_exporter.export_all_indices(
        patches,
        PickupTarget(useless_pickup, 0),
        world_list,
        rng,
        model_style,
        PickupModelDataSource.ETM,
        creator,
        pickup_creator.create_visual_etm(),
    )

    # Assert
    assert len(result) == 5
    assert result[0] == pickup_exporter.ExportedPickupDetails(
        index=PickupIndex(0),
        scan_text="P-A" if has_scan_text else "Unknown item",
        hud_text=["A acquired!"] if model_style != PickupModelStyle.HIDE_ALL else ['Unknown item acquired!'],
        conditional_resources=[ConditionalResources("A", None, ((resource_a, 1),))],
        conversion=[],
        model=model_1 if model_style == PickupModelStyle.ALL_VISIBLE else useless_model,
        other_player=False,
        original_pickup=pickup_a,
    )
    assert result[1] == pickup_exporter.ExportedPickupDetails(
        index=PickupIndex(1),
        scan_text="P-Useless" if has_scan_text else "Unknown item",
        hud_text=["Useless acquired!"] if model_style != PickupModelStyle.HIDE_ALL else ['Unknown item acquired!'],
        conditional_resources=[ConditionalResources("Useless", None, ((useless_resource, 1),))],
        conversion=[],
        model=model_0 if model_style == PickupModelStyle.ALL_VISIBLE else useless_model,
        other_player=False,
        original_pickup=useless_pickup,
    )
    assert result[2] == pickup_exporter.ExportedPickupDetails(
        index=PickupIndex(2),
        scan_text="P-B. Provides the following in order: B, A" if has_scan_text else "Unknown item",
        hud_text=["B acquired!", "A acquired!"] if model_style != PickupModelStyle.HIDE_ALL else [
            'Unknown item acquired!', 'Unknown item acquired!'],
        conditional_resources=[
            ConditionalResources("B", None, ((resource_b, 1),)),
            ConditionalResources("A", resource_b, ((resource_a, 5),)),
        ],
        conversion=[],
        model=model_2 if model_style == PickupModelStyle.ALL_VISIBLE else useless_model,
        other_player=False,
        original_pickup=pickup_b,
    )
    assert result[3] == pickup_exporter.ExportedPickupDetails(
        index=PickupIndex(3),
        scan_text="P-A" if has_scan_text else "Unknown item",
        hud_text=["A acquired!"] if model_style != PickupModelStyle.HIDE_ALL else ['Unknown item acquired!'],
        conditional_resources=[ConditionalResources("A", None, ((resource_a, 1),))],
        conversion=[],
        model=model_1 if model_style == PickupModelStyle.ALL_VISIBLE else useless_model,
        other_player=False,
        original_pickup=pickup_a,
    )
    assert result[4] == pickup_exporter.ExportedPickupDetails(
        index=PickupIndex(4),
        scan_text="P-C. Provides 2 B and 1 A" if has_scan_text else "Unknown item",
        hud_text=["P-C acquired!"] if model_style != PickupModelStyle.HIDE_ALL else ['Unknown item acquired!'],
        conditional_resources=[ConditionalResources("P-C", None, (
            (resource_b, 2), (resource_a, 1),
        ))],
        conversion=[ResourceConversion(source=useless_resource, target=resource_a)],
        model=model_2 if model_style == PickupModelStyle.ALL_VISIBLE else useless_model,
        other_player=False,
        original_pickup=pickup_c,
    )