@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.
Files changed (2) hide show
  1. package/dist/index.js +30 -43
  2. 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, mods);
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.getStackedPosition(this.mode);
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.getStackedPosition(this.mode));
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.getStackedPosition(this.mode);
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
- .getStackedPosition(this.mode)
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 ((_a = object.lazyEndPosition) !== null && _a !== void 0 ? _a : object.object.getStackedPosition(this.mode));
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.getStackedPosition(osuBase.Modes.droid);
620
- const prevStartPosition = prev.object.getStackedPosition(osuBase.Modes.droid);
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].getStackedPosition(osuBase.Modes.droid);
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].getStackedPosition(osuBase.Modes.droid);
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) || 0,
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.66",
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.66"
36
+ "@rian8337/osu-base": "^4.0.0-beta.69"
37
37
  },
38
38
  "publishConfig": {
39
39
  "access": "public"
40
40
  },
41
- "gitHead": "6791c186a09792996f2b58180a7c0fee5d52a8d6"
41
+ "gitHead": "aed764bcd1c55a0a937b8f7439146c00b0457bfb"
42
42
  }