예제 #1
0
    def bit_pack_unpack(cls, decoder: BitPackDecoder, database: ResourceDatabase) -> PickupEntry:
        helper = DatabaseBitPackHelper(database)

        name = bitpacking.decode_string(decoder)
        model = PickupModel(
            game=RandovaniaGame.bit_pack_unpack(decoder, {}),
            name=bitpacking.decode_string(decoder),
        )
        item_category = ItemCategory.bit_pack_unpack(decoder, {})
        broad_category = ItemCategory.bit_pack_unpack(decoder, {})
        progression = bitpacking.decode_tuple(decoder, helper.decode_resource_quantity)
        extra_resources = bitpacking.decode_tuple(decoder, helper.decode_resource_quantity)
        unlocks_resource = bitpacking.decode_bool(decoder)
        resource_lock = None
        if bitpacking.decode_bool(decoder):
            resource_lock = helper.decode_resource_lock(decoder)
        respects_lock = bitpacking.decode_bool(decoder)
        probability_offset = BitPackFloat.bit_pack_unpack(decoder, _PROBABILITY_OFFSET_META)
        probability_multiplier = BitPackFloat.bit_pack_unpack(decoder, _PROBABILITY_MULTIPLIER_META)

        return PickupEntry(
            name=name,
            model=model,
            item_category=item_category,
            broad_category=broad_category,
            progression=progression,
            extra_resources=extra_resources,
            unlocks_resource=unlocks_resource,
            resource_lock=resource_lock,
            respects_lock=respects_lock,
            probability_offset=probability_offset,
            probability_multiplier=probability_multiplier,
        )
예제 #2
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,
        )
예제 #3
0
def _state_with_data(request):
    item = MajorItem(
        name="Item Name",
        item_category=ItemCategory(request.param.get("category", "visor")),
        broad_category=ItemCategory(
            request.param.get("broad_category", "visor")),
        model_name="Model Name",
        progression=(),
        ammo_index=request.param.get("ammo_index", ()),
        required=True,
        original_index=None,
        probability_offset=0,
    )
    return item, request.param["encoded"], MajorItemState.from_json(
        request.param["json"])
예제 #4
0
 def from_json(cls, name: str, value: dict) -> "MajorItem":
     return cls(
         name=name,
         item_category=ItemCategory(value["item_category"]),
         broad_category=ItemCategory(value["broad_category"]),
         model_name=value["model_name"],
         progression=tuple(value["progression"]),
         ammo_index=tuple(value.get("ammo", [])),
         unlocks_ammo=value.get("unlocks_ammo", False),
         required=value.get("required", False),
         original_index=PickupIndex(value["original_index"])
         if "original_index" in value else None,
         probability_offset=value["probability_offset"],
         probability_multiplier=value["probability_multiplier"],
         warning=value.get("warning"),
     )
예제 #5
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,
    )
예제 #6
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,
    )
예제 #7
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,
    )
예제 #8
0
def read_database(
    major_items_data: Dict,
    ammo_data: Dict,
) -> ItemDatabase:
    """

    :param major_items_data:
    :param ammo_data:
    :return:
    """
    major_items = {
        name: MajorItem.from_json(name, value)
        for name, value in major_items_data["items"].items()
    }

    ammo = {
        name: Ammo.from_json(name, value)
        for name, value in ammo_data.items()
    }

    default_items = {
        ItemCategory(category_name):
        tuple(major_items[item_name] for item_name in value)
        for category_name, value in major_items_data["default_items"].items()
    }

    return ItemDatabase(major_items, ammo, default_items)
예제 #9
0
def generic_item_category() -> ItemCategory:
    return ItemCategory(
        name="generic",
        long_name="Generic Item Category",
        hint_details=("an ", "unspecified item"),
        is_major=False
    )
예제 #10
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,
    )
