def load_database(self, skip_skills=False, skip_bonus=False, skip_extra=False): base_dir = self.base_dir raw_cards = card.load_card_data(data_dir=base_dir) self.dungeons = dungeon.load_dungeon_data(data_dir=base_dir) if not skip_bonus: self.bonus_sets = { g.value: bonus.load_bonus_data(data_dir=base_dir, server=self.server, data_group=g.value) for g in StarterGroup } if not skip_skills: self.skills = skill.load_skill_data(data_dir=base_dir) parser = SkillParser() parser.parse(self.skills) self.leader_skills = parser.leader_skills self.active_skills = parser.active_skills self.skill_id_to_leader_skill = { s.skill_id: s for s in self.leader_skills } self.skill_id_to_active_skill = { s.skill_id: s for s in self.active_skills } self.raw_enemy_skills = enemy_skill.load_enemy_skill_data( data_dir=base_dir) es_parser = BehaviorParser() es_parser.parse(self.raw_enemy_skills) self.enemy_skills = es_parser.enemy_behaviors if not skip_extra: self.exchange = exchange.load_data(data_dir=base_dir, server=self.server) self.egg_machines = extra_egg_machine.load_data(data_dir=base_dir, server=self.server) self.bonuses = _clean_bonuses(self.server, self.bonus_sets, self.dungeons) self.enemies = _clean_enemy(raw_cards, self.enemy_skills) self.cards = _clean_cards(self.server, raw_cards, self.enemies, self) self.dungeon_id_to_dungeon = {d.dungeon_id: d for d in self.dungeons} self.monster_no_to_card = {c.monster_no: c for c in self.cards} if self.server == Server.jp: self.monster_id_to_card = self.monster_no_to_card else: self.monster_id_to_card = { nakr_no_to_monster_id(c.monster_no): c for c in self.cards } self.enemy_id_to_enemy = {e.enemy_id: e for e in self.enemies}
def load_database(self, skip_skills=False, skip_bonus=False, skip_extra=False): base_dir = self.base_dir raw_cards = card.load_card_data(data_dir=base_dir) self.dungeons = dungeon.load_dungeon_data(data_dir=base_dir) if not skip_bonus: self.bonus_sets = { g.value: bonus.load_bonus_data(data_dir=base_dir, server=self.server, data_group=g.value) for g in StarterGroup } if not skip_skills: self.skills = skill.load_skill_data(data_dir=base_dir) self.skill_id_to_skill = {s.skill_id: s for s in self.skills} # TODO: need to compute skill data here self.enemy_skills = enemy_skill.load_enemy_skill_data( data_dir=base_dir) if not skip_extra: self.exchange = exchange.load_data(data_dir=base_dir) self.egg_machines = egg_machine.load_data(data_dir=base_dir) self.bonuses = _clean_bonuses(self.server, self.bonus_sets, self.dungeons) self.enemies = _clean_enemy(raw_cards, self.enemy_skills) self.cards = _clean_cards(self.server, raw_cards, self.skills, self.enemies) self.dungeon_id_to_dungeon = {d.dungeon_id: d for d in self.dungeons} self.monster_no_to_card = {c.monster_no: c for c in self.cards} if self.server == Server.jp: self.monster_id_to_card = self.monster_no_to_card else: self.monster_id_to_card = { nakr_no_to_monster_id(c.monster_no): c for c in self.cards } self.enemy_id_to_enemy = {e.enemy_id: e for e in self.enemies}
def no_to_id(self, monster_no: MonsterNo) -> MonsterId: if self.server == Server.jp: return jp_no_to_monster_id(monster_no) else: return nakr_no_to_monster_id(monster_no)
def copy_media(args): base_dir = args.base_dir alt_base_dir = args.alt_base_dir output_dir = args.output_dir jp_icon_input_dir = os.path.join(base_dir, 'jp', 'portrait', 'local') na_icon_input_dir = os.path.join(base_dir, 'na', 'portrait', 'local') jp_portrait_input_dir = os.path.join(base_dir, 'jp', 'full', 'corrected_data') na_portrait_input_dir = os.path.join(base_dir, 'na', 'full', 'corrected_data') hq_portrait_input_dir = os.path.join(base_dir, 'hq_images') animated_portrait_input_dir = os.path.join(base_dir, 'animated') orb_skins_input_dir = os.path.join(alt_base_dir, 'orb_styles', 'extract', 'jp') jp_voice_input_dir = os.path.join(alt_base_dir, 'voices', 'fixed', 'jp') na_voice_input_dir = os.path.join(alt_base_dir, 'voices', 'fixed', 'na') icon_output_dir = os.path.join(output_dir, 'icons') portrait_output_dir = os.path.join(output_dir, 'portraits') hq_portrait_output_dir = os.path.join(output_dir, 'hq_portraits') animated_portrait_output_dir = os.path.join(output_dir, 'animated_portraits') orb_skins_output_dir = os.path.join(output_dir, 'orb_skins') jp_voice_output_dir = os.path.join(output_dir, 'voices', 'jp') na_voice_output_dir = os.path.join(output_dir, 'voices', 'na') for jp_id in range(1, 9000): monster_id = jp_id monster_id_filled = str(monster_id).zfill(5) do_copy(jp_icon_input_dir, '{}.png'.format(monster_id), icon_output_dir, '{}.png'.format(monster_id_filled)) do_copy(jp_portrait_input_dir, '{}.png'.format(monster_id), portrait_output_dir, '{}.png'.format(monster_id_filled)) do_copy(hq_portrait_input_dir, '{}.png'.format(monster_id), hq_portrait_output_dir, '{}.png'.format(monster_id_filled)) do_copy(animated_portrait_input_dir, '{}.mp4'.format(monster_id), animated_portrait_output_dir, '{}.mp4'.format(monster_id_filled)) do_copy(animated_portrait_input_dir, '{}.gif'.format(monster_id), animated_portrait_output_dir, '{}.gif'.format(monster_id_filled)) do_copy(jp_voice_input_dir, '{}.wav'.format(monster_id), jp_voice_output_dir, '{}.wav'.format(monster_id_filled)) for na_id in range(1, 9000): monster_id = monster_id_mapping.nakr_no_to_monster_id(MonsterNo(na_id)) monster_id_filled = str(monster_id).zfill(5) do_copy(na_icon_input_dir, '{}.png'.format(na_id), icon_output_dir, '{}.png'.format(monster_id_filled)) do_copy(na_portrait_input_dir, '{}.png'.format(na_id), portrait_output_dir, '{}.png'.format(monster_id_filled)) do_copy(na_voice_input_dir, '{}.wav'.format(na_id), na_voice_output_dir, '{}.wav'.format(monster_id_filled)) for file_name in os.listdir(orb_skins_input_dir): clean_file_name = file_name.lower().lstrip('block') do_copy(orb_skins_input_dir, file_name, orb_skins_output_dir, clean_file_name)
def convert(self, wave_items: List[WaveItem], try_common_monsters: bool) -> ResultFloor: result = ProcessedFloor() waves_by_entry = defaultdict(list) waves_by_stage_and_entry = defaultdict(lambda: defaultdict(list)) for wave_item in wave_items: drop_id = wave_item.get_drop() # Stuff in this range is supposedly: # 9900: coins # 9901: stones # 9902: pal points # 9911: gift dungeon # 9912: monster points # 9916: permanent dungeon # 9917: badge # 9999: announcement if drop_id and (9000 < drop_id < 10000): raise ValueError('Special drop detected (not handled yet)') # Correct for NA server mappings if necessary monster_id = wave_item.monster_id if wave_item.server != Server.jp: monster_id = monster_id_mapping.nakr_no_to_monster_id(monster_id) if drop_id: drop_id = monster_id_mapping.nakr_no_to_monster_id(drop_id) # Build a structure that merges DB info with wave data. card = self.data.card_by_monster_id(monster_id) drop = self.data.card_by_monster_id(drop_id) if drop_id else None wave_card = WaveCard(monster_id, card, wave_item, drop) # Store data for an individual dungeon entry. waves_by_entry[wave_item.entry_id].append(wave_card) # Store data for each stage, separated by dungeon entry. waves_by_stage_and_entry[wave_item.stage][wave_item.entry_id].append(wave_card) # Calculate stuff that should be done per-entry instead of per-floor. This more # correctly handles invades and alternate spawns. for entry_waves in waves_by_entry.values(): result.add_entry(entry_waves) # Calculate stuff at a per-stage level, like spawns and drops. invades = ProcessedStage(ProcessedStage.INVADE_IDX) stages = [ProcessedStage(i + 1) for i in sorted(waves_by_stage_and_entry.keys())] last_stage_idx = stages[-1].stage_idx for stage in stages: waves_for_stage = waves_by_stage_and_entry[stage.stage_idx - 1] for entry_waves in waves_for_stage.values(): if stage.stage_idx != last_stage_idx and entry_waves[0].wave_item.is_invade(): # Invades happen only on non-boss floors; some bosses represent as invades though. invades.add_wave_group(entry_waves) else: stage.add_wave_group(entry_waves) if invades.count: result.invades = invades result.stages.extend(stages) return ResultFloor(result, try_common_monsters)