예제 #1
0
 def _parse_dungeon_data(self, dungeon_root) -> Pmd2DungeonData:
     dungeon_bin_files = None
     items = []
     dungeons = []
     for e_game in dungeon_root:
         if id_matches_edition(e_game, self._game_edition):
             for e in e_game:
                 ###########################
                 if e.tag == 'DungeonBinFiles':
                     files = []
                     for i, e_var in enumerate(e):
                         files.append(Pmd2BinPackFile(
                             self._xml_int(e_var.attrib['idxfirst']),
                             self._xml_int(e_var.attrib['idxlast']) if 'idxlast' in e_var.attrib else None,
                             e_var.attrib['type'],
                             e_var.attrib['name']
                         ))
                     dungeon_bin_files = Pmd2DungeonBinFiles(files)
                 ###########################
                 if e.tag == 'Items':
                     for i, e_item in enumerate(e):
                         items.append(Pmd2DungeonItem(i, e_item.text))
                 ###########################
                 if e.tag == 'Dungeons':
                     for i, e_dungeon in enumerate(e):
                         dungeons.append(Pmd2DungeonDungeon(i, e_dungeon.text))
     return Pmd2DungeonData(
         dungeon_bin_files,
         items,
         dungeons
     )
    def _randomize_items(self):
        categories = {}
        items = OrderedDict()
        cats_as_list = list(ALLOWED_ITEM_CATS)

        # 1/8 chance for money to get a chance
        if choice([True] + [False] * 7):
            cats_as_list.append(MappaItemCategory.POKE)

        # 1/8 chance for Link Box to get a chance
        if choice([True] + [False] * 7):
            cats_as_list.append(MappaItemCategory.LINK_BOX)

        cats_as_list.sort(key=lambda x: x.value)
        weights = sorted(self._random_weights(len(cats_as_list)))
        for i, cat in enumerate(cats_as_list):
            categories[cat] = weights[i]

            if cat.number_of_items is not None:
                allowed_cat_item_ids = [x for x in cat.item_ids() if x in ALLOWED_ITEM_IDS]
                upper_limit = min(MAX_ITEMS_PER_CAT, len(allowed_cat_item_ids))
                if upper_limit <= MIN_ITEMS_PER_CAT:
                    n_items = MIN_ITEMS_PER_CAT
                else:
                    n_items = randrange(MIN_ITEMS_PER_CAT, upper_limit)
                cat_item_ids = sorted(set(
                    (choice(allowed_cat_item_ids) for _ in range(0, n_items))
                ))
                cat_weights = sorted(self._random_weights(len(cat_item_ids)))

                for item_id, weight in zip(cat_item_ids, cat_weights):
                    items[Pmd2DungeonItem(item_id, '???')] = weight

        return MappaItemList(categories, OrderedDict(sorted(items.items(), key=lambda i: i[0].id)))
예제 #3
0
 def from_xml(cls, ele: Element) -> 'XmlSerializable':
     validate_xml_tag(ele, XML_ITEM_LIST)
     categories = {}
     items = {}
     for child in ele:
         if child.tag == XML_CATEGORY:
             validate_xml_attribs(
                 child, [XML_CATEGORY__NAME, XML_CATEGORY__WEIGHT])
             name = child.get(XML_CATEGORY__NAME)
             if not hasattr(MappaItemCategory, name):
                 raise XmlValidateError(f"Unknown item category {name}.")
             weight_str = child.get(XML_CATEGORY__WEIGHT)
             weight = int(
                 weight_str) if weight_str != 'GUARANTEED' else GUARANTEED
             categories[getattr(MappaItemCategory, name)] = weight
         elif child.tag == XML_ITEM:
             validate_xml_attribs(child, [XML_ITEM__ID, XML_ITEM__WEIGHT])
             weight_str = child.get(XML_ITEM__WEIGHT)
             weight = int(
                 weight_str) if weight_str != 'GUARANTEED' else GUARANTEED
             items[Pmd2DungeonItem(int(child.get(XML_ITEM__ID)),
                                   '???')] = weight
         else:
             raise XmlValidateError(
                 f"Unexpected sub-node for {XML_ITEM_LIST}: {child.tag}")
     return cls(categories, items)
예제 #4
0
 def _parse_dungeon_data(self, dungeon_root) -> Pmd2DungeonData:
     dungeon_bin_files = None
     items = []
     dungeons = []
     item_categories = {}
     for e_game in dungeon_root:
         if id_matches_edition(e_game, self._game_edition):
             for e in e_game:
                 ###########################
                 if e.tag == 'DungeonBinFiles':
                     files = []
                     for i, e_var in enumerate(e):
                         files.append(
                             Pmd2BinPackFile(
                                 self.xml_int(e_var.attrib['idxfirst']),
                                 self.xml_int(e_var.attrib['idxlast'])
                                 if 'idxlast' in e_var.attrib else None,
                                 e_var.attrib['type'],
                                 e_var.attrib['name']))
                     dungeon_bin_files = Pmd2DungeonBinFiles(files)
                 ###########################
                 if e.tag == 'Items':
                     for i, e_item in enumerate(e):
                         items.append(Pmd2DungeonItem(i, e_item.text))
                 ###########################
                 if e.tag == 'Dungeons':
                     for i, e_dungeon in enumerate(e):
                         dungeons.append(
                             Pmd2DungeonDungeon(i, e_dungeon.text))
                 ###########################
                 if e.tag == 'ItemCategories':
                     for e_game in e:
                         if id_matches_edition(e_game, self._game_edition):
                             for i, e_item_cat in enumerate(e_game):
                                 citems = []
                                 for e_item in e_item_cat:
                                     if e_item.tag != 'Item':
                                         raise ValueError(
                                             "Excpeted Item as subtag for ItemCategory."
                                         )
                                     citems.append(self.xml_int(
                                         e_item.text))
                                 item_categories[self.xml_int(
                                     e_item_cat.attrib['id']
                                 )] = Pmd2DungeonItemCategory(
                                     self.xml_int(e_item_cat.attrib['id']),
                                     e_item_cat.attrib['name'], citems)
     return Pmd2DungeonData(
         dungeon_bin_files,  # type: ignore
         items,
         dungeons,
         item_categories)
예제 #5
0
    def _save_item_spawn_rates(self):
        item_stores = {
            None:
            self.builder.get_object('item_categories_store'),
            self.item_categories[0]:
            self.builder.get_object('item_cat_thrown_pierce_store'),
            self.item_categories[1]:
            self.builder.get_object('item_cat_thrown_rock_store'),
            self.item_categories[2]:
            self.builder.get_object('item_cat_berries_store'),
            self.item_categories[3]:
            self.builder.get_object('item_cat_foods_store'),
            self.item_categories[4]:
            self.builder.get_object('item_cat_hold_store'),
            self.item_categories[5]:
            self.builder.get_object('item_cat_tms_store'),
            self.item_categories[9]:
            self.builder.get_object('item_cat_orbs_store'),
            self.item_categories[8]:
            self.builder.get_object('item_cat_others_store')
        }

        category_weights = {}
        item_weights = {}
        for (cat, store) in item_stores.items():

            rows = []
            for row in store:
                rows.append(row[:])
            rows.sort(key=lambda e: e[0])

            sum_of_weights = sum(
                (int(row[4]) for row in store if row[2] is False))

            last_weight = 0
            last_weight_set_idx = None
            for row in rows:
                # Add Poké and Link Box items for those categories
                if not cat:
                    if row[0] == POKE_CATEGORY_ID:
                        item_weights[Pmd2DungeonItem(
                            self.item_categories[POKE_CATEGORY_ID].item_ids()
                            [0], '')] = 10000
                    if row[0] == LINKBOX_CATEGORY_ID:
                        item_weights[Pmd2DungeonItem(
                            self._get_link_box_item_id(), '')] = 10000
                was_set = False
                weight = 0
                if row[4] != "0":
                    weight = last_weight + int(10000 *
                                               (int(row[4]) / sum_of_weights))
                    last_weight = weight
                    was_set = True
                if cat is None:
                    set_idx = self.item_categories[row[0]]
                    category_weights[set_idx] = weight
                    if was_set:
                        last_weight_set_idx = set_idx
                else:
                    set_idx = Pmd2DungeonItem(row[0], '')  # type: ignore
                    item_weights[Pmd2DungeonItem(row[0], '')] = weight
                    if was_set:
                        last_weight_set_idx = set_idx
            if last_weight_set_idx is not None:
                if last_weight != 0 and last_weight != 10000:
                    # We did not sum up to exactly 10000, so the values we entered are not evenly
                    # divisible. Find the last non-zero we set and set it to 10000.
                    if cat is None:
                        category_weights[last_weight_set_idx] = 10000
                    else:
                        item_weights[
                            last_weight_set_idx] = 10000  # type: ignore

        item_weights = {
            k: v
            for k, v in sorted(item_weights.items(), key=lambda x: x[0].id)
        }

        il = self._item_list
        il.categories = category_weights  # type: ignore
        il.items = item_weights

        self.module.mark_item_list_as_modified(self._get_list_id())
