Compare commits
617 Commits
2025.831.0
...
2025.1111.
| Author | SHA1 | Date | |
|---|---|---|---|
| ab7e5c94f1 | |||
| 8dc9ea4553 | |||
| dcf553c252 | |||
| 43f3a506ea | |||
| ab51579c27 | |||
| d8e977c05f | |||
| c023767df9 | |||
|
|
050c10cec2 | ||
|
|
b4fd7ec10f | ||
|
|
cbe7da99ad | ||
|
|
b1a421c22b | ||
|
|
9601708087 | ||
|
|
22f11b6fa5 | ||
|
|
f95d0d214e | ||
|
|
0205cf0fb9 | ||
|
|
8b2b6517ca | ||
|
|
ce3b8bc77b | ||
|
|
98829bf857 | ||
|
|
3c37ac1718 | ||
|
|
f8769d2e44 | ||
|
|
4d66762898 | ||
|
|
e61ae7ab8a | ||
|
|
98eb29c43d | ||
|
|
bb578d254d | ||
|
|
b7c07ad0e5 | ||
|
|
08621c4cc9 | ||
|
|
be9b99f975 | ||
|
|
765b9a20b5 | ||
|
|
473fb5720c | ||
|
|
5faf791ca0 | ||
|
|
9ca47fc53a | ||
|
|
79a76ce587 | ||
|
|
72fa1553c3 | ||
|
|
954061b00b | ||
|
|
b74962af92 | ||
|
|
1af462b692 | ||
|
|
763739e877 | ||
|
|
f96be84c57 | ||
|
|
613c208362 | ||
|
|
a3c78de710 | ||
|
|
e240817087 | ||
|
|
ddb844f81b | ||
|
|
b6f4175939 | ||
|
|
819da1bc38 | ||
|
|
33e42d2809 | ||
|
|
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 | ||
|
|
fbaf27e3db | ||
|
|
45eb34ecde | ||
|
|
10beab6ad3 | ||
|
|
70188d4fab | ||
|
|
1ce846294b | ||
|
|
4be29425a0 | ||
|
|
db3cc583e6 | ||
|
|
fec7ef7624 | ||
|
|
6e378ad5af | ||
|
|
8f8f605748 | ||
|
|
5f9ade6610 | ||
|
|
1a569e9e2a | ||
|
|
98762ce09e | ||
|
|
8f6f859c15 | ||
|
|
cf1834b080 | ||
|
|
a2bae15db1 | ||
|
|
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 | ||
|
|
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 | ||
|
|
9577472c9e | ||
|
|
55fe927af0 | ||
|
|
4ccfebe842 | ||
|
|
b7d6e76d19 | ||
|
|
e34b0659da | ||
|
|
e73e9275ba | ||
|
|
a9c021ce04 | ||
| d47e26f1ae | |||
| b0e5ae1109 | |||
| 47b859ab17 | |||
| 5e523eb0b1 | |||
|
|
9a2513230c | ||
|
|
ccc5ca5d80 | ||
|
|
9b9e7a8f75 | ||
|
|
d912f8c3b9 | ||
|
|
5b781655c1 | ||
|
|
644b797734 | ||
|
|
e5fbf62ff5 | ||
|
|
bcff6be5f6 | ||
|
|
0c68a91b4c | ||
|
|
69a0ac6c76 | ||
|
|
619a6e7321 | ||
|
|
83c6e57984 | ||
|
|
1ea17129cc | ||
|
|
1f4f6ce4fe | ||
|
|
231b366e5e | ||
|
|
762fee91ed | ||
|
|
4d76c467f8 | ||
|
|
699892c6a2 | ||
|
|
fa6b830a13 | ||
|
|
278b232318 | ||
|
|
6660406ee9 | ||
|
|
482b7b6d3f | ||
|
|
c8c87089e5 | ||
|
|
b3abd09517 | ||
|
|
014b55602d | ||
|
|
0cd3894fa6 | ||
|
|
a6e42fb0cb | ||
|
|
2bd734918a | ||
|
|
a436372b05 | ||
|
|
6362fed097 | ||
|
|
16594f2986 | ||
|
|
68e7af0c02 | ||
|
|
caad065433 | ||
|
|
11696a7a3c | ||
|
|
f94d5004ea | ||
|
|
335bc6cdf6 | ||
|
|
eb24e02c38 | ||
|
|
06c1b81c1b | ||
|
|
449038d070 | ||
|
|
35885a17b4 | ||
|
|
c2bc67d083 | ||
|
|
645518f5bd | ||
|
|
ffab8342f2 | ||
|
|
31188127ef | ||
|
|
48bad31255 | ||
|
|
1a49c81bab | ||
|
|
27db49bad3 | ||
|
|
e6dbb1020c | ||
|
|
e0c11504a2 | ||
|
|
35e1fa6660 | ||
|
|
330b61f4c0 | ||
|
|
3985596602 | ||
|
|
3786efaa5e | ||
|
|
0225c1a867 | ||
|
|
111b98ef8e | ||
|
|
22bfab95b0 | ||
|
|
18b5c652a3 | ||
|
|
3c1c537b1b | ||
|
|
6af48975b0 | ||
|
|
058835440d | ||
|
|
ea79422b60 | ||
|
|
543d21a0ce | ||
|
|
ab7985f31e | ||
|
|
52c10a42be | ||
|
|
912c0a39cf | ||
|
|
45ef97c92c | ||
|
|
54d4b16a01 | ||
|
|
54a0c7af23 | ||
|
|
891b717b3d | ||
|
|
11e1c2d73f | ||
|
|
4475bcafa9 | ||
|
|
32576ff249 | ||
|
|
134f854d7b | ||
|
|
bae288859b | ||
|
|
6e5bf57fe7 | ||
|
|
0027b9846d | ||
|
|
1627f67ada | ||
|
|
ae0f9619b9 | ||
|
|
815bf9c37b | ||
|
|
b0c7b6c700 | ||
|
|
3fcc8d45cb | ||
|
|
f1d06f796a | ||
|
|
be365dfdc5 | ||
|
|
1c608e779d | ||
|
|
b2501ae58f | ||
|
|
23d10ccdeb | ||
|
|
98c3437174 | ||
|
|
a56f81a731 | ||
|
|
dac534e22a | ||
|
|
1ba403753c | ||
|
|
f1a020d2c6 | ||
|
|
15d73ce07e | ||
|
|
0bbad3e1cd | ||
|
|
4ec620c4a9 | ||
|
|
6ce76786ed | ||
|
|
b97cb65444 | ||
|
|
3e8775051e | ||
|
|
0ab3b593e7 | ||
|
|
71d0afd4c2 | ||
|
|
19d194476f | ||
|
|
546113451b | ||
|
|
4a7ee6fafc | ||
|
|
eb1263aa32 | ||
|
|
a840e55977 | ||
|
|
315eea8d9a | ||
|
|
aa847c5833 | ||
|
|
5c66998c57 | ||
|
|
51e7593446 | ||
|
|
6399f7e3db | ||
|
|
1e50e36a64 | ||
|
|
48e4844fbb | ||
|
|
566562240e | ||
|
|
19361666a1 | ||
|
|
dc5794dceb | ||
|
|
f414dd70f5 | ||
|
|
69bcef8339 | ||
|
|
c29217240e | ||
|
|
4a193e96e0 | ||
|
|
79f7f0ecad | ||
|
|
95c7252467 | ||
|
|
a1105ba16f | ||
|
|
bee6c32b83 | ||
|
|
6c82f543e6 | ||
|
|
4ed72efeae | ||
|
|
5c6bbfcc6a | ||
|
|
9354547e15 | ||
|
|
a799720232 | ||
|
|
a78c78ecdd | ||
|
|
89aea73495 | ||
|
|
84309f57c5 | ||
|
|
1519084f72 | ||
|
|
677beb4251 | ||
|
|
a8ef57ad0a | ||
|
|
903d91b697 | ||
|
|
b0dcd06b38 | ||
|
|
9422fe52d1 | ||
|
|
f9e89afe03 | ||
|
|
cac136d3c6 | ||
|
|
63ab11ac16 | ||
|
|
a008a66fb2 | ||
|
|
eb392c47e9 | ||
|
|
ffb6ae2066 | ||
|
|
385529ec78 | ||
|
|
cf471066bf | ||
|
|
659480fa3f | ||
|
|
209ba76b21 | ||
|
|
5079a53cca | ||
|
|
060854f23a | ||
|
|
e2d661736e | ||
|
|
82a135af19 | ||
|
|
689cc27e68 | ||
|
|
da7e256302 | ||
|
|
9827f9f189 | ||
|
|
9d0043d03b | ||
|
|
0021434a62 | ||
|
|
677c008b4d | ||
|
|
12430ce464 | ||
|
|
5de7cc3efb | ||
|
|
4e976cff6a | ||
|
|
c7f1210281 | ||
|
|
b02093505d | ||
|
|
6a35b7237b | ||
|
|
90ac249f5e | ||
|
|
08ad27459e | ||
|
|
2fb481e2ee | ||
|
|
d6b4c2958d | ||
|
|
4ffc262073 | ||
|
|
a27fef2437 | ||
|
|
2b52c1de0b | ||
|
|
89492cbd81 | ||
|
|
1bb24c923d | ||
|
|
dfed564bda | ||
|
|
3cf0a9b9c0 | ||
|
|
107e103825 | ||
|
|
3f637db391 | ||
|
|
d4b357dfa0 | ||
|
|
e98579d3af | ||
|
|
a84c364e44 | ||
|
|
2ed79d354c | ||
|
|
d304a31757 | ||
|
|
087f0565e6 | ||
|
|
9ae6e509b7 | ||
|
|
b95573f97d | ||
|
|
03e7e2b0d8 | ||
|
|
20b316d32d | ||
|
|
a6f823e5bc | ||
|
|
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 | ||
|
|
1e2468d2bb | ||
|
|
cc7e60daab | ||
|
|
bb588566e6 | ||
|
|
cbab183ea1 | ||
|
|
b1e0cf8532 |
@@ -19,6 +19,11 @@ indent_style = space
|
||||
indent_size = 4
|
||||
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
|
||||
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.
|
||||
|
||||
|
||||
2
.gitignore
vendored
@@ -344,4 +344,4 @@ inspectcode
|
||||
FodyWeavers.xsd
|
||||
|
||||
.idea/.idea.osu.Desktop/.idea/misc.xml
|
||||
.idea/.idea.osu.Android/.idea/deploymentTargetDropDown.xml
|
||||
.idea/.idea.osu.Android/.idea/deploymentTargetDropDown.xml
|
||||
@@ -10,7 +10,7 @@
|
||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2025.829.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2025.1028.0" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<!-- Fody does not handle Android build well, and warns when unchanged.
|
||||
|
||||
@@ -189,7 +189,7 @@ namespace osu.Desktop
|
||||
}
|
||||
|
||||
// user party
|
||||
if (!hideIdentifiableInformation && multiplayerClient.Room != null)
|
||||
if (!hideIdentifiableInformation && multiplayerClient.Room != null && multiplayerClient.Room.Settings.MatchType != MatchType.Matchmaking)
|
||||
{
|
||||
MultiplayerRoom room = multiplayerClient.Room;
|
||||
|
||||
|
||||
@@ -115,12 +115,10 @@ namespace osu.Desktop
|
||||
if (IsFirstRun)
|
||||
LocalConfig.SetValue(OsuSetting.ReleaseStream, ReleaseStream.Lazer);
|
||||
|
||||
// if (IsPackageManaged)
|
||||
// return new NoActionUpdateManager();
|
||||
if (IsPackageManaged)
|
||||
return new NoActionUpdateManager();
|
||||
|
||||
// return new VelopackUpdateManager();
|
||||
|
||||
return new NoActionUpdateManager(); // for now, APIs are useless for actually downloading the releases. TODO: adapt UpdateManager for gitea
|
||||
return new VelopackUpdateManager(); // yay
|
||||
}
|
||||
|
||||
public override bool RestartAppWhenExited()
|
||||
|
||||
@@ -55,7 +55,7 @@ namespace osu.Desktop.Updater
|
||||
|
||||
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
|
||||
{
|
||||
AllowVersionDowngrade = true
|
||||
|
||||
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 401 KiB |
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 5.0 KiB |
|
Before Width: | Height: | Size: 7.6 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 8.8 KiB |
|
Before Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
@@ -1,2 +0,0 @@
|
||||
[General]
|
||||
// no version specified means v1
|
||||
@@ -157,7 +157,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestTinyDropletMissPreservesCatcherState()
|
||||
public void TestTinyDropletMissChangesCatcherState()
|
||||
{
|
||||
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("miss tiny droplet", () => attemptCatch(new TinyDroplet { X = 100 }));
|
||||
// catcher state and hyper dash state is preserved
|
||||
checkState(CatcherAnimationState.Kiai);
|
||||
// catcher state is changed but hyper dash state is preserved
|
||||
checkState(CatcherAnimationState.Fail);
|
||||
checkHyperDash(true);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
||||
|
||||
private float halfCatcherWidth;
|
||||
|
||||
public override int Version => 20250306;
|
||||
public override int Version => 20251020;
|
||||
|
||||
public CatchDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
|
||||
: base(ruleset, beatmap)
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Difficulty;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Scoring;
|
||||
using osu.Game.Scoring.Legacy;
|
||||
using osu.Game.Utils;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Difficulty
|
||||
{
|
||||
@@ -51,15 +51,13 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
||||
|
||||
// Combo scaling
|
||||
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();
|
||||
|
||||
score.Mods.OfType<IApplicableToDifficulty>().ForEach(m => m.ApplyToDifficulty(difficulty));
|
||||
|
||||
var track = new TrackVirtual(10000);
|
||||
score.Mods.OfType<IApplicableToTrack>().ForEach(m => m.ApplyToTrack(track));
|
||||
double clockRate = track.Rate;
|
||||
double clockRate = ModUtils.CalculateRateWithMods(score.Mods);
|
||||
|
||||
// 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;
|
||||
|
||||
@@ -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
|
||||
{
|
||||
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 LastObject => (PalpableCatchHitObject)base.LastObject;
|
||||
|
||||
/// <summary>
|
||||
/// Normalized position of <see cref="BaseObject"/>.
|
||||
/// </summary>
|
||||
public readonly float NormalizedPosition;
|
||||
|
||||
/// <summary>
|
||||
/// Normalized position of <see cref="LastObject"/>.
|
||||
/// </summary>
|
||||
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>
|
||||
/// Milliseconds elapsed since the start time of the previous <see cref="CatchDifficultyHitObject"/>, with a minimum of 40ms.
|
||||
/// </summary>
|
||||
@@ -29,13 +63,35 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Preprocessing
|
||||
: base(hitObject, lastObject, clockRate, objects, index)
|
||||
{
|
||||
// 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;
|
||||
LastNormalizedPosition = LastObject.EffectiveX * scalingFactor;
|
||||
|
||||
// Every strain interval is hard capped at the equivalent of 375 BPM streaming speed as a safety measure
|
||||
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.
|
||||
// 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.Catch.Difficulty.Evaluators;
|
||||
using osu.Game.Rulesets.Difficulty.Preprocessing;
|
||||
using osu.Game.Rulesets.Difficulty.Skills;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
@@ -11,10 +10,6 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Skills
|
||||
{
|
||||
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 StrainDecayBase => 0.2;
|
||||
|
||||
@@ -24,12 +19,6 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Skills
|
||||
|
||||
protected readonly float HalfCatcherWidth;
|
||||
|
||||
private float? lastPlayerPosition;
|
||||
private float lastDistanceMoved;
|
||||
private float lastExactDistanceMoved;
|
||||
private double lastStrainTime;
|
||||
private bool isInBuzzSection;
|
||||
|
||||
/// <summary>
|
||||
/// The speed multiplier applied to the player's catcher.
|
||||
/// </summary>
|
||||
@@ -49,80 +38,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty.Skills
|
||||
|
||||
protected override double StrainValueOf(DifficultyHitObject current)
|
||||
{
|
||||
var catchCurrent = (CatchDifficultyHitObject)current;
|
||||
|
||||
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;
|
||||
return MovementEvaluator.EvaluateDifficultyOf(current, catcherSpeedMultiplier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,8 @@ namespace osu.Game.Rulesets.Catch.Mods
|
||||
|
||||
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.Collections.Generic;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Catch.Judgements;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
@@ -53,13 +54,25 @@ namespace osu.Game.Rulesets.Catch.Objects
|
||||
|
||||
public override IEnumerable<string> LookupNames => lookup_names;
|
||||
|
||||
public BananaHitSampleInfo(int volume = 100)
|
||||
: base(string.Empty, volume: volume)
|
||||
public BananaHitSampleInfo()
|
||||
: 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)
|
||||
=> new BananaHitSampleInfo(newVolume.GetOr(Volume));
|
||||
public BananaHitSampleInfo(HitSampleInfo info)
|
||||
: 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)
|
||||
=> other != null;
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Catch.Objects
|
||||
{
|
||||
StartTime = time,
|
||||
BananaIndex = count,
|
||||
Samples = new List<HitSampleInfo> { new Banana.BananaHitSampleInfo(CreateHitSampleInfo().Volume) }
|
||||
Samples = new List<HitSampleInfo> { new Banana.BananaHitSampleInfo(CreateHitSampleInfo()) }
|
||||
});
|
||||
|
||||
count++;
|
||||
|
||||
@@ -224,7 +224,20 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
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 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
|
||||
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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
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)));
|
||||
|
||||
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++)
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -12,9 +12,59 @@ namespace osu.Game.Rulesets.Mania.Difficulty.Preprocessing
|
||||
{
|
||||
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)
|
||||
{
|
||||
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.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Rulesets.Difficulty.Preprocessing;
|
||||
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.Mods;
|
||||
|
||||
@@ -15,23 +14,17 @@ namespace osu.Game.Rulesets.Mania.Difficulty.Skills
|
||||
{
|
||||
private const double individual_decay_base = 0.125;
|
||||
private const double overall_decay_base = 0.30;
|
||||
private const double release_threshold = 30;
|
||||
|
||||
protected override double SkillMultiplier => 1;
|
||||
protected override double StrainDecayBase => 1;
|
||||
|
||||
private readonly double[] startTimes;
|
||||
private readonly double[] endTimes;
|
||||
private readonly double[] individualStrains;
|
||||
|
||||
private double individualStrain;
|
||||
private double highestIndividualStrain;
|
||||
private double overallStrain;
|
||||
|
||||
public Strain(Mod[] mods, int totalColumns)
|
||||
: base(mods)
|
||||
{
|
||||
startTimes = new double[totalColumns];
|
||||
endTimes = new double[totalColumns];
|
||||
individualStrains = new double[totalColumns];
|
||||
overallStrain = 1;
|
||||
}
|
||||
@@ -39,65 +32,24 @@ namespace osu.Game.Rulesets.Mania.Difficulty.Skills
|
||||
protected override double StrainValueOf(DifficultyHitObject 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
|
||||
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
|
||||
individualStrains[maniaCurrent.Column] = applyDecay(individualStrains[maniaCurrent.Column], maniaCurrent.ColumnStrainTime, individual_decay_base);
|
||||
individualStrains[maniaCurrent.Column] += IndividualStrainEvaluator.EvaluateDifficultyOf(current);
|
||||
|
||||
for (int i = 0; i < endTimes.Length; ++i)
|
||||
{
|
||||
// The current note is overlapped if a previous note or end is overlapping the current note body
|
||||
isOverlapping |= Precision.DefinitelyBigger(endTimes[i], startTime, 1) &&
|
||||
Precision.DefinitelyBigger(endTime, endTimes[i], 1) &&
|
||||
Precision.DefinitelyBigger(startTime, startTimes[i], 1);
|
||||
// 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.
|
||||
highestIndividualStrain = maniaCurrent.DeltaTime <= 1 ? Math.Max(highestIndividualStrain, individualStrains[maniaCurrent.Column]) : individualStrains[maniaCurrent.Column];
|
||||
|
||||
// We give a slight bonus to everything if something is held meanwhile
|
||||
if (Precision.DefinitelyBigger(endTimes[i], endTime, 1) &&
|
||||
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;
|
||||
overallStrain = applyDecay(overallStrain, maniaCurrent.DeltaTime, overall_decay_base);
|
||||
overallStrain += OverallStrainEvaluator.EvaluateDifficultyOf(current);
|
||||
|
||||
// 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)
|
||||
=> applyDecay(individualStrain, offset - current.Previous(0).StartTime, individual_decay_base)
|
||||
+ applyDecay(overallStrain, offset - current.Previous(0).StartTime, overall_decay_base);
|
||||
protected override double CalculateInitialStrain(double offset, DifficultyHitObject current) =>
|
||||
applyDecay(highestIndividualStrain, offset - current.Previous(0).StartTime, individual_decay_base)
|
||||
+ applyDecay(overallStrain, offset - current.Previous(0).StartTime, overall_decay_base);
|
||||
|
||||
private double applyDecay(double value, double deltaTime, double decayBase)
|
||||
=> value * Math.Pow(decayBase, deltaTime / 1000);
|
||||
|
||||
@@ -79,6 +79,7 @@ namespace osu.Game.Rulesets.Mania
|
||||
return new ManiaArgonSkinTransformer(skin, beatmap);
|
||||
|
||||
case DefaultLegacySkin:
|
||||
case RetroSkin:
|
||||
return new ManiaClassicSkinTransformer(skin, beatmap);
|
||||
|
||||
case LegacySkin:
|
||||
|
||||
@@ -14,8 +14,8 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
public override string Acronym => Name;
|
||||
public abstract int KeyCount { get; }
|
||||
public override ModType Type => ModType.Conversion;
|
||||
public override double ScoreMultiplier => 0.9;
|
||||
public override bool Ranked => UsesDefaultConfiguration;
|
||||
public override double ScoreMultiplier => 1;
|
||||
public override bool Ranked => true;
|
||||
|
||||
public void ApplyToBeatmapConverter(IBeatmapConverter beatmapConverter)
|
||||
{
|
||||
|
||||
@@ -7,5 +7,20 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
{
|
||||
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,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ using osu.Game.Rulesets.Mods;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
|
||||
@@ -34,6 +35,8 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
{
|
||||
var maniaBeatmap = (ManiaBeatmap)beatmap;
|
||||
|
||||
double mostCommonBeatLengthBefore = beatmap.GetMostCommonBeatLength();
|
||||
|
||||
var newObjects = new List<ManiaHitObject>();
|
||||
|
||||
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();
|
||||
|
||||
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 IconUsage? Icon => OsuIcon.ModOneKey;
|
||||
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 IconUsage? Icon => OsuIcon.ModTenKeys;
|
||||
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 IconUsage? Icon => OsuIcon.ModTwoKeys;
|
||||
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 IconUsage? Icon => OsuIcon.ModThreeKeys;
|
||||
public override LocalisableString Description => @"Play with three keys.";
|
||||
public override bool Ranked => false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
||||
|
||||
private Drawable noteAnimation = null!;
|
||||
|
||||
private float? minimumColumnWidth;
|
||||
private float? widthForNoteHeightScale;
|
||||
|
||||
public LegacyNotePiece()
|
||||
{
|
||||
@@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
||||
[BackgroundDependencyLoader]
|
||||
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
|
||||
{
|
||||
@@ -60,9 +60,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
||||
|
||||
if (texture != null)
|
||||
{
|
||||
// The height is scaled to the minimum column width, if provided.
|
||||
float minimumWidth = minimumColumnWidth ?? DrawWidth;
|
||||
noteAnimation.Scale = Vector2.Divide(new Vector2(DrawWidth, minimumWidth), texture.DisplayWidth);
|
||||
float noteHeight = widthForNoteHeightScale ?? DrawWidth;
|
||||
noteAnimation.Scale = Vector2.Divide(new Vector2(DrawWidth, noteHeight), texture.DisplayWidth);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,13 +42,22 @@ namespace osu.Game.Rulesets.Mania
|
||||
var bindings = new List<KeyBinding>();
|
||||
|
||||
for (int i = LeftKeys.Length - columns / 2; i < LeftKeys.Length; i++)
|
||||
bindings.Add(new KeyBinding(LeftKeys[i], currentAction++));
|
||||
{
|
||||
bindings.Add(new KeyBinding(LeftKeys[i], currentAction));
|
||||
bindings.Add(new KeyBinding(InputKey.None, currentAction++));
|
||||
}
|
||||
|
||||
if (columns % 2 == 1)
|
||||
bindings.Add(new KeyBinding(SpecialKey, currentAction++));
|
||||
{
|
||||
bindings.Add(new KeyBinding(SpecialKey, currentAction));
|
||||
bindings.Add(new KeyBinding(InputKey.None, currentAction++));
|
||||
}
|
||||
|
||||
for (int i = 0; i < columns / 2; i++)
|
||||
bindings.Add(new KeyBinding(RightKeys[i], currentAction++));
|
||||
{
|
||||
bindings.Add(new KeyBinding(RightKeys[i], currentAction));
|
||||
bindings.Add(new KeyBinding(InputKey.None, currentAction++));
|
||||
}
|
||||
|
||||
return bindings;
|
||||
}
|
||||
|
||||
@@ -15,22 +15,22 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
protected override string ResourceAssembly => "osu.Game.Rulesets.Osu.Tests";
|
||||
|
||||
[TestCase(6.7331304290522747d, 239, "diffcalc-test")]
|
||||
[TestCase(1.4602604078137214d, 54, "zero-length-sliders")]
|
||||
[TestCase(0.43052813047866129d, 4, "very-fast-slider")]
|
||||
[TestCase(0.14143808967817237d, 2, "nan-slider")]
|
||||
[TestCase(6.6232533278125061d, 239, "diffcalc-test")]
|
||||
[TestCase(1.5045783545699611d, 54, "zero-length-sliders")]
|
||||
[TestCase(0.43333836671191595d, 4, "very-fast-slider")]
|
||||
[TestCase(0.13841532030395723d, 2, "nan-slider")]
|
||||
public void Test(double expectedStarRating, int expectedMaxCombo, string name)
|
||||
=> base.Test(expectedStarRating, expectedMaxCombo, name);
|
||||
|
||||
[TestCase(9.6779746353001634d, 239, "diffcalc-test")]
|
||||
[TestCase(1.7691451263718989d, 54, "zero-length-sliders")]
|
||||
[TestCase(0.55785578988249407d, 4, "very-fast-slider")]
|
||||
[TestCase(9.6491691624112761d, 239, "diffcalc-test")]
|
||||
[TestCase(1.756936832498702d, 54, "zero-length-sliders")]
|
||||
[TestCase(0.57771197086735004d, 4, "very-fast-slider")]
|
||||
public void TestClockRateAdjusted(double expectedStarRating, int expectedMaxCombo, string name)
|
||||
=> Test(expectedStarRating, expectedMaxCombo, name, new OsuModDoubleTime());
|
||||
|
||||
[TestCase(6.7331304290522747d, 239, "diffcalc-test")]
|
||||
[TestCase(1.4602604078137214d, 54, "zero-length-sliders")]
|
||||
[TestCase(0.43052813047866129d, 4, "very-fast-slider")]
|
||||
[TestCase(6.6232533278125061d, 239, "diffcalc-test")]
|
||||
[TestCase(1.5045783545699611d, 54, "zero-length-sliders")]
|
||||
[TestCase(0.43333836671191595d, 4, "very-fast-slider")]
|
||||
public void TestClassicMod(double expectedStarRating, int expectedMaxCombo, string name)
|
||||
=> Test(expectedStarRating, expectedMaxCombo, name, new OsuModClassic());
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 865 B |
|
Before Width: | Height: | Size: 771 B |
|
Before Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
@@ -1,6 +0,0 @@
|
||||
[General]
|
||||
// no version specified means v1
|
||||
|
||||
[Fonts]
|
||||
HitCircleOverlap: 3
|
||||
ScoreOverlap: 3
|
||||
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.7 KiB |