Enough of the profile portion to get festo to let you card in.
This commit is contained in:
parent
ed43e9d3e6
commit
149eca0aab
@ -1105,7 +1105,6 @@ class JubeatClan(
|
||||
return Node.void('gameend')
|
||||
|
||||
def format_scores(self, userid: UserID, profile: Profile, scores: List[Score]) -> Node:
|
||||
|
||||
root = Node.void('gametop')
|
||||
datanode = Node.void('data')
|
||||
root.add_child(datanode)
|
||||
|
@ -1,19 +1,25 @@
|
||||
# vim: set fileencoding=utf-8
|
||||
from typing import Dict, List, Optional
|
||||
import random
|
||||
from typing import Any, Dict, List, Optional, Set
|
||||
from typing_extensions import Final
|
||||
|
||||
from bemani.backend.jubeat.base import JubeatBase
|
||||
from bemani.backend.jubeat.common import (
|
||||
JubeatDemodataGetNewsHandler,
|
||||
JubeatGametopGetMeetingHandler,
|
||||
JubeatLoggerReportHandler,
|
||||
)
|
||||
from bemani.backend.jubeat.clan import JubeatClan
|
||||
|
||||
from bemani.common import VersionConstants
|
||||
from bemani.backend.base import Status
|
||||
from bemani.common import Profile, ValidatedDict, VersionConstants
|
||||
from bemani.data import UserID, Score
|
||||
from bemani.protocol import Node
|
||||
|
||||
|
||||
class JubeatFesto(
|
||||
JubeatDemodataGetNewsHandler,
|
||||
JubeatGametopGetMeetingHandler,
|
||||
JubeatLoggerReportHandler,
|
||||
JubeatBase
|
||||
):
|
||||
@ -70,14 +76,27 @@ class JubeatFesto(
|
||||
},
|
||||
}
|
||||
|
||||
EVENT_STATUS_OPEN: Final[int] = 0x1
|
||||
EVENT_STATUS_COMPLETE: Final[int] = 0x2
|
||||
|
||||
# TODO: Verify these
|
||||
COURSE_STATUS_SEEN: Final[int] = 0x01
|
||||
COURSE_STATUS_PLAYED: Final[int] = 0x02
|
||||
COURSE_STATUS_CLEARED: Final[int] = 0x04
|
||||
|
||||
# Return the netlog service so that Festo doesn't crash on coin-in.
|
||||
extra_services: List[str] = [
|
||||
'netlog',
|
||||
'slocal',
|
||||
]
|
||||
|
||||
def previous_version(self) -> Optional[JubeatBase]:
|
||||
return JubeatClan(self.data, self.config, self.model)
|
||||
|
||||
def __get_course_list(self) -> List[Dict[str, Any]]:
|
||||
return [
|
||||
]
|
||||
|
||||
def __get_global_info(self) -> Node:
|
||||
info = Node.void('info')
|
||||
|
||||
@ -388,3 +407,454 @@ class JubeatFesto(
|
||||
data.add_child(self.__get_global_info())
|
||||
|
||||
return shopinfo
|
||||
|
||||
def handle_gametop_regist_request(self, request: Node) -> Node:
|
||||
data = request.child('data')
|
||||
player = data.child('player')
|
||||
refid = player.child_value('refid')
|
||||
name = player.child_value('name')
|
||||
root = self.new_profile_by_refid(refid, name)
|
||||
return root
|
||||
|
||||
def handle_gametop_get_pdata_request(self, request: Node) -> Node:
|
||||
data = request.child('data')
|
||||
player = data.child('player')
|
||||
refid = player.child_value('refid')
|
||||
root = self.get_profile_by_refid(refid)
|
||||
if root is None:
|
||||
root = Node.void('gametop')
|
||||
root.set_attribute('status', str(Status.NO_PROFILE))
|
||||
return root
|
||||
|
||||
def handle_gametop_get_mdata_request(self, request: Node) -> Node:
|
||||
data = request.child('data')
|
||||
player = data.child('player')
|
||||
extid = player.child_value('jid')
|
||||
mdata_ver = player.child_value('mdata_ver') # Game requests mdata 3 times per profile for some reason
|
||||
if mdata_ver != 1:
|
||||
root = Node.void('gametop')
|
||||
datanode = Node.void('data')
|
||||
root.add_child(datanode)
|
||||
player = Node.void('player')
|
||||
datanode.add_child(player)
|
||||
player.add_child(Node.s32('jid', extid))
|
||||
playdata = Node.void('mdata_list')
|
||||
player.add_child(playdata)
|
||||
return root
|
||||
root = self.get_scores_by_extid(extid)
|
||||
if root is None:
|
||||
root = Node.void('gametop')
|
||||
root.set_attribute('status', str(Status.NO_PROFILE))
|
||||
return root
|
||||
|
||||
def format_scores(self, userid: UserID, profile: Profile, scores: List[Score]) -> Node:
|
||||
root = Node.void('gametop')
|
||||
datanode = Node.void('data')
|
||||
root.add_child(datanode)
|
||||
player = Node.void('player')
|
||||
datanode.add_child(player)
|
||||
player.add_child(Node.s32('jid', profile.extid))
|
||||
playdata = Node.void('mdata_list')
|
||||
player.add_child(playdata)
|
||||
|
||||
# TODO: Need to add hard mode charts, make previous games ignore them, and sum
|
||||
# them up here as well.
|
||||
music = ValidatedDict()
|
||||
for score in scores:
|
||||
data = music.get_dict(str(score.id))
|
||||
play_cnt = data.get_int_array('play_cnt', 3)
|
||||
clear_cnt = data.get_int_array('clear_cnt', 3)
|
||||
clear_flags = data.get_int_array('clear_flags', 3)
|
||||
fc_cnt = data.get_int_array('fc_cnt', 3)
|
||||
ex_cnt = data.get_int_array('ex_cnt', 3)
|
||||
points = data.get_int_array('points', 3)
|
||||
|
||||
# Replace data for this chart type
|
||||
play_cnt[score.chart] = score.plays
|
||||
clear_cnt[score.chart] = score.data.get_int('clear_count')
|
||||
fc_cnt[score.chart] = score.data.get_int('full_combo_count')
|
||||
ex_cnt[score.chart] = score.data.get_int('excellent_count')
|
||||
points[score.chart] = score.points
|
||||
|
||||
# Format the clear flags
|
||||
clear_flags[score.chart] = self.GAME_FLAG_BIT_PLAYED
|
||||
if score.data.get_int('clear_count') > 0:
|
||||
clear_flags[score.chart] |= self.GAME_FLAG_BIT_CLEARED
|
||||
if score.data.get_int('full_combo_count') > 0:
|
||||
clear_flags[score.chart] |= self.GAME_FLAG_BIT_FULL_COMBO
|
||||
if score.data.get_int('excellent_count') > 0:
|
||||
clear_flags[score.chart] |= self.GAME_FLAG_BIT_EXCELLENT
|
||||
|
||||
# Save chart data back
|
||||
data.replace_int_array('play_cnt', 3, play_cnt)
|
||||
data.replace_int_array('clear_cnt', 3, clear_cnt)
|
||||
data.replace_int_array('clear_flags', 3, clear_flags)
|
||||
data.replace_int_array('fc_cnt', 3, fc_cnt)
|
||||
data.replace_int_array('ex_cnt', 3, ex_cnt)
|
||||
data.replace_int_array('points', 3, points)
|
||||
|
||||
# Update the ghost (untyped)
|
||||
ghost = data.get('ghost', [None, None, None])
|
||||
ghost[score.chart] = score.data.get('ghost')
|
||||
data['ghost'] = ghost
|
||||
|
||||
# Save it back
|
||||
music.replace_dict(str(score.id), data)
|
||||
|
||||
for scoreid in music:
|
||||
scoredata = music.get_dict(scoreid)
|
||||
musicdata = Node.void('musicdata')
|
||||
playdata.add_child(musicdata)
|
||||
|
||||
musicdata.set_attribute('music_id', scoreid)
|
||||
normalnode = Node.void('normal')
|
||||
musicdata.add_child(normalnode)
|
||||
|
||||
normalnode.add_child(Node.s32_array('play_cnt', scoredata.get_int_array('play_cnt', 3)))
|
||||
normalnode.add_child(Node.s32_array('clear_cnt', scoredata.get_int_array('clear_cnt', 3)))
|
||||
normalnode.add_child(Node.s32_array('fc_cnt', scoredata.get_int_array('fc_cnt', 3)))
|
||||
normalnode.add_child(Node.s32_array('ex_cnt', scoredata.get_int_array('ex_cnt', 3)))
|
||||
normalnode.add_child(Node.s32_array('score', scoredata.get_int_array('points', 3)))
|
||||
normalnode.add_child(Node.s8_array('clear', scoredata.get_int_array('clear_flags', 3)))
|
||||
|
||||
for i, ghost in enumerate(scoredata.get('ghost', [None, None, None])):
|
||||
if ghost is None:
|
||||
continue
|
||||
|
||||
bar = Node.u8_array('bar', ghost)
|
||||
normalnode.add_child(bar)
|
||||
bar.set_attribute('seq', str(i))
|
||||
|
||||
return root
|
||||
|
||||
def format_profile(self, userid: UserID, profile: Profile) -> Node:
|
||||
root = Node.void('gametop')
|
||||
data = Node.void('data')
|
||||
root.add_child(data)
|
||||
|
||||
# Jubeat Clan appears to allow full event overrides per-player
|
||||
data.add_child(self.__get_global_info())
|
||||
|
||||
player = Node.void('player')
|
||||
data.add_child(player)
|
||||
|
||||
# Basic profile info
|
||||
player.add_child(Node.string('name', profile.get_str('name', 'なし')))
|
||||
player.add_child(Node.s32('jid', profile.extid))
|
||||
|
||||
# Miscelaneous crap
|
||||
player.add_child(Node.s32('session_id', 1))
|
||||
player.add_child(Node.u64('event_flag', profile.get_int('event_flag')))
|
||||
|
||||
# Player info and statistics
|
||||
info = Node.void('info')
|
||||
player.add_child(info)
|
||||
info.add_child(Node.s32('tune_cnt', profile.get_int('tune_cnt')))
|
||||
info.add_child(Node.s32('save_cnt', profile.get_int('save_cnt')))
|
||||
info.add_child(Node.s32('saved_cnt', profile.get_int('saved_cnt')))
|
||||
info.add_child(Node.s32('fc_cnt', profile.get_int('fc_cnt')))
|
||||
info.add_child(Node.s32('ex_cnt', profile.get_int('ex_cnt')))
|
||||
info.add_child(Node.s32('clear_cnt', profile.get_int('clear_cnt')))
|
||||
info.add_child(Node.s32('match_cnt', profile.get_int('match_cnt')))
|
||||
info.add_child(Node.s32('beat_cnt', profile.get_int('beat_cnt')))
|
||||
info.add_child(Node.s32('mynews_cnt', profile.get_int('mynews_cnt')))
|
||||
info.add_child(Node.s32('mtg_entry_cnt', profile.get_int('mtg_entry_cnt')))
|
||||
info.add_child(Node.s32('mtg_hold_cnt', profile.get_int('mtg_hold_cnt')))
|
||||
info.add_child(Node.u8('mtg_result', profile.get_int('mtg_result')))
|
||||
info.add_child(Node.s32('bonus_tune_points', profile.get_int('bonus_tune_points')))
|
||||
info.add_child(Node.bool('is_bonus_tune_played', profile.get_bool('is_bonus_tune_played')))
|
||||
|
||||
# Looks to be set to true when there's an old profile, stops tutorial from
|
||||
# happening on first load.
|
||||
info.add_child(Node.bool('inherit', profile.get_bool('has_old_version')))
|
||||
|
||||
# Last played data, for showing cursor and such
|
||||
lastdict = profile.get_dict('last')
|
||||
last = Node.void('last')
|
||||
player.add_child(last)
|
||||
last.add_child(Node.s64('play_time', lastdict.get_int('play_time')))
|
||||
last.add_child(Node.string('shopname', lastdict.get_str('shopname')))
|
||||
last.add_child(Node.string('areaname', lastdict.get_str('areaname')))
|
||||
last.add_child(Node.s32('music_id', lastdict.get_int('music_id')))
|
||||
last.add_child(Node.s8('seq_id', lastdict.get_int('seq_id')))
|
||||
last.add_child(Node.s8('sort', lastdict.get_int('sort')))
|
||||
last.add_child(Node.s8('category', lastdict.get_int('category')))
|
||||
last.add_child(Node.s8('expert_option', lastdict.get_int('expert_option')))
|
||||
|
||||
settings = Node.void('settings')
|
||||
last.add_child(settings)
|
||||
settings.add_child(Node.s8('marker', lastdict.get_int('marker')))
|
||||
settings.add_child(Node.s8('theme', lastdict.get_int('theme')))
|
||||
settings.add_child(Node.s16('title', lastdict.get_int('title')))
|
||||
settings.add_child(Node.s16('parts', lastdict.get_int('parts')))
|
||||
settings.add_child(Node.s8('rank_sort', lastdict.get_int('rank_sort')))
|
||||
settings.add_child(Node.s8('combo_disp', lastdict.get_int('combo_disp')))
|
||||
settings.add_child(Node.s16_array('emblem', lastdict.get_int_array('emblem', 5)))
|
||||
settings.add_child(Node.s8('matching', lastdict.get_int('matching')))
|
||||
settings.add_child(Node.s8('hard', lastdict.get_int('hard')))
|
||||
settings.add_child(Node.s8('hazard', lastdict.get_int('hazard')))
|
||||
|
||||
# Secret unlocks, TODO: Make these configurable so events work.
|
||||
item = Node.void('item')
|
||||
player.add_child(item)
|
||||
item.add_child(Node.s32_array('music_list', profile.get_int_array('music_list', 64, [-1] * 64)))
|
||||
item.add_child(Node.s32_array('secret_list', profile.get_int_array('secret_list', 64, [-1] * 64)))
|
||||
item.add_child(Node.s32_array('theme_list', profile.get_int_array('theme_list', 16, [-1] * 16)))
|
||||
item.add_child(Node.s32_array('marker_list', profile.get_int_array('marker_list', 16, [-1] * 16)))
|
||||
item.add_child(Node.s32_array('title_list', profile.get_int_array('title_list', 160, [-1] * 160)))
|
||||
item.add_child(Node.s32_array('parts_list', profile.get_int_array('parts_list', 160, [-1] * 160)))
|
||||
item.add_child(Node.s32_array('emblem_list', profile.get_int_array('emblem_list', 96, [-1] * 96)))
|
||||
item.add_child(Node.s32_array('commu_list', profile.get_int_array('commu_list', 16, [-1] * 16)))
|
||||
|
||||
new = Node.void('new')
|
||||
item.add_child(new)
|
||||
new.add_child(Node.s32_array('secret_list', profile.get_int_array('secret_list_new', 64, [-1] * 64)))
|
||||
new.add_child(Node.s32_array('theme_list', profile.get_int_array('theme_list_new', 16, [-1] * 16)))
|
||||
new.add_child(Node.s32_array('marker_list', profile.get_int_array('marker_list_new', 16, [-1] * 16)))
|
||||
|
||||
# Add rivals to profile.
|
||||
rivallist = Node.void('rivallist')
|
||||
player.add_child(rivallist)
|
||||
|
||||
links = self.data.local.user.get_links(self.game, self.version, userid)
|
||||
rivalcount = 0
|
||||
for link in links:
|
||||
if link.type != 'rival':
|
||||
continue
|
||||
|
||||
rprofile = self.get_profile(link.other_userid)
|
||||
if rprofile is None:
|
||||
continue
|
||||
|
||||
rival = Node.void('rival')
|
||||
rivallist.add_child(rival)
|
||||
rival.add_child(Node.s32('jid', rprofile.extid))
|
||||
rival.add_child(Node.string('name', rprofile.get_str('name')))
|
||||
|
||||
# This looks like a carry-over from prop's career and isn't displayed.
|
||||
career = Node.void('career')
|
||||
rival.add_child(career)
|
||||
career.add_child(Node.s16('level', 1))
|
||||
|
||||
# Lazy way of keeping track of rivals, since we can only have 3
|
||||
# or the game with throw up.
|
||||
rivalcount += 1
|
||||
if rivalcount >= 3:
|
||||
break
|
||||
|
||||
lab_edit_seq = Node.void('lab_edit_seq')
|
||||
player.add_child(lab_edit_seq)
|
||||
lab_edit_seq.set_attribute('count', '0')
|
||||
|
||||
# Full combo challenge
|
||||
entry = self.data.local.game.get_time_sensitive_settings(self.game, self.version, 'fc_challenge')
|
||||
if entry is None:
|
||||
entry = ValidatedDict()
|
||||
|
||||
# Figure out if we've played these songs
|
||||
start_time, end_time = self.data.local.network.get_schedule_duration('daily')
|
||||
today_attempts = self.data.local.music.get_all_attempts(
|
||||
self.game, self.version, userid, entry.get_int('today', -1), timelimit=start_time
|
||||
)
|
||||
whim_attempts = self.data.local.music.get_all_attempts(
|
||||
self.game, self.version, userid, entry.get_int('whim', -1), timelimit=start_time
|
||||
)
|
||||
|
||||
# TODO: Are these still the right state constants?
|
||||
fc_challenge = Node.void('fc_challenge')
|
||||
player.add_child(fc_challenge)
|
||||
today = Node.void('today')
|
||||
fc_challenge.add_child(today)
|
||||
today.add_child(Node.s32('music_id', entry.get_int('today', -1)))
|
||||
today.add_child(Node.u8('state', 0x40 if len(today_attempts) > 0 else 0x0))
|
||||
whim = Node.void('whim')
|
||||
fc_challenge.add_child(whim)
|
||||
whim.add_child(Node.s32('music_id', entry.get_int('whim', -1)))
|
||||
whim.add_child(Node.u8('state', 0x40 if len(whim_attempts) > 0 else 0x0))
|
||||
|
||||
# No news, ever.
|
||||
official_news = Node.void('official_news')
|
||||
player.add_child(official_news)
|
||||
news_list = Node.void('news_list')
|
||||
official_news.add_child(news_list)
|
||||
|
||||
# Sane defaults for unknown/who cares nodes
|
||||
history = Node.void('history')
|
||||
player.add_child(history)
|
||||
history.set_attribute('count', '0')
|
||||
|
||||
free_first_play = Node.void('free_first_play')
|
||||
player.add_child(free_first_play)
|
||||
free_first_play.add_child(Node.bool('is_available', False))
|
||||
|
||||
# Player status for events
|
||||
event_info = Node.void('event_info')
|
||||
player.add_child(event_info)
|
||||
achievements = self.data.local.user.get_achievements(self.game, self.version, userid)
|
||||
event_completion: Dict[int, bool] = {}
|
||||
course_completion: Dict[int, ValidatedDict] = {}
|
||||
for achievement in achievements:
|
||||
if achievement.type == 'event':
|
||||
event_completion[achievement.id] = achievement.data.get_bool('is_completed')
|
||||
if achievement.type == 'course':
|
||||
course_completion[achievement.id] = achievement.data
|
||||
|
||||
for eventid, eventdata in self.EVENTS.items():
|
||||
# There are two significant bits here, bit 0 and bit 1, I think the first
|
||||
# one is whether the event is started, second is if its finished?
|
||||
event = Node.void('event')
|
||||
event_info.add_child(event)
|
||||
event.set_attribute('type', str(eventid))
|
||||
|
||||
state = 0x0
|
||||
state |= self.EVENT_STATUS_OPEN if eventdata['enabled'] else 0
|
||||
state |= self.EVENT_STATUS_COMPLETE if event_completion.get(eventid, False) else 0
|
||||
event.add_child(Node.u8('state', state))
|
||||
|
||||
# JBox stuff
|
||||
jbox = Node.void('jbox')
|
||||
jboxdict = profile.get_dict('jbox')
|
||||
player.add_child(jbox)
|
||||
jbox.add_child(Node.s32('point', jboxdict.get_int('point')))
|
||||
emblem = Node.void('emblem')
|
||||
jbox.add_child(emblem)
|
||||
normal = Node.void('normal')
|
||||
emblem.add_child(normal)
|
||||
premium = Node.void('premium')
|
||||
emblem.add_child(premium)
|
||||
|
||||
# Calculate a random index for normal and premium to give to player
|
||||
# as a gatcha.
|
||||
gameitems = self.data.local.game.get_items(self.game, self.version)
|
||||
normalemblems: Set[int] = set()
|
||||
premiumemblems: Set[int] = set()
|
||||
for gameitem in gameitems:
|
||||
if gameitem.type == 'emblem':
|
||||
if gameitem.data.get_int('rarity') in {1, 2, 3}:
|
||||
normalemblems.add(gameitem.id)
|
||||
if gameitem.data.get_int('rarity') in {3, 4, 5}:
|
||||
premiumemblems.add(gameitem.id)
|
||||
|
||||
# Default to some emblems in case the catalog is not available.
|
||||
normalindex = 2
|
||||
premiumindex = 1
|
||||
if normalemblems:
|
||||
normalindex = random.sample(normalemblems, 1)[0]
|
||||
if premiumemblems:
|
||||
premiumindex = random.sample(premiumemblems, 1)[0]
|
||||
|
||||
normal.add_child(Node.s16('index', normalindex))
|
||||
premium.add_child(Node.s16('index', premiumindex))
|
||||
|
||||
# New Music stuff
|
||||
new_music = Node.void('new_music')
|
||||
player.add_child(new_music)
|
||||
|
||||
navi = Node.void('navi')
|
||||
player.add_child(navi)
|
||||
navi.add_child(Node.u64('flag', profile.get_int('navi_flag')))
|
||||
|
||||
# Gift list, maybe from other players?
|
||||
gift_list = Node.void('gift_list')
|
||||
player.add_child(gift_list)
|
||||
# If we had gifts, they look like this. This is incomplete, however,
|
||||
# because I never bothered to find the virtual function to decode "detail".
|
||||
# Note that detail is only necessary if you don't want to give reason/id,
|
||||
# so its gotta be some hacked-on override.
|
||||
# <gift reason="??" id="??">
|
||||
# <detail>??</detail>
|
||||
# </gift>
|
||||
|
||||
# Birthday event?
|
||||
born = Node.void('born')
|
||||
player.add_child(born)
|
||||
born.add_child(Node.s8('status', profile.get_int('born_status')))
|
||||
born.add_child(Node.s16('year', profile.get_int('born_year')))
|
||||
|
||||
# More crap
|
||||
question_list = Node.void('question_list')
|
||||
player.add_child(question_list)
|
||||
|
||||
emo_list = Node.void('emo_list')
|
||||
player.add_child(emo_list)
|
||||
|
||||
# Some server node
|
||||
server = Node.void('server')
|
||||
player.add_child(server)
|
||||
|
||||
# Course List Progress
|
||||
course_list = Node.void('course_list')
|
||||
player.add_child(course_list)
|
||||
|
||||
# Each course that we have completed has one of the following nodes.
|
||||
for course in self.__get_course_list():
|
||||
status_dict = course_completion.get(course['id'], ValidatedDict())
|
||||
status = 0
|
||||
status |= self.COURSE_STATUS_SEEN if status_dict.get_bool('seen') else 0
|
||||
status |= self.COURSE_STATUS_PLAYED if status_dict.get_bool('played') else 0
|
||||
status |= self.COURSE_STATUS_CLEARED if status_dict.get_bool('cleared') else 0
|
||||
|
||||
coursenode = Node.void('course')
|
||||
course_list.add_child(coursenode)
|
||||
coursenode.set_attribute('id', str(course['id']))
|
||||
coursenode.add_child(Node.s8('status', status))
|
||||
|
||||
# For some reason, this is on the course list node this time around.
|
||||
category_list = Node.void('category_list')
|
||||
course_list.add_child(category_list)
|
||||
|
||||
# Fill in category
|
||||
fill_in_category = Node.void('fill_in_category')
|
||||
player.add_child(fill_in_category)
|
||||
|
||||
normal = Node.void('normal')
|
||||
fill_in_category.add_child(normal)
|
||||
normal.add_child(
|
||||
Node.s32_array('no_gray_flag_list', profile.get_int_array('normal_no_gray_flag_list', 16, [-1] * 16))
|
||||
)
|
||||
normal.add_child(
|
||||
Node.s32_array('all_yellow_flag_list', profile.get_int_array('normal_all_yellow_flag_list', 16, [-1] * 16))
|
||||
)
|
||||
normal.add_child(
|
||||
Node.s32_array('full_combo_flag_list', profile.get_int_array('normal_full_combo_flag_list', 16, [-1] * 16))
|
||||
)
|
||||
normal.add_child(
|
||||
Node.s32_array('excellent_flag_list', profile.get_int_array('normal_excellent_flag_list', 16, [-1] * 16))
|
||||
)
|
||||
|
||||
hard = Node.void('hard')
|
||||
fill_in_category.add_child(hard)
|
||||
hard.add_child(
|
||||
Node.s32_array('no_gray_flag_list', profile.get_int_array('hard_no_gray_flag_list', 16, [-1] * 16))
|
||||
)
|
||||
hard.add_child(
|
||||
Node.s32_array('all_yellow_flag_list', profile.get_int_array('hard_all_yellow_flag_list', 16, [-1] * 16))
|
||||
)
|
||||
hard.add_child(
|
||||
Node.s32_array('full_combo_flag_list', profile.get_int_array('hard_full_combo_flag_list', 16, [-1] * 16))
|
||||
)
|
||||
hard.add_child(
|
||||
Node.s32_array('excellent_flag_list', profile.get_int_array('hard_excellent_flag_list', 16, [-1] * 16))
|
||||
)
|
||||
|
||||
# TODO: Unknown department stuff
|
||||
department = Node.void('department')
|
||||
player.add_child(department)
|
||||
department.add_child(Node.void('shop_list'))
|
||||
|
||||
# TODO: Unknown stamp stuff
|
||||
stamp = Node.void('stamp')
|
||||
player.add_child(stamp)
|
||||
stamp.add_child(Node.void('sheet_list'))
|
||||
|
||||
# TODO: team_battle?
|
||||
|
||||
# TODO: eamuse_gift_list?
|
||||
|
||||
# TODO: hike_event
|
||||
|
||||
# TODO: festo_dungeon
|
||||
|
||||
# TODO: travel
|
||||
|
||||
return root
|
||||
|
Loading…
Reference in New Issue
Block a user