mirror of
https://github.com/Yonokid/PyTaiko.git
synced 2026-02-04 11:40:13 +01:00
bug fixes
This commit is contained in:
@@ -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)]
|
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 = Animation.create_texture_change(duration, textures=textures)
|
||||||
self.texture_change.start()
|
self.texture_change.start()
|
||||||
self.hori_move = Animation.create_move(60000 / self.bpm * 5, total_distance=self.tex.screen_width)
|
self.hori_move.duration = 60000 / self.bpm * 5
|
||||||
self.hori_move.start()
|
self.vert_move.duration = 60000 / self.bpm / 2
|
||||||
self.vert_move = Animation.create_move(60000 / self.bpm / 2, total_distance=50 * self.tex.screen_scale, reverse_delay=0)
|
|
||||||
self.vert_move.start()
|
|
||||||
|
|
||||||
def draw(self, tex: TextureWrapper):
|
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))
|
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))
|
||||||
|
|||||||
@@ -1157,7 +1157,6 @@ class FileNavigator:
|
|||||||
content_items.append(self.all_song_files[song_key])
|
content_items.append(self.all_song_files[song_key])
|
||||||
|
|
||||||
self.directory_contents[dir_key] = content_items
|
self.directory_contents[dir_key] = content_items
|
||||||
self.crown_cache_dirty.add(dir_key)
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# For directories without box.def, still process their children
|
# 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):
|
def _calculate_directory_crowns(self, dir_key: str, tja_files: list):
|
||||||
"""Pre-calculate crowns for a directory"""
|
"""Pre-calculate crowns for a directory"""
|
||||||
all_scores = dict()
|
all_scores = dict()
|
||||||
crowns = dict()
|
child_has_any_crown = [] # Track if each child has been played at all
|
||||||
|
|
||||||
for song_obj in tja_files:
|
for item in tja_files:
|
||||||
if not isinstance(song_obj, SongFile):
|
has_crown = False
|
||||||
continue
|
if isinstance(item, SongFile):
|
||||||
for diff in song_obj.box.scores:
|
has_crown = any((item.box.scores.get(d) or (None,)*6)[5] is not None
|
||||||
if diff not in all_scores:
|
for d in [Difficulty.EASY, Difficulty.NORMAL, Difficulty.HARD, Difficulty.ONI])
|
||||||
all_scores[diff] = []
|
for diff in item.box.scores:
|
||||||
all_scores[diff].append(song_obj.box.scores[diff])
|
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:
|
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
|
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
|
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
|
crowns[diff] = Crown.CLEAR
|
||||||
|
|
||||||
self.directory_crowns[dir_key] = crowns
|
self.directory_crowns[dir_key] = crowns
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import logging
|
|||||||
import json
|
import json
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import time
|
import time
|
||||||
|
import csv
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from libs.global_data import Crown
|
from libs.global_data import Crown
|
||||||
@@ -69,10 +70,12 @@ def build_song_hashes(output_dir=Path("cache")):
|
|||||||
if output_path.exists():
|
if output_path.exists():
|
||||||
with open(output_path, "r", encoding="utf-8") as f:
|
with open(output_path, "r", encoding="utf-8") as f:
|
||||||
song_hashes = json.load(f, cls=DiffHashesDecoder)
|
song_hashes = json.load(f, cls=DiffHashesDecoder)
|
||||||
|
'''
|
||||||
for hash in song_hashes:
|
for hash in song_hashes:
|
||||||
entry = song_hashes[hash][0]
|
entry = song_hashes[hash][0]
|
||||||
for diff in entry["diff_hashes"]:
|
for diff in entry["diff_hashes"]:
|
||||||
db_updates.append((entry["diff_hashes"][diff], entry["title"]["en"], entry["title"].get("ja", ""), int(diff)))
|
db_updates.append((entry["diff_hashes"][diff], entry["title"]["en"], entry["title"].get("ja", ""), int(diff)))
|
||||||
|
'''
|
||||||
|
|
||||||
if index_path.exists():
|
if index_path.exists():
|
||||||
with open(index_path, "r", encoding="utf-8") as f:
|
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 song_hashes[current_hash]
|
||||||
del path_to_hash[tja_path_str]
|
del path_to_hash[tja_path_str]
|
||||||
|
|
||||||
# Process only files that need updating
|
|
||||||
song_count = 0
|
song_count = 0
|
||||||
total_songs = len(files_to_process)
|
total_songs = len(files_to_process)
|
||||||
if total_songs > 0:
|
if total_songs > 0:
|
||||||
@@ -167,7 +169,7 @@ def build_song_hashes(output_dir=Path("cache")):
|
|||||||
|
|
||||||
# Prepare database updates for each difficulty
|
# Prepare database updates for each difficulty
|
||||||
en_name = tja.metadata.title.get('en', '') if isinstance(tja.metadata.title, dict) else str(tja.metadata.title)
|
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')
|
score_ini_path = tja_path.with_suffix('.tja.score.ini')
|
||||||
if score_ini_path.exists():
|
if score_ini_path.exists():
|
||||||
@@ -319,7 +321,6 @@ def process_tja_file(tja_file):
|
|||||||
hash = tja.hash_note_data(all_notes)
|
hash = tja.hash_note_data(all_notes)
|
||||||
return hash
|
return hash
|
||||||
|
|
||||||
'''
|
|
||||||
def get_japanese_songs_for_version(csv_file_path, version_column):
|
def get_japanese_songs_for_version(csv_file_path, version_column):
|
||||||
# Read CSV file and filter rows where the specified version column has 'YES'
|
# Read CSV file and filter rows where the specified version column has 'YES'
|
||||||
version_songs = []
|
version_songs = []
|
||||||
@@ -398,13 +399,17 @@ def get_japanese_songs_for_version(csv_file_path, version_column):
|
|||||||
if len(matches) == 1:
|
if len(matches) == 1:
|
||||||
path = matches[0][1]
|
path = matches[0][1]
|
||||||
elif len(matches) > 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 ''})':"
|
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):
|
for i, (key, path_val) in enumerate(matches, 1):
|
||||||
logger.info(f"{i}. {key}: {path_val}")
|
print(f"{i}. {key}: {path_val}")
|
||||||
choice = int(input("Choose number: ")) - 1
|
choice = input("Choose number: ")
|
||||||
path = matches[choice][1]
|
if choice.isdigit():
|
||||||
|
choice = int(choice) - 1
|
||||||
|
path = matches[choice][1]
|
||||||
|
else:
|
||||||
|
path = Path(choice)
|
||||||
else:
|
else:
|
||||||
path = Path(input(f"NOT FOUND {title}: "))
|
path = Path(input(f"NOT FOUND {title}: "))
|
||||||
hash = process_tja_file(path)
|
hash = process_tja_file(path)
|
||||||
@@ -415,7 +420,7 @@ def get_japanese_songs_for_version(csv_file_path, version_column):
|
|||||||
text_files[genre].append(
|
text_files[genre].append(
|
||||||
f"{hash}|{tja_parse.metadata.title['en'].strip()}|{tja_parse.metadata.subtitle['en'].strip()}"
|
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:
|
for genre in text_files:
|
||||||
if not Path(version_column).exists():
|
if not Path(version_column).exists():
|
||||||
Path(version_column).mkdir()
|
Path(version_column).mkdir()
|
||||||
@@ -431,6 +436,9 @@ def get_japanese_songs_for_version(csv_file_path, version_column):
|
|||||||
return text_files
|
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)
|
||||||
'''
|
'''
|
||||||
|
|||||||
@@ -649,24 +649,7 @@ class Player:
|
|||||||
self.is_branch = True
|
self.is_branch = True
|
||||||
if self.branch_condition == 'r':
|
if self.branch_condition == 'r':
|
||||||
end_time = self.branch_m[0].bars[0].load_ms
|
end_time = self.branch_m[0].bars[0].load_ms
|
||||||
end_roll = -1
|
self.curr_branch_reqs = [e_req, m_req, end_time, 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]
|
|
||||||
elif self.branch_condition == 'p':
|
elif self.branch_condition == 'p':
|
||||||
start_time = self.current_bars[0].hit_ms if self.current_bars else self.current_bars[-1].hit_ms
|
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
|
branch_start_time = self.branch_m[0].bars[0].load_ms
|
||||||
@@ -827,7 +810,7 @@ class Player:
|
|||||||
if drum_type != DrumType.DON:
|
if drum_type != DrumType.DON:
|
||||||
return
|
return
|
||||||
if note.is_kusudama:
|
if note.is_kusudama:
|
||||||
self.check_kusudama(note)
|
self.check_kusudama(note, current_time)
|
||||||
return
|
return
|
||||||
if self.balloon_anim is None:
|
if self.balloon_anim is None:
|
||||||
self.balloon_anim = BalloonAnimation(current_time, note.count, self.player_num, self.is_2p)
|
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.note_correct(note, current_time)
|
||||||
self.curr_balloon_count = 0
|
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"""
|
"""Checks if the player has popped a kusudama"""
|
||||||
if self.kusudama_anim is None:
|
if self.kusudama_anim is None:
|
||||||
self.kusudama_anim = KusudamaAnimation(note.count)
|
self.kusudama_anim = KusudamaAnimation(note.count)
|
||||||
@@ -855,6 +838,7 @@ class Player:
|
|||||||
audio.play_sound('kusudama_pop', 'hitsound')
|
audio.play_sound('kusudama_pop', 'hitsound')
|
||||||
self.is_balloon = False
|
self.is_balloon = False
|
||||||
note.popped = True
|
note.popped = True
|
||||||
|
self.kusudama_anim.update(current_time, note.popped)
|
||||||
self.curr_balloon_count = 0
|
self.curr_balloon_count = 0
|
||||||
|
|
||||||
def check_note(self, ms_from_start: float, drum_type: DrumType, current_time: float, background: Optional[Background]):
|
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)
|
self.check_drumroll(drum_type, background, current_time)
|
||||||
elif self.is_balloon:
|
elif self.is_balloon:
|
||||||
if not isinstance(curr_note, 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)
|
self.check_balloon(drum_type, curr_note, current_time)
|
||||||
else:
|
else:
|
||||||
self.curr_drumroll_count = 0
|
self.curr_drumroll_count = 0
|
||||||
|
|||||||
@@ -686,12 +686,13 @@ class SongSelectPlayer:
|
|||||||
def draw_background_diffs(self, state: int):
|
def draw_background_diffs(self, state: int):
|
||||||
if (self.selected_song and state == State.SONG_SELECTED and self.selected_difficulty >= Difficulty.EASY):
|
if (self.selected_song and state == State.SONG_SELECTED and self.selected_difficulty >= Difficulty.EASY):
|
||||||
if self.player_num == PlayerNum.P2:
|
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:
|
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', 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=1025)
|
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=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_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=1025, fade=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:
|
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)
|
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:
|
if self.selected_diff_highlight_fade.is_reversing or self.selected_diff_highlight_fade.is_finished:
|
||||||
|
|||||||
Reference in New Issue
Block a user