Ejemplo n.º 1
0
def create_folder_in_rom(rom: NintendoDSRom, path: str) -> None:
    """Creates a folder in the ROM."""
    folder = rom.filenames.subfolder(path)
    if folder is not None:
        raise FileNotFoundError(f(_("Folder {path} already exists.")))
    path_list = path.split('/')
    par_dir_name = '/'.join(path_list[:-1])
    parent_dir: Optional[Folder] = rom.filenames.subfolder(par_dir_name)
    if parent_dir is None:
        raise FileNotFoundError(f(_("Folder {dir_name} does not exist.")))

    found = False
    first_id = -1
    last_child_count = -1
    for s_name, s_folder in sorted(parent_dir.folders, key=lambda f: f[0]):
        first_id = s_folder.firstID
        last_child_count = len(s_folder.files)
        if s_name > path_list[-1]:
            found = True
            break
    if not found:
        first_id = first_id + last_child_count

    new_folder = Folder(firstID=first_id)
    parent_dir.folders.append((path_list[-1], new_folder))
Ejemplo n.º 2
0
    def _parse_param(self, param: SsbOpParam, built_strings: Dict[str, List[str]], built_constants: List[str]) -> int:
        if isinstance(param, int):
            return param

        if isinstance(param, SsbOpParamConstant):
            try:
                return SsbConstant(param.name, self.rom_data.script_data).value.id
            except ValueError as err:
                raise SsbCompilerError(str(err)) from err

        if isinstance(param, SsbOpParamConstString):
            i = len(built_constants)
            built_constants.append(param.name)
            return i

        if isinstance(param, SsbOpParamLanguageString):
            i = len(built_strings[next(iter(built_strings.keys()))])
            if len(param.strings.keys()) == 1:
                # Single language convenience mode, apply this to all languages.
                only_value = param.strings[next(iter(param.strings.keys()))]
                for lang in built_strings.keys():
                    built_strings[lang].append(only_value)
            else:
                # Multi language regular case. All languages must be known.
                for lang, string in param.strings.items():
                    if lang not in built_strings:
                        raise SsbCompilerError(f(_("Unknown language for string: {lang}")))
                    built_strings[lang].append(string)
            return StringIndexPlaceholder(i)

        raise SsbCompilerError(f(_("Invalid parameter supplied for an operation: {param}")))
