Compare commits
978 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ef471f1e2 | ||
|
|
c3404d296a | ||
|
|
c609bcf2ee | ||
|
|
0aee9d7c3f | ||
|
|
a49c1703ae | ||
|
|
38eecd0db7 | ||
|
|
e320bafa8b | ||
|
|
754e5e61f2 | ||
|
|
afba85827a | ||
|
|
8cd5211b8b | ||
|
|
2d7525f2b4 | ||
|
|
7adb25888f | ||
|
|
b46912afcb | ||
|
|
ed3d4823b2 | ||
|
|
b8a360917e | ||
|
|
26dbe36a15 | ||
|
|
396447519d | ||
|
|
83e436bbd2 | ||
|
|
d307eff71f | ||
|
|
b935725096 | ||
|
|
12248acd7b | ||
|
|
07eb0f5e8e | ||
|
|
cfb5fc25c3 | ||
|
|
3816e1c5bd | ||
|
|
c9d551cd39 | ||
|
|
95bf0473f3 | ||
|
|
a9d92b78a2 | ||
|
|
b8ebace039 | ||
|
|
9223957931 | ||
|
|
5cddb7f2b6 | ||
|
|
08e7a3af16 | ||
|
|
1416cd432d | ||
|
|
2d6cf07a65 | ||
|
|
0b73d6112a | ||
|
|
b742ac0591 | ||
|
|
4546fd44ff | ||
|
|
216fa9341b | ||
|
|
1d6d5dcc94 | ||
|
|
61f451694f | ||
|
|
c681f0bd82 | ||
|
|
cbc0b2707e | ||
|
|
36d0f8a2a0 | ||
|
|
301f65ce16 | ||
|
|
f1b95fe45e | ||
|
|
3091d747e6 | ||
|
|
f4062e5ebb | ||
|
|
a8807f1ef0 | ||
|
|
10945927c1 | ||
|
|
ab25f698da | ||
|
|
b30e03ffb3 | ||
|
|
82157c7bd1 | ||
|
|
eb10f02ac3 | ||
|
|
b1ef94ef60 | ||
|
|
f89392b476 | ||
|
|
32c4f2239d | ||
|
|
404c00c2bf | ||
|
|
9def444442 | ||
|
|
771b69d151 | ||
|
|
cae6aa2305 | ||
|
|
14d80dc2f3 | ||
|
|
cb38bcd270 | ||
|
|
37a9a4121f | ||
|
|
4731c0c60d | ||
|
|
65111ae209 | ||
|
|
2a460de911 | ||
|
|
cee82a08ba | ||
|
|
387437cada | ||
|
|
af14da987e | ||
|
|
389b3ad2a4 | ||
|
|
5f1f5b7dcd | ||
|
|
7e3be4c45d | ||
|
|
c82881e6f2 | ||
|
|
6be1fabc55 | ||
|
|
4d480660b5 | ||
|
|
1f4ce98998 | ||
|
|
605f2e212e | ||
|
|
188eb74a70 | ||
|
|
2d7d113458 | ||
|
|
176ce6a3bd | ||
|
|
f267b1fc0b | ||
|
|
ea0bdb55af | ||
|
|
4004b36bfa | ||
|
|
d0a4c416e4 | ||
|
|
584fccec92 | ||
|
|
41cf8b4485 | ||
|
|
e12d853499 | ||
|
|
5c7fcdae06 | ||
|
|
70b82e0b66 | ||
|
|
32f6194a75 | ||
|
|
dd260e7b2a | ||
|
|
c1fbf2c18c | ||
|
|
42d03a29e7 | ||
|
|
675addf25c | ||
|
|
f0fd3ce850 | ||
|
|
991873dcbe | ||
|
|
fd54c764e7 | ||
|
|
18fe7b9906 | ||
|
|
a350d58065 | ||
|
|
f34e271b6d | ||
|
|
a9715a694c | ||
|
|
c0d6917721 | ||
|
|
08edd8595f | ||
|
|
e999840f8e | ||
|
|
a03bdbf695 | ||
|
|
79f19331f4 | ||
|
|
04e658710e | ||
|
|
769e21115b | ||
|
|
8d3be314d6 | ||
|
|
1a28fc98ac | ||
|
|
125d0aa03d | ||
|
|
388ee5c805 | ||
|
|
ba558c350f | ||
|
|
650b1ff89b | ||
|
|
6c65b8918a | ||
|
|
d31f4806fc | ||
|
|
0c6548a36d | ||
|
|
df5159e34c | ||
|
|
319d65a0c3 | ||
|
|
fd793d6b04 | ||
|
|
15c4188d48 | ||
|
|
9e0479fe9f | ||
|
|
a6ec6adbb5 | ||
|
|
7cdaabf6f8 | ||
|
|
c47ca4d6a4 | ||
|
|
930d365752 | ||
|
|
7a784a7938 | ||
|
|
fba49e7eec | ||
|
|
66b04969fd | ||
|
|
aeaad4194a | ||
|
|
455d4b2195 | ||
|
|
6e62a6a45d | ||
|
|
3c9be7d70b | ||
|
|
91c58eee04 | ||
|
|
958286e078 | ||
|
|
ea76880b7f | ||
|
|
298457a007 | ||
|
|
7d28e00e4f | ||
|
|
0118844c2e | ||
|
|
8c418f197a | ||
|
|
7fa677d766 | ||
|
|
17ae269cc9 | ||
|
|
535b6c3e8e | ||
|
|
f1d0cb6b4d | ||
|
|
7fffd0bb64 | ||
|
|
84890ac308 | ||
|
|
a67666af62 | ||
|
|
2ed69407de | ||
|
|
6e578a71a1 | ||
|
|
bdc0756655 | ||
|
|
4baf06e4f9 | ||
|
|
f4c283890f | ||
|
|
521aaf7294 | ||
|
|
d1da1d67e0 | ||
|
|
5b0715d5d0 | ||
|
|
cf27c6301f | ||
|
|
3354345cef | ||
|
|
6ae2235083 | ||
|
|
c5d2e90e5b | ||
|
|
0eed00dd64 | ||
|
|
2d4f3eac49 | ||
|
|
a55871c059 | ||
|
|
b831173ecf | ||
|
|
13ffce3ab3 | ||
|
|
6d969106c0 | ||
|
|
456ab667e9 | ||
|
|
48ae8c0e93 | ||
|
|
c96e4a0e67 | ||
|
|
2a1570e03a | ||
|
|
435ca37a71 | ||
|
|
e4bba96d1f | ||
|
|
a1382dfbd0 | ||
|
|
fe7ea6fcef | ||
|
|
edd38a686b | ||
|
|
8d4842d2ea | ||
|
|
3a16a724f5 | ||
|
|
677a956b25 | ||
|
|
92b3666f64 | ||
|
|
4d73416952 | ||
|
|
871c8a4477 | ||
|
|
9592b8323f | ||
|
|
9cdd46c0cd | ||
|
|
97f358f047 | ||
|
|
d8e47287b0 | ||
|
|
b9487dd95c | ||
|
|
2e55deebc9 | ||
|
|
b29a08bc93 | ||
|
|
098a52b485 | ||
|
|
cd706c544b | ||
|
|
a456b27011 | ||
|
|
b0b197a7a5 | ||
|
|
897679afc4 | ||
|
|
6ea4e3cfc1 | ||
|
|
ae7b832e00 | ||
|
|
79ab28a52e | ||
|
|
78314855eb | ||
|
|
d691dc1e18 | ||
|
|
297d5b25f0 | ||
|
|
5ebbab6da3 | ||
|
|
229252cd63 | ||
|
|
618f312b84 | ||
|
|
4fb632ecdb | ||
|
|
54878ebe8c | ||
|
|
8657b765b1 | ||
|
|
8ab2058ecc | ||
|
|
42043c3d6c | ||
|
|
28e8862254 | ||
|
|
7e848618e8 | ||
|
|
b6c17e944a | ||
|
|
c7af125afc | ||
|
|
381851e95e | ||
|
|
7f7b28874f | ||
|
|
72a87cae43 | ||
|
|
53914bbd32 | ||
|
|
68663146c8 | ||
|
|
8e395b0770 | ||
|
|
1c0aebf6aa | ||
|
|
65f8a6e335 | ||
|
|
58277574b5 | ||
|
|
7aba5f4578 | ||
|
|
28bc5ee925 | ||
|
|
62ce462c0f | ||
|
|
d9fa632204 | ||
|
|
85e5356a9c | ||
|
|
81e15f205b | ||
|
|
0ef3e69638 | ||
|
|
93e4f14b7b | ||
|
|
5bec5d79e9 | ||
|
|
a7ba214af3 | ||
|
|
f983b4dccf | ||
|
|
bbdf236a10 | ||
|
|
61c3e75a52 | ||
|
|
76f4b681fe | ||
|
|
e2b8236b59 | ||
|
|
bfb2c1cb3d | ||
|
|
fcdf3d6e1e | ||
|
|
838519b350 | ||
|
|
571d804f50 | ||
|
|
6901b5133b | ||
|
|
67a6273f6f | ||
|
|
df440b09e9 | ||
|
|
3f1a6ecc8c | ||
|
|
2b680c02c8 | ||
|
|
c2b28b5148 | ||
|
|
905a0260a6 | ||
|
|
8ce3be5efb | ||
|
|
e5e9b50215 | ||
|
|
e57dc96fd1 | ||
|
|
f097213466 | ||
|
|
d9a86d6d75 | ||
|
|
5afb09d798 | ||
|
|
4fd1daada4 | ||
|
|
8d213e4d6e | ||
|
|
8238134781 | ||
|
|
4496e0854f | ||
|
|
5ed068eb05 | ||
|
|
a44744c05b | ||
|
|
d42a57ef79 | ||
|
|
3a30642969 | ||
|
|
563d3033b9 | ||
|
|
89ababc5c0 | ||
|
|
45c9e6fc7e | ||
|
|
570499f6ab | ||
|
|
513c9b615d | ||
|
|
406708d0ba | ||
|
|
084e7b22fa | ||
|
|
1daddbf302 | ||
|
|
0e32f439fb | ||
|
|
e991c5a96f | ||
|
|
ef70dac1a0 | ||
|
|
b8e8caeb31 | ||
|
|
aceb410331 | ||
|
|
2bbfd46105 | ||
|
|
c879e36a9c | ||
|
|
8b630f7357 | ||
|
|
0c60606b4e | ||
|
|
53465bba25 | ||
|
|
6db3aa3459 | ||
|
|
ecca446505 | ||
|
|
d6192385dd | ||
|
|
fa29dbf5cb | ||
|
|
34aeb589d6 | ||
|
|
f3d8429327 | ||
|
|
0b66766e8a | ||
|
|
66ac678f1b | ||
|
|
78f6ae7e6a | ||
|
|
1e53bc7d1f | ||
|
|
6041d56bcd | ||
|
|
7e7c2cb153 | ||
|
|
189d8096db | ||
|
|
acde0696b1 | ||
|
|
75a9a9718d | ||
|
|
6c1a9465c0 | ||
|
|
507ab06721 | ||
|
|
a511157fa5 | ||
|
|
2e827542cf | ||
|
|
451d86b5b4 | ||
|
|
b24945eaba | ||
|
|
4cf3135d48 | ||
|
|
a26a2e7079 | ||
|
|
503740542d | ||
|
|
1b359aa674 | ||
|
|
b15a7e61d4 | ||
|
|
c022c3595f | ||
|
|
8d10e3d1b0 | ||
|
|
4efd356cbf | ||
|
|
a4c079c2e8 | ||
|
|
7cfee6db53 | ||
|
|
ce22f52b2b | ||
|
|
2e78742d8c | ||
|
|
5cae3fc336 | ||
|
|
3a9305d0d9 | ||
|
|
cc23d7734a | ||
|
|
edc457d5f5 | ||
|
|
37899c2508 | ||
|
|
8b60684103 | ||
|
|
cdc17ef3dd | ||
|
|
d52aedac4f | ||
|
|
d9590078f5 | ||
|
|
3f43fe82d0 | ||
|
|
a78ca88a02 | ||
|
|
d893309b4f | ||
|
|
0c1545f81d | ||
|
|
f76b9954a7 | ||
|
|
a12feaf3e4 | ||
|
|
7be1d119de | ||
|
|
e8ef3a492c | ||
|
|
d389665bd7 | ||
|
|
9b1dc76854 | ||
|
|
6be6ea9927 | ||
|
|
69f4580637 | ||
|
|
250d49e85d | ||
|
|
9bf1b68924 | ||
|
|
07f55fa53c | ||
|
|
c4318bef7b | ||
|
|
0777e5529f | ||
|
|
62d2e87d25 | ||
|
|
8f0bdb3c6d | ||
|
|
8162d0aacd | ||
|
|
09caabba73 | ||
|
|
820de42257 | ||
|
|
2afec0bcda | ||
|
|
5883626020 | ||
|
|
701d735202 | ||
|
|
e9c8a82b47 | ||
|
|
18e1f6c50b | ||
|
|
ca4bcd80d1 | ||
|
|
a4d3f17efb | ||
|
|
43a80f0491 | ||
|
|
104444e83b | ||
|
|
e31894caae | ||
|
|
9c8abf6f62 | ||
|
|
8f54b3e5de | ||
|
|
473ab19034 | ||
|
|
fef273ecc9 | ||
|
|
75d631bebb | ||
|
|
8a95459a17 | ||
|
|
03dc665605 | ||
|
|
036854a8be | ||
|
|
dc4d710d12 | ||
|
|
d7851ef40e | ||
|
|
7f4760ba1a | ||
|
|
667bc69eb1 | ||
|
|
f1ca5991c6 | ||
|
|
4cb15ab99d | ||
|
|
2a8fd5219a | ||
|
|
b62ee8c8e2 | ||
|
|
867624f980 | ||
|
|
efb1cb0632 | ||
|
|
fa8222d9a0 | ||
|
|
a979577e5d | ||
|
|
e917980a39 | ||
|
|
46842f9890 | ||
|
|
0d13686f07 | ||
|
|
f8f524bfe7 | ||
|
|
3fce4eb7ce | ||
|
|
a61dfab64f | ||
|
|
d35969dea5 | ||
|
|
897f2a857f | ||
|
|
0ddf49c7b6 | ||
|
|
032f111b53 | ||
|
|
c0fedc8589 | ||
|
|
4032558ef5 | ||
|
|
584e626ed5 | ||
|
|
ca4162cb82 | ||
|
|
add1fdf32c | ||
|
|
8814a18d0c | ||
|
|
af2707120a | ||
|
|
7246647ab6 | ||
|
|
a20267aee9 | ||
|
|
f8e7a525bd | ||
|
|
2ee4cd79f6 | ||
|
|
e48c25a200 | ||
|
|
3aa455a757 | ||
|
|
2acf2ed83d | ||
|
|
02786eab63 | ||
|
|
38c700ca48 | ||
|
|
1f349d1dae | ||
|
|
0ca463f70a | ||
|
|
8b6a2e58f8 | ||
|
|
14344568f2 | ||
|
|
5a6ed83545 | ||
|
|
1e00505671 | ||
|
|
fbffb7ef71 | ||
|
|
6a4b1b2a8a | ||
|
|
d2881942d8 | ||
|
|
fb6123e4cc | ||
|
|
324fe48df2 | ||
|
|
bfc37a345d | ||
|
|
7f9c8d997b | ||
|
|
219a2cdb3f | ||
|
|
2332458ed9 | ||
|
|
5089f23f79 | ||
|
|
1592d3efc8 | ||
|
|
ae59916e98 | ||
|
|
eb935b4143 | ||
|
|
3f0d0bbffe | ||
|
|
f3cae06288 | ||
|
|
2281aec440 | ||
|
|
48f2647742 | ||
|
|
63a2aeee10 | ||
|
|
714df342d9 | ||
|
|
5aa0368090 | ||
|
|
49b5730e5f | ||
|
|
82c2d14430 | ||
|
|
f8b5f713f3 | ||
|
|
803911c10f | ||
|
|
559d3a42b3 | ||
|
|
5e5f7b12ca | ||
|
|
e75139e5e6 | ||
|
|
4c803b62a8 | ||
|
|
aea3a7921d | ||
|
|
fbb0a08663 | ||
|
|
c02efc5ca1 | ||
|
|
024cf0cac8 | ||
|
|
d35ead558f | ||
|
|
8f91d8e7ac | ||
|
|
448c02033d | ||
|
|
8af0999510 | ||
|
|
f4f5e12a50 | ||
|
|
3e1b5b93d5 | ||
|
|
ee503eedce | ||
|
|
0c8bef6842 | ||
|
|
3370152d58 | ||
|
|
56c9e0f664 | ||
|
|
0c721b85dd | ||
|
|
b07e6799dc | ||
|
|
da8837710a | ||
|
|
7dc3a2159a | ||
|
|
46bd0570d7 | ||
|
|
6ea9a57e9f | ||
|
|
280e28163c | ||
|
|
065ef632ac | ||
|
|
b2cbb65c6a | ||
|
|
7c61df6887 | ||
|
|
a5541c121c | ||
|
|
6ca5abd896 | ||
|
|
5ed7cf73d1 | ||
|
|
ba647db6cf | ||
|
|
dd916a96eb | ||
|
|
eb2f464826 | ||
|
|
9df2758ae6 | ||
|
|
0196d69780 | ||
|
|
1b945bca10 | ||
|
|
8e0ab2f9f9 | ||
|
|
05cae9022f | ||
|
|
52551b2451 | ||
|
|
c841e9952b | ||
|
|
1803699086 | ||
|
|
41cb6749c8 | ||
|
|
abb0a55ac9 | ||
|
|
82f2c84034 | ||
|
|
2cfdd1da4f | ||
|
|
2b52ab90c3 | ||
|
|
958fa657cd | ||
|
|
18dda5aa06 | ||
|
|
1532f66bdf | ||
|
|
b99dc7c27d | ||
|
|
faf993cae6 | ||
|
|
a907b7717d | ||
|
|
4fd7adf547 | ||
|
|
da2d8abc56 | ||
|
|
2232022cf1 | ||
|
|
ffc0f3bc97 | ||
|
|
b3d422a6c5 | ||
|
|
8f6860d7d7 | ||
|
|
b5cd6887ae | ||
|
|
d8b0929975 | ||
|
|
e93428f457 | ||
|
|
e184f25184 | ||
|
|
579e3c639f | ||
|
|
ce726efc4f | ||
|
|
8c4d3092a7 | ||
|
|
a8c6ef8934 | ||
|
|
b1aeedb815 | ||
|
|
435cafd381 | ||
|
|
850d44d549 | ||
|
|
5f149f0a27 | ||
|
|
9e3f3cc036 | ||
|
|
11e83522d6 | ||
|
|
ab03dd3109 | ||
|
|
6e6fbf3be7 | ||
|
|
12a415e3d5 | ||
|
|
cce85ea663 | ||
|
|
a1ed7ed821 | ||
|
|
551a23b625 | ||
|
|
c37278c650 | ||
|
|
81393392ab | ||
|
|
94e1125eca | ||
|
|
fc694f1b0f | ||
|
|
3de827553e | ||
|
|
5a7d8e6b1f | ||
|
|
86224f5152 | ||
|
|
0d887dc5dc | ||
|
|
b8781ee209 | ||
|
|
849d5c63cb | ||
|
|
e3b22363d7 | ||
|
|
04c4fac58d | ||
|
|
c437a08084 | ||
|
|
93f067379c | ||
|
|
91b2901f05 | ||
|
|
9563755f26 | ||
|
|
3e1b0dc4e3 | ||
|
|
d09b237157 | ||
|
|
798ccecb2f | ||
|
|
56f3511395 | ||
|
|
f8ef9afdd9 | ||
|
|
c6e915448e | ||
|
|
cbb0f7f09b | ||
|
|
6d49ab45c3 | ||
|
|
932ed9f784 | ||
|
|
e2f1981dc4 | ||
|
|
a0215cd3f4 | ||
|
|
26e98d012f | ||
|
|
1f94a3b545 | ||
|
|
fc7e97a355 | ||
|
|
fdef9e37bb | ||
|
|
a088fd29b7 | ||
|
|
b5ff5f19fc | ||
|
|
7af3d6924e | ||
|
|
e6fef246cb | ||
|
|
08d2b40cc4 | ||
|
|
45f3cfdfa6 | ||
|
|
e93db8b48f | ||
|
|
5b4815f173 | ||
|
|
0af167d174 | ||
|
|
da66e7614d | ||
|
|
fdd2ef7b3a | ||
|
|
a7cf7b90ce | ||
|
|
bc6593fd81 | ||
|
|
14a405adb2 | ||
|
|
fcb43af8e3 | ||
|
|
0e98abff41 | ||
|
|
828c3c5345 | ||
|
|
d34798649b | ||
|
|
671313ab57 | ||
|
|
50e2b909f1 | ||
|
|
5bc2f47883 | ||
|
|
69a4dd8c6d | ||
|
|
b35c4d3de8 | ||
|
|
2c18f7a4a8 | ||
|
|
8041ccd6bd | ||
|
|
b19f65f7ee | ||
|
|
f6aca2018e | ||
|
|
80cacd609a | ||
|
|
5651bee2b5 | ||
|
|
9638d5c417 | ||
|
|
0fa6ad0e24 | ||
|
|
5431150362 | ||
|
|
171215e653 | ||
|
|
442684d852 | ||
|
|
7ea26bd052 | ||
|
|
72ff8d563b | ||
|
|
c4c5700d32 | ||
|
|
4fd64884f2 | ||
|
|
6d02a95273 | ||
|
|
926371c9a7 | ||
|
|
aaf4b558f3 | ||
|
|
f3faee2e16 | ||
|
|
00abbb4acd | ||
|
|
23bad12f8c | ||
|
|
4dc0935391 | ||
|
|
eb7ee9dabe | ||
|
|
136ea68ab3 | ||
|
|
ae744aa870 | ||
|
|
e967294eb9 | ||
|
|
2193057fce | ||
|
|
ef12275f35 | ||
|
|
c514c303c7 | ||
|
|
75078a5fa1 | ||
|
|
0b17725e8e | ||
|
|
3d5db5d79c | ||
|
|
d330376706 | ||
|
|
f01452dd87 | ||
|
|
d9d63a1b44 | ||
|
|
095008a20f | ||
|
|
bcefd42093 | ||
|
|
f9aec05779 | ||
|
|
406c43b0ec | ||
|
|
cdfb7074ec | ||
|
|
2ce6041ef8 | ||
|
|
2aa09f89db | ||
|
|
9128329d37 | ||
|
|
3cda07db52 | ||
|
|
aa0d98af8b | ||
|
|
f4a4acf742 | ||
|
|
458de52dbc | ||
|
|
654d461da5 | ||
|
|
0345ce844e | ||
|
|
cff3d3df56 | ||
|
|
f47b38f65d | ||
|
|
45ca7009c8 | ||
|
|
8429d78e01 | ||
|
|
d98ab8cf1e | ||
|
|
ed8e6775df | ||
|
|
ade50bad5e | ||
|
|
f6452b2320 | ||
|
|
215abb3198 | ||
|
|
24cfbcce40 | ||
|
|
5d4a2506e8 | ||
|
|
4b03b3c4ac | ||
|
|
cd6415b061 | ||
|
|
46c2d92082 | ||
|
|
58e69654a2 | ||
|
|
fcd879f97c | ||
|
|
d2c7023e7b | ||
|
|
256e5688e0 | ||
|
|
542a7b7fd2 | ||
|
|
984adc7885 | ||
|
|
938f7c9390 | ||
|
|
3458d1c7b3 | ||
|
|
a18a1cb8ce | ||
|
|
e42fb27459 | ||
|
|
28b6dd577a | ||
|
|
5a5110d905 | ||
|
|
8335e77f2e | ||
|
|
dd7c2a697a | ||
|
|
055ee01ae9 | ||
|
|
a59b55db57 | ||
|
|
415376ce08 | ||
|
|
ab56d18bd3 | ||
|
|
68239bc0b5 | ||
|
|
858fcd2a3a | ||
|
|
ed100613f3 | ||
|
|
d4e4150a6e | ||
|
|
306f403f18 | ||
|
|
7a3d5d2b94 | ||
|
|
fa992da2eb | ||
|
|
a5b42b8a43 | ||
|
|
202f2d8bc5 | ||
|
|
3434c7334b | ||
|
|
ebb3aa7ba3 | ||
|
|
5730b3b42d | ||
|
|
8aa44711e3 | ||
|
|
7ff8190977 | ||
|
|
5c6f515d18 | ||
|
|
0ff8a80ef2 | ||
|
|
f37d4063fb | ||
|
|
dde52653e5 | ||
|
|
5e3b346053 | ||
|
|
ed5a444753 | ||
|
|
6253169e35 | ||
|
|
2d143d0afd | ||
|
|
1b36852c8d | ||
|
|
739b13a1ce | ||
|
|
b3c1259580 | ||
|
|
045bcf6dc5 | ||
|
|
6977db708f | ||
|
|
e8d2256683 | ||
|
|
28707fa0f3 | ||
|
|
32d4208761 | ||
|
|
2f34b3ed8b | ||
|
|
02256e04ed | ||
|
|
a964f793d8 | ||
|
|
b80d98f36e | ||
|
|
3b59f95f20 | ||
|
|
f25539f389 | ||
|
|
f9fcc79565 | ||
|
|
a9b23552b0 | ||
|
|
3cd23a07e2 | ||
|
|
70d895fef5 | ||
|
|
5656dcb7ff | ||
|
|
ca78bce534 | ||
|
|
4bce7fadb4 | ||
|
|
681b341a51 | ||
|
|
69635f5e6c | ||
|
|
4ec4600406 | ||
|
|
e13c313839 | ||
|
|
429f82e4fe | ||
|
|
0334391e33 | ||
|
|
80e193398c | ||
|
|
8b686b60f1 | ||
|
|
f1ff0cb55f | ||
|
|
cb518863b0 | ||
|
|
6b6558af01 | ||
|
|
59014b86bf | ||
|
|
9d70f4de04 | ||
|
|
8ceba9fbee | ||
|
|
5cb69910bd | ||
|
|
0b91b02f80 | ||
|
|
50b76bf2ec | ||
|
|
de14c5782d | ||
|
|
fc34d54cdd | ||
|
|
8c41f713a6 | ||
|
|
2b0d918401 | ||
|
|
b56e1d501f | ||
|
|
7e206d4589 | ||
|
|
0c267f8eee | ||
|
|
817a518e82 | ||
|
|
e322b05707 | ||
|
|
3ca9311cb0 | ||
|
|
5899cce9d8 | ||
|
|
b350fedc66 | ||
|
|
8ddfe05dd6 | ||
|
|
6639188c5a | ||
|
|
0ccea05129 | ||
|
|
a36c7c5057 | ||
|
|
86b70728c7 | ||
|
|
d2b3372dd4 | ||
|
|
34e3cd1cbd | ||
|
|
90687007f5 | ||
|
|
8b7e989fed | ||
|
|
08a0407417 | ||
|
|
754ab67de7 | ||
|
|
7169a74e94 | ||
|
|
45331d17b0 | ||
|
|
05bd668cc2 | ||
|
|
2873d0d031 | ||
|
|
5d75f4a53a | ||
|
|
7b61dc3d58 | ||
|
|
8a3db29b02 | ||
|
|
e8fd11c08c | ||
|
|
6583337f48 | ||
|
|
4fae148e35 | ||
|
|
813643036b | ||
|
|
4acc5675d6 | ||
|
|
c2d80578fe | ||
|
|
d5d775f184 | ||
|
|
af5206cbfc | ||
|
|
388fe87c31 | ||
|
|
b22813c8e5 | ||
|
|
07fe495bfd | ||
|
|
959d990ab8 | ||
|
|
183017ca3b | ||
|
|
a60191cc82 | ||
|
|
8afbff9db9 | ||
|
|
06b43d9e07 | ||
|
|
bb586a7c0b | ||
|
|
661dcf0a96 | ||
|
|
c7048a09ac | ||
|
|
75d026b27f | ||
|
|
2045852e9c | ||
|
|
6d57eb1033 | ||
|
|
d9f87f18a1 | ||
|
|
7d8d4691da | ||
|
|
54cdba01ae | ||
|
|
efbf415787 | ||
|
|
80cd240ab8 | ||
|
|
b93c9ce1d6 | ||
|
|
7ee947b404 | ||
|
|
eae6dccbc0 | ||
|
|
181573dc74 | ||
|
|
e169971384 | ||
|
|
259c2e5ba1 | ||
|
|
da2395cc3a | ||
|
|
ab756a1f5a | ||
|
|
82d6d6d757 | ||
|
|
efbce82a8b | ||
|
|
19e70ddf87 | ||
|
|
ec5a412e37 | ||
|
|
f958624f6a | ||
|
|
2c16a4d908 | ||
|
|
2295317a84 | ||
|
|
993398180e | ||
|
|
b6ec7164d5 | ||
|
|
d4279dc309 | ||
|
|
c49540bd83 | ||
|
|
153f5de4fa | ||
|
|
85812ba489 | ||
|
|
442d45bef2 | ||
|
|
890b1822d8 | ||
|
|
3031ff7ab2 | ||
|
|
187023c81f | ||
|
|
a29c3bcc81 | ||
|
|
68fae41251 | ||
|
|
2df59b293b | ||
|
|
ab5cec7f33 | ||
|
|
0228d4e176 | ||
|
|
fba27fb3b1 | ||
|
|
78c660d5c0 | ||
|
|
7be66bb39d | ||
|
|
30e12a1f20 | ||
|
|
a39a210c1f | ||
|
|
04b11e2518 | ||
|
|
edb3920852 | ||
|
|
89eca2995b | ||
|
|
a1fb28b481 | ||
|
|
e02ede58da | ||
|
|
bb80441af0 | ||
|
|
397e16bb85 | ||
|
|
402d7b359d | ||
|
|
e70215eb9d | ||
|
|
618d53c707 | ||
|
|
383495a7e9 | ||
|
|
615caa7937 | ||
|
|
7ae5dd659a | ||
|
|
c2fa7883fe | ||
|
|
1213fff1ed | ||
|
|
58efa571ab | ||
|
|
4df2a22422 | ||
|
|
6f00bada10 | ||
|
|
a4d127afcf | ||
|
|
b6a91c523f | ||
|
|
e18061ffaf | ||
|
|
1376c295e1 | ||
|
|
9eb9be8e8e | ||
|
|
bad69dc66f | ||
|
|
d121ba7d2a | ||
|
|
7d0575aee4 | ||
|
|
060b984f48 | ||
|
|
0b80389971 | ||
|
|
ee23a9405a | ||
|
|
a15713dfa2 | ||
|
|
0b6951527d | ||
|
|
16deacb426 | ||
|
|
83266508af | ||
|
|
0d7e8daf8e | ||
|
|
3bdf8cb2be | ||
|
|
1383efd6c3 | ||
|
|
9538c415e1 | ||
|
|
0a8efa4238 | ||
|
|
90ad58f17f | ||
|
|
799870df63 | ||
|
|
2c1f117d35 | ||
|
|
0dfd57c4ee | ||
|
|
02ede93298 | ||
|
|
1772910a52 | ||
|
|
895326e819 | ||
|
|
a7b5839244 | ||
|
|
7a61779611 | ||
|
|
46fec675f1 | ||
|
|
4beea39615 | ||
|
|
1b32afb524 | ||
|
|
7aa77285a1 | ||
|
|
9bd7548df8 | ||
|
|
c7e36e18af | ||
|
|
55c78c1094 | ||
|
|
fdcc03c5f7 | ||
|
|
6b40f32d30 | ||
|
|
a82cb9c719 | ||
|
|
0a7aa8b05e | ||
|
|
a95728da84 | ||
|
|
137e003d1d | ||
|
|
8120fe2c04 | ||
|
|
efc8884e19 | ||
|
|
98be29b088 | ||
|
|
9443022f16 | ||
|
|
6d520937a1 | ||
|
|
5be2e141f3 | ||
|
|
c6cd69b5d7 | ||
|
|
08e4a05641 | ||
|
|
5d63f0bd9d | ||
|
|
73fc0b9ef5 | ||
|
|
190a601d6d | ||
|
|
1eb7a6b497 | ||
|
|
e5e0dc9332 | ||
|
|
224f5c677b | ||
|
|
3a0ea6fc77 | ||
|
|
7ebc99a6fc | ||
|
|
68155b1569 | ||
|
|
b8a3b64bc0 | ||
|
|
c31ec049e5 | ||
|
|
d2a9c01949 | ||
|
|
80d362dab3 | ||
|
|
a363894882 | ||
|
|
1ab164c935 | ||
|
|
b5ede15bfb | ||
|
|
0203d45901 | ||
|
|
132a4ee989 | ||
|
|
c63fc7475c | ||
|
|
8158955365 | ||
|
|
f5e58f2d4f | ||
|
|
21f2713300 | ||
|
|
20bc1985b1 | ||
|
|
51211cfb1e | ||
|
|
08e7ef3f66 | ||
|
|
322b80f176 | ||
|
|
37dbf6d2b5 | ||
|
|
7a2a194aea | ||
|
|
b47dd03a3e | ||
|
|
35ea13420e | ||
|
|
1f8c9557c8 | ||
|
|
68fe51e8cd | ||
|
|
ee40626c7d | ||
|
|
fc935d5f87 | ||
|
|
dc73cb00de | ||
|
|
a2b8f22e66 | ||
|
|
a17c233693 | ||
|
|
0910dc2428 | ||
|
|
5ee0cd1c98 | ||
|
|
00675ab95d | ||
|
|
9c7763be8c | ||
|
|
ba303432ff | ||
|
|
589492572a | ||
|
|
8f8cd815aa | ||
|
|
17d3ffe1c3 | ||
|
|
d7b6089ada | ||
|
|
2b44b4baa2 | ||
|
|
3a8377c283 | ||
|
|
5480035005 | ||
|
|
c3e3c6dfbb | ||
|
|
132f286391 | ||
|
|
b5c6831129 | ||
|
|
0d47edf1a7 | ||
|
|
cda4433d99 | ||
|
|
50f21af724 | ||
|
|
fc8eadec30 | ||
|
|
4c25c07e28 | ||
|
|
cc541f39d5 | ||
|
|
8aadf7c369 | ||
|
|
bee8b5259b | ||
|
|
3752ebbae5 | ||
|
|
f439c158e2 | ||
|
|
ad812de001 | ||
|
|
5dc16d0cab | ||
|
|
94425ba616 | ||
|
|
dac5c43635 | ||
|
|
c10856546f | ||
|
|
6afd656a99 | ||
|
|
d50b7b6960 | ||
|
|
c4d6531177 | ||
|
|
dddfdcf315 | ||
|
|
0b8d3a0b2b | ||
|
|
cdac59326a | ||
|
|
ce74680953 | ||
|
|
6cef01f946 | ||
|
|
fca7b2adaa | ||
|
|
80b1776ad3 | ||
|
|
727dfb2d62 | ||
|
|
7d0f1cb311 | ||
|
|
61292f5c9b | ||
|
|
7d448cce4f | ||
|
|
f6c06e5f2e | ||
|
|
b7a259e2c4 | ||
|
|
a1fcf21ac9 | ||
|
|
134c34fa58 | ||
|
|
6a63f9d95e | ||
|
|
6d91c79f28 | ||
|
|
5d8ede3247 | ||
|
|
ede8ad8551 | ||
|
|
6da5edd837 | ||
|
|
cd16117553 | ||
|
|
8b8ce3ca24 | ||
|
|
9f643cc739 | ||
|
|
97da2e2b5a | ||
|
|
ae147a5a9f | ||
|
|
67ab83a09b | ||
|
|
77234e29df | ||
|
|
90ed45d1c3 | ||
|
|
bbd2debc08 | ||
|
|
f40a7fa2f8 | ||
|
|
eb4d3d4762 | ||
|
|
a4973b8254 | ||
|
|
8f76e7be25 | ||
|
|
278b5e8140 | ||
|
|
10dc1f03e7 | ||
|
|
2d49c322e1 | ||
|
|
3f8904ef44 | ||
|
|
58dce72979 | ||
|
|
2d932a9e12 | ||
|
|
f74dfbb46a | ||
|
|
346d39c03a | ||
|
|
c4c3f58f41 | ||
|
|
1190513d0c | ||
|
|
012f965f6a | ||
|
|
c1126213cc | ||
|
|
b141efdbf2 | ||
|
|
1386891182 | ||
|
|
f698c41f00 |
13
.dockerignore
Normal file
13
.dockerignore
Normal file
@@ -0,0 +1,13 @@
|
||||
# Project administration files
|
||||
.idea
|
||||
.git
|
||||
.github
|
||||
|
||||
# Not used by the build.
|
||||
docs
|
||||
handbook
|
||||
sql
|
||||
tools
|
||||
|
||||
# Created by the db when using docker-compose, large and causes rebuild issues if sent to the context.
|
||||
docker-db-data
|
||||
24
.github/workflows/bump-version.yml
vendored
Normal file
24
.github/workflows/bump-version.yml
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# This workflow will tag the merge commit when merging a PR into the master branch.
|
||||
# Add "#patch", "#minor", or "#major" at end of the merge commit subject to dictate the type of bump.
|
||||
|
||||
name: Bump version
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: '0'
|
||||
|
||||
- name: Bump version and push tag
|
||||
uses: anothrNick/github-tag-action@1.55.0
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
WITH_V: true
|
||||
BRANCH_HISTORY: last
|
||||
20
.github/workflows/run-build.yml
vendored
Normal file
20
.github/workflows/run-build.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
# This workflow will build a Java project with Maven
|
||||
|
||||
name: Run build
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
- name: Build with Maven (compile -> test -> package)
|
||||
run: mvn -B package --file pom.xml
|
||||
54
.gitignore
vendored
54
.gitignore
vendored
@@ -1,50 +1,18 @@
|
||||
/logs/**
|
||||
.idea/
|
||||
*.iml
|
||||
/target
|
||||
|
||||
# build files
|
||||
|
||||
/build/
|
||||
/dist/
|
||||
/nbproject/private/
|
||||
|
||||
/tools/MapleArrowFetcher/build/
|
||||
/tools/MapleArrowFetcher/dist/
|
||||
/tools/MapleArrowFetcher/nbproject/private/
|
||||
|
||||
/tools/MapleCouponInstaller/build/
|
||||
/tools/MapleCouponInstaller/dist/
|
||||
/tools/MapleCouponInstaller/nbproject/private/
|
||||
|
||||
/tools/MapleIdRetriever/build/
|
||||
/tools/MapleIdRetriever/dist/
|
||||
/tools/MapleIdRetriever/nbproject/private/
|
||||
|
||||
/tools/MapleMapInfoRetriever/build/
|
||||
/tools/MapleMapInfoRetriever/dist/
|
||||
/tools/MapleMapInfoRetriever/nbproject/private/
|
||||
|
||||
/tools/MapleMesoFetcher/build/
|
||||
/tools/MapleMesoFetcher/dist/
|
||||
/tools/MapleMesoFetcher/nbproject/private/
|
||||
|
||||
/tools/MapleMobBookIndexer/build/
|
||||
/tools/MapleMobBookIndexer/dist/
|
||||
/tools/MapleMobBookIndexer/nbproject/private/
|
||||
|
||||
/tools/MapleMobBookUpdate/build/
|
||||
/tools/MapleMobBookUpdate/dist/
|
||||
/tools/MapleMobBookUpdate/nbproject/private/
|
||||
|
||||
/tools/MapleQuestItemFetcher/build/
|
||||
/tools/MapleQuestItemFetcher/dist/
|
||||
/tools/MapleQuestItemFetcher/nbproject/private/
|
||||
|
||||
/tools/MapleSkillMakerFetcher/build/
|
||||
/tools/MapleSkillMakerFetcher/dist/
|
||||
/tools/MapleSkillMakerFetcher/nbproject/private/
|
||||
|
||||
/tools/MapleSkillMakerReagentIndexer/build/
|
||||
/tools/MapleSkillMakerReagentIndexer/dist/
|
||||
/tools/MapleSkillMakerReagentIndexer/nbproject/private/
|
||||
|
||||
/nbproject/
|
||||
/.settings
|
||||
/out
|
||||
*.onetoc2
|
||||
|
||||
# Eclipse m2e generated files
|
||||
# Eclipse Core
|
||||
.project
|
||||
# JDT-specific (Eclipse Java Development Tools)
|
||||
.classpath
|
||||
|
||||
42
Dockerfile
Normal file
42
Dockerfile
Normal file
@@ -0,0 +1,42 @@
|
||||
# Initial Docker support thanks to xinyifly
|
||||
# Optimisation performed by wejrox
|
||||
|
||||
#
|
||||
# Cosmic JAR creation stage
|
||||
#
|
||||
FROM maven:3.9.1-eclipse-temurin-17 AS jar
|
||||
|
||||
# Build in a separated location which won't have permissions issues.
|
||||
WORKDIR /opt/cosmic
|
||||
# Any changes to the pom will affect the entire build, so it should be copied first.
|
||||
COPY pom.xml ./pom.xml
|
||||
# Grab all the dependencies listed in the pom early, since it prevents changes to source code from requiring a complete re-download.
|
||||
# Skip compiling tests since we don't want all the dependecies to be downloaded.
|
||||
RUN mvn -f ./pom.xml clean dependency:go-offline -Dmaven.test.skip -T 1C
|
||||
# Source code changes may not change dependencies, so it can go last.
|
||||
# Skip compiling tests since we don't want all the dependecies to be downloaded for plugins.
|
||||
COPY src ./src
|
||||
RUN mvn -f ./pom.xml clean package -Dmaven.test.skip -T 1C
|
||||
|
||||
#
|
||||
# Server creation stage
|
||||
#
|
||||
FROM eclipse-temurin:17.0.6_10-jre
|
||||
|
||||
# Host the server in a location that won't have permissions issues.
|
||||
WORKDIR /opt/server
|
||||
# Copy the wizet files first since they're so big and won't change often.
|
||||
COPY wz ./wz
|
||||
# Copy the JAR we build earlier.
|
||||
COPY --from=jar /opt/cosmic/target/Cosmic.jar ./Server.jar
|
||||
# Scripts are sourced on server startup, so you can mount over them for quicker redeploy.
|
||||
COPY scripts ./scripts/
|
||||
# Config is read on server startup, so you can mount over it for quicker redeploy.
|
||||
COPY config.yaml ./
|
||||
# Default exposure, although not required if using docker compose.
|
||||
# This exposes the login server, and channels.
|
||||
# Format for channels: WWCC, where WW is 75 plus the world number and CC is 75 plus the channel number (both zero indexed).
|
||||
EXPOSE 8484 7575 7576 7577
|
||||
ENTRYPOINT ["java", "-jar", "./Server.jar"]
|
||||
|
||||
|
||||
336
README.md
336
README.md
@@ -1,125 +1,130 @@
|
||||
# HeavenMS (MapleSolaxiaV2)
|
||||
---
|
||||
# Cosmic - MapleStory v83 server
|
||||
|
||||
## Head developer: Ronan C. P. Lana
|
||||
## Introduction
|
||||
Cosmic launched as a successor to HeavenMS on March 21st 2021.
|
||||
|
||||
Credits are to be given too to Nexon(Duh!), the original MapleSolaxia staff and other colaborators, as just some changes/patches on the game were applied by myself, in which some of them diverged from the original v83 patch contents.
|
||||
HeavenMS is archived, ie. it receives no further updates. This project aims to continue its development; mainly by improving code quality and make getting into PS development as easy as possible.
|
||||
|
||||
Regarding distributability and usage of the code presented here: like it was before, this MapleStory server is open-source. By that, it is meant that anyone is free to install, use, modify and redistribute the contents, as long as there is no kind of commercial trading involved and the credits to the original creators are maintained within the codes.
|
||||
This is an open source project. Anyone may contribute by opening a pull request.
|
||||
|
||||
This is a NetBeans 8.0.2 Project, that MUST be built and run under JDK/JRE 7 in order to run properly. This means that it's easier to install the project via opening the server project folder inside NetBeans' IDE. Once installed, build this project on your machine and run the server using the "launch.bat" application.
|
||||
|
||||
In this project, many gameplay-wise issues generated from either the original WZ files and the server sources have been partially or completely solved. Considering the use of the provided edited WZ's and server-side wz.xml files should be of the greatest importance when dealing with this instance of private server, in order to perceive it at it's full potential. My opinion, though! Refer to "README_wzchanges.txt" for more information on what has been changed from Nexon's v83 WZ files.
|
||||
|
||||
The main objective of this project is to try as best as possible to recreate what once was the original MapleStory v83, while adding up some flavors that spices up the gameplay. In other words, aim to get the best of the MapleStory of that era.
|
||||
|
||||
---
|
||||
### Download items
|
||||
|
||||
Server files: https://github.com/ronancpl/HeavenMS
|
||||
|
||||
Client files & general tools: https://drive.google.com/drive/folders/0BzDsHSr-0V4MYVJ0TWIxd05hYUk
|
||||
|
||||
Recommended localhost: https://hostr.co/r5QDmhlxpp8M
|
||||
|
||||
* MapleSilver's starting on window-mode, with some string fixes. This is a variation of Fraysa's https://hostr.co/gJbLZITRVHmv
|
||||
|
||||
---
|
||||
### Donation
|
||||
|
||||
If you liked what you have seen on the project, donate a little something as a helping hand for my contributions towards Maple development.
|
||||
Paypal: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=3K8KVTWRLFBQ4
|
||||
|
||||
---
|
||||
### Preparing the ambient
|
||||
|
||||
The following link teaches on how to install a MapleStory v83 private server, however IT DIFFERS on what is used here: http://forum.ragezone.com/f428/maplestory-private-server-v83-741739/
|
||||
|
||||
Use that link ONLY AS AN ORIENTATION on where here things start to become ambiguous.
|
||||
|
||||
Firstly, install all the general tools required to run the server:
|
||||
|
||||
* WampServer2.0i.exe -> recipient of the MySQL server.
|
||||
* mysql-query-browser.msi -> MySQL client component, visually shows the DB data and hubs queries.
|
||||
* hamachi.msi -> used for establishing a tunnelling route for the server/client communication.
|
||||
Only the server side is maintained. The client is directly copied from HeavenMS.
|
||||
|
||||
|
||||
Now install the Java 7 Development Kit:
|
||||
Beware - ***This server emulator is not production ready.***
|
||||
It can be useful for testing things locally or for trying out ideas, but launching a new private server based on this and opening it up to the public
|
||||
without knowing what you're doing is not recommended.
|
||||
|
||||
* jdk-7u79-windows-x64.exe
|
||||
* netbeans-8.0.2-javase-windows.exe -> It's a NetBeans project, use other IDE at your own risk.
|
||||
|
||||
Overwrite whenever prompted with the JAR files under "jce_policy-7/UnlimitedJCEPolicy" in these Java folders:
|
||||
## Development information
|
||||
|
||||
* C:\Program Files\Java\jre7\lib
|
||||
* C:\Program Files\Java\jre7\lib\ext
|
||||
* C:\Program Files\Java\jre7\lib\security
|
||||
* C:\Program Files\Java\jdk1.7.0_01\lib
|
||||
* C:\Program Files\Java\jdk1.7.0_01\jre\lib
|
||||
* C:\Program Files\Java\jdk1.7.0_01\jre\lib\ext
|
||||
* C:\Program Files\Java\jdk1.7.0_01\jre\lib\security
|
||||
### Status (updated 2022-10-16)
|
||||
|
||||
Now that the tools have been installed, test if they are working.
|
||||
Development is currently <span style="color:Yellow">**sporadic**</span>.
|
||||
|
||||
For WampServer:
|
||||
My time is very limited nowadays, but I try to keep up with the submitted pull requests. I may submit some stuff of my own, once in a while.
|
||||
|
||||
* Once you're done installing it, run it and you will see the Wamp icon on the bottom right corner.
|
||||
Left click it and click 'Put Online'.
|
||||
* In case of ORANGE ICON, change port 80 at "httpd.conf" to another, as it clashes with a Windows default port. Then Left click it again and click 'Start All Services'.
|
||||
* The Wamp icon must look completely green (if its orange or red, you have a problem).
|
||||
### Ways to contribute
|
||||
|
||||
For Hamachi:
|
||||
* Submit a Pull Request (fork -> commit -> PR). If you don't know where to start, have a look at the issues on GitHub.
|
||||
* Report a bug (preferably as an Issue on GitHub, as reports on Discord may be forgotten or lost)
|
||||
* Spread the word about Cosmic
|
||||
|
||||
* Try opening it. It's that simple.
|
||||
### Working with GitHub
|
||||
|
||||
Hamachi is optional, though. You don't have to install Hamachi if you want to make the server just for use on your own machine. However, if you want to let other players access your server, consider alternatively using port-forwarding methods.
|
||||
Anyone with a GitHub account can contribute by making some changes in a branch and opening up a PR.
|
||||
|
||||
---
|
||||
### Installing the SERVER
|
||||
All activity on the GitHub repo (opening PR, commenting, creating issue, etc.) is automatically pushed (via webhook) to a public Discord channel for visibility.
|
||||
|
||||
Set the "MapleSolaxiaV2" folder on a place of your preference. It is recommended for use "C:\Nexon\MapleSolaxiaV2".
|
||||
Issues is the main place where bugs, issues or general improvements are tracked. Feel free to submit a new issue, but please keep it in English. By providing a good description, you increase the chance of a bug being fixed.
|
||||
|
||||
Setting up the SQL: open MySQL Query Browser, then first-time create a new session, with these parameters at startup and click OK.
|
||||
Tasks (past, present and future) are kept in the Cosmic project, which you get to via the "Projects" tab. This gives you an idea of where the project is moving.
|
||||
|
||||
Server Host: localhost Port: 3306 Username: root
|
||||
### Versioning
|
||||
|
||||
Now it must be done CAREFULLY:
|
||||
The project follows the [SemVer](https://semver.org/) versioning scheme using git tags.
|
||||
As a pull request gets merged, a new version is automatically created.
|
||||
|
||||
1. File -> Open Script... -> Browse for "C:\Nexon\MapleSolaxiaV2\sql" -> db_database.sql, and execute it.
|
||||
Bug fixes result in bumped patch version: 1.2.__3__ -> 1.2.__4__
|
||||
|
||||
2. File -> Open Script... -> Browse for "C:\Nexon\MapleSolaxiaV2\sql" -> db_drops.sql, and execute it.
|
||||
General improvements result in bumped minor version: 1.__2__.3 -> 1.__3__.3
|
||||
|
||||
Now it is OPTIONAL, you don't need to run it if you don't want, as it will simply change some NPC shops to set some new goods, not present in the original MapleStory, to sell:
|
||||
Major changes result in bumped major version: __1__.2.3 -> __2__.2.3
|
||||
|
||||
3. File -> Open Script... -> Browse for "C:\Nexon\MapleSolaxiaV2\sql" -> db_shopupdate.sql, and execute it.
|
||||
### Cosmic
|
||||
|
||||
At the end of the execution of these SQLs, you should have installed a database schema named "heavenms". REGISTER YOUR FIRST ACCOUNT to be used in-game by creating manually an entry on the table "accounts" at that database with a login and a password.
|
||||
- GitHub: https://github.com/P0nk/Cosmic
|
||||
- Discord: https://discord.gg/JU5aQapVZK
|
||||
|
||||
Configure the IP you want to use for your MapleStory server in "configuration.ini" file, or set it as "localhost" if you want to run it only on your machine. Alternatively, you can use the IP given by Hamachi to use on a Hamachi network, or you can use a non-Hamachi method of port-forwarding. Neither will be approached here.
|
||||
### HeavenMS
|
||||
- GitHub: https://github.com/ronancpl/HeavenMS
|
||||
- Discord: https://discord.gg/Q7wKxHX
|
||||
|
||||
Now open NetBeans, and choose to Open a project... Select then the "MapleSolaxiaV2" folder, that should already be a project recognizable by NetBeans. If it isn't, you have a problem.
|
||||
## Tools / downloads
|
||||
* **Java 17 SDK** - Needed to compile and run Java code. Install manually or through IntelliJ depending on how you prefer to launch the server. Not required for launching with Docker.
|
||||
* Link: https://jdk.java.net/17/
|
||||
|
||||
|
||||
Inside the project, you may encounter some code errors. These happens because you have not set yet the "cores" of the project. From the project hierarchy, right-click the project and select "Resolve Project Problems". Locate the "cores" folder inside the root directory of this project and manually configure the missing files with the files that are there.
|
||||
* **IntelliJ IDEA** - Java IDE and your main tool for working with the source code. Community edition is good enough.
|
||||
* Link: https://www.jetbrains.com/idea/
|
||||
|
||||
|
||||
Finally, select "Clean and Build project" to build the JAR file for the MapleStory server. Once done, make sure both WampServer and Hamachi are on and functioning, and then execute "launch.bat" on the root of the project. If no errors were raised from this action, your MapleStory server is now online.
|
||||
* **MySQL Community Server 8** - Database for game data.
|
||||
* Link: https://dev.mysql.com/downloads/mysql/
|
||||
|
||||
|
||||
---
|
||||
### Installing the CLIENT
|
||||
* **MySQL Workbench 8** - Client for interacting with the database. Other clients do exist.
|
||||
* Link: https://dev.mysql.com/downloads/workbench/
|
||||
|
||||
|
||||
The client's set-up is quite straightforward:
|
||||
* **Docker Desktop** (optional) - For launching the game locally with less hassle.
|
||||
* Link: https://www.docker.com/products/docker-desktop
|
||||
|
||||
|
||||
1. From "ManagerMsv83.exe", install MapleStory on your folder of preference (e.g. "C:\Nexon\MapleStory") and follow their instructions.
|
||||
2. Once done, erase these files: "HShield" (folder), "ASPLauncher.exe", "MapleStory.exe" and "patcher.exe".
|
||||
3. Extract into the client folder the "localhost.exe" from the provided link.
|
||||
4. Overwrite the original WZ files with the ones provided from "client_wz" folder on the Google Drive.
|
||||
* **Client files and general tools**
|
||||
* Link: https://drive.google.com/drive/folders/1hgnb92MGL6xqEp9szEMBh0K9pSJcJ6IT?usp=sharing
|
||||
* This is Ponk's own Google Drive, similar to how Ronan provides files for HeavenMS.
|
||||
|
||||
|
||||
If you are not using "localhost" as the target IP on the server's config file, you will need to HEX-EDIT "localhost.exe" to fetch your IP. Track down all IP locations by searching for "Text String" "127.0.0.1", and applying the changes wherever it fits.
|
||||
### MapleStory client
|
||||
|
||||
To hex-edit, install the Neo Hex Editor from "free-hex-editor-neo.exe" and follow their instructions. Once done, open "localhost.exe" for editing and overwrite the IP values under the 3 addresses. Save the changes and exit the editor.
|
||||
- Latest localhost client: https://hostr.co/amuX5SLeeVZx
|
||||
|
||||
Open the "localhost.exe" client. If by any means the program did not open, and checking the server log your ping has been listened by the server and you are using Windows 8 or 10, it probably might be some compatibility issue.
|
||||
**Important note about localhost clients**: these executables are red-flagged by antivirus tools as __potentially malicious software__,
|
||||
this happens due to the reverse engineering methods that were applied onto these software artifacts.
|
||||
Those depicted here have been put to use for years already and posed no harm so far, so they are soundly assumed to be safe.
|
||||
|
||||
In that case, extract "lolwut.exe" from "lolwut-v0.01.rar" and place it on the MapleStory client folder ("C:\Nexon\MapleStory"). Your "localhost.exe" property settings must follow these:
|
||||
|
||||
## Getting started
|
||||
The localhost MapleStory client needs to be installed, as well as the server that will host the game.
|
||||
|
||||
### Installing the client
|
||||
|
||||
1. Install MapleStory with "MapleGlobal-v83-setup.exe" in your folder of choice (e.g. "C:\Nexon\MapleStory") and follow their instructions.
|
||||
2. Once done, erase these files: "HShield" (folder), "ASPLnchr.exe", "MapleStory.exe" and "Patcher.exe".
|
||||
3. Extract into the client folder the "HeavenMS-localhost-WINDOW.exe" (from now on referred to as "localhost.exe") from the provided link.
|
||||
4. Overwrite the original WZ files with the ones provided on the Google Drive: "CosmicWZ-v1-2021.05.10.zip"
|
||||
- This is currently identical to the latest HeavenMS WZ files (except for the file name): "commit397_wz-20210321T173600Z-001.zip"
|
||||
|
||||
#### Editing localhost IP target
|
||||
|
||||
If you are not using "localhost" as the target IP on the server's config file, you will need to HEX-EDIT localhost.exe to fetch your IP. Track down all IP locations by searching for "Type: String" "127.0.0.1", and applying the changes wherever it fits.
|
||||
|
||||
To hex-edit, install the Neo Hex Editor from "free-hex-editor-neo.exe" and follow their instructions. Once done, open localhost.exe for editing and overwrite the IP values under the 3 addresses. Save the changes and exit the editor.
|
||||
|
||||
(TODO: find suitable alternative to Neo Hex Editor)
|
||||
|
||||
#### Testing the localhost
|
||||
|
||||
Open the "localhost.exe" client.
|
||||
If by any means the program did not open, and checking the server log your ping has been listened by the server
|
||||
and you are using Windows 8, 10 or 11, it is probably some compatibility issue.
|
||||
|
||||
In some cases it helps to spam click the exe a few times (2-3 times usually works for me on W10).
|
||||
|
||||
In that case, extract "lolwut.exe" from "lolwut-v0.01.rar" and place it on the MapleStory client folder ("C:\Nexon\MapleStory").
|
||||
Your "localhost.exe" property settings must follow these:
|
||||
|
||||
Note: "lolwut.exe" is currently not available in the Google Drive.
|
||||
|
||||
* Run in compatibility mode: Windows 7;
|
||||
* Unchecked reduced color mode;
|
||||
@@ -128,40 +133,128 @@ In that case, extract "lolwut.exe" from "lolwut-v0.01.rar" and place it on the M
|
||||
* Run as an administrator;
|
||||
* Opening "lolwut.exe", use Fraysa's method.
|
||||
|
||||
Important: should the client be refused a connection to the game server, it may be because of a firewall issues. Head to the end of this file to proceed in allowing this connection through the computer's firewall. Alternatively, one can deactivate the firewall and try opening the client again.
|
||||
Important: should the client be refused a connection to the game server, it may be because of firewall issues. Head to the end of this file to proceed in allowing this connection through the computer's firewall. Alternatively, one can deactivate the firewall and try opening the client again.
|
||||
You can also search the server logs (/logs/cosmic-log.log) if any connection attempts have been made to ease debugging.
|
||||
|
||||
---
|
||||
### Important note about CLIENT EDITING
|
||||
### Installing the server
|
||||
1. Configure the project
|
||||
2. Set up the database
|
||||
3. Launch the server
|
||||
|
||||
DO NOT USE the server's XMLs for reimporting into the client's WZ, it WILL generate some kind of bugs afterwards.
|
||||
If you are using Docker (quick start):
|
||||
1. Configure the project
|
||||
2. Launch the server
|
||||
|
||||
* Use instead the HaRepacker 4.2.4, encryption "GMS (old)".
|
||||
* Open the desired WZ for editing and, USING THE UI, make the desired changes.
|
||||
* Save the changed WZ, overwriting the original content at the client folder.
|
||||
* Finally, RE-EXPORT ("Private Server..." exporting option) the changed XMLs into the server's WZ.XML files, overwriting the old contents.
|
||||
#### Configuring the project
|
||||
|
||||
These steps are IMPORTANT to maintain synchronization between the server and client modules.
|
||||
The easiest way to set up your project is to clone the repository directly into a new IntelliJ project.
|
||||
|
||||
As an example of client WZ editing, consider the MapleMobBookUpdate subproject I developed, for updating all reported drop data of the mobs in the game based on the current drop data on the database:
|
||||
1. Install IntelliJ
|
||||
2. Create a new "Project from Version Control..."
|
||||
3. Enter the URL to this GitHub repository: "https://github.com/P0nk/Cosmic.git"
|
||||
4. Click on "Clone". A new project will now be created with all the files from the repository.
|
||||
|
||||
* Open the MobBookUpdate project on NetBeans, located at "tools\MapleMobBookUpdate", and build it.
|
||||
* At the subfolder "lib", copy the file "MonsterBook.img.xml". This is from the original WZ v83.
|
||||
* Paste it on the "dist" subfolder.
|
||||
* Inside "dist", open the command prompt by alt+right clicking there.
|
||||
* Execute "java -jar MobBookUpdate.jar". It will generate a "MonsterBook_updated.img.xml" file.
|
||||
* At last, overwrite the "MonsterBook.img.xml" on "C:\Nexon\MapleSolaxiaV2\wz\String.wz" with this file, renaming it back to "MonsterBook.img.xml".
|
||||
#### Setting up the database
|
||||
|
||||
At this point, just the server-side Monster Book has been updated with the current state of the database's drop data.
|
||||
1. Install MySQL Server 8 and MySQL Workbench 8.
|
||||
2. Using Workbench, create a new user with username "cosmic_server" and password "snailshell".
|
||||
This the default configuration in Cosmic.
|
||||
* (Optional) Restrict the Schema Privileges for this new user for improved security.
|
||||
Add a new entry with "Schemas matching pattern: cosmic" and only select "SELECT", "INSERT", "UPDATE", "DELETE" under "Object Rights"
|
||||
3. Run the sql scripts in the "database/sql" directory of the project in the order indicated by their names.
|
||||
* Make sure you are connected to the database with the "root" user to be able to run the scripts.
|
||||
* Run scripts one by one through the menu: "File" -> "Run SQL Script" -> select the script file to run -> "Run"
|
||||
* The 3rd script "3-db_shopupdate" is optional. It adds custom shop items for certain NPCs.
|
||||
* The 4th script "4-db_admin" is also optional, but recommended if you are new. It adds an admin account to simplify the setup.
|
||||
|
||||
To update the client as well, open HaRepacker 4.2.2 and load "String.wz" from "C:\Nexon\MapleStory". Drop the "MonsterBook.img" node by removing it from the hierarchy tree, then (CONTRARY TO WHAT SHOULD BE DONE NORMALLY!) import the server's "MonsterBook.img.xml".
|
||||
Use this info when you connect to MySQL Server for the first time:
|
||||
* Server Host: localhost
|
||||
* Port: 3306
|
||||
* Username: root
|
||||
* Password: <whatever password you set during MySQL Server installation>
|
||||
|
||||
The client's WZ now has the proper item drops described by the DB updated into the MobBook drop list.
|
||||
At the end of the execution of these sql scripts, you should have installed a database schema named "cosmic".
|
||||
REGISTER YOUR FIRST ACCOUNT to be used in-game by **manually creating** an entry in the table "accounts" in the database with a username and password.
|
||||
|
||||
Take note that this kind of core change is absolutely dangerous if done unwary. Once the MonsterBook.img does not hold client specific data in it's node contents, importing the XML causes no harm at all.
|
||||
|
||||
However, try not to remove/reimport nodes from WZ files, as it may cause data losses. Use the HaRepacker's UI instead to make the changes.
|
||||
### Running the server
|
||||
|
||||
Save the changes and overwrite the older WZ on the MapleStory client folder.
|
||||
Configure the IP you want to use for your MapleStory server in "config.yaml" file, or set it as "localhost" if you want to run it only on your machine.
|
||||
Alternatively, you can use the IP given by Hamachi to use on a Hamachi network, or you can use a non-Hamachi method of port-forwarding. Neither will be approached here.
|
||||
|
||||
|
||||
To launch the server, you may either:
|
||||
* Launch inside IntelliJ
|
||||
* Launch a built jar file
|
||||
* Launch with Docker
|
||||
|
||||
#### Run inside IntelliJ
|
||||
1. Open the file src/main/java/net/server/Server.java.
|
||||
2. Click the green arrow to the left of the class definition "public class Server", and then "Run Cosmic".
|
||||
* Alternatively (recommended), create a new Configuration that points to "net.server.Server".
|
||||
3. The server launches in a terminal window inside IntelliJ.
|
||||
|
||||
#### Run from a jar file
|
||||
1. Create the jar file
|
||||
* The jar file is created by the Maven assembly plugin in the package lifecycle.
|
||||
* If you already have Maven installed, simply run the command "mvn clean install" to create the jar file.
|
||||
* IntelliJ also comes with built-in Maven support. Open a new terminal window inside IntelliJ, type "mvn clean install" (your command should now be marked green), then Ctrl+Enter to build the jar file.
|
||||
2. Launch the jar file
|
||||
* Double click on "launch.bat" (need to have Java 17 installed)
|
||||
|
||||
#### Run as containers with Docker
|
||||
1. Start Docker
|
||||
2. Run the command "docker compose up" at the root of the project.
|
||||
* If you make any changes to the code, make sure you append the "--build" option at the end of the command to force rebuild the server image.
|
||||
|
||||
---
|
||||
### Getting into the game
|
||||
|
||||
If you ran the admin sql script, there already exists an account in the database with an admin character on it (GM level 6).
|
||||
|
||||
Log in using these credentials:
|
||||
* Username: "admin"
|
||||
* Password: "admin"
|
||||
* Pin: "0000"
|
||||
* Pic: "000000"
|
||||
|
||||
Admin characters have "hide" mode enabled by default. This means your character will be translucent on your screen, and completely invisible to others.
|
||||
It will also prevent you from controlling mobs (making them stand still). To toggle this mode on and off, type "@hide" in the in-game chat.
|
||||
|
||||
By default, the server source is set to allow AUTO-REGISTERING. This means that, by simply typing in a "Login ID" and a "Password", you're able to create a new account.
|
||||
|
||||
After creating a character, experiment typing in all-chat "@commands".
|
||||
This will display all available commands for the current GM level your character has.
|
||||
|
||||
To change a character's GM level, make sure that character is not logged in, then:
|
||||
|
||||
1. Open MySQL Workbench;
|
||||
2. Expand "cosmic" schema;
|
||||
3. Expand "Tables";
|
||||
4. Right-click "characters" and click "Select Rows"
|
||||
5. Find your character in Result Grid. Scroll to the right and find the "gm" column.
|
||||
6. Edit your character's gm value and click "Apply", and then "Apply" again in the window that appeared, then "Finish".
|
||||
* 0 is what ordinary players start with, and 6 is the highest gm value. Higher level gms have access to more commands in game.
|
||||
|
||||
---
|
||||
### Some notes about WZ/WZ.XML EDITING
|
||||
Brief introduction to WZ files: they are the asset/data files required by the client and server. The client can read the .wz files directly, but the server requires them in XML format.
|
||||
The server also does not make use of any of the sprites, which is where different kinds of exporting comes into the picture. HaRepacker allows you to export to Private server XML, which is the .img files packaged in the .wz stripped of sprites and converted to XML.
|
||||
|
||||
Link to HaRepacker-resurrected, the standard tool for handling WZ files: https://github.com/lastbattle/Harepacker-resurrected
|
||||
|
||||
NOTE: Be extremely wary when using server-side's XMLs data being reimported into the client's WZ, as some means of synchronization between the server and client modules, this action COULD generate some kind of bugs afterwards. Client-to-server data reimporting seems to be fine, though.
|
||||
|
||||
#### Editing the v83 WZ's:
|
||||
|
||||
|
||||
* Use the HaRepacker-resurrected 4.2.4 editor, encryption "GMS (old)".
|
||||
* Open the desired WZ for editing and use the node hierarchy to make the desired changes (copy/pasting nodes may be unreliable in rare scenarios).
|
||||
* Save the changed WZ, **overwriting the original content** at the client folder.
|
||||
* Finally, **RE-EXPORT (using the "Private Server..." exporting option) the changed XMLs into the server's WZ.XML files**, overwriting the old contents.
|
||||
|
||||
**These steps are IMPORTANT, to maintain synchronization** between the server and client modules.
|
||||
|
||||
---
|
||||
### Portforwarding the SERVER
|
||||
@@ -172,7 +265,7 @@ The default login/password also varies, so use the link http://www.routerpasswor
|
||||
|
||||
Now you have logged in the router system, search for anything related to portforwarding. Should the system prompt you between portforwarding and portriggering, pick the first, it is what we will be using.
|
||||
|
||||
Now, it is needed to enable the right ports for the Internet. For MapleSolaxia, it is basically needed to open ports 7575 to 7575 + (number of channels) and port 8484. Create a new custom service which enables that range of ports for the server's channel and opt to use TCP/UDP protocols. Finally, create a custom service now for using port 8484.
|
||||
Now, it is needed to enable the right ports for the Internet. For Cosmic, it is basically needed to open ports 7575 to 7575 + (number of channels) and port 8484. Create a new custom service which enables that range of ports for the server's channel and opt to use TCP/UDP protocols. Finally, create a custom service now for using port 8484.
|
||||
|
||||
Optionally, if you want to host a webpage, portforward the port 80 (the HTTP port) as well.
|
||||
|
||||
@@ -181,3 +274,30 @@ It is not done yet, sometimes the firewalls will block connections between the L
|
||||
These rules must target "one application", "enable connections" and must target your MapleStory client (aka localhost).
|
||||
|
||||
After all these steps, the portforwarding process should now be complete.
|
||||
|
||||
---
|
||||
|
||||
### Client changelog
|
||||
The following list, in bottom-up chronological order,
|
||||
holds information regarding all changes that were applied from the starting localhost used in this development.
|
||||
Some lines have a link attached, that will lead you to a snapshot of the localhost at that version of the artifact.
|
||||
Naturally, later versions holds all previous changes along with the proposed changes.
|
||||
|
||||
**Change log:**
|
||||
|
||||
* Fixed Monster Magnet crashing the caster when trying to pull fixed mobs, credits to Shavit. https://gofile.io/?c=BW7dVM (dead link)
|
||||
* Cleared need for administrator privileges (OS) to play the game, credits to Ubaware.
|
||||
* Set a higher cap for AP assigning with AP Reset, credits to Ubaware.
|
||||
* Fixed Monster Magnet crashing the caster when trying to pull bosses. Drawback: Dojo HPBar becomes unavailable. https://hostr.co/SvnSKrGzXhG0
|
||||
* Fixed some 'rn' problems with quest icons & removed "tab" from party leader changed message. https://hostr.co/tsYsQzzV6xT0
|
||||
* Removed block on applying attack-based strengthening gems on non-weapon equipments. https://hostr.co/m2bVtnizCtmD
|
||||
* Set a higher cap for SPEED.
|
||||
* Removed the AP assigning block for beginners below level 10. https://hostr.co/AHAHzneCti9B
|
||||
* Removed block on party for beginners level 10 or below. https://hostr.co/JZq53mMtToCz
|
||||
* Removed block on MTS entering in some maps, rendering the buyback option available.
|
||||
* Removed "AP excess" popup and limited actions on Admin/MWLB, credits to kevintjuh93.
|
||||
* Removed "You've gained a level!" popup, credits to PrinceReborn.
|
||||
* Removed caps for WATK, WDEF, MDEF, ACC, AVOID.
|
||||
* 'n' problem fixed.
|
||||
* Fraysa's https://hostr.co/gJbLZITRVHmv
|
||||
* Eric's MapleSilver starting on window-mode.
|
||||
73
build.xml
73
build.xml
@@ -1,73 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- You may freely edit this file. See commented blocks below for -->
|
||||
<!-- some examples of how to customize the build. -->
|
||||
<!-- (If you delete it and reopen the project it will be recreated.) -->
|
||||
<!-- By default, only the Clean and Build commands use this build script. -->
|
||||
<!-- Commands such as Run, Debug, and Test only use this build script if -->
|
||||
<!-- the Compile on Save feature is turned off for the project. -->
|
||||
<!-- You can turn off the Compile on Save (or Deploy on Save) setting -->
|
||||
<!-- in the project's Project Properties dialog box.-->
|
||||
<project name="HeavenMS" default="default" basedir=".">
|
||||
<description>Builds, tests, and runs the project HeavenMS.</description>
|
||||
<import file="nbproject/build-impl.xml"/>
|
||||
<!--
|
||||
|
||||
There exist several targets which are by default empty and which can be
|
||||
used for execution of your tasks. These targets are usually executed
|
||||
before and after some main targets. They are:
|
||||
|
||||
-pre-init: called before initialization of project properties
|
||||
-post-init: called after initialization of project properties
|
||||
-pre-compile: called before javac compilation
|
||||
-post-compile: called after javac compilation
|
||||
-pre-compile-single: called before javac compilation of single file
|
||||
-post-compile-single: called after javac compilation of single file
|
||||
-pre-compile-test: called before javac compilation of JUnit tests
|
||||
-post-compile-test: called after javac compilation of JUnit tests
|
||||
-pre-compile-test-single: called before javac compilation of single JUnit test
|
||||
-post-compile-test-single: called after javac compilation of single JUunit test
|
||||
-pre-jar: called before JAR building
|
||||
-post-jar: called after JAR building
|
||||
-post-clean: called after cleaning build products
|
||||
|
||||
(Targets beginning with '-' are not intended to be called on their own.)
|
||||
|
||||
Example of inserting an obfuscator after compilation could look like this:
|
||||
|
||||
<target name="-post-compile">
|
||||
<obfuscate>
|
||||
<fileset dir="${build.classes.dir}"/>
|
||||
</obfuscate>
|
||||
</target>
|
||||
|
||||
For list of available properties check the imported
|
||||
nbproject/build-impl.xml file.
|
||||
|
||||
|
||||
Another way to customize the build is by overriding existing main targets.
|
||||
The targets of interest are:
|
||||
|
||||
-init-macrodef-javac: defines macro for javac compilation
|
||||
-init-macrodef-junit: defines macro for junit execution
|
||||
-init-macrodef-debug: defines macro for class debugging
|
||||
-init-macrodef-java: defines macro for class execution
|
||||
-do-jar: JAR building
|
||||
run: execution of project
|
||||
-javadoc-build: Javadoc generation
|
||||
test-report: JUnit report generation
|
||||
|
||||
An example of overriding the target for project execution could look like this:
|
||||
|
||||
<target name="run" depends="HeavenMS-impl.jar">
|
||||
<exec dir="bin" executable="launcher.exe">
|
||||
<arg file="${dist.jar}"/>
|
||||
</exec>
|
||||
</target>
|
||||
|
||||
Notice that the overridden target depends on the jar target and not only on
|
||||
the compile target as the regular run target does. Again, for a list of available
|
||||
properties which you can use, check the target you are overriding in the
|
||||
nbproject/build-impl.xml file.
|
||||
|
||||
-->
|
||||
</project>
|
||||
473
config.yaml
Normal file
473
config.yaml
Normal file
@@ -0,0 +1,473 @@
|
||||
#World Name: (0 "Scania", 1 "Bera", 2 "Broa", 3 "Windia", 4 "Khaini", 5 "Bellocan", 6 "Mardia", 7 "Kradia", 8 "Yellonde", 9 "Demethos", 10 "Galicia", 11 "El Nido", 12 "Zenith", 13 "Arcenia", 14 "Kastia", 15 "Judis", 16 "Plana", 17 "Kalluna", 18 "Stius", 19 "Croa", 20 "Medere")
|
||||
#Flag types: (0 = nothing, 1 = event, 2 = new, 3 = hot)
|
||||
#Recommended to use only up to 15 worlds
|
||||
worlds:
|
||||
#Properties for Scania 0
|
||||
- flag: 0
|
||||
server_message: Welcome to Scania!
|
||||
event_message: Scania!
|
||||
why_am_i_recommended: Welcome to Scania!
|
||||
channels: 3
|
||||
exp_rate: 10
|
||||
meso_rate: 10
|
||||
drop_rate: 10
|
||||
boss_drop_rate: 10 #NOTE: Boss drop rate OVERRIDES common drop rate, for bosses-only.
|
||||
quest_rate: 5 #Multiplier for Exp & Meso gains when completing a quest. Only available when USE_QUEST_RATE is true. Stacks with server Exp & Meso rates.
|
||||
fishing_rate: 10 #Multiplier for success likelihood on meso thrown during fishing.
|
||||
travel_rate: 10 #Means of transportation rides/departs using 1/N of the default time.
|
||||
|
||||
#Properties for Bera 1
|
||||
- flag: 0
|
||||
server_message: Welcome to Bera!
|
||||
event_message: Bera!
|
||||
why_am_i_recommended: Welcome to Bera!
|
||||
channels: 3
|
||||
|
||||
#Properties for Broa 2
|
||||
- flag: 0
|
||||
server_message: Welcome to Broa!
|
||||
event_message: Broa!
|
||||
why_am_i_recommended: Welcome to Broa!
|
||||
channels: 3
|
||||
|
||||
#Properties for Windia 3
|
||||
- flag: 0
|
||||
server_message: Welcome to Windia!
|
||||
event_message: Windia!
|
||||
why_am_i_recommended: Welcome to Windia!
|
||||
channels: 3
|
||||
|
||||
#Properties for Khaini 4
|
||||
- flag: 0
|
||||
server_message: Welcome to Khaini!
|
||||
event_message: Khaini!
|
||||
why_am_i_recommended: Welcome to Khaini!
|
||||
channels: 3
|
||||
|
||||
#Properties for Bellocan 5
|
||||
- flag: 0
|
||||
server_message: Welcome to Bellocan!
|
||||
event_message: Bellocan!
|
||||
why_am_i_recommended: Welcome to Bellocan!
|
||||
channels: 3
|
||||
|
||||
#Properties for Mardia 6
|
||||
- flag: 0
|
||||
server_message: Welcome to Mardia!
|
||||
event_message: Mardia!
|
||||
why_am_i_recommended: Welcome to Mardia!
|
||||
channels: 3
|
||||
|
||||
#Properties for Kradia 7
|
||||
- flag: 0
|
||||
server_message: Welcome to Kradia!
|
||||
event_message: Kradia!
|
||||
why_am_i_recommended: Welcome to Kradia!
|
||||
channels: 3
|
||||
|
||||
#Properties for Yellonde 8
|
||||
- flag: 0
|
||||
server_message: Welcome to Yellonde!
|
||||
event_message: Yellonde!
|
||||
why_am_i_recommended: Welcome to Yellonde!
|
||||
channels: 3
|
||||
|
||||
#Properties for Demethos 9
|
||||
- flag: 0
|
||||
server_message: Welcome to Demethos!
|
||||
event_message: Demethos!
|
||||
why_am_i_recommended: Welcome to Demethos!
|
||||
channels: 3
|
||||
|
||||
#Properties for Galicia 10
|
||||
- flag: 0
|
||||
server_message: Welcome to Galicia!
|
||||
event_message: Galicia!
|
||||
why_am_i_recommended: Welcome to Galicia!
|
||||
channels: 3
|
||||
|
||||
#Properties for Kastia 11
|
||||
- flag: 0
|
||||
server_message: Welcome to Kastia!
|
||||
event_message: Kastia!
|
||||
why_am_i_recommended: Welcome to Kastia!
|
||||
channels: 3
|
||||
|
||||
#Properties for Judis 12
|
||||
- flag: 0
|
||||
server_message: Welcome to Judis!
|
||||
event_message: Judis!
|
||||
why_am_i_recommended: Welcome to Judis!
|
||||
channels: 3
|
||||
|
||||
#Properties for Arcenia 13
|
||||
- flag: 0
|
||||
server_message: Welcome to Arcenia!
|
||||
event_message: Arcenia!
|
||||
why_am_i_recommended: Welcome to Arcenia!
|
||||
channels: 3
|
||||
|
||||
#Properties for Plana 14
|
||||
- flag: 0
|
||||
server_message: Welcome to Plana!
|
||||
event_message: Plana!
|
||||
why_am_i_recommended: Welcome to Plana!
|
||||
channels: 3
|
||||
|
||||
#Properties for El Nido 15
|
||||
- flag: 0
|
||||
server_message: Welcome to El Nido!
|
||||
event_message: El Nido!
|
||||
why_am_i_recommended: Welcome to El Nido!
|
||||
channels: 3
|
||||
|
||||
#Properties for Kalluna 16
|
||||
- flag: 0
|
||||
server_message: Welcome to Kalluna!
|
||||
event_message: Kalluna!
|
||||
why_am_i_recommended: Welcome to Kalluna!
|
||||
channels: 3
|
||||
|
||||
#Properties for Stius 17
|
||||
- flag: 0
|
||||
server_message: Welcome to Stius!
|
||||
event_message: Stius!
|
||||
why_am_i_recommended: Welcome to Stius!
|
||||
channels: 3
|
||||
|
||||
#Properties for Croa 18
|
||||
- flag: 0
|
||||
server_message: Welcome to Croa!
|
||||
event_message: Croa!
|
||||
why_am_i_recommended: Welcome to Croa!
|
||||
channels: 3
|
||||
|
||||
#Properties for Zenith 19
|
||||
- flag: 0
|
||||
server_message: Welcome to Zenith!
|
||||
event_message: Zenith!
|
||||
why_am_i_recommended: Welcome to Zenith!
|
||||
channels: 3
|
||||
|
||||
#Properties for Medere 20
|
||||
- flag: 0
|
||||
server_message: Welcome to Medere!
|
||||
event_message: Medere!
|
||||
why_am_i_recommended: Welcome to Medere!
|
||||
channels: 3
|
||||
|
||||
|
||||
server:
|
||||
#Database Configuration
|
||||
DB_URL_FORMAT: "jdbc:mysql://%s:3306/cosmic" # If the docker ENV for DB_HOST is anything but "db", this string format should be changed from 3306 to 3307 (or whichever port it was changed to in docker)
|
||||
DB_HOST: "localhost"
|
||||
DB_USER: "cosmic_server"
|
||||
DB_PASS: "snailshell"
|
||||
INIT_CONNECTION_POOL_TIMEOUT: 90 # Seconds
|
||||
|
||||
#Login Configuration
|
||||
WORLDS: 1 #Initial number of worlds on the server.
|
||||
WLDLIST_SIZE: 21 #Max possible worlds on the server.
|
||||
CHANNEL_SIZE: 20 #Max possible channels per world (which is 20, based on the channel list on login phase).
|
||||
CHANNEL_LOAD: 100 #Max players per channel (limit actually used to calculate the World server capacity).
|
||||
CHANNEL_LOCKS: 20 #Total number of structure management locks each channel has.
|
||||
|
||||
RESPAWN_INTERVAL: 10000 #10 seconds, 10000.
|
||||
PURGING_INTERVAL: 300000 #5 minutes, 300000.
|
||||
RANKING_INTERVAL: 3600000 #60 minutes, 3600000.
|
||||
COUPON_INTERVAL: 3600000 #60 minutes, 3600000.
|
||||
UPDATE_INTERVAL: 777 #Dictates the frequency on which the "centralized server time" is updated.
|
||||
|
||||
ENABLE_PIC: true #Pick true/false to enable or disable Pic. Delete character requires PIC available.
|
||||
ENABLE_PIN: true #Pick true/false to enable or disable Pin.
|
||||
|
||||
BYPASS_PIC_EXPIRATION: 20 #Enables PIC bypass, which will remain active for that account by that client machine for N minutes. Set 0 to disable.
|
||||
BYPASS_PIN_EXPIRATION: 15 #Enables PIN bypass, which will remain active for that account by that client machine for N minutes. Set 0 to disable.
|
||||
|
||||
AUTOMATIC_REGISTER: true #Automatically register players when they login with a nonexistent username.
|
||||
BCRYPT_MIGRATION: true #Performs a migration from old SHA-1 and SHA-512 password to bcrypt.
|
||||
COLLECTIVE_CHARSLOT: false #Available character slots are contabilized globally rather than per world server.
|
||||
DETERRED_MULTICLIENT: false #Enables detection of multi-client and suspicious remote IP on the login system.
|
||||
#Besides blocking logging in with several client sessions on the same machine, this also blocks suspicious login attempts for players that tries to login on an account using several diferent remote addresses.
|
||||
|
||||
#Multiclient Coordinator Configuration
|
||||
MAX_ALLOWED_ACCOUNT_HWID: 10 #Allows up to N concurrent HWID's for an account. HWID's remains linked to an account longer the more times it's used to login.
|
||||
MAX_ACCOUNT_LOGIN_ATTEMPT: 15 #After N tries on an account, login on that account gets disabled for a short period.
|
||||
LOGIN_ATTEMPT_DURATION: 120 #Period in seconds the login attempt remains registered on the system.
|
||||
|
||||
#Ip Configuration
|
||||
HOST: 127.0.0.1 #WAN IPv4 address
|
||||
LANHOST: 127.0.0.1 #LAN IPv4 address
|
||||
LOCALHOST: 127.0.0.1 #Loopback IPv4 address
|
||||
GMSERVER: false
|
||||
|
||||
#Other configuration
|
||||
SHUTDOWNHOOK: true
|
||||
|
||||
#Server Flags
|
||||
USE_CUSTOM_KEYSET: false #Enables auto-setup of the HeavenMS's custom keybindings when creating characters.
|
||||
USE_DEBUG: false #Will enable some text prints on the client, oriented for debugging purposes.
|
||||
USE_DEBUG_SHOW_INFO_EQPEXP: false #Prints on the cmd all equip exp gain info.
|
||||
USE_DEBUG_SHOW_RCVD_PACKET: false #Prints on the cmd all received packet ids.
|
||||
USE_DEBUG_SHOW_RCVD_MVLIFE: false #Prints on the cmd all received move life content.
|
||||
USE_DEBUG_SHOW_PACKET: false
|
||||
USE_SUPPLY_RATE_COUPONS: true #Allows rate coupons to be sold through the Cash Shop.
|
||||
USE_IP_VALIDATION: false #Enables IP checking when logging in.
|
||||
USE_CHARACTER_ACCOUNT_CHECK: false #Enables one-character-per-account check when logging in. This might be resource intensive.
|
||||
|
||||
USE_MAXRANGE: true #Will send and receive packets from all events on a map, rather than those of only view range.
|
||||
USE_MAXRANGE_ECHO_OF_HERO: true
|
||||
USE_MTS: false
|
||||
USE_CPQ: true #Renders the CPQ available or not.
|
||||
USE_AUTOHIDE_GM: true #When enabled, GMs are automatically hidden when joining. Thanks to Steven Deblois (steven1152).
|
||||
USE_BUYBACK_SYSTEM: false #Enables the HeavenMS-builtin buyback system, to be used by dead players when clicking the MTS button.
|
||||
USE_FIXED_RATIO_HPMP_UPDATE: false #Enables the HeavenMS-builtin HPMP update based on the current pool to max pool ratio.
|
||||
USE_FAMILY_SYSTEM: true
|
||||
USE_DUEY: true
|
||||
USE_RANDOMIZE_HPMP_GAIN: true #Enables randomizing on MaxHP/MaxMP gains and INT accounting for the MaxMP gain on level up.
|
||||
USE_STORAGE_ITEM_SORT: true #Enables storage "Arrange Items" feature.
|
||||
USE_ITEM_SORT: true #Enables inventory "Item Sort/Merge" feature.
|
||||
USE_ITEM_SORT_BY_NAME: false #Item sorting based on name rather than id.
|
||||
USE_PARTY_FOR_STARTERS: false #Players level 10 or below can create/invite other players on the given level range.
|
||||
USE_AUTOASSIGN_STARTERS_AP: true #Beginners level 10 or below have their AP autoassigned (they can't choose to levelup a stat). Set true ONLY if the localhost doesn't support AP assigning for beginners level 10 or below.
|
||||
USE_AUTOASSIGN_SECONDARY_CAP: true #Prevents AP autoassign from spending on secondary stats after the player class' cap (defined on the autoassign handler) has been reached.
|
||||
USE_STARTING_AP_4: false #Use early-GMS 4/4/4/4 starting stats. To overcome AP shortage, this gives 4AP/5AP at 1st/2nd job advancements.
|
||||
USE_AUTOBAN: false #Commands the server to detect infractors automatically.
|
||||
USE_AUTOBAN_LOG: true #Log autoban related messages. Still logs even with USE_AUTOBAN disabled.
|
||||
USE_AUTOSAVE: true #Enables server autosaving feature (saves characters to DB each 1 hour).
|
||||
USE_SERVER_AUTOASSIGNER: false #HeavenMS-builtin autoassigner, uses algorithm based on distributing AP accordingly with required secondary stat on equipments.
|
||||
USE_REFRESH_RANK_MOVE: true
|
||||
USE_ENFORCE_ADMIN_ACCOUNT: false #Forces accounts having GM characters to be treated as a "GM account" by the client (localhost). Some of the GM account perks is the ability to FLY, but unable to TRADE.
|
||||
USE_ENFORCE_NOVICE_EXPRATE: false #Hardsets experience rate 1x for beginners level 10 or under. Ideal for roaming on novice areas without caring too much about losing some stats.
|
||||
USE_ENFORCE_HPMP_SWAP: false #Forces players to reuse stats (via AP Resetting) located on HP/MP pool only inside the HP/MP stats.
|
||||
USE_ENFORCE_MOB_LEVEL_RANGE: true #Players N levels below the killed mob will gain no experience from defeating it.
|
||||
USE_ENFORCE_JOB_LEVEL_RANGE: false #Caps the player level on the minimum required to advance their current jobs.
|
||||
USE_ENFORCE_JOB_SP_RANGE: false #Caps the player SP level on the total obtainable by their current jobs. After changing jobs, missing SP will be retrieved.
|
||||
USE_ENFORCE_ITEM_SUGGESTION: false #Forces the Owl of Minerva and the Cash Shop to always display the defined item array instead of those featured by the players.
|
||||
USE_ENFORCE_UNMERCHABLE_CASH: true #Forces players to not sell CASH items via merchants, drops of it disappears.
|
||||
USE_ENFORCE_UNMERCHABLE_PET: true #Forces players to not sell pets via merchants, drops of it disappears. (since non-named pets gets dirty name and other possible DB-related issues)
|
||||
USE_ENFORCE_MERCHANT_SAVE: true #Forces automatic DB save on merchant owners, at every item movement on shop.
|
||||
USE_ENFORCE_MDOOR_POSITION: false #Forces mystic door to be spawned near spawnpoints.
|
||||
USE_SPAWN_CLEAN_MDOOR: false #Makes mystic doors to be spawned without deploy animation. This clears disconnecting issues that may happen when trying to cancel doors a couple seconds after deployment.
|
||||
USE_SPAWN_LOOT_ON_ANIMATION: false #Makes loot appear some time after the mob has been killed (following the mob death animation, instead of instantly).
|
||||
USE_SPAWN_RELEVANT_LOOT: true #Forces to only spawn loots that are collectable by the player or any of their party members.
|
||||
USE_ERASE_PERMIT_ON_OPENSHOP: true #Forces "shop permit" item to be consumed when player deploy his/her player shop.
|
||||
USE_ERASE_UNTRADEABLE_DROP: true #Forces flagged untradeable items to disappear when dropped.
|
||||
USE_ERASE_PET_ON_EXPIRATION: false #Forces pets to be removed from inventory when expire time comes, rather than converting it to a doll.
|
||||
USE_BUFF_MOST_SIGNIFICANT: true #When applying buffs, the player will stick with the highest stat boost among the listed, rather than overwriting stats.
|
||||
USE_BUFF_EVERLASTING: false #Every applied buff on players holds expiration time so high it'd be considered permanent. Suggestion thanks to Vcoc.
|
||||
USE_MULTIPLE_SAME_EQUIP_DROP: true #Enables multiple drops by mobs of the same equipment, number of possible drops based on the quantities provided at the drop data.
|
||||
USE_BANISHABLE_TOWN_SCROLL: false #Enables town scrolls to act as if it's a "player banish", rendering the antibanish scroll effect available.
|
||||
USE_ENABLE_FULL_RESPAWN: false #At respawn task, always respawn missing mobs when they're available. Spawn count doesn't depend on how many players are currently there.
|
||||
USE_ENABLE_CHAT_LOG: false #Write in-game chat to log
|
||||
USE_REBIRTH_SYSTEM: false #Flag to enable/disable rebirth system
|
||||
USE_MAP_OWNERSHIP_SYSTEM: false #Flag to enable/disable map ownership system
|
||||
USE_FISHING_SYSTEM: false #Flag to enable/disable custom fishing system
|
||||
USE_NPCS_SCRIPTABLE: true #Flag to enable/disable serverside predefined script NPCs.
|
||||
|
||||
#Events/PQs Configuration
|
||||
USE_OLD_GMS_STYLED_PQ_NPCS: true #Enables PQ NPCs with similar behaviour to old GMS style, that skips info about the PQs and immediately tries to register the party in.
|
||||
USE_ENABLE_SOLO_EXPEDITIONS: false #Enables start expeditions with any number of players. This will also bypass all the Zakum prequest.
|
||||
USE_ENABLE_DAILY_EXPEDITIONS: false #Enables daily entry limitations in expeditions.
|
||||
USE_ENABLE_RECALL_EVENT: false #Enables a disconnected player to reaccess the last event instance they were in before logging out. Recall only works if the event isn't cleared or disposed yet. Suggestion thanks to Alisson (Goukken).
|
||||
|
||||
#Announcement Configuration
|
||||
USE_ANNOUNCE_SHOPITEMSOLD: false #Automatic message sent to owner when an item from the Player Shop or Hired Merchant is sold.
|
||||
USE_ANNOUNCE_CHANGEJOB: false #Automatic message sent to acquantainces when changing jobs.
|
||||
USE_ANNOUNCE_NX_COUPON_LOOT: false #Enables or disables the floating text when a player loots a NX card
|
||||
|
||||
#Cash Shop Configuration
|
||||
USE_JOINT_CASHSHOP_INVENTORY: false #Enables usage of a same cash shop inventory for explorers, cygnus and legends. Items from exclusive cash shop inventories won't show up on the shared inventory, though.
|
||||
USE_CLEAR_OUTDATED_COUPONS: true #Enables deletion of older code coupon registry from the DB, freeing so-long irrelevant data.
|
||||
ALLOW_CASHSHOP_NAME_CHANGE: true #Allows players to buy name changes in the cash shop.
|
||||
ALLOW_CASHSHOP_WORLD_TRANSFER: true #Allows players to buy world transfers in the cash shop.
|
||||
|
||||
#Maker Configuration
|
||||
USE_MAKER_PERMISSIVE_ATKUP: false #Allows players to use attack-based strengthening gems on non-weapon items.
|
||||
USE_MAKER_FEE_HEURISTICS: true #Apply compiled values for stimulants and reagents into the Maker fee calculations (max error revolves around 50k mesos). Set false to use basic constant values instead (results are never higher than requested by the client-side).
|
||||
|
||||
#Custom Configuration
|
||||
USE_ENABLE_CUSTOM_NPC_SCRIPT: false #Enables usage of custom HeavenMS NPC scripts (Agent E, Coco, etc). Will not disable Abdula (it's actually useful for the gameplay) or quests.
|
||||
USE_STARTER_MERGE: false #Allows any players to use the Equipment Merge custom mechanic (as opposed to the high-level, Maker lv3 requisites).
|
||||
|
||||
#Commands Configuration
|
||||
BLOCK_GENERATE_CASH_ITEM: false #Prevents creation of cash items with the item/drop command.
|
||||
USE_WHOLE_SERVER_RANKING: false #Enables a ranking pool made from every character registered on the server for the "ranks" command, instead of separated by worlds.
|
||||
|
||||
EQUIP_EXP_RATE: 1.0 #Rate for equipment exp gain, grows linearly. Set 1.0 for default (about 100~200 same-level range mobs killed to pass equip from level 1 to 2).
|
||||
PQ_BONUS_EXP_RATE: 0.5 #Rate for the PQ exp reward.
|
||||
|
||||
EXP_SPLIT_LEVEL_INTERVAL: 5 #Non-contributing players must be within N level between the mob to receive EXP.
|
||||
EXP_SPLIT_LEECH_INTERVAL: 5 #Non-contributing players must be within N level between any contributing party member to receive EXP.
|
||||
EXP_SPLIT_MVP_MOD: 0.2
|
||||
EXP_SPLIT_COMMON_MOD: 0.8
|
||||
PARTY_BONUS_EXP_RATE: 1.0 #Rate for the party exp bonus reward.
|
||||
|
||||
#Miscellaneous Configuration
|
||||
TIMEZONE: GMT
|
||||
CHARSET: US-ASCII # Is loaded first, so applies to the rest of this config. Defaults to US-ASCII if invalid or not set.
|
||||
USE_DISPLAY_NUMBERS_WITH_COMMA: true #Enforce comma on displayed strings (use this when USE_UNITPRICE_WITH_COMMA is active and you still want to display comma-separated values).
|
||||
USE_UNITPRICE_WITH_COMMA: true #Set this accordingly with the layout of the unitPrices on Item.wz XML's, whether it's using commas or dots to represent fractions.
|
||||
MAX_MONITORED_BUFFSTATS: 5 #Limits accounting for "dormant" buff effects, that should take place when stronger stat buffs expires.
|
||||
MAX_AP: 32767 #Max AP allotted on the auto-assigner.
|
||||
MAX_EVENT_LEVELS: 8 #Event has different levels of rewarding system.
|
||||
BLOCK_NPC_RACE_CONDT: 500 # (0.5 * 1000) Time the player client must wait before reopening a conversation with an NPC.
|
||||
TOT_MOB_QUEST_REQUIREMENT: 0 #Overwrites old 999-mobs requirement for the ToT questline with new requirement value, set 0 for default.
|
||||
MOB_REACTOR_REFRESH_TIME: 0 # (30 * 1000) Overwrites refresh time for those reactors oriented to inflict damage to bosses (Ice Queen, Riche), set 0 for default.
|
||||
PARTY_SEARCH_REENTRY_LIMIT: 10 #Max amount of times a party leader is allowed to persist on the Party Search before entry expiration (thus needing to manually restart the Party Search to be able to search for members).
|
||||
NAME_CHANGE_COOLDOWN: 2592000000 # (30*24*60*60*1000) Cooldown for name changes, default (GMS) is 30 days.
|
||||
WORLD_TRANSFER_COOLDOWN: 2592000000 # (30*24*60*60*1000) Cooldown for world tranfers, default is same as name change (30 days).
|
||||
INSTANT_NAME_CHANGE: false #Whether or not to wait for server restart to apply name changes. Does on reconnect otherwise (requires queries on every login).
|
||||
REBIRTH_NPC_ID: 9010021 #ID of the NPC that should be replaced with the rebirth mechanic, if enabled.
|
||||
|
||||
#Dangling Items/Locks Configuration
|
||||
ITEM_EXPIRE_TIME: 180000 # (3 * 60 * 1000) Time before items start disappearing. Recommended to be set up to 3 minutes.
|
||||
KITE_EXPIRE_TIME: 3600000 # (60 * 60 * 1000) Time before kites (cash item) disappears.
|
||||
ITEM_MONITOR_TIME: 300000 # (5 * 60 * 1000) Interval between item monitoring tasks on maps, which checks for dangling (null) item objects on the map item history.
|
||||
LOCK_MONITOR_TIME: 30000 # (30 * 1000) Waiting time for a lock to be released. If it reaches timeout, a critical server deadlock has made present.
|
||||
|
||||
#Map Monitor Configuration
|
||||
ITEM_EXPIRE_CHECK: 10000 # (10 * 10000) Interval between item expiring tasks on maps, which checks and makes disappear expired items.
|
||||
ITEM_LIMIT_ON_MAP: 200 #Max number of items allowed on a map.
|
||||
MAP_VISITED_SIZE: 5 #Max length for last mapids visited by a player. This is used to recover and update drops on these maps accordingly with player actions.
|
||||
MAP_DAMAGE_OVERTIME_INTERVAL: 2500 #Interval in milliseconds between map environment damage (e.g. El Nath and Aqua Road surrondings).
|
||||
MAP_DAMAGE_OVERTIME_COUNT: 2
|
||||
|
||||
#Channel Mob Disease Monitor Configuration
|
||||
MOB_STATUS_MONITOR_PROC: 200 #Frequency in milliseconds between each proc on the mob disease monitor schedule.
|
||||
MOB_STATUS_MONITOR_LIFE: 84 #Idle proc count the mob disease monitor is allowed to be there before closing it due to inactivity.
|
||||
MOB_STATUS_AGGRO_PERSISTENCE: 2 #Idle proc count on aggro update for a mob to keep following the current controller, given him/her is the leading damage dealer.
|
||||
MOB_STATUS_AGGRO_INTERVAL: 5000 #Interval in milliseconds between aggro logistics update.
|
||||
USE_AUTOAGGRO_NEARBY: false #Mobs start following the player when approached.
|
||||
|
||||
#Some Gameplay Enhancing Configurations
|
||||
#Scroll Configuration
|
||||
USE_PERFECT_GM_SCROLL: true #Scrolls from GMs never uses up slots nor fails.
|
||||
USE_PERFECT_SCROLLING: false #Scrolls doesn't use slots upon failure.
|
||||
USE_ENHANCED_CHSCROLL: false #Equips even more powerful with chaos upgrade.
|
||||
USE_ENHANCED_CRAFTING: false #Apply chaos scroll on every equip crafted.
|
||||
USE_ENHANCED_CLNSLATE: false #Clean slates can be applied to recover successfully used slots as well.
|
||||
SCROLL_CHANCE_ROLLS: 1 #Number of rolls for success on a scroll, set 1 for default.
|
||||
CHSCROLL_STAT_RATE: 1 #Number of rolls of stat upgrade on a successfully applied chaos scroll, set 1 for default.
|
||||
CHSCROLL_STAT_RANGE: 6 #Stat upgrade range (-N, N) on chaos scrolls.
|
||||
|
||||
#Beginner Skills Configuration
|
||||
USE_ULTRA_NIMBLE_FEET: false #Massive speed & jump upgrade.
|
||||
USE_ULTRA_RECOVERY: false #Massive recovery amounts overtime.
|
||||
USE_ULTRA_THREE_SNAILS: false #Massive damage on shell toss.
|
||||
|
||||
#Other Skills Configuration
|
||||
USE_FULL_ARAN_SKILLSET: false #Enables starter availability to all Aran job skills. Suggestion thanks to Masterrulax.
|
||||
USE_FAST_REUSE_HERO_WILL: false #Greatly reduce cooldown on Hero's Will.
|
||||
USE_ANTI_IMMUNITY_CRASH: false #Crash skills additionally removes the mob's invincibility buffs. Suggestion thanks to Celestial.
|
||||
USE_UNDISPEL_HOLY_SHIELD: false #Holy shield buff also prevents players from suffering dispel from mobs.
|
||||
USE_FULL_HOLY_SYMBOL: false #Holy symbol doesn't require EXP sharers to work in full.
|
||||
|
||||
#Character Configuration
|
||||
USE_ADD_SLOTS_BY_LEVEL: false #Slots are added each 20 levels.
|
||||
USE_ADD_RATES_BY_LEVEL: false #Rates are added each 20 levels.
|
||||
USE_STACK_COUPON_RATES: false #Multiple coupons effects builds up together.
|
||||
USE_PERFECT_PITCH: false #For lvl 30 or above, each lvlup grants player 1 perfect pitch.
|
||||
|
||||
#Quest Configuration
|
||||
USE_QUEST_RATE: false #Exp/Meso gained by quests uses fixed server exp/meso rate times quest rate as multiplier, instead of player rates.
|
||||
|
||||
#Quest Points Configuration
|
||||
QUEST_POINT_REPEATABLE_INTERVAL: 25 #Minimum interval between repeatable quest completions for quest points to be awarded.
|
||||
QUEST_POINT_REQUIREMENT: 0 #Exchange factor between N quest points to +1 fame, set 0 to disable the entire quest point mechanism.
|
||||
QUEST_POINT_PER_QUEST_COMPLETE: 0 #Each completed quest awards N quest points, set 0 to disable.
|
||||
QUEST_POINT_PER_EVENT_CLEAR: 0 #Each completed event instance awards N quest points, set 0 to disable.
|
||||
|
||||
#Guild Configuration
|
||||
CREATE_GUILD_MIN_PARTNERS: 6 #Minimum number of members on Guild Headquarters to establish a new guild.
|
||||
CREATE_GUILD_COST: 1500000
|
||||
CHANGE_EMBLEM_COST: 5000000
|
||||
EXPAND_GUILD_BASE_COST: 500000
|
||||
EXPAND_GUILD_TIER_COST: 1000000
|
||||
EXPAND_GUILD_MAX_COST: 5000000
|
||||
|
||||
#Family Configuration
|
||||
FAMILY_REP_PER_KILL: 4 #Amount of rep gained per monster kill.
|
||||
FAMILY_REP_PER_BOSS_KILL: 20 #Amount of rep gained per boss kill.
|
||||
FAMILY_REP_PER_LEVELUP: 200 #Amount of rep gained upon leveling up.
|
||||
FAMILY_MAX_GENERATIONS: 1000 #Maximum depth of family tree. (Distance from leader to farthest junior)
|
||||
|
||||
#Equipment Configuration
|
||||
USE_EQUIPMNT_LVLUP_SLOTS: false #Equips can upgrade slots at level up.
|
||||
USE_EQUIPMNT_LVLUP_POWER: false #Enable more powerful stat upgrades at equip level up.
|
||||
USE_EQUIPMNT_LVLUP_CASH: false #Enable equip leveling up on cash equipments as well.
|
||||
USE_SPIKES_AVOID_BANISH: false #Shoes equipped with spikes prevents mobs from banishing wearer.
|
||||
MAX_EQUIPMNT_LVLUP_STAT_UP: 10000 #Max stat upgrade an equipment can have on a levelup.
|
||||
MAX_EQUIPMNT_STAT: 32767 #Max stat on an equipment by leveling up.
|
||||
USE_EQUIPMNT_LVLUP: 1 #All equips lvlup at max level of N, set 1 to disable.
|
||||
|
||||
#Map-Chair Configuration
|
||||
USE_CHAIR_EXTRAHEAL: false #Enable map chairs to further recover player's HP and MP (player must have the Chair Mastery skill).
|
||||
CHAIR_EXTRA_HEAL_MULTIPLIER: 10 #Due to only being able to be send up-to-255 heal values, values being actually updated is the one displayed times this.
|
||||
CHAIR_EXTRA_HEAL_MAX_DELAY: 21 #Players are expected to recover fully after using this skill for N seconds.
|
||||
|
||||
#Player NPC Configuration
|
||||
PLAYERNPC_INITIAL_X: 262 #Map frame width for putting PlayerNPCs.
|
||||
PLAYERNPC_INITIAL_Y: 262 #Map frame height for putting PlayerNPCs.
|
||||
PLAYERNPC_AREA_X: 320 #Initial width gap between PlayerNPCs.
|
||||
PLAYERNPC_AREA_Y: 160 #Initial height gap between PlayerNPCs.
|
||||
PLAYERNPC_AREA_STEPS: 4 #Max number of times gap is shortened to comport PlayerNPCs.
|
||||
PLAYERNPC_ORGANIZE_AREA: true #Automatically rearranges PlayerNPCs on the map if there is no space set the new NPC. Current distance gap between NPCs is decreased to solve this issue.
|
||||
PLAYERNPC_AUTODEPLOY: true #Makes PlayerNPC automatically deployed on the Hall of Fame at the instant one reaches max level. If false, eligible players must talk to 1st job instructor to deploy a NPC.
|
||||
|
||||
#Pet Auto-Pot Configuration
|
||||
USE_COMPULSORY_AUTOPOT: true #Pets will consume as many potions as needed to fulfill the AUTOHP/MP ratio threshold.
|
||||
USE_EQUIPS_ON_AUTOPOT: true #Player MaxHP and MaxMP check values on autopot handler will be updated by the HP/MP bonuses on equipped items.
|
||||
PET_AUTOHP_RATIO: 0.99 #Will automatically consume potions until given ratio of the MaxHP/MaxMP is reached.
|
||||
PET_AUTOMP_RATIO: 0.99
|
||||
|
||||
#Pet & Mount Configuration
|
||||
PET_EXHAUST_COUNT: 3 #Number of proc counts (1 per minute) on the exhaust schedule for fullness.
|
||||
MOUNT_EXHAUST_COUNT: 1 #Number of proc counts (1 per minute) on the exhaust schedule for tiredness.
|
||||
|
||||
#Pet Hunger Configuration
|
||||
PETS_NEVER_HUNGRY: false #If true, pets and mounts will never grow hungry.
|
||||
GM_PETS_NEVER_HUNGRY: true #If true, pets and mounts owned by GMs will never grow hungry.
|
||||
|
||||
#Event Configuration
|
||||
EVENT_MAX_GUILD_QUEUE: 10 #Max number of guilds in queue for GPQ.
|
||||
EVENT_LOBBY_DELAY: 10 #Cooldown duration in seconds before reopening an event lobby.
|
||||
|
||||
#Dojo Configuration
|
||||
USE_FAST_DOJO_UPGRADE: false #Reduced Dojo training points amount required for a belt upgrade.
|
||||
USE_DEADLY_DOJO: true #Should bosses really use 1HP,1MP attacks in dojo?
|
||||
DOJO_ENERGY_ATK: 100 #Dojo energy gain when deal attack
|
||||
DOJO_ENERGY_DMG: 20 #Dojo energy gain when recv attack
|
||||
|
||||
#Wedding Configuration
|
||||
WEDDING_RESERVATION_DELAY: 3 #Minimum idle slots before processing a wedding reservation.
|
||||
WEDDING_RESERVATION_TIMEOUT: 10 #Limit time in minutes for the couple to show up before cancelling the wedding reservation.
|
||||
WEDDING_RESERVATION_INTERVAL: 60 #Time between wedding starts in minutes.
|
||||
WEDDING_BLESS_EXP: 30000 #Exp gained per bless count.
|
||||
WEDDING_GIFT_LIMIT: 1 #Max number of gifts per person to same wishlist on marriage instances.
|
||||
WEDDING_BLESSER_SHOWFX: true #Pops bubble sprite effect on players blessing the couple. Setting this false shows the blessing effect on the couple instead.
|
||||
|
||||
#Buyback Configuration
|
||||
USE_BUYBACK_WITH_MESOS: true #Enables usage of either mesos or NX for the buyback fee.
|
||||
BUYBACK_FEE: 77.70 #Sets the base amount needed to buyback (level 30 or under will use the base value).
|
||||
BUYBACK_LEVEL_STACK_FEE: 85.47 #Sets the level-stacking portion of the amount needed to buyback (fee will sum up linearly until level 120, when it reaches the peak).
|
||||
BUYBACK_MESO_MULTIPLIER: 1000 #Sets a multiplier for the fee when using meso as the charge unit.
|
||||
BUYBACK_RETURN_MINUTES: 1 #Sets the maximum amount of time the player can wait before decide to buyback.
|
||||
BUYBACK_COOLDOWN_MINUTES: 7 #Sets the time the player must wait before using buyback again.
|
||||
|
||||
# Login timeout by shavit
|
||||
TIMEOUT_DURATION: 3600000 # Kicks clients who don't send any packet to the game server in due time (in millisseconds).
|
||||
|
||||
#Event End Timestamp
|
||||
EVENT_END_TIMESTAMP: 1428897600000
|
||||
|
||||
# GM Security Configuration
|
||||
MINIMUM_GM_LEVEL_TO_TRADE: 4
|
||||
MINIMUM_GM_LEVEL_TO_USE_STORAGE: 4
|
||||
MINIMUM_GM_LEVEL_TO_USE_DUEY: 4
|
||||
MINIMUM_GM_LEVEL_TO_DROP: 4
|
||||
|
||||
#Any NPC ids that should search for a js override script (useful if they already have wz entries since otherwise they're ignored).
|
||||
NPCS_SCRIPTABLE:
|
||||
#9200000: Talk to Cody # Cody
|
||||
9001105: Rescue Gaga! # Grandpa moon bunny
|
||||
@@ -1,6 +0,0 @@
|
||||
HOST=127.0.0.1
|
||||
URL=jdbc:mysql://localhost:3306/heavenms
|
||||
DB_USER=root
|
||||
DB_PASS=
|
||||
JAVA8=FALSE
|
||||
SHUTDOWNHOOK=true
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
3
database/docker-db-data/.gitignore
vendored
Normal file
3
database/docker-db-data/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
*
|
||||
*/
|
||||
!.gitignore
|
||||
21502
database/sql/1-db_database.sql
Normal file
21502
database/sql/1-db_database.sql
Normal file
File diff suppressed because it is too large
Load Diff
24539
database/sql/2-db_drops.sql
Normal file
24539
database/sql/2-db_drops.sql
Normal file
File diff suppressed because it is too large
Load Diff
351
database/sql/3-db_shopupdate.sql
Normal file
351
database/sql/3-db_shopupdate.sql
Normal file
@@ -0,0 +1,351 @@
|
||||
#THIS SQL IS OPTIONAL, TO BE USED AFTER 'db_drops.sql'
|
||||
#THIS REQUIRES PROVIDED WZ FILES
|
||||
|
||||
USE `cosmic`;
|
||||
|
||||
# Scroll shop at Asia, chair shop at Kino Konoko, potion shop at T-1337
|
||||
INSERT INTO `shops` (`shopid`,`npcid`) VALUES
|
||||
(2082014,2082014),
|
||||
(9110002,9110002),
|
||||
(9201101,9201101);
|
||||
|
||||
INSERT IGNORE INTO `shopitems` (`shopid`, `itemid`, `price`, `pitch`, `position`) VALUES
|
||||
(2082014, 2040004, 480000, 0, 1),
|
||||
(2082014, 2040025, 500000, 0, 2),
|
||||
(2082014, 2040029, 500000, 0, 3),
|
||||
(2082014, 2040017, 500000, 0, 4),
|
||||
(2082014, 2040301, 400000, 0, 5),
|
||||
(2082014, 2040317, 400000, 0, 6),
|
||||
(2082014, 2040321, 400000, 0, 7),
|
||||
(2082014, 2040413, 400000, 0, 8),
|
||||
(2082014, 2040418, 400000, 0, 9),
|
||||
(2082014, 2040501, 250000, 0, 10),
|
||||
(2082014, 2040513, 250000, 0, 11),
|
||||
(2082014, 2040516, 250000, 0, 12),
|
||||
(2082014, 2040532, 250000, 0, 13),
|
||||
(2082014, 2040613, 400000, 0, 14),
|
||||
(2082014, 2040701, 450000, 0, 15),
|
||||
(2082014, 2040704, 450000, 0, 16),
|
||||
(2082014, 2040707, 450000, 0, 17),
|
||||
(2082014, 2040804, 550000, 0, 18),
|
||||
(2082014, 2040817, 550000, 0, 19),
|
||||
(2082014, 2040914, 480000, 0, 20),
|
||||
(2082014, 2040919, 480000, 0, 21),
|
||||
(2082014, 2041007, 470000, 0, 22),
|
||||
(2082014, 2041010, 470000, 0, 23),
|
||||
(2082014, 2041013, 500000, 0, 24),
|
||||
(2082014, 2041016, 500000, 0, 25),
|
||||
(2082014, 2041019, 500000, 0, 26),
|
||||
(2082014, 2041022, 500000, 0, 27),
|
||||
(2082014, 2044901, 520000, 0, 28),
|
||||
(2082014, 2044701, 520000, 0, 29),
|
||||
(2082014, 2043001, 520000, 0, 30),
|
||||
(2082014, 2043801, 520000, 0, 31),
|
||||
(2082014, 2044601, 520000, 0, 32),
|
||||
(2082014, 2040727, 50000, 0, 33),
|
||||
(2082014, 2041058, 50000, 0, 34),
|
||||
(2082014, 2040807, 1000000, 0, 35),
|
||||
(2082014, 2040005, 22000, 0, 36),
|
||||
(2082014, 2040026, 23000, 0, 37),
|
||||
(2082014, 2040031, 23000, 0, 38),
|
||||
(2082014, 2040016, 23000, 0, 39),
|
||||
(2082014, 2040302, 25000, 0, 40),
|
||||
(2082014, 2040318, 25000, 0, 41),
|
||||
(2082014, 2040323, 25000, 0, 42),
|
||||
(2082014, 2040412, 20000, 0, 43),
|
||||
(2082014, 2040419, 20000, 0, 44),
|
||||
(2082014, 2040502, 25000, 0, 45),
|
||||
(2082014, 2040514, 25000, 0, 46),
|
||||
(2082014, 2040517, 25000, 0, 47),
|
||||
(2082014, 2040534, 25000, 0, 48),
|
||||
(2082014, 2040612, 20000, 0, 49),
|
||||
(2082014, 2040702, 20000, 0, 50),
|
||||
(2082014, 2040705, 25000, 0, 51),
|
||||
(2082014, 2040708, 20000, 0, 52),
|
||||
(2082014, 2040805, 100000, 0, 53),
|
||||
(2082014, 2040816, 100000, 0, 54),
|
||||
(2082014, 2040915, 55000, 0, 55),
|
||||
(2082014, 2040920, 55000, 0, 56),
|
||||
(2082014, 2041008, 38000, 0, 57),
|
||||
(2082014, 2041011, 38000, 0, 58),
|
||||
(2082014, 2041014, 40000, 0, 59),
|
||||
(2082014, 2041017, 40000, 0, 60),
|
||||
(2082014, 2041020, 40000, 0, 61),
|
||||
(2082014, 2041023, 40000, 0, 62),
|
||||
(2082014, 2044902, 50000, 0, 63),
|
||||
(2082014, 2044702, 50000, 0, 64),
|
||||
(2082014, 2043002, 50000, 0, 65),
|
||||
(2082014, 2043802, 50000, 0, 66),
|
||||
(2082014, 2044602, 50000, 0, 67),
|
||||
(2082014, 2049200, 170000, 0, 68),
|
||||
(2082014, 2049201, 220000, 0, 69),
|
||||
(2082014, 2049202, 170000, 0, 70),
|
||||
(2082014, 2049203, 220000, 0, 71),
|
||||
(2082014, 2049204, 170000, 0, 72),
|
||||
(2082014, 2049205, 220000, 0, 73),
|
||||
(2082014, 2049206, 170000, 0, 74),
|
||||
(2082014, 2049207, 220000, 0, 75),
|
||||
(2082014, 2049208, 140000, 0, 76),
|
||||
(2082014, 2049209, 170000, 0, 77),
|
||||
(2082014, 2049210, 140000, 0, 78),
|
||||
(2082014, 2049211, 170000, 0, 79),
|
||||
(2082014, 2040101, 540000, 0, 80),
|
||||
(2082014, 2040100, 700000, 0, 81),
|
||||
(2082014, 2040106, 540000, 0, 82),
|
||||
(2082014, 2040105, 700000, 0, 83),
|
||||
(2082014, 2040201, 540000, 0, 84),
|
||||
(2082014, 2040200, 700000, 0, 85),
|
||||
(2082014, 2040206, 540000, 0, 86),
|
||||
(2082014, 2040205, 700000, 0, 87),
|
||||
(2082014, 2070016, 120000000, 0, 88),
|
||||
(2082014, 2070018, 190000000, 0, 89),
|
||||
(2082014, 2030007, 1800000, 0, 90),
|
||||
(2082014, 4001017, 60000000, 0, 91);
|
||||
|
||||
UPDATE shopitems SET price = 11*price WHERE (`position` >= 33 and `position` <= 79 and `shopid` = 2082014);
|
||||
|
||||
INSERT IGNORE INTO `shopitems` (`shopid`, `itemid`, `price`, `pitch`, `position`) VALUES
|
||||
(1031100, 3010015, 20000, 0, 100),
|
||||
(9110002, 3010019, 7700000, 0, 92),
|
||||
(9110002, 3010008, 10000000, 0, 96),
|
||||
(9110002, 3010007, 10000000, 0, 100),
|
||||
(9201020, 3010009, 4200000, 0, 96),
|
||||
(9201020, 3010014, 7000000, 0, 100),
|
||||
(1081000, 3010013, 4000000, 0, 100),
|
||||
(9201101, 2022338, 2100000, 0, 100),
|
||||
(9201101, 2022339, 2800000, 0, 104),
|
||||
(9201101, 2022340, 4000000, 0, 108),
|
||||
(9201101, 2022341, 2800000, 0, 112),
|
||||
(9201101, 2022342, 2000000, 0, 116),
|
||||
(9201101, 2022343, 4700000, 0, 120),
|
||||
(9201101, 2022344, 5000000, 0, 124),
|
||||
(9201101, 2022345, 4000000, 0, 128),
|
||||
(9201101, 2002028, 5000000, 0, 132),
|
||||
(9201101, 2022544, 100000, 0, 136),
|
||||
(9201101, 2022545, 4400000, 0, 140),
|
||||
(9201101, 2020027, 2100000, 0, 144),
|
||||
(9201101, 2022113, 1800000, 0, 148),
|
||||
(9201101, 2022121, 12000000, 0, 152),
|
||||
(9201101, 2022123, 12000000, 0, 156),
|
||||
(9201101, 2022277, 5300000, 0, 160),
|
||||
(9201101, 2012008, 4200000, 0, 164),
|
||||
(9201101, 2022251, 3800000, 0, 168);
|
||||
|
||||
# adding antibanish scrolls
|
||||
INSERT IGNORE INTO `shopitems` (`shopid`, `itemid`, `price`, `pitch`, `position`) VALUES
|
||||
(1001100, 2030100, 450, 0, 130),
|
||||
(1011100, 2030100, 450, 0, 142),
|
||||
(1021100, 2030100, 450, 0, 142),
|
||||
(1031100, 2030100, 450, 0, 146),
|
||||
(1051002, 2030100, 450, 0, 142),
|
||||
(1052116, 2030100, 450, 0, 118),
|
||||
(1061001, 2030100, 450, 0, 126),
|
||||
(1061002, 2030100, 450, 0, 130),
|
||||
(1091002, 2030100, 450, 0, 130),
|
||||
(1100002, 2030100, 450, 0, 138),
|
||||
(2012005, 2030100, 450, 0, 126),
|
||||
(2022001, 2030100, 450, 0, 126),
|
||||
(2030009, 2030100, 450, 0, 126),
|
||||
(2040051, 2030100, 450, 0, 102),
|
||||
(2041006, 2030100, 450, 0, 134),
|
||||
(2051000, 2030100, 450, 0, 134),
|
||||
(2060004, 2030100, 450, 0, 134),
|
||||
(2070001, 2030100, 450, 0, 134),
|
||||
(2080001, 2030100, 450, 0, 134),
|
||||
(2090003, 2030100, 450, 0, 126),
|
||||
(2093002, 2030100, 450, 0, 126),
|
||||
(2100004, 2030100, 450, 0, 130),
|
||||
(2110001, 2030100, 450, 0, 130),
|
||||
(2130000, 2030100, 450, 0, 126),
|
||||
(9201060, 2030100, 450, 0, 114),
|
||||
(9270021, 2030100, 450, 0, 118),
|
||||
(9270022, 2030100, 450, 0, 114), -- Thanks Rednor for finding duplicate item on NPC
|
||||
(1338, 2030100, 450, 0, 114),
|
||||
(9270057, 2030100, 450, 0, 4),
|
||||
(9270065, 2030100, 450, 0, 3);
|
||||
|
||||
-- Thanks to Vcoc
|
||||
-- GMShop: Sacks, GmEquip, Cheese & Onyx, Utils,
|
||||
-- Arrows, Bullets, Throwings and Capsules,
|
||||
-- Others, Equips, Mounts, Scrolls.
|
||||
|
||||
DELETE FROM `shopitems` WHERE `shopid`=1337;
|
||||
INSERT INTO `shopitems` ( `shopid`, `itemid`, `price`, `position`) VALUES
|
||||
(1337, 2100036, 1, 1),
|
||||
(1337, 2100035, 1, 2),
|
||||
(1337, 2100034, 1, 3),
|
||||
(1337, 2100033, 1, 4),
|
||||
(1337, 2100007, 1, 5),
|
||||
(1337, 2100006, 1, 6),
|
||||
(1337, 2100005, 1, 7),
|
||||
(1337, 2100004, 1, 8),
|
||||
(1337, 2100003, 1, 9),
|
||||
(1337, 2100002, 1, 10),
|
||||
(1337, 2100001, 1, 11),
|
||||
(1337, 1002959, 1, 12),
|
||||
(1337, 1002140, 1, 13),
|
||||
(1337, 1042003, 1, 14),
|
||||
(1337, 1062007, 1, 15),
|
||||
(1337, 1322013, 1, 16),
|
||||
(1337, 1072010, 1, 17),
|
||||
(1337, 2022179, 1, 18),
|
||||
(1337, 2022273, 1, 19),
|
||||
(1337, 2041200, 1, 20),
|
||||
(1337, 4006001, 1, 21),
|
||||
(1337, 4001017, 1, 22),
|
||||
(1337, 4031179, 1, 23),
|
||||
(1337, 2070018, 1, 24),
|
||||
(1337, 2060004, 1, 25),
|
||||
(1337, 2061004, 1, 26),
|
||||
(1337, 2330005, 1, 27),
|
||||
(1337, 2332000, 1, 28),
|
||||
(1337, 2331000, 1, 29),
|
||||
(1337, 5072000, 1, 30),
|
||||
(1337, 5390000, 1, 31),
|
||||
(1337, 5390001, 1, 32),
|
||||
(1337, 5390002, 1, 33),
|
||||
(1337, 5390005, 1, 34),
|
||||
(1337, 5390006, 1, 35),
|
||||
(1337, 1492013, 1, 36),
|
||||
(1337, 1482013, 1, 37),
|
||||
(1337, 1452044, 1, 38),
|
||||
(1337, 1472052, 1, 39),
|
||||
(1337, 1462039, 1, 40),
|
||||
(1337, 1332050, 1, 41),
|
||||
(1337, 1312031, 1, 42),
|
||||
(1337, 1322052, 1, 43),
|
||||
(1337, 1302059, 1, 44),
|
||||
(1337, 1442045, 1, 45),
|
||||
(1337, 1432038, 1, 46),
|
||||
(1337, 1382036, 1, 47),
|
||||
(1337, 1412026, 1, 48),
|
||||
(1337, 1422028, 1, 49),
|
||||
(1337, 1402036, 1, 50),
|
||||
(1337, 1372032, 1, 51),
|
||||
(1337, 1122000, 1, 52),
|
||||
(1337, 1082149, 1, 53),
|
||||
(1337, 1912000, 1, 54),
|
||||
(1337, 1902000, 1, 55),
|
||||
(1337, 1902001, 1, 56),
|
||||
(1337, 1902002, 1, 57),
|
||||
(1337, 1912005, 1, 58),
|
||||
(1337, 1902005, 1, 59),
|
||||
(1337, 1902006, 1, 60),
|
||||
(1337, 1902007, 1, 61),
|
||||
(1337, 1912011, 1, 62),
|
||||
(1337, 1902015, 1, 63),
|
||||
(1337, 1902016, 1, 64),
|
||||
(1337, 1902017, 1, 65),
|
||||
(1337, 1902018, 1, 66),
|
||||
(1337, 2044908, 1, 67),
|
||||
(1337, 2044815, 1, 68),
|
||||
(1337, 2044512, 1, 69),
|
||||
(1337, 2044712, 1, 70),
|
||||
(1337, 2044612, 1, 71),
|
||||
(1337, 2043312, 1, 72),
|
||||
(1337, 2043117, 1, 73),
|
||||
(1337, 2043217, 1, 74),
|
||||
(1337, 2043023, 1, 75),
|
||||
(1337, 2044417, 1, 76),
|
||||
(1337, 2044317, 1, 77),
|
||||
(1337, 2043812, 1, 78),
|
||||
(1337, 2044117, 1, 79),
|
||||
(1337, 2044217, 1, 80),
|
||||
(1337, 2044025, 1, 81),
|
||||
(1337, 2043712, 1, 82),
|
||||
(1337, 2340000, 1, 83),
|
||||
(1337, 2040807, 1, 84),
|
||||
(1337, 2210032, 1, 85),
|
||||
(1337, 2050004, 1, 86);
|
||||
|
||||
-- Thanks to DietStory v1.02 dev team
|
||||
INSERT INTO `shopitems` ( `shopid`, `itemid`, `price`, `pitch`, `position`) VALUES
|
||||
(1200001, 3010001, 1000, 0, 1),
|
||||
(1200001, 1092003, 2000, 0, 2),
|
||||
(1200001, 1072063, 10000, 0, 3),
|
||||
(1200001, 1072062, 10000, 0, 4),
|
||||
(1200001, 1072017, 10000, 0, 5),
|
||||
(1200001, 1072049, 5000, 0, 6),
|
||||
(1200001, 1072048, 5000, 0, 7),
|
||||
(1200001, 1072008, 5000, 0, 8),
|
||||
(1200001, 1072005, 50, 0, 9),
|
||||
(1200001, 1072038, 50, 0, 10),
|
||||
(1200001, 1072037, 50, 0, 11),
|
||||
(1200001, 1072001, 50, 0, 12),
|
||||
(1200001, 1062001, 4800, 0, 13),
|
||||
(1200001, 1062000, 4800, 0, 14),
|
||||
(1200001, 1060004, 2800, 0, 15),
|
||||
(1200001, 1060007, 1000, 0, 16),
|
||||
(1200001, 1041012, 3000, 0, 17),
|
||||
(1200001, 1041004, 3000, 0, 18),
|
||||
(1200001, 1040014, 3000, 0, 19),
|
||||
(1200001, 1040013, 3000, 0, 20),
|
||||
(1200001, 1002001, 3000, 0, 21),
|
||||
(1200001, 1002019, 2000, 0, 22),
|
||||
(1200001, 1002134, 800, 0, 23),
|
||||
(1200001, 1002133, 800, 0, 24),
|
||||
(1200001, 1002132, 800, 0, 25),
|
||||
(1200001, 1002069, 450, 0, 26),
|
||||
(1200001, 1002068, 450, 0, 27),
|
||||
(1200001, 1002067, 450, 0, 28),
|
||||
(1200001, 1002066, 450, 0, 29),
|
||||
(1200001, 1002014, 1000, 0, 30),
|
||||
(1200001, 1002008, 500, 0, 31),
|
||||
(1200001, 1332007, 1000, 0, 32),
|
||||
(1200001, 1312000, 3000, 0, 33),
|
||||
(1200001, 1302007, 3000, 0, 34),
|
||||
(1200001, 1322005, 50, 0, 35),
|
||||
(1200001, 1312004, 50, 0, 36),
|
||||
(1200001, 1302000, 50, 0, 37),
|
||||
(1200002, 2330000, 600, 0, 104),
|
||||
(1200002, 2070000, 500, 0, 108),
|
||||
(1200002, 2061000, 1, 0, 120),
|
||||
(1200002, 2060000, 1, 0, 124),
|
||||
(1200002, 2030100, 400, 0, 128),
|
||||
(1200002, 2030000, 400, 0, 132),
|
||||
(1200002, 2020028, 3000, 0, 136),
|
||||
(1200002, 2010004, 310, 0, 140),
|
||||
(1200002, 2010003, 100, 0, 144),
|
||||
(1200002, 2010001, 106, 0, 148),
|
||||
(1200002, 2010002, 50, 0, 152),
|
||||
(1200002, 2010000, 30, 0, 156),
|
||||
(1200002, 2002005, 500, 0, 160),
|
||||
(1200002, 2002004, 500, 0, 164),
|
||||
(1200002, 2002002, 500, 0, 168),
|
||||
(1200002, 2002001, 400, 0, 172),
|
||||
(1200002, 2002000, 500, 0, 176),
|
||||
(1200002, 2000006, 620, 0, 180),
|
||||
(1200002, 2000003, 200, 0, 184),
|
||||
(1200002, 2000002, 320, 0, 188),
|
||||
(1200002, 2000001, 160, 0, 192),
|
||||
(1200002, 2000000, 50, 0, 196),
|
||||
(1301000, 2330000, 600, 0, 104),
|
||||
(1301000, 2070000, 500, 0, 108),
|
||||
(1301000, 2061000, 1, 0, 112),
|
||||
(1301000, 2060000, 1, 0, 116),
|
||||
(1301000, 2030100, 400, 0, 120),
|
||||
(1301000, 2030000, 400, 0, 124),
|
||||
(1301000, 2022000, 1650, 0, 128),
|
||||
(1301000, 2022003, 1100, 0, 132),
|
||||
(1301000, 2002005, 500, 0, 136),
|
||||
(1301000, 2002004, 500, 0, 140),
|
||||
(1301000, 2002002, 500, 0, 144),
|
||||
(1301000, 2002001, 400, 0, 148),
|
||||
(1301000, 2002000, 500, 0, 152),
|
||||
(1301000, 2000006, 620, 0, 156),
|
||||
(1301000, 2000003, 200, 0, 160),
|
||||
(1301000, 2000002, 320, 0, 164),
|
||||
(1301000, 2000001, 160, 0, 168),
|
||||
(1301000, 2000000, 50, 0, 172);
|
||||
|
||||
# adding missing pirate items at Singapore npc's
|
||||
INSERT INTO `shopitems` ( `shopid`, `itemid`, `price`, `pitch`, `position`) VALUES
|
||||
(9270019, 1492006, 160000, 0, 80),
|
||||
(9270019, 1492005, 100000, 0, 84),
|
||||
(9270019, 1492004, 75000, 0, 88),
|
||||
(9270019, 1482006, 150000, 0, 92),
|
||||
(9270019, 1482005, 100000, 0, 96),
|
||||
(9270019, 1482004, 75000, 0, 100),
|
||||
(9270020, 1052113, 120000, 0, 92),
|
||||
(9270020, 1052110, 100000, 0, 96),
|
||||
(9270020, 1002625, 75000, 0, 100);
|
||||
87
database/sql/4-db-admin.sql
Normal file
87
database/sql/4-db-admin.sql
Normal file
@@ -0,0 +1,87 @@
|
||||
-- MySQL dump 10.13 Distrib 8.0.22, for Win64 (x86_64)
|
||||
--
|
||||
-- Host: 127.0.0.1 Database: cosmic
|
||||
-- ------------------------------------------------------
|
||||
-- Server version 8.0.19
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
|
||||
/*!50503 SET NAMES utf8 */;
|
||||
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
|
||||
/*!40103 SET TIME_ZONE='+00:00' */;
|
||||
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
|
||||
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
|
||||
|
||||
USE `cosmic`;
|
||||
|
||||
--
|
||||
-- Dumping data for table `accounts`
|
||||
--
|
||||
|
||||
LOCK TABLES `accounts` WRITE;
|
||||
/*!40000 ALTER TABLE `accounts` DISABLE KEYS */;
|
||||
INSERT INTO `accounts` VALUES (1,'admin','$2y$12$aFD9BDeUocDMY1X4tDYDyeJw/HhkQwCQWs3KAY7gCaRG0cpqJcaL.','0000','000000',0,'2021-05-24 00:00:01','2021-05-24 00:00:02','2005-05-11',0,NULL,NULL,1000000,1000000,1000000,3,0,'2005-05-11 03:00:00',0,1,NULL,0,NULL,0,NULL,NULL,0,0,'1234-5678',2);
|
||||
/*!40000 ALTER TABLE `accounts` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Dumping data for table `characters`
|
||||
--
|
||||
|
||||
LOCK TABLES `characters` WRITE;
|
||||
/*!40000 ALTER TABLE `characters` DISABLE KEYS */;
|
||||
INSERT INTO `characters` VALUES (1,1,0,'Admin',1,0,0,12,5,4,4,50,5,50,5,0,0,0,0,0,0,0,30030,20000,0,'0,0,0,0,0,0,0,0,0,0',10000,2,6,-1,25,'2021-05-24 00:00:03',1,0,1,0,0,5,0,4,1,0,0,0,0,0,0,0,0,0,0,24,24,24,24,-1,0,5,0,0,0,0,0,0,0,0,0,0,0,'','2021-05-24 00:00:04','2015-01-01 05:00:00',1,0);
|
||||
/*!40000 ALTER TABLE `characters` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Dumping data for table `inventoryequipment`
|
||||
--
|
||||
|
||||
LOCK TABLES `inventoryequipment` WRITE;
|
||||
/*!40000 ALTER TABLE `inventoryequipment` DISABLE KEYS */;
|
||||
INSERT INTO `inventoryequipment` VALUES (17,22,7,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,0,1,0,-1),(18,23,7,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,0,-1),(19,24,5,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,1,0,-1),(20,25,7,0,0,0,0,0,0,0,17,0,0,0,0,0,0,0,0,0,0,1,0,-1);
|
||||
/*!40000 ALTER TABLE `inventoryequipment` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Dumping data for table `inventoryitems`
|
||||
--
|
||||
|
||||
LOCK TABLES `inventoryitems` WRITE;
|
||||
/*!40000 ALTER TABLE `inventoryitems` DISABLE KEYS */;
|
||||
INSERT INTO `inventoryitems` VALUES (21,1,1,NULL,4161001,4,1,1,'',-1,0,-1,''),(22,1,1,NULL,1040002,-1,-5,1,'',-1,0,-1,''),(23,1,1,NULL,1060002,-1,-6,1,'',-1,0,-1,''),(24,1,1,NULL,1072001,-1,-7,1,'',-1,0,-1,''),(25,1,1,NULL,1302000,-1,-11,1,'',-1,0,-1,'');
|
||||
/*!40000 ALTER TABLE `inventoryitems` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Dumping data for table `keymap`
|
||||
--
|
||||
|
||||
LOCK TABLES `keymap` WRITE;
|
||||
/*!40000 ALTER TABLE `keymap` DISABLE KEYS */;
|
||||
INSERT INTO `keymap` VALUES (161,1,18,4,0),(162,1,65,6,106),(163,1,2,4,10),(164,1,23,4,1),(165,1,3,4,12),(166,1,4,4,13),(167,1,5,4,18),(168,1,6,4,24),(169,1,16,4,8),(170,1,17,4,5),(171,1,19,4,4),(172,1,25,4,19),(173,1,26,4,14),(174,1,27,4,15),(175,1,31,4,2),(176,1,34,4,17),(177,1,35,4,11),(178,1,37,4,3),(179,1,38,4,20),(180,1,40,4,16),(181,1,43,4,9),(182,1,44,5,50),(183,1,45,5,51),(184,1,46,4,6),(185,1,50,4,7),(186,1,56,5,53),(187,1,59,6,100),(188,1,60,6,101),(189,1,61,6,102),(190,1,62,6,103),(191,1,63,6,104),(192,1,64,6,105),(193,1,57,5,54),(194,1,48,4,22),(195,1,29,5,52),(196,1,7,4,21),(197,1,24,4,25),(198,1,33,4,26),(199,1,41,4,23),(200,1,39,4,27);
|
||||
/*!40000 ALTER TABLE `keymap` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--
|
||||
-- Dumping data for table `storages`
|
||||
--
|
||||
|
||||
LOCK TABLES `storages` WRITE;
|
||||
/*!40000 ALTER TABLE `storages` DISABLE KEYS */;
|
||||
INSERT INTO `storages` VALUES (1,1,0,4,0);
|
||||
/*!40000 ALTER TABLE `storages` ENABLE KEYS */;
|
||||
UNLOCK TABLES;
|
||||
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
|
||||
|
||||
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
|
||||
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||
6
database/sql/migration/monsterbook.sql
Normal file
6
database/sql/migration/monsterbook.sql
Normal file
@@ -0,0 +1,6 @@
|
||||
/* Manually run this script in MySQL Workbench or some other database client
|
||||
to migrate your old (pre Jan 19th 2022) monsterbook table to the new version */
|
||||
ALTER TABLE cosmic.`monsterbook`
|
||||
CHANGE COLUMN `charid` `charid` INT(11) NOT NULL,
|
||||
ADD PRIMARY KEY (`charid`, `cardid`),
|
||||
ADD CONSTRAINT `FK_monsterbook_1` FOREIGN KEY (`charid`) REFERENCES `characters` (`id`) ON UPDATE CASCADE ON DELETE CASCADE;
|
||||
7
database/sql/readme.txt
Normal file
7
database/sql/readme.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
---- Cosmic MySQL Database ----
|
||||
|
||||
These SQL files must be executed IN ORDER to set up the database:
|
||||
- 1-db_database.sql (Tables and some data)
|
||||
- 2-db_drops.sql (Remaining data: monster drops, reactor drops)
|
||||
- 3-db_shopupdate.sql (Custom shops - optional, requires provided WZs)
|
||||
- 4-db_admin (Basic admin account - optional)
|
||||
34
docker-compose.yml
Normal file
34
docker-compose.yml
Normal file
@@ -0,0 +1,34 @@
|
||||
version: '3'
|
||||
services:
|
||||
maplestory:
|
||||
build: .
|
||||
depends_on:
|
||||
- db
|
||||
ports:
|
||||
# Login server
|
||||
- "8484:8484"
|
||||
# Channels.
|
||||
# Format: WWCC, where WW is 75 plus the world number and CC is 75 plus the channel number (both zero indexed).
|
||||
# In this case, world 1 channels 1-3.
|
||||
- "7575-7577:7575-7577"
|
||||
volumes:
|
||||
# Config changes can be reloaded without rebuilding the image.
|
||||
# Still requires a redeployment as they're sourced on startup.
|
||||
- ./config.yaml:/opt/server/config.yaml
|
||||
- ./scripts:/opt/server/scripts
|
||||
- ./wz:/opt/server/wz
|
||||
environment:
|
||||
DB_HOST: "db" ## Remember if this is present it will OVERRIDE the host in the config.yaml, if you put here anything other than db, you'll need to change the config.yaml jdbc string to port 3307, and not port 3306
|
||||
|
||||
db:
|
||||
image: mysql:8.0.23
|
||||
environment:
|
||||
MYSQL_RANDOM_ROOT_PASSWORD: "true"
|
||||
MYSQL_DATABASE: "cosmic"
|
||||
MYSQL_USER: "cosmic_server"
|
||||
MYSQL_PASSWORD: "snailshell"
|
||||
ports:
|
||||
- "3307:3306"
|
||||
volumes:
|
||||
- ./database/docker-db-data:/var/lib/mysql
|
||||
- ./database/sql:/docker-entrypoint-initdb.d
|
||||
@@ -1,34 +0,0 @@
|
||||
Changes from the original v83 WZs:
|
||||
|
||||
Character.wz/*:
|
||||
Upgraded info of some items.
|
||||
|
||||
Map.wz/MapX/*:
|
||||
Fixed entries of portals placed incorrectly.
|
||||
|
||||
Item.wz/*:
|
||||
Fixed lacking "slotMax" properties in some items.
|
||||
Set flag "Quest Item" for some items.
|
||||
|
||||
Quest.wz/*:
|
||||
Fixed a bunch of quests, now giving the proper output. Added new quests.
|
||||
|
||||
String.wz/*:
|
||||
Fixed some NPC speeches.
|
||||
Updated MonsterBook with current drop data on the sql's DB, using Ronan's
|
||||
MobBookUpdate facility.
|
||||
|
||||
|
||||
P.S.:
|
||||
|
||||
Yeah, these explanations are pretty simplistic, I know. If one really wants to
|
||||
compare the original v83 WZ with the ones I provided, I recommend do the following:
|
||||
- Open HaRepacker and, for each MapleSolaxiaV2's WZ file, extract all the XMLs
|
||||
for "Private Server".
|
||||
- Now, install MapleStory from "ManagerMsv83.exe" on an other folder and do the
|
||||
same procediment said above.
|
||||
- Finally use some app to compare folders, like WinMerge, tracking differences
|
||||
for all WZs.
|
||||
|
||||
Simply edit out any modification that ranges too far from the original MapleStory server
|
||||
and overwrite the given WZ file, assuming you want a server more "GMS-like".
|
||||
35
docs/area_bosses/AreaBoss.js
Normal file
35
docs/area_bosses/AreaBoss.js
Normal file
@@ -0,0 +1,35 @@
|
||||
// @Author: Resinate
|
||||
|
||||
importPackage(Packages.server.life);
|
||||
importPackage(Packages.tools);
|
||||
|
||||
var towns = new Array(800020120, 251010102, 260010201, 107000300, 200010300, 100040105, 100040106, 261030000, 110040000, 240040401, 104000400, 222010310, 230040420, 230040420, 230020100, 105090310, 101030404, 250010304, 220050100, 220050000, 220050200, 221040301);
|
||||
var spawns = new Array(6090002, 5220004, 3220001, 6220000, 8220000, 5220002, 5220002, 8220002, 5220001, 8220003, 2220000, 7220001, 8510000, 8520000, 4220001, 8220008, 3220000, 7220000, 5220003, 5220003, 5220003, 6220001);
|
||||
var x = new Array(560, 560, 645, 90, 208, 456, 474, -300, 200, 0, 400, 0, 527, 138, 0, -626, 800, -300, -300, 0, 0, -4224);
|
||||
var y = new Array(50, 50, 275, 119, 83, 278, 278, 180, 140, 1125, 455, 33, -437, 138, 520, -604, 1280, 390, 1030, 1030, 1030, 776);
|
||||
var mapObj;
|
||||
var mobObj;
|
||||
|
||||
function init() {
|
||||
scheduleNew();
|
||||
}
|
||||
|
||||
function scheduleNew() {
|
||||
setupTask = em.schedule("start", 0);
|
||||
}
|
||||
|
||||
function cancelSchedule() {
|
||||
if (setupTask != null)
|
||||
setupTask.cancel(true);
|
||||
}
|
||||
|
||||
function start() {
|
||||
for(var i = 0; i < towns.length; i++) {
|
||||
mapObj = em.getChannelServer().getMapFactory().getMap(towns[i]);
|
||||
mobObj = MapleLifeFactory.getMonster(spawns[i]);
|
||||
if(mapObj.getMonsterById(spawns[i]) == null) {
|
||||
mapObj.spawnMonsterOnGroundBelow(mobObj, new Packages.java.awt.Point(x[i],y[i]));
|
||||
}
|
||||
}
|
||||
setupTask = em.schedule("start", 30 * 60 * 1000);
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
// @Author: Resinate
|
||||
|
||||
var towns = new Array(800020120, 251010102, 260010201, 107000300, 200010300, 100040105, 100040106, 261030000, 110040000, 250010504, 240040401, 104000400, 222010310, 230040420, 230040420, 230020100, 105090310, 101030404, 250010304, 220050100, 220050000, 220050200, 221040301);
|
||||
var spawns = new Array(6090002, 5220004, 3220001, 6220000, 8220000, 5220002, 5220002, 8220002, 5220001, 7220002, 8220003, 2220000, 7220001, 8510000, 8520000, 4220001, 8220008, 3220000, 7220000, 5220003, 5220003, 5220003, 6220001);
|
||||
var x = new Array(560, 560, 645, 90, 208, 456, 474, -300, 200, 400, 0, 400, 0, 527, 138, 0, -626, 800, -300, -300, 0, 0, -4224);
|
||||
var y = new Array(50, 50, 275, 119, 83, 278, 278, 180, 140, 540, 1125, 455, 33, -437, 138, 520, -604, 1280, 390, 1030, 1030, 1030, 776);
|
||||
var mapObj;
|
||||
var mobObj;
|
||||
|
||||
function init() {
|
||||
scheduleNew();
|
||||
}
|
||||
|
||||
function scheduleNew() {
|
||||
setupTask = em.schedule("start", 0);
|
||||
}
|
||||
|
||||
function cancelSchedule() {
|
||||
if (setupTask != null)
|
||||
setupTask.cancel(true);
|
||||
}
|
||||
|
||||
function start() {
|
||||
var time = (Math.floor(Math.random() * 10) + 10) * (60 * 1000);
|
||||
for(var i = 0; i < towns.length; i++) {
|
||||
mapObj = em.getChannelServer().getMapFactory().getMap(towns[i]);
|
||||
mobObj = Packages.server.life.MapleLifeFactory.getMonster(spawns[i]);
|
||||
if(mapObj.getMonsterById(spawns[i]) == null) {
|
||||
mapObj.spawnMonsterOnGroundBelow(mobObj, new Packages.java.awt.Point(x[i],y[i]));
|
||||
}
|
||||
}
|
||||
em.schedule("start", time);
|
||||
}
|
||||
@@ -1,11 +1,19 @@
|
||||
#**HeavenMS _(MapleSolaxiaV2)_**
|
||||
<img src="https://heavenmssurveyhome.files.wordpress.com/2018/12/heavenmslogo.png" width="370" height="auto">
|
||||
|
||||
Credits:
|
||||
|
||||
Ronan - Developer
|
||||
Ronan - Head Developer
|
||||
|
||||
Vcoc - Freelance Developer
|
||||
|
||||
Thora - Contributor
|
||||
|
||||
GabrielSin - Contributor
|
||||
|
||||
Masterrulax - Contributor
|
||||
|
||||
MedicOP - Adjunct Developer
|
||||
|
||||
---------------------------
|
||||
DISCLAIMER:
|
||||
---------------------------
|
||||
@@ -17,50 +25,104 @@ normal WZs will load properly, there is no guarantee in-game bugs and issues
|
||||
may arise because of some incompatibilities with the clean files.
|
||||
|
||||
---------------------------
|
||||
Feature list:
|
||||
Feature list (as of rev397):
|
||||
---------------------------
|
||||
|
||||
PQs:
|
||||
|
||||
* HPQ/KPQ/LPQ/LMPQ/OPQ/EllinPQ/PiratePQ/MagatiaPQ/HorntailPQ/AmoriaPQ.
|
||||
* HPQ/KPQ/LPQ/LMPQ/OPQ/APQ/EllinPQ/PiratePQ.
|
||||
* RnJPQ/HorntailPQ/TreasurePQ/ElnathPQ/HolidayPQ.
|
||||
* CWKPQ as Expedition-based event.
|
||||
* Expeditions: Scarga/Horntail/Showa/Zakum/Pinkbean.
|
||||
* GuildPQ 100% + Guild queue with multi-lobby systems available.
|
||||
* Expeditions: Scarga/Horntail/Showa/Balrog/Zakum/Pinkbean.
|
||||
* Monster Carnival 1 & 2 - thanks Dragohe4rt & Jayd!
|
||||
* AriantPQ - thanks Dragohe4rt & Jayd!
|
||||
* GuildPQ + Guild queue with multi-lobby system available.
|
||||
* Brand-new PQs: BossRushPQ, CafePQ.
|
||||
* Mu Lung Dojo.
|
||||
* BalrogPQ semi-functional.
|
||||
* Capt. Latanica remade as an event (parties can now fight the boss).
|
||||
* Expeditions with daily/weekly entries system available.
|
||||
|
||||
Skills:
|
||||
|
||||
* Some skills behaving oddly have been patched, such as Steal, Venomous Star/Stab, Heal and Mystic Doors.
|
||||
* Maker skill features properly developed.
|
||||
* Server is using heurisitics to calculate fee costs for the Maker (errors sums up to 8k mesos, reagent errors stacks up comformant with it's level).
|
||||
* Improved current Battleship skill, now showing the HP properly on buff tab and making visible for others after changing maps.
|
||||
* Server is using heuristics to calculate fee costs for the Maker (errors sum up to 8k mesos, reagent errors stacks up conformant with its level).
|
||||
* New skill: Chair Mastery (max lv 1) - Players having this passive skill can gain a significant boost of HP/MP recovery when sitting on a field/map chair.
|
||||
* Mu Lung Dojo skills functional.
|
||||
* M. Magnet on bosses no longer crash.
|
||||
* M. Magnet on fixed mobs no longer crash - thanks shavit!
|
||||
* Skills that use up HP/MP triggers pet autopot.
|
||||
* Skills that imbue weapon with elemental attribute (WK Charges, Snow Charge, etc) is now visible for other players.
|
||||
|
||||
Quests:
|
||||
|
||||
* Doll house quest functional.
|
||||
* Quests can now reward properly items when matching a reward item with the player's job.
|
||||
* Quest rewards according to jobs work properly.
|
||||
* Reward selection and randomized reward work properly.
|
||||
* Loads of quests have been patched.
|
||||
* Quest rewards according to jobs works properly.
|
||||
* Enchanced rewarding system: checks for stacking opportunities on the inventory before checking for new slots.
|
||||
* Meso requirement for starting/completing quests now must be met by the player.
|
||||
* Lots of job questlines (rewarding skills) have been patched/implemented.
|
||||
* Enhanced rewarding system: checks for stacking opportunities on the inventory before checking for new slots.
|
||||
* Improved the quest expiration system, one of the tweaks making the clock UI disappear when completing/expiring quests.
|
||||
* Reviewed Aran questline.
|
||||
* Reviewed 4th job skill questlines as a whole.
|
||||
* Complete overhaul on the 3rd job quiz (explorers), with all 40-question pool now made available.
|
||||
* Quest items supposed to be lootable, as those are required to start quests, shows up properly.
|
||||
* Exclusive quest items that went missing from inventory reacquireable from NPC quest talk.
|
||||
* Mechanics for Item Raise functionality operational.
|
||||
* Players no longer are given movement control just after completing a quest but still talking with the NPC.
|
||||
* Quests that make use of progress data show up as completable to the player on conditions met.
|
||||
|
||||
Player Social Network:
|
||||
|
||||
* Guild and Alliance system fully functional.
|
||||
* Implemented Marriage system from the ground-up (excluding character packet encoding parts that were already present, proper credits given throughout the source files).
|
||||
* Marriage ring effects functional.
|
||||
* Beginners can create and join a "beginner-only" party (characters up to level 10).
|
||||
* HP bar of party members now properly calculates the HP gain from equipment.
|
||||
* Enhanced synchronization on Player Shops and Hired Merchants. Transactions made are instantly informed to the owner.
|
||||
* Player Shops and Hired Merchants properly displaying the correct shop image to other players, and informing whether the shop is available to visit or full.
|
||||
* Game minirooms such as match cards and omok now has a functional password system.
|
||||
* Item pickup cooldown on non-owned/non-partyowned items functional.
|
||||
* Further improved the server's ranking system, now displaying properly daily player ranking movement.
|
||||
* Automated support for Player NPCs and Hall of Fame.
|
||||
* Protected concurrently and improved the face expression system, guarding from trivial packet spam and exploits.
|
||||
* All upgradeable non-cash equipment in inventory with level & EXP information available for reading by anyone, given proper visibility.
|
||||
* Further improved the existent minigame mechanics: remarkably checking out for no-item match requests, allowing different omok/matchcard match layouts and status update on the player matchbox tooltips.
|
||||
* Further improved the trading system.
|
||||
* Party Search system nominal.
|
||||
* Wedding Wishlists - thanks Dragohe4rt!
|
||||
|
||||
Cash & Items:
|
||||
|
||||
* EXP/DROP/Cosmetic Coupons.
|
||||
* EXP/DROP coupons now appears as a buff effect when on active time.
|
||||
* EXP/DROP coupons now appear as a buff effect when on active time.
|
||||
* Code coupons functional, with support for multiple items on the same code.
|
||||
* Merged unique ids for pets, rings and cash items, thus solving some cash shop inventory issues.
|
||||
* Great deal of cash items functional.
|
||||
* MapleTV mechanics stabilized and separated by world.
|
||||
* GMS-esque omok/match card drop chances.
|
||||
* New scroll: antibanish. For use only in cases where bosses send a player back to town.
|
||||
* Inventory system properly checks for item slot free space and ownership.
|
||||
* Storage with "Arrange Items" feature functional.
|
||||
* Close-quarters evaluation mode for items (sandbox).
|
||||
* Further improved Karma scissors & Untradeable items mechanics.
|
||||
* Reviewed pet/item position data inconsistency within CASH inventory.
|
||||
* Implemented close-quarters trial mode for items.
|
||||
* Reviewed stylish-related contents, close to GMS-like.
|
||||
* Plastic surgeons/stylists no longer stuck characters.
|
||||
* Reworked gachapon loots, website-lists lookalike.
|
||||
* Spikes on shoes.
|
||||
* Vega's spell.
|
||||
* Owl of Minerva.
|
||||
* Pet item ignore.
|
||||
* New Year's card (New Year effect sometimes d/c's a player).
|
||||
* Kite.
|
||||
* Cash Shop Surprise.
|
||||
* Maple Life.
|
||||
* EXP Increase.
|
||||
|
||||
Monsters, Maps & Reactors:
|
||||
|
||||
@@ -68,68 +130,182 @@ Monsters, Maps & Reactors:
|
||||
* Added meso drop data for basically every missing overworld mob.
|
||||
* Monsterbook displays drop data info conformant with the underlying DB (needs custom wz). See more on the MobBookUpdate feature.
|
||||
* Every skill/mastery book is now droppable by mobs.
|
||||
* Mobs now can drop more than one of the same equipment (number of possible drops defined at droptime, uses the minimum/maximum quantity fields on DB).
|
||||
* Mobs only drops loot from items that are visible/collectable by the player's party.
|
||||
* Mobs shouldn't fall from foothold too often now.
|
||||
* Redesigned HT mechanics for spawn and linked damage to the sponge.
|
||||
* Reviewed aspects of MoveLifeHandler: implemented banish move, patched MP cost not accounted on non-skill mob moves and slightly fixed mobs dropping from footholds in certain cases.
|
||||
* Limited item count on maps, smartly expiring oldest registered items, preventing potential item flooding.
|
||||
* Implemented Zombify disease status.
|
||||
* Added Boss HP Bar for dozens of bosses (needs provided custom wz).
|
||||
* If multiple bosses are on the same area, client will prioritize Boss HP bar of the target of the player.
|
||||
* Boats, elevator and other travelling mechanics fully working.
|
||||
* Boss HP Bar and Server Messages now toggles (server message disappears when a boss battle is detected, and returns afterwards). Idea thanks to GabrielSin.
|
||||
* Improved map bounding checks for item drop points, assuring most of the items dropped will be available to pickup inside the walkable map area.
|
||||
* Boats, elevator and other traveling mechanics fully working.
|
||||
* HP decreasing overtime on maps and mechanics to prevent them (consumables, equips) fully functional.
|
||||
* Crimson Balrog boat approaching visual effect made functional.
|
||||
* Maps having everlasting items no longer expires them.
|
||||
* PQs, Taxis and other event-driven situations warps players at random spawnpoints, GMS-like.
|
||||
* Some reactors (PQ bonus boxes) now sprays items on the map, instead of dropping everything at once.
|
||||
* Updated Crimsonwood, World Tour and Neo City, enabling quest completion and game progression in these areas.
|
||||
* Some reactors (PQ bonus boxes) spraying items on the map, instead of dropping everything at once.
|
||||
* Reactors pick items up smartly, checking for an option to pick up on many-items-nearby scenario.
|
||||
* Updated many scripted portals not implementing SFX properly.
|
||||
* Updated Crimsonwood, World Tour, Nihal Desert and Neo City, enabling quest completion and game progression in these areas.
|
||||
* Added world maps for Mushroom Castle, World Tour (Singapore, Malaysia and Zipangu) & Ellin Forest areas.
|
||||
* Added World Tour and Masteria continents in the world map.
|
||||
* Reviewed World Map's town/field tooltips and links from the main world map and Masteria region.
|
||||
* Giant Cake (anniversary-themed boss) drops Maple equipments, Maple scrolls, summoning bags and many more interesting items.
|
||||
* Enhanced aggro system, with real-time damage output target redirection.
|
||||
* Puppets influence mob aggroing.
|
||||
* Limited quantity of summons an individual mob can perform.
|
||||
* Damage Reflect (MobSkill) status no longer lags to display.
|
||||
|
||||
PQ potentials:
|
||||
|
||||
* Advanced synchronization and smart management of the PQ registration system, as expected for a core server mechanic that is largely used by the players.
|
||||
* Lobby system - Multiple PQ instances on same channel.
|
||||
* Expedition system - Multiples parties can attempt on a same instance (lobbies and expeds are mutually-exclusive).
|
||||
* Guild queue system - Guilds can register themselves on a queue for the GPQ.
|
||||
* Guild queue system - Guilds can register themselves in a queue for the GPQ.
|
||||
* EIM Pool system - After the first instance setup, next event instances are loaded beforehand and set on a pooling queue, optimizing future loadouts.
|
||||
* Recall system - Players can rejoin the last event instance they were in before disconnection.
|
||||
|
||||
Player potentials:
|
||||
|
||||
* Adventurer Mount quests functional.
|
||||
* All Equipment levels up.
|
||||
* Player level rates.
|
||||
* Gain fame by quests.
|
||||
* Gain fame by quests and event instances.
|
||||
* Pet evolutions functional (not GMS-like).
|
||||
* Reviewed keybinding system.
|
||||
* Account's Character slots: either each world has it's own count or there's a shared value between all worlds.
|
||||
* Optional cash shop inventory separated by player classes or fully account-ranged.
|
||||
* Rock-paper-scissors minigame - thanks Arnah!
|
||||
|
||||
Server potentials:
|
||||
|
||||
* Multi-worlds.
|
||||
* Dynamic world rates, each world can hold it's own rates from server bootup.
|
||||
* Dynamic World/Channel deployment. While not implemented here, new channel deployment sensitive to quantity of online players was originally resinate's idea.
|
||||
* Inventory auto-gather and auto-sorting feature.
|
||||
* Enhanced auto-pot system: pet uses as many potions as necessary to reach the desired threshold.
|
||||
* Enhanced buff system: smartly checks for the best available buff effects to be active on the player.
|
||||
* Enhanced AP auto-assigner: exactly matches AP with the needed for the player's current level, surplus assigned to the primary attribute.
|
||||
* Enhanced inventory check: free slots on inventory smartly fetched on-demand.
|
||||
* Enhanced auto-loot handler: optimized the brute-force checks for some cash items on the player equipped inventory at every requisition.
|
||||
* Added players-appointed bestsellers item ranking system for Owl of Minerva and Cash Shop.
|
||||
* Tweaked pet/mount hunger: calculations for fullness/tiredness takes active time of the subject into account.
|
||||
* Consistent experience and meso gain system.
|
||||
* Fredrick Store Bank now has expirable storage, which warns the player of time remaining and eventually delete unclaimed items.
|
||||
* NPC crafters (equips, plates/jewels, etc) now won't take items freely if the requirement conditions are not properly met.
|
||||
* Improved Duey mechanics: package received popup and reviewed many delivery mechanics.
|
||||
* Pet item pickup now gives preference to player attacks rather than forcing attack disables when automatically picking up.
|
||||
* Channel capacity bar functional and world servers with max capacity checks.
|
||||
* Disease status are now visible for other players, even when changing maps.
|
||||
* Players keep their current disease status saved when exiting the game, returning with them on login.
|
||||
* Poison damage value is now visible for other players.
|
||||
* Mastery book announcer displays droppers of needed books of a player, by reading underlying DB.
|
||||
* Custom jail system (needs provided custom wz).
|
||||
* Custom buyback system.
|
||||
* Custom fishing system, having planned 'seasonal' catch times.
|
||||
* Custom map leasing system.
|
||||
* Delete Character (requires ENABLE_PIC activated).
|
||||
* Smoothed up view-all-char feature, now showing properly all available characters and not disconnecting players too often.
|
||||
* Centralized getcurrenttime throughout several server handlers, boosting it's performance overall.
|
||||
* Centralized server timestamping, several timestamps received from clients are now unused, preventing some spammable exploits.
|
||||
* Autosaver (periodically saves on DB current state of every player in-game).
|
||||
* Both fixed and randomized versions of HP/MP growth rate available, regarding player job (enable one at ServerConstants). Placeholder for HP/MP washing feature.
|
||||
* Accounts can be created automatically when trying to login on an inexistent account -- credits to shavit.
|
||||
* Usage of Bcrypt (up-to-date) as the main password hashing algorithm, replacing old SHA's -- credits to shavit.
|
||||
* Implemented methods to get the current Players' MaxHP/MaxMP method with equipment HP/MP gains already summed up.
|
||||
* Reallocated mapobjectids utilization throughout the source, preventing issues such as "NPC disappearing mysteriously after some server time" from happening.
|
||||
* Implemented old GMS AP assigning for novices level 10 or below. Usage of the edited localhost is mandatory on this.
|
||||
* Implemented SP capping for players that passed the job upgrade level. After upgrading jobs, the missing SP amount is replenished.
|
||||
* Bypassable PIN/PIC system for players that were already authenticated and are currently loggedin and active.
|
||||
* Accounts can be created automatically when trying to login on an inexistent account - credits to shavit.
|
||||
* Usage of Bcrypt (up-to-date) as the main password hashing algorithm, replacing old SHA's - credits to shavit.
|
||||
* Implemented matching system, on which all involved players accept the term or at least one denies/times-out before an event takes place.
|
||||
* Implemented support for custom spawn areas for NPCs & mobs.
|
||||
|
||||
Admin/GM commands:
|
||||
Custom NPCs:
|
||||
|
||||
* Spiegelmann: automatized rock-refiner.
|
||||
* Asia: scroll & rarities shop NPC.
|
||||
* Abdula: lists droppers of needed skill/mastery books.
|
||||
* Agent E: accessory crafter.
|
||||
* Dalair: automatized equipment-merger.
|
||||
* Donation Box: automatized item-buyer.
|
||||
* Coco & Ace of Hearts: C. scroll crafters.
|
||||
* Barry (MapleTV): fill book & exchange items for scroll.
|
||||
|
||||
Server Commands:
|
||||
|
||||
* Server commands layered by GM levels.
|
||||
* Spawn Zakum/Horntail/Pinkbean.
|
||||
* New commands.
|
||||
* Several new commands.
|
||||
* Rank command highlighting users either by world or server-wide.
|
||||
* Revamped command files layout - thanks Arthur L.
|
||||
* Optimized Search command, caching search range contents and added map search functionality.
|
||||
|
||||
External tools:
|
||||
|
||||
* MapleArrowFetcher - Updates min/max quantity dropped on all arrows drop data, calculations based on mob level and whether it's a boss or not.
|
||||
* MapleBossHpBarFetcher - Searches the quest WZ files and reports in all relevant data regarding mobs that has a boss HP bar whilst not having a proper "boss" label.
|
||||
* MapleCashDropFetcher - Searches the DB for any CASH drop data entry and lists them on a report file.
|
||||
* MapleCodeCouponGenerator - Reads the XML recipe at the input folder and loads into the DB new coupon codes bundled with all depicted items.
|
||||
* MapleCouponInstaller - Retrieves coupon info from the WZ and makes a SQL table with it. The server will use that table to gather info regarding rates and intervals.
|
||||
* MapleDojoUpdater - Patches the dojo WZ nodes with correct script names for onUserEnter and onFirstUserEnter fields.
|
||||
* MapleEquipmentOmnileveler - Updates the equipment WZ nodes with item level information, allowing thus access for item level and EXP info for common equipments.
|
||||
* MapleIdRetriever - Two behaviors: generates a SQL table with relation (id, name) of the handbook given as input. Given a file with names, outputs a file with ids.
|
||||
* MapleInvalidItemIdFetcher - Generates a file listing all inexistent itemid's currently laying on the DB.
|
||||
* MapleInvalidItemWithNoNameFetcher - Generates two files: one listing all itemid's with inexistent name and "cash" property. And other with a prepared XML to solve the name issue.
|
||||
* MapleMapInfoRetriever - Basic tool for detecting missing info nodes on the map field structures (maps failing to have an info node on the WZ is an critical issue).
|
||||
* MapleMesoFetcher - Creates meso drop data for mobs with more than 4 items (thus overworld mobs), calculations based on mob level and whether it's a boss or not.
|
||||
* MapleMobBookIndexer - Generates a SQL table with all relations of cardid and mobid present in the mob book.
|
||||
* MapleMobBookUpdate - Generates a wz.xml that is a copy of the original MonsterBook.wz.xml, except it updates the drop data info in the book with those currently on DB.
|
||||
* MapleQuestItemCountFetcher - Searches the quest WZ files and reports in all relevant data regarding missing "count" labels on item acts at "complete quest".
|
||||
* MapleQuestItemFetcher - Searches the SQL tables and project files and reports in all relevant data regarding missing/erroneous quest items.
|
||||
* MapleQuestlineFetcher - Searches the quest WZ files and reports in all questids that currently doesn't have script files.
|
||||
* MapleQuestMesoFetcher - Searches the quest WZ files and reports in all relevant data regarding missing/erroneous quest fee checks.
|
||||
* MapleReactorDropFetcher - Searches the DB for reactors with drop data and reports in reactorids that are not yet coded.
|
||||
* MapleSkillMakerFetcher - Updates the DB Maker-related tables with the current info present on the WZs.
|
||||
* MapleSkillMakerReagentIndexer - Generates a new maker table describing all stat-improvements from the Maker reagents (those empowering crystals and jewels).
|
||||
* MapleWorldmapChecker - Searches the map WZ files for map/field entries with missing tooltip informations (that would point which map the character currently is on the overworld maps).
|
||||
|
||||
Project:
|
||||
|
||||
* Organized project code.
|
||||
* Highly updated drop data.
|
||||
* Highly configurable server (see all server flags at ServerConstants).
|
||||
* Fixed/added some missing packets for MoveEnvironment, summons and others.
|
||||
* Uncovered many Send/Recv opcodes throughout the source.
|
||||
* Reviewed many Java object aspects that needed concurrency protection.
|
||||
* Reviewed SQL data, eliminating duplicated entries on the tables.
|
||||
* Improved login phase, using cache over DB queries.
|
||||
* Usage of HikariCP to improve the DB connection management.
|
||||
* Usage of Java Threadpool to improve runnable call management.
|
||||
* Developed many survey tools for content profiling.
|
||||
* Developed a robust anti-exploit login coordinator system.
|
||||
* Protected many flaws with login management system.
|
||||
* Remodeled item scripts, properly using NPC dialogs.
|
||||
* Channel, World and Server-wide timer management.
|
||||
* Heavily reviewed future task management inside the project. Way less trivial schedules are spawned now, relieving task overload on the TimerManager.
|
||||
* Developed services to act as a central task scheduler, in order to spawn less timer threads.
|
||||
* ThreadTracker: embedded auditing tool for run-time deadlock scanning throughout the server source (relies heavily on memory usage, designed only for debugging purposes).
|
||||
|
||||
Exploits patched:
|
||||
|
||||
* Player being given free access to any character of any account once they have authenticated their account on login phase.
|
||||
* Player being given permission to delete any character of any account once they have authenticated their account on login phase.
|
||||
* Player being able to start/complete any quest freely.
|
||||
* Several assynchronous-oriented exploits patched, highlights on those involving Fredrick & Duey.
|
||||
|
||||
Localhost:
|
||||
|
||||
* Removed the 'n' problem within NPC dialog.
|
||||
* Removed caps for MATK, WDEF, MDEF, ACC and AVOID.
|
||||
* Removed "AP excess" popup and "Admin/MWLB" action block, original credits to kevintjuh93.
|
||||
* Removed "You've gained a level!" popup, original credits to PrinceReborn.
|
||||
* Removed "Cannot enter MTS from this map." popup on maps that blocks transitions (such change channel, CS/MTS), rendering the buyback option now available for all maps.
|
||||
* Removed a check for players wishing to create/join a party being novices under level 10.
|
||||
* Set a new high cap for SPEED.
|
||||
* Removed the AP assign block for novices.
|
||||
* Removed a block that would show up when trying to apply an attack gem on equipments that aren't weapons.
|
||||
|
||||
---------------------------
|
||||
27
docs/fieldlimits.txt
Normal file
27
docs/fieldlimits.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
Provided by Arnah, source: http://forum.ragezone.com/f702/release-harepacker-resurrected-1149521/index2.html
|
||||
|
||||
Field limits (v95):
|
||||
FIELDOPT_MOVELIMIT = 0x1,
|
||||
FIELDOPT_SKILLLIMIT = 0x2,
|
||||
FIELDOPT_SUMMONLIMIT = 0x4,
|
||||
FIELDOPT_MYSTICDOORLIMIT = 0x8,
|
||||
FIELDOPT_MIGRATELIMIT = 0x10,
|
||||
FIELDOPT_PORTALSCROLLLIMIT = 0x20,
|
||||
FIELDOPT_TELEPORTITEMLIMIT = 0x40,
|
||||
FIELDOPT_MINIGAMELIMIT = 0x80,
|
||||
FIELDOPT_SPECIFICPORTALSCROLLLIMIT = 0x100,
|
||||
FIELDOPT_TAMINGMOBLIMIT = 0x200,
|
||||
FIELDOPT_STATCHANGEITEMCONSUMELIMIT = 0x400,
|
||||
FIELDOPT_PARTYBOSSCHANGELIMIT = 0x800,
|
||||
FIELDOPT_NOMOBCAPACITYLIMIT = 0x1000,
|
||||
FIELDOPT_WEDDINGINVITATIONLIMIT = 0x2000,
|
||||
FIELDOPT_CASHWEATHERCONSUMELIMIT = 0x4000,
|
||||
FIELDOPT_NOPET = 0x8000,
|
||||
FIELDOPT_ANTIMACROLIMIT = 0x10000,
|
||||
FIELDOPT_FALLDOWNLIMIT = 0x20000,
|
||||
FIELDOPT_SUMMONNPCLIMIT = 0x40000,
|
||||
FIELDOPT_NOEXPDECREASE = 0x80000,
|
||||
FIELDOPT_NODAMAGEONFALLING = 0x100000,
|
||||
FIELDOPT_PARCELOPENLIMIT = 0x200000,
|
||||
FIELDOPT_DROPLIMIT = 0x400000,
|
||||
FIELDOPT_ROCKETBOOSTER_LIMIT = 0x800000,
|
||||
74
docs/issues.txt
Normal file
74
docs/issues.txt
Normal file
@@ -0,0 +1,74 @@
|
||||
========== HeavenMS ==========
|
||||
Credits:
|
||||
Ronan - Head Developer
|
||||
Vcoc - Freelance Developer
|
||||
|
||||
---------------------------
|
||||
Known issues:
|
||||
- Some criticals (e.g. from Aran skills) will not show up as crit for other players.
|
||||
- Deadlocks may start appearing if the server stays online long enough with many players logged in.
|
||||
- If there are multiple bosses that shows HPBar on the map, if a player hits more than one the HPBar may start flickering on the screen.
|
||||
- Sometimes battleship may behave oddly with the enhanced buff system, making the character d/c in certain scenarios.
|
||||
- Dragon Roar doesn't show the stun effect to players.
|
||||
- Cygnus job 'Final Attack' skill for Wind Archer not functional.
|
||||
- Steal skill doesn't deduct the loot from the drop pool from a mob.
|
||||
- Snipe will show much higher damage value than actually applicable to the attacker.
|
||||
- Some monster status such as weapon/magic reflect doesn't behave properly in certain scenarios.
|
||||
- On low-end connections, things such as command summoning a player that is currently logging in (already visible to other players) may cause the player to freeze, consequently freezing the account as well since the server-side disconnection doesn't happen.
|
||||
- Reportedly, there are cases where mob positions fail to sync between player's client-view.
|
||||
- Visual equip EXP watch value will present stuttering for early levels requirement (EXP needed less than 100), and requirement at level 200 will not progress at all due to the level cap in client.
|
||||
- Monster Magnet will crash the player when trying to pull fixed monsters.
|
||||
- Some magic skills such as "Energy Bolt" or "Holy Arrow" doesn't display damage to other players when the attacks come from close range to the targeted mob. Oddly enough, using "closeRangeAttack" packet seems to clear the issue on most skills, however in others "Error 5" crash renders this unusable.
|
||||
---------------------------
|
||||
|
||||
---------------------------
|
||||
Missing features list:
|
||||
- Change name/World transfer.
|
||||
- Some pirate skills doesn't work for 3rd parties.
|
||||
- Cache frequently used SQL data.
|
||||
- Pet commands are not being propagated to 3rd parties, and the commandResponse packet function seems somewhat wonky.
|
||||
---------------------------
|
||||
|
||||
|
||||
---------------------------
|
||||
** Others **
|
||||
- MTS
|
||||
---------------------------
|
||||
|
||||
|
||||
---------------------------
|
||||
** Quest **
|
||||
- Medal quests.
|
||||
---------------------------
|
||||
|
||||
|
||||
---------------------------
|
||||
** Basic PQs **
|
||||
---------------------------
|
||||
|
||||
|
||||
---------------------------
|
||||
** Packet issues & advanced PQs **
|
||||
- Mystic Doors (won't deploy players properly in some situations, only destination map matches).
|
||||
- Nett's Pyramid Party Quest
|
||||
---------------------------
|
||||
|
||||
|
||||
---------------------------
|
||||
** Skills **
|
||||
- Check autoban system
|
||||
- Attack speed reference for autoban, brought here thanks to GitGud: https://ayumilovemaple.wordpress.com/2009/09/06/maplestory-attack-speed-reference/
|
||||
---------------------------
|
||||
|
||||
|
||||
---------------------------
|
||||
** Jobs **
|
||||
---------------------------
|
||||
|
||||
|
||||
---------------------------
|
||||
** System **
|
||||
- Update Java version
|
||||
---------------------------
|
||||
|
||||
====================================
|
||||
84
docs/leftover.txt
Normal file
84
docs/leftover.txt
Normal file
@@ -0,0 +1,84 @@
|
||||
// Missing contents in HeavenMS (as of commit 311), compiled here thanks to ---
|
||||
|
||||
Uncoded features:
|
||||
NX Format
|
||||
MTS (v53)
|
||||
Family and Medal Quests(?)
|
||||
|
||||
Uncoded Party Quests:
|
||||
Gold Richie (v77)
|
||||
Olivia PQ (v77)
|
||||
Ariant PQ (v??)
|
||||
Nett's Pyramid PQ (v??)
|
||||
Sheep vs Wolf (v??)
|
||||
Abandoned PQ (v??)
|
||||
|
||||
Uncoded pre-v83 events:
|
||||
Independence Day Event (v25)
|
||||
April Fools Dress Up (v53)
|
||||
Find Master M (v72)
|
||||
Gaga the Talent Show Star Event (v76, a "fishing" event)
|
||||
|
||||
I'm not positive what these are but I'm guessing they're "give away" events:
|
||||
Spirit Week (v76)
|
||||
A November to Remember (v79)
|
||||
|
||||
Uncoded Repeating pre-v83 events:
|
||||
Easter
|
||||
Lunar New Year
|
||||
Christmas
|
||||
Anniversary
|
||||
Halloween (v10-v77)
|
||||
Valentines Day (v17-v81)
|
||||
Mardi Gras (v82)
|
||||
Gold Richie (v77)
|
||||
Turkey Event
|
||||
|
||||
Post-v83 codable:
|
||||
Neo City update (v84)
|
||||
Evan release events (v84) (arguably no point without Evan)
|
||||
General Mau (v84)
|
||||
Five Year Reunion Event (v85)
|
||||
Weather Effects Event (v85)
|
||||
OSSS Quests (v89) (arguably not worth doing since it won't be complete without Visitor PQ)
|
||||
Ghost Ship (v90)
|
||||
Ulu City (v90) (New World Map)
|
||||
Aramia's Book Drive (v90)
|
||||
Ancient Artifact Hunt (v98)
|
||||
Gate to the Future (v99) (New World Map)
|
||||
Kenta PQ (v101)
|
||||
|
||||
Post-v83 uncodable:
|
||||
Evan (v84)(some of Evan can be hacked in but it still won't fully function)
|
||||
Dragon Rider PQ (v85)
|
||||
Monster Portraits event (or can it?)
|
||||
Golden Temple (v86) (Not sure if Ravana can be backported, if so then codable)
|
||||
Chaos Zakum/Horntail (v88)
|
||||
Dual Blade (v88)
|
||||
Potential (v88)
|
||||
Ice Gorge PQ (v90)
|
||||
Visitor PQ (v90)
|
||||
Resistance (v94/95)
|
||||
Ultimate Explorer (v96)
|
||||
Lion's King Castle (v96) (due to von Leon being uncodable)
|
||||
Chryse (v96)
|
||||
Dual Raid: Balloon Hunt (v97)
|
||||
PVP (v99/100)
|
||||
Ice Knight PQ (v99)
|
||||
Monster Park (v101) (Not actually sure if this one is uncodable, seems somewhat basic)
|
||||
Familiars (v102)
|
||||
|
||||
Non-GMS but English:
|
||||
La Tomatina Event (EMS) (Giant Tomato boss)
|
||||
Oktoberfest (EMS)
|
||||
Shanghai (MSEA) (New World Map)
|
||||
Thailand (MSEA) (New World Map)
|
||||
Neo Tokyo (MSEA) (New World Map) (different from Neo City)
|
||||
|
||||
Non-GMS no English:
|
||||
Coke Town (J/KMS)
|
||||
Ninja Castle (now in GMS, unsure how it compares to the "classic" version)
|
||||
Ximending (TMS) (New World Map)
|
||||
Taipei 101 (TMS) (New World Map) (Kerning Square Mall, v83, is the non TMS variant)
|
||||
Night Market (TMS) (Now in GMS, unsure how it compares to the "classic" version)
|
||||
Shaolin Temple (C/JMS) (Now in GMS, unsure how it compares to the "classic" version)
|
||||
14
docs/localhost_minimum_specs.txt
Normal file
14
docs/localhost_minimum_specs.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
-- Thanks MikeyJacobs for prompting out minimum specs search for pre-BB MapleStory.
|
||||
-- Minimum specs gathered thanks to AkatsukiLog - src: https://www.clubedohardware.com.br/forums/topic/1081421-maplestory-reinicia-meu-pc-direto-ajuda/
|
||||
|
||||
MapleStory pre-BB specs:
|
||||
|
||||
Minimum Requirement | Recommended Setting
|
||||
|
||||
OS: Windows XP or later | Windows XP or later
|
||||
Processor: Pentium 4 or equivalent | Pentium Dual Core or equivalent
|
||||
Memory: 1GB RAM | 1GB RAM
|
||||
Hard Drive: At least 7GB of free space | At least 7GB of free space
|
||||
Graphics: Video Card with 128MB or higher | GeForce FX5000 / ATI Radeon 9600 or higher (any video card with Shader model 2.0 or higher)
|
||||
Sound: DirectX compatible sound card | DirectX compatible sound card
|
||||
Network: Broadband internet connection | Broadband internet connection
|
||||
@@ -1,315 +0,0 @@
|
||||
var DISABLED = false;
|
||||
|
||||
var SavedLocationType = Packages.server.maps.SavedLocationType;
|
||||
|
||||
var MonsterCarnival = Packages.server.partyquest.mcpq.MonsterCarnival;
|
||||
var MCTracker = Packages.server.partyquest.mcpq.MCTracker;
|
||||
var MCParty = Packages.server.partyquest.mcpq.MCParty;
|
||||
var MCField = Packages.server.partyquest.mcpq.MCField;
|
||||
|
||||
var status = -1;
|
||||
var store = false;
|
||||
var ctx = -1;
|
||||
var storeInfo;
|
||||
var purchaseId;
|
||||
var purchaseCost;
|
||||
|
||||
var coinId = 4001129;
|
||||
var coinIcon = "#i" + coinId + "#";
|
||||
var infoMaps = [220000000, 200000000, 103000000, 540000000]; // ludi, orbis, kerning, singapore
|
||||
var gradeS = 600
|
||||
var gradeA = 500
|
||||
var gradeB = 400
|
||||
var gradeC = 300
|
||||
var gradeD = 200
|
||||
var gradeE = 100
|
||||
|
||||
var expRewards = [[150000, 100000], // S Winner/Loser
|
||||
[100000, 70000], // A Winner/Loser
|
||||
[75000, 43250], // B Winner/Loser
|
||||
[50000, 25000], // C Winner/Loser
|
||||
[25000, 12500], // D Winner/Loser
|
||||
[12500, 6250], // E Winner/Loser
|
||||
[5000, 2500] // F Winner/Loser
|
||||
];
|
||||
|
||||
// Exchange stores
|
||||
var warrior = [[1302004, 7], [1402006, 7], [1302009, 10], [1402007, 10],
|
||||
[1302010, 20], [1402003, 20], [1312006, 7], [1412004, 7],
|
||||
[1312007, 10], [1412005, 10], [1312018, 20], [1412003, 20],
|
||||
[1322015, 7], [1422008, 7], [1322016, 10], [1422007, 10],
|
||||
[1322017, 20], [1422005, 20], [1432003, 7], [1442003, 7],
|
||||
[1432005, 10], [1442009, 10], [1442005, 20], [1432004, 20]];
|
||||
|
||||
var magician = [[1372001, 7], [1382018, 7], [1372012, 10], [1382019, 10],
|
||||
[1382001, 20], [1372007, 20]];
|
||||
|
||||
var archer = [[1452006, 7], [1452007, 10], [1452008, 20], [1462005, 7],
|
||||
[1462006, 10], [1462007, 20]];
|
||||
|
||||
var thief = [[1472013, 7], [1472017, 10], [1472021, 20], [1332014, 7],
|
||||
[1332011, 10], [1332031, 10], [1332016, 20], [1332034, 20]];
|
||||
|
||||
var pirate = [[1482005, 7], [1482006, 10], [1482007, 20], [1492005, 7],
|
||||
[1492006, 10], [1492007, 20]];
|
||||
|
||||
var necklace = [[1122007, 50], [2041211, 40]];
|
||||
|
||||
var infoText = "You wish to know about the Monster Carnival? Very well. The Monster Carnival is a place of trilling battles and exciting competiton against people just as strong and motivated as yourself. You must summon monsters and defeat the monsters summoned by the opposing party. That's the essence of the Monster Carnival. Once you enter the Carnival Field, the task is to earn CP by hunter monsters from the opposing party and use those CP's to distract the opposing party from hunting monsters. There are three ways to distract the other party; Summon a Monster, Skill or Protector. Please remember this though, it's never a good idea to save up CP just for the sake of it. The CP's you've used will also help determine the winner and the loser of the carnival.";
|
||||
var no = "You do not have enough Maple Coins for this item. Come back to me when you acquire more!";
|
||||
|
||||
function getGrade(cp) {
|
||||
if (cp >= gradeS) {
|
||||
return 0;
|
||||
} else if (cp >= gradeA) {
|
||||
return 1;
|
||||
} else if (cp >= gradeB) {
|
||||
return 2;
|
||||
} else if (cp >= gradeC) {
|
||||
return 3;
|
||||
} else if (cp >= gradeD) {
|
||||
return 4;
|
||||
} else if (cp >= gradeE) {
|
||||
return 5;
|
||||
} else {
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
|
||||
function isTownMap(map) {
|
||||
for (var i = 0; i < infoMaps.length; i++) {
|
||||
if (infoMaps[i] == map) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isExitMap(map) {
|
||||
return map == 980000010;
|
||||
}
|
||||
|
||||
function isWinnerMap(map) {
|
||||
return (map >= 980000000 && map <= 980000700 && map % 10 == 3);
|
||||
}
|
||||
|
||||
function isLoserMap(map) {
|
||||
return (map >= 980000000 && map <= 980000700 && map % 10 == 4);
|
||||
}
|
||||
|
||||
var CONTEXT_NONE = -1;
|
||||
var CONTEXT_TOWN = 0;
|
||||
var CONTEXT_EXIT = 1;
|
||||
var CONTEXT_WIN = 2;
|
||||
var CONTEXT_LOSE = 3;
|
||||
|
||||
function start() {
|
||||
if (DISABLED) {
|
||||
cm.sendOk("CPQ is temporarily unavailable.");
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
m = cm.getMapId();
|
||||
if (isTownMap(m)) {
|
||||
ctx = CONTEXT_TOWN;
|
||||
} else if (isExitMap(m)) {
|
||||
ctx = CONTEXT_EXIT;
|
||||
} else if (isWinnerMap(m)) {
|
||||
ctx = CONTEXT_WIN;
|
||||
} else if (isLoserMap(m)) {
|
||||
ctx = CONTEXT_LOSE;
|
||||
} else {
|
||||
ctx = CONTEXT_NONE;
|
||||
}
|
||||
|
||||
action(1, 0, 0);
|
||||
}
|
||||
|
||||
function doLoserMap(mode, type, selection) {
|
||||
if (cm.getPlayer().getMCPQParty() == null) {
|
||||
cm.warp(MonsterCarnival.MAP_LOBBY);
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == -1) {
|
||||
cm.dispose();
|
||||
} else {
|
||||
if (mode == 1) status++;
|
||||
else status--;
|
||||
|
||||
if (status == 0) {
|
||||
cm.sendNext("Unfortunately, you did not manage to win this round. Better luck next time!");
|
||||
} else if (status == 1) {
|
||||
var points = cm.getPlayer().getMCPQParty().getTotalCP();
|
||||
var grade = getGrade(points);
|
||||
var letterGrade = "ABCDF"[grade];
|
||||
var expReward = expRewards[grade][1];
|
||||
|
||||
cm.sendNext("Your grade is: #b" + letterGrade + "\r\n\r\n#kEXP Reward: " + expReward);
|
||||
cm.gainExp(expReward);
|
||||
} else if (status == 2) {
|
||||
cm.warp(MonsterCarnival.MAP_LOBBY);
|
||||
cm.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function doWinnerMap(mode, type, selection) {
|
||||
if (cm.getPlayer().getMCPQParty() == null) {
|
||||
cm.warp(MonsterCarnival.MAP_LOBBY);
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == -1) {
|
||||
cm.dispose();
|
||||
} else {
|
||||
if (mode == 1) status++;
|
||||
else status--;
|
||||
|
||||
if (status == 0) {
|
||||
cm.sendNext("Congratulations! You managed to defeat the enemy team!");
|
||||
} else if (status == 1) {
|
||||
var points = cm.getPlayer().getMCPQParty().getTotalCP();
|
||||
var grade = getGrade(points);
|
||||
var letterGrade = "ABCDF"[grade];
|
||||
var expReward = expRewards[grade][0];
|
||||
|
||||
cm.sendNext("Your grade is: #b" + letterGrade + "\r\n\r\n#kEXP Reward: " + expReward);
|
||||
cm.gainExp(expReward);
|
||||
} else if (status == 2) {
|
||||
cm.warp(MonsterCarnival.MAP_LOBBY);
|
||||
cm.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function doTown(mode, type, selection) {
|
||||
if (mode == -1) {
|
||||
cm.sendOk("Be sure to vote for the server every 24 hours!");
|
||||
cm.dispose();
|
||||
} else {
|
||||
if (mode == 1) status++;
|
||||
else status--;
|
||||
|
||||
if (status == 0) {
|
||||
cm.sendSimple("What would you like to do? If you have never participated in the Monster Carnival, you'll need to know a thing or two about it before joining.\r\n\r\n#b#L0#Go to the Monster Carnival Field#l\r\n#L1#Learn about the Monster Carnival#l\r\n#L2#Trade Maple Coin#l");
|
||||
} else if (status == 1) {
|
||||
if (selection == 0) {
|
||||
if (cm.getChar().getLevel() < MonsterCarnival.MIN_LEVEL || cm.getChar().getLevel() > MonsterCarnival.MAX_LEVEL) {
|
||||
cm.sendOk("You must be between level " + MonsterCarnival.MIN_LEVEL + " and level " + MonsterCarnival.MAX_LEVEL + " to enter.");
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
cm.getChar().saveLocation(SavedLocationType.MONSTER_CARNIVAL);
|
||||
cm.warp(MonsterCarnival.MAP_LOBBY, 4);
|
||||
cm.dispose();
|
||||
return;
|
||||
} else if (selection == 1) {
|
||||
cm.sendPrev(infoText);
|
||||
cm.dispose();
|
||||
return;
|
||||
} else if (selection == 2) {
|
||||
store = true;
|
||||
cm.sendSimple("Select a category:\r\n" +
|
||||
"#L101##bTrade Maple Coins for Warrior Weapons\r\n" +
|
||||
"#L102#Trade Maple Coins for Magician Weapons\r\n" +
|
||||
"#L103#Trade Maple Coins for Bowman Weapons\r\n" +
|
||||
"#L104#Trade Maple Coins for Thief Weapons\r\n" +
|
||||
"#L105#Trade Maple Coins for Pirate Weapons\r\n" +
|
||||
"#L106#Trade Maple Coins for a Necklace");
|
||||
}
|
||||
} else if (status == 2) {
|
||||
if (store) {
|
||||
switch (selection) {
|
||||
case 101:
|
||||
storeInfo = warrior;
|
||||
break;
|
||||
case 102:
|
||||
storeInfo = magician;
|
||||
break;
|
||||
case 103:
|
||||
storeInfo = archer;
|
||||
break;
|
||||
case 104:
|
||||
storeInfo = thief;
|
||||
break;
|
||||
case 105:
|
||||
storeInfo = pirate;
|
||||
break;
|
||||
case 106:
|
||||
storeInfo = necklace;
|
||||
break;
|
||||
default:
|
||||
storeInfo = [];
|
||||
}
|
||||
if (storeInfo.length == 0) {
|
||||
cm.sendOk("That store doesn't exist.");
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
var storeText = "";
|
||||
for (var i = 0; i < storeInfo.length; ++i) {
|
||||
var wepId = storeInfo[i][0];
|
||||
var cost = storeInfo[i][1];
|
||||
storeText += "#L" + i + "##v" + wepId + "# - #z" + wepId + "# - " + cost + " " + coinIcon + "#l\r\n";
|
||||
}
|
||||
cm.sendSimple(storeText);
|
||||
} else {
|
||||
MCTracker.log("[MCPQ_Info] CONTEXT_TOWN: Invalid status 2");
|
||||
}
|
||||
} else if (status == 3) {
|
||||
if (store) {
|
||||
purchaseId = storeInfo[selection][0];
|
||||
purchaseCost = storeInfo[selection][1];
|
||||
|
||||
if (cm.haveItem(coinId, purchaseCost)) {
|
||||
cm.sendYesNo("Are you sure you want to purchase #i" + purchaseId + "#? You will have #r#e" + (cm.itemQuantity(coinId) - purchaseCost) + " " + coinIcon + "##k#n remaining.");
|
||||
} else {
|
||||
cm.sendOk("You don't have enough " + coinIcon + ".");
|
||||
cm.dispose();
|
||||
}
|
||||
} else {
|
||||
MCTracker.log("[MCPQ_Info] CONTEXT_TOWN: Invalid status 3");
|
||||
}
|
||||
} else if (status == 4) {
|
||||
if (store) {
|
||||
if (cm.haveItem(coinId, purchaseCost)) {
|
||||
cm.gainItem(coinId, -purchaseCost);
|
||||
cm.gainItem(purchaseId);
|
||||
cm.sendOk("Congratulations! Enjoy your new item.");
|
||||
cm.dispose();
|
||||
}
|
||||
} else {
|
||||
MCTracker.log("[MCPQ_Info] CONTEXT_TOWN: Invalid status 4");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function doExit() {
|
||||
cm.warp(MonsterCarnival.MAP_LOBBY);
|
||||
cm.sendOk("Hope you had fun in the Carnival PQ!");
|
||||
cm.dispose();
|
||||
}
|
||||
|
||||
function action(mode, type, selection) {
|
||||
switch (ctx) {
|
||||
case CONTEXT_TOWN:
|
||||
doTown(mode, type, selection);
|
||||
break;
|
||||
case CONTEXT_EXIT:
|
||||
doExit();
|
||||
break;
|
||||
case CONTEXT_LOSE:
|
||||
doLoserMap(mode, type, selection);
|
||||
break;
|
||||
case CONTEXT_WIN:
|
||||
doWinnerMap(mode, type, selection);
|
||||
break;
|
||||
default:
|
||||
MCTracker.log("[MCPQ_INFO] Invalid context (value: " + ctx + ")");
|
||||
cm.dispose();
|
||||
}
|
||||
}
|
||||
@@ -1,464 +0,0 @@
|
||||
/*
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package server.partyquest.mcpq;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import packet.creators.CarnivalPackets;
|
||||
import packet.creators.PacketCreator;
|
||||
import client.player.Player;
|
||||
import server.life.MapleLifeFactory;
|
||||
import server.life.MapleMonster;
|
||||
import server.life.MobSkill;
|
||||
import server.life.MobSkillFactory;
|
||||
import server.life.SpawnPoint;
|
||||
import server.life.Spawns;
|
||||
import server.maps.Field;
|
||||
import server.maps.FieldObject;
|
||||
import server.maps.FieldObjectType;
|
||||
import server.maps.reactors.MapleReactor;
|
||||
import server.maps.reactors.MapleReactorFactory;
|
||||
import server.partyquest.mcpq.MCField.MCTeam;
|
||||
import static server.partyquest.mcpq.MCField.MCTeam.RED;
|
||||
import server.partyquest.mcpq.MCWZData.MCGuardianGenPos;
|
||||
import server.partyquest.mcpq.MCWZData.MCMobGenPos;
|
||||
|
||||
|
||||
/**
|
||||
* Keeps track of guardians and spawns in MCPQ.
|
||||
*
|
||||
* @author s4nta
|
||||
*/
|
||||
public class MCBattlefield {
|
||||
|
||||
private Field map;
|
||||
private MCWZData wzData;
|
||||
private int numGuardiansSpawned = 0;
|
||||
private int numMonstersSpawned = 0;
|
||||
// These map Guardian IDs (aka codes for status) to the guardian position.
|
||||
private Map<Integer, MCWZData.MCGuardianGenPos> redGuardianIdToPos = new HashMap<>();
|
||||
private Map<Integer, MCWZData.MCGuardianGenPos> blueGuardianIdToPos = new HashMap<>();
|
||||
// These map Reactor Object IDs to guardian objects.
|
||||
private Map<Integer, MCGuardian> redReactors = new HashMap<>();
|
||||
private Map<Integer, MCGuardian> blueReactors = new HashMap<>();
|
||||
// used for divided maps
|
||||
// we use an arraylist here for easier random element lookup.
|
||||
private List<MCWZData.MCGuardianGenPos> originalRedGuardianSpawns = new ArrayList<>();
|
||||
private List<MCWZData.MCGuardianGenPos> originalBlueGuardianSpawns = new ArrayList<>();
|
||||
// used for undivided map
|
||||
private List<MCWZData.MCGuardianGenPos> originalGuardianSpawns = new ArrayList<>();
|
||||
|
||||
// used for divided maps
|
||||
// we use an arraylist here for easier random element lookup.
|
||||
private List<MCWZData.MCMobGenPos> originalRedSpawns = new ArrayList<>();
|
||||
private List<MCWZData.MCMobGenPos> originalBlueSpawns = new ArrayList<>();
|
||||
// use for undivided map
|
||||
private List<MCWZData.MCMobGenPos> originalUnifiedSpawns = new ArrayList<>();
|
||||
|
||||
private List<SpawnPoint> originalSpawns = new ArrayList<>();
|
||||
private List<SpawnPoint> addedSpawns = new ArrayList<>();
|
||||
|
||||
public MCBattlefield(Field battleInstance) {
|
||||
this.map = battleInstance;
|
||||
fetchCarnivalData();
|
||||
getOriginalSpawnPoints();
|
||||
populateGuardianSpawns();
|
||||
populateMobSpawns();
|
||||
}
|
||||
|
||||
private void fetchCarnivalData() {
|
||||
wzData = this.map.getMCPQData();
|
||||
if (wzData == null) {
|
||||
MCTracker.log("[MCPQ] Fetching carnival failed for map " + map.getId());
|
||||
}
|
||||
}
|
||||
|
||||
private void getOriginalSpawnPoints() {
|
||||
for (Spawns sp : this.map.getSpawnPoints()) {
|
||||
originalSpawns.add((SpawnPoint) sp);
|
||||
}
|
||||
}
|
||||
|
||||
private void populateGuardianSpawns() {
|
||||
for (MCWZData.MCGuardianGenPos gpos : wzData.guardianGenPosList) {
|
||||
switch (gpos.team) {
|
||||
case 0:
|
||||
originalRedGuardianSpawns.add(gpos);
|
||||
break;
|
||||
case 1:
|
||||
originalBlueGuardianSpawns.add(gpos);
|
||||
break;
|
||||
default:
|
||||
originalGuardianSpawns.add(gpos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void populateMobSpawns() {
|
||||
for (MCWZData.MCMobGenPos mpos : wzData.mobGenPosList) {
|
||||
switch (mpos.team) {
|
||||
case 0:
|
||||
originalRedSpawns.add(mpos);
|
||||
break;
|
||||
case 1:
|
||||
originalBlueSpawns.add(mpos);
|
||||
break;
|
||||
default:
|
||||
originalUnifiedSpawns.add(mpos);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addSpawn(Player chr, int num) {
|
||||
if (numMonstersSpawned > wzData.mobGenMax) {
|
||||
chr.getClient().announce(CarnivalPackets.CarnivalMessage(3));
|
||||
return;
|
||||
}
|
||||
|
||||
MCWZData.MCSummonMob mobToSummon = wzData.summons.get(num);
|
||||
MCWZData.MCMobGenPos spawnPos = getRandomSpawnPos(chr.getMCPQTeam());
|
||||
|
||||
MCField.MCTeam team = chr.getMCPQTeam();
|
||||
if (spawnPos == null) {
|
||||
chr.getClient().announce(CarnivalPackets.CarnivalMessage(2));
|
||||
return;
|
||||
}
|
||||
|
||||
int spendCp = mobToSummon.spendCP;
|
||||
if (spendCp > chr.getAvailableCP()) {
|
||||
readdSpawn(spawnPos, team);
|
||||
chr.getClient().announce(CarnivalPackets.CarnivalMessage(1));
|
||||
return;
|
||||
}
|
||||
|
||||
chr.getMCPQField().loseCP(chr, spendCp);
|
||||
this.map.broadcastMessage(CarnivalPackets.PlayerSummoned(MonsterCarnival.TAB_SPAWNS, num, chr.getName()));
|
||||
numMonstersSpawned++; // TODO: AtomicInteger this
|
||||
|
||||
MapleMonster monster = MapleLifeFactory.getMonster(mobToSummon.id);
|
||||
Point pos = new Point(spawnPos.x, spawnPos.y);
|
||||
SpawnPoint sp = new SpawnPoint(monster, pos, mobToSummon.mobTime, chr.getTeam());
|
||||
|
||||
addedSpawns.add(sp);
|
||||
updateMonsterBuffs();
|
||||
}
|
||||
|
||||
public void useSkill(Player chr, int num) {
|
||||
if (!wzData.skills.containsKey(num)) {
|
||||
MCTracker.log("Attempting to use a null skill.");
|
||||
return;
|
||||
}
|
||||
int realSkill = wzData.skills.get(num);
|
||||
MCSkill skill = MCSkillFactory.getMCSkill(realSkill);
|
||||
// TODO: add skill cooldowns
|
||||
|
||||
int spendCp = skill.getSpendCP();
|
||||
if (spendCp > chr.getAvailableCP()) {
|
||||
chr.getClient().announce(CarnivalPackets.CarnivalMessage(1));
|
||||
return;
|
||||
}
|
||||
|
||||
MCParty teamToApply = chr.getMCPQParty().getEnemy();
|
||||
boolean success = teamToApply.applyMCSkill(skill);
|
||||
|
||||
if (success) {
|
||||
chr.getMCPQField().loseCP(chr, spendCp);
|
||||
map.broadcastMessage(CarnivalPackets.PlayerSummoned(MonsterCarnival.TAB_DEBUFF, num, chr.getName()));
|
||||
} else {
|
||||
chr.getClient().getSession().write(CarnivalPackets.CarnivalMessage(5));
|
||||
}
|
||||
}
|
||||
|
||||
public void readdSpawn(MCWZData.MCMobGenPos pos, MCField.MCTeam team) {
|
||||
List<MCWZData.MCMobGenPos> lst = null;
|
||||
if (this.wzData.mapDivided) {
|
||||
if (null == team) {
|
||||
return;
|
||||
} else switch (team) {
|
||||
case RED:
|
||||
lst = originalRedSpawns;
|
||||
break;
|
||||
case BLUE:
|
||||
lst = originalBlueSpawns;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
lst = originalUnifiedSpawns;
|
||||
}
|
||||
|
||||
if (lst == null) {
|
||||
return;
|
||||
}
|
||||
lst.add(pos);
|
||||
}
|
||||
|
||||
public void spawnGuardian(Player chr, int num) {
|
||||
if (numGuardiansSpawned > wzData.guardianGenMax) {
|
||||
chr.getClient().announce(CarnivalPackets.CarnivalMessage(3));
|
||||
return;
|
||||
}
|
||||
|
||||
int guardianId = wzData.guardians.get(num);
|
||||
MCGuardian guardian = MCSkillFactory.getMCGuardian(guardianId);
|
||||
if (guardian == null) {
|
||||
MCTracker.log("Attempting to spawn invalid guardian.");
|
||||
return;
|
||||
}
|
||||
|
||||
MCField.MCTeam team = chr.getMCPQTeam();
|
||||
if (team == MCField.MCTeam.RED) {
|
||||
if (redGuardianIdToPos.containsKey(guardianId)) {
|
||||
chr.getClient().announce(CarnivalPackets.CarnivalMessage(4));
|
||||
return;
|
||||
}
|
||||
} else if (team == MCField.MCTeam.BLUE) {
|
||||
if (blueGuardianIdToPos.containsKey(guardianId)) {
|
||||
chr.getClient().announce(CarnivalPackets.CarnivalMessage(4));
|
||||
return;
|
||||
}
|
||||
}
|
||||
int spendCp = guardian.getSpendCP();
|
||||
if (spendCp > chr.getAvailableCP()) {
|
||||
chr.getClient().announce(CarnivalPackets.CarnivalMessage(1));
|
||||
return;
|
||||
}
|
||||
|
||||
chr.getMCPQField().loseCP(chr, spendCp);
|
||||
this.map.broadcastMessage(CarnivalPackets.PlayerSummoned(MonsterCarnival.TAB_GUARDIAN, num, chr.getName()));
|
||||
numGuardiansSpawned++; // TODO: AtomicInteger this
|
||||
MCWZData.MCGuardianGenPos genPos = getRandomGuardianPos(team);
|
||||
Point spawnPos = new Point(genPos.x, genPos.y);
|
||||
|
||||
MapleReactor reactor;
|
||||
if (null == team) {
|
||||
return;
|
||||
} else switch (team) {
|
||||
case RED:
|
||||
reactor = new MapleReactor(MapleReactorFactory.getReactor(MonsterCarnival.GUARDIAN_RED), MonsterCarnival.GUARDIAN_RED);
|
||||
reactor.setPosition(spawnPos);
|
||||
redGuardianIdToPos.put(num, genPos);
|
||||
break;
|
||||
case BLUE:
|
||||
reactor = new MapleReactor(MapleReactorFactory.getReactor(MonsterCarnival.GUARDIAN_BLUE), MonsterCarnival.GUARDIAN_BLUE);
|
||||
reactor.setPosition(spawnPos);
|
||||
blueGuardianIdToPos.put(num, genPos);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
reactor.setDelay(-1);
|
||||
map.spawnReactor(reactor);
|
||||
|
||||
if (team == MCField.MCTeam.RED) {
|
||||
redReactors.put(reactor.getObjectId(), MCSkillFactory.getMCGuardian(num));
|
||||
} else {
|
||||
blueReactors.put(reactor.getObjectId(), MCSkillFactory.getMCGuardian(num));
|
||||
}
|
||||
|
||||
map.setReactorState(reactor, (byte) 1);
|
||||
updateMonsterBuffs();
|
||||
}
|
||||
|
||||
public void onGuardianHit(Player chr, MapleReactor reactor) {
|
||||
if (MonsterCarnival.DEBUG) {
|
||||
System.out.println("STATE: " + reactor.getState());
|
||||
}
|
||||
MCField.MCTeam team = chr.getMCPQTeam();
|
||||
if (team == MCField.MCTeam.RED && reactor.getId() == MonsterCarnival.GUARDIAN_RED) {
|
||||
return;
|
||||
}
|
||||
if (team == MCField.MCTeam.BLUE && reactor.getId() == MonsterCarnival.GUARDIAN_BLUE) {
|
||||
return;
|
||||
}
|
||||
reactor.setState((byte) (reactor.getState() + 1));
|
||||
map.broadcastMessage(PacketCreator.TriggerReactor(reactor, reactor.getState()));
|
||||
|
||||
if (reactor.getState() > 3) {
|
||||
int reactorObjId = reactor.getObjectId();
|
||||
map.destroyReactor(reactorObjId);
|
||||
|
||||
MCGuardian guard;
|
||||
MCWZData.MCGuardianGenPos guardianGenPos;
|
||||
if (team == MCField.MCTeam.RED) {
|
||||
guard = blueReactors.remove(reactorObjId);
|
||||
guardianGenPos = blueGuardianIdToPos.remove(guard.getType());
|
||||
} else {
|
||||
guard = redReactors.remove(reactorObjId);
|
||||
guardianGenPos = redGuardianIdToPos.remove(guard.getType());
|
||||
}
|
||||
numGuardiansSpawned--;
|
||||
|
||||
if (MonsterCarnival.DEBUG) {
|
||||
System.out.println("Removing reactor with x = " + guardianGenPos.x);
|
||||
}
|
||||
if (wzData.mapDivided) {
|
||||
if (team == MCField.MCTeam.RED) {
|
||||
originalBlueGuardianSpawns.add(guardianGenPos);
|
||||
} else {
|
||||
originalRedGuardianSpawns.add(guardianGenPos);
|
||||
}
|
||||
} else {
|
||||
originalGuardianSpawns.add(guardianGenPos);
|
||||
}
|
||||
|
||||
if (MonsterCarnival.DEBUG) {
|
||||
System.out.println("Attempting to remove buff " + guard.getName());
|
||||
}
|
||||
updateMonsterBuffs();
|
||||
}
|
||||
}
|
||||
|
||||
private MCGuardianGenPos getRandomGuardianPos(MCTeam team) {
|
||||
if (this.wzData.mapDivided) {
|
||||
if (null == team) {
|
||||
return null;
|
||||
} else switch (team) {
|
||||
case RED: {
|
||||
int randIndex = (int) Math.floor(Math.random() * this.originalRedGuardianSpawns.size());
|
||||
return originalRedGuardianSpawns.remove(randIndex);
|
||||
}
|
||||
case BLUE: {
|
||||
int randIndex = (int) Math.floor(Math.random() * this.originalBlueGuardianSpawns.size());
|
||||
return originalBlueGuardianSpawns.remove(randIndex);
|
||||
}
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
int randIndex = (int) Math.floor(Math.random() * this.originalGuardianSpawns.size());
|
||||
return originalGuardianSpawns.remove(randIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private MCMobGenPos getRandomSpawnPos(MCTeam team) {
|
||||
List<MCMobGenPos> lst = null;
|
||||
if (this.wzData.mapDivided) {
|
||||
if (null == team) {
|
||||
return null;
|
||||
} else switch (team) {
|
||||
case RED:
|
||||
lst = originalRedSpawns;
|
||||
break;
|
||||
case BLUE:
|
||||
lst = originalBlueSpawns;
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
lst = originalUnifiedSpawns;
|
||||
}
|
||||
|
||||
if (lst == null) {
|
||||
return null;
|
||||
}
|
||||
if (lst.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
int randIndex = (int) Math.floor(Math.random() * lst.size());
|
||||
return lst.remove(randIndex);
|
||||
}
|
||||
|
||||
private void updateMonsterBuffs() {
|
||||
List<MCGuardian> redGuardians = new ArrayList<>();
|
||||
List<MCGuardian> blueGuardians = new ArrayList<>();
|
||||
|
||||
for (MCGuardian g : this.redReactors.values()) {
|
||||
redGuardians.add(g);
|
||||
if (MonsterCarnival.DEBUG) {
|
||||
System.out.println("update buff red " + g.getMobSkillID());
|
||||
}
|
||||
}
|
||||
for (MCGuardian g : this.blueReactors.values()) {
|
||||
blueGuardians.add(g);
|
||||
if (MonsterCarnival.DEBUG) {
|
||||
System.out.println("update buff blue " + g.getMobSkillID());
|
||||
}
|
||||
}
|
||||
|
||||
for (FieldObject mmo : map.getAllMonsters()) {
|
||||
if (mmo.getType() == FieldObjectType.MONSTER) {
|
||||
MapleMonster mob = ((MapleMonster) mmo);
|
||||
mob.dispel();
|
||||
|
||||
if (mob.getTeam() == MCField.MCTeam.RED.code) {
|
||||
applyGuardians(mob, redGuardians);
|
||||
} else if (mob.getTeam() == MCField.MCTeam.BLUE.code) {
|
||||
applyGuardians(mob, blueGuardians);
|
||||
} else {
|
||||
MCTracker.log("[MCPQ] Attempting to give guardians to mob without team.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void giveMonsterBuffs(MapleMonster mob) {
|
||||
List<MCGuardian> redGuardians = new ArrayList<>();
|
||||
List<MCGuardian> blueGuardians = new ArrayList<>();
|
||||
|
||||
for (MCGuardian g : this.redReactors.values()) {
|
||||
redGuardians.add(g);
|
||||
if (MonsterCarnival.DEBUG) {
|
||||
System.out.println("update buff red " + g.getMobSkillID());
|
||||
}
|
||||
}
|
||||
for (MCGuardian g : this.blueReactors.values()) {
|
||||
blueGuardians.add(g);
|
||||
if (MonsterCarnival.DEBUG) {
|
||||
System.out.println("update buff blue " + g.getMobSkillID());
|
||||
}
|
||||
}
|
||||
|
||||
if (mob.getTeam() == MCField.MCTeam.RED.code) {
|
||||
applyGuardians(mob, redGuardians);
|
||||
} else if (mob.getTeam() == MCField.MCTeam.BLUE.code) {
|
||||
applyGuardians(mob, blueGuardians);
|
||||
} else {
|
||||
MCTracker.log("[MCPQ] Attempting to give guardians to mob without team.");
|
||||
}
|
||||
}
|
||||
|
||||
private void applyGuardians(MapleMonster mob, List<MCGuardian> guardians) {
|
||||
for (MCGuardian g : guardians) {
|
||||
MobSkill sk = MobSkillFactory.getMobSkill(g.getMobSkillID(), g.getLevel());
|
||||
sk.applyEffect(null, mob, true);
|
||||
}
|
||||
}
|
||||
|
||||
public void spawningTask() {
|
||||
for (SpawnPoint sp : originalSpawns) {
|
||||
if (sp.shouldSpawn()) {
|
||||
MapleMonster mob = sp.spawnMonster(this.map);
|
||||
giveMonsterBuffs(mob);
|
||||
}
|
||||
}
|
||||
for (SpawnPoint sp : addedSpawns) {
|
||||
if (sp.shouldSpawn()) {
|
||||
MapleMonster mob = sp.spawnMonster(this.map);
|
||||
giveMonsterBuffs(mob);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,861 +0,0 @@
|
||||
/*
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package server.partyquest.mcpq;
|
||||
|
||||
import handling.channel.ChannelServer;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import packet.creators.CarnivalPackets;
|
||||
import packet.creators.EffectPackets;
|
||||
import packet.creators.PacketCreator;
|
||||
import packet.transfer.write.OutPacket;
|
||||
import client.player.Player;
|
||||
import server.MapleStatEffect;
|
||||
import server.itens.MapleItemInformationProvider;
|
||||
import server.maps.Field;
|
||||
import server.maps.FieldItem;
|
||||
import server.maps.reactors.MapleReactor;
|
||||
import server.maps.portal.Portal;
|
||||
import tools.TimerTools.EventTimer;
|
||||
|
||||
/**
|
||||
* Keeps track of a specific field (1-6). Handles all packet broadcasting, etc.
|
||||
* @author s4nta
|
||||
*/
|
||||
public class MCField {
|
||||
|
||||
/**
|
||||
* Different teams for MCPQ.
|
||||
*/
|
||||
public enum MCTeam {
|
||||
RED(0),
|
||||
BLUE(1),
|
||||
NONE(-1);
|
||||
public final int code;
|
||||
|
||||
MCTeam(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public final int getEnemyTeamCode() {
|
||||
return Math.abs(this.code - 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the current state of the field.
|
||||
*/
|
||||
public enum MCState {
|
||||
LOBBY,
|
||||
BATTLE,
|
||||
END;
|
||||
}
|
||||
|
||||
/**
|
||||
* Keys to access different map instances relating to this field.
|
||||
*/
|
||||
public enum MCMaps {
|
||||
LOBBY(0),
|
||||
BATTLEFIELD(1),
|
||||
RESURRECT(2),
|
||||
VICTORY(3),
|
||||
DEFEAT(4),
|
||||
NONE(-1);
|
||||
private final int code;
|
||||
|
||||
MCMaps(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public static MCMaps getByCode(int code) {
|
||||
for (MCMaps m : values()) {
|
||||
if (m.code == code) {
|
||||
return m;
|
||||
}
|
||||
}
|
||||
return NONE;
|
||||
}
|
||||
}
|
||||
|
||||
private int arena;
|
||||
private ChannelServer cserv;
|
||||
private MCParty red, blue;
|
||||
private List<MCParty> requests = new ArrayList<>();
|
||||
private MCState state;
|
||||
private Map<MCMaps, Field> mapInstances = new HashMap<>();
|
||||
private long startTime;
|
||||
private MCBattlefield battlefield;
|
||||
|
||||
// Timer Tasks
|
||||
private ScheduledFuture<?> acceptRequestsTask, validateRoomTask, startBattleTask,
|
||||
validateBattleTask, runBattleTask, endBattleTask,
|
||||
spawnMonstersTask;
|
||||
|
||||
public MCField(int arena, ChannelServer cserv, MCParty red, MCParty blue) {
|
||||
this.arena = arena;
|
||||
this.cserv = cserv;
|
||||
this.red = red;
|
||||
this.blue = blue;
|
||||
this.state = MCState.LOBBY;
|
||||
}
|
||||
|
||||
public boolean isFull() {
|
||||
if (MonsterCarnival.DEBUG) {
|
||||
return false;
|
||||
}
|
||||
return this.red != null && this.blue != null;
|
||||
}
|
||||
|
||||
public boolean needsRequest() {
|
||||
return this.red != null && this.blue == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the state of the field, warping out players and resetting tasks.
|
||||
* [MENTION=2000183830]para[/MENTION]m warpPlayers Warp out players or not
|
||||
* @param warpPlayers
|
||||
*/
|
||||
public void deregister(boolean warpPlayers) {
|
||||
if (warpPlayers) {
|
||||
if (this.red != null) {
|
||||
this.red.deregisterPlayers();
|
||||
}
|
||||
if (this.blue != null) {
|
||||
this.blue.deregisterPlayers();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.red = null;
|
||||
this.blue = null;
|
||||
this.requests.clear();
|
||||
this.state = MCState.LOBBY;
|
||||
|
||||
if (this.acceptRequestsTask != null) {
|
||||
this.acceptRequestsTask.cancel(true);
|
||||
this.acceptRequestsTask = null;
|
||||
}
|
||||
|
||||
if (this.validateRoomTask != null) {
|
||||
this.validateRoomTask.cancel(true);
|
||||
this.validateRoomTask = null;
|
||||
}
|
||||
|
||||
if (this.startBattleTask != null) {
|
||||
this.startBattleTask.cancel(true);
|
||||
this.startBattleTask = null;
|
||||
}
|
||||
|
||||
if (this.endBattleTask != null) {
|
||||
this.endBattleTask.cancel(true);
|
||||
this.endBattleTask = null;
|
||||
}
|
||||
|
||||
if (this.runBattleTask != null) {
|
||||
this.runBattleTask.cancel(true);
|
||||
this.runBattleTask = null;
|
||||
}
|
||||
|
||||
if (this.validateBattleTask != null) {
|
||||
this.validateBattleTask.cancel(true);
|
||||
this.validateBattleTask = null;
|
||||
}
|
||||
|
||||
if (this.spawnMonstersTask != null) {
|
||||
this.spawnMonstersTask.cancel(true);
|
||||
this.spawnMonstersTask = null;
|
||||
}
|
||||
|
||||
for (MCMaps mapType : MCMaps.values()) {
|
||||
this.mapInstances.remove(mapType);
|
||||
}
|
||||
}
|
||||
|
||||
public MCParty getRed() {
|
||||
return red;
|
||||
}
|
||||
|
||||
public MCParty getBlue() {
|
||||
return blue;
|
||||
}
|
||||
|
||||
public void announce(OutPacket pkt) {
|
||||
if (this.red != null) {
|
||||
red.broadcast(pkt);
|
||||
} else {
|
||||
MCTracker.log("[MCPQ] Trying to announce packet to red when it is null.");
|
||||
}
|
||||
|
||||
if (this.blue != null) {
|
||||
blue.broadcast(pkt);
|
||||
} else {
|
||||
MCTracker.log("[MCPQ] Trying to announce packet to blue when it is null.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a string representing the status of this room for the Spiegelmann NPC.
|
||||
* [MENTION=850422]return[/MENTION] String representing the room's status.
|
||||
* @return
|
||||
*/
|
||||
public String getStatus() {
|
||||
if (isFull()) {
|
||||
return "";
|
||||
}
|
||||
if (this.state != MCState.LOBBY) {
|
||||
return "";
|
||||
}
|
||||
String waitingParty = "";
|
||||
if (this.red != null) {
|
||||
String fmt = " <Party Size: %d, Average Level: %d>";
|
||||
waitingParty = String.format(fmt, this.red.getSize(), this.red.getAverageLevel());
|
||||
}
|
||||
String fmt = "#L%d#Carnival Field %d%s#l\r\n";
|
||||
return String.format(fmt, this.arena, this.arena, waitingParty);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to register a party in this field. If success, then all players in the party
|
||||
* will be warped to the waiting lobby. All players in the party will also have relevant
|
||||
* CPQ information assigned to them.
|
||||
*
|
||||
* [MENTION=2000183830]para[/MENTION]m party The party to register.
|
||||
*/
|
||||
public void register(MCParty party, MCTeam team) {
|
||||
if (this.red == null && team == MCTeam.RED) {
|
||||
party.setTeam(team);
|
||||
this.red = party;
|
||||
} else if (this.blue == null && team == MCTeam.BLUE) {
|
||||
party.setTeam(team);
|
||||
this.blue = party;
|
||||
} else {
|
||||
MCTracker.log("Attempting to register party when team is already set.");
|
||||
return;
|
||||
}
|
||||
party.setField(this);
|
||||
party.updatePlayers();
|
||||
party.warp(MCMaps.LOBBY);
|
||||
onPartyRegistered(party, team);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a challenge to the party in this field.
|
||||
*
|
||||
* [MENTION=2000183830]para[/MENTION]m party The party requesting a challenge.
|
||||
*/
|
||||
public void request(MCParty party) {
|
||||
if (this.red == null) {
|
||||
MCTracker.log("Attempting to request when waiting team is null.");
|
||||
this.deregister(true);
|
||||
return;
|
||||
}
|
||||
requests.add(party);
|
||||
this.red.notice("[MCPQ] A challenge has arrived! Click on the Assistant in your room to view it.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts a challenge from a team.
|
||||
* [MENTION=2000183830]para[/MENTION]m index Index of team in requests.
|
||||
* [MENTION=850422]return[/MENTION] 1 if the challenge was accepted successfully, 0 otherwise.
|
||||
*/
|
||||
public int acceptRequest(int index) {
|
||||
MCParty toAccept = this.requests.get(index);
|
||||
register(toAccept, MCTeam.BLUE);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for pending requests.
|
||||
*
|
||||
* [MENTION=850422]return[/MENTION] True if there are pending requests.
|
||||
*/
|
||||
public boolean hasPendingRequests() {
|
||||
return requests.size() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a pending list of requests, formatted for use in a NPC. Also cleans up the requests,
|
||||
* getting rid of MCParties that no longer exist.
|
||||
*
|
||||
* [MENTION=850422]return[/MENTION] Formatted list of requests for NPC.
|
||||
* @return
|
||||
*/
|
||||
public String getNPCRequestString() {
|
||||
StringBuilder sb = new StringBuilder("Here is the list of pending requests:\r\n\r\n#b");
|
||||
for (MCParty pty : requests) {
|
||||
if (!pty.exists()) {
|
||||
continue;
|
||||
}
|
||||
sb.append("#L").append(requests.indexOf(pty)).append("#");
|
||||
String fmt = "<Party Size: %d, Average Level: %d>";
|
||||
fmt = String.format(fmt, pty.getSize(), pty.getAverageLevel());
|
||||
sb.append(fmt);
|
||||
sb.append("#l\r\n");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a R3 minute waiting timer in the lobby for teams to accept requests.
|
||||
* If the timer completes the countdown, teams are deregistered and sent back to the lobby.
|
||||
*/
|
||||
private void startLobbyTask(MCParty host) {
|
||||
host.clock(MonsterCarnival.TIME_LOBBYWAIT);
|
||||
this.acceptRequestsTask = EventTimer.getInstance().schedule(new AcceptingRequestsTask(this, host), 1000 * MonsterCarnival.TIME_LOBBYWAIT); // 3 minutes
|
||||
this.validateRoomTask = EventTimer.getInstance().register(new ValidateLobbyTask(this), 1000, 1000); // repeat every second
|
||||
}
|
||||
|
||||
/**
|
||||
* Event handling for when a team registers.
|
||||
*
|
||||
* [MENTION=2000183830]para[/MENTION]m party Party that registers.
|
||||
* [MENTION=2000183830]para[/MENTION]m team Team of party.
|
||||
*/
|
||||
private void onPartyRegistered(MCParty party, MCTeam team) {
|
||||
if (team == MCTeam.RED) {
|
||||
startLobbyTask(party);
|
||||
}
|
||||
if (team == MCTeam.BLUE) { // both teams are in
|
||||
this.validateRoomTask.cancel(true);
|
||||
this.acceptRequestsTask.cancel(true);
|
||||
blue.clock(10);
|
||||
red.clock(10);
|
||||
|
||||
this.startBattleTask = EventTimer.getInstance().schedule(new GoBattlefieldTask(this), 1000 * 10); // 10 seconds
|
||||
|
||||
red.notice("[MCPQ] The Carnival PQ will start in 10 seconds!");
|
||||
blue.notice("[MCPQ] The Carnival PQ will start in 10 seconds!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Warps both parties in the field to the battlefield map.
|
||||
*/
|
||||
private void goBattle() {
|
||||
Field map = getMap(MCMaps.BATTLEFIELD);
|
||||
if (MonsterCarnival.DEBUG)
|
||||
System.out.println("warping to battle " + map + " " + map.getId());
|
||||
if (red != null) {
|
||||
red.warp(map, "red00");
|
||||
} else {
|
||||
MCTracker.log("[MCPQ] Trying to warp red party when it is null.");
|
||||
}
|
||||
|
||||
if (blue != null) {
|
||||
blue.warp(map, "blue00");
|
||||
} else {
|
||||
MCTracker.log("[MCPQ] Trying to warp blue party when it is null.");
|
||||
}
|
||||
|
||||
red.clock(MonsterCarnival.TIME_PREBATTLE);
|
||||
blue.clock(MonsterCarnival.TIME_PREBATTLE);
|
||||
|
||||
red.notice("[MCPQ] The battle will start in 10 seconds!");
|
||||
blue.notice("[MCPQ] The battle will start in 10 seconds!");
|
||||
|
||||
startBattleTask = EventTimer.getInstance().schedule(new BeginCarnivalTask(this), 1000 * MonsterCarnival.TIME_PREBATTLE); // 10 seconds
|
||||
|
||||
validateBattleTask = EventTimer.getInstance().register(new ValidateBattlefieldTask(this), 1000, 500); // check every second
|
||||
|
||||
battlefield = new MCBattlefield(getMap(MCMaps.BATTLEFIELD));
|
||||
|
||||
red.setEnemy(blue);
|
||||
blue.setEnemy(red);
|
||||
}
|
||||
|
||||
private void beginCarnival() {
|
||||
red.clock(MonsterCarnival.TIME_BATTLE);
|
||||
blue.clock(MonsterCarnival.TIME_BATTLE);
|
||||
startTime = System.currentTimeMillis();
|
||||
|
||||
getMap(MCMaps.BATTLEFIELD).broadcastMessage(PacketCreator.ServerNotice(6, "[MCPQ] You have 10 minutes to kill monsters!"));
|
||||
|
||||
endBattleTask = EventTimer.getInstance().schedule(new EndBattleTask(this), 1000 * MonsterCarnival.TIME_BATTLE);
|
||||
spawnMonstersTask = EventTimer.getInstance().register(new SpawnTask(this.battlefield), 1000 * 5);
|
||||
|
||||
}
|
||||
|
||||
public void endBattle(MCParty winner, MCParty loser) {
|
||||
endBattle(winner, loser, false);
|
||||
}
|
||||
|
||||
public void endBattle(MCParty winner, MCParty loser, boolean abnormal) {
|
||||
// TODO: Abnormal win codes to prevent exploits
|
||||
|
||||
validateBattleTask.cancel(true);
|
||||
spawnMonstersTask.cancel(true);
|
||||
|
||||
MCWZData cpqData = this.getMap(MCMaps.BATTLEFIELD).getMCPQData();
|
||||
String effectWin = cpqData.effectWin;
|
||||
String effectLose = cpqData.effectLose;
|
||||
String soundWin = cpqData.soundWin;
|
||||
String soundLose = cpqData.soundLose;
|
||||
|
||||
winner.broadcast(EffectPackets.ShowEffect(effectWin));
|
||||
winner.broadcast(EffectPackets.PlaySound(soundWin));
|
||||
loser.broadcast(EffectPackets.ShowEffect(effectLose));
|
||||
loser.broadcast(EffectPackets.PlaySound(soundLose));
|
||||
|
||||
this.getMap(MCMaps.BATTLEFIELD).killAllMonsters(false);
|
||||
this.getMap(MCMaps.BATTLEFIELD).clearDrops();
|
||||
this.deregister(false);
|
||||
|
||||
EventTimer.getInstance().schedule(new WarpEndBattleTask(this, winner, loser), 1000 * 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles CP gain and packet updates when a monster is killed.
|
||||
* [MENTION=2000183830]para[/MENTION]m chr Character that kills the monster.
|
||||
* [MENTION=2000183830]para[/MENTION]m cp CP gained.
|
||||
*/
|
||||
public void monsterKilled(Player chr, int cp) {
|
||||
if (MonsterCarnival.DEBUG) {
|
||||
// System.out.println(chr.getName() + " killed for +" + cp + " CP");
|
||||
}
|
||||
// TODO: Personal stats for CP gain
|
||||
this.gainCP(chr, cp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles game logic and packet broadcasting for CP gain.
|
||||
* Broadcasts personal CP update to chr, and broadcasts party CP update
|
||||
* to the entire field.
|
||||
*
|
||||
* [MENTION=2000183830]para[/MENTION]m chr Character that gains CP.
|
||||
* [MENTION=2000183830]para[/MENTION]m cp CP gained.
|
||||
*/
|
||||
public void gainCP(Player chr, int cp) {
|
||||
if (cp < 0) {
|
||||
MCTracker.log("[MCPQ] Adding negative CP.");
|
||||
if (MonsterCarnival.DEBUG) {
|
||||
System.out.println("Adding negative CP: stacktrace");
|
||||
new Exception().printStackTrace();
|
||||
}
|
||||
}
|
||||
MCParty pty = chr.getMCPQParty();
|
||||
chr.gainCP(cp);
|
||||
pty.gainCP(cp);
|
||||
chr.getClient().announce(CarnivalPackets.UpdatePersonalCP(chr));
|
||||
this.announce(CarnivalPackets.UpdatePartyCP(pty));
|
||||
}
|
||||
|
||||
/**
|
||||
* Subtracts from available CP while leaving total CP untouched.
|
||||
*
|
||||
* [MENTION=2000183830]para[/MENTION]m chr Character that loses CP.
|
||||
* [MENTION=2000183830]para[/MENTION]m cp CP lost (should be positive number).
|
||||
*/
|
||||
public void loseCP(Player chr, int cp) {
|
||||
if (cp < 0) {
|
||||
MCTracker.log("[MCPQ] Losing negative CP.");
|
||||
if (MonsterCarnival.DEBUG) {
|
||||
System.out.println("Adding negative CP: stacktrace");
|
||||
new Exception().printStackTrace();
|
||||
}
|
||||
}
|
||||
MCParty pty = chr.getMCPQParty();
|
||||
chr.loseCP(cp);
|
||||
pty.loseCP(cp);
|
||||
chr.getClient().announce(CarnivalPackets.UpdatePersonalCP(chr));
|
||||
this.announce(CarnivalPackets.UpdatePartyCP(pty));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a player looting an item.
|
||||
* [MENTION=2000183830]para[/MENTION]m player Player that picked up the object.
|
||||
* [MENTION=2000183830]para[/MENTION]m mapitem Object picked up.
|
||||
*
|
||||
* [MENTION=850422]return[/MENTION] True if pickup was successful, false otherwise.
|
||||
*/
|
||||
public boolean onItemPickup(Player player, FieldItem mapitem) {
|
||||
if (mapitem == null) {
|
||||
MCTracker.log("[MCPQ] Attempting to loot null object.");
|
||||
return false;
|
||||
}
|
||||
int itemid = mapitem.getItem().getItemId();
|
||||
if (!MonsterCarnival.isCPQConsumeItem(itemid)) {
|
||||
return false;
|
||||
}
|
||||
MCParty pty = player.getMCPQParty();
|
||||
MapleItemInformationProvider ii = MapleItemInformationProvider.getInstance();
|
||||
MapleStatEffect itemEffect = ii.getItemEffect(itemid);
|
||||
if (!itemEffect.isConsumeOnPickup()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (itemEffect.isParty()) {
|
||||
for (Player chr : pty.getMembers()) {
|
||||
if (chr.getStat().getCurrentHp() > 0) {
|
||||
itemEffect.applyTo(chr);
|
||||
}
|
||||
}
|
||||
} else { // Single Target Item
|
||||
itemEffect.applyTo(player);
|
||||
}
|
||||
// Status items
|
||||
if (itemEffect.getNuffSkill() != -1) {
|
||||
MCSkill debuff = MCSkillFactory.getMCSkill(itemEffect.getNuffSkill());
|
||||
if (debuff == null) {
|
||||
MCTracker.log("[MCPQ] debuff skill is null " + itemEffect.getNuffSkill());
|
||||
return false;
|
||||
}
|
||||
|
||||
pty.getEnemy().applyMCSkill(debuff);
|
||||
}
|
||||
|
||||
if (itemEffect.getCP() > 0) {
|
||||
this.gainCP(player, itemEffect.getCP());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void onPlayerRespawn(Player player) {
|
||||
int cpLoss = Math.min(player.getAvailableCP(), MonsterCarnival.CP_LOSS_ON_DEATH);
|
||||
this.announce(CarnivalPackets.PlayerDiedMessage(player, cpLoss));
|
||||
this.loseCP(player, cpLoss);
|
||||
player.getStat().addMPHP(30000, 30000);
|
||||
player.changeMap(this.getMap(MCMaps.RESURRECT), this.getMap(MCMaps.RESURRECT).getPortal(0));
|
||||
player.getClient().getSession().write(PacketCreator.GetClock(getTimeRemaining()));
|
||||
player.getClient().getSession().write(CarnivalPackets.StartMonsterCarnival(player));
|
||||
}
|
||||
|
||||
public void onPlayerDisconnected(Player player) {
|
||||
MCParty pty = player.getMCPQParty();
|
||||
if (pty != null) {
|
||||
pty.removePlayer(player);
|
||||
} else {
|
||||
MCTracker.log("[MCPQ] Attempting to run player disconnect event when party is null for character " + player.getName());
|
||||
}
|
||||
}
|
||||
|
||||
public void onAddSpawn(Player chr, int num) {
|
||||
if (this.battlefield != null) {
|
||||
battlefield.addSpawn(chr, num);
|
||||
} else {
|
||||
MCTracker.log("[MCPQ] Summoning guardian with null battlefield.");
|
||||
}
|
||||
}
|
||||
|
||||
public void onUseSkill(Player chr, int num) {
|
||||
if (this.battlefield != null) {
|
||||
battlefield.useSkill(chr, num);
|
||||
} else {
|
||||
MCTracker.log("[MCPQ] Summoning guardian with null battlefield.");
|
||||
}
|
||||
}
|
||||
|
||||
public void onGuardianSummon(Player chr, int num) {
|
||||
if (this.battlefield != null) {
|
||||
battlefield.spawnGuardian(chr, num);
|
||||
} else {
|
||||
MCTracker.log("[MCPQ] Summoning guardian with null battlefield.");
|
||||
}
|
||||
}
|
||||
|
||||
public void onGuardianHit(Player chr, MapleReactor reactor) {
|
||||
if (this.battlefield != null) {
|
||||
battlefield.onGuardianHit(chr, reactor);
|
||||
} else {
|
||||
MCTracker.log("[MCPQ] Hitting reactor with null battlefield.");
|
||||
}
|
||||
}
|
||||
|
||||
public void onRevive(Player player) {
|
||||
MCTeam team = player.getMCPQTeam();
|
||||
Portal portal;
|
||||
if (team == MCTeam.RED) {
|
||||
portal = getMap(MCMaps.BATTLEFIELD).getPortal("red_revive");
|
||||
} else {
|
||||
portal = getMap(MCMaps.BATTLEFIELD).getPortal("blue_revive");
|
||||
}
|
||||
|
||||
player.changeMap(getMap(MCMaps.BATTLEFIELD), portal);
|
||||
player.getClient().getSession().write(PacketCreator.GetClock(getTimeRemaining()));
|
||||
player.getClient().getSession().write(CarnivalPackets.StartMonsterCarnival(player));
|
||||
}
|
||||
|
||||
public int getTimeRemaining() {
|
||||
// TODO: add support for setting an explicit endTime instead of using the hack with MonsterCarnival variables
|
||||
return (int) ((startTime + 1000 * MonsterCarnival.TIME_BATTLE) - System.currentTimeMillis()) / 1000;
|
||||
}
|
||||
|
||||
|
||||
// Map Instances
|
||||
|
||||
/**
|
||||
* Returns the map instance for a requested map. Creates a new map instance if unavailable.
|
||||
* [MENTION=2000183830]para[/MENTION]m type Map instance to return.
|
||||
* [MENTION=850422]return[/MENTION] The instanced map.
|
||||
*/
|
||||
public Field getMap(MCMaps type) {
|
||||
if (this.mapInstances.containsKey(type)) {
|
||||
return this.mapInstances.get(type);
|
||||
}
|
||||
return createInstanceMap(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to create an instanced map, based on the type passed in. Also creates a mapping in
|
||||
* this.mapInstances.
|
||||
*
|
||||
* [MENTION=2000183830]para[/MENTION]m type Type of map to generate.
|
||||
* [MENTION=850422]return[/MENTION] MapleMap for the instanced map if type is supported, otherwise null.
|
||||
*/
|
||||
private Field createInstanceMap(MCMaps type) {
|
||||
int mapid = -1;
|
||||
switch (type) {
|
||||
case LOBBY:
|
||||
mapid = MonsterCarnival.getLobbyMap(this.arena);
|
||||
break;
|
||||
case BATTLEFIELD:
|
||||
mapid = MonsterCarnival.getBattleFieldMap(this.arena);
|
||||
break;
|
||||
case RESURRECT:
|
||||
mapid = MonsterCarnival.getResurrectionMap(this.arena);
|
||||
break;
|
||||
case VICTORY:
|
||||
mapid = MonsterCarnival.getVictoriousMap(this.arena);
|
||||
break;
|
||||
case DEFEAT:
|
||||
mapid = MonsterCarnival.getDefeatedMap(this.arena);
|
||||
break;
|
||||
}
|
||||
if (mapid == -1) return null;
|
||||
Field mapInstance = this.cserv.getMapFactory().instanceMap(mapid, true, true);
|
||||
this.mapInstances.put(type, mapInstance);
|
||||
return mapInstance;
|
||||
}
|
||||
|
||||
// Timer Tasks
|
||||
|
||||
public class ValidateLobbyTask implements Runnable {
|
||||
|
||||
private final MCField field;
|
||||
|
||||
/**
|
||||
* Timer task to ensure all players are on the right field.
|
||||
* If anything is wrong with the parties, the field is deregistered.
|
||||
* [MENTION=2000183830]para[/MENTION]m field Field to run the validation task on.
|
||||
* @param field
|
||||
*/
|
||||
public ValidateLobbyTask(MCField field) {
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (this.field.red == null) {
|
||||
this.field.deregister(true);
|
||||
return;
|
||||
}
|
||||
for (Player c : field.red.getMembers()) {
|
||||
if (c.getMap() != field.getMap(MCMaps.LOBBY)) {
|
||||
this.field.deregister(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (this.field.blue != null) {
|
||||
for (Player c : field.blue.getMembers()) {
|
||||
if (c.getMap() != field.getMap(MCMaps.LOBBY)) {
|
||||
this.field.deregister(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ValidateBattlefieldTask implements Runnable {
|
||||
|
||||
private final MCField field;
|
||||
|
||||
/**
|
||||
* Timer task to ensure all players are on the right field.
|
||||
* If anything is wrong with the parties, the field is deregistered.
|
||||
* [MENTION=2000183830]para[/MENTION]m field Field to run the validation task on.
|
||||
*/
|
||||
|
||||
public ValidateBattlefieldTask(MCField field) {
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (this.field.red == null || field.red.getSize() == 0) {
|
||||
MCTracker.log("[MCPQ] Red team null when validating battlefield");
|
||||
field.endBattle(blue, red);
|
||||
return;
|
||||
}
|
||||
Collection<Player> members = Collections.unmodifiableCollection(field.red.getMembers());
|
||||
for (Player c : members) {
|
||||
if (c.getMap() != field.getMap(MCMaps.BATTLEFIELD) && c.getMap() != field.getMap(MCMaps.RESURRECT)) {
|
||||
this.field.announce(CarnivalPackets.CarnivalLeave(MCTeam.RED.code, c.getName()));
|
||||
red.removePlayer(c); // TODO: fix concurrent modification
|
||||
}
|
||||
if (c.getMap() == field.getMap(MCMaps.BATTLEFIELD) && !c.isAlive()) {
|
||||
this.field.onPlayerRespawn(c);
|
||||
}
|
||||
}
|
||||
if (this.field.blue == null || field.blue.getSize() == 0) {
|
||||
MCTracker.log("[MCPQ] Blue team null when validating battlefield");
|
||||
field.endBattle(red, blue);
|
||||
return;
|
||||
}
|
||||
members = Collections.unmodifiableCollection(field.blue.getMembers());
|
||||
for (Player c : members) {
|
||||
if (c.getMap() != field.getMap(MCMaps.BATTLEFIELD) && c.getMap() != field.getMap(MCMaps.RESURRECT)) {
|
||||
this.field.announce(CarnivalPackets.CarnivalLeave(MCTeam.BLUE.code, c.getName()));
|
||||
blue.removePlayer(c);
|
||||
}
|
||||
if (c.getMap() == field.getMap(MCMaps.BATTLEFIELD) && !c.isAlive()) {
|
||||
this.field.onPlayerRespawn(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class AcceptingRequestsTask implements Runnable {
|
||||
|
||||
private final MCField field;
|
||||
private final MCParty host;
|
||||
|
||||
/**
|
||||
* Runs a task that counts down for 3 minutes, then warps the hosting party out.
|
||||
*
|
||||
* [MENTION=2000183830]para[/MENTION]m field Field to accept requests on.
|
||||
* [MENTION=2000183830]para[/MENTION]m host Hosting party that will be warped out if they do not accept a request
|
||||
* within 3 minutes.
|
||||
*/
|
||||
public AcceptingRequestsTask(MCField field, MCParty host) {
|
||||
this.field = field;
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Collection<Player> chrs = this.host.getMembers();
|
||||
for (Player c : chrs) {
|
||||
c.changeMap(MonsterCarnival.MAP_LOBBY);
|
||||
}
|
||||
this.field.deregister(true);
|
||||
}
|
||||
}
|
||||
|
||||
public class GoBattlefieldTask implements Runnable {
|
||||
|
||||
private final MCField field;
|
||||
|
||||
public GoBattlefieldTask(MCField field) {
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
field.goBattle();
|
||||
|
||||
field.red.startBattle();
|
||||
field.blue.startBattle();
|
||||
|
||||
field.state = MCState.BATTLE;
|
||||
}
|
||||
}
|
||||
|
||||
public class BeginCarnivalTask implements Runnable {
|
||||
|
||||
private final MCField field;
|
||||
|
||||
public BeginCarnivalTask(MCField field) {
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Field map = field.getMap(MCMaps.BATTLEFIELD);
|
||||
map.beginSpawning();
|
||||
field.beginCarnival();
|
||||
}
|
||||
}
|
||||
|
||||
/* I have no idea why this doesn't work normally :/ */
|
||||
public class SpawnTask implements Runnable {
|
||||
|
||||
private final MCBattlefield battleMap;
|
||||
|
||||
public SpawnTask(MCBattlefield field) {
|
||||
this.battleMap = field;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
// TODO: adjust spawn rates based on cp
|
||||
battleMap.spawningTask();
|
||||
}
|
||||
}
|
||||
|
||||
public class EndBattleTask implements Runnable {
|
||||
private final MCField field;
|
||||
|
||||
public EndBattleTask(MCField field) {
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
MCParty winner, loser;
|
||||
if (field.red.getTotalCP() > field.blue.getTotalCP()) {
|
||||
winner = field.red;
|
||||
loser = field.blue;
|
||||
} else if (field.red.getTotalCP() < field.blue.getTotalCP()) {
|
||||
winner = field.blue;
|
||||
loser = field.red;
|
||||
} else {
|
||||
// if tied: random chance
|
||||
// TODO: proper extension of time
|
||||
if (Math.random() < .5) {
|
||||
winner = field.red;
|
||||
loser = field.blue;
|
||||
} else {
|
||||
winner = field.blue;
|
||||
loser = field.red;
|
||||
}
|
||||
}
|
||||
|
||||
field.state = MCState.END;
|
||||
field.endBattle(winner, loser);
|
||||
}
|
||||
}
|
||||
|
||||
public class WarpEndBattleTask implements Runnable {
|
||||
|
||||
private final MCField field;
|
||||
private final MCParty winner, loser;
|
||||
|
||||
public WarpEndBattleTask(MCField field, MCParty winner, MCParty loser) {
|
||||
this.field = field;
|
||||
this.winner = winner;
|
||||
this.loser = loser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
winner.warp(field.getMap(MCMaps.VICTORY));
|
||||
loser.warp(field.getMap(MCMaps.DEFEAT));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/*
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package server.partyquest.mcpq;
|
||||
|
||||
/**
|
||||
* Object representing MCGuardian in Skill.wz/MCGuardian.img.
|
||||
*
|
||||
* @author s4nta
|
||||
*/
|
||||
|
||||
public class MCGuardian {
|
||||
private final int type, spendCP, mobSkillID, level;
|
||||
private String name, desc;
|
||||
|
||||
public MCGuardian(int type, int spendCP, int mobSkillID, int level) {
|
||||
this.type = type;
|
||||
this.mobSkillID = mobSkillID;
|
||||
this.level = level;
|
||||
this.spendCP = spendCP;
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public int getSpendCP() {
|
||||
return spendCP;
|
||||
}
|
||||
|
||||
public int getMobSkillID() {
|
||||
return mobSkillID;
|
||||
}
|
||||
|
||||
public int getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public void setDesc(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
}
|
||||
@@ -1,326 +0,0 @@
|
||||
/*
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package server.partyquest.mcpq;
|
||||
|
||||
import community.MapleParty;
|
||||
import community.MaplePartyCharacter;
|
||||
import handling.channel.ChannelServer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import packet.creators.CarnivalPackets;
|
||||
import packet.creators.PacketCreator;
|
||||
import packet.transfer.write.OutPacket;
|
||||
import client.player.Player;
|
||||
import client.player.buffs.Disease;
|
||||
import server.life.MobSkill;
|
||||
import server.life.MobSkillFactory;
|
||||
import server.maps.Field;
|
||||
import server.partyquest.mcpq.MCField.MCTeam;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sammy Guergachi <sguergachi at gmail.com>
|
||||
*/
|
||||
/**
|
||||
* Provides an interface for Monster Carnival-specific party methods and variables.
|
||||
*
|
||||
* @author s4nta
|
||||
*/
|
||||
public class MCParty {
|
||||
|
||||
private MapleParty party;
|
||||
private List<Player> characters = new ArrayList<>();
|
||||
private int availCP = 0;
|
||||
private int totalCP = 0;
|
||||
private MCField.MCTeam team = MCField.MCTeam.NONE;
|
||||
private MCField field;
|
||||
private MCParty enemy;
|
||||
|
||||
public MCParty(MapleParty party) {
|
||||
this.party = party;
|
||||
for (MaplePartyCharacter chr : party.getMembers()) {
|
||||
if (!chr.isOnline()) continue;
|
||||
Player c = ChannelServer.getInstance(chr.getChannel()).getPlayerStorage().getCharacterById(chr.getId());
|
||||
|
||||
characters.add(c);
|
||||
}
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return this.characters.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the underlying MapleParty still exists in the same way it did when it was created.
|
||||
* That is, if there were no players who left the party.
|
||||
*
|
||||
* [MENTION=850422]return[/MENTION] True if the underlying MapleParty still exists in its original format.
|
||||
*/
|
||||
public boolean exists() {
|
||||
Collection<Player> members = getMembers();
|
||||
for (Player chr : members) {
|
||||
if (chr.getParty() == null || chr.getParty() != this.party) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getAverageLevel() {
|
||||
int sum = 0, num = 0;
|
||||
for (Player chr : getMembers()) {
|
||||
sum += chr.getLevel();
|
||||
num += 1;
|
||||
}
|
||||
return sum / num;
|
||||
}
|
||||
|
||||
public boolean checkLevels() {
|
||||
if (MonsterCarnival.DEBUG) {
|
||||
return true;
|
||||
}
|
||||
for (Player chr : getMembers()) {
|
||||
int lv = chr.getLevel();
|
||||
if (lv < MonsterCarnival.MIN_LEVEL || lv > MonsterCarnival.MAX_LEVEL) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean checkChannels() {
|
||||
if (MonsterCarnival.DEBUG) {
|
||||
return true;
|
||||
}
|
||||
for (Player chr : getMembers()) {
|
||||
if (chr.getClient().getChannel() != party.getLeader().getChannel()) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean checkMaps() {
|
||||
if (MonsterCarnival.DEBUG) {
|
||||
return true;
|
||||
}
|
||||
for (Player chr : getMembers()) {
|
||||
if (chr.getMapId() != MonsterCarnival.MAP_LOBBY) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void warp(int map) {
|
||||
for (Player chr : getMembers()) {
|
||||
chr.changeMap(map);
|
||||
}
|
||||
}
|
||||
|
||||
public void warp(Field map) {
|
||||
for (Player chr : getMembers()) {
|
||||
chr.changeMap(map, map.getPortal(0));
|
||||
}
|
||||
}
|
||||
|
||||
public void warp(Field map, String portal) {
|
||||
for (Player chr : getMembers()) {
|
||||
chr.changeMap(map, map.getPortal(portal));
|
||||
}
|
||||
}
|
||||
|
||||
public void warp(MCField.MCMaps type) {
|
||||
Field m = this.field.getMap(type);
|
||||
for (Player chr : getMembers()) {
|
||||
chr.changeMap(m, m.getPortal(0));
|
||||
}
|
||||
}
|
||||
|
||||
public void clock(int secs) {
|
||||
for (Player chr : getMembers()) {
|
||||
chr.getClient().announce(PacketCreator.GetClock(secs));
|
||||
}
|
||||
}
|
||||
|
||||
public void notice(String msg) {
|
||||
broadcast(PacketCreator.ServerNotice(6, msg));
|
||||
}
|
||||
|
||||
public void broadcast(OutPacket pkt) {
|
||||
for (Player chr : getMembers()) {
|
||||
chr.getClient().announce(pkt);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets MCPQTeam, MCPQParty, and MCPQField for a given character.
|
||||
* [MENTION=2000183830]para[/MENTION]m chr Character to update.
|
||||
*/
|
||||
public void updatePlayer(Player chr) {
|
||||
chr.setMCPQTeam(this.team);
|
||||
chr.setMCPQParty(this);
|
||||
chr.setMCPQField(this.field);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets MCPQTeam, MCPQParty, and MCPQ field for all characters in the party.
|
||||
* Unlike deregisterPlayers, this method does NOT warp players to the lobby map.
|
||||
*/
|
||||
public void updatePlayers() {
|
||||
for (Player chr : getMembers()) {
|
||||
this.updatePlayer(chr);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets MCPQ variables for a given character.
|
||||
* [MENTION=2000183830]para[/MENTION]m chr Character to reset.
|
||||
*/
|
||||
public static void deregisterPlayer(Player chr) {
|
||||
chr.setMCPQTeam(MCTeam.NONE);
|
||||
chr.setMCPQParty(null);
|
||||
chr.setMCPQField(null);
|
||||
|
||||
chr.setAvailableCP(0);
|
||||
chr.setTotalCP(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets MCPQ variables for all characters in the party.
|
||||
* Unlike updatePlayers, this method DOES warp players to the lobby map.
|
||||
*/
|
||||
public void deregisterPlayers() {
|
||||
for (Player chr : getMembers()) {
|
||||
MCParty.deregisterPlayer(chr);
|
||||
chr.changeMap(MonsterCarnival.MAP_EXIT);
|
||||
}
|
||||
}
|
||||
|
||||
public void removePlayer(Player chr) {
|
||||
characters.remove(chr);
|
||||
deregisterPlayer(chr);
|
||||
}
|
||||
|
||||
public void startBattle() {
|
||||
for (Player chr : characters) {
|
||||
chr.getClient().getSession().write(CarnivalPackets.StartMonsterCarnival(chr));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses some amount of available CP.
|
||||
* [MENTION=2000183830]para[/MENTION]m use A positive integer to be subtracted from available CP.
|
||||
*/
|
||||
public void loseCP(int use) {
|
||||
// TODO: locks?
|
||||
if (use < 0) {
|
||||
System.err.println("Attempting to use negative CP.");
|
||||
}
|
||||
this.availCP -= use;
|
||||
}
|
||||
|
||||
public void gainCP(int gain) {
|
||||
// TODO: locks?
|
||||
this.availCP += gain;
|
||||
this.totalCP += gain;
|
||||
}
|
||||
|
||||
public MCParty getEnemy() {
|
||||
return enemy;
|
||||
}
|
||||
|
||||
public void setEnemy(MCParty enemy) {
|
||||
this.enemy = enemy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a MCSkill to the entire team. This is used on the team's own players
|
||||
* because it is called when the enemy team uses a debuff/cube of darkness.
|
||||
* [MENTION=2000183830]para[/MENTION]m skill Skill to apply.
|
||||
* [MENTION=850422]return[/MENTION] True if skill was applied, false otherwise.
|
||||
*/
|
||||
public boolean applyMCSkill(MCSkill skill) {
|
||||
MobSkill s = MobSkillFactory.getMobSkill(skill.getMobSkillID(), skill.getLevel());
|
||||
Disease disease = Disease.getType(skill.getMobSkillID());
|
||||
if (disease == null) {
|
||||
disease = Disease.DARKNESS;
|
||||
s = MobSkillFactory.getMobSkill(121, 6); // HACK: darkness
|
||||
} else if (disease == Disease.POISON) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We only target players on the battlefield map.
|
||||
if (skill.getTarget() == 2) {
|
||||
for (Player chr : getMembers()) {
|
||||
if (MonsterCarnival.isBattlefieldMap(chr.getMapId())) {
|
||||
chr.giveDebuff(disease, s);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
if (getRandomMember() != null) {
|
||||
getRandomMember().giveDebuff(disease, 1, 30000L, disease.getDisease(), 1);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setField(MCField field) {
|
||||
this.field = field;
|
||||
}
|
||||
|
||||
public void setTeam(MCTeam newTeam) {
|
||||
this.team = newTeam;
|
||||
}
|
||||
|
||||
public MCTeam getTeam() {
|
||||
return team;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collection of online members in the party.
|
||||
* [MENTION=850422]return[/MENTION] Online MCParty members.
|
||||
*/
|
||||
public Collection<Player> getMembers() {
|
||||
return this.characters;
|
||||
}
|
||||
|
||||
public Player getRandomMember() {
|
||||
List<Player> chrsOnMap = new ArrayList<>();
|
||||
for (Player chr : this.characters) {
|
||||
if (MonsterCarnival.isBattlefieldMap(chr.getMapId())) {
|
||||
chrsOnMap.add(chr);
|
||||
}
|
||||
}
|
||||
if (chrsOnMap.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return chrsOnMap.get(new Random().nextInt(chrsOnMap.size()));
|
||||
}
|
||||
|
||||
public int getAvailableCP() {
|
||||
return availCP;
|
||||
}
|
||||
|
||||
public int getTotalCP() {
|
||||
return totalCP;
|
||||
}
|
||||
}
|
||||
@@ -1,72 +0,0 @@
|
||||
package server.partyquest.mcpq;
|
||||
|
||||
/*
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Object representing MCSkill in Skill.wz/MCSkill.img.
|
||||
*
|
||||
* @author s4nta
|
||||
*/
|
||||
public class MCSkill {
|
||||
private final int id, target, mobSkillID, level, spendCP;
|
||||
private String name, desc;
|
||||
|
||||
public MCSkill(int id, int target, int mobSkillID, int level, int spendCP) {
|
||||
this.id = id;
|
||||
this.target = target;
|
||||
this.mobSkillID = mobSkillID;
|
||||
this.level = level;
|
||||
this.spendCP = spendCP;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public int getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
public int getMobSkillID() {
|
||||
return mobSkillID;
|
||||
}
|
||||
|
||||
public int getLevel() {
|
||||
return level;
|
||||
}
|
||||
|
||||
public int getSpendCP() {
|
||||
return spendCP;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public void setDesc(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
/*
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package server.partyquest.mcpq;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
import provider.MapleData;
|
||||
import provider.MapleDataProvider;
|
||||
import provider.MapleDataProviderFactory;
|
||||
import provider.MapleDataTool;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sammy Guergachi <sguergachi at gmail.com>
|
||||
*/
|
||||
public class MCSkillFactory {
|
||||
|
||||
private static Map<Integer, MCSkill> mcSkills = new HashMap<>();
|
||||
private static Map<Integer, MCGuardian> mcGuardians = new HashMap<>();
|
||||
private static MapleDataProvider dataSource = MapleDataProviderFactory.getDataProvider(new File(System.getProperty("wzpath") + "/Skill.wz"));
|
||||
private static MapleData mcSkillRoot = dataSource.getData("MCSkill.img");
|
||||
private static MapleData mcGuardianRoot = dataSource.getData("MCGuardian.img");
|
||||
private static ReentrantReadWriteLock skillLock = new ReentrantReadWriteLock();
|
||||
private static ReentrantReadWriteLock guardianLock = new ReentrantReadWriteLock();
|
||||
|
||||
public static MCSkill getMCSkill(int skillId) {
|
||||
skillLock.readLock().lock();
|
||||
try {
|
||||
MCSkill ret = mcSkills.get(skillId);
|
||||
if (ret != null) {
|
||||
return ret;
|
||||
}
|
||||
} finally {
|
||||
skillLock.readLock().unlock();
|
||||
}
|
||||
skillLock.writeLock().lock();
|
||||
try {
|
||||
MCSkill ret;
|
||||
ret = mcSkills.get(skillId);
|
||||
if (ret == null) {
|
||||
MapleData skillData = mcSkillRoot.getChildByPath(String.valueOf(skillId));
|
||||
if (skillData != null) {
|
||||
int target = MapleDataTool.getInt("target", skillData, 0);
|
||||
int spendCP = MapleDataTool.getInt("spendCP", skillData, 0);
|
||||
int mobSkillID = MapleDataTool.getInt("mobSkillID", skillData, 0);
|
||||
int level = MapleDataTool.getInt("level", skillData, 0);
|
||||
ret = new MCSkill(skillId, target, mobSkillID, level, spendCP);
|
||||
|
||||
if (MonsterCarnival.DEBUG) {
|
||||
String name = MapleDataTool.getString("name", skillData, "");
|
||||
String desc = MapleDataTool.getString("desc", skillData, "");
|
||||
ret.setName(name);
|
||||
ret.setDesc(desc);
|
||||
}
|
||||
mcSkills.put(skillId, ret);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
} finally {
|
||||
skillLock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public static MCGuardian getMCGuardian(int id) {
|
||||
guardianLock.readLock().lock();
|
||||
try {
|
||||
MCGuardian ret = mcGuardians.get(id);
|
||||
if (ret != null) {
|
||||
return ret;
|
||||
}
|
||||
} finally {
|
||||
guardianLock.readLock().unlock();
|
||||
}
|
||||
guardianLock.writeLock().lock();
|
||||
try {
|
||||
MCGuardian ret;
|
||||
ret = mcGuardians.get(id);
|
||||
if (ret == null) {
|
||||
MapleData skillData = mcGuardianRoot.getChildByPath(String.valueOf(id));
|
||||
if (skillData != null) {
|
||||
int type = MapleDataTool.getInt("type", skillData, 0);
|
||||
int spendCP = MapleDataTool.getInt("spendCP", skillData, 0);
|
||||
int mobSkillID = MapleDataTool.getInt("mobSkillID", skillData, 0);
|
||||
int level = MapleDataTool.getInt("level", skillData, 0);
|
||||
ret = new MCGuardian(type, spendCP, mobSkillID, level);
|
||||
|
||||
if (MonsterCarnival.DEBUG) {
|
||||
String name = MapleDataTool.getString("name", skillData, "");
|
||||
String desc = MapleDataTool.getString("desc", skillData, "");
|
||||
ret.setName(name);
|
||||
ret.setDesc(desc);
|
||||
}
|
||||
mcGuardians.put(type, ret);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
} finally {
|
||||
guardianLock.writeLock().unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package server.partyquest.mcpq;
|
||||
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Logs various errors and also keeps data on Carnival PQ runs.
|
||||
* @author s4nta
|
||||
*/
|
||||
public class MCTracker {
|
||||
|
||||
static org.slf4j.Logger log = LoggerFactory.getLogger(MCTracker.class);
|
||||
|
||||
// TODO:
|
||||
// Add field-specific info
|
||||
// Add methods for calls from different files
|
||||
// Maybe write own version of FilePrinter?
|
||||
|
||||
static final String PATH = "Reports/MCPQ.txt";
|
||||
|
||||
public static void log(String msg) {
|
||||
System.out.println(msg);
|
||||
log.debug(msg);
|
||||
}
|
||||
}
|
||||
@@ -1,164 +0,0 @@
|
||||
/*
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package server.partyquest.mcpq;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import provider.MapleData;
|
||||
import provider.MapleDataTool;
|
||||
|
||||
/**
|
||||
* Representation of the data tree inside of the Map.wz file.
|
||||
*
|
||||
* @author s4nta
|
||||
*/
|
||||
public class MCWZData {
|
||||
|
||||
public List<MCMobGenPos> mobGenPosList = new ArrayList<>();
|
||||
public List<MCGuardianGenPos> guardianGenPosList = new ArrayList<>();
|
||||
public Map<Integer, MCSummonMob> summons = new HashMap<>();
|
||||
public Map<Integer, Integer> skills = new HashMap<>();
|
||||
public Map<Integer, Integer> guardians = new HashMap<>();
|
||||
|
||||
public String effectWin, effectLose, soundWin, soundLose;
|
||||
public int rewardMapWin, rewardMapLose;
|
||||
|
||||
public int mobGenMax, guardianGenMax;
|
||||
public boolean mapDivided;
|
||||
public int deathCP;
|
||||
public int reactorRed, reactorBlue;
|
||||
|
||||
public MCWZData(MapleData src) {
|
||||
parse(src);
|
||||
}
|
||||
|
||||
public void parse(MapleData src) {
|
||||
populateMobGenPos(src.getChildByPath("mobGenPos"));
|
||||
populateSummonMobs(src.getChildByPath("mob"));
|
||||
effectWin = MapleDataTool.getString("effectWin", src);
|
||||
effectLose = MapleDataTool.getString("effectLose", src);
|
||||
soundWin = MapleDataTool.getString("soundWin", src);
|
||||
soundLose = MapleDataTool.getString("soundLose", src);
|
||||
|
||||
rewardMapWin = MapleDataTool.getInt("rewardMapWin", src);
|
||||
rewardMapLose = MapleDataTool.getInt("rewardMapLose", src);
|
||||
|
||||
populateSkills(src.getChildByPath("skill"));
|
||||
populateGuardianGenPos(src.getChildByPath("guardianGenPos"));
|
||||
populateGuardians(src.getChildByPath("guardian"));
|
||||
|
||||
mobGenMax = MapleDataTool.getInt("mobGenMax", src, 20); // HACK: 20 default
|
||||
guardianGenMax = MapleDataTool.getInt("guardianGenMax", src, 20); // HACK: 20 default
|
||||
|
||||
mapDivided = MapleDataTool.getInt("mapDivided", src) > 0;
|
||||
|
||||
deathCP = MapleDataTool.getInt("deathCP", src);
|
||||
reactorRed = MapleDataTool.getInt("reactorRed", src);
|
||||
reactorBlue = MapleDataTool.getInt("reactorBlue", src);
|
||||
}
|
||||
|
||||
private void populateMobGenPos(MapleData src) {
|
||||
for (MapleData n : src) {
|
||||
MCMobGenPos nn = new MCMobGenPos(MapleDataTool.getInt("x", n, 0),
|
||||
MapleDataTool.getInt("y", n, 0),
|
||||
MapleDataTool.getInt("fh", n, 0),
|
||||
MapleDataTool.getInt("cy", n, 0),
|
||||
MapleDataTool.getInt("team", n, -1));
|
||||
mobGenPosList.add(nn);
|
||||
}
|
||||
}
|
||||
|
||||
private void populateSummonMobs(MapleData src) {
|
||||
for (MapleData n : src) {
|
||||
int id = Integer.parseInt(n.getName());
|
||||
MCSummonMob mcs = new MCSummonMob(
|
||||
MapleDataTool.getInt("id", n, 0),
|
||||
MapleDataTool.getInt("spendCP", n, 0),
|
||||
MapleDataTool.getInt("mobTime", n, 0)
|
||||
);
|
||||
|
||||
this.summons.put(id, mcs);
|
||||
}
|
||||
}
|
||||
|
||||
private void populateSkills(MapleData src) {
|
||||
for (MapleData n : src) {
|
||||
int key = Integer.parseInt(n.getName());
|
||||
int val = MapleDataTool.getInt(n);
|
||||
|
||||
skills.put(key, val);
|
||||
}
|
||||
}
|
||||
|
||||
private void populateGuardianGenPos(MapleData src) {
|
||||
for (MapleData n : src) {
|
||||
MCGuardianGenPos nn = new MCGuardianGenPos(MapleDataTool.getInt("x", n, 0),
|
||||
MapleDataTool.getInt("y", n, 0),
|
||||
MapleDataTool.getInt("f", n, 0),
|
||||
MapleDataTool.getInt("team", n, -1));
|
||||
guardianGenPosList.add(nn);
|
||||
}
|
||||
}
|
||||
|
||||
private void populateGuardians(MapleData src) {
|
||||
for (MapleData n : src) {
|
||||
int key = Integer.parseInt(n.getName());
|
||||
int val = MapleDataTool.getInt(n);
|
||||
|
||||
guardians.put(key, val);
|
||||
}
|
||||
}
|
||||
|
||||
public class MCMobGenPos {
|
||||
|
||||
public final int x, y, fh, cy, team;
|
||||
|
||||
private MCMobGenPos(int x, int y, int fh, int cy, int team) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.fh = fh;
|
||||
this.cy = cy;
|
||||
this.team = team;
|
||||
}
|
||||
}
|
||||
|
||||
public class MCGuardianGenPos {
|
||||
|
||||
public final int x, y, f, team;
|
||||
|
||||
private MCGuardianGenPos(int x, int y, int f, int team) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.f = f;
|
||||
this.team = team;
|
||||
}
|
||||
}
|
||||
|
||||
public class MCSummonMob {
|
||||
|
||||
public final int id, spendCP, mobTime;
|
||||
|
||||
private MCSummonMob(int id, int spendCP, int mobTime) {
|
||||
this.id = id;
|
||||
this.spendCP = spendCP;
|
||||
this.mobTime = mobTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,371 +0,0 @@
|
||||
/*
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package server.partyquest.mcpq;
|
||||
|
||||
import community.MapleParty;
|
||||
import handling.channel.ChannelServer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import client.player.Player;
|
||||
import client.player.buffs.Disease;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Sammy Guergachi <sguergachi at gmail.com>
|
||||
*/
|
||||
/**
|
||||
* Processes game logic for Monster Carnival PQ.
|
||||
*
|
||||
* TODO: Display IGNs/Jobs/Level in Pending Requests
|
||||
* TODO: fix reactor handling and make it less hacky
|
||||
* TODO: fix cube of darkness and make it less hacky
|
||||
*
|
||||
* @author s4nta
|
||||
*/
|
||||
public class MonsterCarnival {
|
||||
|
||||
// Logger
|
||||
static org.slf4j.Logger log = LoggerFactory.getLogger(MonsterCarnival.class);
|
||||
|
||||
// Map of channel to a MonsterCarnival instance.
|
||||
private static final HashMap<Integer, MonsterCarnival> instances = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Returns the MonsterCarnival instance for a channel. Creates a new one and maps it
|
||||
* if it does not exist.
|
||||
* [MENTION=2000183830]para[/MENTION]m channel Channel to check for.
|
||||
* [MENTION=850422]return[/MENTION] MonsterCarnival instance for a channel.
|
||||
* @param channel
|
||||
* @return
|
||||
*/
|
||||
public static MonsterCarnival getMonsterCarnival(int channel) {
|
||||
// TODO: synchronization?
|
||||
if (channel < 1 || channel > 20) {
|
||||
log.warn("Attempting to get a Monster Carnival instance for invalid channel.");
|
||||
return null;
|
||||
}
|
||||
if (instances.containsKey(channel)) {
|
||||
return instances.get(channel);
|
||||
}
|
||||
ChannelServer cserv = ChannelServer.getInstance(channel);
|
||||
if (cserv == null) {
|
||||
log.error("ChannelServer instance for channel " + channel + " is null.");
|
||||
return null;
|
||||
}
|
||||
MonsterCarnival inst = new MonsterCarnival(cserv);
|
||||
instances.put(channel, inst);
|
||||
return inst;
|
||||
}
|
||||
|
||||
// Instance variables
|
||||
private ChannelServer cserv;
|
||||
private Map<Integer, MCField> fields = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Constructor for a MonsterCarnival instance.
|
||||
* [MENTION=2000183830]para[/MENTION]m cserv Channel server for this instance.
|
||||
*/
|
||||
public MonsterCarnival(ChannelServer cserv) {
|
||||
this.cserv = cserv;
|
||||
this.initFields();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes empty fields for the instance.
|
||||
*/
|
||||
private void initFields() {
|
||||
for (int i = 1; i <= NUM_FIELDS; i++) {
|
||||
fields.put(i, new MCField(i, this.cserv, null, null));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the field with a specified ID.
|
||||
* [MENTION=2000183830]para[/MENTION]m id ID of field to retrieve.
|
||||
* [MENTION=850422]return[/MENTION]
|
||||
*/
|
||||
public MCField getField(int id) {
|
||||
if (id >= 1 && id <= NUM_FIELDS) {
|
||||
return fields.get(id);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a party can join a field or not.
|
||||
*
|
||||
* [MENTION=2000183830]para[/MENTION]m pty Party to register.
|
||||
* [MENTION=2000183830]para[/MENTION]m room Room to join.
|
||||
* [MENTION=850422]return[/MENTION] Different code based on status. OK if successful.
|
||||
*/
|
||||
public int registerStatus(MapleParty pty, int room) {
|
||||
if (!isValidField(room)) {
|
||||
return STATUS_FIELD_INVALID;
|
||||
}
|
||||
MCField field = this.getField(room);
|
||||
if (field.isFull()) {
|
||||
return STATUS_FIELD_FULL;
|
||||
}
|
||||
MCParty party = new MCParty(pty);
|
||||
if (!sizeCheck(party.getSize(), room)) {
|
||||
return STATUS_PARTY_SIZE;
|
||||
}
|
||||
boolean levelCheck = party.checkLevels();
|
||||
if (!levelCheck) {
|
||||
return STATUS_PARTY_LEVEL;
|
||||
}
|
||||
boolean chanCheck = party.checkChannels();
|
||||
if (!chanCheck) {
|
||||
return STATUS_PARTY_MISSING;
|
||||
}
|
||||
boolean mapCheck = party.checkMaps();
|
||||
if (!mapCheck) {
|
||||
return STATUS_PARTY_MISSING;
|
||||
}
|
||||
if (field.needsRequest()) {
|
||||
return STATUS_REQUEST;
|
||||
}
|
||||
return STATUS_PROCEED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new MCParty based on a regular MapleParty object.
|
||||
* [MENTION=2000183830]para[/MENTION]m pty Party to base off of.
|
||||
* [MENTION=850422]return[/MENTION] Newly created MCParty.
|
||||
*/
|
||||
public MCParty createParty(MapleParty pty) {
|
||||
return new MCParty(pty);
|
||||
}
|
||||
|
||||
public void resetPlayer(Player chr) {
|
||||
MCParty.deregisterPlayer(chr);
|
||||
chr.changeMap(MAP_LOBBY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a String containing information about lobby waiting rooms.
|
||||
*
|
||||
* [MENTION=850422]return[/MENTION] String containing lobby information formatted for NPC.
|
||||
*/
|
||||
public String getNPCAvailableFields() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Welcome to the #bCarnival PQ#k! Rooms 1-4 can hold 2-4 people, and rooms 5-6 can hold 3-6.\r\n#b");
|
||||
for (int i = 1; i <= NUM_FIELDS; i++) {
|
||||
MCField field = this.fields.get(i);
|
||||
sb.append(field.getStatus());
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
// Reference Information
|
||||
|
||||
// Game Constants
|
||||
public static final int CP_LOSS_ON_DEATH = 10;
|
||||
public static final int TIME_PREBATTLE = 10;
|
||||
public static final int TIME_BATTLE = 600;
|
||||
public static final int TIME_LOBBYWAIT = 180;
|
||||
|
||||
public static final int TAB_SPAWNS = 0;
|
||||
public static final int TAB_DEBUFF = 1;
|
||||
public static final int TAB_GUARDIAN = 2;
|
||||
|
||||
/**
|
||||
* Gets a random debuff for (Mini) Cube of Darkness.
|
||||
* [MENTION=850422]return[/MENTION] Random MapleDisease.
|
||||
*/
|
||||
public static Disease getRandomDebuff() {
|
||||
return DEBUFFS[new Random().nextInt(DEBUFFS.length)];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks party size. Information from hidden-street MCPQ page.
|
||||
* [MENTION=2000183830]para[/MENTION]m size Size of the party.
|
||||
* [MENTION=2000183830]para[/MENTION]m field Field to check for.
|
||||
* [MENTION=850422]return[/MENTION] True if party size is okay, False otherwise.
|
||||
*/
|
||||
public static final boolean sizeCheck(int size, int field) {
|
||||
if (DEBUG) {
|
||||
return true;
|
||||
}
|
||||
switch (field) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
// return size >= 2 && size <= 4;
|
||||
return size >= 1 && size <= 4;
|
||||
case 5:
|
||||
case 6:
|
||||
// return size >= 3 && size <= 6;
|
||||
return size >= 1 && size <= 6;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static final boolean isValidField(int field) {
|
||||
return field >= 1 && field <= 6;
|
||||
}
|
||||
|
||||
public static final int getLobbyMap(int field) {
|
||||
if (field < 1 || field > NUM_FIELDS) {
|
||||
log.warn("Attempting to get lobby map for invalid field.");
|
||||
return MAP_EXIT;
|
||||
}
|
||||
return 980000000 + field * 100;
|
||||
}
|
||||
|
||||
public static final boolean isLobbyMap(int mapid) {
|
||||
switch (mapid) {
|
||||
case 980000100:
|
||||
case 980000200:
|
||||
case 980000300:
|
||||
case 980000400:
|
||||
case 980000500:
|
||||
case 980000600:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static final int getBattleFieldMap(int field) {
|
||||
if (field < 1 || field > NUM_FIELDS) {
|
||||
log.warn("Attempting to get battlefield map for invalid field.");
|
||||
return MAP_EXIT;
|
||||
}
|
||||
return 980000000 + field * 100 + 1;
|
||||
}
|
||||
|
||||
public static final boolean isBattlefieldMap(int mapid) {
|
||||
switch (mapid) {
|
||||
case 980000101:
|
||||
case 980000201:
|
||||
case 980000301:
|
||||
case 980000401:
|
||||
case 980000501:
|
||||
case 980000601:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static final int getResurrectionMap(int field) {
|
||||
if (field < 1 || field > NUM_FIELDS) {
|
||||
log.warn("Attempting to get resurrection map for invalid field.");
|
||||
return MAP_EXIT;
|
||||
}
|
||||
return 980000000 + field * 100 + 2;
|
||||
}
|
||||
|
||||
public static final int getVictoriousMap(int field) {
|
||||
if (field < 1 || field > NUM_FIELDS) {
|
||||
log.warn("Attempting to get victory map for invalid field.");
|
||||
return MAP_EXIT;
|
||||
}
|
||||
return 980000000 + field * 100 + 3;
|
||||
}
|
||||
|
||||
public static final int getDefeatedMap(int field) {
|
||||
if (field < 1 || field > NUM_FIELDS) {
|
||||
log.warn("Attempting to get defeat map for invalid field.");
|
||||
return MAP_EXIT;
|
||||
}
|
||||
return 980000000 + field * 100 + 4;
|
||||
}
|
||||
|
||||
public static final boolean isCPQConsumeItem(int itemid) {
|
||||
switch (itemid) {
|
||||
case ITEM_CP_1:
|
||||
case ITEM_CP_2:
|
||||
case ITEM_CP_3:
|
||||
case ITEM_PTY_ELIX:
|
||||
case ITEM_PTY_PELIX:
|
||||
case ITEM_PTY_ALLC:
|
||||
case ITEM_MINICUBE:
|
||||
case ITEM_DARKCUBE:
|
||||
case ITEM_STUNNER:
|
||||
case ITEM_IND_WHITE:
|
||||
case ITEM_IND_MANA:
|
||||
case ITEM_IND_ELIX:
|
||||
case ITEM_IND_PELIX:
|
||||
case ITEM_IND_ALLC:
|
||||
case ITEM_PTY_MANA:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Error Codes
|
||||
// Note: These would be in an enum, but since these will be used in a NPC, they are not.
|
||||
public static final int STATUS_FIELD_FULL = 0;
|
||||
public static final int STATUS_PARTY_SIZE = 1;
|
||||
public static final int STATUS_PARTY_LEVEL = 2;
|
||||
public static final int STATUS_PARTY_MISSING = 3;
|
||||
public static final int STATUS_FIELD_INVALID = 4;
|
||||
public static final int STATUS_REQUEST = 98;
|
||||
public static final int STATUS_PROCEED = 99;
|
||||
|
||||
// Maps
|
||||
public static final int MAP_LOBBY = 980000000;
|
||||
public static final int MAP_EXIT = 980000010;
|
||||
|
||||
// NPCs
|
||||
public static final int NPC_LOBBY = 2042000;
|
||||
public static final int NPC_ENTER = 2042001; // Warp in from outside
|
||||
public static final int NPC_INFO = 2042002;
|
||||
public static final int NPC_ASST_RED = 2042003;
|
||||
public static final int NPC_ASST_BLUE = 2042004;
|
||||
|
||||
// Items
|
||||
public static final int ITEM_CP_1 = 2022157;
|
||||
public static final int ITEM_CP_2 = 2022158;
|
||||
public static final int ITEM_CP_3 = 2022159;
|
||||
public static final int ITEM_PTY_MANA = 2022160;
|
||||
public static final int ITEM_PTY_ELIX = 2022161;
|
||||
public static final int ITEM_PTY_PELIX = 2022162;
|
||||
public static final int ITEM_PTY_ALLC = 2022163;
|
||||
public static final int ITEM_MINICUBE = 2022164;
|
||||
public static final int ITEM_DARKCUBE = 2022165;
|
||||
public static final int ITEM_STUNNER = 2022166;
|
||||
public static final int ITEM_IND_WHITE = 2022174;
|
||||
public static final int ITEM_IND_ELIX = 2022175;
|
||||
public static final int ITEM_IND_PELIX = 2022176;
|
||||
public static final int ITEM_IND_MANA = 2022177;
|
||||
public static final int ITEM_IND_ALLC = 2022178;
|
||||
|
||||
// Guardians
|
||||
public static final int GUARDIAN_RED = 9980000;
|
||||
public static final int GUARDIAN_BLUE = 9980001;
|
||||
|
||||
// Debuffs
|
||||
public static final Disease[] DEBUFFS = {Disease.STUN, Disease.DARKNESS, Disease.WEAKEN}; // intentionally leave out a few
|
||||
|
||||
// Miscellaneous
|
||||
public static final int MIN_LEVEL = 30;
|
||||
public static final int MAX_LEVEL = 50;
|
||||
public static final int NUM_FIELDS = 6;
|
||||
|
||||
// Debug
|
||||
public static final boolean DEBUG = false;
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
Blob contains extra classes for Monster Carnival. Can possibly be used for implementing MCPQ.
|
||||
|
||||
Scripts and Src contains the code changed on OdinMS to have CPQ working.
|
||||
@@ -1,82 +0,0 @@
|
||||
/** * [MENTION=19862]id[/MENTION] 2042000
|
||||
* [MENTION=806871]NPC[/MENTION] Spiegelmann
|
||||
* [MENTION=836108]Function[/MENTION] Monster Carnival Lobby NPC
|
||||
* @author s4nta
|
||||
*/
|
||||
|
||||
// Relevant Monster Carnival classes
|
||||
var MonsterCarnival = net.sf.odinms.server.partyquest.mcpq.MonsterCarnival;
|
||||
var MCTracker = net.sf.odinms.server.partyquest.mcpq.MCTracker;
|
||||
var MCParty = net.sf.odinms.server.partyquest.mcpq.MCParty;
|
||||
var MCField = net.sf.odinms.server.partyquest.mcpq.MCField;
|
||||
var MCTeam = net.sf.odinms.server.partyquest.mcpq.MCField.MCTeam;
|
||||
|
||||
// NPC variables
|
||||
var status = -1;
|
||||
var carnival, field;
|
||||
var room = -1;
|
||||
|
||||
function start() {
|
||||
if (cm.getMapId() != 980000000) {
|
||||
MCTracker.log("Spiegelmann called on invalid map " + cm.getMapId() + " by player " + cm.getName());
|
||||
cm.sendOk("You are not authorized to do this.");
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
action(1, 0, 0);
|
||||
}
|
||||
|
||||
function action(mode, type, selection) {
|
||||
if (mode == -1) {
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
if (mode == 1) status++;
|
||||
else status--;
|
||||
|
||||
if (status == 0) {
|
||||
if (cm.getParty() == null) {
|
||||
cm.sendOk("You are not in a party.");
|
||||
cm.dispose();
|
||||
return;
|
||||
} else if (!cm.isLeader()) {
|
||||
cm.sendOk("If you want to try Carnival PQ, please tell the #bleader of your party#k to talk to me.");
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
carnival = MonsterCarnival.getMonsterCarnival(cm.getChannel());
|
||||
cm.sendSimple(carnival.getNPCAvailableFields());
|
||||
} else if (status == 1) {
|
||||
room = selection;
|
||||
if (room < 1 || room > 6) {
|
||||
cm.sendOk("That is not a valid room.");
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
var code = carnival.registerStatus(cm.getParty(), selection);
|
||||
if (code == MonsterCarnival.STATUS_FIELD_FULL) {
|
||||
cm.sendOk("This room is currently full.")
|
||||
} else if (code == MonsterCarnival.STATUS_PARTY_SIZE) {
|
||||
cm.sendOk("Your party is not the right size for this field.");
|
||||
} else if (code == MonsterCarnival.STATUS_PARTY_LEVEL) {
|
||||
cm.sendOk("Please check to see that the members in your party are between level 30 and 50.");
|
||||
} else if (code == MonsterCarnival.STATUS_PARTY_MISSING) {
|
||||
cm.sendOk("Please make sure everyone in your party is in this lobby.");
|
||||
} else if (code == MonsterCarnival.STATUS_FIELD_INVALID) {
|
||||
cm.sendOk("Unauthorized request.");
|
||||
}
|
||||
|
||||
if (code == MonsterCarnival.STATUS_PROCEED) {
|
||||
field = carnival.getField(room);
|
||||
party = carnival.createParty(cm.getParty());
|
||||
field.register(party, MCTeam.RED);
|
||||
cm.sendOk("You will have 3 minutes to accept challenges from other parties.");
|
||||
} else if (code == MonsterCarnival.STATUS_REQUEST) {
|
||||
cm.sendOk("Sending request to room " + room + ". You will be automatically warped in if they accept your challenge.");
|
||||
field = carnival.getField(room);
|
||||
party = carnival.createParty(cm.getParty());
|
||||
field.request(party);
|
||||
}
|
||||
cm.dispose();
|
||||
}
|
||||
}
|
||||
@@ -1,326 +0,0 @@
|
||||
/** * [MENTION=19862]id[/MENTION] 2042002
|
||||
* [MENTION=806871]NPC[/MENTION] Spiegelmann
|
||||
* [MENTION=836108]Function[/MENTION] Monster Carnival NPC
|
||||
* @author s4nta
|
||||
* [MENTION=497496]cred[/MENTION]its xirengfx (for store code, CPQ description)
|
||||
*/
|
||||
var DISABLED = false;
|
||||
|
||||
var SavedLocationType = Packages.net.sf.odinms.server.maps.SavedLocationType;
|
||||
|
||||
// Relevant Monster Carnival classes
|
||||
var MonsterCarnival = Packages.net.sf.odinms.server.partyquest.mcpq.MonsterCarnival;
|
||||
var MCTracker = Packages.net.sf.odinms.server.partyquest.mcpq.MCTracker;
|
||||
var MCParty = Packages.net.sf.odinms.server.partyquest.mcpq.MCParty;
|
||||
var MCField = Packages.net.sf.odinms.server.partyquest.mcpq.MCField;
|
||||
|
||||
// NPC variables
|
||||
var status = -1;
|
||||
var store = false;
|
||||
var ctx = -1; //context
|
||||
var storeInfo;
|
||||
var purchaseId;
|
||||
var purchaseCost;
|
||||
|
||||
// Reference
|
||||
var coinId = 4001129;
|
||||
var coinIcon = "#i" + coinId + "#";
|
||||
var infoMaps = [220000000, 200000000, 103000000, 540000000]; // ludi, orbis, kerning, singapore
|
||||
var gradeS = 600
|
||||
var gradeA = 500
|
||||
var gradeB = 400
|
||||
var gradeC = 300
|
||||
var gradeD = 200
|
||||
var gradeE = 100
|
||||
|
||||
var expRewards = [[150000, 100000], // S Winner/Loser
|
||||
[100000, 70000], // A Winner/Loser
|
||||
[75000, 43250], // B Winner/Loser
|
||||
[50000, 25000], // C Winner/Loser
|
||||
[25000, 12500], // D Winner/Loser
|
||||
[12500, 6250], // E Winner/Loser
|
||||
[5000, 2500] // F Winner/Loser
|
||||
];
|
||||
|
||||
// Exchange stores
|
||||
var warrior = [[1302004, 7], [1402006, 7], [1302009, 10], [1402007, 10],
|
||||
[1302010, 20], [1402003, 20], [1312006, 7], [1412004, 7],
|
||||
[1312007, 10], [1412005, 10], [1312018, 20], [1412003, 20],
|
||||
[1322015, 7], [1422008, 7], [1322016, 10], [1422007, 10],
|
||||
[1322017, 20], [1422005, 20], [1432003, 7], [1442003, 7],
|
||||
[1432005, 10], [1442009, 10], [1442005, 20], [1432004, 20]];
|
||||
|
||||
var magician = [[1372001, 7], [1382018, 7], [1372012, 10], [1382019, 10],
|
||||
[1382001, 20], [1372007, 20]];
|
||||
|
||||
var archer = [[1452006, 7], [1452007, 10], [1452008, 20], [1462005, 7],
|
||||
[1462006, 10], [1462007, 20]];
|
||||
|
||||
var thief = [[1472013, 7], [1472017, 10], [1472021, 20], [1332014, 7],
|
||||
[1332011, 10], [1332031, 10], [1332016, 20], [1332034, 20]];
|
||||
|
||||
var pirate = [[1482005, 7], [1482006, 10], [1482007, 20], [1492005, 7],
|
||||
[1492006, 10], [1492007, 20]];
|
||||
|
||||
var necklace = [[1122007, 50], [2041211, 40]];
|
||||
|
||||
// Long Text Descriptions
|
||||
var infoText = "You wish to know about the Monster Carnival? Very well. The Monster Carnival is a place of trilling battles and exciting competiton against people just as strong and motivated as yourself. You must summon monsters and defeat the monsters summoned by the opposing party. That's the essence of the Monster Carnival. Once you enter the Carnival Field, the task is to earn CP by hunter monsters from the opposing party and use those CP's to distract the opposing party from hunting monsters. There are three ways to distract the other party; Summon a Monster, Skill or Protector. Please remember this though, it's never a good idea to save up CP just for the sake of it. The CP's you've used will also help determine the winner and the loser of the carnival.";
|
||||
var no = "You do not have enough Maple Coins for this item. Come back to me when you acquire more!";
|
||||
|
||||
function getGrade(cp) {
|
||||
// Returns index of corresponding expRewards pair.
|
||||
if (cp >= gradeS) {
|
||||
return 0;
|
||||
} else if (cp >= gradeA) {
|
||||
return 1;
|
||||
} else if (cp >= gradeB) {
|
||||
return 2;
|
||||
} else if (cp >= gradeC) {
|
||||
return 3;
|
||||
} else if (cp >= gradeD) {
|
||||
return 4;
|
||||
} else if (cp >= gradeE) {
|
||||
return 5;
|
||||
} else {
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
|
||||
function isTownMap(map) {
|
||||
for (var i = 0; i < infoMaps.length; i++) {
|
||||
if (infoMaps[i] == map) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isExitMap(map) {
|
||||
return map == 980000010;
|
||||
}
|
||||
|
||||
function isWinnerMap(map) {
|
||||
return (map >= 980000000 && map <= 980000700 && map % 10 == 3);
|
||||
}
|
||||
|
||||
function isLoserMap(map) {
|
||||
return (map >= 980000000 && map <= 980000700 && map % 10 == 4);
|
||||
}
|
||||
|
||||
var CONTEXT_NONE = -1;
|
||||
var CONTEXT_TOWN = 0;
|
||||
var CONTEXT_EXIT = 1;
|
||||
var CONTEXT_WIN = 2;
|
||||
var CONTEXT_LOSE = 3;
|
||||
|
||||
function start() {
|
||||
if (DISABLED) {
|
||||
cm.sendOk("CPQ is temporarily unavailable.");
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
m = cm.getMapId();
|
||||
if (isTownMap(m)) {
|
||||
ctx = CONTEXT_TOWN;
|
||||
} else if (isExitMap(m)) {
|
||||
ctx = CONTEXT_EXIT;
|
||||
} else if (isWinnerMap(m)) {
|
||||
ctx = CONTEXT_WIN;
|
||||
} else if (isLoserMap(m)) {
|
||||
ctx = CONTEXT_LOSE;
|
||||
} else {
|
||||
ctx = CONTEXT_NONE;
|
||||
}
|
||||
|
||||
action(1, 0, 0);
|
||||
}
|
||||
|
||||
function doLoserMap(mode, type, selection) {
|
||||
if (cm.getPlayer().getMCPQParty() == null) {
|
||||
cm.warp(MonsterCarnival.MAP_LOBBY);
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == -1) {
|
||||
cm.dispose();
|
||||
} else {
|
||||
if (mode == 1) status++;
|
||||
else status--;
|
||||
|
||||
if (status == 0) {
|
||||
cm.sendNext("Unfortunately, you did not manage to win this round. Better luck next time!");
|
||||
} else if (status == 1) {
|
||||
var points = cm.getPlayer().getMCPQParty().getTotalCP();
|
||||
var grade = getGrade(points);
|
||||
var letterGrade = "ABCDF"[grade];
|
||||
var expReward = expRewards[grade][1];
|
||||
|
||||
cm.sendNext("Your grade is: #b" + letterGrade + "\r\n\r\n#kEXP Reward: " + expReward);
|
||||
cm.gainExp(expReward);
|
||||
} else if (status == 2) {
|
||||
cm.warp(MonsterCarnival.MAP_LOBBY);
|
||||
cm.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function doWinnerMap(mode, type, selection) {
|
||||
if (cm.getPlayer().getMCPQParty() == null) {
|
||||
cm.warp(MonsterCarnival.MAP_LOBBY);
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == -1) {
|
||||
cm.dispose();
|
||||
} else {
|
||||
if (mode == 1) status++;
|
||||
else status--;
|
||||
|
||||
if (status == 0) {
|
||||
cm.sendNext("Congratulations! You managed to defeat the enemy team!");
|
||||
} else if (status == 1) {
|
||||
var points = cm.getPlayer().getMCPQParty().getTotalCP();
|
||||
var grade = getGrade(points);
|
||||
var letterGrade = "ABCDF"[grade];
|
||||
var expReward = expRewards[grade][0];
|
||||
|
||||
cm.sendNext("Your grade is: #b" + letterGrade + "\r\n\r\n#kEXP Reward: " + expReward);
|
||||
cm.gainExp(expReward);
|
||||
} else if (status == 2) {
|
||||
cm.warp(MonsterCarnival.MAP_LOBBY);
|
||||
cm.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function doTown(mode, type, selection) {
|
||||
if (mode == -1) {
|
||||
cm.sendOk("Be sure to vote for the server every 24 hours!");
|
||||
cm.dispose();
|
||||
} else {
|
||||
if (mode == 1) status++;
|
||||
else status--;
|
||||
|
||||
if (status == 0) {
|
||||
cm.sendSimple("What would you like to do? If you have never participated in the Monster Carnival, you'll need to know a thing or two about it before joining.\r\n\r\n#b#L0#Go to the Monster Carnival Field#l\r\n#L1#Learn about the Monster Carnival#l\r\n#L2#Trade Maple Coin#l");
|
||||
} else if (status == 1) {
|
||||
if (selection == 0) {
|
||||
if (cm.getChar().getLevel() < MonsterCarnival.MIN_LEVEL || cm.getChar().getLevel() > MonsterCarnival.MAX_LEVEL) {
|
||||
cm.sendOk("You must be between level " + MonsterCarnival.MIN_LEVEL + " and level " + MonsterCarnival.MAX_LEVEL + " to enter.");
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
cm.getChar().saveLocation(SavedLocationType.MONSTER_CARNIVAL);
|
||||
cm.warp(MonsterCarnival.MAP_LOBBY, 4);
|
||||
cm.dispose();
|
||||
return;
|
||||
} else if (selection == 1) {
|
||||
cm.sendPrev(infoText);
|
||||
cm.dispose();
|
||||
return;
|
||||
} else if (selection == 2) {
|
||||
store = true;
|
||||
cm.sendSimple("Select a category:\r\n" +
|
||||
"#L101##bTrade Maple Coins for Warrior Weapons\r\n" +
|
||||
"#L102#Trade Maple Coins for Magician Weapons\r\n" +
|
||||
"#L103#Trade Maple Coins for Bowman Weapons\r\n" +
|
||||
"#L104#Trade Maple Coins for Thief Weapons\r\n" +
|
||||
"#L105#Trade Maple Coins for Pirate Weapons\r\n" +
|
||||
"#L106#Trade Maple Coins for a Necklace");
|
||||
}
|
||||
} else if (status == 2) {
|
||||
if (store) {
|
||||
switch (selection) {
|
||||
case 101:
|
||||
storeInfo = warrior;
|
||||
break;
|
||||
case 102:
|
||||
storeInfo = magician;
|
||||
break;
|
||||
case 103:
|
||||
storeInfo = archer;
|
||||
break;
|
||||
case 104:
|
||||
storeInfo = thief;
|
||||
break;
|
||||
case 105:
|
||||
storeInfo = pirate;
|
||||
break;
|
||||
case 106:
|
||||
storeInfo = necklace;
|
||||
break;
|
||||
default:
|
||||
storeInfo = [];
|
||||
}
|
||||
if (storeInfo.length == 0) {
|
||||
cm.sendOk("That store doesn't exist.");
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
var storeText = "";
|
||||
for (var i = 0; i < storeInfo.length; ++i) {
|
||||
var wepId = storeInfo[i][0];
|
||||
var cost = storeInfo[i][1];
|
||||
storeText += "#L" + i + "##v" + wepId + "# - #z" + wepId + "# - " + cost + " " + coinIcon + "#l\r\n";
|
||||
}
|
||||
cm.sendSimple(storeText);
|
||||
} else {
|
||||
MCTracker.log("[MCPQ_Info] CONTEXT_TOWN: Invalid status 2");
|
||||
}
|
||||
} else if (status == 3) {
|
||||
if (store) {
|
||||
purchaseId = storeInfo[selection][0];
|
||||
purchaseCost = storeInfo[selection][1];
|
||||
|
||||
if (cm.haveItem(coinId, purchaseCost)) {
|
||||
cm.sendYesNo("Are you sure you want to purchase #i" + purchaseId + "#? You will have #r#e" + (cm.itemQuantity(coinId) - purchaseCost) + " " + coinIcon + "##k#n remaining.");
|
||||
} else {
|
||||
cm.sendOk("You don't have enough " + coinIcon + ".");
|
||||
cm.dispose();
|
||||
}
|
||||
} else {
|
||||
MCTracker.log("[MCPQ_Info] CONTEXT_TOWN: Invalid status 3");
|
||||
}
|
||||
} else if (status == 4) {
|
||||
if (store) {
|
||||
if (cm.haveItem(coinId, purchaseCost)) {
|
||||
cm.gainItem(coinId, -purchaseCost);
|
||||
cm.gainItem(purchaseId);
|
||||
cm.sendOk("Congratulations! Enjoy your new item.");
|
||||
cm.dispose();
|
||||
}
|
||||
} else {
|
||||
MCTracker.log("[MCPQ_Info] CONTEXT_TOWN: Invalid status 4");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function doExit() {
|
||||
cm.warp(MonsterCarnival.MAP_LOBBY);
|
||||
cm.sendOk("Hope you had fun in the Carnival PQ!");
|
||||
cm.dispose();
|
||||
}
|
||||
|
||||
function action(mode, type, selection) {
|
||||
switch (ctx) {
|
||||
case CONTEXT_TOWN:
|
||||
doTown(mode, type, selection);
|
||||
break;
|
||||
case CONTEXT_EXIT:
|
||||
doExit();
|
||||
break;
|
||||
case CONTEXT_LOSE:
|
||||
doLoserMap(mode, type, selection);
|
||||
break;
|
||||
case CONTEXT_WIN:
|
||||
doWinnerMap(mode, type, selection);
|
||||
break;
|
||||
default:
|
||||
MCTracker.log("[MCPQ_INFO] Invalid context (value: " + ctx + ")");
|
||||
cm.dispose();
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
/** * [MENTION=19862]id[/MENTION] 2042003
|
||||
* [MENTION=806871]NPC[/MENTION] Assistant Red
|
||||
* [MENTION=836108]Function[/MENTION] Monster Carnival Waiting Room NPC
|
||||
* @author s4nta
|
||||
*/
|
||||
|
||||
// Relevant Monster Carnival classes
|
||||
var MonsterCarnival = net.sf.odinms.server.partyquest.mcpq.MonsterCarnival;
|
||||
var MCTracker = net.sf.odinms.server.partyquest.mcpq.MCTracker;
|
||||
var MCParty = net.sf.odinms.server.partyquest.mcpq.MCParty;
|
||||
var MCField = net.sf.odinms.server.partyquest.mcpq.MCField;
|
||||
var MCTeam = net.sf.odinms.server.partyquest.mcpq.MCField.MCTeam;
|
||||
|
||||
// NPC variables
|
||||
var status = -1;
|
||||
var carnival, field;
|
||||
var room = -1;
|
||||
|
||||
function start() {
|
||||
if (!MonsterCarnival.isLobbyMap(cm.getMapId())) {
|
||||
MCTracker.log("Assistant called on invalid map " + cm.getMapId() + " by player " + cm.getName());
|
||||
cm.sendOk("You are not authorized to do this.");
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
action(1, 0, 0);
|
||||
}
|
||||
|
||||
function action(mode, type, selection) {
|
||||
if (mode == -1) {
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
if (mode == 1) status++;
|
||||
else status--;
|
||||
|
||||
if (status == 0) {
|
||||
if (cm.getParty() == null) {
|
||||
cm.warp(MonsterCarnival.MAP_LOBBY);
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
options = ["#L1#Leave the room #r#e(WARNING: Abusing this will block you from future Carnival PQs)#b#n.#l",
|
||||
"#L2#Close NPC#l"];
|
||||
if (cm.isLeader()) {
|
||||
options.unshift("#L0#View pending challenges#l");
|
||||
}
|
||||
|
||||
text = "Welcome to Carnival PQ. I am #rAssistant Red#k. What can I do for you?#b\r\n";
|
||||
for (var i = 0; i < options.length; i++) {
|
||||
text += options[i];
|
||||
text += "\r\n";
|
||||
}
|
||||
cm.sendSimple(text);
|
||||
} else if (status == 1) {
|
||||
field = cm.getChar().getMCPQField();
|
||||
if (selection == 0) {
|
||||
if (!cm.isLeader()) {
|
||||
cm.sendOk("You are not authorized to do this.");
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
if (!field.hasPendingRequests()) {
|
||||
cm.sendOk("There are no pending requests at this time.");
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
cm.sendSimple(field.getNPCRequestString());
|
||||
} else if (selection == 1) {
|
||||
if (field != null) {
|
||||
field.deregister(true);
|
||||
} else {
|
||||
cm.warp(MonsterCarnival.MAP_EXIT);
|
||||
}
|
||||
cm.dispose();
|
||||
} else {
|
||||
cm.dispose();
|
||||
}
|
||||
} else if (status == 2) {
|
||||
var code = field.acceptRequest(selection);
|
||||
if (code == 1) {
|
||||
cm.sendOk("The challenge was accepted.");
|
||||
} else {
|
||||
cm.sendOk("An unknown error occurred.");
|
||||
}
|
||||
cm.dispose();
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
/** * [MENTION=19862]id[/MENTION] 2042004
|
||||
* [MENTION=806871]NPC[/MENTION] Assistant Blue
|
||||
* [MENTION=836108]Function[/MENTION] Monster Carnival Waiting Room NPC
|
||||
* @author s4nta
|
||||
*/
|
||||
|
||||
// Relevant Monster Carnival classes
|
||||
var MonsterCarnival = net.sf.odinms.server.partyquest.mcpq.MonsterCarnival;
|
||||
var MCTracker = net.sf.odinms.server.partyquest.mcpq.MCTracker;
|
||||
var MCParty = net.sf.odinms.server.partyquest.mcpq.MCParty;
|
||||
var MCField = net.sf.odinms.server.partyquest.mcpq.MCField;
|
||||
var MCTeam = net.sf.odinms.server.partyquest.mcpq.MCField.MCTeam;
|
||||
|
||||
// NPC variables
|
||||
var status = -1;
|
||||
var carnival, field;
|
||||
var room = -1;
|
||||
|
||||
function start() {
|
||||
if (!MonsterCarnival.isLobbyMap(cm.getMapId())) {
|
||||
MCTracker.log("Assistant called on invalid map " + cm.getMapId() + " by player " + cm.getName());
|
||||
cm.sendOk("You are not authorized to do this.");
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
action(1, 0, 0);
|
||||
}
|
||||
|
||||
function action(mode, type, selection) {
|
||||
if (mode == -1) {
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
if (mode == 1) status++;
|
||||
else status--;
|
||||
|
||||
if (status == 0) {
|
||||
if (cm.getParty() == null) {
|
||||
cm.warp(MonsterCarnival.MAP_LOBBY);
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
options = ["#L1#Leave the room #r#e(WARNING: Abusing this will block you from future Carnival PQs)#b#n.#l",
|
||||
"#L2#Close NPC#l"];
|
||||
if (cm.isLeader()) {
|
||||
options.unshift("#L0#View pending challenges#l");
|
||||
}
|
||||
|
||||
text = "Welcome to Carnival PQ. I am #bAssistant Blue#k. What can I do for you?#b\r\n";
|
||||
for (var i = 0; i < options.length; i++) {
|
||||
text += options[i];
|
||||
text += "\r\n";
|
||||
}
|
||||
cm.sendSimple(text);
|
||||
} else if (status == 1) {
|
||||
field = cm.getChar().getMCPQField();
|
||||
if (selection == 0) {
|
||||
if (!cm.isLeader()) {
|
||||
cm.sendOk("You are not authorized to do this.");
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
if (!field.hasPendingRequests()) {
|
||||
cm.sendOk("There are no pending requests at this time.");
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
cm.sendSimple(field.getNPCRequestString());
|
||||
} else if (selection == 1) {
|
||||
if (field != null) {
|
||||
field.deregister(true);
|
||||
} else {
|
||||
cm.warp(MonsterCarnival.MAP_EXIT);
|
||||
}
|
||||
cm.dispose();
|
||||
} else {
|
||||
cm.dispose();
|
||||
}
|
||||
} else if (status == 2) {
|
||||
var code = field.acceptRequest(selection);
|
||||
if (code == 1) {
|
||||
cm.sendOk("The challenge was accepted.");
|
||||
} else {
|
||||
cm.sendOk("An unknown error occurred.");
|
||||
}
|
||||
cm.dispose();
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
function enter(pi) { player = pi.getPlayer();
|
||||
if (player.getMCPQField() != null) {
|
||||
player.getMCPQField().onRevive(player);
|
||||
} else {
|
||||
pi.warp(980000000);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
function enter(pi) { player = pi.getPlayer();
|
||||
if (player.getMCPQField() != null) {
|
||||
player.getMCPQField().onRevive(player);
|
||||
} else {
|
||||
pi.warp(980000000);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
function enter(pi) { player = pi.getPlayer();
|
||||
if (player.getMCPQField() != null) {
|
||||
player.getMCPQField().onRevive(player);
|
||||
} else {
|
||||
pi.warp(980000000);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
function enter(pi) { player = pi.getPlayer();
|
||||
if (player.getMCPQField() != null) {
|
||||
player.getMCPQField().onRevive(player);
|
||||
} else {
|
||||
pi.warp(980000000);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
function enter(pi) { player = pi.getPlayer();
|
||||
if (player.getMCPQField() != null) {
|
||||
player.getMCPQField().onRevive(player);
|
||||
} else {
|
||||
pi.warp(980000000);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
function enter(pi) { player = pi.getPlayer();
|
||||
if (player.getMCPQField() != null) {
|
||||
player.getMCPQField().onRevive(player);
|
||||
} else {
|
||||
pi.warp(980000000);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
This file is part of the OdinMS Maple Story Server
|
||||
Copyright (C) 2008 Patrick Huy <patrick.huy@frz.cc>
|
||||
Matthias Butz <matze@odinms.de>
|
||||
Jan Christian Meyer <vimes@odinms.de>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License version 3
|
||||
as published by the Free Software Foundation. You may not use, modify
|
||||
or distribute this program under any other version of the
|
||||
GNU Affero General Public License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
importPackage(Packages.net.sf.odinms.server.maps);
|
||||
|
||||
/*
|
||||
Return from MCPQ map.
|
||||
*/
|
||||
|
||||
function enter(pi) {
|
||||
var returnMap = pi.getPlayer().getSavedLocation(SavedLocationType.MONSTER_CARNIVAL);
|
||||
if (returnMap < 0) {
|
||||
returnMap = 100000000; // to fix people who entered the fm trough an unconventional way
|
||||
}
|
||||
var target = pi.getPlayer().getClient().getChannelServer().getMapFactory().getMap(returnMap);
|
||||
var targetPortal;
|
||||
|
||||
if (returnMap == 230000000) {
|
||||
targetPortal = target.getPortal("market01");
|
||||
} else {
|
||||
targetPortal = target.getPortal("market00");
|
||||
}
|
||||
|
||||
if (targetPortal == null)
|
||||
targetPortal = target.getPortal(0);
|
||||
|
||||
if (pi.getPlayer().getMapId() != target) {
|
||||
pi.getPlayer().clearSavedLocation(SavedLocationType.MONSTER_CARNIVAL);
|
||||
pi.getPlayer().changeMap(target, targetPortal);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
Under the respawn map change code (!c.getPlayer().isAlive()), add before executeStandardPath is done:
|
||||
PHP Code:
|
||||
if (player.getMCPQField() != null) { player.getMCPQField().onPlayerRespawn(player);
|
||||
return;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
Add before items are added to inventory, or after mesos are handled:
|
||||
PHP Code:
|
||||
|
||||
else if (c.getPlayer().getMCPQField() != null) { // CPQ Handling boolean consumed = c.getPlayer().getMCPQField().onItemPickup(c.getPlayer(), mapitem);
|
||||
if (consumed) {
|
||||
c.getPlayer().getMap().broadcastMessage(MaplePacketCreator.removeItemFromMap(mapitem.getObjectId(), 2, c.getPlayer().getId()),
|
||||
mapitem.getPosition());
|
||||
c.getPlayer().getCheatTracker().pickupComplete();
|
||||
c.getPlayer().getMap().removeMapObject(ob);
|
||||
} else {
|
||||
if (MapleInventoryManipulator.addFromDrop(c, mapitem.getItem(), true)) {
|
||||
c.getPlayer().getMap().broadcastMessage(
|
||||
MaplePacketCreator.removeItemFromMap(mapitem.getObjectId(), 2, c.getPlayer().getId()),
|
||||
mapitem.getPosition());
|
||||
c.getPlayer().getCheatTracker().pickupComplete();
|
||||
c.getPlayer().getMap().removeMapObject(ob);
|
||||
} else {
|
||||
c.getPlayer().getCheatTracker().pickupComplete();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
client/MapleCharacter.java
|
||||
Add fields:
|
||||
PHP Code:
|
||||
private MCField.MCTeam MCPQTeam;private MCParty MCPQParty;
|
||||
private MCField MCPQField;
|
||||
private int availableCP = 0;
|
||||
private int totalCP = 0;
|
||||
under playerDead() method:
|
||||
PHP Code:
|
||||
if (player.getMap().isTown()) { XPdummy *= 0.01;
|
||||
} else if (MonsterCarnival.isBattlefieldMap(player.getMapId())) {
|
||||
XPdummy = 0;
|
||||
}
|
||||
under the giveDebuff() method, add a field that force adds the disease if some variable cpq is set, regardless of buffs.
|
||||
method signature:
|
||||
PHP Code:
|
||||
public void giveDebuff(MapleDisease disease, MobSkill skill, boolean cpq)
|
||||
Add these methods:
|
||||
PHP Code:
|
||||
public int getTeam() { if (this.MCPQTeam == null) {
|
||||
return -1;
|
||||
}
|
||||
return this.MCPQTeam.code;
|
||||
}
|
||||
|
||||
public MCField.MCTeam getMCPQTeam() {
|
||||
return MCPQTeam;
|
||||
}
|
||||
|
||||
public void setMCPQTeam(MCField.MCTeam MCPQTeam) {
|
||||
this.MCPQTeam = MCPQTeam;
|
||||
}
|
||||
|
||||
public MCParty getMCPQParty() {
|
||||
return MCPQParty;
|
||||
}
|
||||
|
||||
public void setMCPQParty(MCParty MCPQParty) {
|
||||
this.MCPQParty = MCPQParty;
|
||||
}
|
||||
|
||||
public MCField getMCPQField() {
|
||||
return MCPQField;
|
||||
}
|
||||
|
||||
public void setMCPQField(MCField MCPQField) {
|
||||
this.MCPQField = MCPQField;
|
||||
}
|
||||
|
||||
public int getAvailableCP() {
|
||||
return availableCP;
|
||||
}
|
||||
|
||||
public void setAvailableCP(int availableCP) {
|
||||
this.availableCP = availableCP;
|
||||
}
|
||||
|
||||
public int getTotalCP() {
|
||||
return totalCP;
|
||||
}
|
||||
|
||||
public void setTotalCP(int totalCP) {
|
||||
this.totalCP = totalCP;
|
||||
}
|
||||
|
||||
public void gainCP(int cp) {
|
||||
this.availableCP += cp;
|
||||
this.totalCP += cp;
|
||||
}
|
||||
|
||||
public void loseCP(int cp) {
|
||||
this.availableCP -= cp;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
Add this under disconnect() (right after event instance calls onPlayerDisconnect, preferably):
|
||||
PHP Code:
|
||||
if (chr.getMCPQField() != null) {
|
||||
chr.getMCPQField().onPlayerDisconnected(player);
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
Add to getMonster(int monsterId):
|
||||
PHP Code:
|
||||
stats.setCp(MapleDataTool.getIntConvert("getCP", monsterInfoData, 0));
|
||||
@@ -1,80 +0,0 @@
|
||||
Add fields:
|
||||
PHP Code:
|
||||
private boolean respawning = true;
|
||||
private MCWZData mcpqData;
|
||||
Add methods:
|
||||
PHP Code:
|
||||
public final List<MapleMonster> getAllMonsters() { return getAllMapObjects(MapleMapObjectType.MONSTER);
|
||||
}
|
||||
|
||||
public void addMonsterSpawn(MapleMonster monster, int mobTime, int team) {
|
||||
Point newpos = calcPointBelow(monster.getPosition());
|
||||
newpos.y -= 1;
|
||||
SpawnPoint sp = new SpawnPoint(monster, newpos, mobTime, team);
|
||||
monsterSpawn.add(sp);
|
||||
if (!respawning) return;
|
||||
|
||||
if (sp.shouldSpawn() || mobTime == -1) {
|
||||
sp.spawnMonster(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void setReactorState(MapleReactor reactor, byte state) {
|
||||
synchronized (this.mapobjects) {
|
||||
reactor.setState(state);
|
||||
broadcastMessage(MaplePacketCreator.triggerReactor(reactor, state));
|
||||
}
|
||||
}
|
||||
|
||||
public <E extends MapleMapObject> List<E> getAllMapObjects(MapleMapObjectType type) {
|
||||
List<E> ret = new ArrayList<>();
|
||||
synchronized (mapobjects) {
|
||||
for (MapleMapObject l : mapobjects.values()) {
|
||||
if (l.getType() == type) {
|
||||
ret.add((E) l);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void clearDrops() {
|
||||
List<MapleMapItem> items = getAllMapObjects(MapleMapObjectType.ITEM);
|
||||
for (MapleMapItem itemmo : items) {
|
||||
removeMapObject(itemmo);
|
||||
broadcastMessage(MaplePacketCreator.removeItemFromMap(itemmo.getObjectId(), 0, 0));
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<SpawnPoint> getSpawnPoints() {
|
||||
return monsterSpawn;
|
||||
}
|
||||
|
||||
public void respawn() {
|
||||
for (SpawnPoint sp : this.monsterSpawn) {
|
||||
if (sp.shouldSpawn()) {
|
||||
sp.spawnMonster(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void beginSpawning() {
|
||||
this.respawning = true;
|
||||
this.respawn();
|
||||
}
|
||||
|
||||
public boolean isRespawning() {
|
||||
return respawning;
|
||||
}
|
||||
|
||||
public void setRespawning(boolean respawning) {
|
||||
this.respawning = respawning;
|
||||
}
|
||||
|
||||
public MCWZData getMCPQData() {
|
||||
return this.mcpqData;
|
||||
}
|
||||
|
||||
public void setMCPQData(MCWZData data) {
|
||||
this.mcpqData = data;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
Add to getMap() method, under where it parses PQ areas:
|
||||
PHP Code:
|
||||
MapleData mcData = mapData.getChildByPath("monsterCarnival");if (mcData != null) {
|
||||
MCWZData mcpqInfo = new MCWZData(mcData);
|
||||
map.setMCPQData(mcpqInfo);
|
||||
map.setRespawning(false);
|
||||
}
|
||||
Add to getMap() method, under where it parses mobTime:
|
||||
PHP Code:
|
||||
int team = MapleDataTool.getInt("team", life, -1);
|
||||
Change addMonsterSpawn() method call to the following, using the new SpawnPoint construction we defined in MapleMap:
|
||||
PHP Code:
|
||||
map.addMonsterSpawn(monster, mobTime, team);
|
||||
Add the method:
|
||||
PHP Code:
|
||||
public MapleMap instanceMap(int mapid, boolean respawns, boolean npcs) { return instanceMap(mapid, respawns, npcs, true);
|
||||
}
|
||||
and
|
||||
|
||||
PHP Code:
|
||||
public MapleMap instanceMap(int mapid, boolean respawns, boolean npcs, boolean reactors)
|
||||
, where the code is the same as getMap but does not try to load from cache and does not store into cache.
|
||||
@@ -1,31 +0,0 @@
|
||||
Add fields:
|
||||
PHP Code:
|
||||
private int team = -1;
|
||||
|
||||
Add methods:
|
||||
PHP Code:
|
||||
public int getCP() { return stats.getCp();
|
||||
}
|
||||
|
||||
public int getTeam() {
|
||||
return team;
|
||||
}
|
||||
|
||||
public void setTeam(int team) {
|
||||
this.team = team;
|
||||
}
|
||||
|
||||
public void dispel() {
|
||||
if (!isAlive()) return;
|
||||
|
||||
for (MonsterStatus i : MonsterStatus.values()) {
|
||||
if (monsterBuffs.contains(i)) {
|
||||
removeMonsterBuff(i);
|
||||
MaplePacket packet = MaplePacketCreator.cancelMonsterStatus(getObjectId(), Collections.singletonMap(i, Integer.valueOf(1)));
|
||||
map.broadcastMessage(packet, getPosition());
|
||||
if (getController() != null && !getController().isMapObjectVisible(MapleMonster.this)) {
|
||||
getController().getClient().getSession().write(packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
Add field:
|
||||
PHP Code:
|
||||
private int cp;
|
||||
|
||||
Add methods:
|
||||
PHP Code:
|
||||
public int getCp() {
|
||||
return cp;
|
||||
}
|
||||
|
||||
public void setCp(int cp) {
|
||||
this.cp = cp;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
Under hitReactor(), add before standard handling:
|
||||
PHP Code:
|
||||
if (c.getPlayer().getMCPQField() != null) {
|
||||
c.getPlayer().getMCPQField().onGuardianHit(c.getPlayer(), this);
|
||||
return;
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
Add fields:
|
||||
PHP Code:
|
||||
private boolean consumeOnPickup, party;
|
||||
private int cp, nuffSkill;
|
||||
|
||||
Add to stat parsing (loadFromData()):
|
||||
PHP Code:
|
||||
|
||||
ret.cp = MapleDataTool.getInt("cp", source, 0);ret.party = MapleDataTool.getInt("party", source, 0) > 0;
|
||||
ret.consumeOnPickup = MapleDataTool.getInt("consumeOnPickup", source, 0) > 0;
|
||||
ret.nuffSkill = MapleDataTool.getInt("nuffSkill", source, -1);
|
||||
Add methods:
|
||||
PHP Code:
|
||||
public int getCP() { return cp;
|
||||
}
|
||||
|
||||
public boolean isParty() {
|
||||
return party;
|
||||
}
|
||||
|
||||
public boolean isConsumeOnPickup() {
|
||||
return consumeOnPickup;
|
||||
}
|
||||
|
||||
public int getNuffSkill() {
|
||||
return nuffSkill;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
Add to applyEffect():
|
||||
|
||||
PHP Code:
|
||||
case 150: monStat = MonsterStatus.WEAPON_ATTACK_UP;
|
||||
break;
|
||||
case 151:
|
||||
monStat = MonsterStatus.WEAPON_DEFENSE_UP;
|
||||
break;
|
||||
case 152:
|
||||
monStat = MonsterStatus.MAGIC_ATTACK_UP;
|
||||
break;
|
||||
case 153:
|
||||
monStat = MonsterStatus.MAGIC_DEFENSE_UP;
|
||||
break;
|
||||
case 154:
|
||||
monStat = MonsterStatus.ACC;
|
||||
break;
|
||||
case 155:
|
||||
monStat = MonsterStatus.AVOID;
|
||||
break;
|
||||
case 156:
|
||||
monStat = MonsterStatus.SPEED;
|
||||
break;
|
||||
@@ -1,41 +0,0 @@
|
||||
package net.sf.odinms.net.channel.handler;
|
||||
import net.sf.odinms.client.MapleCharacter;
|
||||
import net.sf.odinms.client.MapleClient;
|
||||
import net.sf.odinms.net.AbstractMaplePacketHandler;
|
||||
import net.sf.odinms.server.partyquest.mcpq.MCField;
|
||||
import net.sf.odinms.server.partyquest.mcpq.MCTracker;
|
||||
import net.sf.odinms.server.partyquest.mcpq.MonsterCarnival;
|
||||
import net.sf.odinms.tools.data.input.SeekableLittleEndianAccessor;
|
||||
|
||||
/**
|
||||
* Packet handler for Monster Carnival.
|
||||
* @author s4nta
|
||||
*/
|
||||
public class MonsterCarnivalHandler extends AbstractMaplePacketHandler {
|
||||
|
||||
@Override
|
||||
public void handlePacket(SeekableLittleEndianAccessor slea, MapleClient c) {
|
||||
int tab = slea.readByte();
|
||||
int num = slea.readByte();
|
||||
MapleCharacter chr = c.getPlayer();
|
||||
|
||||
if (MonsterCarnival.DEBUG) {
|
||||
MCTracker.log("[MCHandler] " + chr.getName() + " used tab " + tab + " num " + num);
|
||||
System.out.println("[MCHandler] " + chr.getName() + " used tab " + tab + " num " + num);
|
||||
}
|
||||
|
||||
if (chr.getMCPQField() == null || chr.getMCPQParty() == null) {
|
||||
MCTracker.log("[MCHandler] " + chr.getName() + " attempting to use Monster Carnival handler without being in Monster Carnival");
|
||||
return;
|
||||
}
|
||||
|
||||
MCField field = chr.getMCPQField();
|
||||
if (tab == 0) {
|
||||
field.onAddSpawn(c.getPlayer(), num);
|
||||
} else if (tab == 1) {
|
||||
field.onUseSkill(c.getPlayer(), num);
|
||||
} else if (tab == 2) { // status
|
||||
field.onGuardianSummon(c.getPlayer(), num);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
else if (c.getPlayer().getMCPQField() != null) { // CPQ Handling
|
||||
boolean consumed = c.getPlayer().getMCPQField().onItemPickup(c.getPlayer(), mapitem);
|
||||
if (consumed) {
|
||||
c.getPlayer().getMap().broadcastMessage(MaplePacketCreator.removeItemFromMap(mapitem.getObjectId(), 2, c.getPlayer().getId()),
|
||||
mapitem.getPosition());
|
||||
c.getPlayer().getCheatTracker().pickupComplete();
|
||||
c.getPlayer().getMap().removeMapObject(ob);
|
||||
} else {
|
||||
if (MapleInventoryManipulator.addFromDrop(c, mapitem.getItem(), true)) {
|
||||
c.getPlayer().getMap().broadcastMessage(
|
||||
MaplePacketCreator.removeItemFromMap(mapitem.getObjectId(), 2, c.getPlayer().getId()),
|
||||
mapitem.getPosition());
|
||||
c.getPlayer().getCheatTracker().pickupComplete();
|
||||
c.getPlayer().getMap().removeMapObject(ob);
|
||||
} else {
|
||||
c.getPlayer().getCheatTracker().pickupComplete();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
Add field:
|
||||
PHP Code:
|
||||
private int team = -1;
|
||||
Add constructor:
|
||||
PHP Code:
|
||||
public SpawnPoint(MapleMonster monster, Point pos, int mobTime, int team) { super();
|
||||
this.monster = monster;
|
||||
this.pos = new Point(pos);
|
||||
this.mobTime = mobTime;
|
||||
this.immobile = !monster.isMobile();
|
||||
this.nextPossibleSpawn = System.currentTimeMillis();
|
||||
this.team = team;
|
||||
}
|
||||
Add monster death listener under spawnMonster():
|
||||
PHP Code:
|
||||
if (team > -1) { final int cp = mob.getCP();
|
||||
mob.addListener(new MonsterListener() {
|
||||
|
||||
@Override
|
||||
public void monsterKilled(MapleMonster monster, MapleCharacter highestDamageChar) {
|
||||
if (highestDamageChar == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (highestDamageChar.getMCPQParty() == null) {
|
||||
MCTracker.log("Attempted to give CP to character without assigned MCPQ Party.");
|
||||
return;
|
||||
}
|
||||
|
||||
highestDamageChar.getMCPQField().monsterKilled(highestDamageChar, cp);
|
||||
|
||||
}
|
||||
});
|
||||
mob.setTeam(team);
|
||||
}
|
||||
20
docs/moveactions.txt
Normal file
20
docs/moveactions.txt
Normal file
@@ -0,0 +1,20 @@
|
||||
0 walk right
|
||||
1 walk left
|
||||
2 walk right
|
||||
3 walk left
|
||||
4 stand right
|
||||
5 stand left
|
||||
6 jump right
|
||||
7 jump left
|
||||
8 defend right
|
||||
9 defend left
|
||||
10 prone right
|
||||
11 prone left
|
||||
12 swim right
|
||||
13 swim left
|
||||
14 15 ladder left
|
||||
16 17 ladder mid
|
||||
18 dead right
|
||||
19 dead left
|
||||
20 sit right
|
||||
21 sit left
|
||||
File diff suppressed because it is too large
Load Diff
28
docs/npcmarkups.txt
Normal file
28
docs/npcmarkups.txt
Normal file
@@ -0,0 +1,28 @@
|
||||
Source: http://forum.ragezone.com/f428/add-npc-scripting-605225/
|
||||
|
||||
NPC Markups:
|
||||
#b = Blue text.
|
||||
#c[itemid]# Shows how many [itemid] the player has in their inventory.
|
||||
#d = Purple text.
|
||||
#e = Bold text.
|
||||
#f[imagelocation]# - Shows an image inside the .wz files.
|
||||
#g = Green text.
|
||||
#h # - Shows the name of the player.
|
||||
#i[itemid]# - Shows a picture of the item.
|
||||
#k = Black text.
|
||||
#l - Selection close.
|
||||
#m[mapid]# - Shows the name of the map.
|
||||
#n = Normal text (removes bold).
|
||||
#o[mobid]# - Shows the name of the mob.
|
||||
#p[npcid]# - Shows the name of the NPC.
|
||||
#q[skillid]# - Shows the name of the skill.
|
||||
#r = Red text.
|
||||
#s[skillid]# - Shows the image of the skill.
|
||||
#t[itemid]# - Shows the name of the item.
|
||||
#v[itemid]# - Shows a picture of the item.
|
||||
#x - Returns "0%" (need more information on this).
|
||||
#z[itemid]# - Shows the name of the item.
|
||||
#B[%]# - Shows a 'progress' bar.
|
||||
#F[imagelocation]# - Shows an image inside the .wz files.
|
||||
#L[number]# Selection open.
|
||||
\r\n - Moves down a line.
|
||||
@@ -1,52 +0,0 @@
|
||||
========== MapleSolaxiaV2 ==========
|
||||
Credits:
|
||||
Ronan - Freelance Developer
|
||||
Vcoc - Freelance Developer
|
||||
|
||||
---------------------------
|
||||
ToDo / Missing features list:
|
||||
---------------------------
|
||||
|
||||
|
||||
---------------------------
|
||||
** Others **
|
||||
- Marriage
|
||||
---------------------------
|
||||
|
||||
|
||||
---------------------------
|
||||
** Quest **
|
||||
---------------------------
|
||||
|
||||
|
||||
---------------------------
|
||||
** Basic PQs **
|
||||
---------------------------
|
||||
|
||||
|
||||
---------------------------
|
||||
** Packet issues & advanced PQs **
|
||||
- Mystic Doors (won't deploy players properly is some situations, only destination map matches).
|
||||
- Ariant Party Quest
|
||||
- Monster Carnival 1/2 Party Quest
|
||||
- Nett's Pyramid Party Quest
|
||||
---------------------------
|
||||
|
||||
|
||||
---------------------------
|
||||
** Skills **
|
||||
---------------------------
|
||||
|
||||
|
||||
---------------------------
|
||||
** Jobs **
|
||||
- Check Aran
|
||||
- Check Cygnus Knights
|
||||
---------------------------
|
||||
|
||||
|
||||
---------------------------
|
||||
** GM/ADMIN **
|
||||
---------------------------
|
||||
|
||||
====================================
|
||||
@@ -1,206 +0,0 @@
|
||||
/**
|
||||
---------------------------------------------------------------------------------------------------
|
||||
* NPC Name: High Priest John - ID: 9201002.js
|
||||
* @author Vcoc
|
||||
* @author Ronan
|
||||
---------------------------------------------------------------------------------------------------
|
||||
**/
|
||||
importPackage(Packages.client);
|
||||
importPackage(Packages.server);
|
||||
importPackage(Packages.tools);
|
||||
|
||||
var status;
|
||||
var minLevel = 10;
|
||||
var maxLevel = 200;
|
||||
var mySelection = -1;
|
||||
var rings = Array(1112001, 1112002, 1112003, 1112005, 1112006);
|
||||
|
||||
function start() {
|
||||
status = -1;
|
||||
action(1, 0, 0);
|
||||
}
|
||||
|
||||
function action(mode, type, selection) {
|
||||
if (mode == 1) {
|
||||
status++;
|
||||
} else {
|
||||
if (type == 1 && mode == 0)
|
||||
cm.sendOk("...");
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
if (cm.getPlayer().getMapId() == 680000000) {
|
||||
if (status == 0) {
|
||||
cm.sendSimple("Olá #h #,\r\n#bO que você gostaria de fazer hoje?#b\r\n#L0#Eu quero me casar!#l\r\n#L1#Eu quero ver meus amigos no casamento!#l\r\n#L2#Quero trocar um Bilhete Premium de casamento por 5 convites!#l\r\n#L3#Eu quero comprar um Bilhete de Casamento!#l\r\n#L4#Gostaria de obter uma licença de casamento.#l");
|
||||
} else if (status == 1) {
|
||||
if (selection == 0) {
|
||||
if (cm.getParty() == null) { // no party
|
||||
cm.sendOk("Para se casar e necessario estar em grupo com a parceira(o)!");
|
||||
cm.dispose();
|
||||
} else if (!cm.isLeader()) { // not party leader
|
||||
cm.sendOk("Por favor, fale ao seu parceiro(a) para falar comigo.");
|
||||
cm.dispose();
|
||||
} else {
|
||||
var party = cm.getParty().getMembers();
|
||||
var mapId = cm.getPlayer().getMapId();
|
||||
var levelValid = 0;
|
||||
var genderRight = 0;
|
||||
var alreadyMarried = 0;
|
||||
for (var i = 0; i < party.size(); i++) {
|
||||
var pPlayer = party.get(i);
|
||||
if (pPlayer.getLevel() >= minLevel && pPlayer.getLevel() <= maxLevel)
|
||||
levelValid += 1;
|
||||
if (pPlayer.getGender() == 0) {
|
||||
genderRight += 1;
|
||||
} else if (pPlayer.getGender() == 1) {
|
||||
genderRight += 2;
|
||||
}
|
||||
if (pPlayer.isMarried() == 1) {
|
||||
alreadyMarried += 1;
|
||||
}
|
||||
}
|
||||
if (party.size() == 2) {
|
||||
if (party.get(0).getGender() == 0) { // leader.
|
||||
if (levelValid == 2 || cm.partyMembersInMap() == 2) {
|
||||
if (genderRight == 3) {
|
||||
if (alreadyMarried == 0) {
|
||||
if (cm.haveItem(4031374, 1) && cm.haveItem(5251003, 1)) {
|
||||
// Kick it into action. Slate says nothing here, just warps you in.
|
||||
var em = cm.getEventManager("CathedralWedding");
|
||||
if (em == null) {
|
||||
cm.sendOk("Indisponivel!");
|
||||
} else {
|
||||
// Begin the Wedding o.O
|
||||
em.startInstance(cm.getParty(), cm.getPlayer().getMap());
|
||||
party = cm.getPlayer().getEventInstance().getPlayers();
|
||||
var hname = party.get(0).getName();
|
||||
var wname = party.get(1).getName();
|
||||
var StringLine = "[" + hname + " & " + wname + "] Irão se casar na Catedral, no canal (" + cm.getC().getChannel() + ").";
|
||||
cm.worldMessage(5, StringLine);
|
||||
var eim = cm.getChar().getEventInstance();
|
||||
eim.setProperty("husband", party.get(0).getName());
|
||||
eim.setProperty("wife", party.get(1).getName());
|
||||
}
|
||||
} else
|
||||
cm.sendOk("Você não tem os itens necessários, desculpe!");
|
||||
} else
|
||||
cm.sendOk("Você já está casado.");
|
||||
} else
|
||||
cm.sendOk("O nosso servidor não suporta este tipo de casamento!");
|
||||
} else
|
||||
cm.sendOk("Vocês precisam estar no mesmo mapa e ser pelo menos no nível ["+minLevel+" ~ "+maxLevel+"]");
|
||||
} else
|
||||
cm.sendOk("Por favor faça o teu marido lider do grupo.");
|
||||
} else
|
||||
cm.sendOk("Somentos marido e mulher no grupo!");
|
||||
cm.dispose();
|
||||
}
|
||||
} else if (selection == 1) {
|
||||
if (cm.haveItem(5251100, 1)) {
|
||||
cm.sendGetText("Por favor, insira o nome de um dos membros do casamento .");
|
||||
} else {
|
||||
cm.sendOk("Parece que o casal que você quer assistir não te deu um convite ainda.");
|
||||
cm.dispose();
|
||||
}
|
||||
} else if (selection == 2) {
|
||||
if (cm.haveItem(5251003, 1)) {
|
||||
cm.gainItem(5251003, -1);
|
||||
cm.gainItem(5251100,5);
|
||||
} else {
|
||||
cm.sendOk("Você não tem o Bilhete de Casamento Premium.");
|
||||
}
|
||||
cm.dispose();
|
||||
} else if (selection == 3) {
|
||||
cm.sendOk("Você pode comprar um Bilhete de Casamento com a Ria! Localizada no Mercado Livre.");
|
||||
|
||||
cm.dispose();
|
||||
} else if (selection == 4) {
|
||||
if (cm.getPlayer().getMarriageQuestLevel() == 50) {
|
||||
cm.sendNext("Por favor, vá visitar a Mom eo Dad em sua casa. Eles vivem em algum lugar Henesys Hunting Ground II.");
|
||||
cm.getPlayer().addMarriageQuestLevel();
|
||||
} else if (cm.getPlayer().getMarriageQuestLevel() == 53) {
|
||||
if (cm.haveItem(4031373, 1)) {
|
||||
cm.sendNext("Pronto, aqui sua permissão!");
|
||||
cm.removeAll(4031373);
|
||||
cm.gainItem(4031374, 1);
|
||||
cm.getPlayer().setMarriageQuestLevel(100);
|
||||
} else {
|
||||
cm.sendNext("Você não tem a benção de Mom e Dad!");
|
||||
}
|
||||
} else {
|
||||
cm.sendNext("Eu não sei o que você está falando.");
|
||||
}
|
||||
cm.dispose();
|
||||
}
|
||||
} else if (status == 2) {
|
||||
var chr = cm.getCharByName(cm.getText());
|
||||
if (chr != null) {
|
||||
if (chr.getMapId() == 680000200) {
|
||||
var eim = chrr.getEventInstance();
|
||||
eim.registerPlayer(cm.getPlayer());
|
||||
} else {
|
||||
cm.sendOk("O casamento que você gostaria de participar não foi iniciado.");
|
||||
}
|
||||
} else
|
||||
cm.sendOk("Jogador não encontrado.");
|
||||
cm.dispose();
|
||||
}
|
||||
} else if (cm.getPlayer().getMapId() == 680000210) {
|
||||
var eim = cm.getPlayer().getEventInstance();
|
||||
|
||||
var husbandName = eim.getProperty("husband");
|
||||
var wifeName = eim.getProperty("wife");
|
||||
|
||||
var husband = cm.getCharByName(husbandName);
|
||||
var wife = cm.getCharByName(wifeName);
|
||||
|
||||
var id = cm.getPlayer().getId();
|
||||
|
||||
var hclicked = eim.getProperty("hclicked");
|
||||
var wclicked = eim.getProperty("hclicked");
|
||||
|
||||
var otherChar = husband == cm.getPlayer() ? wife : husband;
|
||||
|
||||
if (husband != null && wife != null) {
|
||||
if (status == 0) {
|
||||
if (id != husband.getId() && id != husband.getId()) {
|
||||
cm.sendOk("Você não está se casando!");
|
||||
cm.dispose();
|
||||
} else if (cm.getPlayer().isMarried() > 0) {
|
||||
cm.sendOk("Você já foi casado.");
|
||||
cm.dispose();
|
||||
} else if (hclicked == 1 && husbandName.equals(cm.getPlayer().getName())) {
|
||||
cm.sendOk("Você já aceitou casar-se com sua esposa, pergunte à sua esposa a aceitar agora");
|
||||
cm.dispose();
|
||||
} else if (wclicked == 1 && wifeName.equals(cm.getPlayer().getName())) {
|
||||
cm.sendOk("Você já aceitou casar-se com o seu marido , pergunte ao seu marido a aceitar agora");
|
||||
cm.dispose();
|
||||
} else {
|
||||
cm.sendYesNo("Você deseja se casar com seu parceiro?\r\n\r\nIsso será uma decisão final.");
|
||||
}
|
||||
} else if (status == 1) {
|
||||
if (husband == cm.getPlayer())
|
||||
eim.setProperty("hclicked", 1);
|
||||
else if (wife == cm.getPlayer())
|
||||
eim.setProperty("wclicked", 1);
|
||||
else {
|
||||
cm.sendOk("Como assim?");
|
||||
cm.dispose();
|
||||
}
|
||||
|
||||
if (eim.getProperty("hclicked") == 1 && eim.getProperty("hclicked") == 1) {
|
||||
if (!cm.createMarriage(otherChar.getName())) {
|
||||
cm.sendOk("O sistema não pode encontrar o seu parceiro.");
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
cm.worldMessage(5, "Parabéns a "+husbandName+" e "+wifeName+". São recém-casados, você pode enchê-los de spam agora!");
|
||||
cm.removeAll(4031374);
|
||||
MapleInventoryManipulator.removeById(otherChar.getClient(), MapleInventoryType.USE, 4031374, otherChar.getItemQuantity(4031374, false), false, false);
|
||||
cm.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
var status = 0;
|
||||
|
||||
function start() {
|
||||
status = -1;
|
||||
action(1, 0, 0);
|
||||
}
|
||||
|
||||
function action(mode, type, selection) {
|
||||
if (mode == -1) {
|
||||
cm.dispose();
|
||||
}else if (mode == 0){
|
||||
cm.dispose();
|
||||
return;
|
||||
} else {
|
||||
if (mode == 1)
|
||||
status++;
|
||||
else
|
||||
status--;
|
||||
if (status == 0) {
|
||||
cm.sendOk("Wow Vickii! You look so beautiful today. Are you ready to move on to the next part of this surprise?\r\n I will be giving you a tour for our chapel.");
|
||||
cm.getPlayer().startWedding();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
34
docs/wzchanges_gist.txt
Normal file
34
docs/wzchanges_gist.txt
Normal file
@@ -0,0 +1,34 @@
|
||||
Changes from the original v83 WZs:
|
||||
|
||||
Character.wz/*:
|
||||
Upgraded info of some items.
|
||||
|
||||
Map.wz/MapX/*:
|
||||
Fixed entries of portals placed incorrectly.
|
||||
|
||||
Item.wz/*:
|
||||
Fixed lacking "slotMax" properties in some items.
|
||||
Set flag "Quest Item" for some items.
|
||||
|
||||
Quest.wz/*:
|
||||
Fixed a bunch of quests, now giving the proper output. Added new quests.
|
||||
|
||||
String.wz/*:
|
||||
Fixed some NPC speeches.
|
||||
Updated MonsterBook with current drop data on the sql's DB, using Ronan's
|
||||
MobBookUpdate facility.
|
||||
|
||||
|
||||
P.S.:
|
||||
|
||||
Yeah, these explanations are pretty simplistic, I know. If one really wants to
|
||||
compare the original v83 WZ with the ones I provided, I recommend do the following:
|
||||
- Open HaRepacker and, for each Cosmic's WZ file, extract all the XMLs
|
||||
for "Private Server".
|
||||
- Now, install MapleStory from "ManagerMsv83.exe" on an other folder and do the
|
||||
same procediment said above.
|
||||
- Finally use some app to compare folders, like WinMerge, tracking differences
|
||||
for all WZs.
|
||||
|
||||
Simply edit out any modification that ranges too far from the original MapleStory server
|
||||
and overwrite the given WZ file, assuming you want a server more "GMS-like".
|
||||
@@ -264,7 +264,7 @@
|
||||
5160006 - Sparkling Eyes - On the KeyConfig, configure this expression on a button of your choice. Press the button and watch your character display sparkling eyes.
|
||||
5160007 - Flaming - On the KeyConfig, configure this expression on a button of your choice. Press the button and watch your character display the look of rage.
|
||||
5160008 - Ray - On the KeyConfig, configure this expression on a button of your choice. Press the button and watch your character display beaming eyes.
|
||||
5160009 - Goo Goo - On the KeyConfig, configure this expression on a button of your choice. Press the button and watch your character display the look of “awesome!!!”
|
||||
5160009 - Goo Goo - On the KeyConfig, configure this expression on a button of your choice. Press the button and watch your character display the look of <EFBFBD>awesome!!!<EFBFBD>
|
||||
5160010 - Whoa Whoa - On the KeyConfig, configure this expression on a button of your choice. Press the button and watch your character display the look of being flustered.
|
||||
5160011 - Constant Sigh - On the KeyConfig, configure this expression on a button of your choice. Press the button and watch your character display the thinking look.
|
||||
5160012 - Drool - On the KeyConfig, configure this expression on a button of your choice. Press the button and watch your character act like falling asleep.
|
||||
@@ -405,7 +405,7 @@
|
||||
5420004 - Orbis Hair Membership Coupon - Use it at #cOrbis Hair Salon# to change your hair to a style of #cyour choice#.
|
||||
5420005 - Ludibrium Hair Membership Coupon - Use it at #cLudibrium Hair Salon# to change your hair to a style of #cyour choice#.
|
||||
5420006 - Mu Lung Hair Membership Coupon - Use it at #cMu Lung Hair Salon# to change your hair to a style of #cyour choice#.
|
||||
5430000 - Extra Character Slot Coupon - Increases the character creation slot by 1. Each account may hold a maximum of 6 character slots per server world.
|
||||
5430000 - Extra Character Slot Coupon - Increases the character creation slot by 1. You may have up to 15 slots.
|
||||
5431000 - Maple Life (A-Type) - #c*Warning: If you do not have an empty Character slot, it cannot be used.#\r\n\r\nIf you are over #cLevel 30#, a new Level 30 character can be created in your world.You can choose one of the following classes #c(Warrior, Magician, Thief, Bowman and Pirate)# at #c1st Job status#.\r\n\r\nOnly the amount of AP needed for each respective 1st jobs have been allocated and the rest of AP and SP can be distributed to your liking.#cBasic equips and items# needed for travel are also provided.
|
||||
5432000 - Maple Life (B-Type) - #c*Warning : If all 12 character slots are full, it cannot be used.#\r\n\r\nThis package has the #cMaple Life item plus an Extra Character Slot coupon.#Using this item will automiatically create a new slot.\r\n\r\nIf you are over #cLevel 30#, a new Level 30 character can be created in your world. You can choose one of the following classes #c(Warrior, Magician, Thief, Bowman and Pirate)# at #c1st Job status.#\r\n\r\nOnly the amount of AP needed for each respective 1st jobs have been allocated and the rest of AP and SP can be distributed to your liking.#cBasic equips and items# needed for travel are also provided.
|
||||
5450000 - Miu Miu the Traveling Merchant - Use this to experience the same effect as entering a general store. Can purchase potions to recover HP & MP, throwing stars, and recharge bullets. Some maps restrict the use of this item, though.
|
||||
@@ -479,9 +479,9 @@
|
||||
5610001 - Vega's Spell(60%) - This winning spell from Vega enables a 90% success rate on a 60% scroll. Please check the scroll description to confirm that Vega's Spell is available for the scroll you choose.
|
||||
5590000 - High-Five Stamp - Can equip items that are 5 levels above your current level.
|
||||
5021026 - Gift Box Throwing Stars - A gift box that can be freely thrown around. Using the #cThrowing Star# will create an orbital effect.\n\nThis item cannot be deleted.
|
||||
5010073 - Miss Popular - Well, lookie here. Someone’s certainly become popular with the guys. Turn this effect on and off by assigning it to a shortcut key from the keyboard settings menu.
|
||||
5010073 - Miss Popular - Well, lookie here. Someone<EFBFBD>s certainly become popular with the guys. Turn this effect on and off by assigning it to a shortcut key from the keyboard settings menu.
|
||||
|
||||
5010074 - Mr. Popular - Well, lookie here. Someone’s certainly become popular with the girls. Turn this effect on and off by assigning it to a shortcut key from the keyboard settings menu.
|
||||
5010074 - Mr. Popular - Well, lookie here. Someone<EFBFBD>s certainly become popular with the girls. Turn this effect on and off by assigning it to a shortcut key from the keyboard settings menu.
|
||||
|
||||
5240027 - Golden Drumstick - A drumstick that can be consumed only by #cBaby Tiger#. It recovers hunger and #cincreases Closeness by 100.#
|
||||
5390005 - Cute Tiger Messenger - Shout to everyone in the world your character is on with this megaphone. Now available with your avatar on the top of everyone's screen! Comes with a tiger background for your avatar.
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
1122040 - Sealed Mind of Maple Necklace - A Mind of Maple Necklace that has been sealed up. One more gem, and its mystical powers will begin to be restored.
|
||||
1122040 - Bronze Maple Necklace - A light-weight bronze Maple Necklace.
|
||||
1122041 - Sealed Mind of Maple Necklace - A Mind of Maple Necklace that has been sealed up. One more gem, and its mystical powers will begin to be restored.
|
||||
1122042 - Sealed Mind of Maple Necklace - A Mind of Maple Necklace that has been sealed up. One more gem, and its mystical powers will begin to be restored.
|
||||
1122043 - Sealed Mind of Maple Necklace - A Mind of Maple Necklace that has been sealed up. One more gem, and its mystical powers will begin to be restored.
|
||||
1122044 - Sealed Mind of Maple Necklace - A Mind of Maple Necklace that has been sealed up. One more gem, and its mystical powers will begin to be restored.
|
||||
1122045 - Sealed Mind of Maple Necklace - A Mind of Maple Necklace that has been sealed up. One more gem, and its mystical powers will begin to be restored.
|
||||
1122046 - Restoring Mind of Maple Necklace - A Mind of Maple Necklace that is beginning to be restored. One more gem, and its mystical powers will be amplified and awakened into a power on another level.
|
||||
1122046 - Silver Maple Necklace - A shiny silver Maple Necklace.
|
||||
1122047 - Restoring Mind of Maple Necklace - A Mind of Maple Necklace that is beginning to be restored. One more gem, and its mystical powers will be amplified and awakened into a power on another level.
|
||||
1122048 - Restoring Mind of Maple Necklace - A Mind of Maple Necklace that is beginning to be restored. One more gem, and its mystical powers will be amplified and awakened into a power on another level.
|
||||
1122049 - Restoring Mind of Maple Necklace - A Mind of Maple Necklace that is beginning to be restored. One more gem, and its mystical powers will be amplified and awakened into a power on another level.
|
||||
1122050 - Restoring Mind of Maple Necklace - A Mind of Maple Necklace that is beginning to be restored. One more gem, and its mystical powers will be amplified and awakened into a power on another level.
|
||||
1122051 - Restoring Mind of Maple Necklace - A Mind of Maple Necklace that is beginning to be restored. One more gem, and its mystical powers will be amplified and awakened into a power on another level.
|
||||
1122052 - Awakening Mind of Maple Necklace - A Mind of Maple Necklace that is beginning to be restored. One more gem, and its mystical powers will be amplified and awakened into a power on another level.
|
||||
1122052 - Golden Maple Necklace - A Maple Necklace of 21 karats.
|
||||
1122053 - Awakening Mind of Maple Necklace - A Mind of Maple Necklace that is beginning to be restored. One more gem, and its mystical powers will be amplified and awakened into a power on another level.
|
||||
1122054 - Awakening Mind of Maple Necklace - A Mind of Maple Necklace that is beginning to be restored. One more gem, and its mystical powers will be amplified and awakened into a power on another level.
|
||||
1122055 - Awakening Mind of Maple Necklace - A Mind of Maple Necklace that is beginning to be restored. One more gem, and its mystical powers will be amplified and awakened into a power on another level.
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
1102080 - Ragged Blue Cape - (no description)
|
||||
1102081 - Ragged Yellow Cape - (no description)
|
||||
1102082 - Ragged Black Cape - (no description)
|
||||
1102083 - Ragged Red Cape - (no description)
|
||||
1102083 - Ragged Green Cape - (no description)
|
||||
1102084 - Pink Gaia Cape - (no description)
|
||||
1102085 - Yellow Gaia Cape - (no description)
|
||||
1102086 - Purple Gaia Cape - (no description)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -55,6 +55,9 @@
|
||||
30102 - Brown Fantasy - (no description)
|
||||
30103 - Green Fantasy - (no description)
|
||||
30104 - Blue-Green Fantasy - (no description)
|
||||
30105 - Blue Fantasy - (no description)
|
||||
30106 - Maroon Fantasy - (no description)
|
||||
30107 - Brown Fantasy - (no description)
|
||||
30110 - Black Fireball - (no description)
|
||||
30111 - Red Fireball - (no description)
|
||||
30112 - Orange Fireball - (no description)
|
||||
@@ -167,14 +170,14 @@
|
||||
30245 - Blue Monkey - (no description)
|
||||
30246 - Purple Monkey - (no description)
|
||||
30247 - Brown Monkey - (no description)
|
||||
30250 - Black Afro - (no description)
|
||||
30251 - Red Afro - (no description)
|
||||
30252 - Orange Afro - (no description)
|
||||
30253 - Blonde Afro - (no description)
|
||||
30254 - Green Afro - (no description)
|
||||
30255 - Blue Afro - (no description)
|
||||
30256 - Purple Afro - (no description)
|
||||
30257 - Brown Afro - (no description)
|
||||
30250 - Black Afro (big) - (no description)
|
||||
30251 - Red Afro (big) - (no description)
|
||||
30252 - Orange Afro (big) - (no description)
|
||||
30253 - Blonde Afro (big) - (no description)
|
||||
30254 - Green Afro (big) - (no description)
|
||||
30255 - Blue Afro (big) - (no description)
|
||||
30256 - Purple Afro (big) - (no description)
|
||||
30257 - Brown Afro (big) - (no description)
|
||||
30260 - Black Metrosexual - (no description)
|
||||
30261 - Red Metrosexual - (no description)
|
||||
30262 - Orange Metrosexual - (no description)
|
||||
@@ -223,14 +226,14 @@
|
||||
30315 - Blue Acorn - (no description)
|
||||
30316 - Purple Acorn - (no description)
|
||||
30317 - Brown Acorn - (no description)
|
||||
30320 - Black Afro - (no description)
|
||||
30321 - Red Afro - (no description)
|
||||
30322 - Orange Afro - (no description)
|
||||
30323 - Blonde Afro - (no description)
|
||||
30324 - Green Afro - (no description)
|
||||
30325 - Blue Afro - (no description)
|
||||
30326 - Purple Afro - (no description)
|
||||
30327 - Brown Afro - (no description)
|
||||
30320 - Black Afro (small) - (no description)
|
||||
30321 - Red Afro (small) - (no description)
|
||||
30322 - Orange Afro (small) - (no description)
|
||||
30323 - Blonde Afro (small) - (no description)
|
||||
30324 - Green Afro (small) - (no description)
|
||||
30325 - Blue Afro (small) - (no description)
|
||||
30326 - Purple Afro (small) - (no description)
|
||||
30327 - Brown Afro (small) - (no description)
|
||||
30330 - Black Cabana Boy - (no description)
|
||||
30331 - Red Cabana Boy - (no description)
|
||||
30332 - Orange Cabana Boy - (no description)
|
||||
@@ -1151,6 +1154,14 @@
|
||||
31655 - Blue Dashing Damsel - (no description)
|
||||
31656 - Purple Dashing Damsel - (no description)
|
||||
31657 - Brown Dashing Damsel - (no description)
|
||||
31660 - Black Tighty Bun - (no description)
|
||||
31661 - Red Tighty Bun - (no description)
|
||||
31662 - Orange Tighty Bun - (no description)
|
||||
31663 - Blonde Tighty Bun - (no description)
|
||||
31664 - Green Tighty Bun - (no description)
|
||||
31665 - Blue Tighty Bun - (no description)
|
||||
31666 - Purple Tighty Bun - (no description)
|
||||
31667 - Brown Tighty Bun - (no description)
|
||||
31670 - Black Grandma ma' - (no description)
|
||||
31671 - Red Grandma ma' - (no description)
|
||||
31672 - Orange Grandma ma' - (no description)
|
||||
@@ -1488,6 +1499,7 @@
|
||||
34056 - Purple Aran Hair - (no description)
|
||||
34057 - Brown Aran Hair - (no description)
|
||||
33100 - Black The Coco - (no description)
|
||||
33101 - Red The Coco - (no description)
|
||||
33102 - Orange The Coco - (no description)
|
||||
33103 - Blond The Coco - (no description)
|
||||
33104 - Green The Coco - (no description)
|
||||
|
||||
@@ -402,7 +402,7 @@
|
||||
1402044 - Pumpkin Lantern - (no description)
|
||||
1402045 - Tiger's Fang - (no description)
|
||||
1402046 - Timeless Nibleheim - (no description)
|
||||
1402048 - Raven's Wing - (no description)
|
||||
1402048 - Raven's Wing - (no description)
|
||||
1402049 - Night Raven's Wing - (no description)
|
||||
1402050 - Dawn Raven's Wing - (no description)
|
||||
1402051 - Dusk Raven's Wing - (no description)
|
||||
|
||||
@@ -241,7 +241,7 @@
|
||||
4000172 - Three-Tailed Foxtail - A soft foxtail that Three-Tailed Fox removed from itself.
|
||||
4000173 - Broom - A small broom made from bushes that Blins dropped.
|
||||
4000174 - Money Envelope - You can sell this envelope for 10,000 meso in the store.
|
||||
4000175 - Minature Pianus - A miniature version of Pianus
|
||||
4000175 - Miniature Pianus - A miniature version of Pianus
|
||||
4000176 - Poisonous Mushroom - A poisonous mushroom that lives on the humongous Zombie Mushroom.
|
||||
4000177 - Mixed Block - A block from Mix Golem that consists of its chest area.
|
||||
4000178 - Iron Boar Armor - A small piece of the solid armor from Iron Boar.
|
||||
@@ -1779,8 +1779,8 @@
|
||||
4032103 - The Lost Treasure - The lost treasure that was stolen by the Master of Disguise who brazenly entered Ereve. Let's take it back to Irena.
|
||||
4032104 - The Lost Treasure - The lost treasure that was stolen by the Master of Disguise who brazenly entered Ereve. Let's take it back to Eckhart.
|
||||
4032105 - The Lost Treasure - The lost treasure that was stolen by the Master of Disguise who brazenly entered Ereve. Let's take it back to Hawkeye.
|
||||
4000209 - Co-ke Slime’s Bell - The bell of Co-ke Slime that has been taken off.
|
||||
4000210 - Co-ke Pig’s Ribbon - A piece of Co-ke Pig’s ribbon.
|
||||
4000209 - Co-ke Slime<EFBFBD>s Bell - The bell of Co-ke Slime that has been taken off.
|
||||
4000210 - Co-ke Pig<EFBFBD>s Ribbon - A piece of Co-ke Pig<EFBFBD>s ribbon.
|
||||
4000211 - Coca-Cola Cube - A cube with a drawing of a Coca-Cola bottle on it.
|
||||
4000212 - CokePLAY Cube - A cube with the CokePLAY symbol.
|
||||
4000213 - Coca-Cola Card - A card with a drawing of Coca-Cola.
|
||||
@@ -1802,10 +1802,10 @@
|
||||
4001151 - Happy Valley - Happy Valley
|
||||
4001152 - Ariant - Ariant
|
||||
4001153 - Magatia - Magatia
|
||||
4031832 - Sophelia’s Portrait - A portrait of Sophelia.
|
||||
4031832 - Sophelia<EFBFBD>s Portrait - A portrait of Sophelia.
|
||||
4031833 - Pumpkin Juice - A juice made with pumpkin. It is very fragrant.
|
||||
4031834 - Perfect Tool - The most perfect tool for making dolls.
|
||||
4031835 - Lyudmilla’s Earring - The earrings that Lyudmilla lost. They shine with brilliance.
|
||||
4031835 - Lyudmilla<EFBFBD>s Earring - The earrings that Lyudmilla lost. They shine with brilliance.
|
||||
4031836 - Score - The score that Lyudmilla asked for. No one knows what kind of music is in it.
|
||||
4031837 - Dumped Doll - A doll that Sophelia used to cherish a long time ago. She threw it away when she got a new doll.
|
||||
4031838 - Piece of Cloth - A small piece of cloth. If you drag and drop it onto the rag doll, the doll will be completed bit by bit.
|
||||
@@ -1893,26 +1893,26 @@
|
||||
4032127 - Proof of Ability - The Proof of Ability that is required to learn a new skill. This proof signifies that you are ready to learn a new skill.
|
||||
4032128 - Proof of Ability - The Proof of Ability that is required to learn a new skill. This proof signifies that you are ready to learn a new skill.
|
||||
4032129 - Proof of Ability - The Proof of Ability that is required to learn a new skill. This proof signifies that you are ready to learn a new skill.
|
||||
4032130 - Pig Doll - An adorable doll that resembles a pig. However, something doesn't seem right…
|
||||
4032131 - Pig Doll - An adorable doll that resembles a pig. However, something doesn't seem right…
|
||||
4032130 - Pig Doll - An adorable doll that resembles a pig. However, something doesn't seem right<EFBFBD>
|
||||
4032131 - Pig Doll - An adorable doll that resembles a pig. However, something doesn't seem right<EFBFBD>
|
||||
4032132 - Roca's Mission Report - A mission report written by Roca, the Agent for Henesys. This compiles a list of events that have taken place recently.
|
||||
4032136 - Bubbling Doll - An adorable doll that was designed based on Bubbling, but something doesn't seem right. The way it smiles just seems a bit off, as if it has hidden agenda.
|
||||
4032137 - Bubbling Doll - An adorable doll that was designed based on Bubbling, but something doesn't seem right. The way it smiles just seems a bit off, as if it has hidden agenda.
|
||||
4032138 - Bubbling Doll - An adorable doll that was designed based on Bubbling, but something doesn't seem right. It's in…tears.
|
||||
4032138 - Bubbling Doll - An adorable doll that was designed based on Bubbling, but something doesn't seem right. It's in<EFBFBD>tears.
|
||||
4032139 - Old Key - An old, rusty key that Mr. Pickall has been looking for.
|
||||
4032140 - Bubbling Doll - An adorable doll that was designed based on Bubbling, but something doesn't seem right. It's in…tears.
|
||||
4032140 - Bubbling Doll - An adorable doll that was designed based on Bubbling, but something doesn't seem right. It's in<EFBFBD>tears.
|
||||
4032141 - Mattias' Mission Report - A mission report written by Roca, the Agent for Kerning City. This compiles a list of events that have taken place recently.
|
||||
4032142 - Clear Tree Sap - A clear tree sap that can only be found at the very top of the skyscraping trees. Accompanied by the freshest green scent.
|
||||
4032143 - Fruit - A fruit picked from plants near Henesys.
|
||||
4032144 - Hersha's Mission Report - A mission report written by Hersha, the Agent for Ellinia. This compiles a list of events that have taken place recently.
|
||||
4032145 - Detector - A detector made to detect any forces of darkness. Take this to the 10 Boogies.
|
||||
4032146 - Wooden Mask Doll - An adorable doll modeled after the Wooden Mask, but something doesn't seem right…
|
||||
4032147 - Rocky Mask Doll - An adorable doll modeled after the Stone Mask, but something doesn't seem right…
|
||||
4032146 - Wooden Mask Doll - An adorable doll modeled after the Wooden Mask, but something doesn't seem right<EFBFBD>
|
||||
4032147 - Rocky Mask Doll - An adorable doll modeled after the Stone Mask, but something doesn't seem right<EFBFBD>
|
||||
4032148 - Detector - A detector created with the sole purpose of detecting the Puppeteer's movements. We put it to good use, so let's return it to Neinheart.
|
||||
4032149 - 10 Boogies' Mission Report - A mission report written by 10 Boogies, the Agents for Perion. This compiles a list of events that have taken place recently.
|
||||
4032178 - Hack Attempt - A record that shows that Chief Grays tried to hack into the system.
|
||||
4032179 - Ereve Investigation Permit - A permitt that allows one to investigate every part of Ereve. When the Red Alert is on, this permit is the only way you can roam freely around Ereve.
|
||||
4032190 - Orange Mushroom Doll - An adorable doll modeled after the Orange Mushroom, but something doesn't seem right…
|
||||
4032190 - Orange Mushroom Doll - An adorable doll modeled after the Orange Mushroom, but something doesn't seem right<EFBFBD>
|
||||
4032196 - Concentrated Formula: Step 1 - A formula concentrated with effective and potent ingredients. The first formula used to raise Mimiana and Mimio
|
||||
4032197 - Concentrated Formula: Step 2 - A formula concentrated with effective and potent ingredients. The second formula used to raise Mimiana and Mimio.
|
||||
4032198 - Concentrated Formula: Step 3 - A formula concentrated with effective and potent ingredients. The third formula used to raise Mimiana and Mimio.
|
||||
@@ -2048,16 +2048,16 @@
|
||||
4032270 - Glistening Sunlight - Glistening sunlight filled with the feeling of spring.
|
||||
4032271 - Pure Small Sprout - A fragrant new sprout filled with the energies of spring. Used as an ingredient for Pure Perfume.
|
||||
4032272 - Stationery of Longing - Pink stationary that's rumored to return a favorable response if used to send a letter to a secret crush.
|
||||
4032273 - Pencil of Courage X 10 - A pencil that's used to write things you don’t have the courage to say.
|
||||
4032273 - Pencil of Courage X 10 - A pencil that's used to write things you don<EFBFBD>t have the courage to say.
|
||||
4032275 - Pure Normal Sprout - A fragrant new sprout filled with the energies of spring. Used as an ingredient for Pure Perfume.
|
||||
4032276 - Pure Sprout - A fragrant new sprout filled with the energies of spring. Used as an ingredient for Pure Perfume.
|
||||
4032277 - Pure Large Sprout - A fragrant new sprout filled with the energies of spring. Used as an ingredient for Pure Perfume.
|
||||
4032278 - Stationery of Deep Longing - Pink stationary that's rumored to return a favorable response if used to send a letter to a secret crush.
|
||||
4032279 - Stationary of Hope and Longing - Pink stationary that's rumored to return a favorable response if used to send a letter to a secret crush.
|
||||
4032280 - Letter of Love and Longing - Pink stationary that's rumored to return a favorable response if used to send a letter to a secret crush.
|
||||
4032281 - Pencil of Courage X 100 - A pencil that's used to write things you don’t have the courage to say.
|
||||
4032282 - Pencil of Courage X 1000 - AA pencil that's used to write things you don’t have the courage to say.
|
||||
4032283 - Pencil of Courage X 10000 - A pencil that's used to write things you don’t have the courage to say.
|
||||
4032281 - Pencil of Courage X 100 - A pencil that's used to write things you don<EFBFBD>t have the courage to say.
|
||||
4032282 - Pencil of Courage X 1000 - AA pencil that's used to write things you don<EFBFBD>t have the courage to say.
|
||||
4032283 - Pencil of Courage X 10000 - A pencil that's used to write things you don<EFBFBD>t have the courage to say.
|
||||
4032284 - Child's Broken Toy - A toy stolen from a child by a monster. It's broken and cannot be used.
|
||||
4032285 - Child's Broken Toy - A toy stolen from a child by a monster. It's broken and cannot be used.
|
||||
4032286 - Child's Broken Toy - A toy stolen from a child by a monster. It's broken and cannot be used.
|
||||
|
||||
@@ -1492,7 +1492,7 @@ ossyria
|
||||
270010300 - Time Lane - Memory Lane3
|
||||
270010310 - Time Lane - Resting Spot of Memory3
|
||||
270010400 - Time Lane - Memory Lane4
|
||||
270010410 - Memory Keeper - Resting Spot of Memory4
|
||||
270010410 - Time Lane - Resting Spot of Memory4
|
||||
270010500 - Time Lane - Memory Lane5
|
||||
270020000 - Time Lane - Frozen Past
|
||||
270020100 - Time Lane - Road of Regrets1
|
||||
@@ -1565,9 +1565,9 @@ ossyria
|
||||
200090057 - Empress' Road - To Ellinia
|
||||
200090058 - Empress' Road - To Ereve
|
||||
200090059 - Empress' Road - To Ellinia
|
||||
200010303 - Hidden Street - Eliza’s Garden
|
||||
211040102 - Hidden Street - Snow Soul’s Resting Place
|
||||
209000100 - Happy Village - Cliff’s Hut
|
||||
200010303 - Hidden Street - Eliza<EFBFBD>s Garden
|
||||
211040102 - Hidden Street - Snow Soul<EFBFBD>s Resting Place
|
||||
209000100 - Happy Village - Cliff<EFBFBD>s Hut
|
||||
219000000 - Hidden Street - Coke Town
|
||||
219000001 - Hidden Street - Coke Town Sundry Goods Shop
|
||||
219000002 - Hidden Street - House of Pouch
|
||||
@@ -2175,10 +2175,10 @@ etc
|
||||
680100001 - Maple 7th Day Market - Maple 7th Day Market
|
||||
680100002 - Maple 7th Day Market - Maple 7th Day Market
|
||||
680100003 - Maple 7th Day Market - Maple 7th Day Market
|
||||
674030300 - Treasure Dungeon - (no map name)
|
||||
674030000 - Initiation - (no map name)
|
||||
674030100 - Entrance to MV's Lair - (no map name)
|
||||
674030200 - The Lair of MV - (no map name)
|
||||
674030300 - Treasure Dungeon - (no map name)
|
||||
910020000 - Hidden Street - Nest of a Baby Bird
|
||||
910100000 - Hidden Street - The Cursed Forest
|
||||
910100001 - Hidden Street - The Cursed Forest
|
||||
@@ -2863,7 +2863,7 @@ etc
|
||||
980027000 - Goldrich's Maze - Maze of Erosion
|
||||
980027100 - Goldrich's Maze - Maze of Erosion
|
||||
980027200 - Goldrich's Maze - Maze of Erosion
|
||||
980027300 - Goldrich's Maze - Beginning of the Maze…
|
||||
980027300 - Goldrich's Maze - Beginning of the Maze<EFBFBD>
|
||||
980027400 - Goldrich's Maze - Monster's Maze
|
||||
980027500 - Goldrich's Maze - Monster's Maze
|
||||
980027600 - Goldrich's Maze - Monster's Maze
|
||||
@@ -2944,7 +2944,7 @@ etc
|
||||
980027001 - Goldrich's Maze - Maze of Erosion
|
||||
980027101 - Goldrich's Maze - Maze of Erosion
|
||||
980027201 - Goldrich's Maze - Maze of Erosion
|
||||
980027301 - Goldrich's Maze - Beginning of the Maze…
|
||||
980027301 - Goldrich's Maze - Beginning of the Maze<EFBFBD>
|
||||
980027401 - Goldrich's Maze - Monster's Maze
|
||||
980027501 - Goldrich's Maze - Monster's Maze
|
||||
980027601 - Goldrich's Maze - Monster's Maze
|
||||
@@ -3025,7 +3025,7 @@ etc
|
||||
980027002 - Goldrich's Maze - Maze of Erosion
|
||||
980027102 - Goldrich's Maze - Maze of Erosion
|
||||
980027202 - Goldrich's Maze - Maze of Erosion
|
||||
980027302 - Goldrich's Maze - Beginning of the Maze…
|
||||
980027302 - Goldrich's Maze - Beginning of the Maze<EFBFBD>
|
||||
980027402 - Goldrich's Maze - Monster's Maze
|
||||
980027502 - Goldrich's Maze - Monster's Maze
|
||||
980027602 - Goldrich's Maze - Monster's Maze
|
||||
@@ -3349,7 +3349,7 @@ etc
|
||||
913040007 - Opening - Cygnus Knights
|
||||
913040008 - Opening - Cygnus Knights
|
||||
913040009 - Opening - Cygnus Knights
|
||||
920020000 - Hidden Street - Eliza’s Garden
|
||||
920020000 - Hidden Street - Eliza<EFBFBD>s Garden
|
||||
922020300 - Hidden Street - Origin of the Clock Tower
|
||||
922220000 - Hidden Street - Gloomy Forest
|
||||
922230000 - Hidden Street - Lunar World
|
||||
@@ -4334,6 +4334,7 @@ etc
|
||||
926023400 - Hidden Street - Nett's Pyramid
|
||||
926023500 - Hidden Street - Nett's Pyramid
|
||||
930010000 - Hidden Street - Dangerous Library
|
||||
977777777 - Hidden Street - Developers' Headquarters
|
||||
|
||||
singapore
|
||||
|
||||
|
||||
@@ -192,7 +192,7 @@
|
||||
3010058 - WorldEnd - You will recover 50 HP every 10 seconds. Perhaps, as you recline, you will find the answer to many of life's questions.
|
||||
3010057 - BloodyRose - You will recover 50 HP every 10 seconds. You will experience the might of a conqueror after recovery.
|
||||
3010060 - Noblesse Chair - A chair makes you feel like you're sitting in the lap of luxury. Also recovers 50 HP every 10 seconds.
|
||||
3010061 - Underneath the Maple Tree… - A white chair created to celebrate Maple Story's 6th Anniversary. Sit on it to restore 35 HP and 10 MP every 10 seconds.
|
||||
3010061 - Underneath the Maple Tree<EFBFBD> - A white chair created to celebrate Maple Story's 6th Anniversary. Sit on it to restore 35 HP and 10 MP every 10 seconds.
|
||||
3010062 - Bamboo Chair - A chair that restores HP every 10 seconds when used. It's very strong since it was made from bamboo grown on Rien.
|
||||
3010063 - Moon and Star Cushion - A pretty cushion shaped like a moon. Recovers 60 HP every 10 seconds.
|
||||
3010064 - Male Desert Rabbit Cushion - 60 HP is restored every 10 seconds if you lean back on this cute Male Desert Rabbit Cushion.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
2000000 - Red Potion - A potion made out of red herbs.\nRecovers 50 HP.
|
||||
2000000 - Red Potion - A potion made out of red herbs.\nRecovers 50 HP.
|
||||
2000001 - Orange Potion - A concentrated potion made out of red herbs.\nRecovers 150 HP.
|
||||
2000002 - White Potion - A highly-concentrated potion made out of red herbs.\nRecovers 300 HP.
|
||||
2000003 - Blue Potion - A potion made out of blue herbs.\nRecovers 100 MP.
|
||||
@@ -376,15 +376,15 @@
|
||||
2030004 - Return Scroll to Henesys - Returns you to Henesys.
|
||||
2030005 - Return Scroll to Kerning City - Returns you to the dark Kerning City.
|
||||
2030006 - Return Scroll to Sleepywood - Returns you to Sleepywood, a quiet and dark forest-town.
|
||||
2030007 - Return Scroll for Dead Mine - Returns you to the dead mine at the higher ground of El Nath.nCan only be used in Orbis and El Nath.
|
||||
2030007 - Return Scroll to Dead Mine - Returns you to the dead mine at the higher ground of El Nath.nCan only be used in Orbis and El Nath.
|
||||
2030008 - Coffee Milk - Returns you to the nearest town.
|
||||
2030009 - Strawberry Milk - Returns you to Mushroom Shrine.
|
||||
2030010 - Fruit Milk - Returns you to Showa Town.
|
||||
2030011 - Command Center Warp Capsule - A warp capsule that allows the owner of the capsule to warp to the Command Center of Omega Sector.
|
||||
2030012 - Ludibrium Warp Capsule - A warp capsule that returns you to Ludibrium.
|
||||
2030016 - Phyllia's Warp Powder - Warp powder made by fairy Phyllia. Teleports you to Magatia when used inside the Nihal desert region.
|
||||
2030019 - Nautilus Return Scroll - This scroll enables you to return to the Pirate village, Nautilus. This is a one use item and will disappear after use.
|
||||
2030020 - Return to New Leaf City Scroll - Use this scroll to venture back to New Leaf City whenever you want!
|
||||
2030019 - Return Scroll to Nautilus - This scroll enables you to return to the Pirate village, Nautilus. This is a one use item and will disappear after use.
|
||||
2030020 - Return Scroll to New Leaf City - Use this scroll to venture back to New Leaf City whenever you want!
|
||||
2030100 - Return Scroll - Banished Area - Returns you to the map where you were last banished. Requires immediate use and have changed neither maps nor channels.
|
||||
2031000 - Masked Man's Invitation - An invitation from the Masked Man to the Halloween Party at the Haunted Mansion. Double-click to move straight to the mansion.
|
||||
2031001 - Studio Invitation - An invitation to the studio for the event "For Guild Only".
|
||||
@@ -446,10 +446,10 @@
|
||||
2040303 - Scroll for Earring for INT - Improves INT on ear accessory.\nSuccess rate:30%, magic attack +5, INT+3, magic def. +1
|
||||
2040304 - Dark scroll for Earring for INT - Improves INT on ear accessory.\nSuccess rate:70%, magic attack +2, INT+1nIf failed, the item will be destroyed at a 50% rate.
|
||||
2040305 - Dark scroll for Earring for INT - Improves INT on ear accessory.\nSuccess rate:30%, magic attack +5, INT+3, magic def. +1nIf failed, the item will be destroyed at a 50% rate.
|
||||
2040306 - Dark scroll for Earring for DEX - Improves DEX on ear accesrroy.\nSuccess rate: 70%. DEX + 2nIf failed, the item will be destroyed at a 50% rate.
|
||||
2040306 - Dark scroll for Earring for DEX - Improves DEX on ear accessory.\nSuccess rate: 70%. DEX + 2nIf failed, the item will be destroyed at a 50% rate.
|
||||
2040307 - Dark scroll for Earring for DEX - Improves DEX on ear accessorynSuccess rate: 30%. DEX + 3nIf failed, the item will be destroyed at a 50% rate.
|
||||
2040308 - Dark Scroll for Earrings for DEF - Improves DEF on earringsnSuccess Rate 70%, weapon defense+1, magic defense+1nIf failed, the item will be destroyed at a 50% rate.
|
||||
2040309 - Dark Scroll for Earrings for DEF - Improves DEF on earringsnSuccess Rate 30%, weapon defense+3, magic defense+3, accuracy+1nIf failed, the item will be destroyed at a 50% rate.
|
||||
2040308 - Dark Scroll for Earring for DEF - Improves DEF on earringsnSuccess Rate 70%, weapon defense+1, magic defense+1nIf failed, the item will be destroyed at a 50% rate.
|
||||
2040309 - Dark Scroll for Earring for DEF - Improves DEF on earringsnSuccess Rate 30%, weapon defense+3, magic defense+3, accuracy+1nIf failed, the item will be destroyed at a 50% rate.
|
||||
2040310 - Scroll for Earring for DEF - Improves DEF on earrings.\nSuccess Rate 10%, weapon defense+3, magic defense+3, Accuracy+1. The success rate of this scroll can be enhanced by Vega's Spell.
|
||||
2040311 - Scroll for Earring for DEF - Improves DEF on earrings.\nSuccess Rate 60%, weapon defense+1, magic defense+1. The success rate of this scroll can be enhanced by Vega's Spell.
|
||||
2040312 - Scroll for Earring for DEF - Improves DEF on earringsnSuccess Rate 100%, weapon defense+1
|
||||
@@ -580,10 +580,10 @@
|
||||
2040717 - Dark scroll for Shoes for Speed - Improves speed on shoes.\nSuccess rate:30%, speed+3nIf failed, the item will be destroyed at a 50% rate.
|
||||
2040718 - Scroll for Shoes for DEX - Improves dexterity on shoes.\nSuccess rate:65%, avoidability+2, accuracy+1
|
||||
2040719 - Scroll for Shoes for DEX - Improves dexterity on shoes.\nSuccess rate:15%, avoidability+5, accuracy+3, speed+1
|
||||
2040720 - Scroll for Jump for DEX - Improves jump on shoes.\nSuccess rate:65%, jump+2, DEX+1
|
||||
2040721 - Scroll for Jump for DEX - Improves jump on shoes.\nSuccess rate:15%, jump+5, DEX+3, speed+1
|
||||
2040722 - Scroll for Speed for DEX - Improves speed on shoes.\nSuccess rate:65%, speed+2
|
||||
2040723 - Scroll for Speed for DEX - Improves speed on shoes.\nSuccess rate:15%, speed+3
|
||||
2040720 - Scroll for Shoes for Jump - Improves jump on shoes.\nSuccess rate:65%, jump+2, DEX+1
|
||||
2040721 - Scroll for Shoes for Jump - Improves jump on shoes.\nSuccess rate:15%, jump+5, DEX+3, speed+1
|
||||
2040722 - Scroll for Shoes for Speed - Improves speed on shoes.\nSuccess rate:65%, speed+2
|
||||
2040723 - Scroll for Shoes for Speed - Improves speed on shoes.\nSuccess rate:15%, speed+3
|
||||
2040727 - Scroll for Spikes on Shoes 10% - Adds traction to the shoes, which prevents the shoes from slipping on slippery surface.\nSuccess rate:10%, Does not affect the number of upgrades available. The success rate of this scroll can be enhanced by Vega's Spell.
|
||||
2040800 - Scroll for Gloves for DEX - Improves dexterity on gloves.\nSuccess rate:100%, accurcacy +1
|
||||
2040801 - Scroll for Gloves for DEX - Improves dexterity on gloves.\nSuccess rate: 60%, accuracy+2, DEX+1. The success rate of this scroll can be enhanced by Vega's Spell.
|
||||
@@ -903,10 +903,10 @@
|
||||
2048003 - Scroll for Pet Equip. for Jump - Improves jump on pet equip.\nSuccess rate:100%, jump+1
|
||||
2048004 - Scroll for Pet Equip. for Jump - Improves jump on pet equip.\nSuccess rate:60%, jump+2. The success rate of this scroll can be enhanced by Vega's Spell.
|
||||
2048005 - Scroll for Pet Equip. for Jump - Improves jump on pet equip.\nSuccess rate:10%, jump+3. The success rate of this scroll can be enhanced by Vega's Spell.
|
||||
2048006 - Scroll for Speed for Pet Equip. - Improves speed on Pet Equip. nSuccess rate:65%, speed+2
|
||||
2048007 - Scroll for Speed for Pet Equip. - Improves speed on Pet Equip. nSuccess rate:15%, speed+3
|
||||
2048008 - Scroll for jump for Pet Equip. - Improves jump on Pet equip. nSuccess rate:65%, jump+2
|
||||
2048009 - Scroll for jump for Pet Equip. - Improves jump on Pet equip. nSuccess rate:15%, jump+3
|
||||
2048006 - Scroll for Pet Equip. for Speed - Improves speed on Pet Equip. nSuccess rate:65%, speed+2
|
||||
2048007 - Scroll for Pet Equip. for Speed - Improves speed on Pet Equip. nSuccess rate:15%, speed+3
|
||||
2048008 - Scroll for Pet Equip. for Jump - Improves jump on Pet equip. nSuccess rate:65%, jump+2
|
||||
2048009 - Scroll for Pet Equip. for Jump - Improves jump on Pet equip. nSuccess rate:15%, jump+3
|
||||
2048010 - Scroll for Pet Equip. for STR 60% - Improves strength on pet equipments.\nSuccess rate:60%, STR+1. The success rate of this scroll can be enhanced by Vega's Spell.
|
||||
2048011 - Scroll for Pet Equip. for INT 60% - Improves intelligence on pet equipments.\nSuccess rate:60%, INT+1. The success rate of this scroll can be enhanced by Vega's Spell.
|
||||
2048012 - Scroll for Pet Equip. for DEX 60% - Improves dexterity on pet equipments.\nSuccess rate:60%, DEX+1. The success rate of this scroll can be enhanced by Vega's Spell.
|
||||
@@ -952,8 +952,8 @@
|
||||
2070009 - Wooden Top - When thrown, it spins fast and flies at great speed. Once they are all used up, they need to be recharged.\nLevel Limit : 10, Attack + 19
|
||||
2070010 - Icicle - Sharp icicles. Once they run out, they need to be recharged.rnLevel Limit : 10, Attack + 21
|
||||
2070011 - Maple Throwing-Stars - Maple-shaped steel throwing-stars. Once they run out, they need to be recharged.rnLevel Limit : 10, Attack + 21
|
||||
2070012 - Paper Fighter Plane - A paper plane that can be thrown at things. Once they run out, they need to be recharged. Attack +20
|
||||
2070013 - Orange - A tasty orange that can be thrown at things. Attack + 20
|
||||
2070012 - Paper Fighter Plane - A paper plane that can be thrown at things. Once they run out, they need to be recharged.\nAttack +20
|
||||
2070013 - Orange - A tasty orange that can be thrown at things.\nAttack + 20
|
||||
2070014 - Devil Rain Throwing Star - Throwing Star
|
||||
2070015 - A Beginner Thief's Throwing Stars - These are steel throwing stars given by Dark Lord for Beginner Thieves. Unlike normal throwing stars, you can't recharge it. \nAttack + 15
|
||||
2070016 - Crystal Ilbi Throwing-Stars - A throwing-star made of crystal. Once they run out, they need to be recharged. rnAttack + 29
|
||||
@@ -1181,8 +1181,8 @@
|
||||
2280000 - Lava Bottle - A glass bottle that contains an actual lava, which is waiting to be spilled out. Drink this lava, and the lava will consume the body with fire, which will enable the drinker to master Fire Demon.
|
||||
2280001 - Black Cloud Machine - A mechanical device that produces black clouds. Enables the character to acquire the Smokescreen skill using the clouds.
|
||||
2280002 - Firm Hand - A stimulant packaged inside a bottle that resembles a clenched fist. Drinking the stimulant will allow the character to acquire The Will of a Warrior.
|
||||
2280003 - [Skill Book] Maple Hero - You can learn #cMaple Hero# with this book.rnJob : All 4th jobsrnCondition : #cMaple Hero# not acquired.
|
||||
2280004 - [Skill Book] Infinity - You can learn #Infinity# with this book.rnJob : 4th Advancement MagicianrnCondition : #cInfinity# not acquired
|
||||
2280003 - [Skill Book] Maple Warrior - You can learn #cMaple Warrior# with this book.rnJob : All 4th jobsrnCondition : #cMaple Warrior# not acquired.
|
||||
2280004 - [Skill Book] Infinity - You can learn #cInfinity# with this book.rnJob : 4th Advancement MagicianrnCondition : #cInfinity# not acquired
|
||||
2280005 - [Skill Book] Dragon's Breath - You can learn #cDragon's Breath# with this book.wnJob : 4th Advancement BowmanrnCondition : #cDragon's Breath# not acquired
|
||||
2280006 - [Skill Book] Taunt - You can learn #cTaunt# with this book.rnJob : 4th Advancement ThiefrnCondition : #cTaunt# not acquired
|
||||
2280007 - [Skill Book] Advanced Combo Attack - You can learn #cAdvanced Combo Attack# with this book.rnClass : HerornCondition : #cAdvanced Combo# not acquired
|
||||
@@ -1191,6 +1191,13 @@
|
||||
2280010 - [Skill Book] Triple Throw - You can learn #cTriple Throw# with this book.rnClass : Night LordrnCondition : #cTriple Throw# not acquired
|
||||
2280011 - Ancient Ice Powder - This is a pack full of ancient ice powder. If you eat this, you will feel chilled and can learn Ice Demon.
|
||||
2280012 - [Skill Book] Rush - You can learn #cRush# with this book.rnJob : 4th Advancement WarriorrnCondition : #cRush# not acquired
|
||||
2280013 - [Skill Book] Final Blow - Skill Book from which you can learn about the #cFinal Blow# skill.\nJob: 4th Advancement Aran\nCondition: #cFinal Blow# not available
|
||||
2280014 - [Skill Book] High Defense - Skill Book from which you can learn about the #cHigh Defense# skill.\nJob: 4th Advancement Aran\nCondition: #cHigh Defense# not available
|
||||
2280015 - [Skill Book] Combo Tempest - Skill Book from which you can learn about the #cCombo Tempest# skill.\nJob: 4th Advancement Aran\nCondition: #cCombo Tempest# not available
|
||||
2280016 - [Skill Book] Combo Barrier - Skill Book from which you can learn about the #cCombo Barrier# skill.\nJob: 4th Advancement Aran\nCondition: #cCombo Barrier# not available
|
||||
2280017 - [Skill Book] Pig's Weakness - Skill Book from which you can learn about the #cPig's Weakness# skill.\nCondition: #cPig's Weakness# not available
|
||||
2280018 - [Skill Book] Stump's Weakness - Skill Book from which you can learn about the #cStump's Weakness# skill.\nCondition: #cStump's Weakness# not available
|
||||
2280019 - [Skill Book] Slime's Weakness - Skill Book from which you can learn about the #cSlime's Weakness# skill.\nCondition: #cSlime's Weakness# not available
|
||||
2290000 - [Mastery Book] Monster Magnet - This increases master level of the #cMonster Magnet# skill up to 20 with 70% chance of success.rnJob : 4th Advancement WarriorrnCondition : Skill level above 5
|
||||
2290001 - [Mastery Book] Monster Magnet - This increases master level of the #cMonster Magnet# skill up to 30 with 50% chance of success. rnJob : 4th Advancement WarriorrnCondition : Skill Level above 15
|
||||
2290002 - [Mastery Book] Achilles - This increases the master level of #cAchilles# up to 20 with 70% of chance.rnJob : 4th Advancement WarriorrnCondition : Skill level above 5
|
||||
@@ -1287,7 +1294,7 @@
|
||||
2290093 - [Mastery Book] Assassinate - This increases the master level of #cAssassinate# up to 30 with 50% of chance.rnClass : ShadowerrnCondition : Skill level above 15
|
||||
2290094 - [Mastery Book] Smokescreen - This increases the master level of #cSmokescreen# up to 20 with 70% of chance.rnClass : ShadowerrnCondition : Skill level above 5
|
||||
2290095 - [Mastery Book] Smokescreen - This increases the master level of #cSmokescreen# up to 30 with 50% of chance.rnClass : ShadowerrnCondition : Skill level above 15
|
||||
2290096 - [Mastery Book] Maple Hero 20 - This increases the master level of #cMaple Hero# up to 20 with 70% of chance.rnJob : All 4th Advancement JobsrnCondition : Skill level above 5
|
||||
2290096 - [Mastery Book] Maple Warrior - This increases the master level of #cMaple Warrior# up to 20 with 70% of chance.rnJob : All 4th Advancement JobsrnCondition : Skill level above 5
|
||||
2290097 - [Mastery Book] Dragon Strike - With a 70% success rate, it raises the Master Level of #cDragon Strike# to 20.nJob : BuccaneernRequirement : At least Level 5 in this skill
|
||||
2290098 - [Mastery Book] Dragon Strike - With a 50% success rate, it raises the Master Level of #cDragon Strike# to 30.nJob : BuccaneernRequirement : At least Level 15 in this skill
|
||||
2290099 - [Mastery Book] Energy Orb - With a 70% success rate, it raises the Master Level of #cEnergy Orb# to 20.nJob : BuccaneernRequirement : At least Level 5 in this skill
|
||||
@@ -1316,7 +1323,21 @@
|
||||
2290122 - [Mastery Book] Battleship Torpedo - With a 50% success rate, it raises the Master Level of #cBattleship Torpedo# to 30.nJob : CorsairnRequirement : At least Level 15 in this skill
|
||||
2290123 - [Mastery Book] Hypnotize - With a 70% success rate, it raises the Master Level of #cHypnotize# to 20.nJob : CorsairnRequirement : At least Level 5 in this skill
|
||||
2290124 - [Mastery Book] Bullseye - With a 70% success rate, it raises the Master Level of #cBullseye# to 20.nJob : CorsairnRequirement : At least Level 5 in this skill
|
||||
2290125 - [Mastery Book] Maple Hero 30 - This increases the master level of #cMaple Hero# up to 30 with 50% of chance.rnJob : All 4th Advancement JobsrnCondition : Skill level above 15
|
||||
2290125 - [Mastery Book] Maple Warrior - This increases the master level of #cMaple Warrior# up to 30 with 50% of chance.rnJob : All 4th Advancement JobsrnCondition : Skill level above 15
|
||||
2290126 - [Mastery Book] Overswing - With a 70% success rate, raises the Mastery Level of #cOverswing# to 20.\nJob: Aran\nCondition: Min Skill Lv. 5
|
||||
2290127 - [Mastery Book] Overswing - With a 50% success rate, raises the Mastery Level of #cOverswing# to 30.\nJob: Aran\nCondition: Min Skill Lv. 15
|
||||
2290128 - [Mastery Book] High Mastery - With a 70% success rate, raises the Mastery Level of #cHigh Mastery# to 20.\nJob: Aran\nCondition: Min Skill Lv. 5
|
||||
2290129 - [Mastery Book] High Mastery - With a 50% success rate, raises the Mastery Level of #cHigh Mastery# to 30.\nJob: Aran\nCondition: Min Skill Lv. 15
|
||||
2290130 - [Mastery Book] Freeze Standing - With a 70% success rate, raises the Mastery Level of #cFreeze Standing# to 20.\nJob: Aran\nCondition: Min Skill Lv. 5
|
||||
2290131 - [Mastery Book] Freeze Standing - With a 50% success rate, raises the Mastery Level of #cFreeze Standing# to 30.\nJob: Aran\nCondition: Min Skill Lv. 15
|
||||
2290132 - [Mastery Book] Final Blow - With a 70% success rate, raises the Mastery Level of #cFinal Blow# to 20.\nJob: Aran\nCondition: Min Skill Lv. 5
|
||||
2290133 - [Mastery Book] Final Blow - With a 50% success rate, raises the Mastery Level of #cFinal Blow# to 30.\nJob: Aran\nCondition: Min Skill Lv. 15
|
||||
2290134 - [Mastery Book] High Defense - With a 70% success rate, raises the Mastery Level of #cHigh Defense# to 20.\nJob: Aran\nCondition: Min Skill Lv. 5
|
||||
2290135 - [Mastery Book] High Defense - With a 50% success rate, raises the Mastery Level of #cHigh Defense# to 30.\nJob: Aran\nCondition: Min Skill Lv. 15
|
||||
2290136 - [Mastery Book] Combo Tempest - With a 70% success rate, raises the Mastery Level of #cCombo Tempest# to 20.\nJob: Aran\nCondition: Min Skill Lv. 5
|
||||
2290137 - [Mastery Book] Combo Tempest - With a 50% success rate, raises the Mastery Level of #cCombo Tempest# to 30.\nJob: Aran\nCondition: Min Skill Lv. 15
|
||||
2290138 - [Mastery Book] Combo Barrier - With a 70% success rate, raises the Mastery Level of #cCombo Barrier# to 20.\nJob: Aran\nCondition: Min Skill Lv. 5
|
||||
2290139 - [Mastery Book] Combo Barrier - With a 50% success rate, raises the Mastery Level of #cCombo Barrier# to 30.\nJob: Aran\nCondition: Min Skill Lv. 15
|
||||
2310000 - The Owl of Minerva - #cThe Owl of Minerva#, which represents wisdom, can be used to search for items sold at the Free Market. #cDisappears right after showing the results of the item search#.
|
||||
2320000 - Teleport Rock - Remembers 5 maps of your choice. This rock will enable you to #cteleport to the map you remembered#. It can even allow you to #cmove to the map where a certain character is#, provided that the person is in the same channel at the same world.
|
||||
2330000 - Bullet - A bullet made out of steel. A set contains numerous bullets and once they are used up, they'll need to be recharged.\nAttack + 10
|
||||
@@ -1789,8 +1810,8 @@
|
||||
2044812 - Scroll for Knuckles for ATT 15% - Improves ATT on Knuckles.\nSuccess Rate:15%, Weapon Att+5, STR+3, Weapon DEF+1
|
||||
2044813 - Scroll for Knuckles for Accuracy 65% - Improves Accuracy on Knuckles.\nSuccess Rate:65%, Accuracy+3, DEX+2, Weapon Att+1
|
||||
2044814 - Scroll for Knuckles for Accuracy 15% - Improves Accuracy on Knuckles.\nSuccess Rate:15%, Accuracy+5, DEX+3, Weapon Att+3
|
||||
2044906 - Gun ATT Scroll 65% - Improves ATT on guns.\nSuccess Rate:65%, Weapon Att.+2, Accuracy+1
|
||||
2044907 - Gun ATT Scroll 15% - Improves ATT on guns.\nSuccess Rate:15%, Weapon Att.+5, Accuracy+3, DEX+1
|
||||
2044906 - Scroll for Gun for ATT 65% - Improves ATT on guns.\nSuccess Rate:65%, Weapon Att.+2, Accuracy+1
|
||||
2044907 - Scroll for Gun for ATT 15% - Improves ATT on guns.\nSuccess Rate:15%, Weapon Att.+5, Accuracy+3, DEX+1
|
||||
2049103 - Beach Sandals Scroll 100% - Used on limited-edition beach sandals, with the options of improving/decreasing the stats.\nSuccess rate:100%
|
||||
2100073 - Mu Lung Dojo Summon Package3_Deo - Summon Deo
|
||||
2100074 - Mu Lung Dojo Summon Package4_King Slime - Summon King Slime
|
||||
@@ -1996,7 +2017,7 @@
|
||||
2044015 - Scroll for Two-Handed Swords for ATT 10% - Improves ATT on Two-Handed Swords. nSuccess rate: 10%, Weapons ATT +5, STR +3, Weapons Defense +1
|
||||
2049105 - [6th Anniversary] Dark Scroll for Gloves for ATT 70% - Improves ATT on Gloves. nSuccess rate: 70%, Weapons ATT +1nIf unsuccessful, item has a 50% chance of being destroyed.
|
||||
2049106 - [6th Anniversary] Dark Scroll for Gloves for ATT 30% - Improves ATT on Gloves. nSucces rate: 30%, Weapons ATT +2nIf unsuccessful, item has an 80% chance of being destroyed.
|
||||
2049107 - [6th Anniversary] Dark Scroll for Gloves for STR 70% [ - Improves STR on Gloves. nSuccess rate: 70%, Accuracy +2, STR +1nIf unsuccessful, item has a 50% chance of being destroyed.
|
||||
2049107 - [6th Anniversary] Dark Scroll for Gloves for STR 70% - Improves STR on Gloves. nSuccess rate: 70%, Accuracy +2, STR +1nIf unsuccessful, item has a 50% chance of being destroyed.
|
||||
2049108 - [6th Anniversary] Dark Scroll for Gloves for LUK 70% - Improves LUK on Gloves. nSuccess rate: 70%, Accuracy +2, LUK +1nIf unsuccessful, item has a 50% chance of being destroyed.
|
||||
2049109 - [6th Anniversary] Dark Scroll for Gloves for INT 70% - Improves INT on Gloves. nSuccess rate: 70%, Accuracy +2, INT +1nIf unsuccessful, item has a 50% chance of being destroyed.
|
||||
2049110 - [6th Anniversary] Dark Scroll for Gloves for DEX 70% - Improves DEX on Gloves. nSuccess rate: 70%, Accuracy +2, DEX +1nIf unsuccessful, item has a 50% chance of being destroyed.
|
||||
@@ -2162,27 +2183,6 @@
|
||||
2109008 - Bubbling Summoning Bag - For use in the restricted bonus map area of the subway station.
|
||||
2109009 - Jr. Yeti Pharaoh Summoning Bag - Summons Jr. Yeti Pharaoh for the bonus stage of Nett's Pyramid (Easy, Normal, Hard)
|
||||
2109010 - Jr. Yeti Pharaoh Summoning Bag - Summons Jr. Yeti Pharaoh for the bonus stage of Nett's Pyramid (Hell Mode)
|
||||
2280013 - [Skill Book] Final Blow - Skill Book from which you can learn about the #cFinal Blow# skill.\nJob: 4th Lv Aran\nCondition: #cFinal Blow# not available
|
||||
2280014 - [Skill Book] High Defense - Skill Book from which you can learn about the #cHigh Defense# skill.\nJob: 4th Lv Aran\nCondition: #cHigh Defense# not available
|
||||
2280015 - [Skill Book] Combo Tempest - Skill Book from which you can learn about the #cCombo Tempest# skill.\nJob: 4th Lv Aran\nCondition: #cCombo Tempest# not available
|
||||
2280017 - [Skill Book] Pig's Weakness - Skill Book from which you can learn about the #cPig's Weakness# skill.\nCondition: #cPig's Weakness# not available
|
||||
2280016 - [Skill Book] Combo Barrier - Skill Book from which you can learn about the #cCombo Barrier# skill.\nJob: 4th Lv Aran\nCondition: #cCombo Barrier# not available
|
||||
2280018 - [Skill Book] Stump's Weakness - Skill Book from which you can learn about the #cStump's Weakness# skill.\nCondition: #cStump's Weakness# not available
|
||||
2280019 - [Skill Book] Slime's Weakness - Skill Book from which you can learn about the #cSlime's Weakness# skill.\nCondition: #cSlime's Weakness# not available
|
||||
2290126 - [Mastery Book] Overswing 20 - With a 70% success rate, raises the Mastery Level of #cOverswing# to 20.\nJob: Aran\nCondition: Min Skill Lv. 5
|
||||
2290127 - [Mastery Book] Overswing 30 - With a 50% success rate, raises the Mastery Level of #cOverswing# to 30.\nJob: Aran\nCondition: Min Skill Lv. 15
|
||||
2290128 - [Mastery Book] High Mastery 20 - With a 70% success rate, raises the Mastery Level of #cHigh Mastery# to 20.\nJob: Aran\nCondition: Min Skill Lv. 5
|
||||
2290129 - [Mastery Book]High Mastery 30 - With a 50% success rate, raises the Mastery Level of #cHigh Mastery# to 30.\nJob: Aran\nCondition: Min Skill Lv. 15
|
||||
2290130 - [Mastery Book] Freeze Standing 20 - With a 70% success rate, raises the Mastery Level of #cFreeze Standing# to 20.\nJob: Aran\nCondition: Min Skill Lv. 5
|
||||
2290131 - [Mastery Book] Freeze Standing 30 - With a 50% success rate, raises the Mastery Level of #cFreeze Standing# to 30.\nJob: Aran\nCondition: Min Skill Lv. 15
|
||||
2290132 - [Mastery Book] Final Blow 20 - With a 70% success rate, raises the Mastery Level of #cFinal Blow# to 20.\nJob: Aran\nCondition: Min Skill Lv. 5
|
||||
2290133 - [Mastery Book] Final Blow 30 - With a 50% success rate, raises the Mastery Level of #cFinal Blow# to 30.\nJob: Aran\nCondition: Min Skill Lv. 15
|
||||
2290134 - [Mastery Book] High Defense 20 - With a 70% success rate, raises the Mastery Level of #cHigh Defense# to 20.\nJob: Aran\nCondition: Min Skill Lv. 5
|
||||
2290135 - [Mastery Book] High Defense 30 - With a 50% success rate, raises the Mastery Level of #cHigh Defense# to 30.\nJob: Aran\nCondition: Min Skill Lv. 15
|
||||
2290136 - [Mastery Book] Combo Tempest 20 - With a 70% success rate, raises the Mastery Level of #cCombo Tempest# to 20.\nJob: Aran\nCondition: Min Skill Lv. 5
|
||||
2290137 - [Mastery Book] Combo Tempest 30 - With a 50% success rate, raises the Mastery Level of #cCombo Tempest# to 30.\nJob: Aran\nCondition: Min Skill Lv. 15
|
||||
2290138 - [Mastery Book] Combo Barrier 20 - With a 70% success rate, raises the Mastery Level of #cCombo Barrier# to 20.\nJob: Aran\nCondition: Min Skill Lv. 5
|
||||
2290139 - [Mastery Book] Combo Barrier 30 - With a 50% success rate, raises the Mastery Level of #cCombo Barrier# to 30.\nJob: Aran\nCondition: Min Skill Lv. 15
|
||||
2380014 - Dejected Green Mushroom Card - A card featuring the Dejected Green Mushroom.
|
||||
2380015 - Muru Card - A card featuring Muru.
|
||||
2380016 - Murupa Card - A card featuring Murupa.
|
||||
@@ -2209,7 +2209,7 @@
|
||||
2430016 - Crystal Chest - A chest full of items that's sure to excite anyone who sees it. Open it by August 31st, 2009, or it'll disappear.
|
||||
2450000 - Hunter's Luck - For 30 minutes, doubles your EXP from hunting.
|
||||
2040758 - Scroll for Shoes for ATT - Improves attack on shoes.\nSuccess rate: 100%. Weapon Attack +1
|
||||
2040759 - Scroll for Shoes for ATT - Improves attack on gloves.\nSuccess rate: 60%. Weapon Attack +2. The success rate of this scroll can be enhanced by Vega's Spell.
|
||||
2040759 - Scroll for Shoes for ATT - Improves attack on shoes.\nSuccess rate: 60%. Weapon Attack +2. The success rate of this scroll can be enhanced by Vega's Spell.
|
||||
2040760 - Scroll for Shoes for ATT - Improves attack on shoes.\nSuccess rate: 10%, Weapon Attack +3. The success rate of this scroll can be enhanced by Vega's Spell.
|
||||
2044815 - Scroll for Knuckler for Attack 100% - Improves attack on Knucklers.\nSuccess rate: 100%. Weapon Attack +2, STR +1
|
||||
2044817 - Scroll for Knuckler for Attack 50% - Improves attack on Knucklers.\nSuccess rate: 50%. Weapon Attack +5, STR +3, DEX +1
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@echo off
|
||||
@title HeavenMS
|
||||
set CLASSPATH=.;dist\*
|
||||
java -Xmx2048m -Dwzpath=wz\ net.server.Server
|
||||
@title Cosmic
|
||||
java -Xmx2048m -Dwz-path=wz -jar target\Cosmic.jar
|
||||
pause
|
||||
@@ -1,3 +0,0 @@
|
||||
Manifest-Version: 1.0
|
||||
X-COMMENT: Main-Class will be added automatically by build
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +0,0 @@
|
||||
build.xml.data.CRC32=92113194
|
||||
build.xml.script.CRC32=ff13faf5
|
||||
build.xml.stylesheet.CRC32=8064a381@1.75.2.48
|
||||
# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
|
||||
# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
|
||||
nbproject/build-impl.xml.data.CRC32=92113194
|
||||
nbproject/build-impl.xml.script.CRC32=cef58264
|
||||
nbproject/build-impl.xml.stylesheet.CRC32=876e7a8f@1.75.2.48
|
||||
@@ -1,22 +0,0 @@
|
||||
<#if licenseFirst??>
|
||||
${licenseFirst}
|
||||
</#if>
|
||||
${licensePrefix}This file is part of the HeavenMS (MapleSolaxiaV2) Maple Story Server
|
||||
${licensePrefix?replace(" +$", "", "r")}
|
||||
${licensePrefix}Copyright (C) ${date?date?string("yyyy")} ${project.organization!user}
|
||||
${licensePrefix?replace(" +$", "", "r")}
|
||||
${licensePrefix}This program is free software: you can redistribute it and/or modify
|
||||
${licensePrefix}it under the terms of the GNU General Public License as published by
|
||||
${licensePrefix}the Free Software Foundation, either version 3 of the License, or
|
||||
${licensePrefix}(at your option) any later version.
|
||||
${licensePrefix?replace(" +$", "", "r")}
|
||||
${licensePrefix}This program is distributed in the hope that it will be useful,
|
||||
${licensePrefix}but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
${licensePrefix}MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
${licensePrefix}GNU General Public License for more details.
|
||||
${licensePrefix?replace(" +$", "", "r")}
|
||||
${licensePrefix}You should have received a copy of the GNU General Public License
|
||||
${licensePrefix}along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
<#if licenseLast??>
|
||||
${licenseLast}
|
||||
</#if>
|
||||
@@ -1,10 +0,0 @@
|
||||
compile.on.save=true
|
||||
do.depend=false
|
||||
do.jar=true
|
||||
file.reference.mina-core-2.0.7.jar=C:\\Nexon\\MapleSolaxia\\MapleSolaxiaV2\\cores\\mina-core-2.0.7.jar
|
||||
file.reference.mysql-connector-java-bin.jar=C:\\Nexon\\MapleSolaxia\\MapleSolaxiaV2\\cores\\mysql-connector-java-bin.jar
|
||||
file.reference.slf4j-api-1.6.6.jar=C:\\Nexon\\MapleSolaxia\\MapleSolaxiaV2\\cores\\slf4j-api-1.6.6.jar
|
||||
file.reference.slf4j-jdk14-1.7.5.jar=C:\\Nexon\\MapleSolaxia\\MapleSolaxiaV2\\cores\\slf4j-jdk14-1.7.5.jar
|
||||
javac.debug=true
|
||||
javadoc.preview=true
|
||||
user.properties.file=C:\\Users\\RonanLana\\AppData\\Roaming\\NetBeans\\8.0.2\\build.properties
|
||||
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project-private xmlns="http://www.netbeans.org/ns/project-private/1">
|
||||
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="2"/>
|
||||
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
|
||||
<group/>
|
||||
</open-files>
|
||||
</project-private>
|
||||
@@ -1,101 +0,0 @@
|
||||
annotation.processing.enabled=true
|
||||
annotation.processing.enabled.in.editor=false
|
||||
annotation.processing.processors.list=
|
||||
annotation.processing.run.all.processors=true
|
||||
annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output
|
||||
application.title=HeavenMS
|
||||
application.vendor=Ronan
|
||||
auxiliary.org-netbeans-spi-editor-hints-projects.perProjectHintSettingsFile=nbproject/cfg_hints.xml
|
||||
build.classes.dir=${build.dir}/classes
|
||||
build.classes.excludes=**/*.java,**/*.form
|
||||
# This directory is removed when the project is cleaned:
|
||||
build.dir=build
|
||||
build.generated.dir=${build.dir}/generated
|
||||
build.generated.sources.dir=${build.dir}/generated-sources
|
||||
# Only compile against the classpath explicitly listed here:
|
||||
build.sysclasspath=ignore
|
||||
build.test.classes.dir=${build.dir}/test/classes
|
||||
build.test.results.dir=${build.dir}/test/results
|
||||
# Uncomment to specify the preferred debugger connection transport:
|
||||
#debug.transport=dt_socket
|
||||
debug.classpath=\
|
||||
${run.classpath}
|
||||
debug.test.classpath=\
|
||||
${run.test.classpath}
|
||||
# This directory is removed when the project is cleaned:
|
||||
dist.dir=dist
|
||||
dist.jar=${dist.dir}/HeavenMS.jar
|
||||
dist.javadoc.dir=${dist.dir}/javadoc
|
||||
endorsed.classpath=
|
||||
excludes=
|
||||
file.reference.HikariCP-java7-2.4.12.jar=cores/HikariCP-java7-2.4.12.jar
|
||||
file.reference.MapleSolaxia-src=src
|
||||
file.reference.mina-core-2.0.7.jar=C:\\Users\\Tyler\\Desktop\\MoopleDev\\dist\\mina-core-2.0.7.jar
|
||||
file.reference.mysql-connector-java-bin.jar=C:\\Users\\Tyler\\Desktop\\MoopleDev\\dist\\mysql-connector-java-bin.jar
|
||||
file.reference.slf4j-api-1.6.6.jar=C:\\Users\\Tyler\\Desktop\\MoopleDev\\dist\\slf4j-api-1.6.6.jar
|
||||
file.reference.slf4j-jdk14-1.7.5.jar=C:\\Users\\Tyler\\Desktop\\MoopleDev\\dist\\slf4j-jdk14-1.7.5.jar
|
||||
includes=**
|
||||
jar.archive.disabled=${jnlp.enabled}
|
||||
jar.compress=true
|
||||
jar.index=${jnlp.enabled}
|
||||
javac.classpath=\
|
||||
${file.reference.mina-core-2.0.7.jar}:\
|
||||
${file.reference.mysql-connector-java-bin.jar}:\
|
||||
${file.reference.slf4j-api-1.6.6.jar}:\
|
||||
${file.reference.slf4j-jdk14-1.7.5.jar}:\
|
||||
${file.reference.HikariCP-java7-2.4.12.jar}
|
||||
# Space-separated list of extra javac options
|
||||
javac.compilerargs=
|
||||
javac.deprecation=false
|
||||
javac.processorpath=\
|
||||
${javac.classpath}
|
||||
javac.source=1.7
|
||||
javac.target=1.7
|
||||
javac.test.classpath=\
|
||||
${javac.classpath}:\
|
||||
${build.classes.dir}
|
||||
javac.test.processorpath=\
|
||||
${javac.test.classpath}
|
||||
javadoc.additionalparam=
|
||||
javadoc.author=false
|
||||
javadoc.encoding=${source.encoding}
|
||||
javadoc.noindex=false
|
||||
javadoc.nonavbar=false
|
||||
javadoc.notree=false
|
||||
javadoc.private=false
|
||||
javadoc.splitindex=true
|
||||
javadoc.use=true
|
||||
javadoc.version=false
|
||||
javadoc.windowtitle=
|
||||
jnlp.codebase.type=no.codebase
|
||||
jnlp.descriptor=application
|
||||
jnlp.enabled=false
|
||||
jnlp.mixed.code=default
|
||||
jnlp.offline-allowed=false
|
||||
jnlp.signed=false
|
||||
jnlp.signing=
|
||||
jnlp.signing.alias=
|
||||
jnlp.signing.keystore=
|
||||
main.class=net.server.Server
|
||||
# Optional override of default Codebase manifest attribute, use to prevent RIAs from being repurposed
|
||||
manifest.custom.codebase=
|
||||
# Optional override of default Permissions manifest attribute (supported values: sandbox, all-permissions)
|
||||
manifest.custom.permissions=
|
||||
manifest.file=manifest.mf
|
||||
meta.inf.dir=${src.dir}/META-INF
|
||||
mkdist.disabled=false
|
||||
platform.active=JDK_1.7
|
||||
project.license=gpl30_msv2
|
||||
project.licensePath=./nbproject/licenseheader.txt
|
||||
run.classpath=\
|
||||
${javac.classpath}:\
|
||||
${build.classes.dir}
|
||||
# Space-separated list of JVM arguments used when running the project.
|
||||
# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value.
|
||||
# To set system properties for unit tests define test-sys-prop.name=value:
|
||||
run.jvmargs=
|
||||
run.test.classpath=\
|
||||
${javac.test.classpath}:\
|
||||
${build.test.classes.dir}
|
||||
source.encoding=UTF-8
|
||||
src.dir=${file.reference.MapleSolaxia-src}
|
||||
@@ -1,14 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://www.netbeans.org/ns/project/1">
|
||||
<type>org.netbeans.modules.java.j2seproject</type>
|
||||
<configuration>
|
||||
<data xmlns="http://www.netbeans.org/ns/j2se-project/3">
|
||||
<name>HeavenMS</name>
|
||||
<explicit-platform explicit-source-supported="true"/>
|
||||
<source-roots>
|
||||
<root id="src.dir"/>
|
||||
</source-roots>
|
||||
<test-roots/>
|
||||
</data>
|
||||
</configuration>
|
||||
</project>
|
||||
207
pom.xml
Normal file
207
pom.xml
Normal file
@@ -0,0 +1,207 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>cosmic-maplestory</groupId>
|
||||
<artifactId>Cosmic</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<!-- Project -->
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<java.version>17</java.version>
|
||||
<maven.compiler.source>${java.version}</maven.compiler.source>
|
||||
<maven.compiler.target>${java.version}</maven.compiler.target>
|
||||
<mainClass>net.server.Server</mainClass>
|
||||
|
||||
<!-- Maven plugins -->
|
||||
<maven-surefire-plugin.version>3.0.0-M9</maven-surefire-plugin.version> <!-- For running unit tests -->
|
||||
<maven-jar-plugin.version>3.3.0</maven-jar-plugin.version> <!-- Disabled. (for building thin jar) -->
|
||||
<maven-assembly-plugin.version>3.5.0</maven-assembly-plugin.version> <!-- For packaging the executable fat jar -->
|
||||
|
||||
<!-- Dependencies -->
|
||||
<slf4j-api.version>1.7.36</slf4j-api.version> <!-- Logging facade -->
|
||||
<log4j.version>2.20.0</log4j.version> <!-- Slf4j implementation -->
|
||||
<graalvm.version>22.3.1</graalvm.version> <!-- ScriptEngine implementation -->
|
||||
<netty.version>4.1.89.Final</netty.version> <!-- Networking -->
|
||||
<yamlbeans.version>1.15</yamlbeans.version> <!-- Config file -->
|
||||
<jcip-annotations.version>1.0</jcip-annotations.version> <!-- Annotations for concurrency documentation -->
|
||||
<HikariCP.version>5.0.1</HikariCP.version> <!-- Database connection pool -->
|
||||
<mysql-connector-j.version>8.0.32</mysql-connector-j.version> <!-- MySQL JDBC driver -->
|
||||
<jdbi-version>3.37.1</jdbi-version> <!-- Convenience wrapper around JDBC -->
|
||||
<junit.version>5.9.2</junit.version> <!-- Unit test -->
|
||||
<mockito.version>5.1.1</mockito.version> <!-- Unit test -->
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.esotericsoftware.yamlbeans</groupId>
|
||||
<artifactId>yamlbeans</artifactId>
|
||||
<version>${yamlbeans.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.jcip</groupId>
|
||||
<artifactId>jcip-annotations</artifactId>
|
||||
<version>${jcip-annotations.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Database -->
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP</artifactId>
|
||||
<version>${HikariCP.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.mysql</groupId>
|
||||
<artifactId>mysql-connector-j</artifactId>
|
||||
<version>${mysql-connector-j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jdbi</groupId>
|
||||
<artifactId>jdbi3-core</artifactId>
|
||||
<version>${jdbi-version}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- Networking -->
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-transport</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-codec</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-buffer</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-handler</artifactId>
|
||||
<version>${netty.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Logging -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>${slf4j-api.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-core</artifactId>
|
||||
<version>${log4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-api</artifactId>
|
||||
<version>${log4j.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-slf4j-impl</artifactId>
|
||||
<version>${log4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Scripting -->
|
||||
<dependency>
|
||||
<groupId>org.graalvm.js</groupId>
|
||||
<artifactId>js</artifactId>
|
||||
<version>${graalvm.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.graalvm.js</groupId>
|
||||
<artifactId>js-scriptengine</artifactId>
|
||||
<version>${graalvm.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Testing -->
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-params</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>${mockito.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- Explicitly disable default jar which includes no dependencies -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<version>${maven-jar-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default-jar</id>
|
||||
<phase>none</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>${maven-surefire-plugin.version}</version>
|
||||
</plugin>
|
||||
|
||||
<!-- Enable assembling jar that includes all dependencies -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>${maven-assembly-plugin.version}</version>
|
||||
<configuration>
|
||||
<descriptorRefs>
|
||||
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||
</descriptorRefs>
|
||||
<archive>
|
||||
<manifest>
|
||||
<mainClass>${mainClass}</mainClass>
|
||||
</manifest>
|
||||
<manifestEntries>
|
||||
<Multi-Release>true</Multi-Release>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
<finalName>${project.artifactId}</finalName>
|
||||
<appendAssemblyId>false</appendAssemblyId>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-assembly</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of the HeavenMS (MapleSolaxiaV2) MapleStory Server
|
||||
Copyleft (L) 2017 RonanLana
|
||||
This file is part of the HeavenMS MapleStory Server
|
||||
Copyleft (L) 2016 - 2019 RonanLana
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
@@ -23,36 +23,37 @@
|
||||
*/
|
||||
|
||||
var status;
|
||||
|
||||
|
||||
function start() {
|
||||
status = -1;
|
||||
action(1, 0, 0);
|
||||
status = -1;
|
||||
action(1, 0, 0);
|
||||
}
|
||||
|
||||
function action(mode, type, selection) {
|
||||
if (mode == -1) {
|
||||
cm.dispose();
|
||||
} else {
|
||||
if (mode == 0 && type > 0) {
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
if (mode == 1)
|
||||
status++;
|
||||
else
|
||||
status--;
|
||||
|
||||
if(status == 0) {
|
||||
cm.sendOk("Sample text.");
|
||||
cm.dispose();
|
||||
}
|
||||
if (mode == -1) {
|
||||
cm.dispose();
|
||||
} else {
|
||||
if (mode == 0 && type > 0) {
|
||||
cm.dispose();
|
||||
return;
|
||||
}
|
||||
if (mode == 1) {
|
||||
status++;
|
||||
} else {
|
||||
status--;
|
||||
}
|
||||
|
||||
if (status == 0) {
|
||||
cm.sendOk("Sample text.");
|
||||
cm.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function generateSelectionMenu(array) { // nice tool for generating a string for the sendSimple functionality
|
||||
var menu = "";
|
||||
for (var i = 0; i < array.length; i++) {
|
||||
menu += "#L" + i + "#" + array[i] + "#l\r\n";
|
||||
}
|
||||
return menu;
|
||||
var menu = "";
|
||||
for (var i = 0; i < array.length; i++) {
|
||||
menu += "#L" + i + "#" + array[i] + "#l\r\n";
|
||||
}
|
||||
return menu;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of the HeavenMS (MapleSolaxiaV2) MapleStory Server
|
||||
Copyleft (L) 2017 RonanLana
|
||||
This file is part of the HeavenMS MapleStory Server
|
||||
Copyleft (L) 2016 - 2019 RonanLana
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
@@ -28,20 +28,21 @@ function start(mode, type, selection) {
|
||||
if (mode == -1) {
|
||||
qm.dispose();
|
||||
} else {
|
||||
if(mode == 0 && type > 0) {
|
||||
if (mode == 0 && type > 0) {
|
||||
qm.dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == 1)
|
||||
|
||||
if (mode == 1) {
|
||||
status++;
|
||||
else
|
||||
} else {
|
||||
status--;
|
||||
|
||||
}
|
||||
|
||||
if (status == 0) {
|
||||
qm.sendNext("Sample Text.");
|
||||
} else if (status == 1) {
|
||||
qm.forceStartQuest();
|
||||
|
||||
qm.dispose();
|
||||
}
|
||||
}
|
||||
@@ -51,20 +52,21 @@ function end(mode, type, selection) {
|
||||
if (mode == -1) {
|
||||
qm.dispose();
|
||||
} else {
|
||||
if(mode == 0 && type > 0) {
|
||||
if (mode == 0 && type > 0) {
|
||||
qm.dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode == 1)
|
||||
|
||||
if (mode == 1) {
|
||||
status++;
|
||||
else
|
||||
} else {
|
||||
status--;
|
||||
|
||||
}
|
||||
|
||||
if (status == 0) {
|
||||
qm.sendNext("Sample Text.");
|
||||
} else if (status == 1) {
|
||||
qm.forceCompleteQuest();
|
||||
|
||||
qm.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
28
scripts/REACT Base.js
Normal file
28
scripts/REACT Base.js
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
This file is part of the HeavenMS MapleStory Server
|
||||
Copyleft (L) 2016 - 2019 RonanLana
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation version 3 as published by
|
||||
the Free Software Foundation. You may not use, modify or distribute
|
||||
this program under any other version of the GNU Affero General Public
|
||||
License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* @Author Ronan
|
||||
*
|
||||
* REACTORID.js: sample text
|
||||
*/
|
||||
|
||||
function act() {
|
||||
|
||||
}
|
||||
@@ -12,14 +12,14 @@ var maxMapId;
|
||||
|
||||
var eventTime; // Max time allotted for the event, in minutes.
|
||||
|
||||
var lobbyRange = [0, 0]; // Range of concurrent lobbies (min range is 0, max range is 7).
|
||||
const maxLobbies = 7; // Max amount of concurrent active lobbies.
|
||||
|
||||
function init() {
|
||||
// After loading, ChannelServer
|
||||
}
|
||||
|
||||
function setLobbyRange() {
|
||||
return lobbyRange;
|
||||
function getMaxLobbies() {
|
||||
return maxLobbies;
|
||||
}
|
||||
|
||||
function setEventRequirements() {
|
||||
@@ -62,6 +62,10 @@ function playerExit(eim, player) {
|
||||
// Do something with the player right before disbanding the event instance.
|
||||
}
|
||||
|
||||
function playerLeft(eim, player) {
|
||||
// Do something with the player right before leaving the party.
|
||||
}
|
||||
|
||||
function changedMap(eim, player, mapid) {
|
||||
// What to do when player've changed map, based on the mapid.
|
||||
}
|
||||
@@ -77,7 +81,7 @@ function scheduledTimeout(eim) {
|
||||
function timeOut(eim) {
|
||||
if (eim.getPlayerCount() > 0) {
|
||||
var pIter = eim.getPlayers().iterator();
|
||||
while (pIter.hasNext()){
|
||||
while (pIter.hasNext()) {
|
||||
var player = pIter.next();
|
||||
player.dropMessage(6, "You have run out of time to complete this event!");
|
||||
playerExit(eim, player);
|
||||
@@ -86,14 +90,21 @@ function timeOut(eim) {
|
||||
eim.dispose();
|
||||
}
|
||||
|
||||
function monsterKilled(mob, eim) {}
|
||||
function monsterKilled(mob, eim) {
|
||||
// Happens when an opposing mob dies
|
||||
}
|
||||
|
||||
function monsterValue(eim, mobid) {
|
||||
// Invoked when a monster that's registered has been killed
|
||||
// return x amount for this player - "Saved Points"
|
||||
}
|
||||
|
||||
function friendlyKilled(mob, eim) {
|
||||
// Happens when a friendly mob dies
|
||||
}
|
||||
|
||||
function allMonstersDead(eim) {
|
||||
// When invoking unregisterMonster(MapleMonster mob) OR killed
|
||||
// When invoking unregisterMonster(Monster mob) OR killed
|
||||
// Happens only when size = 0
|
||||
}
|
||||
|
||||
@@ -101,6 +112,10 @@ function playerDead(eim, player) {
|
||||
// Happens when player dies
|
||||
}
|
||||
|
||||
function monsterRevive(mob, eim) {
|
||||
// Happens when an opposing mob revives
|
||||
}
|
||||
|
||||
function playerRevive(eim, player) {
|
||||
// Happens when player's revived.
|
||||
// @Param : returns true/false
|
||||
@@ -112,11 +127,6 @@ function playerDisconnected(eim, player) {
|
||||
// return x that is < 0 - Deregister player normally + Dispose instance if there x player or below, if it's leader = boot all
|
||||
}
|
||||
|
||||
function monsterValue(eim, mobid) {
|
||||
// Invoked when a monster that's registered has been killed
|
||||
// return x amount for this player - "Saved Points"
|
||||
}
|
||||
|
||||
function end(eim) {
|
||||
// Happens when the party fails to complete the event instance.
|
||||
}
|
||||
@@ -134,7 +144,7 @@ function leftParty(eim, player) {
|
||||
}
|
||||
|
||||
function disbandParty(eim, player) {
|
||||
// Happens when the party is disbanded by the leader.
|
||||
// Happens when the party is disbanded.
|
||||
}
|
||||
|
||||
function removePlayer(eim, player) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user