예제 #6
0
    def _save_item_spawn_rates(self):
        item_stores = {
            None:
            self.builder.get_object('item_categories_store'),
            MappaItemCategory.THROWN_PIERCE:
            self.builder.get_object('item_cat_thrown_pierce_store'),
            MappaItemCategory.THROWN_ROCK:
            self.builder.get_object('item_cat_thrown_rock_store'),
            MappaItemCategory.BERRIES_SEEDS_VITAMINS:
            self.builder.get_object('item_cat_berries_store'),
            MappaItemCategory.FOODS_GUMMIES:
            self.builder.get_object('item_cat_foods_store'),
            MappaItemCategory.HOLD:
            self.builder.get_object('item_cat_hold_store'),
            MappaItemCategory.TMS:
            self.builder.get_object('item_cat_tms_store'),
            MappaItemCategory.ORBS:
            self.builder.get_object('item_cat_orbs_store'),
            MappaItemCategory.OTHER:
            self.builder.get_object('item_cat_others_store')
        }

        category_weights = {}
        item_weights = {}
        for (cat, store) in item_stores.items():

            rows = []
            for row in store:
                rows.append(row[:])
            rows.sort(key=lambda e: e[0])

            sum_of_weights = sum(
                (int(row[4]) for row in store if row[2] is False))

            last_weight = 0
            last_weight_set_idx = None
            for i, row in enumerate(rows):

                # Add Poké and Link Box items for those categories
                if not cat:
                    if i == MappaItemCategory.POKE.value:
                        item_weights[Pmd2DungeonItem(
                            MappaItemCategory.POKE.item_ids()[0], '')] = 10000
                    if i == MappaItemCategory.LINK_BOX.value:
                        item_weights[Pmd2DungeonItem(
                            MappaItemCategory.LINK_BOX.item_ids()[0],
                            '')] = 10000
                was_set = False
                weight = 0
                if row[4] != "0":
                    weight = last_weight + int(10000 *
                                               (int(row[4]) / sum_of_weights))
                    last_weight = weight
                    was_set = True
                if cat is None:
                    set_idx = MappaItemCategory(row[0])
                    category_weights[set_idx] = weight
                    if was_set:
                        last_weight_set_idx = set_idx
                else:
                    set_idx = Pmd2DungeonItem(row[0], '')
                    item_weights[Pmd2DungeonItem(row[0], '')] = weight
                    if was_set:
                        last_weight_set_idx = set_idx
            if last_weight_set_idx is not None:
                if last_weight != 0 and last_weight != 10000:
                    # We did not sum up to exactly 10000, so the values we entered are not evenly
                    # divisible. Find the last non-zero we set and set it to 10000.
                    if cat is None:
                        category_weights[last_weight_set_idx] = 10000
                    else:
                        item_weights[last_weight_set_idx] = 10000

        item_weights = {
            k: v
            for k, v in sorted(item_weights.items(), key=lambda x: x[0].id)
        }

        il = self._item_list
        il.categories = category_weights
        il.items = item_weights

        self.module.mark_item_list_as_modified(self._get_list_id())