Ejemplo n.º 3
0
 def set_cart_removed_data(img: Image.Image, arm9: bytearray,
                           config: Pmd2Data) -> None:
     """
     Sets the cartridge removed data
     """
     if img.width != IMG_WIDTH and img.height != IMG_HEIGHT:
         raise AttributeError(
             f(_("The image must have dimensions {IMG_WIDTH}x{IMG_HEIGHT}.")
               ))
     block = config.binaries['arm9.bin'].symbols['CartRemovedImgData']
     img = img.convert("RGB")
     raw_data = img.tobytes()
     img_data = []
     for r, g, b in iter_bytes(raw_data, 3):
         v = (r // 8) + ((g // 8) << 5) + ((b // 8) << 10)
         img_data.append(v % 256)
         img_data.append(v // 256)
     data = CommonAtHandler.serialize(
         CommonAtHandler.compress(bytes(img_data), [CommonAtType.AT3PX]))
     if len(data) > block.end - block.begin:
         raise AttributeError(
             f(
                 _("This image must be compressed better to fit in the arm9 ({len(data)} > {block.end-block.begin})."
                   )))
     arm9[block.begin:block.end] = data + bytes((block.end - block.begin) -
                                                len(data))
Ejemplo n.º 4
0
    def on_spritebot_import_activate(self, *args):
        dialog = Gtk.FileChooserNative.new(
            _("Import portraits from PNG sheet..."), MainController.window(),
            Gtk.FileChooserAction.OPEN, None, None)

        add_dialog_png_filter(dialog)

        response = dialog.run()
        fn = dialog.get_filename()
        dialog.destroy()

        if response == Gtk.ResponseType.ACCEPT:
            try:
                for subindex, image in SpriteBotSheet.load(
                        fn, self._get_portrait_name):
                    try:
                        self.kao.set_from_img(self.item_id, subindex, image)
                    except Exception as err:
                        name = self._get_portrait_name(subindex)
                        logger.error(f"Failed importing image '{name}'.",
                                     exc_info=err)
                        display_error(
                            sys.exc_info(),
                            f(_('Failed importing image "{name}":\n{err}')),
                            f(_("Error for '{name}'.")))
            except Exception as err:
                logger.error(f"Failed importing portraits sheet: {err}",
                             exc_info=err)
                display_error(sys.exc_info(),
                              f(_('Failed importing portraits sheet:\n{err}')),
                              _("Could not import."))
            self.re_render()
            # Mark as modified
            self.module.mark_as_modified()
            self._mark_as_modified_cb()
Ejemplo n.º 5
0
 def _init_tileset_chooser(self):
     store = Gtk.ListStore(int, str)  # id, name
     for i in range(0, COUNT_VALID_TILESETS):
         if i >= TILESET_FIRST_BG:
             store.append([i, f(_("Background {i}"))])
         else:
             store.append([i, f(_("Tileset {i}"))])
     self._fast_set_comboxbox_store(
         self.builder.get_object('tool_choose_tileset_cb'), store, 1)
Ejemplo n.º 6
0
    def from_xml(cls, ele: Element) -> 'MappaFloor':
        data = {
            'layout': None,
            'monsters': None,
            'traps': None,
            'floor_items': None,
            'shop_items': None,
            'monster_house_items': None,
            'buried_items': None,
            'unk_items1': None,
            'unk_items2': None
        }
        for child in ele:
            if child.tag == XML_FLOOR_LAYOUT and data['layout'] is None:
                data['layout'] = MappaFloorLayout.from_xml(child)
            elif child.tag == XML_MONSTER_LIST and data['monsters'] is None:
                monsters = []
                for monster in child:
                    monsters.append(MappaMonster.from_xml(monster))
                data['monsters'] = monsters
            elif child.tag == XML_TRAP_LIST and data['traps'] is None:
                data['traps'] = MappaTrapList.from_xml(child)
            elif child.tag == XML_ITEM_LIST and child.get(
                    XML_ITEM_LIST__TYPE
            ) == XML_ITEM_LIST__TYPE__FLOOR and data['floor_items'] is None:
                data['floor_items'] = MappaItemList.from_xml(child)
            elif child.tag == XML_ITEM_LIST and child.get(
                    XML_ITEM_LIST__TYPE
            ) == XML_ITEM_LIST__TYPE__SHOP and data['shop_items'] is None:
                data['shop_items'] = MappaItemList.from_xml(child)
            elif child.tag == XML_ITEM_LIST and child.get(
                    XML_ITEM_LIST__TYPE
            ) == XML_ITEM_LIST__TYPE__MONSTER_HOUSE and data[
                    'monster_house_items'] is None:
                data['monster_house_items'] = MappaItemList.from_xml(child)
            elif child.tag == XML_ITEM_LIST and child.get(
                    XML_ITEM_LIST__TYPE
            ) == XML_ITEM_LIST__TYPE__BURIED and data['buried_items'] is None:
                data['buried_items'] = MappaItemList.from_xml(child)
            elif child.tag == XML_ITEM_LIST and child.get(
                    XML_ITEM_LIST__TYPE
            ) == XML_ITEM_LIST__TYPE__UNK1 and data['unk_items1'] is None:
                data['unk_items1'] = MappaItemList.from_xml(child)
            elif child.tag == XML_ITEM_LIST and child.get(
                    XML_ITEM_LIST__TYPE
            ) == XML_ITEM_LIST__TYPE__UNK2 and data['unk_items2'] is None:
                data['unk_items2'] = MappaItemList.from_xml(child)
            else:
                raise XmlValidateError(
                    f(_('Floor parsing: Unexpected {child.tag}')))

        for k, v in data.items():
            if v is None:
                raise XmlValidateError(f(_('Missing {k} for Floor data.')))

        return cls(**data)
Ejemplo n.º 7
0
    def on_separate_import_activate(self, *args):
        md = SkyTempleMessageDialog(
            MainController.window(),
            Gtk.DialogFlags.DESTROY_WITH_PARENT,
            Gtk.MessageType.INFO,
            Gtk.ButtonsType.OK,
            f(
                _("To import, select a directory to import from. Files with the pattern '{self.item_id + 1}_XX.png'\n"
                  "will be imported, where XX is a number between 0 and 40.")),
            title=_("Import Portraits"))
        md.run()
        md.destroy()
        dialog = Gtk.FileChooserNative.new(_("Import portraits from PNGs..."),
                                           MainController.window(),
                                           Gtk.FileChooserAction.SELECT_FOLDER,
                                           None, None)

        response = dialog.run()
        fn = dialog.get_filename()
        dialog.destroy()

        if response == Gtk.ResponseType.ACCEPT:
            r = re.compile(rf"{self.item_id + 1}_(\d+)\.png", re.IGNORECASE)
            imgs = {
                int(match[1]): name
                for match, name in self._try_match_import(r, os.listdir(fn))
                if match is not None and int(match[1]) <= 40
            }
            for subindex, image_fn in imgs.items():
                try:
                    with open(os.path.join(fn, image_fn), 'rb') as f:
                        image = Image.open(f)
                        kao = self.kao.get(self.item_id, subindex)
                        if kao:
                            # Replace
                            kao.set(image)
                        else:
                            # New
                            self.kao.set(self.item_id, subindex,
                                         KaoImage.new(image))
                except Exception as err:
                    name = self._get_portrait_name(subindex)
                    logger.error(f"Failed importing image '{name}'.",
                                 exc_info=err)
                    display_error(
                        sys.exc_info(),
                        f(_('Failed importing image "{name}":\n{err}')),
                        f(_(f"Error for '{name}'.")))
            # Re-render
            self._portrait_provider.reset()
            for draw in self._draws:
                draw.queue_draw()
            # Mark as modified
            self.module.mark_as_modified()
            self._mark_as_modified_cb()
Ejemplo n.º 8
0
 def apply(self, name: str, config: Optional[Dict[str, Any]] = None) -> None:
     """
     Apply a patch.
     If the patch requires parameters, values for ALL of them must be in the dict `config` (even if default values
     are specified in the XML config).
     """
     if name not in self._loaded_patches:
         raise ValueError(f(_("The patch '{name}' was not found.")))
     patch = self._loaded_patches[name]
     if isinstance(patch, DependantPatch):
         for patch_name in patch.depends_on():
             try:
                 if not self.is_applied(patch_name):
                     raise PatchDependencyError(f(_("The patch '{patch_name}' needs to be applied before you can "
                                                    "apply '{name}'.")))
             except ValueError as err:
                 raise PatchDependencyError(f(_("The patch '{patch_name}' needs to be applied before you can "
                                                "apply '{name}'. "
                                                "This patch could not be found."))) from err
     # Check config
     patch_data = self._config.asm_patches_constants.patches[name]
     if patch_data.has_parameters():
         if config is None:
             raise PatchNotConfiguredError(_("No configuration was given."), "*", "No configuration was given.")
         for param in patch_data.parameters.values():
             if param.name not in config:
                 raise PatchNotConfiguredError(_("Missing configuration value."), param.name, "Not given.")
             if param.type == Pmd2PatchParameterType.INTEGER:
                 val = config[param.name]
                 if not isinstance(val, int):
                     raise PatchNotConfiguredError(_("Invalid configuration value."), param.name, "Must be int.")
                 if param.min is not None and val < param.min:
                     raise PatchNotConfiguredError(_("Invalid configuration value."), param.name, _("Must be >= {}.").format(param.min))
                 if param.max is not None and val > param.max:
                     raise PatchNotConfiguredError(_("Invalid configuration value."), param.name, _("Must be <= {}.").format(param.max))
             if param.type == Pmd2PatchParameterType.STRING:
                 val = config[param.name]
                 if not isinstance(val, str):
                     raise PatchNotConfiguredError(_("Invalid configuration value."), param.name, "Must be str.")
             if param.type == Pmd2PatchParameterType.SELECT:
                 val = config[param.name]
                 found = False
                 for option in param.options:  # type: ignore
                     if not isinstance(val, type(option.value)) or option.value != val:
                         continue
                     found = True
                     break
                 if not found:
                     raise PatchNotConfiguredError(_("Invalid configuration value."), param.name, "Must be one of the options.")
         patch.supply_parameters(config)
     patch.apply(
         partial(self._apply_armips, name, patch),
         self._rom, self._config
     )
Ejemplo n.º 9
0
 def get_view(self) -> Gtk.Widget:
     self.builder = self._get_builder(__file__, 'tileset.glade')
     self._init_rules()
     self._init_rule_icon_views()
     self._init_chunk_picker_icon_view()
     self._init_secondary_terrain()
     self.builder.connect_signals(self)
     editor = self.builder.get_object('editor')
     root = self.builder.get_object('editor_root')
     root.set_current_page(self.__class__._last_open_tab_id)
     self.on_editor_root_switch_page(None, None, self.__class__._last_open_tab_id)
     self.builder.get_object('label_tileset_name').set_text(f(_('Dungeon Tileset {self.item_id} Rules')))
     self.builder.get_object('label_tileset_name2').set_text(f(_('Dungeon Tileset {self.item_id}')))
     return editor
Ejemplo n.º 10
0
    def _save(self, force=False):
        rom = RomProject.get_current()

        if rom.has_modifications() or force:
            self._loading_dialog = self.builder.get_object('file_opening_dialog')
            # noinspection PyUnusedLocal
            rom_name = os.path.basename(rom.filename)
            self.builder.get_object('file_opening_dialog_label').set_label(
                f(_('Saving ROM "{rom_name}"...'))
            )
            logger.debug(f(_('Saving {rom.filename}.')))

            # This will trigger a signal.
            rom.save(self)
            self._loading_dialog.run()
Ejemplo n.º 11
0
 def _open_file(self, filename: str):
     """Open a file"""
     if self._check_open_file():
         self._loading_dialog = self.builder.get_object('file_opening_dialog')
         # noinspection PyUnusedLocal
         rom_name = os.path.basename(filename)
         self.builder.get_object('file_opening_dialog_label').set_label(
             f(_('Loading ROM "{rom_name}"...'))
         )
         logger.debug(f(_('Opening {filename}.')))
         RomProject.open(filename, self)
         # Add to the list of recent files and save
         self._update_recent_files(filename)
         # Show loading spinner
         self._loading_dialog.run()
Ejemplo n.º 12
0
 def __init__(self,
              builder: Gtk.Builder,
              main_window: Gtk.Window,
              talk_script_names: Dict[int, str],
              scriptdata: Pmd2ScriptData,
              *,
              edit: SsaTrigger = None):
     self.builder = builder
     self.edit: Optional[SsaTrigger] = edit
     self.new_model: Optional[SsaTrigger] = None
     self.talk_script_names = talk_script_names
     self.scriptdata = scriptdata
     self.window: Gtk.Dialog = self.builder.get_object('dialog_event')
     self.window.set_transient_for(main_window)
     self.window.set_attached_to(main_window)
     if self.edit is not None:
         try:
             # noinspection PyUnusedLocal
             script_name = self.talk_script_names[self.edit.script_id]
             self.title = f(
                 _('Edit {script_name}')
             ) + f' / {self.scriptdata.common_routine_info__by_id[self.edit.coroutine.id].name}'
         except KeyError:
             self.title = _('Edit Event')
     else:
         self.title = _('New Event')
Ejemplo n.º 13
0
 def import_from_xml(self, xml: Element, tables: Dict[int, Image.Image]):
     self.entries = []
     self.unknown = 0
     pal_table = 256
     validate_xml_tag(xml, XML_FONT)
     for child in xml:
         if child.tag == XML_TABLE:
             validate_xml_attribs(child, [XML_TABLE__ID])
             t = int(child.get(XML_TABLE__ID))
             if t in FONT_VALID_TABLES and t in tables:
                 if pal_table > t:
                     pal_table = t
                     self.set_palette_raw(
                         memoryview(tables[t].palette.palette))
                 for char in child:
                     validate_xml_tag(char, XML_CHAR)
                     validate_xml_attribs(char,
                                          [XML_CHAR__ID, XML_CHAR__WIDTH])
                     charid = int(char.get(XML_CHAR__ID))
                     width = int(char.get(XML_CHAR__WIDTH))
                     x = (charid % 16) * BANNER_FONT_SIZE
                     y = (charid // 16) * BANNER_FONT_SIZE
                     self.entries.append(
                         BannerFontEntry.from_pil(
                             tables[t].crop(box=[
                                 x, y, x + BANNER_FONT_SIZE, y +
                                 BANNER_FONT_SIZE
                             ]), charid, t, width))
         elif child.tag == XML_HEADER:
             validate_xml_attribs(child, [XML_HEADER__UNKNOWN])
             self.unknown = int(child.get(XML_HEADER__UNKNOWN))
         else:
             raise XmlValidateError(
                 f(_('Font parsing: Unexpected {child.tag}')))
Ejemplo n.º 14
0
 def get_content(self) -> Gtk.Widget:
     # TODO: Adding and removing the sub scenes.
     return self.generate_content_label(
         f(_('This section contains all sub scenes for the map {self.name}.\n\n'
             'These scenes can be loaded on top of the "Enter" scene,\n'
             'depending on the current story progress.'))
     )
Ejemplo n.º 15
0
 def _init_override_dropdown(self):
     store = Gtk.ListStore(int, str)  # id, name
     store.append([0, _("No override")])
     for i in range(1, 256):
         store.append([i, f(_("No. {i}"))])  # TRANSLATORS: Number {i}
     self._fast_set_comboxbox_store(
         self.builder.get_object('settings_override'), store, 1)
Ejemplo n.º 16
0
    def get_view(self) -> Gtk.Widget:
        self.builder = self._get_builder(__file__, 'dungeon.glade')

        self.builder.get_object('label_dungeon_name').set_text(
            self.dungeon_name)
        edit_text = ''

        if not self.dungeon_info.length_can_be_edited:
            edit_text = _(
                '\nSince this is a Dojo Dungeon, the floor count can not be changed.'
            )
            self.builder.get_object('edit_floor_count').set_sensitive(False)
            self.builder.get_object('dungeon_restrictions_grid').set_sensitive(
                False)
        else:
            self._init_dungeon_restrictions()

        floor_count = self.module.get_number_floors(
            self.dungeon_info.dungeon_id)
        self.builder.get_object('label_floor_count').set_text(
            f(_('This dungeon has {floor_count} floors.{edit_text}')))

        self._init_names()
        self._is_loading = False
        self.builder.connect_signals(self)

        return self.builder.get_object('main_box')
Ejemplo n.º 17
0
    def load_tree_items(self, item_store: TreeStore, root_node):
        self._validator = DungeonValidator(self.get_mappa().floor_lists)
        root = item_store.append(root_node, [
            ICON_ROOT, DUNGEONS_NAME, self, MainController, 0, False, '', True
        ])
        self._tree_model = item_store
        self._root_iter = root

        static_data = self.project.get_rom_module().get_static_data()
        self._fixed_floor_data = self.project.open_file_in_rom(
            FIXED_PATH, FileType.FIXED_BIN, static_data=static_data)
        self._dungeon_bin: DungeonBinPack = self.project.open_file_in_rom(
            DUNGEON_BIN, FileType.DUNGEON_BIN, static_data=static_data)

        self._validator.validate(self.get_dungeon_list())

        self._fill_dungeon_tree()

        # Fixed rooms
        self._fixed_floor_root_iter = item_store.append(
            root_node, [
                ICON_FIXED_ROOMS, FIXED_ROOMS_NAME, self, FixedRoomsController,
                0, False, '', True
            ])
        for i in range(0, len(self._fixed_floor_data.fixed_floors)):
            self._fixed_floor_iters.append(
                item_store.append(self._fixed_floor_root_iter, [
                    ICON_FIXED_ROOMS,
                    f(_('Fixed Room {i}')), self, FixedController, i, False,
                    '', True
                ]))

        recursive_generate_item_store_row_label(self._tree_model[root])
        recursive_generate_item_store_row_label(
            self._tree_model[self._fixed_floor_root_iter])
Ejemplo n.º 18
0
def mappa_floor_xml_import(xml: Element, floor: MappaFloor):
    """Imports all data available in the mappa floor XML into the given model."""
    for child in xml:
        if child.tag == XML_FLOOR_LAYOUT:
            floor_number_before = floor.layout.floor_number
            floor.layout = MappaFloorLayout.from_xml(child)
            floor.layout.floor_number = floor_number_before
        elif child.tag == XML_MONSTER_LIST:
            monsters = []
            for monster in child:
                monsters.append(MappaMonster.from_xml(monster))
            floor.monsters = monsters
        elif child.tag == XML_TRAP_LIST:
            floor.traps = MappaTrapList.from_xml(child)
        elif child.tag == XML_ITEM_LIST and child.get(
                XML_ITEM_LIST__TYPE) == XML_ITEM_LIST__TYPE__FLOOR:
            floor.floor_items = MappaItemList.from_xml(child)
        elif child.tag == XML_ITEM_LIST and child.get(
                XML_ITEM_LIST__TYPE) == XML_ITEM_LIST__TYPE__SHOP:
            floor.shop_items = MappaItemList.from_xml(child)
        elif child.tag == XML_ITEM_LIST and child.get(
                XML_ITEM_LIST__TYPE) == XML_ITEM_LIST__TYPE__MONSTER_HOUSE:
            floor.monster_house_items = MappaItemList.from_xml(child)
        elif child.tag == XML_ITEM_LIST and child.get(
                XML_ITEM_LIST__TYPE) == XML_ITEM_LIST__TYPE__BURIED:
            floor.buried_items = MappaItemList.from_xml(child)
        elif child.tag == XML_ITEM_LIST and child.get(
                XML_ITEM_LIST__TYPE) == XML_ITEM_LIST__TYPE__UNK1:
            floor.unk_items1 = MappaItemList.from_xml(child)
        elif child.tag == XML_ITEM_LIST and child.get(
                XML_ITEM_LIST__TYPE) == XML_ITEM_LIST__TYPE__UNK2:
            floor.unk_items2 = MappaItemList.from_xml(child)
        else:
            raise XmlValidateError(
                f(_('Floor parsing: Unexpected {child.tag}')))
Ejemplo n.º 19
0
 def get_content(self) -> Gtk.Widget:
     # TODO: Adding and removing the acting scenes.
     return self.generate_content_label(
         f(
             _('This section contains all acting scenes for the map {self.name}.\n\n'
               'These scenes are used for cutscenes.\n'
               'The player can usually not move the character in them.')))
Ejemplo n.º 20
0
    def refresh(self, patch_category: PatchCategory):
        # ATTACH
        page = self._category_tabs[patch_category]
        page.pack_start(self.builder.get_object('patch_window'), True, True, 0)
        self._current_tab = patch_category

        tree: Gtk.TreeView = self.builder.get_object('patch_tree')
        model: Gtk.ListStore = tree.get_model()
        model.clear()
        self._patcher = self.module.project.create_patcher()
        # Load zip patches
        for fname in glob(os.path.join(self.patch_dir(), '*.skypatch')):
            try:
                self._patcher.add_pkg(fname)
            except BaseException as err:
                logger.error(
                    f"Error loading patch package {os.path.basename(fname)}",
                    exc_info=sys.exc_info())
                self._error(
                    f(
                        _("Error loading patch package {os.path.basename(fname)}:\n{err}"
                          )))
        # List patches:
        for patch in sorted(self._patcher.list(), key=lambda p: p.name):
            if patch.category != patch_category:
                continue
            applied_str = _('Not compatible')
            try:
                applied_str = _('Applied') if self._patcher.is_applied(
                    patch.name) else _('Compatible')
            except NotImplementedError:
                pass
            model.append(
                [patch.name, patch.author, patch.description, applied_str])
Ejemplo n.º 21
0
def validate_xml_attribs(ele: Element, attribs: List[str]):
    for attrib in attribs:
        if attrib not in ele.attrib:
            raise XmlValidateError(
                f(
                    _("Invalid XML. Expected attribute {attrib} for XML tag {ele.tag}."
                      )))
Ejemplo n.º 22
0
    def pil_to_chunks(
            self,
            image: Image.Image,
            force_import=True) -> Tuple[List[bytes], List[List[int]]]:
        """
        Imports chunks. Format same as for chunks_to_pil.
        Replaces tile mappings and returns the new tiles for storing them in a DPCI and the palettes
        for storing in a DPL.

        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.
        """
        tiles, all_tilemaps, palettes = from_pil(image, DPL_PAL_LEN, 16,
                                                 DPCI_TILE_DIM, image.width,
                                                 image.height, DPC_TILING_DIM,
                                                 DPC_TILING_DIM, force_import)
        # Validate number of palettes
        palettes = palettes[:DPL_MAX_PAL]
        for tm in all_tilemaps:
            if tm.pal_idx > DPL_MAX_PAL - 1:
                raise ValueError(
                    f(
                        _("The image to import can only use the first 12 palettes. "
                          "Tried to use palette {tm.pal_idx}")))
        self.chunks = list(
            chunks(all_tilemaps, DPC_TILING_DIM * DPC_TILING_DIM))
        self.re_fill_chunks()
        return tiles, palettes
Ejemplo n.º 23
0
    def provide(self, add_title=None, dark=False, disable_xml_declaration=False) -> Graph:
        chart = pygal.XY(
            xrange=(1, len(self.level_bin_entry.levels) + 1),
            secondary_range=(0, max([x.experience_required for x in self.level_bin_entry.levels])),
            disable_xml_declaration=disable_xml_declaration
        )
        if add_title:
            chart.title = add_title
        if dark:
            chart.style = DarkSolarizedStyle

        exps = []
        hps = []
        atks = []
        sp_atks = []
        defs = []
        sp_defs = []
        hp_accu = self.monster.base_hp
        atk_accu = self.monster.base_atk
        sp_atk_accu = self.monster.base_sp_atk
        def_accu = self.monster.base_def
        sp_def_accu = self.monster.base_sp_def
        for i, level in enumerate(self.level_bin_entry.levels):
            exps.append((i + 1, level.experience_required))
            hp_accu += level.hp_growth  # type: ignore
            hps.append((i + 1, hp_accu))
            atk_accu += level.attack_growth  # type: ignore
            atks.append((i + 1, atk_accu))
            sp_atk_accu += level.special_attack_growth  # type: ignore
            sp_atks.append((i + 1, sp_atk_accu))
            def_accu += level.defense_growth  # type: ignore
            defs.append((i + 1, def_accu))
            sp_def_accu += level.special_defense_growth  # type: ignore
            sp_defs.append((i + 1, sp_def_accu))

        max_val: int = max(hp_accu, atk_accu, sp_atk_accu, def_accu, sp_def_accu)  # type: ignore
        moves = []
        processed_levels: Dict[int, int] = {}
        for lum in self.move_learnset.level_up_moves:
            if lum.level_id in processed_levels:
                processed_levels[lum.level_id] += 1
            else:
                processed_levels[lum.level_id] = 1
            count_so_far = processed_levels[lum.level_id] - 1
            moves.append({
                'value': (lum.level_id, max_val + 5 + (5 * count_so_far)),
                'label': self.move_strings[lum.move_id]
            })

        chart.add(_('Exp.'), exps, secondary=True)  # TRANSLATORS: Experience
        chart.add(_('HP'), hps)  # TRANSLATORS: Health Points
        chart.add(_('ATK'), atks)  # TRANSLATORS: Attack
        chart.add(_('Sp. ATK'), sp_atks)  # TRANSLATORS: Special Attack
        chart.add(_('DEF'), defs)  # TRANSLATORS: Defense
        chart.add(_('Sp. DEF'), sp_defs)  # TRANSLATORS: Special Defense
        chart.add(_('Moves'), moves, stroke=False,
                  formatter=lambda x: f(_('at level {x[0]}')))

        return chart
Ejemplo n.º 24
0
 def get_content(self) -> Gtk.Widget:
     if self.name is not None:
         return self.generate_content_label(
             f(_("This section contains all the map backgrounds, that start with the letter {self.name[0]}."))
         )
     return self.generate_content_label(
         _("This section contains all the map backgrounds, that don't fit in any of the other categories.")
     )
Ejemplo n.º 25
0
 def __init__(self, idx: int, flip_x: bool, flip_y: bool, pal_idx: int, ignore_too_large: bool = False):
     self.idx = idx
     if idx > 0x3FF and not ignore_too_large:
         raise ValueError(f(_("Tile Mapping can not be processed. The tile number referenced ({idx}) is bigger "
                              "than the maximum ({0x3FF}). If you are importing an image, please try to have "
                              "less unique tiles.")))
     self.flip_x = flip_x
     self.flip_y = flip_y
     self.pal_idx = pal_idx
Ejemplo n.º 26
0
 def _done(self, return_code):
     self._update_status(GfxcrunchStatus.SUCCESS if return_code ==
                         0 else GfxcrunchStatus.ERROR)
     if return_code != 0:
         self._stderr(
             f(
                 _('!! Process exited with error. Exit code: {return_code} !!'
                   )))
     self.builder.get_object('spinner').stop()
     self.builder.get_object('close').set_sensitive(True)
Ejemplo n.º 27
0
 def add_manually(self, handler: AbstractPatchHandler, patch_base_dir: str):
     # Try to find the patch in the config
     if handler.name not in self._config.asm_patches_constants.patches.keys(
     ):
         raise ValueError(
             f(
                 _("No patch for handler '{handler.name}' found in the configuration."
                   )))
     self._loaded_patches[handler.name] = handler
     self._patch_dirs[handler.name] = os.path.realpath(patch_base_dir)
Ejemplo n.º 28
0
 def apply(self, name: str):
     if name not in self._loaded_patches:
         raise ValueError(f(_("The patch '{name}' was not found.")))
     patch = self._loaded_patches[name]
     if isinstance(patch, DependantPatch):
         for patch_name in patch.depends_on():
             try:
                 if not self.is_applied(patch_name):
                     raise PatchDependencyError(
                         f(
                             _("The patch '{patch_name}' needs to be applied before you can "
                               "apply '{name}'.")))
             except ValueError as err:
                 raise PatchDependencyError(
                     f(
                         _("The patch '{patch_name}' needs to be applied before you can "
                           "apply '{name}'. "
                           "This patch could not be found."))) from err
     patch.apply(partial(self._apply_armips, name), self._rom, self._config)
Ejemplo n.º 29
0
 def create_for(cls, string):
     if string == 'CLOSED':
         return cls.CLOSED
     if string == 'OPEN':
         return cls.OPEN
     if string == 'REQUEST':
         return cls.REQUEST
     if string == 'OPEN_AND_REQUEST':
         return cls.OPEN_AND_REQUEST
     raise UserValueError(f(_("Invalid DungeonMode: {string}")))
Ejemplo n.º 30
0
 def get_view(self) -> Gtk.Widget:
     self.builder = self._get_builder(__file__, 'map.glade')
     self.builder.connect_signals(self)
     self.builder.get_object('title').set_text(
         f(_('Script Scenes for "{}"').format(self.name)))
     self.builder.get_object('desc').set_text(
         f(
             _('This section contains all scenes for the map {self.name}.\n\n'
               '"Enter (sse)" contains the scene that is loaded when the map is entered\n'
               'by the player by "walking into it" (if applicable).\n\n'
               '"Acting (ssa)" contains the scenes used for cutscenes.\n'
               'The player can usually not move the character in these scenes.\n\n'
               '"Sub (sss)" contains scenes that can be loaded on on top of the "Enter" scene,\n'
               'depending on the current story progress.')))
     self._sub_enter, self._sub_acting, self._sub_sub = self.module.get_subnodes(
         self.name)
     if self._sub_enter:
         self.builder.get_object('btn_add_enter').set_sensitive(False)
     return self.builder.get_object('box_list')