nonebot-plugin-osubot 6.24.0__py3-none-any.whl → 6.24.2__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/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/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 +110 -0
- nonebot_plugin_osubot/matcher/preview.py +7 -0
- nonebot_plugin_osubot/pp.py +7 -0
- {nonebot_plugin_osubot-6.24.0.dist-info → nonebot_plugin_osubot-6.24.2.dist-info}/METADATA +2 -2
- {nonebot_plugin_osubot-6.24.0.dist-info → nonebot_plugin_osubot-6.24.2.dist-info}/RECORD +45 -5
- {nonebot_plugin_osubot-6.24.0.dist-info → nonebot_plugin_osubot-6.24.2.dist-info}/WHEEL +0 -0
|
@@ -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;
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
function JuiceStream(data, beatmap)
|
|
2
|
+
{
|
|
3
|
+
Slider.call(this, data, beatmap);
|
|
4
|
+
|
|
5
|
+
var points = data[5].split('|');
|
|
6
|
+
var sliderType = points[0];
|
|
7
|
+
points[0] = this.position;
|
|
8
|
+
for (var i = 1; i < points.length; i++)
|
|
9
|
+
{
|
|
10
|
+
points[i] = new Point(points[i].split(':'));
|
|
11
|
+
}
|
|
12
|
+
this.repeat = data[6] | 0;
|
|
13
|
+
this.pixelLength = +data[7];
|
|
14
|
+
|
|
15
|
+
this.timingPoint = this.beatmap.timingPointAt(this.time);
|
|
16
|
+
this.beatLength = this.timingPoint.beatLength;
|
|
17
|
+
this.timingPointStart = this.timingPoint.time;
|
|
18
|
+
|
|
19
|
+
this.sliderTime = this.beatLength * ( this.pixelLength / this.beatmap.SliderMultiplier ) / 100;
|
|
20
|
+
this.velocityFactor = 100 * this.beatmap.SliderMultiplier / this.beatLength;
|
|
21
|
+
this.tickDistanceFactor = 100 * this.beatmap.SliderMultiplier / this.beatmap.SliderTickRate;
|
|
22
|
+
this.velocity = this.velocityFactor * this.timingPoint.sliderVelocity;
|
|
23
|
+
this.tickDistance = this.tickDistanceFactor * this.timingPoint.sliderVelocity;
|
|
24
|
+
|
|
25
|
+
this.endTime = this.time + this.sliderTime * this.repeat;
|
|
26
|
+
this.duration = this.endTime - this.time;
|
|
27
|
+
|
|
28
|
+
this.spanCount = parseInt(this.repeat);
|
|
29
|
+
|
|
30
|
+
this.curve = Curve.parse(sliderType, points, this.pixelLength);
|
|
31
|
+
|
|
32
|
+
this.endPosition = this.curve.pointAt(1);
|
|
33
|
+
|
|
34
|
+
this.max_length = 100000;
|
|
35
|
+
let length = Math.min(this.max_length, this.pixelLength);
|
|
36
|
+
this.tickDistance = Math.clamp(this.tickDistance, 0, length);
|
|
37
|
+
this.minDistanceFromEnd = this.velocity * 10;
|
|
38
|
+
|
|
39
|
+
this.events = [];
|
|
40
|
+
this.events.push({type: "head", time: this.time, pathProgress: 0});
|
|
41
|
+
if (this.tickDistance != 0) {
|
|
42
|
+
for (let span = 0; span < this.spanCount; span++) {
|
|
43
|
+
let spanStartTime = this.time + span * this.sliderTime;
|
|
44
|
+
let reversed = span % 2 == 1;
|
|
45
|
+
let ticks = this.generateTicks(span, spanStartTime, this.sliderTime, reversed, length, this.tickDistance, this.minDistanceFromEnd);
|
|
46
|
+
if (reversed) ticks = ticks.reverse();
|
|
47
|
+
this.events.push(...ticks);
|
|
48
|
+
if (span < this.spanCount - 1)
|
|
49
|
+
{
|
|
50
|
+
this.events.push({
|
|
51
|
+
type: "repeat",
|
|
52
|
+
time: spanStartTime + this.sliderTime,
|
|
53
|
+
pathProgress: (span + 1) % 2
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let legacyLastTickOffset = 36;
|
|
60
|
+
let finalSpanIndex = this.spanCount - 1;
|
|
61
|
+
let finalSpanStartTime = this.time + finalSpanIndex * this.sliderTime;
|
|
62
|
+
let finalSpanEndTime = Math.max(this.time + this.duration / 2, (finalSpanStartTime + this.sliderTime) - legacyLastTickOffset);
|
|
63
|
+
let finalProgress = (finalSpanEndTime - finalSpanStartTime) / this.sliderTime;
|
|
64
|
+
|
|
65
|
+
if (this.spanCount % 2 == 0) finalProgress = 1 - finalProgress;
|
|
66
|
+
|
|
67
|
+
this.events.push({
|
|
68
|
+
type: "legacyLastTick",
|
|
69
|
+
time: finalSpanEndTime,
|
|
70
|
+
pathProgress: finalProgress
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
this.events.push({
|
|
74
|
+
type: "tail",
|
|
75
|
+
time: this.endTime,
|
|
76
|
+
pathProgress: this.spanCount % 2
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
this.nested = [];
|
|
80
|
+
}
|
|
81
|
+
JuiceStream.prototype = Object.create(Slider.prototype);
|
|
82
|
+
JuiceStream.prototype.constructor = JuiceStream;
|
|
83
|
+
JuiceStream.ID = 2;
|
|
84
|
+
Catch.prototype.hitObjectTypes[JuiceStream.ID] = JuiceStream;
|
|
85
|
+
JuiceStream.prototype.generateTicks = function(spanIndex, spanStartTime, spanDuration, reversed, length, tickDistance, minDistanceFromEnd) {
|
|
86
|
+
let ticks = [];
|
|
87
|
+
for (let d = tickDistance; d <= length; d += tickDistance) {
|
|
88
|
+
if (d >= length - minDistanceFromEnd)
|
|
89
|
+
break;
|
|
90
|
+
|
|
91
|
+
let pathProgress = d / length;
|
|
92
|
+
let timeProgress = reversed ? 1 - pathProgress : pathProgress;
|
|
93
|
+
|
|
94
|
+
ticks.push({type: "tick", time: spanStartTime + timeProgress * spanDuration, pathProgress});
|
|
95
|
+
}
|
|
96
|
+
return ticks;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
JuiceStream.prototype.buildNested = function() {
|
|
100
|
+
this.nested = [];
|
|
101
|
+
|
|
102
|
+
let lastEvent = null;
|
|
103
|
+
for(let i = 0; i < this.events.length; i++) {
|
|
104
|
+
// generate tiny droplets since the last point
|
|
105
|
+
if (lastEvent != null)
|
|
106
|
+
{
|
|
107
|
+
let sinceLastTick = this.events[i].time - lastEvent.time;
|
|
108
|
+
if (sinceLastTick > 80)
|
|
109
|
+
{
|
|
110
|
+
let timeBetweenTiny = sinceLastTick;
|
|
111
|
+
while (timeBetweenTiny > 100) timeBetweenTiny /= 2;
|
|
112
|
+
for (let t = timeBetweenTiny; t < sinceLastTick; t += timeBetweenTiny) {
|
|
113
|
+
let repeat = (t + lastEvent.time - this.time) * this.repeat / this.duration;
|
|
114
|
+
repeat %= 2;
|
|
115
|
+
if (repeat > 1) repeat = 2 - repeat;
|
|
116
|
+
var point = this.curve.pointAt(repeat);
|
|
117
|
+
this.nested.push(new PalpableCatchHitObject({
|
|
118
|
+
type: "TinyDroplet",
|
|
119
|
+
time: t + lastEvent.time,
|
|
120
|
+
x: point.x,
|
|
121
|
+
// x: this.curve.pointAt(lastEvent.pathProgress + (t / sinceLastTick) * (this.events[i].pathProgress - lastEvent.pathProgress)).x,
|
|
122
|
+
color: this.color,
|
|
123
|
+
radius: this.beatmap.tinyRadius,
|
|
124
|
+
}, this.beatmap));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// this also includes LegacyLastTick and this is used for TinyDroplet generation above.
|
|
130
|
+
// this means that the final segment of TinyDroplets are increasingly mistimed where LegacyLastTickOffset is being applied.
|
|
131
|
+
lastEvent = this.events[i];
|
|
132
|
+
|
|
133
|
+
switch (this.events[i].type)
|
|
134
|
+
{
|
|
135
|
+
case "tick":
|
|
136
|
+
this.nested.push(new PalpableCatchHitObject({
|
|
137
|
+
type: "Droplet",
|
|
138
|
+
time: this.events[i].time,
|
|
139
|
+
x: this.curve.pointAt(this.events[i].pathProgress).x,
|
|
140
|
+
color: this.color,
|
|
141
|
+
radius: this.beatmap.smallRadius,
|
|
142
|
+
}, this.beatmap));
|
|
143
|
+
break;
|
|
144
|
+
|
|
145
|
+
case "head":
|
|
146
|
+
case "tail":
|
|
147
|
+
case "repeat":
|
|
148
|
+
this.nested.push(new PalpableCatchHitObject({
|
|
149
|
+
type: "Fruit",
|
|
150
|
+
time: this.events[i].time,
|
|
151
|
+
x: this.curve.pointAt(this.events[i].pathProgress).x,
|
|
152
|
+
color: this.color,
|
|
153
|
+
radius: this.beatmap.circleRadius,
|
|
154
|
+
}, this.beatmap));
|
|
155
|
+
break;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/* TODO BUG!!!
|
|
160
|
+
* 在预览 #4057684 时第一个滑条出现了
|
|
161
|
+
* PalpableCatchHitObject {beatmap: Catch, type: 'TinyDroplet', time: 464.57142857142895, …}
|
|
162
|
+
* PalpableCatchHitObject {beatmap: Catch, type: 'Droplet', time: 464.571428571429, …}
|
|
163
|
+
* 物件数量偏差导致后续随机数错误
|
|
164
|
+
* 暂时找不到原因,可能因为计算精度问题,临时手动将其剔除
|
|
165
|
+
*/
|
|
166
|
+
let tmp_droplets = this.nested.filter((item) => item.type === "Droplet");
|
|
167
|
+
this.nested = this.nested.filter((item) => {
|
|
168
|
+
if (item.type != "TinyDroplet") return true;
|
|
169
|
+
for (let td = 0; td < tmp_droplets.length; td++) {
|
|
170
|
+
if (Math.abs(item.time - tmp_droplets[td].time) < 0.01) return false;
|
|
171
|
+
}
|
|
172
|
+
return true;
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
return this;
|
|
176
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
function HitNote(data, beatmap)
|
|
2
|
+
{
|
|
3
|
+
HitObject.call(this, data, beatmap);
|
|
4
|
+
|
|
5
|
+
this.column = Math.max(1, Math.min((this.position.x / this.beatmap.columnSize + 1) | 0, this.beatmap.keyCount)) - 1;
|
|
6
|
+
}
|
|
7
|
+
HitNote.prototype = Object.create(HitObject.prototype);
|
|
8
|
+
HitNote.prototype.constructor = HitNote;
|
|
9
|
+
HitNote.ID = 1;
|
|
10
|
+
Mania.prototype.hitObjectTypes[HitNote.ID] = HitNote;
|
|
11
|
+
HitNote.prototype.draw = function(scroll, ctx)
|
|
12
|
+
{
|
|
13
|
+
ctx.beginPath();
|
|
14
|
+
ctx.rect(this.position.x, this.beatmap.calcY(this.position.y, scroll) - Mania.COLUMN_WIDTH / 3,
|
|
15
|
+
Mania.COLUMN_WIDTH, Mania.COLUMN_WIDTH / 3);
|
|
16
|
+
ctx.fillStyle = this.color;
|
|
17
|
+
ctx.fill();
|
|
18
|
+
ctx.strokeStyle = '#ccc';
|
|
19
|
+
ctx.lineWidth = 1;
|
|
20
|
+
ctx.stroke();
|
|
21
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
function HoldNote(data, beatmap)
|
|
2
|
+
{
|
|
3
|
+
HitNote.call(this, data, beatmap);
|
|
4
|
+
|
|
5
|
+
this.endTime = data[5].split(':')[0] | 0;
|
|
6
|
+
}
|
|
7
|
+
HoldNote.prototype = Object.create(HitNote.prototype);
|
|
8
|
+
HoldNote.prototype.constructor = HoldNote;
|
|
9
|
+
HoldNote.ID = 128;
|
|
10
|
+
Mania.prototype.hitObjectTypes[HoldNote.ID] = HoldNote;
|
|
11
|
+
HoldNote.WIDTH_SCALE = 0.8;
|
|
12
|
+
HoldNote.OPACITY = 0.88;
|
|
13
|
+
HoldNote.prototype.draw = function(scroll, ctx)
|
|
14
|
+
{
|
|
15
|
+
var sy = this.beatmap.calcY(this.position.y, scroll) - Mania.COLUMN_WIDTH / 3,
|
|
16
|
+
ey = this.beatmap.calcY(this.endPosition.y, scroll) - Mania.COLUMN_WIDTH / 3;
|
|
17
|
+
|
|
18
|
+
var w = Mania.COLUMN_WIDTH * HoldNote.WIDTH_SCALE;
|
|
19
|
+
ctx.globalAlpha = HoldNote.OPACITY;
|
|
20
|
+
ctx.beginPath();
|
|
21
|
+
ctx.rect(this.position.x + (Mania.COLUMN_WIDTH - w) / 2, ey, w, sy - ey);
|
|
22
|
+
ctx.fillStyle = this.color;
|
|
23
|
+
ctx.fill();
|
|
24
|
+
ctx.globalAlpha = 1;
|
|
25
|
+
|
|
26
|
+
ctx.beginPath();
|
|
27
|
+
ctx.rect(this.position.x, sy, Mania.COLUMN_WIDTH, Mania.COLUMN_WIDTH / 3);
|
|
28
|
+
ctx.fill();
|
|
29
|
+
ctx.strokeStyle = '#ccc';
|
|
30
|
+
ctx.lineWidth = 1;
|
|
31
|
+
ctx.stroke();
|
|
32
|
+
|
|
33
|
+
ctx.beginPath();
|
|
34
|
+
ctx.rect(this.position.x, ey, Mania.COLUMN_WIDTH, Mania.COLUMN_WIDTH / 3);
|
|
35
|
+
ctx.fill();
|
|
36
|
+
ctx.stroke();
|
|
37
|
+
};
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
function Mania(osu)
|
|
2
|
+
{
|
|
3
|
+
Scroll.call(this, osu);
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
this.scrollSpeed = Mania.SCROLL_SPEED;
|
|
7
|
+
//this.columnStart = Mania.COLUMN_START;
|
|
8
|
+
this.columnStart = (Beatmap.WIDTH - Mania.COLUMN_WIDTH * this.keyCount) / 2
|
|
9
|
+
|
|
10
|
+
for (var i = 0; i < this.keyCount; i++)
|
|
11
|
+
{
|
|
12
|
+
this.Colors[i] = Mania.DEFAULT_COLORS[i & 1];
|
|
13
|
+
}
|
|
14
|
+
var p = this.keyCount / 2;
|
|
15
|
+
if (this.keyCount & 1)
|
|
16
|
+
{
|
|
17
|
+
this.Colors[p | 0] = Mania.DEFAULT_COLORS[2];
|
|
18
|
+
}
|
|
19
|
+
else
|
|
20
|
+
{
|
|
21
|
+
this.Colors = this.Colors.slice(0, p).concat(this.Colors.slice(p - 1));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
for (var i = 0; i < this.HitObjects.length; i++)
|
|
26
|
+
{
|
|
27
|
+
var hitObject = this.HitObjects[i];
|
|
28
|
+
hitObject.color = this.Colors[hitObject.column];
|
|
29
|
+
hitObject.position.x = Mania.COLUMN_WIDTH * hitObject.column;
|
|
30
|
+
hitObject.position.y = this.scrollAt(hitObject.time);
|
|
31
|
+
hitObject.endPosition.y = this.scrollAt(hitObject.endTime);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
Mania.prototype = Object.create(Scroll.prototype, {
|
|
35
|
+
keyCount: {
|
|
36
|
+
get: function()
|
|
37
|
+
{
|
|
38
|
+
return this.CircleSize;
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
columnSize: {
|
|
42
|
+
get: function()
|
|
43
|
+
{
|
|
44
|
+
return Beatmap.MAX_X / this.keyCount;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
Mania.prototype.constructor = Mania;
|
|
49
|
+
Mania.prototype.hitObjectTypes = {};
|
|
50
|
+
Mania.ID = 3;
|
|
51
|
+
Beatmap.modes[Mania.ID] = Mania;
|
|
52
|
+
Mania.DEFAULT_COLORS = [
|
|
53
|
+
'#5bf',
|
|
54
|
+
'#ccc',
|
|
55
|
+
'#da2'
|
|
56
|
+
];
|
|
57
|
+
Mania.COLUMN_START = 130;
|
|
58
|
+
Mania.HIT_POSITION = 400;
|
|
59
|
+
Mania.COLUMN_WIDTH = 30;
|
|
60
|
+
let savedSpeed = window.localStorage.getItem("SCROLL_SPEED");
|
|
61
|
+
Mania.SCROLL_SPEED = (savedSpeed) ? parseInt(savedSpeed) : 20;
|
|
62
|
+
Mania.prototype.calcY = function(y, scroll)
|
|
63
|
+
{
|
|
64
|
+
return Mania.HIT_POSITION - (y - scroll) * this.scrollSpeed * 0.035;
|
|
65
|
+
};
|
|
66
|
+
Mania.prototype.update = function(ctx)
|
|
67
|
+
{
|
|
68
|
+
ctx.translate(this.columnStart, 0);
|
|
69
|
+
};
|
|
70
|
+
Mania.prototype.draw = function(time, ctx)
|
|
71
|
+
{
|
|
72
|
+
if (typeof this.tmp.first == 'undefined')
|
|
73
|
+
{
|
|
74
|
+
this.tmp.first = 0;
|
|
75
|
+
this.tmp.last = -1;
|
|
76
|
+
this.tmp.barLine = 0;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
var scroll = this.scrollAt(time);
|
|
80
|
+
while (this.tmp.first < this.HitObjects.length &&
|
|
81
|
+
time > this.HitObjects[this.tmp.first].endTime)
|
|
82
|
+
{
|
|
83
|
+
this.tmp.first++;
|
|
84
|
+
}
|
|
85
|
+
while (this.tmp.last + 1 < this.HitObjects.length)
|
|
86
|
+
{
|
|
87
|
+
var hitObject = this.HitObjects[this.tmp.last + 1];
|
|
88
|
+
if (this.calcY(hitObject.position.y, scroll) < -Mania.COLUMN_WIDTH)
|
|
89
|
+
{
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
this.tmp.last++;
|
|
93
|
+
}
|
|
94
|
+
while (this.tmp.barLine < this.barLines.length &&
|
|
95
|
+
this.calcY(this.barLines[this.tmp.barLine], scroll) > Beatmap.MAX_Y)
|
|
96
|
+
{
|
|
97
|
+
this.tmp.barLine++;
|
|
98
|
+
}
|
|
99
|
+
for (var i = this.tmp.barLine; i < this.barLines.length && this.calcY(this.barLines[i], scroll) > -Mania.COLUMN_WIDTH; i++)
|
|
100
|
+
{
|
|
101
|
+
var barLine = this.calcY(this.barLines[i], scroll);
|
|
102
|
+
ctx.beginPath();
|
|
103
|
+
ctx.moveTo(0, barLine);
|
|
104
|
+
ctx.lineTo(Mania.COLUMN_WIDTH * this.keyCount, barLine);
|
|
105
|
+
ctx.strokeStyle = '#fff';
|
|
106
|
+
ctx.lineWidth = 1;
|
|
107
|
+
ctx.stroke();
|
|
108
|
+
}
|
|
109
|
+
for (var i = this.tmp.first; i <= this.tmp.last; i++)
|
|
110
|
+
{
|
|
111
|
+
var hitObject = this.HitObjects[i];
|
|
112
|
+
if (time > hitObject.endTime)
|
|
113
|
+
{
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
hitObject.draw(scroll, ctx);
|
|
117
|
+
}
|
|
118
|
+
ctx.clearRect(0, Mania.HIT_POSITION, Beatmap.WIDTH, Beatmap.HEIGHT - Mania.HIT_POSITION);
|
|
119
|
+
};
|
|
120
|
+
Mania.prototype.processBG = function(ctx)
|
|
121
|
+
{
|
|
122
|
+
ctx.beginPath();
|
|
123
|
+
ctx.rect(0, 0, Mania.COLUMN_WIDTH * this.keyCount, Beatmap.HEIGHT);
|
|
124
|
+
ctx.strokeStyle = '#ddd';
|
|
125
|
+
ctx.lineWidth = 8;
|
|
126
|
+
ctx.stroke();
|
|
127
|
+
ctx.fillStyle = '#000';
|
|
128
|
+
ctx.fill();
|
|
129
|
+
|
|
130
|
+
for (var i = 0; i < this.keyCount; i++)
|
|
131
|
+
{
|
|
132
|
+
var x = Mania.COLUMN_WIDTH * i;
|
|
133
|
+
|
|
134
|
+
ctx.beginPath();
|
|
135
|
+
ctx.moveTo(x, 0);
|
|
136
|
+
ctx.lineTo(x, Mania.HIT_POSITION);
|
|
137
|
+
ctx.strokeStyle = '#fff';
|
|
138
|
+
ctx.lineWidth = 1;
|
|
139
|
+
ctx.stroke();
|
|
140
|
+
|
|
141
|
+
ctx.beginPath();
|
|
142
|
+
ctx.rect(x, Mania.HIT_POSITION, Mania.COLUMN_WIDTH, Beatmap.HEIGHT - Mania.HIT_POSITION);
|
|
143
|
+
ctx.fillStyle = this.Colors[i];
|
|
144
|
+
ctx.fill();
|
|
145
|
+
ctx.strokeStyle = '#fff';
|
|
146
|
+
ctx.lineWidth = 3;
|
|
147
|
+
ctx.stroke();
|
|
148
|
+
}
|
|
149
|
+
var x = Mania.COLUMN_WIDTH * this.keyCount;
|
|
150
|
+
ctx.beginPath();
|
|
151
|
+
ctx.moveTo(x, 0);
|
|
152
|
+
ctx.lineTo(x, Mania.HIT_POSITION);
|
|
153
|
+
ctx.strokeStyle = '#fff';
|
|
154
|
+
ctx.lineWidth = 1;
|
|
155
|
+
ctx.stroke();
|
|
156
|
+
// HIT POSITION
|
|
157
|
+
ctx.beginPath();
|
|
158
|
+
ctx.rect(0, Mania.HIT_POSITION, Mania.COLUMN_WIDTH * this.keyCount, Mania.COLUMN_WIDTH / 3);
|
|
159
|
+
ctx.strokeStyle = '#fff';
|
|
160
|
+
ctx.lineWidth = 2;
|
|
161
|
+
ctx.stroke();
|
|
162
|
+
ctx.fillStyle = '#568';
|
|
163
|
+
ctx.fill();
|
|
164
|
+
};
|