@rian8337/osu-base 2.0.0-alpha.7 → 2.0.1
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/README.md +261 -18
- package/dist/index.js +231 -82
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/typings/index.d.ts +157 -39
package/dist/index.js
CHANGED
|
@@ -815,9 +815,7 @@ class Slider extends HitObject {
|
|
|
815
815
|
startTime: finalSpanEndTime,
|
|
816
816
|
});
|
|
817
817
|
this.nestedHitObjects.push(this.tail);
|
|
818
|
-
this.nestedHitObjects.sort((a, b) =>
|
|
819
|
-
return a.startTime - b.startTime;
|
|
820
|
-
});
|
|
818
|
+
this.nestedHitObjects.sort((a, b) => a.startTime - b.startTime);
|
|
821
819
|
}
|
|
822
820
|
toString() {
|
|
823
821
|
return `Position: [${this.position.x}, ${this.position.y}], distance: ${this.path.expectedDistance}, repetitions: ${this.repetitions}, slider ticks: ${this.nestedHitObjects.filter((v) => v instanceof SliderTick).length}`;
|
|
@@ -1196,6 +1194,8 @@ class ControlPointManager {
|
|
|
1196
1194
|
/**
|
|
1197
1195
|
* Removes a control point.
|
|
1198
1196
|
*
|
|
1197
|
+
* This method will remove the earliest control point in the array that is equal to the given control point.
|
|
1198
|
+
*
|
|
1199
1199
|
* @param controlPoint The control point to remove.
|
|
1200
1200
|
* @returns Whether the control point was removed.
|
|
1201
1201
|
*/
|
|
@@ -1872,6 +1872,51 @@ class HitWindow {
|
|
|
1872
1872
|
* Represents the hit window of osu!droid.
|
|
1873
1873
|
*/
|
|
1874
1874
|
class DroidHitWindow extends HitWindow {
|
|
1875
|
+
/**
|
|
1876
|
+
* Calculates the overall difficulty value of a great hit window.
|
|
1877
|
+
*
|
|
1878
|
+
* @param value The value of the hit window, in milliseconds.
|
|
1879
|
+
* @param isPrecise Whether to calculate for Precise mod.
|
|
1880
|
+
* @returns The overall difficulty value.
|
|
1881
|
+
*/
|
|
1882
|
+
static hitWindow300ToOD(value, isPrecise) {
|
|
1883
|
+
if (isPrecise) {
|
|
1884
|
+
return 5 - (value - 55) / 6;
|
|
1885
|
+
}
|
|
1886
|
+
else {
|
|
1887
|
+
return 5 - (value - 75) / 5;
|
|
1888
|
+
}
|
|
1889
|
+
}
|
|
1890
|
+
/**
|
|
1891
|
+
* Calculates the overall difficulty value of a good hit window.
|
|
1892
|
+
*
|
|
1893
|
+
* @param value The value of the hit window, in milliseconds.
|
|
1894
|
+
* @param isPrecise Whether to calculate for Precise mod.
|
|
1895
|
+
* @returns The overall difficulty value.
|
|
1896
|
+
*/
|
|
1897
|
+
static hitWindow100ToOD(value, isPrecise) {
|
|
1898
|
+
if (isPrecise) {
|
|
1899
|
+
return 5 - (value - 120) / 8;
|
|
1900
|
+
}
|
|
1901
|
+
else {
|
|
1902
|
+
return 5 - (value - 150) / 10;
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
/**
|
|
1906
|
+
* Calculates the overall difficulty value of a meh hit window.
|
|
1907
|
+
*
|
|
1908
|
+
* @param value The value of the hit window, in milliseconds.
|
|
1909
|
+
* @param isPrecise Whether to calculate for Precise mod.
|
|
1910
|
+
* @returns The overall difficulty value.
|
|
1911
|
+
*/
|
|
1912
|
+
static hitWindow50ToOD(value, isPrecise) {
|
|
1913
|
+
if (isPrecise) {
|
|
1914
|
+
return 5 - (value - 180) / 10;
|
|
1915
|
+
}
|
|
1916
|
+
else {
|
|
1917
|
+
return 5 - (value - 250) / 10;
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1875
1920
|
hitWindowFor300(isPrecise) {
|
|
1876
1921
|
if (isPrecise) {
|
|
1877
1922
|
return 55 + 6 * (5 - this.overallDifficulty);
|
|
@@ -1901,6 +1946,33 @@ class DroidHitWindow extends HitWindow {
|
|
|
1901
1946
|
* Represents the hit window of osu!standard.
|
|
1902
1947
|
*/
|
|
1903
1948
|
class OsuHitWindow extends HitWindow {
|
|
1949
|
+
/**
|
|
1950
|
+
* Calculates the overall difficulty value of a great hit window.
|
|
1951
|
+
*
|
|
1952
|
+
* @param value The value of the hit window, in milliseconds.
|
|
1953
|
+
* @returns The overall difficulty value.
|
|
1954
|
+
*/
|
|
1955
|
+
static hitWindow300ToOD(value) {
|
|
1956
|
+
return (80 - value) / 6;
|
|
1957
|
+
}
|
|
1958
|
+
/**
|
|
1959
|
+
* Calculates the overall difficulty value of a good hit window.
|
|
1960
|
+
*
|
|
1961
|
+
* @param value The value of the hit window, in milliseconds.
|
|
1962
|
+
* @returns The overall difficulty value.
|
|
1963
|
+
*/
|
|
1964
|
+
static hitWindow100ToOD(value) {
|
|
1965
|
+
return (140 - value) / 8;
|
|
1966
|
+
}
|
|
1967
|
+
/**
|
|
1968
|
+
* Calculates the overall difficulty value of a meh hit window.
|
|
1969
|
+
*
|
|
1970
|
+
* @param value The value of the hit window, in milliseconds.
|
|
1971
|
+
* @returns The overall difficulty value.
|
|
1972
|
+
*/
|
|
1973
|
+
static hitWindow50ToOD(value) {
|
|
1974
|
+
return (200 - value) / 10;
|
|
1975
|
+
}
|
|
1904
1976
|
hitWindowFor300() {
|
|
1905
1977
|
return 80 - 6 * this.overallDifficulty;
|
|
1906
1978
|
}
|
|
@@ -2076,6 +2148,8 @@ class ModFlashlight extends Mod {
|
|
|
2076
2148
|
* Represents the Hidden mod.
|
|
2077
2149
|
*/
|
|
2078
2150
|
class ModHidden extends Mod {
|
|
2151
|
+
static fadeInDurationMultiplier = 0.4;
|
|
2152
|
+
static fadeOutDurationMultiplier = 0.3;
|
|
2079
2153
|
scoreMultiplier = 1.06;
|
|
2080
2154
|
acronym = "HD";
|
|
2081
2155
|
name = "Hidden";
|
|
@@ -2234,9 +2308,7 @@ class ModUtil {
|
|
|
2234
2308
|
* Mods that change the way the map looks.
|
|
2235
2309
|
*/
|
|
2236
2310
|
static mapChangingMods = [
|
|
2237
|
-
|
|
2238
|
-
new ModNightCore(),
|
|
2239
|
-
new ModHalfTime(),
|
|
2311
|
+
...this.speedChangingMods,
|
|
2240
2312
|
new ModEasy(),
|
|
2241
2313
|
new ModHardRock(),
|
|
2242
2314
|
new ModSmallCircle(),
|
|
@@ -2245,24 +2317,27 @@ class ModUtil {
|
|
|
2245
2317
|
* Gets a list of mods from a droid mod string, such as "hd".
|
|
2246
2318
|
*
|
|
2247
2319
|
* @param str The string.
|
|
2320
|
+
* @param options Options for parsing behavior.
|
|
2248
2321
|
*/
|
|
2249
|
-
static droidStringToMods(str) {
|
|
2250
|
-
return this.
|
|
2322
|
+
static droidStringToMods(str, options) {
|
|
2323
|
+
return this.processParsingOptions(this.allMods.filter((m) => m.droidString && str.toLowerCase().includes(m.droidString)), options);
|
|
2251
2324
|
}
|
|
2252
2325
|
/**
|
|
2253
2326
|
* Gets a list of mods from a PC modbits.
|
|
2254
2327
|
*
|
|
2255
2328
|
* @param modbits The modbits.
|
|
2329
|
+
* @param options Options for parsing behavior.
|
|
2256
2330
|
*/
|
|
2257
|
-
static pcModbitsToMods(modbits) {
|
|
2258
|
-
return this.
|
|
2331
|
+
static pcModbitsToMods(modbits, options) {
|
|
2332
|
+
return this.processParsingOptions(this.allMods.filter((m) => m.bitwise & modbits), options);
|
|
2259
2333
|
}
|
|
2260
2334
|
/**
|
|
2261
2335
|
* Gets a list of mods from a PC mod string, such as "HDHR".
|
|
2262
2336
|
*
|
|
2263
2337
|
* @param str The string.
|
|
2338
|
+
* @param options Options for parsing behavior.
|
|
2264
2339
|
*/
|
|
2265
|
-
static pcStringToMods(str) {
|
|
2340
|
+
static pcStringToMods(str, options) {
|
|
2266
2341
|
const finalMods = [];
|
|
2267
2342
|
str = str.toLowerCase();
|
|
2268
2343
|
while (str) {
|
|
@@ -2276,14 +2351,25 @@ class ModUtil {
|
|
|
2276
2351
|
}
|
|
2277
2352
|
str = str.slice(nchars);
|
|
2278
2353
|
}
|
|
2279
|
-
return this.
|
|
2354
|
+
return this.processParsingOptions(finalMods, options);
|
|
2280
2355
|
}
|
|
2281
2356
|
/**
|
|
2282
|
-
* Checks for mods that are
|
|
2357
|
+
* Checks for mods that are duplicated.
|
|
2283
2358
|
*
|
|
2284
2359
|
* @param mods The mods to check for.
|
|
2360
|
+
* @returns Mods that have been filtered.
|
|
2285
2361
|
*/
|
|
2286
2362
|
static checkDuplicateMods(mods) {
|
|
2363
|
+
return Array.from(new Set(mods));
|
|
2364
|
+
}
|
|
2365
|
+
/**
|
|
2366
|
+
* Checks for mods that are incompatible with each other.
|
|
2367
|
+
*
|
|
2368
|
+
* This will modify the original array.
|
|
2369
|
+
*
|
|
2370
|
+
* @param mods The mods to check for.
|
|
2371
|
+
*/
|
|
2372
|
+
static checkIncompatibleMods(mods) {
|
|
2287
2373
|
for (const incompatibleMod of this.incompatibleMods) {
|
|
2288
2374
|
const fulfilledMods = mods.filter((m) => incompatibleMod.map((v) => v.acronym).includes(m.acronym));
|
|
2289
2375
|
if (fulfilledMods.length > 1) {
|
|
@@ -2294,8 +2380,22 @@ class ModUtil {
|
|
|
2294
2380
|
mods.push(fulfilledMods[0]);
|
|
2295
2381
|
}
|
|
2296
2382
|
}
|
|
2297
|
-
|
|
2298
|
-
|
|
2383
|
+
}
|
|
2384
|
+
/**
|
|
2385
|
+
* Processes parsing options.
|
|
2386
|
+
*
|
|
2387
|
+
* @param mods The mods to process.
|
|
2388
|
+
* @param options The options to process.
|
|
2389
|
+
* @returns The processed mods.
|
|
2390
|
+
*/
|
|
2391
|
+
static processParsingOptions(mods, options) {
|
|
2392
|
+
if (options?.checkDuplicate !== false) {
|
|
2393
|
+
mods = this.checkDuplicateMods(mods);
|
|
2394
|
+
}
|
|
2395
|
+
if (options?.checkIncompatible !== false) {
|
|
2396
|
+
this.checkIncompatibleMods(mods);
|
|
2397
|
+
}
|
|
2398
|
+
return mods;
|
|
2299
2399
|
}
|
|
2300
2400
|
}
|
|
2301
2401
|
|
|
@@ -2394,29 +2494,31 @@ class MapStats {
|
|
|
2394
2494
|
}
|
|
2395
2495
|
switch (params?.mode ?? exports.modes.osu) {
|
|
2396
2496
|
case exports.modes.droid:
|
|
2397
|
-
// In droid pre-1.6.8, NC speed multiplier is assumed bugged (1.39)
|
|
2497
|
+
// In droid pre-1.6.8, NC speed multiplier is assumed bugged (1.39).
|
|
2398
2498
|
if (this.mods.some((m) => m instanceof ModNightCore) &&
|
|
2399
2499
|
this.oldStatistics) {
|
|
2400
2500
|
this.speedMultiplier *= 1.39 / 1.5;
|
|
2401
2501
|
}
|
|
2402
2502
|
// CS and OD work differently in droid, therefore it
|
|
2403
2503
|
// needs to be computed regardless of map-changing mods
|
|
2404
|
-
// and statistics multiplier
|
|
2504
|
+
// and statistics multiplier.
|
|
2405
2505
|
if (this.od !== undefined) {
|
|
2406
|
-
//
|
|
2506
|
+
// Apply EZ or HR to OD.
|
|
2407
2507
|
this.od = Math.min(this.od * statisticsMultiplier, 10);
|
|
2408
|
-
//
|
|
2508
|
+
// Convert original OD to droid hit window to take
|
|
2509
|
+
// droid hit window and the PR mod in mind.
|
|
2409
2510
|
const droidToMS = new DroidHitWindow(this.od).hitWindowFor300(this.mods.some((m) => m instanceof ModPrecise)) / this.speedMultiplier;
|
|
2410
|
-
|
|
2511
|
+
// Convert droid hit window back to original OD.
|
|
2512
|
+
this.od = OsuHitWindow.hitWindow300ToOD(droidToMS);
|
|
2411
2513
|
}
|
|
2412
2514
|
// HR and EZ works differently in droid in terms of
|
|
2413
|
-
// CS modification (even CS in itself as well)
|
|
2515
|
+
// CS modification (even CS in itself as well).
|
|
2414
2516
|
//
|
|
2415
2517
|
// If present mods are found, they need to be removed
|
|
2416
2518
|
// from the bitwise enum of mods to prevent double
|
|
2417
|
-
// calculation
|
|
2519
|
+
// calculation.
|
|
2418
2520
|
if (this.cs !== undefined) {
|
|
2419
|
-
// Assume 681 is height
|
|
2521
|
+
// Assume 681 is height.
|
|
2420
2522
|
const assumedHeight = 681;
|
|
2421
2523
|
let scale = ((assumedHeight / 480) * (54.42 - this.cs * 4.48) * 2) /
|
|
2422
2524
|
128 +
|
|
@@ -2433,7 +2535,8 @@ class MapStats {
|
|
|
2433
2535
|
if (this.mods.some((m) => m instanceof ModSmallCircle)) {
|
|
2434
2536
|
scale -= ((assumedHeight / 480) * (4 * 4.48) * 2) / 128;
|
|
2435
2537
|
}
|
|
2436
|
-
const radius = (64 *
|
|
2538
|
+
const radius = (64 * Math.max(1e-3, scale)) /
|
|
2539
|
+
((assumedHeight * 0.85) / 384);
|
|
2437
2540
|
this.cs = Math.min(5 + ((1 - radius / 32) * 5) / 0.7, 10);
|
|
2438
2541
|
}
|
|
2439
2542
|
if (this.hp !== undefined) {
|
|
@@ -5226,6 +5329,15 @@ class Encoder {
|
|
|
5226
5329
|
* The result of the encoding process.
|
|
5227
5330
|
*/
|
|
5228
5331
|
finalResult = "";
|
|
5332
|
+
/**
|
|
5333
|
+
* The result of the encoding process.
|
|
5334
|
+
*/
|
|
5335
|
+
get result() {
|
|
5336
|
+
return this.finalResult;
|
|
5337
|
+
}
|
|
5338
|
+
/**
|
|
5339
|
+
* @param target The target of the encoding process.
|
|
5340
|
+
*/
|
|
5229
5341
|
constructor(target) {
|
|
5230
5342
|
this.target = target;
|
|
5231
5343
|
}
|
|
@@ -5237,7 +5349,7 @@ class Encoder {
|
|
|
5237
5349
|
encode() {
|
|
5238
5350
|
this.reset();
|
|
5239
5351
|
this.encodeInternal();
|
|
5240
|
-
return this
|
|
5352
|
+
return this;
|
|
5241
5353
|
}
|
|
5242
5354
|
/**
|
|
5243
5355
|
* Writes a line to encoded text.
|
|
@@ -5715,7 +5827,7 @@ class BeatmapEventsEncoder extends BeatmapBaseEncoder {
|
|
|
5715
5827
|
this.writeLine(`2,${b.startTime},${b.endTime}`);
|
|
5716
5828
|
}
|
|
5717
5829
|
if (this.map.events.storyboard) {
|
|
5718
|
-
this.writeLine(new StoryboardEncoder(this.map.events.storyboard, false).encode());
|
|
5830
|
+
this.writeLine(new StoryboardEncoder(this.map.events.storyboard, false).encode().result);
|
|
5719
5831
|
}
|
|
5720
5832
|
else {
|
|
5721
5833
|
this.writeLine("//Storyboard Layer 0 (Background)");
|
|
@@ -6131,31 +6243,16 @@ class MapInfo {
|
|
|
6131
6243
|
*/
|
|
6132
6244
|
videoAvailable = false;
|
|
6133
6245
|
/**
|
|
6134
|
-
* The
|
|
6246
|
+
* The decoded beatmap from beatmap decoder.
|
|
6135
6247
|
*/
|
|
6136
|
-
get
|
|
6137
|
-
return
|
|
6248
|
+
get beatmap() {
|
|
6249
|
+
return this.cachedBeatmap;
|
|
6138
6250
|
}
|
|
6139
|
-
cachedBeatmap;
|
|
6140
|
-
|
|
6141
|
-
|
|
6142
|
-
|
|
6143
|
-
|
|
6144
|
-
*/
|
|
6145
|
-
static async getInformation(params) {
|
|
6146
|
-
params.file ??= true;
|
|
6147
|
-
const beatmapID = params.beatmapID;
|
|
6148
|
-
const hash = params.hash;
|
|
6149
|
-
if (!beatmapID && !hash) {
|
|
6150
|
-
throw new Error("Beatmap ID or MD5 hash must be defined");
|
|
6151
|
-
}
|
|
6152
|
-
const apiRequestBuilder = new OsuAPIRequestBuilder().setEndpoint("get_beatmaps");
|
|
6153
|
-
if (beatmapID) {
|
|
6154
|
-
apiRequestBuilder.addParameter("b", beatmapID);
|
|
6155
|
-
}
|
|
6156
|
-
else if (hash) {
|
|
6157
|
-
apiRequestBuilder.addParameter("h", hash);
|
|
6158
|
-
}
|
|
6251
|
+
cachedBeatmap = null;
|
|
6252
|
+
static async getInformation(beatmapIdOrHash, downloadBeatmap) {
|
|
6253
|
+
const apiRequestBuilder = new OsuAPIRequestBuilder()
|
|
6254
|
+
.setEndpoint("get_beatmaps")
|
|
6255
|
+
.addParameter(typeof beatmapIdOrHash === "string" ? "h" : "b", beatmapIdOrHash);
|
|
6159
6256
|
const map = new MapInfo();
|
|
6160
6257
|
const result = await apiRequestBuilder.sendRequest();
|
|
6161
6258
|
if (result.statusCode !== 200) {
|
|
@@ -6163,13 +6260,13 @@ class MapInfo {
|
|
|
6163
6260
|
}
|
|
6164
6261
|
const mapinfo = JSON.parse(result.data.toString("utf-8"))[0];
|
|
6165
6262
|
if (!mapinfo) {
|
|
6166
|
-
return
|
|
6263
|
+
return null;
|
|
6167
6264
|
}
|
|
6168
6265
|
if (parseInt(mapinfo.mode) !== 0) {
|
|
6169
|
-
return
|
|
6266
|
+
return null;
|
|
6170
6267
|
}
|
|
6171
6268
|
map.fillMetadata(mapinfo);
|
|
6172
|
-
if (
|
|
6269
|
+
if (downloadBeatmap !== false) {
|
|
6173
6270
|
await map.retrieveBeatmapFile();
|
|
6174
6271
|
}
|
|
6175
6272
|
return map;
|
|
@@ -6232,15 +6329,23 @@ class MapInfo {
|
|
|
6232
6329
|
this.videoAvailable = !!parseInt(mapinfo.video);
|
|
6233
6330
|
return this;
|
|
6234
6331
|
}
|
|
6332
|
+
/**
|
|
6333
|
+
* Checks whether the beatmap file has been downloaded.
|
|
6334
|
+
*/
|
|
6335
|
+
hasDownloadedBeatmap() {
|
|
6336
|
+
return this.cachedBeatmap !== null;
|
|
6337
|
+
}
|
|
6235
6338
|
/**
|
|
6236
6339
|
* Retrieves the .osu file of the beatmap.
|
|
6237
6340
|
*
|
|
6238
|
-
*
|
|
6341
|
+
* After this, you can use the `hasDownloadedBeatmap` method to check if the beatmap has been downloaded.
|
|
6342
|
+
*
|
|
6343
|
+
* @param force Whether to download the file regardless if it's already available.
|
|
6239
6344
|
*/
|
|
6240
|
-
retrieveBeatmapFile(
|
|
6345
|
+
retrieveBeatmapFile(force) {
|
|
6241
6346
|
return new Promise((resolve) => {
|
|
6242
|
-
if (this.
|
|
6243
|
-
return resolve(
|
|
6347
|
+
if (this.hasDownloadedBeatmap() && !force) {
|
|
6348
|
+
return resolve();
|
|
6244
6349
|
}
|
|
6245
6350
|
const url = `https://osu.ppy.sh/osu/${this.beatmapID}`;
|
|
6246
6351
|
const dataArray = [];
|
|
@@ -6250,10 +6355,10 @@ class MapInfo {
|
|
|
6250
6355
|
})
|
|
6251
6356
|
.on("complete", (response) => {
|
|
6252
6357
|
if (response.statusCode !== 200) {
|
|
6253
|
-
return resolve(
|
|
6358
|
+
return resolve();
|
|
6254
6359
|
}
|
|
6255
6360
|
this.cachedBeatmap = new BeatmapDecoder().decode(Buffer.concat(dataArray).toString("utf8")).result;
|
|
6256
|
-
resolve(
|
|
6361
|
+
resolve();
|
|
6257
6362
|
});
|
|
6258
6363
|
});
|
|
6259
6364
|
}
|
|
@@ -6313,10 +6418,12 @@ class MapInfo {
|
|
|
6313
6418
|
*
|
|
6314
6419
|
* - Option `0`: return map title and mods used if defined
|
|
6315
6420
|
* - Option `1`: return song source and map download link to beatmap mirrors
|
|
6316
|
-
* - Option `2`: return
|
|
6317
|
-
* - Option `3`: return
|
|
6318
|
-
* - Option `4`: return
|
|
6319
|
-
* - Option `5`: return
|
|
6421
|
+
* - Option `2`: return circle, slider, and spinner count
|
|
6422
|
+
* - Option `3`: return CS, AR, OD, HP, and max score statistics for droid
|
|
6423
|
+
* - Option `4`: return CS, AR, OD, HP, and max score statistics for PC
|
|
6424
|
+
* - Option `5`: return BPM, map length, and max combo
|
|
6425
|
+
* - Option `6`: return last update date and map status
|
|
6426
|
+
* - Option `7`: return favorite count and play count
|
|
6320
6427
|
*
|
|
6321
6428
|
* @param option The option to pick.
|
|
6322
6429
|
* @param stats The custom statistics to apply. This will only be used to apply mods, custom speed multiplier, and force AR.
|
|
@@ -6339,13 +6446,9 @@ class MapInfo {
|
|
|
6339
6446
|
mapParams.speedMultiplier =
|
|
6340
6447
|
stats.speedMultiplier ?? mapParams.speedMultiplier;
|
|
6341
6448
|
}
|
|
6342
|
-
const mapStatistics = new MapStats(mapParams).calculate();
|
|
6343
|
-
mapStatistics.cs = parseFloat(mapStatistics.cs.toFixed(2));
|
|
6344
|
-
mapStatistics.ar = parseFloat(mapStatistics.ar.toFixed(2));
|
|
6345
|
-
mapStatistics.od = parseFloat(mapStatistics.od.toFixed(2));
|
|
6346
|
-
mapStatistics.hp = parseFloat(mapStatistics.hp.toFixed(2));
|
|
6347
6449
|
switch (option) {
|
|
6348
6450
|
case 0: {
|
|
6451
|
+
const mapStatistics = new MapStats(mapParams).calculate();
|
|
6349
6452
|
let string = `${this.fullTitle}${(mapStatistics.mods.length ?? 0) > 0
|
|
6350
6453
|
? ` +${mapStatistics.mods
|
|
6351
6454
|
.map((m) => m.acronym)
|
|
@@ -6389,19 +6492,65 @@ class MapInfo {
|
|
|
6389
6492
|
return string;
|
|
6390
6493
|
}
|
|
6391
6494
|
case 2:
|
|
6392
|
-
return `**Circles**: ${this.circles} - **Sliders**: ${this.sliders} - **Spinners**: ${this.spinners}
|
|
6495
|
+
return `**Circles**: ${this.circles} - **Sliders**: ${this.sliders} - **Spinners**: ${this.spinners}`;
|
|
6393
6496
|
case 3: {
|
|
6394
|
-
const
|
|
6497
|
+
const droidOriginalStats = new MapStats({
|
|
6498
|
+
cs: this.cs,
|
|
6499
|
+
ar: this.ar,
|
|
6500
|
+
od: this.od,
|
|
6501
|
+
hp: this.hp,
|
|
6502
|
+
}).calculate({ mode: exports.modes.droid });
|
|
6503
|
+
const droidModifiedStats = new MapStats(mapParams).calculate({ mode: exports.modes.droid });
|
|
6504
|
+
droidOriginalStats.cs = MathUtils.round(droidOriginalStats.cs, 2);
|
|
6505
|
+
droidOriginalStats.ar = MathUtils.round(droidOriginalStats.ar, 2);
|
|
6506
|
+
droidOriginalStats.od = MathUtils.round(droidOriginalStats.od, 2);
|
|
6507
|
+
droidOriginalStats.hp = MathUtils.round(droidOriginalStats.hp, 2);
|
|
6508
|
+
droidModifiedStats.cs = MathUtils.round(droidModifiedStats.cs, 2);
|
|
6509
|
+
droidModifiedStats.ar = MathUtils.round(droidModifiedStats.ar, 2);
|
|
6510
|
+
droidModifiedStats.od = MathUtils.round(droidModifiedStats.od, 2);
|
|
6511
|
+
droidModifiedStats.hp = MathUtils.round(droidModifiedStats.hp, 2);
|
|
6512
|
+
const maxScore = this.beatmap?.maxDroidScore(new MapStats(mapParams)) ?? 0;
|
|
6513
|
+
return `**CS**: ${droidOriginalStats.cs}${Precision.almostEqualsNumber(droidOriginalStats.cs, droidModifiedStats.cs)
|
|
6514
|
+
? ""
|
|
6515
|
+
: ` (${droidModifiedStats.cs})`} - **AR**: ${droidOriginalStats.ar}${Precision.almostEqualsNumber(droidOriginalStats.ar, droidModifiedStats.ar)
|
|
6516
|
+
? ""
|
|
6517
|
+
: ` (${droidModifiedStats.ar})`} - **OD**: ${droidOriginalStats.od}${Precision.almostEqualsNumber(droidOriginalStats.od, droidModifiedStats.od)
|
|
6518
|
+
? ""
|
|
6519
|
+
: ` (${droidModifiedStats.od})`} - **HP**: ${droidOriginalStats.hp}${Precision.almostEqualsNumber(droidOriginalStats.hp, droidModifiedStats.hp)
|
|
6520
|
+
? ""
|
|
6521
|
+
: ` (${droidModifiedStats.hp})`}${maxScore > 0
|
|
6522
|
+
? `\n**Max Score**: ${maxScore.toLocaleString()}`
|
|
6523
|
+
: ""}`;
|
|
6524
|
+
}
|
|
6525
|
+
case 4: {
|
|
6526
|
+
const mapStatistics = new MapStats(mapParams).calculate();
|
|
6527
|
+
mapStatistics.cs = MathUtils.round(mapStatistics.cs, 2);
|
|
6528
|
+
mapStatistics.ar = MathUtils.round(mapStatistics.ar, 2);
|
|
6529
|
+
mapStatistics.od = MathUtils.round(mapStatistics.od, 2);
|
|
6530
|
+
mapStatistics.hp = MathUtils.round(mapStatistics.hp, 2);
|
|
6531
|
+
const maxScore = this.beatmap?.maxOsuScore(mapStatistics.mods) ?? 0;
|
|
6532
|
+
return `**CS**: ${this.cs}${Precision.almostEqualsNumber(this.cs, mapStatistics.cs)
|
|
6533
|
+
? ""
|
|
6534
|
+
: ` (${mapStatistics.cs})`} - **AR**: ${this.ar}${Precision.almostEqualsNumber(this.ar, mapStatistics.ar)
|
|
6535
|
+
? ""
|
|
6536
|
+
: ` (${mapStatistics.ar})`} - **OD**: ${this.od}${Precision.almostEqualsNumber(this.od, mapStatistics.od)
|
|
6537
|
+
? ""
|
|
6538
|
+
: ` (${mapStatistics.od})`} - **HP**: ${this.hp}${Precision.almostEqualsNumber(this.hp, mapStatistics.hp)
|
|
6539
|
+
? ""
|
|
6540
|
+
: ` (${mapStatistics.hp})`}${maxScore > 0
|
|
6541
|
+
? `\n**Max Score**: ${maxScore.toLocaleString()}`
|
|
6542
|
+
: ""}`;
|
|
6543
|
+
}
|
|
6544
|
+
case 5: {
|
|
6545
|
+
const mapStatistics = new MapStats(mapParams).calculate();
|
|
6395
6546
|
const convertedBPM = this.convertBPM(mapStatistics);
|
|
6396
6547
|
let string = "**BPM**: ";
|
|
6397
|
-
if (this.
|
|
6398
|
-
const uninheritedTimingPoints = this.
|
|
6548
|
+
if (this.beatmap) {
|
|
6549
|
+
const uninheritedTimingPoints = this.beatmap.controlPoints.timing.points;
|
|
6399
6550
|
if (uninheritedTimingPoints.length === 1) {
|
|
6400
6551
|
string += `${this.bpm}${!Precision.almostEqualsNumber(this.bpm, convertedBPM)
|
|
6401
6552
|
? ` (${convertedBPM})`
|
|
6402
|
-
: ""} - **Length**: ${this.convertTime(mapStatistics)} - **Max Combo**: ${this.maxCombo}x
|
|
6403
|
-
? `\n**Max Score**: ${maxScore.toLocaleString()}`
|
|
6404
|
-
: ""}`;
|
|
6553
|
+
: ""} - **Length**: ${this.convertTime(mapStatistics)} - **Max Combo**: ${this.maxCombo}x`;
|
|
6405
6554
|
}
|
|
6406
6555
|
else {
|
|
6407
6556
|
let maxBPM = this.bpm;
|
|
@@ -6428,23 +6577,19 @@ class MapInfo {
|
|
|
6428
6577
|
string += `(${convertedBPM}) `;
|
|
6429
6578
|
}
|
|
6430
6579
|
}
|
|
6431
|
-
string += `- **Length**: ${this.convertTime(mapStatistics)} - **Max Combo**: ${this.maxCombo}x
|
|
6432
|
-
? `\n**Max score**: ${maxScore.toLocaleString()}`
|
|
6433
|
-
: ""}`;
|
|
6580
|
+
string += `- **Length**: ${this.convertTime(mapStatistics)} - **Max Combo**: ${this.maxCombo}x`;
|
|
6434
6581
|
}
|
|
6435
6582
|
}
|
|
6436
6583
|
else {
|
|
6437
6584
|
string += `${this.bpm}${!Precision.almostEqualsNumber(this.bpm, convertedBPM)
|
|
6438
6585
|
? ` (${convertedBPM})`
|
|
6439
|
-
: ""} - **Length**: ${this.convertTime(mapStatistics)} - **Max Combo**: ${this.maxCombo}x
|
|
6440
|
-
? `\n**Max score**: ${maxScore.toLocaleString()}`
|
|
6441
|
-
: ""}`;
|
|
6586
|
+
: ""} - **Length**: ${this.convertTime(mapStatistics)} - **Max Combo**: ${this.maxCombo}x`;
|
|
6442
6587
|
}
|
|
6443
6588
|
return string;
|
|
6444
6589
|
}
|
|
6445
|
-
case
|
|
6590
|
+
case 6:
|
|
6446
6591
|
return `**Last Update**: ${this.lastUpdate.toUTCString()} | **${this.convertStatus()}**`;
|
|
6447
|
-
case
|
|
6592
|
+
case 7:
|
|
6448
6593
|
return `❤️ **${this.favorites.toLocaleString()}** - ▶️ **${this.plays.toLocaleString()}**`;
|
|
6449
6594
|
default:
|
|
6450
6595
|
throw {
|
|
@@ -6512,9 +6657,11 @@ exports.CommandTimelineGroup = CommandTimelineGroup;
|
|
|
6512
6657
|
exports.CommandTrigger = CommandTrigger;
|
|
6513
6658
|
exports.ControlPointManager = ControlPointManager;
|
|
6514
6659
|
exports.DifficultyControlPoint = DifficultyControlPoint;
|
|
6660
|
+
exports.DifficultyControlPointManager = DifficultyControlPointManager;
|
|
6515
6661
|
exports.DroidAPIRequestBuilder = DroidAPIRequestBuilder;
|
|
6516
6662
|
exports.DroidHitWindow = DroidHitWindow;
|
|
6517
6663
|
exports.EffectControlPoint = EffectControlPoint;
|
|
6664
|
+
exports.EffectControlPointManager = EffectControlPointManager;
|
|
6518
6665
|
exports.HitObject = HitObject;
|
|
6519
6666
|
exports.HitSampleInfo = HitSampleInfo;
|
|
6520
6667
|
exports.Interpolation = Interpolation;
|
|
@@ -6549,6 +6696,7 @@ exports.Precision = Precision;
|
|
|
6549
6696
|
exports.RGBColor = RGBColor;
|
|
6550
6697
|
exports.SampleBankInfo = SampleBankInfo;
|
|
6551
6698
|
exports.SampleControlPoint = SampleControlPoint;
|
|
6699
|
+
exports.SampleControlPointManager = SampleControlPointManager;
|
|
6552
6700
|
exports.Slider = Slider;
|
|
6553
6701
|
exports.SliderHead = SliderHead;
|
|
6554
6702
|
exports.SliderPath = SliderPath;
|
|
@@ -6565,6 +6713,7 @@ exports.StoryboardLayer = StoryboardLayer;
|
|
|
6565
6713
|
exports.StoryboardSample = StoryboardSample;
|
|
6566
6714
|
exports.StoryboardSprite = StoryboardSprite;
|
|
6567
6715
|
exports.TimingControlPoint = TimingControlPoint;
|
|
6716
|
+
exports.TimingControlPointManager = TimingControlPointManager;
|
|
6568
6717
|
exports.Utils = Utils;
|
|
6569
6718
|
exports.Vector2 = Vector2;
|
|
6570
6719
|
//# sourceMappingURL=index.js.map
|