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:
parent
b80764f3eb
commit
0a1b10fbdb
|
@ -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()));
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue
Block a user