예제 #11
0
def read_database(database_data: Dict, game: RandovaniaGame) -> ItemDatabase:
    """
    :param database_data:
    :param game:
    :return:
    """
    migrations.migrate_current(database_data)

    item_categories = {
        name: ItemCategory.from_json(name, value)
        for name, value in database_data["item_categories"].items()
    }

    major_items = {
        name: MajorItem.from_json(name, value, game, item_categories)
        for name, value in database_data["items"].items()
    }

    ammo = {
        name: Ammo.from_json(name, value, game, item_categories)
        for name, value in database_data["ammo"].items()
    }

    default_items = {
        item_categories[category_name]:
        tuple(major_items[item_name] for item_name in value)
        for category_name, value in database_data["default_items"].items()
    }

    return ItemDatabase(item_categories, major_items, ammo, default_items)
예제 #12
0
def _decode_item_category(decoder: BitPackDecoder) -> ItemCategory:
    return ItemCategory(name=bitpacking.decode_string(decoder),
                        long_name=bitpacking.decode_string(decoder),
                        hint_details=(bitpacking.decode_string(decoder),
                                      bitpacking.decode_string(decoder)),
                        is_major=bitpacking.decode_bool(decoder),
                        is_key=bitpacking.decode_bool(decoder))
예제 #13
0
 def from_json(cls, name: str, value: dict) -> "Ammo":
     return cls(
         name=name,
         maximum=value["maximum"],
         models=tuple(value["models"]),
         items=tuple(value["items"]),
         broad_category=ItemCategory(value["broad_category"]),
         unlocked_by=value.get("unlocked_by"),
         temporaries=tuple(value.get("temporaries", [])),
     )
예제 #14
0
 def from_json(cls, name: str, value: dict) -> "MajorItem":
     return cls(
         name=name,
         item_category=ItemCategory(value["item_category"]),
         model_index=value["model_index"],
         progression=tuple(value["progression"]),
         ammo_index=tuple(value.get("ammo", [])),
         converts_indices=tuple(value.get("converts_indices", [])),
         required=value.get("required", False),
         original_index=PickupIndex(value["original_index"])
         if "original_index" in value else None,
         probability_offset=value["probability_offset"],
     )
예제 #15
0
            "model_name": self.model_name,
            "items": frozen_lib.unwrap(self.items),
            "broad_category": self.broad_category.name,
            "extra": frozen_lib.unwrap(self.extra),
        }
        if self.unlocked_by is not None:
            result["temporary"] = self.temporary
            result["unlocked_by"] = self.unlocked_by
        return result

    @property
    def item_category(self) -> ItemCategory:
        return AMMO_ITEM_CATEGORY

    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


AMMO_ITEM_CATEGORY = ItemCategory(
    name="expansion",
    long_name="",
    hint_details=("an ", "expansion"),
    is_major=False
)
예제 #16
0
def test_create_pickup_for(percentage: bool, echoes_item_database,
                           echoes_resource_database, generic_item_category):
    # Setup
    item_a = echoes_resource_database.get_item("DarkVisor")
    item_b = echoes_resource_database.get_item("MorphBall")
    item_c = echoes_resource_database.get_item("Bombs")
    ammo_a = echoes_resource_database.get_item("EnergyTank")
    ammo_b = echoes_resource_database.get_item("DarkAmmo")

    less_generic_item_category = ItemCategory(name="the_category",
                                              long_name="The Category",
                                              hint_details=("a ",
                                                            " wonderful item"),
                                              is_major=True)

    major_item = MajorItem(
        game=echoes_resource_database.game_enum,
        name="The Item",
        item_category=less_generic_item_category,
        broad_category=generic_item_category,
        model_name="SuperModel",
        progression=("DarkVisor", "MorphBall", "Bombs"),
        default_starting_count=0,
        default_shuffled_count=1,
        ammo_index=("EnergyTank", "DarkAmmo"),
        must_be_starting=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),
    )

    if percentage:
        extra_resources = (
            (ammo_a, 10),
            (ammo_b, 20),
            (echoes_resource_database.item_percentage, 1),
        )
    else:
        extra_resources = (
            (ammo_a, 10),
            (ammo_b, 20),
        )

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

    # Assert
    assert result == PickupEntry(
        name="The Item",
        model=PickupModel(echoes_resource_database.game_enum, "SuperModel"),
        progression=(
            (item_a, 1),
            (item_b, 1),
            (item_c, 1),
        ),
        extra_resources=extra_resources,
        item_category=less_generic_item_category,
        broad_category=generic_item_category,
        probability_offset=5,
        respects_lock=False,
    )