冰与火之舞(adofai)判定公式

公式
提前 = ((打击角度 - 参考角度) * ±1(是否旋转) * 180.0 / π) ≤ -(Max(60.0, Max(默认难度初始判定区间/飚速模式倍数, 0.025) * 音高 * 180 / 60.0 * bpm))
太快 = -(Max(60.0, Max(默认难度初始判定区间/飚速模式倍数, 0.025) * 音高 * 180 / 60.0 * bpm)) < ((打击角度 - 参考角度) * ±1(是否旋转) * 180.0 / π) ≤ -(Max(45.0, Max(0.03/飚速模式倍数, 0.025) * 音高 * 180 / 60.0 * bpm))
稍快 = -(Max(45.0, Max(0.03f/飚速模式倍数, 0.025) * 音高 * 180 / 60.0 * bpm)) < ((打击角度 - 参考角度) * ±1(是否旋转) * 180.0 / π) ≤ -(Max(30.0, Max(0.02/飚速模式倍数, 0.025) * 音高 * 180 / 60.0 * bpm))
完美 = -(Max(30.0, Max(0.02f/飚速模式倍数, 0.025) * 音高 * 180 / 60.0 * bpm)) < ((打击角度 - 参考角度) * ±1(是否旋转) * 180.0 / π) ≤ (Max(30.0, Max(0.02/飚速模式倍数, 0.025) * 音高 * 180 / 60.0 * bpm))
稍慢 = (Max(30.0, Max(0.02f/飚速模式倍数, 0.025) * 音高 * 180 / 60.0 * bpm)) < ((打击角度 - 参考角度) * ±1(是否旋转) * 180.0 / π) ≤ (Max(45.0, Max(0.03/飚速模式倍数, 0.025) * 音高 * 180 / 60.0 * bpm))
太慢 = (Max(45.0, Max(0.03f/飚速模式倍数, 0.025) * 音高 * 180 / 60.0 * bpm)) < ((打击角度 - 参考角度) * ±1(是否旋转) * 180.0 / π) ≤ (Max(60.0, Max(默认难度初始判定区间/飚速模式倍数, 0.025) * 音高 * 180 / 60.0 * bpm))
失败 = ((打击角度 - 参考角度) * ±1(是否旋转) * 180.0 / π) > (Max(60.0, Max(默认难度初始判定区间/飚速模式倍数, 0.025) * 音高 * 180 / 60.0 * bpm))
解释:
打击角度-参考角度:玩家操作的球和目标砖块之间的角度差(弧度制)
±1(是否旋转):如果这个砖块有旋转事件则*-1,否则*1
* 180.0 / π:把弧度制转为角度制
Max(a,b):取a,b中较大的一个
默认难度初始判定区间:宽判:0.091;标判:0.065;严判:0.04
飚速模式倍数:默认为1.0,如2.8倍此值就是2.8
/ 60.0 * bpm:把beats/min(每分钟节拍数)转为beats/sec(每秒钟节拍数)
音高默认=1
上述的bpm为等效bpm,也就是当前砖块bpm*飙速倍数
相关源代码(注释为自己写的)
public static HitMargin GetHitMargin(float hitangle, float refangle, bool isCW, float bpmTimesSpeed, float conductorPitch)
{
float num = (hitangle - refangle) * (float)(isCW ? 1 : -1);
HitMargin result = HitMargin.TooEarly;
float num2 = num;
num2 = 57.29578f * num2;
double adjustedAngleBoundaryInDeg = scrMisc.GetAdjustedAngleBoundaryInDeg(HitMarginGeneral.Counted, (double)bpmTimesSpeed, (double)conductorPitch);
double adjustedAngleBoundaryInDeg2 = scrMisc.GetAdjustedAngleBoundaryInDeg(HitMarginGeneral.Perfect, (double)bpmTimesSpeed, (double)conductorPitch);
double adjustedAngleBoundaryInDeg3 = scrMisc.GetAdjustedAngleBoundaryInDeg(HitMarginGeneral.Pure, (double)bpmTimesSpeed, (double)conductorPitch);
/*
adjustedAngleBoundaryInDeg = Math.Max(60.0, Mathf.Max(默认难度初始判定区间/飚速模式倍数, 0.025f) * 音高 * π / 60.0 * bpm);
adjustedAngleBoundaryInDeg2 = Math.Max(45.0, Mathf.Max(0.03f/飚速模式倍数, 0.025f) * 音高 * π / 60.0 * bpm);
adjustedAngleBoundaryInDeg3 = Math.Max(30.0, Mathf.Max(0.02f/飚速模式倍数, 0.025f) * 音高 * π / 60.0 * bpm);
*/
if ((double)num2 > -adjustedAngleBoundaryInDeg)
{
result = HitMargin.VeryEarly;
}
if ((double)num2 > -adjustedAngleBoundaryInDeg2)
{
result = HitMargin.EarlyPerfect;
}
if ((double)num2 > -adjustedAngleBoundaryInDeg3)
{
result = HitMargin.Perfect;
}
if ((double)num2 > adjustedAngleBoundaryInDeg3)
{
result = HitMargin.LatePerfect;
}
if ((double)num2 > adjustedAngleBoundaryInDeg2)
{
result = HitMargin.VeryLate;
}
if ((double)num2 > adjustedAngleBoundaryInDeg)
{
result = HitMargin.TooLate;
}
return result;
}
public static double GetAdjustedAngleBoundaryInDeg(HitMarginGeneral marginType, double bpmTimesSpeed, double conductorPitch)
{
float num = 0.065f;
if (GCS.difficulty == Difficulty.Lenient)
{
num = 0.091f;
}
if (GCS.difficulty == Difficulty.Normal)
{
num = 0.065f;
}
if (GCS.difficulty == Difficulty.Strict)
{
num = 0.04f;
}
bool isMobile = ADOBase.isMobile;
num = (isMobile ? 0.09f : (num / GCS.currentSpeedTrial));
float num2 = isMobile ? 0.07f : (0.03f / GCS.currentSpeedTrial);
float a = isMobile ? 0.05f : (0.02f / GCS.currentSpeedTrial);
//num(最宽松,可能为太快太慢)=默认难度初始判定区间/GCS.currentSpeedTrial
//num2(可能为稍快稍慢)=0.03f/GCS.currentSpeedTrial
//a(可能为完美)=0.02f/GCS.currentSpeedTrial
//currentSpeedTrial应该是飚速模式
num = Mathf.Max(num, 0.025f);
//避免过低bpm导致反向高bpm补偿
num2 = Mathf.Max(num2, 0.025f);
//避免过低bpm导致反向高bpm补偿
double num3 = (double)Mathf.Max(a, 0.025f);
//避免过低bpm导致反向高bpm补偿
/*
num = Mathf.Max(默认难度初始判定区间/GCS.currentSpeedTrial, 0.025f);
num2 = Mathf.Max(0.03f/GCS.currentSpeedTrial, 0.025f);
num3 = Mathf.Max(0.02f/GCS.currentSpeedTrial, 0.025f);
float double 乱用是吧
*/
double val = scrMisc.TimeToAngleInRad((double)num, bpmTimesSpeed, conductorPitch, false) * 57.295780181884766;//180/π=57.29
double val2 = scrMisc.TimeToAngleInRad((double)num2, bpmTimesSpeed, conductorPitch, false) * 57.295780181884766;
double val3 = scrMisc.TimeToAngleInRad(num3, bpmTimesSpeed, conductorPitch, false) * 57.295780181884766;
/*
val=Mathf.Max(默认难度初始判定区间/GCS.currentSpeedTrial, 0.025f) * conductorPitch * π / 60.0 * bpmTimesSpeed
val2=Mathf.Max(0.03f/GCS.currentSpeedTrial, 0.025f) * conductorPitch * π / 60.0 * bpmTimesSpeed
val3=Mathf.Max(0.02f/GCS.currentSpeedTrial, 0.025f) * conductorPitch * π / 60.0 * bpmTimesSpeed
*/
double result = Math.Max((double)GCS.HITMARGIN_COUNTED, val);
//GCS.HITMARGIN_COUNTED被赋值的三个函数最终都未被使用,因此取初始值60f
double result2 = Math.Max(45.0, val2);
double result3 = Math.Max(30.0, val3);
/*
result = Math.Max(60.0, Mathf.Max(默认难度初始判定区间/飚速模式倍数, 0.025f) * 音高 * π / 60.0 * bpm);
result2 = Math.Max(45.0, Mathf.Max(0.03f/飚速模式倍数, 0.025f) * 音高 * π / 60.0 * bpm);
result3 = Math.Max(30.0, Mathf.Max(0.02f/飚速模式倍数, 0.025f) * 音高 * π / 60.0 * bpm);
这123的 起变量名不要num1 val2 result3!!血压已经起来了
*/
if (marginType == HitMarginGeneral.Counted)
{
return result;
}
if (marginType == HitMarginGeneral.Perfect)
{
return result2;
}
if (marginType == HitMarginGeneral.Pure)
{
return result3;
}
return result;
}
public static double TimeToAngleInRad(double timeinAbsoluteSpace, double bpmTimesSpeed, double conductorPitch, bool shrinkMarginsForHigherPitch = false)
{
double num;
/*if (shrinkMarginsForHigherPitch)
{
num = timeinAbsoluteSpace;
}
else
{*/
num = timeinAbsoluteSpace * conductorPitch;
//}
return num * 3.1415927410125732 / scrMisc.bpm2crotchet(bpmTimesSpeed);
//num = timeinAbsoluteSpace * conductorPitch * π / 60.0 * bpmTimesSpeed
}
public static double bpm2crotchet(double bpm)
{
return 60.0 / bpm;
}