nonebot-plugin-osubot 6.23.1__py3-none-any.whl → 6.24.1__py3-none-any.whl

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.

Potentially problematic release.


This version of nonebot-plugin-osubot might be problematic. Click here for more details.

Files changed (81) hide show
  1. nonebot_plugin_osubot/api.py +7 -5
  2. nonebot_plugin_osubot/draw/bmap.py +19 -21
  3. nonebot_plugin_osubot/draw/bp.py +1 -1
  4. nonebot_plugin_osubot/draw/echarts.py +8 -2
  5. nonebot_plugin_osubot/draw/info.py +2 -0
  6. nonebot_plugin_osubot/draw/map.py +5 -2
  7. nonebot_plugin_osubot/draw/osu_preview.py +64 -0
  8. nonebot_plugin_osubot/draw/osu_preview_templates/css/style.css +258 -0
  9. nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/README.md +109 -0
  10. nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.js +3 -0
  11. nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.js.map +1 -0
  12. nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.worker.js +3 -0
  13. nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.worker.js.map +1 -0
  14. nonebot_plugin_osubot/draw/osu_preview_templates/index.html +437 -0
  15. nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/beatmap.js +211 -0
  16. nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/hitobject.js +29 -0
  17. nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/point.js +55 -0
  18. nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/scroll.js +45 -0
  19. nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/timingpoint.js +35 -0
  20. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/LegacyRandom.js +81 -0
  21. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/PalpableCatchHitObject.js +53 -0
  22. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/bananashower.js +33 -0
  23. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/catch.js +211 -0
  24. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/fruit.js +21 -0
  25. nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/juicestream.js +176 -0
  26. nonebot_plugin_osubot/draw/osu_preview_templates/js/mania/hitnote.js +21 -0
  27. nonebot_plugin_osubot/draw/osu_preview_templates/js/mania/holdnote.js +37 -0
  28. nonebot_plugin_osubot/draw/osu_preview_templates/js/mania/mania.js +164 -0
  29. nonebot_plugin_osubot/draw/osu_preview_templates/js/preview.js +61 -0
  30. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/bezier2.js +33 -0
  31. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/catmullcurve.js +34 -0
  32. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/centripetalcatmullrom.js +30 -0
  33. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/circumstancedcircle.js +47 -0
  34. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/curve.js +25 -0
  35. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/curvetype.js +17 -0
  36. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/equaldistancemulticurve.js +70 -0
  37. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/linearbezier.js +40 -0
  38. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/hitcircle.js +85 -0
  39. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/slider.js +120 -0
  40. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/spinner.js +56 -0
  41. nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/standard.js +170 -0
  42. nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/donkat.js +40 -0
  43. nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/drumroll.js +34 -0
  44. nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/shaker.js +58 -0
  45. nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/taiko.js +120 -0
  46. nonebot_plugin_osubot/draw/osu_preview_templates/js/util.js +61 -0
  47. nonebot_plugin_osubot/draw/osu_preview_templates/pic.html +115 -0
  48. nonebot_plugin_osubot/draw/score.py +4 -4
  49. nonebot_plugin_osubot/file.py +1 -12
  50. nonebot_plugin_osubot/mania/__init__.py +9 -10
  51. nonebot_plugin_osubot/matcher/bp_analyze.py +9 -9
  52. nonebot_plugin_osubot/matcher/guess.py +3 -3
  53. nonebot_plugin_osubot/matcher/map_convert.py +12 -7
  54. nonebot_plugin_osubot/matcher/preview.py +10 -3
  55. nonebot_plugin_osubot/matcher/recommend.py +7 -12
  56. nonebot_plugin_osubot/osufile/mods/AP.png +0 -0
  57. nonebot_plugin_osubot/osufile/mods/CL.png +0 -0
  58. nonebot_plugin_osubot/osufile/mods/DT.png +0 -0
  59. nonebot_plugin_osubot/osufile/mods/EZ.png +0 -0
  60. nonebot_plugin_osubot/osufile/mods/FI.png +0 -0
  61. nonebot_plugin_osubot/osufile/mods/FL.png +0 -0
  62. nonebot_plugin_osubot/osufile/mods/HD.png +0 -0
  63. nonebot_plugin_osubot/osufile/mods/HR.png +0 -0
  64. nonebot_plugin_osubot/osufile/mods/HT.png +0 -0
  65. nonebot_plugin_osubot/osufile/mods/MR.png +0 -0
  66. nonebot_plugin_osubot/osufile/mods/NC.png +0 -0
  67. nonebot_plugin_osubot/osufile/mods/NF.png +0 -0
  68. nonebot_plugin_osubot/osufile/mods/PF.png +0 -0
  69. nonebot_plugin_osubot/osufile/mods/RX.png +0 -0
  70. nonebot_plugin_osubot/osufile/mods/SD.png +0 -0
  71. nonebot_plugin_osubot/osufile/mods/SO.png +0 -0
  72. nonebot_plugin_osubot/osufile/mods/TD.png +0 -0
  73. nonebot_plugin_osubot/osufile/mods/V2.png +0 -0
  74. nonebot_plugin_osubot/pp.py +7 -0
  75. nonebot_plugin_osubot/schema/__init__.py +0 -2
  76. nonebot_plugin_osubot/schema/beatmapsets.py +42 -0
  77. nonebot_plugin_osubot/schema/score.py +1 -0
  78. {nonebot_plugin_osubot-6.23.1.dist-info → nonebot_plugin_osubot-6.24.1.dist-info}/METADATA +2 -2
  79. {nonebot_plugin_osubot-6.23.1.dist-info → nonebot_plugin_osubot-6.24.1.dist-info}/RECORD +80 -39
  80. nonebot_plugin_osubot/schema/sayo_beatmap.py +0 -59
  81. {nonebot_plugin_osubot-6.23.1.dist-info → nonebot_plugin_osubot-6.24.1.dist-info}/WHEEL +0 -0
