diff --git a/PyTaiko.py b/PyTaiko.py index 802aeb2..23322a9 100644 --- a/PyTaiko.py +++ b/PyTaiko.py @@ -32,6 +32,7 @@ from scenes.song_select import SongSelectScreen from scenes.title import TitleScreen from scenes.two_player.song_select import TwoPlayerSongSelectScreen from scenes.dan.dan_select import DanSelectScreen +from scenes.dan.dan_result import DanResultScreen logger = logging.getLogger(__name__) @@ -47,6 +48,7 @@ class Screens: SONG_SELECT_2P = "SONG_SELECT_2P" DAN_SELECT = "DAN_SELECT" GAME_DAN = "GAME_DAN" + DAN_RESULT = "DAN_RESULT" SETTINGS = "SETTINGS" DEV_MENU = "DEV_MENU" LOADING = "LOADING" @@ -163,6 +165,7 @@ def main(): dev_screen = DevScreen('dev') dan_select_screen = DanSelectScreen('dan_select') game_screen_dan = DanGameScreen('game_dan') + dan_result_screen = DanResultScreen('dan_result') screen_mapping: dict[str, Screen] = { Screens.ENTRY: entry_screen, @@ -177,6 +180,7 @@ def main(): Screens.DEV_MENU: dev_screen, Screens.DAN_SELECT: dan_select_screen, Screens.GAME_DAN: game_screen_dan, + Screens.DAN_RESULT: dan_result_screen, Screens.LOADING: load_screen } target = ray.load_render_texture(screen_width, screen_height) diff --git a/libs/file_navigator.py b/libs/file_navigator.py index 6330f0f..8133689 100644 --- a/libs/file_navigator.py +++ b/libs/file_navigator.py @@ -492,7 +492,7 @@ class YellowBox: self._draw_text(song_box) class DanBox: - def __init__(self, title: str, color: int, songs: list[tuple[TJAParser, int, int]], exams: list['Exam']): + def __init__(self, title: str, color: int, songs: list[tuple[TJAParser, int, int, int]], exams: list['Exam']): self.position = -11111 self.start_position = -1 self.target_position = -1 @@ -505,7 +505,7 @@ class DanBox: self.exams = exams self.song_text: list[tuple[OutlinedText, OutlinedText]] = [] self.total_notes = 0 - for song, genre_index, difficulty in self.songs: + for song, genre_index, difficulty, level in self.songs: notes, branch_m, branch_e, branch_n = song.notes_to_position(difficulty) self.total_notes += sum(1 for note in notes.play_notes if note.type < 5) for branch in branch_m: @@ -550,7 +550,7 @@ class DanBox: self.name = OutlinedText(self.title, 40, ray.WHITE, vertical=True) self.hori_name = OutlinedText(self.title, 40, ray.WHITE) if self.is_open and not self.song_text: - for song, genre, difficulty in self.songs: + for song, genre, difficulty, level in self.songs: title = song.metadata.title.get(global_data.config["general"]["language"], song.metadata.title["en"]) subtitle = song.metadata.subtitle.get(global_data.config["general"]["language"], "") title_text = OutlinedText(title, 40, ray.WHITE, vertical=True) @@ -907,7 +907,8 @@ class DanCourse(FileSystemItem): _, genre_index, _ = parse_box_def(path.parent.parent) else: genre_index = 9 - self.charts.append((TJAParser(path), genre_index, difficulty)) + tja = TJAParser(path) + self.charts.append((tja, genre_index, difficulty, tja.metadata.course_data[difficulty].level)) else: pass #do something with song_title, song_subtitle diff --git a/libs/global_data.py b/libs/global_data.py index b1bfb5c..1d0016e 100644 --- a/libs/global_data.py +++ b/libs/global_data.py @@ -90,6 +90,65 @@ class Modifiers: inverse: bool = False random: int = 0 +@dataclass +class DanResultSong: + """ + Data class for storing dan result song data. + """ + selected_difficulty: int = 0 + diff_level: int = 0 + song_title: str = "default_title" + genre_index: int = 0 + good: int = 0 + ok: int = 0 + bad: int = 0 + drumroll: int = 0 + +class DanResultExam: + """ + Data class for storing dan result exam data. + """ + progress: float = 0 + counter_value: int = 0 + bar_texture: str = "exam_red" + failed: bool = False + +@dataclass +class DanResultData: + """ + Data class for storing dan result data. + """ + dan_color: int = 0 + dan_title: str = "default_title" + score: int = 0 + gauge_length: float = 0.0 + max_combo: int = 0 + songs: list[DanResultSong] = field(default_factory=list) + exams: list[Any] = field(default_factory=list) + exam_data: list[DanResultExam] = field(default_factory=list) + +@dataclass +class ResultData: + """ + Data class for storing result data. + result_score: The score achieved in the game. + result_good: The number of good notes achieved in the game. + result_ok: The number of ok notes achieved in the game. + result_bad: The number of bad notes achieved in the game. + result_max_combo: The maximum combo achieved in the game. + result_total_drumroll: The total drumroll achieved in the game. + result_gauge_length: The length of the gauge achieved in the game. + prev_score: The previous score pulled from the database. + """ + score: int = 0 + good: int = 0 + ok: int = 0 + bad: int = 0 + max_combo: int = 0 + total_drumroll: int = 0 + gauge_length: float = 0 + prev_score: int = 0 + @dataclass class SessionData: """Data class for storing session data. Wiped after the result screen. @@ -99,30 +158,16 @@ class SessionData: dan_color: int: The emblem color of the selected dan selected_difficulty: The difficulty level selected by the user. song_title: The title of the song being played. - genre_index: The index of the genre being played. - result_score: The score achieved in the game. - result_good: The number of good notes achieved in the game. - result_ok: The number of ok notes achieved in the game. - result_bad: The number of bad notes achieved in the game. - result_max_combo: The maximum combo achieved in the game. - result_total_drumroll: The total drumroll achieved in the game. - result_gauge_length: The length of the gauge achieved in the game. - prev_score: The previous score pulled from the database.""" + genre_index: The index of the genre being played.""" selected_song: Path = Path() - selected_dan: list[tuple[Any, int, int]] = field(default_factory=lambda: []) + selected_dan: list[tuple[Any, int, int, int]] = field(default_factory=lambda: []) selected_dan_exam: list[Any] = field(default_factory=lambda: []) dan_color: int = 0 selected_difficulty: int = 0 - song_title: str = '' + song_title: str = "default_title" genre_index: int = 0 - result_score: int = 0 - result_good: int = 0 - result_ok: int = 0 - result_bad: int = 0 - result_max_combo: int = 0 - result_total_drumroll: int = 0 - result_gauge_length: float = 0 - prev_score: int = 0 + result_data: ResultData = field(default_factory=lambda: ResultData()) + dan_result_data: DanResultData = field(default_factory=lambda: DanResultData()) @dataclass class GlobalData: diff --git a/libs/global_objects.py b/libs/global_objects.py index 078ef7e..002797c 100644 --- a/libs/global_objects.py +++ b/libs/global_objects.py @@ -26,7 +26,7 @@ class Nameplate: self.is_gold = is_gold self.is_rainbow = is_rainbow self.title_bg = title_bg - if self.is_rainbow == True: + if self.is_rainbow: self.rainbow_animation = global_tex.get_animation(12) self.rainbow_animation.start() def update(self, current_time_ms: float): @@ -35,7 +35,7 @@ class Nameplate: Args: current_time_ms (float): The current time in milliseconds. """ - if self.is_rainbow == True: + if self.is_rainbow: self.rainbow_animation.update(current_time_ms) if self.rainbow_animation.is_finished: self.rainbow_animation.restart() @@ -60,7 +60,7 @@ class Nameplate: else: frame = self.title_bg title_offset = 14 - if self.is_rainbow == True: + if self.is_rainbow: if 0 < self.rainbow_animation.attribute < 6: tex.draw_texture('nameplate', 'frame_top_rainbow', frame=self.rainbow_animation.attribute-1, x=x, y=y, fade=fade) tex.draw_texture('nameplate', 'frame_top_rainbow', frame=self.rainbow_animation.attribute, x=x, y=y, fade=fade) diff --git a/scenes/dan/dan_result.py b/scenes/dan/dan_result.py index e69de29..e30c150 100644 --- a/scenes/dan/dan_result.py +++ b/scenes/dan/dan_result.py @@ -0,0 +1,265 @@ +import logging +import pyray as ray + +from libs.animation import Animation +from libs.chara_2d import Chara2D +from libs.global_data import reset_session +from libs.audio import audio +from libs.global_objects import AllNetIcon, CoinOverlay, Nameplate +from libs.screen import Screen +from libs.texture import tex +from libs.utils import ( + OutlinedText, + get_current_ms, + global_data, + is_l_don_pressed, + is_r_don_pressed +) +from scenes.game import Gauge +from scenes.result import Background + +logger = logging.getLogger(__name__) + +class DanResultScreen(Screen): + def on_screen_start(self): + super().on_screen_start() + audio.play_sound('bgm', 'music') + self.fade_out = tex.get_animation(0) + self.coin_overlay = CoinOverlay() + self.allnet_indicator = AllNetIcon() + self.start_ms = get_current_ms() + self.background = Background('4', 1280) + self.player = DanResultPlayer(global_data.player_num) + self.is_result_2 = False + self.result_2_fade_in = tex.get_animation(1) + self.gauge = DanGauge(str(global_data.player_num), global_data.session_data[global_data.player_num-1].dan_result_data.gauge_length) + self.song_names = [OutlinedText(song.song_title, 40, ray.WHITE) for song in global_data.session_data[global_data.player_num-1].dan_result_data.songs] + self.hori_name = OutlinedText(global_data.session_data[global_data.player_num-1].dan_result_data.dan_title, 40, ray.WHITE) + self.exam_info = global_data.session_data[global_data.player_num-1].dan_result_data.exams + self.exam_data = global_data.session_data[global_data.player_num-1].dan_result_data.exam_data + print(global_data.session_data[global_data.player_num-1].dan_result_data.songs) + + def on_screen_end(self, next_screen: str): + reset_session() + return super().on_screen_end(next_screen) + + def handle_input(self): + if is_r_don_pressed() or is_l_don_pressed(): + if self.is_result_2: + self.fade_out.start() + audio.play_sound('don', 'sound') + else: + audio.play_sound('don', 'sound') + self.result_2_fade_in.start() + self.is_result_2 = True + + def update(self): + super().update() + current_time = get_current_ms() + self.player.update(current_time) + self.handle_input() + + self.result_2_fade_in.update(current_time) + self.fade_out.update(current_time) + self.gauge.update(current_time) + if self.fade_out.is_finished: + self.fade_out.update(current_time) + return self.on_screen_end("DAN_SELECT") + + def draw_overlay(self): + ray.draw_rectangle(0, 0, 1280, 720, ray.fade(ray.BLACK, self.fade_out.attribute)) + self.coin_overlay.draw() + self.allnet_indicator.draw() + + def draw_song_info_1(self): + result_data = global_data.session_data[global_data.player_num-1].dan_result_data + height = 191 + for i in range(len(result_data.songs)): + song = result_data.songs[i] + tex.draw_texture('background', 'genre_banner', y=i*height, frame=song.genre_index) + self.song_names[i].draw(x=1230 - self.song_names[i].texture.width, y=i*height + 90) + tex.draw_texture('result_info', 'song_num', frame=i, y=i*height) + tex.draw_texture('result_info', 'difficulty', frame=song.selected_difficulty, y=i*height) + + tex.draw_texture('result_info', 'diff_star', y=i*height) + tex.draw_texture('result_info', 'diff_x', y=i*height) + counter = str(song.diff_level)[::-1] + margin = 12 + for j, digit in enumerate(counter): + tex.draw_texture('result_info', 'diff_num', frame=int(digit), x=-(j*margin), y=i*height) + + tex.draw_texture('result_info', 'good', y=i*height) + margin = 24 + counter = str(song.good)[::-1] + for j, digit in enumerate(counter): + tex.draw_texture('result_info', 'counter', index=0, frame=int(digit), x=-(j*margin), y=i*height) + tex.draw_texture('result_info', 'ok', y=i*height) + counter = str(song.ok)[::-1] + for j, digit in enumerate(counter): + tex.draw_texture('result_info', 'counter', index=1, frame=int(digit), x=-(j*margin), y=i*height) + tex.draw_texture('result_info', 'bad', y=i*height) + counter = str(song.bad)[::-1] + for j, digit in enumerate(counter): + tex.draw_texture('result_info', 'counter', index=2, frame=int(digit), x=-(j*margin), y=i*height) + tex.draw_texture('result_info', 'drumroll', y=i*height) + counter = str(song.drumroll)[::-1] + for j, digit in enumerate(counter): + tex.draw_texture('result_info', 'counter', index=3, frame=int(digit), x=-(j*margin), y=i*height) + + def draw_song_info_2(self, fade: float): + result_data = global_data.session_data[global_data.player_num-1].dan_result_data + tex.draw_texture('background', 'result_2_bg', fade=fade) + for i in range(5): + tex.draw_texture('background', 'result_2_divider', fade=fade, x=i*240) + tex.draw_texture('background', 'result_2_pullout', fade=fade) + tex.draw_texture('result_info', 'dan_emblem', fade=fade, frame=result_data.dan_color) + self.hori_name.draw(outline_color=ray.BLACK, x=276 - (self.hori_name.texture.width//2), + y=123, x2=min(self.hori_name.texture.width, 275)-self.hori_name.texture.width, color=ray.fade(ray.WHITE, fade)) + + tex.draw_texture('result_info', 'good', index=1, fade=fade) + margin = 24 + counter = str(sum(song.good for song in result_data.songs))[::-1] + for j, digit in enumerate(counter): + tex.draw_texture('result_info', 'counter', index=4, frame=int(digit), x=-(j*margin), fade=fade) + tex.draw_texture('result_info', 'ok', index=1, fade=fade) + counter = str(sum(song.ok for song in result_data.songs))[::-1] + for j, digit in enumerate(counter): + tex.draw_texture('result_info', 'counter', index=5, frame=int(digit), x=-(j*margin), fade=fade) + tex.draw_texture('result_info', 'bad', index=1, fade=fade) + counter = str(sum(song.bad for song in result_data.songs))[::-1] + for j, digit in enumerate(counter): + tex.draw_texture('result_info', 'counter', index=6, frame=int(digit), x=-(j*margin), fade=fade) + tex.draw_texture('result_info', 'drumroll', index=1, fade=fade) + counter = str(sum(song.drumroll for song in result_data.songs))[::-1] + for j, digit in enumerate(counter): + tex.draw_texture('result_info', 'counter', index=7, frame=int(digit), x=-(j*margin), fade=fade) + tex.draw_texture('result_info', 'max_combo', fade=fade) + counter = str(result_data.max_combo)[::-1] + for j, digit in enumerate(counter): + tex.draw_texture('result_info', 'counter', index=8, frame=int(digit), x=-(j*margin), fade=fade) + tex.draw_texture('result_info', 'max_hits', fade=fade) + counter = str(sum(song.drumroll + song.ok + song.bad + song.good for song in result_data.songs))[::-1] + for j, digit in enumerate(counter): + tex.draw_texture('result_info', 'counter', index=9, frame=int(digit), x=-(j*margin), fade=fade) + tex.draw_texture('result_info', 'exam_header', fade=fade) + + tex.draw_texture('result_info', 'score_box', fade=fade) + margin = 22 + counter = str(result_data.score)[::-1] + for j, digit in enumerate(counter): + tex.draw_texture('result_info', 'score_counter', frame=int(digit), x=-(j*margin), fade=fade) + + self.gauge.draw(fade) + + self.draw_dan_info(fade) + + if any(exam_data.failed for exam_data in self.exam_data): + tex.draw_texture('exam_info', 'fail', fade=fade) + elif all(exam_data.progress >= exam.gold for exam_data, exam in zip(self.exam_data, self.exam_info)): + tex.draw_texture('exam_info', 'gold_clear', fade=fade) + else: + tex.draw_texture('exam_info', 'red_clear', fade=fade) + + def draw_dan_info(self, fade: float, scale=0.8): + # Draw exam info + for i, exam in enumerate(self.exam_info): + exam_data = self.exam_data[i] + y_offset = i * 94 * scale # Scale the y offset + tex.draw_texture('exam_info', 'exam_bg', y=y_offset, fade=fade, scale=scale) + tex.draw_texture('exam_info', 'exam_overlay_1', y=y_offset, fade=fade, scale=scale) + # Draw progress bar + tex.draw_texture('exam_info', exam_data.bar_texture, x2=940*exam_data.progress*scale, y=y_offset, fade=fade, scale=scale) + # Draw exam type and red value counter + red_counter = str(exam.red) + self._draw_counter(red_counter, margin=22*scale, texture='value_counter', index=0, y=y_offset, fade=fade, scale=scale) + tex.draw_texture('exam_info', f'exam_{exam.type}', y=y_offset, x=-len(red_counter)*20*scale, fade=fade, scale=scale) + # Draw range indicator + if exam.range == 'less': + tex.draw_texture('exam_info', 'exam_less', y=y_offset, fade=fade, scale=scale) + elif exam.range == 'more': + tex.draw_texture('exam_info', 'exam_more', y=y_offset, fade=fade, scale=scale) + # Draw current value counter + tex.draw_texture('exam_info', 'exam_overlay_2', y=y_offset, fade=fade, scale=scale) + value_counter = str(exam_data.counter_value) + self._draw_counter(value_counter, margin=22*scale, texture='value_counter', index=1, y=y_offset, fade=fade, scale=scale) + if exam.type == 'gauge': + tex.draw_texture('exam_info', 'exam_percent', y=y_offset, index=1, fade=fade, scale=scale) + if exam_data.failed: + tex.draw_texture('exam_info', 'exam_bg', fade=min(fade, 0.5), y=y_offset, scale=scale) + tex.draw_texture('exam_info', 'exam_failed', y=y_offset, fade=fade, scale=scale) + + def _draw_counter(self, counter, margin, texture, index=None, y: float = 0.0, fade=0.0, scale=1.0): + """Helper to draw digit counters""" + for j in range(len(counter)): + kwargs = {'frame': int(counter[j]), 'x': -(len(counter) - j) * margin, 'y': y, 'fade': fade, 'scale': scale} + if index is not None: + kwargs['index'] = index + tex.draw_texture('exam_info', texture, **kwargs) + + def draw(self): + self.background.draw() + self.draw_song_info_1() + self.draw_song_info_2(self.result_2_fade_in.attribute) + self.player.draw() + self.draw_overlay() + +class DanResultPlayer: + def __init__(self, player_num: int): + plate_info = global_data.config[f'nameplate_{player_num}p'] + self.nameplate = Nameplate(plate_info['name'], plate_info['title'], player_num, plate_info['dan'], plate_info['gold'], plate_info['rainbow'], plate_info['title_bg']) + self.chara = Chara2D(player_num-1, 100) + + def update(self, current_time_ms: float): + self.nameplate.update(current_time_ms) + self.chara.update(current_time_ms, 100, False, False) + + def draw(self): + self.nameplate.draw(10, 585) + self.chara.draw(0, 405) + +class DanGauge(Gauge): + """The player's gauge""" + def __init__(self, player_num: str, gauge_length: float): + self.player_num = player_num + self.gauge_length = gauge_length + self.visual_length = int(self.gauge_length * 8) + self.gauge_max = 89 + self.tamashii_fire_change = tex.get_animation(25) + self.is_clear = False + self.is_rainbow = False + self.rainbow_animation = Animation.create_texture_change((16.67*8) * 3, textures=[((16.67 * 3) * i, (16.67 * 3) * (i + 1), i) for i in range(8)]) + self.rainbow_animation.start() + self.rainbow_fade_in = Animation.create_fade(450, initial_opacity=0.0, final_opacity=1.0) + self.rainbow_fade_in.start() + + def update(self, current_ms: float): + self.is_rainbow = self.gauge_length == self.gauge_max + self.is_clear = self.is_rainbow + self.tamashii_fire_change.update(current_ms) + self.rainbow_animation.update(current_ms) + self.rainbow_fade_in.update(current_ms) + if self.rainbow_animation.is_finished: + self.rainbow_animation.restart() + + def draw(self, fade: float = 1.0): + tex.draw_texture('gauge', f'{self.player_num}p_unfilled', fade=fade) + + if not self.is_rainbow: + tex.draw_texture('gauge', f'{self.player_num}p_bar', x2=self.visual_length-8, fade=fade) + + # Rainbow effect for full gauge + if self.is_rainbow: + if 0 < self.rainbow_animation.attribute < 8: + tex.draw_texture('gauge', 'rainbow', frame=self.rainbow_animation.attribute-1, fade=min(self.rainbow_fade_in.attribute, fade)) + tex.draw_texture('gauge', 'rainbow', frame=self.rainbow_animation.attribute, fade=min(self.rainbow_fade_in.attribute, fade)) + tex.draw_texture('gauge', 'overlay', fade=min(fade, 0.15)) + + # Draw clear status indicators + tex.draw_texture('gauge', 'footer', fade=fade) + if self.is_rainbow: + tex.draw_texture('gauge', 'tamashii_fire', scale=0.75, center=True, frame=self.tamashii_fire_change.attribute, fade=fade) + tex.draw_texture('gauge', 'tamashii', fade=fade) + if self.is_rainbow and self.tamashii_fire_change.attribute in (0, 1, 4, 5): + tex.draw_texture('gauge', 'tamashii_overlay', fade=min(fade, 0.5)) + else: + tex.draw_texture('gauge', 'tamashii_dark', fade=fade) diff --git a/scenes/dan/game_dan.py b/scenes/dan/game_dan.py index 00bf2a1..e2fc13e 100644 --- a/scenes/dan/game_dan.py +++ b/scenes/dan/game_dan.py @@ -6,7 +6,7 @@ from libs.animation import Animation from libs.audio import audio from libs.background import Background from libs.file_navigator import Exam -from libs.global_data import global_data +from libs.global_data import DanResultExam, DanResultSong, global_data from libs.global_objects import AllNetIcon from libs.tja import TJAParser from libs.transition import Transition @@ -61,7 +61,7 @@ class DanGameScreen(GameScreen): songs = copy.deepcopy(session_data.selected_dan) self.exams = copy.deepcopy(session_data.selected_dan_exam) self.total_notes = 0 - for song, genre_index, difficulty in songs: + for song, genre_index, difficulty, level in songs: notes, branch_m, branch_e, branch_n = song.notes_to_position(difficulty) self.total_notes += sum(1 for note in notes.play_notes if note.type < 5) for branch in branch_m: @@ -70,7 +70,7 @@ class DanGameScreen(GameScreen): self.total_notes += sum(1 for note in branch.play_notes if note.type < 5) for branch in branch_n: self.total_notes += sum(1 for note in branch.play_notes if note.type < 5) - song, genre_index, difficulty = songs[self.song_index] + song, genre_index, difficulty, level = songs[self.song_index] session_data.selected_difficulty = difficulty self.init_tja(song.file_path) self.color = session_data.dan_color @@ -87,7 +87,7 @@ class DanGameScreen(GameScreen): def change_song(self): session_data = global_data.session_data[global_data.player_num-1] songs = session_data.selected_dan - song, genre_index, difficulty = songs[self.song_index] + song, genre_index, difficulty, level = songs[self.song_index] session_data.selected_difficulty = difficulty self.player_1.difficulty = difficulty self.tja = TJAParser(song.file_path, start_delay=self.start_delay, distance=SCREEN_WIDTH - GameScreen.JUDGE_X) @@ -174,6 +174,8 @@ class DanGameScreen(GameScreen): @override def spawn_ending_anims(self): + if sum(song.bad for song in global_data.session_data[global_data.player_num-1].dan_result_data.songs) == 0: + self.player_1.ending_anim = FCAnimation(self.player_1.is_2p) if self.player_1.gauge.is_clear and not any(self.exam_failed): self.player_1.ending_anim = ClearAnimation(self.player_1.is_2p) elif not self.player_1.gauge.is_clear: @@ -201,12 +203,40 @@ class DanGameScreen(GameScreen): if self.result_transition.is_finished and not audio.is_sound_playing('dan_transition'): logger.info("Result transition finished, moving to RESULT screen") - return self.on_screen_end('RESULT') + return self.on_screen_end('DAN_RESULT') elif self.current_ms >= self.player_1.end_time + 1000: session_data = global_data.session_data[global_data.player_num-1] + if len(session_data.selected_dan) > len(session_data.dan_result_data.songs): + song_info = DanResultSong() + song_info.song_title = self.song_info.song_name + song_info.genre_index = session_data.selected_dan[self.song_index][1] + song_info.selected_difficulty = session_data.selected_dan[self.song_index][2] + song_info.diff_level = session_data.selected_dan[self.song_index][3] + prev_good_count = sum(song.good for song in session_data.dan_result_data.songs) + prev_ok_count = sum(song.ok for song in session_data.dan_result_data.songs) + prev_bad_count = sum(song.bad for song in session_data.dan_result_data.songs) + prev_drumroll_count = sum(song.drumroll for song in session_data.dan_result_data.songs) + song_info.good = self.player_1.good_count - prev_good_count + song_info.ok = self.player_1.ok_count - prev_ok_count + song_info.bad = self.player_1.bad_count - prev_bad_count + song_info.drumroll = self.player_1.total_drumroll - prev_drumroll_count + session_data.dan_result_data.songs.append(song_info) if self.song_index == len(session_data.selected_dan) - 1: if self.end_ms != 0: if current_time >= self.end_ms + 1000: + session_data.dan_result_data.dan_color = self.color + session_data.dan_result_data.dan_title = self.hori_name.text + session_data.dan_result_data.score = self.player_1.score + session_data.dan_result_data.gauge_length = self.player_1.gauge.gauge_length + session_data.dan_result_data.max_combo = self.player_1.max_combo + session_data.dan_result_data.exams = self.exams + for i in range(len(self.exams)): + exam_data = DanResultExam() + exam_data.bar_texture = self.dan_info_cache["exam_data"][i]["bar_texture"] + exam_data.counter_value = self.dan_info_cache["exam_data"][i]["counter_value"] + exam_data.failed = self.exam_failed[i] + exam_data.progress = self.dan_info_cache["exam_data"][i]["progress"] + session_data.dan_result_data.exam_data.append(exam_data) if self.player_1.ending_anim is None: self.spawn_ending_anims() if current_time >= self.end_ms + 8533.34: diff --git a/scenes/game.py b/scenes/game.py index 77afdb6..fb0120f 100644 --- a/scenes/game.py +++ b/scenes/game.py @@ -164,29 +164,29 @@ class GameScreen(Screen): existing_score = result[0] if result is not None else None existing_crown = result[1] if result is not None and len(result) > 1 and result[1] is not None else 0 crown = 0 - if session_data.result_bad and session_data.result_ok == 0: + if session_data.result_data.bad and session_data.result_data.ok == 0: crown = 3 - elif session_data.result_bad == 0: + elif session_data.result_data.bad == 0: crown = 2 elif self.player_1.gauge.is_clear: crown = 1 - logger.info(f"Existing score: {existing_score}, Existing crown: {existing_crown}, New score: {session_data.result_score}, New crown: {crown}") - if result is None or (existing_score is not None and session_data.result_score > existing_score): + logger.info(f"Existing score: {existing_score}, Existing crown: {existing_crown}, New score: {session_data.result_data.score}, New crown: {crown}") + if result is None or (existing_score is not None and session_data.result_data.score > existing_score): insert_query = ''' INSERT OR REPLACE INTO Scores (hash, en_name, jp_name, diff, score, good, ok, bad, drumroll, combo, clear) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?); ''' data = (hash, self.tja.metadata.title['en'], self.tja.metadata.title.get('ja', ''), self.player_1.difficulty, - session_data.result_score, session_data.result_good, - session_data.result_ok, session_data.result_bad, - session_data.result_total_drumroll, session_data.result_max_combo, crown) + session_data.result_data.score, session_data.result_data.good, + session_data.result_data.ok, session_data.result_data.bad, + session_data.result_data.total_drumroll, session_data.result_data.max_combo, crown) cursor.execute(insert_query, data) - session_data.prev_score = existing_score if existing_score is not None else 0 - logger.info(f"Wrote score {session_data.result_score} for {self.tja.metadata.title['en']}") + session_data.result_data.prev_score = existing_score if existing_score is not None else 0 + logger.info(f"Wrote score {session_data.result_data.score} for {self.tja.metadata.title['en']}") con.commit() if result is None or (existing_crown is not None and crown > existing_crown): - cursor.execute("UPDATE Scores SET crown = ? WHERE hash = ?", (crown, hash)) + cursor.execute("UPDATE Scores SET clear = ? WHERE hash = ?", (crown, hash)) con.commit() def start_song(self, current_time): @@ -212,7 +212,7 @@ class GameScreen(Screen): return self.on_screen_end('SONG_SELECT') def spawn_ending_anims(self): - if global_data.session_data[global_data.player_num-1].result_bad == 0: + if global_data.session_data[global_data.player_num-1].result_data.bad == 0: self.player_1.ending_anim = FCAnimation(self.player_1.is_2p) elif self.player_1.gauge.is_clear: self.player_1.ending_anim = ClearAnimation(self.player_1.is_2p) @@ -247,8 +247,8 @@ class GameScreen(Screen): return self.on_screen_end('RESULT') elif self.current_ms >= self.player_1.end_time: session_data = global_data.session_data[global_data.player_num-1] - session_data.result_score, session_data.result_good, session_data.result_ok, session_data.result_bad, session_data.result_max_combo, session_data.result_total_drumroll = self.player_1.get_result_score() - session_data.result_gauge_length = self.player_1.gauge.gauge_length + session_data.result_data.score, session_data.result_data.good, session_data.result_data.ok, session_data.result_data.bad, session_data.result_data.max_combo, session_data.result_data.total_drumroll = self.player_1.get_result_score() + session_data.result_data.gauge_length = self.player_1.gauge.gauge_length if self.end_ms != 0: if current_time >= self.end_ms + 1000: if self.player_1.ending_anim is None: diff --git a/scenes/result.py b/scenes/result.py index 16d8ad7..40ded71 100644 --- a/scenes/result.py +++ b/scenes/result.py @@ -118,20 +118,20 @@ class ResultPlayer: self.high_score_indicator = None self.chara = Chara2D(int(self.player_num) - 1, 100) session_data = global_data.session_data[int(self.player_num)-1] - self.score_animator = ScoreAnimator(session_data.result_score) + self.score_animator = ScoreAnimator(session_data.result_data.score) plate_info = global_data.config[f'nameplate_{self.player_num}p'] self.nameplate = Nameplate(plate_info['name'], plate_info['title'], int(self.player_num), plate_info['dan'], plate_info['gold'], plate_info['rainbow'], plate_info['title_bg']) self.score, self.good, self.ok, self.bad, self.max_combo, self.total_drumroll = '', '', '', '', '', '' - self.update_list: list[tuple[str, int]] = [('score', session_data.result_score), - ('good', session_data.result_good), - ('ok', session_data.result_ok), - ('bad', session_data.result_bad), - ('max_combo', session_data.result_max_combo), - ('total_drumroll', session_data.result_total_drumroll)] + self.update_list: list[tuple[str, int]] = [('score', session_data.result_data.score), + ('good', session_data.result_data.good), + ('ok', session_data.result_data.ok), + ('bad', session_data.result_data.bad), + ('max_combo', session_data.result_data.max_combo), + ('total_drumroll', session_data.result_data.total_drumroll)] self.update_index = 0 - if session_data.result_ok == 0 and session_data.result_bad == 0: + if session_data.result_data.ok == 0 and session_data.result_data.bad == 0: self.crown_type = 'crown_dfc' - elif session_data.result_bad == 0: + elif session_data.result_data.bad == 0: self.crown_type = 'crown_fc' else: self.crown_type = 'crown_clear' @@ -163,13 +163,13 @@ class ResultPlayer: self.score_delay += 16.67 * 3 if self.update_index > 0 and self.high_score_indicator is None: session_data = global_data.session_data[int(self.player_num)-1] - if session_data.result_score > session_data.prev_score: - self.high_score_indicator = HighScoreIndicator(session_data.prev_score, session_data.result_score, self.is_2p) + if session_data.result_data.score > session_data.result_data.prev_score: + self.high_score_indicator = HighScoreIndicator(session_data.result_data.prev_score, session_data.result_data.score, self.is_2p) def update(self, current_ms: float, fade_in_finished: bool, is_skipped: bool): self.fade_in_finished = fade_in_finished if self.fade_in_finished and self.gauge is None: - self.gauge = Gauge(self.player_num, global_data.session_data[int(self.player_num)-1].result_gauge_length, self.is_2p) + self.gauge = Gauge(self.player_num, global_data.session_data[int(self.player_num)-1].result_data.gauge_length, self.is_2p) self.bottom_characters.start() self.bottom_characters.update(self.state) self.update_score_animation(is_skipped) diff --git a/scenes/two_player/result.py b/scenes/two_player/result.py index 74d1de8..158a1ac 100644 --- a/scenes/two_player/result.py +++ b/scenes/two_player/result.py @@ -11,7 +11,6 @@ class TwoPlayerResultScreen(ResultScreen): self.fade_in = FadeIn('3') self.player_1 = ResultPlayer('1', True, False) self.player_2 = ResultPlayer('2', True, True) - logger.info("TwoPlayerResultScreen started, background and players initialized") def update(self): super(ResultScreen, self).update()