1
0
mirror of synced 2024-11-15 01:47:34 +01:00

Fix behavior for the #LEVELHOLD command (#54)

Previously, I had translated the existing levelhold behavior in
WHMHammer's tja parsing code, assuming that it would produce the correct
behavior for fumen charts. However, that is not the case -- the behavior
is completely wrong.

So, this PR takes out all the old `flag_levelhold` behavior and instead
properly sets the `branch_info` bytes whenever #LEVELHOLD is present on
a branch.

This PR also prepares `shoto9.tja` for further testing, but I'm leaving
that for later...

Fixes #52.
This commit is contained in:
Viv 2023-07-27 15:02:19 -04:00 committed by GitHub
parent 59046c22ec
commit c0442f3721
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 45 additions and 32 deletions

View File

@ -82,8 +82,8 @@ If there is an unsupported feature that you would like support for, please make
| `#DELAY` | `✅` | `❌` | See [#27](https://github.com/Fluto/TakoTako/issues/27) |
| `#BRANCHSTART`, `#BRANCHEND` | `✅` | `✅` | |
| `#N`, `#E`, `#M` | `✅` | `✅` | |
| `#SECTION` | `⚠️` | `❌` | See [#52](https://github.com/vivaria/tja2fumen/issues/52), [#27](https://github.com/Fluto/TakoTako/issues/27) |
| `#LEVELHOLD` | `⚠️` | `❌` | See [#52](https://github.com/vivaria/tja2fumen/issues/52) |
| `#SECTION` | `⚠️` | `❌` | See [#53](https://github.com/vivaria/tja2fumen/issues/53), [#27](https://github.com/Fluto/TakoTako/issues/27) |
| `#LEVELHOLD` | `✅` | `❌` | |
| `#BMSCROLL`, `#LYRIC`,<br>`#DIRECTION`, etc. | `⚪️` | `❌` | Other simulator-specific chart commands are currently ignored. |
## Reporting bugs

View File

@ -52,6 +52,8 @@ def process_tja_commands(tja):
measure_tja_processed.branch_start = data.value
elif data.name == 'section':
measure_tja_processed.section = data.value
elif data.name == 'levelhold':
measure_tja_processed.levelhold = True
elif data.name == 'barline':
current_barline = bool(int(data.value))
measure_tja_processed.barline = current_barline
@ -181,6 +183,7 @@ def convert_tja_to_fumen(tja):
branch_points_total = 0
branch_points_measure = 0
current_drumroll = None
current_levelhold = False
branch_conditions = []
course_balloons = tja.balloon.copy()
@ -226,10 +229,14 @@ def convert_tja_to_fumen(tja):
measure_fumen.set_branch_info(
branch_condition, branch_points_total, current_branch,
first_branch_condition=(not branch_conditions),
has_section=bool(measure_tja.section)
has_section=bool(measure_tja.section),
has_levelhold=current_levelhold
)
# Reset the points to prepare for the next `#BRANCHSTART p`
branch_points_total = 0
# Reset the levelhold value (so that future branch_conditions
# work normally)
current_levelhold = False
# Keep track of the branch conditions (to later determine how
# to set the header bytes for branches)
branch_conditions.append(branch_condition)
@ -244,6 +251,12 @@ def convert_tja_to_fumen(tja):
# calculation with notes "one measure before".
branch_points_total += branch_points_measure
# LEVELHOLD essentially means "ignore the branch condition for
# the next `#BRANCHSTART` command", so we check this value after
# we've already processed the branch condition for this measure.
if measure_tja.levelhold:
current_levelhold = True
# Create notes based on TJA measure data
branch_points_measure = 0
for idx_d, data in enumerate(measure_tja.data):

View File

@ -175,7 +175,6 @@ def parse_tja_course_data(course):
has_branches = bool([d for d in course.data if d.startswith('#BRANCH')])
current_branch = 'all' if has_branches else 'normal'
branch_condition = None
flag_levelhold = False
# Process course lines
idx_m = 0
@ -210,7 +209,7 @@ def parse_tja_course_data(course):
# 2. Parse measure commands that produce an "event"
elif command in ['GOGOSTART', 'GOGOEND', 'BARLINEON', 'BARLINEOFF',
'DELAY', 'SCROLL', 'BPMCHANGE', 'MEASURE',
'SECTION', 'BRANCHSTART']:
'LEVELHOLD', 'SECTION', 'BRANCHSTART']:
# Get position of the event
for branch in (course.branches.keys() if current_branch == 'all'
else [current_branch]):
@ -233,6 +232,8 @@ def parse_tja_course_data(course):
current_event = TJAData('bpm', float(value), pos)
elif command == 'MEASURE':
current_event = TJAData('measure', value, pos)
elif command == 'LEVELHOLD':
current_event = TJAData('levelhold', None, pos)
elif command == 'SECTION':
# If #SECTION occurs before a #BRANCHSTART, then ensure that
# it's present on every branch. Otherwise, #SECTION will only
@ -247,8 +248,6 @@ def parse_tja_course_data(course):
current_event = TJAData('branch_start', branch_condition,
pos)
elif command == 'BRANCHSTART':
if flag_levelhold:
continue
# Ensure that the #BRANCHSTART command is added to all branches
current_branch = 'all'
branch_condition = value.split(',')
@ -272,9 +271,6 @@ def parse_tja_course_data(course):
else:
if command == 'START' or command == 'END':
current_branch = 'all' if has_branches else 'normal'
flag_levelhold = False
elif command == 'LEVELHOLD':
flag_levelhold = True
elif command == 'N':
current_branch = 'normal'
idx_m = idx_m_branchstart

View File

@ -70,8 +70,8 @@ class TJAMeasureProcessed(DefaultObject):
the number of `TJAMeasure` objects for a given song.))
"""
def __init__(self, bpm, scroll, gogo, barline, time_sig, subdivisions,
pos_start=0, pos_end=0, delay=0, section=None,
branch_start=None, data=None):
pos_start=0, pos_end=0, delay=0, levelhold=False,
section=None, branch_start=None, data=None):
self.bpm = bpm
self.scroll = scroll
self.gogo = gogo
@ -82,6 +82,7 @@ class TJAMeasureProcessed(DefaultObject):
self.pos_end = pos_end
self.delay = delay
self.section = section
self.levelhold = levelhold
self.branch_start = branch_start
self.data = [] if data is None else data
@ -160,14 +161,25 @@ class FumenMeasure(DefaultObject):
self.offset_end = self.offset_start + self.duration
def set_branch_info(self, branch_condition, branch_points_total,
current_branch, first_branch_condition, has_section):
current_branch, first_branch_condition,
has_section, has_levelhold):
"""Compute the values that represent branching/diverge conditions."""
# If levelhold is set, force the branch to stay the same,
# regardless of the value of the current branch condition.
if has_levelhold:
if current_branch == 'normal':
self.branch_info[0:2] = [999, 999] # Forces fail/fail
elif current_branch == 'professional':
self.branch_info[2:4] = [0, 999] # Forces pass/fail
elif current_branch == 'master':
self.branch_info[4:6] = [0, 0] # Forces pass/pass
# Handle branch conditions for percentage accuracy
# There are three cases for interpreting #BRANCHSTART p:
# 1. Percentage is between 0% and 100%
# 2. Percentage is above 100% (guaranteed level down)
# 3. Percentage is 0% (guaranteed level up)
if branch_condition[0] == 'p':
elif branch_condition[0] == 'p':
vals = []
for percent in branch_condition[1:]:
if 0 < percent <= 1:
@ -190,24 +202,14 @@ class FumenMeasure(DefaultObject):
# has a #SECTION command to reset the accuracy.
# 3. It's not the first branching condition, and it
# doesn't have a #SECTION command.
# For the first two cases, the branching conditions are the
# same no matter what branch you're currently on, so we just
# use the values as-is: [c1, c2, c1, c2, c1, c2]
# But, for the third case, since there is no #SECTION, the
# accuracy is not reset. This results in the following
# condition: [999, 999, c1, c2, c2, c2]
# - Normal can't advance to professional/master
# - Professional can stay, or advance to master.
# - Master can only stay in master.
# TODO: Determine the behavior for these 3 conditions
elif branch_condition[0] == 'r':
if first_branch_condition or has_section:
self.branch_info = branch_condition[1:] * 3
else:
self.branch_info = (
[999, 999] +
[branch_condition[1]] +
[branch_condition[2]] * 3
)
if current_branch == 'normal':
self.branch_info[0:2] = branch_condition[1:]
elif current_branch == 'professional':
self.branch_info[2:4] = branch_condition[1:]
elif current_branch == 'master':
self.branch_info[4:6] = branch_condition[1:]
class FumenBranch(DefaultObject):

View File

@ -32,6 +32,7 @@ SCOREDIFF:95
2021002020102020,
#BRANCHSTART r,5,6
#N
#LEVELHOLD
100000000100000000200000500000000008000000100200,
1000202210201120,
#E
@ -40,12 +41,13 @@ SCOREDIFF:95
#M
100000000100000000200000500000000008000000100200,
1000202210201120,
#SECTION
#BRANCHSTART r,7,8
#BRANCHEND
500000000008000000200200100000200200200200200200,
1010202210201020,
#SECTION
#BRANCHSTART r,4,5
#N
1001001070080000,
100