示例#1
0
    def pil_to_tiles_separate(self, images: List[Image.Image]) -> None:
        frames = []
        first_image_dims = None
        for image in images:
            frames.append(
                from_pil(image,
                         BPL_IMG_PAL_LEN,
                         BPL_MAX_PAL,
                         BPA_TILE_DIM,
                         image.width,
                         image.height,
                         optimize=False)[0])
            if first_image_dims is None:
                first_image_dims = (image.width, image.height)
            if (image.width, image.height) != first_image_dims:
                raise ValueError(
                    _("The dimensions of all images must be the same."))
        self.tiles = []
        self.number_of_frames = u16_checked(len(frames))
        self.number_of_tiles = u16_checked(
            int((images[0].height * images[0].width) /
                (BPA_TILE_DIM * BPA_TILE_DIM)))

        for tile in frames:
            self.tiles += tile

        self._correct_frame_info()
示例#2
0
    def pil_to_chunks(self,
                      layer: int,
                      image: Image.Image,
                      force_import: bool = True) -> List[List[int]]:
        """
        Imports chunks. Format same as for chunks_to_pil.
        Replaces tiles, tile mappings and therefor also chunks.
        "Unsets" BPA assignments! BPAs have to be manually re-assigned by using set_tile or set_chunk. BPA
        indices are stored after BPC tile indices.

        The PIL must have a palette containing the 16 sub-palettes with 16 colors each (256 colors).

        If a pixel in a tile uses a color outside of it's 16 color range, an error is thrown or
        the color is replaced with 0 of the palette (transparent). This is controlled by
        the force_import flag.

        Returns the palettes stored in the image for further processing (eg. replacing the BPL palettes).
        """
        self.layers[layer].tiles, self.layers[
            layer].tilemap, palettes = from_pil(image, BPL_IMG_PAL_LEN,
                                                BPL_MAX_PAL, BPC_TILE_DIM,
                                                image.width, image.height, 3,
                                                3, force_import)
        self.layers[layer].number_tiles = u16_checked(
            len(self.layers[layer].tiles) - 1)
        self.layers[layer].chunk_tilemap_len = u16_checked(
            int(
                len(self.layers[layer].tilemap) / self.tiling_width /
                self.tiling_height))
        return palettes  # type: ignore
示例#3
0
 def on_wtu_height_edited(self, widget, path, text):
     try:
         u16_checked(int(text))
     except ValueError:
         return
     wtu_store: Gtk.ListStore = self.builder.get_object('wtu_store')
     wtu_store[path][3] = text
     self._regenerate_wtu()
示例#4
0
    def _actions_to_bytes(self) -> bytes:
        actions: List[Tuple[FixedFloorActionRule,
                            int]] = shrink_list(self.actions)
        buffer = bytearray(4 * len(actions))

        for i, (action, n_times) in enumerate(actions):
            write_u16(buffer, u16_checked(int(action)), i * 4)
            write_u16(buffer, u16_checked(n_times - 1), i * 4 + 0x02)

        return buffer
示例#5
0
 def from_xml(cls, ele: Element) -> 'MappaMonster':
     validate_xml_tag(ele, XML_MONSTER)
     validate_xml_attribs(ele, [
         XML_MONSTER__LEVEL, XML_MONSTER__WEIGHT, XML_MONSTER__WEIGHT2, XML_MONSTER__MD_INDEX
     ])
     return cls(
         u8_checked(int(ele.get(XML_MONSTER__LEVEL))),
         u16_checked(int(ele.get(XML_MONSTER__WEIGHT))),
         u16_checked(int(ele.get(XML_MONSTER__WEIGHT2))),
         u16_checked(int(ele.get(XML_MONSTER__MD_INDEX))),
     )
示例#6
0
    def compress(cls, data: bytes) -> 'At4px':
        """Create a new AT4PX container from originally uncompressed data."""
        from skytemple_files.common.types.file_types import FileType

        new_container = cls()
        flags, px_data = FileType.PX.compress(data)

        new_container.compression_flags = flags
        new_container.length_decompressed = u16_checked(len(data))
        new_container.compressed_data = px_data
        new_container.length_compressed = u16_checked(len(px_data) + 0x12)
        return new_container
