@Override public boolean update( boolean overlap, int delta, int mouseX, int mouseY, boolean keyPressed, int trackPosition) { int repeatCount = hitObject.getRepeatCount(); int[] hitResultOffset = game.getHitResultOffsets(); boolean isAutoMod = GameMod.AUTO.isActive(); if (!sliderClickedInitial) { int time = hitObject.getTime(); // start circle time passed if (trackPosition > time + hitResultOffset[GameData.HIT_50]) { sliderClickedInitial = true; if (isAutoMod) { // "auto" mod: catch any missed notes due to lag ticksHit++; data.sliderTickResult(time, GameData.HIT_SLIDER30, x, y, hitObject, currentRepeats); } else data.sliderTickResult(time, GameData.HIT_MISS, x, y, hitObject, currentRepeats); } // "auto" mod: send a perfect hit result else if (isAutoMod) { if (Math.abs(trackPosition - time) < hitResultOffset[GameData.HIT_300]) { ticksHit++; sliderClickedInitial = true; data.sliderTickResult(time, GameData.HIT_SLIDER30, x, y, hitObject, currentRepeats); } } // "relax" mod: click automatically else if (GameMod.RELAX.isActive() && trackPosition >= time) mousePressed(mouseX, mouseY, trackPosition); } // end of slider if (trackPosition > hitObject.getTime() + sliderTimeTotal) { tickIntervals++; // check if cursor pressed and within end circle if (keyPressed || GameMod.RELAX.isActive()) { float[] c = curve.pointAt(getT(trackPosition, false)); double distance = Math.hypot(c[0] - mouseX, c[1] - mouseY); if (distance < followRadius) sliderHeldToEnd = true; } // final circle hit if (sliderHeldToEnd) ticksHit++; // "auto" mod: always send a perfect hit result if (isAutoMod) ticksHit = tickIntervals; // calculate and send slider result hitResult(); return true; } // repeats boolean isNewRepeat = false; if (repeatCount - 1 > currentRepeats) { float t = getT(trackPosition, true); if (Math.floor(t) > currentRepeats) { currentRepeats++; tickIntervals++; isNewRepeat = true; } } // ticks boolean isNewTick = false; if (ticksT != null && tickIntervals < (ticksT.length * (currentRepeats + 1)) + repeatCount && tickIntervals < (ticksT.length * repeatCount) + repeatCount) { float t = getT(trackPosition, true); if (t - Math.floor(t) >= ticksT[tickIndex]) { tickIntervals++; tickIndex = (tickIndex + 1) % ticksT.length; isNewTick = true; } } // holding slider... float[] c = curve.pointAt(getT(trackPosition, false)); double distance = Math.hypot(c[0] - mouseX, c[1] - mouseY); if (((keyPressed || GameMod.RELAX.isActive()) && distance < followRadius) || isAutoMod) { // mouse pressed and within follow circle followCircleActive = true; data.changeHealth(delta * GameData.HP_DRAIN_MULTIPLIER); // held during new repeat if (isNewRepeat) { ticksHit++; if (currentRepeats % 2 > 0) { // last circle int lastIndex = hitObject.getSliderX().length; data.sliderTickResult( trackPosition, GameData.HIT_SLIDER30, curve.getX(lastIndex), curve.getY(lastIndex), hitObject, currentRepeats); } else // first circle data.sliderTickResult( trackPosition, GameData.HIT_SLIDER30, c[0], c[1], hitObject, currentRepeats); } // held during new tick if (isNewTick) { ticksHit++; data.sliderTickResult( trackPosition, GameData.HIT_SLIDER10, c[0], c[1], hitObject, currentRepeats); } // held near end of slider if (!sliderHeldToEnd && trackPosition > hitObject.getTime() + sliderTimeTotal - hitResultOffset[GameData.HIT_300]) sliderHeldToEnd = true; } else { followCircleActive = false; if (isNewRepeat) data.sliderTickResult(trackPosition, GameData.HIT_MISS, 0, 0, hitObject, currentRepeats); if (isNewTick) data.sliderTickResult(trackPosition, GameData.HIT_MISS, 0, 0, hitObject, currentRepeats); } return false; }