Compare commits
1491 Commits
2025.913.0
...
7d38e6c8eb
| Author | SHA1 | Date | |
|---|---|---|---|
| 7d38e6c8eb | |||
|
|
c4402e9ce5 | ||
|
|
de9cf751d2 | ||
|
|
0988552567 | ||
|
|
0fd0bd3580 | ||
|
|
16bc1de9fd | ||
|
|
0d74983551 | ||
|
|
b46656e7d3 | ||
|
|
482d31d598 | ||
|
|
f9e863af01 | ||
|
|
04767f44bb | ||
|
|
8fe63ade31 | ||
|
|
c1555af620 | ||
|
|
e911217980 | ||
|
|
ba2ae3218e | ||
|
|
b76a7e1bb6 | ||
|
|
6b10ef8709 | ||
|
|
43897457fb | ||
|
|
bb289363a2 | ||
|
|
28a18f768c | ||
|
|
45945e3bb1 | ||
|
|
cab50e94c8 | ||
|
|
ae032622ac | ||
|
|
a0ecbd7c87 | ||
|
|
459d5e8a45 | ||
|
|
9b55e1dfdb | ||
|
|
4c873787c1 | ||
|
|
43af89f75c | ||
|
|
f74a21c1e1 | ||
|
|
a028f0ba4a | ||
|
|
1aa42a73b1 | ||
|
|
d9e182230d | ||
|
|
65b49137ee | ||
|
|
2f96e96576 | ||
|
|
e64e0f0ca9 | ||
|
|
d37f59430b | ||
|
|
d748470754 | ||
|
|
2539bd90fa | ||
|
|
317be21569 | ||
|
|
b1044b6b2d | ||
|
|
c28c64940a | ||
|
|
b4f40639a1 | ||
|
|
7e7421e1ea | ||
|
|
1a8d2855d4 | ||
|
|
54a1417dd8 | ||
|
|
ce542b03db | ||
|
|
f20d182775 | ||
|
|
a7e6286396 | ||
|
|
521a40d860 | ||
|
|
564b6ebd0c | ||
|
|
7dfbab212e | ||
|
|
b831bcbcd4 | ||
|
|
c372f9b8f5 | ||
|
|
b0759ff34d | ||
|
|
d60a12a351 | ||
|
|
d27d0f40c1 | ||
|
|
ee9f8d5e92 | ||
|
|
9c8dfaf386 | ||
|
|
033e13cb3b | ||
|
|
b88cba0829 | ||
|
|
9c489aacf8 | ||
|
|
105342e5bf | ||
|
|
c72b6412ea | ||
|
|
2e659a79ec | ||
|
|
5131b188d1 | ||
|
|
7e2771c3f0 | ||
|
|
5174d8b918 | ||
|
|
32d10406c9 | ||
|
|
0dfb362b2d | ||
|
|
047ea7c09d | ||
|
|
cb597c4120 | ||
|
|
99ab245cf0 | ||
|
|
ee8d99034c | ||
|
|
5b1d4ceb9d | ||
|
|
ccb0224a1b | ||
|
|
5602281bd9 | ||
|
|
fabce18552 | ||
|
|
cb12d35d8f | ||
|
|
efc9a27d2d | ||
|
|
e2cbfb970e | ||
|
|
f39615a374 | ||
|
|
4916c87f14 | ||
|
|
a09489d4c0 | ||
|
|
d139f5997c | ||
|
|
29a39cbfb7 | ||
|
|
c144cf188a | ||
|
|
1e8b9a7639 | ||
|
|
69c2747883 | ||
|
|
d3b48364c5 | ||
|
|
9ae99648fb | ||
|
|
f9f927fa45 | ||
|
|
1153d17153 | ||
|
|
e15cb08b44 | ||
|
|
25d630898b | ||
|
|
48544733c3 | ||
|
|
d33a6d5512 | ||
|
|
110f11fa5e | ||
|
|
fb8c228d32 | ||
|
|
93d1a61dc2 | ||
|
|
83587e2265 | ||
|
|
f15e086bb0 | ||
|
|
9fa78123a6 | ||
|
|
7445efaecd | ||
|
|
86ab507e2e | ||
|
|
cc9a5ede29 | ||
|
|
6e03d5b00e | ||
|
|
71583bc06f | ||
|
|
94cec71502 | ||
|
|
42bf25442b | ||
|
|
fc4e29793d | ||
|
|
8e26cf4e1b | ||
|
|
810edebe87 | ||
|
|
2f459dd94e | ||
|
|
87f323a2e5 | ||
|
|
94d9de955f | ||
|
|
860427e4ae | ||
|
|
5afd6c6835 | ||
|
|
50426eb3c8 | ||
|
|
56bc80ffb9 | ||
|
|
c59e5bf335 | ||
|
|
655d725f0c | ||
|
|
15c49a729e | ||
|
|
3678ea0d0f | ||
|
|
dbce8886f8 | ||
|
|
a1136c3cea | ||
|
|
b613c1dcd5 | ||
|
|
cae8d3f4d4 | ||
|
|
f39b310eb5 | ||
|
|
efd4d12c21 | ||
|
|
60d98f0afd | ||
|
|
01982030ec | ||
|
|
bb83f3dcf2 | ||
|
|
0a4497db3c | ||
|
|
bb04a18060 | ||
|
|
7263551aa8 | ||
|
|
239951eda9 | ||
|
|
5cdf07c7e1 | ||
|
|
2efe0c95e6 | ||
|
|
a616fa61c9 | ||
|
|
e77e08c049 | ||
|
|
5231cfa1c7 | ||
|
|
40b331654e | ||
|
|
5e01dda411 | ||
|
|
5d4bb1bd37 | ||
|
|
1230da33a5 | ||
|
|
57222ea0c7 | ||
|
|
892e34b1f8 | ||
|
|
b8b6327624 | ||
|
|
85b8480e46 | ||
|
|
9e9b5cfc50 | ||
|
|
c9a50b40d0 | ||
|
|
8c21a5ba06 | ||
|
|
2ab7492759 | ||
|
|
cf09ed3e0d | ||
|
|
a774f19aef | ||
|
|
14d8cf7275 | ||
|
|
7d476b4b7c | ||
|
|
de97660fa4 | ||
|
|
5468215de8 | ||
|
|
1885ab86f5 | ||
|
|
586b2987a7 | ||
|
|
9bf52034d7 | ||
|
|
a53ba5e4ef | ||
|
|
35b9c74cf8 | ||
|
|
64a29313a8 | ||
|
|
d5ef0d75fc | ||
|
|
3b3bb266fc | ||
|
|
487347dac6 | ||
|
|
d7648afe96 | ||
|
|
c86f76b972 | ||
|
|
8e5eed63e1 | ||
|
|
b705313d3f | ||
|
|
5dd34f165f | ||
|
|
10651512a5 | ||
|
|
4c2ffa0f79 | ||
|
|
6997f89698 | ||
|
|
0ed4a8dbe5 | ||
|
|
c47f9c5259 | ||
|
|
a401c7d5e9 | ||
|
|
6185a81bd5 | ||
|
|
6d54d20943 | ||
|
|
02fbcaba23 | ||
|
|
7b7777bb56 | ||
|
|
ca7b850c8c | ||
|
|
88e5ac4834 | ||
|
|
b9d5606fd4 | ||
|
|
c8c91cedfa | ||
|
|
0c90cf3cef | ||
|
|
1a0193001d | ||
|
|
6bdb0e1cbb | ||
|
|
0d3b7ab6be | ||
|
|
8202ad18d0 | ||
|
|
fa5a278cf3 | ||
|
|
70321e2f89 | ||
|
|
c1fc1edd9c | ||
|
|
40e55ecb6e | ||
|
|
4a5dbea2a2 | ||
|
|
cffeb92248 | ||
|
|
2c56419fe9 | ||
|
|
add67b95c7 | ||
|
|
6fad798227 | ||
|
|
60690cbccc | ||
|
|
6329e3ee1b | ||
|
|
fa22d1f202 | ||
|
|
12eeab581e | ||
|
|
b5e93b98c9 | ||
|
|
786ea35274 | ||
|
|
d6bf4fd90d | ||
|
|
c407e07514 | ||
|
|
ed0051d119 | ||
|
|
99ea19d55c | ||
|
|
dba17b1fa6 | ||
|
|
fdf28474bf | ||
|
|
42dc73d849 | ||
|
|
6983227240 | ||
|
|
585ce682ef | ||
|
|
3db3b603bc | ||
|
|
1c537a3278 | ||
|
|
c88f10ca1b | ||
|
|
7fef2ce1de | ||
|
|
9a5fd0addb | ||
|
|
9c0b1a4914 | ||
|
|
acdb4477f7 | ||
|
|
4ff29339ed | ||
|
|
f1f4a0001b | ||
|
|
df1dc46603 | ||
|
|
84ec4bb866 | ||
|
|
9f0f9ef229 | ||
|
|
290b141d8f | ||
|
|
7cc025d8f4 | ||
|
|
978fc91b09 | ||
|
|
259c5708f1 | ||
|
|
b7559f93f2 | ||
|
|
c2604e22c7 | ||
|
|
dddd75b7f9 | ||
|
|
d3c9548b52 | ||
|
|
225f4d8814 | ||
|
|
d80934c344 | ||
|
|
6f038bff48 | ||
|
|
98c6f6afcd | ||
|
|
ff28839a09 | ||
|
|
52d5c986ef | ||
|
|
dd9e70b29c | ||
|
|
04e378c09f | ||
|
|
d4cf46e3cd | ||
|
|
42302c45ec | ||
|
|
e2dd4d86b4 | ||
|
|
6693307064 | ||
|
|
f0e7817dda | ||
|
|
a1d325370c | ||
|
|
1e8ffdf128 | ||
|
|
ea0b281f48 | ||
|
|
fdd13cd7e1 | ||
|
|
6354286452 | ||
|
|
6f146a5ce9 | ||
|
|
5d651628bc | ||
|
|
10dc1314f6 | ||
|
|
ce2d54f118 | ||
|
|
042f716b2a | ||
|
|
0ea060c612 | ||
|
|
ea8788a509 | ||
|
|
46b2d5374e | ||
|
|
8860eec9f9 | ||
|
|
8c86ff36a2 | ||
|
|
fdf9092f41 | ||
|
|
76f05a4837 | ||
|
|
ae1402c9cd | ||
|
|
741620d89c | ||
|
|
4ee4aac708 | ||
|
|
dfa7ac2082 | ||
|
|
2a0bafde8c | ||
|
|
91ee5eebc9 | ||
|
|
6bf95068ae | ||
|
|
6d999a8d8e | ||
|
|
c1d9de7e83 | ||
|
|
763dbe1494 | ||
|
|
65f7037e84 | ||
|
|
e62a01cf77 | ||
|
|
a60f262679 | ||
|
|
c0b644c905 | ||
|
|
cf73f8f9e6 | ||
|
|
7608ed4d87 | ||
|
|
eee88a3955 | ||
|
|
676b7a36da | ||
|
|
b5a989d31e | ||
|
|
a6489cd758 | ||
|
|
952fd0d493 | ||
|
|
06b89919be | ||
|
|
e1bde264bc | ||
|
|
e05b6f44b9 | ||
|
|
a8ada50549 | ||
|
|
1add946db4 | ||
|
|
a2ca650a9f | ||
|
|
cd433fea50 | ||
|
|
a6756157d1 | ||
|
|
367d133d2f | ||
|
|
1313883394 | ||
|
|
e8154080b3 | ||
|
|
b4ba327c1c | ||
|
|
c646b4e5ec | ||
|
|
15cb3b7a27 | ||
|
|
0551c75c6b | ||
|
|
2bf0dcf398 | ||
|
|
3302e2e180 | ||
|
|
79f1d77fed | ||
|
|
91718447db | ||
|
|
3f92b451d9 | ||
|
|
ed091dc9cd | ||
|
|
029d544720 | ||
|
|
876dcd060c | ||
|
|
b9a37453f9 | ||
|
|
c5a30d3244 | ||
|
|
96c414be86 | ||
|
|
30a60d83e2 | ||
|
|
ed760e6389 | ||
|
|
5d9ea9d699 | ||
|
|
874e3adcb7 | ||
|
|
e548cd40dc | ||
|
|
7ea1bbf91e | ||
|
|
27abce74ce | ||
|
|
8a581f5a90 | ||
|
|
3f4d1b798e | ||
|
|
d1a231cacf | ||
|
|
9c8d6e63a7 | ||
|
|
5abc0f93fe | ||
|
|
d5aa5b61ad | ||
|
|
f9e70f06b3 | ||
|
|
363b7cf3cb | ||
|
|
eeb4680795 | ||
|
|
f892d5fbaa | ||
|
|
0ba4e9e2a4 | ||
|
|
8de5726aa0 | ||
|
|
d3ed93280a | ||
|
|
37257a7a02 | ||
|
|
df1304af9e | ||
|
|
18fd4758d7 | ||
|
|
9acc632788 | ||
|
|
eb1417696a | ||
|
|
5de23e41cf | ||
|
|
5899800293 | ||
|
|
b15b4e70a5 | ||
|
|
40d8fb6316 | ||
|
|
a8989eb117 | ||
|
|
a81a77c60f | ||
|
|
4726489dba | ||
|
|
38c89a914b | ||
|
|
57f16646a3 | ||
|
|
9bad2c634b | ||
|
|
ae284fcf05 | ||
|
|
8a21c6814c | ||
|
|
f320592229 | ||
|
|
ee5cf25628 | ||
|
|
3e7f0f4c61 | ||
|
|
dda1c7f75b | ||
|
|
7652c91a53 | ||
|
|
1c1a3fbe8d | ||
|
|
7c1b1f4548 | ||
|
|
22082097f8 | ||
|
|
d35658985a | ||
|
|
576be6793b | ||
|
|
5e4e28ef00 | ||
|
|
a2d2c3287b | ||
|
|
23c68cbfea | ||
|
|
3f577aae60 | ||
|
|
2963ebae96 | ||
|
|
3157e82f51 | ||
|
|
b40ffd633f | ||
|
|
48de70e719 | ||
|
|
4f44d13e67 | ||
|
|
9b26b83d55 | ||
|
|
7f99650a04 | ||
|
|
0e8a294400 | ||
|
|
3ae98fd664 | ||
|
|
8c8ba2f3bc | ||
|
|
163ca25907 | ||
|
|
85747f8866 | ||
|
|
d05acc3d4f | ||
|
|
8cbcb0e74f | ||
|
|
d39020038b | ||
|
|
86a3c19547 | ||
|
|
53a5157a2f | ||
|
|
679c6d0229 | ||
|
|
86220622fb | ||
|
|
38360fde7b | ||
|
|
61d0b5a03c | ||
|
|
08364a7b97 | ||
|
|
465ec88371 | ||
|
|
4f2dfccb0f | ||
|
|
43e5aec16e | ||
|
|
59b3afe5aa | ||
|
|
fad53d9134 | ||
|
|
61c4a3dba0 | ||
|
|
8b49572c44 | ||
|
|
78a5654e1f | ||
|
|
2b90cbf59f | ||
|
|
ea289460b0 | ||
|
|
ff3397b6b7 | ||
|
|
a4fe0c924d | ||
|
|
33e49442c6 | ||
|
|
d0ac5cdeae | ||
|
|
23c595a136 | ||
|
|
9916e5bb1c | ||
|
|
25dab7258c | ||
|
|
b7b3e028ab | ||
|
|
88f80799c3 | ||
|
|
5839209d6f | ||
|
|
ff820f730e | ||
|
|
593cc37ea6 | ||
|
|
ebf9c19ad3 | ||
|
|
af08416880 | ||
|
|
3bd2050954 | ||
|
|
351a717795 | ||
|
|
00560cbfba | ||
|
|
b6dc64668e | ||
|
|
e0c4592dc7 | ||
|
|
1fcae16be9 | ||
|
|
212973bd63 | ||
|
|
5cba990940 | ||
|
|
974d3fa5e1 | ||
|
|
2fc621b4f3 | ||
|
|
ff4c281bd9 | ||
|
|
833617e279 | ||
|
|
e539660b14 | ||
|
|
d204b79342 | ||
|
|
54f9360814 | ||
|
|
19cfe9abe6 | ||
|
|
0a2fc12061 | ||
|
|
e1ce1e3188 | ||
|
|
464cc23393 | ||
|
|
338b987ea9 | ||
|
|
04bd381ee3 | ||
|
|
affe295f50 | ||
|
|
bd29c46bd7 | ||
|
|
28a6d6211c | ||
|
|
334a54e6f7 | ||
|
|
a6545bea68 | ||
|
|
7e823af70b | ||
|
|
9f40d630dc | ||
|
|
1cf14952de | ||
|
|
2d119f11ec | ||
|
|
dad138223b | ||
|
|
a23024d80e | ||
|
|
9f57be7410 | ||
|
|
853836a48b | ||
|
|
24a0de1020 | ||
|
|
ebb898f67c | ||
|
|
e2ed5208fe | ||
|
|
e07b828f30 | ||
|
|
e2a245b049 | ||
|
|
57cbe20c12 | ||
|
|
646e6de5df | ||
|
|
191ec072a8 | ||
|
|
1cff386b3a | ||
|
|
71be574c2b | ||
|
|
6e41332ea3 | ||
|
|
3c084c60aa | ||
|
|
3b9b030aad | ||
|
|
d421678d34 | ||
|
|
056d832371 | ||
|
|
4e83814d5a | ||
|
|
8ff2329e22 | ||
|
|
6bf25d700c | ||
|
|
5163b8f5f3 | ||
|
|
2e324fe856 | ||
|
|
8347f83f9c | ||
|
|
e34d266987 | ||
|
|
a6e1713514 | ||
|
|
10ebb5286f | ||
|
|
69fee16eee | ||
|
|
f3fa1122c2 | ||
|
|
0f018988b5 | ||
|
|
4a60d7fe71 | ||
|
|
69250b3260 | ||
|
|
60d9c358b8 | ||
|
|
ef3338ba93 | ||
|
|
99b00ab72f | ||
|
|
56ef5eae14 | ||
|
|
2cb2167765 | ||
|
|
206578bf10 | ||
|
|
36de88f399 | ||
|
|
0bcb3c5839 | ||
|
|
2acc2a84db | ||
|
|
64d16776be | ||
|
|
2d06c2b1a6 | ||
|
|
81f03957d8 | ||
|
|
ecaf3e05d4 | ||
|
|
2d85fe8133 | ||
|
|
0af07b97c5 | ||
|
|
03f44705b3 | ||
|
|
033a73e969 | ||
|
|
1340e18d93 | ||
|
|
43e217120d | ||
|
|
dc53198577 | ||
|
|
95cf050298 | ||
|
|
0bfff2bf88 | ||
|
|
fa32be37d6 | ||
|
|
e4d7bc3896 | ||
|
|
520baf6c50 | ||
|
|
a1d4d44151 | ||
|
|
a3a5b2ca92 | ||
|
|
cb32d2da3e | ||
|
|
4ee7e6f787 | ||
|
|
c2c1fa4d4c | ||
|
|
339aad42a7 | ||
|
|
a2872ee870 | ||
|
|
c6a8d9a150 | ||
|
|
6eec2b0ff8 | ||
|
|
0999e3f048 | ||
|
|
71386fe465 | ||
|
|
f58e4e4862 | ||
|
|
0bebabba94 | ||
|
|
95233fc638 | ||
|
|
277e00c74e | ||
|
|
a25f1cde25 | ||
|
|
2ed37ecbbc | ||
|
|
554961036e | ||
|
|
dbcc7cc09d | ||
|
|
d9dad4c3a8 | ||
|
|
0787345a84 | ||
|
|
9d07ad2761 | ||
|
|
1ab922af12 | ||
|
|
44df9047ae | ||
|
|
17143ca0a8 | ||
|
|
3712093158 | ||
|
|
df524d68fd | ||
|
|
daaea093f0 | ||
|
|
469aa7b303 | ||
|
|
e094eefafb | ||
|
|
4cce6aa123 | ||
|
|
bba4329ab5 | ||
|
|
25ba3f2dc6 | ||
|
|
ecc51d4701 | ||
|
|
32454caaa9 | ||
|
|
0f53886784 | ||
|
|
f598d8b108 | ||
|
|
f273163e58 | ||
|
|
6de1f0cd4d | ||
|
|
c475b4bc4b | ||
|
|
276757315f | ||
|
|
a82d0c3b51 | ||
|
|
4fee1547e3 | ||
|
|
a4215e0442 | ||
|
|
577cf7d1e7 | ||
|
|
09178b5dc4 | ||
|
|
16c4967ee4 | ||
|
|
e526de7f40 | ||
|
|
93a64dad89 | ||
|
|
897cb2c1a9 | ||
|
|
de0c191c47 | ||
|
|
61874e59e0 | ||
|
|
13aeed15f9 | ||
|
|
094860bfea | ||
|
|
44f535dcef | ||
|
|
f5bd888078 | ||
|
|
90d7615432 | ||
|
|
7a32e0eebf | ||
|
|
78043fa782 | ||
|
|
729cd722bd | ||
|
|
8da1fde981 | ||
|
|
1de97712f1 | ||
|
|
83ddcf7b02 | ||
|
|
2e7edf8c1f | ||
|
|
61ecd18d24 | ||
|
|
9e67cf503b | ||
|
|
62fd61def4 | ||
|
|
c120f0ebab | ||
|
|
5bf6a75b50 | ||
|
|
b71a26fcec | ||
|
|
5f9639fc3f | ||
|
|
61bf68f336 | ||
|
|
f581f85eb2 | ||
|
|
b07cd2daa4 | ||
|
|
3b635f6919 | ||
|
|
07817dce70 | ||
|
|
67e0348fa8 | ||
|
|
734c6f933d | ||
|
|
ac213c90cb | ||
|
|
74ca87c252 | ||
|
|
190b5535d7 | ||
|
|
032912e62b | ||
|
|
83f9eba1d1 | ||
|
|
1e79c56240 | ||
| 86f0159e65 | |||
| ae5a64ba81 | |||
|
|
82256ae2de | ||
|
|
1142be45ec | ||
|
|
dcb6d71287 | ||
|
|
881a35b382 | ||
|
|
89d8b402af | ||
|
|
1d351002df | ||
| e3a7ae30cd | |||
| b6f845d99c | |||
|
|
2606f3a0b5 | ||
|
|
1c463aa060 | ||
|
|
7853abe8aa | ||
|
|
1aff418981 | ||
|
|
62e92bb242 | ||
|
|
79151ae5b4 | ||
| a1d6bda63e | |||
| 547d22a4b5 | |||
|
|
c17db2cdd0 | ||
|
|
bbdd70c843 | ||
|
|
4250a54245 | ||
|
|
40fdb8662e | ||
|
|
6ce8b0a4bc | ||
|
|
b30047def6 | ||
|
|
0ffb86262f | ||
|
|
f71eb4b980 | ||
|
|
1faf02e860 | ||
|
|
d700375e55 | ||
|
|
095a67c24e | ||
|
|
86054497d0 | ||
|
|
c4f7dee82b | ||
|
|
22825f6509 | ||
|
|
691e8bcd05 | ||
|
|
e68bab4f4b | ||
|
|
9430a62af4 | ||
| b4c530ac04 | |||
| 5af05d2479 | |||
| 43ab18ffea | |||
| 9f59259a40 | |||
| 82b3015fcc | |||
| 68f92ab57c | |||
| d76d4d9a35 | |||
|
|
bb7417c099 | ||
|
|
066e093987 | ||
|
|
56e0c3e65d | ||
|
|
89d7726903 | ||
|
|
36f1bfef07 | ||
|
|
118f07878a | ||
|
|
e144968893 | ||
|
|
d2ffea41c6 | ||
|
|
a8be9b1381 | ||
|
|
bdac75e542 | ||
|
|
5c2df50714 | ||
|
|
887d280bfa | ||
|
|
42b184f167 | ||
|
|
27737bd4e9 | ||
|
|
84db289779 | ||
|
|
4c0522b795 | ||
|
|
8bb885a0dc | ||
|
|
0b06acb29d | ||
|
|
b129837e57 | ||
|
|
07ea9fe2a4 | ||
|
|
3e221c7f61 | ||
|
|
7106a6a5e5 | ||
|
|
eaf2721f5b | ||
| 490a6fd724 | |||
|
|
59a27dad3d | ||
|
|
4b0017dfea | ||
|
|
f73307876e | ||
|
|
4e4aa44a02 | ||
|
|
d6cd748d2a | ||
| 237e1828f8 | |||
| 3413f722f7 | |||
| 9f779dac03 | |||
| 0727c53cdc | |||
| a57ff24191 | |||
|
|
c23d6b7fd1 | ||
|
|
582ff999aa | ||
|
|
a6c001244f | ||
|
|
a96b024ac5 | ||
|
|
1c10acba76 | ||
|
|
4ae4c700ae | ||
|
|
2be50d917a | ||
|
|
35fdc6f8b9 | ||
|
|
d04029bcc7 | ||
|
|
107098314a | ||
|
|
d1d76a76ba | ||
|
|
fbac5db964 | ||
|
|
5a920d15c1 | ||
|
|
324d088d46 | ||
|
|
1db4b897eb | ||
|
|
8e2230d149 | ||
|
|
8d33c35646 | ||
|
|
c359898a75 | ||
|
|
6343bf7d29 | ||
|
|
b1e27d842b | ||
|
|
28eeb7f743 | ||
|
|
38c3167a9d | ||
|
|
66ebce8c12 | ||
|
|
fed9564b40 | ||
|
|
f595a47059 | ||
|
|
8a9f60df68 | ||
|
|
2d8b1e7152 | ||
|
|
fef8117b5c | ||
|
|
99da986e02 | ||
|
|
1c33291b3f | ||
|
|
c6cc92315c | ||
|
|
12170df80a | ||
|
|
3e4c038a37 | ||
|
|
5d76353ae4 | ||
|
|
0b3ec3f1e1 | ||
|
|
043a1c2793 | ||
|
|
ca8247c667 | ||
|
|
a5ae542502 | ||
|
|
fe5cbc4932 | ||
|
|
0a378e5efd | ||
|
|
2a7e71d7fd | ||
|
|
1d221c1a7a | ||
| bdb3418b67 | |||
|
|
82f4406c79 | ||
|
|
0b4f96efc8 | ||
|
|
92e9a36744 | ||
|
|
c6eba26a67 | ||
|
|
8f927ea7b5 | ||
|
|
a8f058141b | ||
|
|
78c6973298 | ||
|
|
d8d7c80832 | ||
|
|
ae33690632 | ||
|
|
9e2ea63e70 | ||
|
|
6bb25b2abe | ||
|
|
037743e002 | ||
|
|
6244617e5e | ||
|
|
ddfcb4d6da | ||
|
|
2660f4dcb0 | ||
|
|
5a865476ce | ||
|
|
2472c91924 | ||
|
|
db50019f31 | ||
|
|
1e43509e4a | ||
|
|
ded8aaecfd | ||
|
|
75df8e3639 | ||
|
|
0d9a50e839 | ||
|
|
7473c62949 | ||
|
|
8d30e3d852 | ||
|
|
97fdc89fe3 | ||
|
|
f6a6c9f885 | ||
|
|
26c50b874c | ||
|
|
83706b7fb6 | ||
|
|
9e3486d4e6 | ||
|
|
545b13c3fb | ||
|
|
2c9fc32756 | ||
|
|
79bfe7880a | ||
|
|
0786e619f1 | ||
|
|
c968981697 | ||
|
|
45567f19b7 | ||
|
|
f0f4e7c7a5 | ||
|
|
1d353ef637 | ||
|
|
52af905237 | ||
|
|
64668eafb9 | ||
|
|
b0762fc8ec | ||
|
|
d59e9572d2 | ||
|
|
098da946e1 | ||
|
|
510fc506fb | ||
|
|
da09ad9c46 | ||
|
|
aaff7d358f | ||
|
|
a69b2cd803 | ||
|
|
855d5dba3c | ||
|
|
9c981a52f8 | ||
|
|
96de47ac4f | ||
|
|
43834b55f2 | ||
|
|
8fb402665e | ||
|
|
e4975e8d3b | ||
|
|
dbd9f13f2d | ||
|
|
ec890cd459 | ||
|
|
33c8c4d639 | ||
|
|
83ce56b718 | ||
|
|
9d88c761d3 | ||
|
|
49eb013967 | ||
|
|
b6ccc8cae4 | ||
|
|
d0e09e5b5c | ||
|
|
8900c79758 | ||
|
|
fd652982ce | ||
|
|
a2bfb409d2 | ||
| 936640edeb | |||
| 1187d03333 | |||
|
|
26da75ecfb | ||
|
|
9f8554cc13 | ||
|
|
713b6453c0 | ||
|
|
1b3ac49f2a | ||
|
|
d8b71423b0 | ||
|
|
2c40e116e1 | ||
|
|
90e7faf271 | ||
|
|
fc74726d11 | ||
|
|
5d3997152a | ||
|
|
41b56971e5 | ||
|
|
98e7a10e1e | ||
|
|
e99b9984d0 | ||
|
|
38504fed22 | ||
|
|
13dab24d41 | ||
|
|
67530b39cf | ||
|
|
19f5e5ba7c | ||
|
|
56ce955e0c | ||
|
|
73349ab182 | ||
|
|
a6a98fc078 | ||
|
|
a8594f1c08 | ||
|
|
d3860f1630 | ||
|
|
15ee49348d | ||
|
|
908a950cd2 | ||
|
|
df79269e6f | ||
|
|
34146b8bcb | ||
|
|
08ed2844b4 | ||
|
|
871c0ebe3d | ||
|
|
6362cdb675 | ||
|
|
8e78f4dac4 | ||
|
|
fa8d303922 | ||
|
|
d465bee0ab | ||
|
|
721ba8aeba | ||
|
|
1dd026c0f0 | ||
|
|
a873f2be65 | ||
|
|
edf7a126c8 | ||
|
|
f0f33b6df4 | ||
|
|
6052ed790d | ||
|
|
107c481fb9 | ||
|
|
aba567d258 | ||
|
|
094454499c | ||
|
|
c7e1a5770d | ||
|
|
a8ac82aa1f | ||
|
|
47faf774b0 | ||
|
|
be77257ddb | ||
|
|
397041099e | ||
|
|
4b59a4657f | ||
|
|
02090bf6c4 | ||
| 3bd996ee43 | |||
| 37b9f91d42 | |||
|
|
603c77e3e9 | ||
|
|
f284864f96 | ||
| 1a5a5606dc | |||
|
|
fa1bf7bd96 | ||
|
|
ef4408a73e | ||
|
|
6f7f9802bd | ||
| 87ff1051e9 | |||
|
|
277f4268db | ||
|
|
80fbcd5fbd | ||
|
|
9c2319b989 | ||
|
|
a040143825 | ||
|
|
80474565fc | ||
| 2e4b0ff197 | |||
| 499f410c94 | |||
| 616c0d8ecd | |||
| ed889138a0 | |||
|
|
89f2c7160d | ||
|
|
f0ca079fe6 | ||
|
|
fbd83cb048 | ||
|
|
843c318ec1 | ||
|
|
19b6761697 | ||
|
|
bb017ade64 | ||
|
|
549cc08bfe | ||
|
|
96dd95940f | ||
|
|
a30f08be80 | ||
|
|
0c341c1f3e | ||
|
|
ae5584bd88 | ||
|
|
edf08b176a | ||
| 18075bef29 | |||
| bc7780a870 | |||
| 8930b8fadb | |||
| 2d457f4305 | |||
| a784734f94 | |||
|
|
7b952b83bf | ||
|
|
214122f633 | ||
|
|
76c0bd4750 | ||
|
|
4bf3d9397f | ||
|
|
fe56ba2921 | ||
|
|
1ca4c8860b | ||
|
|
1e05613859 | ||
|
|
424ef9237f | ||
|
|
e541e917a4 | ||
|
|
7796394685 | ||
|
|
32900f563c | ||
|
|
e349a597ba | ||
|
|
8b778e8106 | ||
|
|
ce5e54c9d2 | ||
| ecfd4764e7 | |||
| f5ca5083d6 | |||
| 1d7c77d8d6 | |||
| 774e52fbd6 | |||
|
|
45e8df7af2 | ||
|
|
1c30cb8371 | ||
| a9d7a9d5d5 | |||
| f7069b1009 | |||
| c3ce5dc787 | |||
| 98076e2092 | |||
| b7d1092f90 | |||
| 08db90c278 | |||
|
|
bd4ed49c06 | ||
| b7e36164c3 | |||
|
|
1e91dde92e | ||
|
|
a593a40429 | ||
|
|
02b88de76e | ||
|
|
435cd272ea | ||
| 0f5f13858d | |||
|
|
b64abbf1f5 | ||
|
|
4265e72180 | ||
| 89a0c75156 | |||
|
|
72507b80c7 | ||
| ab7e5c94f1 | |||
| 8dc9ea4553 | |||
| dcf553c252 | |||
|
|
cb9d9734d6 | ||
|
|
5763b7dbe9 | ||
|
|
e1baa03622 | ||
|
|
4f783f8c41 | ||
|
|
4c72a60ee2 | ||
| 43f3a506ea | |||
| ab51579c27 | |||
| d8e977c05f | |||
|
|
c56c528824 | ||
|
|
013de9f85d | ||
|
|
cd6c9405fe | ||
|
|
1df640898f | ||
|
|
7b55b9e4f2 | ||
|
|
822cb9e2fb | ||
| c023767df9 | |||
|
|
680614fbee | ||
|
|
cb8ddc706f | ||
|
|
04d2ce150a | ||
|
|
eaffb89b4c | ||
|
|
650a61539b | ||
|
|
75bc934aa5 | ||
|
|
8d80e2bd2c | ||
|
|
34a3b1ba78 | ||
|
|
b354fa4472 | ||
|
|
1fbe1bd6c9 | ||
|
|
3c215f6574 | ||
|
|
8c28d26130 | ||
|
|
933fbd274d | ||
|
|
55ae7e8bb8 | ||
|
|
4a22ef88ce | ||
|
|
43ca046f9b | ||
|
|
dbefba57ce | ||
|
|
20904de276 | ||
|
|
6a6c7ad3ba | ||
|
|
fb2fe65a77 | ||
|
|
4662c5d678 | ||
|
|
243cd9c073 | ||
|
|
e8db35a5c9 | ||
|
|
d98cb9ca45 | ||
|
|
a7e4aa8b12 | ||
|
|
0f54608cee | ||
|
|
f8331e0b28 | ||
|
|
6ff2a6225d | ||
|
|
a8020dea7c | ||
|
|
88dd458394 | ||
|
|
23cb7f3b23 | ||
|
|
7da051b144 | ||
|
|
78f639d760 | ||
|
|
4ea03d0e07 | ||
|
|
4d706b12ac | ||
|
|
c44f701abe | ||
|
|
4c81d661aa | ||
|
|
f4049c7ec1 | ||
|
|
645d27bb32 | ||
|
|
73f1849365 | ||
|
|
89b443bccc | ||
|
|
be9170832c | ||
|
|
9db200ed41 | ||
|
|
1ab017d4e2 | ||
|
|
2413e98108 | ||
|
|
65fb5311ea | ||
|
|
14cdc40f0f | ||
|
|
9a393f912b | ||
|
|
a9ca4634fc | ||
|
|
bdcc0ee937 | ||
|
|
6f94b1ab6d | ||
|
|
b20a41c1e8 | ||
|
|
d0ce74063d | ||
|
|
373162df02 | ||
|
|
8e0c9281d3 | ||
|
|
8755a01622 | ||
|
|
901044d690 | ||
|
|
25a1a1ba37 | ||
|
|
73e05e3fae | ||
|
|
2a01e3d148 | ||
|
|
cf0e5edf34 | ||
|
|
a825104688 | ||
|
|
ea1798d731 | ||
|
|
a435dfe93e | ||
|
|
5c1171f358 | ||
|
|
3fcc626e29 | ||
|
|
7ff6edeb64 | ||
|
|
657bc31539 | ||
|
|
f9f7740acb | ||
|
|
5e4dd77e64 | ||
|
|
ce96c0b037 | ||
|
|
5af9bb784b | ||
|
|
4c60df21db | ||
|
|
3c6fb14a32 | ||
|
|
3afc7b045c | ||
|
|
2f2847f1dd | ||
|
|
ee7c52465b | ||
|
|
beb977892e | ||
|
|
7203f419a2 | ||
|
|
722cfb72d8 | ||
|
|
5da132cc2f | ||
|
|
9fac96cf07 | ||
|
|
fadcb9882c | ||
|
|
0610781c6c | ||
|
|
e9260de56f | ||
|
|
2d177226fd | ||
|
|
bd912710f1 | ||
|
|
4e76bd0f24 | ||
|
|
050c10cec2 | ||
|
|
b4fd7ec10f | ||
|
|
cbe7da99ad | ||
|
|
9a965a2546 | ||
|
|
7b0121a430 | ||
|
|
627fec2e3a | ||
|
|
c779e142e6 | ||
|
|
89fffa5a1a | ||
|
|
6d597fc815 | ||
|
|
a78b456e20 | ||
|
|
9237c76942 | ||
|
|
378c64b7f8 | ||
|
|
87b66685d6 | ||
|
|
c524bf5432 | ||
|
|
a40230da4b | ||
|
|
b1a421c22b | ||
|
|
9601708087 | ||
|
|
22f11b6fa5 | ||
|
|
f95d0d214e | ||
|
|
0205cf0fb9 | ||
|
|
8b2b6517ca | ||
|
|
ce3b8bc77b | ||
|
|
98829bf857 | ||
|
|
3c37ac1718 | ||
|
|
f8769d2e44 | ||
|
|
4d66762898 | ||
|
|
e61ae7ab8a | ||
|
|
98eb29c43d | ||
|
|
bb578d254d | ||
|
|
b7c07ad0e5 | ||
|
|
08621c4cc9 | ||
|
|
be9b99f975 | ||
|
|
765b9a20b5 | ||
|
|
473fb5720c | ||
|
|
5faf791ca0 | ||
|
|
9ca47fc53a | ||
|
|
79a76ce587 | ||
|
|
72fa1553c3 | ||
|
|
afdebcf188 | ||
|
|
954061b00b | ||
|
|
b74962af92 | ||
|
|
1af462b692 | ||
|
|
0558f9f2d9 | ||
|
|
763739e877 | ||
|
|
f96be84c57 | ||
|
|
613c208362 | ||
|
|
a3c78de710 | ||
|
|
e240817087 | ||
|
|
ddb844f81b | ||
|
|
b6f4175939 | ||
|
|
90d1725603 | ||
|
|
819da1bc38 | ||
|
|
33e42d2809 | ||
|
|
78eaad13ae | ||
|
|
511921c1f7 | ||
|
|
e2681c4163 | ||
|
|
1f2f86b016 | ||
|
|
fa7bd482d2 | ||
|
|
1a49d030a0 | ||
|
|
03adae4417 | ||
|
|
5a38e1537b | ||
|
|
6ac8e59a11 | ||
|
|
a816977208 | ||
|
|
f0bfb4becc | ||
|
|
ec6ffb3403 | ||
|
|
6ded2e3de7 | ||
|
|
6c7eafde1a | ||
|
|
14d0982b6c | ||
|
|
29787360ba | ||
|
|
6b56a0611b | ||
|
|
0f1bf35bd9 | ||
|
|
b600860540 | ||
|
|
ae7ba034a7 | ||
|
|
0cb521798d | ||
|
|
1ee24521b8 | ||
|
|
efe7d92096 | ||
|
|
4f478db056 | ||
|
|
646cb71b77 | ||
|
|
ce3e3d17fa | ||
|
|
d062c99666 | ||
|
|
803737c947 | ||
|
|
44a427f4e5 | ||
|
|
85ab0d621c | ||
|
|
1591d49143 | ||
|
|
b9de7ba196 | ||
|
|
dfa8d4fe7c | ||
|
|
5eda9a0fd7 | ||
|
|
ca8fc81a7e | ||
|
|
82bcbb53dd | ||
|
|
9a089315b8 | ||
|
|
baea05a0a1 | ||
|
|
c361e6d3c2 | ||
|
|
a4a2e4e639 | ||
|
|
5fc8cde0f7 | ||
|
|
a2098b633a | ||
|
|
0a3665c43d | ||
|
|
c34b2ffc05 | ||
|
|
4ebd97b804 | ||
|
|
dcb30ed5b3 | ||
|
|
a29a5ab7e6 | ||
|
|
62599de649 | ||
|
|
4cac1781c5 | ||
|
|
fcf6d04791 | ||
|
|
c6fcba7e1c | ||
|
|
47b95de06d | ||
|
|
4e4eba2070 | ||
|
|
2ec0cbe5db | ||
|
|
0644543e28 | ||
|
|
23933452fe | ||
|
|
61547d6b38 | ||
|
|
0b84916c3e | ||
|
|
3120871298 | ||
|
|
2dbfdc3d2c | ||
|
|
0af3f15c7c | ||
|
|
594b8c1a60 | ||
|
|
0269257287 | ||
|
|
03a5aedf99 | ||
|
|
1ec6735a35 | ||
|
|
fbaf27e3db | ||
|
|
45eb34ecde | ||
|
|
10beab6ad3 | ||
|
|
70188d4fab | ||
|
|
1ce846294b | ||
|
|
4be29425a0 | ||
|
|
db3cc583e6 | ||
|
|
fec7ef7624 | ||
|
|
6e378ad5af | ||
|
|
8f8f605748 | ||
|
|
5f9ade6610 | ||
|
|
c8762762f9 | ||
|
|
9333ef361b | ||
|
|
1cf9c04756 | ||
|
|
67849ca418 | ||
|
|
0777bdbfc5 | ||
|
|
798f6bdcc7 | ||
|
|
f38162c550 | ||
|
|
b663fe17ab | ||
|
|
3c1d45b896 | ||
|
|
259bc53699 | ||
|
|
87834d1693 | ||
|
|
f1539167eb | ||
|
|
ff6f797a3e | ||
|
|
bfa45a23ce | ||
|
|
1a569e9e2a | ||
|
|
98762ce09e | ||
|
|
8f6f859c15 | ||
|
|
cf1834b080 | ||
|
|
a2bae15db1 | ||
|
|
c80fe7ab82 | ||
|
|
d85c2ee623 | ||
|
|
b4b26e3a1d | ||
|
|
159349a64b | ||
|
|
81a529200d | ||
|
|
6fa4a7152f | ||
|
|
508c37c27b | ||
|
|
95f86a5c0e | ||
|
|
cd62f66d79 | ||
|
|
3fbe777f33 | ||
|
|
b8ceb91a78 | ||
|
|
9f61284371 | ||
|
|
3f18a1312e | ||
|
|
17758d5934 | ||
|
|
eaebe99a5c | ||
|
|
1edbb1d586 | ||
|
|
a060ddb543 | ||
|
|
f488974d39 | ||
|
|
8e01fb70c3 | ||
|
|
a3f635588c | ||
|
|
f8d3285ab4 | ||
|
|
a73c325235 | ||
|
|
97739c39e7 | ||
|
|
b58f03bc36 | ||
|
|
d870547a18 | ||
|
|
28c846b4d9 | ||
|
|
8e36533f65 | ||
|
|
e183e6bb88 | ||
|
|
5dc44fbdf9 | ||
|
|
60544bf595 | ||
|
|
8f0b8153eb | ||
|
|
3070a0068a | ||
|
|
c5e17f5f0f | ||
|
|
8439e6ec6c | ||
|
|
9ebc5b0a35 | ||
|
|
0b00191d71 | ||
|
|
0389da4559 | ||
|
|
40c447a792 | ||
|
|
4132a7cd53 | ||
|
|
ca4c033b76 | ||
|
|
85bbe13aa9 | ||
|
|
1f2928bf2f | ||
|
|
94c7489c1c | ||
|
|
3d6a3e3eda | ||
|
|
a0f295d6fe | ||
|
|
3bb6685e75 | ||
|
|
e3459eccf2 | ||
|
|
0d68e5eeeb | ||
|
|
faad1753a4 | ||
|
|
fed04eb63b | ||
|
|
52f82c7e56 | ||
|
|
3fc3a53521 | ||
|
|
2136d95087 | ||
|
|
c58d13b802 | ||
|
|
b477790d3e | ||
|
|
e33de9b658 | ||
|
|
6eaf91d31a | ||
|
|
6da6edd1d1 | ||
|
|
6af5158bb4 | ||
|
|
79c367d208 | ||
|
|
348713d83d | ||
|
|
cab0b3451f | ||
|
|
91019dcdf7 | ||
|
|
0cc2e4eaa0 | ||
|
|
422392233b | ||
|
|
7b1e3cd537 | ||
|
|
30412ba3f2 | ||
|
|
4622d39f41 | ||
|
|
0d5c041cac | ||
|
|
ffe8b9f4c3 | ||
|
|
9ba9966078 | ||
|
|
f1ec04114f | ||
|
|
4337046680 | ||
|
|
1a522a19f1 | ||
|
|
e4c5fc1906 | ||
|
|
568ddc2d2d | ||
|
|
0ebc90462d | ||
|
|
a08f7327b1 | ||
|
|
533c61e719 | ||
|
|
64fba9470d | ||
|
|
743a94bd22 | ||
|
|
bda5737135 | ||
|
|
03bbbebbbc | ||
|
|
97c95de94a | ||
|
|
3dcbcb5f64 | ||
|
|
19718c706a | ||
|
|
4b3d2b0c57 | ||
|
|
df58dc0ca2 | ||
|
|
d08b5a72b7 | ||
|
|
b286f05c78 | ||
|
|
b3ed7717a8 | ||
|
|
bc7e02c30b | ||
|
|
557df19bf4 | ||
|
|
8a450563fd | ||
|
|
f9a226d68e | ||
|
|
dd846dcc52 | ||
|
|
71ae1d34cd | ||
|
|
dd8dfc04b3 | ||
|
|
2f6bd6605f | ||
|
|
e76d1ae619 | ||
|
|
c0a7c97185 | ||
|
|
dbd48bc3a1 | ||
|
|
a2770a8674 | ||
|
|
67041254db | ||
|
|
68d5f53cc7 | ||
|
|
a30c7f51d0 | ||
|
|
4e90a2aee2 | ||
|
|
e24df0b9d0 | ||
|
|
27ff2a7d49 | ||
|
|
3cb85f743a | ||
|
|
43878f6d33 | ||
|
|
60dc2c8876 | ||
|
|
87128453d6 | ||
|
|
ae4e015352 | ||
|
|
007de10e2b | ||
|
|
3d5dc60cfe | ||
|
|
e7076b9582 | ||
|
|
2a85f7b7c8 | ||
|
|
44a1a5ffc7 | ||
|
|
365cdfd40e | ||
|
|
aad321a0b8 | ||
|
|
1867aad1a6 | ||
|
|
37a11b5592 | ||
|
|
565a2866ea | ||
|
|
c9a6a4887c | ||
|
|
9b78187d29 | ||
|
|
0230a27de6 | ||
|
|
ccf3151172 | ||
|
|
b980183e98 | ||
|
|
b7d36cffd4 | ||
|
|
345ae29770 | ||
|
|
6bf589af88 | ||
|
|
03455ba683 | ||
|
|
1f7aa2fe5e | ||
|
|
e26e44cd45 | ||
|
|
5ab40e4b73 | ||
|
|
ee638492bf | ||
|
|
7d81ff8115 | ||
|
|
114e7f5c61 | ||
|
|
e2b9288716 | ||
|
|
919c47b918 | ||
|
|
bc4d5d07d7 | ||
|
|
4b2f3efcbd | ||
|
|
33ddb84633 | ||
|
|
f66c8d10e0 | ||
|
|
38278eaaac | ||
|
|
ac2df49c35 | ||
|
|
2edd49d2c0 | ||
|
|
a078d4bdb4 | ||
|
|
6e39e714e1 | ||
|
|
d512adb971 | ||
|
|
a3e09a1c31 | ||
|
|
e636a09e0f | ||
|
|
3ebb72a20a | ||
|
|
256483165f | ||
|
|
1a084f28ff | ||
|
|
a0ff7728b9 | ||
|
|
9860bba2f3 | ||
|
|
bb9b4a2827 | ||
|
|
057406c910 | ||
|
|
062174d874 | ||
|
|
d31df5bbc7 | ||
|
|
41698d5848 | ||
|
|
838b8d3013 | ||
|
|
2c39e1e9db | ||
|
|
18549ea7dc | ||
|
|
d76dce76ec | ||
|
|
40cbe58220 | ||
|
|
68523a637a | ||
|
|
3f5b71fdc3 | ||
|
|
573d639238 | ||
|
|
82beeec730 | ||
|
|
5336bcd71d | ||
|
|
47b6b70cae | ||
|
|
fd412618db | ||
|
|
9dc79e6f0d | ||
|
|
ba3d7392bf | ||
|
|
bed9fb0ba6 | ||
|
|
9257e62bac | ||
|
|
70f683e7fa | ||
|
|
d1cf248b9a | ||
|
|
295adf9f28 | ||
|
|
6ac4f482ee | ||
|
|
33791318fe | ||
|
|
cf20bbbf80 | ||
|
|
55ef221390 | ||
|
|
0f8d8780d3 | ||
|
|
b743506207 | ||
|
|
0a17a3c4ed | ||
|
|
da80b61f38 | ||
|
|
badeb24d56 | ||
|
|
76c3043913 | ||
|
|
c66cc5ebb1 | ||
|
|
9dc5605d95 | ||
|
|
3af4edf051 | ||
|
|
e9063dcf57 | ||
|
|
d690477776 | ||
|
|
7879e091c0 | ||
|
|
702511c918 | ||
|
|
e1ba1b45b0 | ||
|
|
8ea9e2e4bb | ||
|
|
ef88a3530a | ||
|
|
df795da070 | ||
|
|
12e29f0bcc | ||
|
|
ff54908687 | ||
|
|
3c37fb11be | ||
|
|
3176006510 | ||
|
|
183ccbf792 | ||
|
|
f1ffc1dc33 | ||
|
|
b3cfded8f2 | ||
|
|
67291c1a42 | ||
|
|
93afc83c4b | ||
|
|
57e5fe7265 | ||
|
|
e082d24bab | ||
|
|
13cb5deca3 | ||
|
|
3556d6c8c8 | ||
|
|
83dafb4ef9 | ||
|
|
9df3bd9a98 | ||
|
|
597a06ac38 | ||
|
|
a129345a82 | ||
|
|
8660578d2c | ||
|
|
bf63b6f9f0 | ||
|
|
85ea278e1d | ||
|
|
37e661b27e | ||
|
|
ff6c6083b4 | ||
|
|
aba0d2c1d3 | ||
|
|
3789010dd5 | ||
|
|
82ac42cae3 | ||
|
|
87061959ea | ||
|
|
1840363713 | ||
|
|
b91ff8a5c5 | ||
|
|
9fddce92e9 | ||
|
|
7c5278ea45 | ||
|
|
0e523d3eb7 | ||
|
|
55a4c75e76 | ||
|
|
c07dd72f6d | ||
|
|
c320c9df1c | ||
|
|
c08d88eb7f | ||
|
|
5eaf376a60 | ||
|
|
b26a1b6330 | ||
|
|
6dc3432735 | ||
|
|
e0c86b3048 | ||
|
|
7852df639a | ||
|
|
37f58e5c80 | ||
|
|
0dbee70ca9 | ||
|
|
2749184c38 | ||
|
|
0a3844d3ef | ||
|
|
c7f50f35b7 | ||
|
|
b1bc5cae87 | ||
|
|
9577472c9e | ||
|
|
55fe927af0 | ||
|
|
4ccfebe842 | ||
|
|
b7d6e76d19 | ||
|
|
e34b0659da | ||
|
|
e73e9275ba | ||
|
|
a9c021ce04 | ||
|
|
9a2513230c | ||
|
|
ccc5ca5d80 | ||
|
|
9b9e7a8f75 | ||
|
|
5b781655c1 | ||
|
|
644b797734 | ||
|
|
e5fbf62ff5 | ||
|
|
bcff6be5f6 | ||
|
|
0c68a91b4c | ||
|
|
69a0ac6c76 | ||
|
|
619a6e7321 | ||
|
|
a436372b05 | ||
|
|
449038d070 | ||
|
|
ffab8342f2 | ||
|
|
31188127ef | ||
|
|
48bad31255 | ||
|
|
1a49c81bab | ||
|
|
27db49bad3 | ||
|
|
e6dbb1020c | ||
|
|
e0c11504a2 | ||
|
|
35e1fa6660 | ||
|
|
330b61f4c0 | ||
|
|
3985596602 | ||
|
|
3786efaa5e | ||
|
|
0225c1a867 | ||
|
|
111b98ef8e | ||
|
|
22bfab95b0 | ||
|
|
a78c78ecdd | ||
|
|
84309f57c5 | ||
|
|
6a35b7237b | ||
|
|
90ac249f5e | ||
|
|
087f0565e6 | ||
|
|
038bf3fdda | ||
|
|
61c3aad537 | ||
|
|
3aad0868af | ||
|
|
973c4c8319 | ||
|
|
ac21f8b960 | ||
|
|
0b3b6468a5 | ||
|
|
7d1c54f045 | ||
|
|
dce4132209 | ||
|
|
fa1fea02dc | ||
|
|
802e559472 | ||
|
|
dbb16fc834 | ||
|
|
eaaca60b1d | ||
|
|
803e30f50f | ||
|
|
e54779ceee | ||
|
|
83765abe34 | ||
|
|
28d36dd3bd | ||
|
|
945db7b431 | ||
|
|
56b072cfd9 | ||
|
|
ddf9d6b8c8 | ||
|
|
a75e0c3850 | ||
|
|
f2dcf2024a | ||
|
|
7ec6c8bf57 | ||
|
|
cf4d6bea72 | ||
|
|
d5ef8c8524 | ||
|
|
b783bb70e9 | ||
|
|
19e9bffc11 | ||
|
|
87023b22ea | ||
|
|
7066f3def7 | ||
|
|
699fbb1a85 | ||
|
|
5df41c08f4 | ||
|
|
c4b07413b1 | ||
|
|
6ae8a68389 | ||
|
|
642b938358 | ||
|
|
6a9aeda5d4 | ||
|
|
b982c3cd20 | ||
|
|
366f2469ef | ||
|
|
737ec8b2a8 | ||
|
|
63654ad1e0 | ||
|
|
01d9c526d9 | ||
|
|
ace74824b8 | ||
|
|
ee055ba8f5 | ||
|
|
60eaf088df | ||
|
|
4a343ceaf1 | ||
|
|
553a8601ed | ||
|
|
9314ea94b5 | ||
|
|
d22b3fb200 | ||
|
|
3165b147ee | ||
|
|
ce73dbbcc6 | ||
|
|
4f298760de | ||
|
|
2aeb80a8bd | ||
|
|
7a9d31adb6 | ||
|
|
cf7fdc0627 | ||
|
|
30f9716db9 | ||
|
|
69c90f9926 | ||
|
|
0c3ee1938e | ||
|
|
8b11be5ac0 | ||
|
|
9eadc9f68c | ||
|
|
2c88e60ed3 | ||
|
|
fd504e5641 | ||
|
|
93ed0483b6 | ||
|
|
4dd0672aa5 | ||
|
|
66eff14d2b | ||
|
|
245ade004a | ||
|
|
6cb46106fe | ||
|
|
3666e4c332 |
@@ -21,7 +21,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"ppy.localisationanalyser.tools": {
|
"ppy.localisationanalyser.tools": {
|
||||||
"version": "2024.802.0",
|
"version": "2025.1208.0",
|
||||||
"commands": [
|
"commands": [
|
||||||
"localisation"
|
"localisation"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -19,6 +19,11 @@ indent_style = space
|
|||||||
indent_size = 4
|
indent_size = 4
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
# temporary workaround for https://youtrack.jetbrains.com/issue/RIDER-130051/Cannot-resolve-symbol-inspections-incorrectly-firing-for-xmldoc-protected-member-references
|
||||||
|
resharper_c_sharp_warnings_cs1574_cs1584_cs1581_cs1580_highlighting = hint
|
||||||
|
# temporary workaround for https://youtrack.jetbrains.com/issue/RIDER-130381/Rider-does-not-respect-propagated-NoWarn-CS1591?backToIssues=false
|
||||||
|
dotnet_diagnostic.CS1591.severity = none
|
||||||
|
|
||||||
#license header
|
#license header
|
||||||
file_header_template = Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.\nSee the LICENCE file in the repository root for full licence text.
|
file_header_template = Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.\nSee the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
|||||||
12
.github/ISSUE_TEMPLATE/config.yml
vendored
12
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,12 +1,6 @@
|
|||||||
blank_issues_enabled: false
|
blank_issues_enabled: true
|
||||||
contact_links:
|
contact_links:
|
||||||
- name: Help
|
- name: Help
|
||||||
url: https://github.com/ppy/osu/discussions/categories/q-a
|
url: https://t.me/jvnkosu_chat
|
||||||
about: osu! not working or performing as you'd expect? Not sure it's a bug? Check the Q&A section!
|
about: Your jvnkosu! is not working right? Please contact us using our Telegram chat
|
||||||
- name: Suggestions or feature request
|
|
||||||
url: https://github.com/ppy/osu/discussions/categories/ideas
|
|
||||||
about: Got something you think should change or be added? Search for or start a new discussion!
|
|
||||||
- name: osu!stable issues
|
|
||||||
url: https://github.com/ppy/osu-stable-issues
|
|
||||||
about: For osu!(stable) - ie. the current "live" game version, check out the dedicated repository. Note that this is for serious bug reports only, not tech support.
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
name: Update osu-web mod definitions
|
name: Update osu-web mod definitions (DO NOT USE YET!!!!!)
|
||||||
on:
|
on:
|
||||||
push:
|
workflow_dispatch:
|
||||||
tags:
|
# push:
|
||||||
- '*'
|
# tags:
|
||||||
|
# - '*'
|
||||||
|
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read # to fetch code (actions/checkout)
|
contents: read # to fetch code (actions/checkout)
|
||||||
10
.github/workflows/ci.yml
vendored
10
.github/workflows/ci.yml
vendored
@@ -1,4 +1,10 @@
|
|||||||
on: [push, pull_request]
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
|
||||||
name: Continuous Integration
|
name: Continuous Integration
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
@@ -33,7 +39,7 @@ jobs:
|
|||||||
key: inspectcode-${{ hashFiles('.config/dotnet-tools.json', '.github/workflows/ci.yml', 'osu.sln*', 'osu*.slnf', '.editorconfig', '.globalconfig', 'CodeAnalysis/*', '**/*.csproj', '**/*.props') }}
|
key: inspectcode-${{ hashFiles('.config/dotnet-tools.json', '.github/workflows/ci.yml', 'osu.sln*', 'osu*.slnf', '.editorconfig', '.globalconfig', 'CodeAnalysis/*', '**/*.csproj', '**/*.props') }}
|
||||||
|
|
||||||
- name: Dotnet code style
|
- name: Dotnet code style
|
||||||
run: dotnet build -c Debug -warnaserror osu.Desktop.slnf -p:EnforceCodeStyleInBuild=true
|
run: dotnet build -c Debug -warnaserror osu.Desktop.slnf
|
||||||
|
|
||||||
- name: CodeFileSanity
|
- name: CodeFileSanity
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
3
.github/workflows/deploy.yml
vendored
3
.github/workflows/deploy.yml
vendored
@@ -4,6 +4,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- '*'
|
- '*'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
notify_pending_production_deploy:
|
notify_pending_production_deploy:
|
||||||
@@ -12,7 +13,7 @@ jobs:
|
|||||||
- name: Submit pending deployment notification
|
- name: Submit pending deployment notification
|
||||||
run: |
|
run: |
|
||||||
export TITLE="Pending osu Production Deployment: $GITHUB_REF_NAME"
|
export TITLE="Pending osu Production Deployment: $GITHUB_REF_NAME"
|
||||||
export URL="https://github.com/ppy/osu/actions/runs/$GITHUB_RUN_ID"
|
export URL="https://github.com/jvnkosu-dev/client/actions/runs/$GITHUB_RUN_ID"
|
||||||
export DESCRIPTION="Awaiting approval for building NuGet packages for tag $GITHUB_REF_NAME:
|
export DESCRIPTION="Awaiting approval for building NuGet packages for tag $GITHUB_REF_NAME:
|
||||||
[View Workflow Run]($URL)"
|
[View Workflow Run]($URL)"
|
||||||
export ACTOR_ICON="https://avatars.githubusercontent.com/u/$GITHUB_ACTOR_ID"
|
export ACTOR_ICON="https://avatars.githubusercontent.com/u/$GITHUB_ACTOR_ID"
|
||||||
|
|||||||
8
.github/workflows/sentry-release.yml
vendored
8
.github/workflows/sentry-release.yml
vendored
@@ -21,9 +21,9 @@ jobs:
|
|||||||
uses: getsentry/action-release@v1
|
uses: getsentry/action-release@v1
|
||||||
env:
|
env:
|
||||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||||
SENTRY_ORG: ppy
|
SENTRY_ORG: jvnkosu
|
||||||
SENTRY_PROJECT: osu
|
SENTRY_PROJECT: client
|
||||||
SENTRY_URL: https://sentry.ppy.sh/
|
SENTRY_URL: https://satellite.jvnko.boats/
|
||||||
with:
|
with:
|
||||||
environment: production
|
environment: production
|
||||||
version: osu@${{ github.ref_name }}
|
version: jvnkosu@${{ github.ref_name }}
|
||||||
|
|||||||
@@ -55,9 +55,7 @@ When in doubt, it's probably best to start with a discussion first. We will esca
|
|||||||
|
|
||||||
While pull requests from unaffiliated contributors are welcome, please note that due to significant community interest and limited review throughput, the core team's primary focus is on the issues which are currently [on the roadmap](https://github.com/orgs/ppy/projects/7/views/6). Reviewing PRs that fall outside of the scope of the roadmap is done on a best-effort basis, so please be aware that it may take a while before a core maintainer gets around to review your change.
|
While pull requests from unaffiliated contributors are welcome, please note that due to significant community interest and limited review throughput, the core team's primary focus is on the issues which are currently [on the roadmap](https://github.com/orgs/ppy/projects/7/views/6). Reviewing PRs that fall outside of the scope of the roadmap is done on a best-effort basis, so please be aware that it may take a while before a core maintainer gets around to review your change.
|
||||||
|
|
||||||
The [issue tracker](https://github.com/ppy/osu/issues) should provide plenty of issues to start with. We also have a [`good first issue`](https://github.com/ppy/osu/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) label, although from experience it is not used very often, as it is relatively rare that we can spot an issue that will definitively be a good first issue for a new contributor regardless of their programming experience.
|
The [issue tracker](https://github.com/ppy/osu/issues) should provide plenty of issues to start with. In the case of simple issues, a direct PR is okay. However, if you decide to work on an existing issue which doesn't seem trivial, **please ask us first**. This way we can try to estimate if it is a good fit for you and provide the correct direction on how to address it. In addition, note that while we do not rule out external contributors from working on roadmapped issues, we will generally prefer to handle them ourselves unless they're not very time sensitive.
|
||||||
|
|
||||||
In the case of simple issues, a direct PR is okay. However, if you decide to work on an existing issue which doesn't seem trivial, **please ask us first**. This way we can try to estimate if it is a good fit for you and provide the correct direction on how to address it. In addition, note that while we do not rule out external contributors from working on roadmapped issues, we will generally prefer to handle them ourselves unless they're not very time sensitive.
|
|
||||||
|
|
||||||
If you'd like to propose a subjective change to one of the visual aspects of the game, or there is a bigger task you'd like to work on, but there is no corresponding issue or discussion thread yet for it, **please open a discussion or issue first** to avoid wasted effort. This in particular applies if you want to work on [one of the available designs from the osu! Figma master library](https://www.figma.com/file/VIkXMYNPMtQem2RJg9k2iQ/Master-Library).
|
If you'd like to propose a subjective change to one of the visual aspects of the game, or there is a bigger task you'd like to work on, but there is no corresponding issue or discussion thread yet for it, **please open a discussion or issue first** to avoid wasted effort. This in particular applies if you want to work on [one of the available designs from the osu! Figma master library](https://www.figma.com/file/VIkXMYNPMtQem2RJg9k2iQ/Master-Library).
|
||||||
|
|
||||||
@@ -73,6 +71,9 @@ Aside from the above, below is a brief checklist of things to watch out when you
|
|||||||
After you're done with your changes and you wish to open the PR, please observe the following recommendations:
|
After you're done with your changes and you wish to open the PR, please observe the following recommendations:
|
||||||
|
|
||||||
- Please submit the pull request from a [topic branch](https://git-scm.com/book/en/v2/Git-Branching-Branching-Workflows#_topic_branch) (not `master`), and keep the *Allow edits from maintainers* check box selected, so that we can push fixes to your PR if necessary.
|
- Please submit the pull request from a [topic branch](https://git-scm.com/book/en/v2/Git-Branching-Branching-Workflows#_topic_branch) (not `master`), and keep the *Allow edits from maintainers* check box selected, so that we can push fixes to your PR if necessary.
|
||||||
|
- Please pick the following target branch for your pull request:
|
||||||
|
- `pp-dev`, if the change impacts star rating or performance points calculations for any of the rulesets,
|
||||||
|
- `master`, otherwise.
|
||||||
- Please avoid pushing untested or incomplete code.
|
- Please avoid pushing untested or incomplete code.
|
||||||
- Please do not force-push or rebase unless we ask you to.
|
- Please do not force-push or rebase unless we ask you to.
|
||||||
- Please do not merge `master` continually if there are no conflicts to resolve. We will do this for you when the change is ready for merge.
|
- Please do not merge `master` continually if there are no conflicts to resolve. We will do this for you when the change is ready for merge.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<PackageType>Template</PackageType>
|
<PackageType>Template</PackageType>
|
||||||
<PackageId>ppy.osu.Game.Templates</PackageId>
|
<PackageId>jvnkosu.Client.Templates</PackageId>
|
||||||
<Title>osu! templates</Title>
|
<Title>osu! templates</Title>
|
||||||
<Authors>ppy Pty Ltd</Authors>
|
<Authors>ppy Pty Ltd</Authors>
|
||||||
<PackageLicenseUrl>https://github.com/ppy/osu/blob/master/LICENCE</PackageLicenseUrl>
|
<PackageLicenseUrl>https://github.com/ppy/osu/blob/master/LICENCE</PackageLicenseUrl>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2025.908.0" />
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2026.303.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<!-- Fody does not handle Android build well, and warns when unchanged.
|
<!-- Fody does not handle Android build well, and warns when unchanged.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="sh.ppy.osulazer" android:installLocation="auto">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="boats.jvnko.osu.android" android:installLocation="auto">
|
||||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="34" />
|
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="34" />
|
||||||
<application android:allowBackup="true"
|
<application android:allowBackup="true"
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace osu.Desktop
|
|||||||
{
|
{
|
||||||
internal partial class DiscordRichPresence : Component
|
internal partial class DiscordRichPresence : Component
|
||||||
{
|
{
|
||||||
private const string client_id = "1216669957799018608";
|
private const string client_id = "1440647613358800918";
|
||||||
|
|
||||||
private DiscordRpcClient client = null!;
|
private DiscordRpcClient client = null!;
|
||||||
|
|
||||||
@@ -189,7 +189,7 @@ namespace osu.Desktop
|
|||||||
}
|
}
|
||||||
|
|
||||||
// user party
|
// user party
|
||||||
if (!hideIdentifiableInformation && multiplayerClient.Room != null)
|
if (!hideIdentifiableInformation && multiplayerClient.Room != null && multiplayerClient.Room.Settings.MatchType != MatchType.Matchmaking)
|
||||||
{
|
{
|
||||||
MultiplayerRoom room = multiplayerClient.Room;
|
MultiplayerRoom room = multiplayerClient.Room;
|
||||||
|
|
||||||
|
|||||||
@@ -115,12 +115,10 @@ namespace osu.Desktop
|
|||||||
if (IsFirstRun)
|
if (IsFirstRun)
|
||||||
LocalConfig.SetValue(OsuSetting.ReleaseStream, ReleaseStream.Lazer);
|
LocalConfig.SetValue(OsuSetting.ReleaseStream, ReleaseStream.Lazer);
|
||||||
|
|
||||||
// if (IsPackageManaged)
|
if (IsPackageManaged)
|
||||||
// return new NoActionUpdateManager();
|
return new NoActionUpdateManager();
|
||||||
|
|
||||||
// return new VelopackUpdateManager();
|
return new VelopackUpdateManager(); // yay
|
||||||
|
|
||||||
return new NoActionUpdateManager(); // for now, APIs are useless for actually downloading the releases. TODO: adapt UpdateManager for gitea
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool RestartAppWhenExited()
|
public override bool RestartAppWhenExited()
|
||||||
@@ -150,7 +148,13 @@ namespace osu.Desktop
|
|||||||
|
|
||||||
var iconStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(GetType(), "lazer.ico");
|
var iconStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(GetType(), "lazer.ico");
|
||||||
if (iconStream != null)
|
if (iconStream != null)
|
||||||
|
try
|
||||||
|
{
|
||||||
host.Window.SetIconFromStream(iconStream);
|
host.Window.SetIconFromStream(iconStream);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
host.Window.Title = Name;
|
host.Window.Title = Name;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ namespace osu.Desktop
|
|||||||
|
|
||||||
// While .NET 8 only supports Windows 10 and above, running on Windows 7/8.1 may still work. We are limited by realm currently, as they choose to only support 8.1 and higher.
|
// While .NET 8 only supports Windows 10 and above, running on Windows 7/8.1 may still work. We are limited by realm currently, as they choose to only support 8.1 and higher.
|
||||||
// See https://www.mongodb.com/docs/realm/sdk/dotnet/compatibility/
|
// See https://www.mongodb.com/docs/realm/sdk/dotnet/compatibility/
|
||||||
if (windowsVersion.Major < 6 || (windowsVersion.Major == 6 && windowsVersion.Minor <= 2))
|
if (windowsVersion.Major < 6)
|
||||||
{
|
{
|
||||||
unsafe
|
unsafe
|
||||||
{
|
{
|
||||||
@@ -53,13 +53,26 @@ namespace osu.Desktop
|
|||||||
// We could also better detect compatibility mode if required:
|
// We could also better detect compatibility mode if required:
|
||||||
// https://stackoverflow.com/questions/10744651/how-i-can-detect-if-my-application-is-running-under-compatibility-mode#comment58183249_10744730
|
// https://stackoverflow.com/questions/10744651/how-i-can-detect-if-my-application-is-running-under-compatibility-mode#comment58183249_10744730
|
||||||
SDL3.SDL_ShowSimpleMessageBox(SDL_MessageBoxFlags.SDL_MESSAGEBOX_ERROR,
|
SDL3.SDL_ShowSimpleMessageBox(SDL_MessageBoxFlags.SDL_MESSAGEBOX_ERROR,
|
||||||
"Your operating system is too old to run osu!"u8,
|
"Your operating system is too old to run this game!"u8,
|
||||||
"This version of osu! requires at least Windows 8.1 to run.\n"u8
|
"This version of the game requires at least Windows 8.1 to run reliably.\n"u8
|
||||||
+ "Please upgrade your operating system or consider using an older version of osu!.\n\n"u8
|
+ "You may try to run it on Windows 8 or older, but it's not guaranteed to actually work.\n\n"u8
|
||||||
+ "If you are running a newer version of windows, please check you don't have \"Compatibility mode\" turned on for osu!"u8, null);
|
+ "Please upgrade your operating system or consider using an older game version.\n\n"u8
|
||||||
|
+ "If you are running a newer version of Windows, please check you don't have \"Compatibility mode\" turned on for the game's executable."u8, null);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (windowsVersion.Major == 6 && windowsVersion.Minor <= 2)
|
||||||
|
{
|
||||||
|
unsafe
|
||||||
|
{
|
||||||
|
SDL3.SDL_ShowSimpleMessageBox(SDL_MessageBoxFlags.SDL_MESSAGEBOX_WARNING,
|
||||||
|
"Your operating system is too old to run this game!"u8,
|
||||||
|
"While the version of Windows you're using may be able to launch it, it's likely to work unreliably and crash.\n"u8
|
||||||
|
+ "Please upgrade your operating system or consider using an older game version.\n\n"u8
|
||||||
|
+ "If you are running a newer version of Windows, please check you don't have \"Compatibility mode\" turned on for the game's executable."u8, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NVIDIA profiles are based on the executable name of a process.
|
// NVIDIA profiles are based on the executable name of a process.
|
||||||
@@ -208,9 +221,10 @@ namespace osu.Desktop
|
|||||||
[SupportedOSPlatform("windows")]
|
[SupportedOSPlatform("windows")]
|
||||||
private static void configureWindows(VelopackApp app)
|
private static void configureWindows(VelopackApp app)
|
||||||
{
|
{
|
||||||
app.OnFirstRun(_ => WindowsAssociationManager.InstallAssociations());
|
// we do not want associations here, as that breaks official lazer's associations
|
||||||
app.OnAfterUpdateFastCallback(_ => WindowsAssociationManager.UpdateAssociations());
|
// app.OnFirstRun(_ => WindowsAssociationManager.InstallAssociations());
|
||||||
app.OnBeforeUninstallFastCallback(_ => WindowsAssociationManager.UninstallAssociations());
|
// app.OnAfterUpdateFastCallback(_ => WindowsAssociationManager.UpdateAssociations());
|
||||||
|
// app.OnBeforeUninstallFastCallback(_ => WindowsAssociationManager.UninstallAssociations());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using osu.Framework.Allocation;
|
|||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Localisation;
|
||||||
using osu.Game.Overlays;
|
using osu.Game.Overlays;
|
||||||
using osu.Game.Overlays.Notifications;
|
using osu.Game.Overlays.Notifications;
|
||||||
|
|
||||||
@@ -32,7 +33,7 @@ namespace osu.Desktop.Security
|
|||||||
{
|
{
|
||||||
public ElevatedPrivilegesNotification()
|
public ElevatedPrivilegesNotification()
|
||||||
{
|
{
|
||||||
Text = $"Running osu! as {(RuntimeInfo.IsUnix ? "root" : "administrator")} does not improve performance, may break integrations and poses a security risk. Please run the game as a normal user.";
|
Text = NotificationsStrings.ElevatedPrivileges(RuntimeInfo.IsUnix ? "root" : "Administrator");
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ namespace osu.Desktop.Updater
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
IUpdateSource updateSource = new GithubSource(@"https://github.com/ppy/osu", null, ReleaseStream.Value == Game.Configuration.ReleaseStream.Tachyon);
|
IUpdateSource updateSource = new GiteaSource(@"https://gitea.jvnko.boats/jvnkosu/client", null, ReleaseStream.Value == Game.Configuration.ReleaseStream.Tachyon);
|
||||||
Velopack.UpdateManager updateManager = new Velopack.UpdateManager(updateSource, new UpdateOptions
|
Velopack.UpdateManager updateManager = new Velopack.UpdateManager(updateSource, new UpdateOptions
|
||||||
{
|
{
|
||||||
AllowVersionDowngrade = true
|
AllowVersionDowngrade = true
|
||||||
|
|||||||
@@ -53,8 +53,8 @@ namespace osu.Desktop.Windows
|
|||||||
|
|
||||||
private static readonly UriAssociation[] uri_associations =
|
private static readonly UriAssociation[] uri_associations =
|
||||||
{
|
{
|
||||||
new UriAssociation(@"osu", WindowsAssociationManagerStrings.OsuProtocol, Icons.Lazer),
|
new UriAssociation(@"jvnkosu", WindowsAssociationManagerStrings.OsuProtocol, Icons.Lazer),
|
||||||
new UriAssociation(@"osump", WindowsAssociationManagerStrings.OsuMultiplayer, Icons.Lazer),
|
new UriAssociation(@"jvnkosump", WindowsAssociationManagerStrings.OsuMultiplayer, Icons.Lazer),
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 401 KiB |
@@ -5,7 +5,7 @@ using BenchmarkDotNet.Attributes;
|
|||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
using osu.Game.Screens.Select;
|
using osu.Game.Screens.Select;
|
||||||
using osu.Game.Screens.Select.Carousel;
|
using osu.Game.Tests.NonVisual.Filtering;
|
||||||
|
|
||||||
namespace osu.Game.Benchmarks
|
namespace osu.Game.Benchmarks
|
||||||
{
|
{
|
||||||
@@ -42,7 +42,7 @@ namespace osu.Game.Benchmarks
|
|||||||
Status = BeatmapOnlineStatus.Loved
|
Status = BeatmapOnlineStatus.Loved
|
||||||
};
|
};
|
||||||
|
|
||||||
private CarouselBeatmap carouselBeatmap = null!;
|
private FilterMatchingTest.CarouselBeatmap carouselBeatmap = null!;
|
||||||
private FilterCriteria criteria1 = null!;
|
private FilterCriteria criteria1 = null!;
|
||||||
private FilterCriteria criteria2 = null!;
|
private FilterCriteria criteria2 = null!;
|
||||||
private FilterCriteria criteria3 = null!;
|
private FilterCriteria criteria3 = null!;
|
||||||
@@ -55,7 +55,7 @@ namespace osu.Game.Benchmarks
|
|||||||
var beatmap = getExampleBeatmap();
|
var beatmap = getExampleBeatmap();
|
||||||
beatmap.OnlineID = 20201010;
|
beatmap.OnlineID = 20201010;
|
||||||
beatmap.BeatmapSet = new BeatmapSetInfo { OnlineID = 1535 };
|
beatmap.BeatmapSet = new BeatmapSetInfo { OnlineID = 1535 };
|
||||||
carouselBeatmap = new CarouselBeatmap(beatmap);
|
carouselBeatmap = new FilterMatchingTest.CarouselBeatmap(beatmap);
|
||||||
criteria1 = new FilterCriteria();
|
criteria1 = new FilterCriteria();
|
||||||
criteria2 = new FilterCriteria
|
criteria2 = new FilterCriteria
|
||||||
{
|
{
|
||||||
|
|||||||
77
osu.Game.Benchmarks/BenchmarkDifficultyCalculation.cs
Normal file
77
osu.Game.Benchmarks/BenchmarkDifficultyCalculation.cs
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.IO;
|
||||||
|
using BenchmarkDotNet.Attributes;
|
||||||
|
using osu.Framework.IO.Stores;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.IO;
|
||||||
|
using osu.Game.IO.Archives;
|
||||||
|
using osu.Game.Rulesets.Catch;
|
||||||
|
using osu.Game.Rulesets.Difficulty;
|
||||||
|
using osu.Game.Rulesets.Mania;
|
||||||
|
using osu.Game.Rulesets.Osu;
|
||||||
|
using osu.Game.Rulesets.Taiko;
|
||||||
|
using osu.Game.Tests.Resources;
|
||||||
|
|
||||||
|
namespace osu.Game.Benchmarks
|
||||||
|
{
|
||||||
|
public class BenchmarkDifficultyCalculation : BenchmarkTest
|
||||||
|
{
|
||||||
|
private DifficultyCalculator osuCalculator = null!;
|
||||||
|
private DifficultyCalculator taikoCalculator = null!;
|
||||||
|
private DifficultyCalculator catchCalculator = null!;
|
||||||
|
private DifficultyCalculator maniaCalculator = null!;
|
||||||
|
|
||||||
|
public override void SetUp()
|
||||||
|
{
|
||||||
|
using var resources = new DllResourceStore(typeof(TestResources).Assembly);
|
||||||
|
|
||||||
|
using var archive = resources.GetStream("Resources/Archives/241526 Soleily - Renatus.osz");
|
||||||
|
using var archiveReader = new ZipArchiveReader(archive);
|
||||||
|
|
||||||
|
var osuBeatmap = readBeatmap(archiveReader, "Soleily - Renatus (Gamu) [Insane].osu");
|
||||||
|
var taikoBeatmap = readBeatmap(archiveReader, "Soleily - Renatus (MMzz) [Oni].osu");
|
||||||
|
var catchBeatmap = readBeatmap(archiveReader, "Soleily - Renatus (Deif) [Salad].osu");
|
||||||
|
var maniaBeatmap = readBeatmap(archiveReader, "Soleily - Renatus (ExPew) [Another].osu");
|
||||||
|
|
||||||
|
osuCalculator = new OsuRuleset().CreateDifficultyCalculator(osuBeatmap);
|
||||||
|
taikoCalculator = new TaikoRuleset().CreateDifficultyCalculator(taikoBeatmap);
|
||||||
|
catchCalculator = new CatchRuleset().CreateDifficultyCalculator(catchBeatmap);
|
||||||
|
maniaCalculator = new ManiaRuleset().CreateDifficultyCalculator(maniaBeatmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
private WorkingBeatmap readBeatmap(ZipArchiveReader archiveReader, string beatmapName)
|
||||||
|
{
|
||||||
|
using var beatmapStream = new MemoryStream();
|
||||||
|
archiveReader.GetStream(beatmapName).CopyTo(beatmapStream);
|
||||||
|
|
||||||
|
beatmapStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
using var reader = new LineBufferedReader(beatmapStream);
|
||||||
|
|
||||||
|
var decoder = Beatmaps.Formats.Decoder.GetDecoder<Beatmap>(reader);
|
||||||
|
return new FlatWorkingBeatmap(decoder.Decode(reader));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void CalculateDifficultyOsu() => osuCalculator.Calculate();
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void CalculateDifficultyTaiko() => taikoCalculator.Calculate();
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void CalculateDifficultyCatch() => catchCalculator.Calculate();
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void CalculateDifficultyMania() => maniaCalculator.Calculate();
|
||||||
|
|
||||||
|
[Benchmark]
|
||||||
|
public void CalculateDifficultyOsuHundredTimes()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 100; i++)
|
||||||
|
{
|
||||||
|
osuCalculator.Calculate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -35,8 +35,6 @@
|
|||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
</array>
|
</array>
|
||||||
<key>XSAppIconAssets</key>
|
|
||||||
<string>Assets.xcassets/AppIcon.appiconset</string>
|
|
||||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestTinyDropletMissPreservesCatcherState()
|
public void TestTinyDropletMissChangesCatcherState()
|
||||||
{
|
{
|
||||||
AddStep("catch hyper kiai fruit", () => attemptCatch(new TestKiaiFruit
|
AddStep("catch hyper kiai fruit", () => attemptCatch(new TestKiaiFruit
|
||||||
{
|
{
|
||||||
@@ -165,8 +165,8 @@ namespace osu.Game.Rulesets.Catch.Tests
|
|||||||
}));
|
}));
|
||||||
AddStep("catch tiny droplet", () => attemptCatch(new TinyDroplet()));
|
AddStep("catch tiny droplet", () => attemptCatch(new TinyDroplet()));
|
||||||
AddStep("miss tiny droplet", () => attemptCatch(new TinyDroplet { X = 100 }));
|
AddStep("miss tiny droplet", () => attemptCatch(new TinyDroplet { X = 100 }));
|
||||||
// catcher state and hyper dash state is preserved
|
// catcher state is changed but hyper dash state is preserved
|
||||||
checkState(CatcherAnimationState.Kiai);
|
checkState(CatcherAnimationState.Fail);
|
||||||
checkHyperDash(true);
|
checkHyperDash(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -176,15 +176,20 @@ namespace osu.Game.Rulesets.Catch
|
|||||||
|
|
||||||
public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.RulesetCatch };
|
public override Drawable CreateIcon() => new SpriteIcon { Icon = OsuIcon.RulesetCatch };
|
||||||
|
|
||||||
protected override IEnumerable<HitResult> GetValidHitResults()
|
public override IEnumerable<HitResult> GetValidHitResults()
|
||||||
{
|
{
|
||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
HitResult.Great,
|
HitResult.Great,
|
||||||
|
HitResult.Miss,
|
||||||
|
|
||||||
HitResult.LargeTickHit,
|
HitResult.LargeTickHit,
|
||||||
|
HitResult.LargeTickMiss,
|
||||||
HitResult.SmallTickHit,
|
HitResult.SmallTickHit,
|
||||||
|
HitResult.SmallTickMiss,
|
||||||
HitResult.LargeBonus,
|
HitResult.LargeBonus,
|
||||||
|
HitResult.IgnoreHit,
|
||||||
|
HitResult.IgnoreMiss,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,7 +305,7 @@ namespace osu.Game.Rulesets.Catch
|
|||||||
Description = "Affects how early fruits fade in on the screen.",
|
Description = "Affects how early fruits fade in on the screen.",
|
||||||
AdditionalMetrics =
|
AdditionalMetrics =
|
||||||
[
|
[
|
||||||
new RulesetBeatmapAttribute.AdditionalMetric("Fade-in time", LocalisableString.Interpolate($@"{IBeatmapDifficultyInfo.DifficultyRange(effectiveDifficulty.ApproachRate, CatchHitObject.PREEMPT_RANGE):#,0.##} ms"))
|
new RulesetBeatmapAttribute.AdditionalMetric("Fade-in time", LocalisableString.Interpolate($@"{IBeatmapDifficultyInfo.DifficultyRangeInt(effectiveDifficulty.ApproachRate, CatchHitObject.PREEMPT_RANGE):#,0.##} ms"))
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
yield return new RulesetBeatmapAttribute(SongSelectStrings.HPDrain, @"HP", originalDifficulty.DrainRate, effectiveDifficulty.DrainRate, 10)
|
yield return new RulesetBeatmapAttribute(SongSelectStrings.HPDrain, @"HP", originalDifficulty.DrainRate, effectiveDifficulty.DrainRate, 10)
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
|||||||
|
|
||||||
private float halfCatcherWidth;
|
private float halfCatcherWidth;
|
||||||
|
|
||||||
public override int Version => 20250306;
|
public override int Version => 20251020;
|
||||||
|
|
||||||
public CatchDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
|
public CatchDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
|
||||||
: base(ruleset, beatmap)
|
: base(ruleset, beatmap)
|
||||||
|
|||||||
@@ -3,13 +3,13 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Audio.Track;
|
|
||||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Difficulty;
|
using osu.Game.Rulesets.Difficulty;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
using osu.Game.Scoring.Legacy;
|
using osu.Game.Scoring.Legacy;
|
||||||
|
using osu.Game.Utils;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Catch.Difficulty
|
namespace osu.Game.Rulesets.Catch.Difficulty
|
||||||
{
|
{
|
||||||
@@ -51,15 +51,13 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
|||||||
|
|
||||||
// Combo scaling
|
// Combo scaling
|
||||||
if (catchAttributes.MaxCombo > 0)
|
if (catchAttributes.MaxCombo > 0)
|
||||||
value *= Math.Min(Math.Pow(score.MaxCombo, 0.8) / Math.Pow(catchAttributes.MaxCombo, 0.8), 1.0);
|
value *= Math.Min(Math.Pow(score.MaxCombo, 0.35) / Math.Pow(catchAttributes.MaxCombo, 0.35), 1.0);
|
||||||
|
|
||||||
var difficulty = score.BeatmapInfo!.Difficulty.Clone();
|
var difficulty = score.BeatmapInfo!.Difficulty.Clone();
|
||||||
|
|
||||||
score.Mods.OfType<IApplicableToDifficulty>().ForEach(m => m.ApplyToDifficulty(difficulty));
|
score.Mods.OfType<IApplicableToDifficulty>().ForEach(m => m.ApplyToDifficulty(difficulty));
|
||||||
|
|
||||||
var track = new TrackVirtual(10000);
|
double clockRate = ModUtils.CalculateRateWithMods(score.Mods);
|
||||||
score.Mods.OfType<IApplicableToTrack>().ForEach(m => m.ApplyToTrack(track));
|
|
||||||
double clockRate = track.Rate;
|
|
||||||
|
|
||||||
// this is the same as osu!, so there's potential to share the implementation... maybe
|
// this is the same as osu!, so there's potential to share the implementation... maybe
|
||||||
double preempt = IBeatmapDifficultyInfo.DifficultyRange(difficulty.ApproachRate, 1800, 1200, 450) / clockRate;
|
double preempt = IBeatmapDifficultyInfo.DifficultyRange(difficulty.ApproachRate, 1800, 1200, 450) / clockRate;
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using osu.Game.Rulesets.Catch.Difficulty.Preprocessing;
|
||||||
|
using osu.Game.Rulesets.Difficulty.Preprocessing;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Catch.Difficulty.Evaluators
|
||||||
|
{
|
||||||
|
public static class MovementEvaluator
|
||||||
|
{
|
||||||
|
private const double direction_change_bonus = 21.0;
|
||||||
|
|
||||||
|
public static double EvaluateDifficultyOf(DifficultyHitObject current, double catcherSpeedMultiplier)
|
||||||
|
{
|
||||||
|
var catchCurrent = (CatchDifficultyHitObject)current;
|
||||||
|
var catchLast = (CatchDifficultyHitObject)current.Previous(0);
|
||||||
|
var catchLastLast = (CatchDifficultyHitObject)current.Previous(1);
|
||||||
|
|
||||||
|
double weightedStrainTime = catchCurrent.StrainTime + 13 + (3 / catcherSpeedMultiplier);
|
||||||
|
|
||||||
|
double distanceAddition = (Math.Pow(Math.Abs(catchCurrent.DistanceMoved), 1.3) / 510);
|
||||||
|
double sqrtStrain = Math.Sqrt(weightedStrainTime);
|
||||||
|
|
||||||
|
double edgeDashBonus = 0;
|
||||||
|
|
||||||
|
// Direction change bonus.
|
||||||
|
if (Math.Abs(catchCurrent.DistanceMoved) > 0.1)
|
||||||
|
{
|
||||||
|
if (current.Index >= 1 && Math.Abs(catchLast.DistanceMoved) > 0.1 && Math.Sign(catchCurrent.DistanceMoved) != Math.Sign(catchLast.DistanceMoved))
|
||||||
|
{
|
||||||
|
double bonusFactor = Math.Min(50, Math.Abs(catchCurrent.DistanceMoved)) / 50;
|
||||||
|
double antiflowFactor = Math.Max(Math.Min(70, Math.Abs(catchLast.DistanceMoved)) / 70, 0.38);
|
||||||
|
|
||||||
|
distanceAddition += direction_change_bonus / Math.Sqrt(catchLast.StrainTime + 16) * bonusFactor * antiflowFactor * Math.Max(1 - Math.Pow(weightedStrainTime / 1000, 3), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Base bonus for every movement, giving some weight to streams.
|
||||||
|
distanceAddition += 12.5 * Math.Min(Math.Abs(catchCurrent.DistanceMoved), CatchDifficultyHitObject.NORMALIZED_HALF_CATCHER_WIDTH * 2)
|
||||||
|
/ (CatchDifficultyHitObject.NORMALIZED_HALF_CATCHER_WIDTH * 6) / sqrtStrain;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bonus for edge dashes.
|
||||||
|
if (catchCurrent.LastObject.DistanceToHyperDash <= 20.0f)
|
||||||
|
{
|
||||||
|
if (!catchCurrent.LastObject.HyperDash)
|
||||||
|
edgeDashBonus += 5.7;
|
||||||
|
|
||||||
|
distanceAddition *= 1.0 + edgeDashBonus * ((20 - catchCurrent.LastObject.DistanceToHyperDash) / 20)
|
||||||
|
* Math.Pow((Math.Min(catchCurrent.StrainTime * catcherSpeedMultiplier, 265) / 265), 1.5); // Edge Dashes are easier at lower ms values
|
||||||
|
}
|
||||||
|
|
||||||
|
// There is an edge case where horizontal back and forth sliders create "buzz" patterns which are repeated "movements" with a distance lower than
|
||||||
|
// the platter's width but high enough to be considered a movement due to the absolute_player_positioning_error and NORMALIZED_HALF_CATCHER_WIDTH offsets
|
||||||
|
// We are detecting this exact scenario. The first back and forth is counted but all subsequent ones are nullified.
|
||||||
|
// To achieve that, we need to store the exact distances (distance ignoring absolute_player_positioning_error and NORMALIZED_HALF_CATCHER_WIDTH)
|
||||||
|
if (current.Index >= 2 && Math.Abs(catchCurrent.ExactDistanceMoved) <= CatchDifficultyHitObject.NORMALIZED_HALF_CATCHER_WIDTH * 2
|
||||||
|
&& catchCurrent.ExactDistanceMoved == -catchLast.ExactDistanceMoved && catchLast.ExactDistanceMoved == -catchLastLast.ExactDistanceMoved
|
||||||
|
&& catchCurrent.StrainTime == catchLast.StrainTime && catchLast.StrainTime == catchLastLast.StrainTime)
|
||||||
|
distanceAddition = 0;
|
||||||
|
|
||||||
|
return distanceAddition / weightedStrainTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,15 +11,49 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Preprocessing
|
|||||||
{
|
{
|
||||||
public class CatchDifficultyHitObject : DifficultyHitObject
|
public class CatchDifficultyHitObject : DifficultyHitObject
|
||||||
{
|
{
|
||||||
private const float normalized_hitobject_radius = 41.0f;
|
public const float NORMALIZED_HALF_CATCHER_WIDTH = 41.0f;
|
||||||
|
private const float absolute_player_positioning_error = 16.0f;
|
||||||
|
|
||||||
public new PalpableCatchHitObject BaseObject => (PalpableCatchHitObject)base.BaseObject;
|
public new PalpableCatchHitObject BaseObject => (PalpableCatchHitObject)base.BaseObject;
|
||||||
|
|
||||||
public new PalpableCatchHitObject LastObject => (PalpableCatchHitObject)base.LastObject;
|
public new PalpableCatchHitObject LastObject => (PalpableCatchHitObject)base.LastObject;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Normalized position of <see cref="BaseObject"/>.
|
||||||
|
/// </summary>
|
||||||
public readonly float NormalizedPosition;
|
public readonly float NormalizedPosition;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Normalized position of <see cref="LastObject"/>.
|
||||||
|
/// </summary>
|
||||||
public readonly float LastNormalizedPosition;
|
public readonly float LastNormalizedPosition;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Normalized position of the player required to catch <see cref="BaseObject"/>, assuming the player moves as little as possible.
|
||||||
|
/// </summary>
|
||||||
|
public float PlayerPosition { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Normalized position of the player after catching <see cref="LastObject"/>.
|
||||||
|
/// </summary>
|
||||||
|
public float LastPlayerPosition { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Normalized distance between <see cref="LastPlayerPosition"/> and <see cref="PlayerPosition"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The sign of the value indicates the direction of the movement: negative is left and positive is right.
|
||||||
|
/// </remarks>
|
||||||
|
public float DistanceMoved { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Normalized distance the player has to move from <see cref="LastPlayerPosition"/> in order to catch <see cref="BaseObject"/> at its <see cref="NormalizedPosition"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The sign of the value indicates the direction of the movement: negative is left and positive is right.
|
||||||
|
/// </remarks>
|
||||||
|
public float ExactDistanceMoved { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Milliseconds elapsed since the start time of the previous <see cref="CatchDifficultyHitObject"/>, with a minimum of 40ms.
|
/// Milliseconds elapsed since the start time of the previous <see cref="CatchDifficultyHitObject"/>, with a minimum of 40ms.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -29,13 +63,35 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Preprocessing
|
|||||||
: base(hitObject, lastObject, clockRate, objects, index)
|
: base(hitObject, lastObject, clockRate, objects, index)
|
||||||
{
|
{
|
||||||
// We will scale everything by this factor, so we can assume a uniform CircleSize among beatmaps.
|
// We will scale everything by this factor, so we can assume a uniform CircleSize among beatmaps.
|
||||||
float scalingFactor = normalized_hitobject_radius / halfCatcherWidth;
|
float scalingFactor = NORMALIZED_HALF_CATCHER_WIDTH / halfCatcherWidth;
|
||||||
|
|
||||||
NormalizedPosition = BaseObject.EffectiveX * scalingFactor;
|
NormalizedPosition = BaseObject.EffectiveX * scalingFactor;
|
||||||
LastNormalizedPosition = LastObject.EffectiveX * scalingFactor;
|
LastNormalizedPosition = LastObject.EffectiveX * scalingFactor;
|
||||||
|
|
||||||
// Every strain interval is hard capped at the equivalent of 375 BPM streaming speed as a safety measure
|
// Every strain interval is hard capped at the equivalent of 375 BPM streaming speed as a safety measure
|
||||||
StrainTime = Math.Max(40, DeltaTime);
|
StrainTime = Math.Max(40, DeltaTime);
|
||||||
|
|
||||||
|
setMovementState();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setMovementState()
|
||||||
|
{
|
||||||
|
LastPlayerPosition = Index == 0 ? LastNormalizedPosition : ((CatchDifficultyHitObject)Previous(0)).PlayerPosition;
|
||||||
|
|
||||||
|
PlayerPosition = Math.Clamp(
|
||||||
|
LastPlayerPosition,
|
||||||
|
NormalizedPosition - (NORMALIZED_HALF_CATCHER_WIDTH - absolute_player_positioning_error),
|
||||||
|
NormalizedPosition + (NORMALIZED_HALF_CATCHER_WIDTH - absolute_player_positioning_error)
|
||||||
|
);
|
||||||
|
|
||||||
|
DistanceMoved = PlayerPosition - LastPlayerPosition;
|
||||||
|
|
||||||
|
// For the exact position we consider that the catcher is in the correct position for both objects
|
||||||
|
ExactDistanceMoved = NormalizedPosition - LastPlayerPosition;
|
||||||
|
|
||||||
|
// After a hyperdash we ARE in the correct position. Always!
|
||||||
|
if (LastObject.HyperDash)
|
||||||
|
PlayerPosition = NormalizedPosition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using osu.Game.Rulesets.Catch.Difficulty.Evaluators;
|
||||||
using osu.Game.Rulesets.Catch.Difficulty.Preprocessing;
|
|
||||||
using osu.Game.Rulesets.Difficulty.Preprocessing;
|
using osu.Game.Rulesets.Difficulty.Preprocessing;
|
||||||
using osu.Game.Rulesets.Difficulty.Skills;
|
using osu.Game.Rulesets.Difficulty.Skills;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
@@ -11,10 +10,6 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Skills
|
|||||||
{
|
{
|
||||||
public class Movement : StrainDecaySkill
|
public class Movement : StrainDecaySkill
|
||||||
{
|
{
|
||||||
private const float absolute_player_positioning_error = 16f;
|
|
||||||
private const float normalized_hitobject_radius = 41.0f;
|
|
||||||
private const double direction_change_bonus = 21.0;
|
|
||||||
|
|
||||||
protected override double SkillMultiplier => 1;
|
protected override double SkillMultiplier => 1;
|
||||||
protected override double StrainDecayBase => 0.2;
|
protected override double StrainDecayBase => 0.2;
|
||||||
|
|
||||||
@@ -24,12 +19,6 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Skills
|
|||||||
|
|
||||||
protected readonly float HalfCatcherWidth;
|
protected readonly float HalfCatcherWidth;
|
||||||
|
|
||||||
private float? lastPlayerPosition;
|
|
||||||
private float lastDistanceMoved;
|
|
||||||
private float lastExactDistanceMoved;
|
|
||||||
private double lastStrainTime;
|
|
||||||
private bool isInBuzzSection;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The speed multiplier applied to the player's catcher.
|
/// The speed multiplier applied to the player's catcher.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -49,80 +38,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Skills
|
|||||||
|
|
||||||
protected override double StrainValueOf(DifficultyHitObject current)
|
protected override double StrainValueOf(DifficultyHitObject current)
|
||||||
{
|
{
|
||||||
var catchCurrent = (CatchDifficultyHitObject)current;
|
return MovementEvaluator.EvaluateDifficultyOf(current, catcherSpeedMultiplier);
|
||||||
|
|
||||||
lastPlayerPosition ??= catchCurrent.LastNormalizedPosition;
|
|
||||||
|
|
||||||
float playerPosition = Math.Clamp(
|
|
||||||
lastPlayerPosition.Value,
|
|
||||||
catchCurrent.NormalizedPosition - (normalized_hitobject_radius - absolute_player_positioning_error),
|
|
||||||
catchCurrent.NormalizedPosition + (normalized_hitobject_radius - absolute_player_positioning_error)
|
|
||||||
);
|
|
||||||
|
|
||||||
float distanceMoved = playerPosition - lastPlayerPosition.Value;
|
|
||||||
|
|
||||||
// For the exact position we consider that the catcher is in the correct position for both objects
|
|
||||||
float exactDistanceMoved = catchCurrent.NormalizedPosition - lastPlayerPosition.Value;
|
|
||||||
|
|
||||||
double weightedStrainTime = catchCurrent.StrainTime + 13 + (3 / catcherSpeedMultiplier);
|
|
||||||
|
|
||||||
double distanceAddition = (Math.Pow(Math.Abs(distanceMoved), 1.3) / 510);
|
|
||||||
double sqrtStrain = Math.Sqrt(weightedStrainTime);
|
|
||||||
|
|
||||||
double edgeDashBonus = 0;
|
|
||||||
|
|
||||||
// Direction change bonus.
|
|
||||||
if (Math.Abs(distanceMoved) > 0.1)
|
|
||||||
{
|
|
||||||
if (Math.Abs(lastDistanceMoved) > 0.1 && Math.Sign(distanceMoved) != Math.Sign(lastDistanceMoved))
|
|
||||||
{
|
|
||||||
double bonusFactor = Math.Min(50, Math.Abs(distanceMoved)) / 50;
|
|
||||||
double antiflowFactor = Math.Max(Math.Min(70, Math.Abs(lastDistanceMoved)) / 70, 0.38);
|
|
||||||
|
|
||||||
distanceAddition += direction_change_bonus / Math.Sqrt(lastStrainTime + 16) * bonusFactor * antiflowFactor * Math.Max(1 - Math.Pow(weightedStrainTime / 1000, 3), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Base bonus for every movement, giving some weight to streams.
|
|
||||||
distanceAddition += 12.5 * Math.Min(Math.Abs(distanceMoved), normalized_hitobject_radius * 2) / (normalized_hitobject_radius * 6) / sqrtStrain;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bonus for edge dashes.
|
|
||||||
if (catchCurrent.LastObject.DistanceToHyperDash <= 20.0f)
|
|
||||||
{
|
|
||||||
if (!catchCurrent.LastObject.HyperDash)
|
|
||||||
edgeDashBonus += 5.7;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// After a hyperdash we ARE in the correct position. Always!
|
|
||||||
playerPosition = catchCurrent.NormalizedPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
distanceAddition *= 1.0 + edgeDashBonus * ((20 - catchCurrent.LastObject.DistanceToHyperDash) / 20)
|
|
||||||
* Math.Pow((Math.Min(catchCurrent.StrainTime * catcherSpeedMultiplier, 265) / 265), 1.5); // Edge Dashes are easier at lower ms values
|
|
||||||
}
|
|
||||||
|
|
||||||
// There is an edge case where horizontal back and forth sliders create "buzz" patterns which are repeated "movements" with a distance lower than
|
|
||||||
// the platter's width but high enough to be considered a movement due to the absolute_player_positioning_error and normalized_hitobject_radius offsets
|
|
||||||
// We are detecting this exact scenario. The first back and forth is counted but all subsequent ones are nullified.
|
|
||||||
// To achieve that, we need to store the exact distances (distance ignoring absolute_player_positioning_error and normalized_hitobject_radius)
|
|
||||||
if (Math.Abs(exactDistanceMoved) <= HalfCatcherWidth * 2 && exactDistanceMoved == -lastExactDistanceMoved && catchCurrent.StrainTime == lastStrainTime)
|
|
||||||
{
|
|
||||||
if (isInBuzzSection)
|
|
||||||
distanceAddition = 0;
|
|
||||||
else
|
|
||||||
isInBuzzSection = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
isInBuzzSection = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
lastPlayerPosition = playerPosition;
|
|
||||||
lastDistanceMoved = distanceMoved;
|
|
||||||
lastStrainTime = catchCurrent.StrainTime;
|
|
||||||
lastExactDistanceMoved = exactDistanceMoved;
|
|
||||||
|
|
||||||
return distanceAddition / weightedStrainTime;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints
|
|||||||
private double placementStartTime;
|
private double placementStartTime;
|
||||||
private double placementEndTime;
|
private double placementEndTime;
|
||||||
|
|
||||||
protected override bool IsValidForPlacement => Precision.DefinitelyBigger(HitObject.Duration, 0);
|
protected override bool IsValidForPlacement => base.IsValidForPlacement && (PlacementActive == PlacementState.Waiting || Precision.DefinitelyBigger(HitObject.Duration, 0));
|
||||||
|
|
||||||
public BananaShowerPlacementBlueprint()
|
public BananaShowerPlacementBlueprint()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints
|
|||||||
|
|
||||||
private InputManager inputManager = null!;
|
private InputManager inputManager = null!;
|
||||||
|
|
||||||
protected override bool IsValidForPlacement => Precision.DefinitelyBigger(HitObject.Duration, 0);
|
protected override bool IsValidForPlacement => base.IsValidForPlacement && (PlacementActive == PlacementState.Waiting || Precision.DefinitelyBigger(HitObject.Duration, 0));
|
||||||
|
|
||||||
public JuiceStreamPlacementBlueprint()
|
public JuiceStreamPlacementBlueprint()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
@@ -224,7 +225,8 @@ namespace osu.Game.Rulesets.Catch.Edit
|
|||||||
#region Clipboard handling
|
#region Clipboard handling
|
||||||
|
|
||||||
public override string ConvertSelectionToString()
|
public override string ConvertSelectionToString()
|
||||||
=> string.Join(',', EditorBeatmap.SelectedHitObjects.Cast<CatchHitObject>().OrderBy(h => h.StartTime).Select(h => (h.IndexInCurrentCombo + 1).ToString()));
|
=> string.Join(',', EditorBeatmap.SelectedHitObjects.Cast<CatchHitObject>().OrderBy(h => h.StartTime)
|
||||||
|
.Select(h => (h.IndexInCurrentCombo + 1).ToString(CultureInfo.InvariantCulture)));
|
||||||
|
|
||||||
// 1,2,3,4 ...
|
// 1,2,3,4 ...
|
||||||
private static readonly Regex selection_regex = new Regex(@"^\d+(,\d+)*$", RegexOptions.Compiled);
|
private static readonly Regex selection_regex = new Regex(@"^\d+(,\d+)*$", RegexOptions.Compiled);
|
||||||
|
|||||||
@@ -51,7 +51,8 @@ namespace osu.Game.Rulesets.Catch.Mods
|
|||||||
|
|
||||||
return string.Empty;
|
return string.Empty;
|
||||||
|
|
||||||
string format(string acronym, DifficultyBindable bindable) => $"{acronym}{bindable.Value!.Value.ToStandardFormattedString(1)}";
|
string format(string acronym, DifficultyBindable bindable)
|
||||||
|
=> $"{acronym}{bindable.Value!.Value.ToStandardFormattedString(1)}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Game.Audio;
|
using osu.Game.Audio;
|
||||||
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Rulesets.Catch.Judgements;
|
using osu.Game.Rulesets.Catch.Judgements;
|
||||||
using osu.Game.Rulesets.Judgements;
|
using osu.Game.Rulesets.Judgements;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
@@ -53,13 +54,25 @@ namespace osu.Game.Rulesets.Catch.Objects
|
|||||||
|
|
||||||
public override IEnumerable<string> LookupNames => lookup_names;
|
public override IEnumerable<string> LookupNames => lookup_names;
|
||||||
|
|
||||||
public BananaHitSampleInfo(int volume = 100)
|
public BananaHitSampleInfo()
|
||||||
: base(string.Empty, volume: volume)
|
: this(string.Empty)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed override HitSampleInfo With(Optional<string> newName = default, Optional<string> newBank = default, Optional<string?> newSuffix = default, Optional<int> newVolume = default, Optional<bool> newEditorAutoBank = default)
|
public BananaHitSampleInfo(HitSampleInfo info)
|
||||||
=> new BananaHitSampleInfo(newVolume.GetOr(Volume));
|
: this(info.Name, info.Bank, info.Suffix, info.Volume, info.EditorAutoBank, info.UseBeatmapSamples)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private BananaHitSampleInfo(string name, string bank = SampleControlPoint.DEFAULT_BANK, string? suffix = null, int volume = 100, bool editorAutoBank = true, bool useBeatmapSamples = false)
|
||||||
|
: base(name, bank, suffix, volume, editorAutoBank, useBeatmapSamples)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed override HitSampleInfo With(Optional<string> newName = default, Optional<string> newBank = default, Optional<string?> newSuffix = default, Optional<int> newVolume = default,
|
||||||
|
Optional<bool> newEditorAutoBank = default, Optional<bool> newUseBeatmapSamples = default)
|
||||||
|
=> new BananaHitSampleInfo(newName.GetOr(Name), newBank.GetOr(Bank), newSuffix.GetOr(Suffix), newVolume.GetOr(Volume),
|
||||||
|
newEditorAutoBank.GetOr(EditorAutoBank), newUseBeatmapSamples.GetOr(UseBeatmapSamples));
|
||||||
|
|
||||||
public bool Equals(BananaHitSampleInfo? other)
|
public bool Equals(BananaHitSampleInfo? other)
|
||||||
=> other != null;
|
=> other != null;
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Catch.Objects
|
|||||||
{
|
{
|
||||||
StartTime = time,
|
StartTime = time,
|
||||||
BananaIndex = count,
|
BananaIndex = count,
|
||||||
Samples = new List<HitSampleInfo> { new Banana.BananaHitSampleInfo(CreateHitSampleInfo().Volume) }
|
Samples = new List<HitSampleInfo> { new Banana.BananaHitSampleInfo(CreateHitSampleInfo()) }
|
||||||
});
|
});
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ namespace osu.Game.Rulesets.Catch.Objects
|
|||||||
{
|
{
|
||||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||||
|
|
||||||
TimePreempt = (float)IBeatmapDifficultyInfo.DifficultyRange(difficulty.ApproachRate, PREEMPT_RANGE);
|
TimePreempt = IBeatmapDifficultyInfo.DifficultyRangeInt(difficulty.ApproachRate, PREEMPT_RANGE);
|
||||||
|
|
||||||
Scale = LegacyRulesetExtensions.CalculateScaleFromCircleSize(difficulty.CircleSize);
|
Scale = LegacyRulesetExtensions.CalculateScaleFromCircleSize(difficulty.CircleSize);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,6 +72,9 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy
|
|||||||
leaderboard.Origin = Anchor.CentreLeft;
|
leaderboard.Origin = Anchor.CentreLeft;
|
||||||
leaderboard.X = 10;
|
leaderboard.X = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var d in container.OfType<ISerialisableDrawable>())
|
||||||
|
d.UsesFixedAnchor = true;
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
|
|||||||
@@ -224,7 +224,20 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
addLighting(result, drawableObject.AccentColour.Value, positionInStack.X);
|
addLighting(result, drawableObject.AccentColour.Value, positionInStack.X);
|
||||||
}
|
}
|
||||||
|
|
||||||
// droplet doesn't affect the catcher state
|
if (result.IsHit)
|
||||||
|
CurrentState = hitObject.Kiai ? CatcherAnimationState.Kiai : CatcherAnimationState.Idle;
|
||||||
|
else if (hitObject is not Banana)
|
||||||
|
CurrentState = CatcherAnimationState.Fail;
|
||||||
|
|
||||||
|
if (palpableObject.HitObject.LastInCombo)
|
||||||
|
{
|
||||||
|
if (result.Judgement is CatchJudgement catchJudgement && catchJudgement.ShouldExplodeFor(result))
|
||||||
|
Explode();
|
||||||
|
else
|
||||||
|
Drop();
|
||||||
|
}
|
||||||
|
|
||||||
|
// droplet doesn't affect hyperdash state
|
||||||
if (hitObject is TinyDroplet) return;
|
if (hitObject is TinyDroplet) return;
|
||||||
|
|
||||||
// if a hyper fruit was already handled this frame, just go where it says to go.
|
// if a hyper fruit was already handled this frame, just go where it says to go.
|
||||||
@@ -244,19 +257,6 @@ namespace osu.Game.Rulesets.Catch.UI
|
|||||||
else
|
else
|
||||||
SetHyperDashState();
|
SetHyperDashState();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.IsHit)
|
|
||||||
CurrentState = hitObject.Kiai ? CatcherAnimationState.Kiai : CatcherAnimationState.Idle;
|
|
||||||
else if (!(hitObject is Banana))
|
|
||||||
CurrentState = CatcherAnimationState.Fail;
|
|
||||||
|
|
||||||
if (palpableObject.HitObject.LastInCombo)
|
|
||||||
{
|
|
||||||
if (result.Judgement is CatchJudgement catchJudgement && catchJudgement.ShouldExplodeFor(result))
|
|
||||||
Explode();
|
|
||||||
else
|
|
||||||
Drop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnRevertResult(JudgementResult result)
|
public void OnRevertResult(JudgementResult result)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
<PropertyGroup Label="Nuget">
|
<PropertyGroup Label="Nuget">
|
||||||
<Title>osu!catch (ruleset)</Title>
|
<Title>osu!catch (ruleset)</Title>
|
||||||
<PackageId>ppy.osu.Game.Rulesets.Catch</PackageId>
|
<PackageId>jvnkosu.Client.Rulesets.Catch</PackageId>
|
||||||
<IsPackable>true</IsPackable>
|
<IsPackable>true</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -35,8 +35,6 @@
|
|||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
</array>
|
</array>
|
||||||
<key>XSAppIconAssets</key>
|
|
||||||
<string>Assets.xcassets/AppIcon.appiconset</string>
|
|
||||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Rulesets.Edit;
|
using osu.Game.Rulesets.Edit;
|
||||||
@@ -16,6 +17,7 @@ using osu.Game.Rulesets.Objects;
|
|||||||
using osu.Game.Rulesets.Objects.Drawables;
|
using osu.Game.Rulesets.Objects.Drawables;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osu.Game.Rulesets.UI.Scrolling;
|
using osu.Game.Rulesets.UI.Scrolling;
|
||||||
|
using osu.Game.Screens.Edit;
|
||||||
using osu.Game.Tests.Visual;
|
using osu.Game.Tests.Visual;
|
||||||
using osuTK.Input;
|
using osuTK.Input;
|
||||||
|
|
||||||
@@ -36,21 +38,8 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
|
|||||||
[Test]
|
[Test]
|
||||||
public void TestPlaceBeforeCurrentTimeDownwards()
|
public void TestPlaceBeforeCurrentTimeDownwards()
|
||||||
{
|
{
|
||||||
|
AddStep("seek to 200", () => HitObjectContainer.Dependencies.Get<EditorClock>().Seek(200));
|
||||||
AddStep("move mouse before current time", () =>
|
AddStep("move mouse before current time", () =>
|
||||||
{
|
|
||||||
var column = this.ChildrenOfType<Column>().Single();
|
|
||||||
InputManager.MoveMouseTo(column.ScreenSpacePositionAtTime(-100));
|
|
||||||
});
|
|
||||||
|
|
||||||
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
|
||||||
|
|
||||||
AddAssert("note start time < 0", () => getNote().StartTime < 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestPlaceAfterCurrentTimeDownwards()
|
|
||||||
{
|
|
||||||
AddStep("move mouse after current time", () =>
|
|
||||||
{
|
{
|
||||||
var column = this.ChildrenOfType<Column>().Single();
|
var column = this.ChildrenOfType<Column>().Single();
|
||||||
InputManager.MoveMouseTo(column.ScreenSpacePositionAtTime(100));
|
InputManager.MoveMouseTo(column.ScreenSpacePositionAtTime(100));
|
||||||
@@ -58,7 +47,22 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
|
|||||||
|
|
||||||
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||||
|
|
||||||
AddAssert("note start time > 0", () => getNote().StartTime > 0);
|
AddAssert("note start time < 200", () => getNote().StartTime < 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestPlaceAfterCurrentTimeDownwards()
|
||||||
|
{
|
||||||
|
AddStep("seek to 200", () => HitObjectContainer.Dependencies.Get<EditorClock>().Seek(200));
|
||||||
|
AddStep("move mouse after current time", () =>
|
||||||
|
{
|
||||||
|
var column = this.ChildrenOfType<Column>().Single();
|
||||||
|
InputManager.MoveMouseTo(column.ScreenSpacePositionAtTime(300));
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||||
|
|
||||||
|
AddAssert("note start time > 200", () => getNote().StartTime > 200);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Note getNote() => this.ChildrenOfType<DrawableNote>().FirstOrDefault()?.HitObject;
|
private Note getNote() => this.ChildrenOfType<DrawableNote>().FirstOrDefault()?.HitObject;
|
||||||
|
|||||||
@@ -18,15 +18,11 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
|
|||||||
public void TestNormalSelection()
|
public void TestNormalSelection()
|
||||||
{
|
{
|
||||||
addStepClickLink("00:05:920 (5920|3,6623|3,6857|2,7326|1)");
|
addStepClickLink("00:05:920 (5920|3,6623|3,6857|2,7326|1)");
|
||||||
AddAssert("selected group", () => checkSnapAndSelectColumn(5_920, new List<(int, int)>
|
AddAssert("selected group", () => checkSnapAndSelectColumn(5_920, [(5_920, 3), (6_623, 3), (6_857, 2), (7_326, 1)]));
|
||||||
{ (5_920, 3), (6_623, 3), (6_857, 2), (7_326, 1) }
|
|
||||||
));
|
|
||||||
|
|
||||||
addReset();
|
addReset();
|
||||||
addStepClickLink("00:42:716 (42716|3,43420|2,44123|0,44357|1,45295|1)");
|
addStepClickLink("00:42:716 (42716|3,43420|2,44123|0,44357|1,45295|1)");
|
||||||
AddAssert("selected ungrouped", () => checkSnapAndSelectColumn(42_716, new List<(int, int)>
|
AddAssert("selected ungrouped", () => checkSnapAndSelectColumn(42_716, [(42_716, 3), (43_420, 2), (44_123, 0), (44_357, 1), (45_295, 1)]));
|
||||||
{ (42_716, 3), (43_420, 2), (44_123, 0), (44_357, 1), (45_295, 1) }
|
|
||||||
));
|
|
||||||
|
|
||||||
addReset();
|
addReset();
|
||||||
AddStep("add notes to row", () =>
|
AddStep("add notes to row", () =>
|
||||||
@@ -41,15 +37,20 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
|
|||||||
EditorBeatmap.AddRange(new[] { second, third, forth });
|
EditorBeatmap.AddRange(new[] { second, third, forth });
|
||||||
});
|
});
|
||||||
addStepClickLink("00:11:545 (11545|0,11545|1,11545|2,11545|3)");
|
addStepClickLink("00:11:545 (11545|0,11545|1,11545|2,11545|3)");
|
||||||
AddAssert("selected in row", () => checkSnapAndSelectColumn(11_545, new List<(int, int)>
|
AddAssert("selected in row", () => checkSnapAndSelectColumn(11_545, [(11_545, 0), (11_545, 1), (11_545, 2), (11_545, 3)]));
|
||||||
{ (11_545, 0), (11_545, 1), (11_545, 2), (11_545, 3) }
|
|
||||||
));
|
|
||||||
|
|
||||||
addReset();
|
addReset();
|
||||||
addStepClickLink("01:36:623 (96623|1,97560|1,97677|1,97795|1,98966|1)");
|
addStepClickLink("01:36:623 (96623|1,97560|1,97677|1,97795|1,98966|1)");
|
||||||
AddAssert("selected in column", () => checkSnapAndSelectColumn(96_623, new List<(int, int)>
|
AddAssert("selected in column", () => checkSnapAndSelectColumn(96_623, [(96_623, 1), (97_560, 1), (97_677, 1), (97_795, 1), (98_966, 1)]));
|
||||||
{ (96_623, 1), (97_560, 1), (97_677, 1), (97_795, 1), (98_966, 1) }
|
}
|
||||||
));
|
|
||||||
|
[Test]
|
||||||
|
public void TestRoundingToNearestMillisecondApplied()
|
||||||
|
{
|
||||||
|
AddStep("resnap note to have fractional coordinates",
|
||||||
|
() => EditorBeatmap.HitObjects.OfType<ManiaHitObject>().Single(ho => ho.StartTime == 85_373 && ho.Column == 1).StartTime = 85_373.125);
|
||||||
|
addStepClickLink("01:25:373 (85373|1)");
|
||||||
|
AddAssert("selected note", () => checkSnapAndSelectColumn(85_373.125, [(85_373.125, 1)]));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
@@ -75,7 +76,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
|
|||||||
|
|
||||||
private void addReset() => addStepClickLink("00:00:000", "reset", false);
|
private void addReset() => addStepClickLink("00:00:000", "reset", false);
|
||||||
|
|
||||||
private bool checkSnapAndSelectColumn(double startTime, IReadOnlyCollection<(int, int)>? columnPairs = null)
|
private bool checkSnapAndSelectColumn(double startTime, IReadOnlyCollection<(double, int)>? columnPairs = null)
|
||||||
{
|
{
|
||||||
bool checkColumns = columnPairs != null
|
bool checkColumns = columnPairs != null
|
||||||
? EditorBeatmap.SelectedHitObjects.All(x => columnPairs.Any(col => isNoteAt(x, col.Item1, col.Item2)))
|
? EditorBeatmap.SelectedHitObjects.All(x => columnPairs.Any(col => isNoteAt(x, col.Item1, col.Item2)))
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
[TestCase("mania-samples")]
|
[TestCase("mania-samples")]
|
||||||
[TestCase("mania-slider")] // e.g. second and fourth notes of https://osu.ppy.sh/beatmapsets/73883#mania/216407
|
[TestCase("mania-slider")] // e.g. second and fourth notes of https://osu.ppy.sh/beatmapsets/73883#mania/216407
|
||||||
[TestCase("slider-convert-samples")]
|
[TestCase("slider-convert-samples")]
|
||||||
|
[TestCase("spinner-convert-samples")]
|
||||||
public void Test(string name) => base.Test(name);
|
public void Test(string name) => base.Test(name);
|
||||||
|
|
||||||
protected override IEnumerable<SampleConvertValue> CreateConvertValue(HitObject hitObject)
|
protected override IEnumerable<SampleConvertValue> CreateConvertValue(HitObject hitObject)
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
osu file format v14
|
||||||
|
|
||||||
|
[General]
|
||||||
|
Mode: 0
|
||||||
|
|
||||||
|
[TimingPoints]
|
||||||
|
0,300,4,0,2,100,1,0
|
||||||
|
|
||||||
|
[HitObjects]
|
||||||
|
444,320,1000,5,2,0:0:0:0:
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"Mappings": [{
|
||||||
|
"StartTime": 1000.0,
|
||||||
|
"Objects": [{
|
||||||
|
"StartTime": 1000.0,
|
||||||
|
"EndTime": 8000.0,
|
||||||
|
"Column": 0,
|
||||||
|
"PlaySlidingSamples": false,
|
||||||
|
"NodeSamples": [
|
||||||
|
["Gameplay/soft-hitnormal"],
|
||||||
|
["Gameplay/soft-hitnormal", "Gameplay/soft-hitfinish"]
|
||||||
|
],
|
||||||
|
"Samples": ["Gameplay/soft-hitnormal", "Gameplay/soft-hitfinish"],
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
osu file format v14
|
||||||
|
|
||||||
|
[General]
|
||||||
|
Mode: 0
|
||||||
|
|
||||||
|
[Difficulty]
|
||||||
|
HPDrainRate:5
|
||||||
|
CircleSize:5
|
||||||
|
OverallDifficulty:5
|
||||||
|
ApproachRate:5
|
||||||
|
SliderMultiplier:1.4
|
||||||
|
SliderTickRate:1
|
||||||
|
|
||||||
|
[TimingPoints]
|
||||||
|
0,500,4,2,0,100,1,0
|
||||||
|
|
||||||
|
[HitObjects]
|
||||||
|
256,192,1000,8,4,8000,0:2:0:0:
|
||||||
@@ -45,5 +45,19 @@ namespace osu.Game.Rulesets.Mania.Tests
|
|||||||
AssertBeatmapLookup(expected_sample);
|
AssertBeatmapLookup(expected_sample);
|
||||||
AssertNoLookup(unwanted_sample);
|
AssertNoLookup(unwanted_sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestConvertHitObjectCustomSampleBank()
|
||||||
|
{
|
||||||
|
const string beatmap_sample = "normal-hitwhistle2";
|
||||||
|
const string user_skin_sample = "normal-hitnormal";
|
||||||
|
|
||||||
|
SetupSkins(beatmap_sample, user_skin_sample);
|
||||||
|
|
||||||
|
CreateTestWithBeatmap("convert-beatmap-custom-sample-bank.osu");
|
||||||
|
|
||||||
|
AssertBeatmapLookup(beatmap_sample);
|
||||||
|
AssertUserLookup(user_skin_sample);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,7 +85,11 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
|||||||
Duration = endTime - HitObject.StartTime,
|
Duration = endTime - HitObject.StartTime,
|
||||||
Column = column,
|
Column = column,
|
||||||
Samples = HitObject.Samples,
|
Samples = HitObject.Samples,
|
||||||
NodeSamples = (HitObject as IHasRepeats)?.NodeSamples
|
NodeSamples =
|
||||||
|
[
|
||||||
|
HitObject.Samples.Where(s => s.Name == HitSampleInfo.HIT_NORMAL).ToList(),
|
||||||
|
HitObject.Samples
|
||||||
|
]
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Framework.Utils;
|
||||||
|
using osu.Game.Rulesets.Difficulty.Preprocessing;
|
||||||
|
using osu.Game.Rulesets.Mania.Difficulty.Preprocessing;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Difficulty.Evaluators
|
||||||
|
{
|
||||||
|
public class IndividualStrainEvaluator
|
||||||
|
{
|
||||||
|
public static double EvaluateDifficultyOf(DifficultyHitObject current)
|
||||||
|
{
|
||||||
|
var maniaCurrent = (ManiaDifficultyHitObject)current;
|
||||||
|
double startTime = maniaCurrent.StartTime;
|
||||||
|
double endTime = maniaCurrent.EndTime;
|
||||||
|
|
||||||
|
double holdFactor = 1.0; // Factor to all additional strains in case something else is held
|
||||||
|
|
||||||
|
// We award a bonus if this note starts and ends before the end of another hold note.
|
||||||
|
foreach (var maniaPrevious in maniaCurrent.PreviousHitObjects)
|
||||||
|
{
|
||||||
|
if (maniaPrevious is null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (Precision.DefinitelyBigger(maniaPrevious.EndTime, endTime, 1) &&
|
||||||
|
Precision.DefinitelyBigger(startTime, maniaPrevious.StartTime, 1))
|
||||||
|
{
|
||||||
|
holdFactor = 1.25;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 2.0 * holdFactor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using osu.Framework.Utils;
|
||||||
|
using osu.Game.Rulesets.Difficulty.Preprocessing;
|
||||||
|
using osu.Game.Rulesets.Difficulty.Utils;
|
||||||
|
using osu.Game.Rulesets.Mania.Difficulty.Preprocessing;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Mania.Difficulty.Evaluators
|
||||||
|
{
|
||||||
|
public class OverallStrainEvaluator
|
||||||
|
{
|
||||||
|
private const double release_threshold = 30;
|
||||||
|
|
||||||
|
public static double EvaluateDifficultyOf(DifficultyHitObject current)
|
||||||
|
{
|
||||||
|
var maniaCurrent = (ManiaDifficultyHitObject)current;
|
||||||
|
double startTime = maniaCurrent.StartTime;
|
||||||
|
double endTime = maniaCurrent.EndTime;
|
||||||
|
bool isOverlapping = false;
|
||||||
|
|
||||||
|
double closestEndTime = Math.Abs(endTime - startTime); // Lowest value we can assume with the current information
|
||||||
|
double holdFactor = 1.0; // Factor to all additional strains in case something else is held
|
||||||
|
double holdAddition = 0; // Addition to the current note in case it's a hold and has to be released awkwardly
|
||||||
|
|
||||||
|
foreach (var maniaPrevious in maniaCurrent.PreviousHitObjects)
|
||||||
|
{
|
||||||
|
if (maniaPrevious is null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// The current note is overlapped if a previous note or end is overlapping the current note body
|
||||||
|
isOverlapping |= Precision.DefinitelyBigger(maniaPrevious.EndTime, startTime, 1) &&
|
||||||
|
Precision.DefinitelyBigger(endTime, maniaPrevious.EndTime, 1) &&
|
||||||
|
Precision.DefinitelyBigger(startTime, maniaPrevious.StartTime, 1);
|
||||||
|
|
||||||
|
// We give a slight bonus to everything if something is held meanwhile
|
||||||
|
if (Precision.DefinitelyBigger(maniaPrevious.EndTime, endTime, 1) &&
|
||||||
|
Precision.DefinitelyBigger(startTime, maniaPrevious.StartTime, 1))
|
||||||
|
holdFactor = 1.25;
|
||||||
|
|
||||||
|
closestEndTime = Math.Min(closestEndTime, Math.Abs(endTime - maniaPrevious.EndTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
// The hold addition is given if there was an overlap, however it is only valid if there are no other note with a similar ending.
|
||||||
|
// Releasing multiple notes is just as easy as releasing 1. Nerfs the hold addition by half if the closest release is release_threshold away.
|
||||||
|
// holdAddition
|
||||||
|
// ^
|
||||||
|
// 1.0 + - - - - - -+-----------
|
||||||
|
// | /
|
||||||
|
// 0.5 + - - - - -/ Sigmoid Curve
|
||||||
|
// | /|
|
||||||
|
// 0.0 +--------+-+---------------> Release Difference / ms
|
||||||
|
// release_threshold
|
||||||
|
if (isOverlapping)
|
||||||
|
holdAddition = DifficultyCalculationUtils.Logistic(x: closestEndTime, multiplier: 0.27, midpointOffset: release_threshold);
|
||||||
|
|
||||||
|
return (1 + holdAddition) * holdFactor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -65,13 +65,22 @@ namespace osu.Game.Rulesets.Mania.Difficulty
|
|||||||
protected override IEnumerable<DifficultyHitObject> CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate)
|
protected override IEnumerable<DifficultyHitObject> CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate)
|
||||||
{
|
{
|
||||||
var sortedObjects = beatmap.HitObjects.ToArray();
|
var sortedObjects = beatmap.HitObjects.ToArray();
|
||||||
|
int totalColumns = ((ManiaBeatmap)beatmap).TotalColumns;
|
||||||
|
|
||||||
LegacySortHelper<HitObject>.Sort(sortedObjects, Comparer<HitObject>.Create((a, b) => (int)Math.Round(a.StartTime) - (int)Math.Round(b.StartTime)));
|
LegacySortHelper<HitObject>.Sort(sortedObjects, Comparer<HitObject>.Create((a, b) => (int)Math.Round(a.StartTime) - (int)Math.Round(b.StartTime)));
|
||||||
|
|
||||||
List<DifficultyHitObject> objects = new List<DifficultyHitObject>();
|
List<DifficultyHitObject> objects = new List<DifficultyHitObject>();
|
||||||
|
List<DifficultyHitObject>[] perColumnObjects = new List<DifficultyHitObject>[totalColumns];
|
||||||
|
|
||||||
|
for (int column = 0; column < totalColumns; column++)
|
||||||
|
perColumnObjects[column] = new List<DifficultyHitObject>();
|
||||||
|
|
||||||
for (int i = 1; i < sortedObjects.Length; i++)
|
for (int i = 1; i < sortedObjects.Length; i++)
|
||||||
objects.Add(new ManiaDifficultyHitObject(sortedObjects[i], sortedObjects[i - 1], clockRate, objects, objects.Count));
|
{
|
||||||
|
var currentObject = new ManiaDifficultyHitObject(sortedObjects[i], sortedObjects[i - 1], clockRate, objects, perColumnObjects, objects.Count);
|
||||||
|
objects.Add(currentObject);
|
||||||
|
perColumnObjects[currentObject.Column].Add(currentObject);
|
||||||
|
}
|
||||||
|
|
||||||
return objects;
|
return objects;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,9 +12,59 @@ namespace osu.Game.Rulesets.Mania.Difficulty.Preprocessing
|
|||||||
{
|
{
|
||||||
public new ManiaHitObject BaseObject => (ManiaHitObject)base.BaseObject;
|
public new ManiaHitObject BaseObject => (ManiaHitObject)base.BaseObject;
|
||||||
|
|
||||||
public ManiaDifficultyHitObject(HitObject hitObject, HitObject lastObject, double clockRate, List<DifficultyHitObject> objects, int index)
|
private readonly List<DifficultyHitObject>[] perColumnObjects;
|
||||||
|
|
||||||
|
private readonly int columnIndex;
|
||||||
|
|
||||||
|
public readonly int Column;
|
||||||
|
|
||||||
|
// The hit object earlier in time than this note in each column
|
||||||
|
public readonly ManiaDifficultyHitObject?[] PreviousHitObjects;
|
||||||
|
|
||||||
|
public readonly double ColumnStrainTime;
|
||||||
|
|
||||||
|
public ManiaDifficultyHitObject(HitObject hitObject, HitObject lastObject, double clockRate, List<DifficultyHitObject> objects, List<DifficultyHitObject>[] perColumnObjects, int index)
|
||||||
: base(hitObject, lastObject, clockRate, objects, index)
|
: base(hitObject, lastObject, clockRate, objects, index)
|
||||||
{
|
{
|
||||||
|
int totalColumns = perColumnObjects.Length;
|
||||||
|
this.perColumnObjects = perColumnObjects;
|
||||||
|
Column = BaseObject.Column;
|
||||||
|
columnIndex = perColumnObjects[Column].Count;
|
||||||
|
PreviousHitObjects = new ManiaDifficultyHitObject[totalColumns];
|
||||||
|
ColumnStrainTime = StartTime - PrevInColumn(0)?.StartTime ?? StartTime;
|
||||||
|
|
||||||
|
if (index > 0)
|
||||||
|
{
|
||||||
|
ManiaDifficultyHitObject prevNote = (ManiaDifficultyHitObject)objects[index - 1];
|
||||||
|
|
||||||
|
for (int i = 0; i < prevNote.PreviousHitObjects.Length; i++)
|
||||||
|
PreviousHitObjects[i] = prevNote.PreviousHitObjects[i];
|
||||||
|
|
||||||
|
// intentionally depends on processing order to match live.
|
||||||
|
PreviousHitObjects[prevNote.Column] = prevNote;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The previous object in the same column as this <see cref="ManiaDifficultyHitObject"/>, exclusive of Long Note tails.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="backwardsIndex">The number of notes to go back.</param>
|
||||||
|
/// <returns>The object in this column <paramref name="backwardsIndex"/> notes back, or null if this is the first note in the column.</returns>
|
||||||
|
public ManiaDifficultyHitObject? PrevInColumn(int backwardsIndex)
|
||||||
|
{
|
||||||
|
int index = columnIndex - (backwardsIndex + 1);
|
||||||
|
return index >= 0 && index < perColumnObjects[Column].Count ? (ManiaDifficultyHitObject)perColumnObjects[Column][index] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The next object in the same column as this <see cref="ManiaDifficultyHitObject"/>, exclusive of Long Note tails.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="forwardsIndex">The number of notes to go forward.</param>
|
||||||
|
/// <returns>The object in this column <paramref name="forwardsIndex"/> notes forward, or null if this is the last note in the column.</returns>
|
||||||
|
public ManiaDifficultyHitObject? NextInColumn(int forwardsIndex)
|
||||||
|
{
|
||||||
|
int index = columnIndex + (forwardsIndex + 1);
|
||||||
|
return index >= 0 && index < perColumnObjects[Column].Count ? (ManiaDifficultyHitObject)perColumnObjects[Column][index] : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,9 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using osu.Framework.Utils;
|
|
||||||
using osu.Game.Rulesets.Difficulty.Preprocessing;
|
using osu.Game.Rulesets.Difficulty.Preprocessing;
|
||||||
using osu.Game.Rulesets.Difficulty.Skills;
|
using osu.Game.Rulesets.Difficulty.Skills;
|
||||||
using osu.Game.Rulesets.Difficulty.Utils;
|
using osu.Game.Rulesets.Mania.Difficulty.Evaluators;
|
||||||
using osu.Game.Rulesets.Mania.Difficulty.Preprocessing;
|
using osu.Game.Rulesets.Mania.Difficulty.Preprocessing;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
|
|
||||||
@@ -15,23 +14,17 @@ namespace osu.Game.Rulesets.Mania.Difficulty.Skills
|
|||||||
{
|
{
|
||||||
private const double individual_decay_base = 0.125;
|
private const double individual_decay_base = 0.125;
|
||||||
private const double overall_decay_base = 0.30;
|
private const double overall_decay_base = 0.30;
|
||||||
private const double release_threshold = 30;
|
|
||||||
|
|
||||||
protected override double SkillMultiplier => 1;
|
protected override double SkillMultiplier => 1;
|
||||||
protected override double StrainDecayBase => 1;
|
protected override double StrainDecayBase => 1;
|
||||||
|
|
||||||
private readonly double[] startTimes;
|
|
||||||
private readonly double[] endTimes;
|
|
||||||
private readonly double[] individualStrains;
|
private readonly double[] individualStrains;
|
||||||
|
private double highestIndividualStrain;
|
||||||
private double individualStrain;
|
|
||||||
private double overallStrain;
|
private double overallStrain;
|
||||||
|
|
||||||
public Strain(Mod[] mods, int totalColumns)
|
public Strain(Mod[] mods, int totalColumns)
|
||||||
: base(mods)
|
: base(mods)
|
||||||
{
|
{
|
||||||
startTimes = new double[totalColumns];
|
|
||||||
endTimes = new double[totalColumns];
|
|
||||||
individualStrains = new double[totalColumns];
|
individualStrains = new double[totalColumns];
|
||||||
overallStrain = 1;
|
overallStrain = 1;
|
||||||
}
|
}
|
||||||
@@ -39,64 +32,23 @@ namespace osu.Game.Rulesets.Mania.Difficulty.Skills
|
|||||||
protected override double StrainValueOf(DifficultyHitObject current)
|
protected override double StrainValueOf(DifficultyHitObject current)
|
||||||
{
|
{
|
||||||
var maniaCurrent = (ManiaDifficultyHitObject)current;
|
var maniaCurrent = (ManiaDifficultyHitObject)current;
|
||||||
double startTime = maniaCurrent.StartTime;
|
|
||||||
double endTime = maniaCurrent.EndTime;
|
|
||||||
int column = maniaCurrent.BaseObject.Column;
|
|
||||||
bool isOverlapping = false;
|
|
||||||
|
|
||||||
double closestEndTime = Math.Abs(endTime - startTime); // Lowest value we can assume with the current information
|
individualStrains[maniaCurrent.Column] = applyDecay(individualStrains[maniaCurrent.Column], maniaCurrent.ColumnStrainTime, individual_decay_base);
|
||||||
double holdFactor = 1.0; // Factor to all additional strains in case something else is held
|
individualStrains[maniaCurrent.Column] += IndividualStrainEvaluator.EvaluateDifficultyOf(current);
|
||||||
double holdAddition = 0; // Addition to the current note in case it's a hold and has to be released awkwardly
|
|
||||||
|
|
||||||
for (int i = 0; i < endTimes.Length; ++i)
|
// Take the hardest individualStrain for notes that happen at the same time (in a chord).
|
||||||
{
|
// This is to ensure the order in which the notes are processed does not affect the resultant total strain.
|
||||||
// The current note is overlapped if a previous note or end is overlapping the current note body
|
highestIndividualStrain = maniaCurrent.DeltaTime <= 1 ? Math.Max(highestIndividualStrain, individualStrains[maniaCurrent.Column]) : individualStrains[maniaCurrent.Column];
|
||||||
isOverlapping |= Precision.DefinitelyBigger(endTimes[i], startTime, 1) &&
|
|
||||||
Precision.DefinitelyBigger(endTime, endTimes[i], 1) &&
|
|
||||||
Precision.DefinitelyBigger(startTime, startTimes[i], 1);
|
|
||||||
|
|
||||||
// We give a slight bonus to everything if something is held meanwhile
|
overallStrain = applyDecay(overallStrain, maniaCurrent.DeltaTime, overall_decay_base);
|
||||||
if (Precision.DefinitelyBigger(endTimes[i], endTime, 1) &&
|
overallStrain += OverallStrainEvaluator.EvaluateDifficultyOf(current);
|
||||||
Precision.DefinitelyBigger(startTime, startTimes[i], 1))
|
|
||||||
holdFactor = 1.25;
|
|
||||||
|
|
||||||
closestEndTime = Math.Min(closestEndTime, Math.Abs(endTime - endTimes[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
// The hold addition is given if there was an overlap, however it is only valid if there are no other note with a similar ending.
|
|
||||||
// Releasing multiple notes is just as easy as releasing 1. Nerfs the hold addition by half if the closest release is release_threshold away.
|
|
||||||
// holdAddition
|
|
||||||
// ^
|
|
||||||
// 1.0 + - - - - - -+-----------
|
|
||||||
// | /
|
|
||||||
// 0.5 + - - - - -/ Sigmoid Curve
|
|
||||||
// | /|
|
|
||||||
// 0.0 +--------+-+---------------> Release Difference / ms
|
|
||||||
// release_threshold
|
|
||||||
if (isOverlapping)
|
|
||||||
holdAddition = DifficultyCalculationUtils.Logistic(x: closestEndTime, multiplier: 0.27, midpointOffset: release_threshold);
|
|
||||||
|
|
||||||
// Decay and increase individualStrains in own column
|
|
||||||
individualStrains[column] = applyDecay(individualStrains[column], startTime - startTimes[column], individual_decay_base);
|
|
||||||
individualStrains[column] += 2.0 * holdFactor;
|
|
||||||
|
|
||||||
// For notes at the same time (in a chord), the individualStrain should be the hardest individualStrain out of those columns
|
|
||||||
individualStrain = maniaCurrent.DeltaTime <= 1 ? Math.Max(individualStrain, individualStrains[column]) : individualStrains[column];
|
|
||||||
|
|
||||||
// Decay and increase overallStrain
|
|
||||||
overallStrain = applyDecay(overallStrain, current.DeltaTime, overall_decay_base);
|
|
||||||
overallStrain += (1 + holdAddition) * holdFactor;
|
|
||||||
|
|
||||||
// Update startTimes and endTimes arrays
|
|
||||||
startTimes[column] = startTime;
|
|
||||||
endTimes[column] = endTime;
|
|
||||||
|
|
||||||
// By subtracting CurrentStrain, this skill effectively only considers the maximum strain of any one hitobject within each strain section.
|
// By subtracting CurrentStrain, this skill effectively only considers the maximum strain of any one hitobject within each strain section.
|
||||||
return individualStrain + overallStrain - CurrentStrain;
|
return highestIndividualStrain + overallStrain - CurrentStrain;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override double CalculateInitialStrain(double offset, DifficultyHitObject current)
|
protected override double CalculateInitialStrain(double offset, DifficultyHitObject current) =>
|
||||||
=> applyDecay(individualStrain, offset - current.Previous(0).StartTime, individual_decay_base)
|
applyDecay(highestIndividualStrain, offset - current.Previous(0).StartTime, individual_decay_base)
|
||||||
+ applyDecay(overallStrain, offset - current.Previous(0).StartTime, overall_decay_base);
|
+ applyDecay(overallStrain, offset - current.Previous(0).StartTime, overall_decay_base);
|
||||||
|
|
||||||
private double applyDecay(double value, double deltaTime, double decayBase)
|
private double applyDecay(double value, double deltaTime, double decayBase)
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private IScrollingInfo scrollingInfo { get; set; } = null!;
|
private IScrollingInfo scrollingInfo { get; set; } = null!;
|
||||||
|
|
||||||
protected override bool IsValidForPlacement => Precision.DefinitelyBigger(HitObject.Duration, 0);
|
protected override bool IsValidForPlacement => base.IsValidForPlacement && (PlacementActive == PlacementState.Waiting || Precision.DefinitelyBigger(HitObject.Duration, 0));
|
||||||
|
|
||||||
public HoldNotePlacementBlueprint()
|
public HoldNotePlacementBlueprint()
|
||||||
: base(new HoldNote())
|
: base(new HoldNote())
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Edit;
|
using osu.Game.Rulesets.Edit;
|
||||||
using osu.Game.Rulesets.Edit.Tools;
|
using osu.Game.Rulesets.Edit.Tools;
|
||||||
@@ -54,7 +56,8 @@ namespace osu.Game.Rulesets.Mania.Edit
|
|||||||
};
|
};
|
||||||
|
|
||||||
public override string ConvertSelectionToString()
|
public override string ConvertSelectionToString()
|
||||||
=> string.Join(',', EditorBeatmap.SelectedHitObjects.Cast<ManiaHitObject>().OrderBy(h => h.StartTime).Select(h => $"{h.StartTime}|{h.Column}"));
|
=> string.Join(',', EditorBeatmap.SelectedHitObjects.Cast<ManiaHitObject>().OrderBy(h => h.StartTime)
|
||||||
|
.Select(h => FormattableString.Invariant($"{Math.Round(h.StartTime)}|{h.Column}")));
|
||||||
|
|
||||||
// 123|0,456|1,789|2 ...
|
// 123|0,456|1,789|2 ...
|
||||||
private static readonly Regex selection_regex = new Regex(@"^\d+\|\d+(,\d+\|\d+)*$", RegexOptions.Compiled);
|
private static readonly Regex selection_regex = new Regex(@"^\d+\|\d+(,\d+\|\d+)*$", RegexOptions.Compiled);
|
||||||
@@ -73,10 +76,10 @@ namespace osu.Game.Rulesets.Mania.Edit
|
|||||||
if (split.Length != 2)
|
if (split.Length != 2)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!double.TryParse(split[0], out double time) || !int.TryParse(split[1], out int column))
|
if (!int.TryParse(split[0], out int time) || !int.TryParse(split[1], out int column))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ManiaHitObject? current = remainingHitObjects.FirstOrDefault(h => h.StartTime == time && h.Column == column);
|
ManiaHitObject? current = remainingHitObjects.FirstOrDefault(h => Precision.AlmostEquals(h.StartTime, time, 0.5) && h.Column == column);
|
||||||
|
|
||||||
if (current == null)
|
if (current == null)
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -383,7 +383,7 @@ namespace osu.Game.Rulesets.Mania
|
|||||||
return (PlayfieldType)Enum.GetValues(typeof(PlayfieldType)).Cast<int>().OrderDescending().First(v => variant >= v);
|
return (PlayfieldType)Enum.GetValues(typeof(PlayfieldType)).Cast<int>().OrderDescending().First(v => variant >= v);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override IEnumerable<HitResult> GetValidHitResults()
|
public override IEnumerable<HitResult> GetValidHitResults()
|
||||||
{
|
{
|
||||||
return new[]
|
return new[]
|
||||||
{
|
{
|
||||||
@@ -392,9 +392,11 @@ namespace osu.Game.Rulesets.Mania
|
|||||||
HitResult.Good,
|
HitResult.Good,
|
||||||
HitResult.Ok,
|
HitResult.Ok,
|
||||||
HitResult.Meh,
|
HitResult.Meh,
|
||||||
|
HitResult.Miss,
|
||||||
|
|
||||||
// HitResult.SmallBonus is used for awarding perfect bonus score but is not included here as
|
HitResult.IgnoreHit,
|
||||||
// it would be a bit redundant to show this to the user.
|
HitResult.ComboBreak,
|
||||||
|
HitResult.IgnoreMiss,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ using osu.Framework;
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterfaceV2;
|
||||||
using osu.Game.Localisation;
|
using osu.Game.Localisation;
|
||||||
using osu.Game.Overlays.Settings;
|
using osu.Game.Overlays.Settings;
|
||||||
using osu.Game.Rulesets.Mania.Configuration;
|
using osu.Game.Rulesets.Mania.Configuration;
|
||||||
@@ -31,47 +31,45 @@ namespace osu.Game.Rulesets.Mania
|
|||||||
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
new SettingsEnumDropdown<ManiaScrollingDirection>
|
new SettingsItemV2(new FormEnumDropdown<ManiaScrollingDirection>
|
||||||
{
|
{
|
||||||
LabelText = RulesetSettingsStrings.ScrollingDirection,
|
Caption = RulesetSettingsStrings.ScrollingDirection,
|
||||||
Current = config.GetBindable<ManiaScrollingDirection>(ManiaRulesetSetting.ScrollDirection)
|
Current = config.GetBindable<ManiaScrollingDirection>(ManiaRulesetSetting.ScrollDirection)
|
||||||
},
|
}),
|
||||||
new SettingsSlider<double, ManiaScrollSlider>
|
new SettingsItemV2(new FormSliderBar<double>
|
||||||
{
|
{
|
||||||
LabelText = RulesetSettingsStrings.ScrollSpeed,
|
Caption = RulesetSettingsStrings.ScrollSpeed,
|
||||||
Current = config.GetBindable<double>(ManiaRulesetSetting.ScrollSpeed),
|
Current = config.GetBindable<double>(ManiaRulesetSetting.ScrollSpeed),
|
||||||
KeyboardStep = 1
|
KeyboardStep = 1,
|
||||||
},
|
LabelFormat = v => RulesetSettingsStrings.ScrollSpeedTooltip((int)DrawableManiaRuleset.ComputeScrollTime(v), v),
|
||||||
new SettingsCheckbox
|
}),
|
||||||
|
new SettingsItemV2(new FormCheckBox
|
||||||
|
{
|
||||||
|
Caption = RulesetSettingsStrings.TimingBasedColouring,
|
||||||
|
Current = config.GetBindable<bool>(ManiaRulesetSetting.TimingBasedNoteColouring),
|
||||||
|
})
|
||||||
{
|
{
|
||||||
Keywords = new[] { "color" },
|
Keywords = new[] { "color" },
|
||||||
LabelText = RulesetSettingsStrings.TimingBasedColouring,
|
|
||||||
Current = config.GetBindable<bool>(ManiaRulesetSetting.TimingBasedNoteColouring),
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
Add(new SettingsCheckbox
|
Add(new SettingsItemV2(new FormCheckBox
|
||||||
{
|
{
|
||||||
LabelText = RulesetSettingsStrings.TouchOverlay,
|
Caption = RulesetSettingsStrings.TouchOverlay,
|
||||||
Current = config.GetBindable<bool>(ManiaRulesetSetting.TouchOverlay)
|
Current = config.GetBindable<bool>(ManiaRulesetSetting.TouchOverlay)
|
||||||
});
|
}));
|
||||||
|
|
||||||
if (RuntimeInfo.IsMobile)
|
if (RuntimeInfo.IsMobile)
|
||||||
{
|
{
|
||||||
Add(new SettingsEnumDropdown<ManiaMobileLayout>
|
Add(new SettingsItemV2(new FormEnumDropdown<ManiaMobileLayout>
|
||||||
{
|
{
|
||||||
LabelText = RulesetSettingsStrings.MobileLayout,
|
Caption = RulesetSettingsStrings.MobileLayout,
|
||||||
Current = config.GetBindable<ManiaMobileLayout>(ManiaRulesetSetting.MobileLayout),
|
Current = config.GetBindable<ManiaMobileLayout>(ManiaRulesetSetting.MobileLayout),
|
||||||
#pragma warning disable CS0618 // Type or member is obsolete
|
#pragma warning disable CS0618 // Type or member is obsolete
|
||||||
Items = Enum.GetValues<ManiaMobileLayout>().Where(l => l != ManiaMobileLayout.LandscapeWithOverlay),
|
Items = Enum.GetValues<ManiaMobileLayout>().Where(l => l != ManiaMobileLayout.LandscapeWithOverlay),
|
||||||
#pragma warning restore CS0618 // Type or member is obsolete
|
#pragma warning restore CS0618 // Type or member is obsolete
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private partial class ManiaScrollSlider : RoundedSliderBar<double>
|
|
||||||
{
|
|
||||||
public override LocalisableString TooltipText => RulesetSettingsStrings.ScrollSpeedTooltip((int)DrawableManiaRuleset.ComputeScrollTime(Current.Value), Current.Value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,8 @@ namespace osu.Game.Rulesets.Mania.Mods
|
|||||||
public override string Acronym => Name;
|
public override string Acronym => Name;
|
||||||
public abstract int KeyCount { get; }
|
public abstract int KeyCount { get; }
|
||||||
public override ModType Type => ModType.Conversion;
|
public override ModType Type => ModType.Conversion;
|
||||||
public override double ScoreMultiplier => 0.9;
|
public override double ScoreMultiplier => 1;
|
||||||
public override bool Ranked => UsesDefaultConfiguration;
|
public override bool Ranked => true;
|
||||||
|
|
||||||
public void ApplyToBeatmapConverter(IBeatmapConverter beatmapConverter)
|
public void ApplyToBeatmapConverter(IBeatmapConverter beatmapConverter)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
|||||||
typeof(ManiaModFadeIn)
|
typeof(ManiaModFadeIn)
|
||||||
}).ToArray();
|
}).ToArray();
|
||||||
|
|
||||||
public override bool Ranked => false;
|
public override bool Ranked => true;
|
||||||
|
|
||||||
public override bool ValidForFreestyleAsRequiredMod => false;
|
public override bool ValidForFreestyleAsRequiredMod => false;
|
||||||
|
|
||||||
|
|||||||
@@ -7,5 +7,20 @@ namespace osu.Game.Rulesets.Mania.Mods
|
|||||||
{
|
{
|
||||||
public class ManiaModDifficultyAdjust : ModDifficultyAdjust
|
public class ManiaModDifficultyAdjust : ModDifficultyAdjust
|
||||||
{
|
{
|
||||||
|
public override DifficultyBindable OverallDifficulty { get; } = new DifficultyBindable
|
||||||
|
{
|
||||||
|
Precision = 0.1f,
|
||||||
|
MinValue = 0,
|
||||||
|
MaxValue = 10,
|
||||||
|
// Use larger extended limits for mania to include OD values that occur with EZ or HR enabled
|
||||||
|
#if !DEBUG
|
||||||
|
ExtendedMaxValue = 15,
|
||||||
|
ExtendedMinValue = -15,
|
||||||
|
#else
|
||||||
|
ExtendedMinValue = -250,
|
||||||
|
ExtendedMaxValue = 50,
|
||||||
|
#endif
|
||||||
|
ReadCurrentFromDifficulty = diff => diff.OverallDifficulty,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
|||||||
public class ManiaModHardRock : ModHardRock, IApplicableToHitObject
|
public class ManiaModHardRock : ModHardRock, IApplicableToHitObject
|
||||||
{
|
{
|
||||||
public override double ScoreMultiplier => 1;
|
public override double ScoreMultiplier => 1;
|
||||||
public override bool Ranked => false;
|
public override bool Ranked => true;
|
||||||
|
|
||||||
public const double HIT_WINDOW_DIFFICULTY_MULTIPLIER = 1.4;
|
public const double HIT_WINDOW_DIFFICULTY_MULTIPLIER = 1.4;
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ using osu.Game.Rulesets.Mods;
|
|||||||
using osu.Framework.Graphics.Sprites;
|
using osu.Framework.Graphics.Sprites;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Localisation;
|
using osu.Framework.Localisation;
|
||||||
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||||
|
|
||||||
@@ -34,6 +35,8 @@ namespace osu.Game.Rulesets.Mania.Mods
|
|||||||
{
|
{
|
||||||
var maniaBeatmap = (ManiaBeatmap)beatmap;
|
var maniaBeatmap = (ManiaBeatmap)beatmap;
|
||||||
|
|
||||||
|
double mostCommonBeatLengthBefore = beatmap.GetMostCommonBeatLength();
|
||||||
|
|
||||||
var newObjects = new List<ManiaHitObject>();
|
var newObjects = new List<ManiaHitObject>();
|
||||||
|
|
||||||
foreach (var h in beatmap.HitObjects.OfType<HoldNote>())
|
foreach (var h in beatmap.HitObjects.OfType<HoldNote>())
|
||||||
@@ -48,6 +51,17 @@ namespace osu.Game.Rulesets.Mania.Mods
|
|||||||
}
|
}
|
||||||
|
|
||||||
maniaBeatmap.HitObjects = maniaBeatmap.HitObjects.OfType<Note>().Concat(newObjects).OrderBy(h => h.StartTime).ToList();
|
maniaBeatmap.HitObjects = maniaBeatmap.HitObjects.OfType<Note>().Concat(newObjects).OrderBy(h => h.StartTime).ToList();
|
||||||
|
|
||||||
|
double mostCommonBeatLengthAfter = beatmap.GetMostCommonBeatLength();
|
||||||
|
|
||||||
|
// the process of removing hold notes can result in shortening the beatmap's play time,
|
||||||
|
// and therefore, as a side effect, changing the most common BPM, which will change scroll speed.
|
||||||
|
// to compensate for this, apply a multiplier to effect points in order to maintain the beatmap's original intended scroll speed.
|
||||||
|
if (!Precision.AlmostEquals(mostCommonBeatLengthBefore, mostCommonBeatLengthAfter))
|
||||||
|
{
|
||||||
|
foreach (var effectPoint in beatmap.ControlPointInfo.EffectPoints)
|
||||||
|
effectPoint.ScrollSpeed *= mostCommonBeatLengthBefore / mostCommonBeatLengthAfter;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,5 @@ namespace osu.Game.Rulesets.Mania.Mods
|
|||||||
public override string Acronym => "1K";
|
public override string Acronym => "1K";
|
||||||
public override IconUsage? Icon => OsuIcon.ModOneKey;
|
public override IconUsage? Icon => OsuIcon.ModOneKey;
|
||||||
public override LocalisableString Description => @"Play with one key.";
|
public override LocalisableString Description => @"Play with one key.";
|
||||||
public override bool Ranked => false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,5 @@ namespace osu.Game.Rulesets.Mania.Mods
|
|||||||
public override string Acronym => "10K";
|
public override string Acronym => "10K";
|
||||||
public override IconUsage? Icon => OsuIcon.ModTenKeys;
|
public override IconUsage? Icon => OsuIcon.ModTenKeys;
|
||||||
public override LocalisableString Description => @"Play with ten keys.";
|
public override LocalisableString Description => @"Play with ten keys.";
|
||||||
public override bool Ranked => false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,5 @@ namespace osu.Game.Rulesets.Mania.Mods
|
|||||||
public override string Acronym => "2K";
|
public override string Acronym => "2K";
|
||||||
public override IconUsage? Icon => OsuIcon.ModTwoKeys;
|
public override IconUsage? Icon => OsuIcon.ModTwoKeys;
|
||||||
public override LocalisableString Description => @"Play with two keys.";
|
public override LocalisableString Description => @"Play with two keys.";
|
||||||
public override bool Ranked => false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,5 @@ namespace osu.Game.Rulesets.Mania.Mods
|
|||||||
public override string Acronym => "3K";
|
public override string Acronym => "3K";
|
||||||
public override IconUsage? Icon => OsuIcon.ModThreeKeys;
|
public override IconUsage? Icon => OsuIcon.ModThreeKeys;
|
||||||
public override LocalisableString Description => @"Play with three keys.";
|
public override LocalisableString Description => @"Play with three keys.";
|
||||||
public override bool Ranked => false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
|||||||
public class ManiaModMirror : ModMirror, IApplicableToBeatmap
|
public class ManiaModMirror : ModMirror, IApplicableToBeatmap
|
||||||
{
|
{
|
||||||
public override LocalisableString Description => "Notes are flipped horizontally.";
|
public override LocalisableString Description => "Notes are flipped horizontally.";
|
||||||
public override bool Ranked => UsesDefaultConfiguration;
|
public override bool Ranked => true;
|
||||||
|
|
||||||
public void ApplyToBeatmap(IBeatmap beatmap)
|
public void ApplyToBeatmap(IBeatmap beatmap)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -57,6 +57,9 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
|||||||
|
|
||||||
if (spectatorList != null)
|
if (spectatorList != null)
|
||||||
spectatorList.Position = new Vector2(36, -66);
|
spectatorList.Position = new Vector2(36, -66);
|
||||||
|
|
||||||
|
foreach (var d in container.OfType<ISerialisableDrawable>())
|
||||||
|
d.UsesFixedAnchor = true;
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
new DrawableGameplayLeaderboard(),
|
new DrawableGameplayLeaderboard(),
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
|||||||
|
|
||||||
private Drawable noteAnimation = null!;
|
private Drawable noteAnimation = null!;
|
||||||
|
|
||||||
private float? minimumColumnWidth;
|
private float? widthForNoteHeightScale;
|
||||||
|
|
||||||
public LegacyNotePiece()
|
public LegacyNotePiece()
|
||||||
{
|
{
|
||||||
@@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(ISkinSource skin, IScrollingInfo scrollingInfo)
|
private void load(ISkinSource skin, IScrollingInfo scrollingInfo)
|
||||||
{
|
{
|
||||||
minimumColumnWidth = skin.GetConfig<ManiaSkinConfigurationLookup, float>(new ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups.MinimumColumnWidth))?.Value;
|
widthForNoteHeightScale = skin.GetConfig<ManiaSkinConfigurationLookup, float>(new ManiaSkinConfigurationLookup(LegacyManiaSkinConfigurationLookups.WidthForNoteHeightScale))?.Value;
|
||||||
|
|
||||||
InternalChild = directionContainer = new Container
|
InternalChild = directionContainer = new Container
|
||||||
{
|
{
|
||||||
@@ -60,9 +60,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
|||||||
|
|
||||||
if (texture != null)
|
if (texture != null)
|
||||||
{
|
{
|
||||||
// The height is scaled to the minimum column width, if provided.
|
float noteHeight = widthForNoteHeightScale ?? DrawWidth;
|
||||||
float minimumWidth = minimumColumnWidth ?? DrawWidth;
|
noteAnimation.Scale = Vector2.Divide(new Vector2(DrawWidth, noteHeight), texture.DisplayWidth);
|
||||||
noteAnimation.Scale = Vector2.Divide(new Vector2(DrawWidth, minimumWidth), texture.DisplayWidth);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,11 +64,13 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
|||||||
private readonly Lazy<bool> hasKeyTexture;
|
private readonly Lazy<bool> hasKeyTexture;
|
||||||
|
|
||||||
private readonly ManiaBeatmap beatmap;
|
private readonly ManiaBeatmap beatmap;
|
||||||
|
private readonly bool isBeatmapConverted;
|
||||||
|
|
||||||
public ManiaLegacySkinTransformer(ISkin skin, IBeatmap beatmap)
|
public ManiaLegacySkinTransformer(ISkin skin, IBeatmap beatmap)
|
||||||
: base(skin)
|
: base(skin)
|
||||||
{
|
{
|
||||||
this.beatmap = (ManiaBeatmap)beatmap;
|
this.beatmap = (ManiaBeatmap)beatmap;
|
||||||
|
isBeatmapConverted = !beatmap.BeatmapInfo.Ruleset.Equals(new ManiaRuleset().RulesetInfo);
|
||||||
|
|
||||||
isLegacySkin = new Lazy<bool>(() => GetConfig<SkinConfiguration.LegacySetting, decimal>(SkinConfiguration.LegacySetting.Version) != null);
|
isLegacySkin = new Lazy<bool>(() => GetConfig<SkinConfiguration.LegacySetting, decimal>(SkinConfiguration.LegacySetting.Version) != null);
|
||||||
hasKeyTexture = new Lazy<bool>(() =>
|
hasKeyTexture = new Lazy<bool>(() =>
|
||||||
@@ -120,6 +122,9 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
|||||||
leaderboard.Origin = Anchor.CentreLeft;
|
leaderboard.Origin = Anchor.CentreLeft;
|
||||||
leaderboard.X = 10;
|
leaderboard.X = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var d in container.OfType<ISerialisableDrawable>())
|
||||||
|
d.UsesFixedAnchor = true;
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
new LegacyManiaComboCounter(),
|
new LegacyManiaComboCounter(),
|
||||||
@@ -196,8 +201,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
|||||||
|
|
||||||
public override ISample GetSample(ISampleInfo sampleInfo)
|
public override ISample GetSample(ISampleInfo sampleInfo)
|
||||||
{
|
{
|
||||||
// layered hit sounds never play in mania
|
// layered hit sounds never play in mania-native beatmaps (but do play on converts)
|
||||||
if (sampleInfo is ConvertHitObjectParser.LegacyHitSampleInfo legacySample && legacySample.IsLayered)
|
if (sampleInfo is ConvertHitObjectParser.LegacyHitSampleInfo legacySample && legacySample.IsLayered && !isBeatmapConverted)
|
||||||
return new SampleVirtual();
|
return new SampleVirtual();
|
||||||
|
|
||||||
return base.GetSample(sampleInfo);
|
return base.GetSample(sampleInfo);
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ namespace osu.Game.Rulesets.Mania.UI
|
|||||||
|
|
||||||
var hitWindows = new ManiaHitWindows();
|
var hitWindows = new ManiaHitWindows();
|
||||||
|
|
||||||
AddInternal(judgementPooler = new JudgementPooler<DrawableManiaJudgement>(Enum.GetValues<HitResult>().Where(r => hitWindows.IsHitResultAllowed(r))));
|
AddInternal(judgementPooler = new JudgementPooler<DrawableManiaJudgement>(Enum.GetValues<HitResult>().Where(hitWindows.IsHitResultAllowed)));
|
||||||
|
|
||||||
RegisterPool<BarLine, DrawableBarLine>(50, 200);
|
RegisterPool<BarLine, DrawableBarLine>(50, 200);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
<PropertyGroup Label="Nuget">
|
<PropertyGroup Label="Nuget">
|
||||||
<Title>osu!mania (ruleset)</Title>
|
<Title>osu!mania (ruleset)</Title>
|
||||||
<PackageId>ppy.osu.Game.Rulesets.Mania</PackageId>
|
<PackageId>jvnkosu.Client.Rulesets.Mania</PackageId>
|
||||||
<IsPackable>true</IsPackable>
|
<IsPackable>true</IsPackable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -35,8 +35,6 @@
|
|||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
</array>
|
</array>
|
||||||
<key>XSAppIconAssets</key>
|
|
||||||
<string>Assets.xcassets/AppIcon.appiconset</string>
|
|
||||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||||
|
|||||||
@@ -245,13 +245,13 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
|||||||
AddAssert("grid spacing is distance to slider tail", () =>
|
AddAssert("grid spacing is distance to slider tail", () =>
|
||||||
{
|
{
|
||||||
var composer = Editor.ChildrenOfType<RectangularPositionSnapGrid>().Single();
|
var composer = Editor.ChildrenOfType<RectangularPositionSnapGrid>().Single();
|
||||||
return Precision.AlmostEquals(composer.Spacing.Value.X, 32.05, 0.01)
|
return Precision.AlmostEquals(composer.Spacing.Value.X, 32.05, 0.1)
|
||||||
&& Precision.AlmostEquals(composer.Spacing.Value.X, composer.Spacing.Value.Y);
|
&& Precision.AlmostEquals(composer.Spacing.Value.X, composer.Spacing.Value.Y);
|
||||||
});
|
});
|
||||||
AddAssert("grid rotation points to slider tail", () =>
|
AddAssert("grid rotation points to slider tail", () =>
|
||||||
{
|
{
|
||||||
var composer = Editor.ChildrenOfType<RectangularPositionSnapGrid>().Single();
|
var composer = Editor.ChildrenOfType<RectangularPositionSnapGrid>().Single();
|
||||||
return Precision.AlmostEquals(composer.GridLineRotation.Value, 0.09, 0.01);
|
return Precision.AlmostEquals(composer.GridLineRotation.Value, 0.09, 0.1);
|
||||||
});
|
});
|
||||||
|
|
||||||
AddStep("start grid placement", () => InputManager.Key(Key.Number5));
|
AddStep("start grid placement", () => InputManager.Key(Key.Number5));
|
||||||
@@ -280,9 +280,9 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
|||||||
AddAssert("grid spacing and rotation unchanged", () =>
|
AddAssert("grid spacing and rotation unchanged", () =>
|
||||||
{
|
{
|
||||||
var composer = Editor.ChildrenOfType<RectangularPositionSnapGrid>().Single();
|
var composer = Editor.ChildrenOfType<RectangularPositionSnapGrid>().Single();
|
||||||
return Precision.AlmostEquals(composer.Spacing.Value.X, 32.05, 0.01)
|
return Precision.AlmostEquals(composer.Spacing.Value.X, 32.05, 0.1)
|
||||||
&& Precision.AlmostEquals(composer.Spacing.Value.X, composer.Spacing.Value.Y)
|
&& Precision.AlmostEquals(composer.Spacing.Value.X, composer.Spacing.Value.Y)
|
||||||
&& Precision.AlmostEquals(composer.GridLineRotation.Value, 0.09, 0.01);
|
&& Precision.AlmostEquals(composer.GridLineRotation.Value, 0.09, 0.1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using osu.Framework.Graphics.Containers;
|
|||||||
using osu.Framework.Input;
|
using osu.Framework.Input;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Beatmaps.ControlPoints;
|
||||||
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders;
|
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders;
|
||||||
using osu.Game.Rulesets.Osu.Objects;
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
@@ -22,7 +23,12 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
|||||||
[TestFixture]
|
[TestFixture]
|
||||||
public partial class TestSceneSliderDrawing : TestSceneOsuEditor
|
public partial class TestSceneSliderDrawing : TestSceneOsuEditor
|
||||||
{
|
{
|
||||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset, false);
|
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||||
|
{
|
||||||
|
var beatmap = new TestBeatmap(ruleset, false);
|
||||||
|
beatmap.ControlPointInfo.Add(0, new TimingControlPoint());
|
||||||
|
return beatmap;
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestTouchInputPlaceHitCircleDirectly()
|
public void TestTouchInputPlaceHitCircleDirectly()
|
||||||
|
|||||||
@@ -3,10 +3,13 @@
|
|||||||
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Testing;
|
||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
|
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders;
|
||||||
|
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders.Components;
|
||||||
using osu.Game.Rulesets.Osu.Objects;
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
using osu.Game.Rulesets.Osu.UI;
|
using osu.Game.Rulesets.Osu.UI;
|
||||||
using osu.Game.Tests.Beatmaps;
|
using osu.Game.Tests.Beatmaps;
|
||||||
@@ -30,6 +33,16 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
|||||||
PathType.LINEAR,
|
PathType.LINEAR,
|
||||||
new Vector2(100, 0),
|
new Vector2(100, 0),
|
||||||
new Vector2(100, 100)
|
new Vector2(100, 100)
|
||||||
|
),
|
||||||
|
createPathSegment(
|
||||||
|
PathType.PERFECT_CURVE,
|
||||||
|
new Vector2(100.009f, -50.0009f),
|
||||||
|
new Vector2(200.0089f, -100)
|
||||||
|
),
|
||||||
|
createPathSegment(
|
||||||
|
PathType.PERFECT_CURVE,
|
||||||
|
new Vector2(25, -50),
|
||||||
|
new Vector2(100, 75)
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -48,9 +61,13 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
|||||||
|
|
||||||
[TestCase(0, 250)]
|
[TestCase(0, 250)]
|
||||||
[TestCase(0, 200)]
|
[TestCase(0, 200)]
|
||||||
[TestCase(1, 120)]
|
[TestCase(1, 120, false, false)]
|
||||||
[TestCase(1, 80)]
|
[TestCase(1, 80, false, false)]
|
||||||
public void TestSliderReversal(int pathIndex, double length)
|
[TestCase(2, 250)]
|
||||||
|
[TestCase(2, 190)]
|
||||||
|
[TestCase(3, 250)]
|
||||||
|
[TestCase(3, 190)]
|
||||||
|
public void TestSliderReversal(int pathIndex, double length, bool assertEqualDistances = true, bool assertSliderReduction = true)
|
||||||
{
|
{
|
||||||
var controlPoints = paths[pathIndex];
|
var controlPoints = paths[pathIndex];
|
||||||
|
|
||||||
@@ -90,6 +107,215 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
|||||||
InputManager.ReleaseKey(Key.LControl);
|
InputManager.ReleaseKey(Key.LControl);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (pathIndex == 2)
|
||||||
|
{
|
||||||
|
AddRepeatStep("Reverse slider again", () =>
|
||||||
|
{
|
||||||
|
InputManager.PressKey(Key.LControl);
|
||||||
|
InputManager.Key(Key.G);
|
||||||
|
InputManager.ReleaseKey(Key.LControl);
|
||||||
|
}, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (assertEqualDistances)
|
||||||
|
{
|
||||||
|
AddAssert("Middle control point has the same distance from start to end", () =>
|
||||||
|
{
|
||||||
|
var pathControlPoints = selectedSlider.Path.ControlPoints;
|
||||||
|
float middleToStart = Vector2.Distance(pathControlPoints[^2].Position, pathControlPoints[0].Position);
|
||||||
|
float middleToEnd = Vector2.Distance(pathControlPoints[^2].Position, pathControlPoints[^1].Position);
|
||||||
|
|
||||||
|
return Precision.AlmostEquals(middleToStart, middleToEnd, 1f);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
AddAssert("Middle control point is not at start or end", () =>
|
||||||
|
Vector2.Distance(selectedSlider.Path.ControlPoints[^2].Position, oldStartPos) > 1 &&
|
||||||
|
Vector2.Distance(selectedSlider.Path.ControlPoints[^2].Position, oldEndPos) > 1
|
||||||
|
);
|
||||||
|
|
||||||
|
AddAssert("Slider has correct length", () =>
|
||||||
|
Precision.AlmostEquals(selectedSlider.Path.Distance, oldDistance));
|
||||||
|
|
||||||
|
AddAssert("Slider has correct start position", () =>
|
||||||
|
Vector2.Distance(selectedSlider.Position, oldEndPos) < 1);
|
||||||
|
|
||||||
|
AddAssert("Slider has correct end position", () =>
|
||||||
|
Vector2.Distance(selectedSlider.EndPosition, oldStartPos) < 1);
|
||||||
|
|
||||||
|
AddAssert("Control points have correct types", () =>
|
||||||
|
{
|
||||||
|
var newControlPointTypes = selectedSlider.Path.ControlPoints.Select(p => p.Type).ToArray();
|
||||||
|
|
||||||
|
return oldControlPointTypes.Take(newControlPointTypes.Length).SequenceEqual(newControlPointTypes);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (assertSliderReduction)
|
||||||
|
{
|
||||||
|
AddStep("Move to marker", () =>
|
||||||
|
{
|
||||||
|
var marker = this.ChildrenOfType<SliderEndDragMarker>().Single();
|
||||||
|
var markerPos = (marker.ScreenSpaceDrawQuad.TopRight + marker.ScreenSpaceDrawQuad.BottomRight) / 2;
|
||||||
|
// sometimes the cursor may miss the marker's hitbox so we
|
||||||
|
// add a little offset here to be sure it lands in a clickable position.
|
||||||
|
var position = new Vector2(markerPos.X + 2f, markerPos.Y);
|
||||||
|
InputManager.MoveMouseTo(position);
|
||||||
|
});
|
||||||
|
AddStep("Click", () => InputManager.PressButton(MouseButton.Left));
|
||||||
|
AddStep("Reduce slider", () =>
|
||||||
|
{
|
||||||
|
var middleControlPoint = this.ChildrenOfType<PathControlPointPiece<Slider>>().ToArray()[^2];
|
||||||
|
InputManager.MoveMouseTo(middleControlPoint);
|
||||||
|
});
|
||||||
|
AddStep("Release click", () => InputManager.ReleaseButton(MouseButton.Left));
|
||||||
|
|
||||||
|
AddStep("Save half slider info", () =>
|
||||||
|
{
|
||||||
|
oldStartPos = selectedSlider.Position;
|
||||||
|
oldEndPos = selectedSlider.EndPosition;
|
||||||
|
oldDistance = selectedSlider.Path.Distance;
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("Reverse slider", () =>
|
||||||
|
{
|
||||||
|
InputManager.PressKey(Key.LControl);
|
||||||
|
InputManager.Key(Key.G);
|
||||||
|
InputManager.ReleaseKey(Key.LControl);
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("Middle control point has the same distance from start to end", () =>
|
||||||
|
{
|
||||||
|
var pathControlPoints = selectedSlider.Path.ControlPoints;
|
||||||
|
float middleToStart = Vector2.Distance(pathControlPoints[^2].Position, pathControlPoints[0].Position);
|
||||||
|
float middleToEnd = Vector2.Distance(pathControlPoints[^2].Position, pathControlPoints[^1].Position);
|
||||||
|
|
||||||
|
return Precision.AlmostEquals(middleToStart, middleToEnd, 1f);
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("Middle control point is not at start or end", () =>
|
||||||
|
Vector2.Distance(selectedSlider.Path.ControlPoints[^2].Position, oldStartPos) > 1 &&
|
||||||
|
Vector2.Distance(selectedSlider.Path.ControlPoints[^2].Position, oldEndPos) > 1
|
||||||
|
);
|
||||||
|
|
||||||
|
AddAssert("Slider has correct length", () =>
|
||||||
|
Precision.AlmostEquals(selectedSlider.Path.Distance, oldDistance));
|
||||||
|
|
||||||
|
AddAssert("Slider has correct start position", () =>
|
||||||
|
Vector2.Distance(selectedSlider.Position, oldEndPos) < 1);
|
||||||
|
|
||||||
|
AddAssert("Slider has correct end position", () =>
|
||||||
|
Vector2.Distance(selectedSlider.EndPosition, oldStartPos) < 1);
|
||||||
|
|
||||||
|
AddAssert("Control points have correct types", () =>
|
||||||
|
{
|
||||||
|
var newControlPointTypes = selectedSlider.Path.ControlPoints.Select(p => p.Type).ToArray();
|
||||||
|
|
||||||
|
return oldControlPointTypes.Take(newControlPointTypes.Length).SequenceEqual(newControlPointTypes);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSegmentedSliderReversal()
|
||||||
|
{
|
||||||
|
PathControlPoint[] segmentedSliderPath =
|
||||||
|
[
|
||||||
|
new PathControlPoint
|
||||||
|
{
|
||||||
|
Position = new Vector2(0, 0),
|
||||||
|
Type = PathType.PERFECT_CURVE
|
||||||
|
},
|
||||||
|
new PathControlPoint
|
||||||
|
{
|
||||||
|
Position = new Vector2(100, 150),
|
||||||
|
},
|
||||||
|
new PathControlPoint
|
||||||
|
{
|
||||||
|
Position = new Vector2(75, -50),
|
||||||
|
Type = PathType.PERFECT_CURVE
|
||||||
|
},
|
||||||
|
new PathControlPoint
|
||||||
|
{
|
||||||
|
Position = new Vector2(225, -75),
|
||||||
|
},
|
||||||
|
new PathControlPoint
|
||||||
|
{
|
||||||
|
Position = new Vector2(350, 50),
|
||||||
|
Type = PathType.PERFECT_CURVE
|
||||||
|
},
|
||||||
|
new PathControlPoint
|
||||||
|
{
|
||||||
|
Position = new Vector2(500, -75),
|
||||||
|
},
|
||||||
|
new PathControlPoint
|
||||||
|
{
|
||||||
|
Position = new Vector2(350, -120),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
Vector2 oldStartPos = default;
|
||||||
|
Vector2 oldEndPos = default;
|
||||||
|
double oldDistance = default;
|
||||||
|
|
||||||
|
var oldControlPointTypes = segmentedSliderPath.Select(p => p.Type);
|
||||||
|
|
||||||
|
AddStep("Add slider", () =>
|
||||||
|
{
|
||||||
|
var slider = new Slider
|
||||||
|
{
|
||||||
|
Position = new Vector2(0, 200),
|
||||||
|
Path = new SliderPath(segmentedSliderPath)
|
||||||
|
{
|
||||||
|
ExpectedDistance = { Value = 1314 }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
EditorBeatmap.Add(slider);
|
||||||
|
|
||||||
|
oldStartPos = slider.Position;
|
||||||
|
oldEndPos = slider.EndPosition;
|
||||||
|
oldDistance = slider.Path.Distance;
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("Select slider", () =>
|
||||||
|
{
|
||||||
|
var slider = (Slider)EditorBeatmap.HitObjects[0];
|
||||||
|
EditorBeatmap.SelectedHitObjects.Add(slider);
|
||||||
|
});
|
||||||
|
|
||||||
|
AddRepeatStep("Reverse slider", () =>
|
||||||
|
{
|
||||||
|
InputManager.PressKey(Key.LControl);
|
||||||
|
InputManager.Key(Key.G);
|
||||||
|
InputManager.ReleaseKey(Key.LControl);
|
||||||
|
}, 3);
|
||||||
|
|
||||||
|
AddAssert("First arc's control is not at the slider's middle", () =>
|
||||||
|
Vector2.Distance(selectedSlider.Path.ControlPoints[^2].Position, selectedSlider.Path.PositionAt(0.5)) > 1
|
||||||
|
);
|
||||||
|
|
||||||
|
AddAssert("Last arc's control is not at the slider's middle", () =>
|
||||||
|
Vector2.Distance(selectedSlider.Path.ControlPoints[1].Position, selectedSlider.Path.PositionAt(0.5)) > 1
|
||||||
|
);
|
||||||
|
|
||||||
|
AddAssert("First arc centered middle control point", () =>
|
||||||
|
{
|
||||||
|
var pathControlPoints = selectedSlider.Path.ControlPoints;
|
||||||
|
float middleToStart = Vector2.Distance(pathControlPoints[1].Position, pathControlPoints[0].Position);
|
||||||
|
float middleToEnd = Vector2.Distance(pathControlPoints[1].Position, pathControlPoints[2].Position);
|
||||||
|
|
||||||
|
return Precision.AlmostEquals(middleToStart, middleToEnd, 1f);
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("Last arc centered middle control point", () =>
|
||||||
|
{
|
||||||
|
var pathControlPoints = selectedSlider.Path.ControlPoints;
|
||||||
|
float middleToStart = Vector2.Distance(pathControlPoints[^2].Position, pathControlPoints[^3].Position);
|
||||||
|
float middleToEnd = Vector2.Distance(pathControlPoints[^2].Position, pathControlPoints[^1].Position);
|
||||||
|
|
||||||
|
return Precision.AlmostEquals(middleToStart, middleToEnd, 1f);
|
||||||
|
});
|
||||||
|
|
||||||
AddAssert("Slider has correct length", () =>
|
AddAssert("Slider has correct length", () =>
|
||||||
Precision.AlmostEquals(selectedSlider.Path.Distance, oldDistance));
|
Precision.AlmostEquals(selectedSlider.Path.Distance, oldDistance));
|
||||||
|
|
||||||
|
|||||||
88
osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModEasy.cs
Normal file
88
osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModEasy.cs
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
|
using osu.Game.Rulesets.Osu.Mods;
|
||||||
|
using osu.Game.Tests.Beatmaps;
|
||||||
|
using osu.Game.Tests.Visual;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||||
|
{
|
||||||
|
public partial class TestSceneOsuModEasy : OsuModTestScene
|
||||||
|
{
|
||||||
|
protected override bool AllowFail => true;
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestMultipleApplication()
|
||||||
|
{
|
||||||
|
bool reapplied = false;
|
||||||
|
CreateModTest(new ModTestData
|
||||||
|
{
|
||||||
|
Mods = [new OsuModEasy { Retries = { Value = 1 } }],
|
||||||
|
Autoplay = false,
|
||||||
|
CreateBeatmap = () =>
|
||||||
|
{
|
||||||
|
// do stuff to speed up fails
|
||||||
|
var b = new TestBeatmap(new OsuRuleset().RulesetInfo)
|
||||||
|
{
|
||||||
|
Difficulty = { DrainRate = 10 }
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var ho in b.HitObjects)
|
||||||
|
ho.StartTime /= 4;
|
||||||
|
|
||||||
|
return b;
|
||||||
|
},
|
||||||
|
PassCondition = () =>
|
||||||
|
{
|
||||||
|
if (((ModEasyTestPlayer)Player).FailuresSuppressed > 0 && !reapplied)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
foreach (var mod in Player.GameplayState.Mods.OfType<IApplicableToDifficulty>())
|
||||||
|
mod.ApplyToDifficulty(new BeatmapDifficulty());
|
||||||
|
|
||||||
|
foreach (var mod in Player.GameplayState.Mods.OfType<IApplicableToPlayer>())
|
||||||
|
mod.ApplyToPlayer(Player);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// don't care if this fails. in fact a failure here is probably better than the alternative.
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
reapplied = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Player.GameplayState.HasFailed && ((ModEasyTestPlayer)Player).FailuresSuppressed <= 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override TestPlayer CreateModPlayer(Ruleset ruleset) => new ModEasyTestPlayer(CurrentTestData, AllowFail);
|
||||||
|
|
||||||
|
private partial class ModEasyTestPlayer : ModTestPlayer
|
||||||
|
{
|
||||||
|
public int FailuresSuppressed { get; private set; }
|
||||||
|
|
||||||
|
public ModEasyTestPlayer(ModTestData data, bool allowFail)
|
||||||
|
: base(data, allowFail)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool CheckModsAllowFailure()
|
||||||
|
{
|
||||||
|
bool failureAllowed = GameplayState.Mods.OfType<IApplicableFailOverride>().All(m => m.PerformFail());
|
||||||
|
|
||||||
|
if (!failureAllowed)
|
||||||
|
FailuresSuppressed++;
|
||||||
|
|
||||||
|
return failureAllowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,10 @@
|
|||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using osu.Game.Rulesets.Osu.Beatmaps;
|
||||||
using osu.Game.Rulesets.Osu.Mods;
|
using osu.Game.Rulesets.Osu.Mods;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
|
using osu.Game.Rulesets.Osu.UI;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Tests.Mods
|
namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||||
{
|
{
|
||||||
@@ -18,5 +21,39 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods
|
|||||||
Autoplay = false,
|
Autoplay = false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSkipToFirstCircleNotSuppressed()
|
||||||
|
{
|
||||||
|
CreateModTest(new ModTestData
|
||||||
|
{
|
||||||
|
Mod = new OsuModFreezeFrame(),
|
||||||
|
CreateBeatmap = () => new OsuBeatmap
|
||||||
|
{
|
||||||
|
HitObjects =
|
||||||
|
{
|
||||||
|
new HitCircle { StartTime = 5000, Position = OsuPlayfield.BASE_SIZE / 2 }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
PassCondition = () => Player.GameplayClockContainer.GameplayStartTime > 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSkipToFirstSpinnerNotSuppressed()
|
||||||
|
{
|
||||||
|
CreateModTest(new ModTestData
|
||||||
|
{
|
||||||
|
Mod = new OsuModFreezeFrame(),
|
||||||
|
CreateBeatmap = () => new OsuBeatmap
|
||||||
|
{
|
||||||
|
HitObjects =
|
||||||
|
{
|
||||||
|
new Spinner { StartTime = 5000, Position = OsuPlayfield.BASE_SIZE / 2 }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
PassCondition = () => Player.GameplayClockContainer.GameplayStartTime > 0
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,9 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
[TestCase("multi-segment-slider")]
|
[TestCase("multi-segment-slider")]
|
||||||
[TestCase("nan-slider")]
|
[TestCase("nan-slider")]
|
||||||
[TestCase("1124896")]
|
[TestCase("1124896")]
|
||||||
|
[TestCase("1341554")]
|
||||||
|
[TestCase("2593923")]
|
||||||
|
[TestCase("801165")]
|
||||||
public void Test(string name) => base.Test(name);
|
public void Test(string name) => base.Test(name);
|
||||||
|
|
||||||
protected override IEnumerable<ConvertValue> CreateConvertValue(HitObject hitObject)
|
protected override IEnumerable<ConvertValue> CreateConvertValue(HitObject hitObject)
|
||||||
|
|||||||
@@ -15,22 +15,22 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
{
|
{
|
||||||
protected override string ResourceAssembly => "osu.Game.Rulesets.Osu.Tests";
|
protected override string ResourceAssembly => "osu.Game.Rulesets.Osu.Tests";
|
||||||
|
|
||||||
[TestCase(6.7331304290522747d, 239, "diffcalc-test")]
|
[TestCase(6.6232533278125061d, 239, "diffcalc-test")]
|
||||||
[TestCase(1.4602604078137214d, 54, "zero-length-sliders")]
|
[TestCase(1.5045783545699611d, 54, "zero-length-sliders")]
|
||||||
[TestCase(0.43052813047866129d, 4, "very-fast-slider")]
|
[TestCase(0.43333836671191595d, 4, "very-fast-slider")]
|
||||||
[TestCase(0.14143808967817237d, 2, "nan-slider")]
|
[TestCase(0.13841532030395723d, 2, "nan-slider")]
|
||||||
public void Test(double expectedStarRating, int expectedMaxCombo, string name)
|
public void Test(double expectedStarRating, int expectedMaxCombo, string name)
|
||||||
=> base.Test(expectedStarRating, expectedMaxCombo, name);
|
=> base.Test(expectedStarRating, expectedMaxCombo, name);
|
||||||
|
|
||||||
[TestCase(9.6779746353001634d, 239, "diffcalc-test")]
|
[TestCase(9.6491691624112761d, 239, "diffcalc-test")]
|
||||||
[TestCase(1.7691451263718989d, 54, "zero-length-sliders")]
|
[TestCase(1.756936832498702d, 54, "zero-length-sliders")]
|
||||||
[TestCase(0.55785578988249407d, 4, "very-fast-slider")]
|
[TestCase(0.57771197086735004d, 4, "very-fast-slider")]
|
||||||
public void TestClockRateAdjusted(double expectedStarRating, int expectedMaxCombo, string name)
|
public void TestClockRateAdjusted(double expectedStarRating, int expectedMaxCombo, string name)
|
||||||
=> Test(expectedStarRating, expectedMaxCombo, name, new OsuModDoubleTime());
|
=> Test(expectedStarRating, expectedMaxCombo, name, new OsuModDoubleTime());
|
||||||
|
|
||||||
[TestCase(6.7331304290522747d, 239, "diffcalc-test")]
|
[TestCase(6.6232533278125061d, 239, "diffcalc-test")]
|
||||||
[TestCase(1.4602604078137214d, 54, "zero-length-sliders")]
|
[TestCase(1.5045783545699611d, 54, "zero-length-sliders")]
|
||||||
[TestCase(0.43052813047866129d, 4, "very-fast-slider")]
|
[TestCase(0.43333836671191595d, 4, "very-fast-slider")]
|
||||||
public void TestClassicMod(double expectedStarRating, int expectedMaxCombo, string name)
|
public void TestClassicMod(double expectedStarRating, int expectedMaxCombo, string name)
|
||||||
=> Test(expectedStarRating, expectedMaxCombo, name, new OsuModClassic());
|
=> Test(expectedStarRating, expectedMaxCombo, name, new OsuModClassic());
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,941 @@
|
|||||||
|
osu file format v14
|
||||||
|
|
||||||
|
[General]
|
||||||
|
AudioLeadIn: 0
|
||||||
|
PreviewTime: 76429
|
||||||
|
Countdown: 0
|
||||||
|
SampleSet: Soft
|
||||||
|
StackLeniency: 0.2
|
||||||
|
Mode: 0
|
||||||
|
LetterboxInBreaks: 0
|
||||||
|
WidescreenStoryboard: 1
|
||||||
|
|
||||||
|
[Difficulty]
|
||||||
|
HPDrainRate:5
|
||||||
|
CircleSize:4.3
|
||||||
|
OverallDifficulty:8
|
||||||
|
ApproachRate:9.3
|
||||||
|
SliderMultiplier:2.99999995231628
|
||||||
|
SliderTickRate:1
|
||||||
|
|
||||||
|
[Events]
|
||||||
|
//Background and Video events
|
||||||
|
//Break Periods
|
||||||
|
//Storyboard Layer 0 (Background)
|
||||||
|
//Storyboard Layer 1 (Fail)
|
||||||
|
//Storyboard Layer 2 (Pass)
|
||||||
|
//Storyboard Layer 3 (Foreground)
|
||||||
|
//Storyboard Sound Samples
|
||||||
|
|
||||||
|
[TimingPoints]
|
||||||
|
763,444.444444444444,4,2,1,60,1,0
|
||||||
|
763,-111.111111111111,4,2,1,60,0,0
|
||||||
|
1929,-100,4,2,1,5,0,0
|
||||||
|
1985,-100,4,2,1,60,0,0
|
||||||
|
2040,-100,4,2,1,5,0,0
|
||||||
|
2096,-153.846153846153,4,2,1,60,0,0
|
||||||
|
2429,-133.333333333333,4,2,1,5,0,0
|
||||||
|
2540,-71.4285714285714,4,2,1,70,0,1
|
||||||
|
2985,-100,4,2,1,70,0,1
|
||||||
|
4485,-100,4,2,1,5,0,1
|
||||||
|
4540,-100,4,2,1,70,0,1
|
||||||
|
4707,-100,4,2,1,5,0,1
|
||||||
|
4762,-100,4,2,1,70,0,1
|
||||||
|
4929,-100,4,2,1,5,0,1
|
||||||
|
4985,-100,4,2,1,70,0,1
|
||||||
|
5096,-83.3333333333333,4,2,1,70,0,1
|
||||||
|
5429,-133.333333333333,4,2,1,70,0,1
|
||||||
|
5596,-133.333333333333,4,2,1,70,0,1
|
||||||
|
5652,-133.333333333333,4,2,1,70,0,1
|
||||||
|
5818,-133.333333333333,4,2,1,70,0,1
|
||||||
|
5874,-133.333333333333,4,2,1,70,0,1
|
||||||
|
6040,-133.333333333333,4,2,1,70,0,1
|
||||||
|
6096,-100,4,2,1,70,0,1
|
||||||
|
6540,-100,4,2,1,70,0,1
|
||||||
|
8040,-100,4,2,1,5,0,1
|
||||||
|
8096,-100,4,2,1,70,0,1
|
||||||
|
8262,-100,4,2,1,5,0,1
|
||||||
|
8318,-100,4,2,1,70,0,1
|
||||||
|
8485,-100,4,2,1,5,0,1
|
||||||
|
8540,-133.333333333333,4,2,1,70,0,1
|
||||||
|
8874,-100,4,2,1,5,0,1
|
||||||
|
8985,-100,4,2,1,70,0,1
|
||||||
|
9651,-100,4,2,1,70,0,1
|
||||||
|
10096,-100,4,2,1,70,0,1
|
||||||
|
11596,-100,4,2,1,5,0,1
|
||||||
|
11651,-100,4,2,1,70,0,1
|
||||||
|
11818,-100,4,2,1,5,0,1
|
||||||
|
11873,-100,4,2,1,70,0,1
|
||||||
|
11874,-80,4,2,1,70,0,1
|
||||||
|
12040,-80,4,2,1,5,0,1
|
||||||
|
12096,-80,4,2,1,70,0,1
|
||||||
|
12207,-133.333333333333,4,2,1,70,0,1
|
||||||
|
12429,-100,4,2,1,5,0,1
|
||||||
|
12540,-100,4,2,1,70,0,1
|
||||||
|
12707,-100,4,2,1,70,0,1
|
||||||
|
12763,-100,4,2,1,70,0,1
|
||||||
|
12929,-100,4,2,1,70,0,1
|
||||||
|
12985,-100,4,2,1,70,0,1
|
||||||
|
13429,-300,4,2,1,70,0,1
|
||||||
|
13651,-83.3333333333333,4,2,1,70,0,1
|
||||||
|
13874,-100,4,2,1,70,0,1
|
||||||
|
15151,-100,4,2,1,5,0,1
|
||||||
|
15207,-100,4,2,1,70,0,1
|
||||||
|
15373,-100,4,2,1,5,0,1
|
||||||
|
15429,-100,4,2,1,70,0,1
|
||||||
|
15596,-100,4,2,1,5,0,1
|
||||||
|
15651,-100,4,2,1,70,0,1
|
||||||
|
15985,-100,4,2,1,5,0,1
|
||||||
|
16096,-100,4,2,1,70,0,1
|
||||||
|
16262,-100,4,2,1,70,0,1
|
||||||
|
16318,-83.3333333333333,4,2,1,70,0,1
|
||||||
|
16651,-100,4,2,1,70,0,1
|
||||||
|
16762,-133.333333333333,4,2,1,60,0,0
|
||||||
|
17096,-133.333333333333,4,2,1,5,0,0
|
||||||
|
17207,-200,4,2,1,60,0,0
|
||||||
|
18096,-66.6666666666667,4,2,1,60,0,0
|
||||||
|
18262,-66.6666666666667,4,2,1,5,0,0
|
||||||
|
18318,-66.6666666666667,4,2,1,60,0,0
|
||||||
|
18540,-100,4,2,1,60,0,0
|
||||||
|
18874,-100,4,2,1,5,0,0
|
||||||
|
18985,-100,4,2,1,60,0,0
|
||||||
|
19985,-100,4,2,1,60,0,0
|
||||||
|
20485,-100,4,2,1,5,0,0
|
||||||
|
20540,-100,4,2,1,60,0,0
|
||||||
|
20707,-100,4,2,1,5,0,0
|
||||||
|
20762,-200,4,2,1,60,0,0
|
||||||
|
20985,-100,4,2,1,60,0,0
|
||||||
|
21095,-100,4,2,1,60,0,0
|
||||||
|
21374,-100,4,2,1,5,0,0
|
||||||
|
21429,-100,4,2,1,60,0,0
|
||||||
|
21596,-100,4,2,1,5,0,0
|
||||||
|
21651,-100,4,2,1,60,0,0
|
||||||
|
21818,-100,4,2,1,5,0,0
|
||||||
|
21874,-66.6666666666667,4,2,1,60,0,0
|
||||||
|
21985,-100,4,2,1,60,0,0
|
||||||
|
22096,-100,4,2,1,60,0,0
|
||||||
|
22985,-200,4,2,1,60,0,0
|
||||||
|
23318,-100,4,2,1,60,0,0
|
||||||
|
23429,-100,4,2,1,60,0,0
|
||||||
|
23540,-100,4,2,1,60,0,0
|
||||||
|
23651,-100,4,2,1,60,0,0
|
||||||
|
23762,-100,4,2,1,60,0,0
|
||||||
|
23874,-133.333333333333,4,2,1,60,0,0
|
||||||
|
24208,-133.333333333333,4,2,1,5,0,0
|
||||||
|
24318,-200,4,2,1,5,0,0
|
||||||
|
24319,-200,4,2,1,60,0,0
|
||||||
|
24540,-100,4,2,1,60,0,0
|
||||||
|
24651,-66.6666666666667,4,2,1,60,0,0
|
||||||
|
24874,-100,4,2,1,60,0,0
|
||||||
|
25374,-100,4,2,1,5,0,0
|
||||||
|
25429,-100,4,2,1,60,0,0
|
||||||
|
27096,-100,4,2,1,60,0,0
|
||||||
|
27596,-100,4,2,1,5,0,0
|
||||||
|
27651,-100,4,2,1,60,0,0
|
||||||
|
27818,-100,4,2,1,5,0,0
|
||||||
|
27873,-133.333333333333,4,2,1,60,0,0
|
||||||
|
28096,-100,4,2,1,60,0,0
|
||||||
|
28206,-100,4,2,1,60,0,0
|
||||||
|
28485,-100,4,2,1,5,0,0
|
||||||
|
28540,-100,4,2,1,60,0,0
|
||||||
|
28707,-100,4,2,1,5,0,0
|
||||||
|
28762,-100,4,2,1,60,0,0
|
||||||
|
28929,-100,4,2,1,5,0,0
|
||||||
|
28985,-66.6666666666667,4,2,1,60,0,0
|
||||||
|
29151,-100,4,2,1,60,0,0
|
||||||
|
29207,-100,4,2,1,60,0,0
|
||||||
|
29651,-100,4,2,1,60,0,0
|
||||||
|
30429,-100,4,2,1,60,0,0
|
||||||
|
30540,-58.8235294117647,4,2,1,60,0,0
|
||||||
|
30874,-58.8235294117647,4,2,1,5,0,0
|
||||||
|
30985,-58.8235294117647,4,2,1,60,0,0
|
||||||
|
31040,-100,4,2,1,5,0,0
|
||||||
|
31429,-100,4,2,1,60,0,0
|
||||||
|
32485,-100,4,2,1,60,0,0
|
||||||
|
32540,-100,4,2,1,60,0,0
|
||||||
|
32707,-100,4,2,1,60,0,0
|
||||||
|
32762,-100,4,2,1,60,0,0
|
||||||
|
32985,-100,4,2,1,60,0,0
|
||||||
|
34318,-50,4,2,1,60,0,0
|
||||||
|
34485,-100,4,2,1,5,0,0
|
||||||
|
34540,-100,4,2,1,60,0,0
|
||||||
|
35151,-100,4,2,1,5,0,0
|
||||||
|
35207,-100,4,2,1,60,0,0
|
||||||
|
35374,-100,4,2,1,5,0,0
|
||||||
|
35430,-100,4,2,1,60,0,0
|
||||||
|
35818,-100,4,2,1,5,0,0
|
||||||
|
35874,-200,4,2,1,60,0,0
|
||||||
|
36429,-100,4,2,1,60,0,0
|
||||||
|
37818,-100,4,2,1,5,0,0
|
||||||
|
37874,-100,4,2,1,60,0,0
|
||||||
|
38040,-100,4,2,1,5,0,0
|
||||||
|
38096,-50,4,2,1,60,0,0
|
||||||
|
38151,-100,4,2,1,5,0,0
|
||||||
|
38540,-100,4,2,1,60,0,0
|
||||||
|
39596,-100,4,2,1,5,0,0
|
||||||
|
39651,-100,4,2,1,60,0,0
|
||||||
|
39818,-100,4,2,1,60,0,0
|
||||||
|
39873,-100,4,2,1,60,0,0
|
||||||
|
40096,-100,4,2,1,60,0,0
|
||||||
|
41429,-50,4,2,1,60,0,0
|
||||||
|
41596,-100,4,2,1,5,0,0
|
||||||
|
41651,-100,4,2,1,60,0,0
|
||||||
|
41818,-100,4,2,1,5,0,0
|
||||||
|
41874,-100,4,2,1,60,0,0
|
||||||
|
42040,-100,4,2,1,5,0,0
|
||||||
|
42096,-100,4,2,1,60,0,0
|
||||||
|
44318,-100,4,2,1,60,0,0
|
||||||
|
44762,-83.3333333333333,4,2,1,60,0,0
|
||||||
|
45207,-66.6666666666667,4,2,1,45,0,0
|
||||||
|
45651,-133.333333333333,4,2,1,45,0,0
|
||||||
|
51540,-133.333333333333,4,2,1,50,0,0
|
||||||
|
51651,-133.333333333333,4,2,1,45,0,0
|
||||||
|
52318,-133.333333333333,4,2,1,45,0,0
|
||||||
|
58540,-76.9230769230769,4,2,1,45,0,0
|
||||||
|
58818,-100,4,2,1,45,0,0
|
||||||
|
58874,-111.111111111111,4,2,1,45,0,0
|
||||||
|
59318,-111.111111111111,4,2,1,45,0,0
|
||||||
|
59429,-83.3333333333333,4,2,1,60,0,0
|
||||||
|
59540,-83.3333333333333,4,2,1,5,0,0
|
||||||
|
59874,-100,4,2,1,60,0,0
|
||||||
|
60096,-100,4,2,1,5,0,0
|
||||||
|
60207,-100,4,2,1,60,0,0
|
||||||
|
60707,-100,4,2,1,5,0,0
|
||||||
|
60763,-100,4,2,1,60,0,0
|
||||||
|
60818,-100,4,2,1,5,0,0
|
||||||
|
60874,-100,4,2,1,60,0,0
|
||||||
|
60929,-100,4,2,1,5,0,0
|
||||||
|
60985,-100,4,2,1,60,0,0
|
||||||
|
61040,-100,4,2,1,5,0,0
|
||||||
|
61096,-100,4,2,1,60,0,0
|
||||||
|
61151,-100,4,2,1,5,0,0
|
||||||
|
61207,-100,4,2,1,60,0,0
|
||||||
|
61596,-100,4,2,1,5,0,0
|
||||||
|
61651,-100,4,2,1,60,0,0
|
||||||
|
61762,-83.3333333333333,4,2,1,60,0,0
|
||||||
|
61985,-100,4,2,1,5,0,0
|
||||||
|
62096,-100,4,2,1,60,0,0
|
||||||
|
62151,-100,4,2,1,5,0,0
|
||||||
|
62207,-100,4,2,1,60,0,0
|
||||||
|
62262,-100,4,2,1,5,0,0
|
||||||
|
62318,-100,4,2,1,60,0,0
|
||||||
|
62374,-100,4,2,1,5,0,0
|
||||||
|
62430,-100,4,2,1,60,0,0
|
||||||
|
62485,-100,4,2,1,5,0,0
|
||||||
|
62540,-100,4,2,1,60,0,0
|
||||||
|
62596,-100,4,2,1,5,0,0
|
||||||
|
62651,-100,4,2,1,60,0,0
|
||||||
|
62707,-100,4,2,1,5,0,0
|
||||||
|
62762,-100,4,2,1,60,0,0
|
||||||
|
62818,-100,4,2,1,5,0,0
|
||||||
|
62874,-100,4,2,1,60,0,0
|
||||||
|
62929,-100,4,2,1,60,0,0
|
||||||
|
62930,-100,4,2,1,5,0,0
|
||||||
|
62985,-100,4,2,1,60,0,0
|
||||||
|
63707,-100,4,2,1,5,0,0
|
||||||
|
63762,-100,4,2,1,60,0,0
|
||||||
|
64262,-100,4,2,1,5,0,0
|
||||||
|
64318,-100,4,2,1,60,0,0
|
||||||
|
64485,-100,4,2,1,5,0,0
|
||||||
|
64540,-100,4,2,1,60,0,0
|
||||||
|
64596,-100,4,2,1,5,0,0
|
||||||
|
64651,-100,4,2,1,60,0,0
|
||||||
|
64707,-100,4,2,1,5,0,0
|
||||||
|
64762,-71.4285714285714,4,2,1,60,0,0
|
||||||
|
64929,-71.4285714285714,4,2,1,5,0,0
|
||||||
|
64984,-133.333333333333,4,2,1,60,0,0
|
||||||
|
65151,-133.333333333333,4,2,1,5,0,0
|
||||||
|
65206,-71.4285714285714,4,2,1,60,0,0
|
||||||
|
65374,-71.4285714285714,4,2,1,5,0,0
|
||||||
|
65429,-133.333333333333,4,2,1,60,0,0
|
||||||
|
65596,-133.333333333333,4,2,1,5,0,0
|
||||||
|
65651,-100,4,2,1,60,0,0
|
||||||
|
66540,-66.6666666666667,4,2,1,60,0,0
|
||||||
|
66596,-66.6666666666667,4,2,1,5,0,0
|
||||||
|
66929,-100,4,2,1,5,0,0
|
||||||
|
66985,-200,4,2,1,60,0,0
|
||||||
|
67207,-200,4,2,1,5,0,0
|
||||||
|
67318,-100,4,2,1,60,0,0
|
||||||
|
67818,-100,4,2,1,5,0,0
|
||||||
|
67874,-100,4,2,1,60,0,0
|
||||||
|
67929,-100,4,2,1,5,0,0
|
||||||
|
67985,-100,4,2,1,60,0,0
|
||||||
|
68040,-100,4,2,1,5,0,0
|
||||||
|
68096,-100,4,2,1,60,0,0
|
||||||
|
68151,-100,4,2,1,5,0,0
|
||||||
|
68207,-100,4,2,1,60,0,0
|
||||||
|
68262,-100,4,2,1,5,0,0
|
||||||
|
68318,-100,4,2,1,60,0,0
|
||||||
|
68874,-83.3333333333333,4,2,1,60,0,0
|
||||||
|
69096,-100,4,2,1,60,0,0
|
||||||
|
69097,-100,4,2,1,5,0,0
|
||||||
|
69207,-100,4,2,1,60,0,0
|
||||||
|
69263,-100,4,2,1,5,0,0
|
||||||
|
69319,-100,4,2,1,60,0,0
|
||||||
|
69374,-100,4,2,1,5,0,0
|
||||||
|
69430,-100,4,2,1,60,0,0
|
||||||
|
69486,-100,4,2,1,5,0,0
|
||||||
|
69542,-100,4,2,1,60,0,0
|
||||||
|
69597,-100,4,2,1,5,0,0
|
||||||
|
69651,-100,4,2,1,60,0,0
|
||||||
|
69707,-100,4,2,1,5,0,0
|
||||||
|
69762,-100,4,2,1,60,0,0
|
||||||
|
69818,-100,4,2,1,5,0,0
|
||||||
|
69874,-100,4,2,1,60,0,0
|
||||||
|
69929,-100,4,2,1,5,0,0
|
||||||
|
69985,-100,4,2,1,60,0,0
|
||||||
|
70040,-100,4,2,1,60,0,0
|
||||||
|
70041,-100,4,2,1,5,0,0
|
||||||
|
70096,-100,4,2,1,60,0,0
|
||||||
|
70818,-100,4,2,1,5,0,0
|
||||||
|
70873,-100,4,2,1,60,0,0
|
||||||
|
71207,-71.4285714285714,4,2,1,60,0,0
|
||||||
|
71429,-100,4,2,1,60,0,0
|
||||||
|
71874,-71.4285714285714,4,2,1,60,0,0
|
||||||
|
72041,-71.4285714285714,4,2,1,5,0,0
|
||||||
|
72096,-133.333333333333,4,2,1,60,0,0
|
||||||
|
72263,-133.333333333333,4,2,1,5,0,0
|
||||||
|
72318,-71.4285714285714,4,2,1,60,0,0
|
||||||
|
72485,-71.4285714285714,4,2,1,5,0,0
|
||||||
|
72540,-133.333333333333,4,2,1,60,0,0
|
||||||
|
72985,-66.6666666666667,4,2,1,60,0,0
|
||||||
|
73207,-100,4,2,1,60,0,0
|
||||||
|
73651,-133.333333333333,4,2,1,45,0,0
|
||||||
|
75318,-133.333333333333,4,2,1,5,0,0
|
||||||
|
75429,-133.333333333333,4,2,1,45,0,0
|
||||||
|
76762,-100,4,2,1,45,0,0
|
||||||
|
77096,-100,4,2,1,5,0,0
|
||||||
|
77207,-100,4,2,1,70,0,1
|
||||||
|
77818,-100,4,2,1,5,0,1
|
||||||
|
77874,-100,4,2,1,70,0,1
|
||||||
|
78262,-100,4,2,1,5,0,1
|
||||||
|
78318,-100,4,2,1,70,0,1
|
||||||
|
78540,-83.3333333333333,4,2,1,70,0,1
|
||||||
|
78985,-100,4,2,1,70,0,1
|
||||||
|
79596,-100,4,2,1,5,0,1
|
||||||
|
79651,-100,4,2,1,70,0,1
|
||||||
|
80040,-100,4,2,1,5,0,1
|
||||||
|
80096,-100,4,2,1,70,0,1
|
||||||
|
80318,-83.3333333333333,4,2,1,70,0,1
|
||||||
|
84318,-100,4,2,1,70,0,1
|
||||||
|
84929,-100,4,2,1,5,0,1
|
||||||
|
84985,-100,4,2,1,70,0,1
|
||||||
|
85207,-100,4,2,1,70,0,1
|
||||||
|
85374,-100,4,2,1,5,0,1
|
||||||
|
85429,-100,4,2,1,70,0,1
|
||||||
|
85651,-83.3333333333333,4,2,1,70,0,1
|
||||||
|
86096,-100,4,2,1,70,0,1
|
||||||
|
86707,-100,4,2,1,5,0,1
|
||||||
|
86762,-100,4,2,1,70,0,1
|
||||||
|
88818,-100,4,2,1,5,0,1
|
||||||
|
88874,-100,4,2,1,70,0,1
|
||||||
|
88929,-100,4,2,1,5,0,1
|
||||||
|
88985,-100,4,2,1,70,0,1
|
||||||
|
89040,-100,4,2,1,5,0,1
|
||||||
|
89096,-100,4,2,1,70,0,1
|
||||||
|
92040,-100,4,2,1,5,0,1
|
||||||
|
92096,-100,4,2,1,70,0,1
|
||||||
|
92485,-100,4,2,1,5,0,1
|
||||||
|
92540,-100,4,2,1,70,0,1
|
||||||
|
97651,-200,4,2,1,70,0,1
|
||||||
|
97818,-200,4,2,1,5,0,1
|
||||||
|
97874,-66.6666666666667,4,2,1,70,0,1
|
||||||
|
97985,-66.6666666666667,4,2,1,70,0,1
|
||||||
|
98040,-66.6666666666667,4,2,1,5,0,1
|
||||||
|
98096,-133.333333333333,4,2,1,70,0,1
|
||||||
|
98262,-133.333333333333,4,2,1,5,0,1
|
||||||
|
98318,-66.6666666666667,4,2,1,70,0,1
|
||||||
|
98540,-100,4,2,1,70,0,1
|
||||||
|
99151,-100,4,2,1,5,0,1
|
||||||
|
99207,-100,4,2,1,70,0,1
|
||||||
|
99596,-100,4,2,1,5,0,1
|
||||||
|
99651,-100,4,2,1,70,0,1
|
||||||
|
103040,-100,4,2,1,5,0,1
|
||||||
|
103096,-100,4,2,1,70,0,1
|
||||||
|
103151,-100,4,2,1,5,0,1
|
||||||
|
103207,-100,4,2,1,70,0,1
|
||||||
|
103262,-100,4,2,1,5,0,1
|
||||||
|
103318,-100,4,2,1,70,0,1
|
||||||
|
105207,-83.3333333333333,4,2,1,70,0,1
|
||||||
|
105540,-83.3333333333333,4,2,1,70,0,1
|
||||||
|
105651,-133.333333333333,4,2,1,60,0,0
|
||||||
|
105985,-133.333333333333,4,2,1,5,0,0
|
||||||
|
106096,-200,4,2,1,60,0,0
|
||||||
|
106985,-66.6666666666667,4,2,1,60,0,0
|
||||||
|
107151,-66.6666666666667,4,2,1,5,0,0
|
||||||
|
107207,-66.6666666666667,4,2,1,60,0,0
|
||||||
|
107429,-100,4,2,1,60,0,0
|
||||||
|
107763,-100,4,2,1,5,0,0
|
||||||
|
107874,-100,4,2,1,60,0,0
|
||||||
|
108874,-100,4,2,1,60,0,0
|
||||||
|
109374,-100,4,2,1,5,0,0
|
||||||
|
109429,-100,4,2,1,60,0,0
|
||||||
|
109596,-100,4,2,1,5,0,0
|
||||||
|
109651,-200,4,2,1,60,0,0
|
||||||
|
109929,-100,4,2,1,60,0,0
|
||||||
|
109984,-100,4,2,1,60,0,0
|
||||||
|
110262,-100,4,2,1,5,0,0
|
||||||
|
110318,-100,4,2,1,60,0,0
|
||||||
|
110485,-100,4,2,1,5,0,0
|
||||||
|
110540,-100,4,2,1,60,0,0
|
||||||
|
110707,-100,4,2,1,5,0,0
|
||||||
|
110762,-66.6666666666667,4,2,1,60,0,0
|
||||||
|
110929,-100,4,2,1,60,0,0
|
||||||
|
110985,-133.333333333333,4,2,1,60,0,0
|
||||||
|
111429,-133.333333333333,4,2,1,60,0,0
|
||||||
|
111596,-133.333333333333,4,2,1,60,0,0
|
||||||
|
111651,-133.333333333333,4,2,1,60,0,0
|
||||||
|
111818,-133.333333333333,4,2,1,60,0,0
|
||||||
|
111874,-100,4,2,1,60,0,1
|
||||||
|
112318,-83.3333333333333,4,2,1,60,0,1
|
||||||
|
112429,-100,4,2,1,5,0,0
|
||||||
|
|
||||||
|
|
||||||
|
[Colours]
|
||||||
|
Combo1 : 112,75,180
|
||||||
|
Combo2 : 0,255,255
|
||||||
|
Combo3 : 255,15,117
|
||||||
|
Combo4 : 255,135,15
|
||||||
|
|
||||||
|
[HitObjects]
|
||||||
|
309,230,763,37,0,3:0:0:0:
|
||||||
|
485,146,985,2,0,L|406:167,1,67.4999968671799,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
374,249,1207,2,0,L|299:227,1,67.4999968671799,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
196,91,1429,2,0,L|191:44,3,33.7499984335899,0|0|0|0,3:0|3:0|3:0|3:0,0:0:0:0:
|
||||||
|
124,173,1651,2,0,L|131:222,2,44.9999979114532,0|0|0,3:0|3:0|3:0,0:0:0:0:
|
||||||
|
221,284,1874,2,0,L|213:208,1,67.4999968671799,0|0,3:0|3:0,0:0:0:0:
|
||||||
|
292,86,2096,38,0,L|310:234,1,146.249990980625,12|0,3:0|0:0,0:0:0:0:
|
||||||
|
314,328,2540,38,0,B|280:359|280:359|230:320|252:242|313:230,1,209.999990253448,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
421,300,2874,1,0,0:0:0:0:
|
||||||
|
421,300,2985,2,0,P|461:288|491:253,1,74.999998807907,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
309,231,3207,2,0,P|297:190|305:153,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
394,22,3429,5,0,3:0:0:0:
|
||||||
|
461,72,3540,2,0,B|477:103|477:103|461:148,1,74.999998807907,0|4,0:0|0:0,0:0:0:0:
|
||||||
|
378,183,3762,2,0,L|206:157,1,149.999997615814,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
229,161,4096,2,0,P|227:202|211:250,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
61,384,4318,38,0,P|101:359|134:322,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
317,310,4540,2,0,P|267:305|226:288,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
141,110,4762,2,0,B|121:175|152:226|152:226|152:202|161:183,1,149.999997615814,8|4,3:0|0:0,0:0:0:0:
|
||||||
|
155,196,5096,6,0,P|67:211|79:286,1,179.999991645813,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
212,366,5429,38,0,P|207:335|174:281,1,56.2500012516975,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
206,286,5651,2,0,P|236:297|299:295,1,56.2500012516975,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
281,321,5874,2,0,P|257:340|227:396,1,56.2500012516975,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
124,246,6096,6,0,P|198:198|277:232,1,149.999997615814,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
253,211,6429,1,0,0:0:0:0:
|
||||||
|
276,99,6540,2,0,P|335:139|369:215,1,149.999997615814,8|4,3:0|0:0,0:0:0:0:
|
||||||
|
368,208,6874,1,0,0:0:0:0:
|
||||||
|
430,96,6985,37,0,3:0:0:0:
|
||||||
|
497,147,7096,2,0,P|507:189|488:244,1,74.999998807907,0|4,0:0|0:0,0:0:0:0:
|
||||||
|
414,379,7318,2,0,B|383:322|421:267|421:267|421:308,1,149.999997615814,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
421,298,7651,2,0,P|378:312|336:304,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
270,170,7874,6,0,P|275:228|236:278,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
94,300,8096,2,0,P|133:263|208:274,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
261,374,8318,2,0,L|176:365,1,74.999998807907,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
38,377,8540,2,0,L|55:197,1,168.750003755093,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
123,25,8985,38,0,L|132:110,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
217,242,9207,2,0,L|237:168,1,74.999998807907,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
48,92,9429,5,4,0:0:0:0:
|
||||||
|
63,176,9540,1,0,0:0:0:0:
|
||||||
|
83,259,9651,38,0,P|167:223|231:255,1,149.999997615814,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
274,312,9985,1,0,0:0:0:0:
|
||||||
|
274,312,10096,2,0,L|354:292,1,74.999998807907,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
459,225,10318,2,0,L|375:204,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
269,107,10540,1,0,3:0:0:0:
|
||||||
|
276,54,10651,1,0,0:0:0:0:
|
||||||
|
313,17,10762,1,4,0:0:0:0:
|
||||||
|
363,9,10874,1,0,0:0:0:0:
|
||||||
|
363,9,11096,5,0,0:0:0:0:
|
||||||
|
432,68,11207,2,0,P|444:107|425:154,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
309,252,11429,38,0,P|297:195|321:158,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
450,316,11651,2,0,L|361:312,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
160,341,11874,2,0,B|187:380|187:380|233:309|177:235,1,187.499997019767,8|4,3:0|0:0,0:0:0:0:
|
||||||
|
116,200,12207,6,0,P|52:224|122:264,1,168.750003755093,0|4,0:0|0:0,0:0:0:0:
|
||||||
|
297,91,12762,37,8,3:0:0:0:
|
||||||
|
276,44,12874,1,0,0:0:0:0:
|
||||||
|
226,27,12985,1,4,0:0:0:0:
|
||||||
|
187,63,13096,1,0,0:0:0:0:
|
||||||
|
196,115,13207,1,0,0:0:0:0:
|
||||||
|
376,144,13429,2,0,L|378:121,2,16.6666664017571,0|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||||
|
436,220,13651,6,0,B|395:211|373:164|373:164|332:208|264:185,1,179.999991645813,8|4,3:0|0:0,0:0:0:0:
|
||||||
|
276,44,13985,1,0,0:0:0:0:
|
||||||
|
196,115,14096,38,0,L|139:124,4,37.4999994039535,0|0|0|0|4,3:0|0:0|0:0|0:0|0:0,0:0:0:0:
|
||||||
|
82,69,14429,1,0,0:0:0:0:
|
||||||
|
106,190,14540,2,0,L|126:276,1,74.999998807907,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
218,383,14762,2,0,L|234:309,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
26,231,14985,5,0,3:0:0:0:
|
||||||
|
253,202,15207,37,0,0:0:0:0:
|
||||||
|
331,271,15318,1,0,0:0:0:0:
|
||||||
|
233,309,15429,1,8,3:0:0:0:
|
||||||
|
389,73,15651,6,0,P|410:22|447:112,1,224.999996423721,4|0,3:0|0:0,0:0:0:0:
|
||||||
|
391,165,16096,1,0,0:0:0:0:
|
||||||
|
377,177,16207,1,0,0:0:0:0:
|
||||||
|
365,187,16318,38,0,B|253:261|221:119|94:192,1,269.999987468719,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
73,319,16762,22,0,P|133:336|116:236,1,168.750003755093,4|0,3:0|0:0,0:0:0:0:
|
||||||
|
139,258,17207,6,0,P|138:315|69:283,1,112.500002503395,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
92,323,17762,37,0,0:0:0:0:
|
||||||
|
43,245,17874,1,4,0:0:0:0:
|
||||||
|
4,322,17985,1,0,0:0:0:0:
|
||||||
|
133,245,18096,1,0,3:0:0:0:
|
||||||
|
29,105,18318,6,0,L|38:40,3,56.2500012516975,4|0|0|0,3:0|0:0|0:0|0:0,0:0:0:0:
|
||||||
|
50,30,18540,38,0,P|111:56|193:25,1,149.999997615814,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
240,120,18985,2,0,P|328:91|394:125,1,149.999997615814,8|4,3:0|0:0,0:0:0:0:
|
||||||
|
409,213,19318,2,0,B|377:226|377:226|243:200,1,149.999997615814,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
119,187,19651,2,0,L|127:286,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
179,338,19874,1,8,3:0:0:0:
|
||||||
|
45,307,19985,6,0,L|3:297,2,37.4999994039535,0|0|4,0:0|0:0|0:0,0:0:0:0:
|
||||||
|
103,380,20207,1,0,3:0:0:0:
|
||||||
|
212,257,20318,38,0,P|233:218|231:171,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
111,118,20540,1,4,0:0:0:0:
|
||||||
|
111,118,20762,6,0,L|197:109,1,74.999998807907,8|4,3:0|0:0,0:0:0:0:
|
||||||
|
256,18,21096,37,0,0:0:0:0:
|
||||||
|
337,121,21207,2,0,P|350:60|403:16,1,112.49999821186,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
384,26,21429,2,0,P|406:86|465:122,1,112.49999821186,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
443,114,21651,2,0,P|377:105|327:131,1,112.49999821186,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
352,223,21874,6,0,B|369:230|369:230|391:228|391:228|416:239|416:239|440:235|440:235|462:244|462:244|489:249,1,112.500002503395,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
322,343,22096,37,0,3:0:0:0:
|
||||||
|
259,270,22207,2,0,P|223:276|182:263,2,74.999998807907,0|4|0,0:0|0:0|0:0,0:0:0:0:
|
||||||
|
86,360,22540,5,8,3:0:0:0:
|
||||||
|
15,295,22651,2,0,L|0:201,2,74.999998807907,0|4|0,0:0|0:0|0:0,0:0:0:0:
|
||||||
|
94,384,22985,38,0,P|118:328|112:277,1,112.49999821186,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
0,211,23429,22,0,L|76:196,1,74.999998807907,12|0,3:0|0:0,0:0:0:0:
|
||||||
|
215,134,23651,2,0,L|114:110,1,74.999998807907,12|0,3:0|0:0,0:0:0:0:
|
||||||
|
33,124,23874,22,0,L|43:2,1,112.49999821186,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
150,269,24318,2,0,L|162:194,1,74.999998807907,0|4,3:0|0:0,0:0:0:0:
|
||||||
|
229,134,24651,6,0,L|386:164,1,112.500002503395,12|0,3:0|0:0,0:0:0:0:
|
||||||
|
486,268,24874,37,0,0:0:0:0:
|
||||||
|
410,119,24985,1,4,0:0:0:0:
|
||||||
|
381,213,25096,1,0,0:0:0:0:
|
||||||
|
512,120,25207,1,0,3:0:0:0:
|
||||||
|
247,36,25429,6,0,L|191:25,3,37.4999994039535,4|0|0|0,3:0|0:0|0:0|0:0,0:0:0:0:
|
||||||
|
185,24,25651,2,0,B|145:72|145:72|174:164,1,149.999997615814,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
253,219,26096,2,0,B|281:311|281:311|228:382,1,149.999997615814,8|4,3:0|0:0,0:0:0:0:
|
||||||
|
100,363,26429,38,0,L|259:354,1,149.999997615814,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
404,262,26762,1,4,0:0:0:0:
|
||||||
|
390,352,26874,1,0,0:0:0:0:
|
||||||
|
314,295,26985,1,8,3:0:0:0:
|
||||||
|
425,256,27096,6,0,L|492:246,2,37.4999994039535,0|0|4,0:0|0:0|0:0,0:0:0:0:
|
||||||
|
329,216,27318,1,0,3:0:0:0:
|
||||||
|
193,177,27429,38,0,L|266:161,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
322,107,27651,1,4,0:0:0:0:
|
||||||
|
322,107,27874,2,0,L|310:238,1,112.500002503395,8|4,3:0|0:0,0:0:0:0:
|
||||||
|
110,299,28207,5,0,0:0:0:0:
|
||||||
|
164,231,28318,2,0,B|168:303|168:303|121:338,1,112.49999821186,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
30,284,28540,2,0,B|90:244|90:244|144:267,1,112.49999821186,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
148,371,28762,2,0,B|83:338|83:338|76:280,1,112.49999821186,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
194,201,28985,38,0,B|207:210|207:210|227:210|227:210|243:217|243:217|265:218|265:218|282:227|282:227|305:225|305:225|325:238,1,112.500002503395,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
492,114,29207,6,0,P|445:136|410:138,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
324,102,29429,2,0,P|291:68|280:29,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
418,17,29651,1,8,3:0:0:0:
|
||||||
|
495,201,29874,1,4,3:2:0:0:
|
||||||
|
221,136,30096,37,0,3:0:0:0:
|
||||||
|
299,188,30207,2,0,B|316:251|316:251|271:352,1,149.999997615814,4|0,3:0|0:0,0:0:0:0:
|
||||||
|
115,334,30540,6,0,P|11:252|167:266,1,382.500001215934,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
216,326,30985,38,0,L|304:331,1,63.7500002026557,4|0,3:0|0:0,0:0:0:0:
|
||||||
|
280,330,31429,6,0,L|293:241,1,74.999998807907,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
426,252,31651,2,0,L|439:163,1,74.999998807907,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
253,158,31874,37,0,3:0:0:0:
|
||||||
|
258,132,31985,1,0,0:0:0:0:
|
||||||
|
337,111,32096,5,4,0:0:0:0:
|
||||||
|
341,85,32207,1,0,0:0:0:0:
|
||||||
|
271,30,32318,38,0,B|212:42|212:42|141:19,1,112.49999821186,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
163,26,32540,2,0,L|144:181,1,149.999997615814,4|0,0:0|3:0,0:0:0:0:
|
||||||
|
445,343,32985,22,0,B|439:234|439:234|384:269,1,149.999997615814,4|8,0:0|3:0,0:0:0:0:
|
||||||
|
240,257,33429,2,0,B|263:148|263:148|291:205,1,149.999997615814,4|0,0:0|3:0,0:0:0:0:
|
||||||
|
68,333,33874,2,0,B|83:233|83:233|41:256,1,149.999997615814,4|8,0:0|3:0,0:0:0:0:
|
||||||
|
344,347,34318,22,0,B|368:372|368:372|455:355|455:355|472:308,1,149.999997615814,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
452,255,34540,2,0,B|389:212|389:212|332:273,1,149.999997615814,0|4,3:0|0:0,0:0:0:0:
|
||||||
|
256,220,34874,5,0,0:0:0:0:
|
||||||
|
256,220,34985,2,0,B|256:128,1,74.999998807907,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
256,70,35207,2,0,B|256:162,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
112,312,35429,37,0,3:0:0:0:
|
||||||
|
60,255,35540,2,0,B|123:212|123:212|180:273,1,149.999997615814,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
169,350,35874,6,0,B|144:375|144:375|57:358|57:358|40:311,1,149.999997615814,8|0,3:0|3:0,0:0:0:0:
|
||||||
|
62,169,36429,6,0,L|76:267,2,74.999998807907,0|4|0,0:0|0:0|0:0,0:0:0:0:
|
||||||
|
134,61,36762,1,8,3:0:0:0:
|
||||||
|
201,113,36874,2,0,L|215:211,2,74.999998807907,0|4|0,0:0|0:0|0:0,0:0:0:0:
|
||||||
|
298,272,37207,6,0,L|315:184,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
330,114,37429,1,4,0:0:0:0:
|
||||||
|
446,176,37540,2,0,B|404:214|404:214|307:197,1,149.999997615814,4|0,3:0|0:0,0:0:0:0:
|
||||||
|
231,240,37874,2,0,P|223:199|231:162,1,74.999998807907,4|0,3:0|0:0,0:0:0:0:
|
||||||
|
325,285,38096,6,0,L|154:300,1,149.999997615814,4|0,3:0|0:0,0:0:0:0:
|
||||||
|
175,298,38540,6,0,L|163:396,1,74.999998807907,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
75,208,38762,2,0,L|63:306,1,74.999998807907,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
233,74,38985,37,0,3:0:0:0:
|
||||||
|
231,98,39096,1,0,0:0:0:0:
|
||||||
|
156,139,39207,5,4,0:0:0:0:
|
||||||
|
155,165,39318,1,0,0:0:0:0:
|
||||||
|
227,215,39429,38,0,P|282:209|352:230,1,112.49999821186,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
336,222,39651,2,0,L|366:67,1,149.999997615814,4|0,0:0|3:0,0:0:0:0:
|
||||||
|
81,35,40096,22,0,B|82:105|82:105|118:136|118:136|132:89,1,149.999997615814,4|8,0:0|3:0,0:0:0:0:
|
||||||
|
272,158,40540,2,0,B|270:228|270:228|234:259|234:259|220:212,1,149.999997615814,4|0,0:0|3:0,0:0:0:0:
|
||||||
|
423,36,40985,2,0,B|400:102|400:102|423:143|423:143|453:104,1,149.999997615814,4|8,0:0|3:0,0:0:0:0:
|
||||||
|
512,278,41429,6,0,P|415:258|361:293,1,149.999997615814,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
359,302,41651,6,0,B|320:264|320:264|310:187,1,112.49999821186,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
322,190,41874,2,0,L|449:171,1,112.49999821186,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
443,159,42096,1,8,3:0:0:0:
|
||||||
|
240,52,42318,6,0,B|255:79|255:79|241:135,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
177,166,42540,1,0,3:0:0:0:
|
||||||
|
163,151,42651,2,0,B|161:207|161:207|192:240|192:240|189:299,1,149.999997615814,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
131,365,42985,2,0,P|198:322|280:345,1,149.999997615814,8|4,3:0|0:0,0:0:0:0:
|
||||||
|
335,377,43318,1,0,0:0:0:0:
|
||||||
|
442,239,43429,38,0,B|456:178|456:178|422:136|422:136|427:68|427:68|449:112,1,224.999996423721,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
444,103,43874,2,0,P|402:118|356:120,1,74.999998807907,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
249,28,44096,2,0,P|295:35|324:48,1,74.999998807907,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
364,201,44318,5,0,0:0:0:0:
|
||||||
|
332,195,44429,1,0,0:0:0:0:
|
||||||
|
251,135,44540,37,0,0:0:0:0:
|
||||||
|
281,123,44651,1,0,0:0:0:0:
|
||||||
|
332,195,44762,6,0,B|356:269|324:333|324:333|303:293,1,179.999991645813,4|0,0:3|0:0,0:0:0:0:
|
||||||
|
61,25,45207,38,0,L|88:158,1,112.500002503395,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
84,136,45651,1,8,3:0:0:0:
|
||||||
|
84,136,46096,1,0,3:0:0:0:
|
||||||
|
176,33,46207,2,0,L|164:103,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
219,207,46429,2,0,L|232:152,1,56.2500012516975,0|8,0:0|3:0,0:0:0:0:
|
||||||
|
312,65,46651,1,0,0:0:0:0:
|
||||||
|
312,65,46762,2,0,L|398:94,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
512,176,46985,5,0,3:0:0:0:
|
||||||
|
421,192,47096,1,0,0:0:0:0:
|
||||||
|
421,192,47429,1,8,3:0:0:0:
|
||||||
|
402,357,47651,37,0,0:0:0:0:
|
||||||
|
394,277,47762,1,0,0:0:0:0:
|
||||||
|
328,324,47874,1,0,3:0:0:0:
|
||||||
|
328,324,48318,1,8,3:0:0:0:
|
||||||
|
110,357,48540,5,0,0:0:0:0:
|
||||||
|
118,277,48651,1,0,0:0:0:0:
|
||||||
|
184,324,48763,1,0,3:0:0:0:
|
||||||
|
110,357,48874,1,0,0:0:0:0:
|
||||||
|
110,357,49207,1,8,3:0:0:0:
|
||||||
|
110,357,49651,1,0,3:0:0:0:
|
||||||
|
0,283,49762,38,0,P|41:301|97:295,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
188,219,49985,2,0,P|168:236|137:246,1,56.2500012516975,0|8,0:0|3:0,0:0:0:0:
|
||||||
|
49,137,50207,1,0,0:0:0:0:
|
||||||
|
49,137,50318,2,0,P|65:184|93:205,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
107,67,50540,5,0,3:0:0:0:
|
||||||
|
32,15,50651,1,0,0:0:0:0:
|
||||||
|
32,15,50985,1,8,3:0:0:0:
|
||||||
|
265,114,51207,37,0,0:0:0:0:
|
||||||
|
254,196,51318,1,0,0:0:0:0:
|
||||||
|
241,279,51429,1,0,3:0:0:0:
|
||||||
|
241,279,51651,1,0,0:0:0:0:
|
||||||
|
336,207,51762,6,0,P|397:191|371:274,1,168.750003755093,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
83,206,52318,5,0,3:0:0:0:
|
||||||
|
83,206,52429,2,0,L|101:260,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
40,383,52651,2,0,P|70:355|90:324,1,56.2500012516975,0|8,0:0|3:0,0:0:0:0:
|
||||||
|
214,334,52874,1,0,0:0:0:0:
|
||||||
|
214,334,52985,2,0,P|171:322|140:304,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
151,160,53207,5,0,3:0:0:0:
|
||||||
|
188,135,53318,1,0,0:0:0:0:
|
||||||
|
232,129,53429,1,0,0:0:0:0:
|
||||||
|
273,146,53540,1,0,0:0:0:0:
|
||||||
|
339,198,53651,37,8,3:0:0:0:
|
||||||
|
383,199,53762,1,0,0:0:0:0:
|
||||||
|
426,185,53874,1,0,0:0:0:0:
|
||||||
|
450,147,53985,1,0,0:0:0:0:
|
||||||
|
444,61,54096,6,0,P|414:28|377:15,1,56.2500012516975,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
301,28,54318,2,0,P|268:48|255:77,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
189,271,54540,38,0,P|209:222|204:198,1,56.2500012516975,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
186,114,54762,2,0,P|152:74|124:68,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
27,137,54985,5,0,3:0:0:0:
|
||||||
|
34,167,55096,1,0,0:0:0:0:
|
||||||
|
122,204,55207,37,0,0:0:0:0:
|
||||||
|
116,178,55318,1,0,0:0:0:0:
|
||||||
|
48,249,55429,5,8,3:0:0:0:
|
||||||
|
54,274,55540,1,0,0:0:0:0:
|
||||||
|
124,329,55651,38,0,P|157:326|200:310,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
320,185,55874,5,0,3:0:0:0:
|
||||||
|
287,175,55985,1,0,0:0:0:0:
|
||||||
|
254,181,56096,2,0,P|258:221|264:241,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
337,347,56318,2,0,P|348:321|350:293,1,56.2500012516975,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
418,197,56540,37,0,0:0:0:0:
|
||||||
|
418,197,56651,2,0,L|492:180,1,56.2500012516975,0|0,0:0|3:0,0:0:0:0:
|
||||||
|
329,114,56874,2,0,L|262:94,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
436,59,57096,6,0,L|413:126,1,56.2500012516975,0|8,0:0|3:0,0:0:0:0:
|
||||||
|
332,194,57318,2,0,L|353:259,2,56.2500012516975,0|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||||
|
202,194,57651,37,0,3:0:0:0:
|
||||||
|
224,233,57762,1,0,0:0:0:0:
|
||||||
|
222,279,57874,1,0,0:0:0:0:
|
||||||
|
193,314,57985,1,0,0:0:0:0:
|
||||||
|
144,244,58096,5,0,0:0:0:0:
|
||||||
|
127,214,58207,1,0,0:0:0:0:
|
||||||
|
126,180,58318,1,0,0:0:0:0:
|
||||||
|
139,149,58429,1,0,0:0:0:0:
|
||||||
|
224,113,58540,38,0,B|262:88|235:70|189:83|189:83|224:138|194:193,1,194.999987974167
|
||||||
|
299,319,58874,1,0,0:0:0:0:
|
||||||
|
299,319,58985,2,0,B|316:283|314:237|314:237|278:226|278:226|320:243|359:227,1,202.49999060154,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
428,181,59429,22,0,P|454:129|399:4,1,179.999991645813,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
418,18,59874,2,0,L|373:15,6,24.9999996026357,8|0|0|0|0|0|4,3:0|0:0|0:0|0:0|0:0|0:0|0:0,0:0:0:0:
|
||||||
|
428,181,60207,5,0,0:0:0:0:
|
||||||
|
352,209,60318,1,0,3:0:0:0:
|
||||||
|
278,177,60429,1,0,0:0:0:0:
|
||||||
|
208,225,60540,2,0,L|222:267,2,37.4999994039535,4|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||||
|
71,144,60762,38,0,L|65:109,3,24.9999996026357,8|0|0|0,3:0|0:0|0:0|0:0,0:0:0:0:
|
||||||
|
145,86,60985,1,4,0:0:0:0:
|
||||||
|
163,127,61096,1,0,0:0:0:0:
|
||||||
|
161,171,61207,1,0,3:0:0:0:
|
||||||
|
136,208,61318,1,0,0:0:0:0:
|
||||||
|
99,231,61429,2,0,B|91:279|91:279|117:314,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
177,378,61651,5,8,3:0:0:0:
|
||||||
|
177,378,61762,2,0,B|231:371|231:371|272:326|272:326|345:319,1,179.999991645813
|
||||||
|
417,293,62096,1,0,3:0:0:0:
|
||||||
|
438,263,62207,1,0,0:0:0:0:
|
||||||
|
436,225,62318,1,4,0:0:0:0:
|
||||||
|
412,196,62429,1,0,0:0:0:0:
|
||||||
|
320,172,62540,6,0,P|307:192|291:204,1,37.4999994039535,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
291,147,62651,2,0,P|274:156|245:153,1,37.4999994039535,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
276,114,62762,2,0,P|250:107|234:94,1,37.4999994039535,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
283,81,62874,2,0,P|265:61|260:45,1,37.4999994039535,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
365,31,62985,38,0,P|398:44|442:49,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
512,169,63207,2,0,P|466:163|421:176,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
350,107,63429,1,8,3:0:0:0:
|
||||||
|
293,237,63540,38,0,L|276:158,1,74.999998807907,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
428,269,63762,2,0,B|373:275|373:275|338:249|338:249|267:255,1,149.999997615814,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
191,318,64096,2,0,B|182:355|182:355|212:395,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
192,186,64318,5,8,3:0:0:0:
|
||||||
|
135,253,64429,2,0,L|56:270,2,74.999998807907,0|4|0,0:0|0:0|0:0,0:0:0:0:
|
||||||
|
24,136,64762,38,0,P|69:76|158:75,1,157.499992690086,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
160,80,64985,6,0,P|193:102|255:102,1,84.3750018775463,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
276,34,65207,38,0,L|290:212,1,157.499992690086,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
291,219,65429,6,0,L|311:132,1,84.3750018775463,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
381,111,65651,38,0,B|418:126|418:126|460:126,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
221,163,65874,2,0,B|186:143|186:143|139:153,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
41,231,66096,1,8,3:0:0:0:
|
||||||
|
49,267,66207,1,0,0:0:0:0:
|
||||||
|
56,303,66318,1,4,0:0:0:0:
|
||||||
|
67,288,66429,1,4,0:0:0:0:
|
||||||
|
77,270,66540,6,0,P|171:255|72:350,1,337.500007510185,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
95,356,66985,38,0,L|185:343,1,74.999998807907,8|4,3:0|0:0,0:0:0:0:
|
||||||
|
274,286,67318,6,0,B|289:324|289:324|268:378,1,74.999998807907,0|0,0:0|3:0,0:0:0:0:
|
||||||
|
191,227,67540,1,0,0:0:0:0:
|
||||||
|
255,168,67651,2,0,L|264:116,2,37.4999994039535,4|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||||
|
147,83,67874,2,0,L|154:108,3,24.9999996026357,8|0|0|0,3:0|0:0|0:0|0:0,0:0:0:0:
|
||||||
|
80,148,68096,38,0,L|98:224,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
125,356,68318,1,0,3:0:0:0:
|
||||||
|
0,319,68429,1,0,0:0:0:0:
|
||||||
|
0,319,68540,2,0,L|76:294,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
277,219,68762,5,8,3:0:0:0:
|
||||||
|
277,219,68874,2,0,B|327:199|327:199|293:138|197:173,1,179.999991645813,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
157,273,69207,37,0,3:0:0:0:
|
||||||
|
175,316,69318,1,0,0:0:0:0:
|
||||||
|
212,334,69429,1,4,0:0:0:0:
|
||||||
|
254,333,69540,1,0,0:0:0:0:
|
||||||
|
332,268,69651,38,0,P|333:237|343:213,1,37.4999994039535,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
373,265,69762,2,0,P|386:239|404:232,1,37.4999994039535,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
413,284,69874,2,0,P|430:269|454:269,1,37.4999994039535,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
433,318,69985,2,0,P|452:320|474:337,1,37.4999994039535,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
401,384,70096,6,0,P|353:378|319:346,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
251,251,70318,2,0,P|240:196|260:154,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
401,18,70540,1,8,3:0:0:0:
|
||||||
|
401,18,70651,2,0,P|409:54|398:90,1,74.999998807907,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
327,193,70874,2,0,L|304:45,1,149.999997615814,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
290,26,71207,6,0,L|308:144,1,104.999995126724,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
272,302,71429,2,0,L|187:288,1,74.999998807907,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
33,217,71651,37,4,0:0:0:0:
|
||||||
|
27,187,71762,1,4,0:0:0:0:
|
||||||
|
20,157,71874,2,0,B|103:140|103:140|162:58,1,157.499992690086,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
145,82,72096,6,0,L|218:75,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
336,136,72318,38,0,P|331:213|231:208,1,157.499992690086
|
||||||
|
263,232,72540,6,0,L|278:300,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
183,384,72762,2,0,L|172:307,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
37,140,72985,38,0,B|10:168|10:168|17:204|17:204|54:220|54:220|89:196|89:196|87:157|87:157|57:138,1,225.00000500679
|
||||||
|
275,372,73651,6,0,P|320:352|387:369,1,112.500002503395
|
||||||
|
380,364,74096,2,0,L|436:358,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
495,271,74318,2,0,L|424:282,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
339,270,74540,1,0,0:0:0:0:
|
||||||
|
339,270,74651,1,0,0:0:0:0:
|
||||||
|
339,270,74762,2,0,L|329:196,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
408,46,74985,38,0,L|392:120,1,56.2500012516975
|
||||||
|
220,230,75207,2,0,L|209:156,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
282,7,75429,37,0,0:0:0:0:
|
||||||
|
300,98,75540,1,0,0:0:0:0:
|
||||||
|
197,25,75651,5,0,0:0:0:0:
|
||||||
|
222,103,75762,1,0,0:0:0:0:
|
||||||
|
126,69,75874,5,0,0:0:0:0:
|
||||||
|
153,134,75985,1,0,0:0:0:0:
|
||||||
|
76,145,76096,5,0,0:0:0:0:
|
||||||
|
116,179,76207,1,0,0:0:0:0:
|
||||||
|
70,222,76318,5,0,0:0:0:0:
|
||||||
|
111,222,76429,1,0,0:0:0:0:
|
||||||
|
134,253,76540,6,0,P|135:298|126:314,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
21,384,76762,2,0,P|124:354|260:391,1,224.999996423721,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
384,366,77207,22,0,L|394:268,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
499,62,77429,2,0,L|486:135,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
507,237,77651,2,0,P|450:231|388:184,1,112.49999821186,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
404,203,77874,2,0,L|313:217,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
113,212,78096,6,0,P|128:267|111:328,1,112.49999821186,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
115,319,78318,2,0,L|213:340,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
274,371,78540,38,0,L|257:186,1,179.999991645813,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
128,139,78874,1,0,0:0:0:0:
|
||||||
|
128,139,78985,6,0,L|230:128,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
365,34,79207,37,4,0:0:0:0:
|
||||||
|
430,114,79318,1,0,0:0:0:0:
|
||||||
|
361,184,79429,2,0,P|304:170|277:110,1,112.49999821186,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
278,126,79651,2,0,L|189:133,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
64,263,79874,6,0,B|37:230|37:230|50:143,1,112.49999821186,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
66,119,80096,2,0,L|80:210,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
71,361,80318,38,0,B|135:350|135:350|182:305|182:305|243:297,1,179.999991645813,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
302,247,80651,1,0,0:0:0:0:
|
||||||
|
222,211,80762,1,0,3:0:0:0:
|
||||||
|
478,344,80985,5,4,0:0:0:0:
|
||||||
|
491,309,81096,5,0,0:0:0:0:
|
||||||
|
498,265,81207,5,8,3:0:0:0:
|
||||||
|
485,223,81318,5,0,0:0:0:0:
|
||||||
|
458,179,81429,5,4,0:0:0:0:
|
||||||
|
418,147,81540,5,0,0:0:0:0:
|
||||||
|
352,126,81651,5,0,3:0:0:0:
|
||||||
|
281,149,81762,5,0,0:0:0:0:
|
||||||
|
239,221,81874,5,4,0:0:0:0:
|
||||||
|
159,262,81985,5,0,0:0:0:0:
|
||||||
|
66,234,82096,5,8,3:0:0:0:
|
||||||
|
11,145,82207,5,0,0:0:0:0:
|
||||||
|
55,33,82318,5,4,0:0:0:0:
|
||||||
|
273,44,82540,37,0,3:0:0:0:
|
||||||
|
320,103,82651,1,0,0:0:0:0:
|
||||||
|
394,118,82762,1,4,0:0:0:0:
|
||||||
|
468,100,82874,1,0,0:0:0:0:
|
||||||
|
507,36,82985,1,8,3:0:0:0:
|
||||||
|
495,19,83207,5,4,0:0:0:0:
|
||||||
|
335,83,83318,1,0,0:0:0:0:
|
||||||
|
453,81,83429,1,0,3:0:0:0:
|
||||||
|
283,24,83540,2,0,P|196:37|141:120,1,149.999997615814,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
60,238,83874,1,8,3:0:0:0:
|
||||||
|
21,164,83985,2,0,P|59:149|175:193,1,149.999997615814,0|8,0:0|3:0,0:0:0:0:
|
||||||
|
252,206,84318,38,0,P|271:160|264:125,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
139,257,84540,2,0,P|131:302|149:340,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
240,379,84762,2,0,B|330:360|330:360|298:344,1,112.49999821186,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
312,351,84985,2,0,P|279:321|270:287,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
359,165,85207,6,0,B|389:202|389:202|368:282,1,112.49999821186,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
373,265,85429,2,0,L|454:282,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
498,139,85651,38,0,P|446:120|396:0,1,179.999991645813,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
394,13,85985,1,0,0:0:0:0:
|
||||||
|
301,92,86096,6,0,L|214:83,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
66,66,86318,1,4,0:0:0:0:
|
||||||
|
13,136,86429,1,0,0:0:0:0:
|
||||||
|
72,193,86540,2,0,P|120:210|190:178,1,112.49999821186,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
176,192,86762,2,0,P|154:237|160:288,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
309,370,86985,37,0,3:0:0:0:
|
||||||
|
359,310,87096,1,0,0:0:0:0:
|
||||||
|
283,297,87207,2,0,L|203:318,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
4,203,87429,2,0,B|55:211|55:211|82:255|82:255|134:266,1,149.999997615814,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
238,217,87762,1,0,0:0:0:0:
|
||||||
|
183,120,87874,6,0,L|89:111,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
98,33,88096,2,0,L|23:26,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
306,182,88318,38,0,L|400:173,1,74.999998807907,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
391,95,88540,2,0,L|465:88,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
232,28,88762,2,0,L|220:92,1,37.4999994039535,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
243,39,88874,2,0,L|231:103,1,37.4999994039535,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
256,50,88985,2,0,L|251:87,1,37.4999994039535,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
485,87,89207,6,0,L|493:51,3,37.4999994039535,8|0|0|0,3:0|0:0|0:0|0:0,0:0:0:0:
|
||||||
|
396,120,89429,2,0,L|411:197,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
471,317,89651,38,0,P|411:299|320:336,1,149.999997615814,0|4,3:0|0:0,0:0:0:0:
|
||||||
|
61,239,90096,2,0,P|121:221|212:258,1,149.999997615814,8|4,3:0|0:0,0:0:0:0:
|
||||||
|
367,21,90540,6,0,P|336:57|328:104,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
163,96,90762,2,0,P|194:132|202:179,1,74.999998807907,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
190,346,90985,37,8,3:0:0:0:
|
||||||
|
328,272,91096,1,0,0:0:0:0:
|
||||||
|
154,272,91207,5,8,3:0:0:0:
|
||||||
|
365,338,91318,1,0,0:0:0:0:
|
||||||
|
257,382,91429,38,0,B|290:333|224:286|269:219,1,149.999997615814,4|4,3:0|0:0,0:0:0:0:
|
||||||
|
325,196,91762,1,0,0:0:0:0:
|
||||||
|
325,196,91874,2,0,P|365:210|436:184,1,112.49999821186,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
430,190,92096,2,0,B|418:110,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
313,19,92318,2,0,L|190:36,1,112.49999821186,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
201,34,92540,2,0,B|214:117,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
209,252,92762,5,8,3:0:0:0:
|
||||||
|
156,261,92874,1,0,0:0:0:0:
|
||||||
|
112,231,92985,1,4,0:0:0:0:
|
||||||
|
60,222,93096,1,0,0:0:0:0:
|
||||||
|
13,247,93207,38,0,P|4:288|19:328,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
173,186,93429,1,4,0:0:0:0:
|
||||||
|
215,120,93540,1,0,0:0:0:0:
|
||||||
|
162,49,93651,2,0,P|125:39|76:61,1,74.999998807907,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
234,138,93874,2,0,P|273:157|313:148,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
385,39,94096,5,0,3:0:0:0:
|
||||||
|
337,286,94318,2,0,L|322:373,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
409,327,94540,2,0,P|418:277|280:230,1,224.999996423721,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
239,319,94985,2,0,P|218:357|173:373,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
34,344,95207,37,4,0:0:0:0:
|
||||||
|
21,309,95318,5,0,0:0:0:0:
|
||||||
|
14,265,95429,5,8,3:0:0:0:
|
||||||
|
27,223,95540,5,0,0:0:0:0:
|
||||||
|
54,179,95651,5,4,0:0:0:0:
|
||||||
|
94,147,95762,5,0,0:0:0:0:
|
||||||
|
160,126,95873,5,0,3:0:0:0:
|
||||||
|
231,149,95984,5,0,0:0:0:0:
|
||||||
|
273,221,96096,5,4,0:0:0:0:
|
||||||
|
353,262,96207,5,0,0:0:0:0:
|
||||||
|
446,234,96318,5,8,3:0:0:0:
|
||||||
|
501,145,96429,5,0,0:0:0:0:
|
||||||
|
450,36,96540,5,4,0:0:0:0:
|
||||||
|
239,44,96762,5,0,3:0:0:0:
|
||||||
|
192,103,96873,1,0,0:0:0:0:
|
||||||
|
118,118,96984,1,4,0:0:0:0:
|
||||||
|
44,100,97096,1,0,0:0:0:0:
|
||||||
|
5,36,97207,1,8,3:0:0:0:
|
||||||
|
17,19,97429,37,4,0:0:0:0:
|
||||||
|
146,51,97540,1,0,0:0:0:0:
|
||||||
|
29,122,97651,2,0,L|39:193,1,56.2499991059302,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
44,197,97874,6,0,P|100:231|176:201,1,112.500002503395,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
301,160,98096,38,0,P|329:140|382:137,1,84.3750018775463,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
398,147,98318,6,0,B|431:187|431:187|415:279,1,112.500002503395,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
265,371,98540,38,0,L|180:361,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
127,202,98762,2,0,L|141:113,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
193,260,98985,2,0,P|144:291|68:278,1,112.49999821186,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
91,290,99207,2,0,L|79:373,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
20,184,99429,6,0,B|4:141|4:141|27:66,1,112.49999821186,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
23,78,99651,2,0,L|109:91,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
271,74,99874,2,0,P|254:31|222:12,1,74.999998807907,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
186,180,100096,2,0,P|232:175|260:147,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
132,63,100318,37,0,3:0:0:0:
|
||||||
|
253,157,100540,1,4,0:0:0:0:
|
||||||
|
285,167,100651,1,0,0:0:0:0:
|
||||||
|
357,129,100762,5,8,3:0:0:0:
|
||||||
|
389,139,100873,1,0,0:0:0:0:
|
||||||
|
422,148,100985,2,0,P|407:200|416:233,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
459,377,101207,38,0,P|472:333|459:295,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
398,242,101429,2,0,L|314:257,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
165,354,101651,2,0,P|116:332|211:264,1,224.999996423721,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
302,165,102096,6,0,L|292:89,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
392,91,102318,2,0,L|382:14,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
192,229,102540,38,0,L|212:136,1,74.999998807907,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
107,172,102762,2,0,L|127:79,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
314,332,102985,6,0,L|305:278,1,37.4999994039535,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
343,345,103096,2,0,L|334:291,1,37.4999994039535,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
370,358,103207,2,0,L|361:304,1,37.4999994039535,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
380,117,103429,38,0,L|374:75,3,37.4999994039535,8|0|0|0,3:0|0:0|0:0|0:0,0:0:0:0:
|
||||||
|
444,166,103651,2,0,P|417:188|346:191,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
392,2,103874,2,0,P|424:14|462:74,1,74.999998807907,4|0,3:0|0:0,0:0:0:0:
|
||||||
|
271,129,104096,2,0,P|265:94|298:31,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
505,113,104318,5,8,3:0:0:0:
|
||||||
|
269,217,104540,38,0,L|216:216,3,37.4999994039535,0|0|0|0,3:0|3:0|3:0|3:0,0:0:0:0:
|
||||||
|
360,220,104762,1,0,3:0:0:0:
|
||||||
|
296,384,104874,1,4,3:0:0:0:
|
||||||
|
102,307,105096,5,0,0:0:0:0:
|
||||||
|
102,307,105207,2,0,B|206:381|258:244|374:330,1,269.999987468719,12|0,3:0|0:0,0:0:0:0:
|
||||||
|
439,319,105651,6,0,P|379:336|396:236,1,168.750003755093,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
373,258,106096,6,0,P|374:315|443:283,1,112.500002503395,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
420,323,106651,37,0,0:0:0:0:
|
||||||
|
469,245,106763,1,4,0:0:0:0:
|
||||||
|
508,322,106874,1,0,0:0:0:0:
|
||||||
|
379,245,106985,1,8,3:0:0:0:
|
||||||
|
483,105,107207,6,0,L|474:40,3,56.2500012516975,4|0|0|0,3:0|0:0|0:0|0:0,0:0:0:0:
|
||||||
|
462,30,107429,38,0,P|401:56|319:25,1,149.999997615814,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
272,120,107874,2,0,P|184:91|118:125,1,149.999997615814,8|4,3:0|0:0,0:0:0:0:
|
||||||
|
103,213,108207,2,0,B|128:232|128:232|269:200,1,149.999997615814,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
393,187,108540,2,0,L|385:286,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
333,338,108763,1,8,3:0:0:0:
|
||||||
|
467,307,108874,6,0,L|509:297,2,37.4999994039535,0|0|4,0:0|0:0|0:0,0:0:0:0:
|
||||||
|
409,380,109096,1,0,0:0:0:0:
|
||||||
|
300,257,109207,38,0,P|279:218|281:171,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
401,118,109429,1,4,0:0:0:0:
|
||||||
|
401,118,109651,6,0,L|315:109,1,74.999998807907,8|4,3:0|0:0,0:0:0:0:
|
||||||
|
256,15,109985,37,0,0:0:0:0:
|
||||||
|
175,121,110096,2,0,P|162:60|109:16,1,112.49999821186,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
128,26,110318,2,0,P|106:86|47:122,1,112.49999821186,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
69,114,110540,2,0,P|135:105|185:131,1,112.49999821186,8|0,3:0|0:0,0:0:0:0:
|
||||||
|
160,223,110762,6,0,B|142:230|142:230|120:228|120:228|95:239|95:239|71:235|71:235|49:244|49:244|22:249,1,112.500002503395,4|0,0:0|0:0,0:0:0:0:
|
||||||
|
193,334,110985,38,0,P|216:310|242:301,1,56.2500012516975,0|0,3:0|0:0,0:0:0:0:
|
||||||
|
335,325,111207,2,0,P|366:353|378:379,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
273,383,111429,2,0,L|304:213,1,168.750003755093,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
383,255,111874,22,0,B|422:273|422:273|476:273,1,74.999998807907,8|0,3:0|3:0,0:0:0:0:
|
||||||
|
209,219,112096,2,0,B|169:221|169:221|131:206,1,74.999998807907,0|0,0:0|0:0,0:0:0:0:
|
||||||
|
403,147,112318,2,0,B|352:114|352:114|337:43|337:43|295:109|295:109|234:115,1,269.999987468719,8|0,3:0|0:0,0:0:0:0:
|
||||||
File diff suppressed because one or more lines are too long
1213
osu.Game.Rulesets.Osu.Tests/Resources/Testing/Beatmaps/2593923.osu
Normal file
1213
osu.Game.Rulesets.Osu.Tests/Resources/Testing/Beatmaps/2593923.osu
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
1768
osu.Game.Rulesets.Osu.Tests/Resources/Testing/Beatmaps/801165.osu
Normal file
1768
osu.Game.Rulesets.Osu.Tests/Resources/Testing/Beatmaps/801165.osu
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 9.7 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 644 KiB |
@@ -4,7 +4,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.IO;
|
using osu.Game.IO;
|
||||||
@@ -19,23 +18,9 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
public class StackingTest
|
public class StackingTest
|
||||||
{
|
{
|
||||||
[Test]
|
[Test]
|
||||||
public void TestStacking()
|
public void TestStackingEdgeCaseOne()
|
||||||
{
|
{
|
||||||
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(beatmap_data)))
|
using (var stream = new MemoryStream(@"
|
||||||
using (var reader = new LineBufferedReader(stream))
|
|
||||||
{
|
|
||||||
var beatmap = Decoder.GetDecoder<Beatmap>(reader).Decode(reader);
|
|
||||||
var converted = new TestWorkingBeatmap(beatmap).GetPlayableBeatmap(new OsuRuleset().RulesetInfo, Array.Empty<Mod>());
|
|
||||||
|
|
||||||
var objects = converted.HitObjects.ToList();
|
|
||||||
|
|
||||||
// The last hitobject triggers the stacking
|
|
||||||
for (int i = 0; i < objects.Count - 1; i++)
|
|
||||||
Assert.AreEqual(0, ((OsuHitObject)objects[i]).StackHeight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private const string beatmap_data = @"
|
|
||||||
osu file format v14
|
osu file format v14
|
||||||
|
|
||||||
[General]
|
[General]
|
||||||
@@ -62,6 +47,65 @@ SliderTickRate:0.5
|
|||||||
311,185,218471,2,0,L|325:209,1,25
|
311,185,218471,2,0,L|325:209,1,25
|
||||||
311,185,218671,2,0,L|304:212,1,25
|
311,185,218671,2,0,L|304:212,1,25
|
||||||
311,185,240271,5,0,0:0:0:0:
|
311,185,240271,5,0,0:0:0:0:
|
||||||
";
|
"u8.ToArray()))
|
||||||
|
using (var reader = new LineBufferedReader(stream))
|
||||||
|
{
|
||||||
|
var beatmap = Decoder.GetDecoder<Beatmap>(reader).Decode(reader);
|
||||||
|
var converted = new TestWorkingBeatmap(beatmap).GetPlayableBeatmap(new OsuRuleset().RulesetInfo, Array.Empty<Mod>());
|
||||||
|
|
||||||
|
var objects = converted.HitObjects.ToList();
|
||||||
|
|
||||||
|
// The last hitobject triggers the stacking
|
||||||
|
for (int i = 0; i < objects.Count - 1; i++)
|
||||||
|
Assert.AreEqual(0, ((OsuHitObject)objects[i]).StackHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestStackingEdgeCaseTwo()
|
||||||
|
{
|
||||||
|
using (var stream = new MemoryStream(@"
|
||||||
|
osu file format v14
|
||||||
|
// extracted from https://osu.ppy.sh/beatmapsets/365006#osu/801165
|
||||||
|
|
||||||
|
[General]
|
||||||
|
StackLeniency: 0.2
|
||||||
|
|
||||||
|
[Difficulty]
|
||||||
|
HPDrainRate:6
|
||||||
|
CircleSize:4
|
||||||
|
OverallDifficulty:8
|
||||||
|
ApproachRate:9.3
|
||||||
|
SliderMultiplier:2
|
||||||
|
SliderTickRate:1
|
||||||
|
|
||||||
|
[TimingPoints]
|
||||||
|
5338,444.444444444444,4,2,0,50,1,0
|
||||||
|
82893,-76.9230769230769,4,2,8,50,0,0
|
||||||
|
85115,-76.9230769230769,4,2,0,50,0,0
|
||||||
|
85337,-100,4,2,8,60,0,0
|
||||||
|
85893,-100,4,2,7,60,0,0
|
||||||
|
86226,-100,4,2,8,60,0,0
|
||||||
|
88893,-58.8235294117647,4,1,8,70,0,1
|
||||||
|
|
||||||
|
[HitObjects]
|
||||||
|
427,124,84226,1,0,3:0:0:0:
|
||||||
|
427,124,84337,1,0,3:0:0:0:
|
||||||
|
427,124,84449,1,8,0:0:0:0:
|
||||||
|
"u8.ToArray()))
|
||||||
|
using (var reader = new LineBufferedReader(stream))
|
||||||
|
{
|
||||||
|
var beatmap = Decoder.GetDecoder<Beatmap>(reader).Decode(reader);
|
||||||
|
var converted = new TestWorkingBeatmap(beatmap).GetPlayableBeatmap(new OsuRuleset().RulesetInfo, Array.Empty<Mod>());
|
||||||
|
|
||||||
|
var objects = converted.HitObjects.ToList();
|
||||||
|
|
||||||
|
Assert.That(objects, Has.Count.EqualTo(3));
|
||||||
|
|
||||||
|
// The last hitobject triggers the stacking
|
||||||
|
for (int i = 0; i < objects.Count - 1; i++)
|
||||||
|
Assert.AreEqual(0, ((OsuHitObject)objects[i]).StackHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
63
osu.Game.Rulesets.Osu.Tests/TestSceneAutoGeneration.cs
Normal file
63
osu.Game.Rulesets.Osu.Tests/TestSceneAutoGeneration.cs
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Rulesets.Osu.Beatmaps;
|
||||||
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
|
using osu.Game.Rulesets.Osu.Replays;
|
||||||
|
using osu.Game.Rulesets.Replays;
|
||||||
|
using osu.Game.Tests.Visual;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.Tests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
[HeadlessTest]
|
||||||
|
public partial class TestSceneAutoGeneration : OsuTestScene
|
||||||
|
{
|
||||||
|
[TestCase(-1, true)]
|
||||||
|
[TestCase(0, false)]
|
||||||
|
[TestCase(1, false)]
|
||||||
|
public void TestAlternating(double offset, bool shouldAlternate)
|
||||||
|
{
|
||||||
|
const double first_object_time = 1000;
|
||||||
|
double secondObjectTime = first_object_time + AutoGenerator.KEY_UP_DELAY + OsuAutoGenerator.MIN_FRAME_SEPARATION_FOR_ALTERNATING + offset;
|
||||||
|
|
||||||
|
var beatmap = new OsuBeatmap();
|
||||||
|
beatmap.HitObjects.Add(new HitCircle { StartTime = first_object_time });
|
||||||
|
beatmap.HitObjects.Add(new HitCircle { StartTime = secondObjectTime });
|
||||||
|
|
||||||
|
var generated = new OsuAutoGenerator(beatmap, []).Generate();
|
||||||
|
var frames = generated.Frames.OfType<OsuReplayFrame>().ToList();
|
||||||
|
|
||||||
|
Assert.That(frames.Exists(f => f.Time == first_object_time && f.Actions.SingleOrDefault() == OsuAction.LeftButton));
|
||||||
|
Assert.That(frames.Exists(f => f.Time == first_object_time + AutoGenerator.KEY_UP_DELAY && !f.Actions.Any()));
|
||||||
|
|
||||||
|
Assert.That(frames.Exists(f => f.Time == secondObjectTime && f.Actions.SingleOrDefault() == (shouldAlternate ? OsuAction.RightButton : OsuAction.LeftButton)));
|
||||||
|
Assert.That(frames.Exists(f => f.Time == secondObjectTime + AutoGenerator.KEY_UP_DELAY && !f.Actions.Any()));
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase(300)]
|
||||||
|
[TestCase(600)]
|
||||||
|
[TestCase(1200)]
|
||||||
|
public void TestAlternatingSpecificBPM(double bpm)
|
||||||
|
{
|
||||||
|
const double first_object_time = 1000;
|
||||||
|
double secondObjectTime = first_object_time + 60000 / bpm;
|
||||||
|
|
||||||
|
var beatmap = new OsuBeatmap();
|
||||||
|
beatmap.HitObjects.Add(new HitCircle { StartTime = first_object_time });
|
||||||
|
beatmap.HitObjects.Add(new HitCircle { StartTime = secondObjectTime });
|
||||||
|
|
||||||
|
var generated = new OsuAutoGenerator(beatmap, []).Generate();
|
||||||
|
var frames = generated.Frames.OfType<OsuReplayFrame>().ToList();
|
||||||
|
|
||||||
|
Assert.That(frames.Exists(f => f.Time == first_object_time && f.Actions.SingleOrDefault() == OsuAction.LeftButton));
|
||||||
|
Assert.That(frames.Exists(f => f.Time == first_object_time + AutoGenerator.KEY_UP_DELAY && !f.Actions.Any()));
|
||||||
|
|
||||||
|
Assert.That(frames.Exists(f => f.Time == secondObjectTime && f.Actions.SingleOrDefault() == OsuAction.RightButton));
|
||||||
|
Assert.That(frames.Exists(f => f.Time == secondObjectTime + AutoGenerator.KEY_UP_DELAY && !f.Actions.Any()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Configuration;
|
||||||
|
using osu.Game.Skinning;
|
||||||
|
using osu.Game.Tests.Visual;
|
||||||
|
using osuTK.Input;
|
||||||
|
|
||||||
|
namespace osu.Game.Rulesets.Osu.Tests
|
||||||
|
{
|
||||||
|
public partial class TestSceneGameplayCursorSizeChange : PlayerTestScene
|
||||||
|
{
|
||||||
|
private const float initial_cursor_size = 1f;
|
||||||
|
protected override Ruleset CreatePlayerRuleset() => new OsuRuleset();
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private SkinManager? skins { get; set; }
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
if (skins != null) skins.CurrentSkinInfo.Value = skins.DefaultClassicSkin.SkinInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
[SetUpSteps]
|
||||||
|
public override void SetUpSteps()
|
||||||
|
{
|
||||||
|
base.SetUpSteps();
|
||||||
|
|
||||||
|
AddStep("Set gameplay cursor size: 1", () => LocalConfig.SetValue(OsuSetting.GameplayCursorSize, initial_cursor_size));
|
||||||
|
AddStep("resume player", () => Player.GameplayClockContainer.Start());
|
||||||
|
AddUntilStep("clock running", () => Player.GameplayClockContainer.IsRunning);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestPausedChangeCursorSize()
|
||||||
|
{
|
||||||
|
AddStep("move cursor to center", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.Centre));
|
||||||
|
AddStep("move cursor to top left", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.TopLeft));
|
||||||
|
AddStep("move cursor to center", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.Centre));
|
||||||
|
AddStep("move cursor to top right", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.TopRight));
|
||||||
|
AddStep("press escape", () => InputManager.Key(Key.Escape));
|
||||||
|
|
||||||
|
AddSliderStep("cursor size", 0.1f, 2f, 1f, v => LocalConfig.SetValue(OsuSetting.GameplayCursorSize, v));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override TestPlayer CreatePlayer(Ruleset ruleset) => new TestPlayer(true, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
Debug.Assert(drawableHitObject.HitObject.HitWindows != null);
|
Debug.Assert(drawableHitObject.HitObject.HitWindows != null);
|
||||||
|
|
||||||
double delay = drawableHitObject.HitObject.StartTime - (drawableHitObject.HitObject.HitWindows.WindowFor(HitResult.Miss) + RNG.Next(0, 300)) - Time.Current;
|
double delay = drawableHitObject.HitObject.StartTime - (drawableHitObject.HitObject.HitWindows.WindowFor(HitResult.Miss) + RNG.Next(0, 300)) - Time.Current;
|
||||||
scheduledTasks.Add(Scheduler.AddDelayed(() => drawableHitObject.TriggerJudgement(), delay));
|
scheduledTasks.Add(Scheduler.AddDelayed(drawableHitObject.TriggerJudgement, delay));
|
||||||
|
|
||||||
return drawableHitObject;
|
return drawableHitObject;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Input.Events;
|
using osu.Framework.Input.Events;
|
||||||
@@ -10,6 +11,7 @@ using osu.Framework.Input.States;
|
|||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Framework.Testing.Input;
|
using osu.Framework.Testing.Input;
|
||||||
using osu.Game.Rulesets.Osu.UI;
|
using osu.Game.Rulesets.Osu.UI;
|
||||||
|
using osu.Game.Skinning;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Tests
|
namespace osu.Game.Rulesets.Osu.Tests
|
||||||
@@ -58,7 +60,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
|
|
||||||
foreach (var smokeContainer in smokeContainers)
|
foreach (var smokeContainer in smokeContainers)
|
||||||
{
|
{
|
||||||
if (smokeContainer.Children.Count != 0)
|
if (smokeContainer.Children.OfType<SkinnableDrawable>().Any())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -191,6 +191,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
[FlakyTest]
|
||||||
public void TestRewind()
|
public void TestRewind()
|
||||||
{
|
{
|
||||||
AddStep("set manual clock", () => manualClock = new ManualClock
|
AddStep("set manual clock", () => manualClock = new ManualClock
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
double endTime = stackBaseObject.GetEndTime();
|
double endTime = stackBaseObject.GetEndTime();
|
||||||
double stackThreshold = objectN.TimePreempt * beatmap.StackLeniency;
|
float stackThreshold = calculateStackThreshold(beatmap, objectN);
|
||||||
|
|
||||||
if (objectN.StartTime - endTime > stackThreshold)
|
if (objectN.StartTime - endTime > stackThreshold)
|
||||||
// We are no longer within stacking range of the next object.
|
// We are no longer within stacking range of the next object.
|
||||||
@@ -136,7 +136,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
|||||||
OsuHitObject objectI = hitObjects[i];
|
OsuHitObject objectI = hitObjects[i];
|
||||||
if (objectI.StackHeight != 0 || objectI is Spinner) continue;
|
if (objectI.StackHeight != 0 || objectI is Spinner) continue;
|
||||||
|
|
||||||
double stackThreshold = objectI.TimePreempt * beatmap.StackLeniency;
|
float stackThreshold = calculateStackThreshold(beatmap, objectI);
|
||||||
|
|
||||||
/* If this object is a hitcircle, then we enter this "special" case.
|
/* If this object is a hitcircle, then we enter this "special" case.
|
||||||
* It either ends with a stack of hitcircles only, or a stack of hitcircles that are underneath a slider.
|
* It either ends with a stack of hitcircles only, or a stack of hitcircles that are underneath a slider.
|
||||||
@@ -151,7 +151,10 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
|||||||
|
|
||||||
double endTime = objectN.GetEndTime();
|
double endTime = objectN.GetEndTime();
|
||||||
|
|
||||||
if (objectI.StartTime - endTime > stackThreshold)
|
// truncation to integer is required to match stable
|
||||||
|
// compare https://github.com/peppy/osu-stable-reference/blob/08e3dafd525934cf48880b08e91c24ce4ad8b761/osu!/GameplayElements/HitObjectManager.cs#L1725
|
||||||
|
// - both quantities being subtracted there are integers
|
||||||
|
if ((int)objectI.StartTime - (int)endTime > stackThreshold)
|
||||||
// We are no longer within stacking range of the previous object.
|
// We are no longer within stacking range of the previous object.
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -232,7 +235,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
|||||||
|
|
||||||
for (int j = i + 1; j < hitObjects.Count; j++)
|
for (int j = i + 1; j < hitObjects.Count; j++)
|
||||||
{
|
{
|
||||||
double stackThreshold = hitObjects[i].TimePreempt * beatmap.StackLeniency;
|
float stackThreshold = calculateStackThreshold(beatmap, hitObjects[i]);
|
||||||
|
|
||||||
if (hitObjects[j].StartTime - stackThreshold > startTime)
|
if (hitObjects[j].StartTime - stackThreshold > startTime)
|
||||||
break;
|
break;
|
||||||
@@ -264,5 +267,17 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <remarks>
|
||||||
|
/// Truncation of <see cref="OsuHitObject.TimePreempt"/> to <see cref="int"/>, as well as keeping the result as <see cref="float"/>, are both done
|
||||||
|
/// <a href="https://github.com/peppy/osu-stable-reference/blob/08e3dafd525934cf48880b08e91c24ce4ad8b761/osu!/GameplayElements/HitObjectManager.cs#L1652">
|
||||||
|
/// for the purposes of stable compatibility
|
||||||
|
/// </a>.
|
||||||
|
/// Note that for top-level objects <see cref="OsuHitObject.TimePreempt"/> is supposed to be integral anyway;
|
||||||
|
/// see <see cref="OsuHitObject.ApplyDefaultsToSelf"/> using <see cref="IBeatmapDifficultyInfo.DifficultyRangeInt"/> when calculating it.
|
||||||
|
/// Slider ticks and end circles are the exception to that, but they do not matter for stacking.
|
||||||
|
/// </remarks>
|
||||||
|
private static float calculateStackThreshold(IBeatmap beatmap, OsuHitObject hitObject)
|
||||||
|
=> (int)hitObject.TimePreempt * beatmap.StackLeniency;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
|||||||
public static class AimEvaluator
|
public static class AimEvaluator
|
||||||
{
|
{
|
||||||
private const double wide_angle_multiplier = 1.5;
|
private const double wide_angle_multiplier = 1.5;
|
||||||
private const double acute_angle_multiplier = 2.6;
|
private const double acute_angle_multiplier = 2.55;
|
||||||
private const double slider_multiplier = 1.35;
|
private const double slider_multiplier = 1.35;
|
||||||
private const double velocity_change_multiplier = 0.75;
|
private const double velocity_change_multiplier = 0.75;
|
||||||
private const double wiggle_multiplier = 1.02;
|
private const double wiggle_multiplier = 1.02;
|
||||||
@@ -34,12 +34,13 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
|||||||
var osuCurrObj = (OsuDifficultyHitObject)current;
|
var osuCurrObj = (OsuDifficultyHitObject)current;
|
||||||
var osuLastObj = (OsuDifficultyHitObject)current.Previous(0);
|
var osuLastObj = (OsuDifficultyHitObject)current.Previous(0);
|
||||||
var osuLastLastObj = (OsuDifficultyHitObject)current.Previous(1);
|
var osuLastLastObj = (OsuDifficultyHitObject)current.Previous(1);
|
||||||
|
var osuLast2Obj = (OsuDifficultyHitObject)current.Previous(2);
|
||||||
|
|
||||||
const int radius = OsuDifficultyHitObject.NORMALISED_RADIUS;
|
const int radius = OsuDifficultyHitObject.NORMALISED_RADIUS;
|
||||||
const int diameter = OsuDifficultyHitObject.NORMALISED_DIAMETER;
|
const int diameter = OsuDifficultyHitObject.NORMALISED_DIAMETER;
|
||||||
|
|
||||||
// Calculate the velocity to the current hitobject, which starts with a base distance / time assuming the last object is a hitcircle.
|
// Calculate the velocity to the current hitobject, which starts with a base distance / time assuming the last object is a hitcircle.
|
||||||
double currVelocity = osuCurrObj.LazyJumpDistance / osuCurrObj.StrainTime;
|
double currVelocity = osuCurrObj.LazyJumpDistance / osuCurrObj.AdjustedDeltaTime;
|
||||||
|
|
||||||
// But if the last object is a slider, then we extend the travel velocity through the slider into the current object.
|
// But if the last object is a slider, then we extend the travel velocity through the slider into the current object.
|
||||||
if (osuLastObj.BaseObject is Slider && withSliderTravelDistance)
|
if (osuLastObj.BaseObject is Slider && withSliderTravelDistance)
|
||||||
@@ -51,7 +52,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
|||||||
}
|
}
|
||||||
|
|
||||||
// As above, do the same for the previous hitobject.
|
// As above, do the same for the previous hitobject.
|
||||||
double prevVelocity = osuLastObj.LazyJumpDistance / osuLastObj.StrainTime;
|
double prevVelocity = osuLastObj.LazyJumpDistance / osuLastObj.AdjustedDeltaTime;
|
||||||
|
|
||||||
if (osuLastLastObj.BaseObject is Slider && withSliderTravelDistance)
|
if (osuLastLastObj.BaseObject is Slider && withSliderTravelDistance)
|
||||||
{
|
{
|
||||||
@@ -69,8 +70,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
|||||||
|
|
||||||
double aimStrain = currVelocity; // Start strain with regular velocity.
|
double aimStrain = currVelocity; // Start strain with regular velocity.
|
||||||
|
|
||||||
if (Math.Max(osuCurrObj.StrainTime, osuLastObj.StrainTime) < 1.25 * Math.Min(osuCurrObj.StrainTime, osuLastObj.StrainTime)) // If rhythms are the same.
|
|
||||||
{
|
|
||||||
if (osuCurrObj.Angle != null && osuLastObj.Angle != null)
|
if (osuCurrObj.Angle != null && osuLastObj.Angle != null)
|
||||||
{
|
{
|
||||||
double currAngle = osuCurrObj.Angle.Value;
|
double currAngle = osuCurrObj.Angle.Value;
|
||||||
@@ -79,20 +78,26 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
|||||||
// Rewarding angles, take the smaller velocity as base.
|
// Rewarding angles, take the smaller velocity as base.
|
||||||
double angleBonus = Math.Min(currVelocity, prevVelocity);
|
double angleBonus = Math.Min(currVelocity, prevVelocity);
|
||||||
|
|
||||||
wideAngleBonus = calcWideAngleBonus(currAngle);
|
if (Math.Max(osuCurrObj.AdjustedDeltaTime, osuLastObj.AdjustedDeltaTime) < 1.25 * Math.Min(osuCurrObj.AdjustedDeltaTime, osuLastObj.AdjustedDeltaTime)) // If rhythms are the same.
|
||||||
|
{
|
||||||
acuteAngleBonus = calcAcuteAngleBonus(currAngle);
|
acuteAngleBonus = calcAcuteAngleBonus(currAngle);
|
||||||
|
|
||||||
// Penalize angle repetition.
|
// Penalize angle repetition.
|
||||||
wideAngleBonus *= 1 - Math.Min(wideAngleBonus, Math.Pow(calcWideAngleBonus(lastAngle), 3));
|
|
||||||
acuteAngleBonus *= 0.08 + 0.92 * (1 - Math.Min(acuteAngleBonus, Math.Pow(calcAcuteAngleBonus(lastAngle), 3)));
|
acuteAngleBonus *= 0.08 + 0.92 * (1 - Math.Min(acuteAngleBonus, Math.Pow(calcAcuteAngleBonus(lastAngle), 3)));
|
||||||
|
|
||||||
// Apply full wide angle bonus for distance more than one diameter
|
|
||||||
wideAngleBonus *= angleBonus * DifficultyCalculationUtils.Smootherstep(osuCurrObj.LazyJumpDistance, 0, diameter);
|
|
||||||
|
|
||||||
// Apply acute angle bonus for BPM above 300 1/2 and distance more than one diameter
|
// Apply acute angle bonus for BPM above 300 1/2 and distance more than one diameter
|
||||||
acuteAngleBonus *= angleBonus *
|
acuteAngleBonus *= angleBonus *
|
||||||
DifficultyCalculationUtils.Smootherstep(DifficultyCalculationUtils.MillisecondsToBPM(osuCurrObj.StrainTime, 2), 300, 400) *
|
DifficultyCalculationUtils.Smootherstep(DifficultyCalculationUtils.MillisecondsToBPM(osuCurrObj.AdjustedDeltaTime, 2), 300, 400) *
|
||||||
DifficultyCalculationUtils.Smootherstep(osuCurrObj.LazyJumpDistance, diameter, diameter * 2);
|
DifficultyCalculationUtils.Smootherstep(osuCurrObj.LazyJumpDistance, diameter, diameter * 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
wideAngleBonus = calcWideAngleBonus(currAngle);
|
||||||
|
|
||||||
|
// Penalize angle repetition.
|
||||||
|
wideAngleBonus *= 1 - Math.Min(wideAngleBonus, Math.Pow(calcWideAngleBonus(lastAngle), 3));
|
||||||
|
|
||||||
|
// Apply full wide angle bonus for distance more than one diameter
|
||||||
|
wideAngleBonus *= angleBonus * DifficultyCalculationUtils.Smootherstep(osuCurrObj.LazyJumpDistance, 0, diameter);
|
||||||
|
|
||||||
// Apply wiggle bonus for jumps that are [radius, 3*diameter] in distance, with < 110 angle
|
// Apply wiggle bonus for jumps that are [radius, 3*diameter] in distance, with < 110 angle
|
||||||
// https://www.desmos.com/calculator/dp0v0nvowc
|
// https://www.desmos.com/calculator/dp0v0nvowc
|
||||||
@@ -103,25 +108,39 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
|||||||
* DifficultyCalculationUtils.Smootherstep(osuLastObj.LazyJumpDistance, radius, diameter)
|
* DifficultyCalculationUtils.Smootherstep(osuLastObj.LazyJumpDistance, radius, diameter)
|
||||||
* Math.Pow(DifficultyCalculationUtils.ReverseLerp(osuLastObj.LazyJumpDistance, diameter * 3, diameter), 1.8)
|
* Math.Pow(DifficultyCalculationUtils.ReverseLerp(osuLastObj.LazyJumpDistance, diameter * 3, diameter), 1.8)
|
||||||
* DifficultyCalculationUtils.Smootherstep(lastAngle, double.DegreesToRadians(110), double.DegreesToRadians(60));
|
* DifficultyCalculationUtils.Smootherstep(lastAngle, double.DegreesToRadians(110), double.DegreesToRadians(60));
|
||||||
|
|
||||||
|
if (osuLast2Obj != null)
|
||||||
|
{
|
||||||
|
// If objects just go back and forth through a middle point - don't give as much wide bonus
|
||||||
|
// Use Previous(2) and Previous(0) because angles calculation is done prevprev-prev-curr, so any object's angle's center point is always the previous object
|
||||||
|
var lastBaseObject = (OsuHitObject)osuLastObj.BaseObject;
|
||||||
|
var last2BaseObject = (OsuHitObject)osuLast2Obj.BaseObject;
|
||||||
|
|
||||||
|
float distance = (last2BaseObject.StackedPosition - lastBaseObject.StackedPosition).Length;
|
||||||
|
|
||||||
|
if (distance < 1)
|
||||||
|
{
|
||||||
|
wideAngleBonus *= 1 - 0.35 * (1 - distance);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Math.Max(prevVelocity, currVelocity) != 0)
|
if (Math.Max(prevVelocity, currVelocity) != 0)
|
||||||
{
|
{
|
||||||
// We want to use the average velocity over the whole object when awarding differences, not the individual jump and slider path velocities.
|
// We want to use the average velocity over the whole object when awarding differences, not the individual jump and slider path velocities.
|
||||||
prevVelocity = (osuLastObj.LazyJumpDistance + osuLastLastObj.TravelDistance) / osuLastObj.StrainTime;
|
prevVelocity = (osuLastObj.LazyJumpDistance + osuLastLastObj.TravelDistance) / osuLastObj.AdjustedDeltaTime;
|
||||||
currVelocity = (osuCurrObj.LazyJumpDistance + osuLastObj.TravelDistance) / osuCurrObj.StrainTime;
|
currVelocity = (osuCurrObj.LazyJumpDistance + osuLastObj.TravelDistance) / osuCurrObj.AdjustedDeltaTime;
|
||||||
|
|
||||||
// Scale with ratio of difference compared to 0.5 * max dist.
|
// Scale with ratio of difference compared to 0.5 * max dist.
|
||||||
double distRatio = Math.Pow(Math.Sin(Math.PI / 2 * Math.Abs(prevVelocity - currVelocity) / Math.Max(prevVelocity, currVelocity)), 2);
|
double distRatio = DifficultyCalculationUtils.Smoothstep(Math.Abs(prevVelocity - currVelocity) / Math.Max(prevVelocity, currVelocity), 0, 1);
|
||||||
|
|
||||||
// Reward for % distance up to 125 / strainTime for overlaps where velocity is still changing.
|
// Reward for % distance up to 125 / strainTime for overlaps where velocity is still changing.
|
||||||
double overlapVelocityBuff = Math.Min(diameter * 1.25 / Math.Min(osuCurrObj.StrainTime, osuLastObj.StrainTime), Math.Abs(prevVelocity - currVelocity));
|
double overlapVelocityBuff = Math.Min(diameter * 1.25 / Math.Min(osuCurrObj.AdjustedDeltaTime, osuLastObj.AdjustedDeltaTime), Math.Abs(prevVelocity - currVelocity));
|
||||||
|
|
||||||
velocityChangeBonus = overlapVelocityBuff * distRatio;
|
velocityChangeBonus = overlapVelocityBuff * distRatio;
|
||||||
|
|
||||||
// Penalize for rhythm changes.
|
// Penalize for rhythm changes.
|
||||||
velocityChangeBonus *= Math.Pow(Math.Min(osuCurrObj.StrainTime, osuLastObj.StrainTime) / Math.Max(osuCurrObj.StrainTime, osuLastObj.StrainTime), 2);
|
velocityChangeBonus *= Math.Pow(Math.Min(osuCurrObj.AdjustedDeltaTime, osuLastObj.AdjustedDeltaTime) / Math.Max(osuCurrObj.AdjustedDeltaTime, osuLastObj.AdjustedDeltaTime), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (osuLastObj.BaseObject is Slider)
|
if (osuLastObj.BaseObject is Slider)
|
||||||
@@ -131,9 +150,13 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
|||||||
}
|
}
|
||||||
|
|
||||||
aimStrain += wiggleBonus * wiggle_multiplier;
|
aimStrain += wiggleBonus * wiggle_multiplier;
|
||||||
|
aimStrain += velocityChangeBonus * velocity_change_multiplier;
|
||||||
|
|
||||||
// Add in acute angle bonus or wide angle bonus + velocity change bonus, whichever is larger.
|
// Add in acute angle bonus or wide angle bonus, whichever is larger.
|
||||||
aimStrain += Math.Max(acuteAngleBonus * acute_angle_multiplier, wideAngleBonus * wide_angle_multiplier + velocityChangeBonus * velocity_change_multiplier);
|
aimStrain += Math.Max(acuteAngleBonus * acute_angle_multiplier, wideAngleBonus * wide_angle_multiplier);
|
||||||
|
|
||||||
|
// Apply high circle size bonus
|
||||||
|
aimStrain *= osuCurrObj.SmallCircleBonus;
|
||||||
|
|
||||||
// Add in additional slider velocity bonus.
|
// Add in additional slider velocity bonus.
|
||||||
if (withSliderTravelDistance)
|
if (withSliderTravelDistance)
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
|||||||
var currentObj = (OsuDifficultyHitObject)current.Previous(i);
|
var currentObj = (OsuDifficultyHitObject)current.Previous(i);
|
||||||
var currentHitObject = (OsuHitObject)(currentObj.BaseObject);
|
var currentHitObject = (OsuHitObject)(currentObj.BaseObject);
|
||||||
|
|
||||||
cumulativeStrainTime += lastObj.StrainTime;
|
cumulativeStrainTime += lastObj.AdjustedDeltaTime;
|
||||||
|
|
||||||
if (!(currentObj.BaseObject is Spinner))
|
if (!(currentObj.BaseObject is Spinner))
|
||||||
{
|
{
|
||||||
@@ -95,7 +95,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
|||||||
if (osuCurrent.BaseObject is Slider osuSlider)
|
if (osuCurrent.BaseObject is Slider osuSlider)
|
||||||
{
|
{
|
||||||
// Invert the scaling factor to determine the true travel distance independent of circle size.
|
// Invert the scaling factor to determine the true travel distance independent of circle size.
|
||||||
double pixelTravelDistance = osuSlider.LazyTravelDistance / scalingFactor;
|
double pixelTravelDistance = osuCurrent.LazyTravelDistance / scalingFactor;
|
||||||
|
|
||||||
// Reward sliders based on velocity.
|
// Reward sliders based on velocity.
|
||||||
sliderBonus = Math.Pow(Math.Max(0.0, pixelTravelDistance / osuCurrent.TravelTime - min_velocity), 0.5);
|
sliderBonus = Math.Pow(Math.Max(0.0, pixelTravelDistance / osuCurrent.TravelTime - min_velocity), 0.5);
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
|||||||
{
|
{
|
||||||
private const int history_time_max = 5 * 1000; // 5 seconds
|
private const int history_time_max = 5 * 1000; // 5 seconds
|
||||||
private const int history_objects_max = 32;
|
private const int history_objects_max = 32;
|
||||||
private const double rhythm_overall_multiplier = 0.95;
|
private const double rhythm_overall_multiplier = 1.0;
|
||||||
private const double rhythm_ratio_multiplier = 12.0;
|
private const double rhythm_ratio_multiplier = 15.0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates a rhythm multiplier for the difficulty of the tap associated with historic data of the current <see cref="OsuDifficultyHitObject"/>.
|
/// Calculates a rhythm multiplier for the difficulty of the tap associated with historic data of the current <see cref="OsuDifficultyHitObject"/>.
|
||||||
@@ -26,6 +26,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
|||||||
if (current.BaseObject is Spinner)
|
if (current.BaseObject is Spinner)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
var currentOsuObject = (OsuDifficultyHitObject)current;
|
||||||
|
|
||||||
double rhythmComplexitySum = 0;
|
double rhythmComplexitySum = 0;
|
||||||
|
|
||||||
double deltaDifferenceEpsilon = ((OsuDifficultyHitObject)current).HitWindowGreat * 0.3;
|
double deltaDifferenceEpsilon = ((OsuDifficultyHitObject)current).HitWindowGreat * 0.3;
|
||||||
@@ -62,22 +64,26 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
|||||||
|
|
||||||
double currHistoricalDecay = Math.Min(noteDecay, timeDecay); // either we're limited by time or limited by object count.
|
double currHistoricalDecay = Math.Min(noteDecay, timeDecay); // either we're limited by time or limited by object count.
|
||||||
|
|
||||||
double currDelta = currObj.StrainTime;
|
// Use custom cap value to ensure that that at this point delta time is actually zero
|
||||||
double prevDelta = prevObj.StrainTime;
|
double currDelta = Math.Max(currObj.DeltaTime, 1e-7);
|
||||||
double lastDelta = lastObj.StrainTime;
|
double prevDelta = Math.Max(prevObj.DeltaTime, 1e-7);
|
||||||
|
double lastDelta = Math.Max(lastObj.DeltaTime, 1e-7);
|
||||||
|
|
||||||
// calculate how much current delta difference deserves a rhythm bonus
|
// calculate how much current delta difference deserves a rhythm bonus
|
||||||
// this function is meant to reduce rhythm bonus for deltas that are multiples of each other (i.e 100 and 200)
|
// this function is meant to reduce rhythm bonus for deltas that are multiples of each other (i.e 100 and 200)
|
||||||
double deltaDifferenceRatio = Math.Min(prevDelta, currDelta) / Math.Max(prevDelta, currDelta);
|
double deltaDifference = Math.Max(prevDelta, currDelta) / Math.Min(prevDelta, currDelta);
|
||||||
double currRatio = 1.0 + rhythm_ratio_multiplier * Math.Min(0.5, Math.Pow(Math.Sin(Math.PI / deltaDifferenceRatio), 2));
|
|
||||||
|
// Take only the fractional part of the value since we're only interested in punishing multiples
|
||||||
|
double deltaDifferenceFraction = deltaDifference - Math.Truncate(deltaDifference);
|
||||||
|
|
||||||
|
double currRatio = 1.0 + rhythm_ratio_multiplier * Math.Min(0.5, DifficultyCalculationUtils.SmoothstepBellCurve(deltaDifferenceFraction));
|
||||||
|
|
||||||
// reduce ratio bonus if delta difference is too big
|
// reduce ratio bonus if delta difference is too big
|
||||||
double fraction = Math.Max(prevDelta / currDelta, currDelta / prevDelta);
|
double differenceMultiplier = Math.Clamp(2.0 - deltaDifference / 8.0, 0.0, 1.0);
|
||||||
double fractionMultiplier = Math.Clamp(2.0 - fraction / 8.0, 0.0, 1.0);
|
|
||||||
|
|
||||||
double windowPenalty = Math.Min(1, Math.Max(0, Math.Abs(prevDelta - currDelta) - deltaDifferenceEpsilon) / deltaDifferenceEpsilon);
|
double windowPenalty = Math.Min(1, Math.Max(0, Math.Abs(prevDelta - currDelta) - deltaDifferenceEpsilon) / deltaDifferenceEpsilon);
|
||||||
|
|
||||||
double effectiveRatio = windowPenalty * currRatio * fractionMultiplier;
|
double effectiveRatio = windowPenalty * currRatio * differenceMultiplier;
|
||||||
|
|
||||||
if (firstDeltaSwitch)
|
if (firstDeltaSwitch)
|
||||||
{
|
{
|
||||||
@@ -170,7 +176,10 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
|||||||
prevObj = currObj;
|
prevObj = currObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Math.Sqrt(4 + rhythmComplexitySum * rhythm_overall_multiplier) / 2.0; // produces multiplier that can be applied to strain. range [1, infinity) (not really though)
|
double rhythmDifficulty = Math.Sqrt(4 + rhythmComplexitySum * rhythm_overall_multiplier) / 2.0; // produces multiplier that can be applied to strain. range [1, infinity) (not really though)
|
||||||
|
rhythmDifficulty *= 1 - currentOsuObject.GetDoubletapness((OsuDifficultyHitObject)current.Next(0));
|
||||||
|
|
||||||
|
return rhythmDifficulty;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Island : IEquatable<Island>
|
private class Island : IEquatable<Island>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
|||||||
private const double single_spacing_threshold = OsuDifficultyHitObject.NORMALISED_DIAMETER * 1.25; // 1.25 circles distance between centers
|
private const double single_spacing_threshold = OsuDifficultyHitObject.NORMALISED_DIAMETER * 1.25; // 1.25 circles distance between centers
|
||||||
private const double min_speed_bonus = 200; // 200 BPM 1/4th
|
private const double min_speed_bonus = 200; // 200 BPM 1/4th
|
||||||
private const double speed_balancing_factor = 40;
|
private const double speed_balancing_factor = 40;
|
||||||
private const double distance_multiplier = 0.9;
|
private const double distance_multiplier = 0.8;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Evaluates the difficulty of tapping the current object, based on:
|
/// Evaluates the difficulty of tapping the current object, based on:
|
||||||
@@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
|||||||
var osuCurrObj = (OsuDifficultyHitObject)current;
|
var osuCurrObj = (OsuDifficultyHitObject)current;
|
||||||
var osuPrevObj = current.Index > 0 ? (OsuDifficultyHitObject)current.Previous(0) : null;
|
var osuPrevObj = current.Index > 0 ? (OsuDifficultyHitObject)current.Previous(0) : null;
|
||||||
|
|
||||||
double strainTime = osuCurrObj.StrainTime;
|
double strainTime = osuCurrObj.AdjustedDeltaTime;
|
||||||
double doubletapness = 1.0 - osuCurrObj.GetDoubletapness((OsuDifficultyHitObject?)osuCurrObj.Next(0));
|
double doubletapness = 1.0 - osuCurrObj.GetDoubletapness((OsuDifficultyHitObject?)osuCurrObj.Next(0));
|
||||||
|
|
||||||
// Cap deltatime to the OD 300 hitwindow.
|
// Cap deltatime to the OD 300 hitwindow.
|
||||||
@@ -60,6 +60,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Evaluators
|
|||||||
// Max distance bonus is 1 * `distance_multiplier` at single_spacing_threshold
|
// Max distance bonus is 1 * `distance_multiplier` at single_spacing_threshold
|
||||||
double distanceBonus = Math.Pow(distance / single_spacing_threshold, 3.95) * distance_multiplier;
|
double distanceBonus = Math.Pow(distance / single_spacing_threshold, 3.95) * distance_multiplier;
|
||||||
|
|
||||||
|
// Apply reduced small circle bonus because flow aim difficulty on small circles doesn't scale as hard as jumps
|
||||||
|
distanceBonus *= Math.Sqrt(osuCurrObj.SmallCircleBonus);
|
||||||
|
|
||||||
if (mods.OfType<OsuModAutopilot>().Any())
|
if (mods.OfType<OsuModAutopilot>().Any())
|
||||||
distanceBonus = 0;
|
distanceBonus = 0;
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user