/// <summary> /// Correction #8 - Stacked notes nerf /// We apply a nerf to the difficulty depending on how much objects overlap. /// </summary> private static double calculateStackedNoteNerf(OsuObjectPair lastToCurrent) { return(Math.Max(0, Math.Min(lastToCurrent.RelativeLength, Math.Min(1.2 * lastToCurrent.RelativeLength - 0.185, 1.4 * lastToCurrent.RelativeLength - 0.32) ) )); }
private static double cosineOfAngleBetweenPairs(OsuObjectPair first, OsuObjectPair second) { // it is assumed that first points from object A to B, and second points from B to C // therefore to adhere to the dot product formula for cosine, the first vector has to be reversed double cosine = -first.RelativeVector.DotProduct(second.RelativeVector) / first.RelativeLength / second.RelativeLength; // clamp mostly for sanity. return(Math.Clamp(cosine, -1, 1)); }
/// <summary> /// Correction #4 - Tap Strain /// This buffs current object's aim difficulty rating by tap difficulty when distance is bigger than 0. /// </summary> private static double calculateTapStrainBuff(double tapStrain, OsuObjectPair lastToCurrent, double movementThroughput) { if (!(lastToCurrent.RelativeLength > 0)) { return(1.0); } var tapBonus = SpecialFunctions.Logistic((tapStrain / movementThroughput - 1.34) / 0.1); return(1.0 + tapBonus * 0.15); }
public MovementExtractionParameters( [CanBeNull] OsuHitObject fourthLastObject, [CanBeNull] OsuHitObject secondLastObject, OsuHitObject lastObject, OsuHitObject currentObject, [CanBeNull] OsuHitObject nextObject, double gameplayRate) { FourthLastObject = fourthLastObject; SecondLastObject = secondLastObject is Spinner ? null : secondLastObject; LastObject = lastObject; CurrentObject = currentObject; NextObject = nextObject is Spinner ? null : nextObject; FourthLastToCurrent = OsuObjectPair.Nullable(FourthLastObject, CurrentObject, gameplayRate); SecondLastToLast = OsuObjectPair.Nullable(SecondLastObject, LastObject, gameplayRate); SecondLastToCurrent = OsuObjectPair.Nullable(SecondLastObject, CurrentObject, gameplayRate); SecondLastToNext = OsuObjectPair.Nullable(SecondLastObject, NextObject, gameplayRate); LastToCurrent = new OsuObjectPair(LastObject, CurrentObject, gameplayRate); LastToNext = OsuObjectPair.Nullable(LastObject, NextObject, gameplayRate); CurrentToNext = OsuObjectPair.Nullable(CurrentObject, NextObject, gameplayRate); EffectiveBPM = 30 / (LastToCurrent.TimeDelta + 1e-10); LastObjectTemporallyCenteredBetweenNeighbours = false; CurrentObjectTemporallyCenteredBetweenNeighbours = false; SecondLastToCurrentFlowiness = 0; LastToNextFlowiness = 0; Cheesability = 0; CheeseWindow = 0; }