1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-21 15:27:24 +08:00

drastically improved algorithm

This commit is contained in:
Givikap120 2024-06-13 14:09:20 +03:00
parent 16c3137920
commit f286693273

View File

@ -58,25 +58,42 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Skills
catchCurrent.NormalizedPosition + (normalized_hitobject_radius - absolute_player_positioning_error) catchCurrent.NormalizedPosition + (normalized_hitobject_radius - absolute_player_positioning_error)
); );
float distanceMoved = playerPosition - lastPlayerPosition.Value; float groupness = getGroupness(catchCurrent);
if (catchCurrent.NormalizedPositionLast0.IsNotNull() && catchCurrent.NormalizedPositionLast1.IsNotNull()) // If 3 objects are in group - player will try to cheese them
if (groupness > 0)
{ {
float lenience = normalized_hitobject_radius * 2; // Coordinates of the group
float antiCheese = 1; float leftCoords = Math.Min(Math.Min(catchCurrent.NormalizedPosition, catchCurrent.NormalizedPositionLast0), (float)catchCurrent.NormalizedPositionLast1!);
float rightCoords = Math.Max(Math.Max(catchCurrent.NormalizedPosition, catchCurrent.NormalizedPositionLast0), (float)catchCurrent.NormalizedPositionLast1!);
float centerCoords = (leftCoords + rightCoords) / 2;
float deltaCurrLast0 = Math.Clamp(lenience - Math.Abs(catchCurrent.NormalizedPosition - catchCurrent.NormalizedPositionLast0), 0, absolute_player_positioning_error); // Distance from player to the boundaries of group
antiCheese *= deltaCurrLast0 / absolute_player_positioning_error; float leftDelta = Math.Abs(lastPlayerPosition.Value - leftCoords);
float rightDelta = Math.Abs(lastPlayerPosition.Value - rightCoords);
float deltaCurrLast1 = Math.Clamp(lenience - Math.Abs((float)(catchCurrent.NormalizedPosition - catchCurrent.NormalizedPositionLast1)), 0, absolute_player_positioning_error); // Normalized deltas:
antiCheese *= deltaCurrLast1 / absolute_player_positioning_error; leftDelta = normalizeDelta(leftDelta, normalized_hitobject_radius);
rightDelta = normalizeDelta(rightDelta, normalized_hitobject_radius);
float deltaLast0Last1 = Math.Clamp(lenience - Math.Abs((float)(catchCurrent.NormalizedPositionLast0 - catchCurrent.NormalizedPositionLast1)), 0, absolute_player_positioning_error); // Determines how close player is to position where they can hit it
antiCheese *= deltaLast0Last1 / absolute_player_positioning_error; float closetness = 1;
closetness *= 1 - leftDelta;
closetness *= 1 - rightDelta;
distanceMoved *= 1 - antiCheese; // Player will be more likely to move if it's far away from center of group
float resultPosition = float.Lerp(centerCoords, lastPlayerPosition.Value, closetness);
// Assume that player will take the easier route
if (Math.Abs(playerPosition - lastPlayerPosition.Value) < Math.Abs(resultPosition - lastPlayerPosition.Value))
resultPosition = playerPosition;
// Player will be more likely to move to group center if objects are close enough
playerPosition = float.Lerp(playerPosition, resultPosition, groupness);
} }
float distanceMoved = playerPosition - lastPlayerPosition.Value;
double weightedStrainTime = catchCurrent.StrainTime + 13 + (3 / catcherSpeedMultiplier); double weightedStrainTime = catchCurrent.StrainTime + 13 + (3 / catcherSpeedMultiplier);
double distanceAddition = (Math.Pow(Math.Abs(distanceMoved), 1.3) / 510); double distanceAddition = (Math.Pow(Math.Abs(distanceMoved), 1.3) / 510);
@ -119,5 +136,39 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Skills
return distanceAddition / weightedStrainTime; return distanceAddition / weightedStrainTime;
} }
private float getGroupness(CatchDifficultyHitObject obj)
{
if (obj.NormalizedPositionLast1.IsNull())
return 0;
// Raw deltas between objects
float delta01 = Math.Abs(obj.NormalizedPosition - obj.NormalizedPositionLast0);
float delta02 = Math.Abs((float)(obj.NormalizedPosition - obj.NormalizedPositionLast1));
float delta12 = Math.Abs((float)(obj.NormalizedPositionLast0 - obj.NormalizedPositionLast1));
// Normalized deltas:
// 0 - very close, inbetween - moderately close, 1 - too far
delta01 = normalizeDelta(delta01, 2 * normalized_hitobject_radius);
delta02 = normalizeDelta(delta02, 2 * normalized_hitobject_radius);
delta12 = normalizeDelta(delta12, 2 * normalized_hitobject_radius);
// If at least one is far apart - groupness is 0
float groupness = 1;
groupness *= 1 - delta01;
groupness *= 1 - delta02;
groupness *= 1 - delta12;
return groupness;
}
/// <summary>
/// Normalizing delta:
/// 0 - very close, inbetween - moderately close, 1 - too far
/// </summary>
/// <param name="delta"></param>
/// <param name="shift">Deltas lower than shift will be 0</param>
/// <returns></returns>
private float normalizeDelta(float delta, float shift) => Math.Clamp(delta - shift + absolute_player_positioning_error, 0, absolute_player_positioning_error) / absolute_player_positioning_error;
} }
} }