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