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.
- nonebot_plugin_osubot/api.py +7 -5
- nonebot_plugin_osubot/draw/bmap.py +19 -21
- nonebot_plugin_osubot/draw/bp.py +1 -1
- nonebot_plugin_osubot/draw/echarts.py +8 -2
- nonebot_plugin_osubot/draw/info.py +2 -0
- nonebot_plugin_osubot/draw/map.py +5 -2
- nonebot_plugin_osubot/draw/osu_preview.py +64 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/css/style.css +258 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/README.md +109 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.js +3 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.js.map +1 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.worker.js +3 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/gif.js/gif.worker.js.map +1 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/index.html +437 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/beatmap.js +211 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/hitobject.js +29 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/point.js +55 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/scroll.js +45 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/beatmap/timingpoint.js +35 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/LegacyRandom.js +81 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/PalpableCatchHitObject.js +53 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/bananashower.js +33 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/catch.js +211 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/fruit.js +21 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/catch/juicestream.js +176 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/mania/hitnote.js +21 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/mania/holdnote.js +37 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/mania/mania.js +164 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/preview.js +61 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/bezier2.js +33 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/catmullcurve.js +34 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/centripetalcatmullrom.js +30 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/circumstancedcircle.js +47 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/curve.js +25 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/curvetype.js +17 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/equaldistancemulticurve.js +70 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/curve/linearbezier.js +40 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/hitcircle.js +85 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/slider.js +120 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/spinner.js +56 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/standard/standard.js +170 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/donkat.js +40 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/drumroll.js +34 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/shaker.js +58 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/taiko/taiko.js +120 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/js/util.js +61 -0
- nonebot_plugin_osubot/draw/osu_preview_templates/pic.html +115 -0
- nonebot_plugin_osubot/draw/score.py +4 -4
- nonebot_plugin_osubot/file.py +1 -12
- nonebot_plugin_osubot/mania/__init__.py +9 -10
- nonebot_plugin_osubot/matcher/bp_analyze.py +9 -9
- nonebot_plugin_osubot/matcher/guess.py +3 -3
- nonebot_plugin_osubot/matcher/map_convert.py +12 -7
- nonebot_plugin_osubot/matcher/preview.py +10 -3
- nonebot_plugin_osubot/matcher/recommend.py +7 -12
- nonebot_plugin_osubot/osufile/mods/AP.png +0 -0
- nonebot_plugin_osubot/osufile/mods/CL.png +0 -0
- nonebot_plugin_osubot/osufile/mods/DT.png +0 -0
- nonebot_plugin_osubot/osufile/mods/EZ.png +0 -0
- nonebot_plugin_osubot/osufile/mods/FI.png +0 -0
- nonebot_plugin_osubot/osufile/mods/FL.png +0 -0
- nonebot_plugin_osubot/osufile/mods/HD.png +0 -0
- nonebot_plugin_osubot/osufile/mods/HR.png +0 -0
- nonebot_plugin_osubot/osufile/mods/HT.png +0 -0
- nonebot_plugin_osubot/osufile/mods/MR.png +0 -0
- nonebot_plugin_osubot/osufile/mods/NC.png +0 -0
- nonebot_plugin_osubot/osufile/mods/NF.png +0 -0
- nonebot_plugin_osubot/osufile/mods/PF.png +0 -0
- nonebot_plugin_osubot/osufile/mods/RX.png +0 -0
- nonebot_plugin_osubot/osufile/mods/SD.png +0 -0
- nonebot_plugin_osubot/osufile/mods/SO.png +0 -0
- nonebot_plugin_osubot/osufile/mods/TD.png +0 -0
- nonebot_plugin_osubot/osufile/mods/V2.png +0 -0
- nonebot_plugin_osubot/pp.py +7 -0
- nonebot_plugin_osubot/schema/__init__.py +0 -2
- nonebot_plugin_osubot/schema/beatmapsets.py +42 -0
- nonebot_plugin_osubot/schema/score.py +1 -0
- {nonebot_plugin_osubot-6.23.1.dist-info → nonebot_plugin_osubot-6.24.1.dist-info}/METADATA +2 -2
- {nonebot_plugin_osubot-6.23.1.dist-info → nonebot_plugin_osubot-6.24.1.dist-info}/RECORD +80 -39
- nonebot_plugin_osubot/schema/sayo_beatmap.py +0 -59
- {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;
|