@rian8337/osu-difficulty-calculator 4.0.0-beta.66 → 4.0.0-beta.69
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +30 -43
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -75,12 +75,17 @@ class DifficultyCalculator {
|
|
|
75
75
|
osuBase.ModRelax,
|
|
76
76
|
osuBase.ModAutopilot,
|
|
77
77
|
osuBase.ModMirror,
|
|
78
|
+
osuBase.ModRandom,
|
|
78
79
|
];
|
|
79
80
|
}
|
|
80
81
|
calculate(beatmap, mods) {
|
|
82
|
+
const difficultyAdjustmentMods = this.retainDifficultyAdjustmentMods(mods ? Array.from(mods.values()) : []);
|
|
81
83
|
const playableBeatmap = beatmap instanceof osuBase.PlayableBeatmap
|
|
82
84
|
? beatmap
|
|
83
|
-
: this.createPlayableBeatmap(beatmap,
|
|
85
|
+
: this.createPlayableBeatmap(beatmap, new osuBase.ModMap(difficultyAdjustmentMods.map((m) => [
|
|
86
|
+
m.constructor,
|
|
87
|
+
m,
|
|
88
|
+
])));
|
|
84
89
|
const skills = this.createSkills(playableBeatmap);
|
|
85
90
|
const objects = this.createDifficultyHitObjects(playableBeatmap);
|
|
86
91
|
for (const object of objects) {
|
|
@@ -342,9 +347,8 @@ class DifficultyHitObject {
|
|
|
342
347
|
const { scalingFactor } = this;
|
|
343
348
|
const lastCursorPosition = this.lastDifficultyObject !== null
|
|
344
349
|
? this.getEndCursorPosition(this.lastDifficultyObject)
|
|
345
|
-
: this.lastObject.
|
|
346
|
-
this.lazyJumpDistance = this.object
|
|
347
|
-
.getStackedPosition(this.mode)
|
|
350
|
+
: this.lastObject.stackedPosition;
|
|
351
|
+
this.lazyJumpDistance = this.object.stackedPosition
|
|
348
352
|
.scale(scalingFactor)
|
|
349
353
|
.subtract(lastCursorPosition.scale(scalingFactor)).length;
|
|
350
354
|
this.minimumJumpTime = this.strainTime;
|
|
@@ -372,20 +376,15 @@ class DifficultyHitObject {
|
|
|
372
376
|
// In this case the most natural jump path is better approximated by a new distance called "tailJumpDistance" - the distance between the slider's tail and the next hitobject.
|
|
373
377
|
//
|
|
374
378
|
// Thus, the player is assumed to jump the minimum of these two distances in all cases.
|
|
375
|
-
const tailJumpDistance = this.lastObject.tail
|
|
376
|
-
.getStackedPosition(this.mode)
|
|
377
|
-
.subtract(this.object.getStackedPosition(this.mode))
|
|
378
|
-
.length * scalingFactor;
|
|
379
|
+
const tailJumpDistance = this.lastObject.tail.stackedPosition.subtract(this.object.stackedPosition).length * scalingFactor;
|
|
379
380
|
this.minimumJumpDistance = Math.max(0, Math.min(this.lazyJumpDistance -
|
|
380
381
|
(this.maximumSliderRadius - this.assumedSliderRadius), tailJumpDistance - this.maximumSliderRadius));
|
|
381
382
|
}
|
|
382
383
|
if (this.lastLastDifficultyObject &&
|
|
383
384
|
!(this.lastLastDifficultyObject.object instanceof osuBase.Spinner)) {
|
|
384
385
|
const lastLastCursorPosition = this.getEndCursorPosition(this.lastLastDifficultyObject);
|
|
385
|
-
const v1 = lastLastCursorPosition.subtract(this.lastObject.
|
|
386
|
-
const v2 = this.object
|
|
387
|
-
.getStackedPosition(this.mode)
|
|
388
|
-
.subtract(lastCursorPosition);
|
|
386
|
+
const v1 = lastLastCursorPosition.subtract(this.lastObject.stackedPosition);
|
|
387
|
+
const v2 = this.object.stackedPosition.subtract(lastCursorPosition);
|
|
389
388
|
const dot = v1.dot(v2);
|
|
390
389
|
const det = v1.x * v2.y - v1.y * v2.x;
|
|
391
390
|
this.angle = Math.abs(Math.atan2(det, dot));
|
|
@@ -427,7 +426,7 @@ class DifficultyHitObject {
|
|
|
427
426
|
}
|
|
428
427
|
if (this.mode === osuBase.Modes.droid) {
|
|
429
428
|
// Temporary lazy end position until a real result can be derived.
|
|
430
|
-
this.lazyEndPosition = this.object.
|
|
429
|
+
this.lazyEndPosition = this.object.stackedPosition;
|
|
431
430
|
// Stop here if the slider has too short duration, allowing the player to essentially
|
|
432
431
|
// complete the slider without movement, making travel distance and time irrelevant.
|
|
433
432
|
if (osuBase.Precision.almostEqualsNumber(this.object.startTime, this.object.endTime)) {
|
|
@@ -443,16 +442,12 @@ class DifficultyHitObject {
|
|
|
443
442
|
endTimeMin %= 1;
|
|
444
443
|
}
|
|
445
444
|
// Temporary lazy end position until a real result can be derived.
|
|
446
|
-
this.lazyEndPosition = this.object
|
|
447
|
-
|
|
448
|
-
.add(this.object.path.positionAt(endTimeMin));
|
|
449
|
-
let currentCursorPosition = this.object.getStackedPosition(this.mode);
|
|
445
|
+
this.lazyEndPosition = this.object.stackedPosition.add(this.object.path.positionAt(endTimeMin));
|
|
446
|
+
let currentCursorPosition = this.object.stackedPosition;
|
|
450
447
|
const scalingFactor = DifficultyHitObject.normalizedRadius / this.object.radius;
|
|
451
448
|
for (let i = 1; i < nestedObjects.length; ++i) {
|
|
452
449
|
const currentMovementObject = nestedObjects[i];
|
|
453
|
-
let currentMovement = currentMovementObject
|
|
454
|
-
.getStackedPosition(this.mode)
|
|
455
|
-
.subtract(currentCursorPosition);
|
|
450
|
+
let currentMovement = currentMovementObject.stackedPosition.subtract(currentCursorPosition);
|
|
456
451
|
let currentMovementLength = scalingFactor * currentMovement.length;
|
|
457
452
|
// The amount of movement required so that the cursor position needs to be updated.
|
|
458
453
|
let requiredMovement = this.assumedSliderRadius;
|
|
@@ -488,7 +483,7 @@ class DifficultyHitObject {
|
|
|
488
483
|
}
|
|
489
484
|
getEndCursorPosition(object) {
|
|
490
485
|
var _a;
|
|
491
|
-
return (
|
|
486
|
+
return (_a = object.lazyEndPosition) !== null && _a !== void 0 ? _a : object.object.stackedPosition;
|
|
492
487
|
}
|
|
493
488
|
}
|
|
494
489
|
/**
|
|
@@ -616,8 +611,8 @@ class DroidDifficultyHitObject extends DifficultyHitObject {
|
|
|
616
611
|
return true;
|
|
617
612
|
}
|
|
618
613
|
const distanceThreshold = 2 * this.object.radius;
|
|
619
|
-
const startPosition = this.object.
|
|
620
|
-
const prevStartPosition = prev.object.
|
|
614
|
+
const startPosition = this.object.stackedPosition;
|
|
615
|
+
const prevStartPosition = prev.object.stackedPosition;
|
|
621
616
|
// We need to consider two cases:
|
|
622
617
|
//
|
|
623
618
|
// Case 1: Current object is a circle, or previous object is a circle.
|
|
@@ -634,7 +629,7 @@ class DroidDifficultyHitObject extends DifficultyHitObject {
|
|
|
634
629
|
}
|
|
635
630
|
// Check if all nested hitobjects can be hit together.
|
|
636
631
|
for (let i = 1; i < this.object.nestedHitObjects.length; ++i) {
|
|
637
|
-
const position = this.object.nestedHitObjects[i].
|
|
632
|
+
const position = this.object.nestedHitObjects[i].stackedPosition;
|
|
638
633
|
const prevPosition = prevStartPosition.add(prev.object.curvePositionAt(i / (this.object.nestedHitObjects.length - 1)));
|
|
639
634
|
if (position.getDistance(prevPosition) > distanceThreshold) {
|
|
640
635
|
return false;
|
|
@@ -642,7 +637,7 @@ class DroidDifficultyHitObject extends DifficultyHitObject {
|
|
|
642
637
|
}
|
|
643
638
|
// Do the same for the previous slider as well.
|
|
644
639
|
for (let i = 1; i < prev.object.nestedHitObjects.length; ++i) {
|
|
645
|
-
const prevPosition = prev.object.nestedHitObjects[i].
|
|
640
|
+
const prevPosition = prev.object.nestedHitObjects[i].stackedPosition;
|
|
646
641
|
const position = startPosition.add(this.object.curvePositionAt(i / (prev.object.nestedHitObjects.length - 1)));
|
|
647
642
|
if (prevPosition.getDistance(position) > distanceThreshold) {
|
|
648
643
|
return false;
|
|
@@ -680,16 +675,12 @@ class DroidDifficultyHitObject extends DifficultyHitObject {
|
|
|
680
675
|
prevVisibleObjects.push(prev.object);
|
|
681
676
|
}
|
|
682
677
|
for (const hitObject of prevVisibleObjects) {
|
|
683
|
-
const distance = this.object
|
|
684
|
-
.getStackedPosition(this.mode)
|
|
685
|
-
.getDistance(hitObject.getStackedEndPosition(this.mode));
|
|
678
|
+
const distance = this.object.stackedPosition.getDistance(hitObject.stackedEndPosition);
|
|
686
679
|
const deltaTime = this.startTime - hitObject.endTime / clockRate;
|
|
687
680
|
this.applyToOverlappingFactor(distance, deltaTime);
|
|
688
681
|
}
|
|
689
682
|
for (const hitObject of nextVisibleObjects) {
|
|
690
|
-
const distance = hitObject
|
|
691
|
-
.getStackedPosition(this.mode)
|
|
692
|
-
.getDistance(this.object.getStackedEndPosition(this.mode));
|
|
683
|
+
const distance = hitObject.stackedPosition.getDistance(this.object.stackedEndPosition);
|
|
693
684
|
const deltaTime = hitObject.startTime / clockRate - this.endTime;
|
|
694
685
|
if (deltaTime >= 0) {
|
|
695
686
|
this.noteDensity += 1 - deltaTime / this.timePreempt;
|
|
@@ -1157,9 +1148,7 @@ class DroidFlashlightEvaluator {
|
|
|
1157
1148
|
if (!(currentObject.object instanceof osuBase.Spinner) &&
|
|
1158
1149
|
// Exclude overlapping objects that can be tapped at once.
|
|
1159
1150
|
!currentObject.isOverlapping(false)) {
|
|
1160
|
-
const jumpDistance = current.object
|
|
1161
|
-
.getStackedPosition(osuBase.Modes.droid)
|
|
1162
|
-
.subtract(currentObject.object.getStackedEndPosition(osuBase.Modes.droid)).length;
|
|
1151
|
+
const jumpDistance = current.object.stackedPosition.subtract(currentObject.object.stackedEndPosition).length;
|
|
1163
1152
|
// We want to nerf objects that can be easily seen within the Flashlight circle radius.
|
|
1164
1153
|
if (i === 0) {
|
|
1165
1154
|
smallDistNerf = Math.min(1, jumpDistance / 75);
|
|
@@ -1807,7 +1796,7 @@ class DroidDifficultyCalculator extends DifficultyCalculator {
|
|
|
1807
1796
|
constructor() {
|
|
1808
1797
|
super();
|
|
1809
1798
|
this.difficultyMultiplier = 0.18;
|
|
1810
|
-
this.difficultyAdjustmentMods.push(osuBase.ModPrecise, osuBase.ModScoreV2, osuBase.ModTraceable);
|
|
1799
|
+
this.difficultyAdjustmentMods.push(osuBase.ModPrecise, osuBase.ModScoreV2, osuBase.ModTraceable, osuBase.ModReplayV6);
|
|
1811
1800
|
}
|
|
1812
1801
|
retainDifficultyAdjustmentMods(mods) {
|
|
1813
1802
|
return mods.filter((mod) => mod.isApplicableToDroid() &&
|
|
@@ -2144,10 +2133,7 @@ class PerformanceCalculator {
|
|
|
2144
2133
|
* @param options Options for performance calculation.
|
|
2145
2134
|
*/
|
|
2146
2135
|
handleOptions(options) {
|
|
2147
|
-
var _a;
|
|
2148
|
-
const maxCombo = this.difficultyAttributes.maxCombo;
|
|
2149
|
-
const miss = this.computedAccuracy.nmiss;
|
|
2150
|
-
const combo = (_a = options === null || options === void 0 ? void 0 : options.combo) !== null && _a !== void 0 ? _a : maxCombo - miss;
|
|
2136
|
+
var _a, _b;
|
|
2151
2137
|
if ((options === null || options === void 0 ? void 0 : options.accPercent) instanceof osuBase.Accuracy) {
|
|
2152
2138
|
// Copy into new instance to not modify the original
|
|
2153
2139
|
this.computedAccuracy = new osuBase.Accuracy(options.accPercent);
|
|
@@ -2165,9 +2151,12 @@ class PerformanceCalculator {
|
|
|
2165
2151
|
this.computedAccuracy = new osuBase.Accuracy({
|
|
2166
2152
|
percent: options === null || options === void 0 ? void 0 : options.accPercent,
|
|
2167
2153
|
nobjects: this.totalHits,
|
|
2168
|
-
nmiss: (options === null || options === void 0 ? void 0 : options.miss)
|
|
2154
|
+
nmiss: (_a = options === null || options === void 0 ? void 0 : options.miss) !== null && _a !== void 0 ? _a : 0,
|
|
2169
2155
|
});
|
|
2170
2156
|
}
|
|
2157
|
+
const maxCombo = this.difficultyAttributes.maxCombo;
|
|
2158
|
+
const miss = this.computedAccuracy.nmiss;
|
|
2159
|
+
const combo = (_b = options === null || options === void 0 ? void 0 : options.combo) !== null && _b !== void 0 ? _b : maxCombo - miss;
|
|
2171
2160
|
this.effectiveMissCount = this.calculateEffectiveMissCount(combo, maxCombo);
|
|
2172
2161
|
if (this.mods.has(osuBase.ModNoFail)) {
|
|
2173
2162
|
this.finalMultiplier *= Math.max(0.9, 1 - 0.02 * this.effectiveMissCount);
|
|
@@ -3099,9 +3088,7 @@ class OsuFlashlightEvaluator {
|
|
|
3099
3088
|
const currentObject = current.previous(i);
|
|
3100
3089
|
cumulativeStrainTime += last.strainTime;
|
|
3101
3090
|
if (!(currentObject.object instanceof osuBase.Spinner)) {
|
|
3102
|
-
const jumpDistance = current.object
|
|
3103
|
-
.getStackedPosition(osuBase.Modes.osu)
|
|
3104
|
-
.subtract(currentObject.object.getStackedEndPosition(osuBase.Modes.osu)).length;
|
|
3091
|
+
const jumpDistance = current.object.stackedPosition.subtract(currentObject.object.stackedEndPosition).length;
|
|
3105
3092
|
// We want to nerf objects that can be easily seen within the Flashlight circle radius.
|
|
3106
3093
|
if (i === 0) {
|
|
3107
3094
|
smallDistNerf = Math.min(1, jumpDistance / 75);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rian8337/osu-difficulty-calculator",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.69",
|
|
4
4
|
"description": "A module for calculating osu!standard beatmap difficulty and performance value with respect to the current difficulty and performance algorithm.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"osu",
|
|
@@ -33,10 +33,10 @@
|
|
|
33
33
|
"url": "https://github.com/Rian8337/osu-droid-module/issues"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@rian8337/osu-base": "^4.0.0-beta.
|
|
36
|
+
"@rian8337/osu-base": "^4.0.0-beta.69"
|
|
37
37
|
},
|
|
38
38
|
"publishConfig": {
|
|
39
39
|
"access": "public"
|
|
40
40
|
},
|
|
41
|
-
"gitHead": "
|
|
41
|
+
"gitHead": "aed764bcd1c55a0a937b8f7439146c00b0457bfb"
|
|
42
42
|
}
|