@@ -0,0 +1,55 @@
1
+ function Point()
2
+ {
3
+ if (arguments.length >= 2)
4
+ {
5
+ this.x = +arguments[0];
6
+ this.y = +arguments[1];
7
+ }
8
+ else if (arguments.length == 1)
9
+ {
10
+ this.x = +arguments[0][0];
11
+ this.y = +arguments[0][1];
12
+ }
13
+ else
14
+ {
15
+ this.x = 0;
16
+ this.y = 0;
17
+ }
18
+ }
19
+ Point.prototype.distanceTo = function(point)
20
+ {
21
+ return Math.hypot(point.x - this.x, point.y - this.y);
22
+ };
23
+ Point.prototype.equalTo = function(point)
24
+ {
25
+ return point instanceof Point &&
26
+ this.x == point.x && this.y == point.y;
27
+ };
28
+ Point.prototype.angleTo = function(point)
29
+ {
30
+ return Math.atan2(point.y - this.y, point.x - this.x);
31
+ };
32
+ Point.prototype.clone = function()
33
+ {
34
+ return new Point(this.x, this.y);
35
+ };
36
+ Point.prototype.translate = function(n)
37
+ {
38
+ if (n instanceof Point)
39
+ {
40
+ this.x += n.x;
41
+ this.y += n.y;
42
+ }
43
+ else
44
+ {
45
+ this.x += n;
46
+ this.y += n;
47
+ }
48
+ return this;
49
+ };
50
+ Point.prototype.scale = function(n)
51
+ {
52
+ this.x *= n;
53
+ this.y *= n;
54
+ return this;
55
+ };
@@ -0,0 +1,45 @@
1
+ function Scroll(osu)
2
+ {
3
+ Beatmap.call(this, osu);
4
+
5
+ // dp for numerous call to this.scrollAt
6
+ this.scrollAtTimingPointIndex = [ 0 ];
7
+ var currentIdx = this.timingPointIndexAt(0),
8
+ current = this.TimingPoints[currentIdx],
9
+ base = this.TimingPoints[0],
10
+ scrollVelocity = base.beatLength / current.beatLength;
11
+ this.scrollAtTimingPointIndex[currentIdx] = current.time * scrollVelocity;
12
+ while (++currentIdx < this.TimingPoints.length)
13
+ {
14
+ var next = this.TimingPoints[currentIdx];
15
+ this.scrollAtTimingPointIndex[currentIdx] = (next.time - current.time) * scrollVelocity +
16
+ this.scrollAtTimingPointIndex[currentIdx - 1];
17
+ current = next;
18
+ scrollVelocity = base.beatLength / current.beatLength;
19
+ }
20
+
21
+ this.barLines = [];
22
+ var endTime = (this.HitObjects.length ? this.HitObjects[this.HitObjects.length - 1].endTime : 0) + 1;
23
+ for (var i = 0; i < this.TimingPoints.length; i++)
24
+ {
25
+ var current = this.TimingPoints[i],
26
+ base = current.parent || current,
27
+ barLength = base.beatLength * base.meter,
28
+ next = this.TimingPoints[i + 1],
29
+ barLineLimit = next ? (next.parent || next).time : endTime;
30
+ for (var barTime = base.time; barTime < barLineLimit; barTime += barLength)
31
+ {
32
+ this.barLines.push(this.scrollAt(barTime));
33
+ }
34
+ }
35
+ }
36
+ Scroll.prototype = Object.create(Beatmap.prototype);
37
+ Scroll.prototype.constructor = Scroll;
38
+ Scroll.prototype.scrollAt = function(time)
39
+ {
40
+ var currentIdx = this.timingPointIndexAt(time),
41
+ current = this.TimingPoints[currentIdx],
42
+ base = this.TimingPoints[0],
43
+ scrollVelocity = base.beatLength / current.beatLength;
44
+ return (time - current.time) * scrollVelocity + this.scrollAtTimingPointIndex[currentIdx];
45
+ };
@@ -0,0 +1,35 @@
1
+ function TimingPoint(line)
2
+ {
3
+ var data = line.split(',');
4
+ if (data.length < 2)
5
+ {
6
+ throw 'invalid data';
7
+ }
8
+
9
+ this.time = data[0] | 0;
10
+ this.beatLength = +data[1];
11
+ this.meter = (data[2] | 0) || 4;
12
+ this.kiai = (data[7] | 0) % 2;
13
+
14
+ // this is non-inherited timingPoint
15
+ if (this.beatLength >= 0)
16
+ {
17
+ TimingPoint.parent = this;
18
+ this.sliderVelocity = 1;
19
+ }
20
+ else
21
+ {
22
+ this.parent = TimingPoint.parent;
23
+ this.sliderVelocity = -100 / this.beatLength;
24
+ this.beatLength = this.parent.beatLength / this.sliderVelocity;
25
+ this.meter = this.parent.meter;
26
+ }
27
+ }
28
+ Object.defineProperties(TimingPoint.prototype, {
29
+ bpm: {
30
+ get: function()
31
+ {
32
+ return 60000 / this.beatLength;
33
+ }
34
+ }
35
+ });
@@ -0,0 +1,81 @@
1
+ class LegacyRandom{
2
+ constructor(x) {
3
+ this.int_to_real = 1 / 2147483648;
4
+ this.int_mask = 0x7FFFFFFF;
5
+ this.x = x || Date.now();
6
+ this.x = this.ToUInt(this.x);
7
+ this._X = this.x;
8
+ this.y = 842502087;
9
+ this._Y = this.y;
10
+ this.z = 3579807591;
11
+ this._Z = this.z;
12
+ this.w = 273326509;
13
+ this._W = this.w;
14
+
15
+ this.bitBuffer;
16
+ this.bitIndex = 32;
17
+ }
18
+
19
+ ToInt(num) {
20
+ if (num > 2147483647) return this.ToInt(num - 4294967296);
21
+ else if (num < -2147483648) return this.ToInt(4294967296 + num);
22
+ else return parseInt(num);
23
+ }
24
+
25
+ ToUInt(num) {
26
+ if (num > 4294967296) return this.ToUInt(num - 4294967296);
27
+ if (num < 0) return this.ToUInt(4294967296 + num);
28
+ else return num;
29
+ }
30
+
31
+ NextUInt() {
32
+ let t = this.ToUInt(this._X ^ this.ToUInt(this._X << 11));
33
+ this._X = this._Y;
34
+ this._Y = this._Z;
35
+ this._Z = this._W;
36
+ let tmp = this.ToUInt(this._W >>> 19);
37
+ tmp = this.ToUInt(this._W ^ tmp);
38
+ tmp = this.ToUInt(tmp ^ t);
39
+ let tmp2 = this.ToUInt(t >>> 8);
40
+ this._W = this.ToUInt(tmp ^ tmp2);
41
+ return this._W;
42
+ }
43
+
44
+ Next() {
45
+ if (arguments.length <= 0) {
46
+ return this.ToInt(this.int_mask & this.NextUInt());
47
+ }
48
+ else if (arguments.length === 1) { // upperBound
49
+ return this.ToInt(this.NextDouble() * arguments[0]);
50
+ }
51
+ else { // lowerBound, upperBound
52
+ return this.ToInt(arguments[0] + this.NextDouble() * (arguments[1] - arguments[0]));
53
+ }
54
+ }
55
+
56
+ NextDouble() {
57
+ return this.int_to_real * this.Next();
58
+ }
59
+
60
+ NextBool() {
61
+ if (this.bitIndex == 32)
62
+ {
63
+ this.bitBuffer = this.NextUInt();
64
+ this.bitIndex = 1;
65
+
66
+ return ((this.bitBuffer & 1) == 1);
67
+ }
68
+
69
+ this.bitIndex++;
70
+ this.bitBuffer = this.bitBuffer >>> 1;
71
+ return ((this.bitBuffer & 1) == 1);
72
+ }
73
+ }
74
+ /*
75
+ let rng = new LegacyRandom(1337);
76
+ for(let i = 0; i < 1000; i++)
77
+ {
78
+ rng.NextDouble();
79
+ }
80
+ console.log(rng.NextDouble());
81
+ */
@@ -0,0 +1,53 @@
1
+ function PalpableCatchHitObject(data, beatmap)
2
+ {
3
+ this.beatmap = beatmap;
4
+ this.type = data.type;
5
+ this.time = data.time;
6
+ this.x = data.x;
7
+ this.color = data.color;
8
+ this.radius = data.radius;
9
+ this.hyperDash = false;
10
+ }
11
+ PalpableCatchHitObject.prototype.draw = function(time, ctx)
12
+ {
13
+ var dt = this.time - time;
14
+ if (dt >= -this.beatmap.FALLOUT_TIME) {
15
+ if (this.type === "Banana") this.drawBanana({x: this.x, y: (1 - dt / this.beatmap.approachTime) * Beatmap.HEIGHT - this.beatmap.CATCHER_HEIGHT}, ctx);
16
+ else {
17
+ if (this.hyperDash) this.drawDashCircle({x: this.x, y: (1 - dt / this.beatmap.approachTime) * Beatmap.HEIGHT - this.beatmap.CATCHER_HEIGHT}, ctx);
18
+ this.drawCircle({x: this.x, y: (1 - dt / this.beatmap.approachTime) * Beatmap.HEIGHT - this.beatmap.CATCHER_HEIGHT}, ctx);
19
+ }
20
+ }
21
+ };
22
+ PalpableCatchHitObject.prototype.drawCircle = function(position, ctx)
23
+ {
24
+ ctx.save();
25
+ ctx.beginPath();
26
+ ctx.arc(position.x, position.y, this.radius, -Math.PI, Math.PI);
27
+ ctx.shadowBlur = 0;
28
+ ctx.fillStyle = this.color;
29
+ ctx.fill();
30
+ ctx.restore();
31
+ };
32
+ PalpableCatchHitObject.prototype.drawBanana = function(position, ctx)
33
+ {
34
+ ctx.save();
35
+ ctx.beginPath();
36
+ ctx.shadowBlur = 0;
37
+ ctx.arc(position.x, position.y, this.radius * 0.9, -Math.PI, Math.PI);
38
+ ctx.lineWidth = this.radius * 0.2;
39
+ ctx.strokeStyle = this.color;
40
+ ctx.stroke();
41
+ ctx.restore();
42
+ };
43
+ PalpableCatchHitObject.prototype.drawDashCircle = function(position, ctx)
44
+ {
45
+ ctx.save();
46
+ ctx.beginPath();
47
+ ctx.shadowBlur = 0;
48
+ ctx.arc(position.x, position.y, this.radius * 1.1, -Math.PI, Math.PI);
49
+ ctx.lineWidth = this.radius * 0.2;
50
+ ctx.strokeStyle = 'rgb(255,0,0)';
51
+ ctx.stroke();
52
+ ctx.restore();
53
+ };
@@ -0,0 +1,33 @@
1
+ function BananaShower(data, beatmap) {
2
+ Spinner.call(this, data, beatmap);
3
+
4
+ this.endTime = data[5] | 0;
5
+ this.duration = this.endTime - this.time;
6
+
7
+ this.nested = [];
8
+ }
9
+ BananaShower.prototype = Object.create(Spinner.prototype);
10
+ BananaShower.prototype.constructor = BananaShower;
11
+ BananaShower.ID = 8;
12
+ Catch.prototype.hitObjectTypes[BananaShower.ID] = BananaShower;
13
+ BananaShower.prototype.buildNested = function() {
14
+ this.nested = [];
15
+ let spacing = this.duration;
16
+ while (spacing > 100) spacing /= 2;
17
+ if (spacing <= 0) return;
18
+ let time = this.time;
19
+ let i = 0;
20
+ while (time <= this.endTime) {
21
+ this.nested.push(new PalpableCatchHitObject({
22
+ type: "Banana",
23
+ time,
24
+ x: 0,
25
+ color: 'rgb(255,240,0)',
26
+ radius: this.beatmap.bananaRadius,
27
+ }, this.beatmap));
28
+
29
+ time += spacing;
30
+ i++;
31
+ }
32
+ return this;
33
+ };
@@ -0,0 +1,211 @@
1
+ function Catch(osu) {
2
+ Beatmap.call(this, osu);
3
+
4
+ let savedDefaultColor = window.localStorage.getItem("DefaultColor");
5
+ this.useDefaultColor = (savedDefaultColor) ? parseInt(savedDefaultColor) : 0;
6
+
7
+ let savedColorChange = window.localStorage.getItem("ColorChange");
8
+ this.colorChange = (savedColorChange) ? parseInt(savedColorChange) : 0;
9
+
10
+ if (this.Colors.length && !this.useDefaultColor) {
11
+ this.Colors.push(this.Colors.shift());
12
+ }
13
+ else {
14
+ this.Colors = Catch.DEFAULT_COLORS;
15
+ }
16
+
17
+ this.circleRadius = this.circleDiameter / 2 - 4;
18
+ this.smallRadius = this.circleRadius / 2;
19
+ this.tinyRadius = this.smallRadius / 2;
20
+ this.bananaRadius = this.circleRadius * 0.8;
21
+
22
+ this.CATCHER_HEIGHT = Beatmap.HEIGHT / 8;
23
+ this.FALLOUT_TIME = (this.CATCHER_HEIGHT / Beatmap.HEIGHT) * this.approachTime;
24
+
25
+ var combo = 1,
26
+ comboIndex = -1,
27
+ setComboIndex = 1;
28
+ for (var i = 0; i < this.HitObjects.length; i++) {
29
+ let hitObject = this.HitObjects[i];
30
+ if (hitObject instanceof BananaShower) {
31
+ setComboIndex = 1;
32
+ }
33
+ else if (hitObject.newCombo || setComboIndex) {
34
+ combo = 1;
35
+ comboIndex = ((comboIndex + 1) + hitObject.comboSkip) % this.Colors.length;
36
+ setComboIndex = 0;
37
+ }
38
+ hitObject.combo = combo++;
39
+ hitObject.color = (this.colorChange) ? this.Colors[i % this.Colors.length] : this.Colors[comboIndex];
40
+
41
+ if (hitObject instanceof JuiceStream || hitObject instanceof BananaShower) {
42
+ hitObject.buildNested();
43
+ }
44
+ }
45
+
46
+ this.CATCHER_BASE_SIZE = 106.75;
47
+ this.ALLOWED_CATCH_RANGE = 0.8;
48
+ this.HYPER_DASH_TRANSITION_DURATION = 180;
49
+ this.calculateScale = 1.0 - 0.7 * (this.CircleSize - 5) / 5;
50
+ this.catchWidth = this.CATCHER_BASE_SIZE * Math.abs(this.calculateScale) * this.ALLOWED_CATCH_RANGE;
51
+ this.halfCatcherWidth = this.catchWidth / 2;
52
+ this.halfCatcherWidth /= this.ALLOWED_CATCH_RANGE;
53
+ this.BASE_DASH_SPEED = 1;
54
+ this.BASE_WALK_SPEED = 0.5;
55
+
56
+ // sliders & spins xoffset
57
+ this.RNG_SEED = 1337;
58
+ var rng = new LegacyRandom(this.RNG_SEED);
59
+
60
+ for (var i = 0; i < this.HitObjects.length; i++) {
61
+ let hitObject = this.HitObjects[i];
62
+ // console.log(hitObject.nested)
63
+ if (hitObject instanceof BananaShower) {
64
+ hitObject.nested.forEach(banana => {
65
+ banana.x += (rng.NextDouble() * Beatmap.MAX_X);
66
+ rng.Next(); // osu!stable retrieved a random banana type
67
+ rng.Next(); // osu!stable retrieved a random banana rotation
68
+ rng.Next(); // osu!stable retrieved a random banana colour
69
+ });
70
+ }
71
+ else if (hitObject instanceof JuiceStream) {
72
+ hitObject.nested.forEach(item => {
73
+ if (item.type === "TinyDroplet") item.x += Math.clamp(rng.Next(-20, 20), -item.x, Beatmap.MAX_X - item.x);
74
+ else if (item.type === "Droplet") rng.Next(); // osu!stable retrieved a random droplet rotation
75
+ });
76
+ }
77
+ }
78
+
79
+ // catch objects
80
+ this.palpableObjects = [];
81
+ this.fullCatchObjects = [];
82
+ for (var i = 0; i < this.HitObjects.length; i++) {
83
+ let hitObject = this.HitObjects[i];
84
+ if (hitObject instanceof Fruit) {
85
+ let pch = new PalpableCatchHitObject({
86
+ type: "Fruit",
87
+ time: hitObject.time,
88
+ x: hitObject.position.x,
89
+ color: hitObject.color,
90
+ radius: this.circleRadius,
91
+ }, this);
92
+
93
+ this.palpableObjects.push(pch);
94
+ this.fullCatchObjects.push(pch);
95
+ }
96
+ else if (hitObject instanceof BananaShower) {
97
+ hitObject.nested.forEach(banana => {
98
+ this.fullCatchObjects.push(banana);
99
+ });
100
+ }
101
+ else if (hitObject instanceof JuiceStream) {
102
+ hitObject.nested.forEach(item => {
103
+ this.fullCatchObjects.push(item);
104
+ if (item.type != "TinyDroplet") this.palpableObjects.push(item);
105
+ });
106
+ }
107
+ }
108
+
109
+ this.palpableObjects.sort((a, b) => a.time - b.time);
110
+ this.fullCatchObjects.sort((a, b) => a.time - b.time);
111
+
112
+ // hyperdash
113
+ let lastDirection = 0;
114
+ let lastExcess = this.halfCatcherWidth;
115
+
116
+ for (let i = 0; i < this.palpableObjects.length - 1; i++) {
117
+ var currentObject = this.palpableObjects[i];
118
+ var nextObject = this.palpableObjects[i + 1];
119
+
120
+ currentObject.hyperDash = false;
121
+
122
+ let thisDirection = nextObject.x > currentObject.x ? 1 : -1;
123
+ let timeToNext = nextObject.time - currentObject.time - 1000 / 60 / 4; // 1/4th of a frame of grace time, taken from osu-stable
124
+ let distanceToNext = Math.abs(nextObject.x - currentObject.x) - (lastDirection == thisDirection ? lastExcess : this.halfCatcherWidth);
125
+ let distanceToHyper = timeToNext * this.BASE_DASH_SPEED - distanceToNext;
126
+
127
+ if (distanceToHyper < 0) {
128
+ currentObject.hyperDash = true;
129
+ lastExcess = this.halfCatcherWidth;
130
+ }
131
+ else {
132
+ lastExcess = Math.clamp(distanceToHyper, 0, this.halfCatcherWidth);
133
+ }
134
+
135
+ lastDirection = thisDirection;
136
+ }
137
+
138
+ }
139
+ Catch.prototype = Object.create(Beatmap.prototype, {
140
+ approachTime: { // droptime
141
+ get: function () {
142
+ return this.ApproachRate < 5
143
+ ? 1800 - this.ApproachRate * 120
144
+ : 1200 - (this.ApproachRate - 5) * 150;
145
+ }
146
+ },
147
+ // https://github.com/itdelatrisu/opsu/commit/8892973d98e04ebaa6656fe2a23749e61a122705
148
+ circleDiameter: {
149
+ get: function () {
150
+ return 108.848 - this.CircleSize * 8.9646;
151
+ }
152
+ }
153
+ });
154
+ Catch.prototype.constructor = Catch;
155
+ Catch.prototype.hitObjectTypes = {};
156
+ Catch.ID = 2;
157
+ Beatmap.modes[Catch.ID] = Catch;
158
+ Catch.DEFAULT_COLORS = [
159
+ 'rgb(255,210,128)',
160
+ 'rgb(128,255,128)',
161
+ 'rgb(128,191,255)',
162
+ 'rgb(191,128,255)'
163
+ ];
164
+ Catch.prototype.update = function (ctx) {
165
+ ctx.translate((Beatmap.WIDTH - Beatmap.MAX_X) / 2, (Beatmap.HEIGHT - Beatmap.MAX_Y) / 2);
166
+ };
167
+ Catch.prototype.draw = function (time, ctx) {
168
+ if (typeof this.tmp.first == 'undefined') {
169
+ this.tmp.first = 0;
170
+ this.tmp.last = -1;
171
+ }
172
+
173
+ while (this.tmp.first < this.fullCatchObjects.length) {
174
+ var catchHitObject = this.fullCatchObjects[this.tmp.first];
175
+ if (time <= catchHitObject.time + this.FALLOUT_TIME) {
176
+ break;
177
+ }
178
+ this.tmp.first++;
179
+ }
180
+ while (this.tmp.last + 1 < this.fullCatchObjects.length &&
181
+ time >= this.fullCatchObjects[this.tmp.last + 1].time - this.approachTime * 1.1) {
182
+ this.tmp.last++;
183
+ }
184
+ for (var i = this.tmp.last; i >= this.tmp.first; i--) {
185
+ var catchHitObject = this.fullCatchObjects[i];
186
+ if (time > catchHitObject.time + this.FALLOUT_TIME) {
187
+ continue;
188
+ }
189
+ catchHitObject.draw(time, ctx);
190
+ }
191
+ };
192
+ Catch.prototype.processBG = function (ctx) {
193
+ let xoffset = (Beatmap.WIDTH - Beatmap.MAX_X) / 2;
194
+ let yoffset = (Beatmap.HEIGHT - Beatmap.MAX_Y) / 2;
195
+ // line
196
+ ctx.beginPath();
197
+ ctx.moveTo(-xoffset, Beatmap.HEIGHT - this.CATCHER_HEIGHT - yoffset);
198
+ ctx.lineTo(Beatmap.WIDTH - xoffset, Beatmap.HEIGHT - this.CATCHER_HEIGHT - yoffset);
199
+ ctx.strokeStyle = '#fff';
200
+ ctx.lineWidth = 1;
201
+ ctx.stroke();
202
+ // plate
203
+ let plateHeight = 20;
204
+ ctx.beginPath();
205
+ ctx.rect(Beatmap.WIDTH / 2 - this.catchWidth / 2 - xoffset, Beatmap.HEIGHT - this.CATCHER_HEIGHT - plateHeight / 2 - yoffset, this.catchWidth, plateHeight);
206
+ ctx.strokeStyle = '#fff';
207
+ ctx.lineWidth = 8;
208
+ ctx.stroke();
209
+ ctx.fillStyle = '#fff';
210
+ ctx.fill();
211
+ };
@@ -0,0 +1,21 @@
1
+ function Fruit(data, beatmap)
2
+ {
3
+ HitObject.call(this, data, beatmap);
4
+ }
5
+ Fruit.prototype = Object.create(HitObject.prototype, {
6
+ newCombo: {
7
+ get: function()
8
+ {
9
+ return this.flag & 4;
10
+ }
11
+ },
12
+ comboSkip: {
13
+ get: function()
14
+ {
15
+ return this.flag >> 4;
16
+ }
17
+ }
18
+ });
19
+ Fruit.prototype.constructor = Fruit;
20
+ Fruit.ID = 1;
21
+ Catch.prototype.hitObjectTypes[Fruit.ID] = Fruit;