示例#7
0
 def on_cb_excl_parameter_changed(self, w, *args):
     try:
         val = u16_checked(int(w.get_text()))
     except ValueError:
         return
     assert self.item_sp is not None
     self.item_sp.parameter = val
示例#8
0
 def on_entry_move_id_changed(self, w, *args):
     try:
         val = u16_checked(int(w.get_text()))
     except ValueError:
         return
     self.item_p.move_id = val
     self.mark_as_modified()
示例#9
0
 def on_entry_base_power_changed(self, w, *args):
     try:
         val = u16_checked(int(w.get_text()))
     except ValueError:
         return
     self.move.base_power = val
     self.mark_as_modified()
    def apply(self, apply: Callable[[], None], rom: NintendoDSRom,
              config: Pmd2Data) -> None:
        if not self.is_applied(rom, config):
            if config.game_version == GAME_VERSION_EOS:
                if config.game_region == GAME_REGION_US:
                    bar_list = BAR_LIST_US
                if config.game_region == GAME_REGION_EU:
                    bar_list = BAR_LIST_EU
                if config.game_region == GAME_REGION_JP:
                    bar_list = BAR_LIST_JP

            data = rom.loadArm9Overlays([19])[19].data

            header = bytearray([0xFF] * (4 + 2 * NB_ITEMS))
            write_u32(header, u32(4 + 2 * NB_ITEMS), 0)
            list_data: List[bytes] = []
            for x in range(bar_list, bar_list + BAR_LIST_SIZE,
                           BAR_LIST_ENTRY_SIZE):
                item_id = read_u16(data, x)
                cdata = bytes(data[x + 2:x + BAR_LIST_ENTRY_SIZE])
                if cdata in list_data:
                    index = list_data.index(cdata)
                else:
                    index = len(list_data)
                    list_data.append(cdata)
                write_u16(header, u16_checked(index), 4 + 2 * item_id)
            file_data = header + b''.join(list_data)
            if ITEM_LIST_PATH not in rom.filenames:
                create_file_in_rom(rom, ITEM_LIST_PATH, file_data)
            else:
                rom.setFileByName(ITEM_LIST_PATH, file_data)
        try:
            apply()
        except RuntimeError as ex:
            raise ex
示例#11
0
    def on_cr_entity_edited(self, widget, path, text):
        match = PATTERN_MD_ENTRY.match(text)
        if match is None:
            return
        try:
            entid = u16_checked(int(match.group(1)))
        except ValueError:
            return
        idx = int(self._list_store[path][0])

        # Check, if this is a special entry,
        # in this case we update the standin entry!
        # TODO: it's a bit weird doing this over the color
        if self._list_store[path][8] == ORANGE:
            logger.debug(f"Updated standin for actor {idx}: {entid}")
            standins = self._sprite_provider.get_standin_entities()
            standins[idx] = entid
            self._sprite_provider.set_standin_entities(standins)

        # ent_name:
        try:
            self._list_store[path][7] = self._ent_names[entid]
        except KeyError as e:
            raise UserValueError(_("No Pokémon with this ID found."))

        # entid:
        self._list_store[path][4] = entid
        # ent_icon:
        # If color is orange it's special.
        # TODO: it's a bit weird doing this over the color
        self._list_store[path][3] = self._get_icon(
            entid, idx, self._list_store[path][8] == ORANGE)
