Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed stack leniency calculations #406

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 59 additions & 36 deletions src/itdelatrisu/opsu/states/Game.java
Original file line number Diff line number Diff line change
Expand Up @@ -2329,57 +2329,80 @@ else if (endTime - trackPosition < approachTime)
private void calculateStacks() {
// reverse pass for stack calculation
for (int i = gameObjects.length - 1; i > 0; i--) {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed.

HitObject hitObjectI = beatmap.objects[i];

// already calculated
if (hitObjectI.getStack() != 0 || hitObjectI.isSpinner())
continue;

// search for hit objects in stack
for (int n = i - 1; n >= 0; n--) {
HitObject hitObjectN = beatmap.objects[n];
if (hitObjectN.isSpinner())
continue;
if (hitObjectI.isCircle()) {
for (int n = i - 1; n >= 0; n--) {
HitObject hitObjectN = beatmap.objects[n];
if (hitObjectN.isSpinner())
continue;

// check if in range stack calculation
float timeI = hitObjectI.getTime() - (approachTime * beatmap.stackLeniency);
float timeN = hitObjectN.isSlider() ? gameObjects[n].getEndTime() : hitObjectN.getTime();
if (timeI > timeN)
break;
// check if in range stack calculation
float timeI = hitObjectI.getTime() - (approachTime * beatmap.stackLeniency);
float timeN = hitObjectN.isSlider() ? gameObjects[n].getEndTime() : hitObjectN.getTime();
if (timeI > timeN)
break;

// possible special case: if slider end in the stack,
// all next hit objects in stack move right down
if (hitObjectN.isSlider()) {
Vec2f p1 = gameObjects[i].getPointAt(hitObjectI.getTime());
Vec2f p2 = gameObjects[n].getPointAt(gameObjects[n].getEndTime());
float distance = Utils.distance(p1.x, p1.y, p2.x, p2.y);
// possible special case: if slider end in the stack,
// all next hit objects in stack move right down
if (hitObjectN.isSlider()) {
Vec2f p1 = gameObjects[i].getPointAt(hitObjectI.getTime());
Vec2f p2 = gameObjects[n].getPointAt(gameObjects[n].getEndTime());
float distance = Utils.distance(p1.x, p1.y, p2.x, p2.y);

// check if hit object part of this stack
if (distance < STACK_LENIENCE * HitObject.getXMultiplier()) {
int offset = hitObjectI.getStack() - hitObjectN.getStack() + 1;
for (int j = n + 1; j <= i; j++) {
HitObject hitObjectJ = beatmap.objects[j];
p1 = gameObjects[j].getPointAt(hitObjectJ.getTime());
distance = Utils.distance(p1.x, p1.y, p2.x, p2.y);

// hit object below slider end
if (distance < STACK_LENIENCE * HitObject.getXMultiplier())
hitObjectJ.setStack(hitObjectJ.getStack() - offset);
}
break; // slider end always start of the stack: reset calculation
}
}

// check if hit object part of this stack
float distance = Utils.distance(
hitObjectI.getX(), hitObjectI.getY(),
hitObjectN.getX(), hitObjectN.getY()
);
if (distance < STACK_LENIENCE * HitObject.getXMultiplier()) {
int offset = hitObjectI.getStack() - hitObjectN.getStack() + 1;
for (int j = n + 1; j <= i; j++) {
HitObject hitObjectJ = beatmap.objects[j];
p1 = gameObjects[j].getPointAt(hitObjectJ.getTime());
distance = Utils.distance(p1.x, p1.y, p2.x, p2.y);

// hit object below slider end
if (distance < STACK_LENIENCE * HitObject.getXMultiplier())
hitObjectJ.setStack(hitObjectJ.getStack() - offset);
}
break; // slider end always start of the stack: reset calculation
hitObjectN.setStack(hitObjectI.getStack() + 1);
hitObjectI = hitObjectN;
}
}
} else if (hitObjectI.isSlider()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we care about the case where the hit object is not a circle or slider (e.g. when it's a spinner)? If so, should we be doing anything with it in an else clause?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, we don't care about them.

for (int n = i - 1; n >= 0; n--) {
HitObject hitObjectN = beatmap.objects[n];
if (hitObjectN.isSpinner())
continue;

// check if in range stack calculation
float timeI = hitObjectI.getTime() - (approachTime * beatmap.stackLeniency);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Parentheses around approachTime * beatmap.stackLeniency can be removed as * has precedence over -.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was basing on the code that was before that had parenthesis

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, then I would have kept it the way you had it, but it seems I didn't reply soon enough. Oh well, it's done now, so let's see if @itdelatrisu cares much about it.

float timeN = hitObjectN.getTime();
if (timeI > timeN)
break;

// not a special case: stack moves up left
float distance = Utils.distance(
hitObjectI.getX(), hitObjectI.getY(),
hitObjectN.getX(), hitObjectN.getY()
);
if (distance < STACK_LENIENCE) {
hitObjectN.setStack(hitObjectI.getStack() + 1);
hitObjectI = hitObjectN;
float distance = Utils.distance(
hitObjectI.getX(), hitObjectI.getY(),
hitObjectN.getX(), hitObjectN.getY()
);
if (distance < STACK_LENIENCE * HitObject.getXMultiplier()) {
hitObjectN.setStack(hitObjectI.getStack() + 1);
hitObjectI = hitObjectN;
}
}
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed.

}

// update hit object positions
Expand Down