From 1c88e3ab317334eec2dbc5213d8da19f9aedf703 Mon Sep 17 00:00:00 2001 From: Anthony Samms Date: Mon, 15 Dec 2025 10:24:06 -0500 Subject: [PATCH] bug fixes --- libs/bg_objects/chibi.py | 6 ++--- libs/file_navigator.py | 57 +++++++++++++++++++++++++++++++--------- libs/song_hash.py | 28 +++++++++++++------- scenes/game.py | 26 ++++-------------- scenes/song_select.py | 11 ++++---- 5 files changed, 76 insertions(+), 52 deletions(-) diff --git a/libs/bg_objects/chibi.py b/libs/bg_objects/chibi.py index 0aa6dc5..c733a9c 100644 --- a/libs/bg_objects/chibi.py +++ b/libs/bg_objects/chibi.py @@ -48,10 +48,8 @@ class BaseChibi: textures = [((duration / len(self.keyframes))*i, (duration / len(self.keyframes))*(i+1), index) for i, index in enumerate(self.keyframes)] self.texture_change = Animation.create_texture_change(duration, textures=textures) self.texture_change.start() - self.hori_move = Animation.create_move(60000 / self.bpm * 5, total_distance=self.tex.screen_width) - self.hori_move.start() - self.vert_move = Animation.create_move(60000 / self.bpm / 2, total_distance=50 * self.tex.screen_scale, reverse_delay=0) - self.vert_move.start() + self.hori_move.duration = 60000 / self.bpm * 5 + self.vert_move.duration = 60000 / self.bpm / 2 def draw(self, tex: TextureWrapper): tex.draw_texture(self.name, str(self.index), frame=self.texture_change.attribute, x=self.hori_move.attribute, y=-self.vert_move.attribute+(self.is_2p*tex.skin_config["game_2p_offset"].y)) diff --git a/libs/file_navigator.py b/libs/file_navigator.py index 01ba001..02c25b1 100644 --- a/libs/file_navigator.py +++ b/libs/file_navigator.py @@ -1157,7 +1157,6 @@ class FileNavigator: content_items.append(self.all_song_files[song_key]) self.directory_contents[dir_key] = content_items - self.crown_cache_dirty.add(dir_key) else: # For directories without box.def, still process their children @@ -1374,22 +1373,56 @@ class FileNavigator: def _calculate_directory_crowns(self, dir_key: str, tja_files: list): """Pre-calculate crowns for a directory""" all_scores = dict() - crowns = dict() + child_has_any_crown = [] # Track if each child has been played at all - for song_obj in tja_files: - if not isinstance(song_obj, SongFile): - continue - for diff in song_obj.box.scores: - if diff not in all_scores: - all_scores[diff] = [] - all_scores[diff].append(song_obj.box.scores[diff]) + for item in tja_files: + has_crown = False + if isinstance(item, SongFile): + has_crown = any((item.box.scores.get(d) or (None,)*6)[5] is not None + for d in [Difficulty.EASY, Difficulty.NORMAL, Difficulty.HARD, Difficulty.ONI]) + for diff in item.box.scores: + if diff not in all_scores: + all_scores[diff] = [] + all_scores[diff].append(item.box.scores[diff]) + elif isinstance(item, Directory): + child_key = str(item.path) + child_crowns = self._get_directory_crowns_cached(child_key) + has_crown = bool(child_crowns) # Directory is "played" if it has any crowns + if not child_crowns: + # Unplayed directory - add None for all difficulties + for diff in [Difficulty.EASY, Difficulty.NORMAL, Difficulty.HARD, Difficulty.ONI]: + if diff not in all_scores: + all_scores[diff] = [] + all_scores[diff].append((None, None, None, None, None, None)) + else: + # Played directory - add its crowns + for diff in [Difficulty.EASY, Difficulty.NORMAL, Difficulty.HARD, Difficulty.ONI]: + if diff not in all_scores: + all_scores[diff] = [] + if diff in child_crowns: + all_scores[diff].append((None, None, None, None, None, child_crowns[diff])) + else: + # This directory doesn't have this difficulty, but it's been played + # Don't add anything - this child doesn't count for this difficulty + pass + + child_has_any_crown.append(has_crown) + + # If ANY child is completely unplayed, no crowns at all + if not all(child_has_any_crown): + self.directory_crowns[dir_key] = {} + return + + crowns = {} for diff in all_scores: - if all(score is not None and score[5] == Crown.DFC for score in all_scores[diff]): + if any(score is None or score[5] is None for score in all_scores[diff]): + continue + if all(score[5] == Crown.DFC for score in all_scores[diff]): crowns[diff] = Crown.DFC - elif all(score is not None and score[5] == Crown.FC for score in all_scores[diff]): + elif all(score[5] == Crown.FC for score in all_scores[diff]): crowns[diff] = Crown.FC - elif all(score is not None and score[5] >= Crown.CLEAR for score in all_scores[diff]): + elif all(score[5] >= Crown.CLEAR for score in all_scores[diff]): crowns[diff] = Crown.CLEAR self.directory_crowns[dir_key] = crowns diff --git a/libs/song_hash.py b/libs/song_hash.py index 1c6187c..78055cc 100644 --- a/libs/song_hash.py +++ b/libs/song_hash.py @@ -3,6 +3,7 @@ import logging import json import sqlite3 import time +import csv from pathlib import Path from libs.global_data import Crown @@ -69,10 +70,12 @@ def build_song_hashes(output_dir=Path("cache")): if output_path.exists(): with open(output_path, "r", encoding="utf-8") as f: song_hashes = json.load(f, cls=DiffHashesDecoder) + ''' for hash in song_hashes: entry = song_hashes[hash][0] for diff in entry["diff_hashes"]: db_updates.append((entry["diff_hashes"][diff], entry["title"]["en"], entry["title"].get("ja", ""), int(diff))) + ''' if index_path.exists(): with open(index_path, "r", encoding="utf-8") as f: @@ -111,7 +114,6 @@ def build_song_hashes(output_dir=Path("cache")): del song_hashes[current_hash] del path_to_hash[tja_path_str] - # Process only files that need updating song_count = 0 total_songs = len(files_to_process) if total_songs > 0: @@ -167,7 +169,7 @@ def build_song_hashes(output_dir=Path("cache")): # Prepare database updates for each difficulty en_name = tja.metadata.title.get('en', '') if isinstance(tja.metadata.title, dict) else str(tja.metadata.title) - jp_name = tja.metadata.title.get('jp', '') if isinstance(tja.metadata.title, dict) else '' + jp_name = tja.metadata.title.get('ja', '') if isinstance(tja.metadata.title, dict) else '' score_ini_path = tja_path.with_suffix('.tja.score.ini') if score_ini_path.exists(): @@ -319,7 +321,6 @@ def process_tja_file(tja_file): hash = tja.hash_note_data(all_notes) return hash -''' def get_japanese_songs_for_version(csv_file_path, version_column): # Read CSV file and filter rows where the specified version column has 'YES' version_songs = [] @@ -398,13 +399,17 @@ def get_japanese_songs_for_version(csv_file_path, version_column): if len(matches) == 1: path = matches[0][1] elif len(matches) > 1: - logger.info( + print( f"Multiple matches found for '{title.split('/')[0]} ({title.split('/')[1] if len(title.split('/')) > 1 else ''})':" ) for i, (key, path_val) in enumerate(matches, 1): - logger.info(f"{i}. {key}: {path_val}") - choice = int(input("Choose number: ")) - 1 - path = matches[choice][1] + print(f"{i}. {key}: {path_val}") + choice = input("Choose number: ") + if choice.isdigit(): + choice = int(choice) - 1 + path = matches[choice][1] + else: + path = Path(choice) else: path = Path(input(f"NOT FOUND {title}: ")) hash = process_tja_file(path) @@ -415,7 +420,7 @@ def get_japanese_songs_for_version(csv_file_path, version_column): text_files[genre].append( f"{hash}|{tja_parse.metadata.title['en'].strip()}|{tja_parse.metadata.subtitle['en'].strip()}" ) - logger.info(f"Added {title}: {path}") + print(f"Added {title}: {path}") for genre in text_files: if not Path(version_column).exists(): Path(version_column).mkdir() @@ -431,6 +436,9 @@ def get_japanese_songs_for_version(csv_file_path, version_column): return text_files -if len(sys.argv) > 1: - get_japanese_songs_for_version(sys.argv[1], sys.argv[2]) +''' +versions = ['AC6'] +for version in versions: + print(version) + get_japanese_songs_for_version('full.csv', version) ''' diff --git a/scenes/game.py b/scenes/game.py index 737235c..947e2b5 100644 --- a/scenes/game.py +++ b/scenes/game.py @@ -649,24 +649,7 @@ class Player: self.is_branch = True if self.branch_condition == 'r': end_time = self.branch_m[0].bars[0].load_ms - end_roll = -1 - - note_lists = [ - self.other_notes, - self.branch_m[0].play_notes if self.branch_m else [], - self.branch_e[0].play_notes if self.branch_e else [], - self.branch_n[0].play_notes if self.branch_n else [], - ] - - end_roll = -1 - for notes in note_lists: - for i in range(len(notes)-1, -1, -1): - if notes[i].type == NoteType.TAIL and notes[i].hit_ms <= end_time: - end_roll = notes[i].hit_ms - break - if end_roll != -1: - break - self.curr_branch_reqs = [e_req, m_req, end_roll, 1] + self.curr_branch_reqs = [e_req, m_req, end_time, 1] elif self.branch_condition == 'p': start_time = self.current_bars[0].hit_ms if self.current_bars else self.current_bars[-1].hit_ms branch_start_time = self.branch_m[0].bars[0].load_ms @@ -827,7 +810,7 @@ class Player: if drum_type != DrumType.DON: return if note.is_kusudama: - self.check_kusudama(note) + self.check_kusudama(note, current_time) return if self.balloon_anim is None: self.balloon_anim = BalloonAnimation(current_time, note.count, self.player_num, self.is_2p) @@ -843,7 +826,7 @@ class Player: self.note_correct(note, current_time) self.curr_balloon_count = 0 - def check_kusudama(self, note: Balloon): + def check_kusudama(self, note: Balloon, current_time: float): """Checks if the player has popped a kusudama""" if self.kusudama_anim is None: self.kusudama_anim = KusudamaAnimation(note.count) @@ -855,6 +838,7 @@ class Player: audio.play_sound('kusudama_pop', 'hitsound') self.is_balloon = False note.popped = True + self.kusudama_anim.update(current_time, note.popped) self.curr_balloon_count = 0 def check_note(self, ms_from_start: float, drum_type: DrumType, current_time: float, background: Optional[Background]): @@ -876,7 +860,7 @@ class Player: self.check_drumroll(drum_type, background, current_time) elif self.is_balloon: if not isinstance(curr_note, Balloon): - raise Exception("Balloon mode entered but current note is not balloon") + return self.check_balloon(drum_type, curr_note, current_time) else: self.curr_drumroll_count = 0 diff --git a/scenes/song_select.py b/scenes/song_select.py index b12c181..49d6dc4 100644 --- a/scenes/song_select.py +++ b/scenes/song_select.py @@ -686,12 +686,13 @@ class SongSelectPlayer: def draw_background_diffs(self, state: int): if (self.selected_song and state == State.SONG_SELECTED and self.selected_difficulty >= Difficulty.EASY): if self.player_num == PlayerNum.P2: - tex.draw_texture('global', 'background_diff', frame=self.selected_difficulty, fade=min(0.5, self.selected_diff_fadein.attribute), x=1025, y=-self.selected_diff_bounce.attribute, y2=self.selected_diff_bounce.attribute) + x_offset = 1025 * tex.screen_scale + tex.draw_texture('global', 'background_diff', frame=self.selected_difficulty, fade=min(0.5, self.selected_diff_fadein.attribute), x=x_offset, y=-self.selected_diff_bounce.attribute, y2=self.selected_diff_bounce.attribute) if self.selected_diff_highlight_fade.is_reversing or self.selected_diff_highlight_fade.is_finished: - tex.draw_texture('global', 'background_diff', frame=self.selected_difficulty, x=1025, y=-self.selected_diff_bounce.attribute, y2=self.selected_diff_bounce.attribute) - tex.draw_texture('global', 'background_diff_highlight', frame=min(Difficulty.ONI, self.selected_difficulty), fade=self.selected_diff_highlight_fade.attribute, x=1025) - tex.draw_texture('global', 'bg_diff_text_bg', x=1025, fade=min(0.5, self.selected_diff_text_fadein.attribute), scale=self.selected_diff_text_resize.attribute, center=True) - tex.draw_texture('global', 'bg_diff_text', frame=min(Difficulty.ONI, self.selected_difficulty), x=1025, fade=self.selected_diff_text_fadein.attribute, scale=self.selected_diff_text_resize.attribute, center=True) + tex.draw_texture('global', 'background_diff', frame=self.selected_difficulty, x=x_offset, y=-self.selected_diff_bounce.attribute, y2=self.selected_diff_bounce.attribute) + tex.draw_texture('global', 'background_diff_highlight', frame=min(Difficulty.ONI, self.selected_difficulty), fade=self.selected_diff_highlight_fade.attribute, x=x_offset) + tex.draw_texture('global', 'bg_diff_text_bg', x=x_offset, fade=min(0.5, self.selected_diff_text_fadein.attribute), scale=self.selected_diff_text_resize.attribute, center=True) + tex.draw_texture('global', 'bg_diff_text', frame=min(Difficulty.ONI, self.selected_difficulty), x=x_offset, fade=self.selected_diff_text_fadein.attribute, scale=self.selected_diff_text_resize.attribute, center=True) else: tex.draw_texture('global', 'background_diff', frame=self.selected_difficulty, fade=min(0.5, self.selected_diff_fadein.attribute), y=-self.selected_diff_bounce.attribute, y2=self.selected_diff_bounce.attribute) if self.selected_diff_highlight_fade.is_reversing or self.selected_diff_highlight_fade.is_finished: