Added options for global fixed difficulty settings (CS, HP, AR, OD).
- Added a new tab in Game Options screen containing the values. Other changes: - Corrected "Hard Rock" difficulty modifiers. Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
This commit is contained in:
parent
06f8dae037
commit
83f13a8879
|
@ -810,18 +810,31 @@ public class Game extends BasicGameState {
|
||||||
*/
|
*/
|
||||||
private void setMapModifiers() {
|
private void setMapModifiers() {
|
||||||
try {
|
try {
|
||||||
// map-based properties, so re-initialize each game
|
// map-based properties, re-initialized each game
|
||||||
float circleSize = osu.circleSize;
|
float circleSize = osu.circleSize;
|
||||||
float approachRate = osu.approachRate;
|
float approachRate = osu.approachRate;
|
||||||
float overallDifficulty = osu.overallDifficulty;
|
float overallDifficulty = osu.overallDifficulty;
|
||||||
float HPDrainRate = osu.HPDrainRate;
|
float HPDrainRate = osu.HPDrainRate;
|
||||||
if (Options.isModActive(Options.MOD_HARD_ROCK)) { // hard rock modifiers
|
|
||||||
circleSize = Math.max(circleSize - 1, 0);
|
// fixed difficulty overrides
|
||||||
approachRate = Math.min(approachRate + 3, 10);
|
if (Options.getFixedCS() > 0f)
|
||||||
overallDifficulty = Math.min(overallDifficulty + 3, 10);
|
circleSize = Options.getFixedCS();
|
||||||
HPDrainRate = Math.min(HPDrainRate + 3, 10);
|
if (Options.getFixedAR() > 0f)
|
||||||
|
approachRate = Options.getFixedAR();
|
||||||
|
if (Options.getFixedOD() > 0f)
|
||||||
|
overallDifficulty = Options.getFixedOD();
|
||||||
|
if (Options.getFixedHP() > 0f)
|
||||||
|
HPDrainRate = Options.getFixedHP();
|
||||||
|
|
||||||
|
// hard rock modifiers
|
||||||
|
if (Options.isModActive(Options.MOD_HARD_ROCK)) {
|
||||||
|
circleSize = Math.min(circleSize * 1.4f, 10);
|
||||||
|
approachRate = Math.min(approachRate * 1.4f, 10);
|
||||||
|
overallDifficulty = Math.min(overallDifficulty * 1.4f, 10);
|
||||||
|
HPDrainRate = Math.min(HPDrainRate * 1.4f, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// initialize objects
|
||||||
Circle.init(container, circleSize);
|
Circle.init(container, circleSize);
|
||||||
Slider.init(container, circleSize, osu);
|
Slider.init(container, circleSize, osu);
|
||||||
Spinner.init(container);
|
Spinner.init(container);
|
||||||
|
|
|
@ -130,7 +130,11 @@ public class Options extends BasicGameState {
|
||||||
SHOW_PERFECT_HIT,
|
SHOW_PERFECT_HIT,
|
||||||
BACKGROUND_DIM,
|
BACKGROUND_DIM,
|
||||||
FORCE_DEFAULT_PLAYFIELD,
|
FORCE_DEFAULT_PLAYFIELD,
|
||||||
IGNORE_BEATMAP_SKINS;
|
IGNORE_BEATMAP_SKINS,
|
||||||
|
FIXED_CS,
|
||||||
|
FIXED_HP,
|
||||||
|
FIXED_AR,
|
||||||
|
FIXED_OD;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -140,7 +144,8 @@ public class Options extends BasicGameState {
|
||||||
TAB_DISPLAY = 0,
|
TAB_DISPLAY = 0,
|
||||||
TAB_MUSIC = 1,
|
TAB_MUSIC = 1,
|
||||||
TAB_GAMEPLAY = 2,
|
TAB_GAMEPLAY = 2,
|
||||||
TAB_MAX = 3; // not a tab
|
TAB_CUSTOM = 3,
|
||||||
|
TAB_MAX = 4; // not a tab
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Option tab names.
|
* Option tab names.
|
||||||
|
@ -148,7 +153,8 @@ public class Options extends BasicGameState {
|
||||||
private static final String[] TAB_NAMES = {
|
private static final String[] TAB_NAMES = {
|
||||||
"Display",
|
"Display",
|
||||||
"Music",
|
"Music",
|
||||||
"Gameplay"
|
"Gameplay",
|
||||||
|
"Custom"
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -196,12 +202,22 @@ public class Options extends BasicGameState {
|
||||||
GameOption.SHOW_PERFECT_HIT
|
GameOption.SHOW_PERFECT_HIT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Custom options.
|
||||||
|
*/
|
||||||
|
private static final GameOption[] customOptions = {
|
||||||
|
GameOption.FIXED_CS,
|
||||||
|
GameOption.FIXED_HP,
|
||||||
|
GameOption.FIXED_AR,
|
||||||
|
GameOption.FIXED_OD
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Max number of options displayed on one screen.
|
* Max number of options displayed on one screen.
|
||||||
*/
|
*/
|
||||||
private static int maxOptionsScreen = Math.max(
|
private static int maxOptionsScreen = Math.max(
|
||||||
Math.max(displayOptions.length, musicOptions.length),
|
Math.max(displayOptions.length, musicOptions.length),
|
||||||
gameplayOptions.length);
|
Math.max(gameplayOptions.length, customOptions.length));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Screen resolutions.
|
* Screen resolutions.
|
||||||
|
@ -318,6 +334,13 @@ public class Options extends BasicGameState {
|
||||||
*/
|
*/
|
||||||
private static boolean ignoreBeatmapSkins = false;
|
private static boolean ignoreBeatmapSkins = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fixed difficulty overrides.
|
||||||
|
*/
|
||||||
|
private static float
|
||||||
|
fixedCS = 0f, fixedHP = 0f,
|
||||||
|
fixedAR = 0f, fixedOD = 0f;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Game option coordinate modifiers (for drawing).
|
* Game option coordinate modifiers (for drawing).
|
||||||
*/
|
*/
|
||||||
|
@ -351,9 +374,11 @@ public class Options extends BasicGameState {
|
||||||
|
|
||||||
// option tabs
|
// option tabs
|
||||||
Image tab = Utils.getTabImage();
|
Image tab = Utils.getTabImage();
|
||||||
|
int subtextWidth = Utils.FONT_DEFAULT.getWidth("Click or drag an option to change it.");
|
||||||
float tabX = (width / 50) + (tab.getWidth() / 2f);
|
float tabX = (width / 50) + (tab.getWidth() / 2f);
|
||||||
float tabY = 15 + Utils.FONT_XLARGE.getHeight() + (tab.getHeight() / 2f);
|
float tabY = 15 + Utils.FONT_XLARGE.getHeight() + (tab.getHeight() / 2f);
|
||||||
float tabOffset = tab.getWidth() * 0.85f;
|
float tabOffset = (float) Math.min(tab.getWidth(),
|
||||||
|
((width - subtextWidth - tab.getWidth()) / 2) / TAB_MAX);
|
||||||
for (int i = 0; i < optionTabs.length; i++)
|
for (int i = 0; i < optionTabs.length; i++)
|
||||||
optionTabs[i] = new GUIMenuButton(tab, tabX + (i * tabOffset), tabY);
|
optionTabs[i] = new GUIMenuButton(tab, tabX + (i * tabOffset), tabY);
|
||||||
|
|
||||||
|
@ -424,6 +449,10 @@ public class Options extends BasicGameState {
|
||||||
for (int i = 0; i < gameplayOptions.length; i++)
|
for (int i = 0; i < gameplayOptions.length; i++)
|
||||||
drawOption(gameplayOptions[i], i);
|
drawOption(gameplayOptions[i], i);
|
||||||
break;
|
break;
|
||||||
|
case TAB_CUSTOM:
|
||||||
|
for (int i = 0; i < customOptions.length; i++)
|
||||||
|
drawOption(customOptions[i], i);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// option tabs
|
// option tabs
|
||||||
|
@ -580,46 +609,72 @@ public class Options extends BasicGameState {
|
||||||
// options (drag only)
|
// options (drag only)
|
||||||
switch (getClickedOption(oldy)) {
|
switch (getClickedOption(oldy)) {
|
||||||
case MUSIC_VOLUME:
|
case MUSIC_VOLUME:
|
||||||
musicVolume += diff;
|
musicVolume = getBoundedValue(musicVolume, diff, 0, 100);
|
||||||
if (musicVolume < 0)
|
|
||||||
musicVolume = 0;
|
|
||||||
else if (musicVolume > 100)
|
|
||||||
musicVolume = 100;
|
|
||||||
container.setMusicVolume(getMusicVolume());
|
container.setMusicVolume(getMusicVolume());
|
||||||
break;
|
break;
|
||||||
case EFFECT_VOLUME:
|
case EFFECT_VOLUME:
|
||||||
effectVolume += diff;
|
effectVolume = getBoundedValue(effectVolume, diff, 0, 100);
|
||||||
if (effectVolume < 0)
|
|
||||||
effectVolume = 0;
|
|
||||||
else if (effectVolume > 100)
|
|
||||||
effectVolume = 100;
|
|
||||||
break;
|
break;
|
||||||
case HITSOUND_VOLUME:
|
case HITSOUND_VOLUME:
|
||||||
hitSoundVolume += diff;
|
hitSoundVolume = getBoundedValue(hitSoundVolume, diff, 0, 100);
|
||||||
if (hitSoundVolume < 0)
|
|
||||||
hitSoundVolume = 0;
|
|
||||||
else if (hitSoundVolume > 100)
|
|
||||||
hitSoundVolume = 100;
|
|
||||||
break;
|
break;
|
||||||
case MUSIC_OFFSET:
|
case MUSIC_OFFSET:
|
||||||
musicOffset += diff;
|
musicOffset = getBoundedValue(musicOffset, diff, -500, 500);
|
||||||
if (musicOffset < -500)
|
|
||||||
musicOffset = -500;
|
|
||||||
else if (musicOffset > 500)
|
|
||||||
musicOffset = 500;
|
|
||||||
break;
|
break;
|
||||||
case BACKGROUND_DIM:
|
case BACKGROUND_DIM:
|
||||||
backgroundDim += diff;
|
backgroundDim = getBoundedValue(backgroundDim, diff, 0, 100);
|
||||||
if (backgroundDim < 0)
|
break;
|
||||||
backgroundDim = 0;
|
case FIXED_CS:
|
||||||
else if (backgroundDim > 100)
|
fixedCS = getBoundedValue(fixedCS, diff / 10f, 0f, 10f);
|
||||||
backgroundDim = 100;
|
break;
|
||||||
|
case FIXED_HP:
|
||||||
|
fixedHP = getBoundedValue(fixedHP, diff / 10f, 0f, 10f);
|
||||||
|
break;
|
||||||
|
case FIXED_AR:
|
||||||
|
fixedAR = getBoundedValue(fixedAR, diff / 10f, 0f, 10f);
|
||||||
|
break;
|
||||||
|
case FIXED_OD:
|
||||||
|
fixedOD = getBoundedValue(fixedOD, diff / 10f, 0f, 10f);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a bounded value for when an option is dragged.
|
||||||
|
* @param var the initial value
|
||||||
|
* @param diff the value change
|
||||||
|
* @param min the minimum value
|
||||||
|
* @param max the maximum value
|
||||||
|
* @return the bounded value
|
||||||
|
*/
|
||||||
|
private int getBoundedValue(int var, int diff, int min, int max) {
|
||||||
|
int val = var + diff;
|
||||||
|
if (val < min)
|
||||||
|
val = min;
|
||||||
|
else if (val > max)
|
||||||
|
val = max;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a bounded value for when an option is dragged.
|
||||||
|
* @param var the initial value
|
||||||
|
* @param diff the value change
|
||||||
|
* @param min the minimum value
|
||||||
|
* @param max the maximum value
|
||||||
|
* @return the bounded value
|
||||||
|
*/
|
||||||
|
private float getBoundedValue(float var, float diff, float min, float max) {
|
||||||
|
float val = var + diff;
|
||||||
|
if (val < min)
|
||||||
|
val = min;
|
||||||
|
else if (val > max)
|
||||||
|
val = max;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void keyPressed(int key, char c) {
|
public void keyPressed(int key, char c) {
|
||||||
switch (key) {
|
switch (key) {
|
||||||
|
@ -755,6 +810,30 @@ public class Options extends BasicGameState {
|
||||||
"Whether to show perfect hit result bursts (300s, slider ticks)."
|
"Whether to show perfect hit result bursts (300s, slider ticks)."
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
case FIXED_CS:
|
||||||
|
drawOption(pos, "Fixed Circle Size (CS)",
|
||||||
|
(fixedCS == 0f) ? "Disabled" : String.format("%.1f", fixedCS),
|
||||||
|
"Determines the size of circles and sliders."
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case FIXED_HP:
|
||||||
|
drawOption(pos, "Fixed HP Drain Rate (HP)",
|
||||||
|
(fixedHP == 0f) ? "Disabled" : String.format("%.1f", fixedHP),
|
||||||
|
"Determines the rate at which health decreases."
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case FIXED_AR:
|
||||||
|
drawOption(pos, "Fixed Approach Rate (AR)",
|
||||||
|
(fixedAR == 0f) ? "Disabled" : String.format("%.1f", fixedAR),
|
||||||
|
"Determines how long hit circles stay on the screen."
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case FIXED_OD:
|
||||||
|
drawOption(pos, "Fixed Overall Difficulty (OD)",
|
||||||
|
(fixedOD == 0f) ? "Disabled" : String.format("%.1f", fixedOD),
|
||||||
|
"Determines the time window for hit results."
|
||||||
|
);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -806,6 +885,9 @@ public class Options extends BasicGameState {
|
||||||
if (index < gameplayOptions.length)
|
if (index < gameplayOptions.length)
|
||||||
option = gameplayOptions[index];
|
option = gameplayOptions[index];
|
||||||
break;
|
break;
|
||||||
|
case TAB_CUSTOM:
|
||||||
|
if (index < customOptions.length)
|
||||||
|
option = customOptions[index];
|
||||||
}
|
}
|
||||||
return option;
|
return option;
|
||||||
}
|
}
|
||||||
|
@ -942,6 +1024,30 @@ public class Options extends BasicGameState {
|
||||||
*/
|
*/
|
||||||
public static boolean isBeatmapSkinIgnored() { return ignoreBeatmapSkins; }
|
public static boolean isBeatmapSkinIgnored() { return ignoreBeatmapSkins; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the fixed circle size override, if any.
|
||||||
|
* @return the CS value (0, 10], 0 if disabled
|
||||||
|
*/
|
||||||
|
public static float getFixedCS() { return fixedCS; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the fixed HP drain rate override, if any.
|
||||||
|
* @return the HP value (0, 10], 0 if disabled
|
||||||
|
*/
|
||||||
|
public static float getFixedHP() { return fixedHP; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the fixed approach rate override, if any.
|
||||||
|
* @return the AR value (0, 10], 0 if disabled
|
||||||
|
*/
|
||||||
|
public static float getFixedAR() { return fixedAR; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the fixed overall difficulty override, if any.
|
||||||
|
* @return the OD value (0, 10], 0 if disabled
|
||||||
|
*/
|
||||||
|
public static float getFixedOD() { return fixedOD; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current beatmap directory.
|
* Returns the current beatmap directory.
|
||||||
* If invalid, this will attempt to search for the directory,
|
* If invalid, this will attempt to search for the directory,
|
||||||
|
@ -1078,6 +1184,18 @@ public class Options extends BasicGameState {
|
||||||
case "PerfectHit":
|
case "PerfectHit":
|
||||||
showPerfectHit = Boolean.parseBoolean(value);
|
showPerfectHit = Boolean.parseBoolean(value);
|
||||||
break;
|
break;
|
||||||
|
case "FixedCS":
|
||||||
|
fixedCS = Float.parseFloat(value);
|
||||||
|
break;
|
||||||
|
case "FixedHP":
|
||||||
|
fixedHP = Float.parseFloat(value);
|
||||||
|
break;
|
||||||
|
case "FixedAR":
|
||||||
|
fixedAR = Float.parseFloat(value);
|
||||||
|
break;
|
||||||
|
case "FixedOD":
|
||||||
|
fixedOD = Float.parseFloat(value);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -1145,6 +1263,14 @@ public class Options extends BasicGameState {
|
||||||
writer.newLine();
|
writer.newLine();
|
||||||
writer.write(String.format("PerfectHit = %b", showPerfectHit));
|
writer.write(String.format("PerfectHit = %b", showPerfectHit));
|
||||||
writer.newLine();
|
writer.newLine();
|
||||||
|
writer.write(String.format("FixedCS = %.1f", fixedCS));
|
||||||
|
writer.newLine();
|
||||||
|
writer.write(String.format("FixedHP = %.1f", fixedHP));
|
||||||
|
writer.newLine();
|
||||||
|
writer.write(String.format("FixedAR = %.1f", fixedAR));
|
||||||
|
writer.newLine();
|
||||||
|
writer.write(String.format("FixedOD = %.1f", fixedOD));
|
||||||
|
writer.newLine();
|
||||||
writer.close();
|
writer.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.error(String.format("Failed to write to file '%s'.", OPTIONS_FILE.getAbsolutePath()), e);
|
Log.error(String.format("Failed to write to file '%s'.", OPTIONS_FILE.getAbsolutePath()), e);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user