public float CalculateStandardPP(float combo, float c50, float c100, float c300, float cMiss, float cKatu = 0, float cGeki = 0) { if ((Play.Mods & OsuMods.Relax) != 0 || (Play.Mods & OsuMods.Relax2) != 0 || (Play.Mods & OsuMods.Autoplay) != 0) { return(0f); } float Accuracy = OsuApi.CalculateAccuracy(Play.Mode, cMiss, c50, c100, c300, cKatu, cGeki) * 0.01f; #region Standard MUL float cTotalHits = c50 + c100 + c300 + cMiss; float BonusLength = 0.95f + 0.4f * Mathf.Min(1.0f, cTotalHits / 2000.0f) + (cTotalHits > 2000?Mathf.Log10(cTotalHits / 2000.0f) * 0.5f:0.0f); float BonusMiss = (cMiss > 0?0.97f * Mathf.Pow(1.0f - Mathf.Pow(cMiss / cTotalHits, 0.775f), cMiss):1.0f); float BonusCombo = (Beatmap.MaxCombo > 0 ? Mathf.Min((Mathf.Pow(combo, 0.8f) / Mathf.Pow((float)Beatmap.MaxCombo, 0.8f)), 1.0f) : 1.0f); float BonusApproachRateFactor = 0.0f; if (Beatmap.MapStats.AR > 10.33f) { BonusApproachRateFactor += 0.4f * (Beatmap.MapStats.AR - 10.33f); } else if (Beatmap.MapStats.AR < 8.0f) { BonusApproachRateFactor += 0.01f * (8.0f - Beatmap.MapStats.AR); } float BonusApproachRate = 1.0f + Mathf.Min(BonusApproachRateFactor, BonusApproachRateFactor * (cTotalHits / 1000.0f)); float BonusHidden = ((Play.Mods & OsuMods.Hidden) != 0)?1.0f + 0.04f * (12.0f - Beatmap.MapStats.AR):1.0f; float BonusFlashlight = ((Play.Mods & OsuMods.Flashlight) != 0) ?1.0f + 0.35f * Mathf.Min(1.0f, cTotalHits / 200.0f) + (cTotalHits > 200?0.3f * Mathf.Min(1.0f, (cTotalHits - 200f) / 300f) + (cTotalHits > 500? ( cTotalHits - 500) / 1200.0f:0.0f):0.0f):1.0f; #endregion #region Standard AIM float AimValue = GetPPBase((float)Beatmap.StarratingAim); AimValue *= BonusLength; AimValue *= BonusMiss; AimValue *= BonusCombo; AimValue *= BonusApproachRate; AimValue *= BonusHidden; AimValue *= BonusFlashlight; AimValue *= (0.5f + Accuracy / 2.0f); AimValue *= (0.98f + (Mathf.Pow(Beatmap.MapStats.OD, 2f) / 2500f)); #endregion #region Standard SPEED float SpeedValue = GetPPBase((float)Beatmap.StarratingSpeed); SpeedValue *= BonusLength; SpeedValue *= BonusMiss; SpeedValue *= BonusCombo; //SpeedValue *= BonusApproachRate; float BonusSpeedApproachRateFactor = 0; if (Beatmap.MapStats.AR > 10.33f) { BonusSpeedApproachRateFactor += 0.4f * (Beatmap.MapStats.AR - 10.33f); } SpeedValue *= 1.0f + Mathf.Min(BonusSpeedApproachRateFactor, BonusSpeedApproachRateFactor * (cTotalHits / 1000f)); SpeedValue *= BonusHidden; SpeedValue *= (0.95f + Mathf.Pow(Beatmap.MapStats.OD, 2f) / 750f) * Mathf.Pow(Accuracy, (14.5f - Mathf.Max(Beatmap.MapStats.OD, 8.0f)) / 2f); SpeedValue *= Mathf.Pow(0.98f, (c50 < cTotalHits / 500f) ? (0.0f) : (c50 - cTotalHits / 500f)); #endregion #region Standard ACC float BetterAccuracyPercentage = 0; float cHitObjectsWithAccuracy = (float)Beatmap.CircleCount; if (cHitObjectsWithAccuracy > 0) { BetterAccuracyPercentage = ((c300 - (cTotalHits - cHitObjectsWithAccuracy)) * 6 + c100 * 2 + c50) / (cHitObjectsWithAccuracy * 6); } if (BetterAccuracyPercentage < 0) { BetterAccuracyPercentage = 0; } float AccValue = Mathf.Pow(1.52163f, Beatmap.MapStats.OD) * Mathf.Pow(BetterAccuracyPercentage, 24) * 2.83f; AccValue *= Mathf.Min(1.15f, Mathf.Pow(cHitObjectsWithAccuracy / 1000f, 0.3f)); if ((Play.Mods & OsuMods.Hidden) != 0) { AccValue *= 1.08f; } if ((Play.Mods & OsuMods.Flashlight) != 0) { AccValue *= 1.02f; } #endregion float TotalMultiplier = 1.12f; if ((Play.Mods & OsuMods.NoFail) != 0) { TotalMultiplier *= Mathf.Max(0.9f, 1.0f - 0.02f * cMiss); } if ((Play.Mods & OsuMods.SpunOut) != 0) { TotalMultiplier *= 1.0f - Mathf.Pow((float)Beatmap.SpinnerCount / cTotalHits, 0.85f); } float TotalValue = Mathf.Pow( Mathf.Pow(AimValue, 1.1f) + Mathf.Pow(SpeedValue, 1.1f) + Mathf.Pow(AccValue, 1.1f), 1.0f / 1.1f ) * TotalMultiplier; return(TotalValue); }
public float CalculateTaikoPP(float combo, float c50, float c100, float c300, float cMiss, float cKatu = 0, float cGeki = 0) { if ((Play.Mods & OsuMods.Relax) != 0 || (Play.Mods & OsuMods.Relax2) != 0 || (Play.Mods & OsuMods.Autoplay) != 0) { return(0f); } float cTotalHits = combo; float real_acc = OsuApi.CalculateAccuracy(Play.Mode, cMiss, c50, c100, c300, cKatu, cGeki) * 0.01f; //float real_acc = Mathf.Min(1.0f, Mathf.Max(0.0f, (c100 * 150 + c300 * 300)/(cTotalHits*300))); float strain = Mathf.Pow(5.0f * Mathf.Max(1.0f, (float)Beatmap.Starrating / 0.0075f) - 4.0f, 2.0f) / 100000.0f; float bonusLength = 1f + 0.1f * Mathf.Min(1.0f, cTotalHits / 1500f); strain *= bonusLength; strain *= Mathf.Pow(0.985f, cMiss); strain *= Mathf.Min(Mathf.Pow(Play.MaxCombo, 0.5f) / Mathf.Pow(cTotalHits, 0.5f), 1); if ((Play.Mods & OsuMods.Hidden) != 0) { strain *= 1.025f; } if ((Play.Mods & OsuMods.Flashlight) != 0) { strain *= 1.05f * bonusLength; } strain *= real_acc; float OD300 = 0; float hwMax = 20f; float hwMin = 50f; float hwResult = hwMin + (hwMax - hwMin) * Beatmap.MapStats.OD / 10f; hwResult = Mathf.Floor(hwResult) - 0.5f; if ((Play.Mods & OsuMods.HalfTime) != 0) { hwResult *= 1.5f; } if ((Play.Mods & OsuMods.DoubleTime) != 0) { hwResult *= 0.75f; } OD300 = Mathf.Round(hwResult * 100f) / 100f; float acc = 0; if (OD300 > 0) { acc = Mathf.Pow(150.0f / OD300, 1.1f) * Mathf.Pow(real_acc, 15f) * 22.0f; acc *= Mathf.Min(1.15f, Mathf.Pow(cTotalHits / 1500.0f, 0.3f)); } float total = 1.1f; if ((Play.Mods & OsuMods.NoFail) != 0) { total *= 0.9f; } if ((Play.Mods & OsuMods.Hidden) != 0) { total *= 1.1f; } return(Mathf.Pow( Mathf.Pow(strain, 1.1f) + Mathf.Pow(acc, 1.1f), 1.0f / 1.1f ) * total); }
public float CalculateManiaPP(float combo, float c50, float c100, float c300, float cMiss, float cKatu = 0, float cGeki = 0) { if ((Play.Mods & OsuMods.Relax) != 0 || (Play.Mods & OsuMods.Relax2) != 0 || (Play.Mods & OsuMods.Autoplay) != 0) { return(0f); } float cTotalHits = c50 + c100 + c300 + cMiss + cGeki + cKatu; float real_acc = OsuApi.CalculateAccuracy(Play.Mode, cMiss, c50, c100, c300, cKatu, cGeki); float strainbase = Mathf.Pow(5.0f * Mathf.Max(1f, (float)Beatmap.Starrating / 0.2f) - 4f, 2.2f) / 135.0f; strainbase *= 1f + 0.1f * Mathf.Min(1f, cTotalHits / 1500f); float strain = strainbase; float scoreMultiplier = 0; if (Play.Score < 500000) { scoreMultiplier = Play.Score / 500000f * 0.1f; } else if (Play.Score < 600000) { scoreMultiplier = (Play.Score - 500000f) / 100000f * 0.3f; } else if (Play.Score < 700000) { scoreMultiplier = (Play.Score - 600000f) / 100000f * 0.25f + 0.3f; } else if (Play.Score < 800000) { scoreMultiplier = (Play.Score - 700000f) / 100000f * 0.2f + 0.55f; } else if (Play.Score < 900000) { scoreMultiplier = (Play.Score - 800000f) / 100000f * 0.15f + 0.75f; } else { scoreMultiplier = (Play.Score - 900000f) / 100000f * 0.1f + 0.9f; } // float[][] odconvertwindow = new float[2][] // { // new float[2] {47, 34}, // new float[2] {65, 47} // }; // // float odwindow = ((Beatmap.OriginalMode == OsuMode.Standard)) ? odconvertwindow[((Play.Mods&OsuMods.Easy)!=0)?1:0][(Beatmap.MapStats.OD>=5)?1:0]:((64f-3f*Beatmap.MapStats.OD)* (((Play.Mods & OsuMods.Easy) != 0) ? 1.4f : 1f)); // // float acc = Mathf.Max(0.0f, 0.2f - ((odwindow - 34f) * 0.006667f)) * strain; // acc *= Mathf.Pow(Mathf.Max(0.0f, (Play.Score - 960000f)) / 40000.0f, 1.1f); float acc = 1.0f; float nerfod = ((Play.Mods & OsuMods.Easy) != 0) ? 0.5f : 1.0f; if (Play.Score >= 960000) { acc = Beatmap.MapStats.OD * nerfod * 0.02f * strainbase * Mathf.Pow((Play.Score - 960000f) / 40000f, 1.1f); } else { acc = 0; } float total = 0.8f; if ((Play.Mods & OsuMods.NoFail) != 0) { total *= 0.9f; } if ((Play.Mods & OsuMods.SpunOut) != 0) { total *= 0.95f; } if ((Play.Mods & OsuMods.Easy) != 0) { total *= 0.5f; } return(total * Mathf.Pow( Mathf.Pow(strain * scoreMultiplier, 1.1f) + Mathf.Pow(acc, 1.1f), 1.0f / 1.1f )); }