@rian8337/osu-difficulty-calculator 4.0.0-beta.68 → 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 +28 -42
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -79,9 +79,13 @@ class DifficultyCalculator {
|
|
|
79
79
|
];
|
|
80
80
|
}
|
|
81
81
|
calculate(beatmap, mods) {
|
|
82
|
+
const difficultyAdjustmentMods = this.retainDifficultyAdjustmentMods(mods ? Array.from(mods.values()) : []);
|
|
82
83
|
const playableBeatmap = beatmap instanceof osuBase.PlayableBeatmap
|
|
83
84
|
? beatmap
|
|
84
|
-
: this.createPlayableBeatmap(beatmap,
|
|
85
|
+
: this.createPlayableBeatmap(beatmap, new osuBase.ModMap(difficultyAdjustmentMods.map((m) => [
|
|
86
|
+
m.constructor,
|
|
87
|
+
m,
|
|
88
|
+
])));
|
|
85
89
|
const skills = this.createSkills(playableBeatmap);
|
|
86
90
|
const objects = this.createDifficultyHitObjects(playableBeatmap);
|
|
87
91
|
for (const object of objects) {
|
|
@@ -343,9 +347,8 @@ class DifficultyHitObject {
|
|
|
343
347
|
const { scalingFactor } = this;
|
|
344
348
|
const lastCursorPosition = this.lastDifficultyObject !== null
|
|
345
349
|
? this.getEndCursorPosition(this.lastDifficultyObject)
|
|
346
|
-
: this.lastObject.
|
|
347
|
-
this.lazyJumpDistance = this.object
|
|
348
|
-
.getStackedPosition(this.mode)
|
|
350
|
+
: this.lastObject.stackedPosition;
|
|
351
|
+
this.lazyJumpDistance = this.object.stackedPosition
|
|
349
352
|
.scale(scalingFactor)
|
|
350
353
|
.subtract(lastCursorPosition.scale(scalingFactor)).length;
|
|
351
354
|
this.minimumJumpTime = this.strainTime;
|
|
@@ -373,20 +376,15 @@ class DifficultyHitObject {
|
|
|
373
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.
|
|
374
377
|
//
|
|
375
378
|
// Thus, the player is assumed to jump the minimum of these two distances in all cases.
|
|
376
|
-
const tailJumpDistance = this.lastObject.tail
|
|
377
|
-
.getStackedPosition(this.mode)
|
|
378
|
-
.subtract(this.object.getStackedPosition(this.mode))
|
|
379
|
-
.length * scalingFactor;
|
|
379
|
+
const tailJumpDistance = this.lastObject.tail.stackedPosition.subtract(this.object.stackedPosition).length * scalingFactor;
|
|
380
380
|
this.minimumJumpDistance = Math.max(0, Math.min(this.lazyJumpDistance -
|
|
381
381
|
(this.maximumSliderRadius - this.assumedSliderRadius), tailJumpDistance - this.maximumSliderRadius));
|
|
382
382
|
}
|
|
383
383
|
if (this.lastLastDifficultyObject &&
|
|
384
384
|
!(this.lastLastDifficultyObject.object instanceof osuBase.Spinner)) {
|
|
385
385
|
const lastLastCursorPosition = this.getEndCursorPosition(this.lastLastDifficultyObject);
|
|
386
|
-
const v1 = lastLastCursorPosition.subtract(this.lastObject.
|
|
387
|
-
const v2 = this.object
|
|
388
|
-
.getStackedPosition(this.mode)
|
|
389
|
-
.subtract(lastCursorPosition);
|
|
386
|
+
const v1 = lastLastCursorPosition.subtract(this.lastObject.stackedPosition);
|
|
387
|
+
const v2 = this.object.stackedPosition.subtract(lastCursorPosition);
|
|
390
388
|
const dot = v1.dot(v2);
|
|
391
389
|
const det = v1.x * v2.y - v1.y * v2.x;
|
|
392
390
|
this.angle = Math.abs(Math.atan2(det, dot));
|
|
@@ -428,7 +426,7 @@ class DifficultyHitObject {
|
|
|
428
426
|
}
|
|
429
427
|
if (this.mode === osuBase.Modes.droid) {
|
|
430
428
|
// Temporary lazy end position until a real result can be derived.
|
|
431
|
-
this.lazyEndPosition = this.object.
|
|
429
|
+
this.lazyEndPosition = this.object.stackedPosition;
|
|
432
430
|
// Stop here if the slider has too short duration, allowing the player to essentially
|
|
433
431
|
// complete the slider without movement, making travel distance and time irrelevant.
|
|
434
432
|
if (osuBase.Precision.almostEqualsNumber(this.object.startTime, this.object.endTime)) {
|
|
@@ -444,16 +442,12 @@ class DifficultyHitObject {
|
|
|
444
442
|
endTimeMin %= 1;
|
|
445
443
|
}
|
|
446
444
|
// Temporary lazy end position until a real result can be derived.
|
|
447
|
-
this.lazyEndPosition = this.object
|
|
448
|
-
|
|
449
|
-
.add(this.object.path.positionAt(endTimeMin));
|
|
450
|
-
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;
|
|
451
447
|
const scalingFactor = DifficultyHitObject.normalizedRadius / this.object.radius;
|
|
452
448
|
for (let i = 1; i < nestedObjects.length; ++i) {
|
|
453
449
|
const currentMovementObject = nestedObjects[i];
|
|
454
|
-
let currentMovement = currentMovementObject
|
|
455
|
-
.getStackedPosition(this.mode)
|
|
456
|
-
.subtract(currentCursorPosition);
|
|
450
|
+
let currentMovement = currentMovementObject.stackedPosition.subtract(currentCursorPosition);
|
|
457
451
|
let currentMovementLength = scalingFactor * currentMovement.length;
|
|
458
452
|
// The amount of movement required so that the cursor position needs to be updated.
|
|
459
453
|
let requiredMovement = this.assumedSliderRadius;
|
|
@@ -489,7 +483,7 @@ class DifficultyHitObject {
|
|
|
489
483
|
}
|
|
490
484
|
getEndCursorPosition(object) {
|
|
491
485
|
var _a;
|
|
492
|
-
return (
|
|
486
|
+
return (_a = object.lazyEndPosition) !== null && _a !== void 0 ? _a : object.object.stackedPosition;
|
|
493
487
|
}
|
|
494
488
|
}
|
|
495
489
|
/**
|
|
@@ -617,8 +611,8 @@ class DroidDifficultyHitObject extends DifficultyHitObject {
|
|
|
617
611
|
return true;
|
|
618
612
|
}
|
|
619
613
|
const distanceThreshold = 2 * this.object.radius;
|
|
620
|
-
const startPosition = this.object.
|
|
621
|
-
const prevStartPosition = prev.object.
|
|
614
|
+
const startPosition = this.object.stackedPosition;
|
|
615
|
+
const prevStartPosition = prev.object.stackedPosition;
|
|
622
616
|
// We need to consider two cases:
|
|
623
617
|
//
|
|
624
618
|
// Case 1: Current object is a circle, or previous object is a circle.
|
|
@@ -635,7 +629,7 @@ class DroidDifficultyHitObject extends DifficultyHitObject {
|
|
|
635
629
|
}
|
|
636
630
|
// Check if all nested hitobjects can be hit together.
|
|
637
631
|
for (let i = 1; i < this.object.nestedHitObjects.length; ++i) {
|
|
638
|
-
const position = this.object.nestedHitObjects[i].
|
|
632
|
+
const position = this.object.nestedHitObjects[i].stackedPosition;
|
|
639
633
|
const prevPosition = prevStartPosition.add(prev.object.curvePositionAt(i / (this.object.nestedHitObjects.length - 1)));
|
|
640
634
|
if (position.getDistance(prevPosition) > distanceThreshold) {
|
|
641
635
|
return false;
|
|
@@ -643,7 +637,7 @@ class DroidDifficultyHitObject extends DifficultyHitObject {
|
|
|
643
637
|
}
|
|
644
638
|
// Do the same for the previous slider as well.
|
|
645
639
|
for (let i = 1; i < prev.object.nestedHitObjects.length; ++i) {
|
|
646
|
-
const prevPosition = prev.object.nestedHitObjects[i].
|
|
640
|
+
const prevPosition = prev.object.nestedHitObjects[i].stackedPosition;
|
|
647
641
|
const position = startPosition.add(this.object.curvePositionAt(i / (prev.object.nestedHitObjects.length - 1)));
|
|
648
642
|
if (prevPosition.getDistance(position) > distanceThreshold) {
|
|
649
643
|
return false;
|
|
@@ -681,16 +675,12 @@ class DroidDifficultyHitObject extends DifficultyHitObject {
|
|
|
681
675
|
prevVisibleObjects.push(prev.object);
|
|
682
676
|
}
|
|
683
677
|
for (const hitObject of prevVisibleObjects) {
|
|
684
|
-
const distance = this.object
|
|
685
|
-
.getStackedPosition(this.mode)
|
|
686
|
-
.getDistance(hitObject.getStackedEndPosition(this.mode));
|
|
678
|
+
const distance = this.object.stackedPosition.getDistance(hitObject.stackedEndPosition);
|
|
687
679
|
const deltaTime = this.startTime - hitObject.endTime / clockRate;
|
|
688
680
|
this.applyToOverlappingFactor(distance, deltaTime);
|
|
689
681
|
}
|
|
690
682
|
for (const hitObject of nextVisibleObjects) {
|
|
691
|
-
const distance = hitObject
|
|
692
|
-
.getStackedPosition(this.mode)
|
|
693
|
-
.getDistance(this.object.getStackedEndPosition(this.mode));
|
|
683
|
+
const distance = hitObject.stackedPosition.getDistance(this.object.stackedEndPosition);
|
|
694
684
|
const deltaTime = hitObject.startTime / clockRate - this.endTime;
|
|
695
685
|
if (deltaTime >= 0) {
|
|
696
686
|
this.noteDensity += 1 - deltaTime / this.timePreempt;
|
|
@@ -1158,9 +1148,7 @@ class DroidFlashlightEvaluator {
|
|
|
1158
1148
|
if (!(currentObject.object instanceof osuBase.Spinner) &&
|
|
1159
1149
|
// Exclude overlapping objects that can be tapped at once.
|
|
1160
1150
|
!currentObject.isOverlapping(false)) {
|
|
1161
|
-
const jumpDistance = current.object
|
|
1162
|
-
.getStackedPosition(osuBase.Modes.droid)
|
|
1163
|
-
.subtract(currentObject.object.getStackedEndPosition(osuBase.Modes.droid)).length;
|
|
1151
|
+
const jumpDistance = current.object.stackedPosition.subtract(currentObject.object.stackedEndPosition).length;
|
|
1164
1152
|
// We want to nerf objects that can be easily seen within the Flashlight circle radius.
|
|
1165
1153
|
if (i === 0) {
|
|
1166
1154
|
smallDistNerf = Math.min(1, jumpDistance / 75);
|
|
@@ -2145,10 +2133,7 @@ class PerformanceCalculator {
|
|
|
2145
2133
|
* @param options Options for performance calculation.
|
|
2146
2134
|
*/
|
|
2147
2135
|
handleOptions(options) {
|
|
2148
|
-
var _a;
|
|
2149
|
-
const maxCombo = this.difficultyAttributes.maxCombo;
|
|
2150
|
-
const miss = this.computedAccuracy.nmiss;
|
|
2151
|
-
const combo = (_a = options === null || options === void 0 ? void 0 : options.combo) !== null && _a !== void 0 ? _a : maxCombo - miss;
|
|
2136
|
+
var _a, _b;
|
|
2152
2137
|
if ((options === null || options === void 0 ? void 0 : options.accPercent) instanceof osuBase.Accuracy) {
|
|
2153
2138
|
// Copy into new instance to not modify the original
|
|
2154
2139
|
this.computedAccuracy = new osuBase.Accuracy(options.accPercent);
|
|
@@ -2166,9 +2151,12 @@ class PerformanceCalculator {
|
|
|
2166
2151
|
this.computedAccuracy = new osuBase.Accuracy({
|
|
2167
2152
|
percent: options === null || options === void 0 ? void 0 : options.accPercent,
|
|
2168
2153
|
nobjects: this.totalHits,
|
|
2169
|
-
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,
|
|
2170
2155
|
});
|
|
2171
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;
|
|
2172
2160
|
this.effectiveMissCount = this.calculateEffectiveMissCount(combo, maxCombo);
|
|
2173
2161
|
if (this.mods.has(osuBase.ModNoFail)) {
|
|
2174
2162
|
this.finalMultiplier *= Math.max(0.9, 1 - 0.02 * this.effectiveMissCount);
|
|
@@ -3100,9 +3088,7 @@ class OsuFlashlightEvaluator {
|
|
|
3100
3088
|
const currentObject = current.previous(i);
|
|
3101
3089
|
cumulativeStrainTime += last.strainTime;
|
|
3102
3090
|
if (!(currentObject.object instanceof osuBase.Spinner)) {
|
|
3103
|
-
const jumpDistance = current.object
|
|
3104
|
-
.getStackedPosition(osuBase.Modes.osu)
|
|
3105
|
-
.subtract(currentObject.object.getStackedEndPosition(osuBase.Modes.osu)).length;
|
|
3091
|
+
const jumpDistance = current.object.stackedPosition.subtract(currentObject.object.stackedEndPosition).length;
|
|
3106
3092
|
// We want to nerf objects that can be easily seen within the Flashlight circle radius.
|
|
3107
3093
|
if (i === 0) {
|
|
3108
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
|
}
|