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)))
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)
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)
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())
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())