diff --git a/src/itdelatrisu/opsu/GameData.java b/src/itdelatrisu/opsu/GameData.java index 5bfb4796..a0a16908 100644 --- a/src/itdelatrisu/opsu/GameData.java +++ b/src/itdelatrisu/opsu/GameData.java @@ -522,22 +522,25 @@ public class GameData { */ @SuppressWarnings("deprecation") public void drawGameElements(Graphics g, boolean breakPeriod, boolean firstObject) { + boolean relaxAutoPilot = (GameMod.RELAX.isActive() || GameMod.AUTOPILOT.isActive()); int margin = (int) (width * 0.008f); // score - drawFixedSizeSymbolString((scoreDisplay < 100000000) ? String.format("%08d", scoreDisplay) : Long.toString(scoreDisplay), - width - margin, 0, 1.0f, getScoreSymbolImage('0').getWidth() - 2, true); + if (!relaxAutoPilot) + drawFixedSizeSymbolString((scoreDisplay < 100000000) ? String.format("%08d", scoreDisplay) : Long.toString(scoreDisplay), + width - margin, 0, 1.0f, getScoreSymbolImage('0').getWidth() - 2, true); // score percentage int symbolHeight = getScoreSymbolImage('0').getHeight(); - drawSymbolString( - String.format((scorePercentDisplay < 10f) ? "0%.2f%%" : "%.2f%%", scorePercentDisplay), - width - margin, symbolHeight, 0.60f, 1f, true); + if (!relaxAutoPilot) + drawSymbolString( + String.format((scorePercentDisplay < 10f) ? "0%.2f%%" : "%.2f%%", scorePercentDisplay), + width - margin, symbolHeight, 0.60f, 1f, true); // map progress circle - g.setAntiAlias(true); - g.setLineWidth(2f); - g.setColor(Color.white); + OsuFile osu = MusicController.getOsuFile(); + int firstObjectTime = osu.objects[0].getTime(); + int trackPosition = MusicController.getPosition(); float circleDiameter = symbolHeight * 0.60f; int circleX = (int) (width - margin - ( // max width: "100.00%" getScoreSymbolImage('1').getWidth() + @@ -545,22 +548,23 @@ public class GameData { getScoreSymbolImage('.').getWidth() + getScoreSymbolImage('%').getWidth() ) * 0.60f - circleDiameter); - g.drawOval(circleX, symbolHeight, circleDiameter, circleDiameter); - - OsuFile osu = MusicController.getOsuFile(); - int firstObjectTime = osu.objects[0].getTime(); - int trackPosition = MusicController.getPosition(); - if (trackPosition > firstObjectTime) { - // map progress (white) - g.fillArc(circleX, symbolHeight, circleDiameter, circleDiameter, - -90, -90 + (int) (360f * (trackPosition - firstObjectTime) / (osu.endTime - firstObjectTime)) - ); - } else { - // lead-in time (yellow) - g.setColor(Utils.COLOR_YELLOW_ALPHA); - g.fillArc(circleX, symbolHeight, circleDiameter, circleDiameter, - -90 + (int) (360f * trackPosition / firstObjectTime), -90 - ); + if (!relaxAutoPilot) { + g.setAntiAlias(true); + g.setLineWidth(2f); + g.setColor(Color.white); + g.drawOval(circleX, symbolHeight, circleDiameter, circleDiameter); + if (trackPosition > firstObjectTime) { + // map progress (white) + g.fillArc(circleX, symbolHeight, circleDiameter, circleDiameter, + -90, -90 + (int) (360f * (trackPosition - firstObjectTime) / (osu.endTime - firstObjectTime)) + ); + } else { + // lead-in time (yellow) + g.setColor(Utils.COLOR_YELLOW_ALPHA); + g.fillArc(circleX, symbolHeight, circleDiameter, circleDiameter, + -90 + (int) (360f * trackPosition / firstObjectTime), -90 + ); + } } // mod icons @@ -624,7 +628,7 @@ public class GameData { } } - if (!breakPeriod) { + if (!breakPeriod && !relaxAutoPilot) { // scorebar float healthRatio = healthDisplay / 100f; if (firstObject) { // gradually move ki before map begins @@ -671,7 +675,7 @@ public class GameData { drawSymbolString(comboString, margin, height - margin - (symbolHeight * comboPopBack), comboPopBack, 0.5f, false); drawSymbolString(comboString, margin, height - margin - (symbolHeight * comboPopFront), comboPopFront, 1f, false); } - } else { + } else if (!relaxAutoPilot) { // grade Grade grade = getGrade(); if (grade != Grade.NULL) { @@ -860,7 +864,8 @@ public class GameData { * If "No Fail" or "Auto" mods are active, this will always return true. */ public boolean isAlive() { - return (health > 0f || GameMod.NO_FAIL.isActive() || GameMod.AUTO.isActive()); + return (health > 0f || GameMod.NO_FAIL.isActive() || GameMod.AUTO.isActive() || + GameMod.RELAX.isActive() || GameMod.AUTOPILOT.isActive()); } /** @@ -1043,7 +1048,7 @@ public class GameData { * Resets the combo streak to zero. */ private void resetComboStreak() { - if (combo >= 20) + if (combo >= 20 && !(GameMod.RELAX.isActive() || GameMod.AUTOPILOT.isActive())) SoundController.playSound(SoundEffect.COMBOBREAK); combo = 0; if (GameMod.SUDDEN_DEATH.isActive()) @@ -1173,6 +1178,8 @@ public class GameData { if (perfectHit && !Options.isPerfectHitBurstEnabled()) ; // hide perfect hit results + else if (result == HIT_MISS && (GameMod.RELAX.isActive() || GameMod.AUTOPILOT.isActive())) + ; // "relax" and "autopilot" mods: hide misses else hitResultList.add(new OsuHitObjectResult(time, result, x, y, color, hitObject.isSpinner())); } diff --git a/src/itdelatrisu/opsu/GameMod.java b/src/itdelatrisu/opsu/GameMod.java index 6320e857..da5633f4 100644 --- a/src/itdelatrisu/opsu/GameMod.java +++ b/src/itdelatrisu/opsu/GameMod.java @@ -49,7 +49,7 @@ public enum GameMod { "Play with no approach circles and fading notes for a slight score advantage."), FLASHLIGHT (Category.HARD, 4, GameImage.MOD_FLASHLIGHT, "FL", 1024, Input.KEY_G, 1.12f, false, "Restricted view area."), - RELAX (Category.SPECIAL, 0, GameImage.MOD_RELAX, "RL", 128, Input.KEY_Z, 0f, false, + RELAX (Category.SPECIAL, 0, GameImage.MOD_RELAX, "RL", 128, Input.KEY_Z, 0f, "You don't need to click.\nGive your clicking/tapping finger a break from the heat of things.\n**UNRANKED**"), AUTOPILOT (Category.SPECIAL, 1, GameImage.MOD_AUTOPILOT, "AP", 8192, Input.KEY_X, 0f, false, "Automatic cursor movement - just follow the rhythm.\n**UNRANKED**"), @@ -303,28 +303,34 @@ public enum GameMod { scoreMultiplier = -1f; if (checkInverse) { + boolean b = (this == SUDDEN_DEATH || this == NO_FAIL || this == RELAX || this == AUTOPILOT); if (AUTO.isActive()) { if (this == AUTO) { - if (SPUN_OUT.isActive()) - SPUN_OUT.toggle(false); - if (SUDDEN_DEATH.isActive()) - SUDDEN_DEATH.toggle(false); - } else if (this == SPUN_OUT || this == SUDDEN_DEATH) { - if (active) - toggle(false); - } + SPUN_OUT.active = false; + SUDDEN_DEATH.active = false; + RELAX.active = false; + AUTOPILOT.active = false; + } else if (b) + this.active = false; } - if (SUDDEN_DEATH.isActive() && NO_FAIL.isActive()) { - if (this == SUDDEN_DEATH) - NO_FAIL.toggle(false); + if (active && b) { + SUDDEN_DEATH.active = false; + NO_FAIL.active = false; + RELAX.active = false; + AUTOPILOT.active = false; + active = true; + } + if (AUTOPILOT.isActive() && SPUN_OUT.isActive()) { + if (this == AUTOPILOT) + SPUN_OUT.active = false; else - SUDDEN_DEATH.toggle(false); + AUTOPILOT.active = false; } if (EASY.isActive() && HARD_ROCK.isActive()) { if (this == EASY) - HARD_ROCK.toggle(false); + HARD_ROCK.active = false; else - EASY.toggle(false); + EASY.active = false; } } } diff --git a/src/itdelatrisu/opsu/objects/Circle.java b/src/itdelatrisu/opsu/objects/Circle.java index fb8533a4..6bb4da9e 100644 --- a/src/itdelatrisu/opsu/objects/Circle.java +++ b/src/itdelatrisu/opsu/objects/Circle.java @@ -175,6 +175,10 @@ public class Circle implements HitObject { } } + // "relax" mod: click automatically + else if (GameMod.RELAX.isActive() && trackPosition >= time) + return mousePressed(mouseX, mouseY); + return false; } } \ No newline at end of file diff --git a/src/itdelatrisu/opsu/objects/Slider.java b/src/itdelatrisu/opsu/objects/Slider.java index c80d6862..1cbcb6b3 100644 --- a/src/itdelatrisu/opsu/objects/Slider.java +++ b/src/itdelatrisu/opsu/objects/Slider.java @@ -344,6 +344,10 @@ public class Slider implements HitObject { hitObject.getX(), hitObject.getY(), hitObject, currentRepeats); } } + + // "relax" mod: click automatically + else if (GameMod.RELAX.isActive() && trackPosition >= time) + mousePressed(mouseX, mouseY); } // end of slider @@ -351,7 +355,7 @@ public class Slider implements HitObject { tickIntervals++; // check if cursor pressed and within end circle - if (Utils.isGameKeyPressed()) { + if (Utils.isGameKeyPressed() || GameMod.RELAX.isActive()) { float[] c = curve.pointAt(getT(trackPosition, false)); double distance = Math.hypot(c[0] - mouseX, c[1] - mouseY); int followCircleRadius = GameImage.SLIDER_FOLLOWCIRCLE.getImage().getWidth() / 2; @@ -400,7 +404,7 @@ public class Slider implements HitObject { float[] c = curve.pointAt(getT(trackPosition, false)); double distance = Math.hypot(c[0] - mouseX, c[1] - mouseY); int followCircleRadius = GameImage.SLIDER_FOLLOWCIRCLE.getImage().getWidth() / 2; - if ((Utils.isGameKeyPressed() && distance < followCircleRadius) || isAutoMod) { + if (((Utils.isGameKeyPressed() || GameMod.RELAX.isActive()) && distance < followCircleRadius) || isAutoMod) { // mouse pressed and within follow circle followCircleActive = true; data.changeHealth(delta * GameData.HP_DRAIN_MULTIPLIER); diff --git a/src/itdelatrisu/opsu/objects/Spinner.java b/src/itdelatrisu/opsu/objects/Spinner.java index 2c8b384c..0c8fbab6 100644 --- a/src/itdelatrisu/opsu/objects/Spinner.java +++ b/src/itdelatrisu/opsu/objects/Spinner.java @@ -195,13 +195,13 @@ public class Spinner implements HitObject { } // game button is released - if (isSpinning && !Utils.isGameKeyPressed()) + if (isSpinning && !(Utils.isGameKeyPressed() || GameMod.RELAX.isActive())) isSpinning = false; float angle = (float) Math.atan2(mouseY - (height / 2), mouseX - (width / 2)); // set initial angle to current mouse position to skip first click - if (!isSpinning && Utils.isGameKeyPressed()) { + if (!isSpinning && (Utils.isGameKeyPressed() || GameMod.RELAX.isActive())) { lastAngle = angle; isSpinning = true; return false; diff --git a/src/itdelatrisu/opsu/states/Game.java b/src/itdelatrisu/opsu/states/Game.java index d926d094..4ae66795 100644 --- a/src/itdelatrisu/opsu/states/Game.java +++ b/src/itdelatrisu/opsu/states/Game.java @@ -384,8 +384,9 @@ public class Game extends BasicGameState { // returning from pause screen: must click previous mouse position if (pauseTime > -1) { - // paused during lead-in or break: continue immediately - if (pausedMouseX < 0 && pausedMouseY < 0) { + // paused during lead-in or break, or "relax" or "autopilot": continue immediately + if ((pausedMouseX < 0 && pausedMouseY < 0) || + (GameMod.RELAX.isActive() || GameMod.AUTOPILOT.isActive())) { pauseTime = -1; if (!isLeadIn()) MusicController.resume(); @@ -429,7 +430,7 @@ public class Game extends BasicGameState { else { // go to ranking screen ((GameRanking) game.getState(Opsu.STATE_GAMERANKING)).setGameData(data); ScoreData score = data.getScoreData(osu); - if (!GameMod.AUTO.isActive()) + if (!GameMod.AUTO.isActive() && !GameMod.RELAX.isActive() && !GameMod.AUTOPILOT.isActive()) ScoreDB.addScore(score); game.enterState(Opsu.STATE_GAMERANKING, new FadeOutTransition(Color.black), new FadeInTransition(Color.black)); } @@ -685,8 +686,8 @@ public class Game extends BasicGameState { return; // successfully skipped } - // "auto" mod: ignore user actions - if (GameMod.AUTO.isActive()) + // "auto" and "relax" mods: ignore user actions + if (GameMod.AUTO.isActive() || GameMod.RELAX.isActive()) return; // circles diff --git a/src/itdelatrisu/opsu/states/GameRanking.java b/src/itdelatrisu/opsu/states/GameRanking.java index 5a62ebbb..e8fe500a 100644 --- a/src/itdelatrisu/opsu/states/GameRanking.java +++ b/src/itdelatrisu/opsu/states/GameRanking.java @@ -102,7 +102,7 @@ public class GameRanking extends BasicGameState { // background if (!osu.drawBG(width, height, 0.7f, true)) - GameImage.MENU_BG.getImage().draw(0,0); + GameImage.PLAYFIELD.getImage().draw(0,0); // ranking screen elements data.drawRankingElements(g, osu);