Merge remote-tracking branch 'org/master' into ReplayTest

Conflicts:
	src/itdelatrisu/opsu/GameData.java
	src/itdelatrisu/opsu/states/Game.java
This commit is contained in:
fd
2015-06-21 20:05:36 -04:00
7 changed files with 73 additions and 107 deletions

View File

@@ -293,19 +293,8 @@ public class GameData {
/** Displayed health (for animation, slightly behind health). */ /** Displayed health (for animation, slightly behind health). */
private float healthDisplay; private float healthDisplay;
/** Beatmap HPDrainRate value. (0:easy ~ 10:hard) */ /** The difficulty multiplier used in the score formula. */
private float drainRate = 5f; private int difficultyMultiplier = 2;
/** Beatmap OverallDifficulty value. (0:easy ~ 10:hard) */
private float difficulty = 5f;
/** Beatmap ApproachRate value. (0:easy ~ 10:hard) */
private float approachRate = 5f;
/** Beatmap CircleSize value. (2:big ~ 7:small) */
private float circleSize = 5f;
private int difficultyMultiplier = -1;
/** Default text symbol images. */ /** Default text symbol images. */
private Image[] defaultSymbols; private Image[] defaultSymbols;
@@ -472,40 +461,6 @@ public class GameData {
*/ */
public Image getScoreSymbolImage(char c) { return scoreSymbols.get(c); } public Image getScoreSymbolImage(char c) { return scoreSymbols.get(c); }
/**
* Sets the health drain rate.
* @param drainRate the new drain rate [0-10]
*/
public void setDrainRate(float drainRate) { this.drainRate = drainRate; }
/**
* Returns the health drain rate.
*/
public float getDrainRate() { return drainRate; }
/**
* Sets the overall difficulty level.
* @param difficulty the new difficulty [0-10]
*/
public void setDifficulty(float difficulty) { this.difficulty = difficulty; }
/**
* Returns the overall difficulty level.
*/
public float getDifficulty() { return difficulty; }
/**
* Sets or returns the approach rate.
*/
public void setApproachRate(float approachRate) { this.approachRate = approachRate; }
public float getApproachRate() { return approachRate; }
/**
* Sets or returns the approach rate.
*/
public void setCircleSize(float circleSize) { this.circleSize = circleSize; }
public float getCircleSize() { return circleSize; }
/** /**
* Sets the array of hit result offsets. * Sets the array of hit result offsets.
*/ */
@@ -1212,7 +1167,6 @@ public class GameData {
switch (result) { switch (result) {
case HIT_SLIDER30: case HIT_SLIDER30:
hitValue = 30; hitValue = 30;
incrementComboStreak();
changeHealth(1f); changeHealth(1f);
SoundController.playHitSound( SoundController.playHitSound(
hitObject.getEdgeHitSoundType(repeat), hitObject.getEdgeHitSoundType(repeat),
@@ -1221,7 +1175,6 @@ public class GameData {
break; break;
case HIT_SLIDER10: case HIT_SLIDER10:
hitValue = 10; hitValue = 10;
incrementComboStreak();
SoundController.playHitSound(HitSound.SLIDERTICK); SoundController.playHitSound(HitSound.SLIDERTICK);
break; break;
case HIT_MISS: case HIT_MISS:
@@ -1230,15 +1183,18 @@ public class GameData {
default: default:
return; return;
} }
fullObjectCount++;
if (hitValue > 0) { if (hitValue > 0) {
// calculate score and increment combo streak
score += hitValue; score += hitValue;
incrementComboStreak();
if (!Options.isPerfectHitBurstEnabled()) if (!Options.isPerfectHitBurstEnabled())
; // hide perfect hit results ; // hide perfect hit results
else else
hitResultList.add(new HitObjectResult(time, result, x, y, null, HitObjectType.SLIDERTICK, null, false)); hitResultList.add(new HitObjectResult(time, result, x, y, null, HitObjectType.SLIDERTICK, null, false));
} }
fullObjectCount++;
} }
public void sliderFinalResult(int time, int hitSlider30, float x, float y, public void sliderFinalResult(int time, int hitSlider30, float x, float y,
HitObject hitObject, int currentRepeats) { HitObject hitObject, int currentRepeats) {
@@ -1253,7 +1209,7 @@ public class GameData {
* <ul> * <ul>
* <li><strong>Hit Value:</strong> hit result (50, 100, 300), slider ticks, spinner bonus * <li><strong>Hit Value:</strong> hit result (50, 100, 300), slider ticks, spinner bonus
* <li><strong>Combo:</strong> combo before this hit - 1 (minimum 0) * <li><strong>Combo:</strong> combo before this hit - 1 (minimum 0)
* <li><strong>Difficulty:</strong> the beatmap difficulty * <li><strong>Difficulty:</strong> the difficulty setting (see {@link #calculateDifficultyMultiplier(float, float, float)})
* <li><strong>Mod:</strong> mod multipliers * <li><strong>Mod:</strong> mod multipliers
* </ul> * </ul>
* @param hitValue the hit value * @param hitValue the hit value
@@ -1265,9 +1221,44 @@ public class GameData {
if(hitObject.isSlider()){ if(hitObject.isSlider()){
comboMulti += 1; comboMulti += 1;
} }
return (hitValue + (int)(hitValue * (comboMulti * getDifficultyMultiplier() * GameMod.getScoreMultiplier()) / 25)); return (hitValue + (int)(hitValue * (comboMulti * difficultyMultiplier * GameMod.getScoreMultiplier()) / 25));
}
/**
* https://osu.ppy.sh/wiki/Score#How_to_calculate_the_Difficulty_multiplier
* Computes and stores the difficulty multiplier used in the score formula.
* @param drainRate the raw HP drain rate value
* @param circleSize the raw circle size value
* @param overallDifficulty the raw overall difficulty value
*/
public void calculateDifficultyMultiplier(float drainRate, float circleSize, float overallDifficulty) {
//TODO THE LIES ( difficultyMultiplier )
//*
float sum = drainRate + circleSize + overallDifficulty; // typically 2~27
if (sum <= 5f)
difficultyMultiplier = 2;
else if (sum <= 12f)
difficultyMultiplier = 3;
else if (sum <= 17f)
difficultyMultiplier = 4;
else if (sum <= 24f)
difficultyMultiplier = 5;
else //if (sum <= 30f)
difficultyMultiplier = 6;
//*/
/*
924 3x1/4 beat notes 0.14stars
924 3x1beat 0.28stars
912 3x1beat wth 1 extra note 10 sec away 0.29stars
seems to be based on hitobject density? (Total Objects/Time)
*/
/*
float mult = ((circleSize + overallDifficulty + drainRate) / 6) + 1.5f;
System.out.println("diffuculty Multiplier : "+ mult);
difficultyMultiplier = (int)mult;
*/
} }
/** /**
* Handles a hit result and performs all associated calculations. * Handles a hit result and performs all associated calculations.
* @param time the object start time * @param time the object start time
@@ -1291,18 +1282,15 @@ public class GameData {
changeHealth(5f); changeHealth(5f);
break; break;
case HIT_100: case HIT_100:
System.out.println("100! "+hitObject+" "+hitObject.getTime()+" "+hitObject.getTypeName());
hitValue = 100; hitValue = 100;
changeHealth(2f); changeHealth(2f);
comboEnd |= 1; comboEnd |= 1;
break; break;
case HIT_50: case HIT_50:
System.out.println("50! "+hitObject+" "+hitObject.getTime()+" "+hitObject.getTypeName());
hitValue = 50; hitValue = 50;
comboEnd |= 2; comboEnd |= 2;
break; break;
case HIT_MISS: case HIT_MISS:
System.out.println("miss! "+hitObject+" "+hitObject.getTime()+" "+hitObject.getTypeName());
hitValue = 0; hitValue = 0;
changeHealth(-10f); changeHealth(-10f);
comboEnd |= 2; comboEnd |= 2;
@@ -1320,7 +1308,6 @@ public class GameData {
// calculate score and increment combo streak // calculate score and increment combo streak
changeScore(getScoreForHit(hitValue, hitObject)); changeScore(getScoreForHit(hitValue, hitObject));
incrementComboStreak(); incrementComboStreak();
//merge conflict end
} }
hitResultCount[result]++; hitResultCount[result]++;
fullObjectCount++; fullObjectCount++;
@@ -1365,45 +1352,26 @@ public class GameData {
public void hitResult(int time, int result, float x, float y, Color color, public void hitResult(int time, int result, float x, float y, Color color,
boolean end, HitObject hitObject, int repeat, boolean end, HitObject hitObject, int repeat,
HitObjectType hitResultType, Curve curve, boolean expand) { HitObjectType hitResultType, Curve curve, boolean expand) {
result = handleHitResult(time, result, x, y, color, end, hitObject, repeat, hitResultType); int hitResult = handleHitResult(time, result, x, y, color, end, hitObject, repeat, hitResultType);
if ((result == HIT_300 || result == HIT_300G || result == HIT_300K) && !Options.isPerfectHitBurstEnabled()) if ((hitResult == HIT_300 || hitResult == HIT_300G || hitResult == HIT_300K) && !Options.isPerfectHitBurstEnabled())
; // hide perfect hit results ; // hide perfect hit results
else if (result == HIT_MISS && (GameMod.RELAX.isActive() || GameMod.AUTOPILOT.isActive())) else if (hitResult == HIT_MISS && (GameMod.RELAX.isActive() || GameMod.AUTOPILOT.isActive()))
; // "relax" and "autopilot" mods: hide misses ; // "relax" and "autopilot" mods: hide misses
else { else {
hitResultList.add(new HitObjectResult(time, result, x, y, color, hitResultType, curve, expand)); hitResultList.add(new HitObjectResult(time, hitResult, x, y, color, hitResultType, curve, expand));
// sliders: add the other curve endpoint for the hit animation // sliders: add the other curve endpoint for the hit animation
if (curve != null) { if (curve != null) {
boolean isFirst = (hitResultType == HitObjectType.SLIDER_FIRST); boolean isFirst = (hitResultType == HitObjectType.SLIDER_FIRST);
float[] p = curve.pointAt((isFirst) ? 1f : 0f); float[] p = curve.pointAt((isFirst) ? 1f : 0f);
HitObjectType type = (isFirst) ? HitObjectType.SLIDER_LAST : HitObjectType.SLIDER_FIRST; HitObjectType type = (isFirst) ? HitObjectType.SLIDER_LAST : HitObjectType.SLIDER_FIRST;
hitResultList.add(new HitObjectResult(time, result, p[0], p[1], color, type, null, expand)); hitResultList.add(new HitObjectResult(time, hitResult, p[0], p[1], color, type, null, expand));
} }
} }
} }
private int getDifficultyMultiplier() {
return difficultyMultiplier;
}
/**
* https://osu.ppy.sh/wiki/Score#How_to_calculate_the_Difficulty_multiplier
*/
public void calculateDifficultyMultiplier() {
//TODO THE LIES ( difficultyMultiplier )
/*
924 3x1/4 beat notes 0.14stars
924 3x1beat 0.28stars
912 3x1beat wth 1 extra note 10 sec away 0.29stars
seems to be based on hitobject density? (Total Objects/Time)
*/
float mult = ((circleSize + difficulty + drainRate) / 6) + 1.5f;
System.out.println("diffuculty Multiplier : "+ mult);
difficultyMultiplier = (int)mult;
}
/** /**
* Returns a ScoreData object encapsulating all game data. * Returns a ScoreData object encapsulating all game data.
* If score data already exists, the existing object will be returned * If score data already exists, the existing object will be returned

View File

@@ -260,6 +260,8 @@ public class DownloadNode {
UI.sendBarNotification("Download failed due to a connection error."); UI.sendBarNotification("Download failed due to a connection error.");
} }
}); });
if (Options.useUnicodeMetadata()) // load glyphs
Utils.loadGlyphs(Utils.FONT_LARGE, getTitle(), null);
} }
/** /**

View File

@@ -65,7 +65,7 @@ public class Circle implements GameObject {
* @param circleSize the map's circleSize value * @param circleSize the map's circleSize value
*/ */
public static void init(GameContainer container, float circleSize) { public static void init(GameContainer container, float circleSize) {
diameter = (108 - (circleSize * 8)); diameter = (104 - (circleSize * 8));
diameter = (diameter * HitObject.getXMultiplier()); // convert from Osupixels (640x480) diameter = (diameter * HitObject.getXMultiplier()); // convert from Osupixels (640x480)
int diameterInt = (int)diameter; int diameterInt = (int)diameter;
GameImage.HITCIRCLE.setImage(GameImage.HITCIRCLE.getImage().getScaledCopy(diameterInt, diameterInt)); GameImage.HITCIRCLE.setImage(GameImage.HITCIRCLE.getImage().getScaledCopy(diameterInt, diameterInt));

View File

@@ -117,15 +117,11 @@ public class Slider implements GameObject {
containerWidth = container.getWidth(); containerWidth = container.getWidth();
containerHeight = container.getHeight(); containerHeight = container.getHeight();
diameter = (108 - (circleSize * 8)); diameter = (104 - (circleSize * 8));
diameter = (diameter * HitObject.getXMultiplier()); // convert from Osupixels (640x480) diameter = (diameter * HitObject.getXMultiplier()); // convert from Osupixels (640x480)
int diameterInt = (int)diameter; int diameterInt = (int)diameter;
followRadius = diameter / 2 * 3f; followRadius = diameter / 2 * 3f;
/*
int diameter = (int) (104 - (circleSize * 8));
diameter = (int) (diameter * HitObject.getXMultiplier()); // convert from Osupixels (640x480)
*/
// slider ball // slider ball
if (GameImage.SLIDER_BALL.hasSkinImages() || if (GameImage.SLIDER_BALL.hasSkinImages() ||
(!GameImage.SLIDER_BALL.hasSkinImage() && GameImage.SLIDER_BALL.getImages() != null)) (!GameImage.SLIDER_BALL.hasSkinImage() && GameImage.SLIDER_BALL.getImages() != null))

View File

@@ -41,6 +41,9 @@ public class Spinner implements GameObject {
/** Container dimensions. */ /** Container dimensions. */
private static int width, height; private static int width, height;
/** The map's overall difficulty value. */
private static float overallDifficulty = 5f;
/** The number of rotation velocities to store. */ /** The number of rotation velocities to store. */
private int maxStoredDeltaAngles; private int maxStoredDeltaAngles;
@@ -104,10 +107,12 @@ public class Spinner implements GameObject {
/** /**
* Initializes the Spinner data type with images and dimensions. * Initializes the Spinner data type with images and dimensions.
* @param container the game container * @param container the game container
* @param difficulty the map's overall difficulty value
*/ */
public static void init(GameContainer container) { public static void init(GameContainer container, float difficulty) {
width = container.getWidth(); width = container.getWidth();
height = container.getHeight(); height = container.getHeight();
overallDifficulty = difficulty;
} }
/** /**
@@ -160,7 +165,7 @@ public class Spinner implements GameObject {
storedDeltaAngle = new float[maxStoredDeltaAngles]; storedDeltaAngle = new float[maxStoredDeltaAngles];
// calculate rotations needed // calculate rotations needed
float spinsPerMinute = 100 + (data.getDifficulty() * 15); float spinsPerMinute = 100 + (overallDifficulty * 15);
rotationsNeeded = spinsPerMinute * (hitObject.getEndTime() - hitObject.getTime()) / 60000f; rotationsNeeded = spinsPerMinute * (hitObject.getEndTime() - hitObject.getTime()) / 60000f;
} }
@@ -263,7 +268,6 @@ public class Spinner implements GameObject {
if (isSpinning && !(keyPressed || GameMod.RELAX.isActive())) if (isSpinning && !(keyPressed || GameMod.RELAX.isActive()))
isSpinning = false; isSpinning = false;
System.out.println("Spinner update "+mouseX+" "+mouseY+" "+deltaOverflow);
// spin automatically // spin automatically
// http://osu.ppy.sh/wiki/FAQ#Spinners // http://osu.ppy.sh/wiki/FAQ#Spinners

View File

@@ -10,6 +10,8 @@ import itdelatrisu.opsu.db.ScoreDB;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import org.newdawn.slick.util.Log;
public class ReplayImporter { public class ReplayImporter {
public static void importAllReplaysFromDir(File dir) { public static void importAllReplaysFromDir(File dir) {
for (File replayToImport : dir.listFiles()) { for (File replayToImport : dir.listFiles()) {
@@ -28,21 +30,18 @@ public class ReplayImporter {
//ErrorHandler.error("Importing"+replayToImport+" forBeatmap:"+oFile, null, false); //ErrorHandler.error("Importing"+replayToImport+" forBeatmap:"+oFile, null, false);
ScoreData data = r.getScoreData(oFile); ScoreData data = r.getScoreData(oFile);
File moveToFile = new File(replaydir, replayToImport.getName()); File moveToFile = new File(replaydir, replayToImport.getName());
System.out.println("Moving "+replayToImport+" to "+moveToFile);
if( if(
!replayToImport.renameTo(moveToFile) !replayToImport.renameTo(moveToFile)
){ ){
System.out.println("Rename Failed "+moveToFile); Log.warn("Rename Failed "+moveToFile);
} }
data.replayString = replayToImport.getName().substring(0, replayToImport.getName().length()-4); data.replayString = replayToImport.getName().substring(0, replayToImport.getName().length()-4);
ScoreDB.addScore(data);; ScoreDB.addScore(data);;
} else { } else {
System.out.println("Could not find beatmap for replay "+replayToImport); Log.warn("Could not find beatmap for replay "+replayToImport);
//ErrorHandler.error("Could not find beatmap for replay "+replayToImport, null, false);
} }
} catch (IOException e) { } catch (IOException e) {
//e.printStackTrace(); Log.warn("Failed to import replays ",e);
System.out.println(e);
} }
} }

View File

@@ -924,7 +924,6 @@ public class Game extends BasicGameState {
if(!GameMod.AUTO.isActive() && y < 50){ if(!GameMod.AUTO.isActive() && y < 50){
float pos = (float)x / width * beatmap.endTime; float pos = (float)x / width * beatmap.endTime;
System.out.println("Seek to"+pos);
MusicController.setPosition((int)pos); MusicController.setPosition((int)pos);
} }
return; return;
@@ -1403,8 +1402,9 @@ public class Game extends BasicGameState {
float circleSize = Math.min(beatmap.circleSize * multiplier, 10f); float circleSize = Math.min(beatmap.circleSize * multiplier, 10f);
float approachRate = Math.min(beatmap.approachRate * multiplier, 10f); float approachRate = Math.min(beatmap.approachRate * multiplier, 10f);
float overallDifficulty = Math.min(beatmap.overallDifficulty * multiplier, 10f); float overallDifficulty = Math.min(beatmap.overallDifficulty * multiplier, 10f);
float HPDrainRate = Math.min(beatmap.HPDrainRate * multiplier, 10f); //TODO never actually used, everything seems to be using GameData.HP_DRAIN_MULTIPLIER
float HPDrainRate = Math.min(beatmap.HPDrainRate * multiplier, 10f);
// fixed difficulty overrides // fixed difficulty overrides
if (Options.getFixedCS() > 0f) if (Options.getFixedCS() > 0f)
circleSize = Options.getFixedCS(); circleSize = Options.getFixedCS();
@@ -1423,7 +1423,7 @@ public class Game extends BasicGameState {
// initialize objects // initialize objects
Circle.init(container, circleSize); Circle.init(container, circleSize);
Slider.init(container, circleSize, beatmap); Slider.init(container, circleSize, beatmap);
Spinner.init(container); Spinner.init(container, overallDifficulty);
Curve.init(container.getWidth(), container.getHeight(), circleSize, (Options.isBeatmapSkinIgnored()) ? Curve.init(container.getWidth(), container.getHeight(), circleSize, (Options.isBeatmapSkinIgnored()) ?
Options.getSkin().getSliderBorderColor() : beatmap.getSliderBorderColor()); Options.getSkin().getSliderBorderColor() : beatmap.getSliderBorderColor());
@@ -1446,14 +1446,11 @@ public class Game extends BasicGameState {
hitResultOffset[GameData.HIT_100] = (int) (138 - (overallDifficulty * 8)); hitResultOffset[GameData.HIT_100] = (int) (138 - (overallDifficulty * 8));
hitResultOffset[GameData.HIT_50] = (int) (198 - (overallDifficulty * 10)); hitResultOffset[GameData.HIT_50] = (int) (198 - (overallDifficulty * 10));
hitResultOffset[GameData.HIT_MISS] = (int) (500 - (overallDifficulty * 10)); hitResultOffset[GameData.HIT_MISS] = (int) (500 - (overallDifficulty * 10));
//*/
// HPDrainRate (health change), overallDifficulty (scoring)
data.setDrainRate(HPDrainRate);
data.setDifficulty(overallDifficulty);
data.setApproachRate(approachRate);
data.setCircleSize(circleSize);
data.setHitResultOffset(hitResultOffset); data.setHitResultOffset(hitResultOffset);
data.calculateDifficultyMultiplier(); //*/
// difficulty multiplier (scoring)
data.calculateDifficultyMultiplier(beatmap.HPDrainRate, beatmap.circleSize, beatmap.overallDifficulty);
} }
/** /**