示例#12
0
 def set_palettes(self, palettes: List[List[int]]) -> None:
     """Sets the palette properly, adding dummy grayscale entries if needed. """
     self.palettes = palettes
     self.number_palettes = u16_checked(len(palettes))
     while len(self.palettes) < BPL_MAX_PAL:
         self.palettes.append([(i // 3) * BPL_MAX_PAL
                               for i in range(BPL_MAX_PAL * 3)])
示例#13
0
 def on_entry_belly_lost_wtw_1000_changed(self, widget, *args):
     try:
         val = u16_checked(int(widget.get_text()))
     except ValueError:
         return
     static_data = self.module.project.get_rom_module().get_static_data()
     self.module.project.modify_binary(BinaryName.OVERLAY_29, lambda bin: HardcodedDungeonMisc.set_belly_loss_1000ile_walk_through_walls(val, bin, static_data))
     self.module.mark_misc_settings_as_modified()
示例#14
0
文件: iq.py 项目: SkyTemple/skytemple
 def on_intimidator_activation_chance_changed(self, widget, *args):
     try:
         val = u16_checked(int(widget.get_text()))
     except ValueError:
         return
     static_data = self.module.project.get_rom_module().get_static_data()
     self.module.project.modify_binary(BinaryName.OVERLAY_10, lambda bin: HardcodedIq.set_intimidator_chance(val, bin, static_data))
     self.module.mark_misc_settings_as_modified()
示例#15
0
 def on_id_description_edited(self, widget, path, text):
     try:
         tree_store: Gtk.ListStore = self.builder.get_object('tree_store')
         tree_store[path][2] = u16_checked(int(text))
     except ValueError:
         return
     
     self._regenerate_list()
示例#16
0
 def on_entry_stolen_spawn_delay_changed(self, widget, *args):
     try:
         val = u16_checked(int(widget.get_text()))
     except ValueError:
         return
     static_data = self.module.project.get_rom_module().get_static_data()
     self.module.project.modify_binary(BinaryName.OVERLAY_10, lambda bin: HardcodedSpawnRate.set_stolen_spawn_rate(val, bin, static_data))
     self.module.mark_misc_settings_as_modified()
示例#17
0
文件: iq.py 项目: SkyTemple/skytemple
 def on_entry_min_iq_item_master_changed(self, widget, *args):
     try:
         val = u16_checked(int(widget.get_text()))
     except ValueError:
         return
     static_data = self.module.project.get_rom_module().get_static_data()
     self.module.project.modify_binary(BinaryName.ARM9, lambda bin: HardcodedIq.set_min_iq_for_item_master(val, bin, static_data))
     self.module.mark_iq_as_modified()
示例#18
0
 def on_entry_ginseng_3_chance_changed(self, widget, *args):
     try:
         val = u16_checked(int(widget.get_text()))
     except ValueError:
         return
     static_data = self.module.project.get_rom_module().get_static_data()
     self.module.project.modify_binary(BinaryName.OVERLAY_10, lambda bin: HardcodedDungeonMisc.set_ginseng_increase_by_3_chance(val, bin, static_data))
     self.module.mark_misc_settings_as_modified()
示例#19
0
 def on_entry_life_seed_changed(self, widget, *args):
     try:
         val = u16_checked(int(widget.get_text()))
     except ValueError:
         return
     static_data = self.module.project.get_rom_module().get_static_data()
     self.module.project.modify_binary(BinaryName.OVERLAY_10, lambda bin: HardcodedHpItems.set_life_seed_hp(val, bin, static_data))
     self.module.mark_misc_settings_as_modified()
示例#20
0
    def compress(cls, data: bytes) -> 'BmaCollisionRleCompressionContainer':
        from skytemple_files.common.types.file_types import FileType

        new_container = cls()
        compressed_data = FileType.BMA_COLLISION_RLE.compress(data)

        new_container.length_decompressed = u16_checked(len(data))
        new_container.compressed_data = compressed_data
        return new_container
示例#21
0
 def on_cr_stats_unka_edited(self, widget, path, text):
     store: Gtk.Store = self.builder.get_object('model_stats')
     try:
         v = u16_checked(int(text))
     except ValueError:
         return
     store[path][8] = text
     self.lst_stats[int(store[path][0])].unkA = v
     self._save()
示例#22
0
 def on_cr_items_item_quantity_edited(self, widget, path, text):
     store: Gtk.Store = self.builder.get_object('model_items')
     try:
         quantity = u16_checked(int(text))
     except ValueError:
         return
     self.lst_item[int(store[path][0])].quantity = quantity
     store[path][3] = quantity
     self._save()
示例#23
0
    def compress(cls, data: bytes) -> 'GenericNrlCompressionContainer':
        from skytemple_files.common.types.file_types import FileType

        new_container = cls()
        compressed_data = FileType.GENERIC_NRL.compress(data)

        new_container.length_decompressed = u16_checked(len(data))
        new_container.compressed_data = compressed_data
        return new_container
示例#24
0
    def compress(cls, data: bytes) -> 'BpcTilemapCompressionContainer':
        from skytemple_files.common.types.file_types import FileType

        new_container = cls()
        compressed_data = FileType.BPC_TILEMAP.compress(data)

        new_container.length_decompressed = u16_checked(len(data))
        new_container.compressed_data = compressed_data
        return new_container
示例#25
0
 def to_bytes(self):
     mevo_data = bytearray(MEVO_ENTRY_LENGTH)
     write_u16(mevo_data, u16_checked(len(self.evos)), 0)
     for j, x in enumerate(self.evos):
         write_u16(mevo_data, x, j * 2 + 2)
     write_u8(mevo_data, u8_checked(len(self.eggs)), 0x12)
     for j, x in enumerate(self.eggs):
         write_u16(mevo_data, x, j * 2 + 0x14)
     return mevo_data
示例#26
0
    def from_pil(self, img: Image.Image, img_type: WteImageType,
                 discard_palette: bool) -> 'Wte':
        """ Replace the image data by the new one passed in argument. """
        if img.mode != 'P':
            raise AttributeError(
                _('Can not convert PIL image to WTE: Must be indexed image (=using a palette)'
                  ))

        if img_type.has_image:
            try:
                self._adjust_actual_dimensions(img.width, img.height)
            except ValueError:
                raise ValueError(
                    _('This image is too big to fit into a WTE file.'))

            self.width = u16_checked(img.width)
            self.height = u16_checked(img.height)
            dimensions = self.actual_dimensions()
        else:
            self.width = u16(0)
            self.height = u16(0)
            self.actual_dim = u8(0)

        self.image_type = img_type
        if self.image_type.has_image:
            raw_image = img.tobytes("raw", "P")
            self.image_data = bytearray(dimensions[0] // 8 * self.height *
                                        img_type.bpp)
            i = 0
            pixels_per_byte = 8 // img_type.bpp
            for pix in raw_image:
                b = (i % pixels_per_byte) * img_type.bpp
                x = i // pixels_per_byte
                self.image_data[x] += pix << b
                i += 1
                if i % dimensions[0] == self.width:
                    i += dimensions[0] - self.width
        else:
            self.image_data = bytearray(0)
        if discard_palette:
            self.palette = []
        else:
            self.palette = [x for x in memoryview(img.palette.palette)]
        return self
示例#27
0
    def to_bytes(self):
        """Convert the LSD back to bytes"""
        data = bytearray(2 + len(self.entries) * MAX_LEN)
        write_u16(data, u16_checked(len(self.entries)), 0)
        bytes_written = 2
        for e in self.entries:
            data[bytes_written:bytes_written + MAX_LEN] = self._str_to_bytes(e)
            bytes_written += MAX_LEN

        return data[:bytes_written]
示例#28
0
 def on_sp_effect_id_edited(self, widget, path, text):
     try:
         if int(text) >= self.sp_effects.nb_effects() or int(text)<0:
             return
         tree_store: Gtk.ListStore = self.builder.get_object('sp_effects_store')
         tree_store[path][1] = u16_checked(int(text))
     except ValueError:
         return
     self.sp_effects.set_item_effect_id(tree_store[path][0], tree_store[path][1])
     self.on_cb_effect_ids_changed()
     self.module.mark_sp_effects_as_modified()
示例#29
0
    def compress(cls, data: bytes) -> 'Atupx':
        """Create a new ATUPX container from originally uncompressed data."""
        from skytemple_files.common.types.file_types import FileType

        new_container = cls()
        compressed_data = FileType.CUSTOM_999.compress(data)

        new_container.compressed_data = compressed_data
        new_container.length_decompressed = u32_checked(len(data))
        new_container.length_compressed = u16_checked(
            len(compressed_data) + 0xb)
        return new_container
示例#30
0
 def set_gummi_iq_gains(value: List[List[int]], arm9: bytearray, config: Pmd2Data, add_types_patch_applied: bool) -> None:
     dim, byte_size = IQ_GAINS_TABLES[add_types_patch_applied]
     block = config.binaries['arm9.bin'].symbols['IqGummiGain']
     lst_flattened = list(chain.from_iterable(value))
     if len(lst_flattened) != dim * dim:
         raise ValueError("IQ gain table does not match ROM size")
     if byte_size == 1:
         for i, b in enumerate(lst_flattened):
             write_u8(arm9, u8_checked(b), block.begin + i * byte_size)
     else:
         for i, b in enumerate(lst_flattened):
             write_u16(arm9, u16_checked(b), block.begin + i * byte_size)