74f3ab7c3f
- Added support for Card Maker 1.36.xx - Added cards importer to ONGEKI importer - Added 4 new 1.36 gachas (requires importing them from opt files) - Fixed version for Card Maker opt importer
162 lines
6.8 KiB
Python
162 lines
6.8 KiB
Python
from decimal import Decimal
|
|
import logging
|
|
import os
|
|
import re
|
|
import xml.etree.ElementTree as ET
|
|
from typing import Any, Dict, List, Optional
|
|
|
|
from read import BaseReader
|
|
from core.config import CoreConfig
|
|
from titles.ongeki.database import OngekiData
|
|
from titles.ongeki.const import OngekiConstants
|
|
from titles.ongeki.config import OngekiConfig
|
|
|
|
|
|
class OngekiReader(BaseReader):
|
|
def __init__(self, config: CoreConfig, version: int, bin_dir: Optional[str],
|
|
opt_dir: Optional[str], extra: Optional[str]) -> None:
|
|
super().__init__(config, version, bin_dir, opt_dir, extra)
|
|
self.data = OngekiData(config)
|
|
|
|
try:
|
|
self.logger.info(
|
|
f"Start importer for {OngekiConstants.game_ver_to_string(version)}")
|
|
except IndexError:
|
|
self.logger.error(f"Invalid ongeki version {version}")
|
|
exit(1)
|
|
|
|
def read(self) -> None:
|
|
data_dirs = []
|
|
if self.bin_dir is not None:
|
|
data_dirs += self.get_data_directories(self.bin_dir)
|
|
|
|
if self.opt_dir is not None:
|
|
data_dirs += self.get_data_directories(self.opt_dir)
|
|
|
|
for dir in data_dirs:
|
|
self.read_events(f"{dir}/event")
|
|
self.read_music(f"{dir}/music")
|
|
self.read_card(f"{dir}/card")
|
|
|
|
def read_card(self, base_dir: str) -> None:
|
|
self.logger.info(f"Reading cards from {base_dir}...")
|
|
|
|
version_ids = {
|
|
'1000': OngekiConstants.VER_ONGEKI,
|
|
'1005': OngekiConstants.VER_ONGEKI_PLUS,
|
|
'1010': OngekiConstants.VER_ONGEKI_SUMMER,
|
|
'1015': OngekiConstants.VER_ONGEKI_SUMMER_PLUS,
|
|
'1020': OngekiConstants.VER_ONGEKI_RED,
|
|
'1025': OngekiConstants.VER_ONGEKI_RED_PLUS,
|
|
'1030': OngekiConstants.VER_ONGEKI_BRIGHT,
|
|
'1035': OngekiConstants.VER_ONGEKI_BRIGHT_MEMORY
|
|
}
|
|
|
|
for root, dirs, files in os.walk(base_dir):
|
|
for dir in dirs:
|
|
if os.path.exists(f"{root}/{dir}/Card.xml"):
|
|
with open(f"{root}/{dir}/Card.xml", "r", encoding="utf-8") as f:
|
|
troot = ET.fromstring(f.read())
|
|
|
|
card_id = int(troot.find('Name').find('id').text)
|
|
|
|
# skip already existing cards
|
|
if self.data.static.get_card(
|
|
OngekiConstants.VER_ONGEKI_BRIGHT_MEMORY, card_id) is not None:
|
|
|
|
self.logger.info(f"Card {card_id} already added, skipping")
|
|
continue
|
|
|
|
name = troot.find('Name').find('str').text
|
|
chara_id = int(troot.find('CharaID').find('id').text)
|
|
nick_name = troot.find('NickName').text
|
|
school = troot.find('School').find('str').text
|
|
attribute = troot.find('Attribute').text
|
|
gakunen = troot.find('Gakunen').find('str').text
|
|
rarity = OngekiConstants.RARITY_TYPES[
|
|
troot.find('Rarity').text].value
|
|
|
|
level_param = []
|
|
for lvl in troot.find('LevelParam').findall('int'):
|
|
level_param.append(lvl.text)
|
|
|
|
skill_id = int(troot.find('SkillID').find('id').text)
|
|
cho_kai_ka_skill_id = int(troot.find('ChoKaikaSkillID').find('id').text)
|
|
|
|
version = version_ids[
|
|
troot.find('VersionID').find('id').text]
|
|
card_number = troot.find('CardNumberString').text
|
|
|
|
self.data.static.put_card(
|
|
version,
|
|
card_id,
|
|
name=name,
|
|
charaId=chara_id,
|
|
nickName=nick_name,
|
|
school=school,
|
|
attribute=attribute,
|
|
gakunen=gakunen,
|
|
rarity=rarity,
|
|
levelParam=','.join(level_param),
|
|
skillId=skill_id,
|
|
choKaikaSkillId=cho_kai_ka_skill_id,
|
|
cardNumber=card_number
|
|
)
|
|
self.logger.info(f"Added card {card_id}")
|
|
|
|
def read_events(self, base_dir: str) -> None:
|
|
self.logger.info(f"Reading events from {base_dir}...")
|
|
|
|
for root, dirs, files in os.walk(base_dir):
|
|
for dir in dirs:
|
|
if os.path.exists(f"{root}/{dir}/Event.xml"):
|
|
with open(f"{root}/{dir}/Event.xml", "r", encoding="utf-8") as f:
|
|
troot = ET.fromstring(f.read())
|
|
|
|
name = troot.find('Name').find('str').text
|
|
id = int(troot.find('Name').find('id').text)
|
|
event_type = OngekiConstants.EVT_TYPES[troot.find(
|
|
'EventType').text].value
|
|
|
|
self.data.static.put_event(
|
|
self.version, id, event_type, name)
|
|
self.logger.info(f"Added event {id}")
|
|
|
|
def read_music(self, base_dir: str) -> None:
|
|
self.logger.info(f"Reading music from {base_dir}...")
|
|
|
|
for root, dirs, files in os.walk(base_dir):
|
|
for dir in dirs:
|
|
if os.path.exists(f"{root}/{dir}/Music.xml"):
|
|
strdata = ""
|
|
|
|
with open(f"{root}/{dir}/Music.xml", "r", encoding="utf-8") as f:
|
|
strdata = f.read()
|
|
|
|
troot = ET.fromstring(strdata)
|
|
|
|
if root is None:
|
|
continue
|
|
|
|
name = troot.find('Name')
|
|
song_id = name.find('id').text
|
|
title = name.find('str').text
|
|
artist = troot.find('ArtistName').find('str').text
|
|
genre = troot.find('Genre').find('str').text
|
|
|
|
fumens = troot.find("FumenData")
|
|
for fumens_data in fumens.findall('FumenData'):
|
|
path = fumens_data.find('FumenFile').find('path').text
|
|
if path is None or not os.path.exists(f"{root}/{dir}/{path}"):
|
|
continue
|
|
|
|
chart_id = int(path.split(".")[0].split("_")[1])
|
|
level = float(
|
|
f"{fumens_data.find('FumenConstIntegerPart').text}.{fumens_data.find('FumenConstFractionalPart').text}"
|
|
)
|
|
|
|
self.data.static.put_chart(
|
|
self.version, song_id, chart_id, title, artist, genre, level)
|
|
self.logger.info(
|
|
f"Added song {song_id} chart {chart_id}")
|