Implemented "relax" mod.

Also added a few checks for related "autopilot" mod (probably incomplete).

Fixed the wrong default background being shown in the ranking screen.

Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
This commit is contained in:
Jeffrey Han 2015-03-06 00:25:48 -05:00
parent b80764f3eb
commit 0a1b10fbdb
7 changed files with 75 additions and 53 deletions

View File

@ -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
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();
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,11 +548,11 @@ public class GameData {
getScoreSymbolImage('.').getWidth() +
getScoreSymbolImage('%').getWidth()
) * 0.60f - circleDiameter);
if (!relaxAutoPilot) {
g.setAntiAlias(true);
g.setLineWidth(2f);
g.setColor(Color.white);
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,
@ -562,6 +565,7 @@ public class GameData {
-90 + (int) (360f * trackPosition / firstObjectTime), -90
);
}
}
// mod icons
if ((firstObject && trackPosition < firstObjectTime) || GameMod.AUTO.isActive()) {
@ -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()));
}

View File

@ -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 (active && b) {
SUDDEN_DEATH.active = false;
NO_FAIL.active = false;
RELAX.active = false;
AUTOPILOT.active = false;
active = true;
}
if (SUDDEN_DEATH.isActive() && NO_FAIL.isActive()) {
if (this == SUDDEN_DEATH)
NO_FAIL.toggle(false);
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;
}
}
}

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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);